@graineai/inapp-react-native 0.30.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +3 -0
- package/dist/client.js +9 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/protocol.d.ts +2 -0
- package/dist/protocol.js +12 -0
- package/dist/react-native/index.d.ts +7 -0
- package/dist/react-native/index.js +26 -8
- package/dist/react-native/voice-launcher.js +5 -0
- package/package.json +2 -2
package/dist/client.d.ts
CHANGED
|
@@ -63,6 +63,9 @@ export declare class GraineInAppClient {
|
|
|
63
63
|
configureFriction(override: FrictionConfig | null | undefined): void;
|
|
64
64
|
get friction(): Required<FrictionConfig>;
|
|
65
65
|
on(event: string, fn: Listener): () => void;
|
|
66
|
+
private lastWidget;
|
|
67
|
+
get pendingWidget(): any;
|
|
68
|
+
clearPendingWidget(): void;
|
|
66
69
|
emit(event: string, payload?: any): void;
|
|
67
70
|
private get fetch();
|
|
68
71
|
session(): Promise<SessionConfig>;
|
package/dist/client.js
CHANGED
|
@@ -28,6 +28,7 @@ export class GraineInAppClient {
|
|
|
28
28
|
this.identity = {};
|
|
29
29
|
this.appVersion = null;
|
|
30
30
|
this.recentEvents = [];
|
|
31
|
+
this.lastWidget = null;
|
|
31
32
|
if (!opts?.publishableKey)
|
|
32
33
|
throw new Error("[Graine] publishableKey is required.");
|
|
33
34
|
if (!opts?.baseUrl)
|
|
@@ -57,7 +58,15 @@ export class GraineInAppClient {
|
|
|
57
58
|
this.listeners.get(event).add(fn);
|
|
58
59
|
return () => this.listeners.get(event)?.delete(fn);
|
|
59
60
|
}
|
|
61
|
+
get pendingWidget() {
|
|
62
|
+
return this.lastWidget;
|
|
63
|
+
}
|
|
64
|
+
clearPendingWidget() {
|
|
65
|
+
this.lastWidget = null;
|
|
66
|
+
}
|
|
60
67
|
emit(event, payload) {
|
|
68
|
+
if (event === "widget")
|
|
69
|
+
this.lastWidget = payload ?? null;
|
|
61
70
|
for (const fn of this.listeners.get(event) ?? []) {
|
|
62
71
|
try {
|
|
63
72
|
fn(payload);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export type { ActionHandler, AppActionRequest, AppActionResult, AppEvent, ScreenContext, ScreenField, } from "./protocol.js";
|
|
1
|
+
export type { ActionHandler, AppActionRequest, AppActionResult, AppEvent, ScreenContext, ScreenField, WidgetSurface, } from "./protocol.js";
|
|
2
|
+
export { widgetSurface } from "./protocol.js";
|
|
2
3
|
export { GraineInAppClient, type GraineInAppOptions, type SessionConfig, type ActionDiagnosis, } from "./client.js";
|
|
3
4
|
export { FrictionDetector, resolveFriction, rulesFor, DEFAULT_FRICTION, type FrictionConfig, type FrictionScreenRules, type FrictionNudge, type FrictionSignal, type FrictionKind, } from "./friction.js";
|
|
4
5
|
export { VoiceSession, liveAudioStreamAdapter, base64ToPcm16, CAPTURE_SAMPLE_RATE, type AudioAdapter, type VoiceSessionOptions, } from "./voice.js";
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { widgetSurface } from "./protocol.js";
|
|
1
2
|
export { GraineInAppClient, } from "./client.js";
|
|
2
3
|
export { FrictionDetector, resolveFriction, rulesFor, DEFAULT_FRICTION, } from "./friction.js";
|
|
3
4
|
export { VoiceSession, liveAudioStreamAdapter, base64ToPcm16, CAPTURE_SAMPLE_RATE, } from "./voice.js";
|
package/dist/protocol.d.ts
CHANGED
|
@@ -62,3 +62,5 @@ export declare const ACTION_DEADLINE_MS = 6000;
|
|
|
62
62
|
export declare const CONTEXT_THROTTLE_MS = 400;
|
|
63
63
|
export declare const UNNAMED_TAP = "tap:screen";
|
|
64
64
|
export declare function resolveWidgetImages(data: Record<string, unknown>, baseUrl: string): Record<string, unknown>;
|
|
65
|
+
export type WidgetSurface = "screen" | "sheet" | "card";
|
|
66
|
+
export declare function widgetSurface(kind: string | null | undefined): WidgetSurface;
|
package/dist/protocol.js
CHANGED
|
@@ -29,3 +29,15 @@ export function resolveWidgetImages(data, baseUrl) {
|
|
|
29
29
|
}
|
|
30
30
|
return out;
|
|
31
31
|
}
|
|
32
|
+
const SURFACE = {
|
|
33
|
+
product_list: "screen",
|
|
34
|
+
products: "screen",
|
|
35
|
+
plan_comparison: "sheet",
|
|
36
|
+
choices: "sheet",
|
|
37
|
+
quick_actions: "sheet",
|
|
38
|
+
calendar_slots: "sheet",
|
|
39
|
+
info_card: "card",
|
|
40
|
+
};
|
|
41
|
+
export function widgetSurface(kind) {
|
|
42
|
+
return SURFACE[String(kind ?? "").trim().toLowerCase()] ?? "card";
|
|
43
|
+
}
|
|
@@ -4,6 +4,8 @@ import { type AudioAdapter, type VoiceSessionOptions } from "../voice.js";
|
|
|
4
4
|
import type { ActionHandler, ScreenContext, ScreenField } from "../protocol.js";
|
|
5
5
|
export { GraineFab, GraineTouchCapture } from "./fab.js";
|
|
6
6
|
export type { GraineFabProps, GraineTouchCaptureProps } from "./fab.js";
|
|
7
|
+
export { widgetSurface } from "../protocol.js";
|
|
8
|
+
export type { WidgetSurface } from "../protocol.js";
|
|
7
9
|
import type { FrictionConfig } from "../friction.js";
|
|
8
10
|
import { type LauncherInset, type LauncherVisibility } from "./navigation.js";
|
|
9
11
|
interface GraineContextValue {
|
|
@@ -123,6 +125,11 @@ export declare function useGraineHighlight(name: string): {
|
|
|
123
125
|
};
|
|
124
126
|
export declare function useGraineWidget(): {
|
|
125
127
|
widget: GraineWidget | null;
|
|
128
|
+
answered: {
|
|
129
|
+
widget: GraineWidget;
|
|
130
|
+
data: Record<string, unknown>;
|
|
131
|
+
summary: string;
|
|
132
|
+
} | null;
|
|
126
133
|
submit: (data: Record<string, unknown>, summary: string) => void;
|
|
127
134
|
dismiss: () => void;
|
|
128
135
|
};
|
|
@@ -6,6 +6,7 @@ import { VoiceSession } from "../voice.js";
|
|
|
6
6
|
import { resolveWidgetImages } from "../protocol.js";
|
|
7
7
|
import { GraineFab, GraineTouchCapture } from "./fab.js";
|
|
8
8
|
export { GraineFab, GraineTouchCapture } from "./fab.js";
|
|
9
|
+
export { widgetSurface } from "../protocol.js";
|
|
9
10
|
import { LauncherVisibilityTracker, activeRouteName, } from "./navigation.js";
|
|
10
11
|
export const Ctx = createContext(null);
|
|
11
12
|
let defaultClient = null;
|
|
@@ -389,25 +390,42 @@ export function useGraineHighlight(name) {
|
|
|
389
390
|
}
|
|
390
391
|
export function useGraineWidget() {
|
|
391
392
|
const client = useGraineClient();
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
if (!w?.widget_id)
|
|
395
|
-
return;
|
|
396
|
-
setWidget({
|
|
393
|
+
const adopt = useCallback((w) => w?.widget_id
|
|
394
|
+
? {
|
|
397
395
|
id: String(w.widget_id),
|
|
398
396
|
kind: String(w.kind || ""),
|
|
399
397
|
data: resolveWidgetImages((w.data || {}), client.opts.baseUrl),
|
|
400
398
|
fallbackText: String(w.fallback_text || ""),
|
|
399
|
+
}
|
|
400
|
+
: null, [client]);
|
|
401
|
+
const [widget, setWidget] = useState(() => adopt(client.pendingWidget));
|
|
402
|
+
const [answered, setAnswered] = useState(null);
|
|
403
|
+
useEffect(() => {
|
|
404
|
+
const pending = adopt(client.pendingWidget);
|
|
405
|
+
if (pending)
|
|
406
|
+
setWidget((cur) => (cur && cur.id === pending.id ? cur : pending));
|
|
407
|
+
return client.on("widget", (w) => {
|
|
408
|
+
const next = adopt(w);
|
|
409
|
+
if (!next)
|
|
410
|
+
return;
|
|
411
|
+
setWidget(next);
|
|
412
|
+
setAnswered(null);
|
|
401
413
|
});
|
|
402
|
-
}
|
|
414
|
+
}, [client, adopt]);
|
|
403
415
|
const submit = useCallback((data, summary) => {
|
|
404
416
|
if (!widget)
|
|
405
417
|
return;
|
|
406
418
|
client.submitWidget(widget.id, data, summary);
|
|
419
|
+
client.clearPendingWidget();
|
|
407
420
|
setWidget(null);
|
|
421
|
+
setAnswered({ widget, data, summary });
|
|
408
422
|
}, [client, widget]);
|
|
409
|
-
const dismiss = useCallback(() =>
|
|
410
|
-
|
|
423
|
+
const dismiss = useCallback(() => {
|
|
424
|
+
client.clearPendingWidget();
|
|
425
|
+
setWidget(null);
|
|
426
|
+
setAnswered(null);
|
|
427
|
+
}, [client]);
|
|
428
|
+
return { widget, answered, submit, dismiss };
|
|
411
429
|
}
|
|
412
430
|
export function useGraineAction(name, handler) {
|
|
413
431
|
const client = useGraineClient();
|
|
@@ -138,6 +138,9 @@ export function GraineVoiceLauncher({ webView: WebView, autoStart = false, activ
|
|
|
138
138
|
startedRef.current = true;
|
|
139
139
|
void beginCall();
|
|
140
140
|
}
|
|
141
|
+
else if (!activeRef.current && !startedRef.current) {
|
|
142
|
+
post({ type: "graine:warm" });
|
|
143
|
+
}
|
|
141
144
|
return;
|
|
142
145
|
case "graine:call":
|
|
143
146
|
setConnected(!!msg.connected);
|
|
@@ -200,6 +203,7 @@ export function GraineVoiceLauncher({ webView: WebView, autoStart = false, activ
|
|
|
200
203
|
start: useCallback(() => {
|
|
201
204
|
setConnecting(true);
|
|
202
205
|
setCaptions([]);
|
|
206
|
+
client.clearPendingWidget();
|
|
203
207
|
if (!ready) {
|
|
204
208
|
pendingStartRef.current = true;
|
|
205
209
|
return;
|
|
@@ -243,6 +247,7 @@ export function GraineVoiceLauncher({ webView: WebView, autoStart = false, activ
|
|
|
243
247
|
setConnected(false);
|
|
244
248
|
setConnecting(false);
|
|
245
249
|
setCaptions([]);
|
|
250
|
+
client.clearPendingWidget();
|
|
246
251
|
onCallState?.({ connected: false, connecting: false });
|
|
247
252
|
}, [active]);
|
|
248
253
|
useEffect(() => {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graineai/inapp-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "Graine in-app agent for React Native
|
|
5
|
+
"description": "Graine in-app agent for React Native — an agent that sees the screen your customer is on and can act on it.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"private": false,
|
|
8
8
|
"main": "dist/index.js",
|