Adaptador React
El paquete @presage-kit/react proporciona componentes y hooks de React para construir interfaces adaptativas.
Instalacion
Sección titulada «Instalacion»pnpm add @presage-kit/core @presage-kit/reactAdaptiveProvider
Sección titulada «AdaptiveProvider»Proporciona el AdaptiveClient a todo el arbol de componentes mediante el contexto de React.
import { AdaptiveProvider } from '@presage-kit/react'import { createAdaptiveClient, createLocalStorageDriver } from '@presage-kit/core'
const client = createAdaptiveClient({ rules: [/* ... */], persistence: { driver: createLocalStorageDriver('my-app') },})
function App() { return ( <AdaptiveProvider client={client}> <YourApp /> </AdaptiveProvider> )}Props:
| Prop | Tipo | Descripcion |
|---|---|---|
client | AdaptiveClient | La instancia del cliente creada con createAdaptiveClient() |
children | ReactNode | Su arbol de aplicacion |
Componente <Adaptive>
Sección titulada «Componente <Adaptive>»Declara un adaptation point y renderiza la variante correspondiente.
import { Adaptive, Variant } from '@presage-kit/react'
function Dashboard() { return ( <Adaptive id="dashboard-layout" defaultVariant="standard"> <Variant id="compact"> <CompactDashboard /> </Variant> <Variant id="standard"> <StandardDashboard /> </Variant> <Variant id="advanced"> <AdvancedDashboard /> </Variant> </Adaptive> )}Props de <Adaptive>:
| Prop | Tipo | Descripcion |
|---|---|---|
id | string | Identificador unico del adaptation point |
defaultVariant | string | Variante a mostrar cuando ninguna regla coincide |
children | ReactNode | Debe contener componentes <Variant> |
Props de <Variant>:
| Prop | Tipo | Descripcion |
|---|---|---|
id | string | Identificador de la variante (referenciado en las acciones de reglas) |
children | ReactNode | Contenido a renderizar cuando esta variante es seleccionada |
El componente <Adaptive> utiliza internamente useAdaptive() y rastrea automaticamente las impresiones cuando la variante seleccionada cambia.
Componente <AdaptiveNav>
Sección titulada «Componente <AdaptiveNav>»Renderiza una lista de elementos de navegacion que pueden ser reordenados por reglas de adaptacion.
import { AdaptiveNav, type NavItem } from '@presage-kit/react'
interface MenuItem extends NavItem { label: string href: string icon: string}
const menuItems: MenuItem[] = [ { id: 'home', label: 'Home', href: '/', icon: 'home' }, { id: 'analytics', label: 'Analytics', href: '/analytics', icon: 'chart' }, { id: 'settings', label: 'Settings', href: '/settings', icon: 'gear' },]
function Sidebar() { return ( <AdaptiveNav id="sidebar-nav" items={menuItems} renderItem={(item, index) => ( <a key={item.id} href={item.href}> {item.icon} {item.label} </a> )} /> )}Con una regla reorder, el orden de navegacion cambia segun el contexto del usuario:
{ id: 'power-user-nav-order', adaptationId: 'sidebar-nav', priority: 10, conditions: { all: [{ field: 'maturity', operator: 'eq', value: 'power' }], }, action: { type: 'reorder', order: ['analytics', 'home', 'settings'] },}Con una regla hide, toda la navegacion se oculta:
{ id: 'hide-nav-for-new-users', adaptationId: 'sidebar-nav', priority: 20, conditions: { all: [{ field: 'maturity', operator: 'eq', value: 'new' }], }, action: { type: 'hide' },}Props:
| Prop | Tipo | Descripcion |
|---|---|---|
id | string | Identificador del adaptation point |
items | T[] (extiende NavItem) | Array de elementos, cada uno con al menos un campo id |
renderItem | (item: T, index: number) => ReactNode | Funcion de renderizado para cada elemento |
Interfaz NavItem:
interface NavItem { id: string [key: string]: unknown}Hook useAdaptive()
Sección titulada «Hook useAdaptive()»El hook principal para resolver adaptation points. Devuelve la variante seleccionada, detalles completos de resolucion, contexto y una funcion de rastreo con scope.
import { useAdaptive } from '@presage-kit/react'
function FeatureDiscovery() { const { selectedVariant, resolution, context, track } = useAdaptive('feature-discovery', { variants: ['tooltip', 'banner', 'modal'] as const, defaultVariant: 'tooltip', })
// Track a conversion event scoped to this adaptation point function handleDismiss() { track('feature_discovery_dismissed') }
switch (selectedVariant) { case 'tooltip': return <Tooltip onDismiss={handleDismiss} /> case 'banner': return <Banner onDismiss={handleDismiss} /> case 'modal': return <Modal onDismiss={handleDismiss} /> }}Parametros:
| Parametro | Tipo | Descripcion |
|---|---|---|
adaptationId | string | Identificador unico del adaptation point |
config.variants | readonly string[] | IDs de variantes disponibles |
config.defaultVariant | string | Variante de respaldo |
config.strategy | Strategy | Opcional. Por defecto { type: 'rules' } |
Tipo de retorno:
| Campo | Tipo | Descripcion |
|---|---|---|
selectedVariant | V | La variante seleccionada (tipo restringido a su union de variantes) |
resolution | ResolvedAdaptation | Detalles completos de resolucion (estrategia, razon, marca de tiempo) |
context | UserContext | Contexto actual del usuario |
track | (event: string, properties?: Record<string, unknown>) => void | Funcion de rastreo con scope para este adaptation point |
Genericos de TypeScript: El hook infiere el tipo de variante a partir de variants:
// selectedVariant is typed as 'tooltip' | 'banner' | 'modal'const { selectedVariant } = useAdaptive('feature-discovery', { variants: ['tooltip', 'banner', 'modal'] as const, defaultVariant: 'tooltip',})Rastreo automatico de impresiones: Cuando la variante seleccionada cambia, useAdaptive() rastrea automaticamente un evento presage:impression con el ID de adaptacion, la variante y la estrategia.
Hook useVariant()
Sección titulada «Hook useVariant()»Un hook mas ligero que devuelve unicamente la cadena de la variante seleccionada. Uselo cuando no necesite los detalles completos de resolucion.
import { useVariant } from '@presage-kit/react'
function CTAButton() { const variant = useVariant('cta-style', { variants: ['primary', 'secondary', 'subtle'] as const, defaultVariant: 'primary', })
return <button className={`cta cta--${variant}`}>Get Started</button>}Parametros: Los mismos que useAdaptive().
Tipo de retorno: V — La cadena de la variante seleccionada.
Hook useAdaptiveClient()
Sección titulada «Hook useAdaptiveClient()»Devuelve la instancia de AdaptiveClient desde el contexto. Util para operaciones imperativas como rastreo e identificacion.
import { useAdaptiveClient } from '@presage-kit/react'
function TrackingButton() { const client = useAdaptiveClient()
function handleClick() { client.track('feature_used', { featureId: 'export' }) }
return <button onClick={handleClick}>Export</button>}Tipo de retorno: AdaptiveClient
Lanza un error si se llama fuera de <AdaptiveProvider>.
Ejemplo completo: Tablero SaaS
Sección titulada «Ejemplo completo: Tablero SaaS»Este ejemplo muestra una barra lateral adaptativa y un flujo de incorporacion para un tablero SaaS.
import { createAdaptiveClient, createLocalStorageDriver } from '@presage-kit/core'
export const client = createAdaptiveClient({ rules: [ // Sidebar: prioritize analytics for power users { id: 'power-user-sidebar', adaptationId: 'sidebar', priority: 10, conditions: { all: [{ field: 'maturity', operator: 'eq', value: 'power' }], }, action: { type: 'reorder', order: ['analytics', 'dashboards', 'settings', 'home'] }, }, // Onboarding: guided tour for new users { id: 'new-user-tour', adaptationId: 'onboarding', priority: 10, conditions: { all: [{ field: 'maturity', operator: 'eq', value: 'new' }], }, action: { type: 'show', variantId: 'guided-tour' }, }, // Onboarding: hide for experienced users { id: 'experienced-no-onboarding', adaptationId: 'onboarding', priority: 5, conditions: { any: [ { field: 'maturity', operator: 'eq', value: 'active' }, { field: 'maturity', operator: 'eq', value: 'power' }, ], }, action: { type: 'hide' }, }, ], persistence: { driver: createLocalStorageDriver('saas-demo'), },})import { AdaptiveProvider } from '@presage-kit/react'import { client } from './lib/adaptive-client'import { Sidebar } from './components/Sidebar'import { Onboarding } from './components/Onboarding'import { Dashboard } from './components/Dashboard'
export function App() { return ( <AdaptiveProvider client={client}> <div style={{ display: 'flex' }}> <Sidebar /> <main> <Onboarding /> <Dashboard /> </main> </div> </AdaptiveProvider> )}import { AdaptiveNav, type NavItem } from '@presage-kit/react'
interface SidebarItem extends NavItem { label: string href: string}
const items: SidebarItem[] = [ { id: 'home', label: 'Home', href: '/' }, { id: 'dashboards', label: 'Dashboards', href: '/dashboards' }, { id: 'analytics', label: 'Analytics', href: '/analytics' }, { id: 'settings', label: 'Settings', href: '/settings' },]
export function Sidebar() { return ( <nav> <AdaptiveNav id="sidebar" items={items} renderItem={(item) => ( <a key={item.id} href={item.href}> {item.label} </a> )} /> </nav> )}import { Adaptive, Variant } from '@presage-kit/react'
export function Onboarding() { return ( <Adaptive id="onboarding" defaultVariant="standard"> <Variant id="guided-tour"> <div> <h2>Welcome! Let us show you around.</h2> <p>Follow the steps to get set up.</p> </div> </Variant> <Variant id="standard"> <div> <h2>What is new</h2> <p>Check out the latest features.</p> </div> </Variant> </Adaptive> )}