@pelatform/ui.hook 0.1.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.
@@ -0,0 +1,1111 @@
1
+ import * as React from 'react';
2
+ import React__default, { DragEvent, ChangeEvent, InputHTMLAttributes, ComponentType, SVGProps, RefObject } from 'react';
3
+
4
+ /**
5
+ * Analytics tracking hook for React components
6
+ * Provides utilities for tracking CRUD operations and user interactions
7
+ * with Google Analytics integration
8
+ */
9
+ /**
10
+ * Type definition for window with Google Analytics gtag function
11
+ * This extends the Window interface to include the gtag function
12
+ * that's injected by the Google Analytics script
13
+ * This implementation matches the global declaration in analytics.ts
14
+ */
15
+ interface GtagWindow extends Window {
16
+ gtag?: (command: "event" | "config" | "set", targetId: string, config?: Record<string, string | number | boolean | object | null | undefined>) => void;
17
+ }
18
+ /**
19
+ * Main application modules for analytics tracking
20
+ * Comprehensive SaaS platform modules
21
+ */
22
+ type ModuleType = "workspace" | "user" | "billing" | "analytics" | "integration" | "content" | "communication" | "system" | "security" | "automation" | "ecommerce";
23
+ /**
24
+ * Workspace module specific submodules
25
+ * Core workspace management functionality
26
+ */
27
+ type WorkspaceSubModuleType = "workspaces" | "projects" | "teams" | "collaboration" | "templates" | "workflows" | "dashboard" | "kanban" | "calendar" | "files";
28
+ /**
29
+ * User module specific submodules
30
+ * User management and authentication
31
+ */
32
+ type UserSubModuleType = "users" | "profiles" | "roles" | "permissions" | "groups" | "invitations" | "authentication" | "sessions" | "preferences" | "activity";
33
+ /**
34
+ * Billing module specific submodules
35
+ * Subscription and payment management
36
+ */
37
+ type BillingSubModuleType = "subscriptions" | "plans" | "invoices" | "payments" | "credits" | "usage" | "discounts" | "taxes" | "refunds" | "billing_history";
38
+ /**
39
+ * Analytics module specific submodules
40
+ * Data analytics and reporting
41
+ */
42
+ type AnalyticsSubModuleType = "reports" | "dashboards" | "metrics" | "events" | "funnels" | "cohorts" | "segments" | "exports" | "real_time" | "custom_reports";
43
+ /**
44
+ * Integration module specific submodules
45
+ * Third-party integrations and APIs
46
+ */
47
+ type IntegrationSubModuleType = "api_keys" | "webhooks" | "oauth" | "connectors" | "sync" | "imports" | "exports" | "marketplace" | "custom_integrations" | "rate_limits";
48
+ /**
49
+ * Content module specific submodules
50
+ * Content management and media
51
+ */
52
+ type ContentSubModuleType = "documents" | "media" | "assets" | "libraries" | "versions" | "comments" | "reviews" | "publishing" | "cdn" | "storage";
53
+ /**
54
+ * Communication module specific submodules
55
+ * Messaging and notification systems
56
+ */
57
+ type CommunicationSubModuleType = "notifications" | "emails" | "sms" | "chat" | "announcements" | "broadcasts" | "templates" | "campaigns" | "channels" | "delivery";
58
+ /**
59
+ * System module specific submodules
60
+ * System administration and maintenance
61
+ */
62
+ type SystemSubModuleType = "settings" | "configurations" | "logs" | "monitoring" | "backups" | "maintenance" | "health_checks" | "performance" | "database" | "cache";
63
+ /**
64
+ * Security module specific submodules
65
+ * Security and compliance features
66
+ */
67
+ type SecuritySubModuleType = "audit_logs" | "access_control" | "encryption" | "compliance" | "threats" | "vulnerabilities" | "certificates" | "firewall" | "monitoring" | "incidents";
68
+ /**
69
+ * Automation module specific submodules
70
+ * Workflow automation and triggers
71
+ */
72
+ type AutomationSubModuleType = "workflows" | "triggers" | "actions" | "conditions" | "schedules" | "pipelines" | "bots" | "scripts" | "rules" | "execution_logs";
73
+ /**
74
+ * E-commerce module specific submodules
75
+ * Online store and transaction management
76
+ */
77
+ type EcommerceSubModuleType = "products" | "categories" | "inventory" | "orders" | "customers" | "payments" | "shipping" | "discounts" | "reviews" | "analytics";
78
+ /**
79
+ * Union type of all possible submodules
80
+ * Combines all module-specific submodule types for comprehensive tracking
81
+ */
82
+ type SubModuleType = WorkspaceSubModuleType | UserSubModuleType | BillingSubModuleType | AnalyticsSubModuleType | IntegrationSubModuleType | ContentSubModuleType | CommunicationSubModuleType | SystemSubModuleType | SecuritySubModuleType | AutomationSubModuleType | EcommerceSubModuleType;
83
+ /**
84
+ * Hook for tracking analytics events in React components
85
+ *
86
+ * This hook provides methods for tracking CRUD operations
87
+ * with proper typing and structure for Google Analytics.
88
+ *
89
+ * @returns Object containing tracking methods for different CRUD operations
90
+ *
91
+ * @example
92
+ * ```tsx
93
+ * // Workspace management tracking
94
+ * function WorkspaceManagement() {
95
+ * const { trackCreate, trackUpdate, trackDelete, trackView } = useAnalytics();
96
+ *
97
+ * const handleCreateWorkspace = async (workspaceData) => {
98
+ * const workspace = await createWorkspace(workspaceData);
99
+ * trackCreate('workspace', 'workspaces', 'workspace', workspace.id);
100
+ * };
101
+ *
102
+ * const handleViewProject = (projectId) => {
103
+ * trackView('workspace', 'projects', 'project', projectId);
104
+ * };
105
+ *
106
+ * return <WorkspaceForm onSubmit={handleCreateWorkspace} />;
107
+ * }
108
+ *
109
+ * // Billing and subscription tracking
110
+ * function BillingDashboard() {
111
+ * const { trackUpdate, trackView } = useAnalytics();
112
+ *
113
+ * const handleUpgradePlan = async (planId) => {
114
+ * await upgradePlan(planId);
115
+ * trackUpdate('billing', 'subscriptions', 'plan', planId);
116
+ * };
117
+ *
118
+ * const handleViewInvoice = (invoiceId) => {
119
+ * trackView('billing', 'invoices', 'invoice', invoiceId);
120
+ * };
121
+ *
122
+ * return <BillingInterface onUpgrade={handleUpgradePlan} />;
123
+ * }
124
+ *
125
+ * // User management tracking
126
+ * function UserManagement() {
127
+ * const { trackCreate, trackUpdate } = useAnalytics();
128
+ *
129
+ * const handleInviteUser = async (email, role) => {
130
+ * const invitation = await inviteUser(email, role);
131
+ * trackCreate('user', 'invitations', 'invitation', invitation.id);
132
+ * };
133
+ *
134
+ * const handleUpdatePermissions = async (userId, permissions) => {
135
+ * await updateUserPermissions(userId, permissions);
136
+ * trackUpdate('user', 'permissions', 'permission', userId);
137
+ * };
138
+ *
139
+ * return <UserInviteForm onInvite={handleInviteUser} />;
140
+ * }
141
+ *
142
+ * // Integration and automation tracking
143
+ * function IntegrationSettings() {
144
+ * const { trackCreate, trackUpdate } = useAnalytics();
145
+ *
146
+ * const handleCreateWebhook = async (webhookData) => {
147
+ * const webhook = await createWebhook(webhookData);
148
+ * trackCreate('integration', 'webhooks', 'webhook', webhook.id);
149
+ * };
150
+ *
151
+ * const handleUpdateWorkflow = async (workflowId, updates) => {
152
+ * await updateWorkflow(workflowId, updates);
153
+ * trackUpdate('automation', 'workflows', 'workflow', workflowId);
154
+ * };
155
+ *
156
+ * return <IntegrationPanel onCreate={handleCreateWebhook} />;
157
+ * }
158
+ * ```
159
+ */
160
+ declare const useAnalytics: () => {
161
+ trackCreate: (module: ModuleType, submodule: SubModuleType, itemType: string, itemId?: string) => void;
162
+ trackUpdate: (module: ModuleType, submodule: SubModuleType, itemType: string, itemId: string) => void;
163
+ trackDelete: (module: ModuleType, submodule: SubModuleType, itemType: string, itemId: string, isHardDelete?: boolean) => void;
164
+ };
165
+
166
+ /**
167
+ * Body class management hook for React components
168
+ * Dynamically adds and removes CSS classes from the document body element
169
+ * Useful for global styling based on component state or route changes
170
+ */
171
+ /**
172
+ * Hook to dynamically add and remove CSS classes from the document body
173
+ *
174
+ * This hook automatically manages the lifecycle of body classes:
175
+ * - Adds classes when the component mounts
176
+ * - Removes classes when the component unmounts
177
+ * - Updates classes when the className prop changes
178
+ *
179
+ * @param className - Space-separated string of CSS class names to apply to body
180
+ *
181
+ * @example
182
+ * ```tsx
183
+ * // Single class
184
+ * useBodyClasses('dark-theme');
185
+ *
186
+ * // Multiple classes
187
+ * useBodyClasses('modal-open overflow-hidden');
188
+ *
189
+ * // Conditional classes
190
+ * useBodyClasses(isModalOpen ? 'modal-open' : '');
191
+ * ```
192
+ */
193
+ declare const useBodyClasses: (className: string) => void;
194
+
195
+ /**
196
+ * Clipboard copy functionality hook for React components
197
+ * Provides a simple interface for copying text to clipboard with feedback
198
+ * Includes automatic state management and timeout handling
199
+ */
200
+ /**
201
+ * Configuration options for the copy to clipboard hook
202
+ */
203
+ interface UseCopyToClipboardOptions {
204
+ /** Duration in milliseconds to show the copied state (default: 2000ms) */
205
+ timeout?: number;
206
+ /** Callback function executed after successful copy operation */
207
+ onCopy?: () => void;
208
+ }
209
+ /**
210
+ * Hook for copying text to clipboard with automatic state management
211
+ *
212
+ * Features:
213
+ * - Automatic copied state management with timeout
214
+ * - Browser compatibility checks
215
+ * - Error handling for failed copy operations
216
+ * - Optional callback for successful copies
217
+ *
218
+ * @param options - Configuration options for the hook
219
+ * @returns Object containing copied state and copy function
220
+ *
221
+ * @example
222
+ * ```tsx
223
+ * const { copied, copy } = useCopyToClipboard({
224
+ * timeout: 3000,
225
+ * onCopy: () => toast.success('Copied to clipboard!')
226
+ * });
227
+ *
228
+ * return (
229
+ * <button onClick={() => copy('Hello World')}>
230
+ * {copied ? 'Copied!' : 'Copy Text'}
231
+ * </button>
232
+ * );
233
+ * ```
234
+ */
235
+ declare function useCopyToClipboard({ timeout, onCopy, }?: UseCopyToClipboardOptions): {
236
+ /** Whether text was recently copied (true for timeout duration) */
237
+ copied: boolean;
238
+ /** Function to copy text to clipboard */
239
+ copy: (value: string) => void;
240
+ };
241
+
242
+ /**
243
+ * File upload functionality hook for React components
244
+ * Provides comprehensive file upload capabilities with drag & drop support
245
+ * Includes validation, preview generation, and state management
246
+ */
247
+
248
+ /**
249
+ * Metadata structure for uploaded files
250
+ */
251
+ interface FileMetadata {
252
+ /** The name of the file */
253
+ name: string;
254
+ /** The size of the file in bytes */
255
+ size: number;
256
+ /** The MIME type of the file */
257
+ type: string;
258
+ /** The URL where the file can be accessed */
259
+ url: string;
260
+ /** Unique identifier for the file */
261
+ id: string;
262
+ }
263
+ /**
264
+ * File object with preview capabilities
265
+ */
266
+ interface FileWithPreview {
267
+ /** The actual file object or metadata */
268
+ file: File | FileMetadata;
269
+ /** Unique identifier for the file */
270
+ id: string;
271
+ /** Optional preview URL for the file (typically for images) */
272
+ preview?: string;
273
+ }
274
+ /**
275
+ * Configuration options for the file upload hook
276
+ */
277
+ interface FileUploadOptions {
278
+ /** Maximum number of files allowed (only used when multiple is true, defaults to Infinity) */
279
+ maxFiles?: number;
280
+ /** Maximum file size in bytes (defaults to Infinity) */
281
+ maxSize?: number;
282
+ /** Accepted file types (MIME types or extensions, defaults to '*') */
283
+ accept?: string;
284
+ /** Whether multiple files can be selected (defaults to false) */
285
+ multiple?: boolean;
286
+ /** Initial files to populate the upload state */
287
+ initialFiles?: FileMetadata[];
288
+ /** Callback function executed when files change */
289
+ onFilesChange?: (files: FileWithPreview[]) => void;
290
+ /** Callback function executed when new files are added */
291
+ onFilesAdded?: (addedFiles: FileWithPreview[]) => void;
292
+ onError?: (errors: string[]) => void;
293
+ }
294
+ /**
295
+ * Current state of the file upload component
296
+ */
297
+ interface FileUploadState {
298
+ /** Array of files currently selected/uploaded */
299
+ files: FileWithPreview[];
300
+ /** Whether the user is currently dragging files over the drop zone */
301
+ isDragging: boolean;
302
+ /** Array of validation error messages */
303
+ errors: string[];
304
+ }
305
+ /**
306
+ * Actions available for file upload management
307
+ */
308
+ interface FileUploadActions {
309
+ /** Add new files to the upload state */
310
+ addFiles: (files: FileList | File[]) => void;
311
+ /** Remove a specific file by its ID */
312
+ removeFile: (id: string) => void;
313
+ /** Clear all files from the upload state */
314
+ clearFiles: () => void;
315
+ /** Clear all error messages */
316
+ clearErrors: () => void;
317
+ /** Handle drag enter event for drop zone */
318
+ handleDragEnter: (e: DragEvent<HTMLElement>) => void;
319
+ /** Handle drag leave event for drop zone */
320
+ handleDragLeave: (e: DragEvent<HTMLElement>) => void;
321
+ /** Handle drag over event for drop zone */
322
+ handleDragOver: (e: DragEvent<HTMLElement>) => void;
323
+ /** Handle drop event for drop zone */
324
+ handleDrop: (e: DragEvent<HTMLElement>) => void;
325
+ /** Handle file input change event */
326
+ handleFileChange: (e: ChangeEvent<HTMLInputElement>) => void;
327
+ /** Programmatically open the file dialog */
328
+ openFileDialog: () => void;
329
+ /** Get props for the file input element */
330
+ getInputProps: (props?: InputHTMLAttributes<HTMLInputElement>) => InputHTMLAttributes<HTMLInputElement> & {
331
+ ref: React__default.Ref<HTMLInputElement>;
332
+ };
333
+ }
334
+ /**
335
+ * Hook for comprehensive file upload functionality with drag & drop support
336
+ *
337
+ * Features:
338
+ * - Single and multiple file upload support
339
+ * - Drag and drop functionality
340
+ * - File validation (size, type, count)
341
+ * - Preview generation for images
342
+ * - Error handling and state management
343
+ * - Duplicate file detection
344
+ * - Memory cleanup for object URLs
345
+ *
346
+ * @param options - Configuration options for the file upload hook
347
+ * @returns Tuple containing current state and available actions
348
+ *
349
+ * @example
350
+ * ```tsx
351
+ * const [state, actions] = useFileUpload({
352
+ * maxFiles: 5,
353
+ * maxSize: 10 * 1024 * 1024, // 10MB
354
+ * accept: 'image/*',
355
+ * multiple: true,
356
+ * onFilesChange: (files) => console.log('Files changed:', files),
357
+ * onFilesAdded: (newFiles) => console.log('New files added:', newFiles)
358
+ * });
359
+ *
360
+ * return (
361
+ * <div
362
+ * onDragEnter={actions.handleDragEnter}
363
+ * onDragLeave={actions.handleDragLeave}
364
+ * onDragOver={actions.handleDragOver}
365
+ * onDrop={actions.handleDrop}
366
+ * >
367
+ * <input {...actions.getInputProps()} />
368
+ * <button onClick={actions.openFileDialog}>
369
+ * Upload Files
370
+ * </button>
371
+ * {state.files.map(file => (
372
+ * <div key={file.id}>
373
+ * {file.file.name}
374
+ * <button onClick={() => actions.removeFile(file.id)}>
375
+ * Remove
376
+ * </button>
377
+ * </div>
378
+ * ))}
379
+ * </div>
380
+ * );
381
+ * ```
382
+ */
383
+ declare const useFileUpload: (options?: FileUploadOptions) => [FileUploadState, FileUploadActions];
384
+ /**
385
+ * Helper function to format bytes to human-readable format
386
+ *
387
+ * @param bytes - The number of bytes to format
388
+ * @param decimals - Number of decimal places to show (default: 2)
389
+ * @returns Formatted string with appropriate unit (e.g., "1.5 MB")
390
+ *
391
+ * @example
392
+ * ```tsx
393
+ * formatBytes(1024); // "1 KB"
394
+ * formatBytes(1536, 1); // "1.5 KB"
395
+ * formatBytes(1048576); // "1 MB"
396
+ * ```
397
+ */
398
+ declare const formatBytes: (bytes: number, decimals?: number) => string;
399
+
400
+ /**
401
+ * Hook that indicates whether code is executing on the client after hydration
402
+ *
403
+ * Features:
404
+ * - SSR-safe: returns `false` on the server to avoid hydration mismatches
405
+ * - Client-stable: returns `true` after hydration and remains stable
406
+ * - Minimal overhead: uses a no-op external store subscription
407
+ *
408
+ * @returns Boolean indicating hydration state (`true` on client, `false` on server)
409
+ *
410
+ * @example
411
+ * ```tsx
412
+ * // Conditionally render client-only components safely
413
+ * function ClientOnly() {
414
+ * const hydrated = useHydrated();
415
+ * if (!hydrated) return null;
416
+ * return <InteractiveChart />;
417
+ * }
418
+ * ```
419
+ *
420
+ * @since 1.0.0
421
+ */
422
+ declare function useHydrated(): boolean;
423
+
424
+ /**
425
+ * Media query hook for responsive React components
426
+ * Provides real-time tracking of CSS media query matches
427
+ * with SSR-safe implementation and automatic cleanup
428
+ */
429
+ /**
430
+ * Hook for tracking CSS media query matches in React components
431
+ *
432
+ * Features:
433
+ * - Real-time updates when media query state changes
434
+ * - SSR-safe implementation
435
+ * - Automatic event listener cleanup
436
+ * - Supports all standard CSS media queries
437
+ *
438
+ * @param query - CSS media query string (e.g., '(min-width: 768px)')
439
+ * @returns Boolean indicating whether the media query currently matches
440
+ *
441
+ * @example
442
+ * ```tsx
443
+ * // Basic responsive behavior
444
+ * const isMobile = useMediaQuery('(max-width: 768px)');
445
+ * const isTablet = useMediaQuery('(min-width: 769px) and (max-width: 1024px)');
446
+ * const isDesktop = useMediaQuery('(min-width: 1025px)');
447
+ *
448
+ * // Dark mode preference
449
+ * const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
450
+ *
451
+ * // Reduced motion preference
452
+ * const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');
453
+ *
454
+ * return (
455
+ * <div>
456
+ * {isMobile && <MobileLayout />}
457
+ * {isTablet && <TabletLayout />}
458
+ * {isDesktop && <DesktopLayout />}
459
+ * </div>
460
+ * );
461
+ * ```
462
+ */
463
+ declare const useMediaQuery: (query: string) => boolean;
464
+
465
+ /**
466
+ * Menu navigation utilities hook for dashboard layouts
467
+ * Provides comprehensive menu state management and navigation helpers
468
+ * Handles active states, breadcrumbs, and hierarchical menu structures
469
+ */
470
+
471
+ /**
472
+ * Menu item interface
473
+ */
474
+ interface MenuItem {
475
+ /** Heading text */
476
+ heading?: string;
477
+ /** Menu item title */
478
+ title?: string;
479
+ /** Navigation path */
480
+ path?: string;
481
+ /** Menu item icon component */
482
+ icon?: ComponentType<SVGProps<SVGSVGElement>>;
483
+ /** Whether to show separator */
484
+ separator?: boolean;
485
+ /** Root path for active state matching */
486
+ rootPath?: string;
487
+ /** Child menu items */
488
+ children?: MenuConfig;
489
+ /** Children index for nested items */
490
+ childrenIndex?: number;
491
+ /** Whether the item is external */
492
+ external?: boolean;
493
+ /** Whether the item is disabled */
494
+ disabled?: boolean;
495
+ /** Disable text */
496
+ disabledText?: string;
497
+ /** Badge text */
498
+ badge?: string;
499
+ /** Badge variant */
500
+ badgeVariant?: "primary" | "destructive" | "success" | "info" | "warning" | "secondary" | "outline";
501
+ /** Collapse configuration */
502
+ collapse?: boolean;
503
+ /** Title when collapsed */
504
+ collapseTitle?: string;
505
+ /** Title when expanded */
506
+ expandTitle?: string;
507
+ }
508
+ /**
509
+ * Type aliases for backward compatibility
510
+ */
511
+ type MenuConfig = MenuItem[];
512
+ /** Return type interface for useMenu hook */
513
+ interface UseMenuReturn {
514
+ /** Check if a specific path is currently active */
515
+ isActive: (path: string | undefined) => boolean;
516
+ /** Check if any child menu item is currently active */
517
+ hasActiveChild: (children: MenuItem[] | undefined) => boolean;
518
+ /** Check if a menu item (including its children) is currently active */
519
+ isItemActive: (item: MenuItem) => boolean;
520
+ /** Get the currently active menu item from the menu configuration */
521
+ getCurrentItem: (items: MenuConfig) => MenuItem | undefined;
522
+ /** Generate breadcrumb trail for the current active path */
523
+ getBreadcrumb: (items: MenuConfig) => MenuItem[];
524
+ /** Get child menu items at a specific level for the current active path */
525
+ getChildren: (items: MenuConfig, level: number) => MenuConfig | null;
526
+ }
527
+ /**
528
+ * Hook for managing menu navigation state and utilities
529
+ *
530
+ * This hook provides comprehensive menu management functionality including:
531
+ * - Active state detection for menu items and paths
532
+ * - Hierarchical menu navigation support
533
+ * - Breadcrumb generation for current navigation path
534
+ * - Child menu extraction at specific levels
535
+ * - Support for nested menu structures
536
+ *
537
+ * @param pathname - Current pathname from router or location
538
+ * @returns Object containing menu utility functions
539
+ *
540
+ * @example
541
+ * ```tsx
542
+ * const { isActive, getBreadcrumb, getCurrentItem } = useMenu(pathname);
543
+ *
544
+ * // Check if path is active
545
+ * const isHomeActive = isActive('/dashboard');
546
+ *
547
+ * // Get breadcrumb for current path
548
+ * const breadcrumb = getBreadcrumb(menuItems);
549
+ *
550
+ * // Get current active menu item
551
+ * const currentItem = getCurrentItem(menuItems);
552
+ * ```
553
+ */
554
+ declare const useMenu: (pathname: string) => UseMenuReturn;
555
+
556
+ /**
557
+ * Mobile device detection hook for React components
558
+ * Provides real-time mobile/desktop state based on configurable viewport width breakpoint
559
+ * Uses customizable mobile breakpoint with proper SSR handling and hydration safety
560
+ */
561
+ /**
562
+ * Hook to detect if the current viewport is mobile-sized based on configurable breakpoint
563
+ *
564
+ * This hook provides real-time detection of mobile vs desktop viewports with a customizable
565
+ * breakpoint threshold. It handles SSR properly by starting with undefined state and updating
566
+ * on client-side hydration to prevent hydration mismatches.
567
+ *
568
+ * The hook uses both `matchMedia` API for efficient media query listening and `window.innerWidth`
569
+ * for consistent viewport width detection across different browsers and devices.
570
+ *
571
+ * Features:
572
+ * - Real-time viewport size tracking with media query listeners
573
+ * - SSR-safe implementation preventing hydration mismatches
574
+ * - Automatic event listener cleanup on unmount
575
+ * - Configurable mobile breakpoint with sensible default (1024px)
576
+ * - Performance optimized with proper dependency management
577
+ * - TypeScript support with proper type definitions
578
+ *
579
+ * @param breakpoint - Custom breakpoint in pixels. Viewports smaller than this value are considered mobile. Defaults to 1024px if not provided.
580
+ * @returns Boolean indicating if current viewport width is smaller than the specified breakpoint (mobile-sized)
581
+ *
582
+ * @example
583
+ * ```tsx
584
+ * // Basic usage with default breakpoint (1024px)
585
+ * function ResponsiveComponent() {
586
+ * const isMobile = useIsMobile();
587
+ *
588
+ * return (
589
+ * <div>
590
+ * {isMobile ? (
591
+ * <MobileNavigation />
592
+ * ) : (
593
+ * <DesktopNavigation />
594
+ * )}
595
+ * </div>
596
+ * );
597
+ * }
598
+ *
599
+ * // Custom breakpoint for tablet detection
600
+ * function TabletResponsiveComponent() {
601
+ * const isMobile = useIsMobile(768); // Use 768px breakpoint
602
+ * const isTablet = useIsMobile(1024); // Use 1024px for tablet detection
603
+ *
604
+ * return (
605
+ * <div className={isMobile ? 'mobile-layout' : isTablet ? 'tablet-layout' : 'desktop-layout'}>
606
+ * <Content />
607
+ * </div>
608
+ * );
609
+ * }
610
+ *
611
+ * // Conditional rendering with custom breakpoint
612
+ * function AdaptiveLayout() {
613
+ * const isSmallScreen = useIsMobile(640); // Custom small screen breakpoint
614
+ *
615
+ * return (
616
+ * <div className="container">
617
+ * {isSmallScreen ? (
618
+ * <div className="flex flex-col space-y-4">
619
+ * <MobileHeader />
620
+ * <MobileContent />
621
+ * </div>
622
+ * ) : (
623
+ * <div className="grid grid-cols-12 gap-6">
624
+ * <aside className="col-span-3">
625
+ * <Sidebar />
626
+ * </aside>
627
+ * <main className="col-span-9">
628
+ * <DesktopContent />
629
+ * </main>
630
+ * </div>
631
+ * )}
632
+ * </div>
633
+ * );
634
+ * }
635
+ *
636
+ * // Multiple breakpoints for different layouts
637
+ * function MultiBreakpointLayout() {
638
+ * const isMobile = useIsMobile(640); // Mobile: < 640px
639
+ * const isTablet = useIsMobile(1024); // Tablet: < 1024px
640
+ * const isDesktop = !isTablet; // Desktop: >= 1024px
641
+ *
642
+ * if (isMobile) {
643
+ * return <MobileLayout />;
644
+ * }
645
+ *
646
+ * if (isTablet) {
647
+ * return <TabletLayout />;
648
+ * }
649
+ *
650
+ * return <DesktopLayout />;
651
+ * }
652
+ * ```
653
+ *
654
+ * @since 1.0.0
655
+ */
656
+ declare function useIsMobile(breakpoint?: number): boolean;
657
+
658
+ /**
659
+ * Component mount state hook for React components
660
+ * Provides a reliable way to detect when a component has mounted on the client
661
+ * Essential for SSR applications to prevent hydration mismatches
662
+ */
663
+ /**
664
+ * Hook to detect when a React component has mounted on the client side
665
+ *
666
+ * This hook is essential for SSR applications where you need to conditionally
667
+ * render content only after the component has mounted on the client. It helps
668
+ * prevent hydration mismatches between server and client rendering.
669
+ *
670
+ * Features:
671
+ * - Starts with false during SSR
672
+ * - Updates to true after client-side mount
673
+ * - Prevents hydration mismatches
674
+ * - Simple boolean state management
675
+ *
676
+ * @returns Boolean indicating whether the component has mounted
677
+ *
678
+ * @example
679
+ * ```tsx
680
+ * function ClientOnlyComponent() {
681
+ * const mounted = useMounted();
682
+ *
683
+ * // Prevent rendering until mounted to avoid hydration issues
684
+ * if (!mounted) {
685
+ * return <div>Loading...</div>;
686
+ * }
687
+ *
688
+ * return (
689
+ * <div>
690
+ * <BrowserOnlyFeature />
691
+ * <LocalStorageComponent />
692
+ * </div>
693
+ * );
694
+ * }
695
+ *
696
+ * // Conditional rendering based on mount state
697
+ * function ThemeToggle() {
698
+ * const mounted = useMounted();
699
+ * const { theme, setTheme } = useTheme();
700
+ *
701
+ * // Avoid showing theme toggle until mounted
702
+ * if (!mounted) return null;
703
+ *
704
+ * return (
705
+ * <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
706
+ * Toggle Theme
707
+ * </button>
708
+ * );
709
+ * }
710
+ * ```
711
+ */
712
+ declare function useMounted(): boolean;
713
+
714
+ /**
715
+ * DOM Mutation Observer hook for React components
716
+ * Provides a React-friendly interface for observing DOM changes
717
+ * with automatic cleanup and ref integration
718
+ */
719
+
720
+ /**
721
+ * Hook to observe DOM mutations on a referenced element
722
+ *
723
+ * This hook provides a React-friendly way to use the MutationObserver API.
724
+ * It automatically handles observer creation, cleanup, and ref management.
725
+ * Useful for detecting DOM changes that occur outside of React's control.
726
+ *
727
+ * Features:
728
+ * - Automatic observer lifecycle management
729
+ * - Configurable observation options
730
+ * - Ref-based element targeting
731
+ * - Automatic cleanup on unmount
732
+ *
733
+ * @param ref - React ref pointing to the element to observe
734
+ * @param callback - Function called when mutations are detected
735
+ * @param options - MutationObserver configuration options
736
+ *
737
+ * @example
738
+ * ```tsx
739
+ * function DynamicContent() {
740
+ * const contentRef = useRef<HTMLDivElement>(null);
741
+ *
742
+ * // Watch for any changes to the content div
743
+ * useMutationObserver(
744
+ * contentRef,
745
+ * (mutations) => {
746
+ * mutations.forEach((mutation) => {
747
+ * console.log('DOM changed:', mutation.type);
748
+ * });
749
+ * }
750
+ * );
751
+ *
752
+ * return <div ref={contentRef}>Dynamic content here</div>;
753
+ * }
754
+ *
755
+ * // Watch only for attribute changes
756
+ * function AttributeWatcher() {
757
+ * const elementRef = useRef<HTMLElement>(null);
758
+ *
759
+ * useMutationObserver(
760
+ * elementRef,
761
+ * (mutations) => {
762
+ * mutations.forEach((mutation) => {
763
+ * if (mutation.type === 'attributes') {
764
+ * console.log('Attribute changed:', mutation.attributeName);
765
+ * }
766
+ * });
767
+ * },
768
+ * { attributes: true, childList: false, subtree: false }
769
+ * );
770
+ *
771
+ * return <div ref={elementRef}>Watched element</div>;
772
+ * }
773
+ * ```
774
+ */
775
+ declare const useMutationObserver: (ref: React.RefObject<HTMLElement | null>, callback: MutationCallback, options?: MutationObserverInit) => void;
776
+
777
+ /**
778
+ * Google reCAPTCHA v2 integration hook for React components
779
+ * Provides a complete solution for implementing reCAPTCHA v2 with automatic
780
+ * script loading, widget management, and token retrieval
781
+ */
782
+ /**
783
+ * Hook for integrating Google reCAPTCHA v2 into React components
784
+ *
785
+ * This hook provides a complete solution for reCAPTCHA v2 integration including:
786
+ * - Automatic script loading and initialization
787
+ * - Widget rendering and management
788
+ * - Token retrieval and validation
789
+ * - Cleanup and reset functionality
790
+ *
791
+ * @param siteKey - Your Google reCAPTCHA site key
792
+ * @returns Object containing ref, token getter, reset function, and initializer
793
+ *
794
+ * @example
795
+ * ```tsx
796
+ * function ContactForm() {
797
+ * const { containerRef, getToken, resetCaptcha } = useRecaptchaV2('your-site-key');
798
+ *
799
+ * const handleSubmit = async (e) => {
800
+ * e.preventDefault();
801
+ *
802
+ * try {
803
+ * const token = getToken();
804
+ * if (!token) {
805
+ * alert('Please complete the reCAPTCHA');
806
+ * return;
807
+ * }
808
+ *
809
+ * // Submit form with token
810
+ * await submitForm({ token, ...formData });
811
+ * resetCaptcha(); // Reset after successful submission
812
+ * } catch (error) {
813
+ * console.error('Submission failed:', error);
814
+ * }
815
+ * };
816
+ *
817
+ * return (
818
+ * <form onSubmit={handleSubmit}>
819
+ * <input type="email" placeholder="Email" />
820
+ * <div ref={containerRef}></div>
821
+ * <button type="submit">Submit</button>
822
+ * </form>
823
+ * );
824
+ * }
825
+ * ```
826
+ */
827
+ declare function useRecaptchaV2(siteKey: string): {
828
+ /** Ref to attach to the container div where reCAPTCHA will be rendered */
829
+ containerRef: React.RefObject<HTMLDivElement | null>;
830
+ /** Function to get the reCAPTCHA response token */
831
+ getToken: () => string;
832
+ /** Function to reset the reCAPTCHA widget */
833
+ resetCaptcha: () => void;
834
+ /** Function to manually initialize reCAPTCHA (usually not needed) */
835
+ initializeRecaptcha: () => Promise<void>;
836
+ };
837
+
838
+ /**
839
+ * Google Analytics linker parameter cleanup hook for React
840
+ * Safely removes the GA `_gl` query parameter from the URL after GA initialization.
841
+ */
842
+ /**
843
+ * Hook to remove the Google Analytics `_gl` query parameter from the current URL.
844
+ *
845
+ * GA's cross-domain linker temporarily appends `_gl` to URLs for attribution.
846
+ * Removing it *too early* can break attribution, so this hook waits briefly
847
+ * (≈2 seconds) to allow GA to read it, then strips the param using
848
+ * `history.replaceState` without causing a page reload or React re-render.
849
+ *
850
+ * Behavior:
851
+ * - Runs once on mount.
852
+ * - If `_gl` is present, schedules its removal after ~2000ms.
853
+ * - Uses `window.history.replaceState` to avoid navigation/re-render.
854
+ *
855
+ * @example
856
+ * ```tsx
857
+ * // app/layout.tsx or a top-level client component
858
+ * import { useRemoveGAParams } from '@/hooks/use-remove-ga-params';
859
+ *
860
+ * export default function RootLayout({ children }: { children: React.ReactNode }) {
861
+ * useRemoveGAParams();
862
+ * return <>{children}</>;
863
+ * }
864
+ * ```
865
+ */
866
+ declare function useRemoveGAParams(): void;
867
+
868
+ /**
869
+ * Scroll position tracking hook for React components
870
+ * Monitors scroll position of window or specific elements
871
+ * with real-time updates and automatic cleanup
872
+ */
873
+
874
+ /**
875
+ * Configuration options for the scroll position hook
876
+ */
877
+ interface UseScrollPositionProps {
878
+ /** Optional ref to a specific scrollable element (defaults to document) */
879
+ targetRef?: RefObject<HTMLElement | Document | undefined>;
880
+ }
881
+ /**
882
+ * Hook to track scroll position of window or specific elements
883
+ *
884
+ * This hook provides real-time tracking of scroll position with support
885
+ * for both window scrolling and element-specific scrolling. It automatically
886
+ * handles event listener management and cleanup.
887
+ *
888
+ * Features:
889
+ * - Real-time scroll position tracking
890
+ * - Support for window and element scrolling
891
+ * - Automatic event listener cleanup
892
+ * - SSR-safe implementation
893
+ * - Performance optimized
894
+ *
895
+ * @param options - Configuration options for the hook
896
+ * @returns Current scroll position in pixels
897
+ *
898
+ * @example
899
+ * ```tsx
900
+ * // Track window scroll position
901
+ * function ScrollIndicator() {
902
+ * const scrollPosition = useScrollPosition();
903
+ *
904
+ * return (
905
+ * <div className="scroll-indicator">
906
+ * Scrolled: {scrollPosition}px
907
+ * </div>
908
+ * );
909
+ * }
910
+ *
911
+ * // Track specific element scroll position
912
+ * function ScrollableContent() {
913
+ * const contentRef = useRef<HTMLDivElement>(null);
914
+ * const scrollPosition = useScrollPosition({ targetRef: contentRef });
915
+ *
916
+ * return (
917
+ * <div
918
+ * ref={contentRef}
919
+ * className="h-96 overflow-y-auto"
920
+ * >
921
+ * <div className="h-[1000px]">
922
+ * <p>Scroll position: {scrollPosition}px</p>
923
+ * <p>Long content here...</p>
924
+ * </div>
925
+ * </div>
926
+ * );
927
+ * }
928
+ *
929
+ * // Show/hide header based on scroll
930
+ * function StickyHeader() {
931
+ * const scrollPosition = useScrollPosition();
932
+ * const isVisible = scrollPosition < 100;
933
+ *
934
+ * return (
935
+ * <header className={`transition-transform ${
936
+ * isVisible ? 'translate-y-0' : '-translate-y-full'
937
+ * }`}>
938
+ * Header content
939
+ * </header>
940
+ * );
941
+ * }
942
+ * ```
943
+ */
944
+ declare const useScrollPosition: ({ targetRef, }?: UseScrollPositionProps) => number;
945
+
946
+ /**
947
+ * Dual slider input management hook for React components
948
+ * Provides synchronized state management between range slider and number inputs
949
+ * with validation and boundary enforcement
950
+ */
951
+
952
+ /**
953
+ * Configuration options for the slider input hook
954
+ */
955
+ interface UseSliderInputProps {
956
+ /** Minimum allowed value for the range */
957
+ minValue: number;
958
+ /** Maximum allowed value for the range */
959
+ maxValue: number;
960
+ /** Initial values for the range [min, max] */
961
+ initialValue: [number, number];
962
+ }
963
+ /**
964
+ * Hook for managing dual slider input with synchronized state
965
+ *
966
+ * This hook provides state management for components that need both
967
+ * a range slider and corresponding number inputs. It handles synchronization
968
+ * between the two input types, validation, and boundary enforcement.
969
+ *
970
+ * Features:
971
+ * - Synchronized slider and input values
972
+ * - Automatic validation and boundary enforcement
973
+ * - Prevents invalid range configurations (min > max)
974
+ * - Optimized with useCallback for performance
975
+ *
976
+ * @param props - Configuration options for the hook
977
+ * @returns Object containing state and handlers for slider and inputs
978
+ *
979
+ * @example
980
+ * ```tsx
981
+ * function PriceRangeFilter() {
982
+ * const {
983
+ * sliderValues,
984
+ * inputValues,
985
+ * handleSliderChange,
986
+ * handleInputChange,
987
+ * validateAndUpdateValue
988
+ * } = useSliderInput({
989
+ * minValue: 0,
990
+ * maxValue: 1000,
991
+ * initialValue: [100, 500]
992
+ * });
993
+ *
994
+ * return (
995
+ * <div className="price-range">
996
+ * <div className="inputs">
997
+ * <input
998
+ * type="number"
999
+ * value={inputValues[0]}
1000
+ * onChange={(e) => handleInputChange(e, 0)}
1001
+ * onBlur={() => validateAndUpdateValue(inputValues[0], 0)}
1002
+ * placeholder="Min price"
1003
+ * />
1004
+ * <input
1005
+ * type="number"
1006
+ * value={inputValues[1]}
1007
+ * onChange={(e) => handleInputChange(e, 1)}
1008
+ * onBlur={() => validateAndUpdateValue(inputValues[1], 1)}
1009
+ * placeholder="Max price"
1010
+ * />
1011
+ * </div>
1012
+ *
1013
+ * <Slider
1014
+ * value={sliderValues}
1015
+ * onValueChange={handleSliderChange}
1016
+ * min={0}
1017
+ * max={1000}
1018
+ * step={10}
1019
+ * />
1020
+ * </div>
1021
+ * );
1022
+ * }
1023
+ * ```
1024
+ */
1025
+ declare function useSliderInput({ minValue, maxValue, initialValue, }: UseSliderInputProps): {
1026
+ /** Function to manually set slider values */
1027
+ setSliderValues: React.Dispatch<React.SetStateAction<[number, number]>>;
1028
+ /** Function to manually set input values */
1029
+ setInputValues: React.Dispatch<React.SetStateAction<[number, number]>>;
1030
+ /** Current slider values [min, max] */
1031
+ sliderValues: [number, number];
1032
+ /** Current input values [min, max] */
1033
+ inputValues: [number, number];
1034
+ /** Handler for slider value changes */
1035
+ handleSliderChange: (values: [number, number]) => void;
1036
+ /** Handler for input field changes */
1037
+ handleInputChange: (e: React.ChangeEvent<HTMLInputElement>, index: 0 | 1) => void;
1038
+ /** Function to validate and update values from inputs */
1039
+ validateAndUpdateValue: (value: number, index: 0 | 1) => void;
1040
+ };
1041
+
1042
+ /**
1043
+ * Viewport dimensions tracking hook for React components
1044
+ * Provides real-time viewport width and height with automatic updates
1045
+ * on window resize events with SSR-safe implementation
1046
+ */
1047
+ /**
1048
+ * Type definition for viewport dimensions
1049
+ * Returns tuple of [height, width] in pixels
1050
+ */
1051
+ type ViewportDimensions = [number, number];
1052
+ /**
1053
+ * Hook to track viewport dimensions with real-time updates
1054
+ *
1055
+ * This hook provides the current viewport dimensions and automatically
1056
+ * updates when the window is resized. It's useful for responsive layouts,
1057
+ * conditional rendering based on screen size, and dynamic calculations.
1058
+ *
1059
+ * Features:
1060
+ * - Real-time viewport dimension tracking
1061
+ * - Automatic updates on window resize
1062
+ * - Performance optimized with passive event listeners
1063
+ * - SSR-safe implementation
1064
+ * - Returns both height and width
1065
+ *
1066
+ * @returns Tuple containing [height, width] in pixels
1067
+ *
1068
+ * @example
1069
+ * ```tsx
1070
+ * // Basic usage
1071
+ * function ResponsiveComponent() {
1072
+ * const [height, width] = useViewport();
1073
+ *
1074
+ * return (
1075
+ * <div>
1076
+ * <p>Viewport: {width}x{height}</p>
1077
+ * {width > 768 ? <DesktopLayout /> : <MobileLayout />}
1078
+ * </div>
1079
+ * );
1080
+ * }
1081
+ *
1082
+ * // Destructured usage
1083
+ * function ViewportInfo() {
1084
+ * const [height, width] = useViewport();
1085
+ * const aspectRatio = (width / height).toFixed(2);
1086
+ *
1087
+ * return (
1088
+ * <div className="viewport-info">
1089
+ * <p>Width: {width}px</p>
1090
+ * <p>Height: {height}px</p>
1091
+ * <p>Aspect Ratio: {aspectRatio}</p>
1092
+ * </div>
1093
+ * );
1094
+ * }
1095
+ *
1096
+ * // Conditional rendering based on viewport
1097
+ * function AdaptiveGrid() {
1098
+ * const [, width] = useViewport();
1099
+ * const columns = width > 1200 ? 4 : width > 768 ? 3 : width > 480 ? 2 : 1;
1100
+ *
1101
+ * return (
1102
+ * <div className={`grid grid-cols-${columns} gap-4`}>
1103
+ * {items.map(item => <GridItem key={item.id} {...item} />)}
1104
+ * </div>
1105
+ * );
1106
+ * }
1107
+ * ```
1108
+ */
1109
+ declare const useViewport: () => ViewportDimensions;
1110
+
1111
+ export { type FileMetadata, type FileUploadActions, type FileUploadOptions, type FileUploadState, type FileWithPreview, type GtagWindow, formatBytes, useAnalytics, useBodyClasses, useCopyToClipboard, useFileUpload, useHydrated, useIsMobile, useMediaQuery, useMenu, useMounted, useMutationObserver, useRecaptchaV2, useRemoveGAParams, useScrollPosition, useSliderInput, useViewport };