Files
zemion ed030cada6
Verify / verify (push) Canceled after 0s
Release Colour Tools 0.2.0
2026-09-02 07:11:11 +02:00

4.4 KiB
Raw Permalink Blame History

Architecture

Colour Tools is a client-only React application built as relocatable static files. The UI and calculation engine are intentionally separated so colour operations can be tested without a browser and UI state can keep showing the last valid result while an input is incomplete.

Layers

  1. src/colour/ is the serialisable colour domain. It parses and formats colours, converts gamuts, composites layers, interpolates stops, evaluates contrast and Delta E, simulates colour-vision deficiencies, builds CSS gradients, imports DTCG tokens, and builds or exports palettes. Its public API is re-exported from src/colour/index.ts.
  2. src/palette/ contains browser-independent raster bounds, sampling and deterministic OKLab clustering. src/workers/palette.worker.ts exposes the expensive extraction path to a dedicated worker.
  3. src/components/ contains the seven workspaces and shared accessible controls. Workspace selection is represented by a URL fragment, so a view can be bookmarked without router or server support.
  4. src/hooks/ owns bounded device-local UI persistence. Image bytes are not stored there.
  5. src/toolbox/ contains the checked manifest identity. The shared Toolbox shell supplies navigation, contextual actions and theme behaviour without changing the standalone application domain.

Colour values

The engine's ColourValue is a plain object: colour-space identifier, three numeric coordinates and alpha. It deliberately carries coordinates that may sit outside a display gamut. Color.js 0.7.1 supplies standards-aligned parsing and conversion primitives; Colour Tools wraps these in typed, bounded domain operations and stable UI formats.

Browser preview is a separate operation. It maps a value to sRGB and reports whether mapping occurred. This keeps display limitations from mutating the source colour used by later conversions or comparisons.

dtcg.ts walks at most 32 group levels/10,000 tokens, validates DTCG 2025.10 structured colour components, resolves local curly aliases and local JSON Pointer $ref token/property references with cycle detection, and resolves token type from the token, its nearest group or its reference. It does not infer a missing type. Numeric none semantics cannot be represented by ColourValue, so such tokens produce an explicit diagnostic. Imported wide-gamut coordinates are stored as CSS rather than being destructively mapped to the preview gamut.

accessibility.ts parses a maximum of 64 palette colours once before its bounded 64×64 directional contrast loop. Each foreground/background cell reports WCAG ratio thresholds after flattening transparency against a stated canvas. gradient.ts validates 264 ascending stops and exports inert CSS plus a schema-versioned recipe for linear, radial, conic and repeating syntax.

Raster pipeline

The image picker validates the selected file before decode, rejects excessive bytes/dimensions/pixels, then draws the decoded image to a same-origin in-memory Canvas 2D surface. Sampling reads a bounded neighbourhood. Palette extraction subsamples deterministically, converts points to OKLab and clusters them with a fixed initialization and iteration bound. The worker client can fall back to the same pure function when workers are unavailable.

Temporary object URLs are revoked and outstanding extraction is aborted when an image is replaced or removed. No image or extracted palette is transmitted.

Build and deployment

Vite builds with a relative base. scripts/generate-toolbox-manifest.mjs checks package, application and Toolbox versions plus immutable source identity. scripts/prepare-release-files.mjs places project documentation and the exact installed runtime licence inventory beside the executable app.

The service worker is relative-scope and deployment-subpath aware. It is progressive enhancement: the app remains usable when registration is rejected. The deterministic packager rejects symbolic links, source maps, secret-like filenames and root-absolute asset references before creating the release ZIP and SHA-256 sidecar.

Testing boundaries

Unit tests cover parsing, numerical operations, invalid inputs, raster bounds, sampling and palette determinism. Browser smoke tests run the production build under a restrictive policy at /deep/nested/colour/, exercise all major workspaces and fail on uncaught errors or external network requests. The Toolbox contract checker validates the static artifact independently.