@gravity-platform/unoverse-react 0.0.1

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 ADDED
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ StreamedUnoverseComponent: () => StreamedUnoverseComponent,
24
+ UnoverseComponent: () => UnoverseComponent,
25
+ renderNode: () => renderNode,
26
+ useUnoverseInstance: () => useUnoverseInstance
27
+ });
28
+ module.exports = __toCommonJS(index_exports);
29
+
30
+ // src/UnoverseComponent.tsx
31
+ var import_react = require("react");
32
+
33
+ // src/tokens.ts
34
+ var spacing = {
35
+ xs: "4px",
36
+ sm: "12px",
37
+ md: "16px",
38
+ lg: "24px",
39
+ xl: "32px"
40
+ };
41
+ var colors = {
42
+ "text-primary": "#111827",
43
+ "text-secondary": "#4b5563",
44
+ muted: "#6b7280",
45
+ surface: "#ffffff"
46
+ };
47
+ var fonts = {
48
+ "headline-sm": { fontSize: "1.25rem", lineHeight: 1.3 },
49
+ title: { fontSize: "1.125rem", lineHeight: 1.3 },
50
+ "body-md": { fontSize: "1rem", lineHeight: 1.6 },
51
+ body: { fontSize: "1rem", lineHeight: 1.6 }
52
+ };
53
+ var shadows = {
54
+ lg: "0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)"
55
+ };
56
+ var radii = { sm: "4px", md: "8px", lg: "12px" };
57
+ var borders = { subtle: "1px solid #e5e7eb" };
58
+ function buttonStyle(variant = "primary") {
59
+ const base = {
60
+ border: "none",
61
+ cursor: "pointer",
62
+ fontWeight: 600,
63
+ padding: "12px 24px",
64
+ borderRadius: radii.sm
65
+ };
66
+ if (variant === "primary") return { ...base, background: "#d81e2c", color: "#ffffff" };
67
+ if (variant === "outline") return { ...base, background: "transparent", border: "2px solid #d81e2c", color: "#d81e2c" };
68
+ return base;
69
+ }
70
+
71
+ // src/render.tsx
72
+ var import_jsx_runtime = require("react/jsx-runtime");
73
+ function styleToCss(s = {}) {
74
+ const css = {};
75
+ const dim = (v) => v === "full" ? "100%" : v;
76
+ if (s.width != null) css.width = dim(s.width);
77
+ if (s.height != null) css.height = dim(s.height);
78
+ if (s.direction) {
79
+ css.display = "flex";
80
+ css.flexDirection = s.direction;
81
+ }
82
+ if (s.gap) css.gap = spacing[s.gap] ?? s.gap;
83
+ if (s.padding) css.padding = spacing[s.padding] ?? s.padding;
84
+ if (s.align) css.alignItems = s.align === "start" ? "flex-start" : s.align;
85
+ if (s.justify) css.justifyContent = s.justify;
86
+ if (s.background) css.background = colors[s.background] ?? s.background;
87
+ if (s.border) css.border = borders[s.border] ?? s.border;
88
+ if (s.shadow) css.boxShadow = shadows[s.shadow] ?? s.shadow;
89
+ if (s.radius) css.borderRadius = radii[s.radius] ?? s.radius;
90
+ if (s.overflow) css.overflow = s.overflow;
91
+ if (s.fit) css.objectFit = s.fit;
92
+ if (s.font && fonts[s.font]) Object.assign(css, fonts[s.font]);
93
+ if (s.weight === "semibold") css.fontWeight = 600;
94
+ if (s.color) css.color = colors[s.color] ?? s.color;
95
+ return css;
96
+ }
97
+ function bound(field, data) {
98
+ return field ? data[field] : void 0;
99
+ }
100
+ function renderNode(node, data, onAction, key) {
101
+ if (node.visibleWhen) {
102
+ const v = data[node.visibleWhen];
103
+ if (v == null || v === "" || v === false) return null;
104
+ }
105
+ const style = styleToCss(node.style);
106
+ const kids = (node.children ?? []).map((c, i) => renderNode(c, data, onAction, i));
107
+ switch (node.type) {
108
+ case "Box":
109
+ case "Stack":
110
+ case "Row":
111
+ case "Column":
112
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style, children: kids }, key);
113
+ case "Text":
114
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style, children: bound(node.bind?.value, data) }, key);
115
+ case "Image":
116
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { style, src: bound(node.bind?.src, data), alt: bound(node.bind?.alt, data) ?? "" }, key);
117
+ case "Button":
118
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
119
+ "button",
120
+ {
121
+ style: { ...buttonStyle(node.style?.variant), ...style },
122
+ onClick: () => onAction?.(node.action ?? "click", data),
123
+ children: bound(node.bind?.label, data)
124
+ },
125
+ key
126
+ );
127
+ default:
128
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style, "data-unoverse-unknown": node.type, children: kids }, key);
129
+ }
130
+ }
131
+
132
+ // src/UnoverseComponent.tsx
133
+ var import_jsx_runtime2 = require("react/jsx-runtime");
134
+ function UnoverseComponent({ client, uri, data, onAction }) {
135
+ const [def, setDef] = (0, import_react.useState)(null);
136
+ const [error, setError] = (0, import_react.useState)(null);
137
+ (0, import_react.useEffect)(() => {
138
+ let alive = true;
139
+ setDef(null);
140
+ setError(null);
141
+ client.readDefinition(uri).then((d) => alive && setDef(d)).catch((e) => alive && setError(String(e?.message ?? e)));
142
+ return () => {
143
+ alive = false;
144
+ };
145
+ }, [client, uri]);
146
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { color: "#d81e2c", fontSize: 13 }, children: [
147
+ "Unoverse error: ",
148
+ error
149
+ ] });
150
+ if (!def) return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { color: "#9ca3af", fontSize: 13 }, children: [
151
+ "Loading ",
152
+ uri,
153
+ "\u2026"
154
+ ] });
155
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: renderNode(def.root, data ?? {}, onAction) });
156
+ }
157
+
158
+ // src/streamed.tsx
159
+ var import_react2 = require("react");
160
+ var import_jsx_runtime3 = require("react/jsx-runtime");
161
+ function useUnoverseInstance(store, chatId, nodeId) {
162
+ const subscribe = (0, import_react2.useCallback)((cb) => store.subscribe(cb), [store]);
163
+ const getVersion = (0, import_react2.useCallback)(() => store.getVersion(), [store]);
164
+ (0, import_react2.useSyncExternalStore)(subscribe, getVersion);
165
+ return { type: store.getType(chatId, nodeId), data: store.get(chatId, nodeId) };
166
+ }
167
+ function StreamedUnoverseComponent({ client, store, chatId, nodeId, onAction }) {
168
+ const { type, data } = useUnoverseInstance(store, chatId, nodeId);
169
+ if (!type) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { color: "#9ca3af", fontSize: 13 }, children: "waiting for COMPONENT_INIT\u2026" });
170
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(UnoverseComponent, { client, uri: `unoverse://components/${type}`, data, onAction });
171
+ }
172
+ // Annotate the CommonJS export names for ESM import in node:
173
+ 0 && (module.exports = {
174
+ StreamedUnoverseComponent,
175
+ UnoverseComponent,
176
+ renderNode,
177
+ useUnoverseInstance
178
+ });
179
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/UnoverseComponent.tsx","../src/tokens.ts","../src/render.tsx","../src/streamed.tsx"],"sourcesContent":["export { UnoverseComponent } from \"./UnoverseComponent\";\nexport type { UnoverseComponentProps } from \"./UnoverseComponent\";\nexport { StreamedUnoverseComponent, useUnoverseInstance } from \"./streamed\";\nexport type { StreamedUnoverseComponentProps } from \"./streamed\";\nexport { renderNode } from \"./render\";\nexport type { ActionHandler } from \"./render\";\n","/**\n * <UnoverseComponent> — reads a definition by URI from the Unoverse MCP server\n * (via @gravity-platform/unoverse-core) and renders it natively with the given data.\n */\nimport { useEffect, useState } from \"react\";\nimport type { UnoverseClient, UnoverseDefinition } from \"@gravity-platform/unoverse-core\";\nimport { renderNode, type ActionHandler } from \"./render\";\n\nexport interface UnoverseComponentProps {\n client: UnoverseClient;\n /** e.g. \"unoverse://components/Card\" */\n uri: string;\n /** instance data bound into the definition (the streamed props) */\n data?: Record<string, unknown>;\n onAction?: ActionHandler;\n}\n\nexport function UnoverseComponent({ client, uri, data, onAction }: UnoverseComponentProps) {\n const [def, setDef] = useState<UnoverseDefinition | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let alive = true;\n setDef(null);\n setError(null);\n client\n .readDefinition(uri)\n .then((d) => alive && setDef(d))\n .catch((e) => alive && setError(String(e?.message ?? e)));\n return () => {\n alive = false;\n };\n }, [client, uri]);\n\n if (error) return <div style={{ color: \"#d81e2c\", fontSize: 13 }}>Unoverse error: {error}</div>;\n if (!def) return <div style={{ color: \"#9ca3af\", fontSize: 13 }}>Loading {uri}…</div>;\n return <>{renderNode(def.root, data ?? {}, onAction)}</>;\n}\n","/**\n * Unoverse style vocabulary → CSS values (web renderer).\n *\n * A small, fixed token set — the part that is native-per-platform. (Later this\n * is sourced from shared design tokens; for v0 it's a sensible inline set.)\n */\nimport type { CSSProperties } from \"react\";\n\nexport const spacing: Record<string, string> = {\n xs: \"4px\",\n sm: \"12px\",\n md: \"16px\",\n lg: \"24px\",\n xl: \"32px\",\n};\n\nexport const colors: Record<string, string> = {\n \"text-primary\": \"#111827\",\n \"text-secondary\": \"#4b5563\",\n muted: \"#6b7280\",\n surface: \"#ffffff\",\n};\n\nexport const fonts: Record<string, CSSProperties> = {\n \"headline-sm\": { fontSize: \"1.25rem\", lineHeight: 1.3 },\n title: { fontSize: \"1.125rem\", lineHeight: 1.3 },\n \"body-md\": { fontSize: \"1rem\", lineHeight: 1.6 },\n body: { fontSize: \"1rem\", lineHeight: 1.6 },\n};\n\nexport const shadows: Record<string, string> = {\n lg: \"0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)\",\n};\n\nexport const radii: Record<string, string> = { sm: \"4px\", md: \"8px\", lg: \"12px\" };\nexport const borders: Record<string, string> = { subtle: \"1px solid #e5e7eb\" };\n\n/** Brand button (matches the SAB-red primary). */\nexport function buttonStyle(variant = \"primary\"): CSSProperties {\n const base: CSSProperties = {\n border: \"none\",\n cursor: \"pointer\",\n fontWeight: 600,\n padding: \"12px 24px\",\n borderRadius: radii.sm,\n };\n if (variant === \"primary\") return { ...base, background: \"#d81e2c\", color: \"#ffffff\" };\n if (variant === \"outline\") return { ...base, background: \"transparent\", border: \"2px solid #d81e2c\", color: \"#d81e2c\" };\n return base;\n}\n","/**\n * The generic tree renderer: UnoverseNode → React. No per-component code.\n */\nimport type { CSSProperties, ReactNode } from \"react\";\nimport type { UnoverseNode } from \"@gravity-platform/unoverse-core\";\nimport { spacing, colors, fonts, shadows, radii, borders, buttonStyle } from \"./tokens\";\n\nexport type ActionHandler = (action: string, data: Record<string, unknown>) => void;\n\n/** Map the neutral style vocab → CSS. Unknown keys pass through as-is. */\nfunction styleToCss(s: Record<string, unknown> = {}): CSSProperties {\n const css: CSSProperties = {};\n const dim = (v: unknown) => (v === \"full\" ? \"100%\" : (v as CSSProperties[\"width\"]));\n\n if (s.width != null) css.width = dim(s.width);\n if (s.height != null) css.height = dim(s.height);\n if (s.direction) {\n css.display = \"flex\";\n css.flexDirection = s.direction as CSSProperties[\"flexDirection\"];\n }\n if (s.gap) css.gap = spacing[s.gap as string] ?? (s.gap as string);\n if (s.padding) css.padding = spacing[s.padding as string] ?? (s.padding as string);\n if (s.align) css.alignItems = s.align === \"start\" ? \"flex-start\" : (s.align as CSSProperties[\"alignItems\"]);\n if (s.justify) css.justifyContent = s.justify as CSSProperties[\"justifyContent\"];\n if (s.background) css.background = colors[s.background as string] ?? (s.background as string);\n if (s.border) css.border = borders[s.border as string] ?? (s.border as string);\n if (s.shadow) css.boxShadow = shadows[s.shadow as string] ?? (s.shadow as string);\n if (s.radius) css.borderRadius = radii[s.radius as string] ?? (s.radius as string);\n if (s.overflow) css.overflow = s.overflow as CSSProperties[\"overflow\"];\n if (s.fit) css.objectFit = s.fit as CSSProperties[\"objectFit\"];\n if (s.font && fonts[s.font as string]) Object.assign(css, fonts[s.font as string]);\n if (s.weight === \"semibold\") css.fontWeight = 600;\n if (s.color) css.color = colors[s.color as string] ?? (s.color as string);\n return css;\n}\n\nfunction bound(field: string | undefined, data: Record<string, unknown>): string | undefined {\n return field ? (data[field] as string | undefined) : undefined;\n}\n\nexport function renderNode(\n node: UnoverseNode,\n data: Record<string, unknown>,\n onAction?: ActionHandler,\n key?: React.Key,\n): ReactNode {\n // visibleWhen — conditional visibility (the interaction vocab)\n if (node.visibleWhen) {\n const v = data[node.visibleWhen];\n if (v == null || v === \"\" || v === false) return null;\n }\n\n const style = styleToCss(node.style);\n const kids = (node.children ?? []).map((c, i) => renderNode(c, data, onAction, i));\n\n switch (node.type) {\n case \"Box\":\n case \"Stack\":\n case \"Row\":\n case \"Column\":\n return (\n <div key={key} style={style}>\n {kids}\n </div>\n );\n case \"Text\":\n return (\n <span key={key} style={style}>\n {bound(node.bind?.value, data)}\n </span>\n );\n case \"Image\":\n return <img key={key} style={style} src={bound(node.bind?.src, data)} alt={bound(node.bind?.alt, data) ?? \"\"} />;\n case \"Button\":\n return (\n <button\n key={key}\n style={{ ...buttonStyle(node.style?.variant as string), ...style }}\n onClick={() => onAction?.(node.action ?? \"click\", data)}\n >\n {bound(node.bind?.label, data)}\n </button>\n );\n default:\n // Unknown primitive — render children so the tree doesn't break.\n return (\n <div key={key} style={style} data-unoverse-unknown={node.type}>\n {kids}\n </div>\n );\n }\n}\n","/**\n * Streaming binding: subscribe to the merge-state store and render the\n * component instance, re-rendering when COMPONENT_INIT/COMPONENT_DATA merge in.\n */\nimport { useCallback, useSyncExternalStore } from \"react\";\nimport type { ComponentStore, UnoverseClient } from \"@gravity-platform/unoverse-core\";\nimport { UnoverseComponent } from \"./UnoverseComponent\";\nimport type { ActionHandler } from \"./render\";\n\n/** Subscribe to a component instance in the store (re-renders on merge). */\nexport function useUnoverseInstance(store: ComponentStore, chatId: string, nodeId: string) {\n const subscribe = useCallback((cb: () => void) => store.subscribe(cb), [store]);\n const getVersion = useCallback(() => store.getVersion(), [store]);\n useSyncExternalStore(subscribe, getVersion);\n return { type: store.getType(chatId, nodeId), data: store.get(chatId, nodeId) };\n}\n\nexport interface StreamedUnoverseComponentProps {\n client: UnoverseClient;\n store: ComponentStore;\n chatId: string;\n nodeId: string;\n onAction?: ActionHandler;\n}\n\n/** Resolves `type` from the store → its definition → renders with merged data. */\nexport function StreamedUnoverseComponent({ client, store, chatId, nodeId, onAction }: StreamedUnoverseComponentProps) {\n const { type, data } = useUnoverseInstance(store, chatId, nodeId);\n if (!type) return <div style={{ color: \"#9ca3af\", fontSize: 13 }}>waiting for COMPONENT_INIT…</div>;\n return <UnoverseComponent client={client} uri={`unoverse://components/${type}`} data={data} onAction={onAction} />;\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_react","import_jsx_runtime"]}
@@ -0,0 +1,37 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { UnoverseNode, UnoverseClient, ComponentStore } from '@gravity-platform/unoverse-core';
4
+
5
+ /**
6
+ * The generic tree renderer: UnoverseNode → React. No per-component code.
7
+ */
8
+
9
+ type ActionHandler = (action: string, data: Record<string, unknown>) => void;
10
+ declare function renderNode(node: UnoverseNode, data: Record<string, unknown>, onAction?: ActionHandler, key?: React.Key): ReactNode;
11
+
12
+ interface UnoverseComponentProps {
13
+ client: UnoverseClient;
14
+ /** e.g. "unoverse://components/Card" */
15
+ uri: string;
16
+ /** instance data bound into the definition (the streamed props) */
17
+ data?: Record<string, unknown>;
18
+ onAction?: ActionHandler;
19
+ }
20
+ declare function UnoverseComponent({ client, uri, data, onAction }: UnoverseComponentProps): react.JSX.Element;
21
+
22
+ /** Subscribe to a component instance in the store (re-renders on merge). */
23
+ declare function useUnoverseInstance(store: ComponentStore, chatId: string, nodeId: string): {
24
+ type: string | undefined;
25
+ data: Record<string, unknown>;
26
+ };
27
+ interface StreamedUnoverseComponentProps {
28
+ client: UnoverseClient;
29
+ store: ComponentStore;
30
+ chatId: string;
31
+ nodeId: string;
32
+ onAction?: ActionHandler;
33
+ }
34
+ /** Resolves `type` from the store → its definition → renders with merged data. */
35
+ declare function StreamedUnoverseComponent({ client, store, chatId, nodeId, onAction }: StreamedUnoverseComponentProps): react.JSX.Element;
36
+
37
+ export { type ActionHandler, StreamedUnoverseComponent, type StreamedUnoverseComponentProps, UnoverseComponent, type UnoverseComponentProps, renderNode, useUnoverseInstance };
@@ -0,0 +1,37 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { UnoverseNode, UnoverseClient, ComponentStore } from '@gravity-platform/unoverse-core';
4
+
5
+ /**
6
+ * The generic tree renderer: UnoverseNode → React. No per-component code.
7
+ */
8
+
9
+ type ActionHandler = (action: string, data: Record<string, unknown>) => void;
10
+ declare function renderNode(node: UnoverseNode, data: Record<string, unknown>, onAction?: ActionHandler, key?: React.Key): ReactNode;
11
+
12
+ interface UnoverseComponentProps {
13
+ client: UnoverseClient;
14
+ /** e.g. "unoverse://components/Card" */
15
+ uri: string;
16
+ /** instance data bound into the definition (the streamed props) */
17
+ data?: Record<string, unknown>;
18
+ onAction?: ActionHandler;
19
+ }
20
+ declare function UnoverseComponent({ client, uri, data, onAction }: UnoverseComponentProps): react.JSX.Element;
21
+
22
+ /** Subscribe to a component instance in the store (re-renders on merge). */
23
+ declare function useUnoverseInstance(store: ComponentStore, chatId: string, nodeId: string): {
24
+ type: string | undefined;
25
+ data: Record<string, unknown>;
26
+ };
27
+ interface StreamedUnoverseComponentProps {
28
+ client: UnoverseClient;
29
+ store: ComponentStore;
30
+ chatId: string;
31
+ nodeId: string;
32
+ onAction?: ActionHandler;
33
+ }
34
+ /** Resolves `type` from the store → its definition → renders with merged data. */
35
+ declare function StreamedUnoverseComponent({ client, store, chatId, nodeId, onAction }: StreamedUnoverseComponentProps): react.JSX.Element;
36
+
37
+ export { type ActionHandler, StreamedUnoverseComponent, type StreamedUnoverseComponentProps, UnoverseComponent, type UnoverseComponentProps, renderNode, useUnoverseInstance };
package/dist/index.js ADDED
@@ -0,0 +1,149 @@
1
+ // src/UnoverseComponent.tsx
2
+ import { useEffect, useState } from "react";
3
+
4
+ // src/tokens.ts
5
+ var spacing = {
6
+ xs: "4px",
7
+ sm: "12px",
8
+ md: "16px",
9
+ lg: "24px",
10
+ xl: "32px"
11
+ };
12
+ var colors = {
13
+ "text-primary": "#111827",
14
+ "text-secondary": "#4b5563",
15
+ muted: "#6b7280",
16
+ surface: "#ffffff"
17
+ };
18
+ var fonts = {
19
+ "headline-sm": { fontSize: "1.25rem", lineHeight: 1.3 },
20
+ title: { fontSize: "1.125rem", lineHeight: 1.3 },
21
+ "body-md": { fontSize: "1rem", lineHeight: 1.6 },
22
+ body: { fontSize: "1rem", lineHeight: 1.6 }
23
+ };
24
+ var shadows = {
25
+ lg: "0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)"
26
+ };
27
+ var radii = { sm: "4px", md: "8px", lg: "12px" };
28
+ var borders = { subtle: "1px solid #e5e7eb" };
29
+ function buttonStyle(variant = "primary") {
30
+ const base = {
31
+ border: "none",
32
+ cursor: "pointer",
33
+ fontWeight: 600,
34
+ padding: "12px 24px",
35
+ borderRadius: radii.sm
36
+ };
37
+ if (variant === "primary") return { ...base, background: "#d81e2c", color: "#ffffff" };
38
+ if (variant === "outline") return { ...base, background: "transparent", border: "2px solid #d81e2c", color: "#d81e2c" };
39
+ return base;
40
+ }
41
+
42
+ // src/render.tsx
43
+ import { jsx } from "react/jsx-runtime";
44
+ function styleToCss(s = {}) {
45
+ const css = {};
46
+ const dim = (v) => v === "full" ? "100%" : v;
47
+ if (s.width != null) css.width = dim(s.width);
48
+ if (s.height != null) css.height = dim(s.height);
49
+ if (s.direction) {
50
+ css.display = "flex";
51
+ css.flexDirection = s.direction;
52
+ }
53
+ if (s.gap) css.gap = spacing[s.gap] ?? s.gap;
54
+ if (s.padding) css.padding = spacing[s.padding] ?? s.padding;
55
+ if (s.align) css.alignItems = s.align === "start" ? "flex-start" : s.align;
56
+ if (s.justify) css.justifyContent = s.justify;
57
+ if (s.background) css.background = colors[s.background] ?? s.background;
58
+ if (s.border) css.border = borders[s.border] ?? s.border;
59
+ if (s.shadow) css.boxShadow = shadows[s.shadow] ?? s.shadow;
60
+ if (s.radius) css.borderRadius = radii[s.radius] ?? s.radius;
61
+ if (s.overflow) css.overflow = s.overflow;
62
+ if (s.fit) css.objectFit = s.fit;
63
+ if (s.font && fonts[s.font]) Object.assign(css, fonts[s.font]);
64
+ if (s.weight === "semibold") css.fontWeight = 600;
65
+ if (s.color) css.color = colors[s.color] ?? s.color;
66
+ return css;
67
+ }
68
+ function bound(field, data) {
69
+ return field ? data[field] : void 0;
70
+ }
71
+ function renderNode(node, data, onAction, key) {
72
+ if (node.visibleWhen) {
73
+ const v = data[node.visibleWhen];
74
+ if (v == null || v === "" || v === false) return null;
75
+ }
76
+ const style = styleToCss(node.style);
77
+ const kids = (node.children ?? []).map((c, i) => renderNode(c, data, onAction, i));
78
+ switch (node.type) {
79
+ case "Box":
80
+ case "Stack":
81
+ case "Row":
82
+ case "Column":
83
+ return /* @__PURE__ */ jsx("div", { style, children: kids }, key);
84
+ case "Text":
85
+ return /* @__PURE__ */ jsx("span", { style, children: bound(node.bind?.value, data) }, key);
86
+ case "Image":
87
+ return /* @__PURE__ */ jsx("img", { style, src: bound(node.bind?.src, data), alt: bound(node.bind?.alt, data) ?? "" }, key);
88
+ case "Button":
89
+ return /* @__PURE__ */ jsx(
90
+ "button",
91
+ {
92
+ style: { ...buttonStyle(node.style?.variant), ...style },
93
+ onClick: () => onAction?.(node.action ?? "click", data),
94
+ children: bound(node.bind?.label, data)
95
+ },
96
+ key
97
+ );
98
+ default:
99
+ return /* @__PURE__ */ jsx("div", { style, "data-unoverse-unknown": node.type, children: kids }, key);
100
+ }
101
+ }
102
+
103
+ // src/UnoverseComponent.tsx
104
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
105
+ function UnoverseComponent({ client, uri, data, onAction }) {
106
+ const [def, setDef] = useState(null);
107
+ const [error, setError] = useState(null);
108
+ useEffect(() => {
109
+ let alive = true;
110
+ setDef(null);
111
+ setError(null);
112
+ client.readDefinition(uri).then((d) => alive && setDef(d)).catch((e) => alive && setError(String(e?.message ?? e)));
113
+ return () => {
114
+ alive = false;
115
+ };
116
+ }, [client, uri]);
117
+ if (error) return /* @__PURE__ */ jsxs("div", { style: { color: "#d81e2c", fontSize: 13 }, children: [
118
+ "Unoverse error: ",
119
+ error
120
+ ] });
121
+ if (!def) return /* @__PURE__ */ jsxs("div", { style: { color: "#9ca3af", fontSize: 13 }, children: [
122
+ "Loading ",
123
+ uri,
124
+ "\u2026"
125
+ ] });
126
+ return /* @__PURE__ */ jsx2(Fragment, { children: renderNode(def.root, data ?? {}, onAction) });
127
+ }
128
+
129
+ // src/streamed.tsx
130
+ import { useCallback, useSyncExternalStore } from "react";
131
+ import { jsx as jsx3 } from "react/jsx-runtime";
132
+ function useUnoverseInstance(store, chatId, nodeId) {
133
+ const subscribe = useCallback((cb) => store.subscribe(cb), [store]);
134
+ const getVersion = useCallback(() => store.getVersion(), [store]);
135
+ useSyncExternalStore(subscribe, getVersion);
136
+ return { type: store.getType(chatId, nodeId), data: store.get(chatId, nodeId) };
137
+ }
138
+ function StreamedUnoverseComponent({ client, store, chatId, nodeId, onAction }) {
139
+ const { type, data } = useUnoverseInstance(store, chatId, nodeId);
140
+ if (!type) return /* @__PURE__ */ jsx3("div", { style: { color: "#9ca3af", fontSize: 13 }, children: "waiting for COMPONENT_INIT\u2026" });
141
+ return /* @__PURE__ */ jsx3(UnoverseComponent, { client, uri: `unoverse://components/${type}`, data, onAction });
142
+ }
143
+ export {
144
+ StreamedUnoverseComponent,
145
+ UnoverseComponent,
146
+ renderNode,
147
+ useUnoverseInstance
148
+ };
149
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/UnoverseComponent.tsx","../src/tokens.ts","../src/render.tsx","../src/streamed.tsx"],"sourcesContent":["/**\n * <UnoverseComponent> — reads a definition by URI from the Unoverse MCP server\n * (via @gravity-platform/unoverse-core) and renders it natively with the given data.\n */\nimport { useEffect, useState } from \"react\";\nimport type { UnoverseClient, UnoverseDefinition } from \"@gravity-platform/unoverse-core\";\nimport { renderNode, type ActionHandler } from \"./render\";\n\nexport interface UnoverseComponentProps {\n client: UnoverseClient;\n /** e.g. \"unoverse://components/Card\" */\n uri: string;\n /** instance data bound into the definition (the streamed props) */\n data?: Record<string, unknown>;\n onAction?: ActionHandler;\n}\n\nexport function UnoverseComponent({ client, uri, data, onAction }: UnoverseComponentProps) {\n const [def, setDef] = useState<UnoverseDefinition | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let alive = true;\n setDef(null);\n setError(null);\n client\n .readDefinition(uri)\n .then((d) => alive && setDef(d))\n .catch((e) => alive && setError(String(e?.message ?? e)));\n return () => {\n alive = false;\n };\n }, [client, uri]);\n\n if (error) return <div style={{ color: \"#d81e2c\", fontSize: 13 }}>Unoverse error: {error}</div>;\n if (!def) return <div style={{ color: \"#9ca3af\", fontSize: 13 }}>Loading {uri}…</div>;\n return <>{renderNode(def.root, data ?? {}, onAction)}</>;\n}\n","/**\n * Unoverse style vocabulary → CSS values (web renderer).\n *\n * A small, fixed token set — the part that is native-per-platform. (Later this\n * is sourced from shared design tokens; for v0 it's a sensible inline set.)\n */\nimport type { CSSProperties } from \"react\";\n\nexport const spacing: Record<string, string> = {\n xs: \"4px\",\n sm: \"12px\",\n md: \"16px\",\n lg: \"24px\",\n xl: \"32px\",\n};\n\nexport const colors: Record<string, string> = {\n \"text-primary\": \"#111827\",\n \"text-secondary\": \"#4b5563\",\n muted: \"#6b7280\",\n surface: \"#ffffff\",\n};\n\nexport const fonts: Record<string, CSSProperties> = {\n \"headline-sm\": { fontSize: \"1.25rem\", lineHeight: 1.3 },\n title: { fontSize: \"1.125rem\", lineHeight: 1.3 },\n \"body-md\": { fontSize: \"1rem\", lineHeight: 1.6 },\n body: { fontSize: \"1rem\", lineHeight: 1.6 },\n};\n\nexport const shadows: Record<string, string> = {\n lg: \"0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)\",\n};\n\nexport const radii: Record<string, string> = { sm: \"4px\", md: \"8px\", lg: \"12px\" };\nexport const borders: Record<string, string> = { subtle: \"1px solid #e5e7eb\" };\n\n/** Brand button (matches the SAB-red primary). */\nexport function buttonStyle(variant = \"primary\"): CSSProperties {\n const base: CSSProperties = {\n border: \"none\",\n cursor: \"pointer\",\n fontWeight: 600,\n padding: \"12px 24px\",\n borderRadius: radii.sm,\n };\n if (variant === \"primary\") return { ...base, background: \"#d81e2c\", color: \"#ffffff\" };\n if (variant === \"outline\") return { ...base, background: \"transparent\", border: \"2px solid #d81e2c\", color: \"#d81e2c\" };\n return base;\n}\n","/**\n * The generic tree renderer: UnoverseNode → React. No per-component code.\n */\nimport type { CSSProperties, ReactNode } from \"react\";\nimport type { UnoverseNode } from \"@gravity-platform/unoverse-core\";\nimport { spacing, colors, fonts, shadows, radii, borders, buttonStyle } from \"./tokens\";\n\nexport type ActionHandler = (action: string, data: Record<string, unknown>) => void;\n\n/** Map the neutral style vocab → CSS. Unknown keys pass through as-is. */\nfunction styleToCss(s: Record<string, unknown> = {}): CSSProperties {\n const css: CSSProperties = {};\n const dim = (v: unknown) => (v === \"full\" ? \"100%\" : (v as CSSProperties[\"width\"]));\n\n if (s.width != null) css.width = dim(s.width);\n if (s.height != null) css.height = dim(s.height);\n if (s.direction) {\n css.display = \"flex\";\n css.flexDirection = s.direction as CSSProperties[\"flexDirection\"];\n }\n if (s.gap) css.gap = spacing[s.gap as string] ?? (s.gap as string);\n if (s.padding) css.padding = spacing[s.padding as string] ?? (s.padding as string);\n if (s.align) css.alignItems = s.align === \"start\" ? \"flex-start\" : (s.align as CSSProperties[\"alignItems\"]);\n if (s.justify) css.justifyContent = s.justify as CSSProperties[\"justifyContent\"];\n if (s.background) css.background = colors[s.background as string] ?? (s.background as string);\n if (s.border) css.border = borders[s.border as string] ?? (s.border as string);\n if (s.shadow) css.boxShadow = shadows[s.shadow as string] ?? (s.shadow as string);\n if (s.radius) css.borderRadius = radii[s.radius as string] ?? (s.radius as string);\n if (s.overflow) css.overflow = s.overflow as CSSProperties[\"overflow\"];\n if (s.fit) css.objectFit = s.fit as CSSProperties[\"objectFit\"];\n if (s.font && fonts[s.font as string]) Object.assign(css, fonts[s.font as string]);\n if (s.weight === \"semibold\") css.fontWeight = 600;\n if (s.color) css.color = colors[s.color as string] ?? (s.color as string);\n return css;\n}\n\nfunction bound(field: string | undefined, data: Record<string, unknown>): string | undefined {\n return field ? (data[field] as string | undefined) : undefined;\n}\n\nexport function renderNode(\n node: UnoverseNode,\n data: Record<string, unknown>,\n onAction?: ActionHandler,\n key?: React.Key,\n): ReactNode {\n // visibleWhen — conditional visibility (the interaction vocab)\n if (node.visibleWhen) {\n const v = data[node.visibleWhen];\n if (v == null || v === \"\" || v === false) return null;\n }\n\n const style = styleToCss(node.style);\n const kids = (node.children ?? []).map((c, i) => renderNode(c, data, onAction, i));\n\n switch (node.type) {\n case \"Box\":\n case \"Stack\":\n case \"Row\":\n case \"Column\":\n return (\n <div key={key} style={style}>\n {kids}\n </div>\n );\n case \"Text\":\n return (\n <span key={key} style={style}>\n {bound(node.bind?.value, data)}\n </span>\n );\n case \"Image\":\n return <img key={key} style={style} src={bound(node.bind?.src, data)} alt={bound(node.bind?.alt, data) ?? \"\"} />;\n case \"Button\":\n return (\n <button\n key={key}\n style={{ ...buttonStyle(node.style?.variant as string), ...style }}\n onClick={() => onAction?.(node.action ?? \"click\", data)}\n >\n {bound(node.bind?.label, data)}\n </button>\n );\n default:\n // Unknown primitive — render children so the tree doesn't break.\n return (\n <div key={key} style={style} data-unoverse-unknown={node.type}>\n {kids}\n </div>\n );\n }\n}\n","/**\n * Streaming binding: subscribe to the merge-state store and render the\n * component instance, re-rendering when COMPONENT_INIT/COMPONENT_DATA merge in.\n */\nimport { useCallback, useSyncExternalStore } from \"react\";\nimport type { ComponentStore, UnoverseClient } from \"@gravity-platform/unoverse-core\";\nimport { UnoverseComponent } from \"./UnoverseComponent\";\nimport type { ActionHandler } from \"./render\";\n\n/** Subscribe to a component instance in the store (re-renders on merge). */\nexport function useUnoverseInstance(store: ComponentStore, chatId: string, nodeId: string) {\n const subscribe = useCallback((cb: () => void) => store.subscribe(cb), [store]);\n const getVersion = useCallback(() => store.getVersion(), [store]);\n useSyncExternalStore(subscribe, getVersion);\n return { type: store.getType(chatId, nodeId), data: store.get(chatId, nodeId) };\n}\n\nexport interface StreamedUnoverseComponentProps {\n client: UnoverseClient;\n store: ComponentStore;\n chatId: string;\n nodeId: string;\n onAction?: ActionHandler;\n}\n\n/** Resolves `type` from the store → its definition → renders with merged data. */\nexport function StreamedUnoverseComponent({ client, store, chatId, nodeId, onAction }: StreamedUnoverseComponentProps) {\n const { type, data } = useUnoverseInstance(store, chatId, nodeId);\n if (!type) return <div style={{ color: \"#9ca3af\", fontSize: 13 }}>waiting for COMPONENT_INIT…</div>;\n return <UnoverseComponent client={client} uri={`unoverse://components/${type}`} data={data} onAction={onAction} />;\n}\n"],"mappings":"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","names":["jsx","jsx"]}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@gravity-platform/unoverse-react",
3
+ "version": "0.0.1",
4
+ "description": "Unoverse React renderer — neutral definition → React/DOM (web channel SDK)",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "dist/index.cjs",
8
+ "module": "dist/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": ["dist"],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch"
21
+ },
22
+ "dependencies": {
23
+ "@gravity-platform/unoverse-core": "^0.0.1"
24
+ },
25
+ "peerDependencies": {
26
+ "react": ">=18"
27
+ },
28
+ "devDependencies": {
29
+ "@types/react": "^18.2.0",
30
+ "react": "^18.2.0",
31
+ "tsup": "^8.0.0",
32
+ "typescript": "^5.2.0"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ }
37
+ }