Skip to content

Commit

Permalink
feat: implement nesting via menu operation
Browse files Browse the repository at this point in the history
  • Loading branch information
ChibiBlasphem committed Jan 9, 2025
1 parent 6f2754a commit 378c718
Show file tree
Hide file tree
Showing 22 changed files with 331 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '@app-builder/services/editor/ast-editor';
import {
useDefaultCoerceToConstant,
useGetAstNodeOption,
useGetAstNodeOperandProps,
useOperandOptions,
} from '@app-builder/services/editor/options';
import { useFormatReturnValue } from '@app-builder/services/editor/return-value';
Expand Down Expand Up @@ -82,14 +82,14 @@ export function OperandBuilderNode({
onSave?: (astNode: AstNode) => void;
}) {
const enumValues = useEnumValuesFromNeighbour(treePath);
const getAstNodeOption = useGetAstNodeOption();

const options = useOperandOptions(enumValues);
const coerceToConstant = useDefaultCoerceToConstant();

const operandProps = React.useMemo(() => {
return getAstNodeOption(astNode, { enumValues });
}, [astNode, enumValues, getAstNodeOption]);
const getAstNodeOperandProps = useGetAstNodeOperandProps();
const astNodeOperandProps = React.useMemo(() => {
return getAstNodeOperandProps(astNode, { enumValues });
}, [astNode, enumValues, getAstNodeOperandProps]);

const evaluation = useEvaluation(treePath);
const formatReturnValue = useFormatReturnValue();
Expand All @@ -110,7 +110,7 @@ export function OperandBuilderNode({
validationStatus={validationStatus}
astNodeErrors={evaluation}
returnValue={returnValue}
{...operandProps}
{...astNodeOperandProps}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@ import {
useEvaluationErrors,
} from '@app-builder/services/editor/ast-editor';
import { useMainAstOperatorFunctions } from '@app-builder/services/editor/options';
import clsx from 'clsx';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { Switch } from 'ui-design-system';
import {
MenuButton,
MenuItem,
MenuPopover,
MenuRoot,
ScrollAreaV2,
Switch,
} from 'ui-design-system';

import { AstBuilderNode } from './AstBuilderNode';
import { Operator } from './Operator';
Expand Down Expand Up @@ -42,10 +50,22 @@ export function MainAstBinaryOperatorLine({
setAstNodeAtPath(stringPath, NewNestedChild(child));
}

function removeNestedChild(stringPath: string, child: AstNode) {
const nestedChild = child.children[0];
function removeNesting() {
const nestedChild = mainAstNode.children[0];
if (!nestedChild) return;
setAstNodeAtPath(stringPath, nestedChild);
setAstNodeAtPath(treePath, nestedChild);
}

function invertOperands() {
const leftChild = mainAstNode.children[0];
const rightChild = mainAstNode.children[1];

if (!leftChild || !rightChild) return;

setAstNodeAtPath(treePath, {
...mainAstNode,
children: [rightChild, leftChild],
});
}

const operators = useMainAstOperatorFunctions();
Expand All @@ -60,11 +80,14 @@ export function MainAstBinaryOperatorLine({
const evaluationErrors = useEvaluationErrors(treePath);

const children = (
<>
<div className="group/nest contents">
{!root ? (
<span className="text-grey-100 border-grey-10 flex h-10 items-center justify-center rounded border px-2">
<NestingParenthesis
invertOperands={invertOperands}
removeNesting={removeNesting}
>
(
</span>
</NestingParenthesis>
) : null}
<AstBuilderNode
treePath={leftPath}
Expand Down Expand Up @@ -92,11 +115,14 @@ export function MainAstBinaryOperatorLine({
viewOnly={viewOnly}
/>
{!root ? (
<span className="text-grey-100 border-grey-10 flex h-10 items-center justify-center rounded border px-2">
<NestingParenthesis
invertOperands={invertOperands}
removeNesting={removeNesting}
>
)
</span>
</NestingParenthesis>
) : null}
</>
</div>
);

// remove the <div> root wrapper to flatten the structure and use a single root flex-wrap
Expand All @@ -122,6 +148,12 @@ export function MainAstUnaryOperatorLine({
}) {
const { setAstNodeAtPath, setOperatorAtPath } = useAstNodeEditorActions();

function removeNesting() {
const nestedChild = mainAstNode.children[0];
if (!nestedChild) return;
setAstNodeAtPath(treePath, nestedChild);
}

const operators = useMainAstOperatorFunctions();

const left = mainAstNode.children[0];
Expand All @@ -130,28 +162,34 @@ export function MainAstUnaryOperatorLine({
const evaluationErrors = useEvaluationErrors(treePath);

return (
<div className="flex justify-between gap-2">
<div className="flex flex-row flex-wrap items-center gap-2">
{!root ? <span className="text-grey-25">(</span> : null}
<AstBuilderNode
treePath={leftPath}
astNode={left}
onSave={(astNode) => {
setAstNodeAtPath(leftPath, astNode);
}}
viewOnly={viewOnly}
/>
<Operator
value={mainAstNode.name}
setValue={(operator: (typeof operators)[number]) => {
setOperatorAtPath(treePath, operator);
}}
validationStatus={evaluationErrors.length > 0 ? 'error' : 'valid'}
viewOnly={viewOnly}
operators={operators}
/>
{!root ? <span className="text-grey-25">)</span> : null}
</div>
<div className="group/nest contents">
{!root ? (
<NestingParenthesis unary removeNesting={removeNesting}>
(
</NestingParenthesis>
) : null}
<AstBuilderNode
treePath={leftPath}
astNode={left}
onSave={(astNode) => {
setAstNodeAtPath(leftPath, astNode);
}}
viewOnly={viewOnly}
/>
<Operator
value={mainAstNode.name}
setValue={(operator: (typeof operators)[number]) => {
setOperatorAtPath(treePath, operator);
}}
validationStatus={evaluationErrors.length > 0 ? 'error' : 'valid'}
viewOnly={viewOnly}
operators={operators}
/>
{!root ? (
<NestingParenthesis unary removeNesting={removeNesting}>
)
</NestingParenthesis>
) : null}
</div>
);
}
Expand All @@ -174,3 +212,42 @@ function NestSwitch({
</div>
);
}

type NestingParenthesisProps = {
children: React.ReactNode;
removeNesting: () => void;
} & ({ unary: true } | { unary?: false; invertOperands: () => void });

const NestingParenthesis = ({
children,
removeNesting,
...props
}: NestingParenthesisProps) => {
return (
<MenuRoot>
<MenuButton
render={
<button className="text-grey-100 border-grey-10 [.group\/nest:hover:not(:has(.group\/nest:hover))_>_&]:bg-blue-10 flex h-10 items-center justify-center rounded border px-2 [.group\/nest:hover:not(:has(.group\/nest:hover))_>_&]:border-blue-50" />
}
>
{children}
</MenuButton>
<MenuPopover className="flex flex-col gap-2 p-2">
{!props.unary ? (
<MenuItem
onClick={props.invertOperands}
className="data-[active-item]:bg-purple-05 rounded p-2 outline-none"
>
Invert operands
</MenuItem>
) : null}
<MenuItem
onClick={removeNesting}
className="data-[active-item]:bg-purple-05 rounded p-2 outline-none"
>
Delete nesting
</MenuItem>
</MenuPopover>
</MenuRoot>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
type AstNodeErrors,
type ValidationStatus,
} from '@app-builder/services/validation/ast-node-validation';
import { type OperandOption } from '@app-builder/types/operand-options';
import { cva } from 'class-variance-authority';

import { OperandEditor } from './OperandEditor';
Expand Down Expand Up @@ -39,12 +40,7 @@ export function Operand({
viewOnly?: boolean;
validationStatus: ValidationStatus;
astNodeErrors?: AstNodeErrors;
options: {
astNode: AstNode;
dataType: DataType;
operandType: OperandType;
displayName: string;
}[];
options: OperandOption[];
coerceToConstant?: (searchValue: string) => {
astNode: ConstantAstNode<ConstantType>;
displayName: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '@app-builder/models/editable-operators';
import {
useDefaultCoerceToConstant,
useGetAstNodeOption,
useGetAstNodeOperandProps,
useOperandOptions,
} from '@app-builder/services/editor/options';
import {
Expand Down Expand Up @@ -201,15 +201,15 @@ function FilterValue({
// TODO: try to get enum values from the left operand
const filterOptions = useOperandOptions([]);
const coerceToConstant = useDefaultCoerceToConstant();
const getAstNodeOption = useGetAstNodeOption();
const getAstNodeOperandProps = useGetAstNodeOperandProps();

const operandProps = useMemo(() => {
return getAstNodeOption(filterValue);
}, [filterValue, getAstNodeOption]);
const astNodeOperandProps = useMemo(() => {
return getAstNodeOperandProps(filterValue);
}, [filterValue, getAstNodeOperandProps]);

return (
<Operand
{...operandProps}
{...astNodeOperandProps}
onSave={onSave}
options={filterOptions}
coerceToConstant={coerceToConstant}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type AstNode } from '@app-builder/models';
import {
useDefaultCoerceToConstant,
useGetAstNodeOption,
useGetAstNodeOperandProps,
useOperandOptions,
} from '@app-builder/services/editor/options';
import {
Expand Down Expand Up @@ -40,12 +40,10 @@ export function LeftOperand({
[defaultCoerceToConstant],
);

const getAstNodeOption = useGetAstNodeOption();

const operandProps = React.useMemo(
() => getAstNodeOption(astNode),
[astNode, getAstNodeOption],
);
const getAstNodeOperandProps = useGetAstNodeOperandProps();
const astNodeOperandProps = React.useMemo(() => {
return getAstNodeOperandProps(astNode);
}, [astNode, getAstNodeOperandProps]);

return (
<Operand
Expand All @@ -55,7 +53,7 @@ export function LeftOperand({
coerceToConstant={coerceToConstant}
validationStatus={validationStatus}
astNodeErrors={astNodeErrors}
{...operandProps}
{...astNodeOperandProps}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type AstNode } from '@app-builder/models';
import {
useDefaultCoerceToConstant,
useGetAstNodeOption,
useGetAstNodeOperandProps,
useOperandOptions,
} from '@app-builder/services/editor/options';
import {
Expand Down Expand Up @@ -47,12 +47,10 @@ export function RightOperand({
[defaultCoerceToConstant],
);

const getAstNodeOption = useGetAstNodeOption();

const operandProps = React.useMemo(
() => getAstNodeOption(astNode),
[astNode, getAstNodeOption],
);
const getAstNodeOperandProps = useGetAstNodeOperandProps();
const astNodeOperandProps = React.useMemo(() => {
return getAstNodeOperandProps(astNode);
}, [astNode, getAstNodeOperandProps]);

return (
<Operand
Expand All @@ -62,7 +60,7 @@ export function RightOperand({
coerceToConstant={coerceToConstant}
validationStatus={validationStatus}
astNodeErrors={astNodeErrors}
{...operandProps}
{...astNodeOperandProps}
/>
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type AstNode } from '@app-builder/models';
import {
useDefaultCoerceToConstant,
useGetAstNodeOption,
useGetAstNodeOperandProps,
useOperandOptions,
} from '@app-builder/services/editor/options';
import {
Expand Down Expand Up @@ -43,11 +43,10 @@ export const LeftOperand = ({
[defaultCoerceToConstant],
);

const getAstNodeOption = useGetAstNodeOption();
const operandProps = useMemo(
() => getAstNodeOption(astNode),
[astNode, getAstNodeOption],
);
const getAstNodeOperandProps = useGetAstNodeOperandProps();
const astNodeOperandProps = useMemo(() => {
return getAstNodeOperandProps(astNode);
}, [astNode, getAstNodeOperandProps]);

return (
<Operand
Expand All @@ -56,7 +55,7 @@ export const LeftOperand = ({
coerceToConstant={coerceToConstant}
astNodeErrors={astNodeErrors}
validationStatus={validationStatus}
{...operandProps}
{...astNodeOperandProps}
/>
);
};
Loading

0 comments on commit 378c718

Please sign in to comment.