{"id":31805104,"url":"https://github.com/munimtechnologies/munim-pencilkit","last_synced_at":"2026-01-20T17:57:59.974Z","repository":{"id":316676919,"uuid":"1064398756","full_name":"munimtechnologies/munim-pencilkit","owner":"munimtechnologies","description":null,"archived":false,"fork":false,"pushed_at":"2025-09-26T02:31:18.000Z","size":274,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-26T03:48:58.295Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/munimtechnologies.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-26T01:30:58.000Z","updated_at":"2025-09-26T02:31:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"fe8f5195-d2bd-431b-9bf1-128d5a6eb57e","html_url":"https://github.com/munimtechnologies/munim-pencilkit","commit_stats":null,"previous_names":["munimtechnologies/munim-pencilkit"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/munimtechnologies/munim-pencilkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munimtechnologies%2Fmunim-pencilkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munimtechnologies%2Fmunim-pencilkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munimtechnologies%2Fmunim-pencilkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munimtechnologies%2Fmunim-pencilkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/munimtechnologies","download_url":"https://codeload.github.com/munimtechnologies/munim-pencilkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/munimtechnologies%2Fmunim-pencilkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279005963,"owners_count":26084004,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-11T02:46:30.143Z","updated_at":"2025-10-11T02:46:32.285Z","avatar_url":"https://github.com/munimtechnologies.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- Banner Image --\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/munimtechnologies/munim-pencilkit\"\u003e\n    \u003cimg alt=\"Munim Technologies PencilKit\" height=\"128\" src=\"./.github/resources/banner.png?v=3\"\u003e\n    \u003ch1 align=\"center\"\u003emunim-pencilkit\u003c/h1\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n   \u003ca aria-label=\"Package version\" href=\"https://www.npmjs.com/package/munim-pencilkit\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Package version\" src=\"https://img.shields.io/npm/v/munim-pencilkit.svg?style=flat-square\u0026label=Version\u0026labelColor=000000\u0026color=0066CC\" /\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"Package is free to use\" href=\"https://github.com/munimtechnologies/munim-pencilkit/blob/main/LICENSE\" target=\"_blank\"\u003e\n    \u003cimg alt=\"License: MIT\" src=\"https://img.shields.io/badge/License-MIT-success.svg?style=flat-square\u0026color=33CC12\" target=\"_blank\" /\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"package downloads\" href=\"https://www.npmtrends.com/munim-pencilkit\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Downloads\" src=\"https://img.shields.io/npm/dm/munim-pencilkit.svg?style=flat-square\u0026labelColor=gray\u0026color=33CC12\u0026label=Downloads\" /\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"total package downloads\" href=\"https://www.npmjs.com/package/munim-pencilkit\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Total Downloads\" src=\"https://img.shields.io/npm/dt/munim-pencilkit.svg?style=flat-square\u0026labelColor=gray\u0026color=0066CC\u0026label=Total%20Downloads\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca aria-label=\"try with expo\" href=\"https://docs.expo.dev/\"\u003e\u003cb\u003eWorks with Expo\u003c/b\u003e\u003c/a\u003e\n\u0026ensp;•\u0026ensp;\n  \u003ca aria-label=\"documentation\" href=\"https://github.com/munimtechnologies/munim-pencilkit#readme\"\u003eRead the Documentation\u003c/a\u003e\n\u0026ensp;•\u0026ensp;\n  \u003ca aria-label=\"report issues\" href=\"https://github.com/munimtechnologies/munim-pencilkit/issues\"\u003eReport Issues\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch6 align=\"center\"\u003eFollow Munim Technologies\u003c/h6\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca aria-label=\"Follow Munim Technologies on GitHub\" href=\"https://github.com/munimtechnologies\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Munim Technologies on GitHub\" src=\"https://img.shields.io/badge/GitHub-222222?style=for-the-badge\u0026logo=github\u0026logoColor=white\" target=\"_blank\" /\u003e\n  \u003c/a\u003e\u0026nbsp;\n  \u003ca aria-label=\"Follow Munim Technologies on LinkedIn\" href=\"https://linkedin.com/in/sheehanmunim\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Munim Technologies on LinkedIn\" src=\"https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge\u0026logo=linkedin\u0026logoColor=white\" target=\"_blank\" /\u003e\n  \u003c/a\u003e\u0026nbsp;\n  \u003ca aria-label=\"Visit Munim Technologies Website\" href=\"https://munimtech.com\" target=\"_blank\"\u003e\n    \u003cimg alt=\"Munim Technologies Website\" src=\"https://img.shields.io/badge/Website-0066CC?style=for-the-badge\u0026logo=globe\u0026logoColor=white\" target=\"_blank\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Introduction\n\n**munim-pencilkit** is a React Native library for Apple PencilKit integration with comprehensive Apple Pencil support. This library provides advanced stroke analysis, raw sensor data collection, haptic feedback, and professional drawing tools using well-established iOS APIs.\n\n**Fully compatible with Expo!** Works seamlessly with both Expo managed and bare workflows.\n\n**Comprehensive Apple Pencil Support!** Includes pressure sensitivity, tilt detection, predicted touches, coalesced touches, estimated properties, and haptic feedback using verified iOS APIs.\n\n## Table of contents\n\n- [📚 Documentation](#-documentation)\n- [🚀 Features](#-features)\n- [📦 Installation](#-installation)\n- [⚡ Quick Start](#-quick-start)\n- [🔧 API Reference](#-api-reference)\n- [📖 Usage Examples](#-usage-examples)\n- [🎨 Apple Pencil Pro Features](#-apple-pencil-pro-features)\n- [🔍 Troubleshooting](#-troubleshooting)\n- [👏 Contributing](#-contributing)\n- [📄 License](#-license)\n\n## 📚 Documentation\n\n\u003cp\u003eLearn about building PencilKit apps \u003ca aria-label=\"documentation\" href=\"https://github.com/munimtechnologies/munim-pencilkit#readme\"\u003ein our documentation!\u003c/a\u003e\u003c/p\u003e\n\n- [Getting Started](#-installation)\n- [API Reference](#-api-reference)\n- [Usage Examples](#-usage-examples)\n- [Apple Pencil Pro Features](#-apple-pencil-pro-features)\n- [Troubleshooting](#-troubleshooting)\n\n## 🚀 Features\n\n### Core PencilKit Integration\n\n- 🎨 **Full PencilKit Framework** - Complete Apple PencilKit framework support\n- ✏️ **Professional Drawing Tools** - Pen, pencil, marker, eraser, and lasso tools\n- 📱 **Native Performance** - Built with Turbo modules for optimal performance\n- 🎯 **TypeScript Support** - Full TypeScript definitions included\n- 🔄 **Undo/Redo Support** - Built-in drawing history management\n- 🎛️ **Configurable** - Customizable drawing policies and tool settings\n- 🚀 **Expo Compatible** - Works seamlessly with Expo managed and bare workflows\n\n### Apple Pencil Data Capture\n\n- 📊 **Raw Sensor Data** - Pressure, tilt, azimuth, force, and location data\n- 🎯 **Precise Location** - High-precision touch coordinates\n- ⚡ **Real-time Streaming** - Live Apple Pencil data streaming\n- 🔄 **Coalesced Touches** - High-fidelity input for smooth drawing\n- 🔮 **Predicted Touches** - Latency compensation for responsive drawing\n- 📈 **Property Tracking** - Estimated properties and refinement updates\n\n### Apple Pencil Advanced Features\n\n- 📊 **Pressure Sensitivity** - Full pressure detection with Apple's recommended curves\n- 🎯 **Tilt Detection** - Altitude and azimuth angle tracking\n- 🧭 **Azimuth Unit Vector** - Efficient azimuth direction vector for transforms\n- 🔄 **Coalesced Touches** - Optimized high-fidelity input for smooth drawing\n- 🔮 **Predicted Touches** - Latency compensation for responsive drawing\n- 📈 **Estimated Properties** - Real-time property refinement with `touchesEstimatedPropertiesUpdated`\n- 📱 **Haptic Feedback** - Tactile responses for interactions\n- 🎢 **Motion Tracking** - Core Motion gyroscope data for barrel roll detection\n- 🧭 **Device Orientation** - Roll, pitch, and yaw angle tracking\n- ⚡ **Velocity \u0026 Acceleration** - Real-time stroke velocity and acceleration tracking\n- 📐 **Stroke Analysis** - Advanced stroke smoothness and consistency analysis\n\n### Advanced Capabilities\n\n- 🧮 **Perpendicular Force** - Computed perpendicular force for accurate pressure\n- 📊 **Estimated Properties** - Track and handle property refinements\n- 🎨 **Custom Brush Logic** - Advanced brush behavior based on sensor data\n- 🔧 **Dynamic Updates** - Update drawing configuration while active\n- 📱 **Cross-Platform** - Works on all iOS devices with Apple Pencil support\n- 📐 **Stroke Analysis** - Real-time stroke smoothness, consistency, and quality metrics\n- ⚡ **Performance Optimized** - Apple's recommended coalesced touches handling\n- 🎯 **Pressure Curves** - Natural pressure response using Apple's recommended algorithms\n\n## 📦 Installation\n\n### React Native CLI\n\n```bash\nnpm install munim-pencilkit\n# or\nyarn add munim-pencilkit\n```\n\n### Expo\n\n```bash\nnpx expo install munim-pencilkit\n```\n\n\u003e **Note**: This library requires Expo SDK 50+ and works with both managed and bare workflows.\n\n### iOS Setup\n\nFor iOS, add PencilKit framework to your project:\n\n1. Open your project in Xcode\n2. Select your target\n3. Go to \"Build Phases\" → \"Link Binary With Libraries\"\n4. Add `PencilKit.framework`\n\n**For Expo projects**, PencilKit framework is automatically included. However, you need to add the following permissions to your `app.json`:\n\n```json\n{\n  \"expo\": {\n    \"ios\": {\n      \"infoPlist\": {\n        \"NSApplePencilUsageDescription\": \"This app uses Apple Pencil for drawing and note-taking\"\n      }\n    }\n  }\n}\n```\n\n## ⚡ Quick Start\n\n### Basic Usage\n\n```tsx\nimport React, { useRef } from 'react';\nimport { View, StyleSheet } from 'react-native';\nimport { PencilKitView, type PencilKitConfig } from 'munim-pencilkit';\n\nexport default function DrawingScreen() {\n  const pencilKitRef = useRef\u003cany\u003e(null);\n\n  const config: PencilKitConfig = {\n    allowsFingerDrawing: true,\n    allowsPencilOnlyDrawing: false,\n    isRulerActive: false,\n    drawingPolicy: 'default',\n  };\n\n  return (\n    \u003cView style={styles.container}\u003e\n      \u003cPencilKitView\n        ref={pencilKitRef}\n        style={styles.canvas}\n        config={config}\n        enableApplePencilData={true}\n        enableToolPicker={true}\n        onApplePencilData={(data) =\u003e {\n          console.log('Apple Pencil Data:', data);\n        }}\n        onDrawingChange={(drawing) =\u003e {\n          console.log('Drawing changed:', drawing);\n        }}\n      /\u003e\n    \u003c/View\u003e\n  );\n}\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n  },\n  canvas: {\n    flex: 1,\n  },\n});\n```\n\n### Apple Pencil Advanced Usage\n\n```tsx\nimport React, { useRef } from 'react';\nimport { View, StyleSheet } from 'react-native';\nimport {\n  PencilKitView,\n  type PencilKitConfig,\n  type ApplePencilData,\n  type ApplePencilMotionData,\n} from 'munim-pencilkit';\n\nexport default function AdvancedDrawingScreen() {\n  const pencilKitRef = useRef\u003cany\u003e(null);\n\n  const config: PencilKitConfig = {\n    allowsFingerDrawing: true,\n    allowsPencilOnlyDrawing: false,\n    isRulerActive: false,\n    drawingPolicy: 'default',\n    enableHapticFeedback: true,\n  };\n\n  return (\n    \u003cView style={styles.container}\u003e\n      \u003cPencilKitView\n        ref={pencilKitRef}\n        style={styles.canvas}\n        config={config}\n        enableApplePencilData={true}\n        enableToolPicker={true}\n        enableHapticFeedback={true}\n        enableMotionTracking={true}\n        onApplePencilData={(data: ApplePencilData) =\u003e {\n          console.log('Advanced Apple Pencil Data:', {\n            pressure: data.pressure,\n            perpendicularForce: data.perpendicularForce,\n            azimuth: data.azimuth,\n            azimuthUnitVector: data.azimuthUnitVector,\n            rollAngle: data.rollAngle,\n            preciseLocation: data.preciseLocation,\n            estimatedProperties: data.estimatedProperties,\n          });\n        }}\n        onApplePencilMotion={(data: ApplePencilMotionData) =\u003e {\n          console.log('Motion data:', {\n            rollAngle: data.rollAngle,\n            pitchAngle: data.pitchAngle,\n            yawAngle: data.yawAngle,\n          });\n          // Handle motion - adjust brush orientation, barrel roll effects\n        }}\n        onApplePencilCoalescedTouches={(data) =\u003e {\n          console.log('Coalesced touches:', data.touches.length);\n          // Handle high-fidelity input for smooth drawing\n        }}\n        onApplePencilPredictedTouches={(data) =\u003e {\n          console.log('Predicted touches:', data.touches.length);\n          // Handle predicted touches for latency compensation\n        }}\n        onDrawingChange={(drawing) =\u003e {\n          console.log('Drawing changed:', drawing);\n        }}\n      /\u003e\n    \u003c/View\u003e\n  );\n}\n```\n\n## 🔧 API Reference\n\n### PencilKitView Component\n\nMain React Native component for PencilKit integration with full Apple Pencil Pro support.\n\n**Props:**\n\n#### Basic Props\n\n- `config` (PencilKitConfig): PencilKit configuration\n- `style` (ViewStyle): Component styling\n- `onViewReady` (function): View ready callback\n\n#### Apple Pencil Data Props\n\n- `enableApplePencilData` (boolean): Enable Apple Pencil data capture\n- `onApplePencilData` (function): Apple Pencil data callback\n- `onApplePencilCoalescedTouches` (function): Coalesced touches callback\n- `onApplePencilPredictedTouches` (function): Predicted touches callback\n- `onApplePencilEstimatedProperties` (function): Estimated properties callback\n\n#### Apple Pencil Pro Props\n\n- `enableSqueezeInteraction` (boolean): Enable squeeze gesture detection\n- `enableDoubleTapInteraction` (boolean): Enable double-tap detection\n- `enableHoverSupport` (boolean): Enable hover pose detection\n- `enableHapticFeedback` (boolean): Enable haptic feedback\n- `onApplePencilSqueeze` (function): Squeeze gesture callback\n- `onApplePencilDoubleTap` (function): Double-tap callback\n- `onApplePencilHover` (function): Hover pose callback\n- `onApplePencilPreferredSqueezeAction` (function): Preferred squeeze action callback\n\n#### Drawing Props\n\n- `enableToolPicker` (boolean): Show tool picker\n- `onDrawingChange` (function): Drawing change callback\n\n### PencilKitUtils\n\nUtility functions for advanced PencilKit operations.\n\n**Methods:**\n\n#### View Management\n\n- `createView()`: Create a new PencilKit view\n- `destroyView(viewId)`: Destroy a PencilKit view\n- `setConfig(viewId, config)`: Configure PencilKit view\n\n#### Drawing Operations\n\n- `getDrawing(viewId)`: Get current drawing data\n- `setDrawing(viewId, drawing)`: Set drawing data\n- `clearDrawing(viewId)`: Clear the drawing\n- `undo(viewId)`: Undo last action\n- `redo(viewId)`: Redo last action\n- `canUndo(viewId)`: Check if undo is available\n- `canRedo(viewId)`: Check if redo is available\n\n#### Apple Pencil Data Capture\n\n- `startApplePencilCapture(viewId)`: Start capturing Apple Pencil data\n- `stopApplePencilCapture(viewId)`: Stop capturing Apple Pencil data\n- `isApplePencilCaptureActive(viewId)`: Check if capture is active\n\n#### Event Listeners\n\n- `addApplePencilListener(callback)`: Add Apple Pencil data listener\n- `removeApplePencilListener()`: Remove Apple Pencil data listener\n- `addDrawingChangeListener(callback)`: Add drawing change listener\n- `removeDrawingChangeListener()`: Remove drawing change listener\n- `addApplePencilSqueezeListener(callback)`: Add squeeze listener\n- `removeApplePencilSqueezeListener()`: Remove squeeze listener\n- `addApplePencilDoubleTapListener(callback)`: Add double-tap listener\n- `removeApplePencilDoubleTapListener()`: Remove double-tap listener\n- `addApplePencilHoverListener(callback)`: Add hover listener\n- `removeApplePencilHoverListener()`: Remove hover listener\n- `addApplePencilCoalescedTouchesListener(callback)`: Add coalesced touches listener\n- `removeApplePencilCoalescedTouchesListener()`: Remove coalesced touches listener\n- `addApplePencilPredictedTouchesListener(callback)`: Add predicted touches listener\n- `removeApplePencilPredictedTouchesListener()`: Remove predicted touches listener\n- `addApplePencilEstimatedPropertiesListener(callback)`: Add estimated properties listener\n- `removeApplePencilEstimatedPropertiesListener()`: Remove estimated properties listener\n- `addApplePencilPreferredSqueezeActionListener(callback)`: Add preferred squeeze action listener\n- `removeApplePencilPreferredSqueezeActionListener()`: Remove preferred squeeze action listener\n\n### Types\n\n#### ApplePencilData\n\nEnhanced interface for Apple Pencil data with all advanced properties:\n\n```typescript\ninterface ApplePencilData {\n  // Basic properties\n  pressure: number; // 0.0 to 1.0\n  altitude: number; // 0.0 to 1.0\n  azimuth: number; // 0.0 to 2π radians\n  azimuthUnitVector: {\n    x: number;\n    y: number;\n  }; // Unit vector pointing in azimuth direction\n  force: number; // 0.0 to 1.0\n  maximumPossibleForce: number;\n  timestamp: number;\n\n  // Location data\n  location: {\n    x: number;\n    y: number;\n  };\n  previousLocation: {\n    x: number;\n    y: number;\n  };\n  preciseLocation: {\n    x: number;\n    y: number;\n  };\n\n  // Apple Pencil Pro properties\n  perpendicularForce: number; // Computed perpendicular force\n  rollAngle: number; // Barrel roll angle (Apple Pencil Pro)\n\n  // Touch properties\n  isApplePencil: boolean;\n  phase: 'began' | 'moved' | 'ended' | 'cancelled';\n  hasPreciseLocation: boolean;\n\n  // Advanced properties\n  estimatedProperties: string[];\n  estimatedPropertiesExpectingUpdates: string[];\n}\n```\n\n#### Apple Pencil Pro Event Types\n\n```typescript\ninterface ApplePencilSqueezeData {\n  viewId: number;\n  phase: 'began' | 'changed' | 'ended';\n  value: number;\n  timestamp: number;\n  isActive: boolean;\n  preferredAction:\n    | 'ignore'\n    | 'showContextualPalette'\n    | 'switchPrevious'\n    | 'runShortcut';\n}\n\ninterface ApplePencilDoubleTapData {\n  viewId: number;\n  phase: 'began' | 'changed' | 'ended';\n  timestamp: number;\n  isActive: boolean;\n}\n\ninterface ApplePencilHoverData {\n  viewId: number;\n  location: {\n    x: number;\n    y: number;\n  };\n  altitude: number;\n  azimuth: number;\n  timestamp: number;\n}\n\ninterface ApplePencilCoalescedTouchesData {\n  viewId: number;\n  touches: ApplePencilData[];\n  timestamp: number;\n}\n\ninterface ApplePencilPredictedTouchesData {\n  viewId: number;\n  touches: ApplePencilData[];\n  timestamp: number;\n}\n\ninterface ApplePencilEstimatedPropertiesData {\n  viewId: number;\n  touchId: number;\n  updatedProperties: string[];\n  newData: ApplePencilData;\n  timestamp: number;\n}\n\ninterface ApplePencilPreferredSqueezeActionData {\n  preferredAction:\n    | 'ignore'\n    | 'showContextualPalette'\n    | 'switchPrevious'\n    | 'runShortcut';\n  customAction?: string;\n}\n```\n\n#### PencilKitConfig\n\nConfiguration interface for PencilKit:\n\n```typescript\ninterface PencilKitConfig {\n  // Basic configuration\n  allowsFingerDrawing: boolean;\n  allowsPencilOnlyDrawing: boolean;\n  isRulerActive: boolean;\n  drawingPolicy: 'default' | 'anyInput' | 'pencilOnly';\n\n  // Apple Pencil Pro configuration\n  enableApplePencilData?: boolean;\n  enableToolPicker?: boolean;\n  enableSqueezeInteraction?: boolean;\n  enableDoubleTapInteraction?: boolean;\n  enableHoverSupport?: boolean;\n  enableHapticFeedback?: boolean;\n}\n```\n\n#### Drawing Data Types\n\n```typescript\ninterface PencilKitDrawingData {\n  strokes: PencilKitStroke[];\n  bounds: {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n  };\n}\n\ninterface PencilKitStroke {\n  points: PencilKitPoint[];\n  tool: PencilKitTool;\n  color: string;\n  width: number;\n}\n\ninterface PencilKitPoint {\n  location: {\n    x: number;\n    y: number;\n  };\n  pressure: number;\n  azimuth: number;\n  altitude: number;\n  timestamp: number;\n}\n\ninterface PencilKitTool {\n  type: 'pen' | 'pencil' | 'marker' | 'eraser' | 'lasso';\n  width: number;\n  color: string;\n}\n```\n\n## 📖 Usage Examples\n\n### Professional Drawing App with Apple Pencil Pro\n\n```tsx\nimport React, { useRef, useState } from 'react';\nimport { View, StyleSheet, Button, Text } from 'react-native';\nimport {\n  PencilKitView,\n  PencilKitUtils,\n  type ApplePencilData,\n  type ApplePencilSqueezeData,\n} from 'munim-pencilkit';\n\nconst ProfessionalDrawingApp = () =\u003e {\n  const pencilKitRef = useRef\u003cany\u003e(null);\n  const [isDrawing, setIsDrawing] = useState(false);\n  const [brushSize, setBrushSize] = useState(5);\n\n  const config = {\n    allowsFingerDrawing: false,\n    allowsPencilOnlyDrawing: true,\n    isRulerActive: true,\n    drawingPolicy: 'pencilOnly',\n    enableSqueezeInteraction: true,\n    enableDoubleTapInteraction: true,\n    enableHoverSupport: true,\n    enableHapticFeedback: true,\n  };\n\n  const handleApplePencilData = (data: ApplePencilData) =\u003e {\n    // Use advanced properties for sophisticated brush behavior\n    const newBrushSize = data.perpendicularForce * 20;\n    setBrushSize(newBrushSize);\n\n    // Use roll angle for brush orientation\n    const brushAngle = data.rollAngle;\n\n    // Use precise location if available\n    const location = data.hasPreciseLocation\n      ? data.preciseLocation\n      : data.location;\n\n    console.log('Advanced brush data:', {\n      size: newBrushSize,\n      angle: brushAngle,\n      location,\n      pressure: data.pressure,\n    });\n  };\n\n  const handleSqueeze = (data: ApplePencilSqueezeData) =\u003e {\n    if (data.phase === 'ended') {\n      // Show contextual palette on squeeze\n      console.log('Showing contextual palette');\n    }\n  };\n\n  const handleSave = async () =\u003e {\n    const drawing = await pencilKitRef.current.getDrawing();\n    console.log('Saving drawing:', drawing);\n  };\n\n  return (\n    \u003cView style={styles.container}\u003e\n      \u003cPencilKitView\n        ref={pencilKitRef}\n        style={styles.canvas}\n        config={config}\n        enableApplePencilData={true}\n        enableToolPicker={true}\n        enableSqueezeInteraction={true}\n        enableDoubleTapInteraction={true}\n        enableHoverSupport={true}\n        enableHapticFeedback={true}\n        onApplePencilData={handleApplePencilData}\n        onApplePencilSqueeze={handleSqueeze}\n        onApplePencilDoubleTap={(data) =\u003e {\n          // Toggle between pen and eraser on double tap\n          console.log('Double tap - switching tool');\n        }}\n        onApplePencilHover={(data) =\u003e {\n          // Show brush preview on hover\n          console.log('Hover preview at:', data.location);\n        }}\n        onDrawingChange={(drawing) =\u003e {\n          console.log('Drawing changed:', drawing);\n        }}\n      /\u003e\n      \u003cView style={styles.controls}\u003e\n        \u003cText\u003eBrush Size: {brushSize.toFixed(1)}\u003c/Text\u003e\n        \u003cButton title=\"Save\" onPress={handleSave} /\u003e\n      \u003c/View\u003e\n    \u003c/View\u003e\n  );\n};\n```\n\n### Real-time Data Collection with Advanced Features\n\n```tsx\nimport React, { useEffect, useState } from 'react';\nimport { View, Text, StyleSheet, ScrollView } from 'react-native';\nimport {\n  PencilKitUtils,\n  type ApplePencilData,\n  type ApplePencilPredictedTouchesData,\n  type ApplePencilEstimatedPropertiesData,\n} from 'munim-pencilkit';\n\nconst AdvancedDataCollectionApp = () =\u003e {\n  const [pencilData, setPencilData] = useState\u003cApplePencilData | null\u003e(null);\n  const [predictedTouches, setPredictedTouches] =\n    useState\u003cApplePencilPredictedTouchesData | null\u003e(null);\n  const [estimatedProperties, setEstimatedProperties] =\n    useState\u003cApplePencilEstimatedPropertiesData | null\u003e(null);\n\n  useEffect(() =\u003e {\n    // Apple Pencil data listener\n    const handlePencilData = (data: ApplePencilData) =\u003e {\n      setPencilData(data);\n    };\n\n    // Predicted touches listener\n    const handlePredictedTouches = (data: ApplePencilPredictedTouchesData) =\u003e {\n      setPredictedTouches(data);\n    };\n\n    // Estimated properties listener\n    const handleEstimatedProperties = (\n      data: ApplePencilEstimatedPropertiesData\n    ) =\u003e {\n      setEstimatedProperties(data);\n    };\n\n    PencilKitUtils.addApplePencilListener(handlePencilData);\n    PencilKitUtils.addApplePencilPredictedTouchesListener(\n      handlePredictedTouches\n    );\n    PencilKitUtils.addApplePencilEstimatedPropertiesListener(\n      handleEstimatedProperties\n    );\n\n    return () =\u003e {\n      PencilKitUtils.removeApplePencilListener(handlePencilData);\n      PencilKitUtils.removeApplePencilPredictedTouchesListener(\n        handlePredictedTouches\n      );\n      PencilKitUtils.removeApplePencilEstimatedPropertiesListener(\n        handleEstimatedProperties\n      );\n    };\n  }, []);\n\n  return (\n    \u003cScrollView style={styles.container}\u003e\n      \u003cText style={styles.title}\u003eAdvanced Apple Pencil Data\u003c/Text\u003e\n\n      {pencilData \u0026\u0026 (\n        \u003cView style={styles.dataContainer}\u003e\n          \u003cText style={styles.sectionTitle}\u003eBasic Data\u003c/Text\u003e\n          \u003cText\u003ePressure: {pencilData.pressure.toFixed(3)}\u003c/Text\u003e\n          \u003cText\u003eAltitude: {pencilData.altitude.toFixed(3)}\u003c/Text\u003e\n          \u003cText\u003eAzimuth: {pencilData.azimuth.toFixed(3)}\u003c/Text\u003e\n          \u003cText\u003eForce: {pencilData.force.toFixed(3)}\u003c/Text\u003e\n\n          \u003cText style={styles.sectionTitle}\u003eApple Pencil Pro Data\u003c/Text\u003e\n          \u003cText\u003e\n            Perpendicular Force: {pencilData.perpendicularForce.toFixed(3)}\n          \u003c/Text\u003e\n          \u003cText\u003eRoll Angle: {pencilData.rollAngle.toFixed(3)}\u003c/Text\u003e\n          \u003cText\u003e\n            Has Precise Location: {pencilData.hasPreciseLocation ? 'Yes' : 'No'}\n          \u003c/Text\u003e\n\n          \u003cText style={styles.sectionTitle}\u003eLocation Data\u003c/Text\u003e\n          \u003cText\u003e\n            Location: ({pencilData.location.x.toFixed(1)},{' '}\n            {pencilData.location.y.toFixed(1)})\n          \u003c/Text\u003e\n          \u003cText\u003e\n            Precise: ({pencilData.preciseLocation.x.toFixed(1)},{' '}\n            {pencilData.preciseLocation.y.toFixed(1)})\n          \u003c/Text\u003e\n\n          \u003cText style={styles.sectionTitle}\u003eAdvanced Properties\u003c/Text\u003e\n          \u003cText\u003eEstimated: {pencilData.estimatedProperties.join(', ')}\u003c/Text\u003e\n          \u003cText\u003e\n            Expecting Updates:{' '}\n            {pencilData.estimatedPropertiesExpectingUpdates.join(', ')}\n          \u003c/Text\u003e\n        \u003c/View\u003e\n      )}\n\n      {predictedTouches \u0026\u0026 (\n        \u003cView style={styles.dataContainer}\u003e\n          \u003cText style={styles.sectionTitle}\u003ePredicted Touches\u003c/Text\u003e\n          \u003cText\u003eCount: {predictedTouches.touches.length}\u003c/Text\u003e\n          \u003cText\u003eTimestamp: {predictedTouches.timestamp}\u003c/Text\u003e\n        \u003c/View\u003e\n      )}\n\n      {estimatedProperties \u0026\u0026 (\n        \u003cView style={styles.dataContainer}\u003e\n          \u003cText style={styles.sectionTitle}\u003eEstimated Properties Update\u003c/Text\u003e\n          \u003cText\u003eTouch ID: {estimatedProperties.touchId}\u003c/Text\u003e\n          \u003cText\u003e\n            Updated: {estimatedProperties.updatedProperties.join(', ')}\n          \u003c/Text\u003e\n          \u003cText\u003eTimestamp: {estimatedProperties.timestamp}\u003c/Text\u003e\n        \u003c/View\u003e\n      )}\n    \u003c/ScrollView\u003e\n  );\n};\n```\n\n## 🎨 Apple Pencil Pro Features\n\n### Squeeze Gestures\n\nApple Pencil Pro squeeze gestures allow users to perform actions by squeezing the pencil:\n\n```tsx\n\u003cPencilKitView\n  enableSqueezeInteraction={true}\n  onApplePencilSqueeze={(data) =\u003e {\n    if (data.phase === 'ended') {\n      // Show contextual palette\n      showContextualPalette(data.preferredAction);\n    }\n  }}\n/\u003e\n```\n\n### Double Tap Gestures\n\nDouble-tap gestures for quick tool switching:\n\n```tsx\n\u003cPencilKitView\n  enableDoubleTapInteraction={true}\n  onApplePencilDoubleTap={(data) =\u003e {\n    if (data.phase === 'ended') {\n      // Toggle between pen and eraser\n      toggleTool();\n    }\n  }}\n/\u003e\n```\n\n### Hover Effects\n\nHover pose detection for previews and visual feedback:\n\n```tsx\n\u003cPencilKitView\n  enableHoverSupport={true}\n  onApplePencilHover={(data) =\u003e {\n    // Show brush preview at hover location\n    showBrushPreview(data.location, data.altitude);\n  }}\n/\u003e\n```\n\n### Barrel Roll Support\n\nUse barrel roll for brush angle control:\n\n```tsx\n\u003cPencilKitView\n  onApplePencilData={(data) =\u003e {\n    // Use roll angle for brush orientation\n    const brushAngle = data.rollAngle;\n    updateBrushOrientation(brushAngle);\n  }}\n/\u003e\n```\n\n### Predicted Touches\n\nUse predicted touches for latency compensation:\n\n```tsx\n\u003cPencilKitView\n  onApplePencilPredictedTouches={(data) =\u003e {\n    // Pre-render predicted strokes for smoothness\n    preRenderStrokes(data.touches);\n  }}\n/\u003e\n```\n\n### Haptic Feedback\n\nEnable haptic feedback for interactions:\n\n```tsx\n\u003cPencilKitView\n  enableHapticFeedback={true}\n  onApplePencilSqueeze={(data) =\u003e {\n    // Haptic feedback is automatically triggered\n    console.log('Squeeze with haptic feedback');\n  }}\n/\u003e\n```\n\n## 🔍 Troubleshooting\n\n### Common Issues\n\n1. **PencilKit Not Loading**: Ensure PencilKit.framework is properly linked in your iOS project\n2. **Apple Pencil Data Not Captured**: Check that `enableApplePencilData` is set to true\n3. **Drawing Not Appearing**: Verify that the PencilKitView has proper dimensions and styling\n4. **Apple Pencil Pro Features Not Working**: Ensure you're using Apple Pencil Pro and iOS 13.0+\n\n### Expo-Specific Issues\n\n1. **Development Build Required**: This library requires a development build in Expo. Use `npx expo run:ios`\n2. **Framework Not Found**: Ensure you're using Expo SDK 50+ and have the latest Expo CLI\n3. **Build Errors**: Make sure PencilKit.framework is available in your iOS project\n\n### Apple Pencil Pro Issues\n\n1. **Squeeze Not Working**: Ensure `enableSqueezeInteraction` is true and using Apple Pencil Pro\n2. **Hover Not Detected**: Check that `enableHoverSupport` is true and pencil is hovering\n3. **Haptic Feedback Missing**: Verify `enableHapticFeedback` is true and device supports haptics\n\n### Debug Mode\n\nEnable debug logging by setting the following environment variable:\n\n```bash\nexport REACT_NATIVE_PENCILKIT_DEBUG=1\n```\n\n### Requirements\n\n- iOS 13.0+\n- React Native 0.60+\n- Xcode 11+\n- Apple Pencil (for full functionality)\n- Apple Pencil Pro (for advanced features)\n- Expo SDK 50+ (for Expo projects)\n\n## 👏 Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on how to submit pull requests, report issues, and contribute to the project.\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n---\n\n\u003cimg alt=\"Star the Munim Technologies repo on GitHub to support the project\" src=\"https://user-images.githubusercontent.com/9664363/185428788-d762fd5d-97b3-4f59-8db7-f72405be9677.gif\" width=\"50%\"\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmunimtechnologies%2Fmunim-pencilkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmunimtechnologies%2Fmunim-pencilkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmunimtechnologies%2Fmunim-pencilkit/lists"}