@presage-kit/svelte
Svelte bindings for Presage. Provides context helpers and reactive stores for adaptive UIs in Svelte 4 and 5.
pnpm add @presage-kit/core @presage-kit/sveltesetAdaptiveClient(client)
Sección titulada «setAdaptiveClient(client)»Sets the AdaptiveClient in Svelte’s context. Must be called in a root component (e.g. +layout.svelte).
<script> import { setAdaptiveClient } from '@presage-kit/svelte' import { createAdaptiveClient } from '@presage-kit/core'
const client = createAdaptiveClient({ /* ... */ }) setAdaptiveClient(client)</script>
<slot />Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
client | AdaptiveClient | Yes | Client from createAdaptiveClient() |
Implementation: Calls Svelte’s setContext() with a symbol key, making the client available to all descendant components.
getAdaptiveClient()
Sección titulada «getAdaptiveClient()»Returns the AdaptiveClient from Svelte’s context.
import { getAdaptiveClient } from '@presage-kit/svelte'
const client = getAdaptiveClient()
client.track('feature_used', { featureId: 'export' })client.identify('user-789', { role: 'admin' })const context = client.getContext()Return type: AdaptiveClient
Throws: Error if setAdaptiveClient() has not been called in a parent component.
useAdaptive(adaptationId, config)
Sección titulada «useAdaptive(adaptationId, config)»Resolves an adaptation point reactively. Returns Svelte Readable stores that update when user context changes.
import { useAdaptive } from '@presage-kit/svelte'
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:
| Field | Type | Description |
|---|---|---|
selectedVariant | Readable<V> | Currently selected variant |
resolution | Readable<ResolvedAdaptation> | Full resolution metadata |
context | Readable<UserContext> | Current user context |
track | (event: string, props?: Record<string, unknown>) => void | Scoped track function |
Reactivity: Uses derived() stores internally. When the client state changes, all stores update automatically. Use the $ prefix in templates to subscribe.
Impressions: Tracks presage:impression events automatically when the selected variant changes, using a derived() store that fires on each change.
Usage in templates:
<script lang="ts"> import { useAdaptive } from '@presage-kit/svelte'
const { selectedVariant } = useAdaptive('panel', { variants: ['compact', 'expanded'] as const, defaultVariant: 'compact', })</script>
{#if $selectedVariant === 'compact'} <CompactPanel />{:else} <ExpandedPanel />{/if}useVariant(adaptationId, config)
Sección titulada «useVariant(adaptationId, config)»Lightweight function returning only the selected variant as a readable store.
import { useVariant } from '@presage-kit/svelte'
const variant = useVariant('layout', { variants: ['sidebar', 'topnav'] as const, defaultVariant: 'sidebar',})Parameters: Same as useAdaptive().
Return type: Readable<V> — A store containing the selected variant string.
Internally delegates to useAdaptive() and returns selectedVariant.
Usage in templates:
<script lang="ts"> import { useVariant } from '@presage-kit/svelte'
const variant = useVariant('cta-style', { variants: ['primary', 'secondary'] as const, defaultVariant: 'primary', })</script>
<button class="btn btn--{$variant}">Get Started</button>useAdaptiveOrder(id, items)
Sección titulada «useAdaptiveOrder(id, items)»Generic adaptive ordering function for any list of items. Returns a Readable store that evaluates rules to reorder, hide, or preserve the original order.
import { useAdaptiveOrder } from '@presage-kit/svelte'
const features = [ { id: 'analytics', title: 'Analytics', description: 'Track user behavior' }, { id: 'automation', title: 'Automation', description: 'Automate repetitive tasks' },]
const orderedFeatures = useAdaptiveOrder('feature-highlights', features)Parameters:
| Param | Type | Description |
|---|---|---|
id | string | Adaptation point identifier |
items | T[] (extends Orderable) | Array of items, each with at least an id field |
Return type: Readable<T[]> — A store containing the ordered items. Returns an empty array when a hide action matches.
Orderable interface:
interface Orderable { id: string [key: string]: unknown}Reactivity: The store re-evaluates whenever the client state changes. Use the $ prefix in templates to subscribe.
Usage in templates:
<script lang="ts"> import { useAdaptiveOrder } from '@presage-kit/svelte'
const features = [ { id: 'analytics', title: 'Analytics', description: 'Track user behavior' }, { id: 'automation', title: 'Automation', description: 'Automate repetitive tasks' }, { id: 'integrations', title: 'Integrations', description: 'Connect your tools' }, ]
const orderedFeatures = useAdaptiveOrder('feature-highlights', features)</script>
<div class="feature-grid"> {#each $orderedFeatures as feature (feature.id)} <div class="card"> <h3>{feature.title}</h3> <p>{feature.description}</p> </div> {/each}</div>useAdaptiveNav(id, items)
Sección titulada «useAdaptiveNav(id, items)»A thin wrapper around useAdaptiveOrder(), specialized for navigation lists. Internally delegates all logic to useAdaptiveOrder().
Returns a Readable store of navigation items, automatically reordered or hidden by adaptation rules.
import { useAdaptiveNav } from '@presage-kit/svelte'
const items = [ { id: 'home', label: 'Home', href: '/' }, { id: 'analytics', label: 'Analytics', href: '/analytics' },]
const navItems = useAdaptiveNav('sidebar-nav', items)Parameters:
| Param | Type | Description |
|---|---|---|
id | string | Adaptation point identifier |
items | T[] (extends NavItem) | Array of items, each with at least an id field |
Return type: Readable<T[]> — A store containing the ordered items. Returns an empty array when a hide action matches.
NavItem interface:
interface NavItem { id: string [key: string]: unknown}Reactivity: The store re-evaluates whenever the client state changes. Use the $ prefix in templates to subscribe.
Usage in templates:
<script lang="ts"> import { useAdaptiveNav } from '@presage-kit/svelte'
const items = [ { id: 'home', label: 'Home', href: '/' }, { id: 'analytics', label: 'Analytics', href: '/analytics' }, { id: 'settings', label: 'Settings', href: '/settings' }, ]
const navItems = useAdaptiveNav('sidebar-nav', items)</script>
<nav> {#each $navItems as item (item.id)} <a href={item.href}>{item.label}</a> {/each}</nav>Differences from React and Vue Adapters
Sección titulada «Differences from React and Vue Adapters»| Feature | React | Vue | Svelte |
|---|---|---|---|
| Provider | <AdaptiveProvider> | AdaptivePlugin | setAdaptiveClient() |
| Declarative component | <Adaptive> + <Variant> | <Adaptive> + <Variant> | Not included (use {#if} with useAdaptive()) |
| Generic ordering | <AdaptiveOrder> component | <AdaptiveOrder> with scoped slots | useAdaptiveOrder() store |
| Adaptive navigation | <AdaptiveNav> (wraps <AdaptiveOrder>) | <AdaptiveNav> (wraps <AdaptiveOrder>) | useAdaptiveNav() (wraps useAdaptiveOrder()) |
| Return type | Plain object | Reactive getters | Readable stores |
| State bridge | useSyncExternalStore | ref + listen() | readable() + listen() |
| Subscribe syntax | Direct access | Direct access | $store prefix |
The Svelte adapter follows Svelte conventions. Svelte’s {#if} blocks and store subscriptions make it natural to conditionally render variants without wrapper components, while useAdaptiveNav() provides a store-based alternative to a dedicated component.