@sansavision/yousaid-react 0.0.0-stage → 0.2.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/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@sansavision/yousaid-react` are recorded here. The project
4
+ follows semantic versioning for the stable surface listed in README.md.
5
+
6
+ ## 0.2.0
7
+
8
+ First npm release.
9
+
10
+ - Ships compiled ES2022 JavaScript (`jsx: react-jsx`) with TypeScript declarations and declaration maps.
11
+ - Depends on `@sansavision/yousaid` `^0.2.0`; peer dependency `react >= 19`.
12
+ - Stable: `YouSaidProvider`, `useYouSaid`, `YouSaidLauncher`, `Inbox`, `useInbox` and `LifecycleReceipt`.
13
+ - Experimental (tagged `@experimental`): Rooms components and hooks, agents, approvals, moderation, Proof widgets, `ProofPrompt` and proof hooks, map helpers.
package/LICENSE ADDED
@@ -0,0 +1,6 @@
1
+ Copyright (c) 2026 Sansa Group AB
2
+
3
+ All rights reserved, Sansa Group AB. Licence terms pending owner and legal review.
4
+
5
+ No licence is granted to use, copy, modify or distribute this software until
6
+ Sansa Group AB publishes licence terms for it.
package/README.md CHANGED
@@ -1,3 +1,106 @@
1
- # Temporary Holding Version
1
+ # @sansavision/yousaid-react
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ React components and hooks for YouSaid: a feedback launcher, the end user's live
4
+ inbox of replies, and lifecycle receipts. Requires React 19 or later.
5
+
6
+ ```sh
7
+ npm install @sansavision/yousaid-react @sansavision/yousaid-server
8
+ ```
9
+
10
+ `@sansavision/yousaid` (the framework-free client) is installed with it.
11
+ `@sansavision/yousaid-server` runs on your server only and signs the end user's
12
+ identity.
13
+
14
+ ## 1. Mint an identity token on your server
15
+
16
+ ```ts
17
+ import { createYouSaidIdentityToken } from "@sansavision/yousaid-server";
18
+
19
+ export async function GET(request: Request) {
20
+ const user = await currentUser(request);
21
+ const token = await createYouSaidIdentityToken(
22
+ { sub: user.id, org_id: "org_...", product_id: "prd_...", email: user.email },
23
+ process.env.YOUSAID_SIGNING_SECRET!,
24
+ { keyId: process.env.YOUSAID_KEY_ID! },
25
+ );
26
+ return new Response(token, { headers: { "cache-control": "no-store" } });
27
+ }
28
+ ```
29
+
30
+ ## 2. Wrap your app in the provider
31
+
32
+ ```tsx
33
+ "use client";
34
+ import { YouSaidProvider, YouSaidLauncher, Inbox } from "@sansavision/yousaid-react";
35
+
36
+ // A function, not a string: every write consumes the token's nonce.
37
+ const getToken = () => fetch("/api/yousaid-token").then((response) => response.text());
38
+
39
+ export function Feedback() {
40
+ return (
41
+ <YouSaidProvider token={getToken}>
42
+ <YouSaidLauncher label="Talk to us" appVersion="4.2.0" />
43
+ <Inbox title="Replies" />
44
+ </YouSaidProvider>
45
+ );
46
+ }
47
+ ```
48
+
49
+ `YouSaidProvider` takes the same options as `YouSaidClient` (`token`, `endpoint`,
50
+ `fetch`). Keep the `token` function stable (define it outside the component or
51
+ wrap it in `useCallback`) so the client is not recreated on every render.
52
+
53
+ ## Components and hooks
54
+
55
+ | Export | What it does |
56
+ | --- | --- |
57
+ | `YouSaidProvider` | Creates one `YouSaidClient` for the tree. |
58
+ | `useYouSaid()` | Returns that client, for example to call `sendSignal` or `confirmRelease` from your own UI. Throws outside the provider. |
59
+ | `YouSaidLauncher` | A floating "Talk to us" button and form: message kind, attachments and an opt-in diagnostics checkbox. Props: `label`, `defaultView`, `appVersion`, `featureFlags`, `breadcrumbs`, `verifyInstall` (default true). |
60
+ | `Inbox` | The signed-in end user's replies, live over Server-Sent Events, with unread counts and mark-read. Props: `title`, `emptyMessage`, `onOpen(item)`. |
61
+ | `useInbox({ live, limit })` | The same data headless: `{ items, unread, loading, connected, error, refresh, markRead }`. |
62
+ | `LifecycleReceipt` | A `role="status"` receipt that tells the user where their report is. Props: `title`, `state`. |
63
+
64
+ ```tsx
65
+ import { LifecycleReceipt, useInbox, useYouSaid } from "@sansavision/yousaid-react";
66
+
67
+ function ReleaseQuestion({ releaseId }: { releaseId: string }) {
68
+ const client = useYouSaid();
69
+ return <button onClick={() => void client.confirmRelease(releaseId, "resolved")}>It works now</button>;
70
+ }
71
+
72
+ function UnreadBadge() {
73
+ const { unread } = useInbox({ live: true });
74
+ return unread ? <span aria-label={`${unread} unread replies`}>{unread}</span> : null;
75
+ }
76
+
77
+ <LifecycleReceipt title="Report received" state="The team is looking at it." />;
78
+ ```
79
+
80
+ Send AppHelm context with a signal through `useYouSaid().sendSignal({ ..., context: { apphelm: { workspaceId, externalUserId } } })`.
81
+ See the `@sansavision/yousaid` README for the field rules.
82
+
83
+ ## Server rendering
84
+
85
+ Every component renders on the server without touching `window`; the network work
86
+ starts in effects after hydration. The modules carry `"use client"`.
87
+
88
+ ## Stability
89
+
90
+ Version 0.2.0 marks these exports as **stable** under semantic versioning:
91
+ `YouSaidProvider`, `useYouSaid`, `YouSaidLauncher`, `Inbox`, `useInbox` and
92
+ `LifecycleReceipt`.
93
+
94
+ Everything else is **experimental** and tagged `@experimental` in the type
95
+ declarations: `YouSaidRooms` and every Rooms component and hook, agent and
96
+ approval cards, moderation, the Proof widgets (`ProofWall`, `ProofCarousel`,
97
+ `ProofCard`, `ProofBadge`, `ProofMap`, `ProofMarquee`, `ProofVideoBubble`,
98
+ `ProofLogoStrip`), `ProofPrompt` and the proof hooks, and the map helpers.
99
+ Experimental APIs can change in any minor release.
100
+
101
+ ## Licence
102
+
103
+ `UNLICENSED`. All rights reserved, Sansa Group AB. Licence terms are pending
104
+ owner and legal review; see LICENSE.
105
+
106
+ Documentation: https://yousaid.dev/docs/sdk
@@ -0,0 +1,7 @@
1
+ import { type ReactNode } from "react";
2
+ import { YouSaidClient, type YouSaidClientOptions } from "@sansavision/yousaid";
3
+ export declare function YouSaidProvider({ children, ...options }: YouSaidClientOptions & {
4
+ children: ReactNode;
5
+ }): import("react").JSX.Element;
6
+ export declare function useYouSaid(): YouSaidClient;
7
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAIhF,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,GAAG,OAAO,EACX,EAAE,oBAAoB,GAAG;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,+BAQhD;AAED,wBAAgB,UAAU,IAAI,aAAa,CAK1C"}
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext, useMemo } from "react";
4
+ import { YouSaidClient } from "@sansavision/yousaid";
5
+ const YouSaidContext = createContext(null);
6
+ export function YouSaidProvider({ children, ...options }) {
7
+ const client = useMemo(() => new YouSaidClient(options), [options.endpoint, options.fetch, options.token]);
8
+ return (_jsx(YouSaidContext.Provider, { value: client, children: children }));
9
+ }
10
+ export function useYouSaid() {
11
+ const client = useContext(YouSaidContext);
12
+ if (!client)
13
+ throw new Error("useYouSaid must be used inside YouSaidProvider.");
14
+ return client;
15
+ }
@@ -0,0 +1,107 @@
1
+ import { type ReactNode } from "react";
2
+ import { type DiagnosticsCapsule, type InboxItem, type RoomDetail, type RoomSummary } from "@sansavision/yousaid";
3
+ export { YouSaidProvider, useYouSaid } from "./context.js";
4
+ export { AgentMentionMenu, canvasEntries, DEFAULT_CANVAS_LABELS, DEFAULT_MENTION_AGENTS, filterAgents, mentionMenuKey, RequestHumanButton, RoomCanvas, roomAgentStyles, useAgentRun, usePendingApprovals, useRequestHuman, useRoomCanvas, useRoomEvents, useRoomMembers, type CanvasEntry, type MentionAgent, } from "./rooms.js";
5
+ export declare function YouSaidLauncher({ label, defaultView, appVersion, featureFlags, breadcrumbs, verifyInstall, }: {
6
+ label?: string;
7
+ defaultView?: "feedback" | "rooms";
8
+ /** Included in the diagnostic capsule only when the user opts in. */
9
+ appVersion?: string;
10
+ featureFlags?: string[];
11
+ breadcrumbs?: DiagnosticsCapsule["breadcrumbs"];
12
+ /** Report SDK installation health once per page load (used by onboarding). */
13
+ verifyInstall?: boolean;
14
+ }): import("react").JSX.Element;
15
+ /**
16
+ * Live in-app inbox for the signed-in end user: loads the latest items, keeps
17
+ * a Server-Sent Events stream open (with backoff reconnects), and marks items read.
18
+ */
19
+ export declare function useInbox(options?: {
20
+ live?: boolean;
21
+ limit?: number;
22
+ }): {
23
+ items: InboxItem[];
24
+ unread: number;
25
+ loading: boolean;
26
+ connected: boolean;
27
+ error: string;
28
+ refresh: () => Promise<void>;
29
+ markRead: (ids?: string[]) => Promise<void>;
30
+ };
31
+ export declare function Inbox({ title, emptyMessage, onOpen }: {
32
+ title?: string;
33
+ emptyMessage?: string;
34
+ onOpen?: (item: InboxItem) => void;
35
+ }): import("react").JSX.Element;
36
+ /** @experimental */
37
+ export declare function useRooms(): {
38
+ rooms: RoomSummary[];
39
+ loading: boolean;
40
+ error: string;
41
+ refresh: () => Promise<void>;
42
+ };
43
+ /** @experimental */
44
+ export declare function useRoom(roomId: string | null): {
45
+ room: RoomDetail | null;
46
+ loading: boolean;
47
+ error: string;
48
+ refresh: () => Promise<void>;
49
+ };
50
+ /** @experimental */
51
+ export declare function useRoomComposer(roomId: string | null, onSent?: () => void | Promise<void>): {
52
+ send: (body: string) => Promise<boolean>;
53
+ pending: boolean;
54
+ error: string;
55
+ };
56
+ /** @experimental */
57
+ export declare function YouSaidRooms({ embedded, initialRoomId, onSolveSession, }: {
58
+ embedded?: boolean;
59
+ initialRoomId?: string | null;
60
+ onSolveSession?: (session: {
61
+ authToken: string;
62
+ mode: "audio" | "video" | "screen_share";
63
+ }) => void;
64
+ }): import("react").JSX.Element;
65
+ /** @experimental */
66
+ export declare function RoomsList({ rooms, selectedId, onSelect, }: {
67
+ rooms: RoomSummary[];
68
+ selectedId?: string | null;
69
+ onSelect: (roomId: string) => void;
70
+ }): import("react").JSX.Element;
71
+ /** @experimental */
72
+ export declare function RoomView({ detail, onRefresh, onSolveSession, }: {
73
+ detail: RoomDetail;
74
+ onRefresh: () => void | Promise<void>;
75
+ onSolveSession?: (session: {
76
+ authToken: string;
77
+ mode: "audio" | "video" | "screen_share";
78
+ }) => void;
79
+ }): import("react").JSX.Element;
80
+ /** @experimental */
81
+ export declare function RoomComposer({ roomId, onSent, }: {
82
+ roomId: string;
83
+ onSent?: () => void | Promise<void>;
84
+ }): import("react").JSX.Element;
85
+ /** @experimental */
86
+ export declare function AgentActionCard({ state, children, }: {
87
+ state: "drafted" | "approval_needed" | "completed";
88
+ children: ReactNode;
89
+ }): import("react").JSX.Element;
90
+ /** @experimental */
91
+ export declare function ApprovalCard({ summary, onApprove, onReject, }: {
92
+ summary: string;
93
+ onApprove: () => void;
94
+ onReject: () => void;
95
+ }): import("react").JSX.Element;
96
+ export declare function LifecycleReceipt({ title, state, }: {
97
+ title: string;
98
+ state: string;
99
+ }): import("react").JSX.Element;
100
+ export * from "./proof.js";
101
+ export { ProofPromptView, useProofPrompt, type ProofPromptOptions, type ProofPromptProps, type ProofPromptState } from "./proof-prompt.js";
102
+ /**
103
+ * Native in-app Proof prompt using the provider's signed identity. See ProofPromptView for props.
104
+ * @experimental
105
+ */
106
+ export declare function ProofPrompt(props: Omit<import("./proof-prompt.js").ProofPromptProps, "client">): import("react").JSX.Element;
107
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}