@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.
@@ -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 };