From d29419bcf7ab41887b87f601a4ecb672db7fe9bf Mon Sep 17 00:00:00 2001 From: Grant Date: Thu, 15 Feb 2024 19:44:12 -0700 Subject: [PATCH] replace client with client-next --- packages/client-next/package.json | 52 -- packages/client-next/src/lib/canvas.ts | 272 -------- packages/client-next/src/style.scss | 146 ----- packages/client-next/tsconfig.json | 3 - packages/{client-next => client}/.nvmrc | 0 packages/client/gulpfile.js | 26 - packages/client/package.json | 58 +- .../{client-next => client}/postcss.config.js | 0 packages/client/public/index.html | 64 -- .../{client-next => client}/src/board.scss | 0 .../src/components/App.tsx | 0 .../src/components/CanvasMeta.tsx | 0 .../src/components/CanvasWrapper.tsx | 0 .../src/components/Header.tsx | 0 .../src/components/Pallete.scss | 0 .../src/components/Pallete.tsx | 0 .../src/contexts/AppContext.tsx | 0 .../{client-next => client}/src/index.html | 0 packages/client/src/index.ts | 11 - .../{client-next => client}/src/index.tsx | 0 packages/client/src/lib/auth.ts | 32 - packages/client/src/lib/canvas.ts | 618 +++++++----------- packages/client/src/lib/net.ts | 74 --- .../src/lib/network.ts | 0 packages/client/src/lib/pallete.ts | 80 --- .../{client-next => client}/src/lib/routes.ts | 0 packages/client/src/style.scss | 103 ++- packages/{client-next => client}/src/types.ts | 0 .../{client-next => client}/src/vite-env.d.ts | 0 .../tailwind.config.js | 0 packages/client/tsconfig.json | 5 +- .../{client-next => client}/vite.config.js | 0 packages/client/webpack.config.js | 22 - 33 files changed, 328 insertions(+), 1238 deletions(-) delete mode 100644 packages/client-next/package.json delete mode 100644 packages/client-next/src/lib/canvas.ts delete mode 100644 packages/client-next/src/style.scss delete mode 100644 packages/client-next/tsconfig.json rename packages/{client-next => client}/.nvmrc (100%) delete mode 100644 packages/client/gulpfile.js rename packages/{client-next => client}/postcss.config.js (100%) delete mode 100644 packages/client/public/index.html rename packages/{client-next => client}/src/board.scss (100%) rename packages/{client-next => client}/src/components/App.tsx (100%) rename packages/{client-next => client}/src/components/CanvasMeta.tsx (100%) rename packages/{client-next => client}/src/components/CanvasWrapper.tsx (100%) rename packages/{client-next => client}/src/components/Header.tsx (100%) rename packages/{client-next => client}/src/components/Pallete.scss (100%) rename packages/{client-next => client}/src/components/Pallete.tsx (100%) rename packages/{client-next => client}/src/contexts/AppContext.tsx (100%) rename packages/{client-next => client}/src/index.html (100%) delete mode 100644 packages/client/src/index.ts rename packages/{client-next => client}/src/index.tsx (100%) delete mode 100644 packages/client/src/lib/auth.ts delete mode 100644 packages/client/src/lib/net.ts rename packages/{client-next => client}/src/lib/network.ts (100%) delete mode 100644 packages/client/src/lib/pallete.ts rename packages/{client-next => client}/src/lib/routes.ts (100%) rename packages/{client-next => client}/src/types.ts (100%) rename packages/{client-next => client}/src/vite-env.d.ts (100%) rename packages/{client-next => client}/tailwind.config.js (100%) rename packages/{client-next => client}/vite.config.js (100%) delete mode 100644 packages/client/webpack.config.js diff --git a/packages/client-next/package.json b/packages/client-next/package.json deleted file mode 100644 index 6ae1cba..0000000 --- a/packages/client-next/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "client", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "build": "vite build", - "dev": "vite serve", - "preview": "vite preview", - "lint": "eslint ." - }, - "type": "module", - "keywords": [], - "author": "", - "license": "ISC", - "eslintConfig": { - "extends": "react-app" - }, - "dependencies": { - "@fortawesome/fontawesome-svg-core": "^6.5.1", - "@fortawesome/free-solid-svg-icons": "^6.5.1", - "@fortawesome/react-fontawesome": "^0.2.0", - "@nextui-org/react": "^2.2.9", - "@sc07-canvas/lib": "^1.0.0", - "eventemitter3": "^5.0.1", - "framer-motion": "^11.0.5", - "lodash.throttle": "^4.1.1", - "prop-types": "^15.8.1", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-zoom-pan-pinch": "^3.4.1", - "socket.io-client": "^4.7.4" - }, - "devDependencies": { - "@tsconfig/vite-react": "^3.0.0", - "@types/lodash.throttle": "^4.1.9", - "@types/react": "^18.2.48", - "@types/react-dom": "^18.2.18", - "@types/socket.io-client": "^3.0.0", - "@vitejs/plugin-react": "^4.2.1", - "autoprefixer": "^10.4.17", - "eslint": "^8.56.0", - "eslint-config-react-app": "^7.0.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "postcss": "^8.4.35", - "sass": "^1.70.0", - "tailwindcss": "^3.4.1", - "vite": "^5.1.1", - "vite-plugin-simple-html": "^0.1.2" - } -} diff --git a/packages/client-next/src/lib/canvas.ts b/packages/client-next/src/lib/canvas.ts deleted file mode 100644 index d8a4add..0000000 --- a/packages/client-next/src/lib/canvas.ts +++ /dev/null @@ -1,272 +0,0 @@ -import EventEmitter from "eventemitter3"; -import { ClientConfig, IPalleteContext, IPosition, Pixel } from "../types"; -import Network from "./network"; -import { - ClickEvent, - HoverEvent, - PanZoom, -} from "@sc07-canvas/lib/src/renderer/PanZoom"; - -interface CanvasEvents { - /** - * Cursor canvas position - * (-1, -1) is not on canvas - * @param position Canvas position - * @returns - */ - cursorPos: (position: IPosition) => void; -} - -export class Canvas extends EventEmitter { - static instance: Canvas | undefined; - - private _destroy = false; - private config: ClientConfig; - private canvas: HTMLCanvasElement; - private PanZoom: PanZoom; - private ctx: CanvasRenderingContext2D; - - private cursor = { x: -1, y: -1 }; - private pixels: { - [x_y: string]: { color: number; type: "full" | "pending" }; - } = {}; - private lastPlace: number | undefined; - - constructor( - config: ClientConfig, - canvas: HTMLCanvasElement, - PanZoom: PanZoom - ) { - super(); - Canvas.instance = this; - - this.config = config; - this.canvas = canvas; - this.PanZoom = PanZoom; - this.ctx = canvas.getContext("2d")!; - - canvas.width = config.canvas.size[0]; - canvas.height = config.canvas.size[1]; - - this.PanZoom.addListener("hover", this.handleMouseMove.bind(this)); - this.PanZoom.addListener("click", this.handleMouseDown.bind(this)); - - Network.waitFor("canvas").then(([pixels]) => this.handleBatch(pixels)); - - this.draw(); - } - - destroy() { - this._destroy = true; - - this.PanZoom.removeListener("hover", this.handleMouseMove.bind(this)); - this.PanZoom.removeListener("click", this.handleMouseDown.bind(this)); - - Network.off("canvas", this.handleBatch.bind(this)); - } - - handleMouseDown(e: ClickEvent) { - const [x, y] = this.screenToPos(e.clientX, e.clientY); - this.place(x, y); - } - - handleMouseMove(e: HoverEvent) { - const canvasRect = this.canvas.getBoundingClientRect(); - if ( - canvasRect.left <= e.clientX && - canvasRect.right >= e.clientX && - canvasRect.top <= e.clientY && - canvasRect.bottom >= e.clientY - ) { - const [x, y] = this.screenToPos(e.clientX, e.clientY); - this.cursor.x = x; - this.cursor.y = y; - } else { - this.cursor.x = -1; - this.cursor.y = -1; - } - - this.emit("cursorPos", this.cursor); - } - - handleBatch(pixels: string[]) { - pixels.forEach((hex, index) => { - const x = index % this.config.canvas.size[0]; - const y = index / this.config.canvas.size[1]; - const color = this.Pallete.getColorFromHex(hex); - - this.pixels[x + "_" + y] = { - color: color ? color.id : -1, - type: "full", - }; - }); - } - - handlePixel({ x, y, color }: Pixel) { - this.pixels[x + "_" + y] = { - color, - type: "full", - }; - } - - palleteCtx: IPalleteContext = {}; - Pallete = { - getColor: (colorId: number) => { - return this.config.pallete.colors.find((c) => c.id === colorId); - }, - - getSelectedColor: () => { - if (!this.palleteCtx.color) return undefined; - - return this.Pallete.getColor(this.palleteCtx.color); - }, - - getColorFromHex: (hex: string) => { - return this.config.pallete.colors.find((c) => c.hex === hex); - }, - }; - - updatePallete(pallete: IPalleteContext) { - this.palleteCtx = pallete; - } - - place(x: number, y: number) { - if (!this.Pallete.getSelectedColor()) return; - - if (this.lastPlace) { - if (this.lastPlace + this.config.pallete.pixel_cooldown > Date.now()) { - console.log("cannot place; cooldown"); - return; - } - } - - this.lastPlace = Date.now(); - - Network.socket - .emitWithAck("place", { - x, - y, - color: this.Pallete.getSelectedColor()!.id, - }) - .then((ack) => { - if (ack.success) { - this.handlePixel(ack.data); - } else { - // TODO: handle undo pixel - alert("error: " + ack.error); - } - }); - } - - panZoomTransformToCanvas() { - const { x, y, scale: zoom } = this.PanZoom.transform; - const rect = this.canvas.getBoundingClientRect(); - - let canvasX = 0; - let canvasY = 0; - - if (this.PanZoom.flags.useZoom) { - // css zoom doesn't change the bounding client rect - // therefore dividing by zoom doesn't return the correct output - canvasX = this.canvas.width - (x + rect.width / 2); - canvasY = this.canvas.height - (y + rect.height / 2); - } else { - canvasX = this.canvas.width / 2 - (x + rect.width / zoom); - canvasY = this.canvas.height / 2 - (y + rect.height / zoom); - - canvasX += this.canvas.width; - canvasY += this.canvas.height; - } - - canvasX >>= 0; - canvasY >>= 0; - - return { canvasX, canvasY }; - } - - debug(x: number, y: number, id?: string) { - if (document.getElementById("debug-" + id)) { - document.getElementById("debug-" + id)!.style.top = y + "px"; - document.getElementById("debug-" + id)!.style.left = x + "px"; - return; - } - let el = document.createElement("div"); - if (id) el.id = "debug-" + id; - el.classList.add("debug-point"); - el.style.setProperty("top", y + "px"); - el.style.setProperty("left", x + "px"); - document.body.appendChild(el); - } - - screenToPos(x: number, y: number) { - // the rendered dimentions in the browser - const rect = this.canvas.getBoundingClientRect(); - - let output = { - x: 0, - y: 0, - }; - - if (this.PanZoom.flags.useZoom) { - const scale = this.PanZoom.transform.scale; - - output.x = x / scale - rect.left; - output.y = y / scale - rect.top; - } else { - // get the ratio - const scale = [ - this.canvas.width / rect.width, - this.canvas.height / rect.height, - ]; - - output.x = (x - rect.left) * scale[0]; - output.y = (y - rect.top) * scale[1]; - } - - // floor it, we're getting canvas coords, which can't have decimals - output.x >>= 0; - output.y >>= 0; - - return [output.x, output.y]; - } - - draw() { - this.ctx.imageSmoothingEnabled = false; - - const bezier = (n: number) => n * n * (3 - 2 * n); - - this.ctx.globalAlpha = 1; - - this.ctx.fillStyle = "#fff"; - this.ctx.fillRect( - 0, - 0, - this.config.canvas.size[0], - this.config.canvas.size[1] - ); - - for (const [x_y, pixel] of Object.entries(this.pixels)) { - const [x, y] = x_y.split("_").map((a) => parseInt(a)); - - this.ctx.globalAlpha = pixel.type === "full" ? 1 : 0.5; - this.ctx.fillStyle = - pixel.color > -1 - ? "#" + this.Pallete.getColor(pixel.color)!.hex - : "transparent"; - this.ctx.fillRect(x, y, 1, 1); - } - - if (this.palleteCtx.color && this.cursor.x > -1 && this.cursor.y > -1) { - const color = this.config.pallete.colors.find( - (c) => c.id === this.palleteCtx.color - ); - - let t = ((Date.now() / 100) % 10) / 10; - this.ctx.globalAlpha = t < 0.5 ? bezier(t) : -bezier(t) + 1; - this.ctx.fillStyle = "#" + color!.hex; - this.ctx.fillRect(this.cursor.x, this.cursor.y, 1, 1); - } - - if (!this._destroy) window.requestAnimationFrame(() => this.draw()); - } -} diff --git a/packages/client-next/src/style.scss b/packages/client-next/src/style.scss deleted file mode 100644 index ff5cba8..0000000 --- a/packages/client-next/src/style.scss +++ /dev/null @@ -1,146 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -* { - box-sizing: border-box; -} - -html, -body { - overscroll-behavior: contain; - touch-action: none; - - background-color: #ddd !important; -} - -header#main-header { - position: fixed; - top: 0; - left: 0; - width: 100%; - - display: flex; - flex-direction: row; - box-sizing: border-box; - z-index: 9999; - touch-action: none; - pointer-events: none; - - .spacer { - flex-grow: 1; - } - - .box { - padding: 10px; - touch-action: initial; - pointer-events: initial; - } -} - -.user-card { - background-color: #444; - color: #fff; - border-radius: 10px; - padding: 5px 10px; - - display: flex; - flex-direction: row; - gap: 10px; - - &--overview { - display: flex; - flex-direction: column; - justify-content: center; - line-height: 1; - - span:first-of-type { - font-size: 130%; - margin-bottom: 5px; - } - } - - img { - width: 64px; - height: 64px; - - background-color: #aaa; - border-radius: 50%; - } -} - -#cursor { - position: fixed; - top: 20px; - left: 10px; - width: 36px; - height: 36px; - border: 2px solid #000; - border-radius: 3px; - - pointer-events: none; - will-change: transform; - z-index: 2; -} - -#canvas-meta { - position: absolute; - top: -10px; - background-color: rgba(0, 0, 0, 0.5); - color: #fff; - border-radius: 5px; - padding: 5px; - transform: translateY(-100%); - - display: flex; - flex-direction: column; - - .canvas-meta--cursor-pos { - font-style: italic; - } -} - -main { - z-index: 0; - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - display: flex; - align-items: center; - justify-content: center; - - canvas { - display: block; - box-sizing: border-box; - } -} - -.pixelate { - image-rendering: optimizeSpeed; - -ms-interpolation-mode: nearest-neighbor; - image-rendering: -webkit-optimize-contrast; - image-rendering: -webkit-crisp-edges; - image-rendering: -moz-crisp-edges; - image-rendering: -o-crisp-edges; - image-rendering: pixelated; - image-rendering: crisp-edges; -} - -.btn-link { - background-color: transparent; - border: 0; - padding: 0; - margin: 0; - color: inherit; - font-size: inherit; - text-decoration: underline; - - &:active { - opacity: 0.5; - } -} - -@import "./components/Pallete.scss"; -@import "./board.scss"; diff --git a/packages/client-next/tsconfig.json b/packages/client-next/tsconfig.json deleted file mode 100644 index 90af7e7..0000000 --- a/packages/client-next/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "@tsconfig/vite-react/tsconfig.json", -} diff --git a/packages/client-next/.nvmrc b/packages/client/.nvmrc similarity index 100% rename from packages/client-next/.nvmrc rename to packages/client/.nvmrc diff --git a/packages/client/gulpfile.js b/packages/client/gulpfile.js deleted file mode 100644 index 8b2bd65..0000000 --- a/packages/client/gulpfile.js +++ /dev/null @@ -1,26 +0,0 @@ -var gulp = require("gulp"); -var ts = require("gulp-typescript"); -const webpack = require("webpack-stream"); -const sass = require("gulp-sass")(require("sass")); - -gulp.task("css", function () { - return gulp - .src("src/**/*.scss") - .pipe(sass().on("error", sass.logError)) - .pipe(gulp.dest("./public/css")); -}); - -gulp.task("js", function () { - return gulp - .src("src/**/*.ts") - .pipe(webpack(require("./webpack.config.js"))) - .pipe(gulp.dest("public")); -}); - -gulp.task( - "watch", - gulp.series("js", "css", function () { - gulp.watch("src/**/*.ts", gulp.series("js")); - gulp.watch("src/**/*.scss", gulp.series("css")); - }) -); diff --git a/packages/client/package.json b/packages/client/package.json index 7f5be13..6ae1cba 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,26 +1,52 @@ { - "name": "@sc07-canvas/client", + "name": "client", "version": "1.0.0", + "description": "", + "main": "index.js", "scripts": { - "dev": "gulp watch" + "build": "vite build", + "dev": "vite serve", + "preview": "vite preview", + "lint": "eslint ." + }, + "type": "module", + "keywords": [], + "author": "", + "license": "ISC", + "eslintConfig": { + "extends": "react-app" }, "dependencies": { + "@fortawesome/fontawesome-svg-core": "^6.5.1", + "@fortawesome/free-solid-svg-icons": "^6.5.1", + "@fortawesome/react-fontawesome": "^0.2.0", + "@nextui-org/react": "^2.2.9", "@sc07-canvas/lib": "^1.0.0", - "gulp": "^4.0.2", - "gulp-cli": "^2.3.0", - "gulp-typescript": "^2.12.2", - "socket.io-client": "^4.7.2", - "ts-loader": "^9.4.4" + "eventemitter3": "^5.0.1", + "framer-motion": "^11.0.5", + "lodash.throttle": "^4.1.1", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-zoom-pan-pinch": "^3.4.1", + "socket.io-client": "^4.7.4" }, "devDependencies": { - "@babel/cli": "^7.22.10", - "@babel/core": "^7.22.10", - "@babel/preset-env": "^7.22.10", - "babel-loader": "^9.1.3", - "gulp-sass": "^5.1.0", - "sass": "^1.65.1", - "webpack": "^5.88.2", - "webpack-cli": "^5.1.4", - "webpack-stream": "^7.0.0" + "@tsconfig/vite-react": "^3.0.0", + "@types/lodash.throttle": "^4.1.9", + "@types/react": "^18.2.48", + "@types/react-dom": "^18.2.18", + "@types/socket.io-client": "^3.0.0", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.17", + "eslint": "^8.56.0", + "eslint-config-react-app": "^7.0.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "postcss": "^8.4.35", + "sass": "^1.70.0", + "tailwindcss": "^3.4.1", + "vite": "^5.1.1", + "vite-plugin-simple-html": "^0.1.2" } } diff --git a/packages/client-next/postcss.config.js b/packages/client/postcss.config.js similarity index 100% rename from packages/client-next/postcss.config.js rename to packages/client/postcss.config.js diff --git a/packages/client/public/index.html b/packages/client/public/index.html deleted file mode 100644 index 3f2c6b2..0000000 --- a/packages/client/public/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - Document - - - -
-
-
-
-
-
-
-
-
- User Avatar -
-
-
- -
-
-
- -
-
-
- - -
-
- - - Pixels: - - - - Users Online: - - - -
- -
-
- you are not logged in - -
-
- - - - diff --git a/packages/client-next/src/board.scss b/packages/client/src/board.scss similarity index 100% rename from packages/client-next/src/board.scss rename to packages/client/src/board.scss diff --git a/packages/client-next/src/components/App.tsx b/packages/client/src/components/App.tsx similarity index 100% rename from packages/client-next/src/components/App.tsx rename to packages/client/src/components/App.tsx diff --git a/packages/client-next/src/components/CanvasMeta.tsx b/packages/client/src/components/CanvasMeta.tsx similarity index 100% rename from packages/client-next/src/components/CanvasMeta.tsx rename to packages/client/src/components/CanvasMeta.tsx diff --git a/packages/client-next/src/components/CanvasWrapper.tsx b/packages/client/src/components/CanvasWrapper.tsx similarity index 100% rename from packages/client-next/src/components/CanvasWrapper.tsx rename to packages/client/src/components/CanvasWrapper.tsx diff --git a/packages/client-next/src/components/Header.tsx b/packages/client/src/components/Header.tsx similarity index 100% rename from packages/client-next/src/components/Header.tsx rename to packages/client/src/components/Header.tsx diff --git a/packages/client-next/src/components/Pallete.scss b/packages/client/src/components/Pallete.scss similarity index 100% rename from packages/client-next/src/components/Pallete.scss rename to packages/client/src/components/Pallete.scss diff --git a/packages/client-next/src/components/Pallete.tsx b/packages/client/src/components/Pallete.tsx similarity index 100% rename from packages/client-next/src/components/Pallete.tsx rename to packages/client/src/components/Pallete.tsx diff --git a/packages/client-next/src/contexts/AppContext.tsx b/packages/client/src/contexts/AppContext.tsx similarity index 100% rename from packages/client-next/src/contexts/AppContext.tsx rename to packages/client/src/contexts/AppContext.tsx diff --git a/packages/client-next/src/index.html b/packages/client/src/index.html similarity index 100% rename from packages/client-next/src/index.html rename to packages/client/src/index.html diff --git a/packages/client/src/index.ts b/packages/client/src/index.ts deleted file mode 100644 index 44ab01b..0000000 --- a/packages/client/src/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import "./lib/net"; -import Pallete from "./lib/pallete"; -import Canvas from "./lib/canvas"; - -window.addEventListener("mousemove", (e) => { - const cursor = document.getElementById("cursor"); - cursor!.style.transform = `translate(${e.pageX}px, ${e.pageY}px)`; -}); - -Canvas.setup(); -Canvas.draw(); diff --git a/packages/client-next/src/index.tsx b/packages/client/src/index.tsx similarity index 100% rename from packages/client-next/src/index.tsx rename to packages/client/src/index.tsx diff --git a/packages/client/src/lib/auth.ts b/packages/client/src/lib/auth.ts deleted file mode 100644 index dd4a1e2..0000000 --- a/packages/client/src/lib/auth.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SUserPacket, AuthSession } from "@sc07-canvas/lib/src/net"; - -const $puseroverlay = document.querySelector( - "#pallete .pallete-user-overlay" -)! as HTMLDivElement; -const $usercard = document.querySelector(".user-card")! as HTMLDivElement; -const $usercard_name = $usercard.querySelector(".user-name")! as HTMLDivElement; -const $usercard_instance = $usercard.querySelector( - ".user-instance" -)! as HTMLDivElement; -const $usercard_avatar = $usercard.querySelector( - "img.user-avatar" -)! as HTMLImageElement; - -class Auth { - private user: AuthSession | undefined; - - login() { - window.location.href = "/api/login"; - } - - handleAuth(data: SUserPacket) { - this.user = data.user; - $puseroverlay.style.display = "none"; - - $usercard_name.innerText = data.user.user.username; - $usercard_instance.innerHTML = data.user.service.instance.hostname; - $usercard_avatar.setAttribute("src", data.user.user.profile); - } -} - -export default new Auth(); diff --git a/packages/client/src/lib/canvas.ts b/packages/client/src/lib/canvas.ts index bfbbcfc..d8a4add 100644 --- a/packages/client/src/lib/canvas.ts +++ b/packages/client/src/lib/canvas.ts @@ -1,407 +1,99 @@ -import pallete from "./pallete"; -import Network from "./net"; +import EventEmitter from "eventemitter3"; +import { ClientConfig, IPalleteContext, IPosition, Pixel } from "../types"; +import Network from "./network"; import { - CPixelPacket, - SCanvasPacket, - SPixelPacket, -} from "@sc07-canvas/lib/src/net"; - -const $moveContainer = document.querySelector("main")!; -const $canvas = document.getElementById("board")! as HTMLCanvasElement; -const $zoom = document.getElementById("board-zoom")!; -const $move = document.getElementById("board-move")!; -const $container = document.querySelector("main")!; - -const $metabox = document.getElementById("canvas-meta")! as HTMLDivElement; -const $metabox_pixels = $metabox.querySelector( - ".canvas-meta--pixels" -) as HTMLSpanElement; -const $metabox_online = $metabox.querySelector( - ".canvas-meta--online" -) as HTMLSpanElement; - -const $testbtn = document.getElementById("test")! as HTMLButtonElement; - -export type CanvasConfig = { - size: [number, number]; - zoom: number; -}; - -const ZOOM_SPEED = 0.1; - -class Canvas { - private config: CanvasConfig = { size: [0, 0], zoom: 1 }; + ClickEvent, + HoverEvent, + PanZoom, +} from "@sc07-canvas/lib/src/renderer/PanZoom"; +interface CanvasEvents { /** - * Last pixel place date - * - * TODO: Support pixel stacking + * Cursor canvas position + * (-1, -1) is not on canvas + * @param position Canvas position + * @returns */ - private lastPlace: Date | undefined; - private zoom = 1; - private move = { x: 0, y: 0 }; + cursorPos: (position: IPosition) => void; +} + +export class Canvas extends EventEmitter { + static instance: Canvas | undefined; + + private _destroy = false; + private config: ClientConfig; + private canvas: HTMLCanvasElement; + private PanZoom: PanZoom; + private ctx: CanvasRenderingContext2D; + private cursor = { x: -1, y: -1 }; - private ctx: CanvasRenderingContext2D | null = null; - // private pixels: { - // x: number; - // y: number; - // color: number; - // type: "full" | "pending"; - // }[] = []; private pixels: { [x_y: string]: { color: number; type: "full" | "pending" }; } = {}; + private lastPlace: number | undefined; - private mouseDown = false; - private dragOrigin = { x: 0, y: 0 }; - private downTime: number | undefined; + constructor( + config: ClientConfig, + canvas: HTMLCanvasElement, + PanZoom: PanZoom + ) { + super(); + Canvas.instance = this; - load(config: CanvasConfig) { this.config = config; - $canvas.setAttribute("width", config.size[0] + ""); - $canvas.setAttribute("height", config.size[1] + ""); - this.setZoom(config.zoom); + this.canvas = canvas; + this.PanZoom = PanZoom; + this.ctx = canvas.getContext("2d")!; + + canvas.width = config.canvas.size[0]; + canvas.height = config.canvas.size[1]; + + this.PanZoom.addListener("hover", this.handleMouseMove.bind(this)); + this.PanZoom.addListener("click", this.handleMouseDown.bind(this)); + + Network.waitFor("canvas").then(([pixels]) => this.handleBatch(pixels)); + + this.draw(); } - setZoom(newzoom: number, mouse?: { x: number; y: number }) { - if (newzoom < 0.5) newzoom = 0.5; - const oldzoom = this.zoom; - this.zoom = newzoom; + destroy() { + this._destroy = true; - $zoom.style.transform = `scale(${newzoom})`; + this.PanZoom.removeListener("hover", this.handleMouseMove.bind(this)); + this.PanZoom.removeListener("click", this.handleMouseDown.bind(this)); - if (mouse) { - const dx = mouse.x - $container.clientWidth / 2; - const dy = mouse.y - $container.clientHeight / 2; - this.move.x -= dx / oldzoom; - this.move.x += dx / newzoom; - this.move.y -= dy / oldzoom; - this.move.y += dy / newzoom; - $move.style.transform = `translate(${this.move.x}px, ${this.move.y}px)`; - } + Network.off("canvas", this.handleBatch.bind(this)); } - setup() { - this.ctx = $canvas.getContext("2d"); + handleMouseDown(e: ClickEvent) { + const [x, y] = this.screenToPos(e.clientX, e.clientY); + this.place(x, y); + } - let pinching = false; - let pinchInit = 0; - - $testbtn.addEventListener("click", (e) => { - e.preventDefault(); - - $canvas.classList.toggle("pixelate"); - }); - - window.addEventListener("wheel", (e) => { - const oldzoom = this.zoom; - let newzoom = (this.zoom += ZOOM_SPEED * (e.deltaY > 0 ? -1 : 1)); - this.setZoom(newzoom, { - x: e.clientX, - y: e.clientY, - }); - }); - - const handleMouseStart = (e: { pageX: number; pageY: number }) => { - this.mouseDown = true; - this.dragOrigin = { x: e.pageX, y: e.pageY }; - this.downTime = Date.now(); - }; - - $moveContainer.addEventListener( - "touchstart", - (e) => { - if (e.changedTouches.length === 2) { - pinching = true; - pinchInit = Math.hypot( - e.touches[0].pageX - e.touches[1].pageX, - e.touches[0].pageY - e.touches[1].pageY - ); - } else { - handleMouseStart(e.touches[0]); - } - - $testbtn.innerText = e.changedTouches.length + ""; - }, - { passive: false } - ); - $moveContainer.addEventListener("mousedown", handleMouseStart); - - const update = (x: number, y: number, update: boolean) => { - const deltaX = (x - this.dragOrigin.x) / this.zoom; - const deltaY = (y - this.dragOrigin.y) / this.zoom; - const newX = this.move.x + deltaX; - const newY = this.move.y + deltaY; - if (update) { - this.move.x += deltaX; - this.move.y += deltaY; - } - $move.style.transform = `translate(${newX}px, ${newY}px)`; - }; - - const handleMouseEnd = (e: { - clientX: number; - clientY: number; - pageX: number; - pageY: number; - }) => { - if (!this.mouseDown) return; - - this.mouseDown = false; - - const downDelta = Date.now() - this.downTime!; - const delta = [ - Math.abs(this.dragOrigin.x - e.clientX), - Math.abs(this.dragOrigin.y - e.clientY), - ]; - if (downDelta < 500) { - // mouse was down for less than 500ms - - if (delta[0] < 5 && delta[1] < 5) { - const [x, y] = this.screenToPos(e.clientX, e.clientY); - this.place(x, y); - } - } - - update(e.pageX, e.pageY, true); - }; - - window.addEventListener("touchend", (e) => { - if (pinching) { - console.log("pinching end"); - pinching = false; - } else { - handleMouseEnd(e.changedTouches[0]); - } - }); - window.addEventListener("mouseup", (e) => { - if (pinching) { - pinching = false; - } else { - handleMouseEnd(e); - } - }); - - const handleMouseMove = (e: { - pageX: number; - pageY: number; - clientX: number; - clientY: number; - }) => { - if (this.mouseDown) { - update(e.pageX, e.pageY, false); - } else { - const canvasRect = $canvas.getBoundingClientRect(); - if ( - canvasRect.left <= e.pageX && - canvasRect.right >= e.pageX && - canvasRect.top <= e.pageY && - canvasRect.bottom >= e.pageY - ) { - const [x, y] = this.screenToPos(e.clientX, e.clientY); - this.cursor.x = x; - this.cursor.y = y; - } else { - this.cursor.x = -1; - this.cursor.y = -1; - } - } - }; - - window.addEventListener( - "touchmove", - (e) => { - if (pinching) { - let initDiff = Math.hypot( - e.touches[0].pageX - e.touches[1].pageX, - e.touches[0].pageY - e.touches[1].pageY - ); - let diff = (pinchInit - initDiff) / (10 / this.zoom); - - let newzoom = (this.zoom += ZOOM_SPEED * -diff); - this.setZoom(newzoom, { - x: window.innerWidth / 2, - y: window.innerHeight / 2, - }); - - pinchInit = initDiff; - } else { - handleMouseMove(e.touches[0]); - } - }, - { passive: false } - ); - window.addEventListener("mousemove", handleMouseMove); - - $canvas.addEventListener("touchmove", (e) => { - if (!pinching) { - const [x, y] = this.screenToPos( - e.touches[0].clientX, - e.touches[0].clientY - ); - this.cursor.x = x; - this.cursor.y = y; - } - }); - $canvas.addEventListener("mousemove", (e) => { + handleMouseMove(e: HoverEvent) { + const canvasRect = this.canvas.getBoundingClientRect(); + if ( + canvasRect.left <= e.clientX && + canvasRect.right >= e.clientX && + canvasRect.top <= e.clientY && + canvasRect.bottom >= e.clientY + ) { const [x, y] = this.screenToPos(e.clientX, e.clientY); this.cursor.x = x; this.cursor.y = y; - - // window.requestAnimationFrame(() => this.draw()); - }); - } - - screenToPos(x: number, y: number) { - const rect = $canvas.getBoundingClientRect(); - const scale = [$canvas.width / rect.width, $canvas.height / rect.height]; - return [x - rect.left, y - rect.top] - .map((v, i) => v * scale[i]) - .map((v) => v >> 0); - } - - draw() { - if (!this.ctx) { - window.requestAnimationFrame(() => this.draw()); - return; - } - - /* @ts-ignore */ - this.ctx.mozImageSmoothingEnabled = - /* @ts-ignore */ - this.ctx.webkitImageSmoothingEnabled = - /* @ts-ignore */ - this.ctx.msImageSmoothingEnabled = - this.ctx.imageSmoothingEnabled = - false; - - this.ctx.canvas.width = window.innerWidth; - this.ctx.canvas.height = window.innerHeight; - - const bezier = (n: number) => n * n * (3 - 2 * n); - - this.ctx.globalAlpha = 1; - - this.ctx.fillStyle = "#fff"; - this.ctx.fillRect(0, 0, this.config.size[0], this.config.size[1]); - - for (const [x_y, pixel] of Object.entries(this.pixels)) { - const [x, y] = x_y.split("_").map((a) => parseInt(a)); - - this.ctx.globalAlpha = pixel.type === "full" ? 1 : 0.5; - this.ctx.fillStyle = - pixel.color > -1 - ? "#" + pallete.getPalleteColor(pixel.color)!.hex - : "transparent"; - this.ctx.fillRect(x, y, 1, 1); - } - - if (pallete.getColor() && this.cursor.x > -1 && this.cursor.y > -1) { - let t = ((Date.now() / 100) % 10) / 10; - this.ctx.globalAlpha = t < 0.5 ? bezier(t) : -bezier(t) + 1; - this.ctx.fillStyle = "#" + pallete.getColor()!.hex; - this.ctx.fillRect(this.cursor.x, this.cursor.y, 1, 1); - } - - this.renderMetabox(); - - window.requestAnimationFrame(() => this.draw()); - } - - /** - * update canvas metabox with latest information - * - * executed by #draw() - */ - renderMetabox() { - if (this.lastPlace) { - let cooldown = - this.lastPlace.getTime() + - pallete.getPixelCooldown() - - new Date().getTime(); - $metabox_pixels.innerText = cooldown > 0 ? cooldown / 1000 + "s" : "none"; } else { - $metabox_pixels.innerText = "no cooldown"; + this.cursor.x = -1; + this.cursor.y = -1; } - $metabox_online.innerText = Network.getOnline() + ""; + this.emit("cursorPos", this.cursor); } - place(x: number, y: number) { - if (!pallete.getColor()) return; - - if (this.lastPlace) { - if ( - this.lastPlace.getTime() + pallete.getPixelCooldown() > - new Date().getTime() - ) { - console.log("cannot place, cooldown in place"); - return; - } - } - - this.lastPlace = new Date(); - - const color = pallete.getColor()!; - - // this.pixels.push({ - // x, - // y, - // color: color.id, - // type: "pending", - // }); - this.pixels[x + "_" + y] = { - color: color.id, - type: "pending", - }; - - Network.sendAck("place", { - x, - y, - color: color.id, - }).then((ack) => { - // remove pending pixel at coord - // can remove regardless of success or failure, as success places pixel at coord from server - // this.pixels.splice( - // this.pixels.indexOf( - // this.pixels.find( - // (pxl) => - // pxl.x === x && - // pxl.y === y && - // pxl.color === color.id && - // pxl.type === "pending" - // )! - // ), - // 1 - // ); - - if (ack.success) { - this.handlePixel(ack.data); - } else { - // TODO: handle undo pixel - alert("Error: " + ack.error); - } - }); - } - - handlePixel({ x, y, color, ...rest }: SPixelPacket) { - // this.pixels.push({ - // x, - // y, - // color, - // type: "full", - // }); - this.pixels[x + "_" + y] = { - color, - type: "full", - }; - } - - handleBatch(batch: SCanvasPacket) { - batch.pixels.forEach((hex, index) => { - const x = index / this.config.size[0]; - const y = index % this.config.size[0]; - const color = pallete.getPalleteFromHex(hex); + handleBatch(pixels: string[]) { + pixels.forEach((hex, index) => { + const x = index % this.config.canvas.size[0]; + const y = index / this.config.canvas.size[1]; + const color = this.Pallete.getColorFromHex(hex); this.pixels[x + "_" + y] = { color: color ? color.id : -1, @@ -409,6 +101,172 @@ class Canvas { }; }); } -} -export default new Canvas(); + handlePixel({ x, y, color }: Pixel) { + this.pixels[x + "_" + y] = { + color, + type: "full", + }; + } + + palleteCtx: IPalleteContext = {}; + Pallete = { + getColor: (colorId: number) => { + return this.config.pallete.colors.find((c) => c.id === colorId); + }, + + getSelectedColor: () => { + if (!this.palleteCtx.color) return undefined; + + return this.Pallete.getColor(this.palleteCtx.color); + }, + + getColorFromHex: (hex: string) => { + return this.config.pallete.colors.find((c) => c.hex === hex); + }, + }; + + updatePallete(pallete: IPalleteContext) { + this.palleteCtx = pallete; + } + + place(x: number, y: number) { + if (!this.Pallete.getSelectedColor()) return; + + if (this.lastPlace) { + if (this.lastPlace + this.config.pallete.pixel_cooldown > Date.now()) { + console.log("cannot place; cooldown"); + return; + } + } + + this.lastPlace = Date.now(); + + Network.socket + .emitWithAck("place", { + x, + y, + color: this.Pallete.getSelectedColor()!.id, + }) + .then((ack) => { + if (ack.success) { + this.handlePixel(ack.data); + } else { + // TODO: handle undo pixel + alert("error: " + ack.error); + } + }); + } + + panZoomTransformToCanvas() { + const { x, y, scale: zoom } = this.PanZoom.transform; + const rect = this.canvas.getBoundingClientRect(); + + let canvasX = 0; + let canvasY = 0; + + if (this.PanZoom.flags.useZoom) { + // css zoom doesn't change the bounding client rect + // therefore dividing by zoom doesn't return the correct output + canvasX = this.canvas.width - (x + rect.width / 2); + canvasY = this.canvas.height - (y + rect.height / 2); + } else { + canvasX = this.canvas.width / 2 - (x + rect.width / zoom); + canvasY = this.canvas.height / 2 - (y + rect.height / zoom); + + canvasX += this.canvas.width; + canvasY += this.canvas.height; + } + + canvasX >>= 0; + canvasY >>= 0; + + return { canvasX, canvasY }; + } + + debug(x: number, y: number, id?: string) { + if (document.getElementById("debug-" + id)) { + document.getElementById("debug-" + id)!.style.top = y + "px"; + document.getElementById("debug-" + id)!.style.left = x + "px"; + return; + } + let el = document.createElement("div"); + if (id) el.id = "debug-" + id; + el.classList.add("debug-point"); + el.style.setProperty("top", y + "px"); + el.style.setProperty("left", x + "px"); + document.body.appendChild(el); + } + + screenToPos(x: number, y: number) { + // the rendered dimentions in the browser + const rect = this.canvas.getBoundingClientRect(); + + let output = { + x: 0, + y: 0, + }; + + if (this.PanZoom.flags.useZoom) { + const scale = this.PanZoom.transform.scale; + + output.x = x / scale - rect.left; + output.y = y / scale - rect.top; + } else { + // get the ratio + const scale = [ + this.canvas.width / rect.width, + this.canvas.height / rect.height, + ]; + + output.x = (x - rect.left) * scale[0]; + output.y = (y - rect.top) * scale[1]; + } + + // floor it, we're getting canvas coords, which can't have decimals + output.x >>= 0; + output.y >>= 0; + + return [output.x, output.y]; + } + + draw() { + this.ctx.imageSmoothingEnabled = false; + + const bezier = (n: number) => n * n * (3 - 2 * n); + + this.ctx.globalAlpha = 1; + + this.ctx.fillStyle = "#fff"; + this.ctx.fillRect( + 0, + 0, + this.config.canvas.size[0], + this.config.canvas.size[1] + ); + + for (const [x_y, pixel] of Object.entries(this.pixels)) { + const [x, y] = x_y.split("_").map((a) => parseInt(a)); + + this.ctx.globalAlpha = pixel.type === "full" ? 1 : 0.5; + this.ctx.fillStyle = + pixel.color > -1 + ? "#" + this.Pallete.getColor(pixel.color)!.hex + : "transparent"; + this.ctx.fillRect(x, y, 1, 1); + } + + if (this.palleteCtx.color && this.cursor.x > -1 && this.cursor.y > -1) { + const color = this.config.pallete.colors.find( + (c) => c.id === this.palleteCtx.color + ); + + let t = ((Date.now() / 100) % 10) / 10; + this.ctx.globalAlpha = t < 0.5 ? bezier(t) : -bezier(t) + 1; + this.ctx.fillStyle = "#" + color!.hex; + this.ctx.fillRect(this.cursor.x, this.cursor.y, 1, 1); + } + + if (!this._destroy) window.requestAnimationFrame(() => this.draw()); + } +} diff --git a/packages/client/src/lib/net.ts b/packages/client/src/lib/net.ts deleted file mode 100644 index bf75bb7..0000000 --- a/packages/client/src/lib/net.ts +++ /dev/null @@ -1,74 +0,0 @@ -import io from "socket.io-client"; -import Pallete from "./pallete"; -import Canvas from "./canvas"; -import { - CPixelPacket, - ClientPacket, - PacketAck, - SCanvasPacket, - SPixelPacket, - SUserPacket, - ServerPacket, -} from "@sc07-canvas/lib/src/net"; -import Auth from "./auth"; - -class Network { - private socket; - private online_count = 0; - - constructor() { - this.socket = io(); - - this.socket.on("config", (config) => { - Pallete.load(config.pallete); - Canvas.load(config.canvas); - }); - - this.socket.on("pixel", (data: SPixelPacket) => { - Canvas.handlePixel(data); - }); - - this.socket.on("user", (data: SUserPacket) => { - Auth.handleAuth(data); - }); - - this.socket.on("canvas", (data: SCanvasPacket) => { - Canvas.handleBatch(data); - }); - - this.socket.on("online", (data: { count: number }) => { - this.online_count = data.count; - }); - } - - send( - type: T["type"], - data: Omit - ) { - // @ts-ignore - data._direction = "client->server"; - - this.socket.emit(type, data); - } - - sendAck( - type: O["type"], - data: Omit - ) { - return new Promise>((res) => { - this.socket.emit(type, data, (data: PacketAck) => { - res(data); - }); - }); - } - - /** - * Get online user count - * @returns online users count - */ - getOnline() { - return this.online_count; - } -} - -export default new Network(); diff --git a/packages/client-next/src/lib/network.ts b/packages/client/src/lib/network.ts similarity index 100% rename from packages/client-next/src/lib/network.ts rename to packages/client/src/lib/network.ts diff --git a/packages/client/src/lib/pallete.ts b/packages/client/src/lib/pallete.ts deleted file mode 100644 index c05cc35..0000000 --- a/packages/client/src/lib/pallete.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { SUserPacket } from "@sc07-canvas/lib/src/net"; - -export type PalleteColor = { - id: number; - hex: string; - name: string; -}; - -const $pallete = document.getElementById("pallete")!; -const $pcolors = $pallete.querySelector(".pallete-colors")!; -const $puseroverlay = $pallete.querySelector( - ".pallete-user-overlay" -)! as HTMLDivElement; -const $cursor = document.getElementById("cursor")!; - -class Pallete { - private pallete: PalleteColor[] = []; - private active: PalleteColor | undefined; - private pixel_cooldown = 0; - - load({ - colors, - pixel_cooldown, - }: { - colors: PalleteColor[]; - pixel_cooldown: number; - }) { - $pcolors.innerHTML = ""; - - this.pallete = colors; - this.pixel_cooldown = pixel_cooldown; - - colors.forEach((color) => { - const $color = document.createElement("a"); - $color.href = "#"; - $color.classList.add("pallete-color"); - $color.style.backgroundColor = "#" + color.hex; - $color.addEventListener("click", () => { - this.pick(color); - }); - $pcolors.append($color); - }); - - this.active = undefined; - } - - pick(color?: PalleteColor) { - this.active = color; - - $cursor.style.display = color ? "block" : "none"; - - if (color) $cursor.style.backgroundColor = "#" + color.hex; - } - - getColor() { - return this.active; - } - - getPallete() { - return this.pallete; - } - - getPalleteColor(id: number) { - return this.pallete.find((p) => p.id === id); - } - - getPalleteFromHex(hex: string) { - return this.pallete.find((p) => p.hex === hex); - } - - /** - * Get pixel cooldown - * @returns Pixel cooldown in ms - */ - getPixelCooldown() { - return this.pixel_cooldown; - } -} - -export default new Pallete(); diff --git a/packages/client-next/src/lib/routes.ts b/packages/client/src/lib/routes.ts similarity index 100% rename from packages/client-next/src/lib/routes.ts rename to packages/client/src/lib/routes.ts diff --git a/packages/client/src/style.scss b/packages/client/src/style.scss index 2fef649..ff5cba8 100644 --- a/packages/client/src/style.scss +++ b/packages/client/src/style.scss @@ -1,14 +1,20 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +* { + box-sizing: border-box; +} + html, body { overscroll-behavior: contain; touch-action: none; + + background-color: #ddd !important; } -body { - background-color: #ddd; -} - -header { +header#main-header { position: fixed; top: 0; left: 0; @@ -16,13 +22,20 @@ header { display: flex; flex-direction: row; - padding: 10px; box-sizing: border-box; z-index: 9999; + touch-action: none; + pointer-events: none; .spacer { flex-grow: 1; } + + .box { + padding: 10px; + touch-action: initial; + pointer-events: initial; + } } .user-card { @@ -70,59 +83,20 @@ header { z-index: 2; } -#pallete { - position: fixed; - left: 0; - bottom: 0; - width: 100%; +#canvas-meta { + position: absolute; + top: -10px; + background-color: rgba(0, 0, 0, 0.5); + color: #fff; + border-radius: 5px; + padding: 5px; + transform: translateY(-100%); display: flex; - gap: 10px; - padding: 10px; + flex-direction: column; - background-color: #fff; - - .pallete-colors { - display: flex; - width: 100%; - justify-content: center; - gap: 10px; - padding: 10px; - } - - .pallete-color { - width: 36px; - height: 36px; - border: 2px solid #000; - border-radius: 3px; - } - - .pallete-user-overlay { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 1; - background-color: rgba(0, 0, 0, 0.5); - color: #fff; - - display: flex; - justify-content: center; - align-items: center; - } - - #canvas-meta { - position: absolute; - top: -10px; - background-color: rgba(0, 0, 0, 0.5); - color: #fff; - border-radius: 5px; - padding: 5px; - transform: translateY(-100%); - - display: flex; - flex-direction: column; + .canvas-meta--cursor-pos { + font-style: italic; } } @@ -153,3 +127,20 @@ main { image-rendering: pixelated; image-rendering: crisp-edges; } + +.btn-link { + background-color: transparent; + border: 0; + padding: 0; + margin: 0; + color: inherit; + font-size: inherit; + text-decoration: underline; + + &:active { + opacity: 0.5; + } +} + +@import "./components/Pallete.scss"; +@import "./board.scss"; diff --git a/packages/client-next/src/types.ts b/packages/client/src/types.ts similarity index 100% rename from packages/client-next/src/types.ts rename to packages/client/src/types.ts diff --git a/packages/client-next/src/vite-env.d.ts b/packages/client/src/vite-env.d.ts similarity index 100% rename from packages/client-next/src/vite-env.d.ts rename to packages/client/src/vite-env.d.ts diff --git a/packages/client-next/tailwind.config.js b/packages/client/tailwind.config.js similarity index 100% rename from packages/client-next/tailwind.config.js rename to packages/client/tailwind.config.js diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 59d3ab3..90af7e7 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -1,6 +1,3 @@ { - "extends": "@tsconfig/recommended/tsconfig.json", - "compilerOptions": { - "sourceMap": true - } + "extends": "@tsconfig/vite-react/tsconfig.json", } diff --git a/packages/client-next/vite.config.js b/packages/client/vite.config.js similarity index 100% rename from packages/client-next/vite.config.js rename to packages/client/vite.config.js diff --git a/packages/client/webpack.config.js b/packages/client/webpack.config.js deleted file mode 100644 index 8cd6a89..0000000 --- a/packages/client/webpack.config.js +++ /dev/null @@ -1,22 +0,0 @@ -const path = require("path"); - -module.exports = { - entry: "./src/index.ts", - devtool: "inline-source-map", - module: { - rules: [ - { - test: /\.tsx?$/, - use: "ts-loader", - exclude: /node_modules/, - }, - ], - }, - resolve: { - extensions: [".tsx", ".ts", ".js"], - }, - output: { - filename: "bundle.js", - path: path.resolve(__dirname, "public"), - }, -};