Adaptateur React
Le package @presage-kit/react fournit des composants React et des hooks pour construire des interfaces adaptatives.
Installation
Section intitulée « Installation »pnpm add @presage-kit/core @presage-kit/reactAdaptiveProvider
Section intitulée « AdaptiveProvider »Fournit le AdaptiveClient à l’ensemble de l’arbre de composants via le contexte 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 | Type | Description |
|---|---|---|
client | AdaptiveClient | L’instance du client issue de createAdaptiveClient() |
children | ReactNode | Votre arbre applicatif |
Composant <Adaptive>
Section intitulée « Composant <Adaptive> »Déclare un point d’adaptation et rend la variante correspondante.
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 | Type | Description |
|---|---|---|
id | string | Identifiant unique du point d’adaptation |
defaultVariant | string | Variante à afficher quand aucune règle ne correspond |
children | ReactNode | Doit contenir des composants <Variant> |
Props de <Variant> :
| Prop | Type | Description |
|---|---|---|
id | string | Identifiant de la variante (référencé dans les actions de règles) |
children | ReactNode | Contenu à rendre quand cette variante est sélectionnée |
Le composant <Adaptive> utilise en interne useAdaptive() et suit automatiquement les impressions quand la variante sélectionnée change.
Composant <AdaptiveNav>
Section intitulée « Composant <AdaptiveNav> »Rend une liste d’éléments de navigation pouvant être réordonnés par les règles d’adaptation.
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> )} /> )}Avec une règle reorder, l’ordre de navigation change en fonction du contexte utilisateur :
{ 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'] },}Avec une règle hide, la navigation entière est masquée :
{ id: 'hide-nav-for-new-users', adaptationId: 'sidebar-nav', priority: 20, conditions: { all: [{ field: 'maturity', operator: 'eq', value: 'new' }], }, action: { type: 'hide' },}Props :
| Prop | Type | Description |
|---|---|---|
id | string | Identifiant du point d’adaptation |
items | T[] (extends NavItem) | Tableau d’éléments, chacun avec au minimum un champ id |
renderItem | (item: T, index: number) => ReactNode | Fonction de rendu pour chaque élément |
Interface NavItem :
interface NavItem { id: string [key: string]: unknown}Hook useAdaptive()
Section intitulée « Hook useAdaptive() »Le hook principal pour résoudre les points d’adaptation. Retourne la variante sélectionnée, les détails complets de résolution, le contexte et une fonction de suivi scopée.
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} /> }}Paramètres :
| Param | Type | Description |
|---|---|---|
adaptationId | string | Identifiant unique du point d’adaptation |
config.variants | readonly string[] | IDs de variantes disponibles |
config.defaultVariant | string | Variante de repli |
config.strategy | Strategy | Optionnel. Par défaut { type: 'rules' } |
Type de retour :
| Champ | Type | Description |
|---|---|---|
selectedVariant | V | La variante sélectionnée (type restreint à votre union de variantes) |
resolution | ResolvedAdaptation | Détails complets de résolution (stratégie, raison, horodatage) |
context | UserContext | Contexte utilisateur courant |
track | (event: string, properties?: Record<string, unknown>) => void | Fonction de suivi scopée à ce point d’adaptation |
Génériques TypeScript : Le hook infère le type de variante depuis variants :
// selectedVariant is typed as 'tooltip' | 'banner' | 'modal'const { selectedVariant } = useAdaptive('feature-discovery', { variants: ['tooltip', 'banner', 'modal'] as const, defaultVariant: 'tooltip',})Suivi automatique des impressions : Quand la variante sélectionnée change, useAdaptive() suit automatiquement un événement presage:impression avec l’ID d’adaptation, la variante et la stratégie.
Hook useVariant()
Section intitulée « Hook useVariant() »Un hook plus léger qui retourne uniquement la chaîne de la variante sélectionnée. Utilisez-le quand vous n’avez pas besoin des détails complets de résolution.
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>}Paramètres : Identiques à useAdaptive().
Type de retour : V — La chaîne de la variante sélectionnée.
Hook useAdaptiveClient()
Section intitulée « Hook useAdaptiveClient() »Retourne l’instance AdaptiveClient depuis le contexte. Utile pour les opérations impératives comme le suivi et l’identification.
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>}Type de retour : AdaptiveClient
Lance une erreur s’il est appelé en dehors de <AdaptiveProvider>.
Exemple complet : Tableau de bord SaaS
Section intitulée « Exemple complet : Tableau de bord SaaS »Cet exemple montre une barre latérale adaptative et un flux d’intégration pour un tableau de bord 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> )}