@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
package/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # @nitrostack/widgets
2
+
3
+ Lightweight widget utilities for building interactive UI components in NitroStack MCP servers.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @nitrostack/widgets
9
+ ```
10
+
11
+ ## Features
12
+
13
+ - **OpenAI ChatGPT Compatible** - Works with OpenAI's widget format
14
+ - **React Hooks** - Easy-to-use hooks for widget state management
15
+ - **Theme Support** - Automatic dark/light mode detection
16
+ - **Type Safe** - Full TypeScript support
17
+
18
+ ## Quick Start
19
+
20
+ ```tsx
21
+ import { useWidgetSDK, useTheme, WidgetLayout } from '@nitrostack/widgets';
22
+
23
+ export default function MyWidget() {
24
+ const sdk = useWidgetSDK();
25
+ const { isDark } = useTheme();
26
+
27
+ // Access tool output data
28
+ const data = sdk.getOutput();
29
+
30
+ return (
31
+ <WidgetLayout>
32
+ <div style={{ background: isDark ? '#1a1a1a' : '#ffffff' }}>
33
+ <h1>Hello from Widget!</h1>
34
+ <pre>{JSON.stringify(data, null, 2)}</pre>
35
+ </div>
36
+ </WidgetLayout>
37
+ );
38
+ }
39
+ ```
40
+
41
+ ## Hooks
42
+
43
+ ### `useWidgetSDK()`
44
+
45
+ Main SDK hook providing access to all widget functionality:
46
+
47
+ ```tsx
48
+ const sdk = useWidgetSDK();
49
+
50
+ // Get tool output data
51
+ const data = sdk.getOutput();
52
+
53
+ // Call another tool
54
+ const result = await sdk.callTool('tool_name', { param: 'value' });
55
+
56
+ // Update widget state
57
+ sdk.setState({ count: 1 });
58
+ const state = sdk.getState();
59
+
60
+ // Theme
61
+ const isDark = sdk.isDarkMode();
62
+
63
+ // Display mode
64
+ const mode = sdk.getDisplayMode(); // 'split' | 'fullscreen'
65
+ ```
66
+
67
+ ### `useTheme()`
68
+
69
+ Access current theme:
70
+
71
+ ```tsx
72
+ const { isDark, theme } = useTheme();
73
+ ```
74
+
75
+ ### `useWidgetState(initialState)`
76
+
77
+ Persistent widget state:
78
+
79
+ ```tsx
80
+ const [state, setState] = useWidgetState({ count: 0 });
81
+ ```
82
+
83
+ ### `useMaxHeight()`
84
+
85
+ Get maximum available height for the widget:
86
+
87
+ ```tsx
88
+ const maxHeight = useMaxHeight(); // e.g., '600px'
89
+ ```
90
+
91
+ ### `useDisplayMode()`
92
+
93
+ Get current display mode:
94
+
95
+ ```tsx
96
+ const displayMode = useDisplayMode(); // 'split' | 'fullscreen'
97
+ ```
98
+
99
+ ## Components
100
+
101
+ ### `WidgetLayout`
102
+
103
+ Wrapper component that handles theme and polyfills:
104
+
105
+ ```tsx
106
+ import { WidgetLayout } from '@nitrostack/widgets';
107
+
108
+ export default function Page() {
109
+ return (
110
+ <WidgetLayout>
111
+ <YourWidgetContent />
112
+ </WidgetLayout>
113
+ );
114
+ }
115
+ ```
116
+
117
+ ## Utilities
118
+
119
+ ```tsx
120
+ import {
121
+ prefersReducedMotion,
122
+ isPrimarilyTouchDevice,
123
+ isHoverAvailable,
124
+ prefersDarkColorScheme,
125
+ } from '@nitrostack/widgets';
126
+
127
+ // Check user preferences
128
+ if (prefersReducedMotion()) {
129
+ // Disable animations
130
+ }
131
+ ```
132
+
133
+ ## License
134
+
135
+ Apache-2.0
136
+
@@ -0,0 +1,7 @@
1
+ export { useOpenAiGlobal } from './use-openai-global.js';
2
+ export { useWidgetState } from './use-widget-state.js';
3
+ export { useTheme } from './use-theme.js';
4
+ export { useMaxHeight } from './use-max-height.js';
5
+ export { useDisplayMode } from './use-display-mode.js';
6
+ export { useWidgetSDK } from './useWidgetSDK.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { useOpenAiGlobal } from './use-openai-global.js';
2
+ export { useWidgetState } from './use-widget-state.js';
3
+ export { useTheme } from './use-theme.js';
4
+ export { useMaxHeight } from './use-max-height.js';
5
+ export { useDisplayMode } from './use-display-mode.js';
6
+ export { useWidgetSDK } from './useWidgetSDK.js';
@@ -0,0 +1,11 @@
1
+ import { type DisplayMode } from '../types.js';
2
+ /**
3
+ * Hook to get the current display mode
4
+ * Returns 'inline' | 'pip' | 'fullscreen'
5
+ *
6
+ * @example
7
+ * const displayMode = useDisplayMode();
8
+ * const isFullscreen = displayMode === 'fullscreen';
9
+ */
10
+ export declare const useDisplayMode: () => DisplayMode | null;
11
+ //# sourceMappingURL=use-display-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-display-mode.d.ts","sourceRoot":"","sources":["../../src/hooks/use-display-mode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,QAAO,WAAW,GAAG,IAE/C,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { useOpenAiGlobal } from './use-openai-global.js';
2
+ /**
3
+ * Hook to get the current display mode
4
+ * Returns 'inline' | 'pip' | 'fullscreen'
5
+ *
6
+ * @example
7
+ * const displayMode = useDisplayMode();
8
+ * const isFullscreen = displayMode === 'fullscreen';
9
+ */
10
+ export const useDisplayMode = () => {
11
+ return useOpenAiGlobal('displayMode');
12
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Hook to get the maximum available height for the widget
3
+ * Useful for responsive layouts
4
+ *
5
+ * @example
6
+ * const maxHeight = useMaxHeight();
7
+ * return <div style={{ maxHeight }}>{content}</div>;
8
+ */
9
+ export declare const useMaxHeight: () => number | null;
10
+ //# sourceMappingURL=use-max-height.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-max-height.d.ts","sourceRoot":"","sources":["../../src/hooks/use-max-height.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,QAAO,MAAM,GAAG,IAExC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { useOpenAiGlobal } from './use-openai-global.js';
2
+ /**
3
+ * Hook to get the maximum available height for the widget
4
+ * Useful for responsive layouts
5
+ *
6
+ * @example
7
+ * const maxHeight = useMaxHeight();
8
+ * return <div style={{ maxHeight }}>{content}</div>;
9
+ */
10
+ export const useMaxHeight = () => {
11
+ return useOpenAiGlobal('maxHeight');
12
+ };
@@ -0,0 +1,12 @@
1
+ import { type OpenAiGlobals } from '../types.js';
2
+ /**
3
+ * Hook to subscribe to a specific property of window.openai
4
+ * Automatically re-renders when the property changes
5
+ *
6
+ * @example
7
+ * const theme = useOpenAiGlobal('theme');
8
+ * const locale = useOpenAiGlobal('locale');
9
+ * const maxHeight = useOpenAiGlobal('maxHeight');
10
+ */
11
+ export declare function useOpenAiGlobal<K extends keyof OpenAiGlobals>(key: K): OpenAiGlobals[K] | null;
12
+ //# sourceMappingURL=use-openai-global.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-openai-global.d.ts","sourceRoot":"","sources":["../../src/hooks/use-openai-global.ts"],"names":[],"mappings":"AACA,OAAO,EAGH,KAAK,aAAa,EACrB,MAAM,aAAa,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,aAAa,EACzD,GAAG,EAAE,CAAC,GACP,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CA2BzB"}
@@ -0,0 +1,31 @@
1
+ import { useSyncExternalStore } from 'react';
2
+ import { SET_GLOBALS_EVENT_TYPE, } from '../types.js';
3
+ /**
4
+ * Hook to subscribe to a specific property of window.openai
5
+ * Automatically re-renders when the property changes
6
+ *
7
+ * @example
8
+ * const theme = useOpenAiGlobal('theme');
9
+ * const locale = useOpenAiGlobal('locale');
10
+ * const maxHeight = useOpenAiGlobal('maxHeight');
11
+ */
12
+ export function useOpenAiGlobal(key) {
13
+ return useSyncExternalStore((onChange) => {
14
+ if (typeof window === 'undefined') {
15
+ return () => { };
16
+ }
17
+ const handleSetGlobal = (event) => {
18
+ const value = event.detail.globals[key];
19
+ if (value === undefined) {
20
+ return;
21
+ }
22
+ onChange();
23
+ };
24
+ window.addEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal, {
25
+ passive: true,
26
+ });
27
+ return () => {
28
+ window.removeEventListener(SET_GLOBALS_EVENT_TYPE, handleSetGlobal);
29
+ };
30
+ }, () => typeof window !== 'undefined' ? window.openai?.[key] ?? null : null, () => typeof window !== 'undefined' ? window.openai?.[key] ?? null : null);
31
+ }
@@ -0,0 +1,10 @@
1
+ import { type Theme } from '../types.js';
2
+ /**
3
+ * Hook to get the current theme ('light' | 'dark')
4
+ *
5
+ * @example
6
+ * const theme = useTheme();
7
+ * const bgColor = theme === 'dark' ? '#000' : '#fff';
8
+ */
9
+ export declare const useTheme: () => Theme | null;
10
+ //# sourceMappingURL=use-theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-theme.d.ts","sourceRoot":"","sources":["../../src/hooks/use-theme.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,QAAO,KAAK,GAAG,IAEnC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { useOpenAiGlobal } from './use-openai-global.js';
2
+ /**
3
+ * Hook to get the current theme ('light' | 'dark')
4
+ *
5
+ * @example
6
+ * const theme = useTheme();
7
+ * const bgColor = theme === 'dark' ? '#000' : '#fff';
8
+ */
9
+ export const useTheme = () => {
10
+ return useOpenAiGlobal('theme');
11
+ };
@@ -0,0 +1,18 @@
1
+ import { type SetStateAction } from 'react';
2
+ import type { UnknownObject } from '../types.js';
3
+ /**
4
+ * Hook for managing widget state with automatic persistence
5
+ * State is scoped to the widget instance (message_id/widgetId)
6
+ *
7
+ * @example
8
+ * const [state, setState] = useWidgetState(() => ({
9
+ * selectedItems: [],
10
+ * viewMode: 'grid'
11
+ * }));
12
+ *
13
+ * // Update state (automatically persists)
14
+ * setState({ ...state, viewMode: 'list' });
15
+ */
16
+ export declare function useWidgetState<T extends UnknownObject>(defaultState: T | (() => T)): readonly [T, (state: SetStateAction<T>) => void];
17
+ export declare function useWidgetState<T extends UnknownObject>(defaultState?: T | (() => T | null) | null): readonly [T | null, (state: SetStateAction<T | null>) => void];
18
+ //# sourceMappingURL=use-widget-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-widget-state.d.ts","sourceRoot":"","sources":["../../src/hooks/use-widget-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAE9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,EAClD,YAAY,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAC5B,SAAS,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AACpD,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,EAClD,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAC3C,SAAS,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useOpenAiGlobal } from './use-openai-global.js';
3
+ export function useWidgetState(defaultState) {
4
+ const widgetStateFromWindow = useOpenAiGlobal('widgetState');
5
+ const [widgetState, _setWidgetState] = useState(() => {
6
+ if (widgetStateFromWindow != null) {
7
+ return widgetStateFromWindow;
8
+ }
9
+ return typeof defaultState === 'function'
10
+ ? defaultState()
11
+ : defaultState ?? null;
12
+ });
13
+ useEffect(() => {
14
+ _setWidgetState(widgetStateFromWindow);
15
+ }, [widgetStateFromWindow]);
16
+ const setWidgetState = useCallback((state) => {
17
+ _setWidgetState((prevState) => {
18
+ const newState = typeof state === 'function' ? state(prevState) : state;
19
+ if (newState != null && window.openai?.setWidgetState) {
20
+ window.openai.setWidgetState(newState);
21
+ }
22
+ return newState;
23
+ });
24
+ }, []);
25
+ return [widgetState, setWidgetState];
26
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * React hook to access the Widget SDK
3
+ */
4
+ import { WidgetSDK } from '../sdk.js';
5
+ /**
6
+ * Hook to access the Widget SDK instance
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const { callTool, requestFullscreen, getTheme } = useWidgetSDK();
11
+ *
12
+ * // Call a tool
13
+ * await callTool('show_pizza_shop', { shopId: '123' });
14
+ *
15
+ * // Request fullscreen
16
+ * await requestFullscreen();
17
+ *
18
+ * // Get theme
19
+ * const theme = getTheme();
20
+ * ```
21
+ */
22
+ export declare function useWidgetSDK(): {
23
+ sdk: WidgetSDK;
24
+ isReady: boolean;
25
+ setState: (state: Record<string, unknown>) => Promise<void>;
26
+ getState: () => Record<string, unknown> | null;
27
+ callTool: (name: string, args?: Record<string, unknown>) => Promise<import("../types.js").CallToolResponse>;
28
+ requestFullscreen: () => Promise<void>;
29
+ requestInline: () => Promise<void>;
30
+ requestPip: () => Promise<void>;
31
+ requestDisplayMode: (mode: import("../types.js").DisplayMode) => Promise<{
32
+ mode: import("../types.js").DisplayMode;
33
+ }>;
34
+ requestClose: () => void;
35
+ openExternal: (url: string) => void;
36
+ sendFollowUpMessage: (prompt: string) => Promise<void>;
37
+ getToolInput: <T = unknown>() => T | null;
38
+ getToolOutput: <T = unknown>() => T | null;
39
+ getOutput: <T = unknown>() => T | null;
40
+ getToolResponseMetadata: <T = unknown>() => T | null;
41
+ getTheme: () => "light" | "dark";
42
+ getMaxHeight: () => number;
43
+ getDisplayMode: () => import("../types.js").DisplayMode;
44
+ getUserAgent: () => import("../types.js").UserAgent | null;
45
+ getLocale: () => string;
46
+ getSafeArea: () => import("../types.js").SafeArea | null;
47
+ isDarkMode: () => boolean;
48
+ };
49
+ //# sourceMappingURL=useWidgetSDK.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWidgetSDK.d.ts","sourceRoot":"","sources":["../../src/hooks/useWidgetSDK.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAgB,SAAS,EAAE,MAAM,WAAW,CAAC;AAEpD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;EAwD3B"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * React hook to access the Widget SDK
3
+ */
4
+ import { useEffect, useState } from 'react';
5
+ import { getWidgetSDK } from '../sdk.js';
6
+ /**
7
+ * Hook to access the Widget SDK instance
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const { callTool, requestFullscreen, getTheme } = useWidgetSDK();
12
+ *
13
+ * // Call a tool
14
+ * await callTool('show_pizza_shop', { shopId: '123' });
15
+ *
16
+ * // Request fullscreen
17
+ * await requestFullscreen();
18
+ *
19
+ * // Get theme
20
+ * const theme = getTheme();
21
+ * ```
22
+ */
23
+ export function useWidgetSDK() {
24
+ const [sdk] = useState(() => getWidgetSDK());
25
+ const [isReady, setIsReady] = useState(sdk.isReady());
26
+ useEffect(() => {
27
+ if (isReady)
28
+ return;
29
+ const checkReady = () => setIsReady(true);
30
+ window.addEventListener('openai:ready', checkReady);
31
+ // Check immediately in case it's already ready
32
+ if (sdk.isReady()) {
33
+ setIsReady(true);
34
+ }
35
+ return () => window.removeEventListener('openai:ready', checkReady);
36
+ }, [sdk, isReady]);
37
+ return {
38
+ // SDK instance
39
+ sdk,
40
+ isReady,
41
+ // State management
42
+ setState: sdk.setState.bind(sdk),
43
+ getState: sdk.getState.bind(sdk),
44
+ // Tool calling
45
+ callTool: sdk.callTool.bind(sdk),
46
+ // Display controls
47
+ requestFullscreen: sdk.requestFullscreen.bind(sdk),
48
+ requestInline: sdk.requestInline.bind(sdk),
49
+ requestPip: sdk.requestPip.bind(sdk),
50
+ requestDisplayMode: sdk.requestDisplayMode.bind(sdk),
51
+ requestClose: sdk.requestClose.bind(sdk),
52
+ // Navigation
53
+ openExternal: sdk.openExternal.bind(sdk),
54
+ sendFollowUpMessage: sdk.sendFollowUpMessage.bind(sdk),
55
+ // Data access
56
+ getToolInput: sdk.getToolInput.bind(sdk),
57
+ getToolOutput: sdk.getToolOutput.bind(sdk),
58
+ getOutput: sdk.getOutput.bind(sdk),
59
+ getToolResponseMetadata: sdk.getToolResponseMetadata.bind(sdk),
60
+ getTheme: sdk.getTheme.bind(sdk),
61
+ getMaxHeight: sdk.getMaxHeight.bind(sdk),
62
+ getDisplayMode: sdk.getDisplayMode.bind(sdk),
63
+ getUserAgent: sdk.getUserAgent.bind(sdk),
64
+ getLocale: sdk.getLocale.bind(sdk),
65
+ getSafeArea: sdk.getSafeArea.bind(sdk),
66
+ // Convenience
67
+ isDarkMode: sdk.isDarkMode.bind(sdk),
68
+ };
69
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * NitroStack Widgets Utilities
3
+ *
4
+ * This module provides utilities for building Next.js widgets
5
+ * that integrate with NitroStack tools and are compatible with OpenAI ChatGPT.
6
+ */
7
+ export { WidgetSDK, getWidgetSDK } from './sdk.js';
8
+ export { WidgetLayout, type WidgetLayoutProps } from './runtime/WidgetLayout.js';
9
+ export { withToolData, type ToolOutputWrapper } from './withToolData.js';
10
+ export { defineWidgetMetadata, type WidgetMetadata, type WidgetExample, type WidgetManifest } from './metadata.js';
11
+ export type { UnknownObject, Theme, SafeAreaInsets, SafeArea, DeviceType, UserAgent, DisplayMode, RequestDisplayMode, CallToolResponse, CallTool, OpenAiGlobals, OpenAiAPI, SetGlobalsEvent, } from './types.js';
12
+ export { SET_GLOBALS_EVENT_TYPE } from './types.js';
13
+ export { useOpenAiGlobal, useWidgetState, useTheme, useMaxHeight, useDisplayMode, useWidgetSDK, } from './hooks/index.js';
14
+ export { prefersReducedMotion, isPrimarilyTouchDevice, isHoverAvailable, prefersDarkColorScheme, } from './utils/media-queries.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAGjF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAGnH,YAAY,EACR,aAAa,EACb,KAAK,EACL,cAAc,EACd,QAAQ,EACR,UAAU,EACV,SAAS,EACT,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAChB,QAAQ,EACR,aAAa,EACb,SAAS,EACT,eAAe,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EACH,eAAe,EACf,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,YAAY,GACf,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACH,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EAChB,sBAAsB,GACzB,MAAM,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * NitroStack Widgets Utilities
3
+ *
4
+ * This module provides utilities for building Next.js widgets
5
+ * that integrate with NitroStack tools and are compatible with OpenAI ChatGPT.
6
+ */
7
+ // Widget SDK - Clean abstraction layer
8
+ export { WidgetSDK, getWidgetSDK } from './sdk.js';
9
+ export { WidgetLayout } from './runtime/WidgetLayout.js';
10
+ // Legacy exports (backward compatibility)
11
+ export { withToolData } from './withToolData.js';
12
+ export { defineWidgetMetadata } from './metadata.js';
13
+ export { SET_GLOBALS_EVENT_TYPE } from './types.js';
14
+ // OpenAI SDK compatibility - Hooks
15
+ export { useOpenAiGlobal, useWidgetState, useTheme, useMaxHeight, useDisplayMode, useWidgetSDK, // New clean SDK hook
16
+ } from './hooks/index.js';
17
+ // OpenAI SDK compatibility - Utilities
18
+ export { prefersReducedMotion, isPrimarilyTouchDevice, isHoverAvailable, prefersDarkColorScheme, } from './utils/media-queries.js';
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Widget Metadata System
3
+ *
4
+ * Allows frontend developers to define widget examples independently
5
+ * from backend tool definitions.
6
+ */
7
+ export interface WidgetExample {
8
+ name: string;
9
+ description: string;
10
+ data: Record<string, any>;
11
+ }
12
+ export interface WidgetMetadata {
13
+ /** Widget URI/route (e.g., '/calculator-result') */
14
+ uri: string;
15
+ /** Widget display name */
16
+ name: string;
17
+ /** Widget description */
18
+ description: string;
19
+ /** Example data for preview/testing */
20
+ examples: WidgetExample[];
21
+ /** Optional tags for categorization */
22
+ tags?: string[];
23
+ }
24
+ /**
25
+ * Define widget metadata with type safety
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * export const metadata = defineWidgetMetadata({
30
+ * uri: '/calculator-result',
31
+ * name: 'Calculator Result',
32
+ * description: 'Displays calculation results',
33
+ * examples: [
34
+ * {
35
+ * name: 'Addition Example',
36
+ * description: 'Shows addition result',
37
+ * data: { result: 8, operation: 'add', a: 5, b: 3 }
38
+ * }
39
+ * ]
40
+ * });
41
+ * ```
42
+ */
43
+ export declare function defineWidgetMetadata(metadata: WidgetMetadata): WidgetMetadata;
44
+ /**
45
+ * Widget manifest structure
46
+ * Generated during widget build process
47
+ */
48
+ export interface WidgetManifest {
49
+ version: string;
50
+ widgets: WidgetMetadata[];
51
+ generatedAt: string;
52
+ }
53
+ //# sourceMappingURL=metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IAEZ,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IAEb,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IAEpB,uCAAuC;IACvC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAE1B,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,cAAc,CAE7E;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Widget Metadata System
3
+ *
4
+ * Allows frontend developers to define widget examples independently
5
+ * from backend tool definitions.
6
+ */
7
+ /**
8
+ * Define widget metadata with type safety
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * export const metadata = defineWidgetMetadata({
13
+ * uri: '/calculator-result',
14
+ * name: 'Calculator Result',
15
+ * description: 'Displays calculation results',
16
+ * examples: [
17
+ * {
18
+ * name: 'Addition Example',
19
+ * description: 'Shows addition result',
20
+ * data: { result: 8, operation: 'add', a: 5, b: 3 }
21
+ * }
22
+ * ]
23
+ * });
24
+ * ```
25
+ */
26
+ export function defineWidgetMetadata(metadata) {
27
+ return metadata;
28
+ }
@@ -0,0 +1,32 @@
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
+ import { type ReactNode } from 'react';
8
+ export interface WidgetLayoutProps {
9
+ children: ReactNode;
10
+ /**
11
+ * Optional callback when SDK is ready
12
+ */
13
+ onReady?: () => void;
14
+ }
15
+ /**
16
+ * Widget Layout component that sets up the widget runtime
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * export default function RootLayout({ children }) {
21
+ * return (
22
+ * <html lang="en">
23
+ * <body>
24
+ * <WidgetLayout>{children}</WidgetLayout>
25
+ * </body>
26
+ * </html>
27
+ * );
28
+ * }
29
+ * ```
30
+ */
31
+ export declare function WidgetLayout({ children, onReady }: WidgetLayoutProps): import("react/jsx-runtime").JSX.Element;
32
+ //# sourceMappingURL=WidgetLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetLayout.d.ts","sourceRoot":"","sources":["../../src/runtime/WidgetLayout.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAc,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,iBAAiB,2CA8IpE"}