From b35dbefbbb5f3f63d92e1bb7aa4c7eeca8280308 Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Tue, 10 Oct 2023 17:32:36 -0400 Subject: [PATCH 01/10] feat(components): create base deck fixture components creates single slot, staging area, and waste chute components to be used by the existing BaseDeck component. BaseDeck now receives a deckConfig prop describing a robot deck configuration of fixures. the deck fixture components render SVGs corresponding to the fixture areas and slot clips provided by each fixture type closes RAUT-783 --- .../AddDeckConfigurationModal.tsx | 4 +- .../DeviceDetailsDeckConfiguration/index.tsx | 10 +- .../LocationConflictModal.tsx | 12 +- .../SetupModuleAndDeck/SetupFixtureList.tsx | 3 +- .../SetupModuleAndDeck/SetupModulesList.tsx | 5 +- ...seModuleRenderInfoForProtocolById.test.tsx | 6 +- .../MoveLabwareInterventionContent.tsx | 2 +- app/src/resources/deck_configuration/hooks.ts | 4 +- .../BaseDeck/BaseDeck.stories.tsx | 34 ++- .../BaseDeck/SingleSlotFixture.tsx | 196 ++++++++++++++++++ .../src/hardware-sim/BaseDeck/SlotBase.tsx | 5 + .../src/hardware-sim/BaseDeck/SlotClip.tsx | 13 ++ .../BaseDeck/StagingAreaFixture.tsx | 112 ++++++++++ .../BaseDeck/WasteChuteFixture.tsx | 58 ++++++ .../BaseDeck/WasteChuteStagingAreaFixture.tsx | 62 ++++++ .../BaseDeck/__fixtures__/index.ts | 137 ++++++++++++ .../src/hardware-sim/BaseDeck/index.tsx | 94 +++++++-- .../src/hardware-sim/Deck/FlexTrash.tsx | 41 ++-- .../hardware-sim/Deck/MoveLabwareOnDeck.tsx | 8 +- .../src/hardware-sim/Deck/RobotWorkSpace.tsx | 7 +- .../src/hardware-sim/Deck/StyledDeck.tsx | 12 +- .../DeckConfigurator/EmptyFixture.tsx | 6 +- .../DeckConfigurator/StagingAreaFixture.tsx | 6 +- .../DeckConfigurator/TrashBinFixture.tsx | 8 +- .../DeckConfigurator/WasteChuteFixture.tsx | 6 +- .../hardware-sim/DeckConfigurator/index.tsx | 6 +- .../src/components/DeckSetup/index.tsx | 4 +- .../src/file-data/selectors/fileCreator.ts | 4 +- shared-data/js/types.ts | 16 +- .../protocol/types/schemaV7/command/setup.ts | 3 +- 30 files changed, 804 insertions(+), 80 deletions(-) create mode 100644 components/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx create mode 100644 components/src/hardware-sim/BaseDeck/SlotBase.tsx create mode 100644 components/src/hardware-sim/BaseDeck/SlotClip.tsx create mode 100644 components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx create mode 100644 components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx create mode 100644 components/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx create mode 100644 components/src/hardware-sim/BaseDeck/__fixtures__/index.ts diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/AddDeckConfigurationModal.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/AddDeckConfigurationModal.tsx index 02e9fab7fa4..db0292d653e 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/AddDeckConfigurationModal.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/AddDeckConfigurationModal.tsx @@ -28,12 +28,12 @@ import { TertiaryButton } from '../../atoms/buttons' import { Modal } from '../../molecules/Modal' import { LegacyModal } from '../../molecules/LegacyModal' -import type { FixtureLoadName } from '@opentrons/shared-data' +import type { Cutout, FixtureLoadName } from '@opentrons/shared-data' import type { ModalHeaderBaseProps } from '../../molecules/Modal/types' import type { LegacyModalProps } from '../../molecules/LegacyModal' interface AddDeckConfigurationModalProps { - fixtureLocation: string + fixtureLocation: Cutout setShowAddFixtureModal: (showAddFixtureModal: boolean) => void isOnDevice?: boolean } diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx index eba66844ce7..ee6d9403d84 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx @@ -29,6 +29,8 @@ import { StyledText } from '../../atoms/text' import { DeckFixtureSetupInstructionsModal } from './DeckFixtureSetupInstructionsModal' import { AddDeckConfigurationModal } from './AddDeckConfigurationModal' +import type { Cutout } from '@opentrons/shared-data' + interface DeviceDetailsDeckConfigurationProps { robotName: string } @@ -47,17 +49,17 @@ export function DeviceDetailsDeckConfiguration({ const [ targetFixtureLocation, setTargetFixtureLocation, - ] = React.useState('') + ] = React.useState(null) const deckConfig = useDeckConfigurationQuery().data ?? [] const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation() - const handleClickAdd = (fixtureLocation: string): void => { + const handleClickAdd = (fixtureLocation: Cutout): void => { setTargetFixtureLocation(fixtureLocation) setShowAddFixtureModal(true) } - const handleClickRemove = (fixtureLocation: string): void => { + const handleClickRemove = (fixtureLocation: Cutout): void => { updateDeckConfiguration({ fixtureLocation, loadName: STANDARD_SLOT_LOAD_NAME, @@ -71,7 +73,7 @@ export function DeviceDetailsDeckConfiguration({ return ( <> - {showAddFixtureModal ? ( + {showAddFixtureModal && targetFixtureLocation != null ? ( void - cutout: string + cutout: Cutout requiredFixture?: FixtureLoadName requiredModule?: ModuleModel } diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx index 3005891a175..11beb6697f5 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx @@ -33,6 +33,7 @@ import { LocationConflictModal } from './LocationConflictModal' import { getFixtureImage } from './utils' import type { LoadedFixturesBySlot } from '@opentrons/api-client' +import type { Cutout } from '@opentrons/shared-data' interface SetupFixtureListProps { loadedFixturesBySlot: LoadedFixturesBySlot @@ -100,7 +101,7 @@ export const SetupFixtureList = (props: SetupFixtureListProps): JSX.Element => { interface FixtureListItemProps { loadedFixtures: LoadFixtureRunTimeCommand[] loadName: FixtureLoadName - cutout: string + cutout: Cutout commandId: string } diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupModulesList.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupModulesList.tsx index ca4131d5821..ab64efde649 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupModulesList.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupModulesList.tsx @@ -49,7 +49,7 @@ import { ModuleWizardFlows } from '../../../ModuleWizardFlows' import { LocationConflictModal } from './LocationConflictModal' import { getModuleImage } from './utils' -import type { ModuleModel, Fixture } from '@opentrons/shared-data' +import type { Cutout, ModuleModel, Fixture } from '@opentrons/shared-data' import type { AttachedModule } from '../../../../redux/modules/types' import type { ProtocolCalibrationStatus } from '../../hooks' @@ -351,7 +351,8 @@ export function ModulesListItem({ {showLocationConflictModal ? ( setShowLocationConflictModal(false)} - cutout={slotName} + // TODO(bh, 2023-10-10): when module caddies are fixtures, narrow slotName to Cutout and remove type assertion + cutout={slotName as Cutout} requiredModule={moduleModel} /> ) : null} diff --git a/app/src/organisms/Devices/hooks/__tests__/useModuleRenderInfoForProtocolById.test.tsx b/app/src/organisms/Devices/hooks/__tests__/useModuleRenderInfoForProtocolById.test.tsx index b30d436bc61..9fbe83dc694 100644 --- a/app/src/organisms/Devices/hooks/__tests__/useModuleRenderInfoForProtocolById.test.tsx +++ b/app/src/organisms/Devices/hooks/__tests__/useModuleRenderInfoForProtocolById.test.tsx @@ -109,7 +109,7 @@ const MAGNETIC_MODULE_INFO = { nestedLabwareId: null, nestedLabwareDisplayName: null, protocolLoadOrder: 0, - slotName: '1', + slotName: 'D1', } const TEMPERATURE_MODULE_INFO = { @@ -122,12 +122,12 @@ const TEMPERATURE_MODULE_INFO = { nestedLabwareId: null, nestedLabwareDisplayName: null, protocolLoadOrder: 0, - slotName: '1', + slotName: 'D1', } const mockFixture = { fixtureId: 'mockId', - fixtureLocation: '1', + fixtureLocation: 'D1', loadName: STAGING_AREA_LOAD_NAME, } as Fixture diff --git a/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx b/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx index 81c667ba048..4a84ee449e1 100644 --- a/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx +++ b/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx @@ -198,7 +198,7 @@ export function MoveLabwareInterventionContent({ loadedModules={run.modules} loadedLabware={run.labware} // TODO(bh, 2023-07-19): read trash slot name from protocol - trashSlotName={robotType === 'OT-3 Standard' ? 'A3' : undefined} + trashLocation={robotType === 'OT-3 Standard' ? 'A3' : undefined} backgroundItems={ <> {moduleRenderInfo.map( diff --git a/app/src/resources/deck_configuration/hooks.ts b/app/src/resources/deck_configuration/hooks.ts index 8388cfab084..7658ccd318e 100644 --- a/app/src/resources/deck_configuration/hooks.ts +++ b/app/src/resources/deck_configuration/hooks.ts @@ -1,4 +1,5 @@ import { useDeckConfigurationQuery } from '@opentrons/react-api-client' +import { STANDARD_SLOT_LOAD_NAME } from '@opentrons/shared-data' import type { Fixture, LoadFixtureRunTimeCommand } from '@opentrons/shared-data' @@ -34,7 +35,8 @@ export function useLoadedFixturesConfigStatus( configurationStatus = CONFIGURED } else if ( deckConfigurationAtLocation != null && - deckConfigurationAtLocation.loadName !== loadedFixture.params.loadName + deckConfigurationAtLocation.loadName !== loadedFixture.params.loadName && + deckConfigurationAtLocation.loadName !== STANDARD_SLOT_LOAD_NAME ) { configurationStatus = CONFLICTING } diff --git a/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx b/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx index 76d8598cabd..a5de0777a58 100644 --- a/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx +++ b/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx @@ -1,9 +1,17 @@ import * as React from 'react' import fixture_96_plate from '@opentrons/shared-data/labware/fixtures/2/fixture_96_plate.json' import fixture_tiprack_1000_ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_1000_ul.json' -import { FLEX_ROBOT_TYPE, LabwareDefinition2 } from '@opentrons/shared-data' +import { + DeckConfiguration, + FLEX_ROBOT_TYPE, + LabwareDefinition2, +} from '@opentrons/shared-data' import type { Meta, StoryObj } from '@storybook/react' +import { + EXTENDED_DECK_CONFIG_FIXTURE, + STANDARD_SLOT_DECK_CONFIG_FIXTURE, +} from './__fixtures__' import { BaseDeck as BaseDeckComponent } from './' import { HEATERSHAKER_MODULE_V1, @@ -15,16 +23,30 @@ import { const meta: Meta> = { component: BaseDeckComponent, title: 'Library/Molecules/Simulation/BaseDeck', + argTypes: { + deckConfig: { + // options: [ + // EXTENDED_DECK_CONFIG_FIXTURE, + // STANDARD_SLOT_DECK_CONFIG_FIXTURE, + // ], + options: ['single slot deck', 'staging area deck'], + control: { type: 'radio' }, + }, + }, } as Meta export default meta type Story = StoryObj> +const getDeckConfig = (args: any): DeckConfiguration => + args.deckConfig === 'staging area deck' + ? EXTENDED_DECK_CONFIG_FIXTURE + : STANDARD_SLOT_DECK_CONFIG_FIXTURE + export const BaseDeck: Story = { - render: args => , args: { robotType: FLEX_ROBOT_TYPE, - trashSlotName: 'A3', + deckConfig: EXTENDED_DECK_CONFIG_FIXTURE, labwareLocations: [ { labwareLocation: { slotName: 'C2' }, @@ -48,7 +70,7 @@ export const BaseDeck: Story = { nestedLabwareDef: fixture_96_plate as LabwareDefinition2, }, { - moduleLocation: { slotName: 'D3' }, + moduleLocation: { slotName: 'B3' }, moduleModel: HEATERSHAKER_MODULE_V1, nestedLabwareDef: fixture_96_plate as LabwareDefinition2, }, @@ -61,4 +83,8 @@ export const BaseDeck: Story = { darkFill: 'rebeccapurple', lightFill: 'lavender', }, + render: args => { + const deckConfig = getDeckConfig(args) + return + }, } diff --git a/components/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx b/components/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx new file mode 100644 index 00000000000..2dbbe04f915 --- /dev/null +++ b/components/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx @@ -0,0 +1,196 @@ +import * as React from 'react' + +import { SlotBase } from './SlotBase' +import { SlotClip } from './SlotClip' + +import type { Cutout, DeckDefinition, ModuleType } from '@opentrons/shared-data' + +interface SingleSlotFixtureProps extends React.SVGProps { + cutoutLocation: Cutout + deckDefinition: DeckDefinition + moduleType?: ModuleType + fixtureBaseColor?: React.SVGProps['fill'] + slotClipColor?: React.SVGProps['stroke'] + showExtensions?: boolean +} + +export function SingleSlotFixture( + props: SingleSlotFixtureProps +): JSX.Element | null { + const { + cutoutLocation, + deckDefinition, + fixtureBaseColor, + slotClipColor, + showExtensions, + ...restProps + } = props + + // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key + const cutoutDef = deckDefinition?.locations.orderedSlots.find( + s => s.id === cutoutLocation + ) + if (cutoutDef == null) { + console.warn( + `cannot render SingleSlotFixture, no cutout named: ${cutoutDef} in deck def ${deckDefinition?.otId}` + ) + return null + } + + const contentsByCutoutLocation: { + [cutoutLocation in Cutout]: JSX.Element + } = { + A1: ( + <> + {showExtensions ? ( + + ) : null} + + + + + + + ), + A2: ( + <> + + , + , + , + + + ), + A3: ( + <> + + , + , + , + + + ), + B1: ( + <> + + , + , + , + + + ), + B2: ( + <> + + , + , + , + + + ), + B3: ( + <> + + , + , + , + + + ), + C1: ( + <> + + + + + + + ), + C2: ( + <> + + , + , + , + + + ), + C3: ( + <> + + , + , + , + + + ), + D1: ( + <> + + + + + + + ), + D2: ( + <> + + + + + + + ), + D3: ( + <> + + + + + + + ), + } + + return {contentsByCutoutLocation[cutoutLocation]} +} diff --git a/components/src/hardware-sim/BaseDeck/SlotBase.tsx b/components/src/hardware-sim/BaseDeck/SlotBase.tsx new file mode 100644 index 00000000000..5c8b7eb6100 --- /dev/null +++ b/components/src/hardware-sim/BaseDeck/SlotBase.tsx @@ -0,0 +1,5 @@ +import * as React from 'react' + +export function SlotBase(props: React.SVGProps): JSX.Element { + return +} diff --git a/components/src/hardware-sim/BaseDeck/SlotClip.tsx b/components/src/hardware-sim/BaseDeck/SlotClip.tsx new file mode 100644 index 00000000000..50a413c3f57 --- /dev/null +++ b/components/src/hardware-sim/BaseDeck/SlotClip.tsx @@ -0,0 +1,13 @@ +import * as React from 'react' + +export function SlotClip(props: React.SVGProps): JSX.Element { + return ( + + ) +} diff --git a/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx b/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx new file mode 100644 index 00000000000..2b3d8491da6 --- /dev/null +++ b/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx @@ -0,0 +1,112 @@ +import * as React from 'react' + +import { SlotBase } from './SlotBase' +import { SlotClip } from './SlotClip' + +import type { DeckDefinition, ModuleType } from '@opentrons/shared-data' + +export type StagingAreaLocation = 'A3' | 'B3' | 'C3' | 'D3' + +interface StagingAreaFixtureProps extends React.SVGProps { + cutoutLocation: StagingAreaLocation + deckDefinition: DeckDefinition + moduleType?: ModuleType + fixtureBaseColor?: React.SVGProps['fill'] + slotClipColor?: React.SVGProps['stroke'] + showExtensions?: boolean +} + +export function StagingAreaFixture( + props: StagingAreaFixtureProps +): JSX.Element | null { + const { + cutoutLocation, + deckDefinition, + fixtureBaseColor, + slotClipColor, + ...restProps + } = props + + // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key + const cutoutDef = deckDefinition?.locations.orderedSlots.find( + s => s.id === cutoutLocation + ) + if (cutoutDef == null) { + console.warn( + `cannot render StagingAreaFixture, no cutout named: ${cutoutDef} in deck def ${deckDefinition?.otId}` + ) + return null + } + + // TODO(bh, 2023-10-10): adjust base and clip d values if needed to fit v4 deck definition + const contentsByCutoutLocation: { + [cutoutLocation in StagingAreaLocation]: JSX.Element + } = { + A3: ( + <> + + , + , + , + + , + , + , + + + ), + B3: ( + <> + + , + , + , + + , + , + , + + + ), + C3: ( + <> + + , + , + , + + , + , + , + + + ), + D3: ( + <> + + + + + + , + , + , + + + ), + } + + return {contentsByCutoutLocation[cutoutLocation]} +} diff --git a/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx b/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx new file mode 100644 index 00000000000..1cb024d535b --- /dev/null +++ b/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx @@ -0,0 +1,58 @@ +import * as React from 'react' + +import { SlotBase } from './SlotBase' + +import type { DeckDefinition, ModuleType } from '@opentrons/shared-data' + +// waste chute only in cutout location D3 +export type WasteChuteLocation = 'D3' + +interface WasteChuteFixtureProps extends React.SVGProps { + cutoutLocation: WasteChuteLocation + deckDefinition: DeckDefinition + moduleType?: ModuleType + fixtureBaseColor?: React.SVGProps['fill'] + slotClipColor?: React.SVGProps['stroke'] + showExtensions?: boolean +} + +export function WasteChuteFixture( + props: WasteChuteFixtureProps +): JSX.Element | null { + const { + cutoutLocation, + deckDefinition, + fixtureBaseColor, + slotClipColor, + ...restProps + } = props + + if (cutoutLocation !== 'D3') { + console.warn( + `cannot render WasteChuteFixture in given cutout location ${cutoutLocation}` + ) + return null + } + + // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key + const cutoutDef = deckDefinition?.locations.orderedSlots.find( + s => s.id === cutoutLocation + ) + if (cutoutDef == null) { + console.warn( + `cannot render WasteChuteFixture, no cutout named: ${cutoutDef} in deck def ${deckDefinition?.otId}` + ) + return null + } + + // TODO(bh, 2023-10-10): adjust base and clip d values if needed to fit v4 deck definition + return ( + // TODO: render a "Waste chute" foreign object similar to FlexTrash + + + + ) +} diff --git a/components/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx b/components/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx new file mode 100644 index 00000000000..8de92d35299 --- /dev/null +++ b/components/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx @@ -0,0 +1,62 @@ +import * as React from 'react' + +import { SlotBase } from './SlotBase' +import { SlotClip } from './SlotClip' + +import type { DeckDefinition, ModuleType } from '@opentrons/shared-data' +import type { WasteChuteLocation } from './WasteChuteFixture' + +interface WasteChuteStagingAreaFixtureProps + extends React.SVGProps { + cutoutLocation: WasteChuteLocation + deckDefinition: DeckDefinition + moduleType?: ModuleType + fixtureBaseColor?: React.SVGProps['fill'] + slotClipColor?: React.SVGProps['stroke'] + showExtensions?: boolean +} + +export function WasteChuteStagingAreaFixture( + props: WasteChuteStagingAreaFixtureProps +): JSX.Element | null { + const { + cutoutLocation, + deckDefinition, + fixtureBaseColor, + slotClipColor, + ...restProps + } = props + + if (cutoutLocation !== 'D3') { + console.warn( + `cannot render WasteChuteStagingAreaFixture in given cutout location ${cutoutLocation}` + ) + return null + } + + // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key + const cutoutDef = deckDefinition?.locations.orderedSlots.find( + s => s.id === cutoutLocation + ) + if (cutoutDef == null) { + console.warn( + `cannot render WasteChuteStagingAreaFixture, no cutout named: ${cutoutDef} in deck def ${deckDefinition?.otId}` + ) + return null + } + + // TODO(bh, 2023-10-10): adjust base and clip d values if needed to fit v4 deck definition + return ( + // TODO: render a "Waste chute" foreign object similar to FlexTrash + + + , + , + , + + + ) +} diff --git a/components/src/hardware-sim/BaseDeck/__fixtures__/index.ts b/components/src/hardware-sim/BaseDeck/__fixtures__/index.ts new file mode 100644 index 00000000000..774d1be7352 --- /dev/null +++ b/components/src/hardware-sim/BaseDeck/__fixtures__/index.ts @@ -0,0 +1,137 @@ +import { v4 as uuidv4 } from 'uuid' + +import { + STAGING_AREA_LOAD_NAME, + STANDARD_SLOT_LOAD_NAME, + TRASH_BIN_LOAD_NAME, + WASTE_CHUTE_LOAD_NAME, +} from '@opentrons/shared-data' + +import type { DeckConfiguration } from '@opentrons/shared-data' + +export const STANDARD_SLOT_DECK_CONFIG_FIXTURE: DeckConfiguration = [ + { + fixtureLocation: 'A1', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'B1', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'C1', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'D1', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'A2', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'B2', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'C2', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'D2', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'A3', + loadName: TRASH_BIN_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'B3', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'C3', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'D3', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, +] + +// contains staging area and waste chute fixtures +export const EXTENDED_DECK_CONFIG_FIXTURE: DeckConfiguration = [ + { + fixtureLocation: 'A1', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'B1', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'C1', + loadName: TRASH_BIN_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'D1', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'A2', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'B2', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'C2', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'D2', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'A3', + loadName: STANDARD_SLOT_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'B3', + loadName: STAGING_AREA_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'C3', + loadName: STAGING_AREA_LOAD_NAME, + fixtureId: uuidv4(), + }, + { + fixtureLocation: 'D3', + loadName: WASTE_CHUTE_LOAD_NAME, + fixtureId: uuidv4(), + }, +] diff --git a/components/src/hardware-sim/BaseDeck/index.tsx b/components/src/hardware-sim/BaseDeck/index.tsx index bac8b365482..bd19459e9be 100644 --- a/components/src/hardware-sim/BaseDeck/index.tsx +++ b/components/src/hardware-sim/BaseDeck/index.tsx @@ -1,6 +1,5 @@ import * as React from 'react' import { - DeckSlot, RobotType, getDeckDefFromRobotType, ModuleModel, @@ -10,16 +9,33 @@ import { inferModuleOrientationFromXCoordinate, LabwareLocation, OT2_ROBOT_TYPE, + STAGING_AREA_LOAD_NAME, + STANDARD_SLOT_LOAD_NAME, + TRASH_BIN_LOAD_NAME, + WASTE_CHUTE_LOAD_NAME, } from '@opentrons/shared-data' import { RobotCoordinateSpace } from '../RobotCoordinateSpace' import { Module } from '../Module' import { LabwareRender } from '../Labware' import { FlexTrash } from '../Deck/FlexTrash' -import { DeckSlotLocation } from '../DeckSlotLocation' import { DeckFromData } from '../Deck/DeckFromData' import { SlotLabels } from '../Deck' import { COLORS } from '../../ui-style-constants' +import { + // EXTENDED_DECK_CONFIG_FIXTURE, + STANDARD_SLOT_DECK_CONFIG_FIXTURE, +} from './__fixtures__' +import { SingleSlotFixture } from './SingleSlotFixture' +import { StagingAreaFixture } from './StagingAreaFixture' +import { WasteChuteFixture } from './WasteChuteFixture' +// import { WasteChuteStagingAreaFixture } from './WasteChuteStagingAreaFixture' + +import type { DeckConfiguration } from '@opentrons/shared-data' +import type { TrashLocation } from '../Deck/FlexTrash' +import type { StagingAreaLocation } from './StagingAreaFixture' +import type { WasteChuteLocation } from './WasteChuteFixture' + interface BaseDeckProps { robotType: RobotType labwareLocations: Array<{ @@ -32,23 +48,39 @@ interface BaseDeckProps { nestedLabwareDef?: LabwareDefinition2 innerProps?: React.ComponentProps['innerProps'] }> + deckConfig?: DeckConfiguration lightFill?: string darkFill?: string - trashSlotName?: DeckSlot['id'] children?: React.ReactNode } export function BaseDeck(props: BaseDeckProps): JSX.Element { const { robotType, - trashSlotName, moduleLocations, labwareLocations, lightFill = COLORS.light1, darkFill = COLORS.darkGreyEnabled, + // TODO(bh, 2023-10-09): remove deck config fixture for Flex after migration to v4 + // deckConfig = EXTENDED_DECK_CONFIG_FIXTURE, + deckConfig = STANDARD_SLOT_DECK_CONFIG_FIXTURE, children, } = props const deckDef = getDeckDefFromRobotType(robotType) + + const singleSlotFixtures = deckConfig.filter( + fixture => fixture.loadName === STANDARD_SLOT_LOAD_NAME + ) + const stagingAreaFixtures = deckConfig.filter( + fixture => fixture.loadName === STAGING_AREA_LOAD_NAME + ) + const trashBinFixtures = deckConfig.filter( + fixture => fixture.loadName === TRASH_BIN_LOAD_NAME + ) + const wasteChuteFixtures = deckConfig.filter( + fixture => fixture.loadName === WASTE_CHUTE_LOAD_NAME + ) + return ( ) : ( - deckDef.locations.orderedSlots.map(slotDef => ( - <> - + {singleSlotFixtures.map(fixture => ( + + ))} + {stagingAreaFixtures.map(fixture => ( + - {slotDef.id === trashSlotName ? ( + ))} + {trashBinFixtures.map(fixture => ( + <> + - ) : null} - - )) + + ))} + {wasteChuteFixtures.map(fixture => ( + + ))} + )} {moduleLocations.map( ({ moduleModel, moduleLocation, nestedLabwareDef, innerProps }) => { diff --git a/components/src/hardware-sim/Deck/FlexTrash.tsx b/components/src/hardware-sim/Deck/FlexTrash.tsx index 87f99b328d3..f1d07a48738 100644 --- a/components/src/hardware-sim/Deck/FlexTrash.tsx +++ b/components/src/hardware-sim/Deck/FlexTrash.tsx @@ -1,9 +1,9 @@ import * as React from 'react' import { Icon } from '../../icons' -import { Flex } from '../../primitives' +import { Flex, Text } from '../../primitives' import { ALIGN_CENTER, JUSTIFY_CENTER } from '../../styles' -import { BORDERS } from '../../ui-style-constants' +import { BORDERS, TYPOGRAPHY } from '../../ui-style-constants' import { RobotCoordsForeignObject } from './RobotCoordsForeignObject' import { getDeckDefFromRobotType } from '@opentrons/shared-data' @@ -11,8 +11,8 @@ import trashDef from '@opentrons/shared-data/labware/definitions/2/opentrons_1_t import type { RobotType } from '@opentrons/shared-data' -// only allow edge slots (columns 1 and 3) -export type TrashSlotName = +// only allow edge cutout locations (columns 1 and 3) +export type TrashLocation = | 'A1' | 'B1' | 'C1' @@ -26,7 +26,7 @@ interface FlexTrashProps { robotType: RobotType trashIconColor: string backgroundColor: string - trashSlotName?: TrashSlotName + trashLocation?: TrashLocation } /** @@ -37,18 +37,19 @@ export const FlexTrash = ({ robotType, trashIconColor, backgroundColor, - // default Flex trash slot position A3 - trashSlotName = 'A3', + trashLocation, }: FlexTrashProps): JSX.Element | null => { // be sure we don't try to render for an OT-2 if (robotType !== 'OT-3 Standard') return null const deckDef = getDeckDefFromRobotType(robotType) + // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key const trashSlot = deckDef.locations.orderedSlots.find( - slot => slot.id === trashSlotName + slot => slot.id === trashLocation ) // retrieve slot x,y positions and dimensions from deck definition for the given trash slot + // TODO(bh, 2023-10-09): refactor position, offsets, and rotation after v4 migration const [x = 0, y = 0] = trashSlot?.position ?? [] const { xDimension: slotXDimension = 0, yDimension: slotYDimension = 0 } = trashSlot?.boundingBox ?? {} @@ -59,10 +60,10 @@ export const FlexTrash = ({ // rotate trash 180 degrees in column 1 const rotateDegrees = - trashSlotName === 'A1' || - trashSlotName === 'B1' || - trashSlotName === 'C1' || - trashSlotName === 'D1' + trashLocation === 'A1' || + trashLocation === 'B1' || + trashLocation === 'C1' || + trashLocation === 'D1' ? '180' : '0' @@ -87,6 +88,17 @@ export const FlexTrash = ({ justifyContent={JUSTIFY_CENTER} width="100%" > + {rotateDegrees === '180' ? ( + + Trash + + ) : null} + {rotateDegrees === '0' ? ( + + Trash + + ) : null} diff --git a/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx b/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx index 38adc9e0904..55656526e1b 100644 --- a/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx +++ b/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx @@ -23,7 +23,7 @@ import type { DeckDefinition, } from '@opentrons/shared-data' import type { StyleProps } from '../../primitives' -import type { TrashSlotName } from './FlexTrash' +import type { TrashLocation } from './FlexTrash' const getModulePosition = ( orderedSlots: DeckSlot[], @@ -126,7 +126,7 @@ interface MoveLabwareOnDeckProps extends StyleProps { loadedLabware: LoadedLabware[] backgroundItems?: React.ReactNode deckFill?: string - trashSlotName?: TrashSlotName + trashLocation?: TrashLocation } export function MoveLabwareOnDeck( props: MoveLabwareOnDeckProps @@ -140,7 +140,7 @@ export function MoveLabwareOnDeck( loadedModules, backgroundItems = null, deckFill = '#e6e6e6', - trashSlotName, + trashLocation, ...styleProps } = props const deckDef = React.useMemo(() => getDeckDefFromRobotType(robotType), [ @@ -209,7 +209,7 @@ export function MoveLabwareOnDeck( def={deckDef} deckFill={deckFill} layerBlocklist={[]} - trashSlotName={trashSlotName} + trashLocation={trashLocation} /> )} {backgroundItems} diff --git a/components/src/hardware-sim/Deck/RobotWorkSpace.tsx b/components/src/hardware-sim/Deck/RobotWorkSpace.tsx index 360e1ba8c9a..5f36dababc5 100644 --- a/components/src/hardware-sim/Deck/RobotWorkSpace.tsx +++ b/components/src/hardware-sim/Deck/RobotWorkSpace.tsx @@ -3,7 +3,7 @@ import { StyleProps, Svg } from '../../primitives' import { StyledDeck } from './StyledDeck' import type { DeckDefinition, DeckSlot } from '@opentrons/shared-data' -import type { TrashSlotName } from './FlexTrash' +import type { TrashLocation } from './FlexTrash' export interface RobotWorkSpaceRenderProps { deckSlotsById: { [slotId: string]: DeckSlot } @@ -19,7 +19,8 @@ export interface RobotWorkSpaceProps extends StyleProps { children?: (props: RobotWorkSpaceRenderProps) => React.ReactNode deckFill?: string deckLayerBlocklist?: string[] - trashSlotName?: TrashSlotName + // TODO(bh, 2023-10-09): remove + trashSlotName?: TrashLocation trashColor?: string id?: string } @@ -84,7 +85,7 @@ export function RobotWorkSpace(props: RobotWorkSpaceProps): JSX.Element | null { deckFill={deckFill} def={deckDef} layerBlocklist={deckLayerBlocklist} - trashSlotName={trashSlotName} + trashLocation={trashSlotName} trashColor={trashColor} /> )} diff --git a/components/src/hardware-sim/Deck/StyledDeck.tsx b/components/src/hardware-sim/Deck/StyledDeck.tsx index 205b0c702ff..55e1cbfc3c9 100644 --- a/components/src/hardware-sim/Deck/StyledDeck.tsx +++ b/components/src/hardware-sim/Deck/StyledDeck.tsx @@ -5,12 +5,12 @@ import { DeckFromData } from './DeckFromData' import { FlexTrash } from './FlexTrash' import type { DeckFromDataProps } from './DeckFromData' -import type { TrashSlotName } from './FlexTrash' +import type { TrashLocation } from './FlexTrash' interface StyledDeckProps { deckFill: string trashColor?: string - trashSlotName?: TrashSlotName + trashLocation?: TrashLocation } // apply fill to .SLOT_BASE class from ot3_standard deck definition @@ -25,7 +25,7 @@ export function StyledDeck( ): JSX.Element { const { deckFill, - trashSlotName, + trashLocation, trashColor = '#757070', ...deckFromDataProps } = props @@ -33,7 +33,7 @@ export function StyledDeck( const robotType = deckFromDataProps.def.robot.model ?? 'OT-2 Standard' const trashSlotClipId = - trashSlotName != null ? `SLOT_CLIPS_${trashSlotName}` : null + trashLocation != null ? `SLOT_CLIPS_${trashLocation}` : null const trashLayerBlocklist = trashSlotClipId != null @@ -46,12 +46,12 @@ export function StyledDeck( {...deckFromDataProps} layerBlocklist={trashLayerBlocklist} /> - {trashSlotName != null ? ( + {trashLocation != null ? ( ) : null} diff --git a/components/src/hardware-sim/DeckConfigurator/EmptyFixture.tsx b/components/src/hardware-sim/DeckConfigurator/EmptyFixture.tsx index 47302323ce2..b57975a8e3a 100644 --- a/components/src/hardware-sim/DeckConfigurator/EmptyFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/EmptyFixture.tsx @@ -11,6 +11,8 @@ import { ALIGN_CENTER, DISPLAY_FLEX, JUSTIFY_CENTER } from '../../styles' import { BORDERS, COLORS } from '../../ui-style-constants' import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' +import type { Cutout } from '@opentrons/shared-data' + // TODO: replace stubs with JSON definitions when available const standardSlotDef = { schemaVersion: 1, @@ -30,8 +32,8 @@ const standardSlotDef = { } interface EmptyFixtureProps { - fixtureLocation: string - handleClickAdd: (fixtureLocation: string) => void + fixtureLocation: Cutout + handleClickAdd: (fixtureLocation: Cutout) => void } export function EmptyFixture(props: EmptyFixtureProps): JSX.Element { diff --git a/components/src/hardware-sim/DeckConfigurator/StagingAreaFixture.tsx b/components/src/hardware-sim/DeckConfigurator/StagingAreaFixture.tsx index b89a5189c79..3dc02b8e4ce 100644 --- a/components/src/hardware-sim/DeckConfigurator/StagingAreaFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/StagingAreaFixture.tsx @@ -11,6 +11,8 @@ import { ALIGN_CENTER, DISPLAY_FLEX, JUSTIFY_CENTER } from '../../styles' import { BORDERS, COLORS, SPACING, TYPOGRAPHY } from '../../ui-style-constants' import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' +import type { Cutout } from '@opentrons/shared-data' + // TODO: replace stubs with JSON definitions when available const stagingAreaDef = { schemaVersion: 1, @@ -30,8 +32,8 @@ const stagingAreaDef = { } interface StagingAreaFixtureProps { - fixtureLocation: string - handleClickRemove?: (fixtureLocation: string) => void + fixtureLocation: Cutout + handleClickRemove?: (fixtureLocation: Cutout) => void } export function StagingAreaFixture( diff --git a/components/src/hardware-sim/DeckConfigurator/TrashBinFixture.tsx b/components/src/hardware-sim/DeckConfigurator/TrashBinFixture.tsx index 8d2da3178f8..df4f37c7db2 100644 --- a/components/src/hardware-sim/DeckConfigurator/TrashBinFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/TrashBinFixture.tsx @@ -11,13 +11,15 @@ import { ALIGN_CENTER, DISPLAY_FLEX, JUSTIFY_CENTER } from '../../styles' import { BORDERS, COLORS, SPACING, TYPOGRAPHY } from '../../ui-style-constants' import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' +import type { Cutout } from '@opentrons/shared-data' + // TODO: replace stubs with JSON definitions when available const trashBinDef = { schemaVersion: 1, version: 1, namespace: 'opentrons', metadata: { - displayName: 'Trash', + displayName: 'Trash bin', }, parameters: { loadName: 'trash_bin', @@ -30,8 +32,8 @@ const trashBinDef = { } interface TrashBinFixtureProps { - fixtureLocation: string - handleClickRemove?: (fixtureLocation: string) => void + fixtureLocation: Cutout + handleClickRemove?: (fixtureLocation: Cutout) => void } export function TrashBinFixture(props: TrashBinFixtureProps): JSX.Element { diff --git a/components/src/hardware-sim/DeckConfigurator/WasteChuteFixture.tsx b/components/src/hardware-sim/DeckConfigurator/WasteChuteFixture.tsx index 0c547cbbfa1..b46fab2335f 100644 --- a/components/src/hardware-sim/DeckConfigurator/WasteChuteFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/WasteChuteFixture.tsx @@ -11,6 +11,8 @@ import { ALIGN_CENTER, DISPLAY_FLEX, JUSTIFY_CENTER } from '../../styles' import { BORDERS, COLORS, SPACING, TYPOGRAPHY } from '../../ui-style-constants' import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' +import type { Cutout } from '@opentrons/shared-data' + // TODO: replace stubs with JSON definitions when available const wasteChuteDef = { schemaVersion: 1, @@ -30,8 +32,8 @@ const wasteChuteDef = { } interface WasteChuteFixtureProps { - fixtureLocation: string - handleClickRemove?: (fixtureLocation: string) => void + fixtureLocation: Cutout + handleClickRemove?: (fixtureLocation: Cutout) => void } export function WasteChuteFixture(props: WasteChuteFixtureProps): JSX.Element { diff --git a/components/src/hardware-sim/DeckConfigurator/index.tsx b/components/src/hardware-sim/DeckConfigurator/index.tsx index 5e82f946424..048c9d25346 100644 --- a/components/src/hardware-sim/DeckConfigurator/index.tsx +++ b/components/src/hardware-sim/DeckConfigurator/index.tsx @@ -18,12 +18,12 @@ import { StagingAreaFixture } from './StagingAreaFixture' import { TrashBinFixture } from './TrashBinFixture' import { WasteChuteFixture } from './WasteChuteFixture' -import type { DeckConfiguration } from '@opentrons/shared-data' +import type { Cutout, DeckConfiguration } from '@opentrons/shared-data' interface DeckConfiguratorProps { deckConfig: DeckConfiguration - handleClickAdd: (fixtureLocation: string) => void - handleClickRemove: (fixtureLocation: string) => void + handleClickAdd: (fixtureLocation: Cutout) => void + handleClickRemove: (fixtureLocation: Cutout) => void lightFill?: string darkFill?: string children?: React.ReactNode diff --git a/protocol-designer/src/components/DeckSetup/index.tsx b/protocol-designer/src/components/DeckSetup/index.tsx index e989314ee18..04c4c5bdf1f 100644 --- a/protocol-designer/src/components/DeckSetup/index.tsx +++ b/protocol-designer/src/components/DeckSetup/index.tsx @@ -12,7 +12,7 @@ import { RobotWorkSpaceRenderProps, Module, COLORS, - TrashSlotName, + TrashLocation, } from '@opentrons/components' import { MODULES_WITH_COLLISION_ISSUES, @@ -565,7 +565,7 @@ export const DeckSetup = (): JSX.Element => { width="100%" height="100%" trashSlotName={ - trashSlot != null ? (trashSlot as TrashSlotName) : undefined + trashSlot != null ? (trashSlot as TrashLocation) : undefined } trashColor={COLORS.darkGreyEnabled} > diff --git a/protocol-designer/src/file-data/selectors/fileCreator.ts b/protocol-designer/src/file-data/selectors/fileCreator.ts index b7761db26a5..430aa9ac5b7 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.ts +++ b/protocol-designer/src/file-data/selectors/fileCreator.ts @@ -304,7 +304,9 @@ export const createFile: Selector = createSelector( commandType: 'loadFixture' as const, params: { fixtureId: additionalEquipment.id, - location: { cutout: additionalEquipment.location as Cutout }, + location: { + cutout: additionalEquipment.location as Cutout, + }, loadName: additionalEquipment.name, }, } diff --git a/shared-data/js/types.ts b/shared-data/js/types.ts index aaff84e60ac..911fd33244e 100644 --- a/shared-data/js/types.ts +++ b/shared-data/js/types.ts @@ -532,9 +532,23 @@ export type StatusBarAnimation = export type StatusBarAnimations = StatusBarAnimation[] // TODO(bh, 2023-09-28): refine types when settled +export type Cutout = + | 'A1' + | 'B1' + | 'C1' + | 'D1' + | 'A2' + | 'B2' + | 'C2' + | 'D2' + | 'A3' + | 'B3' + | 'C3' + | 'D3' + export interface Fixture { fixtureId: string - fixtureLocation: string + fixtureLocation: Cutout loadName: FixtureLoadName } diff --git a/shared-data/protocol/types/schemaV7/command/setup.ts b/shared-data/protocol/types/schemaV7/command/setup.ts index 920a8d3c1be..f0d3ff0b0da 100644 --- a/shared-data/protocol/types/schemaV7/command/setup.ts +++ b/shared-data/protocol/types/schemaV7/command/setup.ts @@ -6,6 +6,7 @@ import type { PipetteName, ModuleModel, FixtureLoadName, + Cutout, } from '../../../../js' export interface LoadPipetteCreateCommand extends CommonCommandCreateInfo { @@ -150,7 +151,7 @@ interface LoadLiquidParams { interface LoadLiquidResult { liquidId: string } -export type Cutout = 'B3' | 'C3' | 'D3' + interface LoadFixtureParams { location: { cutout: Cutout } loadName: FixtureLoadName From b6e36be7ba6135b0b693188cd54fcd895d99412b Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Tue, 10 Oct 2023 17:46:29 -0400 Subject: [PATCH 02/10] rename configurator components e.g. StagingAreaConfigFixture --- .../{EmptyFixture.tsx => EmptyConfigFixture.tsx} | 6 ++++-- ...aFixture.tsx => StagingAreaConfigFixture.tsx} | 6 +++--- ...hBinFixture.tsx => TrashBinConfigFixture.tsx} | 6 ++++-- ...teFixture.tsx => WasteChuteConfigFixture.tsx} | 6 ++++-- .../src/hardware-sim/DeckConfigurator/index.tsx | 16 ++++++++-------- 5 files changed, 23 insertions(+), 17 deletions(-) rename components/src/hardware-sim/DeckConfigurator/{EmptyFixture.tsx => EmptyConfigFixture.tsx} (95%) rename components/src/hardware-sim/DeckConfigurator/{StagingAreaFixture.tsx => StagingAreaConfigFixture.tsx} (95%) rename components/src/hardware-sim/DeckConfigurator/{TrashBinFixture.tsx => TrashBinConfigFixture.tsx} (95%) rename components/src/hardware-sim/DeckConfigurator/{WasteChuteFixture.tsx => WasteChuteConfigFixture.tsx} (94%) diff --git a/components/src/hardware-sim/DeckConfigurator/EmptyFixture.tsx b/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx similarity index 95% rename from components/src/hardware-sim/DeckConfigurator/EmptyFixture.tsx rename to components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx index b57975a8e3a..ef579ea5bda 100644 --- a/components/src/hardware-sim/DeckConfigurator/EmptyFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx @@ -31,12 +31,14 @@ const standardSlotDef = { }, } -interface EmptyFixtureProps { +interface EmptyConfigFixtureProps { fixtureLocation: Cutout handleClickAdd: (fixtureLocation: Cutout) => void } -export function EmptyFixture(props: EmptyFixtureProps): JSX.Element { +export function EmptyConfigFixture( + props: EmptyConfigFixtureProps +): JSX.Element { const { handleClickAdd, fixtureLocation } = props const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) diff --git a/components/src/hardware-sim/DeckConfigurator/StagingAreaFixture.tsx b/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx similarity index 95% rename from components/src/hardware-sim/DeckConfigurator/StagingAreaFixture.tsx rename to components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx index 3dc02b8e4ce..7832160d0ad 100644 --- a/components/src/hardware-sim/DeckConfigurator/StagingAreaFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx @@ -31,13 +31,13 @@ const stagingAreaDef = { }, } -interface StagingAreaFixtureProps { +interface StagingAreaConfigFixtureProps { fixtureLocation: Cutout handleClickRemove?: (fixtureLocation: Cutout) => void } -export function StagingAreaFixture( - props: StagingAreaFixtureProps +export function StagingAreaConfigFixture( + props: StagingAreaConfigFixtureProps ): JSX.Element { const { handleClickRemove, fixtureLocation } = props const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) diff --git a/components/src/hardware-sim/DeckConfigurator/TrashBinFixture.tsx b/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx similarity index 95% rename from components/src/hardware-sim/DeckConfigurator/TrashBinFixture.tsx rename to components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx index df4f37c7db2..bb5a14bccad 100644 --- a/components/src/hardware-sim/DeckConfigurator/TrashBinFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx @@ -31,12 +31,14 @@ const trashBinDef = { }, } -interface TrashBinFixtureProps { +interface TrashBinConfigFixtureProps { fixtureLocation: Cutout handleClickRemove?: (fixtureLocation: Cutout) => void } -export function TrashBinFixture(props: TrashBinFixtureProps): JSX.Element { +export function TrashBinConfigFixture( + props: TrashBinConfigFixtureProps +): JSX.Element { const { handleClickRemove, fixtureLocation } = props const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) diff --git a/components/src/hardware-sim/DeckConfigurator/WasteChuteFixture.tsx b/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx similarity index 94% rename from components/src/hardware-sim/DeckConfigurator/WasteChuteFixture.tsx rename to components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx index b46fab2335f..8f079145665 100644 --- a/components/src/hardware-sim/DeckConfigurator/WasteChuteFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx @@ -31,12 +31,14 @@ const wasteChuteDef = { }, } -interface WasteChuteFixtureProps { +interface WasteChuteConfigFixtureProps { fixtureLocation: Cutout handleClickRemove?: (fixtureLocation: Cutout) => void } -export function WasteChuteFixture(props: WasteChuteFixtureProps): JSX.Element { +export function WasteChuteConfigFixture( + props: WasteChuteConfigFixtureProps +): JSX.Element { const { handleClickRemove, fixtureLocation } = props const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) diff --git a/components/src/hardware-sim/DeckConfigurator/index.tsx b/components/src/hardware-sim/DeckConfigurator/index.tsx index 048c9d25346..296ea7388b9 100644 --- a/components/src/hardware-sim/DeckConfigurator/index.tsx +++ b/components/src/hardware-sim/DeckConfigurator/index.tsx @@ -13,10 +13,10 @@ import { COLORS } from '../../ui-style-constants' import { DeckSlotLocation } from '../DeckSlotLocation' import { SlotLabels } from '../Deck' import { RobotCoordinateSpace } from '../RobotCoordinateSpace' -import { EmptyFixture } from './EmptyFixture' -import { StagingAreaFixture } from './StagingAreaFixture' -import { TrashBinFixture } from './TrashBinFixture' -import { WasteChuteFixture } from './WasteChuteFixture' +import { EmptyConfigFixture } from './EmptyConfigFixture' +import { StagingAreaConfigFixture } from './StagingAreaConfigFixture' +import { TrashBinConfigFixture } from './TrashBinConfigFixture' +import { WasteChuteConfigFixture } from './WasteChuteConfigFixture' import type { Cutout, DeckConfiguration } from '@opentrons/shared-data' @@ -85,28 +85,28 @@ export function DeckConfigurator(props: DeckConfiguratorProps): JSX.Element { ))} {stagingAreaFixtures.map(fixture => ( - ))} {emptyFixtures.map(fixture => ( - ))} {wasteChuteFixtures.map(fixture => ( - ))} {trashBinFixtures.map(fixture => ( - Date: Wed, 11 Oct 2023 14:44:28 -0400 Subject: [PATCH 03/10] add waste chute foreign object --- .../BaseDeck/BaseDeck.stories.tsx | 4 -- .../BaseDeck/WasteChuteFixture.tsx | 52 +++++++++++++++++-- .../BaseDeck/WasteChuteStagingAreaFixture.tsx | 10 +++- .../src/hardware-sim/BaseDeck/index.tsx | 7 +-- .../StagingAreaConfigFixture.tsx | 1 - .../TrashBinConfigFixture.tsx | 1 - .../WasteChuteConfigFixture.tsx | 1 - 7 files changed, 61 insertions(+), 15 deletions(-) diff --git a/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx b/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx index a5de0777a58..9b6805b5aba 100644 --- a/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx +++ b/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx @@ -25,10 +25,6 @@ const meta: Meta> = { title: 'Library/Molecules/Simulation/BaseDeck', argTypes: { deckConfig: { - // options: [ - // EXTENDED_DECK_CONFIG_FIXTURE, - // STANDARD_SLOT_DECK_CONFIG_FIXTURE, - // ], options: ['single slot deck', 'staging area deck'], control: { type: 'radio' }, }, diff --git a/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx b/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx index 1cb024d535b..a4ac6673bf5 100644 --- a/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx +++ b/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx @@ -1,5 +1,10 @@ import * as React from 'react' +import { Icon } from '../../icons' +import { Flex, Text } from '../../primitives' +import { ALIGN_CENTER, DIRECTION_COLUMN, JUSTIFY_CENTER } from '../../styles' +import { BORDERS, COLORS, TYPOGRAPHY } from '../../ui-style-constants' +import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' import { SlotBase } from './SlotBase' import type { DeckDefinition, ModuleType } from '@opentrons/shared-data' @@ -22,8 +27,8 @@ export function WasteChuteFixture( const { cutoutLocation, deckDefinition, - fixtureBaseColor, - slotClipColor, + fixtureBaseColor = COLORS.light1, + slotClipColor = COLORS.darkGreyEnabled, ...restProps } = props @@ -47,12 +52,53 @@ export function WasteChuteFixture( // TODO(bh, 2023-10-10): adjust base and clip d values if needed to fit v4 deck definition return ( - // TODO: render a "Waste chute" foreign object similar to FlexTrash + ) } + +interface WasteChuteProps { + wasteIconColor: string + backgroundColor: string +} + +/** + * a deck map foreign object representing the physical location of the waste chute connected to the deck + * based on preliminary designs + * TODO(bh, 2023-10-11): when designs and definitions settled, resolve position details etc + */ +export function WasteChute(props: WasteChuteProps): JSX.Element { + const { wasteIconColor, backgroundColor } = props + + return ( + + + + Waste chute + + + ) +} diff --git a/components/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx b/components/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx index 8de92d35299..b2cdbad8e2d 100644 --- a/components/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx +++ b/components/src/hardware-sim/BaseDeck/WasteChuteStagingAreaFixture.tsx @@ -1,7 +1,9 @@ import * as React from 'react' +import { COLORS } from '../../ui-style-constants' import { SlotBase } from './SlotBase' import { SlotClip } from './SlotClip' +import { WasteChute } from './WasteChuteFixture' import type { DeckDefinition, ModuleType } from '@opentrons/shared-data' import type { WasteChuteLocation } from './WasteChuteFixture' @@ -22,8 +24,8 @@ export function WasteChuteStagingAreaFixture( const { cutoutLocation, deckDefinition, - fixtureBaseColor, - slotClipColor, + fixtureBaseColor = COLORS.light1, + slotClipColor = COLORS.darkGreyEnabled, ...restProps } = props @@ -57,6 +59,10 @@ export function WasteChuteStagingAreaFixture( , , + ) } diff --git a/components/src/hardware-sim/BaseDeck/index.tsx b/components/src/hardware-sim/BaseDeck/index.tsx index bd19459e9be..6232429f14b 100644 --- a/components/src/hardware-sim/BaseDeck/index.tsx +++ b/components/src/hardware-sim/BaseDeck/index.tsx @@ -110,9 +110,8 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element { /> ))} {trashBinFixtures.map(fixture => ( - <> + - + ))} {wasteChuteFixtures.map(fixture => ( diff --git a/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx index 7832160d0ad..f8ba5b44e35 100644 --- a/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx @@ -73,7 +73,6 @@ export function StagingAreaConfigFixture( justifyContent={JUSTIFY_CENTER} width="100%" > - {} {stagingAreaDef.metadata.displayName} diff --git a/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx index bb5a14bccad..0d78b538fb7 100644 --- a/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx @@ -79,7 +79,6 @@ export function TrashBinConfigFixture( justifyContent={JUSTIFY_CENTER} width="100%" > - {} {trashBinDef.metadata.displayName} diff --git a/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx index 8f079145665..da0b9241df7 100644 --- a/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx @@ -73,7 +73,6 @@ export function WasteChuteConfigFixture( justifyContent={JUSTIFY_CENTER} width="100%" > - {} {wasteChuteDef.metadata.displayName} From 50a45de006ba2698cf58682cb44661849e19acda Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Wed, 11 Oct 2023 14:51:32 -0400 Subject: [PATCH 04/10] add some Cutout typing --- .../ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx | 6 ++++-- app/src/resources/deck_configuration/hooks.ts | 6 +----- .../components/modals/CreateFileWizard/StagingAreaTile.tsx | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx index be95deb66ee..c568ef1fe95 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/NotConfiguredModal.tsx @@ -11,16 +11,18 @@ import { BORDERS, ALIGN_CENTER, } from '@opentrons/components' -import { FixtureLoadName, getFixtureDisplayName } from '@opentrons/shared-data' +import { getFixtureDisplayName } from '@opentrons/shared-data' import { TertiaryButton } from '../../../../atoms/buttons/TertiaryButton' import { Portal } from '../../../../App/portal' import { LegacyModal } from '../../../../molecules/LegacyModal' import { StyledText } from '../../../../atoms/text' +import type { Cutout, FixtureLoadName } from '@opentrons/shared-data' + interface NotConfiguredModalProps { onCloseClick: () => void requiredFixture: FixtureLoadName - cutout: string + cutout: Cutout } export const NotConfiguredModal = ( diff --git a/app/src/resources/deck_configuration/hooks.ts b/app/src/resources/deck_configuration/hooks.ts index c9a3e12c975..967d46b5119 100644 --- a/app/src/resources/deck_configuration/hooks.ts +++ b/app/src/resources/deck_configuration/hooks.ts @@ -1,11 +1,7 @@ import { useDeckConfigurationQuery } from '@opentrons/react-api-client' import { STANDARD_SLOT_LOAD_NAME } from '@opentrons/shared-data' -import { - Fixture, - LoadFixtureRunTimeCommand, - STANDARD_SLOT_LOAD_NAME, -} from '@opentrons/shared-data' +import type { Fixture, LoadFixtureRunTimeCommand } from '@opentrons/shared-data' export const CONFIGURED = 'configured' export const CONFLICTING = 'conflicting' diff --git a/protocol-designer/src/components/modals/CreateFileWizard/StagingAreaTile.tsx b/protocol-designer/src/components/modals/CreateFileWizard/StagingAreaTile.tsx index 5c54fc2095f..24f11c7b5c7 100644 --- a/protocol-designer/src/components/modals/CreateFileWizard/StagingAreaTile.tsx +++ b/protocol-designer/src/components/modals/CreateFileWizard/StagingAreaTile.tsx @@ -21,10 +21,10 @@ import { getEnableDeckModification } from '../../../feature-flags/selectors' import { GoBack } from './GoBack' import { HandleEnter } from './HandleEnter' -import type { DeckConfiguration } from '@opentrons/shared-data' +import type { Cutout, DeckConfiguration } from '@opentrons/shared-data' import type { WizardTileProps } from './types' -const STAGING_AREA_SLOTS = ['A3', 'B3', 'C3', 'D3'] +const STAGING_AREA_SLOTS: Cutout[] = ['A3', 'B3', 'C3', 'D3'] export function StagingAreaTile(props: WizardTileProps): JSX.Element | null { const { values, goBack, proceed, setFieldValue } = props From 4dca870d6e2e88d2601bdc8d44754007f66f16f9 Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Wed, 11 Oct 2023 15:05:10 -0400 Subject: [PATCH 05/10] remove a console.log --- .../Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx index 7b177002673..4817fc8ca09 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/SetupFixtureList.tsx @@ -83,7 +83,6 @@ export const SetupFixtureList = (props: SetupFixtureListProps): JSX.Element => { > {map(loadedFixturesBySlot, ({ params, id }) => { const { loadName, location } = params - console.log(id) return ( Date: Wed, 11 Oct 2023 15:05:41 -0400 Subject: [PATCH 06/10] update a stubbed fixture id --- app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx b/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx index fb8ca40118e..c5680e8817e 100644 --- a/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx +++ b/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx @@ -109,10 +109,10 @@ export function ProtocolRunSetup({ status: 'succeeded', }, C3: { - id: 'stubbed_load_fixture_2', + id: 'stubbed_load_fixture_3', commandType: 'loadFixture', params: { - fixtureId: 'stubbedFixtureId_2', + fixtureId: 'stubbedFixtureId_3', loadName: TRASH_BIN_LOAD_NAME, location: { cutout: 'C3' }, }, From 3efcfe2680fccba013cf5fc38fe7b555e6060ebb Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Wed, 11 Oct 2023 15:09:09 -0400 Subject: [PATCH 07/10] remove stray format --- protocol-designer/src/file-data/selectors/fileCreator.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/protocol-designer/src/file-data/selectors/fileCreator.ts b/protocol-designer/src/file-data/selectors/fileCreator.ts index 430aa9ac5b7..b7761db26a5 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.ts +++ b/protocol-designer/src/file-data/selectors/fileCreator.ts @@ -304,9 +304,7 @@ export const createFile: Selector = createSelector( commandType: 'loadFixture' as const, params: { fixtureId: additionalEquipment.id, - location: { - cutout: additionalEquipment.location as Cutout, - }, + location: { cutout: additionalEquipment.location as Cutout }, loadName: additionalEquipment.name, }, } From 60627d4c05ad95b61c492d037db96a0889816876 Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Wed, 11 Oct 2023 16:54:42 -0400 Subject: [PATCH 08/10] sort base deck story imports --- .../BaseDeck/BaseDeck.stories.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx b/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx index 9b6805b5aba..145707f77f5 100644 --- a/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx +++ b/components/src/hardware-sim/BaseDeck/BaseDeck.stories.tsx @@ -2,23 +2,24 @@ import * as React from 'react' import fixture_96_plate from '@opentrons/shared-data/labware/fixtures/2/fixture_96_plate.json' import fixture_tiprack_1000_ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_1000_ul.json' import { - DeckConfiguration, FLEX_ROBOT_TYPE, - LabwareDefinition2, + HEATERSHAKER_MODULE_V1, + MAGNETIC_BLOCK_V1, + TEMPERATURE_MODULE_V2, + THERMOCYCLER_MODULE_V2, } from '@opentrons/shared-data' -import type { Meta, StoryObj } from '@storybook/react' import { EXTENDED_DECK_CONFIG_FIXTURE, STANDARD_SLOT_DECK_CONFIG_FIXTURE, } from './__fixtures__' import { BaseDeck as BaseDeckComponent } from './' -import { - HEATERSHAKER_MODULE_V1, - MAGNETIC_BLOCK_V1, - TEMPERATURE_MODULE_V2, - THERMOCYCLER_MODULE_V2, -} from '@opentrons/shared-data/js' + +import type { Meta, StoryObj } from '@storybook/react' +import type { + DeckConfiguration, + LabwareDefinition2, +} from '@opentrons/shared-data' const meta: Meta> = { component: BaseDeckComponent, From aca2cc8e95ca934b87aedb50de760f7da311be17 Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Wed, 11 Oct 2023 17:11:22 -0400 Subject: [PATCH 09/10] update SlotClip stroke default constant --- components/src/hardware-sim/BaseDeck/SlotClip.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/src/hardware-sim/BaseDeck/SlotClip.tsx b/components/src/hardware-sim/BaseDeck/SlotClip.tsx index 50a413c3f57..2a500641113 100644 --- a/components/src/hardware-sim/BaseDeck/SlotClip.tsx +++ b/components/src/hardware-sim/BaseDeck/SlotClip.tsx @@ -1,10 +1,12 @@ import * as React from 'react' +import { COLORS } from '../../ui-style-constants' + export function SlotClip(props: React.SVGProps): JSX.Element { return ( Date: Wed, 11 Oct 2023 17:12:20 -0400 Subject: [PATCH 10/10] leave replace DeckSlotLocation TODO --- components/src/hardware-sim/DeckSlotLocation/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/components/src/hardware-sim/DeckSlotLocation/index.tsx b/components/src/hardware-sim/DeckSlotLocation/index.tsx index c098128210d..162a92df3e0 100644 --- a/components/src/hardware-sim/DeckSlotLocation/index.tsx +++ b/components/src/hardware-sim/DeckSlotLocation/index.tsx @@ -12,6 +12,7 @@ interface DeckSlotLocationProps extends React.SVGProps { showExtensions?: boolean } +// TODO(bh, 2023-10-11): replace usage of this component with base deck fixtures export function DeckSlotLocation( props: DeckSlotLocationProps ): JSX.Element | null {