diff --git a/docusaurus/docs/getting-started.md b/docusaurus/docs/getting-started.md index ef7da3006f0..fa5a11d7959 100644 --- a/docusaurus/docs/getting-started.md +++ b/docusaurus/docs/getting-started.md @@ -1,162 +1,303 @@ ---- -id: getting-started -title: Getting Started ---- +import React, { useRef, useState, useEffect } from "react"; + +// KidsDrawingApp.jsx +// Single-file React component. Uses Tailwind CSS for styling. +// Features: touch + mouse drawing, color palette, brush size, eraser, +// undo, clear, save PNG, simple stickers (emoji), background patterns. + +export default function KidsDrawingApp() { + const canvasRef = useRef(null); + const wrapperRef = useRef(null); + const [isDrawing, setIsDrawing] = useState(false); + const [color, setColor] = useState("#ff3b30"); + const [size, setSize] = useState(12); + const [isEraser, setIsEraser] = useState(false); + const [undoStack, setUndoStack] = useState([]); + const [maxUndo] = useState(20); + const [selectedSticker, setSelectedSticker] = useState(null); + const stickers = ["🌟", "🐢", "πŸš€", "🌈", "🍎", "🎈", "⚽️", "😊"]; + + // initialize canvas size + useEffect(() => { + resizeCanvas(); + window.addEventListener("resize", resizeCanvas); + const canvas = canvasRef.current; + // set initial white background + const ctx = canvas.getContext("2d"); + ctx.fillStyle = "#fff"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + pushUndo(); + return () => window.removeEventListener("resize", resizeCanvas); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + function resizeCanvas() { + const canvas = canvasRef.current; + if (!canvas || !wrapperRef.current) return; + const rect = wrapperRef.current.getBoundingClientRect(); + // preserve current content + const old = canvas.toDataURL(); + canvas.width = Math.max(600, Math.floor(rect.width)); + canvas.height = Math.max(400, Math.floor(rect.height)); + const img = new Image(); + img.onload = () => { + const ctx = canvas.getContext("2d"); + // fill white background then draw old content + ctx.fillStyle = "#fff"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(img, 0, 0); + }; + img.src = old; + } + + function getPointerPos(e) { + const canvas = canvasRef.current; + const rect = canvas.getBoundingClientRect(); + const isTouch = e.touches && e.touches[0]; + const clientX = isTouch ? e.touches[0].clientX : e.clientX; + const clientY = isTouch ? e.touches[0].clientY : e.clientY; + return { + x: Math.round((clientX - rect.left) * (canvas.width / rect.width)), + y: Math.round((clientY - rect.top) * (canvas.height / rect.height)), + }; + } + + function startDraw(e) { + if (selectedSticker) { + placeSticker(e); + return; + } + setIsDrawing(true); + const canvas = canvasRef.current; + const ctx = canvas.getContext("2d"); + const pos = getPointerPos(e); + ctx.beginPath(); + ctx.lineCap = "round"; + ctx.lineJoin = "round"; + ctx.lineWidth = size; + ctx.strokeStyle = isEraser ? "#fff" : color; + ctx.moveTo(pos.x, pos.y); + e.preventDefault(); + } + + function draw(e) { + if (!isDrawing) return; + const canvas = canvasRef.current; + const ctx = canvas.getContext("2d"); + const pos = getPointerPos(e); + ctx.lineTo(pos.x, pos.y); + ctx.stroke(); + e.preventDefault(); + } + + function endDraw() { + if (!isDrawing) return; + setIsDrawing(false); + const canvas = canvasRef.current; + const ctx = canvas.getContext("2d"); + ctx.closePath(); + pushUndo(); + } + + function pushUndo() { + const canvas = canvasRef.current; + if (!canvas) return; + const url = canvas.toDataURL("image/png"); + setUndoStack((s) => { + const next = [...s, url]; + if (next.length > maxUndo) next.shift(); + return next; + }); + } + + function undo() { + setUndoStack((s) => { + if (s.length <= 1) return s; // keep at least one state + const next = s.slice(0, -1); + const last = next[next.length - 1]; + const img = new Image(); + img.onload = () => { + const canvas = canvasRef.current; + const ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(img, 0, 0); + }; + img.src = last; + return next; + }); + } + + function clearCanvas() { + const canvas = canvasRef.current; + const ctx = canvas.getContext("2d"); + ctx.fillStyle = "#fff"; + ctx.fillRect(0, 0, canvas.width, canvas.height); + pushUndo(); + } + + function saveImage() { + const canvas = canvasRef.current; + const link = document.createElement("a"); + link.download = `kids-drawing-${new Date().toISOString()}.png`; + link.href = canvas.toDataURL("image/png"); + link.click(); + } + + function placeSticker(e) { + if (!selectedSticker) return; + const canvas = canvasRef.current; + const ctx = canvas.getContext("2d"); + const pos = getPointerPos(e); + // draw sticker as text in a big font + const fontSize = 64; + ctx.font = `${fontSize}px serif`; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillText(selectedSticker, pos.x, pos.y); + pushUndo(); + // auto-deselect sticker after placing + setSelectedSticker(null); + } + + function setToolColor(c) { + setColor(c); + setIsEraser(false); + } + + return ( +
+
+
+

Fun Drawing β€” Kids Edition

+
+ + + +
+
+ +
+ + +
+
+ +
+
Tool preview
+
+
+
{isEraser ? 'Eraser' : 'Brush'}
+
+
+
+ +
+
Made for little artists β€” friendly controls and big buttons.
+
Undo steps: {undoStack.length - 1}
+
+
+
+
+
+ ); +} -Create React App is an officially supported way to create single-page React -applications. It offers a modern build setup with no configuration. - -## Quick Start - -```sh -npx create-react-app my-app -cd my-app -npm start -``` - -> If you've previously installed `create-react-app` globally via `npm install -g create-react-app`, we recommend you uninstall the package using `npm uninstall -g create-react-app` or `yarn global remove create-react-app` to ensure that `npx` always uses the latest version. - -_([npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) comes with npm 5.2+ and higher, see [instructions for older npm versions](https://gist.github.com/gaearon/4064d3c23a77c74a3614c498a8bb1c5f))_ - -Then open [http://localhost:3000/](http://localhost:3000/) to see your app. - -When you’re ready to deploy to production, create a minified bundle with `npm run build`. - -

-npm start -

- -### Get Started Immediately - -You **don’t** need to install or configure tools like webpack or Babel. They are preconfigured and hidden so that you can focus on the code. - -Create a project, and you’re good to go. - -## Creating an App - -**You’ll need to have Node >= 14 on your local development machine** (but it’s not required on the server). You can use [nvm](https://github.com/creationix/nvm#installation) (macOS/Linux) or [nvm-windows](https://github.com/coreybutler/nvm-windows#node-version-manager-nvm-for-windows) to switch Node versions between different projects. - -To create a new app, you may choose one of the following methods: - -### npx - -```sh -npx create-react-app@latest my-app -``` - -_([npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) comes with npm 5.2+ and higher, see [instructions for older npm versions](https://gist.github.com/gaearon/4064d3c23a77c74a3614c498a8bb1c5f))_ - -### npm - -```sh -npm init react-app my-app -``` - -_`npm init ` is available in npm 6+_ - -### Yarn - -```sh -yarn create react-app my-app -``` - -_`yarn create` is available in Yarn 0.25+_ - -### Selecting a template - -You can now optionally start a new app from a template by appending `--template [template-name]` to the creation command. - -If you don't select a template, we'll create your project with our base template. - -Templates are always named in the format `cra-template-[template-name]`, however you only need to provide the `[template-name]` to the creation command. - -```sh -npx create-react-app my-app --template [template-name] -``` - -> You can find a list of available templates by searching for ["cra-template-\*"](https://www.npmjs.com/search?q=cra-template-*) on npm. - -Our [Custom Templates](custom-templates.md) documentation describes how you can build your own template. - -#### Creating a TypeScript app - -You can start a new TypeScript app using templates. To use our provided TypeScript template, append `--template typescript` to the creation command. - -```sh -npx create-react-app my-app --template typescript -``` - -If you already have a project and would like to add TypeScript, see our [Adding TypeScript](adding-typescript.md) documentation. - -### Selecting a package manager - -When you create a new app, the CLI will use [npm](https://docs.npmjs.com) or [Yarn](https://yarnpkg.com/) to install dependencies, depending on which tool you use to run `create-react-app`. For example: - -```sh -# Run this to use npm -npx create-react-app my-app -# Or run this to use yarn -yarn create react-app my-app -``` - -## Output - -Running any of these commands will create a directory called `my-app` inside the current folder. Inside that directory, it will generate the initial project structure and install the transitive dependencies: - -``` -my-app -β”œβ”€β”€ README.md -β”œβ”€β”€ node_modules -β”œβ”€β”€ package.json -β”œβ”€β”€ .gitignore -β”œβ”€β”€ public -β”‚ β”œβ”€β”€ favicon.ico -β”‚ β”œβ”€β”€ index.html -β”‚ β”œβ”€β”€ logo192.png -β”‚ β”œβ”€β”€ logo512.png -β”‚ β”œβ”€β”€ manifest.json -β”‚ └── robots.txt -└── src - β”œβ”€β”€ App.css - β”œβ”€β”€ App.js - β”œβ”€β”€ App.test.js - β”œβ”€β”€ index.css - β”œβ”€β”€ index.js - β”œβ”€β”€ logo.svg - β”œβ”€β”€ serviceWorker.js - └── setupTests.js -``` - -No configuration or complicated folder structures, only the files you need to build your app. Once the installation is done, you can open your project folder: - -```sh -cd my-app -``` - -## Scripts - -Inside the newly created project, you can run some built-in commands: - -### `npm start` or `yarn start` - -Runs the app in development mode. Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will automatically reload if you make changes to the code. You will see the build errors and lint warnings in the console. - -

-Build errors -

- -### `npm test` or `yarn test` - -Runs the test watcher in an interactive mode. By default, runs tests related to files changed since the last commit. - -[Read more about testing](running-tests.md). - -### `npm run build` or `yarn build` - -Builds the app for production to the `build` folder. It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes. - -Your app is ready to be deployed.