@elevasis/ui 2.53.0 → 2.54.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.
@@ -126,6 +126,22 @@ interface PublicAgentChatConnectionState {
126
126
  error: string | null;
127
127
  }
128
128
 
129
+ /**
130
+ * Context passed to the `renderIntro` render-prop. Provides the start action,
131
+ * loading state, resolved display strings, raw branding, and the agent slug.
132
+ */
133
+ interface PublicAgentIntroRenderContext {
134
+ /** Begins the authorize → session flow (the same action the default CTA runs). */
135
+ start: () => void;
136
+ /** True while a session is being created — disable the button / show a spinner. */
137
+ starting: boolean;
138
+ /** Resolved display strings (prop/branding-derived), provided for convenience. */
139
+ title: string;
140
+ subtitle?: string;
141
+ /** Raw grant branding record, so a custom intro can still read intro/instructions/etc. if it wants. */
142
+ branding: Record<string, unknown>;
143
+ slug: string;
144
+ }
129
145
  interface PublicAgentChatProps {
130
146
  apiUrl: string;
131
147
  slug: string;
@@ -142,8 +158,16 @@ interface PublicAgentChatProps {
142
158
  * a specific public agent.
143
159
  */
144
160
  showAgentActivity?: boolean;
161
+ /**
162
+ * Render the entire pre-session intro screen yourself. When provided, this fully
163
+ * replaces the default branding-driven intro panel (paragraph + instructions + CTA).
164
+ * Compose any header/headline, body, styled callouts (e.g. a yellow Alert), and one or
165
+ * more buttons; wire your button(s) to `ctx.start()`. When omitted, the default
166
+ * branding-driven intro renders unchanged.
167
+ */
168
+ renderIntro?: (ctx: PublicAgentIntroRenderContext) => React.ReactNode;
145
169
  }
146
- declare function PublicAgentChat({ apiUrl, slug, visitorId, metadata, title, className, style, onSessionReady, showAgentActivity }: PublicAgentChatProps): react_jsx_runtime.JSX.Element;
170
+ declare function PublicAgentChat({ apiUrl, slug, visitorId, metadata, title, className, style, onSessionReady, showAgentActivity, renderIntro }: PublicAgentChatProps): react_jsx_runtime.JSX.Element;
147
171
 
148
172
  interface PublicAgentChatRoutePageProps extends PublicAgentChatProps {
149
173
  pageStyle?: React.CSSProperties;
@@ -172,4 +196,4 @@ declare const publicAgentChatKeys: {
172
196
  };
173
197
 
174
198
  export { PublicAgentChat, PublicAgentChatRoutePage, publicAgentChatKeys, usePublicAgentChatMessages, usePublicAgentChatWebSocket };
175
- export type { PublicAgentChatAuthorizeResponse, PublicAgentChatConnectionState, PublicAgentChatGrant, PublicAgentChatMessagesResponse, PublicAgentChatMetadataResponse, PublicAgentChatProps, PublicAgentChatRoutePageProps, PublicAgentChatSessionResponse };
199
+ export type { PublicAgentChatAuthorizeResponse, PublicAgentChatConnectionState, PublicAgentChatGrant, PublicAgentChatMessagesResponse, PublicAgentChatMetadataResponse, PublicAgentChatProps, PublicAgentChatRoutePageProps, PublicAgentChatSessionResponse, PublicAgentIntroRenderContext };
@@ -386,7 +386,8 @@ function PublicAgentChat({
386
386
  className,
387
387
  style,
388
388
  onSessionReady,
389
- showAgentActivity = false
389
+ showAgentActivity = false,
390
+ renderIntro
390
391
  }) {
391
392
  const [grant, setGrant] = useState(null);
392
393
  const [capabilityToken, setCapabilityToken] = useState(null);
@@ -419,7 +420,7 @@ function PublicAgentChat({
419
420
  setGrant(payload.grant);
420
421
  if (payload.grant.requiresCode) {
421
422
  setStatus("code-required");
422
- } else if (hasIntroContent(payload.grant)) {
423
+ } else if (renderIntro || hasIntroContent(payload.grant)) {
423
424
  setStatus("intro");
424
425
  } else {
425
426
  setStatus("authorizing");
@@ -432,7 +433,7 @@ function PublicAgentChat({
432
433
  return () => {
433
434
  cancelled = true;
434
435
  };
435
- }, [apiUrl, slug]);
436
+ }, [apiUrl, slug, renderIntro]);
436
437
  const startSession = useCallback(
437
438
  async (code) => {
438
439
  if (!grant) return;
@@ -474,12 +475,12 @@ function PublicAgentChat({
474
475
  [apiUrl, grant, metadata, onSessionReady, slug, visitorId]
475
476
  );
476
477
  useEffect(() => {
477
- if (!grant || grant.requiresCode || hasIntroContent(grant) || autoStartedRef.current) {
478
+ if (!grant || grant.requiresCode || renderIntro || hasIntroContent(grant) || autoStartedRef.current) {
478
479
  return;
479
480
  }
480
481
  autoStartedRef.current = true;
481
482
  void startSession();
482
- }, [grant, startSession]);
483
+ }, [grant, startSession, renderIntro]);
483
484
  const allMessages = useMemo(() => {
484
485
  const merged = mergeSessionMessages(historyMessages, liveMessages);
485
486
  const greeting = brandingText(brandingRecord(grant?.branding).greeting);
@@ -501,7 +502,7 @@ function PublicAgentChat({
501
502
  sendMessage(trimmed);
502
503
  setInput("");
503
504
  };
504
- if (status === "loading" || status === "authorizing") {
505
+ if (status === "loading" || status === "authorizing" && !renderIntro) {
505
506
  return /* @__PURE__ */ jsx(
506
507
  PublicAgentChatFrame,
507
508
  {
@@ -567,8 +568,32 @@ function PublicAgentChat({
567
568
  }
568
569
  );
569
570
  }
570
- if (status === "intro" && grant) {
571
+ if ((status === "intro" || renderIntro && status === "authorizing") && grant) {
571
572
  const branding = brandingRecord(grant.branding);
573
+ if (renderIntro) {
574
+ const ctx = {
575
+ start: () => {
576
+ void startSession();
577
+ },
578
+ starting: status === "authorizing",
579
+ title: displayTitle,
580
+ subtitle: displaySubtitle,
581
+ branding,
582
+ slug
583
+ };
584
+ return /* @__PURE__ */ jsx(
585
+ PublicAgentChatFrame,
586
+ {
587
+ className,
588
+ style,
589
+ title: displayTitle,
590
+ subtitle: displaySubtitle,
591
+ statusTone: "ready",
592
+ children: renderIntro(ctx)
593
+ }
594
+ );
595
+ }
596
+ const headlineText = brandingText(branding.headline);
572
597
  const introText = brandingText(branding.intro);
573
598
  const instructions = Array.isArray(branding.instructions) ? branding.instructions.filter((item) => typeof item === "string") : [];
574
599
  const ctaLabel = brandingText(branding.ctaLabel) ?? "Start the conversation";
@@ -593,6 +618,7 @@ function PublicAgentChat({
593
618
  boxShadow: "var(--card-shadow)"
594
619
  },
595
620
  children: /* @__PURE__ */ jsxs(Stack, { gap: "lg", children: [
621
+ headlineText && /* @__PURE__ */ jsx(Title, { order: 2, children: headlineText }),
596
622
  introText && /* @__PURE__ */ jsx(Text, { size: "sm", style: { color: "var(--color-text)", lineHeight: 1.6 }, children: introText }),
597
623
  instructions.length > 0 && /* @__PURE__ */ jsx(List, { size: "sm", style: { color: "var(--color-text-dimmed)" }, children: instructions.map((item, index) => /* @__PURE__ */ jsx(List.Item, { children: item }, index)) }),
598
624
  /* @__PURE__ */ jsx(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/ui",
3
- "version": "2.53.0",
3
+ "version": "2.54.0",
4
4
  "description": "UI components and platform-aware hooks for building custom frontends on the Elevasis platform",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -274,10 +274,10 @@
274
274
  "typescript": "5.9.2",
275
275
  "vite": "^7.0.0",
276
276
  "vitest": "^3.2.4",
277
- "@elevasis/sdk": "1.36.3",
278
- "@repo/elevasis-core": "1.0.0",
277
+ "@elevasis/sdk": "1.36.4",
278
+ "@repo/core": "0.51.0",
279
279
  "@repo/typescript-config": "0.0.0",
280
- "@repo/core": "0.50.0",
280
+ "@repo/elevasis-core": "1.0.0",
281
281
  "@repo/eslint-config": "0.0.0"
282
282
  },
283
283
  "dependencies": {