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

@medway-ui/native

v1.1.2

Published

Medway UI components for React Native (iOS/Android via Expo)

Readme

@medway-ui/native

React Native components for iOS and Android (Expo). Same visual API as @medway-ui/core, built on NativeWind + @rn-primitives.

Minimum recommended version for npm brownfield setup: 1.1.2+


Installation

npm install @medway-ui/native @medway-ui/core @medway-ui/icons \
  class-variance-authority clsx tailwind-merge nativewind \
  react-native-reanimated react-native-svg

# Expo (aligns versions with your SDK)
npx expo install react-native-reanimated react-native-svg

Brownfield apps that already use babel-plugin-module-resolver with @/ aliases pointing at the app src/ also need:

npm install -D babel-plugin-module-resolver

Brownfield setup (Expo + legacy UI / Restyle)

NativeWind applies only to @medway-ui/native + screens/components that use the library (e.g. src/pages/medway-ui/, partially migrated features).

Reference implementation: test-prep-app (metro.config.js, babel.config.js, tailwind.config.js, src/pages/medway-ui/).

1. metro.config.js

const { getDefaultConfig } = require("expo/metro-config");
const { withMedwayUi } = require("@medway-ui/native/metro");

module.exports = withMedwayUi(getDefaultConfig(__dirname), {
  projectRoot: __dirname,
  // linkedMedwayUiRoot: auto-detected (npm or monorepo)
});

| Scenario | linkedMedwayUiRoot | | --- | --- | | npm packages (npm install) | Omit — auto-detects node_modules/@medway-ui | | Monorepo with local clone | "../medway-ui" (optional; also auto-detected) | | Symlink file:../medway-ui/native | Auto-detected as monorepo |

Do not set resolveNativeSource: false — the compiled lib still references internal @/ aliases. The default (true) resolves to native/src and works with npm.

2. tailwind.config.js

const { createMedwayUiTailwindConfig } = require("@medway-ui/native/tailwind");

module.exports = createMedwayUiTailwindConfig({
  projectRoot: __dirname,
  content: [
    "./src/pages/medway-ui/**/*.{ts,tsx}",
    // add extra folders that use className + @medway-ui/native:
    // "./src/pages/MyFeature/**/*.{ts,tsx}",
  ],
});

createMedwayUiTailwindConfig already includes globs for node_modules/@medway-ui/native/src and loads tokens from @medway-ui/core (Node 22+ compatible).

3. babel.config.js

The app default preset must not enable NativeWind globally. Use createBrownfieldOverride to scope NativeWind to the library + migrated screens folder.

If the app defines @/ aliases for ./src/* via babel-plugin-module-resolver, you must redirect @/ imports from @medway-ui/native files to the library source — otherwise imports like @/components/Badge resolve to the app src/ and break the bundle.

const {
  createBrownfieldOverride,
  createMedwayUiAliasResolver,
} = require("@medway-ui/native/babel-brownfield");

const resolveMedwayUiAlias = createMedwayUiAliasResolver(__dirname);

module.exports = function (api) {
  api.cache(true);

  const appPlugins = [
    [
      "module-resolver",
      {
        root: ["."],
        extensions: [".ios.ts", ".android.ts", ".ts", ".tsx", ".js", ".jsx", ".json"],
        alias: {
          "@/components": "./src/components",
          "@/pages": "./src/pages",
          // ... other app aliases
        },
        resolvePath(sourcePath, currentFile) {
          return resolveMedwayUiAlias(sourcePath, currentFile);
        },
      },
    ],
    // other app plugins (no reanimated here)
  ];

  return {
    presets: ["babel-preset-expo"],
    plugins: appPlugins,
    overrides: [
      createBrownfieldOverride({
        projectRoot: __dirname,
        appPagesDir: "medway-ui", // src/pages subfolder with NativeWind screens
        plugins: [
          // repeat any plugins needed in the medway-ui scope
          "react-native-reanimated/plugin", // always last
        ],
      }),
    ],
  };
};

Apps without @/ Babel aliases do not need createMedwayUiAliasResolver.

4. Provider + CSS

Wrap the subtree that uses @medway-ui/native with MedwayUiProvider and import CSS once:

import { MedwayUiProvider } from "@medway-ui/native/setup";
import "@medway-ui/native/setup/global.css";

function MyScreen() {
  return (
    <MedwayUiProvider theme="system">
      {/* Button, CardNews, etc. */}
    </MedwayUiProvider>
  );
}

Dark mode: pass colorScheme="light" | "dark" when the app already resolves theme (Redux, Zustand, etc.):

<MedwayUiProvider colorScheme={appColorScheme}>
  {children}
</MedwayUiProvider>

MedwayUiProvider includes PortalHost (required for Select, Dialog, Popover, Tooltip).

Do not import @medway-ui/core/tokens.css directly — incompatible with NativeWind v4. Tokens come from setup/global.css + setup/tokens.native.css.

5. Auto navigator (catalog / isolated screens)

Create once src/pages/medway-ui/navigator.tsx:

import { createMedwayUiNavigator, MedwayUiProvider } from "@medway-ui/native/setup";
import "@medway-ui/native/setup/global.css";

const { MedwayUiNavigator } = createMedwayUiNavigator(
  require.context(".", true, /^\.\/[^/]+\/index\.tsx$/),
);

function MedwayUiRoot() {
  return (
    <MedwayUiProvider theme="system">
      <MedwayUiNavigator />
    </MedwayUiProvider>
  );
}

export { MedwayUiRoot, MedwayUiNavigator };

Register in the app stack:

<Stack.Screen name="MedwayUi" component={MedwayUiRoot} options={{ headerShown: false }} />

New screen = new folder src/pages/medway-ui/MyScreen/index.tsx — no manual route registration.

6. Using components in existing screens (Restyle + Medway UI mix)

Pattern used in Content Hub and partially migrated features:

import { Button, CardNews } from "@medway-ui/native";
import { MedwayUiProvider } from "@medway-ui/native/setup";
import "@medway-ui/native/setup/global.css";

function ContentHubScreen() {
  return (
    <Box> {/* Restyle */}
      <MedwayUiProvider colorScheme={colorScheme}>
        <CardNews>{/* ... */}</CardNews>
      </MedwayUiProvider>
    </Box>
  );
}

Add the feature folder to content in tailwind.config.js.


Monorepo development (file:../medway-ui/native)

{
  "@medway-ui/core": "file:../medway-ui",
  "@medway-ui/native": "file:../medway-ui/native"
}

Metro and Babel auto-detect the local clone. After library changes:

cd ../medway-ui/native && npm run build:lib   # if testing the compiled lib

Restart Metro with a clean cache: npx expo start --clear.


Troubleshooting

| Error | Cause | Fix | | --- | --- | --- | | Unable to resolve .../src/components/Badge | App @/ alias overrides lib @/ | Add createMedwayUiAliasResolver in Babel | | Unable to resolve @/lib/medwayIcons | Bug in @medway-ui/[email protected] | Upgrade to 1.1.2+ | | Unable to resolve ../../../../../src/... from lib/module/ | resolveNativeSource: false | Remove the option (use default true) | | Tokens / tailwind fail to load (Node 22+) | require of .ts inside node_modules | Use @medway-ui/[email protected]+ (createMedwayUiTailwindConfig uses jiti fallback) | | NativeWind styles not applied | File outside brownfield scope | Move to src/pages/medway-ui/ or add a tailwind glob | | Select/Dialog not opening | Missing PortalHost | Use MedwayUiProvider |


Greenfield setup (100% NativeWind app)

For new apps without legacy UI:

// babel.config.js
module.exports = function (api) {
  api.cache(true);
  return {
    presets: [
      ["babel-preset-expo", { jsxImportSource: "nativewind" }],
      "nativewind/babel",
    ],
    plugins: ["react-native-reanimated/plugin"],
  };
};
// metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
const { withMedwayUi } = require("@medway-ui/native/metro");

module.exports = withMedwayUi(getDefaultConfig(__dirname), {
  projectRoot: __dirname,
});

Import @medway-ui/native/setup/global.css in the root layout.


Usage

import {
  Alert,
  AlertContainer,
  AlertContent,
  AlertTitle,
  AlertDescription,
  Badge,
  Button,
  Input,
} from "@medway-ui/native";

export default function Screen() {
  return (
    <>
      <Button variant="regular" size="md" onPress={() => {}}>
        Continue
      </Button>

      <Input
        label="Email"
        type="email"
        size="lg"
        value={email}
        onChangeText={setEmail}
        placeholder="[email protected]"
      />

      <Alert variant="success" onClose={() => {}}>
        <AlertContainer>
          <AlertContent>
            <AlertTitle>Done</AlertTitle>
            <AlertDescription>Operation completed successfully.</AlertDescription>
          </AlertContent>
        </AlertContainer>
      </Alert>

      <Badge variant="regular" size="md">9+</Badge>
    </>
  );
}

Icons

The @medway-ui/icons package includes a native entry point:

import { Check, CloseMd } from "@medway-ui/icons/native";

Components — status

| Component | Status | Notes | | --- | --- | --- | | Button | ✅ | Variants, loading, badge, alert dot | | Input | ✅ | text, email, password, numeric | | Alert | ✅ | Sub-components, all variants | | Badge | ✅ | Variants, icon-only | | Loading | ✅ | Reanimated spin | | Checkbox | ✅ | @rn-primitives/checkbox | | RadioGroup | ✅ | @rn-primitives/radio-group | | Switch | ✅ | @rn-primitives/switch | | Select | ✅ | @rn-primitives/select | | Label | ✅ | Pressable + Text | | Separator | ✅ | View 1px | | Dialog | ✅ | @rn-primitives/dialog | | AlertDialog | ✅ | @rn-primitives/alert-dialog | | Sheet | ✅ | @rn-primitives/dialog (side-aware) | | Tag | ✅ | 16+ variants | | Toast | ✅ | useToast + toast() | | Tooltip | ✅ | @rn-primitives/tooltip | | Popover | ✅ | @rn-primitives/popover | | Skeleton | ✅ | Shimmer | | Avatar | ✅ | @rn-primitives/avatar | | FallbackImage | ✅ | react-native-svg | | CardNews | ✅ | Composable card (Content Hub) | | Tabs | 🔜 | @rn-primitives/tabs | | Progress | 🔜 | @rn-primitives/progress | | ProgressCircle | 🔜 | react-native-svg | | Cards | 🔜 | CardModule, CardLesson, etc. | | DatePicker | 🔜 | @react-native-community/datetimepicker |