@foxpixel/react 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 +216 -0
- package/dist/index.d.mts +408 -0
- package/dist/index.d.ts +408 -0
- package/dist/index.js +495 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +448 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +39 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode, ComponentType } from 'react';
|
|
3
|
+
import { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Core types for FoxPixel React SDK
|
|
7
|
+
*/
|
|
8
|
+
interface FoxPixelConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Base URL of the FoxPixel API
|
|
11
|
+
* Default: process.env.NEXT_PUBLIC_FOXPIXEL_API_URL
|
|
12
|
+
*/
|
|
13
|
+
apiUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* API Key for authentication (server-side only)
|
|
16
|
+
* NEVER expose this in client-side code
|
|
17
|
+
* Default: process.env.FOXPIXEL_API_KEY
|
|
18
|
+
*/
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Tenant ID (optional, can be set per request)
|
|
22
|
+
*/
|
|
23
|
+
tenantId?: string;
|
|
24
|
+
}
|
|
25
|
+
interface Service {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
category?: string;
|
|
30
|
+
price?: number;
|
|
31
|
+
active: boolean;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
updatedAt: string;
|
|
34
|
+
}
|
|
35
|
+
interface ServiceCatalogResponse {
|
|
36
|
+
id: string;
|
|
37
|
+
tenantId: string;
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
unitPrice: number;
|
|
41
|
+
unitType: string;
|
|
42
|
+
currency: string;
|
|
43
|
+
category?: string;
|
|
44
|
+
isActive: boolean;
|
|
45
|
+
version: number;
|
|
46
|
+
createdAt: string;
|
|
47
|
+
updatedAt: string;
|
|
48
|
+
}
|
|
49
|
+
interface Lead {
|
|
50
|
+
id: string;
|
|
51
|
+
fullName: string;
|
|
52
|
+
email: string;
|
|
53
|
+
phone?: string;
|
|
54
|
+
source?: string;
|
|
55
|
+
status: string;
|
|
56
|
+
createdAt: string;
|
|
57
|
+
}
|
|
58
|
+
interface CreateLeadRequest {
|
|
59
|
+
fullName: string;
|
|
60
|
+
email?: string;
|
|
61
|
+
phone?: string;
|
|
62
|
+
source?: string;
|
|
63
|
+
notes?: string;
|
|
64
|
+
}
|
|
65
|
+
interface EndUser {
|
|
66
|
+
id: string;
|
|
67
|
+
email: string;
|
|
68
|
+
fullName?: string;
|
|
69
|
+
phone?: string;
|
|
70
|
+
tenantId: string;
|
|
71
|
+
subscriptionStatus: 'trial' | 'active' | 'inactive' | 'cancelled';
|
|
72
|
+
trialEndsAt?: string;
|
|
73
|
+
hasAccess: boolean;
|
|
74
|
+
[key: string]: any;
|
|
75
|
+
}
|
|
76
|
+
interface EndUserLoginRequest {
|
|
77
|
+
email: string;
|
|
78
|
+
password: string;
|
|
79
|
+
}
|
|
80
|
+
interface ApiError$1 {
|
|
81
|
+
message: string;
|
|
82
|
+
code?: string;
|
|
83
|
+
status?: number;
|
|
84
|
+
expected?: boolean;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* HTTP client for FoxPixel API
|
|
89
|
+
* Handles authentication and request/response transformation
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
declare class FoxPixelHttpClient {
|
|
93
|
+
private client;
|
|
94
|
+
private apiKey?;
|
|
95
|
+
private tenantId?;
|
|
96
|
+
private endUserToken?;
|
|
97
|
+
constructor(config: FoxPixelConfig);
|
|
98
|
+
/**
|
|
99
|
+
* Set API Key (server-side only)
|
|
100
|
+
*/
|
|
101
|
+
setApiKey(apiKey: string): void;
|
|
102
|
+
/**
|
|
103
|
+
* Set tenant ID
|
|
104
|
+
*/
|
|
105
|
+
setTenantId(tenantId: string): void;
|
|
106
|
+
/**
|
|
107
|
+
* Set end user token (for client-side auth)
|
|
108
|
+
* Note: In practice, end user auth uses httpOnly cookies
|
|
109
|
+
*/
|
|
110
|
+
setEndUserToken(token: string): void;
|
|
111
|
+
/**
|
|
112
|
+
* Clear end user token (logout)
|
|
113
|
+
*/
|
|
114
|
+
clearEndUserToken(): void;
|
|
115
|
+
/**
|
|
116
|
+
* Get underlying axios instance
|
|
117
|
+
*/
|
|
118
|
+
getInstance(): AxiosInstance;
|
|
119
|
+
/**
|
|
120
|
+
* Make GET request
|
|
121
|
+
*/
|
|
122
|
+
get<T>(url: string, config?: AxiosRequestConfig): Promise<T>;
|
|
123
|
+
/**
|
|
124
|
+
* Make POST request
|
|
125
|
+
*/
|
|
126
|
+
post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
|
|
127
|
+
/**
|
|
128
|
+
* Make PUT request
|
|
129
|
+
*/
|
|
130
|
+
put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
|
|
131
|
+
/**
|
|
132
|
+
* Make DELETE request
|
|
133
|
+
*/
|
|
134
|
+
delete<T>(url: string, config?: AxiosRequestConfig): Promise<T>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface FoxPixelContextValue {
|
|
138
|
+
client: FoxPixelHttpClient;
|
|
139
|
+
config: FoxPixelConfig;
|
|
140
|
+
}
|
|
141
|
+
interface FoxPixelProviderProps {
|
|
142
|
+
children: ReactNode;
|
|
143
|
+
config?: FoxPixelConfig;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* FoxPixelProvider - Wraps your app and provides SDK functionality
|
|
147
|
+
*
|
|
148
|
+
* IMPORTANT: API Key should NEVER be passed from client-side.
|
|
149
|
+
* Use server-side proxy (Next.js API routes) for API Key authentication.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```tsx
|
|
153
|
+
* // Client-side (no API Key)
|
|
154
|
+
* <FoxPixelProvider>
|
|
155
|
+
* <App />
|
|
156
|
+
* </FoxPixelProvider>
|
|
157
|
+
*
|
|
158
|
+
* // Server-side proxy (Next.js API route)
|
|
159
|
+
* // pages/api/foxpixel/[...path].ts
|
|
160
|
+
* export default async function handler(req, res) {
|
|
161
|
+
* const apiKey = process.env.FOXPIXEL_API_KEY;
|
|
162
|
+
* // Proxy request with API Key
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
declare function FoxPixelProvider({ children, config }: FoxPixelProviderProps): react_jsx_runtime.JSX.Element;
|
|
167
|
+
/**
|
|
168
|
+
* Hook to access FoxPixel context
|
|
169
|
+
* @throws Error if used outside FoxPixelProvider
|
|
170
|
+
*/
|
|
171
|
+
declare function useFoxPixelContext(): FoxPixelContextValue;
|
|
172
|
+
|
|
173
|
+
interface AuthContextValue {
|
|
174
|
+
user: EndUser | null;
|
|
175
|
+
isLoading: boolean;
|
|
176
|
+
isAuthenticated: boolean;
|
|
177
|
+
error: ApiError$1 | null;
|
|
178
|
+
login: (credentials: EndUserLoginRequest) => Promise<void>;
|
|
179
|
+
logout: () => Promise<void>;
|
|
180
|
+
register: (data: {
|
|
181
|
+
email: string;
|
|
182
|
+
password: string;
|
|
183
|
+
fullName: string;
|
|
184
|
+
phone?: string;
|
|
185
|
+
}) => Promise<void>;
|
|
186
|
+
updateProfile: (data: {
|
|
187
|
+
fullName?: string;
|
|
188
|
+
phone?: string;
|
|
189
|
+
}) => Promise<void>;
|
|
190
|
+
refetch: () => Promise<void>;
|
|
191
|
+
}
|
|
192
|
+
interface AuthProviderProps {
|
|
193
|
+
children: ReactNode;
|
|
194
|
+
/**
|
|
195
|
+
* Redirect path when user is not authenticated
|
|
196
|
+
* Default: '/login'
|
|
197
|
+
*/
|
|
198
|
+
loginPath?: string;
|
|
199
|
+
/**
|
|
200
|
+
* Redirect path after successful login
|
|
201
|
+
* Default: '/account'
|
|
202
|
+
*/
|
|
203
|
+
accountPath?: string;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* AuthProvider - Manages authentication state globally
|
|
207
|
+
*
|
|
208
|
+
* Automatically:
|
|
209
|
+
* - Restores session on mount (checks httpOnly cookie)
|
|
210
|
+
* - Manages user state across the app
|
|
211
|
+
* - Handles login/logout transparently
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```tsx
|
|
215
|
+
* // In _app.tsx
|
|
216
|
+
* <FoxPixelProvider>
|
|
217
|
+
* <AuthProvider>
|
|
218
|
+
* <Component {...pageProps} />
|
|
219
|
+
* </AuthProvider>
|
|
220
|
+
* </FoxPixelProvider>
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
declare function AuthProvider({ children, loginPath, accountPath }: AuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
224
|
+
/**
|
|
225
|
+
* Hook to access authentication context
|
|
226
|
+
* @throws Error if used outside AuthProvider
|
|
227
|
+
*/
|
|
228
|
+
declare function useAuth(): AuthContextValue;
|
|
229
|
+
|
|
230
|
+
interface ProtectedRouteProps {
|
|
231
|
+
children: ReactNode;
|
|
232
|
+
/**
|
|
233
|
+
* Redirect path when not authenticated
|
|
234
|
+
* Default: '/login'
|
|
235
|
+
*/
|
|
236
|
+
loginPath?: string;
|
|
237
|
+
/**
|
|
238
|
+
* Show loading spinner while checking auth
|
|
239
|
+
*/
|
|
240
|
+
loadingComponent?: ReactNode;
|
|
241
|
+
}
|
|
242
|
+
declare function ProtectedRoute({ children, loginPath, loadingComponent, }: ProtectedRouteProps): string | number | true | Iterable<ReactNode> | react_jsx_runtime.JSX.Element | null;
|
|
243
|
+
|
|
244
|
+
interface GuestOnlyRouteProps {
|
|
245
|
+
children: ReactNode;
|
|
246
|
+
/**
|
|
247
|
+
* Where to redirect when already authenticated.
|
|
248
|
+
* Default: '/account'
|
|
249
|
+
*/
|
|
250
|
+
redirectTo?: string;
|
|
251
|
+
/**
|
|
252
|
+
* Show this while checking auth or redirecting.
|
|
253
|
+
*/
|
|
254
|
+
loadingComponent?: ReactNode;
|
|
255
|
+
}
|
|
256
|
+
declare function GuestOnlyRoute({ children, redirectTo, loadingComponent, }: GuestOnlyRouteProps): string | number | true | Iterable<ReactNode> | react_jsx_runtime.JSX.Element;
|
|
257
|
+
|
|
258
|
+
interface WithAuthOptions {
|
|
259
|
+
loginPath?: string;
|
|
260
|
+
loadingComponent?: ReactNode;
|
|
261
|
+
}
|
|
262
|
+
declare function withAuth<P extends object>(Component: ComponentType<P>, options?: WithAuthOptions): (props: P) => string | number | true | Iterable<ReactNode> | react_jsx_runtime.JSX.Element | null;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Hook to fetch and manage services (Projects module)
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
interface UseServicesOptions {
|
|
269
|
+
category?: string;
|
|
270
|
+
active?: boolean;
|
|
271
|
+
}
|
|
272
|
+
interface UseServicesReturn {
|
|
273
|
+
services: ServiceCatalogResponse[] | null;
|
|
274
|
+
isLoading: boolean;
|
|
275
|
+
error: ApiError$1 | null;
|
|
276
|
+
refetch: () => Promise<void>;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Fetch services from Projects module
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```tsx
|
|
283
|
+
* function ServicesPage() {
|
|
284
|
+
* const { services, isLoading, error } = useServices({ active: true });
|
|
285
|
+
*
|
|
286
|
+
* if (isLoading) return <div>Loading...</div>;
|
|
287
|
+
* if (error) return <div>Error: {error.message}</div>;
|
|
288
|
+
*
|
|
289
|
+
* return (
|
|
290
|
+
* <div>
|
|
291
|
+
* {services?.map(service => (
|
|
292
|
+
* <ServiceCard key={service.id} service={service} />
|
|
293
|
+
* ))}
|
|
294
|
+
* </div>
|
|
295
|
+
* );
|
|
296
|
+
* }
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
declare function useServices(options?: UseServicesOptions): UseServicesReturn;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Hook to capture leads (CRM module)
|
|
303
|
+
*/
|
|
304
|
+
|
|
305
|
+
interface UseLeadCaptureReturn {
|
|
306
|
+
captureLead: (data: CreateLeadRequest) => Promise<Lead>;
|
|
307
|
+
isLoading: boolean;
|
|
308
|
+
error: ApiError$1 | null;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Capture a lead (create lead in CRM)
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```tsx
|
|
315
|
+
* function ContactForm() {
|
|
316
|
+
* const { captureLead, isLoading, error } = useLeadCapture();
|
|
317
|
+
*
|
|
318
|
+
* const handleSubmit = async (e) => {
|
|
319
|
+
* e.preventDefault();
|
|
320
|
+
* try {
|
|
321
|
+
* const lead = await captureLead({
|
|
322
|
+
* fullName: 'John Doe',
|
|
323
|
+
* email: 'john@example.com',
|
|
324
|
+
* phone: '+1234567890',
|
|
325
|
+
* source: 'website',
|
|
326
|
+
* });
|
|
327
|
+
* alert('Lead created!');
|
|
328
|
+
* } catch (err) {
|
|
329
|
+
* console.error('Error:', err);
|
|
330
|
+
* }
|
|
331
|
+
* };
|
|
332
|
+
*
|
|
333
|
+
* return <form onSubmit={handleSubmit}>...</form>;
|
|
334
|
+
* }
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
337
|
+
declare function useLeadCapture(): UseLeadCaptureReturn;
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Hook to capture contacts (CRM module)
|
|
341
|
+
*/
|
|
342
|
+
interface Contact {
|
|
343
|
+
id: string;
|
|
344
|
+
fullName: string;
|
|
345
|
+
email?: string;
|
|
346
|
+
phone?: string;
|
|
347
|
+
company?: string;
|
|
348
|
+
notes?: string;
|
|
349
|
+
postalCode?: string;
|
|
350
|
+
address?: string;
|
|
351
|
+
city?: string;
|
|
352
|
+
createdAt: string;
|
|
353
|
+
}
|
|
354
|
+
interface CreateContactRequest {
|
|
355
|
+
fullName: string;
|
|
356
|
+
email?: string;
|
|
357
|
+
phone?: string;
|
|
358
|
+
company?: string;
|
|
359
|
+
notes?: string;
|
|
360
|
+
nif?: string;
|
|
361
|
+
address?: string;
|
|
362
|
+
postalCode?: string;
|
|
363
|
+
city?: string;
|
|
364
|
+
}
|
|
365
|
+
interface ApiError {
|
|
366
|
+
message: string;
|
|
367
|
+
status?: number;
|
|
368
|
+
code?: string;
|
|
369
|
+
}
|
|
370
|
+
interface UseContactCaptureReturn {
|
|
371
|
+
captureContact: (data: CreateContactRequest) => Promise<Contact>;
|
|
372
|
+
isLoading: boolean;
|
|
373
|
+
error: ApiError | null;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Capture a contact (create contact in CRM)
|
|
377
|
+
*
|
|
378
|
+
* The frontend/SDK decides which fields to fill.
|
|
379
|
+
* This hook accepts any fields from CreateContactRequest.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```tsx
|
|
383
|
+
* function ContactForm() {
|
|
384
|
+
* const { captureContact, isLoading, error } = useContactCapture();
|
|
385
|
+
*
|
|
386
|
+
* const handleSubmit = async (e) => {
|
|
387
|
+
* e.preventDefault();
|
|
388
|
+
* try {
|
|
389
|
+
* const contact = await captureContact({
|
|
390
|
+
* fullName: 'John Doe',
|
|
391
|
+
* email: 'john@example.com',
|
|
392
|
+
* phone: '+1234567890',
|
|
393
|
+
* postalCode: '75001',
|
|
394
|
+
* notes: 'Interested in garden maintenance',
|
|
395
|
+
* });
|
|
396
|
+
* alert('Contact created!');
|
|
397
|
+
* } catch (err) {
|
|
398
|
+
* console.error('Error:', err);
|
|
399
|
+
* }
|
|
400
|
+
* };
|
|
401
|
+
*
|
|
402
|
+
* return <form onSubmit={handleSubmit}>...</form>;
|
|
403
|
+
* }
|
|
404
|
+
* ```
|
|
405
|
+
*/
|
|
406
|
+
declare function useContactCapture(): UseContactCaptureReturn;
|
|
407
|
+
|
|
408
|
+
export { type ApiError$1 as ApiError, AuthProvider, type CreateLeadRequest, type EndUser, type EndUserLoginRequest, type FoxPixelConfig, FoxPixelHttpClient, FoxPixelProvider, GuestOnlyRoute, type Lead, ProtectedRoute, type Service, type ServiceCatalogResponse, useAuth, useContactCapture, useFoxPixelContext, useLeadCapture, useServices, withAuth };
|