sunpeak 0.1.25 → 0.2.2

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.
Files changed (44) hide show
  1. package/README.md +9 -76
  2. package/bin/sunpeak.js +87 -0
  3. package/dist/index.cjs +827 -1361
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +98 -589
  6. package/dist/index.d.ts +98 -589
  7. package/dist/index.js +795 -1337
  8. package/dist/index.js.map +1 -1
  9. package/dist/styles/chatgpt/index.css +146 -0
  10. package/dist/styles/globals.css +220 -0
  11. package/package.json +34 -36
  12. package/template/.prettierignore +4 -0
  13. package/template/.prettierrc +9 -0
  14. package/template/README.md +47 -0
  15. package/template/assets/favicon.ico +0 -0
  16. package/template/components.json +21 -0
  17. package/template/dev/main.tsx +65 -0
  18. package/template/dev/styles.css +5 -0
  19. package/template/eslint.config.cjs +49 -0
  20. package/template/index.html +13 -0
  21. package/template/package.json +56 -0
  22. package/template/src/App.tsx +45 -0
  23. package/template/src/components/index.ts +2 -0
  24. package/template/src/components/shadcn/button.tsx +60 -0
  25. package/template/src/components/shadcn/card.tsx +76 -0
  26. package/template/src/components/shadcn/carousel.tsx +260 -0
  27. package/template/src/components/shadcn/index.ts +5 -0
  28. package/template/src/components/shadcn/label.tsx +24 -0
  29. package/template/src/components/shadcn/select.tsx +157 -0
  30. package/template/src/components/sunpeak-card.test.tsx +76 -0
  31. package/template/src/components/sunpeak-card.tsx +140 -0
  32. package/template/src/components/sunpeak-carousel.test.tsx +42 -0
  33. package/template/src/components/sunpeak-carousel.tsx +126 -0
  34. package/template/src/index.ts +3 -0
  35. package/template/src/lib/index.ts +1 -0
  36. package/template/src/lib/utils.ts +6 -0
  37. package/template/src/styles/chatgpt.css +146 -0
  38. package/template/src/styles/globals.css +220 -0
  39. package/template/src/test/setup.ts +37 -0
  40. package/template/tsconfig.json +32 -0
  41. package/template/tsconfig.node.json +11 -0
  42. package/template/tsup.config.ts +23 -0
  43. package/template/vite.config.ts +35 -0
  44. package/template/vitest.config.ts +15 -0
package/dist/index.js CHANGED
@@ -1,1421 +1,879 @@
1
- import { useTheme, Box, IconButton, Typography, FormControl, InputLabel, Select, MenuItem, TextField, Button } from '@mui/material';
2
- import { createContext, useSyncExternalStore, useState, useEffect, useCallback, useRef, Children, useContext } from 'react';
3
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
- import { createTheme, ThemeProvider } from '@mui/material/styles';
5
- import CssBaseline from '@mui/material/CssBaseline';
6
- import CloseIcon from '@mui/icons-material/Close';
1
+ import * as React3 from 'react';
2
+ import { useSyncExternalStore, useCallback, useMemo, useState, useEffect } from 'react';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+ import { Slot } from '@radix-ui/react-slot';
5
+ import { cva } from 'class-variance-authority';
6
+ import { ChevronDown, ChevronUp, Check, XIcon } from 'lucide-react';
7
+ import { clsx } from 'clsx';
8
+ import { twMerge } from 'tailwind-merge';
9
+ import * as SheetPrimitive from '@radix-ui/react-dialog';
10
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
11
+ import * as SelectPrimitive from '@radix-ui/react-select';
12
+ import * as LabelPrimitive from '@radix-ui/react-label';
7
13
 
8
- // src/components/Card/Card.tsx
9
-
10
- // src/types/chatgpt.ts
11
- var SET_GLOBALS_EVENT_TYPE = "chatgpt:set_globals";
14
+ var __defProp = Object.defineProperty;
15
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
16
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
17
+ var ThemeProviderContext = React3.createContext(
18
+ void 0
19
+ );
20
+ function ThemeProvider({
21
+ children,
22
+ defaultTheme = "light",
23
+ theme: controlledTheme,
24
+ ...props
25
+ }) {
26
+ const [internalTheme] = React3.useState(defaultTheme);
27
+ const theme = controlledTheme ?? internalTheme;
28
+ React3.useEffect(() => {
29
+ const root = window.document.documentElement;
30
+ root.classList.remove("light", "dark");
31
+ root.classList.add(theme);
32
+ }, [theme]);
33
+ const value = {
34
+ theme
35
+ };
36
+ return /* @__PURE__ */ jsx(ThemeProviderContext.Provider, { ...props, value, children });
37
+ }
38
+ var useThemeContext = () => {
39
+ const context = React3.useContext(ThemeProviderContext);
40
+ if (context === void 0)
41
+ throw new Error("useThemeContext must be used within a ThemeProvider");
42
+ return context;
43
+ };
12
44
 
13
- // src/platforms/chatgpt.ts
14
- var ChatGPTPlatformAdapter = class {
45
+ // src/types/openai.ts
46
+ var SET_GLOBALS_EVENT_TYPE = "openai:set_globals";
47
+ var SetGlobalsEvent = class extends CustomEvent {
15
48
  constructor() {
16
- this.name = "chatgpt";
17
- }
18
- isAvailable() {
19
- return typeof window !== "undefined" && "openai" in window;
20
- }
21
- getGlobal(key) {
22
- if (!this.isAvailable()) {
23
- return null;
24
- }
25
- return window.openai?.[key] ?? null;
26
- }
27
- getGlobals() {
28
- if (!this.isAvailable()) {
29
- return null;
30
- }
31
- return window.openai ?? null;
32
- }
33
- subscribe(callback) {
34
- if (typeof window === "undefined") {
35
- return () => {
36
- };
37
- }
38
- const handleSetGlobal = (_event) => {
39
- callback();
40
- };
41
- window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {
42
- passive: true
43
- });
44
- return () => {
45
- window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
46
- };
49
+ super(...arguments);
50
+ __publicField(this, "type", SET_GLOBALS_EVENT_TYPE);
47
51
  }
48
52
  };
49
- var chatgptPlatform = new ChatGPTPlatformAdapter();
50
53
 
51
- // src/platforms/registry.ts
52
- var DefaultPlatformRegistry = class {
53
- constructor() {
54
- this.adapters = /* @__PURE__ */ new Map();
55
- this.register(chatgptPlatform);
56
- }
57
- register(adapter) {
58
- this.adapters.set(adapter.name, adapter);
59
- }
60
- get(name) {
61
- return this.adapters.get(name) ?? null;
62
- }
63
- detect() {
64
- for (const adapter of this.adapters.values()) {
65
- if (adapter.isAvailable()) {
66
- return adapter;
67
- }
68
- }
69
- return null;
70
- }
71
- getAll() {
72
- return Array.from(this.adapters.values());
73
- }
54
+ // src/types/simulator.ts
55
+ var SCREEN_WIDTHS = {
56
+ "mobile-s": 375,
57
+ "mobile-l": 425,
58
+ tablet: 768,
59
+ full: 1024
74
60
  };
75
- function createPlatformRegistry() {
76
- return new DefaultPlatformRegistry();
77
- }
78
- var defaultPlatformRegistry = createPlatformRegistry();
79
- var PlatformContext = createContext(null);
80
- function PlatformProvider({ adapter, platform, children }) {
81
- const resolvedAdapter = adapter ?? (platform ? defaultPlatformRegistry.get(platform) : null) ?? defaultPlatformRegistry.detect();
82
- return /* @__PURE__ */ jsx(PlatformContext.Provider, { value: { adapter: resolvedAdapter }, children });
83
- }
84
- function usePlatformContext() {
85
- const context = useContext(PlatformContext);
86
- if (!context) {
87
- return {
88
- adapter: defaultPlatformRegistry.detect()
89
- };
90
- }
91
- return context;
92
- }
93
- function usePlatform() {
94
- const { adapter } = usePlatformContext();
95
- return adapter;
96
- }
97
61
 
98
- // src/hooks/usePlatformGlobal.ts
99
- function usePlatformGlobal(key) {
100
- const platform = usePlatform();
62
+ // src/hooks/use-openai-global.ts
63
+ function useOpenAiGlobal(key) {
101
64
  return useSyncExternalStore(
102
65
  (onChange) => {
103
- if (!platform) {
66
+ if (typeof window === "undefined") {
104
67
  return () => {
105
68
  };
106
69
  }
107
- return platform.subscribe(onChange);
70
+ const handleSetGlobal = (event) => {
71
+ const value = event.detail.globals[key];
72
+ if (value === void 0) {
73
+ return;
74
+ }
75
+ onChange();
76
+ };
77
+ window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {
78
+ passive: true
79
+ });
80
+ return () => {
81
+ window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
82
+ };
108
83
  },
109
- () => platform?.getGlobal(key) ?? null,
110
- () => platform?.getGlobal(key) ?? null
84
+ () => window.openai?.[key] ?? null,
85
+ () => window.openai?.[key] ?? null
111
86
  );
112
87
  }
113
88
 
114
- // src/hooks/useDisplayMode.ts
89
+ // src/hooks/use-display-mode.ts
115
90
  var useDisplayMode = () => {
116
- return usePlatformGlobal("displayMode");
91
+ return useOpenAiGlobal("displayMode");
117
92
  };
118
93
 
119
- // src/hooks/useMaxHeight.ts
94
+ // src/hooks/use-max-height.ts
120
95
  var useMaxHeight = () => {
121
- return usePlatformGlobal("maxHeight");
96
+ return useOpenAiGlobal("maxHeight");
122
97
  };
123
-
124
- // src/hooks/useRequestDisplayMode.ts
125
- function useRequestDisplayMode() {
126
- const platform = usePlatform();
127
- return async (args) => {
128
- const globals = platform?.getGlobals();
129
- if (globals?.requestDisplayMode) {
130
- return await globals.requestDisplayMode(args);
131
- }
132
- console.warn("requestDisplayMode is not available on this platform");
133
- return { mode: args.mode };
134
- };
98
+ var MOBILE_BREAKPOINT = 768;
99
+ function useIsMobile() {
100
+ const [isMobile, setIsMobile] = React3.useState(void 0);
101
+ React3.useEffect(() => {
102
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
103
+ const onChange = () => {
104
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
105
+ };
106
+ mql.addEventListener("change", onChange);
107
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
108
+ return () => mql.removeEventListener("change", onChange);
109
+ }, []);
110
+ return !!isMobile;
135
111
  }
136
112
 
137
- // src/hooks/useColorScheme.ts
138
- var useColorScheme = () => {
139
- return usePlatformGlobal("colorScheme");
113
+ // src/hooks/use-theme.ts
114
+ var useTheme = () => {
115
+ return useOpenAiGlobal("theme");
140
116
  };
141
-
142
- // src/hooks/useWidgetProps.ts
143
- function useWidgetProps(defaultState) {
144
- const props = usePlatformGlobal("toolOutput");
145
- const fallback = typeof defaultState === "function" ? defaultState() : defaultState ?? null;
146
- return props ?? fallback;
117
+ function useWidgetState() {
118
+ const widgetState = useOpenAiGlobal("widgetState");
119
+ const setWidgetState = useOpenAiGlobal("setWidgetState");
120
+ const setter = useCallback(
121
+ async (state) => {
122
+ if (setWidgetState) {
123
+ await setWidgetState(state);
124
+ }
125
+ },
126
+ [setWidgetState]
127
+ );
128
+ return useMemo(() => [widgetState, setter], [widgetState, setter]);
129
+ }
130
+ function cn(...inputs) {
131
+ return twMerge(clsx(inputs));
147
132
  }
148
- function useWidgetState(defaultState) {
149
- const widgetStateFromWindow = usePlatformGlobal("widgetState");
150
- const platform = usePlatform();
151
- const [widgetState, _setWidgetState] = useState(() => {
152
- if (widgetStateFromWindow != null) {
153
- return widgetStateFromWindow;
133
+ function Sheet({ ...props }) {
134
+ return /* @__PURE__ */ jsx(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
135
+ }
136
+ function SheetPortal({
137
+ ...props
138
+ }) {
139
+ return /* @__PURE__ */ jsx(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
140
+ }
141
+ function SheetOverlay({
142
+ className,
143
+ ...props
144
+ }) {
145
+ return /* @__PURE__ */ jsx(
146
+ SheetPrimitive.Overlay,
147
+ {
148
+ "data-slot": "sheet-overlay",
149
+ className: cn(
150
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
151
+ className
152
+ ),
153
+ ...props
154
154
  }
155
- return typeof defaultState === "function" ? defaultState() : defaultState ?? null;
156
- });
157
- useEffect(() => {
158
- _setWidgetState(widgetStateFromWindow);
159
- }, [widgetStateFromWindow]);
160
- const setWidgetState = useCallback(
161
- (state) => {
162
- _setWidgetState((prevState) => {
163
- const newState = typeof state === "function" ? state(prevState) : state;
164
- if (newState != null && platform) {
165
- const globals = platform.getGlobals();
166
- if (globals?.setWidgetState) {
167
- globals.setWidgetState(newState);
168
- }
169
- }
170
- return newState;
171
- });
172
- },
173
- [platform]
174
155
  );
175
- return [widgetState, setWidgetState];
176
156
  }
177
- var Card = ({
178
- children,
179
- image,
180
- imageAlt,
181
- imageMaxWidth,
182
- imageMaxHeight,
183
- header,
184
- metadata,
185
- button1,
186
- button2,
187
- variant = "default",
157
+ function SheetContent({
188
158
  className,
189
- onClick,
190
- id,
159
+ children,
160
+ side = "right",
191
161
  ...props
192
- }) => {
193
- const requestDisplayMode = useRequestDisplayMode();
194
- const displayMode = useDisplayMode();
195
- const maxHeight = useMaxHeight();
196
- const theme = useTheme();
197
- const [widgetState, setWidgetState] = useWidgetState({});
198
- const isInline = displayMode !== "fullscreen" && displayMode !== "pip";
199
- const hasButtons = button1 || button2;
200
- const handleCardClick = async (e) => {
201
- onClick?.(e);
202
- if (isInline && !e.defaultPrevented) {
203
- try {
204
- if (id) {
205
- setWidgetState({ ...widgetState, selectedCardId: id });
206
- }
207
- await requestDisplayMode({ mode: "fullscreen" });
208
- } catch (error) {
209
- console.error("Failed to request fullscreen mode:", error);
162
+ }) {
163
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
164
+ /* @__PURE__ */ jsx(SheetOverlay, {}),
165
+ /* @__PURE__ */ jsxs(
166
+ SheetPrimitive.Content,
167
+ {
168
+ "data-slot": "sheet-content",
169
+ className: cn(
170
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
171
+ side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
172
+ side === "left" && "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
173
+ side === "top" && "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
174
+ side === "bottom" && "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
175
+ className
176
+ ),
177
+ ...props,
178
+ children: [
179
+ children,
180
+ /* @__PURE__ */ jsxs(SheetPrimitive.Close, { className: "ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none", children: [
181
+ /* @__PURE__ */ jsx(XIcon, { className: "size-4" }),
182
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
183
+ ] })
184
+ ]
210
185
  }
186
+ )
187
+ ] });
188
+ }
189
+ function SheetHeader({ className, ...props }) {
190
+ return /* @__PURE__ */ jsx(
191
+ "div",
192
+ {
193
+ "data-slot": "sheet-header",
194
+ className: cn("flex flex-col gap-1.5 p-4", className),
195
+ ...props
211
196
  }
212
- };
213
- const renderButton = (buttonProps) => {
214
- const { isPrimary = false, onClick: buttonOnClick, children: children2, ...muiProps } = buttonProps;
215
- const handleClick = (e) => {
216
- e.stopPropagation();
217
- buttonOnClick();
197
+ );
198
+ }
199
+ function SheetTitle({
200
+ className,
201
+ ...props
202
+ }) {
203
+ return /* @__PURE__ */ jsx(
204
+ SheetPrimitive.Title,
205
+ {
206
+ "data-slot": "sheet-title",
207
+ className: cn("text-foreground font-semibold", className),
208
+ ...props
209
+ }
210
+ );
211
+ }
212
+ function SheetDescription({
213
+ className,
214
+ ...props
215
+ }) {
216
+ return /* @__PURE__ */ jsx(
217
+ SheetPrimitive.Description,
218
+ {
219
+ "data-slot": "sheet-description",
220
+ className: cn("text-muted-foreground text-sm", className),
221
+ ...props
222
+ }
223
+ );
224
+ }
225
+ function TooltipProvider({
226
+ delayDuration = 0,
227
+ ...props
228
+ }) {
229
+ return /* @__PURE__ */ jsx(
230
+ TooltipPrimitive.Provider,
231
+ {
232
+ "data-slot": "tooltip-provider",
233
+ delayDuration,
234
+ ...props
235
+ }
236
+ );
237
+ }
238
+ var SIDEBAR_COOKIE_NAME = "sidebar_state";
239
+ var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
240
+ var SIDEBAR_WIDTH = "16rem";
241
+ var SIDEBAR_WIDTH_MOBILE = "18rem";
242
+ var SIDEBAR_WIDTH_ICON = "3rem";
243
+ var SIDEBAR_KEYBOARD_SHORTCUT = "b";
244
+ var SidebarContext = React3.createContext(null);
245
+ function useSidebar() {
246
+ const context = React3.useContext(SidebarContext);
247
+ if (!context) {
248
+ throw new Error("useSidebar must be used within a SidebarProvider.");
249
+ }
250
+ return context;
251
+ }
252
+ function SidebarProvider({
253
+ defaultOpen = true,
254
+ open: openProp,
255
+ onOpenChange: setOpenProp,
256
+ className,
257
+ style,
258
+ children,
259
+ ...props
260
+ }) {
261
+ const isMobile = useIsMobile();
262
+ const [openMobile, setOpenMobile] = React3.useState(false);
263
+ const [_open, _setOpen] = React3.useState(defaultOpen);
264
+ const open = openProp ?? _open;
265
+ const setOpen = React3.useCallback(
266
+ (value) => {
267
+ const openState = typeof value === "function" ? value(open) : value;
268
+ if (setOpenProp) {
269
+ setOpenProp(openState);
270
+ } else {
271
+ _setOpen(openState);
272
+ }
273
+ document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
274
+ },
275
+ [setOpenProp, open]
276
+ );
277
+ const toggleSidebar = React3.useCallback(() => {
278
+ return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
279
+ }, [isMobile, setOpen, setOpenMobile]);
280
+ React3.useEffect(() => {
281
+ const handleKeyDown = (event) => {
282
+ if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
283
+ event.preventDefault();
284
+ toggleSidebar();
285
+ }
218
286
  };
287
+ window.addEventListener("keydown", handleKeyDown);
288
+ return () => window.removeEventListener("keydown", handleKeyDown);
289
+ }, [toggleSidebar]);
290
+ const state = open ? "expanded" : "collapsed";
291
+ const contextValue = React3.useMemo(
292
+ () => ({
293
+ state,
294
+ open,
295
+ setOpen,
296
+ isMobile,
297
+ openMobile,
298
+ setOpenMobile,
299
+ toggleSidebar
300
+ }),
301
+ [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
302
+ );
303
+ return /* @__PURE__ */ jsx(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx(
304
+ "div",
305
+ {
306
+ "data-slot": "sidebar-wrapper",
307
+ style: {
308
+ "--sidebar-width": SIDEBAR_WIDTH,
309
+ "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
310
+ ...style
311
+ },
312
+ className: cn(
313
+ "group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full",
314
+ className
315
+ ),
316
+ ...props,
317
+ children
318
+ }
319
+ ) }) });
320
+ }
321
+ function Sidebar({
322
+ side = "left",
323
+ variant = "sidebar",
324
+ collapsible = "offcanvas",
325
+ className,
326
+ children,
327
+ ...props
328
+ }) {
329
+ const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
330
+ if (collapsible === "none") {
219
331
  return /* @__PURE__ */ jsx(
220
- Button,
332
+ "div",
221
333
  {
222
- ...muiProps,
223
- variant: isPrimary ? "contained" : "outlined",
224
- onClick: handleClick,
225
- children: children2
334
+ "data-slot": "sidebar",
335
+ className: cn(
336
+ "bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col",
337
+ className
338
+ ),
339
+ ...props,
340
+ children
226
341
  }
227
342
  );
228
- };
343
+ }
344
+ if (isMobile) {
345
+ return /* @__PURE__ */ jsx(Sheet, { open: openMobile, onOpenChange: setOpenMobile, ...props, children: /* @__PURE__ */ jsxs(
346
+ SheetContent,
347
+ {
348
+ "data-sidebar": "sidebar",
349
+ "data-slot": "sidebar",
350
+ "data-mobile": "true",
351
+ className: "bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden",
352
+ style: {
353
+ "--sidebar-width": SIDEBAR_WIDTH_MOBILE
354
+ },
355
+ side,
356
+ children: [
357
+ /* @__PURE__ */ jsxs(SheetHeader, { className: "sr-only", children: [
358
+ /* @__PURE__ */ jsx(SheetTitle, { children: "Sidebar" }),
359
+ /* @__PURE__ */ jsx(SheetDescription, { children: "Displays the mobile sidebar." })
360
+ ] }),
361
+ /* @__PURE__ */ jsx("div", { className: "flex h-full w-full flex-col", children })
362
+ ]
363
+ }
364
+ ) });
365
+ }
229
366
  return /* @__PURE__ */ jsxs(
230
- Box,
367
+ "div",
231
368
  {
232
- id,
233
- className,
234
- onClick: handleCardClick,
235
- sx: {
236
- backgroundColor: theme.palette.background.default,
237
- borderRadius: theme.spacing(3),
238
- overflow: "auto",
239
- display: "flex",
240
- flexDirection: "column",
241
- fontFamily: theme.typography.fontFamily,
242
- width: isInline ? "220px" : "100%",
243
- maxWidth: isInline ? "220px" : `${imageMaxWidth}px`,
244
- maxHeight: maxHeight ? `${maxHeight}px` : void 0,
245
- cursor: isInline ? "pointer" : "default",
246
- userSelect: "none",
247
- marginLeft: isInline ? void 0 : "auto",
248
- marginRight: isInline ? void 0 : "auto",
249
- ...variant === "bordered" && {
250
- border: `1px solid ${theme.palette.divider}`
251
- },
252
- ...variant === "elevated" && {
253
- boxShadow: theme.shadows[2],
254
- border: `1px solid ${theme.palette.divider}`
255
- }
256
- },
257
- ...props,
369
+ className: "group peer text-sidebar-foreground hidden md:block",
370
+ "data-state": state,
371
+ "data-collapsible": state === "collapsed" ? collapsible : "",
372
+ "data-variant": variant,
373
+ "data-side": side,
374
+ "data-slot": "sidebar",
258
375
  children: [
259
- image && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(
260
- Box,
376
+ /* @__PURE__ */ jsx(
377
+ "div",
261
378
  {
262
- component: "img",
263
- src: image,
264
- alt: imageAlt,
265
- loading: "lazy",
266
- sx: {
267
- width: "100%",
268
- height: "auto",
269
- aspectRatio: "1",
270
- objectFit: "cover",
271
- borderRadius: theme.spacing(3),
272
- display: "block",
273
- maxWidth: `${imageMaxWidth}px`,
274
- maxHeight: `${imageMaxHeight}px`
275
- }
379
+ "data-slot": "sidebar-gap",
380
+ className: cn(
381
+ "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
382
+ "group-data-[collapsible=offcanvas]:w-0",
383
+ "group-data-[side=right]:rotate-180",
384
+ variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
385
+ )
276
386
  }
277
- ) }),
278
- /* @__PURE__ */ jsxs(
279
- Box,
387
+ ),
388
+ /* @__PURE__ */ jsx(
389
+ "div",
280
390
  {
281
- sx: {
282
- display: "flex",
283
- flexDirection: "column",
284
- flex: 1,
285
- gap: isInline ? theme.spacing(3) : theme.spacing(4),
286
- padding: isInline ? theme.spacing(4) : theme.spacing(6),
287
- ...image && {
288
- paddingTop: isInline ? theme.spacing(3) : theme.spacing(4)
391
+ "data-slot": "sidebar-container",
392
+ className: cn(
393
+ "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex",
394
+ side === "left" ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
395
+ variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
396
+ className
397
+ ),
398
+ ...props,
399
+ children: /* @__PURE__ */ jsx(
400
+ "div",
401
+ {
402
+ "data-sidebar": "sidebar",
403
+ "data-slot": "sidebar-inner",
404
+ className: "bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm",
405
+ children
289
406
  }
290
- },
291
- children: [
292
- /* @__PURE__ */ jsxs(
293
- Box,
294
- {
295
- sx: {
296
- display: "flex",
297
- flexDirection: "column",
298
- flex: 1,
299
- gap: isInline ? theme.spacing(1) : theme.spacing(2)
300
- },
301
- children: [
302
- header && /* @__PURE__ */ jsx(
303
- Box,
304
- {
305
- sx: {
306
- fontSize: theme.typography.body1.fontSize,
307
- fontWeight: theme.typography.fontWeightMedium,
308
- color: theme.palette.text.primary,
309
- lineHeight: 1.25,
310
- overflow: "hidden",
311
- textOverflow: "ellipsis",
312
- whiteSpace: "nowrap"
313
- },
314
- children: header
315
- }
316
- ),
317
- metadata && /* @__PURE__ */ jsx(
318
- Box,
319
- {
320
- sx: {
321
- fontSize: theme.typography.caption.fontSize,
322
- color: theme.palette.text.secondary,
323
- lineHeight: 1.5
324
- },
325
- children: metadata
326
- }
327
- ),
328
- children && /* @__PURE__ */ jsx(
329
- Box,
330
- {
331
- sx: {
332
- fontSize: theme.typography.body2.fontSize,
333
- color: theme.palette.text.primary,
334
- lineHeight: 1.5,
335
- display: "-webkit-box",
336
- WebkitBoxOrient: "vertical",
337
- overflow: "hidden",
338
- ...isInline && (metadata || header) && {
339
- marginTop: theme.spacing(1),
340
- WebkitLineClamp: 2
341
- },
342
- ...!isInline && (metadata || header) && {
343
- marginTop: theme.spacing(2),
344
- WebkitLineClamp: "unset"
345
- }
346
- },
347
- children
348
- }
349
- )
350
- ]
351
- }
352
- ),
353
- hasButtons && /* @__PURE__ */ jsxs(
354
- Box,
355
- {
356
- sx: {
357
- display: "flex",
358
- gap: theme.spacing(2),
359
- flexWrap: "wrap"
360
- },
361
- children: [
362
- button1 && renderButton(button1),
363
- button2 && renderButton(button2)
364
- ]
365
- }
366
- )
367
- ]
407
+ )
368
408
  }
369
409
  )
370
410
  ]
371
411
  }
372
412
  );
373
- };
374
- var ChevronLeftIcon = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
375
- "path",
376
- {
377
- d: "M15 18L9 12L15 6",
378
- stroke: "currentColor",
379
- strokeWidth: "1.5",
380
- strokeLinecap: "round",
381
- strokeLinejoin: "round"
382
- }
383
- ) });
384
- var ChevronRightIcon = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
385
- "path",
386
- {
387
- d: "M9 18L15 12L9 6",
388
- stroke: "currentColor",
389
- strokeWidth: "1.5",
390
- strokeLinecap: "round",
391
- strokeLinejoin: "round"
392
- }
393
- ) });
394
- var Carousel = ({
395
- children,
396
- gap = 16,
397
- maxWidth = 800,
398
- showArrows = true,
399
- showEdgeGradients = true,
400
- cardWidth: cardWidthProp,
413
+ }
414
+ function SidebarInset({ className, ...props }) {
415
+ return /* @__PURE__ */ jsx(
416
+ "main",
417
+ {
418
+ "data-slot": "sidebar-inset",
419
+ className: cn(
420
+ "bg-background relative flex w-full flex-1 flex-col",
421
+ "md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
422
+ className
423
+ ),
424
+ ...props
425
+ }
426
+ );
427
+ }
428
+ function SidebarContent({ className, ...props }) {
429
+ return /* @__PURE__ */ jsx(
430
+ "div",
431
+ {
432
+ "data-slot": "sidebar-content",
433
+ "data-sidebar": "content",
434
+ className: cn(
435
+ "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
436
+ className
437
+ ),
438
+ ...props
439
+ }
440
+ );
441
+ }
442
+ function SidebarGroup({ className, ...props }) {
443
+ return /* @__PURE__ */ jsx(
444
+ "div",
445
+ {
446
+ "data-slot": "sidebar-group",
447
+ "data-sidebar": "group",
448
+ className: cn("relative flex w-full min-w-0 flex-col p-2", className),
449
+ ...props
450
+ }
451
+ );
452
+ }
453
+ function SidebarGroupLabel({
401
454
  className,
455
+ asChild = false,
402
456
  ...props
403
- }) => {
404
- const scrollRef = useRef(null);
405
- const [canScrollLeft, setCanScrollLeft] = useState(false);
406
- const [canScrollRight, setCanScrollRight] = useState(false);
407
- const [isDragging, setIsDragging] = useState(false);
408
- const [startX, setStartX] = useState(0);
409
- const [scrollLeft, setScrollLeft] = useState(0);
410
- const maxHeight = useMaxHeight();
411
- const displayMode = useDisplayMode();
412
- const theme = useTheme();
413
- const isFullscreen = displayMode === "fullscreen";
414
- const getCardWidth = () => {
415
- if (typeof cardWidthProp === "number") {
416
- return cardWidthProp;
417
- }
418
- if (typeof cardWidthProp === "object") {
419
- return isFullscreen ? cardWidthProp.fullscreen ?? 340 : cardWidthProp.inline ?? 220;
457
+ }) {
458
+ const Comp = asChild ? Slot : "div";
459
+ return /* @__PURE__ */ jsx(
460
+ Comp,
461
+ {
462
+ "data-slot": "sidebar-group-label",
463
+ "data-sidebar": "group-label",
464
+ className: cn(
465
+ "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
466
+ "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
467
+ className
468
+ ),
469
+ ...props
420
470
  }
421
- return isFullscreen ? 340 : 220;
422
- };
423
- const cardWidth = getCardWidth();
424
- const checkScroll = () => {
425
- const el = scrollRef.current;
426
- if (!el) return;
427
- setCanScrollLeft(el.scrollLeft > 0);
428
- setCanScrollRight(el.scrollLeft < el.scrollWidth - el.clientWidth - 1);
429
- };
430
- useEffect(() => {
431
- checkScroll();
432
- const el = scrollRef.current;
433
- if (!el) return;
434
- el.addEventListener("scroll", checkScroll);
435
- window.addEventListener("resize", checkScroll);
436
- return () => {
437
- el.removeEventListener("scroll", checkScroll);
438
- window.removeEventListener("resize", checkScroll);
439
- };
440
- }, []);
441
- const scroll = (direction) => {
442
- const el = scrollRef.current;
443
- if (!el) return;
444
- const firstCard = el.children[0];
445
- if (!firstCard) return;
446
- const cardWidth2 = firstCard.offsetWidth;
447
- const scrollAmount = cardWidth2 + gap;
448
- const targetScroll = direction === "left" ? el.scrollLeft - scrollAmount : el.scrollLeft + scrollAmount;
449
- el.scrollTo({
450
- left: targetScroll,
451
- behavior: "smooth"
452
- });
453
- };
454
- const handleMouseDown = (e) => {
455
- const el = scrollRef.current;
456
- if (!el) return;
457
- setIsDragging(true);
458
- setStartX(e.pageX - el.offsetLeft);
459
- setScrollLeft(el.scrollLeft);
460
- };
461
- const handleMouseMove = (e) => {
462
- if (!isDragging) return;
463
- e.preventDefault();
464
- const el = scrollRef.current;
465
- if (!el) return;
466
- const x = e.pageX - el.offsetLeft;
467
- const walk = (x - startX) * 2;
468
- el.scrollLeft = scrollLeft - walk;
469
- };
470
- const handleMouseUpOrLeave = () => {
471
- setIsDragging(false);
472
- };
473
- return /* @__PURE__ */ jsxs(
474
- Box,
471
+ );
472
+ }
473
+ function SidebarGroupContent({
474
+ className,
475
+ ...props
476
+ }) {
477
+ return /* @__PURE__ */ jsx(
478
+ "div",
475
479
  {
476
- className,
477
- sx: {
478
- position: "relative",
479
- width: "100%",
480
- maxWidth: `${maxWidth}px`,
481
- maxHeight: maxHeight ? `${maxHeight}px` : void 0
482
- },
483
- ...props,
484
- children: [
485
- /* @__PURE__ */ jsx(Box, { sx: { overflow: "hidden" }, children: /* @__PURE__ */ jsx(
486
- Box,
487
- {
488
- ref: scrollRef,
489
- onMouseDown: handleMouseDown,
490
- onMouseMove: handleMouseMove,
491
- onMouseUp: handleMouseUpOrLeave,
492
- onMouseLeave: handleMouseUpOrLeave,
493
- sx: {
494
- display: "flex",
495
- gap: `${gap}px`,
496
- overflowX: "auto",
497
- overflowY: "hidden",
498
- scrollBehavior: isDragging ? "auto" : "smooth",
499
- scrollbarWidth: "none",
500
- msOverflowStyle: "none",
501
- userSelect: "none",
502
- cursor: isDragging ? "grabbing" : "grab",
503
- "&::-webkit-scrollbar": {
504
- display: "none"
505
- }
506
- },
507
- children: Children.map(children, (child) => /* @__PURE__ */ jsx(
508
- Box,
509
- {
510
- sx: {
511
- flexShrink: 0,
512
- width: `${cardWidth}px`,
513
- "& > *": {
514
- width: "100%",
515
- maxWidth: "100%"
516
- }
517
- },
518
- children: child
519
- }
520
- ))
521
- }
522
- ) }),
523
- showEdgeGradients && canScrollLeft && /* @__PURE__ */ jsx(
524
- Box,
525
- {
526
- "aria-hidden": "true",
527
- sx: {
528
- position: "absolute",
529
- top: 0,
530
- bottom: 0,
531
- left: 0,
532
- width: "80px",
533
- pointerEvents: "none",
534
- background: `linear-gradient(to right, ${theme.palette.background.default} 0%, transparent 100%)`,
535
- opacity: canScrollLeft ? 1 : 0,
536
- transition: "opacity 0.2s ease",
537
- zIndex: 1
538
- }
539
- }
540
- ),
541
- showEdgeGradients && canScrollRight && /* @__PURE__ */ jsx(
542
- Box,
543
- {
544
- "aria-hidden": "true",
545
- sx: {
546
- position: "absolute",
547
- top: 0,
548
- bottom: 0,
549
- right: 0,
550
- width: "80px",
551
- pointerEvents: "none",
552
- background: `linear-gradient(to left, ${theme.palette.background.default} 0%, transparent 100%)`,
553
- opacity: canScrollRight ? 1 : 0,
554
- transition: "opacity 0.2s ease",
555
- zIndex: 1
556
- }
557
- }
558
- ),
559
- showArrows && canScrollLeft && /* @__PURE__ */ jsx(
560
- IconButton,
561
- {
562
- "aria-label": "Previous",
563
- onClick: () => scroll("left"),
564
- sx: {
565
- position: "absolute",
566
- top: "50%",
567
- left: theme.spacing(0.5),
568
- transform: "translateY(-50%)",
569
- width: 32,
570
- height: 32,
571
- backgroundColor: theme.palette.background.default,
572
- boxShadow: theme.shadows[2],
573
- zIndex: 2,
574
- "&:hover": {
575
- boxShadow: theme.shadows[3],
576
- transform: "translateY(-50%) scale(1.05)"
577
- },
578
- "&:active": {
579
- transform: "translateY(-50%) scale(0.95)"
580
- },
581
- transition: "all 0.2s ease"
582
- },
583
- children: /* @__PURE__ */ jsx(ChevronLeftIcon, {})
584
- }
585
- ),
586
- showArrows && canScrollRight && /* @__PURE__ */ jsx(
587
- IconButton,
588
- {
589
- "aria-label": "Next",
590
- onClick: () => scroll("right"),
591
- sx: {
592
- position: "absolute",
593
- top: "50%",
594
- right: theme.spacing(0.5),
595
- transform: "translateY(-50%)",
596
- width: 32,
597
- height: 32,
598
- backgroundColor: theme.palette.background.default,
599
- boxShadow: theme.shadows[2],
600
- zIndex: 2,
601
- "&:hover": {
602
- boxShadow: theme.shadows[3],
603
- transform: "translateY(-50%) scale(1.05)"
604
- },
605
- "&:active": {
606
- transform: "translateY(-50%) scale(0.95)"
607
- },
608
- transition: "all 0.2s ease"
609
- },
610
- children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
611
- }
612
- )
613
- ]
480
+ "data-slot": "sidebar-group-content",
481
+ "data-sidebar": "group-content",
482
+ className: cn("w-full text-sm", className),
483
+ ...props
614
484
  }
615
485
  );
616
- };
617
- var baseThemeOptions = {
618
- spacing: 4,
619
- // 4px base unit
620
- shape: {
621
- borderRadius: 8
622
- // Default border radius in pixels
623
- },
624
- typography: {
625
- fontFamily: [
626
- "-apple-system",
627
- "BlinkMacSystemFont",
628
- '"Segoe UI"',
629
- "Roboto",
630
- '"Helvetica Neue"',
631
- "Arial",
632
- "sans-serif"
633
- ].join(",")
634
- },
635
- // Common breakpoints for responsive design
636
- breakpoints: {
637
- values: {
638
- xs: 0,
639
- sm: 600,
640
- md: 900,
641
- lg: 1200,
642
- xl: 1536
486
+ }
487
+ cva(
488
+ "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
489
+ {
490
+ variants: {
491
+ variant: {
492
+ default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
493
+ outline: "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]"
494
+ },
495
+ size: {
496
+ default: "h-8 text-sm",
497
+ sm: "h-7 text-xs",
498
+ lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!"
499
+ }
500
+ },
501
+ defaultVariants: {
502
+ variant: "default",
503
+ size: "default"
643
504
  }
644
505
  }
645
- };
646
- var createBaseTheme = () => createTheme(baseThemeOptions);
647
-
648
- // src/themes/chatgpt.ts
649
- var lightPalette = {
650
- mode: "light",
651
- primary: {
652
- main: "#f46c21",
653
- dark: "#d45e1c",
654
- light: "rgba(244, 108, 33, 0.9)",
655
- contrastText: "#ffffff"
656
- },
657
- secondary: {
658
- main: "#5d5d5d",
659
- contrastText: "#ffffff"
660
- },
661
- error: {
662
- main: "#e02e2a",
663
- contrastText: "#ffffff"
664
- },
665
- warning: {
666
- main: "#e25507",
667
- contrastText: "#ffffff"
668
- },
669
- info: {
670
- main: "#0285ff",
671
- contrastText: "#ffffff"
672
- },
673
- success: {
674
- main: "#008635",
675
- contrastText: "#ffffff"
676
- },
677
- background: {
678
- default: "#ffffff",
679
- paper: "#f3f3f3"
680
- },
681
- text: {
682
- primary: "#0d0d0d",
683
- secondary: "#5d5d5d",
684
- disabled: "#8f8f8f"
685
- },
686
- divider: "rgba(0, 0, 0, 0.15)",
687
- action: {
688
- hover: "rgba(0, 0, 0, 0.04)",
689
- selected: "rgba(0, 0, 0, 0.08)",
690
- disabled: "#8f8f8f",
691
- disabledBackground: "rgba(0, 0, 0, 0.12)"
692
- },
693
- grey: {
694
- 50: "#f3f3f3",
695
- 100: "#e8e8e8",
696
- 200: "rgba(0, 0, 0, 0.05)",
697
- 300: "rgba(0, 0, 0, 0.15)",
698
- 400: "#8f8f8f",
699
- 500: "#5d5d5d",
700
- 900: "#0d0d0d"
506
+ );
507
+ var Select = SelectPrimitive.Root;
508
+ var SelectValue = SelectPrimitive.Value;
509
+ var SelectTrigger = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
510
+ SelectPrimitive.Trigger,
511
+ {
512
+ ref,
513
+ className: cn(
514
+ "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
515
+ className
516
+ ),
517
+ ...props,
518
+ children: [
519
+ children,
520
+ /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 opacity-50" }) })
521
+ ]
701
522
  }
702
- };
703
- var darkPalette = {
704
- mode: "dark",
705
- primary: {
706
- main: "#f46c21",
707
- dark: "#d45e1c",
708
- light: "rgba(244, 108, 33, 0.9)",
709
- contrastText: "#ffffff"
710
- },
711
- secondary: {
712
- main: "#cdcdcd",
713
- contrastText: "#212121"
714
- },
715
- error: {
716
- main: "#ff8583",
717
- contrastText: "#212121"
718
- },
719
- warning: {
720
- main: "#ff9e6c",
721
- contrastText: "#212121"
722
- },
723
- info: {
724
- main: "#0285ff",
725
- contrastText: "#ffffff"
726
- },
727
- success: {
728
- main: "#40c977",
729
- contrastText: "#212121"
730
- },
731
- background: {
732
- default: "#212121",
733
- paper: "#414141"
734
- },
735
- text: {
736
- primary: "#ffffff",
737
- secondary: "#cdcdcd",
738
- disabled: "#afafaf"
739
- },
740
- divider: "rgba(0, 0, 0, 0.15)",
741
- action: {
742
- hover: "rgba(255, 255, 255, 0.08)",
743
- selected: "rgba(255, 255, 255, 0.16)",
744
- disabled: "#afafaf",
745
- disabledBackground: "rgba(255, 255, 255, 0.12)"
746
- },
747
- grey: {
748
- 50: "#414141",
749
- 100: "#303030",
750
- 200: "rgba(0, 0, 0, 0.05)",
751
- 300: "rgba(0, 0, 0, 0.15)",
752
- 400: "#afafaf",
753
- 500: "#cdcdcd",
754
- 900: "#ffffff",
755
- 800: "#212121"
523
+ ));
524
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
525
+ var SelectScrollUpButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
526
+ SelectPrimitive.ScrollUpButton,
527
+ {
528
+ ref,
529
+ className: cn(
530
+ "flex cursor-default items-center justify-center py-1",
531
+ className
532
+ ),
533
+ ...props,
534
+ children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4" })
756
535
  }
757
- };
758
- var typography = {
759
- fontFamily: [
760
- "-apple-system",
761
- "BlinkMacSystemFont",
762
- '"Segoe UI"',
763
- "Roboto",
764
- '"Helvetica Neue"',
765
- "Arial",
766
- "sans-serif"
767
- ].join(","),
768
- fontSize: 16,
769
- fontWeightLight: 300,
770
- fontWeightRegular: 400,
771
- fontWeightMedium: 500,
772
- fontWeightBold: 600,
773
- h1: {
774
- fontSize: "1.25rem",
775
- fontWeight: 600,
776
- lineHeight: 1.25
777
- },
778
- h2: {
779
- fontSize: "1.125rem",
780
- fontWeight: 600,
781
- lineHeight: 1.25
782
- },
783
- h3: {
784
- fontSize: "1rem",
785
- fontWeight: 600,
786
- lineHeight: 1.25
787
- },
788
- h4: {
789
- fontSize: "1rem",
790
- fontWeight: 500,
791
- lineHeight: 1.25
792
- },
793
- h5: {
794
- fontSize: "0.875rem",
795
- fontWeight: 600,
796
- lineHeight: 1.25
797
- },
798
- h6: {
799
- fontSize: "0.75rem",
800
- fontWeight: 600,
801
- lineHeight: 1.25
802
- },
803
- body1: {
804
- fontSize: "1rem",
805
- lineHeight: 1.5
806
- },
807
- body2: {
808
- fontSize: "0.875rem",
809
- lineHeight: 1.5
810
- },
811
- button: {
812
- fontSize: "0.875rem",
813
- fontWeight: 500,
814
- lineHeight: 1.25,
815
- textTransform: "none"
816
- },
817
- caption: {
818
- fontSize: "0.75rem",
819
- lineHeight: 1.5
820
- },
821
- overline: {
822
- fontSize: "0.75rem",
823
- fontWeight: 500,
824
- lineHeight: 1.5,
825
- textTransform: "uppercase"
536
+ ));
537
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
538
+ var SelectScrollDownButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
539
+ SelectPrimitive.ScrollDownButton,
540
+ {
541
+ ref,
542
+ className: cn(
543
+ "flex cursor-default items-center justify-center py-1",
544
+ className
545
+ ),
546
+ ...props,
547
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
826
548
  }
827
- };
828
- var spacing = 4;
829
- var shape = {
830
- borderRadius: 8
831
- };
832
- var shadows = [
833
- "none",
834
- "0px 1px 2px rgba(0, 0, 0, 0.05)",
835
- "0px 2px 6px rgba(0, 0, 0, 0.06)",
836
- "0px 4px 12px rgba(0, 0, 0, 0.1)",
837
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
838
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
839
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
840
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
841
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
842
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
843
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
844
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
845
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
846
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
847
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
848
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
849
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
850
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
851
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
852
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
853
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
854
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
855
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
856
- "0px 8px 24px rgba(0, 0, 0, 0.12)",
857
- "0px 8px 24px rgba(0, 0, 0, 0.12)"
858
- ];
859
- var components = {
860
- MuiButton: {
861
- styleOverrides: {
862
- root: {
863
- borderRadius: "0.5rem",
864
- padding: "0.375rem 1rem",
865
- fontSize: "0.875rem",
866
- fontWeight: 500,
867
- textTransform: "none",
868
- transition: "all 0.2s ease"
869
- },
870
- contained: {
871
- boxShadow: "none",
872
- "&:hover": {
873
- boxShadow: "none"
549
+ ));
550
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
551
+ var SelectContent = React3.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
552
+ SelectPrimitive.Content,
553
+ {
554
+ ref,
555
+ className: cn(
556
+ "relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-select-content-transform-origin]",
557
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
558
+ className
559
+ ),
560
+ position,
561
+ ...props,
562
+ children: [
563
+ /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
564
+ /* @__PURE__ */ jsx(
565
+ SelectPrimitive.Viewport,
566
+ {
567
+ className: cn(
568
+ "p-1",
569
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
570
+ ),
571
+ children
874
572
  }
573
+ ),
574
+ /* @__PURE__ */ jsx(SelectScrollDownButton, {})
575
+ ]
576
+ }
577
+ ) }));
578
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
579
+ var SelectLabel = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
580
+ SelectPrimitive.Label,
581
+ {
582
+ ref,
583
+ className: cn("px-2 py-1.5 text-sm font-semibold", className),
584
+ ...props
585
+ }
586
+ ));
587
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
588
+ var SelectItem = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
589
+ SelectPrimitive.Item,
590
+ {
591
+ ref,
592
+ className: cn(
593
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
594
+ className
595
+ ),
596
+ ...props,
597
+ children: [
598
+ /* @__PURE__ */ jsx("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) }) }),
599
+ /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
600
+ ]
601
+ }
602
+ ));
603
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
604
+ var SelectSeparator = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
605
+ SelectPrimitive.Separator,
606
+ {
607
+ ref,
608
+ className: cn("-mx-1 my-1 h-px bg-muted", className),
609
+ ...props
610
+ }
611
+ ));
612
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
613
+ var labelVariants = cva(
614
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
615
+ );
616
+ var Label2 = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
617
+ LabelPrimitive.Root,
618
+ {
619
+ ref,
620
+ className: cn(labelVariants(), className),
621
+ ...props
622
+ }
623
+ ));
624
+ Label2.displayName = LabelPrimitive.Root.displayName;
625
+ function Conversation({
626
+ children,
627
+ screenWidth,
628
+ displayMode,
629
+ appName = "ChatGPT",
630
+ appIcon,
631
+ userMessage = "Show me some interesting places to visit."
632
+ }) {
633
+ const containerWidth = screenWidth === "full" ? "100%" : `${SCREEN_WIDTHS[screenWidth]}px`;
634
+ if (displayMode === "fullscreen") {
635
+ return /* @__PURE__ */ jsx(SidebarInset, { className: "flex flex-col bg-background", children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto", children }) });
636
+ }
637
+ return /* @__PURE__ */ jsxs(SidebarInset, { className: "flex flex-col bg-background", children: [
638
+ /* @__PURE__ */ jsx("header", { className: "h-12 border-b border-border bg-background flex items-center px-4 text-lg", children: /* @__PURE__ */ jsx("span", { className: "text-foreground", children: "ChatGPT" }) }),
639
+ /* @__PURE__ */ jsxs(
640
+ "div",
641
+ {
642
+ className: "flex flex-col flex-1 mx-auto w-full transition-all duration-200 overflow-hidden",
643
+ style: { maxWidth: containerWidth },
644
+ children: [
645
+ /* @__PURE__ */ jsxs("main", { className: "flex-1 overflow-y-auto overflow-x-hidden", children: [
646
+ /* @__PURE__ */ jsxs(
647
+ "article",
648
+ {
649
+ className: "text-foreground w-full focus:outline-none",
650
+ dir: "auto",
651
+ "data-turn": "user",
652
+ children: [
653
+ /* @__PURE__ */ jsx("h5", { className: "sr-only", children: "You said:" }),
654
+ /* @__PURE__ */ jsx("div", { className: "text-base my-auto mx-auto pt-12 px-4", children: /* @__PURE__ */ jsx("div", { className: "max-w-[48rem] mx-auto flex-1 relative flex w-full min-w-0 flex-col", children: /* @__PURE__ */ jsx("div", { className: "flex max-w-full flex-col grow", children: /* @__PURE__ */ jsx(
655
+ "div",
656
+ {
657
+ "data-message-author-role": "user",
658
+ className: "min-h-8 relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal",
659
+ children: /* @__PURE__ */ jsx("div", { className: "flex w-full flex-col gap-1 empty:hidden items-end", children: /* @__PURE__ */ jsx("div", { className: "bg-secondary text-secondary-foreground relative rounded-[18px] px-4 py-3 max-w-[70%]", children: /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap", children: userMessage }) }) })
660
+ }
661
+ ) }) }) })
662
+ ]
663
+ }
664
+ ),
665
+ /* @__PURE__ */ jsxs(
666
+ "article",
667
+ {
668
+ className: "text-foreground w-full focus:outline-none",
669
+ dir: "auto",
670
+ "data-turn": "assistant",
671
+ children: [
672
+ /* @__PURE__ */ jsxs("h6", { className: "sr-only", children: [
673
+ appName,
674
+ " said:"
675
+ ] }),
676
+ /* @__PURE__ */ jsx("div", { className: "text-base my-auto mx-auto pb-10 px-4", children: /* @__PURE__ */ jsx("div", { className: "max-w-[48rem] mx-auto flex-1 relative flex w-full min-w-0 flex-col", children: /* @__PURE__ */ jsxs("div", { className: "flex max-w-full flex-col grow", children: [
677
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
678
+ appIcon ? /* @__PURE__ */ jsx("div", { className: "size-6 flex items-center justify-center text-base", children: appIcon }) : /* @__PURE__ */ jsx("div", { className: "size-6 rounded-full bg-primary flex items-center justify-center text-primary-foreground font-medium text-xs", children: "AI" }),
679
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-sm", children: appName })
680
+ ] }),
681
+ /* @__PURE__ */ jsx(
682
+ "div",
683
+ {
684
+ "data-message-author-role": "assistant",
685
+ className: "min-h-8 relative flex w-full flex-col items-start gap-2 text-start break-words whitespace-normal",
686
+ children: /* @__PURE__ */ jsx("div", { className: "flex w-full flex-col gap-1 empty:hidden", children: /* @__PURE__ */ jsx(
687
+ "div",
688
+ {
689
+ className: cn(
690
+ "w-full overflow-x-auto",
691
+ displayMode === "pip" && "fixed bottom-20 right-6 z-50 w-80 rounded-xl shadow-xl border bg-card p-4 overflow-x-hidden"
692
+ ),
693
+ children
694
+ }
695
+ ) })
696
+ }
697
+ )
698
+ ] }) }) })
699
+ ]
700
+ }
701
+ )
702
+ ] }),
703
+ /* @__PURE__ */ jsx("footer", { className: "bg-background", children: /* @__PURE__ */ jsx("div", { className: "max-w-[48rem] mx-auto px-4 py-4", children: /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(
704
+ "input",
705
+ {
706
+ type: "text",
707
+ disabled: true,
708
+ placeholder: "Message ChatGPT",
709
+ className: "w-full bg-secondary text-secondary-foreground placeholder:text-muted-foreground rounded-3xl px-5 py-3 pr-12 outline-none"
710
+ }
711
+ ) }) }) })
712
+ ]
875
713
  }
876
- }
877
- },
878
- MuiCard: {
879
- styleOverrides: {
880
- root: {
881
- borderRadius: "0.75rem",
882
- overflow: "hidden"
714
+ )
715
+ ] });
716
+ }
717
+
718
+ // src/components/simulator/mock-openai.ts
719
+ var MockOpenAI = class {
720
+ constructor() {
721
+ __publicField(this, "theme", "light");
722
+ __publicField(this, "userAgent", {
723
+ device: { type: "desktop" },
724
+ capabilities: {
725
+ hover: true,
726
+ touch: false
883
727
  }
884
- }
885
- },
886
- MuiPaper: {
887
- styleOverrides: {
888
- rounded: {
889
- borderRadius: "0.75rem"
728
+ });
729
+ __publicField(this, "locale", "en-US");
730
+ __publicField(this, "maxHeight", 600);
731
+ __publicField(this, "displayMode", "inline");
732
+ __publicField(this, "safeArea", {
733
+ insets: {
734
+ top: 0,
735
+ bottom: 0,
736
+ left: 0,
737
+ right: 0
890
738
  }
739
+ });
740
+ __publicField(this, "toolInput", {});
741
+ __publicField(this, "toolOutput", null);
742
+ __publicField(this, "toolResponseMetadata", null);
743
+ __publicField(this, "widgetState", null);
744
+ }
745
+ async callTool(name, args) {
746
+ console.log("Mock callTool:", name, args);
747
+ return { result: JSON.stringify({ success: true }) };
748
+ }
749
+ async sendFollowUpMessage(args) {
750
+ console.log("Mock sendFollowUpMessage:", args.prompt);
751
+ }
752
+ openExternal(payload) {
753
+ console.log("Mock openExternal:", payload.href);
754
+ window.open(payload.href, "_blank");
755
+ }
756
+ async requestDisplayMode(args) {
757
+ this.setDisplayMode(args.mode);
758
+ return { mode: args.mode };
759
+ }
760
+ async setWidgetState(state) {
761
+ this.widgetState = state;
762
+ this.emitUpdate({ widgetState: state });
763
+ }
764
+ setTheme(theme) {
765
+ this.theme = theme;
766
+ this.emitUpdate({ theme });
767
+ }
768
+ setDisplayMode(displayMode) {
769
+ this.displayMode = displayMode;
770
+ this.emitUpdate({ displayMode });
771
+ }
772
+ emitUpdate(globals) {
773
+ if (typeof window !== "undefined") {
774
+ const event = new CustomEvent(SET_GLOBALS_EVENT_TYPE, {
775
+ detail: { globals }
776
+ });
777
+ window.dispatchEvent(event);
891
778
  }
892
779
  }
893
780
  };
894
- var chatgptLightTheme = createTheme({
895
- ...baseThemeOptions,
896
- palette: lightPalette,
897
- typography,
898
- spacing,
899
- shape,
900
- shadows,
901
- components
902
- });
903
- var chatgptDarkTheme = createTheme({
904
- ...baseThemeOptions,
905
- palette: darkPalette,
906
- typography,
907
- spacing,
908
- shape,
909
- shadows,
910
- components
911
- });
912
- var getChatGPTTheme = (mode) => {
913
- return mode === "dark" ? chatgptDarkTheme : chatgptLightTheme;
914
- };
915
-
916
- // src/themes/index.ts
917
- var getCurrentPlatform = () => {
918
- return "chatgpt";
919
- };
920
- var platformThemes = {
921
- chatgpt: getChatGPTTheme
922
- // Add more platforms here:
923
- // gemini: getGeminiTheme,
924
- // claude: getClaudeTheme,
925
- };
926
- var getTheme = (mode) => {
927
- const platform = getCurrentPlatform();
928
- const themeGetter = platformThemes[platform];
929
- if (!themeGetter) {
930
- console.warn(`Unknown platform "${platform}", falling back to chatgpt theme`);
931
- return getChatGPTTheme(mode);
781
+ function initMockOpenAI() {
782
+ if (typeof window !== "undefined") {
783
+ const mock = new MockOpenAI();
784
+ window.openai = mock;
785
+ return mock;
932
786
  }
933
- return themeGetter(mode);
934
- };
935
- var getLightTheme = () => getTheme("light");
936
- var getDarkTheme = () => getTheme("dark");
937
- function GenAI(renderFn) {
938
- const GenAIComponent = (props = {}) => {
939
- const maxHeight = useMaxHeight();
940
- const detectedColorScheme = useColorScheme();
941
- const {
942
- className,
943
- maxWidth = 800,
944
- mode: overrideMode,
945
- enableCssBaseline = true,
946
- ...rest
947
- } = props;
948
- const colorScheme = overrideMode || detectedColorScheme || "light";
949
- const theme = getTheme(colorScheme);
950
- return /* @__PURE__ */ jsxs(ThemeProvider, { theme, children: [
951
- enableCssBaseline && /* @__PURE__ */ jsx(CssBaseline, {}),
952
- /* @__PURE__ */ jsx(
953
- Box,
954
- {
955
- className,
956
- sx: {
957
- maxWidth: `${maxWidth}px`,
958
- maxHeight: maxHeight ? `${maxHeight}px` : void 0
959
- },
960
- ...rest,
961
- children: renderFn({ maxHeight, colorScheme })
962
- }
963
- )
964
- ] });
965
- };
966
- GenAIComponent.displayName = "GenAI";
967
- return GenAIComponent;
787
+ return new MockOpenAI();
968
788
  }
969
789
  function ChatGPTSimulator({
970
790
  children,
971
- displayMode: initialDisplayMode = "inline",
972
- colorScheme: initialColorScheme = "dark",
973
- toolInput = {},
974
- toolOutput = null,
975
- widgetState: initialWidgetState = null,
976
- userMessage = "Show me some recommendations",
977
- showControls = true,
978
- uiSimulations,
979
- initialUISimulation
791
+ appName,
792
+ appIcon,
793
+ userMessage
980
794
  }) {
981
- const [displayMode, setDisplayMode] = useState(initialDisplayMode);
982
- const [widgetState, setWidgetStateInternal] = useState(
983
- initialWidgetState
984
- );
985
- const [bodyWidth, setBodyWidth] = useState("100%");
986
- const [selectedUISimulation, setSelectedUISimulation] = useState(
987
- initialUISimulation || uiSimulations?.[0] || ""
988
- );
989
- const [viewportHeight, setViewportHeight] = useState(window.innerHeight);
990
- const [colorScheme, setColorScheme] = useState(initialColorScheme);
991
- const theme = getTheme(colorScheme);
795
+ const [theme, setTheme] = useState("dark");
796
+ const [displayMode, setDisplayMode] = useState("inline");
797
+ const [screenWidth, setScreenWidth] = useState("full");
798
+ const mock = useMemo(() => initMockOpenAI(), []);
992
799
  useEffect(() => {
993
- const handleSetGlobals = (event) => {
994
- const customEvent = event;
995
- if (customEvent.detail?.globals?.colorScheme) {
996
- setColorScheme(customEvent.detail.globals.colorScheme);
800
+ return () => {
801
+ if (typeof window !== "undefined") {
802
+ delete window.openai;
997
803
  }
998
804
  };
999
- window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobals);
1000
- return () => window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobals);
1001
- }, []);
1002
- useEffect(() => {
1003
- const handleResize = () => {
1004
- setViewportHeight(window.innerHeight);
1005
- };
1006
- window.addEventListener("resize", handleResize);
1007
- return () => window.removeEventListener("resize", handleResize);
1008
805
  }, []);
1009
806
  useEffect(() => {
1010
- const inputBarHeight = 80;
1011
- const openaiGlobals = {
1012
- colorScheme,
1013
- displayMode,
1014
- locale: "en-US",
1015
- maxHeight: displayMode === "fullscreen" ? viewportHeight - inputBarHeight : 600,
1016
- userAgent: {
1017
- device: { type: "desktop" },
1018
- capabilities: { hover: true, touch: false }
1019
- },
1020
- safeArea: {
1021
- insets: { top: 0, bottom: 0, left: 0, right: 0 }
1022
- },
1023
- toolInput,
1024
- toolOutput,
1025
- toolResponseMetadata: null,
1026
- widgetState,
1027
- setWidgetState: async (state) => {
1028
- console.log("[ChatGPT Simulator] setWidgetState called:", state);
1029
- setWidgetStateInternal(state);
1030
- }
1031
- };
1032
- const openaiAPI = {
1033
- callTool: async (name, args) => {
1034
- console.log("[ChatGPT Simulator] callTool called:", name, args);
1035
- return { result: "Mock tool result" };
1036
- },
1037
- sendFollowUpMessage: async (args) => {
1038
- console.log("[ChatGPT Simulator] sendFollowUpMessage called:", args);
1039
- },
1040
- openExternal: (payload) => {
1041
- console.log("[ChatGPT Simulator] openExternal called:", payload);
1042
- window.open(payload.href, "_blank");
1043
- },
1044
- requestDisplayMode: async (args) => {
1045
- console.log("[ChatGPT Simulator] requestDisplayMode called:", args);
1046
- setDisplayMode(args.mode);
1047
- return { mode: args.mode };
1048
- }
1049
- };
1050
- window.openai = { ...openaiGlobals, ...openaiAPI };
1051
- window.dispatchEvent(
1052
- new CustomEvent(SET_GLOBALS_EVENT_TYPE, {
1053
- detail: { globals: openaiGlobals }
1054
- })
1055
- );
1056
- return () => {
1057
- delete window.openai;
1058
- };
1059
- }, [colorScheme, displayMode, toolInput, toolOutput, widgetState, viewportHeight]);
1060
- useEffect(() => {
1061
- if (window.openai) {
1062
- const inputBarHeight = 80;
1063
- const calculatedMaxHeight = displayMode === "fullscreen" ? viewportHeight - inputBarHeight : 600;
1064
- window.openai.colorScheme = colorScheme;
1065
- window.openai.displayMode = displayMode;
1066
- window.openai.widgetState = widgetState;
1067
- window.openai.maxHeight = calculatedMaxHeight;
1068
- window.dispatchEvent(
1069
- new CustomEvent(SET_GLOBALS_EVENT_TYPE, {
1070
- detail: {
1071
- globals: { colorScheme, displayMode, widgetState, maxHeight: calculatedMaxHeight }
1072
- }
1073
- })
1074
- );
1075
- }
1076
- }, [colorScheme, displayMode, widgetState, viewportHeight]);
1077
- const isFullscreen = displayMode === "fullscreen";
1078
- const renderChildren = () => {
1079
- if (typeof children === "function") {
1080
- return children(selectedUISimulation);
807
+ if (mock) {
808
+ mock.setTheme(theme);
1081
809
  }
1082
- return children;
1083
- };
1084
- return /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs(
1085
- Box,
1086
- {
1087
- sx: {
1088
- minHeight: "100vh",
1089
- width: "100vw",
1090
- display: "flex",
1091
- fontFamily: theme.typography.fontFamily,
1092
- backgroundColor: theme.palette.background.default,
1093
- color: theme.palette.text.primary,
1094
- boxSizing: "border-box",
1095
- "@media (max-width: 768px)": {
1096
- flexDirection: "column"
1097
- }
1098
- },
1099
- children: [
1100
- showControls && /* @__PURE__ */ jsxs(
1101
- Box,
1102
- {
1103
- sx: {
1104
- width: "250px",
1105
- flexShrink: 0,
1106
- padding: theme.spacing(5),
1107
- display: "flex",
1108
- flexDirection: "column",
1109
- gap: theme.spacing(5),
1110
- overflowY: "auto",
1111
- backgroundColor: theme.palette.mode === "light" ? theme.palette.background.paper : theme.palette.background.default,
1112
- borderRight: `1px solid ${theme.palette.divider}`,
1113
- boxSizing: "border-box",
1114
- "@media (max-width: 768px)": {
1115
- width: "100%",
1116
- borderRight: "none",
1117
- borderBottom: `1px solid ${theme.palette.divider}`,
1118
- padding: theme.spacing(4)
1119
- }
1120
- },
1121
- children: [
1122
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Typography, { variant: "h6", sx: { fontWeight: 600 }, children: "Controls" }) }),
1123
- /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", gap: theme.spacing(3) }, children: [
1124
- uiSimulations && uiSimulations.length > 0 && /* @__PURE__ */ jsxs(FormControl, { fullWidth: true, size: "small", children: [
1125
- /* @__PURE__ */ jsx(InputLabel, { children: "App UI" }),
1126
- /* @__PURE__ */ jsx(
1127
- Select,
1128
- {
1129
- value: selectedUISimulation,
1130
- onChange: (e) => setSelectedUISimulation(e.target.value),
1131
- label: "App UI",
1132
- children: uiSimulations.map((simulation) => /* @__PURE__ */ jsx(MenuItem, { value: simulation, children: simulation }, simulation))
1133
- }
1134
- )
1135
- ] }),
1136
- /* @__PURE__ */ jsxs(FormControl, { fullWidth: true, size: "small", children: [
1137
- /* @__PURE__ */ jsx(InputLabel, { children: "Color Scheme" }),
1138
- /* @__PURE__ */ jsxs(
1139
- Select,
1140
- {
1141
- value: colorScheme,
1142
- onChange: (e) => setColorScheme(e.target.value),
1143
- label: "Color Scheme",
1144
- children: [
1145
- /* @__PURE__ */ jsx(MenuItem, { value: "light", children: "Light" }),
1146
- /* @__PURE__ */ jsx(MenuItem, { value: "dark", children: "Dark" })
1147
- ]
1148
- }
1149
- )
1150
- ] }),
1151
- /* @__PURE__ */ jsxs(FormControl, { fullWidth: true, size: "small", children: [
1152
- /* @__PURE__ */ jsx(InputLabel, { children: "Display Mode" }),
1153
- /* @__PURE__ */ jsxs(
1154
- Select,
1155
- {
1156
- value: displayMode,
1157
- onChange: (e) => setDisplayMode(e.target.value),
1158
- label: "Display Mode",
1159
- children: [
1160
- /* @__PURE__ */ jsx(MenuItem, { value: "inline", children: "Inline" }),
1161
- /* @__PURE__ */ jsx(MenuItem, { value: "fullscreen", children: "Fullscreen" }),
1162
- /* @__PURE__ */ jsx(MenuItem, { value: "pip", children: "Picture-in-Picture" })
1163
- ]
1164
- }
1165
- )
1166
- ] }),
1167
- /* @__PURE__ */ jsxs(FormControl, { fullWidth: true, size: "small", children: [
1168
- /* @__PURE__ */ jsx(InputLabel, { children: "Body Width" }),
1169
- /* @__PURE__ */ jsxs(
1170
- Select,
1171
- {
1172
- value: bodyWidth,
1173
- onChange: (e) => setBodyWidth(e.target.value),
1174
- label: "Body Width",
1175
- children: [
1176
- /* @__PURE__ */ jsx(MenuItem, { value: "100%", children: "100% (Full)" }),
1177
- /* @__PURE__ */ jsx(MenuItem, { value: "1024px", children: "1024px (Laptop)" }),
1178
- /* @__PURE__ */ jsx(MenuItem, { value: "768px", children: "768px (Tablet)" }),
1179
- /* @__PURE__ */ jsx(MenuItem, { value: "425px", children: "425px (Mobile L)" }),
1180
- /* @__PURE__ */ jsx(MenuItem, { value: "320px", children: "320px (Mobile S)" })
1181
- ]
1182
- }
1183
- )
1184
- ] })
1185
- ] })
1186
- ]
1187
- }
1188
- ),
1189
- /* @__PURE__ */ jsxs(
1190
- Box,
1191
- {
1192
- sx: {
1193
- flex: 1,
1194
- minWidth: 0,
1195
- display: "flex",
1196
- flexDirection: "column",
1197
- overflowY: "auto",
1198
- padding: isFullscreen ? 0 : `${theme.spacing(4)} 0 ${theme.spacing(4)} ${theme.spacing(6)}`,
1199
- position: "relative",
1200
- height: isFullscreen ? "100vh" : "auto",
1201
- boxSizing: "border-box"
1202
- },
1203
- children: [
1204
- isFullscreen && /* @__PURE__ */ jsx(
1205
- IconButton,
1206
- {
1207
- onClick: () => setDisplayMode("inline"),
1208
- "aria-label": "Exit fullscreen",
1209
- sx: {
1210
- position: "absolute",
1211
- top: theme.spacing(4),
1212
- left: theme.spacing(4),
1213
- width: 40,
1214
- height: 40,
1215
- backgroundColor: theme.palette.background.paper,
1216
- zIndex: 10,
1217
- "&:hover": {
1218
- backgroundColor: theme.palette.mode === "light" ? theme.palette.grey[200] : theme.palette.grey[800]
1219
- }
1220
- },
1221
- children: /* @__PURE__ */ jsx(CloseIcon, {})
1222
- }
1223
- ),
1224
- !isFullscreen && /* @__PURE__ */ jsx(Box, { sx: { mb: theme.spacing(4) }, children: /* @__PURE__ */ jsx(Typography, { variant: "h4", sx: { fontWeight: 600, margin: 0 }, children: "ChatGPT" }) }),
1225
- /* @__PURE__ */ jsxs(
1226
- Box,
1227
- {
1228
- sx: {
1229
- maxWidth: bodyWidth === "100%" ? "48rem" : bodyWidth,
1230
- mx: "auto",
1231
- flex: 1,
1232
- position: "relative",
1233
- display: "flex",
1234
- width: "100%",
1235
- minWidth: 0,
1236
- flexDirection: "column",
1237
- boxSizing: "border-box"
1238
- },
1239
- children: [
1240
- /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", maxWidth: "100%", flexDirection: "column", flexGrow: 1, minWidth: 0, boxSizing: "border-box" }, children: [
1241
- !isFullscreen && /* @__PURE__ */ jsxs(Fragment, { children: [
1242
- /* @__PURE__ */ jsx(
1243
- Box,
1244
- {
1245
- sx: {
1246
- display: "flex",
1247
- alignItems: "flex-start",
1248
- justifyContent: "flex-end",
1249
- marginLeft: "auto",
1250
- marginRight: theme.spacing(6),
1251
- maxWidth: "70%",
1252
- "@media (max-width: 768px)": {
1253
- maxWidth: "85%"
1254
- }
1255
- },
1256
- children: /* @__PURE__ */ jsx(
1257
- Box,
1258
- {
1259
- sx: {
1260
- flex: "0 1 auto",
1261
- padding: `${theme.spacing(2)} ${theme.spacing(4)}`,
1262
- borderRadius: theme.spacing(3),
1263
- lineHeight: 1.5,
1264
- fontSize: theme.typography.body1.fontSize,
1265
- overflowWrap: "break-word",
1266
- wordBreak: "break-word",
1267
- minWidth: 0,
1268
- backgroundColor: theme.palette.grey[100],
1269
- color: theme.palette.text.primary,
1270
- boxSizing: "border-box"
1271
- },
1272
- children: userMessage
1273
- }
1274
- )
1275
- }
1276
- ),
1277
- /* @__PURE__ */ jsx(
1278
- Box,
1279
- {
1280
- sx: {
1281
- minHeight: "32px",
1282
- position: "relative",
1283
- display: "flex",
1284
- width: "100%",
1285
- minWidth: 0,
1286
- flexDirection: "column",
1287
- alignItems: "flex-end",
1288
- gap: theme.spacing(2),
1289
- textAlign: "start",
1290
- wordBreak: "break-word",
1291
- whiteSpace: "normal",
1292
- boxSizing: "border-box"
1293
- },
1294
- children: /* @__PURE__ */ jsx(
1295
- Box,
1296
- {
1297
- sx: {
1298
- display: "flex",
1299
- width: "100%",
1300
- minWidth: 0,
1301
- flexDirection: "column",
1302
- gap: theme.spacing(1),
1303
- "&:empty": { display: "none" },
1304
- "&:first-of-type": { pt: "1px" },
1305
- boxSizing: "border-box"
1306
- },
1307
- children: /* @__PURE__ */ jsxs(Box, { sx: { width: "100%", minWidth: 0, wordBreak: "break-word", boxSizing: "border-box" }, children: [
1308
- /* @__PURE__ */ jsxs(
1309
- Box,
1310
- {
1311
- sx: {
1312
- color: theme.palette.text.secondary,
1313
- display: "flex",
1314
- alignItems: "center",
1315
- gap: theme.spacing(2),
1316
- margin: `${theme.spacing(4)} 0`,
1317
- fontSize: theme.typography.body2.fontSize,
1318
- fontWeight: 500,
1319
- opacity: 0.7
1320
- },
1321
- children: [
1322
- /* @__PURE__ */ jsx(Box, { component: "span", sx: { fontSize: theme.typography.body1.fontSize, lineHeight: 1 }, children: "\u2708\uFE0F" }),
1323
- /* @__PURE__ */ jsx(Box, { component: "span", sx: { lineHeight: 1 }, children: "Splorin" })
1324
- ]
1325
- }
1326
- ),
1327
- /* @__PURE__ */ jsx(
1328
- Box,
1329
- {
1330
- sx: {
1331
- overflow: "hidden",
1332
- width: "100%",
1333
- minWidth: 0,
1334
- boxSizing: "border-box"
1335
- },
1336
- children: renderChildren()
1337
- }
1338
- )
1339
- ] })
1340
- }
1341
- )
1342
- }
1343
- )
1344
- ] }),
1345
- isFullscreen && /* @__PURE__ */ jsx(
1346
- Box,
1347
- {
1348
- sx: {
1349
- flex: 1,
1350
- display: "flex",
1351
- flexDirection: "column",
1352
- width: "100%",
1353
- minWidth: 0,
1354
- height: "100%",
1355
- overflowY: "auto",
1356
- paddingBottom: "80px",
1357
- boxSizing: "border-box"
1358
- },
1359
- children: renderChildren()
1360
- }
1361
- )
1362
- ] }),
1363
- /* @__PURE__ */ jsx(
1364
- Box,
1365
- {
1366
- sx: {
1367
- position: "absolute",
1368
- bottom: 0,
1369
- left: 0,
1370
- right: 0,
1371
- margin: `${theme.spacing(4)} 0`,
1372
- padding: `0 ${theme.spacing(10)} 0 ${theme.spacing(4)}`,
1373
- display: "flex",
1374
- justifyContent: "center",
1375
- pointerEvents: "none",
1376
- boxSizing: "border-box"
1377
- },
1378
- children: /* @__PURE__ */ jsx(
1379
- TextField,
1380
- {
1381
- placeholder: "Message ChatGPT",
1382
- disabled: true,
1383
- sx: {
1384
- pointerEvents: "auto",
1385
- width: "100%",
1386
- maxWidth: "800px",
1387
- boxSizing: "border-box",
1388
- "& .MuiOutlinedInput-root": {
1389
- borderRadius: theme.spacing(8),
1390
- backgroundColor: theme.palette.grey[100],
1391
- "& fieldset": {
1392
- borderColor: theme.palette.mode === "light" ? theme.palette.grey[300] : theme.palette.grey[700]
1393
- },
1394
- "&.Mui-disabled": {
1395
- cursor: "not-allowed",
1396
- opacity: 0.6
1397
- }
1398
- },
1399
- "& .MuiInputBase-input::placeholder": {
1400
- color: theme.palette.text.secondary,
1401
- opacity: 0.7
1402
- }
1403
- }
1404
- }
1405
- )
1406
- }
1407
- )
1408
- ]
1409
- }
1410
- )
1411
- ]
1412
- }
1413
- )
1414
- ]
810
+ }, [mock, theme]);
811
+ useEffect(() => {
812
+ if (mock) {
813
+ mock.setDisplayMode(displayMode);
1415
814
  }
1416
- ) });
815
+ }, [mock, displayMode]);
816
+ return /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsxs(SidebarProvider, { defaultOpen: true, children: [
817
+ /* @__PURE__ */ jsx(Sidebar, { children: /* @__PURE__ */ jsx(SidebarContent, { children: /* @__PURE__ */ jsxs(SidebarGroup, { children: [
818
+ /* @__PURE__ */ jsx(SidebarGroupLabel, { className: "text-md", children: "Controls" }),
819
+ /* @__PURE__ */ jsxs(SidebarGroupContent, { className: "space-y-4", children: [
820
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
821
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "app-ui-select", className: "text-xs", children: "App UI" }),
822
+ /* @__PURE__ */ jsxs(Select, { value: "carousel", onValueChange: () => {
823
+ }, children: [
824
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "app-ui-select", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
825
+ /* @__PURE__ */ jsx(SelectContent, { children: /* @__PURE__ */ jsx(SelectItem, { value: "carousel", children: "Carousel" }) })
826
+ ] })
827
+ ] }),
828
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
829
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "theme-select", className: "text-xs", children: "Color Scheme" }),
830
+ /* @__PURE__ */ jsxs(Select, { value: theme, onValueChange: (value) => setTheme(value), children: [
831
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "theme-select", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
832
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
833
+ /* @__PURE__ */ jsx(SelectItem, { value: "light", children: "Light" }),
834
+ /* @__PURE__ */ jsx(SelectItem, { value: "dark", children: "Dark" })
835
+ ] })
836
+ ] })
837
+ ] }),
838
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
839
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "display-mode-select", className: "text-xs", children: "Display Mode" }),
840
+ /* @__PURE__ */ jsxs(Select, { value: displayMode, onValueChange: (value) => setDisplayMode(value), children: [
841
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "display-mode-select", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
842
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
843
+ /* @__PURE__ */ jsx(SelectItem, { value: "inline", children: "Inline" }),
844
+ /* @__PURE__ */ jsx(SelectItem, { value: "pip", children: "Picture in Picture" }),
845
+ /* @__PURE__ */ jsx(SelectItem, { value: "fullscreen", children: "Fullscreen" })
846
+ ] })
847
+ ] })
848
+ ] }),
849
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
850
+ /* @__PURE__ */ jsx(Label2, { htmlFor: "screen-width-select", className: "text-xs", children: "Body Width" }),
851
+ /* @__PURE__ */ jsxs(Select, { value: screenWidth, onValueChange: (value) => setScreenWidth(value), children: [
852
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "screen-width-select", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
853
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
854
+ /* @__PURE__ */ jsx(SelectItem, { value: "mobile-s", children: "Mobile S (375px)" }),
855
+ /* @__PURE__ */ jsx(SelectItem, { value: "mobile-l", children: "Mobile L (425px)" }),
856
+ /* @__PURE__ */ jsx(SelectItem, { value: "tablet", children: "Tablet (768px)" }),
857
+ /* @__PURE__ */ jsx(SelectItem, { value: "full", children: "100% (Full)" })
858
+ ] })
859
+ ] })
860
+ ] })
861
+ ] })
862
+ ] }) }) }),
863
+ /* @__PURE__ */ jsx(
864
+ Conversation,
865
+ {
866
+ screenWidth,
867
+ displayMode,
868
+ appName,
869
+ appIcon,
870
+ userMessage,
871
+ children
872
+ }
873
+ )
874
+ ] }) });
1417
875
  }
1418
876
 
1419
- export { Card, Carousel, ChatGPTSimulator, GenAI, PlatformProvider, baseThemeOptions, chatgptDarkTheme, chatgptLightTheme, chatgptPlatform, createBaseTheme, createPlatformRegistry, getChatGPTTheme, getCurrentPlatform, getDarkTheme, getLightTheme, getTheme, useColorScheme, useDisplayMode, useMaxHeight, usePlatform, usePlatformGlobal, useRequestDisplayMode, useWidgetProps, useWidgetState };
877
+ export { ChatGPTSimulator, SCREEN_WIDTHS, SET_GLOBALS_EVENT_TYPE, SetGlobalsEvent, ThemeProvider, cn, initMockOpenAI, useDisplayMode, useIsMobile, useMaxHeight, useOpenAiGlobal, useTheme, useThemeContext, useWidgetState };
1420
878
  //# sourceMappingURL=index.js.map
1421
879
  //# sourceMappingURL=index.js.map