import { c as AnnouncementConfig, M as ModalOptions, S as SlideoutOptions, B as BannerOptions, T as ToastOptions, b as SpotlightOptions } from './announcement-CWko-5bT.cjs'; export { a as AnnouncementAction, A as AnnouncementMedia, d as BannerPosition, C as ChangelogEntry, e as SerializeFeedOptions, f as SlideoutPosition, g as ToastPosition } from './announcement-CWko-5bT.cjs'; import { b as AnnouncementState, D as DismissalReason, Q as QueueConfig, A as AnnouncementVariant, d as AnnouncementPriority, f as QueueItem, P as PriorityOrder, E as EngineAnnouncementConfig, I as IsScheduleActive } from './types-MpBl5-ej.cjs'; export { c as AnnouncementStorageAdapter, e as DEFAULT_QUEUE_CONFIG, S as StackBehavior } from './types-MpBl5-ej.cjs'; import { T as ToastAdapter } from './toast-adapter-DRX4OW9l.cjs'; import * as React$1 from 'react'; import * as react_jsx_runtime from 'react/jsx-runtime'; import { FrequencyRule } from '@tour-kit/core/engine'; export { matchesAudience, validateConditions } from '@tour-kit/core/engine'; export { AudienceCondition, AudienceProp, FrequencyRule, UILibrary, UILibraryProvider, cn, isSegmentAudience, useUILibrary } from '@tour-kit/core'; export { F as FORCE_SHOW_BYPASS, a as ForceShowBypassKey } from './reducer-CkKL7M9K.cjs'; import '@tour-kit/media'; import '@tour-kit/scheduling/engine'; /** * Return type for useAnnouncement hook */ interface UseAnnouncementReturn { /** Current state of the announcement */ state: AnnouncementState | undefined; /** Configuration of the announcement */ config: AnnouncementConfig | undefined; /** Whether the announcement is currently visible */ isVisible: boolean; /** Whether the announcement is active (being displayed) */ isActive: boolean; /** Whether the announcement has been dismissed */ isDismissed: boolean; /** Whether the announcement can be shown (respects frequency, schedule, etc.) */ canShow: boolean; /** Number of times the announcement has been viewed */ viewCount: number; /** Show the announcement */ show: () => void; /** * Force-show the announcement (admin/demo affordance). Bypasses frequency, * cooldown, viewCount, isDismissed, and audience gates. License soft-gate * is preserved — unlicensed renders still show the watermark. */ forceShow: () => void; /** Hide the announcement temporarily */ hide: () => void; /** Dismiss the announcement (marks as dismissed) */ dismiss: (reason?: DismissalReason) => void; /** Complete the announcement (primary action taken) */ complete: () => void; /** Reset the announcement (clear dismissed state) */ reset: () => void; } /** * Hook to interact with a single announcement * @param id - The announcement ID * @returns Announcement state and control methods */ declare function useAnnouncement(id: string): UseAnnouncementReturn; interface HeadlessModalRenderProps { /** Whether the modal is open */ open: boolean; /** The announcement state */ state: ReturnType['state']; /** The announcement config */ config: ReturnType['config']; /** Close the modal */ close: () => void; /** Dismiss the modal */ dismiss: (reason?: DismissalReason) => void; /** Complete the announcement */ complete: () => void; /** Props for the overlay element */ overlayProps: { onClick: () => void; 'aria-hidden': boolean; }; /** Props for the content element */ contentProps: { role: string; 'aria-modal': boolean; 'aria-labelledby': string; onKeyDown: (e: React$1.KeyboardEvent) => void; }; /** Modal options */ options: ModalOptions; } interface HeadlessModalProps { /** Announcement ID */ id: string; /** Whether the modal is open (controlled) */ open?: boolean; /** Callback when open state changes */ onOpenChange?: (open: boolean) => void; /** Modal options */ options?: ModalOptions; /** Render function */ children: (props: HeadlessModalRenderProps) => React$1.ReactNode; } declare function HeadlessModal({ id, open: openProp, onOpenChange, options, children, }: HeadlessModalProps): React$1.ReactNode; interface HeadlessSlideoutRenderProps { /** Whether the slideout is open */ open: boolean; /** The announcement state */ state: ReturnType['state']; /** The announcement config */ config: ReturnType['config']; /** Close the slideout */ close: () => void; /** Dismiss the slideout */ dismiss: (reason?: DismissalReason) => void; /** Complete the announcement */ complete: () => void; /** Props for the overlay element */ overlayProps: { onClick: () => void; 'aria-hidden': boolean; }; /** Props for the content element */ contentProps: { role: string; 'aria-modal': boolean; 'aria-labelledby': string; onKeyDown: (e: React$1.KeyboardEvent) => void; }; /** Slideout options */ options: SlideoutOptions; } interface HeadlessSlideoutProps { /** Announcement ID */ id: string; /** Whether the slideout is open (controlled) */ open?: boolean; /** Callback when open state changes */ onOpenChange?: (open: boolean) => void; /** Slideout options */ options?: SlideoutOptions; /** Render function */ children: (props: HeadlessSlideoutRenderProps) => React$1.ReactNode; } declare function HeadlessSlideout({ id, open: openProp, onOpenChange, options, children, }: HeadlessSlideoutProps): React$1.ReactNode; interface HeadlessBannerRenderProps { /** Whether the banner is visible */ open: boolean; /** The announcement state */ state: ReturnType['state']; /** The announcement config */ config: ReturnType['config']; /** Dismiss the banner */ dismiss: (reason?: DismissalReason) => void; /** Props for the banner element */ bannerProps: { role: string; 'data-state': string; }; /** Banner options */ options: BannerOptions; } interface HeadlessBannerProps { /** Announcement ID */ id: string; /** Whether the banner is visible (controlled) */ open?: boolean; /** Callback when visibility changes */ onOpenChange?: (open: boolean) => void; /** Banner options */ options?: BannerOptions; /** Render function */ children: (props: HeadlessBannerRenderProps) => React$1.ReactNode; } declare function HeadlessBanner({ id, open: openProp, onOpenChange, options, children, }: HeadlessBannerProps): React$1.ReactNode; interface HeadlessToastRenderProps { /** Whether the toast is visible */ open: boolean; /** The announcement state */ state: ReturnType['state']; /** The announcement config */ config: ReturnType['config']; /** Dismiss the toast */ dismiss: (reason?: DismissalReason) => void; /** Props for the toast element */ toastProps: { role: string; 'aria-live': 'polite' | 'assertive'; 'data-state': string; }; /** Auto-dismiss progress (0-100) */ progress: number; /** Toast options */ options: ToastOptions; } interface HeadlessToastProps { /** Announcement ID */ id: string; /** Whether the toast is visible (controlled) */ open?: boolean; /** Callback when visibility changes */ onOpenChange?: (open: boolean) => void; /** Toast options */ options?: ToastOptions; /** Render function */ children: (props: HeadlessToastRenderProps) => React$1.ReactNode; } declare function HeadlessToast({ id, open: openProp, onOpenChange, options, children, }: HeadlessToastProps): React$1.ReactNode; interface HeadlessSpotlightRenderProps { /** Whether the spotlight is visible */ open: boolean; /** The announcement state */ state: ReturnType['state']; /** The announcement config */ config: ReturnType['config']; /** Close the spotlight */ close: () => void; /** Dismiss the spotlight */ dismiss: (reason?: DismissalReason) => void; /** Complete the announcement */ complete: () => void; /** Target element */ targetElement: Element | null; /** Target element rect */ targetRect: DOMRect | null; /** Floating styles from @floating-ui */ floatingStyles: React$1.CSSProperties; /** Set floating element ref */ setFloating: (node: HTMLElement | null) => void; /** Props for the overlay element */ overlayProps: { onClick: () => void; 'aria-hidden': boolean; }; /** Props for the content element */ contentProps: { role: string; 'aria-labelledby': string; }; /** Spotlight options */ options: SpotlightOptions; } interface HeadlessSpotlightProps { /** Announcement ID */ id: string; /** Whether the spotlight is visible (controlled) */ open?: boolean; /** Callback when visibility changes */ onOpenChange?: (open: boolean) => void; /** Spotlight options */ options?: SpotlightOptions; /** Render function */ children: (props: HeadlessSpotlightRenderProps) => React$1.ReactNode; } declare function HeadlessSpotlight({ id, open: openProp, onOpenChange, options, children, }: HeadlessSpotlightProps): React$1.ReactNode; /** * Announcements context value */ interface AnnouncementsContextValue { /** All registered announcements */ announcements: Map; /** Currently active announcement (visible) */ activeAnnouncement: string | null; /** Queue of pending announcements */ queue: string[]; /** Queue configuration */ queueConfig: QueueConfig; /** Register an announcement */ register: (config: AnnouncementConfig) => void; /** Unregister an announcement */ unregister: (id: string) => void; /** Show an announcement */ show: (id: string) => void; /** * Force-show an announcement, bypassing every gate enumerated in * `FORCE_SHOW_BYPASS` (frequency, scheduler cooldown, viewCount, isDismissed, * audience). The `` wrapper is NOT bypassed — * unlicensed renders still show the license watermark/warning state. * * Used by admin previews and demo affordances. `viewCount` is still * incremented (so admins see real telemetry deltas) and analytics events * are stamped with `metadata.trigger="forced"` for downstream filtering. */ forceShow: (id: string) => void; /** Hide an announcement temporarily */ hide: (id: string) => void; /** Dismiss an announcement (marks as dismissed) */ dismiss: (id: string, reason?: DismissalReason) => void; /** Complete an announcement (primary action taken) */ complete: (id: string) => void; /** Reset a dismissed announcement */ reset: (id: string) => void; /** Reset all dismissed announcements */ resetAll: () => void; /** Get announcement state by ID */ getState: (id: string) => AnnouncementState | undefined; /** Get announcement config by ID */ getConfig: (id: string) => AnnouncementConfig | undefined; /** Check if an announcement can be shown (respects frequency, schedule, etc.) */ canShow: (id: string) => boolean; /** Force show next announcement in queue */ showNext: () => void; /** Clear the queue */ clearQueue: () => void; /** * Optional toast adapter routing `variant="toast"` announcements through an * external transport (Sonner, react-hot-toast, …). When `null`, the built-in * `` portal renders. See `@tour-kit/announcements/adapters/sonner`. */ toastAdapter: ToastAdapter | null; } /** * Provider props */ interface AnnouncementsProviderProps { /** Child components */ children: React.ReactNode; /** Initial announcements to register */ announcements?: AnnouncementConfig[]; /** Queue configuration */ queueConfig?: Partial; /** Storage adapter for persistence */ storage?: Storage | null; /** Storage key prefix */ storageKey?: string; /** User context for audience targeting */ userContext?: Record; /** Callback when any announcement is shown */ onAnnouncementShow?: (id: string) => void; /** Callback when any announcement is dismissed */ onAnnouncementDismiss?: (id: string, reason: DismissalReason) => void; /** Callback when any announcement is completed */ onAnnouncementComplete?: (id: string) => void; /** * Optional toast adapter routing `variant="toast"` announcements through an * external transport (Sonner, react-hot-toast, …). The adapter is invoked * inside `` via context — when `render` returns a non-null * handle, the built-in portal toast is suppressed; when it returns `null` * (e.g., sonner isn't installed), the portal renders as before. * * @example * ```tsx * import { sonnerAdapter } from '@tour-kit/announcements/adapters/sonner' * {children} * ``` */ toastAdapter?: ToastAdapter; } /** * Announcements context */ declare const AnnouncementsContext: React$1.Context; /** * Hook to access the announcements context * @throws Error if used outside of AnnouncementsProvider */ declare function useAnnouncementsContext(): AnnouncementsContextValue; declare function AnnouncementsProvider({ children, announcements: initialAnnouncements, queueConfig: queueConfigOverrides, storage, storageKey, userContext, onAnnouncementShow, onAnnouncementDismiss, onAnnouncementComplete, toastAdapter, }: AnnouncementsProviderProps): react_jsx_runtime.JSX.Element; /** * Filter options for announcements */ interface AnnouncementsFilter { /** Filter by variant type */ variant?: AnnouncementVariant | AnnouncementVariant[]; /** Filter by dismissed state */ isDismissed?: boolean; /** Filter by active state */ isActive?: boolean; /** Filter by visibility */ isVisible?: boolean; /** Custom filter function */ filter?: (state: AnnouncementState, config: AnnouncementConfig) => boolean; } /** * Return type for useAnnouncements hook */ interface UseAnnouncementsReturn { /** All announcement states */ announcements: Map; /** Currently active announcement ID */ activeId: string | null; /** Get all announcement IDs */ ids: string[]; /** Get announcements by filter */ getFiltered: (filter: AnnouncementsFilter) => AnnouncementState[]; /** Get visible announcements */ visible: AnnouncementState[]; /** Get dismissed announcements */ dismissed: AnnouncementState[]; /** Get count of announcements */ count: number; /** Reset all announcements */ resetAll: () => void; } /** * Hook to access all announcements * @returns All announcements state and query methods */ declare function useAnnouncements(): UseAnnouncementsReturn; /** * Return type for useAnnouncementQueue hook */ interface UseAnnouncementQueueReturn { /** IDs of announcements in the queue */ queue: string[]; /** Number of announcements in the queue */ size: number; /** Whether the queue is empty */ isEmpty: boolean; /** Current queue configuration */ config: QueueConfig; /** Show the next announcement in the queue */ showNext: () => void; /** Clear all announcements from the queue */ clear: () => void; /** Check if a specific announcement is in the queue */ isQueued: (id: string) => boolean; /** Get position of an announcement in the queue (-1 if not queued) */ getPosition: (id: string) => number; } /** * Hook to interact with the announcement queue * @returns Queue state and control methods */ declare function useAnnouncementQueue(): UseAnnouncementQueueReturn; /** * Priority queue implementation for announcement ordering */ declare class PriorityQueue { private items; private config; private sequenceCounter; constructor(config: QueueConfig); /** * Add an item to the queue */ enqueue(id: string, priority: AnnouncementPriority): void; /** * Remove and return the highest priority item */ dequeue(): QueueItem | undefined; /** * Peek at the highest priority item without removing */ peek(): QueueItem | undefined; /** * Remove a specific item by ID */ remove(id: string): boolean; /** * Check if an item is in the queue */ has(id: string): boolean; /** * Get position of an item in the queue (0-indexed) */ getPosition(id: string): number; /** * Get all item IDs in order */ getIds(): string[]; /** * Get queue size */ get size(): number; /** * Check if queue is empty */ get isEmpty(): boolean; /** * Clear the queue */ clear(): void; /** * Update configuration and re-sort */ updateConfig(config: QueueConfig): void; /** * Sort items based on priority order */ private sort; } /** * Create a comparator function for a given priority order */ declare function createComparator(order: PriorityOrder, weights: Record): (a: QueueItem, b: QueueItem) => number; /** * Comparator for announcements at the provider boundary. * * Phase 3 (refactor train) — replaces the inline `priorityOrder` literal in * `` that duplicated `QueueConfig.priorityWeights` and * ignored the `priorityOrder: 'priority' | 'fifo' | 'lifo'` setting. * * Works on a lightweight pick of `AnnouncementConfig` because the provider * doesn't have `QueueItem`s yet — they're only minted when the scheduler * enqueues. The `sequenceById` map carries the original insertion order from * the filtered announcements list so `fifo` / `lifo` can break ties * deterministically. */ declare function createAnnouncementComparator(order: PriorityOrder, weights: Record, sequenceById: ReadonlyMap): (a: Pick, b: Pick) => number; /** * Announcement scheduler manages the queue and determines when announcements should show */ declare class AnnouncementScheduler { private queue; private config; private activeCount; /** Injected optional-peer loader; `undefined` keeps the default require path. */ private loadScheduling; /** * `isScheduleActive` is the optional `@tour-kit/scheduling` peer, injected * (v3 Phase 3, plan Decision 7b). It is a SECOND, optional argument so every * existing caller and the existing scheduler suites are untouched. * * Left undefined, `resolveScheduleActive` falls back to its call-time * `require('@tour-kit/scheduling')` — which degrades OPEN whenever `require` * is absent, i.e. in every ESM build. An ESM consumer of `/engine` passes * `isScheduleActive` from `@tour-kit/scheduling/engine` to get real gating. */ constructor(config: QueueConfig, isScheduleActive?: IsScheduleActive); /** * Check if an announcement can be shown */ canShow(config: EngineAnnouncementConfig, state: AnnouncementState, userContext?: Record, now?: Date): boolean; /** * Try to queue an announcement * Returns true if queued, false if should show immediately or can't show */ shouldQueue(config: EngineAnnouncementConfig, state: AnnouncementState, userContext?: Record): boolean; /** * Add an announcement to the queue */ enqueue(config: EngineAnnouncementConfig): number; /** * Get the next announcement to show */ getNext(): string | undefined; /** * Peek at the next announcement without removing */ peekNext(): string | undefined; /** * Remove an announcement from the queue */ remove(id: string): boolean; /** * Check if an announcement is queued */ isQueued(id: string): boolean; /** * Get queue position for an announcement (0-indexed, -1 if not queued) */ getQueuePosition(id: string): number; /** * Get all queued announcement IDs in order */ getQueuedIds(): string[]; /** * Get queue size */ get queueSize(): number; /** * Check if more announcements can be shown */ canShowMore(): boolean; /** * Mark an announcement as active (being shown) */ markActive(): void; /** * Mark an announcement as inactive (hidden/dismissed) */ markInactive(): void; /** * Get current active count */ get currentActiveCount(): number; /** * Clear the queue */ clearQueue(): void; /** * Reset active count */ resetActive(): void; /** * Update configuration */ updateConfig(config: QueueConfig): void; /** * Get delay between announcements */ get delayBetween(): number; /** * Check if auto-show is enabled */ get autoShow(): boolean; /** * Read-only view of the active queue configuration. * * Phase 3 (refactor train) — exposed so callers (notably the provider's * auto-show effect) can drive ordering from `priorityWeights` / * `priorityOrder` without reaching into the private `config` field. */ get queueConfig(): Readonly; } /** * Phase 3a lifted these helpers to `@tour-kit/core`. This module keeps the * named exports intact so existing imports (`import { canShowByFrequency } * from '@tour-kit/announcements'` via the package barrel) keep resolving. * Bodies are thin shims that delegate to core — `AnnouncementState` already * satisfies `FrequencyState` (`viewCount`, `isDismissed`, `lastViewedAt`). * * @deprecated Prefer `import { canShowByFrequency } from '@tour-kit/core'` in * new code. Re-exports here remain through 1.x. */ declare function canShowByFrequency(state: AnnouncementState, rule: FrequencyRule | undefined): boolean; declare function canShowAfterDismissal(rule: FrequencyRule | undefined): boolean; declare function getViewLimit(rule: FrequencyRule | undefined): number; /** * Announcement analytics event types */ type AnnouncementEventType = 'announcement_registered' | 'announcement_shown' | 'announcement_dismissed' | 'announcement_completed' | 'announcement_action_clicked' | 'announcement_queued' | 'announcement_dequeued'; /** * Base announcement event */ interface BaseAnnouncementEvent { type: AnnouncementEventType; announcementId: string; variant: AnnouncementVariant; timestamp: number; metadata?: Record; } /** * Announcement registered event */ interface AnnouncementRegisteredEvent extends BaseAnnouncementEvent { type: 'announcement_registered'; } /** * Announcement shown event */ interface AnnouncementShownEvent extends BaseAnnouncementEvent { type: 'announcement_shown'; viewCount: number; fromQueue: boolean; } /** * Announcement dismissed event */ interface AnnouncementDismissedEvent extends BaseAnnouncementEvent { type: 'announcement_dismissed'; reason: DismissalReason; viewDuration: number; } /** * Announcement completed event */ interface AnnouncementCompletedEvent extends BaseAnnouncementEvent { type: 'announcement_completed'; viewDuration: number; } /** * Announcement action clicked event */ interface AnnouncementActionClickedEvent extends BaseAnnouncementEvent { type: 'announcement_action_clicked'; actionType: 'primary' | 'secondary'; actionLabel: string; } /** * Announcement queued event */ interface AnnouncementQueuedEvent extends BaseAnnouncementEvent { type: 'announcement_queued'; queuePosition: number; } /** * Announcement dequeued event */ interface AnnouncementDequeuedEvent extends BaseAnnouncementEvent { type: 'announcement_dequeued'; reason: 'shown' | 'expired' | 'removed'; } /** * Union of all announcement events */ type AnnouncementEvent = AnnouncementRegisteredEvent | AnnouncementShownEvent | AnnouncementDismissedEvent | AnnouncementCompletedEvent | AnnouncementActionClickedEvent | AnnouncementQueuedEvent | AnnouncementDequeuedEvent; export { type AnnouncementActionClickedEvent, type AnnouncementCompletedEvent, AnnouncementConfig, type AnnouncementDequeuedEvent, type AnnouncementDismissedEvent, type AnnouncementEvent, type AnnouncementEventType, AnnouncementPriority, type AnnouncementQueuedEvent, type AnnouncementRegisteredEvent, AnnouncementScheduler, type AnnouncementShownEvent, AnnouncementState, AnnouncementVariant, AnnouncementsContext, type AnnouncementsContextValue, type AnnouncementsFilter, AnnouncementsProvider, type AnnouncementsProviderProps, BannerOptions, type BaseAnnouncementEvent, DismissalReason, HeadlessBanner, type HeadlessBannerProps, type HeadlessBannerRenderProps, HeadlessModal, type HeadlessModalProps, type HeadlessModalRenderProps, HeadlessSlideout, type HeadlessSlideoutProps, type HeadlessSlideoutRenderProps, HeadlessSpotlight, type HeadlessSpotlightProps, type HeadlessSpotlightRenderProps, HeadlessToast, type HeadlessToastProps, type HeadlessToastRenderProps, ModalOptions, PriorityOrder, PriorityQueue, QueueConfig, QueueItem, SlideoutOptions, SpotlightOptions, ToastOptions, type UseAnnouncementQueueReturn, type UseAnnouncementReturn, type UseAnnouncementsReturn, canShowAfterDismissal, canShowByFrequency, createAnnouncementComparator, createComparator, getViewLimit, useAnnouncement, useAnnouncementQueue, useAnnouncements, useAnnouncementsContext };