From 5513716d6fb3d3da1bfdfe7d633369beb7b1d68b Mon Sep 17 00:00:00 2001 From: Akalanka Perera Date: Fri, 5 Apr 2024 20:54:10 +0530 Subject: [PATCH] Feat: added chain seat selection mode --- src/components/workspace/elements/index.tsx | 35 ++++++++++++--------- src/components/workspace/index.tsx | 8 +++-- src/components/workspace/reload.tsx | 22 +++++++++++++ src/components/workspace/visibility.tsx | 5 ++- src/components/workspace/zoom.tsx | 6 ++-- src/constants/index.ts | 3 +- src/types/index.ts | 5 +++ src/types/styles.ts | 1 + 8 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 src/components/workspace/reload.tsx diff --git a/src/components/workspace/elements/index.tsx b/src/components/workspace/elements/index.tsx index c962d1b..f5d0ea2 100644 --- a/src/components/workspace/elements/index.tsx +++ b/src/components/workspace/elements/index.tsx @@ -58,23 +58,30 @@ export const Element: React.FC = ({ const onClick = (e: any) => { if ( consumer.mode === "user" && - (type !== ElementType.Seat || - (type === ElementType.Seat && props.status && props.status !== SeatStatus.Available)) - ) + (type !== ElementType.Seat || (props.status && props.status !== SeatStatus.Available)) + ) { return; - const selectedTool = store.getState().toolbar.selectedTool; - if (selectedTool === Tool.Select && ref.current) { - const ctrlPressed = e.ctrlKey || e.metaKey; + } + if (consumer.mode === "user" && consumer.seatSelectionMode === "chain") { if (isSelected) { - if (ctrlPressed) { - return store.dispatch(deselectElement(ref.current.id)); - } - return; + return store.dispatch(deselectElement(id)); } - if (!ctrlPressed) { - store.dispatch(clearAndSelectElements([ref.current.id])); - } else { - store.dispatch(selectElement(ref.current.id)); + return store.dispatch(selectElement(id)); + } else { + const selectedTool = store.getState().toolbar.selectedTool; + if (selectedTool === Tool.Select && ref.current) { + const ctrlPressed = e.ctrlKey || e.metaKey; + if (isSelected) { + if (ctrlPressed) { + return store.dispatch(deselectElement(ref.current.id)); + } + return; + } + if (!ctrlPressed) { + store.dispatch(clearAndSelectElements([ref.current.id])); + } else { + store.dispatch(selectElement(ref.current.id)); + } } } }; diff --git a/src/components/workspace/index.tsx b/src/components/workspace/index.tsx index 15226a6..b2abc22 100644 --- a/src/components/workspace/index.tsx +++ b/src/components/workspace/index.tsx @@ -7,6 +7,7 @@ import { Tool, tools } from "../toolbar/data"; import { default as Crosshairs } from "./crosshairs"; import { default as Element, ElementType } from "./elements"; import { default as Grid } from "./grid"; +import { default as Reload } from "./reload"; import { default as VisibilityControls } from "./visibility"; import { default as Zoom } from "./zoom"; @@ -46,6 +47,8 @@ export const Workspace: React.FC = (props) => { [selectedElementIds] ); + const showReloadButton = props.options?.showReloadButton ?? false; + const showZoomControls = props.options?.showZoomControls ?? true; const showVisibilityControls = props.mode === "designer" && (props.options?.showVisibilityControls ?? true); @@ -135,8 +138,9 @@ export const Workspace: React.FC = (props) => { )} - {showZoomControls && } - {showVisibilityControls && } + {showZoomControls && } + {showVisibilityControls && } + {showReloadButton && } ); }; diff --git a/src/components/workspace/reload.tsx b/src/components/workspace/reload.tsx new file mode 100644 index 0000000..7f18305 --- /dev/null +++ b/src/components/workspace/reload.tsx @@ -0,0 +1,22 @@ +import { memo } from "react"; +import { RotateCcw } from "lucide-react"; +import { twMerge } from "tailwind-merge"; +import { ids } from "@/constants"; +import type { ISTKProps } from "@/types"; + +const Reloader = (props: Pick) => { + return ( +
svg]:hover:-rotate-45 [&>svg]:transition-all [&>svg]:transition-medium rounded-md p-2 transition-all duration-medium", + props.styles?.reloadButton?.className + )} + style={props.styles?.reloadButton?.properties} + > + +
+ ); +}; + +export default memo(Reloader); diff --git a/src/components/workspace/visibility.tsx b/src/components/workspace/visibility.tsx index 9545bea..51ff9db 100644 --- a/src/components/workspace/visibility.tsx +++ b/src/components/workspace/visibility.tsx @@ -1,4 +1,3 @@ -import { memo } from "react"; import { useSelector } from "react-redux"; import { twMerge } from "tailwind-merge"; import { dataAttributes, ids, selectors } from "@/constants"; @@ -26,7 +25,7 @@ const unsetVisibility = () => { showAllElements(); }; -const VisibilityControls = (props: ISTKProps) => { +const VisibilityControls = (props: Pick) => { const initialViewBoxScale = useSelector((state: any) => state.editor.initialViewBoxScale); const visibilityOffset = useSelector((state: any) => state.editor.visibilityOffset); @@ -60,4 +59,4 @@ const VisibilityControls = (props: ISTKProps) => { ); }; -export default memo(VisibilityControls); +export default VisibilityControls; diff --git a/src/components/workspace/zoom.tsx b/src/components/workspace/zoom.tsx index 28e9407..ac308f6 100644 --- a/src/components/workspace/zoom.tsx +++ b/src/components/workspace/zoom.tsx @@ -1,4 +1,4 @@ -import { memo, useLayoutEffect } from "react"; +import { useLayoutEffect } from "react"; import { ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Minus, Plus } from "lucide-react"; import { useSelector } from "react-redux"; import { twMerge } from "tailwind-merge"; @@ -69,7 +69,7 @@ export const panAndZoomWithTransition = ({ k, x, y }) => { const panHandleClasses = "absolute z-10 text-black/40 cursor-pointer hover:text-black/80 transition-all duration-medium"; -const Zoom = (props: ISTKProps) => { +const Zoom = (props: Pick) => { const selectedTool = useSelector((state: any) => state.toolbar.selectedTool); const showControls = useSelector((state: any) => state.editor.showControls); @@ -198,4 +198,4 @@ const Zoom = (props: ISTKProps) => { ); }; -export default memo(Zoom); +export default Zoom; diff --git a/src/constants/index.ts b/src/constants/index.ts index b99baee..015cc7a 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -14,7 +14,8 @@ export const ids = { workspaceContainer: "stk-workspace-container", zoomControls: "stk-zoom-controls", panControls: "stk-pan-controls", - visibilityControls: "stk-visibility-controls" + visibilityControls: "stk-visibility-controls", + reloader: "stk-reloader" }; export const selectors = { diff --git a/src/types/index.ts b/src/types/index.ts index 6fbd759..ebececc 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -15,6 +15,8 @@ export * from "./elements"; export type STKMode = "designer" | "user"; +export type SeatSelectionMode = "default" | "chain"; + export interface ICoordinates { x: number; y: number; @@ -52,6 +54,8 @@ export interface ISTKData { export interface ISTKProps { mode: STKMode; + /** Only applicable in user mode. If set to "chain", user can select multiple seats in a row without pressing ctrl and needs to reclick a selected seat to deselect it. */ + seatSelectionMode?: SeatSelectionMode; events?: IEvents; data?: ISTKData; styles?: IStyles; @@ -61,6 +65,7 @@ export interface ISTKProps { showFooter?: boolean; showZoomControls?: boolean; showVisibilityControls?: boolean; + showReloadButton?: boolean; exportButtonText?: string; operationTriggerIcon?: React.FC; seatIcon?: React.FC; diff --git a/src/types/styles.ts b/src/types/styles.ts index 8dd9a6d..29ec5ae 100644 --- a/src/types/styles.ts +++ b/src/types/styles.ts @@ -47,6 +47,7 @@ export interface IStyles { root?: IStyle; buttons?: IStyle; }; + reloadButton?: IStyle; elements?: { booth?: { selected?: IStyle;