JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 14
  • Score
    100M100P100Q43106F
  • License MIT

Random picker with drop animation — a spinner alternative.

Package Exports

  • drop-spinner

Readme

drop-spinner

drop-spinner es una librería ligera para seleccionar elementos al azar con una interfaz visual opcional. Está pensada para ser usada como componente React, como utilidad programática y (opcionalmente) como Web Component. El paquete está preparado para publicarse en npm y es compatible con entornos SSR como Next.js.

Contenido del README:

  • Instalación
  • Uso rápido (React)
  • Uso en Next.js (SSR)
  • Uso programático
  • API
  • Build y publicación
  • Ejemplo local

Instalación

npm install drop-spinner

Nota: el paquete debe declarar react y react-dom como peerDependencies. Asegúrate de instalarlos en tu proyecto consumidor.


Uso rápido — Componente React

import { RandomImagePicker, ImageOption } from 'drop-spinner';

const items: ImageOption[] = [
  { name: 'Apple', url: '/img/apple.png' },
  { name: 'Banana', url: '/img/banana.png' },
  { name: 'Cherry' }
];

export default function Page() {
  return <RandomImagePicker items={items} />;
}

Uso adicional: CircularWheel

El paquete también incluye un componente visual tipo rueda/slot llamado CircularWheel pensado para mostrar imágenes alrededor de una rueda o en un viewport de 'slot'. Usa el mismo tipo ImageOption.

Ejemplo de uso:

import { CircularWheel, ImageOption } from 'drop-spinner';

const images: ImageOption[] = [
  { name: 'Burger', url: 'https://images.unsplash.com/photo-1568901346375-23c9450c58cd' },
  { name: 'Pizza', url: 'https://images.unsplash.com/photo-1544982503-9f984c14501a' },
  { name: 'Coffee', url: 'https://images.unsplash.com/photo-1533776992670-a72f4c28235e' },
  { name: 'Donut', url: 'https://images.unsplash.com/photo-1733754348967-62a6870f51b7' }
];

export default function Page() {
  const handleSpin = (winnerIndex: number, winnerName: string) => {
    console.log('Ganador:', winnerIndex, winnerName);
  };

  return <CircularWheel images={images} size={360} onSpin={handleSpin} />;
}

Notas:

  • images acepta ImageOption[] donde ImageOption = { name: string; url?: string }.
  • onSpin se invoca cuando la animación termina con (winnerIndex, winnerName).

El componente es sencillo: recibe items: ImageOption[] y muestra el elemento seleccionado (o un texto si no hay imagen). ImageOption es { name: string; url?: string }.


Uso en Next.js / SSR

Si usas características que dependen del DOM (registro de Web Components o utilidades que montan nodos), registra el componente solo en el cliente:

import { useEffect } from 'react';
import { registerDropSpinner, dropSpinner } from 'drop-spinner';

export default function Page() {
  useEffect(() => {
    if (typeof registerDropSpinner === 'function') registerDropSpinner();
  }, []);

  async function handlePick() {
    const result = await dropSpinner({ items: ['A','B','C'] });
    alert('Picked: ' + result);
  }

  return <button onClick={handlePick}>Pick</button>;
}

Registra el Web Component (si existe) dentro de useEffect para evitar fallos en SSR (no existe window en el servidor).

Uso recomendado: wrapper server + componente cliente

El paquete exporta dos variantes:

  • RandomImagePicker — server-safe placeholder (se puede importar desde componentes server sin causar errores de hidratación).
  • RandomImagePickerClient — componente con toda la interactividad; debe importarse desde un Client Component.

Ejemplo (page.tsx — Server Component):

import { RandomImagePicker } from 'drop-spinner';

export default function Page() {
  const items = [{ name: 'Apple' }, { name: 'Banana' }, { name: 'Cherry' }];
  return <RandomImagePicker items={items} />; // server-safe
}

Ejemplo (PickerClient.tsx — Client Component):

'use client';
import { RandomImagePickerClient } from 'drop-spinner';

export default function PickerClient({ items }) {
  return <RandomImagePickerClient items={items} />;
}

Si quieres montar dinámicamente el componente cliente desde un componente server puedes usar next/dynamic:

import dynamic from 'next/dynamic';
const DynamicPicker = dynamic(() => import('drop-spinner').then(m => m.RandomImagePickerClient), { ssr: false });

export default function Page() {
  const items = [{ name: 'Apple' }, { name: 'Banana' }];
  return <DynamicPicker items={items} />;
}

Uso programático

La utilidad dropSpinner(options) permite invocar la selección programáticamente. En cliente retorna una Promise que se resuelve tras la animación; en entornos sin DOM puede comportarse de forma síncrona.

import { dropSpinner } from 'drop-spinner';

const winner = await dropSpinner({
  items: ['🍎','🍌','🍇'],
  animationSpeed: 1200,
  circleSize: 200,
  onPick: (item) => console.log('picked', item)
});

API (resumen)

  • RandomImagePicker — componente React. Props:

    • items: ImageOption[]
  • getRandomItem(items: ImageOption[]): ImageOption | undefined — devuelve un item aleatorio o undefined si la lista está vacía.

  • dropSpinner(options: DropSpinnerOptions) — función útil para lanzar la selección con animación.

  • registerDropSpinner() — registra el Web Component en el cliente (si el paquete lo exporta).

Tipos importantes:

  • ImageOption = { name: string; url?: string }
  • DropSpinnerOptions = { items: string[] | ImageOption[]; animationSpeed?: number; circleSize?: number; onPick?: (item: any) => void }

Build y publicación

El proyecto usa tsup para generar bundles ESM/CJS y tipados.

Antes de publicar:

  1. Asegúrate de que package.json tiene los campos name, version, main, module, types y exports correctamente configurados.
  2. Ejecuta:
npm run build
  1. Comprueba el contenido del paquete:
npm pack --dry-run
  1. Publica en npm:
npm publish --access public

Recomendación: mantener react/react-dom en peerDependencies y @types/react en devDependencies.


Ejemplo local (Next.js)

El repositorio incluye un ejemplo minimal en example/next-app. Para ejecutarlo localmente:

cd example/next-app
npm install
npm run dev

El ejemplo está configurado para usar el paquete local empaquetado (tarball) como dependencia de desarrollo.


Limpieza y publicación segura

  • Añade .npmignore para excluir código fuente y archivos de desarrollo del paquete publicado.
  • Añade .gitignore para evitar subir node_modules, artefactos de build y tarballs.

Contribuciones

PRs y issues son bienvenidos. Incluye tests y actualiza README.md si cambias la API.


Licencia

MIT