{"id":20879922,"url":"https://github.com/mirayatech/ninjasketch","last_synced_at":"2025-04-05T22:07:05.194Z","repository":{"id":214896875,"uuid":"737608315","full_name":"mirayatech/NinjaSketch","owner":"mirayatech","description":"🥷🏽 An Excalidraw clone built with React and TypeScript.","archived":false,"fork":false,"pushed_at":"2024-04-12T13:12:03.000Z","size":351,"stargazers_count":391,"open_issues_count":1,"forks_count":54,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T21:04:08.975Z","etag":null,"topics":["canvas","cypress","drawing","e2e","e2e-tests","excalidraw","excalidraw-clone","javascript","notes","react","testing","testing-library","typescript","unit-testing","unittest","vite","vitest"],"latest_commit_sha":null,"homepage":"https://ninja-sketch.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mirayatech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-31T18:15:02.000Z","updated_at":"2025-03-28T13:58:19.000Z","dependencies_parsed_at":"2024-01-18T11:45:14.869Z","dependency_job_id":"6d69b658-c7ac-4bc1-bc7e-e0956f8b1827","html_url":"https://github.com/mirayatech/NinjaSketch","commit_stats":null,"previous_names":["mirayatech/ninjasketch"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirayatech%2FNinjaSketch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirayatech%2FNinjaSketch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirayatech%2FNinjaSketch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirayatech%2FNinjaSketch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mirayatech","download_url":"https://codeload.github.com/mirayatech/NinjaSketch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247406089,"owners_count":20933803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["canvas","cypress","drawing","e2e","e2e-tests","excalidraw","excalidraw-clone","javascript","notes","react","testing","testing-library","typescript","unit-testing","unittest","vite","vitest"],"created_at":"2024-11-18T07:18:19.773Z","updated_at":"2025-04-05T22:07:05.168Z","avatar_url":"https://github.com/mirayatech.png","language":"TypeScript","readme":"# 🥷🏽 NinjaSketch\n\nAn Excalidraw clone with React and TypeScript. Rough.js is used for the sketchy, hand-drawn style. I built the side project for learning purposes. The app is not responsive. I mainly focused on the functionalities since I already have plenty of projects that are responsive.\n\n## 📦 Technologies\n\n- `Vite`\n- `React.js`\n- `TypeScript`\n- `Rough.js`\n- `CSS`\n- `Vitest`\n- `Cypress` \n- `Testing Library`\n\n## 🦄 Features\n\nHere's what you can do with NinjaSketch:\n\n- **Choose a Tool**: You have pencils, lines, rectangles, and text tools. Pick one and start creating.\n\n- **Draw and Move**: Click and drag on the canvas to draw. To move something, select it and drag it to a new spot. Also, resize elements by dragging the corners. Resizing only works on rectangles or lines.\n\n- **Edit Text**: Click on the canvas and start typing to add text to your drawings. You can also edit existing text.\n\n- **Zoom**: Use Ctrl + Scroll or click on the buttons to zoom in for detail or out to see the whole picture.\n\n- **Pan**: Hold the Space bar and drag or use the middle mouse button to move around the whiteboard canvas.\n\n### 🎯 Keyboard Shortcuts:\n\nSpeed up your work with these shortcuts:\n\n- **Canvas Navigation**: Press the Space bar and drag or use the middle mouse button.\n- **Undo**: Ctrl + Z.\n- **Redo**: Ctrl + Y or Ctrl + Shift + Z.\n- **Zoom In**: Ctrl + Plus.\n- **Zoom Out**: Ctrl + Minus.\n\n## 👩🏽‍🍳 The Process\n\nI started by rendering a canvas with rough.js to create the base for all the drawings. Then, I focused on drawing on the canvas, allowing users to make lines, rectangles, and other shapes.\n\nNext, I made sure users could move elements around. This was important for adjusting drawings. After that, I added the ability to resize elements to give more control over the shapes.\n\nTo make sure mistakes could be fixed, I implemented undo and redo features. I also added freehand drawing for a more natural sketching experience and a text tool to label or note on the canvas.\n\nTo navigate larger drawings, I put in pan and zoom tools. With everything functioning, I designed the whole UI to make it user-friendly and appealing.\n\nFinally, I added testing with Cypress and Testing Library. I conducted end-to-end tests on drawing and manipulating text, lines, rectangles, and freehand drawings to make sure everything worked smoothly.\n\nAlong the way, while building everything, I took notes on what I've learned so I don't miss out on it. I also documented the behind-the-scenes processes every time a feature was added.\n\nThis way, I understood what I've built. The funny thing is, as soon as I started to document what happened behind the scenes and the features I've added, it made me realize that we fully understand something once we've actually taken a step back, thought about it, and documented what we've done. I think this is a good practice to follow when learning something new.\n\n## 📚 What I Learned\n\nDuring this project, I've picked up important skills and a better understanding of complex ideas, which improved my logical thinking.\n\n### 🧠 `useHistory` Hook:\n\n- **Logical Thinking**: Creating the `useHistory` hook taught me to think about how to manage saving, undoing, and redoing actions. I had to really understand how to track changes and plan out user actions.\n\n### 📏 Coordinates and Measurements:\n\n- **Accuracy**: I've become better at working with shapes and points, like knowing if a point is inside a shape. This required careful measurements.\n- **Math Skills**: I used math functions to make sure everything was placed correctly and to calculate distances.\n\n### 🎨 Discovering Rough.js:\n\n- **New Tools**: I found out about Rough.js, which lets me make graphics look hand-drawn. This was a new and exciting tool for me.\n\n### 🔍 Deep Dive into Functions:\n\n- **Complex Functions**: I spent time understanding the `getSvgPathFromStroke` function, which turns drawing movements into smooth paths.\n\n### ✏️ Managing Points and Drawing:\n\n- **Working with Points**: I learned how to collect and use points from drawings, which involved understanding and managing data to reflect what the user does.\n\n### 🎣 React Hooks and Rendering:\n\n- **New Knowledge**: I learned about `useLayoutEffect`, which helps make sure changes are done before the screen updates. This was useful for certain drawing functions.\n\n### 🎡 Advanced Event Handling:\n\n- **User Interaction**: I worked with the wheel event listener, which allowed me to add zooming and panning features. This made the app more interactive and user-friendly.\n\n### 📈 Overall Growth:\n\nEach part of this project helped me understand more about building apps, managing complex information, and improving user experience. It was more than just making a tool. It was about solving problems, learning new things, and improving my skills for future work.\n\n## 💭 How can it be improved?\n\n- Add more colors to the color picker.\n- Add more tools like a circle, eraser, and more.\n- Add more shapes like triangles, stars, and more.\n- Add more keyboard shortcuts to make things faster.\n- Add more themes like dark mode, light mode, and more.\n- Add more text options like font size, font color, and more.\n- Instead of have any in two places, create a type for the rough.js elements.\n\n## 🚦 Running the Project\n\nTo run the project in your local environment, follow these steps:\n\n1. Clone the repository to your local machine.\n2. Run `npm install` or `yarn` in the project directory to install the required dependencies.\n3. Run `npm run start` or `yarn start` to get the project started.\n4. Open [http://localhost:5173](http://localhost:5173) (or the address shown in your console) in your web browser to view the app.\n\n## 🍿 Video\n\nhttps://github.com/mirayatech/NinjaSketch/assets/71933266/6a16c9e5-6380-4317-96e7-d132768f7b40\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirayatech%2Fninjasketch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmirayatech%2Fninjasketch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirayatech%2Fninjasketch/lists"}