@gravity-platform/unoverse-react 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +77 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +66 -34
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.d.cts
CHANGED
|
@@ -86,8 +86,14 @@ interface UnoverseComponentProps {
|
|
|
86
86
|
* (e.g. the workbench's light/dark toggle); swap it to restyle, zero def changes.
|
|
87
87
|
*/
|
|
88
88
|
theme?: ResolvedTheme;
|
|
89
|
+
/**
|
|
90
|
+
* Render inside a Shadow DOM for full CSS isolation (default true). The SDK owns the
|
|
91
|
+
* isolation boundary so every consumer is protected identically; the canvas/channel no
|
|
92
|
+
* longer wrap it themselves. Set false only for a host that manages its own isolation.
|
|
93
|
+
*/
|
|
94
|
+
isolate?: boolean;
|
|
89
95
|
}
|
|
90
|
-
declare function UnoverseComponent({ client, uri, data, onAction, theme }: UnoverseComponentProps): react.JSX.Element;
|
|
96
|
+
declare function UnoverseComponent({ client, uri, data, onAction, theme, isolate }: UnoverseComponentProps): react.JSX.Element;
|
|
91
97
|
|
|
92
98
|
/** Subscribe to a component instance in the store (re-renders on merge). */
|
|
93
99
|
declare function useUnoverseInstance(store: ComponentStore, chatId: string, nodeId: string): {
|
|
@@ -118,14 +124,20 @@ interface StreamedUnoverseTemplateProps {
|
|
|
118
124
|
/** Channel overrides for the template's declared props (e.g. per-tenant logoUrl/brandName).
|
|
119
125
|
* Merged OVER the definition's own `props` defaults into the root data scope. */
|
|
120
126
|
props?: Record<string, unknown>;
|
|
127
|
+
/** Render inside a Shadow DOM for full CSS isolation (default true). See UnoverseComponent. */
|
|
128
|
+
isolate?: boolean;
|
|
121
129
|
}
|
|
122
130
|
/** Resolve a ComponentSlot's `select` against the store → ordered pointers. Exported for testing. */
|
|
123
131
|
declare function selectPointers(store: ComponentStore, node: UnoverseNode): string[];
|
|
124
|
-
declare function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themeProp, props }: StreamedUnoverseTemplateProps): react.JSX.Element;
|
|
132
|
+
declare function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themeProp, props, isolate }: StreamedUnoverseTemplateProps): react.JSX.Element;
|
|
125
133
|
|
|
126
134
|
/** Returns the resolved theme (null until the first fetch resolves). */
|
|
127
135
|
declare function useUnoverseTheme(client: UnoverseClient, name?: string): ResolvedTheme | null;
|
|
128
136
|
|
|
137
|
+
declare function IsolatedRoot({ children }: {
|
|
138
|
+
children: ReactNode;
|
|
139
|
+
}): react.JSX.Element;
|
|
140
|
+
|
|
129
141
|
interface UnoverseConnectionConfig {
|
|
130
142
|
/** Gravity API base, e.g. "http://localhost:4100". REST execute lives here. */
|
|
131
143
|
apiUrl: string;
|
|
@@ -163,4 +175,4 @@ declare function useUnoverseConnection(config: UnoverseConnectionConfig, session
|
|
|
163
175
|
enabled?: boolean;
|
|
164
176
|
}): UnoverseConnection;
|
|
165
177
|
|
|
166
|
-
export { type ActionHandler, type SlotResolver, StreamedUnoverseComponent, type StreamedUnoverseComponentProps, StreamedUnoverseTemplate, type StreamedUnoverseTemplateProps, UnoverseComponent, type UnoverseComponentProps, type UnoverseConnection, type UnoverseConnectionConfig, type UnoverseSessionParams, keyframesCss, renderNode, selectPointers, styleToCss, useUnoverseConnection, useUnoverseInstance, useUnoverseTheme };
|
|
178
|
+
export { type ActionHandler, IsolatedRoot, type SlotResolver, StreamedUnoverseComponent, type StreamedUnoverseComponentProps, StreamedUnoverseTemplate, type StreamedUnoverseTemplateProps, UnoverseComponent, type UnoverseComponentProps, type UnoverseConnection, type UnoverseConnectionConfig, type UnoverseSessionParams, keyframesCss, renderNode, selectPointers, styleToCss, useUnoverseConnection, useUnoverseInstance, useUnoverseTheme };
|
package/dist/index.d.ts
CHANGED
|
@@ -86,8 +86,14 @@ interface UnoverseComponentProps {
|
|
|
86
86
|
* (e.g. the workbench's light/dark toggle); swap it to restyle, zero def changes.
|
|
87
87
|
*/
|
|
88
88
|
theme?: ResolvedTheme;
|
|
89
|
+
/**
|
|
90
|
+
* Render inside a Shadow DOM for full CSS isolation (default true). The SDK owns the
|
|
91
|
+
* isolation boundary so every consumer is protected identically; the canvas/channel no
|
|
92
|
+
* longer wrap it themselves. Set false only for a host that manages its own isolation.
|
|
93
|
+
*/
|
|
94
|
+
isolate?: boolean;
|
|
89
95
|
}
|
|
90
|
-
declare function UnoverseComponent({ client, uri, data, onAction, theme }: UnoverseComponentProps): react.JSX.Element;
|
|
96
|
+
declare function UnoverseComponent({ client, uri, data, onAction, theme, isolate }: UnoverseComponentProps): react.JSX.Element;
|
|
91
97
|
|
|
92
98
|
/** Subscribe to a component instance in the store (re-renders on merge). */
|
|
93
99
|
declare function useUnoverseInstance(store: ComponentStore, chatId: string, nodeId: string): {
|
|
@@ -118,14 +124,20 @@ interface StreamedUnoverseTemplateProps {
|
|
|
118
124
|
/** Channel overrides for the template's declared props (e.g. per-tenant logoUrl/brandName).
|
|
119
125
|
* Merged OVER the definition's own `props` defaults into the root data scope. */
|
|
120
126
|
props?: Record<string, unknown>;
|
|
127
|
+
/** Render inside a Shadow DOM for full CSS isolation (default true). See UnoverseComponent. */
|
|
128
|
+
isolate?: boolean;
|
|
121
129
|
}
|
|
122
130
|
/** Resolve a ComponentSlot's `select` against the store → ordered pointers. Exported for testing. */
|
|
123
131
|
declare function selectPointers(store: ComponentStore, node: UnoverseNode): string[];
|
|
124
|
-
declare function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themeProp, props }: StreamedUnoverseTemplateProps): react.JSX.Element;
|
|
132
|
+
declare function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themeProp, props, isolate }: StreamedUnoverseTemplateProps): react.JSX.Element;
|
|
125
133
|
|
|
126
134
|
/** Returns the resolved theme (null until the first fetch resolves). */
|
|
127
135
|
declare function useUnoverseTheme(client: UnoverseClient, name?: string): ResolvedTheme | null;
|
|
128
136
|
|
|
137
|
+
declare function IsolatedRoot({ children }: {
|
|
138
|
+
children: ReactNode;
|
|
139
|
+
}): react.JSX.Element;
|
|
140
|
+
|
|
129
141
|
interface UnoverseConnectionConfig {
|
|
130
142
|
/** Gravity API base, e.g. "http://localhost:4100". REST execute lives here. */
|
|
131
143
|
apiUrl: string;
|
|
@@ -163,4 +175,4 @@ declare function useUnoverseConnection(config: UnoverseConnectionConfig, session
|
|
|
163
175
|
enabled?: boolean;
|
|
164
176
|
}): UnoverseConnection;
|
|
165
177
|
|
|
166
|
-
export { type ActionHandler, type SlotResolver, StreamedUnoverseComponent, type StreamedUnoverseComponentProps, StreamedUnoverseTemplate, type StreamedUnoverseTemplateProps, UnoverseComponent, type UnoverseComponentProps, type UnoverseConnection, type UnoverseConnectionConfig, type UnoverseSessionParams, keyframesCss, renderNode, selectPointers, styleToCss, useUnoverseConnection, useUnoverseInstance, useUnoverseTheme };
|
|
178
|
+
export { type ActionHandler, IsolatedRoot, type SlotResolver, StreamedUnoverseComponent, type StreamedUnoverseComponentProps, StreamedUnoverseTemplate, type StreamedUnoverseTemplateProps, UnoverseComponent, type UnoverseComponentProps, type UnoverseConnection, type UnoverseConnectionConfig, type UnoverseSessionParams, keyframesCss, renderNode, selectPointers, styleToCss, useUnoverseConnection, useUnoverseInstance, useUnoverseTheme };
|
package/dist/index.js
CHANGED
|
@@ -6885,7 +6885,7 @@ var require_dist = __commonJS({
|
|
|
6885
6885
|
});
|
|
6886
6886
|
|
|
6887
6887
|
// src/UnoverseComponent.tsx
|
|
6888
|
-
import { useEffect as
|
|
6888
|
+
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
6889
6889
|
|
|
6890
6890
|
// src/primitives.tsx
|
|
6891
6891
|
import { createElement, useMemo, useState } from "react";
|
|
@@ -7192,14 +7192,43 @@ function useUnoverseTheme(client, name = "light") {
|
|
|
7192
7192
|
return theme;
|
|
7193
7193
|
}
|
|
7194
7194
|
|
|
7195
|
-
// src/
|
|
7195
|
+
// src/isolate.tsx
|
|
7196
|
+
import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
|
|
7197
|
+
import { createPortal } from "react-dom";
|
|
7196
7198
|
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7199
|
+
var RESET_CSS = `
|
|
7200
|
+
:host { all: initial; display: contents; }
|
|
7201
|
+
.uno-isolate-root { box-sizing: border-box; }
|
|
7202
|
+
.uno-isolate-root *, .uno-isolate-root *::before, .uno-isolate-root *::after { box-sizing: border-box; }
|
|
7203
|
+
.uno-isolate-root button, .uno-isolate-root input, .uno-isolate-root textarea, .uno-isolate-root select {
|
|
7204
|
+
font: inherit; letter-spacing: inherit; color: inherit; margin: 0;
|
|
7205
|
+
}
|
|
7206
|
+
`;
|
|
7207
|
+
function IsolatedRoot({ children }) {
|
|
7208
|
+
const hostRef = useRef(null);
|
|
7209
|
+
const [shadow, setShadow] = useState3(null);
|
|
7210
|
+
useEffect2(() => {
|
|
7211
|
+
const host = hostRef.current;
|
|
7212
|
+
if (!host) return;
|
|
7213
|
+
setShadow(host.shadowRoot ?? host.attachShadow({ mode: "open" }));
|
|
7214
|
+
}, []);
|
|
7215
|
+
return /* @__PURE__ */ jsx3("div", { ref: hostRef, style: { display: "contents" }, children: shadow && createPortal(
|
|
7216
|
+
/* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
7217
|
+
/* @__PURE__ */ jsx3("style", { children: RESET_CSS }),
|
|
7218
|
+
/* @__PURE__ */ jsx3("div", { className: "uno-isolate-root", children })
|
|
7219
|
+
] }),
|
|
7220
|
+
shadow
|
|
7221
|
+
) });
|
|
7222
|
+
}
|
|
7223
|
+
|
|
7224
|
+
// src/UnoverseComponent.tsx
|
|
7225
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
7226
|
+
function UnoverseComponent({ client, uri, data, onAction, theme, isolate = true }) {
|
|
7227
|
+
const [def, setDef] = useState4(null);
|
|
7228
|
+
const [error2, setError] = useState4(null);
|
|
7200
7229
|
const fetched = useUnoverseTheme(client, "light");
|
|
7201
7230
|
const activeTheme = theme ?? fetched;
|
|
7202
|
-
|
|
7231
|
+
useEffect3(() => {
|
|
7203
7232
|
let alive = true;
|
|
7204
7233
|
setDef(null);
|
|
7205
7234
|
setError(null);
|
|
@@ -7208,11 +7237,11 @@ function UnoverseComponent({ client, uri, data, onAction, theme }) {
|
|
|
7208
7237
|
alive = false;
|
|
7209
7238
|
};
|
|
7210
7239
|
}, [client, uri]);
|
|
7211
|
-
if (error2) return /* @__PURE__ */
|
|
7240
|
+
if (error2) return /* @__PURE__ */ jsxs3("div", { children: [
|
|
7212
7241
|
"Unoverse error: ",
|
|
7213
7242
|
error2
|
|
7214
7243
|
] });
|
|
7215
|
-
if (!def || !activeTheme) return /* @__PURE__ */
|
|
7244
|
+
if (!def || !activeTheme) return /* @__PURE__ */ jsxs3("div", { children: [
|
|
7216
7245
|
"Loading ",
|
|
7217
7246
|
uri,
|
|
7218
7247
|
"\u2026"
|
|
@@ -7220,17 +7249,18 @@ function UnoverseComponent({ client, uri, data, onAction, theme }) {
|
|
|
7220
7249
|
const propDefaults2 = Object.fromEntries(
|
|
7221
7250
|
Object.entries(def.props ?? {}).map(([k, v]) => [k, v?.default])
|
|
7222
7251
|
);
|
|
7223
|
-
const merged =
|
|
7224
|
-
|
|
7225
|
-
/* @__PURE__ */
|
|
7226
|
-
/* @__PURE__ */
|
|
7252
|
+
const merged = data ?? propDefaults2;
|
|
7253
|
+
const body = /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
7254
|
+
/* @__PURE__ */ jsx4("style", { children: keyframesCss(activeTheme) }),
|
|
7255
|
+
/* @__PURE__ */ jsx4("div", { style: { display: "contents", ...activeTheme.root }, children: renderNode(def.root, merged, onAction, activeTheme) })
|
|
7227
7256
|
] });
|
|
7257
|
+
return isolate ? /* @__PURE__ */ jsx4(IsolatedRoot, { children: body }) : body;
|
|
7228
7258
|
}
|
|
7229
7259
|
|
|
7230
7260
|
// src/streamed.tsx
|
|
7231
7261
|
import { useCallback, useMemo as useMemo2, useSyncExternalStore } from "react";
|
|
7232
7262
|
import { dispatchAction } from "@gravity-platform/unoverse-core";
|
|
7233
|
-
import { jsx as
|
|
7263
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
7234
7264
|
function useUnoverseInstance(store, chatId, nodeId) {
|
|
7235
7265
|
const subscribe = useCallback((cb) => store.subscribe(cb), [store]);
|
|
7236
7266
|
const getVersion = useCallback(() => store.getVersion(), [store]);
|
|
@@ -7248,14 +7278,14 @@ function StreamedUnoverseComponent({ client, store, chatId, nodeId, onAction, th
|
|
|
7248
7278
|
}),
|
|
7249
7279
|
[store, chatId, nodeId, onAction]
|
|
7250
7280
|
);
|
|
7251
|
-
if (!type) return /* @__PURE__ */
|
|
7281
|
+
if (!type) return /* @__PURE__ */ jsx5("div", { children: "waiting for COMPONENT_INIT\u2026" });
|
|
7252
7282
|
const merged = extraData ? { ...data, ...extraData } : data;
|
|
7253
|
-
return /* @__PURE__ */
|
|
7283
|
+
return /* @__PURE__ */ jsx5(UnoverseComponent, { client, uri: `unoverse://components/${type}`, data: merged, onAction: handleAction, theme });
|
|
7254
7284
|
}
|
|
7255
7285
|
|
|
7256
7286
|
// src/template.tsx
|
|
7257
|
-
import { useEffect as
|
|
7258
|
-
import { Fragment as
|
|
7287
|
+
import { useEffect as useEffect4, useState as useState5, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
7288
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
7259
7289
|
function propDefaults(props) {
|
|
7260
7290
|
const out = {};
|
|
7261
7291
|
for (const [k, v] of Object.entries(props ?? {})) {
|
|
@@ -7286,16 +7316,16 @@ function selectPointers(store, node) {
|
|
|
7286
7316
|
if (sel.limit != null) pointers = pointers.slice(0, sel.limit);
|
|
7287
7317
|
return pointers;
|
|
7288
7318
|
}
|
|
7289
|
-
function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themeProp, props }) {
|
|
7290
|
-
const [def, setDef] =
|
|
7291
|
-
const [error2, setError] =
|
|
7319
|
+
function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themeProp, props, isolate = true }) {
|
|
7320
|
+
const [def, setDef] = useState5(null);
|
|
7321
|
+
const [error2, setError] = useState5(null);
|
|
7292
7322
|
const fetched = useUnoverseTheme(client, "light");
|
|
7293
7323
|
const theme = themeProp ?? fetched;
|
|
7294
7324
|
useSyncExternalStore2(
|
|
7295
7325
|
(cb) => store.subscribe(cb),
|
|
7296
7326
|
() => store.getVersion()
|
|
7297
7327
|
);
|
|
7298
|
-
|
|
7328
|
+
useEffect4(() => {
|
|
7299
7329
|
let alive = true;
|
|
7300
7330
|
setDef(null);
|
|
7301
7331
|
setError(null);
|
|
@@ -7304,18 +7334,18 @@ function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themePr
|
|
|
7304
7334
|
alive = false;
|
|
7305
7335
|
};
|
|
7306
7336
|
}, [client, uri]);
|
|
7307
|
-
if (error2) return /* @__PURE__ */
|
|
7337
|
+
if (error2) return /* @__PURE__ */ jsxs4("div", { children: [
|
|
7308
7338
|
"Unoverse error: ",
|
|
7309
7339
|
error2
|
|
7310
7340
|
] });
|
|
7311
|
-
if (!def || !theme) return /* @__PURE__ */
|
|
7341
|
+
if (!def || !theme) return /* @__PURE__ */ jsxs4("div", { children: [
|
|
7312
7342
|
"Loading ",
|
|
7313
7343
|
uri,
|
|
7314
7344
|
"\u2026"
|
|
7315
7345
|
] });
|
|
7316
7346
|
const leaf = (pointer, extraData) => {
|
|
7317
7347
|
const { chatId, nodeId } = store.split(pointer);
|
|
7318
|
-
return /* @__PURE__ */
|
|
7348
|
+
return /* @__PURE__ */ jsx6(StreamedUnoverseComponent, { client, store, chatId, nodeId, onAction, theme, extraData }, pointer);
|
|
7319
7349
|
};
|
|
7320
7350
|
const resolveSlot = (node, key) => {
|
|
7321
7351
|
const pointers = selectPointers(store, node);
|
|
@@ -7325,7 +7355,7 @@ function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themePr
|
|
|
7325
7355
|
return pointers.map((p) => leaf(p));
|
|
7326
7356
|
};
|
|
7327
7357
|
const resolveTimeline = (node, key) => {
|
|
7328
|
-
return /* @__PURE__ */
|
|
7358
|
+
return /* @__PURE__ */ jsx6("div", { style: styleToCss(node.style, theme), children: store.getTimeline().map((turn) => {
|
|
7329
7359
|
const sub = turn.role === "user" ? node.user : node.assistant;
|
|
7330
7360
|
if (!sub) return null;
|
|
7331
7361
|
const turnSlot = (slotNode, k) => {
|
|
@@ -7364,14 +7394,15 @@ function StreamedUnoverseTemplate({ client, store, uri, onAction, theme: themePr
|
|
|
7364
7394
|
// button submits it. Lives in the store (shared state), not locally in Input.
|
|
7365
7395
|
draft: store.getDraft()
|
|
7366
7396
|
};
|
|
7367
|
-
|
|
7368
|
-
/* @__PURE__ */
|
|
7369
|
-
/* @__PURE__ */
|
|
7397
|
+
const body = /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
7398
|
+
/* @__PURE__ */ jsx6("style", { children: keyframesCss(theme) }),
|
|
7399
|
+
/* @__PURE__ */ jsx6("div", { style: { display: "contents", ...theme.root }, children: renderNode(def.root, rootData, onAction, theme, void 0, resolve) })
|
|
7370
7400
|
] });
|
|
7401
|
+
return isolate ? /* @__PURE__ */ jsx6(IsolatedRoot, { children: body }) : body;
|
|
7371
7402
|
}
|
|
7372
7403
|
|
|
7373
7404
|
// src/connection.tsx
|
|
7374
|
-
import { useCallback as useCallback2, useEffect as
|
|
7405
|
+
import { useCallback as useCallback2, useEffect as useEffect5, useRef as useRef2, useState as useState6, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
7375
7406
|
import { applyServerMessage } from "@gravity-platform/unoverse-core";
|
|
7376
7407
|
|
|
7377
7408
|
// ../node_modules/zod/v4/core/core.js
|
|
@@ -17596,11 +17627,11 @@ function useUnoverseConnection(config2, session, store, options = {}) {
|
|
|
17596
17627
|
const { apiUrl, streamUrl, getAccessToken } = config2;
|
|
17597
17628
|
const { workflowId, targetTriggerNode, userId, conversationId } = session;
|
|
17598
17629
|
const chatId = session.chatId ?? conversationId;
|
|
17599
|
-
const [isConnected, setIsConnected] =
|
|
17600
|
-
const [isReady, setIsReady] =
|
|
17601
|
-
const clientRef =
|
|
17602
|
-
const seenRef =
|
|
17603
|
-
|
|
17630
|
+
const [isConnected, setIsConnected] = useState6(false);
|
|
17631
|
+
const [isReady, setIsReady] = useState6(false);
|
|
17632
|
+
const clientRef = useRef2(null);
|
|
17633
|
+
const seenRef = useRef2(/* @__PURE__ */ new Set());
|
|
17634
|
+
useEffect5(() => {
|
|
17604
17635
|
if (!enabled) return;
|
|
17605
17636
|
if (!workflowId || !userId || !conversationId) {
|
|
17606
17637
|
console.warn("[unoverse] connection missing workflowId/userId/conversationId");
|
|
@@ -17700,6 +17731,7 @@ function useUnoverseConnection(config2, session, store, options = {}) {
|
|
|
17700
17731
|
return { isConnected, isReady, sendMessage, trigger, sendAction, activeTemplate };
|
|
17701
17732
|
}
|
|
17702
17733
|
export {
|
|
17734
|
+
IsolatedRoot,
|
|
17703
17735
|
StreamedUnoverseComponent,
|
|
17704
17736
|
StreamedUnoverseTemplate,
|
|
17705
17737
|
UnoverseComponent,
|