@thelol3882/sapar 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +380 -2
  3. package/dist/adapter-Y9yB3-q3.d.ts +14 -0
  4. package/dist/adapter-fFZPsINL.d.ts +14 -0
  5. package/dist/chunk-7B66QEMY.js +536 -0
  6. package/dist/chunk-7B66QEMY.js.map +1 -0
  7. package/dist/chunk-FM64UDKJ.js +893 -0
  8. package/dist/chunk-FM64UDKJ.js.map +1 -0
  9. package/dist/chunk-VC6XLWM3.js +176 -0
  10. package/dist/chunk-VC6XLWM3.js.map +1 -0
  11. package/dist/chunk-ZBVQGMR4.js +583 -0
  12. package/dist/chunk-ZBVQGMR4.js.map +1 -0
  13. package/dist/cli/index.js +1335 -0
  14. package/dist/core/index.d.ts +273 -0
  15. package/dist/core/index.js +71 -0
  16. package/dist/core/index.js.map +1 -0
  17. package/dist/expo/index.d.ts +189 -0
  18. package/dist/expo/index.js +39 -0
  19. package/dist/expo/index.js.map +1 -0
  20. package/dist/expo-router/index.d.ts +18 -0
  21. package/dist/expo-router/index.js +46 -0
  22. package/dist/expo-router/index.js.map +1 -0
  23. package/dist/next/index.d.ts +18 -0
  24. package/dist/next/index.js +49 -0
  25. package/dist/next/index.js.map +1 -0
  26. package/dist/presentation-CClsPRT6.d.ts +12 -0
  27. package/dist/react/index.d.ts +35 -0
  28. package/dist/react/index.js +29 -0
  29. package/dist/react/index.js.map +1 -0
  30. package/dist/rtk/index.d.ts +751 -0
  31. package/dist/rtk/index.js +114 -0
  32. package/dist/rtk/index.js.map +1 -0
  33. package/dist/stepCount-CTYYFWiV.d.ts +57 -0
  34. package/dist/types-CHD2pB5X.d.ts +192 -0
  35. package/dist/web/index.d.ts +112 -0
  36. package/dist/web/index.js +34 -0
  37. package/dist/web/index.js.map +1 -0
  38. package/package.json +147 -3
  39. package/templates/expo/AnnouncementModal.tsx +102 -0
  40. package/templates/expo/TourCard.tsx +112 -0
  41. package/templates/expo/WhatsNewButton.tsx +87 -0
  42. package/templates/expo/WhatsNewPanel.tsx +167 -0
  43. package/templates/mantine/AnnouncementModal.tsx +66 -0
  44. package/templates/mantine/TourCard.tsx +84 -0
  45. package/templates/mantine/WhatsNewButton.tsx +62 -0
  46. package/templates/mantine/WhatsNewPanel.tsx +129 -0
  47. package/templates/tailwind/AnnouncementModal.tsx +100 -0
  48. package/templates/tailwind/TourCard.tsx +69 -0
  49. package/templates/tailwind/WhatsNewButton.tsx +56 -0
  50. package/templates/tailwind/WhatsNewPanel.tsx +174 -0
@@ -0,0 +1,273 @@
1
+ import { S as SaparControllerOptions, a as SaparController, R as RunnerSnapshot, T as Tour, P as ProgressInput, b as PlatformAdapter, A as AnnouncementTier, L as LocalizedText, c as TourTrigger, d as Placement, e as Platform, f as Announcement, I as InterruptionPolicy, g as TourStatus, h as Interruption, K as KeyValueStore, i as SaparSource, j as Inbox, k as AnchorHandle, l as AnchorRect } from '../types-CHD2pB5X.js';
2
+ export { m as InboxStatus, n as RunnerPhase, o as SaparSnapshot, p as SessionStore, q as TourStep } from '../types-CHD2pB5X.js';
3
+ export { P as Presentation, a as PresentationInput, r as resolvePresentation } from '../presentation-CClsPRT6.js';
4
+
5
+ declare function createSaparController(options: SaparControllerOptions): SaparController;
6
+
7
+ interface TourMachineEvents {
8
+ onProgress(input: ProgressInput): void;
9
+ onError(error: unknown, context: string): void;
10
+ }
11
+ interface TourMachineOptions {
12
+ anchorTimeoutMs?: number;
13
+ presentAnchorTimeoutMs?: number;
14
+ locales?: readonly string[];
15
+ }
16
+ interface TourMachine {
17
+ subscribe(listener: () => void): () => void;
18
+ /** Referentially stable until the state changes. */
19
+ getSnapshot(): RunnerSnapshot;
20
+ start(tour: Tour, options: {
21
+ autoStarted: boolean;
22
+ }): Promise<void>;
23
+ next(): Promise<void>;
24
+ previous(): Promise<void>;
25
+ skip(): void;
26
+ finish(): void;
27
+ /** Every method is a no-op afterwards. */
28
+ destroy(): void;
29
+ }
30
+ declare function createTourMachine(adapter: PlatformAdapter, events: TourMachineEvents, options?: TourMachineOptions): TourMachine;
31
+
32
+ declare const DEFAULT_ANCHOR_TIMEOUT_MS = 3000;
33
+ declare const DEFAULT_PRESENT_ANCHOR_TIMEOUT_MS = 300;
34
+ declare const DEFAULT_AUTO_START_TIMEOUT_MS = 10000;
35
+
36
+ declare const SESSION_CAP_KEY = "sapar.session-interruption-spent";
37
+ declare function hasSpentSessionInterruption(adapter: PlatformAdapter): boolean;
38
+ declare function spendSessionInterruption(adapter: PlatformAdapter): void;
39
+
40
+ declare function normalizeRoute(route: string | null | undefined, locales: readonly string[]): string;
41
+ declare function routeMatches(pattern: string, route: string, locales: readonly string[]): boolean;
42
+ declare function isValidRoutePattern(pattern: string): boolean;
43
+
44
+ interface StepDefinition {
45
+ key: string;
46
+ anchor?: string;
47
+ route?: string;
48
+ title: LocalizedText;
49
+ body: LocalizedText;
50
+ placement: Placement;
51
+ padding: number;
52
+ required: boolean;
53
+ advanceOn: 'next' | 'press';
54
+ }
55
+ interface TourDefinition {
56
+ key: string;
57
+ revision: number;
58
+ title: LocalizedText;
59
+ trigger: TourTrigger;
60
+ steps: StepDefinition[];
61
+ /** Platforms the tour is offered on. Absent means all. */
62
+ platforms?: Platform[];
63
+ }
64
+ interface AnnouncementDefinition {
65
+ key: string;
66
+ tier: AnnouncementTier;
67
+ title: LocalizedText;
68
+ body: LocalizedText;
69
+ imageUrl?: string;
70
+ cta?: {
71
+ label: LocalizedText;
72
+ url: string;
73
+ };
74
+ /** ISO 8601. */
75
+ publishedAt: string;
76
+ tourKey?: string;
77
+ }
78
+ type StepInput = Pick<StepDefinition, 'key' | 'title' | 'body'> & Partial<StepDefinition>;
79
+ type TourInput = Pick<TourDefinition, 'key' | 'title'> & Partial<Omit<TourDefinition, 'steps'>> & {
80
+ steps: StepInput[];
81
+ };
82
+ type AnnouncementInput = Pick<AnnouncementDefinition, 'key' | 'title' | 'body' | 'publishedAt'> & Partial<AnnouncementDefinition>;
83
+ interface TextLocale {
84
+ locale: string;
85
+ fallbackLocale: string;
86
+ }
87
+ /** Grammar for tour, step, announcement and anchor keys. Shared with the backend and the CLI. */
88
+ declare const KEY_PATTERN: RegExp;
89
+ declare function defineTour(input: TourInput): TourDefinition;
90
+ declare function defineAnnouncement(input: AnnouncementInput): AnnouncementDefinition;
91
+ declare function defineAnchors<const Keys extends readonly string[]>(keys: Keys): Keys;
92
+ type AnchorKey<Anchors extends readonly string[]> = Anchors[number];
93
+ declare function resolveText(text: LocalizedText, locale: string, fallbackLocale: string): string;
94
+ declare function resolveTour(tour: TourDefinition, textLocale: TextLocale): Tour;
95
+ declare function resolveAnnouncement(announcement: AnnouncementDefinition, { locale, fallbackLocale }: TextLocale, unread: boolean): Announcement;
96
+
97
+ declare const DEFAULT_POLICY: InterruptionPolicy;
98
+ interface TourRecord {
99
+ status: TourStatus;
100
+ revision: number;
101
+ lastStepIndex: number;
102
+ /** Epoch ms of the first report for this (tour, revision). */
103
+ startedAt: number;
104
+ dismissedAt: number | null;
105
+ /** Sticky: once a run counted as an automatic interruption it stays one. */
106
+ autoStarted: boolean;
107
+ }
108
+ interface InterruptionBudget {
109
+ policy: InterruptionPolicy;
110
+ now: number;
111
+ registeredAt: number | null;
112
+ lastAutoInterruptionAt: number | null;
113
+ }
114
+ declare function interruptionsAllowed({ policy, now, registeredAt, lastAutoInterruptionAt }: InterruptionBudget): boolean;
115
+ declare function isTourOfferable({ policy, now, state, revision }: {
116
+ policy: InterruptionPolicy;
117
+ now: number;
118
+ state: TourRecord | undefined;
119
+ revision: number;
120
+ }): boolean;
121
+ interface InterruptionCandidates {
122
+ /** `undefined` means the host sent no route, which opts out of route triggers. */
123
+ route: string | undefined;
124
+ locales: readonly string[];
125
+ tours: readonly Tour[];
126
+ stateOf(tour: Tour): TourRecord | undefined;
127
+ announcements: readonly Announcement[];
128
+ dismissedKeys: ReadonlySet<string>;
129
+ }
130
+ declare function pickInterruption(budget: InterruptionBudget, candidates: InterruptionCandidates): Interruption | null;
131
+
132
+ declare function memoryStore(): KeyValueStore;
133
+
134
+ interface MemorySourceOptions {
135
+ tours: readonly TourDefinition[];
136
+ announcements?: readonly AnnouncementDefinition[];
137
+ storage: KeyValueStore;
138
+ locale?: string | (() => string);
139
+ fallbackLocale?: string;
140
+ /**
141
+ * Applied to every resolved string at read time, after locale resolution. Lets definitions hold message keys
142
+ * resolved by a stable function, so the source identity survives a locale switch.
143
+ */
144
+ translate?: (text: string) => string;
145
+ policy?: Partial<InterruptionPolicy>;
146
+ registeredAt?: Date | string | null;
147
+ now?: () => number;
148
+ namespace?: string;
149
+ }
150
+ declare function memorySource(options: MemorySourceOptions): SaparSource;
151
+
152
+ interface HttpSourceOptions {
153
+ baseUrl: string;
154
+ fetch?: typeof fetch;
155
+ headers?: HeadersInit | (() => HeadersInit | Promise<HeadersInit>);
156
+ credentials?: RequestCredentials;
157
+ locale?: string | (() => string);
158
+ }
159
+ declare class SaparHttpError extends Error {
160
+ readonly status: number;
161
+ constructor(status: number, message: string);
162
+ }
163
+ declare function httpSource(options: HttpSourceOptions): SaparSource;
164
+
165
+ interface WireStep {
166
+ step_key: string;
167
+ order: number;
168
+ /** Empty means a centered step. */
169
+ anchor_key: string;
170
+ /** Empty means the current route. */
171
+ route: string;
172
+ title: string;
173
+ body: string;
174
+ placement: Placement;
175
+ spotlight_padding: number;
176
+ is_required: boolean;
177
+ }
178
+ interface WireTour {
179
+ key: string;
180
+ revision: number;
181
+ title: string;
182
+ trigger: 'manual' | 'route';
183
+ steps: WireStep[];
184
+ }
185
+ interface WireTourState {
186
+ status: TourStatus;
187
+ last_step_index: number;
188
+ completed_at: string | null;
189
+ dismissed_at: string | null;
190
+ }
191
+ interface WireTourDetail extends WireTour {
192
+ state: WireTourState | null;
193
+ }
194
+ interface WireAnnouncement {
195
+ key: string;
196
+ tier: AnnouncementTier;
197
+ title: string;
198
+ body: string;
199
+ image_url: string;
200
+ cta_label: string;
201
+ cta_url: string;
202
+ published_at: string | null;
203
+ tour_key: string | null;
204
+ is_unread: boolean;
205
+ }
206
+ interface WireInterruption {
207
+ kind: 'tour' | 'announcement';
208
+ tour: WireTour | null;
209
+ announcement: WireAnnouncement | null;
210
+ }
211
+ interface WireInbox {
212
+ unread_count: number;
213
+ items: WireAnnouncement[];
214
+ interruption: WireInterruption | null;
215
+ }
216
+ interface WireProgress {
217
+ status: TourStatus;
218
+ step_index: number;
219
+ auto_started: boolean;
220
+ }
221
+ declare function fromWireTour(tour: WireTour): Tour;
222
+ declare function fromWireAnnouncement(announcement: WireAnnouncement): Announcement;
223
+ declare function fromWireInbox(inbox: WireInbox): Inbox;
224
+ declare function toWireProgress({ status, stepIndex, autoStarted }: ProgressInput): WireProgress;
225
+
226
+ interface TestAnchorHandle extends AnchorHandle {
227
+ press(): void;
228
+ pressListenerCount(): number;
229
+ }
230
+ interface TestAdapterOptions {
231
+ platform?: Platform;
232
+ /** Anchors that exist from the start. */
233
+ anchors?: readonly string[];
234
+ /** Anchors that resolve only once `showAnchor` is called, or to null on timeout. */
235
+ delayedAnchors?: readonly string[];
236
+ route?: string;
237
+ now?: number;
238
+ reducedMotion?: boolean;
239
+ compact?: boolean;
240
+ }
241
+ interface TestAdapter extends PlatformAdapter {
242
+ anchors: Map<string, TestAnchorHandle>;
243
+ navigations: string[];
244
+ scrolls: Array<{
245
+ handle: AnchorHandle;
246
+ reducedMotion: boolean;
247
+ }>;
248
+ resolveRequests: Array<{
249
+ key: string;
250
+ timeoutMs: number;
251
+ }>;
252
+ sessionValues: Map<string, string>;
253
+ showAnchor(key: string): TestAnchorHandle;
254
+ hideAnchor(key: string): void;
255
+ setRoute(route: string): void;
256
+ advanceTime(ms: number): void;
257
+ }
258
+ declare function createTestAdapter(options?: TestAdapterOptions): TestAdapter;
259
+
260
+ interface SpotlightPathInput {
261
+ /** Null dims the whole window. */
262
+ rect: AnchorRect | null;
263
+ padding: number;
264
+ radius: number;
265
+ bounds: {
266
+ width: number;
267
+ height: number;
268
+ };
269
+ }
270
+ /** The bounds with a rounded hole around `rect`; fill it with the even-odd rule so the hole stays click-through. */
271
+ declare function spotlightPath({ rect, padding, radius, bounds }: SpotlightPathInput): string;
272
+
273
+ export { AnchorHandle, type AnchorKey, AnchorRect, Announcement, type AnnouncementDefinition, type AnnouncementInput, AnnouncementTier, DEFAULT_ANCHOR_TIMEOUT_MS, DEFAULT_AUTO_START_TIMEOUT_MS, DEFAULT_POLICY, DEFAULT_PRESENT_ANCHOR_TIMEOUT_MS, type HttpSourceOptions, Inbox, Interruption, type InterruptionBudget, type InterruptionCandidates, InterruptionPolicy, KEY_PATTERN, KeyValueStore, LocalizedText, type MemorySourceOptions, Placement, Platform, PlatformAdapter, ProgressInput, RunnerSnapshot, SESSION_CAP_KEY, SaparController, SaparControllerOptions, SaparHttpError, SaparSource, type SpotlightPathInput, type StepDefinition, type StepInput, type TestAdapter, type TestAdapterOptions, type TestAnchorHandle, type TextLocale, Tour, type TourDefinition, type TourInput, type TourMachine, type TourMachineEvents, type TourMachineOptions, type TourRecord, TourStatus, TourTrigger, type WireAnnouncement, type WireInbox, type WireInterruption, type WireProgress, type WireStep, type WireTour, type WireTourDetail, type WireTourState, createSaparController, createTestAdapter, createTourMachine, defineAnchors, defineAnnouncement, defineTour, fromWireAnnouncement, fromWireInbox, fromWireTour, hasSpentSessionInterruption, httpSource, interruptionsAllowed, isTourOfferable, isValidRoutePattern, memorySource, memoryStore, normalizeRoute, pickInterruption, resolveAnnouncement, resolveText, resolveTour, routeMatches, spendSessionInterruption, spotlightPath, toWireProgress };
@@ -0,0 +1,71 @@
1
+ import {
2
+ DEFAULT_ANCHOR_TIMEOUT_MS,
3
+ DEFAULT_AUTO_START_TIMEOUT_MS,
4
+ DEFAULT_POLICY,
5
+ DEFAULT_PRESENT_ANCHOR_TIMEOUT_MS,
6
+ KEY_PATTERN,
7
+ SESSION_CAP_KEY,
8
+ SaparHttpError,
9
+ createSaparController,
10
+ createTestAdapter,
11
+ createTourMachine,
12
+ defineAnchors,
13
+ defineAnnouncement,
14
+ defineTour,
15
+ fromWireAnnouncement,
16
+ fromWireInbox,
17
+ fromWireTour,
18
+ hasSpentSessionInterruption,
19
+ httpSource,
20
+ interruptionsAllowed,
21
+ isTourOfferable,
22
+ isValidRoutePattern,
23
+ memorySource,
24
+ memoryStore,
25
+ normalizeRoute,
26
+ pickInterruption,
27
+ resolveAnnouncement,
28
+ resolvePresentation,
29
+ resolveText,
30
+ resolveTour,
31
+ routeMatches,
32
+ spendSessionInterruption,
33
+ spotlightPath,
34
+ toWireProgress
35
+ } from "../chunk-FM64UDKJ.js";
36
+ export {
37
+ DEFAULT_ANCHOR_TIMEOUT_MS,
38
+ DEFAULT_AUTO_START_TIMEOUT_MS,
39
+ DEFAULT_POLICY,
40
+ DEFAULT_PRESENT_ANCHOR_TIMEOUT_MS,
41
+ KEY_PATTERN,
42
+ SESSION_CAP_KEY,
43
+ SaparHttpError,
44
+ createSaparController,
45
+ createTestAdapter,
46
+ createTourMachine,
47
+ defineAnchors,
48
+ defineAnnouncement,
49
+ defineTour,
50
+ fromWireAnnouncement,
51
+ fromWireInbox,
52
+ fromWireTour,
53
+ hasSpentSessionInterruption,
54
+ httpSource,
55
+ interruptionsAllowed,
56
+ isTourOfferable,
57
+ isValidRoutePattern,
58
+ memorySource,
59
+ memoryStore,
60
+ normalizeRoute,
61
+ pickInterruption,
62
+ resolveAnnouncement,
63
+ resolvePresentation,
64
+ resolveText,
65
+ resolveTour,
66
+ routeMatches,
67
+ spendSessionInterruption,
68
+ spotlightPath,
69
+ toWireProgress
70
+ };
71
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,189 @@
1
+ export { E as ExpoAdapterOptions, c as createExpoAdapter } from '../adapter-fFZPsINL.js';
2
+ import * as react from 'react';
3
+ import { ComponentRef, RefCallback, Ref, ReactNode } from 'react';
4
+ import * as react_native from 'react-native';
5
+ import { ScrollViewProps, View, GestureResponderEvent, StyleProp, ViewStyle, ViewProps, TextProps, PressableProps, TextStyle } from 'react-native';
6
+ import { p as SessionStore, K as KeyValueStore, l as AnchorRect, d as Placement, k as AnchorHandle } from '../types-CHD2pB5X.js';
7
+ import { T as TourStepState, S as StepAnnouncement, a as StepCount } from '../stepCount-CTYYFWiV.js';
8
+ import { P as Presentation } from '../presentation-CClsPRT6.js';
9
+
10
+ interface ContainerMeasurement {
11
+ /** Top edge of the anchor within the scrollable content. */
12
+ offsetY: number;
13
+ height: number;
14
+ viewportHeight: number;
15
+ }
16
+ /** A vertically scrolling parent that tour anchors can be scrolled into view within. */
17
+ interface ScrollContainer {
18
+ measure(instance: AnchorInstance): Promise<ContainerMeasurement | null>;
19
+ scrollToOffset(offsetY: number, animated: boolean): void;
20
+ /** Calls `listener` at most once per frame while the user or the tour scrolls. */
21
+ subscribeToScroll(listener: () => void): () => void;
22
+ }
23
+ /** The nearest `TourScrollView` above the caller, if any. */
24
+ declare function useTourScrollContainer(): ScrollContainer | null;
25
+ /** A drop-in `ScrollView` whose children's anchors can be scrolled into view by the tour. Vertical only. */
26
+ declare const TourScrollView: react.ForwardRefExoticComponent<ScrollViewProps & react.RefAttributes<react_native.ScrollViewInstance>>;
27
+
28
+ type AnchorInstance = ComponentRef<typeof View>;
29
+ interface RegisteredAnchor {
30
+ instance: AnchorInstance;
31
+ /** The scroll container the anchor lived in when it registered. */
32
+ container: ScrollContainer | null;
33
+ }
34
+ declare function registerAnchor(key: string, anchor: RegisteredAnchor): () => void;
35
+ declare function getAnchor(key: string): RegisteredAnchor | null;
36
+ /** Resolves `null` on timeout. Woken by registration. */
37
+ declare function waitForAnchor(key: string, timeoutMs: number): Promise<RegisteredAnchor | null>;
38
+
39
+ /** The part of `@react-native-async-storage/async-storage` the tours use. */
40
+ interface AsyncStorageLike {
41
+ getItem(key: string): Promise<string | null>;
42
+ setItem(key: string, value: string): Promise<void>;
43
+ removeItem(key: string): Promise<void>;
44
+ }
45
+ /** The part of a `react-native-mmkv` instance the tours use: `remove` since v4, `delete` before. */
46
+ type MmkvLike = {
47
+ getString(key: string): string | undefined;
48
+ set(key: string, value: string): void;
49
+ } & ({
50
+ remove(key: string): void;
51
+ } | {
52
+ delete(key: string): void;
53
+ });
54
+ declare const asyncStorageStore: (storage: AsyncStorageLike) => KeyValueStore;
55
+ declare const mmkvStore: (mmkv: MmkvLike) => KeyValueStore;
56
+ /** Lives as long as the JS runtime, which is what an app session is. */
57
+ declare function appSessionStore(): SessionStore;
58
+
59
+ interface TourAnchorProps {
60
+ ref: RefCallback<AnchorInstance>;
61
+ /** Keeps the native node alive on Android so it stays measurable. */
62
+ collapsable: false;
63
+ /** Reports presses without taking the responder from the host's own `Pressable`. */
64
+ onTouchEnd: (event: GestureResponderEvent) => void;
65
+ }
66
+ /** What the anchored view already has: spreading the result would overwrite it, so it is passed in and composed. */
67
+ interface TourAnchorHost {
68
+ ref?: Ref<AnchorInstance>;
69
+ onTouchEnd?: (event: GestureResponderEvent) => void;
70
+ }
71
+ /**
72
+ * Spread the result onto the view a tour step points at: `<Pressable {...useTourAnchor('billing.upgrade')} />`.
73
+ * A view that has its own `ref` or `onTouchEnd` passes them as `host`; its `onPress` needs no help.
74
+ */
75
+ declare function useTourAnchor<K extends string = string>(key: K, { ref: hostRef, onTouchEnd: hostOnTouchEnd }?: TourAnchorHost): TourAnchorProps;
76
+
77
+ interface Size {
78
+ width: number;
79
+ height: number;
80
+ }
81
+ interface Insets {
82
+ top: number;
83
+ right: number;
84
+ bottom: number;
85
+ left: number;
86
+ }
87
+ interface CardPositionInput {
88
+ /** Null centers the card in the window. */
89
+ anchor: AnchorRect | null;
90
+ card: Size;
91
+ window: Size;
92
+ placement: Placement;
93
+ /** Gap between the anchor and the card. */
94
+ offset: number;
95
+ /** Space the card must keep clear at each window edge. */
96
+ insets: Insets;
97
+ }
98
+ interface CardPosition {
99
+ x: number;
100
+ y: number;
101
+ /** False when neither the preferred side of the anchor nor the opposite one has room for the card. */
102
+ fits: boolean;
103
+ }
104
+ /** Top-left corner for the card: on the preferred side, flipped when it does not fit, and kept inside the insets. */
105
+ declare function computeCardPosition(input: CardPositionInput): CardPosition;
106
+
107
+ /** Window rect of the anchor; null without a handle or while it cannot be measured. Re-measures when the window resizes or its scroll container scrolls. */
108
+ declare function useAnchorRect(handle: AnchorHandle | null): AnchorRect | null;
109
+
110
+ interface TourPopoverProps {
111
+ style?: StyleProp<ViewStyle>;
112
+ /** Gap between the anchor and the card. */
113
+ offset?: number;
114
+ /** Space kept clear at the window edges; pass the safe-area insets and any tab bar height. Default 8 each. */
115
+ insets?: Partial<Insets>;
116
+ /**
117
+ * `'anchored'` puts the card next to the anchor (centred without one), `'sheet'` is a bottom sheet, and
118
+ * `'auto'` is anchored unless the card does not fit beside the anchor or the window is narrower than the
119
+ * adapter's `compactBreakpointPx`. Default `'auto'`.
120
+ */
121
+ presentation?: Presentation;
122
+ children?: ReactNode;
123
+ }
124
+ /** Render at the root after `TourSpotlight`. Sits next to the anchor, centred without one, and is a bottom sheet when it does not fit. */
125
+ declare function TourPopover({ offset, insets, presentation, ...rest }: TourPopoverProps): react.JSX.Element | null;
126
+
127
+ interface TourOverlayProps extends Pick<TourPopoverProps, 'insets' | 'presentation'> {
128
+ spotlightColor?: string;
129
+ spotlightStyle?: StyleProp<ViewStyle>;
130
+ popoverStyle?: StyleProp<ViewStyle>;
131
+ onClickOutside?: () => void;
132
+ /** The step card, either directly or built from the running step. */
133
+ children: ReactNode | ((tourStep: TourStepState) => ReactNode);
134
+ }
135
+ /** Render at the root, inside the provider and after the app content. The Android back button skips the tour. */
136
+ declare function TourOverlay({ spotlightColor, spotlightStyle, popoverStyle, onClickOutside, insets, presentation, children }: TourOverlayProps): react.JSX.Element | null;
137
+
138
+ interface TourSpotlightProps {
139
+ /** Colour of the dim layer. */
140
+ color?: string;
141
+ style?: StyleProp<ViewStyle>;
142
+ /** Corner radius of the cutout. */
143
+ radius?: number;
144
+ /** Called when the dim layer is pressed. Defaults to skipping the tour. */
145
+ onClickOutside?: () => void;
146
+ }
147
+ /** Render at the root, inside the provider and after the app content, so it covers the screen. */
148
+ declare function TourSpotlight({ onClickOutside, ...rest }: TourSpotlightProps): react.JSX.Element | null;
149
+
150
+ interface TourStepRootProps extends ViewProps {
151
+ /** Text read by screen readers on each step change. */
152
+ announceStep?: (step: StepAnnouncement) => string;
153
+ }
154
+ declare function Root(props: TourStepRootProps): react.JSX.Element | null;
155
+ declare function Title({ children, ...rest }: TextProps): react.JSX.Element;
156
+ declare function Body({ children, ...rest }: TextProps): react.JSX.Element;
157
+ interface TourStepProgressProps extends Omit<TextProps, 'children'> {
158
+ /** Defaults to `"{position} / {total}"`. */
159
+ children?: ReactNode | ((count: StepCount) => ReactNode);
160
+ }
161
+ declare function Progress({ children, ...rest }: TourStepProgressProps): react.JSX.Element;
162
+ interface TourStepButtonProps extends Omit<PressableProps, 'children'> {
163
+ children?: ReactNode;
164
+ /** Styles the label; the button itself takes `style`, which may be a function of the pressed state. */
165
+ textStyle?: StyleProp<TextStyle>;
166
+ }
167
+ interface TourStepNextProps extends TourStepButtonProps {
168
+ /** Labels for the last step and the others. Ignored when `children` is given. */
169
+ doneLabel?: ReactNode;
170
+ nextLabel?: ReactNode;
171
+ /** Steps that advance when the anchor is pressed hide this button unless set. */
172
+ showOnPress?: boolean;
173
+ }
174
+ declare function Next({ doneLabel, nextLabel, showOnPress, children, onPress, ...rest }: TourStepNextProps): react.JSX.Element | null;
175
+ declare function Back({ children, onPress, ...rest }: TourStepButtonProps): react.JSX.Element | null;
176
+ declare function Skip({ children, onPress, ...rest }: TourStepButtonProps): react.JSX.Element;
177
+ declare function Close({ children, ...rest }: TourStepButtonProps): react.JSX.Element;
178
+ declare const TourStep: {
179
+ Root: typeof Root;
180
+ Title: typeof Title;
181
+ Body: typeof Body;
182
+ Progress: typeof Progress;
183
+ Next: typeof Next;
184
+ Back: typeof Back;
185
+ Skip: typeof Skip;
186
+ Close: typeof Close;
187
+ };
188
+
189
+ export { type AnchorInstance, type AsyncStorageLike, type CardPosition, type CardPositionInput, type ContainerMeasurement, type Insets, type MmkvLike, Presentation, type RegisteredAnchor, type ScrollContainer, type Size, type TourAnchorProps, TourOverlay, type TourOverlayProps, TourPopover, type TourPopoverProps, TourScrollView, TourSpotlight, type TourSpotlightProps, TourStep, type TourStepButtonProps, type TourStepNextProps, type TourStepProgressProps, type TourStepRootProps, appSessionStore, asyncStorageStore, computeCardPosition, getAnchor, mmkvStore, registerAnchor, useAnchorRect, useTourAnchor, useTourScrollContainer, waitForAnchor };
@@ -0,0 +1,39 @@
1
+ import {
2
+ TourOverlay,
3
+ TourPopover,
4
+ TourScrollView,
5
+ TourSpotlight,
6
+ TourStep,
7
+ appSessionStore,
8
+ asyncStorageStore,
9
+ computeCardPosition,
10
+ createExpoAdapter,
11
+ getAnchor,
12
+ mmkvStore,
13
+ registerAnchor,
14
+ useAnchorRect,
15
+ useTourAnchor,
16
+ useTourScrollContainer,
17
+ waitForAnchor
18
+ } from "../chunk-ZBVQGMR4.js";
19
+ import "../chunk-VC6XLWM3.js";
20
+ import "../chunk-FM64UDKJ.js";
21
+ export {
22
+ TourOverlay,
23
+ TourPopover,
24
+ TourScrollView,
25
+ TourSpotlight,
26
+ TourStep,
27
+ appSessionStore,
28
+ asyncStorageStore,
29
+ computeCardPosition,
30
+ createExpoAdapter,
31
+ getAnchor,
32
+ mmkvStore,
33
+ registerAnchor,
34
+ useAnchorRect,
35
+ useTourAnchor,
36
+ useTourScrollContainer,
37
+ waitForAnchor
38
+ };
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,18 @@
1
+ import { b as PlatformAdapter, S as SaparControllerOptions } from '../types-CHD2pB5X.js';
2
+ import { E as ExpoAdapterOptions } from '../adapter-fFZPsINL.js';
3
+ import * as react from 'react';
4
+ import { ReactNode } from 'react';
5
+
6
+ type ExpoRouterAdapterOptions = Pick<ExpoAdapterOptions, 'compactBreakpointPx' | 'session'>;
7
+ /** Identity never changes; `options` are read on first render only. */
8
+ declare function useExpoRouterAdapter(options?: ExpoRouterAdapterOptions): PlatformAdapter;
9
+
10
+ interface ExpoSaparProviderProps extends Omit<SaparControllerOptions, 'adapter'> {
11
+ children: ReactNode;
12
+ /** Stop reporting route changes, so tours and announcements are never offered automatically. */
13
+ disableRouteTriggers?: boolean;
14
+ adapterOptions?: ExpoRouterAdapterOptions;
15
+ }
16
+ declare function ExpoSaparProvider({ children, disableRouteTriggers, adapterOptions, ...controllerOptions }: ExpoSaparProviderProps): react.JSX.Element;
17
+
18
+ export { type ExpoRouterAdapterOptions, ExpoSaparProvider, type ExpoSaparProviderProps, useExpoRouterAdapter };
@@ -0,0 +1,46 @@
1
+ import {
2
+ createExpoAdapter
3
+ } from "../chunk-ZBVQGMR4.js";
4
+ import {
5
+ SaparProvider
6
+ } from "../chunk-VC6XLWM3.js";
7
+ import "../chunk-FM64UDKJ.js";
8
+
9
+ // src/expo-router/useExpoRouterAdapter.ts
10
+ import { usePathname, useRouter } from "expo-router";
11
+ import { useEffect, useRef, useState } from "react";
12
+ function useExpoRouterAdapter(options = {}) {
13
+ const router = useRouter();
14
+ const pathname = usePathname();
15
+ const latest = useRef({ router, pathname });
16
+ useEffect(() => {
17
+ latest.current = { router, pathname };
18
+ });
19
+ const [adapter] = useState(
20
+ () => createExpoAdapter({
21
+ ...options,
22
+ navigate: (route) => latest.current.router.push(route),
23
+ currentRoute: () => latest.current.pathname
24
+ })
25
+ );
26
+ return adapter;
27
+ }
28
+
29
+ // src/expo-router/ExpoSaparProvider.tsx
30
+ import { usePathname as usePathname2 } from "expo-router";
31
+ import { jsx } from "react/jsx-runtime";
32
+ function ExpoSaparProvider({
33
+ children,
34
+ disableRouteTriggers = false,
35
+ adapterOptions,
36
+ ...controllerOptions
37
+ }) {
38
+ const adapter = useExpoRouterAdapter(adapterOptions);
39
+ const pathname = usePathname2();
40
+ return /* @__PURE__ */ jsx(SaparProvider, { ...controllerOptions, adapter, route: disableRouteTriggers ? void 0 : pathname, children });
41
+ }
42
+ export {
43
+ ExpoSaparProvider,
44
+ useExpoRouterAdapter
45
+ };
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/expo-router/useExpoRouterAdapter.ts","../../src/expo-router/ExpoSaparProvider.tsx"],"sourcesContent":["import { usePathname, useRouter } from 'expo-router';\nimport { useEffect, useRef, useState } from 'react';\nimport type { PlatformAdapter } from '../core';\nimport { createExpoAdapter, type ExpoAdapterOptions } from '../expo';\n\nexport type ExpoRouterAdapterOptions = Pick<ExpoAdapterOptions, 'compactBreakpointPx' | 'session'>;\n\n/** Identity never changes; `options` are read on first render only. */\nexport function useExpoRouterAdapter(options: ExpoRouterAdapterOptions = {}): PlatformAdapter {\n const router = useRouter();\n const pathname = usePathname();\n const latest = useRef({ router, pathname });\n useEffect(() => {\n latest.current = { router, pathname };\n });\n\n const [adapter] = useState(() =>\n createExpoAdapter({\n ...options,\n navigate: (route) => latest.current.router.push(route),\n currentRoute: () => latest.current.pathname,\n }),\n );\n return adapter;\n}\n","import { usePathname } from 'expo-router';\nimport type { ReactNode } from 'react';\nimport type { SaparControllerOptions } from '../core';\nimport { SaparProvider } from '../react';\nimport { useExpoRouterAdapter, type ExpoRouterAdapterOptions } from './useExpoRouterAdapter';\n\nexport interface ExpoSaparProviderProps extends Omit<SaparControllerOptions, 'adapter'> {\n children: ReactNode;\n /** Stop reporting route changes, so tours and announcements are never offered automatically. */\n disableRouteTriggers?: boolean;\n adapterOptions?: ExpoRouterAdapterOptions;\n}\n\nexport function ExpoSaparProvider({\n children,\n disableRouteTriggers = false,\n adapterOptions,\n ...controllerOptions\n}: ExpoSaparProviderProps) {\n const adapter = useExpoRouterAdapter(adapterOptions);\n const pathname = usePathname();\n\n return (\n <SaparProvider {...controllerOptions} adapter={adapter} route={disableRouteTriggers ? undefined : pathname}>\n {children}\n </SaparProvider>\n );\n}\n"],"mappings":";;;;;;;;;AAAA,SAAS,aAAa,iBAAiB;AACvC,SAAS,WAAW,QAAQ,gBAAgB;AAOrC,SAAS,qBAAqB,UAAoC,CAAC,GAAoB;AAC1F,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,YAAY;AAC7B,QAAM,SAAS,OAAO,EAAE,QAAQ,SAAS,CAAC;AAC1C,YAAU,MAAM;AACZ,WAAO,UAAU,EAAE,QAAQ,SAAS;AAAA,EACxC,CAAC;AAED,QAAM,CAAC,OAAO,IAAI;AAAA,IAAS,MACvB,kBAAkB;AAAA,MACd,GAAG;AAAA,MACH,UAAU,CAAC,UAAU,OAAO,QAAQ,OAAO,KAAK,KAAK;AAAA,MACrD,cAAc,MAAM,OAAO,QAAQ;AAAA,IACvC,CAAC;AAAA,EACL;AACA,SAAO;AACX;;;ACxBA,SAAS,eAAAA,oBAAmB;AAuBpB;AAVD,SAAS,kBAAkB;AAAA,EAC9B;AAAA,EACA,uBAAuB;AAAA,EACvB;AAAA,EACA,GAAG;AACP,GAA2B;AACvB,QAAM,UAAU,qBAAqB,cAAc;AACnD,QAAM,WAAWC,aAAY;AAE7B,SACI,oBAAC,iBAAe,GAAG,mBAAmB,SAAkB,OAAO,uBAAuB,SAAY,UAC7F,UACL;AAER;","names":["usePathname","usePathname"]}
@@ -0,0 +1,18 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { b as PlatformAdapter, S as SaparControllerOptions } from '../types-CHD2pB5X.js';
4
+ import { W as WebAdapterOptions } from '../adapter-Y9yB3-q3.js';
5
+
6
+ type NextSaparAdapterOptions = Pick<WebAdapterOptions, 'compactBreakpointPx' | 'session'>;
7
+ /** Identity never changes; `options` are read on first render only. */
8
+ declare function useNextSaparAdapter(options?: NextSaparAdapterOptions): PlatformAdapter;
9
+
10
+ interface NextSaparProviderProps extends Omit<SaparControllerOptions, 'adapter'> {
11
+ children: ReactNode;
12
+ /** Stop reporting route changes, so tours and announcements are never offered automatically. */
13
+ disableRouteTriggers?: boolean;
14
+ adapterOptions?: NextSaparAdapterOptions;
15
+ }
16
+ declare function NextSaparProvider({ children, disableRouteTriggers, adapterOptions, ...controllerOptions }: NextSaparProviderProps): react.JSX.Element;
17
+
18
+ export { type NextSaparAdapterOptions, NextSaparProvider, type NextSaparProviderProps, useNextSaparAdapter };