Skip to content

Commit

Permalink
Merge pull request #10 from mezh-hq/development
Browse files Browse the repository at this point in the history
Feature / UI Revamp
  • Loading branch information
Akalanka47000 committed Aug 27, 2024
2 parents 7de7176 + 84ccf68 commit 57075ca
Show file tree
Hide file tree
Showing 90 changed files with 1,917 additions and 1,103 deletions.
2 changes: 1 addition & 1 deletion .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const preview: Preview = {
reactRouter: {},
options: {
storySort: {
order: ["Introduction", "Installation", "Customization"],
order: ["Introduction", "Installation", "Customization", "Modifying State", "External Shapes"]
},
}
},
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
Changelog

# v3.0.0 [2024-08-27]

## Major Release

### Features
- Complete UI overhaul with a new design system
- Adds support for element rotation
- Adds support for passing external shapes into the toolkit

---

# v2.1.1 [2024-08-07]

## Patch Release
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@

<br/>

<img width="1440" alt="image" src="https://github.com/mezh-hq/react-seat-toolkit/assets/73662613/1c0a5c80-e402-46ed-bc17-364730122173">
<img width="1440" alt="image" src="https://github.com/user-attachments/assets/a34e5eb6-73e6-437a-8712-8aaefed26483">

<p align="center">
<img width="49.5%" alt="image" src="https://github.com/mezh-hq/react-seat-toolkit/assets/73662613/18a321a0-4ced-49c8-91eb-44605ea2ab9c">
<img width="49.5%" alt="image" src="https://github.com/mezh-hq/react-seat-toolkit/assets/73662613/e43be42f-40b0-4aaf-8d3a-a538abc8b2c1">
<img width="49.5%" alt="image" src="https://github.com/user-attachments/assets/e6b08c94-fa08-4fd0-ad1d-9454f9511c0c">
<img width="49.5%" alt="image" src="https://github.com/user-attachments/assets/63405b00-b821-4a3a-9c16-66a1f05bd114">
</p>

## Features
Expand All @@ -40,7 +40,7 @@
- Change seat colors ✓
- Change seat labels ✓
- Change seat status ✓
- Group seats together into categories ✓
- Group seats into categories ✓
- Categorizer (Manage seat categories) ✓

- **Pen**
Expand Down Expand Up @@ -68,8 +68,8 @@

- **Miscallaneous**
- Add, move around and scale background images ✓
- Add and move around booths ✓
- Multiple element selection and deselection ✓
- Rotate elements ✓
- Bring elements to front or back ✓

- **Responsive**: The layout is responsive and can be viewed on any device ✓
Expand Down
Binary file modified bun.lockb
Binary file not shown.
3 changes: 1 addition & 2 deletions esbuild.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,13 @@ build({
outfile: "./dist/index.slim.js",
external: [
...options.external,
"@radix-ui/react-checkbox",
"@radix-ui/react-label",
"@radix-ui/react-popover",
"@radix-ui/react-radio-group",
"@radix-ui/react-select",
"@radix-ui/react-tooltip",
"class-variance-authority",
"lodash",
"lucide-react",
"tailwind-merge"
]
});
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mezh-hq/react-seat-toolkit",
"version": "2.1.1",
"version": "3.0.0-blizzard.8",
"description": "React UI library to design and render seat layouts",
"main": "dist/index.cjs",
"module": "dist/index.mjs",
Expand Down Expand Up @@ -63,11 +63,10 @@
"@interactjs/auto-start": "1.10.26",
"@interactjs/interact": "1.10.26",
"@mezh-hq/react-gridlines": "1.0.1",
"@radix-ui/react-checkbox": "1.0.4",
"@radix-ui/react-label": "2.0.2",
"@radix-ui/react-popover": "1.0.7",
"@radix-ui/react-radio-group": "1.1.3",
"@radix-ui/react-select": "2.0.0",
"@radix-ui/react-switch": "1.1.0",
"@radix-ui/react-tooltip": "1.0.6",
"@reduxjs/toolkit": "2.1.0",
"class-variance-authority": "0.7.0",
Expand Down Expand Up @@ -108,9 +107,7 @@
"eslint-plugin-react": "7.33.2",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-storybook": "0.6.13",
"install": "0.13.0",
"lefthook": "1.4.3",
"npm": "10.8.1",
"postcss": "8.4.31",
"prettier": "2.8.8",
"sonner": "1.5.0",
Expand Down
2 changes: 1 addition & 1 deletion src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { panDown, panLeft, panRight, panUp } from "@/components/workspace/zoom";
import { panDown, panLeft, panRight, panUp } from "@/components/workspace/dock";
import { store } from "@/store";
import { clearElements, deselectElement, selectElement } from "@/store/reducers/editor";
import { stateToJSON } from "@/utils";
Expand Down
2 changes: 1 addition & 1 deletion src/components/controls/control-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const ControlInput = ({ id, label, ...props }: ControlInputProps) => {
return (
<>
<Label htmlFor={id}>{label}</Label>
<Input id={id} className="col-span-2 h-8" {...props} />
<Input id={id} className="col-span-2" {...props} />
</>
);
};
Expand Down
20 changes: 14 additions & 6 deletions src/components/controls/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const onUploadClick = () => document.getElementById("image-input").click();

type IImageControlProps = Pick<ISTKProps, "options" | "styles">;

const ImageControls = ({ options: { maxImageSize = 1024000 } = {} }: IImageControlProps) => {
const Controls = ({ options: { maxImageSize = 1024000 } = {} }: IImageControlProps) => {
const [file, setFile] = useState(null);

const onUpload = async (e) => {
Expand Down Expand Up @@ -49,19 +49,27 @@ const ImageControls = ({ options: { maxImageSize = 1024000 } = {} }: IImageContr
}, [file]);

return (
<div className="w-full h-full flex flex-col justify-between gap-5">
<div className="w-full flex flex-col gap-5">
<div
className="h-full w-full flex justify-center items-center rounded-md cursor-pointer bg-gray-100 hover:bg-gray-200 transition-all duration-medium"
className="w-full aspect-square flex justify-center items-center rounded-md overflow-clip cursor-pointer bg-slate-100 border border-gray-200"
onClick={onUploadClick}
>
{file ? <img src={file} alt="uploaded image" className="h-full w-full" /> : <Image size={30} />}
{file ? (
<img src={file} alt="uploaded image" className="h-full w-full object-cover" />
) : (
<Image size={24} className="text-slate-500" />
)}
</div>
<Button className="py-2.5" onClick={onAddToWorkspace} disabled={!file}>
<Button className="py-2.5" variant="secondary" onClick={onAddToWorkspace} disabled={!file}>
Add to Workspace
</Button>
<input id="image-input" type="file" accept="image/*" className="hidden" onInput={onUpload} />
</div>
);
};

export default memo(ImageControls);
const ImageControls = memo(Controls);

(ImageControls as any).name = "ImageControls";

export default ImageControls;
48 changes: 29 additions & 19 deletions src/components/controls/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { useMemo } from "react";
import { X } from "lucide-react";
import { useSelector } from "react-redux";
import { twMerge } from "tailwind-merge";
import { dataAttributes, ids } from "@/constants";
import { store } from "@/store";
import { toggleControls } from "@/store/reducers/editor";
import { ISTKProps } from "@/types";
import { AnimatedSwitcher } from "../core";
import { AnimatedSwitcher, IconButton } from "../core";
import { Tool } from "../toolbar/data";
import { ElementType } from "../workspace/elements";
import { default as ImageControls } from "./image";
import { default as NoControls } from "./no-controls";
import { default as NoSelectedElement } from "./no-selection";
Expand All @@ -15,7 +17,9 @@ import { default as SeatControls } from "./seat";
import { default as SelectControls } from "./select";
import { default as ShapeControls } from "./shapes";

const transition = "transition-all duration-500";
const onCogClick = () => store.dispatch(toggleControls());

const transition = "transition-all duration-500 ease-in-out";

const width = "w-[22rem]";

Expand All @@ -32,7 +36,6 @@ const Controls = ({ options, styles }: IControlProps) => {
const firstElementType = document
.getElementById(selectedElementIds[0])
?.getAttribute?.(dataAttributes.elementType);
if (firstElementType === ElementType.Booth) return NoSelectionControls;
if (selectedElementIds.length > 1) {
const same = selectedElementIds.every((id) => {
return document.getElementById(id)?.getAttribute?.(dataAttributes.elementType) === firstElementType;
Expand All @@ -51,23 +54,30 @@ const Controls = ({ options, styles }: IControlProps) => {
}, [selectedTool, selectedElementIds]);

return (
<>
<div className={twMerge("pointer-events-none grow-0 shrink-0", transition, open ? width : "w-0")} />
<div
id={ids.controls}
className={twMerge(
"py-5 px-6 h-[calc(100%-32px)] absolute top-0 border-t border-black overflow-y-auto",
transition,
width,
open ? "right-0" : "-right-[22rem]"
)}
>
<AnimatedSwitcher
key={ControlComponent.name}
component={<ControlComponent options={options} styles={styles} />}
<div
id={ids.controls}
className={twMerge(
"h-full bg-white border-l shadow-lg border-gray-200 absolute top-0 overflow-y-auto z-10",
transition,
width,
open ? "right-0" : "-right-[22rem]"
)}
>
<div className="flex justify-between items-center gap-4 h-14 border-b border-gray-200 box-content px-5 sticky top-0 bg-white">
<h5>Settings</h5>
<IconButton
className="w-6 h-6 p-0 shrink-0"
variant="secondary"
icon={<X className="w-4 h-4" />}
onClick={onCogClick}
/>
</div>
</>
<AnimatedSwitcher
key={ControlComponent.name}
component={<ControlComponent options={options} styles={styles} />}
className="py-4 px-5 h-[calc(100%-3.5rem)]"
/>
</div>
);
};

Expand Down
8 changes: 4 additions & 4 deletions src/components/controls/no-controls.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CircleSlash } from "lucide-react";
import { Frame } from "lucide-react";

const NoControls = () => {
return (
<div className="h-full w-full flex flex-col justify-center items-center gap-6">
<span className="text-lg font-medium">No controls available for tool</span>
<CircleSlash size={40} strokeWidth={1} />
<div className="h-full w-full flex flex-col justify-center items-center gap-2 text-slate-400">
<Frame />
<p className="text-sm">No controls available for tool</p>
</div>
);
};
Expand Down
8 changes: 4 additions & 4 deletions src/components/controls/no-selection-controls.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CircleSlash } from "lucide-react";
import { FolderCog } from "lucide-react";

const NoSelectionControls = () => {
return (
<div className="h-full w-full flex flex-col justify-center items-center gap-6">
<span className="text-lg font-medium">No controls available for selection</span>
<CircleSlash size={40} strokeWidth={1} />
<div className="h-full w-full flex flex-col justify-center items-center gap-2 text-slate-400">
<FolderCog />
<p className="text-sm">No controls available for selection</p>
</div>
);
};
Expand Down
8 changes: 4 additions & 4 deletions src/components/controls/no-selection.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { CircleSlash } from "lucide-react";
import { MousePointerSquareDashed } from "lucide-react";

const NoSelectedElement = () => {
return (
<div className="h-full w-full flex flex-col justify-center items-center gap-6">
<span className="text-lg font-medium">No element selected</span>
<CircleSlash size={40} strokeWidth={1} />
<div className="h-full w-full flex flex-col justify-center items-center gap-2 text-slate-400">
<MousePointerSquareDashed />
<p className="text-sm">No element selected</p>
</div>
);
};
Expand Down
28 changes: 25 additions & 3 deletions src/components/controls/select/general.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import { useSelector } from "react-redux";
import { Button } from "@/components/core";
import { Button, Input, Label } from "@/components/core";
import { d3Extended } from "@/utils";

const GeneralSelectControls = () => {
const selectedElementIds = useSelector((state: any) => state.editor.selectedElementIds);

const firstElement = d3Extended.selectById(selectedElementIds[0]);
return (
<div className="flex flex-col gap-4 py-1 mt-1">
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-3">
<Label htmlFor="rotation-input">Rotation (deg)</Label>
<Input
id="rotation-input"
key={firstElement?.rotation()}
defaultValue={firstElement?.rotation()}
type="number"
min={-360}
max={360}
onChange={(e) => {
selectedElementIds.forEach((id) => {
const element = d3Extended.selectById(id);
if (element?.node()?.tagName === "svg") {
element.node().parentElement.style.transform = `rotate(${e.target.value}deg)`;
} else {
element.style("transform", `rotate(${e.target.value}deg)`);
}
});
}}
/>
</div>
<Button
className="py-[0.35rem]"
variant="secondary"
Expand All @@ -20,6 +41,7 @@ const GeneralSelectControls = () => {
</Button>
<Button
className="py-[0.35rem]"
variant="secondary"
onClick={() => {
selectedElementIds.forEach((id) => {
d3Extended.selectById(id).moveToBack();
Expand Down
15 changes: 6 additions & 9 deletions src/components/controls/select/image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from "react";
import { useSelector } from "react-redux";
import { Checkbox } from "@/components/core";
import { Label, Switch } from "@/components/core";
import { dataAttributes } from "@/constants";

const ImageSelectControls = () => {
Expand All @@ -18,14 +18,11 @@ const ImageSelectControls = () => {
};

return (
<div className="flex justify-end gap-4 py-1">
<Checkbox id="stk-lock-position" checked={locked} onCheckedChange={onCheckedChange} />
<label
htmlFor="stk-lock-position"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Object Lock
</label>
<div className="flex flex-col gap-5">
<div className="flex justify-between items-center gap-2">
<Label htmlFor="stk-lock-position">Object Lock</Label>
<Switch id="stk-lock-position" checked={locked} onCheckedChange={onCheckedChange} />
</div>
</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/controls/select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const SelectControls = ({ options, styles }: IControlProps) => {
}, [selectedElementIds]);

return (
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-5">
<ControlComponent options={options} styles={styles} />
<GeneralSelectControls />
</div>
Expand Down
Loading

0 comments on commit 57075ca

Please sign in to comment.