@bitbitpress/client 1.1.3 → 1.2.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 +8 -152
- package/dist/generated/openapi.d.ts +802 -314
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/react/index.d.ts +76 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +122 -3
- package/dist/react/index.js.map +1 -1
- package/dist/react-native-expo/BitBitPiece.d.ts +64 -0
- package/dist/react-native-expo/BitBitPiece.d.ts.map +1 -0
- package/dist/react-native-expo/BitBitPiece.js +164 -0
- package/dist/react-native-expo/BitBitPiece.js.map +1 -0
- package/dist/react-native-expo/BitBitView.d.ts.map +1 -1
- package/dist/react-native-expo/BitBitView.js +21 -2
- package/dist/react-native-expo/BitBitView.js.map +1 -1
- package/dist/react-native-expo/bootstrapHtml.d.ts +13 -0
- package/dist/react-native-expo/bootstrapHtml.d.ts.map +1 -1
- package/dist/react-native-expo/bootstrapHtml.js +108 -12
- package/dist/react-native-expo/bootstrapHtml.js.map +1 -1
- package/dist/react-native-expo/index.d.ts +1 -0
- package/dist/react-native-expo/index.d.ts.map +1 -1
- package/dist/react-native-expo/index.js +1 -0
- package/dist/react-native-expo/index.js.map +1 -1
- package/dist/runtime/index.d.ts +32 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +68 -2
- package/dist/runtime/index.js.map +1 -1
- package/dist/studio/BitBitMobilePreview.d.ts +33 -0
- package/dist/studio/BitBitMobilePreview.d.ts.map +1 -0
- package/dist/studio/BitBitMobilePreview.js +120 -0
- package/dist/studio/BitBitMobilePreview.js.map +1 -0
- package/dist/studio/index.d.ts +7 -0
- package/dist/studio/index.d.ts.map +1 -0
- package/dist/studio/index.js +7 -0
- package/dist/studio/index.js.map +1 -0
- package/dist/synthesisUi/types.d.ts +3 -0
- package/dist/synthesisUi/types.d.ts.map +1 -1
- package/dist/user/index.d.ts +42 -19
- package/dist/user/index.d.ts.map +1 -1
- package/dist/user/index.js +8 -3
- package/dist/user/index.js.map +1 -1
- package/dist/user/profile.d.ts +2 -2
- package/dist/user/profile.js +2 -2
- package/dist/user/submissions.d.ts +0 -21
- package/dist/user/submissions.d.ts.map +1 -1
- package/dist/user/submissions.js +0 -39
- package/dist/user/submissions.js.map +1 -1
- package/dist/user/synthesisOutputTts.d.ts +21 -0
- package/dist/user/synthesisOutputTts.d.ts.map +1 -0
- package/dist/user/synthesisOutputTts.js +32 -0
- package/dist/user/synthesisOutputTts.js.map +1 -0
- package/dist/user/synthesisPiece.d.ts +38 -0
- package/dist/user/synthesisPiece.d.ts.map +1 -0
- package/dist/user/synthesisPiece.js +58 -0
- package/dist/user/synthesisPiece.js.map +1 -0
- package/dist/user/track-batch-manager.d.ts +10 -4
- package/dist/user/track-batch-manager.d.ts.map +1 -1
- package/dist/user/track-batch-manager.js +6 -5
- package/dist/user/track-batch-manager.js.map +1 -1
- package/dist/user/track.d.ts +9 -0
- package/dist/user/track.d.ts.map +1 -1
- package/dist/user/track.js +17 -0
- package/dist/user/track.js.map +1 -1
- package/package.json +5 -1
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type { ProfileResponse, ProfileUpdateRequest } from './user/profile.js';
|
|
|
16
16
|
export type { RecommendationsRequest, RecommendationsResponse } from './user/recommendations.js';
|
|
17
17
|
export type { ReportRequest, ReportResponse } from './user/report.js';
|
|
18
18
|
export type { Signal, SignalRequest, SignalResponse } from './user/signal.js';
|
|
19
|
-
export type {
|
|
19
|
+
export type { PublicSubmission, SubmissionAggregate, SubmissionFeed, SubmissionFile, SubmissionState, SubmitRequest, SubmitResponse, } from './user/submissions.js';
|
|
20
20
|
export type { SynthesisHistoryEntry, SynthesizeEvent, SynthesizeItemResponse, SynthesizeOptions, } from './user/synthesize.js';
|
|
21
21
|
export type { SynthesizeOnStreamingData } from './user/synthesize-batch-manager.js';
|
|
22
22
|
export type { TokenRequest, TokenResponse } from './user/token.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,mBAAmB,wBAAwB,CAAC;AAC5C,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,WAAW,EACX,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,YAAY,EACV,eAAe,EACf,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACjG,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACtE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC9E,YAAY,EACV,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,mBAAmB,wBAAwB,CAAC;AAC5C,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,WAAW,EACX,QAAQ,GACT,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,YAAY,EACV,eAAe,EACf,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACjG,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACtE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC9E,YAAY,EACV,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AACpF,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EACV,4BAA4B,EAC5B,0BAA0B,EAC1B,eAAe,EACf,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC"}
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { type BitBitTtsRef } from '../runtime/index.js';
|
|
1
2
|
import type { SynthesisUiPlatform, SynthesisUiRequestInputs, SynthesisUiStreamEvent, SynthesizeUiFetcher } from '../synthesisUi/types.js';
|
|
2
|
-
export type { BitBitViewContext, GeneratedUiModule, GeneratedUiViewHandle, } from '../runtime/index.js';
|
|
3
|
+
export type { BitBitTtsRef, BitBitViewContext, GeneratedUiModule, GeneratedUiViewHandle, } from '../runtime/index.js';
|
|
3
4
|
export { type BitBitContextValue, BitBitProvider } from '../synthesisUi/context.js';
|
|
4
5
|
export type { SynthesisUiPlatform, SynthesisUiRequestInputs, SynthesisUiStreamEvent, SynthesizeUiFetcher, };
|
|
5
6
|
/** `SynthesisUiRequestInputs` (`inputs`, `output`, `searchOptionsOverrides`,
|
|
@@ -21,6 +22,8 @@ export interface BitBitViewProps extends SynthesisUiRequestInputs {
|
|
|
21
22
|
onEvent?: (name: string, payload?: unknown) => void;
|
|
22
23
|
/** Navigate a link the view requested. */
|
|
23
24
|
onNavigate?: (href: string) => void;
|
|
25
|
+
/** Resolve an on-demand audio URL for a voice player (`ctx.tts`). */
|
|
26
|
+
onTts?: (ref?: BitBitTtsRef) => Promise<string>;
|
|
24
27
|
}
|
|
25
28
|
/**
|
|
26
29
|
* Web view for a server-generated SynthesisUI. Streams the UI by `keyName`
|
|
@@ -31,7 +34,78 @@ export interface BitBitViewProps extends SynthesisUiRequestInputs {
|
|
|
31
34
|
* `mobile` preview in the light DOM). Native delivery renders the same mobile
|
|
32
35
|
* bundle in a WebView via the `react-native-expo` entry.
|
|
33
36
|
*/
|
|
34
|
-
export declare function BitBitView({ client: clientProp, keyName, platform, onTrack, onEvent, onNavigate, inputs, output, searchOptionsOverrides, synthesisHistoryLimit, }: BitBitViewProps): import("react").DetailedReactHTMLElement<{
|
|
37
|
+
export declare function BitBitView({ client: clientProp, keyName, platform, onTrack, onEvent, onNavigate, onTts, inputs, output, searchOptionsOverrides, synthesisHistoryLimit, }: BitBitViewProps): import("react").DetailedReactHTMLElement<{
|
|
38
|
+
ref: import("react").RefObject<HTMLDivElement>;
|
|
39
|
+
style: {
|
|
40
|
+
height: string;
|
|
41
|
+
};
|
|
42
|
+
}, HTMLDivElement>;
|
|
43
|
+
/** What `<BitBitPiece keyName>` needs from a client: resolve a piece for embedding.
|
|
44
|
+
* A full `BitBitPressClient` satisfies this; the piece studio's static preview
|
|
45
|
+
* doesn't need it (it uses `code`+`data`). */
|
|
46
|
+
export interface BitBitPieceFetcher {
|
|
47
|
+
user: {
|
|
48
|
+
getSynthesisPiece(keyName: string): Promise<{
|
|
49
|
+
uiWebCode: string;
|
|
50
|
+
fields: unknown;
|
|
51
|
+
theme?: Record<string, string>;
|
|
52
|
+
}>;
|
|
53
|
+
/** Mint an on-demand audio URL for a piece's spoken turns. When present, embed mode
|
|
54
|
+
* (`keyName`) wires it into `ctx.tts` so audio players play without host setup. */
|
|
55
|
+
synthesisPieceTtsUrl?(keyName: string, ref?: BitBitTtsRef): Promise<string>;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
interface BitBitPieceCommonProps {
|
|
59
|
+
/** Brand tokens → CSS custom properties + `ctx.theme`. In `keyName` mode the
|
|
60
|
+
* fetched deployment theme is used unless this overrides it. */
|
|
61
|
+
theme?: Record<string, string>;
|
|
62
|
+
/** Web (Shadow DOM isolation) or the studio's light-DOM mobile preview. */
|
|
63
|
+
platform?: SynthesisUiPlatform;
|
|
64
|
+
/** Force the rendered scheme (`ctx.colorScheme`). Leave unset to let a
|
|
65
|
+
* dual-mode piece follow the browser's `prefers-color-scheme`. */
|
|
66
|
+
colorScheme?: 'light' | 'dark';
|
|
67
|
+
onTrack?: (event: string, payload?: unknown) => void;
|
|
68
|
+
onEvent?: (name: string, payload?: unknown) => void;
|
|
69
|
+
onNavigate?: (href: string) => void;
|
|
70
|
+
/** Resolve an on-demand audio URL for a voice player (`ctx.tts`). */
|
|
71
|
+
onTts?: (ref?: BitBitTtsRef) => Promise<string>;
|
|
72
|
+
/** Bump to force a clean re-mount (reusing the loaded module) — the editor uses this
|
|
73
|
+
* to recover after a structural in-place edit that would corrupt the framework's
|
|
74
|
+
* own reconciliation. */
|
|
75
|
+
remountToken?: number;
|
|
76
|
+
}
|
|
77
|
+
/** Direct mode — the bundle source + data are already in hand (editor-side
|
|
78
|
+
* previews, e.g. the piece studio). No fetch, no client. */
|
|
79
|
+
export interface BitBitPieceCodeProps extends BitBitPieceCommonProps {
|
|
80
|
+
/** The generated self-contained ESM bundle — source string or a URL. */
|
|
81
|
+
code: string;
|
|
82
|
+
/** Field values passed to the bundle as `props.data`. */
|
|
83
|
+
data: unknown;
|
|
84
|
+
keyName?: never;
|
|
85
|
+
client?: never;
|
|
86
|
+
}
|
|
87
|
+
/** Embed mode — resolve the piece by `keyName` through `client` (or the
|
|
88
|
+
* `<BitBitProvider client>` in scope), exactly like `<BitBitView keyName>`. */
|
|
89
|
+
export interface BitBitPieceKeyNameProps extends BitBitPieceCommonProps {
|
|
90
|
+
keyName: string;
|
|
91
|
+
/** Client to fetch through. Optional when a `<BitBitProvider client>` is in scope. */
|
|
92
|
+
client?: BitBitPieceFetcher;
|
|
93
|
+
code?: never;
|
|
94
|
+
data?: never;
|
|
95
|
+
}
|
|
96
|
+
export type BitBitPieceProps = BitBitPieceCodeProps | BitBitPieceKeyNameProps;
|
|
97
|
+
/**
|
|
98
|
+
* Render a generated piece bundle (its `uiWebCode`). Two modes:
|
|
99
|
+
* - **Direct** (`code` + `data`): mounts the module from source in hand — editor
|
|
100
|
+
* previews where code and data are already available (the piece studio).
|
|
101
|
+
* - **Embed** (`keyName` + `client`): resolves the piece's bundle, field values
|
|
102
|
+
* (incl. pre-generated `audioData.url`s), and theme by `keyName` through the
|
|
103
|
+
* client (like `<BitBitView keyName>`).
|
|
104
|
+
*
|
|
105
|
+
* Either way the module mounts on the host (web: Shadow DOM) and `data` is pushed
|
|
106
|
+
* in, re-rendering in place when it changes.
|
|
107
|
+
*/
|
|
108
|
+
export declare function BitBitPiece(props: BitBitPieceProps): import("react").DetailedReactHTMLElement<{
|
|
35
109
|
ref: import("react").RefObject<HTMLDivElement>;
|
|
36
110
|
style: {
|
|
37
111
|
height: string;
|
|
@@ -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":"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"}
|
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createElement, useEffect, useRef } from 'react';
|
|
2
|
-
import { loadGeneratedModule, mountGeneratedView, } from '../runtime/index.js';
|
|
1
|
+
import { createElement, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { attachHlsMedia, loadGeneratedModule, mountGeneratedView, } from '../runtime/index.js';
|
|
3
3
|
import { useBitBitContext } from '../synthesisUi/context.js';
|
|
4
4
|
export { BitBitProvider } from '../synthesisUi/context.js';
|
|
5
5
|
const noop = () => { };
|
|
@@ -12,7 +12,7 @@ const noop = () => { };
|
|
|
12
12
|
* `mobile` preview in the light DOM). Native delivery renders the same mobile
|
|
13
13
|
* bundle in a WebView via the `react-native-expo` entry.
|
|
14
14
|
*/
|
|
15
|
-
export function BitBitView({ client: clientProp, keyName, platform = 'web', onTrack, onEvent, onNavigate, inputs, output, searchOptionsOverrides, synthesisHistoryLimit, }) {
|
|
15
|
+
export function BitBitView({ client: clientProp, keyName, platform = 'web', onTrack, onEvent, onNavigate, onTts, inputs, output, searchOptionsOverrides, synthesisHistoryLimit, }) {
|
|
16
16
|
const contextClient = useBitBitContext()?.client;
|
|
17
17
|
const client = clientProp ?? contextClient;
|
|
18
18
|
const hostRef = useRef(null);
|
|
@@ -31,6 +31,16 @@ export function BitBitView({ client: clientProp, keyName, platform = 'web', onTr
|
|
|
31
31
|
const beacon = (type, name, payload) => {
|
|
32
32
|
trackItem?.({ keyName, type, ...(name != null && { name }), payload })?.catch?.(() => { });
|
|
33
33
|
};
|
|
34
|
+
// The latest streamed output id — what auto-wired `ctx.tts` mints on-request audio against.
|
|
35
|
+
let latestOutputId;
|
|
36
|
+
// Embed mode wires audio automatically: mint against the streamed output through the client.
|
|
37
|
+
// An explicit `onTts` (host-supplied) always wins; absent a client method, `tts` stays undefined
|
|
38
|
+
// so audio-less UIs render normally.
|
|
39
|
+
const clientTtsUrl = client.user.synthesisOutputTtsUrl;
|
|
40
|
+
const autoTts = clientTtsUrl &&
|
|
41
|
+
((ref) => latestOutputId
|
|
42
|
+
? clientTtsUrl(latestOutputId, ref)
|
|
43
|
+
: Promise.reject(new Error('No audio available')));
|
|
34
44
|
const makeCtx = () => ({
|
|
35
45
|
theme,
|
|
36
46
|
track: (event, payload) => {
|
|
@@ -39,6 +49,8 @@ export function BitBitView({ client: clientProp, keyName, platform = 'web', onTr
|
|
|
39
49
|
},
|
|
40
50
|
onEvent: onEvent ?? noop,
|
|
41
51
|
navigate: onNavigate,
|
|
52
|
+
tts: onTts ?? autoTts,
|
|
53
|
+
playMedia: attachHlsMedia,
|
|
42
54
|
});
|
|
43
55
|
void (async () => {
|
|
44
56
|
const stream = await client.user.synthesizeUi({
|
|
@@ -59,6 +71,8 @@ export function BitBitView({ client: clientProp, keyName, platform = 'web', onTr
|
|
|
59
71
|
mod = await loadGeneratedModule(src);
|
|
60
72
|
}
|
|
61
73
|
else if (event.type === 'data' && mod) {
|
|
74
|
+
if (event.synthesisOutputId)
|
|
75
|
+
latestOutputId = event.synthesisOutputId;
|
|
62
76
|
// Mount on the first data event (bundle is ready); update thereafter.
|
|
63
77
|
const props = {
|
|
64
78
|
data: event.data,
|
|
@@ -90,6 +104,7 @@ export function BitBitView({ client: clientProp, keyName, platform = 'web', onTr
|
|
|
90
104
|
onTrack,
|
|
91
105
|
onEvent,
|
|
92
106
|
onNavigate,
|
|
107
|
+
onTts,
|
|
93
108
|
inputs,
|
|
94
109
|
output,
|
|
95
110
|
searchOptionsOverrides,
|
|
@@ -97,4 +112,108 @@ export function BitBitView({ client: clientProp, keyName, platform = 'web', onTr
|
|
|
97
112
|
]);
|
|
98
113
|
return createElement('div', { ref: hostRef, style: { height: '100%' } });
|
|
99
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Render a generated piece bundle (its `uiWebCode`). Two modes:
|
|
117
|
+
* - **Direct** (`code` + `data`): mounts the module from source in hand — editor
|
|
118
|
+
* previews where code and data are already available (the piece studio).
|
|
119
|
+
* - **Embed** (`keyName` + `client`): resolves the piece's bundle, field values
|
|
120
|
+
* (incl. pre-generated `audioData.url`s), and theme by `keyName` through the
|
|
121
|
+
* client (like `<BitBitView keyName>`).
|
|
122
|
+
*
|
|
123
|
+
* Either way the module mounts on the host (web: Shadow DOM) and `data` is pushed
|
|
124
|
+
* in, re-rendering in place when it changes.
|
|
125
|
+
*/
|
|
126
|
+
export function BitBitPiece(props) {
|
|
127
|
+
const { theme, platform = 'web', colorScheme, onTrack, onEvent, onNavigate, onTts, remountToken, } = props;
|
|
128
|
+
const keyName = 'keyName' in props ? props.keyName : undefined;
|
|
129
|
+
const contextClient = useBitBitContext()?.client;
|
|
130
|
+
const client = ('client' in props ? props.client : undefined) ?? contextClient;
|
|
131
|
+
// In embed mode, the resolved bundle/data/theme are fetched by keyName.
|
|
132
|
+
const [fetched, setFetched] = useState(null);
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (keyName == null || !client)
|
|
135
|
+
return;
|
|
136
|
+
let cancelled = false;
|
|
137
|
+
void (async () => {
|
|
138
|
+
const payload = await client.user.getSynthesisPiece(keyName);
|
|
139
|
+
if (cancelled)
|
|
140
|
+
return;
|
|
141
|
+
setFetched({ code: payload.uiWebCode, data: payload.fields, theme: payload.theme });
|
|
142
|
+
})();
|
|
143
|
+
return () => {
|
|
144
|
+
cancelled = true;
|
|
145
|
+
};
|
|
146
|
+
}, [keyName, client]);
|
|
147
|
+
const code = keyName != null ? (fetched?.code ?? null) : props.code;
|
|
148
|
+
const data = keyName != null ? fetched?.data : props.data;
|
|
149
|
+
const resolvedTheme = (keyName != null ? fetched?.theme : undefined) ?? theme;
|
|
150
|
+
// Embed mode wires audio playback through the client automatically; an explicit `onTts`
|
|
151
|
+
// (or direct `code` mode) always wins. The client-backed URL captures the piece's keyName.
|
|
152
|
+
const clientTtsUrl = client?.user.synthesisPieceTtsUrl;
|
|
153
|
+
const resolvedOnTts = onTts ??
|
|
154
|
+
(keyName != null && clientTtsUrl
|
|
155
|
+
? (ref) => clientTtsUrl(keyName, ref)
|
|
156
|
+
: undefined);
|
|
157
|
+
const hostRef = useRef(null);
|
|
158
|
+
const handleRef = useRef(undefined);
|
|
159
|
+
// Latest props, read at mount/update without re-mounting on identity changes.
|
|
160
|
+
const propsRef = useRef({
|
|
161
|
+
data,
|
|
162
|
+
theme: resolvedTheme,
|
|
163
|
+
colorScheme,
|
|
164
|
+
onTrack,
|
|
165
|
+
onEvent,
|
|
166
|
+
onNavigate,
|
|
167
|
+
onTts: resolvedOnTts,
|
|
168
|
+
});
|
|
169
|
+
propsRef.current = {
|
|
170
|
+
data,
|
|
171
|
+
theme: resolvedTheme,
|
|
172
|
+
colorScheme,
|
|
173
|
+
onTrack,
|
|
174
|
+
onEvent,
|
|
175
|
+
onNavigate,
|
|
176
|
+
onTts: resolvedOnTts,
|
|
177
|
+
};
|
|
178
|
+
const makeCtx = useCallback(() => {
|
|
179
|
+
const p = propsRef.current;
|
|
180
|
+
return {
|
|
181
|
+
theme: p.theme ?? {},
|
|
182
|
+
...(p.colorScheme && { colorScheme: p.colorScheme }),
|
|
183
|
+
track: p.onTrack ?? noop,
|
|
184
|
+
onEvent: p.onEvent ?? noop,
|
|
185
|
+
navigate: p.onNavigate,
|
|
186
|
+
tts: p.onTts,
|
|
187
|
+
playMedia: attachHlsMedia,
|
|
188
|
+
};
|
|
189
|
+
}, []);
|
|
190
|
+
// Mount when the bundle source changes (in embed mode, once it has resolved).
|
|
191
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: remountToken is a deliberate remount trigger — bumping it re-runs the teardown/mount even though the body never reads it.
|
|
192
|
+
useEffect(() => {
|
|
193
|
+
const host = hostRef.current;
|
|
194
|
+
if (!host || !code)
|
|
195
|
+
return;
|
|
196
|
+
let cancelled = false;
|
|
197
|
+
void (async () => {
|
|
198
|
+
const mod = await loadGeneratedModule(code);
|
|
199
|
+
if (cancelled || !hostRef.current)
|
|
200
|
+
return;
|
|
201
|
+
handleRef.current = mountGeneratedView(hostRef.current, mod, { data: propsRef.current.data, ctx: makeCtx() }, { isolateStyles: platform !== 'mobile' });
|
|
202
|
+
})();
|
|
203
|
+
return () => {
|
|
204
|
+
cancelled = true;
|
|
205
|
+
handleRef.current?.unmount();
|
|
206
|
+
handleRef.current = undefined;
|
|
207
|
+
};
|
|
208
|
+
// `remountToken` re-runs this to tear down + re-mount cleanly (module is cached).
|
|
209
|
+
}, [code, platform, makeCtx, remountToken]);
|
|
210
|
+
// Push fresh data (and ctx) into the mounted view. `colorScheme` is included so a
|
|
211
|
+
// light/dark toggle re-pushes ctx — `makeCtx` reads props from a ref (stable identity),
|
|
212
|
+
// so without it a scheme change would sit unflushed until `data` changed.
|
|
213
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: colorScheme is a deliberate re-push trigger — makeCtx reads it through a stable ref, so it must stay in deps to flush a scheme toggle.
|
|
214
|
+
useEffect(() => {
|
|
215
|
+
handleRef.current?.update({ data, ctx: makeCtx() });
|
|
216
|
+
}, [data, makeCtx, colorScheme]);
|
|
217
|
+
return createElement('div', { ref: hostRef, style: { height: '100%' } });
|
|
218
|
+
}
|
|
100
219
|
//# 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,MAAM,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { WebView } from 'react-native-webview';
|
|
2
|
+
/** What the native `<BitBitPiece keyName>` needs from a client: resolve a
|
|
3
|
+
* published piece for embedding. A full `BitBitPressClient` satisfies this. */
|
|
4
|
+
export interface BitBitPieceFetcher {
|
|
5
|
+
user: {
|
|
6
|
+
getSynthesisPiece(keyName: string): Promise<{
|
|
7
|
+
uiWebCode: string;
|
|
8
|
+
fields: unknown;
|
|
9
|
+
theme?: Record<string, string>;
|
|
10
|
+
}>;
|
|
11
|
+
trackPieceItem?(e: {
|
|
12
|
+
keyName: string;
|
|
13
|
+
type: 'VIEW' | 'CLICK';
|
|
14
|
+
name?: string;
|
|
15
|
+
payload?: unknown;
|
|
16
|
+
}): Promise<unknown>;
|
|
17
|
+
/** Mint an on-demand streaming audio URL for referenced piece content — wired into the
|
|
18
|
+
* view's `ctx.tts` so audio players play without host setup. */
|
|
19
|
+
synthesisPieceTtsUrl?(keyName: string, ref?: {
|
|
20
|
+
field?: string;
|
|
21
|
+
index?: number;
|
|
22
|
+
}): Promise<string>;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export interface BitBitPieceProps {
|
|
26
|
+
/** Client to resolve the piece through. Optional when a `<BitBitProvider
|
|
27
|
+
* client>` is in scope. */
|
|
28
|
+
client?: BitBitPieceFetcher;
|
|
29
|
+
keyName: string;
|
|
30
|
+
/** Brand analytics / link tracking. */
|
|
31
|
+
onTrack?: (event: string, payload?: unknown) => void;
|
|
32
|
+
/** Host slot callbacks (developer-supplied event handlers). */
|
|
33
|
+
onEvent?: (name: string, payload?: unknown) => void;
|
|
34
|
+
/** Navigate a link the view requested (the WebView never navigates itself). */
|
|
35
|
+
onNavigate?: (href: string) => void;
|
|
36
|
+
/** Called when the piece fails to resolve, load, or render. Defaults to
|
|
37
|
+
* `console.warn` so failures are never silent. */
|
|
38
|
+
onError?: (message: string) => void;
|
|
39
|
+
/** Fill the host's height (`flex: 1`) instead of sizing to the piece's own
|
|
40
|
+
* content height. Use for a full-screen piece; defaults to false so the piece
|
|
41
|
+
* renders at its natural height inside a scrolling host (a feed tile). */
|
|
42
|
+
fillHeight?: boolean;
|
|
43
|
+
/** Height (px) to reserve before the content reports its own — avoids a layout
|
|
44
|
+
* jump. Ignored when `fillHeight`. Defaults to 240. */
|
|
45
|
+
initialHeight?: number;
|
|
46
|
+
/** Force the rendered scheme. Defaults to the device appearance
|
|
47
|
+
* (`useColorScheme`) — the WebView can't read it itself, so it's passed in. */
|
|
48
|
+
colorScheme?: 'light' | 'dark';
|
|
49
|
+
/** Style for the hosting WebView. */
|
|
50
|
+
style?: Record<string, unknown>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* React Native view for a published SynthesisPiece — the native counterpart of
|
|
54
|
+
* the web `<BitBitPiece keyName>`. Resolves the piece's generated web bundle
|
|
55
|
+
* (`uiWebCode`), current field values (`fields`), and deployment `theme` by
|
|
56
|
+
* `keyName`, hosts the bundle (plain DOM: Preact + htm) in a `WebView`, pushes
|
|
57
|
+
* `fields` in as its data, and relays the view's `track`/`onEvent`/`navigate`
|
|
58
|
+
* back out (plus auto-beaconing when `client` is a full `BitBitPressClient`).
|
|
59
|
+
*
|
|
60
|
+
* Unlike `<BitBitView>` there is no stream — a piece is a single resolved
|
|
61
|
+
* snapshot, so the data is pushed once the WebView signals `ready`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function BitBitPiece({ client: clientProp, keyName, onTrack, onEvent, onNavigate, onError, fillHeight, initialHeight, colorScheme, style, }: BitBitPieceProps): import("react").CElement<import("react-native-webview").WebViewProps, WebView> | null;
|
|
64
|
+
//# sourceMappingURL=BitBitPiece.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitBitPiece.d.ts","sourceRoot":"","sources":["../../src/react-native-expo/BitBitPiece.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAA4B,MAAM,sBAAsB,CAAC;AAIzE;gFACgF;AAChF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE;QACJ,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;YAC1C,SAAS,EAAE,MAAM,CAAC;YAClB,MAAM,EAAE,OAAO,CAAC;YAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;SAChC,CAAC,CAAC;QAIH,cAAc,CAAC,CAAC,CAAC,EAAE;YACjB,OAAO,EAAE,MAAM,CAAC;YAChB,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;YACvB,IAAI,CAAC,EAAE,MAAM,CAAC;YACd,OAAO,CAAC,EAAE,OAAO,CAAC;SACnB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACrB;yEACiE;QACjE,oBAAoB,CAAC,CACnB,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,GACvC,OAAO,CAAC,MAAM,CAAC,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B;gCAC4B;IAC5B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,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,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC;uDACmD;IACnD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC;;+EAE2E;IAC3E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;4DACwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;oFACgF;IAChF,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC/B,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAaD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EAAE,UAAU,EAClB,OAAO,EACP,OAAO,EACP,OAAO,EACP,UAAU,EACV,OAAO,EACP,UAAkB,EAClB,aAAmB,EACnB,WAAW,EACX,KAAK,GACN,EAAE,gBAAgB,yFAqKlB"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { createElement, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { useColorScheme } from 'react-native';
|
|
3
|
+
import { WebView } from 'react-native-webview';
|
|
4
|
+
import { useBitBitContext } from '../synthesisUi/context.js';
|
|
5
|
+
import { buildBootstrapHtml } from './bootstrapHtml.js';
|
|
6
|
+
/**
|
|
7
|
+
* React Native view for a published SynthesisPiece — the native counterpart of
|
|
8
|
+
* the web `<BitBitPiece keyName>`. Resolves the piece's generated web bundle
|
|
9
|
+
* (`uiWebCode`), current field values (`fields`), and deployment `theme` by
|
|
10
|
+
* `keyName`, hosts the bundle (plain DOM: Preact + htm) in a `WebView`, pushes
|
|
11
|
+
* `fields` in as its data, and relays the view's `track`/`onEvent`/`navigate`
|
|
12
|
+
* back out (plus auto-beaconing when `client` is a full `BitBitPressClient`).
|
|
13
|
+
*
|
|
14
|
+
* Unlike `<BitBitView>` there is no stream — a piece is a single resolved
|
|
15
|
+
* snapshot, so the data is pushed once the WebView signals `ready`.
|
|
16
|
+
*/
|
|
17
|
+
export function BitBitPiece({ client: clientProp, keyName, onTrack, onEvent, onNavigate, onError, fillHeight = false, initialHeight = 240, colorScheme, style, }) {
|
|
18
|
+
const contextClient = useBitBitContext()?.client;
|
|
19
|
+
const client = clientProp ?? contextClient;
|
|
20
|
+
// The WebView can't read the OS appearance, so resolve it here and pass it in.
|
|
21
|
+
const osScheme = useColorScheme();
|
|
22
|
+
const scheme = colorScheme ?? (osScheme === 'dark' ? 'dark' : 'light');
|
|
23
|
+
// Read at (re)build time without making it a build dependency — scheme changes
|
|
24
|
+
// are pushed live below instead of rebuilding (which would reload the WebView).
|
|
25
|
+
const schemeRef = useRef(scheme);
|
|
26
|
+
schemeRef.current = scheme;
|
|
27
|
+
const reportError = useCallback((message) => {
|
|
28
|
+
if (onError)
|
|
29
|
+
onError(message);
|
|
30
|
+
else
|
|
31
|
+
console.warn(`[BitBitPiece] ${message}`);
|
|
32
|
+
}, [onError]);
|
|
33
|
+
const webRef = useRef(null);
|
|
34
|
+
const [html, setHtml] = useState(null);
|
|
35
|
+
// Content height reported by the bundle (auto-height mode); null until first report.
|
|
36
|
+
const [contentHeight, setContentHeight] = useState(null);
|
|
37
|
+
// Resolved field values + whether the WebView has loaded the bundle and can
|
|
38
|
+
// receive them. Refs (not state) so the bridge round-trip doesn't churn renders.
|
|
39
|
+
const dataRef = useRef(undefined);
|
|
40
|
+
const readyRef = useRef(false);
|
|
41
|
+
// A `BitBitPressClient` may be a retry Proxy whose method getters return a NEW
|
|
42
|
+
// function on every access, so we depend on this stable boolean — never the
|
|
43
|
+
// function identities — and read the methods fresh from `client` when calling.
|
|
44
|
+
const hasTts = typeof client?.user.synthesisPieceTtsUrl === 'function';
|
|
45
|
+
const beacon = useCallback((type, name, payload) => {
|
|
46
|
+
client?.user
|
|
47
|
+
.trackPieceItem?.({ keyName, type, ...(name != null && { name }), payload })
|
|
48
|
+
?.catch?.(() => { });
|
|
49
|
+
}, [client, keyName]);
|
|
50
|
+
const pushData = useCallback((data) => {
|
|
51
|
+
webRef.current?.injectJavaScript(`window.__bb && window.__bb.update(${JSON.stringify(data)}); true;`);
|
|
52
|
+
}, []);
|
|
53
|
+
// Resolve the piece and build the WebView document. Pushes the fields in
|
|
54
|
+
// immediately if the WebView has already signalled `ready`.
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (!client)
|
|
57
|
+
return;
|
|
58
|
+
let cancelled = false;
|
|
59
|
+
readyRef.current = false;
|
|
60
|
+
dataRef.current = undefined;
|
|
61
|
+
setHtml(null);
|
|
62
|
+
void (async () => {
|
|
63
|
+
try {
|
|
64
|
+
const piece = await client.user.getSynthesisPiece(keyName);
|
|
65
|
+
if (cancelled)
|
|
66
|
+
return;
|
|
67
|
+
dataRef.current = piece.fields;
|
|
68
|
+
setHtml(buildBootstrapHtml({
|
|
69
|
+
bundle: piece.uiWebCode,
|
|
70
|
+
theme: piece.theme ?? {},
|
|
71
|
+
autoHeight: !fillHeight,
|
|
72
|
+
enableTts: hasTts,
|
|
73
|
+
colorScheme: schemeRef.current,
|
|
74
|
+
}));
|
|
75
|
+
if (readyRef.current)
|
|
76
|
+
pushData(piece.fields);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (!cancelled)
|
|
80
|
+
reportError(err instanceof Error ? err.message : String(err));
|
|
81
|
+
}
|
|
82
|
+
})();
|
|
83
|
+
return () => {
|
|
84
|
+
cancelled = true;
|
|
85
|
+
};
|
|
86
|
+
}, [client, keyName, pushData, fillHeight, hasTts, reportError]);
|
|
87
|
+
// Push OS appearance changes into the loaded WebView (no reload) so a dual-mode
|
|
88
|
+
// piece recolors live when the device switches light/dark.
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
webRef.current?.injectJavaScript(`window.__bb && window.__bb.setColorScheme(${JSON.stringify(scheme)}); true;`);
|
|
91
|
+
}, [scheme]);
|
|
92
|
+
const onMessage = useCallback((e) => {
|
|
93
|
+
let msg;
|
|
94
|
+
try {
|
|
95
|
+
msg = JSON.parse(e.nativeEvent.data);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
switch (msg.kind) {
|
|
101
|
+
case 'ready':
|
|
102
|
+
readyRef.current = true;
|
|
103
|
+
if (dataRef.current !== undefined)
|
|
104
|
+
pushData(dataRef.current);
|
|
105
|
+
break;
|
|
106
|
+
case 'height':
|
|
107
|
+
if (!fillHeight && msg.px > 0)
|
|
108
|
+
setContentHeight(msg.px);
|
|
109
|
+
break;
|
|
110
|
+
case 'error':
|
|
111
|
+
reportError(msg.message);
|
|
112
|
+
break;
|
|
113
|
+
case 'tts': {
|
|
114
|
+
const { id, ref } = msg;
|
|
115
|
+
const resolve = (url, error) => webRef.current?.injectJavaScript(`window.__bb && window.__bb.resolveTts(${id}, ${JSON.stringify(url)}, ${JSON.stringify(error ?? null)}); true;`);
|
|
116
|
+
const ttsUrl = client?.user.synthesisPieceTtsUrl;
|
|
117
|
+
if (!ttsUrl) {
|
|
118
|
+
resolve(null, 'Could not load audio');
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
ttsUrl(keyName, ref)
|
|
122
|
+
.then((url) => resolve(url))
|
|
123
|
+
.catch((err) => resolve(null, err instanceof Error ? err.message : 'Could not load audio'));
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
case 'view':
|
|
127
|
+
beacon('VIEW');
|
|
128
|
+
break;
|
|
129
|
+
case 'track':
|
|
130
|
+
onTrack?.(msg.event, msg.payload);
|
|
131
|
+
beacon('CLICK', msg.event, msg.payload);
|
|
132
|
+
break;
|
|
133
|
+
case 'event':
|
|
134
|
+
onEvent?.(msg.name, msg.payload);
|
|
135
|
+
break;
|
|
136
|
+
case 'navigate':
|
|
137
|
+
onNavigate?.(msg.href);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}, [beacon, onTrack, onEvent, onNavigate, pushData, fillHeight, client, keyName, reportError]);
|
|
141
|
+
if (!html)
|
|
142
|
+
return null;
|
|
143
|
+
// Auto-height: the host feed scrolls, so the WebView sizes to the piece's
|
|
144
|
+
// reported content height and never scrolls itself. Fill mode fills the parent.
|
|
145
|
+
const sizeStyle = fillHeight
|
|
146
|
+
? { flex: 1 }
|
|
147
|
+
: { width: '100%', height: contentHeight ?? initialHeight };
|
|
148
|
+
return createElement(WebView, {
|
|
149
|
+
ref: webRef,
|
|
150
|
+
source: { html, baseUrl: 'https://localhost/' },
|
|
151
|
+
originWhitelist: ['*'],
|
|
152
|
+
onMessage,
|
|
153
|
+
onError: () => reportError('WebView failed to load'),
|
|
154
|
+
scrollEnabled: fillHeight,
|
|
155
|
+
javaScriptEnabled: true,
|
|
156
|
+
domStorageEnabled: true,
|
|
157
|
+
allowsInlineMediaPlayback: true,
|
|
158
|
+
mediaPlaybackRequiresUserAction: false,
|
|
159
|
+
// Links go to `onNavigate`, never in-WebView navigation.
|
|
160
|
+
onShouldStartLoadWithRequest: (request) => request.url === 'https://localhost/' || request.url.startsWith('about:'),
|
|
161
|
+
style: style ?? { backgroundColor: 'transparent', ...sizeStyle },
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=BitBitPiece.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BitBitPiece.js","sourceRoot":"","sources":["../../src/react-native-expo/BitBitPiece.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitBitView.d.ts","sourceRoot":"","sources":["../../src/react-native-expo/BitBitView.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAA4B,MAAM,sBAAsB,CAAC;AAEzE,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAGjC;;;mCAGmC;AACnC,MAAM,WAAW,eAAgB,SAAQ,wBAAwB;IAC/D;uBACmB;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB;oBACgB;IAChB,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,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;
|
|
1
|
+
{"version":3,"file":"BitBitView.d.ts","sourceRoot":"","sources":["../../src/react-native-expo/BitBitView.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAA4B,MAAM,sBAAsB,CAAC;AAEzE,OAAO,KAAK,EACV,mBAAmB,EACnB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,yBAAyB,CAAC;AAGjC;;;mCAGmC;AACnC,MAAM,WAAW,eAAgB,SAAQ,wBAAwB;IAC/D;uBACmB;IACnB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB;oBACgB;IAChB,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,+EAA+E;IAC/E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAWD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EACzB,MAAM,EAAE,UAAU,EAClB,OAAO,EACP,QAAmB,EACnB,OAAO,EACP,OAAO,EACP,UAAU,EACV,KAAK,EACL,MAAM,EACN,MAAM,EACN,sBAAsB,EACtB,qBAAqB,GACtB,EAAE,eAAe,yFAuKjB"}
|
|
@@ -18,6 +18,8 @@ export function BitBitView({ client: clientProp, keyName, platform = 'mobile', o
|
|
|
18
18
|
// and can receive it. Refs (not state) so streaming doesn't churn renders.
|
|
19
19
|
const dataRef = useRef(undefined);
|
|
20
20
|
const historyRef = useRef(undefined);
|
|
21
|
+
// The latest streamed output id — what `ctx.tts` mints on-request audio against.
|
|
22
|
+
const outputIdRef = useRef(undefined);
|
|
21
23
|
const readyRef = useRef(false);
|
|
22
24
|
// Auto-beacon when `client` is a full BitBitPressClient (the bare preview
|
|
23
25
|
// fetcher has no `trackItem`). Failures are swallowed — analytics never break
|
|
@@ -38,6 +40,7 @@ export function BitBitView({ client: clientProp, keyName, platform = 'mobile', o
|
|
|
38
40
|
readyRef.current = false;
|
|
39
41
|
dataRef.current = undefined;
|
|
40
42
|
historyRef.current = undefined;
|
|
43
|
+
outputIdRef.current = undefined;
|
|
41
44
|
setHtml(null);
|
|
42
45
|
void (async () => {
|
|
43
46
|
try {
|
|
@@ -55,11 +58,13 @@ export function BitBitView({ client: clientProp, keyName, platform = 'mobile', o
|
|
|
55
58
|
if (event.type === 'manifest') {
|
|
56
59
|
const bundle = event.bundleUrl ?? event.bundleSource;
|
|
57
60
|
if (bundle)
|
|
58
|
-
setHtml(buildBootstrapHtml({ bundle, theme: event.theme }));
|
|
61
|
+
setHtml(buildBootstrapHtml({ bundle, theme: event.theme, enableTts: true }));
|
|
59
62
|
}
|
|
60
63
|
else if (event.type === 'data') {
|
|
61
64
|
dataRef.current = event.data;
|
|
62
65
|
historyRef.current = event.synthesisHistoryEntries;
|
|
66
|
+
if (event.synthesisOutputId)
|
|
67
|
+
outputIdRef.current = event.synthesisOutputId;
|
|
63
68
|
if (readyRef.current)
|
|
64
69
|
pushData(event.data, event.synthesisHistoryEntries);
|
|
65
70
|
}
|
|
@@ -109,8 +114,22 @@ export function BitBitView({ client: clientProp, keyName, platform = 'mobile', o
|
|
|
109
114
|
case 'navigate':
|
|
110
115
|
onNavigate?.(msg.href);
|
|
111
116
|
break;
|
|
117
|
+
case 'tts': {
|
|
118
|
+
const { id, ref } = msg;
|
|
119
|
+
const resolve = (url, error) => webRef.current?.injectJavaScript(`window.__bb && window.__bb.resolveTts(${id}, ${JSON.stringify(url)}, ${JSON.stringify(error ?? null)}); true;`);
|
|
120
|
+
const ttsUrl = client?.user?.synthesisOutputTtsUrl;
|
|
121
|
+
const outputId = outputIdRef.current;
|
|
122
|
+
if (!ttsUrl || !outputId) {
|
|
123
|
+
resolve(null, 'Could not load audio');
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
ttsUrl(outputId, ref)
|
|
127
|
+
.then((url) => resolve(url))
|
|
128
|
+
.catch((err) => resolve(null, err instanceof Error ? err.message : 'Could not load audio'));
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
112
131
|
}
|
|
113
|
-
}, [beacon, onTrack, onEvent, onNavigate, pushData]);
|
|
132
|
+
}, [beacon, onTrack, onEvent, onNavigate, pushData, client]);
|
|
114
133
|
if (!html)
|
|
115
134
|
return null;
|
|
116
135
|
return createElement(WebView, {
|