2020-10-19 17:14:28 +03:00
|
|
|
import clsx from "clsx";
|
2020-12-27 18:26:30 +02:00
|
|
|
import oc from "open-color";
|
2021-10-14 22:56:51 +05:30
|
|
|
import { useEffect, useRef, useState } from "react";
|
2020-07-10 02:20:23 -07:00
|
|
|
import { close } from "../components/icons";
|
2020-12-27 18:26:30 +02:00
|
|
|
import { MIME_TYPES } from "../constants";
|
2020-07-10 02:20:23 -07:00
|
|
|
import { t } from "../i18n";
|
2021-04-08 19:54:50 +02:00
|
|
|
import { useIsMobile } from "../components/App";
|
2020-12-27 18:26:30 +02:00
|
|
|
import { exportToSvg } from "../scene/export";
|
2021-10-21 22:05:48 +02:00
|
|
|
import { BinaryFiles, LibraryItem } from "../types";
|
2020-12-27 18:26:30 +02:00
|
|
|
import "./LibraryUnit.scss";
|
2020-07-10 02:20:23 -07:00
|
|
|
|
|
|
|
// fa-plus
|
|
|
|
const PLUS_ICON = (
|
|
|
|
<svg viewBox="0 0 1792 1792">
|
2020-08-13 04:35:31 -07:00
|
|
|
<path
|
|
|
|
fill="currentColor"
|
|
|
|
d="M1600 736v192q0 40-28 68t-68 28h-416v416q0 40-28 68t-68 28h-192q-40 0-68-28t-28-68v-416h-416q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h416v-416q0-40 28-68t68-28h192q40 0 68 28t28 68v416h416q40 0 68 28t28 68z"
|
|
|
|
/>
|
2020-07-10 02:20:23 -07:00
|
|
|
</svg>
|
|
|
|
);
|
|
|
|
|
|
|
|
export const LibraryUnit = ({
|
|
|
|
elements,
|
2021-10-21 22:05:48 +02:00
|
|
|
files,
|
2020-07-10 02:20:23 -07:00
|
|
|
pendingElements,
|
|
|
|
onRemoveFromLibrary,
|
|
|
|
onClick,
|
|
|
|
}: {
|
2020-07-27 15:29:19 +03:00
|
|
|
elements?: LibraryItem;
|
2021-10-21 22:05:48 +02:00
|
|
|
files: BinaryFiles;
|
2020-07-27 15:29:19 +03:00
|
|
|
pendingElements?: LibraryItem;
|
2020-07-10 02:20:23 -07:00
|
|
|
onRemoveFromLibrary: () => void;
|
|
|
|
onClick: () => void;
|
|
|
|
}) => {
|
|
|
|
const ref = useRef<HTMLDivElement | null>(null);
|
|
|
|
useEffect(() => {
|
2021-07-03 02:07:01 +05:30
|
|
|
(async () => {
|
2021-10-21 22:05:48 +02:00
|
|
|
const elementsToRender = elements || pendingElements;
|
|
|
|
if (!elementsToRender) {
|
|
|
|
return;
|
2020-07-10 02:20:23 -07:00
|
|
|
}
|
2021-10-21 22:05:48 +02:00
|
|
|
const svg = await exportToSvg(
|
|
|
|
elementsToRender,
|
|
|
|
{
|
|
|
|
exportBackground: false,
|
|
|
|
viewBackgroundColor: oc.white,
|
|
|
|
},
|
|
|
|
files,
|
|
|
|
);
|
|
|
|
if (ref.current) {
|
|
|
|
ref.current.innerHTML = svg.outerHTML;
|
2021-07-03 02:07:01 +05:30
|
|
|
}
|
2021-10-21 22:05:48 +02:00
|
|
|
})();
|
|
|
|
}, [elements, pendingElements, files]);
|
2020-07-10 02:20:23 -07:00
|
|
|
|
|
|
|
const [isHovered, setIsHovered] = useState(false);
|
2020-07-20 00:12:56 +03:00
|
|
|
const isMobile = useIsMobile();
|
2020-07-10 02:20:23 -07:00
|
|
|
|
2020-07-20 00:12:56 +03:00
|
|
|
const adder = (isHovered || isMobile) && pendingElements && (
|
2020-07-10 02:20:23 -07:00
|
|
|
<div className="library-unit__adder">{PLUS_ICON}</div>
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
2020-10-19 17:14:28 +03:00
|
|
|
className={clsx("library-unit", {
|
|
|
|
"library-unit__active": elements || pendingElements,
|
|
|
|
})}
|
2020-07-10 02:20:23 -07:00
|
|
|
onMouseEnter={() => setIsHovered(true)}
|
|
|
|
onMouseLeave={() => setIsHovered(false)}
|
|
|
|
>
|
|
|
|
<div
|
2020-10-19 17:14:28 +03:00
|
|
|
className={clsx("library-unit__dragger", {
|
|
|
|
"library-unit__pulse": !!pendingElements,
|
|
|
|
})}
|
2020-07-10 02:20:23 -07:00
|
|
|
ref={ref}
|
|
|
|
draggable={!!elements}
|
|
|
|
onClick={!!elements || !!pendingElements ? onClick : undefined}
|
|
|
|
onDragStart={(event) => {
|
|
|
|
setIsHovered(false);
|
|
|
|
event.dataTransfer.setData(
|
2020-10-13 14:47:07 +02:00
|
|
|
MIME_TYPES.excalidrawlib,
|
2020-07-10 02:20:23 -07:00
|
|
|
JSON.stringify(elements),
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
{adder}
|
2020-07-20 00:12:56 +03:00
|
|
|
{elements && (isHovered || isMobile) && (
|
2020-07-10 02:20:23 -07:00
|
|
|
<button
|
|
|
|
className="library-unit__removeFromLibrary"
|
|
|
|
aria-label={t("labels.removeFromLibrary")}
|
|
|
|
onClick={onRemoveFromLibrary}
|
|
|
|
>
|
|
|
|
{close}
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|