Aller au contenu

@presage-kit/react

React bindings for Presage. Provides a context provider, declarative components, and hooks.

Fenêtre de terminal
pnpm add @presage-kit/core @presage-kit/react

Provides the AdaptiveClient to descendant components via React context.

import { AdaptiveProvider } from '@presage-kit/react'
<AdaptiveProvider client={client}>
<App />
</AdaptiveProvider>

Props:

PropTypeRequiredDescription
clientAdaptiveClientYesClient from createAdaptiveClient()
childrenReactNodeYesComponent tree

Declares an adaptation point. Evaluates rules and renders the matching <Variant> child.

import { Adaptive, Variant } from '@presage-kit/react'
<Adaptive id="onboarding" defaultVariant="standard">
<Variant id="guided-tour"><GuidedTour /></Variant>
<Variant id="standard"><StandardView /></Variant>
</Adaptive>

Props:

PropTypeRequiredDescription
idstringYesAdaptation point identifier
defaultVariantstringYesFallback variant ID
childrenReactNodeYesMust contain <Variant> elements

Behavior:

  • Extracts <Variant> children and their IDs
  • Calls useAdaptive() internally with the extracted variant list
  • Renders the content of the matching <Variant>
  • Returns null if no variant matches (shouldn’t happen with defaultVariant)

Declares a variant within an <Adaptive> block. Does not render anything on its own — <Adaptive> controls which variant is visible.

<Variant id="guided-tour">
<GuidedTour />
</Variant>

Props:

PropTypeRequiredDescription
idstringYesVariant identifier (referenced in rule actions)
childrenReactNodeYesContent to render when selected

Generic adaptive ordering component for any list of items. Evaluates rules to reorder, hide, or preserve the original order.

import { AdaptiveOrder, type Orderable } from '@presage-kit/react'
<AdaptiveOrder<FeatureCard>
id="feature-highlights"
items={features}
renderItem={(item, index) => <Card key={item.id} item={item} />}
/>

Props:

PropTypeRequiredDescription
idstringYesAdaptation point identifier
itemsT[]YesArray of items extending Orderable
renderItem(item: T, index: number) => ReactNodeYesRender function per item

Orderable interface:

interface Orderable {
id: string
[key: string]: unknown
}

Action handling:

  • { type: 'reorder', order: [...] } — Reorders items to match the order array. Items not in the array are appended at the end.
  • { type: 'hide' } — Returns null (hides the entire list).
  • Other actions or no match — Renders items in their original order.

Generics: AdaptiveOrder is generic over the item type:

interface FeatureCard extends Orderable {
title: string
description: string
}
<AdaptiveOrder<FeatureCard>
id="feature-highlights"
items={features}
renderItem={(item) => (
<div className="card">{item.title}: {item.description}</div>
)}
/>

A thin wrapper around <AdaptiveOrder>, specialized for navigation items. Internally delegates all logic to <AdaptiveOrder>.

Renders navigation items with adaptive reordering.

import { AdaptiveNav, type NavItem } from '@presage-kit/react'
<AdaptiveNav<MenuItem>
id="sidebar"
items={menuItems}
renderItem={(item, index) => <NavLink key={item.id} item={item} />}
/>

Props:

PropTypeRequiredDescription
idstringYesAdaptation point identifier
itemsT[]YesArray of items extending NavItem
renderItem(item: T, index: number) => ReactNodeYesRender function per item

NavItem interface:

interface NavItem {
id: string
[key: string]: unknown
}

Action handling:

  • { type: 'reorder', order: [...] } — Reorders items to match the order array. Items not in the array are appended at the end.
  • { type: 'hide' } — Returns null (hides the entire navigation).
  • Other actions or no match — Renders items in their original order.

Generics: AdaptiveNav is generic over the item type:

interface MenuItem extends NavItem {
label: string
href: string
icon: React.ReactNode
}
<AdaptiveNav<MenuItem>
id="sidebar"
items={menuItems}
renderItem={(item) => (
<a href={item.href}>{item.icon} {item.label}</a>
)}
/>

Resolves an adaptation point and tracks impressions.

import { useAdaptive } from '@presage-kit/react'
const { selectedVariant, resolution, context, track } = useAdaptive('feature-panel', {
variants: ['compact', 'expanded', 'hidden'] as const,
defaultVariant: 'compact',
})

Parameters:

ParamTypeDescription
adaptationIdstringUnique adaptation point ID
config.variantsreadonly V[]Array of variant IDs
config.defaultVariantNoInfer<V>Default variant (must be in variants)
config.strategyStrategyOptional. Defaults to { type: 'rules' }

Return type: UseAdaptiveResult<V>

FieldTypeDescription
selectedVariantVCurrently selected variant
resolutionResolvedAdaptationFull resolution metadata
contextUserContextCurrent user context
track(event: string, props?: Record<string, unknown>) => voidTrack function that auto-attaches _adaptationId

Impressions: Automatically tracks presage:impression when selectedVariant changes, with properties:

{
adaptationId: string
variant: string
strategy: string
}

TypeScript: Uses NoInfer<V> to prevent defaultVariant from widening the type. Use as const on the variants array for best type inference:

const { selectedVariant } = useAdaptive('x', {
variants: ['a', 'b', 'c'] as const,
defaultVariant: 'a',
})
// selectedVariant: 'a' | 'b' | 'c'

Lightweight hook returning only the selected variant string.

import { useVariant } from '@presage-kit/react'
const variant = useVariant('layout', {
variants: ['sidebar', 'topnav'] as const,
defaultVariant: 'sidebar',
})
// variant: 'sidebar' | 'topnav'

Parameters: Same as useAdaptive().

Return type: V — The selected variant string.

Internally delegates to useAdaptive() and destructures selectedVariant.

Returns the AdaptiveClient from context.

import { useAdaptiveClient } from '@presage-kit/react'
const client = useAdaptiveClient()
client.track('button_clicked', { buttonId: 'cta' })
client.identify('user-456', { role: 'editor' })
const ctx = client.getContext()

Return type: AdaptiveClient

Throws: Error if called outside <AdaptiveProvider>.