Repository navigation
feat(core): tuple and typed-array interop for GPU and three.js - #202
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fb19a6df41
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
eca3ad1 to
ee33734
Compare
fb19a6d to
545cbfa
Compare
Stack 2/4. Adds `out`-first, allocation-free `*Into` variants (conversions, low-level kernels, `mixInto`/`interpolateInto`, `toSrgbGamutInto`/`toP3GamutInto`). Allocating APIs become thin wrappers over the kernels — bit-identical (0 mismatches, 100k inputs × 30 functions). - `bench:into`: Into variants ~0 B/op, 0 GCs per 1e6 ops (vs up to 28); ns/op roughly equal. - Side benefit: existing gamut mapping 20–28% faster, `toRgb`/`toP3` allocate 1 object instead of 4. - A React ColorPlane CPU-loop dogfood was measured and **dropped**: fewer GCs but clamp paths 8–10% slower (V8 boxes doubles in object fields). **Recommendation: adopt in addition** — object API stays primary; Into reduces GC count, not time. Typed arrays (#202) are the better zero-alloc per-pixel target. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add a `color-kit/interop` module (also exported from the root) with allocation-free array writers and readers for linearSrgb, srgb, linearP3, p3, oklab and oklch, `*Array4` variants that carry alpha, and `packColors`/`unpackColors` for strided GPU buffers. Writers emit unclamped floats by default (matching three.js and HDR pipelines); `clamp` clips RGB channels and `gamutMap` reuses toSrgbGamut/toP3Gamut. Exports `ColorTuple`/`ColorTuple4`. Tests cover round trips, offset/stride math, Float32Array precision, clamp/gamutMap, colorjs.io agreement for every space, and the three.js `Color.fromArray` recipe against the real `three` package (devDependency). Co-Authored-By: Claude Opus 5.5 <[email protected]>
…omposition The option pulled the gamut-mapping solver (~1 kB gzip) into every array writer. Callers now compose instead: `toLinearSrgbArray(toSrgbGamut(c), out)` or `packColors(colors.map(toSrgbGamut), space)`. `clamp` stays. toLinearSrgbArray drops from 1.62 kB to 617 B gzip; packColors + unpackColors from 2.73 kB to 2.23 kB. Size budgets lowered to ~15% above. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Split packColors into overloads: no `out` (or `undefined`) returns `Float32Array`, and a provided `out` returns its own type. Previously an explicit `undefined` with options inferred `WritableArrayLike`, so `.subarray` did not type-check. Locked in interop.typecheck.ts. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Nothing ran tsc over `packages/*/src`: tsup only emits declarations for the public entries and vitest does not typecheck, so the type-level assertions in `core/src/interop/interop.typecheck.ts`, `core/src/plane/define-plane.typecheck.ts` and `driver/src/color-input.typecheck.ts` were never checked. Add a `typecheck` script (`tsc --noEmit`) to core and driver, a root `pnpm typecheck` that runs it recursively, and a CI step in the build-and-test job. Verified that removing a `@ts-expect-error` in either core file makes `pnpm typecheck` fail. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Passing `out: T | undefined` (for example a lazily created `Float32Array | undefined` scratch buffer) to `packColors` or any `to*Array` writer failed with TS2769, because the split overloads only accepted `undefined` or `T`. Add a third overload per function that takes `T | undefined` and returns exactly `T | Float32Array` (packColors) or `T | ColorTuple` / `T | ColorTuple4` (writers). interop.typecheck.ts now asserts the exact result types with an `Equal` helper for the union, absent and present cases. Without the new overloads those assertions fail to compile. Co-Authored-By: Claude Opus 5.5 <[email protected]>
1b6a929 to
626c845
Compare
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Stack 4/4. New guide at `/docs/guides/graphics-and-performance` (new Guides nav section) demonstrating #200–#202 with live demos, API examples, comparisons to existing APIs and pmndrs/math, and adopt-in-addition vs replace recommendations. - Linear-mix demo: pickers/presets, per-space gradient strips, midpoint hex / OKLab L / Y / out-of-sRGB flag. - `mixInto` rAF loop with frame counter (reduced-motion aware). - WebGL2 quad colored via `packColors` (linear vs gamma blending, packed floats shown). - Code shown is the demo source (`?raw`), demos lazy-loaded per chunk. Verified in browser: no console errors, interactions work, 375px no horizontal scroll. Docs tsc errors on this branch are only the 4 pre-existing home-route errors fixed by #199. 🤖 Generated with [Claude Code](https://claude.com/claude-code)

Stack 3/4. New
interopmodule (root +color-kit/interop):to<Space>Array(color, out?, offset, { clamp? })/*Array4writers,from<Space>Arrayreaders for linearSrgb, srgb, linearP3, p3, oklab, oklch;packColors/unpackColorsfor GPU buffers (stride/offset, WGSL vec3 padding).toLinearSrgbArray(toSrgbGamut(c))).new Color().fromArray(toLinearSrgbArray(c))is exact and unclamped;setStyle(toCss(c))quantizes to 8-bit and clips.toLinearSrgbArray617 B gzip; pack+unpack 2.3 kB; everyday import unchanged. New size budgets.Recommendation: adopt in addition —
toRgb/toP3/toCssstay for UI/CSS; arrays for GPU/three.js/HDR.🤖 Generated with Claude Code