diff --git a/src/components/Connectors/Connector/Connector.tsx b/src/components/Connectors/Connector/Connector.tsx index 7f89f68..dc572da 100644 --- a/src/components/Connectors/Connector/Connector.tsx +++ b/src/components/Connectors/Connector/Connector.tsx @@ -59,6 +59,18 @@ export const Connector = ({ connector }: Props) => { return (unprojectedTileSize / 100) * connector.width; }, [connector.width, unprojectedTileSize]); + const strokeDashArray = useMemo(() => { + switch (connector.style) { + case 'DASHED': + return `${connectorWidthPx * 1.5}, ${connectorWidthPx * 1.5}`; + case 'DOTTED': + return `0, ${connectorWidthPx * 1.4}`; + case 'SOLID': + default: + return 'none'; + } + }, [connector.style, connectorWidthPx]); + return ( { strokeWidth={connectorWidthPx} strokeLinecap="round" strokeLinejoin="round" + strokeDasharray={strokeDashArray} fill="none" /> {anchorPositions.map((anchor) => { diff --git a/src/components/ItemControls/ConnectorControls/ConnectorControls.tsx b/src/components/ItemControls/ConnectorControls/ConnectorControls.tsx index 9d46937..3675203 100644 --- a/src/components/ItemControls/ConnectorControls/ConnectorControls.tsx +++ b/src/components/ItemControls/ConnectorControls/ConnectorControls.tsx @@ -1,6 +1,6 @@ import React, { useCallback } from 'react'; -import { Connector } from 'src/types'; -import { useTheme, Box, Slider } from '@mui/material'; +import { Connector, ConnectorStyleEnum } from 'src/types'; +import { useTheme, Box, Slider, Select, MenuItem } from '@mui/material'; import { useSceneStore } from 'src/stores/sceneStore'; import { useConnector } from 'src/hooks/useConnector'; import { ColorSelector } from 'src/components/ColorSelector/ColorSelector'; @@ -59,6 +59,20 @@ export const ConnectorControls = ({ id }: Props) => { }} /> +
+ +
diff --git a/src/config.ts b/src/config.ts index 80caf61..ea25b33 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,10 @@ -import { Size, Coords, SceneInput } from 'src/types'; +import { + Size, + Coords, + SceneInput, + Connector, + ConnectorStyleEnum +} from 'src/types'; import { customVars } from './styles/theme'; export const UNPROJECTED_TILE_SIZE = 100; @@ -8,21 +14,24 @@ export const TILE_PROJECTION_MULTIPLIERS: Size = { }; export const DEFAULT_COLOR = customVars.diagramPalette.blue; -interface ConnectorDefaults { - width: number; - searchOffset: Coords; -} export const NODE_DEFAULTS = { label: '', labelHeight: 140, color: DEFAULT_COLOR }; +interface ConnectorDefaults { + width: number; + searchOffset: Coords; + style: Connector['style']; +} + export const CONNECTOR_DEFAULTS: ConnectorDefaults = { width: 20, // The boundaries of the search area for the pathfinder algorithm // is the grid that encompasses the two nodes + the offset below. - searchOffset: { x: 3, y: 3 } + searchOffset: { x: 3, y: 3 }, + style: ConnectorStyleEnum.SOLID }; export const ZOOM_INCREMENT = 0.2; export const MIN_ZOOM = 0.2; diff --git a/src/types/inputs.ts b/src/types/inputs.ts index 47584f4..3cf820d 100644 --- a/src/types/inputs.ts +++ b/src/types/inputs.ts @@ -8,6 +8,7 @@ import { } from 'src/validation/sceneItems'; import { sceneInput } from 'src/validation/scene'; +export { ConnectorStyleEnum } from 'src/validation/sceneItems'; export type IconInput = z.infer; export type NodeInput = z.infer; export type ConnectorAnchorInput = z.infer; diff --git a/src/types/scene.ts b/src/types/scene.ts index c4e0d4a..baf49d3 100644 --- a/src/types/scene.ts +++ b/src/types/scene.ts @@ -4,7 +4,8 @@ import { SceneInput, RectangleInput, ConnectorInput, - NodeInput + NodeInput, + ConnectorStyleEnum } from './inputs'; export enum TileOriginEnum { @@ -47,6 +48,7 @@ export interface Connector { id: string; color: string; width: number; + style: ConnectorStyleEnum; anchors: ConnectorAnchor[]; path: { tiles: Coords[]; diff --git a/src/utils/inputs.ts b/src/utils/inputs.ts index 6928030..ff12e20 100644 --- a/src/utils/inputs.ts +++ b/src/utils/inputs.ts @@ -73,6 +73,7 @@ export const connectorInputToConnector = ( id: connectorInput.id, color: connectorInput.color ?? DEFAULT_COLOR, width: connectorInput.width ?? CONNECTOR_DEFAULTS.width, + style: connectorInput.style ?? CONNECTOR_DEFAULTS.style, anchors, path: getConnectorPath({ anchors, nodes }) }; diff --git a/src/validation/sceneItems.ts b/src/validation/sceneItems.ts index 9214e2a..e399dab 100644 --- a/src/validation/sceneItems.ts +++ b/src/validation/sceneItems.ts @@ -37,10 +37,23 @@ export const connectorAnchorInput = z } }); +export enum ConnectorStyleEnum { + SOLID = 'SOLID', + DOTTED = 'DOTTED', + DASHED = 'DASHED' +} + export const connectorInput = z.object({ id: z.string(), color: z.string().optional(), width: z.number().optional(), + style: z + .union([ + z.literal(ConnectorStyleEnum.SOLID), + z.literal(ConnectorStyleEnum.DOTTED), + z.literal(ConnectorStyleEnum.DASHED) + ]) + .optional(), anchors: z.array(connectorAnchorInput) });