Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Revamp #8

Merged
merged 31 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
38d752f
Style(WIP): added few ui enhancements
miyurugunarathna Jul 28, 2024
f2e753f
Merge pull request #7 from mezh-hq/development
Akalanka47000 Jul 31, 2024
28450a4
Chore: manually updated version
Akalanka47000 Jul 31, 2024
f6e8ac9
Feat: added support for square shaped seats
Akalanka47000 Aug 2, 2024
956aad2
Feat: added a few more actions
Akalanka47000 Aug 7, 2024
17f8f1d
Fix: a ui issue
Akalanka47000 Aug 7, 2024
f0f7cc0
Feat: exposed actions to retrive state as well as the underlying redi…
Akalanka47000 Aug 7, 2024
3573482
CI: @mezh-hq/react-seat-toolkit - minor release
github-actions[bot] Aug 7, 2024
a396b3a
Merge remote-tracking branch 'origin/main' into feature/square-seats
Akalanka47000 Aug 7, 2024
bc0f97d
Fix: popover styling issue
Akalanka47000 Aug 7, 2024
220d780
Merge branch 'main' into feature/square-seats
Akalanka47000 Aug 7, 2024
f70b4d9
CI: @mezh-hq/react-seat-toolkit - patch release
github-actions[bot] Aug 7, 2024
11b695a
Fix: hid cursor above controls
Akalanka47000 Aug 7, 2024
036428b
Docs: updated changelog
Akalanka47000 Aug 7, 2024
7de7176
Docs: updated changelog
Akalanka47000 Aug 7, 2024
04c3bc6
Merge branch 'main' into feature/square-seats
Akalanka47000 Aug 8, 2024
4acbd22
Fix: pan handle alignment
Akalanka47000 Aug 8, 2024
6c4afe9
Fix: eraser icon
Akalanka47000 Aug 8, 2024
cc97222
Feat: element rotation
Akalanka47000 Aug 10, 2024
eeba3fe
Feat(wip): make more ui enhancements
miyurugunarathna Aug 10, 2024
449731e
Fix: cursor display
Akalanka47000 Aug 10, 2024
55a82d6
Feat: completed the dock
miyurugunarathna Aug 10, 2024
06b02e3
Feat: update content on drawer
miyurugunarathna Aug 10, 2024
cd2052b
Merge branch 'feature/square-seats' of https://github.com/mezh-hq/rea…
miyurugunarathna Aug 11, 2024
9efa5b2
Merge branch 'feature/element-rotation' of https://github.com/mezh-hq…
miyurugunarathna Aug 11, 2024
8353710
Feat: make few ui enhancements
miyurugunarathna Aug 11, 2024
027de56
Feat: completed ui revamping
miyurugunarathna Aug 11, 2024
b683c85
Fix: square seat delete
Akalanka47000 Aug 11, 2024
e63325e
Refactor: dock buttons
Akalanka47000 Aug 11, 2024
0077dfb
Refactor: dock file arrangement
Akalanka47000 Aug 11, 2024
948aa91
Feat: added few touch ups
miyurugunarathna Aug 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
Changelog

# v2.1.1 [2024-08-07]

## Patch Release

### Fixes
- Fixes an issue where the styles of the category and section selector were not being applied correctly.

---

# v2.1.0 [2024-08-07]

## Minor Release

### Features
- Adds 2 new actions, `actions.selectElement` and `actions.getState` to select an element and retrieve the updated state respectively.
- Exposes the `store` object which is the Redux store used by the toolkit to manage its state.

---

# v2.0.0 [2024-07-31]

## Patch with Breaking Changes
Expand Down
Binary file modified bun.lockb
Binary file not shown.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mezh-hq/react-seat-toolkit",
"version": "2.0.0-blizzard.2",
"version": "2.1.1",
"description": "React UI library to design and render seat layouts",
"main": "dist/index.cjs",
"module": "dist/index.mjs",
Expand Down Expand Up @@ -68,6 +68,7 @@
"@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
11 changes: 8 additions & 3 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
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 } from "@/store/reducers/editor";
import { clearElements, deselectElement, selectElement } from "@/store/reducers/editor";
import { stateToJSON } from "@/utils";

export const actions = {
const actions = {
selectElement: (elementId: string) => store.dispatch(selectElement(elementId)),
deselectElement: (elementId: string) => store.dispatch(deselectElement(elementId)),
deselectAllElements: () => store.dispatch(clearElements(false)),
getState: stateToJSON,
panLeft,
panDown,
panRight,
panUp
};

export { store, actions };

export default actions;
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
12 changes: 8 additions & 4 deletions src/components/controls/image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,18 @@ 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-border"
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} />
Expand Down
48 changes: 30 additions & 18 deletions src/components/controls/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
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";
Expand All @@ -15,7 +18,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 +37,7 @@ const Controls = ({ options, styles }: IControlProps) => {
const firstElementType = document
.getElementById(selectedElementIds[0])
?.getAttribute?.(dataAttributes.elementType);
if (firstElementType === ElementType.Booth) return NoSelectionControls;
if (firstElementType === ElementType.Booth) return SelectControls;
if (selectedElementIds.length > 1) {
const same = selectedElementIds.every((id) => {
return document.getElementById(id)?.getAttribute?.(dataAttributes.elementType) === firstElementType;
Expand All @@ -51,23 +56,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-border 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-border 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"
/>
</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
23 changes: 20 additions & 3 deletions src/components/controls/select/general.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
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) => {
d3Extended.selectById(id).style("transform", `rotate(${e.target.value}deg)`);
});
}}
/>
</div>
<Button
className="py-[0.35rem]"
variant="secondary"
Expand All @@ -20,6 +36,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
5 changes: 3 additions & 2 deletions src/components/controls/select/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo } from "react";
import { Fragment, useMemo } from "react";
import { useSelector } from "react-redux";
import { ElementType } from "@/components/workspace/elements";
import { dataAttributes } from "@/constants";
Expand All @@ -21,11 +21,12 @@ const SelectControls = ({ options, styles }: IControlProps) => {
if (firstElementType === ElementType.Shape) return ShapeSelectControls;
if (firstElementType === ElementType.Polyline) return PolylineSelectControls;
if (firstElementType === ElementType.Image) return ImageSelectControls;
if (firstElementType === ElementType.Booth) return Fragment;
return SeatSelectControls;
}, [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
46 changes: 22 additions & 24 deletions src/components/controls/select/polyline/section-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Percent, Trash2 } from "lucide-react";
import { DollarSign, Plus, X } from "lucide-react";
import { useSelector } from "react-redux";
import { default as debounce } from "lodash/debounce";
import { twMerge } from "tailwind-merge";
import { Input, Popover, PopoverContent, PopoverTrigger } from "@/components/core";
import { IconButton, Input, Popover, PopoverContent, PopoverTrigger } from "@/components/core";
import { dataAttributes } from "@/constants";
import { store } from "@/store";
import { addSection, deleteSection, updatePolylines, updateSection } from "@/store/reducers/editor";
Expand All @@ -21,56 +21,54 @@ export const SectionManager = ({ options }: IControlProps) => {
const sections = useSelector((state: any) => state.editor.sections);
return (
<div className="grid gap-4">
<div className="flex flex-col gap-2">
<h4 className="font-bold leading-none pb-1">Manage Sections</h4>
<hr />
<span className="hover:text-gray-500 cursor-pointer transition-all duration-medium" onClick={onAddSection}>
+ Add Section
</span>
<hr />
<div className="flex gap-2 justify-between items-center">
<h6 className="font-medium text-sm">Sections</h6>
<IconButton
className="w-6 h-6 p-0"
variant="secondary"
icon={<Plus className="w-4 h-4" />}
onClick={onAddSection}
/>
</div>
<div className="flex flex-col gap-4">
{sections.map(
(section, index) =>
section.id !== "0" && (
<div key={`category-${section.id}`} className="flex justify-start items-center gap-4">
<div key={`category-${section.id}`} className="flex justify-start items-center gap-2">
<input
defaultValue={section.color}
type="color"
className="flex-shrink-0 w-6 h-6 p-0 bg-white rounded-color-input"
className="flex-shrink-0 w-6 h-6 p-0 bg-white square-color-input"
onChange={(e) => onUpdateSection({ ...section, color: e.target.value })}
/>
<input
defaultValue={section.stroke}
type="color"
className="flex-shrink-0 w-6 h-6 p-0 bg-white rounded-color-input"
className="flex-shrink-0 w-6 h-6 p-0 bg-white square-color-input"
onChange={(e) => onUpdateSection({ ...section, stroke: e.target.value })}
/>
<Input
defaultValue={section.name}
className="h-8"
onChange={(e) => onUpdateSection({ ...section, name: e.target.value })}
/>
<Percent
size={22}
className={twMerge(
"flex-shrink-0 cursor-pointer transition-all duration-medium ",
section?.freeSeating ? "text-blue-600 hover:text-blue-500" : "hover:text-gray-500"
)}
<IconButton
className={twMerge("w-6 h-6 p-0 shrink-0", section?.freeSeating && "text-gray-400")}
variant="secondary"
icon={<DollarSign className="w-4 h-4" />}
onClick={() =>
section?.freeSeating
? onUpdateSection({ ...section, freeSeating: false })
: onUpdateSection({ ...section, freeSeating: true })
}
/>
{!options?.disableSectionDelete && (
<Trash2
size={22}
className={twMerge(
"hover:text-gray-500 flex-shrink-0 cursor-pointer transition-all duration-medium",
index === 0 && "opacity-0 pointer-events-none"
)}
<IconButton
className="w-6 h-6 p-0 shrink-0"
variant="secondary"
icon={<X className="w-4 h-4" />}
onClick={() => onDeleteSection(section.id)}
disabled={index === 0}
/>
)}
</div>
Expand Down
Loading
Loading