{"_id":"@assalabs/design-system-tools","_rev":"4-eb054b25c24410ecfc7e625b44d85116","name":"@assalabs/design-system-tools","dist-tags":{"latest":"0.4.0"},"versions":{"0.1.0":{"name":"@assalabs/design-system-tools","version":"0.1.0","license":"MIT","_id":"@assalabs/design-system-tools@0.1.0","maintainers":[{"name":"matanassa","email":"matan@matto.com"}],"bin":{"assalabs-ds":"bin/assalabs-ds.mjs"},"dist":{"shasum":"e0896a89055b158ddd9657058b27049e35d0d3a8","tarball":"https://registry.npmjs.org/@assalabs/design-system-tools/-/design-system-tools-0.1.0.tgz","fileCount":9,"integrity":"sha512-nhUrPrQgxu6vv37iO5zfWgHYzuTYueFNrd5rRxJfpB5R/5/PPiAo19b2O/6C2hmGho2hPfQnTo8xPcHlH2c5sA==","signatures":[{"sig":"MEQCICmFERmO2vgpDiAF5FsVYvo73OjYPLNccsHWEH2nCROkAiBhuE8W7l0iuVsFQGGRY2g3sJYgpnHdRlw/DYPtjZENxg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23394},"main":"./dist/index.js","type":"module","_from":"file:assalabs-design-system-tools-0.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"eslint .","test":"node --test test/*.test.mjs","build":"tsup src/index.ts src/cli.ts --format esm --target node22 --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"matanassa","email":"matan@matto.com"},"_resolved":"/tmp/b91cfb2c426360971c156ab858628516/assalabs-design-system-tools-0.1.0.tgz","_integrity":"sha512-nhUrPrQgxu6vv37iO5zfWgHYzuTYueFNrd5rRxJfpB5R/5/PPiAo19b2O/6C2hmGho2hPfQnTo8xPcHlH2c5sA==","_npmVersion":"11.16.0","description":"Standards-based design token tooling for web and React Native","directories":{},"_nodeVersion":"24.18.0","dependencies":{"chokidar":"5.0.0","@terrazzo/parser":"2.5.0","@terrazzo/plugin-css":"2.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","typescript":"~6.0.3","@types/node":"^24.10.1","@tsconfig/recommended":"^1.0.8","@assalabs/eslint-config":"0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/design-system-tools_0.1.0_1786107728152_0.4562016034639762","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@assalabs/design-system-tools","version":"0.2.0","license":"MIT","_id":"@assalabs/design-system-tools@0.2.0","maintainers":[{"name":"matanassa","email":"matan@matto.com"}],"homepage":"https://github.com/assalabs/design-system#readme","bugs":{"url":"https://github.com/assalabs/design-system/issues"},"bin":{"assalabs-ds":"bin/assalabs-ds.mjs"},"dist":{"shasum":"4abdbd4f45b722e2199f7afc178f077dccaebd09","tarball":"https://registry.npmjs.org/@assalabs/design-system-tools/-/design-system-tools-0.2.0.tgz","fileCount":9,"integrity":"sha512-5Cy8LrTOTjHSr4iZzgcaZJGo/zX/fKqGHJQFPWwZ7xzDLZpBMBLHIXwJy38XZUtoTH4bj2q6E/kgbqt+uKfh7g==","signatures":[{"sig":"MEUCIQDixgK+u9COZxesyjtuE9bHS4b/cFnramubnInxX2v8CgIgPbbY/E+AH1NlouIuSd3FH3rtuwjWX10kh5rbCd1jY4s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@assalabs%2fdesign-system-tools@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":27603},"main":"./dist/index.js","type":"module","_from":"file:../../../../_temp/changeset-pack-9761737148-1788186267306/packages/assalabs-design-system-tools-0.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"eslint .","test":"node --test test/*.test.mjs","build":"tsup src/index.ts src/cli.ts --format esm --target node22 --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d4a96335-ea53-42f6-93b7-9c8ba14e0101"}},"_resolved":"/home/runner/work/_temp/changeset-pack-9761737148-1788186267306/packages/assalabs-design-system-tools-0.2.0.tgz","_integrity":"sha512-5Cy8LrTOTjHSr4iZzgcaZJGo/zX/fKqGHJQFPWwZ7xzDLZpBMBLHIXwJy38XZUtoTH4bj2q6E/kgbqt+uKfh7g==","repository":{"url":"git+https://github.com/assalabs/design-system.git","type":"git","directory":"packages/design-system-tools"},"_npmVersion":"11.17.0","description":"Standards-based design token tooling for web and React Native","directories":{},"_nodeVersion":"24.19.0","dependencies":{"chokidar":"5.0.0","@terrazzo/parser":"2.5.0","@terrazzo/plugin-css":"2.5.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","typescript":"~6.0.3","@types/node":"^24.10.1","@tsconfig/recommended":"^1.0.8","@assalabs/eslint-config":"^0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/design-system-tools_0.2.0_1788186273209_0.8606741118226007","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@assalabs/design-system-tools","version":"0.3.0","license":"MIT","_id":"@assalabs/design-system-tools@0.3.0","maintainers":[{"name":"matanassa","email":"matan@matto.com"}],"homepage":"https://github.com/assalabs/design-system#readme","bugs":{"url":"https://github.com/assalabs/design-system/issues"},"bin":{"assalabs-ds":"bin/assalabs-ds.mjs"},"dist":{"shasum":"46dade35e8862d4eff7ec06126b6c2d0eee401a2","tarball":"https://registry.npmjs.org/@assalabs/design-system-tools/-/design-system-tools-0.3.0.tgz","fileCount":9,"integrity":"sha512-vEr78o16PHOqMqMYPMII3o9rAGNvtXRacA1wVWvGIE0AAkU+Dyu10xnXLx33SS3U9jCRJYxaf+PzxDlOz5rARg==","signatures":[{"sig":"MEYCIQDtT3K91Sg8yjRqpT1d/GrMMqVPZDIrOowaTg+J4IU19wIhAOJZ2Q3vJDy9kqMm7xbiMKjARxs9epOWX2xR/BTXtOZA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@assalabs%2fdesign-system-tools@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":77266},"main":"./dist/index.js","type":"module","_from":"file:../../../../_temp/changeset-pack-9766806016-1788194488786/packages/assalabs-design-system-tools-0.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"lint":"eslint .","test":"node --test test/*.test.mjs","build":"tsup src/index.ts src/cli.ts --format esm --target node22 --dts --clean","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d4a96335-ea53-42f6-93b7-9c8ba14e0101"}},"_resolved":"/home/runner/work/_temp/changeset-pack-9766806016-1788194488786/packages/assalabs-design-system-tools-0.3.0.tgz","_integrity":"sha512-vEr78o16PHOqMqMYPMII3o9rAGNvtXRacA1wVWvGIE0AAkU+Dyu10xnXLx33SS3U9jCRJYxaf+PzxDlOz5rARg==","repository":{"url":"git+https://github.com/assalabs/design-system.git","type":"git","directory":"packages/design-system-tools"},"_npmVersion":"11.17.0","description":"Standards-based design token tooling for web and React Native","directories":{},"_nodeVersion":"24.19.0","dependencies":{"culori":"^4.0.2","chokidar":"5.0.0","@terrazzo/parser":"2.5.0","@terrazzo/plugin-css":"2.5.0","@terrazzo/token-tools":"2.7.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","typescript":"~6.0.3","@types/node":"^24.10.1","@types/culori":"^4.0.1","@tsconfig/recommended":"^1.0.8","@assalabs/eslint-config":"^0.1.1"},"_npmOperationalInternal":{"tmp":"tmp/design-system-tools_0.3.0_1788194494090_0.03159005896288325","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@assalabs/design-system-tools","version":"0.4.0","description":"Standards-based design token tooling for web and React Native","license":"MIT","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"bin":{"assalabs-ds":"bin/assalabs-ds.mjs"},"dependencies":{"@terrazzo/parser":"2.7.1","@terrazzo/plugin-css":"2.5.0","@terrazzo/token-tools":"2.7.1","chokidar":"5.0.0","culori":"^4.0.2"},"devDependencies":{"@assalabs/eslint-config":"^0.1.1","@tsconfig/recommended":"^1.0.8","@types/culori":"^4.0.1","@types/node":"^24.10.1","eslint":"^9.39.2","tsup":"^8.5.1","typescript":"~6.0.3"},"engines":{"node":">=22"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/assalabs/design-system.git","directory":"packages/design-system-tools"},"homepage":"https://github.com/assalabs/design-system#readme","bugs":{"url":"https://github.com/assalabs/design-system/issues"},"scripts":{"build":"tsup src/index.ts src/cli.ts --format esm --target node22 --dts --clean","lint":"eslint .","test":"node --test test/*.test.mjs","typecheck":"tsc --noEmit"},"_id":"@assalabs/design-system-tools@0.4.0","_integrity":"sha512-XILEWnJ1vV5P0qgo2kyEt7879Nylm7vh+dPlzUTlPExqN7rbXyioLzJUYwCOfe1JWPWqQluOVq1dYII9Xz++fQ==","_resolved":"/home/runner/work/_temp/changeset-pack-9893601622-1788439144331/packages/assalabs-design-system-tools-0.4.0.tgz","_from":"file:../../../../_temp/changeset-pack-9893601622-1788439144331/packages/assalabs-design-system-tools-0.4.0.tgz","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-XILEWnJ1vV5P0qgo2kyEt7879Nylm7vh+dPlzUTlPExqN7rbXyioLzJUYwCOfe1JWPWqQluOVq1dYII9Xz++fQ==","shasum":"ab983cd048e38cfd7ded875fe5987b259fbbc2ce","tarball":"https://registry.npmjs.org/@assalabs/design-system-tools/-/design-system-tools-0.4.0.tgz","fileCount":9,"unpackedSize":77266,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@assalabs%2fdesign-system-tools@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDy0e/T6dPjVoZ0SHmFWUGk2EuABcFqFHLoNtYVrm+l6wIgdC8bEh+oi2UlGTYbuEdmsbdsFEF+fF3Q4Cr0T3uRfgM="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:d4a96335-ea53-42f6-93b7-9c8ba14e0101"}},"directories":{},"maintainers":[{"name":"matanassa","email":"matan@matto.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/design-system-tools_0.4.0_1788439150698_0.2568072468302378"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-07T13:02:07.954Z","modified":"2026-09-03T12:39:11.380Z","0.1.0":"2026-08-07T13:02:08.306Z","0.2.0":"2026-08-31T14:24:33.331Z","0.3.0":"2026-08-31T16:41:34.221Z","0.4.0":"2026-09-03T12:39:10.823Z"},"bugs":{"url":"https://github.com/assalabs/design-system/issues"},"license":"MIT","homepage":"https://github.com/assalabs/design-system#readme","repository":{"type":"git","url":"git+https://github.com/assalabs/design-system.git","directory":"packages/design-system-tools"},"description":"Standards-based design token tooling for web and React Native","maintainers":[{"name":"matanassa","email":"matan@matto.com"}],"readme":"# @assalabs/design-system-tools\n\nBuild-time tooling that turns DTCG design tokens into static CSS and plain\nTypeScript themes for web and React Native.\n\nThe package wraps a pinned Terrazzo toolchain and adds semantic-contract,\ntheme-parity, contrast, and generated-output drift checks, plus a palette\ngenerator that derives a full accessible token set from one brand colour.\n\nRequires Node.js 22 or newer.\n\n```bash\npnpm add --save-dev @assalabs/design-system-tools\n```\n\nApplications do not depend on this package at runtime. They consume only the\ngenerated outputs published by their theme package.\n\n## Commands\n\n```bash\nassalabs-ds tokens build           # generate every configured output\nassalabs-ds tokens check           # regenerate in memory, byte-compare, fail on drift\nassalabs-ds tokens watch           # rebuild on token or config change\nassalabs-ds palette --brand '#FF3131'\n```\n\nEvery command takes `--config <path>` (default `design-system.config.mjs`) and\n`--debug`. Run `assalabs-ds --help` or `assalabs-ds palette --help` for the full\noption list.\n\n## `palette`\n\n`palette` derives eleven-step ramps and both semantic themes from a single seed\nand writes three files into the token directory:\n\n```text\nprimitives/colors.tokens.json\nsemantic/light.tokens.json\nsemantic/dark.tokens.json\n```\n\nIt refuses to overwrite existing files unless `--force` is passed, and reports\nevery file that would be clobbered in one run rather than stopping at the first.\n`--json` prints the primitives, the anchor step per ramp, the resolved semantic\nroles, and the contrast report to stdout and writes nothing.\n\n```bash\nassalabs-ds palette --brand '#FF3131'                    # derive everything\nassalabs-ds palette --brand '#FF3131' --neutral gray     # achromatic neutral\nassalabs-ds palette --brand '#FF3131' --accent '#31FFB0' # pin the accent\nassalabs-ds palette --brand '#FF3131' --json             # preview, write nothing\n```\n\n### Derivation rules\n\nAll colour maths happens in OKLCH, via culori.\n\n| Ramp      | Hue                     | Chroma                                          |\n| --------- | ----------------------- | ----------------------------------------------- |\n| `brand`   | the seed's own hue      | the seed's own chroma                           |\n| `neutral` | the **brand hue**, kept | `min(0.015, brand chroma)` — a tint, not a grey |\n| `accent`  | brand hue **+ 150°**    | the brand's chroma                              |\n| `success` | fixed **145**           | brand chroma clamped to `[0.09, 0.19]`          |\n| `warning` | fixed **80**            | same                                            |\n| `danger`  | fixed **25**            | same                                            |\n| `info`    | fixed **250**           | same                                            |\n\n`--neutral gray` forces chroma to `0` for a truly achromatic neutral;\n`--neutral <hex>` and `--accent <hex>` replace the derivation with your seed.\n\nEach ramp has steps `50 … 950`. The seed hex is **preserved exactly** at one\nstep: derived seeds anchor at `500`, and a user-supplied seed anchors at\nwhichever step's reference lightness is nearest to it, so `#123456` anchors at\n`900` and `#fff5f5` at `50`. The rest of the ramp is re-fitted from that anchor\ntowards fixed light and dark ends, so the seed never drifts and the ends stay\nput. Chroma follows a per-step multiplier curve peaking at `500`, and every step\nis gamut-mapped into sRGB with `clampChroma`.\n\nSemantic roles are then **chosen by contrast, not by convention**. Each role has\nan ordered candidate list, and the first candidate that satisfies every declared\npair wins:\n\n| Pair                                                  | Minimum |\n| ----------------------------------------------------- | ------- |\n| `fg.default` on `bg.canvas`                           | 4.5     |\n| `fg.muted` on `bg.canvas`, `fg.muted` on `bg.surface` | 4.5     |\n| `fg.onBrand` on `brand.default`                       | 4.5     |\n| `border.strong` on `bg.canvas`                        | 3       |\n| each `status.*` on `bg.canvas`                        | 3       |\n\n`brand.default` and `fg.onBrand` are resolved **jointly**: the brand ramp is\nwalked from its anchor outwards (darker first, then lighter) until a step\nreaches 4.5 against either white or `neutral.950`, and the winner picks the\nforeground. `brand.hover` and `brand.active` are then one and two steps further\nalong that ramp — darker in light mode, lighter in dark mode.\n\nThe scaffolded theme's `contrastPairs` are exactly this table, so\n`assalabs-ds tokens check` re-asserts what `palette` promised.\n\n### Edge cases\n\n- **Achromatic seeds.** `#000000`, `#ffffff` and `#808080` have no hue at all.\n  Their ramps are built at chroma `0`, and the accent's \"+150°\" is a rotation of\n  an undefined hue, so it too comes out neutral. Ask for colour with a chromatic\n  seed.\n- **Near-white and near-black seeds.** Gamut mapping shifts hue slightly, so the\n  accent lands _near_ +150° rather than exactly on it (`#fff5f5` measures\n  ~147°). Mid-lightness chromatic seeds hit +150° to within half a degree.\n- **Extreme seeds** anchor at the end of the ramp (`50` or `950`), which leaves\n  one side of the ladder short. The ramp still spans light to dark, but with\n  fewer distinct steps on the crowded side.\n- **Unsatisfiable seeds** raise a `PaletteError` naming the pair and the best\n  ratio found, for example\n  `light: no candidate for color.fg.muted satisfies fg.muted/bg.canvas ≥ 4.5 (best 4.12)`.\n  Nothing is written when this happens.\n\n`generatePalette` is pure — no IO, no randomness, no clock — so the same seed\nalways produces byte-identical files.\n\n## Config\n\n`design-system.config.mjs` exports `defineDesignSystem({ … })`. At least one of\n`outputs.css` or `outputs.native` is required.\n\n```js\nimport { defineDesignSystem } from \"@assalabs/design-system-tools\";\n\nexport default defineDesignSystem({\n  name: \"Acme\",\n  prefix: \"ac\",\n  source: \"./tokens/theme.resolver.json\",\n  themes: [\"light\", \"dark\"],\n  defaultTheme: \"light\",\n  outputs: {\n    css: \"styles/generated.css\",\n    native: \"src/generated/themes.ts\",\n    tokenNames: \"src/generated/tokenNames.ts\",\n    stylex: { file: \"src/generated/tokens.stylex.ts\" },\n    unistyles: { dir: \"src/generated/\" },\n  },\n  requiredTokens: [\"color.bg.canvas\", \"color.fg.default\"],\n  contrastPairs: [\n    {\n      foreground: \"color.fg.default\",\n      background: \"color.bg.canvas\",\n      minimum: 4.5,\n    },\n  ],\n});\n```\n\nEvery output path is relative to the theme package root and must stay inside it.\n\n`outputs.css` emits one stylesheet with a flat `:root` block, explicit\n`[data-theme=\"light\"]` / `[data-theme=\"dark\"]` blocks, and a\n`@media (prefers-color-scheme: dark) { :root:not([data-theme]) }` block — so an\napp follows the system by default and `data-theme` on `<html>` pins it.\n\n`outputs.native` emits plain TypeScript theme objects, **nested by token path**:\n`theme.color.bg.canvas`, `theme.dimension.radius.md`. Native colours are sRGB\nhex and dimensions are unitless numbers; anything that cannot be expressed that\nway fails the build instead of emitting invalid React Native.\n\n### `outputs.stylex`\n\n```text\noutputs: { stylex: { file: \"src/generated/tokens.stylex.ts\" } }\n```\n\nEmits one file of flat `stylex.defineVars` groups — `colors`, `spacing`,\n`radius`, `dimensions`, `fonts`, `motion`, and one `typography<Variant>` group\nper typography variant. Keys are **camelCase and flat**, so `color.fg.onBrand`\nbecomes `colors.fgOnBrand` and `dimension.space.4` becomes `spacing[4]`.\n(`dimension.breakpoint.*` is deliberately absent: breakpoints are media queries,\nnot variables.)\n\n**Requires `outputs.css`**, and requires `themes` to be exactly\n`[\"light\", \"dark\"]`. Theme-dependent tokens — every colour, plus any other token\nwhose light and dark values differ — are emitted as a `var()` reference to the\ncustom property the stylesheet already declares:\n\n```ts\nexport const colors = stylex.defineVars({\n  bgCanvas: \"var(--ac-color-bg-canvas)\",\n  fgOnBrand: \"var(--ac-color-fg-on-brand)\",\n});\n\nexport const spacing = stylex.defineVars({\n  \"4\": \"16px\",\n});\n```\n\nNote that the StyleX **key** is camelCase (`fgOnBrand`) while the **custom\nproperty** is kebab-cased and lowercased (`--ac-color-fg-on-brand`); the adapter\nderives the reference from the same helper the CSS plugin declares with, so the\ntwo cannot drift.\n\nEverything theme-independent stays a literal, so it still inlines. Dark mode is\ndriven entirely by the theme's `generated.css`: importing `<pkg>/css` once is\nwhat makes the StyleX variables resolve, and switching `data-theme` on `<html>`\nrecomputes them. `stylex.defineVars` cannot carry the override itself — StyleX\n0.19 treats every non-`default` key of a value object as an at-rule, so a\nselector key lowers to a dead `[data-theme=dark] :root` descendant rule.\n\nConsuming apps need StyleX's `unstable_moduleResolution` set to\n`type: \"commonJS\"` with a `rootDir` at the workspace root, plus\n`treeshakeCompensation`, so the compiled variable definitions survive bundling.\n\n### `outputs.unistyles`\n\n```text\noutputs: { unistyles: { dir: \"src/generated/\", spacingBaseToken: \"dimension.space.base\" } }\n```\n\nEmits a **single** `<dir>/unistyles.ts` containing the themes, the breakpoints,\n`configureUnistyles()`, and the `react-native-unistyles` module augmentation.\n\n**Requires `outputs.native`**, and `dir` must contain the directory of\n`outputs.native`, because the generated module imports the themes file with a\nrelative specifier. `themes` must be exactly `[\"light\", \"dark\"]`.\n\n```ts\nimport { configureUnistyles } from \"@acme/theme/unistyles\";\nconfigureUnistyles(); // before any StyleSheet.create call\n\nStyleSheet.create((theme) => ({\n  screen: {\n    backgroundColor: theme.color.bg.canvas, // nested, like outputs.native\n    padding: theme.spacing(3), // 3 × dimension.space.base\n  },\n}));\n```\n\n- The theme shape is the **nested** native shape (`theme.color.bg.canvas`), not\n  the flat camelCase StyleX shape.\n- `spacing(factor)` multiplies `spacingBaseToken` (default `dimension.space.base`,\n  falling back to `8` with a warning when the token is absent).\n- Breakpoints come from `dimension.breakpoint.*`. Unistyles requires a\n  breakpoint at `0`, so `xs: 0` is injected when no token provides one.\n- The `declare module` augmentation is **inline in `unistyles.ts`**; no sibling\n  `unistyles.d.ts` is emitted. TypeScript drops a declaration file shadowed by a\n  same-named `.ts` from wildcard-`include` programs, and module resolution\n  prefers the `.ts`, so a sibling declaration would silently never load. The\n  augmentation applies wherever the module is imported.\n- Keep `unistyles.ts` out of your bundler entries: it must reach the consumer as\n  source, both so Metro compiles it and so the augmentation loads.\n\n## Error output\n\nFailures exit `1` and print one line to stderr. That line is the finished\nmessage for everything this tool raises itself — `PaletteError`, config\nvalidation, unsatisfied `requiredTokens` or `contrastPairs`, stale generated\noutput.\n\nIt is a summary, not the whole story, for errors that merely pass _through_ the\ntool. `design-system.config.mjs` is imported as real ESM, so a mistake inside it\nis V8's error, not ours:\n\n```console\n$ assalabs-ds tokens build\nCould not load /repo/packages/theme/design-system.config.mjs: Unexpected end of input\n```\n\nThe config path is prefixed onto those messages, because the underlying error\ndoes not name a file. Pass `--debug` for the stack and the `cause` chain:\n\n```console\n$ assalabs-ds tokens build --debug\nError: Could not load /repo/packages/theme/design-system.config.mjs: …\n    at loadDesignSystemConfig …\nCaused by: TypeError: Cannot read properties of undefined (reading 'css')\n    at file:///repo/packages/theme/design-system.config.mjs:12:25\n```\n\nFor a **runtime** error in the config, `--debug` gives the exact line and\ncolumn. For a **syntax** error the cause's stack is pure Node module-loader\nframes and names no file or line at all, so the path in the message is the only\nlocator you get — check the file the message names.\n\n`--debug` never changes the curated messages above; it only adds the stack after\nthem.\n","readmeFilename":"README.md"}