Skip to content

Commit

Permalink
#144 - Added Copy/Paste Button
Browse files Browse the repository at this point in the history
- Added SVGs for Copy and Paste buttons
- Created individual components to handle SVGs.
- Created copy-pasted-button
  • Loading branch information
jsanzdev committed Aug 20, 2024
1 parent 5cb17a6 commit 92e7110
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 4 deletions.
1 change: 1 addition & 0 deletions public/icons/copy.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/icons/paste.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/common/components/icons/copy-icon.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const CopyIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 256 256"
>
<path
fill="currentColor"
d="M216 32H88a8 8 0 0 0-8 8v40H40a8 8 0 0 0-8 8v128a8 8 0 0 0 8 8h128a8 8 0 0 0 8-8v-40h40a8 8 0 0 0 8-8V40a8 8 0 0 0-8-8m-56 176H48V96h112Zm48-48h-32V88a8 8 0 0 0-8-8H96V48h112Z"
/>
</svg>
);
};
2 changes: 2 additions & 0 deletions src/common/components/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export * from './send-to-back-icon.component';
export * from './linkedin-icon.component';
export * from './x-icon.component';
export * from './quickmock-logo.component';
export * from './copy-icon.component';
export * from './paste-icon.component';
15 changes: 15 additions & 0 deletions src/common/components/icons/paste-icon.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const PasteIcon = () => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 256 256"
>
<path
fill="currentColor"
d="M200 32h-36.26a47.92 47.92 0 0 0-71.48 0H56a16 16 0 0 0-16 16v168a16 16 0 0 0 16 16h144a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16m-72 0a32 32 0 0 1 32 32H96a32 32 0 0 1 32-32m72 184H56V48h26.75A47.9 47.9 0 0 0 80 64v8a8 8 0 0 0 8 8h80a8 8 0 0 0 8-8v-8a47.9 47.9 0 0 0-2.75-16H200Z"
/>
</svg>
);
};
4 changes: 2 additions & 2 deletions src/pods/canvas/canvas.pod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@ export const CanvasPod = () => {
updateShapePosition(id, { x, y });
};

const { copyShape, pasteShapeFromClipboard } = useClipboard();
const { copyShapeToClipboard, pasteShapeFromClipboard } = useClipboard();

useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
const isCtrlOrCmdPressed = e.ctrlKey || e.metaKey;

if (isCtrlOrCmdPressed && e.key === 'c') {
copyShape();
copyShapeToClipboard();
}
if (isCtrlOrCmdPressed && e.key === 'v') {
pasteShapeFromClipboard();
Expand Down
4 changes: 2 additions & 2 deletions src/pods/canvas/use-clipboard.hook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const useClipboard = () => {
const clipboardShapeRef = useRef<ShapeModel | null>(null);
const copyCount = useRef(1);

const copyShape = () => {
const copyShapeToClipboard = () => {
const selectedShape = findShapeById(selectionInfo.selectedShapeId, shapes);
if (selectedShape) {
clipboardShapeRef.current = cloneShape(selectedShape);
Expand All @@ -31,5 +31,5 @@ export const useClipboard = () => {
}
};

return { copyShape, pasteShapeFromClipboard };
return { copyShapeToClipboard, pasteShapeFromClipboard };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { CopyIcon, PasteIcon } from '@/common/components/icons';
import { ToolbarButton } from '../toolbar-button';
import classes from '@/pods/toolbar/toolbar.pod.module.css';
import { useCanvasContext } from '@/core/providers';
import { SHORTCUTS } from '../../shortcut/shortcut.const';
import { useClipboard } from '@/pods/canvas/use-clipboard.hook';

export const CopyButton = () => {
const { selectionInfo } = useCanvasContext();
const { copyShapeToClipboard, pasteShapeFromClipboard } = useClipboard();

const handleCopyClick = () => {
if (selectionInfo.selectedShapeId) {
copyShapeToClipboard();
}
};

const handlePasteClick = () => {
pasteShapeFromClipboard();
};

return (
<div>
<ul className={classes.buttonGroup}>
<li>
<ToolbarButton
icon={<CopyIcon />}
label="Copy"
onClick={handleCopyClick}
className={classes.button}
disabled={!selectionInfo.selectedShapeId}
shortcutOptions={SHORTCUTS.copy}
/>
</li>
<li>
<ToolbarButton
icon={<PasteIcon />}
label="Paste"
onClick={handlePasteClick}
className={classes.button}
shortcutOptions={SHORTCUTS.paste}
/>
</li>
</ul>
</div>
);
};
1 change: 1 addition & 0 deletions src/pods/toolbar/components/copy-paste-button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './copy-paste-button';
12 changes: 12 additions & 0 deletions src/pods/toolbar/shortcut/shortcut.const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,16 @@ export const SHORTCUTS: Shortcut = {
targetKey: ['Backspace'],
targetKeyLabel: 'Backspace',
},
copy: {
description: 'Copy',
id: 'copy-button-shortcut',
targetKey: ['Ctrl', 'C'],
targetKeyLabel: 'Ctrl + C',
},
paste: {
description: 'Paste',
id: 'paste-button-shortcut',
targetKey: ['Ctrl', 'V'],
targetKeyLabel: 'Ctrl + V',
},
};
5 changes: 5 additions & 0 deletions src/pods/toolbar/toolbar.pod.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { DeleteButton } from './components/delete-button';
import { CopyButton } from './components/copy-paste-button';
import { PasteButton } from './components/paste-button';
import {
ZoomInButton,
ZoomOutButton,
Expand Down Expand Up @@ -36,6 +38,9 @@ export const ToolbarPod: React.FC = () => {
<li>
<RedoButton />
</li>
<li>
<CopyButton />
</li>
<li>
<DeleteButton />
</li>
Expand Down

0 comments on commit 92e7110

Please sign in to comment.