@sidecar-ai/react 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +46 -0
- package/dist/index.js +144 -0
- package/dist/index.js.map +1 -0
- package/package.json +25 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ComponentType, ReactNode } from 'react';
|
|
3
|
+
import { WidgetBridge, SidecarHostContext, WidgetToolResult } from '@sidecar-ai/client';
|
|
4
|
+
export { HostFeatureResult, HostLogLevel, HostLogMessage, ModelMessage, SamplingMessageRequest, SamplingMessageResult, ServerResource, ServerResourceContent, ServerResourceListResult, ServerResourceReadResult, SidecarHostContext, SizeChangedMessage, ToolCancelledListener, ToolInput, ToolInputListener, WidgetBridge, WidgetToolResult, browserBridge, createBrowserBridge, createToolClient, getToolResult, log, model, sampling, server, view } from '@sidecar-ai/client';
|
|
5
|
+
import { ToolWidgetOptions } from '@sidecar-ai/core';
|
|
6
|
+
export { ChatGptWidgetOptions, WidgetCspOptions } from '@sidecar-ai/core';
|
|
7
|
+
|
|
8
|
+
/** Props supplied to generated widget roots. Widgets read data through hooks. */
|
|
9
|
+
type WidgetProps = Record<string, never>;
|
|
10
|
+
/** React component returned by `widget(...)` with static Sidecar metadata. */
|
|
11
|
+
type SidecarWidget = ComponentType<WidgetProps> & {
|
|
12
|
+
readonly kind: "sidecar.widget";
|
|
13
|
+
readonly options: ToolWidgetOptions;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Declares a React widget and its MCP Apps resource metadata.
|
|
17
|
+
*
|
|
18
|
+
* The compiler reads the options statically from `widget.tsx`; at runtime this
|
|
19
|
+
* returns the component itself so React rendering stays ordinary.
|
|
20
|
+
*/
|
|
21
|
+
declare function widget(options: ToolWidgetOptions, Component: ComponentType<WidgetProps>): SidecarWidget;
|
|
22
|
+
/** Provides a custom widget bridge for tests or non-browser embedding. */
|
|
23
|
+
declare function SidecarWidgetProvider(props: {
|
|
24
|
+
bridge: WidgetBridge;
|
|
25
|
+
children?: ReactNode;
|
|
26
|
+
}): React.FunctionComponentElement<React.ProviderProps<WidgetBridge | null>>;
|
|
27
|
+
/** Generated widgets mount through this root so host context is always active. */
|
|
28
|
+
declare function SidecarWidgetRoot(props: {
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
bridge?: WidgetBridge;
|
|
31
|
+
}): React.FunctionComponentElement<{
|
|
32
|
+
bridge: WidgetBridge;
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
}>;
|
|
35
|
+
/** Returns the nearest bridge provider or the default browser bridge. */
|
|
36
|
+
declare function useWidgetBridge(): WidgetBridge;
|
|
37
|
+
/** React hook for reading the current tool result. */
|
|
38
|
+
declare function useToolResult<Structured, Meta = Record<string, unknown>>(): WidgetToolResult<Structured, Meta>;
|
|
39
|
+
/** React hook for the active host/theme context. */
|
|
40
|
+
declare function useHost(): SidecarHostContext;
|
|
41
|
+
/** React hook for just the active light/dark theme. */
|
|
42
|
+
declare function useTheme(): SidecarHostContext["theme"];
|
|
43
|
+
/** Session-storage backed state helper for lightweight widget state. */
|
|
44
|
+
declare function useWidgetState<T>(key: string, initialValue: T): [T, (value: T) => void];
|
|
45
|
+
|
|
46
|
+
export { type SidecarWidget, SidecarWidgetProvider, SidecarWidgetRoot, ToolWidgetOptions as WidgetOptions, type WidgetProps, useHost, useTheme, useToolResult, useWidgetBridge, useWidgetState, widget };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// packages/react/src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
browserBridge
|
|
4
|
+
} from "@sidecar-ai/client";
|
|
5
|
+
import {
|
|
6
|
+
createContext,
|
|
7
|
+
createElement,
|
|
8
|
+
useEffect,
|
|
9
|
+
useContext,
|
|
10
|
+
useMemo,
|
|
11
|
+
useState
|
|
12
|
+
} from "react";
|
|
13
|
+
import {
|
|
14
|
+
browserBridge as browserBridge2,
|
|
15
|
+
createBrowserBridge,
|
|
16
|
+
createToolClient,
|
|
17
|
+
getToolResult,
|
|
18
|
+
log,
|
|
19
|
+
model,
|
|
20
|
+
sampling,
|
|
21
|
+
server,
|
|
22
|
+
view
|
|
23
|
+
} from "@sidecar-ai/client";
|
|
24
|
+
var WidgetBridgeContext = createContext(null);
|
|
25
|
+
var HostContextContext = createContext(null);
|
|
26
|
+
function widget(options, Component) {
|
|
27
|
+
Object.defineProperties(Component, {
|
|
28
|
+
kind: {
|
|
29
|
+
enumerable: false,
|
|
30
|
+
value: "sidecar.widget"
|
|
31
|
+
},
|
|
32
|
+
options: {
|
|
33
|
+
enumerable: false,
|
|
34
|
+
value: Object.freeze({ ...options })
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return Component;
|
|
38
|
+
}
|
|
39
|
+
function SidecarWidgetProvider(props) {
|
|
40
|
+
const [hostContext, setHostContext] = useState(
|
|
41
|
+
() => props.bridge.getHostContext()
|
|
42
|
+
);
|
|
43
|
+
useEffect(() => props.bridge.subscribeHostContext(setHostContext), [props.bridge]);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (typeof document === "undefined") {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
document.documentElement.dataset.sidecarHost = hostContext.name;
|
|
49
|
+
document.documentElement.dataset.sidecarTheme = hostContext.theme;
|
|
50
|
+
}, [hostContext]);
|
|
51
|
+
return createElement(
|
|
52
|
+
WidgetBridgeContext.Provider,
|
|
53
|
+
{ value: props.bridge },
|
|
54
|
+
createElement(
|
|
55
|
+
HostContextContext.Provider,
|
|
56
|
+
{ value: hostContext },
|
|
57
|
+
props.children
|
|
58
|
+
)
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
function SidecarWidgetRoot(props) {
|
|
62
|
+
return createElement(
|
|
63
|
+
SidecarWidgetProvider,
|
|
64
|
+
{ bridge: props.bridge ?? browserBridge },
|
|
65
|
+
props.children
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
function useWidgetBridge() {
|
|
69
|
+
const bridge = useContext(WidgetBridgeContext);
|
|
70
|
+
if (!bridge) {
|
|
71
|
+
return browserBridge;
|
|
72
|
+
}
|
|
73
|
+
return bridge;
|
|
74
|
+
}
|
|
75
|
+
function useToolResult() {
|
|
76
|
+
const bridge = useWidgetBridge();
|
|
77
|
+
const [result, setResult] = useState(
|
|
78
|
+
() => bridge.getToolResult()
|
|
79
|
+
);
|
|
80
|
+
useEffect(
|
|
81
|
+
() => bridge.subscribeToolResult(
|
|
82
|
+
(next) => setResult(next)
|
|
83
|
+
),
|
|
84
|
+
[bridge]
|
|
85
|
+
);
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
function useHost() {
|
|
89
|
+
const context = useContext(HostContextContext);
|
|
90
|
+
if (context) {
|
|
91
|
+
return context;
|
|
92
|
+
}
|
|
93
|
+
return useWidgetBridge().getHostContext();
|
|
94
|
+
}
|
|
95
|
+
function useTheme() {
|
|
96
|
+
return useHost().theme;
|
|
97
|
+
}
|
|
98
|
+
function useWidgetState(key, initialValue) {
|
|
99
|
+
const storageKey = `sidecar.widget.${key}`;
|
|
100
|
+
const [value, setValue] = useState(() => {
|
|
101
|
+
if (typeof window === "undefined") {
|
|
102
|
+
return initialValue;
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
const stored = window.sessionStorage.getItem(storageKey);
|
|
106
|
+
return stored === null ? initialValue : JSON.parse(stored);
|
|
107
|
+
} catch {
|
|
108
|
+
return initialValue;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
const update = useMemo(
|
|
112
|
+
() => (next) => {
|
|
113
|
+
setValue(next);
|
|
114
|
+
if (typeof window !== "undefined") {
|
|
115
|
+
try {
|
|
116
|
+
window.sessionStorage.setItem(storageKey, JSON.stringify(next));
|
|
117
|
+
} catch {
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
[storageKey]
|
|
122
|
+
);
|
|
123
|
+
return [value, update];
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
SidecarWidgetProvider,
|
|
127
|
+
SidecarWidgetRoot,
|
|
128
|
+
browserBridge2 as browserBridge,
|
|
129
|
+
createBrowserBridge,
|
|
130
|
+
createToolClient,
|
|
131
|
+
getToolResult,
|
|
132
|
+
log,
|
|
133
|
+
model,
|
|
134
|
+
sampling,
|
|
135
|
+
server,
|
|
136
|
+
useHost,
|
|
137
|
+
useTheme,
|
|
138
|
+
useToolResult,
|
|
139
|
+
useWidgetBridge,
|
|
140
|
+
useWidgetState,
|
|
141
|
+
view,
|
|
142
|
+
widget
|
|
143
|
+
};
|
|
144
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../packages/react/src/index.ts"],"sourcesContent":["/**\n * React conveniences over the framework-agnostic `@sidecar-ai/client` bridge.\n *\n * Widgets can use this package for hooks, but the underlying iframe bridge is\n * intentionally not React-specific.\n */\nimport {\n browserBridge,\n type WidgetBridge,\n type WidgetToolResult,\n type SidecarHostContext,\n} from \"@sidecar-ai/client\";\nimport {\n createContext,\n createElement,\n useEffect,\n useContext,\n useMemo,\n useState,\n type ComponentType,\n type ReactNode,\n} from \"react\";\nimport type { ToolWidgetOptions } from \"@sidecar-ai/core\";\n\nexport {\n browserBridge,\n createBrowserBridge,\n createToolClient,\n getToolResult,\n log,\n model,\n sampling,\n server,\n view,\n type HostFeatureResult,\n type HostLogLevel,\n type HostLogMessage,\n type SamplingMessageRequest,\n type SamplingMessageResult,\n type ServerResource,\n type ServerResourceContent,\n type ServerResourceListResult,\n type ServerResourceReadResult,\n type SidecarHostContext,\n type ModelMessage,\n type SizeChangedMessage,\n type ToolCancelledListener,\n type ToolInput,\n type ToolInputListener,\n type WidgetBridge,\n type WidgetToolResult,\n} from \"@sidecar-ai/client\";\nexport type {\n ChatGptWidgetOptions,\n ToolWidgetOptions as WidgetOptions,\n WidgetCspOptions,\n} from \"@sidecar-ai/core\";\n\n/** Props supplied to generated widget roots. Widgets read data through hooks. */\nexport type WidgetProps = Record<string, never>;\n\n/** React component returned by `widget(...)` with static Sidecar metadata. */\nexport type SidecarWidget = ComponentType<WidgetProps> & {\n readonly kind: \"sidecar.widget\";\n readonly options: ToolWidgetOptions;\n};\n\nconst WidgetBridgeContext = createContext<WidgetBridge | null>(null);\nconst HostContextContext = createContext<SidecarHostContext | null>(null);\n\n/**\n * Declares a React widget and its MCP Apps resource metadata.\n *\n * The compiler reads the options statically from `widget.tsx`; at runtime this\n * returns the component itself so React rendering stays ordinary.\n */\nexport function widget(\n options: ToolWidgetOptions,\n Component: ComponentType<WidgetProps>,\n): SidecarWidget {\n Object.defineProperties(Component, {\n kind: {\n enumerable: false,\n value: \"sidecar.widget\",\n },\n options: {\n enumerable: false,\n value: Object.freeze({ ...options }),\n },\n });\n\n return Component as SidecarWidget;\n}\n\n/** Provides a custom widget bridge for tests or non-browser embedding. */\nexport function SidecarWidgetProvider(props: { bridge: WidgetBridge; children?: ReactNode }) {\n const [hostContext, setHostContext] = useState<SidecarHostContext>(() =>\n props.bridge.getHostContext(),\n );\n\n useEffect(() => props.bridge.subscribeHostContext(setHostContext), [props.bridge]);\n\n useEffect(() => {\n if (typeof document === \"undefined\") {\n return;\n }\n\n document.documentElement.dataset.sidecarHost = hostContext.name;\n document.documentElement.dataset.sidecarTheme = hostContext.theme;\n }, [hostContext]);\n\n return createElement(\n WidgetBridgeContext.Provider,\n { value: props.bridge },\n createElement(\n HostContextContext.Provider,\n { value: hostContext },\n props.children,\n ),\n );\n}\n\n/** Generated widgets mount through this root so host context is always active. */\nexport function SidecarWidgetRoot(props: { children: ReactNode; bridge?: WidgetBridge }) {\n return createElement(\n SidecarWidgetProvider,\n { bridge: props.bridge ?? browserBridge },\n props.children,\n );\n}\n\n/** Returns the nearest bridge provider or the default browser bridge. */\nexport function useWidgetBridge(): WidgetBridge {\n const bridge = useContext(WidgetBridgeContext);\n if (!bridge) {\n return browserBridge;\n }\n return bridge;\n}\n\n/** React hook for reading the current tool result. */\nexport function useToolResult<Structured, Meta = Record<string, unknown>>(): WidgetToolResult<Structured, Meta> {\n const bridge = useWidgetBridge();\n const [result, setResult] = useState<WidgetToolResult<Structured, Meta>>(() =>\n bridge.getToolResult<Structured, Meta>(),\n );\n\n useEffect(\n () =>\n bridge.subscribeToolResult((next) =>\n setResult(next as WidgetToolResult<Structured, Meta>),\n ),\n [bridge],\n );\n\n return result;\n}\n\n/** React hook for the active host/theme context. */\nexport function useHost(): SidecarHostContext {\n const context = useContext(HostContextContext);\n if (context) {\n return context;\n }\n\n return useWidgetBridge().getHostContext();\n}\n\n/** React hook for just the active light/dark theme. */\nexport function useTheme(): SidecarHostContext[\"theme\"] {\n return useHost().theme;\n}\n\n/** Session-storage backed state helper for lightweight widget state. */\nexport function useWidgetState<T>(key: string, initialValue: T): [T, (value: T) => void] {\n const storageKey = `sidecar.widget.${key}`;\n const [value, setValue] = useState<T>(() => {\n if (typeof window === \"undefined\") {\n return initialValue;\n }\n\n try {\n const stored = window.sessionStorage.getItem(storageKey);\n return stored === null ? initialValue : (JSON.parse(stored) as T);\n } catch {\n return initialValue;\n }\n });\n\n const update = useMemo(\n () => (next: T) => {\n setValue(next);\n if (typeof window !== \"undefined\") {\n try {\n window.sessionStorage.setItem(storageKey, JSON.stringify(next));\n } catch {\n // Session storage can be unavailable or quota-limited in host iframes.\n }\n }\n },\n [storageKey]\n );\n\n return [value, update];\n}\n"],"mappings":"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","names":["browserBridge"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sidecar-ai/react",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@sidecar-ai/client": "0.1.0-alpha.0",
|
|
17
|
+
"@sidecar-ai/core": "0.1.0-alpha.0"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
}
|
|
25
|
+
}
|