@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.
- package/README.md +313 -0
- package/dist/index.d.ts +1111 -0
- package/dist/index.js +876 -0
- package/package.json +60 -0
package/dist/index.d.ts
ADDED
|
@@ -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 };
|