npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

aix

v0.2.0

Published

aix is a react native package built with Nitro

Readme

aix

Primitives for building beautiful AI chat apps with React Native.

aix is currently in alpha preview. The API will change, and it is not yet feature complete.

We're rewriting the engine that powers the chat experience in the v0 mobile app with a focus on native feel.

aix is a native module with UIKit with Nitro Modules.

Installation

npm i aix react-native-nitro-modules

Next, rebuild your native app. For Expo users, run npx expo prebuild and rebuild.

Usage

Wrap your ScrollView with Aix, and wrap your messages with AixCell.

import { Aix, AixCell } from 'aix';
import { Message } from 'path/to/your/message';
import { Composer } from 'path/to/your/composer';

export function ChatScreen({ messages }) {
  return (
    <Aix style={{ flex: 1 }}>
      <ScrollView>
        {messages.map((message) => (
          <AixCell
            key={message.id}
            index={index}
            isLast={index === messages.length - 1}
          >
            <Message message={message} />
          </AixCell>
        ))}
      </ScrollView>
    </Aix>
  );
}

To add a floating composer which lets content scroll under it, you can use the AixFooter and KeyboardStickyView from react-native-keyboard-controller:

import { Aix, AixCell, AixFooter } from 'aix';
import { KeyboardStickyView } from 'react-native-keyboard-controller';

export function ChatScreen({ messages }) {
  return (
    <Aix style={{ flex: 1 }}>
      <ScrollView>
        {messages.map((message) => (
          <AixCell
            key={message.id}
            index={index}
            isLast={index === messages.length - 1}
          >
            <Message message={message} />
          </AixCell>
        ))}
      </ScrollView>

      <KeyboardStickyView offset={{ opened: 0, closed: -bottomInsetPadding }}>
        <AixFooter style={{ position: 'absolute', inset: 0, top: 'auto'}}>
          <Composer />
        </AixFooter>
      </KeyboardStickyView>
    </Aix>
  );
}

TODOs

  • [ ] Android support
  • [ ] LegendList support
  • [ ] FlashList support

API Reference

Aix

The main container component that provides keyboard-aware behavior and manages scrolling for chat interfaces.

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | shouldStartAtEnd | boolean | - | Whether the scroll view should start scrolled to the end of the content. | | scrollOnFooterSizeUpdate | object | { enabled: true, scrolledToEndThreshold: 100, animated: false } | Control the behavior of scrolling when the footer size changes. By default, changing the height of the footer will shift content up in the scroll view. | | scrollEndReachedThreshold | number | max(blankSize, 200) | The number of pixels from the bottom of the scroll view to the end of the content that is considered "near the end". Used to determine if content should shift up when keyboard opens. | | additionalContentInsets | object | - | Additional content insets applied when keyboard is open or closed. Shape: { top?: { whenKeyboardOpen, whenKeyboardClosed }, bottom?: { whenKeyboardOpen, whenKeyboardClosed } } | | additionalScrollIndicatorInsets | object | - | Additional insets for the scroll indicator, added to existing safe area insets. Applied to verticalScrollIndicatorInsets on iOS. | | mainScrollViewID | string | - | The nativeID of the scroll view to use. If provided, will search for a scroll view with this accessibilityIdentifier. | | penultimateCellIndex | number | - | The index of the second-to-last message (typically the last user message in AI chat apps). Used to determine which message will be scrolled into view. Useful when you have custom message types like timestamps in your list. |

Ref Methods

Access these methods via useAixRef():

const aix = useAixRef();

// Scroll to the end of the content
aix.current?.scrollToEnd(animated);

// Scroll to a specific index when the blank size is ready
aix.current?.scrollToIndexWhenBlankSizeReady(index, animated, waitForKeyboardToEnd);

| Method | Parameters | Description | |--------|------------|-------------| | scrollToEnd | animated?: boolean | Scrolls to the end of the content. | | scrollToIndexWhenBlankSizeReady | index: number, animated?: boolean, waitForKeyboardToEnd?: boolean | Scrolls to a specific cell index once the blank size calculation is ready. |


AixCell

A wrapper component for each message in the list. It communicates cell position and dimensions to the parent Aix component.

Props

| Prop | Type | Required | Description | |------|------|----------|-------------| | index | number | Yes | The index of this cell in the message list. | | isLast | boolean | Yes | Whether this cell is the last item in the list. Used for scroll positioning and animations. |


AixFooter

A footer component for floating composers that allows content to scroll underneath it. The footer's height is automatically tracked for proper scroll offset calculations.

Props

Accepts all standard React Native View props.

Important Notes

  • Do not apply vertical padding (padding, paddingBottom) directly to AixFooter. Apply padding to a child view instead.
  • Position the footer absolutely at the bottom of the Aix container:
<AixFooter style={{ position: 'absolute', inset: 0, top: 'auto' }}>
  <Composer />
</AixFooter>

useAixRef

A hook that returns a ref to access imperative methods on the Aix component.

import { useAixRef } from 'aix';

function Chat({ messages }) {
  const aix = useAixRef();
  const send = useSendMessage()
  
  const handleSend = () => {
    // Scroll to end after sending a message
    send(message);
    aix.current?.scrollToIndexWhenBlankSizeReady(messages.length + 1, true);
    requestAnimationFrame(Keyboard.dismiss);
  };
  
  return <Aix ref={aix}>{/* ... */}</Aix>;
}

TODOs

Requirements

  • React Native v0.78.0 or higher
  • Node 18.0.0 or higher