diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 8e4eecf..1f67da3 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,6 +1,7 @@ module.exports = { rules: { - "react-refresh/only-export-components": "warn" + "react-refresh/only-export-components": "warn", + "react/prop-types": "off" }, reportUnusedDisableDirectives: true, ignorePatterns: [ diff --git a/components.json b/components.json index e3b8873..1ea8f66 100644 --- a/components.json +++ b/components.json @@ -12,7 +12,7 @@ }, "aliases": { "components": "@/components", - "utils": "@/lib/utils", + "utils": "@/lib/tailwind-utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" diff --git a/package.json b/package.json index 9c55dfe..594847b 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "react-dom": "^19.0.0", "react-streaming": "^0.3.46", "sirv": "^2.0.3", + "tailwind-merge": "^3.3.1", "tailwindcss": "^3.4.17", "tailwindcss-animate": "^1.0.7", "ts-node": "^10.9.2", @@ -73,7 +74,9 @@ "@testing-library/jest-dom": "^6.6.1", "@testing-library/react": "^16.0.1", "@testing-library/user-event": "^14.5.2", + "@types/cookie-parser": "^1.4.9", "@vitest/coverage-v8": "2.1.3", + "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.5.3", "fake-indexeddb": "^6.0.0", "husky": "^9.1.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 59c09bb..629e5c4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -107,6 +107,9 @@ dependencies: sirv: specifier: ^2.0.3 version: 2.0.3 + tailwind-merge: + specifier: ^3.3.1 + version: 3.3.1 tailwindcss: specifier: ^3.4.17 version: 3.4.17(ts-node@10.9.2) @@ -142,12 +145,18 @@ devDependencies: '@testing-library/user-event': specifier: ^14.5.2 version: 14.5.2(@testing-library/dom@10.4.0) + '@types/cookie-parser': + specifier: ^1.4.9 + version: 1.4.9(@types/express@4.17.17) '@vitest/coverage-v8': specifier: 2.1.3 version: 2.1.3(vitest@2.1.3) + eslint-config-prettier: + specifier: ^10.1.8 + version: 10.1.8(eslint@8.47.0) eslint-plugin-prettier: specifier: ^5.5.3 - version: 5.5.3(eslint@8.47.0)(prettier@3.3.3) + version: 5.5.3(eslint-config-prettier@10.1.8)(eslint@8.47.0)(prettier@3.3.3) fake-indexeddb: specifier: ^6.0.0 version: 6.0.0 @@ -3872,7 +3881,6 @@ packages: dependencies: '@types/connect': 3.4.38 '@types/node': 20.4.10 - dev: false /@types/compression@1.7.2: resolution: {integrity: sha512-lwEL4M/uAGWngWFLSG87ZDr2kLrbuR8p7X+QZB1OQlT+qkHsCPDVFnHPyXf4Vyl4yDDorNY+mAhosxkCvppatg==} @@ -3884,7 +3892,14 @@ packages: resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} dependencies: '@types/node': 20.4.10 - dev: false + + /@types/cookie-parser@1.4.9(@types/express@4.17.17): + resolution: {integrity: sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==} + peerDependencies: + '@types/express': '*' + dependencies: + '@types/express': 4.17.17 + dev: true /@types/estree@1.0.6: resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -3897,7 +3912,6 @@ packages: '@types/qs': 6.9.18 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - dev: false /@types/express@4.17.17: resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==} @@ -3906,11 +3920,9 @@ packages: '@types/express-serve-static-core': 4.19.6 '@types/qs': 6.9.18 '@types/serve-static': 1.15.7 - dev: false /@types/http-errors@2.0.4: resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: false /@types/json-schema@7.0.15: resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -3918,7 +3930,6 @@ packages: /@types/mime@1.3.5: resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: false /@types/node@20.4.10: resolution: {integrity: sha512-vwzFiiy8Rn6E0MtA13/Cxxgpan/N6UeNYR9oUu6kuJWxu6zCk98trcDp8CBhbtaeuq9SykCmXkFr2lWLoPcvLg==} @@ -3929,11 +3940,9 @@ packages: /@types/qs@6.9.18: resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} - dev: false /@types/range-parser@1.2.7: resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: false /@types/react-dom@19.0.2(@types/react@19.0.2): resolution: {integrity: sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==} @@ -3956,7 +3965,6 @@ packages: dependencies: '@types/mime': 1.3.5 '@types/node': 20.4.10 - dev: false /@types/serve-static@1.15.7: resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} @@ -3964,7 +3972,6 @@ packages: '@types/http-errors': 2.0.4 '@types/node': 20.4.10 '@types/send': 0.17.4 - dev: false /@types/uuid@10.0.0: resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} @@ -5237,7 +5244,16 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - /eslint-plugin-prettier@5.5.3(eslint@8.47.0)(prettier@3.3.3): + /eslint-config-prettier@10.1.8(eslint@8.47.0): + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.47.0 + dev: true + + /eslint-plugin-prettier@5.5.3(eslint-config-prettier@10.1.8)(eslint@8.47.0)(prettier@3.3.3): resolution: {integrity: sha512-NAdMYww51ehKfDyDhv59/eIItUVzU0Io9H2E8nHNGKEeeqlnci+1gCvrHib6EmZdf6GxF+LCV5K7UC65Ezvw7w==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -5252,6 +5268,7 @@ packages: optional: true dependencies: eslint: 8.47.0 + eslint-config-prettier: 10.1.8(eslint@8.47.0) prettier: 3.3.3 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 @@ -7736,6 +7753,10 @@ packages: '@pkgr/core': 0.2.9 dev: true + /tailwind-merge@3.3.1: + resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==} + dev: false + /tailwindcss-animate@1.0.7(tailwindcss@3.4.17): resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} peerDependencies: diff --git a/src/components/ColorThumb/ColorThumb.tsx b/src/components/ColorThumb/ColorThumb.tsx index a603f54..9d00e41 100644 --- a/src/components/ColorThumb/ColorThumb.tsx +++ b/src/components/ColorThumb/ColorThumb.tsx @@ -1,6 +1,6 @@ // Components import { ColorThumb as AriaColorThumb } from "react-aria-components"; -import clsx from "clsx"; +import cn from "@/lib/tailwind-utils"; // Types import type { ComponentProps, ReactNode } from "react"; @@ -8,7 +8,7 @@ import type { ComponentProps, ReactNode } from "react"; function ColorThumb({ className, ...props }: ComponentProps<"div">): ReactNode { return ( changeColor(color.toString('hex')); + const onChange = (color: Color) => changeColor(color.toString("hex")); const wheelColor = parseColor(color).toString("hsl"); const COLOR_WHEEL_OUTER_RADIUS = 80; diff --git a/src/components/DrawingToolbar/DrawingToolbar.tsx b/src/components/DrawingToolbar/DrawingToolbar.tsx index f1459d3..3b8a77d 100644 --- a/src/components/DrawingToolbar/DrawingToolbar.tsx +++ b/src/components/DrawingToolbar/DrawingToolbar.tsx @@ -3,7 +3,7 @@ import { SHAPES } from "@/state/store"; import { memo, Fragment } from "react"; import useStore from "@/state/hooks/useStore"; import { useShallow } from "zustand/react/shallow"; -import clsx from "clsx"; +import cn from "@/lib/tailwind-utils"; // Type import type { ReactNode, ChangeEvent, MouseEvent, ReactElement } from "react"; @@ -86,7 +86,7 @@ function DrawingToolbar(): ReactNode { >