{"_id":"@a-company/atelier-types","_rev":"5-519001afab734c1c01874058b78aa1b3","name":"@a-company/atelier-types","dist-tags":{"latest":"0.31.0"},"versions":{"0.25.1":{"name":"@a-company/atelier-types","version":"0.25.1","_id":"@a-company/atelier-types@0.25.1","maintainers":[{"name":"ascend42","email":"ascend@a-company.org"}],"dist":{"shasum":"562f47993ef87d3fc627341481369c19f0fb1dde","tarball":"https://registry.npmjs.org/@a-company/atelier-types/-/atelier-types-0.25.1.tgz","fileCount":8,"integrity":"sha512-S1fi20vNF2YYxDYWNsBBHwwRvkhATfAy4dfyThHbhbOcaEffIcKbGYh/4ZVZV91YhhsherbJsHRfXI7oebg4tw==","signatures":[{"sig":"MEYCIQDBEaLdKXfgHJHHko1jGPzS74wsRinY5GN/mHx1VSVc+gIhAKnvmnxwjSdQ140f8IkrW83S/YN/pABV1nkxCmDS0Oif","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43105},"main":"./dist/index.cjs","type":"module","_from":"file:a-company-atelier-types-0.25.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ascend42","email":"ascend@a-company.org"},"_resolved":"/private/var/folders/gq/nt2kdpsj39dc8vpq6cfzx8gw0000gn/T/783f0b5eeb74dfe4f67c30a31c630cd3/a-company-atelier-types-0.25.1.tgz","_integrity":"sha512-S1fi20vNF2YYxDYWNsBBHwwRvkhATfAy4dfyThHbhbOcaEffIcKbGYh/4ZVZV91YhhsherbJsHRfXI7oebg4tw==","_npmVersion":"11.7.0","description":"Pure TypeScript type definitions for the Atelier animation format","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.4.0","vitest":"^3.0.0","typescript":"^5.7.0"},"_npmOperationalInternal":{"tmp":"tmp/atelier-types_0.25.1_1771887809862_0.4689955342251555","host":"s3://npm-registry-packages-npm-production"}},"0.25.2":{"name":"@a-company/atelier-types","version":"0.25.2","_id":"@a-company/atelier-types@0.25.2","maintainers":[{"name":"ascend42","email":"ascend@a-company.org"}],"dist":{"shasum":"64d15c0da7aff43771863b674e81edf1766ac70a","tarball":"https://registry.npmjs.org/@a-company/atelier-types/-/atelier-types-0.25.2.tgz","fileCount":8,"integrity":"sha512-HM6eCRMaz5agpkdT8yZ1Eejv49/0O01+kIgKtnFtQ+5NgPKrQdqsPmt8lcKzi6KH8D0tWvc3F9LdMZ6P8ZVdig==","signatures":[{"sig":"MEYCIQCDCd+Ovki+LuVMoTeoSg8VkVfRsJUb2S2Qfbu11GaYTQIhAOxqyfemzgEGkhylrSFV4V808j306UmxqYXkRYg3UNaR","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43128},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"a014974918c3dd3907ef5e1ee3ef85bc3a227d31","scripts":{"test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ascend42","email":"ascend@a-company.org"},"_npmVersion":"11.7.0","description":"Pure TypeScript type definitions for the Atelier animation format","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.4.0","vitest":"^3.0.0","typescript":"^5.7.0"},"_npmOperationalInternal":{"tmp":"tmp/atelier-types_0.25.2_1772560060102_0.7872085421853723","host":"s3://npm-registry-packages-npm-production"}},"0.25.3":{"name":"@a-company/atelier-types","version":"0.25.3","_id":"@a-company/atelier-types@0.25.3","maintainers":[{"name":"ascend42","email":"ascend@a-company.org"}],"dist":{"shasum":"1f0819b1971ca35e5edf866274725c3677328fda","tarball":"https://registry.npmjs.org/@a-company/atelier-types/-/atelier-types-0.25.3.tgz","fileCount":8,"integrity":"sha512-wje09fWSNUOP3J2329p/7Q5pNQGxoosZd88zcsTgofck6zZ8y/wx8MbWcOzHTlTecNETaWYMCIyd+uD6Wzvskg==","signatures":[{"sig":"MEUCIFH94uIjbyp8DyWV9bRvCM7HzBBM0YNq7+lM4WsNakqOAiEA1L8W/I+bJFU0uQp+AZl9bCL06369y+wmb7orXfaOLnc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":43127},"main":"./dist/index.cjs","type":"module","_from":"file:a-company-atelier-types-0.25.3.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ascend42","email":"ascend@a-company.org"},"_resolved":"/private/var/folders/gq/nt2kdpsj39dc8vpq6cfzx8gw0000gn/T/b3fee4e089d887e73b27b65487daca2a/a-company-atelier-types-0.25.3.tgz","_integrity":"sha512-wje09fWSNUOP3J2329p/7Q5pNQGxoosZd88zcsTgofck6zZ8y/wx8MbWcOzHTlTecNETaWYMCIyd+uD6Wzvskg==","_npmVersion":"11.7.0","description":"Pure TypeScript type definitions for the Atelier animation format","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.4.0","vitest":"^3.0.0","typescript":"^5.7.0"},"_npmOperationalInternal":{"tmp":"tmp/atelier-types_0.25.3_1772568029401_0.016581336662921498","host":"s3://npm-registry-packages-npm-production"}},"0.26.0":{"name":"@a-company/atelier-types","version":"0.26.0","_id":"@a-company/atelier-types@0.26.0","maintainers":[{"name":"ascend42","email":"ascend@a-company.org"}],"dist":{"shasum":"b44515d460995beafea9311c087db4e56fdf0810","tarball":"https://registry.npmjs.org/@a-company/atelier-types/-/atelier-types-0.26.0.tgz","fileCount":8,"integrity":"sha512-pfh4orme4uYMEyaaXwBwKeQRnM6Io0ortKnjyp1YEzroR8BlYcPrah9PNe/lKoUQdeyc8A1cfFjf8uLup27GVg==","signatures":[{"sig":"MEUCIAZDBVJv7n96O5xe/xgxFaYIXtcpGh/hCof1IlCPVs0WAiEAnA7GkXCwMoHQRJp7iVy/U/yqEeGpTMsja+Fi8VDoghg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45141},"main":"./dist/index.cjs","type":"module","_from":"file:a-company-atelier-types-0.26.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ascend42","email":"ascend@a-company.org"},"_resolved":"/private/var/folders/gq/nt2kdpsj39dc8vpq6cfzx8gw0000gn/T/fb4670861a2c4aed249fd9e6c7c5dd38/a-company-atelier-types-0.26.0.tgz","_integrity":"sha512-pfh4orme4uYMEyaaXwBwKeQRnM6Io0ortKnjyp1YEzroR8BlYcPrah9PNe/lKoUQdeyc8A1cfFjf8uLup27GVg==","_npmVersion":"11.7.0","description":"Pure TypeScript type definitions for the Atelier animation format","directories":{},"_nodeVersion":"24.12.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.4.0","vitest":"^3.0.0","typescript":"^5.7.0"},"_npmOperationalInternal":{"tmp":"tmp/atelier-types_0.26.0_1778200980625_0.378815326007099","host":"s3://npm-registry-packages-npm-production"}},"0.31.0":{"name":"@a-company/atelier-types","version":"0.31.0","publishConfig":{"access":"public"},"description":"Pure TypeScript type definitions for the Atelier animation format","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"devDependencies":{"tsup":"^8.4.0","typescript":"^5.7.0","vitest":"^3.0.0"},"scripts":{"build":"tsup","typecheck":"tsc --noEmit","test":"vitest run","clean":"rm -rf dist"},"_id":"@a-company/atelier-types@0.31.0","_integrity":"sha512-AUS5ucjbVL4CP5j06BDbx4KIJ4vVSbt83SxJCoKmDncW5r9upa9XD9s7Do1m8TwxBlHOCgJAfAXZlyLG0qq4Jw==","_resolved":"/private/var/folders/gq/nt2kdpsj39dc8vpq6cfzx8gw0000gn/T/d21e08e49fddffaa9479d8c6bb561128/a-company-atelier-types-0.31.0.tgz","_from":"file:a-company-atelier-types-0.31.0.tgz","_nodeVersion":"24.12.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-AUS5ucjbVL4CP5j06BDbx4KIJ4vVSbt83SxJCoKmDncW5r9upa9XD9s7Do1m8TwxBlHOCgJAfAXZlyLG0qq4Jw==","shasum":"ee30877118b24185c06dd40d74cc5afeb88edb42","tarball":"https://registry.npmjs.org/@a-company/atelier-types/-/atelier-types-0.31.0.tgz","fileCount":8,"unpackedSize":63683,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGAqH8QcgSUEtSXmTwKWRL1gLgk9j1AQJjy16qYfcUXHAiEAvyL95OnVJwZT9s5zenMDWlH4fpdj9pYKCPoJImtaYd0="}]},"_npmUser":{"name":"ascend42","email":"ascend@a-company.org"},"directories":{},"maintainers":[{"name":"ascend42","email":"ascend@a-company.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/atelier-types_0.31.0_1779253707506_0.2430159343357141"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-23T23:03:29.776Z","modified":"2026-05-20T05:08:27.781Z","0.25.1":"2026-02-23T23:03:30.021Z","0.25.2":"2026-03-03T17:47:40.282Z","0.25.3":"2026-03-03T20:00:29.537Z","0.26.0":"2026-05-08T00:43:00.780Z","0.31.0":"2026-05-20T05:08:27.659Z"},"description":"Pure TypeScript type definitions for the Atelier animation format","maintainers":[{"name":"ascend42","email":"ascend@a-company.org"}],"readme":"---\ntitle: \"@atelier/types\"\nscope: 47 TypeScript type definitions across 12 modules\npackages: [\"@atelier/types\"]\nrelated: [\"docs/format-spec.md\", \"docs/architecture.md\", \"packages/schema/README.md\"]\n---\n\n# @atelier/types\n\nPure TypeScript type definitions for the Atelier animation format. Zero runtime -- every export is a `type` or `interface`. No dependencies.\n\n## Overview\n\n| | |\n|---|---|\n| **Package** | `@atelier/types` |\n| **Version** | `0.1.0` |\n| **Runtime footprint** | Zero -- types are erased at compile time |\n| **Dependencies** | None |\n| **Build** | tsup (ESM + CJS + DTS) |\n| **Source** | `packages/types/src/` |\n| **Exports** | 47 types and interfaces across 12 modules |\n\nAll other `@atelier/*` packages depend on these types. They define the complete vocabulary for describing layered, frame-based animations in YAML or JSON.\n\n## Installation\n\n```bash\npnpm add @atelier/types\n```\n\n```typescript\nimport type { AtelierDocument, Layer, Delta } from \"@atelier/types\";\n```\n\n## Type Hierarchy\n\nThe types compose from primitives up to the root document:\n\n```\nAtelierDocument\n |-- version, name, description, tags\n |-- Canvas  (width, height, fps, background)\n |-- Record<string, Variable>       -- template slots\n |-- Record<string, Asset>          -- external files\n |-- Record<string, Preset>         -- reusable delta sets\n |     '-- PresetDelta[]\n |           '-- AnimatableProperty, Easing\n |-- Layer[]\n |     |-- id, parentId, opacity, rotation, scale, visible\n |     |-- Frame  (x, y)            -- position\n |     |-- Bounds (width, height)   -- size\n |     |-- AnchorPoint (x, y)       -- transform origin\n |     '-- Visual (union)\n |           |-- ShapeVisual\n |           |     |-- Shape (RectShape | EllipseShape | PathShape)\n |           |     |     '-- PathPoint (x, y, in?, out?)\n |           |     |-- Fill  (SolidFill | LinearGradientFill | RadialGradientFill)\n |           |     |     '-- GradientStop (offset, Color)\n |           |     '-- Stroke (color, width, dash?, lineCap?, lineJoin?)\n |           |-- TextVisual\n |           |     '-- TextStyle (fontFamily, fontSize, color, ...)\n |           |-- ImageVisual (assetId)\n |           |-- GroupVisual\n |           '-- RefVisual  (src -- path to another .atelier file)\n |\n '-- Record<string, State>\n       |-- duration (frames)\n       '-- Delta[]\n             |-- layer        -- target layer ID\n             |-- property     -- AnimatableProperty (16 paths)\n             |-- range        -- FrameRange [start, end]\n             |-- from / to   -- start and end values\n             '-- easing?      -- Easing\n                   |-- LinearEasing\n                   |-- CubicBezierEasing (x1, y1, x2, y2)\n                   |-- SpringEasing (mass, stiffness, damping, velocity)\n                   |-- StepEasing (steps, position)\n                   '-- EasingPreset (\"ease-in\" | \"ease-out\" | \"ease-in-out\")\n\nPrimitives:\n  UnitValue = Pixel (number) | Percentage (`${number}%`)\n  Color     = RGBAColor | HSLAColor | HexColor (string)\n```\n\n---\n\n## Module Reference\n\n### 1. `units.ts` -- Unit System\n\nThree types that underpin all spatial values.\n\n```typescript\ntype Pixel = number;\ntype Percentage = `${number}%`;\ntype UnitValue = Pixel | Percentage;\n```\n\n`UnitValue` appears throughout `Frame`, `Bounds`, gradient centers, and radii. A plain number is interpreted as pixels; a template-literal string like `\"50%\"` is a percentage of the parent dimension.\n\n---\n\n### 2. `coordinates.ts` -- Spatial Types\n\nPosition, size, and transform origin for every layer.\n\n```typescript\ninterface Frame {\n  x: UnitValue;\n  y: UnitValue;\n}\n\ninterface Bounds {\n  width: UnitValue;\n  height: UnitValue;\n}\n\ninterface AnchorPoint {\n  x: number;  // 0-1 normalized\n  y: number;  // 0-1 normalized\n}\n```\n\n`AnchorPoint` defaults to `{ x: 0.5, y: 0.5 }` (center) when omitted. Rotation and scale transforms pivot around this point.\n\n---\n\n### 3. `color.ts` -- Color Formats\n\nFour types supporting RGB, HSL, and hex notation.\n\n```typescript\ninterface RGBAColor {\n  r: number;  // 0-255\n  g: number;  // 0-255\n  b: number;  // 0-255\n  a: number;  // 0-1\n}\n\ninterface HSLAColor {\n  h: number;  // 0-360 degrees\n  s: number;  // 0-100\n  l: number;  // 0-100\n  a: number;  // 0-1\n}\n\ntype HexColor = string;  // e.g. \"#FF0000\" or \"#FF000080\"\n\ntype Color = RGBAColor | HSLAColor | HexColor;\n```\n\n`Color` is the universal color union used by fills, strokes, gradients, and text styles.\n\n---\n\n### 4. `shape.ts` -- Shape Primitives\n\nTwelve types covering geometry, fills, strokes, and text styling.\n\n```typescript\ninterface PathPoint {\n  x: number;\n  y: number;\n  in?: { x: number; y: number };   // incoming bezier handle (relative)\n  out?: { x: number; y: number };  // outgoing bezier handle (relative)\n}\n\ninterface RectShape {\n  type: \"rect\";\n  cornerRadius?: number | [number, number, number, number];\n}\n\ninterface EllipseShape {\n  type: \"ellipse\";\n}\n\ninterface PathShape {\n  type: \"path\";\n  points: PathPoint[];\n  closed?: boolean;\n}\n\ntype Shape = RectShape | EllipseShape | PathShape;\n```\n\n```typescript\ninterface GradientStop {\n  offset: number;  // 0-1\n  color: Color;\n}\n\ninterface SolidFill {\n  type: \"solid\";\n  color: Color;\n}\n\ninterface LinearGradientFill {\n  type: \"linear-gradient\";\n  angle: number;  // degrees\n  stops: GradientStop[];\n}\n\ninterface RadialGradientFill {\n  type: \"radial-gradient\";\n  center: { x: UnitValue; y: UnitValue };\n  radius: UnitValue;\n  stops: GradientStop[];\n}\n\ntype Fill = SolidFill | LinearGradientFill | RadialGradientFill;\n```\n\n```typescript\ninterface Stroke {\n  color: Color;\n  width: number;\n  dash?: number[];\n  lineCap?: \"butt\" | \"round\" | \"square\";\n  lineJoin?: \"miter\" | \"round\" | \"bevel\";\n}\n\ninterface TextStyle {\n  fontFamily: string;\n  fontSize: number;\n  fontWeight?: number | \"normal\" | \"bold\";\n  fontStyle?: \"normal\" | \"italic\";\n  textAlign?: \"left\" | \"center\" | \"right\";\n  lineHeight?: number;\n  letterSpacing?: number;\n  color: Color;\n}\n```\n\n---\n\n### 5. `layer.ts` -- Layer System\n\nSeven types that define visual content and the layer container itself.\n\n```typescript\ninterface ShapeVisual  { type: \"shape\"; shape: Shape; fill?: Fill; stroke?: Stroke; }\ninterface TextVisual   { type: \"text\"; content: string; style: TextStyle; }\ninterface ImageVisual  { type: \"image\"; assetId: string; }\ninterface GroupVisual   { type: \"group\"; }\ninterface RefVisual     { type: \"ref\"; src: string; }\n\ntype Visual = ShapeVisual | TextVisual | ImageVisual | GroupVisual | RefVisual;\n```\n\n```typescript\ninterface Layer {\n  id: string;\n  description?: string;\n  tags?: string[];\n  visual: Visual;\n  frame: Frame;\n  bounds: Bounds;\n  anchorPoint?: AnchorPoint;\n  parentId?: string;        // parent layer ID for transform inheritance\n  opacity?: number;         // 0-1\n  rotation?: number;        // degrees\n  scale?: { x: number; y: number };\n  visible?: boolean;\n}\n```\n\nLayers form a flat list with optional parent-child relationships via `parentId`. Child layers inherit their parent's transform.\n\n---\n\n### 6. `easing.ts` -- Easing Definitions\n\nSix types controlling interpolation curves.\n\n```typescript\ninterface LinearEasing       { type: \"linear\"; }\ninterface CubicBezierEasing  { type: \"cubic-bezier\"; x1: number; y1: number; x2: number; y2: number; }\ninterface SpringEasing        { type: \"spring\"; mass?: number; stiffness?: number; damping?: number; velocity?: number; }\ninterface StepEasing          { type: \"step\"; steps: number; position?: \"start\" | \"end\"; }\n\ntype EasingPreset = \"ease-in\" | \"ease-out\" | \"ease-in-out\";\n\ntype Easing = LinearEasing | CubicBezierEasing | SpringEasing | StepEasing | EasingPreset;\n```\n\n`Easing` accepts either a structured object or a named preset string. When omitted from a `Delta`, linear interpolation is assumed.\n\n---\n\n### 7. `delta.ts` -- Animation Instructions\n\nThree types that describe a single property change over a frame range.\n\n```typescript\ntype AnimatableProperty =\n  | \"frame.x\" | \"frame.y\"\n  | \"bounds.width\" | \"bounds.height\"\n  | \"opacity\" | \"rotation\"\n  | \"scale.x\" | \"scale.y\"\n  | \"anchorPoint.x\" | \"anchorPoint.y\"\n  | \"visual.shape.cornerRadius\"\n  | \"visual.fill.color\"\n  | \"visual.stroke.color\" | \"visual.stroke.width\"\n  | \"visual.style.fontSize\" | \"visual.style.color\";\n\ntype FrameRange = [number, number];  // [start, end], inclusive, 0-based\n\ninterface Delta {\n  id?: string;\n  layer: string;             // target layer ID\n  property: AnimatableProperty;\n  range: FrameRange;\n  from: unknown;\n  to: unknown;\n  easing?: Easing;\n  description?: string;\n  tags?: string[];\n}\n```\n\nA `Delta` is the atomic unit of animation. It says: \"on layer X, animate property Y from value A to value B across frames [start, end] using easing Z.\"\n\n---\n\n### 8. `state.ts` -- Animation States\n\nA named choreography grouping deltas with a duration.\n\n```typescript\ninterface State {\n  description?: string;\n  tags?: string[];\n  duration: number;   // in frames\n  deltas: Delta[];\n}\n```\n\nEach key in `AtelierDocument.states` is a state name (e.g. `\"idle\"`, `\"hover\"`, `\"entrance\"`). States can be sequenced or triggered independently.\n\n---\n\n### 9. `preset.ts` -- Reusable Animations\n\nTwo types for defining layer-agnostic delta templates.\n\n```typescript\ninterface PresetDelta {\n  property: AnimatableProperty;\n  offset?: [number, number];   // relative frame offset\n  from: unknown;\n  to: unknown;\n  easing?: Easing;\n}\n\ninterface Preset {\n  description?: string;\n  tags?: string[];\n  deltas: PresetDelta[];\n}\n```\n\nPresets omit the `layer` field. When applied, the target layer and absolute frame range are supplied at the call site.\n\n---\n\n### 10. `variable.ts` -- Template Variables\n\nTwo types for parameterizing documents.\n\n```typescript\ntype VariableType = \"string\" | \"number\" | \"color\" | \"asset\" | \"boolean\";\n\ninterface Variable {\n  type: VariableType;\n  default?: unknown;\n  description?: string;\n}\n```\n\nVariables allow a single `.atelier` document to serve as a template. Consumers supply values at render time; unset variables fall back to `default`.\n\n---\n\n### 11. `asset.ts` -- External Assets\n\nTwo types for referencing external files.\n\n```typescript\ntype AssetType = \"image\" | \"svg\" | \"font\" | \"animation\";\n\ninterface Asset {\n  type: AssetType;\n  src: string;         // file path or URL\n  description?: string;\n}\n```\n\nAssets are declared in `AtelierDocument.assets` and referenced by ID from `ImageVisual.assetId` or variable bindings.\n\n---\n\n### 12. `document.ts` -- Root Document\n\nTwo types that form the top-level structure.\n\n```typescript\ninterface Canvas {\n  width: number;\n  height: number;\n  fps: number;\n  background?: string;\n}\n\ninterface AtelierDocument {\n  version: string;\n  name: string;\n  description?: string;\n  tags?: string[];\n  canvas: Canvas;\n  variables?: Record<string, Variable>;\n  assets?: Record<string, Asset>;\n  presets?: Record<string, Preset>;\n  layers: Layer[];\n  states: Record<string, State>;\n}\n```\n\n`AtelierDocument` is the root type. Every `.atelier` YAML/JSON file deserializes to this shape.\n\n---\n\n## AnimatableProperty Catalog\n\nAll 16 properties that can be animated via `Delta`:\n\n| Property | Value Type | Description |\n|---|---|---|\n| `frame.x` | `UnitValue` (number or `\"N%\"`) | X position within parent |\n| `frame.y` | `UnitValue` (number or `\"N%\"`) | Y position within parent |\n| `bounds.width` | `UnitValue` (number or `\"N%\"`) | Layer width |\n| `bounds.height` | `UnitValue` (number or `\"N%\"`) | Layer height |\n| `opacity` | `number` (0--1) | Layer opacity |\n| `rotation` | `number` (degrees) | Rotation around anchor point |\n| `scale.x` | `number` | Horizontal scale factor |\n| `scale.y` | `number` | Vertical scale factor |\n| `anchorPoint.x` | `number` (0--1) | Anchor X (normalized) |\n| `anchorPoint.y` | `number` (0--1) | Anchor Y (normalized) |\n| `visual.shape.cornerRadius` | `number` | Corner radius (rect shapes only) |\n| `visual.fill.color` | `Color` | Fill color |\n| `visual.stroke.color` | `Color` | Stroke color |\n| `visual.stroke.width` | `number` | Stroke width in pixels |\n| `visual.style.fontSize` | `number` | Font size (text layers only) |\n| `visual.style.color` | `Color` | Text color (text layers only) |\n\n---\n\n## Export Summary\n\nAll 47 types re-exported from the barrel `index.ts`:\n\n| Module | Exports | Count |\n|---|---|---|\n| `units.ts` | `Pixel`, `Percentage`, `UnitValue` | 3 |\n| `coordinates.ts` | `Frame`, `Bounds`, `AnchorPoint` | 3 |\n| `color.ts` | `RGBAColor`, `HSLAColor`, `HexColor`, `Color` | 4 |\n| `shape.ts` | `PathPoint`, `RectShape`, `EllipseShape`, `PathShape`, `Shape`, `GradientStop`, `SolidFill`, `LinearGradientFill`, `RadialGradientFill`, `Fill`, `Stroke`, `TextStyle` | 12 |\n| `layer.ts` | `ShapeVisual`, `TextVisual`, `ImageVisual`, `GroupVisual`, `RefVisual`, `Visual`, `Layer` | 7 |\n| `easing.ts` | `LinearEasing`, `CubicBezierEasing`, `SpringEasing`, `StepEasing`, `EasingPreset`, `Easing` | 6 |\n| `delta.ts` | `AnimatableProperty`, `FrameRange`, `Delta` | 3 |\n| `state.ts` | `State` | 1 |\n| `preset.ts` | `PresetDelta`, `Preset` | 2 |\n| `variable.ts` | `VariableType`, `Variable` | 2 |\n| `asset.ts` | `AssetType`, `Asset` | 2 |\n| `document.ts` | `Canvas`, `AtelierDocument` | 2 |\n| **Total** | | **47** |\n\n---\n\n## Build\n\n```bash\npnpm --filter @atelier/types build       # compile with tsup\npnpm --filter @atelier/types typecheck   # tsc --noEmit\npnpm --filter @atelier/types test        # vitest run\npnpm --filter @atelier/types clean       # rm -rf dist\n```\n\nOutput lands in `dist/` with three artifacts:\n\n| File | Format |\n|---|---|\n| `dist/index.js` | ESM |\n| `dist/index.cjs` | CommonJS |\n| `dist/index.d.ts` | TypeScript declarations |\n\n---\n\n## Design Principles\n\n**Type-only, zero runtime.** Every export uses `export type` or `export interface`. The compiled JavaScript output is empty. This guarantees the package adds nothing to bundle size.\n\n**Flat union discrimination.** Shape, Visual, Fill, and Easing unions use a literal `type` field for narrowing:\n\n```typescript\nfunction renderVisual(v: Visual) {\n  switch (v.type) {\n    case \"shape\": /* v is ShapeVisual */ break;\n    case \"text\":  /* v is TextVisual  */ break;\n    case \"image\": /* v is ImageVisual */ break;\n    case \"group\": /* v is GroupVisual */ break;\n    case \"ref\":   /* v is RefVisual   */ break;\n  }\n}\n```\n\n**Flat layer list.** Layers are stored as a flat array with optional `parentId` references rather than a nested tree. This simplifies serialization and delta targeting while still supporting transform inheritance.\n\n**Stringly-typed property paths.** `AnimatableProperty` uses dot-notation strings (`\"frame.x\"`, `\"visual.fill.color\"`) to address nested fields. This keeps the `Delta` interface uniform regardless of property depth.\n","readmeFilename":"README.md"}