@bitbitpress/client 1.1.0 → 1.1.2
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/README.md +110 -19
- package/dist/data/assets.d.ts +11 -3
- package/dist/data/assets.d.ts.map +1 -1
- package/dist/data/assets.js +2 -2
- package/dist/data/assets.js.map +1 -1
- package/dist/data/index.d.ts +2 -2
- package/dist/generated/openapi.d.ts +503 -24
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/react/index.d.ts +29 -54
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +69 -81
- package/dist/react/index.js.map +1 -1
- package/dist/react-native-expo/index.d.ts +1 -52
- package/dist/react-native-expo/index.d.ts.map +1 -1
- package/dist/react-native-expo/index.js +1 -91
- package/dist/react-native-expo/index.js.map +1 -1
- package/dist/runtime/index.d.ts +60 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +84 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/synthesisUi/context.d.ts +18 -0
- package/dist/synthesisUi/context.d.ts.map +1 -0
- package/dist/synthesisUi/context.js +15 -0
- package/dist/synthesisUi/context.js.map +1 -0
- package/dist/synthesisUi/types.d.ts +30 -0
- package/dist/synthesisUi/types.d.ts.map +1 -0
- package/dist/{synthesisView → synthesisUi}/types.js.map +1 -1
- package/dist/user/index.d.ts +61 -13
- package/dist/user/index.d.ts.map +1 -1
- package/dist/user/index.js +12 -6
- package/dist/user/index.js.map +1 -1
- package/dist/user/interaction.d.ts +5 -0
- package/dist/user/interaction.d.ts.map +1 -1
- package/dist/user/interaction.js +5 -0
- package/dist/user/interaction.js.map +1 -1
- package/dist/user/submissions.d.ts +65 -0
- package/dist/user/submissions.d.ts.map +1 -1
- package/dist/user/submissions.js +57 -0
- package/dist/user/submissions.js.map +1 -1
- package/dist/user/synthesize-batch-manager.js +2 -0
- package/dist/user/synthesize-batch-manager.js.map +1 -1
- package/dist/user/synthesize.d.ts +29 -6
- package/dist/user/synthesize.d.ts.map +1 -1
- package/dist/user/synthesize.js +12 -3
- package/dist/user/synthesize.js.map +1 -1
- package/dist/user/synthesizeUi.d.ts +67 -0
- package/dist/user/synthesizeUi.d.ts.map +1 -0
- package/dist/user/synthesizeUi.js +51 -0
- package/dist/user/synthesizeUi.js.map +1 -0
- package/dist/user/track-batch-manager.d.ts +17 -0
- package/dist/user/track-batch-manager.d.ts.map +1 -0
- package/dist/user/track-batch-manager.js +52 -0
- package/dist/user/track-batch-manager.js.map +1 -0
- package/dist/user/track.d.ts +17 -0
- package/dist/user/track.d.ts.map +1 -0
- package/dist/user/track.js +24 -0
- package/dist/user/track.js.map +1 -0
- package/dist/user/typeDefs.d.ts +9 -3
- package/dist/user/typeDefs.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/react/primitives.d.ts +0 -54
- package/dist/react/primitives.d.ts.map +0 -1
- package/dist/react/primitives.js +0 -223
- package/dist/react/primitives.js.map +0 -1
- package/dist/react-native-expo/primitives.d.ts +0 -58
- package/dist/react-native-expo/primitives.d.ts.map +0 -1
- package/dist/react-native-expo/primitives.js +0 -218
- package/dist/react-native-expo/primitives.js.map +0 -1
- package/dist/synthesisView/context.d.ts +0 -18
- package/dist/synthesisView/context.d.ts.map +0 -1
- package/dist/synthesisView/context.js +0 -15
- package/dist/synthesisView/context.js.map +0 -1
- package/dist/synthesisView/createComponentMap.d.ts +0 -18
- package/dist/synthesisView/createComponentMap.d.ts.map +0 -1
- package/dist/synthesisView/createComponentMap.js +0 -40
- package/dist/synthesisView/createComponentMap.js.map +0 -1
- package/dist/synthesisView/devLog.d.ts +0 -10
- package/dist/synthesisView/devLog.d.ts.map +0 -1
- package/dist/synthesisView/devLog.js +0 -23
- package/dist/synthesisView/devLog.js.map +0 -1
- package/dist/synthesisView/engine.d.ts +0 -35
- package/dist/synthesisView/engine.d.ts.map +0 -1
- package/dist/synthesisView/engine.js +0 -139
- package/dist/synthesisView/engine.js.map +0 -1
- package/dist/synthesisView/primitives.d.ts +0 -180
- package/dist/synthesisView/primitives.d.ts.map +0 -1
- package/dist/synthesisView/primitives.js +0 -29
- package/dist/synthesisView/primitives.js.map +0 -1
- package/dist/synthesisView/resolve.d.ts +0 -17
- package/dist/synthesisView/resolve.d.ts.map +0 -1
- package/dist/synthesisView/resolve.js +0 -42
- package/dist/synthesisView/resolve.js.map +0 -1
- package/dist/synthesisView/types.d.ts +0 -121
- package/dist/synthesisView/types.d.ts.map +0 -1
- package/dist/synthesisView/useEventDrivenView.d.ts +0 -32
- package/dist/synthesisView/useEventDrivenView.d.ts.map +0 -1
- package/dist/synthesisView/useEventDrivenView.js +0 -157
- package/dist/synthesisView/useEventDrivenView.js.map +0 -1
- package/dist/synthesisView/useSynthesisView.d.ts +0 -13
- package/dist/synthesisView/useSynthesisView.d.ts.map +0 -1
- package/dist/synthesisView/useSynthesisView.js +0 -49
- package/dist/synthesisView/useSynthesisView.js.map +0 -1
- package/dist/user/synthesize-view-batch-manager.d.ts +0 -17
- package/dist/user/synthesize-view-batch-manager.d.ts.map +0 -1
- package/dist/user/synthesize-view-batch-manager.js +0 -52
- package/dist/user/synthesize-view-batch-manager.js.map +0 -1
- package/dist/user/synthesizeView.d.ts +0 -41
- package/dist/user/synthesizeView.d.ts.map +0 -1
- package/dist/user/synthesizeView.js +0 -26
- package/dist/user/synthesizeView.js.map +0 -1
- /package/dist/{synthesisView → synthesisUi}/types.js +0 -0
package/dist/react/index.d.ts
CHANGED
|
@@ -1,60 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export { type BitBitContextValue, BitBitProvider } from '../
|
|
4
|
-
export {
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** Override how unregistered components render. Defaults to a dev-only
|
|
10
|
-
* marker (see {@link isDevEnvironment}). */
|
|
11
|
-
renderUnknown?: RenderUnknown;
|
|
12
|
-
/** Force the in-dev warning behavior regardless of `process.env.NODE_ENV`.
|
|
13
|
-
* Set true in CMS / preview hosts (e.g. BitBitPress's own admin UI) so
|
|
14
|
-
* unknown components stay visible even when those hosts are built in
|
|
15
|
-
* production mode. Defaults to env-derived. */
|
|
16
|
-
dev?: boolean;
|
|
17
|
-
};
|
|
18
|
-
/** Web renderer for a pre-fetched `uiData` array. BB built-in primitives are
|
|
19
|
-
* registered automatically; pass `components` to add or override entries by
|
|
20
|
-
* name. Use `<BitBitView>` if you want it to fetch for you. */
|
|
21
|
-
export declare function BitBitViewRenderer({ renderUnknown, dev, onEvent, ...rest }: BitBitViewRendererProps): import("react").FunctionComponentElement<SynthesisViewTreeProps>;
|
|
22
|
-
export type BitBitViewProps = {
|
|
23
|
-
/** A BitBitPressClient (or anything with `user.synthesizeViewItem`). */
|
|
24
|
-
client: SynthesizeViewFetcher;
|
|
1
|
+
import type { SynthesisUiPlatform, SynthesisUiStreamEvent, SynthesizeUiFetcher } from '../synthesisUi/types.js';
|
|
2
|
+
export type { BitBitViewContext, GeneratedUiModule, GeneratedUiViewHandle, } from '../runtime/index.js';
|
|
3
|
+
export { type BitBitContextValue, BitBitProvider } from '../synthesisUi/context.js';
|
|
4
|
+
export type { SynthesisUiPlatform, SynthesisUiStreamEvent, SynthesizeUiFetcher };
|
|
5
|
+
export interface BitBitSynthesisProps {
|
|
6
|
+
/** Client to fetch the UI through. Optional when a `<BitBitProvider client>`
|
|
7
|
+
* is in scope. */
|
|
8
|
+
client?: SynthesizeUiFetcher;
|
|
25
9
|
keyName: string;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
onEvent?: (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
dev?: boolean;
|
|
37
|
-
/** Force a dark/light mode. Defaults to the browser's
|
|
38
|
-
* `prefers-color-scheme` (live-updates if the user toggles their OS
|
|
39
|
-
* theme). */
|
|
40
|
-
darkMode?: boolean;
|
|
41
|
-
/** When true (default), speculatively prefetches the agent's next-UI for
|
|
42
|
-
* AGENT events whose payloads don't need runtime input. Real clicks land
|
|
43
|
-
* on the cached response with zero server roundtrip. Set false to
|
|
44
|
-
* disable. */
|
|
45
|
-
preloadNextUi?: boolean;
|
|
46
|
-
};
|
|
10
|
+
/** Target platform. Defaults to `web`; the studio passes `mobile` to
|
|
11
|
+
* preview the react-native-web bundle. */
|
|
12
|
+
platform?: SynthesisUiPlatform;
|
|
13
|
+
/** Brand analytics / link tracking. */
|
|
14
|
+
onTrack?: (event: string, payload?: unknown) => void;
|
|
15
|
+
/** Host slot callbacks (developer-supplied event handlers). */
|
|
16
|
+
onEvent?: (name: string, payload?: unknown) => void;
|
|
17
|
+
/** Navigate a link the view requested. */
|
|
18
|
+
onNavigate?: (href: string) => void;
|
|
19
|
+
}
|
|
47
20
|
/**
|
|
48
|
-
* Web view
|
|
49
|
-
*
|
|
50
|
-
* (
|
|
21
|
+
* Web view for a server-generated SynthesisUI. Streams the UI by `keyName`
|
|
22
|
+
* through `client` (or the `<BitBitProvider client>` in scope): loads and
|
|
23
|
+
* mounts the built bundle (which owns its React) on the `manifest`, then pushes
|
|
24
|
+
* `data` into the mounted view as it streams in. Web mounts in a Shadow DOM;
|
|
25
|
+
* the `mobile` preview (react-native-web) mounts in the light DOM so rn-web's
|
|
26
|
+
* global stylesheet applies. Native delivery (React Native via Re.Pack) is a
|
|
27
|
+
* separate entry.
|
|
51
28
|
*/
|
|
52
|
-
export declare function
|
|
53
|
-
|
|
29
|
+
export declare function BitBitSynthesis({ client: clientProp, keyName, platform, onTrack, onEvent, onNavigate, }: BitBitSynthesisProps): import("react").DetailedReactHTMLElement<{
|
|
30
|
+
ref: import("react").RefObject<HTMLDivElement>;
|
|
54
31
|
style: {
|
|
55
|
-
|
|
56
|
-
fontFamily: "monospace";
|
|
57
|
-
fontSize: number;
|
|
32
|
+
height: string;
|
|
58
33
|
};
|
|
59
|
-
},
|
|
34
|
+
}, HTMLDivElement>;
|
|
60
35
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,kBAAkB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACpF,YAAY,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,CAAC;AAEjF,MAAM,WAAW,oBAAoB;IACnC;uBACmB;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB;+CAC2C;IAC3C,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,uCAAuC;IACvC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD,0CAA0C;IAC1C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAID;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EAAE,UAAU,EAClB,OAAO,EACP,QAAgB,EAChB,OAAO,EACP,OAAO,EACP,UAAU,GACX,EAAE,oBAAoB;;;;;mBAkEtB"}
|
package/dist/react/index.js
CHANGED
|
@@ -1,85 +1,73 @@
|
|
|
1
|
-
import { createElement, useEffect,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export { BitBitProvider } from '../synthesisView/context.js';
|
|
7
|
-
export { createComponentMap, } from '../synthesisView/createComponentMap.js';
|
|
8
|
-
export { useEventDrivenView, } from '../synthesisView/useEventDrivenView.js';
|
|
9
|
-
export { bitBitBuiltins } from './primitives.js';
|
|
10
|
-
/** Track the browser's `prefers-color-scheme` and re-render on change. Returns
|
|
11
|
-
* `null` during SSR or when the API isn't available — callers fall back to
|
|
12
|
-
* the server's default. */
|
|
13
|
-
function useSystemDarkMode() {
|
|
14
|
-
const [isDark, setIsDark] = useState(() => {
|
|
15
|
-
if (typeof window === 'undefined' || !window.matchMedia)
|
|
16
|
-
return null;
|
|
17
|
-
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
18
|
-
});
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
if (typeof window === 'undefined' || !window.matchMedia)
|
|
21
|
-
return;
|
|
22
|
-
const mq = window.matchMedia('(prefers-color-scheme: dark)');
|
|
23
|
-
const onChange = (e) => setIsDark(e.matches);
|
|
24
|
-
mq.addEventListener('change', onChange);
|
|
25
|
-
return () => mq.removeEventListener('change', onChange);
|
|
26
|
-
}, []);
|
|
27
|
-
return isDark;
|
|
28
|
-
}
|
|
29
|
-
const renderUnknownWarning = (name) => createElement('span', {
|
|
30
|
-
'data-bitbit-unknown': name,
|
|
31
|
-
style: { color: '#b00020', fontFamily: 'monospace', fontSize: 12 },
|
|
32
|
-
}, `⚠ Unknown component: ${name}`);
|
|
33
|
-
/** Silent in production: an unknown name renders nothing rather than splashing
|
|
34
|
-
* a debug marker in the customer's real app. */
|
|
35
|
-
const renderUnknownSilent = () => null;
|
|
36
|
-
/** Wrap `onEvent` so each emission prints to the console with the dispatch
|
|
37
|
-
* routing inline. Routed through {@link devLog} so the message is auto-
|
|
38
|
-
* prefixed with `[BB]` and stripped to a no-op outside dev. */
|
|
39
|
-
function withDevEventLog(dev, onEvent) {
|
|
40
|
-
return (event) => {
|
|
41
|
-
devLog(dev, `event ${event.componentName}.${event.slot} → ${event.handleWith}`, event);
|
|
42
|
-
onEvent?.(event);
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
/** Web renderer for a pre-fetched `uiData` array. BB built-in primitives are
|
|
46
|
-
* registered automatically; pass `components` to add or override entries by
|
|
47
|
-
* name. Use `<BitBitView>` if you want it to fetch for you. */
|
|
48
|
-
export function BitBitViewRenderer({ renderUnknown, dev, onEvent, ...rest }) {
|
|
49
|
-
const isDev = dev ?? isDevEnvironment();
|
|
50
|
-
return createElement(SynthesisViewTree, {
|
|
51
|
-
...rest,
|
|
52
|
-
defaultComponents: bitBitBuiltins,
|
|
53
|
-
renderUnknown: renderUnknown ?? (isDev ? renderUnknownWarning : renderUnknownSilent),
|
|
54
|
-
onEvent: isDev ? withDevEventLog(dev, onEvent) : onEvent,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
1
|
+
import { createElement, useEffect, useRef } from 'react';
|
|
2
|
+
import { loadGeneratedModule, mountGeneratedView, } from '../runtime/index.js';
|
|
3
|
+
import { useBitBitContext } from '../synthesisUi/context.js';
|
|
4
|
+
export { BitBitProvider } from '../synthesisUi/context.js';
|
|
5
|
+
const noop = () => { };
|
|
57
6
|
/**
|
|
58
|
-
* Web view
|
|
59
|
-
*
|
|
60
|
-
* (
|
|
7
|
+
* Web view for a server-generated SynthesisUI. Streams the UI by `keyName`
|
|
8
|
+
* through `client` (or the `<BitBitProvider client>` in scope): loads and
|
|
9
|
+
* mounts the built bundle (which owns its React) on the `manifest`, then pushes
|
|
10
|
+
* `data` into the mounted view as it streams in. Web mounts in a Shadow DOM;
|
|
11
|
+
* the `mobile` preview (react-native-web) mounts in the light DOM so rn-web's
|
|
12
|
+
* global stylesheet applies. Native delivery (React Native via Re.Pack) is a
|
|
13
|
+
* separate entry.
|
|
61
14
|
*/
|
|
62
|
-
export function
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
15
|
+
export function BitBitSynthesis({ client: clientProp, keyName, platform = 'web', onTrack, onEvent, onNavigate, }) {
|
|
16
|
+
const contextClient = useBitBitContext()?.client;
|
|
17
|
+
const client = clientProp ?? contextClient;
|
|
18
|
+
const hostRef = useRef(null);
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
const host = hostRef.current;
|
|
21
|
+
if (!host || !client)
|
|
22
|
+
return;
|
|
23
|
+
let cancelled = false;
|
|
24
|
+
let handle;
|
|
25
|
+
let mod;
|
|
26
|
+
let theme = {};
|
|
27
|
+
// Auto-beacon when `client` is a full BitBitPressClient (the bare preview
|
|
28
|
+
// fetcher has no `trackItem`, so the studio stays inspector-only). Failures
|
|
29
|
+
// are swallowed — analytics must never break the view.
|
|
30
|
+
const trackItem = client.user.trackItem;
|
|
31
|
+
const beacon = (type, name, payload) => {
|
|
32
|
+
trackItem?.({ keyName, type, ...(name != null && { name }), payload })?.catch?.(() => { });
|
|
33
|
+
};
|
|
34
|
+
const makeCtx = () => ({
|
|
35
|
+
theme,
|
|
36
|
+
track: (event, payload) => {
|
|
37
|
+
onTrack?.(event, payload);
|
|
38
|
+
beacon('CLICK', event, payload);
|
|
39
|
+
},
|
|
40
|
+
onEvent: onEvent ?? noop,
|
|
41
|
+
navigate: onNavigate,
|
|
42
|
+
});
|
|
43
|
+
void (async () => {
|
|
44
|
+
const stream = await client.user.synthesizeUi({ keyName, platform });
|
|
45
|
+
for await (const event of stream) {
|
|
46
|
+
if (cancelled)
|
|
47
|
+
break;
|
|
48
|
+
if (event.type === 'manifest') {
|
|
49
|
+
theme = event.theme;
|
|
50
|
+
const src = event.bundleUrl ?? event.bundleSource;
|
|
51
|
+
if (src)
|
|
52
|
+
mod = await loadGeneratedModule(src);
|
|
53
|
+
}
|
|
54
|
+
else if (event.type === 'data' && mod) {
|
|
55
|
+
// Mount on the first data event (bundle is ready); update thereafter.
|
|
56
|
+
if (handle) {
|
|
57
|
+
handle.update({ data: event.data, ctx: makeCtx() });
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
handle = mountGeneratedView(host, mod, { data: event.data, ctx: makeCtx() }, { isolateStyles: platform !== 'mobile' });
|
|
61
|
+
beacon('VIEW');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})();
|
|
66
|
+
return () => {
|
|
67
|
+
cancelled = true;
|
|
68
|
+
handle?.unmount();
|
|
69
|
+
};
|
|
70
|
+
}, [client, keyName, platform, onTrack, onEvent, onNavigate]);
|
|
71
|
+
return createElement('div', { ref: hostRef, style: { height: '100%' } });
|
|
84
72
|
}
|
|
85
73
|
//# sourceMappingURL=index.js.map
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,53 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import type { ComponentMap, ContentInput, SynthesisViewEvent, SynthesizeViewFetcher } from '../synthesisView/types.js';
|
|
3
|
-
export { type BitBitContextValue, BitBitProvider } from '../synthesisView/context.js';
|
|
4
|
-
export { createComponentMap, type GlobModules, type RequireContext, } from '../synthesisView/createComponentMap.js';
|
|
5
|
-
export type { ComponentMap, ContentInput, FlatUiKeyNameNode, FlatUiNode, FlatUiPrimitiveNode, SynthesisViewEvent, SynthesisViewEventInput, SynthesizeViewFetcher, ViewEventHandleWith, ViewInputs, } from '../synthesisView/types.js';
|
|
6
|
-
export { type UseEventDrivenViewOptions, type UseEventDrivenViewResult, useEventDrivenView, } from '../synthesisView/useEventDrivenView.js';
|
|
7
|
-
export { bitBitBuiltins } from './primitives.js';
|
|
8
|
-
export type BitBitViewRendererProps = Omit<SynthesisViewTreeProps, 'renderUnknown' | 'defaultComponents'> & {
|
|
9
|
-
/**
|
|
10
|
-
* Override how unregistered components render. Defaults are env-derived:
|
|
11
|
-
* a dev-only warning marker when `process.env.NODE_ENV !== 'production'`,
|
|
12
|
-
* silent in production builds. Set `dev` to force the warning behavior.
|
|
13
|
-
*/
|
|
14
|
-
renderUnknown?: RenderUnknown;
|
|
15
|
-
/** Force the in-dev warning behavior regardless of `process.env.NODE_ENV`. */
|
|
16
|
-
dev?: boolean;
|
|
17
|
-
};
|
|
18
|
-
/**
|
|
19
|
-
* React Native (Expo) renderer for a pre-fetched `uiData` array. BB built-in
|
|
20
|
-
* primitives are registered automatically; pass `components` to add or
|
|
21
|
-
* override entries by name. Targets Expo specifically — the built-ins lean
|
|
22
|
-
* on Expo packages (`expo-linear-gradient`, etc.). Use `<BitBitView>` if you
|
|
23
|
-
* want it to fetch for you.
|
|
24
|
-
*/
|
|
25
|
-
export declare function BitBitViewRenderer({ renderUnknown, dev, onEvent, ...rest }: BitBitViewRendererProps): import("react").FunctionComponentElement<SynthesisViewTreeProps>;
|
|
26
|
-
export type BitBitViewProps = {
|
|
27
|
-
/** A BitBitPressClient (or anything with `user.synthesizeViewItem`). */
|
|
28
|
-
client: SynthesizeViewFetcher;
|
|
29
|
-
keyName: string;
|
|
30
|
-
contentInputs?: ContentInput[];
|
|
31
|
-
components?: ComponentMap;
|
|
32
|
-
/** Fires for `HOST` events the component contract declared. `AGENT`
|
|
33
|
-
* events are handled internally — the SDK round-trips to the synthesis
|
|
34
|
-
* endpoint and swaps the UI in place. */
|
|
35
|
-
onEvent?: (event: SynthesisViewEvent) => void;
|
|
36
|
-
renderUnknown?: RenderUnknown;
|
|
37
|
-
/** Force the in-dev warning behavior regardless of `process.env.NODE_ENV`.
|
|
38
|
-
* See {@link BitBitViewRendererProps.dev}. */
|
|
39
|
-
dev?: boolean;
|
|
40
|
-
/** Force a dark/light mode. Defaults to the system appearance via RN's
|
|
41
|
-
* `useColorScheme` (re-renders when the user toggles their OS theme). */
|
|
42
|
-
darkMode?: boolean;
|
|
43
|
-
/** When true (default), speculatively prefetches AGENT events with
|
|
44
|
-
* payload-less contracts so real clicks render with zero roundtrip. */
|
|
45
|
-
preloadNextUi?: boolean;
|
|
46
|
-
};
|
|
47
|
-
/**
|
|
48
|
-
* React Native (Expo) view: fetches a synthesis view by `keyName` and renders
|
|
49
|
-
* it in place. AGENT events drive next UIs back through the agent (preloaded
|
|
50
|
-
* when possible). HOST events fire `onEvent`.
|
|
51
|
-
*/
|
|
52
|
-
export declare function BitBitView({ client, keyName, contentInputs, components, onEvent, renderUnknown, dev, darkMode, preloadNextUi, }: BitBitViewProps): import("react").FunctionComponentElement<BitBitViewRendererProps> | null;
|
|
1
|
+
export { type BitBitContextValue, BitBitProvider } from '../synthesisUi/context.js';
|
|
53
2
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react-native-expo/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react-native-expo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -1,92 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { Text, useColorScheme } from 'react-native';
|
|
3
|
-
import { devLog, isDevEnvironment } from '../synthesisView/devLog.js';
|
|
4
|
-
import { SynthesisViewTree, } from '../synthesisView/engine.js';
|
|
5
|
-
import { useEventDrivenView } from '../synthesisView/useEventDrivenView.js';
|
|
6
|
-
import { bitBitBuiltins } from './primitives.js';
|
|
7
|
-
export { BitBitProvider } from '../synthesisView/context.js';
|
|
8
|
-
export { createComponentMap, } from '../synthesisView/createComponentMap.js';
|
|
9
|
-
export { useEventDrivenView, } from '../synthesisView/useEventDrivenView.js';
|
|
10
|
-
export { bitBitBuiltins } from './primitives.js';
|
|
11
|
-
const renderUnknownWarning = (name) => createElement(Text, { style: { color: '#b00020', fontFamily: 'monospace', fontSize: 12 } }, `⚠ Unknown component: ${name}`);
|
|
12
|
-
const renderUnknownSilent = () => null;
|
|
13
|
-
const DEFAULT_FONT_SIZE = 16;
|
|
14
|
-
/** Extract the primary family name from a CSS-shape `fontFamily` value.
|
|
15
|
-
* Web takes the full fallback chain (`'"Inter-Regular", "Inter", ...'`);
|
|
16
|
-
* RN takes one registered name, so we keep the first segment and strip
|
|
17
|
-
* quotes. Single-name input passes through unchanged. */
|
|
18
|
-
function pickRNFontFamily(value) {
|
|
19
|
-
const first = value.split(',')[0]?.trim();
|
|
20
|
-
if (!first)
|
|
21
|
-
return value;
|
|
22
|
-
return first.replace(/^["']|["']$/g, '');
|
|
23
|
-
}
|
|
24
|
-
/** Bridge CSS-shape style values into RN's stricter form. Two patches:
|
|
25
|
-
* - `lineHeight` as a unitless multiplier (CSS) → pixels using `fontSize`
|
|
26
|
-
* on the same node (RN treats numeric lineHeight as pixels).
|
|
27
|
-
* - `fontFamily` CSS fallback chain → first registered name (RN accepts
|
|
28
|
-
* one family at a time). */
|
|
29
|
-
function normalizeRNStyle(value) {
|
|
30
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
31
|
-
return value;
|
|
32
|
-
const obj = value;
|
|
33
|
-
let changed = false;
|
|
34
|
-
const out = { ...obj };
|
|
35
|
-
if (typeof obj.lineHeight === 'number' && obj.lineHeight < 4) {
|
|
36
|
-
const fontSize = typeof obj.fontSize === 'number' ? obj.fontSize : DEFAULT_FONT_SIZE;
|
|
37
|
-
out.lineHeight = obj.lineHeight * fontSize;
|
|
38
|
-
changed = true;
|
|
39
|
-
}
|
|
40
|
-
if (typeof obj.fontFamily === 'string' && obj.fontFamily.includes(',')) {
|
|
41
|
-
out.fontFamily = pickRNFontFamily(obj.fontFamily);
|
|
42
|
-
changed = true;
|
|
43
|
-
}
|
|
44
|
-
return changed ? out : value;
|
|
45
|
-
}
|
|
46
|
-
/** Wrap `onEvent` so each emission prints to the console with the dispatch
|
|
47
|
-
* routing inline. Routed through {@link devLog} so the message is auto-
|
|
48
|
-
* prefixed with `[BB]` and stripped to a no-op outside dev. */
|
|
49
|
-
function withDevEventLog(dev, onEvent) {
|
|
50
|
-
return (event) => {
|
|
51
|
-
devLog(dev, `event ${event.componentName}.${event.slot} → ${event.handleWith}`, event);
|
|
52
|
-
onEvent?.(event);
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* React Native (Expo) renderer for a pre-fetched `uiData` array. BB built-in
|
|
57
|
-
* primitives are registered automatically; pass `components` to add or
|
|
58
|
-
* override entries by name. Targets Expo specifically — the built-ins lean
|
|
59
|
-
* on Expo packages (`expo-linear-gradient`, etc.). Use `<BitBitView>` if you
|
|
60
|
-
* want it to fetch for you.
|
|
61
|
-
*/
|
|
62
|
-
export function BitBitViewRenderer({ renderUnknown, dev, onEvent, ...rest }) {
|
|
63
|
-
const isDev = dev ?? isDevEnvironment();
|
|
64
|
-
return createElement(SynthesisViewTree, {
|
|
65
|
-
...rest,
|
|
66
|
-
defaultComponents: bitBitBuiltins,
|
|
67
|
-
normalizeStyle: normalizeRNStyle,
|
|
68
|
-
renderUnknown: renderUnknown ?? (isDev ? renderUnknownWarning : renderUnknownSilent),
|
|
69
|
-
onEvent: isDev ? withDevEventLog(dev, onEvent) : onEvent,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* React Native (Expo) view: fetches a synthesis view by `keyName` and renders
|
|
74
|
-
* it in place. AGENT events drive next UIs back through the agent (preloaded
|
|
75
|
-
* when possible). HOST events fire `onEvent`.
|
|
76
|
-
*/
|
|
77
|
-
export function BitBitView({ client, keyName, contentInputs, components, onEvent, renderUnknown, dev, darkMode, preloadNextUi, }) {
|
|
78
|
-
const systemScheme = useColorScheme();
|
|
79
|
-
const resolvedDark = darkMode ?? (systemScheme === 'dark' ? true : systemScheme === 'light' ? false : undefined);
|
|
80
|
-
const viewInputs = resolvedDark !== undefined ? { darkMode: resolvedDark } : undefined;
|
|
81
|
-
const { uiData, loading, error, handleEvent } = useEventDrivenView(client, keyName, onEvent, contentInputs, viewInputs, { preloadNextUi });
|
|
82
|
-
if (loading || error || !uiData.length)
|
|
83
|
-
return null;
|
|
84
|
-
return createElement(BitBitViewRenderer, {
|
|
85
|
-
uiData,
|
|
86
|
-
components,
|
|
87
|
-
onEvent: handleEvent,
|
|
88
|
-
renderUnknown,
|
|
89
|
-
dev,
|
|
90
|
-
});
|
|
91
|
-
}
|
|
1
|
+
export { BitBitProvider } from '../synthesisUi/context.js';
|
|
92
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react-native-expo/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react-native-expo/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,cAAc,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime contract + loader for server-generated SynthesisUI bundles.
|
|
3
|
+
*
|
|
4
|
+
* Generated UI is built server-side into a self-contained ESM bundle that
|
|
5
|
+
* owns its own React (and react-native-web for the mobile preview) and
|
|
6
|
+
* exposes a `mount` entry. The host (studio preview or consuming SDK) only
|
|
7
|
+
* creates a container (a Shadow DOM root for web) and calls `mount` — it
|
|
8
|
+
* never shares a React instance with the bundle, sidestepping duplicate-React
|
|
9
|
+
* hook errors. The contract here is types + DOM glue only (no React import).
|
|
10
|
+
*/
|
|
11
|
+
/** Props every generated view receives. `data` is the synthesis output
|
|
12
|
+
* (typed from the config's output schema); `ctx` is the host-provided
|
|
13
|
+
* runtime. This is a shared TYPE, not a runtime dependency. */
|
|
14
|
+
export interface BitBitViewProps<T = unknown> {
|
|
15
|
+
data: T;
|
|
16
|
+
ctx: BitBitViewContext;
|
|
17
|
+
}
|
|
18
|
+
export interface BitBitViewContext {
|
|
19
|
+
/** Built-in analytics / link tracking. */
|
|
20
|
+
track(event: string, payload?: unknown): void;
|
|
21
|
+
/** Host slot callbacks (developer-supplied event handlers). */
|
|
22
|
+
onEvent(name: string, payload?: unknown): void;
|
|
23
|
+
/** Brand design tokens (also mirrored as CSS custom properties on the host). */
|
|
24
|
+
theme: Record<string, string>;
|
|
25
|
+
/** Navigate a link (web: location; native: linking/navigation). */
|
|
26
|
+
navigate?(href: string): void;
|
|
27
|
+
}
|
|
28
|
+
/** Handle returned by a mounted view: push new props as `data` streams in,
|
|
29
|
+
* and tear down. */
|
|
30
|
+
export interface GeneratedUiViewHandle {
|
|
31
|
+
update(props: BitBitViewProps): void;
|
|
32
|
+
unmount(): void;
|
|
33
|
+
}
|
|
34
|
+
/** Shape a generated web/mobile bundle's default ESM exports must satisfy.
|
|
35
|
+
* `mount` renders into `element` and returns a handle whose `update` is
|
|
36
|
+
* called as streamed `data` arrives. A bare unmount function is also accepted
|
|
37
|
+
* for static (non-streaming) bundles. */
|
|
38
|
+
export interface GeneratedUiModule {
|
|
39
|
+
mount(element: Element, props: BitBitViewProps): GeneratedUiViewHandle | (() => void);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Load a generated bundle. `src` is either a URL to the ESM (served by the
|
|
43
|
+
* API/CDN) or the bundle source as a string (dynamic-imported via a Blob URL).
|
|
44
|
+
*/
|
|
45
|
+
export declare function loadGeneratedModule(src: string): Promise<GeneratedUiModule>;
|
|
46
|
+
export interface MountGeneratedViewOptions {
|
|
47
|
+
/** Isolate styles in a Shadow DOM root (default). Disable for bundles that
|
|
48
|
+
* inject a global stylesheet into `document.head` — e.g. react-native-web,
|
|
49
|
+
* whose styles don't cross the shadow boundary and would render zero-size. */
|
|
50
|
+
isolateStyles?: boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Mount a generated module into `host`. By default it attaches a Shadow DOM
|
|
54
|
+
* root (style isolation both ways); pass `isolateStyles: false` to mount into
|
|
55
|
+
* the light DOM. Brand `theme` tokens are written as CSS custom properties on
|
|
56
|
+
* the host so they inherit either way. Returns a handle whose `update` pushes
|
|
57
|
+
* new props (e.g. as `data` streams in) and `unmount` tears down.
|
|
58
|
+
*/
|
|
59
|
+
export declare function mountGeneratedView(host: HTMLElement, mod: GeneratedUiModule, props: BitBitViewProps, options?: MountGeneratedViewOptions): GeneratedUiViewHandle;
|
|
60
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;gEAEgE;AAChE,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,IAAI,EAAE,CAAC,CAAC;IACR,GAAG,EAAE,iBAAiB,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9C,+DAA+D;IAC/D,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/C,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;qBACqB;AACrB,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;0CAG0C;AAC1C,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,GAAG,qBAAqB,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;CACvF;AAUD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAyBjF;AAED,MAAM,WAAW,yBAAyB;IACxC;;mFAE+E;IAC/E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AASD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,iBAAiB,EACtB,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,yBAA8B,GACtC,qBAAqB,CAqBvB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime contract + loader for server-generated SynthesisUI bundles.
|
|
3
|
+
*
|
|
4
|
+
* Generated UI is built server-side into a self-contained ESM bundle that
|
|
5
|
+
* owns its own React (and react-native-web for the mobile preview) and
|
|
6
|
+
* exposes a `mount` entry. The host (studio preview or consuming SDK) only
|
|
7
|
+
* creates a container (a Shadow DOM root for web) and calls `mount` — it
|
|
8
|
+
* never shares a React instance with the bundle, sidestepping duplicate-React
|
|
9
|
+
* hook errors. The contract here is types + DOM glue only (no React import).
|
|
10
|
+
*/
|
|
11
|
+
function isGeneratedUiModule(value) {
|
|
12
|
+
return typeof value?.mount === 'function';
|
|
13
|
+
}
|
|
14
|
+
function toViewHandle(result) {
|
|
15
|
+
return typeof result === 'function' ? { update: () => { }, unmount: result } : result;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Load a generated bundle. `src` is either a URL to the ESM (served by the
|
|
19
|
+
* API/CDN) or the bundle source as a string (dynamic-imported via a Blob URL).
|
|
20
|
+
*/
|
|
21
|
+
export async function loadGeneratedModule(src) {
|
|
22
|
+
const isUrl = /^(https?:|blob:|data:|\/)/.test(src);
|
|
23
|
+
let url = src;
|
|
24
|
+
let revoke;
|
|
25
|
+
if (!isUrl) {
|
|
26
|
+
const blob = new Blob([src], { type: 'text/javascript' });
|
|
27
|
+
url = URL.createObjectURL(blob);
|
|
28
|
+
revoke = url;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const mod = (await import(/* @vite-ignore */ url));
|
|
32
|
+
const resolved = isGeneratedUiModule(mod)
|
|
33
|
+
? mod
|
|
34
|
+
: isGeneratedUiModule(mod.default)
|
|
35
|
+
? mod.default
|
|
36
|
+
: null;
|
|
37
|
+
if (!resolved) {
|
|
38
|
+
throw new Error('Generated bundle does not export a `mount` function.');
|
|
39
|
+
}
|
|
40
|
+
return resolved;
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
if (revoke)
|
|
44
|
+
URL.revokeObjectURL(revoke);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function applyThemeTokens(host, theme) {
|
|
48
|
+
for (const [token, value] of Object.entries(theme)) {
|
|
49
|
+
// Tokens like "colors.primary" → "--bb-colors-primary".
|
|
50
|
+
host.style.setProperty(`--bb-${token.replace(/[^a-z0-9]+/gi, '-')}`, value);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Mount a generated module into `host`. By default it attaches a Shadow DOM
|
|
55
|
+
* root (style isolation both ways); pass `isolateStyles: false` to mount into
|
|
56
|
+
* the light DOM. Brand `theme` tokens are written as CSS custom properties on
|
|
57
|
+
* the host so they inherit either way. Returns a handle whose `update` pushes
|
|
58
|
+
* new props (e.g. as `data` streams in) and `unmount` tears down.
|
|
59
|
+
*/
|
|
60
|
+
export function mountGeneratedView(host, mod, props, options = {}) {
|
|
61
|
+
const { isolateStyles = true } = options;
|
|
62
|
+
applyThemeTokens(host, props.ctx.theme);
|
|
63
|
+
const root = isolateStyles
|
|
64
|
+
? (host.shadowRoot ?? host.attachShadow({ mode: 'open' }))
|
|
65
|
+
: host;
|
|
66
|
+
const container = document.createElement('div');
|
|
67
|
+
// rn-web's flex layouts need a real height to fill the host (phone frame).
|
|
68
|
+
if (!isolateStyles)
|
|
69
|
+
container.style.height = '100%';
|
|
70
|
+
root.replaceChildren(container);
|
|
71
|
+
const handle = toViewHandle(mod.mount(container, props));
|
|
72
|
+
return {
|
|
73
|
+
update: (next) => {
|
|
74
|
+
applyThemeTokens(host, next.ctx.theme);
|
|
75
|
+
handle.update(next);
|
|
76
|
+
},
|
|
77
|
+
unmount: () => {
|
|
78
|
+
handle.unmount();
|
|
79
|
+
if (root.contains(container))
|
|
80
|
+
root.removeChild(container);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"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"}
|