{"_id":"@ateliercartographie/ok-palette","_rev":"4-52c393cc17bf6dd3a11f2ebeb96944c5","name":"@ateliercartographie/ok-palette","dist-tags":{"latest":"0.1.4"},"versions":{"0.1.0":{"name":"@ateliercartographie/ok-palette","version":"0.1.0","keywords":["color","palette","dataviz","cartography","oklch","sequential","divergent","categorical","pattern","motif"],"author":{"name":"Atelier de cartographie de Sciences Po"},"license":"ISC","_id":"@ateliercartographie/ok-palette@0.1.0","maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"homepage":"https://github.com/AtelierCartographie/ok-palette#readme","bugs":{"url":"https://github.com/AtelierCartographie/ok-palette/issues"},"dist":{"shasum":"8a91faa16962a426f573ca1e8a13ecc8209f73de","tarball":"https://registry.npmjs.org/@ateliercartographie/ok-palette/-/ok-palette-0.1.0.tgz","fileCount":14,"integrity":"sha512-XrNJg8O8MwN5bphLRa1+JxiuRahit4opVsNZTEaOMOg2lWT2lMh5yvnaF97ZMOddL7yJ0g9ZNsdm2nZtKiEX2A==","signatures":[{"sig":"MEYCIQDVfxFjbroGBgeDxiM93lMVLEkjdYSYqZBD1x9QXukWzAIhAMhyXbBZLr8MfuJkAq2GAblrrX6zmPeBAVdPT8pGUKl5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41505},"main":"./dist/ok-palette.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/ok-palette.js","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/ok-palette.js","require":"./dist/ok-palette.cjs"}},"gitHead":"cc60e3aede410e577c6eff9c2a17edc248facaaf","scripts":{"dev":"vite serve demo","build":"tsc --noEmit && vite build && tsc --declaration --emitDeclarationOnly","preview":"vite preview","release:major":"npm version major && git push && git push --tags","release:minor":"npm version minor && git push && git push --tags","release:patch":"npm version patch && git push && git push --tags"},"_npmUser":{"name":"tombor","email":"thomas2ansart@gmail.com"},"repository":{"url":"git+https://github.com/AtelierCartographie/ok-palette.git","type":"git"},"_npmVersion":"10.9.2","description":"Générateur de palettes de couleurs séquentielles, divergentes et catégorielles pour la dataviz et la cartographie","directories":{},"_nodeVersion":"22.19.0","_hasShrinkwrap":false,"packageManager":"pnpm@10.17.1","devDependencies":{"vite":"^7.3.1","typescript":"^5.9.3","@ateliercartographie/motif.js":"^0.1.4"},"_npmOperationalInternal":{"tmp":"tmp/ok-palette_0.1.0_1772638982997_0.31425596182892646","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@ateliercartographie/ok-palette","version":"0.1.2","keywords":["color","palette","dataviz","cartography","oklch","sequential","divergent","categorical","pattern","motif"],"author":{"name":"Atelier de cartographie de Sciences Po"},"license":"ISC","_id":"@ateliercartographie/ok-palette@0.1.2","maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"homepage":"https://github.com/AtelierCartographie/ok-palette#readme","bugs":{"url":"https://github.com/AtelierCartographie/ok-palette/issues"},"dist":{"shasum":"7b32d459f14dd7012c955823d6308b8c108271f6","tarball":"https://registry.npmjs.org/@ateliercartographie/ok-palette/-/ok-palette-0.1.2.tgz","fileCount":14,"integrity":"sha512-eiY9e4p9XGA/UXqy9cRWF4159ObylgtFEMHvL+rbq0/sa06kHgcHcI9Mh7bYd6R9L6U6Fkw5tEKD9JLlgIuI+A==","signatures":[{"sig":"MEQCIEyg8pzLCmUBssFn9wG+LoHH6WpfcqAUKMNpITYgjwiMAiAu3e27oIIwjAl6bLWSk8O5/eInIEuNr6pgH6GFb5M4cQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ateliercartographie%2fok-palette@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":41505},"main":"./dist/ok-palette.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/ok-palette.js","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/ok-palette.js","require":"./dist/ok-palette.cjs"}},"gitHead":"6adcca2422615d06207bcbce39584820710df790","scripts":{"dev":"vite serve demo","build":"tsc --noEmit && vite build && tsc --declaration --emitDeclarationOnly","preview":"vite preview","release:major":"npm version major && git push && git push --tags","release:minor":"npm version minor && git push && git push --tags","release:patch":"npm version patch && git push && git push --tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:06c14c5c-1734-452a-a644-bcbfeb5d29fc"}},"repository":{"url":"git+https://github.com/AtelierCartographie/ok-palette.git","type":"git"},"_npmVersion":"11.8.0","description":"Générateur de palettes de couleurs séquentielles, divergentes et catégorielles pour la dataviz et la cartographie","directories":{},"_nodeVersion":"24.13.1","_hasShrinkwrap":false,"packageManager":"pnpm@10.17.1","devDependencies":{"vite":"^7.3.1","typescript":"^5.9.3","@ateliercartographie/motif.js":"^0.1.4"},"_npmOperationalInternal":{"tmp":"tmp/ok-palette_0.1.2_1772639221366_0.817299596372109","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@ateliercartographie/ok-palette","version":"0.1.3","keywords":["color","palette","dataviz","cartography","oklch","sequential","divergent","categorical","pattern","motif"],"author":{"name":"Atelier de cartographie de Sciences Po"},"license":"ISC","_id":"@ateliercartographie/ok-palette@0.1.3","maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"homepage":"https://github.com/AtelierCartographie/ok-palette#readme","bugs":{"url":"https://github.com/AtelierCartographie/ok-palette/issues"},"dist":{"shasum":"e6ef709adfb5c9348da9bad619b781e0c797f7d6","tarball":"https://registry.npmjs.org/@ateliercartographie/ok-palette/-/ok-palette-0.1.3.tgz","fileCount":14,"integrity":"sha512-8svGeruYoyjAGuLN4OAXI0hEJOlWFefxkO5/aiBmmxcAAok9W0KB3aXvamRxjZrMxWFU6zBHwnba0hRjMg7JJA==","signatures":[{"sig":"MEUCIF3UOj49hMvUvwIzPos6qJ1Qa+3gzOK1FYGJSttYGIdsAiEAgD8Zcru/l5nW1gvbcMbtfoUDbfx0nytW7nIJET1ANrY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ateliercartographie%2fok-palette@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":42802},"main":"./dist/ok-palette.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/ok-palette.js","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/ok-palette.js","require":"./dist/ok-palette.cjs"}},"gitHead":"9dc968735c555f811852d31f1043cb279b3d320c","scripts":{"dev":"vite serve demo","build":"tsc --noEmit && vite build && tsc --declaration --emitDeclarationOnly","preview":"vite preview","release:major":"npm version major && git push && git push --tags","release:minor":"npm version minor && git push && git push --tags","release:patch":"npm version patch && git push && git push --tags"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:06c14c5c-1734-452a-a644-bcbfeb5d29fc"}},"repository":{"url":"git+https://github.com/AtelierCartographie/ok-palette.git","type":"git"},"_npmVersion":"11.9.0","description":"Générateur de palettes de couleurs séquentielles, divergentes et catégorielles pour la dataviz et la cartographie","directories":{},"_nodeVersion":"24.14.0","_hasShrinkwrap":false,"packageManager":"pnpm@10.17.1","devDependencies":{"vite":"^7.3.1","typescript":"^5.9.3","@ateliercartographie/motif.js":"^0.1.4"},"_npmOperationalInternal":{"tmp":"tmp/ok-palette_0.1.3_1772698433940_0.9209241926844967","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@ateliercartographie/ok-palette","version":"0.1.4","description":"Générateur de palettes de couleurs séquentielles, divergentes et catégorielles pour la dataviz et la cartographie","type":"module","main":"./dist/ok-palette.cjs","module":"./dist/ok-palette.js","types":"./dist/src/index.d.ts","exports":{".":{"types":"./dist/src/index.d.ts","import":"./dist/ok-palette.js","require":"./dist/ok-palette.cjs"}},"scripts":{"dev":"vite serve demo","build":"tsc --noEmit && vite build && tsc --declaration --emitDeclarationOnly","preview":"vite preview","release:patch":"npm version patch && git push && git push --tags","release:minor":"npm version minor && git push && git push --tags","release:major":"npm version major && git push && git push --tags"},"keywords":["color","palette","dataviz","cartography","oklch","sequential","divergent","categorical","pattern","motif"],"author":{"name":"Atelier de cartographie de Sciences Po"},"license":"ISC","repository":{"type":"git","url":"git+https://github.com/AtelierCartographie/ok-palette.git"},"packageManager":"pnpm@10.17.1","devDependencies":{"@ateliercartographie/motif.js":"^0.1.4","typescript":"^5.9.3","vite":"^7.3.1"},"gitHead":"3e242df9b5d4a490df57ab757fba27783c07d0ce","_id":"@ateliercartographie/ok-palette@0.1.4","bugs":{"url":"https://github.com/AtelierCartographie/ok-palette/issues"},"homepage":"https://github.com/AtelierCartographie/ok-palette#readme","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-HSLgx0l1zAIKXkHdAM9/jujZZXe85FFHdspMwWD1GZY7W55zRR5zKxMblTf2ToXchtSMtegG1Fanqw645Zpr4w==","shasum":"3e2e3428b5ebfeb9283b1b23a0bbf40a1358e040","tarball":"https://registry.npmjs.org/@ateliercartographie/ok-palette/-/ok-palette-0.1.4.tgz","fileCount":14,"unpackedSize":43299,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ateliercartographie%2fok-palette@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICt5zbIEri+rJ9L0QYKv7QFZ+h2FOtuHblbXbi6+70G4AiEA0h4h3Z+UFaoj3xd2K1U/05tx2gQ3lDJZ2MdD8lkRLAU="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:06c14c5c-1734-452a-a644-bcbfeb5d29fc"}},"directories":{},"maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ok-palette_0.1.4_1772702976982_0.31989485118197947"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-04T15:43:02.936Z","modified":"2026-03-05T09:29:37.433Z","0.1.0":"2026-03-04T15:43:03.146Z","0.1.2":"2026-03-04T15:47:01.535Z","0.1.3":"2026-03-05T08:13:54.084Z","0.1.4":"2026-03-05T09:29:37.146Z"},"bugs":{"url":"https://github.com/AtelierCartographie/ok-palette/issues"},"author":{"name":"Atelier de cartographie de Sciences Po"},"license":"ISC","homepage":"https://github.com/AtelierCartographie/ok-palette#readme","keywords":["color","palette","dataviz","cartography","oklch","sequential","divergent","categorical","pattern","motif"],"repository":{"type":"git","url":"git+https://github.com/AtelierCartographie/ok-palette.git"},"description":"Générateur de palettes de couleurs séquentielles, divergentes et catégorielles pour la dataviz et la cartographie","maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"readme":"# @ateliercartographie/ok-palette\n\nColor palette generator for **sequential, diverging, and categorical** schemes for **data visualization** and **cartography**. Also generates **pattern palettes** compatible with [@ateliercartographie/motif.js](https://github.com/AtelierCartographie/motif.js).\n\nZero dependencies. Relies entirely on modern browser CSS capabilities (`oklch`, `color-mix()`) to guarantee perceptually uniform results.\n\n**Created by:** [Thomas Ansart — Atelier de cartographie de Sciences Po](https://www.sciencespo.fr/cartographie/)  \n**License:** ISC\n\n## Installation\n\n```bash\npnpm add @ateliercartographie/ok-palette\n```\n\n## Quick start\n\n```ts\nimport {\n  sequential,\n  divergent,\n  divergentSequential,\n  categorical,\n  categoricalPatterns,\n  sequentialPatterns,\n  resolveColor,\n  resolvePalette,\n  presets,\n  temperature,\n} from \"@ateliercartographie/ok-palette\";\n\n// 5-class monochrome sequential palette\nconst mono = sequential({ colorStart: \"steelblue\" });\n\n// 7-class two-tone sequential palette, high contrast\nconst biTone = sequential({\n  colorStart: \"#f4e285\",\n  colorEnd: \"#1d3557\",\n  steps: 7,\n  contrast: \"high\",\n});\n\n// Symmetric diverging palette (3+3 classes)\nconst div = divergent({ colorA: \"#3b4cc0\" });\n\n// Asymmetric diverging palette, oklch interpolation\nconst divLch = divergent({\n  colorA: \"#d7191c\",\n  colorB: \"#2b83ba\",\n  steps: [5, 2],\n  contrast: \"high\",\n  colorSpace: \"oklch\",\n});\n\n// Diverging palette built as two mirrored sequential palettes\nconst divSeq = divergentSequential({ colorA: \"steelblue\" });\n\n// 8-color vivid categorical palette\nconst colors = categorical(8, presets.vif);\n\n// Warm categorical palette with hue offset\nconst warm = categorical(6, {\n  ...presets.vif,\n  ...temperature.chaude,\n  hueOffset: 30,\n});\n\n// Categorical patterns for motif.js\nconst patterns = categoricalPatterns(6);\n\n// Sequential patterns (size progressively increases with contrast)\nconst seqPatterns = sequentialPatterns(5, { shape: \"line\", contrast: \"high\" });\n\n// Resolve CSS colors to usable values\nconst css = resolvePalette(mono); // string[]\nconst webgl = resolvePalette(mono, { format: \"webgl\" }); // [r,g,b,a][]\n```\n\n## API\n\n### `sequential(options)`\n\nGenerates a sequential palette (monochrome or two-tone).\n\n| Option       | Type                          | Default      | Description                                         |\n| ------------ | ----------------------------- | ------------ | --------------------------------------------------- |\n| `colorStart` | `string`                      | —            | CSS start color (light tones)                       |\n| `colorEnd`   | `string?`                     | `colorStart` | CSS end color (dark tones). If omitted → monochrome |\n| `steps`      | `number`                      | `5`          | Number of classes (2–12)                            |\n| `contrast`   | `\"low\" \\| \"normal\" \\| \"high\"` | `\"normal\"`   | Contrast profile                                    |\n\n**Returns** `string[]` — CSS colors `color-mix(in oklch, …)`.\n\n#### How it works\n\nThe start color is normalized to a light tone (chroma halved to avoid a fluorescent effect), the end color to a dark tone. The lightness range is automatically adapted to the number of classes via the contrast profile, inspired by ColorBrewer palette analysis:\n\n- **3 classes** → ~30% lightness gap\n- **9 classes** → ~70% lightness gap\n\nInterpolation is entirely delegated to the browser via `color-mix(in oklch, …)`: no color library needed.\n\n### `divergent(options)`\n\nGenerates a diverging (bipolar) palette around a tinted pivot.\n\n| Option           | Type                          | Default                | Description                      |\n| ---------------- | ----------------------------- | ---------------------- | -------------------------------- |\n| `colorA`         | `string`                      | —                      | Left-extreme CSS color           |\n| `colorB`         | `string?`                     | complement of `colorA` | Right-extreme CSS color          |\n| `steps`          | `[number, number]`            | `[3, 3]`               | Classes per side `[left, right]` |\n| `contrast`       | `\"low\" \\| \"normal\" \\| \"high\"` | `\"normal\"`             | Contrast profile                 |\n| `hasCenterClass` | `boolean`                     | `false`                | Add a neutral center class       |\n| `colorSpace`     | `\"oklab\" \\| \"oklch\"`          | `\"oklab\"`              | Ramp interpolation color space   |\n\n**Returns** `string[]` — CSS colors.\n\n#### How it works\n\nBoth extremes converge toward an automatically derived **tinted pivot**: the OkLab midpoint of light, highly-desaturated variants of A and B. Because A and B are opposite on the hue wheel, their components almost cancel in OkLab, producing a quasi-neutral, slightly-tinted tone — visually integrated rather than a foreign grey.\n\n- `colorSpace: \"oklab\"` (default): Cartesian path — smoother, avoids hue artifacts\n- `colorSpace: \"oklch\"`: circular path on the hue wheel — more saturated at the center\n\n```ts\n// Default symmetric palette (7 classes: 3 + 3)\ndivergent({ colorA: \"#3b4cc0\" });\n\n// Asymmetric, high contrast, oklch interpolation\ndivergent({\n  colorA: \"#d7191c\",\n  colorB: \"#2b83ba\",\n  steps: [5, 2],\n  contrast: \"high\",\n  colorSpace: \"oklch\",\n});\n\n// With a center class (3 + 1 + 3 classes)\ndivergent({ colorA: \"steelblue\", steps: [3, 3], hasCenterClass: true });\n```\n\n### `divergentSequential(options)`\n\nGenerates a diverging palette built as two mirrored `sequential()` calls — guarantees full consistency with the sequential palette.\n\nAccepts the same options as `divergent()` **except** `colorSpace` (interpolation is always oklch, as in `sequential`).\n\n| Option           | Type                          | Default    | Description                |\n| ---------------- | ----------------------------- | ---------- | -------------------------- |\n| `colorA`         | `string`                      | —          | Left-extreme color         |\n| `colorB`         | `string?`                     | complement | Right-extreme color        |\n| `steps`          | `[number, number]`            | `[3, 3]`   | Classes per side           |\n| `contrast`       | `\"low\" \\| \"normal\" \\| \"high\"` | `\"normal\"` | Contrast profile           |\n| `hasCenterClass` | `boolean`                     | `false`    | Add a neutral center class |\n\n**Returns** `string[]` — CSS colors.\n\n```ts\n// Rigorously identical to two mirrored `sequential` calls\ndivergentSequential({ colorA: \"#3b4cc0\" });\n\n// Asymmetric with a center class\ndivergentSequential({\n  colorA: \"#d7191c\",\n  colorB: \"#2b83ba\",\n  steps: [5, 2],\n  hasCenterClass: true,\n});\n```\n\n### `categorical(count, options?)`\n\nGenerates a categorical color palette.\n\n| Option           | Type               | Default        | Description                        |\n| ---------------- | ------------------ | -------------- | ---------------------------------- |\n| `hueRange`       | `[number, number]` | `[0, 360]`     | Hue range in degrees               |\n| `hueOffset`      | `number`           | `0`            | Hue rotation applied to all colors |\n| `chromaRange`    | `[number, number]` | `[0.15, 0.25]` | Oklch chroma range                 |\n| `lightnessRange` | `[number, number]` | `[0.5, 0.75]`  | Oklch lightness range, values 0–1  |\n\n**Returns** `string[]` — CSS colors `oklch(…)`.\n\n#### Presets\n\n```ts\npresets.vif; // Saturated, vivid colors\npresets.pastel; // Soft, light colors\npresets.sepia; // Warm, desaturated tones\n```\n\n#### Temperature filters\n\n```ts\ntemperature.mixte; // Full hue wheel\ntemperature.chaude; // Reds, oranges, yellows\ntemperature.froide; // Greens, blues, purples\n```\n\nCombining: `categorical(8, { ...presets.vif, ...temperature.chaude })`\n\n#### Van der Corput sequence\n\nHue distribution relies on the [Van der Corput sequence](https://en.wikipedia.org/wiki/Van_der_Corput_sequence) in base 2. It always fills the largest gap on the hue wheel, guaranteeing maximum distance between colors regardless of count.\n\nThis approach is non iterative. Performance is independent of class count and very fast (~4ms in modern browsers).\n\n### `categoricalPatterns(count, options?)`\n\nGenerates categorical pattern parameters compatible with [@ateliercartographie/motif.js](https://github.com/AtelierCartographie/motif.js).\n\n| Option       | Type                                 | Default                                   | Description                                  |\n| ------------ | ------------------------------------ | ----------------------------------------- | -------------------------------------------- |\n| `shapes`     | `string[]`                           | `[\"line\", \"circle\", \"plaid\", \"triangle\"]` | Shapes to cycle through                      |\n| `angleRange` | `[number, number]`                   | `[0, 180]`                                | Angle range (degrees)                        |\n| `scaleRange` | `[number, number]`                   | `[2, 8]`                                  | Scale range                                  |\n| `size`       | `number`                             | `10`                                      | Fixed size                                   |\n| `fill`       | `string`                             | `\"#000000\"`                               | Fill color                                   |\n| `background` | `string`                             | `\"#ffffff\"`                               | Background color                             |\n| `patchSize`  | `boolean`                            | `true`                                    | Enable patchSize                             |\n| `vdcOffset`  | `number`                             | `0`                                       | Van der Corput offset                        |\n| `colorize`   | `boolean \\| CategoricalColorOptions` | `false`                                   | Auto-colorize pattern fill via `categorical` |\n\n**Returns** `PatternParams[]`\n\n#### How it works\n\nPattern variation combines three complementary mechanisms so classes stay distinct without looking purely random:\n\n- **Shape**: forms are assigned by cycling through `shapes` (`i % shapes.length`) to guarantee balanced reuse when `count` exceeds the shape list.\n- **Scale**: values oscillate between `scaleRange[0]` and `scaleRange[1]` (triangle-wave style), creating contrast while avoiding monotonic growth that could suggest an ordered scale.\n- **Angle**: orientation is sampled with the Van der Corput sequence, but independently **within each shape group**. In practice, each shape gets its own low-discrepancy angle stream, which spreads angles evenly and prevents two identical shapes from clustering around similar directions.\n\n### `sequentialPatterns(count, options?)`\n\nGenerates sequential pattern parameters compatible with [@ateliercartographie/motif.js](https://github.com/AtelierCartographie/motif.js).\n\nPattern **size** increases monotonically across classes, analogous to the lightness range in sequential color palettes. The size range is adapted to both the class count and the contrast profile.\n\nThe shape is fixed to preserve the perception of order.\n\n| Option       | Type                          | Default     | Description               |\n| ------------ | ----------------------------- | ----------- | ------------------------- |\n| `shape`      | `string`                      | `\"line\"`    | Pattern shape             |\n| `sizeRange`  | `[number, number]`            | `[4, 14]`   | Size range [small, large] |\n| `angle`      | `number`                      | `45`        | Fixed angle (degrees)     |\n| `scale`      | `number`                      | `4`         | Fixed scale               |\n| `contrast`   | `\"low\" \\| \"normal\" \\| \"high\"` | `\"normal\"`  | Contrast profile          |\n| `fill`       | `string`                      | `\"#000000\"` | Fill color                |\n| `background` | `string`                      | `\"#ffffff\"` | Background color          |\n| `patchSize`  | `boolean`                     | `true`      | Enable patchSize          |\n\n**Returns** `PatternParams[]`\n\n### `resolveColor(color, options?)`\n\nResolves a complex CSS color (`color-mix(…)`, `oklch(from …)`, etc.) to a usable value.\n\n- `{ format: \"css\" }` (default) → `string` as computed by the browser\n- `{ format: \"webgl\" }` → `[r, g, b, a]` (0–255)\n\n#### How it works\n\n`resolveColor` delegates parsing and evaluation to the browser color engine: the input is applied to a temporary element/canvas context, then read back as a computed color.\n\nThis ensures full support for modern CSS color syntax (`oklch`, relative colors, `color-mix()`) without external dependencies and with behavior aligned to real rendering engines. The function then normalizes the result either as a CSS color string (`css`) or as a WebGL-ready numeric tuple (`webgl`).\n\n### `resolvePalette(colors, options?)`\n\nApplies `resolveColor` to an entire array of colors.\n\n## Why this approach?\n\n### Problem 1 — Color space\n\nThe choice of interpolation space dramatically changes the result. Using **oklch** guarantees perceptually uniform steps across each component (lightness, chroma, hue). As of 2025, oklch is supported by all modern browsers.\n\n### Problem 2 — Lightness range\n\nA sequential palette only works if the lightness gap between the first and last color is sufficient and adapted to the number of classes. This library automatically normalizes input colors to guarantee a readable result.\n\n### Solution\n\n- **Universal**: normalizes any CSS color before generating the palette\n- **Modern**: zero dependencies, relies on native `oklch` and `color-mix()`\n- **Performant**: the Van der Corput sequence generates categorical palettes in constant time, unlike iterative approaches like I Want Hue\n\n## Development\n\n```bash\n# Start the demo page\npnpm dev\n\n# Build the library\npnpm build\n```\n\n## License\n\nISC — Atelier de cartographie de Sciences Po\n\n## Resources\n\n- [Chroma.js](https://gka.github.io/chroma.js) — Documentation\n- [Chroma.js Color Palette Helper](https://gka.github.io/palettes)\n- [MDN — `color-mix()`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/color-mix)\n- [ColorBrewer](https://colorbrewer2.org/)\n- [Mastering Multi-hued Color Scales](https://www.vis4.net/blog/mastering-multi-hued-color-scales/) — Gregor Aisch\n- [Van der Corput sequence](https://en.wikipedia.org/wiki/Van_der_Corput_sequence)\n- [@ateliercartographie/motif.js](https://github.com/AtelierCartographie/motif.js)\n","readmeFilename":"README.md"}