Skip to content

Instantly share code, notes, and snippets.

@ljmotta
Last active October 13, 2020 20:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ljmotta/44baea817175649b5c02ab0f8e3c5b8f to your computer and use it in GitHub Desktop.
Save ljmotta/44baea817175649b5c02ab0f8e3c5b8f to your computer and use it in GitHub Desktop.
Base64Png Editor with Patternfly and Invert Tweaker
import * as React from "react";
import { useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
import { EditorApi, KogitoEditorEnvelopeContextType } from "@kogito-tooling/editor/dist/api";
import { Nav, NavItem, NavList, Page, Switch, Title } from "@patternfly/react-core";
import { DEFAULT_RECT } from "@kogito-tooling/guided-tour/dist/api";
import { Base64PngEdit, Base64PngStateControl } from "./Base64PngStateControl";
import "./styles.scss";
interface Props {
envelopeContext: KogitoEditorEnvelopeContextType;
}
export const Base64PngEditor = React.forwardRef<EditorApi, Props>((props, forwardedRef) => {
const [originalContent, setOriginalContent] = useState("");
const [editorContent, setEditorContent] = useState("");
const imageRef = useRef<HTMLImageElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
props.envelopeContext.channelApi.notifications.receive_ready();
}, []);
const getContent = useCallback(() => {
return editorContent;
}, [editorContent]);
const getPreview = useCallback(() => {
const width = imageRef.current!.width;
const height = imageRef.current!.height;
return `
<svg version="1.1" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="${width}" height="${height}" xlink:href="data:image/png;base64,${editorContent}" />
</svg>`;
}, [editorContent]);
const setContent = useCallback((path: string, content: string) => {
setOriginalContent(content);
}, []);
useImperativeHandle(forwardedRef, () => {
return {
getContent: () => Promise.resolve(getContent()),
getPreview: () => Promise.resolve(getPreview()),
setContent: (path: string, content: string) => Promise.resolve(setContent(path, content)),
undo: () => Promise.resolve(),
redo: () => Promise.resolve(),
getElementPosition: (selector: string) => Promise.resolve(DEFAULT_RECT),
};
});
const [disabled, setDisabled] = useState(true);
const [invert, setInvert] = useState("0");
const tweakInvert = useCallback((value: string) => {
setInvert(value);
props.envelopeContext.channelApi.notifications.receive_newEdit({ id: new Date().getTime().toString() });
}, [invert]);
useEffect(() => {
const ctx = canvasRef.current?.getContext("2d")!;
ctx.filter = `invert(${invert}%)`;
ctx.drawImage(imageRef.current!, 0, 0);
setEditorContent(canvasRef.current!.toDataURL().split(",")[1]);
}, [invert]);
useEffect(() => {
const ctx = canvasRef.current?.getContext("2d")!;
canvasRef.current!.width = 0;
canvasRef.current!.height = 0;
imageRef.current!.onload = () => {
canvasRef.current!.width = imageRef.current!.width;
canvasRef.current!.height = imageRef.current!.height;
ctx.drawImage(imageRef.current!, 0, 0);
setEditorContent(canvasRef.current!.toDataURL().split(",")[1]);
setDisabled(false);
};
return () => {
imageRef.current!.onload = null;
};
}, []);
return (
<Page className={"base64png-editor--page"}>
<div className={"base64png-editor--main"}>
<div className={"base64png-editor--viewport"}>
<img
ref={imageRef}
className={"base64png-editor--image"}
src={`data:image/png;base64,${originalContent}`}
alt={"Original"}
/>
{disabled && (
<EmptyState>
<EmptyStateIcon icon={CubesIcon} />
<Title headingLevel="h5" size="4xl">
Empty image
</Title>
</EmptyState>
)}
<canvas ref={canvasRef} className={"base64png-editor--canvas"} />
</div>
<div className={"base64png-editor--tweaks"}>
<Nav aria-label="Image tweaker">
<NavList>
<NavItem itemId={0}>
<div className={"base64png-editor--tweaks-nav-item"}>
<p>Invert</p>
<Switch
id="invert-switch"
isDisabled={disabled}
isChecked={invert === "100"}
onChange={(value) => tweakInvert(value ? "100" : "0")}
/>
</div>
</NavItem>
</NavList>
</Nav>
</div>
</div>
</Page>
);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment