From 708cd3e8c4d6961400c60daead6e7058d476c4e1 Mon Sep 17 00:00:00 2001 From: Makisuo Date: Sat, 24 Oct 2026 00:54:23 +0200 Subject: [PATCH 1/2] chore(deps): drop dependencies that only had one easy caller - Delete lib/effect-router: no package depends on it or imports it. Takes @tanstack/react-router with it; @effect/atom-react moves from the catalog to a direct pin in examples/effect-todo, its last user. - expect-type: import expectTypeOf from vitest, which re-exports the same package. - postgres: audit-raw-sql and restore-test run on @effect/sql-pg like the other db scripts. A failed connect still reports every restore check as failed instead of crashing. The v2 -> v3 dashboard backfill is deleted: it was a one-shot and the deployed code already decodes v3 only. - motion: the landing trace waterfall animates with the Web Animations API. - ogl: the /compare hero drops its WebGL grain canvas; each cell keeps the flat tint and halftone it already painted underneath. --- .changeset/config.json | 2 +- apps/landing/package.json | 2 - .../src/components/compare/ComparePair.astro | 9 +- .../src/components/compare/Grainient.tsx | 397 -------------- .../src/components/compare/HubPair.astro | 2 - .../src/components/compare/PairGrainient.tsx | 83 --- .../components/live/live-waterfall.client.ts | 47 +- apps/landing/src/styles/global.css | 3 - apps/web/src/page/preload.ts | 26 +- bun.lock | 71 +-- examples/effect-todo/package.json | 2 +- lib/effect-router/package.json | 28 - lib/effect-router/src/atoms.ts | 98 ---- lib/effect-router/src/file-route.ts | 101 ---- lib/effect-router/src/index.ts | 4 - lib/effect-router/src/provider.tsx | 80 --- lib/effect-router/src/react.ts | 1 - lib/effect-router/src/route.ts | 254 --------- lib/effect-router/src/router.ts | 192 ------- lib/effect-router/tsconfig.json | 24 - package.json | 1 - .../DashboardPersistenceService.test.ts | 2 +- packages/db/package.json | 8 +- packages/db/scripts/audit-raw-sql.ts | 33 +- .../backfill-dashboard-datasource-v3.test.ts | 234 -------- .../backfill-dashboard-datasource-v3.ts | 501 ------------------ packages/db/scripts/restore-test.ts | 52 +- packages/query-engine/package.json | 1 - .../src/ch/endpoint-types.test-d.ts | 2 +- .../src/query-builder/model.test-d.ts | 2 +- 30 files changed, 118 insertions(+), 2144 deletions(-) delete mode 100644 apps/landing/src/components/compare/Grainient.tsx delete mode 100644 apps/landing/src/components/compare/PairGrainient.tsx delete mode 100644 lib/effect-router/package.json delete mode 100644 lib/effect-router/src/atoms.ts delete mode 100644 lib/effect-router/src/file-route.ts delete mode 100644 lib/effect-router/src/index.ts delete mode 100644 lib/effect-router/src/provider.tsx delete mode 100644 lib/effect-router/src/react.ts delete mode 100644 lib/effect-router/src/route.ts delete mode 100644 lib/effect-router/src/router.ts delete mode 100644 lib/effect-router/tsconfig.json delete mode 100644 packages/db/scripts/backfill-dashboard-datasource-v3.test.ts delete mode 100644 packages/db/scripts/backfill-dashboard-datasource-v3.ts diff --git a/.changeset/config.json b/.changeset/config.json index 38ef3eed45..fba4642bd1 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,6 +7,6 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["@maple/landing", "@maple/clickhouse-cli", "@effect-router/core"], + "ignore": ["@maple/landing", "@maple/clickhouse-cli"], "privatePackages": { "version": true, "tag": false } } diff --git a/apps/landing/package.json b/apps/landing/package.json index 87af0413fd..8b1ec96989 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -41,8 +41,6 @@ "d3-scale": "^4.0.2", "effect": "catalog:effect", "fuse.js": "^7.5.0", - "motion": "^14.0.0", - "ogl": "^1.0.11", "react": "catalog:react", "react-dom": "catalog:react", "tailwindcss": "catalog:tailwind", diff --git a/apps/landing/src/components/compare/ComparePair.astro b/apps/landing/src/components/compare/ComparePair.astro index 5b894f5f64..c932c96687 100644 --- a/apps/landing/src/components/compare/ComparePair.astro +++ b/apps/landing/src/components/compare/ComparePair.astro @@ -7,14 +7,12 @@ * who is being compared. Two hairline cells, each mark in its own brand * color (a vs-pairing is the one place two brand colors belong together), * the name, and the vendor's domain as a literal: no claim, no tagline. - * Each cell is washed in its side's color: a flat tint from `.pair-cell` - * under a grainy gradient canvas (`PairGrainient`, React Bits' Grainient) in the same - * hue: the page's one animated moment. + * Each cell is washed in its side's color: a flat tint and a halftone dither + * from `.pair-cell`. */ import { MapleMark } from "@maple/ui/components/icons/maple-mark"; import BrandMarkIcon from "../BrandMarkIcon.astro"; import { brandMark, markTint } from "../../lib/brand-marks"; -import { PairGrainient } from "./PairGrainient"; import type { Competitor } from "../../lib/competitors"; interface Props { @@ -25,12 +23,10 @@ const { competitor } = Astro.props; // The vendor's brand color drives its cell's dither; near-black marks tint // with the muted foreground so the field stays visible on the dark ground. const vendorColor = markTint(brandMark(competitor.mark)); -const MAPLE_AMBER = "#e8872a"; // --primary on the dark theme, as hex ---
- @@ -40,7 +36,6 @@ const MAPLE_AMBER = "#e8872a"; // --primary on the dark theme, as hex
- diff --git a/apps/landing/src/components/compare/Grainient.tsx b/apps/landing/src/components/compare/Grainient.tsx deleted file mode 100644 index fbe31bb986..0000000000 --- a/apps/landing/src/components/compare/Grainient.tsx +++ /dev/null @@ -1,397 +0,0 @@ -/** - * Grainient: React Bits' grainy gradient swirl (reactbits.dev/backgrounds/grainient), - * vendored for the /compare hero pairing. - * - * One full-screen triangle, one fragment shader, rendered through `ogl` - * (~50 KB). Departures from upstream: the WebGL context is built in a - * `useMountEffect` (the repo's escape hatch for one-time external sync) and - * props reach the uniforms from the render loop through a ref, so there is - * no second, dependency-tracked effect; no CSS file (the host positions the - * container); and `paused` freezes the clock for reduced motion. - */ -import { useMountEffect } from "@maple/ui/hooks/use-mount-effect" -import { Mesh, Program, Renderer, Triangle } from "ogl" -import { useRef } from "react" - -export interface GrainientProps { - timeSpeed?: number - colorBalance?: number - warpStrength?: number - warpFrequency?: number - warpSpeed?: number - warpAmplitude?: number - blendAngle?: number - blendSoftness?: number - rotationAmount?: number - noiseScale?: number - grainAmount?: number - grainScale?: number - grainAnimated?: boolean - contrast?: number - gamma?: number - saturation?: number - centerX?: number - centerY?: number - zoom?: number - color1?: string - color2?: string - color3?: string - lightMode?: boolean - /** Stop advancing time (the frame still renders once). */ - paused?: boolean - className?: string -} - -const hexToRgb = (hex: string): [number, number, number] => { - const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) - if (!result) return [1, 1, 1] - return [parseInt(result[1], 16) / 255, parseInt(result[2], 16) / 255, parseInt(result[3], 16) / 255] -} - -const vertex = `#version 300 es -in vec2 position; -void main() { - gl_Position = vec4(position, 0.0, 1.0); -} -` - -const fragment = `#version 300 es -precision highp float; -uniform vec2 iResolution; -uniform float iTime; -uniform float uTimeSpeed; -uniform float uColorBalance; -uniform float uWarpStrength; -uniform float uWarpFrequency; -uniform float uWarpSpeed; -uniform float uWarpAmplitude; -uniform float uBlendAngle; -uniform float uBlendSoftness; -uniform float uRotationAmount; -uniform float uNoiseScale; -uniform float uGrainAmount; -uniform float uGrainScale; -uniform float uGrainAnimated; -uniform float uContrast; -uniform float uGamma; -uniform float uSaturation; -uniform vec2 uCenterOffset; -uniform float uZoom; -uniform vec3 uColor1; -uniform vec3 uColor2; -uniform vec3 uColor3; -uniform float uLightMode; -out vec4 fragColor; -#define S(a,b,t) smoothstep(a,b,t) -mat2 Rot(float a){float s=sin(a),c=cos(a);return mat2(c,-s,s,c);} -vec2 hash(vec2 p){p=vec2(dot(p,vec2(2127.1,81.17)),dot(p,vec2(1269.5,283.37)));return fract(sin(p)*43758.5453);} -float noise(vec2 p){vec2 i=floor(p),f=fract(p),u=f*f*(3.0-2.0*f);float n=mix(mix(dot(-1.0+2.0*hash(i+vec2(0.0,0.0)),f-vec2(0.0,0.0)),dot(-1.0+2.0*hash(i+vec2(1.0,0.0)),f-vec2(1.0,0.0)),u.x),mix(dot(-1.0+2.0*hash(i+vec2(0.0,1.0)),f-vec2(0.0,1.0)),dot(-1.0+2.0*hash(i+vec2(1.0,1.0)),f-vec2(1.0,1.0)),u.x),u.y);return 0.5+0.5*n;} -void mainImage(out vec4 o, vec2 C){ - float t=iTime*uTimeSpeed; - vec2 uv=C/iResolution.xy; - float ratio=iResolution.x/iResolution.y; - vec2 tuv=uv-0.5+uCenterOffset; - tuv/=max(uZoom,0.001); - - float degree=noise(vec2(t*0.1,tuv.x*tuv.y)*uNoiseScale); - tuv.y*=1.0/ratio; - tuv*=Rot(radians((degree-0.5)*uRotationAmount+180.0)); - tuv.y*=ratio; - - float frequency=uWarpFrequency; - float ws=max(uWarpStrength,0.001); - float amplitude=uWarpAmplitude/ws; - float warpTime=t*uWarpSpeed; - tuv.x+=sin(tuv.y*frequency+warpTime)/amplitude; - tuv.y+=sin(tuv.x*(frequency*1.5)+warpTime)/(amplitude*0.5); - - vec3 colLav=uColor1; - vec3 colOrg=uColor2; - vec3 colDark=uColor3; - float b=uColorBalance; - float s=max(uBlendSoftness,0.0); - mat2 blendRot=Rot(radians(uBlendAngle)); - float blendX=(tuv*blendRot).x; - float edge0=-0.3-b-s; - float edge1=0.2-b+s; - float v0=0.5-b+s; - float v1=-0.3-b-s; - vec3 layer1=mix(colDark,colOrg,S(edge0,edge1,blendX)); - vec3 layer2=mix(colOrg,colLav,S(edge0,edge1,blendX)); - vec3 col=mix(layer1,layer2,S(v0,v1,tuv.y)); - - vec2 grainUv=uv*max(uGrainScale,0.001); - if(uGrainAnimated>0.5){grainUv+=vec2(iTime*0.05);} - float grain=fract(sin(dot(grainUv,vec2(12.9898,78.233)))*43758.5453); - col+=(grain-0.5)*uGrainAmount; - - col=(col-0.5)*uContrast+0.5; - float luma=dot(col,vec3(0.2126,0.7152,0.0722)); - col=mix(vec3(luma),col,uSaturation); - col=pow(max(col,0.0),vec3(1.0/max(uGamma,0.001))); - col=clamp(col,0.0,1.0); - if(uLightMode>0.5){ - float energy=max(max(col.r,col.g),col.b); - vec3 hue=col/max(energy,0.001); - float chroma=length(col-vec3(dot(col,vec3(0.333333)))); - float coverage=clamp(0.12+chroma*1.15+energy*0.18,0.0,0.88); - col=mix(vec3(1.0),clamp(hue*0.58+col*0.18,0.0,1.0),coverage); - } - - o=vec4(col,1.0); -} -void main(){ - vec4 o=vec4(0.0); - mainImage(o,gl_FragCoord.xy); - fragColor=o; -} -` - -interface Uniform { - value: T -} - -export default function Grainient({ - timeSpeed = 0.25, - colorBalance = 0.0, - warpStrength = 1.0, - warpFrequency = 5.0, - warpSpeed = 2.0, - warpAmplitude = 50.0, - blendAngle = 0.0, - blendSoftness = 0.05, - rotationAmount = 500.0, - noiseScale = 2.0, - grainAmount = 0.1, - grainScale = 2.0, - grainAnimated = false, - contrast = 1.5, - gamma = 1.0, - saturation = 1.0, - centerX = 0.0, - centerY = 0.0, - zoom = 0.9, - color1 = "#FF9FFC", - color2 = "#5227FF", - color3 = "#B497CF", - lightMode = false, - paused = false, - className = "", -}: GrainientProps) { - const containerRef = useRef(null) - - // The latest props, read by the render loop each frame. Assigning a few - // floats per frame is far cheaper than a dependency-tracked effect, and it - // keeps the component to one mount-scoped effect. - const propsRef = useRef>>({ - timeSpeed, - colorBalance, - warpStrength, - warpFrequency, - warpSpeed, - warpAmplitude, - blendAngle, - blendSoftness, - rotationAmount, - noiseScale, - grainAmount, - grainScale, - grainAnimated, - contrast, - gamma, - saturation, - centerX, - centerY, - zoom, - color1, - color2, - color3, - lightMode, - paused, - }) - propsRef.current = { - timeSpeed, - colorBalance, - warpStrength, - warpFrequency, - warpSpeed, - warpAmplitude, - blendAngle, - blendSoftness, - rotationAmount, - noiseScale, - grainAmount, - grainScale, - grainAnimated, - contrast, - gamma, - saturation, - centerX, - centerY, - zoom, - color1, - color2, - color3, - lightMode, - paused, - } - - useMountEffect(() => { - const container = containerRef.current - if (!container) return - // ogl's Renderer throws when the browser has no WebGL (hardware acceleration off, - // context limit, headless), and the shaders are GLSL 300 es, so WebGL1 cannot run them - // either. Keep the flat tint underneath instead. - const probe = document.createElement("canvas") - const probeGl = probe.getContext("webgl2") - if (!probeGl) return - probeGl.getExtension("WEBGL_lose_context")?.loseContext() - - const renderer = new Renderer({ - webgl: 2, - alpha: true, - antialias: false, - dpr: Math.min(window.devicePixelRatio || 1, 2), - }) - - const gl = renderer.gl - const canvas = gl.canvas as HTMLCanvasElement - canvas.style.width = "100%" - canvas.style.height = "100%" - canvas.style.display = "block" - container.appendChild(canvas) - - const geometry = new Triangle(gl) - const program = new Program(gl, { - vertex, - fragment, - uniforms: { - iTime: { value: 0 }, - iResolution: { value: new Float32Array([1, 1]) }, - uTimeSpeed: { value: 0 }, - uColorBalance: { value: 0 }, - uWarpStrength: { value: 0 }, - uWarpFrequency: { value: 0 }, - uWarpSpeed: { value: 0 }, - uWarpAmplitude: { value: 0 }, - uBlendAngle: { value: 0 }, - uBlendSoftness: { value: 0 }, - uRotationAmount: { value: 0 }, - uNoiseScale: { value: 0 }, - uGrainAmount: { value: 0 }, - uGrainScale: { value: 0 }, - uGrainAnimated: { value: 0 }, - uContrast: { value: 0 }, - uGamma: { value: 0 }, - uSaturation: { value: 0 }, - uCenterOffset: { value: new Float32Array([0, 0]) }, - uZoom: { value: 1 }, - uColor1: { value: new Float32Array([1, 1, 1]) }, - uColor2: { value: new Float32Array([1, 1, 1]) }, - uColor3: { value: new Float32Array([1, 1, 1]) }, - uLightMode: { value: 0 }, - }, - }) - const u = program.uniforms as Record> - const mesh = new Mesh(gl, { geometry, program }) - - const setVec = (name: string, values: number[]) => { - const arr = u[name].value as Float32Array - for (let i = 0; i < values.length; i++) arr[i] = values[i] - } - const syncProps = () => { - const p = propsRef.current - u.uTimeSpeed.value = p.timeSpeed - u.uColorBalance.value = p.colorBalance - u.uWarpStrength.value = p.warpStrength - u.uWarpFrequency.value = p.warpFrequency - u.uWarpSpeed.value = p.warpSpeed - u.uWarpAmplitude.value = p.warpAmplitude - u.uBlendAngle.value = p.blendAngle - u.uBlendSoftness.value = p.blendSoftness - u.uRotationAmount.value = p.rotationAmount - u.uNoiseScale.value = p.noiseScale - u.uGrainAmount.value = p.grainAmount - u.uGrainScale.value = p.grainScale - u.uGrainAnimated.value = p.grainAnimated ? 1 : 0 - u.uContrast.value = p.contrast - u.uGamma.value = p.gamma - u.uSaturation.value = p.saturation - setVec("uCenterOffset", [p.centerX, p.centerY]) - u.uZoom.value = p.zoom - setVec("uColor1", hexToRgb(p.color1)) - setVec("uColor2", hexToRgb(p.color2)) - setVec("uColor3", hexToRgb(p.color3)) - u.uLightMode.value = p.lightMode ? 1 : 0 - } - - const setSize = () => { - const rect = container.getBoundingClientRect() - const w = Math.max(1, Math.floor(rect.width)) - const h = Math.max(1, Math.floor(rect.height)) - renderer.setSize(w, h) - const res = u.iResolution.value as Float32Array - res[0] = gl.drawingBufferWidth - res[1] = gl.drawingBufferHeight - syncProps() - renderer.render({ scene: mesh }) - } - - const ro = new ResizeObserver(setSize) - ro.observe(container) - setSize() - - let raf = 0 - let isVisible = true - let isPageVisible = !document.hidden - const t0 = performance.now() - - const loop = (t: number) => { - syncProps() - // Paused (reduced motion): the clock holds, the frame still renders - // so a color change shows. - if (!propsRef.current.paused) u.iTime.value = (t - t0) * 0.001 - renderer.render({ scene: mesh }) - raf = requestAnimationFrame(loop) - } - - const tryStart = () => { - if (isVisible && isPageVisible && raf === 0) raf = requestAnimationFrame(loop) - } - const tryStop = () => { - if (raf !== 0) { - cancelAnimationFrame(raf) - raf = 0 - } - } - - const io = new IntersectionObserver( - ([entry]) => { - isVisible = entry.isIntersecting - if (isVisible) tryStart() - else tryStop() - }, - { threshold: 0 }, - ) - io.observe(container) - - const onVisibility = () => { - isPageVisible = !document.hidden - if (isPageVisible) tryStart() - else tryStop() - } - document.addEventListener("visibilitychange", onVisibility) - - tryStart() - - return () => { - tryStop() - ro.disconnect() - io.disconnect() - document.removeEventListener("visibilitychange", onVisibility) - canvas.remove() - } - }) - - return
-} diff --git a/apps/landing/src/components/compare/HubPair.astro b/apps/landing/src/components/compare/HubPair.astro index 0d806aacd5..58df94b79c 100644 --- a/apps/landing/src/components/compare/HubPair.astro +++ b/apps/landing/src/components/compare/HubPair.astro @@ -7,14 +7,12 @@ import { MapleMark } from "@maple/ui/components/icons/maple-mark"; import BrandMarkIcon from "../BrandMarkIcon.astro"; import { comparePath, competitors } from "../../lib/competitors"; -import { PairGrainient } from "./PairGrainient"; const locale = Astro.currentLocale ?? "en"; ---
- diff --git a/apps/landing/src/components/compare/PairGrainient.tsx b/apps/landing/src/components/compare/PairGrainient.tsx deleted file mode 100644 index eaa26d1c0b..0000000000 --- a/apps/landing/src/components/compare/PairGrainient.tsx +++ /dev/null @@ -1,83 +0,0 @@ -/** - * PairGrainient: the grainy gradient behind one cell of the /compare logo - * pairing, in that side's brand color. - * - * Wraps React Bits' `Grainient` with Maple's tokens. The three stops are the - * brand color, the brand color pulled toward the page ground, and the - * ground itself, so the swirl is one hue fading into the page rather than a - * poster. Motion is slow and stops under `prefers-reduced-motion`. - * - * Mounted `client:only`: a WebGL canvas has no useful server render, and the - * `.pair-cell` flat tint underneath is the ground until it appears. - */ -import { useState } from "react" -import Grainient from "./Grainient" - -/** `--background` on the dark theme. */ -const GROUND = "#1a1714" - -const hexToRgb = (hex: string): [number, number, number] => { - const n = parseInt(hex.replace("#", ""), 16) - return [(n >> 16) & 255, (n >> 8) & 255, n & 255] -} - -const toHex = ([r, g, b]: [number, number, number]) => - `#${[r, g, b] - .map((c) => - Math.round(Math.max(0, Math.min(255, c))) - .toString(16) - .padStart(2, "0"), - ) - .join("")}` - -/** `color` pulled `keep` of the way from the ground (0 = ground, 1 = color). */ -const towardGround = (color: string, keep: number): string => { - const a = hexToRgb(GROUND) - const b = hexToRgb(color) - return toHex([a[0] + (b[0] - a[0]) * keep, a[1] + (b[1] - a[1]) * keep, a[2] + (b[2] - a[2]) * keep]) -} - -interface Props { - /** Brand color as a hex literal, e.g. "#632CA6". */ - color: string - /** How much of the brand color survives at the brightest stop, 0–1. */ - strength?: number -} - -export function PairGrainient({ color, strength = 0.7 }: Props) { - const [reduced] = useState( - () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches, - ) - - return ( -