{"_id":"@cryterion/expo-chat-ui","_rev":"5-79af7d852b328513ef164ee846ad4725","name":"@cryterion/expo-chat-ui","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"@cryterion/expo-chat-ui","version":"1.0.0","keywords":["react-native","expo","chat","ui","component","messaging","conversation","chatbot"],"author":{"name":"cryterion"},"license":"MIT","_id":"@cryterion/expo-chat-ui@1.0.0","maintainers":[{"name":"cryterion","email":"me@phassani.com"}],"homepage":"https://github.com/mphassani/expo-chat-ui#readme","bugs":{"url":"https://github.com/mphassani/expo-chat-ui/issues"},"dist":{"shasum":"c367f16c4f048da82d64f70041e6543041ee0935","tarball":"https://registry.npmjs.org/@cryterion/expo-chat-ui/-/expo-chat-ui-1.0.0.tgz","fileCount":9,"integrity":"sha512-yMuJgnvGS00+rS0qucqkVhkAKGrN7m0IGirarUPoizWk3FsUdwqmPZTqnoTcJr1FkKhxK7x1ivW/ZHrj10FhMA==","signatures":[{"sig":"MEQCIEROpZcRZQPADQK/8tG0F0dgAl7Ptq7K3VfCrFw8eCzUAiBzq6sPoWCmqappDdWAXO5Pf05ohI5xmfNix1lefPkTdg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":22057},"main":"src/index.ts","types":"src/index.ts","module":"src/index.ts","source":"src/index.ts","exports":{".":{"types":"./src/index.ts","import":"./src/index.ts","require":"./src/index.ts"}},"gitHead":"65a7c23a2d0e1909d204dff6e3891eaa210428f0","scripts":{"typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck"},"_npmUser":{"name":"cryterion","email":"me@phassani.com"},"repository":{"url":"git+https://github.com/mphassani/expo-chat-ui.git","type":"git"},"_npmVersion":"11.6.1","description":"A reusable chat UI component for Expo + React Native applications","directories":{},"sideEffects":false,"_nodeVersion":"24.11.0","react-native":"src/index.ts","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^50.0.0","react":"18.2.0","typescript":"~5.9.3","@types/react":"^18.2.79","react-native":"0.73.6","expo-clipboard":"^7.0.0","@expo/vector-icons":"^14.1.0"},"peerDependencies":{"expo":">=50.0.0","react":">=18.0.0","react-native":">=0.72.0","expo-clipboard":">=7.0.0","@expo/vector-icons":">=14.0.0"},"_npmOperationalInternal":{"tmp":"tmp/expo-chat-ui_1.0.0_1768453996464_0.7585564643508302","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@cryterion/expo-chat-ui","version":"1.0.1","keywords":["react-native","expo","chat","ui","component","messaging","conversation","chatbot"],"author":{"name":"cryterion"},"license":"MIT","_id":"@cryterion/expo-chat-ui@1.0.1","maintainers":[{"name":"cryterion","email":"me@phassani.com"}],"homepage":"https://github.com/mphassani/expo-chat-ui#readme","bugs":{"url":"https://github.com/mphassani/expo-chat-ui/issues"},"dist":{"shasum":"9adb5e0b82e17819a34bf2484725427a40f5e511","tarball":"https://registry.npmjs.org/@cryterion/expo-chat-ui/-/expo-chat-ui-1.0.1.tgz","fileCount":9,"integrity":"sha512-Sn0taGido2J+ZBWkCHF/+OwcQSO2WxOFIdqsiI1To29uLVRvX/R3rKDqdm1BopHCWqZXM4sAHfS3qpOEQnuk9Q==","signatures":[{"sig":"MEUCIFs00CCGiU5QOJSrXP9KRJmhFcUdvhPniX2y8tco2jndAiEA8732YQEMfruEaMW7HINF1uCUQjaMX4esjrUJVkNtZ/Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":22202},"main":"src/index.ts","types":"src/index.ts","module":"src/index.ts","source":"src/index.ts","exports":{".":{"types":"./src/index.ts","import":"./src/index.ts","require":"./src/index.ts"}},"gitHead":"9f1d98119e9c12c46e77f347bc8b6ec7b1aeaa2e","scripts":{"typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck"},"_npmUser":{"name":"cryterion","email":"me@phassani.com"},"repository":{"url":"git+https://github.com/mphassani/expo-chat-ui.git","type":"git"},"_npmVersion":"11.6.1","description":"A reusable chat UI component for Expo + React Native applications","directories":{},"sideEffects":false,"_nodeVersion":"24.11.0","react-native":"src/index.ts","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^50.0.0","react":"18.2.0","typescript":"~5.9.3","@types/react":"^18.2.79","react-native":"0.73.6","expo-clipboard":"^7.0.0","@expo/vector-icons":"^14.1.0"},"peerDependencies":{"expo":">=50.0.0","react":">=18.0.0","react-native":">=0.72.0","expo-clipboard":">=7.0.0","@expo/vector-icons":">=14.0.0"},"_npmOperationalInternal":{"tmp":"tmp/expo-chat-ui_1.0.1_1769240226787_0.33101214006775415","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@cryterion/expo-chat-ui","version":"1.0.2","keywords":["react-native","expo","chat","ui","component","messaging","conversation","chatbot"],"author":{"name":"cryterion"},"license":"MIT","_id":"@cryterion/expo-chat-ui@1.0.2","maintainers":[{"name":"cryterion","email":"me@phassani.com"}],"homepage":"https://github.com/mphassani/expo-chat-ui#readme","bugs":{"url":"https://github.com/mphassani/expo-chat-ui/issues"},"dist":{"shasum":"cd0bf5449bc542dfe9c71ca8b6d214e162baa492","tarball":"https://registry.npmjs.org/@cryterion/expo-chat-ui/-/expo-chat-ui-1.0.2.tgz","fileCount":9,"integrity":"sha512-eNcPJiuLfR9tmBCSioBGjl+WmY6eMXKJy1HbYMD/cnOtZCeDe8se0hMcfzMS9n5ZDYy9S0U7IVhpGdgTeXncag==","signatures":[{"sig":"MEUCIHpaztjB6HPmeU4h08+hQaBVzslpT+qbf54m/W0cv47zAiEAlAdGHH84jBIboh/LQX1xYkVym+MBa22k8ExKxUIClPM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23074},"main":"src/index.ts","types":"src/index.ts","module":"src/index.ts","source":"src/index.ts","exports":{".":{"types":"./src/index.ts","import":"./src/index.ts","require":"./src/index.ts"}},"gitHead":"8116f8c260ef26702c2e23ead68c84d45cbafbd0","scripts":{"typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck"},"_npmUser":{"name":"cryterion","email":"me@phassani.com"},"repository":{"url":"git+https://github.com/mphassani/expo-chat-ui.git","type":"git"},"_npmVersion":"11.6.1","description":"A reusable chat UI component for Expo + React Native applications","directories":{},"sideEffects":false,"_nodeVersion":"24.11.0","react-native":"src/index.ts","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^50.0.0","react":"18.2.0","typescript":"~5.9.3","@types/react":"^18.2.79","react-native":"0.73.6","expo-clipboard":"^7.0.0","@expo/vector-icons":"^14.1.0"},"peerDependencies":{"expo":">=50.0.0","react":">=18.0.0","react-native":">=0.72.0","expo-clipboard":">=7.0.0","@expo/vector-icons":">=14.0.0"},"_npmOperationalInternal":{"tmp":"tmp/expo-chat-ui_1.0.2_1769466139187_0.5529647156520141","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@cryterion/expo-chat-ui","version":"1.1.0","keywords":["react-native","expo","chat","ui","component","messaging","conversation","chatbot"],"author":{"name":"cryterion"},"license":"MIT","_id":"@cryterion/expo-chat-ui@1.1.0","maintainers":[{"name":"cryterion","email":"me@phassani.com"}],"homepage":"https://github.com/mphassani/expo-chat-ui#readme","bugs":{"url":"https://github.com/mphassani/expo-chat-ui/issues"},"dist":{"shasum":"07db39590a8d69c41a3fa26822447891e6d74e02","tarball":"https://registry.npmjs.org/@cryterion/expo-chat-ui/-/expo-chat-ui-1.1.0.tgz","fileCount":9,"integrity":"sha512-fV7GFZRgYKrluXvJziXv9WZgcqbDingIYbmQoddysFc9pbS6S8NZnzcDIBMK/AULLTXX9oe2tbzT+8l6cdKbCQ==","signatures":[{"sig":"MEUCIQCnTr53X9qCLI4v6X6vFZ/71lIoGfBZCra9VOP+DRZj6gIgKj6Ck14Mw5WdqR2z2RZcM5eNcII6j7EUJR1JuWAeULE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25384},"main":"src/index.ts","types":"src/index.ts","module":"src/index.ts","source":"src/index.ts","exports":{".":{"types":"./src/index.ts","import":"./src/index.ts","require":"./src/index.ts"}},"gitHead":"3aa1357e0cbe62ddb518251df4b01b8d6dc1dc7d","scripts":{"typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck"},"_npmUser":{"name":"cryterion","email":"me@phassani.com"},"repository":{"url":"git+https://github.com/mphassani/expo-chat-ui.git","type":"git"},"_npmVersion":"11.8.0","description":"A reusable chat UI component for Expo + React Native applications","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","react-native":"src/index.ts","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"expo":"^50.0.0","react":"18.2.0","typescript":"~5.9.3","@types/react":"^18.2.79","react-native":"0.73.6","expo-clipboard":"^7.0.0","semantic-release":"^25.0.2","@expo/vector-icons":"^14.1.0","@semantic-release/git":"^10.0.1","@semantic-release/npm":"^13.1.3","@semantic-release/github":"^12.0.2","@semantic-release/changelog":"^6.0.3"},"peerDependencies":{"expo":">=50.0.0","react":">=18.0.0","react-native":">=0.72.0","expo-clipboard":">=7.0.0","@expo/vector-icons":">=14.0.0"},"_npmOperationalInternal":{"tmp":"tmp/expo-chat-ui_1.1.0_1769499465268_0.2365364993224237","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@cryterion/expo-chat-ui","version":"1.2.0","description":"A reusable chat UI component for Expo + React Native applications","author":{"name":"cryterion"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/mphassani/expo-chat-ui.git"},"bugs":{"url":"https://github.com/mphassani/expo-chat-ui/issues"},"homepage":"https://github.com/mphassani/expo-chat-ui#readme","publishConfig":{"access":"public"},"main":"src/index.ts","module":"src/index.ts","types":"src/index.ts","react-native":"src/index.ts","source":"src/index.ts","exports":{".":{"import":"./src/index.ts","require":"./src/index.ts","types":"./src/index.ts"}},"sideEffects":false,"scripts":{"typecheck":"tsc --noEmit","prepublishOnly":"npm run typecheck"},"keywords":["react-native","expo","chat","ui","component","messaging","conversation","chatbot"],"peerDependencies":{"react":">=18.0.0","react-native":">=0.72.0","expo":">=50.0.0","@expo/vector-icons":">=14.0.0","expo-clipboard":">=7.0.0"},"devDependencies":{"@expo/vector-icons":"^14.1.0","@semantic-release/changelog":"^6.0.3","@semantic-release/git":"^10.0.1","@semantic-release/github":"^12.0.2","@semantic-release/npm":"^13.1.3","@types/react":"^18.2.79","expo":"^50.0.0","expo-clipboard":"^7.0.0","react":"18.2.0","react-native":"0.73.6","semantic-release":"^25.0.2","typescript":"~5.9.3"},"dependencies":{"react-native-markdown-display":"^7.0.2"},"gitHead":"d6dff977408f3c80f3a85bf713ffcbc27de65f2e","_id":"@cryterion/expo-chat-ui@1.2.0","_nodeVersion":"24.11.0","_npmVersion":"11.6.1","dist":{"integrity":"sha512-owQuTs414IxmRQep1v8PVHdpxQ6tV79bAbEbbMe7LEqlpN2Wlpsf6D2x39mvpo5xXpZY4DpNaFLOglwAK7lyVQ==","shasum":"1b8196b95a2a870c5edd9104f124e97a4009df91","tarball":"https://registry.npmjs.org/@cryterion/expo-chat-ui/-/expo-chat-ui-1.2.0.tgz","fileCount":9,"unpackedSize":31499,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD+oiu+Vh5d/pg7BMztVbeGAO+N5UlZu5ptwzPp5V/AZwIgS0o3wDuPzlx5KGqP9CZFXcqHlChbrUCW+aXcR8BAOo0="}]},"_npmUser":{"name":"cryterion","email":"me@phassani.com"},"directories":{},"maintainers":[{"name":"cryterion","email":"me@phassani.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/expo-chat-ui_1.2.0_1770965925266_0.7643769726670049"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-15T05:13:16.397Z","modified":"2026-02-13T06:58:45.528Z","1.0.0":"2026-01-15T05:13:16.605Z","1.0.1":"2026-01-24T07:37:06.924Z","1.0.2":"2026-01-26T22:22:19.325Z","1.1.0":"2026-01-27T07:37:45.418Z","1.2.0":"2026-02-13T06:58:45.416Z"},"bugs":{"url":"https://github.com/mphassani/expo-chat-ui/issues"},"author":{"name":"cryterion"},"license":"MIT","homepage":"https://github.com/mphassani/expo-chat-ui#readme","keywords":["react-native","expo","chat","ui","component","messaging","conversation","chatbot"],"repository":{"type":"git","url":"git+https://github.com/mphassani/expo-chat-ui.git"},"description":"A reusable chat UI component for Expo + React Native applications","maintainers":[{"name":"cryterion","email":"me@phassani.com"}],"readme":"# @cryterion/expo-chat-ui\n\nA reusable chat UI component for Expo + React Native applications.\n\n## Installation\n\n```bash\nbun add @cryterion/expo-chat-ui\n```\n\n## Usage\n\n### Basic Usage\n\n```tsx\nimport { Chat, ChatMessage } from '@cryterion/expo-chat-ui';\n\nfunction ChatScreen() {\n  const [messages, setMessages] = useState<ChatMessage[]>([]);\n  const [isLoading, setIsLoading] = useState(false);\n\n  const handleSend = async (text: string) => {\n    // Add user message\n    const userMessage: ChatMessage = {\n      id: `user-${Date.now()}`,\n      role: 'user',\n      content: text,\n      timestamp: Date.now(),\n    };\n    setMessages(prev => [...prev, userMessage]);\n\n    // Your AI/backend logic here...\n  };\n\n  return (\n    <Chat\n      messages={messages}\n      onSend={handleSend}\n      isLoading={isLoading}\n    />\n  );\n}\n```\n\n### With Custom Theme\n\n```tsx\nimport { Chat, ChatTheme } from '@cryterion/expo-chat-ui';\n\nconst customTheme: Partial<ChatTheme> = {\n  colors: {\n    primary: '#007AFF',\n    userBubble: '#007AFF',\n    assistantBubble: '#E5E5EA',\n    userText: '#FFFFFF',\n    assistantText: '#000000',\n  },\n};\n\nfunction ChatScreen() {\n  return (\n    <Chat\n      messages={messages}\n      onSend={handleSend}\n      theme={customTheme}\n    />\n  );\n}\n```\n\n### Markdown Messages\n\n```tsx\nimport { Chat } from '@cryterion/expo-chat-ui';\n\nfunction ChatScreen() {\n  return (\n    <Chat\n      messages={messages}\n      onSend={handleSend}\n      messageFormat=\"markdown\"\n    />\n  );\n}\n```\n\nBy default, markdown rendering applies to `assistant` and `system` messages when `messageFormat=\"markdown\"`.\n\n```tsx\n<Chat\n  messages={messages}\n  onSend={handleSend}\n  messageFormat=\"markdown\"\n  markdownRoles={['assistant', 'user']}\n/>\n```\n\n### Custom Message Content Rendering\n\n```tsx\nimport { Chat, RenderMessageContentArgs } from '@cryterion/expo-chat-ui';\nimport { View } from 'react-native';\n\nfunction ChatScreen() {\n  return (\n    <Chat\n      messages={messages}\n      onSend={handleSend}\n      messageFormat=\"markdown\"\n      renderMessageContent={({ defaultContent, isUser }: RenderMessageContentArgs) => (\n        <View style={{ opacity: isUser ? 0.95 : 1 }}>\n          {defaultContent}\n        </View>\n      )}\n    />\n  );\n}\n```\n\n### Using Individual Components\n\nYou can also use the individual building blocks:\n\n```tsx\nimport { MessageList, ChatInput, MessageBubble } from '@cryterion/expo-chat-ui';\n\nfunction CustomChat() {\n  return (\n    <View style={{ flex: 1 }}>\n      <MessageList messages={messages} isLoading={isLoading} />\n      <ChatInput onSend={handleSend} />\n    </View>\n  );\n}\n```\n\n## API\n\n### `<Chat />` Props\n\n| Prop | Type | Required | Description |\n|------|------|----------|-------------|\n| `messages` | `ChatMessage[]` | Yes | Array of messages to display |\n| `onSend` | `(text: string) => void \\| Promise<void>` | Yes | Callback when user sends a message |\n| `isLoading` | `boolean` | No | Shows typing indicator when true |\n| `disabled` | `boolean` | No | Disables input when true |\n| `theme` | `Partial<ChatTheme>` | No | Custom theme colors |\n| `renderEmptyState` | `ReactNode \\| () => ReactNode` | No | Custom empty state |\n| `onCopyMessage` | `(message: ChatMessage) => void` | No | Custom copy handler |\n| `placeholder` | `string` | No | Input placeholder |\n| `emptyStateTitle` | `string` | No | Empty state title |\n| `emptyStateSubtitle` | `string` | No | Empty state subtitle |\n| `keyboardVerticalOffset` | `number` | No | Keyboard offset for iOS `KeyboardAvoidingView` |\n| `autoCorrect` | `boolean` | No | Toggle input autocorrect |\n| `spellCheck` | `boolean` | No | Toggle input spellcheck |\n| `keyboardType` | `KeyboardTypeOptions` | No | Input keyboard type |\n| `messageFormat` | `'plain' \\| 'markdown'` | No | Message rendering mode (defaults to `'plain'`) |\n| `markdownRoles` | `('user' \\| 'assistant' \\| 'system')[]` | No | Roles rendered as markdown when `messageFormat='markdown'` (defaults to `['assistant','system']`) |\n| `renderMessageContent` | `(args: RenderMessageContentArgs) => ReactNode` | No | Full custom message content renderer |\n\n### `ChatMessage` Type\n\n```ts\ninterface ChatMessage {\n  id: string;\n  role: 'user' | 'assistant' | 'system';\n  content: string;\n  timestamp: number | Date;\n  meta?: Record<string, unknown>;\n}\n```\n\n### `RenderMessageContentArgs` Type\n\n```ts\ninterface RenderMessageContentArgs {\n  message: ChatMessage;\n  isUser: boolean;\n  theme: ChatTheme;\n  defaultContent: ReactNode;\n  isMarkdown: boolean;\n}\n```\n\n### `ChatTheme` Type\n\n```ts\ninterface ChatTheme {\n  mode: 'light' | 'dark';\n  colors: {\n    primary: string;\n    background: string;\n    inputBackground: string;\n    userBubble: string;\n    assistantBubble: string;\n    userText: string;\n    assistantText: string;\n    text: string;\n    textMuted: string;\n    placeholder: string;\n    border: string;\n    sendButtonDisabled: string;\n  };\n}\n```\n\n## Contributing\n\nWe welcome contributions! This project uses [Conventional Commits](https://www.conventionalcommits.org/) for automated versioning and releases.\n\n### Commit Message Format\n\nAll commits must follow the conventional commit format:\n\n```\n<type>(<scope>): <description>\n\n[optional body]\n\n[optional footer(s)]\n```\n\n**Types:**\n- `feat:` - A new feature (triggers minor version bump)\n- `fix:` - A bug fix (triggers patch version bump)\n- `docs:` - Documentation changes only\n- `style:` - Code style changes (formatting, missing semicolons, etc.)\n- `refactor:` - Code changes that neither fix bugs nor add features\n- `perf:` - Performance improvements\n- `test:` - Adding or updating tests\n- `chore:` - Maintenance tasks, dependency updates, etc.\n\n**Breaking Changes:**\n- Add `!` after the type/scope (e.g., `feat!:`) or\n- Include `BREAKING CHANGE:` in the footer\n\nThis triggers a major version bump.\n\n**Examples:**\n```bash\nfeat: add message reactions\nfix(input): disable autocorrect on iOS\nfeat(theme)!: replace color system with new tokens\ndocs: update installation instructions\nchore: update dependencies\n```\n\n### Development Workflow\n\n1. Fork the repository\n2. Create a feature branch: `git checkout -b feat/my-feature`\n3. Make your changes\n4. Run type check: `bun run typecheck`\n5. Commit using conventional commits: `git commit -m \"feat: add my feature\"`\n6. Push to your fork: `git push origin feat/my-feature`\n7. Open a Pull Request\n\n## Release Process\n\nThis project uses [semantic-release](https://github.com/semantic-release/semantic-release) for automated versioning and publishing on NPM.\n\n**How it works:**\n- When commits are pushed to `main`, semantic-release analyzes commit messages\n- Based on conventional commits, it determines the next version number\n- Automatically updates `package.json` and generates `CHANGELOG.md`\n- Creates a GitHub release with release notes\n- Publishes the package to npm\n\n**Version Bumping:**\n- `fix:` commits → Patch release (1.0.0 → 1.0.1)\n- `feat:` commits → Minor release (1.0.0 → 1.1.0)\n- `BREAKING CHANGE:` → Major release (1.0.0 → 2.0.0)\n\n## License\n\nMIT\n","readmeFilename":"README.md"}