{"_id":"@ateliercartographie/motif.js","_rev":"4-912a12d62cd263a86ace07d1dbbcb08d","name":"@ateliercartographie/motif.js","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.0":{"name":"@ateliercartographie/motif.js","version":"0.1.0","keywords":["pattern","motif","svg","canvas","generator"],"author":{"name":"Thomas Ansart"},"license":"ISC","_id":"@ateliercartographie/motif.js@0.1.0","maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"homepage":"https://github.com/AtelierCartographie/motif.js#readme","bugs":{"url":"https://github.com/AtelierCartographie/motif.js/issues"},"dist":{"shasum":"c369724f3fbb73a7829a1e31062d25fe80916689","tarball":"https://registry.npmjs.org/@ateliercartographie/motif.js/-/motif.js-0.1.0.tgz","fileCount":6,"integrity":"sha512-PW28/oIYDMH59/PKGZOoz1AmRfFoYDUJKjhbTxNHjERF0U2SRtrvrckoWly6Cg6CvZC/SZiIyieNwy7LN5KwQg==","signatures":[{"sig":"MEYCIQDbakzaHpTuCUWrmFWOnLHqqBgzKI7p7PU71p+Mg6KacQIhALBNe/iVWd/xp/lilw40yFRFT09iJ2VceGCNvwFC6ieP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41178},"main":"./dist/motif.js","type":"module","types":"./dist/index.d.ts","module":"./dist/motif.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/motif.mjs","require":"./dist/motif.js"}},"gitHead":"673f87e2b569435a1224b216557f8afe8ba090fe","scripts":{"dev":"vite --config demo/vite.config.ts demo","build":"tsc && vite build","preview":"npm run build","build:demo":"pnpm --filter motif-demo build","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"tombor","email":"thomas2ansart@gmail.com"},"repository":{"url":"git+https://github.com/AtelierCartographie/motif.js.git","type":"git"},"_npmVersion":"10.9.2","description":"A pattern generator that can be used in SVG environment or Canvas context","directories":{},"_nodeVersion":"22.19.0","dependencies":{"d3-path":"^3.1.0"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.4.1","typescript":"^5.3.3","@types/node":"^22.10.0","vite-plugin-dts":"^4.5.4"},"_npmOperationalInternal":{"tmp":"tmp/motif.js_0.1.0_1772451163642_0.6181798960292917","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@ateliercartographie/motif.js","version":"0.1.3","keywords":["pattern","motif","svg","canvas","generator"],"author":{"name":"Thomas Ansart"},"license":"ISC","_id":"@ateliercartographie/motif.js@0.1.3","maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"homepage":"https://github.com/AtelierCartographie/motif.js#readme","bugs":{"url":"https://github.com/AtelierCartographie/motif.js/issues"},"dist":{"shasum":"8bc3c5e808fd9b4ba30942125dbcb5f739acc271","tarball":"https://registry.npmjs.org/@ateliercartographie/motif.js/-/motif.js-0.1.3.tgz","fileCount":6,"integrity":"sha512-lbNtAVct5P+OdD3zM8krrVIEYS93YzxhmD3VFNX+D0OiZdf+7NWSFxpUE4QvEAtDkj67MA618f/qrVZ3SKwX9A==","signatures":[{"sig":"MEQCIDOm1MBWx09tFZ+7GxXEG60Ooz0pac+Hk+NGdF23jLPRAiAB9yzzuQT0AgLBqwxxfaAvp/9TRUwIKtFaBNIrTi3E7Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ateliercartographie%2fmotif.js@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":41178},"main":"./dist/motif.js","type":"module","types":"./dist/index.d.ts","module":"./dist/motif.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/motif.mjs","require":"./dist/motif.js"}},"gitHead":"7965a4f23e33aafa4188dfbf0bb60e1f93d91ebd","scripts":{"dev":"vite --config demo/vite.config.ts demo","build":"tsc && vite build","preview":"npm run build","build:demo":"pnpm --filter motif-demo build","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9edec50d-9522-4aa8-90ee-bc40d341f53f"}},"repository":{"url":"git+https://github.com/AtelierCartographie/motif.js.git","type":"git"},"_npmVersion":"11.8.0","description":"A pattern generator that can be used in SVG environment or Canvas context","directories":{},"_nodeVersion":"24.13.1","dependencies":{"d3-path":"^3.1.0"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.4.1","typescript":"^5.3.3","@types/node":"^22.10.0","vite-plugin-dts":"^4.5.4"},"_npmOperationalInternal":{"tmp":"tmp/motif.js_0.1.3_1772459363931_0.13453023845281176","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@ateliercartographie/motif.js","version":"0.1.4","keywords":["pattern","motif","svg","canvas","generator"],"author":{"name":"Thomas Ansart"},"license":"ISC","_id":"@ateliercartographie/motif.js@0.1.4","maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"homepage":"https://github.com/AtelierCartographie/motif.js#readme","bugs":{"url":"https://github.com/AtelierCartographie/motif.js/issues"},"dist":{"shasum":"cb86d57cb73e6e0164c17b215961a2a25893e75c","tarball":"https://registry.npmjs.org/@ateliercartographie/motif.js/-/motif.js-0.1.4.tgz","fileCount":6,"integrity":"sha512-P7klzGfcpyE9cXR/rW9F0xDxiwLddXVgx2O4lcDdmxc0Yr0iixGdtSwMJ0n/G6ex856fZzfZz6gsg4oJ7XdcSg==","signatures":[{"sig":"MEUCIA8jPeTa6UI20XGksrLarzAlNLF0NmvEeRmJdo0DUmwyAiEA6PRMUQ/ymtTaR3Lmr44rcSr9LDyy6eQAj0Iuq/wowMs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ateliercartographie%2fmotif.js@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":41178},"main":"./dist/motif.js","type":"module","types":"./dist/index.d.ts","module":"./dist/motif.mjs","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/motif.mjs","require":"./dist/motif.js"}},"gitHead":"665a72d68561dc8920c80732bf3c456b0e70d0c8","scripts":{"dev":"vite --config demo/vite.config.ts demo","build":"tsc && vite build","preview":"npm run build","build:demo":"pnpm --filter motif-demo build","release:major":"npm version major && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:patch":"npm version patch && git push --follow-tags","prepublishOnly":"pnpm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9edec50d-9522-4aa8-90ee-bc40d341f53f"}},"repository":{"url":"git+https://github.com/AtelierCartographie/motif.js.git","type":"git"},"_npmVersion":"11.8.0","description":"A pattern generator that can be used in SVG environment or Canvas context","directories":{},"_nodeVersion":"24.13.1","dependencies":{"d3-path":"^3.1.0"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.4.1","typescript":"^5.3.3","@types/node":"^22.10.0","vite-plugin-dts":"^4.5.4"},"_npmOperationalInternal":{"tmp":"tmp/motif.js_0.1.4_1772459631720_0.5293515247838723","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@ateliercartographie/motif.js","version":"0.1.5","type":"module","description":"A pattern generator that can be used in SVG environment or Canvas context","main":"./dist/motif.js","module":"./dist/motif.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/motif.mjs","require":"./dist/motif.js"}},"scripts":{"dev":"vite --config demo/vite.config.ts demo","build":"tsc && vite build","build:demo":"pnpm --filter motif-demo build","preview":"npm run build","prepublishOnly":"pnpm run build","release:patch":"npm version patch && git push --follow-tags","release:minor":"npm version minor && git push --follow-tags","release:major":"npm version major && git push --follow-tags"},"devDependencies":{"@types/node":"^22.10.0","typescript":"^5.3.3","vite":"^6.4.1","vite-plugin-dts":"^4.5.4"},"repository":{"type":"git","url":"git+https://github.com/AtelierCartographie/motif.js.git"},"keywords":["pattern","motif","svg","canvas","generator"],"author":{"name":"Thomas Ansart"},"license":"ISC","dependencies":{"d3-path":"^3.1.0"},"gitHead":"613dcd45f999b1bd69d4cb2e8306bf6a32be0f4d","_id":"@ateliercartographie/motif.js@0.1.5","bugs":{"url":"https://github.com/AtelierCartographie/motif.js/issues"},"homepage":"https://github.com/AtelierCartographie/motif.js#readme","_nodeVersion":"24.14.0","_npmVersion":"11.9.0","dist":{"integrity":"sha512-of4obGxpTyw1YGd/ExO0iGV7HixL1AO7WTvLwOI0kZ5nCsYTYs43sMugpZzA+3jIk9lWGBxLWayxsg0MJOGfIA==","shasum":"2d8bd016fbbd035f69f936174ae228cdae973661","tarball":"https://registry.npmjs.org/@ateliercartographie/motif.js/-/motif.js-0.1.5.tgz","fileCount":6,"unpackedSize":43229,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ateliercartographie%2fmotif.js@0.1.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGduztcBDJjvFpjokM1kRCH5dojQEskZopJabRasxcwSAiBzSYuKcbyQh1XGzAxZMq8mFVnQzE+fcB4OqfNFohQ9fA=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:9edec50d-9522-4aa8-90ee-bc40d341f53f"}},"directories":{},"maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/motif.js_0.1.5_1772706858160_0.7707696082577604"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-02T11:32:43.572Z","modified":"2026-03-05T10:34:19.081Z","0.1.0":"2026-03-02T11:32:43.795Z","0.1.3":"2026-03-02T13:49:24.102Z","0.1.4":"2026-03-02T13:53:51.856Z","0.1.5":"2026-03-05T10:34:18.305Z"},"bugs":{"url":"https://github.com/AtelierCartographie/motif.js/issues"},"author":{"name":"Thomas Ansart"},"license":"ISC","homepage":"https://github.com/AtelierCartographie/motif.js#readme","keywords":["pattern","motif","svg","canvas","generator"],"repository":{"type":"git","url":"git+https://github.com/AtelierCartographie/motif.js.git"},"description":"A pattern generator that can be used in SVG environment or Canvas context","maintainers":[{"name":"tombor","email":"thomas2ansart@gmail.com"}],"readme":"# Motif.js\n\nA pattern generator that can be used in SVG environments or Canvas contexts. Create beautiful, customizable patterns for data visualization, cartography, and design.\n\n**Created by:** [Thomas Ansart - Atelier de cartographie de Sciences Po](https://www.sciencespo.fr/cartographie/)  \n**Original development** as an [Observable notebook](https://observablehq.com/@ateliercartographie/motif)  \n**License:** ISC\n\n## ✨ Features\n\n- **8 Built-in Patterns**: line, plaid, circle, plus, cross, triangle, square, diamond\n- **SVG Support**: Generate SVG patterns for scalable graphics\n- **Canvas Support**: Generate Canvas patterns with automatic DPI handling\n- **Full Customization**: Control size, scale, angle, colors, strokes, and more\n- **TypeScript**: Fully typed for excellent developer experience\n- **Custom Shapes**: Define your own pattern shapes as SVG string path or Canvas path method\n\n## 📦 Installation\n\n### With pnpm (recommended)\n\n```bash\npnpm add @ateliercartographie/motif.js\n```\n\n### With npm\n\n```bash\nnpm install @ateliercartographie/motif.js\n```\n\n### With yarn\n\n```bash\nyarn add @ateliercartographie/motif.js\n```\n\n## 🚀 Quick Start\n\n### SVG Pattern\n\n```typescript\nimport { motif } from \"@ateliercartographie/motif.js\";\n\nconst pattern = motif({\n  type: \"circle\",\n  size: 30,\n  fill: \"#3b82f6\",\n  background: \"#f0f0f0\",\n});\n\n// Insert pattern definitions\nconst svg = document.querySelector(\"svg\");\nsvg.innerHTML = pattern.defs;\n\n// Use pattern as fill\nconst rect = document.createElementNS(\"http://www.w3.org/2000/svg\", \"rect\");\nrect.setAttribute(\"x\", \"0\");\nrect.setAttribute(\"y\", \"0\");\nrect.setAttribute(\"width\", \"400\");\nrect.setAttribute(\"height\", \"300\");\nrect.setAttribute(\"fill\", pattern.url);\nsvg.appendChild(rect);\n```\n\n### Canvas Pattern\n\n```typescript\nimport { motif } from \"@ateliercartographie/motif.js\";\n\nconst canvas = document.querySelector(\"canvas\");\nconst ctx = canvas.getContext(\"2d\");\n\nconst pattern = motif({\n  type: \"line\",\n  size: 25,\n  angle: 45,\n  fill: \"#000\",\n});\n\nconst canvasPattern = pattern.context(ctx);\nctx.fillStyle = canvasPattern;\nctx.fillRect(0, 0, canvas.width, canvas.height);\npattern.apply();\n```\n\n### Observable Plot Integration\n\n```typescript\nimport * as Plot from \"@observablehq/plot\";\nimport { motif } from \"@ateliercartographie/motif.js\";\n\nconst pattern = motif({\n  type: \"circle\",\n  size: 20,\n  fill: \"#ff6b6b\",\n});\n\nconst chart = Plot.plot({\n  marks: [\n    () => pattern.defs,\n    Plot.areaY(data, {\n      x: \"date\",\n      y: \"value\",\n      fill: pattern.url,\n    }),\n  ],\n});\n```\n\n## 📋 API Reference\n\n### `motif(options)`\n\nCreates a pattern that can be used in SVG or Canvas.\n\n#### Options\n\n| Option         | Type     | Default         | Description                                                                                                      |\n| -------------- | -------- | --------------- | ---------------------------------------------------------------------------------------------------------------- |\n| `type`         | string   | `\"line\"`        | Pattern type: \"line\", \"plaid\", \"circle\", \"plus\", \"cross\", \"triangle\", \"square\", \"diamond\", \"dithering\", \"custom\" |\n| `scale`        | number   | `1`             | Scale of the tile (multiplier)                                                                                   |\n| `size`         | number   | `20`            | Shape size as a percentage of tile area (0-100)                                                                  |\n| `angle`        | number   | `0`             | Rotation angle in degrees (0-360)                                                                                |\n| `fill`         | string   | `\"black\"`       | Fill color (CSS color)                                                                                           |\n| `stroke`       | string   | `\"transparent\"` | Stroke color (CSS color)                                                                                         |\n| `strokeWidth`  | number   | `0`             | Stroke width in pixels                                                                                           |\n| `dash`         | number[] | `[]`            | Dash pattern for stroke (e.g., `[5, 5]`)                                                                         |\n| `background`   | string   | `\"white\"`       | Background color of the pattern tile                                                                             |\n| `border`       | number   | `0`             | Border width around tile edges                                                                                   |\n| `patchSize`    | boolean  | `false`         | Intelligently swap foreground/background for better appearance at high sizes                                     |\n| `custom.shape` | function | -               | Custom shape function (for type: \"custom\")                                                                       |\n| `custom.patch` | number   | `50`            | Patch size for custom shapes                                                                                     |\n\n#### Return Value\n\nThe function returns an object with:\n\n- **`defs`** (string): SVG pattern definitions (use in `<defs>` tag)\n- **`url`** (string): CSS url reference (e.g., `url(#pattern-xyz)`)\n- **`context(ctx)`** (function): Creates a Canvas pattern from a 2D context\n- **`apply()`** (function): Applies pattern transformation to Canvas context\n- **`tile`** (number): The size of the pattern tile in pixels\n\n### `motifAtlas(patterns, options?)`\n\nCreates a pattern atlas (sprite sheet) from a set of named motif configurations. Returns a canvas and a mapping object ready for use with Deck.gl's `FillStyleExtension`.\n\n#### Parameters\n\n| Parameter  | Type                             | Description                       |\n| ---------- | -------------------------------- | --------------------------------- |\n| `patterns` | `Record<string, PatternOptions>` | A record of named pattern options |\n\n#### Return Value\n\n- **`canvas`** (HTMLCanvasElement): The sprite sheet atlas (variable dimensions)\n- **`mapping`** (Record\\<string, PatternMapping\\>): Mapping object with `{ x, y, width, height, angle }` for each pattern\n\nThe atlas uses **natural tile dimensions** from each motif (based on `scale`). Tiles are arranged horizontally and centered vertically. The `angle` is stored in the mapping for custom Deck.gl extensions that support rotation.\n\n## 🎨 Pattern Types\n\n### Line\n\nHorizontal lines pattern\n\n```typescript\nmotif({ type: \"line\", angle: 45 });\n```\n\n### Plaid\n\nGrid/plaid pattern\n\n```typescript\nmotif({ type: \"plaid\", size: 30 });\n```\n\n### Circle\n\nCircular dots pattern\n\n```typescript\nmotif({ type: \"circle\", size: 25 });\n```\n\n### Plus & Cross\n\nPlus sign pattern (cross is 45° rotated)\n\n```typescript\nmotif({ type: \"plus\", size: 30 });\nmotif({ type: \"cross\", size: 30 });\n```\n\n### Triangle\n\nTriangular pattern\n\n```typescript\nmotif({ type: \"triangle\", angle: 30 });\n```\n\n### Square & Diamond\n\nSquare pattern (diamond is 45° rotated)\n\n```typescript\nmotif({ type: \"square\", size: 25 });\nmotif({ type: \"diamond\", size: 25 });\n```\n\n### Dithering\n\nDithering pattern. Due to the 4x4 Bayer matrix, the `size` option is limited to only 16 values/steps (multiples of 4).\n\n```typescript\nmotif({ type: \"dithering\", scale: 2, size: 30 });\n```\n\n### Custom\n\nDefine your own pattern shape\n\n```typescript\nmotif({\n  type: \"custom\",\n  custom: {\n    shape: (tile, shapeArea) => {\n      // Return SVG path or canvas path\n      return `M 0 0 L ${tile} ${tile} Z`;\n    },\n  },\n});\n```\n\n## 💡 Examples\n\n### Colored Stripes\n\n```typescript\nconst stripes = motif({\n  type: \"line\",\n  angle: 45,\n  fill: \"#ff6b6b\",\n  background: \"#fff1f2\",\n  size: 15,\n});\n```\n\n### Polka Dots\n\n```typescript\nconst dots = motif({\n  type: \"circle\",\n  size: 25,\n  fill: \"#4ecdc4\",\n  background: \"#ecf9f7\",\n});\n```\n\n### Complex Grid\n\n```typescript\nconst grid = motif({\n  type: \"plaid\",\n  size: 25,\n  fill: \"#333\",\n  stroke: \"#ddd\",\n  strokeWidth: 1,\n  background: \"#f5f5f5\",\n});\n```\n\n### Cartography Example\n\nUse patterns to fill geographic regions:\n\n```typescript\nimport * as d3 from \"d3\";\nimport { motif } from \"@ateliercartographie/motif.js\";\n\nconst canvas = document.querySelector(\"canvas\");\nconst ctx = canvas.getContext(\"2d\");\n\n// Create multiple patterns\nconst patterns = [\n  motif({ type: \"circle\", fill: \"#3b82f6\" }),\n  motif({ type: \"line\", angle: 45, fill: \"#f59e0b\" }),\n  motif({ type: \"plaid\", fill: \"#10b981\" }),\n];\n\n// Load GeoJSON\nconst [departments, borders] = await Promise.all([\n  fetch(\"departments.json\").then((r) => r.json()),\n  fetch(\"borders.json\").then((r) => r.json()),\n]);\n\n// Create projection\nconst proj = d3.geoIdentity().fitSize([width, height], borders);\nconst path = d3.geoPath(proj).context(ctx);\n\n// Fill departments with random patterns\ndepartments.features.forEach((feature) => {\n  const pattern = patterns[Math.floor(Math.random() * patterns.length)];\n  ctx.fillStyle = pattern.context(ctx);\n  path(feature);\n  pattern.apply();\n});\n\n// Draw borders\nctx.strokeStyle = \"black\";\npath(borders);\nctx.stroke();\n```\n\n### Deck.gl Pattern Atlas\n\nUse `motifAtlas` to generate a sprite sheet for Deck.gl's `FillStyleExtension`. Each motif keeps its rotation, scale, and all visual options.\n\n```typescript\nimport { motifAtlas } from \"@ateliercartographie/motif.js\";\nimport { GeoJsonLayer } from \"@deck.gl/layers\";\nimport { FillStyleExtension } from \"@deck.gl/extensions\";\n\n// 1. Define a palette of motifs\n// Here a choropleth of 4 class with a line pattern of progressive size.\nconst { canvas, mapping } = motifAtlas({\n  lines_10: { type: \"line\", angle: 45, fill: \"goldenrod\", size: 10 },\n  lines_30: { type: \"line\", angle: 45, fill: \"goldenrod\", size: 30 },\n  lines_50: { type: \"line\", angle: 45, fill: \"goldenrod\", size: 50 },\n  lines_70: { type: \"line\", angle: 45, fill: \"goldenrod\", size: 70 },\n});\n\n// 2. Use directly with Deck.gl\nconst layer = new GeoJsonLayer({\n  id: \"choropleth\",\n  data: \"data/regions.geojson\",\n  filled: true,\n\n  extensions: [new FillStyleExtension({ pattern: true })],\n\n  // The atlas canvas and mapping are ready to use as-is\n  fillPatternAtlas: canvas,\n  fillPatternMapping: mapping,\n\n  // Assign a pattern to each feature\n  getFillPattern: (d) => d.properties.category,\n});\n\n// mapping[\"stripes\"].angle contains the original rotation (45)\n```\n\n**Note:** `motifAtlas` works with Deck.gl's `FillStyleExtension` when `fillPatternMask: false` is set (the default). This enables colored pattern rendering directly from the atlas.\n\n## 🔧 Development\n\n### Setup\n\n```bash\npnpm install\n```\n\n### Local Demo\n\nStart the interactive demo at http://localhost:5173:\n\n```bash\npnpm dev\n```\n\n### Build Library\n\n```bash\npnpm run build\n```\n\nOutputs:\n\n- `dist/motif.mjs` (ES Module)\n- `dist/motif.js` (UMD)\n- `dist/index.d.ts` (TypeScript declarations)\n\n### Build Demo for Deploy\n\n```bash\npnpm run build:demo\n```\n\nOutputs to `dist-demo/` for deployment to GitHub Pages or static hosting.\n\n## Ressources about patterns and symbols\n\n- [lib] [Textures.js](https://riccardoscalco.it/textures/) by Riccardo Scalco\n- [book] [Traditional methods of pattern designing; an introduction to the study of the decorative art](https://archive.org/details/traditionalmetho00chririch/page/128/mode/2up?view=theater)\n  by Archibald H Christie\n- [book] [Patterns chapter](https://thebookofshaders.com/09/) of _The Book of shaders_ by Patricio Gonzalez Vivo and Jen Lowe\n- [notebook] [Émile Cheysson color palettes](https://observablehq.com/@tomshanley/cheysson-color-palettes) by Tom Shanley\n- [book] Sémiologie graphique by Jacques Bertin\n- Pre-atentive symbols\n  - https://observablehq.com/d/be0598261eea8fba\n  - https://observablehq.com/@fil/scintillating-symbols\n  - https://observablehq.com/@heman/preattentive-symbols-176\n","readmeFilename":"README.md"}