{"_id":"@boyntonsc/touch-indicator","_rev":"6-e3d735959e074b19ccc7aadf3229f9f7","name":"@boyntonsc/touch-indicator","dist-tags":{"latest":"1.2.0"},"versions":{"1.1.5":{"name":"@boyntonsc/touch-indicator","version":"1.1.5","_id":"@boyntonsc/touch-indicator@1.1.5","maintainers":[{"name":"boyntonsc","email":"boyntonsc@gmail.com"}],"dist":{"shasum":"d471e95e16d30cd22d9f1df3bd96a1181a47a7c1","tarball":"https://registry.npmjs.org/@boyntonsc/touch-indicator/-/touch-indicator-1.1.5.tgz","fileCount":39,"integrity":"sha512-qHF6jWaJmcmZtKch4t9gkGsUhwin8+ECq5BgV1HixqVufT2pgvTgoCFvfvIt9L3FTeEUFNsjBN4VgQ87KUhQ7Q==","signatures":[{"sig":"MEUCIAv+MbIWeApVJQ7EszxW2750weehMYFWxBVYXUyR+QjJAiEAnwA1rsvwzRmXVS+MGxNbhcQpuSs6if2ptjrQWBQVfbE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":59571},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"fef230339e6c1b9515663f80ac0501c49bfbaf49","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"message":"chore(release): ${nextRelease.version} [skip ci]"}]],"branches":["main"]},"scripts":{"dev":"concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","lint":"eslint src --ext .ts,.tsx","test":"bun test","build":"tsc && cp src/components/TouchIndicator.css dist/components/","format":"prettier --write \"src/**/*.{ts,tsx}\"","prepare":"husky","lint:fix":"eslint src --ext .ts,.tsx --fix","dev:debug":"DEBUG=true concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","typecheck":"tsc --noEmit","test:watch":"bun test --watch","format:check":"prettier --check \"src/**/*.{ts,tsx}\""},"_npmUser":{"name":"boyntonsc","email":"boyntonsc@gmail.com"},"_npmVersion":"11.10.0","description":"A React library for displaying a touch indicator that mimics Apple's Magic Trackpad behavior. Receive touch data via WebSocket or provide your own external data source.","directories":{},"_nodeVersion":"22.22.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29","husky":"^9.1.7","eslint":"^9.0.0","prettier":"^3.0.0","@types/bun":"latest","@types/react-dom":"^19.2.3","semantic-release":"^25.0.3","typescript-eslint":"^8.56.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^13.1.4","@testing-library/react":"^16.3.2","@semantic-release/changelog":"^6.0.3","@testing-library/jest-native":"^5.4.3"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","typescript":"^5","@types/react":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/touch-indicator_1.1.5_1771548772443_0.8219227496705761","host":"s3://npm-registry-packages-npm-production"}},"1.1.6":{"name":"@boyntonsc/touch-indicator","version":"1.1.6","_id":"@boyntonsc/touch-indicator@1.1.6","maintainers":[{"name":"boyntonsc","email":"boyntonsc@gmail.com"}],"dist":{"shasum":"e96a9466d6bab668685ebd6d31528ca00052e8fa","tarball":"https://registry.npmjs.org/@boyntonsc/touch-indicator/-/touch-indicator-1.1.6.tgz","fileCount":4,"integrity":"sha512-bEO2rgCzCgDT7Ndeowz/O1lIYM51xSdBK671XipQbmdrst7Cz1D+b+TYKBTycCnlo/Kb5oaY7yWNq4lA/UTP7A==","signatures":[{"sig":"MEUCIQCt3jfFcG0ut3RWo2hVj1ntxJdX5BJR/P8b09Fv445uQwIgbyISA464HPGXbHDOEH3TJUeJrH2rd9qVy+/uafgFq+g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33632},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f130c9df51ae69b973030fc4d427eef2ccb1c5bb","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"message":"chore(release): ${nextRelease.version} [skip ci]"}]],"branches":["main"]},"scripts":{"dev":"concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","lint":"eslint src --ext .ts,.tsx","test":"bun test","build":"tsup","format":"prettier --write \"src/**/*.{ts,tsx}\"","prepare":"husky","lint:fix":"eslint src --ext .ts,.tsx --fix","dev:debug":"DEBUG=true concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","typecheck":"tsc --noEmit","test:watch":"bun test --watch","format:check":"prettier --check \"src/**/*.{ts,tsx}\""},"_npmUser":{"name":"boyntonsc","email":"boyntonsc@gmail.com"},"_npmVersion":"11.10.0","description":"A React library for displaying a touch indicator that mimics Apple's Magic Trackpad behavior. Receive touch data via WebSocket or provide your own external data source.","directories":{},"_nodeVersion":"22.22.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.0.0","prettier":"^3.0.0","@types/bun":"latest","@types/react-dom":"^19.2.3","semantic-release":"^25.0.3","typescript-eslint":"^8.56.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^13.1.4","@testing-library/react":"^16.3.2","@semantic-release/changelog":"^6.0.3","@testing-library/jest-native":"^5.4.3"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","typescript":"^5","@types/react":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/touch-indicator_1.1.6_1771551611843_0.6255838753084395","host":"s3://npm-registry-packages-npm-production"}},"1.1.7":{"name":"@boyntonsc/touch-indicator","version":"1.1.7","_id":"@boyntonsc/touch-indicator@1.1.7","maintainers":[{"name":"boyntonsc","email":"boyntonsc@gmail.com"}],"dist":{"shasum":"c083f6e63a29003e1f5c521b9af680bd203da62a","tarball":"https://registry.npmjs.org/@boyntonsc/touch-indicator/-/touch-indicator-1.1.7.tgz","fileCount":4,"integrity":"sha512-WyCHWAgVShXBNbkXt7ZM37zh14ylQXHpW2yd0yIpaRxKY04TtP7w6a4KfZ4U55PVpSPU7dTYmheFMsHuidiw3Q==","signatures":[{"sig":"MEQCIHD+mRTrAPjPIYOyzdW9099wCHMUT48OACN0FuSxOFuJAiB16nHFHal/pR3Ihq3Vqlm80hKYq8TZzNxv/6l8gIXq4w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34186},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"94871daea3a069f82af546b9d43232d7112f5eae","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"message":"chore(release): ${nextRelease.version} [skip ci]"}]],"branches":["main"]},"scripts":{"dev":"concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","lint":"eslint src --ext .ts,.tsx","test":"bun test","build":"tsup","format":"prettier --write \"src/**/*.{ts,tsx}\"","prepare":"husky","lint:fix":"eslint src --ext .ts,.tsx --fix","dev:debug":"DEBUG=true concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","typecheck":"tsc --noEmit","test:watch":"bun test --watch","format:check":"prettier --check \"src/**/*.{ts,tsx}\""},"_npmUser":{"name":"boyntonsc","email":"boyntonsc@gmail.com"},"_npmVersion":"11.10.0","description":"A React library for displaying a touch indicator that mimics Apple's Magic Trackpad behavior. Receive touch data via WebSocket or provide your own external data source.","directories":{},"_nodeVersion":"22.22.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.0.0","prettier":"^3.0.0","@types/bun":"latest","@types/react-dom":"^19.2.3","semantic-release":"^25.0.3","typescript-eslint":"^8.56.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^13.1.4","@testing-library/react":"^16.3.2","@semantic-release/changelog":"^6.0.3","@testing-library/jest-native":"^5.4.3"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","typescript":"^5","@types/react":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/touch-indicator_1.1.7_1771861592846_0.15116414520806654","host":"s3://npm-registry-packages-npm-production"}},"1.1.8":{"name":"@boyntonsc/touch-indicator","version":"1.1.8","_id":"@boyntonsc/touch-indicator@1.1.8","maintainers":[{"name":"boyntonsc","email":"boyntonsc@gmail.com"}],"dist":{"shasum":"b0019c89186e8a9484378bc0206922d60dcefc29","tarball":"https://registry.npmjs.org/@boyntonsc/touch-indicator/-/touch-indicator-1.1.8.tgz","fileCount":4,"integrity":"sha512-NXlT4ejTp808aTlkEb7gaGKelGdtDfp4SrqIG/SP4mYHlu7ugiwrZz2DopN9nwxqgZnrrVGQ6bfeoPmKzxm03Q==","signatures":[{"sig":"MEUCIQDvOcakbw9Di4cLr8e8kI865YSThgKed0E6jKiizT8cyQIgNdtlZ2RNhEDsYeUU6HIjrBzAfjc1XEKGOdm5VNzwDik=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34331},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"bf78f0d896f87302fffbc102161cca28b8f6f47e","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"message":"chore(release): ${nextRelease.version} [skip ci]"}]],"branches":["main"]},"scripts":{"dev":"concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","lint":"eslint src --ext .ts,.tsx","test":"bun test","build":"tsup","format":"prettier --write \"src/**/*.{ts,tsx}\"","prepare":"husky","lint:fix":"eslint src --ext .ts,.tsx --fix","dev:debug":"DEBUG=true concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","typecheck":"tsc --noEmit","test:watch":"bun test --watch","format:check":"prettier --check \"src/**/*.{ts,tsx}\""},"_npmUser":{"name":"boyntonsc","email":"boyntonsc@gmail.com"},"_npmVersion":"11.10.0","description":"A React library for displaying a touch indicator that mimics Apple's Magic Trackpad behavior. Receive touch data via WebSocket or provide your own external data source.","directories":{},"_nodeVersion":"22.22.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.0.0","prettier":"^3.0.0","@types/bun":"latest","@types/react-dom":"^19.2.3","semantic-release":"^25.0.3","typescript-eslint":"^8.56.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^13.1.4","@testing-library/react":"^16.3.2","@semantic-release/changelog":"^6.0.3","@testing-library/jest-native":"^5.4.3"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","typescript":"^5","@types/react":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/touch-indicator_1.1.8_1771865478049_0.990335073282721","host":"s3://npm-registry-packages-npm-production"}},"1.1.9":{"name":"@boyntonsc/touch-indicator","version":"1.1.9","_id":"@boyntonsc/touch-indicator@1.1.9","maintainers":[{"name":"boyntonsc","email":"boyntonsc@gmail.com"}],"dist":{"shasum":"c0312efe167ac626ce9cf888f0862c7e26436d8c","tarball":"https://registry.npmjs.org/@boyntonsc/touch-indicator/-/touch-indicator-1.1.9.tgz","fileCount":4,"integrity":"sha512-8pVWhWtDZicF7bQxiC7xmowyETbRpYpQSUxCtOC6Dtw2Ua6f0pvjhJcbD1//CI5lHkls8SCU1rV4i14iFOKojQ==","signatures":[{"sig":"MEUCIQDN+6rgKkbQ1jIcpka13dzw/mRQWsEn1E47mndCJHCuiwIgUoaAog9b8n35nkiqsC2W/X1R2CmvyKZt8M61Q0hsbPk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34349},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f29a99b3fed59aacdb7702f34e04324df24d2ecb","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"message":"chore(release): ${nextRelease.version} [skip ci]"}]],"branches":["main"]},"scripts":{"dev":"concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","lint":"eslint src --ext .ts,.tsx","test":"bun test","build":"tsup","format":"prettier --write \"src/**/*.{ts,tsx}\"","prepare":"husky","lint:fix":"eslint src --ext .ts,.tsx --fix","dev:debug":"DEBUG=true concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","typecheck":"tsc --noEmit","test:watch":"bun test --watch","format:check":"prettier --check \"src/**/*.{ts,tsx}\""},"_npmUser":{"name":"boyntonsc","email":"boyntonsc@gmail.com"},"_npmVersion":"11.10.0","description":"A React library for displaying a touch indicator that mimics Apple's Magic Trackpad behavior. Receive touch data via WebSocket or provide your own external data source.","directories":{},"_nodeVersion":"22.22.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"jest":"29","tsup":"^8.5.1","husky":"^9.1.7","eslint":"^9.0.0","prettier":"^3.0.0","@types/bun":"latest","@types/react-dom":"^19.2.3","semantic-release":"^25.0.3","typescript-eslint":"^8.56.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^13.1.4","@testing-library/react":"^16.3.2","@semantic-release/changelog":"^6.0.3","@testing-library/jest-native":"^5.4.3"},"peerDependencies":{"react":"^18.0.0 || ^19.0.0","typescript":"^5","@types/react":"^18.0.0 || ^19.0.0"},"_npmOperationalInternal":{"tmp":"tmp/touch-indicator_1.1.9_1771865974837_0.12898448230823023","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@boyntonsc/touch-indicator","version":"1.2.0","type":"module","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"scripts":{"prepare":"husky","test":"bun test","test:watch":"bun test --watch","lint":"eslint src --ext .ts,.tsx","lint:fix":"eslint src --ext .ts,.tsx --fix","format":"prettier --write \"src/**/*.{ts,tsx}\"","format:check":"prettier --check \"src/**/*.{ts,tsx}\"","typecheck":"tsc --noEmit","build":"tsup","dev":"concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\"","dev:debug":"DEBUG=true concurrently --kill-others \"cd server && bun run start\" \" cd ./demo && bun run dev\""},"release":{"branches":["main"],"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/changelog","@semantic-release/npm",["@semantic-release/git",{"message":"chore(release): ${nextRelease.version} [skip ci]"}]]},"devDependencies":{"@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^13.1.4","@testing-library/jest-native":"^5.4.3","@testing-library/react":"^16.3.2","@types/bun":"latest","@types/react-dom":"^19.2.3","eslint":"^9.0.0","husky":"^9.1.7","jest":"29","prettier":"^3.0.0","semantic-release":"^25.0.3","tsup":"^8.5.1","typescript-eslint":"^8.56.0"},"peerDependencies":{"@types/react":"^18.0.0 || ^19.0.0","react":"^18.0.0 || ^19.0.0","typescript":"^5"},"dependencies":{},"publishConfig":{"access":"public"},"gitHead":"5f26f3f7f1099c7f8a9f25d28cabacf19b06d5e6","_id":"@boyntonsc/touch-indicator@1.2.0","description":"A React library for displaying a touch indicator that mimics Apple's Magic Trackpad behavior. Receive touch data via WebSocket or provide your own external data source.","_nodeVersion":"22.22.0","_npmVersion":"11.10.0","dist":{"integrity":"sha512-CVYmN03wA+IU+PzvAHyU+ftwQIQ7b45cLe0p+22OtAgsacl8ul4XvJRiH6h04DbReP2nDXCQMSOt6O6jyd587g==","shasum":"ab1c9a59201bb2d36e64c29e75961d384de9bab3","tarball":"https://registry.npmjs.org/@boyntonsc/touch-indicator/-/touch-indicator-1.2.0.tgz","fileCount":4,"unpackedSize":32324,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDHXVdc1jyMUzaSu5nHqaZ5RPS4wqtSweGOHCLShUDKpgIgXkDLHMyF6TKrq71c1VpBJZSGZgVEtcbgZ/a+hZRb09w="}]},"_npmUser":{"name":"boyntonsc","email":"boyntonsc@gmail.com"},"directories":{},"maintainers":[{"name":"boyntonsc","email":"boyntonsc@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/touch-indicator_1.2.0_1771876480975_0.9803344161836711"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-20T00:52:52.338Z","modified":"2026-02-23T19:54:41.244Z","1.1.5":"2026-02-20T00:52:52.599Z","1.1.6":"2026-02-20T01:40:11.979Z","1.1.7":"2026-02-23T15:46:32.992Z","1.1.8":"2026-02-23T16:51:18.195Z","1.1.9":"2026-02-23T16:59:34.995Z","1.2.0":"2026-02-23T19:54:41.123Z"},"description":"A React library for displaying a touch indicator that mimics Apple's Magic Trackpad behavior. Receive touch data via WebSocket or provide your own external data source.","maintainers":[{"name":"boyntonsc","email":"boyntonsc@gmail.com"}],"readme":"# Touch Indicator\n\nA React library for displaying a touch indicator that mimics Apple's Magic Trackpad behavior. Receive touch data via WebSocket or provide your own external data source.\n\n![Touch Indicator Demo](https://via.placeholder.com/800x400/2196F3/ffffff?text=Touch+Indicator+Demo)\n\n## Features\n\n- **Magic Trackpad-like visual** - Circular touch indicator that follows finger movement\n- **WebSocket or External Source** - Auto-connect to a WebSocket server or provide your own touch data\n- **Configurable Appearance** - Customize size, color, and opacity\n- **Animation Effects** - Pulse on tap, ripple effect on touch\n- **Sensitivity Adjustment** - Scale movement for different trackpad sensitivities\n- **Connection State Handling** - Visual feedback for connecting, connected, disconnected, and error states\n- **Callbacks** - Handle tap and move events for custom functionality\n- **TypeScript Support** - Full TypeScript support with type definitions\n\n## Installation\n\n```bash\nbun add touch-indicator\n# or\nnpm install touch-indicator\n```\n\n## Quick Start\n\n### WebSocket Mode\n\nAutomatically connects to a WebSocket server:\n\n```tsx\nimport { TouchIndicator } from 'touch-indicator';\n\nfunction App() {\n  return <TouchIndicator connection={{ wsUrl: 'ws://localhost:8080/ws' }} />;\n}\n```\n\n### External Source Mode\n\nProvide your own touch data:\n\n```tsx\nimport { TouchIndicator, useTouchIndicator } from 'touch-indicator';\n\nfunction App() {\n  const { connectionState, lastMessage } = useTouchIndicator({\n    wsUrl: 'ws://localhost:8080/ws',\n  });\n\n  return <TouchIndicator source={{ message: lastMessage, connectionState }} />;\n}\n```\n\n## API Reference\n\n### TouchIndicator Props\n\n| Prop         | Type                                           | Default     | Description                                                              |\n| ------------ | ---------------------------------------------- | ----------- | ------------------------------------------------------------------------ |\n| `source`     | `TouchIndicatorSource`                         | `undefined` | External message source (use instead of `connection` for manual control) |\n| `connection` | `TouchIndicatorConnection`                     | `undefined` | WebSocket configuration (use for auto-connect mode)                      |\n| `visual`     | `TouchIndicatorVisual`                         | See below   | Visual appearance settings                                               |\n| `animation`  | `TouchIndicatorAnimation`                      | See below   | Animation configuration                                                  |\n| `onTap`      | `() => void`                                   | `undefined` | Callback fired on tap                                                    |\n| `onMove`     | `(position: { x: number; y: number }) => void` | `undefined` | Callback fired on move                                                   |\n| `className`  | `string`                                       | `undefined` | Additional CSS class                                                     |\n| `style`      | `React.CSSProperties`                          | `undefined` | Additional inline styles                                                 |\n| `show`       | `boolean`                                      | `true`      | Whether to show the indicator                                            |\n| `disabled`   | `boolean`                                      | `false`     | Disable the indicator                                                    |\n\n### TouchIndicatorSource\n\n```ts\ninterface TouchIndicatorSource {\n  message?: TouchMessage | null;\n  connectionState?: ConnectionState;\n}\n```\n\n### TouchIndicatorConnection\n\n```ts\ninterface TouchIndicatorConnection {\n  wsUrl?: string; // WebSocket URL (default: 'ws://localhost:8080')\n  reconnectAttempts?: number; // Max reconnection attempts\n  reconnectInterval?: number; // Reconnection interval in ms\n  onConnect?: () => void; // Called when connected\n  onDisconnect?: () => void; // Called when disconnected\n  onError?: (error: Event) => void; // Called on WebSocket error\n}\n```\n\n### TouchIndicatorVisual\n\n```ts\ninterface TouchIndicatorVisual {\n  size?: number; // Diameter in pixels (default: 20)\n  color?: string; // Color hex (default: '#2196F3')\n  opacity?: number; // Opacity 0-1 (default: 0.8)\n}\n```\n\n### TouchIndicatorAnimation\n\n```ts\ninterface TouchIndicatorAnimation {\n  transitionDuration?: number; // CSS transition duration in ms (default: 0)\n  sensitivity?: number; // Movement sensitivity multiplier (default: 1.8)\n  pulseScale?: number; // Scale factor when tapping (default: 1.5)\n  pulseDuration?: number; // Pulse animation duration in ms (default: 150)\n  rippleScale?: number; // Ripple effect scale (default: 2.5)\n  rippleDuration?: number; // Ripple animation duration in ms (default: 300)\n}\n```\n\n## Examples\n\n### Custom Appearance\n\n```tsx\nimport { TouchIndicator } from 'touch-indicator';\n\nfunction CustomIndicator() {\n  return (\n    <TouchIndicator\n      visual={{\n        size: 30,\n        color: '#FF6B6B',\n        opacity: 0.9,\n      }}\n    />\n  );\n}\n```\n\n### With Callbacks\n\n```tsx\nimport { TouchIndicator } from 'touch-indicator';\n\nfunction WithCallbacks() {\n  const handleTap = () => {\n    console.log('Tapped!');\n  };\n\n  const handleMove = position => {\n    console.log(`Moved to: ${position.x}, ${position.y}`);\n  };\n\n  return (\n    <TouchIndicator\n      source={{ message: { phase: 'move', dx: 10, dy: 20 } }}\n      onTap={handleTap}\n      onMove={handleMove}\n    />\n  );\n}\n```\n\n### Full Configuration\n\n```tsx\nimport { TouchIndicator } from 'touch-indicator';\n\nfunction FullConfig() {\n  return (\n    <TouchIndicator\n      connection={{\n        wsUrl: 'ws://localhost:8080/ws',\n        reconnectAttempts: 5,\n        reconnectInterval: 1000,\n        onConnect: () => console.log('Connected'),\n        onDisconnect: () => console.log('Disconnected'),\n        onError: err => console.error('Error:', err),\n      }}\n      visual={{\n        size: 25,\n        color: '#4ECDC4',\n        opacity: 0.85,\n      }}\n      animation={{\n        transitionDuration: 50,\n        sensitivity: 2.0,\n        pulseScale: 1.3,\n        pulseDuration: 200,\n        rippleScale: 2.0,\n        rippleDuration: 400,\n      }}\n      className=\"my-touch-indicator\"\n      style={{ zIndex: 9999 }}\n    />\n  );\n}\n```\n\n### Manual Connection Control\n\n```tsx\nimport { TouchIndicator, useTouchIndicator } from 'touch-indicator';\n\nfunction ManualControl() {\n  const { connectionState, lastMessage, connect, disconnect } = useTouchIndicator({\n    wsUrl: 'ws://localhost:8080/ws',\n  });\n\n  return (\n    <div>\n      <button onClick={connect}>Connect</button>\n      <button onClick={disconnect}>Disconnect</button>\n      <span>Status: {connectionState}</span>\n\n      <TouchIndicator source={{ message: lastMessage, connectionState }} />\n    </div>\n  );\n}\n```\n\n## WebSocket Message Format\n\nThe WebSocket server should send messages in this format:\n\n```ts\ninterface TouchMessage {\n  phase: 'start' | 'move' | 'tap';\n  dx: number; // Delta X movement\n  dy: number; // Delta Y movement\n}\n```\n\nExample message:\n\n```json\n{ \"phase\": \"move\", \"dx\": 10, \"dy\": -5 }\n```\n\n## Running the Demo\n\nStart both the WebSocket server and demo application:\n\n```bash\nbun run dev\n```\n\nThis runs:\n\n- WebSocket server on `ws://localhost:8080`\n- Demo app on `http://localhost:3000`\n\n## Additional Exports\n\n### Hooks\n\n```ts\nimport { useTouchIndicator, useTouchIndicatorTracking } from 'touch-indicator';\n```\n\n- `useTouchIndicator` - WebSocket connection management\n- `useTouchIndicatorTracking` - Position tracking and state\n\n### Utilities\n\n```ts\nimport {\n  clamp,\n  applySensitivity,\n  clampPosition,\n  getPositionStyle,\n  getIndicatorStyle,\n  getRippleStyle,\n} from 'touch-indicator';\n```\n\n- `clamp` - Clamp a value between min and max\n- `applySensitivity` - Apply sensitivity multiplier to delta values\n- `clampPosition` - Clamp position within bounds\n- `getPositionStyle` - Generate position styles\n- `getIndicatorStyle` - Generate indicator styles\n- `getRippleStyle` - Generate ripple effect styles\n\n## License\n\nMIT\n","readmeFilename":"README.md"}