@hifilabs/pixel 0.2.0 → 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 (2) hide show
  1. package/dist/index.esm.d.ts +512 -26
  2. package/package.json +1 -1
@@ -1,6 +1,110 @@
1
+ /**
2
+ * BALANCE Pixel - TypeScript Type Definitions
3
+ * @hifilabs/pixel
4
+ */
5
+
6
+ import * as React from 'react';
7
+
8
+ // ============================================
9
+ // Core Types
10
+ // ============================================
11
+
12
+ /**
13
+ * Consent preferences structure
14
+ */
15
+ export interface ConsentPreferences {
16
+ analytics: boolean;
17
+ marketing: boolean;
18
+ personalization: boolean;
19
+ timestamp: string;
20
+ ip_address?: string;
21
+ user_agent?: string;
22
+ }
23
+
24
+ /**
25
+ * Attribution data from URL parameters
26
+ */
27
+ export interface Attribution {
28
+ utm_source?: string;
29
+ utm_medium?: string;
30
+ utm_campaign?: string;
31
+ utm_content?: string;
32
+ utm_term?: string;
33
+ referrer?: string;
34
+ landing_page?: string;
35
+ [key: string]: string | undefined;
36
+ }
37
+
38
+ // ============================================
39
+ // Balance Provider & Context
40
+ // ============================================
41
+
42
+ /**
43
+ * Balance Context Value - all methods and state
44
+ */
45
+ export interface BalanceContextValue {
46
+ track: (event: string, properties?: Record<string, unknown>) => void;
47
+ identify: (email: string, traits?: Record<string, unknown>) => void;
48
+ page: (options?: { title?: string; url?: string }) => void;
49
+ purchase: (amount: number, currency?: string, properties?: Record<string, unknown>) => void;
50
+ getSessionId: () => string | null;
51
+ getFanIdHash: () => string | null;
52
+ getAttribution: () => Attribution;
53
+ setConsent: (preferences: ConsentPreferences) => void;
54
+ getConsent: () => ConsentPreferences | null;
55
+ hasConsent: (type: 'analytics' | 'marketing' | 'personalization') => boolean;
56
+ isReady: boolean;
57
+ artistId: string;
58
+ projectId?: string;
59
+ endpoint?: string;
60
+ debug: boolean;
61
+ }
62
+
63
+ /**
64
+ * Balance Provider Props
65
+ */
66
+ export interface BalanceProviderProps {
67
+ artistId: string;
68
+ projectId?: string;
69
+ debug?: boolean;
70
+ scriptUrl?: string;
71
+ endpoint?: string;
72
+ gtmId?: string;
73
+ useEmulator?: boolean;
74
+ children: React.ReactNode;
75
+ }
76
+
77
+ export declare const BalanceContext: React.Context<BalanceContextValue>;
78
+ export declare function BalanceProvider(props: BalanceProviderProps): JSX.Element;
79
+
80
+ // ============================================
81
+ // Primary Hooks
82
+ // ============================================
83
+
84
+ export declare function useBalance(): BalanceContextValue;
85
+ export declare function useBalanceOptional(): BalanceContextValue | null;
86
+ export declare function useBalanceReady(): boolean;
87
+
88
+ export interface UseBalanceConsentReturn {
89
+ consent: ConsentPreferences | null;
90
+ setConsent: (preferences: ConsentPreferences) => void;
91
+ hasConsent: (type: 'analytics' | 'marketing' | 'personalization') => boolean;
92
+ acceptAll: () => void;
93
+ declineAll: () => void;
94
+ }
95
+
96
+ export declare function useBalanceConsent(): UseBalanceConsentReturn;
97
+
98
+ // ============================================
99
+ // Components
100
+ // ============================================
101
+
1
102
  export declare function BalanceAnalytics(): null;
2
103
 
3
- // SSR-safe wrapper function type declarations
104
+ // ============================================
105
+ // SSR-safe Wrapper Functions
106
+ // ============================================
107
+
4
108
  export declare const track: (eventName: string, properties?: Record<string, any>) => void;
5
109
  export declare const identify: (email: string, traits?: Record<string, any>) => Promise<void>;
6
110
  export declare const page: (options?: { title?: string; url?: string }) => void;
@@ -8,18 +112,14 @@ export declare const purchase: (revenue: number, currency?: string, properties?:
8
112
  export declare const getSessionId: () => string | null;
9
113
  export declare const getFanIdHash: () => string | null;
10
114
  export declare const getAttribution: () => Record<string, string>;
11
- export declare const setConsent: (preferences: {
12
- analytics: boolean;
13
- marketing: boolean;
14
- personalization: boolean;
15
- timestamp: string;
16
- ip_address?: string;
17
- user_agent?: string;
18
- }) => void;
19
- export declare const getConsent: () => any;
115
+ export declare const setConsent: (preferences: ConsentPreferences) => void;
116
+ export declare const getConsent: () => ConsentPreferences | null;
20
117
  export declare const hasConsent: (type: 'analytics' | 'marketing' | 'personalization') => boolean;
21
118
 
22
- // GTM Integration Types
119
+ // ============================================
120
+ // GTM Integration
121
+ // ============================================
122
+
23
123
  export type GTMConsentState = 'granted' | 'denied';
24
124
 
25
125
  export interface GTMConsentConfig {
@@ -31,7 +131,6 @@ export interface GTMConsentConfig {
31
131
 
32
132
  export declare const DEFAULT_GTM_CONSENT: GTMConsentConfig;
33
133
 
34
- // GTMProvider Component
35
134
  export interface GTMProviderProps {
36
135
  gtmId?: string;
37
136
  children: React.ReactNode;
@@ -40,10 +139,10 @@ export interface GTMProviderProps {
40
139
 
41
140
  export declare function GTMProvider(props: GTMProviderProps): JSX.Element;
42
141
 
43
- // useGTMConsent Hook
44
142
  export interface UseGTMConsentOptions {
45
143
  pollInterval?: number;
46
144
  debug?: boolean;
145
+ enabled?: boolean;
47
146
  }
48
147
 
49
148
  export declare function useGTMConsent(options?: UseGTMConsentOptions): {
@@ -51,23 +150,19 @@ export declare function useGTMConsent(options?: UseGTMConsentOptions): {
51
150
  getConsentConfig: () => GTMConsentConfig;
52
151
  };
53
152
 
54
- // useBalanceIdentify hook - consent-aware identify wrapper
153
+ // ============================================
154
+ // useBalanceIdentify Hook
155
+ // ============================================
156
+
55
157
  export declare function useBalanceIdentify(): {
56
- /**
57
- * Identify a user with BALANCE pixel.
58
- * Handles consent checks, queuing, and storage tier automatically.
59
- * @param email - User's email address
60
- * @param traits - Optional additional user traits
61
- * @returns true if identify was called immediately, false if queued or blocked
62
- */
63
158
  identify: (email: string, traits?: Record<string, unknown>) => boolean;
64
- /**
65
- * Check if analytics consent is currently granted
66
- */
67
159
  hasAnalyticsConsent: () => boolean;
68
160
  };
69
161
 
70
- // Storage types
162
+ // ============================================
163
+ // Storage Manager
164
+ // ============================================
165
+
71
166
  export type StorageTier = 'session' | 'local';
72
167
 
73
168
  export interface StorageConfig {
@@ -75,7 +170,6 @@ export interface StorageConfig {
75
170
  tier: StorageTier;
76
171
  }
77
172
 
78
- // StorageManager class for tiered storage
79
173
  export declare class StorageManager {
80
174
  constructor(config?: Partial<StorageConfig>);
81
175
  getTier(): StorageTier;
@@ -90,3 +184,395 @@ export declare class StorageManager {
90
184
 
91
185
  export declare function getStorageManager(): StorageManager;
92
186
  export declare function initStorageWithConsent(hasAnalyticsConsent: boolean): StorageManager;
187
+
188
+ // ============================================
189
+ // useBalanceEcommerce Hook
190
+ // ============================================
191
+
192
+ export interface EcommerceProduct {
193
+ id: string;
194
+ name: string;
195
+ price: number;
196
+ currency?: string;
197
+ category?: string;
198
+ variant?: string;
199
+ quantity?: number;
200
+ brand?: string;
201
+ }
202
+
203
+ export interface CartItem extends EcommerceProduct {
204
+ quantity: number;
205
+ }
206
+
207
+ export interface UseBalanceEcommerceReturn {
208
+ viewProduct: (product: EcommerceProduct, listName?: string, position?: number) => void;
209
+ addToCart: (product: CartItem, cartTotal?: number) => void;
210
+ removeFromCart: (product: CartItem, cartTotal?: number) => void;
211
+ updateCart: (items: CartItem[], cartTotal: number) => void;
212
+ viewCart: (items: CartItem[], cartTotal: number) => void;
213
+ beginCheckout: (items: CartItem[], cartTotal: number, couponCode?: string) => void;
214
+ addPaymentInfo: (paymentMethod: string, cartTotal: number) => void;
215
+ addShippingInfo: (shippingMethod: string, cartTotal: number) => void;
216
+ completePurchase: (orderId: string, items: CartItem[], revenue: number, currency?: string, tax?: number, shipping?: number) => void;
217
+ refund: (orderId: string, amount: number, reason?: string) => void;
218
+ applyCoupon: (couponCode: string, discountAmount?: number) => void;
219
+ removeCoupon: (couponCode: string) => void;
220
+ getStats: () => { productsViewed: number; cartActions: number; checkoutsStarted: number; purchasesCompleted: number; totalRevenue: number };
221
+ reset: () => void;
222
+ }
223
+
224
+ export declare function useBalanceEcommerce(): UseBalanceEcommerceReturn;
225
+
226
+ // ============================================
227
+ // useBalanceMedia Hook
228
+ // ============================================
229
+
230
+ export interface MediaItem {
231
+ id: string;
232
+ title: string;
233
+ artist?: string;
234
+ album?: string;
235
+ genre?: string;
236
+ duration?: number;
237
+ type?: 'audio' | 'video';
238
+ }
239
+
240
+ export interface UseBalanceMediaReturn {
241
+ play: (item: MediaItem, position?: number) => void;
242
+ pause: (mediaId: string, position: number) => void;
243
+ resume: (mediaId: string, position: number) => void;
244
+ stop: (mediaId: string, position: number, completed?: boolean) => void;
245
+ seek: (mediaId: string, fromPosition: number, toPosition: number) => void;
246
+ progress: (mediaId: string, position: number, duration: number) => void;
247
+ complete: (mediaId: string) => void;
248
+ skip: (mediaId: string, position: number, direction: 'forward' | 'backward') => void;
249
+ rateChange: (mediaId: string, rate: number) => void;
250
+ volumeChange: (mediaId: string, volume: number, muted: boolean) => void;
251
+ qualityChange: (mediaId: string, quality: string) => void;
252
+ error: (mediaId: string, errorCode: string, errorMessage?: string) => void;
253
+ getStats: () => { totalPlays: number; totalListenTime: number; completions: number; currentMediaId: string | null };
254
+ reset: () => void;
255
+ }
256
+
257
+ export declare function useBalanceMedia(): UseBalanceMediaReturn;
258
+
259
+ // ============================================
260
+ // useBalanceEngagement Hook
261
+ // ============================================
262
+
263
+ export interface UseBalanceEngagementReturn {
264
+ share: (platform: string, contentType?: string) => void;
265
+ like: (contentType?: string) => void;
266
+ unlike: (contentType?: string) => void;
267
+ comment: (commentLength: number) => void;
268
+ save: (contentType?: string) => void;
269
+ trackScrollDepth: (scrollPercent: number) => void;
270
+ trackTimeOnPage: () => void;
271
+ getTimeOnPage: () => number;
272
+ click: (elementType: string, elementId?: string) => void;
273
+ copy: (textLength: number) => void;
274
+ download: (fileName: string, fileType: string) => void;
275
+ expand: (sectionName: string) => void;
276
+ reset: () => void;
277
+ }
278
+
279
+ export declare function useBalanceEngagement(contentId: string, contentTitle?: string): UseBalanceEngagementReturn;
280
+
281
+ // ============================================
282
+ // useBalanceForm Hook
283
+ // ============================================
284
+
285
+ export interface UseBalanceFormReturn {
286
+ startForm: () => void;
287
+ fieldFocus: (fieldName: string, fieldType?: string) => void;
288
+ fieldBlur: (fieldName: string, hasValue: boolean, isValid?: boolean) => void;
289
+ fieldChange: (fieldName: string, hasValue: boolean) => void;
290
+ fieldError: (fieldName: string, errorMessage: string) => void;
291
+ stepChange: (stepNumber: number, stepName?: string) => void;
292
+ submit: (success: boolean, errorMessage?: string) => void;
293
+ abandon: (lastFieldInteracted?: string) => void;
294
+ getStats: () => { fieldsInteracted: number; errorsEncountered: number; timeSpentSeconds: number; currentStep: number };
295
+ reset: () => void;
296
+ }
297
+
298
+ export declare function useBalanceForm(formId: string, formName?: string): UseBalanceFormReturn;
299
+
300
+ // ============================================
301
+ // useBalanceSearch Hook
302
+ // ============================================
303
+
304
+ export interface SearchResult {
305
+ id: string;
306
+ title: string;
307
+ type?: string;
308
+ position?: number;
309
+ }
310
+
311
+ export interface SearchFilter {
312
+ name: string;
313
+ value: string | number | boolean;
314
+ }
315
+
316
+ export interface UseBalanceSearchReturn {
317
+ search: (query: string, filters?: SearchFilter[]) => void;
318
+ searchResults: (query: string, resultCount: number, results?: SearchResult[]) => void;
319
+ searchNoResults: (query: string, filters?: SearchFilter[]) => void;
320
+ resultClick: (query: string, result: SearchResult) => void;
321
+ filterApply: (filterName: string, filterValue: string | number | boolean) => void;
322
+ filterRemove: (filterName: string) => void;
323
+ sortChange: (sortField: string, sortDirection: 'asc' | 'desc') => void;
324
+ pagination: (page: number, pageSize: number, totalResults: number) => void;
325
+ autocomplete: (partialQuery: string, suggestions: string[]) => void;
326
+ suggestionClick: (suggestion: string, position: number) => void;
327
+ searchRefine: (originalQuery: string, refinedQuery: string) => void;
328
+ getStats: () => { searches: number; resultsClicked: number; noResultSearches: number; avgResultsPerSearch: number };
329
+ reset: () => void;
330
+ }
331
+
332
+ export declare function useBalanceSearch(): UseBalanceSearchReturn;
333
+
334
+ // ============================================
335
+ // useBalanceNotification Hook
336
+ // ============================================
337
+
338
+ export type NotificationChannel = 'push' | 'email' | 'sms' | 'in_app' | 'web_push';
339
+
340
+ export interface NotificationPreference {
341
+ channel: NotificationChannel;
342
+ enabled: boolean;
343
+ frequency?: 'instant' | 'daily' | 'weekly';
344
+ }
345
+
346
+ export interface UseBalanceNotificationReturn {
347
+ permissionRequest: (channel: NotificationChannel) => void;
348
+ permissionGranted: (channel: NotificationChannel) => void;
349
+ permissionDenied: (channel: NotificationChannel, reason?: string) => void;
350
+ delivered: (notificationId: string, channel: NotificationChannel, campaignId?: string) => void;
351
+ opened: (notificationId: string, channel: NotificationChannel, campaignId?: string) => void;
352
+ clicked: (notificationId: string, channel: NotificationChannel, actionId?: string) => void;
353
+ dismissed: (notificationId: string, channel: NotificationChannel) => void;
354
+ preferencesUpdated: (preferences: NotificationPreference[]) => void;
355
+ unsubscribe: (channel: NotificationChannel, reason?: string) => void;
356
+ tokenRefresh: (channel: NotificationChannel, tokenType?: string) => void;
357
+ getStats: () => { delivered: number; opened: number; clicked: number; dismissed: number; openRate: number };
358
+ reset: () => void;
359
+ }
360
+
361
+ export declare function useBalanceNotification(): UseBalanceNotificationReturn;
362
+
363
+ // ============================================
364
+ // useBalanceSocial Hook
365
+ // ============================================
366
+
367
+ export type SocialEntityType = 'user' | 'artist' | 'playlist' | 'album' | 'post' | 'comment' | 'group' | 'event';
368
+ export type SocialActionType = 'follow' | 'unfollow' | 'block' | 'mute' | 'report';
369
+
370
+ export interface UseBalanceSocialReturn {
371
+ follow: (entityId: string, entityType: SocialEntityType, entityName?: string) => void;
372
+ unfollow: (entityId: string, entityType: SocialEntityType, reason?: string) => void;
373
+ block: (userId: string, reason?: string) => void;
374
+ unblock: (userId: string) => void;
375
+ mute: (entityId: string, entityType: SocialEntityType, duration?: number) => void;
376
+ unmute: (entityId: string, entityType: SocialEntityType) => void;
377
+ report: (entityId: string, entityType: SocialEntityType, reason: string, details?: string) => void;
378
+ share: (contentId: string, contentType: string, platform: string, method?: 'link' | 'embed' | 'native') => void;
379
+ invite: (method: 'email' | 'sms' | 'link' | 'social', recipientCount?: number) => void;
380
+ inviteAccepted: (inviteId: string, inviterId?: string) => void;
381
+ mention: (mentionedUserId: string, context: 'post' | 'comment' | 'message') => void;
382
+ tag: (taggedUserId: string, contentId: string, contentType: string) => void;
383
+ reaction: (contentId: string, contentType: string, reactionType: string) => void;
384
+ removeReaction: (contentId: string, contentType: string, reactionType: string) => void;
385
+ joinGroup: (groupId: string, groupName?: string, isPrivate?: boolean) => void;
386
+ leaveGroup: (groupId: string, reason?: string) => void;
387
+ createGroup: (groupId: string, groupName: string, isPrivate?: boolean) => void;
388
+ directMessage: (recipientId: string, hasMedia?: boolean) => void;
389
+ getStats: () => { follows: number; unfollows: number; shares: number; reactions: number; messages: number };
390
+ reset: () => void;
391
+ }
392
+
393
+ export declare function useBalanceSocial(): UseBalanceSocialReturn;
394
+
395
+ // ============================================
396
+ // useBalanceAuth Hook
397
+ // ============================================
398
+
399
+ export type AuthMethod = 'email' | 'password' | 'magic_link' | 'oauth_google' | 'oauth_apple' | 'oauth_facebook' | 'oauth_twitter' | 'oauth_spotify' | 'passkey' | 'biometric' | 'sms' | 'totp';
400
+
401
+ export interface UseBalanceAuthReturn {
402
+ loginStart: (method: AuthMethod) => void;
403
+ loginSuccess: (method: AuthMethod, isNewUser?: boolean, userId?: string) => void;
404
+ loginFailure: (method: AuthMethod, errorCode: string, errorMessage?: string) => void;
405
+ signupStart: (method: AuthMethod, source?: string) => void;
406
+ signupSuccess: (method: AuthMethod, userId?: string) => void;
407
+ signupFailure: (method: AuthMethod, errorCode: string, errorMessage?: string) => void;
408
+ logout: (reason?: 'user' | 'session_expired' | 'forced' | 'security') => void;
409
+ passwordResetRequest: (method: 'email' | 'sms') => void;
410
+ passwordResetComplete: (success: boolean) => void;
411
+ mfaChallenge: (method: 'sms' | 'totp' | 'email' | 'passkey') => void;
412
+ mfaSuccess: (method: 'sms' | 'totp' | 'email' | 'passkey') => void;
413
+ mfaFailure: (method: 'sms' | 'totp' | 'email' | 'passkey', reason?: string) => void;
414
+ mfaEnroll: (method: 'sms' | 'totp' | 'passkey') => void;
415
+ sessionRefresh: (success: boolean) => void;
416
+ accountLink: (provider: AuthMethod, success: boolean) => void;
417
+ accountUnlink: (provider: AuthMethod) => void;
418
+ profileUpdate: (fieldsUpdated: string[]) => void;
419
+ accountDelete: (reason?: string) => void;
420
+ getStats: () => { logins: number; signups: number; failures: number; mfaChallenges: number };
421
+ reset: () => void;
422
+ }
423
+
424
+ export declare function useBalanceAuth(): UseBalanceAuthReturn;
425
+
426
+ // ============================================
427
+ // useBalanceError Hook
428
+ // ============================================
429
+
430
+ export type ErrorSeverity = 'debug' | 'info' | 'warning' | 'error' | 'critical';
431
+
432
+ export type PerformanceMetricType =
433
+ | 'page_load'
434
+ | 'api_response'
435
+ | 'component_render'
436
+ | 'interaction'
437
+ | 'resource_load'
438
+ | 'long_task'
439
+ | 'first_paint'
440
+ | 'first_contentful_paint'
441
+ | 'largest_contentful_paint'
442
+ | 'first_input_delay'
443
+ | 'cumulative_layout_shift'
444
+ | 'time_to_interactive';
445
+
446
+ export interface ApiErrorDetails {
447
+ statusCode?: number;
448
+ url: string;
449
+ method?: string;
450
+ responseBody?: string;
451
+ durationMs?: number;
452
+ }
453
+
454
+ export interface UseBalanceErrorReturn {
455
+ captureError: (error: Error, context?: Record<string, unknown>, severity?: ErrorSeverity) => void;
456
+ captureApiError: (details: ApiErrorDetails, context?: Record<string, unknown>) => void;
457
+ captureUserReport: (category: string, description: string, metadata?: Record<string, unknown>) => void;
458
+ trackPerformance: (metricType: PerformanceMetricType, valueMs: number, context?: Record<string, unknown>) => void;
459
+ trackWebVitals: (vitals: { lcp?: number; fid?: number; cls?: number; fcp?: number; ttfb?: number }) => void;
460
+ captureComponentError: (error: Error, componentName: string, componentStack?: string) => void;
461
+ captureUnhandledRejection: (reason: unknown, promiseInfo?: string) => void;
462
+ captureResourceError: (resourceUrl: string, resourceType: 'script' | 'stylesheet' | 'image' | 'font' | 'other', details?: Record<string, unknown>) => void;
463
+ trackSlowInteraction: (interactionType: string, durationMs: number, targetElement?: string) => void;
464
+ startMeasure: (measureName: string) => void;
465
+ endMeasure: (measureName: string, metricType?: PerformanceMetricType) => number | null;
466
+ getStats: () => { errors: number; apiErrors: number; userReports: number; avgPageLoad: number | null };
467
+ reset: () => void;
468
+ }
469
+
470
+ export declare function useBalanceError(): UseBalanceErrorReturn;
471
+
472
+ // ============================================
473
+ // useBalanceAB Hook
474
+ // ============================================
475
+
476
+ export type ExperimentVariant = 'control' | 'A' | 'B' | 'C' | 'D' | string;
477
+ export type ExperimentStatus = 'active' | 'paused' | 'completed' | 'draft';
478
+
479
+ export interface ExperimentConfig {
480
+ id: string;
481
+ name: string;
482
+ variants: ExperimentVariant[];
483
+ trafficAllocation?: number;
484
+ audience?: string;
485
+ }
486
+
487
+ export interface FeatureFlag {
488
+ key: string;
489
+ enabled: boolean;
490
+ variant?: string;
491
+ source?: string;
492
+ }
493
+
494
+ export interface UseBalanceABReturn {
495
+ trackExposure: (experimentId: string, variant: ExperimentVariant, context?: Record<string, unknown>) => void;
496
+ trackConversion: (experimentId: string, variant: ExperimentVariant, conversionData?: Record<string, unknown>) => void;
497
+ trackInteraction: (experimentId: string, variant: ExperimentVariant, interactionType: string, details?: Record<string, unknown>) => void;
498
+ enrollUser: (experimentId: string, variant: ExperimentVariant, source?: 'random' | 'targeted' | 'override') => void;
499
+ exitExperiment: (experimentId: string, reason?: 'completed' | 'abandoned' | 'error' | 'excluded') => void;
500
+ trackFeatureFlag: (flag: FeatureFlag) => void;
501
+ trackFeatureFlagToggle: (flagKey: string, newValue: boolean, previousValue: boolean) => void;
502
+ trackGoal: (experimentId: string, goalName: string, value?: number, context?: Record<string, unknown>) => void;
503
+ trackSegment: (segmentId: string, segmentName: string, criteria?: Record<string, unknown>) => void;
504
+ getVariant: (experimentId: string) => ExperimentVariant | null;
505
+ setVariant: (experimentId: string, variant: ExperimentVariant) => void;
506
+ getActiveExperiments: () => Map<string, ExperimentVariant>;
507
+ getStats: () => { exposures: number; conversions: number; activeExperiments: number; conversionRate: number };
508
+ reset: () => void;
509
+ }
510
+
511
+ export declare function useBalanceAB(): UseBalanceABReturn;
512
+
513
+ // ============================================
514
+ // useBalanceLive Hook
515
+ // ============================================
516
+
517
+ export type StreamType = 'video' | 'audio' | 'hybrid' | 'podcast' | 'radio';
518
+ export type StreamQuality = 'auto' | '360p' | '480p' | '720p' | '1080p' | '4k' | 'audio_only';
519
+ export type ViewerInteraction = 'chat' | 'reaction' | 'tip' | 'share' | 'follow' | 'subscribe' | 'gift' | 'poll_vote' | 'question';
520
+
521
+ export interface UseBalanceLiveReturn {
522
+ joinStream: (streamId: string, streamTitle: string, artistId?: string, metadata?: Record<string, unknown>) => void;
523
+ leaveStream: (streamId: string, reason?: 'user' | 'ended' | 'error' | 'network') => void;
524
+ playbackStarted: (streamId: string, quality?: StreamQuality, latencyMs?: number) => void;
525
+ buffering: (streamId: string, durationMs: number, reason?: string) => void;
526
+ qualityChanged: (streamId: string, previousQuality: StreamQuality, newQuality: StreamQuality, isAutomatic: boolean) => void;
527
+ sendChat: (streamId: string, messageLength: number, hasEmoji?: boolean) => void;
528
+ react: (streamId: string, reactionType: string) => void;
529
+ tip: (streamId: string, amount: number, currency: string, message?: string) => void;
530
+ gift: (streamId: string, giftType: string, recipientId?: string, value?: number) => void;
531
+ pollVote: (streamId: string, pollId: string, optionId: string) => void;
532
+ submitQuestion: (streamId: string, questionId: string, isAnonymous?: boolean) => void;
533
+ share: (streamId: string, platform: string) => void;
534
+ captureClip: (streamId: string, clipDurationSeconds: number) => void;
535
+ toggleFullscreen: (streamId: string, isFullscreen: boolean) => void;
536
+ togglePiP: (streamId: string, isPiP: boolean) => void;
537
+ volumeChanged: (streamId: string, volume: number, isMuted: boolean) => void;
538
+ streamError: (streamId: string, errorCode: string, errorMessage?: string) => void;
539
+ viewerMilestone: (streamId: string, minutesWatched: number) => void;
540
+ getStats: () => { totalWatchTimeSeconds: number; messagesent: number; reactions: number; tips: number; currentStreamId: string | null };
541
+ reset: () => void;
542
+ }
543
+
544
+ export declare function useBalanceLive(): UseBalanceLiveReturn;
545
+
546
+ // ============================================
547
+ // useBalanceSubscription Hook
548
+ // ============================================
549
+
550
+ export type BillingInterval = 'daily' | 'weekly' | 'monthly' | 'quarterly' | 'yearly' | 'lifetime';
551
+ export type SubscriptionStatus = 'active' | 'trialing' | 'past_due' | 'paused' | 'canceled' | 'expired';
552
+ export type PaymentMethod = 'card' | 'paypal' | 'apple_pay' | 'google_pay' | 'bank_transfer' | 'crypto' | 'carrier_billing';
553
+ export type CancellationReason = 'too_expensive' | 'not_using' | 'missing_features' | 'found_alternative' | 'technical_issues' | 'other';
554
+
555
+ export interface UseBalanceSubscriptionReturn {
556
+ subscribe: (planId: string, planName: string, price: number, currency: string, interval: BillingInterval, paymentMethod?: PaymentMethod, trialDays?: number) => void;
557
+ startTrial: (planId: string, planName: string, trialDays: number, requiredPaymentMethod?: boolean) => void;
558
+ trialConverted: (planId: string, price: number, currency: string) => void;
559
+ trialExpired: (planId: string, converted: boolean) => void;
560
+ upgrade: (fromPlanId: string, toPlanId: string, priceDifference: number, currency: string, immediate?: boolean) => void;
561
+ downgrade: (fromPlanId: string, toPlanId: string, priceDifference: number, effectiveDate?: string) => void;
562
+ cancel: (planId: string, reason?: CancellationReason, feedback?: string, immediate?: boolean) => void;
563
+ pause: (planId: string, pauseDurationDays?: number, reason?: string) => void;
564
+ resume: (planId: string, pausedDays?: number) => void;
565
+ renewal: (planId: string, price: number, currency: string, success: boolean, failureReason?: string) => void;
566
+ paymentFailed: (planId: string, amount: number, currency: string, errorCode: string, retryCount?: number) => void;
567
+ paymentMethodUpdate: (planId: string, method: PaymentMethod, success: boolean) => void;
568
+ priceChange: (planId: string, oldPrice: number, newPrice: number, currency: string, effectiveDate: string) => void;
569
+ featureUsage: (planId: string, featureName: string, usageCount?: number, usageLimit?: number) => void;
570
+ usageLimitReached: (planId: string, featureName: string, limit: number) => void;
571
+ upsellShown: (currentPlanId: string, suggestedPlanId: string, trigger: string) => void;
572
+ upsellClicked: (currentPlanId: string, suggestedPlanId: string) => void;
573
+ upsellConverted: (fromPlanId: string, toPlanId: string, price: number, currency: string) => void;
574
+ getStats: () => { subscriptions: number; trials: number; upgrades: number; cancellations: number; totalRevenue: number };
575
+ reset: () => void;
576
+ }
577
+
578
+ export declare function useBalanceSubscription(): UseBalanceSubscriptionReturn;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hifilabs/pixel",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "BALANCE Pixel - Lightweight browser tracking script for artist fan analytics",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",