@presage-kit/vue
Vue 3 bindings for Presage. Provides a plugin for dependency injection and composables for reactive adaptation.
pnpm add @presage-kit/core @presage-kit/vueAdaptivePlugin
Section intitulée « AdaptivePlugin »A Vue 3 plugin that provides the AdaptiveClient to all components via provide/inject.
import { createApp } from 'vue'import { AdaptivePlugin } from '@presage-kit/vue'import { createAdaptiveClient } from '@presage-kit/core'
const client = createAdaptiveClient({ /* ... */ })
const app = createApp(App)app.use(AdaptivePlugin, { client })app.mount('#app')Install options: AdaptivePluginOptions
interface AdaptivePluginOptions { client: AdaptiveClient}| Option | Type | Required | Description |
|---|---|---|---|
client | AdaptiveClient | Yes | Client from createAdaptiveClient() |
Implementation: Calls app.provide() with an injection key symbol, making the client available to all descendant components.
useAdaptive(adaptationId, config)
Section intitulée « useAdaptive(adaptationId, config) »Resolves an adaptation point reactively. Re-evaluates when user context changes.
import { useAdaptive } from '@presage-kit/vue'
const { selectedVariant, resolution, context, track } = useAdaptive('onboarding', { variants: ['guided-tour', 'standard', 'minimal'] as const, defaultVariant: 'standard',})Parameters:
| Param | Type | Description |
|---|---|---|
adaptationId | string | Unique adaptation point ID |
config.variants | readonly V[] | Array of variant IDs |
config.defaultVariant | NoInfer<V> | Default variant (must be in variants) |
config.strategy | Strategy | Optional. Defaults to { type: 'rules' } |
Return type:
The returned object uses JavaScript getters backed by Vue computed() refs, making all values reactive.
| Field | Type | Description |
|---|---|---|
selectedVariant | V (getter) | Currently selected variant |
resolution | ResolvedAdaptation (getter) | Full resolution metadata |
context | UserContext (getter) | Current user context |
track | (event: string, props?: Record<string, unknown>) => void | Scoped track function |
Reactivity: The composable uses useAtom() internally to bridge the core’s atom-based state to Vue’s reactivity system. When the client state changes, all computed values update automatically.
Impressions: Uses Vue’s watch() with { immediate: true } to track presage:impression events when the selected variant changes.
Usage in templates:
<script setup lang="ts">import { useAdaptive } from '@presage-kit/vue'
const { selectedVariant } = useAdaptive('panel', { variants: ['compact', 'expanded'] as const, defaultVariant: 'compact',})</script>
<template> <CompactPanel v-if="selectedVariant === 'compact'" /> <ExpandedPanel v-else /></template>useVariant(adaptationId, config)
Section intitulée « useVariant(adaptationId, config) »Lightweight composable returning only the selected variant string.
import { useVariant } from '@presage-kit/vue'
const variant = useVariant('layout', { variants: ['sidebar', 'topnav'] as const, defaultVariant: 'sidebar',})Parameters: Same as useAdaptive().
Return type: V — The selected variant string (reactive getter).
Internally delegates to useAdaptive() and returns selectedVariant.
Usage in templates:
<script setup lang="ts">import { useVariant } from '@presage-kit/vue'
const variant = useVariant('cta-style', { variants: ['primary', 'secondary'] as const, defaultVariant: 'primary',})</script>
<template> <button :class="`btn btn--${variant}`">Get Started</button></template>useAdaptiveClient()
Section intitulée « useAdaptiveClient() »Returns the AdaptiveClient instance from the plugin injection.
import { useAdaptiveClient } from '@presage-kit/vue'
const client = useAdaptiveClient()
client.track('feature_used', { featureId: 'export' })client.identify('user-789', { role: 'admin' })const context = client.getContext()Return type: AdaptiveClient
Throws: Error if AdaptivePlugin has not been installed.
Common patterns:
<script setup lang="ts">import { useAdaptiveClient } from '@presage-kit/vue'
const client = useAdaptiveClient()
// Identify after authenticationonMounted(() => { const user = getCurrentUser() client.identify(user.id, { role: user.role, plan: user.plan, signupDate: user.createdAt, })})
// Track actionsfunction handleExport() { client.track('feature_used', { featureId: 'export' }) doExport()}
// Evaluate rules imperativelyfunction getNavAction() { return client.evaluateAction('sidebar-nav')}</script><Adaptive> Component
Section intitulée « <Adaptive> Component »Declares an adaptation point and renders the matching <Variant> child. Built with defineComponent.
<script setup lang="ts">import { Adaptive, Variant } from '@presage-kit/vue'</script>
<template> <Adaptive id="onboarding" default-variant="standard"> <Variant id="guided-tour"> <GuidedTour /> </Variant> <Variant id="standard"> <StandardOnboarding /> </Variant> </Adaptive></template>Props:
| Prop | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique adaptation point identifier |
default-variant | string | Yes | Variant to show when no rule matches |
Behavior: Internally calls useAdaptive() with the variant IDs collected from child <Variant> components. Automatically tracks presage:impression events when the selected variant changes.
<Variant> Component
Section intitulée « <Variant> Component »Defines a single variant inside an <Adaptive> parent.
Props:
| Prop | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Variant identifier (referenced in rule actions) |
Only the matching variant’s slot content is rendered.
<AdaptiveOrder> Component
Section intitulée « <AdaptiveOrder> Component »Generic adaptive ordering component for any list of items. Evaluates rules to reorder, hide, or preserve the original order. Uses Vue scoped slots for rendering.
<script setup lang="ts">import { AdaptiveOrder } from '@presage-kit/vue'
const features = [ { id: 'analytics', title: 'Analytics', description: 'Track user behavior' }, { id: 'automation', title: 'Automation', description: 'Automate repetitive tasks' },]</script>
<template> <AdaptiveOrder id="feature-highlights" :items="features" v-slot="{ item, index }"> <div class="card">{{ item.title }}: {{ item.description }}</div> </AdaptiveOrder></template>Props:
| Prop | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Adaptation point identifier |
items | T[] (extends Orderable) | Yes | Array of items, each with at least an id field |
Scoped slot:
| Field | Type | Description |
|---|---|---|
item | T | The current item |
index | number | The current item index in the ordered list |
Orderable interface:
interface Orderable { id: string [key: string]: unknown}Behavior: Evaluates reorder and hide actions from the rule engine. When hidden, renders nothing. When reordered, items are rendered in the new order. Items not mentioned in the order array are appended at the end.
<AdaptiveNav> Component
Section intitulée « <AdaptiveNav> Component »A thin wrapper around <AdaptiveOrder>, specialized for navigation items. Internally delegates all logic to <AdaptiveOrder>.
Renders navigation items that can be reordered or hidden by adaptation rules. Uses Vue scoped slots for rendering.
<script setup lang="ts">import { AdaptiveNav } from '@presage-kit/vue'
const items = [ { id: 'home', label: 'Home', href: '/' }, { id: 'analytics', label: 'Analytics', href: '/analytics' },]</script>
<template> <AdaptiveNav id="sidebar-nav" :items="items" v-slot="{ item }"> <a :href="item.href">{{ item.label }}</a> </AdaptiveNav></template>Props:
| Prop | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Adaptation point identifier |
items | T[] (extends NavItem) | Yes | Array of items, each with at least an id field |
Scoped slot:
| Field | Type | Description |
|---|---|---|
item | T | The current navigation item |
NavItem interface:
interface NavItem { id: string [key: string]: unknown}Behavior: Evaluates reorder and hide actions from the rule engine. When hidden, renders nothing. When reordered, items are rendered in the new order.
Differences from React Adapter
Section intitulée « Differences from React Adapter »| Feature | React | Vue |
|---|---|---|
| Provider | <AdaptiveProvider> component | AdaptivePlugin (Vue plugin) |
| Declarative component | <Adaptive> + <Variant> | <Adaptive> + <Variant> (defineComponent-based) |
| Generic ordering | <AdaptiveOrder> with renderItem prop | <AdaptiveOrder> with scoped slots |
| Adaptive navigation | <AdaptiveNav> (wraps <AdaptiveOrder>) | <AdaptiveNav> (wraps <AdaptiveOrder>) |
| Hook/composable return | Plain object | Object with reactive getters |
| State bridge | useSyncExternalStore-style | ref + atom subscribe() |