diff --git a/src/components/controls/shapes/index.tsx b/src/components/controls/shapes/index.tsx index 57b9b4d..e1135a9 100644 --- a/src/components/controls/shapes/index.tsx +++ b/src/components/controls/shapes/index.tsx @@ -2,11 +2,13 @@ import { memo, useCallback, useState } from "react"; import { RectangleHorizontal } from "lucide-react"; import { default as isEqual } from "lodash/isEqual"; import { twMerge } from "tailwind-merge"; +import { useShapes } from "@/hooks"; +import { getMergedShapes } from "@/hooks/shapes"; import { store } from "@/store"; import { setCursor } from "@/store/reducers/editor"; +import { ISTKProps } from "@/types"; import { fallible } from "@/utils"; import { resizableRectangle, shapeSize, shapeStrokeWidth } from "../../workspace/elements/shape"; -import { shapeList } from "./shape-list"; const CursorShape = (Shape) => { const icon = (props) => ( @@ -25,7 +27,7 @@ const CursorShape = (Shape) => { return icon; }; -const Controls = () => { +const Controls = ({ options }: Pick) => { const [selectedIndex, setSelectedIndex] = useState(0); const onShapeClick = useCallback((shape, i) => { @@ -35,9 +37,11 @@ const Controls = () => { }); }, []); + const shapes = useShapes({ options }); + return (
- {shapeList.map((Shape, i) => ( + {shapes.map((Shape, i) => (
{ ); }; -export const selectFirstShape = () => +export const selectFirstShape = ({ options }: Pick) => fallible(() => { - store.dispatch(setCursor(CursorShape(shapeList[0]))); + store.dispatch(setCursor(CursorShape(getMergedShapes(options)[0]))); }); const ShapeControls = memo(Controls, isEqual); diff --git a/src/components/toolbar/index.tsx b/src/components/toolbar/index.tsx index 0737f13..0fdf12f 100644 --- a/src/components/toolbar/index.tsx +++ b/src/components/toolbar/index.tsx @@ -66,7 +66,7 @@ const ToolBar: React.FC = (props) => { store.dispatch(selectTool(tool)); if ([Tool.Image, Tool.Shape].includes(tool)) { store.dispatch(showControls()); - if (tool === Tool.Shape) selectFirstShape(); + if (tool === Tool.Shape) selectFirstShape({ options: props.options }); } if (tool !== Tool.Pen && selectedPolylineId) { store.dispatch(setSelectedPolylineId(null)); diff --git a/src/components/workspace/elements/shape.tsx b/src/components/workspace/elements/shape.tsx index ba0e274..07f0a97 100644 --- a/src/components/workspace/elements/shape.tsx +++ b/src/components/workspace/elements/shape.tsx @@ -1,7 +1,7 @@ import { forwardRef } from "react"; import { twMerge } from "tailwind-merge"; -import { shapes } from "@/components/controls/shapes/shape-list"; import { dataAttributes } from "@/constants"; +import { useShapeMap } from "@/hooks"; import { ISTKProps, IShape } from "@/types"; export const shapeSize = 50; @@ -44,6 +44,7 @@ const Shape: React.FC = forwardRef( }, ref: any ) => { + const shapes = useShapeMap({ options: consumer.options }); if (name === "RectangleHorizontal") { width ??= resizableRectangle.width; height ??= resizableRectangle.height; diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 46772a6..803be95 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -5,3 +5,4 @@ export { default as useSkipFirstRender } from "./skip-first-render"; export { default as useToast } from "./toast"; export * from "./events"; +export * from "./shapes"; diff --git a/src/hooks/shapes.ts b/src/hooks/shapes.ts new file mode 100644 index 0000000..fe24506 --- /dev/null +++ b/src/hooks/shapes.ts @@ -0,0 +1,27 @@ +import { useMemo } from "react"; +import { shapeList } from "@/components/controls/shapes/shape-list"; +import { ISTKProps } from "@/types"; + +export const getMergedShapes = (options: ISTKProps["options"]) => { + if (!options?.shapes) return shapeList; + if (options?.shapes.icons.length === 0) return shapeList; + if (options?.shapes.overrideDefaultIconset) return options.shapes.icons; + return [...shapeList, ...options.shapes.icons]; +}; + +export const useShapes = ({ options }: Pick) => { + return useMemo(() => { + return getMergedShapes(options); + }, [options?.shapes]); +}; + +export const useShapeMap = ({ options }: Pick) => { + return useMemo( + () => + getMergedShapes(options).reduce((acc, shape) => { + acc[shape.displayName] = shape; + return acc; + }, {}), + [options?.shapes] + ); +}; diff --git a/src/types/index.ts b/src/types/index.ts index 9cecc7b..7c5efd4 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -88,6 +88,10 @@ export interface ISTKProps { /** Disables category deletion if there are reserved seats falling under the category */ disableCategoryDeleteIfReserved?: boolean; disableSectionDelete?: boolean; + shapes?: { + icons: React.FC[]; + overrideDefaultIconset?: boolean; + }; }; plugins?: IPlugins; }