@demokit-ai/react 0.3.0 → 0.4.1
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/dist/banner.d.ts +26 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/context.d.ts +7 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/guard.d.ts +59 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/hooks.d.ts +59 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/index.cjs +67 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +23 -460
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +65 -27
- package/dist/index.js.map +1 -1
- package/dist/powered-by.d.ts +46 -0
- package/dist/powered-by.d.ts.map +1 -0
- package/dist/provider.d.ts +50 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/toggle.d.ts +76 -0
- package/dist/toggle.d.ts.map +1 -0
- package/dist/types.d.ts +229 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +20 -30
- package/LICENSE +0 -190
- package/dist/index.d.cts +0 -480
package/dist/index.d.ts
CHANGED
|
@@ -1,480 +1,43 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import * as _demokit_ai_core from '@demokit-ai/core';
|
|
3
|
-
import { FixtureMap, CloudFixtureResponse, SessionState } from '@demokit-ai/core';
|
|
4
|
-
export { FixtureHandler, FixtureMap, RequestContext, SessionState } from '@demokit-ai/core';
|
|
5
|
-
import * as react from 'react';
|
|
6
|
-
import { ReactNode, CSSProperties } from 'react';
|
|
7
|
-
|
|
8
1
|
/**
|
|
9
|
-
*
|
|
2
|
+
* @demokit-ai/react
|
|
10
3
|
*
|
|
11
|
-
*
|
|
12
|
-
* 1. **Local mode**: Provide `fixtures` prop with pattern handlers
|
|
13
|
-
* 2. **Remote mode**: Provide `apiKey` to fetch from DemoKit Cloud
|
|
4
|
+
* React bindings for DemoKit - provider, hooks, and components.
|
|
14
5
|
*
|
|
15
|
-
* @example
|
|
16
|
-
*
|
|
17
|
-
* <DemoKitProvider fixtures={{ 'GET /api/users': () => [] }}>
|
|
18
|
-
* <App />
|
|
19
|
-
* </DemoKitProvider>
|
|
20
|
-
* ```
|
|
21
|
-
*
|
|
22
|
-
* @example Remote mode (zero-config)
|
|
23
|
-
* ```tsx
|
|
24
|
-
* <DemoKitProvider apiKey="dk_live_xxx">
|
|
25
|
-
* <App />
|
|
26
|
-
* </DemoKitProvider>
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* @example Remote mode with local overrides
|
|
30
|
-
* ```tsx
|
|
31
|
-
* <DemoKitProvider
|
|
32
|
-
* apiKey="dk_live_xxx"
|
|
33
|
-
* fixtures={{ 'POST /api/users': ({ body }) => ({ id: 'custom', ...body }) }}
|
|
34
|
-
* >
|
|
35
|
-
* <App />
|
|
36
|
-
* </DemoKitProvider>
|
|
37
|
-
* ```
|
|
38
|
-
*/
|
|
39
|
-
interface DemoKitProviderProps {
|
|
40
|
-
/**
|
|
41
|
-
* Child components to render
|
|
42
|
-
*/
|
|
43
|
-
children: ReactNode;
|
|
44
|
-
/**
|
|
45
|
-
* Map of URL patterns to fixture handlers (local mode)
|
|
46
|
-
* In remote mode, these act as overrides for cloud fixtures
|
|
47
|
-
*/
|
|
48
|
-
fixtures?: FixtureMap;
|
|
49
|
-
/**
|
|
50
|
-
* DemoKit Cloud API key for remote mode
|
|
51
|
-
* Format: dk_live_xxxx
|
|
52
|
-
*
|
|
53
|
-
* When provided, fixtures are fetched from DemoKit Cloud.
|
|
54
|
-
* Any `fixtures` prop values will override the cloud fixtures.
|
|
55
|
-
*/
|
|
56
|
-
apiKey?: string;
|
|
57
|
-
/**
|
|
58
|
-
* DemoKit Cloud API URL
|
|
59
|
-
* @default 'https://api.demokit.cloud'
|
|
60
|
-
*/
|
|
61
|
-
cloudUrl?: string;
|
|
62
|
-
/**
|
|
63
|
-
* Timeout for cloud API requests in milliseconds
|
|
64
|
-
* @default 10000
|
|
65
|
-
*/
|
|
66
|
-
timeout?: number;
|
|
67
|
-
/**
|
|
68
|
-
* Whether to retry on fetch failure
|
|
69
|
-
* @default true
|
|
70
|
-
*/
|
|
71
|
-
retry?: boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Maximum number of retries for cloud fetch
|
|
74
|
-
* @default 3
|
|
75
|
-
*/
|
|
76
|
-
maxRetries?: number;
|
|
77
|
-
/**
|
|
78
|
-
* Callback when remote fixtures are successfully loaded
|
|
79
|
-
*/
|
|
80
|
-
onRemoteLoad?: (response: CloudFixtureResponse) => void;
|
|
81
|
-
/**
|
|
82
|
-
* Callback when remote fetch fails
|
|
83
|
-
*/
|
|
84
|
-
onRemoteError?: (error: Error) => void;
|
|
85
|
-
/**
|
|
86
|
-
* Content to render while loading remote fixtures
|
|
87
|
-
* @default null (renders nothing while loading)
|
|
88
|
-
*/
|
|
89
|
-
loadingFallback?: ReactNode;
|
|
90
|
-
/**
|
|
91
|
-
* Content to render when remote fetch fails
|
|
92
|
-
* If not provided, children are rendered (with local fixtures only if provided)
|
|
93
|
-
*/
|
|
94
|
-
errorFallback?: ReactNode | ((error: Error) => ReactNode);
|
|
95
|
-
/**
|
|
96
|
-
* localStorage key for persisting demo mode state
|
|
97
|
-
* @default 'demokit-mode'
|
|
98
|
-
*/
|
|
99
|
-
storageKey?: string;
|
|
100
|
-
/**
|
|
101
|
-
* Whether demo mode should be initially enabled
|
|
102
|
-
* If not provided, will read from localStorage
|
|
103
|
-
* @default false
|
|
104
|
-
*/
|
|
105
|
-
initialEnabled?: boolean;
|
|
106
|
-
/**
|
|
107
|
-
* Callback invoked when demo mode state changes
|
|
108
|
-
*/
|
|
109
|
-
onDemoModeChange?: (enabled: boolean) => void;
|
|
110
|
-
/**
|
|
111
|
-
* Base URL to use for relative URL parsing
|
|
112
|
-
* @default 'http://localhost'
|
|
113
|
-
*/
|
|
114
|
-
baseUrl?: string;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Value provided by the DemoMode context
|
|
118
|
-
*/
|
|
119
|
-
interface DemoModeContextValue {
|
|
120
|
-
/**
|
|
121
|
-
* Whether demo mode is currently enabled
|
|
122
|
-
*/
|
|
123
|
-
isDemoMode: boolean;
|
|
124
|
-
/**
|
|
125
|
-
* Whether the component has hydrated (for SSR safety)
|
|
126
|
-
* Always check this before rendering demo-dependent UI
|
|
127
|
-
*/
|
|
128
|
-
isHydrated: boolean;
|
|
129
|
-
/**
|
|
130
|
-
* Whether remote fixtures are currently being loaded
|
|
131
|
-
* Only relevant when apiKey is provided
|
|
132
|
-
*/
|
|
133
|
-
isLoading: boolean;
|
|
134
|
-
/**
|
|
135
|
-
* Error that occurred during remote fetch
|
|
136
|
-
* Only set when apiKey is provided and fetch fails
|
|
137
|
-
*/
|
|
138
|
-
remoteError: Error | null;
|
|
139
|
-
/**
|
|
140
|
-
* Version identifier from the loaded cloud fixtures
|
|
141
|
-
* Useful for cache invalidation and debugging
|
|
142
|
-
*/
|
|
143
|
-
remoteVersion: string | null;
|
|
144
|
-
/**
|
|
145
|
-
* Enable demo mode
|
|
146
|
-
*/
|
|
147
|
-
enable(): void;
|
|
148
|
-
/**
|
|
149
|
-
* Disable demo mode
|
|
150
|
-
*/
|
|
151
|
-
disable(): void;
|
|
152
|
-
/**
|
|
153
|
-
* Toggle demo mode and return the new state
|
|
154
|
-
*/
|
|
155
|
-
toggle(): void;
|
|
156
|
-
/**
|
|
157
|
-
* Set demo mode to a specific state
|
|
158
|
-
*/
|
|
159
|
-
setDemoMode(enabled: boolean): void;
|
|
160
|
-
/**
|
|
161
|
-
* Reset the session state, clearing all stored data
|
|
162
|
-
* Call this to manually reset the demo session without page refresh
|
|
163
|
-
*/
|
|
164
|
-
resetSession(): void;
|
|
165
|
-
/**
|
|
166
|
-
* Get the current session state instance
|
|
167
|
-
* Useful for inspecting or manipulating session state directly
|
|
168
|
-
* Returns null if the interceptor hasn't been initialized yet
|
|
169
|
-
*/
|
|
170
|
-
getSession(): SessionState | null;
|
|
171
|
-
/**
|
|
172
|
-
* Refetch fixtures from DemoKit Cloud
|
|
173
|
-
* Only works when apiKey is provided
|
|
174
|
-
* Returns a promise that resolves when the fetch completes
|
|
175
|
-
*/
|
|
176
|
-
refetch(): Promise<void>;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Props for the DemoModeBanner component
|
|
180
|
-
*/
|
|
181
|
-
interface DemoModeBannerProps {
|
|
182
|
-
/**
|
|
183
|
-
* Additional CSS class name
|
|
184
|
-
*/
|
|
185
|
-
className?: string;
|
|
186
|
-
/**
|
|
187
|
-
* Label for the exit button
|
|
188
|
-
* @default 'Exit Demo Mode'
|
|
189
|
-
*/
|
|
190
|
-
exitLabel?: string;
|
|
191
|
-
/**
|
|
192
|
-
* Label shown when demo mode is active
|
|
193
|
-
* @default 'Demo Mode Active'
|
|
194
|
-
*/
|
|
195
|
-
demoLabel?: string;
|
|
196
|
-
/**
|
|
197
|
-
* Description shown in the banner
|
|
198
|
-
* @default 'Changes are simulated and not saved'
|
|
199
|
-
*/
|
|
200
|
-
description?: string;
|
|
201
|
-
/**
|
|
202
|
-
* Whether to show the eye icon
|
|
203
|
-
* @default true
|
|
204
|
-
*/
|
|
205
|
-
showIcon?: boolean;
|
|
206
|
-
/**
|
|
207
|
-
* Show "Powered by DemoKit" branding
|
|
208
|
-
* Note: For OSS users, this is always true regardless of the prop value.
|
|
209
|
-
* Only paid DemoKit Cloud users can hide the branding.
|
|
210
|
-
* @default true
|
|
211
|
-
*/
|
|
212
|
-
showPoweredBy?: boolean;
|
|
213
|
-
/**
|
|
214
|
-
* URL for the "Powered by" link
|
|
215
|
-
* @default 'https://demokit.ai'
|
|
216
|
-
*/
|
|
217
|
-
poweredByUrl?: string;
|
|
218
|
-
/**
|
|
219
|
-
* Custom styles for the banner container
|
|
220
|
-
*/
|
|
221
|
-
style?: React.CSSProperties;
|
|
222
|
-
/**
|
|
223
|
-
* Callback when exit button is clicked
|
|
224
|
-
* If not provided, will call disable() from context
|
|
225
|
-
*/
|
|
226
|
-
onExit?: () => void;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Provider component that enables demo mode functionality
|
|
231
|
-
*
|
|
232
|
-
* Wraps your app to provide demo mode state and controls.
|
|
233
|
-
* Handles SSR hydration safely and persists state to localStorage.
|
|
234
|
-
*
|
|
235
|
-
* Supports two modes:
|
|
236
|
-
* 1. **Local mode**: Pass `fixtures` prop with pattern handlers
|
|
237
|
-
* 2. **Remote mode**: Pass `apiKey` to fetch from DemoKit Cloud
|
|
6
|
+
* @example
|
|
7
|
+
* import { DemoKitProvider, useDemoMode, DemoModeBanner } from '@demokit-ai/react'
|
|
238
8
|
*
|
|
239
|
-
* @example Local mode
|
|
240
|
-
* ```tsx
|
|
241
9
|
* const fixtures = {
|
|
242
10
|
* 'GET /api/users': () => [{ id: '1', name: 'Demo User' }],
|
|
243
|
-
* 'GET /api/users/:id': ({ params }) => ({ id: params.id, name: 'Demo User' }),
|
|
244
11
|
* }
|
|
245
12
|
*
|
|
246
13
|
* function App() {
|
|
247
14
|
* return (
|
|
248
15
|
* <DemoKitProvider fixtures={fixtures}>
|
|
16
|
+
* <DemoModeBanner />
|
|
249
17
|
* <YourApp />
|
|
250
18
|
* </DemoKitProvider>
|
|
251
19
|
* )
|
|
252
20
|
* }
|
|
253
|
-
* ```
|
|
254
|
-
*
|
|
255
|
-
* @example Remote mode (zero-config)
|
|
256
|
-
* ```tsx
|
|
257
|
-
* function App() {
|
|
258
|
-
* return (
|
|
259
|
-
* <DemoKitProvider
|
|
260
|
-
* apiKey="dk_live_xxx"
|
|
261
|
-
* loadingFallback={<LoadingSpinner />}
|
|
262
|
-
* >
|
|
263
|
-
* <YourApp />
|
|
264
|
-
* </DemoKitProvider>
|
|
265
|
-
* )
|
|
266
|
-
* }
|
|
267
|
-
* ```
|
|
268
|
-
*/
|
|
269
|
-
declare function DemoKitProvider({ children, fixtures, apiKey, cloudUrl, timeout, retry, maxRetries, onRemoteLoad, onRemoteError, loadingFallback, errorFallback, storageKey, initialEnabled, onDemoModeChange, baseUrl, }: DemoKitProviderProps): react_jsx_runtime.JSX.Element;
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Hook to access demo mode state and controls
|
|
273
|
-
*
|
|
274
|
-
* @returns Demo mode context value with state and control methods
|
|
275
|
-
* @throws Error if used outside of DemoKitProvider
|
|
276
21
|
*
|
|
277
|
-
*
|
|
22
|
+
* // In any component
|
|
278
23
|
* function MyComponent() {
|
|
279
24
|
* const { isDemoMode, isHydrated, toggle } = useDemoMode()
|
|
280
|
-
*
|
|
281
|
-
* // Wait for hydration before rendering demo-dependent UI
|
|
282
|
-
* if (!isHydrated) {
|
|
283
|
-
* return <Loading />
|
|
284
|
-
* }
|
|
285
|
-
*
|
|
286
|
-
* return (
|
|
287
|
-
* <div>
|
|
288
|
-
* <p>Demo mode: {isDemoMode ? 'ON' : 'OFF'}</p>
|
|
289
|
-
* <button onClick={toggle}>Toggle</button>
|
|
290
|
-
* </div>
|
|
291
|
-
* )
|
|
292
|
-
* }
|
|
293
|
-
*/
|
|
294
|
-
declare function useDemoMode(): DemoModeContextValue;
|
|
295
|
-
/**
|
|
296
|
-
* Hook to check if demo mode is enabled
|
|
297
|
-
* Shorthand for useDemoMode().isDemoMode
|
|
298
|
-
*
|
|
299
|
-
* @returns Whether demo mode is enabled
|
|
300
|
-
*/
|
|
301
|
-
declare function useIsDemoMode(): boolean;
|
|
302
|
-
/**
|
|
303
|
-
* Hook to check if the component has hydrated
|
|
304
|
-
* Shorthand for useDemoMode().isHydrated
|
|
305
|
-
*
|
|
306
|
-
* @returns Whether the component has hydrated
|
|
307
|
-
*/
|
|
308
|
-
declare function useIsHydrated(): boolean;
|
|
309
|
-
/**
|
|
310
|
-
* Hook to access the session state
|
|
311
|
-
* Shorthand for useDemoMode().getSession()
|
|
312
|
-
*
|
|
313
|
-
* @returns The session state, or null if not yet initialized
|
|
314
|
-
*
|
|
315
|
-
* @example
|
|
316
|
-
* function MyComponent() {
|
|
317
|
-
* const session = useDemoSession()
|
|
318
|
-
*
|
|
319
|
-
* const cart = session?.get<CartItem[]>('cart') || []
|
|
320
|
-
* const addToCart = (item: CartItem) => {
|
|
321
|
-
* session?.set('cart', [...cart, item])
|
|
322
|
-
* }
|
|
323
|
-
*
|
|
324
|
-
* return <CartView items={cart} onAdd={addToCart} />
|
|
25
|
+
* // ...
|
|
325
26
|
* }
|
|
326
|
-
*/
|
|
327
|
-
declare function useDemoSession(): _demokit_ai_core.SessionState | null;
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* A ready-to-use banner component that shows when demo mode is active
|
|
331
|
-
*
|
|
332
|
-
* Displays a prominent amber banner with a label, description, and exit button.
|
|
333
|
-
* Automatically hides when demo mode is disabled or before hydration.
|
|
334
|
-
*
|
|
335
|
-
* @example
|
|
336
|
-
* function App() {
|
|
337
|
-
* return (
|
|
338
|
-
* <DemoKitProvider fixtures={fixtures}>
|
|
339
|
-
* <DemoModeBanner />
|
|
340
|
-
* <YourApp />
|
|
341
|
-
* </DemoKitProvider>
|
|
342
|
-
* )
|
|
343
|
-
* }
|
|
344
|
-
*
|
|
345
|
-
* @example Custom labels
|
|
346
|
-
* <DemoModeBanner
|
|
347
|
-
* demoLabel="Preview Mode"
|
|
348
|
-
* description="You're viewing sample data"
|
|
349
|
-
* exitLabel="Exit Preview"
|
|
350
|
-
* />
|
|
351
|
-
*/
|
|
352
|
-
declare function DemoModeBanner({ className, exitLabel, demoLabel, description, showIcon, showPoweredBy, poweredByUrl, style, onExit, }: DemoModeBannerProps): react_jsx_runtime.JSX.Element | null;
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Props for the DemoModeToggle component
|
|
356
|
-
*/
|
|
357
|
-
interface DemoModeToggleProps {
|
|
358
|
-
/**
|
|
359
|
-
* Show "Demo Mode" label next to the toggle
|
|
360
|
-
* @default true
|
|
361
|
-
*/
|
|
362
|
-
showLabel?: boolean;
|
|
363
|
-
/**
|
|
364
|
-
* Label text to display
|
|
365
|
-
* @default 'Demo Mode'
|
|
366
|
-
*/
|
|
367
|
-
label?: string;
|
|
368
|
-
/**
|
|
369
|
-
* Show "Powered by DemoKit" branding
|
|
370
|
-
* Note: For OSS users, this is always true regardless of the prop value.
|
|
371
|
-
* Only paid DemoKit Cloud users can hide the branding.
|
|
372
|
-
* @default true
|
|
373
|
-
*/
|
|
374
|
-
showPoweredBy?: boolean;
|
|
375
|
-
/**
|
|
376
|
-
* URL for the "Powered by" link
|
|
377
|
-
* @default 'https://demokit.ai'
|
|
378
|
-
*/
|
|
379
|
-
poweredByUrl?: string;
|
|
380
|
-
/**
|
|
381
|
-
* Position of the toggle
|
|
382
|
-
* - 'inline': Renders where placed in the component tree
|
|
383
|
-
* - 'floating': Fixed position, can be moved around
|
|
384
|
-
* - 'corner': Fixed to bottom-right corner
|
|
385
|
-
* @default 'inline'
|
|
386
|
-
*/
|
|
387
|
-
position?: 'inline' | 'floating' | 'corner';
|
|
388
|
-
/**
|
|
389
|
-
* Size of the toggle
|
|
390
|
-
* @default 'md'
|
|
391
|
-
*/
|
|
392
|
-
size?: 'sm' | 'md' | 'lg';
|
|
393
|
-
/**
|
|
394
|
-
* Additional CSS class name
|
|
395
|
-
*/
|
|
396
|
-
className?: string;
|
|
397
|
-
/**
|
|
398
|
-
* Custom styles
|
|
399
|
-
*/
|
|
400
|
-
style?: CSSProperties;
|
|
401
|
-
/**
|
|
402
|
-
* Callback when toggle state changes
|
|
403
|
-
*/
|
|
404
|
-
onChange?: (enabled: boolean) => void;
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* A toggle switch component for enabling/disabling demo mode
|
|
408
|
-
*
|
|
409
|
-
* Supports inline placement or fixed positioning (floating/corner).
|
|
410
|
-
* Includes optional "Powered by DemoKit" branding that is always shown for OSS users.
|
|
411
|
-
*
|
|
412
|
-
* @example Basic inline usage
|
|
413
|
-
* <DemoModeToggle />
|
|
414
27
|
*
|
|
415
|
-
* @
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
*/
|
|
432
|
-
interface PoweredByBadgeProps {
|
|
433
|
-
/**
|
|
434
|
-
* URL to link to when clicked
|
|
435
|
-
* @default 'https://demokit.ai'
|
|
436
|
-
*/
|
|
437
|
-
url?: string;
|
|
438
|
-
/**
|
|
439
|
-
* Visual variant for light/dark backgrounds
|
|
440
|
-
* @default 'auto'
|
|
441
|
-
*/
|
|
442
|
-
variant?: 'light' | 'dark' | 'auto';
|
|
443
|
-
/**
|
|
444
|
-
* Size of the badge
|
|
445
|
-
* @default 'sm'
|
|
446
|
-
*/
|
|
447
|
-
size?: 'xs' | 'sm' | 'md';
|
|
448
|
-
/**
|
|
449
|
-
* Additional CSS class name
|
|
450
|
-
*/
|
|
451
|
-
className?: string;
|
|
452
|
-
/**
|
|
453
|
-
* Custom styles
|
|
454
|
-
*/
|
|
455
|
-
style?: CSSProperties;
|
|
456
|
-
}
|
|
457
|
-
/**
|
|
458
|
-
* A "Powered by DemoKit" badge that links to demokit.ai
|
|
459
|
-
*
|
|
460
|
-
* This badge is shown by default for OSS users and cannot be hidden
|
|
461
|
-
* without a valid DemoKit Cloud paid plan.
|
|
462
|
-
*
|
|
463
|
-
* @example
|
|
464
|
-
* <PoweredByBadge />
|
|
465
|
-
*
|
|
466
|
-
* @example With dark theme
|
|
467
|
-
* <PoweredByBadge variant="dark" />
|
|
468
|
-
*
|
|
469
|
-
* @example Small size
|
|
470
|
-
* <PoweredByBadge size="xs" />
|
|
471
|
-
*/
|
|
472
|
-
declare function PoweredByBadge({ url, variant, size, className, style, }: PoweredByBadgeProps): react_jsx_runtime.JSX.Element;
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* React context for demo mode state
|
|
476
|
-
* @internal
|
|
477
|
-
*/
|
|
478
|
-
declare const DemoModeContext: react.Context<DemoModeContextValue | undefined>;
|
|
479
|
-
|
|
480
|
-
export { DemoKitProvider, type DemoKitProviderProps, DemoModeBanner, type DemoModeBannerProps, DemoModeContext, type DemoModeContextValue, DemoModeToggle, type DemoModeToggleProps, PoweredByBadge, type PoweredByBadgeProps, useDemoMode, useDemoSession, useIsDemoMode, useIsHydrated };
|
|
28
|
+
* @packageDocumentation
|
|
29
|
+
*/
|
|
30
|
+
export { DemoKitProvider } from './provider';
|
|
31
|
+
export { createRemoteSource } from './config';
|
|
32
|
+
export { useDemoMode, useIsDemoMode, useIsHydrated, useDemoSession } from './hooks';
|
|
33
|
+
export { useDemoGuard } from './guard';
|
|
34
|
+
export { DemoModeBanner } from './banner';
|
|
35
|
+
export { DemoModeToggle } from './toggle';
|
|
36
|
+
export { PoweredByBadge } from './powered-by';
|
|
37
|
+
export { DemoModeContext } from './context';
|
|
38
|
+
export type { DemoKitProviderProps, DemoModeContextValue, DemoModeBannerProps, } from './types';
|
|
39
|
+
export type { UseDemoGuardOptions, DemoGuardReturn } from './guard';
|
|
40
|
+
export type { DemoModeToggleProps } from './toggle';
|
|
41
|
+
export type { PoweredByBadgeProps } from './powered-by';
|
|
42
|
+
export type { FixtureMap, FixtureHandler, RequestContext, SessionState, RemoteConfig, DetectionConfig, MutationInterceptedContext, } from '@demokit-ai/core';
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAG5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAG7C,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACnF,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAGtC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAG7C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAG3C,YAAY,EACV,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAGhB,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAGnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AAGvD,YAAY,EACV,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,0BAA0B,GAC3B,MAAM,kBAAkB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -17,11 +17,7 @@ function DemoKitProvider({
|
|
|
17
17
|
children,
|
|
18
18
|
fixtures,
|
|
19
19
|
// Remote config
|
|
20
|
-
|
|
21
|
-
cloudUrl,
|
|
22
|
-
timeout,
|
|
23
|
-
retry,
|
|
24
|
-
maxRetries,
|
|
20
|
+
source,
|
|
25
21
|
onRemoteLoad,
|
|
26
22
|
onRemoteError,
|
|
27
23
|
loadingFallback = null,
|
|
@@ -30,11 +26,16 @@ function DemoKitProvider({
|
|
|
30
26
|
storageKey = "demokit-mode",
|
|
31
27
|
initialEnabled = false,
|
|
32
28
|
onDemoModeChange,
|
|
33
|
-
baseUrl
|
|
29
|
+
baseUrl,
|
|
30
|
+
// Detection & guards
|
|
31
|
+
detection,
|
|
32
|
+
canDisable,
|
|
33
|
+
onMutationIntercepted
|
|
34
34
|
}) {
|
|
35
35
|
const [isDemoMode, setIsDemoMode] = useState(initialEnabled);
|
|
36
36
|
const [isHydrated, setIsHydrated] = useState(false);
|
|
37
|
-
const [
|
|
37
|
+
const [isPublicDemo, setIsPublicDemo] = useState(false);
|
|
38
|
+
const [isLoading, setIsLoading] = useState(!!source?.apiKey);
|
|
38
39
|
const [remoteError, setRemoteError] = useState(null);
|
|
39
40
|
const [remoteVersion, setRemoteVersion] = useState(null);
|
|
40
41
|
const interceptorRef = useRef(null);
|
|
@@ -49,6 +50,9 @@ function DemoKitProvider({
|
|
|
49
50
|
storageKey,
|
|
50
51
|
initialEnabled,
|
|
51
52
|
baseUrl,
|
|
53
|
+
detection,
|
|
54
|
+
canDisable,
|
|
55
|
+
onMutationIntercepted,
|
|
52
56
|
onEnable: () => {
|
|
53
57
|
setIsDemoMode(true);
|
|
54
58
|
onDemoModeChange?.(true);
|
|
@@ -60,21 +64,22 @@ function DemoKitProvider({
|
|
|
60
64
|
});
|
|
61
65
|
const storedState = interceptorRef.current.isEnabled();
|
|
62
66
|
setIsDemoMode(storedState);
|
|
67
|
+
setIsPublicDemo(interceptorRef.current.isPublicDemo());
|
|
63
68
|
setIsHydrated(true);
|
|
64
69
|
},
|
|
65
|
-
[storageKey, initialEnabled, baseUrl, onDemoModeChange]
|
|
70
|
+
[storageKey, initialEnabled, baseUrl, onDemoModeChange, detection, canDisable, onMutationIntercepted]
|
|
66
71
|
);
|
|
67
72
|
const fetchAndSetup = useCallback(async () => {
|
|
68
|
-
if (!apiKey) return;
|
|
73
|
+
if (!source?.apiKey) return;
|
|
69
74
|
setIsLoading(true);
|
|
70
75
|
setRemoteError(null);
|
|
71
76
|
try {
|
|
72
77
|
const response = await fetchCloudFixtures({
|
|
73
|
-
apiKey,
|
|
74
|
-
|
|
75
|
-
timeout,
|
|
76
|
-
retry,
|
|
77
|
-
maxRetries,
|
|
78
|
+
apiKey: source.apiKey,
|
|
79
|
+
apiUrl: source.apiUrl,
|
|
80
|
+
timeout: source.timeout,
|
|
81
|
+
retry: source.retry,
|
|
82
|
+
maxRetries: source.maxRetries,
|
|
78
83
|
onLoad: onRemoteLoad,
|
|
79
84
|
onError: onRemoteError
|
|
80
85
|
});
|
|
@@ -95,11 +100,7 @@ function DemoKitProvider({
|
|
|
95
100
|
setIsLoading(false);
|
|
96
101
|
}
|
|
97
102
|
}, [
|
|
98
|
-
|
|
99
|
-
cloudUrl,
|
|
100
|
-
timeout,
|
|
101
|
-
retry,
|
|
102
|
-
maxRetries,
|
|
103
|
+
source,
|
|
103
104
|
fixtures,
|
|
104
105
|
onRemoteLoad,
|
|
105
106
|
onRemoteError,
|
|
@@ -111,7 +112,7 @@ function DemoKitProvider({
|
|
|
111
112
|
return;
|
|
112
113
|
}
|
|
113
114
|
initializedRef.current = true;
|
|
114
|
-
if (apiKey) {
|
|
115
|
+
if (source?.apiKey) {
|
|
115
116
|
fetchAndSetup();
|
|
116
117
|
} else if (fixtures) {
|
|
117
118
|
setupInterceptor(fixtures);
|
|
@@ -127,18 +128,18 @@ function DemoKitProvider({
|
|
|
127
128
|
}, []);
|
|
128
129
|
useEffect(() => {
|
|
129
130
|
if (!isHydrated || isLoading) return;
|
|
130
|
-
if (apiKey && remoteFixturesRef.current) {
|
|
131
|
+
if (source?.apiKey && remoteFixturesRef.current) {
|
|
131
132
|
const merged = { ...remoteFixturesRef.current, ...fixtures };
|
|
132
133
|
interceptorRef.current?.setFixtures(merged);
|
|
133
134
|
} else if (fixtures) {
|
|
134
135
|
interceptorRef.current?.setFixtures(fixtures);
|
|
135
136
|
}
|
|
136
|
-
}, [fixtures, isHydrated, isLoading,
|
|
137
|
+
}, [fixtures, isHydrated, isLoading, source]);
|
|
137
138
|
const enable = useCallback(() => {
|
|
138
139
|
interceptorRef.current?.enable();
|
|
139
140
|
}, []);
|
|
140
141
|
const disable = useCallback(() => {
|
|
141
|
-
interceptorRef.current?.disable();
|
|
142
|
+
return interceptorRef.current?.disable() ?? true;
|
|
142
143
|
}, []);
|
|
143
144
|
const toggle = useCallback(() => {
|
|
144
145
|
interceptorRef.current?.toggle();
|
|
@@ -157,16 +158,17 @@ function DemoKitProvider({
|
|
|
157
158
|
return interceptorRef.current?.getSession() ?? null;
|
|
158
159
|
}, []);
|
|
159
160
|
const refetch = useCallback(async () => {
|
|
160
|
-
if (!apiKey) {
|
|
161
|
-
console.warn("[DemoKit] refetch() called but no
|
|
161
|
+
if (!source?.apiKey) {
|
|
162
|
+
console.warn("[DemoKit] refetch() called but no source provided");
|
|
162
163
|
return;
|
|
163
164
|
}
|
|
164
165
|
await refetchFnRef.current?.();
|
|
165
|
-
}, [
|
|
166
|
+
}, [source]);
|
|
166
167
|
const value = useMemo(
|
|
167
168
|
() => ({
|
|
168
169
|
isDemoMode,
|
|
169
170
|
isHydrated,
|
|
171
|
+
isPublicDemo,
|
|
170
172
|
isLoading,
|
|
171
173
|
remoteError,
|
|
172
174
|
remoteVersion,
|
|
@@ -181,6 +183,7 @@ function DemoKitProvider({
|
|
|
181
183
|
[
|
|
182
184
|
isDemoMode,
|
|
183
185
|
isHydrated,
|
|
186
|
+
isPublicDemo,
|
|
184
187
|
isLoading,
|
|
185
188
|
remoteError,
|
|
186
189
|
remoteVersion,
|
|
@@ -193,7 +196,7 @@ function DemoKitProvider({
|
|
|
193
196
|
refetch
|
|
194
197
|
]
|
|
195
198
|
);
|
|
196
|
-
if (isLoading && apiKey) {
|
|
199
|
+
if (isLoading && source?.apiKey) {
|
|
197
200
|
return /* @__PURE__ */ jsx(DemoModeContext.Provider, { value, children: loadingFallback });
|
|
198
201
|
}
|
|
199
202
|
if (remoteError && errorFallback) {
|
|
@@ -203,6 +206,16 @@ function DemoKitProvider({
|
|
|
203
206
|
return /* @__PURE__ */ jsx(DemoModeContext.Provider, { value, children });
|
|
204
207
|
}
|
|
205
208
|
|
|
209
|
+
// src/config.ts
|
|
210
|
+
function createRemoteSource(config) {
|
|
211
|
+
return {
|
|
212
|
+
timeout: 1e4,
|
|
213
|
+
retry: true,
|
|
214
|
+
maxRetries: 3,
|
|
215
|
+
...config
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
206
219
|
// src/hooks.ts
|
|
207
220
|
import { useContext } from "react";
|
|
208
221
|
function useDemoMode() {
|
|
@@ -224,6 +237,29 @@ function useDemoSession() {
|
|
|
224
237
|
return useDemoMode().getSession();
|
|
225
238
|
}
|
|
226
239
|
|
|
240
|
+
// src/guard.ts
|
|
241
|
+
import { useCallback as useCallback2 } from "react";
|
|
242
|
+
function useDemoGuard(options = {}) {
|
|
243
|
+
const { isDemoMode } = useDemoMode();
|
|
244
|
+
const { onBlocked } = options;
|
|
245
|
+
const guardMutation = useCallback2(
|
|
246
|
+
(action, actionName) => {
|
|
247
|
+
if (isDemoMode) {
|
|
248
|
+
const message = actionName ? `${actionName} (simulated in demo mode)` : "Action simulated in demo mode";
|
|
249
|
+
onBlocked?.(message);
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
action();
|
|
253
|
+
return true;
|
|
254
|
+
},
|
|
255
|
+
[isDemoMode, onBlocked]
|
|
256
|
+
);
|
|
257
|
+
return {
|
|
258
|
+
guardMutation,
|
|
259
|
+
isDemoMode
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
227
263
|
// src/powered-by.tsx
|
|
228
264
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
229
265
|
function ExternalLinkIcon({ size }) {
|
|
@@ -625,6 +661,8 @@ export {
|
|
|
625
661
|
DemoModeContext,
|
|
626
662
|
DemoModeToggle,
|
|
627
663
|
PoweredByBadge,
|
|
664
|
+
createRemoteSource,
|
|
665
|
+
useDemoGuard,
|
|
628
666
|
useDemoMode,
|
|
629
667
|
useDemoSession,
|
|
630
668
|
useIsDemoMode,
|