Skip to content

Commit

Permalink
targetSupportsChildren is false when component annotation says so (#5671
Browse files Browse the repository at this point in the history
)

* targetSupportsChildren is false when component annotation says so

* Optimization

* Add test

* Added test
  • Loading branch information
gbalint authored May 14, 2024
1 parent 9e6233b commit d73c6db
Show file tree
Hide file tree
Showing 32 changed files with 323 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ export function pickCanvasStateFromEditorState(
startingMetadata: editorState.jsxMetadata,
startingElementPathTree: editorState.elementPathTree,
startingAllElementProps: editorState.allElementProps,
propertyControlsInfo: editorState.propertyControlsInfo,
}
}

Expand All @@ -207,6 +208,7 @@ export function pickCanvasStateFromEditorStateWithMetadata(
startingMetadata: metadata,
startingElementPathTree: editorState.elementPathTree, // IMPORTANT! This isn't based on the passed in metadata
startingAllElementProps: allElementProps ?? editorState.allElementProps,
propertyControlsInfo: editorState.propertyControlsInfo,
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import type { InsertionSubject } from '../../editor/editor-modes'
import type { CanvasCommand } from '../commands/commands'
import type { StrategyApplicationStatus } from './interaction-state'
import type { ElementPathTrees } from '../../../core/shared/element-path-tree'
import type { RemixRoutingTable } from '../../editor/store/remix-derived-data'
import type { ActiveFrameAction } from '../commands/set-active-frames-command'
import type { PropertyControlsInfo } from '../../custom-code/code-file'

// TODO: fill this in, maybe make it an ADT for different strategies
export interface CustomStrategyState {
Expand Down Expand Up @@ -100,6 +100,7 @@ export interface InteractionCanvasState {
startingMetadata: ElementInstanceMetadataMap
startingElementPathTree: ElementPathTrees
startingAllElementProps: AllElementProps
propertyControlsInfo: PropertyControlsInfo
}

export type InteractionTarget = TargetPaths | InsertionSubjects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ function getNavigatorReparentCommands(
editor.elementPathTree,
wrapperUID,
data.dragSources.length,
editor.propertyControlsInfo,
)

if (newParentPath == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ function getTargetParentForPasteHere(
originalContextElementPathTrees: originalPathTree,
},
editor.elementPathTree,
editor.propertyControlsInfo,
)

if (isLeft(target)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { AllElementProps } from '../../../../editor/store/editor-state'
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'

export type ReparentAsAbsolute = 'REPARENT_AS_ABSOLUTE'
export type ReparentAsStatic = 'REPARENT_AS_STATIC'
Expand Down Expand Up @@ -68,6 +69,7 @@ export function findReparentStrategies(
canvasState.startingAllElementProps,
allowSmallerParent,
elementSupportsChildren,
canvasState.propertyControlsInfo,
)

if (targetParent == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import type { ElementPathTrees } from '../../../../../core/shared/element-path-t
import { isConditionalWithEmptyOrTextEditableActiveBranch } from '../../../../../core/model/conditionals'
import { getInsertionPathForReparentTarget } from './reparent-helpers'
import { treatElementAsGroupLike } from '../group-helpers'
import type { PropertyControlsInfo } from '../../../../custom-code/code-file'

export type FindReparentStrategyResult = {
strategy: ReparentStrategy
Expand All @@ -52,6 +53,7 @@ export function getReparentTargetUnified(
allElementProps: AllElementProps,
allowSmallerParent: AllowSmallerParent,
elementSupportsChildren: Array<ElementSupportsChildren> = ['supportsChildren'],
propertyControlsInfo: PropertyControlsInfo,
): ReparentTarget | null {
const canvasScale = canvasState.scale

Expand All @@ -65,6 +67,7 @@ export function getReparentTargetUnified(
allElementProps,
allowSmallerParent,
elementSupportsChildren,
propertyControlsInfo,
)

// For Flex parents, we want to be able to insert between two children that don't have a gap between them.
Expand Down Expand Up @@ -151,6 +154,7 @@ function findValidTargetsUnderPoint(
allElementProps: AllElementProps,
allowSmallerParent: AllowSmallerParent,
elementSupportsChildren: Array<ElementSupportsChildren> = ['supportsChildren'],
propertyControlsInfo: PropertyControlsInfo,
): Array<ElementPath> {
const projectContents = canvasState.projectContents
const openFile = canvasState.openFile ?? null
Expand Down Expand Up @@ -222,6 +226,7 @@ function findValidTargetsUnderPoint(
metadata,
target,
elementPathTree,
propertyControlsInfo,
),
)
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { flattenSelection } from './shared-move-strategies-helpers'
import type { InsertionPath } from '../../../editor/store/insertion-path'
import { childInsertionPath } from '../../../editor/store/insertion-path'
import { treatElementAsGroupLike } from './group-helpers'
import { PropertyControlsInfo } from '../../../custom-code/code-file'

interface ReparentFactoryAndDetails {
targetParent: InsertionPath
Expand Down Expand Up @@ -158,6 +159,7 @@ function getStartingTargetParentsToFilterOutInner(
canvasState.startingAllElementProps,
allowSmallerParent,
elementSupportsChildren,
canvasState.propertyControlsInfo,
)
if (regularReparentTarget != null) {
result.push(regularReparentTarget)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
withUnderlyingTarget,
} from '../../../editor/store/editor-state'
import {
StaticElementPath,
type ElementPath,
type Imports,
type NodeModules,
Expand Down Expand Up @@ -45,7 +44,7 @@ import { addElements } from '../../commands/add-elements-command'
import type { ElementPathTrees } from '../../../../core/shared/element-path-tree'
import { getRequiredGroupTrueUps } from '../../commands/queue-true-up-command'
import type { Either } from '../../../../core/shared/either'
import { flatMapEither, foldEither, left, right } from '../../../../core/shared/either'
import { flatMapEither, left, right } from '../../../../core/shared/either'
import { maybeBranchConditionalCase } from '../../../../core/model/conditionals'
import type { NonEmptyArray } from '../../../../core/shared/array-utils'
import {
Expand All @@ -59,9 +58,9 @@ import { isElementRenderedBySameComponent } from './reparent-helpers/reparent-he
import type { ParsedCopyData } from '../../../../utils/clipboard'
import { getParseSuccessForFilePath } from '../../canvas-utils'
import { renameDuplicateImports } from '../../../../core/shared/import-shared-utils'
import { modify, set } from '../../../../core/shared/optics/optic-utilities'
import { set } from '../../../../core/shared/optics/optic-utilities'
import { fromField, fromTypeGuard } from '../../../../core/shared/optics/optic-creators'
import { Optic } from '../../../../core/shared/optics/optics'
import type { PropertyControlsInfo } from '../../../custom-code/code-file'

interface GetReparentOutcomeResult {
commands: Array<CanvasCommand>
Expand Down Expand Up @@ -424,6 +423,7 @@ function insertIntoSlot(
projectContents: ProjectContentTreeRoot,
elementPathTrees: ElementPathTrees,
numberOfElementsToInsert: number,
propertyControlsInfo: PropertyControlsInfo,
): ReparentTargetForPaste | null {
const targetPath = selectedViews[0]
const parentPath = EP.parentPath(targetPath)
Expand All @@ -448,6 +448,7 @@ function insertIntoSlot(
elementPathTrees,
wrapperFragmentUID,
numberOfElementsToInsert,
propertyControlsInfo,
)

if (parentInsertionPath == null) {
Expand Down Expand Up @@ -540,6 +541,7 @@ function canInsertIntoTarget(
elementPathTree: ElementPathTrees,
parentTarget: ElementPath,
elementsToInsert: JSXElementChild[],
propertyControlsInfo: PropertyControlsInfo,
): boolean {
const pastedElementNames = mapDropNulls(
(element) => (element.type === 'JSX_ELEMENT' ? element.name : null),
Expand All @@ -557,6 +559,7 @@ function canInsertIntoTarget(
metadata,
parentTarget,
elementPathTree,
propertyControlsInfo,
)

return targetElementSupportsInsertedElement && supportsChildren
Expand All @@ -568,11 +571,19 @@ function pasteIntoParentOrGrandparent(
selectedViews: NonEmptyArray<ElementPath>,
metadata: ElementInstanceMetadataMap,
elementPathTree: ElementPathTrees,
propertyControlsInfo: PropertyControlsInfo,
): ReparentTargetForPaste | null {
const parentTarget = EP.getCommonParentOfNonemptyPathArray(selectedViews, true)

if (
canInsertIntoTarget(projectContents, metadata, elementPathTree, parentTarget, elementsToInsert)
canInsertIntoTarget(
projectContents,
metadata,
elementPathTree,
parentTarget,
elementsToInsert,
propertyControlsInfo,
)
) {
return { type: 'parent', parentPath: childInsertionPath(parentTarget) }
}
Expand All @@ -585,6 +596,7 @@ function pasteIntoParentOrGrandparent(
metadata,
parentOfSelected,
elementPathTree,
propertyControlsInfo,
)
) {
return { type: 'parent', parentPath: childInsertionPath(parentOfSelected) }
Expand All @@ -603,6 +615,7 @@ export function applyElementCeilingToReparentTarget(
elementPathTree: ElementPathTrees,
reparentTarget: Either<PasteParentNotFoundError, ReparentTargetForPaste>,
elementCeiling: ElementPath | null,
propertyControlsInfo: PropertyControlsInfo,
): Either<PasteParentNotFoundError, ReparentTargetForPaste> {
if (elementCeiling == null) {
return reparentTarget
Expand All @@ -627,6 +640,7 @@ export function applyElementCeilingToReparentTarget(
elementPathTree,
ceilingStaticPath,
elementsToInsert,
propertyControlsInfo,
)
) {
return right(set(intendedPathOptic, ceilingStaticPath, targetForPaste))
Expand Down Expand Up @@ -656,6 +670,7 @@ export function getTargetParentForOneShotInsertion(
elementsToInsert: JSXElementChild[],
elementPathTree: ElementPathTrees,
insertionCeiling: ElementPath | null,
propertyControlsInfo: PropertyControlsInfo,
): Either<PasteParentNotFoundError, ReparentTargetForPaste> {
if (!isNonEmptyArray(selectedViews)) {
return right({ type: 'parent', parentPath: childInsertionPath(storyboardPath) })
Expand All @@ -671,6 +686,7 @@ export function getTargetParentForOneShotInsertion(
projectContents,
elementPathTree,
elementsToInsert.length,
propertyControlsInfo,
)
if (insertIntoSlotResult != null) {
return right(insertIntoSlotResult)
Expand All @@ -682,6 +698,7 @@ export function getTargetParentForOneShotInsertion(
selectedViews,
metadata,
elementPathTree,
propertyControlsInfo,
)
if (pasteIntoParentOrGrandparentResult != null) {
return applyElementCeilingToReparentTarget(
Expand All @@ -691,6 +708,7 @@ export function getTargetParentForOneShotInsertion(
elementPathTree,
right(pasteIntoParentOrGrandparentResult),
insertionCeiling,
propertyControlsInfo,
)
}
return left('Cannot find a suitable parent')
Expand All @@ -703,6 +721,7 @@ export function getTargetParentForPaste(
metadata: ElementInstanceMetadataMap,
copyData: ParsedCopyData,
elementPathTree: ElementPathTrees,
propertyControlsInfo: PropertyControlsInfo,
): Either<PasteParentNotFoundError, ReparentTargetForPaste> {
if (!isNonEmptyArray(selectedViews)) {
return right({ type: 'parent', parentPath: childInsertionPath(storyboardPath) })
Expand All @@ -725,6 +744,7 @@ export function getTargetParentForPaste(
projectContents,
elementPathTree,
copyData.elementPaste.length,
propertyControlsInfo,
)
if (insertIntoSlotResult != null) {
return right(insertIntoSlotResult)
Expand All @@ -745,6 +765,7 @@ export function getTargetParentForPaste(
selectedViews,
metadata,
elementPathTree,
propertyControlsInfo,
)
if (pasteIntoParentOrGrandparentResult != null) {
return right(pasteIntoParentOrGrandparentResult)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export const setBorderRadiusStrategy: CanvasStrategyFactory = (
canvasState.scale,
canvasState.startingMetadata,
canvasState.startingElementPathTree,
canvasState.propertyControlsInfo,
).has('borderRadius')
if (!canShowBorderRadiusControls) {
return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export const setPaddingStrategy: CanvasStrategyFactory = (canvasState, interacti
canvasState.scale,
canvasState.startingMetadata,
canvasState.startingElementPathTree,
canvasState.propertyControlsInfo,
).has('padding')
if (!canShowPadding) {
return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const runAddContainLayoutIfNeeded: CommandFunction<AddContainLayoutIfNeed
command.element,
editorState.jsxMetadata,
editorState.elementPathTree,
editorState.propertyControlsInfo,
) !== 'supportsChildren'

if (isNotNeeded) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export const runWrapInContainerCommand: CommandFunction<WrapInContainerCommand>
editor.elementPathTree,
wrapperUID,
1,
editor.propertyControlsInfo,
)
if (insertionPath == null) {
return // maybe this should throw instead?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { isInsertMode } from '../../../editor/editor-modes'
import { useRefEditorState } from '../../../editor/store/store-hook'
import type { MouseCallbacks } from '../select-mode/select-mode-hooks'
import { useHighlightCallbacks } from '../select-mode/select-mode-hooks'
import { property } from 'css-tree'

function useGetHighlightableViewsForInsertMode() {
const storeRef = useRefEditorState((store) => {
Expand All @@ -19,10 +20,12 @@ function useGetHighlightableViewsForInsertMode() {
nodeModules: store.editor.nodeModules.files,
remixRoutingTable: store.derived.remixData?.routingTable ?? null,
resolve: resolveFn,
propertyControlsInfo: store.editor.propertyControlsInfo,
}
})
return React.useCallback(() => {
const { componentMetadata, elementPathTree, mode, projectContents } = storeRef.current
const { componentMetadata, elementPathTree, mode, projectContents, propertyControlsInfo } =
storeRef.current
if (isInsertMode(mode)) {
const allPaths = MetadataUtils.getAllPaths(componentMetadata, elementPathTree)
const insertTargets = allPaths.filter((path) => {
Expand All @@ -31,6 +34,7 @@ function useGetHighlightableViewsForInsertMode() {
componentMetadata,
path,
elementPathTree,
propertyControlsInfo,
)
})
return insertTargets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ const NewCanvasControlsInner = (props: NewCanvasControlsInnerProps) => {
EP.fromString(p),
componentMetadata,
pathTrees,
propertyControlsInfo,
),
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { ElementPath } from '../../../../core/shared/project-file-types'
import { treatElementAsGroupLikeFromMetadata } from '../../canvas-strategies/strategies/group-helpers'
import { assertNever } from '../../../../core/shared/utils'
import { mapDropNulls } from '../../../../core/shared/array-utils'
import type { PropertyControlsInfo } from '../../../custom-code/code-file'

export const Emdash: string = '\u2014'

Expand Down Expand Up @@ -202,6 +203,7 @@ export function canShowCanvasPropControl(
scale: number,
metadata: ElementInstanceMetadataMap,
elementPathTree: ElementPathTrees,
propertyControlsInfo: PropertyControlsInfo,
): Set<CanvasPropControl> {
function getControls(element: ElementInstanceMetadata): CanvasPropControl[] {
const frame = zeroRectIfNullOrInfinity(element.globalFrame)
Expand All @@ -225,6 +227,7 @@ export function canShowCanvasPropControl(
element.elementPath,
metadata,
elementPathTree,
propertyControlsInfo,
)
) {
return ['borderRadius', 'gap']
Expand Down
Loading

0 comments on commit d73c6db

Please sign in to comment.