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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@react-xp/native

v0.1.0-beta.1

Published

This is a React Experience native package

Downloads

102

Readme

React XP React Native Design System

Design system para React Native com foco em DX e consistência visual. Inclui tokens de design, theming com override granular e componentes acessíveis.

Componentes incluídos

  • Botões (Button, IconButton)
  • Tipografia (Typography)
  • Inputs (TextField, TextArea, PasswordField)
  • Inputs avançados (PinInput, SearchInput)
  • Cartões (Card, CardHeader, CardContent, CardFooter)
  • Tabelas (DataTable)
  • Tags (Tag)
  • Chips e filtros (Chip)
  • Barra de progresso (ProgressBar)
  • Loader (Loader inline e global)
  • Selects (Select, MultiSelect)
  • Overlays (Modal, Drawer)
  • Form primitives (Form, Form.Section, Form.Field, Form.Footer)
  • Controles booleanos (Checkbox, Radio, RadioGroup)
  • Ações flutuantes (FloatingActionButton)
  • Layout primitives (Stack, Inline, Divider)

Templates de ecrã

  • AnalyticsDashboardTemplate: métricas, tendências com ProgressBar e feed de atividades para backoffices analíticos.
  • ListDetailTemplate: master/detail com cartões clicáveis e painel de detalhes para listas de pedidos, tarefas ou contactos.
  • OnboardingTemplate: fluxo de onboarding multi-step com progress bar, ilustrações e CTAs configuráveis.
  • CommerceProductTemplate: apresentação de produto com galeria, badges, features e reviews resumidas.
  • MessagingTemplate: inbox + thread com bubbles e composer integrado.
  • SupportCenterTemplate: centro de ajuda com ações rápidas, artigos destacados e pedidos recentes.

Páginas base

  • LoginPage: autenticação com suporte opcional a social login/magic link via feature flags.
  • RegisterPage: fluxo de registo com password confirmation, consentimento e código de convite controlado por flags.
  • SettingsPage: gestão de sessão, configuração do bloqueio por inatividade/PIN, painel de feature flags e limpeza de storage encriptado.

Páginas de demonstração

  • DesignSystemPlayground: página interativa para testar variantes, estados e espaçamentos dos componentes com dados fictícios e loaders inline/global.
  • DesignSystemShowcase: catálogo que agrupa tipografia, formulários, tabelas, overlays e feedback visual num único ecrã responsivo.
import {
  DesignSystemPlayground,
  DesignSystemShowcase,
  ThemeProvider,
} from '@react-xp/rn-ds';

export function DemoScreens() {
  return (
    <ThemeProvider>
      <DesignSystemShowcase />
      <DesignSystemPlayground />
    </ThemeProvider>
  );
}

Utilização básica

import { ThemeProvider, Button, Typography } from '@react-xp/rn-ds';

export function App() {
  return (
    <ThemeProvider>
      <Stack space="lg" style={{ padding: 24 }}>
        <Typography variant="display" weight="bold">
          React XP RN Design System
        </Typography>
        <Button variant="primary" onPress={() => {}}>
          Começar agora
        </Button>
      </Stack>
    </ThemeProvider>
  );
}

Camada de styling e escalabilidade

  • Na comparação com Tailwind (twrnc), Radix UI e shadcn/ui avaliados na comunidade, optámos por manter uma camada styled orientada a tokens: garante paridade com React Native + react-native-web, evita dependências nativas adicionais e oferece DX typed semelhante a Restyle/Tamagui, padrões adotados em design systems escaláveis.
  • A biblioteca expõe um helper styled inspirado em styled-components/native, que aplica os tokens do tema automaticamente e funciona tanto em React Native como em React (via react-native-web).
  • O ThemeProvider exportado injeta o tema partilhado para os componentes do design system e para o helper styled, permitindo criar extensões sem duplicar tokens.
  • Cada componente consome exclusivamente tokens (spacing, radius, typography, components) para espaçamentos, cores e tamanhos; as props de tamanho/variante convertem-se em leituras de tema, garantindo responsividade por device.
  • É possível criar componentes adicionais que respeitam o tema partilhado:
import { ThemeProvider, styled } from '@react-xp/rn-ds';

const Pill = styled.View(({ theme }) => ({
  paddingHorizontal: theme.spacing.md,
  paddingVertical: theme.spacing.xs,
  borderRadius: theme.radius.pill,
  backgroundColor: theme.colors.surface,
}));
  • Em React web basta reutilizar o mesmo ThemeProvider juntamente com react-native-web. O helper styled partilha o tema e garante paridade visual.

Customização de tema

Select e MultiSelect

import { useState } from 'react';
import { MultiSelect, Select, Stack } from '@react-xp/rn-ds';

const statusOptions = [
  { label: 'Pendente', value: 'pending' },
  { label: 'Em progresso', value: 'in_progress' },
  { label: 'Concluído', value: 'done' },
];

export function Filters() {
  const [status, setStatus] = useState<string | undefined>();
  const [tags, setTags] = useState<string[]>([]);

  return (
    <Stack space="md">
      <Select
        label="Status"
        options={statusOptions}
        value={status}
        onValueChange={(value) => setStatus(value)}
        placeholder="Filtrar por status"
      />
      <MultiSelect
        label="Tags"
        options={statusOptions}
        value={tags}
        onValueChange={(values) => setTags(values)}
        placeholder="Seleciona um ou mais"
      />
    </Stack>
  );
}

Modal e Drawer

import { useState } from 'react';
import { Button, Drawer, Modal, Select, Stack, TextField } from '@react-xp/rn-ds';

export function Overlays() {
  const [modalOpen, setModalOpen] = useState(false);
  const [drawerOpen, setDrawerOpen] = useState(false);

  return (
    <>
      <Button onPress={() => setModalOpen(true)}>Abrir modal</Button>
      <Button variant="outline" onPress={() => setDrawerOpen(true)}>
        Abrir drawer
      </Button>

      <Modal
        open={modalOpen}
        onClose={() => setModalOpen(false)}
        title="Enviar relatório"
        description="Confirma o envio do relatório mensal?"
        actions={
          <Stack direction="row" space="sm">
            <Button variant="ghost" onPress={() => setModalOpen(false)}>
              Cancelar
            </Button>
            <Button onPress={() => setModalOpen(false)}>Confirmar</Button>
          </Stack>
        }
      />

      <Drawer
        open={drawerOpen}
        onClose={() => setDrawerOpen(false)}
        title="Filtros avançados"
        footer={
          <Stack direction="row" space="sm">
            <Button variant="ghost" onPress={() => setDrawerOpen(false)}>
              Fechar
            </Button>
            <Button onPress={() => setDrawerOpen(false)}>Aplicar filtros</Button>
          </Stack>
        }
      >
        <TextField label="Projeto" placeholder="Nome do projeto" />
        <Select label="Prioridade" options={[{ label: 'Alta', value: 'high' }]} />
      </Drawer>
    </>
  );
}

Form helpers

import { Button, Form, TextField } from '@react-xp/rn-ds';

export function ProfileForm() {
  return (
    <Form>
      <Form.Section title="Informações pessoais">
        <Form.Field label="Nome" required>
          <TextField placeholder="Nome completo" />
        </Form.Field>
        <Form.Field label="Email" helperText="Usado para notificações">
          <TextField keyboardType="email-address" autoCapitalize="none" />
        </Form.Field>
      </Form.Section>

      <Form.Footer>
        <Button variant="ghost">Cancelar</Button>
        <Button>Guardar</Button>
      </Form.Footer>
    </Form>
  );
}

PinInput e autenticação

import { useState } from 'react';
import { PinInput, Stack } from '@react-xp/rn-ds';

export function TwoFactorStep() {
  const [code, setCode] = useState('');

  return (
    <Stack space="md">
      <PinInput
        label="Código de verificação"
        length={6}
        value={code}
        onChange={setCode}
        onComplete={(value) => console.log('Código completo', value)}
        helperText="Enviámos o código para o teu email."
      />
    </Stack>
  );
}

Pesquisa assíncrona

import { useState } from 'react';
import { SearchInput, Stack } from '@react-xp/rn-ds';

const cities = ['Lisboa', 'Porto', 'Braga', 'Faro'];

async function fetchCities(query: string) {
  await new Promise((resolve) => setTimeout(resolve, 350));
  return cities
    .filter((city) => city.toLowerCase().includes(query.toLowerCase()))
    .map((city) => ({ id: city, title: city }));
}

export function SearchExample() {
  const [selected, setSelected] = useState<string | undefined>();

  return (
    <Stack space="md">
      <SearchInput
        label="Cidade"
        placeholder="Procura uma cidade"
        fetchResults={fetchCities}
        onSelectResult={(result) => setSelected(result.title)}
        helperText={selected ? `Selecionado: ${selected}` : undefined}
      />
    </Stack>
  );
}

Checkbox, Radio e Chip

import { useState } from 'react';
import {
  Checkbox,
  Chip,
  Radio,
  RadioGroup,
  Stack,
} from '@react-xp/rn-ds';

export function Preferences() {
  const [newsletter, setNewsletter] = useState(true);
  const [priority, setPriority] = useState('standard');
  const [tags, setTags] = useState(['design']);

  return (
    <Stack space="lg">
      <Checkbox
        label="Receber newsletter"
        helperText="Atualizações mensais sobre o produto"
        checked={newsletter}
        onChange={setNewsletter}
      />

      <RadioGroup
        label="Prioridade"
        value={priority}
        onValueChange={setPriority}
        direction="row"
        gap={16}
      >
        <Radio value="standard" label="Standard" />
        <Radio value="express" label="Express" />
      </RadioGroup>

      <Stack direction="row" space="sm">
        {['design', 'mobile', 'react'].map((tag) => {
          const selected = tags.includes(tag);
          return (
            <Chip
              key={tag}
              label={tag}
              selected={selected}
              onPress={() =>
                setTags((current) =>
                  selected
                    ? current.filter((item) => item !== tag)
                    : [...current, tag],
                )
              }
            />
          );
        })}
      </Stack>
    </Stack>
  );
}

Loader inline e global

import { useState } from 'react';
import { Button, Loader, Stack } from '@react-xp/rn-ds';

export function LoadingStates() {
  const [overlay, setOverlay] = useState(false);

  return (
    <>
      <Stack space="md">
        <Loader size="sm" message="A carregar lista" />
        <Button onPress={() => setOverlay(true)}>Mostrar loader global</Button>
      </Stack>

      <Loader
        mode="overlay"
        visible={overlay}
        message="A sincronizar dados"
        onRequestClose={() => setOverlay(false)}
      />
    </>
  );
}

FloatingActionButton

import { FloatingActionButton } from '@react-xp/rn-ds';

export function FabExample() {
  return (
    <FloatingActionButton
      label="Nova tarefa"
      onPress={() => console.log('Adicionar tarefa')}
      position={{ bottom: 48, right: 24 }}
    />
  );
}

Override rápido de tokens

const customTheme = {
  colors: {
    primary: '#7c3aed',
    primaryForeground: '#f8fafc'
  }
};

<ThemeProvider theme={customTheme}>
  <Button variant="primary">Personalizado</Button>
</ThemeProvider>;

Todos os tokens suportam override parcial. Arrays e objetos internos são combinados de forma profunda.

Feature flags e experiências condicionais

  • FeatureFlagProvider: carrega overrides assíncronos, suporta rollout percentual com audienceKey e dependências entre flags.
  • useFeatureFlag, useIsFeatureEnabled e FeatureGate: hooks/componentes para consumir flags com DX segura.
  • FeatureFlagDevPanel: painel interactivo para overrides manuais e visualização do rollout.

Segurança e produtividade cross-app

  • createEncryptedStorage: wrapper com codificação XOR + fallback para AsyncStorage/memória, pensado para tokens sensíveis.
  • InactivityLockProvider: monitoriza inatividade e permite auto lock, mensagem custom e overlay com PinInput.
  • InactivityLockOverlay e InactivityLockTouchBoundary: helpers para proteger o ecrã após X segundos sem interação.
  • WebContentView: componente resiliente para embutir websites via react-native-webview, com fallback e abertura externa.

Boas práticas

  • Utilizar os helpers useThemedStyles e useTheme para derivar estilos com tokens atualizados.
  • Preferir os componentes do design system em vez de Text, View e Pressable puros para manter consistência.
  • Mantém as variantes alinhadas com defaultTheme.components.

Scripts

  • pnpm --filter "./apps/rn-ds" run typecheck