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

@agroshine/ags-mobile-ui-kit

v1.0.1

Published

AgroShine · librería de componentes React Native reutilizables (NativeWind + rn-primitives + lucide-react-native).

Downloads

254

Readme

@agroshine/ags-mobile-ui-kit

npm version license: MIT

Librería de componentes React Native reutilizables de AgroShine. Es el espejo móvil de @agroshine/ags-web-ui-kit: misma paleta, mismos tokens semánticos, misma filosofía AgroShine — adaptada al stack RN.


Tabla de contenidos


Stack

  • NativeWind 4 (sintaxis Tailwind v3) — clases utilitarias en React Native.
  • React Native Reusables (@rn-primitives/*) — primitives accesibles (Radix-style) para RN.
  • lucide-react-native — iconografía vectorial.
  • jotai — estado del Toaster.
  • react-native-builder-bob 0.40 — empaqueta a CJS, ESM y .d.ts.
  • TypeScript estricto, ESLint flat config, Prettier.

Instalación

# pnpm
pnpm add @agroshine/ags-mobile-ui-kit

# yarn
yarn add @agroshine/ags-mobile-ui-kit

# npm
npm install @agroshine/ags-mobile-ui-kit

Peer dependencies

El kit declara como peers (no las trae él mismo) las libs que tu app ya debería estar usando. Instala las que falten:

pnpm add nativewind tailwindcss@^3 tailwind-merge clsx \
  class-variance-authority lucide-react-native \
  react-native-gesture-handler react-native-reanimated \
  react-native-safe-area-context react-native-svg \
  @rn-primitives/slot

@rn-primitives/* adicionales (accordion, dialog, popover, select, tabs, tooltip, etc.) son opcionales — solo instala los que use el componente que vayas a consumir.

jotai es opcional pero requerido si vas a usar el Toaster o el toastStore del kit.


Setup en una app Expo / React Native

1. tailwind.config.js

Asegúrate de incluir el dist del kit en content y aplicar tanto el preset de NativeWind como el del kit:

module.exports = {
  content: [
    './App.{js,jsx,ts,tsx}',
    './index.{js,jsx,ts,tsx}',
    './app/**/*.{js,jsx,ts,tsx}',
    './node_modules/@agroshine/ags-mobile-ui-kit/**/*.{js,ts,jsx,tsx}',
  ],
  presets: [
    require('nativewind/preset'),
    require('@agroshine/ags-mobile-ui-kit/tailwind.preset'),
  ],
};

2. metro.config.js

const { getDefaultConfig } = require('expo/metro-config');
const { withNativeWind } = require('nativewind/metro');

const config = getDefaultConfig(__dirname);

module.exports = withNativeWind(config, {
  input: './global.css', // tu propio CSS app
});

3. global.css de la app

Re-exporta los tokens del kit (o cópialos) para que las variables HSL estén disponibles:

@import '@agroshine/ags-mobile-ui-kit/styles/global.css';

/* Y/o agrega tus propios overrides debajo. */

4. babel.config.js

module.exports = function (api) {
  api.cache(true);
  return {
    presets: [
      ['babel-preset-expo', { jsxImportSource: 'nativewind' }],
      'nativewind/babel',
    ],
  };
};

5. Provider raíz (opcional pero recomendado)

Si vas a usar Toaster, monta SafeAreaProvider en la raíz:

import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Toaster } from '@agroshine/ags-mobile-ui-kit';

export default function App() {
  return (
    <SafeAreaProvider>
      {/* tu app */}
      <Toaster position="bottom" />
    </SafeAreaProvider>
  );
}

Setup en Storybook (web)

El kit incluye configuración de Storybook 8 (React + Vite) en .storybook/ que renderiza componentes RN en el browser vía react-native-web. Para arrancarlo localmente sobre el repo del kit:

pnpm storybook        # http://localhost:6006
pnpm build-storybook  # static build

Detalles del setup (alias react-nativereact-native-web, stub para react-native-safe-area-context, NativeWind via PostCSS) viven en .storybook/main.ts y .storybook/preview.tsx. Si añades organisms que toquen APIs nativas adicionales (TurboModules, codegen), recuerda stubearlas en .storybook/mocks/ y excluirlas de optimizeDeps.


Estructura del paquete

src/
├── atoms/          Componentes opinionados AgroShine (Button, Input, …)
├── molecules/      Composiciones (FormField, Select, EntityCard, …)
├── organisms/      Composiciones de alto nivel (Layout, Drawer, Toaster, …)
├── ui/             Primitives rn-primitives-style (button, switch, …)
├── hooks/          Hooks compartidos (placeholder — en desarrollo)
├── lib/            Utilidades (cn, tailwindColors, toastStore)
├── foundation/     Catálogo visual (vacío — en desarrollo)
└── styles/
    └── global.css  Directivas Tailwind + tokens semánticos HSL

Subpath exports

| Import path | Contenido | | --------------------------------------------------- | ------------------------------- | | @agroshine/ags-mobile-ui-kit | Barrel raíz (atoms + molecules + organisms + lib + hooks) | | @agroshine/ags-mobile-ui-kit/atoms | Solo atoms | | @agroshine/ags-mobile-ui-kit/molecules | Solo molecules | | @agroshine/ags-mobile-ui-kit/organisms | Solo organisms | | @agroshine/ags-mobile-ui-kit/ui | Primitives rn-primitives-style | | @agroshine/ags-mobile-ui-kit/hooks | Hooks | | @agroshine/ags-mobile-ui-kit/lib | cn, tailwindColors, toast atoms | | @agroshine/ags-mobile-ui-kit/tailwind.preset | Preset de Tailwind | | @agroshine/ags-mobile-ui-kit/styles/global.css | Stylesheet base + tokens HSL |

Los primitives bajo /ui no se re-exportan desde el barrel raíz para evitar colisión con sus wrappers opinionados.


API pública

Atoms

| Componente | Props clave | | ------------ | --------------------------------------------------------------------------- | | Button | variant (primary · secondary · outline · ghost · danger · success · link), size (sm/md/lg), loading, disabled, fullWidth | | IconButton | Igual que Button + icon: IconName | | Input | label, helperText, error, containerClassName, etc. (extiende TextInputProps) | | TextArea | Igual que Input + multi-línea | | Badge | tone (default · secondary · success · warning · danger · outline · muted) | | Card | Wrapper + CardHeader, CardContent, CardFooter, CardTitle, CardDescription | | Divider | orientation (horizontal/vertical) | | Icon | name: IconName, size, className (color por Tailwind) | | Snackbar | variant (default · success · info · warning · error), message, actionLabel, onActionPress | | Spinner | Wrapper de ActivityIndicator | | Text | variant (default · h1..h4 · p · blockquote · code · lead · large · small · muted) |

import { Button, Input, Badge } from '@agroshine/ags-mobile-ui-kit';

<Button variant="primary" loading={isSubmitting} onPress={save}>
  Guardar
</Button>

<Input label="Correo" error={!!errors.email} helperText={errors.email} />

<Badge tone="success">Sincronizado</Badge>

Molecules

| Componente | Descripción | | ---------------------- | ------------------------------------------------------------ | | ActionSheet | Bottom sheet modal con acciones | | ConfirmActionSheet | ActionSheet con CTA destructiva + cancelar | | CardButton | Card táctil con icono + label | | EmptyState | Estado vacío (icono + título + descripción + CTA) | | EntityCard | Card para listas (avatar/icon + título + subtítulo + actions) | | FormField | Wrapper para inputs (label, required, error, helperText) | | ObservationCard | Card de observación con estado (pending/synced/error) | | SearchInput | Input con icono de búsqueda + clear | | Select | Dropdown con búsqueda opcional (options, searchable) | | SyncStatusBadge | Badge con estado de sync | | TechnicalSheetButton | Botón que abre el TechnicalSheet organism |

import { FormField, Select } from '@agroshine/ags-mobile-ui-kit';

<FormField label="País" required error={errors.country}>
  <Select
    value={country}
    options={[
      { label: 'Chile', value: 'CL' },
      { label: 'Perú', value: 'PE' },
    ]}
    onSelect={setCountry}
    searchable
  />
</FormField>

Organisms

| Componente | Descripción | | ----------------- | ---------------------------------------------------------- | | Layout | Contenedor de pantalla (safe area + scroll opcional) | | ScreenHeader | Header con back + título + acciones | | Breadcrumbs | Migas de pan | | BottomMenu | Menú inferior con acciones (observación, ficha, crear, etc.) | | Drawer | Drawer lateral / modal sheet | | TechnicalSheet | Ficha técnica de Block/Ship (datos de cultivo) | | Toaster | Stack de toasts global (consume toastStore) | | QueryState | Renderiza loading / error / empty / data para queries |

UI primitives (rn-primitives-style)

Wrappers shadcn-style, sin opinión de marca. Útiles para construir componentes nuevos:

badge · button · card · icon · input · separator · skeleton · text · textarea

import { Button, buttonVariants } from '@agroshine/ags-mobile-ui-kit/ui';

// con variants para construir tus propios componentes
<Pressable className={buttonVariants({ variant: 'outline', size: 'lg' })}>
  <Text>Custom</Text>
</Pressable>

Lib utils

import { cn, addToastAtom, dismissToastAtom, toastsAtom }
  from '@agroshine/ags-mobile-ui-kit/lib';

// cn: clsx + tailwind-merge
<View className={cn('p-4', isActive && 'bg-primary-50', extraClass)} />

Sistema de iconos

El atom Icon mapea nombres semánticos a iconos de lucide-react-native. Las pantallas y componentes propios deben usar Icon y nunca importar lucide-react-native directamente (esto centraliza el catálogo y permite sustituir el set de iconos en el futuro).

import { Icon } from '@agroshine/ags-mobile-ui-kit';

<Icon name="checkCircle" size={20} className="text-success" />

Nombres disponibles (extracto): alert · archive · arrowLeft · arrowRight · check · checkCircle · checkSquare · chevronDown · chevronLeft · chevronRight · chevronUp · circle · add · edit · eye · eyeOff · fileText · filter · home · info · list · listChecks · logout · menu · more · pencil · plus · refresh · save · search · send · settings · square · trash · upload · close

El catálogo completo está en src/atoms/Icon/icons.ts. Si pasas un nombre desconocido y __DEV__ está activo verás un warning en consola; el render cae a menu como fallback seguro.


Toasts (Toaster)

El Toaster es un organism global respaldado por átomos de Jotai (toastStore). Mismo enfoque shadcn/sonner pero RN-native.

// App.tsx
import { Toaster } from '@agroshine/ags-mobile-ui-kit';

<Toaster position="bottom" visibleToasts={3} />
// Cualquier pantalla
import { useSetAtom } from 'jotai';
import { addToastAtom } from '@agroshine/ags-mobile-ui-kit/lib';

const showToast = useSetAtom(addToastAtom);

showToast({
  message: 'Observación guardada',
  variant: 'success',
  duration: 4000, // opcional, default 4000
  actionLabel: 'Deshacer', // opcional
  onActionPress: () => undo(),
});

Variantes (heredadas de Snackbar): default · success · info · warning · error.


Tokens y paleta

La paleta de marca (default · primary · secondary · success · warning · danger · grey, escala completa 50→900 + DEFAULT + foreground, además de content1-content4, focus, overlay) es idéntica a la del web kit (ags-web-ui-kit/src/styles/tokens.css). Vive en tailwind.preset.cjs con sintaxis Tailwind v3 porque NativeWind 4 aún no soporta el @theme de v4.

Los tokens semánticos shadcn-compatibles (--background, --border, --ring, --muted, --accent, --popover, --card, --destructive, --input, --radius) viven en src/styles/global.css como variables HSL. El soporte de .dark:root está activo — para alternarlo, agrega la clase dark a la raíz desde tu app.

Acceso programático desde JS (útil para style={} o componentes que no aceptan className):

import { tailwindColors } from '@agroshine/ags-mobile-ui-kit/lib';

<ActivityIndicator color={tailwindColors.primary.DEFAULT} />

Scripts

| Comando | Descripción | | ---------------------- | ---------------------------------------------------------- | | pnpm build | Compila con react-native-builder-bob (CJS + ESM + d.ts) | | pnpm clean | Borra lib/ | | pnpm typecheck | tsc --noEmit | | pnpm lint | ESLint sobre src/ | | pnpm lint:fix | ESLint con --fix | | pnpm format | Prettier sobre src/ | | pnpm format:check | Prettier en modo check | | pnpm storybook | Levanta Storybook web (vite + RN-Web) en :6006 | | pnpm build-storybook | Build estático de Storybook | | pnpm commit | Commitizen interactivo (cz-customizable) | | pnpm release | semantic-release |


Compatibilidad

  • Node ≥ 20
  • pnpm ≥ 10 (es el package manager del kit; las apps consumidoras pueden usar yarn/npm)
  • React 18 o 19
  • React Native ≥ 0.73 (probado con 0.81.x)
  • Expo SDK 50+ (NativeWind 4 requiere Reanimated 3+)
  • NativeWind 4.x
  • Tailwind CSS 3.4+

⚠️ El kit se construye y publica con react-native-builder-bob 0.40. Los tipos viven en lib/typescript/{commonjs,module}/src/**. Si forkeas el kit y cambias bob, verifica que el campo exports.<sub>.import.types y .require.types siga apuntando a archivos existentes (corre pnpm build && npm pack --dry-run).


Publicación a npm

El paquete está bajo el scope público @agroshine. Para publicar:

pnpm typecheck    # debe pasar
pnpm lint         # debe pasar
pnpm build        # genera lib/
npm pack --dry-run  # revisa contenido del tarball

# bump de versión (semantic-release lo hace automático en CI):
npm version patch | minor | major

npm publish --access public

La automatización vía pnpm release usa semantic-release con changelog, git tag, npm publish y GitHub release.


Contribuir

  1. Crea una rama desde main.
  2. pnpm install (Node ≥ 20, pnpm ≥ 10).
  3. Añade tu componente bajo el nivel correcto (atoms / molecules / organisms) con su index.ts, Component.tsx, Component.types.ts y Component.stories.tsx.
  4. Re-exporta desde el barrel del nivel.
  5. pnpm typecheck && pnpm lint && pnpm build.
  6. pnpm commit para un commit Conventional via Commitizen.
  7. Abre PR.

Convenciones:

  • Nunca importes lucide-react-native directo desde un componente del kit — usa el atom Icon y agrega el icono al catálogo si hace falta.
  • Nunca importes desde pantallas de las apps — el kit es self-contained.
  • Estilos solo vía className (NativeWind). Evita style={{ ... }} salvo para valores no expresables en Tailwind.
  • Props con Props suffix en sus types files (ButtonProps).
  • Si tu componente necesita un primitive nuevo, agrégalo a src/ui/ primero y luego envuélvelo en el atom/molecule/organism.

Licencia

MIT © AgroShine