diff --git a/package.json b/package.json index 289fe28..89ee5f6 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "next": "14.2.9", "react": "^18", "react-dom": "^18", + "react-draggable": "^4.4.6", "react-hook-form": "^7.53.0", "tailwind-merge": "^2.5.2", "tailwindcss-animate": "^1.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6927393..60522ef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,9 @@ importers: react-dom: specifier: ^18 version: 18.3.1(react@18.3.1) + react-draggable: + specifier: ^4.4.6 + version: 4.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-hook-form: specifier: ^7.53.0 version: 7.53.0(react@18.3.1) @@ -645,6 +648,10 @@ packages: client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} @@ -1501,6 +1508,12 @@ packages: peerDependencies: react: ^18.3.1 + react-draggable@4.4.6: + resolution: {integrity: sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==} + peerDependencies: + react: '>= 16.3.0' + react-dom: '>= 16.3.0' + react-hook-form@7.53.0: resolution: {integrity: sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==} engines: {node: '>=18.0.0'} @@ -2375,6 +2388,8 @@ snapshots: client-only@0.0.1: {} + clsx@1.2.1: {} + clsx@2.0.0: {} clsx@2.1.1: {} @@ -2603,8 +2618,8 @@ snapshots: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.10.0(eslint@8.57.0) eslint-plugin-react: 7.35.2(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -2623,37 +2638,37 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.8.0 is-bun-module: 1.2.1 is-glob: 4.0.3 optionalDependencies: - eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) transitivePeerDependencies: - '@typescript-eslint/parser' - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.6.2) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -2664,7 +2679,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.11.0(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.6.2))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.30.0)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -3394,6 +3409,13 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 + react-draggable@4.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + clsx: 1.2.1 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-hook-form@7.53.0(react@18.3.1): dependencies: react: 18.3.1 diff --git a/src/app/page.tsx b/src/app/page.tsx index 73c5b2d..4686dd4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,8 +1,7 @@ "use client"; import { zodResolver } from "@hookform/resolvers/zod"; -import { useState } from "react"; import { RadialBackground, type Vector } from "./radialBackground"; -import { useForm } from "react-hook-form"; +import { Controller, useForm } from "react-hook-form"; import { z } from "zod"; import { Form, @@ -12,9 +11,10 @@ import { FormLabel, } from "@/components/ui/form"; import { Checkbox } from "@/components/ui/checkbox"; -import { Label } from "@/components/ui/label"; import { Slider } from "@/components/ui/slider"; import _ from "lodash"; +import Draggable from "react-draggable"; +import { cn } from "@/lib/utils"; const vectorSchema = z.tuple([z.number(), z.number()]); @@ -49,9 +49,9 @@ export default function Home() { initialParentAspect: 5 / 2, debug: false, - showHandles: false, + showHandles: true, showGrid: false, - runtimeAspectCalculation: false, + runtimeAspectCalculation: true, originalGradientSize: [0.5, 0.5] as Vector, @@ -66,7 +66,7 @@ export default function Home() { }, }); - const { width, height, ...props } = form.watch(); + const { width, height, showHandles, ...props } = form.watch(); return (
@@ -75,8 +75,8 @@ export default function Home() { {( [ "debug", - "showHandles", "showGrid", + "showHandles", "runtimeAspectCalculation", ] as const ).map((name) => ( @@ -88,7 +88,7 @@ export default function Home() { @@ -108,7 +108,7 @@ export default function Home() { min={150} max={800} value={[field.value]} - onValueChange={field.onChange} + onValueChange={(v) => field.onChange(v[0])} /> Width @@ -126,7 +126,7 @@ export default function Home() { min={150} max={800} value={[field.value]} - onValueChange={field.onChange} + onValueChange={(v) => field.onChange(v[0])} /> Height @@ -145,7 +145,7 @@ export default function Home() { max={1.5} step={0.01} value={[field.value]} - onValueChange={field.onChange} + onValueChange={(v) => field.onChange(v[0])} /> Original ellipse width % @@ -164,19 +164,38 @@ export default function Home() { max={1.5} step={0.01} value={[field.value]} - onValueChange={field.onChange} + onValueChange={(v) => field.onChange(v[0])} /> Original ellipse width % )} /> + ( + + + field.onChange(v[0])} + /> + + Initial parent aspect ratio + + )} + />
@@ -184,6 +203,40 @@ export default function Home() { {width} x {height} + {showHandles && + (["center", "a", "b"] as const).map((name, index) => ( +
+ ( + { + field.onChange([data.x / width, data.y / height]); + }} + > +
+
+
+ + )} + > +
+ ))}
diff --git a/src/app/radialBackground.tsx b/src/app/radialBackground.tsx index 62ac0ae..2e27337 100644 --- a/src/app/radialBackground.tsx +++ b/src/app/radialBackground.tsx @@ -46,7 +46,6 @@ type Props = { runtimeAspectCalculation?: boolean; stops: Stop[]; - showHandles?: boolean; showGrid?: boolean; debug?: boolean; } & ( @@ -65,7 +64,6 @@ export function RadialBackground({ b, stops, debug = false, - showHandles = false, showGrid = false, originalGradientSize = [1, 1] as Vector, initialParentAspect = 1, @@ -109,11 +107,9 @@ export function RadialBackground({ const A = sub(a, center).map((x) => (x * 2) / originalGradientSize[0]); const B = sub(b, center).map((x) => (x * 2) / originalGradientSize[1]); - console.log({ A, B }); // Account for aspect ratio (don't ask me why this works) A[1] = A[1] / parentAspect; B[0] = B[0] * parentAspect; - console.log("Transformed", { A, B }); const matrixString = `matrix(${A.join(", ")}, ${B.join(", ")}, 0, 0)`; return ( @@ -141,22 +137,10 @@ export function RadialBackground({ _.times(4).map((i) => (
))}
- {showHandles && - [center, a, b].map((point, index) => ( -
-
-
- ))} ); }