@uraiagent/react 0.0.3 → 0.0.5

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 CHANGED
@@ -15,15 +15,15 @@ npm install @uraiagent/react
15
15
 
16
16
  ## Usage (React)
17
17
 
18
- Wrap the widget in `<Root>` and pass a single grouped `config` object. `identity`
19
- and `connection` are required; everything else is optional.
18
+ Render the single `<AgentWidget>` component and pass a grouped `config` object.
19
+ `identity` and `connection` are required; everything else is optional.
20
20
 
21
21
  ```tsx
22
- import { Root, AgentWidget } from "@uraiagent/react";
22
+ import { AgentWidget } from "@uraiagent/react";
23
23
 
24
24
  export default function Agent() {
25
25
  return (
26
- <Root
26
+ <AgentWidget
27
27
  config={{
28
28
  identity: {
29
29
  token: "your_widget_token",
@@ -41,6 +41,10 @@ export default function Agent() {
41
41
  defaultOpen: false,
42
42
  language: "en",
43
43
  },
44
+ design: {
45
+ colors: { primary: "#6d28d9" },
46
+ radius: 16,
47
+ },
44
48
  people: {
45
49
  agent: { name: "AI Bot" },
46
50
  user: { name: "John Doe", email: "john@example.com" },
@@ -54,9 +58,7 @@ export default function Agent() {
54
58
  },
55
59
  },
56
60
  }}
57
- >
58
- <AgentWidget />
59
- </Root>
61
+ />
60
62
  );
61
63
  }
62
64
  ```
@@ -65,12 +67,13 @@ export default function Agent() {
65
67
 
66
68
  | Export | Description |
67
69
  | --- | --- |
68
- | `Root` | Context provider + host container. Takes `config` and renders `children`. |
69
- | `AgentWidget` | The chat UI (trigger button + panel). Render inside `<Root>`. |
70
+ | `AgentWidget` | The widget one self-contained component. Takes `config`; renders the launcher + chat panel. |
71
+ | `AgentProvider`, `useAgent` | Optional host-app SDK: visitor activity capture + imperative API (`identify`, `track`, `open`…). |
70
72
  | `AgentMessage`, `AgentMessageWrapper` | Building blocks for custom message components. |
71
- | `WidgetConfig` | TypeScript type for the `config` prop. |
73
+ | `WidgetConfig`, `WidgetDesign` | TypeScript types for the `config` prop and its typed design/branding. |
72
74
 
73
- Peer dependencies: `react`, `react-dom`, `framer-motion`, `postcss`.
75
+ Peer dependencies: `react` and `react-dom` (>=18). Everything else, including
76
+ `framer-motion`, is bundled — no extra installs or stylesheet imports.
74
77
 
75
78
  ---
76
79
 
@@ -0,0 +1,19 @@
1
+ import { WidgetConfig } from './interfaces/config';
2
+ export type AgentWidgetProps = {
3
+ /** The full grouped widget configuration. */
4
+ config: WidgetConfig;
5
+ };
6
+ /**
7
+ * The widget — one self-contained component.
8
+ *
9
+ * Drop it anywhere in your React tree with a `config` and you get the launcher
10
+ * plus chat panel, fully wired: context providers, realtime, identity, and the
11
+ * imperative SDK controls. This is the only component you need to render:
12
+ *
13
+ * ```tsx
14
+ * import { AgentWidget } from "@uraiagent/react";
15
+ *
16
+ * <AgentWidget config={{ identity: { token: "…" }, connection: {} }} />
17
+ * ```
18
+ */
19
+ export declare function AgentWidget({ config }: AgentWidgetProps): import("react/jsx-runtime").JSX.Element;
package/dist/Root.d.ts CHANGED
@@ -4,5 +4,5 @@ type RootProps = {
4
4
  children: React.ReactNode;
5
5
  config: WidgetConfig;
6
6
  };
7
- declare function Root({ children, config }: RootProps): import("react/jsx-runtime").JSX.Element;
7
+ declare function Root({ children, config }: RootProps): import("react/jsx-runtime").JSX.Element | null;
8
8
  export default Root;
package/dist/Widget.d.ts CHANGED
@@ -1 +1,6 @@
1
- export declare function AgentWidget(): import("react/jsx-runtime").JSX.Element;
1
+ /**
2
+ * The widget's UI shell — launcher trigger + chat panel. Internal: it must render
3
+ * inside the providers set up by `Root`. Consumers use the unified `AgentWidget`
4
+ * (which composes `Root` + this) instead of rendering it directly.
5
+ */
6
+ export declare function WidgetShell(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,33 @@
1
+ import { ReactNode } from 'react';
2
+ import { StoredIdentity } from './identity.storage';
3
+ /** Fields a caller (props, gate, or SDK `identify`) can set on the visitor. */
4
+ export type IdentityPatch = {
5
+ name?: string;
6
+ email?: string;
7
+ phone?: string;
8
+ userHash?: string;
9
+ custom?: Record<string, string>;
10
+ };
11
+ export type ResolvedIdentity = {
12
+ name?: string;
13
+ email?: string;
14
+ phone?: string;
15
+ userHash?: string;
16
+ custom?: Record<string, string>;
17
+ verified: boolean;
18
+ };
19
+ type IdentityContextType = {
20
+ visitorId: string;
21
+ identity: ResolvedIdentity;
22
+ /** True once we have an email (from props or the gate). */
23
+ isKnown: boolean;
24
+ lastConversationId?: string;
25
+ /** Merge + persist an identity patch (used by the gate and SDK identify). */
26
+ setIdentity: (patch: IdentityPatch) => StoredIdentity;
27
+ setLastConversationId: (id: string | undefined) => void;
28
+ };
29
+ export declare function IdentityProvider({ children }: {
30
+ children: ReactNode;
31
+ }): import("react/jsx-runtime").JSX.Element;
32
+ export declare function useIdentity(): IdentityContextType;
33
+ export {};
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Persistent visitor identity, stored in localStorage. This replaces the old
3
+ * single-session cookie as the widget's source of identity. A `visitorId` is
4
+ * minted once and never rotated client-side; it anchors conversation listing
5
+ * and activity even before an email is known (anonymous → identified → verified).
6
+ */
7
+ export interface StoredIdentity {
8
+ v: 1;
9
+ /** Stable anonymous visitor handle (nanoid). Minted once. */
10
+ visitorId: string;
11
+ /** Identity-verification hash supplied by the host app (HMAC). */
12
+ userHash?: string;
13
+ /** Set true once the backend confirms `userHash`. */
14
+ verified?: boolean;
15
+ name?: string;
16
+ email?: string;
17
+ phone?: string;
18
+ custom?: Record<string, string>;
19
+ /** Pointer to the most recent conversation, for resume. */
20
+ lastConversationId?: string;
21
+ /** ISO timestamp of the last write. */
22
+ updatedAt: string;
23
+ }
24
+ /** Subscribe to identity changes. Returns an unsubscribe fn. */
25
+ export declare function subscribeIdentity(listener: (identity: StoredIdentity) => void): () => void;
26
+ /** Read the stored identity, minting + persisting a fresh one on first use. */
27
+ export declare function readIdentity(): StoredIdentity;
28
+ /** Overwrite the stored identity. */
29
+ export declare function writeIdentity(identity: StoredIdentity): void;
30
+ /** Shallow-merge a patch into the stored identity and return the result. */
31
+ export declare function mergeIdentity(patch: Partial<Omit<StoredIdentity, "v" | "visitorId" | "updatedAt">>): StoredIdentity;
32
+ /** One-time migration: adopt a legacy `uraiagent-session` cookie as lastConversationId. */
33
+ export declare function migrateLegacyCookie(): void;
@@ -0,0 +1,3 @@
1
+ export { IdentityProvider, useIdentity } from './IdentityContext';
2
+ export type { IdentityPatch, ResolvedIdentity } from './IdentityContext';
3
+ export type { StoredIdentity } from './identity.storage';
@@ -29,13 +29,52 @@ export interface CreateSessionOptions {
29
29
  organizationId: string;
30
30
  agentId: string;
31
31
  agentName?: string;
32
+ /** Stable anonymous visitor handle; links the conversation to a durable contact. */
33
+ visitorId?: string;
34
+ /** Identity-verification hash (HMAC) computed on the host's server. */
35
+ userHash?: string;
32
36
  user?: {
33
37
  name?: string;
34
38
  email?: string;
35
39
  phone?: string;
40
+ custom?: Record<string, string>;
36
41
  };
37
42
  }
43
+ /** A visitor's conversation as summarized for the Home / conversations list. */
44
+ export interface ConversationSummary {
45
+ sessionId: string;
46
+ conversationId: string;
47
+ state: "active" | "resolved" | "archived";
48
+ lastMessage?: {
49
+ text: string;
50
+ from: "agent" | "user" | "event";
51
+ at: string;
52
+ };
53
+ unread?: number;
54
+ agent?: {
55
+ name?: string;
56
+ logo?: string;
57
+ };
58
+ updatedAt: string;
59
+ }
60
+ export interface ListConversationsResponse {
61
+ items: ConversationSummary[];
62
+ total: number;
63
+ page: number;
64
+ limit: number;
65
+ }
38
66
  export declare function createSession(api: string, widgetToken: string, options: CreateSessionOptions): Promise<SessionResponse>;
67
+ /**
68
+ * List the conversations belonging to a visitor (or contact). Best-effort — the
69
+ * caller treats a failure as "no history yet" so the widget still works before
70
+ * the backend endpoint exists.
71
+ */
72
+ export declare function listConversations(api: string, organizationId: string, params: {
73
+ visitorId?: string;
74
+ contactId?: string;
75
+ page?: number;
76
+ limit?: number;
77
+ }): Promise<ListConversationsResponse>;
39
78
  export declare function loadSession(api: string, sessionId: string, widgetToken: string, organizationId: string): Promise<SessionHistoryResponse>;
40
79
  export interface SendMessageOptions {
41
80
  headers?: Record<string, string>;
@@ -1,5 +1,6 @@
1
1
  export * from './useAsyncFn.ts';
2
2
  export * from './useAudioRecord.ts';
3
+ export * from './useAutosizeTextArea';
3
4
  export * from './useMountedState';
4
5
  export * from './useScrollTo';
5
6
  export * from './useToggle';
@@ -0,0 +1,7 @@
1
+ import { RefObject } from 'react';
2
+ type AutosizeOptions = {
3
+ minRows?: number;
4
+ maxRows?: number;
5
+ };
6
+ export declare function useAutosizeTextArea(ref: RefObject<HTMLTextAreaElement | null>, value: string, { minRows, maxRows }?: AutosizeOptions): void;
7
+ export {};
@@ -0,0 +1,21 @@
1
+ import { OptionsProps } from '../interfaces/config';
2
+ export type ResolvedConfig = {
3
+ /** Options with `organizationId`/`design` filled in from the remote config. */
4
+ options: OptionsProps;
5
+ /**
6
+ * Whether the config lookup has settled. Stays `false` while the remote `/chat/config`
7
+ * lookup is in flight so the widget doesn't flash before it binds. Settling does NOT imply
8
+ * a usable config — the caller must also check that `options.organizationId` is present.
9
+ */
10
+ ready: boolean;
11
+ };
12
+ /**
13
+ * Resolves the widget's binding (organizationId/design) from its embed token via
14
+ * `GET /chat/config`, so the host only has to supply a `token`. Values passed explicitly in
15
+ * props win over the remote copy. Gates rendering until the lookup settles.
16
+ *
17
+ * Fails CLOSED: if the lookup errors or the token is unknown, no `organizationId` is resolved and
18
+ * the widget won't render (unless props supplied one). If there's no token at all, we resolve
19
+ * immediately from props (back-compat for fully-specified configs).
20
+ */
21
+ export declare function useResolvedConfig(base: OptionsProps): ResolvedConfig;