@nitrostack/widgets 1.0.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.
Files changed (47) hide show
  1. package/README.md +136 -0
  2. package/dist/hooks/index.d.ts +7 -0
  3. package/dist/hooks/index.d.ts.map +1 -0
  4. package/dist/hooks/index.js +6 -0
  5. package/dist/hooks/use-display-mode.d.ts +11 -0
  6. package/dist/hooks/use-display-mode.d.ts.map +1 -0
  7. package/dist/hooks/use-display-mode.js +12 -0
  8. package/dist/hooks/use-max-height.d.ts +10 -0
  9. package/dist/hooks/use-max-height.d.ts.map +1 -0
  10. package/dist/hooks/use-max-height.js +12 -0
  11. package/dist/hooks/use-openai-global.d.ts +12 -0
  12. package/dist/hooks/use-openai-global.d.ts.map +1 -0
  13. package/dist/hooks/use-openai-global.js +31 -0
  14. package/dist/hooks/use-theme.d.ts +10 -0
  15. package/dist/hooks/use-theme.d.ts.map +1 -0
  16. package/dist/hooks/use-theme.js +11 -0
  17. package/dist/hooks/use-widget-state.d.ts +18 -0
  18. package/dist/hooks/use-widget-state.d.ts.map +1 -0
  19. package/dist/hooks/use-widget-state.js +26 -0
  20. package/dist/hooks/useWidgetSDK.d.ts +49 -0
  21. package/dist/hooks/useWidgetSDK.d.ts.map +1 -0
  22. package/dist/hooks/useWidgetSDK.js +69 -0
  23. package/dist/index.d.ts +15 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +18 -0
  26. package/dist/metadata.d.ts +53 -0
  27. package/dist/metadata.d.ts.map +1 -0
  28. package/dist/metadata.js +28 -0
  29. package/dist/runtime/WidgetLayout.d.ts +32 -0
  30. package/dist/runtime/WidgetLayout.d.ts.map +1 -0
  31. package/dist/runtime/WidgetLayout.js +143 -0
  32. package/dist/runtime/widget-polyfill.d.ts +2 -0
  33. package/dist/runtime/widget-polyfill.d.ts.map +1 -0
  34. package/dist/runtime/widget-polyfill.js +27 -0
  35. package/dist/sdk.d.ts +117 -0
  36. package/dist/sdk.d.ts.map +1 -0
  37. package/dist/sdk.js +232 -0
  38. package/dist/types.d.ts +89 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +7 -0
  41. package/dist/utils/media-queries.d.ts +34 -0
  42. package/dist/utils/media-queries.d.ts.map +1 -0
  43. package/dist/utils/media-queries.js +41 -0
  44. package/dist/withToolData.d.ts +19 -0
  45. package/dist/withToolData.d.ts.map +1 -0
  46. package/dist/withToolData.js +227 -0
  47. package/package.json +64 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Widget Layout Component
3
+ *
4
+ * Handles all the RPC setup and window.openai initialization automatically.
5
+ * Developers just wrap their widget content with this component.
6
+ */
7
+ 'use client';
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ import { useEffect } from 'react';
10
+ /**
11
+ * Widget Layout component that sets up the widget runtime
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * export default function RootLayout({ children }) {
16
+ * return (
17
+ * <html lang="en">
18
+ * <body>
19
+ * <WidgetLayout>{children}</WidgetLayout>
20
+ * </body>
21
+ * </html>
22
+ * );
23
+ * }
24
+ * ```
25
+ */
26
+ export function WidgetLayout({ children, onReady }) {
27
+ useEffect(() => {
28
+ console.log('🔧 WidgetLayout: Setting up widget runtime');
29
+ let rpcId = 0;
30
+ const pendingRpcCalls = new Map();
31
+ // RPC helper to call parent methods
32
+ const callParentRpc = (method, ...args) => {
33
+ return new Promise((resolve, reject) => {
34
+ const id = ++rpcId;
35
+ pendingRpcCalls.set(id, { resolve, reject });
36
+ window.parent.postMessage({
37
+ type: 'NITRO_WIDGET_RPC',
38
+ method,
39
+ args,
40
+ id
41
+ }, '*');
42
+ // Timeout after 5 seconds
43
+ setTimeout(() => {
44
+ if (pendingRpcCalls.has(id)) {
45
+ pendingRpcCalls.delete(id);
46
+ reject(new Error(`RPC timeout: ${method}`));
47
+ }
48
+ }, 5000);
49
+ });
50
+ };
51
+ // Listen for messages from parent
52
+ const handleMessage = (event) => {
53
+ // Handle openai data injection
54
+ if (event.data?.type === 'NITRO_INJECT_OPENAI') {
55
+ console.log('📦 WidgetLayout: Received window.openai data from parent');
56
+ const data = event.data.data;
57
+ // Set up window.openai with data + RPC functions
58
+ window.openai = {
59
+ ...data,
60
+ // Functions that call back to parent via RPC
61
+ setWidgetState: async (state) => {
62
+ await callParentRpc('setWidgetState', state);
63
+ },
64
+ callTool: async (name, args) => {
65
+ return await callParentRpc('callTool', name, args);
66
+ },
67
+ sendFollowUpMessage: async ({ prompt }) => {
68
+ await callParentRpc('sendFollowUpMessage', { prompt });
69
+ },
70
+ openExternal: ({ href }) => {
71
+ callParentRpc('openExternal', { href });
72
+ },
73
+ requestClose: () => {
74
+ callParentRpc('requestClose');
75
+ },
76
+ requestDisplayMode: async ({ mode }) => {
77
+ return await callParentRpc('requestDisplayMode', { mode });
78
+ },
79
+ };
80
+ // Dispatch ready event
81
+ const readyEvent = new CustomEvent('openai:ready');
82
+ window.dispatchEvent(readyEvent);
83
+ console.log('✅ WidgetLayout: window.openai initialized');
84
+ // Call onReady callback if provided
85
+ onReady?.();
86
+ }
87
+ // Handle RPC responses
88
+ if (event.data?.type === 'NITRO_WIDGET_RPC_RESPONSE') {
89
+ const { id, result, error } = event.data;
90
+ const pending = pendingRpcCalls.get(id);
91
+ if (pending) {
92
+ pendingRpcCalls.delete(id);
93
+ if (error) {
94
+ pending.reject(new Error(error));
95
+ }
96
+ else {
97
+ pending.resolve(result);
98
+ }
99
+ }
100
+ }
101
+ // Handle legacy toolOutput for backward compatibility
102
+ if (event.data?.type === 'TOOL_OUTPUT' && event.data?.data) {
103
+ console.log('📦 WidgetLayout: Received legacy toolOutput');
104
+ if (window.openai) {
105
+ window.openai.toolOutput = event.data.data;
106
+ }
107
+ }
108
+ };
109
+ window.addEventListener('message', handleMessage);
110
+ console.log('✅ WidgetLayout: Message listener registered');
111
+ return () => {
112
+ console.log('🔧 WidgetLayout: Cleaning up');
113
+ window.removeEventListener('message', handleMessage);
114
+ };
115
+ }, [onReady]);
116
+ // Set up ResizeObserver to track content height
117
+ useEffect(() => {
118
+ // Reset body margins/padding for accurate measurement
119
+ document.body.style.margin = '0';
120
+ document.body.style.padding = '0';
121
+ document.body.style.overflow = 'hidden';
122
+ const contentWrapper = document.getElementById('nitro-widget-content');
123
+ if (!contentWrapper)
124
+ return;
125
+ const resizeObserver = new ResizeObserver((entries) => {
126
+ for (const entry of entries) {
127
+ const height = entry.contentRect.height;
128
+ const finalHeight = Math.ceil(height) + 16;
129
+ console.log('📐 Widget content height:', height, '→ sending:', finalHeight);
130
+ // Send height update to parent
131
+ window.parent.postMessage({
132
+ type: 'NITRO_WIDGET_RESIZE',
133
+ height: finalHeight // Add small buffer
134
+ }, '*');
135
+ }
136
+ });
137
+ resizeObserver.observe(contentWrapper);
138
+ return () => {
139
+ resizeObserver.disconnect();
140
+ };
141
+ }, []);
142
+ return _jsx("div", { id: "nitro-widget-content", children: children });
143
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=widget-polyfill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-polyfill.d.ts","sourceRoot":"","sources":["../../src/runtime/widget-polyfill.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ // NitroStack Widget Runtime Polyfill
2
+ // This script listens for window.openai injection from the parent frame
3
+ (function () {
4
+ 'use strict';
5
+ // Listen for openai runtime injection from parent
6
+ window.addEventListener('message', (event) => {
7
+ if (event.data?.type === 'NITRO_INJECT_OPENAI') {
8
+ console.log('📦 Received window.openai from parent frame');
9
+ // Set up window.openai
10
+ window.openai = event.data.openai;
11
+ // Dispatch event for widgets to know openai is ready
12
+ const readyEvent = new CustomEvent('openai:ready');
13
+ window.dispatchEvent(readyEvent);
14
+ console.log('✅ window.openai initialized');
15
+ }
16
+ });
17
+ // Also handle legacy toolOutput postMessage for backward compatibility
18
+ window.addEventListener('message', (event) => {
19
+ if (event.data?.type === 'TOOL_OUTPUT' && event.data?.data) {
20
+ console.log('📦 Received legacy toolOutput');
21
+ if (window.openai) {
22
+ window.openai.toolOutput = event.data.data;
23
+ }
24
+ }
25
+ });
26
+ })();
27
+ export {};
package/dist/sdk.d.ts ADDED
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Widget SDK - Clean abstraction over window.openai
3
+ *
4
+ * Provides a developer-friendly API for widget functionality without
5
+ * exposing OpenAI-specific implementation details.
6
+ */
7
+ import type { DisplayMode, CallToolResponse } from './types.js';
8
+ /**
9
+ * Widget SDK class that wraps window.openai functionality
10
+ */
11
+ export declare class WidgetSDK {
12
+ private static instance;
13
+ private constructor();
14
+ /**
15
+ * Get the SDK instance
16
+ */
17
+ static getInstance(): WidgetSDK;
18
+ /**
19
+ * Check if the SDK is ready (window.openai is available)
20
+ */
21
+ isReady(): boolean;
22
+ /**
23
+ * Wait for SDK to be ready
24
+ */
25
+ waitForReady(timeout?: number): Promise<void>;
26
+ /**
27
+ * Set widget state
28
+ */
29
+ setState(state: Record<string, unknown>): Promise<void>;
30
+ /**
31
+ * Get current widget state
32
+ */
33
+ getState(): Record<string, unknown> | null;
34
+ /**
35
+ * Call a tool by name with arguments
36
+ */
37
+ callTool(name: string, args?: Record<string, unknown>): Promise<CallToolResponse>;
38
+ /**
39
+ * Request fullscreen mode
40
+ */
41
+ requestFullscreen(): Promise<void>;
42
+ /**
43
+ * Request inline mode
44
+ */
45
+ requestInline(): Promise<void>;
46
+ /**
47
+ * Request picture-in-picture mode
48
+ */
49
+ requestPip(): Promise<void>;
50
+ /**
51
+ * Request display mode change
52
+ */
53
+ requestDisplayMode(mode: DisplayMode): Promise<{
54
+ mode: DisplayMode;
55
+ }>;
56
+ /**
57
+ * Close the widget
58
+ */
59
+ requestClose(): void;
60
+ /**
61
+ * Open external URL
62
+ */
63
+ openExternal(url: string): void;
64
+ /**
65
+ * Send a follow-up message to the chat
66
+ */
67
+ sendFollowUpMessage(prompt: string): Promise<void>;
68
+ /**
69
+ * Get tool input data
70
+ */
71
+ getToolInput<T = unknown>(): T | null;
72
+ /**
73
+ * Get tool output data
74
+ */
75
+ getToolOutput<T = unknown>(): T | null;
76
+ /**
77
+ * Get tool response metadata
78
+ */
79
+ getToolResponseMetadata<T = unknown>(): T | null;
80
+ /**
81
+ * Get current theme
82
+ */
83
+ getTheme(): 'light' | 'dark';
84
+ /**
85
+ * Get maximum height constraint
86
+ */
87
+ getMaxHeight(): number;
88
+ /**
89
+ * Get current display mode
90
+ */
91
+ getDisplayMode(): DisplayMode;
92
+ /**
93
+ * Get user agent information
94
+ */
95
+ getUserAgent(): import("./types.js").UserAgent | null;
96
+ /**
97
+ * Get locale
98
+ */
99
+ getLocale(): string;
100
+ /**
101
+ * Get safe area insets
102
+ */
103
+ getSafeArea(): import("./types.js").SafeArea | null;
104
+ /**
105
+ * Alias for getToolOutput - commonly used
106
+ */
107
+ getOutput<T = unknown>(): T | null;
108
+ /**
109
+ * Check if dark mode is active
110
+ */
111
+ isDarkMode(): boolean;
112
+ }
113
+ /**
114
+ * Get the global Widget SDK instance
115
+ */
116
+ export declare function getWidgetSDK(): WidgetSDK;
117
+ //# sourceMappingURL=sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEhE;;GAEG;AACH,qBAAa,SAAS;IAClB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA0B;IAEjD,OAAO;IAIP;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,SAAS;IAO/B;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACG,YAAY,CAAC,OAAO,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBjD;;OAEG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7D;;OAEG;IACH,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAO1C;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAS3F;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAOxC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC;;OAEG;IACG,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC;IAO3E;;OAEG;IACH,YAAY,IAAI,IAAI;IASpB;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO/B;;OAEG;IACG,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxD;;OAEG;IACH,YAAY,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,IAAI;IAKrC;;OAEG;IACH,aAAa,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,IAAI;IAKtC;;OAEG;IACH,uBAAuB,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,IAAI;IAKhD;;OAEG;IACH,QAAQ,IAAI,OAAO,GAAG,MAAM;IAK5B;;OAEG;IACH,YAAY,IAAI,MAAM;IAKtB;;OAEG;IACH,cAAc,IAAI,WAAW;IAK7B;;OAEG;IACH,YAAY;IAKZ;;OAEG;IACH,SAAS,IAAI,MAAM;IAKnB;;OAEG;IACH,WAAW;IAKX;;OAEG;IACH,SAAS,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,IAAI;IAIlC;;OAEG;IACH,UAAU,IAAI,OAAO;CAGxB;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,SAAS,CAExC"}
package/dist/sdk.js ADDED
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Widget SDK - Clean abstraction over window.openai
3
+ *
4
+ * Provides a developer-friendly API for widget functionality without
5
+ * exposing OpenAI-specific implementation details.
6
+ */
7
+ /**
8
+ * Widget SDK class that wraps window.openai functionality
9
+ */
10
+ export class WidgetSDK {
11
+ static instance = null;
12
+ constructor() {
13
+ // Private constructor for singleton
14
+ }
15
+ /**
16
+ * Get the SDK instance
17
+ */
18
+ static getInstance() {
19
+ if (!WidgetSDK.instance) {
20
+ WidgetSDK.instance = new WidgetSDK();
21
+ }
22
+ return WidgetSDK.instance;
23
+ }
24
+ /**
25
+ * Check if the SDK is ready (window.openai is available)
26
+ */
27
+ isReady() {
28
+ return typeof window !== 'undefined' && 'openai' in window;
29
+ }
30
+ /**
31
+ * Wait for SDK to be ready
32
+ */
33
+ async waitForReady(timeout = 5000) {
34
+ if (this.isReady())
35
+ return;
36
+ return new Promise((resolve, reject) => {
37
+ const timeoutId = setTimeout(() => {
38
+ window.removeEventListener('openai:ready', handler);
39
+ reject(new Error('Widget SDK initialization timeout'));
40
+ }, timeout);
41
+ const handler = () => {
42
+ clearTimeout(timeoutId);
43
+ resolve();
44
+ };
45
+ window.addEventListener('openai:ready', handler, { once: true });
46
+ });
47
+ }
48
+ // ==================== State Management ====================
49
+ /**
50
+ * Set widget state
51
+ */
52
+ async setState(state) {
53
+ if (!this.isReady()) {
54
+ throw new Error('Widget SDK not ready');
55
+ }
56
+ await window.openai.setWidgetState(state);
57
+ }
58
+ /**
59
+ * Get current widget state
60
+ */
61
+ getState() {
62
+ if (!this.isReady())
63
+ return null;
64
+ return window.openai.widgetState;
65
+ }
66
+ // ==================== Tool Calling ====================
67
+ /**
68
+ * Call a tool by name with arguments
69
+ */
70
+ async callTool(name, args = {}) {
71
+ if (!this.isReady()) {
72
+ throw new Error('Widget SDK not ready');
73
+ }
74
+ return await window.openai.callTool(name, args);
75
+ }
76
+ // ==================== Display Controls ====================
77
+ /**
78
+ * Request fullscreen mode
79
+ */
80
+ async requestFullscreen() {
81
+ if (!this.isReady()) {
82
+ throw new Error('Widget SDK not ready');
83
+ }
84
+ await window.openai.requestDisplayMode({ mode: 'fullscreen' });
85
+ }
86
+ /**
87
+ * Request inline mode
88
+ */
89
+ async requestInline() {
90
+ if (!this.isReady()) {
91
+ throw new Error('Widget SDK not ready');
92
+ }
93
+ await window.openai.requestDisplayMode({ mode: 'inline' });
94
+ }
95
+ /**
96
+ * Request picture-in-picture mode
97
+ */
98
+ async requestPip() {
99
+ if (!this.isReady()) {
100
+ throw new Error('Widget SDK not ready');
101
+ }
102
+ await window.openai.requestDisplayMode({ mode: 'pip' });
103
+ }
104
+ /**
105
+ * Request display mode change
106
+ */
107
+ async requestDisplayMode(mode) {
108
+ if (!this.isReady()) {
109
+ throw new Error('Widget SDK not ready');
110
+ }
111
+ return await window.openai.requestDisplayMode({ mode });
112
+ }
113
+ /**
114
+ * Close the widget
115
+ */
116
+ requestClose() {
117
+ if (!this.isReady()) {
118
+ throw new Error('Widget SDK not ready');
119
+ }
120
+ window.openai.requestClose();
121
+ }
122
+ // ==================== Navigation ====================
123
+ /**
124
+ * Open external URL
125
+ */
126
+ openExternal(url) {
127
+ if (!this.isReady()) {
128
+ throw new Error('Widget SDK not ready');
129
+ }
130
+ window.openai.openExternal({ href: url });
131
+ }
132
+ /**
133
+ * Send a follow-up message to the chat
134
+ */
135
+ async sendFollowUpMessage(prompt) {
136
+ if (!this.isReady()) {
137
+ throw new Error('Widget SDK not ready');
138
+ }
139
+ await window.openai.sendFollowUpMessage({ prompt });
140
+ }
141
+ // ==================== Data Access ====================
142
+ /**
143
+ * Get tool input data
144
+ */
145
+ getToolInput() {
146
+ if (!this.isReady())
147
+ return null;
148
+ return window.openai.toolInput;
149
+ }
150
+ /**
151
+ * Get tool output data
152
+ */
153
+ getToolOutput() {
154
+ if (!this.isReady())
155
+ return null;
156
+ return window.openai.toolOutput;
157
+ }
158
+ /**
159
+ * Get tool response metadata
160
+ */
161
+ getToolResponseMetadata() {
162
+ if (!this.isReady())
163
+ return null;
164
+ return window.openai.toolResponseMetadata;
165
+ }
166
+ /**
167
+ * Get current theme
168
+ */
169
+ getTheme() {
170
+ if (!this.isReady())
171
+ return 'light';
172
+ return window.openai.theme;
173
+ }
174
+ /**
175
+ * Get maximum height constraint
176
+ */
177
+ getMaxHeight() {
178
+ if (!this.isReady())
179
+ return 0;
180
+ return window.openai.maxHeight;
181
+ }
182
+ /**
183
+ * Get current display mode
184
+ */
185
+ getDisplayMode() {
186
+ if (!this.isReady())
187
+ return 'inline';
188
+ return window.openai.displayMode;
189
+ }
190
+ /**
191
+ * Get user agent information
192
+ */
193
+ getUserAgent() {
194
+ if (!this.isReady())
195
+ return null;
196
+ return window.openai.userAgent;
197
+ }
198
+ /**
199
+ * Get locale
200
+ */
201
+ getLocale() {
202
+ if (!this.isReady())
203
+ return 'en-US';
204
+ return window.openai.locale;
205
+ }
206
+ /**
207
+ * Get safe area insets
208
+ */
209
+ getSafeArea() {
210
+ if (!this.isReady())
211
+ return null;
212
+ return window.openai.safeArea;
213
+ }
214
+ /**
215
+ * Alias for getToolOutput - commonly used
216
+ */
217
+ getOutput() {
218
+ return this.getToolOutput();
219
+ }
220
+ /**
221
+ * Check if dark mode is active
222
+ */
223
+ isDarkMode() {
224
+ return this.getTheme() === 'dark';
225
+ }
226
+ }
227
+ /**
228
+ * Get the global Widget SDK instance
229
+ */
230
+ export function getWidgetSDK() {
231
+ return WidgetSDK.getInstance();
232
+ }
@@ -0,0 +1,89 @@
1
+ export type UnknownObject = Record<string, unknown>;
2
+ export type Theme = 'light' | 'dark';
3
+ export type SafeAreaInsets = {
4
+ top: number;
5
+ bottom: number;
6
+ left: number;
7
+ right: number;
8
+ };
9
+ export type SafeArea = {
10
+ insets: SafeAreaInsets;
11
+ };
12
+ export type DeviceType = 'mobile' | 'tablet' | 'desktop' | 'unknown';
13
+ export type UserAgent = {
14
+ device: {
15
+ type: DeviceType;
16
+ };
17
+ capabilities: {
18
+ hover: boolean;
19
+ touch: boolean;
20
+ };
21
+ };
22
+ /** Display mode */
23
+ export type DisplayMode = 'pip' | 'inline' | 'fullscreen';
24
+ export type RequestDisplayMode = (args: {
25
+ mode: DisplayMode;
26
+ }) => Promise<{
27
+ /**
28
+ * The granted display mode. The host may reject the request.
29
+ * For mobile, PiP is always coerced to fullscreen.
30
+ */
31
+ mode: DisplayMode;
32
+ }>;
33
+ export type CallToolResponse = {
34
+ result: string;
35
+ };
36
+ /** Calling APIs */
37
+ export type CallTool = (name: string, args: Record<string, unknown>) => Promise<CallToolResponse>;
38
+ /**
39
+ * OpenAI globals injected into widget runtime
40
+ */
41
+ export type OpenAiGlobals<ToolInput = UnknownObject, ToolOutput = UnknownObject, ToolResponseMetadata = UnknownObject, WidgetState = UnknownObject> = {
42
+ theme: Theme;
43
+ userAgent: UserAgent;
44
+ locale: string;
45
+ maxHeight: number;
46
+ displayMode: DisplayMode;
47
+ safeArea: SafeArea;
48
+ toolInput: ToolInput;
49
+ toolOutput: ToolOutput | null;
50
+ toolResponseMetadata: ToolResponseMetadata | null;
51
+ widgetState: WidgetState | null;
52
+ setWidgetState: (state: WidgetState) => Promise<void>;
53
+ };
54
+ /**
55
+ * OpenAI API methods
56
+ */
57
+ export type OpenAiAPI = {
58
+ callTool: CallTool;
59
+ sendFollowUpMessage: (args: {
60
+ prompt: string;
61
+ }) => Promise<void>;
62
+ openExternal(payload: {
63
+ href: string;
64
+ }): void;
65
+ requestClose(): void;
66
+ requestDisplayMode: RequestDisplayMode;
67
+ };
68
+ /**
69
+ * Custom event for globals updates
70
+ */
71
+ export declare const SET_GLOBALS_EVENT_TYPE = "openai:set_globals";
72
+ export declare class SetGlobalsEvent extends CustomEvent<{
73
+ globals: Partial<OpenAiGlobals>;
74
+ }> {
75
+ readonly type = "openai:set_globals";
76
+ }
77
+ /**
78
+ * Global openai object injected by the web sandbox for communicating with chatgpt host page.
79
+ */
80
+ declare global {
81
+ interface Window {
82
+ openai: OpenAiAPI & OpenAiGlobals;
83
+ }
84
+ interface WindowEventMap {
85
+ [SET_GLOBALS_EVENT_TYPE]: SetGlobalsEvent;
86
+ }
87
+ }
88
+ export {};
89
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Custom event for globals updates
3
+ */
4
+ export const SET_GLOBALS_EVENT_TYPE = 'openai:set_globals';
5
+ export class SetGlobalsEvent extends CustomEvent {
6
+ type = SET_GLOBALS_EVENT_TYPE;
7
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Media query utilities for responsive and accessible widget design
3
+ */
4
+ /**
5
+ * Check if user prefers reduced motion
6
+ * Use this to disable animations for accessibility
7
+ *
8
+ * @example
9
+ * const shouldAnimate = !prefersReducedMotion();
10
+ */
11
+ export declare const prefersReducedMotion: () => boolean;
12
+ /**
13
+ * Check if device is primarily touch-based
14
+ *
15
+ * @example
16
+ * const isTouchDevice = isPrimarilyTouchDevice();
17
+ */
18
+ export declare const isPrimarilyTouchDevice: () => boolean;
19
+ /**
20
+ * Check if hover is available
21
+ * Use this to conditionally show hover states
22
+ *
23
+ * @example
24
+ * const canHover = isHoverAvailable();
25
+ */
26
+ export declare const isHoverAvailable: () => boolean;
27
+ /**
28
+ * Check if user prefers dark color scheme
29
+ *
30
+ * @example
31
+ * const prefersDark = prefersDarkColorScheme();
32
+ */
33
+ export declare const prefersDarkColorScheme: () => boolean;
34
+ //# sourceMappingURL=media-queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-queries.d.ts","sourceRoot":"","sources":["../../src/utils/media-queries.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,eAEhC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,eAA0C,CAAC;AAE9E;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,eAAuC,CAAC;AAErE;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,eAElC,CAAC"}