@demokit-ai/react 0.1.0 → 0.3.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/dist/index.cjs CHANGED
@@ -1,96 +1,242 @@
1
- 'use strict';
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
2
19
 
3
- var react = require('react');
4
- var core = require('@demokit-ai/core');
5
- var jsxRuntime = require('react/jsx-runtime');
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ DemoKitProvider: () => DemoKitProvider,
24
+ DemoModeBanner: () => DemoModeBanner,
25
+ DemoModeContext: () => DemoModeContext,
26
+ DemoModeToggle: () => DemoModeToggle,
27
+ PoweredByBadge: () => PoweredByBadge,
28
+ useDemoMode: () => useDemoMode,
29
+ useDemoSession: () => useDemoSession,
30
+ useIsDemoMode: () => useIsDemoMode,
31
+ useIsHydrated: () => useIsHydrated
32
+ });
33
+ module.exports = __toCommonJS(index_exports);
6
34
 
7
35
  // src/provider.tsx
8
- var DemoModeContext = react.createContext(void 0);
36
+ var import_react2 = require("react");
37
+ var import_core = require("@demokit-ai/core");
38
+
39
+ // src/context.ts
40
+ var import_react = require("react");
41
+ var DemoModeContext = (0, import_react.createContext)(void 0);
9
42
  DemoModeContext.displayName = "DemoModeContext";
43
+
44
+ // src/provider.tsx
45
+ var import_jsx_runtime = require("react/jsx-runtime");
10
46
  function DemoKitProvider({
11
47
  children,
12
48
  fixtures,
49
+ // Remote config
50
+ apiKey,
51
+ cloudUrl,
52
+ timeout,
53
+ retry,
54
+ maxRetries,
55
+ onRemoteLoad,
56
+ onRemoteError,
57
+ loadingFallback = null,
58
+ errorFallback,
59
+ // Standard props
13
60
  storageKey = "demokit-mode",
14
61
  initialEnabled = false,
15
62
  onDemoModeChange,
16
63
  baseUrl
17
64
  }) {
18
- const [isDemoMode, setIsDemoMode] = react.useState(initialEnabled);
19
- const [isHydrated, setIsHydrated] = react.useState(false);
20
- const interceptorRef = react.useRef(null);
21
- const initializedRef = react.useRef(false);
22
- react.useEffect(() => {
65
+ const [isDemoMode, setIsDemoMode] = (0, import_react2.useState)(initialEnabled);
66
+ const [isHydrated, setIsHydrated] = (0, import_react2.useState)(false);
67
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(!!apiKey);
68
+ const [remoteError, setRemoteError] = (0, import_react2.useState)(null);
69
+ const [remoteVersion, setRemoteVersion] = (0, import_react2.useState)(null);
70
+ const interceptorRef = (0, import_react2.useRef)(null);
71
+ const initializedRef = (0, import_react2.useRef)(false);
72
+ const remoteFixturesRef = (0, import_react2.useRef)(null);
73
+ const refetchFnRef = (0, import_react2.useRef)(null);
74
+ const setupInterceptor = (0, import_react2.useCallback)(
75
+ (mergedFixtures) => {
76
+ interceptorRef.current?.destroy();
77
+ interceptorRef.current = (0, import_core.createDemoInterceptor)({
78
+ fixtures: mergedFixtures,
79
+ storageKey,
80
+ initialEnabled,
81
+ baseUrl,
82
+ onEnable: () => {
83
+ setIsDemoMode(true);
84
+ onDemoModeChange?.(true);
85
+ },
86
+ onDisable: () => {
87
+ setIsDemoMode(false);
88
+ onDemoModeChange?.(false);
89
+ }
90
+ });
91
+ const storedState = interceptorRef.current.isEnabled();
92
+ setIsDemoMode(storedState);
93
+ setIsHydrated(true);
94
+ },
95
+ [storageKey, initialEnabled, baseUrl, onDemoModeChange]
96
+ );
97
+ const fetchAndSetup = (0, import_react2.useCallback)(async () => {
98
+ if (!apiKey) return;
99
+ setIsLoading(true);
100
+ setRemoteError(null);
101
+ try {
102
+ const response = await (0, import_core.fetchCloudFixtures)({
103
+ apiKey,
104
+ cloudUrl,
105
+ timeout,
106
+ retry,
107
+ maxRetries,
108
+ onLoad: onRemoteLoad,
109
+ onError: onRemoteError
110
+ });
111
+ const remoteFixtures = (0, import_core.createRemoteFixtures)(response, fixtures);
112
+ remoteFixturesRef.current = remoteFixtures;
113
+ setRemoteVersion(response.version);
114
+ setupInterceptor(remoteFixtures);
115
+ } catch (error) {
116
+ const err = error instanceof Error ? error : new Error(String(error));
117
+ setRemoteError(err);
118
+ onRemoteError?.(err);
119
+ if (fixtures && Object.keys(fixtures).length > 0) {
120
+ setupInterceptor(fixtures);
121
+ } else {
122
+ setIsHydrated(true);
123
+ }
124
+ } finally {
125
+ setIsLoading(false);
126
+ }
127
+ }, [
128
+ apiKey,
129
+ cloudUrl,
130
+ timeout,
131
+ retry,
132
+ maxRetries,
133
+ fixtures,
134
+ onRemoteLoad,
135
+ onRemoteError,
136
+ setupInterceptor
137
+ ]);
138
+ refetchFnRef.current = fetchAndSetup;
139
+ (0, import_react2.useEffect)(() => {
23
140
  if (initializedRef.current) {
24
141
  return;
25
142
  }
26
143
  initializedRef.current = true;
27
- interceptorRef.current = core.createDemoInterceptor({
28
- fixtures,
29
- storageKey,
30
- initialEnabled,
31
- baseUrl,
32
- onEnable: () => {
33
- setIsDemoMode(true);
34
- onDemoModeChange?.(true);
35
- },
36
- onDisable: () => {
37
- setIsDemoMode(false);
38
- onDemoModeChange?.(false);
39
- }
40
- });
41
- const storedState = interceptorRef.current.isEnabled();
42
- setIsDemoMode(storedState);
43
- setIsHydrated(true);
144
+ if (apiKey) {
145
+ fetchAndSetup();
146
+ } else if (fixtures) {
147
+ setupInterceptor(fixtures);
148
+ } else {
149
+ setIsHydrated(true);
150
+ setIsLoading(false);
151
+ }
44
152
  return () => {
45
153
  interceptorRef.current?.destroy();
46
154
  interceptorRef.current = null;
47
155
  initializedRef.current = false;
48
156
  };
49
157
  }, []);
50
- react.useEffect(() => {
51
- if (interceptorRef.current && isHydrated) {
52
- interceptorRef.current.setFixtures(fixtures);
158
+ (0, import_react2.useEffect)(() => {
159
+ if (!isHydrated || isLoading) return;
160
+ if (apiKey && remoteFixturesRef.current) {
161
+ const merged = { ...remoteFixturesRef.current, ...fixtures };
162
+ interceptorRef.current?.setFixtures(merged);
163
+ } else if (fixtures) {
164
+ interceptorRef.current?.setFixtures(fixtures);
53
165
  }
54
- }, [fixtures, isHydrated]);
55
- const enable = react.useCallback(() => {
166
+ }, [fixtures, isHydrated, isLoading, apiKey]);
167
+ const enable = (0, import_react2.useCallback)(() => {
56
168
  interceptorRef.current?.enable();
57
169
  }, []);
58
- const disable = react.useCallback(() => {
170
+ const disable = (0, import_react2.useCallback)(() => {
59
171
  interceptorRef.current?.disable();
60
172
  }, []);
61
- const toggle = react.useCallback(() => {
173
+ const toggle = (0, import_react2.useCallback)(() => {
62
174
  interceptorRef.current?.toggle();
63
175
  }, []);
64
- const setDemoMode = react.useCallback((enabled) => {
176
+ const setDemoMode = (0, import_react2.useCallback)((enabled) => {
65
177
  if (enabled) {
66
178
  interceptorRef.current?.enable();
67
179
  } else {
68
180
  interceptorRef.current?.disable();
69
181
  }
70
182
  }, []);
71
- const resetSession = react.useCallback(() => {
183
+ const resetSession = (0, import_react2.useCallback)(() => {
72
184
  interceptorRef.current?.resetSession();
73
185
  }, []);
74
- const getSession = react.useCallback(() => {
186
+ const getSession = (0, import_react2.useCallback)(() => {
75
187
  return interceptorRef.current?.getSession() ?? null;
76
188
  }, []);
77
- const value = react.useMemo(
189
+ const refetch = (0, import_react2.useCallback)(async () => {
190
+ if (!apiKey) {
191
+ console.warn("[DemoKit] refetch() called but no apiKey provided");
192
+ return;
193
+ }
194
+ await refetchFnRef.current?.();
195
+ }, [apiKey]);
196
+ const value = (0, import_react2.useMemo)(
78
197
  () => ({
79
198
  isDemoMode,
80
199
  isHydrated,
200
+ isLoading,
201
+ remoteError,
202
+ remoteVersion,
81
203
  enable,
82
204
  disable,
83
205
  toggle,
84
206
  setDemoMode,
85
207
  resetSession,
86
- getSession
208
+ getSession,
209
+ refetch
87
210
  }),
88
- [isDemoMode, isHydrated, enable, disable, toggle, setDemoMode, resetSession, getSession]
211
+ [
212
+ isDemoMode,
213
+ isHydrated,
214
+ isLoading,
215
+ remoteError,
216
+ remoteVersion,
217
+ enable,
218
+ disable,
219
+ toggle,
220
+ setDemoMode,
221
+ resetSession,
222
+ getSession,
223
+ refetch
224
+ ]
89
225
  );
90
- return /* @__PURE__ */ jsxRuntime.jsx(DemoModeContext.Provider, { value, children });
226
+ if (isLoading && apiKey) {
227
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DemoModeContext.Provider, { value, children: loadingFallback });
228
+ }
229
+ if (remoteError && errorFallback) {
230
+ const errorContent = typeof errorFallback === "function" ? errorFallback(remoteError) : errorFallback;
231
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DemoModeContext.Provider, { value, children: errorContent });
232
+ }
233
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DemoModeContext.Provider, { value, children });
91
234
  }
235
+
236
+ // src/hooks.ts
237
+ var import_react3 = require("react");
92
238
  function useDemoMode() {
93
- const context = react.useContext(DemoModeContext);
239
+ const context = (0, import_react3.useContext)(DemoModeContext);
94
240
  if (context === void 0) {
95
241
  throw new Error(
96
242
  "useDemoMode must be used within a DemoKitProvider. Make sure to wrap your app with <DemoKitProvider>."
@@ -107,8 +253,116 @@ function useIsHydrated() {
107
253
  function useDemoSession() {
108
254
  return useDemoMode().getSession();
109
255
  }
256
+
257
+ // src/powered-by.tsx
258
+ var import_jsx_runtime2 = require("react/jsx-runtime");
259
+ function ExternalLinkIcon({ size }) {
260
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
261
+ "svg",
262
+ {
263
+ width: size,
264
+ height: size,
265
+ viewBox: "0 0 24 24",
266
+ fill: "none",
267
+ stroke: "currentColor",
268
+ strokeWidth: "2",
269
+ strokeLinecap: "round",
270
+ strokeLinejoin: "round",
271
+ "aria-hidden": "true",
272
+ children: [
273
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
274
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "15 3 21 3 21 9" }),
275
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
276
+ ]
277
+ }
278
+ );
279
+ }
280
+ var sizeConfig = {
281
+ xs: {
282
+ fontSize: "10px",
283
+ padding: "2px 6px",
284
+ gap: "3px",
285
+ iconSize: 8
286
+ },
287
+ sm: {
288
+ fontSize: "11px",
289
+ padding: "3px 8px",
290
+ gap: "4px",
291
+ iconSize: 10
292
+ },
293
+ md: {
294
+ fontSize: "12px",
295
+ padding: "4px 10px",
296
+ gap: "5px",
297
+ iconSize: 12
298
+ }
299
+ };
300
+ var variantStyles = {
301
+ light: {
302
+ color: "rgba(120, 53, 15, 0.7)",
303
+ hoverColor: "rgba(120, 53, 15, 0.9)",
304
+ backgroundColor: "transparent",
305
+ hoverBackgroundColor: "rgba(217, 119, 6, 0.08)"
306
+ },
307
+ dark: {
308
+ color: "rgba(255, 255, 255, 0.6)",
309
+ hoverColor: "rgba(255, 255, 255, 0.9)",
310
+ backgroundColor: "transparent",
311
+ hoverBackgroundColor: "rgba(255, 255, 255, 0.1)"
312
+ }
313
+ };
314
+ function PoweredByBadge({
315
+ url = "https://demokit.ai",
316
+ variant = "light",
317
+ size = "sm",
318
+ className = "",
319
+ style
320
+ }) {
321
+ const config = sizeConfig[size];
322
+ const colors = variantStyles[variant === "auto" ? "light" : variant];
323
+ const baseStyles = {
324
+ display: "inline-flex",
325
+ alignItems: "center",
326
+ gap: config.gap,
327
+ fontSize: config.fontSize,
328
+ padding: config.padding,
329
+ color: colors.color,
330
+ textDecoration: "none",
331
+ borderRadius: "4px",
332
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
333
+ fontWeight: 500,
334
+ transition: "color 0.15s ease, background-color 0.15s ease",
335
+ whiteSpace: "nowrap",
336
+ ...style
337
+ };
338
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
339
+ "a",
340
+ {
341
+ href: url,
342
+ target: "_blank",
343
+ rel: "noopener noreferrer",
344
+ className: `demokit-powered-by ${className}`.trim(),
345
+ style: baseStyles,
346
+ onMouseOver: (e) => {
347
+ e.currentTarget.style.color = colors.hoverColor;
348
+ e.currentTarget.style.backgroundColor = colors.hoverBackgroundColor;
349
+ },
350
+ onMouseOut: (e) => {
351
+ e.currentTarget.style.color = colors.color;
352
+ e.currentTarget.style.backgroundColor = "transparent";
353
+ },
354
+ children: [
355
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Powered by DemoKit" }),
356
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ExternalLinkIcon, { size: config.iconSize })
357
+ ]
358
+ }
359
+ );
360
+ }
361
+
362
+ // src/banner.tsx
363
+ var import_jsx_runtime3 = require("react/jsx-runtime");
110
364
  function EyeIcon() {
111
- return /* @__PURE__ */ jsxRuntime.jsxs(
365
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
112
366
  "svg",
113
367
  {
114
368
  width: "20",
@@ -121,8 +375,8 @@ function EyeIcon() {
121
375
  strokeLinejoin: "round",
122
376
  "aria-hidden": "true",
123
377
  children: [
124
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
125
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "3" })
378
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
379
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "3" })
126
380
  ]
127
381
  }
128
382
  );
@@ -173,6 +427,8 @@ function DemoModeBanner({
173
427
  demoLabel = "Demo Mode Active",
174
428
  description = "Changes are simulated and not saved",
175
429
  showIcon = true,
430
+ showPoweredBy = true,
431
+ poweredByUrl = "https://demokit.ai",
176
432
  style,
177
433
  onExit
178
434
  }) {
@@ -187,45 +443,222 @@ function DemoModeBanner({
187
443
  disable();
188
444
  }
189
445
  };
190
- return /* @__PURE__ */ jsxRuntime.jsxs(
446
+ const effectiveShowPoweredBy = showPoweredBy;
447
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
191
448
  "div",
192
449
  {
193
450
  className: `demokit-banner ${className}`.trim(),
194
- style: { ...defaultStyles.container, ...style },
451
+ style: { ...defaultStyles.container, flexDirection: "column", gap: "4px", ...style },
195
452
  role: "status",
196
453
  "aria-live": "polite",
197
454
  children: [
198
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles.content, children: [
199
- showIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { style: defaultStyles.icon, children: /* @__PURE__ */ jsxRuntime.jsx(EyeIcon, {}) }),
200
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: defaultStyles.label, children: demoLabel }),
201
- description && /* @__PURE__ */ jsxRuntime.jsx("span", { style: defaultStyles.description, children: description })
455
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", width: "100%" }, children: [
456
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.content, children: [
457
+ showIcon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: defaultStyles.icon, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EyeIcon, {}) }),
458
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: defaultStyles.label, children: demoLabel }),
459
+ description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: defaultStyles.description, children: description })
460
+ ] }),
461
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
462
+ "button",
463
+ {
464
+ onClick: handleExit,
465
+ style: defaultStyles.button,
466
+ onMouseOver: (e) => {
467
+ e.currentTarget.style.backgroundColor = "rgba(217, 119, 6, 0.1)";
468
+ },
469
+ onMouseOut: (e) => {
470
+ e.currentTarget.style.backgroundColor = "transparent";
471
+ },
472
+ type: "button",
473
+ children: exitLabel
474
+ }
475
+ )
202
476
  ] }),
203
- /* @__PURE__ */ jsxRuntime.jsx(
204
- "button",
205
- {
206
- onClick: handleExit,
207
- style: defaultStyles.button,
208
- onMouseOver: (e) => {
209
- e.currentTarget.style.backgroundColor = "rgba(217, 119, 6, 0.1)";
210
- },
211
- onMouseOut: (e) => {
212
- e.currentTarget.style.backgroundColor = "transparent";
213
- },
214
- type: "button",
215
- children: exitLabel
216
- }
217
- )
477
+ effectiveShowPoweredBy && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", justifyContent: "flex-end", width: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PoweredByBadge, { url: poweredByUrl, size: "xs" }) })
218
478
  ]
219
479
  }
220
480
  );
221
481
  }
222
482
 
223
- exports.DemoKitProvider = DemoKitProvider;
224
- exports.DemoModeBanner = DemoModeBanner;
225
- exports.DemoModeContext = DemoModeContext;
226
- exports.useDemoMode = useDemoMode;
227
- exports.useDemoSession = useDemoSession;
228
- exports.useIsDemoMode = useIsDemoMode;
229
- exports.useIsHydrated = useIsHydrated;
230
- //# sourceMappingURL=index.cjs.map
483
+ // src/toggle.tsx
484
+ var import_jsx_runtime4 = require("react/jsx-runtime");
485
+ var sizeConfig2 = {
486
+ sm: {
487
+ trackWidth: 36,
488
+ trackHeight: 20,
489
+ thumbSize: 16,
490
+ thumbOffset: 2,
491
+ fontSize: "12px",
492
+ padding: "8px 12px",
493
+ gap: "8px"
494
+ },
495
+ md: {
496
+ trackWidth: 44,
497
+ trackHeight: 24,
498
+ thumbSize: 20,
499
+ thumbOffset: 2,
500
+ fontSize: "14px",
501
+ padding: "12px 16px",
502
+ gap: "10px"
503
+ },
504
+ lg: {
505
+ trackWidth: 52,
506
+ trackHeight: 28,
507
+ thumbSize: 24,
508
+ thumbOffset: 2,
509
+ fontSize: "16px",
510
+ padding: "16px 20px",
511
+ gap: "12px"
512
+ }
513
+ };
514
+ var positionStyles = {
515
+ inline: {},
516
+ floating: {
517
+ position: "fixed",
518
+ zIndex: 9999,
519
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
520
+ borderRadius: "8px"
521
+ },
522
+ corner: {
523
+ position: "fixed",
524
+ bottom: "20px",
525
+ right: "20px",
526
+ zIndex: 9999,
527
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
528
+ borderRadius: "8px"
529
+ }
530
+ };
531
+ var defaultStyles2 = {
532
+ container: {
533
+ display: "inline-flex",
534
+ flexDirection: "column",
535
+ alignItems: "flex-start",
536
+ gap: "4px",
537
+ backgroundColor: "#ffffff",
538
+ border: "1px solid rgba(0, 0, 0, 0.1)",
539
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
540
+ },
541
+ row: {
542
+ display: "flex",
543
+ alignItems: "center",
544
+ width: "100%"
545
+ },
546
+ label: {
547
+ fontWeight: 500,
548
+ color: "#1f2937",
549
+ userSelect: "none"
550
+ },
551
+ track: {
552
+ position: "relative",
553
+ borderRadius: "9999px",
554
+ cursor: "pointer",
555
+ transition: "background-color 0.2s ease",
556
+ flexShrink: 0
557
+ },
558
+ trackOff: {
559
+ backgroundColor: "#d1d5db"
560
+ },
561
+ trackOn: {
562
+ backgroundColor: "#d97706"
563
+ },
564
+ thumb: {
565
+ position: "absolute",
566
+ top: "50%",
567
+ transform: "translateY(-50%)",
568
+ backgroundColor: "#ffffff",
569
+ borderRadius: "50%",
570
+ boxShadow: "0 1px 3px rgba(0, 0, 0, 0.2)",
571
+ transition: "left 0.2s ease"
572
+ },
573
+ poweredByContainer: {
574
+ display: "flex",
575
+ justifyContent: "flex-end",
576
+ width: "100%"
577
+ }
578
+ };
579
+ function DemoModeToggle({
580
+ showLabel = true,
581
+ label = "Demo Mode",
582
+ showPoweredBy = true,
583
+ poweredByUrl = "https://demokit.ai",
584
+ position = "inline",
585
+ size = "md",
586
+ className = "",
587
+ style,
588
+ onChange
589
+ }) {
590
+ const { isDemoMode, isHydrated, toggle } = useDemoMode();
591
+ if (!isHydrated) {
592
+ return null;
593
+ }
594
+ const config = sizeConfig2[size];
595
+ const posStyle = positionStyles[position];
596
+ const handleToggle = () => {
597
+ toggle();
598
+ onChange?.(!isDemoMode);
599
+ };
600
+ const thumbLeft = isDemoMode ? config.trackWidth - config.thumbSize - config.thumbOffset : config.thumbOffset;
601
+ const effectiveShowPoweredBy = showPoweredBy;
602
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
603
+ "div",
604
+ {
605
+ className: `demokit-toggle ${className}`.trim(),
606
+ style: {
607
+ ...defaultStyles2.container,
608
+ padding: config.padding,
609
+ ...posStyle,
610
+ ...style
611
+ },
612
+ role: "group",
613
+ "aria-label": "Demo mode toggle",
614
+ children: [
615
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...defaultStyles2.row, gap: config.gap }, children: [
616
+ showLabel && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { ...defaultStyles2.label, fontSize: config.fontSize }, children: label }),
617
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
618
+ "button",
619
+ {
620
+ type: "button",
621
+ role: "switch",
622
+ "aria-checked": isDemoMode,
623
+ "aria-label": `${label}: ${isDemoMode ? "On" : "Off"}`,
624
+ onClick: handleToggle,
625
+ style: {
626
+ ...defaultStyles2.track,
627
+ ...isDemoMode ? defaultStyles2.trackOn : defaultStyles2.trackOff,
628
+ width: config.trackWidth,
629
+ height: config.trackHeight,
630
+ border: "none",
631
+ padding: 0
632
+ },
633
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
634
+ "span",
635
+ {
636
+ style: {
637
+ ...defaultStyles2.thumb,
638
+ width: config.thumbSize,
639
+ height: config.thumbSize,
640
+ left: thumbLeft
641
+ }
642
+ }
643
+ )
644
+ }
645
+ )
646
+ ] }),
647
+ effectiveShowPoweredBy && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles2.poweredByContainer, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PoweredByBadge, { url: poweredByUrl, size: "xs" }) })
648
+ ]
649
+ }
650
+ );
651
+ }
652
+ // Annotate the CommonJS export names for ESM import in node:
653
+ 0 && (module.exports = {
654
+ DemoKitProvider,
655
+ DemoModeBanner,
656
+ DemoModeContext,
657
+ DemoModeToggle,
658
+ PoweredByBadge,
659
+ useDemoMode,
660
+ useDemoSession,
661
+ useIsDemoMode,
662
+ useIsHydrated
663
+ });
231
664
  //# sourceMappingURL=index.cjs.map