diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a4f4357..d48e721 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,7 +1,3 @@
-## Installation
-
-Run `bun i @mezh-hq/react-seat-toolkit` to incorporate into your project
-
## Getting started
- Run `bun install` to install all dependencies
diff --git a/README.md b/README.md
index 0d4f96f..0ac3084 100644
--- a/README.md
+++ b/README.md
@@ -29,8 +29,6 @@ React UI library to design and render seat layouts. The library is still under a
-
-
## Features
- **JSON based**: Define your seat layout using JSON data and retrieve it back as JSON after customization ✓
@@ -82,6 +80,71 @@ React UI library to design and render seat layouts. The library is still under a
- **Override styles**: Override the default styles to match your application's theme 🛠️
+## Installation
+
+Run `bun i @mezh-hq/react-seat-toolkit` to incorporate into your project
+
+## Usage
+
+### User mode
+
+```jsx
+import React from 'react';
+import SeatToolkit from '@mezh-hq/react-seat-toolkit';
+
+const App = () => {
+ const data = {
+ seats: [
+ {
+ id: '1',
+ x: 100,
+ y: 100,
+ label: 'A1',
+ color: 'blue',
+ },
+ ],
+ };
+ return (
+ {
+ console.log(seat);
+ },
+ onSectionClick: (section) => {
+ console.log(section);
+ },
+ }}
+ />
+ );
+};
+
+export default App;
+```
+
+### Designer mode
+
+```jsx
+import React from 'react';
+import SeatToolkit from '@mezh-hq/react-seat-toolkit';
+
+const App = () => {
+ return (
+ {
+ console.log(data);
+ },
+ }}
+ />
+ );
+};
+
+export default App;
+```
+
## Contributing
-Please read [CONTRIBUTING.md](https://github.com/mezh-hq/react-seat-toolkit/blob/main/CONTRIBUTING.md) for details on setting up your development environment and the process for submitting pull requests to us.
+Please read [CONTRIBUTING.md](https://github.com/mezh-hq/react-seat-toolkit/blob/main/CONTRIBUTING.md) for details on setting up your development environment and the process of submitting pull requests to us.
diff --git a/package.json b/package.json
index 0bfbf64..b02ebd6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@mezh-hq/react-seat-toolkit",
- "version": "0.0.1",
+ "version": "0.1.0-blizzard.1",
"description": "React UI library to design and render seat layouts",
"main": "dist/index.js",
"private": false,
@@ -23,7 +23,9 @@
"keywords": [
"Designer",
"Seats",
- "Layout"
+ "Layout",
+ "Hall arrangement",
+ "Editor"
],
"author": "Akalanka Perera, Miyuru Gunarathna",
"license": "MIT",
diff --git a/src/components/controls/index.jsx b/src/components/controls/index.tsx
similarity index 90%
rename from src/components/controls/index.jsx
rename to src/components/controls/index.tsx
index 76ce3b2..2f0bee8 100644
--- a/src/components/controls/index.jsx
+++ b/src/components/controls/index.tsx
@@ -17,9 +17,9 @@ const transition = "transition-all duration-500";
const width = "w-[22rem]";
const Controls = () => {
- const open = useSelector((state) => state.editor.showControls);
- const selectedTool = useSelector((state) => state.toolbar.selectedTool);
- const selectedElementIds = useSelector((state) => state.editor.selectedElementIds);
+ const open = useSelector((state: any) => state.editor.showControls);
+ const selectedTool = useSelector((state: any) => state.toolbar.selectedTool);
+ const selectedElementIds = useSelector((state: any) => state.editor.selectedElementIds);
const ControlComponent = useMemo(() => {
if (selectedTool === Tool.Select) {
diff --git a/src/components/core/animated-switcher.jsx b/src/components/core/animated-switcher.tsx
similarity index 59%
rename from src/components/core/animated-switcher.jsx
rename to src/components/core/animated-switcher.tsx
index 9f17a7a..f0066b5 100644
--- a/src/components/core/animated-switcher.jsx
+++ b/src/components/core/animated-switcher.tsx
@@ -1,7 +1,23 @@
import { motion } from "framer-motion";
import { twMerge } from "tailwind-merge";
-const AnimatedSwitcher = ({ customKey, component, alternateComponent, show, className, duration }) => {
+interface AnimatedSwitcherProps {
+ customKey?: string;
+ component: React.ReactNode;
+ alternateComponent?: React.ReactNode;
+ show: boolean;
+ className?: string;
+ duration?: number;
+}
+
+const AnimatedSwitcher = ({
+ customKey,
+ component,
+ alternateComponent,
+ show,
+ className,
+ duration
+}: AnimatedSwitcherProps) => {
return (
{
- const selectedTool = useSelector((state) => state.toolbar.selectedTool);
+ const selectedTool = useSelector((state: any) => state.toolbar.selectedTool);
return (
React Seat Toolkit
@@ -12,6 +12,7 @@ const Footer = () => {
customKey={selectedTool}
className="absolute top-[0.4rem] left-5 text-xs"
component={{tools[selectedTool]?.description}}
+ alternateComponent={null}
duration={0.2}
/>
diff --git a/src/components/index.jsx b/src/components/index.jsx
deleted file mode 100644
index 87e6411..0000000
--- a/src/components/index.jsx
+++ /dev/null
@@ -1,6 +0,0 @@
-export * from "./core";
-export * from "./workspace";
-export { default as Controls } from "./controls";
-export { default as Footer } from "./footer";
-export { default as Operations } from "./operations";
-export { default as Toolbar } from "./toolbar";
diff --git a/src/components/index.tsx b/src/components/index.tsx
new file mode 100644
index 0000000..bd83353
--- /dev/null
+++ b/src/components/index.tsx
@@ -0,0 +1,46 @@
+import { STKMode } from "@/constants";
+import { useEvents, useInteractions } from "@/hooks";
+import type { ISTKProps } from "@/types";
+import { default as Controls } from "./controls";
+import { default as Footer } from "./footer";
+import { default as Operations } from "./operations";
+import { default as Toolbar } from "./toolbar";
+import { Cursor, default as Workspace } from "./workspace";
+
+export * from "./core";
+
+const Designer: React.FC = (props) => {
+ useEvents();
+ useInteractions();
+ return (
+ <>
+
+
+
+ >
+ );
+};
+
+const User: React.FC = (props) => {
+ return (
+
+
+
+ );
+};
+
+const Core = (props: ISTKProps) => {
+ if (props.mode === STKMode.Designer) {
+ return ;
+ }
+ return ;
+};
+
+export default Core;
diff --git a/src/components/toolbar/index.jsx b/src/components/toolbar/index.tsx
similarity index 97%
rename from src/components/toolbar/index.jsx
rename to src/components/toolbar/index.tsx
index 0cf5cd7..6b73e25 100644
--- a/src/components/toolbar/index.jsx
+++ b/src/components/toolbar/index.tsx
@@ -11,7 +11,7 @@ import { selectFirstShape } from "../controls/shapes";
import { Tool, tools } from "./data";
const ToolBar = () => {
- const selectedTool = useSelector((state) => state.toolbar.selectedTool);
+ const selectedTool = useSelector((state: any) => state.toolbar.selectedTool);
const selectedPolylineId = store.getState().editor.selectedPolylineId;
const onEscape = useCallback(
diff --git a/src/components/workspace/crosshairs.jsx b/src/components/workspace/crosshairs.tsx
similarity index 97%
rename from src/components/workspace/crosshairs.jsx
rename to src/components/workspace/crosshairs.tsx
index 6587805..8143af2 100644
--- a/src/components/workspace/crosshairs.jsx
+++ b/src/components/workspace/crosshairs.tsx
@@ -7,7 +7,7 @@ export const Crosshairs = ({ render }) => {
const [y, setY] = useState(0);
const [enabled, setEnabled] = useState(false);
- const move = (e) => {
+ const move = (e: Event) => {
const pointer = d3.pointer(e);
setX(pointer[0]);
setY(pointer[1]);
diff --git a/src/components/workspace/cursor.jsx b/src/components/workspace/cursor.tsx
similarity index 96%
rename from src/components/workspace/cursor.jsx
rename to src/components/workspace/cursor.tsx
index 74eb295..372e373 100644
--- a/src/components/workspace/cursor.jsx
+++ b/src/components/workspace/cursor.tsx
@@ -13,7 +13,7 @@ export const Cursor = () => {
const [cursorX, setCursorX] = useState(0);
const [cursorY, setCursorY] = useState(0);
- const Cursor = useSelector((state) => state.editor.cursor);
+ const Cursor = useSelector((state: any) => state.editor.cursor);
const move = (e) => {
const pointer = d3.pointer(e);
diff --git a/src/components/workspace/elements/index.jsx b/src/components/workspace/elements/index.tsx
similarity index 82%
rename from src/components/workspace/elements/index.jsx
rename to src/components/workspace/elements/index.tsx
index 8d65658..8fc6784 100644
--- a/src/components/workspace/elements/index.jsx
+++ b/src/components/workspace/elements/index.tsx
@@ -2,7 +2,7 @@ import { memo, useEffect, useMemo, useRef } from "react";
import * as d3 from "d3";
import { isEqual } from "lodash";
import { twMerge } from "tailwind-merge";
-import { dataAttributes } from "@/constants";
+import { STKMode, dataAttributes } from "@/constants";
import { store } from "@/store";
import { clearAndSelectElements, deselectElement, selectElement } from "@/store/reducers/editor";
import { d3Extended } from "@/utils";
@@ -19,25 +19,26 @@ import {
export * from "./utils";
-export const Element = ({ type = ElementType.Seat, id, x = 250, y = 250, isSelected = false, ...props }) => {
- const ref = useRef();
+export const Element = ({ type = ElementType.Seat, id, x = 250, y = 250, isSelected = false, options, ...props }) => {
+ const ref = useRef();
const node = ref.current && d3.select(ref.current);
- const centerCoords = isSelected && node && d3Extended.getNodeCenter(node);
+ const centerCoords = isSelected && options.mode === STKMode.Designer && node && d3Extended.getNodeCenter(node);
const Element = elements[type];
const controlRadius = useMemo(() => {
+ if (!node) return 0;
switch (type) {
case ElementType.Seat:
- return node?.attr("r") * 6;
+ return +node.attr("r") * 6;
}
- return node?.attr("width") * 1.5;
+ return +node.attr("width") * 1.5;
}, [node]);
useEffect(() => {
- if (!ref.current) return;
+ if (!ref.current || options.mode !== STKMode.Designer) return;
const node = d3.select(ref.current);
if (type === ElementType.Seat) {
handleSeatDrag(node);
@@ -50,11 +51,11 @@ export const Element = ({ type = ElementType.Seat, id, x = 250, y = 250, isSelec
} else {
handleDrag(node);
}
- }, [ref]);
+ }, [ref, options.mode]);
- const onClick = (e) => {
+ const onClick = (e: any) => {
const selectedTool = store.getState().toolbar.selectedTool;
- if (selectedTool === Tool.Select) {
+ if (selectedTool === Tool.Select && ref.current) {
const ctrlPressed = e.ctrlKey || e.metaKey;
if (isSelected) {
if (ctrlPressed) {
@@ -101,6 +102,7 @@ export const Element = ({ type = ElementType.Seat, id, x = 250, y = 250, isSelec
!props.color && type !== ElementType.Text && "text-white"
)}
onClick={onClick}
+ options={options}
{...{ [dataAttributes.elementType]: type }}
/>
>
diff --git a/src/components/workspace/elements/seat.jsx b/src/components/workspace/elements/seat.jsx
index 7210782..4c3b62d 100644
--- a/src/components/workspace/elements/seat.jsx
+++ b/src/components/workspace/elements/seat.jsx
@@ -7,67 +7,79 @@ export const seatSize = 28;
export const seatLabelFontSize = seatSize / 3;
-const Seat = forwardRef(({ x, y, id, label, categories, category, status, ...props }, ref) => {
- const categoryObject = useMemo(() => categories?.find?.((c) => c.id === category), [categories, category]);
+const Seat = forwardRef(
+ ({ x, y, id, label, categories, category, status, onClick, options, element, ...props }, ref) => {
+ const categoryObject = useMemo(() => categories?.find?.((c) => c.id === category), [categories, category]);
- const textX = useMemo(() => {
- let value = (+ref.current?.getAttribute("cx") || x) - seatLabelFontSize / 3.5;
- const labelLength = label?.toString()?.length ?? 0;
- if (labelLength >= 2) value -= (seatLabelFontSize / 2.75) * (labelLength - 1);
- return value;
- }, [ref, label, x]);
+ const textX = useMemo(() => {
+ let value = (+ref.current?.getAttribute("cx") || x) - seatLabelFontSize / 3.5;
+ const labelLength = label?.toString()?.length ?? 0;
+ if (labelLength >= 2) value -= (seatLabelFontSize / 2.75) * (labelLength - 1);
+ return value;
+ }, [ref, label, x]);
- const textY = useMemo(() => {
- return (+ref.current?.getAttribute("cy") || y) + seatLabelFontSize / 2.75;
- }, [ref, label, y]);
+ const textY = useMemo(() => {
+ return (+ref.current?.getAttribute("cy") || y) + seatLabelFontSize / 2.75;
+ }, [ref, label, y]);
- useEffect(() => {
- if (ref.current) {
- const seat = d3Extended.select(ref.current);
- const seatLabel = d3Extended.selectById(`${id}-label`);
- const status = seat.attr(dataAttributes.status);
- if (status === SeatStatus.Unavailable || status === SeatStatus.Reserved) {
- seat.style("color", seatStatusColors[status].background);
- seatLabel?.style("stroke", seatStatusColors[status].label);
- } else {
- if (categoryObject) {
- seat.style("color", categoryObject.color);
- seatLabel?.style("stroke", categoryObject.textColor);
+ useEffect(() => {
+ if (ref.current) {
+ const seat = d3Extended.select(ref.current);
+ const seatLabel = d3Extended.selectById(`${id}-label`);
+ const status = seat.attr(dataAttributes.status);
+ if (status === SeatStatus.Unavailable || status === SeatStatus.Reserved) {
+ seat.style("color", seatStatusColors[status].background);
+ seatLabel?.style("stroke", seatStatusColors[status].label);
+ } else {
+ if (categoryObject) {
+ seat.style("color", categoryObject.color);
+ seatLabel?.style("stroke", categoryObject.textColor);
+ }
}
}
- }
- }, [ref, categoryObject]);
+ }, [ref, categoryObject]);
- return (
- <>
-
- {label && (
- {
+ onClick(e);
+ options.events?.onSeatClick?.({
+ ...element,
+ category: categoryObject
+ });
+ };
+
+ return (
+ <>
+
- {label ?? "A"}
-
- )}
- >
- );
-});
+ />
+ {label && (
+
+ {label ?? "A"}
+
+ )}
+ >
+ );
+ }
+);
Seat.displayName = "Seat";
diff --git a/src/components/workspace/elements/utils.js b/src/components/workspace/elements/utils.ts
similarity index 100%
rename from src/components/workspace/elements/utils.js
rename to src/components/workspace/elements/utils.ts
diff --git a/src/components/workspace/grid.jsx b/src/components/workspace/grid.tsx
similarity index 74%
rename from src/components/workspace/grid.jsx
rename to src/components/workspace/grid.tsx
index 0297015..93ac3e5 100644
--- a/src/components/workspace/grid.jsx
+++ b/src/components/workspace/grid.tsx
@@ -1,15 +1,14 @@
-import GridLines from "react-gridlines";
+import { default as GridLines } from "react-gridlines";
import { useSelector } from "react-redux";
import { AnimatedSwitcher } from "../core";
const Grid = () => {
- const grid = useSelector((state) => state.editor.grid);
+ const grid = useSelector((state: any) => state.editor.grid);
if (!grid) return null;
return (
}
- alternateComponent={null}
className="absolute top-0 left-0 pointer-events-none"
/>
);
diff --git a/src/components/workspace/index.jsx b/src/components/workspace/index.tsx
similarity index 64%
rename from src/components/workspace/index.jsx
rename to src/components/workspace/index.tsx
index 5603e16..9de630b 100644
--- a/src/components/workspace/index.jsx
+++ b/src/components/workspace/index.tsx
@@ -1,8 +1,9 @@
import { useCallback, useLayoutEffect } from "react";
import { useSelector } from "react-redux";
-import { ids } from "@/constants";
+import { STKMode, ids } from "@/constants";
import { store } from "@/store";
-import { initializeElements } from "@/store/reducers/editor";
+import { initializeElements, sync } from "@/store/reducers/editor";
+import type { ISTKProps } from "@/types";
import { Tool, tools } from "../toolbar/data";
import { default as Crosshairs } from "./crosshairs";
import { default as Element, ElementType } from "./elements";
@@ -11,21 +12,25 @@ import { default as Zoom } from "./zoom";
export { default as Cursor } from "./cursor";
-export const Workspace = () => {
- const booths = useSelector((state) => state.editor.booths);
- const seats = useSelector((state) => state.editor.seats);
- const text = useSelector((state) => state.editor.text);
- const shapes = useSelector((state) => state.editor.shapes);
- const polylines = useSelector((state) => state.editor.polylines);
- const images = useSelector((state) => state.editor.images);
- const categories = useSelector((state) => state.editor.categories);
- const selectedElementIds = useSelector((state) => state.editor.selectedElementIds);
- const selectedPolylineId = useSelector((state) => state.editor.selectedPolylineId);
- const selectedTool = useSelector((state) => state.toolbar.selectedTool);
+export const Workspace: React.FC = (props) => {
+ const booths = useSelector((state: any) => state.editor.booths);
+ const seats = useSelector((state: any) => state.editor.seats);
+ const text = useSelector((state: any) => state.editor.text);
+ const shapes = useSelector((state: any) => state.editor.shapes);
+ const polylines = useSelector((state: any) => state.editor.polylines);
+ const images = useSelector((state: any) => state.editor.images);
+ const categories = useSelector((state: any) => state.editor.categories);
+ const selectedElementIds = useSelector((state: any) => state.editor.selectedElementIds);
+ const selectedPolylineId = useSelector((state: any) => state.editor.selectedPolylineId);
+ const selectedTool = useSelector((state: any) => state.toolbar.selectedTool);
useLayoutEffect(() => {
- store.dispatch(initializeElements());
- }, []);
+ if (props.data) {
+ store.dispatch(sync(props.data));
+ } else {
+ store.dispatch(initializeElements());
+ }
+ }, [props.data]);
const elementProps = useCallback(
(elem) => ({
@@ -35,7 +40,12 @@ export const Workspace = () => {
isSelected: selectedElementIds.includes(elem.id),
label: elem.label,
color: elem.color,
- stroke: elem.stroke
+ stroke: elem.stroke,
+ options: {
+ mode: props.mode,
+ events: props.events
+ },
+ element: elem
}),
[selectedElementIds]
);
@@ -95,8 +105,12 @@ export const Workspace = () => {
{selectedPolylineId && }
-
-
+ {props.mode === STKMode.Designer && (
+ <>
+
+
+ >
+ )}
);
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 727f2bf..9634278 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -46,3 +46,8 @@ export const seatStatusColors = {
label: "#ffffff"
}
};
+
+export enum STKMode {
+ Designer = "designer",
+ User = "user"
+}
diff --git a/src/icons/arrow-pair.jsx b/src/icons/arrow-pair.tsx
similarity index 100%
rename from src/icons/arrow-pair.jsx
rename to src/icons/arrow-pair.tsx
diff --git a/src/icons/index.jsx b/src/icons/index.tsx
similarity index 100%
rename from src/icons/index.jsx
rename to src/icons/index.tsx
diff --git a/src/index.tsx b/src/index.tsx
index 010af74..ab66d23 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,34 +1,15 @@
import { Provider } from "react-redux";
-import { Controls, Cursor, Footer, Operations, Toolbar, TooltipProvider, Workspace } from "@/components";
-import { useEvents, useInteractions } from "@/hooks";
+import { default as Core, TooltipProvider } from "@/components";
import { store } from "@/store";
+import { type ISTKProps } from "./types";
-export const SeatToolkit = () => {
+export const SeatToolkit = (props: ISTKProps) => {
return (
-
-
- );
-};
-
-const Designer = () => {
- useEvents();
- useInteractions();
- return (
- <>
-
-
+
-
- >
+
);
};
diff --git a/src/store/reducers/editor/index.ts b/src/store/reducers/editor/index.ts
index 46b2591..fdcf0f2 100644
--- a/src/store/reducers/editor/index.ts
+++ b/src/store/reducers/editor/index.ts
@@ -1,5 +1,6 @@
import { createSlice } from "@reduxjs/toolkit";
import { v4 as uuidv4 } from "uuid";
+import type { ISTKData } from "@/types";
import booths from "./booths";
import seats from "./seats";
import shapes from "./shapes";
@@ -203,6 +204,13 @@ export const slice = createSlice({
},
setSelectedPolylineId: (state, action) => {
state.selectedPolylineId = action.payload;
+ },
+ sync: (state, action) => {
+ const { name, ...data } = action.payload as ISTKData;
+ state.location = name ?? state.location;
+ Object.keys(data).forEach((key) => {
+ state[key] = data[key] ?? state[key];
+ });
}
}
});
@@ -241,7 +249,8 @@ export const {
addSection,
updateSection,
deleteSection,
- setSelectedPolylineId
+ setSelectedPolylineId,
+ sync
} = slice.actions;
export default slice.reducer;
diff --git a/src/stories/designer.stories.jsx b/src/stories/designer.stories.tsx
similarity index 58%
rename from src/stories/designer.stories.jsx
rename to src/stories/designer.stories.tsx
index 6e5dc5f..b6013b2 100644
--- a/src/stories/designer.stories.jsx
+++ b/src/stories/designer.stories.tsx
@@ -1,7 +1,8 @@
+import { STKMode } from "@/constants";
import SeatToolkit from "@/index";
export default {
- title: "Designer",
+ title: "Designer Mode",
component: SeatToolkit,
parameters: {
layout: "fullscreen"
@@ -10,5 +11,5 @@ export default {
};
export const Default = {
- render: () =>
+ render: () =>
};
diff --git a/src/stories/user.stories.tsx b/src/stories/user.stories.tsx
new file mode 100644
index 0000000..77a2978
--- /dev/null
+++ b/src/stories/user.stories.tsx
@@ -0,0 +1,41 @@
+import { STKMode } from "@/constants";
+import SeatToolkit from "@/index";
+
+export default {
+ title: "User Mode",
+ component: SeatToolkit,
+ parameters: {
+ layout: "fullscreen"
+ },
+ argTypes: {}
+};
+
+export const Default = {
+ render: () => (
+ console.log(seat)
+ }}
+ />
+ )
+};
diff --git a/src/types/elements/booth.ts b/src/types/elements/booth.ts
new file mode 100644
index 0000000..6525e9e
--- /dev/null
+++ b/src/types/elements/booth.ts
@@ -0,0 +1,5 @@
+export interface IBooth {
+ id: string;
+ x: number;
+ y: number;
+}
diff --git a/src/types/elements/image.ts b/src/types/elements/image.ts
new file mode 100644
index 0000000..99fe52e
--- /dev/null
+++ b/src/types/elements/image.ts
@@ -0,0 +1,8 @@
+export interface IImage {
+ id: string;
+ x: number;
+ y: number;
+ href: string;
+ width?: number;
+ height?: number;
+}
diff --git a/src/types/elements/index.ts b/src/types/elements/index.ts
new file mode 100644
index 0000000..8a61a15
--- /dev/null
+++ b/src/types/elements/index.ts
@@ -0,0 +1,6 @@
+export * from "./image";
+export * from "./seat";
+export * from "./text";
+export * from "./shape";
+export * from "./booth";
+export * from "./polyline";
diff --git a/src/types/elements/polyline.ts b/src/types/elements/polyline.ts
new file mode 100644
index 0000000..e5506c4
--- /dev/null
+++ b/src/types/elements/polyline.ts
@@ -0,0 +1,20 @@
+export interface ISection {
+ id: string;
+ name: string;
+ color: string;
+ freeSeating: boolean;
+ capacity?: number;
+}
+
+export interface IPolylinepoint {
+ x: number;
+ y: number;
+}
+
+export interface IPolyline {
+ id: string;
+ points: IPolylinepoint[];
+ color?: string;
+ stroke?: string;
+ section?: string;
+}
diff --git a/src/types/elements/seat.ts b/src/types/elements/seat.ts
new file mode 100644
index 0000000..46a150b
--- /dev/null
+++ b/src/types/elements/seat.ts
@@ -0,0 +1,18 @@
+import { SeatStatus } from "@/constants";
+
+export interface ISeatCategory {
+ id: string;
+ name: string;
+ color: string;
+ textColor: string;
+ cost: number;
+}
+
+export interface ISeat {
+ id: string;
+ x: number;
+ y: number;
+ label?: string;
+ category?: string;
+ status?: SeatStatus;
+}
diff --git a/src/types/elements/shape.ts b/src/types/elements/shape.ts
new file mode 100644
index 0000000..9bdf575
--- /dev/null
+++ b/src/types/elements/shape.ts
@@ -0,0 +1,11 @@
+export interface IShape {
+ id: string;
+ x: number;
+ y: number;
+ name: string;
+ width?: number;
+ height?: number;
+ rx?: number;
+ stroke?: string;
+ color?: string;
+}
diff --git a/src/types/elements/text.ts b/src/types/elements/text.ts
new file mode 100644
index 0000000..d052bec
--- /dev/null
+++ b/src/types/elements/text.ts
@@ -0,0 +1,10 @@
+export interface IText {
+ id: string;
+ x: number;
+ y: number;
+ label?: string;
+ fontSize?: number;
+ fontWeight?: number;
+ letterSpacing?: number;
+ color?: string;
+}
diff --git a/src/types/index.ts b/src/types/index.ts
new file mode 100644
index 0000000..8696362
--- /dev/null
+++ b/src/types/index.ts
@@ -0,0 +1,26 @@
+import { STKMode } from "@/constants";
+import { IBooth, IImage, IPolyline, ISeat, ISeatCategory, ISection, IShape, IText } from "./elements";
+
+export interface IEvents {
+ onSeatClick?: (seat: ISeat & { category?: ISeatCategory }) => void;
+ onSectionClick?: (section: ISection) => void;
+ onExport?: (data: ISTKData) => void;
+}
+
+export interface ISTKData {
+ name?: string;
+ categories?: ISeatCategory[];
+ sections?: ISection[];
+ seats?: ISeat[];
+ booths?: IBooth[];
+ text?: IText[];
+ shapes?: IShape[];
+ polylines?: IPolyline[];
+ images?: IImage[];
+}
+
+export interface ISTKProps {
+ mode: STKMode;
+ events?: IEvents;
+ data?: ISTKData;
+}
diff --git a/src/utils/workspace.ts b/src/utils/workspace.ts
index baa0172..6050aca 100644
--- a/src/utils/workspace.ts
+++ b/src/utils/workspace.ts
@@ -12,10 +12,10 @@ export const getWorkspaceHeight = () => {
export const getWorkspaceCenterX = () => {
const workspaceContainer = document.getElementById(ids.workspaceContainer);
- return window.innerWidth / 2 - workspaceContainer.offsetLeft - 8;
+ return window.innerWidth / 2 - (workspaceContainer?.offsetLeft ?? 0) - 8;
};
export const getWorkspaceCenterY = () => {
const workspaceContainer = document.getElementById(ids.workspaceContainer);
- return window.innerHeight / 2 - workspaceContainer.offsetTop;
+ return window.innerHeight / 2 - (workspaceContainer?.offsetTop ?? 0);
};
diff --git a/jsconfig.json b/tsconfig.json
similarity index 79%
rename from jsconfig.json
rename to tsconfig.json
index 4334062..e87e8ee 100644
--- a/jsconfig.json
+++ b/tsconfig.json
@@ -5,6 +5,6 @@
"@/*": ["*"]
},
"jsx": "react-jsx",
- "resolveJsonModule": true
+ "resolveJsonModule": true,
},
}