@sybilion/uilib 1.3.68 → 1.3.70

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.
@@ -1,6 +1,6 @@
1
1
  import styleInject from 'style-inject';
2
2
 
3
- var css_248z = ".ChatMessage_root__6rnsF{background:var(--bg-secondary);display:flex;flex-direction:column;gap:var(--p-1);padding:var(--p-4);padding-bottom:var(--p-1)}.ChatMessage_text__Y1XNR{color:var(--text-secondary);font-size:var(--text-sm);max-width:100%;min-width:0;overflow-wrap:anywhere;-webkit-user-select:text;-moz-user-select:text;user-select:text;width:-moz-fit-content;width:fit-content;word-break:break-word}.ChatMessage_role-assistant__wketE+.ChatMessage_role-assistant__wketE,.ChatMessage_role-system__g13OP+.ChatMessage_role-system__g13OP,.ChatMessage_role-user__u4JPV+.ChatMessage_role-user__u4JPV{padding-top:var(--p-1)}.ChatMessage_role-user__u4JPV{align-items:flex-end;max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_userColumn__cQM6-{align-items:flex-end;display:flex;flex-direction:column;gap:var(--p-2);max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-slate-100);border-radius:var(--p-4);border-bottom-right-radius:0;box-sizing:border-box;overflow:hidden;padding:var(--p-3) var(--p-4);white-space:pre-wrap}.dark .ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-gray-800)}.ChatMessage_role-system__g13OP{align-items:center}.ChatMessage_role-system__g13OP .ChatMessage_text__Y1XNR{color:var(--muted-foreground);width:100%}.ChatMessage_role-assistant__wketE .ChatMessage_text__Y1XNR{width:100%}.ChatMessage_role-assistant__wketE h3{line-height:2.4}.ChatMessage_role-assistant__wketE h4{font-size:1.1em;font-weight:600;line-height:2.2}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq{display:inline-block;margin-left:4px;margin-right:6px}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq:before{color:var(--text-secondary);content:\"•\";display:inline-block}.ChatMessage_role-assistant__wketE .ChatMessage_scrollHorizontal__Rms9n{max-width:100%}.ChatMessage_role-assistant__wketE table{border:1px solid var(--border);border-collapse:collapse;border-radius:var(--p-2);border-spacing:0;margin:var(--p-4) 0;overflow:hidden}.ChatMessage_role-assistant__wketE table td,.ChatMessage_role-assistant__wketE table th{border:1px solid var(--border);min-width:100px;padding:var(--p-1)}.ChatMessage_role-assistant__wketE table th{text-align:left}.ChatMessage_role-assistant__wketE ol,.ChatMessage_role-assistant__wketE ul{padding-left:var(--p-4)}.ChatMessage_role-assistant__wketE ul{list-style-type:disc}.ChatMessage_role-assistant__wketE ol{list-style-type:decimal}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{align-items:center;border:1px dashed var(--sb-slate-300);border-radius:8px;color:var(--foreground);display:inline-flex;font-size:var(--text-xs);gap:6px;margin:1px;max-width:100%;padding:2px 6px 2px 4px;text-decoration:none;vertical-align:middle}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-slate-50);border-color:var(--sb-slate-400);border-style:solid}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{border-color:var(--sb-gray-600)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-gray-900)}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLinkLabel__PMU7e{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ChatMessage_role-assistant__wketE .ChatMessage_quickReplyWrap__1UFyD{display:inline-block;margin:var(--p-1) var(--p-1) var(--p-1) 0;vertical-align:middle}.ChatMessage_role-assistant__wketE .ChatMessage_downloadButtons__RygM-{display:flex;gap:var(--p-2);margin-top:var(--p-4)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{align-items:center;background-color:var(--background);border-radius:var(--p-3);box-shadow:0 0 0 1px var(--border);cursor:pointer;display:flex;gap:var(--p-4);margin-top:var(--p-3);padding:var(--p-3);padding-right:var(--p-4);transition:all .15s;width:-moz-fit-content;width:fit-content}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-50);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{background-color:var(--sb-gray-900);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-800)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardIcon__jkxDJ{align-items:center;border-radius:var(--p-2);display:flex;flex-shrink:0;height:32px;justify-content:center;width:32px}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardContent__PTPwz{display:flex;flex:1;flex-direction:column;min-width:0}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardTitle__K1wqr{font-size:var(--text-base);font-weight:600;line-height:1.4}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardSubtitle__fVeF2{color:var(--muted-foreground);font-size:var(--text-sm);line-height:1.4}";
3
+ var css_248z = ".ChatMessage_root__6rnsF{background:var(--bg-secondary);display:flex;flex-direction:column;gap:var(--p-1);padding:var(--p-4);padding-bottom:var(--p-1)}.ChatMessage_text__Y1XNR{color:var(--text-secondary);font-size:var(--text-sm);max-width:100%;min-width:0;overflow-wrap:anywhere;-webkit-user-select:text;-moz-user-select:text;user-select:text;width:-moz-fit-content;width:fit-content;word-break:break-word}.ChatMessage_role-assistant__wketE+.ChatMessage_role-assistant__wketE,.ChatMessage_role-system__g13OP+.ChatMessage_role-system__g13OP,.ChatMessage_role-user__u4JPV+.ChatMessage_role-user__u4JPV{padding-top:var(--p-1)}.ChatMessage_role-user__u4JPV{align-items:flex-end;max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_userColumn__cQM6-{align-items:flex-end;display:flex;flex-direction:column;gap:var(--p-2);max-width:100%;min-width:0}.ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-slate-100);border-radius:var(--p-4);border-bottom-right-radius:0;box-sizing:border-box;overflow:hidden;padding:var(--p-3) var(--p-4);white-space:pre-wrap}.dark .ChatMessage_role-user__u4JPV .ChatMessage_text__Y1XNR{background-color:var(--sb-gray-900)}.ChatMessage_role-system__g13OP{align-items:center}.ChatMessage_role-system__g13OP .ChatMessage_text__Y1XNR{color:var(--muted-foreground);width:100%}.ChatMessage_role-assistant__wketE .ChatMessage_text__Y1XNR{width:100%}.ChatMessage_role-assistant__wketE h3{line-height:2.4}.ChatMessage_role-assistant__wketE h4{font-size:1.1em;font-weight:600;line-height:2.2}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq{display:inline-block;margin-left:4px;margin-right:6px}.ChatMessage_role-assistant__wketE .ChatMessage_bullet__6vAhq:before{color:var(--text-secondary);content:\"•\";display:inline-block}.ChatMessage_role-assistant__wketE .ChatMessage_scrollHorizontal__Rms9n{max-width:100%}.ChatMessage_role-assistant__wketE table{border:1px solid var(--border);border-collapse:collapse;border-radius:var(--p-2);border-spacing:0;margin:var(--p-4) 0;overflow:hidden}.ChatMessage_role-assistant__wketE table td,.ChatMessage_role-assistant__wketE table th{border:1px solid var(--border);min-width:100px;padding:var(--p-1)}.ChatMessage_role-assistant__wketE table th{text-align:left}.ChatMessage_role-assistant__wketE ol,.ChatMessage_role-assistant__wketE ul{padding-left:var(--p-4)}.ChatMessage_role-assistant__wketE ul{list-style-type:disc}.ChatMessage_role-assistant__wketE ol{list-style-type:decimal}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{align-items:center;border:1px dashed var(--sb-slate-300);border-radius:8px;color:var(--foreground);display:inline-flex;font-size:var(--text-xs);gap:6px;margin:1px;max-width:100%;padding:2px 6px 2px 4px;text-decoration:none;vertical-align:middle}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-slate-50);border-color:var(--sb-slate-400);border-style:solid}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T{border-color:var(--sb-gray-600)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLink__Pxy-T:hover{background-color:var(--sb-gray-900)}.ChatMessage_role-assistant__wketE .ChatMessage_datasetAppLinkLabel__PMU7e{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ChatMessage_role-assistant__wketE .ChatMessage_quickReplyWrap__1UFyD{display:inline-block;margin:var(--p-1) var(--p-1) var(--p-1) 0;vertical-align:middle}.ChatMessage_role-assistant__wketE .ChatMessage_downloadButtons__RygM-{display:flex;gap:var(--p-2);margin-top:var(--p-4)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{align-items:center;background-color:var(--background);border-radius:var(--p-3);box-shadow:0 0 0 1px var(--border);cursor:pointer;display:flex;gap:var(--p-4);margin-top:var(--p-3);padding:var(--p-3);padding-right:var(--p-4);transition:all .15s;width:-moz-fit-content;width:fit-content}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-50);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa{background-color:var(--sb-gray-900);border-color:var(--border)}.dark .ChatMessage_role-assistant__wketE .ChatMessage_downloadCard__NsNRa:hover{background-color:var(--sb-gray-800)}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardIcon__jkxDJ{align-items:center;border-radius:var(--p-2);display:flex;flex-shrink:0;height:32px;justify-content:center;width:32px}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardContent__PTPwz{display:flex;flex:1;flex-direction:column;min-width:0}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardTitle__K1wqr{font-size:var(--text-base);font-weight:600;line-height:1.4}.ChatMessage_role-assistant__wketE .ChatMessage_downloadCardSubtitle__fVeF2{color:var(--muted-foreground);font-size:var(--text-sm);line-height:1.4}";
4
4
  var S = {"root":"ChatMessage_root__6rnsF","text":"ChatMessage_text__Y1XNR","role-user":"ChatMessage_role-user__u4JPV","role-assistant":"ChatMessage_role-assistant__wketE","role-system":"ChatMessage_role-system__g13OP","userColumn":"ChatMessage_userColumn__cQM6-","bullet":"ChatMessage_bullet__6vAhq","scrollHorizontal":"ChatMessage_scrollHorizontal__Rms9n","datasetAppLink":"ChatMessage_datasetAppLink__Pxy-T","datasetAppLinkLabel":"ChatMessage_datasetAppLinkLabel__PMU7e","quickReplyWrap":"ChatMessage_quickReplyWrap__1UFyD","downloadButtons":"ChatMessage_downloadButtons__RygM-","downloadCard":"ChatMessage_downloadCard__NsNRa","downloadCardIcon":"ChatMessage_downloadCardIcon__jkxDJ","downloadCardContent":"ChatMessage_downloadCardContent__PTPwz","downloadCardTitle":"ChatMessage_downloadCardTitle__K1wqr","downloadCardSubtitle":"ChatMessage_downloadCardSubtitle__fVeF2"};
5
5
  styleInject(css_248z);
6
6
 
@@ -143,8 +143,11 @@ function useChatPromptEditor({ disabled, placeholder, slashCommandItems, onSlash
143
143
  const dom = chatPromptSafeEditorDom(editor);
144
144
  if (dom)
145
145
  syncChatPromptComposerHeight(dom, t);
146
+ if (!disabled && !editor.isDestroyed) {
147
+ editor.chain().focus('end').run();
148
+ }
146
149
  });
147
- }, [editor, prefillMessage]);
150
+ }, [editor, prefillMessage, disabled]);
148
151
  useLayoutEffect(() => {
149
152
  if (!editor)
150
153
  return;
@@ -12,7 +12,7 @@ import 'lucide-react';
12
12
  import S from './SybilionAppHeader.styl.js';
13
13
 
14
14
  function SybilionAppHeader({ pageHeaderId, actionsAnchorId = PAGE_HEADER_ACTIONS_ID, actionsAnchorClassName, actionsStart, actionsEnd, pathname, onNavigate, authenticated, defaultApps, appsStorageKey, logo, logoAreaClassName, welcomeBannerOffset, ...navUserHeaderProps }) {
15
- return (jsxs(AppHeaderPortal, { pageHeaderId: pageHeaderId, children: [jsx("div", { className: cn(S.logoArea, welcomeBannerOffset && S.logoAreaWithBanner, logoAreaClassName), children: jsx(Link, { to: "/", className: S.logoLink, children: logo ?? jsx(Logo, { size: "md", "aria-hidden": true }) }) }), jsx(WorkspaceAppSwitcher, { pathname: pathname, onNavigate: onNavigate, authenticated: authenticated, defaultApps: defaultApps, appsStorageKey: appsStorageKey }), jsx(Gap, {}), jsxs("div", { id: actionsAnchorId, className: cn(S.actionsAnchor, actionsAnchorClassName), children: [actionsStart, jsx(NavUserHeader, { ...navUserHeaderProps }), actionsEnd] })] }));
15
+ return (jsxs(AppHeaderPortal, { pageHeaderId: pageHeaderId, children: [jsx("div", { className: cn(S.logoArea, welcomeBannerOffset && S.logoAreaWithBanner, logoAreaClassName), children: jsx(Link, { to: "/", className: S.logoLink, children: logo ?? jsx(Logo, { size: "md", "aria-hidden": true }) }) }), jsx(WorkspaceAppSwitcher, { pathname: pathname, onNavigate: onNavigate, authenticated: authenticated, defaultApps: defaultApps, appsStorageKey: appsStorageKey }), jsx(Gap, {}), jsxs("div", { className: cn(S.actionsAnchor, actionsAnchorClassName), children: [jsx("div", { id: actionsAnchorId, className: S.pageActionsPortal }), actionsStart, jsx(NavUserHeader, { ...navUserHeaderProps }), actionsEnd] })] }));
16
16
  }
17
17
 
18
18
  export { SybilionAppHeader };
@@ -1,7 +1,7 @@
1
1
  import styleInject from 'style-inject';
2
2
 
3
- var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.SybilionAppHeader_actionsAnchor__ress2{align-items:center;display:flex;flex-shrink:0;gap:var(--p-4)}.SybilionAppHeader_logoArea__3HAhG{align-items:center;display:flex;gap:var(--p-2);left:40px;position:absolute;top:22px;z-index:10}@media (max-width:768px){.SybilionAppHeader_logoArea__3HAhG{left:32px}}@media (min-width:768px){[data-slot=sidebar-wrapper][data-state=expanded] .SybilionAppHeader_logoArea__3HAhG{position:fixed}}.SybilionAppHeader_logoAreaWithBanner__7Iy78{top:22px;top:calc(22px + var(--welcome-banner-height, 0px))}@media (min-width:768px){[data-slot=sidebar-wrapper][data-state=collapsed] .SybilionAppHeader_logoAreaWithBanner__7Iy78{top:22px}}.SybilionAppHeader_logoLink__bH-KX{align-items:center;color:var(--color-foreground);display:flex;font-size:1.5rem;font-weight:400;gap:.5rem;text-decoration:none;white-space:nowrap;width:-moz-fit-content;width:fit-content}.SybilionAppHeader_logoLink__bH-KX svg{display:inline-flex;flex-shrink:0;height:32px;transition:transform .1s ease-in-out;width:auto}.SybilionAppHeader_logoLink__bH-KX:hover svg{transform:scale(1.05)}";
4
- var S = {"actionsAnchor":"SybilionAppHeader_actionsAnchor__ress2","logoArea":"SybilionAppHeader_logoArea__3HAhG","logoAreaWithBanner":"SybilionAppHeader_logoAreaWithBanner__7Iy78","logoLink":"SybilionAppHeader_logoLink__bH-KX"};
3
+ var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.SybilionAppHeader_actionsAnchor__ress2,.SybilionAppHeader_pageActionsPortal__9C5ww{align-items:center;display:flex;flex-shrink:0;gap:var(--p-4)}.SybilionAppHeader_pageActionsPortal__9C5ww:empty{display:none}.SybilionAppHeader_logoArea__3HAhG{align-items:center;display:flex;gap:var(--p-2);left:40px;position:absolute;top:22px;z-index:10}@media (max-width:768px){.SybilionAppHeader_logoArea__3HAhG{left:32px}}@media (min-width:768px){[data-slot=sidebar-wrapper][data-state=expanded] .SybilionAppHeader_logoArea__3HAhG{position:fixed}}.SybilionAppHeader_logoAreaWithBanner__7Iy78{top:22px;top:calc(22px + var(--welcome-banner-height, 0px))}@media (min-width:768px){[data-slot=sidebar-wrapper][data-state=collapsed] .SybilionAppHeader_logoAreaWithBanner__7Iy78{top:22px}}.SybilionAppHeader_logoLink__bH-KX{align-items:center;color:var(--color-foreground);display:flex;font-size:1.5rem;font-weight:400;gap:.5rem;text-decoration:none;white-space:nowrap;width:-moz-fit-content;width:fit-content}.SybilionAppHeader_logoLink__bH-KX svg{display:inline-flex;flex-shrink:0;height:32px;transition:transform .1s ease-in-out;width:auto}.SybilionAppHeader_logoLink__bH-KX:hover svg{transform:scale(1.05)}";
4
+ var S = {"actionsAnchor":"SybilionAppHeader_actionsAnchor__ress2","pageActionsPortal":"SybilionAppHeader_pageActionsPortal__9C5ww","logoArea":"SybilionAppHeader_logoArea__3HAhG","logoAreaWithBanner":"SybilionAppHeader_logoAreaWithBanner__7Iy78","logoLink":"SybilionAppHeader_logoLink__bH-KX"};
5
5
  styleInject(css_248z);
6
6
 
7
7
  export { S as default };
@@ -0,0 +1 @@
1
+ export default function ChatComposerPrefillPage(): import("react/jsx-runtime").JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sybilion/uilib",
3
- "version": "1.3.68",
3
+ "version": "1.3.70",
4
4
  "description": "Sybilion Design System — React UI components (Webpack + Stylus)",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -48,7 +48,7 @@
48
48
  box-sizing border-box
49
49
 
50
50
  :global(.dark) &
51
- background-color var(--sb-gray-800)
51
+ background-color var(--sb-gray-900)
52
52
 
53
53
  .role-system
54
54
  align-items center
@@ -208,8 +208,11 @@ export function useChatPromptEditor({
208
208
  queueMicrotask(() => {
209
209
  const dom = chatPromptSafeEditorDom(editor);
210
210
  if (dom) syncChatPromptComposerHeight(dom, t);
211
+ if (!disabled && !editor.isDestroyed) {
212
+ editor.chain().focus('end').run();
213
+ }
211
214
  });
212
- }, [editor, prefillMessage]);
215
+ }, [editor, prefillMessage, disabled]);
213
216
 
214
217
  useLayoutEffect(() => {
215
218
  if (!editor) return;
@@ -6,6 +6,15 @@
6
6
  gap var(--p-4)
7
7
  flex-shrink 0
8
8
 
9
+ .pageActionsPortal
10
+ display flex
11
+ align-items center
12
+ gap var(--p-4)
13
+ flex-shrink 0
14
+
15
+ &:empty
16
+ display none
17
+
9
18
  .logoArea
10
19
  position absolute
11
20
  top 22px
@@ -5,6 +5,7 @@ interface CssExports {
5
5
  'logoArea': string;
6
6
  'logoAreaWithBanner': string;
7
7
  'logoLink': string;
8
+ 'pageActionsPortal': string;
8
9
  }
9
10
  export const cssExports: CssExports;
10
11
  export default cssExports;
@@ -69,10 +69,8 @@ export function SybilionAppHeader({
69
69
  appsStorageKey={appsStorageKey}
70
70
  />
71
71
  <Gap />
72
- <div
73
- id={actionsAnchorId}
74
- className={cn(S.actionsAnchor, actionsAnchorClassName)}
75
- >
72
+ <div className={cn(S.actionsAnchor, actionsAnchorClassName)}>
73
+ <div id={actionsAnchorId} className={S.pageActionsPortal} />
76
74
  {actionsStart}
77
75
  <NavUserHeader {...navUserHeaderProps} />
78
76
  {actionsEnd}
@@ -0,0 +1,202 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+
3
+ import { Button } from '#uilib/components/ui/Button';
4
+ import {
5
+ ChatChrome,
6
+ type ChatSheetActions,
7
+ type Message,
8
+ MessageRole,
9
+ } from '#uilib/components/ui/Chat';
10
+ import { PageContentSection } from '#uilib/components/ui/Page';
11
+ import { ScrollRef } from '@homecode/ui';
12
+ import { MessageSquare } from 'lucide-react';
13
+
14
+ import { AppPageHeader } from '../components/AppPageHeader/AppPageHeader';
15
+ import { DOCS_CHAT_USER_KEY } from '../docsConstants';
16
+ import { DocsHeaderActions } from '../docsHeaderActions';
17
+
18
+ const NO_QUICK_REPLY_KEYS: ReadonlySet<string> = new Set();
19
+
20
+ const SAMPLE_PREFILL =
21
+ 'Summarize revenue trends for Q4 and highlight outliers.';
22
+
23
+ const ASSISTANT_REPLY_TEXT =
24
+ 'Prefill demo reply — composer should stay editable after send.';
25
+
26
+ function makeMessage(role: MessageRole, text: string): Message {
27
+ return {
28
+ id: crypto.randomUUID(),
29
+ role,
30
+ text,
31
+ timestamp: Date.now(),
32
+ };
33
+ }
34
+
35
+ const DOCS_CHAT_PREFILL_SCOPE_ID = `${DOCS_CHAT_USER_KEY}-docs-composer-prefill`;
36
+
37
+ export default function ChatComposerPrefillPage() {
38
+ const [messages, setMessages] = useState<Message[]>([]);
39
+ const [isLoading, setIsLoading] = useState(false);
40
+ const [inlinePrefill, setInlinePrefill] = useState<string | null>(null);
41
+ const replyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
42
+ const scrollRef = useRef<ScrollRef>(null);
43
+ const sheetActionsRef = useRef<ChatSheetActions | null>(null);
44
+
45
+ useEffect(() => {
46
+ return () => {
47
+ if (replyTimeoutRef.current != null) {
48
+ clearTimeout(replyTimeoutRef.current);
49
+ }
50
+ };
51
+ }, []);
52
+
53
+ const isEmpty = messages.length === 0 && !isLoading;
54
+ const isLastMessageFromUser =
55
+ messages.length > 0 &&
56
+ messages[messages.length - 1]?.role === MessageRole.USER;
57
+
58
+ const onSubmit = useCallback(
59
+ (raw: string) => {
60
+ const text = raw.trim();
61
+ if (!text || isLoading) return;
62
+
63
+ setMessages(prev => [...prev, makeMessage(MessageRole.USER, text)]);
64
+ setIsLoading(true);
65
+ setInlinePrefill(null);
66
+
67
+ if (replyTimeoutRef.current != null) {
68
+ clearTimeout(replyTimeoutRef.current);
69
+ }
70
+ replyTimeoutRef.current = setTimeout(() => {
71
+ replyTimeoutRef.current = null;
72
+ setMessages(prev => [
73
+ ...prev,
74
+ makeMessage(MessageRole.ASSISTANT, ASSISTANT_REPLY_TEXT),
75
+ ]);
76
+ setIsLoading(false);
77
+ }, 900);
78
+ },
79
+ [isLoading],
80
+ );
81
+
82
+ const prefillInlineComposer = useCallback(() => {
83
+ setInlinePrefill(SAMPLE_PREFILL);
84
+ }, []);
85
+
86
+ const openSheetWithPrefill = useCallback(() => {
87
+ sheetActionsRef.current?.openNewChatWithPrefill(SAMPLE_PREFILL);
88
+ }, []);
89
+
90
+ const promptDeepLink = `/docs/chat-composer-prefill?prompt=${encodeURIComponent(SAMPLE_PREFILL)}`;
91
+
92
+ return (
93
+ <>
94
+ <AppPageHeader
95
+ breadcrumbs={[{ label: 'Chat' }, { label: 'Composer prefill' }]}
96
+ title="Chat — composer prefill & focus"
97
+ subheader="Prefill the TipTap composer via prefillMessage, ChatSheetActions.openNewChatWithPrefill, or a ?prompt= deep link. Cursor lands at end; message is not auto-sent."
98
+ actions={
99
+ <DocsHeaderActions
100
+ actionsRef={sheetActionsRef}
101
+ scopeId={DOCS_CHAT_PREFILL_SCOPE_ID}
102
+ triggerLabel={<MessageSquare size={20} />}
103
+ triggerAriaLabel="AI Assistant"
104
+ emptyState={{
105
+ title: 'Start a conversation',
106
+ description:
107
+ 'Use the buttons below or ?prompt= to pre-fill this composer.',
108
+ }}
109
+ />
110
+ }
111
+ />
112
+ <PageContentSection>
113
+ <p style={{ marginBottom: 12, fontSize: 14, lineHeight: 1.5 }}>
114
+ After prefill, the composer receives focus at the end of the text so
115
+ users can edit before sending. Wired through{' '}
116
+ <code style={{ fontSize: 13 }}>useChatPromptEditor</code> (
117
+ <code style={{ fontSize: 13 }}>prefillMessage</code>) and{' '}
118
+ <code style={{ fontSize: 13 }}>useChatPanelChromeModel</code> (
119
+ <code style={{ fontSize: 13 }}>promptPrefill</code> /{' '}
120
+ <code style={{ fontSize: 13 }}>openNewChatWithPrefill</code>).
121
+ </p>
122
+ <p
123
+ style={{
124
+ marginBottom: 16,
125
+ display: 'flex',
126
+ flexWrap: 'wrap',
127
+ gap: 8,
128
+ }}
129
+ >
130
+ <Button
131
+ type="button"
132
+ variant="outline"
133
+ size="sm"
134
+ onClick={prefillInlineComposer}
135
+ >
136
+ Prefill inline composer
137
+ </Button>
138
+ <Button
139
+ type="button"
140
+ variant="outline"
141
+ size="sm"
142
+ onClick={openSheetWithPrefill}
143
+ >
144
+ Open portal chat with prefill
145
+ </Button>
146
+ <Button type="button" variant="outline" size="sm" asChild>
147
+ <a href={promptDeepLink}>Try ?prompt= deep link</a>
148
+ </Button>
149
+ </p>
150
+ <h3 style={{ marginBottom: 8, fontSize: 14, fontWeight: 600 }}>
151
+ What to verify
152
+ </h3>
153
+ <ul
154
+ style={{
155
+ margin: '0 0 16px',
156
+ paddingLeft: 20,
157
+ fontSize: 14,
158
+ lineHeight: 1.6,
159
+ }}
160
+ >
161
+ <li>Composer shows sample text; caret at end (not start)</li>
162
+ <li>User can type or edit before Enter / submit</li>
163
+ <li>Prefill does not send until user submits</li>
164
+ <li>
165
+ Portal path: new session opens, panel visible, same focus behavior
166
+ </li>
167
+ <li>
168
+ Deep link strips <code style={{ fontSize: 13 }}>?prompt=</code> and
169
+ opens chat with prefill once
170
+ </li>
171
+ </ul>
172
+ <ChatChrome
173
+ showResizeHandle={false}
174
+ resizeHandle={undefined}
175
+ onClose={undefined}
176
+ isEmpty={isEmpty}
177
+ renderPresets={() => null}
178
+ messages={messages}
179
+ onQuickReply={() => {}}
180
+ suppressedQuickReplyKeys={NO_QUICK_REPLY_KEYS}
181
+ isLoading={isLoading}
182
+ scriptContinueLabel={undefined}
183
+ onScriptContinue={undefined}
184
+ showSyntheticBranchButtons={false}
185
+ unusedBranchKeys={[]}
186
+ showInlinePresets={false}
187
+ isLastMessageFromUser={isLastMessageFromUser}
188
+ scrollRef={scrollRef}
189
+ effectiveScopeId="docs-chat-composer-prefill-inline"
190
+ onPromptSubmit={onSubmit}
191
+ onChatDeleted={() => {}}
192
+ promptPrefill={inlinePrefill}
193
+ emptyState={{
194
+ title: 'Inline prefill demo',
195
+ description:
196
+ 'Click “Prefill inline composer” or type below. Portal and ?prompt= use the header ChatSheet.',
197
+ }}
198
+ />
199
+ </PageContentSection>
200
+ </>
201
+ );
202
+ }
@@ -139,6 +139,12 @@ export const DOC_REGISTRY: DocEntry[] = [
139
139
  section: 'Chat',
140
140
  load: () => import('./pages/ChatAttachmentsDropzonePage'),
141
141
  },
142
+ {
143
+ slug: 'chat-composer-prefill',
144
+ title: 'Chat composer prefill',
145
+ section: 'Chat',
146
+ load: () => import('./pages/ChatComposerPrefillPage'),
147
+ },
142
148
  {
143
149
  slug: 'checkbox',
144
150
  title: 'Checkbox',