import { WheelEvent, useRef, useMemo } from 'react' import { isCursorInSketchCommandRange } from 'lang/util' import { engineCommandManager } from './lang/std/engineConnection' import { useModelingContext } from 'hooks/useModelingContext' import { useCommandsContext } from 'hooks/useCommandsContext' import { ActionButton } from 'components/ActionButton' import usePlatform from 'hooks/usePlatform' export const Toolbar = () => { const platform = usePlatform() const { commandBarSend } = useCommandsContext() const { state, send, context } = useModelingContext() const toolbarButtonsRef = useRef(null) const bgClassName = 'group-enabled:group-hover:bg-energy-10 group-pressed:bg-energy-10 dark:group-enabled:group-hover:bg-chalkboard-80 dark:group-pressed:bg-chalkboard-80' const pathId = useMemo( () => isCursorInSketchCommandRange( engineCommandManager.artifactMap, context.selectionRanges ), [engineCommandManager.artifactMap, context.selectionRanges] ) function handleToolbarButtonsWheelEvent(ev: WheelEvent) { const span = toolbarButtonsRef.current if (!span) { return } span.scrollLeft = span.scrollLeft += ev.deltaY } function ToolbarButtons({ className = '', ...props }: React.HTMLAttributes) { return (
    {state.nextEvents.includes('Enter sketch') && (
  • send({ type: 'Enter sketch' })} icon={{ icon: 'sketch', bgClassName, }} > Start Sketch
  • )} {state.nextEvents.includes('Enter sketch') && pathId && (
  • send({ type: 'Enter sketch' })} icon={{ icon: 'sketch', bgClassName, }} > Edit Sketch
  • )} {state.nextEvents.includes('Cancel') && !state.matches('idle') && (
  • send({ type: 'Cancel' })} icon={{ icon: 'arrowLeft', bgClassName, }} > Exit Sketch
  • )} {state.matches('Sketch') && !state.matches('idle') && ( <>
  • state?.matches('Sketch.Line tool') ? send('CancelSketch') : send('Equip Line tool') } aria-pressed={state?.matches('Sketch.Line tool')} className="pressed:bg-energy-10/20 dark:pressed:bg-energy-80" icon={{ icon: 'line', bgClassName, }} > Line
  • state.matches('Sketch.Tangential arc to') ? send('CancelSketch') : send('Equip tangential arc to') } aria-pressed={state.matches('Sketch.Tangential arc to')} className="pressed:bg-energy-10/20 dark:pressed:bg-energy-80" icon={{ icon: 'line', bgClassName, }} disabled={ !state.can('Equip tangential arc to') && !state.matches('Sketch.Tangential arc to') } > Tangential Arc
  • )} {state.matches('Sketch.SketchIdle') && state.nextEvents .filter( (eventName) => eventName.includes('Make segment') || eventName.includes('Constrain') ) .sort((a, b) => { const aisEnabled = state.nextEvents .filter((event) => state.can(event as any)) .includes(a) const bIsEnabled = state.nextEvents .filter((event) => state.can(event as any)) .includes(b) if (aisEnabled && !bIsEnabled) { return -1 } if (!aisEnabled && bIsEnabled) { return 1 } return 0 }) .map((eventName) => (
  • send(eventName)} disabled={ !state.nextEvents .filter((event) => state.can(event as any)) .includes(eventName) } title={eventName} icon={{ icon: 'line', bgClassName, }} > {eventName .replace('Make segment ', '') .replace('Constrain ', '')}
  • ))} {state.matches('idle') && (
  • commandBarSend({ type: 'Find and select command', data: { name: 'Extrude', ownerMachine: 'modeling' }, }) } disabled={!state.can('Extrude')} title={ state.can('Extrude') ? 'extrude' : 'sketches need to be closed, or not already extruded' } icon={{ icon: 'extrude', bgClassName, }} > Extrude
  • )}
) } return (
commandBarSend({ type: 'Open' })} className="rounded-r-full pr-4 self-stretch border-energy-10 hover:border-energy-10 dark:border-chalkboard-80 bg-energy-10/50 hover:bg-energy-10 dark:bg-chalkboard-80 dark:text-energy-10" > {platform === 'darwin' ? '⌘K' : 'Ctrl+/'}
) }