{"_id":"@busyexplore/zotonic-curve-editor","name":"@busyexplore/zotonic-curve-editor","dist-tags":{"beta":"0.0.1-beta.0","latest":"0.0.1-beta.0"},"versions":{"0.0.1-beta.0":{"name":"@busyexplore/zotonic-curve-editor","private":false,"version":"0.0.1-beta.0","type":"module","main":"dist/zotonic-curve-editor.umd.js","module":"dist/zotonic-curve-editor.es.js","scripts":{"dev":"set NODE_OPTIONS=--openssl-legacy-provider && vite","build":"vite build","lint":"eslint .","preview":"vite preview","deploy":"npm version prerelease --preid=beta --no-git-tag-version && npm publish --tag beta"},"dependencies":{"@busyexplore/zotonic-command-emitter":"0.0.1-beta.7","mitt":"^3.0.1","react":"^16.8 || ^17 || ^18","react-dom":"^16.8 || ^17 || ^18"},"peerDependencies":{"react":"^16.8 || ^17 || ^18","react-dom":"^16.8 || ^17 || ^18"},"devDependencies":{"@eslint/js":"^9.29.0","@types/react":"^19.1.8","@types/react-dom":"^19.1.6","@vitejs/plugin-react":"^4.6.0","eslint":"^9.29.0","eslint-plugin-react-hooks":"^5.2.0","eslint-plugin-react-refresh":"^0.4.20","globals":"^16.2.0","sass-embedded":"1.89.2","vite":"^6.3.5"},"_id":"@busyexplore/zotonic-curve-editor@0.0.1-beta.0","gitHead":"fa929cb9e9ea742dfc9d8c3c5369a89b7be8f711","description":"Build a multi-point ease curve visually and export it as either a lossless editor snapshot or a ready-to-use player ease format.","_nodeVersion":"20.9.0","_npmVersion":"10.1.0","dist":{"integrity":"sha512-Nq1j9uABX/mwjCwuJHFI0wfoiYdYEnP2bBxj4S60zV/7qSnghDtu2SHreFz2R3vfN8NIateWwVY6qtQLVHXs3w==","shasum":"34cf5e31540125b84eb22ee19e34331505dc440c","tarball":"https://registry.npmjs.org/@busyexplore/zotonic-curve-editor/-/zotonic-curve-editor-0.0.1-beta.0.tgz","fileCount":4,"unpackedSize":42171,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDA6lxpRK4HqsxGeaxclJs9KML48hcyJTscy8RItGAFcAiAtFwVZ75BeY1+/JwZX5aBwq9uP4S3t4OqTGQ/tJlpMPQ=="}]},"_npmUser":{"name":"busyexplore","email":"suprise.mlimi97@gmail.com"},"directories":{},"maintainers":[{"name":"busyexplore","email":"suprise.mlimi97@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/zotonic-curve-editor_0.0.1-beta.0_1786828280723_0.6703257504859141"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-15T21:11:20.572Z","0.0.1-beta.0":"2026-08-15T21:11:20.875Z","modified":"2026-08-15T21:11:21.147Z"},"maintainers":[{"name":"busyexplore","email":"suprise.mlimi97@gmail.com"}],"description":"Build a multi-point ease curve visually and export it as either a lossless editor snapshot or a ready-to-use player ease format.","readme":"# Ease Curve Editor\r\n\r\nBuild a multi-point ease curve visually and export it as either a lossless editor snapshot or a ready-to-use player ease format.\r\n\r\n## Install\r\n\r\n```bash\r\nnpm install @busyexplore/zotonic-curve-editor\r\n```\r\n\r\n```bash\r\nyarn add  @busyexplore/zotonic-command-emitter\r\n```\r\n\r\n## Quick start\r\n\r\n```jsx\r\nimport EaseCurveEditor from \"@busyexplore/zotonic-curve-editor\";\r\n\r\nfunction App() {\r\n  const {\r\n    CurveEditor,\r\n    exportEditorData,\r\n    importEditorData\r\n  } = EaseCurveEditor();\r\n\r\n  return (\r\n    <>\r\n      <CurveEditor />\r\n\r\n      <button onClick={() => console.log(exportEditorData())}>\r\n        Log current ease\r\n      </button>\r\n    </>\r\n  );\r\n}\r\n```\r\n\r\n`EaseCurveEditor()` is a hook-like function component helper — call it inside a component body.\r\n\r\nIt returns:\r\n\r\n| Return value | Type | Description |\r\n|---|---|---|\r\n| `CurveEditor` | Component | Renders the curve editor panel. Mount it once. |\r\n| `exportEditorData()` | `() => { editorFormat, playerFormat } \\| undefined` | Reads the latest snapshot emitted by the editor. Returns `undefined` and warns if the editor has not mounted/reported ready yet. |\r\n| `importEditorData(data)` | `(jsonString) => void` | Pushes an editor-format JSON string into the mounted `CurveEditor`, replacing its current curve. No-ops and warns if the editor is not ready yet. |\r\n| `CURVE_EDITOR_TOOL` | `object` | The raw command/action constants, in case you want to listen to the emitter yourself. |\r\n\r\n## How it works: the command emitter\r\n\r\n`CurveEditor` does not take props for data in/out. It communicates over `@busyexplore/zotonic-command-emitter` using the command name `CURVE_EDITOR_TOOL.EDITOR_COMMAND` (`\"CURVE_EDITOR\"`).\r\n\r\nThis allows the editor to live anywhere in the React tree while still being controlled from a parent.\r\n\r\n| Action | Direction | Payload | When |\r\n|---|---|---|---|\r\n| `ACTION_READY` | editor → app | `{ editorFormat, playerFormat }` | Shortly after mount, once. |\r\n| `ACTION_UPDATE` | editor → app | `{ editorFormat, playerFormat }` | Whenever the curve changes: point moved, added, deleted, or shape changed. |\r\n| `ACTION_IMPORT` | app → editor | `{ editorImport: jsonString }` | Sent via `importEditorData()` to replace the curve. |\r\n| `ACTION_ERROR` | editor → app | `{ message }` | If an `ACTION_IMPORT` payload fails to parse. |\r\n\r\n`EaseCurveEditor()` already listens for `ACTION_READY` and `ACTION_UPDATE` for you and exposes the result through `exportEditorData()`.\r\n\r\nYou only need to interact with the emitter directly for advanced use cases.\r\n\r\n## Data formats\r\n\r\n### Editor format (lossless)\r\n\r\n`editorFormat` contains every point exactly as placed, along with timing metadata.\r\n\r\nIt can be round-tripped through export → import without adding or dropping points.\r\n\r\n```json\r\n{\r\n  \"version\": 1,\r\n  \"points\": [\r\n    { \"x\": 0, \"y\": 0, \"shape\": \"sine\", \"locked\": true },\r\n    { \"x\": 0.35, \"y\": 0.15, \"shape\": \"sine\", \"locked\": false },\r\n    { \"x\": 0.7, \"y\": 0.85, \"shape\": \"linear\", \"locked\": false },\r\n    { \"x\": 1, \"y\": 1, \"shape\": \"linear\", \"locked\": true }\r\n  ],\r\n  \"meta\": {\r\n    \"easeName\": \"myEase\",\r\n    \"startFrame\": 0,\r\n    \"endFrame\": 24\r\n  }\r\n}\r\n```\r\n\r\n### Player format\r\n\r\n`playerFormat` is a stripped and rounded array intended for use by an ease evaluator/player.\r\n\r\n```json\r\n[\r\n  { \"x\": 0, \"y\": 0, \"shape\": \"sine\" },\r\n  { \"x\": 0.35, \"y\": 0.15, \"shape\": \"sine\" },\r\n  { \"x\": 0.7, \"y\": 0.85, \"shape\": \"linear\" },\r\n  { \"x\": 1, \"y\": 1, \"shape\": \"linear\" }\r\n]\r\n```\r\n\r\nAvailable `shape` values per segment:\r\n\r\n- `linear`\r\n- `sine`\r\n- `square`\r\n\r\n## Interacting with the curve\r\n\r\n- **Drag a point** — mouse, touch, or pen.\r\n- **Double-click the canvas** — adds a new point at the nearest spot on the curve.\r\n- **Select a point** — click or tap it, then choose its shape using the shape buttons.\r\n- **Delete a point** — select a point and click **Delete point**. Locked start/end points cannot be deleted.\r\n\r\n## Theming\r\n\r\nColors are exposed as CSS custom properties in `CurveEditor.scss`, prefixed with `--ece-`.\r\n\r\nOverride any subset of them on your own `:root`:\r\n\r\n```css\r\n:root {\r\n  --ece-accent-linear: #4dd0e1;\r\n  --ece-bg-panel-start: #1a1024;\r\n}\r\n```\r\n\r\n## Architecture\r\n\r\nThe editor is intentionally split into a small set of focused modules:\r\n\r\n- `EaseCurveEditor.jsx` — public entry point and command-emitter integration.\r\n- `CurveEditor.jsx` — curve editor UI and interaction.\r\n- `EditorUtil.js` — curve calculations, sampling, and data conversion.\r\n- `CURVE_EDITOR_TOOL.js` — shared command/action constants.\r\n- `CurveEditor.scss` — editor styling and theme variables.\r\n\r\n<!-- ## License\r\n\r\nMIT -->\r\n","readmeFilename":"README.md","_rev":"1-9e82cb4e6f35a54ca90b8985c17eb7f2"}