mirror of
https://github.com/ramvignesh-b/pi-ku.git
synced 2026-05-04 08:56:52 +00:00
feat: refactor ComposeCanvas to use reactive style props and use complete declarative approach for editor+toolbar
This commit is contained in:
@@ -41,7 +41,6 @@ export type CanvasTools = {
|
|||||||
getData: () => CanvasJSON;
|
getData: () => CanvasJSON;
|
||||||
getImages: () => { src: string; file: File }[];
|
getImages: () => { src: string; file: File }[];
|
||||||
loadData: (data: CanvasJSON) => Promise<void>;
|
loadData: (data: CanvasJSON) => Promise<void>;
|
||||||
setStyle: (style: CanvasStyle) => void;
|
|
||||||
getStyle: () => CanvasStyle;
|
getStyle: () => CanvasStyle;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -92,12 +91,14 @@ const DEFAULT_INIT_TEXT = "Take a deep breath...";
|
|||||||
interface ComposeCanvasProps {
|
interface ComposeCanvasProps {
|
||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
initialData?: CanvasJSON | null;
|
initialData?: CanvasJSON | null;
|
||||||
|
style?: CanvasStyle;
|
||||||
ref?: React.Ref<CanvasTools>;
|
ref?: React.Ref<CanvasTools>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ComposeCanvas({
|
export function ComposeCanvas({
|
||||||
readOnly = false,
|
readOnly = false,
|
||||||
initialData = null,
|
initialData = null,
|
||||||
|
style,
|
||||||
ref,
|
ref,
|
||||||
}: ComposeCanvasProps) {
|
}: ComposeCanvasProps) {
|
||||||
// wrapper is the parent div box
|
// wrapper is the parent div box
|
||||||
@@ -230,6 +231,15 @@ export function ComposeCanvas({
|
|||||||
[readOnly, syncViewport, focusTextbox],
|
[readOnly, syncViewport, focusTextbox],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (style && textboxRef.current) {
|
||||||
|
const textBox = textboxRef.current;
|
||||||
|
textBox.fontFamily = style.fontFamily || textBox.fontFamily;
|
||||||
|
textBox.fill = style.fontColor || textBox.fill;
|
||||||
|
syncViewport();
|
||||||
|
}
|
||||||
|
}, [style, syncViewport]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
let resizeObserver: ResizeObserver | null = null;
|
let resizeObserver: ResizeObserver | null = null;
|
||||||
@@ -356,16 +366,6 @@ export function ComposeCanvas({
|
|||||||
await loadContent(data);
|
await loadContent(data);
|
||||||
},
|
},
|
||||||
|
|
||||||
setStyle: (style: CanvasStyle) => {
|
|
||||||
const textBox = textboxRef.current;
|
|
||||||
if (!textBox) return;
|
|
||||||
|
|
||||||
textBox.fontFamily = style.fontFamily || textBox.fontFamily;
|
|
||||||
textBox.fill = style.fontColor || textBox.fill;
|
|
||||||
|
|
||||||
syncViewport();
|
|
||||||
},
|
|
||||||
|
|
||||||
getStyle: () => {
|
getStyle: () => {
|
||||||
const textBox = textboxRef.current;
|
const textBox = textboxRef.current;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { Modal } from "../ui/Modal";
|
|||||||
import type { CanvasStyle } from "./ComposeCanvas.tsx";
|
import type { CanvasStyle } from "./ComposeCanvas.tsx";
|
||||||
|
|
||||||
interface ToolBarProps {
|
interface ToolBarProps {
|
||||||
fileInputRef: React.RefObject<HTMLInputElement | null>;
|
onAddImage: () => void;
|
||||||
sealBtnClicked: boolean;
|
sealBtnClicked: boolean;
|
||||||
setSealBtnClicked: (v: boolean) => void;
|
setSealBtnClicked: (v: boolean) => void;
|
||||||
onSave: (status: "SEALED" | "DRAFT" | "VAULT", date?: Date) => Promise<void>;
|
onSave: (status: "SEALED" | "DRAFT" | "VAULT", date?: Date) => Promise<void>;
|
||||||
@@ -42,7 +42,7 @@ const FONT_COLORS: Map<string, string> = new Map([
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
export function ToolBar({
|
export function ToolBar({
|
||||||
fileInputRef,
|
onAddImage,
|
||||||
sealBtnClicked,
|
sealBtnClicked,
|
||||||
setSealBtnClicked,
|
setSealBtnClicked,
|
||||||
onSave,
|
onSave,
|
||||||
@@ -60,7 +60,7 @@ export function ToolBar({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-ghost btn-sm group"
|
className="btn btn-ghost btn-sm group"
|
||||||
onClick={() => fileInputRef.current?.click()}
|
onClick={onAddImage}
|
||||||
>
|
>
|
||||||
<ImageIcon size={18} weight="bold" />
|
<ImageIcon size={18} weight="bold" />
|
||||||
<span className="hidden md:inline group-hover:inline transition-all duration-1000">
|
<span className="hidden md:inline group-hover:inline transition-all duration-1000">
|
||||||
|
|||||||
@@ -476,22 +476,12 @@ export default function Editor() {
|
|||||||
|
|
||||||
{status === "DRAFT" ? (
|
{status === "DRAFT" ? (
|
||||||
<ToolBar
|
<ToolBar
|
||||||
fileInputRef={fileInputRef}
|
onAddImage={() => fileInputRef.current?.click()}
|
||||||
sealBtnClicked={sealBtnClicked}
|
sealBtnClicked={sealBtnClicked}
|
||||||
setSealBtnClicked={setSealBtnClicked}
|
setSealBtnClicked={setSealBtnClicked}
|
||||||
onSave={handleSave}
|
onSave={handleSave}
|
||||||
setConfirmModal={setConfirmModal}
|
setConfirmModal={setConfirmModal}
|
||||||
onFontChange={(style) => {
|
onFontChange={setCanvasFontStyle}
|
||||||
setCanvasFontStyle({
|
|
||||||
fontFamily: style.fontFamily,
|
|
||||||
fontColor: style.fontColor,
|
|
||||||
});
|
|
||||||
if (canvasRef?.current?.setStyle)
|
|
||||||
canvasRef.current.setStyle({
|
|
||||||
fontFamily: style.fontFamily,
|
|
||||||
fontColor: style.fontColor,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
latestFontStyle={canvasFontStyle}
|
latestFontStyle={canvasFontStyle}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -506,7 +496,11 @@ export default function Editor() {
|
|||||||
className="hidden"
|
className="hidden"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ComposeCanvas ref={canvasRef} readOnly={status !== "DRAFT"} />
|
<ComposeCanvas
|
||||||
|
ref={canvasRef}
|
||||||
|
readOnly={status !== "DRAFT"}
|
||||||
|
style={canvasFontStyle}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<LogModal
|
<LogModal
|
||||||
|
|||||||
Reference in New Issue
Block a user