From 3c983ae6bfadcdb8c40a3a2a4d7d86d4820edcf3 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 30 May 2024 17:32:51 +0200 Subject: [PATCH 001/103] Data reference inspector section (#5789) * show parent outlines for cartouche elements * adjust passing views * update snaps * wip * wip * cartouche picker * fix debug * update snaps * unify functions * fix selector name * update usage --- editor/src/components/inspector/inspector.tsx | 36 +++- .../component-section/data-picker-utils.tsx | 4 +- .../variables-in-scope-utils.ts | 29 +-- .../sections/data-reference-section.tsx | 180 ++++++++++++++++++ ...performance-regression-tests.spec.tsx.snap | 10 + .../performance-regression-tests.spec.tsx | 4 +- 6 files changed, 233 insertions(+), 30 deletions(-) create mode 100644 editor/src/components/inspector/sections/data-reference-section.tsx diff --git a/editor/src/components/inspector/inspector.tsx b/editor/src/components/inspector/inspector.tsx index 72e911aedeca..ae6ee0263226 100644 --- a/editor/src/components/inspector/inspector.tsx +++ b/editor/src/components/inspector/inspector.tsx @@ -99,6 +99,7 @@ import { ListSection } from './sections/layout-section/list-section' import { ExpandableIndicator } from '../navigator/navigator-item/expandable-indicator' import { isIntrinsicElementMetadata } from '../../core/model/project-file-utils' import { assertNever } from '../../core/shared/utils' +import { DataReferenceSection } from './sections/data-reference-section' export interface ElementPathElement { name?: string @@ -270,7 +271,19 @@ export const Inspector = React.memo((props: InspectorProps) => { MetadataUtils.isExpressionOtherJavascript(path, store.editor.jsxMetadata) || MetadataUtils.isJSXMapExpression(path, store.editor.jsxMetadata), ), - 'Inspector hideAllSections', + 'Inspector isCodeElement', + ) + + const isDataReference = useEditorState( + Substores.projectContentsAndMetadata, + (store) => + store.editor.selectedViews.length > 0 && + store.editor.selectedViews.every((path) => + MetadataUtils.isElementDataReference( + getElementFromProjectContents(path, store.editor.projectContents), + ), + ), + 'Inspector isDataReference', ) const multiselectedContract = useEditorState( @@ -345,10 +358,15 @@ export const Inspector = React.memo((props: InspectorProps) => { ) const anyKnownElements = useEditorState( - Substores.metadata, + Substores.projectContentsAndMetadata, (store) => { return strictEvery(store.editor.selectedViews, (view) => { - return MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, view) != null + return ( + MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, view) != null || + MetadataUtils.isElementDataReference( + getElementFromProjectContents(view, store.editor.projectContents), + ) + ) }) }, 'Inspector anyKnownElements', @@ -411,13 +429,17 @@ export const Inspector = React.memo((props: InspectorProps) => { data-testid={InspectorSectionsContainerTestID} > - {isCodeElement ? ( + {when(isDataReference, )} + {when( + isCodeElement, <> - - ) : ( + , + )} + {unless( + isCodeElement || isDataReference, ((props: InspectorProps) => { )} , )} - + , )} diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 691e9a8e18a7..4e9bc0d99ec0 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -68,8 +68,8 @@ export type DataPickerCallback = (e: JSExpressionOtherJavaScript) => void export type ObjectPath = Array -export function jsxElementChildToValuePath(child: JSXElementChild): ObjectPath | null { - if (!isJSExpression(child)) { +export function jsxElementChildToValuePath(child: JSXElementChild | null): ObjectPath | null { + if (child == null || !isJSExpression(child)) { return null } return foldEither( diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index 334ab3530c53..c71684987eb9 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -385,16 +385,10 @@ const keepLocalestScope = } export function useVariablesInScopeForSelectedElement( - selectedView: ElementPath, + elementPath: ElementPath | null, propertyPath: PropertyPath | null, mode: DataPickerFilterOption, ): Array { - const selectedViewPath = useEditorState( - Substores.selectedViews, - (store) => store.editor.selectedViews.at(0) ?? null, - 'useVariablesInScopeForSelectedElement selectedViewPath', - ) - const variablesInScope = useEditorState( Substores.restOfEditor, (store) => store.editor.variablesInScope, @@ -402,16 +396,16 @@ export function useVariablesInScopeForSelectedElement( ) const controlDescriptions = usePropertyControlDescriptions(propertyPath) - const currentPropertyValue = usePropertyValue(selectedView, propertyPath) + const currentPropertyValue = usePropertyValue(elementPath, propertyPath) const variableNamesInScope = React.useMemo((): Array => { - if (selectedViewPath == null) { + if (elementPath == null) { return [] } let variablesInScopeForSelectedPath: VariableData | null = (() => { // if the selected element doesn't have an associacted variablesInScope, we assume it's safe to walk up the path within the same component - const allPathsInsideScope = EP.allPathsInsideComponent(selectedViewPath) + const allPathsInsideScope = EP.allPathsInsideComponent(elementPath) for (const path of allPathsInsideScope) { const pathAsString = EP.toString(path) if (pathAsString in variablesInScope) { @@ -450,14 +444,7 @@ export function useVariablesInScopeForSelectedElement( return orderedVariablesInScope.flatMap((variable) => valuesFromVariable(variable, 0, variable.expression, [variable.expressionPathPart]), ) - }, [ - controlDescriptions, - currentPropertyValue, - mode, - selectedViewPath, - variablesInScope, - propertyPath, - ]) + }, [controlDescriptions, currentPropertyValue, mode, elementPath, variablesInScope, propertyPath]) return variableNamesInScope } @@ -549,7 +536,7 @@ export type PropertyValue = | { type: 'not-found' } function usePropertyValue( - selectedView: ElementPath, + selectedView: ElementPath | null, propertyPath: PropertyPath | null, ): PropertyValue { const allElementProps = useEditorState( @@ -564,6 +551,10 @@ function usePropertyValue( 'usePropertyValue metadata', ) + if (selectedView == null) { + return { type: 'not-found' } + } + if (MetadataUtils.isJSXMapExpression(selectedView, metadata)) { return { type: 'mapped-value' } } diff --git a/editor/src/components/inspector/sections/data-reference-section.tsx b/editor/src/components/inspector/sections/data-reference-section.tsx new file mode 100644 index 000000000000..b693b63d2a8d --- /dev/null +++ b/editor/src/components/inspector/sections/data-reference-section.tsx @@ -0,0 +1,180 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ import { jsx } from '@emotion/react' +import React from 'react' +import { FlexRow, UtopiaTheme, useColorTheme } from '../../../uuiui' +import { Substores, useEditorState } from '../../editor/store/store-hook' +import { MetadataUtils } from '../../../core/model/element-metadata-utils' +import type { ElementPath } from '../../../core/shared/project-file-types' +import { UIGridRow } from '../widgets/ui-grid-row' +import { getElementFromProjectContents } from '../../editor/store/editor-state' +import { mapDropNulls } from '../../../core/shared/array-utils' +import { + DataCartoucheInner, + getTextContentOfElement, +} from './component-section/data-reference-cartouche' +import { useDataPickerButton } from './component-section/component-section' +import { DataPickerPreferredAllAtom } from './component-section/data-picker-popup' +import { useAtom } from 'jotai' +import * as EP from '../../../core/shared/element-path' +import { useDispatch } from '../../editor/store/dispatch-context' +import { replaceElementInScope } from '../../editor/actions/action-creators' +import { NO_OP } from '../../../core/shared/utils' +import { dataPathSuccess, traceDataFromElement } from '../../../core/data-tracing/data-tracing' +import { useVariablesInScopeForSelectedElement } from './component-section/variables-in-scope-utils' +import { jsxElementChildToValuePath } from './component-section/data-picker-utils' + +export const DataReferenceSectionId = 'code-element-section-test-id' + +export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[] }) => { + const colorTheme = useColorTheme() + const dispatch = useDispatch() + + const dataPickerWrapperRef = React.useRef(null) + + const [preferredAllState] = useAtom(DataPickerPreferredAllAtom) + + const [elementPathForDataPicker, setElementPathForDataPicker] = + React.useState(null) + + const elements = useEditorState( + Substores.projectContentsAndMetadata, + (store) => { + return mapDropNulls((path) => { + const element = getElementFromProjectContents(path, store.editor.projectContents) + if (element == null) { + return null + } + + const elementMetadata = MetadataUtils.findElementByElementPath( + store.editor.jsxMetadata, + path, + ) + + const isDataComingFromServer = traceDataFromElement( + element, + EP.parentPath(path), + store.editor.jsxMetadata, + store.editor.projectContents, + dataPathSuccess([]), + ) + + return { + element: element, + textContent: getTextContentOfElement(element, elementMetadata), + path: path, + contentIsComingFromServer: isDataComingFromServer.type === 'hook-result', + } + }, paths) + }, + 'DataReferenceSection elements', + ) + + const isDataReference = React.useMemo(() => { + return elements.every((element) => MetadataUtils.isElementDataReference(element.element)) + }, [elements]) + + const isText = React.useMemo(() => { + return elements.every((element) => element.element?.type === 'JSX_TEXT_BLOCK') + }, [elements]) + + const varsInScope = useVariablesInScopeForSelectedElement( + elementPathForDataPicker, + null, + preferredAllState, + ) + + const pathToCurrenlySelectedValue = React.useMemo(() => { + const element = elements.find((e) => EP.pathsEqual(e.path, elementPathForDataPicker)) + return jsxElementChildToValuePath(element?.element ?? null) + }, [elements, elementPathForDataPicker]) + + const dataPickerButtonData = useDataPickerButton( + varsInScope, + (expression) => { + if (elementPathForDataPicker == null) { + return + } + dispatch([ + replaceElementInScope(EP.parentPath(elementPathForDataPicker), { + type: 'replace-child-with-uid', + uid: EP.toUid(elementPathForDataPicker), + replaceWith: expression, + }), + ]) + }, + pathToCurrenlySelectedValue, + ) + + const openPicker = React.useCallback( + (path: ElementPath | null) => () => { + if (path == null) { + return + } + dataPickerButtonData.setReferenceElement(dataPickerWrapperRef.current) + dataPickerButtonData.openPopup() + setElementPathForDataPicker(path) + }, + [dataPickerButtonData], + ) + + if (!isDataReference) { + return null + } + + return ( +
+
+ {dataPickerButtonData.popupIsOpen ? dataPickerButtonData.DataPickerComponent : null} +
+ + + + {isText ? 'Text' : 'Data'} + + + + {elements.map((element) => { + return ( + + Value + + + + ) + })} +
+ ) +}) diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 20a46304bb07..7606c3d5cd63 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -106,6 +106,11 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/UtopiaSpiedFunctionComponent()/UtopiaSpiedExoticType(Symbol(react.provider))", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/div", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedClass(ComponentSection)", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedFunctionComponent(InspectorSectionHeader)", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)(AlignmentButtons)", @@ -754,6 +759,11 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/UtopiaSpiedFunctionComponent()/UtopiaSpiedExoticType(Symbol(react.provider))", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/div", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedClass(ComponentSection)", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedFunctionComponent(InspectorSectionHeader)", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)(AlignmentButtons)", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index b58aef581c6e..b136465d7450 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -183,7 +183,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`531`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`536`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`643`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`648`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From 6d646d829ac967caadffce498178f928f82734d8 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 30 May 2024 18:19:15 +0200 Subject: [PATCH 002/103] remove quotes, trim space (#5793) --- .../sections/component-section/data-reference-cartouche.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index cd92260e509b..9db9339d24f3 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -212,9 +212,9 @@ export function getTextContentOfElement( case 'ATTRIBUTE_VALUE': return { type: 'literal', label: `${JSON.stringify(element.value)}` } case 'JSX_TEXT_BLOCK': - return { type: 'literal', label: `'${element.text}'` } + return { type: 'literal', label: element.text.trim() } case 'JS_IDENTIFIER': - return { type: 'reference', label: `${element.name}` } + return { type: 'reference', label: element.name.trim() } case 'JS_ELEMENT_ACCESS': return { type: 'reference', From 425833fa4ad2d51c71967890846960a0df54f57d Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 31 May 2024 08:57:48 +0200 Subject: [PATCH 003/103] hide prop rows/children label on collapsed (#5797) --- .../components/navigator/navigator-utils.ts | 77 ++++++++++++------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/editor/src/components/navigator/navigator-utils.ts b/editor/src/components/navigator/navigator-utils.ts index 82f4e7834a30..b7cf6b2ee0d4 100644 --- a/editor/src/components/navigator/navigator-utils.ts +++ b/editor/src/components/navigator/navigator-utils.ts @@ -704,6 +704,51 @@ function getNavigatorRowsForTree( return walkTree(e, i) } + function renderPropRows( + tree: RegularNavigatorTree, + path: ElementPath, + nextIndentation: number, + ): NavigatorRow[] { + return Object.entries(tree.renderProps).flatMap(([propName, renderPropChild]) => { + const fakeRenderPropPath = EP.appendToPath(path, renderPropId(propName)) + let rows: NavigatorRow[] = [] + if (!isSubtreeHidden(tree)) { + rows.push( + regularNavigatorRow( + renderPropNavigatorEntry( + fakeRenderPropPath, + propName, + renderPropChild.navigatorEntry.elementPath, + ), + nextIndentation, + ), + ) + } + rows.push(...walkIfSubtreeVisible(renderPropChild, nextIndentation + 1)) + return rows + }) + } + + function shouldShowChildrenLabel(tree: RegularNavigatorTree): boolean { + return ( + Object.values(tree.renderProps).length > 0 && + tree.children.length > 0 && + !isSubtreeHidden(tree) + ) + } + + function childrenLabelRow(tree: RegularNavigatorTree, path: ElementPath): RegularNavigatorRow { + // we only show the children label if there are render props + return regularNavigatorRow( + renderPropNavigatorEntry( + EP.appendToPath(path, renderPropId('children')), + 'children', + tree.children[0].navigatorEntry.elementPath, // pick the first child path + ), + nextIndentation, + ) + } + if (isElementHidden(entry) && filterVisible === 'visible-navigator-targets') { return [] } @@ -741,37 +786,11 @@ function getNavigatorRowsForTree( ] case 'regular-entry': { const path = entry.navigatorEntry.elementPath - const showChildrenLabel = - Object.values(entry.renderProps).length > 0 && entry.children.length > 0 + const showChildrenLabel = shouldShowChildrenLabel(entry) return [ regularNavigatorRow(entry.navigatorEntry, indentation), - ...Object.entries(entry.renderProps).flatMap(([propName, renderPropChild]) => { - const fakeRenderPropPath = EP.appendToPath(path, renderPropId(propName)) - return [ - regularNavigatorRow( - renderPropNavigatorEntry( - fakeRenderPropPath, - propName, - renderPropChild.navigatorEntry.elementPath, - ), - nextIndentation, - ), - ...walkIfSubtreeVisible(renderPropChild, nextIndentation + 1), - ] - }), - ...(showChildrenLabel - ? // we only show the children label if there are render props - [ - regularNavigatorRow( - renderPropNavigatorEntry( - EP.appendToPath(path, renderPropId('children')), - 'children', - entry.children[0].navigatorEntry.elementPath, // pick the first child path - ), - nextIndentation, - ), - ] - : []), + ...renderPropRows(entry, path, nextIndentation), + ...(showChildrenLabel ? [childrenLabelRow(entry, path)] : []), ...entry.children.flatMap((t) => walkIfSubtreeVisible(t, showChildrenLabel ? nextIndentation + 1 : nextIndentation), ), From 872b256407dd09a621d980b1267c9c20ac1904c2 Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Fri, 31 May 2024 10:30:20 +0100 Subject: [PATCH 004/103] fix(inspector) When loading component descriptors, take account of file mappings. (#5781) - `importedFromWhere` now invokes `applyFilePathMappingsToFilePath` for the path that it returns so that it applies the path mapping rules to the results gained. - Added a call to `getFilePathMappings` in a few places to support a call to `getComponentDescriptorForTarget`. --- editor/src/components/canvas/canvas-utils.ts | 10 +- .../ui-jsx-canvas-component-renderer.tsx | 3 + .../ui-jsx-canvas-contexts.tsx | 3 + .../ui-jsx-canvas-element-renderer-utils.tsx | 5 +- .../ui-jsx-canvas-execution-scope.tsx | 3 + .../src/components/canvas/ui-jsx-canvas.tsx | 4 + editor/src/components/editor/import-utils.ts | 15 +- .../property-controls-utils.spec.ts | 139 ++++++++++++++++++ .../property-controls-utils.ts | 5 + editor/src/utils/utils.test-utils.tsx | 1 + 10 files changed, 183 insertions(+), 5 deletions(-) create mode 100644 editor/src/core/property-controls/property-controls-utils.spec.ts diff --git a/editor/src/components/canvas/canvas-utils.ts b/editor/src/components/canvas/canvas-utils.ts index cafcc228ee0c..3350e9d918b1 100644 --- a/editor/src/components/canvas/canvas-utils.ts +++ b/editor/src/components/canvas/canvas-utils.ts @@ -69,6 +69,7 @@ import { isParseSuccess, isTextFile } from '../../core/shared/project-file-types import { applyUtopiaJSXComponentsChanges, getDefaultExportedTopLevelElement, + getFilePathMappings, getUtopiaJSXComponentsFromSuccess, isRemixSceneElement, } from '../../core/model/project-file-utils' @@ -1700,8 +1701,15 @@ export function getValidElementPaths( resolve: (importOrigin: string, toImport: string) => Either, getRemixValidPathsGenerationContext: (path: ElementPath) => RemixValidPathsGenerationContext, ): Array { + const filePathMappings = getFilePathMappings(projectContents) const { topLevelElements, imports } = getParseSuccessForFilePath(filePath, projectContents) - const importSource = importedFromWhere(filePath, topLevelElementName, topLevelElements, imports) + const importSource = importedFromWhere( + filePathMappings, + filePath, + topLevelElementName, + topLevelElements, + imports, + ) if (importSource != null) { let originTopLevelName = getTopLevelName(importSource, topLevelElementName) const resolvedImportSource = resolve(filePath, importSource.filePath) diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx index 12d42dfc24db..945100fe72b2 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx @@ -48,6 +48,7 @@ import type { ComponentRendererComponent } from './component-renderer-component' import { mapArrayToDictionary } from '../../../core/shared/array-utils' import { assertNever } from '../../../core/shared/utils' import { addFakeSpyEntry } from './ui-jsx-canvas-spy-wrapper' +import type { FilePathMappings } from '../../../core/model/project-file-utils' function tryToGetInstancePath( maybePath: ElementPath | null, @@ -158,6 +159,7 @@ export function createComponentRendererComponent(params: { highlightBounds: highlightBounds, editedText: rerenderUtopiaContext.editedText, variablesInScope: {}, + filePathMappings: rerenderUtopiaContext.filePathMappings, }, undefined, codeError, @@ -228,6 +230,7 @@ export function createComponentRendererComponent(params: { code: code, highlightBounds: highlightBounds, editedText: rerenderUtopiaContext.editedText, + filePathMappings: rerenderUtopiaContext.filePathMappings, } const buildResult = React.useRef(null) diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-contexts.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-contexts.tsx index 27972ae9454a..6e33e1425683 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-contexts.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-contexts.tsx @@ -7,6 +7,7 @@ import { left } from '../../../core/shared/either' import type { ElementPath } from '../../../core/shared/project-file-types' import type { ProjectContentTreeRoot } from '../../assets' import type { TransientFilesState, UIFileBase64Blobs } from '../../editor/store/editor-state' +import type { FilePathMappings } from '../../../core/model/project-file-utils' export interface MutableUtopiaCtxRefData { [filePath: string]: { @@ -32,6 +33,7 @@ interface RerenderUtopiaContextProps { canvasIsLive: boolean shouldIncludeCanvasRootInTheSpy: boolean editedText: ElementPath | null + filePathMappings: FilePathMappings } export const RerenderUtopiaCtxAtom = atomWithPubSub({ @@ -42,6 +44,7 @@ export const RerenderUtopiaCtxAtom = atomWithPubSub( canvasIsLive: false, shouldIncludeCanvasRootInTheSpy: false, editedText: null, + filePathMappings: [], }, }) diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx index 2b8842a3fae5..376ac12923a6 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx @@ -78,6 +78,7 @@ import { import { RemixSceneComponent } from './remix-scene-component' import { STEGANOGRAPHY_ENABLED, isFeatureEnabled } from '../../../utils/feature-switches' import { jsxElementChildToText } from './jsx-element-child-to-text' +import type { FilePathMappings } from '../../../core/model/project-file-utils' export interface RenderContext { rootScope: MapLike @@ -98,6 +99,7 @@ export interface RenderContext { highlightBounds: HighlightBoundsForUids | null editedText: ElementPath | null variablesInScope: VariableData + filePathMappings: FilePathMappings } export function createLookupRender( @@ -704,6 +706,7 @@ function renderJSXElement( highlightBounds, editedText, variablesInScope, + filePathMappings, } = renderContext const createChildrenElement = (child: JSXElementChild): React.ReactChild => { const childPath = optionalMap((path) => EP.appendToPath(path, getUtopiaID(child)), elementPath) @@ -729,7 +732,7 @@ function renderJSXElement( // elements from scope and import to confirm it's not a top level element. const importedFrom = elementIsFragment ? null - : importedFromWhere(filePath, jsx.name.baseVariable, [], imports) + : importedFromWhere(filePathMappings, filePath, jsx.name.baseVariable, [], imports) const isElementImportedFromModule = (moduleName: string, name: string) => !elementIsIntrinsic && diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx index 18cf24ad1b9e..2c2ab7b637a7 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx @@ -35,6 +35,7 @@ import { applyBlockReturnFunctions, } from '../../../core/shared/dom-utils' import { emptySet } from '../../../core/shared/set-utils' +import { getFilePathMappings } from '../../../core/model/project-file-utils' const emptyFileBlobs: UIFileBase64Blobs = {} @@ -65,6 +66,7 @@ export function createExecutionScope( topLevelJsxComponents: Map requireResult: MapLike } { + const filePathMappings = getFilePathMappings(projectContents) if (!(filePath in topLevelComponentRendererComponents.current)) { // we make sure that the ref has an entry for this filepath topLevelComponentRendererComponents.current[filePath] = {} @@ -148,6 +150,7 @@ export function createExecutionScope( highlightBounds: highlightBounds, editedText: editedText, variablesInScope: {}, + filePathMappings: filePathMappings, }, null, propertiesFromParams, diff --git a/editor/src/components/canvas/ui-jsx-canvas.tsx b/editor/src/components/canvas/ui-jsx-canvas.tsx index d9f72b000d8f..e016cfa9105e 100644 --- a/editor/src/components/canvas/ui-jsx-canvas.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas.tsx @@ -91,6 +91,7 @@ import { useAtom } from 'jotai' import { RemixNavigationAtom } from './remix/utopia-remix-root-component' import { IS_TEST_ENVIRONMENT } from '../../common/env-vars' import { listenForReactRouterErrors } from '../../core/shared/runtime-report-logs' +import { getFilePathMappings } from '../../core/model/project-file-utils' applyUIDMonkeyPatch() @@ -495,12 +496,15 @@ export const UiJsxCanvas = React.memo((props) validPaths: rootValidPathsSet, }) + const filePathMappings = getFilePathMappings(projectContents) + const rerenderUtopiaContextValue = useKeepShallowReferenceEquality({ hiddenInstances: hiddenInstances, displayNoneInstances: displayNoneInstances, canvasIsLive: canvasIsLive, shouldIncludeCanvasRootInTheSpy: props.shouldIncludeCanvasRootInTheSpy, editedText: props.editedText, + filePathMappings: filePathMappings, }) const utopiaProjectContextValue = useKeepShallowReferenceEquality({ diff --git a/editor/src/components/editor/import-utils.ts b/editor/src/components/editor/import-utils.ts index 6b0c184bb68a..2cd54405bd87 100644 --- a/editor/src/components/editor/import-utils.ts +++ b/editor/src/components/editor/import-utils.ts @@ -36,6 +36,11 @@ import { withUnderlyingTarget } from './store/editor-state' import * as EP from '../../core/shared/element-path' import { renameDuplicateImportsInMergeResolution } from '../../core/shared/import-shared-utils' import { getParseSuccessForFilePath } from '../canvas/canvas-utils' +import type { FilePathMappings } from '../../core/model/project-file-utils' +import { + applyFilePathMappingsToFilePath, + getFilePathMappings, +} from '../../core/model/project-file-utils' export function getRequiredImportsForElement( target: ElementPath, @@ -44,6 +49,7 @@ export function getRequiredImportsForElement( targetFilePath: string, builtInDependencies: BuiltInDependencies, ): ImportsMergeResolution { + const filePathMappings = getFilePathMappings(projectContents) return withUnderlyingTarget( target, projectContents, @@ -62,6 +68,7 @@ export function getRequiredImportsForElement( // Straight up ignore intrinsic elements as they wont be imported. if (!isIntrinsicElement(elem.name)) { const importedFromResult = importedFromWhere( + filePathMappings, underlyingFilePath, elem.name.baseVariable, topLevelElementsInOriginFile, @@ -144,6 +151,7 @@ export function getRequiredImportsForElement( type ImportedFromWhereResult = ImportInfo export function importedFromWhere( + filePathMappings: FilePathMappings, originFilePath: string, variableName: string, topLevelElements: Array, @@ -172,15 +180,16 @@ export function importedFromWhere( } for (const importSource of Object.keys(importsToSearch)) { const specificImport = importsToSearch[importSource] + const importSourceMapped = applyFilePathMappingsToFilePath(importSource, filePathMappings) if (specificImport.importedAs === variableName) { - return importedOrigin(importSource, variableName, null) + return importedOrigin(importSourceMapped, variableName, null) } if (specificImport.importedWithName === variableName) { - return importedOrigin(importSource, variableName, null) + return importedOrigin(importSourceMapped, variableName, null) } for (const fromWithin of specificImport.importedFromWithin) { if (fromWithin.alias === variableName) { - return importedOrigin(importSource, variableName, fromWithin.name) + return importedOrigin(importSourceMapped, variableName, fromWithin.name) } } } diff --git a/editor/src/core/property-controls/property-controls-utils.spec.ts b/editor/src/core/property-controls/property-controls-utils.spec.ts new file mode 100644 index 000000000000..8c92402e72e8 --- /dev/null +++ b/editor/src/core/property-controls/property-controls-utils.spec.ts @@ -0,0 +1,139 @@ +import type { ProjectContentTreeRoot } from '../../components/assets' +import { addFileToProjectContents } from '../../components/assets' +import type { + ComponentDescriptor, + PropertyControlsInfo, +} from '../../components/custom-code/code-file' +import { componentDescriptorFromDescriptorFile } from '../../components/custom-code/code-file' +import { simpleDefaultProject } from '../../sample-projects/sample-project-utils' +import { parseProjectContents } from '../../sample-projects/sample-project-utils.test-utils' +import { codeFile } from '../shared/project-file-types' +import { assertNever } from '../shared/utils' +import { getComponentDescriptorForTarget } from './property-controls-utils' +import * as EP from '../shared/element-path' + +describe('getComponentDescriptorForTarget', () => { + function getProjectContents(mappedPath: 'mapped-path' | 'regular-path'): ProjectContentTreeRoot { + let baseProjectContents: ProjectContentTreeRoot = simpleDefaultProject().projectContents + baseProjectContents = addFileToProjectContents( + baseProjectContents, + '/jsconfig.json', + codeFile( + `{ + "compilerOptions": { + "checkJs": true, + "jsx": "react-jsx", + "target": "ES2022", + "module": "ES2022", + "moduleResolution": "Bundler", + "baseUrl": ".", + "paths": { + "~/*": ["app/*"] + } + }, + "include": ["./**/*.d.ts", "./**/*.js", "./**/*.jsx"] +} +`, + null, + ), + ) + baseProjectContents = addFileToProjectContents( + baseProjectContents, + '/app/components.js', + codeFile( + ` +import * as React from 'react' +export const Component = () => { + return
+} +`, + null, + ), + ) + switch (mappedPath) { + case 'mapped-path': + baseProjectContents = addFileToProjectContents( + baseProjectContents, + '/src/app.js', + codeFile( + ` +import * as React from 'react' +import { Component } from '~/components' +export const App = (props) => { + return ( +
+ +
+ ) +}`, + null, + ), + ) + break + case 'regular-path': + baseProjectContents = addFileToProjectContents( + baseProjectContents, + '/src/app.js', + codeFile( + ` +import * as react from 'react' +import { Component } from '/app/components' +export const App = (props) => { + return ( +
+ +
+ ) +}`, + null, + ), + ) + break + default: + assertNever(mappedPath) + } + + return parseProjectContents(baseProjectContents) + } + const componentDescriptor: ComponentDescriptor = { + properties: {}, + supportsChildren: true, + preferredChildComponents: [], + variants: [], + source: componentDescriptorFromDescriptorFile('/components.utopia.js'), + focus: 'default', + inspector: { type: 'hidden' }, + emphasis: 'regular', + icon: 'component', + label: 'Component', + } + const propertyControlsInfo: PropertyControlsInfo = { + ['/app/components']: { + ['Component']: componentDescriptor, + }, + } + it('works with the regular path', () => { + const projectContents = getProjectContents('regular-path') + const actualResult = getComponentDescriptorForTarget( + EP.fromString(`sample-storyboard/sample-scene/sample-app:div/component`), + propertyControlsInfo, + projectContents, + ) + expect(actualResult).toEqual(componentDescriptor) + }) + it('works with a mapped path', () => { + const projectContents = getProjectContents('mapped-path') + const actualResult = getComponentDescriptorForTarget( + EP.fromString(`sample-storyboard/sample-scene/sample-app:div/component`), + propertyControlsInfo, + projectContents, + ) + expect(actualResult).toEqual(componentDescriptor) + }) +}) diff --git a/editor/src/core/property-controls/property-controls-utils.ts b/editor/src/core/property-controls/property-controls-utils.ts index c4877e31271f..836f1ca834e0 100644 --- a/editor/src/core/property-controls/property-controls-utils.ts +++ b/editor/src/core/property-controls/property-controls-utils.ts @@ -23,6 +23,7 @@ import { dropFileExtension } from '../shared/file-utils' import type { Styling } from 'utopia-api' import { StylingOptions } from 'utopia-api' import { intersection } from '../shared/set-utils' +import { getFilePathMappings } from '../model/project-file-utils' export function propertyControlsForComponentInFile( componentName: string, @@ -49,6 +50,7 @@ export function getPropertyControlsForTarget( propertyControlsInfo: PropertyControlsInfo, projectContents: ProjectContentTreeRoot, ): PropertyControls | null { + const filePathMappings = getFilePathMappings(projectContents) return withUnderlyingTarget( target, projectContents, @@ -61,6 +63,7 @@ export function getPropertyControlsForTarget( ) => { if (isJSXElement(element)) { const importedFrom = importedFromWhere( + filePathMappings, underlyingFilePath, element.name.baseVariable, success.topLevelElements, @@ -137,6 +140,7 @@ export function getComponentDescriptorForTarget( propertyControlsInfo: PropertyControlsInfo, projectContents: ProjectContentTreeRoot, ): ComponentDescriptor | null { + const filePathMappings = getFilePathMappings(projectContents) return withUnderlyingTarget( target, projectContents, @@ -149,6 +153,7 @@ export function getComponentDescriptorForTarget( ) => { if (isJSXElement(element)) { const importedFrom = importedFromWhere( + filePathMappings, underlyingFilePath, element.name.baseVariable, success.topLevelElements, diff --git a/editor/src/utils/utils.test-utils.tsx b/editor/src/utils/utils.test-utils.tsx index 2ffa82aed7fa..52cee2c61eb0 100644 --- a/editor/src/utils/utils.test-utils.tsx +++ b/editor/src/utils/utils.test-utils.tsx @@ -107,6 +107,7 @@ export const testRenderContext: RenderContext = { highlightBounds: null, editedText: null, variablesInScope: {}, + filePathMappings: [], } export function delay(time: number): Promise { From 968c525f94ba024ca899dfc5acc133dccf403a0d Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 31 May 2024 11:59:16 +0200 Subject: [PATCH 005/103] Collapse scenes from the action sheet (#5800) * collapse scenes from the action sheet * use when for old component --- .../navigator-item-components.tsx | 133 +++++++++++------- .../navigator-item/navigator-item.tsx | 2 + 2 files changed, 82 insertions(+), 53 deletions(-) diff --git a/editor/src/components/navigator/navigator-item/navigator-item-components.tsx b/editor/src/components/navigator/navigator-item/navigator-item-components.tsx index ed3898dc8693..45143f61cc6c 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-components.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-components.tsx @@ -6,14 +6,14 @@ import * as EP from '../../../core/shared/element-path' import type { IcnProps } from '../../../uuiui' import { useColorTheme, Button, FlexRow, Icn } from '../../../uuiui' import { stopPropagation } from '../../inspector/common/inspector-utils' -import { when } from '../../../utils/react-conditionals' -import { Substores, useEditorState, useRefEditorState } from '../../editor/store/store-hook' +import { unless, when } from '../../../utils/react-conditionals' +import { Substores, useEditorState } from '../../editor/store/store-hook' import { MetadataUtils } from '../../../core/model/element-metadata-utils' import type { NavigatorEntry } from '../../editor/store/editor-state' import { - getMetadata, isConditionalClauseNavigatorEntry, isRegularNavigatorEntry, + navigatorEntryToKey, varSafeNavigatorEntryToKey, } from '../../editor/store/editor-state' import type { SelectionLocked } from '../../canvas/canvas-types' @@ -27,11 +27,11 @@ import type { ConditionalCase } from '../../../core/model/conditionals' import { useConditionalCaseCorrespondingToBranchPath } from '../../../core/model/conditionals' import { getJSXElementNameAsString, - isIntrinsicElement, isIntrinsicHTMLElement, } from '../../../core/shared/element-template' import { getRegisteredComponent } from '../../../core/property-controls/property-controls-utils' import { intrinsicHTMLElementNamesThatSupportChildren } from '../../../core/shared/dom-utils' +import { ExpandableIndicator } from './expandable-indicator' export const NavigatorHintCircleDiameter = 8 @@ -443,6 +443,8 @@ interface NavigatorItemActionSheetProps { isVisibleOnCanvas: boolean // TODO FIXME bad name, also, use state instanceOriginalComponentName: string | null isSlot: boolean + isScene: boolean + collapsed: boolean iconColor: IcnProps['color'] background?: string | any dispatch: EditorDispatch @@ -489,14 +491,6 @@ export const NavigatorItemActionSheet: React.FunctionComponent< 'NavigatorItemActionSheet isLockedHierarchy', ) - const jsxMetadataRef = useRefEditorState((store) => getMetadata(store.editor)) - const isSceneElement = React.useMemo(() => { - return ( - isRegularNavigatorEntry(navigatorEntry) && - MetadataUtils.isProbablyScene(jsxMetadataRef.current, navigatorEntry.elementPath) - ) - }, [navigatorEntry, jsxMetadataRef]) - const isDescendantOfLocked = useEditorState( Substores.restOfEditor, (store) => { @@ -514,6 +508,14 @@ export const NavigatorItemActionSheet: React.FunctionComponent< props.navigatorEntry.elementPath, ) + const collapse = React.useCallback( + (event: React.MouseEvent) => { + event.stopPropagation() + dispatch([EditorActions.toggleCollapse(navigatorEntry.elementPath)]) + }, + [dispatch, navigatorEntry.elementPath], + ) + return ( - - {(navigatorEntry.type === 'REGULAR' || navigatorEntry.type === 'RENDER_PROP_VALUE') && - (props.highlighted || props.selected) ? ( + {unless( + props.isScene, <> - - + {when( + (navigatorEntry.type === 'REGULAR' || navigatorEntry.type === 'RENDER_PROP_VALUE') && + (props.highlighted || props.selected), + <> + + + , + )} + - - ) : null} - - + + , + )} + {when( + props.isScene, + , + )} ) }) diff --git a/editor/src/components/navigator/navigator-item/navigator-item.tsx b/editor/src/components/navigator/navigator-item/navigator-item.tsx index 8413bb9aa4d5..530cbf2529a3 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.tsx @@ -1076,6 +1076,8 @@ export const NavigatorItem: React.FunctionComponent< isSlot={isPlaceholder} iconColor={iconColor} background={rowStyle.background} + isScene={isScene} + collapsed={collapsed} />, )} From ce371f808336a2e3fbe8ff3a0af443e3846c6c0a Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Fri, 31 May 2024 11:40:01 -0400 Subject: [PATCH 006/103] move dot (#5799) --- editor/src/components/editor/canvas-toolbar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editor/src/components/editor/canvas-toolbar.tsx b/editor/src/components/editor/canvas-toolbar.tsx index 77c4d95a0151..43b07add066b 100644 --- a/editor/src/components/editor/canvas-toolbar.tsx +++ b/editor/src/components/editor/canvas-toolbar.tsx @@ -237,8 +237,8 @@ const UnreadThreadsIndicator = React.memo(() => { ? `1.5px solid ${colorTheme.primary.value}` : `1.5px solid ${colorTheme.bg1.value}`, position: 'relative', - top: 8, - left: -15, + top: 5, + left: -9, opacity: unreadThreads.length > 0 ? 1 : 0, }} /> From 9b72f0c2c8af412a90adce8f0a9cea9fd5777fca Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Fri, 31 May 2024 23:11:13 +0300 Subject: [PATCH 007/103] Fix: wrap tests (#5794) This PR re-adds the skipped tests and fixes them. Now we pass the specific mode to the picker to show only the components that support children, an in addition `List` is being [special cased](https://github.com/concrete-utopia/utopia/pull/5794/files#diff-aae3a971fe8ad7522e15665e7202a4386a58a51bb5d7ec3feaa1d87f9fb073a5R675) to appear in the wrapping component list since we special-cased it in the insertion process **Manual Tests:** I hereby swear that: - [X] I opened a hydrogen project and it loaded - [X] I could navigate to various routes in Preview mode Fixes #5779 --- .../editor/actions/actions.spec.browser2.tsx | 30 +++++++++---------- .../component-picker-context-menu.tsx | 4 ++- .../components/shared/project-components.ts | 11 +++++-- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/editor/src/components/editor/actions/actions.spec.browser2.tsx b/editor/src/components/editor/actions/actions.spec.browser2.tsx index 2378d2f08f73..4eb4cccb0f64 100644 --- a/editor/src/components/editor/actions/actions.spec.browser2.tsx +++ b/editor/src/components/editor/actions/actions.spec.browser2.tsx @@ -7383,7 +7383,7 @@ export var storyboard = ( ) }) describe('groups', () => { - it.skip('cannot wrap an empty group', async () => { + it('cannot wrap an empty group', async () => { const testCode = `
@@ -7409,7 +7409,7 @@ export var storyboard = ( ) }) - it.skip('can group conditionals', async () => { + it('can group conditionals', async () => { const testCode = `
@@ -7494,10 +7494,10 @@ export var storyboard = ( ), ) - // expect(renderResult.getEditorState().editor.toasts.length).toEqual(1) - // expect(renderResult.getEditorState().editor.toasts[0].message).toEqual( - // 'Not all targets can be wrapped into a Group', - // ) + expect(renderResult.getEditorState().editor.toasts.length).toEqual(1) + expect(renderResult.getEditorState().editor.toasts[0].message).toEqual( + 'Not all targets can be wrapped into a Group', + ) }) it('cannot group conditionals with active branch that cannot be a group child', async () => { @@ -7536,13 +7536,13 @@ export var storyboard = ( ), ) - // expect(renderResult.getEditorState().editor.toasts.length).toEqual(1) - // expect(renderResult.getEditorState().editor.toasts[0].message).toEqual( - // 'Not all targets can be wrapped into a Group', - // ) + expect(renderResult.getEditorState().editor.toasts.length).toEqual(1) + expect(renderResult.getEditorState().editor.toasts[0].message).toEqual( + 'Not all targets can be wrapped into a Group', + ) }) - it.skip('can wrap nested conditionals', async () => { + it('can wrap nested conditionals', async () => { const testCode = `
@@ -7647,10 +7647,10 @@ export var storyboard = ( ), ) - // expect(renderResult.getEditorState().editor.toasts.length).toEqual(1) - // expect(renderResult.getEditorState().editor.toasts[0].message).toEqual( - // 'Not all targets can be wrapped into a Group', - // ) + expect(renderResult.getEditorState().editor.toasts.length).toEqual(1) + expect(renderResult.getEditorState().editor.toasts[0].message).toEqual( + 'Not all targets can be wrapped into a Group', + ) }) }) }) diff --git a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx index 380a54f88f6e..c1b726f1e25e 100644 --- a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx +++ b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx @@ -844,7 +844,9 @@ const ComponentPickerContextMenuFull = React.memo { + const mode = insertionTarget.type === 'wrap-target' ? 'wrap' : 'insert' + + const allInsertableComponents = useGetInsertableComponents(mode).flatMap((group) => { return { label: group.label, options: group.options.filter((option) => { diff --git a/editor/src/components/shared/project-components.ts b/editor/src/components/shared/project-components.ts index 3f7ff0f12122..aec4bb5dab51 100644 --- a/editor/src/components/shared/project-components.ts +++ b/editor/src/components/shared/project-components.ts @@ -6,7 +6,6 @@ import { } from '../../core/property-controls/property-controls-utils' import type { JSXAttributes, - JSXElementChild, JSXMapExpressionWithoutUID, UtopiaJSXComponent, } from '../../core/shared/element-template' @@ -14,7 +13,6 @@ import { emptyComments, functionParam, jsExpressionOtherJavaScript, - jsExpressionOtherJavaScriptSimple, jsExpressionValue, jsxAttributesFromMap, jsxConditionalExpressionWithoutUID, @@ -670,7 +668,14 @@ function isDescriptorEligibleForMode( insertMenuMode: InsertMenuMode, component: ComponentDescriptor, ): boolean { - return insertMenuMode === 'wrap' ? component.supportsChildren : true + if (insertMenuMode === 'wrap') { + return ( + component.supportsChildren || + // in case it's a map ("List") we can handle wrapping even though it doesn't natively "support" children + component.variants.every((variant) => variant.elementToInsert().type === 'JSX_MAP_EXPRESSION') + ) + } + return true } function isUtopiaJSXComponentEligibleForMode( From c3c1c9a09c62dc3dab6b7abd193d77ff9475cd8d Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Sat, 1 Jun 2024 00:19:39 +0300 Subject: [PATCH 008/103] Feat: Show empty state message (#5791) **Problem:** We show an expandable arrow when there is no info to show ![Image](https://github.com/concrete-utopia/utopia/assets/47405698/b46127e3-4fe6-46bb-88a6-17960e29b0e8) **Fix:** We will show an empty state message when there is no content **Manual Tests:** I hereby swear that: - [X] I opened a hydrogen project and it loaded - [X] I could navigate to various routes in Preview mode Fixes #5750 --- .../property-controls-section.tsx | 33 +++++++++++++++++-- ...performance-regression-tests.spec.tsx.snap | 24 +++++++------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/property-controls-section.tsx b/editor/src/components/inspector/sections/component-section/property-controls-section.tsx index 309be0d92d5d..00c697a30a44 100644 --- a/editor/src/components/inspector/sections/component-section/property-controls-section.tsx +++ b/editor/src/components/inspector/sections/component-section/property-controls-section.tsx @@ -1,14 +1,13 @@ import React from 'react' import type { ElementPath } from '../../../../core/shared/project-file-types' import type { PropertyControls } from '../../../custom-code/internal-property-controls' -import { useEditorState } from '../../../editor/store/store-hook' import { setCursorOverlay } from '../../../editor/actions/action-creators' import { useKeepReferenceEqualityIfPossible } from '../../../../utils/react-performance' import { useHiddenElements } from './hidden-controls-section' import { FolderSection } from './folder-section' import type { CSSCursor } from '../../../canvas/canvas-types' import { UIGridRow } from '../../widgets/ui-grid-row' -import { VerySubdued } from '../../../../uuiui' +import { Subdued, VerySubdued } from '../../../../uuiui' import { AdvancedFolderLabel, isAdvancedFolderLabel, @@ -52,7 +51,29 @@ export const PropertyControlsSection = React.memo((props: PropertyControlsSectio const propertiesWithFolders = synthesiseFolders(propertyControls) - return ( + // unify the logic from the sub components + const hasContent = React.useMemo( + () => + (Object.keys(detectedPropsAndValuesWithoutControls).length > 0 && + Object.keys(detectedPropsAndValuesWithoutControls).some( + (prop) => !specialPropertiesToIgnore.includes(prop), + )) || + propertiesWithFolders.folders.length > 0 || + Object.keys(propertiesWithFolders.advanced).length > 0 || + filteredDetectedPropsWithNoValue.length > 0 || + Object.keys(propertiesWithFolders.uncategorized).length > 0 || + propsWithControlsButNoValue.length > 0, + [ + detectedPropsAndValuesWithoutControls, + propertiesWithFolders.folders, + propertiesWithFolders.advanced, + filteredDetectedPropsWithNoValue, + propertiesWithFolders.uncategorized, + propsWithControlsButNoValue.length, + ], + ) + + return hasContent ? ( <> ) : null} + ) : ( + '}> +
+ This component requires no configuration +
+
) }) diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 7606c3d5cd63..ce9d850463cf 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -805,12 +805,12 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(Styled(span))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "//UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/div/div/Symbol(react.forward_ref)(Styled(span))/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/Symbol(react.memo)()", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/Symbol(react.forward_ref)(Styled(div))", @@ -2476,12 +2476,12 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(Styled(span))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "//UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/div/div/Symbol(react.forward_ref)(Styled(span))/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FixedHugDropdown/Symbol(react.memo)(Symbol(react.forward_ref)())", "/FixedHugDropdown/Symbol(react.memo)(Symbol(react.forward_ref)())/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/Symbol(react.memo)(Symbol(react.forward_ref)())/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)/UtopiaSpiedClass(StateManager)", From 0842379d74f44f52f762cc53d1ceaf0a4d39c4dc Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 3 Jun 2024 09:35:34 +0200 Subject: [PATCH 009/103] Align correctly condensed entries (#5806) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** Condensed entries are not correctly aligned vertically with non-condensed entries. **Fix:** | Before | After | |--------|---------| | Screenshot 2024-05-31 at 4 55 33 PM | Screenshot 2024-05-31 at 4 55 43 PM | **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5805 --- .../navigator-condensed-entry.tsx | 126 +++++++++++------- 1 file changed, 78 insertions(+), 48 deletions(-) diff --git a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx index af04ff36130e..fd75bf28ac72 100644 --- a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx @@ -1,4 +1,3 @@ -import type { CSSProperties } from 'react' import React from 'react' import * as EP from '../../../core/shared/element-path' import { Icons, Tooltip, useColorTheme } from '../../../uuiui' @@ -50,8 +49,32 @@ export const CondensedEntryItemWrapper = React.memo( }, [selectedViews, props.navigatorRow]) const wholeRowInsideSelection = React.useMemo(() => { - return selectedViews.some((path) => - props.navigatorRow.entries.every((entry) => EP.isDescendantOf(entry.elementPath, path)), + return selectedViews.some((path) => { + return props.navigatorRow.entries.every((entry) => { + return EP.isDescendantOfOrEqualTo(entry.elementPath, path) + }) + }) + }, [selectedViews, props.navigatorRow]) + + const isCollapsed = useEditorState( + Substores.navigator, + (store) => + store.editor.navigator.collapsedViews.some((path) => + props.navigatorRow.entries.some((entry) => EP.pathsEqual(path, entry.elementPath)), + ), + 'CondensedEntryItemWrapper isCollapsed', + ) + + const isDataReferenceRow = React.useMemo(() => { + return props.navigatorRow.entries.every( + (entry, idx) => + (idx === 0 && entry.type === 'REGULAR') || (idx > 0 && entry.type === 'DATA_REFERENCE'), + ) + }, [props.navigatorRow]) + + const rowContainsSelection = React.useMemo(() => { + return props.navigatorRow.entries.some((entry) => + selectedViews.some((view) => EP.pathsEqual(view, entry.elementPath)), ) }, [selectedViews, props.navigatorRow]) @@ -65,8 +88,10 @@ export const CondensedEntryItemWrapper = React.memo( hasSelection || wholeRowInsideSelection ? colorTheme.childSelectionBlue.value : 'transparent', - borderTopLeftRadius: wholeRowInsideSelection ? 0 : 5, - borderTopRightRadius: wholeRowInsideSelection ? 0 : 5, + borderTopLeftRadius: rowContainsSelection ? 5 : 0, + borderTopRightRadius: rowContainsSelection ? 5 : 0, + borderBottomLeftRadius: isCollapsed || isDataReferenceRow ? 5 : 0, + borderBottomRightRadius: isCollapsed || isDataReferenceRow ? 5 : 0, overflowX: 'auto', }} > @@ -77,11 +102,13 @@ export const CondensedEntryItemWrapper = React.memo( return ( ) })} @@ -95,6 +122,8 @@ const CondensedEntryItem = React.memo( (props: { entry: NavigatorEntry navigatorRow: CondensedNavigatorRow + isDataReferenceRow: boolean + rowContainsSelection: boolean wholeRowInsideSelection: boolean showSeparator: boolean showExpandableIndicator: boolean @@ -135,13 +164,6 @@ const CondensedEntryItem = React.memo( return selectedViews.some((path) => EP.pathsEqual(path, props.entry.elementPath)) }, [selectedViews, props.entry]) - const isDataReferenceRow = React.useMemo(() => { - return props.navigatorRow.entries.every( - (entry, idx) => - (idx === 0 && entry.type === 'REGULAR') || (idx > 0 && entry.type === 'DATA_REFERENCE'), - ) - }, [props.navigatorRow]) - const indentation = React.useMemo(() => { if (!props.showExpandableIndicator) { return 0 @@ -173,13 +195,19 @@ const CondensedEntryItem = React.memo( selected={isSelected} isChildOfSelected={isChildOfSelected} showExpandableIndicator={props.showExpandableIndicator} - isDataReferenceRow={isDataReferenceRow} + isDataReferenceRow={props.isDataReferenceRow} indentation={indentation} /> {when( props.showSeparator, , )} + {when( + !props.showSeparator && + (!props.showExpandableIndicator || + (props.rowContainsSelection && !selectionIsDataReference)), +
, + )} ) }, @@ -275,7 +303,6 @@ const CondensedEntryItemContent = React.memo( display: 'flex', alignItems: 'center', justifyContent: 'center', - gap: 5, borderRadius: 5, backgroundColor: props.selected && !isDataReference ? colorTheme.selectionBlue.value : undefined, @@ -285,29 +312,37 @@ const CondensedEntryItemContent = React.memo( paddingLeft: props.indentation, }} > - {when( - props.showExpandableIndicator, - , - )} - {unless( - isDataReference, - , - )} +
+ {when( + props.showExpandableIndicator, + , + )} + {unless( + isDataReference, + , + )} +
{when(showLabel, )} {when( - isDataReference && props.entry.type === 'DATA_REFERENCE', - , )}
@@ -354,30 +389,36 @@ const WrappedExpandableIndicator = React.memo( selected: boolean collapsed: boolean disabled: boolean + invisible: boolean }) => { const dispatch = useDispatch() const onClickCollapse = React.useCallback( (elementPath: ElementPath) => (e: React.MouseEvent) => { + if (props.disabled) { + return + } e.stopPropagation() dispatch([toggleCollapse(elementPath)], 'leftpane') }, - [dispatch], + [dispatch, props.disabled], ) return (
+ {when(props.invisible,
)} {unless( - props.disabled, + props.disabled || props.invisible, { - return ( -
- -
- ) - }, -) -WrappedCartouche.displayName = 'WrappedCartouche' From 15c5715d60210be90cfb5de7aa6ee9e9114a18e0 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Mon, 3 Jun 2024 09:49:13 +0200 Subject: [PATCH 010/103] show All vars in the data picker (#5804) --- .../inspector/sections/component-section/data-picker-utils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 4e9bc0d99ec0..dcdf4efac24a 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -62,7 +62,7 @@ export function dataPickerFilterOptionToString(mode: DataPickerFilterOption): st } } -export const DataPickerPreferredAllAtom = atom('preferred') +export const DataPickerPreferredAllAtom = atom('all') export type DataPickerCallback = (e: JSExpressionOtherJavaScript) => void From 5f39016b09af01862d5baa4cec5c3b96e1fb3d05 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 3 Jun 2024 10:44:11 +0200 Subject: [PATCH 011/103] Hide tooltip for navigator cartouches (#5813) **Problem:** The cartouches have a tooltip that in the navigator can easily overflow. ![](https://private-user-images.githubusercontent.com/16385508/335189490-390b28b9-6dcc-4a5d-b585-5dbac8a3e635.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MTc0MDIxNjIsIm5iZiI6MTcxNzQwMTg2MiwicGF0aCI6Ii8xNjM4NTUwOC8zMzUxODk0OTAtMzkwYjI4YjktNmRjYy00YTVkLWI1ODUtNWRiYWM4YTNlNjM1LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA2MDMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNjAzVDA4MDQyMlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWFlZTI3N2RjYTM4NmQ0YThkNGRiZDE0MzU0YWMxMjY0YmM1ZDBiNDBlMGI4YWY4OGNlZjNkNDllNzFiY2Y1ZTYmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.e5JRo_SfqDQD3lkWzOIxdKCAvzORnF_lJRBMJ7IYY3A) **Fix:** Like we do for the condensed entries, do not show the tooltip on navigator cartouches. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5798 --- .../sections/component-section/cartouche-ui.tsx | 5 ++--- .../component-section/data-reference-cartouche.tsx | 5 ++++- .../navigator-item/navigator-condensed-entry.tsx | 9 +++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 7f4d1761f3b8..b6a50591d957 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -1,5 +1,4 @@ import React from 'react' -import type { IcnColor } from '../../../../uuiui' import { FlexRow, Icn, Tooltip, UtopiaStyles, useColorTheme } from '../../../../uuiui' import { when } from '../../../../utils/react-conditionals' @@ -9,7 +8,7 @@ export interface HoverHandlers { } export type CartoucheUIProps = React.PropsWithChildren<{ - tooltip: string + tooltip?: string | null source: 'internal' | 'external' | 'literal' role: 'selection' | 'information' | 'folder' datatype: 'renderable' | 'boolean' | 'array' | 'object' @@ -94,7 +93,7 @@ export const CartoucheUI = React.forwardRef( }} ref={ref} > - + {/* this div prevents the popup form putting padding into the condensed rows */}
@@ -151,6 +153,7 @@ interface DataCartoucheInnerProps { onDelete: () => void testId: string contentIsComingFromServer: boolean + hideTooltip?: boolean } export const DataCartoucheInner = React.forwardRef( @@ -193,7 +196,7 @@ export const DataCartoucheInner = React.forwardRef( selected={selected} inverted={inverted} testId={testId} - tooltip={contentsToDisplay.label ?? 'DATA'} + tooltip={!props.hideTooltip ? contentsToDisplay.label ?? 'DATA' : null} role='selection' source={source} ref={ref} diff --git a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx index fd75bf28ac72..fdd3348e08b5 100644 --- a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx @@ -332,7 +332,7 @@ const CondensedEntryItemContent = React.memo( isDataReference, , )} @@ -341,8 +341,9 @@ const CondensedEntryItemContent = React.memo( {when( isDataReference, , )}
@@ -436,7 +437,7 @@ const WrappedExpandableIndicator = React.memo( WrappedExpandableIndicator.displayName = 'WrappedExpandableIndicator' const WrappedLayoutIcon = React.memo( - (props: { entry: NavigatorEntry; disabled: boolean; selected: boolean }) => { + (props: { entry: NavigatorEntry; hideTooltip: boolean; selected: boolean }) => { const entryLabel = useEntryLabel(props.entry) const iconOverride = useEditorState( @@ -457,7 +458,7 @@ const WrappedLayoutIcon = React.memo( ) return ( - +
Date: Mon, 3 Jun 2024 12:30:28 +0200 Subject: [PATCH 012/103] New default hydrogen project (#5803) **Problem:** Let's change the default hydrogen project to the new sample store! --- utopia-remix/app/routes/projects.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/utopia-remix/app/routes/projects.tsx b/utopia-remix/app/routes/projects.tsx index 7c6f35632625..86187b363aee 100644 --- a/utopia-remix/app/routes/projects.tsx +++ b/utopia-remix/app/routes/projects.tsx @@ -1335,7 +1335,10 @@ const projectTemplates = [ title: 'Hydrogen Project', onClick: () => window.open( - createCloneLink(AccessLevel.PUBLIC, { cloneRepo: 'concrete-utopia/hydrogen-november' }), + createCloneLink(AccessLevel.PUBLIC, { + cloneRepo: 'concrete-utopia/hydrogen-may', + cloneBranch: 'sehl-utopia', + }), '_blank', ), thumbnail: '/assets/thumbnail-hydrogen.png', From 8a89dde60c532c7e8ea77935cd16f81645a77a0f Mon Sep 17 00:00:00 2001 From: RheeseyB <1044774+Rheeseyb@users.noreply.github.com> Date: Mon, 3 Jun 2024 15:43:59 +0100 Subject: [PATCH 013/103] Replace floating insert menu (#5746) Blocked waiting on #5794 **Problem** We were still using the old insert menu in the canvas toolbar **Fix** Use the new component picker in the canvas toolbar. The main changes here are in `editor/src/components/editor/canvas-toolbar.tsx` (where the old dropdown list was replaced with the new component picker) and `editor/src/components/navigator/navigator-item/component-picker.tsx` (as I've had to update the props so that they styling is different when the picker is rendered inside the toolbar). This PR has ripped out a lot of now dead code around the old dropdown, but hasn't removed the (already dead but still used in some tests) insert menu pane. Note that this PR has removed the `g` shortcut (which was an alias for the `w` to 'wrap in' shortcut but opened the old menu rather than the new one - `cmd`+`g` still exists). I can put that back if we still want it. I just deleted it whilst I was flushing out dead code. Also note that with the old insert menu we had the ability to wrap in certain elements that cannot be inserted normally (e.g. the `Group` element). That functionality no longer exists. image image **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5443 --------- Co-authored-by: Federico Ruggi <1081051+ruggi@users.noreply.github.com> --- .../canvas-context-menu.spec.browser2.tsx | 4 +- .../canvas/ui/floating-insert-menu-helpers.ts | 8 +- .../canvas/ui/floating-insert-menu.tsx | 212 --------- editor/src/components/context-menu-items.ts | 1 - editor/src/components/editor/action-types.ts | 12 - .../editor/actions/action-creators.ts | 16 - .../components/editor/actions/action-utils.ts | 2 - .../editor/actions/actions.spec.browser2.tsx | 1 - .../src/components/editor/actions/actions.tsx | 20 - .../editor/canvas-toolbar-states.tsx | 13 - .../editor/canvas-toolbar.spec.browser2.tsx | 114 +---- .../src/components/editor/canvas-toolbar.tsx | 415 ++++++------------ .../editor/conditionals.spec.browser2.tsx | 6 +- .../components/editor/convert-callbacks.ts | 317 ------------- editor/src/components/editor/defaults.ts | 17 - .../components/editor/global-shortcuts.tsx | 9 +- .../editor/insertmenu.spec.browser2.tsx | 89 +--- .../editor/remix-navigation-bar.tsx | 1 + .../components/editor/shortcut-definitions.ts | 5 - .../components/editor/store/editor-state.ts | 62 --- .../components/editor/store/editor-update.tsx | 4 - .../store/store-deep-equality-instances.ts | 79 ---- .../store/store-hook-substore-helpers.ts | 3 - .../component-picker-context-menu.tsx | 12 +- .../navigator-item/component-picker.tsx | 62 ++- ...nent-picker-context-menu.spec.browser2.tsx | 6 +- editor/src/utils/utils.test-utils.tsx | 28 +- editor/src/uuiui/icn.tsx | 2 + 28 files changed, 221 insertions(+), 1299 deletions(-) delete mode 100644 editor/src/components/editor/convert-callbacks.ts diff --git a/editor/src/components/canvas/canvas-context-menu.spec.browser2.tsx b/editor/src/components/canvas/canvas-context-menu.spec.browser2.tsx index b6e42fed18c0..fa100a357137 100644 --- a/editor/src/components/canvas/canvas-context-menu.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-context-menu.spec.browser2.tsx @@ -27,7 +27,7 @@ import { } from './ui-jsx.test-utils' import { expectNoAction, - searchInFloatingMenu, + searchInComponentPicker, selectComponentsForTest, } from '../../utils/utils.test-utils' import { MetadataUtils } from '../../core/model/element-metadata-utils' @@ -952,5 +952,5 @@ describe('canvas context menu', () => { async function wrapInElement(renderResult: EditorRenderResult, query: string) { await pressKey('w') // open the wrap menu - await searchInFloatingMenu(renderResult, query) + await searchInComponentPicker(renderResult, query) } diff --git a/editor/src/components/canvas/ui/floating-insert-menu-helpers.ts b/editor/src/components/canvas/ui/floating-insert-menu-helpers.ts index b9a85deb12cf..858c1d1e2e36 100644 --- a/editor/src/components/canvas/ui/floating-insert-menu-helpers.ts +++ b/editor/src/components/canvas/ui/floating-insert-menu-helpers.ts @@ -1,16 +1,12 @@ -import type { FloatingInsertMenuState } from '../../editor/store/editor-state' - -export type InsertMenuMode = FloatingInsertMenuState['insertMenuMode'] +export type InsertMenuMode = 'insert' | 'swap' | 'wrap' export const insertMenuModes: { all: InsertMenuMode[] - onlyClosed: InsertMenuMode[] onlyInsert: InsertMenuMode[] onlyConvert: InsertMenuMode[] onlyWrap: InsertMenuMode[] } = { - all: ['closed', 'insert', 'swap', 'wrap'], - onlyClosed: ['closed'], + all: ['insert', 'swap', 'wrap'], onlyInsert: ['insert'], onlyConvert: ['swap'], onlyWrap: ['wrap'], diff --git a/editor/src/components/canvas/ui/floating-insert-menu.tsx b/editor/src/components/canvas/ui/floating-insert-menu.tsx index 44fe143e1918..f735aeac2c33 100644 --- a/editor/src/components/canvas/ui/floating-insert-menu.tsx +++ b/editor/src/components/canvas/ui/floating-insert-menu.tsx @@ -1,27 +1,17 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ import React from 'react' -import { jsx } from '@emotion/react' -import type { CSSObject } from '@emotion/serialize' -import type { OptionProps, StylesConfig } from 'react-windowed-select' - -import { getControlStyles } from '../../../uuiui-deps' import { Substores, useEditorState } from '../../editor/store/store-hook' -import { Icn, useColorTheme, UtopiaTheme } from '../../../uuiui' import { usePossiblyResolvedPackageDependencies } from '../../editor/npm-dependency/npm-dependency' import type { InsertableComponent, InsertableComponentGroup, InsertableComponentGroupType, - InsertableVariable, } from '../../shared/project-components' import { getInsertableGroupLabel, getNonEmptyComponentGroups, isInsertableVariable, } from '../../shared/project-components' -import { InspectorInputEmotionStyle } from '../../../uuiui/inputs/base-input' import { optionalMap } from '../../../core/shared/optional-utils' import type { InsertMenuMode } from './floating-insert-menu-helpers' import { @@ -29,8 +19,6 @@ import { getVariablesInScope, } from '../../../components/shared/scoped-variables' -export const FloatingMenuTestId = 'floating-menu-test-id' - export type InsertMenuItemValue = InsertableComponent & { source: InsertableComponentGroupType | null key: string @@ -152,203 +140,3 @@ export function useGetInsertableComponents( return insertableComponents } } - -export function useComponentSelectorStyles(): StylesConfig { - const colorTheme = useColorTheme() - // componentSelectorStyles will only be recreated if the theme changes, otherwise we re-use the same object - return React.useMemo( - () => ({ - container: (styles): CSSObject => ({ - // the outermost element. It contains the popup menu, so don't set a height on it! - // shouldn't contain any sizing - // ...styles, - flexGrow: 1, - display: 'flex', - flexDirection: 'column', - }), - control: (styles): CSSObject => ({ - // need to remove styles here, since that implicitly sets a height of 38 - // ...styles, - display: 'flex', - background: 'transparent', - height: UtopiaTheme.layout.rowHeight.normal, - outline: 'none', - paddingLeft: 8, - paddingRight: 8, - ':focus-within': { - outline: 'none', - border: 'none', - }, - }), - valueContainer: (styles): CSSObject => ({ - // the container for added options (tags) and input - // sibling to indicatorsContainer - // default styles mess with layout, so ignore them - // ...styles, - display: 'flex', - position: 'relative', - flexGrow: 1, - flexShrink: 0, - overflowX: 'scroll', - alignItems: 'center', - gap: 4, - paddingLeft: 0, - paddingRight: 0, - paddingTop: 0, - paddingBottom: 0, - }), - indicatorsContainer: (styles): CSSObject => ({ - // ...styles, - display: 'none', - }), - - multiValue: (styles, { data }): CSSObject => { - return { - // ...styles, - cursor: 'pointer', - display: 'flex', - alignItems: 'center', - } - }, - multiValueLabel: (styles, { data }): CSSObject => ({ - // ...styles, - fontSize: 10, - padding: '2px 4px', - }), - multiValueRemove: (styles, { data }): CSSObject => ({ - // ...styles, - width: 11, - display: 'flex', - paddingTop: 2, - opacity: 0.4, - color: styles.color, - ':hover': { - opacity: 1, - backgroundColor: styles.color, - }, - }), - menu: (styles): CSSObject => { - // the outer shell - return { - // ...styles, - boxShadow: 'none', - borderRadius: 0, - background: 'transparent', - overflowY: 'scroll', - flex: 1, - } - }, - menuList: (styles): CSSObject => { - // the list wrapper - return { - // ...styles, - position: 'relative', - maxHeight: 210, - paddingLeft: 8, - paddingRight: 8, - overflowY: 'auto', - display: 'flex', - flexDirection: 'column', - gap: 6, - paddingBottom: UtopiaTheme.layout.rowHeight.large, - } - }, - input: (styles): CSSObject => { - return { - // ...styles, - ...(InspectorInputEmotionStyle({ - hasLabel: false, - controlStyles: getControlStyles('simple'), - }) as CSSObject), - paddingLeft: 4, - backgroundColor: colorTheme.seperator.value, - flexGrow: 1, - display: 'flex', - alignItems: 'center', - } - }, - placeholder: (styles): CSSObject => { - return { ...styles, marginLeft: 4 } - }, - option: (styles, { data, isDisabled, isFocused, isSelected }): CSSObject => { - // a single entry in the options list - - return { - // ...styles, - height: UtopiaTheme.layout.rowHeight.smaller, - display: 'flex', - alignItems: 'center', - paddingLeft: 4, - paddingRight: 4, - cursor: isDisabled ? 'not-allowed' : 'default', - color: isFocused ? colorTheme.bg0.value : colorTheme.fg0.value, - backgroundColor: 'transparent', - borderRadius: UtopiaTheme.inputBorderRadius, - } - }, - group: (): CSSObject => { - return { - // ...styles, - } - }, - groupHeading: (styles): CSSObject => { - return { - // ...styles, - display: 'none', - } - }, - }), - [colorTheme], - ) -} - -export const CustomComponentOption = (props: OptionProps) => { - const { innerRef, innerProps, isDisabled, isFocused, label, data } = props - const colorTheme = useColorTheme() - return ( -
-
- - {label} -
-
-
- {data.source ?? ''} -
- -
-
- ) -} diff --git a/editor/src/components/context-menu-items.ts b/editor/src/components/context-menu-items.ts index 9a19a694980e..e74fdf5bd83a 100644 --- a/editor/src/components/context-menu-items.ts +++ b/editor/src/components/context-menu-items.ts @@ -34,7 +34,6 @@ import { toggleHidden, } from './editor/actions/action-creators' import { - floatingInsertMenuStateSwap, type AllElementProps, type InternalClipboard, type NavigatorEntry, diff --git a/editor/src/components/editor/action-types.ts b/editor/src/components/editor/action-types.ts index 950e6e1eaf53..a50f7c246861 100644 --- a/editor/src/components/editor/action-types.ts +++ b/editor/src/components/editor/action-types.ts @@ -48,7 +48,6 @@ import type { EditorState, ElementsToRerender, ErrorMessages, - FloatingInsertMenuState, GithubState, LeftMenuTab, ModalDialog, @@ -542,15 +541,6 @@ export interface WrapInElement { whatToWrapWith: WrapInElementWith } -export interface OpenFloatingInsertMenu { - action: 'OPEN_FLOATING_INSERT_MENU' - mode: FloatingInsertMenuState -} - -export interface CloseFloatingInsertMenu { - action: 'CLOSE_FLOATING_INSERT_MENU' -} - export interface UnwrapElements { action: 'UNWRAP_ELEMENTS' targets: ElementPath[] @@ -1258,8 +1248,6 @@ export type EditorAction = | SaveAsset | ResetPins | WrapInElement - | OpenFloatingInsertMenu - | CloseFloatingInsertMenu | UnwrapElements | SetNavigatorRenamingTarget | RedrawOldCanvasControls diff --git a/editor/src/components/editor/actions/action-creators.ts b/editor/src/components/editor/actions/action-creators.ts index c05c366c6dc3..219231d9b2f4 100644 --- a/editor/src/components/editor/actions/action-creators.ts +++ b/editor/src/components/editor/actions/action-creators.ts @@ -160,8 +160,6 @@ import type { SetCurrentTheme, FocusFormulaBar, UpdateFormulaBarMode, - OpenFloatingInsertMenu, - CloseFloatingInsertMenu, InsertInsertable, ToggleFocusedOmniboxTab, SetPropTransient, @@ -246,7 +244,6 @@ import type { ImageDragSessionState, DuplicationState, ErrorMessages, - FloatingInsertMenuState, GithubState, LeftMenuTab, ModalDialog, @@ -809,13 +806,6 @@ export function unwrapElements(targets: ElementPath[]): UnwrapElements { } } -export function openFloatingInsertMenu(mode: FloatingInsertMenuState): OpenFloatingInsertMenu { - return { - action: 'OPEN_FLOATING_INSERT_MENU', - mode: mode, - } -} - export function wrapInElement( targets: Array, whatToWrapWith: WrapInElementWith, @@ -827,12 +817,6 @@ export function wrapInElement( } } -export function closeFloatingInsertMenu(): CloseFloatingInsertMenu { - return { - action: 'CLOSE_FLOATING_INSERT_MENU', - } -} - export function setCursorOverlay(cursor: CSSCursor | null): SetCursorOverlay { return { action: 'SET_CURSOR_OVERLAY', diff --git a/editor/src/components/editor/actions/action-utils.ts b/editor/src/components/editor/actions/action-utils.ts index 7f69bc4eacac..a0f06eb2a5c8 100644 --- a/editor/src/components/editor/actions/action-utils.ts +++ b/editor/src/components/editor/actions/action-utils.ts @@ -107,8 +107,6 @@ export function isTransientAction(action: EditorAction): boolean { case 'FOCUS_CLASS_NAME_INPUT': case 'FOCUS_FORMULA_BAR': case 'UPDATE_FORMULA_BAR_MODE': - case 'OPEN_FLOATING_INSERT_MENU': - case 'CLOSE_FLOATING_INSERT_MENU': case 'SET_PROP_TRANSIENT': case 'CLEAR_TRANSIENT_PROPS': case 'DECREMENT_RESIZE_OPTIONS_SELECTED_INDEX': diff --git a/editor/src/components/editor/actions/actions.spec.browser2.tsx b/editor/src/components/editor/actions/actions.spec.browser2.tsx index 4eb4cccb0f64..96605c8da5ea 100644 --- a/editor/src/components/editor/actions/actions.spec.browser2.tsx +++ b/editor/src/components/editor/actions/actions.spec.browser2.tsx @@ -39,7 +39,6 @@ import { expectNoAction, expectSingleUndoNSaves, searchInComponentPicker, - searchInFloatingMenu, selectComponentsForTest, setFeatureForBrowserTestsUseInDescribeBlockOnly, } from '../../../utils/utils.test-utils' diff --git a/editor/src/components/editor/actions/actions.tsx b/editor/src/components/editor/actions/actions.tsx index 4d37da280dac..66fbba473a25 100644 --- a/editor/src/components/editor/actions/actions.tsx +++ b/editor/src/components/editor/actions/actions.tsx @@ -203,7 +203,6 @@ import type { ClearImageFileBlob, ClearParseOrPrintInFlight, ClearTransientProps, - CloseFloatingInsertMenu, ClosePopup, CloseTextEditor, DeleteFile, @@ -224,7 +223,6 @@ import type { Load, NewProject, OpenCodeEditorFile, - OpenFloatingInsertMenu, OpenPopup, OpenTextEditor, RemoveFromNodeModulesContents, @@ -957,7 +955,6 @@ export function restoreEditorState( domWalkerAdditionalElementsToUpdate: currentEditor.canvas.domWalkerAdditionalElementsToUpdate, controls: currentEditor.canvas.controls, }, - floatingInsertMenu: currentEditor.floatingInsertMenu, inspector: { visible: currentEditor.inspector.visible, classnameFocusCounter: currentEditor.inspector.classnameFocusCounter, @@ -2726,23 +2723,6 @@ export const UPDATE_FNS = { ], } }, - OPEN_FLOATING_INSERT_MENU: (action: OpenFloatingInsertMenu, editor: EditorModel): EditorModel => { - return { - ...editor, - floatingInsertMenu: action.mode, - } - }, - CLOSE_FLOATING_INSERT_MENU: ( - action: CloseFloatingInsertMenu, - editor: EditorModel, - ): EditorModel => { - return { - ...editor, - floatingInsertMenu: { - insertMenuMode: 'closed', - }, - } - }, UNWRAP_ELEMENTS: ( action: UnwrapElements, editor: EditorModel, diff --git a/editor/src/components/editor/canvas-toolbar-states.tsx b/editor/src/components/editor/canvas-toolbar-states.tsx index 4660f6629841..091326327fbe 100644 --- a/editor/src/components/editor/canvas-toolbar-states.tsx +++ b/editor/src/components/editor/canvas-toolbar-states.tsx @@ -21,7 +21,6 @@ type ToolbarMode = imageInsertionActive: boolean buttonInsertionActive: boolean conditionalInsertionActive: boolean - floatingInsertMenuOpen: boolean insertSidebarOpen: boolean } } @@ -36,12 +35,6 @@ export function useToolbarMode(): ToolbarMode { 'useGetToolbarMode editorMode', ) - const floatingInsertMenu = useEditorState( - Substores.restOfEditor, - (store) => store.editor.floatingInsertMenu.insertMenuMode, - 'useGetToolbarMode floatingInsertMenu', - ) - const dragStrategyFlags = useGetDragStrategyIndicatorFlags() const rightMenuTab = useEditorState( @@ -98,7 +91,6 @@ export function useToolbarMode(): ToolbarMode { if ( (editorMode.type === 'select' && editorMode.toolbarMode === 'pseudo-insert') || editorMode.type === 'insert' || - floatingInsertMenu === 'insert' || rightMenuTab === RightMenuTab.Insert ) { const insertionTargetDiv = @@ -127,7 +119,6 @@ export function useToolbarMode(): ToolbarMode { imageInsertionActive: insertionTargetImage, buttonInsertionActive: insertionTargetButton, conditionalInsertionActive: insertionTargetConditional, - floatingInsertMenuOpen: floatingInsertMenu === 'insert', insertSidebarOpen: rightMenuTab === RightMenuTab.Insert, }, } @@ -138,10 +129,6 @@ export function useToolbarMode(): ToolbarMode { return { primary: 'edit', secondary: 'nothing-selected' } } - if (floatingInsertMenu === 'swap' || floatingInsertMenu === 'wrap') { - return { primary: 'edit', secondary: 'selected' } - } - if (dragStrategyFlags?.dragStarted) { return { primary: 'edit', secondary: 'strategy-active' } } diff --git a/editor/src/components/editor/canvas-toolbar.spec.browser2.tsx b/editor/src/components/editor/canvas-toolbar.spec.browser2.tsx index c385b144bd85..d1f3e3d59af3 100644 --- a/editor/src/components/editor/canvas-toolbar.spec.browser2.tsx +++ b/editor/src/components/editor/canvas-toolbar.spec.browser2.tsx @@ -4,7 +4,6 @@ import { createTestProjectWithMultipleFiles } from '../../sample-projects/sample import { selectComponentsForTest, expectSingleUndo2Saves, - searchInFloatingMenu, searchInComponentPicker, } from '../../utils/utils.test-utils' import { @@ -871,7 +870,7 @@ export var storyboard = (props) => { await selectComponentsForTest(editor, [EP.fromString('sb/scene-1/insert-target')]) await pressKey('a') - await searchInFloatingMenu(editor, 'DefaultExportedComp') + await searchInComponentPicker(editor, 'DefaultExportedComp') expect(getPrintedUiJsCodeWithoutUIDs(editor.getEditorState())) .toEqual(`import * as React from 'react' @@ -1431,7 +1430,7 @@ export var Playground = () => { const editor = await setup() await pressKey('a') - await searchInFloatingMenu(editor, 'fragm') + await searchInComponentPicker(editor, 'fragm') expect(getPrintedUiJsCode(editor.getEditorState(), PlaygroundFilePath)) .toEqual(`import * as React from 'react' @@ -1468,7 +1467,7 @@ export var Playground = () => { const editor = await setup() await pressKey('s') - await searchInFloatingMenu(editor, 'fragm') + await searchInComponentPicker(editor, 'fragm') expect(getPrintedUiJsCode(editor.getEditorState(), PlaygroundFilePath)) .toEqual(`import * as React from 'react' @@ -1489,104 +1488,6 @@ export var Playground = () => { `) }) }) - - describe('groups', () => { - it('can wrap elements in a group', async () => { - const editor = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(` -
-
-
- `), - 'await-first-dom-report', - ) - - await selectComponentsForTest(editor, [ - EP.fromString(`${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:container/target`), - ]) - - FOR_TESTS_setNextGeneratedUid('new-group') - - await wrapViaAddElementPopup(editor, 'group') - - expect(getPrintedUiJsCode(editor.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
- -
- -
- `), - ) - }) - xit('cannot insert groups because they are not available for insert', async () => { - const editor = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(` -
-
-
- `), - 'await-first-dom-report', - ) - - await selectComponentsForTest(editor, [ - EP.fromString(`${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:container/target`), - ]) - - await insertViaAddElementPopup(editor, 'group') - - expect(getPrintedUiJsCode(editor.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
- `), - ) - }) - }) }) async function clickEmptySlot(editor: EditorRenderResult) { @@ -1596,15 +1497,10 @@ async function clickEmptySlot(editor: EditorRenderResult) { async function insertViaAddElementPopup(editor: EditorRenderResult, query: string) { await pressKey('a') - await searchInFloatingMenu(editor, query) -} - -async function wrapViaAddElementPopup(editor: EditorRenderResult, query: string) { - await pressKey('g') - await searchInFloatingMenu(editor, query) + await searchInComponentPicker(editor, query) } async function convertViaAddElementPopup(editor: EditorRenderResult, query: string) { await pressKey('s') - await searchInFloatingMenu(editor, query) + await searchInComponentPicker(editor, query) } diff --git a/editor/src/components/editor/canvas-toolbar.tsx b/editor/src/components/editor/canvas-toolbar.tsx index 43b07add066b..f4f52c786d1f 100644 --- a/editor/src/components/editor/canvas-toolbar.tsx +++ b/editor/src/components/editor/canvas-toolbar.tsx @@ -1,8 +1,7 @@ /** @jsxRuntime classic */ /** @jsx jsx */ /** @jsxFrag React.Fragment */ -import { css, jsx } from '@emotion/react' -import type { CSSObject } from '@emotion/react' +import { jsx } from '@emotion/react' import React, { useState } from 'react' import type { TooltipProps } from '../../uuiui' import { Tile, UtopiaStyles, opacity } from '../../uuiui' @@ -16,16 +15,12 @@ import { Tooltip as TooltipWithoutSpanFixme, useColorTheme, } from '../../uuiui' -import { getControlStyles } from '../../uuiui-deps' import CanvasActions from '../canvas/canvas-actions' import { - applyCommandsAction, - closeFloatingInsertMenu, - openFloatingInsertMenu, + insertAsChildTarget, resetCanvas, setRightMenuTab, switchEditorMode, - wrapInElement, } from './actions/action-creators' import { EditorModes } from './editor-modes' import { @@ -34,25 +29,18 @@ import { useEnterDrawToInsertForDiv, useEnterDrawToInsertForImage, useEnterTextEditMode, - useToInsert, } from './insert-callbacks' import { useDispatch } from './store/dispatch-context' import { Substores, useEditorState, useRefEditorState } from './store/store-hook' -import { defaultTransparentViewElement } from './defaults' -import { generateUidWithExistingComponents } from '../../core/model/element-template-utils' import { useToolbarMode } from './canvas-toolbar-states' import { unless, when } from '../../utils/react-conditionals' import { StrategyIndicator } from '../canvas/controls/select-mode/strategy-indicator' -import { toggleAbsolutePositioningCommands } from '../inspector/inspector-common' -import { createFilter } from 'react-select' -import WindowedSelect from 'react-windowed-select' -import { InspectorInputEmotionStyle } from '../../uuiui/inputs/base-input' import { stopPropagation } from '../inspector/common/inspector-utils' -import { useConvertTo } from './convert-callbacks' import { useWrapInDiv } from './wrap-in-callbacks' import { ElementsOutsideVisibleAreaIndicator } from './elements-outside-visible-area-indicator' import { RemixNavigationBar } from './remix-navigation-bar' import { + type InsertableComponent, fragmentComponentInfo, fragmentElementsDescriptors, insertableComponentGroupFragment, @@ -62,17 +50,18 @@ import type { CanvasStrategyIcon } from '../canvas/canvas-strategies/canvas-stra import { isLoggedIn } from './action-types' import type { EditorDispatch } from './action-types' import type { InsertMenuItem } from '../canvas/ui/floating-insert-menu' -import { - CustomComponentOption, - useComponentSelectorStyles, - useGetInsertableComponents, -} from '../canvas/ui/floating-insert-menu' -import { RightMenuTab, floatingInsertMenuStateSwap } from './store/editor-state' +import { useGetInsertableComponents } from '../canvas/ui/floating-insert-menu' +import { RightMenuTab } from './store/editor-state' import { useStatus, useThreads } from '../../../liveblocks.config' import { useAllowedToEditProject, useIsMyProject } from './store/collaborative-editing' import { useCanComment, useReadThreads } from '../../core/commenting/comment-hooks' import { pluck } from '../../core/shared/array-utils' import { MultiplayerWrapper } from '../../utils/multiplayer-wrapper' +import { ComponentPicker } from '../navigator/navigator-item/component-picker' +import { insertComponentPickerItem } from '../navigator/navigator-item/component-picker-context-menu' +import { useAtom } from 'jotai' +import { ActiveRemixSceneAtom } from '../canvas/remix/utopia-remix-root-component' +import * as EP from '../../core/shared/element-path' export const InsertMenuButtonTestId = 'insert-menu-button' export const PlayModeButtonTestId = 'canvas-toolbar-play-mode' @@ -82,119 +71,85 @@ export const CanvasToolbarId = 'canvas-toolbar' export const CanvasToolbarSearchPortalId = 'canvas-toolbar-search-portal' -export const ToolbarSearchListing = React.memo(() => { - return
-}) -ToolbarSearchListing.displayName = 'ToolbarSearchListing' - -export interface CanvasToolbarSearchProps { - actionWith: (item: InsertMenuItem | null) => void -} - export const CanvasToolbarSearchTestID = 'canvas-toolbar-search' -export const CanvasToolbarSearch = React.memo((props: CanvasToolbarSearchProps) => { - const dispatch = useDispatch() - const insertMenuMode = useEditorState( +export const CanvasToolbarSearch = React.memo(() => { + const insertionActive = useEditorState( Substores.restOfEditor, - (store) => store.editor.floatingInsertMenu.insertMenuMode, - 'CanvasToolbarSearch insertMenuMode', + (store) => store.editor.mode.type === 'insert' && store.editor.mode.subjects.length > 0, + 'TopMenu editorMode', ) - const options = useGetInsertableComponents(insertMenuMode) - const componentSelectorStyles = useComponentSelectorStyles() - const menuPortalTarget = document.getElementById(CanvasToolbarSearchPortalId) - const theme = useColorTheme() - const focusedPanelRef = useRefEditorState((store) => store.editor.focusedPanel) - const interactionSessionRef = useRefEditorState((store) => store.editor.canvas.interactionSession) - - // Focus the input when it is displayed. - const selectRef = React.useRef(null) - React.useEffect(() => { - // Only focus when: - // - There's a ref we can use to focus. - // - The canvas is focused, so that we don't unfocus the code editor. - // - If an interaction hasn't already been started. - if ( - selectRef.current != null && - focusedPanelRef.current === 'canvas' && - interactionSessionRef.current === null - ) { - selectRef.current.focus() + + const dispatch = useDispatch() + + const target = useEditorState( + Substores.selectedViews, + (store) => store.editor.selectedViews[0], + 'CanvasToolbarSearch selectedView', + ) + + const insertionTarget = insertAsChildTarget() + + const allInsertableComponents = useGetInsertableComponents('insert').flatMap((group) => { + return { + label: group.label, + options: group.options, } }) - const onKeyDown = React.useCallback( - (e: React.KeyboardEvent) => { - if (e.key === 'Escape') { - switchToSelectModeCloseMenus(dispatch) - } + const projectContentsRef = useRefEditorState((state) => state.editor.projectContents) + const metadataRef = useRefEditorState((state) => state.editor.jsxMetadata) + const elementPathTreesRef = useRefEditorState((state) => state.editor.elementPathTree) + const allElementPropsRef = useRefEditorState((state) => state.editor.allElementProps) + const propertyControlsInfoRef = useRefEditorState((state) => state.editor.propertyControlsInfo) + + const onItemClick = React.useCallback( + (preferredChildToInsert: InsertableComponent) => (e: React.UIEvent) => { + e.stopPropagation() + e.preventDefault() + + insertComponentPickerItem( + preferredChildToInsert, + [target], + projectContentsRef.current, + allElementPropsRef.current, + propertyControlsInfoRef.current, + metadataRef.current, + elementPathTreesRef.current, + dispatch, + insertionTarget, + ) }, + [ + target, + projectContentsRef, + allElementPropsRef, + propertyControlsInfoRef, + metadataRef, + elementPathTreesRef, + dispatch, + insertionTarget, + ], + ) + + const closePicker = React.useCallback( + () => dispatch([switchEditorMode(EditorModes.selectMode(null, false, 'none'))], 'everyone'), [dispatch], ) return ( -
- c.data.source + c.data.label, - })} - styles={{ - ...componentSelectorStyles, - menuPortal: (styles: CSSObject): CSSObject => { - return { - zIndex: -2, - padding: '0 4px', - overflow: 'hidden', - height: 'auto', - backgroundColor: theme.bg1subdued.value, - borderRadius: '0px 10px 10px 10px', - boxShadow: UtopiaStyles.shadowStyles.low.boxShadow, - pointerEvents: 'initial', - } - }, - input: (styles: CSSObject): CSSObject => { - return { - ...(InspectorInputEmotionStyle({ - hasLabel: false, - controlStyles: getControlStyles('simple'), - }) as CSSObject), - paddingLeft: 4, - backgroundColor: colorTheme.seperator.value, - flexGrow: 1, - display: 'flex', - alignItems: 'center', - minWidth: '200px', - borderRadius: '10px', - borderWidth: 1, - borderColor: colorTheme.dynamicBlue.value, - borderStyle: 'solid', - } - }, - menuList: (styles: CSSObject): CSSObject => { - return { - position: 'relative', - maxHeight: 210, - paddingLeft: 8, - paddingRight: 8, - overflowY: 'auto', - display: 'flex', - flexDirection: 'column', - gap: 6, - } - }, - }} - maxMenuHeight={138} +
+
) @@ -204,10 +159,7 @@ CanvasToolbarSearch.displayName = 'CanvasToolbarSearch' export const CanvasToolbarEditButtonID = 'canvas-toolbar-edit-button' function switchToSelectModeCloseMenus(dispatch: EditorDispatch) { - dispatch( - [switchEditorMode(EditorModes.selectMode(null, false, 'none')), closeFloatingInsertMenu()], - 'everyone', - ) + dispatch([switchEditorMode(EditorModes.selectMode(null, false, 'none'))], 'everyone') } export const WrapInDivButtonTestId = 'wrap-in-div-button' @@ -257,64 +209,11 @@ export const CanvasToolbar = React.memo(() => { const insertButtonCallback = useEnterDrawToInsertForButton() const insertConditionalCallback = useEnterDrawToInsertForConditional() - const insertMenuMode = useEditorState( - Substores.restOfEditor, - (store) => store.editor.floatingInsertMenu.insertMenuMode, - 'CanvasToolbar insertMenuMode', - ) - const wrapInDivCallback = useWrapInDiv() - - const convertToCallback = useConvertTo() - const toInsertCallback = useToInsert() - // Back to select mode, close the "floating" menu and turn off the forced insert mode. const dispatchSwitchToSelectModeCloseMenus = React.useCallback(() => { switchToSelectModeCloseMenus(dispatch) }, [dispatch]) - const convertToAndClose = React.useCallback( - (convertTo: InsertMenuItem | null) => { - convertToCallback(convertTo) - dispatchSwitchToSelectModeCloseMenus() - }, - [convertToCallback, dispatchSwitchToSelectModeCloseMenus], - ) - - const convertToFragment = React.useCallback(() => { - // Should be consistent with the value that would be present in the dropdown. - // Done like this to avoid having to actually pull the options in the dropdown - // as that will cause a lot of extra work when rendering this toolbar. - const convertToFragmentMenuItem: InsertMenuItem = { - label: fragmentComponentInfo.insertMenuLabel, - source: null, - value: { - importsToAdd: fragmentComponentInfo.importsToAdd, - element: fragmentComponentInfo.elementToInsert, - name: fragmentComponentInfo.insertMenuLabel, - stylePropOptions: [], - defaultSize: null, - source: insertableComponentGroupFragment(), - key: fragmentComponentInfo.insertMenuLabel, - insertionCeiling: null, - icon: fragmentElementsDescriptors.fragment.icon, - }, - } - convertToAndClose(convertToFragmentMenuItem) - }, [convertToAndClose]) - - const wrapInDivAndClose = React.useCallback(() => { - wrapInDivCallback() - dispatchSwitchToSelectModeCloseMenus() - }, [dispatchSwitchToSelectModeCloseMenus, wrapInDivCallback]) - - const toInsertAndClose = React.useCallback( - (toInsert: InsertMenuItem | null) => { - toInsertCallback(toInsert) - dispatchSwitchToSelectModeCloseMenus() - }, - [dispatchSwitchToSelectModeCloseMenus, toInsertCallback], - ) - const zoomLevel = useEditorState( Substores.canvas, (store) => store.editor.canvas.scale, @@ -383,7 +282,7 @@ export const CanvasToolbar = React.memo(() => { { boxShadow: UtopiaStyles.shadowStyles.low.boxShadow, pointerEvents: 'initial', zIndex: -1, // it sits below the main menu row, but we want the main menu's shadow to cast over this one - //to make the submenu appear visually underneath the corners of the main menu + // to make the submenu appear visually underneath the corners of the main menu marginTop: -6, + paddingTop: 6, }} > - {wrapped} + {wrapped} ) }, []) @@ -430,6 +330,13 @@ export const CanvasToolbar = React.memo(() => { const isMyProject = useIsMyProject() + const [activeRemixScene] = useAtom(ActiveRemixSceneAtom) + const remixSceneIsActive = !EP.isEmptyPath(activeRemixScene) + const showRemixNavBar = + remixSceneIsActive && + ((canvasToolbarMode.primary === 'edit' && canvasToolbarMode.secondary !== 'strategy-active') || + canvasToolbarMode.primary === 'play') + return ( { {/* Edit Mode submenus */} {when( canvasToolbarMode.primary === 'edit' && - canvasToolbarMode.secondary === 'selected' && + canvasToolbarMode.secondary === 'strategy-active' && allowedToEdit, - <> - {when( - insertMenuMode === 'wrap', - wrapInSubmenu( - + , + )} + {/* Insert Mode */} + {canvasToolbarMode.primary === 'insert' + ? wrapInSubmenu( + + { style={{ width: undefined }} /> - - - + - - - - , - ), - )} - {when( - insertMenuMode === 'swap', - wrapInSubmenu( - - + - - - + + + + + - - + + + + - , - ), - )} - , - )} - {when( - canvasToolbarMode.primary === 'edit' && - canvasToolbarMode.secondary === 'strategy-active' && - allowedToEdit, - , - )} - {/* Insert Mode */} - {canvasToolbarMode.primary === 'insert' - ? wrapInSubmenu( - - - - - - - - - - - - - - - - - - - - , + + , ) : null} {/* Live Mode */} - {(canvasToolbarMode.primary === 'edit' && - canvasToolbarMode.secondary !== 'strategy-active' && - insertMenuMode === 'closed') || - canvasToolbarMode.primary === 'play' - ? wrapInSubmenu() - : null} - + {showRemixNavBar ? wrapInSubmenu() : null} ) }) diff --git a/editor/src/components/editor/conditionals.spec.browser2.tsx b/editor/src/components/editor/conditionals.spec.browser2.tsx index c4e7b8a5d633..735968b12e6b 100644 --- a/editor/src/components/editor/conditionals.spec.browser2.tsx +++ b/editor/src/components/editor/conditionals.spec.browser2.tsx @@ -10,11 +10,7 @@ import { unsafeGet } from '../../core/shared/optics/optic-utilities' import type { Optic } from '../../core/shared/optics/optics' import { forceNotNull } from '../../core/shared/optional-utils' import type { ElementPath } from '../../core/shared/project-file-types' -import { - searchInComponentPicker, - searchInFloatingMenu, - selectComponentsForTest, -} from '../../utils/utils.test-utils' +import { searchInComponentPicker, selectComponentsForTest } from '../../utils/utils.test-utils' import type { EditorRenderResult } from '../canvas/ui-jsx.test-utils' import { TestScenePath, diff --git a/editor/src/components/editor/convert-callbacks.ts b/editor/src/components/editor/convert-callbacks.ts deleted file mode 100644 index 523f70cf97d1..000000000000 --- a/editor/src/components/editor/convert-callbacks.ts +++ /dev/null @@ -1,317 +0,0 @@ -import * as React from 'react' -import { generateUidWithExistingComponents } from '../../core/model/element-template-utils' -import { safeIndex } from '../..//core/shared/array-utils' -import { emptyElementPath } from '../..//core/shared/element-path' -import type { - ElementInstanceMetadataMap, - JSXConditionalExpressionWithoutUID, - JSXFragmentWithoutUID, -} from '../..//core/shared/element-template' -import { - emptyComments, - jsExpressionValue, - jsxElement, - jsxTextBlock, - setJSXAttributesAttribute, -} from '../..//core/shared/element-template' -import type { ElementPath, Imports } from '../..//core/shared/project-file-types' -import { assertNever } from '../..//core/shared/utils' -import { emptyImports } from '../..//core/workers/common/project-file-utils' -import type { ProjectContentTreeRoot } from '../assets' -import { getElementsToTarget } from '../inspector/common/inspector-utils' -import type { InsertableComponentGroupType } from '../shared/project-components' -import { insertableComponent } from '../shared/project-components' -import type { EditorAction } from './action-types' -import { - wrapInElement, - insertInsertable, - updateJSXElementName, - applyCommandsAction, -} from './actions/action-creators' -import { useDispatch } from './store/dispatch-context' -import type { AllElementProps, FloatingInsertMenuState } from './store/editor-state' -import { useRefEditorState } from './store/store-hook' -import { getInsertionPath } from './store/insertion-path' -import type { ElementPathTrees } from '../../core/shared/element-path-tree' -import type { InsertMenuItem, InsertMenuItemValue } from '../canvas/ui/floating-insert-menu' -import { wrapInDivStrategy } from './wrap-in-callbacks' -import { commandsForFirstApplicableStrategy } from '../inspector/inspector-strategies/inspector-strategy' -import type { PropertyControlsInfo } from '../custom-code/code-file' - -export function changeConditionalOrFragment( - projectContents: ProjectContentTreeRoot, - jsxMetadata: ElementInstanceMetadataMap, - elementPathTree: ElementPathTrees, - selectedViews: Array, - floatingMenuState: FloatingInsertMenuState, - fixedSizeForInsertion: boolean, - element: JSXConditionalExpressionWithoutUID | JSXFragmentWithoutUID, - propertyControlsInfo: PropertyControlsInfo, -): Array { - let actionsToDispatch: Array = [] - const importsToAdd: Imports = - element.type === 'JSX_FRAGMENT' && element.longForm - ? { - react: { - importedAs: 'React', - importedFromWithin: [], - importedWithName: null, - }, - } - : emptyImports() - - switch (floatingMenuState.insertMenuMode) { - case 'wrap': - actionsToDispatch = [ - wrapInElement(selectedViews, { - element: { - ...element, - uid: generateUidWithExistingComponents(projectContents), - }, - importsToAdd: importsToAdd, - }), - ] - break - case 'insert': - const targetParent = safeIndex(selectedViews, 0) ?? emptyElementPath - - const wrapperUID = generateUidWithExistingComponents(projectContents) - - const insertionPath = getInsertionPath( - targetParent, - projectContents, - jsxMetadata, - elementPathTree, - wrapperUID, - selectedViews.length, - propertyControlsInfo, - ) - actionsToDispatch = [ - insertInsertable( - insertionPath, - insertableComponent(importsToAdd, () => element, '', [], null, null, null), - fixedSizeForInsertion ? 'add-size' : 'do-not-add', - floatingMenuState.indexPosition, - ), - ] - break - case 'swap': { - if (element.type === 'JSX_FRAGMENT') { - const targetsForUpdates = getElementsToTarget(selectedViews) - actionsToDispatch = targetsForUpdates.flatMap((path) => { - return updateJSXElementName(path, { type: 'JSX_FRAGMENT' }, importsToAdd) - }) - } - break - } - case 'closed': - break - default: - assertNever(floatingMenuState) - } - return actionsToDispatch -} - -export function changeElement( - projectContents: ProjectContentTreeRoot, - jsxMetadata: ElementInstanceMetadataMap, - elementPathTree: ElementPathTrees, - allElementProps: AllElementProps, - selectedViews: Array, - floatingMenuState: FloatingInsertMenuState, - fixedSizeForInsertion: boolean, - addContentForInsertion: boolean, - pickedInsertableComponent: InsertMenuItemValue, - source: InsertableComponentGroupType | null, - propertyControlsInfo: PropertyControlsInfo, -): Array { - const element = pickedInsertableComponent.element() - if (element.type !== 'JSX_ELEMENT') { - return [] - } - let actionsToDispatch: Array = [] - switch (floatingMenuState.insertMenuMode) { - case 'wrap': - if (source?.type === 'HTML_DIV') { - const commands = commandsForFirstApplicableStrategy([ - wrapInDivStrategy( - jsxMetadata, - selectedViews, - elementPathTree, - allElementProps, - projectContents, - propertyControlsInfo, - ), - ]) - - if (commands != null) { - actionsToDispatch = [applyCommandsAction(commands)] - } - break - } - - const newUID = generateUidWithExistingComponents(projectContents) - - const newElement = jsxElement( - element.name, - newUID, - setJSXAttributesAttribute( - element.props, - 'data-uid', - jsExpressionValue(newUID, emptyComments), - ), - element.children, - ) - - actionsToDispatch = [ - wrapInElement(selectedViews, { - element: newElement, - importsToAdd: pickedInsertableComponent.importsToAdd, - }), - ] - break - case 'insert': - let elementToInsert = pickedInsertableComponent - if (addContentForInsertion && element.children.length === 0) { - elementToInsert = { - ...pickedInsertableComponent, - element: () => ({ - ...element, - children: [jsxTextBlock('Utopia')], - }), - } - } - - const targetParent: ElementPath | null = - floatingMenuState.parentPath ?? safeIndex(selectedViews, 0) ?? null - if (targetParent != null) { - const wrapperUID = generateUidWithExistingComponents(projectContents) - - const insertionPath = getInsertionPath( - targetParent, - projectContents, - jsxMetadata, - elementPathTree, - wrapperUID, - selectedViews.length, - propertyControlsInfo, - ) - // TODO multiselect? - actionsToDispatch = [ - insertInsertable( - insertionPath, - elementToInsert, - fixedSizeForInsertion ? 'add-size' : 'do-not-add', - floatingMenuState.indexPosition, - ), - ] - } - break - case 'swap': - // this is taken from render-as.tsx - const targetsForUpdates = getElementsToTarget(selectedViews) - actionsToDispatch = targetsForUpdates.flatMap((path) => { - return updateJSXElementName( - path, - { type: 'JSX_ELEMENT', name: element.name }, - pickedInsertableComponent.importsToAdd, - ) - }) - break - case 'closed': - break - default: - assertNever(floatingMenuState) - } - - return actionsToDispatch -} - -export function getActionsToApplyChange( - projectContents: ProjectContentTreeRoot, - jsxMetadata: ElementInstanceMetadataMap, - elementPathTree: ElementPathTrees, - allElementProps: AllElementProps, - selectedViews: Array, - floatingMenuState: FloatingInsertMenuState, - fixedSizeForInsertion: boolean, - addContentForInsertion: boolean, - insertMenuItemValue: InsertMenuItemValue, - propertyControlsInfo: PropertyControlsInfo, -): Array { - const element = insertMenuItemValue.element() - switch (element.type) { - case 'JSX_CONDITIONAL_EXPRESSION': - case 'JSX_FRAGMENT': - return changeConditionalOrFragment( - projectContents, - jsxMetadata, - elementPathTree, - selectedViews, - floatingMenuState, - fixedSizeForInsertion, - element, - propertyControlsInfo, - ) - case 'JSX_ELEMENT': - return changeElement( - projectContents, - jsxMetadata, - elementPathTree, - allElementProps, - selectedViews, - floatingMenuState, - fixedSizeForInsertion, - addContentForInsertion, - insertMenuItemValue, - insertMenuItemValue.source, - propertyControlsInfo, - ) - case 'JSX_MAP_EXPRESSION': - return [] // we don't support converting to maps - default: - assertNever(element) - } -} - -export function useConvertTo(): (convertTo: InsertMenuItem | null) => void { - const dispatch = useDispatch() - const selectedViewsRef = useRefEditorState((store) => store.editor.selectedViews) - const jsxMetadataRef = useRefEditorState((store) => store.editor.jsxMetadata) - const elementPathTreeRef = useRefEditorState((store) => store.editor.elementPathTree) - const projectContentsRef = useRefEditorState((store) => store.editor.projectContents) - const allElementPropsRef = useRefEditorState((store) => store.editor.projectContents) - const floatingMenuStateRef = useRefEditorState((store) => store.editor.floatingInsertMenu) - const propertyControlsInfoRef = useRefEditorState((store) => store.editor.propertyControlsInfo) - - return React.useCallback( - (convertToMenuItem: InsertMenuItem | null) => { - if (convertToMenuItem != null) { - const convertTo = convertToMenuItem.value - const actions = getActionsToApplyChange( - projectContentsRef.current, - jsxMetadataRef.current, - elementPathTreeRef.current, - allElementPropsRef.current, - selectedViewsRef.current, - floatingMenuStateRef.current, - false, - false, - convertTo, - propertyControlsInfoRef.current, - ) - dispatch(actions, 'everyone') - } - }, - [ - allElementPropsRef, - dispatch, - elementPathTreeRef, - floatingMenuStateRef, - jsxMetadataRef, - projectContentsRef, - selectedViewsRef, - propertyControlsInfoRef, - ], - ) -} diff --git a/editor/src/components/editor/defaults.ts b/editor/src/components/editor/defaults.ts index 8e2cba91e089..222c4723733d 100644 --- a/editor/src/components/editor/defaults.ts +++ b/editor/src/components/editor/defaults.ts @@ -66,23 +66,6 @@ export function defaultAnimatedDivElement(uid: string): JSXElement { ) } -export function defaultTransparentViewElement(uid: string): JSXElement { - return jsxElement( - jsxElementName('div', []), - uid, - jsxAttributesFromMap({ - style: jsExpressionValue( - { - position: 'absolute', - }, - emptyComments, - ), - 'data-uid': jsExpressionValue(uid, emptyComments), - }), - [], - ) -} - export function defaultUnstyledDivElement(uid: string): JSXElement { return jsxElement( jsxElementName('div', []), diff --git a/editor/src/components/editor/global-shortcuts.tsx b/editor/src/components/editor/global-shortcuts.tsx index a13abc200ceb..99fc2629a71e 100644 --- a/editor/src/components/editor/global-shortcuts.tsx +++ b/editor/src/components/editor/global-shortcuts.tsx @@ -85,7 +85,6 @@ import { ZOOM_UI_IN_SHORTCUT, ZOOM_UI_OUT_SHORTCUT, ADD_ELEMENT_SHORTCUT, - GROUP_ELEMENT_PICKER_SHORTCUT, GROUP_ELEMENT_DEFAULT_SHORTCUT, TOGGLE_FOCUSED_OMNIBOX_TAB, FOCUS_CLASS_NAME_INPUT, @@ -108,7 +107,7 @@ import { COMMENT_SHORTCUT, } from './shortcut-definitions' import type { EditorState, LockedElements, NavigatorEntry, UserState } from './store/editor-state' -import { floatingInsertMenuStateSwap, getOpenFile, RightMenuTab } from './store/editor-state' +import { getOpenFile, RightMenuTab } from './store/editor-state' import { CanvasMousePositionRaw, WindowMousePositionRaw } from '../../utils/global-positions' import { pickColorWithEyeDropper } from '../canvas/canvas-utils' import { @@ -600,7 +599,6 @@ export function handleKeyDown( } return [] }, - // For now, the "Group / G" shortcuts do the same as the Wrap Element shortcuts – until we have Grouping working again [GROUP_ELEMENT_DEFAULT_SHORTCUT]: () => { return isSelectMode(editor.mode) && editor.selectedViews.length > 0 ? [ @@ -615,11 +613,6 @@ export function handleKeyDown( ] : [] }, - [GROUP_ELEMENT_PICKER_SHORTCUT]: () => { - return isSelectMode(editor.mode) - ? [EditorActions.openFloatingInsertMenu({ insertMenuMode: 'wrap' })] - : [] - }, [TOGGLE_HIDDEN_SHORTCUT]: () => { return [EditorActions.toggleHidden()] }, diff --git a/editor/src/components/editor/insertmenu.spec.browser2.tsx b/editor/src/components/editor/insertmenu.spec.browser2.tsx index 211bb182b587..25eb6fdd72ce 100644 --- a/editor/src/components/editor/insertmenu.spec.browser2.tsx +++ b/editor/src/components/editor/insertmenu.spec.browser2.tsx @@ -9,6 +9,8 @@ import { } from '../canvas/event-helpers.test-utils' import type { EditorRenderResult } from '../canvas/ui-jsx.test-utils' import { + TestAppUID, + TestSceneUID, getPrintedUiJsCode, makeTestProjectCodeWithSnippet, renderTestEditorWithCode, @@ -16,9 +18,13 @@ import { import { setPanelVisibility, setRightMenuTab } from './actions/action-creators' import { InsertMenuFilterTestId } from './insertmenu' import { RightMenuTab } from './store/editor-state' +import { ComponentPickerTestId } from '../navigator/navigator-item/component-picker' +import * as EP from '../../core/shared/element-path' +import { BakedInStoryboardUID } from '../../core/model/scene-utils' +import { searchInComponentPicker, selectComponentsForTest } from '../../utils/utils.test-utils' function getInsertItems() { - return screen.queryAllByTestId(/^insert-item-/gi) + return screen.queryAllByTestId(/^component-picker-item-/gi) } const allInsertItemsCount = 23 @@ -42,38 +48,13 @@ describe('insert menu', () => { expect(getInsertItems().length).toEqual(allInsertItemsCount) - document.execCommand('insertText', false, 'span') + await searchInComponentPicker(renderResult, 'span') expect(getInsertItems().length).toEqual(1) expect(getInsertItems()[0].innerText).toEqual('span') }) - it('can filter by group name', async () => { - const renderResult = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(`
`), - 'await-first-dom-report', - ) - - await openInsertMenu(renderResult) - - document.execCommand('insertText', false, 'elem') - - expect(getInsertItems().length).toEqual(9) - expect(getInsertItems().map((s) => s.innerText)).toEqual([ - // html elements group - 'span', - 'h1', - 'h2', - 'p', - 'button', - 'input', - 'video', - 'img', - // sample group - 'Sample text', - ]) - }) describe('no match', () => { - it('shows all elements', async () => { + it('shows no elements', async () => { const renderResult = await renderTestEditorWithCode( makeTestProjectCodeWithSnippet(`
`), 'await-first-dom-report', @@ -81,21 +62,10 @@ describe('insert menu', () => { await openInsertMenu(renderResult) - document.execCommand('insertText', false, 'wr0ng') - expect(getInsertItems().length).toEqual(allInsertItemsCount) + await searchInComponentPicker(renderResult, 'wr0ng') + expect(getInsertItems().length).toEqual(0) }) }) - it('does not show insertables that cannot be inserted', async () => { - const renderResult = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(`
`), - 'await-first-dom-report', - ) - - await openInsertMenu(renderResult) - - document.execCommand('insertText', false, 'group') - expect(getInsertItems().length).toEqual(allInsertItemsCount) - }) }) it('supports inserting via keyboard', async () => { @@ -115,34 +85,15 @@ describe('insert menu', () => { 'await-first-dom-report', ) - await openInsertMenu(renderResult) - - FOR_TESTS_setNextGeneratedUid('the-div') - - expect(getInsertItems().length).toEqual(allInsertItemsCount) - - document.execCommand('insertText', false, 'div') + await selectComponentsForTest(renderResult, [ + EP.fromString(`${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:root`), + ]) - const filterBox = await screen.findByTestId(InsertMenuFilterTestId) - forceNotNull('the filter box must not be null', filterBox) - - await pressKey('Enter', { targetElement: filterBox }) - - const targetElement = renderResult.renderedDOM.getByTestId('root') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) + await openInsertMenu(renderResult) - const startPoint = { - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - } - const endPoint = { - x: targetElementBounds.x + 100, - y: targetElementBounds.y + 150, - } + FOR_TESTS_setNextGeneratedUid('div') - await mouseMoveToPoint(canvasControlsLayer, startPoint) - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) + await searchInComponentPicker(renderResult, 'div') await renderResult.getDispatchFollowUpActionsFinished() expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( @@ -161,12 +112,8 @@ describe('insert menu', () => { style={{ backgroundColor: '#aaaaaa33', position: 'absolute', - left: 6, - top: 6, - width: 95, - height: 145, }} - data-uid='the-div' + data-uid='div' />
`), diff --git a/editor/src/components/editor/remix-navigation-bar.tsx b/editor/src/components/editor/remix-navigation-bar.tsx index 256d9607d1f5..a92717f04e5e 100644 --- a/editor/src/components/editor/remix-navigation-bar.tsx +++ b/editor/src/components/editor/remix-navigation-bar.tsx @@ -129,6 +129,7 @@ export const RemixNavigationBar = React.memo(() => { pointerEvents: 'initial', userSelect: 'none', padding: '0 8px', + height: 32, }} onMouseDown={stopPropagation} onClick={stopPropagation} diff --git a/editor/src/components/editor/shortcut-definitions.ts b/editor/src/components/editor/shortcut-definitions.ts index 5aa2848d8644..7f2bc59e4b63 100644 --- a/editor/src/components/editor/shortcut-definitions.ts +++ b/editor/src/components/editor/shortcut-definitions.ts @@ -44,7 +44,6 @@ export const DUPLICATE_SELECTION_SHORTCUT = 'duplicate-selection' export const TOGGLE_BACKGROUND_SHORTCUT = 'toggle-background' export const UNWRAP_ELEMENT_SHORTCUT = 'unwrap-element' export const WRAP_ELEMENT_PICKER_SHORTCUT = 'wrap-element-picker' -export const GROUP_ELEMENT_PICKER_SHORTCUT = 'group-element-picker' export const GROUP_ELEMENT_DEFAULT_SHORTCUT = 'group-element-default' export const TOGGLE_HIDDEN_SHORTCUT = 'toggle-hidden' export const INSERT_IMAGE_SHORTCUT = 'insert-image' @@ -150,10 +149,6 @@ const shortcutDetailsWithDefaults: ShortcutDetails = { key('g', ['cmd', 'shift']), ), [WRAP_ELEMENT_PICKER_SHORTCUT]: shortcut('Wrap elements with a selected element.', key('w', [])), - [GROUP_ELEMENT_PICKER_SHORTCUT]: shortcut( - 'Group elements with a selected element.', - key('g', []), - ), [GROUP_ELEMENT_DEFAULT_SHORTCUT]: shortcut('Group elements with a div.', key('g', 'cmd')), [TOGGLE_HIDDEN_SHORTCUT]: shortcut('Toggle element as hidden.', key('h', ['cmd', 'shift'])), [INSERT_IMAGE_SHORTCUT]: shortcut('Insert an image.', key('i', [])), diff --git a/editor/src/components/editor/store/editor-state.ts b/editor/src/components/editor/store/editor-state.ts index 6382b472f7c7..20e3549badea 100644 --- a/editor/src/components/editor/store/editor-state.ts +++ b/editor/src/components/editor/store/editor-state.ts @@ -672,59 +672,6 @@ export interface NavigatorState { hiddenInNavigator: Array } -export interface FloatingInsertMenuStateClosed { - insertMenuMode: 'closed' -} - -export function floatingInsertMenuStateClosed(): FloatingInsertMenuStateClosed { - return { - insertMenuMode: 'closed', - } -} - -export interface FloatingInsertMenuStateInsert { - insertMenuMode: 'insert' - parentPath: ElementPath | null - indexPosition: IndexPosition | null -} - -export function floatingInsertMenuStateInsert( - parentPath: ElementPath | null, - indexPosition: IndexPosition | null, -): FloatingInsertMenuStateInsert { - return { - insertMenuMode: 'insert', - parentPath: parentPath, - indexPosition: indexPosition, - } -} - -export interface FloatingInsertMenuStateSwap { - insertMenuMode: 'swap' -} - -export function floatingInsertMenuStateSwap(): FloatingInsertMenuStateSwap { - return { - insertMenuMode: 'swap', - } -} - -export interface FloatingInsertMenuStateWrap { - insertMenuMode: 'wrap' -} - -export function floatingInsertMenuStateWrap(): FloatingInsertMenuStateWrap { - return { - insertMenuMode: 'wrap', - } -} - -export type FloatingInsertMenuState = - | FloatingInsertMenuStateClosed - | FloatingInsertMenuStateInsert - | FloatingInsertMenuStateSwap - | FloatingInsertMenuStateWrap - export interface ResizeOptions { propertyTargetOptions: Array propertyTargetSelectedIndex: number @@ -1469,7 +1416,6 @@ export interface EditorState { rightMenu: EditorStateRightMenu interfaceDesigner: EditorStateInterfaceDesigner canvas: EditorStateCanvas - floatingInsertMenu: FloatingInsertMenuState inspector: EditorStateInspector fileBrowser: EditorStateFileBrowser dependencyList: EditorStateDependencyList @@ -1553,7 +1499,6 @@ export function editorState( rightMenu: EditorStateRightMenu, interfaceDesigner: EditorStateInterfaceDesigner, canvas: EditorStateCanvas, - floatingInsertMenu: FloatingInsertMenuState, inspector: EditorStateInspector, fileBrowser: EditorStateFileBrowser, dependencyList: EditorStateDependencyList, @@ -1638,7 +1583,6 @@ export function editorState( rightMenu: rightMenu, interfaceDesigner: interfaceDesigner, canvas: canvas, - floatingInsertMenu: floatingInsertMenu, inspector: inspector, fileBrowser: fileBrowser, dependencyList: dependencyList, @@ -2690,9 +2634,6 @@ export function createEditorState(dispatch: EditorDispatch): EditorState { parentOutlineHighlight: null, }, }, - floatingInsertMenu: { - insertMenuMode: 'closed', - }, inspector: { visible: true, classnameFocusCounter: 0, @@ -3091,9 +3032,6 @@ export function editorModelFromPersistentModel( parentOutlineHighlight: null, }, }, - floatingInsertMenu: { - insertMenuMode: 'closed', - }, inspector: { visible: true, classnameFocusCounter: 0, diff --git a/editor/src/components/editor/store/editor-update.tsx b/editor/src/components/editor/store/editor-update.tsx index b6fa587a1038..185185010d5e 100644 --- a/editor/src/components/editor/store/editor-update.tsx +++ b/editor/src/components/editor/store/editor-update.tsx @@ -344,8 +344,6 @@ export function runSimpleLocalEditorAction( return UPDATE_FNS.DELETE_SELECTED(state, dispatch) case 'WRAP_IN_ELEMENT': return UPDATE_FNS.WRAP_IN_ELEMENT(action, state, derivedState) - case 'OPEN_FLOATING_INSERT_MENU': - return UPDATE_FNS.OPEN_FLOATING_INSERT_MENU(action, state) case 'UNWRAP_ELEMENTS': return UPDATE_FNS.UNWRAP_ELEMENTS(action, state, builtInDependencies) case 'INSERT_IMAGE_INTO_UI': @@ -419,8 +417,6 @@ export function runSimpleLocalEditorAction( return UPDATE_FNS.FOCUS_FORMULA_BAR(state) case 'UPDATE_FORMULA_BAR_MODE': return UPDATE_FNS.UPDATE_FORMULA_BAR_MODE(action, state) - case 'CLOSE_FLOATING_INSERT_MENU': - return UPDATE_FNS.CLOSE_FLOATING_INSERT_MENU(action, state) case 'INSERT_INSERTABLE': return UPDATE_FNS.INSERT_INSERTABLE(action, state) case 'SET_PROP_TRANSIENT': 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 6f868079d0ab..90c52ff49778 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances.ts @@ -300,11 +300,6 @@ import type { CanvasCursor, CursorStackItem, CursorImportanceLevel, - FloatingInsertMenuStateClosed, - FloatingInsertMenuStateSwap, - FloatingInsertMenuStateWrap, - FloatingInsertMenuStateInsert, - FloatingInsertMenuState, EditorStateInspector, EditorStateFileBrowser, EditorStateDependencyList, @@ -388,10 +383,6 @@ import { editorStateCanvas, cursorStackItem, canvasCursor, - floatingInsertMenuStateClosed, - floatingInsertMenuStateSwap, - floatingInsertMenuStateWrap, - floatingInsertMenuStateInsert, editorStateInspector, editorStateFileBrowser, editorStateDependencyList, @@ -3918,70 +3909,6 @@ export function IndexPositionKeepDeepEquality( return keepDeepEqualityResult(newValue, false) } -// Here to cause the build to break if `FloatingInsertMenuStateClosed` is changed. -floatingInsertMenuStateClosed() -export const FloatingInsertMenuStateClosedKeepDeepEquality: KeepDeepEqualityCall< - FloatingInsertMenuStateClosed -> = (oldValue, newValue) => { - return keepDeepEqualityResult(oldValue, true) -} - -export const FloatingInsertMenuStateInsertKeepDeepEquality: KeepDeepEqualityCall = - combine2EqualityCalls( - (menu) => menu.parentPath, - nullableDeepEquality(ElementPathKeepDeepEquality), - (menu) => menu.indexPosition, - nullableDeepEquality(IndexPositionKeepDeepEquality), - floatingInsertMenuStateInsert, - ) - -// Here to cause the build to break if `FloatingInsertMenuStateConvert` is changed. -floatingInsertMenuStateSwap() -export const FloatingInsertMenuStateConvertKeepDeepEquality: KeepDeepEqualityCall< - FloatingInsertMenuStateSwap -> = (oldValue, newValue) => { - return keepDeepEqualityResult(oldValue, true) -} - -// Here to cause the build to break if `FloatingInsertMenuStateWrap` is changed. -floatingInsertMenuStateWrap() -export const FloatingInsertMenuStateWrapKeepDeepEquality: KeepDeepEqualityCall< - FloatingInsertMenuStateWrap -> = (oldValue, newValue) => { - return keepDeepEqualityResult(oldValue, true) -} - -export const FloatingInsertMenuStateKeepDeepEquality: KeepDeepEqualityCall< - FloatingInsertMenuState -> = (oldValue, newValue) => { - switch (oldValue.insertMenuMode) { - case 'closed': - if (newValue.insertMenuMode === oldValue.insertMenuMode) { - return FloatingInsertMenuStateClosedKeepDeepEquality(oldValue, newValue) - } - break - case 'insert': - if (newValue.insertMenuMode === oldValue.insertMenuMode) { - return FloatingInsertMenuStateInsertKeepDeepEquality(oldValue, newValue) - } - break - case 'swap': - if (newValue.insertMenuMode === oldValue.insertMenuMode) { - return FloatingInsertMenuStateConvertKeepDeepEquality(oldValue, newValue) - } - break - case 'wrap': - if (newValue.insertMenuMode === oldValue.insertMenuMode) { - return FloatingInsertMenuStateWrapKeepDeepEquality(oldValue, newValue) - } - break - default: - const _exhaustiveCheck: never = oldValue - throw new Error(`Unhandled type ${JSON.stringify(oldValue)}`) - } - return keepDeepEqualityResult(newValue, false) -} - export const EditorStateInspectorKeepDeepEquality: KeepDeepEqualityCall = combine2EqualityCalls( (inspector) => inspector.visible, @@ -4892,10 +4819,6 @@ export const EditorStateKeepDeepEquality: KeepDeepEqualityCall = ( newValue.interfaceDesigner, ) const canvasResults = EditorStateCanvasKeepDeepEquality(oldValue.canvas, newValue.canvas) - const floatingInsertMenuResults = FloatingInsertMenuStateKeepDeepEquality( - oldValue.floatingInsertMenu, - newValue.floatingInsertMenu, - ) const inspectorResults = EditorStateInspectorKeepDeepEquality( oldValue.inspector, newValue.inspector, @@ -5104,7 +5027,6 @@ export const EditorStateKeepDeepEquality: KeepDeepEqualityCall = ( rightMenuResults.areEqual && interfaceDesignerResults.areEqual && canvasResults.areEqual && - floatingInsertMenuResults.areEqual && inspectorResults.areEqual && fileBrowserResults.areEqual && dependencyListResults.areEqual && @@ -5190,7 +5112,6 @@ export const EditorStateKeepDeepEquality: KeepDeepEqualityCall = ( rightMenuResults.value, interfaceDesignerResults.value, canvasResults.value, - floatingInsertMenuResults.value, inspectorResults.value, fileBrowserResults.value, dependencyListResults.value, diff --git a/editor/src/components/editor/store/store-hook-substore-helpers.ts b/editor/src/components/editor/store/store-hook-substore-helpers.ts index 5fcd1f4488ae..bdcc43be5676 100644 --- a/editor/src/components/editor/store/store-hook-substore-helpers.ts +++ b/editor/src/components/editor/store/store-hook-substore-helpers.ts @@ -90,9 +90,6 @@ export const EmptyEditorStateForKeysOnly: EditorState = { parentOutlineHighlight: null, }, }, - floatingInsertMenu: { - insertMenuMode: 'closed', - }, inspector: { visible: true, classnameFocusCounter: 0, diff --git a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx index c1b726f1e25e..27964c394194 100644 --- a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx +++ b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx @@ -33,6 +33,7 @@ import { replaceMappedElement, setProp_UNSAFE, showToast, + switchEditorMode, wrapInElement, } from '../../editor/actions/action-creators' import * as EP from '../../../core/shared/element-path' @@ -86,6 +87,7 @@ import { emptyImports } from '../../../core/workers/common/project-file-utils' import { commandsForFirstApplicableStrategy } from '../../../components/inspector/inspector-strategies/inspector-strategy' import { wrapInDivStrategy } from '../../../components/editor/wrap-in-callbacks' import type { AllElementProps } from '../../../components/editor/store/editor-state' +import { EditorModes } from '../../editor/editor-modes' type RenderPropTarget = { type: 'render-prop'; prop: string } type ConditionalTarget = { type: 'conditional'; conditionalCase: ConditionalCase } @@ -468,7 +470,7 @@ function moreItem( } } -function insertComponentPickerItem( +export function insertComponentPickerItem( toInsert: InsertableComponent, targets: ElementPath[], projectContents: ProjectContentTreeRoot, @@ -641,7 +643,7 @@ function insertComponentPickerItem( ] })() - dispatch(actions) + dispatch(actions.concat(switchEditorMode(EditorModes.selectMode(null, false, 'none')))) } function toastMessage(insertionTarget: InsertionTarget, toInsert: InsertableComponent) { @@ -703,11 +705,11 @@ interface ComponentPickerContextMenuProps { insertionTarget: InsertionTarget } -export function iconPropsForIcon(icon: Icon): IcnProps { +export function iconPropsForIcon(icon: Icon, inverted: boolean = false): IcnProps { return { category: 'navigator-element', type: icon, - color: 'white', + color: inverted ? 'black' : 'white', } } @@ -949,6 +951,8 @@ const ComponentPickerContextMenuFull = React.memo ) diff --git a/editor/src/components/navigator/navigator-item/component-picker.tsx b/editor/src/components/navigator/navigator-item/component-picker.tsx index ca7f33f9c9c0..b6924d36ba36 100644 --- a/editor/src/components/navigator/navigator-item/component-picker.tsx +++ b/editor/src/components/navigator/navigator-item/component-picker.tsx @@ -33,6 +33,8 @@ export interface ComponentPickerProps { allComponents: Array onItemClick: (elementToInsert: InsertableComponent) => React.UIEventHandler closePicker: () => void + shownInToolbar: boolean + insertionActive: boolean } export interface ElementToInsert { @@ -61,6 +63,8 @@ export function elementToInsertToInsertableComponent( ) } +export const ComponentPickerTestId = 'component-picker-full' + export function componentPickerTestIdForProp(prop: string): string { return `component-picker-${prop}` } @@ -74,7 +78,7 @@ export function componentPickerOptionTestId(componentName: string, variant?: str } export const ComponentPicker = React.memo((props: ComponentPickerProps) => { - const { onItemClick, closePicker } = props + const { onItemClick, closePicker, shownInToolbar, insertionActive } = props const [selectedComponentKey, setSelectedComponentKey] = React.useState(null) const [filter, setFilter] = React.useState('') const menuRef = React.useRef(null) @@ -177,21 +181,27 @@ export const ComponentPicker = React.memo((props: ComponentPickerProps) => { width: '100%', height: '100%', borderRadius: 10, + paddingBottom: shownInToolbar ? '8px' : undefined, }} onKeyDown={onKeyDown} ref={menuRef} + data-testid={ComponentPickerTestId} > - + {filter.length > 0 || !insertionActive ? ( + + ) : null}
) }) @@ -200,33 +210,39 @@ interface ComponentPickerTopSectionProps { components: Array onFilterChange: (filter: string) => void onKeyDown: (e: React.KeyboardEvent) => void + shownInToolbar: boolean } const ComponentPickerTopSection = React.memo((props: ComponentPickerTopSectionProps) => { - const { components, onFilterChange, onKeyDown } = props + const { components, shownInToolbar, onFilterChange, onKeyDown } = props return (
{components.length > 1 && } - +
) }) interface FilterBarProps { + shownInToolbar: boolean onFilterChange: (filter: string) => void onKeyDown?: (e: React.KeyboardEvent) => void } const FilterBar = React.memo((props: FilterBarProps) => { - const { onFilterChange, onKeyDown } = props + const { shownInToolbar, onFilterChange, onKeyDown } = props const [filter, setFilterState] = React.useState('') const setFilter = React.useCallback( @@ -270,11 +286,11 @@ const FilterBar = React.memo((props: FilterBarProps) => { background: 'transparent', // border: `1px solid ${dark.fg3.value}`, --> doesn't work because uses the css var border: `1px solid #888`, - color: `#888`, + color: shownInToolbar ? undefined : `#888`, borderRadius: 4, width: '100%', '&:focus': { - color: '#ccc', + color: shownInToolbar ? undefined : '#ccc', borderColor: '#ccc', }, }} @@ -424,17 +440,23 @@ interface ComponentPickerComponentSectionProps { onItemClick: (elementToInsert: InsertableComponent) => React.MouseEventHandler onItemHover: (elementToInsert: InsertMenuItemValue) => React.MouseEventHandler currentlySelectedKey: string | null + shownInToolbar: boolean +} + +export function componentPickerComponentTestId(key: string): string { + return `component-picker-item-${key}` } const ComponentPickerComponentSection = React.memo( (props: ComponentPickerComponentSectionProps) => { - const { components, onItemClick, onItemHover, currentlySelectedKey } = props + const { components, onItemClick, onItemHover, currentlySelectedKey, shownInToolbar } = props const [isScrolling, setIsScrolling] = React.useState(false) const debouncedSetIsScrolling = React.useRef(debounce(() => setIsScrolling(false), 100)) const onScroll = React.useCallback(() => { setIsScrolling(true) debouncedSetIsScrolling.current() }, []) + return (
diff --git a/editor/src/components/navigator/navigator-item/run-in-shard-2-component-picker-context-menu.spec.browser2.tsx b/editor/src/components/navigator/navigator-item/run-in-shard-2-component-picker-context-menu.spec.browser2.tsx index 8ee8680f5a1a..8bc7150dc200 100644 --- a/editor/src/components/navigator/navigator-item/run-in-shard-2-component-picker-context-menu.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator-item/run-in-shard-2-component-picker-context-menu.spec.browser2.tsx @@ -619,7 +619,9 @@ describe('The navigator component picker context menu', () => { await editor.getDispatchFollowUpActionsFinished() - const flexRowButton = await editor.renderedDOM.findByTestId('/src/other-utils.js-with a column') + const flexRowButton = await editor.renderedDOM.findByTestId( + 'component-picker-item-/src/other-utils.js-with a column', + ) await mouseClickAtPoint(flexRowButton, { x: 3, y: 3 }) @@ -2173,7 +2175,7 @@ async function openContextMenuAndClick(editor: EditorRenderResult, selectors: Se // eslint-disable-next-line no-await-in-loop const button = await waitFor(() => selector.testId != null - ? editor.renderedDOM.getByTestId(selector.testId) + ? editor.renderedDOM.getByTestId(`component-picker-item-${selector.testId}`) : editor.renderedDOM.getByText(selector.text), ) // eslint-disable-next-line no-await-in-loop diff --git a/editor/src/utils/utils.test-utils.tsx b/editor/src/utils/utils.test-utils.tsx index 52cee2c61eb0..9db5dc1fc12d 100644 --- a/editor/src/utils/utils.test-utils.tsx +++ b/editor/src/utils/utils.test-utils.tsx @@ -86,7 +86,9 @@ import { editorStateToElementChildOptic } from '../core/model/common-optics' import { toFirst } from '../core/shared/optics/optic-utilities' import { emptyUiJsxCanvasContextData } from '../components/canvas/ui-jsx-canvas' import type { RenderContext } from '../components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils' -import { componentPickerFilterInputTestId } from '../components/navigator/navigator-item/component-picker' +import { ComponentPickerTestId } from '../components/navigator/navigator-item/component-picker' +import { forceNotNull } from '../core/shared/optional-utils' +import { pressKey } from '../components/canvas/event-helpers.test-utils' export const testRenderContext: RenderContext = { rootScope: {}, @@ -630,25 +632,11 @@ export function boundingClientRectToCanvasRectangle( return canvasBounds } -export async function searchInFloatingMenu(editor: EditorRenderResult, query: string) { - const floatingMenu = editor.renderedDOM.getByTestId(CanvasToolbarSearchTestID) - const searchBox = queryByAttribute('type', floatingMenu, 'text')! - - await act(() => { - fireEvent.focus(searchBox) - fireEvent.change(searchBox, { target: { value: query } }) - fireEvent.blur(searchBox) - fireEvent.keyDown(searchBox, { key: 'Enter', keyCode: 13, metaKey: true }) - }) -} - export async function searchInComponentPicker(editor: EditorRenderResult, query: string) { - const searchBox = editor.renderedDOM.getByTestId(componentPickerFilterInputTestId) + document.execCommand('insertText', false, query) - await act(() => { - fireEvent.focus(searchBox) - fireEvent.change(searchBox, { target: { value: query } }) - fireEvent.blur(searchBox) - fireEvent.keyDown(searchBox, { key: 'Enter', keyCode: 13, metaKey: true }) - }) + const picker = await editor.renderedDOM.findByTestId(ComponentPickerTestId) + forceNotNull('the component picker must not be null', picker) + + await pressKey('Enter', { targetElement: picker }) } diff --git a/editor/src/uuiui/icn.tsx b/editor/src/uuiui/icn.tsx index bc44f2d1bac9..ac514a1932f0 100644 --- a/editor/src/uuiui/icn.tsx +++ b/editor/src/uuiui/icn.tsx @@ -82,6 +82,8 @@ function useIconColor(intent: IcnColor): IcnResultingColor { return 'lightgray' case 'on-light-main': return 'white' + case 'black': + return 'black' case 'remix': return 'aqua' case 'green': From 36c15d45c6487371abaf9925392c9d75575fe820 Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Mon, 3 Jun 2024 11:03:24 -0400 Subject: [PATCH 014/103] =?UTF-8?q?RIP=20weird=20castle=20=E2=9B=AB=20(#58?= =?UTF-8?q?09)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A modern home for the modern era | before | after | | ------------- | ------------- | | Screenshot 2024-05-31 at 4 03 13 PM | Screenshot 2024-06-03 at 10 26 47 AM | --- .../light/semantic/home-aqua-18x18@2x.png | Bin 0 -> 772 bytes .../light/semantic/home-black-18x18@2x.png | Bin 0 -> 767 bytes .../light/semantic/home-blue-18x18@2x.png | Bin 0 -> 759 bytes .../light/semantic/home-darkgray-18x18@2x.png | Bin 0 -> 762 bytes .../light/semantic/home-gray-18x18@2x.png | Bin 0 -> 736 bytes .../light/semantic/home-green-18x18@2x.png | Bin 0 -> 777 bytes .../semantic/home-lightaqua-18x18@2x.png | Bin 0 -> 757 bytes .../semantic/home-lightblue-18x18@2x.png | Bin 0 -> 736 bytes .../semantic/home-lightgray-18x18@2x.png | Bin 0 -> 745 bytes .../semantic/home-lightgreen-18x18@2x.png | Bin 0 -> 746 bytes .../semantic/home-lightpurple-18x18@2x.png | Bin 0 -> 745 bytes .../light/semantic/home-purple-18x18@2x.png | Bin 0 -> 754 bytes .../light/semantic/home-red-18x18@2x.png | Bin 0 -> 743 bytes .../semantic/home-solid-aqua-18x18@2x.png | Bin 0 -> 674 bytes .../semantic/home-solid-black-18x18@2x.png | Bin 0 -> 685 bytes .../semantic/home-solid-blue-18x18@2x.png | Bin 0 -> 677 bytes .../semantic/home-solid-darkgray-18x18@2x.png | Bin 0 -> 673 bytes .../semantic/home-solid-gray-18x18@2x.png | Bin 0 -> 657 bytes .../semantic/home-solid-green-18x18@2x.png | Bin 0 -> 685 bytes .../home-solid-lightaqua-18x18@2x.png | Bin 0 -> 676 bytes .../home-solid-lightblue-18x18@2x.png | Bin 0 -> 671 bytes .../home-solid-lightgray-18x18@2x.png | Bin 0 -> 676 bytes .../home-solid-lightgreen-18x18@2x.png | Bin 0 -> 673 bytes .../home-solid-lightpurple-18x18@2x.png | Bin 0 -> 675 bytes .../semantic/home-solid-purple-18x18@2x.png | Bin 0 -> 680 bytes .../semantic/home-solid-red-18x18@2x.png | Bin 0 -> 676 bytes .../semantic/home-solid-white-18x18@2x.png | Bin 0 -> 618 bytes .../light/semantic/home-white-18x18@2x.png | Bin 0 -> 685 bytes .../select-mode/remix-scene-label.tsx | 15 ------- .../remix/remix-rendering.spec.browser2.tsx | 8 ---- .../editor/remix-navigation-bar.tsx | 42 +++++++++++------- 31 files changed, 27 insertions(+), 38 deletions(-) create mode 100644 editor/resources/editor/icons/light/semantic/home-aqua-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-black-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-blue-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-darkgray-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-gray-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-green-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-lightaqua-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-lightblue-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-lightgray-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-lightgreen-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-lightpurple-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-purple-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-red-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-aqua-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-black-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-blue-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-darkgray-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-gray-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-green-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-lightaqua-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-lightblue-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-lightgray-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-lightgreen-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-lightpurple-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-purple-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-red-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-solid-white-18x18@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/home-white-18x18@2x.png diff --git a/editor/resources/editor/icons/light/semantic/home-aqua-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-aqua-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3146b098a78e3faea4651eb891601672b5cfe26e GIT binary patch literal 772 zcmV+f1N;1mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Gz{UO z0Jg>H14zGssDsNk@Hw5qB0JCm1D$M)v}{pw&?ZLf9s)IiM#mN<1MOm-?qBgS{lZoI z#}-u|bO^J`0jeIT4C4q@9aIJ5096fC2V;pcgCrOWRL~ekhzc6T2vBr%lX#?!nA^0) zKhj+f=p1wXUGn{q=dat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)pxK}~z&&RU$pn!9Ng;|7h~YhRh~!WD1=z;^^d#Fv9*^e4cBNFQS5&d6yym$3+Wy`W$OXdwo04ANW49b5*)EZT@$iJB{I5~T|(-W1c)lsf<+JH7?sczcp)2J$cA;>U!B+&c+1mD+ xG?Ly5VN3tg1NczHqMMGcKeAw(+vD*}$qA^X=3}X;`#b;u002ovPDHLkV1l%at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?KNqj&c5I6)#G6N# zCIu+1=Q<2DR032c#~GspPZx6tkyq$YrYLWKYB;KxqEfO7{g!zdEw}UPUD_TW#Fg?F zYLeNbl=2heWO|V5F4R>at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(iBjf<*G#j)NluXcW zK<{u!Hb^!|F5ELgm;mxyG7^g77~V67Nd6?t#?Q}uwq%q*6{Hj*LVqnoEW&70oHbky2zA>Rd7yvqXH|e|KHi z;QMSFuirb2DRjH4D#a4AB_jTd>dTUzBX7%@_l+1}r3)j|plr?4u|fOW^yPZ@h`~GY zSeW{VmFB|$M09Ko!4G1<+Myo&^h%x)3C%$eauI}FIFEgQkqyCZ>q^sO3gi|v5$g`& sNbl%5P20Bn2YCla-k7-qfxv9s0LUc9n=bJzUH||907*qoM6N<$g2xd}ga7~l literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-gray-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-gray-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..947e32b3bdf2662071a5b088ec0c8bc5a8b52bb8 GIT binary patch literal 736 zcmV<60w4W}P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?nxKHR$zWYz+G?dY#>4P@iK$W7qhl|@ zf}!~d(+#84Vow9A^Ub-Jm(WDxjT)S0q=xU&L2;lOEw!3GZ&nb-M&+JH)^8|TTE;a5 z5Hv#?FNh3RC^|{VMiR1N{q40K+m{C4Z9LyG&d?Ri(5Bdq)H|?a>zzm>X5#~xhTCw1 SEwdv40000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?HwgN&rrVyJNGiU{Hl2=J;U9ccL3?)6X@85rqB6@I$>^vU?_qzweea2oiygF?p2D ztE1|-WQx)THDUIdqO?FNOc$uuptcxOR4b4!#ssAVNik9s^@)+7sBereikcS~vkEgx zZ~cOb$^JbvHeh_@(Q>Xr<)2z$WXpqV2r|6=pf7Zs@%>QOS&%9VQl$!Ds$;00000NkvXX Hu0mjfbVO#k literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-lightaqua-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-lightaqua-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..39aa95f524393c549422df098d745e104a1b5ab3 GIT binary patch literal 757 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?cTOOyB;0lO43F#mm#Hk=k z1*C+e1Dg)$fCCb6f(Briu`t>L_Tt?&4{1NivbD31PrLSSAQFk(0O_2Edf^%vEcx?w z!K{})!xMrBDnN|PY-2(;exNTn;w)s!$o+jUGYTQ)BvT!e`R?d*$m8>pxrmfa=B!eu z%A7^2txTslS`N{;93MJE4sx}yPVA(-JFMp!nnnhCX;q5RPV-3cnq5rT7&*G8D zNvLk%V8P!~_&8Q;N^0A@cW@w`al$G?Sko3i(ljj#gnN-Ge<`vXh3r(0mN*HakEC3G zgCc*X%q)pWB2s#cFL0m-54evN0^=pr1yRUG6tZFc?5iL%Vc5|`ma!wWq;`iSM*q-+ nhT;bQM=CiiSm%yJA|0{=uOc8XjnBSG00000NkvXXu0mjfD9ljg literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-lightblue-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-lightblue-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7084001d978a8650482c11d8310cf74bde5122 GIT binary patch literal 736 zcmV<60w4W}P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?HY13J5asOmaZ-lN>ug9zTua#6TvK`2fO!$FZOTzTjkWjg;&ZX^ehv8X%!pQd*qTz7J4Uh$19a2q{(z4)mo^n zj903aP^yeaN)@uoSf!{>8H*J4Et4um4FOn_2}k}1V^oWFk@HiV)hEx8N$6ciky*;% z)0aUTGN8pZ{ahvJu#$-xi33l{a>XoOi&I@@&%gjShUM{!UHGF=zY+E#OEQg&Zy4}x zKL$9XW8C|puE|0gSx7@&_O&l|Duwhd68kh{h_FU87b%+;{kG6xHFhSG>5UszH@t7o S5b@*y0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NnC9RZ5s4Ih;U)u4lR?1nZPsW;8NjV8|GE+#678)y~ zl^P}FDx;BNg`_f4DKn>xM9R!9<0{oFRF-AK$rMGg4uW7~4b|A5V@_Wj$3`U7w-AG$ zG5G#x(18qaaYdJFp69DprpEq6S)_*FhjuKb?16v<2nfTFgy`;iBuSFmbC`h@b{qVa zOAw%Xe&D7rm>BhYXllF=hZo{tkNu~R+0c>apo)xZGjL=mLsuAv3gE3fhz0TvJX~y# b$1@vmdA$Bdvt`2b00000NkvXXu0mjf*lkWR literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-lightgreen-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-lightgreen-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0f6a87b7b5fcbda4011c0ddc17b9c26241655a5d GIT binary patch literal 746 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?+szc!B7Bn?s7D94Lwy*rUqSNc-t>mTTv>|Z%jk(7{*;`MMZ;#FsJJ_R1`?U%z>H= znu@WaCV^rx7L*9mVzek)5~D%U(wJD(2&iHSv*N>=!JD(8)=&Cu==mt28rqQxG&J#^ z_b(pv@c-=L9gx;lyat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?`e@fb9HukPsl3%bh{>ns0Q&2+a^|x8WxOD&6!k zf)N5KfEnelfrRqvj#hBy1|4Gt3KA>Q52O7>cSj~qLM%sW(?F| z&`?YiH3*c7iJ(l77vn|Ilo$_+rpBbAIzijDa12bn;kgXI{u#z-z8D`vj=uSl$OY=! zQC9F--tlm9XwM2*b6tO~@=1#p)5!fwS8=~F9^2at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}qdhkHCQv zmJ*-?D1ici5=aAN7)uH4L*9vJlEX^=q){R}wm$udV*`akVGo#|@MSCvK!B6kG2aqn z87tny3Bf@tP;E3<_n)+Y5pzPTGEBG%Qk{?|DN{n5G7lg06z}Kq9X0amIx$O9*+MCq z4zE;}kR~&PRBxfaGG3`(Lb);?DOJcSW0j&YWh_!OwoI$TgOe?R>kyS-~bjHL?Ory|91C9 z)oR!5NMs3La|-xwJ8d1z>gkVX;GP?vr8BU^)^(jNMk$RwQ*;TgNB#p`8j k!hlz097vzLP$-PXFFO~&+kXb}e*gdg07*qoM6N<$f-qN0vj6}9 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-red-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-red-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c9128af6c4d762d9e254a45f04b9f5d3f74d086b GIT binary patch literal 743 zcmV?P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?gt#6u((-z9$_`IGXHEuTN1RB;Ek;^31!R3?1+RBi@bvfny0! z8UAe$3{(QeQ*lAt=@?4X8G4lQLk=~(3RyCx%Fwe6ZD;dPo@ZhDf|w>#(L!}Hw|bjY zl#nFTg;Z;ywlY?!Rzk5d7Aa9kE2EX7K4mmg)VEBmRFjaGWVn+ret+K;?YYxUo7Klc zq!OxY=-uyx-+4{*+6+i>RYwPpbWq7~MlcS?#`*DoRap_T7tbej465&%M_S-Pc66@e zX*@V6FkU}shmJAdhq@*SNhBc&aoOK??0b%oxm@~7MADEUTA&%;0BQLm_j5b Z8z--6vT*kk?9~7O002ovPDHLkV1f|NM*IK( literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-aqua-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-aqua-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e13a354df58377aefcdf7788bf9c4885fc607b0b GIT binary patch literal 674 zcmV;T0$u%yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;}+p8i7}7PkVsYxA)h>jO}W#8e2_k* zC5Uma?2eZEyEh~tR|0Z1D9{njl`!U1ov1EwrL=3dBuSn11c(4wdFP%x%>V!Z07*qo IM6N<$f}eLH>;M1& literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-black-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-black-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1d833bd0b2f10efd0f51bdb17feeb861d2444ea2 GIT binary patch literal 685 zcmV;e0#f~nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? zih#3s4q5^0?7_qsV1H&Ikj$Hq2^!!Dzkno3D=5$NlUWd<1k8$}IMcY$a>%j_ZQE90 z!~z+N*1G(zE2Z{aR50it6AKjt8p6atd4p^iF3Jn!is7J~LB5z!loKcv6N0jWxENnl zG6%*7mCS{4MX8|;>D#0+VRc>i9(#j@wFM(O{cjpqnoqOdbzMrsd~8z$#sU$bYMQ3} z{f#d5j>Zvzu`U^%nHM6rxO+%IwghBrJs^6dZy3qE6zM&5@A>NiOSXMWk~C!>t&Mh0 T)*ZqJ00000NkvXXu0mjfr-Lf% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-blue-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-blue-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2954102c7460c18bc5dfd201aa9bf4fd1befe858 GIT binary patch literal 677 zcmV;W0$TlvP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?E)S!a$DVf!Z*Tq5MHE81PYkARi2PD0dJC1AmkoNP>YM$`0xR19y}e z3NhCL34OMkHGW%umv!6(va)hp59NQpzTe0!U`%zvF2GC(q6_x(q_!02 zOAuCICfu^%hK~EYGo&C}3bHjS&=KurFm(D_rQ!@*#yVTmwBC9FYs_3^!3?gZ00000 LNkvXXu0mjfQMMvx literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-darkgray-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-darkgray-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..737c31a03a5bb0a0bbaa3a43a1a419b6158a6348 GIT binary patch literal 673 zcmV;S0$%-zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?n0mro{il@7<)>b&Vt*(F=7u0uMr^Yw%?Co$m0x{N> z;g@+q=Kk&s2`H3+Lahgczw{0K4aS)J#JWddUCg^BNt&%UXIxlzat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%?wSchp54I4I)JP%&I9M&UmtPWeq9CB;ctfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?MNf-!>90`*|nC}ofYhJ{iBDPXiw(jX0t7D@`lz$l{z zK?X2ND0d=^G|HV2BZc}oI!3~@iJraLv&?iJcvbajk3_h&Z{&pa@tXk~LNgYKfby{` zlI~h?+AIZO56zgrjP5Yp-`yb#8p?u(nh%IT1^TNXUgyt6LEat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?dE`{gV`T`3}pmG9zcw& zJjaCWI->)Gi9uDECQu?!9Y%{v2E|}Bs3cGdMv96CNiY&r6i9tbpl(QduyeWq0000< KMNUMnLSTYKwat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?8_3WC%IX_e{<81J`(716Q3qg# z`y3;=2o9&xhtTn0b}PE{{DJuQTku(4%iaHbf6YzwfJ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-lightgray-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-lightgray-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b04c69c372696f7204c28e06b7ba4c6752e6e424 GIT binary patch literal 676 zcmV;V0$crwP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ra3W4Oj3E}6Wd7z{PG)-GTecx}xfdW|wBgoEse+);shA;y`FHHL} zpfPP-*LyHygMML90L20gVIV|hgHkXMpt3+Y7%)-EAPxo$R1!#nK_)5+DuF=;%1nhp zBFapOK?3UU)-e_)Hnw;#E8PmR9`v>cYwa!EIOi&wjOx~^Y=qq7%zwy8(Y(~(Ru<)%z`_^zD%?L0000< KMNUMnLSTa9#2*3x literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-lightgreen-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-lightgreen-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..00253e48b8a0d9e72db4d37b1708a16526dc5077 GIT binary patch literal 673 zcmV;S0$%-zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?YcK zAPPnEVh}`mM#oeb|K8$Rmb(>Xwf#^%_s_@h;b7JTHw@S{m`OqRhOB*G*t%-dU(6kt ziH?jwPh{@z?vR2)DJayEKy-n>)}Xt7{RMYJu;AXBrcKrh4WV0-zv#vu00000NkvXX Hu0mjfo)0R! literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-lightpurple-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-lightpurple-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ebb6614580b40bbd7b004fd17dda532771532e9 GIT binary patch literal 675 zcmV;U0$lxxP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2s&PzpwhiUvtA5TK$!8VnLqK~N4%3X1x| zAQDA=Vi1A)dv$b$39YTZ%W^k?uEu@s&Taht^~NaOcK8dngfJC|-BFvbsd}HQ_dIo| z1%#=#j0!xExxt+w1BEhBs8NB=Xs>bqq084S;fipfwJpo)tS1RFX$`$2dLjS-002ov JPDHLkV1gV*By9iy literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-purple-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-purple-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..84c30148b3e56f9809ce3fdefc08b72c6d20f06e GIT binary patch literal 680 zcmV;Z0$2TsP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$P=G?FYHHSGaB#!jBNHLRJ3xQE z*1IchkSIB*A%-PKB?Wn6SW;AUP+$y;j*1G3jA2nx!9j^JEI2ACC^LoyMR|h?#V~Ia z^%%oiqp0T?))>`xbZB%(H+{%H%Ssy|Pi@Cu5$^8cX)v}Ix71@K$_lb4{AGJ1{rRq% zn7Q4V3na>0GKB{U`@20PK|T`XGoT>C5$$RNoPH)$ID7sB`R5iwbmj%1+D{3VA$#Qj O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?bbpAY=n zTlmuwLdq$lD|+^KYsi8^EGT43L3Bhn|5K#Xk0H+p3XW}z8O#$6g-YK&2b5C)0000< KMNUMnLSTY?4kg_H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-solid-white-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-solid-white-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1fbe0a16342dce94303caff6a9506a29aa9ad688 GIT binary patch literal 618 zcmV-w0+s!VP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;@gh4RnL^ z1VNDKMRR8&+z*Esh<;!Y@I3DZ5z%`Z)DS}gEd`Wpg(-{Lz?4A=m}^mqm}^i6F}A3a z7#mb3Mi-@o(LpI=@=!(?5!LK~2!=IWZ2f`CdLplZ=fl&@_b;9>Uv*173vFcIH)Z42 zdviZo59O*mLk^O1kkqX}E%uv!ioeMEA9B*OJHq)$07*qoM6N<$ Ef@9ST6951J literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/home-white-18x18@2x.png b/editor/resources/editor/icons/light/semantic/home-white-18x18@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d4a073b416d5a958ceb11524dde34ebd5815b082 GIT binary patch literal 685 zcmV;e0#f~nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?V(NT#gRNT#w;MrtfG zn9ncek|`p^$z+xKRwj#-uS`;@xiU$lLS>>##gg%rQbYk`ANNYB#<6CD!)`Ej$G8yd zD;(pFmCkRx@?E0PJ*d54rh3E((props) => { 〱 - - - ⛫ - - {unless( diff --git a/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx b/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx index d5b8ad652ea1..ad74cb4475ee 100644 --- a/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx +++ b/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx @@ -1353,10 +1353,6 @@ describe('Remix navigation', () => { renderResult.renderedDOM.queryAllByText(AboutTextContent).filter(filterOutMenuLabels), ).toHaveLength(1) expect(getPathInRemixSceneLabel(renderResult, pathToRemixScene)).toEqual('/about') - - await navigateWithRemixSceneLabelButton(renderResult, pathToRemixScene, 'home') - expect(renderResult.renderedDOM.queryAllByText(RootTextContent)).toHaveLength(1) - expect(getPathInRemixSceneLabel(renderResult, pathToRemixScene)).toEqual(RemixIndexPathLabel) }) it('can navigate with the scene label nav buttons, in edit mode', async () => { @@ -1392,10 +1388,6 @@ describe('Remix navigation', () => { renderResult.renderedDOM.queryAllByText(AboutTextContent).filter(filterOutMenuLabels), ).toHaveLength(1) expect(getPathInRemixSceneLabel(renderResult, pathToRemixScene)).toEqual('/about') - - await navigateWithRemixSceneLabelButton(renderResult, pathToRemixScene, 'home') - expect(renderResult.renderedDOM.queryAllByText(RootTextContent)).toHaveLength(1) - expect(getPathInRemixSceneLabel(renderResult, pathToRemixScene)).toEqual(RemixIndexPathLabel) }) it('navigating in one Remix scene does not affect the navigation state in the other', async () => { diff --git a/editor/src/components/editor/remix-navigation-bar.tsx b/editor/src/components/editor/remix-navigation-bar.tsx index a92717f04e5e..51ec53b58993 100644 --- a/editor/src/components/editor/remix-navigation-bar.tsx +++ b/editor/src/components/editor/remix-navigation-bar.tsx @@ -2,13 +2,13 @@ /** @jsx jsx */ import { jsx } from '@emotion/react' import { useAtom } from 'jotai' -import React from 'react' +import React, { useState } from 'react' import { ActiveRemixSceneAtom, RemixNavigationAtom, } from '../canvas/remix/utopia-remix-root-component' import { Substores, useEditorState } from './store/store-hook' -import { FlexRow, StringInput, Tooltip, colorTheme } from '../../uuiui' +import { FlexRow, Icn, StringInput, Tooltip, colorTheme } from '../../uuiui' import { stopPropagation } from '../inspector/common/inspector-utils' import * as EP from '../../core/shared/element-path' import { getRemixLocationLabel, getRemixUrlFromLocation } from '../canvas/remix/remix-utils' @@ -28,6 +28,15 @@ export const RemixNavigationBarButtonTestId = (button: RemixSceneLabelButtonType `remix-navigation-bar-button-${button}` export const RemixNavigationBar = React.memo(() => { + const [isHovered, setIsHovered] = useState(false) + const setIsHoveredTrue = React.useCallback(() => { + setIsHovered(true) + }, []) + + const setIsHoveredFalse = React.useCallback(() => { + setIsHovered(false) + }, []) + const [navigationControls] = useAtom(RemixNavigationAtom) const [activeRemixScene] = useAtom(ActiveRemixSceneAtom) const routes = useEditorState( @@ -137,7 +146,7 @@ export const RemixNavigationBar = React.memo(() => { { { - - ⛫ - + +
Date: Mon, 3 Jun 2024 17:07:57 +0200 Subject: [PATCH 015/103] VariablesInScope Fix: for component arbitrary blocks, change insertionCeiling to rootElementPath (#5818) This is a preparation PR for #5815 **Problem:** The ComponentRendererComponent saves variables declared in its arbitrary block into `VariablesInScope`. However, the `insertionCeiling` is: 1. not guaranteed to be non-null, even though a null value would not be sensible here 2. points to the _element instance_ of the component instead of the component's root element. since the insertionCeiling is a ceiling above which insertion is not allowed, it must be the component's root element. **Commit Details:** (< vv pls delete this section if's not relevant) - Adding null check before pushing to VariablesInScope - Use `insertionCeiling: rootElementPath` - As @bkrmendy pointed out, it actually makes more sense to make insertionCeiling non-nullable, so I did that and fixed the fallout **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../canvas/scoped-variables.spec.tsx | 18 +++++++ .../ui-jsx-canvas-component-renderer.tsx | 24 +++++---- .../ui-jsx-canvas-element-renderer-utils.tsx | 10 ++-- .../src/components/canvas/ui-jsx-canvas.tsx | 2 +- .../model/element-metadata.spec.browser2.tsx | 52 ++++++++++++------- 5 files changed, 70 insertions(+), 36 deletions(-) diff --git a/editor/src/components/canvas/scoped-variables.spec.tsx b/editor/src/components/canvas/scoped-variables.spec.tsx index 6d62b55f9518..b2e40cdfaa09 100644 --- a/editor/src/components/canvas/scoped-variables.spec.tsx +++ b/editor/src/components/canvas/scoped-variables.spec.tsx @@ -230,6 +230,9 @@ describe('scoped variables', () => { "scene-1-entity", "app-entity", ], + Array [ + "8ba", + ], ], "type": "elementpath", }, @@ -247,6 +250,9 @@ describe('scoped variables', () => { "scene-1-entity", "app-entity", ], + Array [ + "8ba", + ], ], "type": "elementpath", }, @@ -283,6 +289,9 @@ describe('scoped variables', () => { "scene-1-entity", "app-entity", ], + Array [ + "8ba", + ], ], "type": "elementpath", }, @@ -334,6 +343,9 @@ describe('scoped variables', () => { "scene-1-entity", "app-entity", ], + Array [ + "af0", + ], ], "type": "elementpath", }, @@ -351,6 +363,9 @@ describe('scoped variables', () => { "scene-1-entity", "app-entity", ], + Array [ + "af0", + ], ], "type": "elementpath", }, @@ -368,6 +383,9 @@ describe('scoped variables', () => { "scene-1-entity", "app-entity", ], + Array [ + "af0", + ], ], "type": "elementpath", }, diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx index 945100fe72b2..77ac87ae5c79 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx @@ -173,7 +173,7 @@ export function createComponentRendererComponent(params: { } let spiedVariablesInScope: VariableData = {} - if (utopiaJsxComponent.param != null) { + if (rootElementPath != null && utopiaJsxComponent.param != null) { spiedVariablesInScope = mapArrayToDictionary( propertiesExposedByParam(utopiaJsxComponent.param), (paramName) => { @@ -182,7 +182,7 @@ export function createComponentRendererComponent(params: { (paramName) => { return { spiedValue: scope[paramName], - insertionCeiling: instancePath, + insertionCeiling: rootElementPath, } }, ) @@ -267,15 +267,17 @@ export function createComponentRendererComponent(params: { switch (arbitraryBlockResult.type) { case 'ARBITRARY_BLOCK_RAN_TO_END': - spiedVariablesInScope = { - ...spiedVariablesInScope, - ...objectMap( - (spiedValue) => ({ - spiedValue: spiedValue, - insertionCeiling: instancePath, - }), - arbitraryBlockResult.scope, - ), + if (rootElementPath != null) { + spiedVariablesInScope = { + ...spiedVariablesInScope, + ...objectMap( + (spiedValue) => ({ + spiedValue: spiedValue, + insertionCeiling: rootElementPath, + }), + arbitraryBlockResult.scope, + ), + } } break case 'EARLY_RETURN_VOID': diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx index 376ac12923a6..e23621d57f8c 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx @@ -137,10 +137,12 @@ export function createLookupRender( let innerVariablesInScope: VariableData = { ...context.variablesInScope, } - for (const valueInScope of valuesInScopeFromParameters) { - innerVariablesInScope[valueInScope] = { - spiedValue: scope[valueInScope], - insertionCeiling: innerPath, + if (innerPath != null) { + for (const valueInScope of valuesInScopeFromParameters) { + innerVariablesInScope[valueInScope] = { + spiedValue: scope[valueInScope], + insertionCeiling: innerPath, + } } } diff --git a/editor/src/components/canvas/ui-jsx-canvas.tsx b/editor/src/components/canvas/ui-jsx-canvas.tsx index e016cfa9105e..74fbf3f6f913 100644 --- a/editor/src/components/canvas/ui-jsx-canvas.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas.tsx @@ -103,7 +103,7 @@ export const ElementsToRerenderGLOBAL: { current: ElementsToRerender } = { export interface VariableMetadata { spiedValue: unknown - insertionCeiling: ElementPath | null + insertionCeiling: ElementPath } export interface VariableData { diff --git a/editor/src/core/model/element-metadata.spec.browser2.tsx b/editor/src/core/model/element-metadata.spec.browser2.tsx index 440d11bbdf41..8143dcb3356d 100644 --- a/editor/src/core/model/element-metadata.spec.browser2.tsx +++ b/editor/src/core/model/element-metadata.spec.browser2.tsx @@ -1400,52 +1400,64 @@ describe('record variable values', () => { const editor = await renderTestEditorWithCode(ProjectWithVariables, 'await-first-dom-report') const { variablesInScope } = editor.getEditorState().editor expect(variablesInScope['sb/scene/pg:root']).toEqual({ - definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg') }, + definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg:root') }, definedInsideObject: { spiedValue: { prop: [33], }, - insertionCeiling: EP.fromString('sb/scene/pg'), + insertionCeiling: EP.fromString('sb/scene/pg:root'), }, - definedInsideString: { spiedValue: 'hello', insertionCeiling: EP.fromString('sb/scene/pg') }, - functionResult: { spiedValue: 35, insertionCeiling: EP.fromString('sb/scene/pg') }, - style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg') }, + definedInsideString: { + spiedValue: 'hello', + insertionCeiling: EP.fromString('sb/scene/pg:root'), + }, + functionResult: { spiedValue: 35, insertionCeiling: EP.fromString('sb/scene/pg:root') }, + style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg:root') }, }) expect(variablesInScope['sb/scene/pg:root/111']).toEqual({ - definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg') }, + definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg:root') }, definedInsideObject: { spiedValue: { prop: [33], }, - insertionCeiling: EP.fromString('sb/scene/pg'), + insertionCeiling: EP.fromString('sb/scene/pg:root'), + }, + definedInsideString: { + spiedValue: 'hello', + insertionCeiling: EP.fromString('sb/scene/pg:root'), }, - definedInsideString: { spiedValue: 'hello', insertionCeiling: EP.fromString('sb/scene/pg') }, - functionResult: { spiedValue: 35, insertionCeiling: EP.fromString('sb/scene/pg') }, - style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg') }, + functionResult: { spiedValue: 35, insertionCeiling: EP.fromString('sb/scene/pg:root') }, + style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg:root') }, }) expect(variablesInScope['sb/scene/pg:root/222']).toEqual({ - definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg') }, + definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg:root') }, definedInsideObject: { spiedValue: { prop: [33], }, - insertionCeiling: EP.fromString('sb/scene/pg'), + insertionCeiling: EP.fromString('sb/scene/pg:root'), }, - definedInsideString: { spiedValue: 'hello', insertionCeiling: EP.fromString('sb/scene/pg') }, - functionResult: { spiedValue: 35, insertionCeiling: EP.fromString('sb/scene/pg') }, - style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg') }, + definedInsideString: { + spiedValue: 'hello', + insertionCeiling: EP.fromString('sb/scene/pg:root'), + }, + functionResult: { spiedValue: 35, insertionCeiling: EP.fromString('sb/scene/pg:root') }, + style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg:root') }, }) expect(variablesInScope['sb/scene/pg:root/333']).toEqual({ - definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg') }, + definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg:root') }, definedInsideObject: { spiedValue: { prop: [33], }, - insertionCeiling: EP.fromString('sb/scene/pg'), + insertionCeiling: EP.fromString('sb/scene/pg:root'), + }, + definedInsideString: { + spiedValue: 'hello', + insertionCeiling: EP.fromString('sb/scene/pg:root'), }, - definedInsideString: { spiedValue: 'hello', insertionCeiling: EP.fromString('sb/scene/pg') }, - functionResult: { spiedValue: 35, insertionCeiling: EP.fromString('sb/scene/pg') }, - style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg') }, + functionResult: { spiedValue: 35, insertionCeiling: EP.fromString('sb/scene/pg:root') }, + style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg:root') }, }) }) }) From dcf5d6cb49fd740c9918e085fd63ee0bcaca8e65 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:58:20 +0200 Subject: [PATCH 016/103] Data Picker: support scope slices (#5815) image image **Problem:** When picking data, if the data picker shows all the variables that are potentially in scope, it can be overwhelming, and hard to navigate. The classic devtools approach is to show scopes below each other in a tree-like structure, each scope toggleable to be visible or hidden. This approach clashes with the current design of the data picker, and it also felt too developery for our needs. **Solution** Show a breadcrumb-style row which lists the available scopes. By default, the innermost scope is activated because most of the time that is the most relevant scope to pick data from for the UI. The user can click around in the breadcrumb UI to check other scopes. **Details** - `lowestInsertionCeiling: ElementPath` added to `DataSelectorModalProps` - `insertionCeiling: ElementPath` to VariableOption - the `DataSelectorModal` organizes variables into scope buckets, and only shows one bucket at a time - I added @bkrmendy 's breadcrumb UI and related helper functions from #5802 **Follow Up Tasks:** - [ ] when opening the data picker for an existing value, we should pre-navigate to the correct scope - [ ] switching scopes makes the UI jump around -> we should make the data picker fixed size - [ ] The component scope is sometimes shown as Outlet, we should fix it to properly show the component's name. This limitation comes from the current navigator's labeling helper function --------- Co-authored-by: Berci Kormendy --- .../component-section/component-section.tsx | 4 + .../component-section/data-picker-utils.tsx | 104 ++++++++--- .../data-reference-cartouche.tsx | 1 + .../component-section/data-selector-modal.tsx | 169 ++++++++++++++++-- .../variables-in-scope-utils.spec.ts | 63 ++++++- .../variables-in-scope-utils.ts | 59 +++--- .../sections/data-reference-section.tsx | 1 + .../layout-section/list-source-cartouche.tsx | 1 + 8 files changed, 338 insertions(+), 64 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index 134baaec25b1..d452d1a379e2 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -342,6 +342,7 @@ export function useDataPickerButton( variablesInScope: DataPickerOption[], onPropertyPicked: DataPickerCallback, currentSelectedValuePath: ObjectPath | null, + lowestInsertionCeiling: ElementPath | null, ) { const [referenceElement, setReferenceElement] = React.useState(null) const [popperElement, setPopperElement] = React.useState(null) @@ -377,6 +378,7 @@ export function useDataPickerButton( onPropertyPicked={onPropertyPicked} variablesInScope={variablesInScope} startingSelectedValuePath={currentSelectedValuePath} + lowestInsertionCeiling={lowestInsertionCeiling} /> ), [ @@ -386,6 +388,7 @@ export function useDataPickerButton( popper.attributes.popper, popper.styles.popper, variablesInScope, + lowestInsertionCeiling, ], ) @@ -472,6 +475,7 @@ function useDataPickerButtonInComponentSection( variableNamesInScope, (e) => optionalMap(dispatch, setPropertyFromDataPickerActions(selectedViews, propertyPath, e)), pathToCurrentValue, + selectedViews.at(0) ?? null, ) return dataPickerButtonData diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index dcdf4efac24a..3b543b5331fe 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -1,50 +1,48 @@ import { atom } from 'jotai' +import { processJSPropertyAccessors } from '../../../../core/data-tracing/data-tracing' +import { MetadataUtils } from '../../../../core/model/element-metadata-utils' +import { foldEither } from '../../../../core/shared/either' +import * as EP from '../../../../core/shared/element-path' +import type { ElementPathTrees } from '../../../../core/shared/element-path-tree' +import type { ElementInstanceMetadataMap } from '../../../../core/shared/element-template' import { isJSExpression, type JSExpressionOtherJavaScript, type JSXElementChild, } from '../../../../core/shared/element-template' +import type { ElementPath } from '../../../../core/shared/project-file-types' import { assertNever } from '../../../../core/shared/utils' +import type { AllElementProps } from '../../../editor/store/editor-state' import type { ArrayInfo, JSXInfo, ObjectInfo, PrimitiveInfo } from './variables-in-scope-utils' -import { processJSPropertyAccessors } from '../../../../core/data-tracing/data-tracing' -import { foldEither } from '../../../../core/shared/either' -export interface PrimitiveOption { - type: 'primitive' - variableInfo: PrimitiveInfo - definedElsewhere: string +interface VariableOptionBase { depth: number + definedElsewhere: string valuePath: Array disabled: boolean + insertionCeiling: ElementPath | null } -export interface ArrayOption { +export interface PrimitiveOption extends VariableOptionBase { + type: 'primitive' + variableInfo: PrimitiveInfo +} + +export interface ArrayOption extends VariableOptionBase { type: 'array' variableInfo: ArrayInfo - depth: number - definedElsewhere: string children: Array - valuePath: Array - disabled: boolean } -export interface ObjectOption { +export interface ObjectOption extends VariableOptionBase { type: 'object' variableInfo: ObjectInfo - depth: number - definedElsewhere: string children: Array - valuePath: Array - disabled: boolean } -export interface JSXOption { +export interface JSXOption extends VariableOptionBase { type: 'jsx' variableInfo: JSXInfo - definedElsewhere: string - depth: number - valuePath: Array - disabled: boolean } export type DataPickerOption = PrimitiveOption | ArrayOption | ObjectOption | JSXOption @@ -78,3 +76,67 @@ export function jsxElementChildToValuePath(child: JSXElementChild | null): Objec processJSPropertyAccessors(child), ) } + +export function getEnclosingScopes( + metadata: ElementInstanceMetadataMap, + allElementProps: AllElementProps, + elementPathTree: ElementPathTrees, + buckets: Array, + lowestInsertionCeiling: ElementPath, +): Array<{ + insertionCeiling: ElementPath + label: string + hasContent: boolean +}> { + let result: Array<{ + insertionCeiling: ElementPath + label: string + hasContent: boolean + }> = [] + const pathsToCheck = [...EP.allPathsInsideComponent(lowestInsertionCeiling)] + for (const current of pathsToCheck) { + const parentOfCurrent = EP.parentPath(current) + + // we add maps and components even if they don't have content in scope, for the sake of breadcrumb readability + if ( + MetadataUtils.isJSXMapExpression(parentOfCurrent, metadata) || + EP.isRootElementOfInstance(current) + ) { + result.unshift({ + insertionCeiling: current, + label: MetadataUtils.getElementLabel( + allElementProps, + parentOfCurrent, + elementPathTree, + metadata, + ), + hasContent: buckets.includes(current), + }) + continue + } + + // we also add anything that has content in scope even if it's not a component or map + if (buckets.includes(current)) { + result.unshift({ + insertionCeiling: current, + label: MetadataUtils.getElementLabel( + allElementProps, + parentOfCurrent, + elementPathTree, + metadata, + ), + hasContent: true, + }) + continue + } + } + + // Add file root + result.unshift({ + insertionCeiling: EP.emptyElementPath, + label: 'File', + hasContent: buckets.includes(EP.emptyElementPath), + }) + + return result +} diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index c779baa8ac8a..43bbd7d84c4a 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -111,6 +111,7 @@ export const DataReferenceCartoucheControl = React.memo( variableNamesInScope, updateDataWithDataPicker, pathToCurrenlySelectedValue, + elementPath, ) const isDataComingFromHookResult = dataTraceResult.type === 'hook-result' diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index abb14088fde5..70d310c3aed1 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { isPrefixOf, last } from '../../../../core/shared/array-utils' +import { groupBy, isPrefixOf, last } from '../../../../core/shared/array-utils' import { jsExpressionOtherJavaScriptSimple } from '../../../../core/shared/element-template' import { CanvasContextMenuPortalTargetID, @@ -21,15 +21,21 @@ import type { SelectOption } from '../../controls/select-control' import { InspectorModal } from '../../widgets/inspector-modal' import type { CartoucheUIProps, HoverHandlers } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' -import type { - ArrayOption, - DataPickerCallback, - JSXOption, - ObjectOption, - PrimitiveOption, - DataPickerOption, - ObjectPath, +import { + type ArrayOption, + type DataPickerCallback, + type JSXOption, + type ObjectOption, + type PrimitiveOption, + type DataPickerOption, + type ObjectPath, + getEnclosingScopes, } from './data-picker-utils' +import type { ElementPath } from '../../../../core/shared/project-file-types' +import * as EP from '../../../../core/shared/element-path' +import { Substores, useEditorState } from '../../../editor/store/store-hook' +import { MetadataUtils } from '../../../../core/model/element-metadata-utils' +import { optionalMap } from '../../../../core/shared/optional-utils' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -39,6 +45,7 @@ export interface DataSelectorModalProps { variablesInScope: DataPickerOption[] onPropertyPicked: DataPickerCallback startingSelectedValuePath: ObjectPath | null + lowestInsertionCeiling: ElementPath | null } const Separator = React.memo( @@ -114,11 +121,65 @@ interface ArrayIndexLookup { export const DataSelectorModal = React.memo( React.forwardRef( ( - { style, closePopup, variablesInScope, onPropertyPicked, startingSelectedValuePath }, + { + style, + closePopup, + variablesInScope: allVariablesInScope, + onPropertyPicked, + startingSelectedValuePath, + lowestInsertionCeiling, + }, forwardedRef, ) => { const colorTheme = useColorTheme() + const scopeBuckets = React.useMemo( + () => putVariablesIntoScopeBuckets(allVariablesInScope), + [allVariablesInScope], + ) + + const scopeBucketPaths = Object.keys(scopeBuckets).map((k) => EP.fromString(k)) + + const lowestMatchingScope = React.useMemo(() => { + if (lowestInsertionCeiling == null) { + return null + } + const matchingScope = findClosestMatchingScope(lowestInsertionCeiling, scopeBuckets) + return matchingScope ?? lowestInsertionCeiling + }, [scopeBuckets, lowestInsertionCeiling]) + + const [selectedScope, setSelectedScope] = React.useState( + lowestMatchingScope, + ) + const setSelectedScopeCurried = React.useCallback( + (name: ElementPath) => () => setSelectedScope(name), + [], + ) + + const { filteredVariablesInScope } = useFilterVariablesInScope( + allVariablesInScope, + scopeBuckets, + selectedScope, + ) + + const elementLabelsWithScopes = useEditorState( + Substores.fullStore, + (store) => { + const scopes = getEnclosingScopes( + store.editor.jsxMetadata, + store.editor.allElementProps, + store.editor.elementPathTree, + scopeBucketPaths, + lowestInsertionCeiling ?? EP.emptyElementPath, + ) + return scopes.map(({ insertionCeiling, label, hasContent }) => ({ + label: label, + scope: insertionCeiling, + })) + }, + 'DataSelectorModal elementLabelsWithScopes', + ) + const [navigatedToPath, setNavigatedToPath] = React.useState([]) const [selectedPath, setSelectedPath] = React.useState( @@ -170,22 +231,22 @@ export const DataSelectorModal = React.memo( [], ) - const processedVariablesInScope = useProcessVariablesInScope(variablesInScope) + const processedVariablesInScope = useProcessVariablesInScope(filteredVariablesInScope) const focusedVariableChildren = React.useMemo(() => { if (navigatedToPath.length === 0) { - return variablesInScope + return filteredVariablesInScope } - const scopeToShow = processedVariablesInScope[navigatedToPath.toString()] + const innerScopeToShow = processedVariablesInScope[navigatedToPath.toString()] if ( - scopeToShow == null || - (scopeToShow.type !== 'array' && scopeToShow.type !== 'object') + innerScopeToShow == null || + (innerScopeToShow.type !== 'array' && innerScopeToShow.type !== 'object') ) { return [] // TODO this should never happen! } - return scopeToShow.children - }, [navigatedToPath, processedVariablesInScope, variablesInScope]) + return innerScopeToShow.children + }, [navigatedToPath, processedVariablesInScope, filteredVariablesInScope]) const { primitiveVars, folderVars } = React.useMemo(() => { let primitives: Array = [] @@ -356,6 +417,28 @@ export const DataSelectorModal = React.memo( > {valuePreviewText} + + {elementLabelsWithScopes.map(({ label, scope }, idx, a) => ( + +
+ {label} +
+ {idx < a.length - 1 ? ( + {'/'} + ) : null} +
+ ))} +
{/* detail view */}
+} + +function findClosestMatchingScope( + targetScope: ElementPath, + scopeBuckets: ScopeBuckets, +): ElementPath | null { + const allPaths = EP.allPathsInsideComponent(targetScope) + for (const path of allPaths) { + if (scopeBuckets[EP.toString(path)] != null) { + return path + } + } + + return null +} + +function putVariablesIntoScopeBuckets(options: DataPickerOption[]): ScopeBuckets { + const buckets: { [insertionCeiling: string]: Array } = groupBy( + (o) => optionalMap(EP.toString, o.insertionCeiling) ?? '', // '' represents "file root scope", TODO make it clearer + options, + ) + + return buckets +} + +function useFilterVariablesInScope( + options: DataPickerOption[], + scopeBuckets: ScopeBuckets, + scopeToShow: ElementPath | null | 'do-not-filter', +): { + filteredVariablesInScope: Array +} { + const filteredOptions = React.useMemo(() => { + if (scopeToShow === 'do-not-filter' || scopeToShow == null) { + return options + } + + const matchingScope = findClosestMatchingScope(scopeToShow, scopeBuckets) + return matchingScope == null ? [] : scopeBuckets[EP.toString(matchingScope)] + }, [scopeBuckets, options, scopeToShow]) + + return { + filteredVariablesInScope: filteredOptions, + } +} + function useProcessVariablesInScope(options: DataPickerOption[]): ProcessedVariablesInScope { return React.useMemo(() => { let lookup: ProcessedVariablesInScope = {} @@ -543,6 +674,10 @@ export function pathBreadcrumbs( current.push(segment) const optionFromLookup = processedVariablesInScope[current.toString()] + if (optionFromLookup == null) { + continue + } + accumulator.push({ segment: segment, path: [...current], diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts index a6b5809db91f..a037958e31b1 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts @@ -1,3 +1,4 @@ +import * as EP from '../../../../core/shared/element-path' import { maybeToArray } from '../../../../core/shared/optional-utils' import type { ControlDescription } from '../../../custom-code/internal-property-controls' import type { PropertyValue, VariableInfo } from './variables-in-scope-utils' @@ -6,7 +7,12 @@ import { orderVariablesForRelevance, variableInfoFromValue } from './variables-i describe('orderVariablesForRelevance', () => { it('should be able to target a given property', () => { const variableNamesInScope: Array = maybeToArray( - variableInfoFromValue('style', 'style', { left: 300, position: 'relative' }), + variableInfoFromValue( + 'style', + 'style', + { left: 300, position: 'relative' }, + EP.fromString('aaa'), + ), ) const controlDescription: ControlDescription = { control: 'object', @@ -35,11 +41,27 @@ describe('orderVariablesForRelevance', () => { Object { "expression": "style", "expressionPathPart": "style", + "insertionCeiling": Object { + "parts": Array [ + Array [ + "aaa", + ], + ], + "type": "elementpath", + }, "matches": false, "props": Array [ Object { "expression": "style['left']", "expressionPathPart": "left", + "insertionCeiling": Object { + "parts": Array [ + Array [ + "aaa", + ], + ], + "type": "elementpath", + }, "matches": true, "type": "primitive", "value": 300, @@ -47,6 +69,14 @@ describe('orderVariablesForRelevance', () => { Object { "expression": "style['position']", "expressionPathPart": "position", + "insertionCeiling": Object { + "parts": Array [ + Array [ + "aaa", + ], + ], + "type": "elementpath", + }, "matches": false, "type": "primitive", "value": "relative", @@ -63,7 +93,12 @@ describe('orderVariablesForRelevance', () => { }) it('handles the case when not targeting a specific property', () => { const variableNamesInScope: Array = maybeToArray( - variableInfoFromValue('style', 'style', { left: 300, position: 'relative' }), + variableInfoFromValue( + 'style', + 'style', + { left: 300, position: 'relative' }, + EP.fromString('aaa'), + ), ) const controlDescription: ControlDescription = { control: 'object', @@ -92,11 +127,27 @@ describe('orderVariablesForRelevance', () => { Object { "expression": "style", "expressionPathPart": "style", + "insertionCeiling": Object { + "parts": Array [ + Array [ + "aaa", + ], + ], + "type": "elementpath", + }, "matches": true, "props": Array [ Object { "expression": "style['left']", "expressionPathPart": "left", + "insertionCeiling": Object { + "parts": Array [ + Array [ + "aaa", + ], + ], + "type": "elementpath", + }, "matches": false, "type": "primitive", "value": 300, @@ -104,6 +155,14 @@ describe('orderVariablesForRelevance', () => { Object { "expression": "style['position']", "expressionPathPart": "position", + "insertionCeiling": Object { + "parts": Array [ + Array [ + "aaa", + ], + ], + "type": "elementpath", + }, "matches": false, "type": "primitive", "value": "relative", diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index c71684987eb9..491cecf515f6 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -18,6 +18,7 @@ import { MetadataUtils } from '../../../../core/model/element-metadata-utils' function valuesFromObject( variable: ArrayInfo | ObjectInfo, + insertionCeiling: ElementPath | null, depth: number, originalObjectName: string, valuePath: Array, @@ -32,11 +33,15 @@ function valuesFromObject( { type: 'array', variableInfo: variable, + insertionCeiling: insertionCeiling, depth: depth, definedElsewhere: originalObjectName, children: variable.elements .flatMap((e, index) => - valuesFromVariable(e, depth + 1, originalObjectName, [...valuePath, index]), + valuesFromVariable(e, insertionCeiling, depth + 1, originalObjectName, [ + ...valuePath, + index, + ]), ) .map(patchDefinedElsewhereInfo), valuePath: valuePath, @@ -48,11 +53,12 @@ function valuesFromObject( { type: 'object', variableInfo: variable, + insertionCeiling: insertionCeiling, depth: depth, definedElsewhere: originalObjectName, children: variable.props .flatMap((e) => - valuesFromVariable(e, depth + 1, originalObjectName, [ + valuesFromVariable(e, insertionCeiling, depth + 1, originalObjectName, [ ...valuePath, e.expressionPathPart, ]), @@ -69,6 +75,7 @@ function valuesFromObject( function valuesFromVariable( variable: VariableInfo, + insertionCeiling: ElementPath | null, depth: number, originalObjectName: string, valuePath: Array, @@ -79,6 +86,7 @@ function valuesFromVariable( { type: 'primitive', variableInfo: variable, + insertionCeiling: insertionCeiling, definedElsewhere: originalObjectName, depth: depth, valuePath: valuePath, @@ -87,12 +95,13 @@ function valuesFromVariable( ] case 'array': case 'object': - return valuesFromObject(variable, depth, originalObjectName, valuePath) + return valuesFromObject(variable, insertionCeiling, depth, originalObjectName, valuePath) case 'jsx': return [ { type: 'jsx', variableInfo: variable, + insertionCeiling: insertionCeiling, definedElsewhere: originalObjectName, depth: depth, valuePath: valuePath, @@ -122,38 +131,31 @@ function usePropertyControlDescriptions( return controlForProp[0] ?? null } -export interface PrimitiveInfo { - type: 'primitive' +interface VariableInfoBase { + type: string expression: string expressionPathPart: string | number value: unknown + insertionCeiling: ElementPath matches: boolean } -export interface ObjectInfo { +export interface PrimitiveInfo extends VariableInfoBase { + type: 'primitive' +} + +export interface ObjectInfo extends VariableInfoBase { type: 'object' - expression: string - expressionPathPart: string | number - value: unknown props: Array - matches: boolean } -export interface ArrayInfo { +export interface ArrayInfo extends VariableInfoBase { type: 'array' - expression: string - expressionPathPart: string | number - value: unknown elements: Array - matches: boolean } -export interface JSXInfo { +export interface JSXInfo extends VariableInfoBase { type: 'jsx' - expression: string - expressionPathPart: string | number - value: unknown - matches: boolean } export type VariableInfo = PrimitiveInfo | ArrayInfo | ObjectInfo | JSXInfo @@ -162,6 +164,7 @@ export function variableInfoFromValue( expression: string, expressionPathPart: string | number, value: unknown, + insertionCeiling: ElementPath, ): VariableInfo | null { switch (typeof value) { case 'function': @@ -177,6 +180,7 @@ export function variableInfoFromValue( expression: expression, expressionPathPart: expressionPathPart, value: value, + insertionCeiling: insertionCeiling, matches: false, } case 'object': @@ -186,6 +190,7 @@ export function variableInfoFromValue( expression: expression, expressionPathPart: expressionPathPart, value: value, + insertionCeiling: insertionCeiling, matches: false, } } @@ -195,9 +200,10 @@ export function variableInfoFromValue( expression: expression, expressionPathPart: expressionPathPart, value: value, + insertionCeiling: insertionCeiling, matches: false, elements: mapDropNulls( - (e, idx) => variableInfoFromValue(`${expression}[${idx}]`, idx, e), + (e, idx) => variableInfoFromValue(`${expression}[${idx}]`, idx, e, insertionCeiling), value, ), } @@ -208,6 +214,7 @@ export function variableInfoFromValue( expression: expression, expressionPathPart: expressionPathPart, value: value, + insertionCeiling: insertionCeiling, matches: false, } } @@ -216,9 +223,10 @@ export function variableInfoFromValue( expression: expression, expressionPathPart: expressionPathPart, value: value, + insertionCeiling: insertionCeiling, matches: false, props: mapDropNulls(([key, propValue]) => { - return variableInfoFromValue(`${expression}['${key}']`, key, propValue) + return variableInfoFromValue(`${expression}['${key}']`, key, propValue, insertionCeiling) }, Object.entries(value)), } } @@ -226,7 +234,8 @@ export function variableInfoFromValue( function variableInfoFromVariableData(variableNamesInScope: VariableData): Array { const info = mapDropNulls( - ([key, { spiedValue }]) => variableInfoFromValue(key, key, spiedValue), + ([key, { spiedValue, insertionCeiling }]) => + variableInfoFromValue(key, key, spiedValue, insertionCeiling), Object.entries(variableNamesInScope), ) @@ -442,7 +451,9 @@ export function useVariablesInScopeForSelectedElement( ) return orderedVariablesInScope.flatMap((variable) => - valuesFromVariable(variable, 0, variable.expression, [variable.expressionPathPart]), + valuesFromVariable(variable, variable.insertionCeiling, 0, variable.expression, [ + variable.expressionPathPart, + ]), ) }, [controlDescriptions, currentPropertyValue, mode, elementPath, variablesInScope, propertyPath]) diff --git a/editor/src/components/inspector/sections/data-reference-section.tsx b/editor/src/components/inspector/sections/data-reference-section.tsx index b693b63d2a8d..30addcc58a4c 100644 --- a/editor/src/components/inspector/sections/data-reference-section.tsx +++ b/editor/src/components/inspector/sections/data-reference-section.tsx @@ -103,6 +103,7 @@ export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[ ]) }, pathToCurrenlySelectedValue, + elementPathForDataPicker, ) const openPicker = React.useCallback( diff --git a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx index 9b8c9768ac55..119667466f39 100644 --- a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx @@ -116,6 +116,7 @@ export const MapListSourceCartouche = React.memo((props: MapListSourceCartoucheP filteredVariableNamesInScope, onPickMappedElement, pathToMappedExpression, + target, ) const onClick = React.useCallback(() => { From a3aab0b361d7cb536b0c1d7304406a56b271738d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Tue, 4 Jun 2024 11:41:34 +0200 Subject: [PATCH 017/103] Trace variables from the data picker (#5816) https://github.com/concrete-utopia/utopia/issues/5814 image ## Description This PR adds data tracing to the data picker. With data tracing, variables that come from a hook call are shown with the appropriate (green) tinted cartouche (see the screenshot above). ### Commit Details - a new data tracing entry point is added (`traceDataFromVariableName`) - the variable picker calls `traceDataFromVariableName` to pass the appropriate value for the `source` prop for `CartoucheUI` ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/data-selector-modal.tsx | 53 +++++++++++- .../core/data-tracing/data-tracing.spec.ts | 82 +++++++++++++++++++ editor/src/core/data-tracing/data-tracing.ts | 35 +++++++- 3 files changed, 163 insertions(+), 7 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 70d310c3aed1..dd4888e9fcaa 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -31,10 +31,13 @@ import { type ObjectPath, getEnclosingScopes, } from './data-picker-utils' +import { + dataPathSuccess, + traceDataFromVariableName, +} from '../../../../core/data-tracing/data-tracing' import type { ElementPath } from '../../../../core/shared/project-file-types' import * as EP from '../../../../core/shared/element-path' import { Substores, useEditorState } from '../../../editor/store/store-hook' -import { MetadataUtils } from '../../../../core/model/element-metadata-utils' import { optionalMap } from '../../../../core/shared/optional-utils' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -270,6 +273,48 @@ export const DataSelectorModal = React.memo( return { primitiveVars: primitives, folderVars: folders } }, [focusedVariableChildren]) + const metadata = useEditorState( + Substores.metadata, + (store) => store.editor.jsxMetadata, + 'DataSelectorModal metadata', + ) + const projectContents = useEditorState( + Substores.projectContents, + (store) => store.editor.projectContents, + 'DataSelectorModal projectContents', + ) + + const variableSources = React.useMemo(() => { + let result: { [valuePath: string]: CartoucheUIProps['source'] } = {} + for (const variable of focusedVariableChildren) { + const container = variable.variableInfo.insertionCeiling + const trace = traceDataFromVariableName( + container, + variable.variableInfo.expression, + metadata, + projectContents, + dataPathSuccess([]), + ) + + switch (trace.type) { + case 'hook-result': + result[variable.valuePath.toString()] = 'external' + break + case 'literal-attribute': + result[variable.valuePath.toString()] = 'literal' + break + case 'component-prop': + case 'element-at-scope': + case 'failed': + result[variable.valuePath.toString()] = 'internal' + break + default: + assertNever(trace) + } + } + return result + }, [focusedVariableChildren, metadata, projectContents]) + const setCurrentSelectedPathCurried = React.useCallback( (path: DataPickerOption['valuePath']) => () => { if (!isPrefixOf(navigatedToPath, path)) { @@ -465,7 +510,7 @@ export const DataSelectorModal = React.memo( { @@ -1174,6 +1175,87 @@ describe('Data Tracing', () => { ) }) }) + + describe('Tracing data from the arbitrary js block of a component', () => { + it('can trace data from the arbitrary js block', async () => { + const editor = await renderTestEditorWithCode( + makeTestProjectCodeWithStoryboard(` + function MyComponent({ doc }) { + return

{doc.title.value}

+ } + + function useLoaderData() { + return { very: { deep: { title: {value: ['hello', 'world'] } }, a: [1, 2] } } + } + + function App() { + const { very } = useLoaderData() + const { deep, a } = very + const deepButWithAccess = very.deep + + const [helloFromDestructuredArray] = a + + return + } + `), + 'await-first-dom-report', + ) + + await focusOnComponentForTest(editor, EP.fromString('sb/app:my-component')) + + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component'), + 'deep', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToAHookCall( + EP.fromString('sb/app:my-component'), + 'useLoaderData', + dataPathSuccess(['very', 'deep']), + ), + ) + } + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component'), + 'deepButWithAccess', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToAHookCall( + EP.fromString('sb/app:my-component'), + 'useLoaderData', + dataPathSuccess(['very', 'deep']), + ), + ) + } + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component'), + 'helloFromDestructuredArray', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToAHookCall( + EP.fromString('sb/app:my-component'), + 'useLoaderData', + dataPathSuccess(['very', 'a', '0', 'helloFromDestructuredArray']), + ), + ) + } + }) + }) }) function makeTestProjectCodeWithStoryboard(codeForComponents: string): string { diff --git a/editor/src/core/data-tracing/data-tracing.ts b/editor/src/core/data-tracing/data-tracing.ts index 5bd44f51a24c..cdd420c54886 100644 --- a/editor/src/core/data-tracing/data-tracing.ts +++ b/editor/src/core/data-tracing/data-tracing.ts @@ -1,4 +1,5 @@ import type { ProjectContentTreeRoot } from '../../components/assets' +import { findUnderlyingTargetComponentImplementationFromImportInfo } from '../../components/custom-code/code-file' import { withUnderlyingTarget } from '../../components/editor/store/editor-state' import * as TPP from '../../components/template-property-path' import { MetadataUtils } from '../model/element-metadata-utils' @@ -18,16 +19,16 @@ import type { UtopiaJSXComponent, } from '../shared/element-template' import { - emptyComments, isJSXElement, - jsIdentifier, type ElementInstanceMetadataMap, isRegularParam, isJSAssignmentStatement, isJSIdentifier, + jsIdentifier, + emptyComments, } from '../shared/element-template' import { getJSXAttributesAtPath, jsxSimpleAttributeToValue } from '../shared/jsx-attribute-utils' -import { forceNotNull, optionalMap } from '../shared/optional-utils' +import { optionalMap } from '../shared/optional-utils' import type { ElementPath, ElementPropertyPath, PropertyPath } from '../shared/project-file-types' import * as PP from '../shared/property-path' import { assertNever } from '../shared/utils' @@ -406,6 +407,34 @@ export function traceDataFromElement( } } +export function traceDataFromVariableName( + enclosingScope: ElementPath, + variableName: string, + metadata: ElementInstanceMetadataMap, + projectContents: ProjectContentTreeRoot, + pathDrillSoFar: DataPathPositiveResult, +): DataTracingResult { + const componentHoldingElement = findContainingComponentForElementPath( + enclosingScope, + projectContents, + ) + + if (componentHoldingElement == null || componentHoldingElement.arbitraryJSBlock == null) { + return dataTracingFailed('Could not find containing component') + } + + return walkUpInnerScopesUntilReachingComponent( + metadata, + projectContents, + enclosingScope, + enclosingScope, + enclosingScope, + componentHoldingElement, + jsIdentifier(variableName, '', null, emptyComments), + pathDrillSoFar, + ) +} + function traceDataFromIdentifierOrAccess( startFromElement: IdentifierOrAccess, enclosingScope: ElementPath, From 5af55cc52c463f1c2152de6efbbee63e7ea3eacc Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:04:19 +0200 Subject: [PATCH 018/103] Chore: remove old insert menu (#5819) The legacy `InsertMenu` component is not used anymore, so this PR removes it and some related helpers. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5444 --- ...g-to-insert-metastrategy.spec.browser2.tsx | 960 ----- .../drag-to-insert-metastrategy.tsx | 4 + .../draw-to-insert-metastrategy.tsx | 8 + .../draw-to-insert-strategy.spec.browser2.tsx | 3154 +---------------- .../components/canvas/design-panel-root.tsx | 2 - .../editor/insertmenu.spec.browser2.tsx | 1 - editor/src/components/editor/insertmenu.tsx | 727 ---- .../components/navigator/insert-menu-pane.tsx | 62 - editor/src/templates/editor-canvas.tsx | 18 +- 9 files changed, 26 insertions(+), 4910 deletions(-) delete mode 100644 editor/src/components/canvas/canvas-strategies/strategies/drag-to-insert-metastrategy.spec.browser2.tsx delete mode 100644 editor/src/components/editor/insertmenu.tsx delete mode 100644 editor/src/components/navigator/insert-menu-pane.tsx diff --git a/editor/src/components/canvas/canvas-strategies/strategies/drag-to-insert-metastrategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/drag-to-insert-metastrategy.spec.browser2.tsx deleted file mode 100644 index b37938937002..000000000000 --- a/editor/src/components/canvas/canvas-strategies/strategies/drag-to-insert-metastrategy.spec.browser2.tsx +++ /dev/null @@ -1,960 +0,0 @@ -import { - FOR_TESTS_setNextGeneratedUid, - FOR_TESTS_setNextGeneratedUids, -} from '../../../../core/model/element-template-utils.test-utils' -import type { Modifiers } from '../../../../utils/modifiers' -import { emptyModifiers } from '../../../../utils/modifiers' -import { - expectSingleUndo2Saves, - slightlyOffsetPointBecauseVeryWeirdIssue, -} from '../../../../utils/utils.test-utils' -import { setRightMenuTab } from '../../../editor/actions/action-creators' -import { RightMenuTab, navigatorEntryToKey } from '../../../editor/store/editor-state' -import { CanvasControlsContainerID } from '../../controls/new-canvas-controls' -import { DragOutlineControlTestId } from '../../controls/select-mode/drag-outline-control' -import { - mouseDownAtPoint, - mouseMoveToPoint, - mouseUpAtPoint, - pressKey, -} from '../../event-helpers.test-utils' -import type { EditorRenderResult } from '../../ui-jsx.test-utils' -import { - getPrintedUiJsCode, - makeTestProjectCodeWithSnippet, - renderTestEditorWithCode, -} from '../../ui-jsx.test-utils' - -// FIXME These tests will probably start to fail if the insert menu becomes too long, at which point we may -// have to insert some mocking to restrict the available items there - -async function setupInsertTest(inputCode: string): Promise { - const renderResult = await renderTestEditorWithCode(inputCode, 'await-first-dom-report') - await renderResult.dispatch([setRightMenuTab(RightMenuTab.Insert)], false) - - const newUID = 'ddd' - FOR_TESTS_setNextGeneratedUid(newUID) - - return renderResult -} - -async function startDraggingFromInsertMenuDivButtonToPoint( - targetPoint: { x: number; y: number }, - modifiers: Modifiers, - renderResult: EditorRenderResult, - elementType: string = 'div', -): Promise { - const insertButton = renderResult.renderedDOM.getByTestId(`insert-item-${elementType}`) - const insertButtonBounds = insertButton.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetPointBecauseVeryWeirdIssue({ - x: insertButtonBounds.x + insertButtonBounds.width / 2, - y: insertButtonBounds.y + insertButtonBounds.height / 2, - }) - - const endPoint = slightlyOffsetPointBecauseVeryWeirdIssue(targetPoint) - - await mouseMoveToPoint(insertButton, startPoint) - await mouseDownAtPoint(insertButton, startPoint) - await mouseMoveToPoint(canvasControlsLayer, endPoint, { - modifiers: modifiers, - eventOptions: { buttons: 1 }, - }) -} - -async function finishDraggingToPoint( - targetPoint: { x: number; y: number }, - modifiers: Modifiers, - renderResult: EditorRenderResult, -): Promise { - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - const endPoint = slightlyOffsetPointBecauseVeryWeirdIssue(targetPoint) - await mouseUpAtPoint(canvasControlsLayer, endPoint, { modifiers: modifiers }) -} - -async function dragFromInsertMenuDivButtonToPoint( - targetPoint: { x: number; y: number }, - modifiers: Modifiers, - renderResult: EditorRenderResult, - showDragOutline: 'show-drag-outline' | 'no-drag-outline', - elementType: string = 'div', -) { - await expectSingleUndo2Saves(renderResult, async () => { - await startDraggingFromInsertMenuDivButtonToPoint( - targetPoint, - modifiers, - renderResult, - elementType, - ) - const dragOutlineControl = await renderResult.renderedDOM.queryByTestId( - DragOutlineControlTestId, - ) - if (showDragOutline === 'show-drag-outline') { - expect(dragOutlineControl).not.toBeNull() - } else { - expect(dragOutlineControl).toBeNull() - } - await finishDraggingToPoint(targetPoint, modifiers, renderResult) - }) - - await renderResult.getDispatchFollowUpActionsFinished() -} - -describe('drag-to-insert', () => { - describe('Dragging from the insert menu into an absolute layout', () => { - const inputCode = makeTestProjectCodeWithSnippet(` -
-
-
-
- `) - - it('Should insert a div into an absolute layout', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetParentElement = renderResult.renderedDOM.getByTestId('larger') - const targetParentElementBounds = targetParentElement.getBoundingClientRect() - const targetPoint = { - x: targetParentElementBounds.x + targetParentElementBounds.width / 2, - y: targetParentElementBounds.y + targetParentElementBounds.height / 2, - } - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'no-drag-outline', - ) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - - it('Should insert into a smaller element', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetParentElement = renderResult.renderedDOM.getByTestId('smaller') - const targetParentElementBounds = targetParentElement.getBoundingClientRect() - const targetPoint = { - x: targetParentElementBounds.x + targetParentElementBounds.width / 2, - y: targetParentElementBounds.y + targetParentElementBounds.height / 2, - } - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'no-drag-outline', - ) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - - it('Should insert a conditional into an absolute layout', async () => { - const renderResult = await setupInsertTest(inputCode) - - FOR_TESTS_setNextGeneratedUids(['ddd']) - - const targetParentElement = renderResult.renderedDOM.getByTestId('larger') - const targetParentElementBounds = targetParentElement.getBoundingClientRect() - const targetPoint = { - x: targetParentElementBounds.x + targetParentElementBounds.width / 2, - y: targetParentElementBounds.y + targetParentElementBounds.height / 2, - } - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'no-drag-outline', - 'Conditional', - ) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
- {true ? ( -
- ) : ( -
- False branch -
- )} -
-
-
- `), - ) - }) - - it('Should insert a fragment into an absolute layout', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetParentElement = renderResult.renderedDOM.getByTestId('larger') - const targetParentElementBounds = targetParentElement.getBoundingClientRect() - const targetPoint = { - x: targetParentElementBounds.x + targetParentElementBounds.width / 2, - y: targetParentElementBounds.y + targetParentElementBounds.height / 2, - } - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'no-drag-outline', - 'Fragment', - ) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
- -
- -
-
-
- `), - ) - }) - }) - - describe('Dragging from the insert menu into a flex layout', () => { - const inputCode = makeTestProjectCodeWithSnippet(` -
-
-
-
- `) - - it('Should insert a div into a flex layout at zero position', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetNextSibling = renderResult.renderedDOM.getByTestId('bbb') - const targetNextSiblingBounds = targetNextSibling.getBoundingClientRect() - // Drag close to the left edge of the target sibling - const targetPoint = { - x: targetNextSiblingBounds.x + 5, - y: targetNextSiblingBounds.y + 5, - } - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'show-drag-outline', - ) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Should insert a wrapped element into a flex layout at zero position', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetNextSibling = renderResult.renderedDOM.getByTestId('bbb') - const targetNextSiblingBounds = targetNextSibling.getBoundingClientRect() - // Drag close to the left edge of the target sibling - const targetPoint = { - x: targetNextSiblingBounds.x + 5, - y: targetNextSiblingBounds.y + 5, - } - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'show-drag-outline', - 'Fragment', - ) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
- -
- -
-
-
- `), - ) - }) - - it('Should insert a div into a flex layout with absolute positioning', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetSibling = renderResult.renderedDOM.getByTestId('bbb') - const targetSiblingBounds = targetSibling.getBoundingClientRect() - // Drag close to the right edge of the target sibling - const targetPoint = { - x: targetSiblingBounds.x + targetSiblingBounds.width - 5, - y: targetSiblingBounds.y + targetSiblingBounds.height - 5, - } - - await startDraggingFromInsertMenuDivButtonToPoint(targetPoint, emptyModifiers, renderResult) - // Tab once to switch from flex insert to abs - await pressKey('Tab', { modifiers: emptyModifiers }) - await finishDraggingToPoint(targetPoint, emptyModifiers, renderResult) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Should forcibly insert a div into a flex layout that does not provide bounds with absolute positioning', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetParent = renderResult.renderedDOM.getByTestId('ccc') - const targetParentBounds = targetParent.getBoundingClientRect() - - const targetPoint = { - x: targetParentBounds.x + targetParentBounds.width / 2, - y: targetParentBounds.y + targetParentBounds.height / 2, - } - - await startDraggingFromInsertMenuDivButtonToPoint(targetPoint, emptyModifiers, renderResult) - // Tab once to switch from flex insert to forced abs - await pressKey('Tab', { modifiers: emptyModifiers }) - await finishDraggingToPoint(targetPoint, emptyModifiers, renderResult) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - - it('Should insert a div into a flex layout at the next position', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetPrevSibling = renderResult.renderedDOM.getByTestId('bbb') - const targetPrevSiblingBounds = targetPrevSibling.getBoundingClientRect() - // Drag close to the right edge of the target sibling - const targetPoint = { - x: targetPrevSiblingBounds.x + targetPrevSiblingBounds.width - 5, - y: targetPrevSiblingBounds.y + targetPrevSiblingBounds.height - 5, - } - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'show-drag-outline', - ) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Should insert a div into a child of a flex layout which provides absolute bounds', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetParentElement = renderResult.renderedDOM.getByTestId('bbb') - const targetParentElementBounds = targetParentElement.getBoundingClientRect() - - const targetPoint = { - x: targetParentElementBounds.x + targetParentElementBounds.width / 2, - y: targetParentElementBounds.y + targetParentElementBounds.height / 2, - } - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'no-drag-outline', - ) - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - }) - - it('can insert two images', async () => { - const renderResult = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(` -
-
-
-
- `), - 'await-first-dom-report', - ) - - const targetParentElement = renderResult.renderedDOM.getByTestId('larger') - const targetParentElementBounds = targetParentElement.getBoundingClientRect() - const targetPoint = { - x: targetParentElementBounds.x + targetParentElementBounds.width / 2, - y: targetParentElementBounds.y + targetParentElementBounds.height / 2, - } - - await renderResult.dispatch([setRightMenuTab(RightMenuTab.Insert)], false) - - FOR_TESTS_setNextGeneratedUid('ddd') - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'no-drag-outline', - 'img', - ) - - await renderResult.dispatch([setRightMenuTab(RightMenuTab.Insert)], false) - - FOR_TESTS_setNextGeneratedUid('eee') - - await dragFromInsertMenuDivButtonToPoint( - targetPoint, - emptyModifiers, - renderResult, - 'no-drag-outline', - 'img', - ) - - expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( - [ - 'regular-utopia-storyboard-uid/scene-aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:aaa', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:aaa/larger', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:aaa/larger/ddd', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:aaa/larger/eee', - 'regular-utopia-storyboard-uid/scene-aaa/app-entity:aaa/smaller', - ], - ) - }) -}) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/drag-to-insert-metastrategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/drag-to-insert-metastrategy.tsx index 60eafa144228..d98c44b2dd47 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/drag-to-insert-metastrategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/drag-to-insert-metastrategy.tsx @@ -58,6 +58,10 @@ import { wrapInContainerCommand } from '../../commands/wrap-in-container-command import type { InsertionPath } from '../../../editor/store/insertion-path' import { childInsertionPath } from '../../../editor/store/insertion-path' +/** + * NOTE: this strategy was mostly used for legacy insert menu interactions, but it's kept + * intact since it's still used for image insertion from other places. + */ export const dragToInsertMetaStrategy: MetaCanvasStrategy = ( canvasState: InteractionCanvasState, interactionSession: InteractionSession | null, diff --git a/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-metastrategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-metastrategy.tsx index 8dec77d65f2c..423ab0bd4d15 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-metastrategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-metastrategy.tsx @@ -66,6 +66,14 @@ import { wildcardPatch } from '../../commands/wildcard-patch-command' import type { InsertionPath } from '../../../editor/store/insertion-path' import { childInsertionPath } from '../../../editor/store/insertion-path' +/** + * + * NOTE: https://github.com/concrete-utopia/utopia/pull/5819 deleted a bunch of + * tests for this strategy that relied on the legacy insert menu. + * + * ! IF YOU WORK ON THIS, PLEASE RESURRECT THE TESTS AND MAKE THEM USE THE 'F' SHORTCUT ! + * + */ export const drawToInsertMetaStrategy: MetaCanvasStrategy = ( canvasState: InteractionCanvasState, interactionSession: InteractionSession | null, diff --git a/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-strategy.spec.browser2.tsx index 9e1cb0480398..2540e52d561d 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/draw-to-insert-strategy.spec.browser2.tsx @@ -4,41 +4,12 @@ import { makeTestProjectCodeWithSnippet, renderTestEditorWithCode, getPrintedUiJsCode, - TestSceneUID, - TestAppUID, } from '../../ui-jsx.test-utils' import { CanvasControlsContainerID } from '../../controls/new-canvas-controls' import * as EP from '../../../../core/shared/element-path' -import { - mouseClickAtPoint, - mouseDownAtPoint, - mouseDragFromPointToPoint, - mouseDragFromPointToPointNoMouseDown, - mouseMoveToPoint, - pressKey, -} from '../../event-helpers.test-utils' +import { mouseClickAtPoint, mouseMoveToPoint, pressKey } from '../../event-helpers.test-utils' import { RightMenuTab } from '../../../editor/store/editor-state' -import { - FOR_TESTS_setNextGeneratedUid, - FOR_TESTS_setNextGeneratedUids, -} from '../../../../core/model/element-template-utils.test-utils' -import { BakedInStoryboardUID } from '../../../../core/model/scene-utils' -import type { ElementInstanceMetadataMap } from '../../../../core/shared/element-template' -import type { CanvasPoint, CanvasRectangle } from '../../../../core/shared/math-utils' -import { - canvasPoint, - isInfinityRectangle, - offsetPoint, - windowPoint, -} from '../../../../core/shared/math-utils' -import { MetadataUtils } from '../../../../core/model/element-metadata-utils' -import type { Direction } from '../../../inspector/common/css-utils' -import { expectSingleUndo2Saves } from '../../../../utils/utils.test-utils' -import type { Modifiers } from '../../../../utils/modifiers' -import { emptyModifiers, shiftModifier } from '../../../../utils/modifiers' - -// FIXME These tests will probably start to fail if the insert menu becomes too long, at which point we may -// have to insert some mocking to restrict the available items there +import { FOR_TESTS_setNextGeneratedUid } from '../../../../core/model/element-template-utils.test-utils' function slightlyOffsetWindowPointBecauseVeryWeirdIssue(point: { x: number; y: number }) { // FIXME when running in headless chrome, the result of getBoundingClientRect will be slightly @@ -60,232 +31,6 @@ function ensureInInsertMode(renderResult: EditorRenderResult): void { expect(renderResult.getEditorState().editor.mode.type).toEqual('insert') } -async function enterInsertModeFromInsertMenu( - renderResult: EditorRenderResult, - elementType: string = 'div', -) { - const insertButton = renderResult.renderedDOM.getByTestId(`insert-item-${elementType}`) - const insertButtonBounds = insertButton.getBoundingClientRect() - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: insertButtonBounds.x + insertButtonBounds.width / 2, - y: insertButtonBounds.y + insertButtonBounds.height / 2, - }) - - await mouseMoveToPoint(insertButton, point) - await mouseClickAtPoint(insertButton, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - ensureInInsertMode(renderResult) -} - -async function enterInsertModeFromInsertMenuStartDrag(renderResult: EditorRenderResult) { - const insertButton = renderResult.renderedDOM.getByTestId('insert-item-div') - const insertButtonBounds = insertButton.getBoundingClientRect() - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: insertButtonBounds.x + insertButtonBounds.width / 2, - y: insertButtonBounds.y + insertButtonBounds.height / 2, - }) - - await mouseMoveToPoint(insertButton, point) - await mouseDownAtPoint(insertButton, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - ensureInInsertMode(renderResult) -} - -function isIndicatorBeforeSiblingBBB( - metadata: ElementInstanceMetadataMap, - reparentLine: CanvasRectangle, -): boolean { - const targetSibling = EP.fromString( - `${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:aaa/bbb`, - ) - const targetParent = EP.fromString(`${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:aaa`) - - const parentFrame = MetadataUtils.getFrameInCanvasCoords(targetParent, metadata) - const nextSiblingFrame = MetadataUtils.getFrameInCanvasCoords(targetSibling, metadata) - - if (parentFrame == null || nextSiblingFrame == null || isInfinityRectangle(nextSiblingFrame)) { - return false - } else { - const isBelowRightOfParentTopLeft = - isInfinityRectangle(parentFrame) || - (reparentLine.x >= parentFrame.x && reparentLine.y >= parentFrame.y) - - return ( - isBelowRightOfParentTopLeft && - reparentLine.x <= nextSiblingFrame.x && - reparentLine.y <= nextSiblingFrame.y - ) - } -} - -function isIndicatorBetweenSiblingsBBBCCC( - metadata: ElementInstanceMetadataMap, - reparentLine: CanvasRectangle, - flexDirection: Direction, -): boolean { - const targetSiblingBefore = EP.fromString( - `${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:aaa/bbb`, - ) - const targetSiblingAfter = EP.fromString( - `${BakedInStoryboardUID}/${TestSceneUID}/${TestAppUID}:aaa/ccc`, - ) - const prevSiblingFrame = MetadataUtils.getFrameInCanvasCoords(targetSiblingBefore, metadata) - const nextSiblingFrame = MetadataUtils.getFrameInCanvasCoords(targetSiblingAfter, metadata) - if ( - prevSiblingFrame == null || - nextSiblingFrame == null || - isInfinityRectangle(prevSiblingFrame) || - isInfinityRectangle(nextSiblingFrame) - ) { - return false - } else { - const prevSiblingEdge = - flexDirection === 'horizontal' - ? { - x: prevSiblingFrame.x + prevSiblingFrame.width, - y: prevSiblingFrame.y, - } - : { - x: prevSiblingFrame.x, - y: prevSiblingFrame.y + prevSiblingFrame.height, - } - return ( - reparentLine.x >= prevSiblingEdge.x && - reparentLine.y >= prevSiblingEdge.y && - reparentLine.x <= nextSiblingFrame.x && - reparentLine.y <= nextSiblingFrame.y - ) - } -} - -const testDrawToInsertImageAspectRatio = async (inputCode: string, expectedCode: string) => { - const renderResult = await setupInsertTest(makeTestProjectCodeWithSnippet(inputCode)) - await enterInsertModeFromInsertMenu(renderResult, 'img') - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 15, // with aspect ratio lock this 10px with should be ignored - y: targetElementBounds.y + 305, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(expectedCode), - ) -} - -async function drawToInsertTestMaybeAddsFlexGrow( - dragDelta: CanvasPoint, - expectedStyle: React.CSSProperties, - flexDirection: 'row' | 'column', - parentSize: number | null = null, -) { - const flexElementWithChildren = (insertedSibling: string = '') => - makeTestProjectCodeWithSnippet(` -
-
-
-
- ${insertedSibling} -
- `) - - const renderResult = await setupInsertTest(flexElementWithChildren()) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bb3') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 5, - y: targetElementBounds.y + targetElementBounds.height + 5, - }) as CanvasPoint - const endPoint = offsetPoint(startPoint, dragDelta) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - - // Drag horizontally close to the first position - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - const insertedSiblingCode = `
- ` - - // Check that the inserted element contains the correct style property - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - flexElementWithChildren(insertedSiblingCode), - ) -} - /* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "runInsertTest", "runClickToInsertTest", "drawToInsertTestMaybeAddsFlexGrow", "testDrawToInsertImageAspectRatio" ] }] */ describe('draw-to-insert', () => { @@ -326,162 +71,25 @@ describe('draw-to-insert', () => {
`) - describe('Inserting into simple target', () => { - async function runInsertTest( - dragDelta: { x: number; y: number }, - modifiers: Modifiers, - expectedSize: { width: number; height: number }, - ) { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: startPoint.x + dragDelta.x, - y: startPoint.y + dragDelta.y, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint, { - modifiers: modifiers, - }) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - } - - it('Should honour the initial target when dragging to insert', async () => { - const xDelta = 20 - const yDelta = 300 - await runInsertTest({ x: xDelta, y: yDelta }, emptyModifiers, { - width: xDelta, - height: yDelta, - }) - }) - - it('Should lock aspect ratio to 1:1 when holding shift and dragging vertically', async () => { - const xDelta = 20 - const yDelta = 300 - - // The result should be the same regardless of which dimension of the drag is the larger - await runInsertTest({ x: xDelta, y: yDelta }, shiftModifier, { - width: yDelta, - height: yDelta, - }) - }) - - it('Should lock aspect ratio to 1:1 when holding shift and dragging horizontally', async () => { - const xDelta = 300 - const yDelta = 20 - - // The result should be the same regardless of which dimension of the drag is the larger - await runInsertTest({ x: xDelta, y: yDelta }, shiftModifier, { - width: xDelta, - height: xDelta, - }) - }) - - it('Should insert a conditional', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult, 'Conditional') - - FOR_TESTS_setNextGeneratedUids([ - 'skip1', - 'skip2', - 'skip3', - 'skip4', - 'skip5', - 'skip6', - 'skip7', - 'false-branch', - ]) - + describe('Click to insert with default size', () => { + async function runClickToInsertTest(renderResult: EditorRenderResult) { const targetElement = renderResult.renderedDOM.getByTestId('bbb') const targetElementBounds = targetElement.getBoundingClientRect() const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - const dragDelta = windowPoint({ x: 50, y: 40 }) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: startPoint.x + dragDelta.x, - y: startPoint.y + dragDelta.y, + const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ + x: targetElementBounds.x + 65, + y: targetElementBounds.y + 55, }) - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) + // Move before clicking + await mouseMoveToPoint(canvasControlsLayer, point) // Highlight should show the candidate parent expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) + // Click in bbb + await mouseClickAtPoint(canvasControlsLayer, point) await renderResult.getDispatchFollowUpActionsFinished() @@ -509,116 +117,17 @@ describe('draw-to-insert', () => { backgroundColor: '#d3d3d3', }} > - {true ? (
- ) : ( -
- False branch -
- )} -
-
-
- `), - ) - }) - - it('Should insert a fragment', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult, 'Fragment') - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const dragDelta = windowPoint({ x: 50, y: 40 }) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: startPoint.x + dragDelta.x, - y: startPoint.y + dragDelta.y, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
- -
-
{
`), ) - }) - }) - - it('Should drag to insert into targets smaller than the element', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 1005, - y: targetElementBounds.y + 1005, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - - describe('Click to insert with default size', () => { - async function runClickToInsertTest(renderResult: EditorRenderResult) { - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 65, - y: targetElementBounds.y + 55, - }) - - // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Click in bbb - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - } - - it('works from the insert menu', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - await runClickToInsertTest(renderResult) - }) + } it('works with the keyboard shortcut', async () => { const renderResult = await setupInsertTest(inputCode) @@ -804,2481 +152,5 @@ describe('draw-to-insert', () => { await runClickToInsertTest(renderResult) }) }) - - it('Click to insert into an element smaller than the default size', async () => { - const renderResult = await setupInsertTest( - makeTestProjectCodeWithSnippet(` -
-
-
- `), - ) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - - // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Click in bbb - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Should not clear the intended target when dragging to insert past the scene boundary', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 1005, - y: targetElementBounds.y + 15, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Drag from inside bbb to outside of the scene - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - - it('when drag ends outside the canvas in insert mode, it is cancelled', async () => { - const renderResult = await setupInsertTest(inputCode) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 2005, - y: targetElementBounds.y + 2005, - }) - - await enterInsertModeFromInsertMenuStartDrag(renderResult) - await renderResult.getDispatchFollowUpActionsFinished() - - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - await mouseDragFromPointToPointNoMouseDown(canvasControlsLayer, startPoint, endPoint) - await renderResult.getDispatchFollowUpActionsFinished() - - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual(inputCode) - }) - it('Drag to insert into a zero sized element', async () => { - const testCode = makeTestProjectCodeWithSnippet(` -
-
-
- `) - const renderResult = await setupInsertTest(testCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x, - y: targetElementBounds.y, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 40, - y: targetElementBounds.y + 50, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - it('Click to insert into a zero size element', async () => { - const testCode = makeTestProjectCodeWithSnippet(` -
-
-
- `) - const renderResult = await setupInsertTest(testCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x, - y: targetElementBounds.y, - }) - - // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Click in bbb - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Ignores fragments and flattens their children', async () => { - const inputWithFragments = makeTestProjectCodeWithSnippet(` -
- -
-
- <> -
- - -
-
- `) - - const renderResult = await setupInsertTest(inputWithFragments) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('aaa') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 200, - y: targetElementBounds.y + 200, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 250, - y: targetElementBounds.y + 250, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
- -
-
- <> -
- - -
-
-
- `), - ) - }) - }) - - describe('Inserting into Static', () => { - const inputCode = makeTestProjectCodeWithSnippet(` -
-
-
-
- `) - - it('By default, it inserts as absolute into a flow parent', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 15, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 25, - y: targetElementBounds.y + 35, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- -
- `), - ) - }) - - it('Using the strategy picker, it happily inserts into a static element', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 15, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 25, - y: targetElementBounds.y + 35, - }) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint, { - midDragCallback: async () => { - await pressKey('2') // this should select the 'Draw to Insert (Flow)' strategy - }, - }) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - }) - - describe('Inserting into flex row', () => { - const inputCode = makeTestProjectCodeWithSnippet(` -
-
-
-
- `) - - it('Insert into zero position in flex', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 25, - y: targetElementBounds.y + 305, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - const indicatorBeforeSibling = isIndicatorBeforeSiblingBBB( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - ) - expect(indicatorBeforeSibling).toEqual(true) - - // Drag horizontally close to the zero position - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is before bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Click to insert into zero position in flex', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - - // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - const indicatorBeforeSibling = isIndicatorBeforeSiblingBBB( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - ) - expect(indicatorBeforeSibling).toEqual(true) - - // Click horizontally close to the zero position - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is before bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Inserting a wrapped element into the 0th position in flex', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult, 'Conditional') - - FOR_TESTS_setNextGeneratedUids([ - 'skip1', - 'skip2', - 'skip3', - 'skip4', - 'skip5', - 'skip6', - 'skip7', - 'false-branch', - ]) - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 25, - y: targetElementBounds.y + 305, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - const indicatorBeforeSibling = isIndicatorBeforeSiblingBBB( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - ) - expect(indicatorBeforeSibling).toEqual(true) - - await expectSingleUndo2Saves(renderResult, () => - // Drag horizontally close to the zero position - mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint), - ) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is before bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
- {true ? ( -
- ) : ( -
- False branch -
- )} -
-
-
- `), - ) - }) - - it('Insert into first position in flex', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 5, - y: targetElementBounds.y + targetElementBounds.height + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 25, - y: targetElementBounds.y + targetElementBounds.height + 305, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - const indicatorBetweenSiblings = isIndicatorBetweenSiblingsBBBCCC( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - 'horizontal', - ) - expect(indicatorBetweenSiblings).toEqual(true) - - // Drag horizontally close to the first position - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is after bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Click to insert into first position in flex', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 5, - y: targetElementBounds.y + targetElementBounds.height + 5, - }) // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - const indicatorBetweenSiblings = isIndicatorBetweenSiblingsBBBCCC( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - 'horizontal', - ) - expect(indicatorBetweenSiblings).toEqual(true) - - // Click horizontally close to the first position - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is after bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Insert into first position in flex, backwards drag', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 25, - y: targetElementBounds.y + 305, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 5, - y: targetElementBounds.y + 5, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - - const indicatorBetweenSiblings = isIndicatorBetweenSiblingsBBBCCC( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - 'horizontal', - ) - expect(indicatorBetweenSiblings).toEqual(true) - - // Drag starts horizontally close to the first position, dragging towards the top left - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is before bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Insert inside a flex child with absolute layout', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 10, - y: targetElementBounds.y + 10, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 30, - y: targetElementBounds.y + 40, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Drag starts inside bbb - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - - it('Click to insert inside a flex child with absolute layout', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 10, - y: targetElementBounds.y + 10, - }) - - // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['bbb']) - - // Click inside bbb - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
-
- `), - ) - }) - - it('Drag inside a flex child close to the edge, which inserts as a sibling', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 3, - y: targetElementBounds.y + 3, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 23, - y: targetElementBounds.y + 33, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - - const indicatorBeforeSibling = isIndicatorBeforeSiblingBBB( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - ) - expect(indicatorBeforeSibling).toEqual(true) - - // Drag starts inside bbb, but very close to its edge (3px) - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is before bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Click inside a flex child close to the edge, which inserts as a sibling', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 3, - y: targetElementBounds.y + 3, - }) - - // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - - const indicatorBeforeSibling = isIndicatorBeforeSiblingBBB( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - ) - expect(indicatorBeforeSibling).toEqual(true) - - // Click inside bbb, but very close to its edge (3px) - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is before bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - describe('insertion adds flex grow on reaching edge if possible', () => { - it('inserting into the end of flex row adds flexGrow when reaching parent`s edge', async () => { - const expectedStyle = { - backgroundColor: '#aaaaaa33', - height: 25, - contain: 'layout', - flexGrow: 1, - } - await drawToInsertTestMaybeAddsFlexGrow(canvasPoint({ x: 60, y: 25 }), expectedStyle, 'row') - }) - it('inserting into the end of flex row adds width when not reaching parent`s edge', async () => { - const expectedStyle = { - backgroundColor: '#aaaaaa33', - width: 50, - height: 25, - contain: 'layout', - } - await drawToInsertTestMaybeAddsFlexGrow(canvasPoint({ x: 50, y: 25 }), expectedStyle, 'row') - }) - it('inserting into the end of flex row only adds width when siblings are shrinked already (no open space for insertion)', async () => { - const expectedStyle = { - backgroundColor: '#aaaaaa33', - width: 60, - height: 25, - contain: 'layout', - } - await drawToInsertTestMaybeAddsFlexGrow( - canvasPoint({ x: 60, y: 25 }), - expectedStyle, - 'row', - 100, - ) - }) - }) - }) - - describe('Inserting into flex column', () => { - const inputCode = makeTestProjectCodeWithSnippet(` -
-
-
-
- `) - - it('Insert into zero position in flex, column layout', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 305, - y: targetElementBounds.y + 25, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - - const indicatorBeforeSibling = isIndicatorBeforeSiblingBBB( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - ) - expect(indicatorBeforeSibling).toEqual(true) - - // Drag vertically close to the first position - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is before bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Click to insert into zero position in flex, column layout', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 5, - y: targetElementBounds.y + 5, - }) - - // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - - const indicatorBeforeSibling = isIndicatorBeforeSiblingBBB( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - ) - expect(indicatorBeforeSibling).toEqual(true) - - // Click vertically close to the first position - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is before bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Insert into first position in flex, column layout', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 5, - y: targetElementBounds.y + targetElementBounds.height + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 305, - y: targetElementBounds.y + targetElementBounds.height + 25, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - - const indicatorBetweenSiblings = isIndicatorBetweenSiblingsBBBCCC( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - 'vertical', - ) - expect(indicatorBetweenSiblings).toEqual(true) - - // Drag vertically close to the first position - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is after bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Click to insert into first position in flex, column layout', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const point = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 5, - y: targetElementBounds.y + targetElementBounds.height + 5, - }) - - // Move before clicking - await mouseMoveToPoint(canvasControlsLayer, point) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - const indicatorBetweenSiblings = isIndicatorBetweenSiblingsBBBCCC( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - 'vertical', - ) - expect(indicatorBetweenSiblings).toEqual(true) - - // Click vertically close to the first position - await mouseClickAtPoint(canvasControlsLayer, point) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is after bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - - it('Insert into first position in flex, column layout, backwards drag', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width + 105, - y: targetElementBounds.y + targetElementBounds.height + 25, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + targetElementBounds.width - 195, - y: targetElementBounds.y + targetElementBounds.height + 5, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual(['aaa']) - // Shows flex indicator line at index position target - expect( - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines.length, - ).toEqual(1) - const indicatorBetweenSiblings = isIndicatorBetweenSiblingsBBBCCC( - renderResult.getEditorState().editor.jsxMetadata, - renderResult.getEditorState().editor.canvas.controls.flexReparentTargetLines[0], - 'vertical', - ) - expect(indicatorBetweenSiblings).toEqual(true) - - // Drag starts vertically close to the first position, dragging towards the top left - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a sibling of bbb, position is after bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
-
- `), - ) - }) - describe('insertion adds flex grow on reaching edge if possible', () => { - it('inserting into the end of flex column adds flexGrow when reaching parent`s edge', async () => { - const expectedStyle = { - backgroundColor: '#aaaaaa33', - width: 60, - contain: 'layout', - flexGrow: 1, - } - await drawToInsertTestMaybeAddsFlexGrow( - canvasPoint({ x: 60, y: 136 }), - expectedStyle, - 'column', - ) - }) - it('inserting into the end of flex column adds width when not reaching parent`s edge', async () => { - const expectedStyle = { - backgroundColor: '#aaaaaa33', - width: 50, - height: 130, - contain: 'layout', - } - await drawToInsertTestMaybeAddsFlexGrow( - canvasPoint({ x: 50, y: 130 }), - expectedStyle, - 'column', - ) - }) - it('inserting into the end of flex column only adds width when siblings are shrinked already (no open space for insertion)', async () => { - const expectedStyle = { - backgroundColor: '#aaaaaa33', - width: 60, - height: 136, - contain: 'layout', - } - await drawToInsertTestMaybeAddsFlexGrow( - canvasPoint({ x: 60, y: 136 }), - expectedStyle, - 'column', - 100, - ) - }) - }) - }) - - describe('Inserting an image', () => { - it('Draw to insert to an absolute layout keeps aspect ratio', async () => { - const inputCode = ` -
-
-
-
- ` - const expectedCode = ` -
-
- -
-
-
- ` - await testDrawToInsertImageAspectRatio(inputCode, expectedCode) - }) - - it('Draw to insert to a flex layout keeps aspect ratio', async () => { - const inputCode = ` -
-
-
- ` - const expectedCode = ` -
-
- -
-
- ` - await testDrawToInsertImageAspectRatio(inputCode, expectedCode) - }) - }) - - describe('Conditionals support', () => { - ;[true, false].forEach((enabled) => { - describe(`with the Conditional feature switch ${enabled ? 'enabled' : 'disabled'}`, () => { - const inputCode = makeTestProjectCodeWithSnippet(` -
-
- {true ? ( -
- ) : null} -
- `) - - it('Draw to insert into a sibling of the conditional', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('bbb') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = - renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 5, - y: targetElementBounds.y + 5, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 25, - y: targetElementBounds.y + 305, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual([ - 'bbb', - ]) - - // Drag from inside bbb to inside ccc - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint, { - midDragCallback: async () => { - expect(renderResult.getEditorState().strategyState.currentStrategy).toEqual( - 'Draw to Insert (Abs)', - ) - }, - }) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
-
-
- {true ? ( -
- ) : null} -
- `), - ) - }) - - it('Draw to insert into the parent of a conditional works', async () => { - const renderResult = await setupInsertTest(inputCode) - await enterInsertModeFromInsertMenu(renderResult) - - const targetElement = renderResult.renderedDOM.getByTestId('aaa') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = - renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 170, - y: targetElementBounds.y + 10, - }) - const endPoint = slightlyOffsetWindowPointBecauseVeryWeirdIssue({ - x: targetElementBounds.x + 220, - y: targetElementBounds.y + 310, - }) - - // Move before starting dragging - await mouseMoveToPoint(canvasControlsLayer, startPoint) - - // Highlight should show the candidate parent - expect(renderResult.getEditorState().editor.highlightedViews.map(EP.toUid)).toEqual([ - 'aaa', - ]) - - await mouseDragFromPointToPoint(canvasControlsLayer, startPoint, endPoint, { - midDragCallback: async () => { - expect(renderResult.getEditorState().strategyState.currentStrategy).toEqual( - 'Draw to Insert (Abs)', - ) - }, - }) - - await renderResult.getDispatchFollowUpActionsFinished() - - // Check that the inserted element is a child of bbb - expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( - makeTestProjectCodeWithSnippet(` -
-
- {true ? ( -
- ) : null} -
-
- `), - ) - }) - }) - }) }) }) diff --git a/editor/src/components/canvas/design-panel-root.tsx b/editor/src/components/canvas/design-panel-root.tsx index 5849399e2bcb..a47489e46279 100644 --- a/editor/src/components/canvas/design-panel-root.tsx +++ b/editor/src/components/canvas/design-panel-root.tsx @@ -21,7 +21,6 @@ import { ErrorsPane } from '../code-editor/errors-pane' import { CanvasStrategyInspector } from './canvas-strategies/canvas-strategy-inspector' import { IS_TEST_ENVIRONMENT, getQueryParam } from '../../common/env-vars' import { when } from '../../utils/react-conditionals' -import { InsertMenuPane } from '../navigator/insert-menu-pane' import { useDispatch } from '../editor/store/dispatch-context' import { GridPanelsContainer } from './grid-panels-container' import { TitleBarCode, TitleBarUserProfile } from '../titlebar/title-bar' @@ -232,7 +231,6 @@ export const RightPane = React.memo((props) => { backgroundColor: colorTheme.inspectorBackground.value, }} > - {when(selectedTab === RightMenuTab.Insert, )} {when(selectedTab === RightMenuTab.Inspector, )} {when(selectedTab === RightMenuTab.Settings, )} {when(selectedTab === RightMenuTab.Comments, )} diff --git a/editor/src/components/editor/insertmenu.spec.browser2.tsx b/editor/src/components/editor/insertmenu.spec.browser2.tsx index 25eb6fdd72ce..3dc761f4d0c3 100644 --- a/editor/src/components/editor/insertmenu.spec.browser2.tsx +++ b/editor/src/components/editor/insertmenu.spec.browser2.tsx @@ -16,7 +16,6 @@ import { renderTestEditorWithCode, } from '../canvas/ui-jsx.test-utils' import { setPanelVisibility, setRightMenuTab } from './actions/action-creators' -import { InsertMenuFilterTestId } from './insertmenu' import { RightMenuTab } from './store/editor-state' import { ComponentPickerTestId } from '../navigator/navigator-item/component-picker' import * as EP from '../../core/shared/element-path' diff --git a/editor/src/components/editor/insertmenu.tsx b/editor/src/components/editor/insertmenu.tsx deleted file mode 100644 index 4f58ad4cdc9a..000000000000 --- a/editor/src/components/editor/insertmenu.tsx +++ /dev/null @@ -1,727 +0,0 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -import type { CSSObject } from '@emotion/react' -import { jsx } from '@emotion/react' -import React, { useState } from 'react' -import type { - InputActionMeta, - InputProps, - MenuListComponentProps, - OptionProps, - StylesConfig, -} from 'react-windowed-select' -import WindowedSelect, { components, createFilter } from 'react-windowed-select' -import { RightMenuTab } from '../../components/editor/store/editor-state' -import { generateUidWithExistingComponents } from '../../core/model/element-template-utils' -import { isLeft } from '../../core/shared/either' -import type { JSXAttributes, JSXElementName } from '../../core/shared/element-template' -import { - emptyComments, - getJSXAttribute, - jsExpressionValue, - jsxElement, - jsxElementNameEquals, - setJSXAttributesAttribute, -} from '../../core/shared/element-template' -import { setJSXValueInAttributeAtPath } from '../../core/shared/jsx-attribute-utils' -import type { CanvasVector } from '../../core/shared/math-utils' -import { canvasPoint, point, windowPoint } from '../../core/shared/math-utils' -import type { - PackageStatus, - PackageStatusMap, - PossiblyUnversionedNpmDependency, -} from '../../core/shared/npm-dependency-types' -import type { ElementPath, Imports } from '../../core/shared/project-file-types' -import { importsEquals } from '../../core/shared/project-file-types' -import * as PP from '../../core/shared/property-path' -import { NO_OP, assertNever } from '../../core/shared/utils' -import { Modifier, emptyModifiers } from '../../utils/modifiers' -import { Icn, InspectorSubsectionHeader, UIRow, UtopiaTheme, useColorTheme } from '../../uuiui' -import { getControlStyles } from '../../uuiui-deps' -import { InspectorInputEmotionStyle } from '../../uuiui/inputs/base-input' -import type { ProjectContentTreeRoot } from '../assets' -import CanvasActions from '../canvas/canvas-actions' -import { - boundingArea, - createHoverInteractionViaMouse, - createInteractionViaMouse, -} from '../canvas/canvas-strategies/interaction-state' -import type { CanvasAction } from '../canvas/canvas-types' -import { windowToCanvasCoordinates } from '../canvas/dom-lookup' -import type { PropertyControlsInfo } from '../custom-code/code-file' -import type { FontSettings } from '../inspector/common/css-utils' -import { NpmDependencyVersionAndStatusIndicator } from '../navigator/dependecy-version-status-indicator' -import type { InsertableComponent } from '../shared/project-components' -import { - getInsertableGroupLabel, - getNonEmptyComponentGroups, - moveSceneToTheBeginningAndSetDefaultSize, -} from '../shared/project-components' -import type { EditorDispatch } from './action-types' -import { enableInsertModeForJSXElement, setRightMenuTab } from './actions/action-creators' -import { defaultDivElement } from './defaults' -import type { InsertionSubject, Mode } from './editor-modes' -import { usePossiblyResolvedPackageDependencies } from './npm-dependency/npm-dependency' -import { useDispatch } from './store/dispatch-context' -import { Substores, useEditorState } from './store/store-hook' - -export const InsertMenuId = 'insert-menu-inspector-tab' - -export const InsertMenuFilterTestId = 'insert-menu-filter' - -interface InsertMenuProps { - lastFontSettings: FontSettings | null - selectedViews: Array - mode: Mode - currentlyOpenFilename: string | null - dependencies: Array - packageStatus: PackageStatusMap - propertyControlsInfo: PropertyControlsInfo - projectContents: ProjectContentTreeRoot - canvasScale: number - canvasOffset: CanvasVector -} - -export const InsertMenu = React.memo(() => { - const restOfEditorProps = useEditorState( - Substores.restOfEditor, - (store) => { - return { - lastFontSettings: store.editor.lastUsedFont, - mode: store.editor.mode, - packageStatus: store.editor.nodeModules.packageStatus, - propertyControlsInfo: store.editor.propertyControlsInfo, - } - }, - 'InsertMenu restOfEditorProps', - ) - - const selectedViews = useEditorState( - Substores.selectedViews, - (store) => store.editor.selectedViews, - 'InsertMenu selectedViews', - ) - - const canvasProps = useEditorState( - Substores.canvas, - (store) => { - return { - currentlyOpenFilename: store.editor.canvas.openFile?.filename ?? null, - canvasScale: store.editor.canvas.scale, - } - }, - 'InsertMenu canvasProps', - ) - - const roundedCanvasOffset = useEditorState( - Substores.canvasOffset, - (store) => store.editor.canvas.roundedCanvasOffset, - 'InsertMenu roundedCanvasOffset', - ) - - const projectContents = useEditorState( - Substores.projectContents, - (store) => store.editor.projectContents, - 'InsertMenu projectContents', - ) - - const dependencies = usePossiblyResolvedPackageDependencies() - - const propsWithDependencies: InsertMenuProps = { - ...restOfEditorProps, - ...canvasProps, - selectedViews: selectedViews, - canvasOffset: roundedCanvasOffset, - projectContents: projectContents, - dependencies: dependencies, - } - - return -}) - -type ElementBeingInserted = - | { - type: 'component' - importsToAdd: Imports - elementName: JSXElementName - props: JSXAttributes - } - | { - type: 'fragment' - } - | { - type: 'conditional' - } - | { - type: 'map' - } - -function componentBeingInserted( - importsToAdd: Imports, - elementName: JSXElementName, - props: JSXAttributes, -): ElementBeingInserted { - return { - type: 'component', - importsToAdd: importsToAdd, - elementName: elementName, - props: props, - } -} - -function elementBeingInserted(insertableComponent: InsertableComponent): ElementBeingInserted { - const element = insertableComponent.element() - switch (element.type) { - case 'JSX_CONDITIONAL_EXPRESSION': - return { type: 'conditional' } - case 'JSX_FRAGMENT': - return { type: 'fragment' } - case 'JSX_MAP_EXPRESSION': - return { type: 'map' } - case 'JSX_ELEMENT': - return componentBeingInserted(insertableComponent.importsToAdd, element.name, element.props) - default: - assertNever(element) - } -} - -export function elementBeingInsertedEquals( - first: ElementBeingInserted, - second: ElementBeingInserted, -): boolean { - if (first.type === 'component' && second.type === 'component') { - return ( - importsEquals(first.importsToAdd, second.importsToAdd) && - jsxElementNameEquals(first.elementName, second.elementName) - ) - } - - return first.type === second.type -} - -const enableInsertMode = ( - component: InsertableComponent, - newUID: string, - createInteractionSessionCommand: CanvasAction, - dispatch: EditorDispatch, -) => { - const element = component.element() - switch (element.type) { - case 'JSX_ELEMENT': { - const newElement = jsxElement( - element.name, - newUID, - setJSXAttributesAttribute( - addPositionAbsoluteToProps(element.props), - 'data-uid', - jsExpressionValue(newUID, emptyComments), - ), - element.children, - ) - - return dispatch( - [ - enableInsertModeForJSXElement( - newElement, - newUID, - component.importsToAdd, - component.defaultSize, - ), - createInteractionSessionCommand, - ], - 'everyone', - ) - } - case 'JSX_CONDITIONAL_EXPRESSION': { - return dispatch( - [ - enableInsertModeForJSXElement( - defaultDivElement(newUID), - newUID, - component.importsToAdd, - component.defaultSize, - { wrapInContainer: 'conditional' }, - ), - createInteractionSessionCommand, - ], - 'everyone', - ) - } - case 'JSX_FRAGMENT': - return dispatch( - [ - enableInsertModeForJSXElement( - defaultDivElement(newUID), - newUID, - component.importsToAdd, - component.defaultSize, - { wrapInContainer: 'fragment' }, - ), - createInteractionSessionCommand, - ], - 'everyone', - ) - case 'JSX_MAP_EXPRESSION': - return NO_OP() // we don't support draw to insert for maps - default: - assertNever(element) - } -} - -const Input = (props: InputProps) => { - return -} - -const Option = React.memo((props: OptionProps) => { - const dispatch = useDispatch() - const colorTheme = useColorTheme() - const component: InsertableComponent = props.data.value - const { isFocused } = props - const isActive: boolean = (props.selectProps as any).isActive - - const projectContents = useEditorState( - Substores.projectContents, - (store) => store.editor.projectContents, - 'CustomOption project contents', - ) - - const { canvasScale, canvasOffset } = useEditorState( - Substores.canvasOffset, - (store) => ({ - canvasScale: store.editor.canvas.scale, - canvasOffset: store.editor.canvas.roundedCanvasOffset, - }), - 'CustomOption canvas offsets', - ) - - const mode = React.useMemo(() => (props.selectProps as any).mode as Mode, [props.selectProps]) - - const currentlyBeingInserted = React.useMemo(() => { - if (mode === null || mode.type !== 'insert' || mode.subjects.length !== 1) { - return null - } - - const insertionSubject: InsertionSubject = mode.subjects[0] - - return componentBeingInserted( - insertionSubject.importsToAdd, - insertionSubject.element.name, - insertionSubject.element.props, - ) - }, [mode]) - - const insertItemOnMouseDown = React.useCallback( - (event: React.MouseEvent) => { - const mousePoint = windowToCanvasCoordinates( - canvasScale, - canvasOffset, - windowPoint(point(event.clientX, event.clientY)), - ).canvasPositionRounded - enableInsertMode( - component, - generateUidWithExistingComponents(projectContents), - CanvasActions.createInteractionSession( - createInteractionViaMouse( - mousePoint, - Modifier.modifiersForEvent(event), - boundingArea(), - 'zero-drag-permitted', - ), - ), - dispatch, - ) - }, - [dispatch, canvasOffset, canvasScale, projectContents, component], - ) - - const insertItemOnMouseUp = React.useCallback( - (_event: React.MouseEvent) => { - dispatch([CanvasActions.clearInteractionSession(false)], 'everyone') - }, - [dispatch], - ) - - const isComponentCurrentlyInserted = - currentlyBeingInserted != null && - elementBeingInsertedEquals(currentlyBeingInserted, elementBeingInserted(component)) - - const isSelected = React.useMemo(() => { - return ( - isComponentCurrentlyInserted || (isActive && isFocused && currentlyBeingInserted !== null) - ) - }, [isComponentCurrentlyInserted, isActive, isFocused, currentlyBeingInserted]) - - const [isHovered, setIsHovered] = useState(false) - const setIsHoveredTrue = React.useCallback(() => { - setIsHovered(true) - }, []) - - const setIsHoveredFalse = React.useCallback(() => { - setIsHovered(false) - }, []) - - return ( -
- - - {props.label} - -
- ) -}) - -type GroupOptionItem = { - label: string - options: ComponentOptionItem[] -} - -type ComponentOptionItem = { - label: string - source: string - value: InsertableComponent -} - -function useSelectStyles(hasResults: boolean): StylesConfig { - const colorTheme = useColorTheme() - return React.useMemo( - () => ({ - container: (styles): CSSObject => ({ - height: '100%', - }), - control: (styles): CSSObject => ({ - background: 'transparent', - outline: 'none', - ':focus-within': { - outline: 'none', - border: 'none', - }, - padding: 8, - }), - valueContainer: (styles): CSSObject => ({ - display: 'flex', - position: 'relative', - flexGrow: 1, - flexShrink: 0, - alignItems: 'center', - gap: 4, - }), - indicatorsContainer: (styles): CSSObject => ({ - display: 'none', - }), - menu: (styles): CSSObject => { - return { - marginTop: 8, - paddingLeft: 8, - paddingRight: 8, - height: '100%', - } - }, - menuList: (styles): CSSObject => { - return { - height: '100%', - overflow: 'scroll', - paddingBottom: 100, - display: 'flex', - flexDirection: 'column', - gap: 2, - paddingLeft: 8, - paddingRight: 8, - } - }, - input: (styles): CSSObject => { - return { - ...(InspectorInputEmotionStyle({ - hasLabel: false, - controlStyles: getControlStyles('simple'), - }) as CSSObject), - paddingLeft: 4, - backgroundColor: colorTheme.bg2.value, - flexGrow: 1, - display: 'flex', - alignItems: 'center', - cursor: 'text', - border: `1px solid ${hasResults ? 'transparent' : colorTheme.error.value}`, - } - }, - placeholder: (styles): CSSObject => { - return { - ...styles, - position: 'absolute', - marginLeft: 5, - } - }, - group: (): CSSObject => { - return { - display: 'flex', - flexDirection: 'column', - gap: 2, - } - }, - groupHeading: (styles): CSSObject => { - return { - display: 'flex', - alignItems: 'center', - height: UtopiaTheme.layout.rowHeight.smaller, - fontWeight: 700, - } - }, - }), - [colorTheme, hasResults], - ) -} - -const MenuList = React.memo((menuListProps: MenuListComponentProps) => { - const focusedOption: ComponentOptionItem | null = (menuListProps as any).focusedOption - const { selectProps } = menuListProps - - React.useEffect(() => { - selectProps.onFocusedOptionChange(focusedOption) - }, [focusedOption, selectProps]) - - return -}) - -const InsertMenuInner = React.memo((props: InsertMenuProps) => { - const dispatch = useDispatch() - const [filter, setFilter] = React.useState('') - - const insertableGroups = React.useMemo(() => { - if (props.currentlyOpenFilename == null) { - return [] - } - return moveSceneToTheBeginningAndSetDefaultSize( - getNonEmptyComponentGroups( - 'insert', - props.packageStatus, - props.propertyControlsInfo, - props.projectContents, - props.dependencies, - props.currentlyOpenFilename, - ), - ) - }, [ - props.packageStatus, - props.propertyControlsInfo, - props.projectContents, - props.dependencies, - props.currentlyOpenFilename, - ]) - - const options = React.useMemo((): GroupOptionItem[] => { - return insertableGroups.map((g) => { - const groupLabel = getInsertableGroupLabel(g.source) - return { - label: groupLabel, - options: g.insertableComponents.map((c): ComponentOptionItem => { - return { - label: c.name, - source: groupLabel, - value: c, - } - }), - } - }) - }, [insertableGroups]) - - const filterOption = createFilter({ - ignoreAccents: true, - stringify: (c) => c.data.source + c.data.label, - ignoreCase: true, - trim: true, - matchFrom: 'any', - }) - - const { hasResults } = React.useMemo(() => { - const filteredOptions = options - .flatMap((g) => g.options) - .filter((o) => filterOption({ data: o } as any, filter)) - return { - hasResults: filteredOptions.length > 0, - } - }, [options, filter, filterOption]) - - function onFilterChange(newValue: string, actionMeta: InputActionMeta) { - if (actionMeta.action !== 'input-blur' && actionMeta.action !== 'menu-close') { - setFilter(newValue.trim()) - } - } - - const [focusedOption, setFocusedOption] = React.useState(null) - - const onKeyDown = React.useCallback( - (e: React.KeyboardEvent) => { - setIsActive(true) - if (e.key === 'Escape') { - dispatch([setRightMenuTab(RightMenuTab.Inspector)]) - } - if (e.key === 'Enter' && focusedOption != null) { - enableInsertMode( - focusedOption.value, - generateUidWithExistingComponents(props.projectContents), - CanvasActions.createInteractionSession( - createInteractionViaMouse( - canvasPoint({ x: 0, y: 0 }), - emptyModifiers, - boundingArea(), - 'zero-drag-permitted', - ), - ), - dispatch, - ) - } - }, - [dispatch, props.projectContents, focusedOption], - ) - - const onChange = React.useCallback( - (e: ComponentOptionItem) => { - onFilterChange(e.label, { action: 'input-change' }) - - dispatch( - [ - CanvasActions.createInteractionSession( - createHoverInteractionViaMouse( - canvasPoint({ x: 0, y: 0 }), - emptyModifiers, - boundingArea(), - 'zero-drag-permitted', - ), - ), - ], - 'everyone', - ) - }, - [dispatch], - ) - - function alwaysTrue() { - return true - } - - const styles = useSelectStyles(hasResults) - - const [isActive, setIsActive] = React.useState(true) - function onMouseLeave() { - setIsActive(false) - } - function onMouseEnter() { - setIsActive(true) - } - - return ( -
- -
- ) -}) -InsertMenuInner.displayName = 'InsertMenuInner' - -function addPositionAbsoluteToProps(props: JSXAttributes) { - const styleAttributes = getJSXAttribute(props, 'style') ?? jsExpressionValue({}, emptyComments) - - const updatedStyleAttrs = setJSXValueInAttributeAtPath( - styleAttributes, - PP.fromString('position'), - jsExpressionValue('absolute', emptyComments), - ) - - if (isLeft(updatedStyleAttrs)) { - throw new Error(`Problem setting position absolute on an element we just created.`) - } - - return setJSXAttributesAttribute(props, 'style', updatedStyleAttrs.value) -} - -interface InsertGroupProps { - label: string - subLabel?: string - dependencyStatus: PackageStatus - dependencyVersion: string | null -} - -export const InsertGroup: React.FunctionComponent> = - React.memo((props) => { - const colorTheme = useColorTheme() - return ( -
- - -
- {props.label} -
- {props.subLabel == null ? null : ( -
- {props.subLabel} -
- )} -
-
- -
-
-
- {props.children} -
-
- ) - }) diff --git a/editor/src/components/navigator/insert-menu-pane.tsx b/editor/src/components/navigator/insert-menu-pane.tsx deleted file mode 100644 index c12e763a710f..000000000000 --- a/editor/src/components/navigator/insert-menu-pane.tsx +++ /dev/null @@ -1,62 +0,0 @@ -/** @jsxRuntime classic */ -/** @jsx jsx */ -/** @jsxFrag React.Fragment */ -import { jsx } from '@emotion/react' -import React from 'react' -import { Section, SectionBodyArea } from '../../uuiui' -import { setFocus } from '../common/actions' -import type { EditorDispatch, LoginState } from '../editor/action-types' -import { InsertMenu } from '../editor/insertmenu' -import { useDispatch } from '../editor/store/dispatch-context' -import type { DerivedState, EditorState } from '../editor/store/editor-state' -import { RightMenuTab } from '../editor/store/editor-state' -import { Substores, useEditorState } from '../editor/store/store-hook' -import { setRightMenuTab } from '../editor/actions/action-creators' -import { unless, when } from '../../utils/react-conditionals' -import { IS_TEST_ENVIRONMENT } from '../../common/env-vars' - -export interface LeftPaneProps { - editorState: EditorState - derivedState: DerivedState - editorDispatch: EditorDispatch - loginState: LoginState -} - -export const InsertMenuPane = React.memo(() => { - const dispatch = useDispatch() - const { focusedPanel } = useEditorState( - Substores.restOfEditor, - (store) => { - return { - focusedPanel: store.editor.focusedPanel, - } - }, - 'InsertMenuPane', - ) - - const onFocus = React.useCallback( - (event: React.FocusEvent) => { - if (focusedPanel !== 'insertmenu') { - dispatch([setFocus('insertmenu')], 'everyone') - } - }, - [dispatch, focusedPanel], - ) - - const onClickClose = React.useCallback(() => { - dispatch([setRightMenuTab(RightMenuTab.Inspector)]) - }, [dispatch]) - - return ( -
- - {when(IS_TEST_ENVIRONMENT, )} - -
- ) -}) diff --git a/editor/src/templates/editor-canvas.tsx b/editor/src/templates/editor-canvas.tsx index efb210aebf9b..381df809eb84 100644 --- a/editor/src/templates/editor-canvas.tsx +++ b/editor/src/templates/editor-canvas.tsx @@ -104,7 +104,6 @@ import { CursorComponent } from '../components/canvas/controls/select-mode/curso import * as ResizeObserverSyntheticDefault from 'resize-observer-polyfill' import { isFeatureEnabled } from '../utils/feature-switches' import { getCanvasViewportCenter } from './paste-helpers' -import { InsertMenuId } from '../components/editor/insertmenu' import { DataPasteHandler, isPasteHandler } from '../utils/paste-handler' const ResizeObserver = ResizeObserverSyntheticDefault.default ?? ResizeObserverSyntheticDefault @@ -807,8 +806,7 @@ export class EditorCanvas extends React.Component { (event.nativeEvent != null && event.nativeEvent.srcElement != null && (isTargetContextMenu(event.nativeEvent.target as any) || - isTargetInPopup(event.nativeEvent.srcElement as any, this.props.editor.openPopupId) || - isTargetInInsertMenu(event.nativeEvent.target as any))) || + isTargetInPopup(event.nativeEvent.srcElement as any, this.props.editor.openPopupId))) || this.props.editor.modal !== null ) { return [] // This is a hack implementing a behavior when context menu blocks the UI @@ -1404,17 +1402,3 @@ function isTargetInPopup(target: HTMLElement, popupId: string | null): boolean { return popupElement != null && popupElement.contains(target) } } - -function isTargetInInsertMenu(target: HTMLElement | null): boolean { - /** - * this hack is incredibly sad, - * the problem is insertmenu.tsx has non-standard mouse handling. - * the real solution would be to rewrite the mouse handling code in the insert menu, - * but I don't have the time to do it now - * - * the way I would change the insert menu is to only start the insert mode if the mouse dragged past a threshold instead of immediately starting it, - * plus I would also _enter_ insert mode on click similar to how we enter insert mode from the insert TopMenu - */ - const insertMenu = document.getElementById(InsertMenuId) - return insertMenu != null && insertMenu.contains(target) -} From 64848d8d3479d7678749c03b43d58cd2e77fc92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Tue, 4 Jun 2024 12:19:02 +0200 Subject: [PATCH 019/103] Icon for radio control options. (#5801) ## Problem https://github.com/concrete-utopia/utopia/issues/5782 ## Fix Extend the API. Example: ``` orientation: Utopia.radioControl([ { label: 'Vertical', value: 'column', icon: 'arrow-down' }, { label: 'Horizontal', value: 'row', icon: 'arrow-right' }, ]), ``` ### Details - added a new icon set for icons that can be used in property controls - added `RadioControlOption` as more idiomatic substitute to `AllowedEnumType[] | BasicControlOptionWithIcon[]` - added the requisite parsing/validation for the radio control description ### Scope This PR adds the component api change, and a follow-up PR will add the actual under-the-hood change that interprets the radio button descriptor and puts the correct icons in the segment (radio) control ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../custom-code/internal-property-controls.ts | 15 +++- .../property-control-controls.tsx | 29 +++++- .../property-control-values.spec.ts | 8 +- .../property-controls-local.ts | 89 +++++++++++++++++++ .../property-controls/property-controls.ts | 13 ++- 5 files changed, 144 insertions(+), 10 deletions(-) diff --git a/editor/src/components/custom-code/internal-property-controls.ts b/editor/src/components/custom-code/internal-property-controls.ts index d9f723f7594e..659b64b5aed3 100644 --- a/editor/src/components/custom-code/internal-property-controls.ts +++ b/editor/src/components/custom-code/internal-property-controls.ts @@ -1,5 +1,6 @@ import type { CSSProperties } from 'react' import type { ComponentInfo } from './code-file' +import type { PropertyControlIcon } from 'utopia-api/core' interface GenericControlProps { label?: string @@ -46,7 +47,16 @@ export interface BasicControlOption { label: string } +export interface BasicControlOptionWithIcon { + value: T + label: string + icon: PropertyControlIcon | null +} + export type BasicControlOptions = AllowedEnumType[] | BasicControlOption[] +export type RadioControlOption = + | { type: 'allowed-enum-type'; allowedEnumType: AllowedEnumType } + | { type: 'control-option-with-icon'; option: BasicControlOptionWithIcon } export interface PopUpListControlDescription extends GenericControlProps> { @@ -118,10 +128,9 @@ export interface NumberInputControlDescription extends GenericControlProps> { +export interface RadioControlDescription extends GenericControlProps> { control: 'radio' - options: BasicControlOptions + options: Array> } export interface ExpressionInputControlDescription extends GenericControlProps { diff --git a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx index 638237158077..add3ad9c2b51 100644 --- a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx +++ b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx @@ -18,6 +18,7 @@ import type { NumberInputControlDescription, PopUpListControlDescription, RadioControlDescription, + RadioControlOption, RegularControlDescription, RegularControlType, StringInputControlDescription, @@ -384,6 +385,28 @@ export const NumberInputPropertyControl = React.memo( }, ) +function valueFromRadioControlOption(option: RadioControlOption): unknown { + switch (option.type) { + case 'allowed-enum-type': + return option.allowedEnumType + case 'control-option-with-icon': + return option.option.value + default: + assertNever(option) + } +} + +function labelFromRadioControlOption(option: RadioControlOption): string { + switch (option.type) { + case 'allowed-enum-type': + return `${option.allowedEnumType}` + case 'control-option-with-icon': + return option.option.label + default: + assertNever(option) + } +} + export const RadioPropertyControl = React.memo( (props: ControlForPropProps) => { const { propName, propMetadata, controlDescription } = props @@ -392,13 +415,13 @@ export const RadioPropertyControl = React.memo( const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined // TS baulks at the map below for some reason if we don't first do this - const controlOptions: Array = controlDescription.options + const controlOptions: RadioControlDescription['options'] = controlDescription.options const options: Array> = useKeepReferenceEqualityIfPossible( controlOptions.map((option) => { return { - value: valueForIndividualOption(option), - label: labelForIndividualOption(option), + value: valueFromRadioControlOption(option), + label: labelFromRadioControlOption(option), } }), ) diff --git a/editor/src/core/property-controls/property-control-values.spec.ts b/editor/src/core/property-controls/property-control-values.spec.ts index be022af11c6d..3c69970faba8 100644 --- a/editor/src/core/property-controls/property-control-values.spec.ts +++ b/editor/src/core/property-controls/property-control-values.spec.ts @@ -177,8 +177,12 @@ describe('RadioControlDescription', () => { control: 'radio', options: [ { - value: validValue, - label: 'Label', + type: 'control-option-with-icon', + option: { + value: validValue, + label: 'Label', + icon: null, + }, }, ], } diff --git a/editor/src/core/property-controls/property-controls-local.ts b/editor/src/core/property-controls/property-controls-local.ts index b3eaf1160e86..f688a5f9378b 100644 --- a/editor/src/core/property-controls/property-controls-local.ts +++ b/editor/src/core/property-controls/property-controls-local.ts @@ -2,6 +2,9 @@ import type { RegularControlDescription as RegularControlDescriptionFromUtopia, JSXControlDescription as JSXControlDescriptionFromUtopia, PropertyControls as PropertyControlsFromUtopiaAPI, + RadioControlDescription as RadioControlDescriptionFromUtopia, + AllowedEnumType as AllowedEnumTypeFromUtopia, + BasicControlOptionWithIcon as BasicControlOptionWithIconFromUtopia, ComponentToRegister, ComponentInsertOption, ComponentExample, @@ -26,6 +29,8 @@ import type { RegularControlDescription, JSXControlDescription, PreferredChildComponentDescriptor, + RadioControlDescription, + RadioControlOption, } from '../../components/custom-code/internal-property-controls' import { packageJsonFileFromProjectContents, walkContentsTree } from '../../components/assets' import { @@ -65,6 +70,7 @@ import { foldEither, forEachRight, isLeft, + isRight, left, mapEither, right, @@ -743,6 +749,86 @@ async function parseJSXControlDescription( }) } +function parseAllowedEnumType(option: AllowedEnumTypeFromUtopia): RadioControlOption { + return { type: 'allowed-enum-type', allowedEnumType: option } +} + +function parseBasicControlOptionWithIcon( + option: BasicControlOptionWithIconFromUtopia, +): RadioControlOption { + return { + type: 'control-option-with-icon', + option: { + label: option.label, + value: option.value, + icon: option.icon ?? null, + }, + } +} + +function isAllowedEnumType( + option: AllowedEnumTypeFromUtopia | BasicControlOptionWithIconFromUtopia, +): option is AllowedEnumTypeFromUtopia { + return ( + typeof option === 'string' || + typeof option === 'boolean' || + typeof option === 'number' || + typeof option === 'undefined' || + (typeof option === 'object' && option === null) + ) +} + +function parseRadioControlOptions( + options: AllowedEnumTypeFromUtopia[] | BasicControlOptionWithIconFromUtopia[], +): Either[]> { + const allowedEnumTypes = sequenceEither( + options.map( + (o): Either> => + isAllowedEnumType(o) ? right(parseAllowedEnumType(o)) : left('Not an allowed enum type'), + ), + ) + + if (isRight(allowedEnumTypes)) { + return allowedEnumTypes + } + + const basicControlOptions = sequenceEither( + options.map( + (o): Either> => + isAllowedEnumType(o) + ? left('Not a BasicControlOptionWithIcon>') + : right(parseBasicControlOptionWithIcon(o)), + ), + ) + + if (isRight(basicControlOptions)) { + return basicControlOptions + } + + return left('Cannot mix AllowedEnumType and BasicControlOptionWithIcon') +} + +async function parseRadioControlDescription( + descriptor: RadioControlDescriptionFromUtopia, +): Promise> { + const options = parseRadioControlOptions(descriptor.options) + if (isLeft(options)) { + return options + } + + return right({ + control: descriptor.control, + label: descriptor.label, + visibleByDefault: descriptor.visibleByDefault, + options: options.value, + required: descriptor.required, + defaultValue: isAllowedEnumType(descriptor.defaultValue) + ? parseAllowedEnumType(descriptor.defaultValue) + : parseBasicControlOptionWithIcon(descriptor.defaultValue), + folder: descriptor.folder, + }) +} + async function makeRegularControlDescription( descriptor: RegularControlDescriptionFromUtopia, context: { moduleName: string; workers: UtopiaTsWorkers }, @@ -752,6 +838,9 @@ async function makeRegularControlDescription( const parsedJSXControlDescription = parseJSXControlDescription(descriptor, context) return parsedJSXControlDescription } + if (descriptor.control === 'radio') { + return parseRadioControlDescription(descriptor) + } return right(descriptor) } switch (descriptor.control) { diff --git a/utopia-api/src/property-controls/property-controls.ts b/utopia-api/src/property-controls/property-controls.ts index cb1a93e40933..c03c98fecfaf 100644 --- a/utopia-api/src/property-controls/property-controls.ts +++ b/utopia-api/src/property-controls/property-controls.ts @@ -12,6 +12,9 @@ interface ControlBaseFields { folder?: string } +export const PropertyControlIcons = ['arrow-left', 'arrow-right', 'arrow-up', 'arrow-down'] as const +export type PropertyControlIcon = (typeof PropertyControlIcons)[number] + // Base Level Controls export type BaseControlType = @@ -60,6 +63,12 @@ export interface BasicControlOption { label: string } +export interface BasicControlOptionWithIcon { + value: T + label: string + icon?: PropertyControlIcon +} + export type BasicControlOptions = AllowedEnumType[] | BasicControlOption[] export interface PopUpListControlDescription { @@ -164,9 +173,9 @@ export interface RadioControlDescription { control: 'radio' label?: string visibleByDefault?: boolean - options: BasicControlOptions + options: AllowedEnumType[] | BasicControlOptionWithIcon[] required?: boolean - defaultValue?: AllowedEnumType | BasicControlOption + defaultValue?: AllowedEnumType | BasicControlOptionWithIcon folder?: string } From febab34d500f2f7e5a146607fdfdb9d33c1a400f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Tue, 4 Jun 2024 15:16:18 +0200 Subject: [PATCH 020/103] Trace variable to a literal-valued declaration in the arbitrary js block. (#5822) ## Problem Consider the following code ```tsx function App() { const label = 'yes' const loaded = true const words = ['hello', 'cheese'] const deeplyNestedObject = { very: { deep: { title: {value: ['hello', 'world'] } }, a: [1, 2] } } const { very } = deeplyNestedObject return } ``` Due to a missing feature, the data tracing code can't recognise `label` (and similar literal-valued declarations) as literals. ## Fix Detect this situation and return a data tracing result for it ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/data-selector-modal.tsx | 1 + .../core/data-tracing/data-tracing.spec.ts | 112 ++++++++++++++++++ editor/src/core/data-tracing/data-tracing.ts | 53 +++++++++ 3 files changed, 166 insertions(+) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index dd4888e9fcaa..f4934041fe40 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -301,6 +301,7 @@ export const DataSelectorModal = React.memo( result[variable.valuePath.toString()] = 'external' break case 'literal-attribute': + case 'literal-assignment': result[variable.valuePath.toString()] = 'literal' break case 'component-prop': diff --git a/editor/src/core/data-tracing/data-tracing.spec.ts b/editor/src/core/data-tracing/data-tracing.spec.ts index 3853c181886b..a466967dd45e 100644 --- a/editor/src/core/data-tracing/data-tracing.spec.ts +++ b/editor/src/core/data-tracing/data-tracing.spec.ts @@ -19,6 +19,7 @@ import { dataTracingFailed, dataTracingToAHookCall, dataTracingToElementAtScope, + dataTracingToLiteralAssignment, dataTracingToLiteralAttribute, traceDataFromElement, traceDataFromProp, @@ -1255,6 +1256,117 @@ describe('Data Tracing', () => { ) } }) + + it('can to a literal-valued variable in the arbitrary js block', async () => { + const editor = await renderTestEditorWithCode( + makeTestProjectCodeWithStoryboard(` + function MyComponent({ doc }) { + + const valueFromTheDeep = doc.title.value + + return

{doc.title.value}

+ } + + function App() { + const label = 'yes' + const loaded = true + const words = ['hello', 'cheese'] + const deeplyNestedObject = { very: { deep: { title: {value: ['hello', 'world'] } }, a: [1, 2] } } + const { very } = deeplyNestedObject + + return + } + `), + 'await-first-dom-report', + ) + + await focusOnComponentForTest(editor, EP.fromString('sb/app:my-component')) + + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component'), + 'label', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToLiteralAssignment(EP.fromString('sb/app:my-component'), dataPathSuccess([])), + ) + } + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component'), + 'loaded', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToLiteralAssignment(EP.fromString('sb/app:my-component'), dataPathSuccess([])), + ) + } + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component'), + 'words', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToLiteralAssignment(EP.fromString('sb/app:my-component'), dataPathSuccess([])), + ) + } + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component'), + 'deeplyNestedObject', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToLiteralAssignment(EP.fromString('sb/app:my-component'), dataPathSuccess([])), + ) + } + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component'), + 'very', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToLiteralAssignment( + EP.fromString('sb/app:my-component'), + dataPathSuccess(['very']), + ), + ) + } + { + const trace = traceDataFromVariableName( + EP.fromString('sb/app:my-component:component-root'), + 'valueFromTheDeep', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess([]), + ) + + expect(trace).toEqual( + dataTracingToLiteralAssignment( + EP.fromString('sb/app:my-component'), + dataPathSuccess(['very', 'deep', 'title', 'value']), + ), + ) + } + }) }) }) diff --git a/editor/src/core/data-tracing/data-tracing.ts b/editor/src/core/data-tracing/data-tracing.ts index cdd420c54886..43707f56b346 100644 --- a/editor/src/core/data-tracing/data-tracing.ts +++ b/editor/src/core/data-tracing/data-tracing.ts @@ -13,6 +13,8 @@ import type { IdentifierOrAccess, JSAssignment, JSExpression, + JSExpressionNestedArray, + JSExpressionNestedObject, JSIdentifier, JSXElementChild, Param, @@ -120,6 +122,23 @@ export function dataTracingToLiteralAttribute( } } +export type DataTracingToLiteralAssignment = { + type: 'literal-assignment' + elementPath: ElementPath + dataPathIntoAttribute: DataPathPositiveResult +} + +export function dataTracingToLiteralAssignment( + elementPath: ElementPath, + dataPathIntoAttribute: DataPathPositiveResult, +): DataTracingToLiteralAssignment { + return { + type: 'literal-assignment', + elementPath: elementPath, + dataPathIntoAttribute: dataPathIntoAttribute, + } +} + export type DataTracingToElementAtScope = { type: 'element-at-scope' scope: ElementPath @@ -188,6 +207,7 @@ export function dataTracingFailed(reason: string): DataTracingFailed { export type DataTracingResult = | DataTracingToLiteralAttribute + | DataTracingToLiteralAssignment | DataTracingToAHookCall | DataTracingToAComponentProp | DataTracingToElementAtScope @@ -819,6 +839,10 @@ function lookupInComponentScope( pathDrillSoFar, ) } + + if (isConsideredLiteralValue(foundAssignmentOfIdentifier.rightHandSide)) { + return dataTracingToLiteralAssignment(componentPath, pathDrillSoFar) + } } } @@ -873,3 +897,32 @@ function lookupInComponentScope( function substractFromStringNumber(n: string, minus: number): string { return `${parseInt(n) - minus}` } + +function isConsideredLiteralValue(value: JSExpression): boolean { + switch (value.type) { + case 'ATTRIBUTE_VALUE': + return true + case 'ATTRIBUTE_NESTED_ARRAY': + return isArrayLiteral(value) + case 'ATTRIBUTE_NESTED_OBJECT': + return isObjectLiteral(value) + case 'ATTRIBUTE_FUNCTION_CALL': + case 'ATTRIBUTE_OTHER_JAVASCRIPT': + case 'JSX_ELEMENT': + case 'JSX_MAP_EXPRESSION': + case 'JS_ELEMENT_ACCESS': + case 'JS_IDENTIFIER': + case 'JS_PROPERTY_ACCESS': + return false + default: + assertNever(value) + } +} + +function isArrayLiteral(array: JSExpressionNestedArray): boolean { + return array.content.every((c) => isConsideredLiteralValue(c.value)) +} + +function isObjectLiteral(value: JSExpressionNestedObject): boolean { + return value.content.every((c) => isConsideredLiteralValue(c.value)) +} From 47ac149b0bd9a0c79f39cf04eea1bba3b1fd8974 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Tue, 4 Jun 2024 15:33:43 +0200 Subject: [PATCH 021/103] Data Picker: be able to pick global variables (#5790) **Problem:** Globally declared variables were missing from the data picker. To investigate, I created a sample project with nested scopes and I've identified two missing cases, the first one is: globally declared variables in the code file. I had to re-acquaint myself with the render-core-element codebase, and with @seanparsons 's help I realized what we are missing was `runBlockUpdatingScope` returning spied variables. **Fix:** The solution was to extend the file-scope-level `mutableContext` and add a new field `spiedVariablesDeclaredInRootScope: VariableData` in there. **Commit Details:** - Added a new FileRootPath type so it's now `insertionCeiling: FileRootPath | ElementPath`, this lets us not use `null` or `EP.emptyPath` as the "file root" reference - New easier-to-read test case in `scoped-variables.spec.tsx` - runBlockUpdatingScope returns `spiedVariablesDeclaredWithinBlock: VariableData` - feed spiedVariablesDeclaredWithinBlock into `mutableContext.spiedVariablesDeclaredInRootScope` - extend `spiedVariablesInScope` in `createComponentRendererComponent` to include the root scope variables **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../strategies/reparent-utils.ts | 7 +- .../canvas/scoped-variables.spec.tsx | 177 +++++++++++++++++- .../ui-jsx-canvas-component-renderer.tsx | 28 +-- .../ui-jsx-canvas-contexts.tsx | 2 + .../ui-jsx-canvas-execution-scope.tsx | 18 +- .../ui-jsx-canvas-scope-utils.ts | 12 +- .../src/components/canvas/ui-jsx-canvas.tsx | 27 ++- .../editor/actions/actions.spec.tsx | 2 +- .../component-section/data-picker-popup.tsx | 2 +- .../component-section/data-picker-utils.tsx | 13 +- .../component-section/data-selector-modal.tsx | 40 ++-- .../variables-in-scope-utils.spec.ts | 3 + .../variables-in-scope-utils.ts | 42 ++++- .../component-picker-context-menu.tsx | 2 +- .../navigator-item/component-picker.tsx | 3 +- .../project-components.spec.ts.snap | 56 ++++-- .../components/shared/project-components.ts | 15 +- .../src/components/shared/scoped-variables.ts | 4 +- editor/src/core/data-tracing/data-tracing.ts | 6 +- .../model/element-metadata.spec.browser2.tsx | 16 ++ editor/src/core/shared/element-template.ts | 12 +- 21 files changed, 401 insertions(+), 86 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/strategies/reparent-utils.ts b/editor/src/components/canvas/canvas-strategies/strategies/reparent-utils.ts index 93f98bcc26ab..c71c406e3d3b 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/reparent-utils.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/reparent-utils.ts @@ -61,6 +61,7 @@ import { renameDuplicateImports } from '../../../../core/shared/import-shared-ut import { set } from '../../../../core/shared/optics/optic-utilities' import { fromField, fromTypeGuard } from '../../../../core/shared/optics/optic-creators' import type { PropertyControlsInfo } from '../../../custom-code/code-file' +import type { FileRootPath } from '../../ui-jsx-canvas' interface GetReparentOutcomeResult { commands: Array @@ -614,10 +615,10 @@ export function applyElementCeilingToReparentTarget( elementsToInsert: JSXElementChild[], elementPathTree: ElementPathTrees, reparentTarget: Either, - elementCeiling: ElementPath | null, + elementCeiling: ElementPath | FileRootPath, propertyControlsInfo: PropertyControlsInfo, ): Either { - if (elementCeiling == null) { + if (elementCeiling.type === 'file-root') { return reparentTarget } else { return flatMapEither((targetForPaste) => { @@ -669,7 +670,7 @@ export function getTargetParentForOneShotInsertion( metadata: ElementInstanceMetadataMap, elementsToInsert: JSXElementChild[], elementPathTree: ElementPathTrees, - insertionCeiling: ElementPath | null, + insertionCeiling: ElementPath | FileRootPath, propertyControlsInfo: PropertyControlsInfo, ): Either { if (!isNonEmptyArray(selectedViews)) { diff --git a/editor/src/components/canvas/scoped-variables.spec.tsx b/editor/src/components/canvas/scoped-variables.spec.tsx index b2e40cdfaa09..32ad1b337d5f 100644 --- a/editor/src/components/canvas/scoped-variables.spec.tsx +++ b/editor/src/components/canvas/scoped-variables.spec.tsx @@ -1,5 +1,9 @@ +import json5 from 'json5' import { createBuiltInDependenciesList } from '../../core/es-modules/package-manager/built-in-dependencies-list' import { getSamplePreviewFile, getSamplePreviewHTMLFile } from '../../core/model/new-project-files' +import * as EP from '../../core/shared/element-path' +import { objectMap } from '../../core/shared/object-utils' +import { optionalMap } from '../../core/shared/optional-utils' import type { ProjectContents, TextFile } from '../../core/shared/project-file-types' import { textFile, @@ -9,6 +13,7 @@ import { directory, } from '../../core/shared/project-file-types' import { complexDefaultProjectPreParsed } from '../../sample-projects/sample-project-utils.test-utils' +import type { ProjectContentTreeRoot } from '../assets' import { contentsToTree } from '../assets' import type { PersistentModel } from '../editor/store/editor-state' import { @@ -16,7 +21,12 @@ import { StoryboardFilePath, persistentModelForProjectContents, } from '../editor/store/editor-state' -import { DefaultStartingFeatureSwitches, renderTestEditorWithModel } from './ui-jsx.test-utils' +import { insertionCeilingToString, type VariableData, type VariableMetadata } from './ui-jsx-canvas' +import { + DefaultStartingFeatureSwitches, + renderTestEditorWithModel, + renderTestEditorWithProjectContent, +} from './ui-jsx.test-utils' function projectWithInlineComponentContents(): ProjectContents { function createCodeFile(path: string, contents: string): TextFile { @@ -210,7 +220,172 @@ function projectWithInlineComponentDestructured(): PersistentModel { return persistentModel } +function projectWithDeepNestedScopes(): ProjectContentTreeRoot { + function createCodeFile(contents: string): TextFile { + return textFile(textFileContents(contents, unparsed, RevisionsState.CodeAhead), null, null, 0) + } + + return contentsToTree({ + '/package.json': textFile( + textFileContents( + JSON.stringify(DefaultPackageJson, null, 2), + unparsed, + RevisionsState.CodeAhead, + ), + null, + null, + 0, + ), + '/src': directory(), + '/assets': directory(), + '/public': directory(), + [StoryboardFilePath]: createCodeFile( + `import * as React from 'react' + import Utopia, { + Scene, + Storyboard, + } from 'utopia-api' + import { App } from '/src/app.js' + + export var storyboard = ( + + + + + + )`, + ), + '/src/app.js': createCodeFile( + `import * as React from 'react' + + const globalVar = ['alap'] + + export var App = ({ style }) => { + const localVar = ['local'] + return ( +
+ { + // @utopia/uid=globalVarMap + globalVar.map((global) => ( +
+ { + // @utopia/uid=localVarMap + localVar.map((local) => ( +
+ { + // @utopia/uid=firstMap + ['a', 'b', 'c'].map((first) => ( +
+ { + // @utopia/uid=secondMap + [1, 2, 3].map((second) => ( +
+ {(() => { + const innerVar = ['cica', 'kutya'] + // @utopia/uid=innerVarMap + return innerVar.map((inner) => { + return ( +
+ {global} -{local} -{first} - + {second} -{inner} +
+ ) + }) + })()} +
+ ))} +
+ ))} +
+ ))} +
+ ))} +
+ ) + } + `, + ), + }) +} + +function prettyPrintVariableData(variableData: VariableData) { + function prettyPrintVariableMetadata(variableMetadata: VariableMetadata) { + return { + spiedValue: JSON.stringify(variableMetadata.spiedValue, null, 2), + insertionCeiling: insertionCeilingToString(variableMetadata.insertionCeiling), + } + } + + return objectMap(prettyPrintVariableMetadata, variableData) +} + describe('scoped variables', () => { + it('project with deep nested scopes works', async () => { + const renderResult = await renderTestEditorWithProjectContent( + projectWithDeepNestedScopes(), + 'dont-await-first-dom-report', + ) + + const spiedVarsInScopeForInnermostElement = prettyPrintVariableData( + renderResult.getEditorState().editor.variablesInScope[ + 'storyboard-entity/scene-1-entity/app-entity:app-root/globalvarmap/div1~~~1/localvarmap/div2~~~1/firstmap/div3~~~1/secondmap/div4~~~1/5d9/div5~~~1' + ], + ) + + expect(spiedVarsInScopeForInnermostElement).toMatchInlineSnapshot(` + Object { + "first": Object { + "insertionCeiling": "storyboard-entity/scene-1-entity/app-entity:app-root/globalvarmap/div1~~~1/localvarmap/div2~~~1/firstmap/div3~~~1", + "spiedValue": "\\"a\\"", + }, + "global": Object { + "insertionCeiling": "storyboard-entity/scene-1-entity/app-entity:app-root/globalvarmap/div1~~~1", + "spiedValue": "\\"alap\\"", + }, + "globalVar": Object { + "insertionCeiling": "file-root", + "spiedValue": "[ + \\"alap\\" + ]", + }, + "local": Object { + "insertionCeiling": "storyboard-entity/scene-1-entity/app-entity:app-root/globalvarmap/div1~~~1/localvarmap/div2~~~1", + "spiedValue": "\\"local\\"", + }, + "localVar": Object { + "insertionCeiling": "storyboard-entity/scene-1-entity/app-entity:app-root", + "spiedValue": "[ + \\"local\\" + ]", + }, + "second": Object { + "insertionCeiling": "storyboard-entity/scene-1-entity/app-entity:app-root/globalvarmap/div1~~~1/localvarmap/div2~~~1/firstmap/div3~~~1/secondmap/div4~~~1", + "spiedValue": "1", + }, + "style": Object { + "insertionCeiling": "storyboard-entity/scene-1-entity/app-entity:app-root", + "spiedValue": undefined, + }, + } + `) + + // TODO: these should not be undefined, to be fixed in a follow up PR: + expect(spiedVarsInScopeForInnermostElement['innerVar']).toMatchInlineSnapshot(`undefined`) + expect(spiedVarsInScopeForInnermostElement['inner']).toMatchInlineSnapshot(`undefined`) + }) + it('includes scoped variables for an inline component destructuring the parameter', async () => { const renderResult = await renderTestEditorWithModel( projectWithInlineComponentDestructured(), diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx index 77ac87ae5c79..2cb0891afbd9 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-component-renderer.tsx @@ -131,6 +131,8 @@ export function createComponentRendererComponent(params: { instancePath, ) + // TODO we should throw an error if rootElementPath is null + let codeError: Error | null = null const appliedProps = optionalMap( @@ -158,7 +160,7 @@ export function createComponentRendererComponent(params: { code: code, highlightBounds: highlightBounds, editedText: rerenderUtopiaContext.editedText, - variablesInScope: {}, + variablesInScope: mutableContext.spiedVariablesDeclaredInRootScope, filePathMappings: rerenderUtopiaContext.filePathMappings, }, undefined, @@ -172,20 +174,16 @@ export function createComponentRendererComponent(params: { ...appliedProps, } - let spiedVariablesInScope: VariableData = {} + let spiedVariablesInScope: VariableData = { + ...mutableContext.spiedVariablesDeclaredInRootScope, + } if (rootElementPath != null && utopiaJsxComponent.param != null) { - spiedVariablesInScope = mapArrayToDictionary( - propertiesExposedByParam(utopiaJsxComponent.param), - (paramName) => { - return paramName - }, - (paramName) => { - return { - spiedValue: scope[paramName], - insertionCeiling: rootElementPath, - } - }, - ) + propertiesExposedByParam(utopiaJsxComponent.param).forEach((paramName) => { + spiedVariablesInScope[paramName] = { + spiedValue: scope[paramName], + insertionCeiling: rootElementPath, + } + }) } // Protect against infinite recursion by taking the view that anything @@ -259,6 +257,7 @@ export function createComponentRendererComponent(params: { applyBlockReturnFunctions(scope) const arbitraryBlockResult = runBlockUpdatingScope( + rootElementPath, params.filePath, mutableContext.requireResult, utopiaJsxComponent.arbitraryJSBlock, @@ -270,6 +269,7 @@ export function createComponentRendererComponent(params: { if (rootElementPath != null) { spiedVariablesInScope = { ...spiedVariablesInScope, + ...arbitraryBlockResult.spiedVariablesDeclaredWithinBlock, ...objectMap( (spiedValue) => ({ spiedValue: spiedValue, diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-contexts.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-contexts.tsx index 6e33e1425683..f223928216b2 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-contexts.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-contexts.tsx @@ -7,6 +7,7 @@ import { left } from '../../../core/shared/either' import type { ElementPath } from '../../../core/shared/project-file-types' import type { ProjectContentTreeRoot } from '../../assets' import type { TransientFilesState, UIFileBase64Blobs } from '../../editor/store/editor-state' +import type { VariableData } from '../ui-jsx-canvas' import type { FilePathMappings } from '../../../core/model/project-file-utils' export interface MutableUtopiaCtxRefData { @@ -15,6 +16,7 @@ export interface MutableUtopiaCtxRefData { requireResult: MapLike fileBlobs: UIFileBase64Blobs rootScope: MapLike + spiedVariablesDeclaredInRootScope: VariableData jsxFactoryFunctionName: string | null } } diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx index 2c2ab7b637a7..f188450fd076 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx @@ -22,7 +22,11 @@ import { import { createLookupRender, utopiaCanvasJSXLookup } from './ui-jsx-canvas-element-renderer-utils' import { runBlockUpdatingScope } from './ui-jsx-canvas-scope-utils' import * as EP from '../../../core/shared/element-path' -import type { DomWalkerInvalidatePathsCtxData, UiJsxCanvasContextData } from '../ui-jsx-canvas' +import type { + DomWalkerInvalidatePathsCtxData, + UiJsxCanvasContextData, + VariableData, +} from '../ui-jsx-canvas' import type { ElementPath, HighlightBoundsForUids } from '../../../core/shared/project-file-types' import { isParseSuccess, isTextFile } from '../../../core/shared/project-file-types' import { defaultIfNull, optionalFlatMap } from '../../../core/shared/optional-utils' @@ -125,6 +129,8 @@ export function createExecutionScope( ...topLevelComponentRendererComponentsForFile, } + let spiedVariablesInRoot: VariableData = {} + // First make sure everything is in scope if (combinedTopLevelArbitraryBlock != null && openStoryboardFileNameKILLME != null) { const { highlightBounds, code } = getCodeAndHighlightBoundsForFile(filePath, projectContents) @@ -164,7 +170,14 @@ export function createExecutionScope( ) applyBlockReturnFunctions(executionScope) - runBlockUpdatingScope(filePath, requireResult, combinedTopLevelArbitraryBlock, executionScope) + const { spiedVariablesDeclaredWithinBlock } = runBlockUpdatingScope( + { type: 'file-root' }, + filePath, + requireResult, + combinedTopLevelArbitraryBlock, + executionScope, + ) + spiedVariablesInRoot = spiedVariablesDeclaredWithinBlock } // WARNING: mutating the mutableContextRef updateMutableUtopiaCtxRefWithNewProps(mutableContextRef, { @@ -173,6 +186,7 @@ export function createExecutionScope( mutableContext: { requireResult: requireResult, rootScope: executionScope, + spiedVariablesDeclaredInRootScope: spiedVariablesInRoot, fileBlobs: fileBlobsForFile, jsxFactoryFunctionName: jsxFactoryFunction, }, diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-scope-utils.ts b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-scope-utils.ts index f4a5a96bf393..a4f17c8b880f 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-scope-utils.ts +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-scope-utils.ts @@ -5,8 +5,11 @@ import { type ArbitraryJSBlock, } from '../../../core/shared/element-template' import { resolveParamsAndRunJsCode } from '../../../core/shared/javascript-cache' +import type { ElementPath } from '../../../core/shared/project-file-types' +import { type FileRootPath, type VariableData } from '../ui-jsx-canvas' export function runBlockUpdatingScope( + elementPath: ElementPath | FileRootPath | null, filePath: string, requireResult: MapLike, block: ArbitraryJSBlock, @@ -20,11 +23,18 @@ export function runBlockUpdatingScope( ) if (result.type === 'ARBITRARY_BLOCK_RAN_TO_END') { const definedWithinWithValues: MapLike = {} + const definedWithinVariableData: VariableData = {} for (const within of block.definedWithin) { currentScope[within] = result.scope[within] definedWithinWithValues[within] = result.scope[within] + if (elementPath != null) { + definedWithinVariableData[within] = { + spiedValue: result.scope[within], + insertionCeiling: elementPath, + } + } } - return arbitraryBlockRanToEnd(definedWithinWithValues) + return arbitraryBlockRanToEnd(definedWithinWithValues, definedWithinVariableData) } else { return result } diff --git a/editor/src/components/canvas/ui-jsx-canvas.tsx b/editor/src/components/canvas/ui-jsx-canvas.tsx index 74fbf3f6f913..92bf28f445e1 100644 --- a/editor/src/components/canvas/ui-jsx-canvas.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas.tsx @@ -101,9 +101,34 @@ export const ElementsToRerenderGLOBAL: { current: ElementsToRerender } = { current: 'rerender-all-elements', } +export type FileRootPath = { + type: 'file-root' +} + +export function insertionCeilingToString(insertionCeiling: ElementPath | FileRootPath): string { + if (insertionCeiling.type === 'file-root') { + return 'file-root' + } else { + return EP.toString(insertionCeiling) + } +} + +export function insertionCeilingsEqual( + a: ElementPath | FileRootPath, + b: ElementPath | FileRootPath, +): boolean { + if (a.type === 'file-root' && b.type === 'file-root') { + return true + } else if (a.type === 'file-root' || b.type === 'file-root') { + return false + } else { + return EP.pathsEqual(a, b) + } +} + export interface VariableMetadata { spiedValue: unknown - insertionCeiling: ElementPath + insertionCeiling: FileRootPath | ElementPath } export interface VariableData { diff --git a/editor/src/components/editor/actions/actions.spec.tsx b/editor/src/components/editor/actions/actions.spec.tsx index b654e46e26d7..5bb199009b99 100644 --- a/editor/src/components/editor/actions/actions.spec.tsx +++ b/editor/src/components/editor/actions/actions.spec.tsx @@ -683,7 +683,7 @@ describe('INSERT_INSERTABLE', () => { 'View', [], null, - null, + { type: 'file-root' }, null, ) diff --git a/editor/src/components/inspector/sections/component-section/data-picker-popup.tsx b/editor/src/components/inspector/sections/component-section/data-picker-popup.tsx index 45dc41120541..4092d61c4cc6 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-popup.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-popup.tsx @@ -56,6 +56,6 @@ export function dataPickerFilterOptionToString(mode: DataPickerFilterOption): st } } -export const DataPickerPreferredAllAtom = atom('preferred') +export const DataPickerPreferredAllAtom = atom('all') export type DataPickerCallback = (e: JSExpressionOtherJavaScript) => void diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 3b543b5331fe..544a3d578f61 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -14,13 +14,14 @@ import type { ElementPath } from '../../../../core/shared/project-file-types' import { assertNever } from '../../../../core/shared/utils' import type { AllElementProps } from '../../../editor/store/editor-state' import type { ArrayInfo, JSXInfo, ObjectInfo, PrimitiveInfo } from './variables-in-scope-utils' +import { insertionCeilingToString, type FileRootPath } from '../../../canvas/ui-jsx-canvas' interface VariableOptionBase { depth: number definedElsewhere: string valuePath: Array disabled: boolean - insertionCeiling: ElementPath | null + insertionCeiling: ElementPath | FileRootPath } export interface PrimitiveOption extends VariableOptionBase { @@ -81,7 +82,7 @@ export function getEnclosingScopes( metadata: ElementInstanceMetadataMap, allElementProps: AllElementProps, elementPathTree: ElementPathTrees, - buckets: Array, + buckets: Array, lowestInsertionCeiling: ElementPath, ): Array<{ insertionCeiling: ElementPath @@ -93,7 +94,7 @@ export function getEnclosingScopes( label: string hasContent: boolean }> = [] - const pathsToCheck = [...EP.allPathsInsideComponent(lowestInsertionCeiling)] + const pathsToCheck = EP.allPathsInsideComponent(lowestInsertionCeiling) for (const current of pathsToCheck) { const parentOfCurrent = EP.parentPath(current) @@ -110,13 +111,13 @@ export function getEnclosingScopes( elementPathTree, metadata, ), - hasContent: buckets.includes(current), + hasContent: buckets.includes(insertionCeilingToString(current)), }) continue } // we also add anything that has content in scope even if it's not a component or map - if (buckets.includes(current)) { + if (buckets.includes(insertionCeilingToString(current))) { result.unshift({ insertionCeiling: current, label: MetadataUtils.getElementLabel( @@ -135,7 +136,7 @@ export function getEnclosingScopes( result.unshift({ insertionCeiling: EP.emptyElementPath, label: 'File', - hasContent: buckets.includes(EP.emptyElementPath), + hasContent: buckets.includes(insertionCeilingToString({ type: 'file-root' })), }) return result diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index f4934041fe40..32c7e552f6e3 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -39,6 +39,8 @@ import type { ElementPath } from '../../../../core/shared/project-file-types' import * as EP from '../../../../core/shared/element-path' import { Substores, useEditorState } from '../../../editor/store/store-hook' import { optionalMap } from '../../../../core/shared/optional-utils' +import type { FileRootPath } from '../../../canvas/ui-jsx-canvas' +import { insertionCeilingToString, insertionCeilingsEqual } from '../../../canvas/ui-jsx-canvas' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -141,17 +143,15 @@ export const DataSelectorModal = React.memo( [allVariablesInScope], ) - const scopeBucketPaths = Object.keys(scopeBuckets).map((k) => EP.fromString(k)) - - const lowestMatchingScope = React.useMemo(() => { + const lowestMatchingScope: ElementPath | FileRootPath = React.useMemo(() => { if (lowestInsertionCeiling == null) { - return null + return { type: 'file-root' } } const matchingScope = findClosestMatchingScope(lowestInsertionCeiling, scopeBuckets) - return matchingScope ?? lowestInsertionCeiling + return matchingScope }, [scopeBuckets, lowestInsertionCeiling]) - const [selectedScope, setSelectedScope] = React.useState( + const [selectedScope, setSelectedScope] = React.useState( lowestMatchingScope, ) const setSelectedScopeCurried = React.useCallback( @@ -172,7 +172,7 @@ export const DataSelectorModal = React.memo( store.editor.jsxMetadata, store.editor.allElementProps, store.editor.elementPathTree, - scopeBucketPaths, + Object.keys(scopeBuckets), lowestInsertionCeiling ?? EP.emptyElementPath, ) return scopes.map(({ insertionCeiling, label, hasContent }) => ({ @@ -474,7 +474,7 @@ export const DataSelectorModal = React.memo( borderRadius: 4, cursor: 'pointer', fontSize: 12, - fontWeight: EP.pathsEqual(selectedScope, scope) ? 800 : undefined, + fontWeight: insertionCeilingsEqual(selectedScope, scope) ? 800 : undefined, }} > {label} @@ -624,22 +624,24 @@ type ScopeBuckets = { } function findClosestMatchingScope( - targetScope: ElementPath, + targetScope: ElementPath | FileRootPath, scopeBuckets: ScopeBuckets, -): ElementPath | null { - const allPaths = EP.allPathsInsideComponent(targetScope) - for (const path of allPaths) { - if (scopeBuckets[EP.toString(path)] != null) { - return path +): ElementPath | FileRootPath { + if (targetScope.type === 'elementpath') { + const allPaths = EP.allPathsInsideComponent(targetScope) + for (const path of allPaths) { + if (scopeBuckets[EP.toString(path)] != null) { + return path + } } } - return null + return { type: 'file-root' } } function putVariablesIntoScopeBuckets(options: DataPickerOption[]): ScopeBuckets { const buckets: { [insertionCeiling: string]: Array } = groupBy( - (o) => optionalMap(EP.toString, o.insertionCeiling) ?? '', // '' represents "file root scope", TODO make it clearer + (o) => insertionCeilingToString(o.insertionCeiling), options, ) @@ -649,17 +651,17 @@ function putVariablesIntoScopeBuckets(options: DataPickerOption[]): ScopeBuckets function useFilterVariablesInScope( options: DataPickerOption[], scopeBuckets: ScopeBuckets, - scopeToShow: ElementPath | null | 'do-not-filter', + scopeToShow: ElementPath | FileRootPath | 'do-not-filter', ): { filteredVariablesInScope: Array } { const filteredOptions = React.useMemo(() => { - if (scopeToShow === 'do-not-filter' || scopeToShow == null) { + if (scopeToShow === 'do-not-filter') { return options } const matchingScope = findClosestMatchingScope(scopeToShow, scopeBuckets) - return matchingScope == null ? [] : scopeBuckets[EP.toString(matchingScope)] + return scopeBuckets[insertionCeilingToString(matchingScope)] }, [scopeBuckets, options, scopeToShow]) return { diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts index a037958e31b1..fca9a29899d0 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts @@ -1,5 +1,6 @@ import * as EP from '../../../../core/shared/element-path' import { maybeToArray } from '../../../../core/shared/optional-utils' +import { emptySet } from '../../../../core/shared/set-utils' import type { ControlDescription } from '../../../custom-code/internal-property-controls' import type { PropertyValue, VariableInfo } from './variables-in-scope-utils' import { orderVariablesForRelevance, variableInfoFromValue } from './variables-in-scope-utils' @@ -12,6 +13,7 @@ describe('orderVariablesForRelevance', () => { 'style', { left: 300, position: 'relative' }, EP.fromString('aaa'), + emptySet(), ), ) const controlDescription: ControlDescription = { @@ -98,6 +100,7 @@ describe('orderVariablesForRelevance', () => { 'style', { left: 300, position: 'relative' }, EP.fromString('aaa'), + emptySet(), ), ) const controlDescription: ControlDescription = { diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index 491cecf515f6..241238a52a00 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -4,7 +4,7 @@ import type { ObjectControlDescription, } from '../../../custom-code/internal-property-controls' import type { ElementPath, PropertyPath } from '../../../../core/shared/project-file-types' -import type { VariableData } from '../../../canvas/ui-jsx-canvas' +import type { FileRootPath, VariableData } from '../../../canvas/ui-jsx-canvas' import { useEditorState, Substores } from '../../../editor/store/store-hook' import type { DataPickerFilterOption, DataPickerOption } from './data-picker-utils' import * as EP from '../../../../core/shared/element-path' @@ -15,10 +15,11 @@ import { mapDropNulls } from '../../../../core/shared/array-utils' import { assertNever, identity } from '../../../../core/shared/utils' import { isValidReactNode } from '../../../../utils/react-utils' import { MetadataUtils } from '../../../../core/model/element-metadata-utils' +import { emptySet } from '../../../../core/shared/set-utils' function valuesFromObject( variable: ArrayInfo | ObjectInfo, - insertionCeiling: ElementPath | null, + insertionCeiling: ElementPath | FileRootPath, depth: number, originalObjectName: string, valuePath: Array, @@ -75,7 +76,7 @@ function valuesFromObject( function valuesFromVariable( variable: VariableInfo, - insertionCeiling: ElementPath | null, + insertionCeiling: ElementPath | FileRootPath, depth: number, originalObjectName: string, valuePath: Array, @@ -136,7 +137,7 @@ interface VariableInfoBase { expression: string expressionPathPart: string | number value: unknown - insertionCeiling: ElementPath + insertionCeiling: ElementPath | FileRootPath matches: boolean } @@ -164,8 +165,16 @@ export function variableInfoFromValue( expression: string, expressionPathPart: string | number, value: unknown, - insertionCeiling: ElementPath, + insertionCeiling: ElementPath | FileRootPath, + valueStackSoFar: Set, ): VariableInfo | null { + if (valueStackSoFar.has(value)) { + // prevent circular dependencies + return null + } + // mutation + valueStackSoFar.add(value) + switch (typeof value) { case 'function': case 'symbol': @@ -203,7 +212,14 @@ export function variableInfoFromValue( insertionCeiling: insertionCeiling, matches: false, elements: mapDropNulls( - (e, idx) => variableInfoFromValue(`${expression}[${idx}]`, idx, e, insertionCeiling), + (e, idx) => + variableInfoFromValue( + `${expression}[${idx}]`, + idx, + e, + insertionCeiling, + valueStackSoFar, + ), value, ), } @@ -226,7 +242,13 @@ export function variableInfoFromValue( insertionCeiling: insertionCeiling, matches: false, props: mapDropNulls(([key, propValue]) => { - return variableInfoFromValue(`${expression}['${key}']`, key, propValue, insertionCeiling) + return variableInfoFromValue( + `${expression}['${key}']`, + key, + propValue, + insertionCeiling, + valueStackSoFar, + ) }, Object.entries(value)), } } @@ -235,7 +257,7 @@ export function variableInfoFromValue( function variableInfoFromVariableData(variableNamesInScope: VariableData): Array { const info = mapDropNulls( ([key, { spiedValue, insertionCeiling }]) => - variableInfoFromValue(key, key, spiedValue, insertionCeiling), + variableInfoFromValue(key, key, spiedValue, insertionCeiling, emptySet()), Object.entries(variableNamesInScope), ) @@ -368,7 +390,7 @@ const keepLocalestScope = (variablesInScope: VariableData): VariableData => { let deepestInsertionCeiling = -Infinity Object.values(variablesInScope).forEach((variable) => { - if (variable.insertionCeiling == null) { + if (variable.insertionCeiling.type === 'file-root') { return } @@ -380,7 +402,7 @@ const keepLocalestScope = const result: VariableData = {} Object.entries(variablesInScope).forEach(([key, variable]) => { - if (variable.insertionCeiling == null) { + if (variable.insertionCeiling.type === 'file-root') { result[key] = variable return } diff --git a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx index 27964c394194..8d2ab5336569 100644 --- a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx +++ b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx @@ -683,7 +683,7 @@ function insertPreferredChild( uid, ['do-not-add'], null, - null, + { type: 'file-root' }, null, ) diff --git a/editor/src/components/navigator/navigator-item/component-picker.tsx b/editor/src/components/navigator/navigator-item/component-picker.tsx index b6924d36ba36..7f4933357eb0 100644 --- a/editor/src/components/navigator/navigator-item/component-picker.tsx +++ b/editor/src/components/navigator/navigator-item/component-picker.tsx @@ -21,6 +21,7 @@ import type { Size } from '../../../core/shared/math-utils' import { dataPasteHandler } from '../../../utils/paste-handler' import { sortBy } from '../../../core/shared/array-utils' import { iconPropsForIcon } from './component-picker-context-menu' +import type { FileRootPath } from '../../canvas/ui-jsx-canvas' const FILTER_CATEGORIES: Array = ['Everything'] @@ -48,7 +49,7 @@ export function elementToInsertToInsertableComponent( uid: string, stylePropOptions: Array, defaultSize: Size | null, - insertionCeiling: ElementPath | null, + insertionCeiling: ElementPath | FileRootPath, icon: Icon | null, ): InsertableComponent { const element = elementToInsert.elementToInsert(uid) diff --git a/editor/src/components/shared/__snapshots__/project-components.spec.ts.snap b/editor/src/components/shared/__snapshots__/project-components.spec.ts.snap index 379e0870f730..8f4fcbee4592 100644 --- a/editor/src/components/shared/__snapshots__/project-components.spec.ts.snap +++ b/editor/src/components/shared/__snapshots__/project-components.spec.ts.snap @@ -9,7 +9,9 @@ Array [ "element": [Function], "icon": null, "importsToAdd": Object {}, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "App", "stylePropOptions": Array [ "do-not-add", @@ -51,7 +53,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "div", "stylePropOptions": Array [ "do-not-add", @@ -76,7 +80,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "span", "stylePropOptions": Array [ "do-not-add", @@ -94,7 +100,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "h1", "stylePropOptions": Array [ "do-not-add", @@ -112,7 +120,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "h2", "stylePropOptions": Array [ "do-not-add", @@ -130,7 +140,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "p", "stylePropOptions": Array [ "do-not-add", @@ -148,7 +160,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "button", "stylePropOptions": Array [ "do-not-add", @@ -166,7 +180,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "input", "stylePropOptions": Array [ "do-not-add", @@ -184,7 +200,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "video", "stylePropOptions": Array [ "do-not-add", @@ -202,7 +220,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "img", "stylePropOptions": Array [ "do-not-add", @@ -221,7 +241,9 @@ Array [ "element": [Function], "icon": "component", "importsToAdd": Object {}, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "Conditional", "stylePropOptions": Array [ "do-not-add", @@ -245,7 +267,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "Fragment", "stylePropOptions": Array [ "do-not-add", @@ -279,7 +303,9 @@ Array [ "importedWithName": null, }, }, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "List", "stylePropOptions": Array [ "do-not-add", @@ -297,7 +323,9 @@ Array [ "element": [Function], "icon": "component", "importsToAdd": Object {}, - "insertionCeiling": null, + "insertionCeiling": Object { + "type": "file-root", + }, "name": "Sample text", "stylePropOptions": Array [ "do-not-add", diff --git a/editor/src/components/shared/project-components.ts b/editor/src/components/shared/project-components.ts index aec4bb5dab51..a6e25286b1b7 100644 --- a/editor/src/components/shared/project-components.ts +++ b/editor/src/components/shared/project-components.ts @@ -62,6 +62,7 @@ import { elementUsesProperty } from '../../core/model/element-template-utils' import { intrinsicHTMLElementNamesThatSupportChildren } from '../../core/shared/dom-utils' import { getTopLevelElementByExportsDetail } from '../../core/model/project-file-utils' import { type Icon } from 'utopia-api' +import type { FileRootPath } from '../canvas/ui-jsx-canvas' export type StylePropOption = 'do-not-add' | 'add-size' @@ -71,7 +72,7 @@ export interface InsertableComponent { name: string stylePropOptions: Array defaultSize: Size | null - insertionCeiling: ElementPath | null + insertionCeiling: ElementPath | FileRootPath icon: Icon | null } @@ -81,7 +82,7 @@ export function insertableComponent( name: string, stylePropOptions: Array, defaultSize: Size | null, - insertionCeiling: ElementPath | null, + insertionCeiling: ElementPath | FileRootPath, icon: Icon | null, ): InsertableComponent { const component = { @@ -305,7 +306,7 @@ export function insertableVariable( variableType: InsertableVariableType, depth: number, originalName: string, - insertionCeiling: ElementPath | null, + insertionCeiling: ElementPath | FileRootPath, ): InsertableVariable { return { ...insertableComponent( @@ -653,7 +654,7 @@ export function moveSceneToTheBeginningAndSetDefaultSize( scene.name, scene.stylePropOptions, size(SceneDefaultWidth, SceneDefaultHeight), - null, + { type: 'file-root' }, null, ), ], @@ -744,7 +745,7 @@ export function getComponentGroups( insertOption.insertMenuLabel, stylePropOptions, null, - null, + { type: 'file-root' }, descriptor.icon, ), ) @@ -760,7 +761,7 @@ export function getComponentGroups( exportedComponent.listingName, stylePropOptions, null, - null, + { type: 'file-root' }, null, ), ) @@ -798,7 +799,7 @@ export function getComponentGroups( insertOption.insertMenuLabel, stylePropOptions, defaultSize ?? null, - null, + { type: 'file-root' }, component.icon, ), ) diff --git a/editor/src/components/shared/scoped-variables.ts b/editor/src/components/shared/scoped-variables.ts index e15c33c15bfb..7d2eb21e77b2 100644 --- a/editor/src/components/shared/scoped-variables.ts +++ b/editor/src/components/shared/scoped-variables.ts @@ -23,7 +23,7 @@ import { isJSXAttributeValue, simplifyAttributeIfPossible, } from '../../core/shared/element-template' -import type { VariableData } from '../canvas/ui-jsx-canvas' +import type { FileRootPath, VariableData } from '../canvas/ui-jsx-canvas' import { type VariablesInScope } from '../canvas/ui-jsx-canvas' import { getContainingComponent, toComponentId } from '../../core/shared/element-path' import { @@ -327,5 +327,5 @@ interface Variable { value?: unknown parent?: Variable depth: number - insertionCeiling: ElementPath | null + insertionCeiling: FileRootPath | ElementPath } diff --git a/editor/src/core/data-tracing/data-tracing.ts b/editor/src/core/data-tracing/data-tracing.ts index 43707f56b346..4c4b2fccd52c 100644 --- a/editor/src/core/data-tracing/data-tracing.ts +++ b/editor/src/core/data-tracing/data-tracing.ts @@ -1,4 +1,5 @@ import type { ProjectContentTreeRoot } from '../../components/assets' +import type { FileRootPath } from '../../components/canvas/ui-jsx-canvas' import { findUnderlyingTargetComponentImplementationFromImportInfo } from '../../components/custom-code/code-file' import { withUnderlyingTarget } from '../../components/editor/store/editor-state' import * as TPP from '../../components/template-property-path' @@ -428,12 +429,15 @@ export function traceDataFromElement( } export function traceDataFromVariableName( - enclosingScope: ElementPath, + enclosingScope: ElementPath | FileRootPath, variableName: string, metadata: ElementInstanceMetadataMap, projectContents: ProjectContentTreeRoot, pathDrillSoFar: DataPathPositiveResult, ): DataTracingResult { + if (enclosingScope.type === 'file-root') { + return dataTracingFailed('Cannot trace data from variable name in file root') + } const componentHoldingElement = findContainingComponentForElementPath( enclosingScope, projectContents, diff --git a/editor/src/core/model/element-metadata.spec.browser2.tsx b/editor/src/core/model/element-metadata.spec.browser2.tsx index 8143dcb3356d..48dc9c92dfd9 100644 --- a/editor/src/core/model/element-metadata.spec.browser2.tsx +++ b/editor/src/core/model/element-metadata.spec.browser2.tsx @@ -1400,6 +1400,10 @@ describe('record variable values', () => { const editor = await renderTestEditorWithCode(ProjectWithVariables, 'await-first-dom-report') const { variablesInScope } = editor.getEditorState().editor expect(variablesInScope['sb/scene/pg:root']).toEqual({ + add: { + insertionCeiling: { type: 'file-root' }, + spiedValue: expect.any(Function), + }, definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg:root') }, definedInsideObject: { spiedValue: { @@ -1415,6 +1419,10 @@ describe('record variable values', () => { style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg:root') }, }) expect(variablesInScope['sb/scene/pg:root/111']).toEqual({ + add: { + insertionCeiling: { type: 'file-root' }, + spiedValue: expect.any(Function), + }, definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg:root') }, definedInsideObject: { spiedValue: { @@ -1430,6 +1438,10 @@ describe('record variable values', () => { style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg:root') }, }) expect(variablesInScope['sb/scene/pg:root/222']).toEqual({ + add: { + insertionCeiling: { type: 'file-root' }, + spiedValue: expect.any(Function), + }, definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg:root') }, definedInsideObject: { spiedValue: { @@ -1445,6 +1457,10 @@ describe('record variable values', () => { style: { spiedValue: {}, insertionCeiling: EP.fromString('sb/scene/pg:root') }, }) expect(variablesInScope['sb/scene/pg:root/333']).toEqual({ + add: { + insertionCeiling: { type: 'file-root' }, + spiedValue: expect.any(Function), + }, definedInsideNumber: { spiedValue: 12, insertionCeiling: EP.fromString('sb/scene/pg:root') }, definedInsideObject: { spiedValue: { diff --git a/editor/src/core/shared/element-template.ts b/editor/src/core/shared/element-template.ts index 806ec416dd0d..072e1180260c 100644 --- a/editor/src/core/shared/element-template.ts +++ b/editor/src/core/shared/element-template.ts @@ -33,6 +33,7 @@ import { allComments } from './comment-flags' import type { Optic } from './optics/optics' import { fromField } from './optics/optic-creators' import { jsxSimpleAttributeToValue } from './jsx-attribute-utils' +import type { VariableData } from '../../components/canvas/ui-jsx-canvas' export interface ParsedComments { leadingComments: Array @@ -2627,35 +2628,44 @@ export type ConditionValue = ActiveAndDefaultConditionValues | 'not-a-conditiona export interface EarlyReturnVoid { type: 'EARLY_RETURN_VOID' + spiedVariablesDeclaredWithinBlock: VariableData } export function earlyReturnVoid(): EarlyReturnVoid { return { type: 'EARLY_RETURN_VOID', + spiedVariablesDeclaredWithinBlock: {}, } } export interface EarlyReturnResult { type: 'EARLY_RETURN_RESULT' result: unknown + spiedVariablesDeclaredWithinBlock: VariableData } export function earlyReturnResult(result: unknown): EarlyReturnResult { return { type: 'EARLY_RETURN_RESULT', result: result, + spiedVariablesDeclaredWithinBlock: {}, } } export interface ArbitraryBlockRanToEnd { type: 'ARBITRARY_BLOCK_RAN_TO_END' scope: MapLike + spiedVariablesDeclaredWithinBlock: VariableData } -export function arbitraryBlockRanToEnd(scope: MapLike): ArbitraryBlockRanToEnd { +export function arbitraryBlockRanToEnd( + scope: MapLike, + spiedVariablesDeclaredWithinBlock: VariableData, +): ArbitraryBlockRanToEnd { return { type: 'ARBITRARY_BLOCK_RAN_TO_END', scope: scope, + spiedVariablesDeclaredWithinBlock: spiedVariablesDeclaredWithinBlock, } } From 9338e22565bccdd60f07b2b79b5cd9b6e2b03b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Tue, 4 Jun 2024 17:05:13 +0200 Subject: [PATCH 022/103] safe indexing in useFilterVariablesInScope (#5826) ## Problem There an uncheck object indexing that can throw an uncaught error in `useFilterVariablesInScope` (and thus crash the editor) ## Fix Check the indexing. Also return the object from the `useMemo` call so that the memo isn't broken ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/data-selector-modal.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 32c7e552f6e3..d6666194d9e4 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -655,18 +655,20 @@ function useFilterVariablesInScope( ): { filteredVariablesInScope: Array } { - const filteredOptions = React.useMemo(() => { + return React.useMemo(() => { if (scopeToShow === 'do-not-filter') { - return options + return { + filteredVariablesInScope: options, + } } const matchingScope = findClosestMatchingScope(scopeToShow, scopeBuckets) - return scopeBuckets[insertionCeilingToString(matchingScope)] + const filteredOptions: Array = + scopeBuckets[insertionCeilingToString(matchingScope)] ?? [] + return { + filteredVariablesInScope: filteredOptions, + } }, [scopeBuckets, options, scopeToShow]) - - return { - filteredVariablesInScope: filteredOptions, - } } function useProcessVariablesInScope(options: DataPickerOption[]): ProcessedVariablesInScope { From fe2161a636fa795bbf3bdd9e1e388b7ff70a8a22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Tue, 4 Jun 2024 17:12:00 +0200 Subject: [PATCH 023/103] Use the starting value path to determine the starting scope (#5825) ## Description This PR tweaks the logic for determining the initially selected scope in the data picker by looking through the scopes, and using the scope that contains a variable with the starting value path. ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/data-selector-modal.tsx | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index d6666194d9e4..207cfb284685 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -147,9 +147,19 @@ export const DataSelectorModal = React.memo( if (lowestInsertionCeiling == null) { return { type: 'file-root' } } + + const scopeFromStartedSelectedValuePath = optionalMap( + (s) => getSelectedScopeFromBuckets(s, scopeBuckets), + startingSelectedValuePath, + ) + + if (scopeFromStartedSelectedValuePath != null) { + return scopeFromStartedSelectedValuePath + } + const matchingScope = findClosestMatchingScope(lowestInsertionCeiling, scopeBuckets) return matchingScope - }, [scopeBuckets, lowestInsertionCeiling]) + }, [lowestInsertionCeiling, startingSelectedValuePath, scopeBuckets]) const [selectedScope, setSelectedScope] = React.useState( lowestMatchingScope, @@ -774,3 +784,19 @@ function pathSegmentToString(segment: string | number) { } return `[${segment}]` } + +function getSelectedScopeFromBuckets( + startingSelectedValuePath: ObjectPath, + scopeBuckets: ScopeBuckets, +): ElementPath | null { + for (const [pathString, options] of Object.entries(scopeBuckets)) { + const anyOptionHasMatchingValuePath = options.some((o) => + arrayEqualsByReference(o.valuePath, startingSelectedValuePath), + ) + if (anyOptionHasMatchingValuePath) { + return EP.fromString(pathString) + } + } + + return null +} From 661c34bd11d3c27848e58d7bd60d208aea7f8fad Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Tue, 4 Jun 2024 17:53:13 +0200 Subject: [PATCH 024/103] Data picker css tweaks (#5828) Assorted tweaks: ![image](https://github.com/concrete-utopia/utopia/assets/2226774/8bb0baca-fe51-4022-b2e9-8c90bb659b47) - the data picker now has a fixed size so it doesn't jump around when switching Scopes - the scrollbar is now visible when scrolling - to make the scrollbar position feel visually more natural, I rearranged one spacer line --- .../component-section/data-selector-modal.tsx | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 207cfb284685..154fed1ccbfe 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -108,13 +108,6 @@ function ArrayIndexSelector({ ) } -const DEFAULT_SIZE: React.CSSProperties = { - minWidth: 600, - minHeight: 50, - maxWidth: 700, - maxHeight: 300, -} - interface ProcessedVariablesInScope { [valuePath: string]: DataPickerOption } @@ -391,8 +384,8 @@ export const DataSelectorModal = React.memo( onClick={catchClick} ref={forwardedRef} style={{ - ...style, - ...DEFAULT_SIZE, + width: 700, + height: 300, paddingTop: 16, paddingLeft: 16, paddingRight: 16, @@ -402,6 +395,7 @@ export const DataSelectorModal = React.memo( borderRadius: UtopiaTheme.panelStyles.panelBorderRadius, boxShadow: UtopiaStyles.shadowStyles.highest.boxShadow, border: `1px solid ${colorTheme.fg0Opacity10.value}`, + ...style, }} > {/* top bar */} @@ -495,18 +489,21 @@ export const DataSelectorModal = React.memo( ))} - {/* detail view */}
+ {when( primitiveVars.length > 0, <> From d49199815e5526a56a055e5d60dcfbfc7572c64c Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:11:32 +0200 Subject: [PATCH 025/103] Fix/data picker fixes more (#5832) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit image An assortment of small data picker fixes: - flipping breadcrumbs and the "data path input field", because the logical scope is breadcrumb -> data path, for example: `Reviews > data.reviews[0].quote`. How it is on master makes it look like we are inside data.reviews[0].quote and we have options File > Reviews to further narrow the scope, which is backwards. - adding an empty state - various minor css tweaks - not allowing clicking on breadcrumbs that point at an empty scope slice, these breadcrumbs are also subdued - fixing vite hot reload for tweaking the data modal by unexporting `function pathBreadcrumbs` - When opening the data picker with an already selected data, navigate into the object hierarchy to be able to show the selected Cartouche - Outlet Name Hack – if we find that the Scope Breadcrumb would be named Outlet, we try to manually look up the component name from the parsed model --- .../component-section/data-picker-utils.tsx | 40 ++++-- .../component-section/data-selector-modal.tsx | 117 +++++++++++++----- editor/src/core/data-tracing/data-tracing.ts | 26 ++-- .../src/core/model/element-template-utils.ts | 14 +++ 4 files changed, 135 insertions(+), 62 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 544a3d578f61..50a0b31cb8b3 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -1,6 +1,7 @@ import { atom } from 'jotai' import { processJSPropertyAccessors } from '../../../../core/data-tracing/data-tracing' import { MetadataUtils } from '../../../../core/model/element-metadata-utils' +import { findContainingComponentForPathInProjectContents } from '../../../../core/model/element-template-utils' import { foldEither } from '../../../../core/shared/either' import * as EP from '../../../../core/shared/element-path' import type { ElementPathTrees } from '../../../../core/shared/element-path-tree' @@ -12,9 +13,10 @@ import { } from '../../../../core/shared/element-template' import type { ElementPath } from '../../../../core/shared/project-file-types' import { assertNever } from '../../../../core/shared/utils' +import type { ProjectContentTreeRoot } from '../../../assets' +import { insertionCeilingToString, type FileRootPath } from '../../../canvas/ui-jsx-canvas' import type { AllElementProps } from '../../../editor/store/editor-state' import type { ArrayInfo, JSXInfo, ObjectInfo, PrimitiveInfo } from './variables-in-scope-utils' -import { insertionCeilingToString, type FileRootPath } from '../../../canvas/ui-jsx-canvas' interface VariableOptionBase { depth: number @@ -82,6 +84,7 @@ export function getEnclosingScopes( metadata: ElementInstanceMetadataMap, allElementProps: AllElementProps, elementPathTree: ElementPathTrees, + projectContents: ProjectContentTreeRoot, buckets: Array, lowestInsertionCeiling: ElementPath, ): Array<{ @@ -105,12 +108,7 @@ export function getEnclosingScopes( ) { result.unshift({ insertionCeiling: current, - label: MetadataUtils.getElementLabel( - allElementProps, - parentOfCurrent, - elementPathTree, - metadata, - ), + label: outletNameHack(metadata, allElementProps, elementPathTree, projectContents, current), hasContent: buckets.includes(insertionCeilingToString(current)), }) continue @@ -120,12 +118,7 @@ export function getEnclosingScopes( if (buckets.includes(insertionCeilingToString(current))) { result.unshift({ insertionCeiling: current, - label: MetadataUtils.getElementLabel( - allElementProps, - parentOfCurrent, - elementPathTree, - metadata, - ), + label: outletNameHack(metadata, allElementProps, elementPathTree, projectContents, current), hasContent: true, }) continue @@ -141,3 +134,24 @@ export function getEnclosingScopes( return result } + +function outletNameHack( + metadata: ElementInstanceMetadataMap, + allElementProps: AllElementProps, + elementPathTree: ElementPathTrees, + projectContents: ProjectContentTreeRoot, + target: ElementPath, +): string { + const namePossiblyOutlet = MetadataUtils.getElementLabel( + allElementProps, + EP.parentPath(target), + elementPathTree, + metadata, + ) + if (namePossiblyOutlet !== 'Outlet') { + return namePossiblyOutlet + } + // if getElementLabel returned Outlet, we try to find the actual component name by hand – this is a hack and should be removed once the Navigator is capable of showing the correct name + const component = findContainingComponentForPathInProjectContents(target, projectContents) + return component?.name ?? namePossiblyOutlet +} diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 154fed1ccbfe..5e38b17d4988 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -3,6 +3,7 @@ import { groupBy, isPrefixOf, last } from '../../../../core/shared/array-utils' import { jsExpressionOtherJavaScriptSimple } from '../../../../core/shared/element-template' import { CanvasContextMenuPortalTargetID, + NO_OP, arrayEqualsByReference, assertNever, } from '../../../../core/shared/utils' @@ -41,6 +42,7 @@ import { Substores, useEditorState } from '../../../editor/store/store-hook' import { optionalMap } from '../../../../core/shared/optional-utils' import type { FileRootPath } from '../../../canvas/ui-jsx-canvas' import { insertionCeilingToString, insertionCeilingsEqual } from '../../../canvas/ui-jsx-canvas' +import { set } from 'objectPath' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -158,7 +160,14 @@ export const DataSelectorModal = React.memo( lowestMatchingScope, ) const setSelectedScopeCurried = React.useCallback( - (name: ElementPath) => () => setSelectedScope(name), + (name: ElementPath, hasContent: boolean) => () => { + if (hasContent) { + setSelectedScope(name) + setSelectedPath(null) + setHoveredPath(null) + setNavigatedToPath([]) + } + }, [], ) @@ -168,6 +177,8 @@ export const DataSelectorModal = React.memo( selectedScope, ) + const processedVariablesInScope = useProcessVariablesInScope(filteredVariablesInScope) + const elementLabelsWithScopes = useEditorState( Substores.fullStore, (store) => { @@ -175,18 +186,22 @@ export const DataSelectorModal = React.memo( store.editor.jsxMetadata, store.editor.allElementProps, store.editor.elementPathTree, + store.editor.projectContents, Object.keys(scopeBuckets), lowestInsertionCeiling ?? EP.emptyElementPath, ) return scopes.map(({ insertionCeiling, label, hasContent }) => ({ label: label, scope: insertionCeiling, + hasContent: hasContent, })) }, 'DataSelectorModal elementLabelsWithScopes', ) - const [navigatedToPath, setNavigatedToPath] = React.useState([]) + const [navigatedToPath, setNavigatedToPath] = React.useState( + findFirstObjectPathToNavigateTo(processedVariablesInScope, startingSelectedValuePath) ?? [], + ) const [selectedPath, setSelectedPath] = React.useState( startingSelectedValuePath, @@ -237,8 +252,6 @@ export const DataSelectorModal = React.memo( [], ) - const processedVariablesInScope = useProcessVariablesInScope(filteredVariablesInScope) - const focusedVariableChildren = React.useMemo(() => { if (navigatedToPath.length === 0) { return filteredVariablesInScope @@ -398,6 +411,32 @@ export const DataSelectorModal = React.memo( ...style, }} > + {/* Scope Selector Breadcrumbs */} + + {elementLabelsWithScopes.map(({ label, scope, hasContent }, idx, a) => ( + +
+ {label} +
+ {idx < a.length - 1 ? ( + {'/'} + ) : null} +
+ ))} +
{/* top bar */} @@ -456,6 +495,7 @@ export const DataSelectorModal = React.memo( {/* Value preview */} {valuePreviewText} - - {elementLabelsWithScopes.map(({ label, scope }, idx, a) => ( - -
- {label} -
- {idx < a.length - 1 ? ( - {'/'} - ) : null} -
- ))} -
+ {/* detail view */}
( ( ( ))} + {/* Empty State */} + {when( + focusedVariableChildren.length === 0, +
+ We did not find any insertable data +
, + )}
@@ -716,7 +747,7 @@ function childVars(option: DataPickerOption, indices: ArrayIndexLookup): DataPic } } -export function pathBreadcrumbs( +function pathBreadcrumbs( valuePath: DataPickerOption['valuePath'], processedVariablesInScope: ProcessedVariablesInScope, ): Array<{ @@ -797,3 +828,29 @@ function getSelectedScopeFromBuckets( return null } + +function findFirstObjectPathToNavigateTo( + processedVariablesInScope: ProcessedVariablesInScope, + selectedValuePath: ObjectPath | null, +): ObjectPath | null { + if (selectedValuePath == null) { + return null + } + + let currentPath = selectedValuePath + while (currentPath.length > 0) { + const parentPath = currentPath.slice(0, -1) + const parentOption = processedVariablesInScope[parentPath.toString()] + const grandParentPath = currentPath.slice(0, -2) + const grandParentOption = processedVariablesInScope[grandParentPath.toString()] + if (grandParentOption != null && grandParentOption.type === 'array') { + return grandParentPath.slice(0, -1) + } + if (parentOption != null && parentOption.type === 'object') { + return parentPath.slice(0, -1) + } + currentPath = currentPath.slice(0, -1) + } + + return null +} diff --git a/editor/src/core/data-tracing/data-tracing.ts b/editor/src/core/data-tracing/data-tracing.ts index 4c4b2fccd52c..e42825b7e93a 100644 --- a/editor/src/core/data-tracing/data-tracing.ts +++ b/editor/src/core/data-tracing/data-tracing.ts @@ -4,7 +4,10 @@ import { findUnderlyingTargetComponentImplementationFromImportInfo } from '../.. import { withUnderlyingTarget } from '../../components/editor/store/editor-state' import * as TPP from '../../components/template-property-path' import { MetadataUtils } from '../model/element-metadata-utils' -import { findContainingComponentForPath } from '../model/element-template-utils' +import { + findContainingComponentForPath, + findContainingComponentForPathInProjectContents, +} from '../model/element-template-utils' import { mapFirstApplicable } from '../shared/array-utils' import type { Either } from '../shared/either' import { isLeft, isRight, left, mapEither, maybeEitherToMaybe, right } from '../shared/either' @@ -214,19 +217,6 @@ export type DataTracingResult = | DataTracingToElementAtScope | DataTracingFailed -function findContainingComponentForElementPath( - elementPath: ElementPath, - projectContents: ProjectContentTreeRoot, -): UtopiaJSXComponent | null { - return withUnderlyingTarget(elementPath, projectContents, null, (success) => { - const containingComponent = findContainingComponentForPath( - success.topLevelElements, - elementPath, - ) - return containingComponent - }) -} - export function processJSPropertyAccessors( expression: JSExpression, ): Either }> { @@ -438,7 +428,7 @@ export function traceDataFromVariableName( if (enclosingScope.type === 'file-root') { return dataTracingFailed('Cannot trace data from variable name in file root') } - const componentHoldingElement = findContainingComponentForElementPath( + const componentHoldingElement = findContainingComponentForPathInProjectContents( enclosingScope, projectContents, ) @@ -466,10 +456,8 @@ function traceDataFromIdentifierOrAccess( projectContents: ProjectContentTreeRoot, pathDrillSoFar: DataPathPositiveResult, ): DataTracingResult { - const componentHoldingElement: UtopiaJSXComponent | null = findContainingComponentForElementPath( - enclosingScope, - projectContents, - ) + const componentHoldingElement: UtopiaJSXComponent | null = + findContainingComponentForPathInProjectContents(enclosingScope, projectContents) if (componentHoldingElement == null) { return dataTracingFailed('Could not find containing component') diff --git a/editor/src/core/model/element-template-utils.ts b/editor/src/core/model/element-template-utils.ts index 67419ccb6dc9..aaee617e0269 100644 --- a/editor/src/core/model/element-template-utils.ts +++ b/editor/src/core/model/element-template-utils.ts @@ -88,6 +88,7 @@ import { MetadataUtils } from './element-metadata-utils' import { mapValues } from '../shared/object-utils' import type { PropertyControlsInfo } from '../../components/custom-code/code-file' import { getComponentDescriptorForTarget } from '../property-controls/property-controls-utils' +import { withUnderlyingTarget } from '../../components/editor/store/editor-state' export function generateUidWithExistingComponents(projectContents: ProjectContentTreeRoot): string { const mockUID = generateMockNextGeneratedUID() @@ -1657,3 +1658,16 @@ export function findContainingComponentForPath( return null } + +export function findContainingComponentForPathInProjectContents( + elementPath: ElementPath, + projectContents: ProjectContentTreeRoot, +): UtopiaJSXComponent | null { + return withUnderlyingTarget(elementPath, projectContents, null, (success) => { + const containingComponent = findContainingComponentForPath( + success.topLevelElements, + elementPath, + ) + return containingComponent + }) +} From 27060e4b1007006a19ac83a409e04b3115db7251 Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Wed, 5 Jun 2024 15:23:34 -0400 Subject: [PATCH 026/103] New Array Icons and new colors for cartouches (#5842) New icons for https://github.com/orgs/concrete-utopia/projects/6/views/1?pane=issue&itemId=66250591 Also new color variants to be used in https://github.com/orgs/concrete-utopia/projects/6/views/1?pane=issue&itemId=66250591 and https://github.com/orgs/concrete-utopia/projects/6/views/1?pane=issue&itemId=66037087 --- .../navigator-element/array-aqua-12x12@2x.png | Bin 630 -> 1039 bytes .../navigator-element/array-black-12x12@2x.png | Bin 625 -> 1038 bytes .../navigator-element/array-blue-12x12@2x.png | Bin 624 -> 961 bytes .../array-darkgray-12x12@2x.png | Bin 623 -> 1012 bytes .../navigator-element/array-gray-12x12@2x.png | Bin 598 -> 909 bytes .../navigator-element/array-green-12x12@2x.png | Bin 601 -> 953 bytes .../array-lightaqua-12x12@2x.png | Bin 626 -> 1002 bytes .../array-lightblue-12x12@2x.png | Bin 622 -> 978 bytes .../array-lightgray-12x12@2x.png | Bin 627 -> 971 bytes .../array-lightgreen-12x12@2x.png | Bin 627 -> 1042 bytes .../array-lightpurple-12x12@2x.png | Bin 631 -> 1006 bytes .../array-purple-12x12@2x.png | Bin 626 -> 1027 bytes .../navigator-element/array-red-12x12@2x.png | Bin 618 -> 933 bytes .../navigator-element/array-white-12x12@2x.png | Bin 569 -> 804 bytes editor/src/uuiui/styles/theme/dark.ts | 2 ++ editor/src/uuiui/styles/theme/light.ts | 2 ++ 16 files changed, 4 insertions(+) diff --git a/editor/resources/editor/icons/light/navigator-element/array-aqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-aqua-12x12@2x.png index 024716edf5e16851f8a4d6e104e17543f285253b..c30d6acc5bfb9db226f741251e0d56c67435d019 100644 GIT binary patch delta 626 zcmV-&0*(Fl1dj-?sR4fiP)S5VRCoc+RXc9mKoEUP39w4$1}xKsWq=@n6665Z2_m1s zR$*C^3rUSdvr#&RH#EW2mW9|fB!`R>pH|>Y_E#x<5+a) zyQtmTXskoZe~gzPcSmsK?Ne0`C^ZfkF^7rHM$WsFq0%c9YlhQarwpc63NBNDTS-U5 z67iZ)Tr4lTD;O}MX~G;$S(r4LI`DZJRCx`qf)(C>`UZhl z^bZlhzrsK6rTXQ?FVg>pup~{cC{09w!2-`An=~B|d-#7njg;uUeo)ZKgKxFt!m7nM z>4rrIN0T$kZQFcBsMlNRM#&zIOUk*E>Lq)UzL56>7w1T5&8%tC7rMyuIM(3uj0qqw zm7AN()VaVg2M(oIYeqQEQgF4OAJCz=n>heaE|M`$`^0O-AUox~5c!M7fKXo~(QP_U zHn^FCjFM_}9DC==Ab%W7-fs(IKh?NWy;0O#h%yI~_duvZ2iIN7#W(}Q-bPm?jf)C*x&-B*3$h=uh=CXLHt3p%QQr}oF3M|vD5Qn4M7j$$3NLB8L z=Gd)InH~5@c?PA|S93?B=wNH;d@u&gv^@0zCcWhJpA?7t!aq)b0TqBm%VGcn7{CAq z{6l^o$Y27!QLeFpQ{MOAq_@j=;0PNy)BvC?kwhLEiLH77#KIoRd4vAx0g==xjj?uL Q1poj507*qoM6N<$f<5qAsQ>@~ diff --git a/editor/resources/editor/icons/light/navigator-element/array-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-black-12x12@2x.png index 05c44d94060bbbdfdb198f0b5aa77f43d87c6fdb..caef16a4904ad230ad53a5f4285a1304d4243db7 100644 GIT binary patch delta 625 zcmV-%0*?Lh1da%>sR4fiPf0{URCoc+RlRQFKoGXgk0>1>;7XT>AKjK$nm2&*s^gvj z=&mEYLGlC%(8loQ)t-qGY6H);lxb?ELIt7#~dL zTa+u6iffvtlSm{y-}mJ?HfK91m&*@eLVfRcyUut#zB*-R8E1bGz?%#%5y2odw5+ZW z!hRPAlosaw;c(c%Ho&r1tJS+X@QLsD`xd8)faPQ|k*91E#u+r5%_fCH;R0J1>l+*f zSU+(tPuaeyi*S1ZV0*b-`clfk_zLuD1nBt|a^A+)0UxB(=}xrwOQlj5okVh~&FyG3 z>gaH^HK0_0Q9FNzU4pa}(f49LpZD2$7wi%%!|O*bmop*v;#k@)0$@{f>=uhfhxhf+ z*s>bXt+CB79ad6zh>)f3Jd??&!iIdi-F~N{^O@F08$l|Sx{Vva={0H)@NKV|UxKw+ zrLV)%)?hlFuCm$eKcwISAT%ESqKJQ#oZdw~pMSzReg1z3??65{tE{%z5#3Ur^IR~MHoBl_4*!LN6AsAntB)XKLK_Ja8>Xt z^)4(1C*UT}7>|MOm2-f1Bj7|1pM?bAn+P~jyIQT*4-Nn-Sh0ujYaD^C`d-On-3Z|iuc<%eiss>BkX@} zhF%QcM-2$`xQjS%HuCGm|4b+qxCn)9FBXeId|b2KrJL)z?8E38vg`{wOTWTh00000 LNkvXXu0mjf#*{Jg delta 209 zcmV;?051QI2=N54sR4fgvPnciRCodHmB9@HArM6eumDTIGmtICEkP^LQnUgsK}#`& zvs;1<01nBL5Z3H^(8F%#CxjoE;ROzSfVqohV~p8_5H8hz=bYP&9iWtY;v~y8&iUS2 zdrf{-H^dlkSn%lm3#N5ujIDd$U{70a4gf-kd!~OQyx}SP^a@EefWx0f00Izz00j7j z26^DU-)gO8@+ol2|NfIO(T+KAu)diDU~yZ7Mu%e*fI48kgvII&IjlU1IIWC<00000 LNkvXXu0mjfblfph?LkP@x{x%eg7z};~-91s5N%uRB;+1=#Jw;SMxMIE&I&2(VU!Wwhj zDP6~JlzbKI!&Oz_8o*N{nyx{6Cq5%1^>I^=yz z=9i-Fa_zayugZTy9hWJ&Ta9u_a$|%ugj%TZDL=spF-5__(lju~Qx*bKxQ8i9_gW<* z!V$Rurwp{>1wR(-G3^(Okg)kpX`kaSB!2?S9z{%#D+(#tuS<4o8{Zc!`x3Hkxtm~Y zCN#$Kr)lYK7J9foflbrXjy<6+MtmnCd|=!Bo zuk#XNf_!Hk;MH7i6R6EYGL&M{&LQv~xrfG!t&4EFd~#%cLIN$yJ~MxaL$)0!B?(q; zY&hGlU1ItKmiNl_{1!i7r72GnWbInB&bVvoQxGx?3&EE};@wZPVsT3ymb;I-zv#BJ mH`x4&Eb|;tbzJh_tch<&(XLPw>Jxwf000005AW+2k->2sR4fgu}MThRCodHm9Y)NFc3w*PY5U(!A!s?Fak^f1!M?90TaLo zFbWfp5$FgF$AKX-!AdAdk?4ML`lqw+NiO_>y31s4aTx=&&CL_UoqpklC_RCV&8?jv zZtoth6+rH#9$mv{l<9^I2t9Wk1F0i_{0(4pc+-E;BE3SxBvOh2gsI%IXsqrt=_8OsgHt^K0000< KMNUMnLSTYS$62HR diff --git a/editor/resources/editor/icons/light/navigator-element/array-darkgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-darkgray-12x12@2x.png index 6329d5e32e15d996970fb0ef3dd5fd880eed562c..3771c4d669a25c89e05f63569d65524d4d58e4fd 100644 GIT binary patch delta 599 zcmV-d0;v7(1oQ{6sR4fiHAzH4RCoc+RXc7XK@ja32nc6yK)3>lop3|A!B~Jqw)g~? zY%}Z|cu!!+SON0*1SWLmaRP++1`{Ij^LtQ@+vBzvOSbHinr^DPUv*Wz>QU;G#d*)> zTCG-g94DX2WXAn|f1c({Y6k$n$K)HT_Ha17Ja*1iDWqPnHwk}^+s`pVQFnqM@Q$5L z4Y@Z%n`~`&Xv>w`+GJlYYk?z*`ib`-5^yz#L<8B!e4El zPN%bCvG@oZf$!A*T?*A#$P1btYb0&QZO2I)AHHlh%Ljik#(NdLa)85EINaPR_h~uN z8_AyadVQ-OJ=)P172Oy7PGGuL&$PbOec=jtQ^0xaF@Z2{wR3=XG&qH8>JGPboGSyI za#pQYgM$M$kr*!ExgrsGn)d)SKQvm(Iy%$2;nY7k(3Hg7LNwR%Jebe%t9oG1183=t z*y3P*a6nJqV~Qj-fsRIRM)6L~zTg_V9sh+47YY0b_3Q5Tnp)<~bzRT)QD-Wa%cV~{ l<}k@JAwroQZDZM|$rJbwF^Q2*he!Yb002ovPDHLkV1k}s9((`* delta 207 zcmV;=05Jdb2k!*1sR4fgut`KgRCodHRl5zsFcf?bWdKG96J!)9>>eh7QD6en+Xalm z1TaE2Fz3jY^0AT>Ns;JXb7#GGKFNiTXzk!AwAN?m+_N=g{uyHqLl?mJg)i^;F7TCJ zXT3z`7YrY-!4-`FI}gx4cnh3Q&3Tsaysfn*O$2uDQTtZ_wE{`5?I9q^nQCe09&dnbUT4qFV2h!ub*Vq?mVM891VsR~L*z|wzW4pWw-O=cg~E}#pSQ7QEv$MGZ7D@k+@@H@-@3jdpYK2c484gH0* zXxev>j32Xd_>QL>`tDN#7@3Btd}@rbSt#t;QbSwzkIcD{cjAGX%Wq-M#XuIM0?vP} z1ZZphU}k}n=$ZAsqV~N`K8`dTyrzKx6rT;Tu!002ovPDHLkV1mpF@{s@l delta 182 zcmV;n07?Ii2i63zsR4fgmq|oHRCodHmEjFQFc5{07{CZjU=&7R0!HWvOuz_?Vgg1m zf+wk{YFa<|LGC4&zTCC_{@o+`y1d;8A#xn8HlNXtZ69Dh;fS<$fqu7{!0@I=jnXgV zR)Y$qPf(dUGy#U4en+@lD?Zl&KD{gkFn|FJV89bHev#u7F=;G?Ch8sHTSvJ3m~*;oAcB?{tbUPns$6cfCwA=Yk)UW zCBUlAJ=6d zcHCFNI2GV+a=b3=T;Ytw#NZ+B3SJW`tT$_b5RVQ305wCnRSsA`#NI<^FGa7>VQ zTo(9U8XB)5H8JP<3V&hw4180ix($>UQoQb!oK_m2RJoV5mP`O2j~VqS($mA0-Kgmb z`AwUi;yrmuFM6TET-Hk3{HB!bNdJ&a)_e+hVDzqmjtqaGSV-L?S7hyxi^+p$~ns7qb6?fPOzWg>(Q ehx*l;_yQDMNSV9V`eQ!;0000hKuf2yyNzkC9F3(Jsi+$1 zdt580vZeQ^!fjIrsAu{u`N$SO{el88@v<1e00uCC0Z&Mm2LUndbw~PM+4njLq)-Fr n5)fhyjgIOZ03j`5rcQ->mL9I9kgYc^rkmg~>3C2OWQ1tda|ap{IIQPwWf#PDqCH zFr&cllh_woI51LhH)B}u4v2klQH7UbS_6mb{hkV)pG9zunhlz-Wl%YwQXdj+7B*8T zxo)g`sXa862=bU+!?~Bz+hifaA^?p^)wy_s?Klo~Ul&Gsr5_#Y3{r!y*g9}^Z*=DO z2sVh>RA5DZG#5L@#@D}nYc}R~dp5|5!OhjSzN@^I%H^F$U8%^JcBxgiY*tyIDi4`k b{4e=^~%~EEo5IUq^gVoOPyx&C_~)$Yq>5pt$Hs0T&&r zm{%j&Hua!q&yEepR)587*6bfPg=UyQQHF~h0h{;U{ti_xD_=^tuMi0`d>Ip%zyu~R z!6)eC0q6OYbKTv47&zg)?}Lf9L>xG20V#vfsQD!YWWj#-xE=nG8(c*$jxsCfegFUf M07*qoM6N<$f>C%_TmS$7 diff --git a/editor/resources/editor/icons/light/navigator-element/array-lightblue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-lightblue-12x12@2x.png index c2194ea28ce0446342cf6a18047bc023a72b5f18..2ed0bb0821488040c4c26f23085272e386b1553c 100644 GIT binary patch delta 565 zcmV-50?PgF1kwkvsR4fi6G=otRCoc+RoiVFF%TS{tR#O?3F;sUkk_YFL8JvB!!1WR~~&WoTgppDMWH3C`7XZm)lQ?>^sF1d^86ukA-O z;b_O!)AkPtI>@Crm}#m4uxoPDd18 zwlx85nwT3>_x*n`Ao*CmCnO(f5MNS2N2y6xsXIU&FV@H2c)amdEx43J8s;Td35U~C zIhjZnlBVh&)+wlimu$Z?9hv0$HQO~S*xp(X&xglnB7~Y)+xKRJr!doq>aT@Vtf!)t zhwnG5ocBY?=649_9Ar4vPscVXHcGlWxIiJ>u-?U}s0)AnPn@B;@MTdKnSxIhJVd=w zpo=oR4(2s*$oNL)qIs#2`pX*XVq6lS_>t_fAoEC1&?|J$a}Ln7J%;7!Zj+;qndxSS z_%$Q*nL1R@vFg4-a4r2SS-ZP#B4#9ry3YmJXqECsC^z58)9h;Qjy|G)5re7ijg~VL ztH@I``;#qs+cTGmpSq-?%VWp&^QOvF2*VKhqt?V9uz||LM!jeW00000NkvXXu0mjf DEL0h! delta 206 zcmV;<05Sj42kr#0sR4fguSrBfRCodHmBA5$Fc3vIjs;i(R^ZLC3n@V>&=R%;tw2lA zF4UV9KnYa9@`1nrVSoc1VD=x9pJX;Kvxj`5xyuxWe{#a~Xq<<rP3K&Ce zfpg@qc-BYN|GrK9k!u+^k_Ao=AWtOU`VeC$06n;n8<`7I0yRe@l0f`R+5i9m07*qo IM6N<$f~h)K{{R30 diff --git a/editor/resources/editor/icons/light/navigator-element/array-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-lightgray-12x12@2x.png index 4429927970d82440a0d43e0445d75ee255582333..7a047a049f4b1fb299ddc8286b869678981a8ed0 100644 GIT binary patch delta 558 zcmV+}0@3~R1j`4osR4fi3`s;mRCoc+RoQXEFc6gt|8WWKAZ9qeO$C7pVk!VCz;pl= z02M$7_?u&FI&cXtfFp066{8q2h{@#8j7QS0_U*kE;)j=f=J9sB4IIbu@Wr)SEwhoa zRQ`+VA%vflDbf?5n~uDMv|?xQ~BitrVQkXOH(qqtWQ% znB#N#`@RBLoATc0P`TudO&+Wiz-kK1RD4=YdC1{S&qnsCD%xx|ln1w3t){R(7yn`1 z^#HN%!`cDL(Zh9BsZ@q~%u!h*@CF5ll=FJMKD1Uqp+GYwC31{hv^DTZXW~9aUqodr zW0C7m3{FjKJQ~{Caxe?t9!p363_zWovvKt`?`XR zEunF|B!SX6&J6$ujd#NbR(4fDb&oA&OH`MR)nm+|p57O9hD=faR1D;K2|q;+=EYl` wN^zqqG5sdgxi5U?ugX=%g%IG&ezhk)0ITaRL<7`73;+NC07*qoM6N<$f__^EX8-^I delta 211 zcmV;^04)E@2lE85sR4fgv`IukRCodHmCX$TArOTJVgZ)0RHnGDJPW!HlqH1iU|5P0(u4m_e?m&!#5VV6?64E7sq?Pjh4d=L1FUQ?y^ z#+dq5uO>WK817uRw4fN{8Pl2@mzb*V{s@3WH{80WH|3l=<(f-hp$E|PWeGq40uX=z zKA}+_;6LAb?+aeG-T!_{IC~@x9C*t`08}A#a%eOdvjDC2VHlbJr6(XkHjJa$_$L4W N002ovPDHLkV1i2eTb%#^ diff --git a/editor/resources/editor/icons/light/navigator-element/array-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-lightgreen-12x12@2x.png index 5ed5ca4886b376e7e213a300942c6215b497187d..99e1729845099ed6a239692fdff19a10d61ba651 100644 GIT binary patch delta 629 zcmV-*0*d|f1d<4_sR4fiQ%OWYRCoc+RZ(u*KoFfVDd}H1f^SfNwltN<2?{4DIRW9b zstQX{)L%G3-~`DHYN;vxEV+S?;NL1?r*FJ#Vq8aYq%_G$hP7wr&FsvZU84Uid>`Wj znRYBm*d!arY?3-YwFA79$!{Tw@^>K~{^HT>F28_kNLx(bgC~E;>D*-|nqsxdQuAr2)xN9p8Jg2)&4q zQEQKA4Hl*J9OTv=yp`#I$sS`FDs#a7VUhc7nU2Zn0m6%)JQ`NvRQ8}PClSDB4qQdL zR}`FT!k5x!}RUa{>2?nV` z^T#)qQ?=Sq<2CGBnFoBR?hf|JE-0JYov`zqIRV+Z`(}-n$0bF}Dy&bUF-5%|9|-jU04YkgykHa4QwZ;7b%H^%7^F?*AmxAh3;q(9b$ak!QzNnzq$~cs z{wF|NzJi9*_pb@oJ(MLg)N%#H-)T!*N}6C#J{JdKa8K|VIofK&XZc(N4qWS*fuo)r zJD?1ZoKY|?fUAU8?pr1RKh42awDB0!?lu6xBB$U9A|JXPQ0s>G5>ZKXF7n-#g8S0g zXd6I0hXHLgK&j5WL*Y2)s)OxPe_pz~p+fI4vjEC_G-K_6rR#H?i)rE4H}YOgcZ1S2;a9%YwG=OK7kK@7nPrX$)WMTH>P-9vMtbadp`d(r P00000NkvXXu0mjf2{SAL delta 211 zcmV;^04)EK2=fH6sR4fgv`IukRCodHmCFsnFc3s%5d}~}sDLwR0!n}ipn~wJ04g9Q zKoj9i1*8NzSjJI;f@LKf$RW|r#pBQJvwZLXeV0@w*8Pgpi?^R=vYR$Fi1qN~5P5Ca znIx%m;{fvt=)*aMywD<^ISX`B*3P)HtnUW^xbfC0e$-u(Q{_v`SNH;q(6J0)00S7n z0RK=Z4;Dx>3=H2QJ%R<=a8Gr4J=1yAe+r76R2fVPDr~I5PC5E7n zF7o8q6d^Xj4)Rp~avAt{5u7JK%;GV-2mz9%GIrnvpS4D2FwK81rT3U^kOQR!8ug#} z#EiHt`SjfL3=TTj*o9G_=1Zl@0v9292y&2oH){bd6j+q1QVfnmY@b#|sSIe*!x1)& zzQlWwgD1F7<&?CXaogv!mM+V(#`*P9rcC;of*7p6Ow4&3PHPS<6$D>6a4SQz#bpD0 z23JYeQT9t_!47{Yx7?iAnJfR5Te5}`OiURhrw!Dl^zdeA0B z*a<#h1>85VW$G)3QD5jvntUE?6ShGeOmg;$Cc8ODqsZvaTY#oG`4AF)sN;Bxy5Uw{dEmI4%@ z00k(Z3pMP#I1bKqYi0XBq`Z5Ww0UYL+=Jy#NPiB$QzG RH1Plc002ovPDHLkV1h>XS)l*` diff --git a/editor/resources/editor/icons/light/navigator-element/array-purple-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-purple-12x12@2x.png index c0b4e9ef03752d0ce7c2a7117c24771c549ad014..d9146a1a37f00109b2a73a1d4a775bcba7117eb6 100644 GIT binary patch delta 614 zcmV-s0-62t1cL~$sR4fiL`g(JRCoc+RZDIgF${f_oz}bh2!o^rx~q>6pP=yx>YTv! zBB{}h?M>li<(we)3F;fvH^^jHpmi`u@X}~A!;%^)8BdgE0`wCC18FGnks==@;4ce3 zX7k`B?}HIx2g}JPGK zjfCaNirNM6QOSR7EPYYd-BaWg-Li@q`-9gUx!(g9UdI@;o$g%-svc6>h6+eyWBISA zS&Kt$j5itQy&$@vP4EOiGR(?OggxfmI5e_yigNUPy1i;{hAYPX9JCN%m z1KyJM1Yth;PD}g`**d{TVNdp(M)K>SX!YXT)X_3hpHF|^D8A!Bcz-Ur?YiHjUPH%k zwCOVVBGbsPn`dbIzR-6f%kUX+1qY_SFKm(ZI(Fci&!qxgrxwr(8w?BJDiQy*Ix7Nx z?!oPTDg5ysAKW+)jekhSu9*@w@Vw{khbA|XzVN3jIY$xGxFaP_-4oAx)TnqJEAPwp z@^RDoz$1z?dK<|N&zegAUjcc*1U<_D1~7mD z4A6yw3gSv!Ds*M)|MyjrwR@=HKn$k|z?mbdX(ST00MQO=nT!$Y3l4=Rj^RJJKL7v# M07*qoM6N<$f=3WntN;K2 diff --git a/editor/resources/editor/icons/light/navigator-element/array-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-red-12x12@2x.png index 1b2f9d575feba46371cb80c25c5bed92d745f71b..0da44d0c5c368074f23b4152d11ab25e88dcb267 100644 GIT binary patch delta 519 zcmV+i0{H#v1f>VCsR4fh=1D|BRCoc+RqJuWFbtN{{x2hBgLZ^4LFohy3zRScut8D= z049J9$Oga$9)Stsezuihf&=ERFW)78=vI7=|a_(~yj86p!5pyJUE z{}<+$y;0MVWoBO5BC zSccp~5C9bEuoPCY2^BnuhC#A)$3V!M9pk5nGEWk^4@)D z8YPM2U3^KmIvGIcy>U&q<24I7?O6C4+kxjJHT7|3fOG&%-s^bBAPj16PRwH1stc?m zlm9juTwZgEB$+SG>I~DyO~>-$QRi^gS+;3s8PgN8o|p7n;|q}|&O|HrK*#_9002ov JPDHLkV1jBt@<{*y delta 202 zcmV;*05$)m2kHc{sR4fgt4TybRCodHmCX%i<(%;L}0fbReucO_E(!Zp3 zCl52_hTJxmFe~%nnX{b@dFIxydH^PK^d;inxAW~Q3;_XbECE6YKmY;|z#8)8L2xB} zVe6^v|Mxx-KI1NMC|m$&0>g%e(!5Lp_(D+^nFPmE1(^XXk0bqiP5=M^07*qoM6N<$ Eg3O{+=Kufz diff --git a/editor/resources/editor/icons/light/navigator-element/array-white-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/array-white-12x12@2x.png index d6ba6d396ad1cbf27f3064a094507ac67981885f..78992445a1d50fad2db384e76984896e1d2626ba 100644 GIT binary patch delta 389 zcmV;00eb$q1f&MAsR4fhWl2OqRCoc+Re@2%Fbq^U2Ji^kfNnt8AZ(Bg=mwMtnhgRI zzy|FGfeDfgk`0VZUsQGNHa=3Wf2VUUZ^`momWeKmEM>B_w%{RW+h$qT)12Votv$q& z<^l(+5VT`^$M?Wy&iUTZG~^iHSei#3M>YfdJ2=x)Wi3*5G$(&JV6F5YaNuW=T15-m z$@0lkjda!EY@bjy7L}8G{4=C-wx$#~DeN&eUT`0)lm%)VMh;#o$yHZzs;X`yYxI%- zqc`5s{w~CPf;%uue?hJIGO)XfQsCrZd&L2-0(=Fou@mpa<$>yPhh|Rk5zfGO5ewcZ zJv%)Sa&;b`E8cwt9u&X!gG)PhlQ!}lSzOR4z6F7DJ8gOL6i(X!O5dIG{FG*AvcQ>G`(89kgrc<}x{Y)DckH j^@rcC!57&1mi`Oh3=AsC#wr9D00000NkvXXu0mjfp&PaN delta 153 zcmV;K0A~NB2Dt>VsR4fgdPzh&-bV1Si{k>K+3)d=rM4Fkak-p;^kobYeOSByo zGGhj2Urn?0^JK`8PmxEa%^Z#tgvVIX`k@+?&00000NkvXX Hu0mjf31&UL diff --git a/editor/src/uuiui/styles/theme/dark.ts b/editor/src/uuiui/styles/theme/dark.ts index 896eb375896c..bf7018b93e12 100644 --- a/editor/src/uuiui/styles/theme/dark.ts +++ b/editor/src/uuiui/styles/theme/dark.ts @@ -22,6 +22,7 @@ const darkBase = { brandNeonGreen: createUtopiColor('oklch(86.6% 0.27 158.6)'), green: createUtopiColor('oklch(88% 0.2535 150)'), green10: createUtopiColor('oklch(88% 0.2535 150 / 10%)'), + green20: createUtopiColor('oklch(88% 0.2535 150 / 20%)'), pinkSubdued: createUtopiColor('oklch(33% 0.07 327)'), secondaryBlue: createUtopiColor('oklch(75.44% 0.138 251.22)'), secondaryOrange: createUtopiColor('oklch(81.8% 0.141 47)'), @@ -29,6 +30,7 @@ const darkBase = { lightDenimBlue: createUtopiColor('oklch(25% 0.07 255)'), selectionBlue: createUtopiColor('oklch(66.9% 0.18 248.8)'), selectionBlue10: createUtopiColor('oklch(66.9% 0.18 248.8 / 10%)'), + selectionBlue20: createUtopiColor('oklch(66.9% 0.18 248.8 / 20%)'), childSelectionBlue: createUtopiColor('oklch(35.15% 0.11 243)'), selectionPurple: createUtopiColor('oklch(53.22% 0.28 289.7)'), childSelectionPurple: createUtopiColor('oklch(32.25% 0.13 293.16)'), diff --git a/editor/src/uuiui/styles/theme/light.ts b/editor/src/uuiui/styles/theme/light.ts index 5977a933ace3..81a84e7b9d4e 100644 --- a/editor/src/uuiui/styles/theme/light.ts +++ b/editor/src/uuiui/styles/theme/light.ts @@ -22,6 +22,7 @@ const lightBase = { brandNeonGreen: createUtopiColor('oklch(86.6% 0.27 158.6)'), green: createUtopiColor('oklch(64.6% 0.17 150.6)'), green10: createUtopiColor('oklch(64.6% 0.17 150.6 / 10%)'), + green20: createUtopiColor('oklch(64.6% 0.17 150.6 / 20%)'), pinkSubdued: createUtopiColor('oklch(92% 0.076 326)'), secondaryBlue: createUtopiColor('oklch(74.5% 0.14 241.9)'), secondaryOrange: createUtopiColor('oklch(78.97% 0.192 70)'), @@ -29,6 +30,7 @@ const lightBase = { lightDenimBlue: createUtopiColor('oklch(97% 0.02 254)'), selectionBlue: createUtopiColor('oklch(66.9% 0.18 248.8)'), selectionBlue10: createUtopiColor('oklch(66.9% 0.18 248.8 / 10%)'), + selectionBlue20: createUtopiColor('oklch(66.9% 0.18 248.8 / 20%)'), childSelectionBlue: createUtopiColor('oklch(92.39% 0.05 236.2)'), selectionPurple: createUtopiColor('oklch(53.22% 0.28 289.7)'), childSelectionPurple: createUtopiColor('oklch(89.45% 0.06 302.7)'), From df6115817b816ef0f5a63b4864c02da8c89db585 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Wed, 5 Jun 2024 21:28:25 +0200 Subject: [PATCH 027/103] unified cartouche datatype (#5836) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** The cartouche sometimes shows `[ ]` icons, sometimes the `{ }` icon, and other times the 🌺 icon. But these icons were not synchronized across the various places rendering cartouches. Despite them sharing the same component they don't share the same data sources, so some more unification was needed. **Fix:** Create a new helper function `getCartoucheDataTypeForExpression` which takes a unified approach to coming up with the right icon to show for the cartouche, so it is the same inside the data picker, navigator, and the inspector. **Commit Details:** - Created `getCartoucheDataTypeForExpression` - Created helper `getSpiedValueForIdentifierOrAccess` – I tried to look for code to reuse for this one, but couldn't find much - Added `datatype: CartoucheDataType` to the various cartouche wrapper component props - Filling `props.datatype` with data from `getCartoucheDataTypeForExpression` **Note:** - The data picker is the last remaining place which uses a separate data source called `childTypeToCartoucheDataType` that is coming from the `VariableInfo` internal type. the reason I'm keeping it separate is because for dozens of cartouches I'm worried it would add extra cost to call out to `getCartoucheDataTypeForExpression`. the results today match up, but if there is a slight divergence we can switch this to getCartoucheDataTypeForExpression too, but it needs some careful performance investigation then. --- .../editor/store/store-hook-substore-types.ts | 4 + .../src/components/editor/store/store-hook.ts | 11 ++ .../component-section/cartouche-control.tsx | 3 + .../component-section/cartouche-ui.tsx | 6 +- .../component-section/component-section.tsx | 26 +++- .../data-reference-cartouche.tsx | 24 +++- .../variables-in-scope-utils.ts | 121 ++++++++++++++++-- .../sections/data-reference-section.tsx | 9 +- .../layout-section/list-source-cartouche.tsx | 25 +++- 9 files changed, 211 insertions(+), 18 deletions(-) diff --git a/editor/src/components/editor/store/store-hook-substore-types.ts b/editor/src/components/editor/store/store-hook-substore-types.ts index 99c12e99764f..949830c50128 100644 --- a/editor/src/components/editor/store/store-hook-substore-types.ts +++ b/editor/src/components/editor/store/store-hook-substore-types.ts @@ -198,6 +198,10 @@ export type CanvasAndMetadataSubstate = { export type ProjectContentAndMetadataSubstate = ProjectContentSubstate & MetadataSubstate +export type ProjectContentAndMetadataAndVariablesInScopeSubstate = ProjectContentSubstate & + MetadataSubstate & + VariablesInScopeSubstate + export type NavigatorSubstate = { editor: Pick } diff --git a/editor/src/components/editor/store/store-hook.ts b/editor/src/components/editor/store/store-hook.ts index a2819bf14aef..73757683b771 100644 --- a/editor/src/components/editor/store/store-hook.ts +++ b/editor/src/components/editor/store/store-hook.ts @@ -31,6 +31,7 @@ import type { NavigatorSubstate, OnlineStateSubstate, PostActionInteractionSessionSubstate, + ProjectContentAndMetadataAndVariablesInScopeSubstate, ProjectContentAndMetadataSubstate, ProjectContentSubstate, ProjectServerStateSubstate, @@ -303,6 +304,16 @@ export const Substores = { ) => { return keysEquality([...projectContentsKeys, ...metadataSubstateKeys], a.editor, b.editor) }, + projectContentsAndMetadataAndVariablesInScope: ( + a: ProjectContentAndMetadataAndVariablesInScopeSubstate, + b: ProjectContentAndMetadataAndVariablesInScopeSubstate, + ) => { + return keysEquality( + [...projectContentsKeys, ...metadataSubstateKeys, ...variablesInScopeSubstateKeys], + a.editor, + b.editor, + ) + }, projectServerState: (a: ProjectServerStateSubstate, b: ProjectServerStateSubstate) => { return ProjectServerStateKeepDeepEquality(a.projectServerState, b.projectServerState).areEqual }, diff --git a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx index 498b041ea685..2bb7b1168b18 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx @@ -8,6 +8,7 @@ import type { ElementPath, PropertyPath } from '../../../../core/shared/project- import * as EPP from '../../../template-property-path' import { dataPathSuccess, traceDataFromProp } from '../../../../core/data-tracing/data-tracing' import { Substores, useEditorState } from '../../../editor/store/store-hook' +import type { CartoucheDataType } from './cartouche-ui' interface IdentifierExpressionCartoucheControlProps { contents: string @@ -19,6 +20,7 @@ interface IdentifierExpressionCartoucheControlProps { testId: string propertyPath: PropertyPath elementPath: ElementPath + datatype: CartoucheDataType } export const IdentifierExpressionCartoucheControl = React.memo( (props: IdentifierExpressionCartoucheControlProps) => { @@ -47,6 +49,7 @@ export const IdentifierExpressionCartoucheControl = React.memo( testId={testId} inverted={false} contentIsComingFromServer={isDataComingFromHookResult} + datatype={props.datatype} /> ) }, diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index b6a50591d957..8c396726ecd6 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -7,11 +7,13 @@ export interface HoverHandlers { onMouseLeave: (e: React.MouseEvent) => void } +export type CartoucheDataType = 'renderable' | 'boolean' | 'array' | 'object' | 'unknown' + export type CartoucheUIProps = React.PropsWithChildren<{ tooltip?: string | null source: 'internal' | 'external' | 'literal' role: 'selection' | 'information' | 'folder' - datatype: 'renderable' | 'boolean' | 'array' | 'object' + datatype: CartoucheDataType inverted: boolean selected: boolean testId: string @@ -173,6 +175,8 @@ function dataTypeToIconType(dataType: CartoucheUIProps['datatype']): string { return 'array' case 'object': return 'object' + case 'unknown': + return '👻' } } diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index d452d1a379e2..c82a83fcd38b 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -96,7 +96,10 @@ import { stopPropagation } from '../../common/inspector-utils' import { IdentifierExpressionCartoucheControl } from './cartouche-control' import { getRegisteredComponent } from '../../../../core/property-controls/property-controls-utils' import type { EditorAction } from '../../../editor/action-types' -import { useVariablesInScopeForSelectedElement } from './variables-in-scope-utils' +import { + getCartoucheDataTypeForExpression, + useVariablesInScopeForSelectedElement, +} from './variables-in-scope-utils' import { useAtom } from 'jotai' import { DataSelectorModal } from './data-selector-modal' import { getModifiableJSXAttributeAtPath } from '../../../../core/shared/jsx-attribute-utils' @@ -202,12 +205,27 @@ const ControlForProp = React.memo((props: ControlForPropProps { + if (attributeExpression == null) { + return 'unknown' + } + return getCartoucheDataTypeForExpression( + props.elementPath, + attributeExpression, + store.editor.variablesInScope, + ) + }, + 'ControlForProp datatypeForExpression', + ) + if (controlDescription == null) { return null } - const attributeExpression = props.propMetadata.attributeExpression - if (attributeExpression != null) { if ( attributeExpression.type === 'JS_IDENTIFIER' || @@ -225,6 +243,7 @@ const ControlForProp = React.memo((props: ControlForPropProps ) } @@ -246,6 +265,7 @@ const ControlForProp = React.memo((props: ControlForPropProps ) } diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index 43bbd7d84c4a..7bf0a01de992 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -16,10 +16,13 @@ import { selectComponents } from '../../../editor/actions/meta-actions' import { dataPathSuccess, traceDataFromElement } from '../../../../core/data-tracing/data-tracing' import type { RenderedAt } from '../../../editor/store/editor-state' import { replaceElementInScope } from '../../../editor/actions/action-creators' -import { useVariablesInScopeForSelectedElement } from './variables-in-scope-utils' +import { + getCartoucheDataTypeForExpression, + useVariablesInScopeForSelectedElement, +} from './variables-in-scope-utils' import { DataPickerPreferredAllAtom, jsxElementChildToValuePath } from './data-picker-utils' import { useAtom } from 'jotai' -import type { CartoucheUIProps } from './cartouche-ui' +import type { CartoucheDataType, CartoucheUIProps } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' interface DataReferenceCartoucheControlProps { @@ -107,6 +110,18 @@ export const DataReferenceCartoucheControl = React.memo( [childOrAttribute], ) + const currentlySelectedValueDataType = useEditorState( + Substores.projectContentsAndMetadataAndVariablesInScope, + (store) => { + return getCartoucheDataTypeForExpression( + elementPath, + childOrAttribute, + store.editor.variablesInScope, + ) + }, + 'DataReferenceCartoucheControl currentlySelectedValueDataType', + ) + const dataPickerButtonData = useDataPickerButton( variableNamesInScope, updateDataWithDataPicker, @@ -134,6 +149,7 @@ export const DataReferenceCartoucheControl = React.memo( testId={`data-reference-cartouche-${EP.toString(elementPath)}`} contentIsComingFromServer={isDataComingFromHookResult} hideTooltip={props.hideTooltip} + datatype={currentlySelectedValueDataType} /> {/* this div prevents the popup form putting padding into the condensed rows */}
@@ -155,6 +171,7 @@ interface DataCartoucheInnerProps { testId: string contentIsComingFromServer: boolean hideTooltip?: boolean + datatype: CartoucheDataType } export const DataCartoucheInner = React.forwardRef( @@ -169,6 +186,7 @@ export const DataCartoucheInner = React.forwardRef( testId, contentsToDisplay, contentIsComingFromServer, + datatype, } = props const onDeleteInner = React.useCallback( @@ -193,7 +211,7 @@ export const DataCartoucheInner = React.forwardRef( onDelete={onDelete} onClick={onClick} onDoubleClick={onDoubleClick} - datatype='renderable' // TODO actually feed the real value here + datatype={datatype} selected={selected} inverted={inverted} testId={testId} diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index 241238a52a00..91be4cf302b2 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -1,10 +1,11 @@ +import * as ObjectPath from 'object-path' import type { ControlDescription, ArrayControlDescription, ObjectControlDescription, } from '../../../custom-code/internal-property-controls' import type { ElementPath, PropertyPath } from '../../../../core/shared/project-file-types' -import type { FileRootPath, VariableData } from '../../../canvas/ui-jsx-canvas' +import type { FileRootPath, VariableData, VariablesInScope } from '../../../canvas/ui-jsx-canvas' import { useEditorState, Substores } from '../../../editor/store/store-hook' import type { DataPickerFilterOption, DataPickerOption } from './data-picker-utils' import * as EP from '../../../../core/shared/element-path' @@ -16,6 +17,13 @@ import { assertNever, identity } from '../../../../core/shared/utils' import { isValidReactNode } from '../../../../utils/react-utils' import { MetadataUtils } from '../../../../core/model/element-metadata-utils' import { emptySet } from '../../../../core/shared/set-utils' +import type { JSExpression, JSXElementChild } from '../../../../core/shared/element-template' +import type { Either } from '../../../../core/shared/either' +import { foldEither, isLeft, left, right } from '../../../../core/shared/either' +import { processJSPropertyAccessors } from '../../../../core/data-tracing/data-tracing' +import type { CartoucheDataType } from './cartouche-ui' +import { jsxSimpleAttributeToValue } from '../../../../core/shared/jsx-attribute-utils' +import type { ModifiableAttribute } from '../../../../core/shared/jsx-attributes' function valuesFromObject( variable: ArrayInfo | ObjectInfo, @@ -482,17 +490,17 @@ export function useVariablesInScopeForSelectedElement( return variableNamesInScope } -function arrayShapesMatch(left: Array, right: Array): boolean { - if (left.length === 0 || right.length === 0) { +function arrayShapesMatch(l: Array, r: Array): boolean { + if (l.length === 0 || r.length === 0) { return true } - return variableShapesMatch(left[0], right[0]) + return variableShapesMatch(l[0], r[0]) } -function objectShapesMatch(left: object, right: object): boolean { - const keysFromLeft = Object.keys(left) - const keysFromRight = Object.keys(right) +function objectShapesMatch(l: object, r: object): boolean { + const keysFromLeft = Object.keys(l) + const keysFromRight = Object.keys(r) const keysMatch = keysFromLeft.length === keysFromRight.length && keysFromLeft.every((key) => keysFromRight.includes(key)) @@ -501,7 +509,7 @@ function objectShapesMatch(left: object, right: object): boolean { return false } - return keysFromLeft.every((key) => variableShapesMatch((left as any)[key], (right as any)[key])) + return keysFromLeft.every((key) => variableShapesMatch((l as any)[key], (r as any)[key])) } function variableShapesMatch(current: unknown, other: unknown): boolean { @@ -608,3 +616,100 @@ function usePropertyValue( return { type: 'existing', value: prop } } + +export function getCartoucheDataTypeForExpression( + enclosingScope: ElementPath, + expression: JSXElementChild | ModifiableAttribute, + variablesInScope: VariablesInScope, +): CartoucheDataType { + switch (expression.type) { + case 'ATTRIBUTE_FUNCTION_CALL': + case 'ATTRIBUTE_NESTED_ARRAY': + case 'ATTRIBUTE_NESTED_OBJECT': + case 'ATTRIBUTE_OTHER_JAVASCRIPT': + return 'unknown' + case 'JSX_ELEMENT': + case 'JSX_FRAGMENT': + case 'JSX_MAP_EXPRESSION': + case 'JSX_CONDITIONAL_EXPRESSION': + case 'JSX_TEXT_BLOCK': + return 'renderable' + case 'ATTRIBUTE_VALUE': + case 'PART_OF_ATTRIBUTE_VALUE': + case 'ATTRIBUTE_NOT_FOUND': + return foldEither( + () => 'unknown', + (value) => getCartoucheDataTypeFromJsValue(value), + jsxSimpleAttributeToValue(expression), + ) + case 'JS_IDENTIFIER': + case 'JS_ELEMENT_ACCESS': + case 'JS_PROPERTY_ACCESS': + return foldEither( + () => 'unknown', + (value) => getCartoucheDataTypeFromJsValue(value), + getSpiedValueForIdentifierOrAccess(enclosingScope, expression, variablesInScope), + ) + default: + assertNever(expression) + } +} + +function getCartoucheDataTypeFromJsValue(value: unknown): CartoucheDataType { + if (React.isValidElement(value) || typeof value === 'string' || typeof value === 'number') { + return 'renderable' + } else if (Array.isArray(value)) { + return 'array' + } else if (typeof value === 'object' && value != null) { + return 'object' + } else { + return 'unknown' + } +} + +function getSpiedValueForIdentifierOrAccess( + enclosingScope: ElementPath, + expression: JSExpression, + variablesInScope: VariablesInScope, +): Either { + const accessorPath = processJSPropertyAccessors(expression) + if (isLeft(accessorPath)) { + return accessorPath + } + const spiedValue = findClosestMatchingScope(variablesInScope, enclosingScope)?.[ + accessorPath.value.originalIdentifier.name + ]?.spiedValue + + if (spiedValue == null) { + return left('Variable not found in scope') + } + + if (accessorPath.value.path.length === 0) { + return right(spiedValue) + } + + if (typeof spiedValue !== 'object') { + return left('Cannot access properties of a non-object') + } + + const value = ObjectPath.get(spiedValue, accessorPath.value.path) + + return right(value) +} + +function findClosestMatchingScope( + variablesInScope: VariablesInScope, + targetScope: ElementPath, +): VariableData | null { + if (targetScope.type === 'elementpath') { + const allPaths = EP.allPathsInsideComponent(targetScope) + for (const path of allPaths) { + const variableData = variablesInScope[EP.toString(path)] + if (variableData != null) { + return variableData + } + } + } + + return null +} diff --git a/editor/src/components/inspector/sections/data-reference-section.tsx b/editor/src/components/inspector/sections/data-reference-section.tsx index 30addcc58a4c..421d5b24162a 100644 --- a/editor/src/components/inspector/sections/data-reference-section.tsx +++ b/editor/src/components/inspector/sections/data-reference-section.tsx @@ -20,7 +20,10 @@ import { useDispatch } from '../../editor/store/dispatch-context' import { replaceElementInScope } from '../../editor/actions/action-creators' import { NO_OP } from '../../../core/shared/utils' import { dataPathSuccess, traceDataFromElement } from '../../../core/data-tracing/data-tracing' -import { useVariablesInScopeForSelectedElement } from './component-section/variables-in-scope-utils' +import { + getCartoucheDataTypeForExpression, + useVariablesInScopeForSelectedElement, +} from './component-section/variables-in-scope-utils' import { jsxElementChildToValuePath } from './component-section/data-picker-utils' export const DataReferenceSectionId = 'code-element-section-test-id' @@ -37,7 +40,7 @@ export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[ React.useState(null) const elements = useEditorState( - Substores.projectContentsAndMetadata, + Substores.projectContentsAndMetadataAndVariablesInScope, (store) => { return mapDropNulls((path) => { const element = getElementFromProjectContents(path, store.editor.projectContents) @@ -63,6 +66,7 @@ export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[ textContent: getTextContentOfElement(element, elementMetadata), path: path, contentIsComingFromServer: isDataComingFromServer.type === 'hook-result', + datatype: getCartoucheDataTypeForExpression(path, element, store.editor.variablesInScope), } }, paths) }, @@ -172,6 +176,7 @@ export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[ onDelete={NO_OP} testId={`inspector-data-cartouche-${EP.toString(element.path)}`} contentIsComingFromServer={element.contentIsComingFromServer} + datatype={element.datatype} /> ) diff --git a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx index 119667466f39..6109875da6b9 100644 --- a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx @@ -20,9 +20,13 @@ import { DataPickerPreferredAllAtom, jsxElementChildToValuePath, } from '../component-section/data-picker-utils' -import { useVariablesInScopeForSelectedElement } from '../component-section/variables-in-scope-utils' +import { + getCartoucheDataTypeForExpression, + useVariablesInScopeForSelectedElement, +} from '../component-section/variables-in-scope-utils' import { mapDropNulls } from '../../../../core/shared/array-utils' import { traceDataFromElement, dataPathSuccess } from '../../../../core/data-tracing/data-tracing' +import type { CartoucheDataType } from '../component-section/cartouche-ui' function filterVariableOption(option: DataPickerOption): DataPickerOption | null { switch (option.type) { @@ -153,6 +157,24 @@ export const MapListSourceCartouche = React.memo((props: MapListSourceCartoucheP 'ListSection isDataComingFromHookResult', ) + const cartoucheDataType: CartoucheDataType = useEditorState( + Substores.projectContentsAndMetadataAndVariablesInScope, + (store) => { + if ( + originalMapExpression === 'multiselect' || + originalMapExpression === 'not-a-mapexpression' + ) { + return 'unknown' + } + return getCartoucheDataTypeForExpression( + target, + originalMapExpression.valueToMap, + store.editor.variablesInScope, + ) + }, + 'MapListSourceCartouche cartoucheDataType', + ) + if (originalMapExpression === 'multiselect' || originalMapExpression === 'not-a-mapexpression') { return null } @@ -183,6 +205,7 @@ export const MapListSourceCartouche = React.memo((props: MapListSourceCartoucheP safeToDelete={false} testId='list-source-cartouche' contentIsComingFromServer={isDataComingFromHookResult} + datatype={cartoucheDataType} />
) From 93677438fe46dbfd9f1a9b4548146fe919adaad0 Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Thu, 6 Jun 2024 12:47:04 +0300 Subject: [PATCH 028/103] chore: re-export relevant types from utopia-shared (#5811) **Problem:** as we moved types from our editor to `utopia-shared`- we need to make sure they don't diverge. **Fix:** since a lot of places in the code currently import those files, we make sure that `element-template.ts` in the editor re-exports the source of truth types from `utopia-shared` **Manual Tests:** I hereby swear that: - [X] I opened a hydrogen project and it loaded - [X] I could navigate to various routes in Preview mode --- editor/src/components/assets.ts | 45 +- editor/src/core/shared/element-template.ts | 551 ++++++------------ editor/src/core/shared/error-messages.ts | 29 +- .../workers/ts/ts-typings/RawSourceMap.ts | 12 +- utopia-shared/src/types/RawSourceMap.ts | 10 + utopia-shared/src/types/element-template.ts | 34 +- 6 files changed, 209 insertions(+), 472 deletions(-) create mode 100644 utopia-shared/src/types/RawSourceMap.ts diff --git a/editor/src/components/assets.ts b/editor/src/components/assets.ts index 1dc9a2ec4acc..91ac6a474218 100644 --- a/editor/src/components/assets.ts +++ b/editor/src/components/assets.ts @@ -20,10 +20,21 @@ import type { FileChecksumsWithFile } from './editor/store/editor-state' import { memoize } from '../core/shared/memoize' import type { Optic } from '../core/shared/optics/optics' import { traversal } from '../core/shared/optics/optics' - -export interface AssetFileWithFileName { - fileName: string - file: ImageFile | AssetFile +import type { + AssetFileWithFileName, + ProjectContentTreeRoot, + ProjectContentDirectory, + ProjectContentFile, + ProjectContentsTree, + PathAndFileEntry, +} from 'utopia-shared/src/types/assets' +export type { + AssetFileWithFileName, + ProjectContentTreeRoot, + ProjectContentDirectory, + ProjectContentFile, + ProjectContentsTree, + PathAndFileEntry, } export function getAllProjectAssetFiles( @@ -192,17 +203,6 @@ export function deriveGithubFileChanges( } } -// Ensure this is kept up to date with clientmodel/lib/src/Utopia/ClientModel.hs. -export type ProjectContentTreeRoot = { [key: string]: ProjectContentsTree } - -// Ensure this is kept up to date with clientmodel/lib/src/Utopia/ClientModel.hs -export interface ProjectContentDirectory { - type: 'PROJECT_CONTENT_DIRECTORY' - fullPath: string - directory: Directory - children: ProjectContentTreeRoot -} - export function projectContentDirectory( fullPath: string, dir: Directory, @@ -216,13 +216,6 @@ export function projectContentDirectory( } } -// Ensure this is kept up to date with clientmodel/lib/src/Utopia/ClientModel.hs. -export interface ProjectContentFile { - type: 'PROJECT_CONTENT_FILE' - fullPath: string - content: TextFile | ImageFile | AssetFile -} - export function projectContentFile( fullPath: string, content: TextFile | ImageFile | AssetFile, @@ -234,9 +227,6 @@ export function projectContentFile( } } -// Ensure this is kept up to date with clientmodel/lib/src/Utopia/ClientModel.hs. -export type ProjectContentsTree = ProjectContentDirectory | ProjectContentFile - export function isProjectContentDirectory( projectContentsTree: ProjectContentsTree | null, ): projectContentsTree is ProjectContentDirectory { @@ -383,11 +373,6 @@ export function walkContentsTree( }) } -export interface PathAndFileEntry { - fullPath: string - file: ProjectFile -} - export const contentsTreeOptic: Optic = traversal( (tree) => { let result: Array = [] diff --git a/editor/src/core/shared/element-template.ts b/editor/src/core/shared/element-template.ts index 072e1180260c..af6d66b0fc11 100644 --- a/editor/src/core/shared/element-template.ts +++ b/editor/src/core/shared/element-template.ts @@ -33,18 +33,173 @@ import { allComments } from './comment-flags' import type { Optic } from './optics/optics' import { fromField } from './optics/optic-creators' import { jsxSimpleAttributeToValue } from './jsx-attribute-utils' +import type { + ParsedComments, + MultiLineComment, + SingleLineComment, + WithComments, + JSExpressionValue, + PartOfJSXAttributeValue, + JSXAttributeNotFound, + JSOpaqueArbitraryStatement, + JSAssignment, + JSAssignmentStatement, + JSExpressionOtherJavaScript, + JSXMapExpression, + JSXSpreadAssignment, + JSXPropertyAssignment, + JSExpressionNestedObject, + JSXArrayValue, + JSXArraySpread, + JSExpressionNestedArray, + JSExpressionFunctionCall, + JSIdentifier, + JSPropertyAccess, + JSElementAccess, + JSXAttributesEntry, + JSXAttributesSpread, + JSXElementName, + JSXElement, + WithElementsWithin, + JSXTextBlock, + JSXFragment, + JSXConditionalExpression, + RegularParam, + DestructuredParamPart, + DestructuredObject, + DestructuredArray, + UtopiaJSXComponent, + ImportStatement, + UnparsedCode, + SameFileOrigin, + ImportedOrigin, + Comment, + JSArbitraryStatement, + JSXProperty, + JSXArrayElement, + OptionallyChained, + IdentifierOrAccess, + JSExpression, + JSExpressionMapOrOtherJavascript, + JSXAttributesPart, + JSXAttributes, + JSXElementWithoutUID, + JSXConditionalExpressionWithoutUID, + JSXFragmentWithoutUID, + JSXMapExpressionWithoutUID, + ElementsWithin, + JSXElementLike, + JSXElementChild, + JSXElementChildWithoutUID, + JSXElementChildren, + DestructuredArrayPart, + BoundParam, + Param, + VarLetOrConst, + FunctionDeclarationSyntax, + BlockOrExpression, + ArbitraryJSBlock, + TopLevelElement, + ComputedStyle, + StyleAttributeMetadataEntry, + StyleAttributeMetadata, + ImportInfo, + ActiveAndDefaultConditionValues, + ConditionValue, + DetectedLayoutSystem, + TextDirection, + HugProperty, + HugPropertyWidthHeight, + ElementsByUID, +} from 'utopia-shared/src/types/element-template' import type { VariableData } from '../../components/canvas/ui-jsx-canvas' -export interface ParsedComments { - leadingComments: Array - trailingComments: Array - questionTokenComments?: ParsedComments -} - -export const emptyComments: ParsedComments = { - leadingComments: [], - trailingComments: [], -} +export type { + ParsedComments, + MultiLineComment, + SingleLineComment, + WithComments, + JSExpressionValue, + PartOfJSXAttributeValue, + JSXAttributeNotFound, + JSOpaqueArbitraryStatement, + JSAssignment, + JSAssignmentStatement, + JSExpressionOtherJavaScript, + JSXMapExpression, + JSXSpreadAssignment, + JSXPropertyAssignment, + JSExpressionNestedObject, + JSXArrayValue, + JSXArraySpread, + JSExpressionNestedArray, + JSExpressionFunctionCall, + JSIdentifier, + JSPropertyAccess, + JSElementAccess, + JSXAttributesEntry, + JSXAttributesSpread, + JSXElementName, + JSXElement, + WithElementsWithin, + JSXTextBlock, + JSXFragment, + JSXConditionalExpression, + RegularParam, + DestructuredParamPart, + DestructuredObject, + DestructuredArray, + UtopiaJSXComponent, + ImportStatement, + UnparsedCode, + SameFileOrigin, + ImportedOrigin, + Comment, + JSArbitraryStatement, + JSXProperty, + JSXArrayElement, + OptionallyChained, + IdentifierOrAccess, + JSExpression, + JSExpressionMapOrOtherJavascript, + JSXAttributesPart, + JSXAttributes, + JSXElementWithoutUID, + JSXConditionalExpressionWithoutUID, + JSXFragmentWithoutUID, + JSXMapExpressionWithoutUID, + ElementsWithin, + JSXElementLike, + JSXElementChild, + JSXElementChildWithoutUID, + JSXElementChildren, + DestructuredArrayPart, + BoundParam, + Param, + VarLetOrConst, + FunctionDeclarationSyntax, + BlockOrExpression, + ArbitraryJSBlock, + TopLevelElement, + ComputedStyle, + StyleAttributeMetadataEntry, + StyleAttributeMetadata, + ImportInfo, + ActiveAndDefaultConditionValues, + ConditionValue, + DetectedLayoutSystem, + TextDirection, + HugProperty, + HugPropertyWidthHeight, + ElementsByUID, +} + +import { + emptyComments, + emptyComputedStyle, + emptyAttributeMetadata, +} from 'utopia-shared/src/types/element-template' +export { emptyComments, emptyComputedStyle, emptyAttributeMetadata } export function isParsedCommentsEmpty(comments: ParsedComments): boolean { return comments.leadingComments.length === 0 && comments.trailingComments.length === 0 @@ -60,17 +215,6 @@ export function parsedComments( } } -interface BaseComment { - comment: string - rawText: string - trailingNewLine: boolean - pos: number | null -} - -export interface MultiLineComment extends BaseComment { - type: 'MULTI_LINE_COMMENT' -} - export function multiLineComment( comment: string, rawText: string, @@ -86,10 +230,6 @@ export function multiLineComment( } } -export interface SingleLineComment extends BaseComment { - type: 'SINGLE_LINE_COMMENT' -} - export function singleLineComment( comment: string, rawText: string, @@ -105,8 +245,6 @@ export function singleLineComment( } } -export type Comment = MultiLineComment | SingleLineComment - export function isMultiLineComment(comment: Comment): comment is MultiLineComment { return comment.type === 'MULTI_LINE_COMMENT' } @@ -115,20 +253,10 @@ export function isSingleLineComment(comment: Comment): comment is SingleLineComm return comment.type === 'SINGLE_LINE_COMMENT' } -export interface WithComments { - comments: ParsedComments -} - export function isWithComments(e: unknown): e is WithComments { return (e as WithComments).comments != null } -export interface JSExpressionValue extends WithComments { - type: 'ATTRIBUTE_VALUE' - uid: string - value: T -} - export function jsExpressionValue( value: T, comments: ParsedComments, @@ -153,10 +281,6 @@ export function jsExpressionValue( we will get a `PART_OF_ATTRIBUTE_VALUE`, whose value is `'red'`. If alternatively `style` were an `ATTRIBUTE_NESTED_OBJECT`, then each of its contents would all be a `JSXAttribute`, in which case `'red'` might be an `ATTRIBUTE_VALUE` */ -export interface PartOfJSXAttributeValue { - type: 'PART_OF_ATTRIBUTE_VALUE' - value: any -} export function partOfJsxAttributeValue(value: any): PartOfJSXAttributeValue { return { @@ -165,24 +289,12 @@ export function partOfJsxAttributeValue(value: any): PartOfJSXAttributeValue { } } -export interface JSXAttributeNotFound { - type: 'ATTRIBUTE_NOT_FOUND' -} - export function jsxAttributeNotFound(): JSXAttributeNotFound { return { type: 'ATTRIBUTE_NOT_FOUND', } } -export interface JSOpaqueArbitraryStatement { - type: 'JS_OPAQUE_ARBITRARY_STATEMENT' - originalJavascript: string - definedWithin: Array - definedElsewhere: Array - uid: string -} - export function jsOpaqueArbitraryStatement( originalJavascript: string, definedWithin: Array, @@ -198,12 +310,6 @@ export function jsOpaqueArbitraryStatement( } } -export interface JSAssignment { - type: 'JS_ASSIGNMENT' - leftHandSide: BoundParam - rightHandSide: R -} - export function jsAssignment(leftHandSide: BoundParam, rightHandSide: JSExpression): JSAssignment { return { type: 'JS_ASSIGNMENT', @@ -212,13 +318,6 @@ export function jsAssignment(leftHandSide: BoundParam, rightHandSide: JSExpressi } } -export interface JSAssignmentStatement { - type: 'JS_ASSIGNMENT_STATEMENT' - declarationKeyword: 'let' | 'const' | 'var' - assignments: Array - uid: string -} - export function jsAssignmentStatement( declarationKeyword: 'let' | 'const' | 'var', assignments: Array, @@ -249,8 +348,6 @@ export function simpleJSAssignmentStatement( ) } -export type JSArbitraryStatement = JSOpaqueArbitraryStatement | JSAssignmentStatement - export function isJSAssignmentStatement( statement: JSArbitraryStatement, ): statement is JSAssignmentStatement { @@ -263,17 +360,6 @@ export function isJSOpaqueArbitraryStatement( return statement.type === 'JS_OPAQUE_ARBITRARY_STATEMENT' } -export interface JSExpressionOtherJavaScript extends WithComments, WithElementsWithin { - type: 'ATTRIBUTE_OTHER_JAVASCRIPT' - params: Array - originalJavascript: string - javascriptWithUIDs: string - transpiledJavascript: string - definedElsewhere: Array - sourceMap: RawSourceMap | null - uid: string -} - export function jsExpressionOtherJavaScript( params: Array, originalJavascript: string, @@ -315,14 +401,6 @@ export function jsExpressionOtherJavaScriptSimple( ) } -export interface JSXMapExpression extends WithComments { - type: 'JSX_MAP_EXPRESSION' - valueToMap: JSExpression - mapFunction: JSExpression - valuesInScopeFromParameters: Array - uid: string -} - export function jsxMapExpression( valueToMap: JSExpression, mapFunction: JSExpression, @@ -340,11 +418,6 @@ export function jsxMapExpression( } } -export interface JSXSpreadAssignment extends WithComments { - type: 'SPREAD_ASSIGNMENT' - value: JSExpression -} - export function jsxSpreadAssignment( value: JSExpression, comments: ParsedComments, @@ -356,13 +429,6 @@ export function jsxSpreadAssignment( } } -export interface JSXPropertyAssignment extends WithComments { - type: 'PROPERTY_ASSIGNMENT' - key: string | number - value: JSExpression - keyComments: ParsedComments -} - export function jsxPropertyAssignment( key: string | number, value: JSExpression, @@ -378,8 +444,6 @@ export function jsxPropertyAssignment( } } -export type JSXProperty = JSXPropertyAssignment | JSXSpreadAssignment - export function isSpreadAssignment(property: JSXProperty): property is JSXSpreadAssignment { return property.type === 'SPREAD_ASSIGNMENT' } @@ -388,12 +452,6 @@ export function isPropertyAssignment(property: JSXProperty): property is JSXProp return property.type === 'PROPERTY_ASSIGNMENT' } -export interface JSExpressionNestedObject extends WithComments { - type: 'ATTRIBUTE_NESTED_OBJECT' - content: Array - uid: string -} - export function jsExpressionNestedObject( content: Array, comments: ParsedComments, @@ -422,11 +480,6 @@ export function jsxAttributeNestedObjectSimple( } } -export interface JSXArrayValue extends WithComments { - type: 'ARRAY_VALUE' - value: JSExpression -} - export function jsxArrayValue(value: JSExpression, comments: ParsedComments): JSXArrayValue { return { type: 'ARRAY_VALUE', @@ -435,11 +488,6 @@ export function jsxArrayValue(value: JSExpression, comments: ParsedComments): JS } } -export interface JSXArraySpread extends WithComments { - type: 'ARRAY_SPREAD' - value: JSExpression -} - export function jsxArraySpread(value: JSExpression, comments: ParsedComments): JSXArraySpread { return { type: 'ARRAY_SPREAD', @@ -448,8 +496,6 @@ export function jsxArraySpread(value: JSExpression, comments: ParsedComments): J } } -export type JSXArrayElement = JSXArrayValue | JSXArraySpread - export function isArrayValue(elem: JSXArrayElement): elem is JSXArrayValue { return elem.type === 'ARRAY_VALUE' } @@ -458,12 +504,6 @@ export function isArraySpread(elem: JSXArrayElement): elem is JSXArraySpread { return elem.type === 'ARRAY_SPREAD' } -export interface JSExpressionNestedArray extends WithComments { - type: 'ATTRIBUTE_NESTED_ARRAY' - content: Array - uid: string -} - export function jsExpressionNestedArray( content: Array, comments: ParsedComments, @@ -486,13 +526,6 @@ export function jsxAttributeNestedArraySimple( ) } -export interface JSExpressionFunctionCall { - type: 'ATTRIBUTE_FUNCTION_CALL' - functionName: string - parameters: Array - uid: string -} - export function jsExpressionFunctionCall( functionName: string, parameters: Array, @@ -506,13 +539,6 @@ export function jsExpressionFunctionCall( } } -export interface JSIdentifier extends WithComments { - type: 'JS_IDENTIFIER' - name: string - uid: string - sourceMap: RawSourceMap | null -} - export function jsIdentifier( name: string, uid: string, @@ -539,18 +565,6 @@ export function isJSIdentifierForName( return isJSIdentifier(expression) && expression.name === name } -export type OptionallyChained = 'not-optionally-chained' | 'optionally-chained' - -export interface JSPropertyAccess extends WithComments { - type: 'JS_PROPERTY_ACCESS' - onValue: JSExpression - property: string - uid: string - sourceMap: RawSourceMap | null - originalJavascript: string - optionallyChained: OptionallyChained -} - export function jsPropertyAccess( onValue: JSExpression, property: string, @@ -583,16 +597,6 @@ export function isJSPropertyAccessForProperty( return isJSPropertyAccess(expression) && expression.property === property } -export interface JSElementAccess extends WithComments { - type: 'JS_ELEMENT_ACCESS' - onValue: JSExpression - element: JSExpression - uid: string - sourceMap: RawSourceMap | null - originalJavascript: string - optionallyChained: OptionallyChained -} - export function jsElementAccess( onValue: JSExpression, element: JSExpression, @@ -618,8 +622,6 @@ export function isJSElementAccess(expression: JSXElementChild): expression is JS return expression.type === 'JS_ELEMENT_ACCESS' } -export type IdentifierOrAccess = JSIdentifier | JSPropertyAccess | JSElementAccess - export function isIdentifierOrAccess( expression: JSXElementChild, ): expression is IdentifierOrAccess { @@ -628,20 +630,6 @@ export function isIdentifierOrAccess( ) } -export type JSExpression = - | JSIdentifier - | JSPropertyAccess - | JSElementAccess - | JSExpressionValue - | JSExpressionOtherJavaScript - | JSExpressionNestedArray - | JSExpressionNestedObject - | JSExpressionFunctionCall - | JSXMapExpression - | JSXElement - -export type JSExpressionMapOrOtherJavascript = JSExpressionOtherJavaScript | JSXMapExpression - export function clearJSXMapExpressionUniqueIDs(mapExpression: JSXMapExpression): JSXMapExpression { const updatedValueToMap = clearExpressionUniqueIDs(mapExpression.valueToMap) const updatedMapFunction = clearExpressionUniqueIDs(mapExpression.mapFunction) @@ -1126,12 +1114,6 @@ export function modifiableAttributeToValuePath( } } -export interface JSXAttributesEntry extends WithComments { - type: 'JSX_ATTRIBUTES_ENTRY' - key: string | number - value: JSExpression -} - export function jsxAttributesEntry( key: string | number, value: JSExpression, @@ -1149,11 +1131,6 @@ export function simpleAttribute(key: string, value: unknown): JSXAttributesEntry return jsxAttributesEntry(key, jsExpressionValue(value, emptyComments), emptyComments) } -export interface JSXAttributesSpread extends WithComments { - type: 'JSX_ATTRIBUTES_SPREAD' - spreadValue: JSExpression -} - export function jsxAttributesSpread( spreadValue: JSExpression, comments: ParsedComments, @@ -1165,8 +1142,6 @@ export function jsxAttributesSpread( } } -export type JSXAttributesPart = JSXAttributesEntry | JSXAttributesSpread - export function isJSXAttributesEntry(part: JSXAttributesPart): part is JSXAttributesEntry { return part.type === 'JSX_ATTRIBUTES_ENTRY' } @@ -1175,8 +1150,6 @@ export function isJSXAttributesSpread(part: JSXAttributesPart): part is JSXAttri return part.type === 'JSX_ATTRIBUTES_SPREAD' } -export type JSXAttributes = Array - export function jsxAttributesFromMap(map: MapLike): Array { return Object.keys(map).map((objectKey) => { return jsxAttributesEntry(objectKey, map[objectKey], emptyComments) @@ -1563,11 +1536,6 @@ export function clearAttributesSourceMaps(attributes: JSXAttributes): JSXAttribu }) } -export interface JSXElementName { - baseVariable: string - propertyPath: PropertyPath -} - export function jsxElementName( baseVariable: string, propertyPathParts: Array, @@ -1636,22 +1604,6 @@ export function getJSXElementNameAsString(name: JSXElementName): string { } } -export interface JSXElement { - type: 'JSX_ELEMENT' - name: JSXElementName - props: JSXAttributes - children: JSXElementChildren - uid: string -} - -export type JSXElementWithoutUID = Omit - -export type JSXConditionalExpressionWithoutUID = Omit - -export type JSXFragmentWithoutUID = Omit - -export type JSXMapExpressionWithoutUID = Omit - export function clearJSXMapExpressionWithoutUIDUniqueIDs( mapExpression: JSXMapExpressionWithoutUID, ): JSXMapExpressionWithoutUID { @@ -1694,22 +1646,10 @@ export function clearJSXFragmentWithoutUIDUniqueIDs( } } -export type ElementsWithin = { [uid: string]: JSXElement } - -export interface WithElementsWithin { - elementsWithin: ElementsWithin -} - export function hasElementsWithin(e: unknown): e is WithElementsWithin { return (e as WithElementsWithin).elementsWithin != null } -export interface JSXTextBlock { - type: 'JSX_TEXT_BLOCK' - text: string - uid: string -} - export function jsxTextBlock(text: string, uid: string = UUID()): JSXTextBlock { return { type: 'JSX_TEXT_BLOCK', @@ -1718,13 +1658,6 @@ export function jsxTextBlock(text: string, uid: string = UUID()): JSXTextBlock { } } -export interface JSXFragment { - type: 'JSX_FRAGMENT' - uid: string - children: JSXElementChildren - longForm: boolean -} - export function jsxFragment( uid: string, children: JSXElementChildren, @@ -1738,17 +1671,6 @@ export function jsxFragment( } } -export type JSXElementLike = JSXElement | JSXFragment - -export interface JSXConditionalExpression extends WithComments { - type: 'JSX_CONDITIONAL_EXPRESSION' - uid: string - condition: JSExpression - originalConditionString: string - whenTrue: JSXElementChild - whenFalse: JSXElementChild -} - function fixBaseComments(comments: ParsedComments, parentComments: Comment[]): ParsedComments { function commentIsNotIncluded(comment: Comment) { return !parentComments.some( @@ -1811,19 +1733,6 @@ export function jsxConditionalExpressionConditionOptic( return fromField(condition) } -export type JSXElementChild = - | JSXElement - | JSExpression - | JSXTextBlock - | JSXFragment - | JSXConditionalExpression - -export type JSXElementChildWithoutUID = - | JSXElementWithoutUID - | JSXConditionalExpressionWithoutUID - | JSXFragmentWithoutUID - | JSXMapExpressionWithoutUID - export function canBeRootElementOfComponent(element: JSXElementChild): boolean { if (isJSXElement(element) || isJSXFragment(element) || isJSXConditionalExpression(element)) { return true @@ -1928,8 +1837,6 @@ export function isElementWithUid(element: unknown): element is ElementWithUid { return (element as ElementWithUid).uid != null } -export type JSXElementChildren = Array - export function clearJSXElementUniqueIDs(element: JSXElement): JSXElement { const updatedProps = clearAttributesUniqueIDs(element.props) const updatedChildren: JSXElementChildren = element.children.map(clearJSXElementChildUniqueIDs) @@ -2146,12 +2053,6 @@ export function unparsedCode(rawCode: string): UnparsedCode { } } -export interface RegularParam { - type: 'REGULAR_PARAM' - paramName: string - defaultExpression: JSExpression | null -} - export function regularParam( paramName: string, defaultExpression: JSExpression | null, @@ -2163,12 +2064,6 @@ export function regularParam( } } -export interface DestructuredParamPart { - propertyName: string | undefined - param: Param - defaultExpression: JSExpression | null -} - export function destructuredParamPart( propertyName: string | undefined, param: Param, @@ -2181,11 +2076,6 @@ export function destructuredParamPart( } } -export interface DestructuredObject { - type: 'DESTRUCTURED_OBJECT' - parts: Array -} - export function destructuredObject(parts: Array): DestructuredObject { return { type: 'DESTRUCTURED_OBJECT', @@ -2203,13 +2093,6 @@ export function omittedParam(): OmittedParam { } } -export type DestructuredArrayPart = Param | OmittedParam - -export interface DestructuredArray { - type: 'DESTRUCTURED_ARRAY' - parts: Array -} - export function isOmittedParam(param: DestructuredArrayPart): param is OmittedParam { return param.type === 'OMITTED_PARAM' } @@ -2225,8 +2108,6 @@ export function destructuredArray(parts: Array): Destruct } } -export type BoundParam = RegularParam | DestructuredObject | DestructuredArray - export function isRegularParam(param: BoundParam): param is RegularParam { return param.type === 'REGULAR_PARAM' } @@ -2239,12 +2120,6 @@ export function isDestructuredArray(param: BoundParam): param is DestructuredArr return param.type === 'DESTRUCTURED_ARRAY' } -export type Param = { - type: 'PARAM' - dotDotDotToken: boolean - boundParam: BoundParam -} - export function functionParam(dotDotDotToken: boolean, boundParam: BoundParam): Param { return { type: 'PARAM', @@ -2304,57 +2179,7 @@ export function propertiesExposedByParam(param: Param): Array { } } -export type VarLetOrConst = 'var' | 'let' | 'const' -export type FunctionDeclarationSyntax = 'function' | VarLetOrConst -export type BlockOrExpression = 'block' | 'parenthesized-expression' | 'expression' - -export interface UtopiaJSXComponent { - type: 'UTOPIA_JSX_COMPONENT' - name: string | null - /** - * isFunction is true if we are talking about a Function Component - * isFunction false means that this is an exported Element with no props - * (NOT a component, NOT a class component!) - */ - isFunction: boolean - declarationSyntax: FunctionDeclarationSyntax - blockOrExpression: BlockOrExpression - param: Param | null - propsUsed: Array - rootElement: JSXElementChild - arbitraryJSBlock: ArbitraryJSBlock | null - usedInReactDOMRender: boolean - returnStatementComments: ParsedComments -} - // FIXME we need to inject data-uids using insertDataUIDsIntoCode -export type ArbitraryJSBlock = { - type: 'ARBITRARY_JS_BLOCK' - params: Array - javascript: string - transpiledJavascript: string - definedWithin: Array - definedElsewhere: Array - sourceMap: RawSourceMap | null - statements: Array - uid: string -} & WithElementsWithin - -export interface ImportStatement { - type: 'IMPORT_STATEMENT' - rawCode: string - importStarAs: boolean // Includes `import * as Name from` - importWithName: boolean // Includes `import Name from` - imports: Array // All other imports inside braces i.e. `import { Name } from` - module: string -} - -export interface UnparsedCode { - type: 'UNPARSED_CODE' - rawCode: string -} - -export type TopLevelElement = UtopiaJSXComponent | ArbitraryJSBlock | ImportStatement | UnparsedCode export function clearArbitraryJSBlockUniqueIDs(block: ArbitraryJSBlock): ArbitraryJSBlock { return { @@ -2560,19 +2385,9 @@ export function isUnparsedCode(topLevelElement: TopLevelElement): topLevelElemen return topLevelElement.type === 'UNPARSED_CODE' } -export type ComputedStyle = { [key: string]: string } -export type StyleAttributeMetadataEntry = { fromStyleSheet: boolean } // TODO rename me to StyleAttributeMetadata, the other one to StyleAttributeMetadataMap -export type StyleAttributeMetadata = { [key: string]: StyleAttributeMetadataEntry | undefined } - export type ElementInstanceMetadataMap = { [key: string]: Readonly } export const emptyJsxMetadata: ElementInstanceMetadataMap = {} -export interface SameFileOrigin { - type: 'SAME_FILE_ORIGIN' - filePath: string - variableName: string -} - export function isSameFileOrigin(importInfo: ImportInfo): importInfo is SameFileOrigin { return importInfo.type === 'SAME_FILE_ORIGIN' } @@ -2585,13 +2400,6 @@ export function sameFileOrigin(filePath: string, variableName: string): SameFile } } -export interface ImportedOrigin { - type: 'IMPORTED_ORIGIN' - filePath: string - variableName: string - exportedName: string | null -} - export function isImportedOrigin(importInfo: ImportInfo): importInfo is ImportedOrigin { return importInfo.type === 'IMPORTED_ORIGIN' } @@ -2609,8 +2417,6 @@ export function importedOrigin( } } -export type ImportInfo = SameFileOrigin | ImportedOrigin - export function createImportedFrom( variableName: string, originalName: string | null, @@ -2623,9 +2429,6 @@ export function createNotImported(path: string, variableName: string): ImportInf return sameFileOrigin(path, variableName) } -export type ActiveAndDefaultConditionValues = { active: boolean; default: boolean } -export type ConditionValue = ActiveAndDefaultConditionValues | 'not-a-conditional' - export interface EarlyReturnVoid { type: 'EARLY_RETURN_VOID' spiedVariablesDeclaredWithinBlock: VariableData @@ -2652,6 +2455,8 @@ export function earlyReturnResult(result: unknown): EarlyReturnResult { } } +export type EarlyReturn = EarlyReturnVoid | EarlyReturnResult + export interface ArbitraryBlockRanToEnd { type: 'ARBITRARY_BLOCK_RAN_TO_END' scope: MapLike @@ -2669,8 +2474,6 @@ export function arbitraryBlockRanToEnd( } } -export type EarlyReturn = EarlyReturnVoid | EarlyReturnResult - export type ArbitraryBlockResult = EarlyReturn | ArbitraryBlockRanToEnd export interface ElementInstanceMetadata { @@ -2730,14 +2533,7 @@ export function elementInstanceMetadata( } } -export type DetectedLayoutSystem = 'flex' | 'grid' | 'flow' | 'none' export type SettableLayoutSystem = 'flex' | 'flow' | 'grid' | LayoutSystem -export type TextDirection = 'ltr' | 'rtl' -export type HugProperty = 'hug' | 'squeeze' | 'collapsed' -export type HugPropertyWidthHeight = { - width: HugProperty | null - height: HugProperty | null -} export interface SpecialSizeMeasurements { offset: LocalPoint @@ -2831,8 +2627,8 @@ export function specialSizeMeasurements( coordinateSystemBounds, immediateParentBounds, immediateParentProvidesLayout, - globalFrameWithTextContent: globalFrameWithTextContent, - textBounds: textBounds, + globalFrameWithTextContent, + textBounds, closestOffsetParentPath, usesParentBounds, parentLayoutSystem, @@ -2851,13 +2647,13 @@ export function specialSizeMeasurements( parentFlexGap, parentPadding, parentHugsOnMainAxis, - gap: gap, + gap, flexDirection, justifyContent, alignItems, htmlElementName, renderedChildrenCount, - globalContentBoxForChildren: globalContentBoxForChildren, + globalContentBoxForChildren, float, hasPositionOffset, parentTextDirection, @@ -2918,11 +2714,6 @@ export const emptySpecialSizeMeasurements = specialSizeMeasurements( { width: null, height: null }, ) -export const emptyComputedStyle: ComputedStyle = {} -export const emptyAttributeMetadata: StyleAttributeMetadata = {} - -export type ElementsByUID = { [uid: string]: JSXElement } - export function walkElement( element: JSXElementChild, parentPath: StaticElementPathPart, diff --git a/editor/src/core/shared/error-messages.ts b/editor/src/core/shared/error-messages.ts index b527d6fdf150..3d0a96bb4b40 100644 --- a/editor/src/core/shared/error-messages.ts +++ b/editor/src/core/shared/error-messages.ts @@ -1,26 +1,9 @@ -export type ErrorMessageSeverity = 'fatal' | 'error' | 'warning' - -export type ErrorMessageSource = - | 'eslint' - | 'build' - | 'utopia-parser' - | 'runtime' - | 'component-descriptor' - -export interface ErrorMessage { - fileName: string - startLine: number | null - startColumn: number | null - endLine: number | null - endColumn: number | null - codeSnippet: string - severity: ErrorMessageSeverity - type: string - message: string - errorCode: string - source: ErrorMessageSource - passTime: number | null -} +import type { + ErrorMessageSeverity, + ErrorMessageSource, + ErrorMessage, +} from 'utopia-shared/src/types/error-messages' +export type { ErrorMessageSeverity, ErrorMessageSource, ErrorMessage } export function errorMessage( fileName: string, diff --git a/editor/src/core/workers/ts/ts-typings/RawSourceMap.ts b/editor/src/core/workers/ts/ts-typings/RawSourceMap.ts index 1048e2d4feac..a962020de320 100644 --- a/editor/src/core/workers/ts/ts-typings/RawSourceMap.ts +++ b/editor/src/core/workers/ts/ts-typings/RawSourceMap.ts @@ -1,10 +1,2 @@ -export interface RawSourceMap { - version: number - sources: string[] - names: string[] - sourceRoot?: string - sourcesContent?: string[] - transpiledContentUtopia?: string - mappings: string - file: string -} +import type { RawSourceMap } from 'utopia-shared/src/types/RawSourceMap' +export type { RawSourceMap } diff --git a/utopia-shared/src/types/RawSourceMap.ts b/utopia-shared/src/types/RawSourceMap.ts new file mode 100644 index 000000000000..1048e2d4feac --- /dev/null +++ b/utopia-shared/src/types/RawSourceMap.ts @@ -0,0 +1,10 @@ +export interface RawSourceMap { + version: number + sources: string[] + names: string[] + sourceRoot?: string + sourcesContent?: string[] + transpiledContentUtopia?: string + mappings: string + file: string +} diff --git a/utopia-shared/src/types/element-template.ts b/utopia-shared/src/types/element-template.ts index 69e271925a09..5adf0419099b 100644 --- a/utopia-shared/src/types/element-template.ts +++ b/utopia-shared/src/types/element-template.ts @@ -1,4 +1,5 @@ import type { PropertyPath } from './project-file-types' +import { RawSourceMap } from './RawSourceMap' export interface ParsedComments { leadingComments: Array @@ -66,12 +67,9 @@ export interface JSOpaqueArbitraryStatement { uid: string } -export interface JSAssignment< - L extends JSIdentifier = JSIdentifier, - R extends JSExpression = JSExpression, -> { +export interface JSAssignment { type: 'JS_ASSIGNMENT' - leftHandSide: L + leftHandSide: BoundParam rightHandSide: R } @@ -95,17 +93,6 @@ export interface JSExpressionOtherJavaScript extends WithComments, WithElementsW uid: string } -export interface RawSourceMap { - version: number - sources: string[] - names: string[] - sourceRoot?: string - sourcesContent?: string[] - transpiledContentUtopia?: string - mappings: string - file: string -} - export interface JSXMapExpression extends WithComments { type: 'JSX_MAP_EXPRESSION' valueToMap: JSExpression @@ -296,13 +283,13 @@ export type JSXElementChildren = Array export interface RegularParam { type: 'REGULAR_PARAM' paramName: string - defaultExpression: JSExpressionMapOrOtherJavascript | null + defaultExpression: JSExpression | null } export interface DestructuredParamPart { propertyName: string | undefined param: Param - defaultExpression: JSExpressionMapOrOtherJavascript | null + defaultExpression: JSExpression | null } export interface DestructuredObject { @@ -405,17 +392,6 @@ export type ImportInfo = SameFileOrigin | ImportedOrigin export type ActiveAndDefaultConditionValues = { active: boolean; default: boolean } export type ConditionValue = ActiveAndDefaultConditionValues | 'not-a-conditional' -export interface EarlyReturnVoid { - type: 'EARLY_RETURN_VOID' -} - -export interface EarlyReturnResult { - type: 'EARLY_RETURN_RESULT' - result: unknown -} - -export type EarlyReturn = EarlyReturnVoid | EarlyReturnResult - export type DetectedLayoutSystem = 'flex' | 'grid' | 'flow' | 'none' export type TextDirection = 'ltr' | 'rtl' export type HugProperty = 'hug' | 'squeeze' | 'collapsed' From edab1e300f34a86636f2caea55a1c48448975f5b Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Thu, 6 Jun 2024 13:27:10 +0300 Subject: [PATCH 029/103] Fix: fixing text wrap while editing (#5810) **Problem:** In some elements (such as Hydrogen's text elements) - the default is `text-wrap: pretty` which truncates leading and trailing spaces. This prevents adding spaces as part of the writing flow (where the space you add is temporarily a "trailing" space) before: **Fix:** Restore the white space behavior of the text editor to be normal, so that inline editing will always be possible after: **Manual Tests:** I hereby swear that: - [X] I opened a hydrogen project and it loaded - [X] I could navigate to various routes in Preview mode Fixes #5784 --- .../text-editor/text-editor.spec.browser2.tsx | 54 +++++++++++++++++-- .../components/text-editor/text-editor.tsx | 3 ++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/editor/src/components/text-editor/text-editor.spec.browser2.tsx b/editor/src/components/text-editor/text-editor.spec.browser2.tsx index 7e21307eebae..31e5199196b8 100644 --- a/editor/src/components/text-editor/text-editor.spec.browser2.tsx +++ b/editor/src/components/text-editor/text-editor.spec.browser2.tsx @@ -221,7 +221,7 @@ describe('Use the text editor', () => { const { before, after } = await testModifierExpectingWayTooManySavesTheFirstTime( cmdModifier, 'b', - projectWithoutTextWithExtraStyle({ font: 'bold 1.2em "Fira Sans"' }), + projectWithCustomTextAndExtraStyle('', { font: 'bold 1.2em "Fira Sans"' }), ) expect(before).toEqual( projectWithStyle({ fontWeight: 'normal' }, { font: 'bold 1.2em "Fira Sans"' }), @@ -240,7 +240,7 @@ describe('Use the text editor', () => { const { before, after } = await testModifierExpectingWayTooManySavesTheFirstTime( cmdModifier, 'i', - projectWithoutTextWithExtraStyle({ font: 'italic 1.2em "Fira Sans"' }), + projectWithCustomTextAndExtraStyle('', { font: 'italic 1.2em "Fira Sans"' }), ) expect(before).toEqual( projectWithStyle({ fontStyle: 'normal' }, { font: 'italic 1.2em "Fira Sans"' }), @@ -672,6 +672,49 @@ describe('Use the text editor', () => { }) }) }) + describe('elements with custom css', () => { + it('allows trailing spaces while editing text-wrap:pretty', async () => { + const editor = await renderTestEditorWithCode( + projectWithCustomTextAndExtraStyle('Initial', { textWrap: 'pretty' }), + 'await-first-dom-report', + ) + + await enterTextEditMode(editor) + typeText('Hello') + typeText(' ') + typeText('Utopia') + await closeTextEditor() + await editor.getDispatchFollowUpActionsFinished() + + expect(editor.getEditorState().editor.mode.type).toEqual('select') + expect(getPrintedUiJsCode(editor.getEditorState())).toEqual( + formatTestProjectCode(` + import * as React from 'react' + import { Storyboard } from 'utopia-api' + + + export var storyboard = ( + +
+ InitialHello Utopia +
+
+ )`), + ) + }) + }) describe('multiline editing', () => { it('renders and escapes newlines', async () => { const editor = await renderTestEditorWithCode(projectWithText, 'await-first-dom-report') @@ -2536,7 +2579,10 @@ export var storyboard = ( ) `) -function projectWithoutTextWithExtraStyle(extraStyleProps: { [prop: string]: string }) { +function projectWithCustomTextAndExtraStyle( + text: string, + extraStyleProps: { [prop: string]: string }, +) { const styleProps = { backgroundColor: '#0091FFAA', position: 'absolute', @@ -2557,7 +2603,7 @@ function projectWithoutTextWithExtraStyle(extraStyleProps: { [prop: string]: str data-testid='div' style={${JSON.stringify(styleProps)}} data-uid='39e' - /> + >${text}
) `) diff --git a/editor/src/components/text-editor/text-editor.tsx b/editor/src/components/text-editor/text-editor.tsx index 172ed2f62d13..43a5bdb1f5f7 100644 --- a/editor/src/components/text-editor/text-editor.tsx +++ b/editor/src/components/text-editor/text-editor.tsx @@ -540,6 +540,9 @@ const TextEditor = React.memo((props: TextEditorProps) => { // text editor outline // Prevent double applying these properties: opacity: 1, + // this is to be able to add trailing spaces (as part of the writing flow) + // to elements where `text-wrap` doesn't allow them + whiteSpace: 'normal', }, onPaste: stopPropagation, onKeyDown: onKeyDown, From 65a732b0b9f20e1c4bb0d250a049046632f9574c Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Thu, 6 Jun 2024 12:35:44 +0100 Subject: [PATCH 030/103] Handle Some Function Wrapped Components (#5808) - Added `functionWrapping` to `UtopiaJSXComponent`, which is an array of `FunctionWrap` elements. - Added utility functions to clear `FunctionWrap` values of unique IDs and source maps. - `looksLikeCanvasElements` has been modified to capture the functions wrapping the components alongside identifying the parameters. - `createExecutionScope` now handles the wrapping of components for execution. - `printUtopiaJSXComponent` now handles printing out the components with their function wrappers. - Reordered the logic in `createExecutionScope` and extracted out the logic for adding a component to the scope. The new function is used for both arbitrary blocks to make components available to their scope and also for their original purpose of adding the components otherwise when created. --- .../__snapshots__/ui-jsx-canvas.spec.tsx.snap | 1326 +++++++++++++++++ .../scene-component.tsx | 1 - .../ui-jsx-canvas-element-renderer-utils.tsx | 2 +- .../ui-jsx-canvas-execution-scope.tsx | 133 +- .../components/canvas/ui-jsx-canvas.spec.tsx | 85 ++ .../editor/actions/actions.spec.tsx | 2 + .../store-deep-equality-instances-2.spec.ts | 3 + .../store/store-deep-equality-instances.ts | 27 +- .../storyboard-utils.spec.ts.snap | 1 + .../model/element-template-utils.spec.tsx | 2 + editor/src/core/model/scene-utils.ts | 1 + editor/src/core/model/storyboard-utils.ts | 1 + .../core/model/test-ui-js-file.test-utils.ts | 3 + .../property-controls-local.ts | 1 + editor/src/core/shared/element-template.ts | 25 +- ...r-printer-arbitrary-elements.spec.tsx.snap | 2 + .../parser-printer-dot-notation.spec.tsx.snap | 1 + .../__snapshots__/parser-printer.spec.ts.snap | 5 + ...parser-printer-arbitrary-elements.spec.tsx | 10 + .../parser-printer-function-wrapped.spec.tsx | 163 ++ ...rser-printer-functional-components.spec.ts | 16 + .../parser-printer-uids.spec.tsx | 1 + .../parser-printer/parser-printer.spec.ts | 55 + .../parser-printer.test-utils.ts | 2 + .../workers/parser-printer/parser-printer.ts | 138 +- editor/src/core/workers/ts/ts-worker.spec.ts | 1 + utopia-shared/src/types/element-template.ts | 19 + 27 files changed, 1951 insertions(+), 75 deletions(-) create mode 100644 editor/src/core/workers/parser-printer/parser-printer-function-wrapped.spec.tsx diff --git a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap index b4707a65ac17..19c16a3d0eea 100644 --- a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap +++ b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap @@ -43525,6 +43525,1332 @@ export var App = (props) => { } `; +exports[`UiJsxCanvas render renders a canvas with a component wrapped in React.memo 1`] = ` +"
+
+
+
+ hi + +
+
+
+
+" +`; + +exports[`UiJsxCanvas render renders a canvas with a component wrapped in React.memo 2`] = ` +Object { + "utopia-storyboard-uid/scene-aaa": Object { + "assignedToProp": null, + "attributeMetadatada": Object {}, + "componentInstance": false, + "computedStyle": Object {}, + "conditionValue": "not-a-conditional", + "earlyReturn": null, + "element": Object { + "type": "RIGHT", + "value": Object { + "children": Array [ + Object { + "children": Array [], + "name": Object { + "baseVariable": "App", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "app-entity", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": Object { + "height": "100%", + "position": "absolute", + "width": "100%", + }, + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "title", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "Hi there!", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + ], + "name": Object { + "baseVariable": "Scene", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": Object { + "height": 200, + "left": 59, + "position": "absolute", + "top": 79, + "width": 200, + }, + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "scene-aaa", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + }, + "elementPath": Object { + "parts": Array [ + Array [ + "utopia-storyboard-uid", + "scene-aaa", + ], + ], + "type": "elementpath", + }, + "globalFrame": null, + "importInfo": Object { + "exportedName": "Scene", + "filePath": "utopia-api", + "type": "IMPORTED_ORIGIN", + "variableName": "Scene", + }, + "isEmotionOrStyledComponent": false, + "label": null, + "localFrame": null, + "nonRoundedGlobalFrame": null, + "specialSizeMeasurements": Object { + "alignItems": null, + "borderRadius": null, + "clientHeight": 0, + "clientWidth": 0, + "closestOffsetParentPath": Object { + "parts": Array [], + "type": "elementpath", + }, + "computedHugProperty": Object { + "height": null, + "width": null, + }, + "coordinateSystemBounds": null, + "display": "initial", + "flexDirection": null, + "float": "none", + "fontSize": null, + "fontStyle": null, + "fontWeight": null, + "gap": null, + "globalContentBoxForChildren": null, + "globalFrameWithTextContent": null, + "hasPositionOffset": false, + "hasTransform": false, + "htmlElementName": "div", + "immediateParentBounds": Object { + "height": 0, + "width": 0, + "x": 0, + "y": 0, + }, + "immediateParentProvidesLayout": true, + "justifyContent": null, + "layoutSystemForChildren": null, + "margin": Object {}, + "naturalHeight": null, + "naturalWidth": null, + "offset": Object { + "x": 0, + "y": 0, + }, + "padding": Object {}, + "parentFlexDirection": null, + "parentFlexGap": 0, + "parentHugsOnMainAxis": false, + "parentJustifyContent": null, + "parentLayoutSystem": "flow", + "parentPadding": Object {}, + "parentTextDirection": "ltr", + "position": "static", + "providesBoundsForAbsoluteChildren": false, + "renderedChildrenCount": 0, + "textBounds": null, + "textDecorationLine": null, + "usesParentBounds": false, + }, + "textContent": null, + }, + "utopia-storyboard-uid/scene-aaa/app-entity": Object { + "assignedToProp": null, + "attributeMetadatada": Object {}, + "componentInstance": false, + "computedStyle": Object {}, + "conditionValue": "not-a-conditional", + "earlyReturn": null, + "element": Object { + "type": "RIGHT", + "value": Object { + "children": Array [], + "name": Object { + "baseVariable": "App", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "app-entity", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": Object { + "height": "100%", + "position": "absolute", + "width": "100%", + }, + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "title", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "Hi there!", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + }, + "elementPath": Object { + "parts": Array [ + Array [ + "utopia-storyboard-uid", + "scene-aaa", + "app-entity", + ], + ], + "type": "elementpath", + }, + "globalFrame": null, + "importInfo": Object { + "filePath": "test.js", + "type": "SAME_FILE_ORIGIN", + "variableName": "App", + }, + "isEmotionOrStyledComponent": false, + "label": null, + "localFrame": null, + "nonRoundedGlobalFrame": null, + "specialSizeMeasurements": Object { + "alignItems": null, + "borderRadius": null, + "clientHeight": 0, + "clientWidth": 0, + "closestOffsetParentPath": Object { + "parts": Array [], + "type": "elementpath", + }, + "computedHugProperty": Object { + "height": null, + "width": null, + }, + "coordinateSystemBounds": null, + "display": "initial", + "flexDirection": null, + "float": "none", + "fontSize": null, + "fontStyle": null, + "fontWeight": null, + "gap": null, + "globalContentBoxForChildren": null, + "globalFrameWithTextContent": null, + "hasPositionOffset": false, + "hasTransform": false, + "htmlElementName": "div", + "immediateParentBounds": Object { + "height": 0, + "width": 0, + "x": 0, + "y": 0, + }, + "immediateParentProvidesLayout": true, + "justifyContent": null, + "layoutSystemForChildren": null, + "margin": Object {}, + "naturalHeight": null, + "naturalWidth": null, + "offset": Object { + "x": 0, + "y": 0, + }, + "padding": Object {}, + "parentFlexDirection": null, + "parentFlexGap": 0, + "parentHugsOnMainAxis": false, + "parentJustifyContent": null, + "parentLayoutSystem": "flow", + "parentPadding": Object {}, + "parentTextDirection": "ltr", + "position": "static", + "providesBoundsForAbsoluteChildren": false, + "renderedChildrenCount": 0, + "textBounds": null, + "textDecorationLine": null, + "usesParentBounds": false, + }, + "textContent": null, + }, + "utopia-storyboard-uid/scene-aaa/app-entity:aaa": Object { + "assignedToProp": null, + "attributeMetadatada": Object {}, + "componentInstance": false, + "computedStyle": Object {}, + "conditionValue": "not-a-conditional", + "earlyReturn": null, + "element": Object { + "type": "RIGHT", + "value": Object { + "children": Array [ + Object { + "children": Array [ + Object { + "text": "hi", + "type": "JSX_TEXT_BLOCK", + "uid": "", + }, + ], + "name": Object { + "baseVariable": "span", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": Object { + "position": "absolute", + }, + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "bbb", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + ], + "name": Object { + "baseVariable": "div", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "content": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "SPREAD_ASSIGNMENT", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "onValue": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "name": "props", + "sourceMap": Object { + "mappings": "CAOyB", + "names": Array [], + "sources": Array [ + "code.tsx", + ], + "sourcesContent": Array [ + " + import * as React from 'react' + import { Storyboard, Scene } from 'utopia-api' + + export var App = React.memo((props) => { + return ( +
+ hi +
+ ) + }) + export var storyboard = (props) => { + return ( + + + + + + ) + } + ", + ], + "version": 3, + }, + "type": "JS_IDENTIFIER", + "uid": "", + }, + "optionallyChained": "not-optionally-chained", + "originalJavascript": "props.style", + "property": "style", + "sourceMap": Object { + "mappings": "CAOyB", + "names": Array [], + "sources": Array [ + "code.tsx", + ], + "sourcesContent": Array [ + " + import * as React from 'react' + import { Storyboard, Scene } from 'utopia-api' + + export var App = React.memo((props) => { + return ( +
+ hi +
+ ) + }) + export var storyboard = (props) => { + return ( + + + + + + ) + } + ", + ], + "version": 3, + }, + "type": "JS_PROPERTY_ACCESS", + "uid": "", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "backgroundColor", + "keyComments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "PROPERTY_ASSIGNMENT", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "#FFFFFF", + }, + }, + ], + "type": "ATTRIBUTE_NESTED_OBJECT", + "uid": "", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "aaa", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + }, + "elementPath": Object { + "parts": Array [ + Array [ + "utopia-storyboard-uid", + "scene-aaa", + "app-entity", + ], + Array [ + "aaa", + ], + ], + "type": "elementpath", + }, + "globalFrame": null, + "importInfo": Object { + "filePath": "test.js", + "type": "SAME_FILE_ORIGIN", + "variableName": "div", + }, + "isEmotionOrStyledComponent": false, + "label": null, + "localFrame": null, + "nonRoundedGlobalFrame": null, + "specialSizeMeasurements": Object { + "alignItems": null, + "borderRadius": null, + "clientHeight": 0, + "clientWidth": 0, + "closestOffsetParentPath": Object { + "parts": Array [], + "type": "elementpath", + }, + "computedHugProperty": Object { + "height": null, + "width": null, + }, + "coordinateSystemBounds": null, + "display": "initial", + "flexDirection": null, + "float": "none", + "fontSize": null, + "fontStyle": null, + "fontWeight": null, + "gap": null, + "globalContentBoxForChildren": null, + "globalFrameWithTextContent": null, + "hasPositionOffset": false, + "hasTransform": false, + "htmlElementName": "div", + "immediateParentBounds": Object { + "height": 0, + "width": 0, + "x": 0, + "y": 0, + }, + "immediateParentProvidesLayout": true, + "justifyContent": null, + "layoutSystemForChildren": null, + "margin": Object {}, + "naturalHeight": null, + "naturalWidth": null, + "offset": Object { + "x": 0, + "y": 0, + }, + "padding": Object {}, + "parentFlexDirection": null, + "parentFlexGap": 0, + "parentHugsOnMainAxis": false, + "parentJustifyContent": null, + "parentLayoutSystem": "flow", + "parentPadding": Object {}, + "parentTextDirection": "ltr", + "position": "static", + "providesBoundsForAbsoluteChildren": false, + "renderedChildrenCount": 0, + "textBounds": null, + "textDecorationLine": null, + "usesParentBounds": false, + }, + "textContent": null, + }, + "utopia-storyboard-uid/scene-aaa/app-entity:aaa/bbb": Object { + "assignedToProp": null, + "attributeMetadatada": Object {}, + "componentInstance": false, + "computedStyle": Object {}, + "conditionValue": "not-a-conditional", + "earlyReturn": null, + "element": Object { + "type": "RIGHT", + "value": Object { + "children": Array [ + Object { + "text": "hi", + "type": "JSX_TEXT_BLOCK", + "uid": "", + }, + ], + "name": Object { + "baseVariable": "span", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": Object { + "position": "absolute", + }, + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "bbb", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + }, + "elementPath": Object { + "parts": Array [ + Array [ + "utopia-storyboard-uid", + "scene-aaa", + "app-entity", + ], + Array [ + "aaa", + "bbb", + ], + ], + "type": "elementpath", + }, + "globalFrame": null, + "importInfo": Object { + "filePath": "test.js", + "type": "SAME_FILE_ORIGIN", + "variableName": "span", + }, + "isEmotionOrStyledComponent": false, + "label": null, + "localFrame": null, + "nonRoundedGlobalFrame": null, + "specialSizeMeasurements": Object { + "alignItems": null, + "borderRadius": null, + "clientHeight": 0, + "clientWidth": 0, + "closestOffsetParentPath": Object { + "parts": Array [], + "type": "elementpath", + }, + "computedHugProperty": Object { + "height": null, + "width": null, + }, + "coordinateSystemBounds": null, + "display": "initial", + "flexDirection": null, + "float": "none", + "fontSize": null, + "fontStyle": null, + "fontWeight": null, + "gap": null, + "globalContentBoxForChildren": null, + "globalFrameWithTextContent": null, + "hasPositionOffset": false, + "hasTransform": false, + "htmlElementName": "div", + "immediateParentBounds": Object { + "height": 0, + "width": 0, + "x": 0, + "y": 0, + }, + "immediateParentProvidesLayout": true, + "justifyContent": null, + "layoutSystemForChildren": null, + "margin": Object {}, + "naturalHeight": null, + "naturalWidth": null, + "offset": Object { + "x": 0, + "y": 0, + }, + "padding": Object {}, + "parentFlexDirection": null, + "parentFlexGap": 0, + "parentHugsOnMainAxis": false, + "parentJustifyContent": null, + "parentLayoutSystem": "flow", + "parentPadding": Object {}, + "parentTextDirection": "ltr", + "position": "static", + "providesBoundsForAbsoluteChildren": false, + "renderedChildrenCount": 0, + "textBounds": null, + "textDecorationLine": null, + "usesParentBounds": false, + }, + "textContent": null, + }, +} +`; + +exports[`UiJsxCanvas render renders a canvas with a component wrapped in a function that wraps the component with more content 1`] = ` +"
+
+
+
+
wrapComponent
+
+
+ hi +
+
+
+
+
+
+" +`; + +exports[`UiJsxCanvas render renders a canvas with a component wrapped in a function that wraps the component with more content 2`] = ` +Object { + "utopia-storyboard-uid/scene-aaa": Object { + "assignedToProp": null, + "attributeMetadatada": Object {}, + "componentInstance": false, + "computedStyle": Object {}, + "conditionValue": "not-a-conditional", + "earlyReturn": null, + "element": Object { + "type": "RIGHT", + "value": Object { + "children": Array [ + Object { + "children": Array [], + "name": Object { + "baseVariable": "App", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "app-entity", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": Object { + "height": "100%", + "position": "absolute", + "width": "100%", + }, + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "title", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "Hi there!", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + ], + "name": Object { + "baseVariable": "Scene", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": Object { + "height": 200, + "left": 59, + "position": "absolute", + "top": 79, + "width": 200, + }, + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "scene-aaa", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + }, + "elementPath": Object { + "parts": Array [ + Array [ + "utopia-storyboard-uid", + "scene-aaa", + ], + ], + "type": "elementpath", + }, + "globalFrame": null, + "importInfo": Object { + "exportedName": "Scene", + "filePath": "utopia-api", + "type": "IMPORTED_ORIGIN", + "variableName": "Scene", + }, + "isEmotionOrStyledComponent": false, + "label": null, + "localFrame": null, + "nonRoundedGlobalFrame": null, + "specialSizeMeasurements": Object { + "alignItems": null, + "borderRadius": null, + "clientHeight": 0, + "clientWidth": 0, + "closestOffsetParentPath": Object { + "parts": Array [], + "type": "elementpath", + }, + "computedHugProperty": Object { + "height": null, + "width": null, + }, + "coordinateSystemBounds": null, + "display": "initial", + "flexDirection": null, + "float": "none", + "fontSize": null, + "fontStyle": null, + "fontWeight": null, + "gap": null, + "globalContentBoxForChildren": null, + "globalFrameWithTextContent": null, + "hasPositionOffset": false, + "hasTransform": false, + "htmlElementName": "div", + "immediateParentBounds": Object { + "height": 0, + "width": 0, + "x": 0, + "y": 0, + }, + "immediateParentProvidesLayout": true, + "justifyContent": null, + "layoutSystemForChildren": null, + "margin": Object {}, + "naturalHeight": null, + "naturalWidth": null, + "offset": Object { + "x": 0, + "y": 0, + }, + "padding": Object {}, + "parentFlexDirection": null, + "parentFlexGap": 0, + "parentHugsOnMainAxis": false, + "parentJustifyContent": null, + "parentLayoutSystem": "flow", + "parentPadding": Object {}, + "parentTextDirection": "ltr", + "position": "static", + "providesBoundsForAbsoluteChildren": false, + "renderedChildrenCount": 0, + "textBounds": null, + "textDecorationLine": null, + "usesParentBounds": false, + }, + "textContent": null, + }, + "utopia-storyboard-uid/scene-aaa/app-entity": Object { + "assignedToProp": null, + "attributeMetadatada": Object {}, + "componentInstance": false, + "computedStyle": Object {}, + "conditionValue": "not-a-conditional", + "earlyReturn": null, + "element": Object { + "type": "RIGHT", + "value": Object { + "children": Array [], + "name": Object { + "baseVariable": "App", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "app-entity", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": Object { + "height": "100%", + "position": "absolute", + "width": "100%", + }, + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "title", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "Hi there!", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + }, + "elementPath": Object { + "parts": Array [ + Array [ + "utopia-storyboard-uid", + "scene-aaa", + "app-entity", + ], + ], + "type": "elementpath", + }, + "globalFrame": null, + "importInfo": Object { + "filePath": "test.js", + "type": "SAME_FILE_ORIGIN", + "variableName": "App", + }, + "isEmotionOrStyledComponent": false, + "label": null, + "localFrame": null, + "nonRoundedGlobalFrame": null, + "specialSizeMeasurements": Object { + "alignItems": null, + "borderRadius": null, + "clientHeight": 0, + "clientWidth": 0, + "closestOffsetParentPath": Object { + "parts": Array [], + "type": "elementpath", + }, + "computedHugProperty": Object { + "height": null, + "width": null, + }, + "coordinateSystemBounds": null, + "display": "initial", + "flexDirection": null, + "float": "none", + "fontSize": null, + "fontStyle": null, + "fontWeight": null, + "gap": null, + "globalContentBoxForChildren": null, + "globalFrameWithTextContent": null, + "hasPositionOffset": false, + "hasTransform": false, + "htmlElementName": "div", + "immediateParentBounds": Object { + "height": 0, + "width": 0, + "x": 0, + "y": 0, + }, + "immediateParentProvidesLayout": true, + "justifyContent": null, + "layoutSystemForChildren": null, + "margin": Object {}, + "naturalHeight": null, + "naturalWidth": null, + "offset": Object { + "x": 0, + "y": 0, + }, + "padding": Object {}, + "parentFlexDirection": null, + "parentFlexGap": 0, + "parentHugsOnMainAxis": false, + "parentJustifyContent": null, + "parentLayoutSystem": "flow", + "parentPadding": Object {}, + "parentTextDirection": "ltr", + "position": "static", + "providesBoundsForAbsoluteChildren": false, + "renderedChildrenCount": 0, + "textBounds": null, + "textDecorationLine": null, + "usesParentBounds": false, + }, + "textContent": null, + }, +} +`; + exports[`UiJsxCanvas render renders a component used in an arbitrary block correctly 1`] = ` "
) => { const colorTheme = useColorTheme() - const canvasIsLive = false const updateInvalidatedPaths = usePubSubAtomReadOnly( DomWalkerInvalidatePathsCtxAtom, AlwaysTrue, diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx index e23621d57f8c..e8e557494e6d 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils.tsx @@ -957,7 +957,7 @@ export function utopiaCanvasJSXLookup( } } -function runJSExpression( +export function runJSExpression( block: JSExpression, elementPath: ElementPath | null, currentScope: MapLike, diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx index f188450fd076..cd40fbbbf6f4 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-execution-scope.tsx @@ -19,7 +19,12 @@ import { updateMutableUtopiaCtxRefWithNewProps, UtopiaProjectCtxAtom, } from './ui-jsx-canvas-contexts' -import { createLookupRender, utopiaCanvasJSXLookup } from './ui-jsx-canvas-element-renderer-utils' +import type { RenderContext } from './ui-jsx-canvas-element-renderer-utils' +import { + createLookupRender, + runJSExpression, + utopiaCanvasJSXLookup, +} from './ui-jsx-canvas-element-renderer-utils' import { runBlockUpdatingScope } from './ui-jsx-canvas-scope-utils' import * as EP from '../../../core/shared/element-path' import type { @@ -70,16 +75,6 @@ export function createExecutionScope( topLevelJsxComponents: Map requireResult: MapLike } { - const filePathMappings = getFilePathMappings(projectContents) - if (!(filePath in topLevelComponentRendererComponents.current)) { - // we make sure that the ref has an entry for this filepath - topLevelComponentRendererComponents.current[filePath] = {} - } - let topLevelComponentRendererComponentsForFile = - topLevelComponentRendererComponents.current[filePath] - - const fileBlobsForFile = defaultIfNull(emptyFileBlobs, fileBlobs[filePath]) - const { topLevelElements, imports, jsxFactoryFunction, combinedTopLevelArbitraryBlock } = getParseSuccessForFilePath(filePath, projectContents) const requireResult: MapLike = importResultFromImports(filePath, imports, customRequire) @@ -105,57 +100,97 @@ export function createExecutionScope( process: process, ...requireResult, } + const filePathMappings = getFilePathMappings(projectContents) + if (!(filePath in topLevelComponentRendererComponents.current)) { + // we make sure that the ref has an entry for this filepath + topLevelComponentRendererComponents.current[filePath] = {} + } + let topLevelComponentRendererComponentsForFile = + topLevelComponentRendererComponents.current[filePath] + + function addComponentToScope(component: UtopiaJSXComponent): void { + const elementName = component.name ?? 'default' + topLevelJsxComponents.set(component.name, component) + if (elementName in topLevelComponentRendererComponentsForFile) { + executionScope[elementName] = topLevelComponentRendererComponentsForFile[elementName] + } else { + const baseComponent = createComponentRendererComponent({ + topLevelElementName: component.name, + mutableContextRef: mutableContextRef, + filePath: filePath, + }) + const wrappedComponent = component.functionWrapping.reduceRight((workingComponent, wrap) => { + switch (wrap.type) { + case 'SIMPLE_FUNCTION_WRAP': + const functionExpression = runJSExpression( + wrap.functionExpression, + null, + executionScope, + renderContext, + wrap.functionExpression.uid, + null, + null, + ) + return functionExpression(workingComponent) + } + }, baseComponent) + topLevelComponentRendererComponentsForFile[elementName] = wrappedComponent + executionScope[elementName] = wrappedComponent + } + } + + const fileBlobsForFile = defaultIfNull(emptyFileBlobs, fileBlobs[filePath]) + // TODO All of this is run on every interaction o_O let topLevelJsxComponents: Map = new Map() - // Make sure there is something in scope for all of the top level components - fastForEach(topLevelElements, (topLevelElement) => { - if (isUtopiaJSXComponent(topLevelElement)) { - topLevelJsxComponents.set(topLevelElement.name, topLevelElement) - const elementName = topLevelElement.name ?? 'default' - if (!(elementName in topLevelComponentRendererComponentsForFile)) { - topLevelComponentRendererComponentsForFile[elementName] = createComponentRendererComponent({ - topLevelElementName: topLevelElement.name, - mutableContextRef: mutableContextRef, - filePath: filePath, - }) - } - } - }) - - executionScope = { - ...executionScope, - ...topLevelComponentRendererComponentsForFile, + const renderContext: RenderContext = { + rootScope: executionScope, + parentComponentInputProps: {}, + requireResult: requireResult, + hiddenInstances: hiddenInstances, + displayNoneInstances: displayNoneInstances, + fileBlobs: fileBlobsForFile, + validPaths: new Set(), + reactChildren: undefined, + metadataContext: metadataContext, + updateInvalidatedPaths: updateInvalidatedPaths, + jsxFactoryFunctionName: jsxFactoryFunction, + shouldIncludeCanvasRootInTheSpy: shouldIncludeCanvasRootInTheSpy, + filePath: filePath, + imports: imports, + code: '', + highlightBounds: {}, + editedText: editedText, + variablesInScope: {}, + filePathMappings: filePathMappings, } let spiedVariablesInRoot: VariableData = {} // First make sure everything is in scope if (combinedTopLevelArbitraryBlock != null && openStoryboardFileNameKILLME != null) { + for (const definedElsewhereValue of combinedTopLevelArbitraryBlock.definedElsewhere) { + const componentFromThisFile = topLevelElements.find( + (topLevelElement): topLevelElement is UtopiaJSXComponent => { + return ( + isUtopiaJSXComponent(topLevelElement) && topLevelElement.name === definedElsewhereValue + ) + }, + ) + if (componentFromThisFile != null) { + addComponentToScope(componentFromThisFile) + } + } const { highlightBounds, code } = getCodeAndHighlightBoundsForFile(filePath, projectContents) const propertiesFromParams = propertiesExposedByParams(combinedTopLevelArbitraryBlock.params) const lookupRenderer = createLookupRender( EP.emptyElementPath, { - rootScope: executionScope, - parentComponentInputProps: {}, - requireResult: requireResult, - hiddenInstances: hiddenInstances, - displayNoneInstances: displayNoneInstances, - fileBlobs: fileBlobsForFile, - validPaths: new Set(), - reactChildren: undefined, - metadataContext: metadataContext, - updateInvalidatedPaths: updateInvalidatedPaths, - jsxFactoryFunctionName: jsxFactoryFunction, - shouldIncludeCanvasRootInTheSpy: shouldIncludeCanvasRootInTheSpy, - filePath: openStoryboardFileNameKILLME, - imports: imports, + ...renderContext, code: code, highlightBounds: highlightBounds, - editedText: editedText, - variablesInScope: {}, filePathMappings: filePathMappings, }, null, @@ -179,6 +214,14 @@ export function createExecutionScope( ) spiedVariablesInRoot = spiedVariablesDeclaredWithinBlock } + + // Make sure there is something in scope for all of the top level components + fastForEach(topLevelElements, (topLevelElement) => { + if (isUtopiaJSXComponent(topLevelElement)) { + addComponentToScope(topLevelElement) + } + }) + // WARNING: mutating the mutableContextRef updateMutableUtopiaCtxRefWithNewProps(mutableContextRef, { ...mutableContextRef.current, diff --git a/editor/src/components/canvas/ui-jsx-canvas.spec.tsx b/editor/src/components/canvas/ui-jsx-canvas.spec.tsx index 2c9c1c937373..aac365459d04 100644 --- a/editor/src/components/canvas/ui-jsx-canvas.spec.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas.spec.tsx @@ -156,6 +156,91 @@ export { ToBeDefaultExported as default }`, ) }) + it('renders a canvas with a component wrapped in React.memo', () => { + testCanvasRender( + null, + ` + import * as React from 'react' + import { Storyboard, Scene } from 'utopia-api' + + export var App = React.memo((props) => { + return ( +
+ hi +
+ ) + }) + export var ${BakedInStoryboardVariableName} = (props) => { + return ( + + + + + + ) + } + `, + ) + }) + + it('renders a canvas with a component wrapped in a function that wraps the component with more content', () => { + testCanvasRender( + null, + ` + import * as React from 'react' + import { Storyboard, Scene } from 'utopia-api' + + function wrapComponent(Component) { + return () => { + return
+
+ wrapComponent +
+
+
+ } + } + + export var App = wrapComponent(() => { + return ( +
+ hi +
+ ) + }) + export var ${BakedInStoryboardVariableName} = (props) => { + return ( + + + + + + ) + } + `, + ) + }) + it('renders a canvas defined by a utopia storyboard component', () => { testCanvasRender( null, diff --git a/editor/src/components/editor/actions/actions.spec.tsx b/editor/src/components/editor/actions/actions.spec.tsx index 5bb199009b99..23e68963d126 100644 --- a/editor/src/components/editor/actions/actions.spec.tsx +++ b/editor/src/components/editor/actions/actions.spec.tsx @@ -154,6 +154,7 @@ function storyboardComponent(numberOfScenes: number): UtopiaJSXComponent { false, 'var', 'block', + [], null, [], jsxElement( @@ -186,6 +187,7 @@ const originalModel = deepFreeze( true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( diff --git a/editor/src/components/editor/store/store-deep-equality-instances-2.spec.ts b/editor/src/components/editor/store/store-deep-equality-instances-2.spec.ts index dab15fd7e549..428d06f16905 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances-2.spec.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances-2.spec.ts @@ -788,6 +788,7 @@ describe('UtopiaJSXComponentKeepDeepEquality', () => { isFunction: true, declarationSyntax: 'const', blockOrExpression: 'block', + functionWrapping: [], param: { type: 'PARAM', dotDotDotToken: false, @@ -837,6 +838,7 @@ describe('UtopiaJSXComponentKeepDeepEquality', () => { isFunction: true, declarationSyntax: 'const', blockOrExpression: 'block', + functionWrapping: [], param: { type: 'PARAM', dotDotDotToken: false, @@ -886,6 +888,7 @@ describe('UtopiaJSXComponentKeepDeepEquality', () => { isFunction: true, declarationSyntax: 'const', blockOrExpression: 'block', + functionWrapping: [], param: { type: 'PARAM', dotDotDotToken: false, 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 90c52ff49778..c2a87be51c3f 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances.ts @@ -604,6 +604,8 @@ import type { OnlineState } from '../online-status' import { onlineState } from '../online-status' import type { NavigatorRow } from '../../navigator/navigator-row' import { condensedNavigatorRow, regularNavigatorRow } from '../../navigator/navigator-row' +import type { SimpleFunctionWrap, FunctionWrap } from 'utopia-shared/src/types' +import { simpleFunctionWrap, isSimpleFunctionWrap } from 'utopia-shared/src/types' export function ElementPropertyPathKeepDeepEquality(): KeepDeepEqualityCall { return combine2EqualityCalls( @@ -1570,8 +1572,29 @@ export function JSXElementChildKeepDeepEquality(): KeepDeepEqualityCall = + combine1EqualityCall( + (wrap) => wrap.functionExpression, + JSExpressionKeepDeepEqualityCall, + simpleFunctionWrap, + ) + +export const FunctionWrapKeepDeepEquality: KeepDeepEqualityCall = ( + oldValue, + newValue, +) => { + switch (oldValue.type) { + case 'SIMPLE_FUNCTION_WRAP': + if (isSimpleFunctionWrap(newValue)) { + return SimpleFunctionWrapKeepDeepEquality(oldValue, newValue) + } + break + } + return keepDeepEqualityResult(newValue, false) +} + export const UtopiaJSXComponentKeepDeepEquality: KeepDeepEqualityCall = - combine10EqualityCalls( + combine11EqualityCalls( (component) => component.name, createCallWithTripleEquals(), (component) => component.isFunction, @@ -1580,6 +1603,8 @@ export const UtopiaJSXComponentKeepDeepEquality: KeepDeepEqualityCall component.blockOrExpression, createCallWithTripleEquals(), + (component) => component.functionWrapping, + arrayDeepEquality(FunctionWrapKeepDeepEquality), (component) => component.param, nullableDeepEquality(ParamKeepDeepEquality()), (component) => component.propsUsed, diff --git a/editor/src/core/model/__snapshots__/storyboard-utils.spec.ts.snap b/editor/src/core/model/__snapshots__/storyboard-utils.spec.ts.snap index 9d067e4dce25..e1545668b90d 100644 --- a/editor/src/core/model/__snapshots__/storyboard-utils.spec.ts.snap +++ b/editor/src/core/model/__snapshots__/storyboard-utils.spec.ts.snap @@ -12,6 +12,7 @@ Array [ "arbitraryJSBlock": null, "blockOrExpression": "block", "declarationSyntax": "var", + "functionWrapping": Array [], "isFunction": false, "name": "storyboard", "param": null, diff --git a/editor/src/core/model/element-template-utils.spec.tsx b/editor/src/core/model/element-template-utils.spec.tsx index a7e46db78aa7..b37102c9fdeb 100644 --- a/editor/src/core/model/element-template-utils.spec.tsx +++ b/editor/src/core/model/element-template-utils.spec.tsx @@ -192,6 +192,7 @@ describe('removeJSXElementChild', () => { true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -212,6 +213,7 @@ describe('removeJSXElementChild', () => { true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( diff --git a/editor/src/core/model/scene-utils.ts b/editor/src/core/model/scene-utils.ts index b10dacf9193a..fbbe93583339 100644 --- a/editor/src/core/model/scene-utils.ts +++ b/editor/src/core/model/scene-utils.ts @@ -116,6 +116,7 @@ export function convertScenesToUtopiaCanvasComponent( false, 'var', 'block', + [], null, [], jsxElement( diff --git a/editor/src/core/model/storyboard-utils.ts b/editor/src/core/model/storyboard-utils.ts index 46211943d6d7..c8bf0942475e 100644 --- a/editor/src/core/model/storyboard-utils.ts +++ b/editor/src/core/model/storyboard-utils.ts @@ -384,6 +384,7 @@ function addStoryboardFileForComponent( false, 'var', 'block', + [], null, [], storyboardElement, diff --git a/editor/src/core/model/test-ui-js-file.test-utils.ts b/editor/src/core/model/test-ui-js-file.test-utils.ts index 6829a626dc91..9bdb51c0b620 100644 --- a/editor/src/core/model/test-ui-js-file.test-utils.ts +++ b/editor/src/core/model/test-ui-js-file.test-utils.ts @@ -61,6 +61,7 @@ const mainComponentForTests = utopiaJSXComponent( true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -332,6 +333,7 @@ const scene = utopiaJSXComponent( true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -398,6 +400,7 @@ const TestStoryboard = utopiaJSXComponent( false, 'var', 'block', + [], null, [], jsxElement( diff --git a/editor/src/core/property-controls/property-controls-local.ts b/editor/src/core/property-controls/property-controls-local.ts index f688a5f9378b..340f7cf073b3 100644 --- a/editor/src/core/property-controls/property-controls-local.ts +++ b/editor/src/core/property-controls/property-controls-local.ts @@ -117,6 +117,7 @@ import type { ScriptLine } from '../../third-party/react-error-overlay/utils/sta import { intrinsicHTMLElementNamesAsStrings } from '../shared/dom-utils' import { valueOrArrayToArray } from '../shared/array-utils' import { optionalMap } from '../shared/optional-utils' +import type { RenderContext } from 'src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-element-renderer-utils' const exportedNameSymbol = Symbol('__utopia__exportedName') const moduleNameSymbol = Symbol('__utopia__moduleName') diff --git a/editor/src/core/shared/element-template.ts b/editor/src/core/shared/element-template.ts index af6d66b0fc11..c52695b3d1bd 100644 --- a/editor/src/core/shared/element-template.ts +++ b/editor/src/core/shared/element-template.ts @@ -111,6 +111,7 @@ import type { HugProperty, HugPropertyWidthHeight, ElementsByUID, + FunctionWrap, } from 'utopia-shared/src/types/element-template' import type { VariableData } from '../../components/canvas/ui-jsx-canvas' @@ -198,6 +199,7 @@ import { emptyComments, emptyComputedStyle, emptyAttributeMetadata, + simpleFunctionWrap, } from 'utopia-shared/src/types/element-template' export { emptyComments, emptyComputedStyle, emptyAttributeMetadata } @@ -1981,6 +1983,7 @@ export function utopiaJSXComponent( isFunction: boolean, declarationSyntax: FunctionDeclarationSyntax, blockOrExpression: BlockOrExpression, + functionWrapping: Array, param: Param | null, propsUsed: Array, rootElement: JSXElementChild, @@ -1994,6 +1997,7 @@ export function utopiaJSXComponent( isFunction: isFunction, declarationSyntax: declarationSyntax, blockOrExpression: blockOrExpression, + functionWrapping: functionWrapping, param: param, propsUsed: propsUsed, rootElement: rootElement, @@ -2179,8 +2183,6 @@ export function propertiesExposedByParam(param: Param): Array { } } -// FIXME we need to inject data-uids using insertDataUIDsIntoCode - export function clearArbitraryJSBlockUniqueIDs(block: ArbitraryJSBlock): ArbitraryJSBlock { return { ...block, @@ -2302,6 +2304,24 @@ export function clearParamUniqueIDs(param: Param): Param { return functionParam(param.dotDotDotToken, clearBoundParamUniqueIDs(param.boundParam)) } +export function clearFunctionWrapUniqueIDs(wrap: FunctionWrap): FunctionWrap { + switch (wrap.type) { + case 'SIMPLE_FUNCTION_WRAP': + return simpleFunctionWrap(clearExpressionUniqueIDs(wrap.functionExpression)) + } +} + +export function clearFunctionWrapSourceMaps(wrap: FunctionWrap): FunctionWrap { + switch (wrap.type) { + case 'SIMPLE_FUNCTION_WRAP': + return simpleFunctionWrap(clearExpressionSourceMaps(wrap.functionExpression)) + } +} + +export function clearFunctionWrapUniqueIDsAndSourceMaps(wrap: FunctionWrap): FunctionWrap { + return clearFunctionWrapSourceMaps(clearFunctionWrapUniqueIDs(wrap)) +} + // FIXME: Should only really be in test code. export function clearTopLevelElementUniqueIDs(element: UtopiaJSXComponent): UtopiaJSXComponent export function clearTopLevelElementUniqueIDs(element: ArbitraryJSBlock): ArbitraryJSBlock @@ -2312,6 +2332,7 @@ export function clearTopLevelElementUniqueIDs(element: TopLevelElement): TopLeve let updatedComponent: UtopiaJSXComponent = { ...element, rootElement: clearJSXElementChildUniqueIDs(element.rootElement), + functionWrapping: element.functionWrapping.map(clearFunctionWrapUniqueIDsAndSourceMaps), } if (updatedComponent.arbitraryJSBlock != null) { updatedComponent.arbitraryJSBlock = clearArbitraryJSBlockUniqueIDs( diff --git a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-arbitrary-elements.spec.tsx.snap b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-arbitrary-elements.spec.tsx.snap index 07cd2a31dd54..6c9a32b345b4 100644 --- a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-arbitrary-elements.spec.tsx.snap +++ b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-arbitrary-elements.spec.tsx.snap @@ -603,6 +603,7 @@ export var storyboard = ( "arbitraryJSBlock": null, "blockOrExpression": "block", "declarationSyntax": "var", + "functionWrapping": Array [], "isFunction": true, "name": "App", "param": Object { @@ -987,6 +988,7 @@ export var storyboard = ( "arbitraryJSBlock": null, "blockOrExpression": "parenthesized-expression", "declarationSyntax": "var", + "functionWrapping": Array [], "isFunction": false, "name": "storyboard", "param": null, diff --git a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-dot-notation.spec.tsx.snap b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-dot-notation.spec.tsx.snap index f89abc4ca6a5..02d5c59eea75 100644 --- a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-dot-notation.spec.tsx.snap +++ b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-dot-notation.spec.tsx.snap @@ -48,6 +48,7 @@ Array [ "arbitraryJSBlock": null, "blockOrExpression": "block", "declarationSyntax": "var", + "functionWrapping": Array [], "isFunction": true, "name": "App", "param": Object { diff --git a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer.spec.ts.snap b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer.spec.ts.snap index eeae8f05557a..24d0718487bd 100644 --- a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer.spec.ts.snap +++ b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer.spec.ts.snap @@ -566,6 +566,7 @@ export var whatever = (props) => { "arbitraryJSBlock": null, "blockOrExpression": "block", "declarationSyntax": "var", + "functionWrapping": Array [], "isFunction": true, "name": "whatever", "param": Object { @@ -952,6 +953,7 @@ Object { "arbitraryJSBlock": null, "blockOrExpression": "expression", "declarationSyntax": "const", + "functionWrapping": Array [], "isFunction": true, "name": "a", "param": Object { @@ -1108,6 +1110,7 @@ const b = (n) => n > 0 ?
n
: a(10) "arbitraryJSBlock": null, "blockOrExpression": "expression", "declarationSyntax": "var", + "functionWrapping": Array [], "isFunction": true, "name": "whatever", "param": Object { @@ -1166,6 +1169,7 @@ const b = (n) => n > 0 ?
n
: a(10) "arbitraryJSBlock": null, "blockOrExpression": "expression", "declarationSyntax": "const", + "functionWrapping": Array [], "isFunction": true, "name": "b", "param": Object { @@ -1656,6 +1660,7 @@ export var App = (props) => "arbitraryJSBlock": null, "blockOrExpression": "expression", "declarationSyntax": "var", + "functionWrapping": Array [], "isFunction": true, "name": "App", "param": Object { diff --git a/editor/src/core/workers/parser-printer/parser-printer-arbitrary-elements.spec.tsx b/editor/src/core/workers/parser-printer/parser-printer-arbitrary-elements.spec.tsx index 46df412fa758..6392ee2f2409 100644 --- a/editor/src/core/workers/parser-printer/parser-printer-arbitrary-elements.spec.tsx +++ b/editor/src/core/workers/parser-printer/parser-printer-arbitrary-elements.spec.tsx @@ -320,6 +320,7 @@ export var whatever = props => ( true, 'var', 'expression', + [], defaultPropsParam, [], jsxElement( @@ -367,6 +368,7 @@ export var whatever = props => ( true, 'var', 'parenthesized-expression', + [], defaultPropsParam, [], view, @@ -507,6 +509,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -670,6 +673,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -817,6 +821,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -901,6 +906,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -1013,6 +1019,7 @@ return { arr: arr };` true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -1097,6 +1104,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -1207,6 +1215,7 @@ return { arr: arr };` true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -1466,6 +1475,7 @@ export var storyboard = ( true, 'var', 'block', + [], defaultPropsParam, [], rootElement, diff --git a/editor/src/core/workers/parser-printer/parser-printer-function-wrapped.spec.tsx b/editor/src/core/workers/parser-printer/parser-printer-function-wrapped.spec.tsx new file mode 100644 index 000000000000..52ce6f129b36 --- /dev/null +++ b/editor/src/core/workers/parser-printer/parser-printer-function-wrapped.spec.tsx @@ -0,0 +1,163 @@ +import { + isArbitraryJSBlock, + type ArbitraryJSBlock, + type UtopiaJSXComponent, + isUtopiaJSXComponent, +} from '../../shared/element-template' +import { isParseSuccess } from '../../shared/project-file-types' +import { printCode, printCodeOptions } from './parser-printer' +import { + clearParseResultSourceMapsUniqueIDsAndEmptyBlocks, + clearParseResultUniqueIDsAndEmptyBlocks, + testParseCode, +} from './parser-printer.test-utils' + +function getLoneMainTopLevelElement(code: string): UtopiaJSXComponent | ArbitraryJSBlock { + const parseResult = clearParseResultSourceMapsUniqueIDsAndEmptyBlocks(testParseCode(code)) + if (isParseSuccess(parseResult)) { + const topLevelElements = parseResult.topLevelElements + const mainTopLevelElements = topLevelElements.filter( + (element): element is UtopiaJSXComponent | ArbitraryJSBlock => + isUtopiaJSXComponent(element) || isArbitraryJSBlock(element), + ) + switch (mainTopLevelElements.length) { + case 0: + throw new Error(`No main top level elements found.`) + case 1: + return mainTopLevelElements[0] + default: + throw new Error(`More than one main top level element found: ${topLevelElements}`) + } + } else { + throw new Error(`Not a successful parse: ${parseResult}`) + } +} + +function testParsePrintParse(code: string): string { + const firstParse = clearParseResultUniqueIDsAndEmptyBlocks(testParseCode(code)) + + if (!isParseSuccess(firstParse)) { + throw new Error(JSON.stringify(firstParse)) + } + + const firstAsParseSuccess = firstParse + + const printed = printCode( + '/index.js', + printCodeOptions(false, true, true), + firstAsParseSuccess.imports, + firstAsParseSuccess.topLevelElements, + firstAsParseSuccess.jsxFactoryFunction, + firstAsParseSuccess.exportsDetail, + ) + + const secondParse = clearParseResultUniqueIDsAndEmptyBlocks(testParseCode(printed)) + + if (!isParseSuccess(secondParse)) { + throw new Error(JSON.stringify(secondParse)) + } + + const secondAsParseSuccess = firstParse + expect(secondAsParseSuccess.topLevelElements).toEqual(firstAsParseSuccess.topLevelElements) + + return printed +} + +const simpleReactMemoComponentCode = `import React from "react"; +export const Wrapped = React.memo(() => { + return
+})` + +describe('parseCode', () => { + it('simple function component wrapped in a React.memo', () => { + const element = getLoneMainTopLevelElement(simpleReactMemoComponentCode) + expect(element.type).toEqual('UTOPIA_JSX_COMPONENT') + expect(element).toMatchInlineSnapshot(` + Object { + "arbitraryJSBlock": null, + "blockOrExpression": "block", + "declarationSyntax": "const", + "functionWrapping": Array [ + Object { + "functionExpression": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "onValue": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "name": "React", + "sourceMap": null, + "type": "JS_IDENTIFIER", + "uid": "", + }, + "optionallyChained": "not-optionally-chained", + "originalJavascript": "React.memo", + "property": "memo", + "sourceMap": null, + "type": "JS_PROPERTY_ACCESS", + "uid": "", + }, + "type": "SIMPLE_FUNCTION_WRAP", + }, + ], + "isFunction": true, + "name": "Wrapped", + "param": null, + "propsUsed": Array [], + "returnStatementComments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "rootElement": Object { + "children": Array [], + "name": Object { + "baseVariable": "div", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "wrapped", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + "type": "UTOPIA_JSX_COMPONENT", + "usedInReactDOMRender": false, + } + `) + }) +}) + +describe('printCode', () => { + it('simple function component wrapped in a React.memo', () => { + const actualResult = testParsePrintParse(simpleReactMemoComponentCode) + expect(actualResult).toMatchInlineSnapshot(` + "import React from 'react' + export const Wrapped = React.memo(() => { + return
+ }) + " + `) + }) +}) diff --git a/editor/src/core/workers/parser-printer/parser-printer-functional-components.spec.ts b/editor/src/core/workers/parser-printer/parser-printer-functional-components.spec.ts index 7d09434dd43d..cfc9a8836b59 100644 --- a/editor/src/core/workers/parser-printer/parser-printer-functional-components.spec.ts +++ b/editor/src/core/workers/parser-printer/parser-printer-functional-components.spec.ts @@ -196,6 +196,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -251,6 +252,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, [], view, @@ -289,6 +291,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, [], view, @@ -331,6 +334,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, ['prop'], view, @@ -388,6 +392,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, ['prop'], view, @@ -431,6 +436,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, ['prop'], view, @@ -488,6 +494,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, ['prop'], view, @@ -532,6 +539,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, ['prop'], view, @@ -571,6 +579,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, [], view, @@ -625,6 +634,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, [], view, @@ -668,6 +678,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], propsParam, [], view, @@ -724,6 +735,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], outerDestructuredObject, ['arrayPart'], view, @@ -812,6 +824,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], outerDestructuredObject, ['arrayPart'], view, @@ -851,6 +864,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -894,6 +908,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -950,6 +965,7 @@ describe('Parsing a function component with props', () => { true, 'var', 'block', + [], defaultPropsParam, ['showA'], expect.objectContaining({ diff --git a/editor/src/core/workers/parser-printer/parser-printer-uids.spec.tsx b/editor/src/core/workers/parser-printer/parser-printer-uids.spec.tsx index 926750fd95f3..e1835f8b11b9 100644 --- a/editor/src/core/workers/parser-printer/parser-printer-uids.spec.tsx +++ b/editor/src/core/workers/parser-printer/parser-printer-uids.spec.tsx @@ -410,6 +410,7 @@ export var app = (props) => { tle.isFunction, tle.declarationSyntax, tle.blockOrExpression, + tle.functionWrapping, tle.param, tle.propsUsed, updatedRootElement, diff --git a/editor/src/core/workers/parser-printer/parser-printer.spec.ts b/editor/src/core/workers/parser-printer/parser-printer.spec.ts index a590ad8db935..97b5d7a120b7 100644 --- a/editor/src/core/workers/parser-printer/parser-printer.spec.ts +++ b/editor/src/core/workers/parser-printer/parser-printer.spec.ts @@ -165,6 +165,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -230,6 +231,7 @@ export var whatever = () => true, 'var', 'expression', + [], null, [], view, @@ -323,6 +325,7 @@ export function whatever(props) { true, 'function', 'block', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -392,6 +395,7 @@ export function whatever() { true, 'function', 'block', + [], null, [], view, @@ -485,6 +489,7 @@ export default function whatever(props) { true, 'function', 'block', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -554,6 +559,7 @@ export default function whatever() { true, 'function', 'block', + [], null, [], view, @@ -644,6 +650,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -774,6 +781,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -863,6 +871,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -987,6 +996,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake', 'rightOfTheCake'], view, @@ -1085,6 +1095,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -1183,6 +1194,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, [], view, @@ -1373,6 +1385,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -1524,6 +1537,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -1684,6 +1698,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['leftOfTheCake'], view, @@ -1774,6 +1789,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, [], view, @@ -1951,6 +1967,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -2058,6 +2075,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -2148,6 +2166,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -2243,6 +2262,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -2340,6 +2360,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -2461,6 +2482,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -2637,6 +2659,7 @@ export var whatever = (props) => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -2708,6 +2731,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, [], view, @@ -2815,6 +2839,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, [], view, @@ -2898,6 +2923,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, [], view, @@ -3029,6 +3055,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['left'], view, @@ -3208,6 +3235,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, [], view, @@ -3349,6 +3377,7 @@ export var whatever = props => ( true, 'var', 'block', + [], defaultPropsParam, ['layout'], rootDiv, @@ -3373,6 +3402,7 @@ export var whatever = props => ( true, 'var', 'parenthesized-expression', + [], defaultPropsParam, [], view, @@ -3514,6 +3544,7 @@ export var whatever = (props) => true, 'var', 'expression', + [], defaultPropsParam, ['color'], view, @@ -3584,6 +3615,7 @@ export var whatever = () => true, 'var', 'expression', + [], null, [], view, @@ -3646,6 +3678,7 @@ export var App = (props) => true, 'var', 'expression', + [], defaultPropsParam, [], view, @@ -3714,6 +3747,7 @@ export var App = (props) => true, 'var', 'parenthesized-expression', + [], null, [], view, @@ -3786,6 +3820,7 @@ export var App = (props) => true, 'var', 'parenthesized-expression', + [], defaultPropsParam, [], view, @@ -3967,6 +4002,7 @@ var spacing = 20` true, 'var', 'parenthesized-expression', + [], null, [], view, @@ -4105,6 +4141,7 @@ export var whatever = props => { true, 'var', 'parenthesized-expression', + [], defaultPropsParam, [], view, @@ -4172,6 +4209,7 @@ export var whatever = props => { true, 'var', 'parenthesized-expression', + [], defaultPropsParam, [], view, @@ -4272,6 +4310,7 @@ export var whatever = props => { true, 'var', 'parenthesized-expression', + [], defaultPropsParam, ['color', 'shadowValue', 'there'], view, @@ -4417,6 +4456,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -4494,6 +4534,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -4556,6 +4597,7 @@ export var whatever = props => { false, 'var', 'parenthesized-expression', + [], null, [], jsxElement( @@ -4622,6 +4664,7 @@ export var App = props => { true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -4709,6 +4752,7 @@ export var App = props => { true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -4763,6 +4807,7 @@ export var App = props => { true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -4837,6 +4882,7 @@ export var App = props => { true, 'var', 'parenthesized-expression', + [], defaultPropsParam, [], jsxElement( @@ -5054,6 +5100,7 @@ export var App = props => { true, 'var', 'block', + [], defaultPropsParam, ['layout'], jsxElement( @@ -5252,6 +5299,7 @@ export var App = props => { true, 'var', 'block', + [], defaultPropsParam, [], jsxElement( @@ -5311,6 +5359,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -5361,6 +5410,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -5469,6 +5519,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -5585,6 +5636,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -5713,6 +5765,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -5879,6 +5932,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], view, @@ -5916,6 +5970,7 @@ export var whatever = props => { true, 'var', 'block', + [], defaultPropsParam, [], view, diff --git a/editor/src/core/workers/parser-printer/parser-printer.test-utils.ts b/editor/src/core/workers/parser-printer/parser-printer.test-utils.ts index cfd9fa9fb1a1..52ef75e7c185 100644 --- a/editor/src/core/workers/parser-printer/parser-printer.test-utils.ts +++ b/editor/src/core/workers/parser-printer/parser-printer.test-utils.ts @@ -873,6 +873,7 @@ export function utopiaJSXComponentArbitrary(): Arbitrary { isFunction, declarationSyntax, blockOrExpression, + [], defaultPropsParam, [], rootElement, @@ -1477,6 +1478,7 @@ export function clearTopLevelElementSourceMapsUniqueIDsAndEmptyBlocks( return clearArbitraryJSBlockSourceMaps({ ...withoutUID, javascript: blockCode, + sourceMap: null, }) } case 'IMPORT_STATEMENT': diff --git a/editor/src/core/workers/parser-printer/parser-printer.ts b/editor/src/core/workers/parser-printer/parser-printer.ts index 2655271ed5b5..011e1a4613c6 100644 --- a/editor/src/core/workers/parser-printer/parser-printer.ts +++ b/editor/src/core/workers/parser-printer/parser-printer.ts @@ -109,6 +109,7 @@ import { markedAsExported, markedAsDefault, parseParams, + parseAttributeExpression, } from './parser-printer-parsing' import { jsonToExpression } from './json-to-expression' import { difference } from '../../shared/set-utils' @@ -122,6 +123,8 @@ import type { Optic } from '../../../core/shared/optics/optics' import { modify } from '../../../core/shared/optics/optic-utilities' import { identifyValuesDefinedInNode } from './parser-printer-expressions' import { isParseableFile } from '../../shared/file-utils' +import type { FunctionWrap } from 'utopia-shared/src/types/element-template' +import { simpleFunctionWrap } from 'utopia-shared/src/types/element-template' const BakedInStoryboardVariableName = 'storyboard' @@ -722,6 +725,25 @@ function getModifersForComponent( return result } +function printFunctionWrapping( + printOptions: PrintCodeOptions, + imports: Imports, + statement: TS.Expression, + functionWrapping: Array, +): TS.Expression { + return functionWrapping.reduceRight((workingStatement, wrap) => { + switch (wrap.type) { + case 'SIMPLE_FUNCTION_WRAP': + const functionExpression = jsxAttributeToExpression( + wrap.functionExpression, + imports, + printOptions.stripUIDs, + ) + return TS.createCall(functionExpression, undefined, [workingStatement]) + } + }, statement) +} + function printUtopiaJSXComponent( printOptions: PrintCodeOptions, imports: Imports, @@ -800,10 +822,21 @@ function printUtopiaJSXComponent( undefined, bodyForArrowFunction(), ) + const wrappedArrowFunction = printFunctionWrapping( + printOptions, + imports, + arrowFunction, + element.functionWrapping, + ) if (element.name == null) { - elementNode = TS.createExportAssignment(undefined, modifiers, undefined, arrowFunction) + elementNode = TS.createExportAssignment( + undefined, + modifiers, + undefined, + wrappedArrowFunction, + ) } else { - const varDec = TS.createVariableDeclaration(element.name, undefined, arrowFunction) + const varDec = TS.createVariableDeclaration(element.name, undefined, wrappedArrowFunction) const varDecList = TS.createVariableDeclarationList([varDec], nodeFlags) elementNode = TS.createVariableStatement(modifiers, varDecList) } @@ -901,10 +934,6 @@ function optionallyCreateDotDotDotToken(createIt: boolean): TS.DotDotDotToken | return createIt ? TS.createToken(TS.SyntaxKind.DotDotDotToken) : undefined } -function printRawComment(comment: Comment): string { - return `${comment.rawText}${comment.trailingNewLine ? '\n' : ''}` -} - function printArbitraryJSBlock(block: ArbitraryJSBlock): TS.Node { return TS.createUnparsedSourceFile(block.javascript) } @@ -1092,18 +1121,21 @@ interface PossibleCanvasContentsExpression { name: string initializer: TS.Expression declarationSyntax: FunctionDeclarationSyntax + functionWrapping: Array } function possibleCanvasContentsExpression( name: string, initializer: TS.Expression, declarationSyntax: FunctionDeclarationSyntax, + functionWrapping: Array, ): PossibleCanvasContentsExpression { return { type: 'POSSIBLE_CANVAS_CONTENTS_EXPRESSION', name: name, initializer: initializer, declarationSyntax: declarationSyntax, + functionWrapping: functionWrapping, } } @@ -1113,6 +1145,7 @@ interface PossibleCanvasContentsFunction { parameters: TS.NodeArray body: TS.ConciseBody declarationSyntax: FunctionDeclarationSyntax + functionWrapping: Array } function possibleCanvasContentsFunction( @@ -1120,6 +1153,7 @@ function possibleCanvasContentsFunction( parameters: TS.NodeArray, body: TS.ConciseBody, declarationSyntax: FunctionDeclarationSyntax, + functionWrapping: Array, ): PossibleCanvasContentsFunction { return { type: 'POSSIBLE_CANVAS_CONTENTS_FUNCTION', @@ -1127,6 +1161,7 @@ function possibleCanvasContentsFunction( parameters: parameters, body: body, declarationSyntax: declarationSyntax, + functionWrapping: functionWrapping, } } @@ -1165,37 +1200,77 @@ function nodeFlagsForVarLetOrConst(varLetOrConst: VarLetOrConst): TS.NodeFlags { export function looksLikeCanvasElements( sourceFile: TS.SourceFile, node: TS.Node, + sourceText: string, + filename: string, + imports: Imports, + topLevelNames: Array, + propsObjectName: string | null, + existingHighlightBounds: Readonly, + alreadyExistingUIDs: Set, + applySteganography: SteganographyMode, ): Either { if (TS.isVariableStatement(node)) { const variableDeclaration = node.declarationList.declarations[0] if (variableDeclaration != null) { if (variableDeclaration.initializer != null) { const name = variableDeclaration.name.getText(sourceFile) - const initializer = variableDeclaration.initializer const varLetOrConst = getVarLetOrConst(node.declarationList) - if (TS.isArrowFunction(initializer)) { - return right( - possibleCanvasContentsFunction( - name, - initializer.parameters, - initializer.body, - varLetOrConst, - ), - ) - } else if (name === BakedInStoryboardVariableName) { - // FIXME The below case should result in a parsed top level *element*, but instead it is treated - // as a *component*. Unfortunately our use of the storyboard incorrectly relies on it being treated - // as a component. See https://github.com/concrete-utopia/utopia/issues/1718 for more info - return right( - possibleCanvasContentsExpression(name, variableDeclaration.initializer, varLetOrConst), - ) + const initializer = variableDeclaration.initializer + + function processVariable( + currentNode: TS.Node, + functionWrapping: Array, + ): Either { + if (TS.isCallExpression(currentNode)) { + const expressionFromCall = parseAttributeExpression( + sourceFile, + sourceText, + filename, + imports, + topLevelNames, + propsObjectName, + currentNode.expression, + existingHighlightBounds, + alreadyExistingUIDs, + [], + applySteganography, + 'outermost-expression', + ) + if (isRight(expressionFromCall) && currentNode.arguments.length === 1) { + const newFunctionWrapping = [ + ...functionWrapping, + simpleFunctionWrap(expressionFromCall.value.value), + ] + return processVariable(currentNode.arguments[0], newFunctionWrapping) + } + } else if (TS.isArrowFunction(currentNode)) { + return right( + possibleCanvasContentsFunction( + name, + currentNode.parameters, + currentNode.body, + varLetOrConst, + functionWrapping, + ), + ) + } else if (name === BakedInStoryboardVariableName) { + // FIXME The below case should result in a parsed top level *element*, but instead it is treated + // as a *component*. Unfortunately our use of the storyboard incorrectly relies on it being treated + // as a component. See https://github.com/concrete-utopia/utopia/issues/1718 for more info + return right( + possibleCanvasContentsExpression(name, initializer, varLetOrConst, functionWrapping), + ) + } + return left(node) } + + return processVariable(initializer, []) } } } else if (TS.isFunctionDeclaration(node)) { if (node.body != null) { const name = node.name == null ? null : node.name.getText(sourceFile) - return right(possibleCanvasContentsFunction(name, node.parameters, node.body, 'function')) + return right(possibleCanvasContentsFunction(name, node.parameters, node.body, 'function', [])) } } @@ -1537,7 +1612,18 @@ export function parseCode( pushImportStatement(rawImportStatement) } } else { - const possibleDeclaration = looksLikeCanvasElements(sourceFile, topLevelElement) + const possibleDeclaration = looksLikeCanvasElements( + sourceFile, + topLevelElement, + sourceText, + filePath, + imports, + topLevelNames, + null, + highlightBounds, + alreadyExistingUIDs_MUTABLE, + applySteganography, + ) if (isRight(possibleDeclaration)) { const canvasContents = possibleDeclaration.value const { name } = canvasContents @@ -1658,6 +1744,7 @@ export function parseCode( isFunction, canvasContents.declarationSyntax, contents.blockOrExpression, + canvasContents.functionWrapping, foldEither( (_) => null, (param) => param?.value ?? null, @@ -1799,6 +1886,7 @@ export function parseCode( topLevelElement.isFunction, topLevelElement.declarationSyntax, topLevelElement.blockOrExpression, + topLevelElement.functionWrapping, topLevelElement.param, topLevelElement.propsUsed, topLevelElement.rootElement, diff --git a/editor/src/core/workers/ts/ts-worker.spec.ts b/editor/src/core/workers/ts/ts-worker.spec.ts index 6a7007598f83..bef9006c3b66 100644 --- a/editor/src/core/workers/ts/ts-worker.spec.ts +++ b/editor/src/core/workers/ts/ts-worker.spec.ts @@ -153,6 +153,7 @@ const SampleInitTSWorkerMessage: IncomingWorkerMessage = { isFunction: true, declarationSyntax: 'var', blockOrExpression: 'block', + functionWrapping: [], param: { type: 'PARAM', dotDotDotToken: false, diff --git a/utopia-shared/src/types/element-template.ts b/utopia-shared/src/types/element-template.ts index 5adf0419099b..01dd7d49e3ff 100644 --- a/utopia-shared/src/types/element-template.ts +++ b/utopia-shared/src/types/element-template.ts @@ -320,6 +320,24 @@ export type VarLetOrConst = 'var' | 'let' | 'const' export type FunctionDeclarationSyntax = 'function' | VarLetOrConst export type BlockOrExpression = 'block' | 'parenthesized-expression' | 'expression' +export interface SimpleFunctionWrap { + type: 'SIMPLE_FUNCTION_WRAP' + functionExpression: JSExpression +} + +export function simpleFunctionWrap(functionExpression: JSExpression): SimpleFunctionWrap { + return { + type: 'SIMPLE_FUNCTION_WRAP', + functionExpression: functionExpression, + } +} + +export type FunctionWrap = SimpleFunctionWrap + +export function isSimpleFunctionWrap(wrap: FunctionWrap): wrap is SimpleFunctionWrap { + return wrap.type === 'SIMPLE_FUNCTION_WRAP' +} + export interface UtopiaJSXComponent { type: 'UTOPIA_JSX_COMPONENT' name: string | null @@ -331,6 +349,7 @@ export interface UtopiaJSXComponent { isFunction: boolean declarationSyntax: FunctionDeclarationSyntax blockOrExpression: BlockOrExpression + functionWrapping: Array param: Param | null propsUsed: Array rootElement: JSXElementChild From 21ae52dbd055271deed52fef189df2a216e5064b Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:25:31 +0200 Subject: [PATCH 031/103] Children row in inspector props (#5839) **Problem:** The children prop for components is not shown in the inspector. **Fix:** - Show the `children` prop in the inspector and allow changing it, via either a cartouche or number/string inputs - Allow setting children elements when asking for a prop update - For number and string children, use string/number inputs - or the default JSX component (or cartouche for data references) otherwise - If the selected component does not support children, don't show it https://github.com/concrete-utopia/utopia/assets/1081051/a66df108-2812-4c7d-9d65-aa83f8641bc6 **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5686 --- .../src/components/editor/element-children.ts | 80 +++++++++ .../common/property-controls-hooks.ts | 33 +++- editor/src/components/inspector/inspector.tsx | 19 +- .../component-section-children.tsx | 129 ++++++++++++++ .../component-section/component-section.tsx | 164 +++++++++++++++--- .../component-section/folder-section.tsx | 3 +- .../property-control-controls.tsx | 134 ++++++++++---- .../property-controls-section.tsx | 26 +++ .../navigator-item-components.tsx | 58 ++----- .../property-controls-utils.ts | 2 +- 10 files changed, 526 insertions(+), 122 deletions(-) create mode 100644 editor/src/components/editor/element-children.ts create mode 100644 editor/src/components/inspector/sections/component-section/component-section-children.tsx diff --git a/editor/src/components/editor/element-children.ts b/editor/src/components/editor/element-children.ts new file mode 100644 index 000000000000..c30d391bb18a --- /dev/null +++ b/editor/src/components/editor/element-children.ts @@ -0,0 +1,80 @@ +import type { ElementPath } from 'utopia-shared/src/types' +import { MetadataUtils } from '../../core/model/element-metadata-utils' +import { getRegisteredComponent } from '../../core/property-controls/property-controls-utils' +import { intrinsicHTMLElementNamesThatSupportChildren } from '../../core/shared/dom-utils' +import type { + ElementInstanceMetadataMap, + JSXElementChild, +} from '../../core/shared/element-template' +import { + isIntrinsicHTMLElement, + getJSXElementNameAsString, +} from '../../core/shared/element-template' +import type { PropertyControlsInfo } from '../custom-code/code-file' +import type { EditorAction } from './action-types' +import { deleteView, replaceElementInScope } from './actions/action-creators' +import * as EP from '../../core/shared/element-path' + +export function elementSupportsChildrenFromPropertyControls( + metadata: ElementInstanceMetadataMap, + propertyControlsInfo: PropertyControlsInfo, + target: ElementPath, +) { + const targetElement = MetadataUtils.findElementByElementPath(metadata, target) + + const targetJSXElement = MetadataUtils.getJSXElementFromElementInstanceMetadata(targetElement) + if (targetJSXElement == null) { + // this should not happen, erring on the side of true + return true + } + if (isIntrinsicHTMLElement(targetJSXElement.name)) { + // when it is an intrinsic html element, we check if it supports children from our list + return intrinsicHTMLElementNamesThatSupportChildren.includes(targetJSXElement.name.baseVariable) + } + + const elementImportInfo = targetElement?.importInfo + if (elementImportInfo == null) { + // erring on the side of true + return true + } + + const targetName = getJSXElementNameAsString(targetJSXElement.name) + const registeredComponent = getRegisteredComponent( + targetName, + elementImportInfo.filePath, + propertyControlsInfo, + ) + if (registeredComponent == null) { + // when there is no component annotation default is supporting children + return true + } + + return registeredComponent.supportsChildren +} + +export function replaceFirstChildAndDeleteSiblings( + target: ElementPath, + children: JSXElementChild[], + replaceWith: JSXElementChild, +): EditorAction[] { + return [ + // replace the first child + replaceElementInScope(target, { + type: 'replace-child-with-uid', + uid: children[0].uid, + replaceWith: replaceWith, + }), + // get rid of all the others + ...children.slice(1).map((child) => deleteView(EP.appendToPath(target, child.uid))), + ] +} + +const reNumericComponents = /[0-9\._]/g + +export function childrenAreProbablyNumericExpression(children: JSXElementChild[]) { + return children.some( + (c) => + c.type === 'ATTRIBUTE_OTHER_JAVASCRIPT' && + c.originalJavascript.trim().replace(reNumericComponents, '').length > 0, + ) +} diff --git a/editor/src/components/inspector/common/property-controls-hooks.ts b/editor/src/components/inspector/common/property-controls-hooks.ts index 6bc8005c4279..32abd88d5b46 100644 --- a/editor/src/components/inspector/common/property-controls-hooks.ts +++ b/editor/src/components/inspector/common/property-controls-hooks.ts @@ -13,7 +13,7 @@ import type { UnionControlDescription, RegularControlDescription, } from '../../custom-code/internal-property-controls' -import type { InspectorInfo, InspectorInfoWithRawValue } from './property-path-hooks' +import type { InspectorInfoWithRawValue } from './property-path-hooks' import { filterUtopiaSpecificProps, InspectorPropsContext, @@ -35,7 +35,7 @@ import { useKeepReferenceEqualityIfPossible, } from '../../../utils/react-performance' import type { UtopiaJSXComponent } from '../../../core/shared/element-template' -import { emptyComments, isJSXElement, jsIdentifier } from '../../../core/shared/element-template' +import { isJSXElement } from '../../../core/shared/element-template' import { addUniquely, mapDropNulls } from '../../../core/shared/array-utils' import { Substores, useEditorState } from '../../editor/store/store-hook' import { MetadataUtils } from '../../../core/model/element-metadata-utils' @@ -66,6 +66,7 @@ function filterSpecialProps(props: Array): Array { } export function useInspectorInfoForPropertyControl( + elementPath: ElementPath, propertyPath: PropertyPath, control: RegularControlDescription, ): InspectorInfoWithRawValue { @@ -103,8 +104,22 @@ export function useInspectorInfoForPropertyControl( const parserFn = unwrapperAndParserForPropertyControl(control) const printerFn = printerForPropertyControl(control) + + const allElementProps = useEditorState( + Substores.metadata, + (store) => store.editor.allElementProps, + 'allElementProps', + ) + let parsedValue: unknown = null - if (0 in rawValues && 0 in realValues) { + if (propertyPath.propertyElements[0] === 'children') { + const fromAllElementProps = allElementProps[EP.toString(elementPath)]?.children ?? null + switch (typeof fromAllElementProps) { + case 'number': + parsedValue = fromAllElementProps + break + } + } else if (0 in rawValues && 0 in realValues) { parsedValue = eitherToMaybe(parserFn(rawValues[0], realValues[0])) // TODO We need a way to surface these errors to the users } @@ -136,13 +151,13 @@ export function useInspectorInfoForPropertyControl( return { value: parsedValue, attributeExpression: attributeExpression, - controlStatus, + controlStatus: controlStatus, propertyStatus: propertyStatusToReturn, - controlStyles, - onSubmitValue, - onTransientSubmitValue, - onUnsetValues, - useSubmitValueFactory, + controlStyles: controlStyles, + onSubmitValue: onSubmitValue, + onTransientSubmitValue: onTransientSubmitValue, + onUnsetValues: onUnsetValues, + useSubmitValueFactory: useSubmitValueFactory, } } diff --git a/editor/src/components/inspector/inspector.tsx b/editor/src/components/inspector/inspector.tsx index ae6ee0263226..773e96377de1 100644 --- a/editor/src/components/inspector/inspector.tsx +++ b/editor/src/components/inspector/inspector.tsx @@ -57,7 +57,6 @@ import { UtopiaTheme, FlexRow, Button, - H1, SectionActionSheet, SquareButton, } from '../../uuiui' @@ -100,6 +99,7 @@ import { ExpandableIndicator } from '../navigator/navigator-item/expandable-indi import { isIntrinsicElementMetadata } from '../../core/model/project-file-utils' import { assertNever } from '../../core/shared/utils' import { DataReferenceSection } from './sections/data-reference-section' +import { replaceFirstChildAndDeleteSiblings } from '../editor/element-children' export interface ElementPathElement { name?: string @@ -779,11 +779,22 @@ export const InspectorContextProvider = React.memo<{ getElementsToTarget(selectedViews), ) + const jsxMetadataRef = useRefEditorState((store) => store.editor.jsxMetadata) + const onSubmitValueForHooks = React.useCallback( (newValue: JSExpression, path: PropertyPath, transient: boolean) => { const actionsArray = [ - ...refElementsToTargetForUpdates.current.map((elem) => { - return setProp_UNSAFE(elem, path, newValue) + ...refElementsToTargetForUpdates.current.flatMap((elem): EditorAction[] => { + // if the target is the children prop, replace the elements instead + if (path.propertyElements[0] === 'children') { + const element = MetadataUtils.findElementByElementPath(jsxMetadataRef.current, elem) + const children = + element != null && isRight(element.element) && isJSXElement(element.element.value) + ? element.element.value.children + : [] + return replaceFirstChildAndDeleteSiblings(elem, children, newValue) + } + return [setProp_UNSAFE(elem, path, newValue)] }), ] const actions: EditorAction[] = transient @@ -791,7 +802,7 @@ export const InspectorContextProvider = React.memo<{ : actionsArray dispatch(actions, 'everyone') }, - [dispatch, refElementsToTargetForUpdates], + [dispatch, refElementsToTargetForUpdates, jsxMetadataRef], ) const onUnsetValue = React.useCallback( diff --git a/editor/src/components/inspector/sections/component-section/component-section-children.tsx b/editor/src/components/inspector/sections/component-section/component-section-children.tsx new file mode 100644 index 000000000000..39f178fe109f --- /dev/null +++ b/editor/src/components/inspector/sections/component-section/component-section-children.tsx @@ -0,0 +1,129 @@ +import React from 'react' +import type { + ControlDescription, + RegularControlDescription, +} from '../../../custom-code/internal-property-controls' +import type { ElementPath } from '../../../../core/shared/project-file-types' +import * as PP from '../../../../core/shared/property-path' +import { iconForControlType } from '../../../../uuiui' +import type { ControlForPropProps } from './property-control-controls' +import { StringInputPropertyControl } from './property-control-controls' +import { Substores, useEditorState } from '../../../editor/store/store-hook' +import { MetadataUtils } from '../../../../core/model/element-metadata-utils' +import type { + ElementInstanceMetadataMap, + JSXElementChild, +} from '../../../../core/shared/element-template' +import { isJSXElement, isJSXTextBlock } from '../../../../core/shared/element-template' +import { IdentifierExpressionCartoucheControl } from './cartouche-control' +import { renderedAtChildNode } from '../../../editor/store/editor-state' +import { isRight } from '../../../../core/shared/either' +import { DataReferenceCartoucheControl } from './data-reference-cartouche' +import { assertNever } from '../../../../core/shared/utils' +import { childrenAreProbablyNumericExpression } from '../../../editor/element-children' +import type { CartoucheDataType } from './cartouche-ui' + +export function useChildrenPropOverride( + props: ControlForPropProps & { + onDeleteCartouche: () => void + safeToDelete: boolean + dataTypeForExpression: CartoucheDataType + }, +) { + const childrenContent = useEditorState( + Substores.metadata, + (store) => { + return getMaybeChildrenContent( + store.editor.jsxMetadata, + props.elementPath, + props.propName, + props.controlDescription, + ) + }, + 'useGetMaybeChildrenOverride maybeChildrenDataRefElement', + ) + + if (childrenContent == null) { + return null + } + + switch (childrenContent.type) { + case 'cartouche': + return ( + + ) + case 'expression': + return ( + + ) + case 'text': + return ( + + ) + default: + assertNever(childrenContent) + } +} + +function getMaybeChildrenContent( + jsxMetadata: ElementInstanceMetadataMap, + elementPath: ElementPath, + propName: string, + controlDescription: ControlDescription, +): + | { type: 'cartouche'; value: JSXElementChild } + | { type: 'text' } + | { type: 'expression' } + | null { + if (propName !== 'children') { + return null + } + + const element = MetadataUtils.findElementByElementPath(jsxMetadata, elementPath) + if (element != null && isRight(element.element) && isJSXElement(element.element.value)) { + const { children } = element.element.value + if (children.every((child) => isJSXTextBlock(child))) { + return { type: 'text' } + } else if ( + controlDescription.control === 'number-input' && + childrenAreProbablyNumericExpression(children) + ) { + return { type: 'expression' } + } else if ( + children.length === 1 && + MetadataUtils.isElementDataReference(children[0]) && + children[0].type !== 'ATTRIBUTE_OTHER_JAVASCRIPT' + ) { + return { type: 'cartouche', value: children[0] } + } + } + + return null +} diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index c82a83fcd38b..263756e5e72d 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -83,10 +83,14 @@ import { getFilePathForImportedComponent } from '../../../../core/model/project- import { safeIndex } from '../../../../core/shared/array-utils' import { useDispatch } from '../../../editor/store/dispatch-context' import { usePopper } from 'react-popper' -import type { JSExpressionOtherJavaScript } from '../../../../core/shared/element-template' +import type { + ElementInstanceMetadataMap, + JSExpressionOtherJavaScript, +} from '../../../../core/shared/element-template' import { getJSXElementNameAsString, isImportedOrigin, + isJSXElement, } from '../../../../core/shared/element-template' import { optionalMap } from '../../../../core/shared/optional-utils' import type { DataPickerCallback, DataPickerOption, ObjectPath } from './data-picker-utils' @@ -103,6 +107,12 @@ import { import { useAtom } from 'jotai' import { DataSelectorModal } from './data-selector-modal' import { getModifiableJSXAttributeAtPath } from '../../../../core/shared/jsx-attribute-utils' +import { isRight } from '../../../../core/shared/either' +import { useChildrenPropOverride } from './component-section-children' +import { + childrenAreProbablyNumericExpression, + replaceFirstChildAndDeleteSiblings, +} from '../../../editor/element-children' export interface PropertyLabelAndPlusButtonProps { title: string @@ -171,12 +181,13 @@ export function PropertyLabelAndPlusButton( } function useComponentPropsInspectorInfo( + elementPath: ElementPath, partialPath: PropertyPath, addPropsToPath: boolean, control: RegularControlDescription, ) { const propertyPath = addPropsToPath ? PP.append(PathForSceneProps, partialPath) : partialPath - return useInspectorInfoForPropertyControl(propertyPath, control) + return useInspectorInfoForPropertyControl(elementPath, propertyPath, control) } const ControlForProp = React.memo((props: ControlForPropProps) => { @@ -222,6 +233,16 @@ const ControlForProp = React.memo((props: ControlForPropProps, propertyPath: PropertyPath, expression: JSExpressionOtherJavaScript, @@ -435,6 +457,21 @@ function setPropertyFromDataPickerActions( return null } + // If the target replacement is the children property and the element has children, + // replace the children directly instead of its prop. + const isReplacingChildren = + propertyPath.propertyElements.length === 1 && propertyPath.propertyElements[0] === 'children' + if (isReplacingChildren) { + // …and the element has children… + const element = MetadataUtils.findElementByElementPath(metadata, target) + const children = + element != null && isRight(element.element) && isJSXElement(element.element.value) + ? element.element.value.children + : [] + return replaceFirstChildAndDeleteSiblings(target, children, expression) + } + + // In all other cases, replace the prop. return [ replaceElementInScope(target, { type: 'replace-property-value', @@ -457,6 +494,12 @@ function useDataPickerButtonInComponentSection( preferredAllState, ) + const metadata = useEditorState( + Substores.metadata, + (store) => store.editor.jsxMetadata, + 'useDataPickerButtonInComponentSection metadata', + ) + const pathToCurrentValue = useEditorState( Substores.metadata, (store) => { @@ -493,7 +536,11 @@ function useDataPickerButtonInComponentSection( const dataPickerButtonData = useDataPickerButton( variableNamesInScope, - (e) => optionalMap(dispatch, setPropertyFromDataPickerActions(selectedViews, propertyPath, e)), + (e) => + optionalMap( + dispatch, + setPropertyFromDataPickerActions(metadata, selectedViews, propertyPath, e), + ), pathToCurrentValue, selectedViews.at(0) ?? null, ) @@ -515,7 +562,12 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => { 'RowForBaseControl selectedViews', ) - const propMetadata = useComponentPropsInspectorInfo(propPath, isScene, controlDescription) + const propMetadata = useComponentPropsInspectorInfo( + selectedViews[0] ?? EP.emptyElementPath, + propPath, + isScene, + controlDescription, + ) const contextMenuItems = Utils.stripNulls([ addOnUnsetValues([propName], propMetadata.onUnsetValues), ]) @@ -535,12 +587,31 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => { setIsHovered(false) }, []) - const isConnectedToData = React.useMemo(() => { - return ( - propMetadata.propertyStatus.controlled && - propMetadata.attributeExpression?.type !== 'JSX_ELEMENT' - ) - }, [propMetadata]) + const isConnectedToData = useEditorState( + Substores.metadata, + (store) => { + if (propName === 'children') { + // for children props, we need to drill down and look for the types of the elements + return selectedViews.some((view) => { + const element = MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, view) + if (element != null && isRight(element.element) && isJSXElement(element.element.value)) { + const children = element.element.value.children + return ( + (controlDescription.control === 'number-input' && + childrenAreProbablyNumericExpression(children)) || + children.some((child) => child.type === 'JS_IDENTIFIER') + ) + } + return false + }) + } + return ( + propMetadata.propertyStatus.controlled && + propMetadata.attributeExpression?.type !== 'JSX_ELEMENT' + ) + }, + 'RowForBaseControl isConnectedToData', + ) const propertyLabel = props.label == null ? ( @@ -634,14 +705,27 @@ interface RowForArrayControlProps extends AbstractRowForControlProps { const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { const { propPath, controlDescription, isScene } = props const title = labelForControl(propPath, controlDescription) + + const selectedViews = useEditorState( + Substores.selectedViews, + (store) => store.editor.selectedViews, + 'RowForArrayControl selectedViews', + ) + const { value, onSubmitValue, propertyStatus } = useComponentPropsInspectorInfo( + selectedViews[0] ?? EP.emptyElementPath, propPath, isScene, controlDescription, ) const propName = `${PP.lastPart(propPath)}` - const propMetadata = useComponentPropsInspectorInfo(propPath, isScene, controlDescription) + const propMetadata = useComponentPropsInspectorInfo( + selectedViews[0] ?? EP.emptyElementPath, + propPath, + isScene, + controlDescription, + ) const sectionHeight = React.useMemo( () => getSectionHeight(controlDescription), @@ -677,12 +761,6 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { false, ) - const selectedViews = useEditorState( - Substores.selectedViews, - (store) => store.editor.selectedViews, - 'RowForArrayControl selectedViews', - ) - const dataPickerButtonData = useDataPickerButtonInComponentSection(selectedViews, props.propPath) return ( @@ -772,7 +850,14 @@ interface ArrayControlItemProps { const ArrayControlItem = React.memo((props: ArrayControlItemProps) => { const { bind, propPath, index, isScene, springStyle, controlDescription } = props const propPathWithIndex = PP.appendPropertyPathElems(propPath, [index]) + + const selectedViews = useEditorState( + Substores.selectedViews, + (store) => store.editor.selectedViews, + 'ArrayControlItem selectedViews', + ) const propMetadata = useComponentPropsInspectorInfo( + selectedViews[0] ?? EP.emptyElementPath, propPathWithIndex, isScene, controlDescription, @@ -848,7 +933,18 @@ interface RowForTupleControlProps extends AbstractRowForControlProps { const RowForTupleControl = React.memo((props: RowForTupleControlProps) => { const { propPath, controlDescription, isScene } = props const title = labelForControl(propPath, controlDescription) - const { value } = useComponentPropsInspectorInfo(propPath, isScene, controlDescription) + + const selectedViews = useEditorState( + Substores.selectedViews, + (store) => store.editor.selectedViews, + 'RowForTupleControl selectedViews', + ) + const { value } = useComponentPropsInspectorInfo( + selectedViews[0] ?? EP.emptyElementPath, + propPath, + isScene, + controlDescription, + ) const rowHeight = UtopiaTheme.layout.rowHeight.normal const transformedValue = Array.isArray(value) ? value : [value] @@ -900,7 +996,14 @@ interface TupleControlItemProps { const TupleControlItem = React.memo((props: TupleControlItemProps) => { const { propPath, index, isScene, controlDescription } = props const propPathWithIndex = PP.appendPropertyPathElems(propPath, [index]) + + const selectedViews = useEditorState( + Substores.selectedViews, + (store) => store.editor.selectedViews, + 'TupleControlItem selectedViews', + ) const propMetadata = useComponentPropsInspectorInfo( + selectedViews[0] ?? EP.emptyElementPath, propPathWithIndex, isScene, controlDescription, @@ -968,17 +1071,22 @@ const RowForObjectControl = React.memo((props: RowForObjectControlProps) => { const propName = `${PP.lastPart(propPath)}` - const propMetadata = useComponentPropsInspectorInfo(propPath, isScene, controlDescription) - const contextMenuItems = Utils.stripNulls([ - addOnUnsetValues([PP.lastPart(propPath)], propMetadata.onUnsetValues), - ]) - const selectedViews = useEditorState( Substores.selectedViews, (store) => store.editor.selectedViews, 'RowForObjectControl selectedViews', ) + const propMetadata = useComponentPropsInspectorInfo( + selectedViews[0] ?? EP.emptyElementPath, + propPath, + isScene, + controlDescription, + ) + const contextMenuItems = Utils.stripNulls([ + addOnUnsetValues([PP.lastPart(propPath)], propMetadata.onUnsetValues), + ]) + const dataPickerButtonData = useDataPickerButtonInComponentSection(selectedViews, props.propPath) const [isHovered, setIsHovered] = React.useState(false) @@ -1161,9 +1269,17 @@ interface RowForControlProps extends AbstractRowForControlProps { } export const RowForControl = React.memo((props: RowForControlProps) => { - const { controlDescription, disableToggling } = props + const { controlDescription, disableToggling, propPath } = props if (isBaseControlDescription(controlDescription)) { return + } else if (propPath.propertyElements[0] === 'children') { + // just show a single element for arrays of children + return ( + + ) } else { switch (controlDescription.control) { case 'array': diff --git a/editor/src/components/inspector/sections/component-section/folder-section.tsx b/editor/src/components/inspector/sections/component-section/folder-section.tsx index 0e88bba10d8e..0cbdfee3c55e 100644 --- a/editor/src/components/inspector/sections/component-section/folder-section.tsx +++ b/editor/src/components/inspector/sections/component-section/folder-section.tsx @@ -29,6 +29,7 @@ interface FolderSectionProps { setGlobalCursor: (cursor: CSSCursor | null) => void showHiddenControl: (path: string) => void title?: string + propsToIgnore: string[] } export const FolderSection = React.memo((props: FolderSectionProps) => { @@ -121,7 +122,7 @@ export const FolderSection = React.memo((props: FolderSectionProps) => { {when( props.isRoot, Object.keys(props.detectedPropsAndValuesWithoutControls).map((propName) => { - if (specialPropertiesToIgnore.includes(propName)) { + if (props.propsToIgnore.includes(propName)) { return null } else { const propValue = props.detectedPropsAndValuesWithoutControls[propName] diff --git a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx index add3ad9c2b51..9e34235c2703 100644 --- a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx +++ b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx @@ -4,7 +4,6 @@ import type { CSSCursor } from '../../../../uuiui-deps' import { SliderControl, getControlStyles } from '../../../../uuiui-deps' import type { AllowedEnumType, - BaseControlDescription, BasicControlOption, CheckboxControlDescription, ColorControlDescription, @@ -20,7 +19,6 @@ import type { RadioControlDescription, RadioControlOption, RegularControlDescription, - RegularControlType, StringInputControlDescription, Vector2ControlDescription, Vector3ControlDescription, @@ -39,11 +37,7 @@ import { FlexRow, UtopiaTheme, useColorTheme, - colorTheme, Icn, - Tooltip, - iconForControlType, - Icons, } from '../../../../uuiui' import type { CSSNumber } from '../../common/css-utils' import { printCSSNumber, cssNumber, defaultCSSColor } from '../../common/css-utils' @@ -68,23 +62,12 @@ import { } from '../../../custom-code/code-file' import { useDispatch } from '../../../editor/store/dispatch-context' import { HtmlPreview, ImagePreview } from './property-content-preview' -import type { - ElementInstanceMetadata, - JSXElementChild, -} from '../../../../core/shared/element-template' -import { - JSElementAccess, - JSIdentifier, - JSPropertyAccess, - getJSXElementNameLastPart, -} from '../../../../core/shared/element-template' +import { isJSXElement } from '../../../../core/shared/element-template' import type { JSXParsedType, JSXParsedValue } from '../../../../utils/value-parser-utils' import { assertNever } from '../../../../core/shared/utils' -import { preventDefault, stopPropagation } from '../../common/inspector-utils' -import { unless, when } from '../../../../utils/react-conditionals' import { MetadataUtils } from '../../../../core/model/element-metadata-utils' -import { parseNoneControlDescription } from '../../../../core/property-controls/property-controls-parser' -import * as EP from '../../../../core/shared/element-path' +import { isRight } from '../../../../core/shared/either' +import { parseNumber } from '../../../../core/shared/math-utils' export interface ControlForPropProps { propPath: PropertyPath @@ -98,12 +81,21 @@ export interface ControlForPropProps { elementPath: ElementPath } +function getValueOrUndefinedFromPropMetadata(propMetadata: InspectorInfoWithRawValue): any { + // NOTE: render props and props.children (which are displayed in the inspector + // as of https://github.com/concrete-utopia/utopia/pull/5839) don't use the same + // underlying data source, so there can be discrepancies in the values. + // Think about unifying the data sources if you touch this. + return propMetadata.propertyStatus.set ? propMetadata.value : undefined +} + export const CheckboxPropertyControl = React.memo( (props: ControlForPropProps) => { const { propName, propMetadata, controlDescription } = props const controlId = `${propName}-checkbox-property-control` - const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined + + const value = getValueOrUndefinedFromPropMetadata(propMetadata) ?? false return ( ) => { const { propMetadata, controlDescription } = props - const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined + const value = getValueOrUndefinedFromPropMetadata(propMetadata) // TS baulks at the map below for some reason if we don't first do this const controlOptions: Array = controlDescription.options @@ -348,8 +341,43 @@ export const NumberInputPropertyControl = React.memo( propMetadata.onUnsetValues, ) + const value = useEditorState( + Substores.metadata, + (store) => { + // if the target prop is children, dig for its value + if (propName === 'children') { + const element = MetadataUtils.findElementByElementPath( + store.editor.jsxMetadata, + props.elementPath, + ) + if ( + element != null && + isRight(element.element) && + isJSXElement(element.element.value) && + element.element.value.children.length > 0 + ) { + const child = element.element.value.children[0] + if (child.type === 'ATTRIBUTE_OTHER_JAVASCRIPT') { + // try first with the prop metadata value… + if (props.propMetadata.value != null) { + return props.propMetadata.value + } + // …if the value is not there, try to parse it + const parsed = parseNumber(child.originalJavascript) + if (isRight(parsed)) { + return parsed.value + } + } + } + return undefined + } + + return getValueOrUndefinedFromPropMetadata(propMetadata) + }, + 'NumberInputPropertyControl value', + ) + const controlId = `${propName}-number-input-property-control` - const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined const controlOptions = useKeepReferenceEqualityIfPossible({ minimum: controlDescription.min, maximum: controlDescription.max, @@ -412,7 +440,7 @@ export const RadioPropertyControl = React.memo( const { propName, propMetadata, controlDescription } = props const controlId = `${propName}-radio-property-control` - const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined + const value = getValueOrUndefinedFromPropMetadata(propMetadata) // TS baulks at the map below for some reason if we don't first do this const controlOptions: RadioControlDescription['options'] = controlDescription.options @@ -454,7 +482,7 @@ const NumberWithSliderControl = React.memo( const { propName, propMetadata, controlDescription } = props const controlId = `${propName}-slider-property-control` - const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined + const value = getValueOrUndefinedFromPropMetadata(propMetadata) ?? 0 return ( |--45px--|'}> @@ -492,10 +520,39 @@ const NumberWithSliderControl = React.memo( export const StringInputPropertyControl = React.memo( (props: ControlForPropProps) => { - const { propName, propMetadata, controlDescription } = props + const { propName, propMetadata } = props const controlId = `${propName}-string-input-property-control` - const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined + const value = useEditorState( + Substores.metadata, + (store) => { + // if the target prop is children, dig for its value + if (propName === 'children') { + const element = MetadataUtils.findElementByElementPath( + store.editor.jsxMetadata, + props.elementPath, + ) + if ( + element != null && + isRight(element.element) && + isJSXElement(element.element.value) && + element.element.value.children.length > 0 + ) { + const child = element.element.value.children[0] + switch (child.type) { + case 'ATTRIBUTE_OTHER_JAVASCRIPT': + return child.originalJavascript + case 'JSX_TEXT_BLOCK': + return child.text + } + } + return undefined + } + + return getValueOrUndefinedFromPropMetadata(propMetadata) + }, + 'StringInputPropertyControl value', + ) const safeValue = value ?? '' @@ -529,7 +586,7 @@ export const HtmlInputPropertyControl = React.memo( const { propName, propMetadata, controlDescription } = props const controlId = `${propName}-string-input-property-control` - const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined + const value = getValueOrUndefinedFromPropMetadata(propMetadata) const safeValue = value ?? '' @@ -565,9 +622,12 @@ export const JSXPropertyControl = React.memo( const theme = useColorTheme() const controlStatus = propMetadata.controlStatus const controlStyles = getControlStyles(controlStatus) - const value = propMetadata.propertyStatus.set ? propMetadata.value : undefined + const value = getValueOrUndefinedFromPropMetadata(propMetadata) - const safeValue: JSXParsedValue = value ?? { type: 'unknown', name: 'JSX' } + const safeValue: JSXParsedValue = + props.propName === 'children' + ? { type: 'internal-component', name: 'JSX' } + : value ?? { type: 'unknown', name: 'JSX' } return (
> = React.useMemo(() => { - const vectorValue = (propMetadata.propertyStatus.set ? propMetadata.value : undefined) ?? [] + const vectorValue = getValueOrUndefinedFromPropMetadata(propMetadata) ?? [] const keys = keysForVectorOfType(controlDescription.control) return propsArrayForCSSNumberArray(vectorValue, keys, propPath, propMetadata) @@ -730,8 +790,8 @@ export const EulerPropertyControl = React.memo( const { propPath, propMetadata, controlDescription, setGlobalCursor } = props const values = React.useMemo( - () => (propMetadata.propertyStatus.set ? propMetadata.value : undefined) ?? [], - [propMetadata.propertyStatus.set, propMetadata.value], + () => getValueOrUndefinedFromPropMetadata(propMetadata) ?? [], + [propMetadata], ) const numericPropsArray: Array> = React.useMemo(() => { @@ -778,7 +838,7 @@ export const Matrix3PropertyControl = React.memo( const { propPath, propMetadata, controlDescription, setGlobalCursor } = props const propsArray: Array> = React.useMemo(() => { - const value = (propMetadata.propertyStatus.set ? propMetadata.value : undefined) ?? [] + const value = getValueOrUndefinedFromPropMetadata(propMetadata) ?? [] // prettier-ignore const keys = [ @@ -822,7 +882,7 @@ export const Matrix4PropertyControl = React.memo( const { propPath, propMetadata, controlDescription, setGlobalCursor } = props const propsArray: Array> = React.useMemo(() => { - const value = (propMetadata.propertyStatus.set ? propMetadata.value : undefined) ?? [] + const value = getValueOrUndefinedFromPropMetadata(propMetadata) ?? [] // prettier-ignore const keys = [ diff --git a/editor/src/components/inspector/sections/component-section/property-controls-section.tsx b/editor/src/components/inspector/sections/component-section/property-controls-section.tsx index 00c697a30a44..3b8381e25b0a 100644 --- a/editor/src/components/inspector/sections/component-section/property-controls-section.tsx +++ b/editor/src/components/inspector/sections/component-section/property-controls-section.tsx @@ -14,6 +14,8 @@ import { specialPropertiesToIgnore, } from '../../../../core/property-controls/property-controls-utils' import { useDispatch } from '../../../editor/store/dispatch-context' +import { Substores, useEditorState } from '../../../editor/store/store-hook' +import { elementSupportsChildrenFromPropertyControls } from '../../../editor/element-children' interface PropertyControlsSectionProps { targets: ElementPath[] @@ -73,6 +75,27 @@ export const PropertyControlsSection = React.memo((props: PropertyControlsSectio ], ) + const targetsSupportChildren = useEditorState( + Substores.metadataAndPropertyControlsInfo, + (store) => { + return props.targets.every((target) => + elementSupportsChildrenFromPropertyControls( + store.editor.jsxMetadata, + store.editor.propertyControlsInfo, + target, + ), + ) + }, + 'PropertyControlsSection targetsSupportChildren', + ) + + const propsToIgnore = React.useMemo(() => { + if (!targetsSupportChildren) { + return [...specialPropertiesToIgnore, 'children'] + } + return specialPropertiesToIgnore + }, [targetsSupportChildren]) + return hasContent ? ( <> {propertiesWithFolders.folders.map(({ name, controls }) => ( ))} {Object.keys(propertiesWithFolders.advanced).length === 0 ? null : ( @@ -109,6 +134,7 @@ export const PropertyControlsSection = React.memo((props: PropertyControlsSectio unsetPropNames={propsWithControlsButNoValue} showHiddenControl={showHiddenControl} detectedPropsAndValuesWithoutControls={detectedPropsAndValuesWithoutControls} + propsToIgnore={propsToIgnore} title={AdvancedFolderLabel} /> )} diff --git a/editor/src/components/navigator/navigator-item/navigator-item-components.tsx b/editor/src/components/navigator/navigator-item/navigator-item-components.tsx index 45143f61cc6c..27d36b3b711b 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-components.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-components.tsx @@ -32,6 +32,7 @@ import { import { getRegisteredComponent } from '../../../core/property-controls/property-controls-utils' import { intrinsicHTMLElementNamesThatSupportChildren } from '../../../core/shared/dom-utils' import { ExpandableIndicator } from './expandable-indicator' +import { elementSupportsChildrenFromPropertyControls } from '../../editor/element-children' export const NavigatorHintCircleDiameter = 8 @@ -205,51 +206,6 @@ export const VisibilityIndicator: React.FunctionComponent< ) }) -const useSupportsChildren = (target: ElementPath): boolean => { - const targetElement = useEditorState( - Substores.metadata, - (store) => MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, target), - 'useSupportsChildren targetElement', - ) - - return useEditorState( - Substores.restOfEditor, - (store) => { - const targetJSXElement = MetadataUtils.getJSXElementFromElementInstanceMetadata(targetElement) - if (targetJSXElement == null) { - // this should not happen, erring on the side of true - return true - } - if (isIntrinsicHTMLElement(targetJSXElement.name)) { - // when it is an intrinsic html element, we check if it supports children from our list - return intrinsicHTMLElementNamesThatSupportChildren.includes( - targetJSXElement.name.baseVariable, - ) - } - - const elementImportInfo = targetElement?.importInfo - if (elementImportInfo == null) { - // erring on the side of true - return true - } - - const targetName = getJSXElementNameAsString(targetJSXElement.name) - const registeredComponent = getRegisteredComponent( - targetName, - elementImportInfo.filePath, - store.editor.propertyControlsInfo, - ) - if (registeredComponent == null) { - // when there is no component annotation default is supporting children - return true - } - - return registeredComponent.supportsChildren - }, - 'useSupportsChildren supportsChildren', - ) -} - interface AddChildButtonProps { target: ElementPath iconColor: IcnProps['color'] @@ -261,7 +217,17 @@ export function addChildButtonTestId(target: ElementPath): string { const AddChildButton = React.memo((props: AddChildButtonProps) => { const { target, iconColor } = props - const supportsChildren = useSupportsChildren(target) + const supportsChildren = useEditorState( + Substores.metadataAndPropertyControlsInfo, + (store) => + elementSupportsChildrenFromPropertyControls( + store.editor.jsxMetadata, + store.editor.propertyControlsInfo, + target, + ), + 'AddChildButton supportsChildren', + ) + const onClick = useCreateCallbackToShowComponentPicker()( [target], EditorActions.insertAsChildTarget(), diff --git a/editor/src/core/property-controls/property-controls-utils.ts b/editor/src/core/property-controls/property-controls-utils.ts index 836f1ca834e0..d4b5f6eb40da 100644 --- a/editor/src/core/property-controls/property-controls-utils.ts +++ b/editor/src/core/property-controls/property-controls-utils.ts @@ -224,7 +224,7 @@ export function hasStyleControls(propertyControls: PropertyControls): boolean { return propertyControls['style']?.control === 'style-controls' } -export const specialPropertiesToIgnore: Array = ['style', 'children'] +export const specialPropertiesToIgnore: Array = ['style'] export type InspectorSectionPreference = 'layout' | 'layout-system' | 'visual' | 'typography' From 826be03793bed15f778e8b7d8974a6a6b8128288 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:06:56 +0200 Subject: [PATCH 032/103] Cartouche colors states (#5847) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is part of #5840 **Problem:** The cartouche colors are not consistent and don't have a hovered state. **Fix:** Make the colors consistent, remove the border, and add a hovered/selected state color change for foreground, background, and icon. The specific colors are taken verbatim from the linked issue ⬆️ An incremental PR will take care of the background color for when a cartouche is part of a selected navigator row. https://github.com/concrete-utopia/utopia/assets/1081051/cc862cd7-62bd-4149-9168-288be9b0a32a **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/cartouche-control.tsx | 1 - .../component-section/cartouche-ui.tsx | 130 +++++++++++------- .../data-reference-cartouche.tsx | 4 - .../component-section/data-selector-modal.tsx | 3 - .../sections/data-reference-section.tsx | 1 - .../sections/layout-section/list-section.tsx | 7 +- .../layout-section/list-source-cartouche.tsx | 2 - .../navigator-item/navigator-item.tsx | 1 - ...performance-regression-tests.spec.tsx.snap | 25 ++-- .../performance-regression-tests.spec.tsx | 4 +- 10 files changed, 102 insertions(+), 76 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx index 2bb7b1168b18..002b5ddc39d6 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx @@ -47,7 +47,6 @@ export const IdentifierExpressionCartoucheControl = React.memo( safeToDelete={safeToDelete} onDelete={onDeleteCartouche} testId={testId} - inverted={false} contentIsComingFromServer={isDataComingFromHookResult} datatype={props.datatype} /> diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 8c396726ecd6..9d0189487b8e 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -1,6 +1,11 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@emotion/react' import React from 'react' +import type { IcnColor } from '../../../../uuiui' import { FlexRow, Icn, Tooltip, UtopiaStyles, useColorTheme } from '../../../../uuiui' import { when } from '../../../../utils/react-conditionals' +import { assertNever } from '../../../../core/shared/utils' export interface HoverHandlers { onMouseEnter: (e: React.MouseEvent) => void @@ -9,12 +14,13 @@ export interface HoverHandlers { export type CartoucheDataType = 'renderable' | 'boolean' | 'array' | 'object' | 'unknown' +type CartoucheSource = 'internal' | 'external' | 'literal' + export type CartoucheUIProps = React.PropsWithChildren<{ tooltip?: string | null - source: 'internal' | 'external' | 'literal' + source: CartoucheSource role: 'selection' | 'information' | 'folder' datatype: CartoucheDataType - inverted: boolean selected: boolean testId: string preview?: boolean @@ -33,7 +39,6 @@ export const CartoucheUI = React.forwardRef( onDelete, children, source, - inverted, selected, role, datatype, @@ -41,49 +46,12 @@ export const CartoucheUI = React.forwardRef( preview = false, } = props - const colorTheme = useColorTheme() - - const cartoucheIconColorToUse = source === 'external' ? 'green' : 'dynamic' - - const cartoucheIconColor = inverted - ? 'on-highlight-main' - : source === 'literal' - ? 'secondary' - : cartoucheIconColorToUse - - const borderColor = inverted - ? colorTheme.white.value - : role === 'folder' && !selected - ? colorTheme.verySubduedForeground.value - : source === 'external' - ? colorTheme.green.value - : colorTheme.selectionBlue.value - - const primaryForegoundColorToUse = - source === 'external' ? colorTheme.green.value : colorTheme.dynamicBlue.value - - const primaryBackgroundColorToUse = - source === 'external' ? colorTheme.green10.value : colorTheme.selectionBlue10.value - - const foregroundColor = inverted - ? colorTheme.white.value - : source === 'literal' || role === 'information' || role === 'folder' - ? colorTheme.neutralForeground.value - : primaryForegoundColorToUse - - const backgroundColor = - role === 'information' || role === 'folder' - ? colorTheme.neutralBackground.value - : source === 'literal' - ? colorTheme.fg0Opacity10.value - : primaryBackgroundColorToUse + const colors = useCartoucheColors(source) const wrappedOnClick = useStopPropagation(onClick) const wrappedOnDoubleClick = useStopPropagation(onDoubleClick) const wrappedOnDelete = useStopPropagation(onDelete) - const shouldShowBorder = selected || role === 'folder' - return (
{source === 'literal' ? null : ( @@ -151,7 +124,7 @@ export const CartoucheUI = React.forwardRef( void) | undefine [callback], ) } + +type CartoucheStateColor = { + default: T + hovered: T + selected: T +} + +function useCartoucheColors(source: CartoucheSource) { + const colorTheme = useColorTheme() + + const colors: { + fg: CartoucheStateColor + bg: CartoucheStateColor + icon: CartoucheStateColor + } = React.useMemo(() => { + switch (source) { + case 'external': + return { + fg: { + default: colorTheme.green.value, + hovered: colorTheme.green.value, + selected: colorTheme.white.value, + }, + bg: { + default: colorTheme.green10.value, + hovered: colorTheme.green20.value, + selected: colorTheme.green.value, + }, + icon: { default: 'green', hovered: 'green', selected: 'on-highlight-main' }, + } + case 'internal': + return { + fg: { + default: colorTheme.selectionBlue.value, + hovered: colorTheme.selectionBlue.value, + selected: colorTheme.white.value, + }, + bg: { + default: colorTheme.selectionBlue10.value, + hovered: colorTheme.selectionBlue20.value, + selected: colorTheme.selectionBlue.value, + }, + icon: { default: 'dynamic', hovered: 'dynamic', selected: 'on-highlight-main' }, + } + case 'literal': + return { + fg: { + default: colorTheme.fg1.value, + hovered: colorTheme.fg1.value, + selected: colorTheme.white.value, + }, + bg: { + default: colorTheme.bg5.value, + hovered: colorTheme.fg8.value, + selected: colorTheme.fg6.value, + }, + icon: { default: 'secondary', hovered: 'secondary', selected: 'on-highlight-main' }, + } + default: + assertNever(source) + } + }, [source, colorTheme]) + + return colors +} diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index 7bf0a01de992..c4c83e024d57 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -144,7 +144,6 @@ export const DataReferenceCartoucheControl = React.memo( contentsToDisplay={contentsToDisplay} selected={selected} safeToDelete={false} - inverted={false} onDelete={NO_OP} testId={`data-reference-cartouche-${EP.toString(elementPath)}`} contentIsComingFromServer={isDataComingFromHookResult} @@ -164,7 +163,6 @@ interface DataCartoucheInnerProps { onClick: (e: React.MouseEvent) => void onDoubleClick: (e: React.MouseEvent) => void selected: boolean - inverted: boolean contentsToDisplay: { type: 'literal' | 'reference'; label: string | null } safeToDelete: boolean onDelete: () => void @@ -182,7 +180,6 @@ export const DataCartoucheInner = React.forwardRef( safeToDelete, onDelete: onDeleteCallback, selected, - inverted, testId, contentsToDisplay, contentIsComingFromServer, @@ -213,7 +210,6 @@ export const DataCartoucheInner = React.forwardRef( onDoubleClick={onDoubleClick} datatype={datatype} selected={selected} - inverted={inverted} testId={testId} tooltip={!props.hideTooltip ? contentsToDisplay.label ?? 'DATA' : null} role='selection' diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 5e38b17d4988..f70ad55eb08e 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -538,7 +538,6 @@ export const DataSelectorModal = React.memo( key={variable.valuePath.toString()} source={variableSources[variable.valuePath.toString()] ?? 'internal'} datatype={childTypeToCartoucheDataType(variable.type)} - inverted={false} selected={ selectedPath == null ? false @@ -563,7 +562,6 @@ export const DataSelectorModal = React.memo( { List Source - + Contents diff --git a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx index 6109875da6b9..505b7863df89 100644 --- a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx @@ -61,7 +61,6 @@ function filterKeepArraysOnly(options: DataPickerOption[]): DataPickerOption[] { interface MapListSourceCartoucheProps { target: ElementPath - inverted: boolean selected: boolean openOn: 'single-click' | 'double-click' } @@ -201,7 +200,6 @@ export const MapListSourceCartouche = React.memo((props: MapListSourceCartoucheP onDoubleClick={onDoubleClick} onDelete={NO_OP} selected={props.selected} - inverted={props.inverted} safeToDelete={false} testId='list-source-cartouche' contentIsComingFromServer={isDataComingFromHookResult} diff --git a/editor/src/components/navigator/navigator-item/navigator-item.tsx b/editor/src/components/navigator/navigator-item/navigator-item.tsx index 530cbf2529a3..ef99437be247 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.tsx @@ -1262,7 +1262,6 @@ export const NavigatorRowLabel = React.memo((props: NavigatorRowLabelProps) => { /> diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index ce9d850463cf..a205f842426f 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -194,14 +194,15 @@ Array [ "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/span", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon):data-testid='delete-cartouche-onMouseDown'", - "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(div))", + "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/UtopiaSpiedClass(Tooltip)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "/Symbol(react.forward_ref)()/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", + "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(Styled(div))/div/Icon/img", "/Symbol(react.forward_ref)(Styled(div))/div/Icon/img", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", @@ -468,14 +469,15 @@ Array [ "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/span", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon):data-testid='delete-cartouche-onMouseDown'", - "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(div))", + "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/UtopiaSpiedClass(Tooltip)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "/Symbol(react.forward_ref)()/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", + "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(pt)", @@ -1618,14 +1620,15 @@ Array [ "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/span", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon):data-testid='delete-cartouche-onMouseDown'", - "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(div))", + "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/UtopiaSpiedClass(Tooltip)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "/Symbol(react.forward_ref)()/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", + "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(Styled(div))/div/Icon/img", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", @@ -1822,14 +1825,15 @@ Array [ "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/span", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon):data-testid='delete-cartouche-onMouseDown'", - "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(div))", + "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/UtopiaSpiedClass(Tooltip)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "/Symbol(react.forward_ref)()/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", + "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(pt)", @@ -2068,14 +2072,15 @@ Array [ "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/span", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon):data-testid='delete-cartouche-onMouseDown'", - "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(div))", + "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/UtopiaSpiedClass(Tooltip)", "//Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", "/Symbol(react.forward_ref)()/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", + "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(pt)", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index b136465d7450..d232eaca33fd 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -127,7 +127,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`906`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`909`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`648`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`650`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From 94965aa2daa7dfcdadaa811df4ab154243a8186d Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:00:42 +0100 Subject: [PATCH 033/103] Handle functions like forwardRef. (#5846) - `createComponentRendererComponent` now creates a regular function instead of an arrow function and that function analyses the `arguments` global to determine what the actual arguments to the function are. Then applies some light heuristics to then fix the "props" to one of those arguments. - `applyPropsParamToPassedProps` reworked to handle the multiple function arguments. - `propsUsedByIdentifierOrAccess` now caters for multiple function parameters. - `codeUsesProperty` and associated functions now handle multiple function parameters. - `UtopiaJSXComponent.param` is now `UtopiaJSXComponent.params`. - `parseCode` now parses multiple parameters for a given function. --- .../__snapshots__/ui-jsx-canvas.spec.tsx.snap | 1326 ----------------- .../ui-jsx-canvas-component-renderer.tsx | 45 +- .../ui-jsx-canvas-props-utils.ts | 33 +- .../components/canvas/ui-jsx-canvas.spec.tsx | 96 +- .../store-deep-equality-instances-2.spec.ts | 56 +- .../store/store-deep-equality-instances.ts | 4 +- .../components/shared/project-components.ts | 4 +- editor/src/core/data-tracing/data-tracing.ts | 9 +- .../storyboard-utils.spec.ts.snap | 2 +- .../src/core/model/element-template-utils.ts | 674 +++++---- editor/src/core/shared/element-template.ts | 14 +- ...r-printer-arbitrary-elements.spec.tsx.snap | 20 +- .../parser-printer-dot-notation.spec.tsx.snap | 18 +- .../__snapshots__/parser-printer.spec.ts.snap | 90 +- .../parser-printer-function-wrapped.spec.tsx | 230 ++- ...rser-printer-functional-components.spec.ts | 24 +- .../parser-printer-pragma.spec.ts | 1 + .../parser-printer-uids.spec.tsx | 2 +- .../parser-printer/parser-printer.spec.ts | 12 +- .../workers/parser-printer/parser-printer.ts | 39 +- editor/src/core/workers/ts/ts-worker.spec.ts | 18 +- utopia-shared/src/types/element-template.ts | 2 +- 22 files changed, 882 insertions(+), 1837 deletions(-) diff --git a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap index 19c16a3d0eea..b4707a65ac17 100644 --- a/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap +++ b/editor/src/components/canvas/__snapshots__/ui-jsx-canvas.spec.tsx.snap @@ -43525,1332 +43525,6 @@ export var App = (props) => { } `; -exports[`UiJsxCanvas render renders a canvas with a component wrapped in React.memo 1`] = ` -"
-
-
-
- hi - -
-
-
-
-" -`; - -exports[`UiJsxCanvas render renders a canvas with a component wrapped in React.memo 2`] = ` -Object { - "utopia-storyboard-uid/scene-aaa": Object { - "assignedToProp": null, - "attributeMetadatada": Object {}, - "componentInstance": false, - "computedStyle": Object {}, - "conditionValue": "not-a-conditional", - "earlyReturn": null, - "element": Object { - "type": "RIGHT", - "value": Object { - "children": Array [ - Object { - "children": Array [], - "name": Object { - "baseVariable": "App", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "app-entity", - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": Object { - "height": "100%", - "position": "absolute", - "width": "100%", - }, - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "title", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "Hi there!", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - ], - "name": Object { - "baseVariable": "Scene", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": Object { - "height": 200, - "left": 59, - "position": "absolute", - "top": 79, - "width": 200, - }, - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "scene-aaa", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - }, - "elementPath": Object { - "parts": Array [ - Array [ - "utopia-storyboard-uid", - "scene-aaa", - ], - ], - "type": "elementpath", - }, - "globalFrame": null, - "importInfo": Object { - "exportedName": "Scene", - "filePath": "utopia-api", - "type": "IMPORTED_ORIGIN", - "variableName": "Scene", - }, - "isEmotionOrStyledComponent": false, - "label": null, - "localFrame": null, - "nonRoundedGlobalFrame": null, - "specialSizeMeasurements": Object { - "alignItems": null, - "borderRadius": null, - "clientHeight": 0, - "clientWidth": 0, - "closestOffsetParentPath": Object { - "parts": Array [], - "type": "elementpath", - }, - "computedHugProperty": Object { - "height": null, - "width": null, - }, - "coordinateSystemBounds": null, - "display": "initial", - "flexDirection": null, - "float": "none", - "fontSize": null, - "fontStyle": null, - "fontWeight": null, - "gap": null, - "globalContentBoxForChildren": null, - "globalFrameWithTextContent": null, - "hasPositionOffset": false, - "hasTransform": false, - "htmlElementName": "div", - "immediateParentBounds": Object { - "height": 0, - "width": 0, - "x": 0, - "y": 0, - }, - "immediateParentProvidesLayout": true, - "justifyContent": null, - "layoutSystemForChildren": null, - "margin": Object {}, - "naturalHeight": null, - "naturalWidth": null, - "offset": Object { - "x": 0, - "y": 0, - }, - "padding": Object {}, - "parentFlexDirection": null, - "parentFlexGap": 0, - "parentHugsOnMainAxis": false, - "parentJustifyContent": null, - "parentLayoutSystem": "flow", - "parentPadding": Object {}, - "parentTextDirection": "ltr", - "position": "static", - "providesBoundsForAbsoluteChildren": false, - "renderedChildrenCount": 0, - "textBounds": null, - "textDecorationLine": null, - "usesParentBounds": false, - }, - "textContent": null, - }, - "utopia-storyboard-uid/scene-aaa/app-entity": Object { - "assignedToProp": null, - "attributeMetadatada": Object {}, - "componentInstance": false, - "computedStyle": Object {}, - "conditionValue": "not-a-conditional", - "earlyReturn": null, - "element": Object { - "type": "RIGHT", - "value": Object { - "children": Array [], - "name": Object { - "baseVariable": "App", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "app-entity", - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": Object { - "height": "100%", - "position": "absolute", - "width": "100%", - }, - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "title", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "Hi there!", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - }, - "elementPath": Object { - "parts": Array [ - Array [ - "utopia-storyboard-uid", - "scene-aaa", - "app-entity", - ], - ], - "type": "elementpath", - }, - "globalFrame": null, - "importInfo": Object { - "filePath": "test.js", - "type": "SAME_FILE_ORIGIN", - "variableName": "App", - }, - "isEmotionOrStyledComponent": false, - "label": null, - "localFrame": null, - "nonRoundedGlobalFrame": null, - "specialSizeMeasurements": Object { - "alignItems": null, - "borderRadius": null, - "clientHeight": 0, - "clientWidth": 0, - "closestOffsetParentPath": Object { - "parts": Array [], - "type": "elementpath", - }, - "computedHugProperty": Object { - "height": null, - "width": null, - }, - "coordinateSystemBounds": null, - "display": "initial", - "flexDirection": null, - "float": "none", - "fontSize": null, - "fontStyle": null, - "fontWeight": null, - "gap": null, - "globalContentBoxForChildren": null, - "globalFrameWithTextContent": null, - "hasPositionOffset": false, - "hasTransform": false, - "htmlElementName": "div", - "immediateParentBounds": Object { - "height": 0, - "width": 0, - "x": 0, - "y": 0, - }, - "immediateParentProvidesLayout": true, - "justifyContent": null, - "layoutSystemForChildren": null, - "margin": Object {}, - "naturalHeight": null, - "naturalWidth": null, - "offset": Object { - "x": 0, - "y": 0, - }, - "padding": Object {}, - "parentFlexDirection": null, - "parentFlexGap": 0, - "parentHugsOnMainAxis": false, - "parentJustifyContent": null, - "parentLayoutSystem": "flow", - "parentPadding": Object {}, - "parentTextDirection": "ltr", - "position": "static", - "providesBoundsForAbsoluteChildren": false, - "renderedChildrenCount": 0, - "textBounds": null, - "textDecorationLine": null, - "usesParentBounds": false, - }, - "textContent": null, - }, - "utopia-storyboard-uid/scene-aaa/app-entity:aaa": Object { - "assignedToProp": null, - "attributeMetadatada": Object {}, - "componentInstance": false, - "computedStyle": Object {}, - "conditionValue": "not-a-conditional", - "earlyReturn": null, - "element": Object { - "type": "RIGHT", - "value": Object { - "children": Array [ - Object { - "children": Array [ - Object { - "text": "hi", - "type": "JSX_TEXT_BLOCK", - "uid": "", - }, - ], - "name": Object { - "baseVariable": "span", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": Object { - "position": "absolute", - }, - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "bbb", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - ], - "name": Object { - "baseVariable": "div", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "content": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "SPREAD_ASSIGNMENT", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "onValue": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "name": "props", - "sourceMap": Object { - "mappings": "CAOyB", - "names": Array [], - "sources": Array [ - "code.tsx", - ], - "sourcesContent": Array [ - " - import * as React from 'react' - import { Storyboard, Scene } from 'utopia-api' - - export var App = React.memo((props) => { - return ( -
- hi -
- ) - }) - export var storyboard = (props) => { - return ( - - - - - - ) - } - ", - ], - "version": 3, - }, - "type": "JS_IDENTIFIER", - "uid": "", - }, - "optionallyChained": "not-optionally-chained", - "originalJavascript": "props.style", - "property": "style", - "sourceMap": Object { - "mappings": "CAOyB", - "names": Array [], - "sources": Array [ - "code.tsx", - ], - "sourcesContent": Array [ - " - import * as React from 'react' - import { Storyboard, Scene } from 'utopia-api' - - export var App = React.memo((props) => { - return ( -
- hi -
- ) - }) - export var storyboard = (props) => { - return ( - - - - - - ) - } - ", - ], - "version": 3, - }, - "type": "JS_PROPERTY_ACCESS", - "uid": "", - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "backgroundColor", - "keyComments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "PROPERTY_ASSIGNMENT", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "#FFFFFF", - }, - }, - ], - "type": "ATTRIBUTE_NESTED_OBJECT", - "uid": "", - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "aaa", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - }, - "elementPath": Object { - "parts": Array [ - Array [ - "utopia-storyboard-uid", - "scene-aaa", - "app-entity", - ], - Array [ - "aaa", - ], - ], - "type": "elementpath", - }, - "globalFrame": null, - "importInfo": Object { - "filePath": "test.js", - "type": "SAME_FILE_ORIGIN", - "variableName": "div", - }, - "isEmotionOrStyledComponent": false, - "label": null, - "localFrame": null, - "nonRoundedGlobalFrame": null, - "specialSizeMeasurements": Object { - "alignItems": null, - "borderRadius": null, - "clientHeight": 0, - "clientWidth": 0, - "closestOffsetParentPath": Object { - "parts": Array [], - "type": "elementpath", - }, - "computedHugProperty": Object { - "height": null, - "width": null, - }, - "coordinateSystemBounds": null, - "display": "initial", - "flexDirection": null, - "float": "none", - "fontSize": null, - "fontStyle": null, - "fontWeight": null, - "gap": null, - "globalContentBoxForChildren": null, - "globalFrameWithTextContent": null, - "hasPositionOffset": false, - "hasTransform": false, - "htmlElementName": "div", - "immediateParentBounds": Object { - "height": 0, - "width": 0, - "x": 0, - "y": 0, - }, - "immediateParentProvidesLayout": true, - "justifyContent": null, - "layoutSystemForChildren": null, - "margin": Object {}, - "naturalHeight": null, - "naturalWidth": null, - "offset": Object { - "x": 0, - "y": 0, - }, - "padding": Object {}, - "parentFlexDirection": null, - "parentFlexGap": 0, - "parentHugsOnMainAxis": false, - "parentJustifyContent": null, - "parentLayoutSystem": "flow", - "parentPadding": Object {}, - "parentTextDirection": "ltr", - "position": "static", - "providesBoundsForAbsoluteChildren": false, - "renderedChildrenCount": 0, - "textBounds": null, - "textDecorationLine": null, - "usesParentBounds": false, - }, - "textContent": null, - }, - "utopia-storyboard-uid/scene-aaa/app-entity:aaa/bbb": Object { - "assignedToProp": null, - "attributeMetadatada": Object {}, - "componentInstance": false, - "computedStyle": Object {}, - "conditionValue": "not-a-conditional", - "earlyReturn": null, - "element": Object { - "type": "RIGHT", - "value": Object { - "children": Array [ - Object { - "text": "hi", - "type": "JSX_TEXT_BLOCK", - "uid": "", - }, - ], - "name": Object { - "baseVariable": "span", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": Object { - "position": "absolute", - }, - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "bbb", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - }, - "elementPath": Object { - "parts": Array [ - Array [ - "utopia-storyboard-uid", - "scene-aaa", - "app-entity", - ], - Array [ - "aaa", - "bbb", - ], - ], - "type": "elementpath", - }, - "globalFrame": null, - "importInfo": Object { - "filePath": "test.js", - "type": "SAME_FILE_ORIGIN", - "variableName": "span", - }, - "isEmotionOrStyledComponent": false, - "label": null, - "localFrame": null, - "nonRoundedGlobalFrame": null, - "specialSizeMeasurements": Object { - "alignItems": null, - "borderRadius": null, - "clientHeight": 0, - "clientWidth": 0, - "closestOffsetParentPath": Object { - "parts": Array [], - "type": "elementpath", - }, - "computedHugProperty": Object { - "height": null, - "width": null, - }, - "coordinateSystemBounds": null, - "display": "initial", - "flexDirection": null, - "float": "none", - "fontSize": null, - "fontStyle": null, - "fontWeight": null, - "gap": null, - "globalContentBoxForChildren": null, - "globalFrameWithTextContent": null, - "hasPositionOffset": false, - "hasTransform": false, - "htmlElementName": "div", - "immediateParentBounds": Object { - "height": 0, - "width": 0, - "x": 0, - "y": 0, - }, - "immediateParentProvidesLayout": true, - "justifyContent": null, - "layoutSystemForChildren": null, - "margin": Object {}, - "naturalHeight": null, - "naturalWidth": null, - "offset": Object { - "x": 0, - "y": 0, - }, - "padding": Object {}, - "parentFlexDirection": null, - "parentFlexGap": 0, - "parentHugsOnMainAxis": false, - "parentJustifyContent": null, - "parentLayoutSystem": "flow", - "parentPadding": Object {}, - "parentTextDirection": "ltr", - "position": "static", - "providesBoundsForAbsoluteChildren": false, - "renderedChildrenCount": 0, - "textBounds": null, - "textDecorationLine": null, - "usesParentBounds": false, - }, - "textContent": null, - }, -} -`; - -exports[`UiJsxCanvas render renders a canvas with a component wrapped in a function that wraps the component with more content 1`] = ` -"
-
-
-
-
wrapComponent
-
-
- hi -
-
-
-
-
-
-" -`; - -exports[`UiJsxCanvas render renders a canvas with a component wrapped in a function that wraps the component with more content 2`] = ` -Object { - "utopia-storyboard-uid/scene-aaa": Object { - "assignedToProp": null, - "attributeMetadatada": Object {}, - "componentInstance": false, - "computedStyle": Object {}, - "conditionValue": "not-a-conditional", - "earlyReturn": null, - "element": Object { - "type": "RIGHT", - "value": Object { - "children": Array [ - Object { - "children": Array [], - "name": Object { - "baseVariable": "App", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "app-entity", - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": Object { - "height": "100%", - "position": "absolute", - "width": "100%", - }, - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "title", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "Hi there!", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - ], - "name": Object { - "baseVariable": "Scene", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": Object { - "height": 200, - "left": 59, - "position": "absolute", - "top": 79, - "width": 200, - }, - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "scene-aaa", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - }, - "elementPath": Object { - "parts": Array [ - Array [ - "utopia-storyboard-uid", - "scene-aaa", - ], - ], - "type": "elementpath", - }, - "globalFrame": null, - "importInfo": Object { - "exportedName": "Scene", - "filePath": "utopia-api", - "type": "IMPORTED_ORIGIN", - "variableName": "Scene", - }, - "isEmotionOrStyledComponent": false, - "label": null, - "localFrame": null, - "nonRoundedGlobalFrame": null, - "specialSizeMeasurements": Object { - "alignItems": null, - "borderRadius": null, - "clientHeight": 0, - "clientWidth": 0, - "closestOffsetParentPath": Object { - "parts": Array [], - "type": "elementpath", - }, - "computedHugProperty": Object { - "height": null, - "width": null, - }, - "coordinateSystemBounds": null, - "display": "initial", - "flexDirection": null, - "float": "none", - "fontSize": null, - "fontStyle": null, - "fontWeight": null, - "gap": null, - "globalContentBoxForChildren": null, - "globalFrameWithTextContent": null, - "hasPositionOffset": false, - "hasTransform": false, - "htmlElementName": "div", - "immediateParentBounds": Object { - "height": 0, - "width": 0, - "x": 0, - "y": 0, - }, - "immediateParentProvidesLayout": true, - "justifyContent": null, - "layoutSystemForChildren": null, - "margin": Object {}, - "naturalHeight": null, - "naturalWidth": null, - "offset": Object { - "x": 0, - "y": 0, - }, - "padding": Object {}, - "parentFlexDirection": null, - "parentFlexGap": 0, - "parentHugsOnMainAxis": false, - "parentJustifyContent": null, - "parentLayoutSystem": "flow", - "parentPadding": Object {}, - "parentTextDirection": "ltr", - "position": "static", - "providesBoundsForAbsoluteChildren": false, - "renderedChildrenCount": 0, - "textBounds": null, - "textDecorationLine": null, - "usesParentBounds": false, - }, - "textContent": null, - }, - "utopia-storyboard-uid/scene-aaa/app-entity": Object { - "assignedToProp": null, - "attributeMetadatada": Object {}, - "componentInstance": false, - "computedStyle": Object {}, - "conditionValue": "not-a-conditional", - "earlyReturn": null, - "element": Object { - "type": "RIGHT", - "value": Object { - "children": Array [], - "name": Object { - "baseVariable": "App", - "propertyPath": Object { - "propertyElements": Array [], - }, - }, - "props": Array [ - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "data-uid", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "app-entity", - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "style", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": Object { - "height": "100%", - "position": "absolute", - "width": "100%", - }, - }, - }, - Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "key": "title", - "type": "JSX_ATTRIBUTES_ENTRY", - "value": Object { - "comments": Object { - "leadingComments": Array [], - "trailingComments": Array [], - }, - "type": "ATTRIBUTE_VALUE", - "uid": "", - "value": "Hi there!", - }, - }, - ], - "type": "JSX_ELEMENT", - "uid": "", - }, - }, - "elementPath": Object { - "parts": Array [ - Array [ - "utopia-storyboard-uid", - "scene-aaa", - "app-entity", - ], - ], - "type": "elementpath", - }, - "globalFrame": null, - "importInfo": Object { - "filePath": "test.js", - "type": "SAME_FILE_ORIGIN", - "variableName": "App", - }, - "isEmotionOrStyledComponent": false, - "label": null, - "localFrame": null, - "nonRoundedGlobalFrame": null, - "specialSizeMeasurements": Object { - "alignItems": null, - "borderRadius": null, - "clientHeight": 0, - "clientWidth": 0, - "closestOffsetParentPath": Object { - "parts": Array [], - "type": "elementpath", - }, - "computedHugProperty": Object { - "height": null, - "width": null, - }, - "coordinateSystemBounds": null, - "display": "initial", - "flexDirection": null, - "float": "none", - "fontSize": null, - "fontStyle": null, - "fontWeight": null, - "gap": null, - "globalContentBoxForChildren": null, - "globalFrameWithTextContent": null, - "hasPositionOffset": false, - "hasTransform": false, - "htmlElementName": "div", - "immediateParentBounds": Object { - "height": 0, - "width": 0, - "x": 0, - "y": 0, - }, - "immediateParentProvidesLayout": true, - "justifyContent": null, - "layoutSystemForChildren": null, - "margin": Object {}, - "naturalHeight": null, - "naturalWidth": null, - "offset": Object { - "x": 0, - "y": 0, - }, - "padding": Object {}, - "parentFlexDirection": null, - "parentFlexGap": 0, - "parentHugsOnMainAxis": false, - "parentJustifyContent": null, - "parentLayoutSystem": "flow", - "parentPadding": Object {}, - "parentTextDirection": "ltr", - "position": "static", - "providesBoundsForAbsoluteChildren": false, - "renderedChildrenCount": 0, - "textBounds": null, - "textDecorationLine": null, - "usesParentBounds": false, - }, - "textContent": null, - }, -} -`; - exports[`UiJsxCanvas render renders a component used in an arbitrary block correctly 1`] = ` "
}): ComponentRendererComponent { - const Component = (realPassedPropsIncludingUtopiaSpecialStuff: any) => { + const Component = (...functionArguments: Array) => { + // Attempt to determine which function argument is the "regular" props object/value. + // Default it to the first if one is not identified by looking for some of our special keys. + let regularPropsArgumentIndex: number = functionArguments.findIndex((functionArgument) => { + if ( + typeof functionArgument === 'object' && + functionArgument != null && + !Array.isArray(functionArgument) + ) { + return UTOPIA_INSTANCE_PATH in functionArgument || UTOPIA_PATH_KEY in functionArgument + } else { + return false + } + }) + if (regularPropsArgumentIndex < 0) { + regularPropsArgumentIndex = 0 + } const { [UTOPIA_INSTANCE_PATH]: instancePathAny, // TODO types? [UTOPIA_PATH_KEY]: pathsString, // TODO types? ...realPassedProps - } = realPassedPropsIncludingUtopiaSpecialStuff + } = functionArguments[regularPropsArgumentIndex] + + // We want to strip the instance path and path from the props that we pass to the component. + let slightlyStrippedFunctionsArguments = [...functionArguments] + slightlyStrippedFunctionsArguments[regularPropsArgumentIndex] = realPassedProps const mutableContext = params.mutableContextRef.current[params.filePath].mutableContext @@ -140,7 +161,7 @@ export function createComponentRendererComponent(params: { applyPropsParamToPassedProps( mutableContext.rootScope, rootElementPath, - realPassedProps, + slightlyStrippedFunctionsArguments, param, { requireResult: mutableContext.requireResult, @@ -166,7 +187,7 @@ export function createComponentRendererComponent(params: { undefined, codeError, ), - utopiaJsxComponent.param, + utopiaJsxComponent.params, ) ?? { props: realPassedProps } let scope: MapLike = { @@ -177,13 +198,15 @@ export function createComponentRendererComponent(params: { let spiedVariablesInScope: VariableData = { ...mutableContext.spiedVariablesDeclaredInRootScope, } - if (rootElementPath != null && utopiaJsxComponent.param != null) { - propertiesExposedByParam(utopiaJsxComponent.param).forEach((paramName) => { - spiedVariablesInScope[paramName] = { - spiedValue: scope[paramName], - insertionCeiling: rootElementPath, - } - }) + if (rootElementPath != null && utopiaJsxComponent.params != null) { + for (const param of utopiaJsxComponent.params) { + propertiesExposedByParam(param).forEach((paramName) => { + spiedVariablesInScope[paramName] = { + spiedValue: scope[paramName], + insertionCeiling: rootElementPath, + } + }) + } } // Protect against infinite recursion by taking the view that anything diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-props-utils.ts b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-props-utils.ts index ff79f0100876..60bb6e6831c5 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-props-utils.ts +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/ui-jsx-canvas-props-utils.ts @@ -1,10 +1,5 @@ import type { MapLike } from 'typescript' -import type { - Param, - BoundParam, - JSExpressionMapOrOtherJavascript, - JSExpression, -} from '../../../core/shared/element-template' +import type { Param, BoundParam, JSExpression } from '../../../core/shared/element-template' import { isRegularParam, isDestructuredObject, @@ -17,8 +12,8 @@ import type { RenderContext } from './ui-jsx-canvas-element-renderer-utils' export function applyPropsParamToPassedProps( inScope: MapLike, elementPath: ElementPath | null, - passedProps: MapLike, - propsParam: Param, + functionArguments: Array, + propsParams: Array, renderContext: RenderContext, uid: string | undefined, codeError: Error | null, @@ -45,14 +40,18 @@ export function applyPropsParamToPassedProps( } } - function applyBoundParamToOutput(value: unknown, boundParam: BoundParam): void { + function applyBoundParamToOutput(functionArgument: unknown, boundParam: BoundParam): void { if (isRegularParam(boundParam)) { const { paramName } = boundParam - output[paramName] = getParamValue(paramName, value, boundParam.defaultExpression) + output[paramName] = getParamValue(paramName, functionArgument, boundParam.defaultExpression) } else if (isDestructuredObject(boundParam)) { - if (typeof value === 'object' && !Array.isArray(value) && value !== null) { - const valueAsRecord: Record = { ...value } - let remainingValues = { ...value } as Record + if ( + typeof functionArgument === 'object' && + !Array.isArray(functionArgument) && + functionArgument !== null + ) { + const valueAsRecord: Record = { ...functionArgument } + let remainingValues = { ...functionArgument } as Record for (const part of boundParam.parts) { const { propertyName, param } = part if (propertyName == null) { @@ -85,8 +84,8 @@ export function applyPropsParamToPassedProps( } // TODO Throw, but what? } else { - if (Array.isArray(value)) { - let remainingValues = [...value] + if (Array.isArray(functionArgument)) { + let remainingValues = [...functionArgument] boundParam.parts.forEach((param) => { if (isOmittedParam(param)) { remainingValues.shift() @@ -115,6 +114,8 @@ export function applyPropsParamToPassedProps( } } - applyBoundParamToOutput(passedProps, propsParam.boundParam) + propsParams.forEach((propsParam, paramIndex) => { + applyBoundParamToOutput(functionArguments[paramIndex], propsParam.boundParam) + }) return output } diff --git a/editor/src/components/canvas/ui-jsx-canvas.spec.tsx b/editor/src/components/canvas/ui-jsx-canvas.spec.tsx index aac365459d04..5f4835769c7d 100644 --- a/editor/src/components/canvas/ui-jsx-canvas.spec.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas.spec.tsx @@ -1,4 +1,4 @@ -/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "testCanvasRender", "testCanvasRenderMultifile", "testCanvasErrorMultifile"] }] */ +/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "testCanvasRender", "testCanvasRenderMultifile", "testCanvasErrorMultifile", "testCanvasRenderInline"] }] */ import { BakedInStoryboardUID, BakedInStoryboardVariableName } from '../../core/model/scene-utils' import { AwkwardFragmentsCode } from '../../core/workers/parser-printer/parser-printer-fragments.test-utils' import { @@ -157,7 +157,7 @@ export { ToBeDefaultExported as default }`, }) it('renders a canvas with a component wrapped in React.memo', () => { - testCanvasRender( + testCanvasRenderInline( null, ` import * as React from 'react' @@ -194,7 +194,7 @@ export { ToBeDefaultExported as default }`, }) it('renders a canvas with a component wrapped in a function that wraps the component with more content', () => { - testCanvasRender( + testCanvasRenderInline( null, ` import * as React from 'react' @@ -241,6 +241,96 @@ export { ToBeDefaultExported as default }`, ) }) + it('renders a canvas with a component wrapped in a function that has more that one parameter', () => { + testCanvasRenderInline( + null, + ` + import * as React from 'react' + import { Storyboard, Scene } from 'utopia-api' + + function twoParameterWrapper(componentFunction) { + return (props) => { + return componentFunction(props, 'Some Text') + } + } + + export var App = twoParameterWrapper((props, otherValue) => { + return ( +
+ {otherValue} +
+ ) + }) + + export var ${BakedInStoryboardVariableName} = (props) => { + return ( + + + + + + ) + } + `, + ) + }) + + it('renders a canvas with a component wrapped in forwardRef', () => { + testCanvasRenderInline( + null, + ` + import * as React from 'react' + import { Storyboard, Scene } from 'utopia-api' + + export var ComponentThatForwards = React.forwardRef((props, ref) => { + return ( +
+ Something +
+ ) + }) + + export var App = () => { + const ref = React.useRef(null) + return ( + + ) + } + + export var ${BakedInStoryboardVariableName} = (props) => { + return ( + + + + + + ) + } + `, + ) + }) + it('renders a canvas defined by a utopia storyboard component', () => { testCanvasRender( null, diff --git a/editor/src/components/editor/store/store-deep-equality-instances-2.spec.ts b/editor/src/components/editor/store/store-deep-equality-instances-2.spec.ts index 428d06f16905..a2d5214f8f5c 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances-2.spec.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances-2.spec.ts @@ -789,15 +789,17 @@ describe('UtopiaJSXComponentKeepDeepEquality', () => { declarationSyntax: 'const', blockOrExpression: 'block', functionWrapping: [], - param: { - type: 'PARAM', - dotDotDotToken: false, - boundParam: { - type: 'REGULAR_PARAM', - paramName: 'props', - defaultExpression: null, + params: [ + { + type: 'PARAM', + dotDotDotToken: false, + boundParam: { + type: 'REGULAR_PARAM', + paramName: 'props', + defaultExpression: null, + }, }, - }, + ], propsUsed: [], rootElement: { type: 'JSX_ELEMENT', @@ -839,15 +841,17 @@ describe('UtopiaJSXComponentKeepDeepEquality', () => { declarationSyntax: 'const', blockOrExpression: 'block', functionWrapping: [], - param: { - type: 'PARAM', - dotDotDotToken: false, - boundParam: { - type: 'REGULAR_PARAM', - paramName: 'props', - defaultExpression: null, + params: [ + { + type: 'PARAM', + dotDotDotToken: false, + boundParam: { + type: 'REGULAR_PARAM', + paramName: 'props', + defaultExpression: null, + }, }, - }, + ], propsUsed: [], rootElement: { type: 'JSX_ELEMENT', @@ -889,15 +893,17 @@ describe('UtopiaJSXComponentKeepDeepEquality', () => { declarationSyntax: 'const', blockOrExpression: 'block', functionWrapping: [], - param: { - type: 'PARAM', - dotDotDotToken: false, - boundParam: { - type: 'REGULAR_PARAM', - paramName: 'props', - defaultExpression: null, + params: [ + { + type: 'PARAM', + dotDotDotToken: false, + boundParam: { + type: 'REGULAR_PARAM', + paramName: 'props', + defaultExpression: null, + }, }, - }, + ], propsUsed: [], rootElement: { type: 'JSX_ELEMENT', @@ -950,7 +956,7 @@ describe('UtopiaJSXComponentKeepDeepEquality', () => { expect(result.value.isFunction).toBe(oldValue.isFunction) expect(result.value.declarationSyntax).toBe(oldValue.declarationSyntax) expect(result.value.blockOrExpression).toBe(oldValue.blockOrExpression) - expect(result.value.param).toBe(oldValue.param) + expect(result.value.params).toBe(oldValue.params) expect(result.value.propsUsed).toBe(oldValue.propsUsed) expect(result.value.rootElement).toBe(oldValue.rootElement) expect(result.value.arbitraryJSBlock).toBe(oldValue.arbitraryJSBlock) 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 c2a87be51c3f..a88058efe598 100644 --- a/editor/src/components/editor/store/store-deep-equality-instances.ts +++ b/editor/src/components/editor/store/store-deep-equality-instances.ts @@ -1605,8 +1605,8 @@ export const UtopiaJSXComponentKeepDeepEquality: KeepDeepEqualityCall component.functionWrapping, arrayDeepEquality(FunctionWrapKeepDeepEquality), - (component) => component.param, - nullableDeepEquality(ParamKeepDeepEquality()), + (component) => component.params, + nullableDeepEquality(arrayDeepEquality(ParamKeepDeepEquality())), (component) => component.propsUsed, arrayDeepEquality(createCallWithTripleEquals()), (component) => component.rootElement, diff --git a/editor/src/components/shared/project-components.ts b/editor/src/components/shared/project-components.ts index a6e25286b1b7..aabba62f4631 100644 --- a/editor/src/components/shared/project-components.ts +++ b/editor/src/components/shared/project-components.ts @@ -686,8 +686,8 @@ function isUtopiaJSXComponentEligibleForMode( if (insertMenuMode === 'wrap') { return ( element != null && - element.param != null && - elementUsesProperty(element.rootElement, element.param, 'children') + element.params != null && + elementUsesProperty(element.rootElement, element.params, 'children') ) } return true diff --git a/editor/src/core/data-tracing/data-tracing.ts b/editor/src/core/data-tracing/data-tracing.ts index e42825b7e93a..0e727d1fceeb 100644 --- a/editor/src/core/data-tracing/data-tracing.ts +++ b/editor/src/core/data-tracing/data-tracing.ts @@ -756,13 +756,10 @@ function lookupInComponentScope( // let's see if the identifier points to a component prop { - if (componentHoldingElement.param != null) { + const firstParam = componentHoldingElement?.params?.at(0) + if (firstParam != null) { // let's try to match the name to the containing component's props! - const foundPropSameName = propUsedByIdentifierOrAccess( - componentHoldingElement.param, - identifier, - pathDrillSoFar, - ) + const foundPropSameName = propUsedByIdentifierOrAccess(firstParam, identifier, pathDrillSoFar) if (isRight(foundPropSameName)) { // ok, so let's now travel to the containing component's instance in the metadata and continue the lookup! diff --git a/editor/src/core/model/__snapshots__/storyboard-utils.spec.ts.snap b/editor/src/core/model/__snapshots__/storyboard-utils.spec.ts.snap index e1545668b90d..8cfa27acee6e 100644 --- a/editor/src/core/model/__snapshots__/storyboard-utils.spec.ts.snap +++ b/editor/src/core/model/__snapshots__/storyboard-utils.spec.ts.snap @@ -15,7 +15,7 @@ Array [ "functionWrapping": Array [], "isFunction": false, "name": "storyboard", - "param": null, + "params": null, "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], diff --git a/editor/src/core/model/element-template-utils.ts b/editor/src/core/model/element-template-utils.ts index aaee617e0269..3583672b34e6 100644 --- a/editor/src/core/model/element-template-utils.ts +++ b/editor/src/core/model/element-template-utils.ts @@ -808,42 +808,49 @@ export function elementOnlyHasTextChildren(element: JSXElementChild): boolean { } } -export function codeUsesProperty(javascript: string, propsParam: Param, property: string): boolean { - switch (propsParam.boundParam.type) { - case 'REGULAR_PARAM': - return javascript.includes(`${propsParam.boundParam.paramName}.${property}`) - case 'DESTRUCTURED_OBJECT': - return propsParam.boundParam.parts.some((part) => { - const partBoundParam = part.param.boundParam - if (partBoundParam.type === 'REGULAR_PARAM') { - // This handles the aliasing that may be applied to the destructured field. - const propertyToCheck = part.propertyName ?? partBoundParam.paramName - if (propertyToCheck === property) { - // This is the aliased name or if there's no alias the field name. - const propertyToLookFor = partBoundParam.paramName - return javascript.includes(propertyToLookFor) +export function codeUsesProperty( + javascript: string, + propsParams: Array, + property: string, +): boolean { + for (const propsParam of propsParams) { + switch (propsParam.boundParam.type) { + case 'REGULAR_PARAM': + return javascript.includes(`${propsParam.boundParam.paramName}.${property}`) + case 'DESTRUCTURED_OBJECT': + return propsParam.boundParam.parts.some((part) => { + const partBoundParam = part.param.boundParam + if (partBoundParam.type === 'REGULAR_PARAM') { + // This handles the aliasing that may be applied to the destructured field. + const propertyToCheck = part.propertyName ?? partBoundParam.paramName + if (propertyToCheck === property) { + // This is the aliased name or if there's no alias the field name. + const propertyToLookFor = partBoundParam.paramName + return javascript.includes(propertyToLookFor) + } } - } + return false + }) + case 'DESTRUCTURED_ARRAY': return false - }) - case 'DESTRUCTURED_ARRAY': - return false - default: - const _exhaustiveCheck: never = propsParam.boundParam - throw new Error(`Unhandled param type: ${JSON.stringify(propsParam.boundParam)}`) + default: + const _exhaustiveCheck: never = propsParam.boundParam + throw new Error(`Unhandled param type: ${JSON.stringify(propsParam.boundParam)}`) + } } + return false } export function componentUsesProperty(component: UtopiaJSXComponent, property: string): boolean { - if (component.param == null) { + if (component.params == null) { return false } else { - return elementUsesProperty(component.rootElement, component.param, property) + return elementUsesProperty(component.rootElement, component.params, property) } } export function componentHonoursPropsPosition(component: UtopiaJSXComponent): boolean { - if (component.param == null) { + if (component.params == null) { return false } else { const rootElement = component.rootElement @@ -856,11 +863,11 @@ export function componentHonoursPropsPosition(component: UtopiaJSXComponent): bo PP.create('style', 'bottom'), ) return ( - ((propertyComesFromPropsStyle(component.param, leftStyleAttr, 'left') || - propertyComesFromPropsStyle(component.param, rightStyleAttr, 'right')) && - (propertyComesFromPropsStyle(component.param, topStyleAttr, 'top') || - propertyComesFromPropsStyle(component.param, bottomStyleAttr, 'bottom'))) || - propsStyleIsSpreadInto(component.param, rootElement.props) + ((propertyComesFromPropsStyle(component.params, leftStyleAttr, 'left') || + propertyComesFromPropsStyle(component.params, rightStyleAttr, 'right')) && + (propertyComesFromPropsStyle(component.params, topStyleAttr, 'top') || + propertyComesFromPropsStyle(component.params, bottomStyleAttr, 'bottom'))) || + propsStyleIsSpreadInto(component.params, rootElement.props) ) } else { return false @@ -869,7 +876,7 @@ export function componentHonoursPropsPosition(component: UtopiaJSXComponent): bo } export function componentHonoursPropsSize(component: UtopiaJSXComponent): boolean { - if (component.param == null) { + if (component.params == null) { return false } else { const rootElement = component.rootElement @@ -880,9 +887,9 @@ export function componentHonoursPropsSize(component: UtopiaJSXComponent): boolea PP.create('style', 'height'), ) return ( - (propertyComesFromPropsStyle(component.param, widthStyleAttr, 'width') && - propertyComesFromPropsStyle(component.param, heightStyleAttr, 'height')) || - propsStyleIsSpreadInto(component.param, rootElement.props) + (propertyComesFromPropsStyle(component.params, widthStyleAttr, 'width') && + propertyComesFromPropsStyle(component.params, heightStyleAttr, 'height')) || + propsStyleIsSpreadInto(component.params, rootElement.props) ) } else { return false @@ -901,157 +908,160 @@ function checkJSReferencesVariable( ) } -function propsStyleIsSpreadInto(propsParam: Param, attributes: JSXAttributes): boolean { - const boundParam = propsParam.boundParam - switch (boundParam.type) { - case 'REGULAR_PARAM': { - const propsVariableName = boundParam.paramName - const stylePropPath = `${propsVariableName}.style` - const styleProp = getJSXAttributesAtPath(attributes, PP.create('style')) - const styleAttribute = styleProp.attribute - switch (styleAttribute.type) { - case 'ATTRIBUTE_NOT_FOUND': - return false - case 'ATTRIBUTE_VALUE': - return false - case 'JSX_MAP_EXPRESSION': - if (isJSExpressionOtherJavaScript(styleAttribute.valueToMap)) { - return checkJSReferencesVariable( - styleAttribute.valueToMap, - propsVariableName, - stylePropPath, - ) - } - if (isJSExpressionOtherJavaScript(styleAttribute.mapFunction)) { - return checkJSReferencesVariable( - styleAttribute.mapFunction, - propsVariableName, - stylePropPath, - ) - } - return false - case 'ATTRIBUTE_OTHER_JAVASCRIPT': - return checkJSReferencesVariable(styleAttribute, propsVariableName, stylePropPath) - case 'ATTRIBUTE_NESTED_ARRAY': - return false - case 'ATTRIBUTE_NESTED_OBJECT': - return styleAttribute.content.some((attributePart) => { - if (isSpreadAssignment(attributePart)) { - const spreadPart = attributePart.value - if (modifiableAttributeIsAttributeOtherJavaScript(spreadPart)) { - return checkJSReferencesVariable(spreadPart, propsVariableName, stylePropPath) - } - if ( - isJSPropertyAccessForProperty(spreadPart, 'style') && - isJSIdentifierForName(spreadPart.onValue, 'props') - ) { - return true - } +function propsStyleIsSpreadInto(propsParams: Array, attributes: JSXAttributes): boolean { + for (const propsParam of propsParams) { + const boundParam = propsParam.boundParam + switch (boundParam.type) { + case 'REGULAR_PARAM': { + const propsVariableName = boundParam.paramName + const stylePropPath = `${propsVariableName}.style` + const styleProp = getJSXAttributesAtPath(attributes, PP.create('style')) + const styleAttribute = styleProp.attribute + switch (styleAttribute.type) { + case 'ATTRIBUTE_NOT_FOUND': + return false + case 'ATTRIBUTE_VALUE': + return false + case 'JSX_MAP_EXPRESSION': + if (isJSExpressionOtherJavaScript(styleAttribute.valueToMap)) { + return checkJSReferencesVariable( + styleAttribute.valueToMap, + propsVariableName, + stylePropPath, + ) + } + if (isJSExpressionOtherJavaScript(styleAttribute.mapFunction)) { + return checkJSReferencesVariable( + styleAttribute.mapFunction, + propsVariableName, + stylePropPath, + ) } return false - }) - case 'ATTRIBUTE_FUNCTION_CALL': - return false - case 'PART_OF_ATTRIBUTE_VALUE': - return false - case 'JS_IDENTIFIER': - return true - case 'JS_PROPERTY_ACCESS': - case 'JS_ELEMENT_ACCESS': - case 'JSX_ELEMENT': - return false - default: - const _exhaustiveCheck: never = styleAttribute - throw new Error(`Unhandled attribute type: ${JSON.stringify(styleAttribute)}`) - } - } - case 'DESTRUCTURED_OBJECT': { - return boundParam.parts.some((part) => { - const partBoundParam = part.param.boundParam - if (partBoundParam.type === 'REGULAR_PARAM') { - // This handles the aliasing that may be applied to the destructured field. - const propertyToCheck = part.propertyName ?? partBoundParam.paramName - if (propertyToCheck === 'style') { - // This is the aliased name or if there's no alias the field name. - const propertyToLookFor = partBoundParam.paramName - - const styleProp = getJSXAttributesAtPath(attributes, PP.create('style')) - const styleAttribute = styleProp.attribute - switch (styleAttribute.type) { - case 'ATTRIBUTE_NOT_FOUND': - return false - case 'ATTRIBUTE_VALUE': - return false - case 'JSX_MAP_EXPRESSION': - if (isJSExpressionOtherJavaScript(styleAttribute.valueToMap)) { - return checkJSReferencesVariable( - styleAttribute.valueToMap, - propertyToLookFor, - propertyToLookFor, - ) + case 'ATTRIBUTE_OTHER_JAVASCRIPT': + return checkJSReferencesVariable(styleAttribute, propsVariableName, stylePropPath) + case 'ATTRIBUTE_NESTED_ARRAY': + return false + case 'ATTRIBUTE_NESTED_OBJECT': + return styleAttribute.content.some((attributePart) => { + if (isSpreadAssignment(attributePart)) { + const spreadPart = attributePart.value + if (modifiableAttributeIsAttributeOtherJavaScript(spreadPart)) { + return checkJSReferencesVariable(spreadPart, propsVariableName, stylePropPath) + } + if ( + isJSPropertyAccessForProperty(spreadPart, 'style') && + isJSIdentifierForName(spreadPart.onValue, 'props') + ) { + return true } - if (isJSExpressionOtherJavaScript(styleAttribute.mapFunction)) { + } + return false + }) + case 'ATTRIBUTE_FUNCTION_CALL': + return false + case 'PART_OF_ATTRIBUTE_VALUE': + return false + case 'JS_IDENTIFIER': + return true + case 'JS_PROPERTY_ACCESS': + case 'JS_ELEMENT_ACCESS': + case 'JSX_ELEMENT': + return false + default: + const _exhaustiveCheck: never = styleAttribute + throw new Error(`Unhandled attribute type: ${JSON.stringify(styleAttribute)}`) + } + } + case 'DESTRUCTURED_OBJECT': { + return boundParam.parts.some((part) => { + const partBoundParam = part.param.boundParam + if (partBoundParam.type === 'REGULAR_PARAM') { + // This handles the aliasing that may be applied to the destructured field. + const propertyToCheck = part.propertyName ?? partBoundParam.paramName + if (propertyToCheck === 'style') { + // This is the aliased name or if there's no alias the field name. + const propertyToLookFor = partBoundParam.paramName + + const styleProp = getJSXAttributesAtPath(attributes, PP.create('style')) + const styleAttribute = styleProp.attribute + switch (styleAttribute.type) { + case 'ATTRIBUTE_NOT_FOUND': + return false + case 'ATTRIBUTE_VALUE': + return false + case 'JSX_MAP_EXPRESSION': + if (isJSExpressionOtherJavaScript(styleAttribute.valueToMap)) { + return checkJSReferencesVariable( + styleAttribute.valueToMap, + propertyToLookFor, + propertyToLookFor, + ) + } + if (isJSExpressionOtherJavaScript(styleAttribute.mapFunction)) { + return checkJSReferencesVariable( + styleAttribute.mapFunction, + propertyToLookFor, + propertyToLookFor, + ) + } + return false + case 'ATTRIBUTE_OTHER_JAVASCRIPT': return checkJSReferencesVariable( - styleAttribute.mapFunction, + styleAttribute, propertyToLookFor, propertyToLookFor, ) - } - return false - case 'ATTRIBUTE_OTHER_JAVASCRIPT': - return checkJSReferencesVariable( - styleAttribute, - propertyToLookFor, - propertyToLookFor, - ) - case 'ATTRIBUTE_NESTED_ARRAY': - return false - case 'ATTRIBUTE_NESTED_OBJECT': - return styleAttribute.content.some((attributePart) => { - if (isSpreadAssignment(attributePart)) { - const spreadPart = attributePart.value - if (modifiableAttributeIsAttributeOtherJavaScript(spreadPart)) { - return checkJSReferencesVariable( - spreadPart, - propertyToLookFor, - propertyToLookFor, - ) - } - if (spreadPart.type === 'JS_IDENTIFIER' && spreadPart.name === 'style') { - return true + case 'ATTRIBUTE_NESTED_ARRAY': + return false + case 'ATTRIBUTE_NESTED_OBJECT': + return styleAttribute.content.some((attributePart) => { + if (isSpreadAssignment(attributePart)) { + const spreadPart = attributePart.value + if (modifiableAttributeIsAttributeOtherJavaScript(spreadPart)) { + return checkJSReferencesVariable( + spreadPart, + propertyToLookFor, + propertyToLookFor, + ) + } + if (spreadPart.type === 'JS_IDENTIFIER' && spreadPart.name === 'style') { + return true + } } - } + return false + }) + case 'ATTRIBUTE_FUNCTION_CALL': return false - }) - case 'ATTRIBUTE_FUNCTION_CALL': - return false - case 'PART_OF_ATTRIBUTE_VALUE': - return false - case 'JS_IDENTIFIER': - return true - case 'JS_PROPERTY_ACCESS': - return ( - isJSPropertyAccessForProperty(styleAttribute, propertyToLookFor) && - isJSIdentifierForName(styleAttribute.onValue, 'style') - ) - case 'JS_ELEMENT_ACCESS': - case 'JSX_ELEMENT': - return false - default: - const _exhaustiveCheck: never = styleAttribute - throw new Error(`Unhandled attribute type: ${JSON.stringify(styleAttribute)}`) + case 'PART_OF_ATTRIBUTE_VALUE': + return false + case 'JS_IDENTIFIER': + return true + case 'JS_PROPERTY_ACCESS': + return ( + isJSPropertyAccessForProperty(styleAttribute, propertyToLookFor) && + isJSIdentifierForName(styleAttribute.onValue, 'style') + ) + case 'JS_ELEMENT_ACCESS': + case 'JSX_ELEMENT': + return false + default: + const _exhaustiveCheck: never = styleAttribute + throw new Error(`Unhandled attribute type: ${JSON.stringify(styleAttribute)}`) + } } } - } + return false + }) + } + case 'DESTRUCTURED_ARRAY': return false - }) + default: + const _exhaustiveCheck: never = boundParam + throw new Error(`Unhandled param type: ${JSON.stringify(boundParam)}`) } - case 'DESTRUCTURED_ARRAY': - return false - default: - const _exhaustiveCheck: never = boundParam - throw new Error(`Unhandled param type: ${JSON.stringify(boundParam)}`) } + return false } function propertyAccessLookupForPropsStyleProperty( @@ -1115,114 +1125,125 @@ function propertyAccessLookupForPropsStyleProperty( } export function propertyComesFromPropsStyle( - propsParam: Param, + propsParams: Array, result: GetJSXAttributeResult, propName: string, ): boolean { - const attribute = result.attribute - switch (attribute.type) { - case 'ATTRIBUTE_NOT_FOUND': - return false - case 'PART_OF_ATTRIBUTE_VALUE': - return false - default: - return checkExpression(attribute) - } - function checkExpression(expression: JSExpression): boolean { - switch (expression.type) { - case 'ATTRIBUTE_VALUE': + for (const propsParam of propsParams) { + const attribute = result.attribute + switch (attribute.type) { + case 'ATTRIBUTE_NOT_FOUND': return false - case 'JSX_MAP_EXPRESSION': - return checkExpression(expression.valueToMap) || checkExpression(expression.mapFunction) - case 'ATTRIBUTE_OTHER_JAVASCRIPT': { - const boundParam = propsParam.boundParam - switch (boundParam.type) { - case 'REGULAR_PARAM': - return ( - expression.definedElsewhere.includes(boundParam.paramName) && - expression.javascriptWithUIDs.includes(`${boundParam.paramName}.style.${propName}`) - ) - case 'DESTRUCTURED_OBJECT': - return boundParam.parts.some((part) => { - const partBoundParam = part.param.boundParam - if (partBoundParam.type === 'REGULAR_PARAM') { - // This handles the aliasing that may be applied to the destructured field. - const propertyToCheck = part.propertyName ?? partBoundParam.paramName - if (propertyToCheck === 'style') { - // This is the aliased name or if there's no alias the field name. - const propertyToLookFor = partBoundParam.paramName - return ( - expression.definedElsewhere.includes(propertyToLookFor) && - expression.transpiledJavascript.includes(`${propertyToLookFor}.${propName}`) - ) + case 'PART_OF_ATTRIBUTE_VALUE': + return false + default: + return checkExpression(attribute) + } + function checkExpression(expression: JSExpression): boolean { + switch (expression.type) { + case 'ATTRIBUTE_VALUE': + return false + case 'JSX_MAP_EXPRESSION': + return checkExpression(expression.valueToMap) || checkExpression(expression.mapFunction) + case 'ATTRIBUTE_OTHER_JAVASCRIPT': { + const boundParam = propsParam.boundParam + switch (boundParam.type) { + case 'REGULAR_PARAM': + return ( + expression.definedElsewhere.includes(boundParam.paramName) && + expression.javascriptWithUIDs.includes(`${boundParam.paramName}.style.${propName}`) + ) + case 'DESTRUCTURED_OBJECT': + return boundParam.parts.some((part) => { + const partBoundParam = part.param.boundParam + if (partBoundParam.type === 'REGULAR_PARAM') { + // This handles the aliasing that may be applied to the destructured field. + const propertyToCheck = part.propertyName ?? partBoundParam.paramName + if (propertyToCheck === 'style') { + // This is the aliased name or if there's no alias the field name. + const propertyToLookFor = partBoundParam.paramName + return ( + expression.definedElsewhere.includes(propertyToLookFor) && + expression.transpiledJavascript.includes(`${propertyToLookFor}.${propName}`) + ) + } else { + return false + } } else { return false } - } else { - return false - } - }) - default: - return false + }) + default: + return false + } } + case 'ATTRIBUTE_NESTED_ARRAY': + return false + case 'ATTRIBUTE_NESTED_OBJECT': + return false + case 'ATTRIBUTE_FUNCTION_CALL': + return false + case 'JS_IDENTIFIER': + const boundParam = propsParam.boundParam + switch (boundParam.type) { + case 'REGULAR_PARAM': + return false + case 'DESTRUCTURED_OBJECT': + return boundParam.parts.some((part) => { + const partBoundParam = part.param.boundParam + if (partBoundParam.type === 'REGULAR_PARAM') { + // This handles the aliasing that may be applied to the destructured field. + const propertyToCheck = part.propertyName ?? partBoundParam.paramName + return propertyToCheck === 'style' && expression.name === 'style' + } else { + return false + } + }) + case 'DESTRUCTURED_ARRAY': + return false + default: + return assertNever(boundParam) + } + case 'JS_ELEMENT_ACCESS': + case 'JSX_ELEMENT': + return false + case 'JS_PROPERTY_ACCESS': + return propertyAccessLookupForPropsStyleProperty(propsParam, expression, propName) + default: + const _exhaustiveCheck: never = expression + throw new Error(`Unhandled attribute type: ${JSON.stringify(expression)}`) } - case 'ATTRIBUTE_NESTED_ARRAY': - return false - case 'ATTRIBUTE_NESTED_OBJECT': - return false - case 'ATTRIBUTE_FUNCTION_CALL': - return false - case 'JS_IDENTIFIER': - const boundParam = propsParam.boundParam - switch (boundParam.type) { - case 'REGULAR_PARAM': - return false - case 'DESTRUCTURED_OBJECT': - return boundParam.parts.some((part) => { - const partBoundParam = part.param.boundParam - if (partBoundParam.type === 'REGULAR_PARAM') { - // This handles the aliasing that may be applied to the destructured field. - const propertyToCheck = part.propertyName ?? partBoundParam.paramName - return propertyToCheck === 'style' && expression.name === 'style' - } else { - return false - } - }) - case 'DESTRUCTURED_ARRAY': - return false - default: - return assertNever(boundParam) - } - case 'JS_ELEMENT_ACCESS': - case 'JSX_ELEMENT': - return false - case 'JS_PROPERTY_ACCESS': - return propertyAccessLookupForPropsStyleProperty(propsParam, expression, propName) - default: - const _exhaustiveCheck: never = expression - throw new Error(`Unhandled attribute type: ${JSON.stringify(expression)}`) } } + return false } function propertyAccessLookupForPropsProperty( - propsParam: Param, + propsParams: Array, toCheck: JSPropertyAccess, propName: string, ): boolean { - // TODO make this not be special cased to the style prop! - - // This checks for `something1.something2.something3`: - if (toCheck.onValue.type === 'JS_IDENTIFIER' && propsParam.boundParam.type === 'REGULAR_PARAM') { - // Constrain the above check to `.style.` - if (toCheck.onValue.name === propsParam.boundParam.paramName && toCheck.property === propName) { - return true + for (const propsParam of propsParams) { + // TODO make this not be special cased to the style prop! + + // This checks for `something1.something2.something3`: + if ( + toCheck.onValue.type === 'JS_IDENTIFIER' && + propsParam.boundParam.type === 'REGULAR_PARAM' + ) { + // Constrain the above check to `.style.` + if ( + toCheck.onValue.name === propsParam.boundParam.paramName && + toCheck.property === propName + ) { + return true + } } - } - // Work our way back up the calls if there's a really deep chain. - if (toCheck.onValue.type === 'JS_PROPERTY_ACCESS') { - return propertyAccessLookupForPropsStyleProperty(propsParam, toCheck.onValue, propName) + // Work our way back up the calls if there's a really deep chain. + if (toCheck.onValue.type === 'JS_PROPERTY_ACCESS') { + return propertyAccessLookupForPropsStyleProperty(propsParam, toCheck.onValue, propName) + } } return false @@ -1230,93 +1251,96 @@ function propertyAccessLookupForPropsProperty( export function identifierUsesProperty( element: JSIdentifier, - propsParam: Param, + propsParams: Array, property: string, ): boolean { - switch (propsParam.boundParam.type) { - case 'REGULAR_PARAM': - return element.name === propsParam.boundParam.paramName - case 'DESTRUCTURED_ARRAY': - return propsParam.boundParam.parts.some((part) => { - switch (part.type) { - case 'PARAM': - return identifierUsesProperty(element, part, property) - case 'OMITTED_PARAM': + for (const propsParam of propsParams) { + switch (propsParam.boundParam.type) { + case 'REGULAR_PARAM': + return element.name === propsParam.boundParam.paramName + case 'DESTRUCTURED_ARRAY': + return propsParam.boundParam.parts.some((part) => { + switch (part.type) { + case 'PARAM': + return identifierUsesProperty(element, [part], property) + case 'OMITTED_PARAM': + return false + default: + return assertNever(part) + } + }) + case 'DESTRUCTURED_OBJECT': + return propsParam.boundParam.parts.some((part) => { + const partBoundParam = part.param.boundParam + if (partBoundParam.type === 'REGULAR_PARAM') { + // This handles the aliasing that may be applied to the destructured field. + const propertyToCheck = part.propertyName ?? partBoundParam.paramName + return propertyToCheck === property + } else { return false - default: - return assertNever(part) - } - }) - case 'DESTRUCTURED_OBJECT': - return propsParam.boundParam.parts.some((part) => { - const partBoundParam = part.param.boundParam - if (partBoundParam.type === 'REGULAR_PARAM') { - // This handles the aliasing that may be applied to the destructured field. - const propertyToCheck = part.propertyName ?? partBoundParam.paramName - return propertyToCheck === property - } else { - return false - } - }) - default: - return assertNever(propsParam.boundParam) + } + }) + default: + return assertNever(propsParam.boundParam) + } } + return false } export function elementUsesProperty( element: JSXElementChild, - propsParam: Param, + propsParams: Array, property: string, ): boolean { switch (element.type) { case 'JSX_ELEMENT': const fromChildren = element.children.some((child) => { - return elementUsesProperty(child, propsParam, property) + return elementUsesProperty(child, propsParams, property) }) - const fromAttributes = attributesUseProperty(element.props, propsParam, property) + const fromAttributes = attributesUseProperty(element.props, propsParams, property) return fromChildren || fromAttributes case 'JSX_MAP_EXPRESSION': return ( - attributeUsesProperty(element.valueToMap, propsParam, property) || - attributeUsesProperty(element.mapFunction, propsParam, property) + attributeUsesProperty(element.valueToMap, propsParams, property) || + attributeUsesProperty(element.mapFunction, propsParams, property) ) case 'ATTRIBUTE_OTHER_JAVASCRIPT': - return codeUsesProperty(element.originalJavascript, propsParam, property) + return codeUsesProperty(element.originalJavascript, propsParams, property) case 'JSX_TEXT_BLOCK': return false case 'JSX_FRAGMENT': return element.children.some((child) => { - return elementUsesProperty(child, propsParam, property) + return elementUsesProperty(child, propsParams, property) }) case 'JSX_CONDITIONAL_EXPRESSION': return ( - attributeUsesProperty(element.condition, propsParam, property) || - elementUsesProperty(element.whenTrue, propsParam, property) || - elementUsesProperty(element.whenFalse, propsParam, property) + attributeUsesProperty(element.condition, propsParams, property) || + elementUsesProperty(element.whenTrue, propsParams, property) || + elementUsesProperty(element.whenFalse, propsParams, property) ) case 'ATTRIBUTE_VALUE': return false case 'ATTRIBUTE_NESTED_ARRAY': return element.content.some((child) => { - return elementUsesProperty(child.value, propsParam, property) + return elementUsesProperty(child.value, propsParams, property) }) case 'ATTRIBUTE_NESTED_OBJECT': return element.content.some((child) => { - return elementUsesProperty(child.value, propsParam, property) + return elementUsesProperty(child.value, propsParams, property) }) case 'ATTRIBUTE_FUNCTION_CALL': return element.parameters.some((param) => { - return elementUsesProperty(param, propsParam, property) + return elementUsesProperty(param, propsParams, property) }) case 'JS_PROPERTY_ACCESS': - return propertyAccessLookupForPropsProperty(propsParam, element, property) + return propertyAccessLookupForPropsProperty(propsParams, element, property) case 'JS_ELEMENT_ACCESS': return ( - elementUsesProperty(element.onValue, propsParam, property) || - elementUsesProperty(element.element, propsParam, property) // TODO I think this is wrong, as it checks if the element part references the prop, but not that the entire expression itself actually points at a prop + elementUsesProperty(element.onValue, propsParams, property) || + elementUsesProperty(element.element, propsParams, property) // TODO I think this is wrong, as it checks if the element part references the prop, but not that the entire expression itself actually points at a prop ) case 'JS_IDENTIFIER': - return identifierUsesProperty(element, propsParam, property) + return identifierUsesProperty(element, propsParams, property) default: const _exhaustiveCheck: never = element throw new Error(`Unhandled element type: ${JSON.stringify(element)}`) @@ -1325,31 +1349,31 @@ export function elementUsesProperty( export function attributesUseProperty( attributes: JSXAttributes, - propsParam: Param, + propsParams: Array, property: string, ): boolean { - return attributes.some((part) => attributePartUsesProperty(part, propsParam, property)) + return attributes.some((part) => attributePartUsesProperty(part, propsParams, property)) } export function arrayElementUsesProperty( arrayElement: JSXArrayElement, - propsParam: Param, + propsParams: Array, property: string, ): boolean { - return attributeUsesProperty(arrayElement.value, propsParam, property) + return attributeUsesProperty(arrayElement.value, propsParams, property) } export function jsxPropertyUsesProperty( jsxProperty: JSXProperty, - propsParam: Param, + propsParams: Array, property: string, ): boolean { - return attributeUsesProperty(jsxProperty.value, propsParam, property) + return attributeUsesProperty(jsxProperty.value, propsParams, property) } export function attributeUsesProperty( attribute: JSExpression, - propsParam: Param, + propsParams: Array, property: string, ): boolean { switch (attribute.type) { @@ -1357,37 +1381,37 @@ export function attributeUsesProperty( return false case 'JSX_ELEMENT': const fromChildren = attribute.children.some((child) => { - return elementUsesProperty(child, propsParam, property) + return elementUsesProperty(child, propsParams, property) }) - const fromAttributes = attributesUseProperty(attribute.props, propsParam, property) + const fromAttributes = attributesUseProperty(attribute.props, propsParams, property) return fromChildren || fromAttributes case 'JSX_MAP_EXPRESSION': return ( - attributeUsesProperty(attribute.valueToMap, propsParam, property) || - attributeUsesProperty(attribute.mapFunction, propsParam, property) + attributeUsesProperty(attribute.valueToMap, propsParams, property) || + attributeUsesProperty(attribute.mapFunction, propsParams, property) ) case 'ATTRIBUTE_OTHER_JAVASCRIPT': - return codeUsesProperty(attribute.javascriptWithUIDs, propsParam, property) + return codeUsesProperty(attribute.javascriptWithUIDs, propsParams, property) case 'ATTRIBUTE_NESTED_ARRAY': return attribute.content.some((elem) => { - return arrayElementUsesProperty(elem, propsParam, property) + return arrayElementUsesProperty(elem, propsParams, property) }) case 'ATTRIBUTE_NESTED_OBJECT': return attribute.content.some((elem) => { - return jsxPropertyUsesProperty(elem, propsParam, property) + return jsxPropertyUsesProperty(elem, propsParams, property) }) case 'ATTRIBUTE_FUNCTION_CALL': return attribute.parameters.some((parameter) => { - return attributeUsesProperty(parameter, propsParam, property) + return attributeUsesProperty(parameter, propsParams, property) }) case 'JS_PROPERTY_ACCESS': - return propertyAccessLookupForPropsProperty(propsParam, attribute, property) + return propertyAccessLookupForPropsProperty(propsParams, attribute, property) case 'JS_IDENTIFIER': - return identifierUsesProperty(attribute, propsParam, property) + return identifierUsesProperty(attribute, propsParams, property) case 'JS_ELEMENT_ACCESS': return ( - elementUsesProperty(attribute.onValue, propsParam, property) || - elementUsesProperty(attribute.element, propsParam, property) + elementUsesProperty(attribute.onValue, propsParams, property) || + elementUsesProperty(attribute.element, propsParams, property) ) default: const _exhaustiveCheck: never = attribute @@ -1397,14 +1421,14 @@ export function attributeUsesProperty( export function attributePartUsesProperty( attributesPart: JSXAttributesPart, - propsParam: Param, + propsParams: Array, property: string, ): boolean { switch (attributesPart.type) { case 'JSX_ATTRIBUTES_ENTRY': - return attributeUsesProperty(attributesPart.value, propsParam, property) + return attributeUsesProperty(attributesPart.value, propsParams, property) case 'JSX_ATTRIBUTES_SPREAD': - return attributeUsesProperty(attributesPart.spreadValue, propsParam, property) + return attributeUsesProperty(attributesPart.spreadValue, propsParams, property) default: const _exhaustiveCheck: never = attributesPart throw new Error(`Unhandled attribute part: ${JSON.stringify(attributesPart)}`) diff --git a/editor/src/core/shared/element-template.ts b/editor/src/core/shared/element-template.ts index c52695b3d1bd..d41793bfbc15 100644 --- a/editor/src/core/shared/element-template.ts +++ b/editor/src/core/shared/element-template.ts @@ -1984,7 +1984,7 @@ export function utopiaJSXComponent( declarationSyntax: FunctionDeclarationSyntax, blockOrExpression: BlockOrExpression, functionWrapping: Array, - param: Param | null, + params: Array | null, propsUsed: Array, rootElement: JSXElementChild, jsBlock: ArbitraryJSBlock | null, @@ -1998,7 +1998,7 @@ export function utopiaJSXComponent( declarationSyntax: declarationSyntax, blockOrExpression: blockOrExpression, functionWrapping: functionWrapping, - param: param, + params: params, propsUsed: propsUsed, rootElement: rootElement, arbitraryJSBlock: jsBlock, @@ -2132,7 +2132,7 @@ export function functionParam(dotDotDotToken: boolean, boundParam: BoundParam): } } -export const defaultPropsParam: Param = functionParam(false, regularParam('props', null)) +export const defaultPropsParam: Array = [functionParam(false, regularParam('props', null))] export function propNamesForParam(param: Param): Array { const { boundParam } = param @@ -2339,8 +2339,8 @@ export function clearTopLevelElementUniqueIDs(element: TopLevelElement): TopLeve updatedComponent.arbitraryJSBlock, ) } - if (updatedComponent.param != null) { - updatedComponent.param = clearParamUniqueIDs(updatedComponent.param) + if (updatedComponent.params != null) { + updatedComponent.params = updatedComponent.params.map(clearParamUniqueIDs) } return updatedComponent case 'ARBITRARY_JS_BLOCK': @@ -2369,8 +2369,8 @@ export function clearTopLevelElementSourceMaps(element: TopLevelElement): TopLev updatedComponent.arbitraryJSBlock, ) } - if (updatedComponent.param != null) { - updatedComponent.param = clearParamSourceMaps(updatedComponent.param) + if (updatedComponent.params != null) { + updatedComponent.params = updatedComponent.params.map(clearParamSourceMaps) } return updatedComponent case 'ARBITRARY_JS_BLOCK': diff --git a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-arbitrary-elements.spec.tsx.snap b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-arbitrary-elements.spec.tsx.snap index 6c9a32b345b4..224499341b8f 100644 --- a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-arbitrary-elements.spec.tsx.snap +++ b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-arbitrary-elements.spec.tsx.snap @@ -606,15 +606,17 @@ export var storyboard = ( "functionWrapping": Array [], "isFunction": true, "name": "App", - "param": Object { - "boundParam": Object { - "defaultExpression": null, - "paramName": "props", - "type": "REGULAR_PARAM", + "params": Array [ + Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "props", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", }, - "dotDotDotToken": false, - "type": "PARAM", - }, + ], "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], @@ -991,7 +993,7 @@ export var storyboard = ( "functionWrapping": Array [], "isFunction": false, "name": "storyboard", - "param": null, + "params": null, "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], diff --git a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-dot-notation.spec.tsx.snap b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-dot-notation.spec.tsx.snap index 02d5c59eea75..262bb4fe1577 100644 --- a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-dot-notation.spec.tsx.snap +++ b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer-dot-notation.spec.tsx.snap @@ -51,15 +51,17 @@ Array [ "functionWrapping": Array [], "isFunction": true, "name": "App", - "param": Object { - "boundParam": Object { - "defaultExpression": null, - "paramName": "props", - "type": "REGULAR_PARAM", + "params": Array [ + Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "props", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", }, - "dotDotDotToken": false, - "type": "PARAM", - }, + ], "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], diff --git a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer.spec.ts.snap b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer.spec.ts.snap index 24d0718487bd..2c4966f9709e 100644 --- a/editor/src/core/workers/parser-printer/__snapshots__/parser-printer.spec.ts.snap +++ b/editor/src/core/workers/parser-printer/__snapshots__/parser-printer.spec.ts.snap @@ -569,15 +569,17 @@ export var whatever = (props) => { "functionWrapping": Array [], "isFunction": true, "name": "whatever", - "param": Object { - "boundParam": Object { - "defaultExpression": null, - "paramName": "props", - "type": "REGULAR_PARAM", + "params": Array [ + Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "props", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", }, - "dotDotDotToken": false, - "type": "PARAM", - }, + ], "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], @@ -956,15 +958,17 @@ Object { "functionWrapping": Array [], "isFunction": true, "name": "a", - "param": Object { - "boundParam": Object { - "defaultExpression": null, - "paramName": "n", - "type": "REGULAR_PARAM", + "params": Array [ + Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "n", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", }, - "dotDotDotToken": false, - "type": "PARAM", - }, + ], "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], @@ -1113,15 +1117,17 @@ const b = (n) => n > 0 ?
n
: a(10) "functionWrapping": Array [], "isFunction": true, "name": "whatever", - "param": Object { - "boundParam": Object { - "defaultExpression": null, - "paramName": "props", - "type": "REGULAR_PARAM", + "params": Array [ + Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "props", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", }, - "dotDotDotToken": false, - "type": "PARAM", - }, + ], "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], @@ -1172,15 +1178,17 @@ const b = (n) => n > 0 ?
n
: a(10) "functionWrapping": Array [], "isFunction": true, "name": "b", - "param": Object { - "boundParam": Object { - "defaultExpression": null, - "paramName": "n", - "type": "REGULAR_PARAM", + "params": Array [ + Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "n", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", }, - "dotDotDotToken": false, - "type": "PARAM", - }, + ], "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], @@ -1663,15 +1671,17 @@ export var App = (props) => "functionWrapping": Array [], "isFunction": true, "name": "App", - "param": Object { - "boundParam": Object { - "defaultExpression": null, - "paramName": "props", - "type": "REGULAR_PARAM", + "params": Array [ + Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "props", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", }, - "dotDotDotToken": false, - "type": "PARAM", - }, + ], "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], diff --git a/editor/src/core/workers/parser-printer/parser-printer-function-wrapped.spec.tsx b/editor/src/core/workers/parser-printer/parser-printer-function-wrapped.spec.tsx index 52ce6f129b36..42c4a76bbe76 100644 --- a/editor/src/core/workers/parser-printer/parser-printer-function-wrapped.spec.tsx +++ b/editor/src/core/workers/parser-printer/parser-printer-function-wrapped.spec.tsx @@ -26,10 +26,16 @@ function getLoneMainTopLevelElement(code: string): UtopiaJSXComponent | Arbitrar case 1: return mainTopLevelElements[0] default: - throw new Error(`More than one main top level element found: ${topLevelElements}`) + throw new Error( + `More than one main top level element found: ${JSON.stringify( + topLevelElements, + null, + 2, + )}`, + ) } } else { - throw new Error(`Not a successful parse: ${parseResult}`) + throw new Error(`Not a successful parse: ${JSON.stringify(parseResult, null, 2)}`) } } @@ -68,6 +74,11 @@ export const Wrapped = React.memo(() => { return
})` +const forwardRefComponentCode = `import {forwardRef} from "react"; +export const Wrapped = forwardRef(({left, width}, ref) => { + return
+})` + describe('parseCode', () => { it('simple function component wrapped in a React.memo', () => { const element = getLoneMainTopLevelElement(simpleReactMemoComponentCode) @@ -106,7 +117,7 @@ describe('parseCode', () => { ], "isFunction": true, "name": "Wrapped", - "param": null, + "params": Array [], "propsUsed": Array [], "returnStatementComments": Object { "leadingComments": Array [], @@ -147,6 +158,201 @@ describe('parseCode', () => { } `) }) + + it('handles a more complicated forwardRef case', () => { + const element = getLoneMainTopLevelElement(forwardRefComponentCode) + expect(element.type).toEqual('UTOPIA_JSX_COMPONENT') + expect(element).toMatchInlineSnapshot(` + Object { + "arbitraryJSBlock": null, + "blockOrExpression": "block", + "declarationSyntax": "const", + "functionWrapping": Array [ + Object { + "functionExpression": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "name": "forwardRef", + "sourceMap": null, + "type": "JS_IDENTIFIER", + "uid": "", + }, + "type": "SIMPLE_FUNCTION_WRAP", + }, + ], + "isFunction": true, + "name": "Wrapped", + "params": Array [ + Object { + "boundParam": Object { + "parts": Array [ + Object { + "defaultExpression": null, + "param": Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "left", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", + }, + "propertyName": undefined, + }, + Object { + "defaultExpression": null, + "param": Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "width", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", + }, + "propertyName": undefined, + }, + ], + "type": "DESTRUCTURED_OBJECT", + }, + "dotDotDotToken": false, + "type": "PARAM", + }, + Object { + "boundParam": Object { + "defaultExpression": null, + "paramName": "ref", + "type": "REGULAR_PARAM", + }, + "dotDotDotToken": false, + "type": "PARAM", + }, + ], + "propsUsed": Array [ + "left", + "width", + ], + "returnStatementComments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "rootElement": Object { + "children": Array [], + "name": Object { + "baseVariable": "div", + "propertyPath": Object { + "propertyElements": Array [], + }, + }, + "props": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "style", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "content": Array [ + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "left", + "keyComments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "PROPERTY_ASSIGNMENT", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "name": "left", + "sourceMap": null, + "type": "JS_IDENTIFIER", + "uid": "", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "width", + "keyComments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "PROPERTY_ASSIGNMENT", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "name": "width", + "sourceMap": null, + "type": "JS_IDENTIFIER", + "uid": "", + }, + }, + ], + "type": "ATTRIBUTE_NESTED_OBJECT", + "uid": "", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "ref", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "name": "ref", + "sourceMap": null, + "type": "JS_IDENTIFIER", + "uid": "", + }, + }, + Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "key": "data-uid", + "type": "JSX_ATTRIBUTES_ENTRY", + "value": Object { + "comments": Object { + "leadingComments": Array [], + "trailingComments": Array [], + }, + "type": "ATTRIBUTE_VALUE", + "uid": "", + "value": "wrapped", + }, + }, + ], + "type": "JSX_ELEMENT", + "uid": "", + }, + "type": "UTOPIA_JSX_COMPONENT", + "usedInReactDOMRender": false, + } + `) + }) }) describe('printCode', () => { @@ -160,4 +366,22 @@ describe('printCode', () => { " `) }) + it('forwardRef wrapped component', () => { + const actualResult = testParsePrintParse(forwardRefComponentCode) + expect(actualResult).toMatchInlineSnapshot(` + "import { forwardRef } from 'react' + export const Wrapped = forwardRef( + ({ left, width }, ref) => { + return ( +
+ ) + }, + ) + " + `) + }) }) diff --git a/editor/src/core/workers/parser-printer/parser-printer-functional-components.spec.ts b/editor/src/core/workers/parser-printer/parser-printer-functional-components.spec.ts index cfc9a8836b59..074cfdc2a759 100644 --- a/editor/src/core/workers/parser-printer/parser-printer-functional-components.spec.ts +++ b/editor/src/core/workers/parser-printer/parser-printer-functional-components.spec.ts @@ -253,7 +253,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], [], view, null, @@ -292,7 +292,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], [], view, null, @@ -335,7 +335,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], ['prop'], view, null, @@ -393,7 +393,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], ['prop'], view, null, @@ -437,7 +437,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], ['prop'], view, null, @@ -495,7 +495,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], ['prop'], view, null, @@ -540,7 +540,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], ['prop'], view, null, @@ -580,7 +580,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], [], view, null, @@ -635,7 +635,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], [], view, null, @@ -679,7 +679,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - propsParam, + [propsParam], [], view, null, @@ -736,7 +736,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - outerDestructuredObject, + [outerDestructuredObject], ['arrayPart'], view, null, @@ -825,7 +825,7 @@ describe('Parsing a function component with props', () => { 'var', 'block', [], - outerDestructuredObject, + [outerDestructuredObject], ['arrayPart'], view, null, diff --git a/editor/src/core/workers/parser-printer/parser-printer-pragma.spec.ts b/editor/src/core/workers/parser-printer/parser-printer-pragma.spec.ts index e3e5a5407f49..5008086ee1e4 100644 --- a/editor/src/core/workers/parser-printer/parser-printer-pragma.spec.ts +++ b/editor/src/core/workers/parser-printer/parser-printer-pragma.spec.ts @@ -1,3 +1,4 @@ +/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "testParseThenPrint"] }] */ import { applyPrettier } from 'utopia-vscode-common' import { testParseCode, testParseThenPrint } from './parser-printer.test-utils' import { BakedInStoryboardUID } from '../../model/scene-utils' diff --git a/editor/src/core/workers/parser-printer/parser-printer-uids.spec.tsx b/editor/src/core/workers/parser-printer/parser-printer-uids.spec.tsx index e1835f8b11b9..3a8ab5a0aeaf 100644 --- a/editor/src/core/workers/parser-printer/parser-printer-uids.spec.tsx +++ b/editor/src/core/workers/parser-printer/parser-printer-uids.spec.tsx @@ -411,7 +411,7 @@ export var app = (props) => { tle.declarationSyntax, tle.blockOrExpression, tle.functionWrapping, - tle.param, + tle.params, tle.propsUsed, updatedRootElement, tle.arbitraryJSBlock, diff --git a/editor/src/core/workers/parser-printer/parser-printer.spec.ts b/editor/src/core/workers/parser-printer/parser-printer.spec.ts index 97b5d7a120b7..f8d14510526d 100644 --- a/editor/src/core/workers/parser-printer/parser-printer.spec.ts +++ b/editor/src/core/workers/parser-printer/parser-printer.spec.ts @@ -232,7 +232,7 @@ export var whatever = () => 'var', 'expression', [], - null, + [], [], view, null, @@ -396,7 +396,7 @@ export function whatever() { 'function', 'block', [], - null, + [], [], view, null, @@ -560,7 +560,7 @@ export default function whatever() { 'function', 'block', [], - null, + [], [], view, null, @@ -3616,7 +3616,7 @@ export var whatever = () => 'var', 'expression', [], - null, + [], [], view, null, @@ -3748,7 +3748,7 @@ export var App = (props) => 'var', 'parenthesized-expression', [], - null, + [], [], view, null, @@ -4003,7 +4003,7 @@ var spacing = 20` 'var', 'parenthesized-expression', [], - null, + [], [], view, null, diff --git a/editor/src/core/workers/parser-printer/parser-printer.ts b/editor/src/core/workers/parser-printer/parser-printer.ts index 011e1a4613c6..ea595dae0c82 100644 --- a/editor/src/core/workers/parser-printer/parser-printer.ts +++ b/editor/src/core/workers/parser-printer/parser-printer.ts @@ -769,7 +769,7 @@ function printUtopiaJSXComponent( ? TS.NodeFlags.None : nodeFlagsForVarLetOrConst(element.declarationSyntax) if (element.isFunction) { - const functionParams = maybeToArray(element.param).map((p) => + const functionParams = (element.params ?? []).map((p) => printParam(p, imports, printOptions.stripUIDs), ) @@ -1631,12 +1631,13 @@ export function parseCode( 'No contents', ) let isFunction: boolean = false - let parsedFunctionParam: Either | null> = right(null) + let parsedFunctionParams: Either> | null> = + right(null) let propsUsed: Array = [] if (isPossibleCanvasContentsFunction(canvasContents)) { const { parameters, body } = canvasContents isFunction = true - const parsedFunctionParams = parseParams( + const notNullParsedFunctionParams = parseParams( parameters, sourceFile, sourceText, @@ -1647,26 +1648,14 @@ export function parseCode( alreadyExistingUIDs_MUTABLE, applySteganography, ) - parsedFunctionParam = flatMapEither((parsedParams) => { - const paramsValue = parsedParams.value - if (paramsValue.length === 0) { - return right(null) - } else if (paramsValue.length === 1) { - // Note: We're explicitly ignoring the `propsUsed` value as - // that should be handled by the call to `propNamesForParam` below. - return right( - withParserMetadata(paramsValue[0], parsedParams.highlightBounds, [], []), - ) - } else { - return left('Invalid number of params') - } - }, parsedFunctionParams) - forEachRight(parsedFunctionParam, (param) => { - const boundParam = param?.value.boundParam + parsedFunctionParams = notNullParsedFunctionParams + forEachRight(notNullParsedFunctionParams, (params) => { + const firstParam = params.value.at(0) + const boundParam = firstParam?.boundParam const propsObjectName = boundParam != null && isRegularParam(boundParam) ? boundParam.paramName : null - propsUsed = param == null ? [] : propNamesForParam(param.value) + propsUsed = firstParam == null ? [] : propNamesForParam(firstParam) parsedContents = parseOutFunctionContents( sourceFile, sourceText, @@ -1674,13 +1663,13 @@ export function parseCode( foldEither( () => [], (paramsSuccess) => paramsSuccess.value, - parsedFunctionParams, + notNullParsedFunctionParams, ), imports, topLevelNames, propsObjectName, body, - param?.highlightBounds ?? {}, + params?.highlightBounds ?? {}, alreadyExistingUIDs_MUTABLE, applySteganography, ) @@ -1722,7 +1711,7 @@ export function parseCode( } } - if (isLeft(parsedContents) || (isFunction && isLeft(parsedFunctionParam))) { + if (isLeft(parsedContents) || (isFunction && isLeft(parsedFunctionParams))) { pushArbitraryNode(topLevelElement) } else { const contents = parsedContents.value.value @@ -1748,7 +1737,7 @@ export function parseCode( foldEither( (_) => null, (param) => param?.value ?? null, - parsedFunctionParam, + parsedFunctionParams, ), propsUsed, contents.elements[0].value, @@ -1887,7 +1876,7 @@ export function parseCode( topLevelElement.declarationSyntax, topLevelElement.blockOrExpression, topLevelElement.functionWrapping, - topLevelElement.param, + topLevelElement.params, topLevelElement.propsUsed, topLevelElement.rootElement, topLevelElement.arbitraryJSBlock, diff --git a/editor/src/core/workers/ts/ts-worker.spec.ts b/editor/src/core/workers/ts/ts-worker.spec.ts index bef9006c3b66..4156c23ad86d 100644 --- a/editor/src/core/workers/ts/ts-worker.spec.ts +++ b/editor/src/core/workers/ts/ts-worker.spec.ts @@ -154,15 +154,17 @@ const SampleInitTSWorkerMessage: IncomingWorkerMessage = { declarationSyntax: 'var', blockOrExpression: 'block', functionWrapping: [], - param: { - type: 'PARAM', - dotDotDotToken: false, - boundParam: { - type: 'REGULAR_PARAM', - paramName: 'props', - defaultExpression: null, + params: [ + { + type: 'PARAM', + dotDotDotToken: false, + boundParam: { + type: 'REGULAR_PARAM', + paramName: 'props', + defaultExpression: null, + }, }, - }, + ], propsUsed: styleStringInArray, rootElement: { type: 'JSX_ELEMENT', diff --git a/utopia-shared/src/types/element-template.ts b/utopia-shared/src/types/element-template.ts index 01dd7d49e3ff..c0bf6a624de0 100644 --- a/utopia-shared/src/types/element-template.ts +++ b/utopia-shared/src/types/element-template.ts @@ -350,7 +350,7 @@ export interface UtopiaJSXComponent { declarationSyntax: FunctionDeclarationSyntax blockOrExpression: BlockOrExpression functionWrapping: Array - param: Param | null + params: Array | null propsUsed: Array rootElement: JSXElementChild arbitraryJSBlock: ArbitraryJSBlock | null From 80431db50fefd84e036ce9041de56d9e65064c08 Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Thu, 6 Jun 2024 13:14:17 -0400 Subject: [PATCH 034/103] Fixing icons to truly be 12x12 with 10x10 inner (#5853) Fixing the sizing of a ton of icons Fixes #5849 --- .../clickable-aqua-12x12@2x.png | Bin 841 -> 842 bytes .../clickable-black-12x12@2x.png | Bin 834 -> 867 bytes .../clickable-blue-12x12@2x.png | Bin 853 -> 849 bytes .../clickable-darkgray-12x12@2x.png | Bin 831 -> 844 bytes .../clickable-gray-12x12@2x.png | Bin 757 -> 784 bytes .../clickable-green-12x12@2x.png | Bin 874 -> 883 bytes .../clickable-lightaqua-12x12@2x.png | Bin 836 -> 846 bytes .../clickable-lightblue-12x12@2x.png | Bin 828 -> 828 bytes .../clickable-lightgray-12x12@2x.png | Bin 831 -> 835 bytes .../clickable-lightgreen-12x12@2x.png | Bin 858 -> 859 bytes .../clickable-lightpurple-12x12@2x.png | Bin 848 -> 845 bytes .../clickable-purple-12x12@2x.png | Bin 857 -> 865 bytes .../clickable-red-12x12@2x.png | Bin 803 -> 808 bytes .../clickable-white-12x12@2x.png | Bin 720 -> 677 bytes .../component-aqua-12x12@2x.png | Bin 1002 -> 935 bytes .../component-black-12x12@2x.png | Bin 971 -> 930 bytes .../component-blue-12x12@2x.png | Bin 972 -> 943 bytes .../component-darkgray-12x12@2x.png | Bin 949 -> 920 bytes .../component-gray-12x12@2x.png | Bin 879 -> 866 bytes .../component-green-12x12@2x.png | Bin 1030 -> 979 bytes .../component-lightaqua-12x12@2x.png | Bin 956 -> 924 bytes .../component-lightblue-12x12@2x.png | Bin 948 -> 921 bytes .../component-lightgray-12x12@2x.png | Bin 936 -> 920 bytes .../component-lightgreen-12x12@2x.png | Bin 982 -> 955 bytes .../component-lightpurple-12x12@2x.png | Bin 959 -> 933 bytes .../component-open-aqua-12x12@2x.png | Bin 1045 -> 1030 bytes .../component-open-black-12x12@2x.png | Bin 1043 -> 1010 bytes .../component-open-blue-12x12@2x.png | Bin 1059 -> 1037 bytes .../component-open-darkgray-12x12@2x.png | Bin 1018 -> 978 bytes .../component-open-gray-12x12@2x.png | Bin 940 -> 923 bytes .../component-open-green-12x12@2x.png | Bin 1099 -> 1077 bytes .../component-open-lightaqua-12x12@2x.png | Bin 1040 -> 988 bytes .../component-open-lightblue-12x12@2x.png | Bin 1008 -> 997 bytes .../component-open-lightgray-12x12@2x.png | Bin 1019 -> 991 bytes .../component-open-lightgreen-12x12@2x.png | Bin 1056 -> 1033 bytes .../component-open-lightpurple-12x12@2x.png | Bin 1032 -> 1007 bytes .../component-open-purple-12x12@2x.png | Bin 1071 -> 1051 bytes .../component-open-red-12x12@2x.png | Bin 977 -> 954 bytes .../component-open-white-12x12@2x.png | Bin 798 -> 787 bytes .../component-purple-12x12@2x.png | Bin 976 -> 954 bytes .../component-red-12x12@2x.png | Bin 904 -> 887 bytes .../component-scene-aqua-12x12@2x.png | Bin 1142 -> 1094 bytes .../component-scene-black-12x12@2x.png | Bin 1152 -> 1078 bytes .../component-scene-blue-12x12@2x.png | Bin 1145 -> 1101 bytes .../component-scene-darkgray-12x12@2x.png | Bin 1083 -> 1047 bytes .../component-scene-gray-12x12@2x.png | Bin 981 -> 945 bytes .../component-scene-green-12x12@2x.png | Bin 1214 -> 1154 bytes .../component-scene-lightaqua-12x12@2x.png | Bin 1107 -> 1091 bytes .../component-scene-lightblue-12x12@2x.png | Bin 1089 -> 1049 bytes .../component-scene-lightgray-12x12@2x.png | Bin 1068 -> 1049 bytes .../component-scene-lightgreen-12x12@2x.png | Bin 1137 -> 1090 bytes .../component-scene-lightpurple-12x12@2x.png | Bin 1118 -> 1083 bytes .../component-scene-purple-12x12@2x.png | Bin 1157 -> 1114 bytes .../component-scene-red-12x12@2x.png | Bin 1045 -> 1006 bytes .../component-scene-white-12x12@2x.png | Bin 807 -> 811 bytes .../component-white-12x12@2x.png | Bin 749 -> 723 bytes .../navigator-element/div-aqua-12x12@2x.png | Bin 564 -> 570 bytes .../navigator-element/div-black-12x12@2x.png | Bin 566 -> 577 bytes .../navigator-element/div-blue-12x12@2x.png | Bin 567 -> 572 bytes .../div-darkgray-12x12@2x.png | Bin 562 -> 571 bytes .../navigator-element/div-gray-12x12@2x.png | Bin 552 -> 555 bytes .../navigator-element/div-green-12x12@2x.png | Bin 567 -> 576 bytes .../div-lightaqua-12x12@2x.png | Bin 563 -> 569 bytes .../div-lightblue-12x12@2x.png | Bin 563 -> 569 bytes .../div-lightgray-12x12@2x.png | Bin 561 -> 566 bytes .../div-lightgreen-12x12@2x.png | Bin 571 -> 573 bytes .../div-lightpurple-12x12@2x.png | Bin 566 -> 566 bytes .../navigator-element/div-purple-12x12@2x.png | Bin 572 -> 577 bytes .../navigator-element/div-red-12x12@2x.png | Bin 563 -> 563 bytes .../navigator-element/div-white-12x12@2x.png | Bin 536 -> 533 bytes .../navigator-element/form-aqua-12x12@2x.png | Bin 825 -> 790 bytes .../navigator-element/form-black-12x12@2x.png | Bin 829 -> 806 bytes .../navigator-element/form-blue-12x12@2x.png | Bin 824 -> 799 bytes .../form-darkgray-12x12@2x.png | Bin 811 -> 796 bytes .../navigator-element/form-gray-12x12@2x.png | Bin 739 -> 724 bytes .../navigator-element/form-green-12x12@2x.png | Bin 853 -> 818 bytes .../form-lightaqua-12x12@2x.png | Bin 814 -> 806 bytes .../form-lightblue-12x12@2x.png | Bin 800 -> 774 bytes .../form-lightgray-12x12@2x.png | Bin 818 -> 789 bytes .../form-lightgreen-12x12@2x.png | Bin 824 -> 799 bytes .../form-lightpurple-12x12@2x.png | Bin 813 -> 792 bytes .../form-purple-12x12@2x.png | Bin 836 -> 804 bytes .../navigator-element/form-red-12x12@2x.png | Bin 780 -> 765 bytes .../navigator-element/form-white-12x12@2x.png | Bin 689 -> 691 bytes .../navigator-element/image-aqua-12x12@2x.png | Bin 824 -> 842 bytes .../image-black-12x12@2x.png | Bin 825 -> 849 bytes .../navigator-element/image-blue-12x12@2x.png | Bin 813 -> 846 bytes .../image-dark-gray-12x12@2x.png | Bin 803 -> 0 bytes .../image-darkgray-12x12@2x.png | Bin 0 -> 833 bytes .../navigator-element/image-gray-12x12@2x.png | Bin 749 -> 766 bytes .../image-green-12x12@2x.png | Bin 853 -> 873 bytes .../image-light-gray-12x12@2x.png | Bin 801 -> 0 bytes .../image-lightaqua-12x12@2x.png | Bin 831 -> 839 bytes .../image-lightblue-12x12@2x.png | Bin 806 -> 830 bytes .../image-lightgray-12x12@2x.png | Bin 0 -> 826 bytes .../image-lightgreen-12x12@2x.png | Bin 833 -> 848 bytes .../image-lightpurple-12x12@2x.png | Bin 819 -> 843 bytes .../image-purple-12x12@2x.png | Bin 837 -> 868 bytes .../navigator-element/image-red-12x12@2x.png | Bin 777 -> 797 bytes .../image-white-12x12@2x.png | Bin 661 -> 675 bytes .../navigator-element/page-aqua-12x12@2x.png | Bin 624 -> 705 bytes .../navigator-element/page-black-12x12@2x.png | Bin 628 -> 685 bytes .../navigator-element/page-blue-12x12@2x.png | Bin 625 -> 698 bytes .../page-darkgray-12x12@2x.png | Bin 622 -> 684 bytes .../navigator-element/page-gray-12x12@2x.png | Bin 610 -> 656 bytes .../navigator-element/page-green-12x12@2x.png | Bin 636 -> 719 bytes .../page-lightaqua-12x12@2x.png | Bin 632 -> 700 bytes .../page-lightblue-12x12@2x.png | Bin 624 -> 687 bytes .../page-lightgray-12x12@2x.png | Bin 631 -> 692 bytes .../page-lightgreen-12x12@2x.png | Bin 627 -> 705 bytes .../page-lightpurple-12x12@2x.png | Bin 627 -> 694 bytes .../page-purple-12x12@2x.png | Bin 632 -> 703 bytes .../navigator-element/page-red-12x12@2x.png | Bin 615 -> 680 bytes .../navigator-element/page-white-12x12@2x.png | Bin 596 -> 624 bytes .../pure-text-aqua-12x12@2x.png | Bin 659 -> 659 bytes .../pure-text-black-12x12@2x.png | Bin 659 -> 659 bytes .../pure-text-blue-12x12@2x.png | Bin 645 -> 644 bytes .../pure-text-darkgray-12x12@2x.png | Bin 665 -> 665 bytes .../pure-text-gray-12x12@2x.png | Bin 635 -> 636 bytes .../pure-text-green-12x12@2x.png | Bin 658 -> 658 bytes .../pure-text-lightaqua-12x12@2x.png | Bin 632 -> 632 bytes .../pure-text-lightblue-12x12@2x.png | Bin 635 -> 635 bytes .../pure-text-lightgray-12x12@2x.png | Bin 639 -> 640 bytes .../pure-text-lightgreen-12x12@2x.png | Bin 645 -> 645 bytes .../pure-text-lightpurple-12x12@2x.png | Bin 637 -> 638 bytes .../pure-text-purple-12x12@2x.png | Bin 636 -> 636 bytes .../pure-text-red-12x12@2x.png | Bin 626 -> 626 bytes .../pure-text-white-12x12@2x.png | Bin 566 -> 565 bytes .../navigator-element/scene-aqua-12x12@2x.png | Bin 1100 -> 1035 bytes .../scene-black-12x12@2x.png | Bin 1075 -> 1017 bytes .../navigator-element/scene-blue-12x12@2x.png | Bin 1099 -> 1034 bytes .../scene-darkgray-12x12@2x.png | Bin 1049 -> 1003 bytes .../navigator-element/scene-gray-12x12@2x.png | Bin 966 -> 935 bytes .../scene-green-12x12@2x.png | Bin 1164 -> 1082 bytes .../scene-lightaqua-12x12@2x.png | Bin 1071 -> 1028 bytes .../scene-lightblue-12x12@2x.png | Bin 1043 -> 1006 bytes .../scene-lightgray-12x12@2x.png | Bin 1037 -> 1009 bytes .../scene-lightgreen-12x12@2x.png | Bin 1089 -> 1035 bytes .../scene-lightpurple-12x12@2x.png | Bin 1070 -> 1025 bytes .../scene-purple-12x12@2x.png | Bin 1104 -> 1049 bytes .../navigator-element/scene-red-12x12@2x.png | Bin 1010 -> 952 bytes .../scene-white-12x12@2x.png | Bin 801 -> 746 bytes .../solidframe-aqua-12x12@2x.png | Bin 564 -> 570 bytes .../solidframe-black-12x12@2x.png | Bin 566 -> 577 bytes .../solidframe-blue-12x12@2x.png | Bin 567 -> 572 bytes .../solidframe-darkgray-12x12@2x.png | Bin 562 -> 571 bytes .../solidframe-gray-12x12@2x.png | Bin 552 -> 555 bytes .../solidframe-green-12x12@2x.png | Bin 567 -> 576 bytes .../solidframe-lightaqua-12x12@2x.png | Bin 563 -> 569 bytes .../solidframe-lightblue-12x12@2x.png | Bin 563 -> 569 bytes .../solidframe-lightgray-12x12@2x.png | Bin 561 -> 566 bytes .../solidframe-lightgreen-12x12@2x.png | Bin 571 -> 573 bytes .../solidframe-lightpurple-12x12@2x.png | Bin 566 -> 566 bytes .../solidframe-purple-12x12@2x.png | Bin 572 -> 577 bytes .../solidframe-red-12x12@2x.png | Bin 563 -> 563 bytes .../solidframe-white-12x12@2x.png | Bin 536 -> 533 bytes .../navigator-element/star-aqua-12x12@2x.png | Bin 646 -> 1012 bytes .../navigator-element/star-black-12x12@2x.png | Bin 424 -> 1015 bytes .../navigator-element/star-blue-12x12@2x.png | Bin 656 -> 1002 bytes .../star-darkgray-12x12@2x.png | Bin 613 -> 967 bytes .../navigator-element/star-gray-12x12@2x.png | Bin 852 -> 867 bytes .../navigator-element/star-green-12x12@2x.png | Bin 1050 -> 1054 bytes .../star-lightaqua-12x12@2x.png | Bin 620 -> 959 bytes .../star-lightblue-12x12@2x.png | Bin 616 -> 970 bytes .../star-lightgray-12x12@2x.png | Bin 622 -> 968 bytes .../star-lightgreen-12x12@2x.png | Bin 1004 -> 1010 bytes .../star-lightpurple-12x12@2x.png | Bin 647 -> 985 bytes .../star-purple-12x12@2x.png | Bin 667 -> 1029 bytes .../navigator-element/star-red-12x12@2x.png | Bin 575 -> 925 bytes .../navigator-element/star-white-12x12@2x.png | Bin 445 -> 776 bytes .../starfilled-aqua-12x12@2x.png | Bin 479 -> 832 bytes .../starfilled-black-12x12@2x.png | Bin 565 -> 845 bytes .../starfilled-blue-12x12@2x.png | Bin 474 -> 824 bytes .../starfilled-darkgray-12x12@2x.png | Bin 461 -> 835 bytes .../starfilled-gray-12x12@2x.png | Bin 496 -> 763 bytes .../starfilled-green-12x12@2x.png | Bin 834 -> 859 bytes .../starfilled-lightaqua-12x12@2x.png | Bin 479 -> 798 bytes .../starfilled-lightblue-12x12@2x.png | Bin 453 -> 797 bytes .../starfilled-lightgray-12x12@2x.png | Bin 471 -> 807 bytes .../starfilled-lightgreen-12x12@2x.png | Bin 821 -> 827 bytes .../starfilled-lightpurple-12x12@2x.png | Bin 470 -> 811 bytes .../starfilled-purple-12x12@2x.png | Bin 481 -> 836 bytes .../starfilled-red-12x12@2x.png | Bin 443 -> 780 bytes .../starfilled-white-12x12@2x.png | Bin 346 -> 682 bytes .../navigator-element/text-aqua-12x12@2x.png | Bin 659 -> 698 bytes .../navigator-element/text-black-12x12@2x.png | Bin 659 -> 659 bytes .../navigator-element/text-blue-12x12@2x.png | Bin 645 -> 701 bytes .../text-darkgray-12x12@2x.png | Bin 665 -> 695 bytes .../navigator-element/text-gray-12x12@2x.png | Bin 635 -> 656 bytes .../navigator-element/text-green-12x12@2x.png | Bin 658 -> 715 bytes .../text-lightaqua-12x12@2x.png | Bin 632 -> 700 bytes .../text-lightblue-12x12@2x.png | Bin 635 -> 688 bytes .../text-lightgray-12x12@2x.png | Bin 639 -> 693 bytes .../text-lightgreen-12x12@2x.png | Bin 645 -> 696 bytes .../text-lightpurple-12x12@2x.png | Bin 637 -> 695 bytes .../text-purple-12x12@2x.png | Bin 636 -> 704 bytes .../navigator-element/text-red-12x12@2x.png | Bin 626 -> 677 bytes .../navigator-element/text-white-12x12@2x.png | Bin 566 -> 643 bytes 198 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 editor/resources/editor/icons/light/navigator-element/image-dark-gray-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/navigator-element/image-darkgray-12x12@2x.png delete mode 100644 editor/resources/editor/icons/light/navigator-element/image-light-gray-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/navigator-element/image-lightgray-12x12@2x.png diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-aqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-aqua-12x12@2x.png index 3395e2774aa42dbd0b3ddf7d526dfc137110272f..fb031a53843d0de2b073c2a65e6ad6d226cb425a 100644 GIT binary patch delta 427 zcmV;c0aX6U2FeDossVqCNklK723#aFfrjI&^}Vmxu0`yf&UJbIMw_PKu>&U!wd^3 zHO2L^0@q#W9|~J?Z?q=Q0~OZ$)!{9>rS#j!4KfHFw&E-5{#b0ej|mUkd~?`Na?K;T4qGadUq`P6 zVg~iXEZsDFAD=GH>w%&I*nzW{NK ziAucCY$?sK?aF_O0g7C*F_)V&^6t$A!sS%1pO-=+WRV)}JYmBkSr^AQd4syojaJ+X zsz?vCb0~U)WzE-p5)@zxO$OBgag$e}mN94tKOfsIk-Q*MyuA+{=?XSSKTEUewj9+S zJ3>7o3)=I8W;s6Byblq$zyti&^k5wET^PF1Q<#ln;zT1fk$FfV&ktSBM$-3xj&J03 ViDg#J>7xJu002ovPDHLkV1mIJz6AgP delta 426 zcmV;b0agCW2FV7nssVqBNklrZ-WSWC6H zW{0ZCuwAq#v|P%05`ac~)<58f0Wy^@ZhB>YDF=9`Hqv;4jG1qNG~uF|Qcd&H-RXV6 z>hAPKA>bT4y)uN3DtUJCM^PlBulkncVUU2V|kD~*N~18pQ-U8n$j0ag$ORjdQ=OR zy=3mo14(M}<|~5)%KB*Feh=UbEI{O8;lu4<>xw;$6{jLAAnNSclcYCmkN&hi0CPQ) U3sl2!(*OVf07*qoM6N<$f@>nkTmS$7 diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-black-12x12@2x.png index 9e7ecdeb35a090838f9005a4a37b0898d8bc17a8..33a7133e722402f859063d5dc86add9f9ce0b157 100644 GIT binary patch delta 452 zcmV;#0XzP}2IB^>ssVqbNklTlv5PtkKPHSRmKMf17@vE~%h(-3xxD)(5!2}qMM%s7vTN8v~I7Km?P&Zp} zsTC@F)RUf1ib}?TgrsFzLK6XfJrR_acBtGHD%Y*jZ|#9;nmPov0hfIhlNJPlLv5zY zBi)rI7b{e~@M=jd25TzD79`GiJbvOPK)*SV zgwfOp8Ixsso$tdN1r0B47p;?=1Ia$Yh~MpY=ahr&=A1F~EKez9#*Z_ME^uu%nn2E~ z8f7^|=?|jjZdXC42mPEdj&)tQ2nSr=K=Gy7Cfgx|vwS>)uzo-&Ncyv37>B9@g$GE| u5@OGqp_V5I5$U^i#%~7w!LIN9pW_pNZmiWm<+Ppv0000JtE$>JO{1`h0$VSRG7rqUWsP64n>ky{kS!z@6X?;MUD^e-Fpj~<5c2+$hM?w}hl z*aU&2Cpf$(5Pgqhr$c}oLorR$K|a4#1?9ZAq%_@7Yp2p=V~6P`2-kzb?Z~^CEXymZ zq_$jBIuug29I^R|0Bza>gr=7RKb^dr5CrcAy#Ea@QB@mNp~3#WyaPcJySohh3@QKs N002ovPDHLkV1hAhxu*aC diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-blue-12x12@2x.png index d0c7e21d634df6ee78bcba7ea2f2bfb127b7efcd..e3af9bd6224bac72c63075a24e6504d6b888b224 100644 GIT binary patch delta 434 zcmV;j0ZsnZ2GItvssVqJNkl*VzfSl(da(gNX@W(x2IGzv;|;GX?%TM8bLqI#A&)-PK`+ z1yPQ1cH+Pj3%yW|$=8Doc@fZusU|)HP3|NeD0-k#3eWLao5Ozu?PUYfdfjlb11ssB zU`n2RH%hUE1LNr601n*u3$z3Kx7!UOC^sR)DctptWw{H55jC6tW5%8At`uK;6_Lw- zzqBE&X}lm_P?Fs&dG8-Vzve@a1c5mOreE`T!~hLiA5yw0qSckTgP=O*>qo#OOeU?t){Z(w$m3%F zB1ikzQ_BB>Qsi(Av~rZ3(G!1DCq@~j5Nbw}>=3!lc1gCh($07*qoM6N<$f?I*frvLx| delta 438 zcmV;n0ZIPR2Gs_zssVqNNkl5PcK=<%T1`34|NK3FHRi33Op7cE*iG zC02?Y_hY6!I{zg3YHLNj0%?za=@K0BudFHLynAQea+Dvp1=Aewk6&c46o6Gjd7 zu!?PDLC+h5aESoY&kuoyBjcaoj|rrdb-$ZtOFDuOEmqqIx;Nh-ilQ-(Hga5W2_)*k zBlWaOVkf~3>%HKABvxju`>Ukxeh5!Hn07*qoM6N<$f)BUH#Q*>R diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-darkgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-darkgray-12x12@2x.png index 840508fc14ee22954189d6c0fc6a2894ecc95322..3c33e2bd126c208471d6d21d20096c4e44d1f8ae 100644 GIT binary patch delta 429 zcmV;e0aE_I2FwPqssVqENkllm=ODXsBhxlX=~s_*<=6E&zSs5@;>NJr6PwLuT9)Nh^nhhq zMHEGuQ9u$0=+4CeKqMcJ$BQrwbB=AbP*v5VBrjl@=mC&Vo2GwJ2VHy;z=C_3uq$aXi`luhoFaj&nExQ5lABS+ZP~bKSeYF%gtZ`0;Eqk`GjJy z8TuZk=O_{9wordB0T3pvIf@7s^a#6?;x2`d$}PvX=m8L9s5u2%2g3tS{eX50axSa% zT?%IBOV<2T8O;vFuV{}<9mVyU)GGps6U-+$PmL6LCMR8hsuSi8;U^|%z0%SLr}bqN zMt?%T6_7kwpjUDqehU;AW(!DnjvTz`sp X!#m$STPd7#00000NkvXXu0mjfGd#tf delta 416 zcmV;R0bl;i2EPWdssVq1Nkl_i6`&~))S~F zD87+EBE7+Sg5n9v4dfjNenX&HEf@j&pmCDP!0zmP^S84^znwJoM+jjWh9PJK&1N$h z1VP#h;JWU-D2g3EO&U+@D2nbn0c_i5v2lV2 zD;hy?(1*Bc>>L2j=*097@UsBi%8uiBL(U8WD9dt*cH97D-vQ*KMPt5j>Y{oNDwb$d ztq*{2x~}VQ%2EQO*J|I>lnCND&LAXs3!rnzS46Z!G#gIeWPpZV;PnO19YpIjKue67 zeHYLe012<>ts#HZg=bftBCLA=dYA+NuO&nVLjrZ?bI0 z2Hgza`(FVZYJl9WA^5T2-cCO=(vr2hO}lcGl1@c@>6jSl&(k}pq^M^&a5z8!0000< KMNUMnLSTZd`@G)( diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-gray-12x12@2x.png index e180694b2d018864b094d1fe241d4f5457c9a9a6..1682eae4e9465009e56b0bd54ac4f069e9d2d328 100644 GIT binary patch delta 368 zcmV-$0gwLm1&{`?ssVpdNkl)InqYeMIk6cz9{wSvD)8Cgo18Cp^7 zChtUm0bgk!Nyjo{;ZtWWAyAMRgC&w0(y~7%Q&RS(B%jU^$kjGMG}tB>Pn2D`rc$%4gDp$t=W&_7Et4ux7t#qL-Y4pSs2Vu{n( z(r*#W`BH&rw)3G0;R-DLEj)#^*BAflSa3o3WJ-z*x|eMXWYwRzCcXiO$bE8dxyyk7 O0000Z&?Y}Du|IJN;A0(O4Tj_i zV~maCxbG6+;tf6tm{2w7n>SHwlYajrFlig2w~| zEAW@+j@ZOP5x6T8@)2O4>#7jjmRr;ThYtye-)vPI&kze8VBTuDL4?J zMX{($fRjT>zUWPg!mMYTdX(8Srz_9`e8m`?l_iQmQ#vWPDU~VeL`@a22z}X{lrUAf nxyX`kASj&Da-jS0M<0PBTrhKxq|(5;00000NkvXXu0mjfG?AQ% diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-green-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-green-12x12@2x.png index 43efc5f0e49886f7f04c46f07fcfc6c5dfde98f1..795175530d14662752e1f3d7396909ecea8dae69 100644 GIT binary patch delta 468 zcmV;_0W1FM2J;56ssVqrNkl5y}Z#P69WukHl?v+^tY579vGWO#G5&x;wKov-7tAe;t@!6rE~Y5@uRKu(av zg-S*{6liLXjF6gHgEAeW_<_i*?JO|qYogx(_011W;Ur8Pg|XdNi~HkBaVT!4&FxZ! z^#!y6V)kqO+08t%{RugB;x0S}qRQURNcY1bv#jY8@Zs7eAmYS0000< KMNUMnLSTZj=;3Yv delta 459 zcmV;+0W|*e2I>Z|ssVqiNkl99nNsPXL~P-oU;v!!$JO28JIIn4!pnj^9is%{H5FlYF}Y`0c>ef#urPNE$XI zfGLzecD!IKLB_SS6N!B`Sdb8iSdYrR#zq3sb^1VX$`+p|2C#n*6j%f_-FX@)KdN|x z`LEPsl3tu4%We@8Al-Iagm4vsq1Rau7;t3#6Z|ZJma^!SYWw)?MG#9Uu-uxW;|$k{ zltC>7^vqcKtM+9cbR5#Xthl(9fiqo5{8+IJSohbfx<6y_zovvkivgA-s;Kt(hFqOt!W}uREQ-GHxccxB4c{S+04^LRu4^6SPF1LKBcF73q9gdJE&GSx2C5$Sfv+(1JL%1@Ovlk1S3LykVT!)JL1 zlWMO{L=C3Y(FYq^xbT|Eb->a4a4hKORX6za_yixou3JUW!ma=S002ovPDHLkV1g_n B*qQ(U diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-lightaqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-lightaqua-12x12@2x.png index ebfecb3271948a424671a1c992ecc13f0d1aaea3..34b8bddcd167f02c54b74d5e408ddebff92d42ff 100644 GIT binary patch delta 431 zcmV;g0Z{(L2F?bsssVqGNkl5PeOt&~k$-a0fT=1Tx+LZvZDyP5_($ zZUEc>PhfJAuu^a%D_2VUItc+&2_-?TvdXTSWM(pXuRkvx;IEtPF0Pi^5jqHe?)TXU%|c7P-e??Qj(C}8eM>naF1UHLUR zx4lw|9Yw)Y?|B4K6-y0A-&zd!tW}Je?!Y~2t2n_4X7N1)aZ7D!3B%;MuvJLZE)Fj8 z&Uq{Jik^3^2BC5kzC{<-DYh~S8i9QR_vpEUxu)o3DQTOcNEygdLXLUi)ml7@o+r~J z9W2U--rQoZ+nD%O>1>wCKSXfjRb`g-$~J;im=dP@@CheY|HStmo}cG|A8nS-wC;c1 ZJ^-PFqhd0+62t%i002ovPDHLkV1j!3$#nn# delta 421 zcmV;W0b2gf2E+!issVq6Nkl-C@7vwH-4FbBNczDI)WIIwC@djUbd>f(|9MyT`Qo()WR_$T;Y0+TXFr^uP25x7)JuQ}ErgQzcp2bj!LSk=LpN+yO? zkzDIjb@Ua})M=l)FVebSN1+J3eTi(67z0t%IX`KP5sS2E>D!vXK*K|}loRVa933NK zky`44ETS?h@;HBLOG7*CUGh=6iVnx^Rs{6gdR4^HCW&h)66;|x?l`x+WBJsLcToZ| z!#&eT5PfUnyGuwqfCImq=>R%NDu7gwO$A8@2^}OA#GH@_ z5+x)Zkb4Bn+wn(>Wm{nlNJu=%pRsr6&Ca~p1^zmeYmC=sWDM^38o>`cUJHa6>Jw$( z(aHblwV7nj+rS3a$6knrp9o<1!y-hF>|1z1KbkI%uo04sASi#a!`HdYy)5PyDGu<% z_$T;&0{vu;De3so@jff)Q_?FE&GZXpS%$$q?@4YdCo&_?Go_lmOY|ggKF!%X<2reN zJw>M~LAoVu@h;62vvW6go2gonUy%)#mOx*qDc*2Jd(8D~64})C+Y>0sam?Q4&UtIt6RfQJU&jZTdX!Xt=N=6d00000NkvXXu0mjfY~;QP delta 405 zcmV;G0c!rd2D}EavH^dU&r!la6vn>?=$R6*0?9$t8+1SiVg;7KT7g;tSb^99o*eNI zt$=i3t`4K?_jY1jNWx5l9CY|*mTbaie{bKv0DoQL-J>CZ3lnqNDmccp6r;AGfs7% z6i~yKwFCSvKvUVw?4Zm$c$OJ(=AQAqUEv1V|CLa zfCjM1rq#zjGFh?I>(xyb7rLIH3D(H(rh3F7#~lNf5d#=8#{-v14H~d;2E}yQcpV^( z0W-o7q8|&jKFS%fcbYg^H^sK3Mdu3d-|GwPc#Js&PCE^600000NkvXXu0mjfLwCBh diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-lightgray-12x12@2x.png index 4f17f6dfcb9cef7097caae6dd797adac8e9c557a..7a69e9268f97750a7e0dfe1969fc43899a9389e6 100644 GIT binary patch delta 420 zcmV;V0bBmR2EzuhssVq5Nkl0ds?2w{V=0MPea{|u^50Tie`Ulnw~4JLO@g1`4~#x zSX+l!6Tgg`z|RYKo_Fv2zVY4py#-K2CW`3|b#q`^woEyqxtBp*$w3h0w9DmEUK61A z6sQTLe1+(?E4_Q~V6|GgqP!Af6cmfeU~%!9Y1`4zLq35#hS(n7KcK%wvvEZ*bmnLQ zc<;g(@K|SPAY^~@ih;-s?EsN8LjE{d0A4$^@VFo$8N#%?e20h*CyMK$_aQ6udC&E6abtsVhy@5ba@}#T78; z7mLMOS@R*vtN96`b=ua{JHQrgQC49mm?e!@N7h3Z`Dh$4oXx!db9@34m%;ENs%LHh O0000am9#GRW;Og zecMX_@I_tMDTbOD8H%F#hGEc6=#lrf}bUzm6Ig#hI})K02Xv$$u&swLn6#?&;@*O^1S>G zTK2H1(nr9Tj>q^WO=TdxmVG}-0ZKuEF2re{;rAuRuQ+iEHEX7CG64hNFL>z}tUFNa zbwm!7<;RG|5Cnhd7CWG_EH%t!-I`Zb)x#u$F5d-!+$f41rU;5y9v(rkvMlRMHJ*!c z@dVI&67fEes@@VW6Yv5xxXDFczqvxL^-L28Znz%`0&ybtmV{g%AKmtDL^Hka{~ereRHWA?ith32P(Cb} zcyvLL7qDGuM`1m3E#1DXoSy5bchrTaFMm5|n==nah#O%A5Wxq?}6H zK60~0IZzh6k7!Skg+6CSV9=KFPw=w@TFMn^H?r)>L;z;v7?B(xq8G$Cs!F>Da`W2+8bWdp zbNGzD^Te%2OeB96G8?ZV%1mI8I54IqS7yB4MVnwRA#Z@_X5K#|9#}ar!5h8TPo!fJ zeV{>#ZVz3M*YJjO-MB#caLXjuxSjy>;o_m|2()vtES>s36_!-t@P$8}Bho=cd`^=t z$^+VfG(i^w8jbEk3YQ!qV}B2=SStyeyf6+ZaJkvvL@+aZ1Ei^Nmo~?()?XYPADCn_ lk*k+Tc015Trw9Fcd;-I_o`{A;)aC#H002ovPDHLkV1n2%#q9t9 diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-lightpurple-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-lightpurple-12x12@2x.png index 3858975181b5b6ba1b5def59341b80e3b451e73a..3e4f8268bc0c7625cc77132f54a21008f8281473 100644 GIT binary patch delta 430 zcmV;f0a5lvCmgfC}Ii z36LNiKm}_m!5xG<3NN!8V;N*DvQ8pJ%1FpO@9xa|u7SS}RW{aB>5Jf*e|@-N3lB?a zA&GiwYhJWV3%cbiYdku@dNXCUZTP;B=8K`pWT54|Xxh>4Zx}c&}6)yYb!# zlw4eJa);;I`^ynTcPa(!q-Jy};pB#DhmE;rsv>eKGKp7=J&PXHSl$uQ9`ZM!kYJ!Y^$sS}`ep?LH!SqB`p5wt4D1xvVUH%DY|?YHKRZX>80HIh+V{VX Y58^+ouzSQo&j0`b07*qoM6N<$f}Rt{NdN!< delta 433 zcmV;i0Z#tS2G9nussVqINklzA0=s-AtI5XoX0lPx_7{y7WSC#{RtyNM6~Qz@T$H)9A5# zA%S}?bt7UWJB)v9x{fHjiiCLvDzTwr)Fu`wnxoEUd9xG2XTC$cq2~3~4&54Lm1*m$ zz~%duZd^hR(AWc|aLq|*=keX>CW4To%%)YtAyTSX>GhT-#U&Q4eS|HD38;uJy}IIf zWFAwXi~~JjD>fyS=)f#;D5UqpZ3OWdP!VmCbm*OVAEYUULb zER@1%e}%dqsD<1prpS8{`7W@C;67^zdHtOL!l-k5EyBC3kK;cG}&|X*GTYJ#CS5wGH00Kxe5ghY^xr~`CkMbp%FlOHa_O`DK zPWVon51)l5jVgb+I}4D;lmqJcHd)fWEaYp0GC#5vVZh$Zn^ii^EwEf+BPP&}Gtz)9sW!>wlTqCABtA}555mllW133pmTt(#Fv=@5lK zh|Jo~fb2B7v^ehLb!D1_qfwzg8|T;nsrl|q)nc2&`Y1XA1%g s3_ERb(uUFx>&SP8{K32rb^q&l1t>S22#D*v8UO$Q07*qoM6N<$g30669RL6T delta 442 zcmV;r0Y(1d2H6I%ssVqRNkl5PdxfE?ngZL0q^KZvZ#o2I2{HBeFAY zD8Pky0`vxW13Uq7XO$(H8{!Db1xlurw)n#Ly;!N@>~6uK;FZ;?nC&?@Q~ zxlra)#QQ*L%Z)-w1Sj0-TLLe!SFUN`sPQz@{aP7xB>B1#Ig2|HAkWS9@HxWZtf0E} zJ!P*=puu_GE5d(%Q<7|ZRE>yA!8^QVMCl0(^w`*wKq3c=3Ehais@~99i{NrxZ=Y9O zsqdu#zIVdhG1ChLm67Gutu)*1y9>|14Z~l#3(EFhnF* k7c}2g8-@P8>VZFxFUHZC*~Gm1RR91007*qoM6N<$f^p~0761SM diff --git a/editor/resources/editor/icons/light/navigator-element/clickable-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/clickable-red-12x12@2x.png index 5536d14e6c8372931fad1f96dbe2f771951277ac..e22a896b91799b974a0a5dc3531ca874a4a1cd85 100644 GIT binary patch delta 393 zcmV;40e1eQ2B-$GssVp#Nkl5Zz-^KuW+4ECD;v4oCs=sUW0+L@mJB z0jVHZiPwQN5b*6SkqZJ7kLZjuzM0MCKJ42+(O-wMH?jwQU6TW9KkyC@J`v`oTGp8&bOZ-_UMQ4PjGnx zRLV6ZIQPAS2UQ5!qi>$2EWh9d^;8@;sWi70=o*Va8o#X&~T@#Nejx9?+4G>_+01{_yT{mR}oc`}%hGguidIaIP& z3#A`)_mv%@QY`DO?H+I*3^)|Kp)$2Ygo>b;MxnN_a$$Y*E(G2k2=ZPttiKtVE*yp5 n+4FlnqM+BLGY=r?~>w66cE` z!hvxj_*()QWs}^bZSJ(KpvO6zabi}#iK3kE=D=CupZa@XHU~OWP0{V9SMT0+j-$Hv z=l&;JRlq={Tf_ygo|E!Tw%;VfnN@;42`tPDzb-^~SZ!*Fq;=J*jwpa2VxN(CfkeAp zi%d$Q$zBAm-)wu;dO(t%6G)MVDZ}+y)i*WnAPi5WdSGx8VL|Lwy7IKkVMPxFHsfm>|?Olj=i$EJRRaAYbSU_yKDQDtIRz|-n zlqv8^gLLm%+*wT55YS?-yuHRt8w+*3Us|S$qzE~H8Q!r%HRPS3Ai44i&TDJ(9HM~e3pQ(a!P+=Fyt2L&DpFniJ)&F zg$`m0L1;8q35i`kUL`^UwbV7@8M1=hAe!W0ja)=GsL^1O=@JP&;*u#Rkq1G{rjgJK zQMS`00=CtU;*JltKlEJdE+-#?oXs0+#0+`JEjuS%*C#Rj`b|SIe;ZY%+^AIdL+Y<< zBM;k#Wk10c%(y8+TaL^`D{NcX>NmfpxxiV3^z*m_LoSLSXjIkQ00000NkvXXu0mjf DedmUM diff --git a/editor/resources/editor/icons/light/navigator-element/component-aqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-aqua-12x12@2x.png index 4b9b63c7ae9748f7dc74eddf0eaddc677a230811..bcafa0132696258ad1e6c39aaf83240957ca334b 100644 GIT binary patch delta 522 zcmV+l0`>js2d4+HsR4fh=t)FDRCoc^Rm*Y0Fc5t*Okg-c2b4eufeJzg&;fAZn*-($ z%#cH%0!#%-Du524gU~@ZT6I8X)R4%Z6BOhWfDJSXAwKe}p zm6c7=Wn%^r9TK!hH3&ZOIUaSF2!afTTY*$uE_IB%13y7?TmbuCso5HtU5Soqi#X^Q zc_MnGQNfyPtn?R@wl~s#9$Z@rbg?Tm@2W=~%X?}K>)=@Iol6Mx{TZ}|LX8@9G;~xV zujU&vGbxn${(OIf3V@NFz?4QZ&@INjTrk17$5h%?O1pLt8PlHZ2zk+Q?71h8pCrOC z>YDUx9$cj0Wrr-H02Gplg6&{QL^=_@SZkSGE^Yy6hzoap$E~iD2+qX664+_W5OGPM4|y-239!=Tco6t z%93mwGpi56AiuSZ1v!7ESzWC*Fl?=zxc!@?aOrR>q)eIfIsMP5>;z81%Abz9wP45&dM^WQV#WGZNyNI@&y?=`It$VneQ8NiXz8PPS;B~JFix6;o{MLUc@tS~W#3)B)M6?8$ zBgOkdwCqKRg8a3QnD8fzsqug91)m}N#7vYdCyL)-EU5 z?{c19GmqS1j9-8C2CCY<-yD>29H8IR#Pp8T4gpe{Fb9{9L<5dujKf~Cs(^WiO{EcX z@N@n>;amx3l-A&&>-2fjp^_pG(<1+StnWeX2m6HV(<=D*V3HzUa3!iV=gFl43XlWm zy7pattb4dX9+%ZBK$)d!X)#fxL`2V+sF{70MmWXRpFV%5X@V6NV4Zm)vH8&-prRRU z*lr1`67UrllRI!z^BANT&J)-;eYk=4|MkH|;s?5RP|UPVXWY;AdZ>LaLUqs^GIhLe znB?Xq!)CLCSj&z({rL&{d|3#)yc$8Y2u?271#8jj6G=J_yPq+=d!c(2oF(J_?5THI zK5(pROhHBCd6SGt;ETQ++ASSQr32?Gk=LRZST!<5GK?8kADPRD06A3~D#KZ{&VH++ bMH{#OW=#EXTLH9;00000NkvXXu0mjf(C!_5 diff --git a/editor/resources/editor/icons/light/navigator-element/component-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-black-12x12@2x.png index b6734f888fa365e885ec18610adeb85d8f2ae774..659877a40a412166a942c3751bd6b102ac891fca 100644 GIT binary patch delta 516 zcmV+f0{i{T2cieCsR4fh<4Ht8RCoc^Rl#w>Fc6eY;KK(x;K>X;+(AqQp#$6jPytW@ zPywcbBo*Ke@B05GnNy2wm}*}+MJnrDN8VlR7gs5|in9d0{J&-RXIY%)_iy-7~ zAFYd4<8gomZmEA%n#=vwBmn)JqLHI}WLPy-06z>KJBW(TMD^?=3fnYoNgO|?IM0jF zfOFhc4-#Z;7RpQji5HOpCh%~OL+tgA=8yo@ya`~6oY-!+f$Zlczf0gz{Hs6|Hl?6= z5LjE&3Lq<@I)lnN5D(&VxyX{?B?JIjKYGaJS(-OG@Qr*PQyt=|enNoK5m87H2a)VZ zi0*-onEt_L0oyNfOp@ac`O+p)uDNgxg;F8KHRL(kELwzO#`VTlY+P}DgnX4x``{=- zuj02Z{Q-n1F{XGYCc3+k`D7B}b&1LZ`k%Pb?md_8Iq?m?zViDMudXWq0000%v1|_znVE{brd}`uuB*%d z;!32`X;$kaIURq){i_8PVBH5GEvZe@lO&pZZUglR3m*hPIe@tH%+dWiV#FUJryayYYD33IynSo6Uw6(HA>M zZJe@*LnzC51MxI$8H>e2+ePGsQxW?X;lj|`DEs{<2%ZylDMem5htOVxz~^&UCb~8% w=&CRNc#bBx043yrtg2mCW&0WDQo0$w0WH2T{)fAFnE(I)07*qoM6N<$f()?(fB*mh diff --git a/editor/resources/editor/icons/light/navigator-element/component-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-blue-12x12@2x.png index cd61249814fbac029825998a1efdcdf06594a07e..47118a7fd9f81f9c87b0eacf188e66ef9c0ad9d6 100644 GIT binary patch delta 530 zcmV+t0`2|G2d@XPsR4fh@JU2LRCoc^Rozj-KoI`!f+8ai+JPn5flz^VKso?s#PN;z z=7=*u1%wLJ3ZMhhfpj1b@)tV5)ycDhVKD#m)-B%&F<|1rw*2AVTddI&UG+; z4~T;AX3$DBPkru)JPTO4v2^@)k z74XuQEqE;Cfr}Sl-kg~%>Npl|#vd8fVIcw8a_V1H=mdXvqN0g~%=*c0(!n$QooZM> zwxe+UAtiLxl1hlCYaHaen%$$Z@}mOt0<6+KVXaIe#x+I0gt0Xty_CD;-BC-87vYF{ zXk5dlODJyz>EbV(l@RB5fw{Dc5oO(`d!iM0Hj=MQiO^hfOH@)3IvjKZx6Tx2m~G8+!@Fuv-^F!dwbskYc^}Chby!A9u^^G z9#B6HYtdg7cF@HAw)Z=Nn{E!Fa}F7n=q;Pz)gg!m5#1#b%@Tjy4Dtx%t;v?%nvevt zmubPZI=JkgL0H8ppBLCx9rqi}`2;HCz^+AtC_7oF)->?6-9%EAL%6WSc?7Wm5nhZd zG6dy*oBneQEW;{gTj6Zem?kPf5RqgI54)R3DqgU|Rj)Jx*O^w3f+qARI~H zJZ>H63iJoihkbHBVPLLE77&Ow zB~arwOj<&NQ0~|8<$sdDtHISEQ0ybMW?Y4-pf5)R@k5_IKu_lbL#C!j2KCq=MDQFW znQlvgh+HNT;y41FdJr5evoTRTvwfsAfi>GdK}rHkdi;O9>gMrRQ+I?h(J}-e737DA zU#OMAm0*T7{UYmzz~8KlE)hA1H(U>HS0Yl9p<)8@!59kbf$qqJphA~LD2X7cRSxR< z&y$FmjHw;h{xeBNJ0=-B6SimSc>j^|BBLOtN0D&)4hqp_GDNujk_8FiC$B-`JKI^V8`R^GBo6 z@Nhn)t4FLXv?;n#(C_z0xVXp?Z?{`X7O*jxe2k&7J%jxGP65a}Am6Lc7}j>9C^}LJ z3gN%2oZ!Xyd_M0Ca>n$|0|+K+Il+7KQ?*k8 z1QP2I0bl9&wIzRmk_)h8Lyz#FWmSNKbdRmag^_6)NFwE}OV`YjWW*`UBV1QLOqA&}p^hq+ZY0cundW`36?e@a1B{Huc0ZB9X|2rjrh1!90aOsEAV`434|f2mAW%VY z1;7spq_~4P6~rCj4#E=&kTc`#Sr^9!lZanNI-SqDo!Q;n+f(YsC|ugm>2#`=WsUIJ zl0o=|LcuAOO5SR<3VtOp7!2yi<8g@3F-A3G+YUl5gr-?SKLmezyqK)>JLg0N0v z3dI91cy|7bPuYA*Tn-Yf!0FswyY;`#l{2MHtzT3xzR`BY?m= zriOT56`=r=ckX`xjS4dh!6z5(*X#9NQGSwKA=fobZ4%Q93>%?uk-j<8pov)s{0H(6 zEGI(l(H0y{9R+7A>6IL)XC9yk*&q$HF@};zQ>#bAQW=o6*btgf2t@bVD|JO7Sn2|_ z5WkU{P@=47zQ!;b}6$0GFYLS26g+LA+-5oc7UtmksM95t%b z>GTRO7PzI$OOJ_$ZW-W-T86ZVSsVc`3wlnQtyV76B&|gx!E|6egM6!umcdS{_hdad zwlaFW`sz&%9C(p6`&H_rl=_*$a1g;F_mi0>gmY;j0=DIb;qBWskJ8QX Z30uA@{HYIK&r$#Y002ovPDHLkV1jqB@ooSB diff --git a/editor/resources/editor/icons/light/navigator-element/component-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-gray-12x12@2x.png index a481032f0057b3aa3319adedb9fb180c54fa24a7..639ca7891bfe7f80d902e146d5025ed3870faf62 100644 GIT binary patch delta 451 zcmV;!0X+Wi2I2;=ssVqaNkldpxFR6Xg5fou*``xU(Ju+@$TL!Q4~GNu@$0whZzdUvTOm9f={3ocLg5stQ>mZ z^d&aNZ0fq+;&#yyb_P9|BmO)}0D%_fS*nikoP@Uw#ydKJ@4REsrYQxVdYy{TeiVo&Nj zHS_2Wn(db`W#fNCu2qPqo(&K&rvXR;51YZB#QiXK1I%b7^!^^3{7(W?@vj1xwq>|Y zf*iO`fjDOzO$5$H92q|P^e*E0VZp6*(K#WTka#BtkFkr-W-7>w2qOhg@D*|nx)NKE z$HW&G7L&tQUAt;|DPcouLQ-h?2o`d`qOg=!#gr6&LX|tt*Z0FoMCg&iTxtVv44yyx tuCp=t%M`JcZs(E*-zkie(TDCn@dE&Ws}KrVsd@ka002ovPDHLkV1il#)T;mh delta 464 zcmV;>0WbdI2JZ&2ssVqnNklezVj(ukSSW5~!lIACxJ%>CUmS{XpO%`niHYzHXodaBvO(xEmnVh2ikY6;Vo6#4`sm*TQMdlm;0000jB5bYjGTU6NxoB<(_!HNi0unSdtf((EN zfC$z^VEMFF#%1IPtPD&BCIfT9MOo6cd#n$#kdVy5Rel#SzxTSQdmaGa9ay%ZzO?FF zUkm`~7Z8}y^oozpz22Q&b{>xrzxZM(iAKDsUa)Nq0$oj$vt57NSyvLME&iAR%05UM zq;|OkG&|Q-HdX9l%4ZD#`&Q2TE+0u7h^v#G`!Qfn6lCHB$!|59g~TMr+No6g`E zv8t1?=!}^BAtrxU2mmKJ8MG;!!7&mIdC-WK)||F2ba@@$Z(alNcTI?MAX0&Dyx#I6 zSAZ8V99w+1IOIY$_tBuEz7ohxIxADBERPNa@OqBTA3I%0CbE*KN*W-B4kd^PTrT94 z@A^s2aRXdbZ2$okvHQF4@2cdV5;zrKDiEg4EeI!~wzPj5#R3@mjNyw3oCx0+{fNtr z=aMc`EysOs@TKZ9Qe|E5%K;^m-c5K-S@;Bsc8Sjtn-h400000NkvXXu0mjf D(HR6d delta 616 zcmV-u0+;>M2Zji+ssVpTNkl)L?pJ~WaeRvS?py=#BE2yHcvD2&ENY5;LL)@6dJzU z_?4(@0%`$4D?47Y>BMq$xb6heKLONzx2Y4=*F-~BYLw{^zzTmA29~97tAGvw>fYN{ z3h7NDTG0wQgWC%mma9&%vKFqZ2(R~a6wWMC^L1|#mI6q`X@b*&(Taa_LJE>z5SB$( z|I9WDN9?7)bBKX*^v7*RIe_z}bI-4)I3}XWMGeLhEj&R4C{Zv_h<)1lh+>DXfbErW z?zzLvxrrQ6MeBcxx|agfVWpHJy|Zc7{-|M|f#Y@VxHOlrDa%$V;<|>9HE=s&dxL;H zVH;mj{LX)6GRO{q4_Nb>NYnWv>{y>f{eFJ21q-a*;Wge}jZ>KD!v&mltnJA%^qs2e~000046ssVr9NklMSdD+^3#zGm;lTK$p)|iFhO7f zU;@kpNhZL_0Qm6dnq491+nP~`hi<2#-7o^&V4z`2V$WZ+IDhbzX^gDnOfL(@X^Jm$-0H6+wS3X5^EkjbDsI#U-Ap ztjZ=MZRFXAwg^gdsne*N1g4V@Tb4Q)@cKv=>9}rv-l_HufjgI?1Q?m^SS?ZUAJqaG zghT}bzj9d&L5031C}+(apcC^c$`wX*tnCHnJGnDy5PTScn=D>-GAPe@>nlZ*i#nGD zb2O!c=L8r;_nUuG08{RJ^wohbKJHcCO27kU(ylSTI<>`E&~GLzHv&$+QxYeYV0{gi zhqM8w;auQ=7yzF{Es{(^@FntD3&24}iPv{l@S_M$m475q2-6OS+litZE}cMDb0)ai zG|90NIIBtvD=bN%^f1%k0FCmu^lj0kiO#w-lMXRj2DNp$L!iqsB4IYV?k9%GO$Fu| z>wd_w@)LITD*C2>tH$fVElve~T8YNe6mknQ00000NkvXXu0mjf>-Fd^ delta 542 zcmV+(0^$9f2fPQcssVrfNklZa6upz@FIH=uti1AmS(mix_^C0c+7(x#A%>+>IXfpeR^k*6D5}h^~#CuKAm}uBk}?Io^Y3~d<;?hzfP{RS0yx{{H z;S4(@2HNn9sl=WV;KcF|upfYO?UzMXhl;ns3+DlNQF?#TLb6L6_92!tB!_a gZ-<8rrIQxPFL#6qD7+6cM*si-07*qoM6N<$g6Ws}KL7v# diff --git a/editor/resources/editor/icons/light/navigator-element/component-lightblue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-lightblue-12x12@2x.png index 69d14a2b23e45403ec068d3a82289984dc382f82..1350343e4ef9a22b2760a33038581dafaa66176c 100644 GIT binary patch delta 506 zcmV|LSFb`j=Kj3DRlNA zi#QJ!N?-^)9;D=6uk~OZ&8i7dLq*8@IKQispCoWD{#8JSt&7{4&=;;iAgVJ%oC#s= zONJMX#aR>-Go|yp&s=U4Rme1S)LRVA#S1Wq=JpZjbX0PPij>1h))boRdyq%WIoix= z`;Ca4m4J6>75klD6zpRSGFc%JhCJglHLJR&-q;Bn7vWE6mE_C+;lx4@i0e`s8wyQu wjd9-HDE(z>vE#braVy?&!%}j>rMpc00lJdF^+*orSpWb407*qoM6N<$f-|S<%m4rY delta 534 zcmV+x0_pvk2eb#UssVrXNkl-m5p?+3 z3Bw~k7g$DO+a~=LfxVa5L^veyF+bO8+{S!vNYt+*DiPSBbRd5?Ekvu9(6f&SBLa=> zqa5H9M>9SH`dry9lT;FD#8|>*VUb36MUR`=MN?~9u=F|12ZcLY!AZ8G3BiLr^A$T_ zVSZO|uF;}_1)^RcQjC;oYwP+}NXv1U@R1uj)aSiys~DRW!3>d7oZjoDq7mL7?0AlgImoEjEFggKTG zx&IF$?yae8Xe}(*{s|frr26B8?vGZ$7)=O-qUPUI7wUh<;Cgq&2_~qv4%3$@>zNnH z3)LHL`$HK>#LF|MndHD_$w=*vInQ_CF3Sfcg3_!c?)q0qL0pJ0%%Z(#)s2 z;e6)On_0q8E;xQ2R(0!|Qfw`Sx+3gSCUT0F}M*WZV%)Kt4Rj{0teAdy|j^Azoc%o(oJs&R;yJV5k#!Ul}e?HX!fFj zpq#bi@%V|yI_U_itAetW5x_q*pE}AAZMR!52iQRtL)b1AIA<}w$pGa^n0*8?`nWYV z-r=D7E>wL@4M2Z(xbtyRp!-&N}-zY;i}p$Ai>| z>}e*M4WPspIl=%T$}+)+{GmHEK(%NCSfZfl{aqCNA%e2u zC2W5cIBkMXrxPn1X^4gv*Fiv2dD?IssVrLNkl1lHa6Zuj3rE5lw=3hyGHfWu(9vYKlJ-QJwcPp${OkqYtq_ILaeHP9r=z z;*^$_B1-TGuN{A&QDJ5w#0o3vcDqkfDX9=pv|-#Ar$e=|Jmh$b^v#(D4a`EI4*z|_ z##i9<=>x-2X0{nYrU;6MPUrjpRa8Q!Q|T_M$HcQlg{ZW6Ao58Bpl1WPb|F~ehG?R~ z&f21;Nbz9#C#XlD%a8Rf{wM}UoD;B)j~`N=U8sA7zQljvJIeTk$sg7;qhOtb>=UwL&+pl|u(!=BjN8(qB*`}g400000 MNkvXXu0jG}f}@G>{r~^~ diff --git a/editor/resources/editor/icons/light/navigator-element/component-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-lightgreen-12x12@2x.png index aaef2e19cc65d8921f95fef2cace212654ebcade..1f153d5620304b98401ea1d59ce4dc47737310a9 100644 GIT binary patch delta 542 zcmV+(0^$AE2fGKbsR4fh{7FPXRCoc^RY6kQKoIO%8|P|%z!NwILRG{I!Vjz;*nU8w zwW*wgUx0W)k{6&u%9R`b0saA8F<8TlwPJ;kY}p5@=nH6fw!3F{W(<6E(58TZZTA5t zG{83o2ky{}L6a%{h<6rH;ssiLARWkOw3$U{YnAZpzPbq-BQ2kOv3*- zk3mjcey1`|8#S1cjpa}L`XTwur=Al>3D%&E4RFp9c}OdFeXDC7@P0y3qXIB!i2sH9 zZdzSi3G9k@6wYC>XrGP1r0XF!;=Hj2i6C$sR4fi7fD1xRCodHRoijeKomVI2$N5z1JXhKmjP!YSCDi79Y6}m zXo(95t^lYYbP#36dHls4SRI&eX4vai7q=|p%0l}GEsHI7;woo#u zAxN8+6KM58>}Q8)w52oWwYV~0(^>+xxP@p|Ike)nh#<==V^cJENl;6WK?QQj(0vIW zl>|MR-0-Jc01M-bsalHzqzEU5gd2E_tOGgK^N}j_#g6?4Z+VoVIqnbSb$+HLl{4Kn z%((QRFO&cL`mTQfFO@Ql{jLOt3ab`EQDHe&_Qxb|a}WFr@WmU({9J+63g%--OK$q| zZAP$e0M!E%&|7=kDxc7_nm|u9WS%nBad0JBQ9X{;lcaTC zw$UK}im(hxWIfSG+{;ragk)zSw6RA5kv`J{O=KQQ94LPgjw~+(2NPs^I};n@nW8=7 zAFrzf3%xm*dkyti(cWQ?%=DSPlVj#(%E2^U`$5IupFO#lcd%LPTP8tjMn?A6*lFp3 zPCdsq*HMeSnVhW~5!<5Spw4&It&R+xq(P@<;n;Y?u~41y#hfvh8@L~ZRnd9VQrg}f zJ6EP35uY)zV`ci0F+X@^))6s|G08?@>Z-K@_v1c8XUv>V~xRJWF00000NkvXX Hu0mjfs}m4> diff --git a/editor/resources/editor/icons/light/navigator-element/component-lightpurple-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-lightpurple-12x12@2x.png index 3b54b9cbc4a015aac1e29617e494d7057572358f..91969fdea18940d45a899d0c39f615cc77de2de0 100644 GIT binary patch delta 519 zcmV+i0{H#E2c-wFsR4fh=1D|BRCoc^Rn1YtKp1@+qi5{E66nCB0_i|Jz>Fub0-yr% zs04_(okhxPid4 zyJ8VM`AroZEue{=AGAo+X17wXYz7CBoT2C6saYw3a44P<+_HaJ&#a0B=)py7`U}*Q z;+o_{8V-VOLVpB42ht)@KTqs8RD^A(WH4Cr`jiQ1wMC(O-B7&^fp8#Ib|!W-78gFF znWF^4XSq^mcw@7w`=Yql2IXXwAJ;nsRkgr`qV=7`e5de5+9VGXavOCg(_SGO@HsWN z;DKT-Hm~f|jQxLL>0+GRZ$SdgbY|H==U!7?ZWZ8!8Pm}lAxR@6-tE_06X)J3&*P#1 zHphe9L)MU;n*a_|QC1@(kaKp^>pz>uTt6Nka>UD!t2<=GsU_VO&U5KIk7S+ zo%ah&DKs*5P(;kRXec4qer3s7LvgZZ)2{VBI_PE{(iD|o%*7)^LNhadleg=o`3c2Y zzTzKFDs+w1m-3iv|G@?NMYXZ_mubZEzNAmI#0QCkLyGP+@e8e*;XUn-_~QTo002ov JPDHLkV1j($`gH&R delta 546 zcmV+-0^R+k2fqifsR4fi07*naRCodHRm)MsKn#8B7=|NsU^;*buq%KLfCDg`0u>M{ z08Y#hW&#zE4s0qQ9mE}wGoOg3_1bYhP8^ur&`jcFExjkLv~PhGn_1)#cVyH1LQ{Yc z!cP{}6TuzUkVMBO{S`rcFM;RdkU$swyIJ8jfQPO$a9u?-MG$|tCFJ5&k!|Lcu!3v& z=n-fTKgxj-G{<~AJTaN)=)@#52{dElqf-hR5cHWI-N~SG41rt5;IOpZl{H-E6%_=@ zgY@|bEU@nHI&L*v)G$YMh9+YTR3d%|n!1Dvva0FH%}0er=XP6;NYrvf zdnom(?jZPBU^$WgW(C?vyOpSE9#(As1holL{nGiyAFY3c(JKgaj`c}}96L};gR5W? zql}qVz}-F1QzIV5K8fd*N}(1wz4(h? zKaaAUjtx#PLXh@NSnk@KMS%$>AXS%m^vwuFOKj6CnKlc#U=tS{@u*{W5ogFTOY!94 z{|};G(#fyhR^mZ)i+bG}@_!ZnuPn-n%YrV49SHrX38}(waDp6Hi3vMCcy$Qz?xI&Y;)&-$i`?d71fY4q!~W9@3%)sv9^v zs`WqF$FB{n6~y`~RUC@Tz&@_^`O?8q^)N*0-0^8U^m=h^CRKyxLBm0nMMJoFv}Ia& l@gyf!HkZSrtrycr;sx+J6q}ed$QA$q002ovPDHLkV1fqSFuec( delta 666 zcmV;L0%iS%2$cvSiBL{Q4GJ0x0000DNk~Le0000R0000R2nGNE0FBi2Rk0z70e@CW zL_t(|0lk*ZaoRu>$Nx`Z#u=X|L3BVW2pz;7gj8VX5ZQ!7#04-uB(A_x1)&3z3gQk> zI^dMam$i9scLkQTtmF*wn~~6n-S^w~E#L`-TCa@bF1{a~@{R$N>hqf}Uw3?^2xy7< zC~H#D47-@Ia(rOGz^{oC);94$>3KeztKd~z}a33sWXzYNNEG@&{E&8B8Ut2?*(0s^hPhnyTbUH6EjkG6%+6JP`K6OFC zOYN$*l5^t7o&qEX&hNJeCHLvHOI|(Ll(AbUxEd$5^+lFKos}RCulN!q%LsW<$1C;^1~E(aI*n%BRM_&gbHW6Ao_bbkzZ6|s=VvOl7_Yx;84<{e;y9jLjFJOJ~yRA z*jSh{!%&ZhLrY*=9DOsez&2KyL(%jEhY~3ZQXh@#d}(0P+msTZm~Z@<>*mIG{eOoP zwWsGI>zxOgew&Y@zu6;M<5sT`!vFvP07*qoM6N<$f*dA6 A>;M1& diff --git a/editor/resources/editor/icons/light/navigator-element/component-open-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-open-black-12x12@2x.png index 51d1f4ff0bc7f10a2cf27ab23cef1fac34d891fa..60433d393c9384c5d961761b835f41493dc29001 100644 GIT binary patch delta 631 zcmV--0*L*S2=WIZiBL{Q4GJ0x0000DNk~Le0000O0000O2nGNE0N{5$_^~000e>?| zL_t(|0ku`jal$YVwM;m1p@Wzk!)L~+08;^U0I7ha0_+Z;f|w5I0Cx}{_}x$m9N+>B z`k#bO}GuC^zTnfk&T>exmM>tncK3Ojsz;6@{d@Q2n3M8Q)88NWUYky2nwI7QtRJJe@ R!W{qr002ovPDHLkV1j~b7Lot} delta 664 zcmV;J0%!g52a^aPiBL{Q4GJ0x0000DNk~Le0000R0000R2nGNE0FBi2Rk0z70e@6U zL_t(|0lk*pZNe}R$DIIgJTL;hApuf4LFokT2BZ@}Cn%YqWrD&4%?8j3$^-C9xA6aR6T21dNyc$-?ss>-vn|9wie);{ah%F_yX{(*)kbqpr&9&5r)Z;6spL(xS`&`(3to+e<8M#Dk(ZVFLBi^ZY~W4jnu`1RF%K93?{E4~Tn zhY|qonnEQE1)fk?uO)~KJ{%6A(lcotg#;6CIpd@O9xNQD=gTa$ZM!GuXMaT{GeH>I z#v`p?H3s$J!GH#Ubm9=frLbPFhpNyU)fv{(g|%HMRfZJ*P0)F&3_OD&14+>xS)~e< z6wXu^j~xot@pv4;Gd~YP-(Vi;f3w)~rAUU#%Y#ygH=9kEm!*o$AV|QtaJ5O1CmEXo z=?oI7zu)h#(A_hriuOW=(0`hlKrn9%#bW{y1kJ#Qg;gu^#vucGv4g^3L2cSbu-CQJc6<;^2cblaLOE+i)V=fz+q^5-yYd9swk2!_S| zIs$Cl6_=N2i$fxPNY4fg?Y3I2J8>bQvVhJf*6l|y+S@Q7U8pgSzlqS?TXctK yKLyQ$X?GFr;TgNcbQo5P|Buj7$Q)sCIr;>4fRKF9ipp;Q000098wWhGn ziYAScgU!z=qCYAk0f$QEP*wqCL;cn=x08*}$`tca`gKeFT2LA1MM`!sb$`n`A)$Wy zH6-&ZF!uFD<2A9zwlAqz9?@<;#C0<${mmj})O0PBxdtk;qvlw+Q5MUQ;m4B$i%r$DF!bi~d4yQZ(q69Nw~rHni`@o-^$VtV2jwYZ zoN6q|WjVwzxKA6(ZgP;=jeqW`(f29&7F;ZfCS?Juv&2n%0Pt@WA=&s0?%!dBSWs|B ztpS>1ZWhSkcdJ6&n&?cMPKEfk>(xzBy+Bb&PKpT(3ls6%1U>*CFA&?ks(`RUwekZK z^LCsh3kwSZv~kpm87`h@cn{>RSHAfat+asLm2w)C2=`u{|2pD_XlJ8*6OMe7>K@2x z5d5?<|AL(v$>l#yoLr@nLvp1kAJ@tGGJyLyp`&=3oKFH~sPhZ?jaPF%nKzo>I#$tu sE}kUXF#peapoz)GZ=D{zm_8H#0knW7yp@*eP5=M^07*qoM6N<$g6j7&QUCw| delta 680 zcmV;Z0$2Tw2%`ugiBL{Q4GJ0x0000DNk~Le0000R0000R2nGNE0FBi2Rk0z70e@sk zL_t(|0lk*paT+lY$Nv(TkBJ{B0e65a2&o|Mz@!44nc&Hr;U(h<$t148P(kPbQbF7S zmkxNygpY9Atfb@capF#lv3G`t6Vm=xtN*S9yr2p1nO&;k@45}5CO{1ysqyj$kQ$;$ zBivSlJQw+}kN=to>4pK#99IJr!hc>CR2%@A@$?ZW9OAU{U`GBd^bT7P@-hh(L)@NB z@?kCrsXGRIM_0_?3~XM<8r?KBxzi-9v*JkUmp8->)jMs&oGIIhILD`w$%IVKUTJ&~ zebgWdud!G+;A=`Y%$f~I2du)GduQ9|bV}YnS`_fq9{Qz0YJRLzb(MfPvVW2x5Qc_m zGV}(7dJGkE1i8MmJ1Jf!AyFxumItoX`_)-z-U15ksJ`(g%9M zzo9c#8~ZSCVk>oyoQ7QFqfCfaw^BOLpB8q#n1Vz-`a9TrKCuH%aiucLRB5_|f?b$i zoG*$jb2bCxGe}CmP&(&Re}5Orzs?Kp(OFJ8%`GoTXEjEs#t}#>vd00x*-VkCMg8gk zpUY=XsCMWJc~v^&v+QygiBny~KGRTOV3fF#zj3&uU^@nQbe#RL6m&_M^Yl(~+M2|% z%%guE59VRd4+{&nlmuoLM#5f(%0uFZ(`<_)`W?ZPZLEYgu9p`$mVKF0k>Bix99fv| zZHhFo#=sw3H}|F`Jp~fip6(v(n>*3=%)VBxY{hG%7D72a80su=dXIiZUqhLfXYxIv z1JKql?>r?o^~cvt&buZ1@=QUqVEZBYuq3nv89`0od<3=jnpU(sFc?%6dxT8g-Qt`3hH>YB0)Qh#^g|IL zavyWQ)9EAyU9DDgwxhy3(iB5y@R>?XXOa2n0Imb%&73I05McePvV~89!+$W0Z7j_Z zp%pzl9ULj9VWWP+9nfHx#S%?8j3=myXY@`wb8 z{(rD5*NKx*r9J7ykvR9=o$s6o@sHvZUFdn9TdUOuFk8?&s0;mo&Tu`P&*%F*AGxqj zr_;jEP(tjE9A{dsR)Z|4a|0xT!+-E{xy(+d6EhOXh#C6Oz7FM@<#M^ng{48DV*p;m zFpNZs^m@HI?vG5UnduK$x7)o#RNJBu3)F|ny>%t@ez91@m8h5x;O1VMT-=nUDkR6_ zk!za@#DI}ql$x0q-3aD`7Tq2{0V155>$NU@(jg+HD%J)e^n5R`ZTTdh2{)<=>x*(Z6)16gR~Azz~F2EXC5M-rIkvF>{MS|yDnmja~!fD zdQZxr=+}ht;oPRk63d*r2^coMk=7JNpti$6o;q9l zNz56YLL0dGD7&u?oiHHjFn!ps*}z_o^f{~9B9)m;*@;@FbZB<)TF)fw z#IeFmD5Ae)tz#y6$67^{Bt_28(qKj8&td59c$Bc`k%Gmq0Qq_-ThtNvS&`JSyfA3D z+ny*%I2Q2zLYwmz!+5qyASe9|?LOg=Bz`Hz?78&KuKwP$)oR68MN~i=H+__JcPrE~ z;Lp-`=F8Lki1BHo3XTC#^S2Q>-z}LhPZOF0vqF?uPZ0T4{ zL_t(|0lig$al$YRRC)}M4H`C}695yy2BZ^ECP=aYOwh0a8;}jk26%*Y0{S8{6~d-1 zE&V&4v19#9vTTU%jO42gWm%?4lFSc>!wAy>EQK|&HIMl2ZW4fF2I3irUxYLSCt_7h zC9Q(|=`FEHsyC z@NBR)l3;k;VgBR=_9j9X6AHl)pE$7Iw};HVJ`=H5Y$&b?1&Fy+TsEKSd7A!br2npqC%hVE=9WJ^kD4>O?OF4#BjQCpue}Q`l zq#*$(V@|&WZu(GjdVxyD0(38GK{tSJJ^SJr@m;h&3COKHituwSZJGas7(e&&)E@)( zcjrNEe{c{{9 delta 561 zcmV-10?z%L2doDniBL{Q4GJ0x0000DNk~Le0000R0000R2nGNE0FBi2Rk0z70e|gD zL_t(|0lk)sal$YRK;;|*WQ4E*ouJvEY=Aof?F3CGXqkX8L9+qr1Z4x<4cH)+uuL7} zPw3^)oi4;!da@!Z0l1@xu^X$Z%7qZ?zVA!CU7+Tu2h<&Ei~p;Xk0cD8lz4eVEfZTC z)H((gH$YCPE$EXRc#TddQCALhhky265*C1LP(Sd$6Ziuw=;DD6PAVKDiu8LdBmkAD zYtYY>unaDggim$Z!5p=4?%7SfjE8t6@A`o4L`eYd?&?#v=`%RU;IFPHX#0sPU z{oLsJ6&AE*M}Ux(12L`8_)R8Z8rD)Sgo zB@y(QK?UlT0%C_(5Y#>X+%t$EH3g3A6XgK(q`=n|IJNy(vG!F%TpV5qGMGrl%+JYSW8@yN%YVEyF!M5$Fuj-&_hVoizOFI%OPENwRo?lw&3Lh6ARYM= z@3%aX{tdBuk9=;ZsxxZ?y(((Hm8i#Cp@9Z}W#7@4r~5r2`G5CQ!t`GUiSL$~2d2m| zj~WA&kd_h>QzSO7lm(SAJgF@m=!#2z9Q^`KiUmc6asx;J00001l5Iqs&=BIh`t)oVq1a0(0_5%u#5_%cG@oi$BCqxS8@`hV%d+cZg% zjpTSuMB@_|M(d2|1EC|rIRTs|$18Rp^4Ysw;bY(<25tuHJQi9-n_b1*wB}*@rB%x5 z>Zge8O%vI%tAaf6@wDYhH(Kk08v;(l5AF!hs!XTDnltx(LD zcP*p#;w&bZHt!*;a8*WBWPdr}Jq8ohvt2|qL<6qL=$j^Xr&rxWz#RP@7y2#%UvqTh zv`>aWsOn_PtPK7oPoxLX`nglzdj!nlj$Nu(B#cT4tVQkM5s})8?n9))&jas127{t5 zDkMk~=}swokA&kg;Qu0c4SRJ0SO!&4@}MC!n#f}{hJ z4tPj1j3wP>?<5f+ACjEG-WP>d!x*{RJdV*3^G3MCFW%H0U{0|*;8l$ zo&WX%oe8n;9xD1e{nJ8$FSn81ftn^AtE0wbAT{AQhK+G$+3eDkyv_|;vw!P2^uA7u z{+UW8(Fk)8Q&tWOL_sa+BH$GPw0BU%fTcdsD~ZHq0isLc#FkT2>TA`RGj~~WyboMo zMhAoy*WWnm2dlC;8s;qDa3JXd;mnk(%P-Vxf$q~>pkgP@r!c+dY{U_&CfS#BF_9`PzT~H zdbcsfw<$;|a?CMaWj>-fDD;Bqz2~2qpekTp$caN|(YxT<%GH^DV4@nzKU1Z|O#V7x zLBZ)efI@AVHuE6tA+$$jerhF$Aejj`lGW*-M}yU|Cx^w&fBjO!xPMdYBS4D#0UX=H zq{XqSerg!E6Wv(3^$Z(dTo;aHsw@cbqmIp|yoRaX#!^$j79sl1^5UlHyKVSS%hz6V zBG5#2qTQZFoAy zL_t(|0ku`pQNlnF-OD(R7K&$|*0O$ZK5IUd(&kCdi@~8O4m*Wpv z-(D`~CElTfurnd#vish<-P;Y(o=yGckS_QnKc>E7O5xomrV}h{JWu7W&s4S*LHf$g zJfRyn+*#0&WkAp>r%{YZg@7rc0e>^~JSPp35q;9!EF94_7H=5t9?~R4R3W&0XGz7- zDK3Jh2+|bUC2m6onFn~U8){rWCw@SZL(z9SW>%4=h*`B0Tyt;vieftmDI!}?fK8kq z3NLB0eyK%TLC^!zIMyw-3K9f}I=DCOat5Li3V&WHd<3{cU=_9N>F|^eJb$7xPzpZ< z@T?A;zH^(_w2~AWg3gj(;M^`%`sr{%OTLCr-#l=*HrRP;#YoT0pHJ0Av4b~Wa8+TH zC}b62597I^T9s2Ipz;D&69JDM5F@y^2^c<4@O`qXi+XsL)M6&W3ZmNpQPTk<$3K7} zPJK`d|HqpMj7e(hM7Vm+VSkNIt^p%v7&=8k0-wkZwV+8lV!(eQ*oEz$U|pTOhJcGa zi}mQAmLHn#mqyGSfjyoiXZdo;1KPr*>m?R-DNd2Cogt8}EJ5lPZ?ya3h2~SV v(X3EP!{R+!qWEJnm^zQvei4L#|H6@ch`LarZ^C~2im9_#&_2&04Eq|fHB1wdX zxYh~Ist`VFx^moL5=wnkpAkG{ibf*gl+uVr5xH%%<6v*EWyG*gnW{XLstPniS?Zdq z6{9e&p>3NE<;U@`0QVXN)DEMYT$ zAL7vKs2FjaHa`oPAFMi7vR`tF11;C!3BI@&jx`6<+2+a?{D&p@K5Fb* zL_t(|0ku_KQo=A0-mT!XHxO=69{hU}PM|kXPk^3)^agqY=?%PreRBq!fg8{x;47l> zOPYqHq~I{HGl4eQ{k|`o&6eoE#@igkM4s@H`chICuQA36Muw46lQPlad?y0&AzR#_ zI{-f#(2(VttVu~75r=^3hz5APcYmfccqY`Kseb#WTm0T(bRC~zh{z*IMzSx#;V2%$ zBNbz_e3j3ueamml+Yvcw<)`|*nNpD(F4Y($_g4zfo$n2~@ym5URUc{1~ z;P9mtG17okh>^^&l8SR4T3{T!O_Q`~n&bI}j_KKj2Q<|9HP>cuPW8IDlm2(V}7mF%aMOst8Vr0dHZvDq@WLO~6=xN8GysSE+h&eSCsr z8Y)&iJ**K;WXl30$7{e!Tz`|=^y61iL?LBJ%^K0dx!F=5yay~UScIx5NZ=9yAgy&k zdDa2{i(ntNe}W^w^Ogj;{#|$-bSFdIU%Qx*nN7_9AQ{U6?O^KGt5|g7vWikmpl@Yy z2MB#eY^(neFj~q?#p+49x}^3DR5f4+J*w0{=5A`y)!GWU_>=-eV?P=5+O_E~ZKGcG zotQRTxt`Var%e~Fqj#h}JcZiaiOL+{9(;S7K1>I-KV@YA1^B5!4*&oF07*qoM6N<$ Ef=*Z(#{d8T delta 629 zcmV-*0*d|R2k-|WiBL{Q4GJ0x0000DNk~Le0000R0000R2nGNE0FBi2Rk0z70e>+` zL_t(|0lk*nZQC#uhJQMC+eeS!Y!E-ReXKh{vq9Vmlul4;g4Pqno}k_!?o)xZK)OMc z4g477V&*>*Em;yNGJ%r=(6R)Q-?@{(D~gJps4vY>-6Jsu6TTjC3_1Q|g9YAVsmCe{ z?Gc3Ozh(l1@BBLnOr2wZv>Uv?H{94R%Nx8_$_dRl`xyy8y~fga>>llYBFsA7`zxqs0O7x!_} zfNV=)?s9!poiUbEJ|qr4m#(-|>dL?tEWI#^0gm~1;c`_8l}xQtT{K^arCkuaCZSt@ zE35exc3tI(Pq~4(_#M_=S?VaEtO=9F!KCOCPcx7`vwG?eFy`-93mS2pi6S;;K?vua z6LfAtl94H&pSN>bbtaZ@9Dh2YqIE1}fJ6OJX*^VQ)`w5i!hLgVRgwP1hV=|Cz5x*( z#|v{nP3J_hB+%A+*ptNc&%ME7<;^vqQz}+y|rv+p^5%yj0z0}Y;P0bkQ)4A=AH5A7~z@Hs6BDxOtQL+8DCCq#fwaFhf1rbLY)P^!MA*G zbRVAe`vi)3a$)l-v8}%q0{52g!?O+Tf_Wi9SOZ#K*KFV1g^A0KVlGFIIruK?20={P P00000NkvXXu0mjf5|bjZ diff --git a/editor/resources/editor/icons/light/navigator-element/component-open-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-open-lightgray-12x12@2x.png index d61e0f4451ad7536df4804621d1a0436c9f46330..4267cf93b7af294923b49c62a1adebd16cd1d7b1 100644 GIT binary patch delta 612 zcmV-q0-OE&2j2%FiBL{Q4GJ0x0000DNk~Le0000O0000O2nGNE0N{5$_^~000e>J# zL_t(|0ku`zal$YVv<>{zK|%*+fN!9J&;g_ZLIs8npn^aLbb!Bk40I5eK)!ip*YS}< zSSG{3&1fW9r`^@vNp_qkn|sS)y$(%q^TKku9Nk3#;8y^* z0sN7GUT=2Yh-4rd*oa&UZ~)+r`hOf^KFH_u8&0s^!n}=PLy?Wsh%N}0%Vif`Ulel_ zz$Ud?Ep#lWJRA=6Z_76j_uxO2xo7NYIDg@oQjrauMzsJOW4KW#dDA|5J;~*AJt+E4 z6tysJ;Z$)#E0xMvDKDmkX^Z&?VH|4A)FjK%0bIwX*F;%_Zh-b;B>oJH6Mt<@ELRlm z_j}(AhbYA`5F%w#s#6nqKA-!ALSf4g#smn%8l5jHbvVS}Ln0Od6PcQu#bVI_M&SI0 zZBwmQ%Q3-fwffQuvxw5n02YftP`aohDkC__&^}3w*2x0K$!6FyOTZbbk@mSDK%&M_ zUBZTUlZc5IKgQSurZ`k#34d*9B@kn1Od=FPN7nJJWdb87{j@4dCD25?$+mTtrw#aD z1dp(X6YO@o;uQgo8nM@LzSnT^>d7$D1bhORyZ{vwICmIteX@6$U`@^hyp=+NzJII! z(}3}I@v`$ne}6Os{H_*gMPUr+Q8QU0000iaf99`+jVLdM7}ZxPMRJ9X*-xkM(*T;J*mVyDXG@TCLWg6lQ`TR9yhx zVD(ZM1R=iIY&I`CRQEIo8xDs7HcVY1CMdj(0D2JnoCX4TQw1Ku#^W&+-NN#|DO5^irAA_3b+o(> zNMeJ?GYs>WCoP|Ap^9x#hL|v0l^R-Tp~HB%v?y$1>Qkw6kt_X5r4nM}Jwb%ydZ!`G znF|Ez_{7;y31UUYD57h%=YOcr=n1Y%6O;;FAu#+BxqQj?S+&Sg8NQzMDlLDhFjv9y zKOr0@P9aQ(!up+UA3Z4>YrZ&>xXjP9!Cd6eVXM{ZFfUUW602T@kvOv;mw{w_D_A;M zIaW{zx8h8~wt((et}(om6eedIfpqx;<^C>5(yt+z-lNVgtNM_$W>vHK$Y$gkzY*SP z^HZS(4gN&kd~SPr=DsIrfHW$1CewcdQS#kleR=B85?CRm6qbduN|E3c%DJh*7_z|S aJB1xz}yl!8Os%f9f+wwaRCuQYjT$>h}3~PFb}elTik(J zf^uat-0Ttn1;V84@n>f^9Dr}%TVOu~cxA(f0Ao@o1@xu}G$x>sw@wf+BY;&O$}B^b zKS|&{sX+j}2|)Q(NIPJ;h#fq~S+)r^ z1U}H5ucA~oVsYa2YJ)0+j#Dy5G0DX45#Ys7oGt7+XsT5and`u{MAStt_KTzKLBK)i zlNrL#F6PKxlu%x9M1OQd6cvEcDP2|x-QsL%aXRt(n%HM-ws-7vbqus<27i6{=x4kf znC+b5DL-$$#8qEYV!8ne5ASbN@A+(c8ke7)Qahy7h&Ed)Mg%W&A|f0pb4c^ zlZzPr5aAJB#)pWx2(CHN*MEk*%7=?-2=w92QdAlA#TVjy3@mO$Dr_N6`#{5zliev` zZHwxj5SMJcM_}X=vyW=4qE-P{h+nG%kgG1@M+v-yy|_T&P2Ng?n6%OIDn8vs^^JU156f<}#^NFC_%>1hVcpFSIAJf@rH$15HiEwS= o&G$}}Sz^K5;OzX+kLgwIKXNTDAbCxre*gdg07*qoM6N<$g7s-FHvj+t delta 677 zcmV;W0$Tlv2%rcdiBL{Q4GJ0x0000DNk~Le0000R0000R2nGNE0FBi2Rk0z70e@jh zL_t(|0lk({a?>ynhJQJ&;W0-@Zjin~D1$ixy+O=BC9 zTE%&nk51S*U5WDrUxC|^N>5QFE`O-H2V~0*R|-XT!ZVVFJuvwR6|$3=3FRxhRd3gw zFdGD*r4M}MsJFJjo=`kuK-`2jXL^9=pVbw}!8x@zC@D98G zkXx=_SODIOJq8o>v{UXYWB!1!^~<0wGpnQ1DS2fK%DHQ@QSZ`b|5~L$F@HB9wyd-Y zM5iR+E(?Ag)ld-$|BK~!NLmIn6JnG?YD;~uI-63=ic=A>`fT6%+nQCH+^Tr(@>9Z| z(pBVvF4$RSOI2;>6bFXXCGw2Nty~aMcL9<>KdUP8%lH$h0XXp0QqPm@2n`9d;p(Z}k%Q&8z6eQa41;DZapwtSS}tp?Z2#s}iQyHUSQK z?fb-abIn`F2>)ni?V(H~EoCM8{m;0N=T*h?9Te`M?(Pe<6*xcNaQV#3xits0ohKv! z9aQ5eQPrPpGhOEv=jPdjx?nCyC(MNEL(ELW#^!fPTXksdJ{(_ zL_t(|0ku`japFJ_eJ${woxwr|I0B;xOa`_O_ST+QM*z+MpSB9N3N`~WkQ~91feC@V z`cvcAqhUN6kHAIQeUe7q?{&ZK9syr$vd^KIo8#;mLj&|-(BsiDqe^4&7e^@bOIaU8 zQ2aKXtc`O5{j#8GTO%V`3%5-~l79l07Djx$2)s&GaEmrp_WcP15uCH4zW2$nND!3_icyNm`xDax6#4b87*;WKCB6Ebb+cgMz0LQL6H`YB&K?s%@qD8Vw*-{opPO-;WhjRa`eO!SFtk!4 z-J4=&`Zk$LwpIUHPAY<_d5AJ>BuZHX>@i5ttxu8Rtn2cSi~(~cX1N!;fLVRP$_fX* zVPbcoPmO?$S|}@>F5eN&*?;&gFg1P$%;d}wx_GHiQI^U~rHP5~7;Lt|AO_}gjZ;&U zBnXM@q%@e0XA|&;2tLC;pP*I0c`E|3I-{oZfkwd75YrOat60wjqx+c|;Q-UE*H~iN zDcbhV66jXC9ncTsee<6J=EeA+u@1v8sqcYKgAwG2=ATuaHG%8507bv{nrS7NZMZ1y{SJBdetb?f11Jj4T`K}++m)a}(nkwYtgO~&W O0000|sdVP9lS$jt$?;b{#PFJ;1oZ=sMDsCqhw=9I!5pU$q#Cg&eYT0BRlhc`A< zp)$n8o+&_TFxN7tXBF!-ByTH+Qd+p6h3kX;yDAl2S0S#bv=@j%`^fVLjDL4f8WC*= zRP=*k8Q{DI*|);l75bn)V=nVNNJ~f!66?960_)o-k4u@0!I>>tN2p3DE45PU837N} z5cwdsy2Xb1(ZZ6YJfRY*w)~U|G{mow`Kr{>LTMAGhdYbHC(dDz>r88YMHM9Q2ubGQBbXt8Z%R0Yl<*+gz>r{ zS_U0jr(ZeSi(nG!uuwF@@V$UGxPN6r#vMwUh`0_|E1GJevz?QGFeQh7Xd~Zu0S)ng zgpB&0&!Uc~L~wPi$51%?|hlY#GZ;D4x`&Jod1i3sTr^*s%*dfEv3>6RDHPlW%4G9kKAQGe{pw8b-j zp3}_7mt>>|25pr~37GcST_BYId`D8eJN z!<<%C;192LR0OmY!41LXvHpTrHhs7Nwk5Fg<%li)&$JdRHZy zywRa^yFiVrz<3e}-3^Lz7pc0)Qk14jRNQ+zJ2%3YfKiUPu8V33d?KX0Y;l=40sj}l zW7wk;zwp~n5YJUOYi6CyzTJmQA0000a delta 693 zcmV;m0!sax2(JhsiBL{Q4GJ0x0000DNk~Le0000R0000R2nGNE0FBi2Rk0z70e^5w zL_t(|0lk(@ZWBQegKI|T-a&J<09gLl4! zk?^p&RX-lK>D@C86>2uqKu^~sAa&TZ5TtB7yo*BeBDKi3g7NtendRpvDu3nhbs7Rk zREh;cC>n^)59lONE?CGernuowyzq?DkT4YpnYlt=E6;{q+c!4!-WgJc?uvcvQs4&c zbl(m*Ix_Ui6{U;NrP>Oz09wtnLB(=MZ+XZ?BOGRnhsZ4KTzl!pcr+#h?R;S%NY_$`m5)V3vU=m%1=685KY`2-X#990dVU+na{(m(%>DnV~scBj; zZ9eE&%UTH2+D54F>fx0Pg(Wv07-IBZ8C&YRrUJJ&X=NB#aPD_d7mM@zAdyM z!QY%kwo5P1%zHu|&@rn*W=)cRdd*b5TS_m_JhTi}2C0N)pnSw|VhGi`nf|X~iyy6( bkE4Hbjb~8CeF+Kx015yANkvXXu0mjfwY)(8 diff --git a/editor/resources/editor/icons/light/navigator-element/component-open-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-open-red-12x12@2x.png index 1d9d5e41f744efdfbf68a4935a00d4f57bddfb43..0e139b56b10bd0c73b89f817d323263d90333859 100644 GIT binary patch delta 576 zcmV-G0>Ayy2f7C#iBL{Q4GJ0x0000DNk~Le0000O0000O2nGNE0N{5$_^}~~0e=De zNklAUXM-B*S zz&>BS_jn}X?)$#nU4jsIHhImV47X206dSlkn2oW7xl~xog?La>C;BD=0EYlsVz@P+ zUekt5zV#7FKX4i2Sy^t1KrlG*!hZtaL0(3dPv#?%UGOzhA@;4}Dkw*g5+37SlK;|L z-AVnC)U%))LV0e$53ERu9y4l#45L%K8q95Z(dNoiP=;YLwGp(?YKlL$^z z5%KZ`PYR5rgD5=KZe31k#>*OG)ImOrZs8d?NU)=eizO{ZV>ca^(%2%ZLw^;w>cIs@ z9JTX>Qpg1BFCwT_+Uc-@h-ky$-rB$?VlffbMe20I1e>#?Q1=n}tP9*?Nc}!?x+tI= zYYalXKe4lO8NRNDfFbUPR2>tP`}F&VZs!t%>+A}V|XJoW%XTtKnO5J6?guZO5u zwI0R71x7mdzAo|-*hB!z2Y+1BKHxtQ{D<9x;K@gz&CAa7tyWCUyQ*DHP+i4jF*+s| zHyE9Ij^!>Y@`iv08aikb-qC@x&m@U_YE%0g!a;g8GoiRo6wIOENOr?QK&KXHWv0p) z#FqZ}LTaEfUa_{krYu1p`cxW};168# zxw7<^D5Z%3x$ufBKtensS-|?`LE?*lBliJ2W-Y&k7H%lo=|Aw4%PrGr!m8e)V zBp`1UGwB|qpp7z)5_$gdHse0GG;E$G)GP(7hcvcGOuSV@9=+viYR=v(%(M^! z{#C|wsGUe=r-YU{fr9`Zo++Ix>wjgnrZ6K1F$o*=$+!~`5f`d&ax_p#0i zH2mL2gc^ZgKw^U6HXwNc5tl+v#GNJ@2yaiXH}BV<*4KJh#43WNPx#07*qoM6N<$f*5(O AIsgCw delta 417 zcmV;S0bc%-2A&2XiBL{Q4GJ0x0000DNk~Le0000R0000R2nGNE0FBi2Rk0z70e@df zL_t(|0nL_yal;@CMR6wZ2#ml6WrU8v2F(Wb2K5HX1|7j8v>Ujcz}Y~BMmWTgKsdf! z{+;4ng!BM^94qyV0)W=XyN|)g1ZREu*!$3G3;9MC0VN$)LkY-)4K1#+#qUP~YVUz` zp?Ri8Gf4K`6#9WVO+eyN5N|yNcG!s102K~=!va?rms&lns4qdV<}<7~{xC}JPtrh_whC^K z(71$&Oi>A$I2dONw-OQ@X;@fNOhIi0q{X~0!Z;|ACm~5*4qG}DaPn>mFI+nkSNL0{JN^Ar@IaOb*M=Pf{H0W zYc!O?hB2tw<$+P?9p0&MW&umQ#bJ|QIp@vE2d^*)D6%W9ug9T z&ip$DGJl=JCim;kjpR(2CG81Z zE@0^PMsC1^#twg5T$E5%>^$NZ>i;-RYN#wI|D5+=YB^!bnhWBnj&On}9r37}CB-RL{N zi;_gIfH-5Wjh=LXaF-AcDJ@vP`;8#m}4m^sS2N>KoEBC!% z%{V9~pZa(#j9!150i!?TYu81eEDEB%f93#_3PZjS<_;_PeQ7>hH>nfg#J08AS742T zA$7w$TpjJmxc^nWbW2zWM=co>{91VwTz%A+7<)+;*$l)Hx=TA4-NQu@5I1AE~6tn$im=d|+ecHGamFN6hQbt_a0*0ETJ#;y zT$vmr`vEJbwXe)FA~etrC6eXcG$X52locBssVqvNkl*Uglb@tkpZT2%e)fl+xkKP&J#HQuo;<(DTq(h1BmtT{J@wPi!;rWaxAx3Yo3WI z?>XoocHx6FQr`u6w(?T5gN5SR61t(b@KTBq!?w@gZ$klKO>IG`6FuQIjcWz4Aebb; zGc0E&KH1wZh|7QHROJ~_0}v4F%*zLtHTiqk!N(Q(ThaklZqKg&9~?q??(pZxtyoblW;)6=v5uF%>b_ zGG9CIfXk7al;5wXnYl2Wb1gxmkA@!E!9=|)zYswk> zmQReawaIG*E``LS)t9Q!g@OL#Y?|&y=O>fJf^uKVcJxK`5D&R@_lbW__Rj$fArII9 O0000(|VL;&CrAQOBhxCb7!BOo@oUwuTv0UY5uue~kRwhV%gJ%E3X(0RoCtfRBWonwCM zB+wqKRl^A0QBD+Wx<;KSQ+!SukQ~vAji^B|JMhy0V|{~+y`>&vh^By>7z_#fG1~`P z;VCf_#&ZP)@4CB$9Z|TfO$frIia>?WJG@3l(JD#1_P!0QGpv~ioMDQwq>#(I!03+3 zDY+aXv{(bP7ixbBfCH9qrI(=sj(7}nU-(TmINJoVkc)90MIC`M1f5O)v4PUgHpbT7 z>}lfNl1I$4OhJ@tB5~i|r+$fWODDtBc8fSgaepM z#vAKWyJXmM;cGZtdRrv|Mgk|dcsCKpzNX}DI1ZxF)S?IawPltiW8J%Dx``+`I_fCA%JbvA=b00000NkvXXu0mjfZ6ey! diff --git a/editor/resources/editor/icons/light/navigator-element/component-scene-aqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-scene-aqua-12x12@2x.png index 56d6e5d8b658100ecbab8c31704783d13521ccaa..6fa0aa3202168a10032e7798966fc6bc4fca2c96 100644 GIT binary patch delta 681 zcmV;a0#^O@2*wDossVq8Nkl5U3zd1%V1eDlo3VaEJ`} z035)FKm?KtdCVNUfz-dk?BOBdnK^iXu&Wjnt=}{adjSR<=7JKW3nfu2-Jmet&PLJ7eGjL zaqNV)O>)+V%3>UF6E&#G38?}6K4?XxZr*&e4GRac`r&`6B?DhALQIYWb&<^h#BmCY zwhPoJqmoYf15Sj6zl=Q&lxdcVy}>ak>viOt&Ew$BX|lX*k*Sf}6h;lK`G#Dmu#}?% za85mWD`$M08QrRiW}uXrGmmFAk(-X^F;*H*c@Db$~@REmLpj|C9k%KIT$xaKOtulrrZC+ z@f|7kj)>BGtVj+t;8M$eFsC+f{FiB*@vP_ha|IzkBdx!Zng;ub{~!DT%~m8_A*ibN P00000NkvXXu0mjfUcy7Y delta 729 zcmV;~0w(>&2=)lDssVquNkl6v%{dUc-4=zVAODvAqNMc3US+ z4}go1>Q_OJo4bG7gSr0?5+Fs0SoOrlRblKv5J303rA1Bq6qPzn6c@!Qlv?79d!PZ_ zZGMrTh8~|0vBNsbG!`4SRdniWRdcSLxYXlX8${vC#WEA4Z1e7}2K0G(;z7s*^;dlG z8Dx*vrH<01&K+vL76L(M}tIY@vUT3gP(U!JV#nz6Z<#P?HU~X{K;a z`t=7{Qw4t$t8judGhA`Z1JPvX7PHBJGnR+YER%sZHr7SV>`}x97saRio-x>zaJekTjn0jnGesH5jfN|9QgV@w#M#ZhmYiwT~e!yrs~zFU)L!0uS@Ehfo|^yOlgZ$kf9ewOdcAI>)9L2naL{MW0xU0^&31o%-w$pIP_0%S0M?

caQYE}6Bw&D9*=7R>=ui~CRCqi{15t2 z++DPCUM`p0i4{~T6&u?Nbp+|JR;x}B1ff(!Cr8D_BRKD&R4Q4SOs0e1bxDj#d9ey` z*c0&XbUJNntu229ol8Xy{tp>gG7co*Gi?B_5y*v2UohH96&$#ukN4R0cDsF%%MGzc z%jL4gifCh5mS(%4_QXAe-$yEF(@*|J!24JQk>HX-7(E!w;qCyi2WDAhS3aL_AX~H7 zM=I0T@HxtzN)R|}1mHfRv9QIJ_rP-{|9i|9I$4!S<+OjgEU#qCZntCkLnDEa!LHX! z0C(yJnaySaE5JP+Spwj1>PER%!Cy;a0QB^DS^NF|le!|X{b2f>ib+$_OAAd&x4C*_ zLx9!ggEFaX4nV#U(E4*Omy7%q>{GD{VB`yMTj*93a7)R9ifjQ!oo~RQ4YIHCo^W0l z6Hg_ys4IVa6JXECl8=S#d6eLm(H1QfeWVR+1NiiC-Vu}5yB1L}cRJ=XhYSETQ`_RjTpCVbl(&I62?mg%J=02s~S*&9U z*=#mGo6X9WW##aglVcyNes*@&@qIt|F9HBN0500LU0JW!@tuFhmNmw^7Km#5i2fl+ zr_(tYeKWizPzPIWGMV^65R5aKOddLAtej!$L9f~C^*TEV=<$3$Z)jk8w_2^5h@hp7 zlF6hKi^az9cC4Qxkw_JPiyDU!ou8jS>WH=ksZ{C}n?qpib$I)O-m(TDb_FCW>NKwP z`+ZLnMWay{;M9L{_#SDyr6ZPrSFkb{>9IuACJA(E zgTbI`i(ygrl7KT^&v>p9j5WZzL#jS;LA4}xp|=(2wrN9KVwjk=c(e&!=b8p$Oz{zZ z$t)gIgR_E=P;~v2p|`P*s*p&|9rFm!uSlcE+5j}pTuXmlOvy1tjKVy$!vxdm)XeWK zR#To`tY?6?;lA8j&@tEBs22CNSQ9~1$!0af@ts6Z7h(R3=O70Q< zBoYZ92Vd~l!JfaqzK&m9T)cFL=#Wi+US$+nI#*9l#Hx(dd`sII+vi%dY_U z@cJ{I!W??o=xVQIB0fPWZ=}#OFB9r0wQXB{cidZp%rypL2gC(V;=c&Y{6g7P#*Bw_ z5Jepkwb)sU#Ui`!QrdgrghgK_FuXr>Wn!y?&&u}GC-VYe7o&&-(@k<@?T}af5|Mw8$eB2}r&Qb{m4c*d>X(tWhcd@&I_Md! zcCofbcwE+!BdGd!1o{zzJIH40s4LGzq-(pU4V?o$sl(GOhZX8nr=r*Cw4B}A~$@}Ir9!F=vexEzgR zh*clibVVX!+bT=7!rdP2yJaNO{x2CfGdKGY7-N!^Dj-shBd47#Tat>6x|E9Nn&!x1 zJ3K&4btxp7r5u=e`gD3HOa~Xy#l(*Rxel613kH`!g=2rF@Ke-c2e*-0WWK*u7h{fC z3g?*7wo7#~D*2lEj5E!`U$$fif!-ABJx-a%yYRzHT8_(<<>iP>jod~sY8Vr&Ar~qx z<=qD8QJp@>8sBENW=8ErpiG~c(p49^E$_{RLT-DZHZ~#WatDZ9Fofkg1*u}lHP}ES z2i(l$UzdNWZM?#^Ju2oc zkgA90^nlj#u&lgH2f;vkO;VrIx`LO>cCrJu{l*oA+@p5Um*ISM_qGAjVc^pvbUlpI z9e!{&jx6gVDJ6FRi>hfPE}_=f9D_Ym>_V}Af; Wh9mF3SFOYV0000Sq delta 732 zcmV<20wev+2>A%GssVqxNklf15$x;1zcAER!qd7 z;SYf&Lj^zwbO5OUIxr>hk;HJ}-p$PHeen#6WM!nwWADs4yEA8JfKN8{SC59tXI|pnirWN+ zK(4bhG}Hp$RwZav+3^`5rG{u-Ob!$9j=fYr5k$K)LrTpEuQ?l3Hw9#Aok_x&4H{6o zoIo5w`%mGCVuIT0ojwZ!Z2TVWwktqfgP$wMf|%RDn}Ssnoy;IXiE9_E?@Y`P$lOnHydJGM@4fUAp# zfCSV-vM@-|Cb*^W0WCtn#CMIGozbR|&%ZIJh9k4Xc zF{^2Zq-@3Tnrq-p)A(dNMUa=faE=*e{j$+LIYA)l5c$zXbNiz2W5#`}=8naeFKO69 z_6R~1Jb!-_?XvqM0S2W&qGNiTJz!Ck^sa?;fbgAQViprXS%oNVcg*VH09FnY35e-O z1W904)K%st>HwY}_?cl$;AXlOh;Jm_;_vGhS!apL&glBv_o2nWp`tj((^J7<-!?T% z?6qtCM!!li4)^%PFsTOh=m!5e9lp7zmhK>GfK*gJZX-cG_6LrwgR|A+IY{Xq+Ub!f zYq_~SI+S)U-szEPhsixojZB^$X$;OEnTLox6oFJF9yqewAJI_ypY{iJrCXr?Au415 O0000hNqYaFa2=Aql|HUK`xUQfmfa&j;bt6 zDue!|gz=VE08(d_Aq=bnM5X8 z>oE@uohEc374wbY;v1_4pmaa7`!sB%x~TIVhHK6csqKG0@|0HzD(BXmDHZd>a?C)U zEQI2}IU&&br|*0@w;yny<;C*M%L{Sm8}Ov&Lp~^7%7q4)VSOcMyl0Rfr|3Z{z$2C$ zfLjDd5*zkGSw%6BurG;KXY_Q07vXA(vy74Q0*1_)DUNnr3NS^jmrqz2ux!MQL_k4 zGMM-iN;TfmAC5JIi`RwlXkq0{p!cZSggMKA7UYDTlKrPCTM5Q9fTzcR|BieDNi#yE Thbm#n00000NkvXXu0mjf!DA+X delta 670 zcmV;P0%84^2)hWdssVp|Nklc)f#qHQRC!B_Imxh(3Q13hs@I5~skMU}?N>36<#52n&rvoEYC+^v9w>e2HpDA9)77RO`a6;q=J|mOV80@}Rb0CU zxja230$_rD5q*D1bT}L~5@?8%PaEP;91#l>-Pmfio?w~^SPH#@!yhVuC$tIB9YN_s zUt$P(fvE(=(KXjr6qF1RPVC|_HAu;g5Hm2XUx}gquBix9V}TdsaDGOO=By3YJjr!X zaqa0TY-6KJ&~CTO{6a7B8cRe0lxf>2I6H=^lcJxLhWUR)kctdP4v?Y?B@zi~!}?9N z@2ldPGenLZpxcVVu{+F}(l9?PwFE3C3vSL3?&Xtz`IiKejuh(QUzo8oOpS1EK{wpX zLhA^zrKo}YksUg)X!yQ|`5$aPTGWS~wiw?fuz5cab4~zjjgplo;7}8yB4T!rIKToDp-%Ug!iMhU|$;0uDAk1^;41!RXj60f{&oD!pC;Ye&%s-%mR1V1F!v zRu36e4@`^NIOFZhMC+m7l8$R=VBQ8|$}yt#sJn3JFt*GbY|(nXPGrht<807*qoM6N<$ Ef(M&2qyPW_ diff --git a/editor/resources/editor/icons/light/navigator-element/component-scene-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-scene-gray-12x12@2x.png index 3292e8ab98ae100c004a701930d7282abbd72141..6caf14aa044ff10552fcad8eb39ad2fbff84bffb 100644 GIT binary patch delta 532 zcmV+v0_*+N2eAjRsR4fh@<~KNRCod1RsV5feDC%sF$y_@Y+;28JwV$XY2ECsbuFGzEVqG?=U@(7-B5k}Oz! z80R_jgf~r~i(M)@!6v*nYZvyhrltyb!b5e)S5&liven>wxd-Mz@TiKARPI)g zY9YKRSq3aGs3>Hu}y3`}2I6g41q#|IovotBOKjQmS zbjFO_3N(;_r*wbo93R=HaunKKHcMb4O~CA>AvKc%4kkbZCT?BD<;dP9RHFg4(;3|& z}Na2h|6#sR4fi7D+@wRCoc!Re^EBFbq_<4nQ{u8^8u(0$>8d1e6Id695w= zOi(t!od7m~5wZc*H*Zdagywq3Rd+haw)8K_jx6$GiGDM1&UK?GnqRNiM5hUtPpVs0 zultuj5vXIVz*7bO&}p~9tWe#nu9}FV8sJ2SrHK~e0fNYNzfgZ2>-W53ldJA@&({(l zVjVK$gy?pNFgVc$1cjM9)v3WmMvIV}X5u*yQ9yrAB=)A9xegPO2yL?p#*hD-RD?B;%@WAZ1l=+tM3+`v6O+YFI`SyC zz5^+5k`VC7>{70w{zKZSxaoLGVxXbZ=6<_f>h57Q(bs9jBZ-X(=6f zu{ z2d9Q8mhvz$8Oie}6a6W7ZJ*2rqD0CkvTvgO5ct{|j>I28m}5a9%pJb^1P zt^lY2Q-SeQCWbLe1)&3z3QPylL+}vvv)MgKAh7s($wRU;jJUh+zP-Kub`RiRH{1uX zM~*!UR0DwC0YN#Lp77S5U%T(`+mE}5p8|Cm5j7cPZ-Grg;n;sLqRzbHP7iWW7bmmt_XC{~+SM{_| z%_FcTGAC>7*P&ygF^s?__CS1cM6&gDND?D# z%;Fryp^FFzJp^(XpDSerJ4_M$5VaT~ho7oN^P-!oOE9}QOgO;ipS89doF}c4MeV)< z2bzMvY`G3dL7Xgv*RaRPfR`Fd;N`7nWh(NrMW%YpRSB^grVQ&yL8VeIGG?OzdYq>> z!1@m3eZYS*#q|gdOcxYDDJ`fJ`b$Wp2ADj?aOHBIfhgf`Hf+Lx2TP{c<3T=Udn`R$0T?m7;Y<5YjED>F3?Umt}@t_nO~hY;;PJbha`17 zuMWrNz$vRpm1R0o(Kz5}~gv-2b5 zPO^MkADq+?BD|%{^=z2OEu(jQ1lQiGO~648vS!^m4SrxQ`NXHohycG8&8WYP`2Vp# XW{+n0w88I~00000NkvXXu0mjfp-Nxo delta 802 zcmV+-1Ks?B3BC!issVrhNklZJPTmIso2&&U&O~iq?!H80_0H4_ba;-8Y+x@a&b2!jVO49G=|IHWG-(NsKooqkw;7Lh|Dif0pW; z)~XN&LSoLhY@@KxDBTqx`pVH4c|-+)bJu$2M@@i)cnW{9ODV=8a_B3ty&-TW&2u2U;=@8EbQpg37kP2lY7k^kw;)2Ufvtz) zu@GqsAB6-72g}YwUuA)H(=<{~z$INT5k7GweFH8vKst=t(=YPlXnJyIB4!7Y2p`2p zY&ByD7VD>&20sfu%yKOTS-K>LbIYb)UI&q=?T_|sYGr>UB5D0tN_xiLhIQf8K$N~r zxuMR4&(8hvsG_Z5g5)NsyDt%Wuk5%vs<)>c#g9e#TCL+(!%}{M3q>$CCr#cG;-`d? zNBN&dhrXmP)!i%#-Vsj4JnBq6E1`peNSq}a$lbF2&?={Hli09>Nb&gLaVwj`#T~yN z!)~JBljVOs0@oCLH!*r)H4Hu^FzHC!&#gr2M*17Jh|Dc#(vp^T8B!tFe=^kUiont&RAas)x zl!2wA_8dCMCje4n^pvJ?K@eB;HKtM2uymAMh)vAn zMKDD7Yc_p5Pj29>&!w5$@yGrqJ;@_H0!vpe(=lX=BJnOUlawuVvmF}{%xm%bsg*i$qsvR-(r g=~o)Ql;D5LUnQQqZxU{v@c;k-07*qoM6N<$g7O1{9D&CX7)P*sv!si-*pgi39l!3Kg&|tZ!IuJDfZ2)@dt^@3fUP2U53ev4o!s$rt#|aH zZ_>JT=PN6S?p)Jl_@>GXmw3X!Hq1;aqN6xP&x)1c*YXausq;LbT}S;Tsbga+6%c&n zFNgN6>ERId_Kkl_q#^}3m`PxtaVk3AU5O1V3JDl%VuFBRut?iXQ?&} zXlr=_diJu1RU+U<>zlA8p|T}^#F#+R#-e;n-Hdmq>!^PmV1uxy-#uFzbGGEblY(7h zvk7AlJBa6Y%y&|j5cm^zlmP!&RtJ#2Lh1G%+Y#QCeU_oTv~S(LJe1N@==K|lf4Ed< zg9BBea(MyfGxEVFmB=?~YV!DnxO~rKhd39y@mkhH%1?bhP=)CM5Z>(lw=J5gx;8G8E^d` z&LU77<@Qv)bpbN)MX{%rO?D6li`myMIn?w{mR}y9@qqC<;FlwR0p4RI;jy|M6951J M07*qoM6N<$g60H7q5uE@ delta 694 zcmV;n0!jVD2-66#ssVqLNklu30tmiVLpigjrWYt&Cr3Cy^x6q?+t>X72TFt&mL`CfZ?Xe~b;j8h?8;M=PWUaUI@Yd@{dggp%076u zC;*@gkzs%5xlHzW`sL>W6zd=iDJeT1n%`v9c2s!1z`A@E<;^vR4k{{*qYRT^qyTpa z-MwcZR_0d9F76ZndNrA(_w4bjB7p=dKPI6brM=wZlHf@gfPO};Ia;(HW?$j39lb%U zL~K8qsb|((KR)iTokP$EXjpB$#wQc0)+j+2$=}5ssVpmNklTLbH;5;2c0S1>ee|I{ZG8)Th)|%0%5^W#{=Kdb+SJ!5!mT2dS+PAMwR?T1{zm92k&5+TwNxIUE zJos9OL&UkxU5kIu2@?Cpq_Q3`Ms*oDd1>JkKX|Dpl1-w(H=Mup8HsPHtch-4bN!{f zZSdWX8RTg-gFxg#j9g-&oJ6ACU_#(_p)T%>&sqqJ0HVFrMV%RSaE#n2LAb;;Og~x1 zK?umyOSyslb}wrA&GbvP6vTzP?)L#SafI1-qV1ITBr1R5g?_@3b|{0twt51G;<8@h zkQuzF?5QlPF?}zuL}coXRf(X6oX=PaDwgtg1N1UIqr5?RuLQ4aOf`d|&x}-VeFbl$ zD5%0bd8mP&`t*GdGEJ@IQ03Sr@XajPkYLx0$QO$*o(m;!N5Lctav?q~(c0#ua#} zAfW=F13EbJD^eT@Ixr>hGYJlxx3hD1o8urTl9iE8uzNG_&AyqN1)kZ=-yH19wapW5 zokNeyo^G%COwhv8cFpFW2<#WvF-;5zJmRu_#BIxGL89?7q62>d``~(TxR0{+wxs76 zO{@vDwcp$|_PDM1%;+<>Z_Kimz-NpGrcsd3ZcdLy9z?l1e&3T6F$pYv1_h$yiC*9? zKT%2W)jje@0O&NK(h6Qb_N|#kM5z*WfCN`@U*ToMBQtW=)x-aK1ZmrX_f0J4Mizf}dyA@8mdv%CVH7pP1@+ zs5L*gC|jlkn|y@S5p41RUEd*mrPtb`8K3k3ICNA`GH*#Y#Te_7Any{oqgJ(kLt+~IPITDW z_r_yZ#&wee&rz1rX7Oc`*P~bmIj$I!qAc{%kCD6{^%u^*7`-Th5>Cw5W+9#R#PMJxYlH diff --git a/editor/resources/editor/icons/light/navigator-element/component-scene-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-scene-lightgray-12x12@2x.png index 30582ebf7f59574fe4dfa783a27510f4e267ec59..5f1916918243afdab69bed885f7e942bd8e025cf 100644 GIT binary patch delta 635 zcmV->0)+jn2$=}5ssVpmNkl$<&CskFYx!E}E*4Pej!aHzx)_@3u^ zOEPeL2fm>)qO)O^BUdxC*{li07X?n>dZkjSlVPdwYwdQsC1t#Wc*Hx}K)#yK=bg+9 zCX-1K5iEoq>;|=X0s_E zniVq=@R*JnvDAM)fbJ7@pzFgXlzSrqB{M*I4m=V06%HQ}F&j2FhQSyCw3!ig)MWL= zJcivhKVbJp9uBV(8CW6+jPK0nK=Y+lsu*e2))Gk8)}Oa!gCgj%9Sx8Q4A3;kea1BOb4X&;S4a{I* zH>lNWOO1Ex59jCzhBvA5Xo_(+!2iUfS`+3X2bxgd5I{|Q7DdGWiDv*0zXSd|^bT*O VY%E-Q-Vp!*002ovPDHLkV1o9#C}RKs delta 655 zcmV;A0&xAA2&@ROssVp(Nkl{D<`SBrP*2pJm~i?5eoB z2DOZVB4P~^@nL`6UP;1~V&`)!hRqhSI8}xvjOGHy8eES?qksHhKNTH;W(1`VeTktl ztwhvp-R0UvA!`+KI@QHvYM{F#3Fowx`Wa={`1__MObv|tN;Saz9W_cZCWtIxuJIqY zTqCy&t+eJ?T)w&85Mw4$vWO)JxVun+pUfYu}S@0!c?f0vJzVE$4*0j=V{e0C0FDgXcg07(Z$PDHLkV1nilF%|#- diff --git a/editor/resources/editor/icons/light/navigator-element/component-scene-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-scene-lightgreen-12x12@2x.png index 9a2217441d75a39d6b8a0448738570ebe45f0f48..5c76e7da4d75b8f71b5eeb318598b40680170577 100644 GIT binary patch delta 677 zcmV;W0$Tm?2*L=kssVq4Nkl|~Q<$7KL9YWOgjGWK3EKw95Uh=q~Bmd;V6*vO7KhtR&s6el31rkOF3w@^V7`Rkl zNv7{^n>Ox8TMyI}L>kz^Mme!o`vcLL0N1^`1U$U! zbwXc25Q{2GOoE*Q&B!HiP3+m{If6b2D0en7+ZN$L;~Rffi^%rKtHmeYsEcnNLa1U7 z`(m}-lRm9gBFcG-JuSjtw$cQ$XI!)B86Guyx*bz^>wgG+l~=4X)w50|tQsFX)dq(7#Sh;cAf}`#S%KK_^odE})sju#!2$inGN>RKb zU1pXl4_<%q`-_?#78xEsA-m-20rS{`(24qpZzeG^bh)t@`EY|9Sd)!7P%!2+mCxlB zy-SbT$d;v+t%_6KHD!BBeh;t7oR=n0D=sciS?8dJe5U7nR2oHKEk-JrKOwUS@pk^< z1c_c3t|zpm+q~z&n!sKOLX)eL#YTN$(eR99S$rLQf_%CQ`2VqAb09h==GJ>800000 LNkvXXu0mjf>3%mf delta 724 zcmV;_0xSK(2=NH8ssVqpNkl_l2#VEY9uFMu3# za2V`Ejy5jv|e&Bt=9s_ZbNS0e#!OnD7^>o+v5WTRO=Nuw- zjTP0phB#t88nj?C!#ZX2xpB#V5xi&Dv{Y*oWj(w$Hn^pR%=CW^WrIyb{}6oOOUbk! zvh_}8ZUC}}%mI{sWOtg8?UsDTcqTXId|pW)8P~{;3PCBJi6x%i7?%e{{IyB6Oob%G z0Mr4bU4WdTbf3bB)&xg9c*IZB12gJN*8(IxSdxuF)Mlasbw{un+?p?AT9=bzthE&* zsS_Vcd`@u8u7`i7UFk+k*h6zmJxKL8yeHa&p~QG1GgA^I(05jkl^+pVc7o%I%mcuk zfJqOq*FwNMd2qsxtO*cG+Jo;52{rE#D;P?yn6Pm4Q0qb#xg?QcC+vyc8aKw;nUaV# zf1-ayj1a#^CG(~6n}Hk|J|6SMn5j0jlr=K+V?`Y2yK8?xjzk1=^EoNv*)qY8LVXc- z2#ARS0PyJ{qYS5$|M~f*QabNjZI-qeO0l>z{TLbV2O`aP05R-CMQ6p*RoNcxVE10r zF{Ip9Vn;igr5Cns1Py68?Plt?OrIr?a;W^ECOZ;+(*~2d1$E7oAPFO+iXia;E|Ooy zEb(i6suF*l9q~n61{Ou>>`LoiP5GX>Es6xWLNYRW#-bi5r=`kCJP3~hK@m78DogxQW-*+OaG!lgv7X}PsX5 diff --git a/editor/resources/editor/icons/light/navigator-element/component-scene-lightpurple-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-scene-lightpurple-12x12@2x.png index a90460f1eeb70b25c06ab7a5bd26d0aaa318f97f..65446d74f64ed3d6d22a1ac90603622a576505fe 100644 GIT binary patch delta 670 zcmV;P0%85$2)hWdssVp|NklKK2TN)Vgv8hyfVRx0PG@72*{d!)vfah-JF^6BVXH| zS7w0=)G^cb5~s${$1xHMFx?j@@E5mZ+aq|o1{Yw1BtA2Vu30KR!e}PnWRDEL>)wiG zTw;EEZ3lZ9q+{FS;-|bb+bc9MWHt+B1Pm(Ky5Iztdq}_7h^Y>hm7Hhb9Y(`Hnx9rWmJGKBygE=F5ehmCRSuU*kM3Ns{tA~!5@UCrflSL z7fj=Z^*t9x%GN2XOiF_{&{V)Be#<)Unv)6xX9^PF6dUD)tZ!`YF(Po})J1T=)*8?y z;GLx|_M3CKA;(ZlB$v1B$HwK}02*X#a5>7_2Mso!*d1Cs15lD#=}&0p;~oCtYy!R8Dvxgq z`Lp2_F1;~Isz2!s$PLI1@CiarfRWl%{S|V8 zzzG_DRSJT<`{LLYq+jg+Q zjRktJ{1s6vYcWL&Su`~HKM|xqY$pgYAkc`f?FP3s0wneflO}(nHw5X-_IP+#W?Oh= ztYCr=D*~<4N82|RH+wz-7EIEPye11G}(rjYK(N@45^SXZW4VpG+BzoyH0#GcbsH z*XEP_nEg=B9MFiqskATpW^%z$OxHFg@TL1+`z&0RD;tuyGCXMw&#oMaSjTKQzY2zr z4^cDi`D+O-)@6n-*`r<9EoWoUW;+M;iT4624y~dl*Pwq+fS79h`^HI zQeEtP5^0_IqQL?jF}7mGLB;kr&PyUmmII_1&N+{(y6)>1;slf7N!FCI4o=j86D`0y z+cAQ+4*WE$e<#fZ+KxhgZK`MP*26)Qy_L;u>IibbLJkq+K0uxv;;lRDt3(NsKG?Vp ztcogj*IIuzKox_wDha$o7@!%8dZ?Vpo#z5ViOxO294xY%6AvLe#w znZ3hDRZFZy(9b`wRK5dtijo*^fF<0rcLG)`Blk+fR|>C*P))a|q%b(UP{TiVkOCj^XM-PijakT!C#rvpPWOunH*(N=N>z$c zC&0fo5)g&XqhFZHdhXzm^>vGp*bIvtX?t8{w67WbIOT_#RWls^##YUImp3am{qEFbgR~WD% z$@_7P-8mOE)`pF1fEC8u3p9n1*kql>pIJ~5pW74Vmd1BkpI)lnl^U4C48q`txa%BO zqP=#|Ydt5=>MlFi#$i7Vz&eW(ip5R&jaBMEibyx6$hm(yFztxbW(SlLjr)Y~*>nrj z&$=ZA9^ZBs+uR3H!Uoa}O>g^LC(|Vi{019}#$T3o4otB)6)*6BaE+eWXA1O*Fnwt+ zSK2gfw;7Vcg*@0ga-r;2UK)Ur-oi_8f5*u=aGRCyJk+YPHc95 zBIE$%(gmV)G@2_ZO4B3;ZOiG9pOMTJnMpi0swOIpNw!xor<$CeexU=A<-wIvmch2O zz*yGv5-Q8U5)7wkaQ0PAZM?NVoXim)d`0>6*djIkFyNy1gS#<-jU42h9grWBnLm|` j5l8=lfrsmW{~!4cbYU^Wtj-X600000NkvXXu0mjf86{D- delta 744 zcmVH}J})UUI01 zCb-u)Qwl|6P;}cvqtGsFW6=De;{PJ3g(gfi%KWp+6|8WZkhp)Rw$WHc^o*eP(a1?J zGp7YX23(EZCk*Scnp_;15(Ce2J{_)Z^OqVdC6E)F0&X)w6aKTSG`i?G$Xj!H)DQ60p@DIPjDkZt_KnK1mw`U$LvAlYNR@tmop+**`ydT z1tFkm1a7)e;j=vt5PCFqAl(KD{r~@0C#w*)8f}ox@d=s;Na?4*Nuv$*#7yRMq5M^M6$=ss4 zMACs=Qa^t}mJ!50K)$>O=Mq5Wl$=ESUk*%^2eyhzXV*j~Ko*1X!z_VS2m|biMLjBE z0F~p2ipr!H$@$HIxf+~1dwv24hWHqVX$c-V*i@QDDA%59xs(eb5)~pl8Wy!a1NMrN zm?Rx9q4;wD#%1Et7WM+JNnP@LcE)EO6W@>7Z+T!l5}de;7r2;#j1k|Dr4LRrWx(Q$ z9}uM78mXQr>tPFrs~)A556&~9`D1c|HBTm2o42~N@sqiX2n7^5>F8Q8cR5p5D8{ft#p+!jP8 zQ^k0C&R?AdHgA}A@kB?=3P9v|2C7JliwFSR#BUo<5}4%-g2{hEHdAjxulcA9N3`&Jn)heo&F@yg=pBpz${R5Fl4S%@u`2wYnm{pZD1uKS@5u|=i=bnL z{f6A7x@aN~tmc1s-Z>(PRx(R%MPXmx`KkHlH3)BN5eTCL*|ez4oXD%SLq3W!yHt4A zj&Lg=@TF@yIFuN$@*P1^%`Epm_v&q{^r;R_Cx=~1ws82f0C-+zmtCGhxTXt+uGq&f`joSbh6vaV7Q3=8|;J^#1T>KlUWS3o3Cm0Ap7Zp4qS1cK_N52Yr zT-tJE3}RoQlryY=4;Niuu-^BMNREjOf&y|Ka>jkd_axI4U3s}z?^6~PKTZ!4c#?YK z+JNIE*bP+*~EWt1Ok8Oxs4)PB~ eG(86Vf5s2eBLV%f@+OP`0000kg>^ delta 631 zcmV--0*L+Y2bBo0ssVpiNklt(} z)|NzHYS%29eI29N@;kGMtyY6n1UalH%?xgOvg_vh%XsMUWAf|osj4$%35|Fe$H z8rKH@>s|u&I8=!dyrT_~-?m1oLkA{FqMYNkNFX_)r#7O5VD`>;14e%R!n{R#ewX+L zNEn+sj04j0bDa=D#}$Tw|NfTkohsZT&+gTJd}sE!xo3NDu;(ZeiN{N`0eILM2^?6> zy@h2V`e~y0hJ}B*g7F?O@#-sItfy6!lKCZ*grgLTwJ0| zB(0%|1SxN@R+QTCInibZ!i8WYVKe)yrll3>@uy+Z?nm;S<9=rc&o)|S$E4klfq^4! zAnozBbGyVVo diff --git a/editor/resources/editor/icons/light/navigator-element/component-scene-white-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-scene-white-12x12@2x.png index a5836e3040b4e6bb345ea36a02d93ee4fdc7a13a..29e0dad44238bd322262b378571fbeda058b79f4 100644 GIT binary patch delta 396 zcmV;70dxMR2CD|JssVp&Nkl$M_#a|Rc%&=*s~_>Fm3lDo)Y z4RQu&dA_K5JVk#wX+T$mc5~1{TIOIY;|1uX!>YK8&>&3S$~Zn~L)7;e4+pK2Sn{AX zkYq?MF1lW9N1DPyWxk>U_lzk~&ZJ9m;gFFrUwu;188_LC9StrB;#5t$4+O zIMy)4brOX`!^RyUaCGeya6}uE5Uwu~s8_;70hG3X6Et&sfZ)r#8TSZMv8_3VZ1+?B zs;`dy`AsU<+Kzwc*4nb;9D3QGaNB4d?e#$1aNB4L6NIb+W!sO6NJGypo&XmnuqX#r zuZTKDR2zsr_BplI>W~6WO5uRA22Sl$I<6=O;Ea2ZL!5N?CZ{v0ZT^(ZQDCpZqhDsx l)lY+Juqd?w$NS`c_ys8$hVGi|ug(Af002ovPDHLkV1gEzw%z~$ diff --git a/editor/resources/editor/icons/light/navigator-element/component-white-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/component-white-12x12@2x.png index f7d2f4496053c64a0cc9f7f6ec0ac4e8aabd9dec..c5799a8eb139f2f4852772ca042417d487bdb684 100644 GIT binary patch delta 307 zcmV-30nGmG1=9tvssVo#Nkl3czDaGDV=5^@d)jX1HHvxsR!&J|A2xPawZmlQLi)|@QP&)0t>h{poxW#*dm2pQnt zTYkQ%7eG(39z#%o&5cOg<3h%XEk6>;1E~enf8>lfTY#;XjJ$~W2d<7cZ!co+E7i%Kgloc@z#6a~f z8_SazHrI%|;La-(LOq5tP}bRnF^b81$>Qr`+eZ8ocmfJ{(TBvc@df|@002ovPDHLk FV1hgmkg)&& delta 333 zcmV-T0kZzn1?>f}ssVp4NklboU=ediW{WSJ%{v4e f_T4TzlvcwN&F%rN$Bu`y00000NkvXXu0mjfb0V2% diff --git a/editor/resources/editor/icons/light/navigator-element/div-aqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/div-aqua-12x12@2x.png index 162eef743a305abc60595a0215b01160ea81357a..5d5194276973d30f15ccd2349abc8cd7612eac18 100644 GIT binary patch delta 153 zcmV;K0A~NR1iA#UssVp{Nkl2tWc-iUTYlfejSEh6F5B0#Z=Y zkSv8e#+CstZ^$M0hnLF|;OkK8#<>Aw1G7gCNklrc424fSi4lxo1tZvk3E092RxpAQOrkD{ zM2X1NNbWzXsYKVzM}yUPk->0$Bi{p_;M;mEgB=QgnfB*{s002ovPDHLkV1iAV BJ6Qk# diff --git a/editor/resources/editor/icons/light/navigator-element/div-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/div-black-12x12@2x.png index 2cbdc774c5dbeb1e6829fad8ffc9d0dc3311500a..9354ad6baacc0a53f40d2fc4124b674dedb743ed 100644 GIT binary patch delta 160 zcmV;R0AK&M1i=KbssVq3Nkll!C7_RXw2O{%PhA)mrr`mKA0V|4@m{n5 O0000TB5&>kwL zP~bxnDM1hSdGZhVy*B~%fXWRskIuOzEhn@QV~iD%{W=)RTkrka@p#7PfVd6B7#aPh zYTyeR(0~Rs@VfvJZRjV}K>82n6cIGa1BMVR)EfusUmf};aTg8d00000NkvXXu0mjf DH+?^| diff --git a/editor/resources/editor/icons/light/navigator-element/div-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/div-blue-12x12@2x.png index 6478bbe09152e0b8e81ac0cc11200eed9f38009b..19b501f1dd8bd7da2f5f0a0f595adab5b43cee3c 100644 GIT binary patch delta 155 zcmV;M0A&BS1iS>WssVp}NklJQ3;!1vbbEj6lZ-bd10X8G%vQ zf+_^N2}qO)1;|%ewk-L+Gw^jx?8d!;FBTxQNWs8?jsa7($ymmPr#bn!5MViI&0QxW z-BuRaxPlU1Mg=NRfeKWRSzuP=LcZEVQ23s!LoysxUgmE&0eutW6x&VUfkyxU002ov JPDHLkV1h8OKOO)8 delta 150 zcmV;H0BQfc1h)jRssVp^Nkl^`5QgEecM~pHO1iJ*VssVp|NklGe-jrAmXL9-kozd&s2&S0Sl8bDM;b^ zv1B3qt$aZGl1tlM(g%E(FuSs3`9>SafFW06*_{OWD`elg^th>9L0zT zQn1pdAN{xoM@R^H0mu*2yAhE^%ck*YBWZ%(IiA6sE$oKl7Y_G>_!2nS@g+fbD4>7> o3Puz}*hwY9nlDrmH36iC6Ru$lB-5znQUCw|07*qoM6N<$g08GKc>n+a diff --git a/editor/resources/editor/icons/light/navigator-element/div-green-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/div-green-12x12@2x.png index e9d8011968eec9c4626da569cffb8825bdee5566..7d057f3ce5e6604dee57a48dac442b7c3a467158 100644 GIT binary patch delta 159 zcmV;Q0AT;O1i%EassVq2Nklf!TQgq(UG9Y3@af zyR2=`et=kbS75x13RIv16{sMtfUqDE_NzSv$swH|1WaG}G(8u7!v$)h9nAcGw;TWf N002ovPDHLkV1gFVLO}ok delta 150 zcmV;H0BQfg1h)jRssVp^NkltY3mOBP5=M^07*qoM6N<$ Ef^S_vRsaA1 diff --git a/editor/resources/editor/icons/light/navigator-element/div-lightaqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/div-lightaqua-12x12@2x.png index ef2091c9c4095fc49dfeed319e35c16a879edcd4..ba71cb3d4080bab8baee29a15c9d92de091dbed5 100644 GIT binary patch delta 152 zcmV;J0B8TR1i1vTssVp`Nkl5*N}v}ymTMA3LT*%cykM* z1%)COsYURR@036C4g|mh<8K^eCRlz1(SEhU}{*Nu*ZS86+mFojw=g3 zKm{sLfeQX82xx_fMZx|o23`j0b|Y|whf>1^0#*|z7{1{T000UA07*qoM6N<$f&!sB A{Qv*} diff --git a/editor/resources/editor/icons/light/navigator-element/div-lightblue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/div-lightblue-12x12@2x.png index 5acf4aaa1b55b63537d0232761137e81c793f4bc..5b1dc15ce319617d0a104102f01e100b4bb6245b 100644 GIT binary patch delta 152 zcmV;J0B8TR1i1vTssVp`Nkl`fc` z5LvsC6^Y}n1DSXFlS%$Ne)u}dhhZ@#DU*#gAsA+I`k_**JG1MNFb0=96fGNtP0d+* zf5fBqA>n02AOaDHKm@S`npn71dkA(qJ32GrXg8Vsh6DbJ58e>NTJ}o-0000JJ8c&j5-#^@%-aKTAF%E~ zIvEapfB^;=VBn7djdUg)SkPS$MAH7l0mWDWxgrlFumGs#000UA07*qoM6N<$f?!@d A`v3p{ diff --git a/editor/resources/editor/icons/light/navigator-element/div-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/div-lightgray-12x12@2x.png index 8b015d7a8c8243b3e3675e935ff175a2b8cecc76..020dc2389a8e8da7f78c6d859b9a38f65c19d2fa 100644 GIT binary patch delta 149 zcmV;G0BZlS1hxdQssVp@NklrU z&?8E4co`Fzzyu~Rfwmw+kMt1GncLb$2boVMe!~qRQWV^ZTgnYV00000NkvXXu0mjf D1)Msv delta 144 zcmV;B0B`@c1hE9LssVp;Nklut~s36WRol zh49EI2M+yCeWhP-1&jxpGD#_QL^N?2@Q&=98@%_+UTDiMFP|05g?>8_rve#(o^U7l y921zp1Sa^SAVN>R6!5bcj{}uNc{ng?SOJEm6(m3ZA=3Z=000O{MNUMnLSTZxJ~r3@ diff --git a/editor/resources/editor/icons/light/navigator-element/div-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/div-lightgreen-12x12@2x.png index b1e3ee0df4bc40157de0efe23ebca9aec1a75c8f..1d9bc9ee147aa59b4db0553171f9b0ee75f6bfbe 100644 GIT binary patch delta 156 zcmV;N0Av5V1ib{XssVp~Nkl^`5QX0zgc%9QU<3zPKmrbMfCMa5LZ#q? z(9(u9X~IU!0J(3vpX7bF9q@H16s?_`0=!z-4oQ%zU?xrT=DRYC8N8&2d+e}-YghDF zZnQuq;zJoPBLWeKKm;PlDj<+XHb~tB2h12R9!I-F{maB}H~|!EF&Nx&7D!HZ1iJ*VssVp|Nkl8V1D-6I?cS+4ph0Wt@c;w;?hD2{ zl?G5rT2SF*L?8kYh~Reu0$J4K9t8)^nUX*bpJQ3n2uwmr$qLy3Mq!XhAud3X=)e>p zUt?RAeBT-PI&?J4lv=WwkT*Kf+Oe%j^H4|sfC~c5fcQ9 z`?~y)cU{0dkn>__H5X5ZQW8U$)KgcD%*U3yoO}A{$9GC0%QoPN3ono=7|`)C3s}Gc v7WiL47)dwX26Um>KMi7S18PQ%d1D2ZycQ%KGUj#w0000JA5Jmri_Kv_Px`8V=f}JDSIf5%V0%KUZ zhf(ATB8eqfXzo>a`N=&(^MS8JVHk`vPGfcsH4-4gLM8ffrH%I@1gFM?#N&*AV2d4< z9~<7)o%kRV@h>R6j0i*^0uhKHtH3vrMJBk_o`M4%q9Eb8<;obuZ@2(a5EtEU@+@Tl O0000WssVp}NklExzHnMmH|B-VF|?2V=@Oe$mJV8#Xvz zKqm2njGs|~3RIwi;sivPk%mR@qr znoI8OufX3$*CYAK^W4}SibOkmrnpAgnjEC1y!`ALc(m+ZHungWlt1e5u?%1U0~o*n r$^Z&blU%hoV7vzf34kyRMSnU;N9YKy;0SKuC~n{guFw%2p_5n>M6?Bwwg?{b zAc2ICmsA rP(U8d$WM3{4EaFeaxV`DN(no?@Dn6yF4?&N0000rFoaAtV**KQI{!EU>@=3)F%eI<6++JDG}A3-%^+SsqO1 V?{;BsQ(OQ5002ovPDHLkV1lR-Ezke} delta 118 zcmV-+0Ez#V1egS{ssV0UNkl-07VCu zfmFH)>I&=*UqJI9*r9 zM?nkheU%bfgywcgthj7Ybh1&e9)jDb240L~Y>maVD~nbU{CI!PI&G*!`~xj0#>J){ zE@t37#7?|Gh>rRiltpUb`VKWXRElYaZRltp9^82t&u@@tk~HKy=6l0p9riEqFiUqv z>-8#29H!EN%UC8e14FpEfg#+?!1X%{&S;lu!p#hJB0qpOCjL?fZf3yPRmy`y`@CNX zAJ4Bbdgvc!AXIJ!@(_mf9zs~{ikaV2`%;~&Ocr!?`PR+vmwGX|0ZI}54E}^y%lx37 zy@CCG2N+3>6X{KQvHe=F;)gTwSLz=BuNaT8aC>>R$bex$&nFx%nl-_j$p9y%PYNfT Ujq9+fRR91007*qoM6N<$f-ZrsUjP6A delta 410 zcmV;L0cHM{2Dt{XssVp`Nkl0z8foxu`#FOI&ZMiptIUz*c;cw@raS%VR$}0MCXO=a|A@Kd@9ms1|`^~ z3OsP(MLe}Ke@Q79h1Gzrw!_2RAaD6v{Jnri@LpJcL@z)St`~4Ka56aYGHeJ}GSOIu z3doz@@QH`h-Uolz3=mFMmr@m>uq*H|Y~j_q$HBovxfq)V5S{WdWB3AOD8LNEAlcl1 zvs96}NYfMUwe{aO_%OqQdM16Pz8@dwcel!;K0jqTk%j#zT zb5I}JlE|u@jJSNYx@G#2%iEs~ZPAi@lR)c5&!@I07*qoM6N<$ Ef_5gud;kCd diff --git a/editor/resources/editor/icons/light/navigator-element/form-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-black-12x12@2x.png index 16cc550f6163f3bb6a5cc03d6f71d2eb43e1b225..4c86f6c0aad959a508d742ce8ea241c7de8eb01e 100644 GIT binary patch delta 390 zcmV;10eSwt2BrqEssVpzNkl zg3v+eARF-!M@rzp0SN?oV*#=eB)j%0QJ%D#Wq0Pi{msDGZ-;XF;d!3XG>y099LI4u zH;yv?}3^Cz&j2d)GM*%(9+h&;`*Y(ptc$-frDH{(|b-94hFqyPW_07*qo IM6N<$g3O}C`Tzg` diff --git a/editor/resources/editor/icons/light/navigator-element/form-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-blue-12x12@2x.png index 551b3b8513891ea24f9fd9e9ec064289cbaefe5e..56a9ebb82606c5ddaea78943b7531de7c777eac2 100644 GIT binary patch delta 383 zcmV-_0f7Fv2A>A7ssVpsNkl6o&s(X}#b>m%t9h9l#D`1;P@1fa#m{ zjS==BuE6eq?!dYOm(T}iL~I*#q0<)0n81_z&-9W^&iChJk`v&!iyEzv`B-IL?dYi+ z@9ZDH@fdfxK}Kl1HwYWssVp_Nkl;L0|b)Kesq&1k%wiI`?Ef#G6q?;Dpu~@JdkHa4=4k z^ZN%SAWd4w6iE-K&j$ZX6_Fs?%tLe6kl9)y$Z|KJk|A-oaHc~RnI00000NkvXXu0mjf D-LS-K diff --git a/editor/resources/editor/icons/light/navigator-element/form-darkgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-darkgray-12x12@2x.png index 70248ca97160ba339939f6e5a571ea17d579b0a4..f11fb695e3a4f2119c25184a300f6f93e2029c12 100644 GIT binary patch delta 380 zcmV-?0fYXl2Al@4ssVppNklq3&{C-CoE=74V`~;ehxtezH&~Em6gb@ z_=Eg_@u+E^ zwwK6V*L5Jiy-IWdq?ADcp$K*lyPB^YzBj}jsjfz!F3HbOi0kow5rMW30%tzy4E`e* zLAlVLTmV1FAMARR!*jV~ a4~1Xe{Mormyj~mt0000#SXRu)(XT9 z);|&;VgzbLY)Dz`xEPy&jjK2$ z4q?jNrr0oy0C7YdeIUbi%`?bBxIT0t`|U*LFL-y4IOiHS1Mlk#Fu3I5TO7wFI|5le zP169&8zNrw6?h-GI#a|E@eQXuVl4WW!A$XuI7i7qRb0uy^E{hZOF37ZV6geH1+!O} zIj6*x47#qfkv)IoOJvF7j^iv%(|khsEH>k816|jzAik#(L|iNui@jLR=o4DP0O2M1 zDH~8D&7@w85@WxNv%yJ-Ke^=h5KUw;MWBRNw9Shf-N*oEL4-P9@j4HgB1oLN9OW8~ qjAbIaG#E}NMN~*~JDgNvDWt;GNU002ovPDBK*LSTX@)3t;E diff --git a/editor/resources/editor/icons/light/navigator-element/form-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-gray-12x12@2x.png index 73d01ac996f80970fbb3111d2e377e34b39f3d3e..55abd080f660339362087b8bdf379c1269783598 100644 GIT binary patch delta 308 zcmV-40n7g51=IzwssVo$NklWtz5 delta 323 zcmV-J0lfay1>*&R01rnfDHsQQ z&fpB1W59gx^;mF-`>dxZAgscGS6O1dmFMnla@KUb=DAcB_CkMz;i|-Zjq8c@GWt#z zc>#Y?cMw~uK)^i7vMeo%!Y%UTv>j5S!rX`?!@ay!Ktprm_h{chWv&W9uiGKEsW~H} z<`{Tk8<>yl%-aUUbU#!#a}?f%3vlTlMomB$JkWIuvcchDJM#h(@E;tj1LPnz!LNUz zJ_lNS18U*_$yPgRDxU-`rczI30lA1`x(=N-u;O#W)5zq{0EH)79e9GR+$8%PTmb3p Vi1(gB1eyQ<002ovPDHLkV1l-fkZAw_ diff --git a/editor/resources/editor/icons/light/navigator-element/form-green-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-green-12x12@2x.png index 1b81e757ababe7ff2d85b6e096a1c7b2b1d9758b..ca502f46a18325666ca343db292898fecbddfa60 100644 GIT binary patch delta 403 zcmV;E0c`%&2C@dQssVpINDty5goT_$ zr*Mpz*evqkNYrNnhMNk006`t(*HBf&0@lcLHUN$SOXV6Aurz$x4xh~F^#ceIS7LF? z=90%!dC{5h;kH`p^ZS=iHD;h`Mc~Sp#A^xY!nFl-;aUR5U6dI$7}QtLK^HW~ZD0k*hADYz0F=>`6y0y>epsD4zpsbmt^K zqbUEPmrUC~uMMRpEsxy6~s$3+gn}j~v~;{QwI9002ovPDHLkV1mMo#w-8; delta 438 zcmV;n0ZIO{2Gs_zssVqNNkl|CB=JK$f%OF94Lm|21pK4kz#9}# zV7&o;3X#?mz!Ay~I6^;+kuKeFw^&k0fiCe!<4fAkG&Aqb?#^TZemf9;05#vXM9dsX z7slP!V5dNB)V@g|ae=@p;E4d}j(37^n>^t-k!F@N=O$f4Gl+kbV{8T{6W9yZkgu?a zoB#s`)F5e}ESR$Z@Y0MdSO(s!uL`V~bXoN9&UjE*Innd7Gj0mRbbE-wRTj5i0TR>+ z(>;6pYzA}KgKcu&4IE?Ca*-%45`~zp*9@B2L*8E%N)L!34|kf0`Vl` z37i`kPoSPaSAJN{N?p;u#2EyfDH2#|@v5dK>2%&pr@A}9Ux&<3%%dh~A+2+^`(mr? zW}>MoZi;Cp?>Msuk}n9%oD@l&fC&0_PqIq##eMd+Ej>4AmKJ}V;+nsNB=>aAf3wpz zXq&w75sNC)%Vf+Jv^q`nB@3-N(RvvyY&3Qu=%&b5>xwoKDt0rr<(*qmIxE(I@5oYg($Al!IeT!ruj*bTgAGB#%(kUp&Sw!Y#fJQ@ kurAz#B*^fAA^sJ<0P&v8>_zHe#{d8T07*qoM6N<$g4K(*`~Uy| delta 399 zcmV;A0dW4N2CfFMssVp*Nkl)&M2wXGY zkZ6FRwsCT2#(5f3K#Y#G$(;jo%!NN^)W5td+{TK-lt%HhKLOw{zFVrp#YYCJhZ_%LWQ%RsIc_jhwi9a$#(y%PKMgwKBW>V1L zc+A(5b=_6u8s&eFh;xCqjof?WrU+kpFYKaL1P=D4>=hD8K{CarX3}|GHo#I~Q*6nq zTUkI-uUE>@!RGAphw(4462*@k>6`8cX#=SQ@jEq>t<807(Z$PDHLkV1oS2x}X36 diff --git a/editor/resources/editor/icons/light/navigator-element/form-lightblue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-lightblue-12x12@2x.png index 986d807640c71bb967cbaffcc55d42751536ed1b..4106606e932826fe8c1ffd0385fb28106a6d54e2 100644 GIT binary patch delta 358 zcmV-s0h#`w28IT(ssVpTNkltPXfJ2A!J9OX8Vfe=yT zJl4$@2}sGs0#b63fPSMA?v}-piv+Ol12E&Qn#YjK1QJ}jR?cNIM6Q=~$KsQ1vskFs z0~=^H2h@z~VsBpMga`i4Imq&EC`Bw%jJo_11nsAp_(T4UJOFW^odh!f21wvCa(Br6 zdHD~HO#>zV3qr%!cieTqJy>JPKOgaT7)#EN(iBI9FP%259Dc)d#{d8T07*qoM6N<$ Eg63MNq5uE@ delta 384 zcmV-`0e}962A~G8ssVptNklL{ou?GhMI*935 zO*R_PjL*RcCG;wE-eg?SsfyRcJ9sRtNzg@~`bzWRmWXVKb?|>>#FgTViKOeB_+54b zM4IE|OFOtWvnFfLOdAFIAl(f zTw%PWk4^yst_r|rs5hdn#0e{p7~zHhug&4 z8hBD^-dAyY@-C>)63R3cr1v7C!(shpQ4fdC)amw9MyKqqpLn!v$c z`SFMGZ?F}`pPZy~D0S|^7L3a@npYd_$o;)ABwgnr+Cev)sQ6;7Wy+NhNH!j9!P4<| eG0r;K-@zv_pqqV>)>v2o0000z29*Y|ssVpiNklt zp@Z|;+LEa!nsK_z* z*>&Ah*L5}QgsZ_>i~=xxeDIkB$^mI$O^)(Cf#*)jgx`(5UL|QjMUF+D_&fWs`cEF) zWC$H{_RaA|0;c4~0;c3f0!2|I^u2LHm)uAI7%w0$l2=vLiw?Pw0LpVS5&C$JTjXU~ z-a`B+&vQu=AmeQe1TqkP-+#c);y4zout$zV`Lg+#Y75{N@8|xa0+$a0XFlx`{Y0*U z@kP4|c-&d(0`R=4-7}W`T7EbV+e z6^Iq=e)AZh14^I(9-c7CP6lBiJO1c+W-`f5Zq6m-++0F_J2dhG$g<3=>)O{eEq5Fz zoD2}h@g1B3G;>JObzRlA?UUzu`H&p*d#v|+u(za?-U1b~4cULOX_`GJBV*8Y-9nd7 zkcS|**qEIL_Llij;SBO;J`6#0J=Sd7-c69d-kX(riV#5G+!6b@+svdcs6!QGB;BXyhqHvr8 xUTp4V`F<;zcmjL`GKo4W!!UNDlKmZg0gNsMNVGpIa{vnf002ovPDHLkV1mO3yP5z1 diff --git a/editor/resources/editor/icons/light/navigator-element/form-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-lightgreen-12x12@2x.png index 8e42ae27d682a8a15397f87ba957b4860f8919e2..6259613db984ac9bd36df550e8aade5b8bc53279 100644 GIT binary patch delta 383 zcmV-_0f7Fv2A>A7ssVpsNklL#FL`fmi;|X?3n<+U9{WrS-2lK={8M% zrfF0+-e;lK&^iNB*hV^uNXV?eKgn$}U^t@}nuZN<_j}hAZD@Zs)a}+zFi(1ta*S15 z?!zHFNaAKVFH#_IK(7q;_1Dl*d>Ndx@YG8`azpbT3{-`0Nr(a8Uo(6QaanZWf}G2hC-7H(}|3%4@3;5$EqBQ}Lw86@B$0o?&FS0->P1C<|V zdDBz(d|U^=WN~-Z=jHf71Mcc1R9PA@Xrkb~>dsTpT#c`Me(;L1mLVT)@UW;aP2!p| zV;sRx@FrO&+P{J8XO-1jc}30-`Mo@^@`t06XRYfvjuwSmnvIHH89{>dMqRT<94@Kh dr;39=rB9^Zxc=Z` delta 409 zcmV;K0cQT62Dk>WssVp_Nkld8AB$nSk(yA|5(InSihX3qV{t z0AYhN0cC<#LMpFegN%?@ew5?0n=}?pXk76E>L)p|oxATlJ9jqGUx%Pyz$q)~kqA5F zCC}n|+9+_w;{g*#Xp+_=$uNJp5Gtu5pP^g&q&?!3xloxNbZvjbobnkpfX&nM@kr{) z1tMqtUA~bQ;vE~0(inzUMXXaqa8%b8;$~7uj+H&&+qp0zhV;0!>sk@^i~V}S@>2Q% z-^pKu3IiTvYjYDMcH*@P+!0OWpjAbvBh1BH3A7C+McE0ZB;X800000NkvXXu0mjf D`isA0 diff --git a/editor/resources/editor/icons/light/navigator-element/form-lightpurple-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-lightpurple-12x12@2x.png index 148b186ffda2dbb7f0902df7ef281e27317f5dd4..c1e618e9754a102973dbd08ff482e6ace3962afd 100644 GIT binary patch delta 376 zcmV-;0f+vr2ABr0ssVplNkleA zB7Tn*7Bs@E_@??abQDHFJ#Z|8ei~6ehXc0BC9=Dhf-ia1Mxw_i*!r$<;QonxVS?4R zoZj_3fG3>D#b*7z1boT81$@c91k{XEd?l`SCHE4LD`*QastTUFkb4Ob;cPvPMQqYX zt_r@8JWaaag>Y~MnFwlKi2Q*!U9CdCQFz3-l_8NLtL!y(7T^$>?JvVlyKTn#h<+s> zfOnxC1tPftG4{Z^Bikgm`D%YS)r^(y`9V delta 398 zcmV;90dfAA2CW9LssVp)Nklf1;R2I4BUzGH@2%`zE%4W&@C)#7#X$=rv=O@J z%G)U5FJ-`mDFhCFx)O_E>`qizBv)Egs4t5{DuIYWOjhUE~`_u0Y?PL(nu;QDcD*U5O;(;tkEKJj=FwxCGv zUZ~OYQl=amCuNP7)V2jnY$2Z+a={hX=8XhulFzbxtORVytpxmqd_@Suur9eq2ldfU z2f;!fNjj_|Zz_M_BrQko-%C%eaV;OX$tGiM0Y>m4yMUxR1VeNY5PcJ|3SH$0sft#)6K()EkP`?;V1Z_5 z*ddo7oVVsV67W|Oo%F^MrG)C{b&c$@iD&wJfTe}KOZQ9k$%*-;CfCga(M zSl8W8uBjtptWrXOAtwPG-pcu>=t2Wka(?GOxOC5+q>)7Jbd^@+ zojj5}$V{fQcd=C)3x?1kS9iI+k$@?=v4APLk$`taJw?uW9qN)B2_#8TfcB$H3mtMJ z0rvb>ty~Wd=lOiFj+~>qo47PQNPvk|1gZ!FUdMEX?vCe#CqYlyEQ*9-i12z&!tijZ6G0C74G)tw;hM(27m9zenK&6k9U0CA|F7{Y z$R!u(3qp-Iq8^PmfNyMMVmy&Jp8C|6Wo+d=ossC}k`pdDG>0S+g+~bNC3f!~uzJM= zjCXL|xfLP4z$fwt;WoFa4IOWi!#qrEB`h(Q9Pp+lr`>zuFC|cr+)J;q60jw=5;)l< zlR=7)DJ)8E;Glmf;uMY0tkM;GQC~!ECqS_P#UWC&N`x diff --git a/editor/resources/editor/icons/light/navigator-element/form-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-red-12x12@2x.png index 8d39c7252b091cc608125caaceb6d9e8cc7bd198..a4787f8bfddad39635f1475b9ef75a387d2be48c 100644 GIT binary patch delta 349 zcmV-j0iynl2K@!FssVpKNkljtoaOdt%P=mg>hl?B8J z>;`lL>joX63)paTnn21)ArF4R;hxjxqxapLG|3Cmr9=1)tzJ_U*&w;j%TPb!5Yw(L ztHARHZqqaHNGT0MP7qiOhmCO(^_bC@gOiL(rleK;Xxhl+b-G#vTL?D+%jXq!0GppFJADXM>QtPrQrz2XE- z(_&;8h$}ST5UFJRFTuwUvI)U&p~iEGc*Hgcg*1eDp1!f`fQysCR-_-8F3!L94p1)@R0000< KMNUMnLSTY8o~v;H diff --git a/editor/resources/editor/icons/light/navigator-element/form-white-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/form-white-12x12@2x.png index 00c9de1b5779a9d890b02807187f36a78859e05a..762e91cc0b3bf7d7e5e36f343fb0573c6369064b 100644 GIT binary patch delta 275 zcmV+u0qp*<1+xXPssVrWNklvjsLsFSi4*j88+5B3fUS*(JEuDP`R(oq ZZ!51<9hEm0QveG9002ovPDHLkV1jw}bV2|C delta 273 zcmV+s0q*{@1+fLNssVrUNklgMu+AWk3@M zIRT-r;psM_*LFUUh#~$N&=e{eAd7}pf1Lnm0wKkD#(pp;3yFW4ma`x?KKiZmEo&wG zF;1PpdK_Tk3^+Q0>uTuy1FZm65u$wsM(B&I6ApYMeWx=d3g3G17fagjFd@oeR-tUHf+~+V40{O%$Zf1hfh2*3Udb%e&u? zpzJ)ud~V`c#N>a8!rCaEo%>D^At<+sq=MjwbHd1tA!(VA)Rc(WGBJ4 zqvFM)bfmjgNFrNWY0Vp`b`J_s)DYCccSd-Sy>b-GWxz@*Z-7P7gn+PExR4fChp)3> zZEml_ZilY99%=q#K9(K7Ter5j(Qdr3@okoS#ar#!W)UOE5)~<70!=|ZLs#a>;2VC9 Vm!K<)Fq;4X002ovPDHLkV1o65!tnqA delta 409 zcmV;K0cQTn2Dk>WssVp_Nkl5Pg%Ppvo2AAV+{3;0@pgasqI{M_4#4 zBp4Us3D6VZ4d4jeKyDx_OQ;lMcatFDBPK|(;VqI(&&+$>J?S3cj6G1HQQfg&(1S5K z#KQ=dDxh;a4h&XkdT#m$kTWvk;0h8O3m6x(OK3eo6qI!u$>e{>x`Wo%#Zk!_-R*lU z92qAT(3ID@lfzL2DsBd!$#?p*2B@|B_*VfYSKffW(lR#4qw3s+)^KFic3x^HvcM1d zD;3Vw!f5m|T`b0t0eyM@BC;z*3v#z{O;tH0@|IY+5Nn;1h>0U=Oix=x8g3?vz=Ax0 z+tjr5O@z(7>qmdo!gQMT?KV7#dIO2A^sD3nW?x05Qq&5JO`Z?&(9r%&0hRkM*-D5I z!6vv;75F?R(hjQa@^bF6Sze|wwg7{>q@`~B(NiezlE%LZaDnX>d7%iN<=gXm`}TzI zgPJoquw66bh|VV)46U`vBKXpXO-_fe=)yT83cdj%FN6`s!=G_l00000NkvXXu0mjf D$1cGO diff --git a/editor/resources/editor/icons/light/navigator-element/image-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-black-12x12@2x.png index 0929750ada58ea507f797108733f4bd2931eeffa..72fcfcfd37a78c7ec180377b942523ea7b873c5a 100644 GIT binary patch delta 434 zcmV;j0Zsn72GItvssVqJNkl=|1Cd)dO${u|YWcpu#L$)s7RT|r z*=$Z7$MN`XsD&U17FEG%nx>6$P!q$^4+1cc>BBI5I2;b1Tw#ChcDvPRG~E0__2Q;$ z!B2gw%Rk$l6AT7}alhZUrEUV$gxTx$wow$VkX@Tjr}Hdz5fB`Cyx|Zz{h4gi^+iz$ z_d($k3sn9>puq8XD83;`=A4I;r2?bJnhS+X?03r)9=oCh90fOGUhj6h8Av`b$5ygR zTgnE6CgvTbu-kv_zFbO>fvX9_FdjKia)571hQ|SUrVxI1jN}(V5uAp`#aNJp-b@d{ zccDVKi6S{maH>`8_j_K)Jbg9MbIjb@JKQimKsiB~0q7N{e3Ne#j7OftfvRC80vh5m zgQJ=x==rsan%%j)W<1jS=XKa9NUQAI?2m>*V(QsagW)O~*9d-+1epR9&V&n6(O5IU cn#$eS7s2(+spA(i5&!@I07*qoM6N<$f_*K}W&i*H delta 410 zcmV;L0cHNt2Dt{XssVp`NklSTg0!Rgz3PLI% z9XK7B5`4fO-{KCEi%BW%;Ds!Fm=)AS)pl22;FEMmyfF_Tk$ldSvJCLu{yw~sd7qG4hO)$9o{o!yZ zn+P1pwGR;&B5!|q>-JV`!#U09jwbj5z0(rA-*1|``2YX_07*qoM6N<$ Ef=NTnivR!s diff --git a/editor/resources/editor/icons/light/navigator-element/image-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-blue-12x12@2x.png index 57bce3bed7a04fc934f64c93d889521c96a228d5..1f10b4c3246eba1a60525e18253bc0c74dbb6446 100644 GIT binary patch delta 431 zcmV;g0Z{&}2F?bsssVqGNkly~j>>4W51xyKP zAkc%<4|vUu?dMq>P_mtx+`^zjiRS68yet3;SY-4~q`o(J7360`h~}Z?8apFIrT+~>OWwSgS7@}ePGnW!H@QVeOkn&ff<4Ix%crUw;|ld% zEV5N#Q>$oR4Pi`}Er|pTEsW(psLUcFQzQx`p>^4THt$>ojLS}1Ou(8Vm4JoHI^pJ$ zlYDn6wo|j);%nZIVErfDmY=*r(%kutR`dD?xo`s39^NOiY=U_O8D*W&Lu$~Ou~+8F Z;0N~`r)SKzQvCn`002ovPDHLkV1jBE(4_zX delta 398 zcmV;90dfA$2CW9LssVp)Nklr35ZCcX>HDQ`}at#E)J+WVG3I;bAPHdZL2foy-E;yryGpqZLn)SNU; z|Hs6Z_0IrX)phK5uob}YxrG<+5h8Fg@*VssfXq>GRn*|N47v((p2(q@jo!MvcM1cv zxePAUa}+^roUS_@6O3jig#%%_KS8oe6q;YxZS~AKCK;xKGw+yT+{RM9n+zFxt^5FO zt`)`)3=ZTp&hdY$?Wn)0I^6t#&*oZwwI7X`hCb&U+FX-bPeJdX*DDtwO=M>BdaU?3 z7`+bSZ#VmcxQwL%Bt9jB6ON^Eo2Yx*tTO?$!Ll@|-$x}O%52j=$@^gFxxYKE*>QoZ sT3a`hGq6OTFOBl{LYWf3}fG(M@8T00000Nks-uM6N<$g3HFdC;$Ke diff --git a/editor/resources/editor/icons/light/navigator-element/image-dark-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-dark-gray-12x12@2x.png deleted file mode 100644 index 2523c141a5f32caf9587d90e733f67f6cab7c08b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 803 zcmV+;1Kj+HP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?jr8(`GLS0}KYpgKYA z1oqJc2y6f&xIx{ZeFs9%G2hpGDrk@zUpxun-jB;U_a_%b9=HI@bf(j3FUztuOh>N6 z*0$~8X0zGpgO>ReK5Q42yqPhqY&06V+#RVaV303yJ*(q| zZkG~^Ez1h?Jde+bRJCYN?)&}%SE7W75Y^2oMh5~rB-5h^tF9xkC)W;bkVO;*;Y!D( zX*%FJMO4)%u*(ijat)BpI-L$@(}SBBF+kRqngl_p+)h1-M{R0nhV3(WVdDxUVn0bMQYv*&LK3&9Fr^1MM7CfX$sT hK(0r^AC5dw2fsGxn!BwU#JB(e002ovPDHLkV1gQ@XrurD diff --git a/editor/resources/editor/icons/light/navigator-element/image-darkgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-darkgray-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..01a7d5b75fefe61cb4e08d7f4d0056d6367589c9 GIT binary patch literal 833 zcmV-H1HSx;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?01V)B-3W=|DTc4setie#Q=x3PLI{ zset@s24fyR*+m{9MDPRhLvM!R-aFX6ySE1-w{DtpY}|Iy=vwfmcL(y% zcIO21`P^JA7KZdqV49{5;4L&AV!4L@EPW9W98z7w9pm~cwpaB^_?%@~Pn4!yLZHBr z{T}`V{u}qPb`==!i0v>tE_L5l;jtFw;28HQbsYqOgS`#FI7A`AG4)J>(;8PQd_9Yx z3a<75JmWse;crPsaFCZ3!kl9ye+cT}v?z*r7Be}ViC(miYhi_0FBQp2f~HS}@B6XJ z78U4dlU|8^f@C5;qG%>)Gi3V?@DDlkKcteX2^6BZo`8nT9o%A`0|3Kn?5vO7DP8kC zivF`524-R0_HOw{g90c$LwYd&)zGqB1Z4%tYRQ0fw+(-payRx3eX+2oX7hmX00000 LNkvXXu0mjf9Ab5d literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/navigator-element/image-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-gray-12x12@2x.png index 2375f9c8c3e85cd55d8b8cc336f47d431d2fa95e..32b37c2effea6520a0c8ad0a85a3ee1cdeb9a1a3 100644 GIT binary patch delta 350 zcmV-k0ipiw1^xxFssVpLNkl|hdT<{Z*6Xpo w_8(1KFOy|ZL+`T*Yz5j0wamu>+{xA8188=Cs}&r=P5=M^07*qoM6N<$g40N$W&i*H delta 333 zcmV-T0kZ!71?>f}ssVp4NklV1sl67@-r;PEdP-wiD0| z(hZUkvO%*!*&w_}&d4$`$OOa>PkOS?T;B8fa3b=+89e!cF{Z$<0ZX|IEx3YC=N7Uc zp_(90%w^c%0ke?=;u*WxN&=9dWB8X~gIOdwN&M6^ncNunHQ;}_f~DNT0K#neA6R2v z$u$jByasb!T3TyAf}9du>fK2*@Wd_n!iB!?jXN$iV-72;PnpCF_Tpwhqeesp@iomf z?!ZD#<|zhyaTnYSWS~Vt9fo%eKmBu$R2}`B<`Osg!SJo&=G-&k_kfKmWg1%OEL;#)z(%%m fIT~;!52RoRD^+mQX0PPB00000NkvXXu0mjfB2I&T{ssVqhNklwp@Rek$2aLfDiA9` zE5J7$;+S-R9Y6Q`K#u#12qrxG7iO;i!_mhBQnPm%HX9#Xyo_9TsY5w1F-gj|zYez7Ik@O7DZ(@=4#R+vSq;9R1mt<)yX?;F?)UA?zL^C$;1`IzQIk$RiN!r2 zv|u|-Di*qPS539U$gdK)+<~0Y$S#^SHA&>k{ zUy#^x-;{lWQ!jv{#J; zy$z8G7%x0E%=}bhrtgj@nm%kCK@q4@jU;=I8MlL@r}jWE#hx7KG;S|Im|t+0#4Dbs z2HxiL&S~6SfC>!OAoA1$rRna&`s$qanlmf^ffcynj_od*F^N3c)W%8#l^A;@Ie~3K gk6%g9g#*gq9XNojy>n|ZdH?_b07*qoM6N<$f{3Tll>h($ diff --git a/editor/resources/editor/icons/light/navigator-element/image-light-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-light-gray-12x12@2x.png deleted file mode 100644 index 2ab186f3780ba4772bd790c32bd325461c1da4e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 801 zcmV++1K#|JP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?m4ht|HSb_}jpLC!lqykL^F%=}K zz;r-5fZu!!b`Uy98UXU1;WB7I1>@w8Zw7B~*?Vty&mBarI0B=&$+B!x6vY~*C&REY zO>=HpR<0eY`4;5<8RW#YPVfh#{Q&+TiyLI|DLsJd#~}aMPf)c5_a#4cM#+WozXI%Q z9LJtqLLiDF{v+NE!w8Zj@#QZCNUoF$V2*3oEKSpgW(+HX@Qkw~eFZdmRaK98Zt26i z((R%cD}(8mWf>e2>1xrI+;!a*o{%=3AoY>;f@1YPhdrSPt3Fvklk0tLzsYyYo^=c= zwdkivUG*=F+MG>t4NUhPGM$nP+prNcM^zME$f*^yfs=|Xc^{lu5BIUu?;OWj>NXA* zs6}%0{hl_~r)J;Vs_qovfJp~z+kVCJvOTQS`q-JB?*V$ri}K_=Y|t`GZ+0r+MKVB! fBjg81uIPg=p(?2;cg}jM00000NkvXXu0mjfHP>iZ diff --git a/editor/resources/editor/icons/light/navigator-element/image-lightaqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-lightaqua-12x12@2x.png index 22b65f3d8c74b2cb10edde1c53e19801e718a672..0b900312dfbbf1ca34205ec79e70c54740f90e08 100644 GIT binary patch delta 424 zcmV;Z0ayON2FC`lssVq9NklekNox|%f@t`6%#iE5K(dx#)vqEs zmA-tY(Rz{tPZajNF@S0iMJ_>}C71Hd!oL`SPFW8sX)XYYq7Z?%5|1G*ZkdW}&jql_ z&u*QreLbdGJ)HZ{O5Wb=Mq}ri{vCE;1nnf};zf{UU`imc7bs|AJ;N&#dt+azMy5x# SXWkY70000 delta 416 zcmV;R0bl;d2EPWdssVq1Nkl1MBh4%H-4DN0%x(iZVcvVv~-P6-=x_f$v4)_Bc7tEWKh3Qe3 zv>8S$)Qrw~;uS%BR|4v9;apL17hK^eu`N{5i9e|nUGfJNfLVV?C||TlUoglrF6!K# zDP^AtXvf$uff-APmt|-d1ZFN3IiWFL#o%ftefm!V>s)AnR~0%{qxLR$2^&Oarqa;f zp`rxdIhy7fqpmv49iJ{G)5x@MbpDMbJ4MbpI`SGL!n$kKO#RwiT1w_DCm3Z*f~a#7 zc;{Zmx`R*U1<1r$?s9-c9$4PB?csx#$;O?|aDl^)X7 z@^buq?mo~?we?`qjx}Z`?bY4|w|yGZDAZ{BOCm+Lx<;t?@x0qK<|WVuqxB?DAbGGP z^7C`9JCm+~7Rt~zU>Xfix$4D41jyqJ$}^%3f!juiu1OdN6u~z$Af7IoHj+XB0000< KMNUMnLSTYnFuw2r diff --git a/editor/resources/editor/icons/light/navigator-element/image-lightblue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-lightblue-12x12@2x.png index 3e365e1d282699fd21ee32ba26f58f8101d6d1c2..cbb5c274878d377b7277a557955964c2e87a3522 100644 GIT binary patch delta 415 zcmV;Q0bu^72EGQcssVq0NklVoI5;1h19>wZ{j7bv+P4z$-=SPbPfQnWMAQvX2L^9A z$D{UD%EPmKp@m^>;|zrXmhh<8Unk%NMh6#;{ZQCb_(Z|cR_TAIBaO@6oATZk{un1t zpg+t&&rE=(33OsSJv9lw5R;5sTuA4rD@dJb|Di$H2*zq^~)!&t-mY0TN{V;mu@{yX?KU@9y>vIARMtw_%>i#|b9<8KN2H z=wN69Z;^Gh3cuTk_aGPau+#({N*BZdf)36&i%-;md800qfBb(;uvHpdlYG;d77mR6 z6_9x~GYWAC0h5yKh<9H2DT~DTO93SZru=lZgD{9@bX$mFXXcd#?9xYFft;KWaVcJ@ z2Ek<0rDE(1UtBj!cDO;LN5}I-#WiQzvt)@AGvw?=bcCH9l!;2Eu5>-5Vng#nl}O)vy kUP!q#nj?`52S?PwH&}j$i0a6rp8x;=07*qoM6N<$f|~}moB#j- diff --git a/editor/resources/editor/icons/light/navigator-element/image-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-lightgray-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6c0bde901c6660f971267214ef1915a7262d472f GIT binary patch literal 826 zcmV-A1I7G_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0DZU<#mwqyrh1Z|p!jNIFO=2&urN z0@8tWpx-U0eFW8;wR! zrfKdtxKXnpUkyM`EWl-;oqrSH0{@_Xr_?V+RfP{}1gf_;{g(XLv%35-u3R7t!$lAT zwhS!*Hy9v~(Oqkrwt>i_3?)EvSZ#yu7{5K|AhK#_!hKN`-P4+KiGU&p=?-_oEQ;c# z+^FlWB2#|Hn#;B;!$T!1$w4@$uV=HFgSjopNV+C@p63jLw>422BAe&41e)Y(4w)=D zPjQIE6eIa`I;}HA>l_mKAO;BfmsOSVw`eVyard$m^0T-UgK6YYtQvd(}07*qoM6N<$ Eg04qzI{*Lx literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/navigator-element/image-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-lightgreen-12x12@2x.png index 87122edc7cf8af9badbdea6a70f139d1dc04935a..886735b6585fdd6118705e2f92aa9a6b70bd523a 100644 GIT binary patch delta 433 zcmV;i0Z#tG2G9nussVqINkluLpD2;eBaK_>@4u#LGGo*wr~a0W3Z2tK>a+T z=K~__)=3}wUhqmQ1+oJQ8HvF63XccaU=eclV+WsksUg9E1BapVxPzO$go*BI| baWVJ?s{FEygeFLH00000NkvXXu0mjfzkk)t delta 418 zcmV;T0bTyk2EhifssVq3Nkl5PcJnHQpdcfSp9FiZ_58$O*s`WFQAn zPk^2PZx9xWF1dl+K-OAL+s$OE0`g0ga>J`iCDZA=*RSUj;D{Yi*})lUzXWecpb!PX zWYZH+d#v=##k_1n32Ic7TtGnWlMBqo%Bu--uYgXuiaBy1Bwc^~fO=mo&|8ybHv#N#VvN}Bd>rX z=Oy>xfi7*#=qBmV77$0`>v~TCNAAWGr8R%MdK6&=bDL)Mc|+FIxSzWIf%3XwmfWEN)8R^`N?$>ZpH-yOSM7lM zBHG2i4%R_-s_`oFeY5mGIHy7Ko8vmglv`GJgCz&Nt~>J6Ktagl^U4}()giP?~cvkk9Fk$ z_s%uf=Kxs)T*ReOkH_?l0Wq9=;|F8~Q0KIOlgEl&bF~qnvz>{4=X!iAZ5gKk)|}6z zCaTPMHajEo&TPFeFqLf}(l#x_eZR;%549%3J8H{@G7?)^Ds&JRlLk=|`^0DX+2^NY z0f}>O-~#GumkNKai1V?+`#uCxjRQyrq$zCDi#U2!fK2c}SJFlRUj{iJU@D>=Pp(b+MgYfb zc8Aur&BrpH580Nb7Ancu?(W#+L>u+lWpv=EhCz#L5hNrTNL0EKhPYHxGkRp=YV-ra WYN`ntH6N(}0000J?P delta 404 zcmV;F0c-xt2D1jRssVp=Nkl)y#BM2G>+{? zR_tKx`IK5yr}W%G+&Z`xqfZ-2upnpK!Q8qylPuO~AhqBgz2Sd#JHbwsbJO6v-s#}L zIxax>RYg3+Apk1mzAV}cF;o(AjQ<3f;Bu2;FEfpn5nq>lq%!r$BdO9wQ-BT5j2k9+ z+9uRM!idlxkG&MDDj17^g_kS7|J`K5BX1|n7O4Y0xOJR3h7 zFfg}1vLOeV-OYch{voHzSPY&+yYMAbouw;1OuQiX8B6wa0Zg!O1(i_Qsr+u%W37(^ z^}y5oSwK_U#?}B6=#o-t(Ul$(;kMZKs;X-NdV`@363~-C?hFLqCuiL|rT;+^vHH_- y{iW3~pn;u~D&P%#{nJ2O$>Ph$Fvdwu^a&yin&%D0XD|!^0000DYf*#$pD!Drw zj-S=|V{ExVIYY(DA?2}YfvTZ&`G8uSS%I}^^7s^+5)kq?jV2GX{Pl*@wNX!GUnN7w zl_N4(M!=JEiHBShIUZlhJbTjcWRmZ^uWJbn`-$!>4=07lk*hrvq$X}(Rh7&CiRTTI z1;b(zBcxi}-a~&Dxm-vfN$%%9B9vra#F@M$VnWX1v4@Q6B$07}5pqF2R6XuhB@FH) zJq(}xLp;<9CthT(z_eCz_oCX~T4E6$xeyJ`bkqZP;v9aGV!FUAu(fq2zZWmQA_S62 zNdvTXBC87s`qqU(yfN=71j)69n%%s-miu5!-F-+~zA!zMjnA6#v+;{|o}ngf;K6aE v{Hon_luLrx0~K*5@B-F^)Qmit*cyBT1`MeNbK>s?00000NkvXXu0mjf7a`NB delta 422 zcmV;X0a^a!2E_)jssVq7Nkl5Ac;)b_qXQtElzM1b2*kcVS>NG93_y9d- z6tEcvCWTV_iM%jiqF;RjXA5#gjz7?g1`Zb!^l|Lt#P(>61gL*noK6|ME)LMFN={0y z=*IkGuw(qMfGvG(o^k=Z5U8DT?#_Rgxb^v6^%4$O1*7C4CR3D;j2s0*MudK6_>)tr zWw$OV07*qoM6N<$fpF diff --git a/editor/resources/editor/icons/light/navigator-element/image-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/image-red-12x12@2x.png index 7c040b48d0dd237208beea3e92225391e3fd4ffa..e9a18c1a17f7f274baa8da32e4d9a7053b731b49 100644 GIT binary patch delta 381 zcmV-@0fPRC2Au}5ssVpqNklL6UX= zyMfujY>;kHMsNb@2L})0Gnz#6Bf0kug&M>UW%2(}3$cgNQO7jeY09<1F3H>M8o5F$ldT$Ed_eI!6 z;K1j)uDSfm5y1{Nfw|INDR4rcR{rZFeET?&z=L}ef7Zu{$eX>6L4$L-2_j^97fA;} z8{C}Gnn+AeVsdrDj2T53EgZ=p!Lh3Xc5H`o-o{ql+>gyyJxI_eTz;?7Z3w(6sp3Kh z49VpLc1doND|FHi9XR2#8>;KWe5eHf&-&H|FWR!2=D{(rTU3}Sf*=CEpyzHh_)b5W b>~7>ANZgjoAZ*|f(hb4}?FbA22@_Bzpk;xw zLD(P}p&Q^0=ma%Su?)r}^c?8*Pj#on(#h{h@)yxXj))2kt80z#7FyCIQ9I~TnYHnr z?0dkWnGVik3zy)R%%X@wc(0Jfo>HK7og=~bIKgZvI2HW2IT?SQSk6npeT9~E3IYIQ z!4GfH*6OOE|0EFb7Qo8aAzlxAOL?v$hA0EzFm%tWBA-~h2tb+E$YFQ zd0t`rb&jYfZU9~}nX{F_M+-@jLePVI!;RIe5U+gCE#F{FegYrLM0$! z5^l!^$@Kyq1C}g(32Dk*{y(ml0&p4-QPFbPj}2Nm1B>HuIfI0PM)2K*7exc;MCx4N z$DG`NT6v{4!wC4tp~pmPW0PfCbg}^<{$TsF$Pamo9P1i`B<_0ST(A5+<|<)szA@N| z#h7E}D#m#+fm^M?PMo#Fi?(eswsMmi0|gmqUo&wpPPm|;XaEOL*sxRRg96(BMU--9 zreS=J;sU2GE7Y!Va!dp<-AAK&NW; zC-}4W1(dxy_?7q$^I@|+iz{gBn+c*hX%@LI+Zoxt*8r%wFO6(SuH?{@ uN)q#J`q@PsS84&49gn;T5nB(=p_*QJ2g@32^Zk|p0000rq=b|}2T}owU~s_&lZ#OS zDxd>ONC_#y9eLiaC1Yg#3kN2@OTJ{2_uIFbUEtTDOKOHbXg`zWBOfue4lry*=0>He z!}0^g4IcJ(qPP}-Jr|5QaM$fA^WZcIoJ->&aAvk-aNZ5Z}Nm|GP#x^rncC57P zW89g8D8iGZ|DZKwmtwIj#9gyp5zS%RW-f!2hncEH&Rb-tvc!&0=jD*)$05AW+1@Hv0sR4fgu}MThRCodHmCX&pFbsvC4FhC^G76J0Lob!!R4#=hD=-O+ zzz7|o3qWuYmHLx5t*ag?<&%;)?~oTqvI7J>P-B;52bpg&40Pn!AjRc$uLN%Sr85pM ziSYhi5IqJq`Uf$XcCr=&aUW*Dpi=4OjYqO|svrCC#v@@Yj5|mJrad$`GISeUk56bw zvW~R)69t1{umXd2p_N_INWoZWA^8((G&5j|L6k#JA?@Ofz!bi~?Itq6k~>ZS0000< KMNUMnLSTYmB2`HM diff --git a/editor/resources/editor/icons/light/navigator-element/page-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/page-black-12x12@2x.png index 29d7348e09c089ce8821e851b39777ff8e7c7e05..49017566dc5348e80bb7351af7ef0411af6d5fce 100644 GIT binary patch delta 269 zcmV+o0rLLz1g!1Q7Ki4Mm)-b);dB6F)DhG-(~PjFh^OIT_JzZC|HU{lsP$$b3p3} z3{(1&*E?`sR~uQPfE3@Et`ZYBVkBKb?>`mBgQz}(Nw5Y?GqY+Zum#&Z&+jw<&+}v( zZ_V879V`Zm!D7&Hl5rA!oJbmi+}mp)pI~#r36VxpTEPwXu(>b-`Bwz=H#`7Kky-Gi TLzDmj0000ZdXQt>Rogo{f8)St}(vHvr z+%rP&2vNIIB}51zL^(v_NeE+Ed~9I@G!|gtK`C`(j1As<33ZIPdSlGv@8D5Dzu|J? zjB5xTJP|;2&bbTjpNu_+%nAI!GQEWmS-X@|%86xqT5Gd*DI807CYb@2;tCZ|hD8Ee z>lajj-+bcRy+lo*2^>HmZZw*b5*x-tJ!5!?Gw9-gHQ)00Oei0o|R^7M|OZ;M_jAkUINt_KoZ~Kv8@BQy44fw zrdO63m}?sBGm9qHeM2L*P;kr$>`YB+81!fgsIJjpBcBCCOfi49S8TfA1N2NSN-NW; z+XJ|@c^Li?v2Spou<}@4fY1(hCFa3MP1ZTstiJQs*|kMdKsJN{7ILQippa@|RNEj8 z{ZkXZTF0f_cTfZr0Y$*Gn{1UN-$`Mrd6ri7A{^1Z!;HP}|B6I!Bhs2KP*o`;R g!waR8gTLVd3r!M6BnYidS^xk507*qoM6N<$f`}G>BLDyZ delta 208 zcmV;>05AW#1@Q#1ssVqpNklgt%Kx&T|Ooc%P*Ub|# z96!C#;!l(elEDfL>_#)cq|gmRh=u8y(88)f6?VczD%9$X#1y`Zku;6(qMS7V0000< KMNUMnLSTXskyz#c diff --git a/editor/resources/editor/icons/light/navigator-element/page-darkgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/page-darkgray-12x12@2x.png index 10d77907a0f45ca3cd357533019f93be6ea8e980..fddf18f6904429858b72e92cf2c59b9fa772ed3c 100644 GIT binary patch delta 268 zcmV+n0rURu1gr(HssVrPNklO)sY|wRMRvEP(=o?EUQBBvMeikZ)>%q zX>$gKT*#pGAixEoCAh~C>neOFXJSkkaehEYy$EzbgSaS)6KH>mRWV17_f*&Q7SZExqfAk8+2-9FT6EBX>PO$?_ew}ib5 zjQ~Egi*VL+lRKCNW`S9t|0XNkNE!+CPN0+ndoqN)YAtLn8R-QB@Sq<34Q`kKUpkeN S>$U&@002ovPDBK*LSTYxQE!d_ delta 205 zcmV;;05boq1?~i}ssVqmNkly+XUGQW23?`A;tuHu z9ibz10MRN~5W^+rAP)h5Aby^IJ{3*@IvcREp|!qw?;lZ0Aix;=#4;IUp8psx2ZRtN z>f(9+kT(dJ!I0%Bgt)}|yP`29YEbZQ&`k&=K0D{ObQ2s720KN;6==*&2G-ga5Ku}j zVuxQ*H|Pc@FsKtPy^=B}OaLP3Pbk~G>Ky9yv-ssVqaNklZe1>olS5U_XPT~`^D4bye;#wuDB9xAy00000NkvXXu0mjfF6>if diff --git a/editor/resources/editor/icons/light/navigator-element/page-green-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/page-green-12x12@2x.png index f05e4381fafd6e95f7bcf4eeb1afbce2752bb40a..1f5f78e177796ed61fe3a389f95bae61d2f43a58 100644 GIT binary patch delta 304 zcmV-00nh&Y1kVMqsR4fh5J^NqRCodHmCa4VKoEuBED53vm*5gY2eD*wg;WAmfKow{ zD>-C4fD&ASOW=rPtsgT^LKX;rF*y+VlPt~bSnti)+FjtkBb%UqKTIJq1(Bj1CBUp2 z`N9$xc`g4y+(=Ywx=GyILNiiPJ7yYK2TvB0yj{J*i9Tan|Jr|J+o*eAA!HJA@6~Fq zX=$;X!dtEC<3>lHt<8T#^bazw!%`@73NM?foXkKb>O2sLr_=6hUVSHAjh2meZ$~Xr z@$1(t5+gW7jbGt#U_MN6B0PV-@Q>Jo-Xb3e!$Z7w@CiDD&Y&~cv6Dk^>DeO3J_OY1 z=LU8J+lAwJ7Z@ne25D}!728ilj^jcL3O#i*91Slge_c8li`Sq40000V*OT delta 220 zcmV<203-j;1^fiCsR4fgy-7qtRCodHmB9_dAQXmws7*XFf{x+{Mm;-2H>ewQ1+PXE zH_#Cr!4Z0|RBxRvYfiRxnJg>Hwp&AkSyIzdsj^r1BU}LuNrDIFZtcsg%dAw1-B7u;FB~J&*#R+H zApoX3^a*(Fu6G2Gp4KgI^ec)1F<=4#_MqukQmBC;1j6*6U|@AXnSEd&C4mlz4B-tj Wygo0+wcHp00000H7=aBaBQOE52~2>P0GNPo zK-nN8^akR@l>?aPLQ%xG3LHTFNl_fTdX8Ns0X`kcjcBPgRSco1;W<)qXeK}6ZQ*jS zZZUa*xKYhEdccK&!|X-SWNn^fWwt1K7LY9lv^(a%nIhPzJB@!)V37Pu%z4aZYBn~A zv)~%tcEl00q7}bv-xHqwiCjzY67mENZ>DnU zV0#+ubAkdybB);AY3O@<1!aOVL7CvfNw%w&ClZB_^Y^3@1igu?Lm$tR=Eku_y!$#~ ipeSMw7N1Of4LcMQ3`(8(d&0s10000MucMk delta 215 zcmV;|04V>w1^5K8ssVqwNkl%Gyl@MDHLxhpjV0|3R&MUCE@T^OM zZWM=!jGl>c4wHv!s-4UyHyk5*AbZ`_d23kaz&_y;)-QYq-GO%iOm;^ z8$w(g#l1l2Y|3bCEpW8H#?0jwToW6APE;h2v5*~+;EXkWWqp5v#Ae!%9DU`)-@^X} z+PR7yubCOSsaDSR88>34`|+#7Y{b@X734w|nR@%N*Uk_h5};=C69^1sSL{#%dC=xH zZv9y86Ep&iKqF9m7DfCcQHm3f>EMxo;1R6(fW{nUxfNIWkhT|zLUqht5#w*T06hgY Vx0(c^w*UYD07(Z$PDHLkV1fbzdd2_% delta 207 zcmV;=05Jcr1@Hv0ssVqoNklzL{Om{$P#A#xO?}}lx7drc$fF?xw_DNS6EOa%BzHd~ zR~GLA5jD^Y&$UH`JC>quow^&_XYgW%>!40#9*r`NlB{1RVlYQB@eT+Zi4-CRV(_hlcz%cS@{7u+F6n6WG!9bA1IgE%Uhq+~1__S}UB#{xq+Z^r)J0BR3&O?}E1+H2{6$cO}zzMhk z3Gv(`>=9f*$BZgP{k8f)`X!T{>1@7lW}DpsejOA!HMSmsCJcDU1_y9^OV-!G#I)vL zAXij{YZ3+KI&o~tFG&TuO1M*BDjI}acr4b_@6R>>mvH3sR4fgv`IukRCodHl+6voFbsvC+YXQsU=27i2{ZK0AxI3s3QPhA zxHCdWU;%0zexxX*%@5*GDc|YEvHa{v4p0a{_F>7pHRHY)sgOrUsP%<5hfkogZ>6~Y zp}1l8ZV+ArlkhU)wg=Be-i9=WQDX*AYTz2uu{6G54?0!>9ZO4Uelm^Ul~>5XOc-Tw zCVfH%3*LUk{{BS8pcqWRz+E)+ODb6yMn0W=a34`2ei zK^dVVbOa{ATtfpD;-x-5K)q5_JC=N$Ms|Q-mv|#tX&{0P6alI!Q=lJBB{jztNc$R+ zn|jQ(@s2A7@^7jReG;vLquHvMTY!}Vk9o@`q!s1J?iy4o; z&Ea3^b_a(Q>%1zXwc~vZE~j$XlG@`6>Bo8X!%vCBsmLopE%E?|hSho8P(c(;yMTELS|rUG^(O6kNgEw2DJg8AUE)fXtMd-BX1w_n6rIw}S#KvH`$ c@i#gHk#0voiq;MtIRF3v07*qoM6N<$g0T>IKmY&$ delta 210 zcmV;@04@Kv1@i>3ssVqrNkldN(DOF@P&f3L~4Kx7267q2@X`HQPajW7yQ$POoZ)B$DhO7Uz) zal`I^KsXIdLS@8A`GdX4vQMKQJ!DWv-=o@-tt&{3CpN>{7llfNadyCj1OZeX`WPf< z$`L?*<4$bxD~bluU$hFcmMzZ diff --git a/editor/resources/editor/icons/light/navigator-element/page-purple-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/page-purple-12x12@2x.png index a05cfcbd147fedaefee72f70f353ab75a559633e..1dd3f5000f2b39400e400b7c717385cb090d447f 100644 GIT binary patch delta 288 zcmV+*0pI@k1iuBasR4fh07*naRCodHm0J$MKoo}mGxcH@BD{AAEWrw}2;z|!5ieo| zSOGg=34M1-mtX;OoHMFXsghnENWY|+e=a@$Oq+8C_;u(ZdUb8n6$_R&(&3gYw8ndK zq@x0-E7lnV7b=(gMiDZQ3BPstTrJZAXJ3!ZCV;sjbj^4?c9egCK@;ZFBW+l&IG`(9 zTaZ4=9)^=6Es2czR|Nl{U)9=|t_0_&EvMpOOKEww!FmIYGcW9X3Oqd#y)(#!hk-)Q zlwJpvLUVGU9TG68>4xWF8;XaVDGUmO!XP4(ITLNpNF+htjWduEEDL75FcoyK$cEq( man0{OPo%){EOQu1{RubYu0_SqY_ClK0000vs1gHhDssVrLNklJ>dXnO9bX=sN5P!lwpf(NRaw}%d# zGm!);gaVQDSa1Z=!&z)txkV|B6PbTU6{xDeyri_foccY97_omg#Q4@nAdd43nJPElE5?+pQ2P7hhd0_STL#Cjmz{AkWh546LLV9}niNhTl!vzr# zuzIu^ZN128!+sF8Au#c1;{HCK>*=nF`}>f%m_P;c4HnA^R|P(VDQYmFZ@$P~{zOS2 z3EV)yZ!|Y06*Y_nA2ScU3S{Q`7<}AF{~>XN9vQPG!>?n`?EnA(07*qoM6N<$f+`(V AQvd(} diff --git a/editor/resources/editor/icons/light/navigator-element/page-white-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/page-white-12x12@2x.png index 5090d3b88bf360ff020e534776ffc9f020f62502..b06e3a45b3be7c59120bdd12a4d1efef7ce1aa9c 100644 GIT binary patch delta 207 zcmV;=05Jd51n>l~ssVqoNklK3`6jbumD6;MPnAo)gTG1VNTZG}LkA@H@ql!1SfL^H^2>ag9?cl z(g@)r2NPaGXlZGofdVvAK*U*(1M^WPh8vTS1WHc=$~YNggH<>&ihGuNjK(=2`{-ST zdz`iiISN`Lgb&aqdg5}ZOy^mjAdfX@wQmhFdD~yTL@hx}@PjJ^^e3Ax*%$Vt-Bsuf hBy~u{9B_d~3K#q&a35c?h^7Dl002ovPDHLkV1lX9MAZNQ diff --git a/editor/resources/editor/icons/light/navigator-element/pure-text-aqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/pure-text-aqua-12x12@2x.png index 6017b82959f4790f4ea75c633e297d3e3cafadb1..c14e7b0260547080dc7fb3746a0a59c9fa0b0bcb 100644 GIT binary patch delta 233 zcmVw>((rA^AkHT7GV@G?^b~bUoOXuZUX5Ycy=KQ^=Ub~Lv#1%F zG+9QC_z^(9e5o5L<;nN8ZQD>vZ?04DO+$9Z*cxHPkr3j3;FC*&xW+vp zc^`N=jc+GtU=%?Y82y27`GZf83*-X1KrYY&(d7m^eg;S661i?&S(bAl#QhgXbOIo+ jVyDyjjWMaGb!2z~AZM?XTKh&CkS`%<1L^>! zqrwbkyYt&ewO;YR@Z^rkMPlsn(owrxWxJ-JT7Hw@VsV{>5;TSAEYfk!S0;u`ma zI=3M2=5amgQIoael=SodC$I j*kyBmV@&Gh`!QSr;08Xigny?x00000NkvXXu0mjf@o{A! diff --git a/editor/resources/editor/icons/light/navigator-element/pure-text-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/pure-text-blue-12x12@2x.png index c4dc7c13bd9647839597340eba105d25b39c7551..72a22d593c478204b500dd3d9ca634898221ca63 100644 GIT binary patch delta 184 zcmV;p07w6Y1%w5#ssRDTldAzRe>M=pf~4P~zcceXv*-YQhbkw2vIImRS1y_ngV+V( z@SqpiKKBq=fHsg=BOISU+d<({WQ+GKjgGmIV)yWnvYUEo=nDkh^j0=nx$ mm@^Qm3v=sq!Fkix+B06yb1GnXYu$hV0000IAhD+awW0y^tL nn13Kr7v|39g7dna@5i_SnTIM~=7Kj~00000NkvXXu0mjfw+d4` diff --git a/editor/resources/editor/icons/light/navigator-element/pure-text-darkgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/pure-text-darkgray-12x12@2x.png index 17204d2355c67c6490d84190a14788c95f2ff64d..07d1259345b7bd02fa05cd53062cafa1b616d545 100644 GIT binary patch delta 194 zcmV;z06qVi1(^k~-~oS%6{U#eldQM@{rBg_M>KaZGm)lgE`&H?8ys;WMH9M%_rJS2;C$~x!V$y(=!A9^uHVA0cgi~s-t07*qoM6N<$f@o=83;+NC delta 194 zcmV;z06qVi1(^k~-~oSNp%g?uDSGGMe|K*Fi99}lnTa$_b0NeI$B-Pr7`vnIT$bft z&rkKABuTai2Yj5|Aq_3#IDXc3eO1Z8aIu05dECIsNv~yD7PW1AlTM4Gn3?P_w?;Uk zo+G|{C;BCjM>3k^-$3;!j!uCg5Ew2P{eZ6i!C&A7ynq)NgMd19_F(zUF&!_|vwY;} wZklFMRn?=9!}mCEFqI*`+b` hf`a;2=g|EE@CKPlFT&G90n`8h002ovPDHLkV1iV4Q%V2; delta 178 zcmV;j08Rh=1p5TAssRDKldAzOf2(a2RsB>s$+B~?&(0?%%7{Qo!Z}xm5G=xq($FfU z?#39$$&C;<5WgbaQaZYUj=;xz|NN09&w%);4=>i*hTq|=;a=UOh<8#Q+!^i$t6~4z zLgeW_xuHa`8qN8F7Dg$iP&5NW^^3nCH^>cggEcgm{Cn`X?BO0XzI2w_3ew`kf<=l@O@9e}=r@&-FC91_Ay0y;D!M#TNo3b&;O z!(hHaA`e=i33MNJ=x3S*H=@;dBFN=-;lPt4b zO*&_!gDhSLZe=+}eqV!*DLhe9IzkJ6<#%3zGEfG}KpE7a@^dv~M{7dxx>R(xm@}Hf rEV`9xR8~O9^*^msAKe?b)}HYJFRMBzn?n8Z00000NkvXXu0mjfhI~>0 delta 189 zcmV;u07Czg1(F4@-T{9B31Ok>TQqH_^M9v{4uGNtlsDL6=8zCx640R;F(Pj7R=6%T z=m*mk5_!-9O`v`dd?!*hC5K0gj+VHTK6AlwLzoMf5h zYSK9)9c1xu;8vDn8VoKM#kD znOYFa|9c0?AQ>csWbg&z=ca2+0on`Gt>in+%!F^T8gd5@TUZ_%oouy1BwMoo-F;u_84UmSYEK1#BwN670mIGf;$-Ul`}&10L_7DG45sZUO)R002ovPDHLkV1k5z BSY!YI delta 199 zcmV;&0672q1p5TAy#ap$b|42F%drEr0yY(B33lSq87M+Zumab>j0|Q7Q5h~wzDxdg z-^=EZ1p*$(-q3|)0GDPmpmoyG|;8wB8~X}JaOb5o!`r4_sodz`+{otCNUPc z*Ei)Yt!-T{CzdAaEZQ{rKlEZ)|DM9ke0>p?PGAB<@v~P@1*$+5Sb{*Y_b8<{l+rt7hEE(a r=-(pGT#jM|n4p2eWW)Ae^e=-Kg`+Z`K?nE@00000NkvXXu0mjfqZ~YH diff --git a/editor/resources/editor/icons/light/navigator-element/pure-text-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/pure-text-lightgreen-12x12@2x.png index 723e7090c2922aabcc8eecfc95af4642d223c76f..08c244b6bee19de6282732e7b531137cb1825be9 100644 GIT binary patch delta 191 zcmV;w06_nR1%(B$vjGRO4Z<)GMgNn!0U>`j0h9vdS6H_1?th;P8~Ald-xzTm5^|}g z9^NAZ#3rTr(r6HH9HA8d7zWJ_v`B92PCcAY$|P1vGO0#}EPVkw7AH+9>gmE`mQy9Z zCUB^h_gbOl`Ng1%H(~#%@vHj+EmON9)jHt|p4GSBfirLh&cGQo!1}layy^p&EzB#w tTh;{+b|gg delta 191 zcmV;w06_nR1%(B$vjGRa4Z<)Gh2N990U>{O_)(h3Ut!t4yZ3x9Y{1a~=^GP{Lqaaq z)WdgVfY_z9TpJAnjw6)fKf|EKiB`#D-K&T5S((HtNha0En58d3=i;O(MFU-U%5tv6 zw*(H=@>wgiJii!p@lQCuYW(WHK+DvwNVQJ*gLn0f{){XL%xAMo#xYsgbh7}%R_gwH65aGAw)@CxJ^@0cIO zzsBTm)tXMv^U!fFs)8)~%#sGU+MCW-G6)+YDqU=4bdPUp?-8W`Fp?} Xyj?5GSV;fG00000NkvXXu0mjf>q2Aw delta 220 zcmV<203-kY1pNfCssVq#Nkln_ut@wB5$T-T}NSxF5BgLCg$;LRhEkP_oAGbYk#T%-BXLgKj}-rfQjRXK zM`)Q?RH4v-s{Gb(5DbDrFzAAT_w8AXXsqry!QFh!pui+I>gp!a@ZO+DPhnqYOK$zz co$t?h0K8l&&+p@|S^xk507*qoM6N<$f&jf%F8}}l diff --git a/editor/resources/editor/icons/light/navigator-element/pure-text-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/pure-text-red-12x12@2x.png index 27fe3b84cce28d28dc145b950aa3df618055628a..727fab05abf641a742de69877b5ea66bee3e4a3b 100644 GIT binary patch delta 200 zcmV;(05|{g1o8y1vjKnG4T3-roFx=M31 zHo)_qcgijo6aR)5918#6{H)W42(d6OcXqzBH^XhDi&j2qMhbj4TfY!GF0000|+WXN00Un6`P?+tG$B~v`7?gGu%}-7Nk{`b0BT(!`FWK)F*PXIvKqKfQ zo*LkJFDqr0iw3RPq|86l${+aWMt0a+#v<>7N{*?%N0=CKy^26wFamA)lXnmVfbn&zRT^ULT%CFE$K#xWvfB2eucqo@591? zgI@jc3Bn)@!XOO1@Xx!GzTJ?Ov>w(3>CxZ#1YF>u=ivNg!f6Zu0000?=8Q5m5lP}0<-2Z5;Z zV)&AGP=20V1i)#9h%VMm?I0^#%`=UYGy{~9_%4>03bjd#m!uaV7Oe)g`W+^7{0|!g z1JvrLPv8b_;07xgsPM;llD>S96|^4K1mRO}d;uPGf9KwO)o~5o00000NkvXXu0mjf DT_-^w diff --git a/editor/resources/editor/icons/light/navigator-element/scene-aqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-aqua-12x12@2x.png index 686789579dbfcb8460a8a62b79526a575dd08d5f..d2699194eda25e67d1dbe2c2ee6610bea8dc6797 100644 GIT binary patch delta 621 zcmV-z0+RjA2#W}?ssVpYNkl6@3wy<=ng|bIHCyKORoat z>*GwFAL>5~pV0BitBBqbbVkR3GV_2(@f50zgOMtbBL^~pH17KZXK4$>^R2$6`hHs^ zRHiv>W8Gnsh!RT_hyxSUj&%xNt|)CX?8EpXf%lj$OB>EE=ae;70eW1e>KOz% zeAH?|R$#Tv)sBDXB=H71!?nur%qUJO#j!P3696=of{;?~4D+=_MsfGtXsmPz{2Q@P z&xv|xB8mTr=thCLz1fIcHMb?jo~_E8+MA zJe^2NGHZZ|079h<#AYS1StlTP@|&9oz!C{kg}{Hd2bzBj?0MZfDG1yq&kLtht!0XY zry3#inyt#GnoGc_f%Vi+sI1p6&$7uv=shEXJs8LPx?#azb>}ua8r-UPQ2l8rVD=ry z2SmDO$$SFP`vc_(0bQ#SrQKg8RfY6yscemE7?_t}G`K2AY2a$7OIX*UOL7oBC#zhg z&3lFG{ZM7s6Uu*9Q{6#^A6y{pa~B*gbNtzyT=N*6UgA!ftWtV zS3S@E@WK$4x_E!GaS=JIaN#~w-I;b$wNGuz_O|h@oUU|`g z6kD5W@>d!_slet>sR@C)7HC&9MNPO)^~x%-j#K1h)INsCItY-2C_vgQ@Nqb?1xy-l z4ZHMOnAfugrB{G+j5}|NBM`Z6Px+jt8qSyo*9`*sT+@GRshNqQ_QOv0kt2?#t$_)Z zx4SW~nKmOLtDBwzA>shMMl9pekDjp72c)bo%O_(=casgyQdR{H;Mv-Dh z#mwPMLagtm08}>v5RM7YcCk;78lguUATWK02j8I|R$Eh6Sx07eyhxPV+;VS;QRgIN z5z}E`#<71z3Y}$?u;u=KL7g;n#Hmr|SjGa4mkB;`*}%+Ui!>Q-skDd(m3Zsf0tRu8 zHJJpwrBU(PPZc=ohbStENI;Pt*V^20br$bARux_*uDGUVDIBMZQN6l5k4TVz;W%#- zGhX?Y0OQU)W>e9nRCwWR14aC=Vb_%j%e?9SS7s+35Fk-8$Klkq5$PZQbSXWT`~{8$ VT%o(6-`4;D002ovPDHLkV1m0gLCXLD diff --git a/editor/resources/editor/icons/light/navigator-element/scene-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-black-12x12@2x.png index a52075dda3775fc61ec4713893d83a2d63f371d2..b412267e88dc1b9a7ed3f4393c04008b77c78e8e 100644 GIT binary patch delta 603 zcmV-h0;K)32>A!FssVpGNkl^6fCC*EZ#>|T4vZD36_5_l3J4V# zDll}Q6+j2%06cD{13dr-{^B=rC$7ngdEA)y_GNZ6^Udu1tq_+^#(x5qWi@uYodfm` z%a+Fh)^I+b`~T@1r+~NHZLd%$JVsH}_(Lqjnv~1sK@bFCE(3p^PR9md7p#*A8O8*k z!D_W4&qb|PyT@4kJtw@E(-BH1KRTn+Od_XB@CyKEvK!EEa=|fp)uX;WL#& z!_8*nhGFgTe%ZA|CZN@2hGlr3<)oQuoOag{S7+7OID=@?HtW+w#IFm}H z5{K8y7+^w4(oKI}P(`N5NmOyTd4Ip(Pvuckb!rYGjjn&H1a%e1gdQ=pH#i&)*Z7R& z*1?V5DW(Lb0@E45#|pSl$xY*BZorngGN5$FjRrohs?>gn{_wcs(m1*hg;)a~1JaNU zwvT1%fR%C5W0_M1n8M@n=vAxLH_ibWqwjLLjQ6L;iOzq(hxpF^lj@12U&*El18`Rb zrmhE1xqDF!BuR!qAlWPYyrzUf!R!nkS`@%(tCK0woi zP-E~tJJK(gz5oGrP6-Yx!Y}{;002ovPDHLkV1gbdADsXI delta 662 zcmV;H0%`sE2eSyUssVp=NklO44CU%~(n0BfxoPy7&>c_}$gV(i1+puU zSb@z7Bvufmf-n`BGy2}l5_pg<`sRUybzqv59gU3{63gWR57@=S8paokdT)VcS+(tU z+gD22__TRC#N(CAzhA1PYn142NhQptgH0y6PL*tRQx#EPBYK|Roq z!{N|btyYn7fpC9DzX=3j?qabR7LqiS>ao7P)Hw;+k`L)K0RWoClQrY>#H3eA&frjg zV!I*?-T8bzHa;lC6%>erVNVCEMW4Zmzax#zWA_}HGzleFm>bC$L8^i@z{Gc`TLCoM z@App#U_@ms9XA?{0scM1;gB2>R{(T_lKz&P0U_!iL^yw_L5fTP9*XW|8#DAkevP3YS+6!k%Yz_f%r8vbQqf!s)=(5ZJ zdL`)t=7xWnv<{9 diff --git a/editor/resources/editor/icons/light/navigator-element/scene-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-blue-12x12@2x.png index 85282e76e2fdeca016818ab30618dc5160c2389b..b4d3481590ab78cf81332684f73af05a64aa4cb7 100644 GIT binary patch delta 620 zcmV-y0+apA2#N@>ssVpXNkl)qryGhl?GV@ZqOp~r}!Yo zs8u|8>>0=4W_gAUyu^@*&a+Or!6V$YAg?@p6hBwK;*eY#+qO?t~Xyq8t z2suR(+^evUh3tR0>(@T%>J*!9`%9Yy|FFdhDpQjH(Vr^aY51 zkShyK+|a}W)XGhg@s!@xs;6`hMqsc2XFgc?kkp{33-5pH^Ly(=M_?QHtAvEOBw|v+ zndL{i*fM=lv6CjIsYgh)*=sD>cNi3J(b?{3YmAFjYh7GwU81JW3!=|_` z&Ek7u6;EWSB$QpF=0NmQTUDlbbmHe5*yh(>TqfixYNa@3t4%9IES*6>mr#9f)9t@- zwuU(Wnl5+>**Vz3;VVSW7&!JU=o=RI*jR|5vMD2fVL}`MXmnuTtT6@dO zhR_7^>0ks;jPY%D3MuLvYx;16kK5cZo4|M+I=#du@=p77Gy{A;9AaCP3wRLnJb^fX zRF|uW)&$MjGhNFJtW}r1ePD0*v52S!Nkp140u=K{W`9I*HElqMd!h@7{rI)S?Icq2 zkx2yF=oCB|g|&YSQK^eJgBvq@4Tdod#*7G{EBq&OCA`;McXe0hN9&^we^4$03aO2| zd>{Lo(aP^xjZY#}mE@-=2hEvYJ_XAp84H+bmzZJ^T3Q*$_jd&$tqq;R7fQqh6LE;T zhfqGDIqz`-lfc(6E&Q236Sx-vl2!!H2=w#z2#7KMay5UcLO5x`F_^Ac?~DkOT1nv9 z1X*g#64RDB2bz-q&P_>I;*1M$}v4D zULSP26GBl2SIY*hs5ffIY1EK4II z*+s`4u(y29TZYoc?ASdrqxwI=u90b~#zlYsk(nk%6ru_^^|gZ8+h6}Rls?M-0Wg$Y UwrbqyHUIzs07*qoM6N<$f~^5PqW}N^ diff --git a/editor/resources/editor/icons/light/navigator-element/scene-darkgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-darkgray-12x12@2x.png index e64732e668cc8e5b4a630a5dad4261bbdeb0c7f6..e48487ca5f34d015140b8ffb4d87c4627f4a814e 100644 GIT binary patch delta 589 zcmV-T0ZlSv|W|8!NVC!Oy1X1aSiO1-;Sc@C{st8Cl0gJly>oy`Z! zvZl-BGRTX!a)1X|4)K&zgDvX_6&8y{Z?RY$Un1yqI&}p0Z?}J&qnSfI-sN&R&`YUQ zYT2XSW*7cmf&kz(fbVGyJ-uG9?q;(& zsTZWz>s4_&S0if3rfhKn=!BQvdcAhlAB5B5wA<|yQblzetNZCyLG!CejJ6%9e+p_N z>8**)Hl2`~9nydGv@=YRjzgM;Y$|6GAXQZ;2hI+Nf@ee-9T$^=X~0fCpyo_QMBf0~ zamPG>$%f@lz^P548YZ5l1>H!a`jJiRjHY&E=_>tw3O`>u&csO&@a^P5pKrix%okoA!PJG&>S!_;U-vAB~H%Ht| zC(?_2U|m6asL%}rY{*~~drxbaT?P-;{pL2{R}r!_0+}B}?0ANwA3^k`ca^$dM!G~N z=^6s2Aqe6LlTvy|0va23a3Y8C<0C+@t2xaT&UbV}36P4*tvgoQRHYQd-%lkVNf}(x zktx6D^EpLI856~T`9$;+I_P+rKO7-K;HTD}rX=oxDY?H)64b;23ALjPu@KJ|z`?5{ b{e9&Je(g+)**`vF00000NkvXXu0mjfjlvRR delta 635 zcmV->0)+kR2bl=4ssVpmNkl)nS5^vxNoK#@0 z0_Q5=?hOf0E*1Dv0d(Li;obp}@58fXyk;@6?2%UcJM+!#elu&#Crj|wfhdYv^?Lmd z!z*c&RS*P8tyU|h(`orGfWcsJvDs{f7=A}8$^jJnfL?zA^m@H3boa_zN`V#w zaFyqI)$Mj87{1eIFi&^8T{fT3i=zPI@kA+ARG^2hlA|-maHxP7(GMHZ0ifUSKf&My z4WlJc{7G-k86rR<7$4FG`f|NqUs6AiYvDaVa0BSqZ#~>8pzU`1D2~R6d>qQ&K16KX zzSlT~y0pPDqhWt<0onr4G9M%og{kXBp#H*Jlo-ad*(^0@isZ`3Jl{lH@3{b_AWr~9 zs>Y|1NhP7ql}e2dSF{&+{S_d$76@$ub}Rul;R9;JAjUn6KVdo+g9Xmt;9o9=nXf_89#VMqV(7PVp?uLbKUy(S}6xY}1C@Xf&3# zP|;g>l38>9%N;YSZ`ik#JUp`b-44Bj7f<3PgEhN#Of% zsGw;{kCVk>ky|zy&!^=5a9mOR@0b%`CRzf(^z1M57!a002ovPDHLkV1l%eD diff --git a/editor/resources/editor/icons/light/navigator-element/scene-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-gray-12x12@2x.png index 61ce40376f693e45280bd4bd7826f154c47d489b..092a279ac26771835ba929028254fc0f818fdf56 100644 GIT binary patch delta 522 zcmV+l0`>jI2d4+HsR4fh=t)FDRCoc^Rnc+6FbtJ@9e@o;H(-OB3EECTHUK7wGXY_O zh7HODWP`E+8G#MxQ!O1LIDz&L-RX2u6g^pba)=&X+^v8R!U!gZzCpdX_s})o)wjNP zLy4Vp^V8|Hz~iVVtc5nv67lU_00{IjGpSmo;Up9*XL*+xZ(@Jy6wn1gS(aRJ)lH0# z8cK*1lM7f(=v*j@qPzk?@C4>t9@o(oj&z40E@NYWrdrgqiCc-~iUa*Yq%FA=G=~-x zPft%K&Wo+-|Dx@ksN*>iw3FlYGNUUU#<7fs05Xb$%Z2B?K$dYxo(f3HWhcxjjEj?On4U67-O#-Z*V8p!m+)6f00GJ9^5W7X^C`4t6H4y^ z|Ah87-_Q>y6QEZ*)3YmAd(f4ezf1wkDKbl2)Ihgfb-43Ne_Z(injQ0wwJjij00000 MNkvXXu0jG}f;3q1tpET3 delta 553 zcmV+^0@nSf2gV1msR4fi2T4RhRCockRe@E)Fc7`^7yvgY6IeH>6Mz#?Cjcj)oj{nN z?F8Zk)(LO}GD0`N`}9)IkO1-|?;W8@?*B{j??QCr7M)v==lL*-qS=Uaca3ICrtYbv&y=Nc~o zBId4CPKd5Xgszk0le10LFn086cccln+{FTn^IalZx}XVBCPese*dE~@$pW17n@l{N zySOt%pF)Cr$?s&&Zt>+>a3L_j(3qAWk$y=3*JAt(oWXaA0^6(T!iHR-!yP1g&LuFy zT(T3S3TXzDNhN=w&XrdE?~lkjjHo+9V~N-{JYLEL_P|9^Ab>4{=K|QUJ@efCsU46U zP30t929taMSi->81!F}hSFB9!>WZ9f3?!2+5$@Vl1%>a(CD2jT`l96`69G3m2?OQD zOMna>lSquZyYMPXDQBkE+bXcI1Oo+xMW{P-woDdbY_ESPR!ha_{s9nAm4!d*)>3u} zUzGG-MYZ&MwIE_wQKFU&9V-W=WrVUIW2MH7)OI%#v5{zNtA9D;jO{@I_ZRHR2O|L< zm1`8d2_0HRCms_a9t*iWu7vzvvH-(#_fr27w%?j1V>I00000NkvXXu0mjf3rYYf diff --git a/editor/resources/editor/icons/light/navigator-element/scene-green-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-green-12x12@2x.png index f19ad8a2d6a0019d10e2050ee0a03e3f1e4adb42..db5b11fc7a15d204e9cc52db1a435396c800846b 100644 GIT binary patch delta 669 zcmV;O0%HA)3AzZdssVp{NklA>(fGyT*Mka{%u0HE! z2+VQ40^q&vZ!{>GU~g*91}>1|59`(!XltSZ()~7c$~buIJ#)x_M7`Zt$G!+TlX@`%-=rkye;baRo#8PccmDhgg;9Ev@9cxG<-WCp#l8y5l@ob)0(A z-(oeWQO5E}XK2aoxKP~2Tw#m!hk{Rc9O6h_*pMUoWlm}f2^I&IZ$9~p12_(ei<`#F zM4*{to$;VUW`#{?q*JgVqQUhQ^mWIjaq?2M=I5SX1B!pB09EA9V1?T};Aou?wIS3w zMWAIZK=je{Uv&+Nb4wZP`>A!3NAO#v0*IYb-XH4<1ZL38r>%#qt6M(5ynOpKqF&C9BrNDYb6wmx0TeE;$G6Dk2^ zan&4v-%V`QfI99sr=Lrp@|#**hy3EGWCki_ThFLufH@*Y=bw?Gk zQZjRpmb1T1DdyPXosaEkiK!yuYsmA+Ng%mg#}vZ(-4 z0d@t%71;X93?^8q0H*@z0F~emC*xSsZFWzxeU@cIU|5EcPrBQ;d;8ulz&jg0x1loh zD}NGoK|nPisO7I8`DoYi^k`ZSqgMg!4*dh2sHP^mFOm`o1E(SlOen?~n?nr?;b00EswFuxA|_^M61{VR9Od z%A(u-&Sw<1*-LZj5JTnZuk(x+0Nzdgi5~~zn25UjJMc}Sg%_9rB??*!u}PVaDE8%$98wDLPqE%wk%DXrSyvKrjfDPKf+ zk;Eba+9syC2n$*fVwm4?V~EN=Fl!7yaunxioC^^3k{Ev)GWPn4%BI4_iXG&<; z5;wwrkx{~y86*#B{C9;ptk@&jo1BI1DZgXqJyT9iK@QF)v|~EX8Tpi5$Zy2Sq z#k&6_EaDk3(zGmaQ4bPS7NFg(O`}rRTnB$~(ZXk{EyE-$u0H0BS_`3ZR(meh=OkDg zIE!d)T8fCY>dwx7gc9wP?|IWuD$b70BXi0BW7seeX&ro_d`v*9oyI6s2tF8b5002ovPDHLkV1h_HZ{Yv{ diff --git a/editor/resources/editor/icons/light/navigator-element/scene-lightaqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-lightaqua-12x12@2x.png index 756e8d7a24c7ad29996e8d34e5c5392509b2a529..cf0baf18adf886b02c7318740a6accab9382ae6b 100644 GIT binary patch delta 614 zcmV-s0-61<2!sf*ssVpRNklJ04lJk zAaVs39mEw_Ndu+>I3?gqd`if{8oya~B_YY6&o|Ha?I&q=_PzOC0k2)mF@ta^9lXIv zfKU4A)C(iHO5dC0*m-jZID3mR4JHtDo-tbyAvGChBwMv22!DS|hyWKN7?q4tlFYEh z!YWSinaT?(B2uHIiD-|Ye=lPi#Z_P)O3@UhIs>MUWM0Sj=;x`K)d<3S=}Cq=tITkP z|A^AAc|Z#x(K#QHCt`huHKzt^x#bcXM|h!xza&-+#qzqKyzia~UMeO}Z?B2K3d6h| zY~x(zb6qxg2{-R5p$U3x^iJm*k8*xOS(gy7QvT9uL*j0SxL=Y?-l!B zIB^q7KmH?+DjT;Gkeo?x(oTN62txFk+s=(G6!=KPQvnb;||HCPW1}GPN z|8#8*>Lx8j=Yn}1vypr5P|C**{vm05rN3Tz0*~oDg*3PRmH+?%07*qoM6N<$g2@*f AUjP6A delta 658 zcmV;D0&V?-2(JjRssVp+NklSf?bM;!8fl0WI&XX63ak*}w<$eRx;P?7TO>EAq->HYvn2+by=G zZ>+@p)Z=S>UtrC$4<>&WK>XWAMMsXIa3WT^Ew|_R9h*YV+JJvL4Tj^xKXzh`%)oL; z;{eI9|6*=sXS!=3(&L!}wvtfy@Wx*9?kb0XF%&PwhXL%&y^OGq!7h^)FR=`9?>IOf zgUqS-r~&}%8J5TyE)d`Ua-Qv(xjaG?C{ZBpb9j4D-H(6S698C(sPeOfcWHyRupjcw z<-l&0F2c2Mo2q|eo$xMgIGY-_GRaoU-vU@;1n8=Gk{BI>#^^ai4& zRsjO0aD5ae+9mQWm~X-OKgq);tQ+>S0>BPN%#Wm&=%$LQDo3PW>FX3wumwPj?t@~) zfkv0XC{d*f2;XVP$WOVKdBcu{JOqB)Fj;a+bW3s1n6V`W>PA8c-ALGHlpAin1LgUo`2xCE(Ba`V1NN&pr!i`~HzcpvXdS)2< z$blz(8#`bc1KU$mpvQbLuMEU^vI@|^PEJkMA+QT~!k=Y5ykRt! z(L7=Yvp?JsYh+hM24^9tq4K--Z^wu~8jF80``M=@Wsnlkm>3ht>1hMym-zQSbNRpa zvP$nsm>PDRo-luBBpa0xTckL#mFjd2T+iNo6VV#QRcj;Tu?L-9FF59=Sv^X5q6d=C zJ(vQPIr_~NcrL|_;W{S>%t{&O>c~M=&Dc?K`#MFd>%k=osA0$t>) z&kS(L#baMEhwt@TQ|yIXGGz}0w>5a-Z|=yP5%N%xp-mvotg=gj-13H$ywTqxRVAn{ z(IaZr2(UCkD(ku?6}xI+b>4nDQO%^48iSei6<^5b`i2Ui6t}tu6X>qW6x&Z`+DicR zG_K~zGuB9k((k>Y~D*Zk~vn5}s&NR)LE?GS&+TQ!El)KjZRNy`i= zRs>qhKk5t{OahynHii5k$|!+Wj2`CRBCW2V#UfnPT9ZK1=AxNY^ynC0YLB)AH|ma$ zfdN+B-(!5!YH`4DM3;_8V^rL>kzOy{wpfxs$QH;w+Artq{x+rk< zTyR71iED}Bund2uB~Tc;$v$3g4D>B+O>OXCv^_(}^u&?b=gRIUhqgvu|% z4sW9bGhU|%0v*dJFLNfIz3l?RkhKVGn-HvGy3FrOeouWOTIQ7TgX-7JoUqGQ1TJ)Y zabD_bUXfr_7h2(-CR?=PFr!?yEO#FOAod?bi(Ki22vG2&VXGebUkr^fG8KpWMhmBf=Ur#xdUTr)8|F=Bc?fT38 P00000NkvXXu0mjfIteTK diff --git a/editor/resources/editor/icons/light/navigator-element/scene-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-lightgray-12x12@2x.png index fd8272acfe29cc096928440662b28667618d1ce2..a3240703fb1d687a2981e5d4bbdddf43b41076d3 100644 GIT binary patch delta 595 zcmV-Z0<8Uw2=NE7ssVp8Nkl zpo35W{^l{JgU~@JfJb(nlSdrpk^G?<#=b+^l~#AMF^_KEEr&RcpLV-l;CWsH%bML@ zV?8XDO5{XP^TBvqHBd~pJJ-~P#rL-Pl-vIJ0o3AIo~7tbicRerUE(f7yZpN6VM z-h%AqTqiVewpxF!Ml9RhX*_X==|U!vI6ZY~4^ZCG4ZL(R#4en;#LDHemstVIe8pqJ zcLpM>FObg&rh&PK1ZD!xWZ2xZB;5*xS)GiADtYTjum$K4eH+M$b8*fH?CtEy7$6b) zQp0N(U@uv~GEN{@OMEU8q@{rf&I3p`l^#gr)%xN%$s&LFrW2eyIulEF(rjB*(*cg) zH^JUW6X+%LWUR{ hJLO=!cceeA{Q&*Cf~G=k6E^?=002ovPDHLkV1j|*8@d1h delta 623 zcmV-#0+9Xj2aO1@ssVpaNkl0H&KTQd@}&g!$ZNDA*MG@`JLPkwGR_)`spkI2Oa|D#r`HBHVO>=ouftZwQ(mjjgD!7Y#j zNwk}j=u|VQCe*!B_<6hCHmN=UtN#M{))V2IpbT?(HDLlZFk}PlvGRrjXz^VG^iR|S zGWv~J!wHxUgO!T0UZC;95FK@6q?z0m5$c9U9T8}&pg4ciiIzk*VQo>X)i$~bBi@!0 zjG=fLCc3PmeC41B`d&YgTR_M@2>dmH?}9F4-Gg`#5KR%PCs<#Ew=DM=E?zJ666*dQu*OvjEiS33A@=jIa%dEFc`Z;z3}QjSSugo$G>hx{+806W!Qla2mKNU_F`fHr ziakov2PYh={x6dgPo}&b)3cwu;m884ZKVYRZ&hrasvAX#s>h8 zLS>CO0rm~T39JQivcorsZV+$dvZvE6Y0xm1!C}X%a#=I#d9Q!d0^U04C4-pF!CyrE z2smSKTpgM-=w?Qj<5vqP@e-{8V9#ZFu*EDVQ1%Ws$;jk837miORcygMfcv!(Wh5kR z@m$wS;4>lWxri#8ag)#!fe(B&5TZ0Bz9*BR0jF%@HK;Eny?Qq?GrCAN1iJjK1FRm( z72oUuM!Z>I2fSxkNmcj&qpNsNjym7jocO zlqUKtq4p)B-xASO$$Vnnv#?V~uFhz2H=PV3aLQh1oOvNHf)p&Oj!Rv~g*;6u%4Iuo zV?c!@%vkocGme^w-8doez}Y+};E+qZrTbXlxf%#jaoB%bZyhI10)Nyeq%?Y3 z>@uoW&nMPf&#+QEy7dJjk7QnL9Lme%vS9RG_xxg?aPknzvydAlS7NpOL6>6RI&@-= z*AuWwMRqPkw{k&psl%6`t73W9OSEuZqr^G{<;-;@Dt2~Q^LpsAj)_F#*Yt-2kzK8n$sR@UicLpTG9_-xl~%N42RGqQivI-)&-Q@$2UC&5~` zNv#w>j$k=}^4Dz6E$MM-&jL?+qpnt!1Y&VQdLA9h@uZq~d85pVYHkTo1CU_^xrFQ9 zh8z7M=<)Oi{yGkr;a~bF*3tpPxsyhK8+weaMSLvh3xX3imk8Pizi{?Y;F^il7f&+1 zRTHEAwTdgk9dCag3ohe3&I*SA^q3e-)GcTzY14m?B)oLw=O|vcS3KMA@XmQIHmRo>Bgjp=Ys`64pz%#%Ps1)d`j0%~9Dm#w$=N@BH zCMe1T((FvG++#EHn<63&68*VFI^WQ?TxGG&sg##3CAg&(HQ#~YIAl>OKbBOHEw{=n z_A^SdWxIdg(B@v|h*7c^XUtE`0eoKg0))=p6!KZEy~TyKE!w3a|0Sb#q#z`E$sRZk zaD^T+XJDyZYtkrqd>-Z`tD2gL5AFcZD7Z_=apocuZt0000< KMNUMnLSTYac162!RN&ssVpONkl6N59p_C2f203&p< zuNAX;R*WiEHed>lbvP7EwF|Sreh@j#Wb=B25$R^wlv86I<;h z98v18U1)_Y@sLeTYAePg)^8+FYjSml$qo57PT-Wi$~g6oTm&H~w4<4~v8%X{r!7Re zt^H~YSfLJjRb?Eu5!d5HFmyJr2{`239Iy6p>vBLM`?G(y-a1a&1pccLjW2yqEP`a~ zsiH2<8pPW5%pD15zQ8)kQqGwu!T~prs)YTsdtS2n+)D=!Bugy064SOfkT?F z73?sB?c@vg!HgY}Q|McxsYx6!J(YJ`U5I#+BW zpQ;Wep-o$^_JJnfo2p9AQ8R88aPjpAmmgmaz%pbM3W=>VD|-noe7@}$&RXaMe!`pB x=z|b%UYS;GV#*qKLrhP!!mSR*T}S%o#S2rvH!%vJyPE(2002ovPDHLkV1iRjCA$Cs delta 657 zcmV;C0&e|*2(AdQssVp*NklZR(dCDM}OB6id zT!21=pW@U?1T%Dz#v_xxh#>hTy&%LXfiCzrYB9?ZU@09;+lYU52$C!5b8}pITUe!x zV2Thc0_DlI92>#;mQ8>Kow

n6!~VJvJfc-l3eJH?&yR5BX;ZJTV5R-u6Ic9 zg<(S!gV9UDb;W<*Or{tX)1}Q4Fz=sGFhzL1)ze4l@0c}yvlf{uCO$I@9JsVs@Q*bJ z=ymCAiK!2Qiu<3H%=+6(b5Ao>O}O1FdHK74W=!B8;Km1nj!Gi3&&_|_rPneiSkDK( zy^=BC-4lFb0ku~GoDk!EYXr(zfwVN71@qJ3n$YhRA8&s&| zk31q;F4lrS^ggF@>Qgq;h;_VZl$;9M%_|ZdSryrrni+vri+WsFl&XcKcRR|VQ);VY z0e=xG#uk5O8LrCFd0coKvIb87nq#bOBYk8ZBNjOI3*68TnUYon)~Fa%I`EFGM60Uy zTqa7)6buMFtkR`Xg*Yii(0JikZ+%%7shGu|&9YQe+ojZc;p`A?^gqC!E7RQ_i-WJs rMxqY-R*svgo5~uu&$*P|Y&`-Qq-w>@5cw$p000R9NkvXXu0mjfq_;U; diff --git a/editor/resources/editor/icons/light/navigator-element/scene-purple-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-purple-12x12@2x.png index 0662c98514840adb22f246c1ebcdc850191153ad..cd1fafbc1e36ada01246d8e64689a3b7603aa74b 100644 GIT binary patch delta 635 zcmV->0)+k02$=}5ssVpmNklo1SBW0ZeUmt zytA}3u)sb6_6@=b>>J=^suF{45U)~HDxOKVq*jKpj14=w%4KQPdawKSN5D%rTIUdl zcIS71hzN()qFEeIEn#pmqv5j&3g9+h9`SEyg%X|FGt{a&PK^sql^Jj?_FyrRYo?4iqdU%MEMP9MoEd|$f=e(`+@&D>43ydFj6)~o zxhH|#58kr&+HpQkl|(78fkfAU5TS;qbOt+wRlvGV_)LE$KU_zkmh!_sZR1*NpoQ1_ z$JR*|!LP#UIP2yA(JmD`lP}1Isszra9vB&mE0-W}K&A!bE)UvXRxrXhIdhB6f!r|o zog^UO0xZ5~Gdf`KT_saommu389Ql#V0nd1PKBF&QS2g)hhG?!`Bfzo*nfS6GMJ>Q_ ziRK{+acRni^?kRf){Z;3yHl_{lA}XG?S7+uBcNMz(JwE}*nyLo?#&uNio_=}LdO_79y+ VG#Hy`b{YTx002ovPDHLkV1mEDD!~8% delta 691 zcmV;k0!;mx2+#viHwJaLJTnUYU>B3#4;5_%&g#co)2{7;u#r!!^8sq$-jF$=>YH4^t z;?eumqb0!kzWK#RD2h4y&l7wRYq5d2a5kx|VHP?foxe?B6r{zr;A1 zGaL$Ul~}!C&N9LIdJv-obO~UU2wMVN68Z@D$sVq|Ol)!!o3rLJTm*kM$8k!6!VAY) z>-YGH5a8lkjZ-$2T}q`F&I-^y{|~X|%7ielg5fL1S7s3q0@T@QCC0U-M+V>j=Tdq! Z`3C@EYCP(f(P#hw002ovPDHLkV1hm=NX7sF diff --git a/editor/resources/editor/icons/light/navigator-element/scene-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/scene-red-12x12@2x.png index 10ea04b55b0490d7777d498b670aafd5c8deb42e..3700790fd539a5c912c274480b795a9921fe3c1f 100644 GIT binary patch delta 539 zcmV+$0_6Sj2e=2YsR4fh`AI}URCoc^RsVH@Fc41Y0^LB|zzrHFu$@3A5S>7rpkN0O zH>eZn2C_lfpf1qRFXkc#MCJLP_g;8Oxck1`k6eU!c9HiKs&M`)#9t&tFu_WZSs{eZ zWciifvzNDlb&Tm8o!mzxo8U8Z z;J&cYpowDsjmg`lA0LmjMA8DB(=1@#eqKCjXgl$q21>?@4sxaQeg9;-N z4+?BkixKbLUci1U+RDYl5>R-nk%z#Eh9~jHy4_Dq#o^>j7UE0Qu^h~*uBpE=7_jPA z99foYdBuZZh|hnPAYiC}Y<>(_4Q%7A_cgdVOfc>cwLNgmtTHCdWmi>vZ7MEx71ze` zg{Z`8<=Oz{LSeQvD<3dxC$ZDHMIdS-bLoPe%YjQgTVHJ_K7wDXR4w>PNImDtrtnRh zz~@_!-02M`U`dwLXM%w&v!P9x{3iOSPIi1Wb8IFS+yH-@o0~yj4{9<(V+7Pcs=2ub zCPXm$XjPS>OLTHoV}V5hn@=J&Sc?m)U_xzT*$U0p^c5R#;cjR_$yJnm#ZVR~kkm_H zN!pFexvb&E3x&)OwSmuv!6TFw9PieH6Ivqq)=YRqI`^P0cb`lmi|~!>CU*8{2aoc; dE&X}rAAb{}4!Pi;%}oFR002ovPDHLkV1hlf{^I}u delta 597 zcmV-b0;>JE2l5B7sR4fiGf6~2RCockRgGD~Fc7^|2fz*L1mXsD0(Am#07WMdClGW1 z+X=)8tP{Wnb_5nM@m+EyX-NV3B;VIIP43>i%l(Atz(Z{lFzJ1dNRJ?z;V%=l1=glS zN2RJJ)m{VuP60B&^d3*ILu?6%8J?#uA{7D7@P72xTCtKrFj;>9XbG7s?2lS9Ii3Rh zWt6~KY~BJTSVsj>GHWZfyc}aX2q4*`huWinVD!yz0mk_z6SkIi7(z4z+(0lY=%2H` zasszFXZ0)_7uy22naF$!3F7iHPQ)#7F}c|n+@e@rbtAtPQwXRp-yZ$nNcnZ#T+{C+ zy{q6N+??9}Z-#%kn<=t%>tee{xGl(ws{cnZkXw%@&a4>lww_qUVv!fl)7~ z+!ov#H%x24#Z=y1Gxv?kT3gil@6OmZvoo=}3u~gP21}_2|6wuwzkpZS!oKTna`&9rPO)hM2J$!|4Z6W{ssVp1Nklk7?x~5F2yy{vJIm;-p@=QCyiM@X+x0DlV+6k^CVO$~@ zuyHbAOxzMd@npcBxK#q(u-BW)#&O_aB;!^I#Cal;i#8hPGsMKL65!nfuZTR~n}IQZ zCqoH=Bua}{D>8Y`ekT^eWYnr`6K)2P4jj1BEJ0x1MKtoEh>}fj+&T8?raOzkSsBBg zs*!D+c&dxgH)KKq@5bq;kwF|wC6Wrtr==wzzXu-kcb(gVhDsrb2ITRz2fM)8_o|}y caNwW76C;e$J)@Sy=l}o!07*qoM6N<$g4M&A9RL6T delta 385 zcmV-{0e=4K1)&D8ssVpuNklcH*!@Fle#_V`T8?-hZA}Y$A ziWWR4`H6LULx+gEM-fLA-Pe{8+k7jctC>*|X5o0O(eBLJvrT{XkyrL*GKdB5o&*zB zl2I-s7IyBB;Jvy9OY;wwpZUAHEIZ&Os|2MO+yUUXR|Zju8!UpXiMI9xOB2donVSUs z9~9ADGc_E?GJ5ULnF6=jaLJH$%GM@;(T%X1X>RDQg0cu?RKch>IXFW#A?$2T0=gQq zm}fLj6qb{dRc3jkMNpMGo(F^I!qHo|Y-YzbOG1(aqfqohu8A}v#6DnsRSY`atfKX* z#6N6GC4mh=DU$sF+yZ*#!9 fgCh<;N-x6?m&7X96~wW-00000NkvXXu0mjf{!Ft1 diff --git a/editor/resources/editor/icons/light/navigator-element/solidframe-aqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/solidframe-aqua-12x12@2x.png index 162eef743a305abc60595a0215b01160ea81357a..5d5194276973d30f15ccd2349abc8cd7612eac18 100644 GIT binary patch delta 153 zcmV;K0A~NR1iA#UssVp{Nkl2tWc-iUTYlfejSEh6F5B0#Z=Y zkSv8e#+CstZ^$M0hnLF|;OkK8#<>Aw1G7gCNklrc424fSi4lxo1tZvk3E092RxpAQOrkD{ zM2X1NNbWzXsYKVzM}yUPk->0$Bi{p_;M;mEgB=QgnfB*{s002ovPDHLkV1iAV BJ6Qk# diff --git a/editor/resources/editor/icons/light/navigator-element/solidframe-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/solidframe-black-12x12@2x.png index 2cbdc774c5dbeb1e6829fad8ffc9d0dc3311500a..9354ad6baacc0a53f40d2fc4124b674dedb743ed 100644 GIT binary patch delta 160 zcmV;R0AK&M1i=KbssVq3Nkll!C7_RXw2O{%PhA)mrr`mKA0V|4@m{n5 O0000TB5&>kwL zP~bxnDM1hSdGZhVy*B~%fXWRskIuOzEhn@QV~iD%{W=)RTkrka@p#7PfVd6B7#aPh zYTyeR(0~Rs@VfvJZRjV}K>82n6cIGa1BMVR)EfusUmf};aTg8d00000NkvXXu0mjf DH+?^| diff --git a/editor/resources/editor/icons/light/navigator-element/solidframe-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/solidframe-blue-12x12@2x.png index 6478bbe09152e0b8e81ac0cc11200eed9f38009b..19b501f1dd8bd7da2f5f0a0f595adab5b43cee3c 100644 GIT binary patch delta 155 zcmV;M0A&BS1iS>WssVp}NklJQ3;!1vbbEj6lZ-bd10X8G%vQ zf+_^N2}qO)1;|%ewk-L+Gw^jx?8d!;FBTxQNWs8?jsa7($ymmPr#bn!5MViI&0QxW z-BuRaxPlU1Mg=NRfeKWRSzuP=LcZEVQ23s!LoysxUgmE&0eutW6x&VUfkyxU002ov JPDHLkV1h8OKOO)8 delta 150 zcmV;H0BQfc1h)jRssVp^Nkl^`5QgEecM~pHO1iJ*VssVp|NklGe-jrAmXL9-kozd&s2&S0Sl8bDM;b^ zv1B3qt$aZGl1tlM(g%E(FuSs3`9>SafFW06*_{OWD`elg^th>9L0zT zQn1pdAN{xoM@R^H0mu*2yAhE^%ck*YBWZ%(IiA6sE$oKl7Y_G>_!2nS@g+fbD4>7> o3Puz}*hwY9nlDrmH36iC6Ru$lB-5znQUCw|07*qoM6N<$g08GKc>n+a diff --git a/editor/resources/editor/icons/light/navigator-element/solidframe-green-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/solidframe-green-12x12@2x.png index e9d8011968eec9c4626da569cffb8825bdee5566..7d057f3ce5e6604dee57a48dac442b7c3a467158 100644 GIT binary patch delta 159 zcmV;Q0AT;O1i%EassVq2Nklf!TQgq(UG9Y3@af zyR2=`et=kbS75x13RIv16{sMtfUqDE_NzSv$swH|1WaG}G(8u7!v$)h9nAcGw;TWf N002ovPDHLkV1gFVLO}ok delta 150 zcmV;H0BQfg1h)jRssVp^NkltY3mOBP5=M^07*qoM6N<$ Ef^S_vRsaA1 diff --git a/editor/resources/editor/icons/light/navigator-element/solidframe-lightaqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/solidframe-lightaqua-12x12@2x.png index ef2091c9c4095fc49dfeed319e35c16a879edcd4..ba71cb3d4080bab8baee29a15c9d92de091dbed5 100644 GIT binary patch delta 152 zcmV;J0B8TR1i1vTssVp`Nkl5*N}v}ymTMA3LT*%cykM* z1%)COsYURR@036C4g|mh<8K^eCRlz1(SEhU}{*Nu*ZS86+mFojw=g3 zKm{sLfeQX82xx_fMZx|o23`j0b|Y|whf>1^0#*|z7{1{T000UA07*qoM6N<$f&!sB A{Qv*} diff --git a/editor/resources/editor/icons/light/navigator-element/solidframe-lightblue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/solidframe-lightblue-12x12@2x.png index 5acf4aaa1b55b63537d0232761137e81c793f4bc..5b1dc15ce319617d0a104102f01e100b4bb6245b 100644 GIT binary patch delta 152 zcmV;J0B8TR1i1vTssVp`Nkl`fc` z5LvsC6^Y}n1DSXFlS%$Ne)u}dhhZ@#DU*#gAsA+I`k_**JG1MNFb0=96fGNtP0d+* zf5fBqA>n02AOaDHKm@S`npn71dkA(qJ32GrXg8Vsh6DbJ58e>NTJ}o-0000JJ8c&j5-#^@%-aKTAF%E~ zIvEapfB^;=VBn7djdUg)SkPS$MAH7l0mWDWxgrlFumGs#000UA07*qoM6N<$f?!@d A`v3p{ diff --git a/editor/resources/editor/icons/light/navigator-element/solidframe-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/solidframe-lightgray-12x12@2x.png index 8b015d7a8c8243b3e3675e935ff175a2b8cecc76..020dc2389a8e8da7f78c6d859b9a38f65c19d2fa 100644 GIT binary patch delta 149 zcmV;G0BZlS1hxdQssVp@NklrU z&?8E4co`Fzzyu~Rfwmw+kMt1GncLb$2boVMe!~qRQWV^ZTgnYV00000NkvXXu0mjf D1)Msv delta 144 zcmV;B0B`@c1hE9LssVp;Nklut~s36WRol zh49EI2M+yCeWhP-1&jxpGD#_QL^N?2@Q&=98@%_+UTDiMFP|05g?>8_rve#(o^U7l y921zp1Sa^SAVN>R6!5bcj{}uNc{ng?SOJEm6(m3ZA=3Z=000O{MNUMnLSTZxJ~r3@ diff --git a/editor/resources/editor/icons/light/navigator-element/solidframe-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/solidframe-lightgreen-12x12@2x.png index b1e3ee0df4bc40157de0efe23ebca9aec1a75c8f..1d9bc9ee147aa59b4db0553171f9b0ee75f6bfbe 100644 GIT binary patch delta 156 zcmV;N0Av5V1ib{XssVp~Nkl^`5QX0zgc%9QU<3zPKmrbMfCMa5LZ#q? z(9(u9X~IU!0J(3vpX7bF9q@H16s?_`0=!z-4oQ%zU?xrT=DRYC8N8&2d+e}-YghDF zZnQuq;zJoPBLWeKKm;PlDj<+XHb~tB2h12R9!I-F{maB}H~|!EF&Nx&7D!HZ1iJ*VssVp|Nkl8V1D-6I?cS+4ph0Wt@c;w;?hD2{ zl?G5rT2SF*L?8kYh~Reu0$J4K9t8)^nUX*bpJQ3n2uwmr$qLy3Mq!XhAud3X=)e>p zUt?RAeBT-PI&?J4lv=WwkT*Kf+Oe%j^H4|sfC~c5fcQ9 z`?~y)cU{0dkn>__H5X5ZQW8U$)KgcD%*U3yoO}A{$9GC0%QoPN3ono=7|`)C3s}Gc v7WiL47)dwX26Um>KMi7S18PQ%d1D2ZycQ%KGUj#w0000JA5Jmri_Kv_Px`8V=f}JDSIf5%V0%KUZ zhf(ATB8eqfXzo>a`N=&(^MS8JVHk`vPGfcsH4-4gLM8ffrH%I@1gFM?#N&*AV2d4< z9~<7)o%kRV@h>R6j0i*^0uhKHtH3vrMJBk_o`M4%q9Eb8<;obuZ@2(a5EtEU@+@Tl O0000WssVp}NklExzHnMmH|B-VF|?2V=@Oe$mJV8#Xvz zKqm2njGs|~3RIwi;sivPk%mR@qr znoI8OufX3$*CYAK^W4}SibOkmrnpAgnjEC1y!`ALc(m+ZHungWlt1e5u?%1U0~o*n r$^Z&blU%hoV7vzf34kyRMSnU;N9YKy;0SKuC~n{guFw%2p_5n>M6?Bwwg?{b zAc2ICmsA rP(U8d$WM3{4EaFeaxV`DN(no?@Dn6yF4?&N0000rFoaAtV**KQI{!EU>@=3)F%eI<6++JDG}A3-%^+SsqO1 V?{;BsQ(OQ5002ovPDHLkV1lR-Ezke} delta 118 zcmV-+0Ez#V1egS{ssV0UNklZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Apv+r_8fO{8fVvdtn?D*DRLm`4MT?>eE|b`UN{9B%>QppE$)x+yFI zNsoF@-+w_B589u9dm#Xq9`@YcBjTaos#eI>uoM~dg}pEE?R2W^WKc3#P?}Z%y=)(H zfIg`>CC1z=*F?AcJmx*E8vPQ(v-=gm2`g4K!E<8JU(O{>6&*jj=j5`D>+>525DBWz zN?6n7cd@4YVV1A)UQ*S|_OKbT)XE4_E78KQg?}WMDK9V7I8k5Fv5h1HA;LtB16@wh zcpX4Qs7Lt001ZCGF|K;u{~AuyT|B-Q$2wXk#oV+NqnE+QwH8 zV1G45B{Iinm9t^I)*^n*a@Em7+yPx#1ZP1_K>z@;j|==^1poj78%ab#RCodH zRLgN1K@fet-YU6#A_K28KoJNcFhpR;01hCpIcPcXy~vIL9Dz{;T1Q|)AOub-7X>?d zGs|azS!$${4(cklX6WwMpVvLWo04|Ff>y8g5*Kl{)ZoA$bAR@vjA0nNxOs3Dk+0j+ z5(?j3-P{8xRbh|^{^sT!MFkf(w*YB-3Xo(*@CS4Le^qpGbqla>j~8RLnwq0yn+_!F zl2@MsB%AZn6HI8iz$h%6`|aS7l@v*K)ry)K0Du4I)73v<9UwOq)y<^!n-!Fhs7I^q z?I7MIa|i&HW`8a+CBWY!heRzg?94J5PRYxX6%;(Io?Go&<053OdC;wDvZ|k_CiXEMcOqv0g{J_UO@D+uk@cMcSN^pPJU>7xf%z&G zU$9As;ln0(tMdcw7Ri$XnWwMmPN$Me9*mFt03?k>Yr^yrK7E{U4)uGa=lq7cuF>h4 zPm^ibVC*EfdL&P{cqGo_9zY~@N?Q^W{Q4+6y<~#2(dorBK1{|Ub`CsgvK0mMG><~- n_-&V|OyV1+Qc+F3%WLErTYA80m2@Iw00000NkvXXu0mjfZGaeC diff --git a/editor/resources/editor/icons/light/navigator-element/star-black-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/star-black-12x12@2x.png index 30006123346e4c0b254fa57d09578791c788ca01..8fb9ece26332ce1eeff2f581b1108309d603453d 100644 GIT binary patch delta 973 zcmV;;12X)m1NR4zIDY|UX+uL$L}_zyY+-pIP%{7kc${^Ry-UMT6va=gQqVex4jmja zi9^)V3U+a5D-=aAR0XS3ntlmwd?YDSaT8Z5_#aroS#Yq3RB&-{5JU$N-JCipxM+CZ zmsHv!-pA$rIGl62T)-Pp87uYzDCw4wOvI$M)Vkz*gNL3|s()s(sG=+i{{6e_^U?L* zPl#DfyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMn zg3~UaJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApGZGS8XUA7^PB7#I zffEo;FmQqiCz#wI*jkVbsxy_q&@h@G^hY*JFm-S(?`Rn^sH zAwIh}wm{GG-0gPz6U$sSo4pQ#K-t)(gr&fFgFH}ov)OcP?J~AN$8lQ6<5BAMS6e%) z3|JmG_kW;6I3MCwy;v-|Hnvs-x;!G4N)7NB==GhAtyPH-^)1UY9*=$QE0v0}Ez^mh zTCLV$+7yKuUS)dzK1^e3i*$Tz?Y>Tkd~Ab0?qS0#V%q@EuDD?U7w1 zkW#7CNT<_}@ImKY*gu>RP}q6^F?ARE08sZm$7takx{QJG@=0Xh4x8Z>fkASQWs3$F z3pW@GGR8T_M;Or4dcE$LrKF@Ujh4%$S}YcWLZLwN22%b#pU?d$f_y&T(U{(JI_)T> z{(oFzVlSF876K73zQ)83zE}dz9%1w|1?}vyEa4tqL~=U6O+>(hLk4xB$AWgw_Ip9i zf0fH+9;(nId-&hP%S8qn^)kG8m^V!vcmSuoguLlKziaXU4ba@}b{vGyz_yWX-zo#n z9y}C`1@wi^pPx#1ZP1_K>z@;j|==^1poj6JxN4CRCodH zl;KUoFc5_w75~WyW`m3nCZJ3}M(74)1G)j-fG|PI1RVi32pbfi{48H1$FU=j_`xSV zC3f!YyYo4~A7g9P;+K%c&s3A^v_U@ie12Iy<~m&=pV8{w>VL+nwz}nJNpdrg@>Ev6 z)f?Yy{2(uIwKrV+%(+E$i7K@~Y=cj$JB|mq3?2~Y7@Pb+=#rRPW!o;;4&Lw@ml+5L zxWm-QVfJc#;M_FZ2Cl;lB5YL_PblY^z9SO%#K5H|h9}HKlJFTaebCWCGD@|hd>d)I zLm`HaeZuCIHgdB;Y!)^UjtLvz3>8+OFPCTfH#M}`V+B(G6W=95Uk-nZ4Zq33jwqx? zIJgF(eI?Qkp#d5-ZcxCUPCn{sZ|ghbOWC0SU5>flHVFNH@q5U@&>^R{cMQnjpEY~~ XSi@qG4l9rr00000NkvXXu0mjf#xkcb diff --git a/editor/resources/editor/icons/light/navigator-element/star-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/star-blue-12x12@2x.png index a639fa51c19cee00e07800f37df7338f61c03102..3aea5d3b4e6ea7b1f22d6e5359a1265ddacbce7f 100644 GIT binary patch delta 960 zcmV;x13&zb1?mToIDY|UX+uL$L}_zyY+-pIP%{7kc${^Ry-UMT6va=gQqVex4jmja zi9^)V3U+a5D-=aAR0XS3ntlmwd?YDSaT8Z5_#aroS#Yq3RB&-{5JU$N-JCipxM+CZ zmsHv!-pA$rIGl62T)-Pp87uYzDCw4wOvI$M)Vkz*gNL3|s()s(sG=+i{{6e_^U?L* zPl#DfyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMn zg3~UaJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApgGdWaU2)~CYo1%ve@3kqbg z44alddeXiQo6A|a#QGLedbU@Hp&XzcS-xMx7UG*`W0l3PY1 z^ndg2^l9l=+AXe)r7b#JkARRRwOXYLzPW$Ofs&bCt75|4FF7wttxd3!!u0khJRYA1H)dud#eW7PSA&Xa iEA!U6Px#1ZP1_K>z@;j|==^1poj7B}qge9g%bpB5TvfqF=5`C@5njFH-EENvV&PO^)ch{6^^&% zE&~%M{$~EtrPQye=oPJ9j8)`gKJ zSg^)rV}j@8L%67&&vR|7=aNCn!8T@1>HS@dLQua|+rUv2JzO-`cuwjzDcKBmZR|`w zyBkxvBifN7>rp>fR=wngpxV%Lh$#CZW{02lRqQaGHGjtt@(s+;ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApjQS4k@a!h^}a-EMCj z;2qif9e)P`k3t3>hwSxqbaf%B6Q0dxbKs)YYVm@#V2T_-$$=3oO9+@dn3l2i3bKQC zyWPu@2aKoPZs$b~CW*-?ZlMtP7ID%pj-vr+NcDs%0 z9{d59{EU4oVc3H146GULg$y8?U>Zv)PU&40pnqnw=|XoQ#zzQZ{>=f2rFXqv_iQFC z=MWnGWY~3G6OA_pJ7jRs?K8tv25~1yeWIkXfPHPfUI$sm69KKDH%vYusWKH~JwV22 z#!~N-EC+ICVN4Nqrc7?5#hwLU<!q2&3=dd8tb9=G$b8PKq-BgIMD=DwT>4qbxs1Js=_Pqk0{q@JoImNU;NqrSQ~P(?`hLn$iz{}$*2%xoRux3$SH00000NkvXXu0mjf0?n*w delta 568 zcmV-80>}Nw2jv8iIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6`bk7VRCodH zRLgC`KoDJnxx0fn9Y6)x6$AuG+<*?C0-yqt3LrNmK!FNuD!?UBf(t;9_sA@A%o=TS z${{0JGrOKQ|5>H}617^bMyJ#1{{-XMD$=;)I3IEh*Xwm`gMTY2ODdI0FCwOJ)U(Ff zDqb#^2G|Z?LK)=Q;H(_5JYXIo--;8@b=|5B*2;k{Pq|!$R1q!v zz*3En^=n?oIHpjXAd+V`9p6M1(^!4&N6los&;bc)`+p+FMLKZ47hbs4g%0#0A(LA( z^RKD?C(nqHTvbc~zJv{vCFHU-xD#+v$5v1Ik25d942^-BE~R+~h$A|YO=dsdAg4+O zK*o`QuouQB+*l$kR{!eVaq3`^)HuZK4>n9?D&Qm61W#s@1cLhmpIoq{tbX+o& zh)+Q*i!n*6n`{|-0PqM?#He>g<0s1$q6b4}N{sra-_R$~685K~kOV~l0000ssVqbNklBdykVx3AmB+3b%o@)bckNe)CoGx`EQe=s!e}_I}5Kx%3cc5fS?+`lf$q1}YGB&V>r>m8Q}G zlp=ElYy-~@mGu#{gihQcf5X|ibRfaK^&_i%Q+e5^1DgrxP_F^6o`9w`dVz3JQO?0$ zTjUbiC^4!irC=L#t(eif4FKflx)BF)jrHz_0|^CSpXO?@!+Pyuc&xxy3NE=fL&HJE zNotS5npV@(6A*t3zp6hW&n-#?SS-%SVmWL>EaRC{+(6%;72?+(nOwZ{;p=n26qWr< z;5)265my?}~CShq*)|?ejb^ zSLmdzwYyTpE8p{akwNx0JBkCvsSag0lg$;r44`rzA|HC)_B$|01-;SgJ0000-nGjF1tK>L>7}QO@NTKhWJf+p+ZY=@9)Tsq1>hD6X+dVikp)mv7N7WX~Dg#27_6KzW4l04K7)kFkx-K+AvQ7%lcuW%_P1QclT7 zHsM^!GsPp@|N*2vKiRm5D>JCfiAPn z$d@jqi3~Q39ivE+q_3)~p&1Ds;=BX-0IstnBc+sly)*LTxaMy?%{vNhoREh$iD6Xp zQZafs=?pz-wDf;LN>%dtWvsK9ad1bzmNnT@f&5{L+;jj*vAP)@9R~AN&pFVC6i(0h zZ>o1Ii)2Z*WQ= fE0CA;FTas5{X2|%7k%ES00000NkvXXu0mjfGBL`W diff --git a/editor/resources/editor/icons/light/navigator-element/star-green-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/star-green-12x12@2x.png index 5ee44faeba37cef95b6d6ac955309f35d0bb694d..c95aeb6c841ffdcde44909ca729c5dde9c70d3a2 100644 GIT binary patch delta 640 zcmV-`0)PFQ2%ZSAssVprNklcF{p{Pml@@ zDu7gwbU=8D0A1Kr5IP7Q93||_Noaq@XAeJFU`Ylkd5EQvJTo49{LN<%zy}N38kQ!m zlf*ayf^t-#@8J1?%{c{@lElho=M`3+VyN1-=kj1J)Z}#MB$|JsAGW8gG7xy=_U!x- zWDrzK_m_^%S*rjB9+n)EPdr4|Ds0)DwSq%Nz-V@Zyij6qh%0*%15iisTYHUHtOr=2m03%1)l(Rl%#M@o={b z5p$b5gfLGpe$9WwENHy&K4z#&_wH$&2WR`{GRGTM%bT^ek{`M~MC`K4&hc8J!x2&( zx~@j-qd3>pi7x%ytpFl?D@W(>iRtJ7;%!ua=)C2)JaNnaV%6n$Y6}rG(p9`7!(M=O zkVIjRcbbw-u0UrCZ;Ab$t+bEGyam?@4Ni*C4t83|9!-B&5828OYjZ^E>QJ?K-pdML z_K+MTx(+Y=URHBDSZIiPzS3rgY_!r-V?pX*<2zi*hyu}u&mt$Idd0Mjl`xAWc%XB1 zep~>4IO#VWW#hasuHA$XKQrcki{o0?EHd6q%}3K^ytAX#E;7R6=4v9su)|O<`Efq zlrrEyfV`;TZ#{OpW_SeRC~8c;S!M771r5IN_qgj^MCcsK*GVvt>P6UYFKIm*ok&q12qo!@W2S%BvxuNH43|F+xz zA0Mo1C^@(=CMk5J&aRhcb^HX>6an<+pl%I`>-v6m#ZbiUF1df_H33DCL_r<5S_v#X z{0j&$WmK0|Z{*Od<6A3136In!Q=XYyy)I10OAfeYrTkDMJ!)N(p0VXd^^%TV`*-mQ z2$~XQ>GIA;KUoH`)E z_WmkK%e8u+&gFk1+6n`~SrKjS^qTF%M;#bJ18MMv8PZ1-oBQ7PDLf(iU7G5@s_x!! z2751CgETl6ck0ym8im@!8N<}(zSpZws1kjb0|yN?e(&Pn#ZMH56E zv&x1PGbC%5oqroOnYt^q@ERJa59z0K8z)Wkt8^kYy=H$kM8FAD2nsPSf&*Q;f>$Oe zl6YQN1TmOZ*$_cN28mEP)s+blO)*GF=E$D&*Hq^FGffy(#qp{R7}GX?*Y?8f5dKnP zM#dC@{6)7VrI}g+SkChW+hT^!LS37F5;cJbPZ%7b6zgJ=!E&2EGc4PZ0Q_tZawFP^ zG_HEW-4Jvs?AxCf&^k8BhvhhggYchL|@v_x)3F1r``r~Co< WUk_pOD(=|;0000ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApL_t(|0o7H@QGX*r41IEK)v`CZu%DBifk^;2 z5iE{iy%DS(0c-@20T2NY0SyT-8F)@$xG*=kVDZ$`V{8~qyMP0#>iKj@deW2B4ScXj zs-nBprZ#X0#j@OD&9|gTv1=ez1eR;}0 zz>fMyn;z;73ja$&rV^d^ShzjR5mB_5L0$zz{gYSp|5AT{mLfsHLJs(q&+OkJo9=s~ ziXbgK&)8;V$7bajA`P}XBUP^9i>c2MccGiC&3}#ga3k$M#yktsjHz2ByJxF1c-8Sx zm&f0*MMvf|kJR{DfC_}K?J!uS!A8Y>oo*En^$tj7KlKQiP-gG9=*%0mJZfZfbbNTS zITi+p6czrvRFeyLt?ij3Vu|2%9tSZUz}={|nVUKmus+fq9pjw9!}TlO3gNFvA?4ZB zwtr&R`KrASs=*UMmxo&xhtN^kYgFONSlBMC<5=iwu#z$$tfgGwo>Vn(9-R;T57{{7 zqO<=Nb?6}B9bq(;l-9Va5$lYp-&`8#`c=uEWI1WkP-I#Vd?hV|*d5l};d*@HJScEB rJ&h2kZopIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj70ZBwbRCodH zRm)KVK@fe7R%v;0J^8t~W`GIE5`h?jn1M#1MxaKZ83+-$M4%bC2TQ?=+&n@1diGNY zyEs_o&8}KzcBenD-*h*?AB!xa-015Amq0$zjQ3>dV^f2tM1KQq*}|ueRX(2L9e{G^ zeg#9V;n>&6o1(@*KV*a+ov-t?PMY?7X!6Ry(W3|mr$a} z++>j01;7}?B7Yabos7|&az2cAq?5lglWT%XXctWTWzdwm+SHk4!PKAm=)pkGv7j9E z^~!9m+K4_vf%kh_q4ABhp`MK6oXaYiv=J);#mP@LW_01uFr!H{C3=w|Hr=SNr&vS` znKOLVPNhy?@14%OR`$faJ_s|7c#ck545OLL_6U$Sl7FJefLXQeDRlBPMXSn9K-YMYxudj{FYPk(rt59VhIfGIMeDkZM;@Nh=~GrEA)Vg1X)3TXPFQ6p zNNfL`d)HW)A)-ubXxl==hU-@0pNu)!kyARk5J^XbopC1Z=D5mTm545(k#5kk+9vY- zNp$h1bT}-aO;_r)vtY;G0ce~U6-JQ_xU$BvZ@ix)$z~Kmbn!30kuSSd>M0S7TNnTU N002ovPDHLkV1f~x7=8c% diff --git a/editor/resources/editor/icons/light/navigator-element/star-lightblue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/star-lightblue-12x12@2x.png index 1cd3e28e06e139adaa238c0ca379d76bc4868f16..a219b790977d11890dffcb44dbe6cdcebdbb4089 100644 GIT binary patch delta 928 zcmV;R17G~;1j+}HIDY|UX+uL$L}_zyY+-pIP%{7kc${^Ry-UMT6va=gQqVex4jmja zi9^)V3U+a5D-=aAR0XS3ntlmwd?YDSaT8Z5_#aroS#Yq3RB&-{5JU$N-JCipxM+CZ zmsHv!-pA$rIGl62T)-Pp87uYzDCw4wOvI$M)Vkz*gNL3|s()s(sG=+i{{6e_^U?L* zPl#DfyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMn zg3~UaJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApX#US z8UYZ25`jYmnt>XD8iD*-idB$-8^V738c+Amt{}5IROyFZ)%%$3>CF zjZ5$c7kq4@fsXB%EM{H}v1YKxYnz_n5r?tU>al^Wz7L1ggKfu7i&}xw#%? z*mnVVdVl18sV?@2LCn-RifY*9HMRfEL|*Nk%VKFN0qoTENJCN)*Q1{;yr0t#2sA*r zpv?X=x>DmSlE71ZW(~9`&2*udYkY1)+cjq&DH3gu2%9dA)-hkyy->xCZ*e?Xipv=| zhV+WJveE3VvwS<^V@e+jI@U0I@AmMjEHrr^*?&!QvIL+(dAG{a6Z#23MqehLxh9@j znA7GT%VFjQBsXIA#)dl`%C;^zM*Vhg6$Tl(DkQVt{gPFC7te1{D`cZse&4ocIuVo>Kt(R8ZoZZWxkwm?EP~ z&X`z^>6s=JZFkL%xNNFa&DC7vMNe7TgMKJg7{KZ2DGhVsCwGd*(G`kfUeNLxj{R^u z9ss2}&h_`$H7iO|IrE#wu5w2j~QlIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6{YgYYRCodH zRKZarF%WF+nd7?|++GH_>hRsYup_{Z06PN{0dfRD1V98p1S~JWP-TbU5c~$bqBSco zYmh+j;=xpDrIlu;H8VW|zLMxW)74|s|A>u>RkY4g;M7@l^na$xW9$;dN`Y;+niF6r z)+`#n%|0jV z+|qck++S%lePuHIkbJjc>9~fTZmJpH0$R1nX)~zXcsp6&7|oMCF0EpZDVcip#>P_B z)*)r&yZWCxc&X#1ss5`p7WfUD%K{o9DKBB`(DXSE0)L1!szT*KorNQVkJ|477}rSa zcxKPb*VMQ(gD!&i3`?71Y6~V!c+Wx>r6YoDv6v${Bj-`FXXta{FLGJDi7gx%GIgDt zaU60zuLz)o+HLs{JmH}f^&R|{>(*2pwA4@tkhmwpo+_ diff --git a/editor/resources/editor/icons/light/navigator-element/star-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/star-lightgray-12x12@2x.png index c7784dbd121e91a17380fe5bd9423661454d4f58..55cde1bfb4db898d2942ef160aae2302608f839e 100644 GIT binary patch delta 926 zcmV;P17ZB`1jq-FIDY|UX+uL$L}_zyY+-pIP%{7kc${^Ry-UMT6va=gQqVex4jmja zi9^)V3U+a5D-=aAR0XS3ntlmwd?YDSaT8Z5_#aroS#Yq3RB&-{5JU$N-JCipxM+CZ zmsHv!-pA$rIGl62T)-Pp87uYzDCw4wOvI$M)Vkz*gNL3|s()s(sG=+i{{6e_^U?L* zPl#DfyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMn zg3~UaJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Apgrj#f{46_70S;ST|KP~2#+{N|HTE~m1lqB zK*A$n{C|^6p7nKfwIBjC9m3OSG*419QmItYnqd+QGFaY|$NivQug|j(G4;{ubPCl&%d!Hs@0-o$ z3PrA>4vs2E1Q6&HterYa7(_LOaZk45gx*C7LVsP@2t>h#lM#ZLT{$4J^$`7%!vse& zI2rwB7&R&pzevRu)D;$^E#y* zuzzsa*z2ir%*qs5`KZq~c#mfiZ@x`6sdGcQ{{v<4x+q)#qvTz2frNa3yDn#eLzfJe zRt7N6lw(|B+^0eIHsES=v8ari9mJio5>mYkFf>srfL4W*ZmZS0Dt4wt<6z+YN$6xC zE>JA^d(0Xqv7LD*&JQ2)4@DW${h^eVeHT3X0os}&0L5(w(*OVf07*qoM6N<$f~Ih? Af&c&j delta 577 zcmV-H0>1so2kr!rIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj714%?dRCodH zRPAlTFc5Vh17w4y8zcgLlT6TL0_X&V2?`Umod7lfCLsLfLt%uBkOBDUdtgUtWJ{(} z|MeuxXZ!Bn^ZCv~{INKX81MJ{H72j!ZpUF5mNq^uVJQfnV1J4*g45{~*!o!mIF9oo z)w0!U4Q&0a0j}3;g0X^nq@L%wXX9rDAk*W4`BH*-wrR2gQ0W0c=DO}&>Q-s0st8y1 z!OGVeA=nJei*C0Yb1kbWz+S4e2Z;hzR@`*yketuw1(@pWnSb75T3fHMjxg3bd&CmE z-7fC+dYLO7N`Dm`^BmKr0Z?{2ouyjC@e`y9*m@1S2-85uxt&#%c?)cQz{tluLBOea zKn{lkeMeABrjG1?08sc2xZX_M8|sLTO;s*U((uXP^IG@OCLQ^k;1=%~#pQB&RcthN ze1`>853I*bUDHNerZAj<$urZ18g70kV6i&R%ZZ6OmSRcmI&j>2jjoPhvXk5f%+gYnRRNF)*VvDB#h^_Q0uFEJj?-ti!kJYPhv%ylLEF}MrCOo^ zG^y&IRN>-Vn9qN!xVy!-o?w_Q!^8oy@c10a!nqC^T^?cY%jJp2mgC-rprirQXf|E^ikp8lAwb8t#1ze#21E6dqT;&L zGp%Ev+u%Hp-&7YdEW}3z;Kh~2wRHZ*jv&9=8&LMUW5-mRkZ%jUiGj2FgVtCqJfyyB zGM{XSJ1YZ@xgN$cc_FrYi#rHK7YZvW157jJVpHb4$QwGOwjtYXKD<%&MInphCrne~)murX0000_k5Gj^%vt zCovqmQIl`UeN*3%bZ^-fF>!_>ZAW)0n6z0BsKz zB;(<8}x&OPxR(L?6QZ$dPE^4(X|mIL_8w-*HzO);&V?`d@;o+H8aZa@O% z-0)=4yf4|#PsD$2wsp)CFz0B=DNdI?J3&G++!9~l=Kyc(C7(^{1-oIp*sJ;i5X#F2 zb24nc|2AlE#byba89=m>Rhy(=uwB1^vlqifo7`|W#yiQ!Vl946;9{fn(UMhQAEe64 zLkfWL54NB8_jqNBgw~O~hMOUQrJxxt0zAkYU-BS;T8n>@Oji(Bg!VvL*L9NMR0jcE zMHpeQ9?9IlO{MqepbWOeJ6IrWR#OJ c{kOldU&lh|4cu6cjQ{`u07*qoM6N<$f{i&E!TZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap7) zL_vJfPC%Ie{tyqTFaa<@$^>)+GD5xqaXEI9KGSk5!3UNiIXAYCeQe(Ve=Oo_m|VF? zLOjBu?$)psA4ulo7r<8n>@s+RT7-9WeBDA{LkX}?fV9xJef_*DPC?X|0N>ALDfxZuJT;@yD2q3w2O$Lc7tw;&0xF5gbK^#t# z8`r9|50J%&VwKvMsv(s=mIz04lcSlI$q*n}Y7ZR5M{++)QN|Bl!lqNFA%>H4uT-(| zn>>$ZqDD;gf?B;i8ZBCK?Rp|OqnZ-rT+y+DB!72qSH6sex^w8p$8tFZU`D#FH7h+L z*yVOxx<3Z)yL#}6GY0Kgazbi~VVDCbLD(d%X5Spv5SQFn*_H_r-~sFC%w8dLV;Y}W zuofvxjk0{+dsP5Tq*VkzCnddVlSMLa^l+g~fI*>Ui%k~A&ne27*;9GOac)dq5ut%+ zwttAL0BGZiZBsuHaPC>D>-d-%eT|AD>%NPx#1ZP1_K>z@;j|==^1poj797#k$RCodH zRKal?K@jXcpY$dJ;S6vDuo3u(z))r6@(&^aB9Q%ZSyB}^0?QHH5rGJS5biJQMm@{v z>Oi}ym0o&is;FCbcV>E~dlq<0mS0PjU&`nuJ|^~}1~(P{>VH}cteu!5#xFsnG5F_t zSsH^cv3}7BXqf>2So0PYvV0|-7^kQN+8%y1;EhyFqU-qB!{3!vWLE)Z2_cBkUQM+)1{-=M6hhF{}9=LiF4mw z0w^BAq^C6(-fz34tD0APL6o^#z?q3ER=1 zm?fUEc0#qym0YlR<)vin#*h04gO>l2u1VQ%B2hU?ilH5w-7|TPeG2-F+dke&&VS2- zrOvtB5!H|_*?R9?N{<1QhYop}*>C2@@g1*Bd2u24_(Y2A{j&z$ahuU;<}p zO_Wgk0VC>7ohdlg!331xevnSlkon{_t?DyDh9J(c4fxwCVLF7Ila;!CwC)+OiRV%CU0VpNF3CP>V(`yFtI6){YBsZl+EE z$^MDZGgICI90CvXF+Qr4ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap=X8c0NLAAk7tb?ugzFW4ryt2dUtxN zr>nbXfd>{7YS@Y;&Mm%Bt!(9Zo1`WS*=G?b1mEXW<%oY;G(z`1LAV?++*GI-gLk2u zf+A3QFn>M$H_;*3ZM|{d?#F?r2gc%S#NodEK|N$|5JjZqJp^gzhZ*Sm(M!ofX_`4` zy^>vm#AQY~DIwrR@lKj9`S{SKz-%(T?n6%0h*s*}XBn1qUixj$+X#$1xXrCpV_~Kj0*m3L8%k*3dp-r5zT< zu;id{k{cvkInZdx{a(R+sjYRnhazTT5E2L!J>aG>42 zHGicxD;rIGq9cRhDjRDt@aoEo&#qZein7nXo>e}*mg@W!@oVgyXRZ-9anNAmWZGOa za8h@uv<|3T4sq^Bkm3?;(3cR0{>)j17W05yzR`)s%=Y4@hsL_&Wko7z4;`3p6x?}^{|s22bL002ov JPDHLkV1i<*-TVLm delta 622 zcmV-!0+IcN2%80vIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj7FiAu~RCodH zR7+CZKoET+%ULTYh!R)!_6e|05c>q!H^2)>cCj}p!-nJpI46iX0nQ2Vk}5Fh2wqVX zh19$r%SONm239QSDwSHA?tcAwJ-}O%otm__Ytns*kMT9s;C~SOQ#}aK8l9P`k6!>! zF@kTox)8ypub(%70BwRC8iN@D+JjgkA3rYu+a4e?0VWK7sQOiix{t3Hz`8wEOs_MH zRrPJtddOPxbro?YcvO0p;ef44cIT$0-`{I;M1VSn-Ejpi5+GbDmjRBEB1U;8!-D>o zGieg|$Ysj}rhlts!oq)>IWrwI!2f#{kU68dnXEIMn=$9I2ynkz0yc@hNk+tvD&Rqn zz20Z(U1pc;otq(^ki7z+%FY+rx51eV$ zA||s*M696U3SJ6eC0q_lSazw6EXh!DQ2SW`$(D=6Ijo2I@HS;%{erR+3AvzK`lLF zMcv$I!xbxZqNeDRdXZkuyi=U?8zpv`TAbCER?3<5@h-2CTiGz(hbXVj{Qv*}07*qo IM6N<$g0)m2Hvj+t diff --git a/editor/resources/editor/icons/light/navigator-element/star-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/star-red-12x12@2x.png index efa04e6d5990c8852c382a3a5fc530d1b0c4ad30..fe565d458355aff8eb010354fdc10ed995f28a30 100644 GIT binary patch delta 882 zcmV-&1C9K@1f2(vIDY|UX+uL$L}_zyY+-pIP%{7kc${^Ry-UMT6va=gQqVex4jmja zi9^)V3U+a5D-=aAR0XS3ntlmwd?YDSaT8Z5_#aroS#Yq3RB&-{5JU$N-JCipxM+CZ zmsHv!-pA$rIGl62T)-Pp87uYzDCw4wOvI$M)Vkz*gNL3|s()s(sG=+i{{6e_^U?L* zPl#DfyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMn zg3~UaJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap=iMARAwd*GQ>Qyj2}qA7QPln3Mvuucs2#ICUL28|hXl6pLy5RA)I1mggj zEj5blLP=kOG5cn`oe2H9D^rBj<(yo#T*R>bg7y#=H?lFC&%Xg)O3k%;f>oB zd#4rxhois(jN3W%*H;b#Na4HZ5w_MsZ{`t(*?%Acv#AeGPO@UCIJh`5OAN!slEaMq zdTbUDAG}P?vzPC3Yz6J-DDaz~F zt*EqDdLr2Q$zQ}44#L3=Kv==}4CQCO(7r(*R~rSs`EBZXovMf%4iaB-^2tYOx542d zAZvJxb;0|}UpjxWqA~!OQx3dx)NGJzdo$#Q#g+dzu;FvhW97I-22)#@YR&|797|cM zLW#OyP)YX`mqA8_tL=W-xHrb-Eczb9w^wLtBe6e}w%GqCKYy;#b_2Ev-v9sr07*qo IM6N<$f`U_?(f|Me delta 530 zcmV+t0`2{s2fqZ6IDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6)Ja4^RCodH zRNGa;KoFe`6rdFtJAeux6$ljo|0PJ3niG`z+~g&LOeV~;3$H(ybr@?{p{7k^Q(G#=#Th;V~YuPXwS zsDO4T`oQmK*G-65Pyo{&0${l%Dt6|bS|PrH6;$nMWH=iM8`LIs&Qg~gOLjFWU-8IQ zzDkVkc#kJ4i26=YivUdv=E9KmRc*A!W?bRmF__`A-da)OLY; z1Bk=|lKD-FiVWVZz7U{Vq{eBOzi-n@SM+=+-rE$c_jdkiye7Y_q zPk_paTf*FCmYlOQOQsT|ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApCc&zzFUJ8G&xV2y9R~ zLD_(AP&z@g0oj0T5H^4fROupLgpUvT!jI(L>5RmaC0h~zJPHuek#r;%k`(p^ZCc_D zmDMk?5;=QXeCBxB+j4Q0KCsQ=`>LEWTHFGU z-!)4AC4c!KpJIVOQjLx}!veSAbTS5hF*$*cO!7(62lg{%GKptbb2)XL9H2Qfh74<(lSeE0`FKL<)4O%YZA O0000Px#1ZP1_K>z@;j|==^1poj6Qb|NXRCodH zRMAnxFbtJB{>cbo1CJ0UpiDqUU<0}V*&y8@VFH&4Is$CaY#?Ove5VxGvG3rnAANT^ zJIQ;pBugQ>Brx+vtfl_|oCh?yx*N*JBi2dmIag$Ii4yfumVXbiJ25MEZ;YANbXghr z^2kz&jbiWETly==0X=G8i&fb7Ia;Hf_^4_`cM9+9OG@$puA@1Fr>Ik7_7sWolhbGw zw_V}7z`a#xgvfU^U#7++QH?6Xoj953ceV}99ad8$gN@4Kl?ox6H)xM%=LDDNKs@;8 z498mIax`AFg@3?jWD`7#h&^7Y1c=OIOmGHp&IXYhv>NL^!3oV!Q7KprmwLDOo2o23 zDh29)z`j!DU>siKo8$RERpi`;i}Nj~+P6DtfJQwxB?oj64YA(l<;?V0wb%700>D%PDHLkV1lZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap>fNa0B-SZlYBf?AXH=`*CNBhJt`sHM>)9rn|R$UpKI0 zkoabASc0!#cvr;nZxxQ?Nz4?a@O6Wq6<#I$tgp?ns?VjbtSX%JZ4v6qRw; zcUPIpGJgol^N;ge5I`1y=seBI$`qBTH>|<@KpTAhWaSmLGwypBUA;yDE{82phLcU9 zbsOWsb5NojwvSx=_3<{t$r)!uHEahLxF0;4O;V;tjvDWrUJ09k;IbgvEZ^ypN~*}{ zno#H61nXmhBOW0!=RwRYbZ;F#zJ>_;2BU#vJAcXU1Fc+$L79UuJAjJKo|XPBjkr9r zvK^<0Lg5Q?cs#<(wh?a6Ab;4f@ Ts17*~00000NkvXXu0mjfuK980 delta 433 zcmV;i0Z#tF2HyjaIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6bV)=(RCodH zRZCKXKoIT5R9WSU8^{ro69i6RJVBBh$Rd=m5f>yF7seCh28Axq1u%-BEy z0~xFaH!ggOR1eer-t=cC0DlVJasrEJ)+Gelo+&xNTV@;RK!5BfoG=5pK)fk!2~%zu zUqH%9%??A86UGzB%cByS@Oe4pgz^N`@)Tf}scLeX^4FCG;&h(6fGsgvjju;)_N|sx z8GuT_TkSO@{eYOjlkcRaQXZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap{e&PUzVf2;xrPxnml$GaQmBn$~ z@I24|$$wXrK~|naN7EdT0HOdWNlzmam1$q1cDvn$ldUsKl4PorBa0#F5zOcFmwkX% zt2MxHO66j>TrMBQU34xi{%kfIw_dMvHeD(QBkcZxCkJiXY&LDnvfePY={)#2$KhhJ znB@XX)o!=jpjNBB;_xo$`_}#jPrKdjX1!i}s(-NXqM@tCX`0@V0I-{^R;#g2XP$8K zNeGmskoe3KPJNQ2SGbN&2=1wZ9zIBp02JQPQMfh(9rt|g#xQ0)G^#4dPwQhAETl_$ zg!a4Q0sZ7y2|DSE1K@zw-S`+CT%7w{fFNV0>r9u!5eHDpz`f0jyT>;C7Vy)_Hp)ii g;2T^07q+G26CAUT6NLcx4gdfE07*qoM6N<$f?3{xvH$=8 delta 520 zcmV+j0{8vR2DJo`IDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6%1J~)RCodH zRZC6+K@crwhVTny62gK7WVnIuT#hG@tt)lu4sXB_yn*oq9zk!QTQ^`JtcO5I2oT14 zZTHxY4K^esE_lgbO1z^N+m9p zN~j=W`Zi9s6`(zSxm+et20yWJv=tET;q1xxlfNs(i3&H`FG~o zd_MOJg#uNpRe#Fo^Mbitj?%z8H4h?i6k&4_6fT(`c*vyu0_FoVgj2KGO!~eF%jJ?r zqmjs-zFKpmf~PA`>R7nUYPAX{lZj}T=Xu89TrKr_Jz6Xlc)VlY$`}bUv>5@j&xeZ| zjfT-+I2;m^V4O1FOg7FR0>2hqN3mE`!;PnUn}9e-`hV`3PN!;@2%tKN_C5k)p|Qx= zj)TEK5DN-oaWN+=-1+juJrmdK^|;k)#T-ao)A!6S#(0OhTCKM86;3ix%fo9~WE)fx#w_bGn^10_o7PuXZ1Gol|IDY|UX+uL$L}_zyY+-pIP%{7kc${^Ry-UMT6va=gQqVex4jmja zi9^)V3U+a5D-=aAR0XS3ntlmwd?YDSaT8Z5_#aroS#Yq3RB&-{5JU$N-JCipxM+CZ zmsHv!-pA$rIGl62T)-Pp87uYzDCw4wOvI$M)Vkz*gNL3|s()s(sG=+i{{6e_^U?L* zPl#DfyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMn zg3~UaJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApNMrM8Dh&ucDjW&*m4XJ-4qA&Cx6^)7t>9lim^zjCW-j%q#t0000< LMFvhpu0mjfO5SRG delta 428 zcmV;d0aO0C2HFFVIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6Z%IT!RCodH zR6$O{Koos5gCdCwZeWifCjd@hIRS7331HlbI}$MB2|R*&gC2n!z!ADIVoN&XuL-ni zr{=eAT=*7~pXt2!`v3etz@NfR;9?pM%1{LRr-91_nUE)S3vY~ua%l0)Sgq|0*vvrNe)$0>(<2U_G)kMuLGPG;AKl0B>H z{KU%}OoNR@q#}fe#c4N=(j{VD8c*LihcGeF7*al4{2o5E9_9@m>aUPAKyiANL0qL< z=^?aF@?xX{03EPl`sEC!Vf@ZG7NIA4s_!j~CN)OKvX2_9(1XnV`y|{uw%<5dL*Wr7^%GKd zX!Wv61tk&}sW{i$)|oM)4R!`fj}TF382yH2ePul}ZzXJL?PBtAO_$t;ibnWH6?_5L WJ!JY<&lw^B0000ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApcWz*}E-ZY4I43ZX zK%%pKgX9FUZ;&!w;tq*V$O+;jxIidfxIyUoWk$jTqg`b{ap5N|EVJ`r-p4_#=Z!R6=f}w=XoBxuIpC;48vH- zoOA^Rw{82iO%-)Qj~-zd9ww6sWiyBW!Gq&C&ontHQ!2+S%RcBZK?fi$5!$ZN`Ti*D z)fIvuh^N!(J8sf7eyY$8J1pHh&+|S{g37e9s(&{4dITP}_}3fJf^?H9UEo97_@n`l z%O&u!kSz!)(ll*|z2+PEh>`!XsD%qN7z_rQ#L>PSO$=o=GKxegQ*GbU!1=bhD5F#u z0F|r1q0PoIL&r}?8C49m>qa4{>;Ujf!;Y>;>?wz)0^J3)MmnV^f;OO2eGc8r!w(n6 Wl@W^;y=(6P0000Px#1ZP1_K>z@;j|==^1poj6Vo5|nRCodH zRLgCHKoA{%cRC0q*cBKmh$BGa7N>)_f+Q6rsUTM*KuJ2-65N4Zf(t;9w^2YVJfJbT z_~0j@-5r>DGsD{QC{ZI$DEbH^{7?owIB!7N331QpzZMO%}z1UCs zVcWKAa}W3uKM{d$4;C|^@4D_n;wvIB+tWeXrv4}El0DB0P`=Lu`+z+dn2&hwxS*y0 zdIHFA&jgtZ1(HZ_`WA7S&jl(Dy1hy8fENe)KaM)q2|-m=UykGGvJ}mSg1VOMKQNIb z$upKGIuBa}et#PpM@L1LWkFrndlCSxT^2>L(egIFie4mQY(d_^L002ov JPDHLkV1gA&ulxW2 diff --git a/editor/resources/editor/icons/light/navigator-element/starfilled-gray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/starfilled-gray-12x12@2x.png index 21ce7edc161e25e1849b5cf2bf1323106d29aac5..06b82b9c0ca64c2e9e7db6697baf9226abf2520d 100644 GIT binary patch delta 719 zcmV;=0xZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApiD0H^?$z>^>8fRw;`qA(#?L1y5=&M0=)vSi7!P4r>>Xcf~m?V#C0+K?Xp zbIrV8(j$g+Asxs>J1N9LQtAJb5~>t&dd@XE0-rsbtBoM`a3fMc>tNvFRB5`U2;mwk zHqeKaz<-YgK8L;C%>jN!4MtwY7 z&yZ1(8e0;r>L?<~5y>9iKPpab2sV%*jGwBcc+jAjqM4BnbJl-A(y4 zfi&Pv5u$Zh@`dzp5k$T#T#6tTc*{~pTbd&|@JNO1YP;_Q{kdm632{(eO-98FwkQd% zn27ERp&R1Ba=T&U$GQT)1wGa&7orEB>bL8DAFef9Q+)8uA#wl!002ovPDHLkV1j1| BOqc)w delta 450 zcmV;z0X_cv1@HrqIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6g-Jv~RCodH zR6A~iKond92S6^|h7t*o@CgDZ2tI*LnKCCxa)QJsuyTUr2(;-e0TP{EBMQ<*;+NS- zpcPrm52s0yY4-Qt%SD8GY*2q=mYqB*i(0=9AM!eJ~fnx<)Jnzn=I z9=iY_j!<1;mVaeOsX!0gwjUsJ&!*uHzCZsEJr&JQqpIqG(Xa&hUbb-Z9l$Ds5g{w> zvjS888$85dvH;*QB5;EBBmq1+{?8cWd7NqsvPVgZj>7O{TpE+_Xah2FT%uXwA|pP= z=eLI~PvRyp_RvI(asuE=Am_Ec6#thvj^CQ5@%fq%cRMX3Qe~6#`TQLv%5B5J0;pMk!YwA?#er34{|EEk3dWZlEU+ zZ{X6MvhqV|asxR6OLyi5vZOM}w37%C$fRs2S@^1wn(CSEp6TiC0oXFgU0Cv5Cyvkq zf&*z&1y215M^6BgI1;Wlex!%aZYVCedTa*()X7GIj=5T_5T$?Nk@&GFv*Nw-wEYot1&63z`$jdU@=254h}Lh3~ge>9gZ zg=pIL0})eASL}ZP)`e)WuUp8X@tIRIJ5OhQM7jb7NOT>x{Jv?f@RAW#08EfXVdE># zBE$|bQC7YXGc!i1=N{M+KY`CgxA3y5g&R*`OK`!wol*Mb(Hjy*9isyjB7fv0w;Nt9 z`AA=CUWqzv2c*dT*)#-NQjzEW&0H4gjIm-Wf6vX8(#JH2=O7EiEVpITAFnP+Y9>sc m&RNYYIpdH#GTT`D|M&t$Etx)s8EA3<0000t{9~Bftc0C%^^D!B^W2=mfw7 zzyy49w7pB%AR}~xc7%TR&as8VUD{mZ97_4&gZCrFvEH*}$pC)|CyOf;&MwDoVvxI0 zI&xuc^6ew_x5G5!#0g+R09};6B{Aa1abZc7E`jqC6>-8?0!4p$oT(BCw5hRmBY@xk&&q8#{0x5GtN69{L6m51awAY^)&^b5CIBG#p` z_-TL8oq!cIap|n#_t;pZNln09r>QX1FVcf!;bNts^Sm;I-boHV)FUE3KpR+^>f7|C zuGxUjyNZp(6|jFm=lUjH`u;S|K^_D#Fd?zIK^g@RE&IJOgsQcGt7#AT7_|}z6IHx3 zas3ay648?ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap*MwwcPM1~Un0W|``o$AcEf_|ggozPQDAi+neAnU@D%NyO>%XCcy0?#Cj z6Kn_~%Z-oO>}P1o@fnG?FraFraeoJM68X9ogQ2VktO)NDMo1JqoTnTlo3Uhb3tRAs z1RiVu{(IyKRuGbdFGo@LM)amKBnoN~_Jm}|n0TJ$fp5w2(OrOqCI8;9Suh+Iav z>Z21-H|0>KqqrS(ioQdOeC2XpjUQHBe5NUyPt(lfP?AHbABBSTx;3&Ded@0mUH kqn@d-3j7VXVY_?y0oK5Dv-eGFDF6Tf07*qoM6N<$g7-^gl>h($ delta 433 zcmV;i0Z#s&2HyjaIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6bV)=(RCodH zRIyRRKoHy$1cZt(5Qz?O1%6dvy8@sDDgY_~Dxd^R1w0+N11n$#oH--H$Gv0;A)h=a z0~tG`dFfua`@etpz#oIU{5*K$CmCXTN9vDhVabVLgq!my41e;RU{4++%mRX8`N9!S ztx0A921d1yk(+UB$ukM$_Au&%vDGH)4u;Ku)uyV7+$$$CB-&3*xL4*D#27>b^phT2!H^Wasxpk@U(WLmSA)Ld?Z-*@)WL~Q6 zy!3w+TZaf;iGR=~x{+V_1G-h>I##=x!9pIP@Aqk{&28#~1Xg^YwX53&I@~wm>S(8F z%VGOLZ|Z7Qz`by|XOd=|mbjA=yjD_TIWwnm?LwD5`_3%2y~NlbkZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap!8Z@|gSysU^?xHX6Sf zmepJ6l27=A*tO)pWRl}*G4MWo>#8V*7FQ!$oN5;FrwK5}5APx#1ZP1_K>z@;j|==^1poj6T1iAfRCodH zRLfDrFc5tTpR+r_C6F0l;6z*jrh+6LkP28T04ksapab84zzpdiDSJz4j*t~73hxwTNsKp2tiMl_~aZh zC^4f$bJY}gj(-YzuqigMgbqV4>Owl`eg~To9c8*3q?^F%=MCS@;|YKf^cY7G@S}5c zCKZmZ+1m?2p3t)$33AS~j7ekf$3oS9Jp2~iHJ3k}D1F35(~z7ZgPma4>TU7O7#u?# z!5TAe(S*IamwMZi9GMmWGJ3RU-uO1_{G$&(0SV??&Jb^jp6~zw002ovPDHLkV1gm1 Bu)6>N diff --git a/editor/resources/editor/icons/light/navigator-element/starfilled-lightgray-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/starfilled-lightgray-12x12@2x.png index 83aebef4fa81aa028abcb1697576cc8557b3c4e7..382223274205fe0c1fa7cabaed6b626bb4148e48 100644 GIT binary patch delta 763 zcmVZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApGo7b<2W~qz(bQ3tB*`7r;pv>v*k{rg-WvRiAPC;N0%@9VOi8AKi~GL+B398< zv<0{lZtzHF0&?v*C$CRr%5tph`kjY~CIGbLh~I``7$0pX6tS++=mnMs8jk}%A^qfS zQIj`Rwa1AbNC2i6iTAoaW0P^3oa8V*eD)uwT6B{Tx1bocFeSX#iPx#1ZP1_K>z@;j|==^1poj6Y)M2xRCodH zRPAkpFc38k1295H015b8n4mC0+7U8A+X>oEkP(_rP<{gv*`SP&0r==MwUI@PbWYoU zeG;-c`|h2e@66aA!?D?1*YyVmZ?oB?K@glNKAaJO;2DMlpMT$Volo^66F81@J3Dc{ zqxz8v#&OK_dDAo=#g9ZF<FMkLWs;YX#X&#sbko6u)ye#djZ;?FBCnI1Oh9HjPlWA?W57tW71a+ZS z1UByt2r_E|W_Qs$D}u5teM9F8yu$uuuzM(s#9(Kxk(Kkig=u;gWWR{cKS7q~MG^_V z;vyC^<3^i{+74830ntQABE|HmY#=nsv_{a%toI0(>LQJ!AZ%F6HOb!DKd!+SzgLbR TNfAny00000NkvXXu0mjfI0?S( diff --git a/editor/resources/editor/icons/light/navigator-element/starfilled-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/starfilled-lightgreen-12x12@2x.png index 53bbc4f27a97913db52400ff4a9b1286984a4554..4d2d9bd523d856a54d3c8fd8971dec160bc4f9f2 100644 GIT binary patch delta 412 zcmV;N0b~BP2D=8ZssVp|NklYov-~e>XK(_<# zr(|lLH6u=nXYAAJ|XG;n)-k1i7%*K&jZ$Hs=V30gLw13<4Z z0A&J305*t3DSUQ=b_Bi=jqxF+gyw>r@WV%+6xq5v`^E3<1O5{_d>yy>YFH(PvG*K!7Cy#%ae8S)ZIMl?d2=ek| z(8{#AWLNS#nxR2jC_P1bCnnrlelswAU(y*}Bn5&tPnMn}wLqZcnJ#Qptv%DlpR5jK_vpYWcSX5#T~wt zZ{i6FPS{4Cb&=W&8g4DP-tK4Z*I~O@gKqLaAu>f`lI=_-64AlN^YpfFX2kD8TY)@o zqXtYM_Hj<*sqf4y*_D{yG23&3={6+>JJi7^r37|H&*=`?eEZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap31NCjjofDV#K zB#0YSK+*v>1RMetKnI%==z#42pA(^Bc5#do?}|x84m`=yYIc76=3`*bAg!XkV#XAI1o3t4efslSn^x^;fp{$xa7;qYh~_K78b#)k9Dl+{2G7_M-X^S&hI5bP zpxJw#5a9+o=Tmb*lh|Fl$OH#Hl8Y}HK(g;ciFnu`)^{w=03~7-{E@zx&A`{EUVN|+hBYs`$pHjqLW`_TP=_yXXka(=bXs$c*B002ovPDHLkV1l!ZY5f2I delta 424 zcmV;Z0ayO32G#?RIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6Ye_^wRCodH zRLf1nKoETs%-tQ}5}<;3E5KBcL?R$=xB{R8!U++OQUXwcT|zoYO5hH7n6<>R*lTHQ zE*$bMJ09=M+xY_j3B?m<#geCeY)E_2I;RTHR%U`Rb1F48FKyl9r?O_9rbI7aDXdU|3JqJ;bj-u`c=_HWeSMM7MA?r;b zNTGz}dD4qOcD~&+NmDPmzLR3!1We-Mk<*Z`2w_Yc-}PGfZa-OmYuQh?zaCN55tmIz z!3ZSe1Mj2N+o74E5ysF)AjUaGh`GY6wBI6h$6V0X9w9O_mohVBj*w%AA@~B5l5E~x SGEbWT0000ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-Ap}xCvvDuUnGVMGKs^fH+ zU)x+lO{(M~llh8qLW$SqCY=0?j2UD!q_sVKr2C&|e9wG{ZmMS@EQ0PH2dg-{e)s~a XUlMSP>5o7H00000NkvXXu0mjfT^w&U delta 435 zcmV;k0ZjhH2H^vcIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj6c1c7*RCodH zR69}vK@fdCfbrhIEzw*~0DA)069_ku0E$e^5Cic99zneUM<7>(BM@3vv271k3sbwZ zRlRFsz)QMorn}$tXBzlV7&bW`G`U;GhqQ(^I2f;1HwMwyZ>hl#-o3UCdr#}8Wg?u!3GT|ZGZE*_9V0#5Y% zMr`Bq1V9H`0u(>SOE9=#yJy1exisuq#J$HQ7@c#+7pv|`Gm$!;yA<0s2+A^Yix zokz$z>4=zTLwPfhc|LXY+-&>)jOcA>Gca59W%L5sm@MzIQ)WJ!$(q(8BKb47QoA-a d(8m!~@C)N&Zza~B2fY9Q002ovPDHLkV1lX1zykmP diff --git a/editor/resources/editor/icons/light/navigator-element/starfilled-red-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/starfilled-red-12x12@2x.png index eca9d4e5f667ee0362f66105301aaad50e3b75b4..7816196e7adea5571fa76f67207a65d4fb8448d6 100644 GIT binary patch delta 736 zcmV<60w4Xm1B?ccIDY|UX+uL$L}_zyY+-pIP%{7kc${^Ry-UMT6va=gQqVex4jmja zi9^)V3U+a5D-=aAR0XS3ntlmwd?YDSaT8Z5_#aroS#Yq3RB&-{5JU$N-JCipxM+CZ zmsHv!-pA$rIGl62T)-Pp87uYzDCw4wOvI$M)Vkz*gNL3|s()s(sG=+i{{6e_^U?L* zPl#DfyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMn zg3~UaJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApIxJUJX9PAsf*GpcHlIZ(r0+91X+{sY5r82vHLKO`|6@b#&)3(9I;GX>L zE8iV;=+;j!VHk{m7rJm!D>@W~x>hq14@k%1I6{h!&)8{~J+5hch722JUf0}@6OXJ7 z#BkBUcOrnxAqLlo0W3xI*ff&u59BD1v#FO!ELnp&uU17^J&gEy6%F8+lznZ#%=`k| zGdfQR(7ufc<+t0`icm3n?4_2?Bq2aULtWcny%V8lrf7Pm9ZZ1G)t5hed-wxq(`C_R SSpRVV0000Px#1ZP1_K>z@;j|==^1poj6P)S5VRCodH zRqa`WFc5wZ9iSVS5$Xhm3B(E7{`Z4UpiUsw0USZyAS1XzGeRdI9)!|>q0a^X_`~;k zfa8+)-n&Z(z+Zw@MQ+vYDuzSSiB{d@K=SV1l8j8LCA zS#5bOvZ6(k;h3l=kgV(C@O$iCEC=fA7OL%cib){N*P7SB1O<*lcaQvdKosnT%xn2W za&&rAO|^pv$$uqh{S_QJ!BUW8bc37_ke@ePX+A*!Ddbp232^`CBOl$Cucv^2#+)?Z z$2o$iRs%=pZiHvDc|%k(nyQw!n1X|OFA;!AAHZ;Sm#|pUIA^;?2PJ@ r%u5-Z;XbB}f1w2@uxL5|h{rdTOkTk-yi!E~0000ZC)fdmEN zfBe&qKaMSOSASqoE{_5%%0x*K6SBnf(4k=xGI0n&>X5i|>wXWd`^jx>?-iJBaLzB< z+Cl?3ouQM}+uC>p7#aX>>P$6MN9v*W=5oOM2{4!fhVLk|VdlaicYA*f=zHP(V+`;e z0(O=2uOrUw8ik*MEByz-ApISeuOwab@dQC6EKInIsg9}a4{Imf43W!*fOeB`1g3^%F9zP6F8o&F% z2qp35iK!*FJCM;PbR857&?IyR5MaU!rF^7E&8)jH`ZJ?nj4^juIq$GMo%1a%(f7F7 z#&Yyr5Oz0?7Pn*Z-OFqyF31)2I2-vDg1V9ooS$5ipCD&}4FOIdrvVMFmZ)Rq>d$4+ zGWv&?m?~qF%;1*TWxx8K8UXnf9vNDaePT^~W@b%*(HmuF+xIG*nF%zY@Q0#Z`+vLu X6xmW%;B&$`00000NkvXXu0mjfS~e%+ delta 299 zcmV+`0o4Ag1=<3TIDY^Eb5ch_0Itp)=>Px#1ZP1_K>z@;j|==^1poj5?@2^KRCodH zmF*FNFbsx+6EH$YU<5V*Cr~$V1V&&3M{tC?32p!z#Pn?MBD9iJyz__8U5^|zZ$4-M z;Fmzemevuzffo6y1YfAmnOu-0-R{w;d3UhwS-DDt~|`gIt^HZ zHg%}y3>thjQj#WssVrdNkl<{907*qoM6N<$f^kxLJ^%m! delta 242 zcmV2 zEOwr?YBGzOkx7$(gIA3i5348`da4Trzu--M;S)#!DIf*PAi)272BZPyyhi@=2~ayV s;kx@g3jPGz#Q=Y^88}u%H{YM(3WOyoO<1)=umAu607*qoM6N<$g4Gsd+9QC_z^(9e5o5L<;nN8ZQD>vZ?04DO+$9Z*cxHPkr3j3;FC*&xW+vp zc^`N=jc+GtU=%?Y82y27`GZf83*-X1KrYY&(d7m^eg;S661i?&S(bAl#QhgXbOIo+ jVyDyjjWMaGb!2z~AZM?XTKh&CkS`%<1L^>! zqrwbkyYt&ewO;YR@Z^rkMPlsn(owrxWxJ-JT7Hw@VsV{>5;TSAEYfk!S0;u`ma zI=3M2=5amgQIoael=SodC$I j*kyBmV@&Gh`!QSr;08Xigny?x00000NkvXXu0mjf@o{A! diff --git a/editor/resources/editor/icons/light/navigator-element/text-blue-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/text-blue-12x12@2x.png index c4dc7c13bd9647839597340eba105d25b39c7551..c6845f8c057189a880d28965815303db77dc4d08 100644 GIT binary patch delta 285 zcmV+&0pk9J1-%8ZssVrgNklslbOjpPJ(2I_xvWV5ZMq<9yCjrldu zhO~o`BmA%GHRG)Y-5q?Frru1HAFzSy_2e5c^~PgafsA9^?b%)E9MGl1m-R5|gJDIfy5a#4>M#106%8@<5tx`xOC zG=an%VSoSFb_$mwo7`tIAh2E8!?I_pB1e;`s9=FaAV e^SYhy$G8ERhbms?f;V0O0000!5mobM7(5R&YJ?0w|@W>$-W8 zBxR>S6h(er*XO2bd@=x1Bv3_|`a@M!dwhIY0XwN@5cNP1!xew9oq>GWUQBWXMgd@c z4>GpUOKqz|attDors-N2Kx?LwVA@AWSpOT)CExNQ1 zi55-z<~iiU7zIXwQQ#j0tg}enZl--8=h9)YKp2J`Bu6U&r89^WUFXb}jP;qL0^0}| dHuA6F1_ilS!>A8iFo*yE002ovPDHLkV1i*Tcwqnl delta 248 zcmV2f(v=vz{yFkWm#|*wQYNoPK%HnuqmRS-0+5Gf*=(}TId|H8|A!a8Ge%zd=#dNn00000~RZW3t8bk zXtM5_6yn0cHE+qYsM(1&q#^hH-dH)U?NR#-<}NPfsBXH40dr?1bhf@@xRKNDd5!_d z<}skgxb*4Y$qBX?hn_w|B-|&ulA8G>R+r<$NCwFu8T^Ama2JW!ZRkC)d+9jFV8L)g p7&G2$eZ>M{GzhP76Kehy+yR(uI8RaJxd;FN002ovPDHLkV1knHYxe*E delta 218 zcmV<0044vB1^WcBssVqzNkls$+B~?&(0?%%7{Qo!Z}xm5G=xq($FfU?#39$$&C;<5Wgba zQaZYUj=;xz|NN09&w%);4=>i*hTq|=;a=UOh<8#Q+!^i$t6@_A+Ct>%KDnVpuo}(z zf)++8rcg8kL-mWlAUDVja)UKAnEZS2x9s5_G`@UV*a3O(F^$*@Dw^JGvHKO^3*3`0 Uz=CZf!vFvP07*qoM6N<$f}OW#zW@LL diff --git a/editor/resources/editor/icons/light/navigator-element/text-green-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/text-green-12x12@2x.png index 8f46445243c993da22e34b1aef351804361ab2e1..334254909cb005f14c02758bc4066229f69034e5 100644 GIT binary patch delta 300 zcmV+{0n`4H1Xp=@@ChdYVboRuyi*6ML}Q*`xKoq>000002~yr}KZOiw=OI29!70Vdjt!UJ}ru88ISm?^d`j zHRuP^6%u*S0!^TMvqL}AEVvOZ-V;GCwsQ$A`x4rO5$m`fns2#uU% zndNHIIU^lp@o(T(mSg1iHRzba6D6f1wBS>I=M^XeWuOfH!JzW*VS8&t@Hka8pO`Zm s!z8+tX;fA~$n~1erVp--JKvA-0>-U6CTW5|CIA2c07*qoM6N<$f~>b@2><{9 diff --git a/editor/resources/editor/icons/light/navigator-element/text-lightaqua-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/text-lightaqua-12x12@2x.png index 356c5a49de7cbf51ef4df8de34f6c0fcb0158a2c..b66e2a850d7999327f11975dc6dfbdac7006ad0d 100644 GIT binary patch delta 284 zcmV+%0ptGo1iS^XssVrfNklU!3wkk zu>#Ky(n0c5U&&Kn>qbvVj^vDrf|7xQW%qVw_YQV}Uk8~EFJKo9Ou%sQ96~utbto(p z@b=tg!dA>KUPDNXVOpe?jtcowllyXUlS!41*uhk+SYiv4S#p2JNv`G?=5{bRFkhXF zp4qDIE=a1}wW((ccoDmNMwApF@#fv{AO|LS8K@@3+RXf2=82^8Io?2CKA|KYJy8)H zd>EBLB~S_cgFwv|%xt&h+$NVRb7`ipgfe+oHV*5s^Nu`{4Y9ToIOwYu`9*PS2dG2Q i$uhzTv5ovIxBwJ;+EDqMw1^5K8ssVqwNkl8d~J4gn}AQ}9Ff%y068e@RA!tg2iN)t2UORR?6!Oa$yCL3F=*Ld>%7$x*g`D93bX^U z0&^2YFddi<%vFM}lO?#FD}$<^_2Sjuqrm@{T6-Qi{#+*uj5D-UMHWg?IcH+?) zC_+lG0@uKd3}y&X87@q|Oa6A>%jS>;0v^cT(1m0Iu$e~qjfx1DJSFWk(52)ejrjjO zapWDH-^*q9%!u#%f@=6CF&4PjH{~s@ZCx(q0Ko|gnOU~E%8F8pn_x@)8#rxq;_kk} z#C$xFDV;EazWm862nN9*7|g+7@bBS5HfFfO-FzynkZ?i|mxl7#M;PvGzVjLI0>641L2bpq7dlO*FjZau=?5ukT2DM86KEe#o-St*UB`(4`k(Syll{IOoM6 z0h)VF)0~A69!&saOp?T15~q8huIoLV2g^ZnQi`Rb4Xi|NM~{CBR`OzPk65c9O;aJg zZQH&oRjNbr1z{0}p|29i(IS797eIb-CngQl=3{`GvJHFxt~Vk`+|nD+)iWB2XCoSd zMIXjYFcZuK|3F}Ti@MuQw-4kN3xePMYtc`9JhxSpS~F z%zS+jmQG*-L-Dg$Pz9<$61GU(qT&s>gT1(=|L!eqntUi2@6 Y7lorTpFs!s3;+NC07*qoM6N<$g5o%2oB#j- diff --git a/editor/resources/editor/icons/light/navigator-element/text-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/text-lightgreen-12x12@2x.png index 723e7090c2922aabcc8eecfc95af4642d223c76f..2fdece7bbf9caf022767755a8dabd15c47ba0d60 100644 GIT binary patch delta 280 zcmV+z0q6dO1-J#UssVrbNklB!_{tO96cV0000yRnfEY#8WCS*W zhA;*hfgY5@Q3NCwcKA`6$X{XEzPtB)E^NTj0O=bOjzdB&)zrgxWPsSEv|Jkv0*)h; z;y=Tn#fetQW8JHV^I4h1DoG~Q$e5)sKb^kB)UHUiPWXd&^{sc{44i>8=z@Xu?Fo1@1a5nnKcB1*9vw(tOd8e>1g;+J eKU-701Ka^w#4bMF$tiFE0000Sja$ diff --git a/editor/resources/editor/icons/light/navigator-element/text-lightpurple-12x12@2x.png b/editor/resources/editor/icons/light/navigator-element/text-lightpurple-12x12@2x.png index 910928037bcd0639a49a952d8edd1984052c255e..0dde28c71986a21c20df24172502387ec89e787e 100644 GIT binary patch delta 279 zcmV+y0qFky1h)mSssVraNkl_ENX(HbnllZi3G z4vZB*33MPG$l1SjFc{elAYwGp@SP?*%)GZlvIG1&q#p#nv~j?QLmRI^h+!cVV~W+| zeDj5L$UwlMgJ#6ig2;=Qikb-@^42_(5?iQNY<4r{DB;{(?@WJ$VQP#{+yfAgvK--( zOBr_I>Q~Kfw@Y32J#uw{bhLEDJ~hDk?)|)j0`%r};F=^0m4ByR-hGV1^z*x@-0%fThTt?Ehao#Hy2pR0bQ`E`i2)sk42)gyjfKY1ED-uKH-U& dlsEqhS2vJOn5qxjCIJ8d002ovPDHLkV1iZOfoA{! delta 220 zcmV<203-jm1^ooDssVq#NklC3z~?|*Na%maQMrf;-`%I-O8WM=UKib1B* zSoBs*h6=QV5@(J%nF8^UJcF`V#PU^oI<6GpNZb9?FnPP)Ao5U7q7FC5N&D0cQol)vawhZ-~ n4j)cf&=4^_;kFqm`B%6A{f|xHgxQ7W00000NkvXXu0mjfyS0Z^ delta 220 zcmV<203-jv1^fiCsR4fgy-7qtRCodHmAwtZFc5{GLkdKd5lkd{*oX}R1wS33rGXLH zgiXLBP|}d&3<5=`*bqf2i2O;H`0w63H$EWn1tk|&DP;uYJWNmz!*Sf5)z)dSOlgCc zcoXJqa(GW-u{o_eWLay{MTCp3l=p^Gm5ZD4Z_kl&d~zdkPTN$E6#s=%jxMi9Xqi}4 zq0oS;{MK&}41z&0=z@Xw?OBXytnN6$-F(cTz$7>7>eBGuphr((UuR2h{o0-H&v*d5 WTq)1*)1f>PAssVrINkl5Phu-fE&OFj=%<&I+**wWlSL-Z$T@d7Ynsil>$T_ z(D!I8dq2fRon&<)k+=cXw<=SfCjS`2scZYD86#_%b?yPM{NLgMf1v zvDdBSJn#*0=_uBi>0s$U~{ZN?gj>nOfU>KBk70pjh0g@lSqgGxz`slG>;7;(LdTrdJ{ z`IC1L1cE>in1ev)?BR%Bazx+YUOvhiSEAX&#o_B9LHB0!`DcI^?HDQdLzssVq*Nklrm-|_g-_^k{YkUlATh@iXKdE$ibIm2suOr zG+wwY$(}qX^@E}v>B!^6{WheDDpn8_j4*<_`z?i79qrf0^JZGgIs1+R7~|sh>F?Ua z?|}DE9zXX)5*mCMwLmRU3;aWYHfKzx+t?*TTi(aLWfwi66il?9A7XxiQUyeZd<%9| c(Bqr90gtD(xb2g0zyJUM07*qoM6N<$f{&AEB>(^b delta 149 zcmV;G0BZk(1-1mRssVp@Nkl?=8Q5m5lP}0<-2Z5;Z zV)&AGP=20V1i)#9h%VMm?I0^#%`=UYGy{~9_%4>03bjd#m!uaV7Oe)g`W+^7{0|!g z1JvrLPv8b_;07xgsPM;llD>S96|^4K1mRO}d;uPGf9KwO)o~5o00000NkvXXu0mjf DK%qeH From e47a1d1164fc8831cfe8df7043dd7b8282e07a07 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Thu, 6 Jun 2024 19:55:34 +0200 Subject: [PATCH 035/103] Layout icon should be blue too (#5854) **Problem:** Icon `layout` coming from the component annotation should be blue, just like `row` and `column` **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../components/navigator/navigator-item/layout-icon.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/editor/src/components/navigator/navigator-item/layout-icon.tsx b/editor/src/components/navigator/navigator-item/layout-icon.tsx index c96e980a5fad..608e6061cc92 100644 --- a/editor/src/components/navigator/navigator-item/layout-icon.tsx +++ b/editor/src/components/navigator/navigator-item/layout-icon.tsx @@ -117,7 +117,12 @@ export const LayoutIcon: React.FunctionComponent Date: Fri, 7 Jun 2024 10:33:05 +0200 Subject: [PATCH 036/103] Cartouche selection color in navigator (#5850) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of #5840 This PR adjusts the coloring of cartouches when inside a navigator selected row (direct or parent). https://github.com/concrete-utopia/utopia/assets/1081051/7a3208e5-9fbd-4b3e-a988-78db3f278622 The entire row coloring is also adjusted following the updated designs in the issue ⬆️ **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/cartouche-ui.tsx | 56 ++++++++++++++----- .../data-reference-cartouche.tsx | 7 ++- .../navigator-condensed-entry.tsx | 51 +++++++++++------ editor/src/uuiui/styles/theme/dark.ts | 6 ++ editor/src/uuiui/styles/theme/light.ts | 6 ++ 5 files changed, 95 insertions(+), 31 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 9d0189487b8e..c2cd4528c4ff 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -15,6 +15,7 @@ export interface HoverHandlers { export type CartoucheDataType = 'renderable' | 'boolean' | 'array' | 'object' | 'unknown' type CartoucheSource = 'internal' | 'external' | 'literal' +export type CartoucheHighlight = 'strong' | 'subtle' export type CartoucheUIProps = React.PropsWithChildren<{ tooltip?: string | null @@ -22,6 +23,7 @@ export type CartoucheUIProps = React.PropsWithChildren<{ role: 'selection' | 'information' | 'folder' datatype: CartoucheDataType selected: boolean + highlight?: CartoucheHighlight | null testId: string preview?: boolean onDelete?: (e: React.MouseEvent) => void @@ -40,13 +42,14 @@ export const CartoucheUI = React.forwardRef( children, source, selected, + highlight, role, datatype, onHover, preview = false, } = props - const colors = useCartoucheColors(source) + const colors = useCartoucheColors(source, highlight ?? null) const wrappedOnClick = useStopPropagation(onClick) const wrappedOnDoubleClick = useStopPropagation(onDoubleClick) @@ -78,10 +81,10 @@ export const CartoucheUI = React.forwardRef( opacity: preview ? 0.5 : 1, }} css={{ - color: selected ? colors.fg.selected : colors.fg.default, + color: selected || highlight === 'strong' ? colors.fg.selected : colors.fg.default, backgroundColor: selected ? colors.bg.selected : colors.bg.default, ':hover': { - color: selected ? undefined : colors.fg.hovered, + color: selected || highlight === 'strong' ? undefined : colors.fg.hovered, backgroundColor: selected ? undefined : colors.bg.hovered, }, }} @@ -90,7 +93,9 @@ export const CartoucheUI = React.forwardRef( @@ -124,7 +129,9 @@ export const CartoucheUI = React.forwardRef( = { selected: T } -function useCartoucheColors(source: CartoucheSource) { +function useCartoucheColors(source: CartoucheSource, highlight: CartoucheHighlight | null) { const colorTheme = useColorTheme() const colors: { @@ -189,8 +196,10 @@ function useCartoucheColors(source: CartoucheSource) { selected: colorTheme.white.value, }, bg: { - default: colorTheme.green10.value, - hovered: colorTheme.green20.value, + default: + highlight === 'strong' ? colorTheme.whiteOpacity20.value : colorTheme.green10.value, + hovered: + highlight === 'strong' ? colorTheme.whiteOpacity30.value : colorTheme.green20.value, selected: colorTheme.green.value, }, icon: { default: 'green', hovered: 'green', selected: 'on-highlight-main' }, @@ -203,8 +212,14 @@ function useCartoucheColors(source: CartoucheSource) { selected: colorTheme.white.value, }, bg: { - default: colorTheme.selectionBlue10.value, - hovered: colorTheme.selectionBlue20.value, + default: + highlight === 'strong' + ? colorTheme.whiteOpacity20.value + : colorTheme.selectionBlue10.value, + hovered: + highlight === 'strong' + ? colorTheme.whiteOpacity30.value + : colorTheme.selectionBlue20.value, selected: colorTheme.selectionBlue.value, }, icon: { default: 'dynamic', hovered: 'dynamic', selected: 'on-highlight-main' }, @@ -217,16 +232,29 @@ function useCartoucheColors(source: CartoucheSource) { selected: colorTheme.white.value, }, bg: { - default: colorTheme.bg5.value, - hovered: colorTheme.fg8.value, - selected: colorTheme.fg6.value, + default: + highlight === 'strong' + ? colorTheme.whiteOpacity20.value + : highlight === 'subtle' + ? colorTheme.cartoucheLiteralHighlightDefault.value + : colorTheme.bg5.value, + hovered: + highlight === 'strong' + ? colorTheme.whiteOpacity30.value + : highlight === 'subtle' + ? colorTheme.cartoucheLiteralHighlightHovered.value + : colorTheme.fg8.value, + selected: + highlight === 'subtle' + ? colorTheme.cartoucheLiteralHighlightSelected.value + : colorTheme.fg6.value, }, icon: { default: 'secondary', hovered: 'secondary', selected: 'on-highlight-main' }, } default: assertNever(source) } - }, [source, colorTheme]) + }, [source, colorTheme, highlight]) return colors } diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index c4c83e024d57..4cf40eb05ddc 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -22,7 +22,7 @@ import { } from './variables-in-scope-utils' import { DataPickerPreferredAllAtom, jsxElementChildToValuePath } from './data-picker-utils' import { useAtom } from 'jotai' -import type { CartoucheDataType, CartoucheUIProps } from './cartouche-ui' +import type { CartoucheDataType, CartoucheHighlight, CartoucheUIProps } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' interface DataReferenceCartoucheControlProps { @@ -32,6 +32,7 @@ interface DataReferenceCartoucheControlProps { renderedAt: RenderedAt surroundingScope: ElementPath hideTooltip?: boolean + highlight?: CartoucheHighlight | null } export const DataReferenceCartoucheControl = React.memo( @@ -144,6 +145,7 @@ export const DataReferenceCartoucheControl = React.memo( contentsToDisplay={contentsToDisplay} selected={selected} safeToDelete={false} + highlight={props.highlight} onDelete={NO_OP} testId={`data-reference-cartouche-${EP.toString(elementPath)}`} contentIsComingFromServer={isDataComingFromHookResult} @@ -170,6 +172,7 @@ interface DataCartoucheInnerProps { contentIsComingFromServer: boolean hideTooltip?: boolean datatype: CartoucheDataType + highlight?: CartoucheHighlight | null } export const DataCartoucheInner = React.forwardRef( @@ -180,6 +183,7 @@ export const DataCartoucheInner = React.forwardRef( safeToDelete, onDelete: onDeleteCallback, selected, + highlight, testId, contentsToDisplay, contentIsComingFromServer, @@ -210,6 +214,7 @@ export const DataCartoucheInner = React.forwardRef( onDoubleClick={onDoubleClick} datatype={datatype} selected={selected} + highlight={highlight} testId={testId} tooltip={!props.hideTooltip ? contentsToDisplay.label ?? 'DATA' : null} role='selection' diff --git a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx index fdd3348e08b5..62cbfce2b6ee 100644 --- a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx @@ -78,20 +78,29 @@ export const CondensedEntryItemWrapper = React.memo( ) }, [selectedViews, props.navigatorRow]) + const rowRootSelected = React.useMemo(() => { + return selectedViews.some((view) => + EP.pathsEqual(view, props.navigatorRow.entries[0].elementPath), + ) + }, [selectedViews, props.navigatorRow]) + return (

@@ -109,6 +118,7 @@ export const CondensedEntryItemWrapper = React.memo( showSeparator={showSeparator} wholeRowInsideSelection={wholeRowInsideSelection} rowContainsSelection={rowContainsSelection} + rowRootSelected={rowRootSelected} /> ) })} @@ -124,6 +134,7 @@ const CondensedEntryItem = React.memo( navigatorRow: CondensedNavigatorRow isDataReferenceRow: boolean rowContainsSelection: boolean + rowRootSelected: boolean wholeRowInsideSelection: boolean showSeparator: boolean showExpandableIndicator: boolean @@ -197,16 +208,14 @@ const CondensedEntryItem = React.memo( showExpandableIndicator={props.showExpandableIndicator} isDataReferenceRow={props.isDataReferenceRow} indentation={indentation} + rowRootSelected={props.rowRootSelected} /> {when( props.showSeparator, - , - )} - {when( - !props.showSeparator && - (!props.showExpandableIndicator || - (props.rowContainsSelection && !selectionIsDataReference)), -
, + , )} ) @@ -220,6 +229,7 @@ const CondensedEntryItemContent = React.memo( wholeRowInsideSelection: boolean isChildOfSelected: boolean selected: boolean + rowRootSelected: boolean showExpandableIndicator: boolean isDataReferenceRow: boolean indentation: number @@ -293,6 +303,7 @@ const CondensedEntryItemContent = React.memo( : undefined, borderTopRightRadius: props.selected ? 5 : 0, borderBottomRightRadius: props.selected ? 5 : 0, + marginRight: !props.showExpandableIndicator && props.isDataReferenceRow ? 4 : 0, }} onClick={onClick} onMouseOver={onMouseOver} @@ -333,7 +344,7 @@ const CondensedEntryItemContent = React.memo( , )}
@@ -343,6 +354,9 @@ const CondensedEntryItemContent = React.memo( , )} @@ -353,7 +367,12 @@ const CondensedEntryItemContent = React.memo( ) CondensedEntryItemContent.displayName = 'CondensedEntryItemContent' -const CondensedEntryTrunkSeparator = React.memo((props: { backgroundColor: string }) => { +type CondensedEntryTrunkSeparatorProps = { + backgroundColor: string + selected: boolean +} + +const CondensedEntryTrunkSeparator = React.memo((props: CondensedEntryTrunkSeparatorProps) => { const colorTheme = useColorTheme() return ( @@ -376,7 +395,7 @@ const CondensedEntryTrunkSeparator = React.memo((props: { backgroundColor: strin color: colorTheme.fg6.value, }} > - +
) diff --git a/editor/src/uuiui/styles/theme/dark.ts b/editor/src/uuiui/styles/theme/dark.ts index bf7018b93e12..0f74311c198a 100644 --- a/editor/src/uuiui/styles/theme/dark.ts +++ b/editor/src/uuiui/styles/theme/dark.ts @@ -130,7 +130,9 @@ const colorsWithOpacity = { fg0Opacity10: createUtopiColor('hsla(0,100%,100%,0.1)'), fg0Opacity20: createUtopiColor('hsla(0,100%,100%,0.2)'), fg6Opacity50: createUtopiColor('rgba(111, 119, 139, 0.5)'), + whiteOpacity20: createUtopiColor('oklch(100% 0 0 /20%)'), whiteOpacity30: createUtopiColor('oklch(100% 0 0 /30%)'), + whiteOpacity35: createUtopiColor('oklch(100% 0 0 /35%)'), canvasControlsSizeBoxShadowColor20: createUtopiColor('rgba(255,255,255,0.20)'), canvasControlsSizeBoxShadowColor50: createUtopiColor('rgba(255,255,255,0.5)'), neutralInvertedBackground10: createUtopiColor('rgba(217, 220, 227, 0.1)'), @@ -141,6 +143,10 @@ const colorsWithOpacity = { // TODO vv only used by button, refactor & remove errorForeground20: createUtopiColor('rgba(253, 0, 59, 0.2)'), subduedBorder80: createUtopiColor('rgba(24, 28, 32, 0.8)'), + + cartoucheLiteralHighlightDefault: createUtopiColor('rgba(255, 255, 255, 0.1)'), + cartoucheLiteralHighlightHovered: createUtopiColor('rgba(255, 255, 255, 0.2)'), + cartoucheLiteralHighlightSelected: createUtopiColor('rgba(255, 255, 255, 0.4)'), } const darkTheme: typeof light = { diff --git a/editor/src/uuiui/styles/theme/light.ts b/editor/src/uuiui/styles/theme/light.ts index 81a84e7b9d4e..2c14f9b169d5 100644 --- a/editor/src/uuiui/styles/theme/light.ts +++ b/editor/src/uuiui/styles/theme/light.ts @@ -131,7 +131,9 @@ const colorsWithOpacity = { fg0Opacity10: createUtopiColor('hsla(0,0%,0%,0.1)'), fg0Opacity20: createUtopiColor('hsla(0,0%,0%,0.2)'), fg6Opacity50: createUtopiColor('hsla(0,0%,0%,0.5)'), + whiteOpacity20: createUtopiColor('oklch(100% 0 0 /20%)'), whiteOpacity30: createUtopiColor('oklch(100% 0 0 /30%)'), + whiteOpacity35: createUtopiColor('oklch(100% 0 0 /35%)'), canvasControlsSizeBoxShadowColor20: createUtopiColor('rgba(0,0,0,0.20)'), canvasControlsSizeBoxShadowColor50: createUtopiColor('rgba(0,0,0,0.5)'), neutralInvertedBackground10: createUtopiColor('hsla(0,0%,0%,0.1)'), @@ -142,6 +144,10 @@ const colorsWithOpacity = { // TODO vv only used by button, refactor & remove errorForeground20: createUtopiColor('rgba(253, 0, 59, 0.2)'), subduedBorder80: createUtopiColor('hsla(0, 0%, 91%, 0.8)'), + + cartoucheLiteralHighlightDefault: createUtopiColor('rgba(43, 43, 43, 0.1)'), + cartoucheLiteralHighlightHovered: createUtopiColor('rgba(43, 43, 43, 0.2)'), + cartoucheLiteralHighlightSelected: createUtopiColor('rgba(43, 43, 43, 0.5)'), } const lightTheme = { From bbb2dfb4553f69e7d6b192d64240e02fb8091a2b Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:47:05 +0200 Subject: [PATCH 037/103] Update projects page hydrogen project link (#5857) Update the hydrogen clone URL to `concrete-utopia/hydrogen-editions-24`. --- utopia-remix/app/routes/projects.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/utopia-remix/app/routes/projects.tsx b/utopia-remix/app/routes/projects.tsx index 86187b363aee..db79a4e4a708 100644 --- a/utopia-remix/app/routes/projects.tsx +++ b/utopia-remix/app/routes/projects.tsx @@ -1336,8 +1336,7 @@ const projectTemplates = [ onClick: () => window.open( createCloneLink(AccessLevel.PUBLIC, { - cloneRepo: 'concrete-utopia/hydrogen-may', - cloneBranch: 'sehl-utopia', + cloneRepo: 'concrete-utopia/hydrogen-editions-24', }), '_blank', ), From 0b2dbb11df720d3c66b26825ac864b8aea56ddab Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 7 Jun 2024 12:35:48 +0200 Subject: [PATCH 038/103] Open inspector cartouches on double click (#5860) Part of #5840 **Problem:** Cartouches in the inspector should be openable on double-click like in the navigator, not on single clicks. **Fix:** Do that. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../sections/component-section/cartouche-control.tsx | 7 ++----- .../inspector/sections/data-reference-section.tsx | 4 ++-- .../inspector/sections/layout-section/list-section.tsx | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx index 002b5ddc39d6..ec4851248411 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx @@ -1,7 +1,4 @@ import React from 'react' -import { when } from '../../../../utils/react-conditionals' -import { FlexRow, Icn, Tooltip, colorTheme } from '../../../../uuiui' -import { stopPropagation } from '../../common/inspector-utils' import { DataCartoucheInner } from './data-reference-cartouche' import { NO_OP } from '../../../../core/shared/utils' import type { ElementPath, PropertyPath } from '../../../../core/shared/project-file-types' @@ -41,9 +38,9 @@ export const IdentifierExpressionCartoucheControl = React.memo( return ( Value { List Source - + Contents From 17596c13f5e9502e06910872d73b92662668aa8f Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:10:38 +0100 Subject: [PATCH 039/103] Remove Variables From Insert Menu (#5862) **Problem:** Variables in scope are causing a lot of noise in the insert menu. **Fix:** Remove the previously included variables in scope from the list of insertable components by just not including the additional values. **Commit Details:** - Remove the addition of `getVariablesInScope` from `useGetInsertableComponents`. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../canvas/ui/floating-insert-menu.tsx | 26 +------------------ ...performance-regression-tests.spec.tsx.snap | 16 ------------ .../performance-regression-tests.spec.tsx | 8 +++--- 3 files changed, 5 insertions(+), 45 deletions(-) diff --git a/editor/src/components/canvas/ui/floating-insert-menu.tsx b/editor/src/components/canvas/ui/floating-insert-menu.tsx index f735aeac2c33..dbf2a9d097c8 100644 --- a/editor/src/components/canvas/ui/floating-insert-menu.tsx +++ b/editor/src/components/canvas/ui/floating-insert-menu.tsx @@ -114,29 +114,5 @@ export function useGetInsertableComponents( } }, [packageStatus, propertyControlsInfo, projectContents, dependencies, fullPath, insertMenuMode]) - const scopedVariables = useEditorState( - Substores.variablesInScope, - (store) => - getVariablesInScope( - store.editor.selectedViews[0], - projectContents, - store.editor.variablesInScope, - store.editor.jsxMetadata, - ), - 'useGetInsertableComponents scopedVariables', - ) - - const insertableVariables = React.useMemo(() => { - if (fullPath == null) { - return [] - } else { - return convertInsertableComponentsToFlatList(convertVariablesToElements(scopedVariables)) - } - }, [fullPath, scopedVariables]) - - if (insertMenuMode === 'insert') { - return insertableComponents.concat(insertableVariables) - } else { - return insertableComponents - } + return insertableComponents } diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index a205f842426f..cd4ba48b5fea 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -432,10 +432,6 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(Styled(div))/div/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", - "//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", "/null///Symbol(react.memo)(PropertyLabel)", @@ -1034,10 +1030,6 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(Styled(div))/div/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", - "//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FrameUpdatingLayoutControl/Symbol(react.memo)(NumberInput)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FrameUpdatingLayoutControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/FrameUpdatingLayoutControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", @@ -2087,10 +2079,6 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)", "/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", "/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", - "//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", @@ -2836,10 +2824,6 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", - "//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index d232eaca33fd..7f4536dcc24d 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -65,7 +65,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`744`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`740`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -127,7 +127,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`909`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`905`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -183,7 +183,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`536`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`532`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`650`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`646`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From 036dd9885d68012c0cada3a18d34655d9f807d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Fri, 7 Jun 2024 15:01:24 +0200 Subject: [PATCH 040/103] Make it possible to set icons for segment controls through the component API (#5845) # [Try it in the sample store](https://utopia.fish/p/c144eec3-dog-derby/?branch_name=feature-component-api-segment-control-icons) image See `layout.utopia.js` for the control descriptor with icons set ## Problem https://github.com/concrete-utopia/utopia/issues/5782 ## Fix Interpret the icons coming from the API and use them in the segment control ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../custom-code/internal-property-controls.ts | 4 +- .../controls/option-chain-control.tsx | 5 +- .../inspector/controls/option-control.tsx | 6 +- .../property-control-controls.tsx | 86 +++++++------ .../property-controls-parser.ts | 115 +++++++++--------- editor/src/uuiui/icons.tsx | 2 +- utopia-api/src/index.ts | 2 + utopia-api/src/primitives/icons.tsx | 73 +++++++++++ .../property-controls/property-controls.ts | 6 +- 9 files changed, 192 insertions(+), 107 deletions(-) create mode 100644 utopia-api/src/primitives/icons.tsx diff --git a/editor/src/components/custom-code/internal-property-controls.ts b/editor/src/components/custom-code/internal-property-controls.ts index 659b64b5aed3..8090e1b63179 100644 --- a/editor/src/components/custom-code/internal-property-controls.ts +++ b/editor/src/components/custom-code/internal-property-controls.ts @@ -1,6 +1,6 @@ import type { CSSProperties } from 'react' import type { ComponentInfo } from './code-file' -import type { PropertyControlIcon } from 'utopia-api/core' +import type { Icons } from '../../uuiui' interface GenericControlProps { label?: string @@ -50,7 +50,7 @@ export interface BasicControlOption { export interface BasicControlOptionWithIcon { value: T label: string - icon: PropertyControlIcon | null + icon: keyof typeof Icons | null } export type BasicControlOptions = AllowedEnumType[] | BasicControlOption[] diff --git a/editor/src/components/inspector/controls/option-chain-control.tsx b/editor/src/components/inspector/controls/option-chain-control.tsx index ff9fd38ad96a..85bc06227b1c 100644 --- a/editor/src/components/inspector/controls/option-chain-control.tsx +++ b/editor/src/components/inspector/controls/option-chain-control.tsx @@ -3,9 +3,8 @@ import type { Interpolation } from '@emotion/react' import { jsx } from '@emotion/react' import React from 'react' -import { FlexRow, colorTheme } from '../../../uuiui' +import { colorTheme } from '../../../uuiui' import type { IcnProps } from '../../../uuiui' -import { UtopiaTheme } from '../../../uuiui' import type { DEPRECATEDControlProps, DEPRECATEDGenericControlOptions } from './control' import { OptionControl } from './option-control' import Utils from '../../../utils/utils' @@ -13,6 +12,7 @@ import Utils from '../../../utils/utils' export interface OptionChainOption { value: T icon?: IcnProps + iconComponent?: React.ReactNode label?: string tooltip?: string forceCallOnSubmitValue?: boolean // Call the onSubmitValue again even when the control is already on that value @@ -86,6 +86,7 @@ export const OptionChainControl: React.FunctionComponent< DEPRECATED_controlOptions={{ tooltip: option.tooltip, icon: option.icon, + iconComponent: option.iconComponent, labelInner: option.label, }} value={props.value === option.value} diff --git a/editor/src/components/inspector/controls/option-control.tsx b/editor/src/components/inspector/controls/option-control.tsx index b7a357b3652d..34baab3711e4 100644 --- a/editor/src/components/inspector/controls/option-control.tsx +++ b/editor/src/components/inspector/controls/option-control.tsx @@ -6,11 +6,11 @@ import type { DEPRECATEDControlProps, DEPRECATEDGenericControlOptions } from './ import { colorTheme } from '../../../uuiui' import type { IcnProps } from '../../../uuiui' import { UtopiaTheme, Tooltip, Icn } from '../../../uuiui' -import { useIsMyProject } from '../../editor/store/collaborative-editing' import { useControlsDisabledInSubtree } from '../../../uuiui/utilities/disable-subtree' export interface DEPRECATEDOptionControlOptions extends DEPRECATEDGenericControlOptions { icon?: IcnProps + iconComponent?: React.ReactNode labelInner?: string tooltip?: string roundCorners?: @@ -181,7 +181,9 @@ export const OptionControl: React.FunctionComponent< style={{ marginRight: controlOptions.labelInner == null ? 0 : 4 }} {...controlOptions.icon} /> - ) : null} + ) : ( + controlOptions.iconComponent ?? null + )} {controlOptions.labelInner != null ? controlOptions.labelInner : null}
diff --git a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx index 9e34235c2703..5c33c6966ea4 100644 --- a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx +++ b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx @@ -1,7 +1,36 @@ import fastDeepEquals from 'fast-deep-equal' import React from 'react' +import { MetadataUtils } from '../../../../core/model/element-metadata-utils' +import { isRight } from '../../../../core/shared/either' +import { isJSXElement } from '../../../../core/shared/element-template' +import { parseNumber } from '../../../../core/shared/math-utils' +import { forceNotNull } from '../../../../core/shared/optional-utils' +import type { ElementPath, Imports, PropertyPath } from '../../../../core/shared/project-file-types' +import { importDetailsFromImportOption } from '../../../../core/shared/project-file-types' +import * as PP from '../../../../core/shared/property-path' +import { assertNever } from '../../../../core/shared/utils' +import { useKeepReferenceEqualityIfPossible } from '../../../../utils/react-performance' +import type { JSXParsedType, JSXParsedValue } from '../../../../utils/value-parser-utils' +import type { NumberInputProps } from '../../../../uuiui' +import { + ChainedNumberInput, + FlexColumn, + FlexRow, + Icn, + Icons, + PopupList, + SimpleNumberInput, + UtopiaTheme, + useColorTheme, + useWrappedEmptyOrUnknownOnSubmitValue, + wrappedEmptyOrUnknownOnSubmitValue, +} from '../../../../uuiui' import type { CSSCursor } from '../../../../uuiui-deps' import { SliderControl, getControlStyles } from '../../../../uuiui-deps' +import { + normalisePathSuccessOrThrowError, + normalisePathToUnderlyingTarget, +} from '../../../custom-code/code-file' import type { AllowedEnumType, BasicControlOption, @@ -24,50 +53,22 @@ import type { Vector3ControlDescription, Vector4ControlDescription, } from '../../../custom-code/internal-property-controls' +import type { EditorAction } from '../../../editor/action-types' +import { addImports, forceParseFile } from '../../../editor/actions/action-creators' +import { useDispatch } from '../../../editor/store/dispatch-context' +import { Substores, useEditorState } from '../../../editor/store/store-hook' +import type { CSSNumber } from '../../common/css-utils' +import { cssNumber, defaultCSSColor, printCSSNumber } from '../../common/css-utils' import type { InspectorInfo, InspectorInfoWithRawValue } from '../../common/property-path-hooks' import { BooleanControl } from '../../controls/boolean-control' -import type { NumberInputProps } from '../../../../uuiui' -import { - useWrappedEmptyOrUnknownOnSubmitValue, - SimpleNumberInput, - PopupList, - ChainedNumberInput, - wrappedEmptyOrUnknownOnSubmitValue, - FlexColumn, - FlexRow, - UtopiaTheme, - useColorTheme, - Icn, -} from '../../../../uuiui' -import type { CSSNumber } from '../../common/css-utils' -import { printCSSNumber, cssNumber, defaultCSSColor } from '../../common/css-utils' -import * as PP from '../../../../core/shared/property-path' import { ColorControl } from '../../controls/color-control' -import { StringControl } from '../../controls/string-control' -import type { SelectOption } from '../../controls/select-control' import type { OptionChainOption } from '../../controls/option-chain-control' import { OptionChainControl } from '../../controls/option-chain-control' -import { useKeepReferenceEqualityIfPossible } from '../../../../utils/react-performance' -import { UIGridRow } from '../../widgets/ui-grid-row' -import type { ElementPath, Imports, PropertyPath } from '../../../../core/shared/project-file-types' -import { importDetailsFromImportOption } from '../../../../core/shared/project-file-types' -import { Substores, useEditorState } from '../../../editor/store/store-hook' -import { addImports, forceParseFile } from '../../../editor/actions/action-creators' -import type { EditorAction } from '../../../editor/action-types' -import { forceNotNull } from '../../../../core/shared/optional-utils' +import type { SelectOption } from '../../controls/select-control' import type { DEPRECATEDSliderControlOptions } from '../../controls/slider-control' -import { - normalisePathSuccessOrThrowError, - normalisePathToUnderlyingTarget, -} from '../../../custom-code/code-file' -import { useDispatch } from '../../../editor/store/dispatch-context' +import { StringControl } from '../../controls/string-control' +import { UIGridRow } from '../../widgets/ui-grid-row' import { HtmlPreview, ImagePreview } from './property-content-preview' -import { isJSXElement } from '../../../../core/shared/element-template' -import type { JSXParsedType, JSXParsedValue } from '../../../../utils/value-parser-utils' -import { assertNever } from '../../../../core/shared/utils' -import { MetadataUtils } from '../../../../core/model/element-metadata-utils' -import { isRight } from '../../../../core/shared/either' -import { parseNumber } from '../../../../core/shared/math-utils' export interface ControlForPropProps { propPath: PropertyPath @@ -435,6 +436,16 @@ function labelFromRadioControlOption(option: RadioControlOption): strin } } +function iconFromRadioControlOption( + option: RadioControlOption, +): OptionChainOption['iconComponent'] { + if (option.type === 'allowed-enum-type' || option.option.icon == null) { + return undefined + } + + return React.createElement(Icons[option.option.icon]) +} + export const RadioPropertyControl = React.memo( (props: ControlForPropProps) => { const { propName, propMetadata, controlDescription } = props @@ -450,6 +461,7 @@ export const RadioPropertyControl = React.memo( return { value: valueFromRadioControlOption(option), label: labelFromRadioControlOption(option), + iconComponent: iconFromRadioControlOption(option), } }), ) diff --git a/editor/src/core/property-controls/property-controls-parser.ts b/editor/src/core/property-controls/property-controls-parser.ts index 3433f925666e..08e35b6cda95 100644 --- a/editor/src/core/property-controls/property-controls-parser.ts +++ b/editor/src/core/property-controls/property-controls-parser.ts @@ -1,39 +1,38 @@ -import type { - CheckboxControlDescription, - ColorControlDescription, - ControlDescription, - NumberInputControlDescription, - RadioControlDescription, - PopUpListControlDescription, - StringInputControlDescription, - NoneControlDescription, - UnionControlDescription, - ArrayControlDescription, - ObjectControlDescription, - StyleControlsControlDescription, - Vector2ControlDescription, - Vector3ControlDescription, - ExpressionPopUpListControlDescription, - ImportType, - PropertyControls, - RegularControlDescription, - ExpressionInputControlDescription, - RegularControlType, - Vector4ControlDescription, - EulerControlDescription, - Matrix3ControlDescription, - Matrix4ControlDescription, - BasicControlOption, - BasicControlOptions, - ExpressionControlOption, - TupleControlDescription, - HtmlInputControlDescription, - JSXControlDescription, - AllowedEnumType, - Matrix3, - Matrix4, - ComponentExample, - PreferredContents, +import { + type CheckboxControlDescription, + type ColorControlDescription, + type ControlDescription, + type NumberInputControlDescription, + type RadioControlDescription, + type PopUpListControlDescription, + type StringInputControlDescription, + type NoneControlDescription, + type UnionControlDescription, + type ArrayControlDescription, + type ObjectControlDescription, + type StyleControlsControlDescription, + type Vector2ControlDescription, + type Vector3ControlDescription, + type ExpressionPopUpListControlDescription, + type ImportType, + type RegularControlDescription, + type ExpressionInputControlDescription, + type RegularControlType, + type Vector4ControlDescription, + type EulerControlDescription, + type Matrix3ControlDescription, + type Matrix4ControlDescription, + type BasicControlOption, + type BasicControlOptions, + type ExpressionControlOption, + type TupleControlDescription, + type HtmlInputControlDescription, + type JSXControlDescription, + type AllowedEnumType, + type Matrix3, + type Matrix4, + type PreferredContents, + type BasicControlOptionWithIcon, } from 'utopia-api/core' import { parseColor } from '../../components/inspector/common/css-utils' import type { Parser, ParseResult } from '../../utils/value-parser-utils' @@ -51,45 +50,27 @@ import { parseArray, parseBoolean, parseConstant, - parseFunction, parseNull, - parseNullable, parseNumber, parseObject, parseString, - parseTuple, - parseUndefined, + parseEnum, } from '../../utils/value-parser-utils' import { applicative2Either, applicative3Either, applicative4Either, - applicative5Either, applicative6Either, applicative8Either, - applicative9Either, foldEither, left, right, - isRight, - mapEither, - flatMapEither, - isLeft, - applicative10Either, applicative7Either, } from '../shared/either' -import { - objectMap, - setOptionalProp, - forEachValue, - objectMapDropNulls, -} from '../shared/object-utils' +import { objectMap, setOptionalProp } from '../shared/object-utils' import { parseEnumValue } from './property-control-values' -import { - parseComponentExample, - parseComponentInsertOption, - parsePreferredContents, -} from './property-controls-local' +import { parsePreferredContents } from './property-controls-local' +import { UtopiaIcons } from 'utopia-api' const requiredFieldParser = optionalObjectKeyParser(parseBoolean, 'required') @@ -129,6 +110,22 @@ const parseBasicControlOptions: Parser> = parseAlte 'Not a valid array of options', ) +const parseBasicControlOptionsWithIcon: Parser< + AllowedEnumType[] | BasicControlOptionWithIcon[] +> = parseAlternative[]>( + [ + parseArray(parseEnumValue), + parseArray( + objectParser>({ + label: parseString, + value: parseAny, + icon: optionalProp(parseEnum(UtopiaIcons)), + }), + ), + ], + 'Not a valid array of options', +) + const parseEnumValueOrBasicControlOption: Parser> = parseAlternative>( [parseEnumValue, parseBasicControlOption(parseAny)], @@ -345,7 +342,7 @@ export function parseRadioControlDescription(value: unknown): ParseResult { export interface BasicControlOptionWithIcon { value: T label: string - icon?: PropertyControlIcon + icon?: UtopiaIcon } export type BasicControlOptions = AllowedEnumType[] | BasicControlOption[] From 866108db59c322c85e1d6ebef693485a4cfd6e93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Fri, 7 Jun 2024 15:11:04 +0200 Subject: [PATCH 041/103] Move the scope selector to the bottom of the data picker. (#5863) ## Before ![image](https://github.com/concrete-utopia/utopia/assets/16385508/9494b1ef-8685-4d52-8fb5-95f056475d13) ## After image Ignore the wide cartouches, fix coming on a separate PR ### Manual Tests I hereby swear that: - [ ] I opened a hydrogen project and it loaded - [ ] I could navigate to various routes in Preview mode --- .../component-section/data-selector-modal.tsx | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index f70ad55eb08e..5f6f6f479179 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -411,32 +411,6 @@ export const DataSelectorModal = React.memo( ...style, }} > - {/* Scope Selector Breadcrumbs */} - - {elementLabelsWithScopes.map(({ label, scope, hasContent }, idx, a) => ( - -
- {label} -
- {idx < a.length - 1 ? ( - {'/'} - ) : null} -
- ))} -
{/* top bar */} @@ -630,6 +604,32 @@ export const DataSelectorModal = React.memo(
, )}
+ {/* Scope Selector Breadcrumbs */} + + {elementLabelsWithScopes.map(({ label, scope, hasContent }, idx, a) => ( + +
+ {label} +
+ {idx < a.length - 1 ? ( + {'/'} + ) : null} +
+ ))} +
From d06b6c308ef7eb9e03b2f5c8fb0db5e491ecc5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Fri, 7 Jun 2024 15:49:03 +0200 Subject: [PATCH 042/103] fix color pickers (#5864) https://utopia.fish/p/216dfd55-enthusiastic-gorgonzola/?branch_name=fix-color-picker ## Problem The color pickers cannot be opened ## Fix Undo the changes in `InspectorModal` and fix the Karma DOM ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode - [x] data picker can be opened --- .../components/canvas/ui-jsx.test-utils.tsx | 24 ++++++++++--------- .../inspector/widgets/inspector-modal.tsx | 11 +++++---- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/editor/src/components/canvas/ui-jsx.test-utils.tsx b/editor/src/components/canvas/ui-jsx.test-utils.tsx index 170502bf542b..6fe1b921ad78 100644 --- a/editor/src/components/canvas/ui-jsx.test-utils.tsx +++ b/editor/src/components/canvas/ui-jsx.test-utils.tsx @@ -613,9 +613,10 @@ export async function renderTestEditorWithModel( numberOfCommits++ }} > -
- {failOnCanvasError ? : null} - - + +
, ) diff --git a/editor/src/components/inspector/widgets/inspector-modal.tsx b/editor/src/components/inspector/widgets/inspector-modal.tsx index 4cf239bd10cd..a3aa4e6a91a9 100644 --- a/editor/src/components/inspector/widgets/inspector-modal.tsx +++ b/editor/src/components/inspector/widgets/inspector-modal.tsx @@ -33,8 +33,9 @@ export const InspectorModal: React.FunctionComponent< useHandleCloseOnESCOrEnter(closePopup) const outerElementRef = React.useRef(null) const wrapperRef = React.useRef(null) - const [editorWidth, setEditorWidth] = React.useState(document.body.clientWidth) - const [editorHeight, setEditorHeight] = React.useState(document.body.clientHeight) + const editor = document.getElementById(EditorID) as HTMLElement + const [editorWidth, setEditorWidth] = React.useState(editor.clientWidth) + const [editorHeight, setEditorHeight] = React.useState(editor.clientHeight) const [wrapperWidth, setWrapperWidth] = React.useState(0) const [wrapperHeight, setWrapperHeight] = React.useState(0) const [originLeft, setOriginLeft] = React.useState(0) @@ -50,8 +51,8 @@ export const InspectorModal: React.FunctionComponent< ) const updatePositionAndSize = React.useCallback(() => { - setEditorWidth(document.body.clientWidth) - setEditorHeight(document.body.clientHeight) + setEditorWidth(editor.clientWidth) + setEditorHeight(editor.clientHeight) if (wrapperRef.current != null) { setWrapperWidth(wrapperRef.current.children[0].clientWidth) setWrapperHeight(wrapperRef.current.children[0].clientHeight) @@ -61,7 +62,7 @@ export const InspectorModal: React.FunctionComponent< setOriginLeft(boundingRect.left) setOriginTop(boundingRect.top) } - }, []) + }, [editor.clientHeight, editor.clientWidth]) React.useLayoutEffect(() => { window.addEventListener('resize', updatePositionAndSize) From d58937c543633244185be3109b754b1e36b648f5 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 7 Jun 2024 15:54:15 +0200 Subject: [PATCH 043/103] Cartouche inspector input-like wrapper (#5861) Part of #5840 This PR adds a wrapper around cartouches in the inspector so they look like individual pills. The wrapper shows a blue outline when hovered. The `x` button is also removed, although the delete wrapper callback is kept for now since this is still in flux. https://github.com/concrete-utopia/utopia/assets/1081051/913fe852-13e5-4d4b-a6c4-e0f9d5ee541f **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/cartouche-control.tsx | 56 ++++++++--- .../component-section/cartouche-ui.tsx | 17 +--- .../sections/data-reference-section.tsx | 26 +++--- .../sections/layout-section/list-section.tsx | 16 +--- .../layout-section/list-source-cartouche.tsx | 39 ++++++-- .../navigator-item/navigator-item.tsx | 4 +- ...performance-regression-tests.spec.tsx.snap | 92 ++++++++++--------- .../performance-regression-tests.spec.tsx | 4 +- 8 files changed, 150 insertions(+), 104 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx index ec4851248411..b8dc71b89fba 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx @@ -1,4 +1,7 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ import React from 'react' +import { jsx } from '@emotion/react' import { DataCartoucheInner } from './data-reference-cartouche' import { NO_OP } from '../../../../core/shared/utils' import type { ElementPath, PropertyPath } from '../../../../core/shared/project-file-types' @@ -6,6 +9,7 @@ import * as EPP from '../../../template-property-path' import { dataPathSuccess, traceDataFromProp } from '../../../../core/data-tracing/data-tracing' import { Substores, useEditorState } from '../../../editor/store/store-hook' import type { CartoucheDataType } from './cartouche-ui' +import { useColorTheme } from '../../../../uuiui' interface IdentifierExpressionCartoucheControlProps { contents: string @@ -36,17 +40,47 @@ export const IdentifierExpressionCartoucheControl = React.memo( ) return ( - + + + ) }, ) + +export const CartoucheInspectorWrapper = React.memo((props: { children: React.ReactNode }) => { + const colorTheme = useColorTheme() + + return ( +
+ {props.children} +
+ ) +}) +CartoucheInspectorWrapper.displayName = 'CartoucheInspectorWrapper' diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index c2cd4528c4ff..343635ab711d 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -53,6 +53,8 @@ export const CartoucheUI = React.forwardRef( const wrappedOnClick = useStopPropagation(onClick) const wrappedOnDoubleClick = useStopPropagation(onDoubleClick) + + // NOTE: this is currently unused, we should decide if we want to keep allowing deletion of the cartouches from here or not const wrappedOnDelete = useStopPropagation(onDelete) return ( @@ -79,6 +81,7 @@ export const CartoucheUI = React.forwardRef( flex: 1, gap: 4, opacity: preview ? 0.5 : 1, + width: 'max-content', }} css={{ color: selected || highlight === 'strong' ? colors.fg.selected : colors.fg.default, @@ -124,20 +127,6 @@ export const CartoucheUI = React.forwardRef( // a trailing ellipsis is added to indicate that the object can be traversed , )} - {when( - onDelete != null, - , - )}
diff --git a/editor/src/components/inspector/sections/data-reference-section.tsx b/editor/src/components/inspector/sections/data-reference-section.tsx index 7c97b3127084..996c7f907c14 100644 --- a/editor/src/components/inspector/sections/data-reference-section.tsx +++ b/editor/src/components/inspector/sections/data-reference-section.tsx @@ -25,6 +25,7 @@ import { useVariablesInScopeForSelectedElement, } from './component-section/variables-in-scope-utils' import { jsxElementChildToValuePath } from './component-section/data-picker-utils' +import { CartoucheInspectorWrapper } from './component-section/cartouche-control' export const DataReferenceSectionId = 'code-element-section-test-id' @@ -165,18 +166,19 @@ export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[ key={`inspector-data-reference-row-${EP.toString(element.path)}`} > Value - - + + +
) })} diff --git a/editor/src/components/inspector/sections/layout-section/list-section.tsx b/editor/src/components/inspector/sections/layout-section/list-section.tsx index 324b30e7b3a5..cd9e1832df15 100644 --- a/editor/src/components/inspector/sections/layout-section/list-section.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-section.tsx @@ -20,7 +20,8 @@ import type { MetadataSubstate } from '../../../editor/store/store-hook-substore import { UIGridRow } from '../../widgets/ui-grid-row' import { getTextContentOfElement } from '../component-section/data-reference-cartouche' import { JSXPropertyControlForListSection } from '../component-section/property-control-controls' -import { MapListSourceCartouche } from './list-source-cartouche' +import { MapListSourceCartoucheInspector } from './list-source-cartouche' +import { CartoucheInspectorWrapper } from '../component-section/cartouche-control' type MapExpression = JSXMapExpression | 'multiselect' | 'not-a-mapexpression' @@ -141,18 +142,11 @@ export const ListSection = React.memo(({ paths }: { paths: ElementPath[] }) => { List Source - + Contents -
+ { } as JSXParsedValue } /> -
+
) diff --git a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx index 505b7863df89..b97383c719da 100644 --- a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx @@ -27,6 +27,7 @@ import { import { mapDropNulls } from '../../../../core/shared/array-utils' import { traceDataFromElement, dataPathSuccess } from '../../../../core/data-tracing/data-tracing' import type { CartoucheDataType } from '../component-section/cartouche-ui' +import { CartoucheInspectorWrapper } from '../component-section/cartouche-control' function filterVariableOption(option: DataPickerOption): DataPickerOption | null { switch (option.type) { @@ -65,7 +66,32 @@ interface MapListSourceCartoucheProps { openOn: 'single-click' | 'double-click' } -export const MapListSourceCartouche = React.memo((props: MapListSourceCartoucheProps) => { +export const MapListSourceCartoucheNavigator = React.memo((props: MapListSourceCartoucheProps) => { + return ( +
+ +
+ ) +}) +MapListSourceCartoucheNavigator.displayName = 'MapListSourceCartoucheNavigator' + +export const MapListSourceCartoucheInspector = React.memo((props: MapListSourceCartoucheProps) => { + return ( + + + + ) +}) +MapListSourceCartoucheInspector.displayName = 'MapListSourceCartoucheInspector' + +const MapListSourceCartoucheInner = React.memo((props: MapListSourceCartoucheProps) => { const { target, openOn } = props const originalMapExpression = useEditorState( @@ -184,14 +210,7 @@ export const MapListSourceCartouche = React.memo((props: MapListSourceCartoucheP ) return ( -
+ {popupIsOpen ? DataPickerComponent : null} -
+ ) }) diff --git a/editor/src/components/navigator/navigator-item/navigator-item.tsx b/editor/src/components/navigator/navigator-item/navigator-item.tsx index ef99437be247..73df1ee99cc7 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.tsx @@ -79,7 +79,7 @@ import { toVSCodeExtensionMessage } from 'utopia-vscode-common' import type { Emphasis, Icon } from 'utopia-api' import { contextMenu } from 'react-contexify' import { DataReferenceCartoucheControl } from '../../inspector/sections/component-section/data-reference-cartouche' -import { MapListSourceCartouche } from '../../inspector/sections/layout-section/list-source-cartouche' +import { MapListSourceCartoucheNavigator } from '../../inspector/sections/layout-section/list-source-cartouche' export function getItemHeight(navigatorEntry: NavigatorEntry): number { if (isConditionalClauseNavigatorEntry(navigatorEntry)) { @@ -1260,7 +1260,7 @@ export const NavigatorRowLabel = React.memo((props: NavigatorRowLabelProps) => { dispatch={props.dispatch} selected={props.selected} /> - { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`905`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`910`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`646`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`649`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From 269303ebd85188ccb560092656a09f88672e1ada Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Mon, 10 Jun 2024 10:28:02 +0100 Subject: [PATCH 044/103] Property for a Remix starting route. (#5858) - Added `startingRoute` to `UtopiaRemixComponentProps`. - `UtopiaRemixComponentProps` triggers a navigation against the starting route. - Added `startingRoute` to `RemixSceneProps`. --- .../canvas/remix/utopia-remix-root-component.tsx | 7 +++++++ .../ui-jsx-canvas-renderer/remix-scene-component.tsx | 10 +++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/editor/src/components/canvas/remix/utopia-remix-root-component.tsx b/editor/src/components/canvas/remix/utopia-remix-root-component.tsx index b84fe149771f..d64bd85bbe26 100644 --- a/editor/src/components/canvas/remix/utopia-remix-root-component.tsx +++ b/editor/src/components/canvas/remix/utopia-remix-root-component.tsx @@ -286,6 +286,7 @@ function traverseRoutesAndGetIDs(routes: RouteLike[]): Set { export interface UtopiaRemixRootComponentProps { [UTOPIA_PATH_KEY]: ElementPath getLoadContext?: (request: Request) => Promise | AppLoadContext + startingRoute?: string } export const UtopiaRemixRootComponent = (props: UtopiaRemixRootComponentProps) => { @@ -314,6 +315,12 @@ export const UtopiaRemixRootComponent = (props: UtopiaRemixRootComponentProps) = return createMemoryRouter(routes, { initialEntries: initialEntries }) }, [routes]) + React.useEffect(() => { + if (props.startingRoute != null && router != null) { + void router.navigate(props.startingRoute) + } + }, [router, props.startingRoute]) + const setNavigationDataForRouter = React.useCallback( ( innerRouter: RouterType, diff --git a/editor/src/components/canvas/ui-jsx-canvas-renderer/remix-scene-component.tsx b/editor/src/components/canvas/ui-jsx-canvas-renderer/remix-scene-component.tsx index 537f4178eb20..d51eec414380 100644 --- a/editor/src/components/canvas/ui-jsx-canvas-renderer/remix-scene-component.tsx +++ b/editor/src/components/canvas/ui-jsx-canvas-renderer/remix-scene-component.tsx @@ -15,13 +15,13 @@ export interface RemixSceneProps { style?: React.CSSProperties [UTOPIA_PATH_KEY]?: string getLoadContext?: (request: Request) => Promise | AppLoadContext + startingRoute?: string } export const RemixSceneComponent = React.memo((props: React.PropsWithChildren) => { const colorTheme = useColorTheme() - const canvasIsLive = false - const { style, getLoadContext, ...remainingProps } = props + const { style, getLoadContext, startingRoute, ...remainingProps } = props const sceneStyle: React.CSSProperties = { position: 'relative', @@ -51,7 +51,11 @@ export const RemixSceneComponent = React.memo((props: React.PropsWithChildren - +
) }) From e5c5e49996c82aeea49846b6daa8cf594860abb3 Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Mon, 10 Jun 2024 10:28:17 +0100 Subject: [PATCH 045/103] Prevent Error On Adding Page From Template (#5865) - `ADD_NEW_PAGE` action parses the template file upfront when adding it to the project. --- .../src/components/editor/actions/actions.tsx | 31 ++++++++++++++++--- .../parser-printer/parser-printer-worker.ts | 2 +- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/editor/src/components/editor/actions/actions.tsx b/editor/src/components/editor/actions/actions.tsx index 66fbba473a25..9863df541927 100644 --- a/editor/src/components/editor/actions/actions.tsx +++ b/editor/src/components/editor/actions/actions.tsx @@ -587,7 +587,10 @@ import { addHookForProjectChanges } from '../store/collaborative-editing' import { arrayDeepEquality, objectDeepEquality } from '../../../utils/deep-equality' import type { ProjectServerState } from '../store/project-server-state' import { updateFileIfPossible } from './can-update-file' -import { getPrintAndReparseCodeResult } from '../../../core/workers/parser-printer/parser-printer-worker' +import { + getParseFileResult, + getPrintAndReparseCodeResult, +} from '../../../core/workers/parser-printer/parser-printer-worker' import { isSteganographyEnabled } from '../../../core/shared/stegano-text' import type { ParsedTextFileWithPath } from '../../../core/property-controls/property-controls-local' import { @@ -4114,15 +4117,35 @@ export const UPDATE_FNS = { addNewFeaturedRouteToPackageJson(action.newPageName), ) - // 2. write the new text file + // 2. Parse the file upfront. + const existingUIDs = new Set(getAllUniqueUids(editor.projectContents).uniqueIDs) + const parsedResult = getParseFileResult( + newFileName, + templateFile.fileContents.code, + null, + 1, + existingUIDs, + isSteganographyEnabled(), + ) + + // 3. write the new text file const withTextFile = addTextFile( withPackageJson, action.parentPath, newFileName, - codeFile(templateFile.fileContents.code, null, 1, RevisionsState.CodeAhead), + textFile( + textFileContents( + templateFile.fileContents.code, + parsedResult.parseResult, + RevisionsState.CodeAhead, + ), + null, + null, + 1, + ), ) - // 3. open the text file + // 4. open the text file return UPDATE_FNS.OPEN_CODE_EDITOR_FILE( openCodeEditorFile(withTextFile.newFileKey, false), withTextFile.editorState, diff --git a/editor/src/core/workers/parser-printer/parser-printer-worker.ts b/editor/src/core/workers/parser-printer/parser-printer-worker.ts index 2940f1df3e05..77f739284597 100644 --- a/editor/src/core/workers/parser-printer/parser-printer-worker.ts +++ b/editor/src/core/workers/parser-printer/parser-printer-worker.ts @@ -57,7 +57,7 @@ export function handleMessage( } } -function getParseFileResult( +export function getParseFileResult( filename: string, content: string, oldParseResultForUIDComparison: ParseSuccess | null, From 770b1cef7d4f98ef203db717c89742b352817f68 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:33:46 +0200 Subject: [PATCH 046/103] Revamped navigator list cartouche (#5866) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** The navigator cartouche for list items needs some tidying up. **Fix:** - Remove its label - Move the counter inside the cartouche itself - Tweak the colors a bit Screenshot 2024-06-07 at 6 17 35 PM **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5843 --- .../component-section/cartouche-ui.tsx | 3 + .../data-reference-cartouche.tsx | 2 + .../layout-section/list-source-cartouche.tsx | 5 ++ .../navigator/navigator-item/map-counter.tsx | 62 +++++++++---------- .../navigator-item.spec.browser2.tsx | 3 +- .../navigator-item/navigator-item.tsx | 14 ++--- 6 files changed, 46 insertions(+), 43 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 343635ab711d..adcbe96f16a0 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -30,6 +30,7 @@ export type CartoucheUIProps = React.PropsWithChildren<{ onClick?: (e: React.MouseEvent) => void onDoubleClick?: (e: React.MouseEvent) => void onHover?: HoverHandlers + badge?: React.ReactNode }> export const CartoucheUI = React.forwardRef( @@ -127,6 +128,8 @@ export const CartoucheUI = React.forwardRef( // a trailing ellipsis is added to indicate that the object can be traversed , )} + {/* badge (this check is redundant but it should make it more clear that this is optional) */} + {when(props.badge != null, props.badge)}
diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index 4cf40eb05ddc..a4462d7d67aa 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -173,6 +173,7 @@ interface DataCartoucheInnerProps { hideTooltip?: boolean datatype: CartoucheDataType highlight?: CartoucheHighlight | null + badge?: React.ReactNode } export const DataCartoucheInner = React.forwardRef( @@ -220,6 +221,7 @@ export const DataCartoucheInner = React.forwardRef( role='selection' source={source} ref={ref} + badge={props.badge} > {contentsToDisplay.label ?? 'DATA'} diff --git a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx index b97383c719da..6f39e7163962 100644 --- a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx @@ -28,6 +28,7 @@ import { mapDropNulls } from '../../../../core/shared/array-utils' import { traceDataFromElement, dataPathSuccess } from '../../../../core/data-tracing/data-tracing' import type { CartoucheDataType } from '../component-section/cartouche-ui' import { CartoucheInspectorWrapper } from '../component-section/cartouche-control' +import { MapCounter } from '../../../navigator/navigator-item/map-counter' function filterVariableOption(option: DataPickerOption): DataPickerOption | null { switch (option.type) { @@ -64,6 +65,7 @@ interface MapListSourceCartoucheProps { target: ElementPath selected: boolean openOn: 'single-click' | 'double-click' + countChildren?: boolean } export const MapListSourceCartoucheNavigator = React.memo((props: MapListSourceCartoucheProps) => { @@ -223,6 +225,9 @@ const MapListSourceCartoucheInner = React.memo((props: MapListSourceCartouchePro testId='list-source-cartouche' contentIsComingFromServer={isDataComingFromHookResult} datatype={cartoucheDataType} + badge={ + props.countChildren ? : null + } /> ) diff --git a/editor/src/components/navigator/navigator-item/map-counter.tsx b/editor/src/components/navigator/navigator-item/map-counter.tsx index f9c6c502017c..c7acaf17f7a9 100644 --- a/editor/src/components/navigator/navigator-item/map-counter.tsx +++ b/editor/src/components/navigator/navigator-item/map-counter.tsx @@ -1,10 +1,7 @@ import React from 'react' import type { CSSProperties } from 'react' -import type { NavigatorEntry } from '../../../components/editor/store/editor-state' -import { isRegularNavigatorEntry } from '../../../components/editor/store/editor-state' import { Substores, useEditorState } from '../../editor/store/store-hook' import { MetadataUtils } from '../../../core/model/element-metadata-utils' -import { colorTheme } from '../../../uuiui' import * as EP from '../../../core/shared/element-path' import type { ElementPath } from '../../../core/shared/project-file-types' import { @@ -14,8 +11,10 @@ import { import { isRight } from '../../../core/shared/either' import { isJSXMapExpression } from '../../../core/shared/element-template' import { assertNever } from '../../../core/shared/utils' -import type { EditorDispatch } from '../../editor/action-types' import { setMapCountOverride } from '../../editor/actions/action-creators' +import { useDispatch } from '../../editor/store/dispatch-context' +import { useColorTheme } from '../../../uuiui' +import type { ThemeObject } from '../../../uuiui/styles/theme/theme-helpers' export const MapCounterTestIdPrefix = 'map-counter-' @@ -27,27 +26,19 @@ type OverrideStatus = 'no-override' | 'overridden' | 'override-failed' type SelectedStatus = true | false interface MapCounterProps { - navigatorEntry: NavigatorEntry - dispatch: EditorDispatch + elementPath: ElementPath selected: boolean } export const MapCounter = React.memo((props: MapCounterProps) => { - const { navigatorEntry, dispatch } = props - const { elementPath } = navigatorEntry + const dispatch = useDispatch() - const { nrChildren, countOverride } = useEditorState( + const counter = useEditorState( Substores.metadata, (store) => { - if (!isRegularNavigatorEntry(navigatorEntry)) { - return { - nrChildren: null, - countOverride: null, - } - } const elementMetadata = MetadataUtils.findElementByElementPath( store.editor.jsxMetadata, - elementPath, + props.elementPath, ) const element = @@ -55,18 +46,16 @@ export const MapCounter = React.memo((props: MapCounterProps) => { ? elementMetadata.element.value : null if (element == null || !isJSXMapExpression(element)) { - return { - nrChildren: null, - countOverride: null, - } + return null } + const commentFlag = findUtopiaCommentFlag(element.comments, 'map-count') const mapCountOverride = isUtopiaCommentFlagMapCount(commentFlag) ? commentFlag.value : null return { nrChildren: MetadataUtils.getChildrenOrdered( store.editor.jsxMetadata, store.editor.elementPathTree, - elementPath, + props.elementPath, ).length, countOverride: mapCountOverride, } @@ -74,6 +63,14 @@ export const MapCounter = React.memo((props: MapCounterProps) => { 'MapCounter counterValue', ) + const nrChildren = React.useMemo(() => { + return counter?.nrChildren ?? null + }, [counter]) + + const countOverride = React.useMemo(() => { + return counter?.countOverride ?? null + }, [counter]) + const isOverridden = nrChildren != null && countOverride != null const shownCounterValue = countOverride ?? nrChildren const overrideFailed = isOverridden && countOverride > nrChildren @@ -93,20 +90,18 @@ export const MapCounter = React.memo((props: MapCounterProps) => { } const nextValue = getNextOverrideValue(overrideStatus, countOverride, nrChildren) if (nextValue !== countOverride) { - dispatch([setMapCountOverride(elementPath, nextValue)]) + dispatch([setMapCountOverride(props.elementPath, nextValue)]) } - }, [elementPath, dispatch, overrideStatus, countOverride, nrChildren]) - - if (nrChildren == null) { - return null - } + }, [props.elementPath, dispatch, overrideStatus, countOverride, nrChildren]) const selectedStatus = props.selected + const colorTheme = useColorTheme() + return (
{shownCounterValue} @@ -115,6 +110,7 @@ export const MapCounter = React.memo((props: MapCounterProps) => { }) function getMapCounterStyleProps( + colorTheme: ThemeObject, overrideStatus: OverrideStatus, selectedStatus: SelectedStatus, ): CSSProperties { @@ -125,7 +121,7 @@ function getMapCounterStyleProps( height: 15, width: 'max-content', minWidth: 15, - borderRadius: 15, + borderRadius: 4, padding: 4, fontWeight: 400, marginRight: 2, @@ -135,10 +131,8 @@ function getMapCounterStyleProps( case 'no-override': return { ...stylePropsBase, - backgroundColor: selectedStatus - ? colorTheme.whiteOpacity30.value - : colorTheme.fg0Opacity10.value, - color: selectedStatus ? colorTheme.white.value : 'unset', + backgroundColor: selectedStatus ? colorTheme.whiteOpacity30.value : colorTheme.bg1.value, + color: selectedStatus ? colorTheme.white.value : colorTheme.brandNeonPink.value, } case 'overridden': return { diff --git a/editor/src/components/navigator/navigator-item/navigator-item.spec.browser2.tsx b/editor/src/components/navigator/navigator-item/navigator-item.spec.browser2.tsx index b7b69de31ab7..ae03a9a349c8 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.spec.browser2.tsx @@ -322,7 +322,6 @@ describe('Navigator item row icons', () => { const testId = itemLabelTestIdForEntry(navigatorEntry) if (expectedLabel != null) { const labelElement = editor.renderedDOM.getByTestId(testId) - expect(labelElement.innerText).toEqual(expectedLabel) } else { expect(() => editor.renderedDOM.getByTestId(testId)).toThrow() @@ -345,7 +344,7 @@ describe('Navigator item row icons', () => { await checkNavigatorLabel(visibleNavigatorTargets[11], null) await checkNavigatorLabel(visibleNavigatorTargets[12], 'CODE') await checkNavigatorLabel(visibleNavigatorTargets[13], 'div') - await checkNavigatorLabel(visibleNavigatorTargets[14], 'LIST') + await checkNavigatorLabel(visibleNavigatorTargets[14], 'List') await checkNavigatorLabel(visibleNavigatorTargets[15], 'div') await checkNavigatorLabel(visibleNavigatorTargets[16], 'Fragment') await checkNavigatorLabel(visibleNavigatorTargets[17], 'div') diff --git a/editor/src/components/navigator/navigator-item/navigator-item.tsx b/editor/src/components/navigator/navigator-item/navigator-item.tsx index 73df1ee99cc7..ee39a0c6208f 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.tsx @@ -64,7 +64,6 @@ import { LayoutIcon } from './layout-icon' import { NavigatorItemActionSheet } from './navigator-item-components' import { assertNever } from '../../../core/shared/utils' import type { ElementPathTrees } from '../../../core/shared/element-path-tree' -import { MapCounter } from './map-counter' import { conditionalTarget, renderPropTarget, @@ -1242,7 +1241,12 @@ export const NavigatorRowLabel = React.memo((props: NavigatorRowLabelProps) => { />, )} -
+
{ remixItemType={props.remixItemType} />
- Date: Mon, 10 Jun 2024 14:10:43 +0200 Subject: [PATCH 047/103] scope selector sticks to the bottom (#5873) image image it sticks to the bottom! (Ignore Whitespace recommended) --- .../component-section/data-selector-modal.tsx | 247 +++++++++--------- 1 file changed, 130 insertions(+), 117 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 5f6f6f479179..4ec605337740 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -483,129 +483,142 @@ export const DataSelectorModal = React.memo( {/* detail view */} -
- - {when( - primitiveVars.length > 0, - <> - - {primitiveVars.map((variable) => ( - - {variableNameFromPath(variable)} - - ))} - - - , - )} - {folderVars.map((variable, idx) => ( - - - {variableNameFromPath(variable)} - - {variable.type === 'array' ? ( - - ) : ( -
- )} - {/* properties in scope */} - - {childVars(variable, indexLookup).map((child) => ( - - {variableNameFromPath(child)} - - ))} - - {idx < focusedVariableChildren.length - 1 ? ( + +
+ + {when( + primitiveVars.length > 0, + <> + + {primitiveVars.map((variable) => ( + + {variableNameFromPath(variable)} + + ))} + - ) : null} - - ))} - {/* Empty State */} - {when( - focusedVariableChildren.length === 0, -
- We did not find any insertable data -
, - )} -
+ , + )} + {folderVars.map((variable, idx) => ( + + + {variableNameFromPath(variable)} + + {variable.type === 'array' ? ( + + ) : ( +
+ )} + {/* properties in scope */} + + {childVars(variable, indexLookup).map((child) => ( + + {variableNameFromPath(child)} + + ))} + + {idx < focusedVariableChildren.length - 1 ? ( + + ) : null} + + ))} + {/* Empty State */} + {when( + focusedVariableChildren.length === 0, +
+ We did not find any insertable data +
, + )} +
+
{/* Scope Selector Breadcrumbs */} - + {elementLabelsWithScopes.map(({ label, scope, hasContent }, idx, a) => (
Date: Mon, 10 Jun 2024 14:53:11 +0200 Subject: [PATCH 048/103] Run dom walker after resize/mutation observer changes in select mode (#5838) **Problem:** In the sample store we encountered out-of-date navigator several times, e.g. after initial load or after remix navigation. Sometimes the problem is automatically fixed after a while, sometimes you need to interact with the editor, and then the navigator is fixed. See: https://github.com/concrete-utopia/utopia/issues/5824 **Fix:** When you navigate with Remix, or you wait for asynchronous load of data and for the changes after that, then there is no final dispatch when the content is ready (which would trigger a dom walker run). We experienced this problem earlier in live mode: when the state of the app changes in live mode, we need to guarantee to run the dom walker, even though no dispatch has happened. To fix this, we rely in resize and mutation observers, see, https://github.com/concrete-utopia/utopia/pull/4167 Even though In the original PR the observers were not turned in select mode due to performance reasons, in my experience the performance impact is acceptable, because we don't listen to the observer during canvas interactions. So we only have extra dom walker runs after one-off interactions, e.g. after changing something in the inspector. I stopped using the resize observer polyfill, because ResizeObserver is widely supported on modern browsers, so that just looked as a potential source of problems (and the native solution should be better regarding performance too). I still needed to keep the polyfill for unit tests, because jsdom doesn't support ResizeObserver. I disabled the dom walker caching tests, because they were already invalid (they expected exactly the opposite what their title described....). Fully understanding why these tests are like this and fix them would greatly increase the scope of this PR, and it is an urgent fix for a project like the sample store. **Manual Tests:** I hereby swear that: - [X] I opened a hydrogen project and it loaded - [X] I could navigate to various routes in Preview mode Fixes https://github.com/concrete-utopia/utopia/issues/5824 --- .../dom-walker-caching.spec.browser2.tsx | 8 +- editor/src/components/canvas/dom-walker.ts | 23 ++-- .../inspector/widgets/inspector-modal.tsx | 2 +- ...performance-regression-tests.spec.tsx.snap | 116 ++++++++++++++++++ .../performance-regression-tests.spec.tsx | 4 +- editor/src/templates/editor-canvas.tsx | 3 +- 6 files changed, 141 insertions(+), 15 deletions(-) diff --git a/editor/src/components/canvas/dom-walker-caching.spec.browser2.tsx b/editor/src/components/canvas/dom-walker-caching.spec.browser2.tsx index b94e3ef0dcc0..ace6845b8d07 100644 --- a/editor/src/components/canvas/dom-walker-caching.spec.browser2.tsx +++ b/editor/src/components/canvas/dom-walker-caching.spec.browser2.tsx @@ -53,7 +53,9 @@ describe('Dom-walker Caching', () => { }) // FIXME The below two tests have become flaky because of the UPDATE_PROJECT_SERVER_STATE action - it('resizing an out-of-file element invalidates the cache for only that scene', async () => { + // TODO: this test doesn't test what the title describes. In the expectation it actually tests there are invalidated elements + // in both scenes. + xit('resizing an out-of-file element invalidates the cache for only that scene', async () => { const renderResult = await prepareTestProject() renderResult.clearRecordedActions() @@ -158,7 +160,9 @@ describe('Dom-walker Caching', () => { expect(saveDomReportActions[3].cachedPaths).toEqual([]) }) - it('resizing an in-file element invalidates the cache for only that scene', async () => { + // TODO: this test doesn't test what the title describes. In the expectation it actually tests there are invalidated elements + // in both scenes. + xit('resizing an in-file element invalidates the cache for only that scene', async () => { const renderResult = await prepareTestProject() renderResult.clearRecordedActions() diff --git a/editor/src/components/canvas/dom-walker.ts b/editor/src/components/canvas/dom-walker.ts index 7eb741cc0a68..ff9ec1bd90cb 100644 --- a/editor/src/components/canvas/dom-walker.ts +++ b/editor/src/components/canvas/dom-walker.ts @@ -1,8 +1,6 @@ import React from 'react' import { sides } from 'utopia-api/core' import * as ResizeObserverSyntheticDefault from 'resize-observer-polyfill' -const ResizeObserver = ResizeObserverSyntheticDefault.default ?? ResizeObserverSyntheticDefault - import * as EP from '../../core/shared/element-path' import type { DetectedLayoutSystem, @@ -88,10 +86,12 @@ import { pick } from '../../core/shared/object-utils' import { getFlexAlignment, getFlexJustifyContent, MaxContent } from '../inspector/inspector-common' import type { EditorDispatch } from '../editor/action-types' import { runDOMWalker } from '../editor/actions/action-creators' -import { isLiveMode } from '../editor/editor-modes' + +export const ResizeObserver = + window.ResizeObserver ?? ResizeObserverSyntheticDefault.default ?? ResizeObserverSyntheticDefault const MutationObserverConfig = { attributes: true, childList: true, subtree: true } -const ObserversAvailable = (window as any).MutationObserver != null && ResizeObserver != null +const ObserversAvailable = window.MutationObserver != null && ResizeObserver != null function elementLayoutSystem(computedStyle: CSSStyleDeclaration | null): DetectedLayoutSystem { if (computedStyle == null) { @@ -170,7 +170,7 @@ function isScene(node: Node): node is HTMLElement { ) } -function findParentScene(target: HTMLElement): string | null { +function findParentScene(target: Element): string | null { // First check if the node is a Scene element, which could be nested at any level const sceneID = getDOMAttribute(target, UTOPIA_SCENE_ID_KEY) if (sceneID != null) { @@ -538,12 +538,19 @@ export function initDomWalkerObservers( editorStore: UtopiaStoreAPI, dispatch: EditorDispatch, ): { resizeObserver: ResizeObserver; mutationObserver: MutationObserver } { + // Warning: I modified this code so it runs in all modes, not just in live mode. We still don't trigger + // the DOM walker during canvas interactions, so the performance impact doesn't seem that bad. But it is + // necessary, because after remix navigation, and after dynamic changes coming from loaders sometimes the + // dom walker was not executed after all the changes. + // + // This was the original comment here when this only ran in live mode: + // // Warning: These observers only trigger the DOM walker whilst in live mode to ensure metadata is up to date // when interacting with the actual running application / components. There are likely edge cases where we // also want these to trigger the DOM walker whilst in select mode, but if we find such a case we need to // adequately assess the performance impact of doing so, and ideally find a way to only do so when the observed // change was not triggered by a user interaction - const resizeObserver = new ResizeObserver((entries: any) => { + const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => { const canvasInteractionHappening = selectCanvasInteractionHappening(editorStore.getState()) const selectedViews = editorStore.getState().editor.selectedViews if (canvasInteractionHappening) { @@ -560,7 +567,7 @@ export function initDomWalkerObservers( shouldRunDOMWalker = true } } - if (shouldRunDOMWalker && isLiveMode(editorStore.getState().editor.mode)) { + if (shouldRunDOMWalker) { dispatch([runDOMWalker()]) } } @@ -592,7 +599,7 @@ export function initDomWalkerObservers( } } } - if (shouldRunDOMWalker && isLiveMode(editorStore.getState().editor.mode)) { + if (shouldRunDOMWalker) { dispatch([runDOMWalker()]) } } diff --git a/editor/src/components/inspector/widgets/inspector-modal.tsx b/editor/src/components/inspector/widgets/inspector-modal.tsx index a3aa4e6a91a9..f018628df9ed 100644 --- a/editor/src/components/inspector/widgets/inspector-modal.tsx +++ b/editor/src/components/inspector/widgets/inspector-modal.tsx @@ -2,8 +2,8 @@ import React from 'react' import * as ReactDOM from 'react-dom' import { useHandleCloseOnESCOrEnter } from '../common/inspector-utils' import { EditorID, PortalTargetID } from '../../../core/shared/utils' -import ResizeObserver from 'resize-observer-polyfill' import { OnClickOutsideHOC } from '../../../uuiui' +import { ResizeObserver } from '../../canvas/dom-walker' export type InspectorModalProps = { offsetX: number diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index c12a11eac03b..2742219605ff 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -2087,6 +2087,89 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)", "/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", "/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//UtopiaSpiedClass(EditorCanvas)", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//Symbol(react.memo)(FloatingPostActionMenu)", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//div", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//Symbol(react.forward_ref)(Styled(div))", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//Symbol(react.forward_ref)(Styled(div))", + "/div//Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/div", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/Symbol(react.memo)(NewCanvasControls)", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/Symbol(react.memo)()", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/Symbol(react.memo)()", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/UtopiaSpiedFunctionComponent(EditorCommon)", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/div:data-testid='canvas-root'", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(DataReferenceParentOutline)", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/div:data-testid='new-canvas-controls-container'", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null///Symbol(react.memo)(PropertyLabel)", + "/null///Symbol(react.memo)()", + "/null///div", + "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", + "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", + "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", + "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/span", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/Symbol(react.memo)(Icon)", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/div:data-testid='plus-button-onMouseDown'", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/UtopiaSpiedClass(Tooltip)", + "/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", + "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div///Symbol(react.forward_ref)()", + "/div///Symbol(react.memo)(CartoucheInspectorWrapper)", + "///CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()", + "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon)", + "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", + "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/span", + "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/UtopiaSpiedClass(Tooltip)", + "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/div", + "/Symbol(react.forward_ref)()/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", + "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/span", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(pt)", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)", + "/div/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", + "/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", @@ -2832,6 +2915,39 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//UtopiaSpiedClass(EditorCanvas)", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//Symbol(react.memo)(FloatingPostActionMenu)", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//div", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//Symbol(react.forward_ref)(Styled(div))", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div//Symbol(react.forward_ref)(Styled(div))", + "/div//Symbol(react.forward_ref)(Styled(div))/div", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/div", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/Symbol(react.memo)(NewCanvasControls)", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/Symbol(react.memo)()", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/Symbol(react.memo)()", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/UtopiaSpiedFunctionComponent(EditorCommon)", + "/Symbol(react.forward_ref)(Styled(div))/div/UtopiaSpiedClass(EditorCanvas)/div:data-testid='canvas-root'", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(DataReferenceParentOutline)", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)()", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/div:data-testid='new-canvas-controls-container'", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", + "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", "/UtopiaSpiedFunctionComponent(Provider)/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(ComponentRenderer(storyboard))/Symbol(react.forward_ref)(SpyWrapper)", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index d63703ba36e6..e0a314bb2ec1 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -65,7 +65,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`740`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`773`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -127,7 +127,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`910`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`993`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) diff --git a/editor/src/templates/editor-canvas.tsx b/editor/src/templates/editor-canvas.tsx index 381df809eb84..5635b684bdb2 100644 --- a/editor/src/templates/editor-canvas.tsx +++ b/editor/src/templates/editor-canvas.tsx @@ -101,11 +101,10 @@ import { UtopiaStyles, colorTheme } from '../uuiui' import { DropHandlers } from './image-drop' import { EditorCommon } from '../components/editor/editor-component-common' import { CursorComponent } from '../components/canvas/controls/select-mode/cursor-component' -import * as ResizeObserverSyntheticDefault from 'resize-observer-polyfill' import { isFeatureEnabled } from '../utils/feature-switches' import { getCanvasViewportCenter } from './paste-helpers' import { DataPasteHandler, isPasteHandler } from '../utils/paste-handler' -const ResizeObserver = ResizeObserverSyntheticDefault.default ?? ResizeObserverSyntheticDefault +import { ResizeObserver } from '../components/canvas/dom-walker' const webFrame = PROBABLY_ELECTRON ? requireElectron().webFrame : null From 21fc7ec5b0dc89807f90a6f5ef3991ac3324639e Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:09:50 +0200 Subject: [PATCH 049/103] Trim children string inspector inputs (#5874) **Problem:** Children text string inputs in the inspector can contain non-trimmed strings. **Fix:** Trim them if defined. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5871 --- .../component-section-children.tsx | 2 +- .../property-control-controls.tsx | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/component-section-children.tsx b/editor/src/components/inspector/sections/component-section/component-section-children.tsx index 39f178fe109f..95a61d76cd38 100644 --- a/editor/src/components/inspector/sections/component-section/component-section-children.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section-children.tsx @@ -82,7 +82,7 @@ export function useChildrenPropOverride( ? props.controlDescription : { control: 'string-input', - label: 'hey', + label: 'children', } } /> diff --git a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx index 5c33c6966ea4..bc6f23f668ec 100644 --- a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx +++ b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx @@ -551,11 +551,19 @@ export const StringInputPropertyControl = React.memo( element.element.value.children.length > 0 ) { const child = element.element.value.children[0] - switch (child.type) { - case 'ATTRIBUTE_OTHER_JAVASCRIPT': - return child.originalJavascript - case 'JSX_TEXT_BLOCK': - return child.text + function getChildText(): string | null { + switch (child.type) { + case 'ATTRIBUTE_OTHER_JAVASCRIPT': + return child.originalJavascript + case 'JSX_TEXT_BLOCK': + return child.text + default: + return null + } + } + const maybeText = getChildText() + if (maybeText != null) { + return maybeText.trim() } } return undefined From ea99e3b3489ecbd4483ed06eefe462b47ee9b4ea Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:21:22 +0200 Subject: [PATCH 050/103] Consistent width for background layers pickers (#5879) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** The color pickers for the background resize with the inspector. **Fix:** Make the different background layers' swatches sizes consistent. Screenshot 2024-06-10 at 5 57 33 PM **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5870 --- .../background-solid-or-gradient-thumbnail-control.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/editor/src/components/inspector/controls/background-solid-or-gradient-thumbnail-control.tsx b/editor/src/components/inspector/controls/background-solid-or-gradient-thumbnail-control.tsx index 1e9c39d353ed..ec7280620d9b 100644 --- a/editor/src/components/inspector/controls/background-solid-or-gradient-thumbnail-control.tsx +++ b/editor/src/components/inspector/controls/background-solid-or-gradient-thumbnail-control.tsx @@ -183,7 +183,11 @@ export const BackgroundSolidOrGradientThumbnailControl = React.memo( ['controlClassName'], props, )} ignore-react-onclickoutside-${props.id}`} - style={props.style} + style={{ + width: 30, + height: 24, + ...props.style, + }} > {picker}
From 41d8b8af87b0e611993f7944541105b2e7d2dd4d Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Mon, 10 Jun 2024 16:44:04 -0400 Subject: [PATCH 051/103] New Inspector Icons (#5882) --- .../alignContent-column-center-aqua-16x16@2x.png | Bin 0 -> 665 bytes ...alignContent-column-center-black-16x16@2x.png | Bin 0 -> 669 bytes .../alignContent-column-center-blue-16x16@2x.png | Bin 0 -> 670 bytes ...gnContent-column-center-darkgray-16x16@2x.png | Bin 0 -> 660 bytes .../alignContent-column-center-gray-16x16@2x.png | Bin 0 -> 643 bytes ...alignContent-column-center-green-16x16@2x.png | Bin 0 -> 682 bytes ...nContent-column-center-lightaqua-16x16@2x.png | Bin 0 -> 671 bytes ...nContent-column-center-lightblue-16x16@2x.png | Bin 0 -> 661 bytes ...nContent-column-center-lightgray-16x16@2x.png | Bin 0 -> 669 bytes ...Content-column-center-lightgreen-16x16@2x.png | Bin 0 -> 668 bytes ...ontent-column-center-lightpurple-16x16@2x.png | Bin 0 -> 674 bytes ...lignContent-column-center-purple-16x16@2x.png | Bin 0 -> 665 bytes .../alignContent-column-center-red-16x16@2x.png | Bin 0 -> 658 bytes ...alignContent-column-center-white-16x16@2x.png | Bin 0 -> 605 bytes ...alignContent-column-flexend-aqua-16x16@2x.png | Bin 0 -> 671 bytes ...lignContent-column-flexend-black-16x16@2x.png | Bin 0 -> 674 bytes ...alignContent-column-flexend-blue-16x16@2x.png | Bin 0 -> 664 bytes ...nContent-column-flexend-darkgray-16x16@2x.png | Bin 0 -> 661 bytes ...alignContent-column-flexend-gray-16x16@2x.png | Bin 0 -> 645 bytes ...lignContent-column-flexend-green-16x16@2x.png | Bin 0 -> 685 bytes ...Content-column-flexend-lightaqua-16x16@2x.png | Bin 0 -> 663 bytes ...Content-column-flexend-lightblue-16x16@2x.png | Bin 0 -> 665 bytes ...Content-column-flexend-lightgray-16x16@2x.png | Bin 0 -> 659 bytes ...ontent-column-flexend-lightgreen-16x16@2x.png | Bin 0 -> 671 bytes ...ntent-column-flexend-lightpurple-16x16@2x.png | Bin 0 -> 678 bytes ...ignContent-column-flexend-purple-16x16@2x.png | Bin 0 -> 662 bytes .../alignContent-column-flexend-red-16x16@2x.png | Bin 0 -> 656 bytes ...lignContent-column-flexend-white-16x16@2x.png | Bin 0 -> 594 bytes ...ignContent-column-flexstart-aqua-16x16@2x.png | Bin 0 -> 676 bytes ...gnContent-column-flexstart-black-16x16@2x.png | Bin 0 -> 686 bytes ...ignContent-column-flexstart-blue-16x16@2x.png | Bin 0 -> 672 bytes ...ontent-column-flexstart-darkgray-16x16@2x.png | Bin 0 -> 669 bytes ...ignContent-column-flexstart-gray-16x16@2x.png | Bin 0 -> 655 bytes ...gnContent-column-flexstart-green-16x16@2x.png | Bin 0 -> 687 bytes ...ntent-column-flexstart-lightaqua-16x16@2x.png | Bin 0 -> 667 bytes ...ntent-column-flexstart-lightblue-16x16@2x.png | Bin 0 -> 662 bytes ...ntent-column-flexstart-lightgray-16x16@2x.png | Bin 0 -> 672 bytes ...tent-column-flexstart-lightgreen-16x16@2x.png | Bin 0 -> 673 bytes ...ent-column-flexstart-lightpurple-16x16@2x.png | Bin 0 -> 673 bytes ...nContent-column-flexstart-purple-16x16@2x.png | Bin 0 -> 667 bytes ...lignContent-column-flexstart-red-16x16@2x.png | Bin 0 -> 656 bytes ...gnContent-column-flexstart-white-16x16@2x.png | Bin 0 -> 588 bytes ...nContent-column-spaceAround-aqua-16x16@2x.png | Bin 0 -> 681 bytes ...Content-column-spaceAround-black-16x16@2x.png | Bin 0 -> 659 bytes ...nContent-column-spaceAround-blue-16x16@2x.png | Bin 0 -> 641 bytes ...tent-column-spaceAround-darkgray-16x16@2x.png | Bin 0 -> 669 bytes ...nContent-column-spaceAround-gray-16x16@2x.png | Bin 0 -> 655 bytes ...Content-column-spaceAround-green-16x16@2x.png | Bin 0 -> 678 bytes ...ent-column-spaceAround-lightaqua-16x16@2x.png | Bin 0 -> 649 bytes ...ent-column-spaceAround-lightblue-16x16@2x.png | Bin 0 -> 656 bytes ...ent-column-spaceAround-lightgray-16x16@2x.png | Bin 0 -> 645 bytes ...nt-column-spaceAround-lightgreen-16x16@2x.png | Bin 0 -> 660 bytes ...t-column-spaceAround-lightpurple-16x16@2x.png | Bin 0 -> 649 bytes ...ontent-column-spaceAround-purple-16x16@2x.png | Bin 0 -> 645 bytes ...gnContent-column-spaceAround-red-16x16@2x.png | Bin 0 -> 636 bytes ...Content-column-spaceAround-white-16x16@2x.png | Bin 0 -> 588 bytes ...Content-column-spaceBetween-aqua-16x16@2x.png | Bin 0 -> 675 bytes ...ontent-column-spaceBetween-black-16x16@2x.png | Bin 0 -> 672 bytes ...Content-column-spaceBetween-blue-16x16@2x.png | Bin 0 -> 670 bytes ...ent-column-spaceBetween-darkgray-16x16@2x.png | Bin 0 -> 672 bytes ...Content-column-spaceBetween-gray-16x16@2x.png | Bin 0 -> 653 bytes ...ontent-column-spaceBetween-green-16x16@2x.png | Bin 0 -> 687 bytes ...nt-column-spaceBetween-lightaqua-16x16@2x.png | Bin 0 -> 670 bytes ...nt-column-spaceBetween-lightblue-16x16@2x.png | Bin 0 -> 662 bytes ...nt-column-spaceBetween-lightgray-16x16@2x.png | Bin 0 -> 669 bytes ...t-column-spaceBetween-lightgreen-16x16@2x.png | Bin 0 -> 670 bytes ...-column-spaceBetween-lightpurple-16x16@2x.png | Bin 0 -> 672 bytes ...ntent-column-spaceBetween-purple-16x16@2x.png | Bin 0 -> 665 bytes ...nContent-column-spaceBetween-red-16x16@2x.png | Bin 0 -> 656 bytes ...ontent-column-spaceBetween-white-16x16@2x.png | Bin 0 -> 596 bytes ...alignContent-column-stretch-aqua-16x16@2x.png | Bin 0 -> 705 bytes ...lignContent-column-stretch-black-16x16@2x.png | Bin 0 -> 699 bytes ...alignContent-column-stretch-blue-16x16@2x.png | Bin 0 -> 697 bytes ...nContent-column-stretch-darkgray-16x16@2x.png | Bin 0 -> 705 bytes ...alignContent-column-stretch-gray-16x16@2x.png | Bin 0 -> 681 bytes ...lignContent-column-stretch-green-16x16@2x.png | Bin 0 -> 715 bytes ...Content-column-stretch-lightaqua-16x16@2x.png | Bin 0 -> 696 bytes ...Content-column-stretch-lightblue-16x16@2x.png | Bin 0 -> 699 bytes ...Content-column-stretch-lightgray-16x16@2x.png | Bin 0 -> 694 bytes ...ontent-column-stretch-lightgreen-16x16@2x.png | Bin 0 -> 711 bytes ...ntent-column-stretch-lightpurple-16x16@2x.png | Bin 0 -> 706 bytes ...ignContent-column-stretch-purple-16x16@2x.png | Bin 0 -> 697 bytes .../alignContent-column-stretch-red-16x16@2x.png | Bin 0 -> 683 bytes ...lignContent-column-stretch-white-16x16@2x.png | Bin 0 -> 614 bytes .../alignContent-row-center-aqua-16x16@2x.png | Bin 0 -> 680 bytes .../alignContent-row-center-black-16x16@2x.png | Bin 0 -> 657 bytes .../alignContent-row-center-blue-16x16@2x.png | Bin 0 -> 637 bytes ...alignContent-row-center-darkgray-16x16@2x.png | Bin 0 -> 671 bytes .../alignContent-row-center-gray-16x16@2x.png | Bin 0 -> 657 bytes .../alignContent-row-center-green-16x16@2x.png | Bin 0 -> 677 bytes ...lignContent-row-center-lightaqua-16x16@2x.png | Bin 0 -> 646 bytes ...lignContent-row-center-lightblue-16x16@2x.png | Bin 0 -> 656 bytes ...lignContent-row-center-lightgray-16x16@2x.png | Bin 0 -> 644 bytes ...ignContent-row-center-lightgreen-16x16@2x.png | Bin 0 -> 661 bytes ...gnContent-row-center-lightpurple-16x16@2x.png | Bin 0 -> 647 bytes .../alignContent-row-center-purple-16x16@2x.png | Bin 0 -> 644 bytes .../alignContent-row-center-red-16x16@2x.png | Bin 0 -> 635 bytes .../alignContent-row-center-white-16x16@2x.png | Bin 0 -> 585 bytes .../alignContent-row-flexend-aqua-16x16@2x.png | Bin 0 -> 678 bytes .../alignContent-row-flexend-black-16x16@2x.png | Bin 0 -> 655 bytes .../alignContent-row-flexend-blue-16x16@2x.png | Bin 0 -> 635 bytes ...lignContent-row-flexend-darkgray-16x16@2x.png | Bin 0 -> 669 bytes .../alignContent-row-flexend-gray-16x16@2x.png | Bin 0 -> 655 bytes .../alignContent-row-flexend-green-16x16@2x.png | Bin 0 -> 676 bytes ...ignContent-row-flexend-lightaqua-16x16@2x.png | Bin 0 -> 644 bytes ...ignContent-row-flexend-lightblue-16x16@2x.png | Bin 0 -> 653 bytes ...ignContent-row-flexend-lightgray-16x16@2x.png | Bin 0 -> 642 bytes ...gnContent-row-flexend-lightgreen-16x16@2x.png | Bin 0 -> 658 bytes ...nContent-row-flexend-lightpurple-16x16@2x.png | Bin 0 -> 645 bytes .../alignContent-row-flexend-purple-16x16@2x.png | Bin 0 -> 642 bytes .../alignContent-row-flexend-red-16x16@2x.png | Bin 0 -> 633 bytes .../alignContent-row-flexend-white-16x16@2x.png | Bin 0 -> 577 bytes .../alignContent-row-flexstart-aqua-16x16@2x.png | Bin 0 -> 685 bytes ...alignContent-row-flexstart-black-16x16@2x.png | Bin 0 -> 662 bytes .../alignContent-row-flexstart-blue-16x16@2x.png | Bin 0 -> 642 bytes ...gnContent-row-flexstart-darkgray-16x16@2x.png | Bin 0 -> 674 bytes .../alignContent-row-flexstart-gray-16x16@2x.png | Bin 0 -> 661 bytes ...alignContent-row-flexstart-green-16x16@2x.png | Bin 0 -> 684 bytes ...nContent-row-flexstart-lightaqua-16x16@2x.png | Bin 0 -> 648 bytes ...nContent-row-flexstart-lightblue-16x16@2x.png | Bin 0 -> 661 bytes ...nContent-row-flexstart-lightgray-16x16@2x.png | Bin 0 -> 646 bytes ...Content-row-flexstart-lightgreen-16x16@2x.png | Bin 0 -> 664 bytes ...ontent-row-flexstart-lightpurple-16x16@2x.png | Bin 0 -> 655 bytes ...lignContent-row-flexstart-purple-16x16@2x.png | Bin 0 -> 648 bytes .../alignContent-row-flexstart-red-16x16@2x.png | Bin 0 -> 636 bytes ...alignContent-row-flexstart-white-16x16@2x.png | Bin 0 -> 580 bytes ...lignContent-row-spaceAround-aqua-16x16@2x.png | Bin 0 -> 681 bytes ...ignContent-row-spaceAround-black-16x16@2x.png | Bin 0 -> 659 bytes ...lignContent-row-spaceAround-blue-16x16@2x.png | Bin 0 -> 641 bytes ...Content-row-spaceAround-darkgray-16x16@2x.png | Bin 0 -> 669 bytes ...lignContent-row-spaceAround-gray-16x16@2x.png | Bin 0 -> 655 bytes ...ignContent-row-spaceAround-green-16x16@2x.png | Bin 0 -> 678 bytes ...ontent-row-spaceAround-lightaqua-16x16@2x.png | Bin 0 -> 649 bytes ...ontent-row-spaceAround-lightblue-16x16@2x.png | Bin 0 -> 656 bytes ...ontent-row-spaceAround-lightgray-16x16@2x.png | Bin 0 -> 645 bytes ...ntent-row-spaceAround-lightgreen-16x16@2x.png | Bin 0 -> 660 bytes ...tent-row-spaceAround-lightpurple-16x16@2x.png | Bin 0 -> 649 bytes ...gnContent-row-spaceAround-purple-16x16@2x.png | Bin 0 -> 645 bytes ...alignContent-row-spaceAround-red-16x16@2x.png | Bin 0 -> 636 bytes ...ignContent-row-spaceAround-white-16x16@2x.png | Bin 0 -> 588 bytes ...ignContent-row-spaceBetween-aqua-16x16@2x.png | Bin 0 -> 687 bytes ...gnContent-row-spaceBetween-black-16x16@2x.png | Bin 0 -> 659 bytes ...ignContent-row-spaceBetween-blue-16x16@2x.png | Bin 0 -> 641 bytes ...ontent-row-spaceBetween-darkgray-16x16@2x.png | Bin 0 -> 677 bytes ...ignContent-row-spaceBetween-gray-16x16@2x.png | Bin 0 -> 665 bytes ...gnContent-row-spaceBetween-green-16x16@2x.png | Bin 0 -> 685 bytes ...ntent-row-spaceBetween-lightaqua-16x16@2x.png | Bin 0 -> 647 bytes ...ntent-row-spaceBetween-lightblue-16x16@2x.png | Bin 0 -> 665 bytes ...ntent-row-spaceBetween-lightgray-16x16@2x.png | Bin 0 -> 646 bytes ...tent-row-spaceBetween-lightgreen-16x16@2x.png | Bin 0 -> 665 bytes ...ent-row-spaceBetween-lightpurple-16x16@2x.png | Bin 0 -> 653 bytes ...nContent-row-spaceBetween-purple-16x16@2x.png | Bin 0 -> 644 bytes ...lignContent-row-spaceBetween-red-16x16@2x.png | Bin 0 -> 635 bytes ...gnContent-row-spaceBetween-white-16x16@2x.png | Bin 0 -> 580 bytes .../alignContent-row-stretch-aqua-16x16@2x.png | Bin 0 -> 683 bytes .../alignContent-row-stretch-black-16x16@2x.png | Bin 0 -> 681 bytes .../alignContent-row-stretch-blue-16x16@2x.png | Bin 0 -> 668 bytes ...lignContent-row-stretch-darkgray-16x16@2x.png | Bin 0 -> 679 bytes .../alignContent-row-stretch-gray-16x16@2x.png | Bin 0 -> 659 bytes .../alignContent-row-stretch-green-16x16@2x.png | Bin 0 -> 684 bytes ...ignContent-row-stretch-lightaqua-16x16@2x.png | Bin 0 -> 679 bytes ...ignContent-row-stretch-lightblue-16x16@2x.png | Bin 0 -> 670 bytes ...ignContent-row-stretch-lightgray-16x16@2x.png | Bin 0 -> 665 bytes ...gnContent-row-stretch-lightgreen-16x16@2x.png | Bin 0 -> 678 bytes ...nContent-row-stretch-lightpurple-16x16@2x.png | Bin 0 -> 679 bytes .../alignContent-row-stretch-purple-16x16@2x.png | Bin 0 -> 668 bytes .../alignContent-row-stretch-red-16x16@2x.png | Bin 0 -> 655 bytes .../alignContent-row-stretch-white-16x16@2x.png | Bin 0 -> 594 bytes .../alignItems-column-baseline-aqua-16x16@2x.png | Bin 0 -> 897 bytes ...alignItems-column-baseline-black-16x16@2x.png | Bin 0 -> 890 bytes .../alignItems-column-baseline-blue-16x16@2x.png | Bin 0 -> 900 bytes ...gnItems-column-baseline-darkgray-16x16@2x.png | Bin 0 -> 884 bytes .../alignItems-column-baseline-gray-16x16@2x.png | Bin 0 -> 806 bytes ...alignItems-column-baseline-green-16x16@2x.png | Bin 0 -> 940 bytes ...nItems-column-baseline-lightaqua-16x16@2x.png | Bin 0 -> 890 bytes ...nItems-column-baseline-lightblue-16x16@2x.png | Bin 0 -> 869 bytes ...nItems-column-baseline-lightgray-16x16@2x.png | Bin 0 -> 890 bytes ...Items-column-baseline-lightgreen-16x16@2x.png | Bin 0 -> 908 bytes ...tems-column-baseline-lightpurple-16x16@2x.png | Bin 0 -> 897 bytes ...lignItems-column-baseline-purple-16x16@2x.png | Bin 0 -> 924 bytes .../alignItems-column-baseline-red-16x16@2x.png | Bin 0 -> 854 bytes ...alignItems-column-baseline-white-16x16@2x.png | Bin 0 -> 744 bytes .../alignItems-column-center-aqua-16x16@2x.png | Bin 0 -> 735 bytes .../alignItems-column-center-black-16x16@2x.png | Bin 0 -> 718 bytes .../alignItems-column-center-blue-16x16@2x.png | Bin 0 -> 705 bytes ...lignItems-column-center-darkgray-16x16@2x.png | Bin 0 -> 724 bytes .../alignItems-column-center-gray-16x16@2x.png | Bin 0 -> 713 bytes .../alignItems-column-center-green-16x16@2x.png | Bin 0 -> 721 bytes ...ignItems-column-center-lightaqua-16x16@2x.png | Bin 0 -> 678 bytes ...ignItems-column-center-lightblue-16x16@2x.png | Bin 0 -> 658 bytes ...ignItems-column-center-lightgray-16x16@2x.png | Bin 0 -> 706 bytes ...gnItems-column-center-lightgreen-16x16@2x.png | Bin 0 -> 667 bytes ...nItems-column-center-lightpurple-16x16@2x.png | Bin 0 -> 666 bytes .../alignItems-column-center-purple-16x16@2x.png | Bin 0 -> 710 bytes .../alignItems-column-center-red-16x16@2x.png | Bin 0 -> 707 bytes .../alignItems-column-center-white-16x16@2x.png | Bin 0 -> 628 bytes .../alignItems-column-flexEnd-aqua-16x16@2x.png | Bin 0 -> 717 bytes .../alignItems-column-flexEnd-black-16x16@2x.png | Bin 0 -> 688 bytes .../alignItems-column-flexEnd-blue-16x16@2x.png | Bin 0 -> 699 bytes ...ignItems-column-flexEnd-darkgray-16x16@2x.png | Bin 0 -> 696 bytes .../alignItems-column-flexEnd-gray-16x16@2x.png | Bin 0 -> 693 bytes .../alignItems-column-flexEnd-green-16x16@2x.png | Bin 0 -> 711 bytes ...gnItems-column-flexEnd-lightaqua-16x16@2x.png | Bin 0 -> 669 bytes ...gnItems-column-flexEnd-lightblue-16x16@2x.png | Bin 0 -> 656 bytes ...gnItems-column-flexEnd-lightgray-16x16@2x.png | Bin 0 -> 697 bytes ...nItems-column-flexEnd-lightgreen-16x16@2x.png | Bin 0 -> 664 bytes ...Items-column-flexEnd-lightpurple-16x16@2x.png | Bin 0 -> 663 bytes ...alignItems-column-flexEnd-purple-16x16@2x.png | Bin 0 -> 700 bytes .../alignItems-column-flexEnd-red-16x16@2x.png | Bin 0 -> 693 bytes .../alignItems-column-flexEnd-white-16x16@2x.png | Bin 0 -> 617 bytes ...alignItems-column-flexStart-aqua-16x16@2x.png | Bin 0 -> 706 bytes ...lignItems-column-flexStart-black-16x16@2x.png | Bin 0 -> 688 bytes ...alignItems-column-flexStart-blue-16x16@2x.png | Bin 0 -> 697 bytes ...nItems-column-flexStart-darkgray-16x16@2x.png | Bin 0 -> 686 bytes ...alignItems-column-flexStart-gray-16x16@2x.png | Bin 0 -> 679 bytes ...lignItems-column-flexStart-green-16x16@2x.png | Bin 0 -> 705 bytes ...Items-column-flexStart-lightaqua-16x16@2x.png | Bin 0 -> 665 bytes ...Items-column-flexStart-lightblue-16x16@2x.png | Bin 0 -> 656 bytes ...Items-column-flexStart-lightgray-16x16@2x.png | Bin 0 -> 695 bytes ...tems-column-flexStart-lightgreen-16x16@2x.png | Bin 0 -> 660 bytes ...ems-column-flexStart-lightpurple-16x16@2x.png | Bin 0 -> 661 bytes ...ignItems-column-flexStart-purple-16x16@2x.png | Bin 0 -> 695 bytes .../alignItems-column-flexStart-red-16x16@2x.png | Bin 0 -> 684 bytes ...lignItems-column-flexStart-white-16x16@2x.png | Bin 0 -> 630 bytes .../alignItems-column-stretch-aqua-16x16@2x.png | Bin 0 -> 672 bytes .../alignItems-column-stretch-black-16x16@2x.png | Bin 0 -> 649 bytes .../alignItems-column-stretch-blue-16x16@2x.png | Bin 0 -> 664 bytes ...ignItems-column-stretch-darkgray-16x16@2x.png | Bin 0 -> 650 bytes .../alignItems-column-stretch-gray-16x16@2x.png | Bin 0 -> 647 bytes .../alignItems-column-stretch-green-16x16@2x.png | Bin 0 -> 675 bytes ...gnItems-column-stretch-lightaqua-16x16@2x.png | Bin 0 -> 631 bytes ...gnItems-column-stretch-lightblue-16x16@2x.png | Bin 0 -> 621 bytes ...gnItems-column-stretch-lightgray-16x16@2x.png | Bin 0 -> 661 bytes ...nItems-column-stretch-lightgreen-16x16@2x.png | Bin 0 -> 628 bytes ...Items-column-stretch-lightpurple-16x16@2x.png | Bin 0 -> 627 bytes ...alignItems-column-stretch-purple-16x16@2x.png | Bin 0 -> 663 bytes .../alignItems-column-stretch-red-16x16@2x.png | Bin 0 -> 654 bytes .../alignItems-column-stretch-white-16x16@2x.png | Bin 0 -> 604 bytes .../alignItems-row-baseline-aqua-16x16@2x.png | Bin 0 -> 897 bytes .../alignItems-row-baseline-black-16x16@2x.png | Bin 0 -> 890 bytes .../alignItems-row-baseline-blue-16x16@2x.png | Bin 0 -> 900 bytes ...alignItems-row-baseline-darkgray-16x16@2x.png | Bin 0 -> 884 bytes .../alignItems-row-baseline-gray-16x16@2x.png | Bin 0 -> 806 bytes .../alignItems-row-baseline-green-16x16@2x.png | Bin 0 -> 940 bytes ...lignItems-row-baseline-lightaqua-16x16@2x.png | Bin 0 -> 890 bytes ...lignItems-row-baseline-lightblue-16x16@2x.png | Bin 0 -> 869 bytes ...lignItems-row-baseline-lightgray-16x16@2x.png | Bin 0 -> 890 bytes ...ignItems-row-baseline-lightgreen-16x16@2x.png | Bin 0 -> 908 bytes ...gnItems-row-baseline-lightpurple-16x16@2x.png | Bin 0 -> 897 bytes .../alignItems-row-baseline-purple-16x16@2x.png | Bin 0 -> 924 bytes .../alignItems-row-baseline-red-16x16@2x.png | Bin 0 -> 854 bytes .../alignItems-row-baseline-white-16x16@2x.png | Bin 0 -> 744 bytes .../alignItems-row-center-aqua-16x16@2x.png | Bin 0 -> 778 bytes .../alignItems-row-center-black-16x16@2x.png | Bin 0 -> 768 bytes .../alignItems-row-center-blue-16x16@2x.png | Bin 0 -> 758 bytes .../alignItems-row-center-darkgray-16x16@2x.png | Bin 0 -> 758 bytes .../alignItems-row-center-gray-16x16@2x.png | Bin 0 -> 738 bytes .../alignItems-row-center-green-16x16@2x.png | Bin 0 -> 785 bytes .../alignItems-row-center-lightaqua-16x16@2x.png | Bin 0 -> 682 bytes .../alignItems-row-center-lightblue-16x16@2x.png | Bin 0 -> 670 bytes .../alignItems-row-center-lightgray-16x16@2x.png | Bin 0 -> 726 bytes ...alignItems-row-center-lightgreen-16x16@2x.png | Bin 0 -> 679 bytes ...lignItems-row-center-lightpurple-16x16@2x.png | Bin 0 -> 676 bytes .../alignItems-row-center-purple-16x16@2x.png | Bin 0 -> 727 bytes .../alignItems-row-center-red-16x16@2x.png | Bin 0 -> 726 bytes .../alignItems-row-center-white-16x16@2x.png | Bin 0 -> 603 bytes .../alignItems-row-flexEnd-aqua-16x16@2x.png | Bin 0 -> 726 bytes .../alignItems-row-flexEnd-black-16x16@2x.png | Bin 0 -> 727 bytes .../alignItems-row-flexEnd-blue-16x16@2x.png | Bin 0 -> 705 bytes .../alignItems-row-flexEnd-darkgray-16x16@2x.png | Bin 0 -> 709 bytes .../alignItems-row-flexEnd-gray-16x16@2x.png | Bin 0 -> 702 bytes .../alignItems-row-flexEnd-green-16x16@2x.png | Bin 0 -> 714 bytes ...alignItems-row-flexEnd-lightaqua-16x16@2x.png | Bin 0 -> 663 bytes ...alignItems-row-flexEnd-lightblue-16x16@2x.png | Bin 0 -> 651 bytes ...alignItems-row-flexEnd-lightgray-16x16@2x.png | Bin 0 -> 695 bytes ...lignItems-row-flexEnd-lightgreen-16x16@2x.png | Bin 0 -> 657 bytes ...ignItems-row-flexEnd-lightpurple-16x16@2x.png | Bin 0 -> 657 bytes .../alignItems-row-flexEnd-purple-16x16@2x.png | Bin 0 -> 692 bytes .../alignItems-row-flexEnd-red-16x16@2x.png | Bin 0 -> 679 bytes .../alignItems-row-flexEnd-white-16x16@2x.png | Bin 0 -> 595 bytes .../alignItems-row-flexStart-aqua-16x16@2x.png | Bin 0 -> 726 bytes .../alignItems-row-flexStart-black-16x16@2x.png | Bin 0 -> 713 bytes .../alignItems-row-flexStart-blue-16x16@2x.png | Bin 0 -> 695 bytes ...lignItems-row-flexStart-darkgray-16x16@2x.png | Bin 0 -> 710 bytes .../alignItems-row-flexStart-gray-16x16@2x.png | Bin 0 -> 701 bytes .../alignItems-row-flexStart-green-16x16@2x.png | Bin 0 -> 729 bytes ...ignItems-row-flexStart-lightaqua-16x16@2x.png | Bin 0 -> 649 bytes ...ignItems-row-flexStart-lightblue-16x16@2x.png | Bin 0 -> 639 bytes ...ignItems-row-flexStart-lightgray-16x16@2x.png | Bin 0 -> 679 bytes ...gnItems-row-flexStart-lightgreen-16x16@2x.png | Bin 0 -> 642 bytes ...nItems-row-flexStart-lightpurple-16x16@2x.png | Bin 0 -> 645 bytes .../alignItems-row-flexStart-purple-16x16@2x.png | Bin 0 -> 681 bytes .../alignItems-row-flexStart-red-16x16@2x.png | Bin 0 -> 676 bytes .../alignItems-row-flexStart-white-16x16@2x.png | Bin 0 -> 588 bytes .../alignItems-row-stretch-aqua-16x16@2x.png | Bin 0 -> 693 bytes .../alignItems-row-stretch-black-16x16@2x.png | Bin 0 -> 674 bytes .../alignItems-row-stretch-blue-16x16@2x.png | Bin 0 -> 666 bytes .../alignItems-row-stretch-darkgray-16x16@2x.png | Bin 0 -> 680 bytes .../alignItems-row-stretch-gray-16x16@2x.png | Bin 0 -> 671 bytes .../alignItems-row-stretch-green-16x16@2x.png | Bin 0 -> 680 bytes ...alignItems-row-stretch-lightaqua-16x16@2x.png | Bin 0 -> 635 bytes ...alignItems-row-stretch-lightblue-16x16@2x.png | Bin 0 -> 623 bytes ...alignItems-row-stretch-lightgray-16x16@2x.png | Bin 0 -> 664 bytes ...lignItems-row-stretch-lightgreen-16x16@2x.png | Bin 0 -> 626 bytes ...ignItems-row-stretch-lightpurple-16x16@2x.png | Bin 0 -> 630 bytes .../alignItems-row-stretch-purple-16x16@2x.png | Bin 0 -> 663 bytes .../alignItems-row-stretch-red-16x16@2x.png | Bin 0 -> 652 bytes .../alignItems-row-stretch-white-16x16@2x.png | Bin 0 -> 581 bytes .../arrowDown-aqua-16x16@2x.png | Bin 0 -> 633 bytes .../arrowDown-black-16x16@2x.png | Bin 0 -> 630 bytes .../arrowDown-blue-16x16@2x.png | Bin 0 -> 622 bytes .../arrowDown-darkgray-16x16@2x.png | Bin 0 -> 634 bytes .../arrowDown-gray-16x16@2x.png | Bin 0 -> 613 bytes .../arrowDown-green-16x16@2x.png | Bin 0 -> 627 bytes .../arrowDown-lightaqua-16x16@2x.png | Bin 0 -> 610 bytes .../arrowDown-lightblue-16x16@2x.png | Bin 0 -> 625 bytes .../arrowDown-lightgray-16x16@2x.png | Bin 0 -> 623 bytes .../arrowDown-lightgreen-16x16@2x.png | Bin 0 -> 628 bytes .../arrowDown-lightpurple-16x16@2x.png | Bin 0 -> 627 bytes .../arrowDown-purple-16x16@2x.png | Bin 0 -> 627 bytes .../inspector-element/arrowDown-red-16x16@2x.png | Bin 0 -> 616 bytes .../arrowDown-white-16x16@2x.png | Bin 0 -> 568 bytes .../arrowLeft-aqua-16x16@2x.png | Bin 0 -> 601 bytes .../arrowLeft-black-16x16@2x.png | Bin 0 -> 602 bytes .../arrowLeft-blue-16x16@2x.png | Bin 0 -> 605 bytes .../arrowLeft-darkgray-16x16@2x.png | Bin 0 -> 602 bytes .../arrowLeft-gray-16x16@2x.png | Bin 0 -> 578 bytes .../arrowLeft-green-16x16@2x.png | Bin 0 -> 613 bytes .../arrowLeft-lightaqua-16x16@2x.png | Bin 0 -> 601 bytes .../arrowLeft-lightblue-16x16@2x.png | Bin 0 -> 601 bytes .../arrowLeft-lightgray-16x16@2x.png | Bin 0 -> 604 bytes .../arrowLeft-lightgreen-16x16@2x.png | Bin 0 -> 607 bytes .../arrowLeft-lightpurple-16x16@2x.png | Bin 0 -> 603 bytes .../arrowLeft-purple-16x16@2x.png | Bin 0 -> 607 bytes .../inspector-element/arrowLeft-red-16x16@2x.png | Bin 0 -> 591 bytes .../arrowLeft-white-16x16@2x.png | Bin 0 -> 543 bytes .../arrowRight-aqua-16x16@2x.png | Bin 0 -> 605 bytes .../arrowRight-black-16x16@2x.png | Bin 0 -> 609 bytes .../arrowRight-blue-16x16@2x.png | Bin 0 -> 605 bytes .../arrowRight-darkgray-16x16@2x.png | Bin 0 -> 606 bytes .../arrowRight-gray-16x16@2x.png | Bin 0 -> 580 bytes .../arrowRight-green-16x16@2x.png | Bin 0 -> 616 bytes .../arrowRight-lightaqua-16x16@2x.png | Bin 0 -> 610 bytes .../arrowRight-lightblue-16x16@2x.png | Bin 0 -> 600 bytes .../arrowRight-lightgray-16x16@2x.png | Bin 0 -> 602 bytes .../arrowRight-lightgreen-16x16@2x.png | Bin 0 -> 605 bytes .../arrowRight-lightpurple-16x16@2x.png | Bin 0 -> 606 bytes .../arrowRight-purple-16x16@2x.png | Bin 0 -> 609 bytes .../arrowRight-red-16x16@2x.png | Bin 0 -> 590 bytes .../arrowRight-white-16x16@2x.png | Bin 0 -> 544 bytes .../inspector-element/arrowUp-aqua-16x16@2x.png | Bin 0 -> 608 bytes .../inspector-element/arrowUp-black-16x16@2x.png | Bin 0 -> 606 bytes .../inspector-element/arrowUp-blue-16x16@2x.png | Bin 0 -> 600 bytes .../arrowUp-darkgray-16x16@2x.png | Bin 0 -> 616 bytes .../inspector-element/arrowUp-gray-16x16@2x.png | Bin 0 -> 598 bytes .../inspector-element/arrowUp-green-16x16@2x.png | Bin 0 -> 609 bytes .../arrowUp-lightaqua-16x16@2x.png | Bin 0 -> 601 bytes .../arrowUp-lightblue-16x16@2x.png | Bin 0 -> 599 bytes .../arrowUp-lightgray-16x16@2x.png | Bin 0 -> 598 bytes .../arrowUp-lightgreen-16x16@2x.png | Bin 0 -> 603 bytes .../arrowUp-lightpurple-16x16@2x.png | Bin 0 -> 603 bytes .../arrowUp-purple-16x16@2x.png | Bin 0 -> 611 bytes .../inspector-element/arrowUp-red-16x16@2x.png | Bin 0 -> 593 bytes .../inspector-element/arrowUp-white-16x16@2x.png | Bin 0 -> 564 bytes .../inspector-element/bold-aqua-16x16@2x.png | Bin 0 -> 770 bytes .../inspector-element/bold-black-16x16@2x.png | Bin 0 -> 789 bytes .../inspector-element/bold-blue-16x16@2x.png | Bin 0 -> 778 bytes .../inspector-element/bold-darkgray-16x16@2x.png | Bin 0 -> 772 bytes .../inspector-element/bold-gray-16x16@2x.png | Bin 0 -> 714 bytes .../inspector-element/bold-green-16x16@2x.png | Bin 0 -> 812 bytes .../bold-lightaqua-16x16@2x.png | Bin 0 -> 768 bytes .../bold-lightblue-16x16@2x.png | Bin 0 -> 758 bytes .../bold-lightgray-16x16@2x.png | Bin 0 -> 779 bytes .../bold-lightgreen-16x16@2x.png | Bin 0 -> 787 bytes .../bold-lightpurple-16x16@2x.png | Bin 0 -> 771 bytes .../inspector-element/bold-purple-16x16@2x.png | Bin 0 -> 785 bytes .../inspector-element/bold-red-16x16@2x.png | Bin 0 -> 733 bytes .../inspector-element/bold-white-16x16@2x.png | Bin 0 -> 671 bytes .../borderRadius-aqua-16x16@2x.png | Bin 0 -> 769 bytes .../borderRadius-black-16x16@2x.png | Bin 0 -> 811 bytes .../borderRadius-blue-16x16@2x.png | Bin 0 -> 759 bytes .../borderRadius-bottomLeft-aqua-16x16@2x.png | Bin 0 -> 662 bytes .../borderRadius-bottomLeft-black-16x16@2x.png | Bin 0 -> 666 bytes .../borderRadius-bottomLeft-blue-16x16@2x.png | Bin 0 -> 667 bytes ...borderRadius-bottomLeft-darkgray-16x16@2x.png | Bin 0 -> 669 bytes .../borderRadius-bottomLeft-gray-16x16@2x.png | Bin 0 -> 627 bytes .../borderRadius-bottomLeft-green-16x16@2x.png | Bin 0 -> 681 bytes ...orderRadius-bottomLeft-lightaqua-16x16@2x.png | Bin 0 -> 652 bytes ...orderRadius-bottomLeft-lightblue-16x16@2x.png | Bin 0 -> 658 bytes ...orderRadius-bottomLeft-lightgray-16x16@2x.png | Bin 0 -> 665 bytes ...rderRadius-bottomLeft-lightgreen-16x16@2x.png | Bin 0 -> 670 bytes ...derRadius-bottomLeft-lightpurple-16x16@2x.png | Bin 0 -> 665 bytes .../borderRadius-bottomLeft-purple-16x16@2x.png | Bin 0 -> 669 bytes .../borderRadius-bottomLeft-red-16x16@2x.png | Bin 0 -> 650 bytes .../borderRadius-bottomLeft-white-16x16@2x.png | Bin 0 -> 590 bytes .../borderRadius-bottomRight-aqua-16x16@2x.png | Bin 0 -> 660 bytes .../borderRadius-bottomRight-black-16x16@2x.png | Bin 0 -> 661 bytes .../borderRadius-bottomRight-blue-16x16@2x.png | Bin 0 -> 660 bytes ...orderRadius-bottomRight-darkgray-16x16@2x.png | Bin 0 -> 666 bytes .../borderRadius-bottomRight-gray-16x16@2x.png | Bin 0 -> 624 bytes .../borderRadius-bottomRight-green-16x16@2x.png | Bin 0 -> 673 bytes ...rderRadius-bottomRight-lightaqua-16x16@2x.png | Bin 0 -> 659 bytes ...rderRadius-bottomRight-lightblue-16x16@2x.png | Bin 0 -> 649 bytes ...rderRadius-bottomRight-lightgray-16x16@2x.png | Bin 0 -> 657 bytes ...derRadius-bottomRight-lightgreen-16x16@2x.png | Bin 0 -> 663 bytes ...erRadius-bottomRight-lightpurple-16x16@2x.png | Bin 0 -> 657 bytes .../borderRadius-bottomRight-purple-16x16@2x.png | Bin 0 -> 665 bytes .../borderRadius-bottomRight-red-16x16@2x.png | Bin 0 -> 645 bytes .../borderRadius-bottomRight-white-16x16@2x.png | Bin 0 -> 596 bytes .../borderRadius-darkgray-16x16@2x.png | Bin 0 -> 750 bytes .../borderRadius-gray-16x16@2x.png | Bin 0 -> 707 bytes .../borderRadius-green-16x16@2x.png | Bin 0 -> 799 bytes .../borderRadius-lightaqua-16x16@2x.png | Bin 0 -> 760 bytes .../borderRadius-lightblue-16x16@2x.png | Bin 0 -> 756 bytes .../borderRadius-lightgray-16x16@2x.png | Bin 0 -> 759 bytes .../borderRadius-lightgreen-16x16@2x.png | Bin 0 -> 768 bytes .../borderRadius-lightpurple-16x16@2x.png | Bin 0 -> 771 bytes .../borderRadius-purple-16x16@2x.png | Bin 0 -> 774 bytes .../borderRadius-red-16x16@2x.png | Bin 0 -> 742 bytes .../borderRadius-topLeft-aqua-16x16@2x.png | Bin 0 -> 668 bytes .../borderRadius-topLeft-black-16x16@2x.png | Bin 0 -> 670 bytes .../borderRadius-topLeft-blue-16x16@2x.png | Bin 0 -> 674 bytes .../borderRadius-topLeft-darkgray-16x16@2x.png | Bin 0 -> 673 bytes .../borderRadius-topLeft-gray-16x16@2x.png | Bin 0 -> 634 bytes .../borderRadius-topLeft-green-16x16@2x.png | Bin 0 -> 682 bytes .../borderRadius-topLeft-lightaqua-16x16@2x.png | Bin 0 -> 663 bytes .../borderRadius-topLeft-lightblue-16x16@2x.png | Bin 0 -> 658 bytes .../borderRadius-topLeft-lightgray-16x16@2x.png | Bin 0 -> 677 bytes .../borderRadius-topLeft-lightgreen-16x16@2x.png | Bin 0 -> 664 bytes ...borderRadius-topLeft-lightpurple-16x16@2x.png | Bin 0 -> 663 bytes .../borderRadius-topLeft-purple-16x16@2x.png | Bin 0 -> 676 bytes .../borderRadius-topLeft-red-16x16@2x.png | Bin 0 -> 654 bytes .../borderRadius-topLeft-white-16x16@2x.png | Bin 0 -> 600 bytes .../borderRadius-topRight-aqua-16x16@2x.png | Bin 0 -> 688 bytes .../borderRadius-topRight-black-16x16@2x.png | Bin 0 -> 687 bytes .../borderRadius-topRight-blue-16x16@2x.png | Bin 0 -> 689 bytes .../borderRadius-topRight-darkgray-16x16@2x.png | Bin 0 -> 685 bytes .../borderRadius-topRight-gray-16x16@2x.png | Bin 0 -> 645 bytes .../borderRadius-topRight-green-16x16@2x.png | Bin 0 -> 702 bytes .../borderRadius-topRight-lightaqua-16x16@2x.png | Bin 0 -> 674 bytes .../borderRadius-topRight-lightblue-16x16@2x.png | Bin 0 -> 676 bytes .../borderRadius-topRight-lightgray-16x16@2x.png | Bin 0 -> 684 bytes ...borderRadius-topRight-lightgreen-16x16@2x.png | Bin 0 -> 684 bytes ...orderRadius-topRight-lightpurple-16x16@2x.png | Bin 0 -> 683 bytes .../borderRadius-topRight-purple-16x16@2x.png | Bin 0 -> 697 bytes .../borderRadius-topRight-red-16x16@2x.png | Bin 0 -> 659 bytes .../borderRadius-topRight-white-16x16@2x.png | Bin 0 -> 596 bytes .../borderRadius-white-16x16@2x.png | Bin 0 -> 626 bytes .../fontStyle-monospace-aqua-16x16@2x.png | Bin 0 -> 692 bytes .../fontStyle-monospace-black-16x16@2x.png | Bin 0 -> 678 bytes .../fontStyle-monospace-blue-16x16@2x.png | Bin 0 -> 669 bytes .../fontStyle-monospace-darkgray-16x16@2x.png | Bin 0 -> 677 bytes .../fontStyle-monospace-gray-16x16@2x.png | Bin 0 -> 644 bytes .../fontStyle-monospace-green-16x16@2x.png | Bin 0 -> 696 bytes .../fontStyle-monospace-lightaqua-16x16@2x.png | Bin 0 -> 669 bytes .../fontStyle-monospace-lightblue-16x16@2x.png | Bin 0 -> 674 bytes .../fontStyle-monospace-lightgray-16x16@2x.png | Bin 0 -> 679 bytes .../fontStyle-monospace-lightgreen-16x16@2x.png | Bin 0 -> 691 bytes .../fontStyle-monospace-lightpurple-16x16@2x.png | Bin 0 -> 678 bytes .../fontStyle-monospace-purple-16x16@2x.png | Bin 0 -> 698 bytes .../fontStyle-monospace-red-16x16@2x.png | Bin 0 -> 667 bytes .../fontStyle-monospace-white-16x16@2x.png | Bin 0 -> 638 bytes .../fontStyle-sansSerif-aqua-16x16@2x.png | Bin 0 -> 776 bytes .../fontStyle-sansSerif-black-16x16@2x.png | Bin 0 -> 774 bytes .../fontStyle-sansSerif-blue-16x16@2x.png | Bin 0 -> 775 bytes .../fontStyle-sansSerif-darkgray-16x16@2x.png | Bin 0 -> 776 bytes .../fontStyle-sansSerif-gray-16x16@2x.png | Bin 0 -> 714 bytes .../fontStyle-sansSerif-green-16x16@2x.png | Bin 0 -> 797 bytes .../fontStyle-sansSerif-lightaqua-16x16@2x.png | Bin 0 -> 765 bytes .../fontStyle-sansSerif-lightblue-16x16@2x.png | Bin 0 -> 759 bytes .../fontStyle-sansSerif-lightgray-16x16@2x.png | Bin 0 -> 777 bytes .../fontStyle-sansSerif-lightgreen-16x16@2x.png | Bin 0 -> 783 bytes .../fontStyle-sansSerif-lightpurple-16x16@2x.png | Bin 0 -> 778 bytes .../fontStyle-sansSerif-purple-16x16@2x.png | Bin 0 -> 792 bytes .../fontStyle-sansSerif-red-16x16@2x.png | Bin 0 -> 745 bytes .../fontStyle-sansSerif-white-16x16@2x.png | Bin 0 -> 687 bytes .../fontStyle-script-aqua-16x16@2x-1.png | Bin 0 -> 979 bytes .../fontStyle-script-aqua-16x16@2x.png | Bin 0 -> 979 bytes .../fontStyle-script-black-16x16@2x-1.png | Bin 0 -> 965 bytes .../fontStyle-script-black-16x16@2x.png | Bin 0 -> 965 bytes .../fontStyle-script-blue-16x16@2x-1.png | Bin 0 -> 991 bytes .../fontStyle-script-blue-16x16@2x.png | Bin 0 -> 991 bytes .../fontStyle-script-darkgray-16x16@2x-1.png | Bin 0 -> 951 bytes .../fontStyle-script-darkgray-16x16@2x.png | Bin 0 -> 951 bytes .../fontStyle-script-gray-16x16@2x-1.png | Bin 0 -> 866 bytes .../fontStyle-script-gray-16x16@2x.png | Bin 0 -> 866 bytes .../fontStyle-script-green-16x16@2x-1.png | Bin 0 -> 1019 bytes .../fontStyle-script-green-16x16@2x.png | Bin 0 -> 1019 bytes .../fontStyle-script-lightaqua-16x16@2x-1.png | Bin 0 -> 976 bytes .../fontStyle-script-lightaqua-16x16@2x.png | Bin 0 -> 976 bytes .../fontStyle-script-lightblue-16x16@2x-1.png | Bin 0 -> 938 bytes .../fontStyle-script-lightblue-16x16@2x.png | Bin 0 -> 938 bytes .../fontStyle-script-lightgray-16x16@2x-1.png | Bin 0 -> 948 bytes .../fontStyle-script-lightgray-16x16@2x.png | Bin 0 -> 948 bytes .../fontStyle-script-lightgreen-16x16@2x-1.png | Bin 0 -> 983 bytes .../fontStyle-script-lightgreen-16x16@2x.png | Bin 0 -> 983 bytes .../fontStyle-script-lightpurple-16x16@2x-1.png | Bin 0 -> 956 bytes .../fontStyle-script-lightpurple-16x16@2x.png | Bin 0 -> 956 bytes .../fontStyle-script-purple-16x16@2x-1.png | Bin 0 -> 994 bytes .../fontStyle-script-purple-16x16@2x.png | Bin 0 -> 994 bytes .../fontStyle-script-red-16x16@2x-1.png | Bin 0 -> 905 bytes .../fontStyle-script-red-16x16@2x.png | Bin 0 -> 905 bytes .../fontStyle-script-white-16x16@2x-1.png | Bin 0 -> 830 bytes .../fontStyle-script-white-16x16@2x.png | Bin 0 -> 830 bytes .../fontStyle-serif-aqua-16x16@2x.png | Bin 0 -> 865 bytes .../fontStyle-serif-black-16x16@2x.png | Bin 0 -> 871 bytes .../fontStyle-serif-blue-16x16@2x.png | Bin 0 -> 864 bytes .../fontStyle-serif-darkgray-16x16@2x.png | Bin 0 -> 832 bytes .../fontStyle-serif-gray-16x16@2x.png | Bin 0 -> 773 bytes .../fontStyle-serif-green-16x16@2x.png | Bin 0 -> 881 bytes .../fontStyle-serif-lightaqua-16x16@2x.png | Bin 0 -> 859 bytes .../fontStyle-serif-lightblue-16x16@2x.png | Bin 0 -> 829 bytes .../fontStyle-serif-lightgray-16x16@2x.png | Bin 0 -> 851 bytes .../fontStyle-serif-lightgreen-16x16@2x.png | Bin 0 -> 854 bytes .../fontStyle-serif-lightpurple-16x16@2x.png | Bin 0 -> 853 bytes .../fontStyle-serif-purple-16x16@2x.png | Bin 0 -> 877 bytes .../fontStyle-serif-red-16x16@2x.png | Bin 0 -> 809 bytes .../fontStyle-serif-white-16x16@2x.png | Bin 0 -> 743 bytes .../gapHorizontal-aqua-16x16@2x.png | Bin 0 -> 671 bytes .../gapHorizontal-black-16x16@2x.png | Bin 0 -> 686 bytes .../gapHorizontal-blue-16x16@2x.png | Bin 0 -> 674 bytes .../gapHorizontal-darkgray-16x16@2x.png | Bin 0 -> 674 bytes .../gapHorizontal-gray-16x16@2x.png | Bin 0 -> 650 bytes .../gapHorizontal-green-16x16@2x.png | Bin 0 -> 694 bytes .../gapHorizontal-lightaqua-16x16@2x.png | Bin 0 -> 686 bytes .../gapHorizontal-lightblue-16x16@2x.png | Bin 0 -> 678 bytes .../gapHorizontal-lightgray-16x16@2x.png | Bin 0 -> 680 bytes .../gapHorizontal-lightgreen-16x16@2x.png | Bin 0 -> 680 bytes .../gapHorizontal-lightpurple-16x16@2x.png | Bin 0 -> 688 bytes .../gapHorizontal-purple-16x16@2x.png | Bin 0 -> 680 bytes .../gapHorizontal-red-16x16@2x.png | Bin 0 -> 661 bytes .../gapHorizontal-white-16x16@2x.png | Bin 0 -> 584 bytes .../gapVertical-aqua-16x16@2x.png | Bin 0 -> 677 bytes .../gapVertical-black-16x16@2x.png | Bin 0 -> 691 bytes .../gapVertical-blue-16x16@2x.png | Bin 0 -> 660 bytes .../gapVertical-darkgray-16x16@2x.png | Bin 0 -> 680 bytes .../gapVertical-gray-16x16@2x.png | Bin 0 -> 661 bytes .../gapVertical-green-16x16@2x.png | Bin 0 -> 699 bytes .../gapVertical-lightaqua-16x16@2x.png | Bin 0 -> 665 bytes .../gapVertical-lightblue-16x16@2x.png | Bin 0 -> 659 bytes .../gapVertical-lightgray-16x16@2x.png | Bin 0 -> 662 bytes .../gapVertical-lightgreen-16x16@2x.png | Bin 0 -> 663 bytes .../gapVertical-lightpurple-16x16@2x.png | Bin 0 -> 669 bytes .../gapVertical-purple-16x16@2x.png | Bin 0 -> 662 bytes .../gapVertical-red-16x16@2x.png | Bin 0 -> 643 bytes .../gapVertical-white-16x16@2x.png | Bin 0 -> 576 bytes .../inspector-element/italic-aqua-16x16@2x.png | Bin 0 -> 639 bytes .../inspector-element/italic-black-16x16@2x.png | Bin 0 -> 632 bytes .../inspector-element/italic-blue-16x16@2x.png | Bin 0 -> 638 bytes .../italic-darkgray-16x16@2x.png | Bin 0 -> 638 bytes .../inspector-element/italic-gray-16x16@2x.png | Bin 0 -> 606 bytes .../inspector-element/italic-green-16x16@2x.png | Bin 0 -> 647 bytes .../italic-lightaqua-16x16@2x.png | Bin 0 -> 638 bytes .../italic-lightblue-16x16@2x.png | Bin 0 -> 629 bytes .../italic-lightgray-16x16@2x.png | Bin 0 -> 638 bytes .../italic-lightgreen-16x16@2x.png | Bin 0 -> 645 bytes .../italic-lightpurple-16x16@2x.png | Bin 0 -> 637 bytes .../inspector-element/italic-purple-16x16@2x.png | Bin 0 -> 647 bytes .../inspector-element/italic-red-16x16@2x.png | Bin 0 -> 628 bytes .../inspector-element/italic-white-16x16@2x.png | Bin 0 -> 595 bytes ...ustifyContent-column-center-aqua-16x16@2x.png | Bin 0 -> 680 bytes ...stifyContent-column-center-black-16x16@2x.png | Bin 0 -> 657 bytes ...ustifyContent-column-center-blue-16x16@2x.png | Bin 0 -> 637 bytes ...fyContent-column-center-darkgray-16x16@2x.png | Bin 0 -> 671 bytes ...ustifyContent-column-center-gray-16x16@2x.png | Bin 0 -> 657 bytes ...stifyContent-column-center-green-16x16@2x.png | Bin 0 -> 677 bytes ...yContent-column-center-lightaqua-16x16@2x.png | Bin 0 -> 646 bytes ...yContent-column-center-lightblue-16x16@2x.png | Bin 0 -> 656 bytes ...yContent-column-center-lightgray-16x16@2x.png | Bin 0 -> 644 bytes ...Content-column-center-lightgreen-16x16@2x.png | Bin 0 -> 661 bytes ...ontent-column-center-lightpurple-16x16@2x.png | Bin 0 -> 647 bytes ...tifyContent-column-center-purple-16x16@2x.png | Bin 0 -> 644 bytes ...justifyContent-column-center-red-16x16@2x.png | Bin 0 -> 635 bytes ...stifyContent-column-center-white-16x16@2x.png | Bin 0 -> 585 bytes ...stifyContent-column-flexend-aqua-16x16@2x.png | Bin 0 -> 678 bytes ...tifyContent-column-flexend-black-16x16@2x.png | Bin 0 -> 655 bytes ...stifyContent-column-flexend-blue-16x16@2x.png | Bin 0 -> 635 bytes ...yContent-column-flexend-darkgray-16x16@2x.png | Bin 0 -> 669 bytes ...stifyContent-column-flexend-gray-16x16@2x.png | Bin 0 -> 655 bytes ...tifyContent-column-flexend-green-16x16@2x.png | Bin 0 -> 676 bytes ...Content-column-flexend-lightaqua-16x16@2x.png | Bin 0 -> 644 bytes ...Content-column-flexend-lightblue-16x16@2x.png | Bin 0 -> 653 bytes ...Content-column-flexend-lightgray-16x16@2x.png | Bin 0 -> 642 bytes ...ontent-column-flexend-lightgreen-16x16@2x.png | Bin 0 -> 658 bytes ...ntent-column-flexend-lightpurple-16x16@2x.png | Bin 0 -> 645 bytes ...ifyContent-column-flexend-purple-16x16@2x.png | Bin 0 -> 642 bytes ...ustifyContent-column-flexend-red-16x16@2x.png | Bin 0 -> 633 bytes ...tifyContent-column-flexend-white-16x16@2x.png | Bin 0 -> 577 bytes ...ifyContent-column-flexstart-aqua-16x16@2x.png | Bin 0 -> 685 bytes ...fyContent-column-flexstart-black-16x16@2x.png | Bin 0 -> 662 bytes ...ifyContent-column-flexstart-blue-16x16@2x.png | Bin 0 -> 642 bytes ...ontent-column-flexstart-darkgray-16x16@2x.png | Bin 0 -> 674 bytes ...ifyContent-column-flexstart-gray-16x16@2x.png | Bin 0 -> 661 bytes ...fyContent-column-flexstart-green-16x16@2x.png | Bin 0 -> 684 bytes ...ntent-column-flexstart-lightaqua-16x16@2x.png | Bin 0 -> 648 bytes ...ntent-column-flexstart-lightblue-16x16@2x.png | Bin 0 -> 661 bytes ...ntent-column-flexstart-lightgray-16x16@2x.png | Bin 0 -> 646 bytes ...tent-column-flexstart-lightgreen-16x16@2x.png | Bin 0 -> 664 bytes ...ent-column-flexstart-lightpurple-16x16@2x.png | Bin 0 -> 655 bytes ...yContent-column-flexstart-purple-16x16@2x.png | Bin 0 -> 648 bytes ...tifyContent-column-flexstart-red-16x16@2x.png | Bin 0 -> 636 bytes ...fyContent-column-flexstart-white-16x16@2x.png | Bin 0 -> 580 bytes ...yContent-column-spaceAround-aqua-16x16@2x.png | Bin 0 -> 681 bytes ...Content-column-spaceAround-black-16x16@2x.png | Bin 0 -> 659 bytes ...yContent-column-spaceAround-blue-16x16@2x.png | Bin 0 -> 641 bytes ...tent-column-spaceAround-darkgray-16x16@2x.png | Bin 0 -> 669 bytes ...yContent-column-spaceAround-gray-16x16@2x.png | Bin 0 -> 655 bytes ...Content-column-spaceAround-green-16x16@2x.png | Bin 0 -> 678 bytes ...ent-column-spaceAround-lightaqua-16x16@2x.png | Bin 0 -> 649 bytes ...ent-column-spaceAround-lightblue-16x16@2x.png | Bin 0 -> 656 bytes ...ent-column-spaceAround-lightgray-16x16@2x.png | Bin 0 -> 645 bytes ...nt-column-spaceAround-lightgreen-16x16@2x.png | Bin 0 -> 660 bytes ...t-column-spaceAround-lightpurple-16x16@2x.png | Bin 0 -> 649 bytes ...ontent-column-spaceAround-purple-16x16@2x.png | Bin 0 -> 645 bytes ...fyContent-column-spaceAround-red-16x16@2x.png | Bin 0 -> 636 bytes ...Content-column-spaceAround-white-16x16@2x.png | Bin 0 -> 588 bytes ...Content-column-spaceBetween-aqua-16x16@2x.png | Bin 0 -> 687 bytes ...ontent-column-spaceBetween-black-16x16@2x.png | Bin 0 -> 659 bytes ...Content-column-spaceBetween-blue-16x16@2x.png | Bin 0 -> 641 bytes ...ent-column-spaceBetween-darkgray-16x16@2x.png | Bin 0 -> 677 bytes ...Content-column-spaceBetween-gray-16x16@2x.png | Bin 0 -> 665 bytes ...ontent-column-spaceBetween-green-16x16@2x.png | Bin 0 -> 685 bytes ...nt-column-spaceBetween-lightaqua-16x16@2x.png | Bin 0 -> 647 bytes ...nt-column-spaceBetween-lightblue-16x16@2x.png | Bin 0 -> 665 bytes ...nt-column-spaceBetween-lightgray-16x16@2x.png | Bin 0 -> 646 bytes ...t-column-spaceBetween-lightgreen-16x16@2x.png | Bin 0 -> 665 bytes ...-column-spaceBetween-lightpurple-16x16@2x.png | Bin 0 -> 653 bytes ...ntent-column-spaceBetween-purple-16x16@2x.png | Bin 0 -> 644 bytes ...yContent-column-spaceBetween-red-16x16@2x.png | Bin 0 -> 635 bytes ...ontent-column-spaceBetween-white-16x16@2x.png | Bin 0 -> 580 bytes ...yContent-column-spaceEvenly-aqua-16x16@2x.png | Bin 0 -> 704 bytes ...Content-column-spaceEvenly-black-16x16@2x.png | Bin 0 -> 710 bytes ...yContent-column-spaceEvenly-blue-16x16@2x.png | Bin 0 -> 701 bytes ...tent-column-spaceEvenly-darkgray-16x16@2x.png | Bin 0 -> 703 bytes ...yContent-column-spaceEvenly-gray-16x16@2x.png | Bin 0 -> 660 bytes ...Content-column-spaceEvenly-green-16x16@2x.png | Bin 0 -> 727 bytes ...ent-column-spaceEvenly-lightaqua-16x16@2x.png | Bin 0 -> 682 bytes ...ent-column-spaceEvenly-lightblue-16x16@2x.png | Bin 0 -> 697 bytes ...ent-column-spaceEvenly-lightgray-16x16@2x.png | Bin 0 -> 705 bytes ...nt-column-spaceEvenly-lightgreen-16x16@2x.png | Bin 0 -> 701 bytes ...t-column-spaceEvenly-lightpurple-16x16@2x.png | Bin 0 -> 702 bytes ...ontent-column-spaceEvenly-purple-16x16@2x.png | Bin 0 -> 723 bytes ...fyContent-column-spaceEvenly-red-16x16@2x.png | Bin 0 -> 683 bytes ...Content-column-spaceEvenly-white-16x16@2x.png | Bin 0 -> 646 bytes .../justifyContent-row-center-aqua-16x16@2x.png | Bin 0 -> 665 bytes .../justifyContent-row-center-black-16x16@2x.png | Bin 0 -> 669 bytes .../justifyContent-row-center-blue-16x16@2x.png | Bin 0 -> 670 bytes ...stifyContent-row-center-darkgray-16x16@2x.png | Bin 0 -> 660 bytes .../justifyContent-row-center-gray-16x16@2x.png | Bin 0 -> 643 bytes .../justifyContent-row-center-green-16x16@2x.png | Bin 0 -> 682 bytes ...tifyContent-row-center-lightaqua-16x16@2x.png | Bin 0 -> 671 bytes ...tifyContent-row-center-lightblue-16x16@2x.png | Bin 0 -> 661 bytes ...tifyContent-row-center-lightgray-16x16@2x.png | Bin 0 -> 669 bytes ...ifyContent-row-center-lightgreen-16x16@2x.png | Bin 0 -> 668 bytes ...fyContent-row-center-lightpurple-16x16@2x.png | Bin 0 -> 674 bytes ...justifyContent-row-center-purple-16x16@2x.png | Bin 0 -> 665 bytes .../justifyContent-row-center-red-16x16@2x.png | Bin 0 -> 658 bytes .../justifyContent-row-center-white-16x16@2x.png | Bin 0 -> 605 bytes .../justifyContent-row-flexend-aqua-16x16@2x.png | Bin 0 -> 671 bytes ...justifyContent-row-flexend-black-16x16@2x.png | Bin 0 -> 674 bytes .../justifyContent-row-flexend-blue-16x16@2x.png | Bin 0 -> 664 bytes ...tifyContent-row-flexend-darkgray-16x16@2x.png | Bin 0 -> 661 bytes .../justifyContent-row-flexend-gray-16x16@2x.png | Bin 0 -> 645 bytes ...justifyContent-row-flexend-green-16x16@2x.png | Bin 0 -> 685 bytes ...ifyContent-row-flexend-lightaqua-16x16@2x.png | Bin 0 -> 663 bytes ...ifyContent-row-flexend-lightblue-16x16@2x.png | Bin 0 -> 665 bytes ...ifyContent-row-flexend-lightgray-16x16@2x.png | Bin 0 -> 659 bytes ...fyContent-row-flexend-lightgreen-16x16@2x.png | Bin 0 -> 671 bytes ...yContent-row-flexend-lightpurple-16x16@2x.png | Bin 0 -> 678 bytes ...ustifyContent-row-flexend-purple-16x16@2x.png | Bin 0 -> 662 bytes .../justifyContent-row-flexend-red-16x16@2x.png | Bin 0 -> 656 bytes ...justifyContent-row-flexend-white-16x16@2x.png | Bin 0 -> 594 bytes ...ustifyContent-row-flexstart-aqua-16x16@2x.png | Bin 0 -> 676 bytes ...stifyContent-row-flexstart-black-16x16@2x.png | Bin 0 -> 686 bytes ...ustifyContent-row-flexstart-blue-16x16@2x.png | Bin 0 -> 672 bytes ...fyContent-row-flexstart-darkgray-16x16@2x.png | Bin 0 -> 669 bytes ...ustifyContent-row-flexstart-gray-16x16@2x.png | Bin 0 -> 655 bytes ...stifyContent-row-flexstart-green-16x16@2x.png | Bin 0 -> 687 bytes ...yContent-row-flexstart-lightaqua-16x16@2x.png | Bin 0 -> 667 bytes ...yContent-row-flexstart-lightblue-16x16@2x.png | Bin 0 -> 662 bytes ...yContent-row-flexstart-lightgray-16x16@2x.png | Bin 0 -> 672 bytes ...Content-row-flexstart-lightgreen-16x16@2x.png | Bin 0 -> 673 bytes ...ontent-row-flexstart-lightpurple-16x16@2x.png | Bin 0 -> 673 bytes ...tifyContent-row-flexstart-purple-16x16@2x.png | Bin 0 -> 667 bytes ...justifyContent-row-flexstart-red-16x16@2x.png | Bin 0 -> 656 bytes ...stifyContent-row-flexstart-white-16x16@2x.png | Bin 0 -> 588 bytes ...tifyContent-row-spaceAround-aqua-16x16@2x.png | Bin 0 -> 672 bytes ...ifyContent-row-spaceAround-black-16x16@2x.png | Bin 0 -> 670 bytes ...tifyContent-row-spaceAround-blue-16x16@2x.png | Bin 0 -> 671 bytes ...Content-row-spaceAround-darkgray-16x16@2x.png | Bin 0 -> 668 bytes ...tifyContent-row-spaceAround-gray-16x16@2x.png | Bin 0 -> 649 bytes ...ifyContent-row-spaceAround-green-16x16@2x.png | Bin 0 -> 684 bytes ...ontent-row-spaceAround-lightaqua-16x16@2x.png | Bin 0 -> 670 bytes ...ontent-row-spaceAround-lightblue-16x16@2x.png | Bin 0 -> 664 bytes ...ontent-row-spaceAround-lightgray-16x16@2x.png | Bin 0 -> 669 bytes ...ntent-row-spaceAround-lightgreen-16x16@2x.png | Bin 0 -> 669 bytes ...tent-row-spaceAround-lightpurple-16x16@2x.png | Bin 0 -> 674 bytes ...fyContent-row-spaceAround-purple-16x16@2x.png | Bin 0 -> 667 bytes ...stifyContent-row-spaceAround-red-16x16@2x.png | Bin 0 -> 658 bytes ...ifyContent-row-spaceAround-white-16x16@2x.png | Bin 0 -> 610 bytes ...ifyContent-row-spaceBetween-aqua-16x16@2x.png | Bin 0 -> 676 bytes ...fyContent-row-spaceBetween-black-16x16@2x.png | Bin 0 -> 673 bytes ...ifyContent-row-spaceBetween-blue-16x16@2x.png | Bin 0 -> 671 bytes ...ontent-row-spaceBetween-darkgray-16x16@2x.png | Bin 0 -> 672 bytes ...ifyContent-row-spaceBetween-gray-16x16@2x.png | Bin 0 -> 654 bytes ...fyContent-row-spaceBetween-green-16x16@2x.png | Bin 0 -> 688 bytes ...ntent-row-spaceBetween-lightaqua-16x16@2x.png | Bin 0 -> 671 bytes ...ntent-row-spaceBetween-lightblue-16x16@2x.png | Bin 0 -> 664 bytes ...ntent-row-spaceBetween-lightgray-16x16@2x.png | Bin 0 -> 669 bytes ...tent-row-spaceBetween-lightgreen-16x16@2x.png | Bin 0 -> 672 bytes ...ent-row-spaceBetween-lightpurple-16x16@2x.png | Bin 0 -> 675 bytes ...yContent-row-spaceBetween-purple-16x16@2x.png | Bin 0 -> 666 bytes ...tifyContent-row-spaceBetween-red-16x16@2x.png | Bin 0 -> 656 bytes ...fyContent-row-spaceBetween-white-16x16@2x.png | Bin 0 -> 594 bytes ...tifyContent-row-spaceEvenly-aqua-16x16@2x.png | Bin 0 -> 705 bytes ...ifyContent-row-spaceEvenly-black-16x16@2x.png | Bin 0 -> 703 bytes ...tifyContent-row-spaceEvenly-blue-16x16@2x.png | Bin 0 -> 688 bytes ...Content-row-spaceEvenly-darkgray-16x16@2x.png | Bin 0 -> 702 bytes ...tifyContent-row-spaceEvenly-gray-16x16@2x.png | Bin 0 -> 666 bytes ...ifyContent-row-spaceEvenly-green-16x16@2x.png | Bin 0 -> 717 bytes ...ontent-row-spaceEvenly-lightaqua-16x16@2x.png | Bin 0 -> 697 bytes ...ontent-row-spaceEvenly-lightblue-16x16@2x.png | Bin 0 -> 699 bytes ...ontent-row-spaceEvenly-lightgray-16x16@2x.png | Bin 0 -> 695 bytes ...ntent-row-spaceEvenly-lightgreen-16x16@2x.png | Bin 0 -> 709 bytes ...tent-row-spaceEvenly-lightpurple-16x16@2x.png | Bin 0 -> 712 bytes ...fyContent-row-spaceEvenly-purple-16x16@2x.png | Bin 0 -> 726 bytes ...stifyContent-row-spaceEvenly-red-16x16@2x.png | Bin 0 -> 690 bytes ...ifyContent-row-spaceEvenly-white-16x16@2x.png | Bin 0 -> 629 bytes .../letterSpacing-aqua-16x16@2x-1.png | Bin 0 -> 779 bytes .../letterSpacing-aqua-16x16@2x.png | Bin 0 -> 852 bytes .../letterSpacing-black-16x16@2x-1.png | Bin 0 -> 773 bytes .../letterSpacing-black-16x16@2x.png | Bin 0 -> 845 bytes .../letterSpacing-blue-16x16@2x-1.png | Bin 0 -> 787 bytes .../letterSpacing-blue-16x16@2x.png | Bin 0 -> 862 bytes .../letterSpacing-darkgray-16x16@2x-1.png | Bin 0 -> 769 bytes .../letterSpacing-darkgray-16x16@2x.png | Bin 0 -> 840 bytes .../letterSpacing-gray-16x16@2x-1.png | Bin 0 -> 707 bytes .../letterSpacing-gray-16x16@2x.png | Bin 0 -> 770 bytes .../letterSpacing-green-16x16@2x-1.png | Bin 0 -> 800 bytes .../letterSpacing-green-16x16@2x.png | Bin 0 -> 903 bytes .../letterSpacing-lightaqua-16x16@2x-1.png | Bin 0 -> 769 bytes .../letterSpacing-lightaqua-16x16@2x.png | Bin 0 -> 859 bytes .../letterSpacing-lightblue-16x16@2x-1.png | Bin 0 -> 755 bytes .../letterSpacing-lightblue-16x16@2x.png | Bin 0 -> 832 bytes .../letterSpacing-lightgray-16x16@2x-1.png | Bin 0 -> 767 bytes .../letterSpacing-lightgray-16x16@2x.png | Bin 0 -> 848 bytes .../letterSpacing-lightgreen-16x16@2x-1.png | Bin 0 -> 781 bytes .../letterSpacing-lightgreen-16x16@2x.png | Bin 0 -> 860 bytes .../letterSpacing-lightpurple-16x16@2x-1.png | Bin 0 -> 771 bytes .../letterSpacing-lightpurple-16x16@2x.png | Bin 0 -> 848 bytes .../letterSpacing-purple-16x16@2x-1.png | Bin 0 -> 800 bytes .../letterSpacing-purple-16x16@2x.png | Bin 0 -> 865 bytes .../letterSpacing-red-16x16@2x-1.png | Bin 0 -> 740 bytes .../letterSpacing-red-16x16@2x.png | Bin 0 -> 818 bytes .../letterSpacing-white-16x16@2x-1.png | Bin 0 -> 668 bytes .../letterSpacing-white-16x16@2x.png | Bin 0 -> 746 bytes .../lowercase-aqua-16x16@2x.png | Bin 0 -> 1072 bytes .../lowercase-black-16x16@2x.png | Bin 0 -> 1082 bytes .../lowercase-blue-16x16@2x.png | Bin 0 -> 1101 bytes .../lowercase-darkgray-16x16@2x.png | Bin 0 -> 1029 bytes .../lowercase-gray-16x16@2x.png | Bin 0 -> 929 bytes .../lowercase-green-16x16@2x.png | Bin 0 -> 1153 bytes .../lowercase-lightaqua-16x16@2x.png | Bin 0 -> 1075 bytes .../lowercase-lightblue-16x16@2x.png | Bin 0 -> 1044 bytes .../lowercase-lightgray-16x16@2x.png | Bin 0 -> 1037 bytes .../lowercase-lightgreen-16x16@2x.png | Bin 0 -> 1106 bytes .../lowercase-lightpurple-16x16@2x.png | Bin 0 -> 1070 bytes .../lowercase-purple-16x16@2x.png | Bin 0 -> 1104 bytes .../inspector-element/lowercase-red-16x16@2x.png | Bin 0 -> 1006 bytes .../lowercase-white-16x16@2x.png | Bin 0 -> 878 bytes .../inspector-element/padding-aqua-16x16@2x.png | Bin 0 -> 614 bytes .../inspector-element/padding-black-16x16@2x.png | Bin 0 -> 601 bytes .../inspector-element/padding-blue-16x16@2x.png | Bin 0 -> 611 bytes .../padding-darkgray-16x16@2x.png | Bin 0 -> 614 bytes .../inspector-element/padding-gray-16x16@2x.png | Bin 0 -> 603 bytes .../inspector-element/padding-green-16x16@2x.png | Bin 0 -> 615 bytes .../padding-lightaqua-16x16@2x.png | Bin 0 -> 615 bytes .../padding-lightblue-16x16@2x.png | Bin 0 -> 609 bytes .../padding-lightgray-16x16@2x.png | Bin 0 -> 618 bytes .../padding-lightgreen-16x16@2x.png | Bin 0 -> 612 bytes .../padding-lightpurple-16x16@2x.png | Bin 0 -> 614 bytes .../padding-purple-16x16@2x.png | Bin 0 -> 614 bytes .../inspector-element/padding-red-16x16@2x.png | Bin 0 -> 604 bytes .../inspector-element/padding-white-16x16@2x.png | Bin 0 -> 572 bytes .../paddingBottom-aqua-16x16@2x.png | Bin 0 -> 596 bytes .../paddingBottom-black-16x16@2x.png | Bin 0 -> 588 bytes .../paddingBottom-blue-16x16@2x.png | Bin 0 -> 593 bytes .../paddingBottom-darkgray-16x16@2x.png | Bin 0 -> 598 bytes .../paddingBottom-gray-16x16@2x.png | Bin 0 -> 586 bytes .../paddingBottom-green-16x16@2x.png | Bin 0 -> 601 bytes .../paddingBottom-lightaqua-16x16@2x.png | Bin 0 -> 601 bytes .../paddingBottom-lightblue-16x16@2x.png | Bin 0 -> 592 bytes .../paddingBottom-lightgray-16x16@2x.png | Bin 0 -> 604 bytes .../paddingBottom-lightgreen-16x16@2x.png | Bin 0 -> 594 bytes .../paddingBottom-lightpurple-16x16@2x.png | Bin 0 -> 596 bytes .../paddingBottom-purple-16x16@2x.png | Bin 0 -> 600 bytes .../paddingBottom-red-16x16@2x.png | Bin 0 -> 590 bytes .../paddingBottom-white-16x16@2x.png | Bin 0 -> 552 bytes .../paddingHorizontal-aqua-16x16@2x.png | Bin 0 -> 607 bytes .../paddingHorizontal-black-16x16@2x.png | Bin 0 -> 601 bytes .../paddingHorizontal-blue-16x16@2x.png | Bin 0 -> 606 bytes .../paddingHorizontal-darkgray-16x16@2x.png | Bin 0 -> 610 bytes .../paddingHorizontal-gray-16x16@2x.png | Bin 0 -> 597 bytes .../paddingHorizontal-green-16x16@2x.png | Bin 0 -> 612 bytes .../paddingHorizontal-lightaqua-16x16@2x.png | Bin 0 -> 613 bytes .../paddingHorizontal-lightblue-16x16@2x.png | Bin 0 -> 602 bytes .../paddingHorizontal-lightgray-16x16@2x.png | Bin 0 -> 613 bytes .../paddingHorizontal-lightgreen-16x16@2x.png | Bin 0 -> 608 bytes .../paddingHorizontal-lightpurple-16x16@2x.png | Bin 0 -> 609 bytes .../paddingHorizontal-purple-16x16@2x.png | Bin 0 -> 612 bytes .../paddingHorizontal-red-16x16@2x.png | Bin 0 -> 599 bytes .../paddingHorizontal-white-16x16@2x.png | Bin 0 -> 564 bytes .../paddingLeft-aqua-16x16@2x.png | Bin 0 -> 605 bytes .../paddingLeft-black-16x16@2x.png | Bin 0 -> 589 bytes .../paddingLeft-blue-16x16@2x.png | Bin 0 -> 594 bytes .../paddingLeft-darkgray-16x16@2x.png | Bin 0 -> 608 bytes .../paddingLeft-gray-16x16@2x.png | Bin 0 -> 594 bytes .../paddingLeft-green-16x16@2x.png | Bin 0 -> 601 bytes .../paddingLeft-lightaqua-16x16@2x.png | Bin 0 -> 600 bytes .../paddingLeft-lightblue-16x16@2x.png | Bin 0 -> 593 bytes .../paddingLeft-lightgray-16x16@2x.png | Bin 0 -> 601 bytes .../paddingLeft-lightgreen-16x16@2x.png | Bin 0 -> 596 bytes .../paddingLeft-lightpurple-16x16@2x.png | Bin 0 -> 597 bytes .../paddingLeft-purple-16x16@2x.png | Bin 0 -> 601 bytes .../paddingLeft-red-16x16@2x.png | Bin 0 -> 589 bytes .../paddingLeft-white-16x16@2x.png | Bin 0 -> 559 bytes .../paddingRight-aqua-16x16@2x.png | Bin 0 -> 606 bytes .../paddingRight-black-16x16@2x.png | Bin 0 -> 590 bytes .../paddingRight-blue-16x16@2x.png | Bin 0 -> 595 bytes .../paddingRight-darkgray-16x16@2x.png | Bin 0 -> 608 bytes .../paddingRight-gray-16x16@2x.png | Bin 0 -> 596 bytes .../paddingRight-green-16x16@2x.png | Bin 0 -> 602 bytes .../paddingRight-lightaqua-16x16@2x.png | Bin 0 -> 602 bytes .../paddingRight-lightblue-16x16@2x.png | Bin 0 -> 594 bytes .../paddingRight-lightgray-16x16@2x.png | Bin 0 -> 602 bytes .../paddingRight-lightgreen-16x16@2x.png | Bin 0 -> 599 bytes .../paddingRight-lightpurple-16x16@2x.png | Bin 0 -> 598 bytes .../paddingRight-purple-16x16@2x.png | Bin 0 -> 603 bytes .../paddingRight-red-16x16@2x.png | Bin 0 -> 591 bytes .../paddingRight-white-16x16@2x.png | Bin 0 -> 560 bytes .../paddingTop-aqua-16x16@2x.png | Bin 0 -> 595 bytes .../paddingTop-black-16x16@2x.png | Bin 0 -> 586 bytes .../paddingTop-blue-16x16@2x.png | Bin 0 -> 593 bytes .../paddingTop-darkgray-16x16@2x.png | Bin 0 -> 596 bytes .../paddingTop-gray-16x16@2x.png | Bin 0 -> 583 bytes .../paddingTop-green-16x16@2x.png | Bin 0 -> 598 bytes .../paddingTop-lightaqua-16x16@2x.png | Bin 0 -> 602 bytes .../paddingTop-lightblue-16x16@2x.png | Bin 0 -> 588 bytes .../paddingTop-lightgray-16x16@2x.png | Bin 0 -> 601 bytes .../paddingTop-lightgreen-16x16@2x.png | Bin 0 -> 593 bytes .../paddingTop-lightpurple-16x16@2x.png | Bin 0 -> 592 bytes .../paddingTop-purple-16x16@2x.png | Bin 0 -> 597 bytes .../paddingTop-red-16x16@2x.png | Bin 0 -> 588 bytes .../paddingTop-white-16x16@2x.png | Bin 0 -> 550 bytes .../paddingVertical-aqua-16x16@2x.png | Bin 0 -> 597 bytes .../paddingVertical-black-16x16@2x.png | Bin 0 -> 590 bytes .../paddingVertical-blue-16x16@2x.png | Bin 0 -> 594 bytes .../paddingVertical-darkgray-16x16@2x.png | Bin 0 -> 599 bytes .../paddingVertical-gray-16x16@2x.png | Bin 0 -> 585 bytes .../paddingVertical-green-16x16@2x.png | Bin 0 -> 601 bytes .../paddingVertical-lightaqua-16x16@2x.png | Bin 0 -> 605 bytes .../paddingVertical-lightblue-16x16@2x.png | Bin 0 -> 591 bytes .../paddingVertical-lightgray-16x16@2x.png | Bin 0 -> 604 bytes .../paddingVertical-lightgreen-16x16@2x.png | Bin 0 -> 595 bytes .../paddingVertical-lightpurple-16x16@2x.png | Bin 0 -> 595 bytes .../paddingVertical-purple-16x16@2x.png | Bin 0 -> 599 bytes .../paddingVertical-red-16x16@2x.png | Bin 0 -> 591 bytes .../paddingVertical-white-16x16@2x.png | Bin 0 -> 554 bytes .../inspector-element/split-full-black-13x13.png | Bin 0 -> 272 bytes .../split-full-black-13x13@2x.png | Bin 0 -> 374 bytes .../inspector-element/split-full-blue-13x13.png | Bin 0 -> 279 bytes .../split-full-blue-13x13@2x.png | Bin 0 -> 399 bytes .../split-full-darkgray-13x13.png | Bin 0 -> 266 bytes .../split-full-darkgray-13x13@2x.png | Bin 0 -> 376 bytes .../inspector-element/split-full-gray-13x13.png | Bin 0 -> 245 bytes .../split-full-gray-13x13@2x.png | Bin 0 -> 325 bytes .../split-full-lightgray-13x13.png | Bin 0 -> 266 bytes .../split-full-lightgray-13x13@2x.png | Bin 0 -> 364 bytes .../split-full-purple-13x13.png | Bin 0 -> 272 bytes .../split-full-purple-13x13@2x.png | Bin 0 -> 395 bytes .../inspector-element/split-full-white-13x13.png | Bin 0 -> 235 bytes .../split-full-white-13x13@2x.png | Bin 0 -> 277 bytes .../inspector-element/split-half-black-13x13.png | Bin 0 -> 280 bytes .../split-half-black-13x13@2x.png | Bin 0 -> 404 bytes .../inspector-element/split-half-blue-13x13.png | Bin 0 -> 285 bytes .../split-half-blue-13x13@2x.png | Bin 0 -> 439 bytes .../split-half-darkgray-13x13.png | Bin 0 -> 274 bytes .../split-half-darkgray-13x13@2x.png | Bin 0 -> 430 bytes .../inspector-element/split-half-gray-13x13.png | Bin 0 -> 239 bytes .../split-half-gray-13x13@2x.png | Bin 0 -> 387 bytes .../split-half-lightgray-13x13.png | Bin 0 -> 273 bytes .../split-half-lightgray-13x13@2x.png | Bin 0 -> 404 bytes .../split-half-purple-13x13.png | Bin 0 -> 288 bytes .../split-half-purple-13x13@2x.png | Bin 0 -> 434 bytes .../inspector-element/split-half-white-13x13.png | Bin 0 -> 224 bytes .../split-half-white-13x13@2x.png | Bin 0 -> 301 bytes .../split-quarter-black-13x13.png | Bin 0 -> 266 bytes .../split-quarter-black-13x13@2x.png | Bin 0 -> 371 bytes .../split-quarter-blue-13x13.png | Bin 0 -> 280 bytes .../split-quarter-blue-13x13@2x.png | Bin 0 -> 416 bytes .../split-quarter-darkgray-13x13.png | Bin 0 -> 270 bytes .../split-quarter-darkgray-13x13@2x.png | Bin 0 -> 400 bytes .../split-quarter-gray-13x13.png | Bin 0 -> 239 bytes .../split-quarter-gray-13x13@2x.png | Bin 0 -> 367 bytes .../split-quarter-lightgray-13x13.png | Bin 0 -> 264 bytes .../split-quarter-lightgray-13x13@2x.png | Bin 0 -> 380 bytes .../split-quarter-purple-13x13.png | Bin 0 -> 281 bytes .../split-quarter-purple-13x13@2x.png | Bin 0 -> 403 bytes .../split-quarter-white-13x13.png | Bin 0 -> 222 bytes .../split-quarter-white-13x13@2x.png | Bin 0 -> 286 bytes .../strikethrough-aqua-16x16@2x.png | Bin 0 -> 936 bytes .../strikethrough-black-16x16@2x.png | Bin 0 -> 921 bytes .../strikethrough-blue-16x16@2x.png | Bin 0 -> 938 bytes .../strikethrough-darkgray-16x16@2x.png | Bin 0 -> 931 bytes .../strikethrough-gray-16x16@2x.png | Bin 0 -> 866 bytes .../strikethrough-green-16x16@2x.png | Bin 0 -> 976 bytes .../strikethrough-lightaqua-16x16@2x.png | Bin 0 -> 872 bytes .../strikethrough-lightblue-16x16@2x.png | Bin 0 -> 871 bytes .../strikethrough-lightgray-16x16@2x.png | Bin 0 -> 917 bytes .../strikethrough-lightgreen-16x16@2x.png | Bin 0 -> 894 bytes .../strikethrough-lightpurple-16x16@2x.png | Bin 0 -> 879 bytes .../strikethrough-purple-16x16@2x.png | Bin 0 -> 946 bytes .../strikethrough-red-16x16@2x.png | Bin 0 -> 894 bytes .../strikethrough-white-16x16@2x.png | Bin 0 -> 747 bytes .../textAlign-center-aqua-16x16@2x.png | Bin 0 -> 547 bytes .../textAlign-center-black-16x16@2x.png | Bin 0 -> 530 bytes .../textAlign-center-blue-16x16@2x.png | Bin 0 -> 548 bytes .../textAlign-center-darkgray-16x16@2x.png | Bin 0 -> 532 bytes .../textAlign-center-gray-16x16@2x.png | Bin 0 -> 526 bytes .../textAlign-center-green-16x16@2x.png | Bin 0 -> 551 bytes .../textAlign-center-lightaqua-16x16@2x.png | Bin 0 -> 533 bytes .../textAlign-center-lightblue-16x16@2x.png | Bin 0 -> 532 bytes .../textAlign-center-lightgray-16x16@2x.png | Bin 0 -> 533 bytes .../textAlign-center-lightgreen-16x16@2x.png | Bin 0 -> 533 bytes .../textAlign-center-lightpurple-16x16@2x.png | Bin 0 -> 534 bytes .../textAlign-center-purple-16x16@2x.png | Bin 0 -> 548 bytes .../textAlign-center-red-16x16@2x.png | Bin 0 -> 530 bytes .../textAlign-center-white-16x16@2x.png | Bin 0 -> 529 bytes .../textAlign-justify-aqua-16x16@2x.png | Bin 0 -> 514 bytes .../textAlign-justify-black-16x16@2x.png | Bin 0 -> 506 bytes .../textAlign-justify-blue-16x16@2x.png | Bin 0 -> 515 bytes .../textAlign-justify-darkgray-16x16@2x.png | Bin 0 -> 508 bytes .../textAlign-justify-gray-16x16@2x.png | Bin 0 -> 506 bytes .../textAlign-justify-green-16x16@2x.png | Bin 0 -> 518 bytes .../textAlign-justify-lightaqua-16x16@2x.png | Bin 0 -> 509 bytes .../textAlign-justify-lightblue-16x16@2x.png | Bin 0 -> 508 bytes .../textAlign-justify-lightgray-16x16@2x.png | Bin 0 -> 509 bytes .../textAlign-justify-lightgreen-16x16@2x.png | Bin 0 -> 509 bytes .../textAlign-justify-lightpurple-16x16@2x.png | Bin 0 -> 510 bytes .../textAlign-justify-purple-16x16@2x.png | Bin 0 -> 515 bytes .../textAlign-justify-red-16x16@2x.png | Bin 0 -> 507 bytes .../textAlign-justify-white-16x16@2x.png | Bin 0 -> 503 bytes .../textAlign-left-aqua-16x16@2x.png | Bin 0 -> 527 bytes .../textAlign-left-black-16x16@2x.png | Bin 0 -> 514 bytes .../textAlign-left-blue-16x16@2x.png | Bin 0 -> 528 bytes .../textAlign-left-darkgray-16x16@2x.png | Bin 0 -> 516 bytes .../textAlign-left-gray-16x16@2x.png | Bin 0 -> 513 bytes .../textAlign-left-green-16x16@2x.png | Bin 0 -> 532 bytes .../textAlign-left-lightaqua-16x16@2x.png | Bin 0 -> 516 bytes .../textAlign-left-lightblue-16x16@2x.png | Bin 0 -> 515 bytes .../textAlign-left-lightgray-16x16@2x.png | Bin 0 -> 517 bytes .../textAlign-left-lightgreen-16x16@2x.png | Bin 0 -> 516 bytes .../textAlign-left-lightpurple-16x16@2x.png | Bin 0 -> 517 bytes .../textAlign-left-purple-16x16@2x.png | Bin 0 -> 528 bytes .../textAlign-left-red-16x16@2x.png | Bin 0 -> 514 bytes .../textAlign-left-white-16x16@2x.png | Bin 0 -> 513 bytes .../textAlign-right-aqua-16x16@2x.png | Bin 0 -> 530 bytes .../textAlign-right-black-16x16@2x.png | Bin 0 -> 512 bytes .../textAlign-right-blue-16x16@2x.png | Bin 0 -> 531 bytes .../textAlign-right-darkgray-16x16@2x.png | Bin 0 -> 516 bytes .../textAlign-right-gray-16x16@2x.png | Bin 0 -> 511 bytes .../textAlign-right-green-16x16@2x.png | Bin 0 -> 533 bytes .../textAlign-right-lightaqua-16x16@2x.png | Bin 0 -> 516 bytes .../textAlign-right-lightblue-16x16@2x.png | Bin 0 -> 515 bytes .../textAlign-right-lightgray-16x16@2x.png | Bin 0 -> 517 bytes .../textAlign-right-lightgreen-16x16@2x.png | Bin 0 -> 516 bytes .../textAlign-right-lightpurple-16x16@2x.png | Bin 0 -> 517 bytes .../textAlign-right-purple-16x16@2x.png | Bin 0 -> 529 bytes .../textAlign-right-red-16x16@2x.png | Bin 0 -> 512 bytes .../textAlign-right-white-16x16@2x.png | Bin 0 -> 514 bytes .../textOverflow-ellipses-aqua-16x16@2x.png | Bin 0 -> 854 bytes .../textOverflow-ellipses-black-16x16@2x.png | Bin 0 -> 828 bytes .../textOverflow-ellipses-blue-16x16@2x.png | Bin 0 -> 844 bytes .../textOverflow-ellipses-darkgray-16x16@2x.png | Bin 0 -> 827 bytes .../textOverflow-ellipses-gray-16x16@2x.png | Bin 0 -> 760 bytes .../textOverflow-ellipses-green-16x16@2x.png | Bin 0 -> 868 bytes .../textOverflow-ellipses-lightaqua-16x16@2x.png | Bin 0 -> 835 bytes .../textOverflow-ellipses-lightblue-16x16@2x.png | Bin 0 -> 813 bytes .../textOverflow-ellipses-lightgray-16x16@2x.png | Bin 0 -> 838 bytes ...textOverflow-ellipses-lightgreen-16x16@2x.png | Bin 0 -> 837 bytes ...extOverflow-ellipses-lightpurple-16x16@2x.png | Bin 0 -> 840 bytes .../textOverflow-ellipses-purple-16x16@2x.png | Bin 0 -> 864 bytes .../textOverflow-ellipses-red-16x16@2x.png | Bin 0 -> 787 bytes .../textOverflow-ellipses-white-16x16@2x.png | Bin 0 -> 710 bytes .../titlecase-aqua-16x16@2x.png | Bin 0 -> 1084 bytes .../titlecase-black-16x16@2x.png | Bin 0 -> 1083 bytes .../titlecase-blue-16x16@2x.png | Bin 0 -> 1102 bytes .../titlecase-darkgray-16x16@2x.png | Bin 0 -> 1049 bytes .../titlecase-gray-16x16@2x.png | Bin 0 -> 949 bytes .../titlecase-green-16x16@2x.png | Bin 0 -> 1157 bytes .../titlecase-lightaqua-16x16@2x.png | Bin 0 -> 1076 bytes .../titlecase-lightblue-16x16@2x.png | Bin 0 -> 1058 bytes .../titlecase-lightgray-16x16@2x.png | Bin 0 -> 1043 bytes .../titlecase-lightgreen-16x16@2x.png | Bin 0 -> 1117 bytes .../titlecase-lightpurple-16x16@2x.png | Bin 0 -> 1093 bytes .../titlecase-purple-16x16@2x.png | Bin 0 -> 1112 bytes .../inspector-element/titlecase-red-16x16@2x.png | Bin 0 -> 1016 bytes .../titlecase-white-16x16@2x.png | Bin 0 -> 853 bytes .../underline-aqua-16x16@2x.png | Bin 0 -> 692 bytes .../underline-black-16x16@2x.png | Bin 0 -> 697 bytes .../underline-blue-16x16@2x.png | Bin 0 -> 685 bytes .../underline-darkgray-16x16@2x.png | Bin 0 -> 686 bytes .../underline-gray-16x16@2x.png | Bin 0 -> 646 bytes .../underline-green-16x16@2x.png | Bin 0 -> 701 bytes .../underline-lightaqua-16x16@2x.png | Bin 0 -> 672 bytes .../underline-lightblue-16x16@2x.png | Bin 0 -> 679 bytes .../underline-lightgray-16x16@2x.png | Bin 0 -> 680 bytes .../underline-lightgreen-16x16@2x.png | Bin 0 -> 682 bytes .../underline-lightpurple-16x16@2x.png | Bin 0 -> 687 bytes .../underline-purple-16x16@2x.png | Bin 0 -> 697 bytes .../inspector-element/underline-red-16x16@2x.png | Bin 0 -> 662 bytes .../underline-white-16x16@2x.png | Bin 0 -> 608 bytes .../uppercase-aqua-16x16@2x.png | Bin 0 -> 1118 bytes .../uppercase-black-16x16@2x.png | Bin 0 -> 1093 bytes .../uppercase-blue-16x16@2x.png | Bin 0 -> 1129 bytes .../uppercase-darkgray-16x16@2x.png | Bin 0 -> 1075 bytes .../uppercase-gray-16x16@2x.png | Bin 0 -> 960 bytes .../uppercase-green-16x16@2x.png | Bin 0 -> 1181 bytes .../uppercase-lightaqua-16x16@2x.png | Bin 0 -> 1091 bytes .../uppercase-lightblue-16x16@2x.png | Bin 0 -> 1071 bytes .../uppercase-lightgray-16x16@2x.png | Bin 0 -> 1073 bytes .../uppercase-lightgreen-16x16@2x.png | Bin 0 -> 1131 bytes .../uppercase-lightpurple-16x16@2x.png | Bin 0 -> 1093 bytes .../uppercase-purple-16x16@2x.png | Bin 0 -> 1133 bytes .../inspector-element/uppercase-red-16x16@2x.png | Bin 0 -> 1026 bytes .../uppercase-white-16x16@2x.png | Bin 0 -> 849 bytes .../wrapColumn-aqua-16x16@2x.png | Bin 0 -> 872 bytes .../wrapColumn-black-16x16@2x.png | Bin 0 -> 892 bytes .../wrapColumn-blue-16x16@2x.png | Bin 0 -> 868 bytes .../wrapColumn-darkgray-16x16@2x.png | Bin 0 -> 881 bytes .../wrapColumn-gray-16x16@2x.png | Bin 0 -> 807 bytes .../wrapColumn-green-16x16@2x.png | Bin 0 -> 912 bytes .../wrapColumn-lightaqua-16x16@2x.png | Bin 0 -> 861 bytes .../wrapColumn-lightblue-16x16@2x.png | Bin 0 -> 848 bytes .../wrapColumn-lightgray-16x16@2x.png | Bin 0 -> 860 bytes .../wrapColumn-lightgreen-16x16@2x.png | Bin 0 -> 863 bytes .../wrapColumn-lightpurple-16x16@2x.png | Bin 0 -> 864 bytes .../wrapColumn-purple-16x16@2x.png | Bin 0 -> 884 bytes .../wrapColumn-red-16x16@2x.png | Bin 0 -> 818 bytes .../wrapColumn-white-16x16@2x.png | Bin 0 -> 734 bytes .../inspector-element/wrapRow-aqua-16x16@2x.png | Bin 0 -> 788 bytes .../inspector-element/wrapRow-black-16x16@2x.png | Bin 0 -> 794 bytes .../inspector-element/wrapRow-blue-16x16@2x.png | Bin 0 -> 790 bytes .../wrapRow-darkgray-16x16@2x.png | Bin 0 -> 787 bytes .../inspector-element/wrapRow-gray-16x16@2x.png | Bin 0 -> 723 bytes .../inspector-element/wrapRow-green-16x16@2x.png | Bin 0 -> 819 bytes .../wrapRow-lightaqua-16x16@2x.png | Bin 0 -> 776 bytes .../wrapRow-lightblue-16x16@2x.png | Bin 0 -> 763 bytes .../wrapRow-lightgray-16x16@2x.png | Bin 0 -> 768 bytes .../wrapRow-lightgreen-16x16@2x.png | Bin 0 -> 791 bytes .../wrapRow-lightpurple-16x16@2x.png | Bin 0 -> 776 bytes .../wrapRow-purple-16x16@2x.png | Bin 0 -> 803 bytes .../inspector-element/wrapRow-red-16x16@2x.png | Bin 0 -> 748 bytes .../inspector-element/wrapRow-white-16x16@2x.png | Bin 0 -> 663 bytes 1064 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-center-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-center-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-center-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-center-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowDown-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowLeft-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowRight-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/arrowUp-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/bold-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/borderRadius-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-aqua-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-black-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-blue-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-darkgray-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-gray-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-green-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightaqua-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightblue-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightgray-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightgreen-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightpurple-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-purple-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-red-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-white-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-script-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/fontStyle-serif-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapHorizontal-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/gapVertical-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/italic-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-aqua-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-black-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-blue-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-darkgray-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-gray-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-green-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightaqua-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightblue-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightgray-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightgreen-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightpurple-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-purple-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-red-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-white-16x16@2x-1.png create mode 100644 editor/resources/editor/icons/light/inspector-element/letterSpacing-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/lowercase-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/padding-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingBottom-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingHorizontal-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingLeft-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingRight-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingTop-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/paddingVertical-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-black-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-black-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-blue-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-blue-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-darkgray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-darkgray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-gray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-gray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-lightgray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-lightgray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-purple-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-purple-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-white-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-full-white-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-black-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-black-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-blue-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-blue-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-darkgray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-darkgray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-gray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-gray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-lightgray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-lightgray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-purple-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-purple-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-white-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-half-white-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-black-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-black-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-blue-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-blue-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-darkgray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-darkgray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-gray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-gray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-lightgray-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-lightgray-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-purple-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-purple-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-white-13x13.png create mode 100644 editor/resources/editor/icons/light/inspector-element/split-quarter-white-13x13@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/strikethrough-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-center-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-justify-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-left-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textAlign-right-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/titlecase-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/underline-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/uppercase-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapColumn-white-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-aqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-black-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-blue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-darkgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-gray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-green-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-lightaqua-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-lightblue-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-lightgray-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-lightgreen-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-lightpurple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-purple-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-red-16x16@2x.png create mode 100644 editor/resources/editor/icons/light/inspector-element/wrapRow-white-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..391c961a9266cb18ea31a840ccbe8f64446e91ed GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?iuJ|7e2$S;wpA=_Xt&LY>00000NkvXXu0mjf*|#G; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..701e361f869f2bac4c41eab598d4d96992775c69 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#A^ra98#t4ZETbU0=&Bz-bL3tr!{+XgElrGvpLOa6-PD{7G!ZoR zdmq7CX9p0UI?t~dGIu+nZfggUE!rsfRD1{n%at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?C7Y3rnyhtpGg0RXjr?RG=kM z0$uo*FfND?0!y-RK+Sx~u$h;<@lA%HMCFJa|#O$4-Q`v3p{07*qoM6N<$ Ef|}?o6#xJL literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cd44da2c02d03f2d4a49ba6f562f8b5800e9e53b GIT binary patch literal 660 zcmV;F0&D$=P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? z{iYRcBBd30|D6BO|K7QjF^}6T@aOYlt2zQb_Z(r08#qE z*^g9L#O1$$1+V}Xzyf|x02;=}S#++uANTw*l`MxF%mZi`3g(F=L6nh06eWat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Z)q-CK5zg4002ovPDHLkV1m148rT2; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..960a5c6d9542e79af0f6b75143ee58742d5687e4 GIT binary patch literal 682 zcmV;b0#*HqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&n@V15}V7?K*OK?@DT0otEL=R9_irc3$R zE65Qb{A7ALpoFSkZ3UcQFqaeT-X>7=0or$uqa{o~xA5v)AcXsT5p9y`Rb+!?t@N}- zE=*W>^#G*O0=HS{73F(g_h7=p%cpyl8K1^76wG~Jvp}fy&0imUhkat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G{~Cu-pB%vnkWq93Z~}1xVFDcm zH(&(cM2DdEcp-$FdU!xhzoa>|O`D&SoV0-Q%gj?|W9YyDJ);7KbwTIC9%b<5b6N-| z#E9ZC?a{)gwUrxiPrQ%@VX1*(#)O@lvX2IAYAXVG0MDGFcykyLJh zJ*{%?mH$p(eFZ8&1*iZO@O=UZIGWQr^ST(%eL~XI%%--w4`hf$)>bB1Aj2cb+Tmfj~ipe;9OYQ&w002ovPDHLk FV1g$AC~E)! literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a89fd707cca830a9ac324538299491f86e95817c GIT binary patch literal 661 zcmV;G0&4wat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?f`8O?bOLY!j|sFB=r{)d zFanc!UWp`)r6iOeD7h~=pqISng+lHD%0ELDvnxzsg_%(U>%L}LaV`g2$YbWUYbi@R zbH@ND zZ=E4Vf>!?mHJ}F6fExHo1C6_sPd@uiZ(SqKXl5izGdg@k(9WOMVtH60~6+ v*cvy_k3DW1yl@%{BvZ6WXewTW0cCdHT!w8=(Is3200000NkvXXu0mjf;w%{w literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..98eff40da53f8b278088b67827fd732eb6378c91 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5au zoh0cyXdoCP7(Z;wJ&55RdFM+s+z|`4n)tMyJ`7={z3W|DxBf_rpbS5W{lTF(F$mY?~S=ee?jW9G4wk^+d)&iw-^KZ>HL zUDAmY3S+faZh;sO17bi7e4hanj2F+SY*&|e;xUvgM(gzhTI&{x?xat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?sgOG0@-&3#E5?#kc%Y1-TY$}f{}!TrDjHdq-ou>F*bxl9RNCZExmBcNeW zRnzH?3Fc~@6G+(XWrM4|L66+Doy@nG&lx;~XdMFtN?)>~rkuvn$HO|OJ_8|I$H3qg zsL2>RZ^aQjglP2@r~x&g2Gqb;8fg0|;WD?AR@}hPY^~D|NX4q8c3*(bNWW*^E8X}< z1rH%w=L8;Pq@MGET(>QQk5diF5^WIL75{|+Wp$nvoOeyog>ZEM0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O{}>Cg1WS-k^q?NW3d9P8qj=Cx zkPaw;PR3cIWOadr<$#)b$+FBWfAX^nVF2Zqxn;~|U;q=0j2f6WC5wzhIoL>UXLXWL z%4w&;hOX$Kuh!XtJmaMlNZtw<7;^$H`H3U6;G=a65FvbM7>C7%=rv4iuQ%bNb>9JT zYo=gJv7NT!8QSpB>Q|r!)PNdL17B&NGMD1adpl{xCEDq&b@~A&q{KMNA1s!BFRt^? z&QGQkE%<1i9SGKx$b&1>M0_k&QfSxJkPOj!pat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?+ z;sP3PQl}A;hPEUv3)IX@rqF>;KBZ&^5Pq3mrj!m$Ai>OtfrTr%&s4#Ol0R;0q+3O3 zE)Tk6gix)u0^6lpvA7;QK$DZgjW=Bh4>4NH0N+@2r^oY?s1H5w@&!D^XkB|C*8>YH zGil6I_zBj^Umym=fEW-1Uuoc_2d-QPGuh9%vb69MtabGR4ab$EVqrDB$hED3pJ1)E z0$jQ3gs{fIEq&f@a~f$#rf8#(uJ|tu2($ABtM+4CG9%`V00000NkvXXu0mjftI#2H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f6f4b96f18721c7ef3aeaf8c5ab568a55c3e7f71 GIT binary patch literal 658 zcmV;D0&V??P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Vn3)qx`c&-{im}rer@dWU#aJL6c zfXbD50<*>2^)o>~(_o@|P z)IsL*U%&!b01IFNzbHVsc*U}MN~5D6OKS~uZlNFWEiSyEVUcLd^EJ@9*&D#70qeQk sPx#07*qoM6N<$f_sD_761SM literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-center-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4fbdf2748bf0dec6838944a9f44718fd86ce133e GIT binary patch literal 605 zcmV-j0;2tiP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%iK~#7F?UexvfFKM-MF#CJ;2$-sScseQ^pP009U<;FALT`Eb|vEQ4ad(K9Wzck;wKM&!oBsJJ#KVZ>;? rupG_vSfHl%6;cAV;1qNh0NptNSWJqr>kU>|00000NkvXXu0mjfuPX*U literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..28c34166dfc2775c415619bd4ce1f3665fb7f5ea GIT binary patch literal 671 zcmV;Q0$}}#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Yn>HOl_&dTa>94}Uz=(lKFZD9>0SZ9m8qqVi57uDNuM*| z>HqtHb=&RKwjj4a42S_SAO?QPfV$`+OyigEqpkQ^?$Wlu9R-pVkIjHEI5(L8RHjm5kXir$002ovPDHLk FV1jSIDr^7% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..82f1858ee93a383e04a2b415b30d87c02a57c678 GIT binary patch literal 674 zcmV;T0$u%yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7E5xm+L6%uoZ%Psmx8<<{B)kC8X7 zP^YG8t^)20#9shE&IW?V0l_uu631~N;7&JSjLG>9;S#Ggu7L6>6a@Jgmus>Ci1A9P zZQH#+uj|_N(HM6Kx(n2R8c+jj;HM09d`XgI=MNFPuCKS6c$p8QV literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ce06b9bc514a88df7091cfd396c87832241aaff4 GIT binary patch literal 664 zcmV;J0%!e+P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O@2K(71tnOLQ~)O8ulg$_Y6V&n zCD4Vhgb_9%5Wxk1z%VCSHZ!@*+(0%vfY3XfJFAs2K+A}MQ6shUut02sVPr}2qsIyE z_@dW-La5#Rx`;m5xw;ZBv7a7mX=B`p>fPWM3@x>BxKl5uD~?s3EUh+anx}yQo~zB9 zZ42ovHniFjat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?WPO<4thG~&V_`oZQ3d~Bec}ebqkhd9X#FQm z82x0oS#Az|3s?XPU;!-PcLbo>EZ(A-j5JRC`5QNfnr^6J?if?(fT=)T%B3i-06Lq( vA{Rk+8Wvt)uJl3jj=Kx+t9W+;7@Ok-OF3tqbfa{;00000NkvXXu0mjfE?6M8 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8e2bc62389fe911de7490e09654518efcdb614 GIT binary patch literal 645 zcmV;00($+4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?YnU$j>Q00?2XBI2+!3;`sJ2t}Y!NTa_XXM&njPrkJs^P>$+$hl`7x)BdXjz3H_(cN?#}?zY-v;2Utk8z zfEh3YhcdA61!Z=SgQ7ogX;Wyb;e>di%z9a5(3kUBZ3@kKfJ^P&{XQwPARh8SlF`=3 fPQ|-3U{vP=5$;?$_L{Qc00000NkvXXu0mjf(p(*O literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3e64164114a18e4bc5d57561e62db07993f1ac3a GIT binary patch literal 685 zcmV;e0#f~nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?JAWYJ5pIiPtdOgNX_eWZs`i7i%49xWC_c0?Nat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?npA@x8UhNlEkqsdH8?y@$4?EAGXT-oLMO@sd!aLOZb?Pj) zNU&97+(&3XK!~I~)0_}?fj~=@V-urg4mq0K(Z7H)s7xY)HGgae&&@tO_d{Bn^ef)4 zPiQYiE4M%lhygJm27bqYt|CW%7FSxi>#sRN+okoyjiWqKt*hL|8;D?Gdx9=4lU$C~ x1RG9*&Ph#TeOl8CI1PzUI|!s456*zlI}f)eY-w_6aDV^+002ovPDHLkV1mlN7jyss literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a034833e7249ab8aa0ceb023b9273df1dd97c2c5 GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?f|LP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?I+wg$)1BN-4V-V?)XV)SgPI zcLnzg)i)4AI6>$$4O^(aoO4|Tcewy)W~X@9TFbOB$2y$WmbkbU3jnnEF~;0zk>pK@ zn*+ZB7Qg~n01NmZ0bn*GMsT_-t&@BxakG6zCD3l6@k7iDJg1qU#6=`$tiAzowjMVT tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mz<7uNb4fH0ti^mN0-_Gm9iG&F*XQPaoGE`v;K7h zG|?59cM7mfXvJAb>q2gU7!U(uKn(npfk}4-b&Wk~#bZe80wIzushZ#YlP6Va{sdvI zeyEz~+R+ubq2i~ON_^j`W+I@y{UPya(<8s)uQMPd=K=1WU5(x{(wP7N002ovPDHLk FV1oXcC~*J) literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..df66b8cdef56e40cffc0ddc39717c7b8ef33ad59 GIT binary patch literal 678 zcmV;X0$KfuP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?T@4=* z8eY*$5aP|LwctGiRY6k7N2A@iv^EetsY;5G;5-%Q zBW~B%1TL+x39-xVJp;iWGf5%^$SBnE0edtHk~iA<(W?0C3@Een06+s`uRnqWmjD0& M07*qoM6N<$f_)Dpy8r+H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5a5a336221fae3d1ed1f40e232712934cc922ba1 GIT binary patch literal 662 zcmV;H0%`q;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?L1Y$@dSD# zE}-EiwN18U#*s~az|fa$qvg@PjV&#JVs6+KMADp{!N^bni(kn5f(#E8|G?aHw}f!J zJn@mh{X+5%Y?rj+U`-%ki3E2(SXBadxB#BS*vHfPh3J~t)^B25%O56yQA)=_j=s~g z^B6Y-y#*>j1*iZO@K*vl={V~he5bQH%d|0W2ndO=>Gs<9K0{d7wkC*i1uiot?*M<$ w$RzN&QdvRA!>0BMl0NPvpjGkY1Sm$w8_TLww$13lqW}N^07*qoM6N<$f*(gH5dZ)H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexend-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fa33f581ba75e54fe7a94525e8dd143cfa44947c GIT binary patch literal 656 zcmV;B0&o3^P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5J0<>&E$x>#xShy-6&JshX1PoC|w#|A7W=@ixjsH z{0dkA3t#~(U`_&1+b@;bee7**Tb75py-^_(zTDzzfKi2>AkB4!%H_^J0SZp_y{O)I q>Q^Y`E^bIZb0+}qiYF(4F*;sKs#DW~59Y@J0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?rAghOHpmTa1KZ?My1<0A)4-zt zz`*lYFQQJRz~3O|m=CHm5D*FYS2z0M=#2G4-^`M#CESGaOoFUjgr78ElDgr#D`k1D zTHx};bWM`QR{#MBKmY=t5?I5*|HkLI7|oYbwu#VgDUTLp>-Gh-_j#LK%Tcr!C}i6N go&fFmbpoI}8&(-z+xBz4@&Et;07*qoM6N<$f}|n}!Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?i19s7=5nW{- zpnT3bR;_^{6>vdxWP^SgS*A0nYtg#AUu$97iR2+Q&cP<(LdCq}7o*TIQr;t}*2ts8 zsI_3PKy`sri@L3xN&BXO4SYSePp!L!|?O<40000< KMNUMnLSTZOa4dKL literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b227e809dde4c946e778b7d4ee058fa25e5fc623 GIT binary patch literal 686 zcmV;f0#W^mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O5j}tfA(qrY;ZZz-o&Y@o%L$au z(&JcC05u1o@dWE%!X_JxI~b#wI4>FYXYvz%c8eLuVSa@uili#%%ecmiI4E zc~w;xvl+*6BBk6z29(#vTnpd##S_m8wedXf*0$}n54**2MlC5X#lsUI{md+obw<}s zvat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? zf}7w^0tq3MYhtt}y)S9F9)EiO(T76_=3nT#&iP0Dn1k3DHXvhA`Tw(&@@|ZIrpdnV z2P~s=?nr5CtT}-eMIJCXCdE(4>8yBBOVQ*BYpqP*@iB#ELTA2X?Qr@fZ3ckkQia%-(W3?00000NkvXXu0mjf DL@6oU literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cfa52aa151fde8dc11bdbab1d89046b4392f29e2 GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?flcab zQsPat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4d1>mhD%JS{0|4Cgca~ei4rhGxb!GFX*~S2geP;4PL|^!62c06s*uCaW zUz=?TP}OxBdRb`}CW?dxEdn3_0w4ea&;oQ1)-o$2$&SUPSN2p{_4BL7 z!(4#*Eei^dVF1Wh{O{-Syr;}+RObj{NO2(#8ObE%vjEQdI1}lzwMA3$-vW?Y*A4u9 VZB~Xjzt8{x002ovPDHLkV1oQzFn9m} literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..60bf727016e43b444544b89702225e672aba709b GIT binary patch literal 667 zcmV;M0%ZM(P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&@pNNZQwco3JHpGh`VMo zxloE%Sa3L&wBH)A!etp_ZsO^YW`wW}(Mq(AU>_qk7k9Kad3Kjt4Mq3Z)Ff>%zH8{# zKG90(El>k$KnI zAnt(aww~{eM@BiqoPRz?r_*=ZVDwe|w+58XxdG33aO#<2c_9D*002ovPDHLkV1h5p BB^v+$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..21f66875f901a51dacd73fc594e4951de0822462 GIT binary patch literal 662 zcmV;H0%`q;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Owcj`?gY>YU>sB~ z9ifw8Tog)_K#~eUk?@x+{o23kOLH-R>Q_WHb649W9*^pBHz)b2uCobRtyONLZosU1w4h9fzjN# zsXcq0eHY-OZk<^u8`RWoxO;*1RP_$UGwftWlBZxcqLeFW w;Q||b$)GuQyTBU!lX}@?=~n!=0IJb-1sJPZ6#zUrY5)KL07*qoM6N<$g2nzIMF0Q* literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..36988f9f5182e9312f7ce86ceea4ed19af220a8f GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?44?^O*NA6wxxD$f$FBpbFnat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mg0C=*P5>?-MFvnN&}HPA z5txMYh;6Jiv=F11cz;s3-2LIc(uW>^=vS0bLH&X+YXu8S0MGE1x%{DM!!}(B2+0Zm4(`pdGq9b-a@$Q}N#dh!)o!t-NEQMFzf200000NkvXX Hu0mjfO4}t( literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-flexstart-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..07a26499412406a0c74fa13ec1c9a9a0323cb5f8 GIT binary patch literal 673 zcmV;S0$%-zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mf+NT#`XD}n6NnQCkK%)F zf^5JDY;s-`N@|m~5TlrQe?mC^`=MXy%K?afMURR|UGQZsU}gyb>cV;c2rYNYIKjJV zHx;G)LdInj%K8-k0|YCkyww-Vv{hHM;l+!W#U0tn0P6(Nym&_^GrCs2PvR*B1!=4ND6W_|gLnx8p z%)OlRxi1^im?P-;!v}N7h<8}at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?HCK}W4Z%%x%so0Z?Gn; z%Vkq4H~~}RkFSPr#jvw4#q|K|+E?0vTp$tv0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NW=mbDvkSn1wv^n)^9G z+O@bExCID600Iy&e?WSz@A>g4#^+=A=GtH#SGb$i{Uac<@O|g|pCDM=rU2>;Zo%*X aFq{i(2VLB6i1&m50000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3($wB!i(#!3(15xfC5Vj=}g zp(qw=N9jc@O)Ncv9>Ei=!}^m@uw)x4n6F@mF!P3xw>tr7I#jp|)*AmHUH^n<$Ntm>R2U6`|m)HZRtAwzS%JLB$Ku-7G;8!If_fu^BDcJpgtwu;*3rA*JBN z=S(A`QHp&RP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?eivg&r>ND;PQ^#}#q-naf z*6w&2!H<$Uak|e^&|G@RnppFcQw#XBq*g%?+}pM-&at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5T?4+g_#r^_~K$*tSPSu=Cwh%GX99~T?O(1i1WH% z-PiEt6GO$=X b&q#R!Hx6*aa^RyV00000NkvXXu0mjf-}W5U literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5bba3ade3da99667b5bee594285ad31e3de62174 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?1M5sNJeLjshXyFaZY>UgI^K2hIu48CyYxR$KSs1-*Zj}ZU+R5{RRZ^&tpcas zBuPFnBN|mL2|Um!-kKCeVbE@<-B7!scEi=to00MZHGz6{^2q8X00000NkvXXu0mjf Dly@ia literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..06196c9ca934f386fef381f7dffd29dd763f4a6e GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-}ml;_|a zyFP@NsG|!rLiPMQ?w@w}wE*Yfjg-q41+WB7AH&ls>)zHz6ZueWNm4GJgUcKS*n4kI zL^EMYUzwQ&=$lZYm29TT6JBYItMe;;3i1kwlBFJWW-!D~V?v#uz6k?w0!d30g2uW@ zsA(c0g4?y$Yu;5ey2@<8j0i$5;=y?XhG8_Y8nPO)8nPOe4*!gpH|WQ5!|i6;9{>OV M07*qoM6N<$f=pj1+yDRo literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..03a8a8e3658dfecc6d06f537ae8bd2ced94c7006 GIT binary patch literal 649 zcmV;40(Sk0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?U%s~!Y~X)zdJ?Y#3XG;fe9!Rzy_2FV3aTc z-2hHN83N-VRB?cWq*6K5Pl}RAaqKwxvH}bpdY|N1X7s>5rPgnPp+mj}*^TFPM=8Sz z!l;R{F(cX`Hh|*7QzmTD0dcS}DOHFeZ}?yzrUbG=AlAm(N;@K!*9Otb_{IM3DsToM z_jj^=*6^&9Wk)fg}S`D3O jHS7behFT5vXQVs;dliW>YoC%q00000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?t_a%t|vEKwgB5RrpzD z=N~>z&TjH7Cat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#q3u380XP9TfjEKg(>7rQ zHmUC=#_)&M(nNl6PeK|(?}O{Txs+({sQHWcKGGjB#(d)*Xz!@p1{_PHlxky)Cn{rv z-9u~rqO}Qx5Y7nvqzYhvwbl+x-;WvN=Cj`5q^AO$b3H21;b9*Gt$|fhql{ndH&;P2 z0hDjz6}`|=Av2pXwJ+I(IL8)A+^GWCUs6g)R)D*g9Z=>k76MPKfSe2kL6B)E(@>_N fOvBBQo00GaKN5`XDb|aI00000NkvXXu0mjfe8(M@ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..52e79d95b2a07c3ea8e71a0b2aaae4a6d57aadc0 GIT binary patch literal 660 zcmV;F0&D$=P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PLCGEC4_InHc{f-)loIT@uL$lWj|DQ2 ziAM$vmYQ2a7p7!$5XlukAVt&{*at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?U%s~!Y~X)zY&8l3f%+_lw->TEfY|VvIH`oi5}{Ah!VwiqS#+nfTcsz#j|F{AK0e!K6izsLq3D9=1lUE%XEVf z2)!iqnxyp5%@o?2cVciy1agT}a-{0h{#tXEQpvz$kh26S5kPz6Qv8cC22kM_oGN0J z@s0oND)3!ka6{K{fj}lcy=JEuVZ%8wE{H(hf3GP)eSzdal?&h`g>Z&Z0Uj9|hGE^% jx}kML>xQ#qKO^G>1*w9GOk+bL00000NkvXXu0mjf@SYv? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..50ed803012eea12e75211667931f3b2c98426d09 GIT binary patch literal 645 zcmV;00($+4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?vK6Il^d| za6aDXioO$AFL+6e3*so`%c=rC>OOPD`kc3wIQXY*_qYtWz7-e+vA6*5$ z2|V;At0)o3$48Q^aoLe4NG{C@5hR3F48y9SRYR+W fRt-nTZbrrv-k)l5ED0tF00000NkvXXu0mjfZF&~4 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceAround-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..64c3f60d1ab77b62b8d14eafb98a2ee95cd79819 GIT binary patch literal 636 zcmV-?0)zdDP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?U&6BgD?z*pHT;4v@$?}PCz?BX*)m}sUu_( zQd>nW7aT$)INat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_CDx?w+|!3hRa|6h;;b}DZhg>kcu5gEP!^FHXcW#J|SdCV4D(5t3^ zPA&15SHaN+{{FEfz6jdI{LsrU5c5W4aIJ)yafO)*5Rr=NhN}rdR5xs-ZrHMkdv`;< ajAQ|l5P82A4t{I^0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7T`i5xDZbu zNAd`s#5z_JQyXb9Q8bw^f&Qd3eSLv+0O4myHcCHV-e-h?5dmXs#{LeDP->5D)}jxK zDgso@u|d}|9|uAZ9avZlU*_cm>fE?CzhXO3r(}$ibpcS$Jw6c{_&_SUb<_%VR+#xr zhusc55(Mxke2RUE`~@OF1c(3;@CO2tGS@Bfwd@U@jMxr5>Vf-^xF+yMuibH5aK55z zrP~40r0&IOPKLwwj+nAiXS002ov JPDHLkV1l=ZB2fSU literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f8ae0dcf630424a592c0b70834f6d86d725c7397 GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?*_DGVXBq2!RjNo-FIP+BjWNO~`$i(5W%351sTay4|3};WU+b|3+ z5cg5xXa%~ibJOxjLJ*j%Mq%(d^cJW96`%rC!2SiG8CBD=B{?HM(lo7Nj?sC5yV^uU za@hBduIO-{TXK|qf)RFIGmyZS+x7(lat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?yqb2um-K=~TnD_7&g=S(m%Dqz;S(|Qjml}mzfe#Q{o zn+;+I46CcmzyV&%IKjI(FvZO`(i8U`Ueb0TTu@`Z&jZlJ2a_$U7)DH`R*dB0fM^vo z9=$l+@4#~d3&xbLHG1EoUx5lx0V+TR{D1)O?pHG*g(<{Yqql?pJitXgQvy>8$q$61 z^aiqD&{f*+03ieOZcreJmh#&!wsn{>L{ss<3Q$Jp0hFIn1qJ>VaR2}S07*qoM6N<$ Eg2YNAy8r+H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ef4f88bd29dc800bd1fb7bce63420915696a8128 GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NbZP)qmbvhv4b`yjB}!$5dr6Lat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?1z2kv=UmHe z_0LaIftvQFfEGgNduQ@Km)w)8z$JP%Tsm4q>mj2Fs}1qX`+h2%t-#`f3UcZwb`|{# zRDcRl0V?490@zl&u$>@hj$&8I&I4?#-|YZ7-uJ~=lWRzlS1{9_B?Ae4ecOIOP_^tl nu$3TqOq`d^1AC(al*9P|v+GQdBzLN500000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O?-@OI6&iDjt(_Ae`SR6>uI|M6``MY^tdZ z9f(XQABlPQSa?=iT-xDE2cAiS0d(QmH6UBO2ss5JKm>>Y5zu}C-OFVA9{SKHh+npH&vB^9uq*ys6WWgfmZF+q?qRa80`6zZD=f&I_ev VQ$@~DwoL#4002ovPDHLkV1n&FC)fZ0 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ac13ae85068d61ad153f3df24f82058436b8700b GIT binary patch literal 670 zcmV;P0%84$P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?acRUzK?3Y|pF75TdhD!@5V_{h{n}r`^=Ls+{Dqv!7wEPDZF^Y0V zNAw`NaYA>bVlKM;d@2w!;SkrH!jt&ID@mTalD7&tO^M!@+at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Q}AAmat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!H5559Z{lMtdWisC^D zK&M7rV~okx*2PpHhsb>xhK3?hN}Vuuq2!j23Y29j+tPHiYNDC7vaBv4X^<=zy|hj0G+L!FDHrwjqB;fE)qNsprgG-dx}JB-DCX? zu@ZW6ZEdgub~g~Zq#Q`l1v|u@DWPh7D*j&s%;vlRX(MQzkTSmy00000NkvXXu0mjf D_2nbn literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..823d325a5287f5b5fe42f046e0aec6918b01bebe GIT binary patch literal 670 zcmV;P0%84$P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?t#djcYEE*0hI~)pNyO$X#S2&QjxPr)O36xQ#0Qz=SY8WwK%ls{k+X`r z_;J3e!%hcA2?BW1yEciPMR$P;Pys4H1?*oy#CbXlYxvVxv9mb)0iYe8RKgQEIZNpw z9ujLLpIKV#^9dRTU)MAwZ!&Uh^M%&9rd{#h3Q#uZ0~Y;OMPdX%O8@`>07*qoM6N<$ Ef`;rF-2eap literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c077002806e88d756b14fd457bbb8d91e5c7f296 GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?cvB`F0Y`LLdP)!iMOXj1n-(*#x+N$;{O$(OwI$>yat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?tXPkB%?nF5RP;gQ`?inxh z;(b)OvjVjMA>_o~-bVBmr~nn90#v~G1<*X45rGa>Le8VUw+%@@@PZy$K#p5`=Ey2H zZKSgT=6#ygp+`eP7t8~LCHhoNyW+_TPzL7-8`nz8(5P*)00000NkvXXu0mjf$q*$> literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-spaceBetween-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..73a3c0e3d5d26211d09ee3980f11a00c94055bdb GIT binary patch literal 656 zcmV;B0&o3^P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?*Jug0}$3i&`qEV{!F@01q&kvcIl1jf1q9fzE|%4gaS~f z#kGc_U-K9l2sH{lf<78x613UlaGl$nm}Ee?n~KF6i$jM`+Ch|qZ^z(_dN$FEGCZ4s zF98jF>SS#eIR#=s42S_SuzmwrJh~yGvdl%fcx@g=Kk&i#z=r0k3kG(qrdb%DfZisY qN*WTJi)Fhy6lG1i;>{Wm7UvBm{Y+h@06=d50000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?FRip4)DCKgwgcPAq~J$rInIaZ z$2}lK(_9aM4}i>qB+!|Bo&|%UKp`L{E{qjMLeCb4&%m i1<)DcaXgy<8O{S+1ZdB@=VI>w0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?8RVQzrJYZ7pB^2TSO!Q}{6VM6h1pX!g^#>HfVEPqEVB)C8 zgVdId nsZY|+eedIWpk#Ccn##EVd>=wkD6=qf00000NkvXXu0mjf3#>8Z literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..038fbe0903f32addc404febf68d5677e663bbfb9 GIT binary patch literal 699 zcmV;s0!00ZP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ts_NKJ20^fNU3Z6RObo_!V2(IIaAOiMy@L3OE3UZf09NKaDu9?0-s{!oD(5&( zBBdlmR@Zg<++SuBX1qLAYDF=Xp6XdFv(=LR^T6{SB=FYrq=#83Wx37{{^C ztm7MqqA1bR#^i7r2{pEDn-CNBdqCZKnxbc*Kz@NSMSV&P#(aVXvF+W8RF>r#!`gIW h6!um8w+1Yea|N@POsvpsY+L{U002ovPDHLkV1m!TGs6G? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..293e1c51f0b4ff9cc992ecdcce5ad5a7de75a990 GIT binary patch literal 697 zcmV;q0!ICbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?UmSPE(;0YD!nEt4rCgnDw!hC5n&7Dl{xhK=P11P=*(-YzQ;XEZ2j1o{uMV{}2 z4Zv(T)x}-Z@;VS~1c(+0T|!%SLoU~I5TH8{R4&BerYiztZ6#Io5+`z@ fZpHs9Kv6hnh_O@FLat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?sq{XaDk6F>}hi+ zDskHx`lloQ4;dzB00ZQ18F=RIat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-(c#X7JsgMM{3 zZjNRHn-YUA8JNKK2)IguFVGyg!9CA1pxzA#fwy#at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?k5?rUXi$1WMTO6F5Qz4i&_y z0H*>tLO^&+p@fvcIfi}M#<7r*BE|v*CHqO%*iRbG^XxAW_%B5BA*%;}Ot+4~h6x7t zy220U!2*zJF?zoHD#j1i(#QnFAr$oKzyZM9{rltbN{Ht6k|Mdbc*VC46r)_$B}9*Q z49bl+oRptgEs7*%aR@nGp1X8yey79g4islDYhDMf*!=l2Mg}FnI|+yG6-vS~3|Lj7vWaCvjzei=L3zjTN#0hePjRt002ovPDHLkV1h|GJg5Kw literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ef676ed227262cb96cee0a25a9ca87c93cdf24aa GIT binary patch literal 696 zcmV;p0!RIcP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Nj2U(}3k$==#jzhYyp?Q$WsG1Er*p zVjpOb}DL2qL@i3Zt zMr3TmAt+-AA@Y78cnk#0V~GfJ9p&gg!PW6D1c)m@VM79pRn5GLP*qy%%nL e_-_qZa_0t7pl@NCbUd8^0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?f+c7L(FzaXfMlGNuxJEvf}-etu*ooCn6oFF>;i#zffEro@MMa8DtIwLz)vx8 z$2v%LjJZkki@J?;kzu6aKMa&{;7`YlS2FO;6X|L5g|)fk+JPp~tpZ+aW5GnFyV=I4 zBq4(HP1Knd@y+^z!)6D#L2({deNyt7|00Hwhb}^{(H=&^XBY$o0YSjW2sr%#c`H?8 zon62at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DFB$qS6)Mzl;FDX5mH2tqR=m7}dLRD3U3_grsX96Q50<<4^b`F$M zS9Ez4MMp1hfo_X70|x947-Obrhq5f!eXOqQCAt&0IPuVdIF8j&0u{zC?9gbpg%y=r zpC?I@4dweCW_JJ!6m}Un;cn+z>jId(^$><(cmpQ#8HxZAAOe0yK=%i1nkL{TvIXEU z=?0G-%RLu*v~8OL6ZUw;b)Amz;@y#at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;d~qTo9D1aZ3OI002ovPDHLkV1j;BH_ZS5 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8ceb943603ccff0ede3f6fdce16c2b796f9004b7 GIT binary patch literal 706 zcmV;z0zLhSP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_g_{!iUM`si0(>fofKG zVIIWNVQL1nc@(1+w}~+UqX`8?D$pQc9W8idlZV`)3%1(i2~QPh4T$mrq9u=Hq%-L? zk=r2Ar0q#^NbRO(NPb>?w!-QPm_7yfX5EVE$ZH6ooB?OxXAIm{ zz-Y~NWt`r?A!P5~jIBsG-d=Ww2PNwBK>AR6&8CsM%b<;`|!kvo$)_|jQuGD#B>}~V__5c6?07*qoM6N<$g4Ity5&!@I literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9df6b76331efbacad2dcc651e3c8eb626f4d0607 GIT binary patch literal 697 zcmV;q0!ICbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Y%g fuj0QIV5yxeE8at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?eP3$kFD<&8d!b{&rfh7uUH13lJ(!Kf{p z!>O4UPI29!jY$9(1p*>IX2Bw~iqDABv$S}Q7X{cP+?7xi<{cVlOK}lRSLI_UlSJM5 zO@+k@K>D&M`Bu1`xfhcVZ(W3J;u{H}zo8OP0!rX#2t0N`n369|6cd1%RK{cKC|`^F z)0BF{hflx;#nzT9<|cH(tLC*54$xEa-x5#^jyo~qP%G^} Rjx_)P002ovPDHLkV1nU1D3|~M literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-column-stretch-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..65342d41698afc6b9f6d41c70d18ccc92a8512ee GIT binary patch literal 614 zcmV-s0-61ZP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? zne-hq?*j610(WD{#7b%Q)kSEGSwM(xLlsZ~75I(7egcLZ#nA$`NaKDd(ml9u15ZIY z^g6CkNQ}Tpiat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?L_&wB!i(#!3(15xfC5Vj=}l z2#ST;QF;+e6HAYvNALveutXCIhHRmjIA6g`!u)IqZyzB1JF2!~v33DHgVql0xKhsn zTmQ%vwYis=CsSIUQPzb$Jt#H7VD!NGbg3%pup^Xqi$q6A{SY>ItB?i+l;tz_Rb?&k z^v%SltM1hD1Rqeu-5{7(py5wN2e!iz&#p^Ko*j7oSJ=JFYi z?=;InE-M?9`FasHeg=V|d=-1K#y3cp@4b!7P!Ky7I~F?@I~F?@8s`aft7Ce=0e`;$ O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZBs-qM% zl_rxUS@M@tGq^LS7C{hP+qNy>18;xgA#5DS86075*5y)X`0`l5!jo_ECm5K&KS14m zSOZ%)!Wwwylv12%L%v^Uzdib~lB_7&uxXki48w~tCc@oTF4WYHo99pj-fEza=Uw2l ry!IX3hKjah5pBo6K-;mlV@0_E#;aod+H;*e00000NkvXXu0mjfm7FFK literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..727169ca6e7daf19783dbb8567af54bfb7512ac8 GIT binary patch literal 637 zcmV-@0)qXCP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?j&lsA_hvcW-I1+jTK0ir!Z z5YMn0ZQ;e#N0^F{mP@#@HMZ7NCwP0jfZ^+l`UoBS^A8{{?)Uj+0avdYLN2zD9wI#_ zAle`Z#ZnaIKd`p(xyH{-JN88ZZX(!n4yeyP5R!Qp+3?-B^B5`}$1)wqKcM4S$FWj3 XM%-=0m?rLu00000NkvXXu0mjfzSI|b literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..742d5de61ae270f33d8968e44a06286292d1559d GIT binary patch literal 671 zcmV;Q0$}}#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?GFr1H1uv0;Qw0 zhl5yBQR5Lj!TNV#94yFA3dI@nW|m}zY_dc46C!2l7+*k=Bq_|vS{smz#u!snRdwTn z*2EV-qHqa!OLBHthcFDEZQI_bf;Ly54ZvKvXT_; zs8>%(3d6^*7=5<%1JIUt-PvWR=s4DKtm9b6v5sS9c3x}Hc6Oc%7at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hCV<|0 zWRx5^c7!ql6NFbaLg5fcK0uN1C%LKAXD6!sVj|_=S(OCNxh8~g!fQ=321IAAy>g-r z_YuiQEIndJaw^2Z81wMn-*TdDp-2-~hr?JB5cO@Wamne{#IsL|iAZv4PFFg>$NBjK zjMD>7Xh}$tGjO_66LyF*Y-pu@fSj~O7S@K7ePE+I&5cx%jFD#d^rSGnUB&oafxZCt rdF{Kn4HX^7I*xT5>p0eNtSrtGvWjbRdTI3U00000NkvXXu0mjfCzm4$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..47d78d5c7a6897e15e0de41b446ec6ea4b2a4122 GIT binary patch literal 677 zcmV;W0$TlvP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?KPy(&SR_&_NUobsg)30E0hpnPfNsMjt zgxfR6=i>MQGT`S2I3-6hstsU?`^-6Tar_oUK@Xb7NCkDdRV*->P|at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Ul9H9Okxn9UFJf$m2c^tt{LyT2DpbbI`C{8?P z!Wt1I!K_ZHLWsQOU4CYkLKg63Voa=DdxUx{zzFn7e1e|+b^&sL4(6VHq)$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..44947a9e64f3b3b97a6af21ba88e25eedbbc3bd9 GIT binary patch literal 656 zcmV;B0&o3^P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kFE2PP;?P_TDmhnO@Lb7$nS)2 zxM5FgcZ?0sRA+|@vV3U`tsEf(x-f}UA1LmRYH9K_&Xc5Y1i^M7-^q~Y3?|||063RIat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?40s~gKW1M7v0!qBaO5i0}F!di`zIvd>^EoJ`-f^4Tkl}I6at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?TEfY|VqzBlf zbc2r2O-zylf&(sT4ne|CN)#!!6Gi^{fb#FqR6uXIV4$?i6+$2k%s6K`-Q+NV&hW+t zToHl2#39>L^J#x6B@>|l`yxkMq(%VUg=?E%`5HijIou7i8<@#A`3ofG=Pxk2sc*SL zATK$C6ep{o<&qdDL|_|WD@jp&fow;OE8sMZa7Hh|iGM(O>wy@}hp^7+d2VtUDr(1S h$7;uF$7;t)avqK0eu|5&nos}$002ovPDHLkV1nRT7$X1x literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..54d55b233bc1565583029e4f055834ee211742fb GIT binary patch literal 644 zcmV-~0(at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@lo$u3 z(QMAte|k7_BtjOi?zd|ZSs{Q$$r|6vP>mijhzRRIB;Vv0$jr}g;G!2PV~ao@IdaMe zR~&gnYMFLOpdidTM=LrjpzWgq@Vv!4=vKX^^ZW;lmot#k^C8HmeXg6m4GptnvtzSk evtzSkBRf~Fon~_K74*LV00003}) literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ddb29f94be1c069b8343ea4e17bc992cea7c80e1 GIT binary patch literal 635 zcmV->0)+jEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=K~#7F?UmsTf-n$;-w_94G#Nm^3D5~d96&~Lgib=e zi$voO4oZKNg!>Xm6YlP{4KEKc_72Sz_`IyRtdKi_z%xJL&9^&P}N|y9zNX*tZKu+F#jST|%^@tl31%1eg z?MF96;S0@*>J5DClNEEPnCc!a*uzlx`v+n?A0+C!uWoW18WzVE#}>yH#}>y%a^8b} VY$_%x9zOs8002ovPDHLkV1h526mkFn literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-center-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..005eb69115b14d7b42c47e48ebd32a7e5bf066b2 GIT binary patch literal 585 zcmV-P0=E5$P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?IS&Ul}1hYgHjWW z_9PJaD6h~Ia4v)77+av;8ruL1S%7vEYF)Pw3zQ`0iVdiBUjda$;(Ijq`UC9J#aEo6 zl*DYPB|n&U11xx^;!3?hOA7u*mrimy``D(@J#Lat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3y+yDRo M07*qoM6N<$g4g0F-T(jq literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b944da93211fc507b705ac356253f87899069325 GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?32yT?rp{lB* z6f~7OlO$R4ms2yiGp80o5M0}~E#L!Je_|0fj^hlDFgNRRsWW_e3}E5OH~A9`%-0)+jEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=K~#7F?bJ;Uf-n#T;5RJPV|X+T5LZELUQU2$ zj}XK&tVUaSG4&CqVx;8~u5691HPs2;9zS6C`l3EU$Nqc+#KrwRzbxSDRYS1ff`pqI?2t8=q_Z%(P=)6yPR;EptHWD3<9c{sG;at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?{`_uzCIx@rJQ5<0R26zMT1j@$f z4hL~$V#XtQg6IDQVsM}@9TXG#OCD`PU)#KX5GjhHEFI%BNRlLlI9Y20lF=ArimIw^ zoY9*2;70^5p>9de4(AYt;j?Yq`;^g!^MK&#pq}fx&PhNV$Id>(D>xt5DZ3T#hW73w z4L-i(E1fTauk+stpnjc`sAon(Mt2&{&ewzm#04iGno5itMeaX4hHiYKD0)B*s2?jy z;Ewv~DM?|_RjjL6SMlr#e2gI)$I=f#f4t+){sPJi5TIf;S|_dE00000NkvXXu0mjf DEX^n{ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d39c6a9891eb93efdfb0efa08ff4fe9be69aedd8 GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hCV<|0 zWRx5^c7!ql6NFbaLg5fcK0uN1C%LKAXUA&tOr$7^^6#ul0_R*4LO9{ICK&^wv({cY z(T4koeiK|01mIOq78*5y0x;63alVT#0oSM^>8u&Or z-@rIM;DnZhBsl}8D_z14afS`8^d2B5t&xSb;bb4!=uY!Rsz}C2vwM0{7<3ftDArND pcmr=X#IXhX0@&xZ@8W+zc>?>nQ!*SL=*0j4002ovPDHLkV1k2tAI1Ox literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9411aed36b5ff4abb4add68cb7c9c0e6b355772a GIT binary patch literal 676 zcmV;V0$crwP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)ht$rBt;fG0qw zqvZsTp;Rh)3{H0KHAG=#U2-QezhY-6J0JgSG6M*LApAS@DZpFTLnzfVS08p9O!;Zt z+$`{|0B;p^OvoH5a1`|~?ak!fyUS)1h0w-mJ-W7bLs;N0gCP+Ol%qrAz7^oGRWvGz zv2C7kd*=9D94{aPeqO*SIf_wj0889w&Vh^LryvS?&@@IWsLPFFfyso5j{8ERd^XeI z8@B{IPEdLjx3)6~46=%470W8lUBJr}c&n;L2E@(nqi^m%Alw0(>{&Cl0>)JU0000< KMNUMnLSTXjPbW+O literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8653c805c81dd23f26d221cc33e97c17f096b157 GIT binary patch literal 644 zcmV-~0(at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4vh2k2n#S<7>H>S72D z>^a^mj$CqrB_c>GPHe4c-GO>Ym05rsU-2@r?B2Zv9dkhGD7Mm3{0&;bQy0YiZy(!~ ey1c#bfVu&Tzi`M@&BUSr0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kFE2PP;?Pat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!HXUjP6A07*qoM6N<$g0|Nf;{X5v literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a4917601f3e4f6398f3c732bacb788ee345911a4 GIT binary patch literal 658 zcmV;D0&V??P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kK@jZEE%5I{=!4g;5?KAhDEVO su|@Ih20l)K#4Te2+Hp3Y%)SH09X|S0hpcM9BLDyZ07*qoM6N<$fat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?TEfY|VqzBlf zbc2r2O-zylf&(sT4ne|CN)#!!V;z&3Hn_SAgZUrNbDD8RnR(H5x@KzHHV=2yN3&|nUC!|VoT@=g8%iTU{kMmO~> zR|w=KXOQA#6|`Iuat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?l~%%%z&1U3cz!UchD_+P3P$YhP7gA#ny_m2k=q_Dfb&M?6951J literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4ecfef78dc47cfbedda464b459a7e1f95972131c GIT binary patch literal 633 zcmV-<0*3vGP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~r!cD^2 zMxyZth2wr43H=htCA59Ll2^bm3}f%mT!7EZioK#HEZJ^|wmK{i;x T$E4h}00000NkvXXu0mjfvDp)v literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexend-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0a5f8a2ee803f963a5a3a374659a8d29d7b5be92 GIT binary patch literal 577 zcmV-H0>1r;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!Y~kqe**(hQf35tL6uv<+edVp;r_mMp zq$+RtS6%_WK*0OPM z3b6kIq5S(oMMy#k7lOH@0QxKH7~3MVvPRT4qigcKk7qOER?MxKTQS2hOy%4F9@0;6 TqcVr800000NkvXXu0mjfK7%QN literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d36af20302d65184ca627e599da5d430bdaab6a2 GIT binary patch literal 662 zcmV;H0%`q;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ID94x+F=>3_X21tZ+8u$$-h=(;ZOOoX3oU73Wy8V$$DWzeB wNXWLjm*O+pB7Z?295CETDV9at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?V;X4t?#^O`{3Y(I@TzoyJxqq$(BsTd#m5z$ZXD zbL-;1gfDL&!kIH8?hwf}2GJHlP=s`N{CCP%U^CtUkH}oYzT$UWWYBuf1s5z-YN3jm z8O9hI6L{g;wl8Y|pMc7zW=swUfy^AN?JU(n6(=X9Nxp(F*5@U~7t}`ng4PodDHbUf c1VLzkC&}YfiKF}q3jhEB07*qoM6N<$g2>4jV*mgE literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cf192c48c32b08f9ebd879780e1c46a782f5e83e GIT binary patch literal 674 zcmV;T0$u%yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?GFr1H1uv0;RLG zhl5yBQR5LjLHu`yani6cIwQ`w-%Qvr*<_P_5&b*H{mHV-(idpk_Gx!PzYKfi6R*6o ze|8V(1;h&&V+NLpV@ZKHdpb#PDJ@!SYltI8g##;k13aRZ)+1@L@B3?-rZ-Guj5UQB z9v}{=`7%FUKExD8$MJ8P<{~LY9^*S0<`}Lh9L||-k|cM|r70y}6%^x? zlc}Nr#;Pgd1wP|6rRQrz8~%hEclY>0r>$69v9@AGQIy$v0BP4*a%avgq5uE@07*qo IM6N<$f*2at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?b;Oaj+s0B4Zy%v6%WFkeT z@`=9m32*~>4MfRO4O$ZzVyBw3u8wp`C-6p)G)Ez57M@!xN=QiN%yn!lNqX3qm@vVPYWaVwGn#hMT zQj&6Z?;WQwz}|XOBAN(G`YOz9K<@(*jbt;uJmHaQTwNVoF70000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DU<1koFiM$# zZU85s41tLesyNVuG*XLHKPgJ0#If^ZIl$1N&q;b?Mh6^Xs{KazXGD<@RerJWT>%Zi z8h}aFv-C;DD|k}d5K7p6G&8+$#t}9MfEe>)MEj<7s{+NCayft;xA^MVsAt;J=3EiT zwIR9lf*#1sZ~{L{^L$&^6WEjR$}=YH5Wp)BV#?8mwBn#GC&*v0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Z0e3m_Fh z8y@wID`XP++%>zo_EDPDgK-oYk%)ZwIgIeSLqsuN@QNjwl@HM v4lowo&oU2x^C>ht8^tz?Z4?`ZVT{fb1d&-IdRLt<00000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)t1>oPo<%{<|!U`B;-g$TM%djFfs(j+VxdK{%SO6l< zyoL~ZC}iO?N&8STI_Ekn;tCaz|EX!3N6IcLV67cF0A#)*k$8?Vo~7gpgSibfNLrG! zBRLOH#zcO%+%FIdpiVwg;yYBpeZakxvhOp_?Q6YIkO2yy6Eu(lJv|&_gm2KhVDkcW g6zeEf6h&EsCo-#Oe9?c?TL1t607*qoM6N<$f*=7I+5i9m literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-flexstart-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7a3ca2709a85bfbb777a6316ca43a4de8bc08e8c GIT binary patch literal 664 zcmV;J0%!e+P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?8 z^!}1^T_TcE%uUm+wMhcE3_1dXlg;E1#qfMftEtoqT*x&5?tH=0)%SI-JRH y(tvsjB>BeQW0SwdB%01zv9)4r#fD)Ri*pAzz*^`%%QD*l0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?tUx>p2kivu zz!K;rW;r-q2(CLSGvqt$z~pDM$(vnZ?oj{dUNYkctYdoZyTFuj9SP~mJMn+-fE6%S zKat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?E$;;pV5rOWaS(E&NE;E_yVYP zkaJuikf)AZ_sS(l9wWI-2Skt%X4?y$8`oXRQm>^NfM*wyVSHeawtNaXOGW~7+E6#sUVftQdAoye!<>?J_Jzf iV67O|iVeds{>Tkmlu-cu^)2K80000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?UmaN!Y~X)uMvZEG&%rnm;ji700Y2CjF3qh zY=nTH#DoZ_RG*J3Rjwbk-2|9A^!gH;F5(AJI6UIcFlMA8HC1`X{_hpA1e63Q$dmiH zMj=ldy5w|}cd~RW*`bQqQaGMdyV(k`p=U{}eMQQegRgSI4S_TP4^z)FCo2>oZ5#Gl z3zQ*r3wCls6}LI?sogoU4E=qvZ=&iVedszRwka WvQ@e7K-m8P0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mINYiLh� zzC@!BM@k_D{;tb^MBxFQO5Z)cOd=SSRFdZ?<|r;Hf}@y-=vF%>g4#|z SDGM|J0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3($wB!i(#!3(15xfC5Vj=}g zp(qw=N9jc@O)Ncv9>Ei=!}^m@uw)x4n6F@mF!P3xw>tr7I#jp|)*AmHUH^n<$Ntm>R2U6`|m)HZRtAwzS%JLB$Ku-7G;8!If_fu^BDcJpgtwu;*3rA*JBN z=S(A`QHp&RP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?eivg&r>ND;PQ^#}#q-naf z*6w&2!H<$Uak|e^&|G@RnppFcQw#XBq*g%?+}pM-&at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5T?4+g_#r^_~K$*tSPSu=Cwh%GX99~T?O(1i1WH% z-PiEt6GO$=X b&q#R!Hx6*aa^RyV00000NkvXXu0mjf-}W5U literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5bba3ade3da99667b5bee594285ad31e3de62174 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?1M5sNJeLjshXyFaZY>UgI^K2hIu48CyYxR$KSs1-*Zj}ZU+R5{RRZ^&tpcas zBuPFnBN|mL2|Um!-kKCeVbE@<-B7!scEi=to00MZHGz6{^2q8X00000NkvXXu0mjf Dly@ia literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..06196c9ca934f386fef381f7dffd29dd763f4a6e GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-}ml;_|a zyFP@NsG|!rLiPMQ?w@w}wE*Yfjg-q41+WB7AH&ls>)zHz6ZueWNm4GJgUcKS*n4kI zL^EMYUzwQ&=$lZYm29TT6JBYItMe;;3i1kwlBFJWW-!D~V?v#uz6k?w0!d30g2uW@ zsA(c0g4?y$Yu;5ey2@<8j0i$5;=y?XhG8_Y8nPO)8nPOe4*!gpH|WQ5!|i6;9{>OV M07*qoM6N<$f=pj1+yDRo literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..03a8a8e3658dfecc6d06f537ae8bd2ced94c7006 GIT binary patch literal 649 zcmV;40(Sk0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?U%s~!Y~X)zdJ?Y#3XG;fe9!Rzy_2FV3aTc z-2hHN83N-VRB?cWq*6K5Pl}RAaqKwxvH}bpdY|N1X7s>5rPgnPp+mj}*^TFPM=8Sz z!l;R{F(cX`Hh|*7QzmTD0dcS}DOHFeZ}?yzrUbG=AlAm(N;@K!*9Otb_{IM3DsToM z_jj^=*6^&9Wk)fg}S`D3O jHS7behFT5vXQVs;dliW>YoC%q00000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?t_a%t|vEKwgB5RrpzD z=N~>z&TjH7Cat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#q3u380XP9TfjEKg(>7rQ zHmUC=#_)&M(nNl6PeK|(?}O{Txs+({sQHWcKGGjB#(d)*Xz!@p1{_PHlxky)Cn{rv z-9u~rqO}Qx5Y7nvqzYhvwbl+x-;WvN=Cj`5q^AO$b3H21;b9*Gt$|fhql{ndH&;P2 z0hDjz6}`|=Av2pXwJ+I(IL8)A+^GWCUs6g)R)D*g9Z=>k76MPKfSe2kL6B)E(@>_N fOvBBQo00GaKN5`XDb|aI00000NkvXXu0mjfe8(M@ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..52e79d95b2a07c3ea8e71a0b2aaae4a6d57aadc0 GIT binary patch literal 660 zcmV;F0&D$=P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PLCGEC4_InHc{f-)loIT@uL$lWj|DQ2 ziAM$vmYQ2a7p7!$5XlukAVt&{*at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?U%s~!Y~X)zY&8l3f%+_lw->TEfY|VvIH`oi5}{Ah!VwiqS#+nfTcsz#j|F{AK0e!K6izsLq3D9=1lUE%XEVf z2)!iqnxyp5%@o?2cVciy1agT}a-{0h{#tXEQpvz$kh26S5kPz6Qv8cC22kM_oGN0J z@s0oND)3!ka6{K{fj}lcy=JEuVZ%8wE{H(hf3GP)eSzdal?&h`g>Z&Z0Uj9|hGE^% jx}kML>xQ#qKO^G>1*w9GOk+bL00000NkvXXu0mjf@SYv? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..50ed803012eea12e75211667931f3b2c98426d09 GIT binary patch literal 645 zcmV;00($+4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?vK6Il^d| za6aDXioO$AFL+6e3*so`%c=rC>OOPD`kc3wIQXY*_qYtWz7-e+vA6*5$ z2|V;At0)o3$48Q^aoLe4NG{C@5hR3F48y9SRYR+W fRt-nTZbrrv-k)l5ED0tF00000NkvXXu0mjfZF&~4 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceAround-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..64c3f60d1ab77b62b8d14eafb98a2ee95cd79819 GIT binary patch literal 636 zcmV-?0)zdDP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?U&6BgD?z*pHT;4v@$?}PCz?BX*)m}sUu_( zQd>nW7aT$)INat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_CDx?w+|!3hRa|6h;;b}DZhg>kcu5gEP!^FHXcW#J|SdCV4D(5t3^ zPA&15SHaN+{{FEfz6jdI{LsrU5c5W4aIJ)yafO)*5Rr=NhN}rdR5xs-ZrHMkdv`;< ajAQ|l5P82A4t{I^0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}|Baqq58nB{L8a6ab+DsBoJocV2F$$^Me&TpIq1(Su zERR+#xFAgTBCNt47=~dO3!>Cwvh?X(A3-S(Ze-+>Vjb>nMs_V2$3sf4&+;bRX^|cb z(CJ-`rW9aTL!tcphl-Gd5-tRDNddGZ>loW2v$6|G+l;Qs^FE%CmR3& literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ebb5288a7a4c4b896a77fb767fad04ecf62aaef GIT binary patch literal 659 zcmV;E0&M+>P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hlBZ70T&hz}Dlq#q@MH&s2 z4K2QhAP9mGLA6aFQCWr%SQ84Q!6LMa=>QYe0urM+HT;%OkPd6dEX%U1_r69KX!l1> tsYs41Bto{;JtaG%E0Plq!U6di2{&M~J&Sk|TF(Fg002ovPDHLkV1k3B9Jc@f literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cea680bc0dd97582ae759b7606f3f804dad7cbb1 GIT binary patch literal 641 zcmV-{0)G98P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?F8F literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..034a3ae13c9a19848cbfd9b5461037cb52b8ce9e GIT binary patch literal 677 zcmV;W0$TlvP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G44&4WtP4`+qTcR3;JcaBA-;{ zmHD$*KobxXFvbjQv5zGM;>_tJzoj&2t*v2>XcZQ$=ne1?wKN_{gMHs$(=@%I8>6i$ zEbstxz&n2?MNt$*!1x^UJTGAO(1n=7=vW7urnyK?ktg^Lf%#j$qHtI{wn>uQSyQH* zd}>&XT^5y!0vOe^L=||A)0Cg@K(gUWXmEFqZ|n3(HhTj4XQVs;VLwSU)?p*-00000 LNkvXXu0mjfSb{Ft literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6479f8af98641e581562aea137879e08d3973d22 GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&XN|KnHq+5|pk8uovza{5L0bH%h#lby<-P2d9bJCL?t(Dat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?b;Oaj+s0BJsBG*DiFvv2zlVx*2P%utUIEp_iet^sG~4OGb*1+WB-Z~em}D{pJn zL_X9&MN-c0z2g)H*jsN(L=$02Uxk?l^z(p3BiT$ZPk5vnS69a)S?LD&XT&@K^_4|y Tm}(Q>00000NkvXXu0mjfsQxC? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d35f2b38410efe90fee4d693a5a369c00dc11cfe GIT binary patch literal 647 zcmV;20(kw2P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DU<1koFiM$# zZU85s41uu`syNV;G!h`yPl}Q#aqN6Wi39Wat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=)tDbl#is;utZQbMonu+$bhb*o(`4B zT`AMv0QBat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|C3Rr7L4gi@`Bofat#p& z6fL#Yj@s%0%9zOSmTSdg0W{H$l=u!6@I2s|lCtkJ&h2ZxP>=x%ph-HA0zG{kV}x(e gJK-h@(3g?&1TZOB5abf5`Tzg`07*qoM6N<$g3RU}G5`Po literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cd0766b32dcdbe7642b706d9bcba8b04f871fecd GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZJ}L5+K#zAxh*&94oRDVD8X(aj%*21=cCO_FdqgaT$rp$~*Qy&wvHs z3!ryH*KmPAMm7&kk2GQ1a88U9B9I%nO;Wl|$<+)bJF1)m2~$1A1ijq3~> zpF&r2CgnJn=?Wo8`Ib_A_LXA28P&WIg)1T$`oW&6Dfv<}mZxLp+L<^xijxunv==VL nz8HJ}6+Xeat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?E49o$S_h$vqJ(IVX{8av9&*>EbFya12F#L9dyfH6>{!4j^ij~3CwdY zq$%Z8F+>~<6ZTtUD-H%Q9r2hL2c%JHO=;^K1Qa38i~H+Jj4Tm>R8p1KlB_mre1o3} edl7)&jGQayphKS9g2Xxi00000)+jEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=K~#7F?U(Hh!XOZa-!l%<(d+=WIDtBWr~~Loj=&_v zJ7d&8a3YCq(tCb1G`#o0k#GRa9s2xOCwgwlBtATT!R~~!NWfl3#vRM* VMp7(}0TuuN002ovPDHLkV1hud89o32 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-spaceBetween-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a79d997f8aab9eea30ad17033bdd031412641aec GIT binary patch literal 580 zcmV-K0=xZ*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?s|m)Msxxz!cg51 S;|Em$0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}V{ z_-mq!6v;}4@juT13t#~(AVq)(;>L7_&}F8;&**fo5TZq16MBSX6RfNq7zH9V!gPAH1O}vRLvI-_G{(cmIv}@z(PBWGXpds_ z>HPOUb*igC$fT4&JGpV+!nQ+X!M2;Y)v0vFjJ(Kv)vum?r}TLGw$@ Rr~Lo`002ovPDHLkV1msjD{24$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c732bfbc01966a123e1535d0d0ddaf6d2d5a4269 GIT binary patch literal 681 zcmV;a0#^NrP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?nhJ^x>C<*r^M}gzGzt^T|iRO-IKKQ<`=?7$4_Q@-0%G4DZ zQ-fhT#djn8v?T04CuM&5cF?@!K>_lQ#d- z6pUVn=rzHPWm%q;QU&$EbzR%CtO#*&RaG%wCG-uvA7BA2U={-SWW>Ayw|Yw4S=P3Q P00000NkvXXu0mjf4U#Pr literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..049185174138c466fa07007ebf428a3b697aad54 GIT binary patch literal 668 zcmV;N0%QG&P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3D5!2r8&fU6VX36RZA zcOdCwI65)=2)L8fzljXxG!n0&Gq2tdPjh0?uhmx2m(c4peTyZeHZl4=!{Is z%8>YG*&V|Taao?{7aA)7mApeSooNDy-P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?OKWYJ%;n5N(K|8Pmy?TVHfS-bvi%~?52%M|GKgQ=b_f1-B?`fL8c)Ox4 z5l2NkQuqamha}{{5^gxihFT-;H9Tkq<8SCIfWbQsR}5pzJZ0Nts0+TWBs=-cL=`$f tKdF?o?&)JC`k?;ND@Q4RnA002ovPDHLkV1h^SAh-Yk literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c883c2247983b37dd0ec3c2feb6b7a0fe7b2f469 GIT binary patch literal 684 zcmV;d0#p5oP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&%}Sc0wO>Jh=42s`(*l`HGJg6S~b07rCW|P$e3iQd@v1A2at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3(V9Mzj0SbB zE6@@s0Xwh*IVthP(UapqjPW1~N}?vrcY*!OyqSI3>;g@Po*R>d8DC)6qet8p{+X;I zb*fTj{m(0)0#twsFba_4D$c%k!YMcnq>`Oy3a(^O*#z;yRD9sb%n=wCsat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?b{{{FpQT43s!?gQ1#_yV*s@Baq)XIe+bxZ>0Q z=MJa<6`%rK0&eYvP8?$(SVe z&r#6QH1L2f9O8~x`lsSvDz7Shg6;=YfC`v|06iHgPmU~3l$ByZHUIzs07*qoM6N<$ Ef_jT0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_laD)yJh<6~;Kl#vr3cUxy5w4eedza7#VD5~o+@>t{dzxO$1AP_Kl`?Nat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hrI#_Th`Kth{$za9KDxg$+n zsnY)E4yXVXpaNV1uK8)i+a+o;;+JN#KYat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O{}AJuQY=9_&<-?Fu0REZ3V@@; z1WTX;v;#}91kN5Dhl_Gy0ZG(^c?Za{v+SRl-N`O6b*R}mXUzBlOP5~rTKH$`h>VF! zpYcDBfC^9nDxgcit$vgT_A!u4#$NLuZOlxaOh}0lOW};Apu`vezu%F`&KLn_Pl<>K z(BVZ3mDIq%ap?rb0CgFZM_$P~@FbZFY1-%u;VLOeyHa2jP-eUlgB&AZ3u|XbMO(jd z7s%?bJ%@M_VUEPvQiUFrIor6ym+>Jz5Xz?lpP=Uf6`%qpAwX|N$`gOVSSCi|vTXnW N002ovPDHLkV1gM{Cz1dF literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d2e9916be51e163a05f6bceeb32420d8fcf89f45 GIT binary patch literal 668 zcmV;N0%QG&P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ID&x-coe;Xo&a5lOL1p# zA)Y{wz)`#ah9j_Y>DVU3xM_Ei$M42S>`AOc(hYW-4kd4V@sN1W)A+JBfJo3RaifCm9#zN_eLwA-B3nq8=3>FR}n zM*G@=3mS4YNMoL;Mv2-|#;O{kI~OJ#_l_a33RuNFBgP3n5Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?> z&`}&ABXokq7qH@=CaD1xdLJ}2BzO0C%|Qc<9eJO)a^vs?#GGGs3;Z+QksMc2;(zXd z3Qz$mAR<7FA6>bwFc9|t_W5c;`y`yi7nUQka4RvFTiH(DnJE{LV(_klm|}2N~@4xj`#oo002ovPDHLkV1h)_9PI!A literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignContent-row-stretch-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..73d4f84643424bf0dac960866ff7ff8894ed86dd GIT binary patch literal 594 zcmV-Y0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?9d;(bYlAIIxSn-uuF;`ks6FDTT0U*gNe!0AqX_6{%r12DiXfPHr6@@YiW$}iT~e7x*A?Ki=fw0MbuSRvvmSq`xM}Gr=D9e g1291L06ZDd3hXCVsYXfPYybcN07*qoM6N<$f}`;OaR2}S literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6bfe6cf96e240e8e4fa2504f172e5ddd8c32ffd9 GIT binary patch literal 897 zcmV-{1AhF8P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?aL17Zcxf$0D)0&+1P zBiO5h>~d}Q3eKzK-YH!2tNy|>Bk>@f3Xc4iiU5+(jS5Q?H7*7?)Z zs|X%$VkiIxML}>22|cTk_)ri(A>eHm*oJ~AMxY;hoIzc$=6uwY>`(*F3m_zg&(XO~yslH>sNm zu*}V8bJ2{r4&s~sP19^X582kszH2^vfS?jp^@KW<$ib!$bcY0o#M40fF8-&q#4q6s XD5i{cSU9vG00000NkvXXu0mjf8h(wP literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b507fe17446969582a7b4e8ee83f31abfc63575e GIT binary patch literal 890 zcmV-=1BLvFP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?({&LW%d2h)evWWykg`^E{siL>)T(cLd~#IF6&!>7>~1 z^?F&J=LLBnBu^X;hva-dzw+Ae_e=7GHvvF3Mi2xKaIaY%U)(8Nog!2UrsrjYcua?4#B%m(P#KV=AU{(S#eaN27Knv_Ao%?|kZM070IH zj4WWS0|>~oA6dGWyWQ^A#?gwvWHMRct={SbLGaw>i~dN&Z>BfuPp~Qhg3rZd;dyHF zMg6BdszM|q1B^|`vyW{lmn)OMHX*T%CKw55vro|awaFhoDM>Tp?9$|KB%n!eYV$+G zJ~)%h<=o`oNat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Uj!7ev3B!i#tn=LykCR8P+_Vk?v7%uk^7)|Q(yEOB4)<&%Wr zb=QU=79mhaP0UZfqnR>{!(b*r);@Xho_v<>Pjh8>7>N)aO#oM=mmGgWWHVYydmZ#( zfMEzk^NAp~IGkfMHP^&Z1oVRjlG=CqLqBrB7T9 z%#EtShX(q6pudf3zpm-M!nk~<nX0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?t$76$&_vEw0NLfb#2qF+g z(T&UtOq;q+y%s5vWm%de$s5EJV<74mj1swUmFIb>SWX{-ZnvB9<~Z?oy)ILoFiLq<}Yp$z;;EwU1RP={HIiL3a&Y#j2KZ19Xa;TGNq*+w}0000< KMNUMnLSTa8vXpKB literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9b3485e212fe55c12c47e500083c1e8047149854 GIT binary patch literal 806 zcmV+>1KIqEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?N-rI!!QgLJqE}KVS{dfJ3-liYycZ1Y`_L2 z6VOaRMqmRnLN|bCcy4^T6w7YYpXS~9WLY}vS(TKEELd>uxRFFuRh2^+svY!R60nkV zlvr0>;}vNg|R6Al(Kcr@F_=cy<{Az$0ai)sD`h5M6|LX$J9yW#xv)AM%%p zJJ|OT*Cl1(fx&wOv(?`*ct%?kQV6(Iciveuvdu$a)ccKR+EE(*MDq~vg7-|lBWCwK z)n|!7EP;};ov^u#+{+vU@XECez5hDlQd63knQ$w5xM^oAzC@5IAHN$qIWqx6X#*4i zU)v3;T2Kulyw<+xo$5=#-POs)FVthuW?)Nc2T%2%Bh0o44T*FTK(Gke`vuiT!f+k3 z*31M=7Z`89Q~1|16k`!`)(|*+`7|FI`g~H|hWuB7%W@eq(25?ePz~=`a1@6*fK+|U k1%Y_Ku}}F^y5KDM0WJbv1~shPO8@`>07*qoM6N<$g3(N5BLDyZ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e44790c11bba56b95516ac8161a5834792a411db GIT binary patch literal 940 zcmV;d15^BoP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?P_ix^YC-y#%#K( zN@S2_0FgZl(iJgoMY62UkU@G9*40cK`r)KmLHy!gHeveaZX2WdITp<(WxHe#XoE@) zcb2d3-Zt&M8wg?0MpZ~8Jp@GF)eLHPX0Q7-P7Xto0aE+!;`{$W0ZVJ-5}R=r08i6Nk+Tp4}l@4`&pBdquY2}B#9>*^Sx_KS``{<}W0 z_Nuo8WlB$,gw7yj8@##^nHM>ntjTDJbez8X3vsfIRY+js;1wB8w8J|EGRYKY2( zs76%WysnhBwf_UtAVEq1~Q-{jg70uNEhg2VI}AEk^eq z!Poxa@{sBKp}s;G$1y!&)PSM(1*2^O~_ugzqBS zB7`p2fZf*XlJ6FgF!(YE<@EErIS%aMcOTGS7K}&4oYwyA{EyND55zA?BdmZO;g*m9 O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2@;V^fXJU7OyV4gNFu=Dm)!J?AyDvtX2-TefS)?Eo6p1- z?sb>kSR|s8P`*({A6S5p3BrllT;PG5LcC+32BL^rFFpb*jP>T+%Q^FP_A7S{=<-}7 zq6zS6UHFw76Q7t@=KhO7x%T<)=YB%q&bi11Wr#p*1f*?E_}!rHb28<|=;8tqh$6rt zp6b?Res$7c!w3-wCLo__h~L`3UgI)zt}&Xh7wU+8Ry#7if@^*{T2f`&T7{_)GS#3E zfM6XMz0v|M0?jBMk3=uTF^GU%(wMdX);vJC+T`o=ghi^HsC5Xvf>X2T&ujN`lOsn; zC!w@N6dKT&gu3?m^b=!HsrGBYBwd9JLo^|z3Z(C?yx`R1fUCht^I`LMLL-5a^v*(F zG^!_bB|MpD?bRg{s7No?h))eli7M?HEo$L)fXj!lMX*qrz0<#nTl^8e0cJ6c#ju4- QNB{r;07*qoM6N<$g3w->0ssI2 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..aa3d88fc14bc3cbeb083ee46029ccaa43a54f6ec GIT binary patch literal 869 zcmV-r1DgDaP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#1E#UaN}4p<91L^)GGKzV1*%DxjYxL&XtZvCt*rNHIW<+IFpdIKj!YlVtnqlR@de!0IBd}L^EKA($*eLi^gq07IPz>m_awiKT#2%D(7 vH22V=2DT26d=&Nwc_z%>fB7hFu@ig)v}beUO9q)F00000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?J1`W;~5d~tq-FA-0qhdRb z%gI1^YdmtCFvQ2YJqe3B$HF_lkENL(GU=>!DW%()D2Hk(iL7%S)K zEkigPGM9Co3D8IB<@_I8d^sDOwBS^T*6TH&=#gz~epkC-6lt9dO`%r7DFRq@B;n`6 zb4&GPS%gZ6WMqL=gq-_2dzJ_Y?F`u%>n_fI}b8~h4h0f=P8chl>> Q%m4rY07*qoM6N<$f=v97MgRZ+ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bc37ded5964116db7e8ad496084ee1d772f7c92e GIT binary patch literal 908 zcmV;719SX|P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xkgtV@u+5!EZ*hD{Du)v!5pe4I2D+D0t$KqPB(( zMQBO%6m?)`pS%6?{W*_jEK|d_=wIw zSg`YA8h9*a8WM|3T>{uqZ@`YmHO4XxR=r?FM8`BAZjfJ_?X1SU=o2BSa-)6)s|;*F z1CcWOcj_#vvgOkBr4OihE$hor+k`UvFexX~=~c*gZv%B~I6+$&gs(dPcr5Ge_mRgi z)cgcJuCuQVphUf~%|jzLZ2Mp?AJo}b22iG69<3ED!8Bbo>Xw=>+GtRL9S?MAM)*VA it7+l;8$YEDeg-c=zLy!OV|`oz0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Ge0 zFTU^P9-$gqaDX*|Xvnw7wco(&k--MjjERK7p(b3}8p_+})h?wq`tg|Y1Bpxxtkn?X zoCL5dy@6cREix3cN)1-IU{#2sF?VQ#cQuw+4+;+?lP6N7_7n9KtUMr>-(>^&?DpuT z$Tl8vOXYz{*cc@!O+u}GWG+9@{t58LD1>oqQxnQnu+zTE{&}hWwN^uxj28b1r3Cg$ z@6_f)qiqNu`q`QZoiBld(z`w`KBpi89hiYC%}rD&z_t#=LuOnMVUP6PzxgSxa29+4 X8zhT315*xJ00000NkvXXu0mjfO{I&$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..419a97a8738d59704e9e2186b1593aa82415a977 GIT binary patch literal 924 zcmV;N17rM&P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xt#Zi?z!Sg?HZTSC+EK-kda=Q z$|#_&Z*~z3pGAlaNMwX0`Z3`~9}~2Yk?an@zP+K1jAU}4cSLo*li8Ygqo)xbKTsv&Tg*4=>x=`HbFwo+_WH8|yhlMr<))Z|(3?d@fX zxy}at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?H&8dI zE+9-`nLtKx0~vt@Bwms$U|%IaYWt6T-s4BYz2uwA-34G`;=dyhh)gyKJyLE~qTbdB zAVM(m0cc=CiRIRubv=Y8%++ap8e zY?=Dhgey2B_tmaZo{-65@ss>bWkaj7p@IV*0=oUD31numRoUPa3r>YdCbzVr=#86C z7ITi1XgLhj-*EImyfQ8pRCt~r$1G`U7A947z*ewe4MNWS%(U79R@(j9Fn6g5E?JQF zukp@q9_Q#wb7r%45YV4|E(eXV5g$DK%4R<*;Gp!Da7J*T>Y9*XVuY>^$mCAqf{6M> g&wa{I>BOJ#4G?jELPG>W(EtDd07*qoM6N<$g5aKm3;+NC literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-baseline-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..81c0fd69973e496a5c805d5be522e14230844f13 GIT binary patch literal 744 zcmVP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?clKsEq3a07G% zCy-5W1Kl8|cSQnMZ7Gx=`|f%@lF+nCNC8MB{v82`{4*J_?#iy8@7iGLO*uu|rZS}{mi*!CXY`reLTeDXLXhD4at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?{n-H~?d1%B{hVgV{w zbZ^oEbQ@Y1g^05`TVmE!sLbj#ibNfpC- zB{O8WJs{oe?bgOFK#->gN-l|z+?^%Qvm!|16yzvCUF`Mojx$NOk27VafrM{DnDGMU zw$beJqFgKmKZbU!s>v1FHCQ1tM!BbyV%lHfEquerD6HbJekCX^`+I=XuLPxK{}d4V zm0-0T>Vcqs#R5nzM->MO2at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4RWY)+hv5it0=NPvKn$%q za-42-XlKIQE}S4Z1tbRSI0`>fl}~a~DOTzzey=J(z=JeRwF&TG0)HkH5V<60S+>zy zZ}D+Kq|_LPwr!6fWGYR>W?SJ@V$7JdImR-M<7?md6?_sr{mFEEp68mvtUZ)*mhLOQ zf~VY?rU6T#!;IG;+B>Mgr2u7yqA19Om$e#%xb%RL-(Hx$mP%19!>;S9BuOq&6fNK` zw|6Lv9lpGTUoeV~k+lZ|_DdnMWwr-|_DkV!%M$zbwPp4Sr1r}kV3;{u4pwX{K$(HF zUka%$+j_voekoX6W@RX}UkU}^w&n0&Fp2^KH&8#jy{`ZNt^fc407*qoM6N<$f{d;_ A%>V!Z literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..629900c57d6b804d23640cee7e8b3aac535e821b GIT binary patch literal 705 zcmV;y0zUnTP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?k74MR^AndadqJx$8__WT0XN9XQ~p zI(&@mGhoFpn_7frvjG?UvK4%=EWocXmMt@2$1f)-mII2-1_b!!B*n6M3!L!FmM~)3 n+yM!G*}C7ra`-Q(gMpw2k7>ELo7HOv00000NkvXXu0mjfXoNeI literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8971310f786b5ea1dd0abcc6dd2604631c847b93 GIT binary patch literal 724 zcmV;_0xSKAP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O2lW7!mekOA6bqpC26zQepmdbh zz(FjjsPPD%0B52F1+)7JK_l6htV_ZqGqN*}K;)P}6h)mZn!t*Fj4Qw!6CB5J%G;^y zI$sH?Jat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=aT|%N?q5D+A9IX zc;Fz1)_fdpAR~~p1u+9yIfiFEiFjb3Cy*Eu)?629^3lkrg@D&k){0H`ptr&Hip+8u zUfG6z!6IHp!6*jeR|AS=uLr>R)qr9-v<1QV)j(r8at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?Uy|cfPXEofxlG0dt6p2wR^#tMpEYt(2 zot>5n2Crc!4T+t23`4Rjn^@4yG6c{__9gsfzbsSCJOY5G0ETM`c|ZXg@MClVEKk@t z_ou+QliZp}BuKX0#zX%AWfx$$y>SxXQ?d=tX0MUIfif{X>n1yX86E|OT>DJMgSs!h z2LyEGW!|yTNNUZ5(hI1FzbYV-r&V}D1F5wDh|s6N>p39UnwDl0>L@mW2>0&S=Aiuq z#?0igg~TG@ViDVy9ejgYe2g-CfS_Ltl9rVPYgQ{iq6y(w``U<6%l`1Cc7o&PD>;HmU6rgznP>R0aoP#_u00000NkvXXu0mjf DD?L7% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f1ebf1946057aa26584eec79e2de2826d8f80759 GIT binary patch literal 678 zcmV;X0$KfuP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NXQ@K{q68~YOVJ9@PM`uUg%T*i zKaEAO9{%s$EEqK8CL!Tt*d6X}9|6dkp#4*IxG+HleykioJm%d?E9r3#x20j}MA5Ws zx#8OZ4i7!5;L3PI(M!9Mn(@+Gpam-03*O700mT-)O4gXCfDRB2)}8eRbH`fw73k5h zR&jXg0PRNVFykkQyxp)$pAmF$V3HQ`F-nqat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&OV0)W((omuO?r}^2KX9)P6KXA={3;6fFIKf7)|&xC7UPwly65N67ukFXYP1+ zfxOrb`EsMe51ifJT$w081qPPR4t$m`kgx&I$Oii^&=iP@Y+!?$Md-mpXXyfNJ8!Ea z%3l}fEvWE76RY?cEt-(fuLPy#VgZ$YB^Iat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?jiqJ_T?Bysr;wWsfyp`X&N_i*Q}no|Cvpp~)3Ojv|4;D;2R>5Z?PQhY2*!9I ziA{WrOcMh7)qu1dOdv+T8kUv|<6%?38mN}78Zh;%foeIcIG6yUUky~t!6J;&uZE@N o;0hr64NUxdE$9D&O(c+c0(&oodwQ)+p8x;=07*qoM6N<$g6$qQO#lD@ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3f947786eac6a765004c398e9e6d4ccaf20898ec GIT binary patch literal 667 zcmV;M0%ZM(P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NXRU-1{FQ370;Bq+-n^Au$ z;VN-G3%I-4yQqZROGx;bY#upw2tcKPR!{o5P{0O%rV5B9ywh_hcpd$16BsrtWO~SO z0|_nA>bUpuE0gsS{ZobulckS9ARV7oI!g=qUE6}EVS{xGECSAuo!Ow_CDaKtLT71# zyNrIV^dRx4a|-P(Jy66dK1RtVOx15>FjdP@0ZaXcNY!%m2rTs*o)NF*sDQD4Lo~=0 z_yvm>a42Wa7O>TCaLSY|K-O=F@7HquFIa^@V|t002ovPDHLkV1l#n BB{2X1 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8dc838685e766513d91eed12293559117776c158 GIT binary patch literal 666 zcmV;L0%iS)P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Qi`wBlk9s@h;!8TmV))2|dm)c{|} z-vb0{kFN&M=vSOk&~g?4)UTA~wcP&;RsqoS0$CSQL4@gm;{X5v07*qoM6N<$f`l3) AiU0rr literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0d80d7479b03cb55218dc97f774419ce9766ea8a GIT binary patch literal 710 zcmV;%0y+JOP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Xu!_{S`Z#s4bTTg zXn^Qs%=Hs5duPsMg=8~dV(i0B?%CNp-)4bK1?Fw%^oI&G@Mm%WNhw~m-Pr$4{6lXU zC1)on))zV8+W}@BHxP$CSw3A|Wy=&cLE@Y1-J>@G`s4DN(+)Tmk4vqf0;J49R~M`K zJKT#FNb)I232@Wp^^8l=8BqLWpFu(op+{S9w8^`Xg$N3e&^w^Vsv#I6aCh?DrRg%k z1C^-7%P49>LcbQ2mV*Hj^=lE-a_|%|`n6!S9Giitel1unXBEc++;ln8Ui-jmIi_M- szZNkq2X}zcui5w)TF&1EwFr>813m*i_@% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f14e0ba359f11a29b4471cffd2143b6be97ab515 GIT binary patch literal 707 zcmV;!0zCbRP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Ier8r5tq2Ws!mj@6yIyw&MctXv8FwykOb@L6x!T|r>OCeQfq*3VCjp}O zm!`u@^lQwyfyv4(G;(k4Cu(MO$+aST2cEVnN_ur}m%IgA_y!j7F$(rTIDS!TRxAtp z;W6=xvXHU70un>zFKSCC;3w$IXj$PnPywMH2*)o5W-R9@4hUexF9v2T2V4*nzbFeC p%j6F5;uoKtJeKo+!6F1?JOGk(gKdY+UW5Pu002ovPDHLkV1f?GF_ZuR literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-center-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..25b8dd5a933ea0abd595a741e0c43f831c7ae576 GIT binary patch literal 628 zcmV-)0*n2LP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%U$W+fo{c>=?-uwBPRF=5ooPM zKY9}WCS?enAu<#oLJEHLGG;(zAbfWhj!*v{2V*#YYQZ`fe0qAC_&P40JJ)fA(zv+* zM`tOJ7?=gxi7S*C7#eB$#3+{1;G0CSU4HygDGs_xd)&@ZU O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?{lla(|pqlSv{1=PW18VvwBgp>{9 z#6`vS*e()Vkk^6nx(9iSbCPSC5aOUN-q050bwJ30ek?m}1l^YPNRXZp9#8sJpN(JR z+&j=TNr>bo)_KMnwz!`HW&z@=_v{~A3DYbl)HGONj-eVaV5cvdUbzT!_6=SKHuD%Y z(Fg2b_egBIG(u$e0AEDWEKz%cFZm-C7b};-fr`s1m%@RHODLDZm5K|MOBUc&?52QX z>N5RLoQ^g`a}T3-H_l^fGA!ai&CI00000NkvXXu0mjf_LMqz literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f608f31e39c359d4bc4bd7737bacba6609c06e5c GIT binary patch literal 688 zcmV;h0#E&kP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?LA{Uf<> zc7HNk0|^JZR6Ef_Uorw|vvo`N05DdjD2hO1`rg2gu>!WBq%6xr2%*8(j7jNnT!vw| zEd^C4fX%eW#m|w&i5-q>p63mu26um_j&9pFa8PXQ{Kr^yx?6zr)9#?IYc^*V%a-DH z3$z7zdURdKCd^{}Qrv+8Y$odLlQ6xat2i|vzQ5L1od8ZkSFm!<^^r7>at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?9}^0gKuY?Ep(p_%G7nIt zz7*I`&!((w1=8yhpq!t)f#y0+*xV9RR=5J=Sic#ukiSGaa002ovPDHLkV1gmII_&@e literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..96b820914bbae621c34218aa06375f54b6191158 GIT binary patch literal 696 zcmV;p0!RIcP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?RnP3V*1zWH4>A42{dp`?>O3zDDz{gs?iX)VZ(5pC7xd^?AW0Z?XrQ)~BMPwBxDIi9at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?SZ)>_-)&x$EoFed!& zb0{f#1GwoGn~#y^#0BGtwOuGFeFH5mP18VK*TDj%6lkq|?f99Oo&kC~wz(h9QHAp5 z7Dxv$w772^gwB9t3FW1SaKd;{leb2(+7;4kNT>P+%+omx#+~zkSVV5)8GhtADo#)? zhg`*p%H_zS;!Wjpat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? zK$k*{@hEI$%{@q{tvW;?)`2T{+#*hMgMl|#ZjL3mA2 z^|&XxQ9W)}16-~Sat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O{}7wd)0RL5N-0_a*a=jirBDJT zc#~KJ<6`2C(H&<+N%kcq5Po((8+ZVTnc4Ns zbe_6t+JWNAdq2E>F?=Lv!l~%FLhJ&Zp$yJqI%|6e7`Yat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?odDdRZeS#=E__ zja?Mof%GyR(&Cqi#WUM9S9gycvat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?T)AScW*_mM&EM2eX1N<0G;0Qu+KkFn(8f$INOqo#c z%Cfw>L{SCCaXjJBdV&)L>bJh{8~LxEDNmb3Rnf2+irDf4-|Cc zf^W3krRymWC4l=n(@1;F@up2KUDSlem=2S;Qlru3gN~x>y{H0JRkgVA8JMqo2A=V> zTsR-toxl4T1@}OJ<#NcaIM8xAq_@m`=s1-*^AjEPxqFC`amdhcs;tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?H(g!^QM4y01ajzzy{QI&<@}> zmIH)6Qx+BON5@z?pGI%R_V00#T8F{Ptn{p*oRP3W%2^AHGC|B+yLB)Z}l_(G! y;FruMfJHj-Dh^Yw*h{>MJ(VkwRs4}0AoBoz)KY~zsAYlx0000u_KKD literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..19dd92df411f68e0bcf5efb4841f8a6176bfe8bc GIT binary patch literal 663 zcmV;I0%-k-P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?B2?C_Z4b!PMWhQPFOY!E7Z@Y515y`YLK~cg zKWi#bo~e<6Pwrcvh>hZbtLA~lS>4YlSjAtJtC2#*LCV!gq2d_j#*PuT2jY~gQDAm~ xAF`POBkasqag1`+F)S($RIWx=@g%uG<_#}NRzq&o(>wqG002ovPDHLkV1nV*Bme*a literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f935084667614b20574c2915c847efbb298e8bf1 GIT binary patch literal 700 zcmV;t0z>_YP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|; zp+mTUhE2{Z!i#C)k`nZxU%~M9{QwvvvrU|%t9_5)$5;XrP_j#0=5M**)L5AE za0un`iB~SDs=#LI7GAjM5GPV}aPf_ob3s)F{D*1vFk1o4Gk(tf3~(#!N19Q5$F)6> z(jbYq$u-1W+)jZufr^G^k6EY(2=u3ci))V|NuNlh6_P*%HceFp4lgVsge3^8tA#&R zTJHrP7@fcS83p%1faOZ)tvJwfCG=JtV!0ASS#huBN|+T7l|V&9m*q+fWyQgkE1|OD i5X%*X&5C=l1dKP1wqHNy=ov8p0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?SQ^UIL_$`~^@JCfGxWZFsNX$7ld65Q6vV0E~~Lw1;^B^sVX6 z*OXOs0>Sz%b`8HddDR%iCD^@BS%oLiJL>!fz^&6R%^je<;lQ|8u%AeCpr$9cIR*E& z*_2tUKp24OsG~b(Xa-xXhB4A4Y;oZeC0cB=zGFlufVGWTUG2E98@#X-kDLxH&foov zvU6Zwaybe}ah~L|vr9;EhU9V-lHz&EUd)53RRHF00000NkvXXu0mjft28!; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexEnd-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..194a94aaba5f964214481fd19807153a887cd217 GIT binary patch literal 617 zcmV-v0+#)WP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;V%b6o7z&q=5(u z!USXw(!l_Xz$6&k3RJ!b+X95-C)tT~mhN)#Js|L8x)yqUnHGLbD4@+oW_b*V1VVI} z6IU5KV7Dycfw=>d%@E>VG$dDaL3ETCH-QJ{4v>h|V-@w04tmBTX>~z%I;&T8wtyqt z9q8&LOmZEIUa<~52vfimKsUA5|JX=Y)iILO-~ls+a=d`Ox@c-OLi(&T<_>HZ1zI!$ z8orKnm&VBbJiv=6pOat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)wtrL? z=kh1?F42a8Gr|#TA}_&^oWMc2X9P%$6h&dE!O9%q&!hy7T%at=i!r9bZpOUQV|xt4 z@B#tO6Tr)O#>MY5ixVeo&pgi?h=E-NxcfKt+qN|v6dT8UK!EcEaDLhy)OF1cv|<^= zPGC(on}DWA*LCbbE7pSmHFc&7h-Ia)PdEFvaE?k+ip~?j38@4trPSQ+G`6eM13z~A zF_Ng5!%NW;6?23s+E>M~6dkN$4qrtl6$h)B!&lKURLrqR(GnGNXb4es`Y+gR0*Nn@ WRK+*t_6bh_0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?^ra-aaGr|d#~Fu zs6aH=df-J@e?|%wOSmaop<)R)MSH7Q!d21UDi#xPRCG|Ww~8fP6|GmX#FvWpSFwb* fqQkkMs|f^diY;~JVfX?v00000NkvXXu0mjf0=zIV literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0a0ff215f2f3c4ebfb105ad4651395b203187cf2 GIT binary patch literal 686 zcmV;f0#W^mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?uv>w7o;%t23diYem2R;fpdzvx5BM;D ztzw3kqGMFd@KSWJiW$C&4puS4SJ6qu!766>Dmq%ljCU0stYSyt6&{LCDozO`o-Brf U{Z1vpd;kCd07*qoM6N<$f@(%9lK=n! literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..42bab9d1bb34f092b8a3611adc9b1f655467423e GIT binary patch literal 679 zcmV;Y0$BZtP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$f9Q{-Uo^+CyBe{HpqaTK&_9es!*2YZo)K8nCE%R?U4wZ0o@%fzBT75kb&I- z*1)O{|BrXk8SpH~fDPdwanmACg%HS1hFwFQ>I=fVTP3c!9-t!f3y=6Pf30Fhl%jJ~ z%!pESvWgk8icVHBBUaI-;$#&wVio-k6(g|5OLA1qSP`LUQ?WH*JOCq8W&eI3uap1) N002ovPDHLkV1jU9Ed>Ao literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4b21470279af68e06ce751b6ebcefac8776e5684 GIT binary patch literal 705 zcmV;y0zUnTP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?X`sd36Wi?P1M zC>t_Vw_7-3?g6P+2Qv7}SQ`xdE}#;~^+~^Dil?y@42UL_5v17M8ZC?8JVHcZV5~qf zKC7;lbBM~-wyQg{TOjnOkt&Hj*2O)6z!~H3R^`xtC+%8(O$*QDyFbi^cPf2 n@tLAIDyDE#wEr)tZ33PvS=M%IFUG8D00000NkvXXu0mjf{Khko literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-flexStart-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..80f0cacc9e54c00d4fea4e7ac13e75324fa6fa3b GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?j7a1)q7M_~j; z@J-?noNZ!!>X9o)^nrd!6A~`HpC-Thrf#?ZTPd@wR?M(AP$%I=qa)Y%4aDf_1{Me{#)dBpjCGat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?L*32RM&PY=T!xaAEA#iEiB9qD`O4pxf{1WHZ%||U3w;Dpw)$w zdqP3>4bU*2srY@Oc;Z0o5ni!H?FQh`K%PM!n|(Y-{O(SQhXOkVTmvKI3{b!gVFx)S zv9boj(WN7J!SwD%ym8ff;9qpBA0v&5If@jmQ87o6qV+1~GmCQ6P%(#>1euC!sF*{f q=o%{K5arOQm}8!z?Z05N4HzFM#7E=jc@-W20000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?c@beSmL zm1TK{0&51waXeAeIwofdir@OaZ=k@M0UEgGHceAxS!R83o@Xq}0?GpSZ4ro60|not z$-iPb6vR_tT>$OtgInHXiI3O>1=b>5*R`WXT)EKra=}Lt3alBZs;Z@d&v3jQXNgYB zMeBh#yZsnxR4n18XpM>`yc8X*VhLYG2dh}ZSJ6?$!77&URkT{g62B@sSjCQs!xSC= d3wFDJ$Pat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? z$Q{&BM6EKwo!W2&c}KrzH!yf_^}v_KUPj3(mWWk!vWg{Q6>V0rgjUfxR4h?wid@Ax uR4k!VbOsem=oD>Hu|%4p{avuw0L}|pwo-*`OQahB0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O#5xfF7(S>foo4`^wdK2^p z9D$pR)5N%9%(Tpdzk2h|SI{*TJh2MAvWI~5$1F3at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_XJP^)>B1&6g*}wEDNat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=$DrO`qx~Mo`#f(Hn|3Jlz?-VUiF(Xsa<-cID2^5|`U}EX5 S5rO#t0000JP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=nqI5wSmc8aWENx29R~Q$tjhy%2^PFUc%4dYUhp!x&W&qK*0_!I>7gZ z@Ow575im%$fCYHL&J#Oe0Uog9`Ie(w(C*7d8%kIO{{@)Esa4DvQ?&jC)u&>HZ$G*K z9u+f8iVjgR9d1x`syIT$43nZGRE&@rx&`gNrDD4Mbwts9fLUY<4iAvL0b3Cg>BJ~w QhyVZp07*qoM6N<$f^9bpQUCw| literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe953534088f7db93f122495b1dc303b646003f0 GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@WTox-ah?EwMhfUSBhw-QbPBCQ z_;E2Bdu$gK7vwuIUJsyeWedrP2udBy;H6xU?|{+?y_RtgS-%S(vigktc%o0zEMMcU z8Hns<&*WAkerkkVT(-bbfV$GN`FCFAb)%uoHZVBW(5wxxqXDAR3d(A}!FOOYFA=CA zz*qfQV%yCT3f>3YMpVq`LWM6QRxDO5RxDO5RxDO51qgQ`%WV0Vr=6()0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?UXSNgD?z5ou~(4jgp~9YS%2#lawr3%aK^J zbCc9YRH`CpKmoD%Ngn|gv2o%LAZ%D`GYL+n%%kCAq<~v3;GFAo&I8_d(8i1kDW!=E zvK_!f^1$Td0m+Fw>SK%at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Q{)`nc_A1#e0dWdOj3B6y zM}=ZiYpULX?7RfH3{URhxx^8hORA}!4n&C@!gdiMmk1$0-LaDZliZ1NsC#C>RgK`} zgF9kPw=K{MAa32O|964B?;tdqt`A`+YeP7=0m?s6L=RJ?ebzg$pUSj$tLF}fL1@9e y_W6L{h>DpzP~*#(6`K{C6`K{C6`K`X0mcKi;B>oj8E3Kp0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7K7*!!g!=xJ*u-{z3IslR|N z0N-mROK;bTO^${0OG7xJ`O*Nat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!tQ?8Y zebGd92l(SFC!c?iT)1#NdCf@^tsNL;@ZOVij(W&BQz_-W=DgRf9+0ZLlMC__jX~3K z3#9CynHOe1O&7CIPMF{~I? h3@e5e!-`P=cmW8mYWat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?6Ldywq9YbXqvEzC-6=1U;J3o|dn@Bn7OtG3D&8U73#nA-&JzKf&k}N` zB7K{Ub$SPsaSi9@qZ&S?^Iu>y(3z9@cCLKXXeiyXger#;m-hm-?k0w!IrWsBK!2$9 zwyF~Z?fOePNOiX5fHjEvpf)cQm>7;?j$)2tj$)2tj$$^zya3X5c=tS()(`*y002ov JPDHLkV1jGSD`@}# literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f8bda0c1ee6e8b970b05c03e91f03596688cdc33 GIT binary patch literal 631 zcmV--0*L*IP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?jZ3Hpf<-hhXjvJrVy|MaVy|MaVy|KsaGr9;Q4d-d Rhq?d&002ovPDHLkV1f*>5*q*j literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e74ef5bd2ea56895f1cf6c04e787092e74725611 GIT binary patch literal 621 zcmV-z0+RiSP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?S(i%0W4$ zgjB+^MmZr{GRo$2m?y1d$+Gv!p8?2(??qx^VSf8m*cb{NaufGn8oj7ihc)IgXa#?E zU1~CU0{TcU+WcYAJaW`}`j@mQ6@WtnYpV2~X#x3KTT`Q0U`2K-Fv6Yz#R3ii_Jm>q ze{%5)UXii>lM!#+aygI^gg<%vkiW$X>Vn#8em;&Sj=T${X0Z`T700000NkvXX Hu0mjf9NP>y literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..616cff521a6aee41d859ad2407f00107d17ce2ee GIT binary patch literal 661 zcmV;G0&4wat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NVWsk+6NkSKypHdaXwn>i6hw#pue4^eIiA z#ArEQu7E87=e3cg*_Gla#>(;R5{3|FEaFWIMDGaDDRTeW4h+Mf(BTQ0s{c&9;Z?nI vI*=8j-C==~AyO<-EK)2|EK)2|ECmR@m&%5jR1at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?eZ+z&cf^QwNpzN5i{*X~1`&14jgQ%yE7dkAAMX^P(MX^P(MX^P(2^bH*QBo-}m&*at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O_BY1`0L>Ibky-8Wh#@?iQ zgC3zb8Hc1R0|^OKyZA35At5k7z&wDgyu4}{*qHA+2mBcZIHnffUORiJ-lh#o5X|=C zuD!_^TaMnqat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=M@S+On0et_~KyJO~sm6^w}_%oV7CmHCUJYWLf(1dvaQ!?Xa zs99}2c-YYq+k+QxJtc9??htBLp#qaHN7w>>gC^n~NH@9|_8I49sR#P9w+3gz$A_z# zbqa(8%vg@{ca6li51xi4QWGY6a4rqR>nE_!CDjVh%u=`7y_EHLa5eKu(t%EX7Wu(| ol~E~HDOM>~DOM>~Db@s(C#gYWJGC_kIsgCw07*qoM6N<$f(+vu#Q*>R literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-column-stretch-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..81e37cfc5725ef3688e63dd5098854f272d75bbf GIT binary patch literal 604 zcmV-i0;BzjP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?R00$f$;3xddxDXikvvIcmja;ITEPR%~j; q{RI~AQ7f+IpgBRt=co$03y2jx$wAP61;a)F0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?aL17Zcxf$0D)0&+1P zBiO5h>~d}Q3eKzK-YH!2tNy|>Bk>@f3Xc4iiU5+(jS5Q?H7*7?)Z zs|X%$VkiIxML}>22|cTk_)ri(A>eHm*oJ~AMxY;hoIzc$=6uwY>`(*F3m_zg&(XO~yslH>sNm zu*}V8bJ2{r4&s~sP19^X582kszH2^vfS?jp^@KW<$ib!$bcY0o#M40fF8-&q#4q6s XD5i{cSU9vG00000NkvXXu0mjf8h(wP literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b507fe17446969582a7b4e8ee83f31abfc63575e GIT binary patch literal 890 zcmV-=1BLvFP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?({&LW%d2h)evWWykg`^E{siL>)T(cLd~#IF6&!>7>~1 z^?F&J=LLBnBu^X;hva-dzw+Ae_e=7GHvvF3Mi2xKaIaY%U)(8Nog!2UrsrjYcua?4#B%m(P#KV=AU{(S#eaN27Knv_Ao%?|kZM070IH zj4WWS0|>~oA6dGWyWQ^A#?gwvWHMRct={SbLGaw>i~dN&Z>BfuPp~Qhg3rZd;dyHF zMg6BdszM|q1B^|`vyW{lmn)OMHX*T%CKw55vro|awaFhoDM>Tp?9$|KB%n!eYV$+G zJ~)%h<=o`oNat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Uj!7ev3B!i#tn=LykCR8P+_Vk?v7%uk^7)|Q(yEOB4)<&%Wr zb=QU=79mhaP0UZfqnR>{!(b*r);@Xho_v<>Pjh8>7>N)aO#oM=mmGgWWHVYydmZ#( zfMEzk^NAp~IGkfMHP^&Z1oVRjlG=CqLqBrB7T9 z%#EtShX(q6pudf3zpm-M!nk~<nX0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?t$76$&_vEw0NLfb#2qF+g z(T&UtOq;q+y%s5vWm%de$s5EJV<74mj1swUmFIb>SWX{-ZnvB9<~Z?oy)ILoFiLq<}Yp$z;;EwU1RP={HIiL3a&Y#j2KZ19Xa;TGNq*+w}0000< KMNUMnLSTa8vXpKB literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9b3485e212fe55c12c47e500083c1e8047149854 GIT binary patch literal 806 zcmV+>1KIqEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?N-rI!!QgLJqE}KVS{dfJ3-liYycZ1Y`_L2 z6VOaRMqmRnLN|bCcy4^T6w7YYpXS~9WLY}vS(TKEELd>uxRFFuRh2^+svY!R60nkV zlvr0>;}vNg|R6Al(Kcr@F_=cy<{Az$0ai)sD`h5M6|LX$J9yW#xv)AM%%p zJJ|OT*Cl1(fx&wOv(?`*ct%?kQV6(Iciveuvdu$a)ccKR+EE(*MDq~vg7-|lBWCwK z)n|!7EP;};ov^u#+{+vU@XECez5hDlQd63knQ$w5xM^oAzC@5IAHN$qIWqx6X#*4i zU)v3;T2Kulyw<+xo$5=#-POs)FVthuW?)Nc2T%2%Bh0o44T*FTK(Gke`vuiT!f+k3 z*31M=7Z`89Q~1|16k`!`)(|*+`7|FI`g~H|hWuB7%W@eq(25?ePz~=`a1@6*fK+|U k1%Y_Ku}}F^y5KDM0WJbv1~shPO8@`>07*qoM6N<$g3(N5BLDyZ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e44790c11bba56b95516ac8161a5834792a411db GIT binary patch literal 940 zcmV;d15^BoP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?P_ix^YC-y#%#K( zN@S2_0FgZl(iJgoMY62UkU@G9*40cK`r)KmLHy!gHeveaZX2WdITp<(WxHe#XoE@) zcb2d3-Zt&M8wg?0MpZ~8Jp@GF)eLHPX0Q7-P7Xto0aE+!;`{$W0ZVJ-5}R=r08i6Nk+Tp4}l@4`&pBdquY2}B#9>*^Sx_KS``{<}W0 z_Nuo8WlB$,gw7yj8@##^nHM>ntjTDJbez8X3vsfIRY+js;1wB8w8J|EGRYKY2( zs76%WysnhBwf_UtAVEq1~Q-{jg70uNEhg2VI}AEk^eq z!Poxa@{sBKp}s;G$1y!&)PSM(1*2^O~_ugzqBS zB7`p2fZf*XlJ6FgF!(YE<@EErIS%aMcOTGS7K}&4oYwyA{EyND55zA?BdmZO;g*m9 O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2@;V^fXJU7OyV4gNFu=Dm)!J?AyDvtX2-TefS)?Eo6p1- z?sb>kSR|s8P`*({A6S5p3BrllT;PG5LcC+32BL^rFFpb*jP>T+%Q^FP_A7S{=<-}7 zq6zS6UHFw76Q7t@=KhO7x%T<)=YB%q&bi11Wr#p*1f*?E_}!rHb28<|=;8tqh$6rt zp6b?Res$7c!w3-wCLo__h~L`3UgI)zt}&Xh7wU+8Ry#7if@^*{T2f`&T7{_)GS#3E zfM6XMz0v|M0?jBMk3=uTF^GU%(wMdX);vJC+T`o=ghi^HsC5Xvf>X2T&ujN`lOsn; zC!w@N6dKT&gu3?m^b=!HsrGBYBwd9JLo^|z3Z(C?yx`R1fUCht^I`LMLL-5a^v*(F zG^!_bB|MpD?bRg{s7No?h))eli7M?HEo$L)fXj!lMX*qrz0<#nTl^8e0cJ6c#ju4- QNB{r;07*qoM6N<$g3w->0ssI2 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..aa3d88fc14bc3cbeb083ee46029ccaa43a54f6ec GIT binary patch literal 869 zcmV-r1DgDaP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#1E#UaN}4p<91L^)GGKzV1*%DxjYxL&XtZvCt*rNHIW<+IFpdIKj!YlVtnqlR@de!0IBd}L^EKA($*eLi^gq07IPz>m_awiKT#2%D(7 vH22V=2DT26d=&Nwc_z%>fB7hFu@ig)v}beUO9q)F00000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?J1`W;~5d~tq-FA-0qhdRb z%gI1^YdmtCFvQ2YJqe3B$HF_lkENL(GU=>!DW%()D2Hk(iL7%S)K zEkigPGM9Co3D8IB<@_I8d^sDOwBS^T*6TH&=#gz~epkC-6lt9dO`%r7DFRq@B;n`6 zb4&GPS%gZ6WMqL=gq-_2dzJ_Y?F`u%>n_fI}b8~h4h0f=P8chl>> Q%m4rY07*qoM6N<$f=v97MgRZ+ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bc37ded5964116db7e8ad496084ee1d772f7c92e GIT binary patch literal 908 zcmV;719SX|P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xkgtV@u+5!EZ*hD{Du)v!5pe4I2D+D0t$KqPB(( zMQBO%6m?)`pS%6?{W*_jEK|d_=wIw zSg`YA8h9*a8WM|3T>{uqZ@`YmHO4XxR=r?FM8`BAZjfJ_?X1SU=o2BSa-)6)s|;*F z1CcWOcj_#vvgOkBr4OihE$hor+k`UvFexX~=~c*gZv%B~I6+$&gs(dPcr5Ge_mRgi z)cgcJuCuQVphUf~%|jzLZ2Mp?AJo}b22iG69<3ED!8Bbo>Xw=>+GtRL9S?MAM)*VA it7+l;8$YEDeg-c=zLy!OV|`oz0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Ge0 zFTU^P9-$gqaDX*|Xvnw7wco(&k--MjjERK7p(b3}8p_+})h?wq`tg|Y1Bpxxtkn?X zoCL5dy@6cREix3cN)1-IU{#2sF?VQ#cQuw+4+;+?lP6N7_7n9KtUMr>-(>^&?DpuT z$Tl8vOXYz{*cc@!O+u}GWG+9@{t58LD1>oqQxnQnu+zTE{&}hWwN^uxj28b1r3Cg$ z@6_f)qiqNu`q`QZoiBld(z`w`KBpi89hiYC%}rD&z_t#=LuOnMVUP6PzxgSxa29+4 X8zhT315*xJ00000NkvXXu0mjfO{I&$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..419a97a8738d59704e9e2186b1593aa82415a977 GIT binary patch literal 924 zcmV;N17rM&P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xt#Zi?z!Sg?HZTSC+EK-kda=Q z$|#_&Z*~z3pGAlaNMwX0`Z3`~9}~2Yk?an@zP+K1jAU}4cSLo*li8Ygqo)xbKTsv&Tg*4=>x=`HbFwo+_WH8|yhlMr<))Z|(3?d@fX zxy}at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?H&8dI zE+9-`nLtKx0~vt@Bwms$U|%IaYWt6T-s4BYz2uwA-34G`;=dyhh)gyKJyLE~qTbdB zAVM(m0cc=CiRIRubv=Y8%++ap8e zY?=Dhgey2B_tmaZo{-65@ss>bWkaj7p@IV*0=oUD31numRoUPa3r>YdCbzVr=#86C z7ITi1XgLhj-*EImyfQ8pRCt~r$1G`U7A947z*ewe4MNWS%(U79R@(j9Fn6g5E?JQF zukp@q9_Q#wb7r%45YV4|E(eXV5g$DK%4R<*;Gp!Da7J*T>Y9*XVuY>^$mCAqf{6M> g&wa{I>BOJ#4G?jELPG>W(EtDd07*qoM6N<$g5aKm3;+NC literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-baseline-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..81c0fd69973e496a5c805d5be522e14230844f13 GIT binary patch literal 744 zcmVP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?clKsEq3a07G% zCy-5W1Kl8|cSQnMZ7Gx=`|f%@lF+nCNC8MB{v82`{4*J_?#iy8@7iGLO*uu|rZS}{mi*!CXY`reLTeDXLXhD4at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4T87|?%d`)O z0fY!QM&D)s9=GG%v}_M9xVS!*&KI(EpjkQ~I>FKL7ha#<{#&{a7m(=lXA(!4_PXWp zboqkh@tK=!&tM%ueOV8c!wu)EA9q&)geDh($)IEv-+yM(YYx1VA7BE{n+a07*qo IM6N<$f`<}Xl>h($ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6fb693630cd7de1d51cfd4b1e23a3cd663f95efb GIT binary patch literal 768 zcmV+b1ONPqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@mFwx50ai~1HBLJa5slHn=_ly&SY!lJOBs0FRTWZEKC)% yavo^gb{mG_FCJG!hckerfj;1TLk@@IQTYe9MVI#dJ;~hw0000n2` literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..09723d4f30c34e8b850f1c079ec424ed138b9688 GIT binary patch literal 758 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?GkQHWZuzL3!1_6m_4J|sVq9iQ#N3qf=UbZmS7~ z?N`+5K>YClG^Xk}@goMeW7I~R&JeG;|MtmcM3#PA7Mdy@SopZGiV+JB+P@7X>9#Sv z`O{Vds&NS`kN1sdX6|g6B3bp|0o?&KBdPoM&1`2y5qaweMX1*S*(qQOgE=L+gL)k} z4Xs@(KS-6RqT|lZ59I|#z`Z8N?5@zMGS}hk5zrkVUdreB{cEp#ClluIKuaCj*w>CQ zGS;ARoXB9Bzyo>&UL<*Jy7|-l17Qia$>pC6cY2c5LJp#Fl94HrQL>(Cs(#Y(lg$f6 oBYgsOwTSt-1y}XE0)c?TH#3};A$u}CUH||907*qoM6N<$g7HLEr2qf` literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d1cc63895d165da95d5f1b1e8f7f0f9538fb6c GIT binary patch literal 758 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Eg` znVH7GK@5qA^$4B-yOpuVDQ0wZsxX+Z3g+3>J%86c0FTErF##NrW!apHMc?<4)ZGR_ zP}X(5)!BW(jq_h}yr$}xGW1Q~PaMa`uIqMVwx4hSIiC-KAkXt_e^phW)q_;v@xnR) z3t4CUlbwq;2cX#B5E`7bti_1&jQTcdnl9h~tpcyeYC~uk)5iH{EbH81I6?$rg9up!i_o^zg|k*^6rXQ~;0iO1hl92l%c}lH@?u o2$wg2aJ;8tN$Fg}at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Xqthpw%SscfgEXz)>Vn=YpQU(ekilXKvMUm%u?cc&S0gJLuWoV1n z38@6aE{&keA!Vib_C>IW9q3=d0j3J{E~^cJ!Pi+v5C>Y<@2ov z{Zs`Wy5c9Zt7B}w)fv13rUXhE)Rt?IZKx>V08<~>(KaI364m`*W9o#`WEOayX-Qj~ zPBz>%07*qoM6N<$fat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?I2YhY|Tg;l=d+gyMP$OV?ZREyGll>6^BH)KZ8HX@z0%o=R3y+uvjbyhJhj6mzxMU zkFn`hhSz8!DT6$PT{_?{26wpBOegPgHvYQJr?oOL0b>zW_m?4j`}uF7KEZn;(oSt! zw{2M6#kHWCjH;Yu!%bZV%UWC72yDX2`BX7ZTmgvL>GLoK1L#xmkFc6?K+sOnfs1f! zxYGAvrw;51M>ga^>Oz+}s;)eg#}fhdH)*pwIj4)R%E2ShP`#bV%+q?b-`&8mcc5;Duur(uy~Xnc~cT? z(q-m3&IU21ORvF3x`_3`06hD6?fd7S_+NPH literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9eae3f761eb384e5a20a974da8ae004ad362719b GIT binary patch literal 682 zcmV;b0#*HqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O{}6i+Jy8NSpp>E&fSo`ES_*VP z2YQoO1mi-YF@#+qJAj9MC&FhlfBv#NfWzTf7=jS{C&yGHQIEmb>yj8*zM(6oG!Q-b z$b<{@Mb5cTX`kjn0QL|Yb?Eh#Vcqap86nIBIzgL26RRqo_ACyYxTA^_2%t4!6RU^; zn^$wAd~Y19NSc!{L~O7iu$2-EYct Q_y7O^07*qoM6N<$f=10JZU6uP literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a37dad5853bef7e16c8c67222ebbad45e34dc6ae GIT binary patch literal 670 zcmV;P0%84$P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(JvtouH;_d0S|~oA}b@n#H~@80&;zse%)^MQOcvJ;ZuNY)LEY@ z>w*Wa@+69}QUVSHGP0i7>pKw4wpC#dniN)T7J6HC^J3)TzF8&jDhC7h5jfb&Bf!B{ z9sz;)e1>}F3IWkCvFW`X2ZqdXat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?E7SJlNM^+R36`NL80Rs#8a57U0@Q34Ih{+yxZ5+pA3HTocWJHoJ zr;~e3)~cMYfHnZUW^WorA(@zcw_pKn9Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? z2~^@5b#xpw3&;W<@?Bu&<>%$?Bnvnkj+r4S;qfsbTtf4^dRx3=P*zf0U`zu(CmXX= zZqtp4=uC0?Ol`ZsYsjo@f;E9#tY-7HIr*^}=N=zIC}1@(Bvusz zLt<4iFcq(B=<}X2AtmkZd;d=YO}ZrVJVl?eO=eF(GEhUN!k7lkJTrD!dqGJ_VLk=gsUbg1)^aIz!{5uLVqmIrIUJ5rxB^GWP6fzn-at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z8=s`S!oxo8p(h1rD zCD6&bFzPsHRxsh`knhCIBiYB>kOe#*&&&`UamzVoAd$!5ZTE^9Sr}1)F%6VC?_{Hk zNf#5R@JQ)5Z3PDqA^uliE9?5l%Gf|BFbT#4npmZH`mtDwHF1|`PT&Be0h?Hz7_f=e zje&`H{f5_Ej@E>1BWi0eCxI?~5_x{bkaxSxo`7bchE9bs4KN{tf@H4h)&{}@rBYat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ux6!3Ose_Um@%NT$KUvHO_TTs__c|4vaX_xgldjbFe002ov JPDHLkV1h3PI~V`} literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-center-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d749bdd922ebc52fecb7109a7c80b5138912fa89 GIT binary patch literal 726 zcmV;{0xA88P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?wDz$JNHVt%(XVH@dGpsTFfub_?z+GKKz&9Yrj z?ojZRga;fY_*_;`31CWhF{{6o)icMy3H*e(>{LHe5BiL0`j$WC|0vL0CSAU+9Mi|Q z$><6=5?~oM$+7-gmCt5F`kvTs%JrgWTc{K0YPEllRe{^#5iMW8)F?xTO9~IfE+flS zs+$yVp`at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0gfI*Q&|xdx4t86iGUy<5G6aE;Fv2)M z#N{XD3y>!!2jHB03X;D#0;j4tzR0aBLfs!Z4KvjQY+-FH4Uj6Ot%mxW0+`!ssJ|GX zPy(!`E~3KMm!96euni!#R|9 phjD&iNY&D}M=iqp{4VF*<+KRm!5N*tsRsZ6002ovPDHLkV1nzU2U-9C literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2daa71609faec53f1a3954a365e4cd9b769712d1 GIT binary patch literal 726 zcmV;{0xA88P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@pID!j^yo_02o1NLn>?-n`+1tO2|Z&a*GQ zCt=Sq>8w<4NtmE9sEXhV(Mo@eWWZPj`O+1K?a|LQ1rsn{qes^%qE{|>-M!5o?s`W} z8lU;OCSZn~4EPdU+Ky*uRgR_-&?fc-f;FJ2>@cWTfRxQ|vyb3JPAGecX1@*ts8`?z zWrrb11KP?ql|Ure1Z)BU39vKWA0_AEZXPxh8MXS8{u|FDS+ma(CF8b?9eWj6?$E|&pP0=rng9R*07*qo IM6N<$f)5f#F8}}l literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f33356070747b21d1f6facfd5fa7a60599e9b294 GIT binary patch literal 727 zcmV;|0x127P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?i!0iy_Gpc^H4Nij6h#DMfunz*2o?kZ6Ct1K(VnutgG>Php)yGl zXb@MHI1P=lbeNgh1uWYh_FdUskbVJL*%3r=j%ZnkY7U`zp;rukHQo>wj|ZseC8 zb=`+C1>op6T!4t+TQH`8sZauxfHnacUBWP|R0@9Fvuy?GW`v1|63q$Z?0Giq(zcHD zJdo#kWSZs+6OskreVvn`9r1+{E>{0*#002ov JPDHLkV1f*4JW>Dv literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8b5a7f79dc07617a6acc2682a99600b443bde187 GIT binary patch literal 705 zcmV;y0zUnTP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?oHP1Ff+ z4jn=^kS$cAo;{*iNNNJ1;6uNpC2fzpKkab^uvjdXnh_`qH*z3o3_?$FAINTpReKMk z0^G|GX!zQ7K@%*yTNuNQPH=DJ9qy#UW1g4otb4VAQlLKf^FcE;tBiXvE1)>F3uygZ zEtuJP(C z6!K$ne59t6u|QDBHXBB_fT=7rLTsQ{I7+Hv9@`B19a!`I{T#hZui^_KNZ#+N!#uYC n#`g&L$DvAAoj7*wUxDQX>7H)Y4rA`g00000NkvXXu0mjfiJCU; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7b347e5e987fba9d04f0bb8d1f68d7988e21c04e GIT binary patch literal 709 zcmV;$0y_PPP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?c8nj;aD~~e(6qy69|Xa@@B6E4>;^1=#&|f;=U@Tl41D9+Q_%Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-4Ev7=N>x>L{%mUCmfUdSMh)Hx zY6)}$T?w#ebpgg4u+8i_XjgzU8^JUB-9O&%8~h15z_bF^nLP(n4p?WlD*=n(1$Y4_ z0Sz~8$@OpHng9R*07*qoM6N<$f;65lXaE2J literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..42c8f81009ec084dd0372bb059921ea1c14f46a2 GIT binary patch literal 714 zcmV;*0yX`KP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?tF+j(P&{01n0j zsGA#(3I?v>$YSD%$54{iLLvdRBtQX&{t`akN9jMj*A_q^5C|#;0VkyMNCk{F`YK1< z4xM7>O{@bHDL^v%Gx{l=6|Z5mcucMB&lvCkA=Q5@y9zwVR(Scg53UiFHI$D40=+;$ zM~S&3whV;|$U)@-8cD&dot*~e9|$@d<1KvGkJg*$&ErsmA_e5>Y(4^VbT%IWB_RX| z0Z9T}|F*uKV$O)|WXz4hJdP!^uK__DV1nlF-7rn=Cw0~kY~C*Qar;g;B$=A6NXP|D wR-R(-v*i9AVF@H-K%hjti5<*c`6>{+04ywO$_3`}i2wiq07*qoM6N<$g87g!>i_@% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..16b6d6e4c0ef7b63d5556c5829bd9d517185715a GIT binary patch literal 663 zcmV;I0%-k-P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@jGcK$~neJjeI@i`&E} zHD_=sFelko1m+~$j=(~QfCy*>)DCus2|_iccd!5&6fj-0Umw#uRG{2Zu9n;reb~2m x+wJeYrFcy5>UjSV9cpGQ$StI9w)d|at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?IQTI9LMm) z2uxzV^udr|EA)r*aKD5=xF_kC_R<0{48vqbAQF#GR~o44v7Ef_=~D76o=7PmJAI{F zYYn_{mlx6eDiw%U#?Jl~FdtZOHb!-avU&gj002ovPDHLkV1h@U9t;2g literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c3d5453d48c0698ec75ee2e1c55470e4b1f633a3 GIT binary patch literal 695 zcmV;o0!aOdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kE z=n1wUwR=EOgpo*7(u1D_QQ`!DEISE+AP7QW6nLWRx>6}sX{{4uc)+nH%d#i@Qb6DL z7j*pK>}b0cMNzNW&fo!bP*NL35yWx4jF008(=-7_f$XaSPT+@>UZ!)apKuF(32-L3 zfXy6m&Fnp}5unV*rna0DDP?@ywiS4QjlegVy@#zFaL#OB0uDh0hyYdqmf4G1DmfFQ zKe)`bVfTS~o*Vq|o$8*R6@iV*TpKn5bbjN)tF4~?mdat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-1pSvzqDW4Yg0fF1i>=|ON4xi3AaQIgU;j)gUXt+Gh7NpoNv`s zRbQ?o(ko@fuWSVi5GdB?+?!hwU|{p7B!Ei+6TAzob>Y;`9z*XAJUUw~Uf|>WUgynK z$j1aO1xz~IihxOHTM?KG5fA~LKnp$1#M)s3>YkU-Lgkd&!2%b`)hoz5`nGQwoOYk$ rF|~{1{UeI_z?hMm_RqDw-vZ$dyF5c-jg44?00000NkvXXu0mjfexf0L literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3107e2bf8a4308a6dfd3af9c5b26a2916ee580 GIT binary patch literal 657 zcmV;C0&e|@P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z8=s`S!oxo8p+6meL zCD6&baBvt#B7}r+*mq)Pm*frkEC7n4D1jk3;$3peKqi+_Z}plPMV!zRJ_V|hPqNTs ztS%C__)7V&+71pNLTX!gA^^tWPe%l=0t*N(us0QLlRbygC(tHaHqS9UKRNF<@ztF( z_!L-@Y$pOslI=!dB~(BKOacwe)Rw)|1ej33fDEa^rgySHe4$)!Jh!8FP-?pGdv6ra r>D?UPKcZJDt}Aj(sM|aETcCUZsdq#t(#wd^00000NkvXXu0mjf%pDvt literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d794dc4ca391979fbab349038f0a123dc7a530f6 GIT binary patch literal 692 zcmV;l0!#ggP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?fN_)B6GcEFp%n0;zl1hvkKWhgxE3%N42FRrXku*(PjgGLwQ@Yz=lPkqdZ2ykzMkH&yK#$0%J$(=U a7Z@Hg&r>^KAc@id0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?tPB&`8-i`Hm^ zoJ0alOAFtV@W&tbc~24UWl4QwsPevjYk6&+JeFW`P8dfB^xlv`u#F4yR4u97sOCy(lh2ebBHo zoT#KZ4afNQasGk2en-i-dh@lmz85~etD{{4U3e5`gq0T?d+}XBJOSoSSq7rnQ%(Q? N002ovPDHLkV1gIwETI4Z literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexEnd-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..eac467a067adb885af114154938b1c9fa9322b54 GIT binary patch literal 595 zcmV-Z0<8UsP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O+fJHo h_G;sGGiJX9W&-SUQ;&u{DewRQ002ovPDHLkV1icj1*!l5 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0c1d73d355eed27ba20eda761904b5634dd17fb2 GIT binary patch literal 726 zcmV;{0xA88P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?6vr|a_3#TPME@Sy;r zSB(A)yiD|pQU4EwLEQC4>jEZkz06}{nHd|C{t5at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?EA&ifRT~SeA7yiXv)j+ZgQVBofo}JT4>VVjXhs zVyja73970{lH^rzWnX1-8(Wp1SAhw@1fUBb6OHftPm9t#rXHARbVtZuI8=j>^lwvp z0;t;qx)ozg-Dw8d>VB_n(47E1oP_j2OcnGMKqi_l6{CF*GzFKDcn9n?Cab!n9a9hF vc^=ueeL=;{>HY?&$RIm756ECJ82*(TD>sTU!2v0J00000NkvXXu0mjf{J=8- literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8cd602fce665135d87a345e8d44f51c99562b3e2 GIT binary patch literal 695 zcmV;o0!aOdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?iD dVzF3C;R7qJgiBe{O>zJL002ovPDHLkV1k9)GiLw* literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fccbe91be32b6a2b02dc58f3e2f01fa21b1dee02 GIT binary patch literal 710 zcmV;%0y+JOP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?aWQ00`6V$(2NX4|V6^RM`k~>K6+B=%w6{5KlbT3(!ahedsd&FMQ+zCv^JkL|k z`2nwyGTcH6Y+>c>dF73oQZ!eol$xF5tq)HF?J zKRfuoU^;{wq0|MtAd<+@_u~X6!6)DoFeSi*l4aB*N=wqx2$=dn0Xd0)O3N; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..345f25eb1623080ab8712b16a08cc6ac11e8ba49 GIT binary patch literal 729 zcmV;~0w(>5P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?jGe>Iu*TI2aG0 zY;Lmp5%d_2E*eKXhBj$!Ni?9g0fNMY{*r#Y{vYs%@CpEB2R$eHx$PRO{<$GCk6B*Fg?LL#2B3&bBbnE%^w7DM|2(2N9596i{chi40 z9&?CBolLoj4Nz!>CvDiVKfNU;@idnz1&$7Y7T14U%Gr{(50Sbje@vl4pvzl&9$$(aE00000 LNkvXXu0mjfLh?WI literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b4825a105c0654320c01303502d028c3d2d08ab9 GIT binary patch literal 649 zcmV;40(Sk0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?Um6Df-n$<|6>aDi4mMY9YrTVH-QOs6x@Ij zeA74tXC)yqO*l$h`oeur4ZWrxP5&#fc4!zJ-pokIBd31v3~Ps^$^C~*>Tof`;_q`y zjJny--M7|B;P~Pb6K=x7Ym-wox7KF#4seDN0_Mh+KDEvQX4MWdg;%Y!Kq6E?1x5u- zcAtat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?*`w}DZzr;_012{S~4%A>RDxxmr-`(Ko5Es4%+qrppxM4eatlibS zU-;cx8ztb@#LeA4p&UOv)s^0} Zgg=x4IAxG&L?HkG002ovPDHLkV1m^77v}%~ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2fd68279cb93702da01d4d30a608fc1e3aba6508 GIT binary patch literal 679 zcmV;Y0$BZtP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?WvX=d z*jHy+)~wB4B%tfM3l8=)#W8j-ilTDO)rl-0mGq3`7?LFU_YcDW<2VAYjN+ARu8!>x zp6R9zsI}9Txr+q^fd#MtqX4wdi=Jd76{X#S2aI)Knx+~>Jjly*%?PZ)1I8Vo%7v3$ zL0c*93{^H;d37PO1;3Ltup{gOF9NnW#(D;pvc)l8b|92v7=~eX;SHg8cKLu~MKb^Z N002ovPDHLkV1ijjE=d3Y literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7d142428410b012c5233ea301425a7244dbcf19f GIT binary patch literal 642 zcmV-|0)737P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?q+-n-Q;+ zKqZbF6B2`ASpN3He5Xy`zat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>?IvwE zV1#Uvx=2VU5+;Ep7yM3;QX*#>JhCqmb&r?1=zb@JZu>{OQ-X|5<(lJp4 fa&?TNC`uB3cU?v&*l@xD00000NkvXXu0mjf^CB6g literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..944a2beb787edaeef7b1e5ea1c48879b052f9d16 GIT binary patch literal 681 zcmV;a0#^NrP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?fMJu`6Hp+bfu`_6e+eyV5AN%=cLk;nl`nfw2#m=2O<&&*rVgnl51t5Qx0QS2 zR)!Nnh%PC`y0)DJ?B-%c0uQtk%6+``wQbUR2ILQUMObctQ~H1W;Aax(*mf2mS#aYw zK4m8buBL5g0i$3ASOF>l88^?UKKQ!ly(}OJ3@}s7vFj^4ES*-7S4ji|v_^m{mqS>i zu~Nz-6CM@iwGXNYpl}jnKx`J65|DADlQGIO&;#v^F%p5XGR9)DSO(z(X?Ig-Kt~Mv P00000NkvXXu0mjfXoetf literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b39a357ae2d7bfb90367125c7dfa05682f38fd14 GIT binary patch literal 676 zcmV;V0$crwP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?c!exx#qx2oxK_W0!#t;NSjKU4LJX?;S77}Uz0000< KMNUMnLSTZwBP*5w literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-flexStart-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5becc3163fffe577ba63390e74a052fb1fb2eaf5 GIT binary patch literal 588 zcmV-S0<-;zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4fKTrQj$T)L$;_i!C(OHFM_0K=r(=W= aVmKT7HZQetB{%y30000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?L_&wDbt}N+tFl!5d(sCQ=BE zzlGXSdJnNu6HAYvNALve?uH;>AhHE9VZH>|*?Acr3B_BW?67b(o^uq*daB-CLD^xM z-O17d_z;{oBfED|@3FBD+S&-!v<60tff(qCRXx#ZfU!Q>-50K>TW)QF8q#3gl8>2b z!0C0uZO6aBJ)Y%K_IJ6p39^2|mKqWnsA@B;o0{664HNhN literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0040ce940fb837872d301116a544ac3c042e2783 GIT binary patch literal 674 zcmV;T0$u%yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}SQ&?|TX;{ajw zIBYVsvpBblC#bKOCZ(~B?Vu*SU-Ia`FYp1c$txjqhnh}VmWq54&iVN41(`cEv{+Tu zUMY2eZedOL5NG&=msG9I(zgIPv4y6ESUF2;h)tGd4=H6AtNj>wqpMELx~`Rt9_x9C zTZ-1j`wPsjV2r&pH?}5|W3(7@Ej7givR!s07*qo IM6N<$f|at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?UQ#A7#aZGd(p00JNY0w4eaAOLm%;z&O>*LPt$j|riZx4exlf#uT&(H?d}FYoo5 zcuTVXft~K*KHjgfG}b}{PJ29a!6x2+liZ9%U!}rat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?B8N4e$z{KBqx z@J4_)qx?Cv*2eb{Zs}n*G}qRv4ypZFz$CB$7Qg~n01IFNEWjxMO~gQv426lY?qh0g ze2%Eba3WVjat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?wpK)G>r z6u5b01RTK$>R)Y1+oX;5KumaF@=DY9`raSH;fHALWM*t<5%+z@-x&9b)gLa>TK!s%PK#_g`y$b`+*o3ocVxmh&MR(J%}q ze@&=$h<$_ywb%{K5KWO-`?Y{YU;!+E1+V}Xzyer6Ou(cTZ761x$at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DjgsYa7Ves6e>{+)5jXp+Mh?8J@bhGK zCaN)4DO($W!8rfv&?&Wr+EB{Y253nLfB*=900@8p2v7x(WUtNbTxtq+te7oHK9U8d z2aIe%DzYeMy(Zaj^<-OUaKHAf!Gn)m1~2=9l>lYy)QJu%*}oIsj8JbUL2Zd)V50m0 O00000)+jEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=K~#7F?U%s~!Y~j7cT+{+l@h1`CzttVlW8engRS^Rn!at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5>aU+k1-5-E;k+a$@HY3 z*DZXvW{U*$PF(c&%GL3~-JRuGoBbz$2LuBwx};u{U6gVJ9AMKoWs3z?f&vtv00k&O z0SZ_GGi;{DY@vX_!^SsdO9k99_Hb7$?dRCzC5>iHc60D$M7}yIIB{X7=O6$8002ov JPDHLkV1k@Y5LW;I literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..34da855e3d96b1fc831b2f8733687cef9d2e688e GIT binary patch literal 664 zcmV;J0%!e+P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?D#*MYtdQP#=B)_Ac?gkWxBWQC-)4?tOs0OQeeUS_UD+)j8LA z!!wReZQDLey^8>pQfFN35vybE*7yCG>kV~GOd6=IstW45{*7y`!59O$Gpdid-cYHJ z@I)tn!Jyw1dKUw%A_iap24DaNU;qY)0$_-EQA>fsm)D<5yrH6r$XYw$!goqFbo>FF yO1z<>Pk=HUPP~Nlv|Gw}e$dSEZchAX#Ciimk$EQ&dHNdw0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%@|-nNXW@13+R{Fz^2T}CJQWu3%Gy_xPS|| zfD2dx18n-tY?^>hF%c$=IoV`^J6oOMWY1swK_K;b(43R~JA5;8UWF_~tEm%f;s5{u M07*qoM6N<$f?GTfCIA2c literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7c2a8b6482e6de86aec93ab610aa0b6901cf9644 GIT binary patch literal 630 zcmV-+0*U>JP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?KL=;Gtz#fPR^ChrkdF+16au|T2L&e29Fa|xcf6#kw4?~BVZf*h-akJ#T z@k`yQAtZ;4uCCcu0;{o^k--IaV&2D7*K8f@H^2kRiZEROyX<#_(KiygWLpa`6FG&o zM`e-^zGJqvKrg6(3aEezsDKKnK$E~zPPe4mc|YeZmr|)?w!#Q@WVoXYQVdjvi|WKN xTfzDUq=xedbJXl9Uv0cC6`EbLe~11VDKAT%RLMI4CTsuz002ovPDHLkV1fgVAW{GT literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/alignItems-row-stretch-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6b6c73ed3895b0ce16213ca6332bf3108899f059 GIT binary patch literal 652 zcmV;70(1R|P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PtB5ZH4FA#=dKYoz)SuQUVrPz%e>hDuybd=AJ2;4m=$`n z0TvMf5C8!X009sH0VDuWxkf(5)2$!dxK-i}c8L`-0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~T0w)b$KWfn_TBM=*#CQG))2?EWk zC@)!)t@*qPAOHafKmY;|fPf^hk<4n$b_)cO3C3(cXRlYcTj{RH(`0`IenwyizJUwp TlN4Nf00000NkvXXu0mjfu0Zy6 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..56f96b6e53bf1b908be29335bc212f573650f4df GIT binary patch literal 633 zcmV-<0*3vGP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?CgB-?WI49eV9oZ9@(4n9*4}tCQupzw-7_dGE zth-ZP)A2#(-^N$#*#nou1`PNDO^G_}@E;@e;q}ZgUry;ZlZ4CJ9dFe%6s0#`63r?% TL0kBs00000NkvXXu0mjf^o|qL literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fef20d28be656459e2b5ddd6a077876c2ff696fe GIT binary patch literal 630 zcmV-+0*U>JP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}Ex3V`F+0XhyZB7TKlL)4XmjRLyatHW*`6o2tWV= z5P-n!0-}Y4x1Tc~d!^JagwPMadGAfm`Oa+@V?2$$Q#yeS*DI(7{s}jwlm!V8{aoQG zT=_U~_4HlIKK+efe;_%9fCXiCat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(^b07*qo IM6N<$f~Y+W+yDRo literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3da9485fb521a0674508f168697a7e6e9569b2c4 GIT binary patch literal 634 zcmV-=0)_pFP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?S@iH@Kh z1;yLIEogm<5Iho1h_UeA6|cE3ArK(^A6FfKATaRWKidEXYhX}o9e~LS7Dfa_KmL%0^S^IWE3j!@Pz!2-Kf(tb3J8!c zH?RsfoQ_zD>C=*R>pTAb1O&(ey~NixIlQ4^207=^7_-IYjuXztT6=w0Ll9>30zK+R UIX|DOlmGw#07*qoM6N<$g7st!(f|Me literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..202c14aeb4670cc28cd21bbcea2f77d7c3e95c45 GIT binary patch literal 613 zcmV-r0-F7aP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?bI*kcI6j)^WRcH?9g-OPi8frR`=Rv%Cl0k(Gcv>>2>j1od77#S5%0ToaI6;J^c z7+ru>NNls*gQ%KXT0ER@zt3jZs(c1>gE2m=F1vr&Kc(%YmA~Re}QM-dZM-fF4@B#_|J48!U@_qmS N002ovPDHLkV1hkU3XcE) literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c280032570f138af0833aa8646b2424644cbb569 GIT binary patch literal 610 zcmV-o0-gPdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?8>Xk=O%ii@d$bny@{@L z@C-ui7hz;}F^i)72caP;&4X?N2oYdC+L?g>3&bc0lF=9mNI(J-kbndv@LK}iXahH( z{$^#~V~xG;ZUY>+1hQdSk75bOPYLF%v6ml6aNxT99=5N;HZ{FqTFG8{G8|5;w1oq= wz)WI#=!@YYC{h317|hXv{%X5s!^Pk51Q+2#0kbY8JOBUy07*qoM6N<$g0LP2%m4rY literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f34ce3987c6cdcc047e87565a4a74fc6dbcb5540 GIT binary patch literal 625 zcmV-%0*?KOP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?k<-K200000 LNkvXXu0mjf4MGhO literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..47c565755e1262f538e17cad9cf734355a6e67e8 GIT binary patch literal 623 zcmV-#0+9WQP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K|8Pm z8-P%PTM0OmXhJp~cHpp={}KWL!hhlPi2xWNrSz6T1MFykTI)oESlSo}KmY;|fB*y_ zu(^P$kZ}9C@^rM;9-MP?dzN#aN+~a1KE3yswQs6^fE&wE1G4rpIHS0$R;YEFveMJE1<^x!FOraVrQtto&002ov JPDHLkV1i_o3O4`% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..877144858aa526c6fe34f642e09ed6cfeac2a9e5 GIT binary patch literal 628 zcmV-)0*n2LP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?p68rXmhUponpV1Sr)xF0Sz>MTz7n?~5w~j$>fTyJuc7Fo2B~MjG^t3%Gy_xPS|| zfD804pc+VKygx8_IRr0m6ykqv%%N>SR{~w`wB2-lQ`LclG?J}-NzhyZ%kW%dB!U9f z<;;Y`Nq)JKW5jPHi=S{lKParBKrK*6e5nbq7APfZ!_CM@e#|0p90PA6Dmb6>OXI8n O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Kqr>_>-bUa+LSQl>x(0@M!pz7ZgmO!$HXi17iXvU;-v!0w!Pr zgA0fTlINNC%vkUg-mj_suZ1H!8Y2+lKHt!;@0+3y#E4ni9K8|3gat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?c0ccfgO0NN7At2Ru$Mw;%ha?gs>mIEUtqvRFwNHb<9`92BSy zx8zH?#ar80*61TyR}1dv%I%;)EijPiNobxd@F$Vj+{_`9>sN#j10Um*G1CjY@^=6L N002ovPDHLkV1hNb4DbK| literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowDown-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowDown-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8a3aad236e4a1976393e7524aa2d7eeb3f949f33 GIT binary patch literal 616 zcmV-u0+;=XP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~`Y{Hh>8VOhRD-*nkZ> zN<9h2kRG7wp^gu|{3peUl*s=nCj*28(0uGQH$4KZ5kfP9tgtW?pa2CZKmiI+U~vK0 zKw=Zn#p=$yw@F(0zdL2CogJS^uIITuoj;%(D;aooC2$=6nUFNWf$MPzYwot~ZAp>& zwvk~xdnCCX;J_^~lK90PUM(;oQ57D>B-%lQkZRta7&4fF4-EeR0000}M{P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?d{$6u9({x8NsrWVAy@p{$@c_@^M!;-I zCdQcI-7Zipz;>VZy&;c4-!5Jo?^ZA)7aP?g-NGf-H7RjbdIg0;e0~LeTgQ5hXU^bv nGWq@wq!8{W%x{Q@$W%Q5Zx<~&5-Eow00000NkvXXu0mjf!J7c0 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..582f88b7852e5cadffa10f27b871a418ec37cb44 GIT binary patch literal 602 zcmV-g0;Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?t0x=K;(65*R>_E>+6Wf6uxFy($C8(9y zLN0+Erv&dI!4W*{!BsCAME-+eVD~T|J^_e`=+}AgPdZ0*vc!kux<;KHtOHDrORaT4 zCkuRWJm)O13h?avfIcLpw4Hu)u`*Dvni!q o(aGxF&qs(5!mYIiA|m=*cZuXOR}-0TTmS$707*qoM6N<$g8J?VNdN!< literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ecb6fc807c75624c45e20e54f18aa7e79bcfb71 GIT binary patch literal 605 zcmV-j0;2tiP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%iK~#7F?bN{u0x=MU;XhH3J=%emVh48MmLMqFf}mgt zY9+Rk61*u3n{jgx1kv5g1Q+Hzg~?$aJQ6U*81whG)rn1YM2V+ud6W`lPWAw=<&J=l zGn6>GEZ-G@Yync=B1?1x_M_?h;Io2QkI~{fjT-Cw8Rr+I#Dm-wWDfED6ZiI?Uy rq4rml41eCH5Ua|@+00000NkvXXu0mjf@<|Bf literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..753dd21a853298497c46b7a61c2cacc2ea0b4b78 GIT binary patch literal 602 zcmV-g0;Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?86M o3K{(ex)2iJo>F>)h={i83lj=FG>1T^tpET307*qoM6N<$f=0puasU7T literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0172ae83a50610f3f93610e8862ea13148d33d27 GIT binary patch literal 578 zcmV-I0=@l-P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%j- zEyX`LIAC3Ni2RrQOgQXJGT8-0MC9wd_aoCIksOicERJblJ;0%PU}_|i;X!kL2UrcT z@4G`9f#+ApA7?8lVCZTE6HALXR$x8E-7Rn|GgC4v5{bP7j%8pLh=|BvZH!(hKV!5q QEC2ui07*qoM6N<$f~Z>ddH?_b literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..debb42bf3cb9933e7347c06a65798d12150584ac GIT binary patch literal 613 zcmV-r0-F7aP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>B+#UoH6S>Z4gh=QLqXQAkQm31!e$xjA|i0I$BrrNqgwSkcgKb8Ypi)w+?0iMeN zpLIHe5kZgTmu2gbD!`*})irGRusBX%2X894j$uT4&f+T+JE*MU(T`lLpiEdn>JT4) zL72BSMECJH>4KbKB>#4K50N+JS)d>yqQSZW^)Wl=4nC@E00000NkvXXu0mjfx(o^3 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be941bfdf0463782571631e3d1dc299a25c3be33 GIT binary patch literal 601 zcmV-f0;c_mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NH$RLA8jOl<5a0ztc5`ap8 zPA=jXQ31meAR+OwlRI11ylAx-%t)&PL`0*K_W n>=4P|-{Z4HapVmmBGP9MG;la#gvF7I00000NkvXXu0mjf(xU{; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f4b16e36524ef1308814b756a58b13a3dc93a15b GIT binary patch literal 601 zcmV-f0;c_mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?*nyVdMbCC%2W|x0xd!lW%R6!;jo>$KRbHq@@MS?p^$|Sd)piaH5kc-Dns33@6?PVG_PgZ6 ngGAcjf&UP2wz?xCB2)DPLpUwaA#xa#00000NkvXXu0mjfY<~u` literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0795bc36f1198cd54124f109d093b62479660e8b GIT binary patch literal 604 zcmV-i0;BzjP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2!XO+3@PoL38|VlG7H|VMup_vMBdC+O z0PN5aoB%u?OicWI0h{K2Nkh{<{0}YwA|f(%DWxNy0~)dTGQ5;B@O6vc0q(<%F{8D1 zgGLN~819@K(JMgho5S~Lpl--}zkdAoQ~`%C(b3BaVvHv)yT4S>JH*>t5JDKZoLR{# q=X^mUi%&mm2%f~1As`|mvvmV1xkMYdft&6C0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?yb_7cUXi)B_578^Kt^UXTS%L{NH&k6Un+kk;>D tEW002ovPDHLkV1irZ355Uv literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..169f5ed3d494b897b480aa6a9837446c6774234a GIT binary patch literal 603 zcmV-h0;K(kP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mX11+0S6AEAw z!zLbq9w`^Qh!iQmjh!fZpJdsxi#z%003srqx=*Ih??Z2hWPzUIemkmSkJJs6#r<-+ zfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(7BOYq{_g6zc- z)Jkl_lTHbqJs2Y*2;#bz3<~*RAWRMkJZ2z-5W=rpR=TmX#!11K;R>~tQ*tlx94?S# z$OI=skKwC>Byug#Jo297Beh2at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?h}l=btWqu|D*>7cfn1k1yCHZJ dHAF<@%vy>=FqV&U#N7Y@002ovPDHLkV1nMb{u=-Q literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowLeft-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowLeft-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..548f3ac38faf9918d5891b891ee2aac0830d019e GIT binary patch literal 543 zcmV+)0^t3LP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>L09 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowRight-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowRight-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b1a3c7a22bfbd49b57f496565c1b2f0a657da9ad GIT binary patch literal 605 zcmV-j0;2tiP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%iK~#7F?bAUK!Y~kp;Xe!lkWec)KtgfAsRaZO;8F>I z1QZ|zEMOqZ7LG7&FIzgD{m#j}H@gWq=bRg@Vpmb_tF~hktc0*Y(uy*k_)h`mTH=97 z-c%xBX&p0!o0iD5%$dVxNo#>3-a#)|_)+3}1*S7ePx_2|uOR6PJ`=rg+~)LFphI}g r?iX|juT8Nc>8g)z))elXb8Zk`W=SuaXJNUa00000NkvXXu0mjf1P%rQ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowRight-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowRight-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fed4dab5eab511993381772f1df84804f5943ef2 GIT binary patch literal 609 zcmV-n0-pVeP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?dSzGWNLi_=}xUjpI(PjA$hFwC!{4fzABBG@VAskzc?OTbS9qND(C;3N!Qpy&e z2dWziVMLMl-dSsJ_;sjrN@*`+0g(3oKA@o&Lh}vu)LNh4YpNrNF}j@dX9O4AzLQ@C vn9{sa8^M(3&03TgW3HI_W~ez45zWF2$=@}HWH;)*00000NkvXXu0mjfSH=o_ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowRight-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowRight-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bdf0a942032932590169a2008e2d9c275663b9a2 GIT binary patch literal 605 zcmV-j0;2tiP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%iK~#7F?bE>t!axv(;eQtqyjjAwVh5HGJMa>*2L($| zORxe<(H1<30e9TZHIU>oF@*VG_xc_)3>agKnXFxPs$U0>8d)QT4I&{?4TJklRf(Jawif$B`+iy`Cc6@1eQ@at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?fWnqsh7H(+5rEom zn1E4W1qQIqxkXWu<^qb|Cq+@BME6T)fQX3J$~kv#*VK0#C^5zyaQ~&?~07*qoM6N<$f;qHq)$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowRight-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowRight-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6c6f46f01601d51fa1fc773fd70483d967037d31 GIT binary patch literal 580 zcmV-K0=xZ*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?v~(1UgW{b)W>4paP}P zf)30kzK}aVdqn0Xlgr7;PO>6IMD$nAxlR*$mx`SVX;Gq=mkN}~iqyUmi5SA*0>_N# zIpE$%r~n=<#}5`RB`jBPXFGq0xq=b*T4EJ=GF(}%AUIrQVrN2f-*6%#`h*>`h9#h~ S{Um$<0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?x%XM10eFj2^*@JmyPvr*RC}0|% z67WFes;dM+P_g$ej;Ln9!O%9$&r9SA*u(6ObU?zJ5+>W|lVW^g$h_j>T@$EAx>4p` zSX?U%RiICJBK8aVgePMNXat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?`Ywl8;LPg wfj;2{w-NLSFD&82?trW9@2V}Fh=?X32NgIn>sSXaq5uE@07*qoM6N<$f}q?7PXGV_ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowRight-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowRight-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..79e6ea8856bc64ed93e7760b9853b9c24255cb5b GIT binary patch literal 600 zcmV-e0;m0nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5}?A( zdSMlhg$QsYe~oa&&yJDRTQ1>&sQ{KXZ$EhGh45R!u(Erx+zJ#QxrP`^1(-9u;kSYr m!y6~~`P%UF*l;2u+JqWUKrJ$4hu5nB0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~? z=!YU44CS1=Qp%kX9b+ybgagI`So>%{z`(Bv%QNtW3wwROn{5mDc#Sdkm@8n)@WyNl orVMX3Fv8(C-nK)-MMPu~-eQUCw|07*qoM6N<$f{cm?k^lez literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowRight-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowRight-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5b65a959934dde04a485774342403614142ccf79 GIT binary patch literal 605 zcmV-j0;2tiP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%iK~#7F?b5*wfB?Pz(5b|F#+0AA*^OISCh=}&;qVG?rse2KeDD-Caun=FY5uk-$ zZK*9pG8RJM=%i^JL2}#10{Ip4ykjcBSzlFn00%=M+(s}&(Kh|F#YSL%;a^IcV5tCe rng?zpnA1Esz)xn)k7Lb=h-ec!P>47a!w>s400000NkvXXu0mjffat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0xK{899JF*0bULW`M;#lG;Qv0t^g4cZB_P`haY46b}%A>vyOZEkuMerP$AS` zff~_J2nR#SQv$a~qSHXH`a50S1!Doym*njM3q2vsTF^&ol-;%2TA&Z|AKqMqxdKcn s?wPeat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?MWTR$*VS^~xv(S~gbV ztxDBZLMZ4MHEQ5#HxWg+onEpdSHNc1*cK_^SBa2q^iRr%A@kA*S{niBMwR=yk&2-T v^a)Rj{enK>$$~=cat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?XP3D`tf03(>d zD7u0P>NNf#>d!&sdy+OH5E0Q^d7GDE#lHJMPa+wGL^QZ3!2D%7iAawk3>0}= zSlNg0B%@m6stmCJsU4ReG;AX@@4yZ}t>0XD1n7*bQ(P5rW_X}@1o7d)7kUA`Y`>%7 cL`3umGfk#4x_h37&;S4c07*qoM6N<$f}ETF>;M1& literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowRight-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowRight-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e87fec9e0510c60c4b3a8f5ed66419c07144c428 GIT binary patch literal 544 zcmV+*0^j|KP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?M9jbhAqXA_ zKK(RlE1%?NWJ>{vh^SSnI$uE)E8q3DAc7T-b&hx)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?I{#0IrZ%LU11BB{*s*{p!JA8olv^8=vqBI*FDV#|kXvU&cW5cs^YSZ%N63sipx u{u}`W5I_I{1Q4(~V24QM1r&OZForJxMm7_^-at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;VKI009U<00Iy=UEoeWG6CRZ1$k~Z$kse-9smFU07*qoM6N<$g7MM=&j0`b literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3431b74208affa91fed96ce7b15ae5a4683d8d1d GIT binary patch literal 600 zcmV-e0;m0nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?vbGZ~LTy3tUH(CjkFHa4{6100k&O m0SZvyb%75;IPQgn2$=y`fi|)G`x1=+0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?rP k3Q&LorwiN>qk)hh3#;%h%JL9IVE_OC07*qoM6N<$f*U;legFUf literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1c69c19c4e10800b380350fff4046058f9d17328 GIT binary patch literal 609 zcmV-n0-pVeP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-bX`R}Qm^1n z5IZ(4qwO-2{%qa{fyo5&K1db=5RyTtigUOYCuHDYB!&Z0b{p?5@BRG<115n{xMGy> zNJPV1^ICgd-AEa3@oYwc{=NHf|B>zQlD4)=BngO!)9}~fQENZee~IRar3lqd;z9<= ve_(1TKmiI+fC3bt!0G}UWH6iy39<48Mrk}5pn>yL00000NkvXXu0mjfzb6RT literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b66f8899b978483dbcb9855160e8435cd10cb764 GIT binary patch literal 601 zcmV-f0;c_mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(hMk_Bo(EEPzrS7C-9>H zIIx8!#P4hbpB>54X&>H^eE=aDRK5PoL4UXdUtV>p;jA+f5hM@_6`#XRb^DYrj1(}k zD|frt`7GrnOaf)M{`Xccig(PnIZ47KP|V@WLV5EN7jr*H37IhBD&i6%1M?1?4FxDb n0SZun0u;Di;DJ0G2+3pt4mdy3{cHLn00000NkvXXu0mjf8pZ!c literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b126cdd8aeb3961f03a2173b8cc8dc626bc75a06 GIT binary patch literal 599 zcmV-d0;v6oP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PxIVOTG*DnrND7aWU6!5unHmKY2^_+qk$54KUAW(E zr`j%O*9o{m`fVlfgK9mPr1m8ec`p#8WfJbb#;;=kSZ@*|?jqhcqyYulf8cB=KmiI+ lfC3btz~cgM=at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?KNF6{UovAnm~xQh{*- z2Cp-QNjvV6rcbFC_n)U kP~dfe4<;D@g@jl+0Q$s7jsYUgLI3~&07*qoM6N<$f>ay-bpQYW literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7dd3dcdfaaf3bdbc24f42ccccee2c652e8f26563 GIT binary patch literal 603 zcmV-h0;K(kP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?P~2~Y|bB+76L zG?0xG%Zjhw&F3;tva}jYJ5RC!LL4;Oy;|*_a3C-;mIHc8OXU5P+Z6^(0%iHU$R=?> zB}I8C;-E2Wr@Ive(tD@!6ZD+(KFubHDuGxax%?ydkn>-hXNmrgt!VV2|u ppa2CZKmiI+V0VEdd;}2UWB`1WJ$R25tz7^B002ovPDHLkV1i_d0{;L2 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..09ef55e8a2f1abe7922fe1bd3cb7040124d9db17 GIT binary patch literal 603 zcmV-h0;K(kP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!{Zooo5w@QO+pGD_!n~>QWqR_|AB8q p0SZun0u-PC1y&c>z()olPF{bxJ1@Frqw4?w002ovPDHLkV1min{!IV? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1e9f7a56e4d929223c74f17ea8c4f0ccddbb6291 GIT binary patch literal 611 zcmV-p0-XJcP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?LU zp$k+|5^Qpn9Fog_ATY-0KV%;a5K=*R)xqk83Isu>a0S}AiQxVG${hhh0_*V7C@67) zlN@g5sf62F6>WFZ0Zv>354-OiE*CUK;EyIM;S$h!(o1;%k(BrQBq>YSp&$0bCZbcJ x0{0u(8VXQ=0u-PC1t@U1z!?>+|AmA^83Bv+Hm{C{s#pL3002ovPDHLkV1n6_2LS*8 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bdbb0062249ef557756639bef66343d501360dd7 GIT binary patch literal 593 zcmV-X0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? zaLJ6H%{|Ew0?FJHU;#jg0bjP`S{)2HC<)=~_&?fAPKFu^R07xV*h(c)Ad@6ql5h!Y z``&{B`+c9`MU@CtT8YdP@a_zE(o2lr=22qCTlli^pva`bfQx00000NkvXXu0mjfOjQ1G literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/arrowUp-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/arrowUp-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cab83b70ca01104994369be66a042444e7ac21ac GIT binary patch literal 564 zcmV-40?Yl0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?c=9Uul~CnLl_wX8Yu~DHQv%ypi3MXwO|A(dlAp`_ z9NOCfFZ%akU~~e%Ljej;Uw?|)-?x4&Qj0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?lS^EV4)G!oCDJP>N-CBeC=sFj6x!rl9e)dCtx87j+G| zm$(_jpTf#@j)#nI)b?KhT}qtvmx41R$i_X9K?S5~1g-9B--uo$Oa05x-XT%!%)Q|$ znL&X69dLslgL6N?974LJAV2Js2frVMA+CDCT2ux8Dc};cJKi$mCbYFIN=)`sb3e)^ zxBXSYCfT8C$$v!HPvW*^19ie*^mo)|(xnl_=Gd)Z#AR3yc>bBUIq?^u>9uiQsa;$C znPE~;mEuZb+9d@p<>7yT^gAxTo+Y~v1Ofr(2P%PFSUeD*ivR!s07*qoM6N<$f|@^8 AMF0Q* literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..da23ae8c580978fa66ee37570d4681b5d29c019f GIT binary patch literal 789 zcmV+w1M2*VP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$(RiB?u;WVg=B+hh2tk*EG#{6h$xGy{jBx3cko|k|d8DS?vR$k!{y?8yr4h z+hYTDz3=;Hjvhy7(zY#>WeMY_Ow*K%9+d;$bM&m{f-wkHfU|Fv17ul7LHMN3;cL8e z_AW_7P{#h5Qp@_x^L#59Xve_Rr~){SvlmR3WPzlcj!h~{KGlLS3|U#A?E*?cB@1YM zhuu*Tsjw<;uqsxU^sbf#MNyo{s50f@OZap9u2KnqLDzV5GTK3if#wH6@b_)oHl?9A zk&&}{geF*cKG5hTk<*<2iEFt4Fh~y^!6kLz4EiU)j-LFhuIo1dn7zHhU@#Cr$og+Y TTmNfs00000NkvXXu0mjfwF6zg literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a54c29b8340fbf025eaa465c6cf19191f93a11ab GIT binary patch literal 778 zcmV+l1NHogP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Rn7&$WgRvo*g zPQ~?HAQTHMha5x#xFG@5l^#=w;1l=tBlVyw0VYc3xT|g`q4olloS>FtpuPs=Oq5oEvLQzEY0bw_)3J zh4f$AcdP~z5U_s(2SxX_wXi_UK;#GuSkc^cHwv_cHGjbusSE5a2nS;_e!Hc-)%VIA; z$Txk(jsUjq^Zz&jUF=$MK?!v!plsSvi4Tn8XUgq89*<|sFKzo@BB#GecK`qY07*qo IM6N<$g1M1XE&u=k literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..402a6e056ea041fa3d9af69f9e19a61604ac6fbc GIT binary patch literal 772 zcmV+f1N;1mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? zTSmb74g7KF1tkoXLV literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..da594d87ab97edd129364f3f6bbfcac7f886dabe GIT binary patch literal 714 zcmV;*0yX`KP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?IRk#+`z8j z1lA3@K^dVN)JIAaO0--A;vc@`r4$Z0xZ{WtiNv2-aSf}g8Wx6oNJ1?nU@M8qn!>P! z4p0GgLWnDOVkie@48wp+s7@SP9|v-12OXg^jUh0(FxH?A{f;zZ-J-3&cVm1{3_^xL zI{xE1fYYlaEUoSbXRgmPltw$V#v0h?#K0#9vM>FT#-wE769QFq8m-po&!7%Bz0UI8|$^`;XlF*Db^D3#E1ViB(-)Wv6_{IFq55gm9s#%ovn w6|q7fA;B^9xd9t>T6N_w=*BsHB9TZa-cNoat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? z_JaO;tW*V!Ltyg$Fnv5$f!OzF#VQaaOqOX7C3SjRs{%HSR?=u;$sMrsVd}(zb8xb2 z(X}*BLM!u}@Zn@E`&oz{Tr!wir`%}W0gn6w7_X5aD+s~_F3?E`WGR|FU#iGn(+8>~ qvK%qTuR#x9lWBDE_8N^wBl!jCU~*RD4eR0n0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?X2({Bi{6YQTUoDG+Wl)Fkx2YAVl_Nls}6W+pl}>( z+2E!+6bB<2VxY+Rd(3g6g4OA>URhs_6F?79T$fK;T5LxLz(wY~W|HBA<2k2X$3Ssu z@w12VxFFXxcMKl?-PigVjx0`Mroe>{(m#=122idv=Z-IW)AyElr^wI+_eIZXRUOD2 z2By?Nv1Q)jqbN;`SAlOj+-ZC9KKQHfy`WsHNd==*;3XJ#JgQ(3s(>`|LYtX1Lw=*F zfWa)=mi$eQ{jF(=AHc7?wJmy(Nk!UNwEAY|DIi? y!1>Rz#c)ary08GLjGAe9at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?6IIK@_DLE!x2vo-dI2w;^Of%f`o)Q=AU*^v!LZ|TeU7jSe0OYgwteR&s{+P+g{CF% zDd~yo)V@(V;Q{s2qI-!?!cSBzzi_;S>s(m0awD+;4o`G(AFEUG_ly++Uy8LvaY!HN o;$Lg%nP;5iUh?`(CX?}e10AhX;+^)E8UO$Q07*qoM6N<$f{}Di@&Et; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e79cc86d5a6d742a68cf1c25ff29d60602cd3e60 GIT binary patch literal 779 zcmV+m1N8ifP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3N>; zegBXoi6kaI*&%{G48ySPy6&?q%V+LJTM1l%L|*bdf8_WYCx9TEAPDaIzEAMfHq`xfw2Ut1@(!CF4!XYQFEzB zpL*$BYh940>4|P002ov JPDHLkV1nPUUvB^a literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..01341a119412361e2f57155f1c9c1d2cbb048373 GIT binary patch literal 787 zcmV+u1MK{XP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)zjLmT^k4l0tbd{4Kpry$8;@1 zTI8x@v_(lu!;%PoNW{A{2G1MNd&YMw+l9Uy=+UZ6R=JI(vjY)$7K5h%pG#ZdGX#bU zpeq}l2^^W=M3;1}zq?h&N-p$hn4H?^cnd*O64ov%wU1@8R&0nprsZpV2N`Gz|8AP@-r@Bx-{WV#+_ R{(}Gj002ovPDHLkV1mh!V0!=n literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..18ddb605700b0fee6ffee21919266c4b7b4af75e GIT binary patch literal 771 zcmV+e1N{7nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?qOhF2SiFNe8$SI3!onL6Qz~ z4IH3_R3PZU9YiJg4&%*=5D?kb_MV% z(UT*T9LDi=tw&@7YVtqL-wzTs@m!$18}R#=G(b-da zRS*y!1OBF44CSk!6cO$ME;{z4>sC86rL6_}i$qxv>;jvDZpGs)=(}0KG;5jWl-_7r zP`#+B-P9Q>usG_b_y!zAu@N1F2jLPWr{AWVEiq`uCGOHHr=ocEfqc*EXPnPJ-H z|39(IVC=Ij5j>|3_%y5kffjSz;Zt(@L?V%}`~n=MV*=e29Q^at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NDj&fi6m-B1$W4+HKm+3r zrwbi7AXnf7zztlc$>1Zn_5_I)1R@*a>YyaTuaso;Yx_y@;bX2XpqL^j{w4%WSQ11=u!0xQ0=}`0corwrEz6H1^${ep%N;G6^XO>JS^3&s%g9}6;bQZvjoEMco&AgTgq3rq>x9WNQ^k+Q0Q zDUKBSX--Acx~)~gbU`zGwd8N2a)V8s2>1&XezxdF+#AsnadNtLg?%?=SlRGkxz3H& z1t^7Ql$+z6oU?8I8#=LIRf-eITz3n8Q<(n&u9eqAg@<&${q!D>$7A>a%ClvC*Pzyp P00000NkvXXu0mjf&TM7c literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f7adac00e566754eb88ee2189fce2a77934c3929 GIT binary patch literal 733 zcmV<30wVp1P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G6p2LsjNoq6@}NEH8b>Lt71oPTxgsVB zjl&!+t{^+2<^^X@+z-ccz~!uEw&83Ha3I-27LYY0?NVUTWSmoG^gGJRb%ltr=$oZq zat;|Y1#0-{-pGUwAbL}T$KhLX=X@K`hIWKnI=WJ*>y{V<)PQTWN5O%Vm;|Iin4wd4 zQdtVw&VoIw3j$J*EbNJgI@rOm-34{Gr}mvYS{J}j(HiYRVVc|UGu0%to$wMeh-5o_ zKA1MtuEC0?bD(+n^`iKef5TKMQ0BMH*%*=nm%437{X|?jC;CVv5;4315M)w#1wz!F P00000NkvXXu0mjfK0`=W literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/bold-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/bold-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4713e0c7d6ce0a441357ebc21ac6fb7c5cae1a14 GIT binary patch literal 671 zcmV;Q0$}}#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?BX1$R;`gI)N*&0W-LP zP9Ph=2C%_-P55ChM6T^&Vsc;dLg|&GeeD&%FpPfzzcY|tq=w{S4KR)yXoK+_C3!cH zPD$F64x}@wXYmVYGP6R@;wKjGBzbcj;Peac>rH@GyQ4?Ny6=*29S8}YvabH4?OE*M zoGU>Sl+$6vU6A8IOB$zk*n)z^ujE1vS|n7#FrAIxOkf%_urb9_Ud=L`W6^;vq~qDK zsAhiHf)*H01DaqQ9STb^XA3x?B!lHoQcWc|f?*hjfHxFYwL0(cFxdbA002ovPDHLk FV1h&nB^>|& literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..39256d89611315754f1be7d5b5e161c84e2f14e3 GIT binary patch literal 769 zcmV+c1OEJpP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3XL65jWCFz^L%oES1jACmwaF*qNIk+009 z&xF4S7rd)NIm+@KuhB}M^12C<7$yG@;z37zU#eV0OPO1*O&L8T6A)iESIscoW?-y9 z9~kqozM6=$H#zp`1}{(f_wPXI$L3?IyBaPXGS`j)*J3;cz%qDl=g+6bH=jKE-EOK>g3IY?N)L=A3E) zM4$4wzMR4~gX?jlk+;LDCnU^-XA7iv3m1j7W>!q;;10ZGwT7_gilk0BXR?6b*k@m` zLpbd;V(m!xC9D>BbgQ?j2ZhX4*>O$WaTa_56X|9mjr@ql00000NkvXXu0mjfSD;$7 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ed79fbbbdb736fb6c8d14e158031dbda6470e666 GIT binary patch literal 811 zcmV+`1JwM9P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K73`=Xc`3x)=PnxDV!$j{i(7la? zb%Ihi&+~m8#~GP{s;WH4aW*U;8{O+52)s6b)h(7~8H-dH_i$aiEXzK~Oi&|D(-+Xj z!&;~hua9lM_YuIAV*%N0HV3jW>-BoyEX{6wHCF8V{;X?1qsgCb;4fhfFc=I*4>S`K zhT_-s*-!DsHBkR&o2I#x7yM#Mv)2IlH6Q1qDDKF@lx2C-EWK{L=LscAdV|S^Ml4Yj z-xWo9O_F4mFT|4zg75&#T@!M_6Z&ob#N&f4-{LdDl;97a3u-{ujiPAVjh%c6!7^jP pE!=`f765cI)IvKx+?;U{d;+u6ePxAd{=@(P002ovPDHLkV1k5AY{LKm literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..74bfa4028cc62ddd700b8cbd5f7255b174216908 GIT binary patch literal 759 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?{dEMaXEeaDZaY~sy(~3QKp&dHI)X)mpJWG^Oo!}dzCe! zdibG{#PT^v&jmvO{}AJuTQd`;bocYl%_x+b*n002ovPDHLkV1ke~RE_`u literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7d3e83ff0ebabc90b3acc5c7415051bda09d54cb GIT binary patch literal 662 zcmV;H0%`q;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kMNBy1 z1UiCFfKDJII07dR7^sheHzg=SFYinG=g^n;rSG)>!!V!ld~HU@NLYpiSbzmsphiI4 z%(B=zup^*jvt+poI|8_rC*%xP1k&_Ca{{ehDuavO1wxfj8Fpr$>phejp;v)|^btas zW^`~LMqNnM3lz5?Fs&peBys)ss}PM&6-hNB>IbKcl1Jp(34=il-;2?LW&$s~jiQh> wej!-C&Gp?+7_1be7}JC$F7qwP5=M^07*qoM6N<$g1-40H~;_u literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b4b7fb069a82295ceed62f6576ef89e878893d22 GIT binary patch literal 666 zcmV;L0%iS)P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?`O z1U}giP)cczp64ZGL%2U>US#jp~#%61@T)65NtA+H*mwi=xmpfUg8z;4-Gz zd`Eu((aybo`U&$qPn)J$A>E<^S9*R{f*=gx4lv$4tnL#6zW@LL07*qoM6N<$f)vRh Ao&W#< literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6543f11814804a541c4554865a8bbb2fc370ee1a GIT binary patch literal 667 zcmV;M0%ZM(P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? zam75W@CzH`ZLRNq!tKb#AfEvFLb#u+`5*|Q6;HMfI)ib(%Etfz002ovPDHLkV1f>Y BA*KKT literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..74db3eab84320d62e52b1246efe6d072749fed63 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PX9ez-fE`!@cEEuHH)ADIf>xk+ zIII<*6-Wt|U;%8_Zw%bTp#1D*Ua|}%z`P7I3y~lQ9VAI&dC|ly$T1=y0wN#+odQa! z2gfu`LvkSiDn1xvB61;Mt-UpIOD+WJx;`U3u_FAGBAQ!3Yt6}ze2#uN#c{l(IRzM0 z;lRy^&k*{)Urr(MRe-DDdETa(h;GW5a<71-hO+HO{YAPnIJ0sTSb8^n!h00000NkvXXu0mjf D?2#Ze literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9a3932264b6d2023dd138960101b926e3ed736d6 GIT binary patch literal 627 zcmV-(0*w8MP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&Zf{=$h<-0%4l_9wo P00000NkvXXu0mjfiaaIG literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2b26c13c81dcbac54625d28ee9d5c2bb4b7f84d5 GIT binary patch literal 652 zcmV;70(1R|P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xf-n@u@$czDz3Ihx>;`(%BNO<1g(iBz5Dmpr@@F(W zLDB`{C!kmb#yTLDg1G+sR8XCl{6}RQ5}BIt=q#`chH&Ye99mQh@CDfkWQzu63!>J5 mfG~bQc{~k&R;3X@)3i4mQ#jvlo*mTy0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?C zL7+lFk&M6y=}~l?jYS1fAS7 s*H=FwO%2JF3?*Gi9N<4IMN#VT0J`=!=(U~AU;qFB07*qoM6N<$f=-bc(EtDd literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ec21e772b56f646c1639fb3b78f888636d4498b0 GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2#&x4P=9COO$^GPzTB5Imo`oA>*abxf*|xz6ouhMGvknDL_h>YKm>XPlu}QQ zT5F$d2pD5Zj!n}fWJ%!B#vR!Z@I3E=P+=u`o+q@lKoA5KUVnODa-1`IVMR*{FsQat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7;I*24cZn6$tKe6+&BmA4cigg6mSf{ zTRfA|%RuKQBuWL`Ddga}laQR4q@b%vc=#h!WztkO?a2wq&?}Z5C7ghM9MLL94Jrw| z@Yz~f65t0S3f}JZRV9qbTDg+3JklkBLKMYHQItB|0amCytvQQl&;S4c07*qoM6N<$ Ef|$S^XaE2J literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomLeft-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1c6e680793cf2ae6871d939c564192f494a93d53 GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{??v-DhjGF z0gM0>027cN31x&-6d-KQ5ITqgA#rn`l$;AcKAoR{AP66rbggwCYDU2`A|L`HAOb}K zsr!X}tKmg}khpNWB7heGi+x^U1RnwygB6F2ucILB*#J!o#3^MQ7OrdzmXWq?G%4WV zEX4F&jQXswtwW+vz-569hPlLmB@X}I6;!5DsI9h~0e+q6Mat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?r$rbkwHZbHUw$S}5mvL%CK7kc%95;Ke`5Pz5PFluI^8bYE` zAY?%;gM?c!6Sux^g=#Y>1a+1FiqlS%IrE$tN*Z*amB3phFW7AH2g>e0#`@_cat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ML-aR;p0YdLzobRFqsgFjKm-UG8h>M zfu3>}7M=@wbH1u($6vz$h{%DN@UkDADL?@VP{3Khm=E?b3~&kpyg?3IG5A07*qoM6N<$f~xKRu>b%7 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ea0a6f0cfb853ac16cb75de4862ff39e8f53ab2e GIT binary patch literal 660 zcmV;F0&D$=P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;TxNpvCrM+*oc3oBp~K~w!qFKAsLh(_u@%VTb6RUiz9NO9F4w84HQi%JD-geUzh z+*7+t9M)q~d9xh|A|J`%@edbbQnsXi2lT9c5auBA^Idhgq4nhghEt4zSk3$d_kC2O uh^s8at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?YSAz?X3V8M>iIyEI>(?Y^eH}ew004?9kK$-$D46`t4nrd^no^K#9EWiRRzyga3 z&3#?RV;EX#5V|8(Kh`oqwi$sI_NB#xpeS4y4fGPk$?;l9=n3ix(0&X);M(dky# v^%W7TF>|&s9i-qd{cLXvzK;!N7^dR~Mrcg!5{Dw;00000NkvXXu0mjfV+bGk literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..03c997e227ed77c35f63a14080b58bd18a90df4e GIT binary patch literal 660 zcmV;F0&D$=P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|H9I)RSR5x5W|q&zEDZxj-&T;7*J-r=?X*Vjt{hGA?IJ*fI>aM3d?zyd750(J$W zJkXUuF9MKSz!B(2z+LF#SlaA9VZzm8JA+r4X4R_0V(~|BJh{*?3u*6CQhkDm{xMB3o0)|(NfmGf39^QC| u#7WyM7@{k$(-LkVy1*M9+6FTW^Wg~!4?M2|PeD8Y0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z?x%4ae~022{b_2>;sj`|G42%C`-0uHzo;$lihfeS^%vuy z#dhzy?pD`zJ7at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DOP*GM{L3n|o1$5z)>mRPfw5;oCy#ZZp%{U6}bk}vxL(ktL524C2>2$1=S)q`GPqGP!!QLuNX|&=A*65a00000NkvXX Hu0mjfLQ^M+ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e19a542dee28365c97a07d9146ec9ee6ac372a2e GIT binary patch literal 659 zcmV;E0&M+>P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?f0 z&IGUlE|8#1g{U}e%PHeT%8#4-q{vQU=Y2WLN&rC+dS?A*c1P9y5fUQ;A|L`H(5rxY z@+x!Q literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ce66d6027f2dbcb2491d202834047a9d00c1f678 GIT binary patch literal 649 zcmV;40(Sk0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?Uua_!Y~kppZRSWA#4B*b(jD)V3lJ7*Z?L0 zDkLbv2p%Cl#c{EmGESu6xVcZVbWUu&FJ~z-peRaY=*3)(ruQQxMg>$r1ymrafcybh zzO+aoAS4zr*!k*;p#|v485nyvnc|Ki1*qT!#<;l&<49{`o7Nh{2>-h9>ijKj%rdn8 zuN|N_=MrAj;nMnT+n(MXkT1?8G?(%qBlnM8c&PQQ0-;+>fKtx#xuQ58Z+YMk00000NkvXXu0mjfRDBy6 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d357c9b4acc0e52c23c5837c96ef39ad0224a57f GIT binary patch literal 657 zcmV;C0&e|@P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?pSl_e)4iXgOaGFAxcWurWnZSiZ)d2jm$M5CIVoflURnEQ|VS zNj?O^F!U>6t-bK5lzP+N0>+plhHDoR1Yg=y0O5zGX+Ath3->sV%dxeJR))jty5{f* z)t5<at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? z4fG^pW2;BlBTz%aIQ*3?B)HPdmp~Sn<$cT+EFcJiV?v6lJi4BHm>3Zd0TB=Zrvf2G zt7d30g#c3tC@6zz1iW2&<{!bmvjUD-QxtIYz8w1~68uv@Q?&4)9`zN)iHb~Dt%8H_ zoWrSJfAdnurLF#_9oW!GXHf4p+y`y@=8W!urgM-X*ZiUbfpl}b3b(bsSHQN5v5@kb xUwz=h;pvbGGmOXZcYN6PIY)6D8Y~Dx%NOqzKIF|xuY>>q002ovPDHLkV1l_NCPn}N literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..212eb54aead903baefc42d33e15621bf9629f058 GIT binary patch literal 657 zcmV;C0&e|@P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0>WQ_CK4cE=Vtj5yfC(axp5@Z-d`+{VN3z@;5E%*+*(e5PL5>j_7Zx=hZjEF zy?+~@XcOAsYX{7oV+sFM;k-oBRMWWwa^eUDVj>*Ch|AkPJkat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O{}{Ef@(5@&vE&GN0=n%fX<2p~o(K-7`|0Sj|IqiF%(VF!$5I_cqxCIteAhj9lNGu`f<6y~iZ)DZsu zg}ZWixPQ^ew*Idb@F(m^_&p1!KITPxDp$at$+!N%la6C0ZHH$LO~Y-aFBGtKF%}{j z$3cuk5K>fTLl+fE-j)du`QvXAd@38PC`!f`QK&jyv^1UH00000NkvXXu0mjf7}Xqw literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-bottomRight-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d88c7b6bf44f7f2ba8b06bf1504eac5ceb7a7712 GIT binary patch literal 645 zcmV;00($+4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Km}Al1#T_C3-E2PJ#rMF>;=B| ztl*8uU!+9=PYirat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?`Oyqeo!e&gTYmpl{BjK(f3sOekzb=r?qEk=17!&KyMa&&+=UNpJ{v)=D>U@;f?jpg@=JWQ=MB gy~?#Ui+f&z14xl;C#~5&w*UYD07*qoM6N<$f-~n*_5c6? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5aaaaee3983c66a15d6f71119cc9048210e8c632 GIT binary patch literal 707 zcmV;!0zCbRP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?oG=quvhAY2dIlh1LtAg*J)+aJ@N1iMWzfKpSj+$LbHXUQpDE2+#pq zGEz|tHqRe{qO}w8u?NbhV&at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DF z0=Yry&bEo=266ZvkQEG2bu{_yCanGuRZoSYMk7Bn}Y_ z*aAb$?ZzAYsbGIKq6U=^2p7BYt6xni)quLTorID%ATX=qC&Oy7&0J%(q1Kx~e`QTs zXr7%zG`rHki$*~NEig8g@e#w6P2iay_mGBPH$hnB)p9#H0Y1Q#p5nW}Yo(l%Ux24B zZ3B^<1dvZ5Eb`@Bkd2DnXB~X#m{?1_Tw@@{mB!UA$9|-yalC;)L^dFiNF*h=nP@Z= zzgSz?#F*3G-UhB1t38Bqwt()dqiR9KYq6;g dtKyQg;2TR)fDwv^GSvV8002ovPDHLkV1jD3XHozF literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a0af38ca12b81e09eb649afea2847dbcd5a9c37d GIT binary patch literal 760 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?02kQinb3)#y85?&sM{SLM@v!0hN`(GgOU?^lXQ#MR!i?;zrR`iYD zh|UH4nlT5=mKX#3PJQ1|^9`SKZcFl^*5N0wfHu_A*uJCGjdb49h0ekF!x~-tK}%H0 zJmCy4XmJhydEBNa2iA17A{h*13WDSom72=1TlWK?9#A{?_^0AuXVbwrnB+YP?; zEF#pNEWim-twSWa>cSY4&={(QX`4$jk>{nHM>mLgbbEpmT)8jUCzA$65qFBVqnA(@ q$ig3gR97SK740`BO+R_!DcAv^Qh3VI4u(wt0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?y6`92a>n+|_@U$vkojk*&&X>jA*i%D)lx)#r$pa5 zO)9_icz)quI~gK>r|^;}A6;Q;QMsvlQ51 zrvC0i#0x&5X4`*Y#$WpS9k+Z=H4+dOQ1eO?AynaLn{B^6g3{MVSRggJo1r!BnkRi@ z$8P%$pT*7u{*s(PCX>lTI59CGD1Oaat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?20PRaLH(+QD4oh}>A3rs}7H zbzP4$Zi9O7Ns=67U?m+*)9jG^0W+6_FCZVs@r`TCfD(gmIgxE#_gd>Rj^iUOpl#cz z>$)u_^=j)rWLaiTaqT7}xUtt4B$ea=JAo408u7N;tu?2(+=6`SO6vo8hF8;?YuCS; zOJ2I{S87IA8~9H`1A#yw@C_Cd7X-zh)eo=YyK7+jX0wbU&s?f08~EfCG~6?JrtkZW zHI3_+ns5)zHc4`5xFbt5AEI;^h9}f6_@3pt8$Z+d7`U*)ah6~H7fkR3A$AMbclHo+ p0vdQEu~ZA-6*N|k7ZkWRz5t2*g2z?`#eM()002ovPDHLkV1g>iRo?&r literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..639a3b1c3a356512454e319a49f5b42ac3f51442 GIT binary patch literal 768 zcmV+b1ONPqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?jqPw$*4C^6k8{1$Emo0Wu8C z7@XEQX3e+bCw%RBR%sx%00CBG$ z`nv|*V_-fpn%6nrpUMfUYzR}j#^?^Htd7;5yE#3?8OuV7_X!^J yUa*6cf>eKpX(!MHeCxNW2c>GM9ru$5&Vp}Fb9)jcoetvw0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}=Ydtpu?K2uH+@dKL(qRH> zt8?rz=cHb&uAnUMr9I|vylw<{?A8>2E+3>p1o{ay>Q(2|uk6-xr;d4l3l7T;&U}a1 za5eiHGdG-#jh(veXEgJ(4g4jkfkYya@Gxd#)KL7QetH#OT?6);ZEaL!PHFlL2tMrf z6Hkat_C>pQsL{G{&lB=^uISkcat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?U_C117nc$ zr_asI9eevH+9vpX&8vJ9Le&6Y?|(G$$5cQdZyJ2F%)mF_7ttbvPto?rTBmusF(a91 zo5f{=QctNy2lSQ6W(p(z`5|qkaQFI4)oQ%wPUdn9ZT%j()FmQd4^Z;yrJC}$N);-{ zbB!%K_~a8rX3o{L9(}i8g(i0`dx&zaneE)bF-aRpBoc`h5+*`{;*k33R(y6FSU$5Q zMjat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?zz587%;) zL`tv(N}vIQ8xq9CATtn^kDM7^dFbfpVRpr{g)ZJ79*e{xww9VI?ypfimX{&s7m++FV2HHm<09^BlsbtP zy2O}S-9OcaujKK7<%+-pasd&po>wyvw-&OxU%LfW*^x;C)}eAi)pOOfnuZQ7dq>P! zX9B;(CE##4917e_m<`4E;=5Pz=n|;D*}_KIr7fnG0J(`H^T9ey+CA=&8#GTyLTSr_ z(%Tl?n%Oa>Y>%f$nMkTAzE9Zkfk9iqe*XneLY#kmZJ-7L96&dEsRmGpSlo`Q;*L@9 Y0I=L=T|~6qumAu607*qoM6N<$f^OGEt^fc4 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..560552cc762ba34b18e6186ea21f9d626b1b05b9 GIT binary patch literal 668 zcmV;N0%QG&P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=pX-@pPazyd75Fw7kU3Oj2*#`h}#0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>>QFJzPe<_JJ$&*KD}Ex=FU033h=Z~%s3UKX}lSpT;^0ssI207*qoM6N<$ Eg3!+-eEat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?i?!2V3>c05Et2M;CSsrqPD$j!GehN zZc+J~RYaWN^L>cZZ3Lo*9h?f$Ixx8i7}CzJg!fDVj5Ty9SXDJ7AY9-xoS?xp2Uu1W zq(t}#-ajW5wNe){9greY;OSVO;`Q@-`r%LfN8q-8@6-jeiFvYF`{CaK10A=pwpoP- z3!u>Ru56GY{sLqQXDvZRE&>(_XPuRE68I4;zyd750t~}E0Hqu^j*G+_H2?qr07*qo IM6N<$f*4vS_5c6? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3a7efbb513bda0e5b36b101744e55717da1d5521 GIT binary patch literal 673 zcmV;S0$%-zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?6uo5MqblZBO_0FdahxO!!;B`-YoIL-(G2SuaVBJm z-VwAqPxCxKD5c(HkyY2G@B6o=^P(uMi))M{(9uKmrE6Ti&D2?&FeZTL_jUQ0OT5zn zqCe^t@hh4UqX7uJb(zu<2AVe?MbR<_egzv~18jf|FbwknXQo?Lf1t@o00000NkvXX Hu0mjf5R)go literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bd46e5ee46edeedbd17c47a968e07bad6f403133 GIT binary patch literal 634 zcmV-=0)_pFP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?uf_owp>E&?>Lls}x`FK|ZlDv$ z2y7rDxIsOV8WIDggaSW!UvjyWhTQc%KoFLWLQjk_8SO;vs4b-<|7*-zqerk(>f)Tc z@|YnJQ4?UeroB+VHmB~D^RC1IIt%=Tm(-cxawH;V1;6luIxzf$gseiB*4i8DmnRRe zXkCFH{o5ZmLwDUqXaalh&#}V03LL#ZFe0G>+IxXH3vm3i6_^AmAO)m=6c7aA3s~7L Udnuz$GXMYp07*qoM6N<$f)QmC-2eap literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e2cce4de826ea61e603dba3dd7a2acb56c91ead8 GIT binary patch literal 682 zcmV;b0#*HqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_F{6O*HYOR-heN zi)Rn46-WtoASHNEV*)rr#Ds&q0?5JnF1y)B{%>cpfFS%kgpBCMNWVGSk{Epk_q?S} zntS%l_?lHmhTyxSt*0vJJwmGQxc#TM(4~?9Xd1cOUb7y^bQX0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4ToaWZ;?4y-`2614*Dz*_7; zD{$?A4&Y|IdGp3N5=e}Zzrf1D`4W;PyPNmTOtOHY{5yo2_#rzOV$HxperNKzRqkCT z^fhaM8o}`hTM6EQ;h-fdb-=%}%Y-x1YUPpgnwO=q1)Q3w1aJjTgZc%gt)ze*N_BP^0D xK-mM+M}RH_I2ABs>PFyKsDKKnfC?yz@&s1%IVyq#fieI9002ovPDHLkV1i#pBpLt! literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5386c2c52d55c49d3f360b92f800271ca84d2c3b GIT binary patch literal 658 zcmV;D0&V??P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?BF+-v}t<}bEzh{-^d s#{_K}pdYL?13!TcumLu}1{j8U0-psf=iZ)&{{R3007*qoM6N<$f=y8v_5c6? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3978481871bb2b0006a24ad05c3c05edf94fac62 GIT binary patch literal 677 zcmV;W0$TlvP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?OXBP{w1nfY<<5#Ujtw1}l7CX=i zqyYjQNC_6e!#gGS|39PJ)e&KO6)t;Y}dg(S#TSVD2`r7(+sH1gOq@5CroC_!SaB0!RP}APB-6G9zJ>Y(hmH00000 LNkvXXu0mjfn(iP7 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..41bdef62bb07e6552359a1396cf192bfa0c129a4 GIT binary patch literal 664 zcmV;J0%!e+P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K;qr}ysJ1_a^XAvDC}z8u*Bt zsGat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Xtqw#R_Q*zrqFO@Cj6EF0DxefCs1*1JPni&?1;yxy$`QPU zC+tA!iZAF8t8DYMmk0ES xxdZ%qU=j=>kl%R~(qIBVK?FoV1Vlg(ga@85G|7*HxElZf002ovPDHLkV1h8MA{GDu literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9bbfcdcd014c1917d1962a5b61fd32b75a98ad5e GIT binary patch literal 676 zcmV;V0$crwP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?N1;*f%O8r!n1d!C;RFwDP0sEH-jI1pG9VGf0v0%VnY zXOF&S^-(W)8vr}K94iGQRCPP4B*%g^3i}&fo!-w?32L8ev$)2 zl(ryKxjTxmv^;vlAcX?^sX8L9JPG&BhR5W#Abt8*JQqVun)W&mk+%`{u!u)exV05t zD4;i1iGaWrEs`ss|G7*KgmBS?0Mb8y@~Ja{pTGhvzyd75Fw6(t|2#FQgPq9$0000< KMNUMnLSTY|mm`G$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..158b06665d5cff3ea0a2d3d0b10f9808c86200bf GIT binary patch literal 654 zcmV;90&)F`P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ujl}dP&aS`brN*}Wdm0*Zr}zw zfsDWgb_5rYdRPp91WG9KgZCwm_gVsXToV967&{6ru{xdsuPqQQxm@HsKF=w0{;4%Z zE8*@~ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topLeft-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d14ca26f5a5a8f72a007192992e24090ff6483a7 GIT binary patch literal 600 zcmV-e0;m0nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?giC^~Sj-)<3_X38lq1J#ffq>j_w_1Dat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G6!2~K^M3k>CWv7kRJNU;UvuKt=r6Pqq+3>SFE4JZx7RVp1N z#uX?z_zM_DOf##Jm=|mKe%4k#yaztH(qTohshiV8K0ACXA3uQxH?XNG%Oo;NVcC|# z_z5(GUP37(G+Q7y_HAXq6DX00s!<3VlL+WYs!^#GCJ}gDK@*b*bbtj|fCX59VVEb5 Wm_gi1n&{mC0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?XY3BfcF@z!ywP;iQBR2W#!oJ+3j0y-ymG1^Pr$B!eI*pi9L|VvZ8L zsH%#7y2GU*2`ovWlv=~D1PDCwolXv2W6Gv!&Y$+rT7o`lnr7G&R1Ol_kl4F@vnTMR zEK7}zsd2f+Qk;hNeNBKsft+ScB7-Fa@Z{QwY+(rjx)p9IVF>{rSbzmsfCU(ac>qSh VNt0pt26F%a002ovPDHLkV1k+HC-ndT literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b31703a3e318ac881733acd293703d116bd7b141 GIT binary patch literal 689 zcmV;i0#5yjP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O|3Wk|UMvACP&>d1v;<4=AjX>> zJ$SGKLnY9Ol)%A2kia^EL}LP30)~V0l7R&Vc>G-ehWU3y=@l!IPJ9$ z+7)=RmLv3Hho)qjNeufl9E4xi-h2&wbEcQYy?M4cK}iJnbya)&2^4HX6N07#@F|6H zSqkkZP;eT!^nFwqA&6FGZNC%9NbGDUVWJZO9d14l6Lcc*{sj$mBA@^ZumB6N0K+g3 XPzE~Z;5a4_00000NkvXXu0mjfMHMAl literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b6c14b8bbbbdb449e237b2f268e20f9b26768afb GIT binary patch literal 685 zcmV;e0#f~nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(G!mCIyais#^E?`cp{7(^ zC1w>Mlv3+33~NkxB++%Cpp^IeNBL%yTMFjv4j9!Oh#lYmJk?!L33ICUcdzwU;!3j0fu27;ons7 T>ukf(00000NkvXXu0mjfctI%v literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bb7be0dfb300b14766b1399b1d55dc9d6fbbc28f GIT binary patch literal 645 zcmV;00($+4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?LsD~ulK$Yn%F6M1{@ zA2arr8<2u0?l4j=$dxZgq?fd@SYRS!FkUpa5+xE<1z6(15*(QVZ1^$OHmLN_r)?(z?|In1QFIMgoE7iCPF`zo4NO0uod} f1yn!<6h-*~t{E@oKAx=~00000NkvXXu0mjfOBEF@ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cdd98cf4bae60ae862f40f1f7660c338ae0ddb57 GIT binary patch literal 702 zcmV;v0zv(WP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?a3^dD903Ev*s>5DjErpL1M@Cx+2h@}e`f(jd3LDkgPp~UdU%<|gJ}}j zW4ehGk2^4EP6$Q>@c59?sz3kwzvpK{L+s2AWf&67Cxc!2+6R_Lb<$`oaLMb`g~x!F zoTpM#qE&%{g&WvCE#+A9WPE1%197shDsQ6)u93yE9*-z*PD!G_Gk>?r+fSgRH+K=S zBmt}?g}15{+E1Wl|DB|=y;L3tFI)3lRrfG~0_I6E7>>||KyWA$kbcBFx)9j>oUdSr kE(GeJ0xF;aDxfIJ3ER3#;3-KuZ2$lO07*qoM6N<$f-@X7`Tzg` literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d2cbc372d356752c365fd5e5c73076164b8bca51 GIT binary patch literal 674 zcmV;T0$u%yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?OwonF+Y=1Yg@6kxpaLqO0*azM0R^}~Ar^wA(EtDd07*qo IM6N<$f>?PVkpKVy literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c48d666224f7dcfd8a7fb0e2ec361991bca9f0e7 GIT binary patch literal 676 zcmV;V0$crwP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?OKN|0puvQ=(Jb1$jv;<4A1F;fA zC2}*7gC$4_Ue%a!7B(at)+}KS2j(S{O<-UjpIJZ<#!g_nkzR@5MrkU;40##{B|0!c ze-u~3b;29>V?l=w&)O4kg_DYSi9p!!+qUL%$!V-z(&#PFlDUw=6lc__I7xUFs3dL_ z@~_Ymk&%d5;$iFeF#~M@y%~Qw>cLcaVgIY&djgF}K?%==PC^UKZ7Fz9pb=OGIWM|G zJh8L&{Y}7-nKi*60-q`Yy~_ea2&Aj#2r3LA;DQKat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?YXVGF{vpjga_|S$U!*TFTa)oFwDOb*k06it-)o0An3H#9oB~sqEJe8 zumAy`;N%iZiuFDW!?S6c+mi1C@T4ruI1IxW1y1;Q{tSw#U>ccA8r}kP+P0PBIOdd! ztHi1TMk2zc$niEd66l~_wtnwD@C{9dOOlz*Df_;^{_0;nfr+ZBQk0-1Na$coVf6$i zk|Zgx&=p|{7hB(E0tB56<~D^r1n6KgB1dZvY{={vl(2_@3oO6_EWiQ`!@L3HO-}rz Sk_KG>0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O|B&dJ64naTn;{;s0xiK3?7%e^ zVyHw89_&I&;HoB!vj|ZS7zh{+&Pz5sfg$^todFc(-=V4(0q+>~NC=cjax_F1$7B;U zz(acsgF}E1H_#>E{kF-+gq8$sC$h=%mLjn#9w$TaqE0nh3%oO9Ydp|VLQ_|wQvpZF z*1wAc=T*rirXrD6<#*8oAGpH?^5^bwSw{L|^DV#g3Y5&*hS~EvQmMkIstTP~pyWh0 zmhp@w^sn&NRe3)Xa4@pS?Uavc4+5FAL=leBhrszYf(CsE)IkMQKm}AlQIrR*Jw#m2 S=EcJR0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?pfUQ7F(1QnWc3>GM za3EF!Rw5;E_K|UxfC&c-gf$$T@3I7j-EaSW0E+VOP}_$rVn#P|=_Qxy3+Bkoj&k&1 zg5mgJgff$a9=Kg&KK1#TFpxCjK$<{0T1&gBUgtcA>5|4^friYPeVQVLO{JrRQ-M+< zVUM07!3Zjel}HqA^)B{613MVcVC>+qN!)S#R_{E4nl$E+xLl4xQdqR5;5>mEv!_g^ zm&v0iDQw&7ekNck?*IKO;Y{ Ro?rj~002ovPDHLkV1hFWD-{3$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..21e9c7a0882cda9e551ddf95e8fc146d9cb33bb0 GIT binary patch literal 697 zcmV;q0!ICbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Pzk&P~f8`NYqqTSgJb@m;BiLx{ zw50R~#*@e~EKJ-ZSXr33<1A5QOfVQQ6wWJP0}H&o>;fptuS0n^W^HB^dx4dMb-*V4 zLz?W!;sXMdL@bS{#>7~=GY%rY_~dy)Nv2(nLWf8S48>-2yKI9721RO=7IWY zuToT^QUTAzaI+y2GK{>$ze9g%>6kaa^cr|&B_BIG46?;3B~Ae*@8(xt;Lg0mv2$68 zqf}_+Rj9ncon%ib5mFg8rNTIG-q!>?{@>uwvPEOmArM}&0$@T9bqFN(u>}q45GaBQ fsDKKnfTAc@EbT{@NUA*m00000NkvXXu0mjfy0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Jh@#ukttNh7hglbGy zFbqqOGa;@7KaO}f?m+tZu3=$>En_E_J-@9@abq&T7mQ)P46dX>WCak2r9d5(heF2KY0D{p=wI~As tCv}Yy0B=XopaejQ6hHwKKmk-L)f3`CJiqr+C#C=Z002ovPDHLkV1iM174QH6 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/borderRadius-topRight-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..38f13356d972fef44f8a6f04d7af950cfcf92eb4 GIT binary patch literal 596 zcmV-a0;~OrP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?h@2WrvN>GAQl%NAzQGpWZKnZl9 z1cr>n&xVNI`EXBivmdj`oXkD|LjI2P6;=Vym^H0raLg7rN$Vj>N5Nh#?r5|boD zZ1$$w+*Bf!j2DR%u~CV05)CYn#)S$jCR0#}UL`8uo&;fObuD0lzKY{A!iw`_@YO>f i!7UV^00k&O2-yIErn|IJxy0cB0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?V*mgE literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..eb726e9d3b2dc32f6baa407fbf6368a0ae13a7e4 GIT binary patch literal 692 zcmV;l0!#ggP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?C-m3^)Q}8FegoeD!^-R6P52Ic2oWFxel9=| a1mOmzra6qR$DZW?0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G%R}ytpl1%^25taOAWq;Yjv#J; z6X*yp0nR!CcLMk~;axaM)p)R9Qu=5~`oFdiDT?y%cvC(O!|)EbfMr!x?MJy2Tnc+2 zx1<*_BqNEUXg-dS0EvK_A8p%iTmZLE;pQ&)bpf8|*{EZ-;28yv zZVXM+B#7}&tY{*l9q@fW9}1^j9LG8cf}8}11Xydi)!gzJH{ZeMLu@jl5ils6VGLIo z8Dq92MEV<2S(Z0mMjUNX6r%Ps;tmWV*7PRg4txp~paOm_Kv5Ls2}n9fVu1>)$^ZZW M07*qoM6N<$f}w#TGynhq literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2c53cfb3afa3807eda96452e36aca4b742e535a7 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Y@UQqkUK~X?a077y*+4IN=Bysv z0Nns4&=K5#6*wVaq_!m?Mo&ByFYlK?NSn|v-z&fvV|A?42yQ0f=KkBBoB8El7NG_U zB+`Z_M=y&u2q*z!^G@<>eiUWjoGT#Do5E1Wy zvKySuWz^56N2*_=H=u316MTr?z?X0U4)FH?j4}2ArQat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?vPczz)y@XR!iHu>|o9 zBufQa0v%`x+)2PU37Z&B?%>bC`I2GC3}N5AS)~L)_;<9=$4Qdh`o5oQt+PDO_oLnk zy%fDWdW%>8Ia3U9&;~@~nqt5a(9k0Yg0(AP`V=X0y^jij#dJuGe0VCyh-&D0VH5)# zbcW?ew+6BwHM$c^at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)!axj#9|QrD015~WZ~!RaP=JMVfCPpE zPyiC<03=KTui;28`^CMn@PmFy)26qiZ?6R$$N6_gB_GEa?@Uuh&3e~)J2C~vgY^s_ zGKR*QL#l2M0*Zh(<>k9UF@dSd-Ub)YF!ot*#kfEaFoDL2amdzS_S;R&QHXj2=afSl z-e$ew1@O;ppjmF#Z*6$$6{D`es2SH(Zy=(sz+AZDb&L&b$$q1c114gDp2!Y-3m4!5 eelEaq9Onspqbr55*k-)|0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#$>EJ_diIPkX(K}e0zaIPVmjK6cP956j<+!N7rCbtd-p@WB z*UsMVUQoD^_9xHUt4+TdV1U6D+G@Ne7SRk?40QT9??<E@3cm1`Euu^4sTO44gH7lAYjdY>8at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!Y~kp-ysU13KgPc1DGJ*AYlTs0V4q$ zzyx@NY><*rk&=qz90?>uEV+iiI|eQQ+S8zLB**1AaD|AGiz^^a^X5jAz48t&at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?a?S)$(5ppx4W$kRk zE#tbHga+^aGlGN%QggDs+BAg#iGb2S@0h*@eEW=BFPya?;LPEz!h|qmS9TBx=s?Dn zYaL>!*!~D^Cx&Qm&36MtMq~|PR@82!v z5F(3!F=INwEhCqikjQ?A+yN&dp%@<`cHmp602T0a0g9q1Pu?vu=d*BAd;kCd07*qo IM6N<$f)+s~bpQYW literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9477007a4986160b71c1f090cf18d81b4a2af49e GIT binary patch literal 679 zcmV;Y0$BZtP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z*UfV&-t6^IpBiY160 zU)60Q>e;Zj%@${ N002ovPDHLkV1iGbCTRcw literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0c73e02f069187ac363b78185b5c49a52323ae9a GIT binary patch literal 691 zcmV;k0!;mhP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0YMPOU$rmRj_^5w*jl*(PGFqC2{2s1 z5paWX0v7&k-GC#^mc^7R$s|}&h=uwk)77b->AbvG8NhLzUx%J~xyHl2lz#$E*VOOa zo{c5|N3uO^Xi$Fi&Hw`pZq_+2-F2HVU=fh&azvq?H)doqIfAkk)1wU>Y40U%nm4P8dUKjW(VGd3vdBn7vMOK Za|T9EJql0kcdGyZ002ovPDHLkV1f!6EK2|Y literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c099ac9c17bd36a04392a1ba5b9e2e0f4da9b95a GIT binary patch literal 678 zcmV;X0$KfuP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?vPc04fkG5E9X&rFiFp zb^sMX33i|*aK?mn76S)PGX5Q$FIk4nlHHg020&4ie}{&AT*T(WWeNvJcSB)sFX0mK zy1HAMJ$t4D2{rsYF_T``hX9FyvUyf;+eRLnfXk%Y`?vtYnH=of2IsgmKn8(;5d;{6 z6JL7hVz@Q-+nJbSAhH=4BW-HML-)A6?0Vl2;DuDO3mM0-B*L0cNo@}TL=iObuLy(O zzM2{<2$4m=co7wL813?QB(mQkcYtvtTHr;*4!jE$paOm_Kv5Ls4s543%}v{n6aWAK M07*qoM6N<$f@PB=ZU6uP literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-monospace-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..822be59e9e62b44fdf14745e7c1099591a9a1b44 GIT binary patch literal 698 zcmV;r0!96aP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@=)h!3V0ILH*h>*CiUPUNcxxT!_-y#ih(G;j65Ii4~D8fQ|pHPJo)dYmznwDHva&at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$Bsu>r9I ztUybk1GfYlkoE7dBMv7w=y)*ikYuvJettrvD9XRXArIRmySj+iN;bu&cXmKbQ5rV; z$(x^~h(y?>P4c+kBLNZtH=pOvtCKuMieJvYEr4rWn{_R_KsccvEMQC`_(;@jyD>Dd z-(n|tN`VM>fT}j#Qv^4A{Q0ON0U`lxcFt;89>IFMMyK+at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;i6b0e#BjK#AieAWG2vYa9ecGfT!5Hos57L&=;#vJQyip zY6L#w;GLh{-SmPGvs@?vVDEN;zcUhAfOmZLj&Ja(@sARK!b=+o`w72>1W3T&1qdO; Y1LEad&@gt(^Z)<=07*qoM6N<$g16urGynhq literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b09718e404e10bdffe12f4e8ded0b78a9cfb8639 GIT binary patch literal 776 zcmV+j1NZ!iP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?p%K1OkCwNA*Tbi&ucgP-=<$ z>=-^=6ptWEc~s-!>S$AF1Yd{})4$K5+Vl2+L6a z5mlyF-%7GGpTaGK>_JMI)%?_2Guo1@(K_?#Z~rbpqfe^uoZ1sU{-K?dnXf~B1sYwF z+Ki+o=H1`Ie18*QaAq_^ct1SD325GDU#qAE0)aqaOFjT^@@Q>Wj!rlL0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?79fS^&4x)4r zR}j*H(*Y%L0Et^%g3tWsjqpZ3n6N{*Wj|?|)iSGnJG=pKI2`{SZ!RGSf-i<0M^={Q zJuKj!cZP)H$US$z<=()aIEtd}ToQA3=fkbg2tZxe&vQ9#+a^$;65x5>(_GFl43AJ? zEr5sb8Ma{<##1@`_6bJ6q*z-3Imm-Ie3?q1NOSu=))r6{MaBa%Oqfy3M{zO6ZpmSZ z$^$&$Q{puq=970&;$sat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5JS6;HAW<2sMG@9Xf9Jt7@C z1M)?gN>65|B&+a+#SN6`4crZv+c4Ua+zp?M>DWUTh*xR?KJ)Mx1szmxRpG1A?|?;0 zlEVnHTc30Z-`@;a>M#oAeDU;WAdhBWf2nRskH_Qbz$a}7U!S@c6*>R_002ovPDHLk FV1jIfTL=IE literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..78e289a9a2d128bcb0b6728f3023110e41f05825 GIT binary patch literal 776 zcmV+j1NZ!iP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?W2h~1i;}M%>mbDCJV~ey(R%70mc}fd@^I2rpi5c=A+XV ziI8pqr(bi6)t*bznGd2qNr+fL(=>asX5^B*G@pGZBBL;Pr3x$0VZLX6AT^&uoB_s` zat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kzvObwcv)YM*8zz{;@=r{39>A^v&~rr*GmLI-HFYzO0E}e z+A+d0eA%o^M9o|_4?<(Wu?^5zD9{?%1ZdV!pfPY{%{XH7O~BtQs=VYFz`#ZNu0`Wd zf5fj1@N@;6tHv-&_zbGsazh~63|yr*h0#yu3$6U4EXO;@a`JX3|w6Z04NE9vs! wMsE=jzFr0dA4b29qK|at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}y}oZmumq^J90m7M;j_0SbYfFzu?$)-s-KYqLu-3@5`+`DSil(`o{fXDz7 zU$$w8cntv(16zH~ruSjcB$({N2qrI}7(*M-yHCwnfvy`xM0WQ+)D}Y&z-W8F={W7G00000NkvXXu0mjfM+jxZ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..767d6416ffde2a5e2d89a2573797bf512ef02859 GIT binary patch literal 765 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{??}vu_5-WHOlv+(zsBjViCNat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?c{`v3(gAdU z=>RGKI)DyxLxKZz043ziA!cGbK}dmkLT>nztcjel{5*bRAP@+=I-)8;ZS|2tmqx69 z#XmftHFF9PjT5c;ew5pSKT_>=rz%Npbk}X}1xEmI#;7u<<-fU2=O8fj$QghEN5G6m zNA0w{mq2$P!TM!^#svthOw<@Z$jVPYL(>A(kBBK`qtuMfd=j=>4)BEMffQ>K%gp#z zRAvbVJOOQUw@GHkk}62pzF&X=OMvQ$ggju(NL7%<{MCFhnD8o)kvfOpwxl)R2PR;` z7NGvb3Aq`mC2!2vGyhn;qYi>js%cY=KAG>!&9cmw!@mL)Et$ZUK0*!iJte@9n=vEx pe|VY`@QG>h-FB~JAP@-D-~!bBQ(b*B?3e%m002ovPDHLkV1knNQD6W7 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e3dff25a49a7a42f3e33ec0e1f9dfec16b790373 GIT binary patch literal 777 zcmV+k1NQuhP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Q#+&zW?P4onA02N`z| zR}j*H(}C{{Lpm@ePyj!EizSZ_*k~~~>zmO?BUa*R_en$+i{;sIrUHthIQD(N#_$k^ z;Tsu%H9uIBVpw6#>%CZ)%t^|!TulWbX03j1ghT)}P4j6Glac_D0LO7Yrea*z-H-r@ zfF0T@&-3I~0BWDIUm!H2r3GN)J@?rB>rTvY`nGL%w6uUIiVo^G`p&8NPJ@Ms1&@fP*wn!m$*FFYqTpGKSk zMqSAoZNu;W9P>RSfYD~;F|uI%@GK?(X8gVy@5y4ZSY~npU$2LpW?Pdf00000NkvXX Hu0mjf5@}X* literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cc550df194a8ca27913866d648197a32d5b3bb72 GIT binary patch literal 783 zcmV+q1MvKbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?UqK~#7F?Ul_@!!Qtq--@3cNeQ6~#=}8$KnHdQp@KxA z0#X5{gV2Ewkl{!NxCE|n@S^n(WCo12Np8_M~m9z{q@6!-W+GwgJg2xTyiCiI-&=*DtpF9)In%ryX zxT*|Pz@xN(h0(M-!@vU+s0@ry<-U3M*Yx);uti<>vm6Rk1`2XAc^$?N9NF&vM)(RS z(UzhA44gMF@^?vg;X6UKfD*NV7jk76Mk&e7@cA7oq2w4_Kz^kRvK8pspL}QaL9Gm5 zhk6GDDM>V8On-hly728}prsC@bo}~*51zdlI0fHz{SmN2Boc{i$rl&EYdfxXXcqtg N002ovPDHLkV1nubS!@6R literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1e30d5be331c144189c28c16ee40660f8612d335 GIT binary patch literal 778 zcmV+l1NHogP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>-9b8tIe?T?(m_NA z$te;XARUkj>=M#JTmt7PVluNfh6Bbsh8z1NYghKS_wVc<1CdDN+MzB%G3Or{Mxrd- zgi-_`?<{4=Y!sx>%&s396={xkh zrVPl=zWn4!7->*dh8dqQVC#Zgf3_P9WX1{C=x%t+6i@gU*5^Y@J5 z+hIQf)GeuDgfD%D9^pI7fYO9$RrT_o{ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-sansSerif-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d57e3ecf896a24bd8fdf15e88225b87c9896a712 GIT binary patch literal 792 zcmV+z1LypSP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?AbX4tlXp2edVLb%+pnLmB+(~I4%fc(`I(h2L#=*`Ff zB<9+g=g@ss9^eE|GX7>pvQ=fcuOFa5CE%mB1Kx WU25!9@(Zm10000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?HQ}%BFPL$xO#1@@QovI!!$G$E zLKQ6fzW=I0Knal2`sBSCHDS-hd<{t0HuR6wns(BXC-dz<@(dEGf|I4TQ8QY(-6cR7&FEhfyzs0jASov&dqg6U b$c-EU%%NYNTbYat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?m5gef-xPj*gPN0t9 z1iDE_s2d=?hBL=S0Szy`e0MntgeLs`3!o^9lEHgF_?dgfnKPal;9p1s6Q&^FlKgA~ zE2v{%kkf-Ci2`F~zNiAH5GK6T!RO+A7;K0ONI`Doa%P}0mI~3+F&aa z-f-m1c);-rk|YXD9vCqUlQ)pLyaHXRHD82N0N0}#*_*cd4Jpx#@wp9O6fpjcW%gxEs3^+fc>$s0 VV64yAcv1iW002ovPDHLkV1h`JEY$!2 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-aqua-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-aqua-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..a45d54625f7e9886799e76c798aa0ef48fbc6992 GIT binary patch literal 979 zcmV;^11$WBP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?g$66#yNW4pf4<82exiUn?0bv?~cXz(M~#`R(p#G=Kii?ii?1qsALU z;kodA7mKE=$J@&p=d(&amiMX=h(9oI{^r{qho|GH~QT*&*8`j!NG;;(+3AZ82s!{`G!3C%Iy!e@yaMdEA8SSpo zw;LQ%884lMwh+Y%2o9OS#JGPBe$h5gXI{p(H*C>)m(NJgkN$;t83F0QQPbSIR)*3# z&KcI*unDy~=Wjoq6&9(Tz<$t9M`6wuE2GpT$&CBES(tl4hg);SIys@uD<2h)0KqpD6Il4HtjIeOfdLDx`hx(9fA7&j&Z z?5ChR_`zFn#=tHEeAksfGOD~%mHEO(T+ymd9#Wy+$UCICe002ovPDHLkV1nHV B#aaLW literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a45d54625f7e9886799e76c798aa0ef48fbc6992 GIT binary patch literal 979 zcmV;^11$WBP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?g$66#yNW4pf4<82exiUn?0bv?~cXz(M~#`R(p#G=Kii?ii?1qsALU z;kodA7mKE=$J@&p=d(&amiMX=h(9oI{^r{qho|GH~QT*&*8`j!NG;;(+3AZ82s!{`G!3C%Iy!e@yaMdEA8SSpo zw;LQ%884lMwh+Y%2o9OS#JGPBe$h5gXI{p(H*C>)m(NJgkN$;t83F0QQPbSIR)*3# z&KcI*unDy~=Wjoq6&9(Tz<$t9M`6wuE2GpT$&CBES(tl4hg);SIys@uD<2h)0KqpD6Il4HtjIeOfdLDx`hx(9fA7&j&Z z?5ChR_`zFn#=tHEeAksfGOD~%mHEO(T+ymd9#Wy+$UCICe002ovPDHLkV1nHV B#aaLW literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-black-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-black-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..0b9f3b760d479bb49cf4141a373492b986cbc2dc GIT binary patch literal 965 zcmV;$13LVPP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Sf7Z?}o3!VQ9mO~CFz13=U zFN8=taijoSwYOfcw_rHP83GVGj?4^zoScLTa!Pv>&I38*$+cRoM&cgvbZI=B%>+9| z0N{ZrN>5T|K<@7M`#zJ$kir1#zI@lFKT`lw=#o{Xk1_*-P)0@sJYGZe9?S@J@{Dgd z%MqZh0Ypww2AcG_mSsI@wzjBPrH?E45bP8I%jI&2v+t+pWrR%CR&n$R(Nv(PWk6MU z1S&q9eUKOnnQFp!^aRY4fQV%v_dk$Cs`!3D*32k%WIWGjAps~zPeBs@jGBnvX9ZD6 z0Fl51sk!&qX7&5o0^+trd-WB|9JQdD&n&<~0uW&bMweph`$!{z(+gcps*Tz%Xfzsk zbcrA`8%1}EsX!AwquWk3kG%`{aL}F|)K5r4j}kx^2}s*`6|f;3bu|%wwW02+1^F9H ngv-p=we{K1rM5(g68{FD#Y7<>at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Sf7Z?}o3!VQ9mO~CFz13=U zFN8=taijoSwYOfcw_rHP83GVGj?4^zoScLTa!Pv>&I38*$+cRoM&cgvbZI=B%>+9| z0N{ZrN>5T|K<@7M`#zJ$kir1#zI@lFKT`lw=#o{Xk1_*-P)0@sJYGZe9?S@J@{Dgd z%MqZh0Ypww2AcG_mSsI@wzjBPrH?E45bP8I%jI&2v+t+pWrR%CR&n$R(Nv(PWk6MU z1S&q9eUKOnnQFp!^aRY4fQV%v_dk$Cs`!3D*32k%WIWGjAps~zPeBs@jGBnvX9ZD6 z0Fl51sk!&qX7&5o0^+trd-WB|9JQdD&n&<~0uW&bMweph`$!{z(+gcps*Tz%Xfzsk zbcrA`8%1}EsX!AwquWk3kG%`{aL}F|)K5r4j}kx^2}s*`6|f;3bu|%wwW02+1^F9H ngv-p=we{K1rM5(g68{FD#Y7<>at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$_2pzbDAQ3>Zy~C^>AjZ4i1R=qPpOnPAliitl^LExijT$vR z7y|1eBo7bpvga122*q@zHHQDK7J%B|F8Kq<00dvNOAr4yLhZU)d^c3{K) zy^q=a6f(KOTyEoNLu4PsKiHaQMdG`5?JT}vV+T?iS^5H-^VB`XR^xY>LbuJCPni)< zyS5u2fTW*$X+*wz9*Jv^D3#Pq!o1O1+fP-v&C?dQm03d**NoiIw zqo{S{5Km<&fX+bFTMQ~iY7SsO?qt6@`V=#uF%CB)78pAq|Jk;8AFwJf(Qlm~XQna$ zvj)<{=lYHe^mQP_U;RQ3&P}(o$6TBdDqv<{t96e4W>A_}8LGppJ62EGD`s+du)xfK zvB4T@1?+ub8Ab8EvMJ3JvR5VWEjwEJz-ve+C^-S;Or>%M zuIyn=tj7Rh`RwNqxLFu)ih;d%0E%KIzN6+)WA)K+bo17WYV`n8I_8=hDCV;KYnH{9 z^@v56R2P#5W({DOkzrPj0OvZZ1Q;e;R1#$x%(Jjqdyyw+~~Uxm+!P>>^1+ zNNys;9S_L>{con@6q&AC4(ys)o8W7shp=gXZ+H`S$=Ymc)Tr^P@dz{1&q@Z(EOP(= N002ovPDHLkV1meq!IA&~ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9e9c365ff437c1896a1b56436893dd71b19cfbd5 GIT binary patch literal 991 zcmV<510ei~P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$_2pzbDAQ3>Zy~C^>AjZ4i1R=qPpOnPAliitl^LExijT$vR z7y|1eBo7bpvga122*q@zHHQDK7J%B|F8Kq<00dvNOAr4yLhZU)d^c3{K) zy^q=a6f(KOTyEoNLu4PsKiHaQMdG`5?JT}vV+T?iS^5H-^VB`XR^xY>LbuJCPni)< zyS5u2fTW*$X+*wz9*Jv^D3#Pq!o1O1+fP-v&C?dQm03d**NoiIw zqo{S{5Km<&fX+bFTMQ~iY7SsO?qt6@`V=#uF%CB)78pAq|Jk;8AFwJf(Qlm~XQna$ zvj)<{=lYHe^mQP_U;RQ3&P}(o$6TBdDqv<{t96e4W>A_}8LGppJ62EGD`s+du)xfK zvB4T@1?+ub8Ab8EvMJ3JvR5VWEjwEJz-ve+C^-S;Or>%M zuIyn=tj7Rh`RwNqxLFu)ih;d%0E%KIzN6+)WA)K+bo17WYV`n8I_8=hDCV;KYnH{9 z^@v56R2P#5W({DOkzrPj0OvZZ1Q;e;R1#$x%(Jjqdyyw+~~Uxm+!P>>^1+ zNNys;9S_L>{con@6q&AC4(ys)o8W7shp=gXZ+H`S$=Ymc)Tr^P@dz{1&q@Z(EOP(= N002ovPDHLkV1meq!IA&~ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-darkgray-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-darkgray-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..777c9447cf077abec6749b913986193ef960934f GIT binary patch literal 951 zcmV;o14#UdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{??gSHbu zCTN)e_(K9jn4ok6x%0mKS*@(Ssuo&Uu?w?RgUVun5sd(Vt& zkBU{!Z}43#Qou5>-|r)25$NkOLt(mBN%l(6#sXErGQc$sDn5v@@;g?JK+T?5qyW|; z1(|(7g;spuAZtd=UNBAT`T)=m0^LbcWRP8CABut~6aYEF7^`c@a!c}bI&IVL`>z8? zuH|$(9qD^SwQbuYgIeZ8RfK^T@zq>(tPt3bVw0`fr8zxJCPnrZG@DI7>GjC&o_c~Q zdjh?7%sMg90DBbtk^;>YfP6^$2q1s7?R? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..777c9447cf077abec6749b913986193ef960934f GIT binary patch literal 951 zcmV;o14#UdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{??gSHbu zCTN)e_(K9jn4ok6x%0mKS*@(Ssuo&Uu?w?RgUVun5sd(Vt& zkBU{!Z}43#Qou5>-|r)25$NkOLt(mBN%l(6#sXErGQc$sDn5v@@;g?JK+T?5qyW|; z1(|(7g;spuAZtd=UNBAT`T)=m0^LbcWRP8CABut~6aYEF7^`c@a!c}bI&IVL`>z8? zuH|$(9qD^SwQbuYgIeZ8RfK^T@zq>(tPt3bVw0`fr8zxJCPnrZG@DI7>GjC&o_c~Q zdjh?7%sMg90DBbtk^;>YfP6^$2q1s7?R? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-gray-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-gray-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..2e50ed6facdf24f7eabd813ba99852dd76756ef2 GIT binary patch literal 866 zcmV-o1D*VdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~<`M1V z7$0rkC<6R}EXy96rdgwDB2z5p6fr-jH%JM47yI@F4KHq>Ua|NG^a|~a1@<+>@9Ii% ze~0A3yc1l~h{Yjykq|EB!;6@&wRQv2Mw*Tk3`JlA*(>?Ghit_*;Q;0@vG^m*QreEr zB(R3m{Z5HY4yh;}Ue3D}J9$V|0$3y$(?y1TWSlHu0>3rX0s2MylLS&{z(BT2_;SdT z;>YAxV)Nm2lt3y4JK4<-_`X1Y2X{FwZniH;&54@p67iLqm;?2zHK srxy66whV1C;=kc6XrY}kW5&P1H)M08J{{dfsQ>@~07*qoM6N<$fat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~<`M1V z7$0rkC<6R}EXy96rdgwDB2z5p6fr-jH%JM47yI@F4KHq>Ua|NG^a|~a1@<+>@9Ii% ze~0A3yc1l~h{Yjykq|EB!;6@&wRQv2Mw*Tk3`JlA*(>?Ghit_*;Q;0@vG^m*QreEr zB(R3m{Z5HY4yh;}Ue3D}J9$V|0$3y$(?y1TWSlHu0>3rX0s2MylLS&{z(BT2_;SdT z;>YAxV)Nm2lt3y4JK4<-_`X1Y2X{FwZniH;&54@p67iLqm;?2zHK srxy66whV1C;=kc6XrY}kW5&P1H)M08J{{dfsQ>@~07*qoM6N<$fat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4YF7xw!JF{zm3Kc5+ zV;~#}*YCJ%Xt?^l0qZb43&Jusw*Qq%Ks$Jp;sZ1H)zEw9gmJj(-CvvRRuX+AG1~OL z1t#AD3efO7-eV+g3Ft@7;nS$=qy7Q#YqcC^G+vo(R}p>(hPDu~Ri!!<1dk=&HXSy0C68{wAi24$|TYfjbXbDIY?jG4m0Nmi`1GxefqAQ`g$&(Rz}G`TVDpt zBmh4ZrgPWnD|zP8Metc^<3T|J)*3*Tn&reOA8{L4e6m;$YB8Ng>WxKGoJ%+Ws{&02 zf~Xht_vbZ3-Mgl?+Op4-(Qu&vRt2mFj4nP(i!U83hPy3zVxNG)MZg6dK;b#?C-#aj zhqPvL>@~b1pGPGiH=?f?=Yk+&m_F%Bu^+;bI4S`|-u3VXwu`a%- zdp|ZTdndrA`NE5;bOH$R4Fe7>i}O`CFcn+4Jtg(UWHPmO!O7RR9U(9zVwY?D1|&_Q z3x8~kuWmaqC#DanmNPxS`6X$lX6B_5&=(0aUB|3i3}L4Bcce}>V>=PxQd+KBB>2gQ pi)NjMWxg9;28*;6DpdGy@Eeut1r7gnWd#5L002ovPDHLkV1oNtz?%R7 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a631b0c4c0062959bcfed50c7b4921464336d76d GIT binary patch literal 1019 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4YF7xw!JF{zm3Kc5+ zV;~#}*YCJ%Xt?^l0qZb43&Jusw*Qq%Ks$Jp;sZ1H)zEw9gmJj(-CvvRRuX+AG1~OL z1t#AD3efO7-eV+g3Ft@7;nS$=qy7Q#YqcC^G+vo(R}p>(hPDu~Ri!!<1dk=&HXSy0C68{wAi24$|TYfjbXbDIY?jG4m0Nmi`1GxefqAQ`g$&(Rz}G`TVDpt zBmh4ZrgPWnD|zP8Metc^<3T|J)*3*Tn&reOA8{L4e6m;$YB8Ng>WxKGoJ%+Ws{&02 zf~Xht_vbZ3-Mgl?+Op4-(Qu&vRt2mFj4nP(i!U83hPy3zVxNG)MZg6dK;b#?C-#aj zhqPvL>@~b1pGPGiH=?f?=Yk+&m_F%Bu^+;bI4S`|-u3VXwu`a%- zdp|ZTdndrA`NE5;bOH$R4Fe7>i}O`CFcn+4Jtg(UWHPmO!O7RR9U(9zVwY?D1|&_Q z3x8~kuWmaqC#DanmNPxS`6X$lX6B_5&=(0aUB|3i3}L4Bcce}>V>=PxQd+KBB>2gQ pi)NjMWxg9;28*;6DpdGy@Eeut1r7gnWd#5L002ovPDHLkV1oNtz?%R7 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightaqua-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightaqua-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..778d561465421b918b4bbb00cf561271ddc7047c GIT binary patch literal 976 zcmV;>126oEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?N-ZC<3JF7E%va>$){cRgf;_j0+fgVhyZ5* zL|}*j904W*a0G}9Oa%DE?}E8dTu}37B)Md3Mv~zG2fZrQ%=EaYUw@{@K#LYFz8Hcf z5#4A9Khd#^S4`u7GHs&c`&}af=73}sd!p!Z8I}%F9L0a-(50upa4v#D{6{WaX9uV= zey5?X;xtHbMMIlcYa-^80RKtfdZhu@UAi=WX^ubwZd5fpsEH! z6Jl5R7@0^`aNts6Y7Du}Y`!iP`A>cE;T0D&-dhw~4++<`nt7j-7I%Rb;f;W=aTJTs zu2T=gY;WehwXf(`2xMS$orr*lRmFS3A!Mp}8#BVOoAmsn|@9$h)L{ zMIG?og6LMatp}`RtY8aiPZ+|@VBivKs^5+7^_b&`qPP(O^N_IF9NH#g6w~L_cbz7_ yr126oEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?N-ZC<3JF7E%va>$){cRgf;_j0+fgVhyZ5* zL|}*j904W*a0G}9Oa%DE?}E8dTu}37B)Md3Mv~zG2fZrQ%=EaYUw@{@K#LYFz8Hcf z5#4A9Khd#^S4`u7GHs&c`&}af=73}sd!p!Z8I}%F9L0a-(50upa4v#D{6{WaX9uV= zey5?X;xtHbMMIlcYa-^80RKtfdZhu@UAi=WX^ubwZd5fpsEH! z6Jl5R7@0^`aNts6Y7Du}Y`!iP`A>cE;T0D&-dhw~4++<`nt7j-7I%Rb;f;W=aTJTs zu2T=gY;WehwXf(`2xMS$orr*lRmFS3A!Mp}8#BVOoAmsn|@9$h)L{ zMIG?og6LMatp}`RtY8aiPZ+|@VBivKs^5+7^_b&`qPP(O^N_IF9NH#g6w~L_cbz7_ yrat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3!g1!Eneg(zC+FUq0OZJ#S3WxTj>Lg%qN&AW(!Jh>m>W)TdCY4sWW$Dq#z(cO>?AP(3P@#G)EHTtX zQxPx^$qEuW#gtjt=FR3yr_lG*lJplzOlhT==6}OU@JX8^M~;7k9|jDz7+i4OfdBvi M07*qoM6N<$g3g<)&j0`b literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..17ea5665a2a32492652fdee603eec85b5715550f GIT binary patch literal 938 zcmV;b16BNqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3!g1!Eneg(zC+FUq0OZJ#S3WxTj>Lg%qN&AW(!Jh>m>W)TdCY4sWW$Dq#z(cO>?AP(3P@#G)EHTtX zQxPx^$qEuW#gtjt=FR3yr_lG*lJplzOlhT==6}OU@JX8^M~;7k9|jDz7+i4OfdBvi M07*qoM6N<$g3g<)&j0`b literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightgray-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-lightgray-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c93b89b607278414dabbca6d98af0353ff42b8fc GIT binary patch literal 948 zcmV;l155mgP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?`3z16E&=X*@-`z6in6i|95R{ln=z7BX!q^vNg}FHp~4@-p);{wuj^>) zYPbo4U{hv|?SG{Ru!F9=3kF-R?>2_WS)9-MH0iO(fqg6$kg>c3G^d z&*Dre2W}353Dh2$c9kJX$12NSBP|M4hqVH>i-X0-mC?p2owh*Fo=_zwkWdZ^?*Sc# z_bUKN!W|Qeay`sNhJq63<@}3_NRx-XjzIJi+hL*p_l2JWE z4IIw_^fP6mr3k2pq=!9E`NqS86iXSZASrG=@u>wqK|Wz|V(SXG<09BfTcJXQe}gY> Wj|i?nB(-}00000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?`3z16E&=X*@-`z6in6i|95R{ln=z7BX!q^vNg}FHp~4@-p);{wuj^>) zYPbo4U{hv|?SG{Ru!F9=3kF-R?>2_WS)9-MH0iO(fqg6$kg>c3G^d z&*Dre2W}353Dh2$c9kJX$12NSBP|M4hqVH>i-X0-mC?p2owh*Fo=_zwkWdZ^?*Sc# z_bUKN!W|Qeay`sNhJq63<@}3_NRx-XjzIJi+hL*p_l2JWE z4IIw_^fP6mr3k2pq=!9E`NqS86iXSZASrG=@u>wqK|Wz|V(SXG<09BfTcJXQe}gY> Wj|i?nB(-}00000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5eBR2jT{)-~vPDvov z_U_VXK=4UnWIGGls8zti4m@z8#m~U@`7ths$-41BOwNDf*8>?(%#SQ=qZX7#@U!Zy zC?nExNDfhkVI8+eygn=kwMiNz@PS4>d1~^BGANXhwK*G0mTSA@QqGCVxp9A~P^OkZ zFb6zx_7Y=VKI#$dcYUWBaL()%L>I}Kp$0((wt!>yBCXDghw{|QYUzEcj1Y~{fS>~5 zi^KL=^6_eHvQ-FH-Y?8^g>b#jP=m&M;65tJw+6|Xb?+BQn$B!RfMc3gjZm3n9@J;= zhiHjb1Q>l<)qY8UF3Y#eiuX@TU|E(^^XpJqPN0MZ4JFu$0AH*75lAgP3Cq;DS%5$y zFGUx9h+q|bq|s-IFK2O_gFboq@tJXIN0V*`mDu8v+IdgE_iy1(cxti{0cj*TyhCw` z@J8Zxs(L6!vT2~zav!at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5eBR2jT{)-~vPDvov z_U_VXK=4UnWIGGls8zti4m@z8#m~U@`7ths$-41BOwNDf*8>?(%#SQ=qZX7#@U!Zy zC?nExNDfhkVI8+eygn=kwMiNz@PS4>d1~^BGANXhwK*G0mTSA@QqGCVxp9A~P^OkZ zFb6zx_7Y=VKI#$dcYUWBaL()%L>I}Kp$0((wt!>yBCXDghw{|QYUzEcj1Y~{fS>~5 zi^KL=^6_eHvQ-FH-Y?8^g>b#jP=m&M;65tJw+6|Xb?+BQn$B!RfMc3gjZm3n9@J;= zhiHjb1Q>l<)qY8UF3Y#eiuX@TU|E(^^XpJqPN0MZ4JFu$0AH*75lAgP3Cq;DS%5$y zFGUx9h+q|bq|s-IFK2O_gFboq@tJXIN0V*`mDu8v+IdgE_iy1(cxti{0cj*TyhCw` z@J8Zxs(L6!vT2~zav!at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?g zZO)=AH7hg5_gyIhdV<;lw<2h>8E(hf{}|n<2iG{Yz(7*GFg|q6T|-gwR|(Y@dMPlG zBSfuhrSv1fDZ{2JRmX{IEXTzVw3x-KQUgWF8|X;`7Y+%VmO$VdJLyV?%7ivc;>(e% z04wWIzL9JFl)@zwe3*u0mnD9aCS!MeUUZw|6C6T-X!DEdcBfXxNPCPvuq!W(HPF7W z&0Ldu3B+A#nHPtAMj04o5|dy<0amX`k7>GREDf7W!0!Q0swMWw*JAwMHH_7Fq>jkE z*Niz6yo;>My*gN)w>Lo>=9hCpadtsgr;;sJ%sZ;N1oByPTW#RR~myGwpnCy}s*P zecQoJOcQAGUU*6u7_nzuih#LDQatcA;Tn%vxxP+)+bQu~wVdOVr{*-JIm`TSI0!yz eD^#fPZ}1J>H`UT$`2%hM0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?g zZO)=AH7hg5_gyIhdV<;lw<2h>8E(hf{}|n<2iG{Yz(7*GFg|q6T|-gwR|(Y@dMPlG zBSfuhrSv1fDZ{2JRmX{IEXTzVw3x-KQUgWF8|X;`7Y+%VmO$VdJLyV?%7ivc;>(e% z04wWIzL9JFl)@zwe3*u0mnD9aCS!MeUUZw|6C6T-X!DEdcBfXxNPCPvuq!W(HPF7W z&0Ldu3B+A#nHPtAMj04o5|dy<0amX`k7>GREDf7W!0!Q0swMWw*JAwMHH_7Fq>jkE z*Niz6yo;>My*gN)w>Lo>=9hCpadtsgr;;sJ%sZ;N1oByPTW#RR~myGwpnCy}s*P zecQoJOcQAGUU*6u7_nzuih#LDQatcA;Tn%vxxP+)+bQu~wVdOVr{*-JIm`TSI0!yz eD^#fPZ}1J>H`UT$`2%hM0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?9}k+S7nG?ttCW0AC(G-#*h(AT>D4EKAj(AO;a4(_#j;t>-@&Hy?vr0Jc(%#+nS66UWSx zKe+9$B;d_~n8tK+;F6EZ^a73VE<4%`ZL+3yohE053V0QG8{=r_LJi9OX@o3Y$10CL zCrxEKsDW1j-^Ec%K6?bCd<%-vXRrjOs6g#KP(&&D?vF8NiqU57YfRWaZbTq` zNCY8`Bg#HW0*rs3IwJ&0M!u((Yy9VBG<_Xo6rR`rH#`dK9%);&Xz^lj10crI%=+Ap Q+yDRo07*qoM6N<$g4FK7RR910 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..426097d40ecf519122b399ed13237884139daf3c GIT binary patch literal 994 zcmV<810DQ{P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?9}k+S7nG?ttCW0AC(G-#*h(AT>D4EKAj(AO;a4(_#j;t>-@&Hy?vr0Jc(%#+nS66UWSx zKe+9$B;d_~n8tK+;F6EZ^a73VE<4%`ZL+3yohE053V0QG8{=r_LJi9OX@o3Y$10CL zCrxEKsDW1j-^Ec%K6?bCd<%-vXRrjOs6g#KP(&&D?vF8NiqU57YfRWaZbTq` zNCY8`Bg#HW0*rs3IwJ&0M!u((Yy9VBG<_Xo6rR`rH#`dK9%);&Xz^lj10crI%=+Ap Q+yDRo07*qoM6N<$g4FK7RR910 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-red-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-red-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..2cee3356714668af6dae7a7927d0afa5588e163c GIT binary patch literal 905 zcmV;419tq0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)!tjBl`P zqY~F1>vy#H=es(F?VO8yhlC@$apbn0Jn_>G6?xF0fW{`-&V7FR0gtU6$g1-hlbex| zo?x%&LIMfV)uA?Pl!;-!A*Z~2?s{Pd!6fw(fRot1D#t36p`D3L97|HOU4m{e)Otxq znIM5s4oI}EN4^-`AKhk5PK?cao}7vT2pvI+Y)@+2=Mic?*VMhn(HEq3L=EsN;J;uh z$;VK1O2TsV`7TW0Kmjz~0~OcRj%DdO7HTNLP6Xim*at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)!tjBl`P zqY~F1>vy#H=es(F?VO8yhlC@$apbn0Jn_>G6?xF0fW{`-&V7FR0gtU6$g1-hlbex| zo?x%&LIMfV)uA?Pl!;-!A*Z~2?s{Pd!6fw(fRot1D#t36p`D3L97|HOU4m{e)Otxq znIM5s4oI}EN4^-`AKhk5PK?cao}7vT2pvI+Y)@+2=Mic?*VMhn(HEq3L=EsN;J;uh z$;VK1O2TsV`7TW0Kmjz~0~OcRj%DdO7HTNLP6Xim*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}zjzyz>CvO&uPLAuJE&qz)j`tir_PUnwjOD~qK03;+NoEaHJVi<-To1BNcEX#IN z_Doq9bbz)(>joKBU|)-NtNFfw@!$rV8tnsZnK7_`jb^{ii> z=wvodu+HI1;Dhy0D!0WY|L{qZ*fNAvGq$_$JkN&uo1g4p_SkM;zSh!sFV*52H= zZIugq7y-5(V30HiU0rr07*qo IM6N<$g3;)DC;$Ke literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-script-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-script-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b87cd34262c21097264c97728e2458596cdf1e27 GIT binary patch literal 830 zcmV-E1Ht@>P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}zjzyz>CvO&uPLAuJE&qz)j`tir_PUnwjOD~qK03;+NoEaHJVi<-To1BNcEX#IN z_Doq9bbz)(>joKBU|)-NtNFfw@!$rV8tnsZnK7_`jb^{ii> z=wvodu+HI1;Dhy0D!0WY|L{qZ*fNAvGq$_$JkN&uo1g4p_SkM;zSh!sFV*52H= zZIugq7y-5(V30HiU0rr07*qo IM6N<$g3;)DC;$Ke literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ca4277bda340dd7dd820ee1f991e4df31119e017 GIT binary patch literal 865 zcmV-n1D^beP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?vmqBxoLnB>VJaeh1iOCz)?&zsUj>6&3#-%A6TKw;}c} zAi7{~>3f2%FdYXt$MCTYqSyE;0`VG7ZH1?s?N8wsnJ;?L4-7DzY^BVlzQ^Rr-vH+j z!jpo{m}rC9?ci)U@^BCy$9(9)_nVoq13AaslbORf{tY?g3oxi^M0&KVWv{4K@99<3 zH_^W$fJi3iMSS69$FV1quTg@c6;OM-ibqY1CY_UcZ9X}dXHshc({U&(5$G}F{`5`K ze8dkZNpS%Rf=R&KNmb!!J`tcKW^Q+38w4^eh??>ry zZlWOh0uJ1kecw7c0}|6Et(m43&*ciqIgUU2GPw)r7ljaVucvn_J+FGd-dJKby8e1* r;>soU_0||7T_ML=WF5y96%`eqJXwadsGIR500000NkvXXu0mjfqi=^d literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0fe89dbdd085bc9c50712a75696b3fd9eeeb6d8a GIT binary patch literal 871 zcmV-t1DO1YP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Y$OVK) z^;k#+0l549epzRHLk++pfz%O+W81b>Wh>?!v_RM&sR4}y1UMTZE9djMGNLGocykvU z2hlgaFIUKFj>RHVuT4u?a4=sec3(Q}Cj zXJ$nm(VBpO++bGBf-JryNj&O^P6R}H^J2u6bmX`!KF$(#MAr;Zp%@?Kl~gG{Wdf#Y zzS3_NEJQw6Ek0!ezVC;HX!)5|Dn4Zb01i(mi% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..39272cea3a78a3a807bb1c0c723863928905a9b4 GIT binary patch literal 864 zcmV-m1E2hfP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?IPt9CBDU9nwZhzaIp^NWU1)xl28=P;@zYw$G0XD#9-t7y z&urRY-X0fuTPTCw3bVE0VJh5Q-?5zY_);+>UQvQ_0&1nS8j&=&asG}j-aWZ%P>71C zNPv?Qo}?w<=eyZHM6yN=R3*Tk`<1p_-0u1(^QriVKS7yD8xy$igk0J{+GO9II zpsL_v`!Q-NzUBlLq<^mrVGWv!uQ>skSZuV>M=HL{iwzp08UZ@`{mOFdBbkbCO3_h- zi(ez~ne=2gJm~>ibary4{GzKKR7#|{9g{QUa*v>P6teq_+v-Zrr)S@Zmw0I3WHCGT qwTJrCq=-~+;FFWnjtvY9488zA&4$VMuO*8B0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?{Js`6z#jNi!IAK z^nLI1@Iz4)CCq@xISah3j$0Amm%20Y3usUtpZ0&UyAz*iMK6lSa|K5YU*h&1OJaXqrZVCe{-8@%PK+E+rYN%AEgi3GDIlZ+id+9*zO8-cat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?*&Rg+N?XxU;BceWgdfBm%3p#6-Zxca{gon zO9%i^Vb8Vii%`6ibJ8~lwfCz~&uYtm=}y73^V2K*ce z!PkFDAVL%nQ=qUanC9yx5J3beuWQEAxDL%nmF`D?aLu?ff63tHyN1BG992N^Dz^Ee z31}gAy#lzVqna<80MT(S4$Br^M}c)m{ZUMWpF&3spmK$AtB)(Myh17$sOFe00000NkvXXu0mjf DmSSD| literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d5de365d0e702bc3541a4a22d474dd35e565e6c2 GIT binary patch literal 881 zcmV-%1CIQOP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hKCZ?0iawMrn2Qj3(^8Kqwr27QQAVO; zIO|Xlk2mwOa0?YM^`cW7>|yJSh2vrB+$fy?yfrm-E_ul5)4oq^$+)pMpp-5$bjV zdj1t4=3|hLhSV0I5fl1ZWAGyjnfdHQg=k140mn4G#*7J*myhS>Gg%bxGDAiX_~Z z>b5cgBB&o*%fomxI$JZ96EQJcld^*)8B%IdRE|43Iy$}qMk%SO&pJqq00000NkvXX Hu0mjfUuB8O literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..41793c6f1132d62c950e0a8e1b9ad7abdadf58a4 GIT binary patch literal 859 zcmV-h1Elat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?AwB4X1cmuitMMA2?g&d0neZ1#7QCga$3F--dha`?)?BDPGc7Q-2@ZX`L4)e}k zd?Dr*?xfjq!HipbMHVHPH|}y9&wliTzA;4`6MI4Peevz0f&2$Uv*bAw#`;d~1MNZ? zClbS1Yi6%$SQg$wHH+MH&%AI{6lgv;lDT{7H?+npDmX-d)@iQkbd6IKuW02apJ7|{ z-vtPXtY)MSz6^U2zYHX9iW(d$K$-Y^B)%}aooYU*eN<)A#sXyE1-tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?52ql;f{3Q&CJ4x}_jBN=4FSIjfpM583y*lfFh=_>)4lx#xkLr|e8QBfl z+-6_Pb5UUecHGWBHe?TEg}e~YL;1&}6PW>Pnvm~X{qh4Vx>lIRs^gb5&w48P2rdZJ z9e*izDj7?)u_c)qqwoR;+yo3*g+_aOjDOLaUc77xc)*uHLtm3?PxK`2gJVMPxi@?X z@ctLpOXQPUd=2a3QxtO)X)pnKC2AZBP~mPMg_YUhoA6hFA=(8NT@~8mn>qiGpAoR~ znqpMC;0$c>$uq6e-x072=hjQxUoxQh!U>$<9!7-(ugF4+FPH$yd^lctG#}GJ#TQIK zL+HbXv4APQ5`pj~&^vyu+?9PSttwrD34V>hJGi^e2YP_nhS`Aps_mXmBGc_yAf?GN z7zJvw4RyCd$C=O`TX`vNJ7YLEh1nVgE5qB9kG127h=_at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?n^_1*QYLgUB7k z71-{868sH9qy*9d1@Oo$*^?Z^^P+tDMmpVVj~(Xb?uZNw44xfU*F+eG3){AR%d%dp zs+#i{>X*%CbEh82xvp^SY>RigJ|qi{aU64fso7fA0o9#)Fq_Q|AW9M+ ztX8XIU%X8N0Q>ZzyGxS9?TY0&B;O%%Dr>)J0D}YstOCnPd7gLv5fXCp03=cxiLnGS zeDur>*@jji<^U2mnt-tc$Z?#jG~FnQyyiTc59Hh-lWG%KE|)2Z0g>pvInU-pb)tzF zO@IN3RRZr(1!X=QzdKFDBmyFDZAPfDQ{&2fqSF5nU??*Jdvzpr%%@ENX8fQZ6gqcXPm@n&#|0{t7%DnjoAaT77 z`1>~b=MpnWr1v?-{_Y{MkFF~Z%n7gCmFJmIQ52W;di|!>;N|oYzem%Pp^Ozm+_~#H dHZU+S_y$p;vdr*#Dxm-X002ovPDHLkV1iWbfBygg literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/fontStyle-serif-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be18e84524f88feb243ad7cb1a71474928eefa3c GIT binary patch literal 854 zcmV-c1F8IpP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?t)6MPT($_beWUrT zbv8N>;41&?aU5|PHqEVK980szVel6^*Y5#2Csjk`!~xW}qXQ7@uBGJYiCzSRf_{8y zooVAN(3DVYFaSLX==t;7n&AVd(Rp0WCnq0vnbeuUJEghoFw-_8c)qZdC_@VjL~jBL zk#|uM;OJO|+I+VtG7Q8Z0w!;1#sU=Aat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0k_I-Ht+*|v~PSaQJw7hD^*f(4rd9pKzWH3+ba z?$xquetzm~9Vs*O$gGdc2w5A>j)KtV#Qk(vG{+D~-k<~((S^e+(5cPUsI zE~+MR13JceTbzNR1b`eH+Y9$^GH!;AX$4`QNu3Eqk1D0KiSE;APtCYCA07XUGcjBN zqS`<(uB%X)@2dNS{Fs21H?t(BRlu4rx}!>eNxPeElL^{iHpfKY`F^UtV`mR|eHzrO(>WKAtu5N2NF<->YUX4bk6_OmQ fwsP#@;oat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?u!axw5wS$t9Cm@mZJb}Cb@&fz=Xpqu{ zG?Ak;@B-imJb@pCGE#!%{J>R;NcLsdJ|iI5#z#_d(|GT0?{0Q?&I?#rSe!d3Z((?& zT22Iy&5i;ZGUqtB^*?Bd0?0m!@T!L)UodxF%%0w9b;$oB@1U1-!(iA{D^i%soKooX zXNdwZ>Auo75f;yD8Wj4Y1TG=SY$nhhHB>#%cff0Wd6&&V`+uSYr35r28=)9q4ss)^ zx#&vNv_<+)2=IY&`9u%at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>A*}1 zFz$d7=pZRU>3{}|a)(Z1h%NL;@)hk2Na$Y6u|fa|2?_rl!e&sLdJ8aC=(3|Hy_!7< zdF){Y9QV$T172s0YccNQp8umQ5eL+m5Jz?5^as54u!_mYWa)%#>NW2S+>o>6B@)VQ zj@qV5qR%Uz;D8SSgrIH=dOohb5f$%XLHbt+OvM|XAM9=;+Qbf*aq ziw|;_NTUg0Vu|;j%e~xskoeRq1R|gV6Adn)ig_2V;(O>J5J3dEy+(}X%v9nvLom&VDU>8E52v~ScreGQ}`}ce9;6rtka_^SbQBs!k56}_p94& zw&WzfVd<`N@Pr3}%a%6U?HOQ1C+@X>!=sak<2Y7(yedv4>01l=*0P=U{s~XJ=UGg} nF$FIT`fL!5?Kn?P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?e_UK5dJiP&;?Aj`gJ>)hFk@Se$v#00Nk+9xtp{4RM_OOhwUy2;k&MSm49k05 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapHorizontal-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapHorizontal-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f7f90234b95acfb9404f7ba790b48ff27c6b30f7 GIT binary patch literal 671 zcmV;Q0$}}#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?v(H^lqy?1NQ^0w|T%f zdx z1DugN<&e~!6c^2<9zCJDja(s*1GrMeDWn$BDQg5V4i^at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?jSja`NA*WdsexMJhCZM&_i>hdnu zx&u7{>uP%VBzL-jZ!^n)xv=!o{?x!HU;}J`4X^<=u!0%T;$jNRKY}=pH(ghOJBsAK zat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?D4fJGs z1G_WTKn09ZirNAyF_~}GOn>HeI!PZu5FNuR5m!hh!ok=E;c$*RcxN9nb+VCNibqx{ zXAgR8Na?^60Zj2u>nwQyHTe^mZUGj@DU#j}c_kui0ux+uD3bTn8CK){yQTUH+z-&+ z<^fyT+d{yXX(u3W*lN@MP{0Qu0VIF~kN^@eKpPZu(S$#Eg4~c?;V_3QdtXw00`+@M zZUec6DGV_r{K84OqCD5Y6Y|X8EfI|zm=an6QW>LO)d->+E^F>Sj=LWb2><{907*qo IM6N<$f_p+8=l}o! literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapHorizontal-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapHorizontal-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1691a724801ff016f893812847eb913e25e7d606 GIT binary patch literal 674 zcmV;T0$u%yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?sb7r`at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%+^&#I~j*=tE59N*!Dayt)++nQ^%;jNM_|LQe=Ug8`F!=0P{+F7&a;j$n zgFs6{u=IlBmRRu|Z6>&3^F4+Uc8XJyaZKX@@%MKNizhHiP~6Rgj>Xms_%^Eq#0#6b zw7(PZ2~>azPys4H1+=sR{&d&y|GywLBoR+?Jd2$r*AdMat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?nelMNfcE9;{c9RZ(AQTLm6V-Kxf@2;iM4apHb_6M?ZQSvd zXvhhi;JohbLODxGLJt8Js;yiPEU9kXDG_;Q@(BHS>dSW1FXMqj#qJwm0ax+F52x%? z>pa*W2E#W#SGF_ cO%RIV26g#Qy~&r-E&u=k07*qoM6N<$f(!IBk^lez literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9cd2279b3a361a38a184e6ed9113b3bf17ce7623 GIT binary patch literal 686 zcmV;f0#W^mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?V-qp;#4I8vNIoItq&H^D{N zk(HbvtwW-c31%XGvgmI$nRL2e_e@nDpeTQa%#HDh*@y_4u-bKKiV}at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?u_i<+(gG?j=1T}oGkxRcD=tN^VF z0q1U>FtM)WUIxBRCj<8jTXAWBXW$cv0Wly3#DEwWp#yev(T4v&0@IK@$l;HPrBku? zEiXq<^Stihi$=n|R)i}u)+_6`=m~QcjCo-QPiU!#e+imZO%VFw27_rqN|46_Pyhe` M07*qoM6N<$f?53~7ytkO literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapHorizontal-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..00ec811f97bb3f7535f8daded386ed072808f9d6 GIT binary patch literal 680 zcmV;Z0$2TsP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?fsR0cy>J3>0>cJ64-iJs z4eSD>UK35qiMA9K9`1YLQhIkk*CzY`3^Ox=F4T3c$dVL7oZ>j%!w8zD$(2$WhM~Eh zBuTI5%3caWU8t(60vy5SN6aZ`^C5(7L)*67uInxsN>slA2XKlv-8=|_T@*#vPkXHs zFbY_|#vmlQ{sMl@Bmw%u4qV#*3HSyqfCaDs7Qh15Fac^Vd|3VwXhZS{CAcF=?pt1t zfc{?54L!p%ID&SpL?4-JCx!KT?|eL=#DWJ*%)pT}O$&UKFm7rLGY@wf4N`CVQHT!! O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G+_;R(PKI8=^W zs3$>Bf;W)fB5oLmfe0pmip73aX4$-bWHXZmV3?LcHE`Yup@d>YIF4tygbG~t!XqV@ zmR2@CaWGf2qn83p3WZzYgCSIWO?!N`coC>e2sdJgU5IEIlluV}K&N<<#YG=R_7t!0 zaTpqq|8IdDNS@0W z%t>;?L%O$=mll*guM|9iA*2vcb3D95M0&Yzb!Nht1Xs3$E*N6Z(WkNjR68|>X@>_( W7)WSt1%+Jz0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?dD&>CI{b@ZthTmWd`+gvH$|ED!DVIMRXDAJ6~f3qO=NN z+)a(b*Oc5!z_%GBKwa3DOZz(kpMV9h02aUkSipn^pf?wN`2QnN4N1Ao$ezO2UseCU zJ95I6YMhW6IKJ@7c)o!+ENat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_`16)w+1mFaU6X;}i13Llr zA)3I6wiFeA+?O3E5CbVqfEO1r{Qoa#3z8d_!m%v&CFyfQ{=C+Y!HL4D(2Ay# vf?n@KOikGAW{W^gfnaTUH!at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3q(20 zOT0Oo0WJ#=^~T*9|E&=6ndQiyat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O|Dc7X-atE#V6@{T-au^#YJn99 zjqwJ05o6;y^az}Qby-Y|WH!NU0?oXH37cVug`NDrfFN)Lu`*W+^*nTpEWoya+{7>$ z!ghD-a^T3JX(|e?@T)M|jdfe`q`y&ud^=JS$^p~p?**=6IFi_(s z|CQ!!*Qj>qLL>at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?E_1lWPAgC z6JCOZ4QCi+Cj|cz2Scs~Qxlf^l2Yiw-%Dx#mPim7(li})p+E6W&!Lr(1WXBZ`jTZ? zM3#JLbXS#?jT=_Qk&Cl?0hZhaA8PNm+6Uff zjeQUVs%_h19#n<|o~XQG7L+|mFxfj002ovPDHLkV1n(jF`@tf literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapVertical-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapVertical-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..773e1b31c56506a00f8fdcf9e3b9155a0c91478d GIT binary patch literal 660 zcmV;F0&D$=P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?q5jZ z`bZ6LQ7xf9x{zWac1Q*@w00o8ZXl(PE)iHFapUi9il8__oxE2~u=0*DL8W7rRn<+T u?&xz^rvr~`H{JZ*2KkiyC1WXOtaAru5<1BTN?ZB>0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G`-H(!Z=joS0uRE#=nd4(4Ob`Q z4Rm9GJ9r9KJpufRnWYCkJ+O|D_ zqA-}T7yc^EP1B6Z9bJeNC0MCg^%c4u+6-in6kqYL*mJ=oF!&iAX}7cwz&pn}&vQdP z#t(+N;l>5ibXnK+69iB@rml*+TePDe59xq=?b5-$9PFpmC7DXG5}g-k!avlzU&hw} O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?JFy<)S0NB`?j7*3d zz)iSGdxYK~d`lUs%0aDMDT|-vCXExzQCj~H8HRxOKC;n5{EN4u!dL>i1bTkp-1eko z5Tlp;o6Ncwtbw%%KnwAa2G`Qy7dYp3=pJEP(!o1_U?X=j41sFu#JQyz^C!hFUWg1M z`=y2uni%61-I{c8DSqRxxJgb?3o!YKhHJN02PnljL0c-;n6WdbhUe5CkW5Dkk{q|N v3%`#2xjIm%#T_Xb#1N0tu4Gnat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?cayjDF5xcw2}0sYEgidyfM}{0l)(V~>3E2^_50@;r?Xj5Ja*SQ zk>+Tg1Mu=_6?#onI%DEGn}&Mxaa5h6+I{5QzyNFCuBtq`gf!8^Wn53{1JPqQ-8|;O hzDoHelU6Kb&J&M@Oas>Ia?k((002ovPDHLkV1lMCIamMy literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapVertical-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapVertical-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..43e0a9e2b744644409f812e617ce0eed42b0192c GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?HT>PY{Ro#3$Y4lydFcgxU*$o8ZpI!%%u>$l02&KEEcb>qL zAB|Fr_q2!f#EuD>jEfu|_`qMygPN;uVtV5(cQF@*K75efbPGC;X$8Yjpr$XjwdT`^ z8fiy2BEzUXsk4GJ2`)ldvGkPvc}Pn=tR>HR^G+TRVyv}(pcar6{BSFmNmH40g$J%3 zyRIs?rFg@j8rOZ`v+cggD;nyjv|lo_Vk0^)Wx`2gd95x`00000NkvXXu0mjfQUWAB literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapVertical-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapVertical-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..543535ee98495ad078e17f38dcceb69d773113c6 GIT binary patch literal 659 zcmV;E0&M+>P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hRE zGH-n}uJMuQxk{{fgPyW@5C^`xddW9k0-vQ>i%k%Qyg64j83RReKtm_~E6p_(gM23! zB1P$u;$s1Pazv0~0$uL3-(hG1OFoat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?X9|pk*`wR{(|GWmhwV zC)v5uC?tDN8sv025h12Ga!wwEfK~3&IJq9kQgdYElurlnqp&X&ttf$_2vFS{o0jIu zl4@zUUWgRMnW@iJQ%FEm->OL8_vpOAERhaFL+?v zF?EsiENu8P`L(<1KsoKc&P$DTr6GPwU6N@jR$Au+w6;dFSEsWV00000NkvXXu0mjf D>XItz literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapVertical-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapVertical-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c02c1068a0c626a9b01d704eb33f0ff646cac7a5 GIT binary patch literal 662 zcmV;H0%`q;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Z)j1O+8h7C*^JBsaF3Satx0v2e__HiAg}vL}%k4!{*aZ-!!}GXzp( zla1b{pE>r`B&B+zrQ|^fYMce|wCROw<002~Qm$#aKp5uF>uVz_FpLG^`{BQ(nUc=S zcJe~RFwRV+tS@QWAwnr8Cyz@b_V5jWoZm+0F*(`#fvX#C%pm7jo?oIv0Hz%)iI$dI wlImOUssqEZhdLi@bdwG1Rq~UJOEHt24;L0Uat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mzZbC zu7IED@}La=9lSWNN=>7MN9vAbdz2CX+$#4NAP5X9_rrgsnJ!&c?B+rw2wPH2wEzZH zq*y(bvlrwh5Oja1)}Ssot{x<+VK^;)cTjG0C}1haexhMdHmvEf#x>`}^- dOr%(7&Kt|}IJWVzbW;ET002ovPDHLkV1hOS6&?Tp literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/gapVertical-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/gapVertical-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..85e8e7ba66c73c52629c2344e849bb351aca4855 GIT binary patch literal 576 zcmV-G0>Axat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?*Ms(!>xUa7<-?qqwat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)sf1tw23~<_sa61TeD) zZdDEa{j9)N3N!(*fcJiD5^(JVQc7(C4g!G$nhgji;7j*W{O?<^Ah)3)2*L+vS~I?c S!oxKH0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?v!Y~j8;AfB^1w}^42-yI!0i)2Qr_V5~ zzzDEGMo1f!_yCC?yR)C8xVf*0d{Sh+Ty!>|l*-H?Rx?P@d+j!8?-er39w7b~xSHYe zdLBPpUD0k1h?Lj?Q#r*Qgv0<+|CYvfAn*a2NA1;CZXoahtW;jTD;5s0hTDN2XVZhg z2N1LW7l!)!v;aWqtf>j$1DvGvCIDEt1I6f1fJ_}oT!3-%1CSH&7Jd}Zd<%Z*ZK#w| YPuhbetvP0_(EtDd07*qoM6N<$f)XJZ_5c6? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/italic-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/italic-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..33d372a6f147d89ba24fa80721dec28551cf54e7 GIT binary patch literal 638 zcmV-^0)hRBP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?sYhST3fZZq`?dq(42x2W6V9qs6N9- zvi(MlbUBa?pNsfK0KF+#av+3Q2>=$5>|cJSo&*332qDbn*n5AjfMj{;z~-FW2%zT; zT#FdGeXoE^4$umK1t_KV!@ntzQl9I;G);#JNDiz7f~Mdg0Ih(X>aY0UT`at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?dg zYTHsSh$JZi6`Yof2~QBDwLnpMl{yg60?kV+tYsb`;1f7{@qZcj7MS2CFtleGKtKz) zAF!U+ZUU&UPZDr%EtWMo0klB#)?zgQvUdU_s?D7aB%FY31V%oA;H~)Ir{Ij8hK6An YA9}YbPNMGl(*OVf07*qoM6N<$g4p*K1ONa4 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/italic-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/italic-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..35eb0ba1724766b8da2f392900146f647ae54ebb GIT binary patch literal 629 zcmV-*0*d{KP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Y5f~vfw1^ED$s4f(H59-G zjF15cM+!h^D*HQ%n|qZnilUcqeH(Bbr!s;}!dW%xy{#mDyFq2D3uJGBC0z6f#o;ra zrr7t$q%?uGS>HiWCZOnl>lYp%parHj^wEPAZXnhTHi02*WB>s#AlR9S z`ukFW&P-GTXn}CmE^5Hy2|N)uK)4F>0^^@R%O{Y06wiGNe(~GTaUACj>G33d!JiHy P00000NkvXXu0mjf#WfDy literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/italic-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/italic-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e2ed7d866795bc08656a14d4b62e9ea52fd6169b GIT binary patch literal 638 zcmV-^0)hRBP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?{uUtlTRkCb>ZH75J2Tz5u%a zB$E0nhaCcms(?WAF;?gU1W^J*Hx|EG8W7L|rB;Q%cIfXQpamRU?yuLtvH~4?zXEM7 zRSN=IVCedd7gMK?5*XSp`$psh&;nbnGJgWFbOoMp#WYFZfP@n0pc4Uh0^ZDiivRr! fj@WN#7>4lz+ZHYD4074n00000NkvXXu0mjfE)Et1 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/italic-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/italic-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ec6380e8a230fbec211e31eaac0cc0436fd585 GIT binary patch literal 637 zcmV-@0)qXCP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PICb@v%61Y@r zy+X171`^!PPuU@mI0qDkbAEszwglynA2kSQ0mqG&qd*z%AfN?E>)79szh@TEdG0#U zoN8%6z&jw=I%n$lQ3ASoxEwBA2haizh4#t+C79iTd@-tjKhA29Py*U^EP(BR9`8{+ h^%neL+t4r!;{yqbDb3a%SWy4~002ovPDHLkV1j7?7wZ53 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/italic-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/italic-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a57a1da09621823d62e84093bc9259631da19e5d GIT binary patch literal 628 zcmV-)0*n2LP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?q3+qX3Jr0wcf% z8KDD!Op!pi`AW`J^W*msSy7Z+&T$Mlj?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?D=ngb* h!`@r);oHzT=PnHpD2*iBc?AFf002ovPDHLkV1htx{at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?L_&wB!i(#!3(15xfC5Vj=}l z2#ST;QF;+e6HAYvNALveutXCIhHRmjIA6g`!u)IqZyzB1JF2!~v33DHgVql0xKhsn zTmQ%vwYis=CsSIUQPzb$Jt#H7VD!NGbg3%pup^Xqi$q6A{SY>ItB?i+l;tz_Rb?&k z^v%SltM1hD1Rqeu-5{7(py5wN2e!iz&#p^Ko*j7oSJ=JFYi z?=;InE-M?9`FasHeg=V|d=-1K#y3cp@4b!7P!Ky7I~F?@I~F?@8s`aft7Ce=0e`;$ O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZBs-qM% zl_rxUS@M@tGq^LS7C{hP+qNy>18;xgA#5DS86075*5y)X`0`l5!jo_ECm5K&KS14m zSOZ%)!Wwwylv12%L%v^Uzdib~lB_7&uxXki48w~tCc@oTF4WYHo99pj-fEza=Uw2l ry!IX3hKjah5pBo6K-;mlV@0_E#;aod+H;*e00000NkvXXu0mjfm7FFK literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..727169ca6e7daf19783dbb8567af54bfb7512ac8 GIT binary patch literal 637 zcmV-@0)qXCP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?j&lsA_hvcW-I1+jTK0ir!Z z5YMn0ZQ;e#N0^F{mP@#@HMZ7NCwP0jfZ^+l`UoBS^A8{{?)Uj+0avdYLN2zD9wI#_ zAle`Z#ZnaIKd`p(xyH{-JN88ZZX(!n4yeyP5R!Qp+3?-B^B5`}$1)wqKcM4S$FWj3 XM%-=0m?rLu00000NkvXXu0mjfzSI|b literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..742d5de61ae270f33d8968e44a06286292d1559d GIT binary patch literal 671 zcmV;Q0$}}#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?GFr1H1uv0;Qw0 zhl5yBQR5Lj!TNV#94yFA3dI@nW|m}zY_dc46C!2l7+*k=Bq_|vS{smz#u!snRdwTn z*2EV-qHqa!OLBHthcFDEZQI_bf;Ly54ZvKvXT_; zs8>%(3d6^*7=5<%1JIUt-PvWR=s4DKtm9b6v5sS9c3x}Hc6Oc%7at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hCV<|0 zWRx5^c7!ql6NFbaLg5fcK0uN1C%LKAXD6!sVj|_=S(OCNxh8~g!fQ=321IAAy>g-r z_YuiQEIndJaw^2Z81wMn-*TdDp-2-~hr?JB5cO@Wamne{#IsL|iAZv4PFFg>$NBjK zjMD>7Xh}$tGjO_66LyF*Y-pu@fSj~O7S@K7ePE+I&5cx%jFD#d^rSGnUB&oafxZCt rdF{Kn4HX^7I*xT5>p0eNtSrtGvWjbRdTI3U00000NkvXXu0mjfCzm4$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..47d78d5c7a6897e15e0de41b446ec6ea4b2a4122 GIT binary patch literal 677 zcmV;W0$TlvP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?KPy(&SR_&_NUobsg)30E0hpnPfNsMjt zgxfR6=i>MQGT`S2I3-6hstsU?`^-6Tar_oUK@Xb7NCkDdRV*->P|at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Ul9H9Okxn9UFJf$m2c^tt{LyT2DpbbI`C{8?P z!Wt1I!K_ZHLWsQOU4CYkLKg63Voa=DdxUx{zzFn7e1e|+b^&sL4(6VHq)$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..44947a9e64f3b3b97a6af21ba88e25eedbbc3bd9 GIT binary patch literal 656 zcmV;B0&o3^P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kFE2PP;?P_TDmhnO@Lb7$nS)2 zxM5FgcZ?0sRA+|@vV3U`tsEf(x-f}UA1LmRYH9K_&Xc5Y1i^M7-^q~Y3?|||063RIat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?40s~gKW1M7v0!qBaO5i0}F!di`zIvd>^EoJ`-f^4Tkl}I6at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?TEfY|VqzBlf zbc2r2O-zylf&(sT4ne|CN)#!!6Gi^{fb#FqR6uXIV4$?i6+$2k%s6K`-Q+NV&hW+t zToHl2#39>L^J#x6B@>|l`yxkMq(%VUg=?E%`5HijIou7i8<@#A`3ofG=Pxk2sc*SL zATK$C6ep{o<&qdDL|_|WD@jp&fow;OE8sMZa7Hh|iGM(O>wy@}hp^7+d2VtUDr(1S h$7;uF$7;t)avqK0eu|5&nos}$002ovPDHLkV1nRT7$X1x literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..54d55b233bc1565583029e4f055834ee211742fb GIT binary patch literal 644 zcmV-~0(at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@lo$u3 z(QMAte|k7_BtjOi?zd|ZSs{Q$$r|6vP>mijhzRRIB;Vv0$jr}g;G!2PV~ao@IdaMe zR~&gnYMFLOpdidTM=LrjpzWgq@Vv!4=vKX^^ZW;lmot#k^C8HmeXg6m4GptnvtzSk evtzSkBRf~Fon~_K74*LV00003}) literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ddb29f94be1c069b8343ea4e17bc992cea7c80e1 GIT binary patch literal 635 zcmV->0)+jEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=K~#7F?UmsTf-n$;-w_94G#Nm^3D5~d96&~Lgib=e zi$voO4oZKNg!>Xm6YlP{4KEKc_72Sz_`IyRtdKi_z%xJL&9^&P}N|y9zNX*tZKu+F#jST|%^@tl31%1eg z?MF96;S0@*>J5DClNEEPnCc!a*uzlx`v+n?A0+C!uWoW18WzVE#}>yH#}>y%a^8b} VY$_%x9zOs8002ovPDHLkV1h526mkFn literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-center-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..005eb69115b14d7b42c47e48ebd32a7e5bf066b2 GIT binary patch literal 585 zcmV-P0=E5$P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?IS&Ul}1hYgHjWW z_9PJaD6h~Ia4v)77+av;8ruL1S%7vEYF)Pw3zQ`0iVdiBUjda$;(Ijq`UC9J#aEo6 zl*DYPB|n&U11xx^;!3?hOA7u*mrimy``D(@J#Lat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3y+yDRo M07*qoM6N<$g4g0F-T(jq literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b944da93211fc507b705ac356253f87899069325 GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?32yT?rp{lB* z6f~7OlO$R4ms2yiGp80o5M0}~E#L!Je_|0fj^hlDFgNRRsWW_e3}E5OH~A9`%-0)+jEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=K~#7F?bJ;Uf-n#T;5RJPV|X+T5LZELUQU2$ zj}XK&tVUaSG4&CqVx;8~u5691HPs2;9zS6C`l3EU$Nqc+#KrwRzbxSDRYS1ff`pqI?2t8=q_Z%(P=)6yPR;EptHWD3<9c{sG;at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?{`_uzCIx@rJQ5<0R26zMT1j@$f z4hL~$V#XtQg6IDQVsM}@9TXG#OCD`PU)#KX5GjhHEFI%BNRlLlI9Y20lF=ArimIw^ zoY9*2;70^5p>9de4(AYt;j?Yq`;^g!^MK&#pq}fx&PhNV$Id>(D>xt5DZ3T#hW73w z4L-i(E1fTauk+stpnjc`sAon(Mt2&{&ewzm#04iGno5itMeaX4hHiYKD0)B*s2?jy z;Ewv~DM?|_RjjL6SMlr#e2gI)$I=f#f4t+){sPJi5TIf;S|_dE00000NkvXXu0mjf DEX^n{ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d39c6a9891eb93efdfb0efa08ff4fe9be69aedd8 GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hCV<|0 zWRx5^c7!ql6NFbaLg5fcK0uN1C%LKAXUA&tOr$7^^6#ul0_R*4LO9{ICK&^wv({cY z(T4koeiK|01mIOq78*5y0x;63alVT#0oSM^>8u&Or z-@rIM;DnZhBsl}8D_z14afS`8^d2B5t&xSb;bb4!=uY!Rsz}C2vwM0{7<3ftDArND pcmr=X#IXhX0@&xZ@8W+zc>?>nQ!*SL=*0j4002ovPDHLkV1k2tAI1Ox literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9411aed36b5ff4abb4add68cb7c9c0e6b355772a GIT binary patch literal 676 zcmV;V0$crwP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)ht$rBt;fG0qw zqvZsTp;Rh)3{H0KHAG=#U2-QezhY-6J0JgSG6M*LApAS@DZpFTLnzfVS08p9O!;Zt z+$`{|0B;p^OvoH5a1`|~?ak!fyUS)1h0w-mJ-W7bLs;N0gCP+Ol%qrAz7^oGRWvGz zv2C7kd*=9D94{aPeqO*SIf_wj0889w&Vh^LryvS?&@@IWsLPFFfyso5j{8ERd^XeI z8@B{IPEdLjx3)6~46=%470W8lUBJr}c&n;L2E@(nqi^m%Alw0(>{&Cl0>)JU0000< KMNUMnLSTXjPbW+O literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8653c805c81dd23f26d221cc33e97c17f096b157 GIT binary patch literal 644 zcmV-~0(at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4vh2k2n#S<7>H>S72D z>^a^mj$CqrB_c>GPHe4c-GO>Ym05rsU-2@r?B2Zv9dkhGD7Mm3{0&;bQy0YiZy(!~ ey1c#bfVu&Tzi`M@&BUSr0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kFE2PP;?Pat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!HXUjP6A07*qoM6N<$g0|Nf;{X5v literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a4917601f3e4f6398f3c732bacb788ee345911a4 GIT binary patch literal 658 zcmV;D0&V??P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kK@jZEE%5I{=!4g;5?KAhDEVO su|@Ih20l)K#4Te2+Hp3Y%)SH09X|S0hpcM9BLDyZ07*qoM6N<$fat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?TEfY|VqzBlf zbc2r2O-zylf&(sT4ne|CN)#!!V;z&3Hn_SAgZUrNbDD8RnR(H5x@KzHHV=2yN3&|nUC!|VoT@=g8%iTU{kMmO~> zR|w=KXOQA#6|`Iuat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?l~%%%z&1U3cz!UchD_+P3P$YhP7gA#ny_m2k=q_Dfb&M?6951J literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4ecfef78dc47cfbedda464b459a7e1f95972131c GIT binary patch literal 633 zcmV-<0*3vGP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~r!cD^2 zMxyZth2wr43H=htCA59Ll2^bm3}f%mT!7EZioK#HEZJ^|wmK{i;x T$E4h}00000NkvXXu0mjfvDp)v literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexend-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0a5f8a2ee803f963a5a3a374659a8d29d7b5be92 GIT binary patch literal 577 zcmV-H0>1r;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!Y~kqe**(hQf35tL6uv<+edVp;r_mMp zq$+RtS6%_WK*0OPM z3b6kIq5S(oMMy#k7lOH@0QxKH7~3MVvPRT4qigcKk7qOER?MxKTQS2hOy%4F9@0;6 TqcVr800000NkvXXu0mjfK7%QN literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d36af20302d65184ca627e599da5d430bdaab6a2 GIT binary patch literal 662 zcmV;H0%`q;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ID94x+F=>3_X21tZ+8u$$-h=(;ZOOoX3oU73Wy8V$$DWzeB wNXWLjm*O+pB7Z?295CETDV9at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?V;X4t?#^O`{3Y(I@TzoyJxqq$(BsTd#m5z$ZXD zbL-;1gfDL&!kIH8?hwf}2GJHlP=s`N{CCP%U^CtUkH}oYzT$UWWYBuf1s5z-YN3jm z8O9hI6L{g;wl8Y|pMc7zW=swUfy^AN?JU(n6(=X9Nxp(F*5@U~7t}`ng4PodDHbUf c1VLzkC&}YfiKF}q3jhEB07*qoM6N<$g2>4jV*mgE literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cf192c48c32b08f9ebd879780e1c46a782f5e83e GIT binary patch literal 674 zcmV;T0$u%yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?GFr1H1uv0;RLG zhl5yBQR5LjLHu`yani6cIwQ`w-%Qvr*<_P_5&b*H{mHV-(idpk_Gx!PzYKfi6R*6o ze|8V(1;h&&V+NLpV@ZKHdpb#PDJ@!SYltI8g##;k13aRZ)+1@L@B3?-rZ-Guj5UQB z9v}{=`7%FUKExD8$MJ8P<{~LY9^*S0<`}Lh9L||-k|cM|r70y}6%^x? zlc}Nr#;Pgd1wP|6rRQrz8~%hEclY>0r>$69v9@AGQIy$v0BP4*a%avgq5uE@07*qo IM6N<$f*2at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?b;Oaj+s0B4Zy%v6%WFkeT z@`=9m32*~>4MfRO4O$ZzVyBw3u8wp`C-6p)G)Ez57M@!xN=QiN%yn!lNqX3qm@vVPYWaVwGn#hMT zQj&6Z?;WQwz}|XOBAN(G`YOz9K<@(*jbt;uJmHaQTwNVoF70000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DU<1koFiM$# zZU85s41tLesyNVuG*XLHKPgJ0#If^ZIl$1N&q;b?Mh6^Xs{KazXGD<@RerJWT>%Zi z8h}aFv-C;DD|k}d5K7p6G&8+$#t}9MfEe>)MEj<7s{+NCayft;xA^MVsAt;J=3EiT zwIR9lf*#1sZ~{L{^L$&^6WEjR$}=YH5Wp)BV#?8mwBn#GC&*v0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Z0e3m_Fh z8y@wID`XP++%>zo_EDPDgK-oYk%)ZwIgIeSLqsuN@QNjwl@HM v4lowo&oU2x^C>ht8^tz?Z4?`ZVT{fb1d&-IdRLt<00000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)t1>oPo<%{<|!U`B;-g$TM%djFfs(j+VxdK{%SO6l< zyoL~ZC}iO?N&8STI_Ekn;tCaz|EX!3N6IcLV67cF0A#)*k$8?Vo~7gpgSibfNLrG! zBRLOH#zcO%+%FIdpiVwg;yYBpeZakxvhOp_?Q6YIkO2yy6Eu(lJv|&_gm2KhVDkcW g6zeEf6h&EsCo-#Oe9?c?TL1t607*qoM6N<$f*=7I+5i9m literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-flexstart-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7a3ca2709a85bfbb777a6316ca43a4de8bc08e8c GIT binary patch literal 664 zcmV;J0%!e+P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?8 z^!}1^T_TcE%uUm+wMhcE3_1dXlg;E1#qfMftEtoqT*x&5?tH=0)%SI-JRH y(tvsjB>BeQW0SwdB%01zv9)4r#fD)Ri*pAzz*^`%%QD*l0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?tUx>p2kivu zz!K;rW;r-q2(CLSGvqt$z~pDM$(vnZ?oj{dUNYkctYdoZyTFuj9SP~mJMn+-fE6%S zKat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?E$;;pV5rOWaS(E&NE;E_yVYP zkaJuikf)AZ_sS(l9wWI-2Skt%X4?y$8`oXRQm>^NfM*wyVSHeawtNaXOGW~7+E6#sUVftQdAoye!<>?J_Jzf iV67O|iVeds{>Tkmlu-cu^)2K80000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?UmaN!Y~X)uMvZEG&%rnm;ji700Y2CjF3qh zY=nTH#DoZ_RG*J3Rjwbk-2|9A^!gH;F5(AJI6UIcFlMA8HC1`X{_hpA1e63Q$dmiH zMj=ldy5w|}cd~RW*`bQqQaGMdyV(k`p=U{}eMQQegRgSI4S_TP4^z)FCo2>oZ5#Gl z3zQ*r3wCls6}LI?sogoU4E=qvZ=&iVedszRwka WvQ@e7K-m8P0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mINYiLh� zzC@!BM@k_D{;tb^MBxFQO5Z)cOd=SSRFdZ?<|r;Hf}@y-=vF%>g4#|z SDGM|J0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3($wB!i(#!3(15xfC5Vj=}g zp(qw=N9jc@O)Ncv9>Ei=!}^m@uw)x4n6F@mF!P3xw>tr7I#jp|)*AmHUH^n<$Ntm>R2U6`|m)HZRtAwzS%JLB$Ku-7G;8!If_fu^BDcJpgtwu;*3rA*JBN z=S(A`QHp&RP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?eivg&r>ND;PQ^#}#q-naf z*6w&2!H<$Uak|e^&|G@RnppFcQw#XBq*g%?+}pM-&at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5T?4+g_#r^_~K$*tSPSu=Cwh%GX99~T?O(1i1WH% z-PiEt6GO$=X b&q#R!Hx6*aa^RyV00000NkvXXu0mjf-}W5U literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5bba3ade3da99667b5bee594285ad31e3de62174 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?1M5sNJeLjshXyFaZY>UgI^K2hIu48CyYxR$KSs1-*Zj}ZU+R5{RRZ^&tpcas zBuPFnBN|mL2|Um!-kKCeVbE@<-B7!scEi=to00MZHGz6{^2q8X00000NkvXXu0mjf Dly@ia literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..06196c9ca934f386fef381f7dffd29dd763f4a6e GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-}ml;_|a zyFP@NsG|!rLiPMQ?w@w}wE*Yfjg-q41+WB7AH&ls>)zHz6ZueWNm4GJgUcKS*n4kI zL^EMYUzwQ&=$lZYm29TT6JBYItMe;;3i1kwlBFJWW-!D~V?v#uz6k?w0!d30g2uW@ zsA(c0g4?y$Yu;5ey2@<8j0i$5;=y?XhG8_Y8nPO)8nPOe4*!gpH|WQ5!|i6;9{>OV M07*qoM6N<$f=pj1+yDRo literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..03a8a8e3658dfecc6d06f537ae8bd2ced94c7006 GIT binary patch literal 649 zcmV;40(Sk0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?U%s~!Y~X)zdJ?Y#3XG;fe9!Rzy_2FV3aTc z-2hHN83N-VRB?cWq*6K5Pl}RAaqKwxvH}bpdY|N1X7s>5rPgnPp+mj}*^TFPM=8Sz z!l;R{F(cX`Hh|*7QzmTD0dcS}DOHFeZ}?yzrUbG=AlAm(N;@K!*9Otb_{IM3DsToM z_jj^=*6^&9Wk)fg}S`D3O jHS7behFT5vXQVs;dliW>YoC%q00000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?t_a%t|vEKwgB5RrpzD z=N~>z&TjH7Cat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#q3u380XP9TfjEKg(>7rQ zHmUC=#_)&M(nNl6PeK|(?}O{Txs+({sQHWcKGGjB#(d)*Xz!@p1{_PHlxky)Cn{rv z-9u~rqO}Qx5Y7nvqzYhvwbl+x-;WvN=Cj`5q^AO$b3H21;b9*Gt$|fhql{ndH&;P2 z0hDjz6}`|=Av2pXwJ+I(IL8)A+^GWCUs6g)R)D*g9Z=>k76MPKfSe2kL6B)E(@>_N fOvBBQo00GaKN5`XDb|aI00000NkvXXu0mjfe8(M@ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..52e79d95b2a07c3ea8e71a0b2aaae4a6d57aadc0 GIT binary patch literal 660 zcmV;F0&D$=P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PLCGEC4_InHc{f-)loIT@uL$lWj|DQ2 ziAM$vmYQ2a7p7!$5XlukAVt&{*at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?U%s~!Y~X)zY&8l3f%+_lw->TEfY|VvIH`oi5}{Ah!VwiqS#+nfTcsz#j|F{AK0e!K6izsLq3D9=1lUE%XEVf z2)!iqnxyp5%@o?2cVciy1agT}a-{0h{#tXEQpvz$kh26S5kPz6Qv8cC22kM_oGN0J z@s0oND)3!ka6{K{fj}lcy=JEuVZ%8wE{H(hf3GP)eSzdal?&h`g>Z&Z0Uj9|hGE^% jx}kML>xQ#qKO^G>1*w9GOk+bL00000NkvXXu0mjf@SYv? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..50ed803012eea12e75211667931f3b2c98426d09 GIT binary patch literal 645 zcmV;00($+4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?vK6Il^d| za6aDXioO$AFL+6e3*so`%c=rC>OOPD`kc3wIQXY*_qYtWz7-e+vA6*5$ z2|V;At0)o3$48Q^aoLe4NG{C@5hR3F48y9SRYR+W fRt-nTZbrrv-k)l5ED0tF00000NkvXXu0mjfZF&~4 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceAround-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..64c3f60d1ab77b62b8d14eafb98a2ee95cd79819 GIT binary patch literal 636 zcmV-?0)zdDP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?U&6BgD?z*pHT;4v@$?}PCz?BX*)m}sUu_( zQd>nW7aT$)INat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_CDx?w+|!3hRa|6h;;b}DZhg>kcu5gEP!^FHXcW#J|SdCV4D(5t3^ zPA&15SHaN+{{FEfz6jdI{LsrU5c5W4aIJ)yafO)*5Rr=NhN}rdR5xs-ZrHMkdv`;< ajAQ|l5P82A4t{I^0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}|Baqq58nB{L8a6ab+DsBoJocV2F$$^Me&TpIq1(Su zERR+#xFAgTBCNt47=~dO3!>Cwvh?X(A3-S(Ze-+>Vjb>nMs_V2$3sf4&+;bRX^|cb z(CJ-`rW9aTL!tcphl-Gd5-tRDNddGZ>loW2v$6|G+l;Qs^FE%CmR3& literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ebb5288a7a4c4b896a77fb767fad04ecf62aaef GIT binary patch literal 659 zcmV;E0&M+>P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hlBZ70T&hz}Dlq#q@MH&s2 z4K2QhAP9mGLA6aFQCWr%SQ84Q!6LMa=>QYe0urM+HT;%OkPd6dEX%U1_r69KX!l1> tsYs41Bto{;JtaG%E0Plq!U6di2{&M~J&Sk|TF(Fg002ovPDHLkV1k3B9Jc@f literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cea680bc0dd97582ae759b7606f3f804dad7cbb1 GIT binary patch literal 641 zcmV-{0)G98P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?F8F literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..034a3ae13c9a19848cbfd9b5461037cb52b8ce9e GIT binary patch literal 677 zcmV;W0$TlvP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G44&4WtP4`+qTcR3;JcaBA-;{ zmHD$*KobxXFvbjQv5zGM;>_tJzoj&2t*v2>XcZQ$=ne1?wKN_{gMHs$(=@%I8>6i$ zEbstxz&n2?MNt$*!1x^UJTGAO(1n=7=vW7urnyK?ktg^Lf%#j$qHtI{wn>uQSyQH* zd}>&XT^5y!0vOe^L=||A)0Cg@K(gUWXmEFqZ|n3(HhTj4XQVs;VLwSU)?p*-00000 LNkvXXu0mjfSb{Ft literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6479f8af98641e581562aea137879e08d3973d22 GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&XN|KnHq+5|pk8uovza{5L0bH%h#lby<-P2d9bJCL?t(Dat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?b;Oaj+s0BJsBG*DiFvv2zlVx*2P%utUIEp_iet^sG~4OGb*1+WB-Z~em}D{pJn zL_X9&MN-c0z2g)H*jsN(L=$02Uxk?l^z(p3BiT$ZPk5vnS69a)S?LD&XT&@K^_4|y Tm}(Q>00000NkvXXu0mjfsQxC? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d35f2b38410efe90fee4d693a5a369c00dc11cfe GIT binary patch literal 647 zcmV;20(kw2P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DU<1koFiM$# zZU85s41uu`syNV;G!h`yPl}Q#aqN6Wi39Wat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=)tDbl#is;utZQbMonu+$bhb*o(`4B zT`AMv0QBat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|C3Rr7L4gi@`Bofat#p& z6fL#Yj@s%0%9zOSmTSdg0W{H$l=u!6@I2s|lCtkJ&h2ZxP>=x%ph-HA0zG{kV}x(e gJK-h@(3g?&1TZOB5abf5`Tzg`07*qoM6N<$g3RU}G5`Po literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cd0766b32dcdbe7642b706d9bcba8b04f871fecd GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZJ}L5+K#zAxh*&94oRDVD8X(aj%*21=cCO_FdqgaT$rp$~*Qy&wvHs z3!ryH*KmPAMm7&kk2GQ1a88U9B9I%nO;Wl|$<+)bJF1)m2~$1A1ijq3~> zpF&r2CgnJn=?Wo8`Ib_A_LXA28P&WIg)1T$`oW&6Dfv<}mZxLp+L<^xijxunv==VL nz8HJ}6+Xeat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?E49o$S_h$vqJ(IVX{8av9&*>EbFya12F#L9dyfH6>{!4j^ij~3CwdY zq$%Z8F+>~<6ZTtUD-H%Q9r2hL2c%JHO=;^K1Qa38i~H+Jj4Tm>R8p1KlB_mre1o3} edl7)&jGQayphKS9g2Xxi00000)+jEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=K~#7F?U(Hh!XOZa-!l%<(d+=WIDtBWr~~Loj=&_v zJ7d&8a3YCq(tCb1G`#o0k#GRa9s2xOCwgwlBtATT!R~~!NWfl3#vRM* VMp7(}0TuuN002ovPDHLkV1hud89o32 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceBetween-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a79d997f8aab9eea30ad17033bdd031412641aec GIT binary patch literal 580 zcmV-K0=xZ*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?s|m)Msxxz!cg51 S;|Em$0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5N`zPEv?@i5SSWBqx;` zbJ;cU*Z|x-6qC1@c1y(29xtT%T59}iVRgS@5?19C-sGH<;E4gMugg!t^5` zQ8M!%JQv7@aT@Sw9c$!I41j-GiXbLX4^c3JcnJf&#XV#r5u+}qE1WCwv(3dvDi{i8 m#b(83#b(83#c#)MM#c^aCWxIOJ}=$?0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xPNp{b%^gFJ7u)1-F&=zTK+Ox!0$4JMsZD;y z7VsofFLykMQ50Ft0L2_eGh19h*L6qgkT4aU8P_Xt02G51XdR s5U~cqfJm`Ou}HBat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ke2I35&c(dL_ zhfp`@2CmQz>T~y(at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?p5!|axlSM^JJ3}ngMf1QJ2a^1#NkD*q$6FrKG&S%8s;ZiGcOYzx=Q7Y* zhd~f%W6T~HpnY4{b>p(LCXi*>ewwBmS9}icd7bb3aaoq#CmUr8fZ_#-Qy|>0z!T5O zcO1tv9%ERO00z*syPo15`1UR+e#hI$X6I_dkQT1^i%$q&B+%1BwE#>OKE2J(`U#L0 zuLBh#PDxe`pifRa)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;?+&==`1Yqkl@xmDM#2;XtPu(4am1%MgJTFDlQ5t28 zjI}wZCR1F~3>C%SIO@neZq8wkG<_)Us5{Cyh1jca0+kJP!6tX{3;N$^9#ot1%RNIC zk~tI-#V9OjU<%1J${WyejyZBiFj5CYdX(d+OUfZT2Rz)pzl<%) uaFk{21R;TpVj0CUie(hbC|(`;83`{55n-_qqbg4T0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5E#dDMupE!Eg(H{!i0Tr@;5axvT{oGH;0jWJ;GW#NuGgr2tW#7iE#~V#AfJI zfb67udic8NLSAnx$tyW7G(UX}8L=~=$v^JI=v@GzamLL80%_f8G(UX?WRhJhH;59j z&kVRG)J+(C3%ok;DCEL9Zu&5FCC3#-Ij07Of=RJSu}QH>u}SgZ*q@Pc2a?u|w+n9? Q%K!iX07*qoM6N<$f>Hb=V*mgE literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..85c46981a417bbb3f095eda18476ba2d0ebeb7ce GIT binary patch literal 697 zcmV;q0!ICbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?oix%;8Ozaw5hH>;@^d=sdQPiM1pT|q<7 zn(ncbXBE-|14VcOcWliR2;Gpr3{$YT88~%dKwec&$)xZ>=->tQPY1>VOEF6^OEF6^ fOY!LNpAqu_@X&EVo`lu?00000NkvXXu0mjfNtH7= literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b45e35bf8830cc985fc7b28c27c21913011fe4d2 GIT binary patch literal 705 zcmV;y0zUnTP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}U(QB=j{tOd zPF#p}U3=94dat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;u-2zoM^QV03$D|bDaa5{*}--0GYIN{W5{`W0re0C%Lt;7{;8mNP$^a^ jRw-5~Rw-^A{WDT-41|OmHPu}I00000NkvXXu0mjf>)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZuqznN-0TMST2|6HJW&{eFf kSXZ&GVqL|Zqkl%q0|z>PWkat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Ln06 z=#Fv;;0AMpxdKZzK#sr?ff(ZeLI^>k3=%Bxw}>W^o!B1xNdX=mI^HzjnQ;SpQ##yh zpxhaX8FVaXiznn2!y*O3s5hY^ZWf?r*;WRnd|K4QnO8KrV{(@ao==(3fokwE_V0?O~F|e;|uYsq=etq5~ZkQQV&$p1N$?I`T?x*D>W*4HwA4Z;+vOV@E5U( z)BNBZk!Cu@5Zv1uMaR(`N&uB&m131*m133RyQ427WdpzPjm-%u?c@Le002ovPDHLk FV1g-pKfC|{ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-column-spaceEvenly-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0e81a1ef0b2e349d11383ed909e7dd09b8376af8 GIT binary patch literal 683 zcmV;c0#yBpP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(SVi23BOf)`s2#SO;=QK+JiwI?nzOl%at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?pO))O0Jct;KO}+`2xPk7!TB>mdVync;N?O^=xF(= z8~g%`N2*J9x}2j{V=we@!)N6^^?;6RiM>;2SYY=osPc`&{5l#iSVz*)`$r~7167N=A gCAk%E0sk{{UQIBiG}dIJ!Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?iuJ|7e2$S;wpA=_Xt&LY>00000NkvXXu0mjf*|#G; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..701e361f869f2bac4c41eab598d4d96992775c69 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#A^ra98#t4ZETbU0=&Bz-bL3tr!{+XgElrGvpLOa6-PD{7G!ZoR zdmq7CX9p0UI?t~dGIu+nZfggUE!rsfRD1{n%at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?C7Y3rnyhtpGg0RXjr?RG=kM z0$uo*FfND?0!y-RK+Sx~u$h;<@lA%HMCFJa|#O$4-Q`v3p{07*qoM6N<$ Ef|}?o6#xJL literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cd44da2c02d03f2d4a49ba6f562f8b5800e9e53b GIT binary patch literal 660 zcmV;F0&D$=P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? z{iYRcBBd30|D6BO|K7QjF^}6T@aOYlt2zQb_Z(r08#qE z*^g9L#O1$$1+V}Xzyf|x02;=}S#++uANTw*l`MxF%mZi`3g(F=L6nh06eWat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Z)q-CK5zg4002ovPDHLkV1m148rT2; literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..960a5c6d9542e79af0f6b75143ee58742d5687e4 GIT binary patch literal 682 zcmV;b0#*HqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&n@V15}V7?K*OK?@DT0otEL=R9_irc3$R zE65Qb{A7ALpoFSkZ3UcQFqaeT-X>7=0or$uqa{o~xA5v)AcXsT5p9y`Rb+!?t@N}- zE=*W>^#G*O0=HS{73F(g_h7=p%cpyl8K1^76wG~Jvp}fy&0imUhkat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?G{~Cu-pB%vnkWq93Z~}1xVFDcm zH(&(cM2DdEcp-$FdU!xhzoa>|O`D&SoV0-Q%gj?|W9YyDJ);7KbwTIC9%b<5b6N-| z#E9ZC?a{)gwUrxiPrQ%@VX1*(#)O@lvX2IAYAXVG0MDGFcykyLJh zJ*{%?mH$p(eFZ8&1*iZO@O=UZIGWQr^ST(%eL~XI%%--w4`hf$)>bB1Aj2cb+Tmfj~ipe;9OYQ&w002ovPDHLk FV1g$AC~E)! literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a89fd707cca830a9ac324538299491f86e95817c GIT binary patch literal 661 zcmV;G0&4wat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?f`8O?bOLY!j|sFB=r{)d zFanc!UWp`)r6iOeD7h~=pqISng+lHD%0ELDvnxzsg_%(U>%L}LaV`g2$YbWUYbi@R zbH@ND zZ=E4Vf>!?mHJ}F6fExHo1C6_sPd@uiZ(SqKXl5izGdg@k(9WOMVtH60~6+ v*cvy_k3DW1yl@%{BvZ6WXewTW0cCdHT!w8=(Is3200000NkvXXu0mjf;w%{w literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..98eff40da53f8b278088b67827fd732eb6378c91 GIT binary patch literal 669 zcmV;O0%HA%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5au zoh0cyXdoCP7(Z;wJ&55RdFM+s+z|`4n)tMyJ`7={z3W|DxBf_rpbS5W{lTF(F$mY?~S=ee?jW9G4wk^+d)&iw-^KZ>HL zUDAmY3S+faZh;sO17bi7e4hanj2F+SY*&|e;xUvgM(gzhTI&{x?xat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?sgOG0@-&3#E5?#kc%Y1-TY$}f{}!TrDjHdq-ou>F*bxl9RNCZExmBcNeW zRnzH?3Fc~@6G+(XWrM4|L66+Doy@nG&lx;~XdMFtN?)>~rkuvn$HO|OJ_8|I$H3qg zsL2>RZ^aQjglP2@r~x&g2Gqb;8fg0|;WD?AR@}hPY^~D|NX4q8c3*(bNWW*^E8X}< z1rH%w=L8;Pq@MGET(>QQk5diF5^WIL75{|+Wp$nvoOeyog>ZEM0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O{}>Cg1WS-k^q?NW3d9P8qj=Cx zkPaw;PR3cIWOadr<$#)b$+FBWfAX^nVF2Zqxn;~|U;q=0j2f6WC5wzhIoL>UXLXWL z%4w&;hOX$Kuh!XtJmaMlNZtw<7;^$H`H3U6;G=a65FvbM7>C7%=rv4iuQ%bNb>9JT zYo=gJv7NT!8QSpB>Q|r!)PNdL17B&NGMD1adpl{xCEDq&b@~A&q{KMNA1s!BFRt^? z&QGQkE%<1i9SGKx$b&1>M0_k&QfSxJkPOj!pat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?+ z;sP3PQl}A;hPEUv3)IX@rqF>;KBZ&^5Pq3mrj!m$Ai>OtfrTr%&s4#Ol0R;0q+3O3 zE)Tk6gix)u0^6lpvA7;QK$DZgjW=Bh4>4NH0N+@2r^oY?s1H5w@&!D^XkB|C*8>YH zGil6I_zBj^Umym=fEW-1Uuoc_2d-QPGuh9%vb69MtabGR4ab$EVqrDB$hED3pJ1)E z0$jQ3gs{fIEq&f@a~f$#rf8#(uJ|tu2($ABtM+4CG9%`V00000NkvXXu0mjftI#2H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f6f4b96f18721c7ef3aeaf8c5ab568a55c3e7f71 GIT binary patch literal 658 zcmV;D0&V??P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Vn3)qx`c&-{im}rer@dWU#aJL6c zfXbD50<*>2^)o>~(_o@|P z)IsL*U%&!b01IFNzbHVsc*U}MN~5D6OKS~uZlNFWEiSyEVUcLd^EJ@9*&D#70qeQk sPx#07*qoM6N<$f_sD_761SM literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-center-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4fbdf2748bf0dec6838944a9f44718fd86ce133e GIT binary patch literal 605 zcmV-j0;2tiP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%iK~#7F?UexvfFKM-MF#CJ;2$-sScseQ^pP009U<;FALT`Eb|vEQ4ad(K9Wzck;wKM&!oBsJJ#KVZ>;? rupG_vSfHl%6;cAV;1qNh0NptNSWJqr>kU>|00000NkvXXu0mjfuPX*U literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..28c34166dfc2775c415619bd4ce1f3665fb7f5ea GIT binary patch literal 671 zcmV;Q0$}}#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Yn>HOl_&dTa>94}Uz=(lKFZD9>0SZ9m8qqVi57uDNuM*| z>HqtHb=&RKwjj4a42S_SAO?QPfV$`+OyigEqpkQ^?$Wlu9R-pVkIjHEI5(L8RHjm5kXir$002ovPDHLk FV1jSIDr^7% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..82f1858ee93a383e04a2b415b30d87c02a57c678 GIT binary patch literal 674 zcmV;T0$u%yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7E5xm+L6%uoZ%Psmx8<<{B)kC8X7 zP^YG8t^)20#9shE&IW?V0l_uu631~N;7&JSjLG>9;S#Ggu7L6>6a@Jgmus>Ci1A9P zZQH#+uj|_N(HM6Kx(n2R8c+jj;HM09d`XgI=MNFPuCKS6c$p8QV literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ce06b9bc514a88df7091cfd396c87832241aaff4 GIT binary patch literal 664 zcmV;J0%!e+P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O@2K(71tnOLQ~)O8ulg$_Y6V&n zCD4Vhgb_9%5Wxk1z%VCSHZ!@*+(0%vfY3XfJFAs2K+A}MQ6shUut02sVPr}2qsIyE z_@dW-La5#Rx`;m5xw;ZBv7a7mX=B`p>fPWM3@x>BxKl5uD~?s3EUh+anx}yQo~zB9 zZ42ovHniFjat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?WPO<4thG~&V_`oZQ3d~Bec}ebqkhd9X#FQm z82x0oS#Az|3s?XPU;!-PcLbo>EZ(A-j5JRC`5QNfnr^6J?if?(fT=)T%B3i-06Lq( vA{Rk+8Wvt)uJl3jj=Kx+t9W+;7@Ok-OF3tqbfa{;00000NkvXXu0mjfE?6M8 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cb8e2bc62389fe911de7490e09654518efcdb614 GIT binary patch literal 645 zcmV;00($+4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?YnU$j>Q00?2XBI2+!3;`sJ2t}Y!NTa_XXM&njPrkJs^P>$+$hl`7x)BdXjz3H_(cN?#}?zY-v;2Utk8z zfEh3YhcdA61!Z=SgQ7ogX;Wyb;e>di%z9a5(3kUBZ3@kKfJ^P&{XQwPARh8SlF`=3 fPQ|-3U{vP=5$;?$_L{Qc00000NkvXXu0mjf(p(*O literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3e64164114a18e4bc5d57561e62db07993f1ac3a GIT binary patch literal 685 zcmV;e0#f~nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?JAWYJ5pIiPtdOgNX_eWZs`i7i%49xWC_c0?Nat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?npA@x8UhNlEkqsdH8?y@$4?EAGXT-oLMO@sd!aLOZb?Pj) zNU&97+(&3XK!~I~)0_}?fj~=@V-urg4mq0K(Z7H)s7xY)HGgae&&@tO_d{Bn^ef)4 zPiQYiE4M%lhygJm27bqYt|CW%7FSxi>#sRN+okoyjiWqKt*hL|8;D?Gdx9=4lU$C~ x1RG9*&Ph#TeOl8CI1PzUI|!s456*zlI}f)eY-w_6aDV^+002ovPDHLkV1mlN7jyss literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a034833e7249ab8aa0ceb023b9273df1dd97c2c5 GIT binary patch literal 665 zcmV;K0%rY*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?f|LP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?I+wg$)1BN-4V-V?)XV)SgPI zcLnzg)i)4AI6>$$4O^(aoO4|Tcewy)W~X@9TFbOB$2y$WmbkbU3jnnEF~;0zk>pK@ zn*+ZB7Qg~n01NmZ0bn*GMsT_-t&@BxakG6zCD3l6@k7iDJg1qU#6=`$tiAzowjMVT tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mz<7uNb4fH0ti^mN0-_Gm9iG&F*XQPaoGE`v;K7h zG|?59cM7mfXvJAb>q2gU7!U(uKn(npfk}4-b&Wk~#bZe80wIzushZ#YlP6Va{sdvI zeyEz~+R+ubq2i~ON_^j`W+I@y{UPya(<8s)uQMPd=K=1WU5(x{(wP7N002ovPDHLk FV1oXcC~*J) literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..df66b8cdef56e40cffc0ddc39717c7b8ef33ad59 GIT binary patch literal 678 zcmV;X0$KfuP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?T@4=* z8eY*$5aP|LwctGiRY6k7N2A@iv^EetsY;5G;5-%Q zBW~B%1TL+x39-xVJp;iWGf5%^$SBnE0edtHk~iA<(W?0C3@Een06+s`uRnqWmjD0& M07*qoM6N<$f_)Dpy8r+H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5a5a336221fae3d1ed1f40e232712934cc922ba1 GIT binary patch literal 662 zcmV;H0%`q;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?L1Y$@dSD# zE}-EiwN18U#*s~az|fa$qvg@PjV&#JVs6+KMADp{!N^bni(kn5f(#E8|G?aHw}f!J zJn@mh{X+5%Y?rj+U`-%ki3E2(SXBadxB#BS*vHfPh3J~t)^B25%O56yQA)=_j=s~g z^B6Y-y#*>j1*iZO@K*vl={V~he5bQH%d|0W2ndO=>Gs<9K0{d7wkC*i1uiot?*M<$ w$RzN&QdvRA!>0BMl0NPvpjGkY1Sm$w8_TLww$13lqW}N^07*qoM6N<$f*(gH5dZ)H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexend-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fa33f581ba75e54fe7a94525e8dd143cfa44947c GIT binary patch literal 656 zcmV;B0&o3^P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5J0<>&E$x>#xShy-6&JshX1PoC|w#|A7W=@ixjsH z{0dkA3t#~(U`_&1+b@;bee7**Tb75py-^_(zTDzzfKi2>AkB4!%H_^J0SZp_y{O)I q>Q^Y`E^bIZb0+}qiYF(4F*;sKs#DW~59Y@J0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?rAghOHpmTa1KZ?My1<0A)4-zt zz`*lYFQQJRz~3O|m=CHm5D*FYS2z0M=#2G4-^`M#CESGaOoFUjgr78ElDgr#D`k1D zTHx};bWM`QR{#MBKmY=t5?I5*|HkLI7|oYbwu#VgDUTLp>-Gh-_j#LK%Tcr!C}i6N go&fFmbpoI}8&(-z+xBz4@&Et;07*qoM6N<$f}|n}!Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?i19s7=5nW{- zpnT3bR;_^{6>vdxWP^SgS*A0nYtg#AUu$97iR2+Q&cP<(LdCq}7o*TIQr;t}*2ts8 zsI_3PKy`sri@L3xN&BXO4SYSePp!L!|?O<40000< KMNUMnLSTZOa4dKL literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b227e809dde4c946e778b7d4ee058fa25e5fc623 GIT binary patch literal 686 zcmV;f0#W^mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O5j}tfA(qrY;ZZz-o&Y@o%L$au z(&JcC05u1o@dWE%!X_JxI~b#wI4>FYXYvz%c8eLuVSa@uili#%%ecmiI4E zc~w;xvl+*6BBk6z29(#vTnpd##S_m8wedXf*0$}n54**2MlC5X#lsUI{md+obw<}s zvat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? zf}7w^0tq3MYhtt}y)S9F9)EiO(T76_=3nT#&iP0Dn1k3DHXvhA`Tw(&@@|ZIrpdnV z2P~s=?nr5CtT}-eMIJCXCdE(4>8yBBOVQ*BYpqP*@iB#ELTA2X?Qr@fZ3ckkQia%-(W3?00000NkvXXu0mjf DL@6oU literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cfa52aa151fde8dc11bdbab1d89046b4392f29e2 GIT binary patch literal 655 zcmV;A0&x9_P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?flcab zQsPat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4d1>mhD%JS{0|4Cgca~ei4rhGxb!GFX*~S2geP;4PL|^!62c06s*uCaW zUz=?TP}OxBdRb`}CW?dxEdn3_0w4ea&;oQ1)-o$2$&SUPSN2p{_4BL7 z!(4#*Eei^dVF1Wh{O{-Syr;}+RObj{NO2(#8ObE%vjEQdI1}lzwMA3$-vW?Y*A4u9 VZB~Xjzt8{x002ovPDHLkV1oQzFn9m} literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..60bf727016e43b444544b89702225e672aba709b GIT binary patch literal 667 zcmV;M0%ZM(P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&@pNNZQwco3JHpGh`VMo zxloE%Sa3L&wBH)A!etp_ZsO^YW`wW}(Mq(AU>_qk7k9Kad3Kjt4Mq3Z)Ff>%zH8{# zKG90(El>k$KnI zAnt(aww~{eM@BiqoPRz?r_*=ZVDwe|w+58XxdG33aO#<2c_9D*002ovPDHLkV1h5p BB^v+$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..21f66875f901a51dacd73fc594e4951de0822462 GIT binary patch literal 662 zcmV;H0%`q;P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Owcj`?gY>YU>sB~ z9ifw8Tog)_K#~eUk?@x+{o23kOLH-R>Q_WHb649W9*^pBHz)b2uCobRtyONLZosU1w4h9fzjN# zsXcq0eHY-OZk<^u8`RWoxO;*1RP_$UGwftWlBZxcqLeFW w;Q||b$)GuQyTBU!lX}@?=~n!=0IJb-1sJPZ6#zUrY5)KL07*qoM6N<$g2nzIMF0Q* literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..36988f9f5182e9312f7ce86ceea4ed19af220a8f GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?44?^O*NA6wxxD$f$FBpbFnat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mg0C=*P5>?-MFvnN&}HPA z5txMYh;6Jiv=F11cz;s3-2LIc(uW>^=vS0bLH&X+YXu8S0MGE1x%{DM!!}(B2+0Zm4(`pdGq9b-a@$Q}N#dh!)o!t-NEQMFzf200000NkvXX Hu0mjfO4}t( literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-flexstart-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..07a26499412406a0c74fa13ec1c9a9a0323cb5f8 GIT binary patch literal 673 zcmV;S0$%-zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mf+NT#`XD}n6NnQCkK%)F zf^5JDY;s-`N@|m~5TlrQe?mC^`=MXy%K?afMURR|UGQZsU}gyb>cV;c2rYNYIKjJV zHx;G)LdInj%K8-k0|YCkyww-Vv{hHM;l+!W#U0tn0P6(Nym&_^GrCs2PvR*B1!=4ND6W_|gLnx8p z%)OlRxi1^im?P-;!v}N7h<8}at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?HCK}W4Z%%x%so0Z?Gn; z%Vkq4H~~}RkFSPr#jvw4#q|K|+E?0vTp$tv0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NW=mbDvkSn1wv^n)^9G z+O@bExCID600Iy&e?WSz@A>g4#^+=A=GtH#SGb$i{Uac<@O|g|pCDM=rU2>;Zo%*X aFq{i(2VLB6i1&m50000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7UD(-F2oba zkvxJYv6h0!f*~m}mc_iJbTZASzfGGCAS{OXtW5j!JRTe)23G9Iz6b#oK`Fn>Jal}+ zC9N@qrEYu&cKI6WRSka95P;~e4^RY-8M<);q{22(CzJ`9*2FC#IA-X$GZ2_>nPz?F z8~fm~*2ygp17bi7h=HXVpr`5L{Me^HG3n=(#a_qM1N!|2uDZ|kGn#d|ZVoesU+Kno zpiC-wv;hXL$*gXRVxl0Kq2nu};?M|c*kY-ZTj1P);G8!_LTT4x$w12h0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#A^o=wSN+K9q6gnS_h6!(c1j7uGuosG=FdXz_KEIRD#)yGKXrnC4${15)nZ8p! zq8rEYNeisic~1a8$q7a7P7&sacw|{tQ-Bzq*ML&0;x~%5aIQE&I}4Jeq5v^EuK^Tb z*QB*>Y;G6^yG|)Uj81NW7!U(uKn(2Gz{HO{&#yLtHfz^Cg;}i&%>y0chECR?#WtKk zqjC4>TRQIvpp9}*KckTAdO}>529j9aj7-IUYe3kX7go)7SJ#_Wz5oCK07*qoM6N<$ Eg3M|o=>Px# literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b2472b9ae7e4efe66b6e17d0ffc1609b2342c525 GIT binary patch literal 671 zcmV;Q0$}}#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?C7Y3rnyhtpGg0RXjr?RG=kM z0$uo*FfI$ig&~21kT_p5FqzHUeJt7R0Lo&!4RYG5IbcrORUE*RUgK&g2o z2$wf>(NovH1KxcPaNJB%z&jIH_zxH2;{A2PFPJ-}Ha{a=k&Pm^HF6-*UndwSTpOZI zP?wr~3z7ahJq2n&4X6P%Fi``Zticw#oT0p>E8ld}qd)qV$paB2?002ovPDHLk FV1n!xB2WMT literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..613e81de3f2140afb594fc234062984ed77ae425 GIT binary patch literal 668 zcmV;N0%QG&P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~+t+n>*T#GSg zn5Jo@9mMhqA;=8@`b`iK=OoNeWM#h#X<0NW}8=7GxKo$c`VydV|egKfKfc0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3K~#7F?N-4JgD?zqD+XbNj?_*7ouJ7CEfbWH7=cZ~ zSt3#t;YdcH@bF0oR?L}$D6)wRSAlabFzICE@3~WDn1M!0c<;LqLXWUrmnLw){*6?C zR=4>F@bD8wen}C=1Nat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?zzM_&lnM0F zpixF)1m+OKwIveNv?Me!ka)kOaC6CNPfD5|fN2X(I3_jlW4_nvpkdfR*Yv@;OkHG| zC(FUB6$2tj=hq`DsH@ZNfD?|Ea+3YqB#I$GhyH2e!L+!APX7ypaPt?@Hl5#u8YFAg z%R1!3goRFTfRtGOb~ z03>$uCi7)}^Yb1RF-`<9VWHFRKst-$olYx=57!AYT2}=UTU`#P;=eV(G|m&_vWY(> SH?!XW0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ND8RtqHWGB2S3*La~7Cb3b1S|cux+fKxjgz zN@c`I(luSsp}s!r1pGViOq00LMC3Bz?B^V!MMHd60A3)F+mN5GDa=WBKgg z0K=8bj4i5Djo3jeL4TkA1qz@53ZMY<1R&rhxA)*K#tv zGFR2c@>v1W4aLT|rv|mWojHfDg=DC&ly1d;3!s`@FUv`VV;=aa-v9sr07*qoM6N<$ Eg0r9~-~a#s literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5f8331540a0142934a56fed08fa6e92fd3c4d987 GIT binary patch literal 664 zcmV;J0%!e+P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Mln&wug1S#Tfp&u0391vc`>5au zoy7FM7ziaV7$^$;gZQ79`&^>opGdJ6^nGu6(2w!G&Ve?D3OGtH@SRFyOl7T2=Fo_F zn`POP7O<8VJb_^tPB4v^gpp$Y=(?^V0WrLw01(RA-ts&*JlN+Lc2kmo7@qVGr2Hs~ zqILn#Pe{gUp56i#paN8Y3fQLr6pj~LRJW^(dHyIRi{Sat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(WSMS9zt|Z0|ZLn@}j1k?6PrR;}jl3bWQ`k zYoI1$hTJHQ;2}h(e}NiM18P7Gtkytlw}i`lNQ~kJerD^O^MG`&N_zMO=#0#7rq6am zwStEbo%04BWTdC_fj(Wg3_eZ`B%!(&Iu-w|0cCNX9JPO=oat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?F;= zn;_J3a(Nih9RrNjS$Ci;cq2u!cM$_)MZm4RZ~_NDI;#O9#I2TbT1P}?n7F_8EuH-v z5Z7i3_mp<2UL3%Mhfe#fpa1{>07*qo IM6N<$g4*yTl>h($ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ef1a55492d9a399907595c1f7297e5b92723826d GIT binary patch literal 667 zcmV;M0%ZM(P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?gS78G50JU@x-uyL0wAP}RI_CRhg zT%hU`PMks}Sf_u18c+jjKn+aRz{_5^gB|)rA9HtUArq{V&I1jPE02l`RPF@#w+1r7 zI`0Z_2dfjp8jfrFzTM_Da3G1*eb7_!Yz-)*^9H^dYTqtPqQ3wD002ovPDHLkV1g@a B9ispM literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceAround-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..73329c57e181beb8e0405886b54b30617841df02 GIT binary patch literal 658 zcmV;D0&V??P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?I zxxomzx?;G9UDNH{7fIQQid|#5wID8@uM@T)m}hWA-yjc;+Y}lQ$=6BWK$RrEab4mi zEUKl-QXLb=7G-i sV)O2rpDyml8j@di3GIp(Ye1Qt2LcyvrRL_l-T(jq07*qoM6N<$fat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?d8RX_3o8t(u%%H4c=H8o75|~4G zisq*+<7A~9^tYir{zfB*y_0D)!&w&UPG+2b`3oi8MloBI@ufn}VshMD7( wY8d)1Dz9fbW#wNWHJ2<<3Pw3@O#oD92R(73n20Uj5&!@I07*qoM6N<$fi_@% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca00447b99b7db964f7994449160ce574af2924 GIT binary patch literal 676 zcmV;V0$crwP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7=*BDqG-}z0{fG;`_^n(0p+KNHpYHmj6cG_sDN?jZ2KG>Vay)eq=tk= z5dbD+AJ1hf&43T00}BhCmh*f9bFL(dU+K<38B=2%tuug9?(xo0p${^_tz%XwldKu1 zeZyoKcm(nU*8Y=EFM119fC^9nD&S89M0sjk;%C_jofyQ>)rK|xZ+6-G1#B-xVI1FupnYyQ`*`M2wV526B;!MOmhxkG%nX^49O0000< KMNUMnLSTY=L?b%@ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d13f02943da24991897abf504f4a9083088ac2af GIT binary patch literal 673 zcmV;S0$%-zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?6 ziqd;uVVK0U(hBSm*ECJ5m=NX98~T7ThIdbh^Ei%f zVeaLGi7L?dy_<(gOpC-^Em|gjhn@m8pa#@{8u$+bXh!us>;&?OA6b^w0gzCzuc?$%Oat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xlv18boLmq>j$`MXUbrrlD>g( zls%EuiA-|41PBF~cUBEavXtL-wQZZ2H_@*69}Os@^8le&Q3Wca%eepm002ovPDHLk FV1hs1CV~I} literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8b79bf4f7855bc0e9c23ea15961d7d14ec37aeab GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?^gxM&JQck1Y6`Y07}WZCKvmXNdf~ zy)ae=7DvomRqHb)}BJ)<*Oxc$K5e53*>Sl;H2F@!3b zg_VJDt1G7=K^4@nzYrr^9#%i_DM9EI?|5aEcIO3Z)>3ts{WKB)0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?p88%{l5(4L(@!ofs zHZ@;111;K};^<=BdY_jUMrB~NQA4=5NlX!a z1u8%Vr~no49|BNb`#7Bm_a%ubLiGbEug~cyb%M_gF_tMv>@QegSEeC>Pbk+H;j+c` o1D_IwPMP)Z`hhJ`0m|+?0MFMat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Ubu(?JtOt^1|jql8i!iT=NWMl~xhC75}9Hp?2=H WTvJ8(?Y*4<0000Ml#|6 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6b34889258ee493f29e43c7c7d688cf6ef8ec2ed GIT binary patch literal 671 zcmV;Q0$}}#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?MqFEML~+<-6PJ3oM)F#{vtqUS%Tk)W(5 zxB~_8nNqw!#?w&JYBLZK!Zv9rlZ45U<{Z4x1b=H_KSq2UeEYRq=d`3CK*3$(_H@rt z8|cER&)aDziV335o{!ioFau`5448rcFc6<;b(xXhLy;WPnk zxEkhsPAat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?U-}M^0ZUwN=~rtsHNuGi0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5au zoh0cCSO_*G_ovw6JqYpR-OJ07a7QHgC5+=}-JmZaq<^4|AqI}2kAZVAE2a9PC?3QB z;%o35Yi*X|ax;)a>^=-blOj&jbi&ke7Iz3{pe#$}zhhyI9km#>6Q>BUaJ|ges;adA zFLc9L8SsQM20dTJL?O3842S_SAO`-!04iL&JkBXD3f6NK69uauKxKQ2_mqG!rU&na z7!4hr;Mku6UOQ1e@aph0AE245@@V00000NkvXXu0mjf DOv)jx literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..dd2bbf041148f611e850f0862c27fe05fe2564dc GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?U|lkvreVkR) z<&EpSpD>jJqe6i%ws&iivx=Pp6JP>NfC=~w0TJivFsv2f%`9gXRX+fat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mf+NT#`XD}n6Hq4*9>E9Q z1lfQQ*yOzWCqb^R4;j`77ye?iNF8%aYFt}tVxOWVZ2yJ%PZmj;y4IRo4wU>=rf`t$$*002ov JPDHLkV1i}YCiMUS literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..79bc79565294d4768fba056e52589ecf740bf702 GIT binary patch literal 666 zcmV;L0%iS)P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?H;7(2|v(7C{f}IDhNNxN?SShkJZQ~Qoe~*VXZUz5TW=Pjf@JIggyrTgU&LwhYO!c zz`C#%mKs6wl&`b`C0jZ{Se4vSb_bO*?&jk2FnKKPG%?qgjW6I7IB(E zoVOb$s(=?L7r2*$JyG-)r~nn90#v|n2tX5Yjfl{pI)VGm-;+W*4?IARY$=WNIl`L0 zi$)PufS;#Y>;wY|x}eFJ<|M1uD>@bbr2u7g?in*m$~VP8#sB~S07*qoM6N<$g3@>& A761SM literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceBetween-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d61a46a1d0f3b3800aaf6c7e8dbce3d74b33baa1 GIT binary patch literal 656 zcmV;B0&o3^P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?CUfdSSV ztg#f;a+w{7EehVE-rH)Xwp%=%IS(hY9Z>$F=Axa$Q;&DdC|)9%DLA5zOLP`1jMafR zABor1at-C@HD#Flffr$bDwLy67`SPQ7GZt@daHQg qY)CK%$91#gbt^%3#eZo)Se+*uJxpB=K5o1K0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?IQW~yMf(g+rW<~YllEI zmAQJ6ix~&w$U~Jpcdz07*qoM6N<$f^ZQ3O8@`> literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e856fb97cad3d105661b2af3e32f1605d5be138a GIT binary patch literal 705 zcmV;y0zUnTP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0~GObopZGWCNzZ(RjhSD*jG{nq>gZ(%s22 z24f56t~|A6ok5g>Fvn_|1$zrBuRxBy9N2pv2#w4m*4f1*eY!VqL(3i}0wDa?=8!`^E`oZ20l}|*E n);fZZe(@G$x1e?aQ|-C~4S|ZI|1)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?R0-b;t%{m z`vgG*Z_N|Di=;DQlISO$jVi{wr%SWt+xR*5d+HT8DYid!kuKmc)0l>?GmdUkt?mG l^1vtBIpiat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?oD5N4*)n z*nyz~I?xjAKuX|Z3?a+9KS;blHhTaQ=OxSR3@^*aUSat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?k7br-5#!np&}G~J1gc0nLD##HDlrP5HXmw`Ob6)lj_TXa&& zebY1%7<2TKBvBz+Zv%8Qwo=dnw|NV}nA?69qV+cLE3g4Jzy{a=8*pVoXZeh%MGeLr zHT~b8AzE((!!YPM%_!$zILCqK)N9*ThiJVGXsvrXOq{4hqV={7e%OAHb`9r=$VO`= kJn)Hj3H}N;H^A5&Z(LcxkA;F|Bme*a07*qoM6N<$f`RBak^lez literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fed8bf37c54e7018bec6ebf474793c19e4a73fc2 GIT binary patch literal 666 zcmV;L0%iS)P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?15ftq^DGoO=MULoO4em{TTD_Y^gBJz;0;~|Efl~f(Nhy z2hf8TtOc!hiqs9U63<-6q16}Kv;k~t5Na@hd*mCAl5@S$XtNDayh=tlUZKQJ z>a|jvZQw6317^Ssm;p1eWFSavrPYotx0U)ssm(Uv>D|qGnd5rN19Gp_<{7{y9w<%} zJK7*+j(4f6v~#2;qCjz|Na7Ri6!r>=8!!~d3-6Iat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?X}7SS9-(^!kFa}#mW5sX(yMq9 z@mG}Q26_Zre#})Fs=Y<;3K)%BAo%79xprLB%=L?G6sq+y5U+nT zOR1fxj17J1zXF-L=6<51EJW*Xz|hzY2$#o6vxJUq?f#G;4bgfVcooEe7!U(uKn&b9 zKvat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%&H##E!SqBV3qFkMJ3Z(aDxlx=Gd@yC z2unbi071Yp=kyv2SY%@~zT8JNc7O|Rq_!<+6C4TVl8+A*_;Onbh|iR82zePKh_)j{ ziE_620VF=$)&ij5Rx-HI%C%6UoJ&UN#ceI%OHctSKn17(70@KW$cNo56|0qfX}M{6 zbMMK00=kWx)5OVafeQt6g&n*$62rX69p2$q->L0DHpHCWY-SzpK3s_0oNr~4_vO|? fr{cdApy(VoIk%Y>Cp8U}00000NkvXXu0mjf3U4u# literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..26990d3196abea0096c5b45038e8cf5da638e5ad GIT binary patch literal 699 zcmV;s0!00ZP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?s)*Ir(S8C6GCmi6L3rMvLZ+`~7_AL4pf6@cN?8TJVx*@^;f|4; z+kS;rj5gQ+7Z^J>*gua@&&izoej23>Ht-{e0Wly3#DExhZ$P;qvAkxQrFQ5dmvgVU zMQMW#44CDwG|SyREat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?UiVU8R$hZr}#( z0D|41j^F~C-a!NrDlyRN$2$n`<$1nbf^tzxuou*IZ8_ABF<-~1jUfUKOAni-N&3FO zAx$x2j81D^8Dp+lmbIbWDHcy)7={PJ$u%TmYi-Fo7K}r=UIOr?7HE)Q7i|E6aS_7x7JwI1x3l|rgp8cKdJ@9*7Vs~K01+SpM1TnRDgZXxx_F`0GH2wRIgI8N z!d)Yv8r=*&|K>f8adbU6UKPUi763Qv(D;m$j@G#{S$^&b-Q^;Si dxd6fD_yBSk!)4Vu6tw^V002ovPDHLkV1h8TF}?r* literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..582b0377cd8865baf6fedb80925c9faa5e5923af GIT binary patch literal 709 zcmV;$0y_PPP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?wQWsPuT5j9sk&$rZE_}UB rwZ4dKq^{whPrP->U(h*#sB=94x5<<#dDVW400000NkvXXu0mjf#~eN+ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/justifyContent-row-spaceEvenly-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..50cdaf846c51d36bcd4a5bb56299d3485210e6d9 GIT binary patch literal 712 zcmV;(0yq7MP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>9qT<~{@TECm>~P1*xz zG{PB-nUoW0r6A`##NMo_NcGm$dIB_rl?CTvLHPcO6+K|>nJ1~;#;g2$N7 zH$+@v>S{m!z#_#P4S>oYCFH_f-bZM5RJhvDv){10HyYqaQUC=|00mHh&j93u1VmU$ znq}_WN3PVtaZB<>1B{U)q?ttO-M!-^a_at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?S5Qh;}k>rVxLlGGIAn}=@oyyIr&)cxhijqUGhbHW^cD$bO{vQk5N%MygD01n3s;x$G~f9l%t(_Akko-83=!Z~y=R07*qo IM6N<$g63vGat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?j`7xZIH_u0_G5CPk{Nvls9 z?G2G)m>@bLRU^*ITnv{x#)lKI4PqZYNWQlvQQu(0gwKr-VD%w)Em8y8PMNE6J^lz| zLj9R@xX}VIm4>7mj?nkE@@1uY+-L#+fd~)*B0vO)fH^NPAt}7o4wkEmF#q6jqXkg? zcC)_q@3_7lTn}bbGr4gBu*f|qGNjJYx=?ntJCat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?zlS;u~=3Z+(*@eu##7!pG1F8T9U;qYSptykzk!IAK zG?+S*>*=HnRFr73!MAs~*9at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-Kz;~65w-Cyc!UtS0McXjui&5n(LIF71Q`2)Av9ir zdIhZ`#LFQB$OLH2o8GjBQkjiE-X9=9Dj;Ipb1Y_seM}4*Lx8)0X&SMD0f?<{1?dgH z!=~=s0yIY7UGuiAsat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(9>3&eitL^h_;K;=h9mtDn9ATt`F= z++VM72n^CX6w5hSVKQuJSA-*@ByfsQ^zNDJ{Z$omf|5`AXmj&q=72E{Cv+Wr;uT@q0}BFa-3CmGr(= zzwP~f1hod5Cf0E@yAvpSpGSDOneL70k8?wSl`d5V2e^w+k6!yr_GQdwGliK6QU*sc zx)JE59W#1~7T>;>9+O;Rba&M7T5aOj2oT%;CN=*#79+DVZs7no4NQhtaD^2gxrUcd evZE6yQQ{4%U40Fqy{ex80000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?A*Fl z1Kfe#0VN;-61Px-&-~_%vPe#ZC3X}Jk@u5Evs$k_Z)avl5IOE0@ApO&MH6jERaHM? z`sBEGJQAXm+I3y`$?G5p9`iiEkN|NLBDlU7S-aVfg_e zM|h3-p-6y808)NnKMcdE@B5V35cEm{q$SX>tgh>Z4Oz%cNwyad$FYXn!H)ADZhwXg z&2QTZK(K^8(x1(Hc!nwaaU8A7U^NHOe4%;!7t?&#!uCeYlg&(cAPW$jZy2&6;9=^Y%6W`BI9_9ygmSslY4f;%u|APA}b~wHOZ-k5lR&GbN00000NkvXXu0mjf D1(se8 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/letterSpacing-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..87da311131730d18d691fdd311ad7ffe4e342308 GIT binary patch literal 845 zcmV-T1G4;yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5O2_A zgl^z&kZhn0>VpmVR*#UgzkNg{v_RcLa_Z(#KR_ZO5#|#~(IT4h-{EM*_x)E0uWj2^ zQ4}Rjfc1LqEfx#*Q|5WT;zoD< zl2EPFVAY6p_yIXk^=F={s)`}@Gz9_rXg)C_5f2%t6z%D^3Gj*G)Pq{8>-PoN=Nb@f zYucKP3Fx~I9PsgE$OiuhPJ=*C;8aO6fK3sGJmJA2zcW}amkGW1gso{Y8WF(BA_%?# zr=MO+X_~Tgz8!AUG=dCZL;xS%D0wt6Kkx*yj|R48HGrHykRep@Ii~jWlkDmQX3Tg4 Xq34kj_A67u00000NkvXXu0mjfhat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=2M)t9hA*`OQX4Pb+?LHhtw z#Y_8$fCtzh*`V1Vn=~Wzg_fpG%-JQ8DpDyn@KDvCWczYC$LBly6u@!rupgR-jl_TQ z;vcNZ;W&2~Y?-VFDELCl{q7}ZYzYhO4`BgO%d5>DEcwMP@J1BB3`}N_{05fTIiSK1 zIi&VZS&V5Ec+7{ez|Mh!PxrIs9K4LQypy-Ez%~VfcAny?m+7Wti4iO?cVMy=)DNh| zwN91^^#ShJ0*077P?Vt_y&|o3J3rDR^NiDARtLs1Kqp_&EOqDOgLhR5`rRv&ns5OV zI-j&d9?)U|Jxv>JKDH_f5n5vA0K8CbwXyP5(E&me2il*3{oNOowWu+~Z=_>Lw9QNg zEx&5uKvjB~Ope-=-!);CkMZXYfQpYQz0dyqsL5+DrG5#?uHiTp++VT7@dcPsVlZL} ReRKc-002ovPDHLkV1gfsW^e!i literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/letterSpacing-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5553899df40faa06ace122d6b523efabeb76e4eb GIT binary patch literal 862 zcmV-k1EKthP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?m`jS@@;F2SiFqyp#wA0Wdm zaLF)34oL^l0d(LFLI=164jFI=@azoVYV~V`IqeK0!m800Guy=^<_LDx&QzG07*qoM6N<$f|Qwp+yDRo literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-darkgray-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/letterSpacing-darkgray-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..a5efdb57282417f2a4fe1cbd11ae3d427f452907 GIT binary patch literal 769 zcmV+c1OEJpP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?gLH#zP;XEkK;o_4fNsDH z-N1R{0VHPwHc3Xv0Q~89m66gasq9nx5XC>~xWicT$7gebC~)sYKL?7USm+<=y6)SW z4-~j}A`((n)n**W1J}rp#+VZc5Ff&6n$%h+N%BTQ!~&LOsiP=5a^Uubgop&N{YYDg z_(1GXtFkP&BtRqp_BWhiy+LTMAtWaO(k)Pkp>5kE2iJ(21b7QTt5$g14fcL_HoQk< z{ER&D7J!9cImdB4tYi2LHD}2-c=dri&ok`#0U}QJ@SRgzF;6}{At4XaG|jPa#(~@B z+8iWJj(7>c!e91Z>U^s^c8(@ToX>#$_7&{cmn^npd>9prAxE4AtgUyR=lw6!G+*Gv zJN>l)&~V%B``%oefWMsqiJf?+z^xGeiUWa9ZZCt8Wt?g100000NkvXXu0mjfOLbgv literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/letterSpacing-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..43c1a510bff6678937da773e5f654203ad68ef88 GIT binary patch literal 840 zcmV-O1GoH%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?e(= zH=utc@PRkr2K5Gd1P(x;@3liijBR(Z#t(VPI>WGW-_E|7MP$Ie!)cw>YISIuX6kv~ zEJ>21TmfMiPOGXqIF55n({#p|D>ueKz>}VUX6De$yFNZ-Syo67T#|w3j_*rPTtdL7 znqkWmGS?@tTrPc~yRZC%&9PWTmLf-V|~C9DZxr=RI}T{rH83$+WegcSkya``H`J$m`Rjq5RR zSRaE`Bf>=zs9T(>9-5#I1jn$(<3$VLodOrWiOs$XmW92R&t z=Umg)Y)pVV(_L=y=dqk8$*#ydf=5+|0c=F*^Jg>~6+caYMq-$fWKG3rL;yEmq^)=N z+t*T_=ga`BgFRs`|3yHwzT39@2exWo4Cb0?05$(8hEVZ2rt^nSvYQhaFyI5VC71at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;}34ZlD{$3T^-! zzy@q0Be;RSh9e>>v4{O(=$E`)X&ZRGUK@bG)S2}=(lounBYgkUH|GdUof(v{m{trI zd0g`O3I$_|&~(}dC>dkmNY$bpl&B0y`Zv^>$|=LX4HRfIkVq`3Oxk-W&>ApQ#Z}i< zwvA>>{2Sm04Z{je>RU=Gk}at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?B1974VFS;2AcgZ+(2>v&RHnQh{~iJ50nS0vv6i9sh|bFM#EC2qWuhU$nW# zZX0od-;Z?tQF$YpP)NW!*<^Dfr!68Nnf(D_{KgzHs8#eUq8w2E}){~7mhAk8A6^VJpcdz07*qoM6N<$f*f*L AhX4Qo literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-green-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/letterSpacing-green-16x16@2x-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f2280ea4fe0206480fff08af69295172d90da01d GIT binary patch literal 800 zcmV+*1K<3KP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?SY~X=+5w;p>=O4eRdwAl13W(+szFNH6jQA3scnPrK z2V+8p9+~M${Pbj*P2ho-fVNc&Yl%%68IxOIv&!IsUkVJTQohyeU0K`9`b<2B2hIYb z)m17+QXrxKg4S|N#;YuaBhCVd%*@(RYpQNcN1thEnVi$$)(46#iRJ9eL(P5!fG!2n z6V6?FLIek54f}?Pd@d8Iz(xNYm1!WyK%4|f{AY6H`a9n)IwH)bC?C4y;2PMS{Zv%s zy&;w{Vyw4wM9jcthYRRhFY&hGdohZ0YmYYS0lzIkwqDrQySaTXf12@rT~=ZmR(yfL eeat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2p3w+sfhWRA+JO>ZBo2^{7w1_H9`LV#RyS2> zj7q>0{sIgoY@sat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?N^0`!ew z;4Vys24G*LF9s#u>ak}AI@ZB~(Gut)5%yVf>EcO!>gJNVaY#UV297Y<_+^oZWC9|7 z(Ta7nq_QVSL=pj(lcni%ac4d-qo37de?x%(8mTd#T-;!;ergt?3D`HunEo-{N`>de z$79e(wv-H!h|j<~uGDb%59=ZN_cR$!J+Wp9Fx5W&Ea2(Ju=CG=AtDh)Kzq3wrhMVf z&Ek9YRS(cl^fAOWBC|?Av*5N>FRBBk04FH;eTzUu5#an@={)m-3l`fCYa*jY2z(b2kq$K=$Tc>!HHT+FYhQfdzvJZ7T_Lat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?^YkHyw};$RUYxiaSU;ARUkn zGA*Qor32Cdw@Aq$C9oxM1tiQcm=(Vg9NPEU7^3O`|N9&>z5C;ke48uvg0Q=ons9>{W_rS08-+wXJg2~k#0fy< z{=Le#;hk=bfRl4T@BS+Li$gBfF|Wz!RLr>rRHb*d$+6W6wNrfH>;j-MFZqcE$0qOt l4Y5p6!V40YLi#ICBo=B|SXPY%f6M>?002ovPDHLkV1n+(Q277= literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e4b794438e2a309aba05bbbfde2deb410df7d9b4 GIT binary patch literal 832 zcmV-G1Hb%at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mo^aTzju zuUi86#I0Q|-JZb%T@$`c7DJv`v00TR?5JYmJBeB=91vV#-o(c>H7&1D{9M0000< KMNUMnLSTZ8at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(T z*z4fzfM+0~1g``N;E&&!-53p;-BBOR?Jt?kuxyx**5q9{fZAa25CS+t9%X?h?bVgc*A9+XmNYqumsB!J5gw?`G8 zU`NEdZQDHw5D7rinthgKCz#KTf_A; zT+a6>kYE8xlH6P0xV4`gL(m*R^X2^QBhhG^@BKmc2rv__LuNuo0U#;AVUCjLNLYWf z$B-vM0+9Hv{9BXHRmbizat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?I^Y|Ga0jLY3gD5M7$kp?XzwD+A7-Ruk7LEn?ar=FWW=+>=_gs1UD~#tO(v81 zVzDUX4#@L-R@e0f(_*Y+LWnmwB~Ka;sJ`rcLYNQbFU<%*{d=T`%+nUt`So=IZaKO(a879fD=wq-_Vo|_Egh59n{>{PjyhyHE*lNY7B7ob{ zj^StR|8-l!H*U`AU{CNx0Tlsk{8QgJ{Yl|_phX(qMFEutaDRIfB|7mrTL1A%_HY6t aMtlP;4W{s+5t0l50000WdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?P;+h+wxoI14cSn@ODA9<(p z&u=;;P91`g8}?TY^rib5__8IxfdO+9$``Y7{|)y5BW3{vD#UcUarSZB?S-KZz0RzzjR{WBQ(Gt|7 zuLl}2^A-CHkwgoSl;>(^=-bgJrKpBy@nwjb0~!1IcDVa`=j*-4#UPBYV`joRBG>}@ z59hm8PRBTnsSrq%0D{Zq%1utbF*}mdJVrop4-9wzxBIK96su1fv(Xq86MAm2fN}In zqcw+O&UQ0FGVzG;b3-AmdG|q2>q8N5at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?u~T2{sxHc<~y?k-XsOjj*4wVBHH&h!icTKsoVAKOo|k~f$k0ufArU~=d2?E58LIEw)S5kx>|IXm^QS7g`C zzLr4+$q{7;8boq?Nk2mmt2^NfB1~;ZDG`muSl@RB65y@U<)&j@d&2Ug5YQV}s8YD$ zGsjMX7%HFvvx`W4+MyCD?W5k75gI2QO)2+ zbM7lfF9PzeR1+kGCsT>i(w1Z;>*dr)n8y0uOj;Kx%#q mPt@Wg-}v^E?BoPmwD<(USb~axkHSF!0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?b4Dw@`_1nN=tdz0(i1LXdcqlESm_sLe#n8-J!=ZI zBuaoBI*~AM?R-Dc(KQhQTGv3h`%c~{wuRWwNm>@#6GTkgecKmdXubTU6~Ak@LhTaI zIJ5w%R-f}af1vrUHTfM?Vj5}9mq;87>907E_y*)ZXIiSzm`?xz002ovPDHLkV1hQb BS2_Ry literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..61f0f25e96da8e7b6dee0296e89c57f57775e8e1 GIT binary patch literal 848 zcmV-W1F!svP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(_I{-@H z#Sk8Z4nhTX2c!dBg5SV!>KG0lK)7Xm!6AGxvZ5HNyNtq2!4n7gq?Q3xiG-%CU@W-C>APJ9(x z?B?1ffL9!;Vdx+0Ax7ewCc=v))-C}GE_L16%2x_I*TW$K5kx@Ga&A3lcacoYq8_(t zFeD-2X$U)rdY|EE6pAmZ7pns>4H=)8@I(-Sy55=dj0aKnjZfMN0lQ;i?Nj}>{MIe5 z8W4=s*Y{}lCa|o1;3_#YvvofCt>~#ZqLZeofCoZE7~5xm!-o%SWmHU0>MKSs0{rJ2 zLvKs0{Y|$e&Q+`it&Rw9jKp6N;EwA0p8w>lDRS>zzyn?y;Qj3wo^awbzW&{nZ07_z aboc-`%6QO$zPz3Q0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@X zxp`7Q-WkBN>nI4B#X7D7JezpG#=*Q)6$FSk;W|Xp#;*Y`AVe%cX-t^Dl3~e%bp|0K z0Ve%yMl_5&whKB(a&@9d5Fiqu1EhBH5X+!OZsPYf&LKc107#hjBD+^*Rw`41g547c za27B-)(M-K^at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?x% z-?}5^7vYuS%a}kk;NRc~X9CRzE=qU05`N$-cvtAa5zYko4@LPKImX{Hg+wg3%Q}wwi#u40xn9Tr|aNUH3(piKtPeQyQ zr@a#b^2WUJw5Y$F{dEuxgpzB!nym?}%>K>YoW|>N_)H;f2su|;mB0elB9zrzIL*yB z{#;H*#<^`at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$`rBbdRR6bkXMxPKqaei9 z^BS=K;j4I6{m%*lZV5s?OxIr!a)SbP#;*5?#bZ7oM5I74KPH_0vNdd)vIztTE#MYm zESEgOgt`5M0I3T!P2Vx_df)tuL9&iu!fZ?H}=O;Oat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_4{^R%HRYUUxvs=be#GBm;S1Hdyu)Q zI6NT`kpwa--MV0vSSRMa5Rfl!a!B*pbbBdkz)qcSXlsthKr24GROY4b^vEAr2Ic+{ zZl`DjAV!3ROe6ih%czF5=6R?Xg9z|t3u(RB{d8L5GnWCkJ6!N7{)zyD`~7XVzx%4C w_kBbFf;6Da`W}Js;!~mi!;$Rb1O^Ov2f$xat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_o3Me5zzA*tj^G50 z;0U+@Y=Fc7rBVBa(jf*6at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z&Phx7Z~A5_`UgzHuins#gqWl z0Z<-mccy`odldLh+6|Q46F@`Ok?k*nd42#a`H0MtEy#>E4O#_$*!#nm+*Ye_L|TYw z+*}qDYVX+0z}kltqHp%Aq;E#%4<92FO#o5;dD3Uue?f~R1&M^4p0PEL8NvEf3OH8g@BwC#LG9O&F6g+=wP3Q z8X;8{ISi#hm?CqlCaCKGEf^!nzoM`2uFaz{ufP_eCe#ohtpo9WF9ma_?EjI2EB}P= c8bG0N05m5qz+MMs+yDRo07*qoM6N<$g29SRbN~PV literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/lowercase-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/lowercase-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..05332e3fe1ed9fc955a428c83932e711208822a7 GIT binary patch literal 1072 zcmV-01kd}4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z)O+*kX$< zUOQ;zj3kNi_f3qq|1x>bunu}@&Dyi$>8hz=0-eDp5FLWKvCun}_dd=~#(tah6yUZz z#q;^V7etgH=UW-;V|bD*nndA+aBa?s#%4(TL!N~)T?)Cjhwz2WONwpDT(hC6t&`&e z0;oDYZ8>s63ych0J;1OtnUD3-k@WwPCnY$V_aCJ#+d0XO-_7=)gsSr`k^dy%-*W;Z zG5&tMXU@+ToGXf$>Mu5JJg(BTwo?7<=tPg4=ner?Lj#WULRd99PI1gIVFHCS3zZNX zEZLM`zLEdNW(0a^L;N(&kU16+#esQ3N(jN??FWkpiLpL`Zh9+=HlRBsnwXfFe~X$Y zLh5uWGfFRhf-B$>(DW-DOt3pUaAMlE40(j=qB9V|N_aw`ycWuMPa1N)Xe5<at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?h+f zcH~bz2!g-|zLZKOv0N^<;vJ|~tL0*`=&x3*=+xVsi%_f8u07AY#kQTemiPv<*=%g% zsn_d0@Z24bM_<3k`8&=LzDX{Z8%(Fuev+qP6Vz-rdtlHH$6)+>I2?SeS2*9pIDbB$ z50gBNM&k#TJA70&f?|4q3BE_l09hd|T^o$_tPKx*D#n+3N5j-sx@55) zPz&PS1|X*sdc``xF~nYC{f#p{>?w~;_~Jj1GN9FJUBlWo6{Da!W=`25$usK$2J=l> zH~@p4G|%!lhzXuIGL^f8smSW`wGLKFs=_;oE|kpbXwTD52V>9p>+;G_=R|> z>MoSi15P=%U`Ne?6eyTRVf#Qa%7_u}oIHfJ3zTOSgfCDn7$thV;}WL$y5>F7B0gk* zhHJ3cfE3(fP(2}n(xf4Zmt0jlzk(;u02UsE4^cZ4Mor(dp7;wXUZNtAj%SlMC(eX7 zicr{o*v@VM!LiK$1Nh<=))REI*^F&7B|`?{A3`f@Co@XH6951J07*qoM6N<$g7s+T AcmMzZ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/lowercase-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/lowercase-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9e5f071b81e57f79ffd067662ece3a026665c04 GIT binary patch literal 1101 zcmV-T1hV^yP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?c zIZR$SUNRm#GsYEwEAY4ioC-oJ2qoM@X26F}%C5v+43Z4Y_|1F|pug3wwBLR@V22%c z*x{u^tX&bSGG-{_6%xcE!6xXaivB+nlXXk|0i51{fD$Kwsy`Z?kVy|0rJ>tq-i4BF zYL$!i0-q2B2{JjNb`R$V@ne&~zY%VXb1~G0P*)~gHNfetZQG=mrDH|f?sqqUF!9V@o3tDQf+cN!RylTQmVd8WBQGK z0oXUtC*$*js^y$P`oTodb|Lb)`KXFAUd zXOt>F{rA$?xtEf+5Td?a0G)XqnQB7N=8BwUY1zGQN;OJf`5E?)@n*ka-M0Z3(>3cR)ESRddxsmglBCb-c8mV+zhYdXMx zVX{NFMpy^-(?7w?Z+XawgRg9iOl%62WZWlqUATV!%Lo3{m(Y7$9%kRVp-_lw! z&LlL%ZRwPT+1;w?`tN~F;Ui(*cfBpo8URDfvY@9r$V=EL=+VJ&at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?aO?=O1nTv= zE|<%Cxm+%$)9FIxK)c8ldZuyEAr*JKU7vfP1MGJkI*%Y-k?D(0EazM(4?>&4 zltbwT$_vmMqMe&Pq_($Suivp`q&>rLwOW+#Fyhr}b)GC09P1j#Tu5br$}oCr8z-cu z{4^akd>Fr$<(1thlJZyOLFn7CjkB>3eFVoe3@SDz*v1%3727%qyr@Jk<#GV2$!!hz>-&t%zTkoI)Fg_E*jBw8Au>Rm$eb>M0P}AxUNIAgkCkEz-tY+6# zuG$aS7vNDQQXas0?_R125p6|i-!*u^j~wSPGn!>{>?tW_J_nRE7Q8;QHyFJqng^lJ zlEFQAQ*cEG>>=erY7$Z@48u<>wG5#*Ip7jsMH(uC%xQAe%6&KGSr|F#pC{SNo`g(0 z4nG$~4wwPhk4!yhgRk3pFrC7Z#^!8bPQ+5FRFe^&F9S&+eHBK}Xb#-*Ovt2UAgK(5 zhZKKf6h>|l?ThCH+`k2`Oq{5H02>bx_BNZ%j9D{$_LDU34UNOWS6esp|3F^&nlSOZ z=E~^5IY4kM<2B@~xWB??f?}Wz^ZuDBaD4azcQ!-*S6lyk00000NkvXXu0mjfJ#*0x literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/lowercase-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/lowercase-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f6a637c06070aabc3f2e0455fdbcafcbe6d10246 GIT binary patch literal 929 zcmV;S177@zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?8nu_?1EN=GX#)eiE^fC?b|>nCO^C~?HWFV z7oNrwD|3=;gk#e%ryCNmL7(aZ^oLln$-#Hn!3*T3Fm0*jcp9A$*XsvHCDSLyuXNoV zyWL~A)#AFP&LXUy=zKud-3hVn6BsU-WCd$DOUP60a6Cq^3JDZ#HiFj2h<(b6?L$=2 zKY>mu3u){?*kRZ^DA&i5TkhWT0@}BrAyXftTOozV!R2i@VAt$?gu-1Q__1!=`9E+& z5*g`5XulI}NAH#Zl8EX0D%vY-=-NTctmn_nfXBlxwszJSFGB{%00000NkvXXu0mjf Dmc*>$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/lowercase-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/lowercase-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6090f29510d802f34aade54e511a395e15849ec4 GIT binary patch literal 1153 zcmV-{1b+L8P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Vi|K~#7F?N(h<;y@7Yo`9y-mmC33uzCXF1RK!R^+|4^ zdjjwT$_aFzl%Enj0qzNwJ;8E>ylhpLFw@%|0%9^Lu*x_29!N3M-}E>AmjG&g5LyYjDXElXCzL*DsUY#0-XMl z55`DH$6Qd=bWT}ZbM?Q}MX_5Gn-b&zNtFo6x|b9LeQtD{)oaV0m9@rFlMVM>{ws*_B3J}C&*}=<23u7`t_X_52(~p@gJ|6x9fV4w| T1k(Gd00000NkvXXu0mjfZw3|V literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/lowercase-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/lowercase-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ab9f25880a486cc8685ca9914f9cef379b038222 GIT binary patch literal 1075 zcmV-31kC%1P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3%&^0M#v@zO|L^JR>B~f&b=FyD z@7+|}1bxjhZBtDDsmS`Opbbpla3XE?N#$*Gg9P+%{=yL*%4@AVS4`g#c;@rjTk;qI zkBC9In!loNKq*+!h4r1(eR`ol%w#4iMKfB_F9`}l`v`QZ7aV6hYWmD)!N&kN5-@@|f8D@Peu8b*6yXxbj}5>af*QGd3UcH6x9DQHVAU@t1=%^J7q+J%4O0j1>Dp8? z6d@FqOCv&}eY683D3AbXzg}wPyjy*gi?H*kte!t)%vTA$bpW8d;)o!rR6c+o8&K2+ z3aDKI3n>A^Ggr1E;yvgi)(Zp^hrYh$0X-lSTeygx&iE)4%=)EnKe9uwBCrk^C@enP zyXC{^fzG`*U_?VIIpocuH!u+%(mjFWs(QMP7naat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%JGH-%*ku+8Z^%{E{;~;ey?)GM%%{%!gzdl9{b#DuPRIu-o6m zR|vLjcWg8BF)>w{UhE($zwyeKD#-8LFE7jwxojA`mMbbZemM6sxt_yYenJGtjf3cN z*xyBJ5Y4()E>vDc26S$k_=wnn3mH8<~P#V@i!viWzrNg>%yLQT$ zCN>PI=SG2Z|NToO&taLcP^FEd~*8I_&; z!&B^#2KPNU#={Xbj2@!d6EuJ^RmNs;H{8IH={MuQ;rtW`-X>_^Av8(o(l4`$`{Y4A zrYo8LHzqGQr+Ws7LAVx4_+}dJapHUPNZ}a-=G0564O<9FNzxVuNExs9^(9*$LIxx@ z=T-KGX?IpkYo^dU3p^8^hGT4c?eND7E!n;^Bq>e(%)WZZxx0^HwbW|9^Ryy7+j5`s zNAS(AwW);G?R$*iSUq7|aMzVTY>Wuo?ZJBttuhx9HDInh^0gy~a2A}}n+@r{6AGsq zmP(F~V~2UUNn?H`c##36V63nNFk8um^l=+`0o_{=@I()<08L%dw_%4n>$PH@eDcJd zz`Yaqb=iae1FemSldu?%LmquK1FR8RmXGYKSfsG4pzpA3`!mzw?cpDO+Vq=Bg2Gz> O0000)E literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/lowercase-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/lowercase-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5c891eb5fe69d00e2d48081d0d49d256c172bde9 GIT binary patch literal 1037 zcmV+o1oHcdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Du>{Zf|&Qo!+fww1%l;qn8oD=JEe;R-rFcro0a6|8ql6RRi|Di$5Q~!W#P<}58Hsx};spk~@ z*X%dz0&CpkD+^#eQ)lEI6(PK?l0u+wYCKr?4d*cT9@C~wO1@H=&j9sPST{OD8jY{7 zOP`=|V~Jn_-W13TSVPK!qqtBAMfHIxi*5+|h7fXohj|s01?3|>m29i!eV6)3oJjXc z{fx-V)d?AP93Ds;WrG=D-eu_78*J6igJ~3|BaDp{a3A4sVi;uz<1G-+D)afgD)&Cl z-0`OEFp+EN>qvt-%YYQN#$p0;|AYukEH7a47MLR8s0%;}uZI*(8MSm>ijcW)$vZLA zWl#POat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2+CUI}BNEu^2ylXsT}fInXX_h~Pl85bVOM;o?KsTacy*38FxMK~z%12}*TT)p<&jKBMVt3By&j(crfxT<7P0nlLuoGQfA*a4_%&?nyotbwVE@GZ6uMW*}$yUvL%HJ?`7A zWg1w8iEXe{Cvnjx150p2;=z*$9Lp@A<3Z}2Wx4aK*0C&Yy=%Sed>PoJPVbcjD5w>8 z8t^fpW8GEEUHopqt_9w>a5A>wSS7(-C=oc3+1ZA{$#?ylI*80TDUciI-&Geqndq7} zYGG>UN+M+NuHFS^QPp_3({{iu8)|( zY+O%DPo|f6XiO;E7U24T`J+bKgar7`%O}$h+`VRJo9-r>oqVfx=iOxGNwRft$M%Ys z&h74mns&=(qJ|7O)XvAobKz1i{W`Vld8b{6WUsU&#t~SsG4*LzX``q-1u87wI^0#4 z41Jz}BzMO9bKaQGSo`x9HaC$YQGj=<>Ow{KJUj#R%Sj>5shw3% zzIL;5CqfmjmQueHHY(cg{2$mCkBBgRFMnH}m4HIqGQXB1iZDCE+YZ`-UGDocbHK~P YKfw_oyEul+RR91007*qoM6N<$g4=Bky8r+H literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/lowercase-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/lowercase-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..12f22ff07c099941c8938d306371e4e8b4bf10f5 GIT binary patch literal 1070 zcmV+}1kwA6P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Sl~!75<+Y1B zbs$+umlyr*uvaeL59JNckqbEkY-7V z$+E#CIZ2y2;D{9&ysK_(v*>%M`NW=ALxMZD-9^5xox<#_fN*(giBXU_;I9Sg5ISP3 z^)(Sb@H%h~_E?^NdDLpZyZMj@k(VXqjQFK{jV7U{orF7AAh|Ho$w%5#NFG8*a>4)yj@@i4$$X>8xY*pZYcG598%_Rqv|^K;8_k73Il`1C)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?99^1m(Z*IDBsf>+#$c|7Br{XCMsUjYLBQsO!#Kay z%-I+c;5l@@iwZm{PYf7x9?%ycl?J*;Kg`mv4P%*##aBM+O{ac-zb$<_8qh9zlHpY` zRU|g{#6nn!z?8g`D8o3&VS9F;mF_Yx+!4l4w-{c;D(ry08CoRZwA_^x%q zLQ8qU7!}~{E7w-rP_W|$gIP#;BygBUi9@7mLl`~OCXg4F6}&7jh!EAq3S@>;+Gn!2yw%gOx*KpxsHw!jBOLGqSWU7?$eVR)e-J<^#h#c zYwMLzb-+?g^1|!Wx!&M}sfkq^OhvWp!L(~}-s z&ubBC;c~67DaGSeNnZPZpf-t$BJ}T}Z_B+BP^c{PYdPSlzJ;BFQqbmg|IBRg@bC}i WeIVQkE>*+;0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_i%|y42H)4p{63_4e(W$+VzBJjKQY5_`xi5Kf9*pa zofl;9ymED5MvTVWt8TmEdlmC+Z!qoUv++F2cscenWw3|^amc$32CUX=gz*^AYCQi# zFnd}D>)3BA@%SQ46`a`zhDC@Xz|6`ttD$nC8LxzvQX9RRD-ri~SSLQ@>VYy?%4*TbB`xLx?ob%8=_nL=6EEG=;i^|>%LnZ{GZ zOKhww%#xB&S2W##PL%3T5yka~l&9+2&-TtYuzr69qqeuchBBtbO89u$CvrLECZzrm zJ>y+}0Tt0v5^lW;Tdkb;K0WPepF6gHgf`v@ec1JdFFbBY79OY@QMwj^u_sQjUU_9M zB^=4d^XMcGW04l-JX;|e=XAP=`ZK=H2@}4}a2;~!O$G!4k2DcT0WL0mpS}S*xeL08 zrs*9Zg;(>9CsFIymr}SJa;ZCe81jz(4@@^ATZHl*-!1QIfH%UmWh7knN7zUQJxu+X cnep-P0#y|Eb7`3>&;S4c07*qoM6N<$fat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?uXm?sNiuTUa(k3l=O`aPNqQ47#q1nF+N~6ty%0 z>|=g|M^R0;f`cSXRrenkru2$W#?(0W5@&<=-1S+70x`43CDS+cU3g(Cq$|9-gX8ng zY|kWJI)Xnlom8w*E00mRtYq!z4CIX?Pt}TJN0+OPLjEAL&N8tv6h=_z+XHqZ9RmlC@yMju7@y6D9Ze{}CVg@h zSiSN1yn&z4L2EBX6*T4Zz{#Fw1!jDYQED*jo!WfXPtUuyyC_{gwg{sFbSltV&9n*l zm9UZX;s9A1D!@AhxI`Xtu-J>p&iIxBfM4n&0bKd$)3+26j{pDw07*qoM6N<$ Eg6qeLPXGV_ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9153026d5ba0057bcb02f6c785d0389cb0204e91 GIT binary patch literal 614 zcmV-s0-61ZP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{??fx}Eo(!Km7+KR^Dt zY((@pp~18MA`v+S)OK>6k9#8^GfSdvh2wfgqQs#F7 zfvZ4aH<)!dZgB*$e2}QCS0e2H5U!Y}UCjbBd07*qoM6N<$f?NOw AwEzGB literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cf43b83ca0ec50ff3da4b8feeafcfd66e7eb865e GIT binary patch literal 601 zcmV-f0;c_mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ePoI~9ybp?(l7!F%0g=jF>BSI20wKm&6uW`Qh5X>yNB1>e3xWmdopWat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?^y=u^9&YRV=IkEz?*pl zS`%R1iFClSpJo&CUqL7~JCn)GWC4-PT=L1=*Mm_VlJ4F?WQsK$+jJ}ME5Nw77x?ZK z{!TL|K5+XI&*F_l+!Xk(j0895A;Dx^1uTG>oAG~{V+oFA-vdfO39wVpz`8uPq+Hkq x1hNACbs<25wts-YRiHZ7;afwtL~lZo?0)7wD;{z`n?V2o002ovPDHLkV1lh23<3ZE literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b799fa785d2149a2fa6b1d24504916ba56fc34a GIT binary patch literal 614 zcmV-s0-61ZP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?NOT3hxG@9UQy;4mlyc7V-$HQv+g1u(r2FaQPsRe^fz@ZXx0 z^#TDv8PLsdKMt?}?*f1_kaJ#jT7`~;Z$hH!KBgfwSx>yE`~Uy|07*qoM6N<$f(0=K A82|tP literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a68e279d42e59ad2065f583e35b2f4efd24823ce GIT binary patch literal 603 zcmV-h0;K(kP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?YEF*LS zM}mCj;hP^rxCiq15SAh=6F_9J)Ej7K4Fr$xTKfT!4YA?aO?P#@CkVCHcWdqIuX!hA zPAOR_<%dqx6nJtwNFH8mf!(MMM1r{O&G_2p48rhpKn17(b_)J}<d27&Fs=OjTC pSV5pV;9oxZV}jg?{s~2fTL5SbFl^qw@Ztaf002ovPDHLkV1mJO2k-y@ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..562457ca2b0b791c27760e8ba12c437f725d3907 GIT binary patch literal 615 zcmV-t0+{`YP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!wu8tAx#8HR`}MpP2<>IN zw-|@i-hL+J0q6R#yPi;pn}Qhoh2+^f#S9=&6?i4U{EWZL>_Mo$2Xp~lfSrOVeST?4 zHF*~h$O_ouOM=N@M-ZqAgzi43-w639dJ~FN_XMHJFKd9VB5(iz002ovPDHLkV1inn B5Q_i+ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..af2daf942aa8913683d88cfdb5f476fbfab15276 GIT binary patch literal 615 zcmV-t0+{`YP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;F&hy?K&oAG~}YY>X>0TrMExG6AvVhm@N zR1X5X2QHHdQh{kvT|uBaaNk>(ejQ{@^d=N3?g#52GY3{WC&~Z-002ovPDHLkV1g)Z B1Qh@P literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cc1a0a823c82ef826e4e3e539aedbb600ec6242b GIT binary patch literal 609 zcmV-n0-pVeP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZGD3%_x=v^41PvQ>1iDVe z5RAYC1Y6?BPac;@=zS6-hbXqJI0_(AStwnY{yBq?o}p;(1|lo`z_Ew!?0z>8+CIPX zgs)BG#*!g4NS{aep%B#t7Ch|)clRa1VpIh@fd967d?|ATq53_b1e5^V1*3iO;F20Z vU@P!G2;d2}AW#*s{_kw)AXlO{p-6Qzf~zo)bD08!00000NkvXXu0mjf;s*yZ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..607bf4cfcb1a57b4d7b74ba41028fd3975f6dde6 GIT binary patch literal 618 zcmV-w0+s!VP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?D+@LbO8<9D3+}-R~rTob#oW za__Hh@4GSPX{}wn_YWBabwRClISQ^?Yv(P&VNeA$fUZY9zLnVtVEPb%707*qoM6N<$ Ef_#Jw+5i9m literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..462f57ee3173da1a1ecc908e3f54c3840c52942d GIT binary patch literal 612 zcmV-q0-ODbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?+tRe`~BA43mW6TJyVn)?9zhcHq1|IN(+0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?AzuSNoN(B)6G7}M0J4&Zx(_l$1%ZdR0UFi^qTAOvCIL4;&VU=C;_$$dVj*o zkm^9-<^XVC3DEnR2MAOJF15A(X(4-}JE2H%1LR>c&*bt_x&QzG07*qoM6N<$f(Yjh A`2YX_ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/padding-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/padding-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..72d282d3e6e23212afa83477c9c9277de7f7ee94 GIT binary patch literal 614 zcmV-s0-61ZP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?uxSj)Yt`PLphK<*koK}{IJ=Bp!gn;00|&dfW^u`EU5qj(t)Z?A-riY qfw2bx<$w#rWXA;YCG;m0qBtw$W+|pNNx-fE0000k}@P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?o74&0Empa*1;g4;6%&Z0-_Hg!6cat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?rfG`jR;CJc(j^Jj_U}IsWje?acxS1ok zfX1kuKOqN!H1C5X%|VXiash~lC^At+*L`XC$*%k-VnK=)Lo>ru0u^Z;m!Ar3SAyO$ zsF>n9#^$?nb#LHK@I_gH@R$G-P`(1JIJ^Ar_HSZmfr73AiBu3-91$ya(}76gJ=0ws i9>U`vi9QF2qB{U8=NBj;Oat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?fvqc|cobXZwPJgp`)>w=n)ZjFE zuoIqE&MK5_@*uDk_?;3^0_-bTEc|xcugoB@73l6ZuqKrg93VnC^z?@t{@MN?Dc%P} aidzB5t{bf*V2u#~0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?59l_0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Pa5gJN-ZH6|e4O*dBai~UU z0__B!%F2Vnm;VDPP`u;NlL!C+DpQih#+bo-zwmFD-At*C$7HQtsZc`#A%y8Jc$)81 zg2h_N;us))opagBX{`f2B$y+rz#otR5)j=2w)5!HY0rwifCNMp;LXRE05QRt00b^Q k{po~%;rxzN?*jnU9iK-fBE0nnRsaA107*qoM6N<$g2`3|dH?_b literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingBottom-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingBottom-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9b84b5d84a21a2a6827851475da98e70ee696a4a GIT binary patch literal 586 zcmV-Q0=4~#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?P)5!|d9n!s~|R%kOvXaiI5 zSLVkN;h*<`LPWTi!w(_=0GLck7CYy*5W*3My0XM8rPx|~(x8O|VsUO1PfQLtY$X|! ze$4#Zxi}xF9k3wkz#k9*0i>tkil5HAy~dM(v;%vmKnmyxK%ltOJ3IWd=Q}d}9sro` Y2D*bErW9Vk@&Et;07*qoM6N<$f)bDZ%K!iX literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingBottom-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingBottom-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..646e6ab9fcbd254a14360886f5c7c24e9649210e GIT binary patch literal 601 zcmV-f0;c_mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)zz&pv5@26J7gqJ}_DMyY1q8AJc3ZfhGuRy> ngwae-b@&#B|48;ZAd=k=?q(n)O-ny100000NkvXXu0mjf_BaR{ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingBottom-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingBottom-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..154efba6d4d337493f70d04fd2f8cfcc8f11cb14 GIT binary patch literal 601 zcmV-f0;c_mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?vgD?;U;CCnkkS0pWB*`e5AsfI3tiUL+ z2$YD52{;akivJUZoA(uVbCRE|^BEu_qQJyc{OR;3iX4h~r=-ycY4wr<7r6p_Tdi$N zPRjc7El*tZfKM_lcEDzE3#himaEK5X12BN^6$tui2F%^Qr-6g(24ukh@Bj;FgDL}& n!)m6Vbogz{eat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)JM9kB>Y zumWQOp45C6kzD3MLJol)mV5vrBFaojHjk_6%z?=+E6$Ll95Ri7Dj}&kLM-T}--t@=`|Lp#c eWPb;UvO56+*&T1-JvW2^0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Xi@h70000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ggh{!Xe*_=t63zp6<hQaHWoFDLx7 g<3Hm49U$^<1+F0;+_fnULI3~&07*qoM6N<$g6iu0LjV8( literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingBottom-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingBottom-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e261a74f657f78add78b180e2cb9a21a3f927b1d GIT binary patch literal 596 zcmV-a0;~OrP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?rfG`jR;1_WKM{pC}#76AhKsT@!8#mES z9Ki{U5v=@4a)_jPA0(tWxFcLH01*)drX<1hpbNdBGsom5WKj{CtW+aBMG!E_8%y#- zdKTy{hD>^Fd8Hn2ZtAs$y}%pM4g7%xumI^RSj|e#Zhx~tKsE<}+L2&2F)fG$ZZqA{ i;h$aqk>GQHD7YQ|lplQ~KD46%0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?81crd%`9ex4f3k%%v|?_yb(AW#9%3fB{&$pmi&rt9_Gej|K*&3`BzO!2@kC_<_h^ mHPd|+eud>f5_}F21vdcQK^wx%IHG_60000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?si3Bea3t zex5STOMx%vgNqMd@F4yGL_}1W(KLJ8wK7anO{B$14aUt2GF4D9Lt^or#ThVL4Ha*X z7;ZMtvz3KP~HNpQq6VRV;mHeJ5creB}_C(KtF;=A$ZeYPWbl)Z~sW~ ccYvt44N?>syLPKpq5uE@07*qoM6N<$f@#3}SO5S3 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingBottom-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingBottom-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6d4f28cdc65b35628fdf141521f08776e010c1c7 GIT binary patch literal 552 zcmV+@0@wYCP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZNr8@vcRE}8s-~;IZ0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&zn9yx?D!a$)u<;3QU=vc{Wpe-+uyncas}?&86zD1tNCc7I tlQCd2ITYwBP$jL6EiQyjNC65EG6VM$9&sezVQl~a002ovPDHLkV1n>e1la%p literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..565bf4ce45b657c7679659c5ee06e08e3511fc97 GIT binary patch literal 601 zcmV-f0;c_mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}~*KHb^Oz8n}qoeJ|XM1z5oC0^Z7Dw$e9*(3eu;&XI}H z<(x;HM0KERB(HoJJp?2N)&$@S!`9|HY$60)gck6uIY4GcJou_72&fMHS_wF$s=z-4 nBnR041D638;v%#F3ovE@3{@eBn<|l500000NkvXXu0mjfs22b< literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..348e84f90d656bcf20a156fa0061cc25918ee6b7 GIT binary patch literal 606 zcmV-k0-^nhP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?} zYy~wYYNtjAL=pajgg}POV;Cj?A!~$<9@ho$y>K%Wpup_{o+vtMedsPXr{6|I1@(@R zdL<4btAOreM{>)57Cels0ycpq`>561Y1p^~7qAH_@US@m)UaLd`l^+g1p=!2aE sHQGLb09ggHZ(;TVC&DJA00jsc0G@{>Fh>uA=Kufz07*qoM6N<$f}KqO>i_@% literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2cef86c2c8851798dca137ee231feb0883baea23 GIT binary patch literal 610 zcmV-o0-gPdP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?JdQEmYppN2`cd9F z_mP-VN^fk$vEOKmmmO0JSkJYd%407*qoM6N<$f;?{rbpQYW literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c62029774ef05dcfbc1e835061fc089d8042d4e7 GIT binary patch literal 597 zcmV-b0;>IqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?J1LO4ooizOkjosmjn9p jMVAE?VG&XQ1rTxof>tPgJKN#(00000NkvXXu0mjfdZ+uX literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..89e95939e26a451bbf57358292ffaab94b1708dc GIT binary patch literal 612 zcmV-q0-ODbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3be4V*mzNJ;2UVTs@9wNvU-} z7%BO{`zD^AH_T+4KuS%adA8S@76zsX{2HiOzueHv|FQ`%;3Z^$ZS4Wo>j|Y_wadG} yz&HW9Of={Pa)p6u0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZS98>G zlp`Un7pUHQdtfG11?-P1lRP-3m>L9B1tLLguY=jpWp6em2-JiUuq_{e;TPX8Ds=)JTO*$GZh?-CWBtVD`pE4^M+`nVm00000NkvXXu0mjf0(%D# literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5f6afef14fb6de77a520df13cf0a04865cd8d20b GIT binary patch literal 602 zcmV-g0;Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0w{ox9nkbBqQyPv;{X5v07*qoM6N<$f`e}ZrvLx| literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..836d8c5083d820f5c9f2fb22cc2332fcb567b561 GIT binary patch literal 613 zcmV-r0-F7aP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?BFWOBVwH5OBGGhvsq4`Bh5!^40b7 z#+bjgcJSW+=pZTwYOTXsbD_2NTm&9Q<$yGh7-KZO{IYBuDZmgyz`gbWGx2d-U$yK4 zQlN5xi@$doh`Vh%_2>U^Y00000NkvXXu0mjf|1$_a literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ed4cb2471f1af7112b08755eddfa138507e8f811 GIT binary patch literal 608 zcmV-m0-ybfP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?{Aq5Co;G>16z)5Vq_rS$a00mqw;N?mFYWY))l^w%M zN-ucER2e-60S?%N6mYLOUat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?u3ss00000NkvXXu0mjf;S~h| literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingHorizontal-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e8e3bcb2fa5a847230460bd8d3b7588a8d1e24cc GIT binary patch literal 612 zcmV-q0-ODbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?I|y8j%Ym36PM^QX)Zy4{0vxaiDd1Rrz-VlQ)K_iKqlN>Q y1DW8lkf7-VPdIQn@UEn^rNoA?2q}O92at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?466_#u z^r|rnfgsF-C5J4@W5@>}^bs*_aZD8C)8&y64&JvGFj#Lr8&ty#vajat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z@aoqf+xI~KMqG8hmZmkAmjxYxTcA{uAMdj0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%iK~#7F?Ulg^gfI|A|F~PgmSAUFgBL+hdQtIY3EG(@ z*nq|uk7{s06yZOZ$sq%I48sHat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?wlm_ST+l6`T>Ef-h-2r1y4i%Dp}fX>hW4Rkj!YKrA*&c>KM#%OO!f@t;LA9#s& z0&AstViN68pqfB#0NJ4_E#~mDP{2b-1OLha;S|}2r#e7^b^=SSfrL~txZx}Okk9}P b5Ymzh9wQyaHeqKM00000NkvXXu0mjfGP?Xn literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingLeft-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingLeft-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f45cb29404e044ebcd06fb0c47f3ff2ec3f0e15c GIT binary patch literal 594 zcmV-Y0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?E*nDgO8yA1wI$>MA2y$C^tjl)wqeQ z0(!_S$qnHqcpF&-OaepctHalIc-aJZun8&fvpE2?FkNo@s?|IT1PCiI#uo`%^ka_4 ga3P@p1qgYO39%R>SR?J>O#lD@07*qoM6N<$f+{ThcK`qY literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingLeft-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingLeft-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..56dd1e7e99d9f954148f64f405e84759bae6428d GIT binary patch literal 608 zcmV-m0-ybfP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|f#-8uJ? zm{LklEX3qMYi;`0yw@*X;9^V;Xamiq6gR5(<>g_3Lr4L~+5^H{!vFfJbr-;Z$pLx% u_NRdgyu*OWft>R!X~v3h2q}O92>AeS3n+C?zVgEW0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?me-Ae%x9Pkx> fNGL!7LQ--72Rat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z z1=Kv~r+pkj5xftG!io2A$SDy36}tn?nd)jBzSUQ;RF57OnMQ zt)1y6q6(yxhNI+6&bi$MZzHMzC*avRr)u%Nc^MLbO9+8~^?|}#hBat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?VOun4vGijRq!&V4uk?>8C>bM4%gx3VStyA0^gbg%B0~>p6U?>j2)2tq<{)a ijl1weLIDa8@+1o=*(KQcK645H0000IqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?29VomeZyWFj4Wou7bW)q=K z3p3y$stJgAeIf2ic7u;mO~4EIB`b|NI^4s{LIE!!4g4zyghk5UJk>K4=yCw4ZUh$T jY48?)NN9it2>Fr?Z3Zay1B2|+00000NkvXXu0mjf&iedL literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingLeft-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingLeft-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..580e8c8a5eaaa12f04603cc19be9427045eada8c GIT binary patch literal 601 zcmV-f0;c_mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?qN?3La+Zw!h)|24L7A#D$ z1RKyXL680of+D;R5&{{Rk0F@^AY_5$s~QF_Ai~X1fC9G*ye+}WPybMqe(6?1+Ls{B zYpHM$TLl#9M)JU?p9BwMsz68(rlJv9+MJu0g8?2w3OuV1csf7a)>G}TM+*a{3Pgf< nCqXv|GMt4U5(-d&kSiGh5j-L?^kN?f00000NkvXXu0mjfYJK}s literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingLeft-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingLeft-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d356c32411f60d7041780a86cf2ed5e48b66a534 GIT binary patch literal 589 zcmV-T0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?I=vRD&9})^s bfRLJ82+bb@xS$Z%00000NkvXXu0mjfZch5s literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingLeft-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingLeft-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c7f8abee90e88d684f40cf4a6e656b3a601a7f0d GIT binary patch literal 559 zcmV+~0?_@5P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?A) zAQu(=zA{7{5!(r$zmsEgP&ph{H6EXk;5WVXcvPTOTDp&vj002ovPDHLkV1jz`?|T3M literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingRight-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingRight-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c79281d94b18fa4d2e83d0dfbbaf106beeae6d35 GIT binary patch literal 606 zcmV-k0-^nhP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hb*1-cFd5<#T* sR1BC*4h6anR7q=diwofpQh)-4%ykMHds^3cl>h($07*qoM6N<$g2zV%2><{9 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingRight-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingRight-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..11b61b01d9757a6ad7677248bf14c183baf328e2 GIT binary patch literal 590 zcmV-U0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Pat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2zsdIzu;s?1LbBYyc##j zI-rNlQrrl)fVasyUat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?gb?tqJ;1CScJFHyWEYSEl>_{E uchEot4x~WkK#XzXG|`1%2q6Fh0N4OB94K`yOuqC00000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?S1C47XCMFqx(gUB$uY(`rL@Y`S5gk=9ET8gYQ*G# z6z7}b%9I5*V{$+X=q5wOm4bQLcrt({gn)m|0pXP8YhP>TAOlthmWKi=Fp>e21M>1s ij*VUfO$Y%H0Kf%`KqG)+uo1=p0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?i~$(n^Z*Y{aZat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!FYycau0;9kr zl!%H6FtJ1l5pMXA?vs+nmhNOFmjHxZKt8J4+N&kF85*F0+YNj?&Do@dC>kizgO))P zRQ*?4oWwN&Sx`m9jeqEA;J`Hj6R@rOiR=}(uu0*7hmZ!|l>-pWb`6i7){OxUyg5)t o1%km4R5hLkKO{6j1BAp_0c_qV`+O7l9{>OV07*qoM6N<$f|2k8!vFvP literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingRight-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingRight-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c9ac0f418972634a5acd155ebdf3f9aef00b7969 GIT binary patch literal 594 zcmV-Y0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?dH*f{l5r=RD zC$KiqPan;XRk#OQ3JK&8N?L%B7jU!pvd&@!GD86hWEUtk$;0AXzhewXdy%r50nt_b0DyVWv`yr$O;A84s;I%L~y{@ g;D>|)6d>e|1MKrAr)%T~8~^|S07*qoM6N<$g4~e%^8f$< literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingRight-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingRight-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..17132a033b32710ebd732f64aa2302464ba14127 GIT binary patch literal 602 zcmV-g0;Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xP%b+S05;>WtgLat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4Sq-{KmkJbSOCFYCD=E6aQOfL002ovPDHLkV1hv;0mJ|R literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingRight-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingRight-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..deddca862cc34585d4d9e7ac0ee0a488e1f995ed GIT binary patch literal 598 zcmV-c0;&CpP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%V#4Sq-{fC30vq6gK0A~G2MId%X5002ovPDHLkV1iwS{~7=Q literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingRight-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingRight-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cbe28b4c48aa956c8acc05820da6ed00a16c84af GIT binary patch literal 591 zcmV-V0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0Dpib;n>n(L?PKp zdMc%J=>mj&Kq_dx1wTUp3d|)Sm$Xa8WOL*<=tWuJ5tTVJ2U-QHA6b0{5e0@8SkcBM ywK*qsq8G9^I9ZTGDkyXBz0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?^;Pl;Ene_zyz3pvI;O_edVqnQ*19#(A_{F8AJw0 h#E98cAR?kaSpbIR7btotQ6m5V002ovPDHLkV1k1~015yA literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingTop-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingTop-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..73af4b84d8b7688ff72ce76fcdb8bd2a6a0e4834 GIT binary patch literal 586 zcmV-Q0=4~#P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?wMtj^MpRIfEPM2Cm>xy*q*% z)D-k!!DPuhn zlC=xQLh_{3m|@Vurb|oS%co<8I2cr)11x|ASi4};a1TG`3Ipp645b7*q*8$sh=}M< Yb~#ZSt>!{~IsgCw07*qoM6N<$f*)r5)c^nh literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingTop-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingTop-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c6283ffea8bf7048bfb8ad1c3969255d3da8d98c GIT binary patch literal 593 zcmV-X0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?nt%hc&4YBb)IyStn}5Lu=~(Qz9@ z@sO+wbe9;CPyDsO#~jG`^Lpsz%`!tw1)f-+11x|ANV}lM^vX>?rW$8~fba(T@Fqcx fwogGsL|-xh@zorRd)=l-00000NkvXXu0mjf#<2yQ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingTop-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingTop-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bd66d988b7f44f2e10f2c9aa9a043867861ec187 GIT binary patch literal 596 zcmV-a0;~OrP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?8kQd6RpHCV}F800|%gQ5CR-hrW9;Q!gL^(GBq7 i-9vzs;6MNX@Fyz|>Lnu4>DxU30000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?F6O22F?2b6JP??D%jF+g&%W;f%OHZLV%oL01*-W$qp+f VAEqXhKK}p!002ovPDHLkV1gar`{n=u literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingTop-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingTop-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fc7b0390c1d0639533a36d56899b23872da5b01a GIT binary patch literal 598 zcmV-c0;&CpP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?AwhT_B#SU%hQLe!qQuPdAp741C+c6#ET;ugVn!33RgbrLUxrI= zC8UM5MgOdSI7rt8-WMCmqddfvP`E)SkK3}BC*urpP)I%pSO5#qc0m`G+xjt0oCONX k7m&|Rf=(b`5E0Rp3||Q#Bzm?yQ2+n{07*qoM6N<$f-bxL{r~^~ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingTop-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingTop-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..55435ee9b5b0531382b6efc693f2d1cd53f05311 GIT binary patch literal 602 zcmV-g0;Tat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?wP6yW^l6e3D^V&hli;kQffZbAS!70pAn|+93mWe#{CE ot{0FF-^~lGK?|xsh=}M)dWNat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kUS{%0;A>7DZ+N`<-1>j0T#dlv|X_HWnO;F84B7LXkHS80y_{9 a(VuK{Z5?m5gok_p0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|UnS zptWwSwLRS=s)CeKa}=EAoWFB|w|yjsIRMYwT3*aO#E?MsK7a&}fT#+Ju?%zeV{$Jb n0nrPT%l{VvIKh?x0N_m~U1=tSMA$jr00000NkvXXu0mjfw+RW0 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingTop-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingTop-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..67ce3a0b259ac16f24f84e2d77471c86177f5c05 GIT binary patch literal 593 zcmV-X0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?r;0g|- zb2x$vNUWd_3jX9lif}$?DJ76lND2@ICi{!OmWl^;l5cW;Kopo*f@7@`#aR2JI|%6o z-=dYQ!A+(v@X3plgBpQVJA~00000NkvXXu0mjfi8KD7 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingTop-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingTop-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..141f40f48670b0a98b81022d7fcfa869cc193dea GIT binary patch literal 592 zcmV-W0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?rfG`jR;CJEx8Np3-6C1I21Kq${Y}`aQ zaRetYM$kgRpDQE??*k=-gLlnc03y%ie9<@7;zLO;hs*#(o{6S-Xl-g|)b405N=6A# z#+h_@Ni_v7yu1ltMO%Zfh0uxC-+7jI+YT{M@V*Dw02|Ow!Q?*k@M4Zo(Cq=BcnFwW eO$8z%`jZ83Hy?fTeaRyL0000IqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?9Ku&rS)p54=eCtI*E z#S&~l$B24R@MjJZg!e&02m><&W&#ieChLpjrHTt>l`L{bAPP(@!O2@cP~`sTHbUx$ zApMt8;3QiYDAJwegSZ_FJnadac-YpxJey{SgF)~)zyer+wF?@*+}@Ar+oOho=>;Oe j_aH&j34S0VqC4pUP2?NGpXuor00000NkvXXu0mjf*m47? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingTop-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingTop-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..130dd2da2b2d572ffdd0b84b775722f13a5f7484 GIT binary patch literal 588 zcmV-S0<-;zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|Be+=`1Z_|oL>si3Bea2C z_9GH9??*`RJ~)Cp@Ccs*M3tHJMR0w7k(f1I=)RFw-Cdh6zMO a^d~#Qs2ICTCoM1l00000@?kEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?^|rKBAtczMkY84^juF683{kg%1Zg)R_?&d)xeVAIqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?d%AMBTYL`;ZLqpL=E zQdWV~j>UHwmLoxL2~at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?RaDWIw cZ$gpkRwbt&ux6lK8UO$Q07*qoM6N<$f>v_@rT_o{ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingVertical-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingVertical-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5f5018ef32994e10102825f9ad9adf7d75c736cf GIT binary patch literal 594 zcmV-Y0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?F9SxM5q3~*a zB&z~FWQO32a8K|v4>I98UTXQU^$=5nH`eat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|s_J712K-8I77Kae#7~`6T?q$g?BI>>0(8yE; zDY$+F&!#KEW+QB-+?BO_yY3JNgYNeL6JP??DmYSel^1h|f%OEIN`RbT0FeRzghbt) XcN`at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?UFwWjBVN! zWat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?%iK~#7F?bf{wgFp-g;AfNpNE4-Gl4O+3kPTo1R$vrZ z1WH831Q;Vh0TMqh&^7NX?xd3?TPN9f08wDFJ@~e&xKa6*Rn7=Rfr%&h)9FtXITZ0u zNTU(b>Lmp(aur}LTHBVKg!R^HPh9kXPckjrUS7;IB!)xqIlux~fUgS#{WJqkUd#p# rt{ad6|HA}Upbe@FL=OBD5(PH`5c?$*NUK#t00000NkvXXu0mjf@Av)u literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingVertical-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingVertical-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e81dc0f0af22fb838f18ce68fef58c4a2aa246 GIT binary patch literal 591 zcmV-V0at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3=9wQk4gm*(ZjDg|s` z%Y;O#D)7PWNARFJ6HHb@rwY@vmM>=yF;K|f2bcg8&{o0bhl#wHD-^Uh&_x1-1P2f) d@J~pT-2n>HA#xH8at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?pfV*{971Sfj6)fk)6JBc zwAP)qcBGd?RghBZu7b0i^M6h7wVz}$2jKs)mN#n;F(gpE4~AgY35E}yx(F}W9z qfanCu=IuiOPOv8c0lWzTs#^g5-ztZ(+Fl(10000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#hK z;Rr4uv4TD*_>%|e%lV+CltMxwX#t|ZtFm|MSe7e_|H zzv`vv@RF$teDLZf_$uBKd@X`ayiVs@-fca^!60}aU;<3QS_P9I?%~B8VPL!g%^w2z h1hoc{0sn+V!7YG#BHuBziTwZo002ovPDHLkV1hUb1%dzo literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingVertical-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingVertical-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8d06f09a1dac5f990af15601d14390c84385de52 GIT binary patch literal 595 zcmV-Z0<8UsP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?9Ku&rS)p7kVnvIPrM zEWrkJjHm|%f94>$yblsW2+Rat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?TpAvqsH_%NngoOqfFf1Ta d;F*x9xf2tO9KP!0usr|(002ovPDHLkV1hXM`g;HX literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/paddingVertical-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/paddingVertical-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..13f513cf673f6629c6a42a5f7e7318ecd91c45f4 GIT binary patch literal 554 zcmV+_0@eMAP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4lSMkNo)gt0mp|WK9=~Yk0nI?K*qN16*;@tb zuH6cMa@yrXgQe4#x2b9OI2Fy#?cDV^^wEt&cX|v<^)5xdf4JX$-vUmJt_eST%bKTr z3jP$n)PGCGqK#AACWK|}`93}Gg$;+c{R7j9&&#cny?kp`F94; O!3>_RelF{r5}E*Iq-gR0 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-full-black-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-full-black-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a3113c02e4d73931d71219327ef8cd3f21a2145d GIT binary patch literal 374 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%oCO|{#S9E$svykh8Km+7D9BhG zu3svPezpuy;a2dfU$lPldmJk!Z;d^pXq- z-74yIVq32Jk;(}I;aB8p@84gNx$4cI3s+kd(_0vNj~wNQT3Fs?Q74q7f243v#;j)z z-l5Z;x@eZFvL#Be&3k^A_0ik3$Z4wmKO3EA?$H)VIxo9Ov&(7W^OU^hWpxhomj>Th z&VKPaJMYfcK#{cq+pc}GI{#UA@n81)Cp7L~?EZ5t>_U}g+m|n&EzNu+rm%Fu RbWnIQc)I$ztaD0e0ss)$l@b5| literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-full-blue-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-full-blue-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..7400baa237573badf82b7fc83705eb31684dbc36 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~W8c!F;kP61V0ULP_83_E@KIw``q032*o(a54 zY7M*%j7io>3=)mJ2`rm9YlAKbX;iXZ5WXy>9NwXeIEf=vfsmpMsp7@WUzmXEq zcW^y#pU2LXj!tgBu9U(fGZ)9KFAB>u5)h_PLQeoTP?UYxgZ!so#R*!WTN%JuS|l*F zM};r)Ty0uXFZL_iA{_2%4O=a=iJcWnq=Bb*^S*z+!(WTQ&HKaQNRt1*jj#Y!yEf!h_$YYWy%%nj9OYY@eQ2cQC8U_gS^4GqPoGvT=e!t~U?=EQbHQ)2Z_ib) zl~+D4R{yd1=n5@`U4`fLkIh*0c%u34Mf;*&C+Qq&EZ;K!F?&>_#ukmGXVz?;dsW8# zc()73-zAbc+rl4By;u9fP;NuCmC+CNl*+^kz7DAr?~L*-zLPYce=jvX19U2br>mdK II;Vst0B*r!7XSbN literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-full-darkgray-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-full-darkgray-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..116238e9ce36e4292e5e4ede5ca6045245ac8444 GIT binary patch literal 376 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%oCO|{#S9E$svykh8Km+7D9BhG z(e#{7`maIdU)uXyCNRHe<@Zeb!v z?K~&VQF##hfKzEk-&(=rg}1h8?>*7;u}Dyc>865A+`3)s@{_7x+!BovP_dkKV^O2s z$E^<1H@mmx?*3uEzP2rB?qZEksekInxClkV5;R@}>Yy8ObLlLfslkH5H-ZYY^h#T?wAxVH3Bo>onG*s)5+{b>~^tOPC_&rK!ZlE0d|`yR*n;pTGY)V)PzzAspuD3|wo$OA*WJm>o6l*H;@?TrPk*i2`P#ovLnzT~-_c#`jAv+1agLsJ z(W(4JQ_W+x%MO=>Pi07LTgaugV6L>x9FDs(iFp$mzkP@nIGb8Z)5;R%dkYr5pZ>o1*e;;`^{_&{L5OpBxD#)0j|hL+`e%1MRL-!gTrmu< T@)y1W^d*C*tDnm{r-UW|cjtlN literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-full-lightgray-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-full-lightgray-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..fdd7edde46c5fee414c964c94e00bcab144437c6 GIT binary patch literal 266 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~Wd`}n0kP61V0jGJJ4R}hG*j{kRE)1GfZSF94 z!QBOKS>Cd}<;Y=BK45v0ujc>@XFszB*E9j~c_}x~&riSU;_kTQNYw8p>!-d!r{Xk2 zb!+(ce79FTGFNb!L^9{W_h-776g2MbHO#eZY1C%1U+r6cfY0)IR>YCEw$LD{v7 z_s-rn!EVvvjptv!*u(i#XkBzg)REiriY>;gTe~ HDWM4fJv?1A literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-full-lightgray-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-full-lightgray-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d65136a7d18b1ec4e6e7e1a76da8aeec33ec02cb GIT binary patch literal 364 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%oCO|{#S9E$svykh8Km+7D9BhG za%=P235pY5AKKKn>D$6% zTi^8t)@@3^$h5&dsX%Sns$AJAM{gAAB(I;mvvtkZ4Kt2&-?aVpPgg&e IbxsLQ0KoQ<;{X5v literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-full-purple-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-full-purple-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..08a16e713b00316cf659174df8d49e0dbc4c963a GIT binary patch literal 272 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~WQcoAhkP61Vfd_e;90carY90{MIoRIeZ>12n zU{U>6rne5#6K*t4Ti~B0JS~B>M_NelK&;abgZZc5ym{kObRb}Ym1nxmfrK|Xg7@Dj zfA5mY=BS(~81^AnOy%XA=Uwb!1~XPw?0NbrYjzp;u~}tBlYSk@zU5YvA)BXUS6lT! zI_s$FFSXKxY7;A7Z@wN?Sl!7w$;oT4%jfw{>q?CZ{kZEQ^}>1j>@7kyr2Y1#v;iH= N;OXk;vd$@?2>{`DVc`G( literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-full-purple-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-full-purple-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..890a1c4e0bfdb7894fce803ad792bdfd36daf607 GIT binary patch literal 395 zcmV;60d)R}P)jL|{cN(27 z2iASb{>+Tt>}d6XmX-pET|VD3Sr8+7bT#7~7KoWRe4Ywk-zG9GhdZ&FxyQFINxY2; zv>_7doapK4Vmn;o>6-ThJ~T4*XSmFAnZZD+Q*hJMdKGGgc0mM{jqO#aj)Mtxtcimwrusof8<)i6@K-WR{cbNhv8S3}RCJ!9 zA;i1D-b=OcNSJWOOtb*cBK- z=t08+7ETL|?L3pzUORoesp@-q_uX~UfqD{_2A?~^G@t7wpZUexYH%h)_T`2P%NtlL z7f79bSh1YlQ&U69Jpawc?5dR$D@wdqde%?yRL|y85}Sb4q9e0O8b5)&Kwi literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-full-white-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-full-white-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1246d76a61ed6f28e9ac1c96d36e6c079f9e3b9d GIT binary patch literal 277 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%oCO|{#S9E$svykh8Km+7D9BhG zrEe1TTmmjkgu(i>qR%f6o^^>tCJQBgx^CW}Vp^C)ROM&`kbKj&fDs#F__LsfV>f>TgTe zUUa;vrF}L?<$V;Jh3KLW9}T+~*f>l-tF*$!wQoINsOcxhOv^v!7u)7IJzCoH!q@Ld Uocg(RpsN`?UHx3vIVCg!096KNEdT%j literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-black-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-half-black-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..80df8251059e4682300f0f47b5bd170b49f2bb01 GIT binary patch literal 280 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~WT2B|pkP61V0fu}`iULpkRDUrLQ$* zUC*KDe(c6s3FEYNbB_odVo3dMb=A^**%Yhywf51PEgl(+OYbex4>0xAY`2+NT(|1w zYpIo6?=AE<-+TD-6_c})ey@tZJZ+b$e711!86Sb4j6LNYWx=x^%sp*-Y)8eX{0|Hp XKUuI%dKnN4bU1^jtDnm{r-UW|?;2_R literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-black-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-half-black-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..35443ec54e3cb24ef20b67e5e88ec6587c608d4d GIT binary patch literal 404 zcmV;F0c-w=P)WZh)GeGAS&EEEI1IxS8GD}BAXmTu zHHNfUD&$X^rW5WCb+bUT0m+N^e{y2){_mdcb%dR0TI;%=!bpT+IJ4y&Yjg>WG0m~F zs~Vlc%NTKzB+AuM6g8(h*oC+wn#LdqmX3CuOX+=aM|R8&jlJ9J`(E6U*r=+iIWDho zCT=zi_cxLT>e)v4=yO`zwk=^KD2#1sSR(kE?jlu%S|;a%X|)WqkQBVUx*D5TAy@@duO|GWPCvm1!KXy3W(=&cSG){u15 zb$jJj9v9M8b1AA0swj}Eyc`j!baByKtphQV7G`U@{Zglx@!0P9&0;SQGb_#a<)rkN zwc?*rJ@!0VELwB>OJ}&SlW6KL0ga;nQSH^12Dt(|-kES-$xgA8%20co;+WsUXcH$z#Fs*S>^Y~ZfMi1j|8cHJcjHv%gT-Om zc}**?!nq>$DIrEoytFadbFRqQXeffd8m>^1oi)S$ja&n@yb+~ ztwt>QU5}FdXPw~Z?d%OUgLd|zwev7mA6<7L^`~ h;POLT*5b%P^9M+Wj!Y@z!&3kN002ovPDHLkV1f>ox4-}Z literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-darkgray-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-half-darkgray-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..1ef40f48f73aad50d41ef5b226bc64e5d87b4869 GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~Wa!(h>kP61VffqRs83^n(kvt%H=Rlv3V&fmH zMq>-lzdR}dcNQpL;Vofi_vp}1aERhuwB`NtzVADBmzTR_H%>hwv6)xV*joBcgnkQ)=g`vQ0Rws=3khPs0&qpspMZG{(kSD zRUGX%f?4ZtODC*8yw&gN7X8(_hXl)x-&FbYkl~?R@*N-R=KW6VqvF{7FPGW2pJzC} Q5$I$FPgg&ebxsLQ0C4VPo&W#< literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-darkgray-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-half-darkgray-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ecc66efd0573944c350b101d59a8dd1dece791a GIT binary patch literal 430 zcmV;f0a5;mP)YXk zKWTP{-8YN|-p&$TanT5ZU?k-YaUI)Y6h)J^ZC~Jy9LHHDNpjQo67ZMcd(6e-EBFhO z<645o2%2*eSP6ec!zeV@gT04g_+%24xd7rsyVEpH=Oh3sc;Hzln8EI0|6*NBoX>+a z$vWz~UTF8u+;i!O$g-^5ws+J-eNelQ<2d#@zpARTuL2X|idc>K2g}ZsQeV6#jTcv> zWnSQ{{2k1uX~Y$Y6G4SJrd!$*ClkZ@6Gt)*j-X|s>%KZ5Xh%W|LEu8CeqF0^$nU2)O) Y23K5rG;)*lv;Y7A07*qoM6N<$f>+SBQvd(} literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-gray-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-half-gray-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..a2dbafaced2cc1002c7f6eb0ccc66627eda3fcb6 GIT binary patch literal 239 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5|=i>HfYNCo5GfJV*+1D@4~nQad8f0v;j z9v6E7`wuNY8|xmh&pO1$oG$3foVYMGQ+m<<2^EPwCqHHsG;MR-Tk=(|>ftOd9<~h~ z68Q?!Wy|?u%7g^IiP}0;Jv_DgldSTVeZN;KF|NPTkz`D8P fCr_7leKYg3bmgh54yNq}x`)Bj)z4*}Q$iB}r?ONI literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-gray-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-half-gray-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2df54f809652ce6c792b035356488b10b94eee36 GIT binary patch literal 387 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%oCO|{#S9E$svykh8Km+7D9BhG zPf*1G%ijk@cew?-q&AGehT?Ym`(}ej*b&APn-3n z_J4p#>mlWCi;dCMXKx!_NSrGe zuIv;g%|COq)BGMIt#lYa{>gTe~DWM4fCsLOz literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-lightgray-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-half-lightgray-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..35438144bd228908536ecdd5c65f44d170546c52 GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~WGEW!BkP61V6MXp&DTuT*9=fOeh0V*!!rit> zeYN=t_ZPF~2jnj>FE~GcgMwo2+KVpfUybCA`)wHhsYb9R`@Ej>I;ltbd5zXSfkzCA zZw!v5d%e`HUg7ZmZ-crnR!e@v zVR!e7UunjbsP8|&d~L4z^k#WsRLiVomaPKsuHCx3$MWa(Bj)@6NZT_05OHEOo7CV9 PbTNactDnm{r-UW|+lFVE literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-lightgray-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-half-lightgray-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2a33d30f3e579038ca79855e37a5d5cac1476779 GIT binary patch literal 404 zcmV;F0c-w=P)02|mkR}W9Z-S<_x@T}y#3bX@b1^OKbbRZo-0sL_`K9v}C7d09af64H8 zI%IswuoAs^YLX=BX?>FS?bwG=6b+%gs;WGW;}r?ib)9Uz&_ESrjAMv@VbL^AMgs7p z#_K?nFbsdiAQ*>c9r?ch4tbsi;ox|>8MunZ$wm5f!L)0hYHlo6-mhw|oK8E^4cvmvCDTQ_~CR(OGkva%1Tw-zQ zLhe?E#|LQ#>NP=2zLaG-ppNh`Hn*u5geJ{-MZ5lZfuI*7FWH+R0?cR_l?!oEOv zjfpobo1;BkUa^(7tZRwA+aMj$Wmuagru<@w)1mFN_Sk>^um7Lm@s?mCAGw7tG3=a<=v<$;i`J_j*{VDne$R>!_$Lr g$8ld-_eVM}__gK!<`dOBfgWJ+boFyt=akR{0QgyPLI3~& literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-purple-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-half-purple-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..66b1ee71812cb03b032c0781f7cffc5956b0a0ef GIT binary patch literal 434 zcmV;j0ZsmiP)llB)6gZH1k*$C4G<^5WkQ2*klY{^1qcccGaH)%#ol!i zC5n_Mt-SL7+3(ekKd@(~8Fcx`RcF(Bi(d9R+z&fE`}o8xJmU#0i0-}AN?qV&q(UY{ zAm|rnM3}+`Ayuu6w#=VGp9fYW*|=X6-wxmC_;E}ZurM6cm1?zSUW!Yr5d$YhafF8C z--yi~jIPya72=e#s;aQ~^+wWF zFU90e6TIj1Gi(MvzpB=Rv6gzcw;Gv@V_ZX1TN1p?zB+iG+9vHy7>_7M6ZD>3?`qw5 cx@YtJ0=jm0n&qU^+yDRo07*qoM6N<$f^ti^2><{9 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-half-white-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-half-white-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..63ea553840b9b14fe260dec941d8ff88d752b3b0 GIT binary patch literal 224 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5|=si%u$NCo5G34y!~20SjaH657vW{9dhVBoZv z*`mnEsldo?VX=;JQmaUW(eU2b_=aSqNVf=+3ExtYG-UQ)KOGX z-0ykP=E2KNy{a;d%cOPweY5&l-dZ0C;Y`fyPo};9ozO*IMmcLb0Fi*+`VXJS;O(q>A_oD t6!O(NJU{#Ln4XRJx=^=vnf2RB29a}87fpdl z?Vqc*5C3%Oe|Y1Oq2bx^Ag{2kqVw44r^{}pw%t6-rx=}RZ+h)kpJADplgs)Q*>y&AExX__q*2SMYHwu@_SV z?UN)~X*GPBE1ETsZti~MN@~yTz0Qen63b&z6k8fd6h#M_&eTSr6b;5X_xPuNTm-&G z`EB>DQjU1f5zq z0+ZPZ*~u-uhd6o|gjGsBOkN7?Y_If~uH?}ma4J0Ve*Vo%{01Tt?JIXKIoHj@`sQ5P zmj1YzWqpjsN;@qj*U0xJy=c~%m~m~t)&X;#IaOsxPoH+#F1qJo@IPtcT<@vTexF{8 z{p&jw`!!e3x;sYuEmvcb?CM&*``YZwM48MlmQLj^@lLU;+VJ?F_^|?oDcllsq<dkAUX&Y1PX}bCcBN5hv3HOLAFVrITvjiUp5oj~Df9Gy9>^SEadgr|BC&=d2d zGeu3xFq+ALajXWBT`D44;veK0<@@-X1^EhPH`*QbYm)hVHR;TJ`~mhMM9Vj}eilBp zQ`f)a8&Tq_#J5oY^6No_2X}jZd+nnpu8idsgt;2ThVR_nPJt$DMRMPfR#+l#Q`oiaj_EU?NM)MAq*o3WrCux8H0000< KMNUMnLSTZse6gJX literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-quarter-darkgray-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-quarter-darkgray-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..7f7f92cc2e0f741ba06b2520dd525c0bcbd2312d GIT binary patch literal 270 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~WVow*xkP61Vfd_dH8SrfJWJ_Q%Td=sreM!yC z2FV#qY?M`lj1Y9^-f?j_`+T zxB6-x%~Zdyn%Nzopr0D{Y7jQ{`u literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-quarter-darkgray-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-quarter-darkgray-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4854fc477b60ad0091ce097064d16d29fe689184 GIT binary patch literal 400 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%oCO|{#S9E$svykh8Km+7D9BhG zbZuR-|Ji0Q#d+y7Ur#@| zN$3BO`+8GW2ZTL-b#Tp<1KXzLR$Te0yJK#_h1pkrYTx&`)$#sT!0SJ~tq1z}qh8zX zHfYNCo5G07lLR1A#xCj6Dg=y++D24saQF znh8itI0{=xOB}4en_y7Nv8g%v_}?9G`!&Q`M7>tZw6mzcxcSlh@%Ia}_8#GsIPgfV zg57e%XEl$=m#hmb1s*9*-G8dO=fb4AqtoXG9ltJ7;JkM2wU}q8q<2NxJPeC#mY(tR f{RO5l5n1+UMQY{2Q%?v1-NWGN>gTe~DWM4flpa!t literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-quarter-gray-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-quarter-gray-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..10199a9beb87bb7834951a7434f59324ced58b7b GIT binary patch literal 367 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%oCO|{#S9E$svykh8Km+7D9BhG zxk?`ua*_KQuChb1-_KIJV8zm+ga zCGfHdTdY`kM2h$RUO5fB;>f<&hn`h*z2KPa`JZzndU9ZMYQ<*IH$Yyu$ zWlYCAT}~~jdMo?$P7L!_|My8H)2o(Dd|)swFY|n6WcgAvry!fFGkbUIyk>ruufcd| z$L-ecvllPTHr88W<`yAw!JwvUY3-X|xqD~lo#~h_uRFtZ-tp@(hSQnye*wdX!PC{x JWt~$(69BJ0ixU6< literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-quarter-lightgray-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-quarter-lightgray-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..22d695346c892c937465c335e0e018a4ead1fd1c GIT binary patch literal 264 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~WTu&FrkP61V6Hf9TG7xaxdrwnQwn2ZL@)U>E zh0Os>>H0cm6sv@u z=wmk`ISfVmLnM;la4PDHfYxU7Bp)@$NhcKzG=a;}_< zEyD}1FY}M8etN_#pYA*5Qn1&{mwWH~Zf~e(uXCCGnpN1yciPMoXA*%9W$<+Mb6Mw< G&;$U$t6|Lm literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-quarter-lightgray-13x13@2x.png b/editor/resources/editor/icons/light/inspector-element/split-quarter-lightgray-13x13@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6d557d16881f48f31f50187fdce1e8c495e45c76 GIT binary patch literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^QXtI11|(N{`J4k%oCO|{#S9E$svykh8Km+7D9BhG z(RV@L(#+o^YXn+!x+^Ld$Hu=OY~-YaE# z%x2YS)oIn3moUfSe&YkSU5q>j`oACfH9a9OFy7@oAyj#$o7lMF3xRIn9=Q~Gv{UH z!^*h+Y!9Y2lFr?7HQGzv771QH{^0k&uB@cUYhn8Aiv-_4Yg(jVAfx_w>HbKKU`0P= zzbnz3gMzP@Zddy&oAp!N%I(OFmAB)k@^lE^HVLr*+U<5m(0N*_@G8zj5&Hf>{b~I( z``-z1p4+N?^8thI-9r+4voCT;w*Ow3yySH8e3pph%f@fTmzBS6JlXth)zWEh#jJB( W=4e=2URVeWECx?kKbLh*2~7Y(wUkr< literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/split-quarter-purple-13x13.png b/editor/resources/editor/icons/light/inspector-element/split-quarter-purple-13x13.png new file mode 100644 index 0000000000000000000000000000000000000000..fc6a9b3ef25d27c46764dbc318595e3696684acd GIT binary patch literal 281 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4uAB#T}@sR2@)1s;*b3=G`DAk4@xYmNj^kg+(( z-HBn{IhmJ04okYDuOkD)#(wTUiL5~WI!_nJkP61V6AyA8au9I+pJS5l?ZIAkacfV6 zlTwp;_6F{Q&TkZ^J@B;2V(pZDqOopv;dg^3E-j%?euw`X)c;`K!g|s`zPMzsBA?Tn zYt>d=cG8~?2t5i&+-w!_(o}WX%8AMj_h&p`tLAXjAw}Y5bjqro2iW)h{BL-5&T{2v zE}zAEADfBq|0OHg5wL6XCcQ+>t5r2mw;p2Z@!I14^qn}T@j3DCd)Zy9|D=ejWz4mn Y_u1xk)~~($fG%h7boFyt=akR{0O}lS!TP)JB;o+#!Z0&&KuAtzEMF4I zPg-fU{(r~X+5JGrUNaeTFRJsjN!{XTz~g+ti}w#K@?(C5gXmt?TJdF}LMmj!6a@Xl zB@y1>L71ynMqlPPdCC*FkZe4z%ooKI9bV7q1P;ZF&Qzbk`*$&~{t>@6xQ=15p*~aQhil84 zFWGzkN0lb#rEyRH^f0MnG^+Fp7*duD9Osqjpe-2 zSazVapln0aJ6D$;=3ft0_p}^1?lUbVQS3#Il%VAXtFYP9$2W-We9XBweruwnfy+Xh zj-xUUXHM#N)#13@DYn0AZI!I@zDBk!;jaJpEtr4tgaOa=fMhpy)#_gDwy*Cm{1lZ^ zmQQ}3U4QAtuL(zf^T${5xZmY{)!kENW1KX*^_5G-9Gmu4jLrWf^}i-3WpX}V)p+gJ d<#YcFSg)jUg!BF@6bCw=!PC{xWt~$(69APqYYqSa literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/strikethrough-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/strikethrough-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..afde151fab89c83f7690793b2df91efdf15c06c7 GIT binary patch literal 936 zcmV;Z16TZsP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?9sURHIvAtS>Py7Xt$*YjqfRw2QiV8v^iJh#DmIq)?ZlFvn zRvGFf3Tq{X4k2)nIB-q=1R?kBpEz@=53FNi5ax*N)l2Qy5h|gON!Dmqw{ozr{Gh}01O~huSlNoxHeWeBzLSj=fV8uFp`P&U_Fi+^ zebF9$q&KF+KZinyV%2aTfqHmxtrahCz(9rjXqu3k7{$Wm*tyf^$pQWG*<3B!fi^VY z@p%HE2r)H0h<2dHq8^_+2UPgn)++PIr%Mly&xxwtAB&cb=4STmNOj5qy>0*vN$)IC zcyT*Q=qO}2J(^`IJdwy9%o<>gEKabSO*9*tR|%ytZqvdOa0-E>jST=z6!i-&<##e0w$T2!quN_{}JtFVhZaEUlnp5@MQDsQArDU=d~o zY~kd#+%K7Y3Wk^k43#W9G0m)&^icxi9Niy9>V&L55D*X$VDbfU`jP~~wsIi=0000< KMNUMnLSTZIkg0M2 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/strikethrough-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/strikethrough-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cb03308883a76a90deab6b695ecc7a7f73354c72 GIT binary patch literal 921 zcmV;K17`e*P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?w`Et1om?D$}z_EEa9C{eGZcu_^vDgfPfU|oG2%S$bG_$yx zrZwmDxyK057!k+gaU?s(vF|RI%TP3oKV&YhVX~fxV zX3O(Zsl=<*Drf3=#|e(3N&E^-&+}~G_bG-rUmhL=0>;8?jsV7icsZ ziM50PC`={Z1C>f8u@;X3lPMl+gl@On*>1OPG%uIS-e52orcgOzfTs$$1-$VN#95(8 zzFMtb;~bHAkSo40G(w&ao||QxlnG(%kzMnD3+i7)VoISIVN(Jr5s7C55z+G$JDuQE z+Pbd)R6isg3u|w&Z%DO(T#Vpw0ueTm&XJ0r*6TITBB~UlHabeZCp#BV{vknH7IENU vXhwm_u8|#JKHcy4W6n9L4&=y@BZt5@mK4mUoU{CT00000NkvXXu0mjfvp$}? literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/strikethrough-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/strikethrough-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..91a5491624ab931f956da2635ab47a7203bdf167 GIT binary patch literal 938 zcmV;b16BNqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?LMNR?{TWmR<~)O{+kuX}usf(|h1Jg;6r@-JOI?Y`TBbYinQ$H0Q4?zu3U8i3 zI{6{p$+232Cf2KMFtETSvUi3izXHs5dWfR|t-(&RO$;g=QTp}9%{*yiquLzMEOuKE z$@auJxV~%9H5eC~mjEgf(3!C~$VoOQTJXc4eTlgO16~dIVV&0XH1k^FVq+y>jPd9) zJ4$$TrrqrL`&XfUeG>}B*%d+ry}|Gn$lVj|1}B;kCn-pY0(jFFW~Z&=?6X`As7n)n zE#3onD!=2o1SmuNnR=Z;jzdo7;||w=M8Re4F|!}dUtF3-Z~S9YwD=;q8PBKi9I*$a!UJs78skFqoKTqG6wpf!frZ4FhN;~;{mJ?8 zj7aN%T(0+fI!RAhx|>6-l6Jq_`#L%0R_wujELJbzSDPPFBO0*dm!c|I`Y*?*_|3?U z<`M^d!^u;5QT(n)dHa{vGU M07*qoM6N<$g2NK7D*ylh literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/strikethrough-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/strikethrough-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4130110dccf41a4c4c832ca23af5290e647b9789 GIT binary patch literal 931 zcmV;U16=%xP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?qnKwM&_cHHKq6``SJ96|3 zxUOsD^Laa$%b5_3^ZC5iG%c7;r)x@yR1UOSE%SIh_CWY_MP;q)dVMmP1oYPqNb)7f z%_Lpu)aUcLM+|7h#NlulMacJ%2V&vutGWoyNQ8-FSLY~+uZIJ+Lf|3ZbycU)X!No5 zq-Ych1sD4`$u`RYkeiXKMO0@toAsN`=3OYCPNzLFz{&v_w(!*N%2n!QV>uwR`|*5r$2NNyfvAlwao$UE zhubAn{~at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?cte$uScPhCuA#hz}*4i&EL=#S(t>@8Zcnh06jaR;lpwDE;g2c{eGX( zFh3S3rHtMAXf%?O$wZ<*uR##3?8L7DQP*|6-EP4^fcHiGFq_Q~MbW$KYZYPBG-|cD z1k>rXnH&-2ocG3P)G-2=Wu(=^?n16CiP)0lih{3d6^>V(jZW$q+e zlZZ#?exOjh^X%PozO#UmZE)D{1@yu6X>4soSR~r#!|4JH?u!3IlHGH=WbZ#D^x%w! s2k2dhoTN&eYBDQ|VVwg50|Nt!FQ{>W*UDW1i~s-t07*qoM6N<$f@Id08~^|S literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/strikethrough-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/strikethrough-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f8dc87bca6f3e3a87bc193d7c2918c77f79cee82 GIT binary patch literal 976 zcmV;>126oEP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?UuoA(?Af0XB-iDNH8;tb9c zU{jQe1JFD{c!QQFKzV`&I6bKpZ^4zJ3&WS|su&+rAGB3}B){++PSj(yJXWgfD3=q1NhS0tO~WboT4P znFj#$!^WX^&e11#4-t2ht!)K{8vu0je6tb=LsKBA`CgyfQAV@v@7+3hwlO!TXao#c zHDLAJ8U*+~Whz{3tOSVS>VCaU`1R!2N$>BitjPzfcO?|(y*{eWY_oU-;)CovA7vjH z2w>cZG%rORUWxi3ZOhca&(q&9I5~#v;PIW!j4hLZ&JdogZ^Cu3v9g}AE!Kd5f`99b z=C^k1*WW+xY=8gun!o?3)m|c%x(4LZ1TMll*lHnAEqOyuwhrHBM7r@<0shcWcH;PG z(&)K)zFD0RRrHW_|BsiVH`B(nsHvU>W_7H8G7}jTZ2f=ts ysBa8GEip^fA0>n^ST&>0$n#lqproXvWXgXvueIzcj9>@=0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?F3#25kMyF4Dmx&fqC!QH#uD$%#r)`u`P{~eU`dZ@RT|#{IjVDFpMpR@n(yz&B)<$ z6>}))lenMA*%Wvi9BqRKMMZ4DFfBOPGxkm(n*yIX3a|sjL5D55u{vO>vRdvpsD^1l zRRtIC(jl?>@uAK1vJ6Dvg|C@{B}$Yik>DHSIE!!OvnGK60000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(Ae=xr0p5V+ z1cnoUH-HnMPey!z8`vZGXaaQnx)h`(q*J5u!G6hRcbji_W_R|RDNv%se}}<0U}sXr z3IUezxkD94m?J`HFU%YTQOE)NEIy5OIcy!E%yEpSt(y=(?LcCD!l9o__UOc!89@OL zS{z}JG5*fhPugRO8)4wWq(DVOa;FDlzJXw5FHJMWc@fL|>?YGH7HF^^=IyO=fGnRz zzhE%VQs|JiQ#sv!@Z1gMLiGl?agE(<=TqUwrgDIWTI_BQaD&V|Oj=PqP_DzxBpm{A zx(=X&4~-(S5IpTp^(y!!{J8_^5JZ$sC8KFAB6JwO#&%Ar@_79{-YWfWR4V9Ar9&0g z+yaBJdv1DJj!QfXydlm3Ylp`6$~5x!R)s(Wb*%G$i{m>Q^Y=&}&af)`?LwD`JcdTL z@{CV9v9HqR>UH&7@^%FGnKi0fpf5&Ki3?Gnq=!sY*P2A7SHTKx0GfKQHXft!4~ff` xf*Y>%kvvRiROnosWKJ-oaaA2CQKCeN7@we3d)wMA?WO<#002ovPDHLkV1kVni;e&Q literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/strikethrough-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/strikethrough-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b17dc4b16aef4ed15165c2f00f5fbc538a1dcebe GIT binary patch literal 917 zcmV;G18V$at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?A)6`GpQhEM6}J5`^ZC4wUg#-TN41{uwBo+a zn!tX)7x?(EkKbRxm`0<~UoMvqo{ws+i2J+R$wgR8w8#bPlu7Meh%QlV0* zM1Mh{Pza4(G@&}@f^NWd-R^F;d-iat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?mAcX=r<-j*EEr6R_Hk%xPZ$=cvP@)cC>70hL^mo~M62vqo54U>fop z?%G=wKn0#}VY8}1-X@|TxZw72DjV1-6sT%IPFEAtkIYMji%k{4Ik%glxZPy9o`MCj zdQ^& z=I!QEJ6TzE3(mN6Z@@LTW+}Xgo?h}cuJO!3pR!CF&>*5#W7pow6xb6fxF#=VfPD~W ze%|71=~&hMvZxx7^!Ct#((CC?I=tl0T?NTv`px0h81|Ld-Xhg3P!A*Na>EV1U>orv z_)62L)VCmky>lHQ_)l#Rj)kNg+5o{>VRdb-Eq@=|04N^ar UC4^|3at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?DCrNkgE%@_(w zP+}?=Wt>k1c(9Gj@Kd%CM)5HzsA!Dr>LEPyFUIw*X{BtQq;E`oJeDeEX!7aqn_CqC zt!w}r`1+bPXHfO)3%LSd_!l>H=~c(u}b}t z=!B?5MUzc=+Le0VP&ypFy#3~=acAx`qf~c+`ZDr|;%(7_U4(LkhDNB=RUmV8tO6=b z)y^%s|B%FL37m7J6{6bODO(^`WRBs|x#}J$C@3hfd;;-VjsD)I34j0q002ovPDHLk FV1ndml5zk5 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/strikethrough-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/strikethrough-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..71ff59b750c48624e012657e96256f4b0499c52c GIT binary patch literal 946 zcmV;j15NyiP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?jK~#7F?Uv6k13?tWzq4%`aZz!Qa4=~}94jOo`3q-r4+Sb)~{3v0SV+lR+A1FX`pzlIzGM}EoHjmoVgsn0X@2mzuPSQ?;|ddG!lDsZrg z93Y|$ce9OzH>aK>U^=>Cx-<-ev#*rOR|ozh&}WAjKR<*74atr0Fgy*6Oyk5mR~G{h zckXUmLSnRjuFe7W5XmvLgwEdjIe!dj1bnSk4i+*0aPMBdvauc%X11~0Kx#M!OhX60 zVx!dE5THo^ksX#cV&#wY|ZuelJm^`2QX6Gs=Rf7Kn=xXSpI#Z7%p>QKMp* zkR&Q`G2%=($6eEUAH;Y?AB=30GF%oWD<31Ns!`&P5}rG0w~@~oC8`4at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Z(k;L+{EL2ke35IdeAGT zt*x2~5B&V^y^^}0m=feDG_H(dA~J03t`Zt@`f#F#@wocobmVpPAE{IeG>Vbs79vwo zUBKyMl|-dcj9AUjfb%o%txB5U=&SgikoQ_-5SU(6!#M{@X2phar8at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?)7|;&OjIa5JB}V8#yG>Lf;`0SBh)zO zjx;6+?4d>M=D;>I1`<3(8=qFc<}HBJ9kt7TVDJ$s)5hi#?$ji@gxtk&|{(Ocj%fx7T?yEPW} zY3GF|X7U8|8SwPjvNGRLT7Wjtf5whWc9Tt@3na$Q=ZS;Aj19jDf!eo$*}~3T5$`3i zOs?Q5cLg)WYC}T-XO(guWNap?q&D=fgng3OMLQu5{VK{5A0`Q|5~-oJN+!tIPizlk dp-?E8xd1cAm0Q4C4ORdE002ovPDHLkV1infPbmNZ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-center-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-center-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..92fabc88caadb25a75df40220b9041c8192326b6 GIT binary patch literal 547 zcmV+;0^I$HP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!yXk|gd0tt_V z@PFM_P|Rdk0%o^((|+F4yQ-~6*RlPBll`4Gdc1+5q$5$*3@`B^PAMg+CGp5$$E5CF lFxz0apk{(;10uMH0DN>^6cy?)`?LT6002ovPDHLkV1lsJ@TUL( literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-center-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-center-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e86a5b92aceb1ec7703862e964698b95638ab4a1 GIT binary patch literal 530 zcmV+t0`2{YP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?dsK~#7F?bfjg03i%O(Rh>G)!BcP)aNML2nvdYN(%pL zBw*>shyb?>^`NSMK3+L1n%P%|M*wGGc44uM=Ee6=0o)BM*!(XHYoG$SVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?X=6dc0tt_V z@P7r#R#41@m4MkT-gG?IcW!Fy*17Kg;AB6ijUIPkDCtO)HN#7Mh*L^QYDqjY*fFX5 mFPLqxTTnB>v;h%pL;zkl9uO7Dw;Lt^0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ufG`Y2Q9mYup**FBf=x_?gb<&CL@shq zXDMZ_Y%^eVIuGu?X69@iN!lV}Ip)cLV)}aUr;O{5ze5Em_gF#8z3^586`&j!5r7?t W2_OxXZLWU+0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?jza$bqVrTuII!ycma&L-G;+5h8sUa1u(a);PSh$tbqz(jvo<#0;4_@4NPco Q^8f$<07*qoM6N<$f|BLqP5=M^ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-center-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-center-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1408673e67a24f1d3869006c130ce02fe88cbe48 GIT binary patch literal 551 zcmV+?0@(eDP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?K~#7F?bbUAfG`k*;W6Mn^hh=y(#9j{J#4fQ6kHR? z1490<30oz_3|R?iUH2UNW!kP|P+t2nuj4&9S+B{Y#2u)MHxrS~cqRUelSfQyNjyTB pIZ6C4m~AjykTSuv0e{$t0Gu(#6cy$RFK++<002ovPDHLkV1m}r>=*z5 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-center-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-center-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..38bdf44c186433732ae30f98eb86dd6b34457d59 GIT binary patch literal 533 zcmV+w0_y#VP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?9ic&7yfkIvX^(SK6$tVFs7pmlVwydzJ&^4u3N$4f1z6g6~G)D5r7D{ WtrQJMjgt%j00006c literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-center-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-center-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9a752004e9d83299adfc09c3ab6f231d9a10b659 GIT binary patch literal 533 zcmV+w0_y#VP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ufG`Y2Q9mYu8NB}po&h#76%s;x3KF@< zJ)NbLxw6fG(dj%y#G0A2btGwX_vM%;1B&VE!Jjg&KmHCCpxk2xE%(A(4OD<~TtonN XcPAhXJn|qY00000NkvXXu0mjfFQntX literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-center-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-center-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fa8270f469bcf59a031f64803a5db7eeb8e2a07a GIT binary patch literal 533 zcmV+w0_y#VP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?6ch`U zEBvpK14}=i2(UZNhwt@&JWg55-H%>rI0P`Jy$ge76feGp3Sh2T!Q_9TSpyZo92*gU Y0L`rw4MSz*?EnA(07*qoM6N<$g78@5T>t<8 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-center-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-center-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..162bab912cce0b1c5eb920dfb8197c816bb63157 GIT binary patch literal 548 zcmV+<0^9wGP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?1RKUe;?0sc{F|63j$mGhT`R;uVmRS`v>KW==By m3uYV47UWDYZNMKkA^;}=brcoWI^BK%0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?dsK~#7F?bfjg03i%O(c~t%oA7pVLES{L5EK*(l@$J0 z2mwn!Mg+K>)b%707*qoM6N<$g7?JV`Tzg` literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-center-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-center-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8ec08bde48f8706e1965180cead08fd6516d45d2 GIT binary patch literal 529 zcmV+s0`C2ZP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Hq)$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-justify-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-justify-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..347fa57c817c6cb4273272828026509b605191c9 GIT binary patch literal 515 zcmV+e0{s1nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-BoyUu=)>8>9SUI&(a^nZy!U_OZ0I&i80}+N470n%p-v9sr07*qo IM6N<$f@cTX%>V!Z literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cfc1aa264d875c00d568e8aeddb9c0a8e5cfa9f6 GIT binary patch literal 509 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?g5Zl7P>s0H6YZ3IHtWtrQLP(ff)30000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?QBIBTmWzZzy$y%5B4ApySf%k00000NkvXXu0mjfyRFy0 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-justify-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d36efcafecf3625810061ed176a520be6beb901a GIT binary patch literal 509 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?x01yyF(OH$yhUP?b+Mp9$BpMKh{qHiF z0=@)zXZOjo_B~N=jbat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?x01yyF(OH$yiE0$38lBJyE)orh!~S=f zOaWg4ytDhXI{Tiew?;0O&ItlOqXK{m04e~m00X=f4I0~@mjD0&07*qoM6N<$f~LCH AhX4Qo literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-justify-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-justify-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..754111ba6a8b2326050d942fd7a5a10420743e60 GIT binary patch literal 515 zcmV+e0{s1nP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?yl|F>>Pv-ogq1RsgU900Rc~6cwp>#i{@R002ovPDHLk FV1gu;)>Hrh literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-justify-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-justify-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..01a831d0aed79a780470a9ddbc256d4e9cc5a97b GIT binary patch literal 507 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?02{I_7!By7!b1Q6002ovPDHLkV1k=i)Q|uG literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-justify-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-justify-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2c496fa4a92dec619caa775c737ced5676b41b5c GIT binary patch literal 503 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5p4E!xk1-u0O t&gV(e*Hqm#Y`1-ifXAo+paOsj089=`6b-3>An5=A002ovPDHLkV1gnS($D|^ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-left-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-left-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3b4ba53fb938bb5d481efefdb79254282e1a9748 GIT binary patch literal 527 zcmV+q0`UEbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?H$tM)rat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?<{907*qoM6N<$ Eg7ekhtN;K2 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-left-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-left-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..125832c57f904360410a5eb16399508ced165d5e GIT binary patch literal 528 zcmV+r0`L8aP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{??FWrQ~*!`a8$wi=p9r5Jl6qZ+#n6?Yk6Y;0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?`SR%B#_`Hr&MWh!<(AqvldQObz0d-H76831C=%VGs|6$)7$E?y W?i3ZdGTSx)0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;I@M8qfbx)psoWESQHJf#-TL;0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?v_4ljT)DgdYexUFFO=o3@`nCn9v6b<at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~t(r~rb65eCQ2{^&z-at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2V-q$(BcUa7h4(d= zzrQB}{LZW+r&h*s@>UJe_&KZq%BTRK0^qiS?W0dn0idn}S=at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PXxG~Di{3+m&Pk=d1KX=mq%LPEVAPU&O!?SS^$i;ph|R)p%##6V1@{Uu@n_S S6{3Iu0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?bzFJN)JmEo2;htg04e}(E7(5z1Qh`8Ix))_4MuKI>Hq)$07*qoM6N<$ Ef;VQ`NdN!< literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-left-white-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-left-white-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3944e460124095d80d577c26c3f5fb0985ba6a71 GIT binary patch literal 513 zcmV+c0{;DpP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?x01yyF(OH$ye^GR@I7m2(h=czwlPTa! z!0&86?w;F3-BrvijS~bsMg;&B0E=FM@5wqu1;BF^si8ucmwr!m00000NkvXXu0mjf DlBU}v literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-right-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-right-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6b1dabc93aac0faf457d6f2026c574d5f2814d1b GIT binary patch literal 530 zcmV+t0`2{YP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?dsK~#7F?bERdz#tGt;Xj!qSu#Zy2xLj!L@Nsg1r-JH zece@ha8CkucSO_k8OdE5%j$pcFr3PNXN(zdU@24pPyx_?67}U2Drix=0u=xW5BJ^_ U6_-r4Z2$lO07*qoM6N<$f}&mC(*OVf literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-right-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-right-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d473f98670b3ea5416821bac767279a20ba5a175 GIT binary patch literal 512 zcmV+b0{{JqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?x01yyF(V-H~+kYv0rW7s`XCfs2yG*8l zF9E*`^D(p1C+V!}?s=Rj;4&%zr~nAsv``Ke0B>owfD{cA{dN}s0000XP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?tfG`jR(f_SPi`pu;DD7lD30^}831r@F z3K$94o&OOLcU7Gl$o7+&*Vl)D$+!UE0>J9jdJY!=%XtCAz90?wB8;j40000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#P=k${0z&WmEuA0bts+P!1IUZ|Na26b(V<`G^1j002ovPDHLkV1oQr B+Kd1I literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-right-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-right-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6db72149e85a17a5be8259a3623ad6317434bf50 GIT binary patch literal 533 zcmV+w0_y#VP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?+KhdbIw43V>1o Xsdp3=FvQNQ00000NkvXXu0mjfNbux- literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-right-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-right-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e56d7612b388bd8d5cea46e010e6491cf03d053a GIT binary patch literal 516 zcmV+f0{i`mP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?xKoJx~(Rsg;uLufwBmel6gUO9Mk{d@urqXK{m0Mnw0a;N~fO9ej-6b-2kQU?G4002ovPDHLk FV1jA2+WPat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?tz#tR^(fz3;X(P>v&Dn-_qFw~giYPem zvTOk(0k^aM{MpAkuhvSz+}F+{U^6NJr~oic8YqVffU^{HsuT@rt&;!%0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?|Iq literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textAlign-right-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textAlign-right-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f82e2e3419fdafad55099c6c4f202b575f86ae74 GIT binary patch literal 529 zcmV+s0`C2ZP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?x01y-e(ful+LcM5^PKblVnFxt_hfTJC zk$~UXe5#MRug)q~QW(bxxQq$_DgaEI7RsRl;4KaLtr!iAUA(dY0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?^?96w|6p9+9<12CIHn0MESj{pDw07*qoM6N<$ Ef-*+iY5)KL literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ff9c49bca6497ade7adfa927fcdb427a236bd23 GIT binary patch literal 854 zcmV-c1F8IpP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?bTWAQOfuxj|en~ssnceKSGqYa-Qlv<6Vqj#{ z>Ads142UD>HLf910`+bIeEJGT6F8q0q1~Q9%uqWcOR$44j~@%B`6?U%Dk4(Rma=!+ zBHln^1SI`LwyyoF<7q47=1U0@A+Yoxv_=0-TcV-1i+LFmA%M!H`)vN9?QG_PG$P-%gGO*88FF$qx6e2Ux+Kf~c`TL+xZk0F4!8-AZGev2^0 zstMVRQLS6$BU-_RpF7rA@SBq?xDY!5x%&ii=Uqb?&2g}-=B*s?FO8@`>07*qoM6N<$f>K|Cxc~qF literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..23e25520adce22f0c5d92f427ef174ad2cf2ae49 GIT binary patch literal 828 zcmV-C1H=4@P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?y4y+LvDil? zj?@q9(zVhw7SczRzGdv-3Qz5^^PkDAmm=EWi zy@G&9?1=W|*G<`d-}g#su4uwDpT(n*M4!25U|?YIxA+2b-QQh{RcsRg0000o literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ef44ceb46861cf1948a691980a5b3b7b3f119323 GIT binary patch literal 844 zcmV-S1GD^zP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Ir0_5Q?4gy_o_MQX)x^0n z&hqBt2Dr?uL}t04htDZjp^MxB^uMntQu&2?TX|Y3f)hN5^}GNUEtpxaz$ejaUDRA6SkicM#Y1RkhJEsSFJinf9JAcJzbWjr5;8tj+3AAf<<(!r$-)=A1i z3VO7Fav6qa$0x90lbitvwZ;0n{5R!jEx`TmU~bJbPf*j2ewV$%kat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?tl z8?+nHZ;(PJh(}<9wiA?pK=fU7L{=(jA{p}ICpmXM+qviS-64d5fx(4g4J}4dv}xP+ z9;(c;>`qKcAdX|duIo>pmeA*Uo|i&1?7oGjX#!RY49{_#r5FLd1Q7a1l9pvXv1uWu zB0%AX2ry)trW655bL7Oen1Vo6RnH`G`wup4>4y_?d;+#@FPKP95($_bA>zmiuI+bulIZgngfUAdws`y|P{FGyLfTxZw}052_uGJ&@Z7%{{?UC&=<8 zIpXO~U4!#Z^<3AbC?rBR0j2g6=-~*sW!C=){286NS3#q0e?zlJSyMWY!;kj zvy~h89R6a+J3h;jNd#R_z_~X%3$;Lk7U$Ru3=9k|j$fJ6(|g}!?==7b002ovPDHLk FV1mGAZ@d5i literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5be0501c11ff8f029ec04143be59ca7e196ba52b GIT binary patch literal 760 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?lss%=7%4G@yB|AJL@% zCd^2G`drZZ^eqq>y@r?*PiZ%_AzDC_fEV$r_z7JJQ28Co-dhE{eRF+>E(8#7;xF+; zJU~YR*5&>Y7bq{{2yF{snH?#kP1d(wyt<5vwX}nmrb`Dinw<0K4V?$Km87{Z}9YHZ2H7?~Lny-3GPDgxtnxLs$VP z_DA-7(#9xfMJ`b`psZyk=-z~#>I+}NI7rY0FMbGoCdR6g1qV6F*9%Ty&Y4DUEg1LM qj%FwKhwVirX}i literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ed22130d40f5d248dff33d8c7dfd63f32daadf42 GIT binary patch literal 868 zcmV-q1DpJbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$$=!^GUWdm$MV$;eCyKY1T{cYC*UFSqX&phSrhM+Rms)?RLW z(&X~4dD!-^phy9yzFUt%d|gjhp+ya7O;(UI)UJgn1V@+^E|~0-Pt}D3V5a~;yb~gz zdtqInYbZ*9TtA=enA&$H3t^d`joc;_A%JV&Hv_`wID%98hNN65LIA^DcWCK};i~qS zR)o}pLkp;mZylyOn{S%BUKnFDo{n7ya>SMZL~YCmq`b{IoAFUNBFwc6TYbP9wcdp* zSZQs>wI-WT`;c=_sQx_M?K0UijwqVJ-%@QWRBj01LEZw)+b1*dkl^k2W;UUS>j9FK z$%7n_{#Vj^Ij{^meq&d{x#vvro(juzb^E5lat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?kAR!UBkQ-c*VRk*Xj3P%wvJHoQ(rP@jyP7v2&jJAf0sk3h!K40y zS=IzKfyy?_E5}Tjsk)?3^lXoos2Hs+dq(9{R)hl#Pyat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?_Hh4TW3rdria29H2t`6wl>SWK62e;CUwOEnPkW_dLVk>0hK-tYZ9F z6*BlHfV%fHy6|HqT3K>qiOb*tixf0Q?>qJWVBG;pQA}w#^pS>IfqL}j&JzYxqCLU4 zofTS0@qpr#aeWM#*rt2UE|`d&ItfHVP~o&eipg+#5+asvvllg9kf4;maNVzuRgP*j rS2IE3j?aQ;#XgFy_5uO|0(Ol*GJt@%adr-g00000NkvXXu0mjf>cVP^ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..97a6965f5cf24a007b6d302c654b9440da499153 GIT binary patch literal 838 zcmV-M1G)T(P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>%2K z=>RKGD+s>>40NDYAO-N@+ss}D&A^zM3;A+SB{BQh{BI5VuS!8ndzVdiMz zWHPy?J_)30IxNfbL%R83Fc^8Bmy>4LZ39(R`SP2gxkXVd=mcmbP}lXH5V>b-S=J5p zMS#-}EO4+Z2X0!{xOkeJg@AMuP;Z~pk3+uxPL?bzWnMrUurGmvaRy?wg1qzpU1Ah+dF|q&pny+BRA7o)o-3a-EO|Fy! zn=u)epD)(?NBL9)?Bw)|^tNI;orXffSDJwAJ@Z=pW++W|jL*Qpz~Joo0kIUx#6lWJ QWdHyG07*qoM6N<$f)=`Yz5oCK literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e3af50c47c54eeb6b7964f64abd88680d2e2dcb1 GIT binary patch literal 837 zcmV-L1G@Z)P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}35+zFP8I(5J;M+%l zTLcPU>E;|o3OHq3GoZKlby@+}L$Xt343je9D~rOhkT-+rAO~y}Krn4(24BSsFHn>K zEx#P>tM?t}kWd zwj<=}cL(>pWsf(9(JBPUT7cetxo*M~2*3ZbUd45#8ttqEtSs1w-pPo1^=%tsi#)O6 zC<_}_6<9|vg@5cB$kUrgSz#kl8c?K`X@8uku>X#2+yd(9C&LZWPB-8%7J8P9aU@3V zsm*ZU?=oiAzhHUyCmOwJ0$#|5Ni-*!K;V1btAAWoEXKQxl_*i7#NP1<8_S)b$GJwx P00000NkvXXu0mjfK4)@c literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/textOverflow-ellipses-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ddece63e481dd889943ab43e3bbad793132e74f GIT binary patch literal 840 zcmV-O1GoH%P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?#QbZs8s0(B8k z`FV1rwU7HU)2Q=w>`qY!0m^@)!8trxTwr2($A+wf06TLjcLOgLn@IScvn&Jbn?U;L zB8C=gKgqk^qAZ&+Ti+i6am(hT+{t>LgzmCIrDfRg0h-T;og=vVvon+h)R-#ugyZ!I zySxLv^DrgSUprkf3h`wsB&eEz-F-bMK;pjfzOh?X00x;yB&YyI3D&IlE$T~q+Xq>R zLYCpAiZZMe$gMY^>6C!pFrorOTC;k^t>)CA_$OL2?T<4h_TOA_3%D?}0~Q#S5y%PB zn$K6PjEwe9i^QT`azXwFmZbbat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?BHvy_tDmfdT~ztQl%i zuwA7g2z904_g~Zz@+8o4$&EDL>~g#nq0$?vF*1fu3xp-q>}$Y}Gtp>Z1<(rur(&su zGqK!;W8_6Z%1?xv^#0~a1!84=u}AyJgFvWpE|v%6PAn&X5IYS~M;-(?u_^avhCrOfC*gMc&2UmqXX?7`mh8} z=KT@DVNn_)V@)W}FIrVq~9{C+~_ag(g8NcsPCYy~1I#cWTJU?6_a{AF`}Z$0rb{l>cg^f<*+bpOqg=bF2we q#z6M+Yd{-DFP8QdC{Uol+VKNL)~Q(63RPDC0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?aX*r_?>T9I_})ttOG$K=fFl;sN0LsiUH@C@A&i>*;P-3GwV7#*O6fEfvaM|t%QeG#zbH!&s8sO&jgUX%YC zeGs7DCt}~kF2&xX9|B6seeo_fMKy?+plbqD=9usFxcr-XYwa-Fc!vb);nV55U%goC zw+&l5K*IAa1Rgd*bQH@4JZr+`dh%pUNd|URHmM(L0#_l0ZvxKQPwDv!JCpMu>X9!3 z|1EH&w@}6Fu;~M75fRZ>KHA_`AQn#9o^R%KO+_o7Eh!eLs%1PMH%#nMpK}V#R0z!5 z^Xp9ByRCf{8E#KhZ{#qau6IzK{lZFbGbo-p(kwsLGmeN>at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?uknbN1_WZMKJ-g27p^V$*DF9I68UG0F_n3tAT;Q7ZQe8}2`s?s!Cq z#tLk~Cv5ih$i9Y8$hYu!K$5OU&KyY>EU1(M(`{(+5O1o*mwq` sG_@x-=N#F8}}l07*qoM6N<$f&>*d%m4rY literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/titlecase-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/titlecase-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bbc2fc202d55e0b09cd986f417a55d32c7a58646 GIT binary patch literal 1084 zcmV-C1jGA@P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2+CUKP!6{PliX-3~a0GmUa0A2%OcoX< zEG#c#0V_BG_6fizh;o7?C$NsdiUcZ5r@KcI0)1WO&%(SaF-V%8e%;gkMgT_~al{)# z70$44Tl71pYYC^DGjNS4=Cp&c2CJ$C&y0KmS8kntTa+hX?v?rsuS#GGP2(7E z$hilI&45%f9H%C8dCb8F$fwr^lt1j87ixmm7B8P^!%h)qup+W-ys859+&lQR{sMnK z&LxQPSG9AIyAVz0$cKF&Hk&)(LIib@YoqaJWT$XSPw#~|J5P-<3tQclQR#abCsh4P z{Q@q=E4P_yqv5-}2imex{~ShxE=6lm4V}|-6HsXasuC0&r9XNGH!`AbCFTn$tV`tM zfwT9HGpL}G<|duMZm|b34)J%*8CU|UcA~g6HVip@NL_Q-_r&%9=|zZP@2kf|x-~@z zlz~;1pD%VcLYP95ZOVdASEB?0G$}@^1BC7&JHt(iagnf9nA>)TND{boEpk#beXoC{ zn~`%aDBgxpnw9cp+)}Y+qh3rP?0qh{(ZGW=*xz`w2vI0xEizDiN z+AC8u>8J#q5tnA3AF5@~o$VoM8sSg zNgr5GQ~?2nM&(XUrci{iKD2Jei1{QyXS5w1A!y)31v?3CcoW!^4f_`3kIH-xln3v7 zZ+MaUPQ)!Z+5_aDhEIh?I&er4ZMO!e>uJ=Ym*WQLe={>_Unz?}$({msRN2l&6=n56 z8+P}e98xbvfMME?z8k1TBURMD>2O=*w)PS47XJaf#Q|*?>Y3UA0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?o5@AIFE0aVE*!)aS5h^n+{?sNNxp? z4oC$+1%V2#Zv~i{B$Gc}LjLpO93wG`k!>==%KhPWWL|$`-DoZj#u)DaLN|!_xpho-Sv7M$|s|cfbaVr2=pN)YU+=CCjsm@P~x~! zsYDoqX0z$Z2LSRe*K#acS1Wo6rvpSlw%ct~tyXC$a2zMZcvaxo1MwS@hYmL(olfT# z`SW+P*-T+Cn9t{Lx#tua;$n!=a=A=k;1==KTmmpO zQX&lqvmZudh;Fyr4Qx7a@()g3JmcAHcD`6FM%ZnL2%h7$-q6PgU~!so48Jiw<`2rU zpIxs=d3Yi?zB1o2f*^lk^J68Tje*1imGykBR$~Mhi9t5Gu+~@NgUu!)5>YohZ%sm7 z`*8GZh8xEs>TLUn4Cn9lJIs@?sAIAM?-GM(J^?_7cm#!!Z2^v9Xc91-6qa2U?+Bn| zLJTw#!PtMB5=hZ`z+=#@8FPsu=1C5)#w#VDYaioSo!dL$SZM50wdQN37gJAOyXCdy zZ|ndENodr5lIL7Ozk6%VT(7$&oZZltK{&v0DV8KWAYioKND5#&%OojFEx{AQ)-#Bt z4>raAa92ve=yDS&N17iv^FU9qWYKueAYLefY3B2Pwm19;R7CdXTat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?6+AtJ-l9Ldc2}^Kxz!IDllpO?C06ncK zv%svUFn|@1tbk+%p(`j|0W2Yd5{f}m-;-n)*FQKXZ3f|qT|$>V!3%=#(c;>cD)79n!wVyyKxgIRy@qjG=y%26!+#|pz%vuG z9`4o@3m$Zo3;Up}D!MH_b8rH=a4`G|A7TnyRsqI5kU^b>&+I}`6V4cxfv4Y>c=^FC zT%3M@lPa>OuU@cp^ z)Au2%pUr^8_-W;(_u-GaUdbNx&#s_<-hx574qRR#3D*$YmjEy$I0}CVC3>dHsU@0s zHXhzxz4Af18>^!TO4)!Eq!Wk+QxCdxi0wH=03)HU6XM#6sv##IQpX&Wr>1Wl=^_-; zjIM&APpHOFtM}8@J<<{907*qoM6N<$f?uZY-T(jq literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/titlecase-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/titlecase-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4e75d83a52e7007c0cf8f0536a808fed0d7cbc79 GIT binary patch literal 1049 zcmV+!1m^pRP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?J^>H{&VUex2p9>FxOs>GHUirj zED_kgAp!C@0{2F+-UvJ)aOb!0K{cwu^D&ZleK1dIbx&1K*X#Pth+J^N1z(Ix*@kYn z8&)cnCoGri_4+D~h*dgpNv8RgTbJ=+wJIqL`5C>p9D6WO`yv= z42KbrlzaeT7&f?aUh{O1m^B#={41;gYzFBFq z<)K+hz}LPUGTBK65Ef21+M0i=*t@=CWJj2brI1QOU;DgGo^gdU#`e(t9082o+m5Mu zbR!u_m?B_Wuag2;V>U_Qks-su#!}p(`eUO}@)bq#Qm!0xw|6&StYK z7#b=;o|*9Zv^RVS=nZ&mXJw`T1LuHohmld9PJ2aS<%M6vbAhat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?R*_=`jD$w`O9F&Kd_|^tETpoaygui$PvzYs4JW^bJ%R%E z7)r!9R^*nb$#d+L+!Jgq@t^pqyFdvh|GC|RjQ(#A=#X4O5-7!f~QIw05mF{O@}@IFZZb)RY^5NuX>kGRzgtTJ4{M}xf|R&5Bl zTW*0ob^+;Qzmq)(5iMcE{yN-+D?yM!Xwqeo5iC2nY!UTbSIUuJ1p|HksD$@K5m# XBI~#-l;#3(00000NkvXXu0mjfpV_Xk literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/titlecase-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/titlecase-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b1090239e57f0a3b86acdb4c1b1106ecbc162aee GIT binary patch literal 1157 zcmV;01bX|4P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(*1K~#7F?N;4U<1i53wG+tPlS>F4qy$p|29BS5BB_8} z1waQ-0r13JV8*5bd=(s50VyFb%p|d;yW40k+SzJZY-E4T8G>nB~99b-Dm_K2&Zm=3v^<;-sZ&V!Uv-=fL0i^NmIbbG?d@kr5*T} z0jLCgX$kOxFDvGb-?}?)!#m)Gf!7L;+tOC8YgA1F;t6jGuF|n;IP8dg?M%BobH2<( zPEDnF{c3`rz$-`IeAv55T>ZV7Vkk)@hvAHSPL(5BESZnLMZ=__Z+Lh_NT*dcX@b9U zJ07~?{w-?q&E_Ro8h}c$Z#smxrWN)hJaf-$-3R^>na17H}!$?@j{1ax6GA`BK6H}1ds+_WY0=}~lEoRbsONWHR6N(0E9aW;=)oR6ms za{{6RC$K;+1l=(X6+V{vOb?>i+RpD)wir{I~c6 XK&w5fUNJhv00000NkvXXu0mjfh({3$ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/titlecase-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/titlecase-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0deefa040f65b66a76b75359eb03a23fa7d54b87 GIT binary patch literal 1076 zcmV-41k3x0P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?MtAf*DS zgCrf;6?j~MtqKfRkfZ|fmdF?Dlw@+?<}Ch$o1GLh;b#Wz}rc+LnRj4DQb)9nGlJdBs#1&7Rj!B3!R?o6KJRJXd`M?I~H#yag|x#jNPe$PQm z^R0L1b+MPy#rir~n3|CA8g>#0wGVn=&bZF2n|=_?wg_yQ?lBo9+=Xr_RI~huf3!Q6sE$ejtl062&kp8~KVJQh?9E|xd u>yr`iB=S<$k6B*#*=PB>qqO&UrT7a-p%))n?n(Xt0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?hs2W`U4hks@-D>R1E>*En4JTn>zsBbzUfdRX@tUkd@5fyyrgdF3qYQtK#vgeF9TNI&uR+yquu+RK$Db8>s2hF3Gd^={VV(FG zt+dx^JP7uXjKa(D4i_*&j4*C7e&_bF&3J{E_PsQ|h59RqF_GS-J-k%^Pqx0g)oIP1 zYco%yQ+j#KHc>~>2umDuJP~3~Bmfay&w5fKvRZ%$(}R#oU?O%DDR1r*BN*W{WF$yn zby$HfHvA4<8vzrE;g-0TIJ8gh37+{O%4DyHun1l5cX028`>&nL=*@s)G~-uTyOP*v zY)OU@F`cy#Z6ttIh$q}I**L^K#~uNP0*z_6i7f(5nGs+Q$!Pp*a93$OwYly}b3yOS zg=&dJ2!Xj!1cqY7C^-wvLw(m~{!B{qxg9j2=de`EbJRQL!4qL6_j3_V7#+!sN@eO<0*Q#Oj}>|%f#n%?Mf-5knFnODc#zJ|LY#)9r0PH%Nz zcQJD*O0P}vnae7#Qnvn*?E*1mzIuraD$-0ZX~!Sljb5;Q#;t07*qoM6N<$f*~v2$N&HU literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/titlecase-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/titlecase-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..be63ba9271629eff2ba507bc7a9fba3e52ef4adc GIT binary patch literal 1043 zcmV+u1nm2XP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&}5}jX~u7~SLQDXtX8X3x_1x@NrhA) zurB6WwxM;E(Byi(-nc)CA`AD&@IWfpa2qh3ESJj%NUCGw@%Rxst}(_~N*j&FckD$W zMO+NA2)tRPQh7vw4ieo0;}hKn=|i6QEynkdO8^^sY+;ZJj70ww5)X&N)VBv$_QrX5 z?hdECg!CY7ocOJ6-~+4D!m& zI*x0g2k42GC%CFY^3|skq^#`Sf;R|p>J}8S{dC=p0OaYZD3c(2(K&H3F*W&^DbXMS z7|*2bL2=Ko%XD1=4v}Em?P8ArQl<^VRASM-`!-1?uqMP>nz43X z?rjga7LvG;ns6_}Qz3WdjQI|>g{>ge+-K>{GcK@>u?=KBC55pEw_-{h-55_0ZV_-w zuQdU<#@ryqYuO=roV1M~{REMXVC)ULpU{R0VB@CBVRPRUz=@Ak$C$G9di?^1Izmum zqqAEZP6B!Z{}*d_?2!L~gTZ@;fo|R$GenS&$<8r N002ovPDHLkV1j4)*7N`X literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/titlecase-lightgreen-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/titlecase-lightgreen-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0abc88a2e67213dd5db9ceaaf3137b14191b5aef GIT binary patch literal 1117 zcmV-j1fu(iP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?T$q5oJ zKpZj*ugwY4o}ldsFf(o8jdB8fguXU3Dt|3+}CL0r+4azR#aq>D9jAzu0l=2+B9z;T^T0Q%wWM73bxMBnw}Wj2)# z$VL;Dx`9e%zifIf!*HMDsKVxp&WqLTl0F9f}-z}x_ETgQATUZ{^ z6eT1K3NMjL*F-9j|5&~!$gQcRCPd@mN(d~O${qtF{ee#!9gt14F2^tnG{Eyi(jIx8 z*1I&HJ((T(AVj9}J1X{uCxOcd=XH($2eyH7=nc=uRdcXakmmKZx8b&Ef#kL`-5$@w zHr5MYqCNi9CEP7-=)BP>8~>7R11UA>a-_Fj$Ei{$JN9Fg=q2^f98lORS*s~HBv6mXLY5$!}G--h5R2E3UpuL00000NkvXXu0mjf{jUgq literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/titlecase-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/titlecase-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8d0878e89304c2f5bf712087f2b39ee714321e33 GIT binary patch literal 1093 zcmV-L1iJf)P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?0SCM@%&rB= zo%BqO2X^OjgyVQ%=GY^GT?=UZ#CJn1(8r$9=s@yKI&6CUWY(DgpYcB(KnsyJ0$lU5 zQg)(bVx8Ivt_yXowoU8WO_Rnj{j`oFq_RNB-;uwDt6Ia%nrUN#7w5bpy_0)s;j3Aa zOAI19Gb`=|O$X^>jhw{G@Co-Eo^$I(qwyAg7W?S?NCZESBeKRTP=5t247ITb5SIN0 zPwa-ttwdE@Xgtw*?zxUmO&p(@VSH}-@*6RoasmCV1I&>l9MfNnSuVIvZ*#qOs$(;D zZm!C6@fVYc!Jx`cr31xbH27%KU!ZL>FsE}TTja{owZ7$etU5D3HL3319Iqsy5vTpY z;CU_GOZ%NdrMa-_oW5>i^e&_))WJ~B;v8*s08aaQ|3gMQtUN2QWSnkI8O5BlZ>&*@m~honw?J!y8JsB*mf5q4n3kNmZ`sNPv-k9iXV>!3Xpnf~6a4etV< z5h;)D{6Fv(D2HZaxu~0iQ%F`GZ+s2k3ci95jITSpl`wB(R7jKx=#qpJ?Q3;i+k-vA z8`4*=at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2+CUI}Ba%h3;t1FzRatTb`2^+$;1fU= zw%Hl)uvhp5m=lsFsGCB^_7P%9vFoL1`XYy_ictLkawkUh^HhF z*5D_G&)Mc$!ykMgsR|f2bY133Uo`I(irICvJiMmyHDn_{TAO1S=B<&a=^7?0lEoU} zvEj6-uiu3D_`8N1apLk;sf>++jW}66AN^3lI>I%FMS#7cHIav}b{(x;@d&4Ez8Htw zNjE|ded)Q$RQfU1&rQGau|9aGeb*Wq|196x&M$tcgNs|$zg(!Uif}*@#-YjtXgC%e z!=H{(3)1Td?d|yqsfKvY5D&B8Mu7^Hha;CACxLV`jZYGOJO1adiNKP&=xmECiqJCT zxW={T=%<<^KEe$+MMw|h+*ep^hda`Y2vc(vXUHsFBZS2x&ydVRz}6}!fH=hL`y|tM z%~7!!XLrUm3e#>IcL*Feb(fawN#1|SS=SRm$uZc{Y>QP$u^}IgQUW&jMQ~K|+_4Ex z_Dyv-OG@+DtYhe@16wV}$Z^bJ??2Mqr#FdcoS-rDEnAvpzO9xlJd7D#ax{3YttARsSndq0%U2bTrFe;D}mJqH}_Lw%y$-_ zJx`H{bwVMK_wCy7ETDE4Y&ttu<$s_uL_-XDFYg=TS`lQ&3va{wf_H&jI4ycv=ik$n zP0{1`x)p_(B-1u3W$7>3eISOskXLS!@7CM&ow|@q>d^=YOsJVnED47SN#1LG=Vdf2 eO6?t9F8%?Fbr?8jRs3@R0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(wMUq2w!37tb8Oo<%^}`)eu)uPI z`C6IjhE9mUuhP4hMW1LJ(TUMX!0NHaFCsuj)Nko82>_u`nc!_Dm_tX(59sw-m*+0M zE9y2Q;qN5~KMbjmD2*U^ruKt1e&^5&3t9Y%y^mNe*a>A`cDWaL42A4D63>7HjBp}S z+`T9L%=bYw!+4`Cl6-g_9j_oA%ghGIWxrZu$)OEfD7;gatTa((b^}kx7!mf}K&BnB zg9#`}I1c|#HW5;HwWBjqR=bG3JXb7b5mZBJKqG;|7_Hpq9XJB~8t&`KwH*k#Rg+EF zNn~#YElHRspZczcJF5nc0Lzypxps4JP3*iq`D(^KKc>%N|0F8vVhd zpC})JRJxp+kr#P>6fKua7O(9ZW``vw40MP4z2Piy5gFOC?11lqV-DckZxpvZljdg1 za?fpeGzGqJ1|WfK4`z9Z;_!jHAv07urT3HUsN>y13-Od(Lb@mNKjBO2*9Zs+P44>T m5|z5QUx>)EyRat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?BV>b& zKsQL3ATWWuLD)dZjZB5{BfursANlTlc5FR9OR@s6V#SJU2O{op#6V*MOM{%g-~|U* z668>^W5aU`OM)Dh?AXpNuhm4|4PW5zX_HQE_<3Drbd=C@XqeD>U&+0it{`HA$;`qZ5{^<^aN2OhlJh1CvX#yed5_L8O>qe!kAm@Tzfi-=QoJs1XJLc zX3%;%u4Z-#yS*QQ+kj9BmnwdZ*xJ*uQQ1&If57+KDTpI=_C=t@M5VJ#<>z}s5ti8^ zMA3R7O;ShF;K(=l^Yxfe5yn_HkU=O?=)HGdyYI@aQ$~9h-cBIk(ojM8A}u>?xvn5f zU~bG#fK#wfoMr3lzXV(gpHXy5n^JLB!(3oTCQ^imfhU^(E&iT_g0W3M!r0I(>~Hx< fO{;?yD?EGxaiW?c7Honw00000NkvXXu0mjfL_~nb literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/underline-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/underline-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a398607880428e1b8012ed136d7a94939838f218 GIT binary patch literal 692 zcmV;l0!#ggP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?wt?wM?Yc{ZkloRs(Z;RWp&yZ^})pE3UN7x zXtWOcUo|LI)tPEep=VB8RPG%tr#Eg}{s{66{5tF?F%j7zc3uGC3yLE!?sb14cb}B4 aSa<->at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?A;cQp)o2r#b%Sat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?qHnPbf4x4JCL9bs8eKtw5(;a@hmX<+p<9(at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5Y!!!1XuGV22M3K`l+Fq0Bq;Y=D0+4mRTF zfXX4-qVssF_$Jg@oUFaZ7-I?{+%esuwxu+==eHabyMKxkcMB}|NT)(1=uyZYe6+ya g>t@H^CwUZ;H}ZEZ{m=XP?*IS*07*qoM6N<$f^GyLegFUf literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/underline-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/underline-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..dfe7febe7fc3bc4c3c5bcd0106fda31ef1d673d8 GIT binary patch literal 701 zcmV;u0z&at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?B$Pty7ohczrp7ABv=FW3h zKD`PP&Z6#S3Lj8VFk(OqhygJm23Q72!O4s(i=Jm|D%*A@hm@W3n*m4;W*j@w(ALDU znwYVpl07hB{e~&-+TUp>O(S&##PDIUZjK>f7zG=jQ`Z3|r7I1R67KYW>pfB)5RGh| z-qBIT$rzZhFX6c#>cZ60JDsPCQ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/underline-lightaqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/underline-lightaqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d621a2bf41f6c6a41af698f5b3dc7813a6bb7fab GIT binary patch literal 672 zcmV;R0$=@!P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?O|40L#4BjXKD-cVt5=#I}u>(60 zJD>z^8c*Cj={h6PY!(tG7{g^=LdYyLvp+214`3L^#E>Q_ySTy;@=tt@skd%@b?)2P zVP7t(zyLE$j0rFSCcp%k0G$9r}GNtn`E3u=B7;86MDGs3Q?Qy#=66sX)#V5d9r zE%TOYEat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?`zvsWRBQSzoG~RRsM{ojl0_rGk zzy^9Va*+`jfx9ua5JTWWVxuu!`ny0&`}&dh@>;+!jGl3tAi6P0WK`L6*O^BNb7e4& zv~YwE4A3(szyz286JP>#0vLJSq&o+G2wgp&m-Cx|A<~BZz^)@E@>ae;fvOu8NT)l? zV^woyk{y?Cj9KFwBbH9Mfr1gVJh7F(EJOrvPauW%9g!I(I6#T|5Yp0RB4RB?Pi2ud zc`*ZEjF3W?Y1dV6K}%4=Gs&Koh8#Eat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?$|z1!(=?@0s+jyVO=tJDZR;l6 zId{#ntb{LUSQ!x@0z`la5CL2P)_1zDi^GJOn1w$I=zV7xhEte;vBLMU89jgjs~Zy7 z=_*`y?~O`5ak-Dh68{;+v11;9!3LN_QFO#pR#+?^i_&@y^GKN1`T|VYAE7aZUc5*1 zHl9Aj(hPt(hH`-k`wBwpx=v8YmTW9+^E~fC_<@fr@aMWE2vbyGjo%N&a&H O0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2sa+Ev3FpP#FjcLfKlS}f@871_>$AL`6 z=kS3D4PyZ;fCaDs7C;q%LFZ79c@vjC19tJdXMPIMfp2&v3 zEt=F=WagZ9!2N@Gp+r4`GDCJfN#8AMFU>P@Cm3H)8A0h>_jk(YN&6KWH)Hxi4Izg{ QdH?_b07*qoM6N<$f(ghe`~Uy| literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/underline-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/underline-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7542e980496c3d7accf02509fe5c1e03805323a1 GIT binary patch literal 687 zcmV;g0#N;lP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?c!v5cAex^srn2UhS4yjY4ST>6Jb^4!wJ={i}%b$ zEYZeIX^juG&@d*z1egF5U;?xP(sJUD9EA;jTdAe^nSd59Z)t{k*h1}>Sv?Afp+Mz^ zIq`u#7{gL25l=klfmmQacy<=Y94WR%2TC}@Sl-f07(GjoSni^xHQ_FnP@?__-HZ~x z!pWhh{E(WKG@k+F@PQjsqTN@01tEUVeOcYRCydlh=mO&lDpydR>;6GFPuj28xB(bg VKMo|7$Xoyb002ovPDHLkV1hHXE8hSB literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/underline-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/underline-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..116ec93d4a3cf03a49f4c470c31104fa92369215 GIT binary patch literal 697 zcmV;q0!ICbP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?v^XVx%P?2(Wi!b3xayF~Q5MEcpaG z2oSlUWmGX+_PVB%iumEpqf6br$6mQvoTx47n}-m(qQmcN%YGX^QX#K<_myM9WQ7&b zhY;~cIFBfz1TEfdZ8!N)VrM=pCTPqL6iNGvN8mH4ntINlWYat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?C1f&`Rm@@PLpXvq$tYB7>UT)U5T!E2l2^#(7DdEg07@5 zOlV}(fErK(YCsJL4Y*q{v$;(a$yylmqk(A?CC^fgE25Yy2@w4aAL(s&LA&ZKF~aM1 zya=C}+VF8h0%jz}Y|(fVwp~E)@*W{WyC)&yLumNGXxA8?{j5jg_q;;Nat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?5;UZG# uE1$WTcg}Sn7g%h;)|=0yppeEqipdD;%Cl*e?lHRn0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2+CUKP775O0LvBD$U~&U|0^<`HPJme$ zY_hPtFv4UJ=LFyrI5`2_z~lth5m>4GopE>1NJvP+E~>n;UKNZqnwft6`Xd1pDDd8a z@K!kTs`Ot4r?h}UcMcm7=y_w%x(SFgI6vNjm*Bb;2)5b)`he~#u_p^U<1bk|h2gOu z-{P!2P($5}x=tR|*RExcgRN^??8-fpMx2ldGK>pxMCohjk81I4A94@u4jOb=m9AL6 z8Yoq#ahAJY!PKlLgI{i2q{bq7-kD3RPT=uzN@Rb8O5`hmxGSTB9bgFo+qr8Gy`~sv zuSZ9FDdUXMPnT5q0~{I+<8V5g0Lv+{2cMYE==xGN=7j;_#EvakhldAOoZ*mizCd0G zo+$R5p2jdhiDXr}P0aUUH4KMmwaELG1WVyUl=&8)%2vP;Lo_-Q8CeCxyb&^wfLJvb z>OX9NGyx-jJ>^jthM?R`tk-A=X;{DpNQXeFrnCoCmx=i>3??}*;I-&_H@2FRaBzo} z&By^~pWUH6fQ+PDCQz8^sO<=qOag#&N#-S3;c9r3B)|rheTX=w>+CawkKE~8>&e`# zbG9?ra#_aF9b5?si)0RHn|#v2^l9p6>X;YoMtdYr(0^68Gq8_Dz^&+$3+TVJ#IvZCkH3kca#G36#sfsr)!x2hqHPd!)crh-qk$QZt(MEoqul zwp?`!hJ8OWEC0+`=^M$`^Zs{u2|aHr-r7=1JmZ%RQYGn?(qq|GsRO@~-v)30LGnZ& kBwqu6ZCDEwDDbZF47Nuexpl9>H~;_u07*qoM6N<$f(b4G7XSbN literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/uppercase-black-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/uppercase-black-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a2a065168e10d60d42b26ed016956d924d7a3fcc GIT binary patch literal 1093 zcmV-L1iJf)P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4ruit}_Y7isVrpkL+y(%$7Yo=fSrbi+L3cPoe?Hr7%Zw3#$0TAJMjTb~adVJZo+_{`R~h?L?!c7+ z3_q0llJO`>1ESN;Y;lw!OSuDADL@|EYC6umI;8;*i}SnuCG?}LBRSSr2BP4$XiB8So^)WQ_<0Ph1h6pAW7%Cy_Db8)=+qi!-Dml!wI zM|lPCX38{}Zb)_M&^T9@^PYgbpZzv?lMj;hdL5fCr~(BF6d?WpA1q_qz00000 LNkvXXu0mjfVhr-_ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/uppercase-blue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/uppercase-blue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b484bbb16b106e4cca6c16618dcc213349d1044c GIT binary patch literal 1129 zcmV-v1eW`WP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?-DYZ{un>XH=#s}4AM4?4Z3{0UqB&b{F&Ds*xH43N&9(76OMLon7ll zbOU4BFqIuV4?`zz@_~k0|180BxKPi0oL(vkfhyu%f2GeP`Gk2mW}d-|a>Z{ffII

}2z! zzroC&^OFP`XS%lo^&^=&ia=7vrk}kV4jHAr10P8aEX)!%Us zklAM8St-kDbVk2`G6K%0)|)G4`X?uhBmpH1+9M)elRP8{ z00?!gt?m~#6SW}T)G*8_GmeVK9r`P)QiCCt`N zrNL;+4sggWP8wN}@+5hu8rGBtY|?rS-C`b|s#jQzf3PqK*Iu?>aoe1bT@FRaIT5nL z9`rI&)}dZX0_S&eHYxAqHcW1^du_d^)lYZ{ow%#k7Tu6?=~%lno$0A6J{RxfY-8r% v;O%}$_SmQuCSlwFwOW5}SeIC0iFb{Ef#3>_)KsKY00000NkvXXu0mjfG}i~B literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/uppercase-darkgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/uppercase-darkgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..825318c12dad63af73b0cb916dffc4f6784e6058 GIT binary patch literal 1075 zcmV-31kC%1P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2$1-Tsen)c zP6fML0pt$}q$L&L4w9`Pl)yi)J?CaFx)>WGq}`wRNMB9`^_>@%7Ev2-*q^^LuLK4y@)DNXEWscE^nMb z3RCR)g<$|DMh81Z3P~p^Lo`bq%rJi9!82(X@(20v$r*s9RD+3FFXl|i#)wi43u%Su zL*7d+4a}*HK3`yYC^KK&xk3h@@LnStQ<4RGj``SnZn4|#LOt_GuE2={q+hh)+=y%% z;8b#?!1IhltaP~oCn-RIB&zVqowsSg!{YoY9|ThLrYXv!NoG$RV4iWnj0=kHP(ZfQ zkpeauG89NLc#W5i{?K*k$N?I(i;$xdg{%#Bx|CxypI5L(#WzKJc`e=lVB|MMX#XG8 zfL1x>7~(Pi=shNEj}X=gud95ZTPjQ^gwy8zaKr$soD!XEP}EEa7`d^=^mf<+9qN;n zSw{4Idu6SD&sj_$0!CkET=DEWOR&qyd#)o=tT(C1xG7$@VYv(#T2WNbat5Go3at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?T8q1SAu* zOhA}`b^@|N=>*LPY(OO}Q=N$uj=T1w&Aao-u`TOaPc{G@I{bG;_#tFjX2@_mP=AkG z2$18NOiHb!{s`?s`%x6lj>qGiKKp9wK<$-UPHQUd(`(r?c9tAtGzT|i-YIw{LnXCB z0yBY>=V{$g``tBcn82ox(>D|{CBoRrdJZ@x|AV(*MrO(DsQc(L(UgI)*oB;6hA`Pw zg0oalesD!#1uM`7R!r+%K zQvn!*x`li#z3;6i;MagIzPzTbWPYqRtYA;r`dSKxnz%1PB6d;tm`K2Z3nsUN!S%9~ zRw95r&-r)4z!vyv|DM`7h1IbL1sA+|WZf&b7h+qvNp-at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?PA{W*XQHhAkm zcqKH0FD|61YZJzQyQ3Mrgn%>NI|ogDJ~d4agB^GRt-x#jORa$>I$^`DVxItFv@o=7 z{q4>VqvsR2@^AU!%GyTSxjPJ}b!VG_=c)uJ`T3YF&k!*JEkvkI#XitZ(hV1iH0li6 z<9!dbcEu2f(AL`O@bOo2-HfPnBadr*jkTwGQUmeSw^UK^4udL|peIfM z;RRSpK{~hkh_sNuz#jH0bq2(a^Bv2KnII^}l?)I$N~m98y2=2Qv6 zRuusrKrbAX|VFi|sQql~oes@T_?pJpwIzRr0Dypdl;=oLHZ z(e*GN*`2Mcy})!*wR2Ov<$<+O04-~m<&k!}fi*}P`oc-@J1?bJPl|mu>T4S(GAsCA z@K~v-xr`WEl+`*fQaUcTx48}To9tFb@4Op)f+xVnClYPd4Jnt7#eat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?&b11K~!_L@?!R{NaT;z)eQ4Wsp9_oJx-%7Uw9LFgWXUz|xuJK2h4uZ(Qg>?uTfO{!R9R8M^QU3s(=J){AcKw1|efkhTl^MOwMe zCBUHuQxg0vd*Y(67FZSWu4QJ|-wRqII&`n+_MjG@dM=1^&kH=viWDh6;tr@e;0h$H zMwF+4G)_wgQrB)7wSSGK6in@!(_eVt(vTJBDQ=07tt_sUOX^%(*BtQZN3H0xG}rct^Y4-aYB2ZKZxwi_Ego~yffcPt?Z5#G^c5Pwc`zy2Sj(lf zIRLG4v5}s$XFoMKFrXprhH>tI)(Mp+qOHXMx~65O!cIltC+hdZ{zkrW{7S9TeVMf^ zt&Eo*zAto7|A!8|{wi~O){_f7B~zP6M&C5aa**x!E|e(W(<$dhc1Q!4{;2hhlhspq zwisADp5}4MKpP%$HvGa{Hat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?D4_F+i_r$-|U?AqyGdX{7`8fH@J)`R}0cD(2rO^l_(rXm>l>+SKkl8%sxzA(Rv_Df$?CB9^ z>}gz*cTbuPx!~y?Gj)}p>0=1%pZkh(gLe-z=37?KmD#atD|F=YN{MbJqXc&%Qej@Pg#-Q zDF~h-X&|d6<$@h9qg= literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/uppercase-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/uppercase-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8e9c36d2ba73218ecb5e220ed12d4f5bae276428 GIT binary patch literal 1073 zcmV-11kU@3P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?C-+d}(MYzbvVW|u5;K~k`}ONXC{;-%UtMbIgJiv4 z2fN)aI3AB_uh-kCa{#PXt1%P|Fikq0PG7xl)IS^!L)^K=t8Z+jwOVcJdEU=ftF?U( zfCnfGILFxUcDqT5@c_nWaz4egfzd7AeT)}+9cTI`BaI@3%jGhXOFVpmC&ZH!oi~h6 z>-G8#JWb90#bOZy$Q@Xi0c=Y%;T0*w;Y;y+q@F1p7M%rC12N7}UD?JdU@yk-2amts z@5g%G34nAm_M}i~zvo4G5h}Ob@rRzP62X3~p2HI|U%2KB0q6{6q+zl!B?F-ET3KP3 z&*wV6iJf4!2s7WzH75g5c%7kZG$tH{g%s$&UEd$X2M~J zWxUnzI2V|JUI3s$qw$Q%giF8@J6+5EX&e-M}PT?A#eiF-ox+&74T>) z6EAfbVy-byKr=gDNC(QgrRZSQFu^xD0L*d$GHSQm&ZL3|^z?->mMgm)A63#Vad&8x zY^MKI1?*-R*taLHPG*4oC!R!lO}ZRC3Q4h4QqH)Ns!%%!_8YmL>2E_aqrtB5B zdL2ryat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?3+AtJ;GAZ5C8@MM3-SsD(F(-hWAaDZ0 zx-&rui!Pg<0CIwo6W~S5bV*N8_XgfJ0lj|DlE8pX8fLNzA7dm-@_XO=7103)Ja;I1 zB1HT-oYOos6r@x2X-4}Hc+XcuB5o^E@eg&;pa+%e+8tH8MCKf?wcJ(;8RHjZE@P#W zM-aIDjUkkIK-~DQbX<1!E$c8KHF4)fp;(=8Muh8r9rMOi>7_@G$^?GoL2E%K1j8AG z)D5W!%W>KHm2x$%lIg^%pROCDHTL>=Ch*i7?}?yH;DWg6#-3$P-LkU~-WKH&s;Rm- zh46Iq46N1|zT&CfQ!rc+FMzmHVvlL^)4KgeK0IL^Q6a=KBE+~uJ5VLoVhj^Uk}tAW z7y_`0-1Nr2^B5uMG6iR}5e8VF#aFC{+Y{OW=b2X_X zV(%C2fh_{!esPhtXsu+jF#M&Uoj<>zg(sBK9yr=&q}npFbN_1Hh5?KvIj`wIkuT*9 zd0AN(<-nProbVu8-!jVt@|lhhq$pRJ)~FC_hEh)a8@>TWs)y_l&SQCxJ>ms9>_i6OE#0gtOD1~YGQqv zasi@!Ye&`cYg5(Nwqkfl`^wkxa$9B{z%#y@;~Dz*(-L3RKD002ovPDHLkV1fr231a{N literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/uppercase-lightpurple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/uppercase-lightpurple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..6eb9cf9f06c8fe3c77300464b990db44b07429cd GIT binary patch literal 1093 zcmV-L1iJf)P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?M;06 zNM;gYg$RN?zAy{yLm-{XjF$mdrM+_#<8i0m)(RsLT=KD7`6)*Wb7|vUJT%$g5ctVU zr1xSF$LA((bpA;q(?;Uf=d`@wC&StjIq~lWv{O-}(`fLE^tm~*hJ*&z=qabB^%duH zIl_>U<{S1t%fuL5G2(}x^qSR#!MLf zN8WbL3N!ycNI>O;<{rr6wD0fIFL-2drJYvEQ)=Isr-pYtPH?;nUEv#rXk$h-xcW;oEwPKq)^FD7vzM z%1Uq9)F{C&!YJlJ>DiKr{Nn}z>#$g$l|574gSfMkZes73bkMfMk3&nfEvwH|07CRkMIwH()- zX}!29r}H311HMmXBo8f{7qL3HY1Y-~LzB!y*7#Q36l4`T<=n{bsl@gq3_G{QTOC-X z0%Tu|-h1bu2|62=c+d5kuFI0x3TN&-=$j?_R4OftkMl#^>B#G_+TQjwbSIg%OU9yk zfk!~&iAEbbA>E;)*Z&**mp>#t1F~IdJ>Y-?o;H31Qs)&-;_?!800000 LNkvXXu0mjf0UiU( literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/uppercase-purple-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/uppercase-purple-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..786102a836a7a9dd3f896c359812fa72eb9fa837 GIT binary patch literal 1133 zcmV-z1d{uSP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?2+CUI}BWzbb8*&51Bvsj&+yG8sd;;JE zn1y3@D4P^^7I97hIf0!MSVthcR3)~R8?eg4py_mvW{4~#{HgNFdR3|(hEezH?+7SS z;;BR7kuZ2iJ{Isjh1sWHYKn&tINYW&0Uf0f9$ly=Zb9Hv^{FZcPWrv93-jx)81 zkE5R|x-)?f+jPakm$m1iIr^=_qO${^eC^@fo)?4Sb;J%-6`@Xcf1`qCIwBi|#%t69 znU~~nU28O0hDGO>#@W*sF}gvdW*KJ!7Q;o1b575D7YVOOA+z2!2Q>P^oS$CN*@GH& z#JHsD_(JVvjSG%1RlrgB%F8OvF?Rd81SFg$_Z-4eq(WYQlNSeXs8K+6XyhikScADn zAkGk>A@w4AxhaS%Xs}XP!>D*T;}rDx#Wpf&ICx8S#EJLW0?XngiOj3?UTy?l+-9Bhd9v+BNuAsqD=E;{fU@CtaA{y- zQk*BaBhsy$hHLA*8ZhCH`N=7|WdXTLSJrcNbMX8J&jTsu zrd*ZaG{~e2j3+Us+B1fB^3Fq6)dk*u2J^hnaW~N#)4|W{^Zqtav z97$xvfpyc;DyfTjwlD)OLjY)rd>*5pH%tVFHQLEBCiOC;WFCY?w)t-9ksVl0|FR40 zG^>jDMaB(D!gnKeLRKJCj>S}nF~L)F6XqK?#hV^j%Lpjg(Tl`D5w0~RTOPhpQmp%K zpGWo{@qHk(g09hGA|Y(?nLXF83f**jo7>RdWLHwHN0;g~ZUHM7Lyf!}QZ60V)22-8 zN!Zy&|8wTs;L$%wV*Vg`IY+cEttCp7c-r^}rMWT~s^|*M00000NkvXXu0mjfD0m5c literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/uppercase-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/uppercase-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1a28d16c6f945d94149cd4253cea27e1bcdcfe90 GIT binary patch literal 1026 zcmV+d1pWJoP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?n(2yjyV3zVS%mhk$0$ZSEowwNgBeQ9OW+hkj=9HD zi_RPDff@k`e;QelO#{GZKh)?rLbbf_f=CL=zQ}1f?$VG@ao)p@2)A-z&u;4o0fpf= zqFgJwRRQ@*UoIq&U5H~&NvyoJyQQ=l8<0he`PB#`4bDpP;V>4-6hCZ@q zCJ`avi%(7P`6FVFR*7j)=Z*l?2^uXVGU=vnDL4^1j}hnzfg5BVEh=<&Tz6)uUPjUn za%cc{!^}4at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{? z1Z9JE1K1#8f@A|B5v5UFr*?Y43;ynOzF3m=V@VD`Lc)JX2EPPEG_){vS(bgkHK0Q( z>~V;c&xu}$TAZSlvkWW&Db(r^8;~_ho(&$v=-%01L8S4uD80*CLY%W~F!%6F<%EF< z2dW`*QED&97BN>v{B4ZfkWNPJDB2nMTKFb#ZjNJpD3a|1MMH-vIB$coyy{g8SGKjAy(~`FyZz-me0OJp0-X$C159&p=Yf z(Z|&NIjO6 bLW1B6VRMUn(Uc4>00000NkvXXu0mjf-~M~| literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapColumn-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapColumn-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..242c54292132c828b5fef05b7d938c818a3885d0 GIT binary patch literal 872 zcmV-u1DE`XP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Q6FcmnYP%EmoMs5j_JXG9ub(t?Wp7bt^{{T3zkz2^HRP19GP(3-`xvKx*` zM+?4Bzsv(?BXpWWETL=wwr${b^A18-5mA>wP8J182au!o@dyZ${&`?*0O3E=l?K2M z3CavJkI-!mps93#bEiipRmyb9e4j?@ev6;AZR+My!EL?m&}@0o5KoNC(MxlM8euNg zy|5`Zq?Un~jT$tS3^4I)p?N>jd@6>kuyKl90T|m04Q>a@ z?$vQT&IzF24mx5OA(Mm~=9|z^JV1#XL4##m)q=Z0I^Twd(r&@Z6%R0(O{I&q0NgbD zYKxscVyjU(G1?)B73&wTfdb&a0F<$e>JHTj!iy|KR3YP6!Fl4Fba4P>AbP6ZysqMX zJ|?RuCL!b*JFc6>Z-E+>2sWt+Xw$-R82K#WWECZ6AVDQ8qo;=at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?s4Nk9+;-fT8|hZz>QQwVwdt&may2rd!)6Q)F<3^VVc{#q`V z9_l-8=YB$nhkn1`BST6BG#ZUAsuoJRSS)TwqfwgoH=E54M7_Ywusv5vl4NASh0e*d z$4n!(5&U{PI5QrP<9fXw!t~MSdor2CWPs2)=ks}6nNd;j9IyPrmOPOmqQrlr27c3Z zQU{Qi-ous!WJ>_{Hpm4i<6}Lb5OxIQW|B|^uu3V{d`FN0LNlPJ%u1&^C*YC{C_4iO zN4Ek}nJFC*cb5aVT7+}J|9?!!5WozF!-x*d-#r6o0VgBCr9HrJ+QQwR6(u74l;bsR zxvm=_M@Y%G0L~9lb&)Tug=`1kWKj^oO`ToiXcH10)9ExrBElI}h;olNfZq;@l0j5k z*_=f^b6@KM7?lleL`c=lwMRQrII98*L~N)O+=_q#5tV~m2N`lGrS#~`f8qz}LCk9M SEftvn0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?CncUxqJpzI7iE1ZjWVh@DgXX1_yPT-LU8qmt9T)k|b zWfnA-^es=UBM>tipW_>7QY|1Qsvz+Tn@{2CLq6gfMg@SLss_)MY54|}m)^$RxCwIt zc=JbtY6xDlF@Yfgu38Df2=xf_eEF;}Az+W#*~n||YR*EHe+&&MwoJKzbmFL4hz-&x zjXYUC+*sTS1lWpzsfZ2pi}%1zz<&|Yz&g0G@Ch_3G$QgSXS6Mj@ye5Qbpg3k8i*qp zxSh1Ylf_u>qF8p3y|OZ^-vYTR&Xf;GeeuM)RFPTp+(r3SW%OKe5i?7+SUD_pQFCb~ uSQJsSd7f&DsR)hc=IO+(>>XmqU*a3t_mD~L{7P&90000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?b=0; zPN!2(QX*DBr_*^t=UsZL>-zO*H1dP>?RL8l^GI=<&F0ecyp^PY7F9{_NzQy2If0?? z!_1L5O%IY1kpkB1^`S#}KMW%eV4&>16e$42SF{*~=csmS0dnX~Oj%2c5&*OU1aWu` zev?~3z>|d}gU`otSL7DJZKkq`RyB8tvKNv9aZ^w_P6~i0ma@K_L%?`E9)i4w{XdWr zVMJ9@gp`cmy9O!&|3-izIe_E3yW8znVSxy*a>NH+T+xv?sV*5o0+7#eR=ABu!?@g};PPOoqr5UUGO>00000NkvXX Hu0mjf6v2>d literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapColumn-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapColumn-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8262e943ee21459312a5949dadac9abe5942cb68 GIT binary patch literal 807 zcmV+?1K9kDP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?>?9vTw56g-z> z0A2=|B%-`Y@_jU8)7MC+0jc@}P1Re*7sHskmh*;N_T3^79|JFxHR?(e9_zjKl=39z zE_qlYfCb#iV@Zy-Bn!|?eZ=1@jA&qG zCFtVa{?A|oRwV`e(4sK{aLqs@>bt77=mi4kx&)KsG7yVu9K!(DKt|c1xy2@7>1q@c zlk%t6z--_&3@kAK-X&{F*|rg}Uggd=={fo*k5TWG?vf3s>Ls^5oHRaF_~UYcSwTR77vbB)t`1`MV$R%bL*^002ovPDHLkV1kX>YHa`j literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapColumn-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapColumn-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..57edd09a4ba8889f3461eb9cc969ca08022b3389 GIT binary patch literal 912 zcmV;B18@9^P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?~ZJngB+UY?2eM{+f?^3?a%9Q1w1LdB#LgFcjjzfLs9_S$3Ki6P;=% z84TmsV1U4a$rV5xIq8^g?T-r>9Qtjwv1cNdSC}JK(V`YHzHUH6i0K#S<4rtVQTct-L%_{{-3} zFsD8MQno>Ks;9~md|J4~Md`Hyj9hURBbMxY;vmmOjZ(pk$j(bw>~AOyR5vYNih%DT mOp2F|_2Aa^I|P>eCEfvRY{3I*)LOa#0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?!#oFhs?rxlCG zH)9CK;eiRU0i^`^6KTsn?o#8+L`HD2u8@@i)N3(#K&V`4baC~CCcC&rOwT;a2URxEAo;R=ov z3g9#+0~!Qb#urfBjqPr5i7Ew16FqBSj@zPsHUM>1a2EWjbWxQ6&OrCWzzQhx-rmem zjR5~C^~7L|azttE!GZi4Xfmi^zi-*7j`YH%c?1U<*fB){JiRcoBW#gYUIPO!;69*% z7-AO!79y}^esv7g0{(}97B+y(w9jQ4XC)$O`qpPDJW1CUkY-9lO=*s&6f*nPX0s@6 z<;oy$oV7oJdbP*{coGIQcy1d6pDA2&J_JSMIAz6Id`ZcciSn|jN(JPIC}q4-R7CGZ ngk_Qj;Lk(DzWzg?<}dLM4FI1R;Be`*00000NkvXXu0mjf*D8KZ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapColumn-lightblue-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapColumn-lightblue-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..44380a96aa6d0ab5da81d8a7481ed303e2835bd7 GIT binary patch literal 848 zcmV-W1F!svP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}Lf9bBMT+^8xFtlnIZYK%^GnvTa$KM9IIevHv}#zwWU%~D4!$se zg2U#agM~a6b8Mhe01Rw1@B_Pp6t~M+MpZ!y0pv5Y?%;`Chs|S~G5b&c(q{isKL;#a z$s;j?p^5=s)r4kgS7%aWbSJp>u01EwB02GXU)V+EDVwo&Z zPOb)VV4&<3i2i1Q%I#{Q0Xo=+fh;tvYyh=BU|ci-AWy`UX2c~OV~gtMIW@#q^@sOB z3$QByU2Gs8*F&b@r4=IKRc`Sr-^;&AD+B0SVFDi*zpJ706TVdywTvER%~Sam$TMc8 zqC<+or!?20!$-V?bAuJgo5!dsP6hcX$&zxjs;F84G9XF?uMHppQ95|-l5c7denYhS aPx=P&T7Urn(%Uou0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?j`_H1YxT*c7A^KzaR{B#DjJ00y^s|3Ypd-Kp=?{d_*( zil!<7T-RO0h(k{e!?>MJr+&8na5$_`_d>YwczlieKs02ORnmJJKQ+uTPGRU*$aY9p z7>3WHsZs#U`>8{CxXCk~3Xrd=-IH_)0NwC`Ie#l_q!u8D-rDc?6X_6Ok}*)F4?eIC zx&g>|a+DgvH2BQb8POhq+e{T}t!gY%U*%V#p{gn9U4;Pf#AeR@FFndEs+i4Y8yrFe z*~ujUQV8i;zjqA`0RINSlorA^b#Md+d4UM8a$L`jX_}=sX=4Byz;(S=We0b_SskM& z9Abpvr&Uouji-QKrEvg2HYh)^%n&UN;dqL21j_o+ii-1;3CYeoE(qZ|2grk{YrHdn mEQF5n&IO1i{~=`1U(z>83dAnbrg=;N0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7s=6({*U$q(Rws!FD_x6M)1Jmr7xd+TE0lIjAMd2x2e2^OI=i4RmaH{7m>4MvzRg$)u@0H5w)5( pCSXQH?dFYh#5zp>Ltw*S;uB_ol>$at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?q?QRN6Qpd=5yA$2E|BA#xKgMRH(#Zo=Ko?h=lFi-+P(|WXv?A^gZ&YE_&^s7 zPkzqfV5ZJ#iVDgFAdX%7#EUrYrkDdJ^vi;*1@Q0LqZWMWdWfT*@E6|YO;=t%HqXHh zPShDqP*7_Drb8Y{(}Rw54@&hZ_yPF910vjNII$m!eU1WhY(^cuagH?STI!Mp62?@z zE*7{!L0JLNG7~x&r#WAWfjiyGN?fB(0GaS8a=>`DjWZiiFTLvzxr4d@B(zS#fqf|B z)pY9tNJKJ2J_RvJd@3pf=woKue7l-r06DS;C?E%0RyM$LDNSU*4xlb*EXS+Qt@wy- zN^P4_Ltw-D!+W3s*cE^_DoC#Do`f(@D@3AH?no-%w`bDQ08ym`j1U5EPuvT`6`QG| zco97sWX)6hFHlz$NCu29DGo7~)O{Kmat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?o@ctp(U{rSOqLR@|Uk zy)xINA?8ZWN8xf-y4)>2TR28a#R3dXKsIQHnUBTem!^A!JOMcEJI3HTZl2kID)psv zo2tkQfK{C^h!^2jHG=~30cdQER>E26A&CT}ZpfU9tN;bl$4muIw5w?hAh3=Un)L`4 zu1J94XDTHYsFkRJtG;ME6@Ck>>NEcR07@Q1V8QymdteFhZva-1L5&KjI>8SsL`)%5 zw~Fz(XZjfyk(Bk-hNm97K$t=Z;42WIHQTvbsj195Ru zRmEYND9NS+%cv@9YF>6tLnJjfbMw&{B8_?OayF@^{zG7?zod7eiH~@g|M0;80000< KMNUMnLSTY&439Jb literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapColumn-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapColumn-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..603d9823187b5224b7dbe5217c7376f26368e4e6 GIT binary patch literal 818 zcmV-21I_%2P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?N!RaG!j7KIoCIS{F1N&~>wE|4m*@yP{m061|{ZIN7C2s9?Lf%ot7A?_0z-q%a zfXVcRB%l@)M_ z7O1-gqr)Y@vsPh5%&G!xyoi0E-5943kc+^`_|rWw2{;b{GxPv|rU6Y-Hi(!at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7w{mr#Pp4x;3wb& z4|42`O@LrOAR>pQ0KIB8-@guf2+$%BnZLdRNk9_dM7{fD*M*qiT|wAtSbsxDb3v}s zLS|xmi&B(`fw2uqV<~BQds^J0Vu~<{-`pZ%yXG?@wr_5TP`hE+%{UR8548$C^VC&k QmH+?%07*qoM6N<$f|jpH_y7O^ literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapRow-aqua-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapRow-aqua-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ff823d1b41daff628392d2781690123938acccf5 GIT binary patch literal 788 zcmV+v1MB>WP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?(gt zY(x=rn;mHy;=oy8Jcv=NfX@Py3usfsjFWD4B4z|s`hm->iBl*S!)4L!pl;-h?*<)SjRoY&ydCw_?)n7^f96ZNKa;+Ai0^KV(LlxxDh)9M;JiQRd$y^uw z{kZn7H=1!P3x>9So22|-up^1`ZFqmv<@O2L2laxQSYHRE1kob|J;P$L>?@xfS$;l( SySjq_0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?r<8)Soq4Y(k2tIxmz32~?p&}Ye1R%=>X2$3p(l6lxq^818;0MKYOSBAh0c%Ju) z!4X|1wa~Jxa}-4k78Fo%K#{FVWEKG#*L5A!G@Y*NC?RBxF%T(+606S=vkMFe?S%-J zxI>Ae&)>j>$@9EO)AVTDc7R>lG|gLL`z;bN)1DEAN9$ZWSmmw0b4qQV(UiV)K z;1Szn+rdP9-w%41(E_|Uh7GoRmat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?Wk_=(7MN0{Su&7J1W&lp~O)yY%2F8PS5U?g45iD*^22ZeOB& zfqe!nB<*n`62QH_#ZW9zIlXYkvqIdiVfwO#svw?$%@L2NMPSvKCubgN5g6(Fepui& z9HSq8;#>y*?afhOe!PGx9#MxI_keSe6yF31KYiK3q2empEPj7aW&0Yo;=SZ3y)2F@ zUJ#|(g5>eUd05HaAj;V*E1>#K)J1vl@QEqht0!FmWm^!*8#c$u#2+J7h=)!3a2wO2 z$tA5BE`(FKswAF&7Zv8E!Cat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?=hSq-Z}0_JwACc6Mfo6bi*3BWMC#*Zr#N z+H4F8k)oe+i(#be`rh~bl;#r9=|qSvgsi)SOd>$W^E|UC3KLxm&m$hY6_G;3!>NeL z1@s8oun-oJ=lOjYhS_mlryCQ;ah4>>Zn0R{7+RX9ePg^ou4^{yX_t>7QoK2Wh=z(iN@3X1nfofq(Q$sZ}OK0BBi0l zwhY5~lh?&1&d-(79)~6kEktd+pJ_TWI1f>PUb+rqR|xKC1np(SPWiA!a2)n!K=Xaq zBz9qoW;rAT*V20z%q5~X4TB(9q1kceD$DYdZp7I-z#<^vy{f7YQYaMvl^?qnr;#Hz RMnM1o002ovPDHLkV1i#nT^j%Z literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapRow-gray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapRow-gray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1a452b2fa0542bba0898733209d3d7c5105b7bd5 GIT binary patch literal 723 zcmV;^0xbQBP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?# zbjMcW${y^}z(ZnyJ`C7>FJ*ua9;qE_!Z|{@d=xfdiZevi67@-6;%*O)kzZU>b5z9I zhEthqZ|4U^ivK!F9R&kaJ&2^=Ycz*hd>3kywGgvfFhM=E6g7*@^!wu40R~qKPDl<6 zjgl=Wi}PR5m5JdG0};a+$%49}CGyUJh~Yq8;qiF>l@HzZX$+^z&#wRg002ovPDHLk FV1l+fJDUIi literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapRow-green-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapRow-green-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3ddec73ec45207cade2ac3d188b318835c6a5320 GIT binary patch literal 819 zcmV-31I+x1P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?zY(CeM&2dGn^V+8nJ;24YMwymdmB9#baIa|3hiXaJA58z8M`sq|) z3m$xys9fMk=*g9_L$g#Q2nAoj^VMPALe1=M{2&~y2Ii=1GnAcIYm%L>UElzNr~8)p z7EK654z_7mq6vX)+7Q>lX4)0MCXL;36yW5imlFd!j#>DKRB*gLI5S#3K2j6XO zQpbvUfM1f-g*e)$VJ}_lA zQ#ltgCj|PuWPwb6Mv92Gto5cV;45#XRKdsjAy~R|Q!$c)kz2p3r0}SJB~h4$;m9AG x+<7!z8Heat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ZBdr)HlD=qS%?Qppj+IMpD;LG(PZO;h@EKCU96KYq zY;lpD$vZ;BHm&$54c!&jdk6%}KQ$w(ag8nv-~?+oOVEXZY~b&ErGe3_&WCS0Lqpj6 z)J|kyiE0Bz9Eu6g@D&=u-rJ9mPa95q`lt|xJHPlRg=1)P!6f8;abNx-UKXW3LAW4d z2#rxUh=v=Taq$LiAuvDRQa*6&3!q;u=qU!;ARlE{W+SwQxs0}0mL;E8ie+55z^L7V zx*Yu0P$mu@LkdnP{J^RCi&r=j{jyDCB7N5IH&-MQ3CTAg--n^)Nok`10000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?4_`3w&cR()kRH2(+=(Re~l2!n_v}V2MpQ#wdw> z@I75FHx`iKoCX}HD2vDHAr|4~HvSI&RloQrK^b=RUKioM*(CV7R+{>6*+#@%jrqEU zs17-NGX_7;I*92MeBhvDe{>pD4x4<8W_cALWT)WHPqkqbPC-#}pLJUjxn*dN%z$U% t3eve=af6yz-v>kjxa7D-Bof(GJ^`+wZAH|wE-nB7002ovPDHLkV1h%rO)vle literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapRow-lightgray-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapRow-lightgray-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4fd00c71dacfda0ded26d3e3939e13608eea32 GIT binary patch literal 768 zcmV+b1ONPqP)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?R#RnHRCf}$uomSyRlKPW_k zJmHAjz2i7L&+`)c6oAo0h!sF)CXiMDbj5M(W?AMU9l-b(ai|~?K#Z;-S_d!z<$1nj z5Cs7SFRjKM>R9~8zVDBa?zl{tovA+FIY1?t&p2Wh#?%LZl=7fbm-+zE>;4h|T5O4H zP7M_V!BC}#rvca;wVNRQqlQB5tDo5G&m}!DulkqXl-7m=^{vGP*fZw$wo;Q}qm78` z4f83rrxfNJnE#s=;!O!){zDC<4kI?@#m0xxrmh3d@0%WmVYosVzf*!&ReKhE3Zk|R yv42kx*1UfgMX{xhB<~F}1ZE-y1X)>GeXUOH#hyx@u&%QJ0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?*Mk4GM>J0@wgXC<{PZ z4jh3AS~e&XkRA{mvjG_)XH@)n7LH_vq%=*^NXXyCPTlr>*0cWr4u_*-2n{gg$%hQS zc}xhD=#hbCA1aC{Ot3?Nf+95Ehnf_LG$LRVaOkf@<_q4y1I`#6n5Co-9_1w(7szuY zLVNILMnp>-ibR^NduW+=+3_n~kE9KeJo=xYvAy29KnBSfFw+ZkA z0z;n8PI!8cnw;`&V5afL0=hWBmvVy7Q4@yBHnFrn@8OT)F!vW*VqL?5`L73ioi-`H zE=uzRd?!J)k|5&kf=KsUel$jNq>=#(iQ=oGgZQfj3hIFB1*E);AcZKFzRSx9i->O0 zvM(1_I_7XL5;`y{x1cJeTiumJ={0<#P+z|%{N(owT4HSuXbBk}at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?}i4d4WN1NFfe-|7*1 z0(~>K57Zm<1`9Xf266OhZSF7UMJFvfQ^bdz>mn3n39KUFhaAG^90d9$dn*Ac zu{d4w3p%2f9GYo%uz(IO!yPkj&=F#6HX;8)YCrd}Cpb*~;z+DAoa%Q;XMFu5c1ZAD zt+W!bYa`P6mQOxIe-x7FwY1{rx*xHUg0jRVb?cA%AS&d_%we={ssK%GDD}=O(=b}6 zpe>DiJ(Wab8Agw!%kM*`0ewSZApBj6T0$+jfWzT9XMO>0BZp0JqTne20000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?;(_~^>MBCEMd3e{~;iwsb67V{- z;)^s3D*jR&su&2GZ7e5mLZM252NobBkXb}vF4`DpiIgH>GrA;+HDny4%Z0Cr&@(C3 zI70uYMCk%4AxV;&m>Cgu8so}WB1-ZNRLn#P_4qFO{4|#QQ+_lswDXkW95`KWhF z+oB=I!SMzQKc@rC{b{^&nsY`EjLi96Cb@e(ltgYDKCQ%nkK=_y8Gqpw717$2)Drg{ hiVij|9S%nwd;?dWhKyW|561ui002ovPDHLkV1f_oYQ_Kn literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/inspector-element/wrapRow-red-16x16@2x.png b/editor/resources/editor/icons/light/inspector-element/wrapRow-red-16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..abbaa1cfecd5c7aa0cff0f57069669d218a8fc45 GIT binary patch literal 748 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?HK~#7F?UfCY!Y~kpUpNe$gG%5WfPy;*hXN=PP{5A? zzyS^b2RI-SFaY7DU53D7n7o-y+H9x$C7VrvprD|drBH%Q)Zf`weyQ1r9XG(& zTIsRI`vAOQ=Cq*?q!fT_m^flbJG6ktFGt$q(tPjSLX-~R2Qo7O(S-OR#QyAWpkmn> zD?RD(X^muMjbo zEF+UJ8+Wvchr!eO#j9a2W!RE`ja|QbCiuOh)E}_GL6qj(#3)bPd}>J>_%@;^1?C%t zlw3wO5I38$`CevKK=QS3&_umC(gQ>1O+j8|-UaW1$Sgypr(Jdnr04ev6{&g8X(6~0 edjtgqeX>q+EO~uhH|fs+0000at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?- zHz*s}4e${$;R9(vpxESo$xHv`xL57~B8FiaBd7qzm=PE09<`@CbQ3~os);pV=24KO zC9sL09dv*O&&0TxiGZQOGtpBEJQGK1fh&t~4co*(|7`|pMaaM=B1l0e%EXqy-9A%- zRH?dQjE5WR92=lYtlz*glrcd+C(qu9Y`slcUhap28&DT`x1~HZG|{Ko>|u1pVKgO; x0JoQ Date: Tue, 11 Jun 2024 10:50:13 +0200 Subject: [PATCH 052/103] disabling "updates property controls after cloning the branch" (#5884) The test unfortunately became flaky, I am making a github TODO to investigate and fix, but I'm disabling it now --- editor/src/core/shared/github/github.spec.browser2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/core/shared/github/github.spec.browser2.ts b/editor/src/core/shared/github/github.spec.browser2.ts index e6412eeeeef9..d7ad57fd5353 100644 --- a/editor/src/core/shared/github/github.spec.browser2.ts +++ b/editor/src/core/shared/github/github.spec.browser2.ts @@ -210,7 +210,7 @@ describe('Github integration', () => { expect(renderResult.renderedDOM.getByText('Editor from Github')).toBeDefined() }) - it('updates property controls after cloning the branch', async () => { + xit('updates property controls after cloning the branch', async () => { const renderResult = await renderTestEditorWithCode( makeTestProjectCodeWithSnippet(`

Starting Editor

From d15fb9dba9788b88ed9fc70f92c7169c3adc533a Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Tue, 11 Jun 2024 11:37:58 +0200 Subject: [PATCH 053/103] Reset viewport on page add (#5877) **Problem:** When adding a new page, the canvas viewport stays the same, which means that the new page could be far away. **Fix:** After adding a new page, scroll to the active scene (top-left) so the new content sits at a usable spot. Note: I did not reset the zoom too because after trying it out a bit it seems potentially confusing, but it's easy to add it. https://github.com/concrete-utopia/utopia/assets/1081051/e0da869d-884e-4dd8-872c-61e54d78a627 **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5867 --- .../navigator/left-pane/pages-pane.tsx | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/editor/src/components/navigator/left-pane/pages-pane.tsx b/editor/src/components/navigator/left-pane/pages-pane.tsx index 349822df25c2..b7061aca2f2f 100644 --- a/editor/src/components/navigator/left-pane/pages-pane.tsx +++ b/editor/src/components/navigator/left-pane/pages-pane.tsx @@ -33,7 +33,7 @@ import { ActiveRemixSceneAtom, RemixNavigationAtom, } from '../../canvas/remix/utopia-remix-root-component' -import { Substores, useEditorState } from '../../editor/store/store-hook' +import { Substores, useEditorState, useRefEditorState } from '../../editor/store/store-hook' import { ExpandableIndicator } from '../navigator-item/expandable-indicator' import { getFeaturedRoutesFromPackageJSON, @@ -50,15 +50,20 @@ import { updateRemixRoute, addNewFeaturedRoute, removeFeaturedRoute, + scrollToPosition, } from '../../editor/actions/action-creators' import type { ElementContextMenuInstance } from '../../element-context-menu' import ReactDOM from 'react-dom' import { createNewPageName } from '../../editor/store/editor-state' import urljoin from 'url-join' import { notice } from '../../common/notice' -import type { EditorDispatch } from '../../editor/action-types' +import type { EditorAction, EditorDispatch } from '../../editor/action-types' import { maybeToArray } from '../../../core/shared/optional-utils' import { StarUnstarIcon } from '../../canvas/star-unstar-icon' +import { canvasRectangle, isFiniteRectangle } from '../../../core/shared/math-utils' +import { MetadataUtils } from '../../../core/model/element-metadata-utils' +import type { ElementInstanceMetadataMap } from '../../../core/shared/element-template' +import type { ElementPath } from 'utopia-shared/src/types' type RouteMatch = { path: string @@ -506,6 +511,23 @@ function fillInGapsInRoutes(routes: RouteMatches): Array { return Object.values(result).sort((a, b) => a.path.localeCompare(b.path)) } +function resetCanvasForNewPage( + metadata: ElementInstanceMetadataMap, + activeScenePath: ElementPath, +): EditorAction[] { + const sceneFrame = MetadataUtils.getFrameInCanvasCoords(activeScenePath, metadata) + if (sceneFrame != null && isFiniteRectangle(sceneFrame)) { + const target = canvasRectangle({ + x: sceneFrame.x, + y: sceneFrame.y, + width: 0, + height: 0, + }) + return [scrollToPosition(target, 'keep-scroll-position-if-visible')] + } + return [] +} + export const AddPageContextMenu = React.memo( ({ contextMenuInstance, @@ -518,13 +540,19 @@ export const AddPageContextMenu = React.memo( }) => { const dispatch = useDispatch() + const metadata = useRefEditorState((store) => store.editor.jsxMetadata) + const [activeRemixScene] = useAtom(ActiveRemixSceneAtom) + const addPageAction = React.useCallback( (template: PageTemplate) => () => { const newPageName = createNewPageName() - dispatch([addNewPage('/app/routes', template, newPageName)]) + dispatch([ + addNewPage('/app/routes', template, newPageName), + ...resetCanvasForNewPage(metadata.current, activeRemixScene), + ]) onAfterPageAdd(newPageName) }, - [dispatch, onAfterPageAdd], + [dispatch, onAfterPageAdd, activeRemixScene, metadata], ) const portalTarget = document.getElementById(PortalTargetID) From 050e8fecb0514238378d09945061deb01d288ed0 Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:51:21 +0100 Subject: [PATCH 054/103] Standardise Some Inspector Sections (#5878) - Removed some outlines and replaced others with box shadows so they would only exist on one edge. - Uppercased some section titles. - Replaced the use of `FolderLabel` with `InspectorSectionHeader`. - Moved `InspectorSectionHeader` into its own file. - Removed the indentation from `FolderSection`. - Corrected a typo in `EditorContractDropdown`. --- .../controls/root-element-indicator.tsx | 1 - .../inspector/editor-contract-section.tsx | 2 +- editor/src/components/inspector/inspector.tsx | 53 ++----------- .../components/inspector/section-header.tsx | 44 +++++++++++ .../component-section/component-section.tsx | 2 +- .../component-section/folder-section.tsx | 79 ++----------------- ...performance-regression-tests.spec.tsx.snap | 16 ++-- 7 files changed, 64 insertions(+), 133 deletions(-) create mode 100644 editor/src/components/inspector/section-header.tsx diff --git a/editor/src/components/inspector/controls/root-element-indicator.tsx b/editor/src/components/inspector/controls/root-element-indicator.tsx index a449314b019b..fd594840b096 100644 --- a/editor/src/components/inspector/controls/root-element-indicator.tsx +++ b/editor/src/components/inspector/controls/root-element-indicator.tsx @@ -7,7 +7,6 @@ export const RootElementIndicator = () => { style={{ justifyContent: 'center', alignItems: 'center', - outline: `1px solid ${colorTheme.seperator.value}`, background: colorTheme.inspectorBackground.value, }} > diff --git a/editor/src/components/inspector/editor-contract-section.tsx b/editor/src/components/inspector/editor-contract-section.tsx index 670e648e2fa8..f0dd37eb0622 100644 --- a/editor/src/components/inspector/editor-contract-section.tsx +++ b/editor/src/components/inspector/editor-contract-section.tsx @@ -349,7 +349,7 @@ export const EditorContractDropdown = React.memo(() => { onSubmitValue={onChange} controlStyles={simpleControlStyles} containerMode={'noBorder'} - style={{ borderRadius: 2, width: 'min-wdith', paddingRight: 6 }} + style={{ borderRadius: 2, width: 'min-width', paddingRight: 6 }} /> {when( groupProblems.length > 0, diff --git a/editor/src/components/inspector/inspector.tsx b/editor/src/components/inspector/inspector.tsx index 773e96377de1..d56988db4c44 100644 --- a/editor/src/components/inspector/inspector.tsx +++ b/editor/src/components/inspector/inspector.tsx @@ -51,15 +51,7 @@ import { useKeepReferenceEqualityIfPossible, useKeepShallowReferenceEquality, } from '../../utils/react-performance' -import { - Icn, - useColorTheme, - UtopiaTheme, - FlexRow, - Button, - SectionActionSheet, - SquareButton, -} from '../../uuiui' +import { Icn, useColorTheme, UtopiaTheme, FlexRow, Button } from '../../uuiui' import { getElementsToTarget } from './common/inspector-utils' import type { ElementPath, PropertyPath } from '../../core/shared/project-file-types' import { unless, when } from '../../utils/react-conditionals' @@ -100,6 +92,7 @@ import { isIntrinsicElementMetadata } from '../../core/model/project-file-utils' import { assertNever } from '../../core/shared/utils' import { DataReferenceSection } from './sections/data-reference-section' import { replaceFirstChildAndDeleteSiblings } from '../editor/element-children' +import { InspectorSectionHeader } from './section-header' export interface ElementPathElement { name?: string @@ -180,7 +173,6 @@ const AlignmentButtons = React.memo((props: { numberOfTargets: number }) => { justifyContent: 'space-around', alignItems: 'center', height: UtopiaTheme.layout.rowHeight.normal, - outline: `1px solid ${colorTheme.seperator.value}`, background: colorTheme.inspectorBackground.value, padding: '8px 0', }} @@ -441,6 +433,7 @@ export const Inspector = React.memo((props: InspectorProps) => { {unless( isCodeElement || isDataReference, ((props: InspectorProps) => { title='Styles' toggle={toggleStyleSection} open={styleSectionOpen} + uppercase={true} />, )} {when( @@ -499,6 +493,7 @@ export const Inspector = React.memo((props: InspectorProps) => { title='Advanced' toggle={toggleAdvancedSection} open={advancedSectionOpen} + uppercase={true} />, )} {when( @@ -916,44 +911,6 @@ export const InspectorContextProvider = React.memo<{ ) }) -function InspectorSectionHeader({ - title, - open, - toggle, -}: { - title: string - open: boolean - toggle: () => void -}) { - return ( - -
- {title} -
- - - - - -
- ) -} - function useBoolean(starting: boolean): { value: boolean set: (_: boolean) => void diff --git a/editor/src/components/inspector/section-header.tsx b/editor/src/components/inspector/section-header.tsx new file mode 100644 index 000000000000..fceb676ea6c6 --- /dev/null +++ b/editor/src/components/inspector/section-header.tsx @@ -0,0 +1,44 @@ +import React from 'react' +import { FlexRow, SectionActionSheet, SquareButton, colorTheme } from '../../uuiui' +import { ExpandableIndicator } from '../navigator/navigator-item/expandable-indicator' + +export function InspectorSectionHeader({ + title, + open, + toggle, + uppercase = false, +}: { + title: string + open: boolean + toggle: () => void + uppercase?: boolean +}) { + return ( + +
+ {title} +
+ + + + + +
+ ) +} diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index 263756e5e72d..364601101c4e 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -1437,7 +1437,7 @@ export const ComponentSectionInner = React.memo((props: ComponentSectionProps) = > {componentData != null ? ( - {componentData.displayName} + {componentData.displayName} {when(componentData.isRegisteredComponent, )} {componentData.secondaryName == null ? null : ( diff --git a/editor/src/components/inspector/sections/component-section/folder-section.tsx b/editor/src/components/inspector/sections/component-section/folder-section.tsx index 0cbdfee3c55e..3b8d0e3f83b9 100644 --- a/editor/src/components/inspector/sections/component-section/folder-section.tsx +++ b/editor/src/components/inspector/sections/component-section/folder-section.tsx @@ -18,6 +18,7 @@ import { isAdvancedFolderLabel, specialPropertiesToIgnore, } from '../../../../core/property-controls/property-controls-utils' +import { InspectorSectionHeader } from '../../section-header' interface FolderSectionProps { isRoot: boolean @@ -94,7 +95,7 @@ export const FolderSection = React.memo((props: FolderSectionProps) => { controlDescription={controlDescription} isScene={false} setGlobalCursor={props.setGlobalCursor} - indentationLevel={props.indentationLevel + 1} + indentationLevel={0} visibleEmptyControls={props.visibleEmptyControls} unsetPropNames={props.unsetPropNames} showHiddenControl={props.showHiddenControl} @@ -107,13 +108,7 @@ export const FolderSection = React.memo((props: FolderSectionProps) => {
{unless( props.isRoot, - , + , )} {when( open, @@ -137,7 +132,7 @@ export const FolderSection = React.memo((props: FolderSectionProps) => { controlDescription={controlDescription} isScene={false} setGlobalCursor={props.setGlobalCursor} - indentationLevel={props.indentationLevel + 1} + indentationLevel={0} showHiddenControl={props.showHiddenControl} focusOnMount={false} /> @@ -154,73 +149,9 @@ export const FolderSection = React.memo((props: FolderSectionProps) => { , )}
) }) - -interface FolderLabelProps { - indentationLevel: number - open: boolean - toggleOpen: () => void - title: string - showIndentation: boolean -} - -const FolderLabel = React.memo((props: FolderLabelProps) => { - const { toggleOpen } = props - const indentation = props.showIndentation ? props.indentationLevel * 8 : 0 - const handleOnClick = React.useCallback(() => toggleOpen(), [toggleOpen]) - return ( -
- - {props.title} -
- ) -}) - -interface ExpansionArrowSVGProps { - style: React.CSSProperties -} - -const ExpansionArrowSVG = React.memo((props: ExpansionArrowSVGProps) => { - const colorTheme = useColorTheme() - return ( - - - - - - ) -}) diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 2742219605ff..91759eca0cc4 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -129,14 +129,14 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedFunctionComponent(FlexCol)", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedFunctionComponent(FlexCol):data-testid='inspector-column'", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedFunctionComponent(DisableControlsInSubtree)", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/div:data-testid='inspector-sections-container'", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/div", "/UtopiaSpiedExoticType(Symbol(react.fragment))/div/UtopiaSpiedFunctionComponent(DisableControlsInSubtree)/UtopiaSpiedExoticType(Symbol(react.provider))", - "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/UtopiaSpiedFunctionComponent(FlexCol)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/Symbol(react.provider)/UtopiaSpiedFunctionComponent(FlexCol)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/UtopiaSpiedFunctionComponent(FlexCol)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='inspector-column'", + "/Symbol(react.provider)/UtopiaSpiedFunctionComponent(FlexCol)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='inspector-column'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedClass(ComponentSection)/Symbol(react.memo)(ComponentSectionInner)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/span", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/span", @@ -154,7 +154,7 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", + "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorSectionHeader)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)", @@ -783,14 +783,14 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedFunctionComponent(FlexCol)", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedFunctionComponent(FlexCol):data-testid='inspector-column'", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedFunctionComponent(DisableControlsInSubtree)", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/div:data-testid='inspector-sections-container'", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/UtopiaSpiedExoticType(Symbol(react.fragment))", "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/Inspector/div", "/UtopiaSpiedExoticType(Symbol(react.fragment))/div/UtopiaSpiedFunctionComponent(DisableControlsInSubtree)/UtopiaSpiedExoticType(Symbol(react.provider))", - "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/UtopiaSpiedFunctionComponent(FlexCol)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/Symbol(react.provider)/UtopiaSpiedFunctionComponent(FlexCol)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedExoticType(Symbol(react.provider))/Symbol(react.provider)/UtopiaSpiedFunctionComponent(FlexCol)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='inspector-column'", + "/Symbol(react.provider)/UtopiaSpiedFunctionComponent(FlexCol)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='inspector-column'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedClass(ComponentSection)/Symbol(react.memo)(ComponentSectionInner)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/span", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/span", @@ -1576,7 +1576,7 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", + "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorSectionHeader)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)", From 26aef23e11169ac9c88c604491766ddf96db475c Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Tue, 11 Jun 2024 13:06:01 +0300 Subject: [PATCH 055/103] fix: segement controls CSS (#5881) Adjust the style of segment controls to match design: image With overridden values: ![image](https://github.com/concrete-utopia/utopia/assets/7003853/26e5ac00-b833-4329-8e23-bb10d52e5bd4) **Manual Tests:** I hereby swear that: - [X] I opened a hydrogen project and it loaded - [X] I could navigate to various routes in Preview mode Fixes #5830 --- .../controls/option-chain-control.tsx | 1 + .../inspector/controls/option-control.tsx | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/editor/src/components/inspector/controls/option-chain-control.tsx b/editor/src/components/inspector/controls/option-chain-control.tsx index 85bc06227b1c..e52f32d5f12f 100644 --- a/editor/src/components/inspector/controls/option-chain-control.tsx +++ b/editor/src/components/inspector/controls/option-chain-control.tsx @@ -66,6 +66,7 @@ export const OptionChainControl: React.FunctionComponent< flexDirection: 'row', border: `1px solid ${colorTheme.bg2.value}`, borderRadius: 3, + padding: '1px', }} className={`option-chain-control-container ${Utils.pathOr( '', diff --git a/editor/src/components/inspector/controls/option-control.tsx b/editor/src/components/inspector/controls/option-control.tsx index 34baab3711e4..249b53b45bab 100644 --- a/editor/src/components/inspector/controls/option-control.tsx +++ b/editor/src/components/inspector/controls/option-control.tsx @@ -118,8 +118,25 @@ export const OptionControl: React.FunctionComponent< borderRadius: rc != null ? 0 : UtopiaTheme.inputBorderRadius, // If part of a option chain control: '.option-chain-control-container &': { - borderRadius: 0, + borderRadius: isChecked ? '3px' : 0, boxShadow: 'none !important', + opacity: 1, + borderColor: colorTheme.border0.value, + backgroundColor: isChecked + ? props.controlStatus === 'overridden' + ? colorTheme.brandNeonPink10.value + : colorTheme.bg4.value + : 'transparent', + color: isChecked + ? props.controlStatus === 'overridden' + ? colorTheme.brandNeonPink.value + : colorTheme.fg1.value + : colorTheme.verySubduedForeground.value, + '&:hover': { + opacity: props.controlStatus == 'disabled' ? undefined : 1, + color: colorTheme.fg1.value, + cursor: 'pointer', + }, }, '.option-chain-control-container .segment:first-of-type &': { borderTopLeftRadius: UtopiaTheme.inputBorderRadius, From a9b84ca2a054ea721b3cdd257472e81f74c3e877 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Tue, 11 Jun 2024 12:58:06 +0200 Subject: [PATCH 056/103] Override control styles for string children input (#5887) **Problem:** String inputs for children props in the inspector have the blue foreground color even if they shouldn't, because they look as `controlled`. **Fix:** Override the control status/styles and make them `simple` if they are used for `children` props. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5886 --- .../property-control-controls.tsx | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx index bc6f23f668ec..27398277341c 100644 --- a/editor/src/components/inspector/sections/component-section/property-control-controls.tsx +++ b/editor/src/components/inspector/sections/component-section/property-control-controls.tsx @@ -25,7 +25,7 @@ import { useWrappedEmptyOrUnknownOnSubmitValue, wrappedEmptyOrUnknownOnSubmitValue, } from '../../../../uuiui' -import type { CSSCursor } from '../../../../uuiui-deps' +import type { CSSCursor, ControlStatus, ControlStyles } from '../../../../uuiui-deps' import { SliderControl, getControlStyles } from '../../../../uuiui-deps' import { normalisePathSuccessOrThrowError, @@ -535,11 +535,14 @@ export const StringInputPropertyControl = React.memo( const { propName, propMetadata } = props const controlId = `${propName}-string-input-property-control` + + const isChildren = propName === 'children' + const value = useEditorState( Substores.metadata, (store) => { // if the target prop is children, dig for its value - if (propName === 'children') { + if (isChildren) { const element = MetadataUtils.findElementByElementPath( store.editor.jsxMetadata, props.elementPath, @@ -574,6 +577,20 @@ export const StringInputPropertyControl = React.memo( 'StringInputPropertyControl value', ) + const controlStatus: ControlStatus = React.useMemo(() => { + if (isChildren) { + return 'simple' + } + return propMetadata.controlStatus + }, [propMetadata.controlStatus, isChildren]) + + const controlStyles: ControlStyles = React.useMemo(() => { + if (isChildren) { + return getControlStyles(controlStatus) + } + return propMetadata.controlStyles + }, [propMetadata.controlStyles, controlStatus, isChildren]) + const safeValue = value ?? '' return ( @@ -591,8 +608,8 @@ export const StringInputPropertyControl = React.memo( testId={controlId} value={safeValue} onSubmitValue={propMetadata.onSubmitValue} - controlStatus={propMetadata.controlStatus} - controlStyles={propMetadata.controlStyles} + controlStatus={controlStatus} + controlStyles={controlStyles} focus={props.focusOnMount} /> From 8dbdfca4f3e45b1928d6150f2a8ae3108fa72847 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:01:58 +0200 Subject: [PATCH 057/103] Multi-column data picker (#5883) **Problem:** The data picker is still somewhat crummy for exploring multiple deep objects in the scope **Fix:** First version of the multi-column data picker! image image image Array picker mode: image **Commit Details:** - Added `DataSelectorColumns` component and file - Tried to only make minimal changes in `data-selector-modal.tsx` so I only have a small conflict with @bkrmendy - When picking a List Source, we show non-pickable options, but without background - Changed the CartoucheUI so it can have disabled background and disabled highlight **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode **TODOs for follow up work** - [ ] For some reason some objects are not traversable, they become leafs. I believe this is behavior of the existing code, needs investigation: image - [ ] Right now we only filter for array type when picking a List Source, we should instead always filter for the correct type - [ ] the value preview column is a placeholder design at best - [ ] there is at least one example in the old demo store where we incorrectly show blue cartouches instead of green: image --- .../component-section/cartouche-ui.tsx | 31 +- .../data-selector-columns.tsx | 338 ++++++++++++++++++ .../component-section/data-selector-modal.tsx | 153 ++------ .../layout-section/list-source-cartouche.tsx | 9 +- .../navigator/navigator-item/map-counter.tsx | 36 +- 5 files changed, 411 insertions(+), 156 deletions(-) create mode 100644 editor/src/components/inspector/sections/component-section/data-selector-columns.tsx diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index adcbe96f16a0..04a55e65aeea 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -14,8 +14,8 @@ export interface HoverHandlers { export type CartoucheDataType = 'renderable' | 'boolean' | 'array' | 'object' | 'unknown' -type CartoucheSource = 'internal' | 'external' | 'literal' -export type CartoucheHighlight = 'strong' | 'subtle' +export type CartoucheSource = 'internal' | 'external' | 'literal' +export type CartoucheHighlight = 'strong' | 'subtle' | 'disabled' export type CartoucheUIProps = React.PropsWithChildren<{ tooltip?: string | null @@ -50,6 +50,8 @@ export const CartoucheUI = React.forwardRef( preview = false, } = props + const showBackground = role !== 'information' + const colors = useCartoucheColors(source, highlight ?? null) const wrappedOnClick = useStopPropagation(onClick) @@ -85,12 +87,25 @@ export const CartoucheUI = React.forwardRef( width: 'max-content', }} css={{ - color: selected || highlight === 'strong' ? colors.fg.selected : colors.fg.default, - backgroundColor: selected ? colors.bg.selected : colors.bg.default, - ':hover': { - color: selected || highlight === 'strong' ? undefined : colors.fg.hovered, - backgroundColor: selected ? undefined : colors.bg.hovered, - }, + color: + role === 'information' + ? undefined + : selected || highlight === 'strong' + ? colors.fg.selected + : colors.fg.default, + backgroundColor: + showBackground == false + ? 'transparent' + : selected + ? colors.bg.selected + : colors.bg.default, + ':hover': + highlight === 'disabled' + ? {} + : { + color: selected || highlight === 'strong' ? undefined : colors.fg.hovered, + backgroundColor: selected ? undefined : colors.bg.hovered, + }, }} > {source === 'literal' ? null : ( diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx new file mode 100644 index 000000000000..cb4e1701b1af --- /dev/null +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -0,0 +1,338 @@ +import styled from '@emotion/styled' +import React from 'react' +import { + dataPathSuccess, + traceDataFromVariableName, +} from '../../../../core/data-tracing/data-tracing' +import { isPrefixOf } from '../../../../core/shared/array-utils' +import { arrayEqualsByReference, assertNever } from '../../../../core/shared/utils' +import { unless, when } from '../../../../utils/react-conditionals' +import { FlexColumn, FlexRow, colorTheme } from '../../../../uuiui' +import { Substores, useEditorState } from '../../../editor/store/store-hook' +import type { CartoucheSource, CartoucheUIProps } from './cartouche-ui' +import { CartoucheUI } from './cartouche-ui' +import type { ArrayOption, DataPickerOption, ObjectOption, ObjectPath } from './data-picker-utils' +import { MapCounterUi } from '../../../navigator/navigator-item/map-counter' + +interface DataSelectorColumnsProps { + activeScope: Array + targetPathInsideScope: ObjectPath + onTargetPathChange: (newTargetPath: ObjectPath) => void +} + +export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) => { + return ( + + + + ) +}) + +interface DataSelectorColumnProps { + activeScope: Array + originalDataForScope: DataPickerOption | null + currentlyShowingScopeForArray: boolean + targetPathInsideScope: ObjectPath + onTargetPathChange: (newTargetPath: ObjectPath) => void +} + +const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { + const { activeScope, targetPathInsideScope, currentlyShowingScopeForArray } = props + + const elementOnSelectedPath: DataPickerOption | null = + activeScope.find((option) => isPrefixOf(option.valuePath, targetPathInsideScope)) ?? null + + // if the current scope is an array, we want to show not only the array indexes, but also the contents of the first element of the array + const pseudoSelectedElementForArray: DataPickerOption | null = + elementOnSelectedPath == null && currentlyShowingScopeForArray && activeScope.length > 0 + ? activeScope[0] + : null + + const nextColumnScope: ArrayOption | ObjectOption | null = (() => { + const elementToUseForNextColumn = elementOnSelectedPath ?? pseudoSelectedElementForArray + if (elementToUseForNextColumn != null) { + if ( + (elementToUseForNextColumn.type === 'object' || + elementToUseForNextColumn.type === 'array') && + elementToUseForNextColumn.children.length > 0 + ) { + return elementToUseForNextColumn + } + } + return null + })() + + const nextColumnScopeValue = nextColumnScope == null ? elementOnSelectedPath : null + + const dataSource = useVariableDataSource(props.originalDataForScope) + + const isLastColumn = nextColumnScope == null && nextColumnScopeValue == null + const columnRef = useScrollIntoView(isLastColumn) + + return ( + <> + + {activeScope.map((option, index) => { + const selected = arrayEqualsByReference(option.valuePath, targetPathInsideScope) + const onActivePath = isPrefixOf(option.valuePath, targetPathInsideScope) + return ( + + ) + })} + + {nextColumnScope != null ? ( + + ) : null} + {nextColumnScopeValue != null ? : null} + + ) +}) + +interface ValuePreviewColumnProps { + data: DataPickerOption +} + +const ValuePreviewColumn = React.memo((props: ValuePreviewColumnProps) => { + const text = JSON.stringify(props.data.variableInfo.value, undefined, 2) + const ref = useScrollIntoView(true) + return ( + +
+ {text} +
+ {variableTypeForInfo(props.data)} +
+ ) +}) + +function variableTypeForInfo(info: DataPickerOption): string { + switch (info.type) { + case 'array': + return 'Array' + case 'object': + return 'Object' + case 'primitive': + return typeof info.variableInfo.value + case 'jsx': + return 'JSX' + default: + assertNever(info) + } +} + +interface RowWithCartoucheProps { + data: DataPickerOption + currentlyShowingScopeForArray: boolean + selected: boolean + onActivePath: boolean + forceShowArrow: boolean + isLeaf: boolean + forcedDataSource: CartoucheSource | null + onTargetPathChange: (newTargetPath: ObjectPath) => void +} +const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { + const { + onTargetPathChange, + data, + currentlyShowingScopeForArray, + forcedDataSource, + isLeaf, + selected, + onActivePath, + forceShowArrow, + } = props + const targetPath = data.valuePath + + const dataSource = useVariableDataSource(data) + + const onClick: React.MouseEventHandler = React.useCallback( + (e) => { + e.stopPropagation() + onTargetPathChange(targetPath) + }, + [targetPath, onTargetPathChange], + ) + + const ref = useScrollIntoView(selected) + + return ( + + + + ) : undefined + } + > + {currentlyShowingScopeForArray ? ( + <> + item + {data.variableInfo.expressionPathPart} + + ) : ( + data.variableInfo.expressionPathPart + )} + + + + {'>'} + + + ) +}) + +function useVariableDataSource(variable: DataPickerOption | null) { + return useEditorState( + Substores.projectContentsAndMetadata, + (store) => { + if (variable == null) { + return null + } + const container = variable.variableInfo.insertionCeiling + const trace = traceDataFromVariableName( + container, + variable.variableInfo.expression, + store.editor.jsxMetadata, + store.editor.projectContents, + dataPathSuccess([]), + ) + + switch (trace.type) { + case 'hook-result': + return 'external' + case 'literal-attribute': + case 'literal-assignment': + return 'literal' + case 'component-prop': + case 'element-at-scope': + case 'failed': + return 'internal' + break + default: + assertNever(trace) + } + }, + 'useVariableDataSource', + ) +} + +function childTypeToCartoucheDataType( + childType: DataPickerOption['type'], +): CartoucheUIProps['datatype'] { + switch (childType) { + case 'array': + return 'array' + case 'object': + return 'object' + case 'jsx': + case 'primitive': + return 'renderable' + default: + assertNever(childType) + } +} + +const DataSelectorFlexColumn = styled(FlexColumn)({ + minWidth: 200, + height: '100%', + flexShrink: 0, + overflowX: 'hidden', + overflowY: 'scroll', + scrollbarWidth: 'auto', + scrollbarColor: 'gray transparent', + paddingRight: 10, // to account for scrollbar + paddingLeft: 6, + paddingBottom: 10, + borderRight: `1px solid ${colorTheme.subduedBorder.cssValue}`, +}) + +function useScrollIntoView(shouldScroll: boolean) { + const elementRef = React.useRef(null) + + React.useEffect(() => { + if (shouldScroll && elementRef.current != null) { + elementRef.current.scrollIntoView({ + behavior: 'instant', + block: 'nearest', + inline: 'nearest', + }) + } + }, [shouldScroll]) + + return elementRef +} diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 4ec605337740..97a9c5b75f3a 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -43,6 +43,7 @@ import { optionalMap } from '../../../../core/shared/optional-utils' import type { FileRootPath } from '../../../canvas/ui-jsx-canvas' import { insertionCeilingToString, insertionCeilingsEqual } from '../../../canvas/ui-jsx-canvas' import { set } from 'objectPath' +import { DataSelectorColumns } from './data-selector-columns' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -163,7 +164,7 @@ export const DataSelectorModal = React.memo( (name: ElementPath, hasContent: boolean) => () => { if (hasContent) { setSelectedScope(name) - setSelectedPath(null) + setSelectedPath([]) setHoveredPath(null) setNavigatedToPath([]) } @@ -203,18 +204,24 @@ export const DataSelectorModal = React.memo( findFirstObjectPathToNavigateTo(processedVariablesInScope, startingSelectedValuePath) ?? [], ) - const [selectedPath, setSelectedPath] = React.useState( - startingSelectedValuePath, + const [selectedPath, setSelectedPath] = React.useState( + startingSelectedValuePath ?? [], ) const [hoveredPath, setHoveredPath] = React.useState(null) + const setSelectedPathFromColumns = React.useCallback((newPath: ObjectPath) => { + setSelectedPath(newPath) + setHoveredPath(null) + setNavigatedToPath([]) + }, []) + const setNavigatedToPathCurried = React.useCallback( (path: DataPickerOption['valuePath']) => (e: React.MouseEvent) => { e.stopPropagation() e.preventDefault() setNavigatedToPath(path) - setSelectedPath(null) + setSelectedPath([]) setHoveredPath(null) }, [], @@ -233,8 +240,6 @@ export const DataSelectorModal = React.memo( const catchClick = React.useCallback((e: React.MouseEvent) => { e.stopPropagation() e.preventDefault() - - setSelectedPath(null) }, []) const onHover = React.useCallback( @@ -351,6 +356,9 @@ export const DataSelectorModal = React.memo( if (variable == null) { return } + if (variable.disabled) { + return + } onPropertyPicked( jsExpressionOtherJavaScriptSimple(variable.variableInfo.expression, [ @@ -394,8 +402,8 @@ export const DataSelectorModal = React.memo( onClick={closePopup} > - {/* detail view */} -
- - {when( - primitiveVars.length > 0, - <> - - {primitiveVars.map((variable) => ( - - {variableNameFromPath(variable)} - - ))} - - - , - )} - {folderVars.map((variable, idx) => ( - - - {variableNameFromPath(variable)} - - {variable.type === 'array' ? ( - - ) : ( -
- )} - {/* properties in scope */} - - {childVars(variable, indexLookup).map((child) => ( - - {variableNameFromPath(child)} - - ))} - - {idx < focusedVariableChildren.length - 1 ? ( - - ) : null} - - ))} - {/* Empty State */} - {when( - focusedVariableChildren.length === 0, -
- We did not find any insertable data -
, - )} -
+ {/* Scope Selector Breadcrumbs */} { const selectedStatus = props.selected - const colorTheme = useColorTheme() - return ( -
- {shownCounterValue} -
+ /> ) }) function getMapCounterStyleProps( - colorTheme: ThemeObject, overrideStatus: OverrideStatus, selectedStatus: SelectedStatus, ): CSSProperties { @@ -150,6 +146,26 @@ function getMapCounterStyleProps( assertNever(overrideStatus) } } +interface MapCounterUIProps { + 'data-testid'?: string + counterValue: number | null + overrideStatus: OverrideStatus + selectedStatus: SelectedStatus + onClick?: React.MouseEventHandler +} +export const MapCounterUi = React.memo((props: MapCounterUIProps) => { + const { counterValue, overrideStatus, selectedStatus, onClick } = props + + return ( +
+ {counterValue} +
+ ) +}) function getNextOverrideValue( overrideStatus: OverrideStatus, From 3d80e7216b24633ee374bebcf02292b48fea9a86 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:57:58 +0200 Subject: [PATCH 058/103] Chore: unified cartouche component (#5891) This PR creates a data-picker specific cartouche component which means everywhere in the data picker we can show a unified cartouche that uses the same data source etc --- .../component-section/data-picker-utils.tsx | 1 + .../data-selector-cartouche.tsx | 102 ++++++++++++++++++ .../data-selector-columns.tsx | 95 +--------------- .../variables-in-scope-utils.ts | 58 +++++++--- 4 files changed, 152 insertions(+), 104 deletions(-) create mode 100644 editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 50a0b31cb8b3..2b3b46558ac0 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -24,6 +24,7 @@ interface VariableOptionBase { valuePath: Array disabled: boolean insertionCeiling: ElementPath | FileRootPath + isChildOfArray: boolean } export interface PrimitiveOption extends VariableOptionBase { diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx new file mode 100644 index 000000000000..5187c6d2198e --- /dev/null +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -0,0 +1,102 @@ +import React from 'react' +import { + dataPathSuccess, + traceDataFromVariableName, +} from '../../../../core/data-tracing/data-tracing' +import { assertNever } from '../../../../core/shared/utils' +import { Substores, useEditorState } from '../../../editor/store/store-hook' +import { MapCounterUi } from '../../../navigator/navigator-item/map-counter' +import type { CartoucheSource, CartoucheUIProps } from './cartouche-ui' +import { CartoucheUI } from './cartouche-ui' +import type { DataPickerOption } from './data-picker-utils' + +export const DataPickerCartouche = React.memo( + (props: { + data: DataPickerOption + forcedDataSource?: CartoucheSource | null // if the DataPickerOption is actually a child (of a child) of a variable, we need to provide the CartoucheSource that belongs to the original variable + selected: boolean + }) => { + const { data, forcedDataSource, selected } = props + const dataSource = useVariableDataSource(data) + return ( + + ) : undefined + } + > + {data.isChildOfArray ? ( + <> + item + {data.variableInfo.expressionPathPart} + + ) : ( + data.variableInfo.expressionPathPart + )} + + ) + }, +) + +export function useVariableDataSource(variable: DataPickerOption | null) { + return useEditorState( + Substores.projectContentsAndMetadata, + (store) => { + if (variable == null) { + return null + } + const container = variable.variableInfo.insertionCeiling + const trace = traceDataFromVariableName( + container, + variable.variableInfo.expression, + store.editor.jsxMetadata, + store.editor.projectContents, + dataPathSuccess([]), + ) + + switch (trace.type) { + case 'hook-result': + return 'external' + case 'literal-attribute': + case 'literal-assignment': + return 'literal' + case 'component-prop': + case 'element-at-scope': + case 'failed': + return 'internal' + break + default: + assertNever(trace) + } + }, + 'useVariableDataSource', + ) +} + +function childTypeToCartoucheDataType( + childType: DataPickerOption['type'], +): CartoucheUIProps['datatype'] { + switch (childType) { + case 'array': + return 'array' + case 'object': + return 'object' + case 'jsx': + case 'primitive': + return 'renderable' + default: + assertNever(childType) + } +} diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx index cb4e1701b1af..81c85d53d074 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -1,18 +1,11 @@ import styled from '@emotion/styled' import React from 'react' -import { - dataPathSuccess, - traceDataFromVariableName, -} from '../../../../core/data-tracing/data-tracing' import { isPrefixOf } from '../../../../core/shared/array-utils' import { arrayEqualsByReference, assertNever } from '../../../../core/shared/utils' -import { unless, when } from '../../../../utils/react-conditionals' import { FlexColumn, FlexRow, colorTheme } from '../../../../uuiui' -import { Substores, useEditorState } from '../../../editor/store/store-hook' -import type { CartoucheSource, CartoucheUIProps } from './cartouche-ui' -import { CartoucheUI } from './cartouche-ui' +import type { CartoucheSource } from './cartouche-ui' import type { ArrayOption, DataPickerOption, ObjectOption, ObjectPath } from './data-picker-utils' -import { MapCounterUi } from '../../../navigator/navigator-item/map-counter' +import { DataPickerCartouche, useVariableDataSource } from './data-selector-cartouche' interface DataSelectorColumnsProps { activeScope: Array @@ -94,7 +87,6 @@ const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { { const { onTargetPathChange, data, - currentlyShowingScopeForArray, forcedDataSource, isLeaf, selected, @@ -188,8 +178,6 @@ const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { } = props const targetPath = data.valuePath - const dataSource = useVariableDataSource(data) - const onClick: React.MouseEventHandler = React.useCallback( (e) => { e.stopPropagation() @@ -216,33 +204,7 @@ const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { }} > - - ) : undefined - } - > - {currentlyShowingScopeForArray ? ( - <> - item - {data.variableInfo.expressionPathPart} - - ) : ( - data.variableInfo.expressionPathPart - )} - + { ) }) -function useVariableDataSource(variable: DataPickerOption | null) { - return useEditorState( - Substores.projectContentsAndMetadata, - (store) => { - if (variable == null) { - return null - } - const container = variable.variableInfo.insertionCeiling - const trace = traceDataFromVariableName( - container, - variable.variableInfo.expression, - store.editor.jsxMetadata, - store.editor.projectContents, - dataPathSuccess([]), - ) - - switch (trace.type) { - case 'hook-result': - return 'external' - case 'literal-attribute': - case 'literal-assignment': - return 'literal' - case 'component-prop': - case 'element-at-scope': - case 'failed': - return 'internal' - break - default: - assertNever(trace) - } - }, - 'useVariableDataSource', - ) -} - -function childTypeToCartoucheDataType( - childType: DataPickerOption['type'], -): CartoucheUIProps['datatype'] { - switch (childType) { - case 'array': - return 'array' - case 'object': - return 'object' - case 'jsx': - case 'primitive': - return 'renderable' - default: - assertNever(childType) - } -} - const DataSelectorFlexColumn = styled(FlexColumn)({ minWidth: 200, height: '100%', diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index 91be4cf302b2..eb0b2a8da4b9 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -31,6 +31,7 @@ function valuesFromObject( depth: number, originalObjectName: string, valuePath: Array, + isChildOfArray: boolean, ): Array { const patchDefinedElsewhereInfo = (option: DataPickerOption): DataPickerOption => ({ ...option, @@ -47,14 +48,19 @@ function valuesFromObject( definedElsewhere: originalObjectName, children: variable.elements .flatMap((e, index) => - valuesFromVariable(e, insertionCeiling, depth + 1, originalObjectName, [ - ...valuePath, - index, - ]), + valuesFromVariable( + e, + insertionCeiling, + depth + 1, + originalObjectName, + [...valuePath, index], + true, + ), ) .map(patchDefinedElsewhereInfo), valuePath: valuePath, disabled: false, + isChildOfArray: isChildOfArray, }, ] } else if (variable.type === 'object') { @@ -67,14 +73,19 @@ function valuesFromObject( definedElsewhere: originalObjectName, children: variable.props .flatMap((e) => - valuesFromVariable(e, insertionCeiling, depth + 1, originalObjectName, [ - ...valuePath, - e.expressionPathPart, - ]), + valuesFromVariable( + e, + insertionCeiling, + depth + 1, + originalObjectName, + [...valuePath, e.expressionPathPart], + false, + ), ) .map(patchDefinedElsewhereInfo), valuePath: valuePath, disabled: false, + isChildOfArray: isChildOfArray, }, ] } else { @@ -88,6 +99,7 @@ function valuesFromVariable( depth: number, originalObjectName: string, valuePath: Array, + isChildOfArray: boolean, ): Array { switch (variable.type) { case 'primitive': @@ -100,11 +112,27 @@ function valuesFromVariable( depth: depth, valuePath: valuePath, disabled: false, + isChildOfArray: isChildOfArray, }, ] case 'array': + return valuesFromObject( + variable, + insertionCeiling, + depth, + originalObjectName, + valuePath, + isChildOfArray, + ) case 'object': - return valuesFromObject(variable, insertionCeiling, depth, originalObjectName, valuePath) + return valuesFromObject( + variable, + insertionCeiling, + depth, + originalObjectName, + valuePath, + isChildOfArray, + ) case 'jsx': return [ { @@ -115,6 +143,7 @@ function valuesFromVariable( depth: depth, valuePath: valuePath, disabled: false, + isChildOfArray: isChildOfArray, }, ] default: @@ -481,9 +510,14 @@ export function useVariablesInScopeForSelectedElement( ) return orderedVariablesInScope.flatMap((variable) => - valuesFromVariable(variable, variable.insertionCeiling, 0, variable.expression, [ - variable.expressionPathPart, - ]), + valuesFromVariable( + variable, + variable.insertionCeiling, + 0, + variable.expression, + [variable.expressionPathPart], + false, + ), ) }, [controlDescriptions, currentPropertyValue, mode, elementPath, variablesInScope, propertyPath]) From 6da61ebc0f713a385a071880b1ead7460212a123 Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Tue, 11 Jun 2024 11:17:53 -0400 Subject: [PATCH 059/103] fix line height icon name (#5895) quick fix for line height icon --- ...-16x16@2x-1.png => lineHeight-aqua-16x16@2x.png} | Bin ...16x16@2x-1.png => lineHeight-black-16x16@2x.png} | Bin ...-16x16@2x-1.png => lineHeight-blue-16x16@2x.png} | Bin ...16@2x-1.png => lineHeight-darkgray-16x16@2x.png} | Bin ...-16x16@2x-1.png => lineHeight-gray-16x16@2x.png} | Bin ...16x16@2x-1.png => lineHeight-green-16x16@2x.png} | Bin ...6@2x-1.png => lineHeight-lightaqua-16x16@2x.png} | Bin ...6@2x-1.png => lineHeight-lightblue-16x16@2x.png} | Bin ...6@2x-1.png => lineHeight-lightgray-16x16@2x.png} | Bin ...@2x-1.png => lineHeight-lightgreen-16x16@2x.png} | Bin ...2x-1.png => lineHeight-lightpurple-16x16@2x.png} | Bin ...6x16@2x-1.png => lineHeight-purple-16x16@2x.png} | Bin ...d-16x16@2x-1.png => lineHeight-red-16x16@2x.png} | Bin ...16x16@2x-1.png => lineHeight-white-16x16@2x.png} | Bin 14 files changed, 0 insertions(+), 0 deletions(-) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-aqua-16x16@2x-1.png => lineHeight-aqua-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-black-16x16@2x-1.png => lineHeight-black-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-blue-16x16@2x-1.png => lineHeight-blue-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-darkgray-16x16@2x-1.png => lineHeight-darkgray-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-gray-16x16@2x-1.png => lineHeight-gray-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-green-16x16@2x-1.png => lineHeight-green-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-lightaqua-16x16@2x-1.png => lineHeight-lightaqua-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-lightblue-16x16@2x-1.png => lineHeight-lightblue-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-lightgray-16x16@2x-1.png => lineHeight-lightgray-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-lightgreen-16x16@2x-1.png => lineHeight-lightgreen-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-lightpurple-16x16@2x-1.png => lineHeight-lightpurple-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-purple-16x16@2x-1.png => lineHeight-purple-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-red-16x16@2x-1.png => lineHeight-red-16x16@2x.png} (100%) rename editor/resources/editor/icons/light/inspector-element/{letterSpacing-white-16x16@2x-1.png => lineHeight-white-16x16@2x.png} (100%) diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-aqua-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-aqua-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-aqua-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-aqua-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-black-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-black-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-black-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-black-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-blue-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-blue-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-blue-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-blue-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-darkgray-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-darkgray-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-darkgray-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-darkgray-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-gray-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-gray-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-gray-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-gray-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-green-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-green-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-green-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-green-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightaqua-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-lightaqua-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-lightaqua-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-lightaqua-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightblue-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-lightblue-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-lightblue-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-lightblue-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightgray-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-lightgray-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-lightgray-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-lightgray-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightgreen-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-lightgreen-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-lightgreen-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-lightgreen-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-lightpurple-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-lightpurple-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-lightpurple-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-lightpurple-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-purple-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-purple-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-purple-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-purple-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-red-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-red-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-red-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-red-16x16@2x.png diff --git a/editor/resources/editor/icons/light/inspector-element/letterSpacing-white-16x16@2x-1.png b/editor/resources/editor/icons/light/inspector-element/lineHeight-white-16x16@2x.png similarity index 100% rename from editor/resources/editor/icons/light/inspector-element/letterSpacing-white-16x16@2x-1.png rename to editor/resources/editor/icons/light/inspector-element/lineHeight-white-16x16@2x.png From 5ad0c9860903c7d09a071babb49bcf1080d01ed7 Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Tue, 11 Jun 2024 15:05:23 -0400 Subject: [PATCH 060/103] Some more icons (#5898) uploading 12x12 minus symbol icons to use [here](https://github.com/orgs/concrete-utopia/projects/6/views/1?pane=issue&itemId=66076920), as well as a new special blue arrow to use [here](https://github.com/orgs/concrete-utopia/projects/6/views/1?pane=issue&itemId=66430293) --- .../icons/light/semantic/arrowOutOfBounds@2x.png | Bin 0 -> 1412 bytes .../icons/light/semantic/minus-aqua-12x12@2x.png | Bin 0 -> 505 bytes .../light/semantic/minus-black-12x12@2x.png | Bin 0 -> 499 bytes .../icons/light/semantic/minus-blue-12x12@2x.png | Bin 0 -> 507 bytes .../light/semantic/minus-darkgray-12x12@2x.png | Bin 0 -> 501 bytes .../icons/light/semantic/minus-gray-12x12@2x.png | Bin 0 -> 498 bytes .../light/semantic/minus-green-12x12@2x.png | Bin 0 -> 509 bytes .../light/semantic/minus-lightaqua-12x12@2x.png | Bin 0 -> 501 bytes .../light/semantic/minus-lightblue-12x12@2x.png | Bin 0 -> 501 bytes .../light/semantic/minus-lightgray-12x12@2x.png | Bin 0 -> 502 bytes .../light/semantic/minus-lightgreen-12x12@2x.png | Bin 0 -> 501 bytes .../semantic/minus-lightpurple-12x12@2x.png | Bin 0 -> 502 bytes .../light/semantic/minus-purple-12x12@2x.png | Bin 0 -> 506 bytes .../icons/light/semantic/minus-red-12x12@2x.png | Bin 0 -> 499 bytes .../light/semantic/minus-white-12x12@2x.png | Bin 0 -> 486 bytes 15 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 editor/resources/editor/icons/light/semantic/arrowOutOfBounds@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-aqua-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-black-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-blue-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-darkgray-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-gray-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-green-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-lightaqua-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-lightblue-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-lightgray-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-lightgreen-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-lightpurple-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-purple-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-red-12x12@2x.png create mode 100644 editor/resources/editor/icons/light/semantic/minus-white-12x12@2x.png diff --git a/editor/resources/editor/icons/light/semantic/arrowOutOfBounds@2x.png b/editor/resources/editor/icons/light/semantic/arrowOutOfBounds@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0d4a28016dc34fa80840411d915bd53551010b45 GIT binary patch literal 1412 zcmV-~1$+95P)^0Wobi0P(*2SaBN|DAW$;^0C=2rkiAR8P!z>at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?d+NjlC zC01~aiG?TyodrfZ3dF`p!*yV_*hpo#2DLCb5;38>1q$p~tte#2_ikssnc3Of8+HjM z@+FhKnVp^a=DqK|nK^(9WP_YZXU5ndJ}SKGVcE{*axVM}KyntAO{T{poHsbZ7VC~C zxAM7>bXadVAB*C|w#sCy<+IhM&-RYAM4!PKpfBOQEmk&meVAPJ+rI~j03RRs!Km!y zMI_q5VA_TZkxzJUiIuHZ=l9QJfa=Qc_EQ1L!-5QvMA8#0W0&NY2l)1>bE1A@VOfC; zkwkJ`tW1>h@aVey$%kDA3!A?BotsGkvN|%AuBfa(4(GeO0lI26k$Z z3E&ClPnEcccg;?ApoM-{vIPjTFe1r`(&}c!whLPSN&kkuwp zpP}{kk7QR56ysf;iX^{Q(DoKN@zBomQc3h;AVu{ET}dV#dgBOIIJwx}gHB94hk+(T zY`OYC(ge*Oq#?-@y3+y+QV@dDSBtg0J&~c5@ONfqJ8JM73A}6FuLH$Le z^NAKZE2@WHQqa`b8NzxUd35Foj`(8l)8(##udZHZhM2+7B(t++gSdLisXl44x0^b(vEcqWd z6I66_r4P>z>F^G1@p6SfsjZaoxeI}t8@iX7kxT*${=XC#5+at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?zzVaoP vlK{ZvwvtMdM$nzEn&TS0?8|d6TL3?s-|__pV0D;c00000NkvXXu0mjf4=UNv literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/minus-black-12x12@2x.png b/editor/resources/editor/icons/light/semantic/minus-black-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..699fe6e3ee99196553993ba0410a8153492457cd GIT binary patch literal 499 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?7Vj@e`- p0C+0*h={S%^k>@c=codJd<%Yd1q9G~0ucZJ002ovPDHLkV1mQz)lUEb literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/minus-blue-12x12@2x.png b/editor/resources/editor/icons/light/semantic/minus-blue-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d8445b09d98c351c8f0dbe3495198c0e51f60f2d GIT binary patch literal 507 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?ntf8ZnD4tOIzv7BZ xE++wi$!$&Ub!OC^rV`Rxc-fcdUbX;!HUK6v1P1dt1epK;002ovPDHLkV1n_!+1vmC literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/minus-darkgray-12x12@2x.png b/editor/resources/editor/icons/light/semantic/minus-darkgray-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a4f9ffc95f23e090f8ffffdb18532f87c8051092 GIT binary patch literal 501 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?SXSrT=R# zx#V&p0H88^;c~1qyxeI$m9Q38eLV281@N^2rtk#@KD>r200000NkvXXu0mjfWZ~M3 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/minus-lightaqua-12x12@2x.png b/editor/resources/editor/icons/light/semantic/minus-lightaqua-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..baf8a5b728a29a0b28ebd36cf9bcc96eb9c5779d GIT binary patch literal 501 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?gce4HruU5{H1OV|C@OA|R8^SKk00000NkvXXu0mjfat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?emI^BO=;*p8(*!34JdJ1pPL{(*OVf07*qoM6N<$f_9kKjQ{`u literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/minus-lightgreen-12x12@2x.png b/editor/resources/editor/icons/light/semantic/minus-lightgreen-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5b8e9455dfcc0c0bc2b91e5fdff9c87435731e47 GIT binary patch literal 501 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?6pcjln){kd rP6B`@yGNe2??n9>%}P2)5CHgF%(evtdX{5d00000NkvXXu0mjfa6r}a literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/minus-lightpurple-12x12@2x.png b/editor/resources/editor/icons/light/semantic/minus-lightpurple-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..544cd86804043a569599f08f49326e2e0018d5ef GIT binary patch literal 502 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?M#PdCh&z sB_{#Elij1$*>|G;j9e_8BM1QeE%bH;1jPmjR{#J207*qoM6N<$f_;A19RL6T literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/minus-purple-12x12@2x.png b/editor/resources/editor/icons/light/semantic/minus-purple-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..085de382b7061dc00b9e1241900920eb9fbe2076 GIT binary patch literal 506 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?z>%07*qoM6N<$g0$V)0{{R3 literal 0 HcmV?d00001 diff --git a/editor/resources/editor/icons/light/semantic/minus-red-12x12@2x.png b/editor/resources/editor/icons/light/semantic/minus-red-12x12@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9bad6058ea54a21e47361cd163463315ceb91867 GIT binary patch literal 499 zcmVat5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?@P)at5VQ9hz=bbGKoXf z(h7EQXe$&&FjNJrQ<{DWZG0ptQgIVkDfk~)!C7#yh*WTKa1cZX5#5|RDY$5O-j`I` zBHqX4{WzR+xm>^-P#G)s0x0R0kxay-wbZ)gdxM9bQ>tdNsG=+i{{6e_^U?L*Pl#Df zyLJ%SPh6MIE|+$m0#kqeUDcn-ni~Dz)Ip6I7T}SIm2Ha&-X$I}Xer{V;JnMng3~Ua zJD!zfocNYl(h6#ZxJfLhJM?@9mx^VrwS(B+pVe2F#T@EU%wZEI7>ZC)fdmENfBe&q zKaMSOS71;sj{+>pL`e}7vc&VypY?`La=`luFqi^{?+ cuLJ=98s+3agCVud!vFvP07*qoM6N<$g11`E&;S4c literal 0 HcmV?d00001 From 60fff8a5ecb00de9be6f5a1d38f8904dcad15251 Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Wed, 12 Jun 2024 11:42:15 +0300 Subject: [PATCH 061/103] Prevent keystrokes from leaking (fix regression) (#5889) **Problem:** Recent upgrade to `react-contexify` caused a regression where there was a race condition between registering and unregistering open menus - so that the code that ignored editor keystrokes when a menu was open was broken **Fix:** Store the open menu ids in a set - to prevent a race condition with overriding the classname on the body This fixes the keystrokes leak and allow keyboard navigation (arrows) - [X] I opened a hydrogen project and it loaded - [X] I could navigate to various routes in Preview mode Related to #5875 --- .../src/components/context-menu-wrapper.tsx | 18 ++++++++++------ .../editor/editor-component-common.tsx | 7 ++----- .../components/editor/editor-component.tsx | 7 ++++++- editor/src/core/shared/menu-state.ts | 21 +++++++++++++++++++ 4 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 editor/src/core/shared/menu-state.ts diff --git a/editor/src/components/context-menu-wrapper.tsx b/editor/src/components/context-menu-wrapper.tsx index 418f695ea9e9..5525fd593e86 100644 --- a/editor/src/components/context-menu-wrapper.tsx +++ b/editor/src/components/context-menu-wrapper.tsx @@ -15,7 +15,7 @@ import type { ContextMenuItem } from './context-menu-items' import type { EditorDispatch } from './editor/action-types' import type { WindowPoint } from '../core/shared/math-utils' import { windowPoint } from '../core/shared/math-utils' -import { BodyMenuOpenClass } from '../core/shared/utils' +import { addOpenMenuId, removeOpenMenuId } from '../core/shared/menu-state' interface Submenu { items: Item[] @@ -56,12 +56,18 @@ export interface ContextMenuProps { items: ContextMenuItem[] } -const onVisibilityChange = (isVisible: boolean) => { - if (isVisible) document.body.classList.add(BodyMenuOpenClass) - else document.body.classList.remove(BodyMenuOpenClass) -} - export const ContextMenu = ({ dispatch, getData, id, items }: ContextMenuProps) => { + const onVisibilityChange = React.useCallback( + (isVisible: boolean) => { + if (isVisible) { + addOpenMenuId(id) + } else { + removeOpenMenuId(id) + } + }, + [id], + ) + const splitItems = React.useMemo(() => { const tempItems: MenuItem[] = [] diff --git a/editor/src/components/editor/editor-component-common.tsx b/editor/src/components/editor/editor-component-common.tsx index b182a9445d58..fe78225abb39 100644 --- a/editor/src/components/editor/editor-component-common.tsx +++ b/editor/src/components/editor/editor-component-common.tsx @@ -1,7 +1,7 @@ import React from 'react' import type { EditorAction, EditorDispatch } from './action-types' import { useDispatch } from './store/dispatch-context' -import { BodyMenuOpenClass } from '../../core/shared/utils' +import { isSomeMenuOpen } from '../../core/shared/menu-state' type EventHandler = (this: Window, event: WindowEventMap[K]) => R @@ -52,10 +52,7 @@ function createHandler( } else { const windowEventHandler = (event: WindowEventMap[K]) => { // check if it's a keyboard event and if react-contexify is open - if ( - ['keydown', 'keyup'].includes(event.type) && - document.body.classList.contains(BodyMenuOpenClass) - ) { + if (['keydown', 'keyup'].includes(event.type) && isSomeMenuOpen()) { return } const collatedActions = handlers.flatMap((handler) => { diff --git a/editor/src/components/editor/editor-component.tsx b/editor/src/components/editor/editor-component.tsx index 117cabbe7b20..4484d9c0772d 100644 --- a/editor/src/components/editor/editor-component.tsx +++ b/editor/src/components/editor/editor-component.tsx @@ -3,7 +3,7 @@ /** @jsxFrag React.Fragment */ import { css, jsx, keyframes } from '@emotion/react' import { chrome as isChrome } from 'platform-detect' -import React from 'react' +import React, { useEffect } from 'react' import ReactDOM from 'react-dom' import { DndProvider } from 'react-dnd' import { HTML5Backend } from 'react-dnd-html5-backend' @@ -92,6 +92,7 @@ import { } from '../navigator/navigator-item/component-picker-context-menu' import { useGithubPolling } from '../../core/shared/github/helpers' import { useAtom } from 'jotai' +import { clearOpenMenuIds } from '../../core/shared/menu-state' const liveModeToastId = 'play-mode-toast' @@ -233,6 +234,10 @@ export const EditorComponentInner = React.memo((props: EditorProps) => { const showComponentPicker = useCreateCallbackToShowComponentPicker() + React.useEffect(() => { + clearOpenMenuIds() + }, []) + const onWindowKeyDown = React.useCallback( (event: KeyboardEvent) => { let actions: Array = [] diff --git a/editor/src/core/shared/menu-state.ts b/editor/src/core/shared/menu-state.ts new file mode 100644 index 000000000000..5b284467bf0d --- /dev/null +++ b/editor/src/core/shared/menu-state.ts @@ -0,0 +1,21 @@ +const openMenuIds = new Set() + +export const addOpenMenuId = (id: string) => { + openMenuIds.add(id) +} + +export const removeOpenMenuId = (id: string) => { + openMenuIds.delete(id) +} + +export const isMenuOpen = (id: string) => { + return openMenuIds.has(id) +} + +export const isSomeMenuOpen = () => { + return openMenuIds.size > 0 +} + +export const clearOpenMenuIds = () => { + openMenuIds.clear() +} From 75e5db7082496cfc480c41d96c2d23a9e2400a02 Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Wed, 12 Jun 2024 10:48:53 +0100 Subject: [PATCH 062/103] Reduce LocalForage Pressure. (#5893) - Created `getDescendentPathsWithAllPaths` and `childPathsWithAllPaths` that use an existing array of paths. - Changed `onPolledWatch` to work against the entire `Map` of entries instead of a single entry and have it upfront call `keys()`. - `withSanityCheckedStore` now doesn't call `getItem` all the time. --- utopia-vscode-common/src/fs/fs-core.ts | 32 ++++++- utopia-vscode-common/src/fs/fs-utils.ts | 118 +++++++++++++----------- 2 files changed, 97 insertions(+), 53 deletions(-) diff --git a/utopia-vscode-common/src/fs/fs-core.ts b/utopia-vscode-common/src/fs/fs-core.ts index 091cff148729..940211be00ae 100644 --- a/utopia-vscode-common/src/fs/fs-core.ts +++ b/utopia-vscode-common/src/fs/fs-core.ts @@ -58,12 +58,42 @@ export function isStoreDoesNotExist(t: unknown): t is StoreDoesNotExist { export type AsyncFSResult = Promise> +const StoreExistsKeyInterval = 1000 + +interface StoreKeyExistsCheck { + lastCheckedTime: number + exists: boolean +} + +let lastCheckedForStoreKeyExists: StoreKeyExistsCheck | null = null + +async function checkStoreKeyExists(): Promise { + if (store == null) { + return false + } else { + const now = Date.now() + if ( + lastCheckedForStoreKeyExists == null || + lastCheckedForStoreKeyExists.lastCheckedTime + StoreExistsKeyInterval < now + ) { + const exists = (await store.getItem(StoreExistsKey)) ?? false + lastCheckedForStoreKeyExists = { + lastCheckedTime: now, + exists: exists, + } + return exists + } else { + return lastCheckedForStoreKeyExists.exists + } + } +} + async function withSanityCheckedStore( withStore: (sanityCheckedStore: LocalForage) => Promise, ): AsyncFSResult { await firstInitialize await initializeStoreChain - const storeExists = store != null && (await store.getItem(StoreExistsKey)) + const storeExists = await checkStoreKeyExists() if (store != null && storeExists) { const result = await withStore(store) return right(result) diff --git a/utopia-vscode-common/src/fs/fs-utils.ts b/utopia-vscode-common/src/fs/fs-utils.ts index 1966dbf67f4c..d72231b81e25 100644 --- a/utopia-vscode-common/src/fs/fs-utils.ts +++ b/utopia-vscode-common/src/fs/fs-utils.ts @@ -174,9 +174,16 @@ export async function stat(path: string): Promise { return fsStatForNode(node) } +export function getDescendentPathsWithAllPaths( + path: string, + allPaths: Array, +): Array { + return allPaths.filter((k) => k != path && k.startsWith(path)) +} + export async function getDescendentPaths(path: string): Promise { const allPaths = await keys() - return allPaths.filter((k) => k != path && k.startsWith(path)) + return getDescendentPathsWithAllPaths(path, allPaths) } async function targetsForOperation(path: string, recursive: boolean): Promise { @@ -207,12 +214,17 @@ function filenameOfPath(path: string): string { return lastSlashIndex >= 0 ? path.slice(lastSlashIndex + 1) : path } -export async function childPaths(path: string): Promise { - const allDescendents = await getDescendentPaths(path) +export function childPathsWithAllPaths(path: string, allPaths: Array): Array { + const allDescendents = getDescendentPathsWithAllPaths(path, allPaths) const pathAsDir = stripTrailingSlash(path) return allDescendents.filter((k) => getParentPath(k) === pathAsDir) } +export async function childPaths(path: string): Promise { + const allDescendents = await getDescendentPaths(path) + return childPathsWithAllPaths(path, allDescendents) +} + async function getDirectory(path: string): Promise { const node = await getNode(path) if (isDirectory(node)) { @@ -458,66 +470,68 @@ function isFSUnavailableError(e: unknown): boolean { type FileModifiedStatus = 'modified' | 'not-modified' | 'unknown' -async function onPolledWatch(path: string, config: WatchConfig): Promise { - const { recursive, onCreated, onModified, onDeleted } = config - - try { - const node = await getItem(path) - if (node == null) { - watchedPaths.delete(path) - lastModifiedTSs.delete(path) - onDeleted(path) - return 'modified' - } else { - const stats = fsStatForNode(node) - - const modifiedTS = stats.mtime - const wasModified = modifiedTS > (lastModifiedTSs.get(path) ?? 0) - const modifiedBySelf = stats.sourceOfLastChange === fsUser - - if (isDirectory(node)) { - if (recursive) { - const children = await childPaths(path) - const unsupervisedChildren = children.filter((p) => !watchedPaths.has(p)) - unsupervisedChildren.forEach((childPath) => { - watchPath(childPath, config) - onCreated(childPath) - }) - if (unsupervisedChildren.length > 0) { +async function onPolledWatch(paths: Map): Promise> { + const allKeys = await keys() + const results = Array.from(paths).map(async ([path, config]) => { + const { recursive, onCreated, onModified, onDeleted } = config + + try { + const node = await getItem(path) + if (node == null) { + watchedPaths.delete(path) + lastModifiedTSs.delete(path) + onDeleted(path) + return 'modified' + } else { + const stats = fsStatForNode(node) + + const modifiedTS = stats.mtime + const wasModified = modifiedTS > (lastModifiedTSs.get(path) ?? 0) + const modifiedBySelf = stats.sourceOfLastChange === fsUser + + if (isDirectory(node)) { + if (recursive) { + const children = childPathsWithAllPaths(path, allKeys) + const unsupervisedChildren = children.filter((p) => !watchedPaths.has(p)) + unsupervisedChildren.forEach((childPath) => { + watchPath(childPath, config) + onCreated(childPath) + }) + if (unsupervisedChildren.length > 0) { + onModified(path, modifiedBySelf) + lastModifiedTSs.set(path, modifiedTS) + return 'modified' + } + } + } else { + if (wasModified) { onModified(path, modifiedBySelf) lastModifiedTSs.set(path, modifiedTS) return 'modified' } } - } else { - if (wasModified) { - onModified(path, modifiedBySelf) - lastModifiedTSs.set(path, modifiedTS) - return 'modified' - } - } - return 'not-modified' - } - } catch (e) { - if (isFSUnavailableError(e)) { - // Explicitly handle unavailable errors here by removing the watchers, then re-throw - watchedPaths.delete(path) - lastModifiedTSs.delete(path) - throw e + return 'not-modified' + } + } catch (e) { + if (isFSUnavailableError(e)) { + // Explicitly handle unavailable errors here by removing the watchers, then re-throw + watchedPaths.delete(path) + lastModifiedTSs.delete(path) + throw e + } + // Something was changed mid-poll, likely the file or its parent was deleted. We'll catch it on the next poll. + return 'unknown' } - // Something was changed mid-poll, likely the file or its parent was deleted. We'll catch it on the next poll. - return 'unknown' - } + }) + return Promise.all(results) } async function polledWatch(): Promise { - let promises: Array> = [] - watchedPaths.forEach((config, path) => { - promises.push(onPolledWatch(path, config)) - }) + let promises: Array>> = [] + promises.push(onPolledWatch(watchedPaths)) - const results = await Promise.all(promises) + const results = await Promise.all(promises).then((nestedResults) => nestedResults.flat()) let shouldReducePollingFrequency = true for (var i = 0, len = results.length; i < len; i++) { From ff3ff9783424776cebf1d1bfef0a25e2ff92daf4 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Wed, 12 Jun 2024 12:27:08 +0200 Subject: [PATCH 063/103] Data Picker: Left Sidebar displaying Sources (#5900) image **Commit Details:** - The root element of the data picker is now a FlexRow - New `DataSelectorLeftSidebar` component in its own file - Removed bottom scope breadcrumbs **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [ ] I could navigate to various routes in Preview mode --- .../component-section/data-picker-utils.tsx | 6 +- .../data-selector-columns.tsx | 22 +- .../data-selector-left-sidebar.tsx | 101 +++++++++ .../component-section/data-selector-modal.tsx | 210 ++++++++---------- 4 files changed, 212 insertions(+), 127 deletions(-) create mode 100644 editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 2b3b46558ac0..73805a5907ed 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -89,12 +89,12 @@ export function getEnclosingScopes( buckets: Array, lowestInsertionCeiling: ElementPath, ): Array<{ - insertionCeiling: ElementPath + insertionCeiling: ElementPath | FileRootPath label: string hasContent: boolean }> { let result: Array<{ - insertionCeiling: ElementPath + insertionCeiling: ElementPath | FileRootPath label: string hasContent: boolean }> = [] @@ -128,7 +128,7 @@ export function getEnclosingScopes( // Add file root result.unshift({ - insertionCeiling: EP.emptyElementPath, + insertionCeiling: { type: 'file-root' }, label: 'File', hasContent: buckets.includes(insertionCeilingToString({ type: 'file-root' })), }) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx index 81c85d53d074..6c02e9223cfd 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -189,19 +189,13 @@ const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { const ref = useScrollIntoView(selected) return ( - @@ -214,7 +208,7 @@ const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { > {'>'} - + ) }) @@ -232,6 +226,16 @@ const DataSelectorFlexColumn = styled(FlexColumn)({ borderRight: `1px solid ${colorTheme.subduedBorder.cssValue}`, }) +export const DataPickerRow = styled(FlexRow)((props: { disabled: boolean }) => ({ + alignSelf: 'stretch', + justifyContent: 'space-between', + fontSize: 10, + borderRadius: 4, + height: 24, + padding: 5, + cursor: !props.disabled ? 'pointer' : 'initial', +})) + function useScrollIntoView(shouldScroll: boolean) { const elementRef = React.useRef(null) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx b/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx new file mode 100644 index 000000000000..2286cecb22ea --- /dev/null +++ b/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx @@ -0,0 +1,101 @@ +import React from 'react' +import type { ElementPath } from 'utopia-shared/src/types' +import { FlexColumn, FlexRow, LargerIcons, colorTheme } from '../../../../uuiui' +import { + insertionCeilingToString, + insertionCeilingsEqual, + type FileRootPath, +} from '../../../canvas/ui-jsx-canvas' +import { stopPropagation } from '../../common/inspector-utils' +import { DataPickerRow } from './data-selector-columns' + +interface SelectableScope { + label: string + scope: ElementPath | FileRootPath + hasContent: boolean +} + +interface DataSelectorLeftSidebarProps { + scopes: Array + activeScope: ElementPath | FileRootPath + setSelectedScope: (scope: ElementPath | FileRootPath) => void +} + +export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSidebarProps) => { + const { scopes, setSelectedScope, activeScope } = props + return ( + + + + + + Sources + + + {scopes.map((scope) => { + return ( + + ) + })} + + + ) +}) + +const ScopeRow = React.memo( + (props: { + scope: SelectableScope + selected: boolean + disabled: boolean + setSelectedScope: (scope: ElementPath | FileRootPath) => void + }) => { + const { scope, selected, disabled, setSelectedScope } = props + + const onClick = React.useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + if (!disabled) { + setSelectedScope(scope.scope) + } + }, + [setSelectedScope, disabled, scope.scope], + ) + + return ( + + {scope.label} + + ) + }, +) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 97a9c5b75f3a..dca580471c38 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -44,6 +44,7 @@ import type { FileRootPath } from '../../../canvas/ui-jsx-canvas' import { insertionCeilingToString, insertionCeilingsEqual } from '../../../canvas/ui-jsx-canvas' import { set } from 'objectPath' import { DataSelectorColumns } from './data-selector-columns' +import { DataSelectorLeftSidebar } from './data-selector-left-sidebar' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -160,14 +161,12 @@ export const DataSelectorModal = React.memo( const [selectedScope, setSelectedScope] = React.useState( lowestMatchingScope, ) - const setSelectedScopeCurried = React.useCallback( - (name: ElementPath, hasContent: boolean) => () => { - if (hasContent) { - setSelectedScope(name) - setSelectedPath([]) - setHoveredPath(null) - setNavigatedToPath([]) - } + const setSelectedScopeAndResetSelection = React.useCallback( + (scope: ElementPath | FileRootPath) => { + setSelectedScope(scope) + setSelectedPath([]) + setHoveredPath(null) + setNavigatedToPath([]) }, [], ) @@ -401,15 +400,11 @@ export const DataSelectorModal = React.memo( }} onClick={closePopup} > - - {/* top bar */} - - - + + + {/* top bar */} + + - {pathBreadcrumbs(pathInTopBarIncludingHover, processedVariablesInScope).map( - ({ segment, path }, idx) => ( - - {idx === 0 ? segment : pathSegmentToString(segment)} - - ), - )} - -
- -
+ + {pathBreadcrumbs(pathInTopBarIncludingHover, processedVariablesInScope).map( + ({ segment, path }, idx) => ( + + {idx === 0 ? segment : pathSegmentToString(segment)} + + ), + )} + +
+ +
+
+
+ Apply +
-
- Apply -
-
- {/* Value preview */} - - {valuePreviewText} - - - - + {valuePreviewText} +
+ + + +
- {/* Scope Selector Breadcrumbs */} - - {elementLabelsWithScopes.map(({ label, scope, hasContent }, idx, a) => ( - -
- {label} -
- {idx < a.length - 1 ? ( - {'/'} - ) : null} -
- ))} -
- +
) From ce93643363bf2201754148cf87d1a9e6c501e0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Wed, 12 Jun 2024 15:15:09 +0200 Subject: [PATCH 064/103] Data picker: Search (#5852) ## Description This PR adds a search mode for the data picker image **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #[ticket_number] (<< pls delete this line if it's not relevant) --------- Co-authored-by: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> --- editor/package.json | 2 + editor/pnpm-lock.yaml | 15 +- .../component-section/cartouche-ui.tsx | 10 +- .../component-section/data-picker-utils.tsx | 1 + .../data-selector-cartouche.tsx | 21 +- .../data-selector-left-sidebar.tsx | 25 +- .../component-section/data-selector-modal.tsx | 527 +++++++----------- .../data-selector-search.tsx | 246 ++++++++ 8 files changed, 482 insertions(+), 365 deletions(-) create mode 100644 editor/src/components/inspector/sections/component-section/data-selector-search.tsx diff --git a/editor/package.json b/editor/package.json index 3e71362cdc8e..35c50e5dbf6f 100644 --- a/editor/package.json +++ b/editor/package.json @@ -209,6 +209,7 @@ "lodash.clamp": "4.0.3", "lodash.debounce": "4.0.8", "lodash.findlastindex": "4.6.0", + "lodash.throttle": "4.1.1", "lru-cache": "7.10.1", "matter-js": "git://github.com/liabru/matter-js.git#e909b0466cea2051267bab92a38ccaa9bf7f154e", "mime-types": "2.1.24", @@ -319,6 +320,7 @@ "@types/jquery": "3.3.29", "@types/json-schema": "6.0.0", "@types/json5": "0.0.29", + "@types/lodash.throttle": "4.1.9", "@types/matter-js": "0.10.0", "@types/mime-types": "2.1.0", "@types/minimatch": "3.0.4", diff --git a/editor/pnpm-lock.yaml b/editor/pnpm-lock.yaml index 0dcfd6a4257d..a7acf6d7be82 100644 --- a/editor/pnpm-lock.yaml +++ b/editor/pnpm-lock.yaml @@ -105,6 +105,7 @@ specifiers: '@types/json-schema': 6.0.0 '@types/json5': 0.0.29 '@types/lodash.findlastindex': 4.6.7 + '@types/lodash.throttle': 4.1.9 '@types/matter-js': 0.10.0 '@types/mime-types': 2.1.0 '@types/minimatch': 3.0.4 @@ -236,6 +237,7 @@ specifiers: lodash.clamp: 4.0.3 lodash.debounce: 4.0.8 lodash.findlastindex: 4.6.0 + lodash.throttle: 4.1.1 lru-cache: 7.10.1 matter-js: git://github.com/liabru/matter-js.git#e909b0466cea2051267bab92a38ccaa9bf7f154e mime-types: 2.1.24 @@ -420,6 +422,7 @@ dependencies: lodash.clamp: 4.0.3 lodash.debounce: 4.0.8 lodash.findlastindex: 4.6.0 + lodash.throttle: 4.1.1 lru-cache: 7.10.1 matter-js: github.com/liabru/matter-js/e909b0466cea2051267bab92a38ccaa9bf7f154e mime-types: 2.1.24 @@ -533,6 +536,7 @@ devDependencies: '@types/jquery': 3.3.29 '@types/json-schema': 6.0.0 '@types/json5': 0.0.29 + '@types/lodash.throttle': 4.1.9 '@types/matter-js': 0.10.0 '@types/mime-types': 2.1.0 '@types/minimatch': 3.0.4 @@ -4855,9 +4859,14 @@ packages: '@types/lodash': 4.14.198 dev: false + /@types/lodash.throttle/4.1.9: + resolution: {integrity: sha512-PCPVfpfueguWZQB7pJQK890F2scYKoDUL3iM522AptHWn7d5NQmeS/LTEHIcLr5PaTzl3dK2Z0xSUHHTHwaL5g==} + dependencies: + '@types/lodash': 4.14.198 + dev: true + /@types/lodash/4.14.198: resolution: {integrity: sha512-trNJ/vtMZYMLhfN45uLq4ShQSw0/S7xCTLLVM+WM1rmFpba/VS42jVUgaO3w/NOLiWR/09lnYk0yMaA/atdIsg==} - dev: false /@types/matter-js/0.10.0: resolution: {integrity: sha512-7KUBacbLrPF8bHf1rtI8/y2t3D2lmMKfQVfuessIl02x5OWsP/IRjo8Jn4r1/NuJlMbxyH72zPyNhS+TeRR77A==} @@ -13229,6 +13238,10 @@ packages: /lodash.merge/4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + /lodash.throttle/4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + dev: false + /lodash.truncate/4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 04a55e65aeea..7449abfbd8ed 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -60,6 +60,8 @@ export const CartoucheUI = React.forwardRef( // NOTE: this is currently unused, we should decide if we want to keep allowing deletion of the cartouches from here or not const wrappedOnDelete = useStopPropagation(onDelete) + const shouldUseRtlCSS = typeof props.children === 'string' + return (
{children} diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 73805a5907ed..5b406b4e884e 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -17,6 +17,7 @@ import type { ProjectContentTreeRoot } from '../../../assets' import { insertionCeilingToString, type FileRootPath } from '../../../canvas/ui-jsx-canvas' import type { AllElementProps } from '../../../editor/store/editor-state' import type { ArrayInfo, JSXInfo, ObjectInfo, PrimitiveInfo } from './variables-in-scope-utils' +import type { CartoucheUIProps } from './cartouche-ui' interface VariableOptionBase { depth: number diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx index 5187c6d2198e..f0eaa9dc4c86 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -11,13 +11,17 @@ import { CartoucheUI } from './cartouche-ui' import type { DataPickerOption } from './data-picker-utils' export const DataPickerCartouche = React.memo( - (props: { - data: DataPickerOption - forcedDataSource?: CartoucheSource | null // if the DataPickerOption is actually a child (of a child) of a variable, we need to provide the CartoucheSource that belongs to the original variable - selected: boolean - }) => { + ( + props: React.PropsWithChildren<{ + data: DataPickerOption + forcedDataSource?: CartoucheSource | null // if the DataPickerOption is actually a child (of a child) of a variable, we need to provide the CartoucheSource that belongs to the original variable + selected: boolean + onClick?: CartoucheUIProps['onClick'] + }>, + ) => { const { data, forcedDataSource, selected } = props const dataSource = useVariableDataSource(data) + const children = props.children ?? data.variableInfo.expressionPathPart return ( ) : undefined } + onClick={props.onClick} > {data.isChildOfArray ? ( <> - item - {data.variableInfo.expressionPathPart} + item + {children} ) : ( - data.variableInfo.expressionPathPart + children )} ) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx b/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx index 2286cecb22ea..7b25f2e76946 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx @@ -24,28 +24,7 @@ interface DataSelectorLeftSidebarProps { export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSidebarProps) => { const { scopes, setSelectedScope, activeScope } = props return ( - - - - + <> Sources @@ -62,7 +41,7 @@ export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSideba ) })} - + ) }) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index dca580471c38..3ec16a087a54 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -1,9 +1,11 @@ import React from 'react' -import { groupBy, isPrefixOf, last } from '../../../../core/shared/array-utils' +import { groupBy } from '../../../../core/shared/array-utils' +import * as EP from '../../../../core/shared/element-path' import { jsExpressionOtherJavaScriptSimple } from '../../../../core/shared/element-template' +import { optionalMap } from '../../../../core/shared/optional-utils' +import type { ElementPath } from '../../../../core/shared/project-file-types' import { CanvasContextMenuPortalTargetID, - NO_OP, arrayEqualsByReference, assertNever, } from '../../../../core/shared/utils' @@ -12,39 +14,25 @@ import { FlexColumn, FlexRow, Icons, - PopupList, + LargerIcons, UtopiaStyles, UtopiaTheme, useColorTheme, } from '../../../../uuiui' -import { getControlStyles } from '../../common/control-styles' -import type { SelectOption } from '../../controls/select-control' +import type { FileRootPath } from '../../../canvas/ui-jsx-canvas' +import { insertionCeilingToString } from '../../../canvas/ui-jsx-canvas' +import { Substores, useEditorState } from '../../../editor/store/store-hook' import { InspectorModal } from '../../widgets/inspector-modal' -import type { CartoucheUIProps, HoverHandlers } from './cartouche-ui' -import { CartoucheUI } from './cartouche-ui' import { - type ArrayOption, + getEnclosingScopes, type DataPickerCallback, - type JSXOption, - type ObjectOption, - type PrimitiveOption, type DataPickerOption, type ObjectPath, - getEnclosingScopes, } from './data-picker-utils' -import { - dataPathSuccess, - traceDataFromVariableName, -} from '../../../../core/data-tracing/data-tracing' -import type { ElementPath } from '../../../../core/shared/project-file-types' -import * as EP from '../../../../core/shared/element-path' -import { Substores, useEditorState } from '../../../editor/store/store-hook' -import { optionalMap } from '../../../../core/shared/optional-utils' -import type { FileRootPath } from '../../../canvas/ui-jsx-canvas' -import { insertionCeilingToString, insertionCeilingsEqual } from '../../../canvas/ui-jsx-canvas' -import { set } from 'objectPath' import { DataSelectorColumns } from './data-selector-columns' import { DataSelectorLeftSidebar } from './data-selector-left-sidebar' +import { DataSelectorSearch } from './data-selector-search' +import { stopPropagation } from '../../common/inspector-utils' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -57,69 +45,10 @@ export interface DataSelectorModalProps { lowestInsertionCeiling: ElementPath | null } -const Separator = React.memo( - ({ - color, - spanGridColumns, - margin, - }: { - color: string - spanGridColumns?: number - margin: number - }) => { - return ( -
- ) - }, -) - -const SIMPLE_CONTROL_STYLES = getControlStyles('simple') - -function ArrayIndexSelector({ - total, - selected, - onSelect, -}: { - total: number - selected: number - onSelect: (_: SelectOption) => void -}) { - const options: SelectOption[] = React.useMemo( - () => - Array(total) - .fill(0) - .map((_, i) => ({ value: i, label: `${i + 1}` })), - [total], - ) - - return ( - - ) -} - interface ProcessedVariablesInScope { [valuePath: string]: DataPickerOption } -interface ArrayIndexLookup { - [valuePath: string]: number -} - export const DataSelectorModal = React.memo( React.forwardRef( ( @@ -177,7 +106,9 @@ export const DataSelectorModal = React.memo( selectedScope, ) - const processedVariablesInScope = useProcessVariablesInScope(filteredVariablesInScope) + const processedVariablesInScope = useProcessVariablesInScope(allVariablesInScope) + + const searchBoxRef = React.useRef(null) const elementLabelsWithScopes = useEditorState( Substores.fullStore, @@ -206,6 +137,27 @@ export const DataSelectorModal = React.memo( const [selectedPath, setSelectedPath] = React.useState( startingSelectedValuePath ?? [], ) + + const [searchTerm, setSearchTerm] = React.useState(null) + const onStartSearch = React.useCallback(() => { + searchBoxRef.current?.focus() + setSearchTerm('') + }, []) + + const cancelSearch = React.useCallback(() => { + setSearchTerm(null) + searchBoxRef.current?.blur() + }, []) + + const onSearchFieldValueChange = React.useCallback( + (e: React.ChangeEvent) => { + e.stopPropagation() + e.preventDefault() + setSearchTerm(e.target.value) + }, + [], + ) + const [hoveredPath, setHoveredPath] = React.useState(null) const setSelectedPathFromColumns = React.useCallback((newPath: ObjectPath) => { @@ -241,141 +193,51 @@ export const DataSelectorModal = React.memo( e.preventDefault() }, []) - const onHover = React.useCallback( - (path: DataPickerOption['valuePath']): HoverHandlers => ({ - onMouseEnter: () => setHoveredPath(path), - onMouseLeave: () => setHoveredPath(null), - }), - [], - ) - - const [indexLookup, setIndexLookup] = React.useState({}) - const updateIndexInLookup = React.useCallback( - (valuePathString: string) => (option: SelectOption) => - setIndexLookup((lookup) => ({ ...lookup, [valuePathString]: option.value })), - [], - ) - - const focusedVariableChildren = React.useMemo(() => { - if (navigatedToPath.length === 0) { - return filteredVariablesInScope - } - - const innerScopeToShow = processedVariablesInScope[navigatedToPath.toString()] - if ( - innerScopeToShow == null || - (innerScopeToShow.type !== 'array' && innerScopeToShow.type !== 'object') - ) { - return [] // TODO this should never happen! - } - return innerScopeToShow.children - }, [navigatedToPath, processedVariablesInScope, filteredVariablesInScope]) - - const { primitiveVars, folderVars } = React.useMemo(() => { - let primitives: Array = [] - let folders: Array = [] - - for (const option of focusedVariableChildren) { - switch (option.type) { - case 'array': - case 'object': - folders.push(option) - break - case 'jsx': - case 'primitive': - primitives.push(option) - break - default: - assertNever(option) - } - } - - return { primitiveVars: primitives, folderVars: folders } - }, [focusedVariableChildren]) - - const metadata = useEditorState( - Substores.metadata, - (store) => store.editor.jsxMetadata, - 'DataSelectorModal metadata', - ) - const projectContents = useEditorState( - Substores.projectContents, - (store) => store.editor.projectContents, - 'DataSelectorModal projectContents', - ) - - const variableSources = React.useMemo(() => { - let result: { [valuePath: string]: CartoucheUIProps['source'] } = {} - for (const variable of focusedVariableChildren) { - const container = variable.variableInfo.insertionCeiling - const trace = traceDataFromVariableName( - container, - variable.variableInfo.expression, - metadata, - projectContents, - dataPathSuccess([]), - ) + const activeTargetPath = selectedPath ?? navigatedToPath + const pathInTopBarIncludingHover = hoveredPath ?? activeTargetPath - switch (trace.type) { - case 'hook-result': - result[variable.valuePath.toString()] = 'external' - break - case 'literal-attribute': - case 'literal-assignment': - result[variable.valuePath.toString()] = 'literal' - break - case 'component-prop': - case 'element-at-scope': - case 'failed': - result[variable.valuePath.toString()] = 'internal' - break - default: - assertNever(trace) + const applyVariable = React.useCallback( + (path: ObjectPath) => { + const variable = processedVariablesInScope[path.toString()] + if (variable == null) { + return } - } - return result - }, [focusedVariableChildren, metadata, projectContents]) - - const setCurrentSelectedPathCurried = React.useCallback( - (path: DataPickerOption['valuePath']) => () => { - if (!isPrefixOf(navigatedToPath, path)) { - // if navigatedToPath is not a prefix of path, we don't update the selection + if (variable.disabled) { return } - setSelectedPath(path) + onPropertyPicked( + jsExpressionOtherJavaScriptSimple(variable.variableInfo.expression, [ + variable.definedElsewhere, + ]), + ) + closePopup() }, - [navigatedToPath], + [closePopup, onPropertyPicked, processedVariablesInScope], ) - const activeTargetPath = selectedPath ?? navigatedToPath - const pathInTopBarIncludingHover = hoveredPath ?? activeTargetPath - - const onApplyClick = React.useCallback(() => { - const variable = processedVariablesInScope[activeTargetPath.toString()] - if (variable == null) { - return - } - if (variable.disabled) { - return - } - - onPropertyPicked( - jsExpressionOtherJavaScriptSimple(variable.variableInfo.expression, [ - variable.definedElsewhere, - ]), - ) - closePopup() - }, [closePopup, onPropertyPicked, processedVariablesInScope, activeTargetPath]) + const onApplyClick = React.useCallback( + () => applyVariable(activeTargetPath), + [applyVariable, activeTargetPath], + ) const valuePreviewText = (() => { const variable = processedVariablesInScope[pathInTopBarIncludingHover.toString()] if (variable == null) { return null } - return JSON.stringify(variable.variableInfo.value, undefined, 2) })() + const navigateToSearchResult = React.useCallback( + (path: ObjectPath) => { + setSearchTerm(null) + setSelectedPathFromColumns(path) + }, + [setSelectedPathFromColumns], + ) + + const searchNullOrEmpty = searchTerm == null || searchTerm.length < 1 + return ( - + + + + + {when( + searchTerm != null, + , + )} + + + - {/* top bar */} - - + {when( + searchNullOrEmpty, + <> + {/* top bar */} - - {pathBreadcrumbs(pathInTopBarIncludingHover, processedVariablesInScope).map( - ({ segment, path }, idx) => ( - - {idx === 0 ? segment : pathSegmentToString(segment)} - - ), - )} + + + + {pathBreadcrumbs( + pathInTopBarIncludingHover, + processedVariablesInScope, + ).map(({ segment, path }, idx) => ( + + {idx === 0 ? segment : pathSegmentToString(segment)} + + ))} + +
+ +
+
- + Apply
-
-
- Apply -
-
- {/* Value preview */} - - {valuePreviewText} - - + {/* Value preview */} + + {valuePreviewText} + + , + )} - + {searchNullOrEmpty ? ( + + ) : ( + + )}
@@ -518,22 +440,6 @@ export const DataSelectorModal = React.memo( ), ) -function childTypeToCartoucheDataType( - childType: DataPickerOption['type'], -): CartoucheUIProps['datatype'] { - switch (childType) { - case 'array': - return 'array' - case 'object': - return 'object' - case 'jsx': - case 'primitive': - return 'renderable' - default: - assertNever(childType) - } -} - type ScopeBuckets = { [insertionCeiling: string]: Array } @@ -608,30 +514,12 @@ function useProcessVariablesInScope(options: DataPickerOption[]): ProcessedVaria }, [options]) } -function childVars(option: DataPickerOption, indices: ArrayIndexLookup): DataPickerOption[] { - switch (option.type) { - case 'object': - return option.children - case 'array': - return option.children.length === 0 - ? [] - : childVars(option.children[indices[option.valuePath.toString()] ?? 0], indices) - case 'jsx': - case 'primitive': - return [] - default: - assertNever(option) - } -} - function pathBreadcrumbs( valuePath: DataPickerOption['valuePath'], processedVariablesInScope: ProcessedVariablesInScope, ): Array<{ segment: string | number path: (string | number)[] - role: CartoucheUIProps['role'] - type: CartoucheUIProps['datatype'] }> { let accumulator = [] let current: (string | number)[] = [] @@ -646,36 +534,11 @@ function pathBreadcrumbs( accumulator.push({ segment: segment, path: [...current], - role: cartoucheFolderOrInfo(optionFromLookup, 'can-be-folder'), - type: childTypeToCartoucheDataType(optionFromLookup.type), }) } return accumulator } -function variableNameFromPath(variable: DataPickerOption): string { - return last(variable.valuePath)?.toString() ?? variable.variableInfo.expression.toString() -} - -function cartoucheFolderOrInfo( - option: DataPickerOption, - canBeFolder: 'no-folder' | 'can-be-folder', -): CartoucheUIProps['role'] { - if (option.variableInfo.matches) { - return 'selection' - } - switch (option.type) { - case 'object': - return canBeFolder === 'can-be-folder' ? 'folder' : 'information' - case 'array': - case 'jsx': - case 'primitive': - return 'information' - default: - assertNever(option) - } -} - function disabledButtonStyles(disabled: boolean): React.CSSProperties { return { opacity: disabled ? 0.5 : 1, diff --git a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx new file mode 100644 index 000000000000..97f3662bdf32 --- /dev/null +++ b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx @@ -0,0 +1,246 @@ +import throttle from 'lodash.throttle' +import React from 'react' +import { memoize } from '../../../../core/shared/memoize' +import { assertNever } from '../../../../core/shared/utils' +import { FlexRow, Icons, UtopiaStyles } from '../../../../uuiui' +import { type DataPickerOption, type ObjectPath } from './data-picker-utils' +import { DataPickerCartouche } from './data-selector-cartouche' + +export interface DataSelectorSearchProps { + setNavigatedToPath: (_: ObjectPath) => void + allVariablesInScope: DataPickerOption[] + searchTerm: string +} + +export const DataSelectorSearch = React.memo( + ({ setNavigatedToPath, searchTerm, allVariablesInScope }: DataSelectorSearchProps) => { + const setNavigatedToPathCurried = React.useCallback( + (path: ObjectPath) => (e: React.MouseEvent) => { + e.stopPropagation() + e.preventDefault() + setNavigatedToPath(path) + }, + [setNavigatedToPath], + ) + return ( +
+ {throttledSearch(allVariablesInScope, searchTerm.toLowerCase())?.map( + (searchResult, idx) => ( + + + + {searchResult.valuePath.map((v, i) => ( + + + {i < searchResult.valuePath.length - 1 ? ( + + ) : null} + + ))} + + + + + + + ), + )} +
+ ) + }, +) + +interface SearchResult { + option: DataPickerOption + valuePath: Array<{ value: string; matched: boolean }> + value: { value: string; matched: boolean } +} + +function searchInValuePath( + valuePath: ObjectPath, + context: SearchContext, +): { valuePath: SearchResult['valuePath']; matched: boolean } { + const segments: SearchResult['valuePath'] = [] + + let foundMatch = false + for (const segment of valuePath) { + const segmentAsString = segment.toString() + if (typeof segment === 'number') { + segments.push({ value: segmentAsString, matched: false }) + } else { + const containsMatch = context.matchesSearchQuery(segmentAsString) + segments.push({ value: segmentAsString, matched: containsMatch }) + foundMatch ||= containsMatch + } + } + + return { valuePath: segments, matched: foundMatch } +} + +function searchInValue(value: unknown, context: SearchContext): SearchResult['value'] { + if (typeof value === 'object' || Array.isArray(value)) { + return { value: '', matched: false } + } + const valueAsString = `${value}` + return { + value: valueAsString, + matched: context.matchesSearchQuery(valueAsString), + } +} + +interface SearchContext { + matchesSearchQuery: (_: string) => boolean +} + +function matches(option: DataPickerOption, context: SearchContext): SearchResult | null { + const maybeValuePath = searchInValuePath(option.valuePath, context) + const maybeValue = searchInValue(option.variableInfo.value, context) + + if (maybeValuePath.matched || maybeValue.matched) { + return { + option: option, + value: maybeValue, + valuePath: maybeValuePath.valuePath, + } + } + + return null +} + +function search(options: DataPickerOption[], term: string): SearchResult[] { + if (term.length === 0) { + return [] + } + + const context: SearchContext = { + matchesSearchQuery: memoize((text) => text.toLowerCase().includes(term), { maxSize: 25 }), + } + + let results: SearchResult[] = [] + + function walk(option: DataPickerOption) { + const searchResult = matches(option, context) + if (searchResult != null) { + results.push(searchResult) + } + + switch (option.type) { + case 'array': + case 'object': + option.children.forEach((o) => walk(o)) + break + case 'jsx': + case 'primitive': + break + default: + assertNever(option) + } + } + + options.forEach((o) => walk(o)) + + return results +} + +const throttledSearch = throttle(search, 50, {}) + +function matchedSegments({ + text, + regexp, +}: { + text: string + regexp: RegExp +}): Array<{ text: string; matched: boolean }> { + const result: Array<{ text: string; matched: boolean }> = [] + let current = 0 + + let match + // https://stackoverflow.com/a/2295681 + while ((match = regexp.exec(text)) != null) { + result.push({ text: text.slice(current, match.index), matched: false }) + result.push({ text: text.slice(match.index, match.index + match[0].length), matched: true }) + current = match.index + match[0].length + } + result.push({ text: text.slice(current), matched: false }) + + return result +} + +function SearchResultString({ + label, + isMatch, + searchTerm, + fontWeightForMatch, +}: { + label: string + isMatch: boolean + searchTerm: string + fontWeightForMatch: number +}) { + const style: React.CSSProperties = { + ...UtopiaStyles.fontStyles.monospaced, + fontSize: 10, + } + + const regexp = React.useMemo(() => new RegExp(searchTerm, 'gi'), [searchTerm]) + + if (!isMatch) { + return {label} + } + + const segments = matchedSegments({ text: label, regexp: regexp }) + return ( + <> + {segments.map(({ text, matched }, idx) => { + if (text.length === 0) { + return null + } + return ( + + {text} + + ) + })} + + ) +} From 1878418be035dd3d3cb8480c14e48c5bf860773d Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Wed, 12 Jun 2024 17:03:15 +0200 Subject: [PATCH 065/103] Data Picker Data Tracing fixes and improvements (#5902) **Problem:** ![image](https://github.com/concrete-utopia/utopia/assets/2226774/85a27535-4f0c-4c63-8aa8-094252133b7e) The data picker sometimes would show data in blue (local variable) even though the variable traces back to a hook, and the correct color should be green (as seen in the navigator's cartouche). Turns out the problem boiled down to a few bugs in `traceDataFromVariableName`. **Commit Details:** - Added a test which calls `traceDataFromVariableName` from inside a map inside a component - Added a test which calls `traceDataFromVariableName` for a `props.title` tracing all the way back to a hook - `traceDataFromVariableName` now correctly passes in `containingComponentPath` to `walkUpInnerScopesUntilReachingComponent` - `useVariableDataSource` now correctly fills out `pathDrillSoFar` to support cases like `props.title` - Fixing the `pathDrillSoFar` fixed an issue I originally worked around by providing a `forcedDataSource` prop, this is no longer needed! - With `forcedDataSource` gone, I could delete `props.originalDataForScope` from `DataSelectorColumn` **Fixed behavior:** image This is pretty interesting, props is of course local data, but props.cica comes from a hook! image **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [ ] I could navigate to various routes in Preview mode --- .../data-selector-cartouche.tsx | 25 +++++----- .../data-selector-columns.tsx | 22 ++------- .../core/data-tracing/data-tracing.spec.ts | 48 +++++++++++++------ editor/src/core/data-tracing/data-tracing.ts | 5 +- 4 files changed, 52 insertions(+), 48 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx index f0eaa9dc4c86..966f0b4849c7 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -6,26 +6,25 @@ import { import { assertNever } from '../../../../core/shared/utils' import { Substores, useEditorState } from '../../../editor/store/store-hook' import { MapCounterUi } from '../../../navigator/navigator-item/map-counter' -import type { CartoucheSource, CartoucheUIProps } from './cartouche-ui' +import type { CartoucheUIProps } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' import type { DataPickerOption } from './data-picker-utils' +interface DataPickerCartoucheProps { + data: DataPickerOption + selected: boolean + onClick?: CartoucheUIProps['onClick'] +} + export const DataPickerCartouche = React.memo( - ( - props: React.PropsWithChildren<{ - data: DataPickerOption - forcedDataSource?: CartoucheSource | null // if the DataPickerOption is actually a child (of a child) of a variable, we need to provide the CartoucheSource that belongs to the original variable - selected: boolean - onClick?: CartoucheUIProps['onClick'] - }>, - ) => { - const { data, forcedDataSource, selected } = props + (props: React.PropsWithChildren) => { + const { data, selected } = props const dataSource = useVariableDataSource(data) const children = props.children ?? data.variableInfo.expressionPathPart return ( x.toString())), ) switch (trace.type) { diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx index 6c02e9223cfd..e214924db859 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -3,9 +3,8 @@ import React from 'react' import { isPrefixOf } from '../../../../core/shared/array-utils' import { arrayEqualsByReference, assertNever } from '../../../../core/shared/utils' import { FlexColumn, FlexRow, colorTheme } from '../../../../uuiui' -import type { CartoucheSource } from './cartouche-ui' import type { ArrayOption, DataPickerOption, ObjectOption, ObjectPath } from './data-picker-utils' -import { DataPickerCartouche, useVariableDataSource } from './data-selector-cartouche' +import { DataPickerCartouche } from './data-selector-cartouche' interface DataSelectorColumnsProps { activeScope: Array @@ -30,7 +29,6 @@ export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) targetPathInsideScope={props.targetPathInsideScope} onTargetPathChange={props.onTargetPathChange} currentlyShowingScopeForArray={false} - originalDataForScope={null} /> ) @@ -38,7 +36,6 @@ export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) interface DataSelectorColumnProps { activeScope: Array - originalDataForScope: DataPickerOption | null currentlyShowingScopeForArray: boolean targetPathInsideScope: ObjectPath onTargetPathChange: (newTargetPath: ObjectPath) => void @@ -72,8 +69,6 @@ const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { const nextColumnScopeValue = nextColumnScope == null ? elementOnSelectedPath : null - const dataSource = useVariableDataSource(props.originalDataForScope) - const isLastColumn = nextColumnScope == null && nextColumnScopeValue == null const columnRef = useScrollIntoView(isLastColumn) @@ -92,7 +87,6 @@ const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { onActivePath={onActivePath} forceShowArrow={pseudoSelectedElementForArray != null && index === 0} onTargetPathChange={props.onTargetPathChange} - forcedDataSource={dataSource} /> ) })} @@ -103,7 +97,6 @@ const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { targetPathInsideScope={targetPathInsideScope} onTargetPathChange={props.onTargetPathChange} currentlyShowingScopeForArray={nextColumnScope.type === 'array'} - originalDataForScope={props.originalDataForScope ?? elementOnSelectedPath} /> ) : null} {nextColumnScopeValue != null ? : null} @@ -163,19 +156,10 @@ interface RowWithCartoucheProps { onActivePath: boolean forceShowArrow: boolean isLeaf: boolean - forcedDataSource: CartoucheSource | null onTargetPathChange: (newTargetPath: ObjectPath) => void } const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { - const { - onTargetPathChange, - data, - forcedDataSource, - isLeaf, - selected, - onActivePath, - forceShowArrow, - } = props + const { onTargetPathChange, data, isLeaf, selected, onActivePath, forceShowArrow } = props const targetPath = data.valuePath const onClick: React.MouseEventHandler = React.useCallback( @@ -198,7 +182,7 @@ const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { disabled={false} > - + { it('Traces back a prop to a useLoaderData with a deep data path through multiple components', async () => { const editor = await renderTestEditorWithCode( makeTestProjectCodeWithStoryboard(` - function MyInnerComponent({title}) { - return
+ function MyInnerComponent(props) { + return
} function MyComponent({doc}) { @@ -702,6 +702,12 @@ describe('Data Tracing', () => { await focusOnComponentForTest(editor, EP.fromString('sb/app:my-component:component-root')) + const expectedResult = dataTracingToAHookCall( + EP.fromString('sb/app:my-component'), + 'useLoaderData', + dataPathSuccess(['very', 'deep', 'title', 'value']), + ) + const traceResult = traceDataFromProp( EPP.create( EP.fromString('sb/app:my-component:component-root:inner-component-root'), @@ -712,13 +718,17 @@ describe('Data Tracing', () => { dataPathSuccess([]), ) - expect(traceResult).toEqual( - dataTracingToAHookCall( - EP.fromString('sb/app:my-component'), - 'useLoaderData', - dataPathSuccess(['very', 'deep', 'title', 'value']), - ), + expect(traceResult).toEqual(expectedResult) + + const variableNameTraceResult = traceDataFromVariableName( + EP.fromString('sb/app:my-component:component-root:inner-component-root'), + 'props', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess(['title', 'value']), ) + + expect(variableNameTraceResult).toEqual(expectedResult) }) it('Traces back a prop to a useLoaderData with a deep data path through multiple components and destructure', async () => { @@ -943,6 +953,12 @@ describe('Data Tracing', () => { await focusOnComponentForTest(editor, EP.fromString('sb/app:my-component:component-root')) + const expectedResult = dataTracingToAHookCall( + EP.fromString('sb/app:my-component:component-root'), + 'useLoaderData', + dataPathSuccess(['reviews', '1', 'title']), + ) + const traceResult = traceDataFromProp( EPP.create( EP.fromString('sb/app:my-component:component-root/map/mapped~~~2/mapped-child'), @@ -953,13 +969,17 @@ describe('Data Tracing', () => { dataPathSuccess([]), ) - expect(traceResult).toEqual( - dataTracingToAHookCall( - EP.fromString('sb/app:my-component:component-root'), - 'useLoaderData', - dataPathSuccess(['reviews', '1', 'title']), - ), + expect(traceResult).toEqual(expectedResult) + + const variableNameTraceResult = traceDataFromVariableName( + EP.fromString('sb/app:my-component:component-root/map/mapped~~~2/mapped-child'), + 'review', + editor.getEditorState().editor.jsxMetadata, + editor.getEditorState().editor.projectContents, + dataPathSuccess(['title']), ) + + expect(variableNameTraceResult).toEqual(expectedResult) }) it('Works with a destructure in the map function', async () => { diff --git a/editor/src/core/data-tracing/data-tracing.ts b/editor/src/core/data-tracing/data-tracing.ts index 0e727d1fceeb..937f99d487db 100644 --- a/editor/src/core/data-tracing/data-tracing.ts +++ b/editor/src/core/data-tracing/data-tracing.ts @@ -428,12 +428,13 @@ export function traceDataFromVariableName( if (enclosingScope.type === 'file-root') { return dataTracingFailed('Cannot trace data from variable name in file root') } + const containingComponentPath = EP.getPathOfComponentRoot(enclosingScope) const componentHoldingElement = findContainingComponentForPathInProjectContents( enclosingScope, projectContents, ) - if (componentHoldingElement == null || componentHoldingElement.arbitraryJSBlock == null) { + if (componentHoldingElement == null) { return dataTracingFailed('Could not find containing component') } @@ -442,7 +443,7 @@ export function traceDataFromVariableName( projectContents, enclosingScope, enclosingScope, - enclosingScope, + containingComponentPath, componentHoldingElement, jsIdentifier(variableName, '', null, emptyComments), pathDrillSoFar, From 02c757d291414f5c2128b08b670bb2a3b27a31a8 Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Wed, 12 Jun 2024 16:29:08 +0100 Subject: [PATCH 066/103] Handle Early Returns In Navigator. (#5904) - `walkRegularNavigatorEntry` now stops walking the tree if it encounters an early return and itself returns null. - Some other functions calling `walkRegularNavigatorEntry` now either themselves return null as well or handle the null case. --- .../components/navigator/navigator-utils.ts | 40 ++++++----- .../navigator/navigator.spec.browser2.tsx | 69 +++++++++++++++++++ 2 files changed, 93 insertions(+), 16 deletions(-) diff --git a/editor/src/components/navigator/navigator-utils.ts b/editor/src/components/navigator/navigator-utils.ts index b7cf6b2ee0d4..3c1b91a635e3 100644 --- a/editor/src/components/navigator/navigator-utils.ts +++ b/editor/src/components/navigator/navigator-utils.ts @@ -212,7 +212,7 @@ function createNavigatorSubtree( collapsedViews: Array, // TODO turn this into a single array!! hiddenInNavigator: Array, subTree: ElementPathTree, -): NavigatorTree { +): NavigatorTree | null { const elementPath = subTree.path const jsxElementChild = getElementFromProjectContents(elementPath, projectContents) if (jsxElementChild == null) { @@ -315,10 +315,16 @@ function walkRegularNavigatorEntry( elementPath: ElementPath, elementHidden: boolean, subtreeHidden: boolean, -): NavigatorTree { +): NavigatorTree | null { let renderPropChildrenAccumulator: { [propName: string]: NavigatorTree } = {} let processedAccumulator: Set = emptySet() + const elementMetadata = MetadataUtils.findElementByElementPath(metadata, elementPath) + // If there was an early return, then we should stop walking the tree here. + if (elementMetadata != null && elementMetadata.earlyReturn != null) { + return null + } + if (isJSXElement(jsxElement)) { Object.entries(propControls ?? {}).forEach(([prop, control]) => { if (control.control !== 'jsx' || prop === 'children') { @@ -352,12 +358,14 @@ function walkRegularNavigatorEntry( hiddenInNavigator, subTreeChild, ) - const childTree: NavigatorTree = { - ...childTreeEntry, - navigatorEntry: renderPropValueNavigatorEntry(childPath, prop), + if (childTreeEntry != null) { + const childTree: NavigatorTree = { + ...childTreeEntry, + navigatorEntry: renderPropValueNavigatorEntry(childPath, prop), + } + processedAccumulator.add(EP.toString(subTreeChild.path)) + renderPropChildrenAccumulator[prop] = childTree } - processedAccumulator.add(EP.toString(subTreeChild.path)) - renderPropChildrenAccumulator[prop] = childTree } else { const synthEntry = isFeatureEnabled('Condensed Navigator Entries') ? dataReferenceNavigatorEntry( @@ -381,8 +389,8 @@ function walkRegularNavigatorEntry( const childrenPaths = subTree.children.filter( (child) => !processedAccumulator.has(EP.toString(child.path)), ) - const children: Array = childrenPaths.map((child) => - createNavigatorSubtree( + const children: Array = mapDropNulls((child) => { + return createNavigatorSubtree( metadata, elementPathTrees, projectContents, @@ -390,8 +398,8 @@ function walkRegularNavigatorEntry( collapsedViews, hiddenInNavigator, child, - ), - ) + ) + }, childrenPaths) return { type: 'regular-entry', @@ -493,8 +501,8 @@ function walkConditionalClause( // if we find regular tree entries for the clause, it means the branch has proper JSXElements, so we recurse into the tree building if (clausePathTrees.length > 0) { - const children = clausePathTrees.map((child) => - createNavigatorSubtree( + const children = mapDropNulls((child) => { + return createNavigatorSubtree( metadata, elementPathTrees, projectContents, @@ -502,8 +510,8 @@ function walkConditionalClause( collapsedViews, hiddenInNavigator, child, - ), - ) + ) + }, clausePathTrees) return children } @@ -563,7 +571,7 @@ function walkMapExpression( return { type: 'map-entry', navigatorEntry: regularNavigatorEntry(subTree.path), - mappedEntries: [...mappedChildren, ...invaldiOverrideEntries], + mappedEntries: dropNulls([...mappedChildren, ...invaldiOverrideEntries]), elementHidden: elementHidden, subtreeHidden: subtreeHidden, } diff --git a/editor/src/components/navigator/navigator.spec.browser2.tsx b/editor/src/components/navigator/navigator.spec.browser2.tsx index 6652c51316b3..601cc6b7eebd 100644 --- a/editor/src/components/navigator/navigator.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator.spec.browser2.tsx @@ -1025,6 +1025,59 @@ export function Heading({ children }) { `, }) +const projectWithEarlyReturn = createModifiedProject({ + [StoryboardFilePath]: `import * as React from 'react' +import * as Utopia from 'utopia-api' +import { + Storyboard, + Scene, +} from 'utopia-api' + +var Playground = ({ style }) => { + if (true) { + return null + } + return ( +
Cake
+ ) +} +export var storyboard = ( + + + + + +) +`, +}) + function getProjectCodeForMultipleSelection(): string { return `import * as React from 'react' import { Scene, Storyboard } from 'utopia-api' @@ -5709,6 +5762,22 @@ describe('Navigator row order', () => { 'regular-sb/scene/pg:dbc/78c/891', ]) }) + + it('is correct in the presence of an early return', async () => { + const renderResult = await renderTestEditorWithModel( + projectWithEarlyReturn, + 'await-first-dom-report', + ) + + await renderResult.getDispatchFollowUpActionsFinished() + + expect(renderResult.getEditorState().derived.navigatorTargets.map(navigatorEntryToKey)).toEqual( + ['regular-sb/scene'], + ) + expect( + renderResult.getEditorState().derived.visibleNavigatorTargets.map(navigatorEntryToKey), + ).toEqual(['regular-sb/scene']) + }) }) describe('Navigator labels', () => { From 5289026ce3a932453b0bea8bb22ed521658cc765 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Wed, 12 Jun 2024 19:32:01 +0200 Subject: [PATCH 067/103] Add icons for text inspector controls (#5907) **Problem:** New icons exposed on the component annotation API for the text inspector controls. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- editor/src/uuiui/icons.tsx | 70 +++++++++++++++++++++++++++++ utopia-api/src/primitives/icons.tsx | 10 +++++ 2 files changed, 80 insertions(+) diff --git a/editor/src/uuiui/icons.tsx b/editor/src/uuiui/icons.tsx index 19667ad3d98a..92288da1d3af 100644 --- a/editor/src/uuiui/icons.tsx +++ b/editor/src/uuiui/icons.tsx @@ -386,6 +386,76 @@ export const Icons = { width: 12, height: 12, }), + Italic: makeIcon({ + category: 'inspector-element', + type: 'italic', + color: 'main', + width: 16, + height: 16, + }), + Underline: makeIcon({ + category: 'inspector-element', + type: 'underline', + color: 'main', + width: 16, + height: 16, + }), + Strikethrough: makeIcon({ + category: 'inspector-element', + type: 'strikethrough', + color: 'main', + width: 16, + height: 16, + }), + FontStyleSerif: makeIcon({ + category: 'inspector-element', + type: 'fontStyle-serif', + color: 'main', + width: 16, + height: 16, + }), + FontStyleScript: makeIcon({ + category: 'inspector-element', + type: 'fontStyle-script', + color: 'main', + width: 16, + height: 16, + }), + FontStyleMonospace: makeIcon({ + category: 'inspector-element', + type: 'fontStyle-monospace', + color: 'main', + width: 16, + height: 16, + }), + FontStyleSansSerif: makeIcon({ + category: 'inspector-element', + type: 'fontStyle-sansSerif', + color: 'main', + width: 16, + height: 16, + }), + TextAlignLeft: makeIcon({ + category: 'inspector-element', + type: 'textAlign-left', + color: 'main', + width: 16, + height: 16, + }), + TextAlignCenter: makeIcon({ + category: 'inspector-element', + type: 'textAlign-center', + color: 'main', + width: 16, + height: 16, + }), + TextAlignRight: makeIcon({ + category: 'inspector-element', + type: 'textAlign-right', + color: 'main', + width: 16, + height: 16, + }), } as const export const FunctionIcons = { diff --git a/utopia-api/src/primitives/icons.tsx b/utopia-api/src/primitives/icons.tsx index e85da20f5ffc..a902fd5f2ec8 100644 --- a/utopia-api/src/primitives/icons.tsx +++ b/utopia-api/src/primitives/icons.tsx @@ -68,6 +68,16 @@ export const UtopiaIcons = [ 'StringInputControl', 'NavigatorText', 'NavigatorData', + 'Italic', + 'Underline', + 'Strikethrough', + 'FontStyleSerif', + 'FontStyleScript', + 'FontStyleMonospace', + 'FontStyleSansSerif', + 'TextAlignLeft', + 'TextAlignCenter', + 'TextAlignRight', ] as const export type UtopiaIcon = (typeof UtopiaIcons)[number] From df11d0890f1162c675e9e9e1957e138bf65618b6 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:15:26 +0200 Subject: [PATCH 068/103] Design: data selector rearrange (#5911) Target design: image Result on branch: image **Commit Details:** - Rearranged the basic layout: search bar lives at the top, apply button moved to the bottom. the "output input field" has been replaced by a "Selection: [cartouche]" row. - Left sidebar options are now checkboxes (BUT they still behave like radio buttons / tabs) - Added fake source filtering options to the left sidebar - minor tweaks to paddings etc - MASSIVE cleanup of code in data-selector-modal - instead of storing `selectedPath`, we store `selectedVariableOption` which allowed further simplification of code - useProcessVariablesInScope no longer necessary **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [ ] I could navigate to various routes in Preview mode --- .../component-section/data-picker-utils.tsx | 6 +- .../data-selector-cartouche.tsx | 5 +- .../data-selector-columns.tsx | 14 +- .../data-selector-left-sidebar.tsx | 97 +++- .../data-selector-modal.spec.browser2.tsx | 2 +- .../component-section/data-selector-modal.tsx | 436 +++++++----------- .../data-selector-search.tsx | 9 +- 7 files changed, 256 insertions(+), 313 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 5b406b4e884e..0c762977192a 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -108,7 +108,7 @@ export function getEnclosingScopes( MetadataUtils.isJSXMapExpression(parentOfCurrent, metadata) || EP.isRootElementOfInstance(current) ) { - result.unshift({ + result.push({ insertionCeiling: current, label: outletNameHack(metadata, allElementProps, elementPathTree, projectContents, current), hasContent: buckets.includes(insertionCeilingToString(current)), @@ -118,7 +118,7 @@ export function getEnclosingScopes( // we also add anything that has content in scope even if it's not a component or map if (buckets.includes(insertionCeilingToString(current))) { - result.unshift({ + result.push({ insertionCeiling: current, label: outletNameHack(metadata, allElementProps, elementPathTree, projectContents, current), hasContent: true, @@ -128,7 +128,7 @@ export function getEnclosingScopes( } // Add file root - result.unshift({ + result.push({ insertionCeiling: { type: 'file-root' }, label: 'File', hasContent: buckets.includes(insertionCeilingToString({ type: 'file-root' })), diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx index 966f0b4849c7..0f54b58a3077 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -13,12 +13,13 @@ import type { DataPickerOption } from './data-picker-utils' interface DataPickerCartoucheProps { data: DataPickerOption selected: boolean + forcedRole?: CartoucheUIProps['role'] onClick?: CartoucheUIProps['onClick'] } export const DataPickerCartouche = React.memo( (props: React.PropsWithChildren) => { - const { data, selected } = props + const { data, selected, forcedRole: forceRole } = props const dataSource = useVariableDataSource(data) const children = props.children ?? data.variableInfo.expressionPathPart return ( @@ -28,7 +29,7 @@ export const DataPickerCartouche = React.memo( datatype={childTypeToCartoucheDataType(data.type)} selected={!data.disabled && selected} highlight={data.disabled ? 'disabled' : null} - role={data.disabled ? 'information' : 'selection'} + role={forceRole ?? (data.disabled ? 'information' : 'selection')} testId={`data-selector-option-${data.variableInfo.expression}`} badge={ data.type === 'array' ? ( diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx index e214924db859..5661fe8fe42e 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -9,7 +9,7 @@ import { DataPickerCartouche } from './data-selector-cartouche' interface DataSelectorColumnsProps { activeScope: Array targetPathInsideScope: ObjectPath - onTargetPathChange: (newTargetPath: ObjectPath) => void + onTargetPathChange: (newTargetVariable: DataPickerOption) => void } export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) => { @@ -38,7 +38,7 @@ interface DataSelectorColumnProps { activeScope: Array currentlyShowingScopeForArray: boolean targetPathInsideScope: ObjectPath - onTargetPathChange: (newTargetPath: ObjectPath) => void + onTargetPathChange: (newTargetVariable: DataPickerOption) => void } const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { @@ -156,18 +156,17 @@ interface RowWithCartoucheProps { onActivePath: boolean forceShowArrow: boolean isLeaf: boolean - onTargetPathChange: (newTargetPath: ObjectPath) => void + onTargetPathChange: (newTargetVariable: DataPickerOption) => void } const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { const { onTargetPathChange, data, isLeaf, selected, onActivePath, forceShowArrow } = props - const targetPath = data.valuePath const onClick: React.MouseEventHandler = React.useCallback( (e) => { e.stopPropagation() - onTargetPathChange(targetPath) + onTargetPathChange(data) }, - [targetPath, onTargetPathChange], + [data, onTargetPathChange], ) const ref = useScrollIntoView(selected) @@ -204,13 +203,14 @@ const DataSelectorFlexColumn = styled(FlexColumn)({ overflowY: 'scroll', scrollbarWidth: 'auto', scrollbarColor: 'gray transparent', + paddingTop: 8, paddingRight: 10, // to account for scrollbar paddingLeft: 6, paddingBottom: 10, borderRight: `1px solid ${colorTheme.subduedBorder.cssValue}`, }) -export const DataPickerRow = styled(FlexRow)((props: { disabled: boolean }) => ({ +const DataPickerRow = styled(FlexRow)((props: { disabled: boolean }) => ({ alignSelf: 'stretch', justifyContent: 'space-between', fontSize: 10, diff --git a/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx b/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx index 7b25f2e76946..309caeb267e1 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx @@ -1,13 +1,13 @@ import React from 'react' import type { ElementPath } from 'utopia-shared/src/types' -import { FlexColumn, FlexRow, LargerIcons, colorTheme } from '../../../../uuiui' +import { CheckboxInput, FlexColumn, FlexRow, LargerIcons, colorTheme } from '../../../../uuiui' import { insertionCeilingToString, insertionCeilingsEqual, type FileRootPath, } from '../../../canvas/ui-jsx-canvas' import { stopPropagation } from '../../common/inspector-utils' -import { DataPickerRow } from './data-selector-columns' +import { NO_OP } from '../../../../core/shared/utils' interface SelectableScope { label: string @@ -24,10 +24,19 @@ interface DataSelectorLeftSidebarProps { export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSidebarProps) => { const { scopes, setSelectedScope, activeScope } = props return ( - <> - - Sources - + + Sources {scopes.map((scope) => { return ( @@ -41,7 +50,33 @@ export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSideba ) })} - + + Origin + + + + + + ) }) @@ -65,16 +100,46 @@ const ScopeRow = React.memo( ) return ( - - {scope.label} - + onClick={onClick} + /> ) }, ) + +interface RowWithCheckboxProps { + label: string + color?: string + selected: boolean + disabled: boolean + onClick: (e: React.MouseEvent) => void +} + +const RowWithCheckbox = React.memo((props: RowWithCheckboxProps) => { + const { label, color, selected, disabled, onClick } = props + return ( + + + {label} + + ) +}) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.spec.browser2.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.spec.browser2.tsx index 27e282a3e39d..6ee251afcb38 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.spec.browser2.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.spec.browser2.tsx @@ -13,7 +13,7 @@ describe('data selector modal', () => { expect(editor.renderedDOM.getByText('Apply')).not.toBeNull() expect(editor.renderedDOM.getByTestId(DataSelectorPopupBreadCrumbsTestId).innerText).toEqual( - ['header', '.title'].join('\n'), + expect.stringContaining('Selection:'), ) }) }) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 3ec16a087a54..40354775c31e 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { groupBy } from '../../../../core/shared/array-utils' +import { groupBy, isPrefixOf } from '../../../../core/shared/array-utils' import * as EP from '../../../../core/shared/element-path' import { jsExpressionOtherJavaScriptSimple } from '../../../../core/shared/element-template' import { optionalMap } from '../../../../core/shared/optional-utils' @@ -7,6 +7,7 @@ import type { ElementPath } from '../../../../core/shared/project-file-types' import { CanvasContextMenuPortalTargetID, arrayEqualsByReference, + arrayEqualsByValue, assertNever, } from '../../../../core/shared/utils' import { when } from '../../../../utils/react-conditionals' @@ -32,7 +33,7 @@ import { import { DataSelectorColumns } from './data-selector-columns' import { DataSelectorLeftSidebar } from './data-selector-left-sidebar' import { DataSelectorSearch } from './data-selector-search' -import { stopPropagation } from '../../common/inspector-utils' +import { DataPickerCartouche } from './data-selector-cartouche' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -45,10 +46,6 @@ export interface DataSelectorModalProps { lowestInsertionCeiling: ElementPath | null } -interface ProcessedVariablesInScope { - [valuePath: string]: DataPickerOption -} - export const DataSelectorModal = React.memo( React.forwardRef( ( @@ -93,9 +90,7 @@ export const DataSelectorModal = React.memo( const setSelectedScopeAndResetSelection = React.useCallback( (scope: ElementPath | FileRootPath) => { setSelectedScope(scope) - setSelectedPath([]) - setHoveredPath(null) - setNavigatedToPath([]) + setSelectedVariableOption(null) }, [], ) @@ -106,11 +101,9 @@ export const DataSelectorModal = React.memo( selectedScope, ) - const processedVariablesInScope = useProcessVariablesInScope(allVariablesInScope) - const searchBoxRef = React.useRef(null) - const elementLabelsWithScopes = useEditorState( + const scopeLabels = useEditorState( Substores.fullStore, (store) => { const scopes = getEnclosingScopes( @@ -127,16 +120,13 @@ export const DataSelectorModal = React.memo( hasContent: hasContent, })) }, - 'DataSelectorModal elementLabelsWithScopes', - ) - - const [navigatedToPath, setNavigatedToPath] = React.useState( - findFirstObjectPathToNavigateTo(processedVariablesInScope, startingSelectedValuePath) ?? [], + 'DataSelectorModal scopeLabels', ) - const [selectedPath, setSelectedPath] = React.useState( - startingSelectedValuePath ?? [], - ) + const [selectedVariableOption, setSelectedVariableOption] = + React.useState( + getVariableInScope(filteredVariablesInScope, startingSelectedValuePath), + ) const [searchTerm, setSearchTerm] = React.useState(null) const onStartSearch = React.useCallback(() => { @@ -158,83 +148,31 @@ export const DataSelectorModal = React.memo( [], ) - const [hoveredPath, setHoveredPath] = React.useState(null) - - const setSelectedPathFromColumns = React.useCallback((newPath: ObjectPath) => { - setSelectedPath(newPath) - setHoveredPath(null) - setNavigatedToPath([]) - }, []) - - const setNavigatedToPathCurried = React.useCallback( - (path: DataPickerOption['valuePath']) => (e: React.MouseEvent) => { - e.stopPropagation() - e.preventDefault() - - setNavigatedToPath(path) - setSelectedPath([]) - setHoveredPath(null) - }, - [], - ) - - const onHomeClick = React.useCallback( - (e: React.MouseEvent) => { - e.stopPropagation() - e.preventDefault() - - setNavigatedToPathCurried([])(e) - }, - [setNavigatedToPathCurried], - ) - const catchClick = React.useCallback((e: React.MouseEvent) => { e.stopPropagation() e.preventDefault() }, []) - const activeTargetPath = selectedPath ?? navigatedToPath - const pathInTopBarIncludingHover = hoveredPath ?? activeTargetPath - - const applyVariable = React.useCallback( - (path: ObjectPath) => { - const variable = processedVariablesInScope[path.toString()] - if (variable == null) { - return - } - if (variable.disabled) { - return - } - onPropertyPicked( - jsExpressionOtherJavaScriptSimple(variable.variableInfo.expression, [ - variable.definedElsewhere, - ]), - ) - closePopup() - }, - [closePopup, onPropertyPicked, processedVariablesInScope], - ) - - const onApplyClick = React.useCallback( - () => applyVariable(activeTargetPath), - [applyVariable, activeTargetPath], - ) - - const valuePreviewText = (() => { - const variable = processedVariablesInScope[pathInTopBarIncludingHover.toString()] + const applyVariable = React.useCallback(() => { + const variable = selectedVariableOption if (variable == null) { - return null + return } - return JSON.stringify(variable.variableInfo.value, undefined, 2) - })() + if (variable.disabled) { + return + } + onPropertyPicked( + jsExpressionOtherJavaScriptSimple(variable.variableInfo.expression, [ + variable.definedElsewhere, + ]), + ) + closePopup() + }, [closePopup, onPropertyPicked, selectedVariableOption]) - const navigateToSearchResult = React.useCallback( - (path: ObjectPath) => { - setSearchTerm(null) - setSelectedPathFromColumns(path) - }, - [setSelectedPathFromColumns], - ) + const navigateToSearchResult = React.useCallback((variable: DataPickerOption) => { + setSearchTerm(null) + setSelectedVariableOption(variable) + }, []) const searchNullOrEmpty = searchTerm == null || searchTerm.length < 1 @@ -264,6 +202,7 @@ export const DataSelectorModal = React.memo( > + - + + + + {when( + searchTerm != null, + , + )} + + + - - - {when( - searchTerm != null, - , + {searchNullOrEmpty ? ( + + ) : ( + )} - - - - + {when( searchNullOrEmpty, <> - {/* top bar */} + {/* bottom bar */} - + - {pathBreadcrumbs( - pathInTopBarIncludingHover, - processedVariablesInScope, - ).map(({ segment, path }, idx) => ( - - {idx === 0 ? segment : pathSegmentToString(segment)} - - ))} + Selection: + {selectedVariableOption != null ? ( + + ) : null} -
- -
+ Cancel +
+
Apply
- {/* Value preview */} - - {valuePreviewText} - , )} - - {searchNullOrEmpty ? ( - - ) : ( - - )} -
@@ -492,53 +423,6 @@ function useFilterVariablesInScope( }, [scopeBuckets, options, scopeToShow]) } -function useProcessVariablesInScope(options: DataPickerOption[]): ProcessedVariablesInScope { - return React.useMemo(() => { - let lookup: ProcessedVariablesInScope = {} - function walk(option: DataPickerOption) { - lookup[option.valuePath.toString()] = option - switch (option.type) { - case 'array': - case 'object': - option.children.forEach((c) => walk(c)) - return - case 'jsx': - case 'primitive': - return - default: - assertNever(option) - } - } - options.forEach((o) => walk(o)) - return lookup - }, [options]) -} - -function pathBreadcrumbs( - valuePath: DataPickerOption['valuePath'], - processedVariablesInScope: ProcessedVariablesInScope, -): Array<{ - segment: string | number - path: (string | number)[] -}> { - let accumulator = [] - let current: (string | number)[] = [] - for (const segment of valuePath) { - current.push(segment) - const optionFromLookup = processedVariablesInScope[current.toString()] - - if (optionFromLookup == null) { - continue - } - - accumulator.push({ - segment: segment, - path: [...current], - }) - } - return accumulator -} - function disabledButtonStyles(disabled: boolean): React.CSSProperties { return { opacity: disabled ? 0.5 : 1, @@ -546,13 +430,6 @@ function disabledButtonStyles(disabled: boolean): React.CSSProperties { } } -function pathSegmentToString(segment: string | number) { - if (typeof segment === 'string') { - return `.${segment}` - } - return `[${segment}]` -} - function getSelectedScopeFromBuckets( startingSelectedValuePath: ObjectPath, scopeBuckets: ScopeBuckets, @@ -569,28 +446,27 @@ function getSelectedScopeFromBuckets( return null } -function findFirstObjectPathToNavigateTo( - processedVariablesInScope: ProcessedVariablesInScope, - selectedValuePath: ObjectPath | null, -): ObjectPath | null { - if (selectedValuePath == null) { - return null - } - - let currentPath = selectedValuePath - while (currentPath.length > 0) { - const parentPath = currentPath.slice(0, -1) - const parentOption = processedVariablesInScope[parentPath.toString()] - const grandParentPath = currentPath.slice(0, -2) - const grandParentOption = processedVariablesInScope[grandParentPath.toString()] - if (grandParentOption != null && grandParentOption.type === 'array') { - return grandParentPath.slice(0, -1) +function getVariableInScope( + variablesInScope: DataPickerOption[], + valuePath: ObjectPath | null, +): DataPickerOption | null { + const looseEquals = (l: string | number, r: string | number) => l == r // props.startingSelectedValuePath seems to have strings for array indexes + function findOption(options: DataPickerOption[]): DataPickerOption | null { + if (valuePath == null) { + return null } - if (parentOption != null && parentOption.type === 'object') { - return parentPath.slice(0, -1) + for (const option of options) { + if (arrayEqualsByValue(option.valuePath, valuePath, looseEquals)) { + return option + } + if (isPrefixOf(option.valuePath, valuePath, looseEquals) && 'children' in option) { + const found = findOption(option.children) + if (found != null) { + return found + } + } } - currentPath = currentPath.slice(0, -1) + return null } - - return null + return findOption(variablesInScope) } diff --git a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx index 97f3662bdf32..c96591f00e9a 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx @@ -7,7 +7,7 @@ import { type DataPickerOption, type ObjectPath } from './data-picker-utils' import { DataPickerCartouche } from './data-selector-cartouche' export interface DataSelectorSearchProps { - setNavigatedToPath: (_: ObjectPath) => void + setNavigatedToPath: (_: DataPickerOption) => void allVariablesInScope: DataPickerOption[] searchTerm: string } @@ -15,10 +15,10 @@ export interface DataSelectorSearchProps { export const DataSelectorSearch = React.memo( ({ setNavigatedToPath, searchTerm, allVariablesInScope }: DataSelectorSearchProps) => { const setNavigatedToPathCurried = React.useCallback( - (path: ObjectPath) => (e: React.MouseEvent) => { + (data: DataPickerOption) => (e: React.MouseEvent) => { e.stopPropagation() e.preventDefault() - setNavigatedToPath(path) + setNavigatedToPath(data) }, [setNavigatedToPath], ) @@ -32,6 +32,7 @@ export const DataSelectorSearch = React.memo( flexGrow: 1, gap: 8, paddingTop: 8, + paddingLeft: 8, display: 'grid', gridTemplateColumns: 'auto 1fr', gridAutoRows: 'min-content', @@ -45,7 +46,7 @@ export const DataSelectorSearch = React.memo( data={searchResult.option} key={`${searchResult.option.variableInfo.expression}-${idx}`} selected={false} - onClick={setNavigatedToPathCurried(searchResult.option.valuePath)} + onClick={setNavigatedToPathCurried(searchResult.option)} > {searchResult.valuePath.map((v, i) => ( From 0fe4b60c4c7b3dc129b62d765450b84f253aa5d1 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 13 Jun 2024 12:19:48 +0200 Subject: [PATCH 069/103] Temporarily disable performance tests (#5913) **Problem:** Performance tests are currently flaky, so temporarily disable them. --- .github/workflows/pull-requests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index 9290bb964ede..b39aaecd7220 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -259,6 +259,7 @@ jobs: performance-test: name: Run Performance Tests + if: false # TODO restore / revamp this! (Temporarily disabled) timeout-minutes: 15 runs-on: self-hosted needs: [deploy-branch, cache-pnpm-store] From 3c847c5aca3f86d68cfefe36b69a0ce80c543323 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 13 Jun 2024 12:31:22 +0200 Subject: [PATCH 070/103] Revamped navigator tree select (#5899) **Problem:** The navigator with the new tree generation used to support condensed rows does not support correctly the whole set of selection operations all navigator entries should support (cmd+click, shift+click). **Fix:** Add a common wrapper (`NavigatorRowClickableWrapper`) and hook (`useGetNavigatorClickActions`) that unify the behavior so it's possible to do additive selection and range selections on navigator entries, regardless of their structure. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5888 --- .../component-section/cartouche-ui.tsx | 13 +- .../navigator-conditionals.spec.browser2.tsx | 2 +- .../component-picker-context-menu.tsx | 42 +- .../navigator/navigator-item/map-counter.tsx | 22 +- .../navigator-condensed-entry.tsx | 72 +-- .../navigator-item-clickable-wrapper.tsx | 328 ++++++++++++ .../navigator-item-components.tsx | 2 +- .../navigator-item-dnd-container.tsx | 6 - .../navigator-item/navigator-item.tsx | 465 ++++++------------ .../navigator/navigator.spec.browser2.tsx | 32 +- 10 files changed, 588 insertions(+), 396 deletions(-) create mode 100644 editor/src/components/navigator/navigator-item/navigator-item-clickable-wrapper.tsx diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 7449abfbd8ed..924d1bf8800e 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -54,7 +54,18 @@ export const CartoucheUI = React.forwardRef( const colors = useCartoucheColors(source, highlight ?? null) - const wrappedOnClick = useStopPropagation(onClick) + const wrappedOnClick = React.useCallback( + (e: React.MouseEvent) => { + if (e.shiftKey || e.metaKey) { + return + } + if (onClick != null) { + e.stopPropagation() + onClick(e) + } + }, + [onClick], + ) const wrappedOnDoubleClick = useStopPropagation(onDoubleClick) // NOTE: this is currently unused, we should decide if we want to keep allowing deletion of the cartouches from here or not diff --git a/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx b/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx index 001efcdb4e03..48cf0211e17d 100644 --- a/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx @@ -721,7 +721,7 @@ describe('conditionals in the navigator', () => { regularNavigatorEntry(elementPathToTarget), )}`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( 'transparent solid 1px', ) }, diff --git a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx index 8d2ab5336569..30a476bf7325 100644 --- a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx +++ b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx @@ -16,8 +16,6 @@ import { jsxElementFromJSXElementWithoutUID, jsxElementNameFromString, getJSXElementNameLastPart, - setJSXAttributesAttribute, - jsExpressionValue, isIntrinsicHTMLElement, } from '../../../core/shared/element-template' import type { ElementPath, Imports } from '../../../core/shared/project-file-types' @@ -31,6 +29,7 @@ import { insertJSXElement, replaceJSXElement, replaceMappedElement, + selectComponents, setProp_UNSAFE, showToast, switchEditorMode, @@ -76,18 +75,23 @@ import { replaceWithSingleElement, } from '../../editor/store/insertion-path' import { mapComponentInfo, type InsertableComponent } from '../../shared/project-components' -import type { ConditionalCase } from '../../../core/model/conditionals' +import { + getConditionalClausePathFromMetadata, + type ConditionalCase, +} from '../../../core/model/conditionals' import type { ElementPathTrees } from '../../../core/shared/element-path-tree' import { absolute } from '../../../utils/utils' import { notice } from '../../common/notice' import { generateUidWithExistingComponents } from '../../../core/model/element-template-utils' -import { emptyComments } from 'utopia-shared/src/types' import { intrinsicHTMLElementNamesThatSupportChildren } from '../../../core/shared/dom-utils' -import { emptyImports } from '../../../core/workers/common/project-file-utils' import { commandsForFirstApplicableStrategy } from '../../../components/inspector/inspector-strategies/inspector-strategy' import { wrapInDivStrategy } from '../../../components/editor/wrap-in-callbacks' import type { AllElementProps } from '../../../components/editor/store/editor-state' import { EditorModes } from '../../editor/editor-modes' +import { + conditionalOverrideUpdateForPath, + getConditionalOverrideActions, +} from './navigator-item-clickable-wrapper' type RenderPropTarget = { type: 'render-prop'; prop: string } type ConditionalTarget = { type: 'conditional'; conditionalCase: ConditionalCase } @@ -325,6 +329,8 @@ export const useCreateCallbackToShowComponentPicker = propertyControlsInfo: store.editor.propertyControlsInfo, })) + const dispatch = useDispatch() + return React.useCallback( ( selectedViews: ElementPath[], @@ -376,8 +382,32 @@ export const useCreateCallbackToShowComponentPicker = setContextMenuProps({ targets: selectedViews, insertionTarget: insertionTarget }) const show = pickerType === 'preferred' ? showPreferred : showFull show({ ...params, event }) + + // conditional slots should get selected as a result, since this action would supersede + // the navigator's selection handling. + if (isConditionalTarget(insertionTarget)) { + let elementsToSelect: ElementPath[] = [] + let overrideActions: EditorAction[] = [] + for (const view of selectedViews) { + const clause = getConditionalClausePathFromMetadata( + view, + editorRef.current.jsxMetadata, + insertionTarget.conditionalCase, + ) + if (clause != null) { + elementsToSelect.push(clause) + overrideActions.push( + ...getConditionalOverrideActions( + view, + conditionalOverrideUpdateForPath(clause, editorRef.current.jsxMetadata), + ), + ) + } + } + dispatch([...overrideActions, selectComponents(elementsToSelect, false)]) + } }, - [editorRef, showPreferred, showFull, setContextMenuProps], + [editorRef, showPreferred, showFull, setContextMenuProps, dispatch], ) } diff --git a/editor/src/components/navigator/navigator-item/map-counter.tsx b/editor/src/components/navigator/navigator-item/map-counter.tsx index 59ec6e10f910..510b846c261b 100644 --- a/editor/src/components/navigator/navigator-item/map-counter.tsx +++ b/editor/src/components/navigator/navigator-item/map-counter.tsx @@ -83,15 +83,19 @@ export const MapCounter = React.memo((props: MapCounterProps) => { return 'no-override' })() - const onClick = React.useCallback(() => { - if (nrChildren == null) { - return - } - const nextValue = getNextOverrideValue(overrideStatus, countOverride, nrChildren) - if (nextValue !== countOverride) { - dispatch([setMapCountOverride(props.elementPath, nextValue)]) - } - }, [props.elementPath, dispatch, overrideStatus, countOverride, nrChildren]) + const onClick = React.useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + if (nrChildren == null) { + return + } + const nextValue = getNextOverrideValue(overrideStatus, countOverride, nrChildren) + if (nextValue !== countOverride) { + dispatch([setMapCountOverride(props.elementPath, nextValue)]) + } + }, + [props.elementPath, dispatch, overrideStatus, countOverride, nrChildren], + ) const selectedStatus = props.selected diff --git a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx index 62cbfce2b6ee..f298ea20aded 100644 --- a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx @@ -4,17 +4,20 @@ import { Icons, Tooltip, useColorTheme } from '../../../uuiui' import { useDispatch } from '../../editor/store/dispatch-context' import type { DataReferenceNavigatorEntry, NavigatorEntry } from '../../editor/store/editor-state' import { Substores, useEditorState } from '../../editor/store/store-hook' -import type { CondensedNavigatorRow } from '../navigator-row' +import { condensedNavigatorRow, type CondensedNavigatorRow } from '../navigator-row' import { MetadataUtils } from '../../../core/model/element-metadata-utils' import { getNavigatorEntryLabel, labelSelector } from './navigator-item-wrapper' import { BasePaddingUnit, elementWarningsSelector } from './navigator-item' import { setHighlightedViews, toggleCollapse } from '../../editor/actions/action-creators' -import { selectComponents } from '../../editor/actions/meta-actions' import type { ElementPath } from 'utopia-shared/src/types' import { unless, when } from '../../../utils/react-conditionals' import { ExpandableIndicator } from './expandable-indicator' import { LayoutIcon } from './layout-icon' import { DataReferenceCartoucheControl } from '../../inspector/sections/component-section/data-reference-cartouche' +import { + NavigatorRowClickableWrapper, + useGetNavigatorClickActions, +} from './navigator-item-clickable-wrapper' function useEntryLabel(entry: NavigatorEntry) { const labelForTheElement = useEditorState( @@ -104,24 +107,26 @@ export const CondensedEntryItemWrapper = React.memo( overflowX: 'auto', }} > - {props.navigatorRow.entries.map((entry, idx) => { - const showSeparator = - props.navigatorRow.variant === 'trunk' && idx < props.navigatorRow.entries.length - 1 - - return ( - - ) - })} + + {props.navigatorRow.entries.map((entry, idx) => { + const showSeparator = + props.navigatorRow.variant === 'trunk' && idx < props.navigatorRow.entries.length - 1 + + return ( + + ) + })} +
) }, @@ -267,15 +272,6 @@ const CondensedEntryItemContent = React.memo( return props.entry.type === 'DATA_REFERENCE' }, [props.entry]) - const onClick = React.useCallback( - (e: React.MouseEvent) => { - e.preventDefault() - e.stopPropagation() - dispatch(selectComponents([props.entry.elementPath], false)) - }, - [dispatch, props.entry], - ) - const onMouseOver = React.useCallback(() => { dispatch([setHighlightedViews([props.entry.elementPath])]) }, [props.entry, dispatch]) @@ -288,6 +284,20 @@ const CondensedEntryItemContent = React.memo( ]) }, [props.entry, dispatch, highlightedViews]) + const getClickActions = useGetNavigatorClickActions( + props.entry.elementPath, + props.selected, + condensedNavigatorRow([props.entry], 'leaf', props.indentation), + ) + + const onClick = React.useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + dispatch(getClickActions(e)) + }, + [dispatch, getClickActions], + ) + return (
{ + const dispatch = useDispatch() + + const selectedViews = useRefEditorState((store) => store.editor.selectedViews) + + const targetPath = React.useMemo(() => { + return getRowPath(props.row) + }, [props.row]) + + const selected = React.useMemo(() => { + return selectedViews.current.some((view) => EP.pathsEqual(targetPath, view)) + }, [selectedViews, targetPath]) + + const getActions = useGetNavigatorClickActions(targetPath, selected, props.row) + + const onClick = React.useCallback( + (e: React.MouseEvent) => { + e.stopPropagation() + e.preventDefault() + + const actions = getActions(e) + dispatch(actions) + }, + [dispatch, getActions], + ) + + return ( +
+ {props.children} +
+ ) + }, +) +NavigatorRowClickableWrapper.displayName = 'NavigatorRowClickableWrapper' + +export function useGetNavigatorClickActions( + targetPath: ElementPath, + selected: boolean, + row: NavigatorRow, +) { + const navigatorTargets = useRefEditorState((store) => store.derived.navigatorTargets) + const selectedViews = useRefEditorState((store) => store.editor.selectedViews) + const collapsedViews = useRefEditorState((store) => store.editor.navigator.collapsedViews) + const projectContents = useRefEditorState((store) => store.editor.projectContents) + const jsxMetadata = useRefEditorState((store) => store.editor.jsxMetadata) + + const highlightBounds = useHighlightBounds(targetPath) + const conditionalOverrideUpdate = useConditionalOverrideUpdate(row) + + return React.useCallback( + (e: React.MouseEvent) => { + if (e.metaKey && !e.shiftKey) { + return actionsForAddToSelection(targetPath) + } else if (e.shiftKey) { + return actionsForRangeSelection( + targetPath, + navigatorTargets.current, + selectedViews.current, + collapsedViews.current, + projectContents.current, + jsxMetadata.current, + ) + } else { + // when we click on an already selected item we should force vscode to navigate there + if (selected && highlightBounds != null) { + sendMessage( + toVSCodeExtensionMessage( + selectedElementChangedMessageFromHighlightBounds(highlightBounds, 'force-navigation'), + ), + ) + } + return actionsForSingleSelection(targetPath, row, conditionalOverrideUpdate) + } + }, + [ + row, + selectedViews, + projectContents, + conditionalOverrideUpdate, + highlightBounds, + jsxMetadata, + selected, + targetPath, + collapsedViews, + navigatorTargets, + ], + ) +} + +function actionsForAddToSelection(targetPath: ElementPath): EditorAction[] { + return [EditorActions.selectComponents([targetPath], true)] +} + +export function actionsForRangeSelection( + targetPath: ElementPath, + navigatorTargets: NavigatorEntry[], + selectedViews: ElementPath[], + collapsedViews: ElementPath[], + projectContents: ProjectContentTreeRoot, + jsxMetadata: ElementInstanceMetadataMap, +): EditorAction[] { + const selectableTargets = navigatorTargets + .filter((target) => target.type !== 'SYNTHETIC') + .map((target) => target.elementPath) + + // boundaries of the current selection + let selectionTop: number = Infinity + let selectionBottom: number = -Infinity + + // index of the row being clicked + let targetIndex: number = Infinity + + // populate the indexes by matching rows, selected views, and the target path + for (let i = 0; i < selectableTargets.length; i++) { + const target = selectableTargets[i] + if ( + selectedViews.some((path) => { + if (EP.pathsEqual(target, path)) { + return true + } + + const element = getElementFromProjectContents(path, projectContents) + if (MetadataUtils.isElementDataReference(element)) { + return EP.isParentOf(target, path) + } + + return false + }) + ) { + selectionTop = Math.min(selectionTop, i) + selectionBottom = Math.max(selectionBottom, i) + } + if (EP.pathsEqual(target, targetPath)) { + targetIndex = Math.min(targetIndex, i) + } + } + + // derive the slice indexes + const sliceFrom = Math.min(selectionTop, targetIndex) + const sliceTo = Math.max(selectionBottom, targetIndex) + + const selectionPaths = selectableTargets + // get the targets inside the new selection bounds + .slice(sliceFrom, sliceTo + 1) + // get their paths + .flatMap((target) => { + let paths = [target] + // if a collapsed view is included in the range, get its children paths + if (collapsedViews.some((view) => EP.pathsEqual(view, target))) { + const children = MetadataUtils.getChildrenUnordered(jsxMetadata, target) + paths.push(...children.map((c) => c.elementPath)) + } + return paths + }) + + const selection = selectionPaths + // filter out conditional branches rows + .filter((path) => { + const parent = MetadataUtils.findElementByElementPath(jsxMetadata, EP.parentPath(path)) + const isConditionalExpression = + parent != null && + isRight(parent.element) && + parent.element.value.type === 'JSX_CONDITIONAL_EXPRESSION' + + return !isConditionalExpression + }) + + return [EditorActions.selectComponents(selection, false)] +} + +function actionsForSingleSelection( + targetPath: ElementPath, + row: NavigatorRow, + conditionalOverrideUpdate: ConditionalOverrideUpdate, +): EditorAction[] { + let actions: EditorAction[] = [] + + if (isRegulaNavigatorRow(row)) { + const conditionalOverrideActions = isConditionalClauseNavigatorEntry(row.entry) + ? getConditionalOverrideActions(targetPath, conditionalOverrideUpdate) + : getConditionalOverrideActions(EP.parentPath(targetPath), conditionalOverrideUpdate) + actions.push(...conditionalOverrideActions) + } + + const isNotSelectable = isRegulaNavigatorRow(row) && row.entry.type === 'CONDITIONAL_CLAUSE' + if (!isNotSelectable) { + actions.push(EditorActions.selectComponents([targetPath], false)) + } + + return actions +} + +function getRowPath(row: NavigatorRow): ElementPath { + return isRegulaNavigatorRow(row) ? row.entry.elementPath : row.entries[0].elementPath +} + +type ConditionalOverrideUpdate = ConditionalCase | 'clear-override' | 'no-update' + +export function getConditionalOverrideActions( + targetPath: ElementPath, + conditionalOverrideUpdate: ConditionalOverrideUpdate, +): Array { + switch (conditionalOverrideUpdate) { + case 'no-update': + return [] + case 'clear-override': + return [EditorActions.setConditionalOverriddenCondition(targetPath, null)] + case 'true-case': + return [EditorActions.setConditionalOverriddenCondition(targetPath, true)] + case 'false-case': + return [EditorActions.setConditionalOverriddenCondition(targetPath, false)] + default: + assertNever(conditionalOverrideUpdate) + } +} + +function useConditionalOverrideUpdate(row: NavigatorRow) { + return useEditorState( + Substores.metadata, + (store): ConditionalOverrideUpdate => { + if (!isRegulaNavigatorRow(row)) { + return 'no-update' + } + const navigatorEntry = row.entry + const path = navigatorEntry.elementPath + const metadata = store.editor.jsxMetadata + const elementMetadata = MetadataUtils.findElementByElementPath( + store.editor.jsxMetadata, + navigatorEntry.elementPath, + ) + if (isConditionalClauseNavigatorEntry(navigatorEntry)) { + return conditionalOverrideUpdateForClause(navigatorEntry.clause, elementMetadata) + } else { + return conditionalOverrideUpdateForPath(path, metadata) + } + }, + 'useConditionalOverrideUpdate conditionalOverrideUpdate', + ) +} + +function conditionalOverrideUpdateForClause( + clause: ConditionalCase, + elementMetadata: ElementInstanceMetadata | null, +) { + if (isActiveBranchOfConditional(clause, elementMetadata)) { + if (isOverriddenConditional(elementMetadata)) { + return 'clear-override' + } else { + return clause + } + } else { + return clause + } +} + +export function conditionalOverrideUpdateForPath( + path: ElementPath, + metadata: ElementInstanceMetadataMap, +) { + const conditionalCase = getConditionalCaseCorrespondingToBranchPath(path, metadata) + if (conditionalCase != null) { + const parentPath = EP.parentPath(path) + const parentMetadata = MetadataUtils.findElementByElementPath(metadata, parentPath) + if (isActiveBranchOfConditional(conditionalCase, parentMetadata)) { + return 'no-update' + } else if (isDefaultBranchOfConditional(conditionalCase, parentMetadata)) { + return 'clear-override' + } else { + return conditionalCase + } + } + + return 'no-update' +} + +function useHighlightBounds(path: ElementPath) { + return useEditorState( + Substores.projectContents, + (store) => { + const staticPath = EP.dynamicPathToStaticPath(path) + if (staticPath != null) { + const bounds = getHighlightBoundsForProject(store.editor.projectContents) + if (bounds != null) { + const highlightedUID = EP.toUid(staticPath) + return bounds[highlightedUID] + } + } + + return null + }, + 'useHighlightBounds highlightBounds', + ) +} diff --git a/editor/src/components/navigator/navigator-item/navigator-item-components.tsx b/editor/src/components/navigator/navigator-item/navigator-item-components.tsx index 27d36b3b711b..3fe002f4ea84 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-components.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-components.tsx @@ -560,7 +560,7 @@ export const NavigatorItemActionSheet: React.FunctionComponent< visible={true} collapsed={props.collapsed} selected={props.selected} - onMouseDown={collapse} + onClick={collapse} style={{ opacity: 'var(--paneHoverOpacity)', }} diff --git a/editor/src/components/navigator/navigator-item/navigator-item-dnd-container.tsx b/editor/src/components/navigator/navigator-item/navigator-item-dnd-container.tsx index 72b6f6b43a42..c09c838e6364 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-dnd-container.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-dnd-container.tsx @@ -871,7 +871,6 @@ export const NavigatorItemContainer = React.memo((props: NavigatorItemDragAndDro > Array, - index: number, - elementPath: ElementPath, - selected: boolean, - event: React.MouseEvent, -): Array { - if (!selected) { - if (event.metaKey && !event.shiftKey) { - // adds to selection - return MetaActions.selectComponents([elementPath], true) - } else if (event.shiftKey) { - // selects range of items - const targets = getSelectedViewsInRange(index) - return MetaActions.selectComponents(targets, false) - } else { - return MetaActions.selectComponents([elementPath], false) - } - } else { - return [] - } -} - -type ConditionalOverrideUpdate = ConditionalCase | 'clear-override' | 'no-update' - -function getConditionalOverrideActions( - targetPath: ElementPath, - conditionalOverrideUpdate: ConditionalOverrideUpdate, -): Array { - switch (conditionalOverrideUpdate) { - case 'no-update': - return [] - case 'clear-override': - return [EditorActions.setConditionalOverriddenCondition(targetPath, null)] - case 'true-case': - return [EditorActions.setConditionalOverriddenCondition(targetPath, true)] - case 'false-case': - return [EditorActions.setConditionalOverriddenCondition(targetPath, false)] - default: - assertNever(conditionalOverrideUpdate) - } -} - -function selectItem( - dispatch: EditorDispatch, - getSelectedViewsInRange: (i: number) => Array, - navigatorEntry: NavigatorEntry, - index: number, - selected: boolean, - event: React.MouseEvent, - conditionalOverrideUpdate: ConditionalOverrideUpdate, - highlightBounds: HighlightBoundsWithFile | null, -) { - const elementPath = navigatorEntry.elementPath - - const shouldSelect = !( - isDataReferenceNavigatorEntry(navigatorEntry) || - isConditionalClauseNavigatorEntry(navigatorEntry) || - isInvalidOverrideNavigatorEntry(navigatorEntry) || - isRenderPropNavigatorEntry(navigatorEntry) || - isSlotNavigatorEntry(navigatorEntry) - ) - - let selectionActions: EditorAction[] = [] - if (shouldSelect) { - selectionActions.push( - ...getSelectionActions(getSelectedViewsInRange, index, elementPath, selected, event), - ) - } else if (isRenderPropNavigatorEntry(navigatorEntry) && navigatorEntry.childPath != null) { - selectionActions.push(...MetaActions.selectComponents([navigatorEntry.childPath], false)) - } - - // when we click on an already selected item we should force vscode to navigate there - if (selected && shouldSelect && highlightBounds != null) { - sendMessage( - toVSCodeExtensionMessage( - selectedElementChangedMessageFromHighlightBounds(highlightBounds, 'force-navigation'), - ), - ) - } - - const conditionalOverrideActions = isConditionalClauseNavigatorEntry(navigatorEntry) - ? getConditionalOverrideActions(elementPath, conditionalOverrideUpdate) - : getConditionalOverrideActions(EP.parentPath(elementPath), conditionalOverrideUpdate) - - dispatch([...conditionalOverrideActions, ...selectionActions], 'leftpane') -} - const highlightItem = ( dispatch: EditorDispatch, navigatorEntry: NavigatorEntry, @@ -215,8 +116,8 @@ const collapseItem = ( elementPath: ElementPath, e: React.MouseEvent, ) => { - dispatch([EditorActions.toggleCollapse(elementPath)], 'leftpane') e.stopPropagation() + dispatch([EditorActions.toggleCollapse(elementPath)], 'leftpane') } type StyleType = @@ -482,7 +383,6 @@ export type RemixItemType = 'scene' | 'outlet' | 'link' | 'none' export interface NavigatorItemInnerProps { navigatorEntry: NavigatorEntry - index: number indentation: number getSelectedViewsInRange: (i: number) => Array // TODO KILLME noOfChildren: number @@ -501,34 +401,7 @@ export interface NavigatorItemInnerProps { export const NavigatorItem: React.FunctionComponent< React.PropsWithChildren > = React.memo((props) => { - const { - dispatch, - isHighlighted, - isElementVisible, - selected, - collapsed, - navigatorEntry, - isOutletOrDescendantOfOutlet, - getSelectedViewsInRange, - index, - } = props - - const highlightBounds = useEditorState( - Substores.projectContents, - (store) => { - const staticPath = EP.dynamicPathToStaticPath(navigatorEntry.elementPath) - if (staticPath != null) { - const bounds = getHighlightBoundsForProject(store.editor.projectContents) - if (bounds != null) { - const highlightedUID = EP.toUid(staticPath) - return bounds[highlightedUID] - } - } - - return null - }, - 'NavigatorItem highlightBounds', - ) + const { dispatch, isHighlighted, isElementVisible, selected, collapsed, navigatorEntry } = props const colorTheme = useColorTheme() @@ -698,45 +571,6 @@ export const NavigatorItem: React.FunctionComponent< const isRemixItem = codeItemType === 'remix' const isCodeItem = codeItemType !== 'none' - const conditionalOverrideUpdate = useEditorState( - Substores.metadata, - (store): ConditionalOverrideUpdate => { - const path = navigatorEntry.elementPath - const metadata = store.editor.jsxMetadata - const elementMetadata = MetadataUtils.findElementByElementPath( - store.editor.jsxMetadata, - navigatorEntry.elementPath, - ) - if (isConditionalClauseNavigatorEntry(navigatorEntry)) { - if (isActiveBranchOfConditional(navigatorEntry.clause, elementMetadata)) { - if (isOverriddenConditional(elementMetadata)) { - return 'clear-override' - } else { - return navigatorEntry.clause - } - } else { - return navigatorEntry.clause - } - } else { - const conditionalCase = getConditionalCaseCorrespondingToBranchPath(path, metadata) - if (conditionalCase != null) { - const parentPath = EP.parentPath(path) - const parentMetadata = MetadataUtils.findElementByElementPath(metadata, parentPath) - if (isActiveBranchOfConditional(conditionalCase, parentMetadata)) { - return 'no-update' - } else if (isDefaultBranchOfConditional(conditionalCase, parentMetadata)) { - return 'clear-override' - } else { - return conditionalCase - } - } - - return 'no-update' - } - }, - 'NavigatorItem conditionalOverrideUpdate', - ) - const metadata = useEditorState( Substores.metadata, (store): ElementInstanceMetadataMap => { @@ -809,29 +643,6 @@ export const NavigatorItem: React.FunctionComponent< [dispatch, navigatorEntry.elementPath], ) - const select = React.useCallback( - (event: React.MouseEvent) => - selectItem( - dispatch, - getSelectedViewsInRange, - navigatorEntry, - index, - selected, - event, - conditionalOverrideUpdate, - highlightBounds, - ), - [ - dispatch, - getSelectedViewsInRange, - navigatorEntry, - index, - selected, - conditionalOverrideUpdate, - highlightBounds, - ], - ) - const highlight = React.useCallback( () => highlightItem(dispatch, navigatorEntry, selected, isHighlighted), [dispatch, navigatorEntry, selected, isHighlighted], @@ -944,145 +755,149 @@ export const NavigatorItem: React.FunctionComponent< }, [props.navigatorEntry, isScene]) return ( -
- - {isPlaceholder ? ( - navigatorEntry.type === 'SLOT' ? ( - - ) : conditionalCase !== null ? ( - + + {isPlaceholder ? ( + navigatorEntry.type === 'SLOT' ? ( + + ) : conditionalCase !== null ? ( + + ) : ( + + ) + ) : isRenderProp ? ( +
+ {props.label} +
+ ) : elementIsData ? ( +
+ +
) : ( - - ) - ) : isRenderProp ? ( -
- {props.label} -
- ) : elementIsData ? ( -
- -
- ) : ( - - - {unless( - hideExpandableIndicator, - + + {unless( + hideExpandableIndicator, + , + )} + + + {unless( + currentlyRenaming || props.navigatorEntry.type === 'CONDITIONAL_CLAUSE', + , )} - - {unless( - currentlyRenaming || props.navigatorEntry.type === 'CONDITIONAL_CLAUSE', - , - )} - - )} -
-
+ )} + +
+ ) }) NavigatorItem.displayName = 'NavigatorItem' diff --git a/editor/src/components/navigator/navigator.spec.browser2.tsx b/editor/src/components/navigator/navigator.spec.browser2.tsx index 601cc6b7eebd..ccb8d9444def 100644 --- a/editor/src/components/navigator/navigator.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator.spec.browser2.tsx @@ -32,7 +32,7 @@ import { pressKey, } from '../canvas/event-helpers.test-utils' import { NavigatorItemTestId } from './navigator-item/navigator-item' -import { expectNoAction, selectComponentsForTest } from '../../utils/utils.test-utils' +import { expectNoAction, selectComponentsForTest, wait } from '../../utils/utils.test-utils' import { DefaultNavigatorWidth, navigatorEntryToKey, @@ -1494,7 +1494,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -1568,7 +1568,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -1642,7 +1642,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -1719,7 +1719,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot/firstdiv`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -1792,7 +1792,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( 'transparent solid 1px', ) @@ -1846,7 +1846,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -1924,7 +1924,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/parentsibling`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -2820,7 +2820,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -2898,7 +2898,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -2976,7 +2976,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -3057,7 +3057,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot/firstdiv`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -3275,7 +3275,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -3350,7 +3350,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -3425,7 +3425,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) @@ -3503,7 +3503,7 @@ describe('Navigator', () => { const parentEntry = renderResult.renderedDOM.getByTestId( `navigator-item-regular_utopia_storyboard_uid/scene_aaa/sceneroot/firstdiv`, ) - expect((parentEntry.firstChild as HTMLElement).style.outline).toEqual( + expect((parentEntry.firstChild?.firstChild as HTMLElement).style.outline).toEqual( '1px solid var(--utopitheme-navigatorResizeHintBorder)', ) From b56b5e6844a0b765bad22edc5f81b53dfb4fdb0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Thu, 13 Jun 2024 16:31:19 +0200 Subject: [PATCH 071/103] Data selector - filter matching variables (#5921) # [Playground](https://utopia.fish/p/67b6ffa9-careful-alto/?branch_name=fix-data-selector-filtering) ## Problem The data picker highlights variables that do not actually fit the place they are being picked for ## Fix Use the (slightly revamped version of the) existing matching logic to highlight matching variables (see the `orderVariablesForRelevance` function for details) ### Details - removed the unused `disabled` prop from `DataPickerOption` and `VariableOptionBase` - remove the bespoke filtering logic for lists - update the matched prop so that it can express whether the option itself matches, has matching children or does not match at all (this is the `VariableMatches` type) - use this type to color the cartouches - add some extra logic to match options to the `children` prop - this doesn't take into account the annotation for the children prop yet - use a safe way to stringify values in `ValuePreviewColumn` (since stringifying react elements throws a circular object error) ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --------- Co-authored-by: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> --- .../component-section/cartouche-ui.tsx | 2 +- .../component-section/data-picker-popup.tsx | 4 -- .../component-section/data-picker-utils.tsx | 2 - .../data-reference-cartouche.tsx | 3 +- .../data-selector-cartouche.tsx | 7 +-- .../data-selector-columns.tsx | 10 ++++- .../component-section/data-selector-modal.tsx | 9 ++-- .../data-selector-search.tsx | 8 ++-- .../variables-in-scope-utils.spec.ts | 12 ++--- .../variables-in-scope-utils.ts | 45 ++++++++++++------- .../sections/data-reference-section.tsx | 3 +- .../layout-section/list-source-cartouche.tsx | 41 +---------------- 12 files changed, 66 insertions(+), 80 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 924d1bf8800e..7400adfa959a 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -144,7 +144,7 @@ export const CartoucheUI = React.forwardRef( /* Beginning of string */ ...(shouldUseRtlCSS ? { - direction: source === 'literal' ? 'ltr' : 'rtl', // TODO we need a better way to ellipsize the beginnign because rtl eats ' " marks + direction: source === 'literal' ? 'ltr' : 'rtl', // TODO we need a better way to ellipsize the beginning because rtl eats ' " marks } : {}), textAlign: 'left', diff --git a/editor/src/components/inspector/sections/component-section/data-picker-popup.tsx b/editor/src/components/inspector/sections/component-section/data-picker-popup.tsx index 4092d61c4cc6..19c10479ba54 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-popup.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-popup.tsx @@ -9,7 +9,6 @@ export interface PrimitiveOption { definedElsewhere: string depth: number valuePath: Array - disabled: boolean } export interface ArrayOption { @@ -19,7 +18,6 @@ export interface ArrayOption { definedElsewhere: string children: Array valuePath: Array - disabled: boolean } export interface ObjectOption { @@ -29,7 +27,6 @@ export interface ObjectOption { definedElsewhere: string children: Array valuePath: Array - disabled: boolean } export interface JSXOption { @@ -38,7 +35,6 @@ export interface JSXOption { definedElsewhere: string depth: number valuePath: Array - disabled: boolean } export type DataPickerOption = PrimitiveOption | ArrayOption | ObjectOption | JSXOption diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 0c762977192a..5c53a9260d6c 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -17,13 +17,11 @@ import type { ProjectContentTreeRoot } from '../../../assets' import { insertionCeilingToString, type FileRootPath } from '../../../canvas/ui-jsx-canvas' import type { AllElementProps } from '../../../editor/store/editor-state' import type { ArrayInfo, JSXInfo, ObjectInfo, PrimitiveInfo } from './variables-in-scope-utils' -import type { CartoucheUIProps } from './cartouche-ui' interface VariableOptionBase { depth: number definedElsewhere: string valuePath: Array - disabled: boolean insertionCeiling: ElementPath | FileRootPath isChildOfArray: boolean } diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index a4462d7d67aa..29cf79aae8d2 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -24,6 +24,7 @@ import { DataPickerPreferredAllAtom, jsxElementChildToValuePath } from './data-p import { useAtom } from 'jotai' import type { CartoucheDataType, CartoucheHighlight, CartoucheUIProps } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' +import * as PP from '../../../../core/shared/property-path' interface DataReferenceCartoucheControlProps { elementPath: ElementPath @@ -95,7 +96,7 @@ export const DataReferenceCartoucheControl = React.memo( props.renderedAt.type === 'element-property-path' ? props.renderedAt.elementPropertyPath.propertyPath : props.renderedAt.type === 'child-node' - ? null + ? PP.create('children') : assertNever(props.renderedAt) const [preferredAllState] = useAtom(DataPickerPreferredAllAtom) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx index 0f54b58a3077..e3b82e694d80 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -9,6 +9,7 @@ import { MapCounterUi } from '../../../navigator/navigator-item/map-counter' import type { CartoucheUIProps } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' import type { DataPickerOption } from './data-picker-utils' +import { variableMatches } from './variables-in-scope-utils' interface DataPickerCartoucheProps { data: DataPickerOption @@ -27,9 +28,9 @@ export const DataPickerCartouche = React.memo( key={data.valuePath.toString()} source={dataSource ?? 'internal'} datatype={childTypeToCartoucheDataType(data.type)} - selected={!data.disabled && selected} - highlight={data.disabled ? 'disabled' : null} - role={forceRole ?? (data.disabled ? 'information' : 'selection')} + selected={variableMatches(data.variableInfo) && selected} + highlight={variableMatches(data.variableInfo) ? null : 'disabled'} + role={forceRole ?? (variableMatches(data.variableInfo) ? 'selection' : 'information')} testId={`data-selector-option-${data.variableInfo.expression}`} badge={ data.type === 'array' ? ( diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx index 5661fe8fe42e..93048ef639f0 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -109,7 +109,7 @@ interface ValuePreviewColumnProps { } const ValuePreviewColumn = React.memo((props: ValuePreviewColumnProps) => { - const text = JSON.stringify(props.data.variableInfo.value, undefined, 2) + const text = safeJSONStringify(props.data.variableInfo.value) const ref = useScrollIntoView(true) return ( @@ -235,3 +235,11 @@ function useScrollIntoView(shouldScroll: boolean) { return elementRef } + +function safeJSONStringify(value: unknown): string | null { + try { + return JSON.stringify(value, undefined, 2) + } catch { + return null + } +} diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 40354775c31e..03bd0abf709e 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -8,7 +8,6 @@ import { CanvasContextMenuPortalTargetID, arrayEqualsByReference, arrayEqualsByValue, - assertNever, } from '../../../../core/shared/utils' import { when } from '../../../../utils/react-conditionals' import { @@ -33,6 +32,7 @@ import { import { DataSelectorColumns } from './data-selector-columns' import { DataSelectorLeftSidebar } from './data-selector-left-sidebar' import { DataSelectorSearch } from './data-selector-search' +import { variableMatches } from './variables-in-scope-utils' import { DataPickerCartouche } from './data-selector-cartouche' export const DataSelectorPopupBreadCrumbsTestId = 'data-selector-modal-top-bar' @@ -158,7 +158,7 @@ export const DataSelectorModal = React.memo( if (variable == null) { return } - if (variable.disabled) { + if (variable.variableInfo.matches !== 'matches') { return } onPropertyPicked( @@ -176,6 +176,9 @@ export const DataSelectorModal = React.memo( const searchNullOrEmpty = searchTerm == null || searchTerm.length < 1 + const selectedVariableIsDisabled = + optionalMap((v) => !variableMatches(v.variableInfo), selectedVariableOption) ?? true + return ( diff --git a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx index c96591f00e9a..1e627b2c40b6 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx @@ -5,6 +5,7 @@ import { assertNever } from '../../../../core/shared/utils' import { FlexRow, Icons, UtopiaStyles } from '../../../../uuiui' import { type DataPickerOption, type ObjectPath } from './data-picker-utils' import { DataPickerCartouche } from './data-selector-cartouche' +import { when } from '../../../../utils/react-conditionals' export interface DataSelectorSearchProps { setNavigatedToPath: (_: DataPickerOption) => void @@ -56,9 +57,10 @@ export const DataSelectorSearch = React.memo( searchTerm={searchTerm} fontWeightForMatch={900} /> - {i < searchResult.valuePath.length - 1 ? ( - - ) : null} + {when( + i < searchResult.valuePath.length - 1, + , + )} ))} diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts index fca9a29899d0..00a3b7d947bc 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts @@ -51,7 +51,7 @@ describe('orderVariablesForRelevance', () => { ], "type": "elementpath", }, - "matches": false, + "matches": "child-matches", "props": Array [ Object { "expression": "style['left']", @@ -64,7 +64,7 @@ describe('orderVariablesForRelevance', () => { ], "type": "elementpath", }, - "matches": true, + "matches": "matches", "type": "primitive", "value": 300, }, @@ -79,7 +79,7 @@ describe('orderVariablesForRelevance', () => { ], "type": "elementpath", }, - "matches": false, + "matches": "does-not-match", "type": "primitive", "value": "relative", }, @@ -138,7 +138,7 @@ describe('orderVariablesForRelevance', () => { ], "type": "elementpath", }, - "matches": true, + "matches": "matches", "props": Array [ Object { "expression": "style['left']", @@ -151,7 +151,7 @@ describe('orderVariablesForRelevance', () => { ], "type": "elementpath", }, - "matches": false, + "matches": "does-not-match", "type": "primitive", "value": 300, }, @@ -166,7 +166,7 @@ describe('orderVariablesForRelevance', () => { ], "type": "elementpath", }, - "matches": false, + "matches": "does-not-match", "type": "primitive", "value": "relative", }, diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index eb0b2a8da4b9..9dce7d40945f 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -59,7 +59,6 @@ function valuesFromObject( ) .map(patchDefinedElsewhereInfo), valuePath: valuePath, - disabled: false, isChildOfArray: isChildOfArray, }, ] @@ -84,7 +83,6 @@ function valuesFromObject( ) .map(patchDefinedElsewhereInfo), valuePath: valuePath, - disabled: false, isChildOfArray: isChildOfArray, }, ] @@ -111,7 +109,6 @@ function valuesFromVariable( definedElsewhere: originalObjectName, depth: depth, valuePath: valuePath, - disabled: false, isChildOfArray: isChildOfArray, }, ] @@ -142,7 +139,6 @@ function valuesFromVariable( definedElsewhere: originalObjectName, depth: depth, valuePath: valuePath, - disabled: false, isChildOfArray: isChildOfArray, }, ] @@ -169,13 +165,27 @@ function usePropertyControlDescriptions( return controlForProp[0] ?? null } +export type VariableMatches = 'matches' | 'child-matches' | 'does-not-match' + +export const variableMatches = (variable: VariableInfoBase) => { + switch (variable.matches) { + case 'matches': + return true + case 'child-matches': + case 'does-not-match': + return false + default: + assertNever(variable.matches) + } +} + interface VariableInfoBase { type: string expression: string expressionPathPart: string | number value: unknown insertionCeiling: ElementPath | FileRootPath - matches: boolean + matches: VariableMatches } export interface PrimitiveInfo extends VariableInfoBase { @@ -227,7 +237,7 @@ export function variableInfoFromValue( expressionPathPart: expressionPathPart, value: value, insertionCeiling: insertionCeiling, - matches: false, + matches: 'does-not-match', } case 'object': if (value == null) { @@ -237,7 +247,7 @@ export function variableInfoFromValue( expressionPathPart: expressionPathPart, value: value, insertionCeiling: insertionCeiling, - matches: false, + matches: 'does-not-match', } } if (Array.isArray(value)) { @@ -247,7 +257,7 @@ export function variableInfoFromValue( expressionPathPart: expressionPathPart, value: value, insertionCeiling: insertionCeiling, - matches: false, + matches: 'does-not-match', elements: mapDropNulls( (e, idx) => variableInfoFromValue( @@ -268,7 +278,7 @@ export function variableInfoFromValue( expressionPathPart: expressionPathPart, value: value, insertionCeiling: insertionCeiling, - matches: false, + matches: 'does-not-match', } } return { @@ -277,7 +287,7 @@ export function variableInfoFromValue( expressionPathPart: expressionPathPart, value: value, insertionCeiling: insertionCeiling, - matches: false, + matches: 'does-not-match', props: mapDropNulls(([key, propValue]) => { return variableInfoFromValue( `${expression}['${key}']`, @@ -366,6 +376,9 @@ export function orderVariablesForRelevance( targetControlDescription != null && variableMatchesControlDescription(variable.value, targetControlDescription) + const valueMatchesChildrenProp = + targetPropertyName === 'children' && isValidReactNode(variable.value) + const valueMatchesCurrentPropValue = currentPropertyValue.type === 'existing' && variableShapesMatch(currentPropertyValue.value, variable.value) @@ -375,15 +388,15 @@ export function orderVariablesForRelevance( (variable.type === 'object' && variable.props.some((e) => e.matches)) if (valueExactlyMatchesPropertyName || variableCanBeMappedOver) { - valuesExactlyMatchingPropertyName.push({ ...variable, matches: true }) + valuesExactlyMatchingPropertyName.push({ ...variable, matches: 'matches' }) } else if (valueExactlyMatchesControlDescription) { - valuesExactlyMatchingPropertyDescription.push({ ...variable, matches: true }) - } else if (valueMatchesControlDescription) { - valuesMatchingPropertyDescription.push({ ...variable, matches: true }) + valuesExactlyMatchingPropertyDescription.push({ ...variable, matches: 'matches' }) + } else if (valueMatchesControlDescription || valueMatchesChildrenProp) { + valuesMatchingPropertyDescription.push({ ...variable, matches: 'matches' }) } else if (arrayOrObjectChildMatches) { - valueElementMatches.push({ ...variable, matches: false }) + valueElementMatches.push({ ...variable, matches: 'child-matches' }) } else if (valueMatchesCurrentPropValue) { - valuesMatchingPropertyShape.push({ ...variable, matches: true }) + valuesMatchingPropertyShape.push({ ...variable, matches: 'matches' }) } else { restOfValues.push(variable) } diff --git a/editor/src/components/inspector/sections/data-reference-section.tsx b/editor/src/components/inspector/sections/data-reference-section.tsx index 996c7f907c14..267b64aad3f6 100644 --- a/editor/src/components/inspector/sections/data-reference-section.tsx +++ b/editor/src/components/inspector/sections/data-reference-section.tsx @@ -26,6 +26,7 @@ import { } from './component-section/variables-in-scope-utils' import { jsxElementChildToValuePath } from './component-section/data-picker-utils' import { CartoucheInspectorWrapper } from './component-section/cartouche-control' +import * as PP from '../../../core/shared/property-path' export const DataReferenceSectionId = 'code-element-section-test-id' @@ -84,7 +85,7 @@ export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[ const varsInScope = useVariablesInScopeForSelectedElement( elementPathForDataPicker, - null, + PP.create('children'), preferredAllState, ) diff --git a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx index f2e9a73a6f91..4a837aefe5f8 100644 --- a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx @@ -3,7 +3,7 @@ import React from 'react' import { MetadataUtils } from '../../../../core/model/element-metadata-utils' import type { ElementPath } from '../../../../core/shared/project-file-types' -import { NO_OP, assertNever } from '../../../../core/shared/utils' +import { NO_OP } from '../../../../core/shared/utils' import { Substores, useEditorState } from '../../../editor/store/store-hook' import { DataCartoucheInner, @@ -15,7 +15,6 @@ import { useDispatch } from '../../../editor/store/dispatch-context' import type { JSExpressionOtherJavaScript } from '../../../../core/shared/element-template' import { replaceElementInScope } from '../../../editor/actions/action-creators' import { useAtom } from 'jotai' -import type { DataPickerOption } from '../component-section/data-picker-utils' import { DataPickerPreferredAllAtom, jsxElementChildToValuePath, @@ -24,42 +23,11 @@ import { getCartoucheDataTypeForExpression, useVariablesInScopeForSelectedElement, } from '../component-section/variables-in-scope-utils' -import { mapDropNulls } from '../../../../core/shared/array-utils' import { traceDataFromElement, dataPathSuccess } from '../../../../core/data-tracing/data-tracing' import type { CartoucheDataType } from '../component-section/cartouche-ui' import { CartoucheInspectorWrapper } from '../component-section/cartouche-control' import { MapCounter } from '../../../navigator/navigator-item/map-counter' -function filterVariableOption(option: DataPickerOption): DataPickerOption | null { - switch (option.type) { - case 'array': - return { - ...option, - children: filterKeepArraysOnly(option.children), - disabled: false, - } - case 'object': - const children = filterKeepArraysOnly(option.children) - return { - ...option, - children: children, - disabled: true, - } - case 'jsx': - case 'primitive': - return { - ...option, - disabled: true, - } - default: - assertNever(option) - } -} - -function filterKeepArraysOnly(options: DataPickerOption[]): DataPickerOption[] { - return mapDropNulls((o) => filterVariableOption(o), options) -} - interface MapListSourceCartoucheProps { target: ElementPath selected: boolean @@ -129,11 +97,6 @@ const MapListSourceCartoucheInner = React.memo((props: MapListSourceCartouchePro preferredAllState, ) - const filteredVariableNamesInScope = React.useMemo( - () => filterKeepArraysOnly(variableNamesInScope), - [variableNamesInScope], - ) - const pathToMappedExpression = React.useMemo( () => originalMapExpression === 'multiselect' || originalMapExpression === 'not-a-mapexpression' @@ -143,7 +106,7 @@ const MapListSourceCartoucheInner = React.memo((props: MapListSourceCartouchePro ) const { popupIsOpen, DataPickerComponent, setReferenceElement, openPopup } = useDataPickerButton( - filteredVariableNamesInScope, + variableNamesInScope, onPickMappedElement, pathToMappedExpression, target, From 58a70921f10bae37bf8a8884329e7bbfc768f386 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:36:52 +0200 Subject: [PATCH 072/103] Consistent border radii for navigator selection (#5928) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** Selected rows in the navigator have inconsistent / potato border radii applied to pretty much any selected row. Moreover, the children selection also does not have any border radius. **Fix:** Contiguous regions of selection now share just 4 rounded corners. This is done with a hook which is used on both the regular and the condensed navigator rows, so they share all the underlying logic to figure out which element should have `borderRadius` applied or not. Note: there's a reasonable chance there will be corner (pun intended) cases here and there, but it feels decently solid. Screenshot 2024-06-13 at 4 08 41 PM **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5927 --- .../navigator-condensed-entry.tsx | 25 ++++- .../navigator-item/navigator-item.tsx | 105 ++++++++++-------- ...e-navigator-selection-bounds-for-entry.tsx | 77 +++++++++++++ 3 files changed, 156 insertions(+), 51 deletions(-) create mode 100644 editor/src/components/navigator/navigator-item/use-navigator-selection-bounds-for-entry.tsx diff --git a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx index f298ea20aded..9ea48a1b6002 100644 --- a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx @@ -7,7 +7,11 @@ import { Substores, useEditorState } from '../../editor/store/store-hook' import { condensedNavigatorRow, type CondensedNavigatorRow } from '../navigator-row' import { MetadataUtils } from '../../../core/model/element-metadata-utils' import { getNavigatorEntryLabel, labelSelector } from './navigator-item-wrapper' -import { BasePaddingUnit, elementWarningsSelector } from './navigator-item' +import { + BasePaddingUnit, + NavigatorRowBorderRadius, + elementWarningsSelector, +} from './navigator-item' import { setHighlightedViews, toggleCollapse } from '../../editor/actions/action-creators' import type { ElementPath } from 'utopia-shared/src/types' import { unless, when } from '../../../utils/react-conditionals' @@ -18,6 +22,7 @@ import { NavigatorRowClickableWrapper, useGetNavigatorClickActions, } from './navigator-item-clickable-wrapper' +import { useNavigatorSelectionBoundsForEntry } from './use-navigator-selection-bounds-for-entry' function useEntryLabel(entry: NavigatorEntry) { const labelForTheElement = useEditorState( @@ -87,6 +92,12 @@ export const CondensedEntryItemWrapper = React.memo( ) }, [selectedViews, props.navigatorRow]) + const { isTopOfSelection, isBottomOfSelection } = useNavigatorSelectionBoundsForEntry( + props.navigatorRow.entries[0], + rowRootSelected, + 0, + ) + return (
diff --git a/editor/src/components/navigator/navigator-item/navigator-item.tsx b/editor/src/components/navigator/navigator-item/navigator-item.tsx index ba2a5105843a..8dba98288451 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.tsx @@ -68,6 +68,7 @@ import { DataReferenceCartoucheControl } from '../../inspector/sections/componen import { MapListSourceCartoucheNavigator } from '../../inspector/sections/layout-section/list-source-cartouche' import { regularNavigatorRow } from '../navigator-row' import { NavigatorRowClickableWrapper } from './navigator-item-clickable-wrapper' +import { useNavigatorSelectionBoundsForEntry } from './use-navigator-selection-bounds-for-entry' export function getItemHeight(navigatorEntry: NavigatorEntry): number { if (isConditionalClauseNavigatorEntry(navigatorEntry)) { @@ -168,22 +169,38 @@ const getColors = ( } } -const computeResultingStyle = ( - selected: boolean, - emphasis: Emphasis, - isInsideComponent: boolean, - isDynamic: boolean, - isProbablyScene: boolean, - fullyVisible: boolean, - isFocusedComponent: boolean, - isInFocusedComponentSubtree: boolean, - isFocusableComponent: boolean, - isHighlightedForInteraction: boolean, - isDescendantOfSelected: boolean, - isErroredGroup: boolean, - colorTheme: ThemeObject, - isSingleItem: boolean, -) => { +export const NavigatorRowBorderRadius = 5 + +const computeResultingStyle = (params: { + selected: boolean + isTopOfSelection: boolean + isBottomOfSelection: boolean + emphasis: Emphasis + isInsideComponent: boolean + isProbablyScene: boolean + fullyVisible: boolean + isFocusedComponent: boolean + isFocusableComponent: boolean + isHighlightedForInteraction: boolean + isDescendantOfSelected: boolean + isErroredGroup: boolean + colorTheme: ThemeObject +}) => { + const { + selected, + isTopOfSelection, + isBottomOfSelection, + emphasis, + isInsideComponent, + isProbablyScene, + fullyVisible, + isFocusedComponent, + isFocusableComponent, + isHighlightedForInteraction, + isDescendantOfSelected, + isErroredGroup, + colorTheme, + } = params let styleType: StyleType = 'default' let selectedType: SelectedType = 'unselected' @@ -224,15 +241,16 @@ const computeResultingStyle = ( let result = getColors(styleType, selectedType, colorTheme) - const borderRadiusTop = selected ? '5px 5px' : '0 0' - // TODO: add the case of a last descendant of a selected component - const borderRadiusBottom = selected && isSingleItem ? '5px 5px' : '0 0' - const borderRadius = `${borderRadiusTop} ${borderRadiusBottom}` + const borderRadiusTop = isTopOfSelection ? NavigatorRowBorderRadius : 0 + const borderRadiusBottom = isBottomOfSelection ? NavigatorRowBorderRadius : 0 result.style = { ...result.style, fontWeight: isProbablyParentOfSelected || isProbablyScene ? 600 : 'inherit', - borderRadius: borderRadius, + borderTopLeftRadius: borderRadiusTop, + borderTopRightRadius: borderRadiusTop, + borderBottomLeftRadius: borderRadiusBottom, + borderBottomRightRadius: borderRadiusBottom, } return result @@ -568,8 +586,6 @@ export const NavigatorItem: React.FunctionComponent< ) const isConditional = codeItemType === 'conditional' - const isRemixItem = codeItemType === 'remix' - const isCodeItem = codeItemType !== 'none' const metadata = useEditorState( Substores.metadata, @@ -648,11 +664,6 @@ export const NavigatorItem: React.FunctionComponent< [dispatch, navigatorEntry, selected, isHighlighted], ) - const removeHighlight = React.useCallback( - () => dispatch([EditorActions.clearHighlightedViews()]), - [dispatch], - ) - const focusComponent = React.useCallback( (event: React.MouseEvent) => { if (isManuallyFocusableComponent && !event.altKey) { @@ -680,7 +691,6 @@ export const NavigatorItem: React.FunctionComponent< const isPlaceholder = isEntryAPlaceholder(props.navigatorEntry) - const isComponentScene = useIsProbablyScene(navigatorEntry) && childComponentCount === 1 const isRenderProp = isRenderPropNavigatorEntry(navigatorEntry) const containerStyle: React.CSSProperties = React.useMemo(() => { @@ -702,25 +712,28 @@ export const NavigatorItem: React.FunctionComponent< ) }, [childComponentCount, isFocusedComponent, isConditional]) - const isSingleItem = (canBeExpanded && collapsed) || childComponentCount === 0 - - const resultingStyle = computeResultingStyle( - elementIsData ? false : selected, - emphasis, - isInsideComponent, - isDynamic, - isProbablyScene, - fullyVisible, - isFocusedComponent, - isInFocusedComponentSubtree, - isManuallyFocusableComponent, - isHighlightedForInteraction, - elementIsData && selected ? false : isDescendantOfSelected, - isErroredGroup, - colorTheme, - isSingleItem, + const { isTopOfSelection, isBottomOfSelection } = useNavigatorSelectionBoundsForEntry( + navigatorEntry, + selected, + childComponentCount, ) + const resultingStyle = computeResultingStyle({ + selected: elementIsData ? false : selected, + isTopOfSelection: isTopOfSelection, + isBottomOfSelection: isBottomOfSelection, + emphasis: emphasis, + isInsideComponent: isInsideComponent, + isProbablyScene: isProbablyScene, + fullyVisible: fullyVisible, + isFocusedComponent: isFocusedComponent, + isFocusableComponent: isManuallyFocusableComponent, + isHighlightedForInteraction: isHighlightedForInteraction, + isDescendantOfSelected: elementIsData && selected ? false : isDescendantOfSelected, + isErroredGroup: isErroredGroup, + colorTheme: colorTheme, + }) + const rowStyle = useKeepReferenceEqualityIfPossible({ paddingLeft: getElementPadding(entryNavigatorDepth), height: getItemHeight(navigatorEntry), diff --git a/editor/src/components/navigator/navigator-item/use-navigator-selection-bounds-for-entry.tsx b/editor/src/components/navigator/navigator-item/use-navigator-selection-bounds-for-entry.tsx new file mode 100644 index 000000000000..43ed0956a51b --- /dev/null +++ b/editor/src/components/navigator/navigator-item/use-navigator-selection-bounds-for-entry.tsx @@ -0,0 +1,77 @@ +import React from 'react' +import * as EP from '../../../core/shared/element-path' +import type { NavigatorEntry } from '../../editor/store/editor-state' +import { Substores, useEditorState } from '../../editor/store/store-hook' +import { isRegulaNavigatorRow } from '../navigator-row' + +export function useNavigatorSelectionBoundsForEntry( + navigatorEntry: NavigatorEntry, + selected: boolean, + childComponentCount: number, +): { + isTopOfSelection: boolean + isBottomOfSelection: boolean +} { + const selectedViews = useEditorState( + Substores.selectedViews, + (store) => store.editor.selectedViews, + 'useNavigatorSelectionBoundsCheck selectedViews', + ) + + const navigatorRowsPaths = useEditorState( + Substores.derived, + (store) => { + return store.derived.navigatorRows.map((row) => + isRegulaNavigatorRow(row) ? row.entry.elementPath : row.entries[0].elementPath, + ) + }, + 'useNavigatorSelectionBoundsCheck navigatorRowsPaths', + ) + + const collapsedViews = useEditorState( + Substores.navigator, + (store) => { + return store.editor.navigator.collapsedViews + }, + 'useNavigatorSelectionBoundsCheck collapsedViews', + ) + + return React.useMemo(() => { + const index = navigatorRowsPaths.findIndex((view) => + EP.pathsEqual(view, navigatorEntry.elementPath), + ) + + const previous = index > 0 ? navigatorRowsPaths.at(index - 1) : null + const next = index < navigatorRowsPaths.length - 1 ? navigatorRowsPaths.at(index + 1) : null + + const isDangling = + childComponentCount === 0 || collapsedViews.includes(navigatorEntry.elementPath) + + const isTopOfSelection = + previous == null || + (!selectedViews.some( + (view) => + EP.pathsEqual(view, previous) || + EP.isDescendantOf(EP.parentPath(navigatorEntry.elementPath), view) || + EP.isDescendantOf(previous, view), + ) && + selected) + + const isBottomOfSelection = + next == null || + ((!selected || isDangling) && + !selectedViews.some((view) => EP.pathsEqual(view, next) || EP.isDescendantOf(next, view))) + + return { + isTopOfSelection: isTopOfSelection, + isBottomOfSelection: isBottomOfSelection, + } + }, [ + navigatorRowsPaths, + navigatorEntry, + selectedViews, + selected, + childComponentCount, + collapsedViews, + ]) +} From 04a5b5bc35b741b841aec8821a761f1e9755bf7e Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:54:18 +0200 Subject: [PATCH 073/103] Feat/condensed row component (#5922) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of #5840 **Problem:** Condensed rows (and even render prop rows!) don't use the purple colors for component contexts. **Fix:** Make them behave like the other navigator rows. | Before | After | |--------|--------| | Screenshot 2024-06-13 at 1 25 32 PM | Screenshot 2024-06-13 at 1 25 25 PM | **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../navigator-condensed-entry.tsx | 58 ++++++++++++++++--- .../navigator-item/navigator-item.tsx | 1 - 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx index 9ea48a1b6002..16ba8ea481cc 100644 --- a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx @@ -22,6 +22,7 @@ import { NavigatorRowClickableWrapper, useGetNavigatorClickActions, } from './navigator-item-clickable-wrapper' +import type { ThemeObject } from '../../../uuiui/styles/theme/theme-helpers' import { useNavigatorSelectionBoundsForEntry } from './use-navigator-selection-bounds-for-entry' function useEntryLabel(entry: NavigatorEntry) { @@ -38,6 +39,12 @@ function useEntryLabel(entry: NavigatorEntry) { return entryLabel } +function getSelectionColor(colorTheme: ThemeObject, isComponent: boolean) { + return isComponent + ? { main: colorTheme.selectionPurple.value, child: colorTheme.childSelectionPurple.value } + : { main: colorTheme.selectionBlue.value, child: colorTheme.childSelectionBlue.value } +} + export const CondensedEntryItemWrapper = React.memo( (props: { windowStyle: React.CSSProperties; navigatorRow: CondensedNavigatorRow }) => { const colorTheme = useColorTheme() @@ -73,6 +80,31 @@ export const CondensedEntryItemWrapper = React.memo( 'CondensedEntryItemWrapper isCollapsed', ) + const autoFocusedPaths = useEditorState( + Substores.derived, + (store) => store.derived.autoFocusedPaths, + 'CondensedEntryItemWrapper autoFocusedPaths', + ) + + const isComponentOrInsideComponent = useEditorState( + Substores.focusedElement, + (store) => + props.navigatorRow.entries.some( + (entry) => + EP.isInExplicitlyFocusedSubtree( + store.editor.focusedElementPath, + autoFocusedPaths, + entry.elementPath, + ) || + EP.isExplicitlyFocused( + store.editor.focusedElementPath, + autoFocusedPaths, + entry.elementPath, + ), + ), + 'CondensedEntryItemWrapper isInFocusedComponentSubtree', + ) + const isDataReferenceRow = React.useMemo(() => { return props.navigatorRow.entries.every( (entry, idx) => @@ -92,6 +124,15 @@ export const CondensedEntryItemWrapper = React.memo( ) }, [selectedViews, props.navigatorRow]) + function getBackgroundColor() { + if (rowRootSelected) { + return getSelectionColor(colorTheme, isComponentOrInsideComponent).main + } else if (hasSelection || wholeRowInsideSelection) { + return getSelectionColor(colorTheme, isComponentOrInsideComponent).child + } else { + return 'transparent' + } + } const { isTopOfSelection, isBottomOfSelection } = useNavigatorSelectionBoundsForEntry( props.navigatorRow.entries[0], rowRootSelected, @@ -104,11 +145,7 @@ export const CondensedEntryItemWrapper = React.memo( ...props.windowStyle, display: 'flex', alignItems: 'center', - backgroundColor: rowRootSelected - ? colorTheme.selectionBlue.value - : hasSelection || wholeRowInsideSelection - ? colorTheme.childSelectionBlue.value - : 'transparent', + backgroundColor: getBackgroundColor(), borderTopLeftRadius: isTopOfSelection ? NavigatorRowBorderRadius : 0, borderTopRightRadius: isTopOfSelection ? NavigatorRowBorderRadius : 0, borderBottomLeftRadius: @@ -138,6 +175,7 @@ export const CondensedEntryItemWrapper = React.memo( wholeRowInsideSelection={wholeRowInsideSelection} rowContainsSelection={rowContainsSelection} rowRootSelected={rowRootSelected} + isComponentOrInsideComponent={isComponentOrInsideComponent} /> ) })} @@ -158,6 +196,7 @@ const CondensedEntryItem = React.memo( wholeRowInsideSelection: boolean showSeparator: boolean showExpandableIndicator: boolean + isComponentOrInsideComponent: boolean }) => { const colorTheme = useColorTheme() @@ -206,7 +245,7 @@ const CondensedEntryItem = React.memo( if (props.wholeRowInsideSelection) { return 'transparent' } else if (!selectionIsDataReference && (isSelected || isChildOfSelected)) { - return colorTheme.childSelectionBlue.value + return getSelectionColor(colorTheme, props.isComponentOrInsideComponent).child } else { return colorTheme.bg1.value } @@ -216,6 +255,7 @@ const CondensedEntryItem = React.memo( selectionIsDataReference, isSelected, isChildOfSelected, + props.isComponentOrInsideComponent, ]) return ( @@ -229,6 +269,7 @@ const CondensedEntryItem = React.memo( isDataReferenceRow={props.isDataReferenceRow} indentation={indentation} rowRootSelected={props.rowRootSelected} + isComponentOrInsideComponent={props.isComponentOrInsideComponent} /> {when( props.showSeparator, @@ -253,6 +294,7 @@ const CondensedEntryItemContent = React.memo( showExpandableIndicator: boolean isDataReferenceRow: boolean indentation: number + isComponentOrInsideComponent: boolean }) => { const dispatch = useDispatch() const colorTheme = useColorTheme() @@ -341,7 +383,9 @@ const CondensedEntryItemContent = React.memo( justifyContent: 'center', borderRadius: 5, backgroundColor: - props.selected && !isDataReference ? colorTheme.selectionBlue.value : undefined, + props.selected && !isDataReference + ? getSelectionColor(colorTheme, props.isComponentOrInsideComponent).main + : undefined, width: '100%', height: '100%', padding: props.showExpandableIndicator ? '0px 5px' : 0, diff --git a/editor/src/components/navigator/navigator-item/navigator-item.tsx b/editor/src/components/navigator/navigator-item/navigator-item.tsx index 8dba98288451..f898de0e0978 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item.tsx @@ -444,7 +444,6 @@ export const NavigatorItem: React.FunctionComponent< const isInFocusedComponentSubtree = useEditorState( Substores.focusedElement, (store) => - isRegularNavigatorEntry(navigatorEntry) && EP.isInExplicitlyFocusedSubtree( store.editor.focusedElementPath, autoFocusedPaths, From 26c219ad8b608967dc6734628f9f2fb2f68b315b Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:44:47 +0200 Subject: [PATCH 074/103] Decode HTML entities in cartouche labels (#5930) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** HTML entities are displayed raw in the cartouche labels. **Fix:** Parse the entities when building the content to display. Screenshot 2024-06-13 at 5 29 45 PM **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5916 --- .../component-section/data-reference-cartouche.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index 29cf79aae8d2..2a1aac0297ba 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -25,6 +25,9 @@ import { useAtom } from 'jotai' import type { CartoucheDataType, CartoucheHighlight, CartoucheUIProps } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' import * as PP from '../../../../core/shared/property-path' +import { AllHtmlEntities } from 'html-entities' + +const htmlEntities = new AllHtmlEntities() interface DataReferenceCartoucheControlProps { elementPath: ElementPath @@ -44,11 +47,16 @@ export const DataReferenceCartoucheControl = React.memo( const contentsToDisplay = useEditorState( Substores.metadata, - (store) => - getTextContentOfElement( + (store) => { + const content = getTextContentOfElement( childOrAttribute, MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, elementPath), - ), + ) + if (content.label != null) { + return { ...content, label: htmlEntities.decode(content.label) } + } + return content + }, 'DataReferenceCartoucheControl contentsToDisplay', ) From 8f9fd54da35570a0daa136b6a0def9c21918640e Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Thu, 13 Jun 2024 12:19:21 -0400 Subject: [PATCH 075/103] fix for out of bounds arrow icon (#5933) fix to make out bounds arrow icon face 9 o'clock --- .../light/semantic/arrowOutOfBounds@2x.png | Bin 1412 -> 1029 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/editor/resources/editor/icons/light/semantic/arrowOutOfBounds@2x.png b/editor/resources/editor/icons/light/semantic/arrowOutOfBounds@2x.png index 0d4a28016dc34fa80840411d915bd53551010b45..056ea514be1754882dbe0af928669d0a28ee7f7c 100644 GIT binary patch delta 651 zcmV;60(AX^3xxwl|s&BAr)A!}khEvH2i2uSL1ktl)og%DeFxk{9W%2jac+5>j)|#5gTUaL5#5EB)IAGOopMhmkuf8NA zoTQdsX-(|HHF&WPA7^y>M>bqWP=bp@iHx8Imq{Sf6u0C&wjz3Gt}1*ExRRwn)<^rC l0y)9u^e@EY@pwEQ;2NT)P$=N*9{~UW002ovPDHLkV1ic!CwTw> delta 1037 zcmV+o1oHcZ2!snEiBL{Q4GJ0x0000DNk~Le0000f0000e2nGNE0AoDUQ?Vh40e=I< zNkl_(=6Jk)m{zWRWXJbzXT6!(+1nd-2`2I-lf9Xpo%!ay@4cBhfD2@U zoJnWK*dRVCyy{`u&gF70{0l&G7JrsarpF?jH#or->y9S3^0|?8SZ_EVi{iw#%4DnM zv(={0_KvhfpTQZRFX6o{RyKBhm|XSSzXyr{A0PL@sO;oLB-+4W+J+2~Pk3*Mm919i z_s?U1>dNo-Qvu1tf((&F(i1CVm*kfR`1YxDqJCpxS%D0ZL~>oMOqBBQ=zqHW$%kDA z3!A?BotFFo3F0!t}ZiYfYKh{9O#N8>M(9P|inWf`%D7ElCRkcUfT@>GBTh zbKjHu#stz|tZn-+?Q}MVuQPqBOv<5_dvbRO9(`4@jRtmVkqO`l=6_F>xQKVnPIjP$ zepj*u2(mCD$%)eHX2iA;9B!#vkor*um|8uF9Y@`%`irq$%}Ek??vn!P{?#1JjzKJh6`y(a?D|o4id9=9&RZ*T>j$2@@JVSSy9cgs$9gxerl3D;gUXG zvAzDVphhYzG<<1?I)6~KIucDvu2@N9$#Atbv5hQ3L`BPx)h1D&q4oBUWLFOq<6WJK zB)?YB_7*wu(9ZKxN%UeMMfC_>NhTe7;|Nwbx!B!G&<0}u0{h%b@%8{cTE~ul3URh+kfal@s_*v8fuXOhAee? zFqoX`OO*mt>+y+QV@dDSBtg0J&~c5@ONfqJ8JM73A}6FuLH$Le^NAKZE2@WHQqa`b8NzxUd z35Foj`(8l)8)9Dsxq6};@kEW^1k!=-JXnrc_Go4L#{%CL>n!;nHxpEJbEOZ@4(ad? zZSiu2KdG&h@VN_tn;W{9nUPEa3;w?p7ZN6)MjW{d{FnFxZTq#9)uCrP00000NkvXX Hu0mjfl=I?M From 7cb0904480bbb1bd25302302d4488ee3178cc482 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Thu, 13 Jun 2024 23:32:06 +0200 Subject: [PATCH 076/103] Fix: fold object rows by default (#5929) **Problem:** Object controls in the component inspector are open by default, even if their value is set by data. **Fix:** Make all object control rows folded by default. **Commit Details:** (< vv pls delete this section if's not relevant) - RowForObjectControl folded by default - RowForObjectControl uses a UIGridRow to show the cartouche at the proper place - RowForArrayControl gets the UIGridRow treatment too - UIGridRow now supports forwardRef image --- .../component-section/component-section.tsx | 67 ++++---- .../inspector/widgets/ui-grid-row.tsx | 45 +++--- ...performance-regression-tests.spec.tsx.snap | 152 +++++++++--------- 3 files changed, 133 insertions(+), 131 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index 364601101c4e..5fe686ba46af 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -770,34 +770,38 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { - - - {title} - - {propertyStatus.overwritable && !propertyStatus.controlled ? ( - - {insertingRow ? ( - - ) : ( - - )} - - ) : null} + + + {title} + + {propertyStatus.overwritable && !propertyStatus.controlled ? ( + + {insertingRow ? ( + + ) : ( + + )} + + ) : null} + { showHiddenControl={props.showHiddenControl} elementPath={selectedViews.at(0) ?? EP.emptyElementPath} /> - +
{ - const [open, setOpen] = React.useState(true) + const partOfBiggerObject = props.propPath.propertyElements.length > 1 + const [open, setOpen] = React.useState(partOfBiggerObject) const handleOnClick = React.useCallback(() => { if (!props.disableToggling) { setOpen(!open) @@ -1119,7 +1124,9 @@ const RowForObjectControl = React.memo((props: RowForObjectControlProps) => { style={{ flexGrow: 1, justifyContent: 'space-between', paddingRight: 10 }} ref={dataPickerButtonData.setReferenceElement} > - { elementPath={selectedViews.at(0) ?? EP.emptyElementPath} />
- +
diff --git a/editor/src/components/inspector/widgets/ui-grid-row.tsx b/editor/src/components/inspector/widgets/ui-grid-row.tsx index 6051b48fbe4b..5350f752c166 100644 --- a/editor/src/components/inspector/widgets/ui-grid-row.tsx +++ b/editor/src/components/inspector/widgets/ui-grid-row.tsx @@ -129,30 +129,25 @@ export interface GridRowProps extends React.InputHTMLAttributes alignItems?: 'start' | 'center' | 'stretch' } -export const UIGridRow: React.FunctionComponent> = ({ - tall, - variant, - alignItems, - style, - padded, - children, - ...props -}) => ( -
- {children} -
+export const UIGridRow = React.forwardRef>( + ({ tall, variant, alignItems, style, padded, children, ...props }, ref) => ( +
+ {children} +
+ ), ) UIGridRow.displayName = 'UIGridRow' diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 91759eca0cc4..08baf6f7f10e 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -144,12 +144,12 @@ Array [ "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", - "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedFunctionComponent(UIGridRow)", + "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(UIGridRow)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", @@ -165,15 +165,15 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/span", @@ -438,15 +438,15 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/span", @@ -544,13 +544,13 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//Symbol(react.memo)(Symbol(react.forward_ref)())", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(SliderNumberControl)", - "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", @@ -608,7 +608,7 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BackgroundSubsection/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)(NumberInput)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(UIGridRow)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/span", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(Styled(div))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -648,7 +648,7 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(Styled(div))/div/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", ] @@ -798,19 +798,19 @@ Array [ "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", - "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedFunctionComponent(UIGridRow)", + "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(UIGridRow)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(Styled(span))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "//UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "//Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/div/div/Symbol(react.forward_ref)(Styled(span))/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/Symbol(react.memo)()", @@ -1094,13 +1094,13 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//Symbol(react.memo)(Symbol(react.forward_ref)())", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(SliderNumberControl)", - "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", @@ -1158,7 +1158,7 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BackgroundSubsection/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)(NumberInput)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(UIGridRow)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/span", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(Styled(div))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -1316,7 +1316,7 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FrameUpdatingLayoutControl/Symbol(react.memo)(NumberInput)", @@ -1340,22 +1340,22 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//Symbol(react.memo)(Symbol(react.forward_ref)())", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(SliderNumberControl)", - "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/UtopiaSpiedFunctionComponent(SliderControl)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/Symbol(react.memo)(NumberInput)", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)", - "/div/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)", + "/div/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(SliderControl)/UtopiaSpiedClass(ComponentEnhancer(undefined))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(SliderControl)/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedFunctionComponent(SliderControl)/Symbol(react.forward_ref)(Styled(div))/div", @@ -1394,7 +1394,7 @@ Array [ "/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", @@ -1452,7 +1452,7 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BackgroundSubsection/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)(NumberInput)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(UIGridRow)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/span", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(Styled(div))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -1566,12 +1566,12 @@ Array [ "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", - "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedFunctionComponent(UIGridRow)", + "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(UIGridRow)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", @@ -1587,15 +1587,15 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/span", @@ -1793,15 +1793,15 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/span", @@ -1859,22 +1859,22 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//Symbol(react.memo)(Symbol(react.forward_ref)())", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(SliderNumberControl)", - "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/UtopiaSpiedFunctionComponent(SliderControl)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/Symbol(react.memo)(NumberInput)", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)", - "/div/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)", + "/div/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(SliderControl)/UtopiaSpiedClass(ComponentEnhancer(undefined))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(SliderControl)/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedFunctionComponent(SliderControl)/Symbol(react.forward_ref)(Styled(div))/div", @@ -1913,7 +1913,7 @@ Array [ "/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", @@ -1971,7 +1971,7 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BackgroundSubsection/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)(NumberInput)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(UIGridRow)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/span", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(Styled(div))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -2042,15 +2042,15 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/span", @@ -2125,15 +2125,15 @@ Array [ "/null///Symbol(react.memo)(PropertyLabel)", "/null///Symbol(react.memo)()", "/null///div", - "/null///UtopiaSpiedFunctionComponent(UIGridRow)", + "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/span", @@ -2330,22 +2330,22 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//Symbol(react.memo)(Symbol(react.forward_ref)())", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(SliderNumberControl)", - "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/UtopiaSpiedFunctionComponent(SliderControl)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/Symbol(react.memo)(NumberInput)", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)", - "/div/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)", + "/div/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(SliderControl)/UtopiaSpiedClass(ComponentEnhancer(undefined))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(SliderControl)/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedFunctionComponent(SliderControl)/Symbol(react.forward_ref)(Styled(div))/div", @@ -2384,7 +2384,7 @@ Array [ "/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", @@ -2442,7 +2442,7 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BackgroundSubsection/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)(NumberInput)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(UIGridRow)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/span", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(Styled(div))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -2552,19 +2552,19 @@ Array [ "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", - "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedFunctionComponent(UIGridRow)", + "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(UIGridRow)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(Styled(span))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "//UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "//Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/div/div/Symbol(react.forward_ref)(Styled(span))/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FixedHugDropdown/Symbol(react.memo)(Symbol(react.forward_ref)())", "/FixedHugDropdown/Symbol(react.memo)(Symbol(react.forward_ref)())/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", @@ -2743,22 +2743,22 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//Symbol(react.memo)(Symbol(react.forward_ref)())", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.memo)(SliderNumberControl)", - "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/OpacityRow/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", - "/UtopiaSpiedFunctionComponent(MenuProvider)/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/div/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/UtopiaSpiedFunctionComponent(SliderControl)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/Symbol(react.memo)(NumberInput)", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)", - "/div/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/SliderNumberControl/UtopiaSpiedFunctionComponent(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)", + "/div/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/SliderNumberControl/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(SliderControl)/UtopiaSpiedClass(ComponentEnhancer(undefined))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(SliderControl)/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedFunctionComponent(SliderControl)/Symbol(react.forward_ref)(Styled(div))/div", @@ -2797,7 +2797,7 @@ Array [ "/UtopiaSpiedFunctionComponent(ContextMenu)/UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(UIGridRow)", + "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)(PropertyLabel)", @@ -2855,7 +2855,7 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BackgroundSubsection/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)()", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.memo)(NumberInput)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(UIGridRow)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/span", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/Symbol(react.forward_ref)(Styled(div))", "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/BorderSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", From de7afad5b00adb83ab7549d36db0a2be652f0f9c Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Thu, 13 Jun 2024 23:34:30 +0200 Subject: [PATCH 077/103] Short Cartouches (#5925) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** The cartouches in the navigator and the inspector don't currently have a max width and they can be overlong. **Fix:** For property and element accessors, only show the last bit. image image image **Commit Details:** - Added `shortLabel` to `getTextContentOfElement` - If the DataReferenceCartouche has a non-null shortLabel, it is used - The tooltip always shows the long label **Bonus** The PR also changes when do we hide the cartouche icon – the new ruleset only hides the cartouche icon for inline value literals such as `myProp="value"` and `
{'myValue'}
` --- .../component-section/cartouche-control.tsx | 9 +++- .../component-section/cartouche-ui.tsx | 15 ++---- .../component-section-children.tsx | 4 +- .../component-section/component-section.tsx | 5 +- .../data-reference-cartouche.tsx | 53 ++++++++++++------- .../data-selector-cartouche.tsx | 7 ++- .../navigator-condensed-entry.tsx | 1 - 7 files changed, 55 insertions(+), 39 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx index b8dc71b89fba..725643c4285f 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx @@ -2,6 +2,7 @@ /** @jsx jsx */ import React from 'react' import { jsx } from '@emotion/react' +import type { DataReferenceCartoucheContentType } from './data-reference-cartouche' import { DataCartoucheInner } from './data-reference-cartouche' import { NO_OP } from '../../../../core/shared/utils' import type { ElementPath, PropertyPath } from '../../../../core/shared/project-file-types' @@ -12,7 +13,11 @@ import type { CartoucheDataType } from './cartouche-ui' import { useColorTheme } from '../../../../uuiui' interface IdentifierExpressionCartoucheControlProps { - contents: string + contents: { + type: DataReferenceCartoucheContentType + label: string | null + shortLabel: string | null + } icon: React.ReactChild matchType: 'full' | 'partial' onOpenDataPicker: () => void @@ -42,7 +47,7 @@ export const IdentifierExpressionCartoucheControl = React.memo( return ( - {source === 'literal' ? null : ( + {source === 'inline-literal' ? null : ( {/* this div prevents the popup form putting padding into the condensed rows */} @@ -170,16 +168,20 @@ export const DataReferenceCartoucheControl = React.memo( }, ) +export type DataReferenceCartoucheContentType = 'value-literal' | 'object-literal' | 'reference' interface DataCartoucheInnerProps { onClick: (e: React.MouseEvent) => void onDoubleClick: (e: React.MouseEvent) => void selected: boolean - contentsToDisplay: { type: 'literal' | 'reference'; label: string | null } + contentsToDisplay: { + type: DataReferenceCartoucheContentType + label: string | null + shortLabel: string | null + } safeToDelete: boolean onDelete: () => void testId: string contentIsComingFromServer: boolean - hideTooltip?: boolean datatype: CartoucheDataType highlight?: CartoucheHighlight | null badge?: React.ReactNode @@ -211,8 +213,10 @@ export const DataCartoucheInner = React.forwardRef( const onDelete = safeToDelete ? onDeleteInner : undefined const source: CartoucheUIProps['source'] = - contentsToDisplay.type === 'literal' - ? 'literal' + contentsToDisplay.type === 'value-literal' + ? 'inline-literal' + : contentsToDisplay.type === 'object-literal' + ? 'internal' : contentIsComingFromServer ? 'external' : 'internal' @@ -226,13 +230,13 @@ export const DataCartoucheInner = React.forwardRef( selected={selected} highlight={highlight} testId={testId} - tooltip={!props.hideTooltip ? contentsToDisplay.label ?? 'DATA' : null} + tooltip={contentsToDisplay.label ?? contentsToDisplay.shortLabel ?? 'DATA'} role='selection' source={source} ref={ref} badge={props.badge} > - {contentsToDisplay.label ?? 'DATA'} + {contentsToDisplay.shortLabel ?? contentsToDisplay.label ?? 'DATA'} ) }, @@ -241,46 +245,55 @@ export const DataCartoucheInner = React.forwardRef( export function getTextContentOfElement( element: JSXElementChild, metadata: ElementInstanceMetadata | null, -): { type: 'literal' | 'reference'; label: string | null } { +): { + type: DataReferenceCartoucheContentType + label: string | null + shortLabel: string | null +} { switch (element.type) { case 'ATTRIBUTE_VALUE': - return { type: 'literal', label: `${JSON.stringify(element.value)}` } + return { type: 'value-literal', label: `${JSON.stringify(element.value)}`, shortLabel: null } case 'JSX_TEXT_BLOCK': - return { type: 'literal', label: element.text.trim() } + return { type: 'value-literal', label: element.text.trim(), shortLabel: null } case 'JS_IDENTIFIER': - return { type: 'reference', label: element.name.trim() } + return { type: 'reference', label: element.name.trim(), shortLabel: null } case 'JS_ELEMENT_ACCESS': return { type: 'reference', label: `${getTextContentOfElement(element.onValue, null).label}[${ getTextContentOfElement(element.element, null).label }]`, + shortLabel: `${TruncationPrefix}${getTextContentOfElement(element.element, null).label}`, } case 'JS_PROPERTY_ACCESS': return { type: 'reference', label: `${getTextContentOfElement(element.onValue, null).label}.${element.property}`, + shortLabel: `${TruncationPrefix}${element.property}`, } case 'ATTRIBUTE_FUNCTION_CALL': - return { type: 'reference', label: `${element.functionName}(...` } + return { type: 'reference', label: `${element.functionName}(...`, shortLabel: null } case 'JSX_ELEMENT': return { - type: 'literal', + type: 'object-literal', label: metadata?.textContent ?? `${getJSXElementNameLastPart(element.name)}`, + shortLabel: null, } case 'ATTRIBUTE_NESTED_ARRAY': - return { type: 'literal', label: '[...]' } + return { type: 'object-literal', label: '[...]', shortLabel: null } case 'ATTRIBUTE_NESTED_OBJECT': - return { type: 'literal', label: '{...}' } + return { type: 'object-literal', label: '{...}', shortLabel: null } case 'JSX_MAP_EXPRESSION': - return { type: 'literal', label: 'List' } + return { type: 'object-literal', label: 'List', shortLabel: null } case 'JSX_CONDITIONAL_EXPRESSION': - return { type: 'literal', label: 'Conditional' } + return { type: 'object-literal', label: 'Conditional', shortLabel: null } case 'ATTRIBUTE_OTHER_JAVASCRIPT': - return { type: 'literal', label: element.originalJavascript } + return { type: 'object-literal', label: element.originalJavascript, shortLabel: null } case 'JSX_FRAGMENT': - return { type: 'literal', label: 'Fragment' } + return { type: 'object-literal', label: 'Fragment', shortLabel: null } default: assertNever(element) } } + +const TruncationPrefix = `…` diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx index e3b82e694d80..78ecb262cf3b 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -26,6 +26,7 @@ export const DataPickerCartouche = React.memo( return ( { @@ -77,7 +80,7 @@ export function useVariableDataSource(variable: DataPickerOption | null) { return 'external' case 'literal-attribute': case 'literal-assignment': - return 'literal' + return 'literal-assignment' case 'component-prop': case 'element-at-scope': case 'failed': diff --git a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx index 16ba8ea481cc..60f9e0afce4e 100644 --- a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx @@ -426,7 +426,6 @@ const CondensedEntryItemContent = React.memo( highlight={ props.rowRootSelected ? 'strong' : props.wholeRowInsideSelection ? 'subtle' : null } - hideTooltip={true} />, )}
From 8b3a8835ef27971c91399cf40a450d0a838964c1 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:42:04 +0200 Subject: [PATCH 078/103] Move arrow indicator under mouse (#5934) **Problem:** The arrow indicator for elements outside of the visible area could become more useful if moved under the mouse cursor rather than being in the canvas toolbar. **Fix:** 1. Move the indicator under the mouse cursor 2. Remove the canvas toolbar button https://github.com/concrete-utopia/utopia/assets/1081051/b40f96ea-0038-46a6-9f2c-02054576ee92 At some point we could revisit this and reinstate the toolbar button to scroll to the element, but since this is experimental territory anyways we can evaluate pros and cons of the two approaches and maybe come up with a hybrid. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5868 --- ...=> arrow-out-of-bounds-white-12x12@2x.png} | Bin .../elements-outside-visible-area-hooks.tsx | 37 +----- ...nts-outside-visible-area.spec.browser2.tsx | 62 +-------- .../components/canvas/design-panel-root.tsx | 2 + .../src/components/editor/canvas-toolbar.tsx | 2 - ...lements-outside-visible-area-indicator.tsx | 120 ++++++------------ ...performance-regression-tests.spec.tsx.snap | 26 +--- .../performance-regression-tests.spec.tsx | 4 +- 8 files changed, 60 insertions(+), 193 deletions(-) rename editor/resources/editor/icons/light/semantic/{arrowOutOfBounds@2x.png => arrow-out-of-bounds-white-12x12@2x.png} (100%) diff --git a/editor/resources/editor/icons/light/semantic/arrowOutOfBounds@2x.png b/editor/resources/editor/icons/light/semantic/arrow-out-of-bounds-white-12x12@2x.png similarity index 100% rename from editor/resources/editor/icons/light/semantic/arrowOutOfBounds@2x.png rename to editor/resources/editor/icons/light/semantic/arrow-out-of-bounds-white-12x12@2x.png diff --git a/editor/src/components/canvas/controls/elements-outside-visible-area-hooks.tsx b/editor/src/components/canvas/controls/elements-outside-visible-area-hooks.tsx index 80dae0839c5c..b256b4cef2e6 100644 --- a/editor/src/components/canvas/controls/elements-outside-visible-area-hooks.tsx +++ b/editor/src/components/canvas/controls/elements-outside-visible-area-hooks.tsx @@ -1,6 +1,6 @@ import React from 'react' import { MetadataUtils } from '../../../core/model/element-metadata-utils' -import { mapDropNulls, uniqBy } from '../../../core/shared/array-utils' +import { mapDropNulls } from '../../../core/shared/array-utils' import * as EP from '../../../core/shared/element-path' import type { CanvasRectangle, WindowPoint, WindowRectangle } from '../../../core/shared/math-utils' import { @@ -8,7 +8,6 @@ import { getRectCenter, isFiniteRectangle, rectangleIntersection, - scaleRect, windowRectangle, } from '../../../core/shared/math-utils' import type { ElementPath } from '../../../core/shared/project-file-types' @@ -23,10 +22,7 @@ type ElementOutsideVisibleArea = { } export type ElementOutsideVisibleAreaIndicator = { - elements: number - rect: CanvasRectangle position: WindowPoint - selected: boolean } export function useElementsOutsideVisibleArea(): ElementOutsideVisibleAreaIndicator | null { @@ -38,12 +34,6 @@ export function useElementsOutsideVisibleArea(): ElementOutsideVisibleAreaIndica 'useElementsOutsideVisibleArea selectedViews', ) - const highlightedViews = useEditorState( - Substores.highlightedHoveredViews, - (store) => store.editor.highlightedViews, - 'useElementsOutsideVisibleArea highlightedViews', - ) - const storeRef = useRefEditorState((store) => ({ jsxMetadata: store.editor.jsxMetadata, })) @@ -59,13 +49,9 @@ export function useElementsOutsideVisibleArea(): ElementOutsideVisibleAreaIndica 'useElementsOutsideVisibleArea canvasOffset', ) - const elements = React.useMemo(() => { - return uniqBy([...selectedViews, ...highlightedViews], EP.pathsEqual) - }, [selectedViews, highlightedViews]) - const framesByPathString = React.useMemo(() => { const frames: { [key: string]: CanvasRectangle } = {} - for (const path of elements) { + for (const path of selectedViews) { const metadata = MetadataUtils.findElementByElementPath(storeRef.current.jsxMetadata, path) if ( metadata != null && @@ -76,7 +62,7 @@ export function useElementsOutsideVisibleArea(): ElementOutsideVisibleAreaIndica } } return frames - }, [storeRef, elements]) + }, [storeRef, selectedViews]) const scaledCanvasArea = React.useMemo(() => { if (canvasBounds == null) { @@ -118,8 +104,8 @@ export function useElementsOutsideVisibleArea(): ElementOutsideVisibleAreaIndica path: path, rect: elementRect, } - }, elements) - }, [elements, canvasOffset, canvasScale, scaledCanvasArea, framesByPathString]) + }, selectedViews) + }, [selectedViews, canvasOffset, canvasScale, scaledCanvasArea, framesByPathString]) return React.useMemo((): ElementOutsideVisibleAreaIndicator | null => { if (elementsOutsideVisibleArea.length === 0) { @@ -129,19 +115,10 @@ export function useElementsOutsideVisibleArea(): ElementOutsideVisibleAreaIndica if (windowRect == null) { return null } - const canvasRect = boundingRectangleArray( - elementsOutsideVisibleArea.map((a) => framesByPathString[EP.toString(a.path)]), - ) - if (canvasRect == null) { - return null - } return { - elements: elementsOutsideVisibleArea.length, - rect: canvasRect, - position: getRectCenter(scaleRect(windowRect, canvasScale)), - selected: elementsOutsideVisibleArea.some((e) => EP.containsPath(e.path, selectedViews)), + position: getRectCenter(windowRect), } - }, [elementsOutsideVisibleArea, framesByPathString, selectedViews, canvasScale]) + }, [elementsOutsideVisibleArea]) } export function getIndicatorAngleToTarget(from: WindowPoint, to: WindowPoint): number { diff --git a/editor/src/components/canvas/controls/elements-outside-visible-area.spec.browser2.tsx b/editor/src/components/canvas/controls/elements-outside-visible-area.spec.browser2.tsx index 16f723229c05..62fe212b12a0 100644 --- a/editor/src/components/canvas/controls/elements-outside-visible-area.spec.browser2.tsx +++ b/editor/src/components/canvas/controls/elements-outside-visible-area.spec.browser2.tsx @@ -1,13 +1,9 @@ import { act, screen } from '@testing-library/react' -import { MetadataUtils } from '../../../core/model/element-metadata-utils' import * as EP from '../../../core/shared/element-path' -import { getRectCenter, isFiniteRectangle, windowRectangle } from '../../../core/shared/math-utils' import type { ElementPath } from '../../../core/shared/project-file-types' import { selectComponents } from '../../editor/actions/meta-actions' import { ToolbarIndicatorElementsOutsideVisibleAreaId } from '../../editor/elements-outside-visible-area-indicator' -import { DefaultNavigatorWidth } from '../../editor/store/editor-state' -import { canvasPointToWindowPoint } from '../dom-lookup' -import { keyDown, mouseClickAtPoint, mouseDragFromPointToPoint } from '../event-helpers.test-utils' +import { keyDown, mouseDragFromPointToPoint } from '../event-helpers.test-utils' import type { EditorRenderResult } from '../ui-jsx.test-utils' import { makeTestProjectCodeWithSnippet, renderTestEditorWithCode } from '../ui-jsx.test-utils' import { CanvasControlsContainerID } from './new-canvas-controls' @@ -52,7 +48,7 @@ const farAway = 99999999 // px describe('elements outside visible area', () => { describe('single element', () => { - it('shows the indicator on the toolbar', async () => { + it('shows the indicator', async () => { const renderResult = await renderTestEditorWithCode( makeTestProjectCodeWithSnippet(`
{ expect(screen.queryByTestId(ToolbarIndicatorElementsOutsideVisibleAreaId)).not.toBe(null) }) }) - describe('scroll', () => { - it('brings the element to the center of the canvas when clicking its indicator', async () => { - const renderResult = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(` -
- `), - 'await-first-dom-report', - ) - - const targetPath = EP.fromString('utopia-storyboard-uid/scene-aaa/app-entity:foo') - - await selectAndPan(renderResult, [targetPath], -farAway, 0) - - const indicator = await screen.findByTestId(ToolbarIndicatorElementsOutsideVisibleAreaId) - const indicatorRect = indicator.getBoundingClientRect() - - await mouseClickAtPoint(indicator, { x: indicatorRect.x + 2, y: indicatorRect.y + 2 }) - - const canvasRect = renderResult.renderedDOM.getByTestId('canvas-root').getBoundingClientRect() - const elementFrame = MetadataUtils.getFrameInCanvasCoords( - targetPath, - renderResult.getEditorState().editor.jsxMetadata, - ) - if (elementFrame == null || !isFiniteRectangle(elementFrame)) { - throw new Error('element frame not found') - } - - const pointOnWindow = canvasPointToWindowPoint( - elementFrame, - renderResult.getEditorState().editor.canvas.scale, - renderResult.getEditorState().editor.canvas.roundedCanvasOffset, - ) - - const canvasCenter = getRectCenter( - windowRectangle({ - x: canvasRect.x + DefaultNavigatorWidth, - y: canvasRect.y, - width: canvasRect.width - DefaultNavigatorWidth - 255, // 255 being the default inspector width (inspectorSmallWidth) - height: canvasRect.height, - }), - ) - expect(pointOnWindow.x).toBeLessThan(canvasCenter.x) - expect(pointOnWindow.x + elementFrame.width).toBeGreaterThan(canvasCenter.x) - expect(pointOnWindow.y).toBeLessThan(canvasCenter.y) - expect(pointOnWindow.y + elementFrame.height).toBeGreaterThan(canvasCenter.y) - }) - }) }) diff --git a/editor/src/components/canvas/design-panel-root.tsx b/editor/src/components/canvas/design-panel-root.tsx index a47489e46279..7d007c4b982e 100644 --- a/editor/src/components/canvas/design-panel-root.tsx +++ b/editor/src/components/canvas/design-panel-root.tsx @@ -34,6 +34,7 @@ import { CommentsPane } from '../inspector/comments-pane' import { EditorModes, isCommentMode } from '../editor/editor-modes' import { useAllowedToEditProject } from '../editor/store/collaborative-editing' import { useCanComment } from '../../core/commenting/comment-hooks' +import { ElementsOutsideVisibleAreaIndicator } from '../editor/elements-outside-visible-area-indicator' function isCodeEditorEnabled(): boolean { if (typeof window !== 'undefined') { @@ -82,6 +83,7 @@ const DesignPanelRootInner = React.memo(() => { }} > + } diff --git a/editor/src/components/editor/canvas-toolbar.tsx b/editor/src/components/editor/canvas-toolbar.tsx index f4f52c786d1f..fbac92139647 100644 --- a/editor/src/components/editor/canvas-toolbar.tsx +++ b/editor/src/components/editor/canvas-toolbar.tsx @@ -37,7 +37,6 @@ import { unless, when } from '../../utils/react-conditionals' import { StrategyIndicator } from '../canvas/controls/select-mode/strategy-indicator' import { stopPropagation } from '../inspector/common/inspector-utils' import { useWrapInDiv } from './wrap-in-callbacks' -import { ElementsOutsideVisibleAreaIndicator } from './elements-outside-visible-area-indicator' import { RemixNavigationBar } from './remix-navigation-bar' import { type InsertableComponent, @@ -449,7 +448,6 @@ export const CanvasToolbar = React.memo(() => { size={16} /> - {unless(isMyProject, )}
{/* Edit Mode submenus */} diff --git a/editor/src/components/editor/elements-outside-visible-area-indicator.tsx b/editor/src/components/editor/elements-outside-visible-area-indicator.tsx index 12f32d09a8b8..14a05c2c0ab2 100644 --- a/editor/src/components/editor/elements-outside-visible-area-indicator.tsx +++ b/editor/src/components/editor/elements-outside-visible-area-indicator.tsx @@ -1,103 +1,65 @@ import React from 'react' -import type { WindowPoint } from '../../core/shared/math-utils' import { windowPoint } from '../../core/shared/math-utils' -import { SquareButton, Tooltip, useColorTheme } from '../../uuiui' import type { ElementOutsideVisibleAreaIndicator } from '../canvas/controls/elements-outside-visible-area-hooks' import { getIndicatorAngleToTarget, useElementsOutsideVisibleArea, } from '../canvas/controls/elements-outside-visible-area-hooks' -import { scrollToPosition } from './actions/action-creators' -import { useDispatch } from './store/dispatch-context' -import { Substores, useEditorState, useRefEditorState } from './store/store-hook' -import { isFollowMode } from './editor-modes' +import { Icn } from '../../uuiui' export const ToolbarIndicatorElementsOutsideVisibleAreaId = 'indicator-elements-outside-visible-area' export const ElementsOutsideVisibleAreaIndicator = React.memo(() => { - const colorTheme = useColorTheme() - const dispatch = useDispatch() - const target = useElementsOutsideVisibleArea() - const mode = useEditorState( - Substores.restOfEditor, - (store) => store.editor.mode, - 'ElementsOutsideVisibleAreaIndicator mode', - ) - - const scrollTo = React.useCallback(() => { - if (target != null && !isFollowMode(mode)) { - dispatch([scrollToPosition(target.rect, 'to-center')]) - } - }, [dispatch, target, mode]) - - if (target == null) { - return null - } - - return ( - 1 ? 's' : ''}`} placement='bottom'> - - - - - ) + return }) ElementsOutsideVisibleAreaIndicator.displayName = 'ElementsOutsideVisibleAreaIndicator' -const IndicatorArrow = React.memo(({ target }: { target: ElementOutsideVisibleAreaIndicator }) => { - const ref = React.useRef(null) - const canvasScale = useRefEditorState((store) => store.editor.canvas.scale) +const IndicatorArrow = React.memo( + ({ target }: { target: ElementOutsideVisibleAreaIndicator | null }) => { + const [mouse, setMouse] = React.useState(windowPoint({ x: 0, y: 0 })) + + const angle = React.useMemo(() => { + if (target == null) { + return null + } + return getIndicatorAngleToTarget(windowPoint({ x: mouse.x, y: mouse.y }), target.position) + }, [mouse, target]) - const [angle, setAngle] = React.useState(0) + React.useEffect(() => { + function storeMousePosition(e: MouseEvent) { + setMouse(windowPoint({ x: e.clientX, y: e.clientY })) + } + window.addEventListener('mousemove', storeMousePosition) + window.addEventListener('wheel', storeMousePosition) + return function () { + window.removeEventListener('mousemove', storeMousePosition) + window.removeEventListener('wheel', storeMousePosition) + } + }, []) - React.useEffect(() => { - // useEffect to make sure the origin point is calculated after the arrow has been rendered - if (ref.current != null) { - const rect = ref.current.getBoundingClientRect() - const newAngle = getIndicatorAngleToTarget( - getIndicatorOriginPoint(rect, canvasScale.current), - target.position, - ) - setAngle(newAngle) + if (target == null) { + return null } - }, [canvasScale, target]) - return ( -
- ← -
- ) -}) + return ( +
+ +
+ ) + }, +) IndicatorArrow.displayName = 'IndicatorArrow' - -function getIndicatorOriginPoint(rect: DOMRect, canvasScale: number): WindowPoint { - return windowPoint({ - x: (rect.x + rect.width / 2) * canvasScale, - y: (rect.y + rect.height / 2) * canvasScale, - }) -} diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 08baf6f7f10e..78a2580573e8 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -87,6 +87,9 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div/ElementsOutsideVisibleAreaIndicator/Symbol(react.memo)(IndicatorArrow)", + "/div/ElementsOutsideVisibleAreaIndicator/IndicatorArrow/Symbol(react.memo)(Icon)", + "/div/ElementsOutsideVisibleAreaIndicator/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", "/div/div/NavigatorComponent/Symbol(react.memo)()", "/div/div/NavigatorComponent/Symbol(react.memo)(NavigatorDragLayer)", "/div/div/NavigatorComponent/UtopiaSpiedClass(AutoSizer)", @@ -424,15 +427,6 @@ Array [ "/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/Symbol(react.forward_ref)(Styled(div))/div:data-testid='section-header-Advanced'", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", - "/div/div/ElementsOutsideVisibleAreaIndicator/Symbol(react.memo)(IndicatorArrow)", - "/div/div/ElementsOutsideVisibleAreaIndicator/Symbol(react.forward_ref)(Styled(div))", - "/div/div/ElementsOutsideVisibleAreaIndicator/UtopiaSpiedClass(Tooltip)", - "/div/ElementsOutsideVisibleAreaIndicator/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/ElementsOutsideVisibleAreaIndicator/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", - "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", - "/Symbol(react.forward_ref)(Styled(div))/div/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", "/null///Symbol(react.memo)(PropertyLabel)", @@ -650,7 +644,6 @@ Array [ "/null///div", "/null///Symbol(react.forward_ref)(UIGridRow)", "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", - "/Symbol(react.forward_ref)(Styled(div))/div/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", ] `; @@ -741,6 +734,9 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.memo)()//Symbol(react.memo)()", "/Symbol(react.memo)()///UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", + "/UtopiaSpiedFunctionComponent(SimpleFlexColumn)/div/ElementsOutsideVisibleAreaIndicator/Symbol(react.memo)(IndicatorArrow)", + "/div/ElementsOutsideVisibleAreaIndicator/IndicatorArrow/Symbol(react.memo)(Icon)", + "/div/ElementsOutsideVisibleAreaIndicator/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", "/div/div/NavigatorComponent/Symbol(react.memo)()", "/div/div/NavigatorComponent/Symbol(react.memo)(NavigatorDragLayer)", "/div/div/NavigatorComponent/UtopiaSpiedClass(AutoSizer)", @@ -1024,15 +1020,6 @@ Array [ "/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/Symbol(react.forward_ref)(Styled(div))/div:data-testid='section-header-Advanced'", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", - "/div/div/ElementsOutsideVisibleAreaIndicator/Symbol(react.memo)(IndicatorArrow)", - "/div/div/ElementsOutsideVisibleAreaIndicator/Symbol(react.forward_ref)(Styled(div))", - "/div/div/ElementsOutsideVisibleAreaIndicator/UtopiaSpiedClass(Tooltip)", - "/div/ElementsOutsideVisibleAreaIndicator/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/ElementsOutsideVisibleAreaIndicator/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", - "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", - "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(Styled(div))/div", - "/Symbol(react.forward_ref)(Styled(div))/div/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FrameUpdatingLayoutControl/Symbol(react.memo)(NumberInput)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FrameUpdatingLayoutControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/FrameUpdatingLayoutControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", @@ -1187,7 +1174,6 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/TextShadowSubsection/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.provider)///Symbol(react.memo)(Inspector)", "/Symbol(react.provider)///Symbol(react.memo)()", - "/Symbol(react.forward_ref)(Styled(div))/div/IndicatorArrow/div:data-testid='indicator-elements-outside-visible-area'", ] `; diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index e0a314bb2ec1..d6a02f3dbd66 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -183,7 +183,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`532`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`525`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`649`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`642`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From a4ea2ae3f4a3ef7dac78da4c7b2640268cce5148 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:17:45 +0200 Subject: [PATCH 079/103] Fix/cartouche map counter (#5920) This PR makes sure the cartouche is showing the array length badge in the navigator, data picker, and the List Section's List Source Picker. This PR also makes it so that the number is only pink when there is an active override in the navigator --- .../layout-section/list-source-cartouche.tsx | 266 +++++++++--------- .../navigator/navigator-item/map-counter.tsx | 12 +- .../navigator-item/navigator-item.tsx | 1 - .../navigator/navigator-map.spec.browser2.tsx | 13 +- 4 files changed, 148 insertions(+), 144 deletions(-) diff --git a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx index 4a837aefe5f8..dcbc2875114d 100644 --- a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx @@ -32,7 +32,6 @@ interface MapListSourceCartoucheProps { target: ElementPath selected: boolean openOn: 'single-click' | 'double-click' - countChildren?: boolean } export const MapListSourceCartoucheNavigator = React.memo((props: MapListSourceCartoucheProps) => { @@ -45,7 +44,7 @@ export const MapListSourceCartoucheNavigator = React.memo((props: MapListSourceC minWidth: 0, }} > - +
) }) @@ -54,143 +53,144 @@ MapListSourceCartoucheNavigator.displayName = 'MapListSourceCartoucheNavigator' export const MapListSourceCartoucheInspector = React.memo((props: MapListSourceCartoucheProps) => { return ( - + ) }) MapListSourceCartoucheInspector.displayName = 'MapListSourceCartoucheInspector' -const MapListSourceCartoucheInner = React.memo((props: MapListSourceCartoucheProps) => { - const { target, openOn } = props - - const originalMapExpression = useEditorState( - Substores.metadata, - (store) => mapExpressionValueToMapSelector(store, [target]), - 'ConditionalSection condition expression', - ) - - const metadataForElement = useEditorState( - Substores.metadata, - (store) => MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, target), - 'ConditionalSection metadata', - ) - - const dispatch = useDispatch() - - const onPickMappedElement = React.useCallback( - (expression: JSExpressionOtherJavaScript) => { - dispatch([ - replaceElementInScope(target, { - type: 'update-map-expression', - valueToMap: expression, - }), - ]) - }, - [dispatch, target], - ) - - const [preferredAllState] = useAtom(DataPickerPreferredAllAtom) - - const variableNamesInScope = useVariablesInScopeForSelectedElement( - target, - null, - preferredAllState, - ) - - const pathToMappedExpression = React.useMemo( - () => - originalMapExpression === 'multiselect' || originalMapExpression === 'not-a-mapexpression' - ? null - : jsxElementChildToValuePath(originalMapExpression.valueToMap), - [originalMapExpression], - ) - - const { popupIsOpen, DataPickerComponent, setReferenceElement, openPopup } = useDataPickerButton( - variableNamesInScope, - onPickMappedElement, - pathToMappedExpression, - target, - ) - - const onClick = React.useCallback(() => { - if (openOn === 'single-click') { - openPopup() - } - }, [openOn, openPopup]) - - const onDoubleClick = React.useCallback(() => { - if (openOn === 'double-click') { - openPopup() - } - }, [openOn, openPopup]) - - const isDataComingFromHookResult = useEditorState( - Substores.projectContentsAndMetadata, - (store) => { - if ( - originalMapExpression === 'multiselect' || - originalMapExpression === 'not-a-mapexpression' - ) { - return false - } else { - const traceDataResult = traceDataFromElement( - originalMapExpression.valueToMap, - target, - store.editor.jsxMetadata, - store.editor.projectContents, - dataPathSuccess([]), - ) - return traceDataResult.type === 'hook-result' +const MapListSourceCartoucheInner = React.memo( + (props: MapListSourceCartoucheProps & { source: 'inspector' | 'navigator' }) => { + const { target, openOn } = props + + const originalMapExpression = useEditorState( + Substores.metadata, + (store) => mapExpressionValueToMapSelector(store, [target]), + 'ConditionalSection condition expression', + ) + + const metadataForElement = useEditorState( + Substores.metadata, + (store) => MetadataUtils.findElementByElementPath(store.editor.jsxMetadata, target), + 'ConditionalSection metadata', + ) + + const dispatch = useDispatch() + + const onPickMappedElement = React.useCallback( + (expression: JSExpressionOtherJavaScript) => { + dispatch([ + replaceElementInScope(target, { + type: 'update-map-expression', + valueToMap: expression, + }), + ]) + }, + [dispatch, target], + ) + + const [preferredAllState] = useAtom(DataPickerPreferredAllAtom) + + const variableNamesInScope = useVariablesInScopeForSelectedElement( + target, + null, + preferredAllState, + ) + + const pathToMappedExpression = React.useMemo( + () => + originalMapExpression === 'multiselect' || originalMapExpression === 'not-a-mapexpression' + ? null + : jsxElementChildToValuePath(originalMapExpression.valueToMap), + [originalMapExpression], + ) + + const { popupIsOpen, DataPickerComponent, setReferenceElement, openPopup } = + useDataPickerButton(variableNamesInScope, onPickMappedElement, pathToMappedExpression, target) + + const onClick = React.useCallback(() => { + if (openOn === 'single-click') { + openPopup() } - }, - 'ListSection isDataComingFromHookResult', - ) + }, [openOn, openPopup]) - const cartoucheDataType: CartoucheDataType = useEditorState( - Substores.projectContentsAndMetadataAndVariablesInScope, - (store) => { - if ( - originalMapExpression === 'multiselect' || - originalMapExpression === 'not-a-mapexpression' - ) { - return 'unknown' + const onDoubleClick = React.useCallback(() => { + if (openOn === 'double-click') { + openPopup() } - return getCartoucheDataTypeForExpression( - target, - originalMapExpression.valueToMap, - store.editor.variablesInScope, - ) - }, - 'MapListSourceCartouche cartoucheDataType', - ) - - if (originalMapExpression === 'multiselect' || originalMapExpression === 'not-a-mapexpression') { - return null - } - - const contentsToDisplay = getTextContentOfElement( - originalMapExpression.valueToMap, - metadataForElement, - ) - - return ( - - {popupIsOpen ? DataPickerComponent : null} - : null + }, [openOn, openPopup]) + + const isDataComingFromHookResult = useEditorState( + Substores.projectContentsAndMetadata, + (store) => { + if ( + originalMapExpression === 'multiselect' || + originalMapExpression === 'not-a-mapexpression' + ) { + return false + } else { + const traceDataResult = traceDataFromElement( + originalMapExpression.valueToMap, + target, + store.editor.jsxMetadata, + store.editor.projectContents, + dataPathSuccess([]), + ) + return traceDataResult.type === 'hook-result' } - /> - - ) -}) + }, + 'ListSection isDataComingFromHookResult', + ) + + const cartoucheDataType: CartoucheDataType = useEditorState( + Substores.projectContentsAndMetadataAndVariablesInScope, + (store) => { + if ( + originalMapExpression === 'multiselect' || + originalMapExpression === 'not-a-mapexpression' + ) { + return 'unknown' + } + return getCartoucheDataTypeForExpression( + target, + originalMapExpression.valueToMap, + store.editor.variablesInScope, + ) + }, + 'MapListSourceCartouche cartoucheDataType', + ) + + if ( + originalMapExpression === 'multiselect' || + originalMapExpression === 'not-a-mapexpression' + ) { + return null + } + + const contentsToDisplay = getTextContentOfElement( + originalMapExpression.valueToMap, + metadataForElement, + ) + + return ( + + {popupIsOpen ? DataPickerComponent : null} + + } + /> + + ) + }, +) diff --git a/editor/src/components/navigator/navigator-item/map-counter.tsx b/editor/src/components/navigator/navigator-item/map-counter.tsx index 510b846c261b..66e50c9c7dd3 100644 --- a/editor/src/components/navigator/navigator-item/map-counter.tsx +++ b/editor/src/components/navigator/navigator-item/map-counter.tsx @@ -17,8 +17,11 @@ import { colorTheme } from '../../../uuiui' export const MapCounterTestIdPrefix = 'map-counter-' -export function getMapCounterTestId(path: ElementPath): string { - return `${MapCounterTestIdPrefix}${EP.toString(path)}` +export function getMapCounterTestId( + path: ElementPath, + source: 'navigator' | 'inspector' | 'data-picker', +): string { + return `${MapCounterTestIdPrefix}${EP.toString(path)}-${source}` } type OverrideStatus = 'no-override' | 'overridden' | 'override-failed' @@ -27,6 +30,7 @@ type SelectedStatus = true | false interface MapCounterProps { elementPath: ElementPath selected: boolean + source: 'navigator' | 'inspector' | 'data-picker' } export const MapCounter = React.memo((props: MapCounterProps) => { @@ -101,7 +105,7 @@ export const MapCounter = React.memo((props: MapCounterProps) => { return ( { target={props.navigatorEntry.elementPath} selected={props.selected} openOn='double-click' - countChildren={true} /> { ) const mapPath = EP.fromString('utopia-storyboard-uid/scene-aaa/containing-div/map') - const counterTestId = getMapCounterTestId(mapPath) + const counterTestId = getMapCounterTestId(mapPath, 'navigator') const counter = await renderResult.renderedDOM.findByTestId(counterTestId) expectRegularCounterWithCount(counter, arr.length) @@ -227,7 +228,7 @@ describe('maps in the navigator', () => { mapParent, )[0] - const counterTestId = getMapCounterTestId(mapElement.elementPath) + const counterTestId = getMapCounterTestId(mapElement.elementPath, 'navigator') const counter = await renderResult.renderedDOM.findByTestId(counterTestId) expectOverriddenCounterWithCount(counter, overrideCount, overrideSuccess) @@ -246,7 +247,7 @@ describe('maps in the navigator', () => { ) const mapPath = EP.fromString('utopia-storyboard-uid/scene-aaa/containing-div/map') - const counterTestId = getMapCounterTestId(mapPath) + const counterTestId = getMapCounterTestId(mapPath, 'navigator') let counter = await renderResult.renderedDOM.findByTestId(counterTestId) const counterBounds = counter.getBoundingClientRect() const counterCentre = { @@ -279,7 +280,7 @@ describe('maps in the navigator', () => { ) const mapPath = EP.fromString('utopia-storyboard-uid/scene-aaa/containing-div/map') - const counterTestId = getMapCounterTestId(mapPath) + const counterTestId = getMapCounterTestId(mapPath, 'navigator') let counter = await renderResult.renderedDOM.findByTestId(counterTestId) const counterBounds = counter.getBoundingClientRect() const counterCentre = { @@ -312,7 +313,7 @@ describe('maps in the navigator', () => { ) const mapPath = EP.fromString('utopia-storyboard-uid/scene-aaa/containing-div/map') - const counterTestId = getMapCounterTestId(mapPath) + const counterTestId = getMapCounterTestId(mapPath, 'navigator') let counter = await renderResult.renderedDOM.findByTestId(counterTestId) const counterBounds = counter.getBoundingClientRect() const counterCentre = { @@ -341,7 +342,7 @@ describe('maps in the navigator', () => { ) const mapPath = EP.fromString('utopia-storyboard-uid/scene-aaa/containing-div/map') - const counterTestId = getMapCounterTestId(mapPath) + const counterTestId = getMapCounterTestId(mapPath, 'navigator') let counter = await renderResult.renderedDOM.findByTestId(counterTestId) const counterBounds = counter.getBoundingClientRect() const counterCentre = { From 6fbfc0e032f3c744332ea8a1234be059300693f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Fri, 14 Jun 2024 13:09:39 +0200 Subject: [PATCH 080/103] Make the canvas plus button respect the insertion index position (#5931) ## Problem The on-canvas plus button doesn't respect the insertion index position ## Fix Pass the index position to the relevant insertion handlers ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode https://github.com/concrete-utopia/utopia/issues/5923 --- .../component-picker-context-menu.tsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx index 30a476bf7325..bbd7068b7067 100644 --- a/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx +++ b/editor/src/components/navigator/navigator-item/component-picker-context-menu.tsx @@ -582,12 +582,26 @@ export function insertComponentPickerItem( } if (!isConditionalTarget(insertionTarget)) { - return [insertJSXElement(fixedElement, firstTarget, toInsert.importsToAdd ?? undefined)] + return [ + insertJSXElement( + fixedElement, + firstTarget, + toInsert.importsToAdd ?? undefined, + insertionTarget.indexPosition, + ), + ] } } if (isInsertAsChildTarget(insertionTarget)) { - return [insertInsertable(childInsertionPath(firstTarget), toInsert, 'do-not-add', null)] + return [ + insertInsertable( + childInsertionPath(firstTarget), + toInsert, + 'do-not-add', + insertionTarget.indexPosition ?? null, + ), + ] } if (isConditionalTarget(insertionTarget)) { From 31bc11458098f3711d7af271ea91463ce68ad218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Fri, 14 Jun 2024 13:17:07 +0200 Subject: [PATCH 081/103] Data picker search design touchup (#5940) ## Description Improves the design of the data picker: - make the search field span the whole length of its outline - use the right colored arrow icon in the search result cartouche - turn the search results view into two side-by-side columns that eact scroll horizontally (see https://screenshot.click/14-12-847sp-icx9w.mp4) ### Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/cartouche-ui.tsx | 1 + .../data-selector-cartouche.tsx | 1 + .../component-section/data-selector-modal.tsx | 1 + .../data-selector-search.tsx | 121 +++++++++++------- editor/src/uuiui/icons.tsx | 7 + 5 files changed, 84 insertions(+), 47 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 3226457d2dde..22546f4984d9 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -145,6 +145,7 @@ export const CartoucheUI = React.forwardRef( ...(role !== 'information' ? UtopiaStyles.fontStyles.monospaced : {}), display: 'flex', flexDirection: 'row', + alignItems: 'center', }} > {children} diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx index 78ecb262cf3b..3ec77f7f3071 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -15,6 +15,7 @@ interface DataPickerCartoucheProps { data: DataPickerOption selected: boolean forcedRole?: CartoucheUIProps['role'] + forcedSource?: CartoucheUIProps['source'] onClick?: CartoucheUIProps['onClick'] } diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 03bd0abf709e..7222beba3b38 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -255,6 +255,7 @@ export const DataSelectorModal = React.memo( outline: 'none', border: 'none', paddingRight: 14, + flex: 1, }} /> {when( diff --git a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx index 1e627b2c40b6..c8e8b7256ff6 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx @@ -2,10 +2,13 @@ import throttle from 'lodash.throttle' import React from 'react' import { memoize } from '../../../../core/shared/memoize' import { assertNever } from '../../../../core/shared/utils' -import { FlexRow, Icons, UtopiaStyles } from '../../../../uuiui' +import { FlexColumn, FlexRow, Icons, SmallerIcons, UtopiaStyles } from '../../../../uuiui' import { type DataPickerOption, type ObjectPath } from './data-picker-utils' -import { DataPickerCartouche } from './data-selector-cartouche' +import { DataPickerCartouche, useVariableDataSource } from './data-selector-cartouche' import { when } from '../../../../utils/react-conditionals' +import { AllHtmlEntities } from 'html-entities' + +const htmlEntities = new AllHtmlEntities() export interface DataSelectorSearchProps { setNavigatedToPath: (_: DataPickerOption) => void @@ -23,6 +26,12 @@ export const DataSelectorSearch = React.memo( }, [setNavigatedToPath], ) + + const results = React.useMemo( + () => throttledSearch(allVariablesInScope, searchTerm.toLowerCase()), + [allVariablesInScope, searchTerm], + ) + return (
- {throttledSearch(allVariablesInScope, searchTerm.toLowerCase())?.map( - (searchResult, idx) => ( - - - - {searchResult.valuePath.map((v, i) => ( - - - {when( - i < searchResult.valuePath.length - 1, - , - )} - - ))} - - - - - - - ), - )} + + {results?.map((searchResult, idx) => ( + + ))} + + + {results?.map((searchResult, idx) => ( + + + + ))} +
) }, @@ -89,7 +78,7 @@ export const DataSelectorSearch = React.memo( interface SearchResult { option: DataPickerOption valuePath: Array<{ value: string; matched: boolean }> - value: { value: string; matched: boolean } + value: { value: string | null; matched: boolean } } function searchInValuePath( @@ -115,7 +104,7 @@ function searchInValuePath( function searchInValue(value: unknown, context: SearchContext): SearchResult['value'] { if (typeof value === 'object' || Array.isArray(value)) { - return { value: '', matched: false } + return { value: null, matched: false } } const valueAsString = `${value}` return { @@ -216,6 +205,7 @@ function SearchResultString({ const style: React.CSSProperties = { ...UtopiaStyles.fontStyles.monospaced, fontSize: 10, + height: 20, } const regexp = React.useMemo(() => new RegExp(searchTerm, 'gi'), [searchTerm]) @@ -247,3 +237,40 @@ function SearchResultString({ ) } + +function SearchResultCartouche({ + searchResult, + searchTerm, + setNavigatedToPath: setNavigatedToPathCurried, +}: { + searchResult: SearchResult + searchTerm: string + setNavigatedToPath: (e: React.MouseEvent) => void +}) { + const dataSource = useVariableDataSource(searchResult.option) + const iconColor = dataSource === 'external' ? 'green' : 'primary' + + return ( + + {searchResult.valuePath.map((v, i) => ( + + + {when( + i < searchResult.valuePath.length - 1, + , + )} + + ))} + + ) +} diff --git a/editor/src/uuiui/icons.tsx b/editor/src/uuiui/icons.tsx index 92288da1d3af..7913ac60ac0f 100644 --- a/editor/src/uuiui/icons.tsx +++ b/editor/src/uuiui/icons.tsx @@ -199,6 +199,13 @@ export const SmallerIcons = { width: 11, height: 11, }), + ExpansionArrowRight: makeIcon({ + category: 'semantic', + type: 'expansionarrow-small-right', + color: 'main', + width: 12, + height: 12, + }), } export const Icons = { From 08c4fb087009a85a0bfb3697977cdcfeedd8c51d Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Fri, 14 Jun 2024 12:19:17 +0100 Subject: [PATCH 082/103] Fix Inspector Indentation (#5935) - Added a lot of `displayName` fields to the React components used in the inspector. - Made `RowForArrayControl` and `RowForObjectControl` more consistent with other components by replacing some flex rows with a single `UIGridRow`. - Moved the toggle for `RowForObjectControl` to `ObjectIndicator` so that it doesn't double up with the data picker trigger. - Removed `paddingLeft` from `objectPropertyLabelStyle` as it was just adding a potentially incorrect value for that property. - Added `ref` to `GridRowProps` and incorporated it into `UIGridRow`. - Added an additional property `shouldIncreaseIndentation`, which is then used to determine if content should visually nest. - Removed a change to `paddingLeft` in `RowForBaseControl` because it didn't make any sense any more. --- .../component-section/component-section.tsx | 200 +++++++------ .../component-section/folder-section.tsx | 9 +- .../property-controls-section.tsx | 5 +- .../row-or-folder-wrapper.tsx | 3 + ...performance-regression-tests.spec.tsx.snap | 280 +++++++++--------- 5 files changed, 258 insertions(+), 239 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index 03c7462697cd..48f47ef811be 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -335,6 +335,8 @@ const ControlForProp = React.memo((props: ControlForPropProps void indentationLevel: number + shouldIncreaseIdentation: boolean focusOnMount: boolean showHiddenControl: (path: string) => void } @@ -621,7 +624,7 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => { target={[propPath]} style={{ textTransform: 'capitalize', - paddingLeft: indentation - 8, + paddingLeft: indentation, alignSelf: 'flex-start', }} > @@ -677,6 +680,7 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => { ) }) +RowForBaseControl.displayName = 'RowForBaseControl' function getSectionHeight(controlDescription: ArrayControlDescription): number { const rowHeight = UtopiaTheme.layout.rowHeight.normal @@ -719,6 +723,7 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { isScene, controlDescription, ) + const indentation = props.indentationLevel * 8 const propName = `${PP.lastPart(propPath)}` const propMetadata = useComponentPropsInspectorInfo( @@ -768,54 +773,51 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { {when(dataPickerButtonData.popupIsOpen, dataPickerButtonData.DataPickerComponent)}
- - - - - {title} - - {propertyStatus.overwritable && !propertyStatus.controlled ? ( - - {insertingRow ? ( - - ) : ( - - )} - - ) : null} - - - - + {title} + + {propertyStatus.overwritable && !propertyStatus.controlled ? ( + + {insertingRow ? ( + + ) : ( + + )} + + ) : null} + +
{ focusOnMount={props.focusOnMount} setGlobalCursor={props.setGlobalCursor} showHiddenControl={props.showHiddenControl} + indentationLevel={props.indentationLevel} /> ))}
@@ -840,6 +843,8 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { ) }) +RowForArrayControl.displayName = 'RowForArrayControl' + interface ArrayControlItemProps { springStyle: { [x: string]: any; [x: number]: any } bind: (...args: any[]) => ReactEventHandlers @@ -850,6 +855,7 @@ interface ArrayControlItemProps { focusOnMount: boolean setGlobalCursor: (cursor: CSSCursor | null) => void showHiddenControl: (path: string) => void + indentationLevel: number } const ArrayControlItem = React.memo((props: ArrayControlItemProps) => { @@ -899,6 +905,7 @@ const ArrayControlItem = React.memo((props: ArrayControlItemProps) => { propPath={PP.appendPropertyPathElems(propPath, [index])} setGlobalCursor={props.setGlobalCursor} indentationLevel={2} + shouldIncreaseIdentation={true} focusOnMount={props.focusOnMount && index === 0} disableToggling={true} showHiddenControl={props.showHiddenControl} @@ -930,6 +937,7 @@ const ArrayControlItem = React.memo((props: ArrayControlItemProps) => { ) }) +ArrayControlItem.displayName = 'ArrayControlItem' interface RowForTupleControlProps extends AbstractRowForControlProps { controlDescription: TupleControlDescription @@ -988,6 +996,7 @@ const RowForTupleControl = React.memo((props: RowForTupleControlProps) => { ) }) +RowForTupleControl.displayName = 'RowForTupleControl' interface TupleControlItemProps { propPath: PropertyPath @@ -1028,20 +1037,24 @@ const TupleControlItem = React.memo((props: TupleControlItemProps) => { propPath={PP.appendPropertyPathElems(propPath, [index])} setGlobalCursor={props.setGlobalCursor} indentationLevel={1} + shouldIncreaseIdentation={true} focusOnMount={false} showHiddenControl={props.showHiddenControl} /> ) }) +TupleControlItem.displayName = 'TupleControlItem' interface ObjectIndicatorProps { open: boolean + toggle: () => void } const ObjectIndicator = (props: ObjectIndicatorProps) => { return (
{ data={null} > {when(dataPickerButtonData.popupIsOpen, dataPickerButtonData.DataPickerComponent)} - - - - - {unless(props.disableToggling, )} - - -
- -
-
-
+ {unless( + props.disableToggling, + , + )} + + +
+ +
+
{when( @@ -1185,7 +1192,10 @@ const RowForObjectControl = React.memo((props: RowForObjectControlProps) => { isScene={isScene} propPath={innerPropPath} setGlobalCursor={props.setGlobalCursor} - indentationLevel={props.indentationLevel + 1} + indentationLevel={ + props.shouldIncreaseIdentation ? props.indentationLevel + 1 : props.indentationLevel + } + shouldIncreaseIdentation={props.shouldIncreaseIdentation} focusOnMount={props.focusOnMount && index === 0} disableToggling={props.disableToggling} showHiddenControl={props.showHiddenControl} @@ -1196,6 +1206,7 @@ const RowForObjectControl = React.memo((props: RowForObjectControlProps) => {
) }) +RowForObjectControl.displayName = 'RowForObjectControl' interface RowForUnionControlProps extends AbstractRowForControlProps { controlDescription: UnionControlDescription @@ -1270,6 +1281,7 @@ const RowForUnionControl = React.memo((props: RowForUnionControlProps) => { ) } }) +RowForUnionControl.displayName = 'RowForUnionControl' interface RowForControlProps extends AbstractRowForControlProps { controlDescription: RegularControlDescription @@ -1310,6 +1322,7 @@ export const RowForControl = React.memo((props: RowForControlProps) => { } } }) +RowForControl.displayName = 'RowForControl' export interface ComponentSectionProps { isScene: boolean @@ -1547,7 +1560,6 @@ export class ComponentSection extends React.Component< const objectPropertyLabelStyle = { textTransform: 'capitalize', - paddingLeft: 8, display: 'flex', alignItems: 'center', height: 34, diff --git a/editor/src/components/inspector/sections/component-section/folder-section.tsx b/editor/src/components/inspector/sections/component-section/folder-section.tsx index 3b8d0e3f83b9..a69bc439e1cd 100644 --- a/editor/src/components/inspector/sections/component-section/folder-section.tsx +++ b/editor/src/components/inspector/sections/component-section/folder-section.tsx @@ -95,7 +95,8 @@ export const FolderSection = React.memo((props: FolderSectionProps) => { controlDescription={controlDescription} isScene={false} setGlobalCursor={props.setGlobalCursor} - indentationLevel={0} + indentationLevel={props.indentationLevel} + shouldIncreaseIdentation={false} visibleEmptyControls={props.visibleEmptyControls} unsetPropNames={props.unsetPropNames} showHiddenControl={props.showHiddenControl} @@ -132,7 +133,8 @@ export const FolderSection = React.memo((props: FolderSectionProps) => { controlDescription={controlDescription} isScene={false} setGlobalCursor={props.setGlobalCursor} - indentationLevel={0} + indentationLevel={props.indentationLevel} + shouldIncreaseIdentation={true} showHiddenControl={props.showHiddenControl} focusOnMount={false} /> @@ -149,9 +151,10 @@ export const FolderSection = React.memo((props: FolderSectionProps) => { , )}
) }) +FolderSection.displayName = 'FolderSection' diff --git a/editor/src/components/inspector/sections/component-section/property-controls-section.tsx b/editor/src/components/inspector/sections/component-section/property-controls-section.tsx index 3b8381e25b0a..11d279b47f1b 100644 --- a/editor/src/components/inspector/sections/component-section/property-controls-section.tsx +++ b/editor/src/components/inspector/sections/component-section/property-controls-section.tsx @@ -113,7 +113,7 @@ export const PropertyControlsSection = React.memo((props: PropertyControlsSectio ) }) +PropertyControlsSection.displayName = 'PropertyControlsSection' interface SyntheticFoldersResult { uncategorized: PropertyControls diff --git a/editor/src/components/inspector/sections/component-section/row-or-folder-wrapper.tsx b/editor/src/components/inspector/sections/component-section/row-or-folder-wrapper.tsx index eb3e036ffa15..33fca0406c77 100644 --- a/editor/src/components/inspector/sections/component-section/row-or-folder-wrapper.tsx +++ b/editor/src/components/inspector/sections/component-section/row-or-folder-wrapper.tsx @@ -11,6 +11,7 @@ type RowOrFolderWrapperProps = { setGlobalCursor: (cursor: CSSCursor | null) => void controlDescription: ControlDescription indentationLevel: number + shouldIncreaseIdentation: boolean visibleEmptyControls: string[] unsetPropNames: string[] showHiddenControl: (path: string) => void @@ -26,9 +27,11 @@ export const RowOrFolderWrapper = React.memo((props: RowOrFolderWrapperProps) => isScene={props.isScene} setGlobalCursor={props.setGlobalCursor} indentationLevel={props.indentationLevel} + shouldIncreaseIdentation={props.shouldIncreaseIdentation} focusOnMount={props.focusOnMount ?? false} showHiddenControl={props.showHiddenControl} /> ) }) +RowOrFolderWrapper.displayName = 'RowOrFolderWrapper' diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 78a2580573e8..3f9dcfe41525 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -148,32 +148,32 @@ Array [ "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(UIGridRow)", - "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", + "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)(PropertyControlsSection)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorSectionHeader)", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)/div", - "/div/null//Symbol(react.memo)()", - "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", - "/null///Symbol(react.forward_ref)(UIGridRow)", - "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", - "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/Symbol(react.memo)(FolderSection)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/UtopiaSpiedFunctionComponent(InspectorSectionHeader)", + "/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/Symbol(react.memo)(RowForControl)", + "/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/Symbol(react.memo)()", + "/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/div/null/RowForControl/Symbol(react.memo)(RowForBaseControl)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", + "/null/RowForControl/RowForBaseControl/div", + "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", + "/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", @@ -189,11 +189,11 @@ Array [ "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/div/Icon/img", - "/div/div//Symbol(react.memo)()", - "/div/div//Symbol(react.memo)()", - "/div///Symbol(react.forward_ref)()", - "/div///Symbol(react.memo)(CartoucheInspectorWrapper)", - "///CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/ControlForProp//Symbol(react.forward_ref)()", + "/div/ControlForProp//Symbol(react.memo)(CartoucheInspectorWrapper)", + "/ControlForProp//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()", "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon)", @@ -427,17 +427,17 @@ Array [ "/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/Symbol(react.forward_ref)(Styled(div))/div:data-testid='section-header-Advanced'", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", - "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", - "/null///Symbol(react.forward_ref)(UIGridRow)", - "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", - "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", + "/null/RowForControl/RowForBaseControl/div", + "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", + "/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", @@ -452,11 +452,11 @@ Array [ "/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/div/div//Symbol(react.memo)()", - "/div/div//Symbol(react.memo)()", - "/div///Symbol(react.forward_ref)()", - "/div///Symbol(react.memo)(CartoucheInspectorWrapper)", - "///CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/ControlForProp//Symbol(react.forward_ref)()", + "/div/ControlForProp//Symbol(react.memo)(CartoucheInspectorWrapper)", + "/ControlForProp//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()", "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon)", @@ -637,13 +637,13 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.provider)///Symbol(react.memo)(Inspector)", "/Symbol(react.provider)///Symbol(react.memo)()", - "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", - "/null///Symbol(react.forward_ref)(UIGridRow)", - "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", + "/null/RowForControl/RowForBaseControl/div", + "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", ] `; @@ -795,18 +795,18 @@ Array [ "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(UIGridRow)", - "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", + "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)(PropertyControlsSection)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(Styled(span))", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "//Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/Symbol(react.forward_ref)(Styled(span))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/Symbol(react.forward_ref)(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/PropertyControlsSection/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/div/div/Symbol(react.forward_ref)(Styled(span))/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(InspectorSectionHeader)/Symbol(react.memo)()", @@ -1297,13 +1297,13 @@ Array [ "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)", "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", "//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", - "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", - "/null///Symbol(react.forward_ref)(UIGridRow)", - "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", + "/null/RowForControl/RowForBaseControl/div", + "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FrameUpdatingLayoutControl/Symbol(react.memo)(NumberInput)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FrameUpdatingLayoutControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", @@ -1553,32 +1553,32 @@ Array [ "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(UIGridRow)", - "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", + "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)(PropertyControlsSection)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedExoticType(Symbol(react.fragment))", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorSectionHeader)", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.memo)()", - "//UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(EmotionCssPropInternal)/div", - "/div/null//Symbol(react.memo)()", - "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", - "/null///Symbol(react.forward_ref)(UIGridRow)", - "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", - "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/Symbol(react.memo)(FolderSection)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))", + "/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/UtopiaSpiedFunctionComponent(InspectorSectionHeader)", + "/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/Symbol(react.memo)(RowForControl)", + "/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/Symbol(react.memo)()", + "/PropertyControlsSection/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/FolderSection/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/div/null/RowForControl/Symbol(react.memo)(RowForBaseControl)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", + "/null/RowForControl/RowForBaseControl/div", + "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", + "/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", @@ -1593,11 +1593,11 @@ Array [ "/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/div/div//Symbol(react.memo)()", - "/div/div//Symbol(react.memo)()", - "/div///Symbol(react.forward_ref)()", - "/div///Symbol(react.memo)(CartoucheInspectorWrapper)", - "///CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/ControlForProp//Symbol(react.forward_ref)()", + "/div/ControlForProp//Symbol(react.memo)(CartoucheInspectorWrapper)", + "/ControlForProp//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()", "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon)", @@ -1774,17 +1774,17 @@ Array [ "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)", "/UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)", "//UtopiaSpiedFunctionComponent(it)/UtopiaSpiedFunctionComponent($)/UtopiaSpiedExoticType(Symbol(react.provider))", - "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", - "/null///Symbol(react.forward_ref)(UIGridRow)", - "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", - "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", + "/null/RowForControl/RowForBaseControl/div", + "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", + "/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", @@ -1799,11 +1799,11 @@ Array [ "/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/div/div//Symbol(react.memo)()", - "/div/div//Symbol(react.memo)()", - "/div///Symbol(react.forward_ref)()", - "/div///Symbol(react.memo)(CartoucheInspectorWrapper)", - "///CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/ControlForProp//Symbol(react.forward_ref)()", + "/div/ControlForProp//Symbol(react.memo)(CartoucheInspectorWrapper)", + "/ControlForProp//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()", "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon)", @@ -2023,17 +2023,17 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", - "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", - "/null///Symbol(react.forward_ref)(UIGridRow)", - "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", - "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", + "/null/RowForControl/RowForBaseControl/div", + "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", + "/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", @@ -2048,11 +2048,11 @@ Array [ "/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/div/div//Symbol(react.memo)()", - "/div/div//Symbol(react.memo)()", - "/div///Symbol(react.forward_ref)()", - "/div///Symbol(react.memo)(CartoucheInspectorWrapper)", - "///CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/ControlForProp//Symbol(react.forward_ref)()", + "/div/ControlForProp//Symbol(react.memo)(CartoucheInspectorWrapper)", + "/ControlForProp//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()", "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon)", @@ -2106,17 +2106,17 @@ Array [ "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/Symbol(react.memo)(SelectionAreaRectangle)", "/div/div/UtopiaSpiedFunctionComponent(NewCanvasControlsInner)/UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(Styled(div))/div/Symbol(react.forward_ref)(Styled(div))/div", - "/null///Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null///UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null///Symbol(react.memo)(PropertyLabel)", - "/null///Symbol(react.memo)()", - "/null///div", - "/null///Symbol(react.forward_ref)(UIGridRow)", - "/null///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", - "///UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", - "//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", + "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", + "/null/RowForControl/RowForBaseControl/div", + "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", + "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(MenuProvider)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/UtopiaSpiedFunctionComponent(ContextMenu)", + "/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal):data-testid='context-menu-for-onMouseDown'", + "/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div:data-testid='context-menu-for-onMouseDown'", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/UtopiaSpiedFunctionComponent(MenuProvider)/div", "/UtopiaSpiedFunctionComponent(MenuProvider)/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", @@ -2131,11 +2131,11 @@ Array [ "/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)", "/UtopiaSpiedClass(Tooltip)/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.forward_ref)(TippyWrapper)/UtopiaSpiedFunctionComponent(Tippy)/UtopiaSpiedExoticType(Symbol(react.fragment))", - "/div/div//Symbol(react.memo)()", - "/div/div//Symbol(react.memo)()", - "/div///Symbol(react.forward_ref)()", - "/div///Symbol(react.memo)(CartoucheInspectorWrapper)", - "///CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/div/ControlForProp/Symbol(react.memo)()", + "/div/ControlForProp//Symbol(react.forward_ref)()", + "/div/ControlForProp//Symbol(react.memo)(CartoucheInspectorWrapper)", + "/ControlForProp//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)", "//CartoucheInspectorWrapper/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()", "/div/Symbol(react.forward_ref)()/Symbol(react.forward_ref)()/Symbol(react.memo)(Icon)", @@ -2539,18 +2539,18 @@ Array [ "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(Styled(div))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.forward_ref)(UIGridRow)", - "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)()", + "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/Symbol(react.memo)(PropertyControlsSection)", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/div/UtopiaSpiedClass(ComponentSection)/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))", "/ComponentSectionInner/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/UtopiaSpiedExoticType(Symbol(react.fragment))/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/Symbol(react.forward_ref)(Styled(div))/div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(Styled(span))", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//div", - "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)", - "/UtopiaSpiedExoticType(Symbol(react.fragment))//Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", - "//Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/Symbol(react.forward_ref)(Styled(span))", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/div", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/Symbol(react.forward_ref)(UIGridRow)", + "/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyControlsSection/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)", + "/PropertyControlsSection/Symbol(react.forward_ref)(UIGridRow)/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/div/div/Symbol(react.forward_ref)(Styled(span))/span", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/FixedHugDropdown/Symbol(react.memo)(Symbol(react.forward_ref)())", "/FixedHugDropdown/Symbol(react.memo)(Symbol(react.forward_ref)())/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(EmotionCssPropInternal)", From 44ab0f9ac59948943ee11598e07500252996734f Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:24:01 +0200 Subject: [PATCH 083/103] oops: fix data picker missing values (#5945) **Problem:** ``` const myTestData = { keyA: 5, keyB: 5, keyC: 5, keyD: 5, } ``` would only show keyA in the data picker: image **Fix:** Turns out I botched a circular reference checker, and prevented traversal if we encountered repeated simple values. but simple values are value-compared, so in the above example keyB would be considered equal to keyA and omitted. **Commit Details:** (< vv pls delete this section if's not relevant) - Only bail out if we encounter a known reference to an object or function. --- .../sections/component-section/variables-in-scope-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index 9dce7d40945f..e6750ed667b2 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -215,7 +215,7 @@ export function variableInfoFromValue( insertionCeiling: ElementPath | FileRootPath, valueStackSoFar: Set, ): VariableInfo | null { - if (valueStackSoFar.has(value)) { + if ((typeof value === 'object' || typeof value === 'function') && valueStackSoFar.has(value)) { // prevent circular dependencies return null } From 4e79a74e361654ed396146cae80c1980fd3fa691 Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Fri, 14 Jun 2024 11:28:39 -0400 Subject: [PATCH 084/103] Add Icons for Flex Component Inspector Controls (#5936) Adding the icons to be used in #5851 --- editor/src/uuiui/icons.tsx | 182 ++++++++++++++++++++++++++++ utopia-api/src/primitives/icons.tsx | 26 ++++ 2 files changed, 208 insertions(+) diff --git a/editor/src/uuiui/icons.tsx b/editor/src/uuiui/icons.tsx index 7913ac60ac0f..2a99e8098dee 100644 --- a/editor/src/uuiui/icons.tsx +++ b/editor/src/uuiui/icons.tsx @@ -463,6 +463,188 @@ export const Icons = { width: 16, height: 16, }), + FlexDirectionRow: makeIcon({ + category: 'inspector-element', + type: 'arrowRight', + color: 'main', + width: 16, + height: 16, + }), + FlexDirectionRowReverse: makeIcon({ + category: 'inspector-element', + type: 'arrowLeft', + color: 'main', + width: 16, + height: 16, + }), + FlexDirectionColumn: makeIcon({ + category: 'inspector-element', + type: 'arrowDown', + color: 'main', + width: 16, + height: 16, + }), + FlexDirectionColumnReverse: makeIcon({ + category: 'inspector-element', + type: 'arrowUp', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsRowCenter: makeIcon({ + category: 'inspector-element', + type: 'alignItems-row-center', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsRowFlexStart: makeIcon({ + category: 'inspector-element', + type: 'alignItems-row-flexStart', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsRowFlexEnd: makeIcon({ + category: 'inspector-element', + type: 'alignItems-row-flexEnd', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsRowStretch: makeIcon({ + category: 'inspector-element', + type: 'alignItems-row-stretch', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsRowBaseline: makeIcon({ + category: 'inspector-element', + type: 'alignItems-row-baseline', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsColumnCenter: makeIcon({ + category: 'inspector-element', + type: 'alignItems-column-center', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsColumnFlexStart: makeIcon({ + category: 'inspector-element', + type: 'alignItems-column-flexStart', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsColumnFlexEnd: makeIcon({ + category: 'inspector-element', + type: 'alignItems-column-flexEnd', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsColumnStretch: makeIcon({ + category: 'inspector-element', + type: 'alignItems-column-stretch', + color: 'main', + width: 16, + height: 16, + }), + AlignItemsColumnBaseline: makeIcon({ + category: 'inspector-element', + type: 'alignItems-column-baseline', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentRowCenter: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-row-center', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentRowFlexStart: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-row-flexstart', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentRowFlexEnd: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-row-flexend', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentRowSpaceBetween: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-row-spaceBetween', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentRowSpaceAround: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-row-spaceAround', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentRowSpaceEvenly: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-row-spaceEvenly', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentColumnCenter: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-column-center', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentColumnFlexStart: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-column-flexstart', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentColumnFlexEnd: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-column-flexend', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentColumnSpaceBetween: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-column-spaceBetween', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentColumnSpaceAround: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-column-spaceAround', + color: 'main', + width: 16, + height: 16, + }), + JustifyContentColumnSpaceEvenly: makeIcon({ + category: 'inspector-element', + type: 'justifyContent-column-spaceEvenly', + color: 'main', + width: 16, + height: 16, + }), } as const export const FunctionIcons = { diff --git a/utopia-api/src/primitives/icons.tsx b/utopia-api/src/primitives/icons.tsx index a902fd5f2ec8..0a6fe0a4242c 100644 --- a/utopia-api/src/primitives/icons.tsx +++ b/utopia-api/src/primitives/icons.tsx @@ -78,6 +78,32 @@ export const UtopiaIcons = [ 'TextAlignLeft', 'TextAlignCenter', 'TextAlignRight', + 'FlexDirectionRow', + 'FlexDirectionRowReverse', + 'FlexDirectionColumn', + 'FlexDirectionColumnReverse', + 'AlignItemsRowCenter', + 'AlignItemsRowFlexStart', + 'AlignItemsRowFlexEnd', + 'AlignItemsRowStretch', + 'AlignItemsRowBaseline', + 'AlignItemsColumnCenter', + 'AlignItemsColumnFlexStart', + 'AlignItemsColumnFlexEnd', + 'AlignItemsColumnStretch', + 'AlignItemsColumnBaseline', + 'JustifyContentRowCenter', + 'JustifyContentRowFlexStart', + 'JustifyContentRowFlexEnd', + 'JustifyContentRowSpaceBetween', + 'JustifyContentRowSpaceAround', + 'JustifyContentRowSpaceEvenly', + 'JustifyContentColumnCenter', + 'JustifyContentColumnFlexStart', + 'JustifyContentColumnFlexEnd', + 'JustifyContentColumnSpaceBetween', + 'JustifyContentColumnSpaceAround', + 'JustifyContentColumnSpaceEvenly', ] as const export type UtopiaIcon = (typeof UtopiaIcons)[number] From 3ec8c3ab4850413d27d85f1822839736967cea2a Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Fri, 14 Jun 2024 11:29:11 -0400 Subject: [PATCH 085/103] Subtle Navigator Fixes (#5939) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some small but mighty fixes for navigator things: - Fixed the `zerosized-div` icon to be whatever color it wants to be - Fixed the "subdued" icons to be the correct gray that matches the text, and isn't too washed out in light mode - Fixed the background for literal cartouches to be translucent over it's row's background | Before | After | | ------------- | ------------- | | Screenshot 2024-06-13 at 5 46 51 PM | Screenshot 2024-06-13 at 5 45 13 PM | | Screenshot 2024-06-13 at 5 47 20 PM | Screenshot 2024-06-13 at 5 47 54 PM | Fixes #5918 and #5894 --- .../inspector/sections/component-section/cartouche-ui.tsx | 6 +++--- .../src/components/navigator/navigator-item/layout-icon.tsx | 2 +- .../navigator-item/navigator-item.spec.browser2.tsx | 2 +- editor/src/uuiui/icn.tsx | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 22546f4984d9..d89cb97e15fb 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -259,17 +259,17 @@ function useCartoucheColors(source: CartoucheSource, highlight: CartoucheHighlig ? colorTheme.whiteOpacity20.value : highlight === 'subtle' ? colorTheme.cartoucheLiteralHighlightDefault.value - : colorTheme.bg5.value, + : colorTheme.cartoucheLiteralHighlightDefault.value, hovered: highlight === 'strong' ? colorTheme.whiteOpacity30.value : highlight === 'subtle' ? colorTheme.cartoucheLiteralHighlightHovered.value - : colorTheme.fg8.value, + : colorTheme.cartoucheLiteralHighlightHovered.value, selected: highlight === 'subtle' ? colorTheme.cartoucheLiteralHighlightSelected.value - : colorTheme.fg6.value, + : colorTheme.cartoucheLiteralHighlightSelected.value, }, icon: { default: 'secondary', hovered: 'secondary', selected: 'on-highlight-main' }, } diff --git a/editor/src/components/navigator/navigator-item/layout-icon.tsx b/editor/src/components/navigator/navigator-item/layout-icon.tsx index 608e6061cc92..b12f7fe14581 100644 --- a/editor/src/components/navigator/navigator-item/layout-icon.tsx +++ b/editor/src/components/navigator/navigator-item/layout-icon.tsx @@ -129,7 +129,7 @@ export const LayoutIcon: React.FunctionComponent { ) await checkNavigatorIcon( 'Sizeless div', - { category: 'navigator-element', type: 'zerosized-div', color: 'lightgray' }, + { category: 'navigator-element', type: 'zerosized-div', color: 'gray' }, visibleNavigatorTargets[17], ) await checkNavigatorIcon( diff --git a/editor/src/uuiui/icn.tsx b/editor/src/uuiui/icn.tsx index ac514a1932f0..3fc9f3465ac2 100644 --- a/editor/src/uuiui/icn.tsx +++ b/editor/src/uuiui/icn.tsx @@ -61,7 +61,7 @@ function useIconColor(intent: IcnColor): IcnResultingColor { case 'secondary': return 'gray' case 'subdued': - return 'lightgray' + return 'gray' case 'primary': return 'blue' case 'warning': From 011e71531010eeb6eaca62080466654240084cd5 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Fri, 14 Jun 2024 17:30:29 +0200 Subject: [PATCH 086/103] Data Picker Simpler Property Accessors (#5952) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** The data picker would generate code such as `reviews['references']['nodes'][0]['id']` which is hard to read and does not pass our bar of trying to write code a real developer would write. **Fix:** Using a simple regex from here https://stackoverflow.com/questions/1661197/what-characters-are-valid-for-javascript-variable-names, we test if the property accessor name is trivially safe. if it is safe, we append it with a `.id`. if it's not safe, we append it as `['id']`. We keep array element accesses as number. **Result:** `reviews.references.nodes[0].id` – this is how I would write it too! --- .../variables-in-scope-utils.spec.ts | 8 ++++---- .../component-section/variables-in-scope-utils.ts | 13 ++++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts index 00a3b7d947bc..a50b0192d7cd 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts @@ -54,7 +54,7 @@ describe('orderVariablesForRelevance', () => { "matches": "child-matches", "props": Array [ Object { - "expression": "style['left']", + "expression": "style.left", "expressionPathPart": "left", "insertionCeiling": Object { "parts": Array [ @@ -69,7 +69,7 @@ describe('orderVariablesForRelevance', () => { "value": 300, }, Object { - "expression": "style['position']", + "expression": "style.position", "expressionPathPart": "position", "insertionCeiling": Object { "parts": Array [ @@ -141,7 +141,7 @@ describe('orderVariablesForRelevance', () => { "matches": "matches", "props": Array [ Object { - "expression": "style['left']", + "expression": "style.left", "expressionPathPart": "left", "insertionCeiling": Object { "parts": Array [ @@ -156,7 +156,7 @@ describe('orderVariablesForRelevance', () => { "value": 300, }, Object { - "expression": "style['position']", + "expression": "style.position", "expressionPathPart": "position", "insertionCeiling": Object { "parts": Array [ diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index e6750ed667b2..eb86b48d7a67 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -290,7 +290,7 @@ export function variableInfoFromValue( matches: 'does-not-match', props: mapDropNulls(([key, propValue]) => { return variableInfoFromValue( - `${expression}['${key}']`, + createPropertyAccessExpressionString(expression, key), key, propValue, insertionCeiling, @@ -311,6 +311,17 @@ function variableInfoFromVariableData(variableNamesInScope: VariableData): Array return info } +const varSafeStringRegex = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/ + +function createPropertyAccessExpressionString(expressionSoFar: string, toAppend: string): string { + const toAppendIsVarsafeString = varSafeStringRegex.test(toAppend) + if (toAppendIsVarsafeString) { + return `${expressionSoFar}.${toAppend}` + } else { + return `${expressionSoFar}['${toAppend}']` + } +} + function getTargetPropertyFromControlDescription( controlDescription: ControlDescription | null, targetPropertyName: string | null, From e0afb46d6417f12c3e1f1b34c09fac722c7fd784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Fri, 14 Jun 2024 17:41:32 +0200 Subject: [PATCH 087/103] Add grayscale/opacity css to the segment controls (#5949) **Problem:** https://github.com/concrete-utopia/utopia/issues/5908 **Fix:** https://screenshot.click/14-08-lg988-d8r7h.mp4 **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../inspector/controls/option-control.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/editor/src/components/inspector/controls/option-control.tsx b/editor/src/components/inspector/controls/option-control.tsx index 249b53b45bab..a4e1fea7cfdc 100644 --- a/editor/src/components/inspector/controls/option-control.tsx +++ b/editor/src/components/inspector/controls/option-control.tsx @@ -162,8 +162,18 @@ export const OptionControl: React.FunctionComponent< rc === 'all' || rc === 'left' || rc === 'bottomLeft' || rc === 'bottom' ? UtopiaTheme.inputBorderRadius : undefined, + + filter: isChecked && props.controlStatus !== 'disabled' ? undefined : 'grayscale(1)', '&:hover': { opacity: props.controlStatus == 'disabled' ? undefined : controlOpacity + 0.2, + filter: props.controlStatus == 'disabled' ? undefined : 'grayscale(0)', + }, + + '.control-option-icon-component': { + opacity: 0.5, + }, + '&:hover .control-option-icon-component': { + opacity: 1, }, '&:active': { opacity: props.controlStatus == 'disabled' ? undefined : 1, @@ -191,6 +201,7 @@ export const OptionControl: React.FunctionComponent< display: 'flex', justifyContent: 'center', alignItems: 'center', + gap: 4, }} > {controlOptions.icon != null ? ( @@ -199,7 +210,9 @@ export const OptionControl: React.FunctionComponent< {...controlOptions.icon} /> ) : ( - controlOptions.iconComponent ?? null +
+ {controlOptions.iconComponent ?? null} +
)} {controlOptions.labelInner != null ? controlOptions.labelInner : null}
From 660971c511d72b128b13745fd789de846be3c946 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:24:07 +0200 Subject: [PATCH 088/103] Fix/data picker touchups (#5951) Assorted fixes: - only show pointer for selectable cartouches, - make Deselect match Finder, - double click should insta-apply a selectable cartouche , - override with alt to Force Apply, - improve the apply button to look like you cannot press it when the selection is not applicable - opacity? more greyed? - show expansion arrow icon on anything that is a folder, selected or not! - remove DataPickerFilterOption **Fix:** The individual commits are self-contained and each fixes one of the above --- .../component-section/cartouche-ui.tsx | 2 +- .../component-section/component-section.tsx | 4 +- .../component-section/data-picker-popup.tsx | 57 --------- .../component-section/data-picker-utils.tsx | 15 --- .../data-reference-cartouche.tsx | 10 +- .../data-selector-cartouche.tsx | 2 + .../data-selector-columns.tsx | 111 ++++++++++++++---- .../component-section/data-selector-modal.tsx | 71 ++++++++--- .../variables-in-scope-utils.spec.ts | 2 - .../variables-in-scope-utils.ts | 10 +- .../sections/data-reference-section.tsx | 4 - .../layout-section/list-source-cartouche.tsx | 13 +- ...performance-regression-tests.spec.tsx.snap | 7 -- .../performance-regression-tests.spec.tsx | 2 +- 14 files changed, 153 insertions(+), 157 deletions(-) delete mode 100644 editor/src/components/inspector/sections/component-section/data-picker-popup.tsx diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index d89cb97e15fb..cb1bf634ec9a 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -87,7 +87,7 @@ export const CartoucheUI = React.forwardRef( -} - -export interface ArrayOption { - type: 'array' - variableInfo: ArrayInfo - depth: number - definedElsewhere: string - children: Array - valuePath: Array -} - -export interface ObjectOption { - type: 'object' - variableInfo: ObjectInfo - depth: number - definedElsewhere: string - children: Array - valuePath: Array -} - -export interface JSXOption { - type: 'jsx' - variableInfo: JSXInfo - definedElsewhere: string - depth: number - valuePath: Array -} - -export type DataPickerOption = PrimitiveOption | ArrayOption | ObjectOption | JSXOption - -const DataPickerFilterOptions = ['all', 'preferred'] as const -export type DataPickerFilterOption = (typeof DataPickerFilterOptions)[number] -export function dataPickerFilterOptionToString(mode: DataPickerFilterOption): string { - switch (mode) { - case 'all': - return 'All Data' - case 'preferred': - return 'Preferred' - default: - assertNever(mode) - } -} - -export const DataPickerPreferredAllAtom = atom('all') - -export type DataPickerCallback = (e: JSExpressionOtherJavaScript) => void diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 5c53a9260d6c..3974192157c4 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -50,21 +50,6 @@ export interface JSXOption extends VariableOptionBase { export type DataPickerOption = PrimitiveOption | ArrayOption | ObjectOption | JSXOption -const DataPickerFilterOptions = ['all', 'preferred'] as const -export type DataPickerFilterOption = (typeof DataPickerFilterOptions)[number] -export function dataPickerFilterOptionToString(mode: DataPickerFilterOption): string { - switch (mode) { - case 'all': - return 'All Data' - case 'preferred': - return 'Preferred' - default: - assertNever(mode) - } -} - -export const DataPickerPreferredAllAtom = atom('all') - export type DataPickerCallback = (e: JSExpressionOtherJavaScript) => void export type ObjectPath = Array diff --git a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx index dc42f2de33a3..b5a223614152 100644 --- a/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-reference-cartouche.tsx @@ -20,7 +20,7 @@ import { getCartoucheDataTypeForExpression, useVariablesInScopeForSelectedElement, } from './variables-in-scope-utils' -import { DataPickerPreferredAllAtom, jsxElementChildToValuePath } from './data-picker-utils' +import { jsxElementChildToValuePath } from './data-picker-utils' import { useAtom } from 'jotai' import type { CartoucheDataType, CartoucheHighlight, CartoucheUIProps } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' @@ -106,13 +106,7 @@ export const DataReferenceCartoucheControl = React.memo( ? PP.create('children') : assertNever(props.renderedAt) - const [preferredAllState] = useAtom(DataPickerPreferredAllAtom) - - const variableNamesInScope = useVariablesInScopeForSelectedElement( - elementPath, - propertyPath, - preferredAllState, - ) + const variableNamesInScope = useVariablesInScopeForSelectedElement(elementPath, propertyPath) const pathToCurrenlySelectedValue = React.useMemo( () => jsxElementChildToValuePath(childOrAttribute), diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx index 3ec77f7f3071..e1c61a84b192 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -17,6 +17,7 @@ interface DataPickerCartoucheProps { forcedRole?: CartoucheUIProps['role'] forcedSource?: CartoucheUIProps['source'] onClick?: CartoucheUIProps['onClick'] + onDoubleClick?: CartoucheUIProps['onDoubleClick'] } export const DataPickerCartouche = React.memo( @@ -44,6 +45,7 @@ export const DataPickerCartouche = React.memo( ) : undefined } onClick={props.onClick} + onDoubleClick={props.onDoubleClick} > {data.isChildOfArray ? ( <> diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx index 93048ef639f0..71e46d678517 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -1,15 +1,17 @@ +import type { PropsOf } from '@emotion/react' import styled from '@emotion/styled' import React from 'react' import { isPrefixOf } from '../../../../core/shared/array-utils' import { arrayEqualsByReference, assertNever } from '../../../../core/shared/utils' -import { FlexColumn, FlexRow, colorTheme } from '../../../../uuiui' +import { FlexColumn, FlexRow, Icons, colorTheme } from '../../../../uuiui' import type { ArrayOption, DataPickerOption, ObjectOption, ObjectPath } from './data-picker-utils' import { DataPickerCartouche } from './data-selector-cartouche' interface DataSelectorColumnsProps { activeScope: Array targetPathInsideScope: ObjectPath - onTargetPathChange: (newTargetVariable: DataPickerOption) => void + onTargetPathChange: (newTargetVariable: DataPickerOption | null) => void + onApplySelection: (newTargetVariable: DataPickerOption) => void } export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) => { @@ -26,8 +28,10 @@ export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) > @@ -36,13 +40,21 @@ export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) interface DataSelectorColumnProps { activeScope: Array + parentScope: DataPickerOption | null currentlyShowingScopeForArray: boolean targetPathInsideScope: ObjectPath - onTargetPathChange: (newTargetVariable: DataPickerOption) => void + onTargetPathChange: (newTargetVariable: DataPickerOption | null) => void + onApplySelection: (newTargetVariable: DataPickerOption) => void } const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { - const { activeScope, targetPathInsideScope, currentlyShowingScopeForArray } = props + const { + activeScope, + parentScope, + onTargetPathChange, + targetPathInsideScope, + currentlyShowingScopeForArray, + } = props const elementOnSelectedPath: DataPickerOption | null = activeScope.find((option) => isPrefixOf(option.valuePath, targetPathInsideScope)) ?? null @@ -72,9 +84,17 @@ const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { const isLastColumn = nextColumnScope == null && nextColumnScopeValue == null const columnRef = useScrollIntoView(isLastColumn) + const onClickColumnBackground: React.MouseEventHandler = React.useCallback( + (e) => { + e.stopPropagation() + onTargetPathChange(parentScope) + }, + [onTargetPathChange, parentScope], + ) + return ( <> - + {activeScope.map((option, index) => { const selected = arrayEqualsByReference(option.valuePath, targetPathInsideScope) const onActivePath = isPrefixOf(option.valuePath, targetPathInsideScope) @@ -82,11 +102,12 @@ const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { ) })} @@ -94,9 +115,11 @@ const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { {nextColumnScope != null ? ( ) : null} {nextColumnScopeValue != null ? : null} @@ -112,7 +135,7 @@ const ValuePreviewColumn = React.memo((props: ValuePreviewColumnProps) => { const text = safeJSONStringify(props.data.variableInfo.value) const ref = useScrollIntoView(true) return ( - +
void + onApplySelection: (newTargetVariable: DataPickerOption) => void } const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { - const { onTargetPathChange, data, isLeaf, selected, onActivePath, forceShowArrow } = props + const { + onTargetPathChange, + onApplySelection, + data, + isLeaf, + selected, + onActivePath, + forceShowArrow, + } = props const onClick: React.MouseEventHandler = React.useCallback( (e) => { @@ -169,6 +201,14 @@ const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { [data, onTargetPathChange], ) + const onDoubleClick: React.MouseEventHandler = React.useCallback( + (e) => { + e.stopPropagation() + onApplySelection(data) + }, + [data, onApplySelection], + ) + const ref = useScrollIntoView(selected) return ( @@ -178,18 +218,18 @@ const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { style={{ backgroundColor: onActivePath ? colorTheme.bg4.value : undefined, }} - disabled={false} + disabled={data.variableInfo.matches !== 'matches'} > - + - {'>'} + ) @@ -204,21 +244,46 @@ const DataSelectorFlexColumn = styled(FlexColumn)({ scrollbarWidth: 'auto', scrollbarColor: 'gray transparent', paddingTop: 8, - paddingRight: 10, // to account for scrollbar - paddingLeft: 6, paddingBottom: 10, borderRight: `1px solid ${colorTheme.subduedBorder.cssValue}`, }) -const DataPickerRow = styled(FlexRow)((props: { disabled: boolean }) => ({ - alignSelf: 'stretch', - justifyContent: 'space-between', - fontSize: 10, - borderRadius: 4, - height: 24, - padding: 5, - cursor: !props.disabled ? 'pointer' : 'initial', -})) +const DataPickerRow = React.forwardRef< + HTMLDivElement, + React.PropsWithChildren< + PropsOf & { + disabled: boolean + } + > +>((props, ref) => { + return ( + + + {props.children} + + + ) +}) function useScrollIntoView(shouldScroll: boolean) { const elementRef = React.useRef(null) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx index 7222beba3b38..d12c902ec445 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-modal.tsx @@ -153,21 +153,29 @@ export const DataSelectorModal = React.memo( e.preventDefault() }, []) - const applyVariable = React.useCallback(() => { - const variable = selectedVariableOption - if (variable == null) { - return - } - if (variable.variableInfo.matches !== 'matches') { + const altKeyPressedForceApplyMode = useAltKeyPressed() + + const onApplyVariable = React.useCallback( + (variable: DataPickerOption) => { + if (!altKeyPressedForceApplyMode && variable.variableInfo.matches !== 'matches') { + return + } + onPropertyPicked( + jsExpressionOtherJavaScriptSimple(variable.variableInfo.expression, [ + variable.definedElsewhere, + ]), + ) + closePopup() + }, + [closePopup, onPropertyPicked, altKeyPressedForceApplyMode], + ) + + const onApplySelectedVariable = React.useCallback(() => { + if (selectedVariableOption == null) { return } - onPropertyPicked( - jsExpressionOtherJavaScriptSimple(variable.variableInfo.expression, [ - variable.definedElsewhere, - ]), - ) - closePopup() - }, [closePopup, onPropertyPicked, selectedVariableOption]) + onApplyVariable(selectedVariableOption) + }, [onApplyVariable, selectedVariableOption]) const navigateToSearchResult = React.useCallback((variable: DataPickerOption) => { setSearchTerm(null) @@ -280,6 +288,7 @@ export const DataSelectorModal = React.memo( activeScope={filteredVariablesInScope} targetPathInsideScope={selectedVariableOption?.valuePath ?? []} onTargetPathChange={setSelectedVariableOption} + onApplySelection={onApplyVariable} /> ) : ( - Apply + {altKeyPressedForceApplyMode && selectedVariableIsDisabled + ? 'Force Apply' + : 'Apply'}
, @@ -429,7 +442,7 @@ function useFilterVariablesInScope( function disabledButtonStyles(disabled: boolean): React.CSSProperties { return { - opacity: disabled ? 0.5 : 1, + opacity: disabled ? 0.3 : 1, cursor: disabled ? undefined : 'pointer', } } @@ -474,3 +487,27 @@ function getVariableInScope( } return findOption(variablesInScope) } + +function useAltKeyPressed(): boolean { + const [altKeyPressed, setAltKeyPressed] = React.useState(false) + React.useEffect(() => { + function handleKeyDown(e: KeyboardEvent) { + if (e.key === 'Alt') { + setAltKeyPressed(true) + } + } + function handleKeyUp(e: KeyboardEvent) { + if (e.key === 'Alt') { + setAltKeyPressed(false) + } + } + window.addEventListener('keydown', handleKeyDown) + window.addEventListener('keyup', handleKeyUp) + return function cleanup() { + window.removeEventListener('keydown', handleKeyDown) + window.removeEventListener('keyup', handleKeyUp) + } + }, []) + + return altKeyPressed +} diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts index a50b0192d7cd..1b9427c83d9d 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.spec.ts @@ -36,7 +36,6 @@ describe('orderVariablesForRelevance', () => { controlDescription, currentPropertyValue, targetPropertyName, - 'all', ) expect(actualResult).toMatchInlineSnapshot(` Array [ @@ -123,7 +122,6 @@ describe('orderVariablesForRelevance', () => { controlDescription, currentPropertyValue, targetPropertyName, - 'all', ) expect(actualResult).toMatchInlineSnapshot(` Array [ diff --git a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts index eb86b48d7a67..d3aa2d1a142d 100644 --- a/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts +++ b/editor/src/components/inspector/sections/component-section/variables-in-scope-utils.ts @@ -7,7 +7,7 @@ import type { import type { ElementPath, PropertyPath } from '../../../../core/shared/project-file-types' import type { FileRootPath, VariableData, VariablesInScope } from '../../../canvas/ui-jsx-canvas' import { useEditorState, Substores } from '../../../editor/store/store-hook' -import type { DataPickerFilterOption, DataPickerOption } from './data-picker-utils' +import type { DataPickerOption } from './data-picker-utils' import * as EP from '../../../../core/shared/element-path' import * as PP from '../../../../core/shared/property-path' import React from 'react' @@ -343,7 +343,6 @@ export function orderVariablesForRelevance( controlDescription: ControlDescription | null, currentPropertyValue: PropertyValue, targetPropertyName: string | null, - mode: DataPickerFilterOption, ): Array { let valuesExactlyMatchingPropertyName: Array = [] let valuesExactlyMatchingPropertyDescription: Array = [] @@ -359,7 +358,6 @@ export function orderVariablesForRelevance( controlDescription, currentPropertyValue, targetPropertyName, - mode, ) } else if (variable.type === 'object') { variable.props = orderVariablesForRelevance( @@ -367,7 +365,6 @@ export function orderVariablesForRelevance( controlDescription, currentPropertyValue, targetPropertyName, - mode, ) } @@ -479,7 +476,6 @@ const keepLocalestScope = export function useVariablesInScopeForSelectedElement( elementPath: ElementPath | null, propertyPath: PropertyPath | null, - mode: DataPickerFilterOption, ): Array { const variablesInScope = useEditorState( Substores.restOfEditor, @@ -512,7 +508,6 @@ export function useVariablesInScopeForSelectedElement( } variablesInScopeForSelectedPath = [ - mode === 'preferred' ? keepLocalestScope() : identity, filterKeyFromObject('className'), filterKeyFromObject('data-uid'), filterKeyFromObject('style'), @@ -530,7 +525,6 @@ export function useVariablesInScopeForSelectedElement( controlDescriptions, currentPropertyValue, propertyPath == null ? null : '' + PP.lastPart(propertyPath), - mode, ) return orderedVariablesInScope.flatMap((variable) => @@ -543,7 +537,7 @@ export function useVariablesInScopeForSelectedElement( false, ), ) - }, [controlDescriptions, currentPropertyValue, mode, elementPath, variablesInScope, propertyPath]) + }, [controlDescriptions, currentPropertyValue, elementPath, variablesInScope, propertyPath]) return variableNamesInScope } diff --git a/editor/src/components/inspector/sections/data-reference-section.tsx b/editor/src/components/inspector/sections/data-reference-section.tsx index 267b64aad3f6..e028579bd7a4 100644 --- a/editor/src/components/inspector/sections/data-reference-section.tsx +++ b/editor/src/components/inspector/sections/data-reference-section.tsx @@ -13,7 +13,6 @@ import { getTextContentOfElement, } from './component-section/data-reference-cartouche' import { useDataPickerButton } from './component-section/component-section' -import { DataPickerPreferredAllAtom } from './component-section/data-picker-popup' import { useAtom } from 'jotai' import * as EP from '../../../core/shared/element-path' import { useDispatch } from '../../editor/store/dispatch-context' @@ -36,8 +35,6 @@ export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[ const dataPickerWrapperRef = React.useRef(null) - const [preferredAllState] = useAtom(DataPickerPreferredAllAtom) - const [elementPathForDataPicker, setElementPathForDataPicker] = React.useState(null) @@ -86,7 +83,6 @@ export const DataReferenceSection = React.memo(({ paths }: { paths: ElementPath[ const varsInScope = useVariablesInScopeForSelectedElement( elementPathForDataPicker, PP.create('children'), - preferredAllState, ) const pathToCurrenlySelectedValue = React.useMemo(() => { diff --git a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx index dcbc2875114d..b7c172d3c1f9 100644 --- a/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx +++ b/editor/src/components/inspector/sections/layout-section/list-source-cartouche.tsx @@ -15,10 +15,7 @@ import { useDispatch } from '../../../editor/store/dispatch-context' import type { JSExpressionOtherJavaScript } from '../../../../core/shared/element-template' import { replaceElementInScope } from '../../../editor/actions/action-creators' import { useAtom } from 'jotai' -import { - DataPickerPreferredAllAtom, - jsxElementChildToValuePath, -} from '../component-section/data-picker-utils' +import { jsxElementChildToValuePath } from '../component-section/data-picker-utils' import { getCartoucheDataTypeForExpression, useVariablesInScopeForSelectedElement, @@ -89,13 +86,7 @@ const MapListSourceCartoucheInner = React.memo( [dispatch, target], ) - const [preferredAllState] = useAtom(DataPickerPreferredAllAtom) - - const variableNamesInScope = useVariablesInScopeForSelectedElement( - target, - null, - preferredAllState, - ) + const variableNamesInScope = useVariablesInScopeForSelectedElement(target, null) const pathToMappedExpression = React.useMemo( () => diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 3f9dcfe41525..f2c5d6fd48a7 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -637,13 +637,6 @@ Array [ "/UtopiaSpiedExoticType(Symbol(react.fragment))/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)/div", "/Symbol(react.provider)///Symbol(react.memo)(Inspector)", "/Symbol(react.provider)///Symbol(react.memo)()", - "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(Symbol(react.forward_ref)())", - "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(PropertyLabelAndPlusButton)", - "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(PropertyLabel)", - "/null/RowForControl/RowForBaseControl/Symbol(react.memo)(ControlForProp)", - "/null/RowForControl/RowForBaseControl/div", - "/null/RowForControl/RowForBaseControl/Symbol(react.forward_ref)(UIGridRow)", - "/null/RowForControl/RowForBaseControl/UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", ] `; diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index d6a02f3dbd66..31c0dcba0a9c 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`642`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`635`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From 6a8fa26bf1a11162ed7242388581fdf9ce172c3c Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:54:25 +0200 Subject: [PATCH 089/103] Reparenting out from a scene should have low fitness (#5950) **Problem:** Reparenting out from a scene is risky. If your component/element depends on anything from the context (e.g. a remix loader), then reparenting it out from the scene will certainly cause issues. See e.g. this issue: https://github.com/concrete-utopia/utopia/issues/5915 The worst part is the an exception happens even during mid-interaction, so you don't even have to drop the element to the storyboard, it is enough to temporarily drag it over that. **Fix:** The best would be to detect when the dragged elements depend on the scope and cause problems when dragged into a different context. However, until then, as a heuristic, it seems useful to decrease the fitness of the reparent strategy when you drag the element out from its scene. So the move and reorder strategies will be the default, and you really have to manually select the reparent strategy to force it. This also fixes the problem of an automatic mid-interaction crash. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes https://github.com/concrete-utopia/utopia/issues/5915 --------- Co-authored-by: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> --- .../canvas-strategies.spec.browser2.tsx | 54 --------------- ...solute-reparent-strategy.spec.browser2.tsx | 67 ++++++++++++++---- ...rag-to-move-metastrategy.spec.browser2.tsx | 68 +------------------ .../reparent-strategy-helpers.ts | 25 +++++++ .../strategies/reparent-metastrategy.tsx | 21 ++++-- .../remix/remix-rendering.spec.browser2.tsx | 14 ++++ .../src/core/model/element-metadata-utils.ts | 14 ++++ 7 files changed, 120 insertions(+), 143 deletions(-) diff --git a/editor/src/components/canvas/canvas-strategies/canvas-strategies.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/canvas-strategies.spec.browser2.tsx index da0bed1a91b7..3239dcd9cee1 100644 --- a/editor/src/components/canvas/canvas-strategies/canvas-strategies.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/canvas-strategies.spec.browser2.tsx @@ -273,60 +273,6 @@ describe('Strategy Fitness', () => { const canvasStrategy = renderResult.getEditorState().strategyState.currentStrategy expect(canvasStrategy).toEqual('FLEX_REORDER') }) - it('fits Flex Reparent to Absolute Strategy when cmd-dragging a flex element with siblings the cursor is outside of the parent', async () => { - const targetElement = elementPath([ - ['utopia-storyboard-uid', 'scene-aaa', 'app-entity'], - ['aaa', 'bbb'], - ]) - - const renderResult = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(` -
-
-
-
- `), - 'await-first-dom-report', - ) - - await act(async () => { - const dispatchDone = renderResult.getDispatchFollowUpActionsFinished() - await renderResult.dispatch([selectComponents([targetElement], false)], false) - await dispatchDone - }) - - const interactionSession: InteractionSession = { - ...createMouseInteractionForTests( - canvasPoint({ x: 10, y: 10 }), - cmdModifier, - boundingArea(), - canvasPoint({ x: -25, y: -25 }), - ), - latestMetadata: renderResult.getEditorState().editor.jsxMetadata, - latestAllElementProps: renderResult.getEditorState().editor.allElementProps, - latestElementPathTree: renderResult.getEditorState().editor.elementPathTree, - latestVariablesInScope: renderResult.getEditorState().editor.variablesInScope, - } - - const canvasStrategy = findCanvasStrategy( - RegisteredCanvasStrategies, - pickCanvasStateFromEditorState( - renderResult.getEditorState().editor, - renderResult.getEditorState().builtInDependencies, - ), - interactionSession, - defaultCustomStrategyState(), - null, - ) - - expect(canvasStrategy.strategy?.strategy.id).toEqual('FLEX_REPARENT_TO_ABSOLUTE') - }) it('fits Absolute Resize Strategy when resizing an absolute element without modifiers', async () => { const targetElement = elementPath([ ['utopia-storyboard-uid', 'scene-aaa', 'app-entity'], diff --git a/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-strategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-strategy.spec.browser2.tsx index ca2440979e27..8fdb02a89c2d 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-strategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/absolute-reparent-strategy.spec.browser2.tsx @@ -58,6 +58,7 @@ import { selectComponentsForTest, wait, } from '../../../../utils/utils.test-utils' +import CanvasActions from '../../canvas-actions' interface CheckCursor { cursor: CSSCursor | null @@ -321,6 +322,11 @@ describe('Absolute Reparent Strategy', () => { const dragDelta = windowPoint({ x: -1000, y: -1000 }) await dragElement(renderResult, 'bbb', dragDelta, cmdModifier, null, async () => { + await renderResult.dispatch( + [CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], + true, + ) + expect(getRegularNavigatorTargets(renderResult)).toEqual([ 'utopia-storyboard-uid/scene-aaa', 'utopia-storyboard-uid/scene-aaa/app-entity', @@ -392,8 +398,12 @@ describe('Absolute Reparent Strategy', () => { ) const dragDelta = windowPoint({ x: 400, y: 400 }) - await dragElement(renderResult, 'bbb', dragDelta, cmdModifier, null, null) - await dragElement(renderResult, 'ccc', dragDelta, cmdModifier, null, null) + await dragElement(renderResult, 'bbb', dragDelta, cmdModifier, null, async () => + renderResult.dispatch([CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], true), + ) + await dragElement(renderResult, 'ccc', dragDelta, cmdModifier, null, async () => + renderResult.dispatch([CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], true), + ) await renderResult.getDispatchFollowUpActionsFinished() @@ -458,7 +468,9 @@ describe('Absolute Reparent Strategy', () => { ) const dragDelta = windowPoint({ x: -1000, y: -1000 }) - await dragElement(renderResult, 'bbb', dragDelta, cmdModifier, null, null) + await dragElement(renderResult, 'bbb', dragDelta, cmdModifier, null, async () => + renderResult.dispatch([CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], true), + ) await renderResult.getDispatchFollowUpActionsFinished() @@ -540,7 +552,9 @@ export var ${BakedInStoryboardVariableName} = (props) => { ) const dragDelta = windowPoint({ x: -1000, y: -1000 }) - await dragElement(renderResult, 'bbb', dragDelta, emptyModifiers, null, null) + await dragElement(renderResult, 'bbb', dragDelta, emptyModifiers, null, async () => + renderResult.dispatch([CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], true), + ) await renderResult.getDispatchFollowUpActionsFinished() @@ -902,14 +916,13 @@ export var ${BakedInStoryboardVariableName} = (props) => { x: dragHereCenter.x - dragMeCenter.x, y: dragHereCenter.y - dragMeCenter.y, }) - await dragElement( - editor, - 'drag-me', - dragDelta, - cmdModifier, - { cursor: CSSCursor.NotPermitted }, // checks that we show that it's not permitted - null, - ) + + await dragElement(editor, 'drag-me', dragDelta, cmdModifier, null, async () => { + await editor.dispatch([CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], true) + expect(getCursorFromEditor(await editor.getEditorState().editor)).toEqual( + CSSCursor.NotPermitted, // checks that we show that it's not permitted + ) + }) // the drag is prevented, nothing changes expect(getPrintedUiJsCode(editor.getEditorState())).toEqual(ProjectWithNestedComponents) @@ -960,7 +973,9 @@ export var ${BakedInStoryboardVariableName} = (props) => { ) const dragDelta = windowPoint({ x: -1000, y: -1000 }) - await dragElement(renderResult, 'bbb', dragDelta, cmdModifier, null, null) + await dragElement(renderResult, 'bbb', dragDelta, cmdModifier, null, async () => + renderResult.dispatch([CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], true), + ) await renderResult.getDispatchFollowUpActionsFinished() @@ -1351,7 +1366,11 @@ export var ${BakedInStoryboardVariableName} = (props) => { dragDelta, cmdModifier, null, - null, + async () => + renderResult.dispatch( + [CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], + true, + ), ) await renderResult.getDispatchFollowUpActionsFinished() @@ -1429,7 +1448,11 @@ export var ${BakedInStoryboardVariableName} = (props) => { dragDelta, cmdModifier, null, - null, + async () => + renderResult.dispatch( + [CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], + true, + ), ) await renderResult.getDispatchFollowUpActionsFinished() @@ -1730,6 +1753,13 @@ export var ${BakedInStoryboardVariableName} = (props) => { canvasControlsLayer, { x: dragme.x + 10, y: dragme.y + 10 }, { x: -100, y: 0 }, + { + midDragCallback: async () => + renderResult.dispatch( + [CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], + true, + ), + }, ) expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( @@ -1778,6 +1808,13 @@ export var ${BakedInStoryboardVariableName} = (props) => { canvasControlsLayer, { x: dragme.x + 10, y: dragme.y + 10 }, { x: -100, y: 0 }, + { + midDragCallback: async () => + renderResult.dispatch( + [CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], + true, + ), + }, ) expect(getPrintedUiJsCode(renderResult.getEditorState())).toEqual( diff --git a/editor/src/components/canvas/canvas-strategies/strategies/drag-to-move-metastrategy.spec.browser2.tsx b/editor/src/components/canvas/canvas-strategies/strategies/drag-to-move-metastrategy.spec.browser2.tsx index a841d3080f4a..3c393c072643 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/drag-to-move-metastrategy.spec.browser2.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/drag-to-move-metastrategy.spec.browser2.tsx @@ -1,5 +1,6 @@ import { windowPoint } from '../../../../core/shared/math-utils' import { cmdModifier, emptyModifiers } from '../../../../utils/modifiers' +import CanvasActions from '../../canvas-actions' import { CanvasControlsContainerID } from '../../controls/new-canvas-controls' import { mouseClickAtPoint, mouseDragFromPointWithDelta } from '../../event-helpers.test-utils' import { makeTestProjectCodeWithSnippet, renderTestEditorWithCode } from '../../ui-jsx.test-utils' @@ -86,37 +87,6 @@ describe('Drag To Move Metastrategy', () => { expect(doNothingInSortedStrategies).toEqual(-1) } - await mouseClickAtPoint(canvasControlsLayer, startPoint, { modifiers: cmdModifier }) - await mouseDragFromPointWithDelta(canvasControlsLayer, startPoint, dragDelta, { - modifiers: emptyModifiers, - midDragCallback: midDragCallback, - }) - }) - it('when a reparent strategy is active, the fallback DO_NOTHING strategy is not applicable', async () => { - const renderResult = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(TestProject2), - 'await-first-dom-report', - ) - - const targetElement = renderResult.renderedDOM.getByTestId('child-1') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = windowPoint({ x: targetElementBounds.x + 5, y: targetElementBounds.y + 5 }) - const dragDelta = windowPoint({ x: -100, y: -100 }) - - const midDragCallback = async () => { - const strategies = renderResult.getEditorState().strategyState.sortedApplicableStrategies - const doNothingInSortedStrategies = strategies?.findIndex( - (strategy) => strategy.name === 'DO_NOTHING', - ) - - expect(renderResult.getEditorState().strategyState.currentStrategy).toEqual( - 'FLEX_REPARENT_TO_ABSOLUTE', - ) - expect(doNothingInSortedStrategies).toEqual(-1) - } - await mouseClickAtPoint(canvasControlsLayer, startPoint, { modifiers: cmdModifier }) await mouseDragFromPointWithDelta(canvasControlsLayer, startPoint, dragDelta, { modifiers: emptyModifiers, @@ -160,42 +130,6 @@ describe('Drag To Move Strategy Indicator', () => { midDragCallback: midDragCallback, }) }) - it('when reparenting an element the Strategy Indicator is visible', async () => { - const renderResult = await renderTestEditorWithCode( - makeTestProjectCodeWithSnippet(TestProject1), - 'await-first-dom-report', - ) - - const targetElement = renderResult.renderedDOM.getByTestId('child-1') - const targetElementBounds = targetElement.getBoundingClientRect() - const canvasControlsLayer = renderResult.renderedDOM.getByTestId(CanvasControlsContainerID) - - const startPoint = windowPoint({ x: targetElementBounds.x + 5, y: targetElementBounds.y + 5 }) - const dragDelta = windowPoint({ x: -50, y: 0 }) // moving it to the empty canvas - - const midDragCallback = async () => { - expect(renderResult.getEditorState().strategyState.currentStrategy).toEqual( - 'FLEX_REPARENT_TO_ABSOLUTE', - ) - expect( - renderResult.getEditorState().editor.canvas.controls.dragToMoveIndicatorFlags.showIndicator, - ).toEqual(true) - expect( - renderResult.getEditorState().editor.canvas.controls.dragToMoveIndicatorFlags.ancestor, - ).toEqual(false) - expect( - renderResult.getEditorState().editor.canvas.controls.dragToMoveIndicatorFlags.reparent, - ).toEqual('different-component') - const indicator = renderResult.renderedDOM.getByTestId('drag-strategy-indicator') - expect(indicator).toBeDefined() - } - - await mouseClickAtPoint(canvasControlsLayer, startPoint, { modifiers: cmdModifier }) - await mouseDragFromPointWithDelta(canvasControlsLayer, startPoint, dragDelta, { - modifiers: emptyModifiers, - midDragCallback: midDragCallback, - }) - }) it('when reordering an element the Strategy Indicator is visible', async () => { const renderResult = await renderTestEditorWithCode( makeTestProjectCodeWithSnippet(TestProject2), diff --git a/editor/src/components/canvas/canvas-strategies/strategies/reparent-helpers/reparent-strategy-helpers.ts b/editor/src/components/canvas/canvas-strategies/strategies/reparent-helpers/reparent-strategy-helpers.ts index bef0a6cc6005..3184a5e6e90f 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/reparent-helpers/reparent-strategy-helpers.ts +++ b/editor/src/components/canvas/canvas-strategies/strategies/reparent-helpers/reparent-strategy-helpers.ts @@ -17,6 +17,7 @@ import type { InsertionPath } from '../../../../editor/store/insertion-path' import type { ElementPathTrees } from '../../../../../core/shared/element-path-tree' import { assertNever } from '../../../../../core/shared/utils' import { PropertyControlsInfo } from '../../../../custom-code/code-file' +import * as EP from '../../../../../core/shared/element-path' export type ReparentAsAbsolute = 'REPARENT_AS_ABSOLUTE' export type ReparentAsStatic = 'REPARENT_AS_STATIC' @@ -25,6 +26,7 @@ export type ReparentStrategy = ReparentAsAbsolute | ReparentAsStatic export type FindReparentStrategyResult = { strategy: ReparentStrategy isFallback: boolean + isReparentingOutFromScene: boolean target: ReparentTarget } @@ -76,14 +78,22 @@ export function findReparentStrategies( return [] } + const isOutFromScene = isReparentingOutFromScene( + reparentSubjects, + canvasState.startingMetadata, + targetParent.newParent.intendedParentPath, + ) + const strategy = { target: targetParent, + isReparentingOutFromScene: isOutFromScene, strategy: targetParent.defaultReparentType, isFallback: false, } const fallbackStrategy: FindReparentStrategyResult = { isFallback: true, + isReparentingOutFromScene: isOutFromScene, target: strategy.target, strategy: strategy.strategy === 'REPARENT_AS_ABSOLUTE' @@ -158,3 +168,18 @@ export function reparentSubjectsForInteractionTarget( throw new Error(`Unhandled interaction target type ${JSON.stringify(interactionTarget)}`) } } + +function isReparentingOutFromScene( + reparentSubjects: ReparentSubjects, + metadata: ElementInstanceMetadataMap, + targetParent: ElementPath, +) { + const reparentSubjectScenes = + reparentSubjects.type === 'EXISTING_ELEMENTS' + ? reparentSubjects.elements.map((s) => MetadataUtils.findSceneOfTarget(s, metadata)) + : [] + + const reparentTargetScene = MetadataUtils.findSceneOfTarget(targetParent, metadata) + + return reparentSubjectScenes.some((s) => !EP.pathsEqual(s, reparentTargetScene)) +} diff --git a/editor/src/components/canvas/canvas-strategies/strategies/reparent-metastrategy.tsx b/editor/src/components/canvas/canvas-strategies/strategies/reparent-metastrategy.tsx index cd7b8b96c523..b1a414c5c26f 100644 --- a/editor/src/components/canvas/canvas-strategies/strategies/reparent-metastrategy.tsx +++ b/editor/src/components/canvas/canvas-strategies/strategies/reparent-metastrategy.tsx @@ -47,6 +47,7 @@ interface ReparentFactoryAndDetails { const DefaultReparentWeight = 4 const FallbackReparentWeight = DefaultReparentWeight - 1 const FlowReparentWeight = FallbackReparentWeight - 1 +const OutOfSceneReparentWeight = FlowReparentWeight - 1 export function getApplicableReparentFactories( canvasState: InteractionCanvasState, @@ -68,7 +69,12 @@ export function getApplicableReparentFactories( const factories: Array = reparentStrategies.map((result) => { switch (result.strategy) { case 'REPARENT_AS_ABSOLUTE': { - const fitness = result.isFallback ? FallbackReparentWeight : DefaultReparentWeight + const fitness = result.isReparentingOutFromScene + ? OutOfSceneReparentWeight + : result.isFallback + ? FallbackReparentWeight + : DefaultReparentWeight + if (allDraggedElementsAbsolute) { return { targetParent: result.target.newParent, @@ -100,12 +106,13 @@ export function getApplicableReparentFactories( const targetParentDisplayType = parentLayoutSystem === 'flex' ? 'flex' : 'flow' // We likely never want flow insertion or re-parenting to be the default - const fitness = - targetParentDisplayType === 'flow' - ? FlowReparentWeight - : result.isFallback - ? FallbackReparentWeight - : DefaultReparentWeight + const fitness = result.isReparentingOutFromScene + ? OutOfSceneReparentWeight + : targetParentDisplayType === 'flow' + ? FlowReparentWeight + : result.isFallback + ? FallbackReparentWeight + : DefaultReparentWeight return { targetParent: result.target.newParent, diff --git a/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx b/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx index ad74cb4475ee..7e9b390d3498 100644 --- a/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx +++ b/editor/src/components/canvas/remix/remix-rendering.spec.browser2.tsx @@ -60,6 +60,7 @@ import { type MetaCanvasStrategy, RegisteredCanvasStrategies, } from '../canvas-strategies/canvas-strategies' +import CanvasActions from '../canvas-actions' const DefaultRouteTextContent = 'Hello Remix!' const RootTextContent = 'This is root!' @@ -2123,10 +2124,17 @@ export default function Index() { AbsoluteDivTestId, ) const absoluteDivBounds = absoluteElement.getBoundingClientRect() + await dragMouse( renderResult, windowPoint({ x: absoluteDivBounds.x + 1, y: absoluteDivBounds.y + 1 }), windowPoint({ x: 10, y: -77 }), + emptyModifiers, + async () => + renderResult.dispatch( + [CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], + true, + ), ) } @@ -2155,6 +2163,12 @@ export default function Index() { renderResult, windowPoint({ x: absoluteDivBounds.x + 1, y: absoluteDivBounds.y + 1 }), windowPoint({ x: -10, y: 77 }), + emptyModifiers, + async () => + renderResult.dispatch( + [CanvasActions.setUsersPreferredStrategy('ABSOLUTE_REPARENT')], + true, + ), ) } diff --git a/editor/src/core/model/element-metadata-utils.ts b/editor/src/core/model/element-metadata-utils.ts index d177d69d0274..e093c90c5912 100644 --- a/editor/src/core/model/element-metadata-utils.ts +++ b/editor/src/core/model/element-metadata-utils.ts @@ -2525,6 +2525,20 @@ export const MetadataUtils = { assertNever(element) } }, + + findSceneOfTarget(target: ElementPath, metadata: ElementInstanceMetadataMap): ElementPath | null { + if ( + MetadataUtils.isProbablyScene(metadata, target) || + MetadataUtils.isProbablyRemixScene(metadata, target) + ) { + return target + } + const parent = EP.parentPath(target) + if (EP.isEmptyPath(parent)) { + return null + } + return MetadataUtils.findSceneOfTarget(parent, metadata) + }, } function getNonExpressionDescendantsInner( From 8941903d59fcab004e0eda7fa1d324e30182d920 Mon Sep 17 00:00:00 2001 From: Liad Yosef Date: Mon, 17 Jun 2024 09:59:28 +0200 Subject: [PATCH 090/103] Assign min width to code pane (#5890) **Problem:** Currently we can resize the code pane to be width 0, which makes it harder to restore **Fix:** Define min width for `Pane`, similar to `GridMenu` **Manual Tests:** I hereby swear that: - [X] I opened a hydrogen project and it loaded - [X] I could navigate to various routes in Preview mode Fixes #5876 (this was the chosen fix for it) --- editor/src/components/canvas/grid-panels-state.tsx | 5 ++++- editor/src/components/canvas/stored-layout.ts | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/editor/src/components/canvas/grid-panels-state.tsx b/editor/src/components/canvas/grid-panels-state.tsx index e709069f3dd4..d8b0f7812c8d 100644 --- a/editor/src/components/canvas/grid-panels-state.tsx +++ b/editor/src/components/canvas/grid-panels-state.tsx @@ -18,6 +18,7 @@ import type { import { GridMenuMaxWidth, GridMenuMinWidth, + GridPaneMinWidth, GridPanelsNumberOfRows, IndexOfCanvas, NumberOfColumns, @@ -340,7 +341,9 @@ export function useColumnWidths(): [ }) } else { // pane resize! - return immutableUpdate(current, { [columnIndex]: { paneWidth: { $set: newWidth } } }) + return immutableUpdate(current, { + [columnIndex]: { paneWidth: { $set: Math.max(newWidth, GridPaneMinWidth) } }, + }) } }) }, diff --git a/editor/src/components/canvas/stored-layout.ts b/editor/src/components/canvas/stored-layout.ts index 4b7d3fd4e0d4..6c8b7139b558 100644 --- a/editor/src/components/canvas/stored-layout.ts +++ b/editor/src/components/canvas/stored-layout.ts @@ -5,6 +5,7 @@ export const GridMenuMinWidth = 200 export const GridMenuMaxWidth = 500 export const GridPaneWidth = 500 +export const GridPaneMinWidth = 100 export const NumberOfColumns = 4 export const IndexOfCanvas = 2 From 44dbd3ee2bd5d6d7be6cec8153590ee0d2cb2ea3 Mon Sep 17 00:00:00 2001 From: McKayla Lankau Date: Mon, 17 Jun 2024 04:03:35 -0400 Subject: [PATCH 091/103] Data Picker Style Adjustments (#5954) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removing some borders, adjusting padding, and font styles, scrollbar colors, etc. in the data picker Before: Screenshot 2024-06-14 at 3 22 32 PM After: Screenshot 2024-06-14 at 3 18 59 PM Co-authored-by: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> --- .../component-section/data-selector-columns.tsx | 15 ++++++++------- .../data-selector-left-sidebar.tsx | 9 ++++----- .../component-section/data-selector-modal.tsx | 8 +++----- .../component-section/data-selector-search.tsx | 11 +++++++++-- .../navigator/navigator-item/component-picker.tsx | 2 +- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx index 71e46d678517..01b190441d36 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -23,7 +23,7 @@ export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) overflowX: 'scroll', overflowY: 'hidden', scrollbarWidth: 'auto', - scrollbarColor: 'gray transparent', + scrollbarColor: `${colorTheme.subduedBorder.cssValue} transparent`, }} > { const text = safeJSONStringify(props.data.variableInfo.value) const ref = useScrollIntoView(true) return ( - +
{text}
- {variableTypeForInfo(props.data)} + {variableTypeForInfo(props.data)}
) }) @@ -242,7 +243,7 @@ const DataSelectorFlexColumn = styled(FlexColumn)({ overflowX: 'hidden', overflowY: 'scroll', scrollbarWidth: 'auto', - scrollbarColor: 'gray transparent', + scrollbarColor: `${colorTheme.subduedBorder.cssValue} transparent`, paddingTop: 8, paddingBottom: 10, borderRight: `1px solid ${colorTheme.subduedBorder.cssValue}`, diff --git a/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx b/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx index 309caeb267e1..571a1c13097a 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-left-sidebar.tsx @@ -28,12 +28,11 @@ export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSideba onClick={stopPropagation} style={{ alignSelf: 'stretch', - minWidth: 150, - paddingLeft: 16, - paddingTop: 8, - paddingRight: 8, + minWidth: 120, + padding: 16, borderRight: `1px solid ${colorTheme.subduedBorder.cssValue}`, contain: 'layout', + gap: 8, }} > Sources @@ -52,7 +51,7 @@ export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSideba - + {searchNullOrEmpty ? ( @@ -307,7 +306,6 @@ export const DataSelectorModal = React.memo( justifyContent: 'space-between', alignItems: 'center', gap: 8, - borderTop: `1px solid ${colorTheme.subduedBorder.cssValue}`, paddingTop: 10, paddingBottom: 10, paddingRight: 16, diff --git a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx index c8e8b7256ff6..cf51927ce3a8 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-search.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-search.tsx @@ -2,7 +2,14 @@ import throttle from 'lodash.throttle' import React from 'react' import { memoize } from '../../../../core/shared/memoize' import { assertNever } from '../../../../core/shared/utils' -import { FlexColumn, FlexRow, Icons, SmallerIcons, UtopiaStyles } from '../../../../uuiui' +import { + FlexColumn, + FlexRow, + Icons, + SmallerIcons, + UtopiaStyles, + colorTheme, +} from '../../../../uuiui' import { type DataPickerOption, type ObjectPath } from './data-picker-utils' import { DataPickerCartouche, useVariableDataSource } from './data-selector-cartouche' import { when } from '../../../../utils/react-conditionals' @@ -38,7 +45,7 @@ export const DataSelectorSearch = React.memo( overflowX: 'hidden', overflowY: 'scroll', scrollbarWidth: 'auto', - scrollbarColor: 'gray transparent', + scrollbarColor: `${colorTheme.subduedBorder.cssValue} transparent`, flexGrow: 1, gap: 8, paddingTop: 8, diff --git a/editor/src/components/navigator/navigator-item/component-picker.tsx b/editor/src/components/navigator/navigator-item/component-picker.tsx index 7f4933357eb0..b050e167b14c 100644 --- a/editor/src/components/navigator/navigator-item/component-picker.tsx +++ b/editor/src/components/navigator/navigator-item/component-picker.tsx @@ -466,7 +466,7 @@ const ComponentPickerComponentSection = React.memo( maxHeight: 250, overflowY: 'scroll', scrollbarWidth: 'auto', - scrollbarColor: 'gray transparent', + scrollbarColor: `${colorTheme.subduedBorder.cssValue} transparent`, }} onScroll={onScroll} > From 74072610b5feaf6c6da34a66c5510e42246edce6 Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 17 Jun 2024 10:28:48 +0200 Subject: [PATCH 092/103] Fix navigator hint lines indentation (#5948) **Problem:** Navigator drag and drop hints are not always indented correctly. **Fix:** Use the row/item's `indentation` prop directly, and remove outdated code. Before/after: https://github.com/concrete-utopia/utopia/assets/1081051/aa022f06-af30-4ce7-a17b-77047723fe89 **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5938 --- .../navigator-conditionals.spec.browser2.tsx | 473 +++++++++--------- .../navigator/navigator-drag-layer.tsx | 22 +- .../navigator-item-dnd-container.tsx | 28 +- .../navigator-item/navigator-item-wrapper.tsx | 10 - .../components/navigator/navigator-utils.ts | 50 +- 5 files changed, 261 insertions(+), 322 deletions(-) diff --git a/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx b/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx index 48cf0211e17d..2df5e397af65 100644 --- a/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx +++ b/editor/src/components/navigator/navigator-conditionals.spec.browser2.tsx @@ -65,7 +65,7 @@ import { DragItemTestId, TopDropTargetLineTestId, } from './navigator-item/navigator-item-dnd-container' -import { navigatorDepth } from './navigator-utils' +import { getEntriesForRow } from './navigator-row' const ASYNC_NOOP = async () => NO_OP() @@ -524,7 +524,10 @@ function navigatorStructure(editorState: EditorState, deriveState: DerivedState) const lines = deriveState.visibleNavigatorTargets.map((target) => { const targetAsText = navigatorEntryToKey(target) let prefix: string = '' - const depth = navigatorDepth(target, editorState.jsxMetadata) + const depth = + deriveState.navigatorRows.find((row) => + EP.pathsEqual(getEntriesForRow(row)[0].elementPath, target.elementPath), + )?.indentation ?? 0 for (let index = 0; index < depth; index++) { prefix = prefix.concat(' ') } @@ -612,36 +615,36 @@ describe('conditionals in the navigator', () => { getProjectCodeTree(), 'await-first-dom-report', ) - const want = ` regular-utopia-storyboard-uid/aaa - regular-utopia-storyboard-uid/cond1 - conditional-clause-utopia-storyboard-uid/cond1-true-case - regular-utopia-storyboard-uid/cond1/bbb - conditional-clause-utopia-storyboard-uid/cond1-false-case - synthetic-utopia-storyboard-uid/cond1/d84-attribute - regular-utopia-storyboard-uid/ccc - regular-utopia-storyboard-uid/ccc/ddd - regular-utopia-storyboard-uid/ccc/cond2 - conditional-clause-utopia-storyboard-uid/ccc/cond2-true-case - regular-utopia-storyboard-uid/ccc/cond2/eee - regular-utopia-storyboard-uid/ccc/cond2/eee/cond3 - conditional-clause-utopia-storyboard-uid/ccc/cond2/eee/cond3-true-case - regular-utopia-storyboard-uid/ccc/cond2/eee/cond3/fff - conditional-clause-utopia-storyboard-uid/ccc/cond2/eee/cond3-false-case - synthetic-utopia-storyboard-uid/ccc/cond2/eee/cond3/019-attribute - regular-utopia-storyboard-uid/ccc/cond2/eee/ggg - conditional-clause-utopia-storyboard-uid/ccc/cond2-false-case - synthetic-utopia-storyboard-uid/ccc/cond2/89b-attribute - regular-utopia-storyboard-uid/cond4 - conditional-clause-utopia-storyboard-uid/cond4-true-case - regular-utopia-storyboard-uid/cond4/hhh - conditional-clause-utopia-storyboard-uid/cond4-false-case - synthetic-utopia-storyboard-uid/cond4/d00-attribute - regular-utopia-storyboard-uid/cond5 - conditional-clause-utopia-storyboard-uid/cond5-true-case - regular-utopia-storyboard-uid/cond5/iii - conditional-clause-utopia-storyboard-uid/cond5-false-case - synthetic-utopia-storyboard-uid/cond5/73a-attribute - regular-utopia-storyboard-uid/jjj` + const want = `regular-utopia-storyboard-uid/aaa +regular-utopia-storyboard-uid/cond1 +conditional-clause-utopia-storyboard-uid/cond1-true-case + regular-utopia-storyboard-uid/cond1/bbb +conditional-clause-utopia-storyboard-uid/cond1-false-case + synthetic-utopia-storyboard-uid/cond1/d84-attribute +regular-utopia-storyboard-uid/ccc + regular-utopia-storyboard-uid/ccc/ddd + regular-utopia-storyboard-uid/ccc/cond2 + conditional-clause-utopia-storyboard-uid/ccc/cond2-true-case + regular-utopia-storyboard-uid/ccc/cond2/eee + regular-utopia-storyboard-uid/ccc/cond2/eee/cond3 + conditional-clause-utopia-storyboard-uid/ccc/cond2/eee/cond3-true-case + regular-utopia-storyboard-uid/ccc/cond2/eee/cond3/fff + conditional-clause-utopia-storyboard-uid/ccc/cond2/eee/cond3-false-case + synthetic-utopia-storyboard-uid/ccc/cond2/eee/cond3/019-attribute + regular-utopia-storyboard-uid/ccc/cond2/eee/ggg + conditional-clause-utopia-storyboard-uid/ccc/cond2-false-case + synthetic-utopia-storyboard-uid/ccc/cond2/89b-attribute +regular-utopia-storyboard-uid/cond4 +conditional-clause-utopia-storyboard-uid/cond4-true-case + regular-utopia-storyboard-uid/cond4/hhh +conditional-clause-utopia-storyboard-uid/cond4-false-case + synthetic-utopia-storyboard-uid/cond4/d00-attribute +regular-utopia-storyboard-uid/cond5 +conditional-clause-utopia-storyboard-uid/cond5-true-case + regular-utopia-storyboard-uid/cond5/iii +conditional-clause-utopia-storyboard-uid/cond5-false-case + synthetic-utopia-storyboard-uid/cond5/73a-attribute +regular-utopia-storyboard-uid/jjj` expect( navigatorStructure( renderResult.getEditorState().editor, @@ -652,18 +655,18 @@ describe('conditionals in the navigator', () => { it('can not drag into a conditional', async () => { const renderResult = await renderTestEditorWithCode(getProjectCode(), 'await-first-dom-report') - const expectedNavigatorStructure = ` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div` + const expectedNavigatorStructure = `regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div` expect( navigatorStructure( @@ -750,18 +753,18 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/019-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/019-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) // Select the entry we plan to drag. const elementPathToDrag = EP.fromString( @@ -823,17 +826,17 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/sibling-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/019-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/sibling-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/019-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div`) expect( getConditionalCaseFromPath( @@ -845,18 +848,18 @@ describe('conditionals in the navigator', () => { it('can reorder to before the conditional', async () => { const renderResult = await renderTestEditorWithCode(getProjectCode(), 'await-first-dom-report') - const expectedNavigatorStructure = ` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div` + const expectedNavigatorStructure = `regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div` expect( navigatorStructure( @@ -927,18 +930,18 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div`) }) it('dragging into an empty inactive clause, takes the place of the empty value and makes it active', async () => { const renderResult = await renderTestEditorWithCode(getProjectCode(), 'await-first-dom-report') @@ -948,18 +951,18 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) // Select the entry we plan to drag. const elementPathToDrag = EP.fromString( @@ -1019,17 +1022,17 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div-element-then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/sibling-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div-element-then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/sibling-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div`) expect( getConditionalCaseFromPath( @@ -1078,18 +1081,18 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) // Select the entry we plan to drag. const elementPathToDrag = EP.fromString( @@ -1166,19 +1169,19 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/${removedOriginalUID}-attribute - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/else-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/${removedOriginalUID}-attribute + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/else-div`) }) it('dragging out of an active clause, replaces with null', async () => { const renderResult = await renderTestEditorWithCode(getProjectCode(), 'await-first-dom-report') @@ -1188,18 +1191,18 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) // Select the entry we plan to drag. const elementPathToDrag = EP.fromString( @@ -1265,19 +1268,19 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/${removedOriginalUID}-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/then-then-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/${removedOriginalUID}-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/d84-attribute + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/then-then-div`) }) it('dragging into child of an active clause, works as it would without the conditional', async () => { const projectCode = getProjectCodeNotEmpty() @@ -1336,14 +1339,14 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/then-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/then-div/sibling-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/then-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/then-div/sibling-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div`) }) it('can select and delete an inactive clause', async () => { const renderResult = await renderTestEditorWithCode(getProjectCode(), 'await-first-dom-report') @@ -1403,14 +1406,14 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-element-conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/${removedOriginalUID}-attribute - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-element-conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/${removedOriginalUID}-attribute + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`) }) it('can be collapsed', async () => { const renderResult = await renderTestEditorWithCode(getProjectCode(), 'await-first-dom-report') @@ -1498,18 +1501,18 @@ describe('conditionals in the navigator', () => { replaceWithSingleElement(), ), expectedToasts: [], - expectedNavigatorStructure: ` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div-element-then-then-div - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/sib - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`, + expectedNavigatorStructure: `regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-true-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/then-then-div-element-then-then-div + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2-false-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/conditional2/sib + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional1-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional1/else-div-element-else-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/sibling-div`, postPasteValidation: ( pasteTestCase: PasteTestCase, startingEditorStore: EditorStorePatched, @@ -1702,19 +1705,19 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~1 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~1/58f - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~2 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~2/58f - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~3 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~3/58f - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional/else-div-element-else-div`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~1 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~1/58f + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~2 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~2/58f + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~3 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/dd4/dbc~~~3/58f + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional/else-div-element-else-div`) }) it('keeps the right order for inlined map expressions with multiple values (null inactive branch)', async () => { const renderResult = await renderTestEditorWithCode( @@ -1727,21 +1730,21 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/505 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/505/7d5~~~1 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/505/7d5~~~2 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/505/7d5~~~3 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional/d84-attribute - regular-utopia-storyboard-uid/scene-aaa/268 - regular-utopia-storyboard-uid/scene-aaa/268/5d1~~~1 - regular-utopia-storyboard-uid/scene-aaa/268/5d1~~~2 - regular-utopia-storyboard-uid/scene-aaa/268/5d1~~~3 - regular-utopia-storyboard-uid/scene-aaa/hey`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/505 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/505/7d5~~~1 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/505/7d5~~~2 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/505/7d5~~~3 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional/d84-attribute +regular-utopia-storyboard-uid/scene-aaa/268 + regular-utopia-storyboard-uid/scene-aaa/268/5d1~~~1 + regular-utopia-storyboard-uid/scene-aaa/268/5d1~~~2 + regular-utopia-storyboard-uid/scene-aaa/268/5d1~~~3 +regular-utopia-storyboard-uid/scene-aaa/hey`) }) it('keeps the right order for inlined map expressions with multiple values (not-null inactive branch)', async () => { const renderResult = await renderTestEditorWithCode( @@ -1754,21 +1757,21 @@ describe('conditionals in the navigator', () => { renderResult.getEditorState().editor, renderResult.getEditorState().derived, ), - ).toEqual(` regular-utopia-storyboard-uid/scene-aaa - regular-utopia-storyboard-uid/scene-aaa/containing-div - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-true-case - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/50c - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/50c/46b~~~1 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/50c/46b~~~2 - regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/50c/46b~~~3 - conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-false-case - synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional/false-branch-element-false-branch - regular-utopia-storyboard-uid/scene-aaa/268 - regular-utopia-storyboard-uid/scene-aaa/268/981~~~1 - regular-utopia-storyboard-uid/scene-aaa/268/981~~~2 - regular-utopia-storyboard-uid/scene-aaa/268/981~~~3 - regular-utopia-storyboard-uid/scene-aaa/hey`) + ).toEqual(`regular-utopia-storyboard-uid/scene-aaa +regular-utopia-storyboard-uid/scene-aaa/containing-div + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-true-case + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/50c + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/50c/46b~~~1 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/50c/46b~~~2 + regular-utopia-storyboard-uid/scene-aaa/containing-div/conditional/50c/46b~~~3 + conditional-clause-utopia-storyboard-uid/scene-aaa/containing-div/conditional-false-case + synthetic-utopia-storyboard-uid/scene-aaa/containing-div/conditional/false-branch-element-false-branch +regular-utopia-storyboard-uid/scene-aaa/268 + regular-utopia-storyboard-uid/scene-aaa/268/981~~~1 + regular-utopia-storyboard-uid/scene-aaa/268/981~~~2 + regular-utopia-storyboard-uid/scene-aaa/268/981~~~3 +regular-utopia-storyboard-uid/scene-aaa/hey`) }) }) }) diff --git a/editor/src/components/navigator/navigator-drag-layer.tsx b/editor/src/components/navigator/navigator-drag-layer.tsx index e940bb76f364..37c960006da0 100644 --- a/editor/src/components/navigator/navigator-drag-layer.tsx +++ b/editor/src/components/navigator/navigator-drag-layer.tsx @@ -1,7 +1,6 @@ import React from 'react' import { useDragLayer } from 'react-dnd' -import type { RegularNavigatorEntry } from '../editor/store/editor-state' -import { navigatorEntryToKey, regularNavigatorEntry } from '../editor/store/editor-state' +import { regularNavigatorEntry } from '../editor/store/editor-state' import { NavigatorItemDragType, type NavigatorItemDragAndDropWrapperProps, @@ -13,18 +12,7 @@ import { NO_OP } from '../../core/shared/utils' import { colorTheme, FlexRow, Icn } from '../../uuiui' import { useLayoutOrElementIcon } from './layout-element-icons' import { emptyElementPath } from '../../core/shared/element-path' -import { Substores, useEditorState } from '../editor/store/store-hook' -import { navigatorDepth } from './navigator-utils' import { getElementPadding } from './navigator-item/navigator-item' -import { metadataSelector } from '../inspector/inpector-selectors' -import createCachedSelector from 're-reselect' -import type { MetadataSubstate } from '../editor/store/store-hook-substore-types' - -const depthSelector = createCachedSelector( - metadataSelector, - (_: MetadataSubstate, navigatorEntry: RegularNavigatorEntry) => navigatorEntry, - (metadata, navigatorEntry) => navigatorDepth(navigatorEntry, metadata) + 1, -)((_, navigatorEntry) => navigatorEntryToKey(navigatorEntry)) export const NavigatorDragLayer = React.memo(() => { const { item, initialOffset, difference } = useDragLayer((monitor) => ({ @@ -43,12 +31,6 @@ export const NavigatorDragLayer = React.memo(() => { const draggedItemIsNavigatorItem = item != null && item.type === NavigatorItemDragType const hidden = !draggedItemIsNavigatorItem - const entryNavigatorDepth = useEditorState( - Substores.metadata, - (store) => depthSelector(store, navigatorEntry), - 'NavigatorDragLayer metadata', - ) - const offset = windowPoint({ x: initialOffset.x + difference.x - (containerRef.current?.getBoundingClientRect()?.x ?? 0), y: initialOffset.y + difference.y - (containerRef.current?.getBoundingClientRect()?.y ?? 0), @@ -73,7 +55,7 @@ export const NavigatorDragLayer = React.memo(() => { > store.editor.navigator.dropTargetHint, - 'NavigatorItemDndWrapper moveToElementPath', + 'NavigatorItemDndWrapper dropTargetHint', ) const navigatorTargets = useEditorState( Substores.derived, (store) => store.derived.navigatorTargets, - 'NavigatorItemDndWrapper moveToElementPath', + 'NavigatorItemDndWrapper navigatorTargets', ) const isFirstSibling = React.useMemo(() => { @@ -795,14 +793,24 @@ export const NavigatorItemContainer = React.memo((props: NavigatorItemDragAndDro !isHintDisallowed(props.elementPath, editorStateRef.current.jsxMetadata) && isCollapsedCondtionalEntry + const navigatorRows = useRefEditorState((store) => store.derived.navigatorRows) + const margin = (() => { if (dropTargetHint == null) { return 0 } - return getHintPaddingForDepth( - navigatorDepth(dropTargetHint.targetParent, editorStateRef.current.jsxMetadata), + const targetRow = navigatorRows.current.find((row) => + isRegulaNavigatorRow(row) + ? EP.pathsEqual(row.entry.elementPath, dropTargetHint.targetParent.elementPath) + : row.entries.some((entry) => + EP.pathsEqual(dropTargetHint.targetParent.elementPath, entry.elementPath), + ), ) + if (targetRow != null) { + return getHintPaddingForDepth(targetRow.indentation) + } + return props.indentation })() const parentOutline = React.useMemo((): ParentOutline => { diff --git a/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx b/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx index aca2551d025e..ffe9becd6407 100644 --- a/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx +++ b/editor/src/components/navigator/navigator-item/navigator-item-wrapper.tsx @@ -37,7 +37,6 @@ import type { PropertyControlsInfoSubstate, } from '../../editor/store/store-hook-substore-types' import { isRegulaNavigatorRow, type NavigatorRow } from '../navigator-row' -import { navigatorDepth } from '../navigator-utils' import type { ConditionalClauseNavigatorItemContainerProps, ErrorNavigatorItemContainerProps, @@ -325,14 +324,6 @@ const SingleEntryNavigatorItemWrapper: React.FunctionComponent< ) const label = getNavigatorEntryLabel(props.navigatorEntry, labelForTheElement) - const entryDepth = useEditorState( - Substores.metadata, - (store) => { - return navigatorDepth(props.navigatorEntry, store.editor.jsxMetadata) - }, - 'NavigatorItemWrapper entryDepth', - ) - const visibleNavigatorTargets = useEditorState( Substores.derived, (store) => store.derived.visibleNavigatorTargets, @@ -380,7 +371,6 @@ const SingleEntryNavigatorItemWrapper: React.FunctionComponent< index: props.index, indentation: props.indentation, editorDispatch: dispatch, - entryDepth: entryDepth, selected: isSelected, highlighted: isHighlighted, collapsed: isCollapsed, diff --git a/editor/src/components/navigator/navigator-utils.ts b/editor/src/components/navigator/navigator-utils.ts index 3c1b91a635e3..78f2579f4e55 100644 --- a/editor/src/components/navigator/navigator-utils.ts +++ b/editor/src/components/navigator/navigator-utils.ts @@ -3,11 +3,8 @@ import * as EP from '../../core/shared/element-path' import type { ElementInstanceMetadata, ElementInstanceMetadataMap, - JSExpression, JSXConditionalExpression, - JSXElement, JSXElementChild, - JSXFragment, JSXMapExpression, } from '../../core/shared/element-template' import { @@ -16,26 +13,16 @@ import { isJSExpressionValue, isJSXConditionalExpression, isJSXElement, - isJSXElementLike, isJSXMapExpression, } from '../../core/shared/element-template' import { MetadataUtils } from '../../core/model/element-metadata-utils' -import { foldEither, isLeft, isRight } from '../../core/shared/either' -import type { - ConditionalClauseNavigatorEntry, - DataReferenceNavigatorEntry, - InvalidOverrideNavigatorEntry, - NavigatorEntry, - RegularNavigatorEntry, - SlotNavigatorEntry, - SyntheticNavigatorEntry, -} from '../editor/store/editor-state' +import { isLeft } from '../../core/shared/either' +import type { ConditionalClauseNavigatorEntry, NavigatorEntry } from '../editor/store/editor-state' import { conditionalClauseNavigatorEntry, dataReferenceNavigatorEntry, getElementFromProjectContents, invalidOverrideNavigatorEntry, - isConditionalClauseNavigatorEntry, regularNavigatorEntry, renderPropNavigatorEntry, renderPropValueNavigatorEntry, @@ -46,7 +33,7 @@ import { } from '../editor/store/editor-state' import type { ElementPathTree, ElementPathTrees } from '../../core/shared/element-path-tree' import { getCanvasRoots, getSubTree } from '../../core/shared/element-path-tree' -import { assertNever, fastForEach } from '../../core/shared/utils' +import { assertNever } from '../../core/shared/utils' import type { ConditionalCase } from '../../core/model/conditionals' import { getConditionalClausePath } from '../../core/model/conditionals' import { findUtopiaCommentFlag, isUtopiaCommentFlagMapCount } from '../../core/shared/comment-flags' @@ -61,14 +48,11 @@ import { condensedNavigatorRow, getEntriesForRow, regularNavigatorRow, - type CondensedNavigatorRow, type NavigatorRow, type RegularNavigatorRow, } from './navigator-row' import { dropNulls, mapDropNulls } from '../../core/shared/array-utils' -import invariant from '../../third-party/remix/invariant' import { getUtopiaID } from '../../core/shared/uid-utils' -import { create } from 'tar' import { emptySet } from '../../core/shared/set-utils' import { objectMap } from '../../core/shared/object-utils' import { dataCanCondenseFromMetadata } from '../../utils/can-condense' @@ -79,34 +63,6 @@ export function baseNavigatorDepth(path: ElementPath): number { return EP.fullDepth(path) - 1 } -export function navigatorDepth( - navigatorEntry: NavigatorEntry, - metadata: ElementInstanceMetadataMap, -): number { - const path = navigatorEntry.elementPath - let result: number = baseNavigatorDepth(path) - for (const ancestorPath of EP.getAncestors(path)) { - const elementMetadata = MetadataUtils.findElementByElementPath(metadata, ancestorPath) - if (elementMetadata != null) { - const isConditional = foldEither( - () => false, - (e) => isJSXConditionalExpression(e), - elementMetadata.element, - ) - if (isConditional) { - result = result + 1 - } - } - } - - // For the clause entry itself, this needs to step back by 1. - if (isConditionalClauseNavigatorEntry(navigatorEntry)) { - result = result + 1 - } - - return result -} - type RegularNavigatorTree = { type: 'regular-entry' elementHidden: boolean From 30c867f740017aeeaeceb0ca9182e2841b5bae90 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Mon, 17 Jun 2024 10:52:22 +0200 Subject: [PATCH 093/103] Disabling flaky "Does not update the metadata in select mode" (#5956) **Problem:** the observer test "Does not update the metadata in select mode" is flaky. I am disabling it for now, and making a follow up ticket to re-enable and debug it. I have a suspicion that it became flaky with #5838 but I did not verify this, just basing the hunch on the tests's name. --- editor/src/components/canvas/dom-walker.spec.browser2.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/components/canvas/dom-walker.spec.browser2.tsx b/editor/src/components/canvas/dom-walker.spec.browser2.tsx index e0928cee519c..de27d8ab4893 100644 --- a/editor/src/components/canvas/dom-walker.spec.browser2.tsx +++ b/editor/src/components/canvas/dom-walker.spec.browser2.tsx @@ -526,7 +526,7 @@ describe('Observing runtime changes', () => { expect(metadataAfter).not.toBeNull() }) - it('Does not update the metadata in select mode', async () => { + xit('Does not update the metadata in select mode', async () => { const renderResult = await renderTestEditorWithCode( changingProjectCode, 'await-first-dom-report', From c32d0824c323a29c9874189a0d45ae66ac8a0973 Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Mon, 17 Jun 2024 10:22:26 +0100 Subject: [PATCH 094/103] Handle Padding Indicator Scaling (#5953) - Reworked a lot of the position and size properties for the two divs that wrap around the padding value itself. --- .../canvas/controls/distance-guideline.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/editor/src/components/canvas/controls/distance-guideline.tsx b/editor/src/components/canvas/controls/distance-guideline.tsx index 95b2b5c161e6..618d6da9065b 100644 --- a/editor/src/components/canvas/controls/distance-guideline.tsx +++ b/editor/src/components/canvas/controls/distance-guideline.tsx @@ -124,14 +124,14 @@ export class DistanceGuideline extends React.Component { return (
0 ? 'visible' : 'hidden', position: 'absolute', - top: Math.min(from.y, to.y), - left: Math.min(from.x, to.x), - width: isHorizontal ? Math.abs(from.x - to.x) : undefined, - height: isHorizontal ? undefined : Math.abs(from.y - to.y), + top: Math.min(from.y, to.y) + (isHorizontal ? 4 : 0) / this.props.scale, // Offset by 4px to keep the control off the line. + left: Math.min(from.x, to.x) + (isHorizontal ? 0 : 4) / this.props.scale, // Offset by 4px to keep the control off the line. + width: isHorizontal ? Math.abs(from.x - to.x) : `max-content`, + height: isHorizontal ? `max-content` : Math.abs(from.y - to.y), pointerEvents: 'none', display: 'flex', flexDirection: isHorizontal ? 'row' : 'column', @@ -140,13 +140,16 @@ export class DistanceGuideline extends React.Component { >
From 2a91de1f910c316f7fb71ba95dbb88aa6a27a12b Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:49:41 +0200 Subject: [PATCH 095/103] alignContent='center' in the component section grid row (#5959) **Problem:** We converted some flex rows to UIGridRow last week, but it messed up vertical alignment on some rows. ![image](https://github.com/concrete-utopia/utopia/assets/2226774/21474f05-95c1-4887-b203-0566696c98d7) **Fix:** Set alignContent: 'center' on all three places using UIGridRow in the component inspector image --- .../sections/component-section/component-section.tsx | 7 ++++++- editor/src/components/inspector/widgets/ui-grid-row.tsx | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index f7b4b03fd000..3e036ebfcdf6 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -654,7 +654,12 @@ const RowForBaseControl = React.memo((props: RowForBaseControlProps) => { data={null} > {dataPickerButtonData.popupIsOpen ? dataPickerButtonData.DataPickerComponent : null} - + {propertyLabel}
* alignItems: default value is 'center' */ alignItems?: 'start' | 'center' | 'stretch' + /** + * alignContent: default value is 'center' + */ + alignContent?: 'start' | 'center' | 'stretch' } export const UIGridRow = React.forwardRef>( - ({ tall, variant, alignItems, style, padded, children, ...props }, ref) => ( + ({ tall, variant, alignItems, alignContent, style, padded, children, ...props }, ref) => (
Date: Mon, 17 Jun 2024 14:19:45 +0200 Subject: [PATCH 096/103] direct to master push: setting alignContent in two more places in component-section.tsx --- .../inspector/sections/component-section/component-section.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index 3e036ebfcdf6..027c940d69d4 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -778,6 +778,7 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => {
{ {when(dataPickerButtonData.popupIsOpen, dataPickerButtonData.DataPickerComponent)} Date: Mon, 17 Jun 2024 14:40:55 +0200 Subject: [PATCH 097/103] Add a property picker button for arrays (#5941) ## Problem Array control rows don't have a + button to open the data picker, and they don't have the blue hover color ## Fix Add it **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode https://github.com/concrete-utopia/utopia/issues/5912 --- .../component-section/component-section.tsx | 109 +++++++++++++----- 1 file changed, 80 insertions(+), 29 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/component-section.tsx b/editor/src/components/inspector/sections/component-section/component-section.tsx index 027c940d69d4..2096c129abf0 100644 --- a/editor/src/components/inspector/sections/component-section/component-section.tsx +++ b/editor/src/components/inspector/sections/component-section/component-section.tsx @@ -708,12 +708,20 @@ function getSectionHeightFromPropControl( interface RowForArrayControlProps extends AbstractRowForControlProps { controlDescription: ArrayControlDescription + disableToggling: boolean } const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { const { propPath, controlDescription, isScene } = props const title = labelForControl(propPath, controlDescription) + const [open, setOpen] = React.useState(false) + const handleOnClick = React.useCallback(() => { + if (!props.disableToggling) { + setOpen(!open) + } + }, [setOpen, open, props.disableToggling]) + const selectedViews = useEditorState( Substores.selectedViews, (store) => store.editor.selectedViews, @@ -726,7 +734,6 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { isScene, controlDescription, ) - const indentation = props.indentationLevel * 8 const propName = `${PP.lastPart(propPath)}` const propMetadata = useComponentPropsInspectorInfo( @@ -742,7 +749,11 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { ) const [insertingRow, setInsertingRow] = React.useState(false) - const toggleInsertRow = React.useCallback(() => setInsertingRow((current) => !current), []) + const toggleInsertRow = React.useCallback((e: React.MouseEvent) => { + e.stopPropagation() + e.preventDefault() + setInsertingRow((current) => !current) + }, []) // Ensure the value is an array, just in case. const transformedValue = React.useMemo(() => { @@ -772,6 +783,23 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { const dataPickerButtonData = useDataPickerButtonInComponentSection(selectedViews, props.propPath) + const [isHovered, setIsHovered] = React.useState(false) + + const handleMouseEnter = React.useCallback(() => { + setIsHovered(true) + }, []) + + const handleMouseLeave = React.useCallback(() => { + setIsHovered(false) + }, []) + + const isConnectedToData = React.useMemo(() => { + return ( + propMetadata.propertyStatus.controlled && + propMetadata.attributeExpression?.type !== 'JSX_ELEMENT' + ) + }, [propMetadata]) + return ( {when(dataPickerButtonData.popupIsOpen, dataPickerButtonData.DataPickerComponent)} @@ -782,13 +810,21 @@ const RowForArrayControl = React.memo((props: RowForArrayControlProps) => { style={{ padding: '3px 8px' }} variant='<--1fr--><--1fr-->' ref={dataPickerButtonData.setReferenceElement} + onClick={handleOnClick} + data-testid={`control-container-${title}`} > - - {title} - + {unless(props.disableToggling, )} + {propertyStatus.overwritable && !propertyStatus.controlled ? ( { elementPath={selectedViews.at(0) ?? EP.emptyElementPath} /> -
- {springs.map((springStyle, index) => ( - - ))} -
+ {when( + open, +
+
+ {springs.map((springStyle, index) => ( + + ))} +
+
, + )}
) @@ -1308,7 +1353,13 @@ export const RowForControl = React.memo((props: RowForControlProps) => { } else { switch (controlDescription.control) { case 'array': - return + return ( + + ) case 'object': return ( Date: Mon, 17 Jun 2024 16:20:29 +0200 Subject: [PATCH 098/103] Fix some cartouche icon problems (#5962) **Problem:** ![image](https://github.com/concrete-utopia/utopia/assets/2226774/0753d10d-2880-40d4-823a-ea2fd294ae30) some array literals were shown with the broken image icon and image directly after insertion, we'd show a broken image icon for a bit and then show the real icon **Commit Details:** - For "unknown" data, Instead of ever again showing the broken image icon, show a 12x12 invisible div, so the cartouche layout doesn't fall apart and we are not showing `?` or anything that would look weird on video or screenshots - Actually for array literals such as `[1, 2, 3]` do not show the 'unknown' icon because we know this to be an array! Fixes #5960 --- .../sections/component-section/cartouche-ui.tsx | 16 +++++++++++----- .../variables-in-scope-utils.ts | 6 ++++-- .../performance-regression-tests.spec.tsx.snap | 13 ++++++------- .../performance-regression-tests.spec.tsx | 2 +- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index cb1bf634ec9a..5c14366bd17f 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -73,6 +73,8 @@ export const CartoucheUI = React.forwardRef( const shouldUseRtlCSS = typeof props.children === 'string' + const iconType = dataTypeToIconType(datatype) + return (
- {source === 'inline-literal' ? null : ( + {source === 'inline-literal' ? null : iconType === 'empty' ? ( +
+ ) : ( { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`635`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`634`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) From f0b96dcf36aa3a808bed4cb9c03fcfb8a932f69a Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:00:25 +0200 Subject: [PATCH 099/103] Feat/zipball remote updates (#5963) **Problem:** The remote changes detection is a) slow and b) prone to false-positives **Fix:** 1. Use the zipball feature from https://github.com/concrete-utopia/utopia/pull/5639 to make those operations an order of magnitude faster 2. Update the assignment of `upstreamChangesSuccess` 3. Move the zeroing of `upstreamChanges` before all the other updates in `updateProjectAgainstGithub` **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5677 --- editor/src/components/editor/server.ts | 6 ++ .../navigator/left-pane/github-pane/index.tsx | 12 ++- editor/src/core/shared/github/github.spec.ts | 3 + editor/src/core/shared/github/helpers.ts | 66 +++++++++++---- .../github/operations/commit-and-push.ts | 28 +++---- .../github/operations/get-branch-checksums.ts | 31 +++---- .../shared/github/operations/load-branch.ts | 19 +++-- .../operations/update-against-branch.ts | 83 ++++++++----------- ...ches.$owner.$repo.branches.$branch.spec.ts | 4 + ...b.branches.$owner.$repo.branch.$branch.tsx | 2 + utopia-remix/app/types.ts | 2 + .../app/util/github-branch-contents.server.ts | 30 +++++-- 12 files changed, 172 insertions(+), 114 deletions(-) diff --git a/editor/src/components/editor/server.ts b/editor/src/components/editor/server.ts index 3f6f675557de..634600c305fd 100644 --- a/editor/src/components/editor/server.ts +++ b/editor/src/components/editor/server.ts @@ -708,6 +708,8 @@ type GetBranchProjectContentsRequest = { type: 'GET_BRANCH_PROJECT_CONTENTS_REQUEST' existingAssets: ExistingAsset[] | null uploadAssets: boolean + previousCommitSha: string | null + specificCommitSha: string | null } function getBranchProjectContentsRequest( @@ -725,6 +727,8 @@ export function getBranchProjectContents(operationContext: GithubOperationContex owner: string repo: string branch: string + previousCommitSha: string | null + specificCommitSha: string | null existingAssets: ExistingAsset[] }): Promise { const url = GithubEndpoints.getBranchProjectContents({ @@ -742,6 +746,8 @@ export function getBranchProjectContents(operationContext: GithubOperationContex getBranchProjectContentsRequest({ existingAssets: params.existingAssets, uploadAssets: true, + previousCommitSha: params.previousCommitSha, + specificCommitSha: params.specificCommitSha, }), ), }) diff --git a/editor/src/components/navigator/left-pane/github-pane/index.tsx b/editor/src/components/navigator/left-pane/github-pane/index.tsx index b21477c3a04e..14e09ea9f02f 100644 --- a/editor/src/components/navigator/left-pane/github-pane/index.tsx +++ b/editor/src/components/navigator/left-pane/github-pane/index.tsx @@ -1213,10 +1213,20 @@ export const GithubPane = React.memo(() => { const [refreshingGithubData, setRefreshingGithubData] = React.useState(false) + const projectId = useEditorState( + Substores.restOfEditor, + (store) => store.editor.id, + 'GithubPane projectId', + ) + const onClickRefresh = React.useCallback(() => { + if (projectId == null) { + return + } setRefreshingGithubData(true) void refreshGithubData( dispatch, + projectId, githubData.targetRepository, githubData.branchName, branchOriginContentsChecksums, @@ -1227,7 +1237,7 @@ export const GithubPane = React.memo(() => { ).finally(() => { setRefreshingGithubData(false) }) - }, [dispatch, githubData, branchOriginContentsChecksums]) + }, [dispatch, githubData, branchOriginContentsChecksums, projectId]) return (
diff --git a/editor/src/core/shared/github/github.spec.ts b/editor/src/core/shared/github/github.spec.ts index be2a3afbf2fe..35cd7628f709 100644 --- a/editor/src/core/shared/github/github.spec.ts +++ b/editor/src/core/shared/github/github.spec.ts @@ -90,6 +90,7 @@ describe('github helpers', () => { const got = await getRefreshGithubActions( mockDispatch, + 'project-id', null, null, null, @@ -146,6 +147,7 @@ describe('github helpers', () => { const got = await getRefreshGithubActions( mockDispatch, + 'project-id', { owner: 'foo', repository: 'bar' }, null, null, @@ -201,6 +203,7 @@ describe('github helpers', () => { const got = await getRefreshGithubActions( mockDispatch, + 'project-id', { owner: 'foo', repository: 'bar' }, null, null, diff --git a/editor/src/core/shared/github/helpers.ts b/editor/src/core/shared/github/helpers.ts index d9e9c5174018..071a31c36ba8 100644 --- a/editor/src/core/shared/github/helpers.ts +++ b/editor/src/core/shared/github/helpers.ts @@ -13,6 +13,7 @@ import { isProjectContentFile, projectContentDirectory, projectContentFile, + walkContentsTree, } from '../../../components/assets' import { notice } from '../../../components/common/notice' import type { EditorAction, EditorDispatch } from '../../../components/editor/action-types' @@ -70,6 +71,8 @@ import { GithubEndpoints } from './endpoints' import { getAllComponentDescriptorFilePaths } from '../../property-controls/property-controls-local' import React from 'react' import { useDispatch } from '../../../components/editor/store/dispatch-context' +import type { ExistingAsset } from '../../../components/editor/server' +import { getBranchProjectContents } from '../../../components/editor/server' export function dispatchPromiseActions( dispatch: EditorDispatch, @@ -113,6 +116,7 @@ export interface BranchContent { export interface GetBranchContentSuccess { type: 'SUCCESS' branch: BranchContent | null + noChanges?: boolean } export type GetBranchContentResponse = GetBranchContentSuccess | GithubFailure @@ -293,7 +297,8 @@ export function connectRepo( ] } -export async function getBranchContentFromServer( +// TODO Remove this once we're positive it's all working fine with the replacement getBranchProjectContents +export async function getBranchContentFromServer_DEPRECATED( githubRepo: GithubRepo, branchName: string | null, commitSha: string | null, @@ -896,10 +901,20 @@ export function useGithubPolling() { (store) => store.derived.branchOriginContentsChecksums, 'useGithubPolling branchOriginContentsChecksums', ) + const projectId = useEditorState( + Substores.restOfEditor, + (store) => store.editor.id, + 'useGithubPolling projectId', + ) const refreshAndScheduleGithubData = React.useCallback(async () => { + if (projectId == null) { + return + } + await refreshGithubData( dispatch, + projectId, githubData.targetRepository, githubData.branchName, branchOriginContentsChecksums, @@ -916,7 +931,7 @@ export function useGithubPolling() { // setTick((t) => t + 1) // }, GITHUB_REFRESH_INTERVAL_MILLISECONDS), // ) - }, [dispatch, branchOriginContentsChecksums, githubData]) + }, [dispatch, branchOriginContentsChecksums, githubData, projectId]) const authState = React.useMemo((): GithubAuthState => { if (!githubAuthenticated) { @@ -981,6 +996,7 @@ export function useGithubPolling() { export async function getRefreshGithubActions( dispatch: EditorDispatch, + projectId: string, githubRepo: GithubRepo | null, branchName: string | null, branchOriginChecksums: FileChecksumsWithFile | null, @@ -1015,6 +1031,7 @@ export async function getRefreshGithubActions( if (originCommitSha != null) { // 3. get the checksums const checksums = await getBranchChecksums(operationContext)( + projectId, githubRepo, branchName, originCommitSha, @@ -1034,6 +1051,7 @@ export async function getRefreshGithubActions( } // 5. finally update upstream changes const upstreamChanges = await updateUpstreamChanges( + projectId, branchName, branchOriginChecksums, githubRepo, @@ -1050,6 +1068,7 @@ export async function getRefreshGithubActions( export async function refreshGithubData( dispatch: EditorDispatch, + projectId: string, githubRepo: GithubRepo | null, branchName: string | null, branchOriginChecksums: FileChecksumsWithFile | null, @@ -1061,6 +1080,7 @@ export async function refreshGithubData( try { const actions = await getRefreshGithubActions( dispatch, + projectId, githubRepo, branchName, branchOriginChecksums, @@ -1078,6 +1098,7 @@ export async function refreshGithubData( } async function updateUpstreamChanges( + projectId: string, branchName: string | null, branchOriginChecksums: FileChecksumsWithFile | null, githubRepo: GithubRepo, @@ -1087,19 +1108,21 @@ async function updateUpstreamChanges( const actions: Array = [] let upstreamChangesSuccess = false if (branchName != null && branchOriginChecksums != null) { - const branchContentResponse = await getBranchContentFromServer( - githubRepo, - branchName, - null, - previousCommitSha, - operationContext, - ) - if (branchContentResponse.ok) { - const branchLatestContent: GetBranchContentResponse = await branchContentResponse.json() - if (branchLatestContent.type === 'SUCCESS' && branchLatestContent.branch != null) { - upstreamChangesSuccess = true + const branchContentResponse = await getBranchProjectContents(operationContext)({ + projectId: projectId, + owner: githubRepo.owner, + repo: githubRepo.repository, + branch: branchName, + existingAssets: [], + previousCommitSha: previousCommitSha, + specificCommitSha: null, + }) + if (branchContentResponse.type === 'SUCCESS') { + upstreamChangesSuccess = + branchContentResponse.noChanges === true || branchContentResponse.branch != null + if (branchContentResponse.branch != null) { const branchLatestChecksums = getProjectContentsChecksums( - branchLatestContent.branch.content, + branchContentResponse.branch.content, {}, ) const upstreamChanges = deriveGithubFileChanges( @@ -1110,13 +1133,10 @@ async function updateUpstreamChanges( actions.push( updateGithubData({ upstreamChanges: upstreamChanges, - lastRefreshedCommit: branchLatestContent.branch.originCommit, + lastRefreshedCommit: branchContentResponse.branch.originCommit, }), ) } - } else if (branchContentResponse.status === 304) { - // Not modified status means that the branch has the same commit SHA. - upstreamChangesSuccess = true } } if (!upstreamChangesSuccess) { @@ -1276,3 +1296,13 @@ export const resolveConflict = throw new Error(`Unhandled conflict ${JSON.stringify(conflict)}`) } } + +export function getExistingAssets(currentProjectContents: ProjectContentTreeRoot): ExistingAsset[] { + let existingAssets: ExistingAsset[] = [] + walkContentsTree(currentProjectContents, (path, file) => { + if (file.type === 'ASSET_FILE' || file.type === 'IMAGE_FILE') { + existingAssets.push({ gitBlobSha: file.gitBlobSha, path: path, type: file.type }) + } + }) + return existingAssets +} diff --git a/editor/src/core/shared/github/operations/commit-and-push.ts b/editor/src/core/shared/github/operations/commit-and-push.ts index 7b05b95673ef..d99aedd19477 100644 --- a/editor/src/core/shared/github/operations/commit-and-push.ts +++ b/editor/src/core/shared/github/operations/commit-and-push.ts @@ -13,10 +13,10 @@ import type { PersistentModel, } from '../../../../components/editor/store/editor-state' import { projectGithubSettings } from '../../../../components/editor/store/editor-state' -import type { GetBranchContentResponse, GithubFailure, GithubOperationSource } from '../helpers' +import type { GithubFailure, GithubOperationSource } from '../helpers' import { dispatchPromiseActions, - getBranchContentFromServer, + getExistingAssets, githubAPIError, githubAPIErrorFromResponse, runGithubOperation, @@ -24,6 +24,7 @@ import { import { getBranchesForGithubRepository } from './list-branches' import type { GithubOperationContext } from './github-operation-context' import { GithubEndpoints } from '../endpoints' +import { getBranchProjectContents } from '../../../../components/editor/server' export interface SaveProjectToGithubOptions { branchName: string | null @@ -62,18 +63,17 @@ export const saveProjectToGithub = // and avoid a fast forward error. let originCommit = persistentModel.githubSettings.originCommit if (originCommit == null && targetRepository != null && branchName != null) { - const getBranchResponse = await getBranchContentFromServer( - targetRepository, - branchName, - null, - null, - operationContext, - ) - if (getBranchResponse.ok) { - const content: GetBranchContentResponse = await getBranchResponse.json() - if (content.type === 'SUCCESS' && content.branch != null) { - originCommit = content.branch.originCommit - } + const getBranchResponse = await getBranchProjectContents(operationContext)({ + projectId: projectID, + repo: targetRepository.repository, + owner: targetRepository.owner, + existingAssets: getExistingAssets(persistentModel.projectContents), + branch: branchName, + previousCommitSha: null, + specificCommitSha: null, + }) + if (getBranchResponse.type === 'SUCCESS' && getBranchResponse.branch != null) { + originCommit = getBranchResponse.branch.originCommit } } diff --git a/editor/src/core/shared/github/operations/get-branch-checksums.ts b/editor/src/core/shared/github/operations/get-branch-checksums.ts index 95f13fabb439..ccd359b63a09 100644 --- a/editor/src/core/shared/github/operations/get-branch-checksums.ts +++ b/editor/src/core/shared/github/operations/get-branch-checksums.ts @@ -1,34 +1,29 @@ import type { EditorAction } from '../../../../components/editor/action-types' import { updateBranchContents } from '../../../../components/editor/actions/action-creators' +import { getBranchProjectContents } from '../../../../components/editor/server' import type { GithubRepo } from '../../../../components/editor/store/editor-state' -import type { GetBranchContentResponse } from '../helpers' -import { getBranchContentFromServer } from '../helpers' import type { GithubOperationContext } from './github-operation-context' export const getBranchChecksums = (operationContext: GithubOperationContext) => async ( + projectId: string, githubRepo: GithubRepo, branchName: string, commitSha: string, ): Promise> => { - const specificCommitRequest = getBranchContentFromServer( - githubRepo, - branchName, - commitSha, - null, - operationContext, - ) + const specificCommitResponse = await getBranchProjectContents(operationContext)({ + projectId: projectId, + repo: githubRepo.repository, + owner: githubRepo.owner, + branch: branchName, + specificCommitSha: commitSha, + previousCommitSha: null, + existingAssets: [], + }) - const specificCommitResponse = await specificCommitRequest - - if (specificCommitResponse.ok) { - const specificCommitContent: GetBranchContentResponse = await specificCommitResponse.json() - if (specificCommitContent.type === 'SUCCESS') { - if (specificCommitContent.branch != null) { - return [updateBranchContents(specificCommitContent.branch.content)] - } - } + if (specificCommitResponse.type === 'SUCCESS' && specificCommitResponse.branch != null) { + return [updateBranchContents(specificCommitResponse.branch.content)] } return [] } diff --git a/editor/src/core/shared/github/operations/load-branch.ts b/editor/src/core/shared/github/operations/load-branch.ts index 12b06139f388..88c4f2d2d8e4 100644 --- a/editor/src/core/shared/github/operations/load-branch.ts +++ b/editor/src/core/shared/github/operations/load-branch.ts @@ -25,7 +25,13 @@ import type { RequestedNpmDependency } from '../../npm-dependency-types' import { forceNotNull } from '../../optional-utils' import { isTextFile } from '../../project-file-types' import type { BranchContent, GithubOperationSource } from '../helpers' -import { connectRepo, githubAPIError, runGithubOperation, saveGithubAsset } from '../helpers' +import { + connectRepo, + getExistingAssets, + githubAPIError, + runGithubOperation, + saveGithubAsset, +} from '../helpers' import type { GithubOperationContext } from './github-operation-context' import { createStoryboardFileIfNecessary } from '../../../../components/editor/actions/actions' import { getAllComponentDescriptorFilePaths } from '../../../property-controls/property-controls-local' @@ -118,19 +124,14 @@ export const updateProjectWithBranchContent = dispatch, initiator, async (operation: GithubOperation) => { - let existingAssets: ExistingAsset[] = [] - walkContentsTree(currentProjectContents, (path, file) => { - if (file.type === 'ASSET_FILE' || file.type === 'IMAGE_FILE') { - existingAssets.push({ gitBlobSha: file.gitBlobSha, path: path, type: file.type }) - } - }) - const responseBody = await GithubOperations.getBranchProjectContents({ projectId: projectID, owner: githubRepo.owner, repo: githubRepo.repository, branch: branchName, - existingAssets: existingAssets, + existingAssets: getExistingAssets(currentProjectContents), + previousCommitSha: null, + specificCommitSha: null, }) switch (responseBody.type) { diff --git a/editor/src/core/shared/github/operations/update-against-branch.ts b/editor/src/core/shared/github/operations/update-against-branch.ts index a45cf15388c4..5c348c5698e6 100644 --- a/editor/src/core/shared/github/operations/update-against-branch.ts +++ b/editor/src/core/shared/github/operations/update-against-branch.ts @@ -10,15 +10,11 @@ import { } from '../../../../components/editor/actions/action-creators' import type { GithubOperation, GithubRepo } from '../../../../components/editor/store/editor-state' import { updateProjectContentsWithParseResults } from '../../parser-projectcontents-utils' -import type { GetBranchContentResponse, GithubOperationSource } from '../helpers' -import { - getBranchContentFromServer, - githubAPIError, - githubAPIErrorFromResponse, - runGithubOperation, -} from '../helpers' +import type { GithubOperationSource } from '../helpers' +import { getExistingAssets, githubAPIError, runGithubOperation } from '../helpers' import { saveAssetsToProject } from './load-branch' import type { GithubOperationContext } from './github-operation-context' +import { getBranchProjectContents } from '../../../../components/editor/server' export const updateProjectAgainstGithub = (operationContext: GithubOperationContext) => @@ -37,45 +33,38 @@ export const updateProjectAgainstGithub = dispatch, initiator, async (operation: GithubOperation) => { - const branchLatestRequest = getBranchContentFromServer( - githubRepo, - branchName, - null, - null, - operationContext, - ) - const specificCommitRequest = getBranchContentFromServer( - githubRepo, - branchName, - commitSha, - null, - operationContext, - ) + const existingAssets = getExistingAssets(currentProjectContents) - const branchLatestResponse = await branchLatestRequest - const specificCommitResponse = await specificCommitRequest + const branchLatestResponse = await getBranchProjectContents(operationContext)({ + projectId: projectID, + repo: githubRepo.repository, + owner: githubRepo.owner, + branch: branchName, + specificCommitSha: null, + previousCommitSha: null, + existingAssets: existingAssets, + }) + const specificCommitResponse = await getBranchProjectContents(operationContext)({ + projectId: projectID, + repo: githubRepo.repository, + owner: githubRepo.owner, + branch: branchName, + specificCommitSha: commitSha, + previousCommitSha: null, + existingAssets: existingAssets, + }) - if (!branchLatestResponse.ok) { - throw await githubAPIErrorFromResponse(operation, branchLatestResponse) - } - if (!specificCommitResponse.ok) { - throw await githubAPIErrorFromResponse(operation, specificCommitResponse) + if (branchLatestResponse.type === 'FAILURE') { + throw githubAPIError(operation, branchLatestResponse.failureReason) } - - const branchLatestContent: GetBranchContentResponse = await branchLatestResponse.json() - - if (branchLatestContent.type === 'FAILURE') { - throw githubAPIError(operation, branchLatestContent.failureReason) - } - if (branchLatestContent.branch == null) { + if (branchLatestResponse.branch == null) { throw githubAPIError(operation, `Could not find latest code for branch ${branchName}`) } - const specificCommitContent: GetBranchContentResponse = await specificCommitResponse.json() - if (specificCommitContent.type === 'FAILURE') { - throw githubAPIError(operation, specificCommitContent.failureReason) + if (specificCommitResponse.type === 'FAILURE') { + throw githubAPIError(operation, specificCommitResponse.failureReason) } - if (specificCommitContent.branch == null) { + if (specificCommitResponse.branch == null) { throw githubAPIError( operation, `Could not find commit ${commitSha} for branch ${branchName}`, @@ -86,14 +75,14 @@ export const updateProjectAgainstGithub = // TODO: Ideally this should only do a partial parse based on what has changed. const parsedLatestContent = await updateProjectContentsWithParseResults( workers, - branchLatestContent.branch.content, + branchLatestResponse.branch.content, ) // Save assets to the server from Github. await saveAssetsToProject(operationContext)( githubRepo, projectID, - branchLatestContent.branch, + branchLatestResponse.branch, dispatch, currentProjectContents, initiator, @@ -101,16 +90,16 @@ export const updateProjectAgainstGithub = dispatch( [ + updateGithubData({ + upstreamChanges: null, + lastRefreshedCommit: branchLatestResponse.branch.originCommit, + }), updateBranchContents(parsedLatestContent), updateAgainstGithub( parsedLatestContent, - specificCommitContent.branch.content, - branchLatestContent.branch.originCommit, + specificCommitResponse.branch.content, + branchLatestResponse.branch.originCommit, ), - updateGithubData({ - upstreamChanges: null, - lastRefreshedCommit: branchLatestContent.branch.originCommit, - }), showToast( notice(`Github: Updated the project against the branch ${branchName}.`, 'SUCCESS'), ), diff --git a/utopia-remix/app/routes-test/internal.projects.$id.github.branches.$owner.$repo.branches.$branch.spec.ts b/utopia-remix/app/routes-test/internal.projects.$id.github.branches.$owner.$repo.branches.$branch.spec.ts index 3ce355103083..2375a1371a08 100644 --- a/utopia-remix/app/routes-test/internal.projects.$id.github.branches.$owner.$repo.branches.$branch.spec.ts +++ b/utopia-remix/app/routes-test/internal.projects.$id.github.branches.$owner.$repo.branches.$branch.spec.ts @@ -111,6 +111,8 @@ describe('get branch project contents', () => { getBranchProjectContentsRequest({ existingAssets: [], uploadAssets: true, + previousCommitSha: null, + specificCommitSha: null, }), ), }), @@ -163,6 +165,8 @@ describe('get branch project contents', () => { getBranchProjectContentsRequest({ existingAssets: [], uploadAssets: true, + previousCommitSha: null, + specificCommitSha: null, }), ), }), diff --git a/utopia-remix/app/routes/internal.projects.$id.github.branches.$owner.$repo.branch.$branch.tsx b/utopia-remix/app/routes/internal.projects.$id.github.branches.$owner.$repo.branch.$branch.tsx index 9c645ecb8805..522e795d75b2 100644 --- a/utopia-remix/app/routes/internal.projects.$id.github.branches.$owner.$repo.branch.$branch.tsx +++ b/utopia-remix/app/routes/internal.projects.$id.github.branches.$owner.$repo.branch.$branch.tsx @@ -61,6 +61,8 @@ async function handler(req: Request, params: Params) { branch: branch, uploadAssets: body.uploadAssets, existingAssets: body.existingAssets ?? [], + previousCommitSha: body.previousCommitSha, + specificCommitSha: body.specificCommitSha, }), ) } diff --git a/utopia-remix/app/types.ts b/utopia-remix/app/types.ts index 708dc0f9e893..909a3bb2adea 100644 --- a/utopia-remix/app/types.ts +++ b/utopia-remix/app/types.ts @@ -409,6 +409,8 @@ export type GetBranchProjectContentsRequest = { type: 'GET_BRANCH_PROJECT_CONTENTS_REQUEST' existingAssets: ExistingAsset[] | null uploadAssets: boolean + previousCommitSha: string | null + specificCommitSha: string | null } export function getBranchProjectContentsRequest( diff --git a/utopia-remix/app/util/github-branch-contents.server.ts b/utopia-remix/app/util/github-branch-contents.server.ts index d1c2f517ddc8..4c6f9dfef95e 100644 --- a/utopia-remix/app/util/github-branch-contents.server.ts +++ b/utopia-remix/app/util/github-branch-contents.server.ts @@ -45,7 +45,8 @@ export type BranchResponse = { branchName: string originCommit: string content: ProjectContentTreeRoot - } + } | null + noChanges?: boolean } export function getBranchProjectContents(params: { @@ -55,15 +56,30 @@ export function getBranchProjectContents(params: { branch: string uploadAssets: boolean existingAssets: ExistingAsset[] + specificCommitSha: string | null + previousCommitSha: string | null }) { return async function (client: OctokitClient): Promise> { // 1. get the branch details - const response = await client.request('GET /repos/{owner}/{repo}/branches/{branch}', { - owner: params.owner, - repo: params.repo, - branch: params.branch, - }) - const commit = response.data.commit.sha + async function getCommit() { + if (params.specificCommitSha != null) { + return params.specificCommitSha + } + const response = await client.request('GET /repos/{owner}/{repo}/branches/{branch}', { + owner: params.owner, + repo: params.repo, + branch: params.branch, + }) + return response.data.commit.sha + } + const commit = await getCommit() + + if (params.previousCommitSha != null && commit === params.previousCommitSha) { + return toApiSuccess({ + branch: null, + noChanges: true, + }) + } // 2. get the zipball const tarball = await client.request('GET /repos/{owner}/{repo}/zipball/{ref}', { From 34a84f2fc7d3a9c4774d14c3d75f7267570715a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bertalan=20K=C3=B6rmendy?= Date: Mon, 17 Jun 2024 17:04:45 +0200 Subject: [PATCH 100/103] =?UTF-8?q?Data=20Picker:=20show=20Promises=20in?= =?UTF-8?q?=20a=20way=20that=20it=E2=80=99s=20clear=20that=20they=20are=20?= =?UTF-8?q?promises=20(#5967)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Implements https://github.com/concrete-utopia/utopia/issues/5946 within the functionality of the current data picker image ## Manual Tests I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode --- .../component-section/cartouche-ui.tsx | 16 ++++++++++---- .../component-section/data-picker-utils.tsx | 9 +++++++- .../data-selector-cartouche.tsx | 14 +++++------- .../data-selector-columns.tsx | 22 ++++++++----------- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx index 5c14366bd17f..d154de64080b 100644 --- a/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx +++ b/editor/src/components/inspector/sections/component-section/cartouche-ui.tsx @@ -12,7 +12,13 @@ export interface HoverHandlers { onMouseLeave: (e: React.MouseEvent) => void } -export type CartoucheDataType = 'renderable' | 'boolean' | 'array' | 'object' | 'unknown' +export type CartoucheDataType = + | 'renderable' + | 'boolean' + | 'array' + | 'object' + | 'promise' + | 'unknown' export type CartoucheSource = 'internal' | 'external' | 'inline-literal' | 'literal-assignment' export type CartoucheHighlight = 'strong' | 'subtle' | 'disabled' @@ -71,8 +77,6 @@ export const CartoucheUI = React.forwardRef( // NOTE: this is currently unused, we should decide if we want to keep allowing deletion of the cartouches from here or not const wrappedOnDelete = useStopPropagation(onDelete) - const shouldUseRtlCSS = typeof props.children === 'string' - const iconType = dataTypeToIconType(datatype) return ( @@ -172,7 +176,7 @@ export const CartoucheUI = React.forwardRef( function dataTypeToIconType( dataType: CartoucheUIProps['datatype'], -): 'array' | 'object' | 'data' | 'empty' { +): 'array' | 'object' | 'data' | 'empty' | 'dashedframe' { switch (dataType) { case 'renderable': return 'data' @@ -182,8 +186,12 @@ function dataTypeToIconType( return 'array' case 'object': return 'object' + case 'promise': + return 'dashedframe' case 'unknown': return 'empty' + default: + assertNever(dataType) } } diff --git a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx index 3974192157c4..df0afb23ccce 100644 --- a/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx +++ b/editor/src/components/inspector/sections/component-section/data-picker-utils.tsx @@ -12,7 +12,6 @@ import { type JSXElementChild, } from '../../../../core/shared/element-template' import type { ElementPath } from '../../../../core/shared/project-file-types' -import { assertNever } from '../../../../core/shared/utils' import type { ProjectContentTreeRoot } from '../../../assets' import { insertionCeilingToString, type FileRootPath } from '../../../canvas/ui-jsx-canvas' import type { AllElementProps } from '../../../editor/store/editor-state' @@ -140,3 +139,11 @@ function outletNameHack( const component = findContainingComponentForPathInProjectContents(target, projectContents) return component?.name ?? namePossiblyOutlet } + +export function mightBePromise(value: unknown) { + return ( + typeof value === 'object' && + value != null && + typeof (value as { [key: string]: any }).then === 'function' + ) +} diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx index e1c61a84b192..378c5c51b5a1 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx @@ -8,7 +8,7 @@ import { Substores, useEditorState } from '../../../editor/store/store-hook' import { MapCounterUi } from '../../../navigator/navigator-item/map-counter' import type { CartoucheUIProps } from './cartouche-ui' import { CartoucheUI } from './cartouche-ui' -import type { DataPickerOption } from './data-picker-utils' +import { mightBePromise, type DataPickerOption } from './data-picker-utils' import { variableMatches } from './variables-in-scope-utils' interface DataPickerCartoucheProps { @@ -30,7 +30,7 @@ export const DataPickerCartouche = React.memo( key={data.valuePath.toString()} tooltip={null} source={dataSource ?? 'internal'} - datatype={childTypeToCartoucheDataType(data.type)} + datatype={childTypeToCartoucheDataType(data)} selected={variableMatches(data.variableInfo) && selected} highlight={variableMatches(data.variableInfo) ? null : 'disabled'} role={forceRole ?? (variableMatches(data.variableInfo) ? 'selection' : 'information')} @@ -97,18 +97,16 @@ export function useVariableDataSource( ) } -function childTypeToCartoucheDataType( - childType: DataPickerOption['type'], -): CartoucheUIProps['datatype'] { - switch (childType) { +function childTypeToCartoucheDataType(option: DataPickerOption): CartoucheUIProps['datatype'] { + switch (option.type) { case 'array': return 'array' case 'object': - return 'object' + return mightBePromise(option.variableInfo.value) ? 'promise' : 'object' case 'jsx': case 'primitive': return 'renderable' default: - assertNever(childType) + assertNever(option) } } diff --git a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx index 01b190441d36..cf7019f7b644 100644 --- a/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx +++ b/editor/src/components/inspector/sections/component-section/data-selector-columns.tsx @@ -4,7 +4,13 @@ import React from 'react' import { isPrefixOf } from '../../../../core/shared/array-utils' import { arrayEqualsByReference, assertNever } from '../../../../core/shared/utils' import { FlexColumn, FlexRow, Icons, colorTheme } from '../../../../uuiui' -import type { ArrayOption, DataPickerOption, ObjectOption, ObjectPath } from './data-picker-utils' +import { + mightBePromise, + type ArrayOption, + type DataPickerOption, + type ObjectOption, + type ObjectPath, +} from './data-picker-utils' import { DataPickerCartouche } from './data-selector-cartouche' interface DataSelectorColumnsProps { @@ -105,7 +111,6 @@ const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => { isLeaf={!('children' in option)} selected={selected} onActivePath={onActivePath} - forceShowArrow={pseudoSelectedElementForArray != null && index === 0} onTargetPathChange={props.onTargetPathChange} onApplySelection={props.onApplySelection} /> @@ -164,7 +169,7 @@ function variableTypeForInfo(info: DataPickerOption): string { case 'array': return 'Array' case 'object': - return 'Object' + return mightBePromise(info.variableInfo.value) ? 'Promise' : 'Object' case 'primitive': return typeof info.variableInfo.value case 'jsx': @@ -178,21 +183,12 @@ interface RowWithCartoucheProps { data: DataPickerOption selected: boolean onActivePath: boolean - forceShowArrow: boolean isLeaf: boolean onTargetPathChange: (newTargetVariable: DataPickerOption) => void onApplySelection: (newTargetVariable: DataPickerOption) => void } const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => { - const { - onTargetPathChange, - onApplySelection, - data, - isLeaf, - selected, - onActivePath, - forceShowArrow, - } = props + const { onTargetPathChange, onApplySelection, data, isLeaf, selected, onActivePath } = props const onClick: React.MouseEventHandler = React.useCallback( (e) => { From 42a8476d62fb301e57f8cc868ce7a56b0a7ff612 Mon Sep 17 00:00:00 2001 From: Balint Gabor <127662+gbalint@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:21:39 +0200 Subject: [PATCH 101/103] List index in navigator (#5968) **Problem:** For list children, add a number to the navigator item, see https://github.com/concrete-utopia/utopia/issues/5961 image **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes https://github.com/concrete-utopia/utopia/issues/5961 --- .../navigator/navigator-item/layout-icon.tsx | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/editor/src/components/navigator/navigator-item/layout-icon.tsx b/editor/src/components/navigator/navigator-item/layout-icon.tsx index b12f7fe14581..d8395148718c 100644 --- a/editor/src/components/navigator/navigator-item/layout-icon.tsx +++ b/editor/src/components/navigator/navigator-item/layout-icon.tsx @@ -221,6 +221,23 @@ export const LayoutIcon: React.FunctionComponent { + const generatedIndex = EP.extractIndexFromIndexedUid( + EP.toUid(props.navigatorEntry.elementPath), + ) + if (generatedIndex == null) { + return null + } + const parent = EP.parentPath(props.navigatorEntry.elementPath) + return MetadataUtils.isJSXMapExpression(parent, store.editor.jsxMetadata) + ? generatedIndex + : null + }, + 'NavigatorRowLabel listIndex', + ) + return (
, )} + {when( + listIndex != null, +
+ {listIndex} +
, + )} {icon}
) From 77480dfc00a832d4b3c2856ca8229bfa2e74418e Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:43:14 +0200 Subject: [PATCH 102/103] Fix: rename component-solid gray icon (#5970) Rename `component-solid-black-12x12@2x-1.png` to `component-solid-gray-12x12@2x.png`. **Manual Tests:** I hereby swear that: - [x] I opened a hydrogen project and it loaded - [x] I could navigate to various routes in Preview mode Fixes #5969 --- ...2@2x-1.png => component-solid-gray-12x12@2x.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename editor/resources/editor/icons/light/navigator-element/{component-solid-black-12x12@2x-1.png => component-solid-gray-12x12@2x.png} (100%) diff --git a/editor/resources/editor/icons/light/navigator-element/component-solid-black-12x12@2x-1.png b/editor/resources/editor/icons/light/navigator-element/component-solid-gray-12x12@2x.png similarity index 100% rename from editor/resources/editor/icons/light/navigator-element/component-solid-black-12x12@2x-1.png rename to editor/resources/editor/icons/light/navigator-element/component-solid-gray-12x12@2x.png From 5eb250f65b1470f4961b3fc6976810adf0e737ab Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:04:53 +0100 Subject: [PATCH 103/103] Replace Inspector Icons (#5966) - Added entries for some of the newly added icons. - Updated border radius inspector icons. - Changed `SplitChainedNumberInputProps.labels` type to support `React.ReactChild`. - Updated padding inspector icons. - Added icons for wrap and gap in the flex controls. --- .../flex-container-controls.tsx | 47 +++++-- .../layout-system-controls.tsx | 11 +- .../split-chained-number-input.tsx | 14 +- .../container-subsection/radius-row.tsx | 14 +- .../text-subsection/text-subsection.tsx | 4 +- ...performance-regression-tests.spec.tsx.snap | 96 +++++++++++++ .../performance-regression-tests.spec.tsx | 8 +- editor/src/uuiui/icons.tsx | 133 ++++++++++++++++++ 8 files changed, 292 insertions(+), 35 deletions(-) diff --git a/editor/src/components/inspector/sections/layout-section/flex-container-subsection/flex-container-controls.tsx b/editor/src/components/inspector/sections/layout-section/flex-container-subsection/flex-container-controls.tsx index 5e0a813e1b2e..c8d79179ea14 100644 --- a/editor/src/components/inspector/sections/layout-section/flex-container-subsection/flex-container-controls.tsx +++ b/editor/src/components/inspector/sections/layout-section/flex-container-subsection/flex-container-controls.tsx @@ -16,9 +16,17 @@ import type { OptionsType } from 'react-select' import { unsetPropertyMenuItem } from '../../../common/context-menu-items' import { UIGridRow } from '../../../widgets/ui-grid-row' import { PropertyLabel } from '../../../widgets/property-label' -import { PopupList, useWrappedEmptyOrUnknownOnSubmitValue, NumberInput } from '../../../../../uuiui' +import { + PopupList, + useWrappedEmptyOrUnknownOnSubmitValue, + NumberInput, + Icons, +} from '../../../../../uuiui' import { useContextSelector } from 'use-context-selector' import type { FlexDirection } from '../../../common/css-utils' +import { when } from '../../../../../utils/react-conditionals' +import { Substores, useEditorState } from '../../../../editor/store/store-hook' +import { flexDirectionSelector } from '../../../inpector-selectors' type uglyLabel = | 'left' @@ -169,6 +177,11 @@ export const FlexWrapControl = React.memo((props: FlexWrapControlProps) => { }, [onSubmit], ) + const flexDirection = useEditorState( + Substores.metadata, + flexDirectionSelector, + 'FlexWrapControl flexDirection', + ) return ( { width: undefined, }} > - option.value === props.value)} - options={FlexWrapOptions} - onSubmitValue={onSubmitValue} - controlStyles={props.controlStyles} - style={{ background: 'transparent' }} - /> + + {when(flexDirection.startsWith('row'), )} + {when(flexDirection.startsWith('column'), )} + option.value === props.value)} + options={FlexWrapOptions} + onSubmitValue={onSubmitValue} + controlStyles={props.controlStyles} + style={{ background: 'transparent' }} + /> + ) }) @@ -241,17 +258,17 @@ export const FlexGapControl = React.memo(() => { onUnsetValues, ) - const targetPath = useContextSelector(InspectorPropsContext, (contextData) => { - return contextData.targetPath - }) - const flexGapProp = React.useMemo(() => { - return [stylePropPathMappingFn('gap', targetPath)] - }, [targetPath]) + const flexDirection = useEditorState( + Substores.metadata, + flexDirectionSelector, + 'FlexGapControl flexDirection', + ) return ( - Gap + {when(flexDirection.startsWith('row'), )} + {when(flexDirection.startsWith('column'), )} { return ( , + horizontal: , + vertical: , + top: , + left: , + bottom: , + right: , + }} tooltips={{ oneValue: 'Padding', perDirection: 'Padding per direction', diff --git a/editor/src/components/inspector/sections/layout-section/layout-system-subsection/split-chained-number-input.tsx b/editor/src/components/inspector/sections/layout-section/layout-system-subsection/split-chained-number-input.tsx index 36df8590d16a..8e6a85ebf136 100644 --- a/editor/src/components/inspector/sections/layout-section/layout-system-subsection/split-chained-number-input.tsx +++ b/editor/src/components/inspector/sections/layout-section/layout-system-subsection/split-chained-number-input.tsx @@ -106,13 +106,13 @@ export interface SplitChainedNumberInputProps { mode: ControlMode | null onCycleMode: () => void labels?: { - top?: string - bottom?: string - left?: string - right?: string - horizontal?: string - vertical?: string - oneValue?: string + top?: React.ReactChild + bottom?: React.ReactChild + left?: React.ReactChild + right?: React.ReactChild + horizontal?: React.ReactChild + vertical?: React.ReactChild + oneValue?: React.ReactChild } tooltips?: { oneValue?: string diff --git a/editor/src/components/inspector/sections/style-section/container-subsection/radius-row.tsx b/editor/src/components/inspector/sections/style-section/container-subsection/radius-row.tsx index 0c1a930f469a..3714f2f805ab 100644 --- a/editor/src/components/inspector/sections/style-section/container-subsection/radius-row.tsx +++ b/editor/src/components/inspector/sections/style-section/container-subsection/radius-row.tsx @@ -37,6 +37,7 @@ import { longhandShorthandEventHandler, SplitChainedNumberInput, } from '../../layout-section/layout-system-subsection/split-chained-number-input' +import { Icons } from '../../../../../uuiui/icons' export const RadiusRow = React.memo(() => { const { value: borderRadiusValue, onUnsetValues } = useInspectorStyleInfo('borderRadius') @@ -232,7 +233,7 @@ export const BorderRadiusControl = React.memo(() => { const isCmdPressedRef = useRefEditorState((store) => store.editor.keysPressed.cmd === true) - const onCylceMode = React.useCallback( + const onCycleMode = React.useCallback( () => cycleToNextMode(initialMode, isCmdPressedRef.current === true ? 'backward' : 'forward'), [cycleToNextMode, initialMode, isCmdPressedRef], ) @@ -242,16 +243,17 @@ export const BorderRadiusControl = React.memo(() => { return ( , + bottom: , + left: , + right: , + oneValue: , }} tooltips={{ oneValue: 'Radius', perSide: 'Radius per corner', }} - onCycleMode={onCylceMode} + onCycleMode={onCycleMode} numberType={'LengthPercent'} name='radius' mode={modeToUse} diff --git a/editor/src/components/inspector/sections/style-section/text-subsection/text-subsection.tsx b/editor/src/components/inspector/sections/style-section/text-subsection/text-subsection.tsx index 6cca2b939ee4..9abe995da948 100644 --- a/editor/src/components/inspector/sections/style-section/text-subsection/text-subsection.tsx +++ b/editor/src/components/inspector/sections/style-section/text-subsection/text-subsection.tsx @@ -414,7 +414,7 @@ export const TextSubsection = React.memo(() => { onSubmitValue={wrappedLetterSpacingOnSubmitValue} onTransientSubmitValue={wrappedLetterSpacingOnTransientSubmitValue} controlStatus={letterSpacingMetadata.controlStatus} - DEPRECATED_labelBelow='letter' + DEPRECATED_labelBelow= stepSize={0.01} numberType='Length' defaultUnitToHide={'px'} @@ -438,7 +438,7 @@ export const TextSubsection = React.memo(() => { controlStatus={lineHeightMetadata.controlStatus} onSubmitValue={wrappedLineHeightOnSubmitValue} onTransientSubmitValue={wrappedLineHeightOnTransientSubmitValue} - DEPRECATED_labelBelow='line' + DEPRECATED_labelBelow= stepSize={0.01} numberType='Length' defaultUnitToHide={'em'} diff --git a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap index 16b4e9488594..13256ba225d4 100644 --- a/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap +++ b/editor/src/core/performance/__snapshots__/performance-regression-tests.spec.tsx.snap @@ -365,6 +365,11 @@ Array [ "/UtopiaSpiedFunctionComponent(DropdownIndicator)/UtopiaSpiedFunctionComponent(DropdownIndicator)/Symbol(react.forward_ref)(render)/UtopiaSpiedExoticType(Symbol(react.context))", "/Symbol(react.forward_ref)(render)/UtopiaSpiedExoticType(Symbol(react.context))/Symbol(react.context)/div", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/div///Symbol(react.forward_ref)(Styled(div)):data-testid='radius-cycle-mode'", "/div///UtopiaSpiedClass(Tooltip)", "/div///Symbol(react.memo)()", @@ -387,6 +392,13 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.memo)(Symbol(react.forward_ref)())/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(input)):data-testid='radius-one'", "/Symbol(react.memo)(Symbol(react.forward_ref)())/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(input))/input:data-testid='radius-one'", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/div///Symbol(react.forward_ref)(Styled(div)):data-testid='padding-cycle-mode'", "/div///UtopiaSpiedClass(Tooltip)", "/div///Symbol(react.memo)()", @@ -530,6 +542,11 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(BooleanControl)", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/ChildPinControl/Symbol(react.memo)()", @@ -553,6 +570,13 @@ Array [ "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/span", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(FlexRow)", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -951,6 +975,11 @@ Array [ "/UtopiaSpiedFunctionComponent(DropdownIndicator)/UtopiaSpiedFunctionComponent(DropdownIndicator)/Symbol(react.forward_ref)(render)/UtopiaSpiedExoticType(Symbol(react.context))", "/Symbol(react.forward_ref)(render)/UtopiaSpiedExoticType(Symbol(react.context))/Symbol(react.context)/div", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/div///Symbol(react.forward_ref)(Styled(div)):data-testid='radius-cycle-mode'", "/div///UtopiaSpiedClass(Tooltip)", "/div///Symbol(react.memo)()", @@ -973,6 +1002,13 @@ Array [ "/Symbol(react.forward_ref)(EmotionCssPropInternal)/Symbol(react.memo)(Symbol(react.forward_ref)())/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(input)):data-testid='radius-one'", "/Symbol(react.memo)(Symbol(react.forward_ref)())/Symbol(react.forward_ref)()/Symbol(react.forward_ref)(Styled(input))/input:data-testid='radius-one'", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/div///Symbol(react.forward_ref)(Styled(div)):data-testid='padding-cycle-mode'", "/div///UtopiaSpiedClass(Tooltip)", "/div///Symbol(react.memo)()", @@ -1066,6 +1102,11 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(BooleanControl)", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/ChildPinControl/Symbol(react.memo)()", @@ -1089,6 +1130,13 @@ Array [ "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/span", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(FlexRow)", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -1311,6 +1359,11 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(BooleanControl)", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/ChildPinControl/Symbol(react.memo)()", @@ -1382,6 +1435,13 @@ Array [ "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/span", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(FlexRow)", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -1830,6 +1890,11 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(BooleanControl)", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/ChildPinControl/Symbol(react.memo)()", @@ -1901,6 +1966,13 @@ Array [ "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/span", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(FlexRow)", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -2301,6 +2373,11 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(BooleanControl)", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/ChildPinControl/Symbol(react.memo)()", @@ -2372,6 +2449,13 @@ Array [ "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/span", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(FlexRow)", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", @@ -2714,6 +2798,11 @@ Array [ "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedFunctionComponent(BooleanControl)", "/Symbol(react.forward_ref)(Styled(div))/div//UtopiaSpiedExoticType(Symbol(react.fragment))", "/Symbol(react.forward_ref)(EmotionCssPropInternal)/div/ChildPinControl/Symbol(react.memo)()", @@ -2785,6 +2874,13 @@ Array [ "//UtopiaSpiedExoticType(Symbol(react.fragment))//UtopiaSpiedFunctionComponent(InspectorContextMenuWrapper)", "/div/div/PropertyLabel/Symbol(react.forward_ref)(EmotionCssPropInternal)", "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", + "/div/div//Symbol(react.memo)()", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/span", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(FlexRow)", "/StyleSection/UtopiaSpiedExoticType(Symbol(react.fragment))/TextSubsection/UtopiaSpiedFunctionComponent(RemovePropertyButton)", diff --git a/editor/src/core/performance/performance-regression-tests.spec.tsx b/editor/src/core/performance/performance-regression-tests.spec.tsx index 835583e939cb..0bc51a5d18ee 100644 --- a/editor/src/core/performance/performance-regression-tests.spec.tsx +++ b/editor/src/core/performance/performance-regression-tests.spec.tsx @@ -65,7 +65,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`773`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`797`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -127,7 +127,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`993`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`1017`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -183,7 +183,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`525`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`549`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) @@ -249,7 +249,7 @@ describe('React Render Count Tests -', () => { const renderCountAfter = renderResult.getNumberOfRenders() // if this breaks, GREAT NEWS but update the test please :) - expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`634`) + expect(renderCountAfter - renderCountBefore).toMatchInlineSnapshot(`658`) expect(renderResult.getRenderInfo()).toMatchSnapshot() }) }) diff --git a/editor/src/uuiui/icons.tsx b/editor/src/uuiui/icons.tsx index 2a99e8098dee..b50edc10e8ba 100644 --- a/editor/src/uuiui/icons.tsx +++ b/editor/src/uuiui/icons.tsx @@ -645,6 +645,139 @@ export const Icons = { width: 16, height: 16, }), + BorderRadius: makeIcon({ + category: 'inspector-element', + type: 'borderRadius', + color: 'main', + width: 16, + height: 16, + }), + BorderRadiusBottomLeft: makeIcon({ + category: 'inspector-element', + type: 'borderRadius-bottomLeft', + color: 'main', + width: 16, + height: 16, + }), + BorderRadiusBottomRight: makeIcon({ + category: 'inspector-element', + type: 'borderRadius-bottomRight', + color: 'main', + width: 16, + height: 16, + }), + BorderRadiusTopLeft: makeIcon({ + category: 'inspector-element', + type: 'borderRadius-topLeft', + color: 'main', + width: 16, + height: 16, + }), + BorderRadiusTopRight: makeIcon({ + category: 'inspector-element', + type: 'borderRadius-topRight', + color: 'main', + width: 16, + height: 16, + }), + Padding: makeIcon({ + category: 'inspector-element', + type: 'padding', + color: 'main', + width: 16, + height: 16, + }), + PaddingVertical: makeIcon({ + category: 'inspector-element', + type: 'paddingVertical', + color: 'main', + width: 16, + height: 16, + }), + PaddingHorizontal: makeIcon({ + category: 'inspector-element', + type: 'paddingHorizontal', + color: 'main', + width: 16, + height: 16, + }), + PaddingTop: makeIcon({ + category: 'inspector-element', + type: 'paddingTop', + color: 'main', + width: 16, + height: 16, + }), + PaddingBottom: makeIcon({ + category: 'inspector-element', + type: 'paddingBottom', + color: 'main', + width: 16, + height: 16, + }), + PaddingLeft: makeIcon({ + category: 'inspector-element', + type: 'paddingLeft', + color: 'main', + width: 16, + height: 16, + }), + PaddingRight: makeIcon({ + category: 'inspector-element', + type: 'paddingRight', + color: 'main', + width: 16, + height: 16, + }), + GapVertical: makeIcon({ + category: 'inspector-element', + type: 'gapVertical', + color: 'main', + width: 16, + height: 16, + }), + GapHorizontal: makeIcon({ + category: 'inspector-element', + type: 'gapHorizontal', + color: 'main', + width: 16, + height: 16, + }), + WrapRow: makeIcon({ + category: 'inspector-element', + type: 'wrapRow', + color: 'main', + width: 16, + height: 16, + }), + WrapColumn: makeIcon({ + category: 'inspector-element', + type: 'wrapColumn', + color: 'main', + width: 16, + height: 16, + }), + LetterSpacing: makeIcon({ + category: 'inspector-element', + type: 'letterSpacing', + color: 'main', + width: 16, + height: 16, + }), + LineHeight: makeIcon({ + category: 'inspector-element', + type: 'lineHeight', + color: 'main', + width: 16, + height: 16, + }), + StrikeThrough: makeIcon({ + category: 'inspector-element', + type: 'strikethrough', + color: 'main', + width: 16, + height: 16, + }), } as const export const FunctionIcons = {