@usereq/widget 0.1.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/README.md +166 -0
- package/dist/widget.css +2 -0
- package/dist/widget.js +3569 -0
- package/package.json +98 -0
- package/src/chat-widget/chat-widget-appearance.ts +55 -0
- package/src/chat-widget/chat-widget-defaults.tsx +45 -0
- package/src/chat-widget/components/chat-widget-frame.tsx +56 -0
- package/src/chat-widget/components/chat-widget-layout.ts +6 -0
- package/src/chat-widget/components/chat-widget-primitives.tsx +720 -0
- package/src/chat-widget/components/confirmation.tsx +155 -0
- package/src/chat-widget/components/conversation.tsx +110 -0
- package/src/chat-widget/components/message.tsx +325 -0
- package/src/chat-widget/index.ts +9 -0
- package/src/chat-widget/stop-confirmation.ts +288 -0
- package/src/chat-widget/styles/chat-widget-box.tsx +258 -0
- package/src/chat-widget/styles/chat-widget-bubble.tsx +238 -0
- package/src/chat-widget/styles/chat-widget-chatbar.tsx +248 -0
- package/src/custom-element/agent-widget-element.tsx +584 -0
- package/src/embed.ts +8 -0
- package/src/index.ts +10 -0
- package/src/register.ts +15 -0
- package/src/renderer/index.ts +6 -0
- package/src/renderer/widget-runtime.tsx +205 -0
- package/src/runtime/analytics.ts +327 -0
- package/src/runtime/api-origin.ts +29 -0
- package/src/runtime/api.ts +151 -0
- package/src/runtime/bootstrap.ts +309 -0
- package/src/runtime/messages.ts +12 -0
- package/src/runtime/session-storage.ts +32 -0
- package/src/runtime/token-renewal.ts +13 -0
- package/src/runtime/trigger-rule.ts +182 -0
- package/src/shared/analytics.ts +54 -0
- package/src/shared/shadow-css.ts +15 -0
- package/src/shared/shadow-theme.ts +85 -0
- package/src/shared/stop-confirmation.ts +20 -0
- package/src/shared/widget-config.ts +104 -0
- package/src/styles/widget.css.ts +27 -0
- package/src/types.ts +85 -0
- package/src/vite-env.d.ts +4 -0
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@usereq/widget",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./src/index.ts",
|
|
10
|
+
"import": "./src/index.ts",
|
|
11
|
+
"default": "./src/index.ts"
|
|
12
|
+
},
|
|
13
|
+
"./types": {
|
|
14
|
+
"types": "./src/types.ts",
|
|
15
|
+
"import": "./src/types.ts",
|
|
16
|
+
"default": "./src/types.ts"
|
|
17
|
+
},
|
|
18
|
+
"./renderer": {
|
|
19
|
+
"types": "./src/renderer/index.ts",
|
|
20
|
+
"import": "./src/renderer/index.ts",
|
|
21
|
+
"default": "./src/renderer/index.ts"
|
|
22
|
+
},
|
|
23
|
+
"./shared/widget-config": {
|
|
24
|
+
"types": "./src/shared/widget-config.ts",
|
|
25
|
+
"import": "./src/shared/widget-config.ts",
|
|
26
|
+
"default": "./src/shared/widget-config.ts"
|
|
27
|
+
},
|
|
28
|
+
"./shared/analytics": {
|
|
29
|
+
"types": "./src/shared/analytics.ts",
|
|
30
|
+
"import": "./src/shared/analytics.ts",
|
|
31
|
+
"default": "./src/shared/analytics.ts"
|
|
32
|
+
},
|
|
33
|
+
"./shared/shadow-css": {
|
|
34
|
+
"types": "./src/shared/shadow-css.ts",
|
|
35
|
+
"import": "./src/shared/shadow-css.ts",
|
|
36
|
+
"default": "./src/shared/shadow-css.ts"
|
|
37
|
+
},
|
|
38
|
+
"./shared/stop-confirmation": {
|
|
39
|
+
"types": "./src/shared/stop-confirmation.ts",
|
|
40
|
+
"import": "./src/shared/stop-confirmation.ts",
|
|
41
|
+
"default": "./src/shared/stop-confirmation.ts"
|
|
42
|
+
},
|
|
43
|
+
"./register": {
|
|
44
|
+
"types": "./src/register.ts",
|
|
45
|
+
"import": "./src/register.ts",
|
|
46
|
+
"default": "./src/register.ts"
|
|
47
|
+
},
|
|
48
|
+
"./runtime/*": {
|
|
49
|
+
"types": "./src/runtime/*.ts",
|
|
50
|
+
"import": "./src/runtime/*.ts",
|
|
51
|
+
"default": "./src/runtime/*.ts"
|
|
52
|
+
},
|
|
53
|
+
"./custom-element/*": {
|
|
54
|
+
"types": "./src/custom-element/*.tsx",
|
|
55
|
+
"import": "./src/custom-element/*.tsx",
|
|
56
|
+
"default": "./src/custom-element/*.tsx"
|
|
57
|
+
},
|
|
58
|
+
"./embed": "./dist/widget.js"
|
|
59
|
+
},
|
|
60
|
+
"files": [
|
|
61
|
+
"src",
|
|
62
|
+
"dist",
|
|
63
|
+
"README.md"
|
|
64
|
+
],
|
|
65
|
+
"unpkg": "./dist/widget.js",
|
|
66
|
+
"jsdelivr": "./dist/widget.js",
|
|
67
|
+
"publishConfig": {
|
|
68
|
+
"access": "public"
|
|
69
|
+
},
|
|
70
|
+
"packageManager": "bun@1.2.22",
|
|
71
|
+
"scripts": {
|
|
72
|
+
"build:core": "bunx tsc -p tsconfig.json --noEmit",
|
|
73
|
+
"build:embed": "vite build",
|
|
74
|
+
"build": "bun run build:core && bun run build:embed",
|
|
75
|
+
"typecheck": "bunx tsc -p tsconfig.json --noEmit"
|
|
76
|
+
},
|
|
77
|
+
"dependencies": {
|
|
78
|
+
"@streamdown/mermaid": "^1.0.2",
|
|
79
|
+
"@usereq/ui": "latest",
|
|
80
|
+
"lucide-react": "^0.553.0",
|
|
81
|
+
"motion": "^12.23.24",
|
|
82
|
+
"react": "^19.2.0",
|
|
83
|
+
"react-dom": "^19.2.0",
|
|
84
|
+
"react-markdown": "^10.1.0",
|
|
85
|
+
"remark-gfm": "^4.0.1",
|
|
86
|
+
"streamdown": "^2.5.0",
|
|
87
|
+
"use-stick-to-bottom": "^1.1.3"
|
|
88
|
+
},
|
|
89
|
+
"devDependencies": {
|
|
90
|
+
"@tailwindcss/postcss": "^4.2.3",
|
|
91
|
+
"@types/react": "^19.2.2",
|
|
92
|
+
"@types/react-dom": "^19.2.2",
|
|
93
|
+
"esbuild": "^0.28.0",
|
|
94
|
+
"tailwindcss": "^4.2.3",
|
|
95
|
+
"typescript": "^5.9.3",
|
|
96
|
+
"vite": "^8.0.3"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
|
|
3
|
+
export type ChatWidgetAppearance = {
|
|
4
|
+
avatarOrbColor1?: string | null;
|
|
5
|
+
avatarOrbColor2?: string | null;
|
|
6
|
+
actionText?: string | null;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type ResolvedChatWidgetAppearance = Required<ChatWidgetAppearance>;
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_CHAT_WIDGET_APPEARANCE: ResolvedChatWidgetAppearance = {
|
|
12
|
+
avatarOrbColor1: "#2563eb",
|
|
13
|
+
avatarOrbColor2: "#60a5fa",
|
|
14
|
+
actionText: "Need help?",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function resolveChatWidgetAppearance(
|
|
18
|
+
appearance?: Partial<ChatWidgetAppearance> | null,
|
|
19
|
+
): ResolvedChatWidgetAppearance {
|
|
20
|
+
return {
|
|
21
|
+
avatarOrbColor1:
|
|
22
|
+
normalizeString(appearance?.avatarOrbColor1) ??
|
|
23
|
+
DEFAULT_CHAT_WIDGET_APPEARANCE.avatarOrbColor1,
|
|
24
|
+
avatarOrbColor2:
|
|
25
|
+
normalizeString(appearance?.avatarOrbColor2) ??
|
|
26
|
+
DEFAULT_CHAT_WIDGET_APPEARANCE.avatarOrbColor2,
|
|
27
|
+
actionText:
|
|
28
|
+
normalizeString(appearance?.actionText) ??
|
|
29
|
+
DEFAULT_CHAT_WIDGET_APPEARANCE.actionText,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function getChatWidgetGradientStyle(
|
|
34
|
+
appearance?: Partial<ChatWidgetAppearance> | null,
|
|
35
|
+
): CSSProperties {
|
|
36
|
+
const resolved = resolveChatWidgetAppearance(appearance);
|
|
37
|
+
return {
|
|
38
|
+
background: `linear-gradient(135deg, ${resolved.avatarOrbColor1}, ${resolved.avatarOrbColor2})`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function getChatWidgetAvatarStyle(
|
|
43
|
+
appearance?: Partial<ChatWidgetAppearance> | null,
|
|
44
|
+
): CSSProperties {
|
|
45
|
+
const resolved = resolveChatWidgetAppearance(appearance);
|
|
46
|
+
return {
|
|
47
|
+
background: `linear-gradient(135deg, ${resolved.avatarOrbColor1}, ${resolved.avatarOrbColor2})`,
|
|
48
|
+
boxShadow: `0 10px 24px color-mix(in srgb, ${resolved.avatarOrbColor1} 22%, transparent)`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function normalizeString(value: string | null | undefined): string | null {
|
|
53
|
+
const trimmed = value?.trim();
|
|
54
|
+
return trimmed ? trimmed : null;
|
|
55
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default values for the chat widget when database / agent config is not set.
|
|
3
|
+
* Central place to manage all static default states.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Default rotating spotlight messages used by closed-state widget surfaces. */
|
|
7
|
+
export const DEFAULT_SPOTLIGHT_MESSAGES = [
|
|
8
|
+
"Ask me anything…",
|
|
9
|
+
"How can I help you today?",
|
|
10
|
+
"Try: What can you do?",
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
/** Default first message from the agent when welcome copy is shown in the open widget. */
|
|
14
|
+
export const DEFAULT_WELCOME_MESSAGE = "Hello! How can I help you today?";
|
|
15
|
+
|
|
16
|
+
/** Default agent name when not set (e.g. ChatWidgetBox closed state). */
|
|
17
|
+
export const DEFAULT_AGENT_NAME_BOX = "Need help?";
|
|
18
|
+
|
|
19
|
+
/** Default agent name for Bubble launcher. */
|
|
20
|
+
export const DEFAULT_AGENT_NAME_BUBBLE = "Assistant";
|
|
21
|
+
|
|
22
|
+
/** Default agent name for ChatBar. */
|
|
23
|
+
export const DEFAULT_AGENT_NAME_CHATBAR = "Mana";
|
|
24
|
+
|
|
25
|
+
/** Default label for "Start chat" button (Box closed card). */
|
|
26
|
+
export const DEFAULT_START_CHAT_LABEL = "Start chat";
|
|
27
|
+
|
|
28
|
+
/** Default label for the open empty-state CTA. */
|
|
29
|
+
export const DEFAULT_START_CONVERSATION_LABEL = "Start a new conversation";
|
|
30
|
+
|
|
31
|
+
/** Default label on the ChatBar pill when closed. */
|
|
32
|
+
export const DEFAULT_LAUNCHER_LABEL = "Ask";
|
|
33
|
+
|
|
34
|
+
/** Default composer input placeholder. */
|
|
35
|
+
export const DEFAULT_COMPOSER_PLACEHOLDER = "Ask anything…";
|
|
36
|
+
|
|
37
|
+
/** Default "Powered by" text in the widget footer. */
|
|
38
|
+
export const DEFAULT_POWERED_BY = "Powered by UserEQ";
|
|
39
|
+
|
|
40
|
+
/** Default empty state title when there are no messages. */
|
|
41
|
+
export const DEFAULT_EMPTY_TITLE = "No conversation started";
|
|
42
|
+
|
|
43
|
+
/** Default empty state description. */
|
|
44
|
+
export const DEFAULT_EMPTY_DESCRIPTION =
|
|
45
|
+
"Start a new conversation to get started.";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "@usereq/ui/lib/utils";
|
|
5
|
+
|
|
6
|
+
/** Widget position anchor (mirrors server enum values). */
|
|
7
|
+
export type WidgetAnchor =
|
|
8
|
+
| "TOP_LEFT"
|
|
9
|
+
| "TOP_CENTER"
|
|
10
|
+
| "TOP_RIGHT"
|
|
11
|
+
| "BOTTOM_LEFT"
|
|
12
|
+
| "BOTTOM_CENTER"
|
|
13
|
+
| "BOTTOM_RIGHT";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Builds Tailwind classes for the widget anchor from DB WidgetAnchor.
|
|
17
|
+
* Used so the widget renders in the correct position (user-configurable in playground).
|
|
18
|
+
* Side anchors use min-w-[320px] so chatbar doesn't shrink when on left/right.
|
|
19
|
+
*/
|
|
20
|
+
const WIDGET_ANCHOR_CLASSES: Record<WidgetAnchor, string> = {
|
|
21
|
+
TOP_LEFT: "absolute top-8 left-8 min-w-[320px]",
|
|
22
|
+
TOP_CENTER:
|
|
23
|
+
"absolute top-8 left-1/2 w-full -translate-x-1/2 px-6 flex justify-center",
|
|
24
|
+
TOP_RIGHT: "absolute top-8 right-8 min-w-[320px]",
|
|
25
|
+
BOTTOM_LEFT: "absolute bottom-8 left-8 min-w-[320px]",
|
|
26
|
+
BOTTOM_CENTER:
|
|
27
|
+
"absolute bottom-10 left-1/2 w-full -translate-x-1/2 px-6 flex justify-center",
|
|
28
|
+
BOTTOM_RIGHT: "absolute bottom-8 right-8 min-w-[320px]",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function ChatWidgetPreviewStage({
|
|
32
|
+
children,
|
|
33
|
+
className,
|
|
34
|
+
anchor = "BOTTOM_RIGHT",
|
|
35
|
+
}: {
|
|
36
|
+
children: React.ReactNode;
|
|
37
|
+
className?: string;
|
|
38
|
+
/** Widget position from DB (agent.anchor). User can update in playground. */
|
|
39
|
+
anchor?: WidgetAnchor;
|
|
40
|
+
}) {
|
|
41
|
+
const anchorClasses =
|
|
42
|
+
WIDGET_ANCHOR_CLASSES[anchor] ?? WIDGET_ANCHOR_CLASSES.BOTTOM_RIGHT;
|
|
43
|
+
return (
|
|
44
|
+
<div
|
|
45
|
+
className={cn(
|
|
46
|
+
"relative flex min-h-[620px] w-full items-center justify-center overflow-hidden rounded-2xl border bg-linear-to-b from-muted/20 to-muted/5 p-6",
|
|
47
|
+
className
|
|
48
|
+
)}
|
|
49
|
+
>
|
|
50
|
+
<div data-chat-widget-anchor={anchor} className={anchorClasses}>
|
|
51
|
+
{children}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|