JSPM

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

Random picker with drop animation — a spinner alternative.

Package Exports

  • drop-spinner
  • drop-spinner/dist/index.js
  • drop-spinner/dist/index.mjs

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (drop-spinner) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

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