2
0
Files
bot/apps/builder/contexts/GraphContext.tsx

166 lines
4.1 KiB
TypeScript
Raw Normal View History

import { Block, Edge, IdMap, Source, Step, Target } from 'models'
2021-12-16 10:43:49 +01:00
import {
createContext,
Dispatch,
2022-01-15 17:30:20 +01:00
MutableRefObject,
2021-12-16 10:43:49 +01:00
ReactNode,
SetStateAction,
useContext,
useEffect,
2021-12-16 10:43:49 +01:00
useState,
} from 'react'
export const stubLength = 20
export const blockWidth = 300
export const blockAnchorsOffset = {
left: {
x: 0,
y: 20,
},
top: {
x: blockWidth / 2,
y: 0,
},
right: {
x: blockWidth,
y: 20,
},
}
2022-01-12 09:10:59 +01:00
2021-12-16 10:43:49 +01:00
export type Coordinates = { x: number; y: number }
type Position = Coordinates & { scale: number }
export type Anchor = {
coordinates: Coordinates
}
export type Node = Omit<Block, 'steps'> & {
steps: (Step & {
sourceAnchorsPosition: { left: Coordinates; right: Coordinates }
})[]
}
export const graphPositionDefaultValue = { x: 400, y: 100, scale: 1 }
2021-12-16 10:43:49 +01:00
2022-01-12 09:10:59 +01:00
export type ConnectingIds = {
source: Source
2022-01-06 09:40:56 +01:00
target?: Target
2022-01-12 09:10:59 +01:00
}
2022-01-15 17:30:20 +01:00
type StepId = string
type ButtonId = string
2022-01-15 17:30:20 +01:00
export type Endpoint = {
id: StepId | ButtonId
2022-01-15 17:30:20 +01:00
ref: MutableRefObject<HTMLDivElement | null>
}
export type BlocksCoordinates = IdMap<Coordinates>
2021-12-16 10:43:49 +01:00
const graphContext = createContext<{
blocksCoordinates: BlocksCoordinates
updateBlockCoordinates: (blockId: string, newCoord: Coordinates) => void
2021-12-16 10:43:49 +01:00
graphPosition: Position
setGraphPosition: Dispatch<SetStateAction<Position>>
2022-01-12 09:10:59 +01:00
connectingIds: ConnectingIds | null
setConnectingIds: Dispatch<SetStateAction<ConnectingIds | null>>
previewingEdge?: Edge
setPreviewingEdge: Dispatch<SetStateAction<Edge | undefined>>
sourceEndpoints: IdMap<Endpoint>
2022-01-15 17:30:20 +01:00
addSourceEndpoint: (endpoint: Endpoint) => void
targetEndpoints: IdMap<Endpoint>
2022-01-15 17:30:20 +01:00
addTargetEndpoint: (endpoint: Endpoint) => void
openedStepId?: string
setOpenedStepId: Dispatch<SetStateAction<string | undefined>>
isReadOnly: boolean
focusedBlockId?: string
setFocusedBlockId: Dispatch<SetStateAction<string | undefined>>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
2021-12-16 10:43:49 +01:00
}>({
graphPosition: graphPositionDefaultValue,
connectingIds: null,
})
export const GraphProvider = ({
children,
blocks,
isReadOnly = false,
}: {
children: ReactNode
blocks: Block[]
isReadOnly?: boolean
}) => {
2021-12-16 10:43:49 +01:00
const [graphPosition, setGraphPosition] = useState(graphPositionDefaultValue)
2022-01-12 09:10:59 +01:00
const [connectingIds, setConnectingIds] = useState<ConnectingIds | null>(null)
const [previewingEdge, setPreviewingEdge] = useState<Edge>()
const [sourceEndpoints, setSourceEndpoints] = useState<IdMap<Endpoint>>({})
const [targetEndpoints, setTargetEndpoints] = useState<IdMap<Endpoint>>({})
const [openedStepId, setOpenedStepId] = useState<string>()
const [blocksCoordinates, setBlocksCoordinates] = useState<BlocksCoordinates>(
{}
)
const [focusedBlockId, setFocusedBlockId] = useState<string>()
useEffect(() => {
setBlocksCoordinates(
blocks.reduce(
(coords, block) => ({
...coords,
[block.id]: block.graphCoordinates,
}),
{}
)
)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [blocks])
2022-01-15 17:30:20 +01:00
const addSourceEndpoint = (endpoint: Endpoint) => {
setSourceEndpoints((endpoints) => ({
...endpoints,
[endpoint.id]: endpoint,
2022-01-15 17:30:20 +01:00
}))
}
const addTargetEndpoint = (endpoint: Endpoint) => {
setTargetEndpoints((endpoints) => ({
...endpoints,
[endpoint.id]: endpoint,
2022-01-15 17:30:20 +01:00
}))
}
2021-12-16 10:43:49 +01:00
const updateBlockCoordinates = (blockId: string, newCoord: Coordinates) =>
setBlocksCoordinates((blocksCoordinates) => ({
...blocksCoordinates,
[blockId]: newCoord,
}))
2021-12-16 10:43:49 +01:00
return (
<graphContext.Provider
value={{
graphPosition,
setGraphPosition,
connectingIds,
setConnectingIds,
previewingEdge,
setPreviewingEdge,
2022-01-15 17:30:20 +01:00
sourceEndpoints,
targetEndpoints,
addSourceEndpoint,
addTargetEndpoint,
openedStepId,
setOpenedStepId,
blocksCoordinates,
updateBlockCoordinates,
isReadOnly,
focusedBlockId,
setFocusedBlockId,
2021-12-16 10:43:49 +01:00
}}
>
{children}
</graphContext.Provider>
)
}
export const useGraph = () => useContext(graphContext)