Command bar: add extrude command, nonlinear editing, etc (#1204)

* Tweak toaster look and feel

* Add icons, tweak plus icon names

* Rename commandBarMeta to commandBarConfig

* Refactor command bar, add support for icons

* Create a tailwind plugin for aria-pressed button state

* Remove overlay from behind command bar

* Clean up toolbar

* Button and other style tweaks

* Icon tweaks follow-up: make old icons work with new sizing

* Delete unused static icons

* More CSS tweaks

* Small CSS tweak to project sidebar

* Add command bar E2E test

* fumpt

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* fix typo in a comment

* Fix icon padding (built version only)

* Update onboarding and warning banner icons padding

* Misc minor style fixes

* Get Extrude opening and canceling from command bar

* Iconography tweaks

* Get extrude kind of working

* Refactor command bar config types and organization

* Move command bar configs to be co-located with each other

* Start building a state machine for the command bar

* Start converting command bar to state machine

* Add support for multiple args, confirmation step

* Submission behavior, hotkeys, code organization

* Add new test for extruding from command bar

* Polish step back and selection hotkeys, CSS tweaks

* Loading style tweaks

* Validate selection inputs, polish UX of args re-editing

* Prevent submission with multiple selection on singlular arg

* Remove stray console logs

* Tweak test, CSS nit, remove extrude "result" argument

* Fix linting warnings

* Show Ctrl+/ instead of ⌘K on all platforms but Mac

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Add "Enter sketch" to command bar

* fix command bar test

* Fix flaky cmd bar extrude test by waiting for engine select response

* Cover both button labels '⌘K' and 'Ctrl+/' in test

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Frank Noirot
2023-12-13 12:49:01 -05:00
committed by GitHub
parent b01357b49e
commit d2535bb8c2
60 changed files with 4549 additions and 1939 deletions

View File

@ -1,46 +1,68 @@
import { useEffect } from 'react'
import { AnyStateMachine, StateFrom } from 'xstate'
import {
Command,
CommandBarConfig,
createMachineCommand,
} from '../lib/commands'
import { AnyStateMachine, InterpreterFrom, StateFrom } from 'xstate'
import { createMachineCommand } from '../lib/createMachineCommand'
import { useCommandsContext } from './useCommandsContext'
import { modelingMachine } from 'machines/modelingMachine'
import { authMachine } from 'machines/authMachine'
import { settingsMachine } from 'machines/settingsMachine'
import { homeMachine } from 'machines/homeMachine'
import { Command, CommandSetConfig, CommandSetSchema } from 'lib/commandTypes'
interface UseStateMachineCommandsArgs<T extends AnyStateMachine> {
// This might not be necessary, AnyStateMachine from xstate is working
export type AllMachines =
| typeof modelingMachine
| typeof settingsMachine
| typeof authMachine
| typeof homeMachine
interface UseStateMachineCommandsArgs<
T extends AllMachines,
S extends CommandSetSchema<T>
> {
machineId: T['id']
state: StateFrom<T>
send: Function
commandBarConfig?: CommandBarConfig<T>
commands: Command[]
owner: string
actor?: InterpreterFrom<T>
commandBarConfig?: CommandSetConfig<T, S>
onCancel?: () => void
}
export default function useStateMachineCommands<T extends AnyStateMachine>({
export default function useStateMachineCommands<
T extends AnyStateMachine,
S extends CommandSetSchema<T>
>({
machineId,
state,
send,
actor,
commandBarConfig,
owner,
}: UseStateMachineCommandsArgs<T>) {
const { addCommands, removeCommands } = useCommandsContext()
onCancel,
}: UseStateMachineCommandsArgs<T, S>) {
const { commandBarSend } = useCommandsContext()
useEffect(() => {
const newCommands = state.nextEvents
.filter((e) => !['done.', 'error.'].some((n) => e.includes(n)))
.map((type) =>
createMachineCommand<T>({
createMachineCommand<T, S>({
ownerMachine: machineId,
type,
state,
send,
actor,
commandBarConfig,
owner,
onCancel,
})
)
.filter((c) => c !== null) as Command[] // TS isn't smart enough to know this filter removes nulls
addCommands(newCommands)
commandBarSend({ type: 'Add commands', data: { commands: newCommands } })
return () => {
removeCommands(newCommands)
commandBarSend({
type: 'Remove commands',
data: { commands: newCommands },
})
}
}, [state])
}