Add ability to create named constant without code (#5840)
* Add support for forcing kcl input create variable * Command palette padding tweak * Make traverse function work for ExpressionStatements * Add utilities for getting earliest safe index in AST * Fix the insertIndex logic to not be based on the selection anymore * Add workflow to create a named constant * Fix bug with nameEndInDigits matcher * Tweak command config * Add a three-dot menu to feature tree pane to create parameters * Add E2E test for create parameter flow * Remove edit flow oops * Fix tsc error * Fix E2E test * Update named constant position in edit flow test * Add tags into consideration for safe insert index Per @Irev-dev's helpful feedback, with unit tests!
This commit is contained in:
@ -114,7 +114,7 @@ export const CommandBar = () => {
|
||||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
<WrapperComponent.Panel
|
||||
className="relative z-50 pointer-events-auto w-full max-w-xl py-2 mx-auto border rounded rounded-tl-none shadow-lg bg-chalkboard-10 dark:bg-chalkboard-100 dark:border-chalkboard-70"
|
||||
className="relative z-50 pointer-events-auto w-full max-w-xl pt-2 mx-auto border rounded rounded-tl-none shadow-lg bg-chalkboard-10 dark:bg-chalkboard-100 dark:border-chalkboard-70"
|
||||
as="div"
|
||||
data-testid="command-bar"
|
||||
>
|
||||
|
@ -81,7 +81,8 @@ function CommandBarKclInput({
|
||||
const [value, setValue] = useState(initialValue)
|
||||
const [createNewVariable, setCreateNewVariable] = useState(
|
||||
(previouslySetValue && 'variableName' in previouslySetValue) ||
|
||||
arg.createVariableByDefault ||
|
||||
arg.createVariable === 'byDefault' ||
|
||||
arg.createVariable === 'force' ||
|
||||
false
|
||||
)
|
||||
const [canSubmit, setCanSubmit] = useState(true)
|
||||
@ -248,7 +249,7 @@ function CommandBarKclInput({
|
||||
</span>
|
||||
</label>
|
||||
{createNewVariable ? (
|
||||
<div className="flex items-baseline gap-4 mx-4 border-solid border-0 border-b border-chalkboard-50">
|
||||
<div className="flex mb-2 items-baseline gap-4 mx-4 border-solid border-0 border-b border-chalkboard-50">
|
||||
<label
|
||||
htmlFor="variable-name"
|
||||
className="text-base text-chalkboard-80 dark:text-chalkboard-20"
|
||||
@ -269,7 +270,11 @@ function CommandBarKclInput({
|
||||
autoFocus
|
||||
onChange={(e) => setNewVariableName(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.currentTarget.value === '' && e.key === 'Backspace') {
|
||||
if (
|
||||
e.currentTarget.value === '' &&
|
||||
e.key === 'Backspace' &&
|
||||
arg.createVariable !== 'force'
|
||||
) {
|
||||
setCreateNewVariable(false)
|
||||
}
|
||||
}}
|
||||
@ -290,15 +295,17 @@ function CommandBarKclInput({
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex justify-between gap-2 px-4">
|
||||
<button
|
||||
onClick={() => setCreateNewVariable(true)}
|
||||
className="text-blue border-none bg-transparent font-sm flex gap-1 items-center pl-0 pr-1"
|
||||
>
|
||||
<CustomIcon name="plus" className="w-5 h-5" />
|
||||
Create new variable
|
||||
</button>
|
||||
</div>
|
||||
arg.createVariable !== 'disallow' && (
|
||||
<div className="flex justify-between gap-2 px-4">
|
||||
<button
|
||||
onClick={() => setCreateNewVariable(true)}
|
||||
className="text-blue border-none bg-transparent font-sm flex gap-1 items-center pl-0 pr-1"
|
||||
>
|
||||
<CustomIcon name="plus" className="w-5 h-5" />
|
||||
Create new variable
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</form>
|
||||
)
|
||||
|
@ -0,0 +1,51 @@
|
||||
import { Menu } from '@headlessui/react'
|
||||
import { PropsWithChildren } from 'react'
|
||||
import { ActionIcon } from 'components/ActionIcon'
|
||||
import styles from './KclEditorMenu.module.css'
|
||||
import { commandBarActor } from 'machines/commandBarMachine'
|
||||
|
||||
export const FeatureTreeMenu = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
<Menu>
|
||||
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
|
||||
<div
|
||||
className="relative"
|
||||
onClick={(e) => {
|
||||
const target = e.target as HTMLElement
|
||||
if (e.eventPhase === 3 && target.closest('a') === null) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Menu.Button className="!p-0 !bg-transparent hover:text-primary border-transparent dark:!border-transparent hover:!border-primary dark:hover:!border-chalkboard-70 ui-open:!border-primary dark:ui-open:!border-chalkboard-70 !outline-none">
|
||||
<ActionIcon
|
||||
icon="three-dots"
|
||||
className="p-1"
|
||||
size="sm"
|
||||
bgClassName="bg-transparent dark:bg-transparent"
|
||||
iconClassName={'!text-chalkboard-90 dark:!text-chalkboard-40'}
|
||||
/>
|
||||
</Menu.Button>
|
||||
<Menu.Items className="absolute right-0 left-auto w-72 flex flex-col gap-1 divide-y divide-chalkboard-20 dark:divide-chalkboard-70 align-stretch px-0 py-1 bg-chalkboard-10 dark:bg-chalkboard-100 rounded-sm shadow-lg border border-solid border-chalkboard-20/50 dark:border-chalkboard-80/50">
|
||||
<Menu.Item>
|
||||
<button
|
||||
onClick={() =>
|
||||
commandBarActor.send({
|
||||
type: 'Find and select command',
|
||||
data: {
|
||||
groupId: 'modeling',
|
||||
name: 'event.parameter.create',
|
||||
},
|
||||
})
|
||||
}
|
||||
className={styles.button}
|
||||
>
|
||||
<span>Create parameter</span>
|
||||
</button>
|
||||
</Menu.Item>
|
||||
</Menu.Items>
|
||||
</div>
|
||||
</Menu>
|
||||
)
|
||||
}
|
@ -19,6 +19,7 @@ import { ContextFrom } from 'xstate'
|
||||
import { settingsMachine } from 'machines/settingsMachine'
|
||||
import { FeatureTreePane } from './FeatureTreePane'
|
||||
import { kclErrorsByFilename } from 'lang/errors'
|
||||
import { FeatureTreeMenu } from './FeatureTreeMenu'
|
||||
|
||||
export type SidebarType =
|
||||
| 'code'
|
||||
@ -85,6 +86,7 @@ export const sidebarPanes: SidebarPane[] = [
|
||||
id={props.id}
|
||||
icon="model"
|
||||
title="Feature Tree"
|
||||
Menu={FeatureTreeMenu}
|
||||
onClose={props.onClose}
|
||||
/>
|
||||
<FeatureTreePane />
|
||||
|
Reference in New Issue
Block a user