@yoamigo.com/core 0.4.7 → 1.0.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.
package/dist/index.d.ts CHANGED
@@ -1,44 +1,11 @@
1
+ import { C as ChangeSource, Q as QueryFilter, b as CollectionRecord, o as CartItem, E as EditMode } from './cart-storage-DFdGPcwm.js';
2
+ export { a as CollectionClient, d as CollectionClientConfig, t as ContentStoreContextType, v as ContentStoreMode, p as ContentStoreProvider, L as ListOptions, c as ListResponse, S as SingleResponse, f as clearSessionId, g as getCollectionClient, n as getLocalCartItemCount, k as getLocalCartItems, e as getSessionId, i as initBuilderSelection, r as resetCollectionClient, q as useContentStore } from './cart-storage-DFdGPcwm.js';
3
+ export { D as BackgroundConfig, F as BackgroundImageConfig, C as ContentStoreProviderProd, q as EmbedFieldValue, r as EmbedType, I as ImageFieldValue, f as MarkdownText, g as MarkdownTextProps, O as OverlayConfig, P as PageInfo, c as StaticImage, d as StaticImageProps, M as StaticText, S as StaticTextProps, V as VideoFieldValue, y as YaContainer, B as YaContainerProps, m as YaEmbed, o as YaEmbedProps, Y as YaImage, h as YaImageProps, w as YaLink, x as YaLinkProps, j as YaVideo, l as YaVideoProps, b as background, e as embed, i as image, z as parseBackgroundConfig, p as parseEmbedUrl, A as serializeBackgroundConfig, n as serializeEmbedValue, s as serializeImageValue, k as serializeVideoValue, t as text, u as useContentStoreProd, v as video } from './content-helpers-DOUKazMz.js';
1
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
5
  import React$1, { ReactNode } from 'react';
3
- export { D as BackgroundConfig, F as BackgroundImageConfig, C as ContentStoreProviderProd, q as EmbedFieldValue, r as EmbedType, I as ImageFieldValue, f as MarkdownText, g as MarkdownTextProps, O as OverlayConfig, P as PageInfo, c as StaticImage, d as StaticImageProps, M as StaticText, S as StaticTextProps, V as VideoFieldValue, y as YaContainer, B as YaContainerProps, m as YaEmbed, o as YaEmbedProps, Y as YaImage, h as YaImageProps, w as YaLink, x as YaLinkProps, j as YaVideo, l as YaVideoProps, b as background, e as embed, i as image, z as parseBackgroundConfig, p as parseEmbedUrl, A as serializeBackgroundConfig, n as serializeEmbedValue, s as serializeImageValue, k as serializeVideoValue, t as text, u as useContentStoreProd, v as video } from './content-helpers-DOUKazMz.js';
4
- export { Link, LinkProps, NavigateFunction, Router, RouterProps, ScrollRestoration, useNavigate } from './router.js';
5
- export { Route, Switch, useParams } from 'wouter';
6
+ export { Link, LinkProps, NavigateFunction, RouteDefinition, Router, RouterProps, ScrollRestoration, createRouteDefinition, extractRouteParams, filePathToRoutePath, generatePath, sortRoutesBySpecificity, useNavigate } from './router.js';
7
+ export { Route, Switch, useLocation, useParams } from 'wouter';
6
8
  export { A as AssetResolverFn, C as ContentRegistry, c as contentRegistry, a as getAllContent, g as getContent, h as hasContent, r as registerContent, b as resolveAssetUrl, s as setAssetResolver } from './asset-resolver-BnIvDkVv.js';
7
- export { i as initBuilderSelection } from './builder-selection-CYP91nRu.js';
8
-
9
- type EditMode = 'read-only' | 'inline-edit';
10
- type ChangeSource = 'user' | 'ai' | 'initial';
11
- interface PageInfo {
12
- path: string;
13
- label: string;
14
- }
15
- interface ActiveFieldCallbacks {
16
- close: () => void;
17
- }
18
- interface ContentStore {
19
- getValue: (fieldId: string) => string;
20
- setValue: (fieldId: string, value: string, source?: ChangeSource) => void;
21
- getChangeSource: (fieldId: string) => ChangeSource;
22
- clearChangeSource: (fieldId: string) => void;
23
- mode: EditMode;
24
- setMode: (mode: EditMode) => void;
25
- subscribe: (listener: () => void) => () => void;
26
- saveToWorker?: (fieldId: string, value: string) => Promise<void>;
27
- activeFieldId: string | null;
28
- setActiveField: (fieldId: string, callbacks: ActiveFieldCallbacks) => void;
29
- clearActiveField: () => void;
30
- getPages: () => PageInfo[];
31
- }
32
- type ContentStoreContextType = ContentStore;
33
- type ContentStoreMode = EditMode;
34
- declare function useContentStore(): ContentStoreContextType;
35
- interface ContentStoreProviderProps {
36
- children: ReactNode;
37
- initialContent?: Record<string, string>;
38
- initialMode?: EditMode;
39
- pages?: PageInfo[];
40
- }
41
- declare function ContentStoreProvider({ children, initialContent, initialMode, pages, }: ContentStoreProviderProps): react_jsx_runtime.JSX.Element;
42
9
 
43
10
  /** Common HTML elements that YaText can render as */
44
11
  type YaTextElement = 'span' | 'div' | 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'strong' | 'em';
@@ -126,6 +93,435 @@ interface TooltipProps {
126
93
  }
127
94
  declare function Tooltip({ content, children, position, delay, }: TooltipProps): react_jsx_runtime.JSX.Element;
128
95
 
96
+ interface CollectionContentContextValue {
97
+ /** Get a value from the collection record */
98
+ getValue: (fieldId: string) => string;
99
+ /** Set a value (triggers local update + backend save). Only available in edit mode. */
100
+ setValue?: (fieldId: string, value: string, source?: ChangeSource) => void;
101
+ /** Save to backend (creates/updates StagedAppRecord). Only available in edit mode. */
102
+ saveToBackend?: (fieldId: string, value: string) => Promise<void>;
103
+ /** Get the change source for animation tracking */
104
+ getChangeSource?: (fieldId: string) => ChangeSource;
105
+ /** Clear change source after animation completes */
106
+ clearChangeSource?: (fieldId: string) => void;
107
+ /** Whether this content is from a collection */
108
+ isCollectionContent: true;
109
+ /** The prefix used for field IDs */
110
+ prefix: string;
111
+ /** The record ID (for UPDATE) or undefined (for CREATE) */
112
+ recordId?: string;
113
+ /** Collection slug for API calls */
114
+ collectionSlug?: string;
115
+ /** App ID for API calls */
116
+ appId?: string;
117
+ /** Whether editing is enabled */
118
+ isEditable: boolean;
119
+ }
120
+ interface CollectionContentProviderProps {
121
+ /** The collection record data (the `data` field from CollectionRecord) */
122
+ record: Record<string, unknown>;
123
+ /** Prefix for field IDs (e.g., "product" makes "product.name") */
124
+ prefix: string;
125
+ /** Child components */
126
+ children: ReactNode;
127
+ /** The AppRecord ID (required for UPDATE, optional for CREATE) */
128
+ recordId?: string;
129
+ /** Collection slug for API calls */
130
+ collectionSlug?: string;
131
+ /** App ID for API calls */
132
+ appId?: string;
133
+ /** Whether this is a new record or existing */
134
+ changeType?: 'CREATE' | 'UPDATE';
135
+ }
136
+ /**
137
+ * Hook to get collection content context.
138
+ * Returns null if not inside a CollectionContentProvider.
139
+ */
140
+ declare function useCollectionContent(): CollectionContentContextValue | null;
141
+ /**
142
+ * Provider that makes collection record data available to YaText, YaImage, etc.
143
+ *
144
+ * Fields are accessed using dot notation with the prefix:
145
+ * - `prefix="product"` + field `name` → `fieldId="product.name"`
146
+ * - Nested: `prefix="product"` + field `image.src` → `fieldId="product.image.src"`
147
+ *
148
+ * When edit props are provided, inline edits are saved to StagedAppRecord.
149
+ */
150
+ declare function CollectionContentProvider({ record, prefix, children, recordId, collectionSlug, appId, changeType: _changeType, }: CollectionContentProviderProps): react_jsx_runtime.JSX.Element;
151
+
152
+ /**
153
+ * Collection Hooks
154
+ *
155
+ * React hooks for fetching collection data from the API.
156
+ * Used in templates for dynamic pages powered by collection records.
157
+ */
158
+
159
+ interface UseCollectionListOptions {
160
+ /** Collection slug (e.g., 'products', 'posts') */
161
+ collection: string;
162
+ /** Optional filters to apply */
163
+ filters?: QueryFilter[];
164
+ /** Page number (1-indexed for convenience) */
165
+ page?: number;
166
+ /** Number of items per page */
167
+ pageSize?: number;
168
+ /** Field to order by */
169
+ orderBy?: string;
170
+ /** Order direction */
171
+ orderDir?: 'asc' | 'desc';
172
+ /** Whether to fetch (useful for conditional fetching) */
173
+ enabled?: boolean;
174
+ }
175
+ interface UseCollectionListResult<T = Record<string, unknown>> {
176
+ /** The fetched records, or null if not yet loaded */
177
+ data: CollectionRecord<T>[] | null;
178
+ /** Whether the initial fetch is in progress */
179
+ isLoading: boolean;
180
+ /** Error message if fetch failed */
181
+ error: string | null;
182
+ /** Total count of records matching the query */
183
+ totalCount: number;
184
+ /** Whether there are more pages */
185
+ hasMore: boolean;
186
+ /** Current page number */
187
+ currentPage: number;
188
+ /** Total number of pages */
189
+ totalPages: number;
190
+ /** Refetch the data */
191
+ refetch: () => void;
192
+ /** Go to a specific page */
193
+ goToPage: (page: number) => void;
194
+ }
195
+ interface UseCollectionRecordOptions {
196
+ /** Collection slug (e.g., 'products', 'posts') */
197
+ collection: string;
198
+ /** Field name that contains the slug (e.g., 'slug', 'handle') */
199
+ slugField: string;
200
+ /** Slug value to look up */
201
+ slugValue: string;
202
+ /** Whether to fetch (useful for conditional fetching) */
203
+ enabled?: boolean;
204
+ }
205
+ interface UseCollectionRecordResult<T = Record<string, unknown>> {
206
+ /** The fetched record, or null if not yet loaded */
207
+ data: CollectionRecord<T> | null;
208
+ /** Whether the fetch is in progress */
209
+ isLoading: boolean;
210
+ /** Error message if fetch failed */
211
+ error: string | null;
212
+ /** Whether the record was not found (404) */
213
+ notFound: boolean;
214
+ /** Refetch the data */
215
+ refetch: () => void;
216
+ }
217
+ /**
218
+ * Hook for fetching a list of collection records with pagination.
219
+ *
220
+ * @example
221
+ * ```tsx
222
+ * const { data: products, isLoading, goToPage } = useCollectionList({
223
+ * collection: 'products',
224
+ * pageSize: 12,
225
+ * orderBy: 'createdAt',
226
+ * orderDir: 'desc'
227
+ * })
228
+ * ```
229
+ */
230
+ declare function useCollectionList<T = Record<string, unknown>>(options: UseCollectionListOptions): UseCollectionListResult<T>;
231
+ /**
232
+ * Hook for fetching a single collection record by slug.
233
+ *
234
+ * @example
235
+ * ```tsx
236
+ * const { slug } = useParams()
237
+ * const { data: product, isLoading, notFound } = useCollectionRecord({
238
+ * collection: 'products',
239
+ * slugField: 'slug',
240
+ * slugValue: slug!
241
+ * })
242
+ * ```
243
+ */
244
+ declare function useCollectionRecord<T = Record<string, unknown>>(options: UseCollectionRecordOptions): UseCollectionRecordResult<T>;
245
+
246
+ /**
247
+ * CollectionPage Components
248
+ *
249
+ * Higher-level wrapper components for common collection page patterns.
250
+ * These simplify creating list and detail pages powered by collection data.
251
+ *
252
+ * @example List Page
253
+ * ```tsx
254
+ * <CollectionListPage
255
+ * collection="products"
256
+ * pageSize={12}
257
+ * render={({ data, isLoading }) => (
258
+ * isLoading ? <Skeleton /> : <ProductGrid products={data} />
259
+ * )}
260
+ * />
261
+ * ```
262
+ *
263
+ * @example Detail Page
264
+ * ```tsx
265
+ * <CollectionDetailPage
266
+ * collection="products"
267
+ * slugField="slug"
268
+ * render={({ data, isLoading, notFound }) => {
269
+ * if (isLoading) return <Skeleton />
270
+ * if (notFound) return <NotFound />
271
+ * return <ProductDetail product={data} />
272
+ * }}
273
+ * />
274
+ * ```
275
+ */
276
+
277
+ interface CollectionListPageProps<T = Record<string, unknown>> {
278
+ /** Collection slug (e.g., 'products', 'posts') */
279
+ collection: string;
280
+ /** Number of items per page */
281
+ pageSize?: number;
282
+ /** Initial page number */
283
+ page?: number;
284
+ /** Filters to apply */
285
+ filters?: QueryFilter[];
286
+ /** Field to order by */
287
+ orderBy?: string;
288
+ /** Order direction */
289
+ orderDir?: 'asc' | 'desc';
290
+ /** Whether to fetch data */
291
+ enabled?: boolean;
292
+ /** Render function that receives the list result */
293
+ render: (result: UseCollectionListResult<T>) => ReactNode;
294
+ }
295
+ /**
296
+ * Wrapper component for collection list pages.
297
+ *
298
+ * Handles data fetching and provides the result to a render function,
299
+ * giving you full control over the UI.
300
+ */
301
+ declare function CollectionListPage<T = Record<string, unknown>>({ collection, pageSize, page, filters, orderBy, orderDir, enabled, render, }: CollectionListPageProps<T>): ReactNode;
302
+ interface CollectionDetailPageProps<T = Record<string, unknown>> {
303
+ /** Collection slug (e.g., 'products', 'posts') */
304
+ collection: string;
305
+ /** Field name that contains the slug (e.g., 'slug', 'handle') */
306
+ slugField?: string;
307
+ /** URL parameter name for the slug (default: 'slug') */
308
+ slugParam?: string;
309
+ /** Override slug value (instead of reading from URL params) */
310
+ slug?: string;
311
+ /** Whether to fetch data */
312
+ enabled?: boolean;
313
+ /** Render function that receives the record result */
314
+ render: (result: CollectionDetailRenderProps<T>) => ReactNode;
315
+ }
316
+ interface CollectionDetailRenderProps<T = Record<string, unknown>> extends UseCollectionRecordResult<T> {
317
+ /** The slug value from URL params */
318
+ slug: string;
319
+ }
320
+ /**
321
+ * Wrapper component for collection detail pages.
322
+ *
323
+ * Automatically reads the slug from URL params (default: `:slug`)
324
+ * and fetches the matching record.
325
+ *
326
+ * @example
327
+ * ```tsx
328
+ * // For route /products/:slug
329
+ * <CollectionDetailPage
330
+ * collection="products"
331
+ * render={({ data, isLoading, notFound }) => {
332
+ * if (isLoading) return <Skeleton />
333
+ * if (notFound) return <NotFound />
334
+ * return <ProductDetail product={data} />
335
+ * }}
336
+ * />
337
+ * ```
338
+ */
339
+ declare function CollectionDetailPage<T = Record<string, unknown>>({ collection, slugField, slugParam, slug: slugOverride, enabled, render, }: CollectionDetailPageProps<T>): ReactNode;
340
+ /**
341
+ * Type helper for creating typed collection page components.
342
+ *
343
+ * @example
344
+ * ```tsx
345
+ * interface Product {
346
+ * slug: string
347
+ * name: string
348
+ * price: number
349
+ * }
350
+ *
351
+ * // Products list page with type safety
352
+ * function ProductsPage() {
353
+ * return (
354
+ * <CollectionListPage<Product>
355
+ * collection="products"
356
+ * render={({ data }) => (
357
+ * data?.map(p => <div key={p.id}>{p.data.name}</div>)
358
+ * )}
359
+ * />
360
+ * )
361
+ * }
362
+ * ```
363
+ */
364
+ type CollectionData<T> = CollectionRecord<T>;
365
+ /**
366
+ * Type helper for list page data
367
+ */
368
+ type CollectionListData<T> = CollectionRecord<T>[];
369
+
370
+ /**
371
+ * CollectionList
372
+ *
373
+ * Renders a filtered list of collection items with editing support.
374
+ * Each item is wrapped in CollectionContentProvider so YaText/YaImage
375
+ * components can read and edit collection fields.
376
+ *
377
+ * @example
378
+ * ```tsx
379
+ * <CollectionList
380
+ * collection="products"
381
+ * prefix="product"
382
+ * filters={[{ field: 'category', operator: 'eq', value: 'guitars' }]}
383
+ * pageSize={6}
384
+ * skeleton={({ index }) => <ProductCardSkeleton key={index} />}
385
+ * empty={<p>No products found</p>}
386
+ * wrapper={({ children }) => (
387
+ * <div className="grid grid-cols-3 gap-4">{children}</div>
388
+ * )}
389
+ * >
390
+ * {({ record, fieldPrefix }) => (
391
+ * <div key={record.id}>
392
+ * <YaImage fieldId={`${fieldPrefix}.image`} />
393
+ * <YaText fieldId={`${fieldPrefix}.name`} />
394
+ * </div>
395
+ * )}
396
+ * </CollectionList>
397
+ * ```
398
+ */
399
+
400
+ interface CollectionListRenderProps<T = Record<string, unknown>> {
401
+ /** The collection record */
402
+ record: CollectionRecord<T>;
403
+ /** Index of this item in the list */
404
+ index: number;
405
+ /** The unique fieldId prefix for this item (e.g., "product.abc123") */
406
+ fieldPrefix: string;
407
+ }
408
+ interface CollectionListProps<T = Record<string, unknown>> extends Omit<UseCollectionListOptions, 'enabled'> {
409
+ /** Base prefix for fieldIds. Each item gets `{prefix}.{recordId}` */
410
+ prefix: string;
411
+ /** Render function for each item */
412
+ children: (props: CollectionListRenderProps<T>) => ReactNode;
413
+ /** Render function for skeleton items during loading (REQUIRED for zero layout shift) */
414
+ skeleton: (props: {
415
+ index: number;
416
+ }) => ReactNode;
417
+ /** Empty state render (when no items match) */
418
+ empty?: ReactNode;
419
+ /** Error state render */
420
+ error?: (error: string) => ReactNode;
421
+ /** App ID for editing (auto-detected in builder context) */
422
+ appId?: string;
423
+ /** Whether to enable fetching (default: true) */
424
+ enabled?: boolean;
425
+ /** Render pagination controls */
426
+ pagination?: (props: CollectionListPaginationProps) => ReactNode;
427
+ /** Wrapper element/component for the list items */
428
+ wrapper?: (props: {
429
+ children: ReactNode;
430
+ }) => ReactNode;
431
+ }
432
+ interface CollectionListPaginationProps {
433
+ currentPage: number;
434
+ totalPages: number;
435
+ totalCount: number;
436
+ hasMore: boolean;
437
+ goToPage: (page: number) => void;
438
+ }
439
+ /**
440
+ * Renders a filtered collection list with editing support.
441
+ *
442
+ * Each record is wrapped in CollectionContentProvider with a unique prefix
443
+ * (`{prefix}.{recordId}`) so that multiple items can be rendered and edited
444
+ * on the same page without fieldId collisions.
445
+ */
446
+ declare function CollectionList<T = Record<string, unknown>>({ collection, prefix, filters, page, pageSize, orderBy, orderDir, children, skeleton, empty, error, appId, enabled, pagination, wrapper: Wrapper, }: CollectionListProps<T>): ReactNode;
447
+
448
+ /**
449
+ * CollectionItem
450
+ *
451
+ * Renders a single collection item with editing support.
452
+ * The item is wrapped in CollectionContentProvider so YaText/YaImage
453
+ * components can read and edit collection fields.
454
+ *
455
+ * @example
456
+ * ```tsx
457
+ * // By slug with required skeleton for zero layout shift
458
+ * <CollectionItem
459
+ * collection="products"
460
+ * slugField="slug"
461
+ * slugValue="featured-guitar"
462
+ * prefix="featured"
463
+ * skeleton={<FeaturedProductSkeleton />}
464
+ * >
465
+ * {({ record, notFound }) => (
466
+ * notFound ? <NotFound /> :
467
+ * <>
468
+ * <YaImage fieldId="featured.image" />
469
+ * <YaText fieldId="featured.name" />
470
+ * </>
471
+ * )}
472
+ * </CollectionItem>
473
+ *
474
+ * // By ID (uses slug lookup with id field)
475
+ * <CollectionItem
476
+ * collection="products"
477
+ * slugField="id"
478
+ * slugValue={productId}
479
+ * prefix="product"
480
+ * skeleton={<ProductCardSkeleton />}
481
+ * >
482
+ * {({ record }) => <ProductCard />}
483
+ * </CollectionItem>
484
+ * ```
485
+ */
486
+
487
+ interface CollectionItemRenderProps<T = Record<string, unknown>> {
488
+ /** The fetched record, or null if not loaded/found */
489
+ record: CollectionRecord<T> | null;
490
+ /** Whether the fetch is in progress */
491
+ isLoading: boolean;
492
+ /** Whether the record was not found (404) */
493
+ notFound: boolean;
494
+ /** Error message if fetch failed */
495
+ error: string | null;
496
+ /** Refetch the record */
497
+ refetch: () => void;
498
+ }
499
+ interface CollectionItemProps<T = Record<string, unknown>> {
500
+ /** Collection slug (e.g., 'products', 'posts') */
501
+ collection: string;
502
+ /** Prefix for fieldIds (e.g., "featured" makes "featured.name") */
503
+ prefix: string;
504
+ /** Field name to use for lookup (e.g., 'slug', 'handle', 'id') */
505
+ slugField?: string;
506
+ /** Value to look up */
507
+ slugValue: string;
508
+ /** Render function */
509
+ children: (props: CollectionItemRenderProps<T>) => ReactNode;
510
+ /** Skeleton to show during loading (REQUIRED for zero layout shift) */
511
+ skeleton: ReactNode;
512
+ /** App ID for editing (auto-detected in builder context) */
513
+ appId?: string;
514
+ /** Whether to enable fetching (default: true) */
515
+ enabled?: boolean;
516
+ }
517
+ /**
518
+ * Renders a single collection item with editing support.
519
+ *
520
+ * The record is wrapped in CollectionContentProvider with the specified prefix
521
+ * so YaText/YaImage can read fields like `{prefix}.name`, `{prefix}.image`, etc.
522
+ */
523
+ declare function CollectionItem<T = Record<string, unknown>>({ collection, prefix, slugField, slugValue, children, skeleton, appId, enabled, }: CollectionItemProps<T>): ReactNode;
524
+
129
525
  /**
130
526
  * Animation state for a single field
131
527
  */
@@ -201,6 +597,108 @@ interface AIEditProviderProps {
201
597
  */
202
598
  declare function AIEditProvider({ children, staggerDelay }: AIEditProviderProps): react_jsx_runtime.JSX.Element;
203
599
 
600
+ /**
601
+ * useCart Hook
602
+ *
603
+ * React hook for managing shopping cart state.
604
+ * Supports both logged-in users (API persistence) and guests (localStorage fallback).
605
+ */
606
+
607
+ interface UseCartOptions {
608
+ /** App ID to scope the cart */
609
+ appId?: string;
610
+ /** App user token for authenticated users */
611
+ userToken?: string | null;
612
+ /** API base URL */
613
+ apiUrl?: string;
614
+ }
615
+ interface UseCartResult {
616
+ /** Cart items */
617
+ items: CartItem[];
618
+ /** Total number of items (sum of quantities) */
619
+ itemCount: number;
620
+ /** Whether the cart is loading */
621
+ isLoading: boolean;
622
+ /** Error message if any */
623
+ error: string | null;
624
+ /** Add an item to the cart */
625
+ addItem: (productId: string, collectionSlug: string, quantity?: number, variantId?: string, data?: Record<string, unknown>) => Promise<void>;
626
+ /** Update item quantity (0 removes the item) */
627
+ updateQuantity: (itemId: string, quantity: number) => Promise<void>;
628
+ /** Remove an item from the cart */
629
+ removeItem: (itemId: string) => Promise<void>;
630
+ /** Clear all items from the cart */
631
+ clearCart: () => Promise<void>;
632
+ /** Merge guest cart into user cart after login */
633
+ mergeGuestCart: () => Promise<void>;
634
+ /** Refresh cart from server */
635
+ refresh: () => Promise<void>;
636
+ }
637
+ /**
638
+ * Hook for managing shopping cart.
639
+ *
640
+ * @example
641
+ * ```tsx
642
+ * const {
643
+ * items,
644
+ * itemCount,
645
+ * addItem,
646
+ * removeItem,
647
+ * clearCart,
648
+ * } = useCart({ userToken: authToken })
649
+ *
650
+ * // Add item
651
+ * await addItem('product-123', 'products', 2)
652
+ *
653
+ * // Remove item
654
+ * await removeItem('item-456')
655
+ * ```
656
+ */
657
+ declare function useCart(options?: UseCartOptions): UseCartResult;
658
+
659
+ interface CartProviderProps extends UseCartOptions {
660
+ /** Child components */
661
+ children: ReactNode;
662
+ /** Callback when user token changes (for cart merge) */
663
+ onUserTokenChange?: (hasToken: boolean) => void;
664
+ }
665
+ /**
666
+ * Cart provider component.
667
+ *
668
+ * @example
669
+ * ```tsx
670
+ * // In your app root
671
+ * function App() {
672
+ * const [userToken, setUserToken] = useState<string | null>(null)
673
+ *
674
+ * return (
675
+ * <CartProvider userToken={userToken}>
676
+ * <MyApp />
677
+ * </CartProvider>
678
+ * )
679
+ * }
680
+ *
681
+ * // In any child component
682
+ * function CartIcon() {
683
+ * const { itemCount } = useCartContext()
684
+ * return <Badge count={itemCount}>Cart</Badge>
685
+ * }
686
+ * ```
687
+ */
688
+ declare function CartProvider({ children, userToken, onUserTokenChange, ...options }: CartProviderProps): react_jsx_runtime.JSX.Element;
689
+ /**
690
+ * Hook to access cart context.
691
+ * Must be used within a CartProvider.
692
+ *
693
+ * @throws Error if used outside CartProvider
694
+ */
695
+ declare function useCartContext(): UseCartResult;
696
+ /**
697
+ * Hook to access cart context with optional null return.
698
+ * Useful when cart might not be available.
699
+ */
700
+ declare function useOptionalCartContext(): UseCartResult | null;
701
+
204
702
  /**
205
703
  * Text Diffing Utilities for AI Edit Animations
206
704
  *
@@ -572,4 +1070,665 @@ interface UseSafeTriangleReturn<T extends HTMLElement, U extends HTMLElement> {
572
1070
  */
573
1071
  declare function useSafeTriangle<T extends HTMLElement = HTMLElement, U extends HTMLElement = HTMLDivElement>(options?: UseSafeTriangleOptions): UseSafeTriangleReturn<T, U>;
574
1072
 
575
- export { type AIEditContextValue, AIEditProvider, type AnimatedTextOptions, type AnimatedTextResult, type AnimationConfig, type AnimationMetadata, type AnimationOptions, type AnimationPhase, type AnimationResult, type AnimationState, type AnimationStrategy, type ContentStoreContextType, type ContentStoreMode, ContentStoreProvider, type ImageValue, type LinkValue, SafeHtml, type SafeHtmlProps, SafeTriangleBelow, type TextAnimationMetadata, type TextDiff, Tooltip, type TooltipProps, YaText, type YaTextProps, buildIntermediateText, calculateAnimationTiming, computeTextDiff, containsHtml, getTextCursorPosition, imageCrossfadeStrategy, linkTransitionStrategy, stripHtml, textTypingStrategy, useAIEditAnimation, useAIEditContext, useAIEditContextOptional, useAnimatedText, useContentStore, useSafeTriangle };
1073
+ /**
1074
+ * useContent - Unified Content Access Hook
1075
+ *
1076
+ * Provides a single API for Ya* components to access content regardless
1077
+ * of whether it comes from static content (ContentStoreProvider) or
1078
+ * collection data (CollectionContentProvider).
1079
+ *
1080
+ * @example
1081
+ * ```tsx
1082
+ * // Simple text field
1083
+ * const content = useContent<string>(fieldId)
1084
+ * const text = content.value
1085
+ *
1086
+ * // Typed image field
1087
+ * const content = useContent<ImageField>(fieldId)
1088
+ * const { src, alt } = content.value
1089
+ *
1090
+ * // Compound fields (like YaLink)
1091
+ * const textContent = useContent<string>(`${fieldId}.text`)
1092
+ * const hrefContent = useContent<string>(`${fieldId}.href`)
1093
+ * ```
1094
+ */
1095
+
1096
+ interface ContentHandle<T> {
1097
+ /** Parsed value (for object types like ImageField) */
1098
+ value: T;
1099
+ /** Get raw string value */
1100
+ get(): string;
1101
+ /** Set value with optional change source for animations */
1102
+ set(value: T | string, source?: ChangeSource): void;
1103
+ /** Persist to backend (static or collection) */
1104
+ save(): Promise<void>;
1105
+ /** Current change source (for animations: 'user' | 'ai' | 'initial') */
1106
+ changeSource: ChangeSource | undefined;
1107
+ /** Clear change source after animation completes */
1108
+ clearChangeSource(): void;
1109
+ /** Current edit mode: 'read-only' | 'inline-edit' */
1110
+ mode: EditMode;
1111
+ /** Is this field in a collection context? */
1112
+ isCollectionField: boolean;
1113
+ }
1114
+ /**
1115
+ * Unified content access hook.
1116
+ *
1117
+ * Automatically routes to the correct provider based on fieldId:
1118
+ * - If inside CollectionContentProvider and fieldId starts with prefix, uses collection context
1119
+ * - Otherwise uses ContentStoreProvider
1120
+ *
1121
+ * @param fieldId - The field identifier (e.g., "hero.title" or "product.name")
1122
+ * @returns ContentHandle<T> with value, get, set, save, and animation helpers
1123
+ */
1124
+ declare function useContent<T = string>(fieldId: string): ContentHandle<T>;
1125
+
1126
+ /** Simple text field - just a string */
1127
+ type TextField = string;
1128
+ /** Image field with metadata */
1129
+ interface ImageField {
1130
+ /** Image source URL */
1131
+ src: string;
1132
+ /** Alt text for accessibility */
1133
+ alt?: string;
1134
+ /** CSS object-fit */
1135
+ objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
1136
+ /** CSS object-position (e.g., "50% 50%", "top left") */
1137
+ objectPosition?: string;
1138
+ }
1139
+ /** Link field with text and destination */
1140
+ interface LinkField {
1141
+ /** Display text */
1142
+ text: string;
1143
+ /** URL or route path */
1144
+ href: string;
1145
+ }
1146
+ /** Video field with playback options */
1147
+ interface VideoField {
1148
+ /** Video source type */
1149
+ type: 'upload' | 'youtube' | 'vimeo';
1150
+ /** Video URL (for upload) or video ID (for embeds) */
1151
+ src: string;
1152
+ /** Poster image URL */
1153
+ poster?: string;
1154
+ /** Autoplay video (requires muted for browser policy) */
1155
+ autoplay?: boolean;
1156
+ /** Mute video audio */
1157
+ muted?: boolean;
1158
+ /** Loop video playback */
1159
+ loop?: boolean;
1160
+ /** Show video controls */
1161
+ controls?: boolean;
1162
+ /** Play inline on mobile (prevent fullscreen hijack) */
1163
+ playsinline?: boolean;
1164
+ /** Preload strategy */
1165
+ preload?: 'none' | 'metadata' | 'auto';
1166
+ /** CSS object-fit */
1167
+ objectFit?: 'cover' | 'contain' | 'fill';
1168
+ /** CSS aspect-ratio (e.g., "16/9") */
1169
+ aspectRatio?: string;
1170
+ }
1171
+ /** Embed field for iframes (YouTube, Vimeo, Spotify, etc.) */
1172
+ interface EmbedField {
1173
+ /** Embed type */
1174
+ type: 'youtube' | 'vimeo' | 'spotify' | 'soundcloud' | 'custom';
1175
+ /** Embed URL or ID */
1176
+ src: string;
1177
+ /** CSS aspect-ratio (e.g., "16/9") */
1178
+ aspectRatio?: string;
1179
+ /** Fixed height in pixels (overrides aspectRatio) */
1180
+ height?: number;
1181
+ }
1182
+ /** Container/section field for background styling */
1183
+ interface ContainerField {
1184
+ /** Background color */
1185
+ backgroundColor?: string;
1186
+ /** Background image URL */
1187
+ backgroundImage?: string;
1188
+ /** Background position */
1189
+ backgroundPosition?: string;
1190
+ /** Background size */
1191
+ backgroundSize?: 'cover' | 'contain' | 'auto';
1192
+ }
1193
+ /** All field types union */
1194
+ type AnyField = TextField | ImageField | LinkField | VideoField | EmbedField | ContainerField;
1195
+ /** Parse raw string value into typed field */
1196
+ declare function parseFieldValue<T>(raw: string | undefined): T;
1197
+ /** Stringify field value for storage */
1198
+ declare function stringifyFieldValue<T>(value: T): string;
1199
+
1200
+ /**
1201
+ * useCheckout Hook
1202
+ *
1203
+ * React hook for initiating Stripe Checkout sessions.
1204
+ */
1205
+ interface UseCheckoutOptions {
1206
+ /** App ID to scope the checkout */
1207
+ appId?: string;
1208
+ /** App user token for authenticated users */
1209
+ userToken?: string | null;
1210
+ /** API base URL */
1211
+ apiUrl?: string;
1212
+ }
1213
+ interface CheckoutOptions {
1214
+ /** URL to redirect to on successful payment */
1215
+ successUrl: string;
1216
+ /** URL to redirect to if user cancels checkout */
1217
+ cancelUrl: string;
1218
+ /** Customer email (optional, auto-filled if user is logged in) */
1219
+ customerEmail?: string;
1220
+ /** Additional metadata to attach to the order */
1221
+ metadata?: Record<string, string>;
1222
+ }
1223
+ interface CheckoutResult {
1224
+ /** Stripe Checkout Session ID */
1225
+ sessionId: string;
1226
+ /** URL to redirect to for payment */
1227
+ url: string;
1228
+ /** Order ID in our database */
1229
+ orderId: string;
1230
+ /** Human-readable order number */
1231
+ orderNumber: string;
1232
+ }
1233
+ interface UseCheckoutResult {
1234
+ /** Initiate checkout and get the checkout URL */
1235
+ initiateCheckout: (options: CheckoutOptions) => Promise<CheckoutResult>;
1236
+ /** Whether checkout is being initiated */
1237
+ isLoading: boolean;
1238
+ /** Error message if checkout failed */
1239
+ error: string | null;
1240
+ }
1241
+ /**
1242
+ * Hook for initiating Stripe Checkout.
1243
+ *
1244
+ * @example
1245
+ * ```tsx
1246
+ * const { initiateCheckout, isLoading, error } = useCheckout({ userToken: authToken })
1247
+ *
1248
+ * const handleCheckout = async () => {
1249
+ * try {
1250
+ * const result = await initiateCheckout({
1251
+ * successUrl: `${window.location.origin}/checkout/success`,
1252
+ * cancelUrl: `${window.location.origin}/cart`,
1253
+ * })
1254
+ *
1255
+ * // Redirect to Stripe Checkout
1256
+ * window.location.href = result.url
1257
+ * } catch (err) {
1258
+ * console.error('Checkout failed:', err)
1259
+ * }
1260
+ * }
1261
+ * ```
1262
+ */
1263
+ declare function useCheckout(options?: UseCheckoutOptions): UseCheckoutResult;
1264
+ interface CheckoutSessionStatus {
1265
+ sessionId: string;
1266
+ status: 'open' | 'complete' | 'expired';
1267
+ paymentStatus: 'no_payment_required' | 'paid' | 'unpaid';
1268
+ customerEmail: string | null;
1269
+ amountTotal: number | null;
1270
+ currency: string | null;
1271
+ order: {
1272
+ id: string;
1273
+ orderNumber: string;
1274
+ status: string;
1275
+ } | null;
1276
+ }
1277
+ interface UseCheckoutStatusOptions extends UseCheckoutOptions {
1278
+ /** Stripe Checkout Session ID to check */
1279
+ sessionId: string;
1280
+ /** Whether to poll for status updates */
1281
+ poll?: boolean;
1282
+ /** Polling interval in milliseconds (default: 2000) */
1283
+ pollInterval?: number;
1284
+ }
1285
+ interface UseCheckoutStatusResult {
1286
+ /** Checkout session status */
1287
+ status: CheckoutSessionStatus | null;
1288
+ /** Whether status is loading */
1289
+ isLoading: boolean;
1290
+ /** Error message if any */
1291
+ error: string | null;
1292
+ /** Refresh status */
1293
+ refresh: () => Promise<void>;
1294
+ }
1295
+ /**
1296
+ * Hook for checking Stripe Checkout session status.
1297
+ *
1298
+ * @example
1299
+ * ```tsx
1300
+ * // On success page, check if payment completed
1301
+ * const searchParams = new URLSearchParams(window.location.search)
1302
+ * const sessionId = searchParams.get('session_id')
1303
+ *
1304
+ * const { status, isLoading } = useCheckoutStatus({
1305
+ * sessionId: sessionId!,
1306
+ * poll: true,
1307
+ * })
1308
+ *
1309
+ * if (status?.paymentStatus === 'paid') {
1310
+ * // Show success message
1311
+ * }
1312
+ * ```
1313
+ */
1314
+ declare function useCheckoutStatus(options: UseCheckoutStatusOptions): UseCheckoutStatusResult;
1315
+
1316
+ /**
1317
+ * useProducts Hook
1318
+ *
1319
+ * Thin wrapper around useCollectionList for fetching products.
1320
+ * Provides product-specific filtering and types.
1321
+ */
1322
+
1323
+ interface Product {
1324
+ /** Product name */
1325
+ name: string;
1326
+ /** URL-friendly slug */
1327
+ slug?: string;
1328
+ /** Price in cents */
1329
+ price: number;
1330
+ /** Product type */
1331
+ productType: 'one_time' | 'subscription';
1332
+ /** Product status */
1333
+ status: 'draft' | 'active' | 'archived';
1334
+ /** Product images */
1335
+ images?: string[];
1336
+ /** Short description */
1337
+ description?: string;
1338
+ /** Full description/details */
1339
+ details?: string;
1340
+ /** Product category */
1341
+ category?: string;
1342
+ /** Stripe integration */
1343
+ stripe?: {
1344
+ productId?: string;
1345
+ priceId?: string;
1346
+ };
1347
+ /** Subscription details (for subscription products) */
1348
+ subscription?: {
1349
+ interval: 'month' | 'year';
1350
+ intervalCount: number;
1351
+ trialDays?: number;
1352
+ };
1353
+ /** Inventory tracking */
1354
+ inventory?: {
1355
+ trackQuantity: boolean;
1356
+ quantity: number;
1357
+ };
1358
+ /** Any additional custom fields */
1359
+ [key: string]: unknown;
1360
+ }
1361
+ interface UseProductsOptions {
1362
+ /** Collection slug where products are stored (default: 'products') */
1363
+ collection?: string;
1364
+ /** Only fetch active products (default: true) */
1365
+ activeOnly?: boolean;
1366
+ /** Filter by category */
1367
+ category?: string;
1368
+ /** Filter by product type */
1369
+ productType?: 'one_time' | 'subscription';
1370
+ /** Additional filters */
1371
+ filters?: QueryFilter[];
1372
+ /** Page number */
1373
+ page?: number;
1374
+ /** Items per page */
1375
+ pageSize?: number;
1376
+ /** Field to sort by */
1377
+ orderBy?: string;
1378
+ /** Sort direction */
1379
+ orderDir?: 'asc' | 'desc';
1380
+ /** Whether to fetch */
1381
+ enabled?: boolean;
1382
+ }
1383
+ interface UseProductsResult extends Omit<UseCollectionListResult<Product>, 'data'> {
1384
+ /** The fetched products */
1385
+ products: CollectionRecord<Product>[] | null;
1386
+ }
1387
+ interface UseProductOptions {
1388
+ /** Collection slug where products are stored (default: 'products') */
1389
+ collection?: string;
1390
+ /** Product slug to fetch */
1391
+ slug: string;
1392
+ /** Whether to fetch */
1393
+ enabled?: boolean;
1394
+ }
1395
+ interface UseProductResult {
1396
+ /** The fetched product */
1397
+ product: CollectionRecord<Product> | null;
1398
+ /** Whether the fetch is in progress */
1399
+ isLoading: boolean;
1400
+ /** Error message if fetch failed */
1401
+ error: string | null;
1402
+ /** Whether the product was not found */
1403
+ notFound: boolean;
1404
+ /** Refetch the product */
1405
+ refetch: () => void;
1406
+ }
1407
+ /**
1408
+ * Hook for fetching a list of products from a collection.
1409
+ *
1410
+ * @example
1411
+ * ```tsx
1412
+ * // Fetch all active products
1413
+ * const { products, isLoading, goToPage } = useProducts({
1414
+ * pageSize: 12,
1415
+ * })
1416
+ *
1417
+ * // Fetch products by category
1418
+ * const { products } = useProducts({
1419
+ * category: 'merch',
1420
+ * activeOnly: true,
1421
+ * })
1422
+ *
1423
+ * // Fetch subscription products only
1424
+ * const { products } = useProducts({
1425
+ * productType: 'subscription',
1426
+ * })
1427
+ * ```
1428
+ */
1429
+ declare function useProducts(options?: UseProductsOptions): UseProductsResult;
1430
+ /**
1431
+ * Hook for fetching a single product by slug.
1432
+ *
1433
+ * @example
1434
+ * ```tsx
1435
+ * const { slug } = useParams()
1436
+ * const { product, isLoading, notFound } = useProduct({ slug: slug! })
1437
+ *
1438
+ * if (notFound) {
1439
+ * return <NotFoundPage />
1440
+ * }
1441
+ *
1442
+ * if (product) {
1443
+ * return <ProductDetails product={product.data} />
1444
+ * }
1445
+ * ```
1446
+ */
1447
+ declare function useProduct(options: UseProductOptions): UseProductResult;
1448
+
1449
+ /**
1450
+ * Subscription Types
1451
+ *
1452
+ * Type definitions for subscription management in yoamigo-core.
1453
+ */
1454
+ type SubscriptionStatusType = 'active' | 'trialing' | 'past_due' | 'canceled' | 'incomplete' | 'incomplete_expired' | 'unpaid' | 'paused';
1455
+ interface SubscriptionProduct {
1456
+ id: string;
1457
+ name: string;
1458
+ description?: string;
1459
+ }
1460
+ interface SubscriptionPrice {
1461
+ id: string;
1462
+ unitAmount: number;
1463
+ currency: string;
1464
+ interval: 'day' | 'week' | 'month' | 'year';
1465
+ intervalCount: number;
1466
+ }
1467
+ interface SubscriptionDetails {
1468
+ id: string;
1469
+ status: SubscriptionStatusType;
1470
+ currentPeriodStart: string;
1471
+ currentPeriodEnd: string;
1472
+ cancelAtPeriodEnd: boolean;
1473
+ canceledAt?: string;
1474
+ endedAt?: string;
1475
+ trialStart?: string;
1476
+ trialEnd?: string;
1477
+ product: SubscriptionProduct;
1478
+ price: SubscriptionPrice;
1479
+ }
1480
+ interface SubscribeParams {
1481
+ /** Tier slug to subscribe to (e.g., "pro", "business") */
1482
+ tierSlug: string;
1483
+ /** URL to redirect to on successful subscription */
1484
+ successUrl: string;
1485
+ /** URL to redirect to if user cancels */
1486
+ cancelUrl: string;
1487
+ /** Quantity of the subscription (default: 1) */
1488
+ quantity?: number;
1489
+ /** Number of trial days (overrides price default if set) */
1490
+ trialDays?: number;
1491
+ /** Customer email (auto-filled if authenticated) */
1492
+ customerEmail?: string;
1493
+ /** Additional metadata */
1494
+ metadata?: Record<string, string>;
1495
+ }
1496
+ interface SubscribeResult {
1497
+ success: boolean;
1498
+ checkoutUrl?: string;
1499
+ sessionId?: string;
1500
+ error?: string;
1501
+ }
1502
+ interface CustomerPortalParams {
1503
+ /** URL to return to after portal session */
1504
+ returnUrl: string;
1505
+ }
1506
+ interface CustomerPortalResult {
1507
+ success: boolean;
1508
+ portalUrl?: string;
1509
+ error?: string;
1510
+ }
1511
+ interface SubscriptionStatusResult {
1512
+ success: boolean;
1513
+ status: SubscriptionStatusType | 'none';
1514
+ subscriptions?: SubscriptionDetails[];
1515
+ error?: string;
1516
+ }
1517
+
1518
+ /**
1519
+ * useSubscription Hook
1520
+ *
1521
+ * React hook for creating Stripe subscription checkout sessions.
1522
+ * Used by template websites to allow customers to subscribe to recurring products.
1523
+ *
1524
+ * Uses tier-based subscriptions - users select tiers (e.g., "pro", "business"),
1525
+ * not arbitrary price IDs. The API resolves tiers to the correct Stripe price
1526
+ * based on the environment (staging vs production).
1527
+ */
1528
+
1529
+ interface UseSubscriptionOptions {
1530
+ /** App ID to scope the subscription */
1531
+ appId?: string;
1532
+ /** App user token for authenticated users */
1533
+ userToken?: string | null;
1534
+ /** API base URL */
1535
+ apiUrl?: string;
1536
+ }
1537
+ interface UseSubscriptionResult {
1538
+ /** Create a subscription checkout session and get the checkout URL */
1539
+ subscribe: (params: SubscribeParams) => Promise<SubscribeResult>;
1540
+ /** Whether subscription checkout is being created */
1541
+ isLoading: boolean;
1542
+ /** Error message if subscription creation failed */
1543
+ error: string | null;
1544
+ }
1545
+ /**
1546
+ * Hook for creating subscription checkout sessions using tier-based pricing.
1547
+ *
1548
+ * @example
1549
+ * ```tsx
1550
+ * const { subscribe, isLoading, error } = useSubscription({ userToken: authToken })
1551
+ *
1552
+ * const handleSubscribe = async (tierSlug: string) => {
1553
+ * const result = await subscribe({
1554
+ * tierSlug, // e.g., "pro", "business"
1555
+ * // URLs are site-specific - use whatever routes your template defines
1556
+ * successUrl: `${window.location.origin}/your-success-page`,
1557
+ * cancelUrl: `${window.location.origin}/your-pricing-page`,
1558
+ * })
1559
+ *
1560
+ * if (result.success && result.checkoutUrl) {
1561
+ * window.location.href = result.checkoutUrl
1562
+ * }
1563
+ * }
1564
+ * ```
1565
+ */
1566
+ declare function useSubscription(options?: UseSubscriptionOptions): UseSubscriptionResult;
1567
+
1568
+ /**
1569
+ * useSubscriptionTiers Hook
1570
+ *
1571
+ * React hook for fetching available subscription tiers for an app.
1572
+ * Tiers are returned pre-sorted by displayOrder for easy UI rendering.
1573
+ */
1574
+ interface SubscriptionTier {
1575
+ /** Unique identifier for the tier (e.g., "pro", "business") */
1576
+ slug: string;
1577
+ /** Display name (e.g., "Pro Plan") */
1578
+ name: string;
1579
+ /** Optional description */
1580
+ description: string | null;
1581
+ /** Price in cents (e.g., 1999 = $19.99) */
1582
+ priceCents: number;
1583
+ /** Billing interval: "month" or "year" */
1584
+ billingInterval: 'month' | 'year';
1585
+ /** Interval count (e.g., 1 for monthly, 12 for yearly) */
1586
+ billingIntervalCount: number;
1587
+ /** Currency code (e.g., "usd") */
1588
+ currency: string;
1589
+ /** List of feature descriptions */
1590
+ features: string[];
1591
+ /** Whether to show "Most Popular" or similar badge */
1592
+ highlighted: boolean;
1593
+ /** Sort order for UI display */
1594
+ displayOrder: number;
1595
+ }
1596
+ interface UseSubscriptionTiersOptions {
1597
+ /** App ID to fetch tiers for */
1598
+ appId?: string;
1599
+ /** API base URL */
1600
+ apiUrl?: string;
1601
+ /** Whether to fetch tiers immediately on mount (default: true) */
1602
+ fetchOnMount?: boolean;
1603
+ }
1604
+ interface UseSubscriptionTiersResult {
1605
+ /** Available subscription tiers (sorted by displayOrder) */
1606
+ tiers: SubscriptionTier[];
1607
+ /** Whether tiers are being loaded */
1608
+ isLoading: boolean;
1609
+ /** Error message if loading failed */
1610
+ error: string | null;
1611
+ /** Manually refresh the tiers */
1612
+ refresh: () => Promise<void>;
1613
+ }
1614
+ /**
1615
+ * Hook for fetching available subscription tiers.
1616
+ *
1617
+ * @example
1618
+ * ```tsx
1619
+ * const { tiers, isLoading, error } = useSubscriptionTiers()
1620
+ *
1621
+ * if (isLoading) return <Loading />
1622
+ * if (error) return <Error message={error} />
1623
+ *
1624
+ * return (
1625
+ * <div className="pricing-grid">
1626
+ * {tiers.map(tier => (
1627
+ * <PricingCard
1628
+ * key={tier.slug}
1629
+ * tier={tier}
1630
+ * onSelect={() => handleSubscribe(tier.slug)}
1631
+ * />
1632
+ * ))}
1633
+ * </div>
1634
+ * )
1635
+ * ```
1636
+ */
1637
+ declare function useSubscriptionTiers(options?: UseSubscriptionTiersOptions): UseSubscriptionTiersResult;
1638
+
1639
+ /**
1640
+ * useCustomerPortal Hook
1641
+ *
1642
+ * React hook for creating Stripe Customer Portal sessions.
1643
+ * Allows customers to manage their subscriptions (update payment method,
1644
+ * cancel subscription, view billing history, etc.).
1645
+ */
1646
+
1647
+ interface UseCustomerPortalOptions {
1648
+ /** App ID to scope the portal */
1649
+ appId?: string;
1650
+ /** App user token for authenticated users (required for portal) */
1651
+ userToken: string;
1652
+ /** API base URL */
1653
+ apiUrl?: string;
1654
+ }
1655
+ interface UseCustomerPortalResult {
1656
+ /** Open the customer portal and get the portal URL */
1657
+ openPortal: (params: CustomerPortalParams) => Promise<CustomerPortalResult>;
1658
+ /** Whether portal session is being created */
1659
+ isLoading: boolean;
1660
+ /** Error message if portal creation failed */
1661
+ error: string | null;
1662
+ }
1663
+ /**
1664
+ * Hook for creating Stripe Customer Portal sessions.
1665
+ *
1666
+ * @example
1667
+ * ```tsx
1668
+ * const { openPortal, isLoading, error } = useCustomerPortal({ userToken: authToken })
1669
+ *
1670
+ * const handleManageSubscription = async () => {
1671
+ * const result = await openPortal({
1672
+ * returnUrl: `${window.location.origin}/account`,
1673
+ * })
1674
+ *
1675
+ * if (result.success && result.portalUrl) {
1676
+ * window.location.href = result.portalUrl
1677
+ * }
1678
+ * }
1679
+ * ```
1680
+ */
1681
+ declare function useCustomerPortal(options: UseCustomerPortalOptions): UseCustomerPortalResult;
1682
+
1683
+ /**
1684
+ * useSubscriptionStatus Hook
1685
+ *
1686
+ * React hook for fetching and polling the current user's subscription status.
1687
+ * Provides information about active subscriptions, trial periods, and billing dates.
1688
+ */
1689
+
1690
+ interface UseSubscriptionStatusOptions {
1691
+ /** App ID to scope the subscription status */
1692
+ appId?: string;
1693
+ /** App user token for authenticated users (required) */
1694
+ userToken: string;
1695
+ /** API base URL */
1696
+ apiUrl?: string;
1697
+ /** Whether to automatically fetch on mount (default: true) */
1698
+ autoFetch?: boolean;
1699
+ /** Poll interval in milliseconds (0 to disable polling, default: 0) */
1700
+ pollInterval?: number;
1701
+ }
1702
+ interface UseSubscriptionStatusResult {
1703
+ /** Aggregated subscription status ('active' if any subscription is active) */
1704
+ status: SubscriptionStatusType | 'none' | null;
1705
+ /** All subscriptions for the user */
1706
+ subscriptions: SubscriptionDetails[];
1707
+ /** Whether status is loading */
1708
+ isLoading: boolean;
1709
+ /** Error message if any */
1710
+ error: string | null;
1711
+ /** Manually refresh the subscription status */
1712
+ refresh: () => Promise<void>;
1713
+ }
1714
+ /**
1715
+ * Hook for checking the current user's subscription status.
1716
+ *
1717
+ * @example
1718
+ * ```tsx
1719
+ * const { status, subscriptions, isLoading, refresh } = useSubscriptionStatus({
1720
+ * userToken: authToken,
1721
+ * })
1722
+ *
1723
+ * if (status === 'active') {
1724
+ * // Show premium content
1725
+ * } else if (status === 'trialing') {
1726
+ * // Show trial banner with days remaining
1727
+ * } else {
1728
+ * // Show upgrade prompt
1729
+ * }
1730
+ * ```
1731
+ */
1732
+ declare function useSubscriptionStatus(options: UseSubscriptionStatusOptions): UseSubscriptionStatusResult;
1733
+
1734
+ export { type AIEditContextValue, AIEditProvider, type AnimatedTextOptions, type AnimatedTextResult, type AnimationConfig, type AnimationMetadata, type AnimationOptions, type AnimationPhase, type AnimationResult, type AnimationState, type AnimationStrategy, type AnyField, CartItem, CartProvider, type CartProviderProps, type CheckoutOptions, type CheckoutResult, type CheckoutSessionStatus, type CollectionContentContextValue, CollectionContentProvider, type CollectionContentProviderProps, type CollectionData, CollectionDetailPage, type CollectionDetailPageProps, type CollectionDetailRenderProps, CollectionItem, type CollectionItemProps, type CollectionItemRenderProps, CollectionList, type CollectionListData, CollectionListPage, type CollectionListPageProps, type CollectionListPaginationProps, type CollectionListProps, type CollectionListRenderProps, CollectionRecord, type ContainerField, type ContentHandle, type CustomerPortalParams, type CustomerPortalResult, type EmbedField, type ImageField, type ImageValue, type LinkField, type LinkValue, type Product, QueryFilter, SafeHtml, type SafeHtmlProps, SafeTriangleBelow, type SubscribeParams, type SubscribeResult, type SubscriptionDetails, type SubscriptionPrice, type SubscriptionProduct, type SubscriptionStatusResult, type SubscriptionStatusType, type SubscriptionTier, type TextAnimationMetadata, type TextDiff, type TextField, Tooltip, type TooltipProps, type UseCartOptions, type UseCartResult, type UseCheckoutOptions, type UseCheckoutResult, type UseCheckoutStatusOptions, type UseCheckoutStatusResult, type UseCollectionListOptions, type UseCollectionListResult, type UseCollectionRecordOptions, type UseCollectionRecordResult, type UseCustomerPortalOptions, type UseCustomerPortalResult, type UseProductOptions, type UseProductResult, type UseProductsOptions, type UseProductsResult, type UseSubscriptionOptions, type UseSubscriptionResult, type UseSubscriptionStatusOptions, type UseSubscriptionStatusResult, type UseSubscriptionTiersOptions, type UseSubscriptionTiersResult, type VideoField, YaText, type YaTextProps, buildIntermediateText, calculateAnimationTiming, computeTextDiff, containsHtml, getTextCursorPosition, imageCrossfadeStrategy, linkTransitionStrategy, parseFieldValue, stringifyFieldValue, stripHtml, textTypingStrategy, useAIEditAnimation, useAIEditContext, useAIEditContextOptional, useAnimatedText, useCart, useCartContext, useCheckout, useCheckoutStatus, useCollectionContent, useCollectionList, useCollectionRecord, useContent, useCustomerPortal, useOptionalCartContext, useProduct, useProducts, useSafeTriangle, useSubscription, useSubscriptionStatus, useSubscriptionTiers };