@sybilion/uilib 1.3.21 → 1.3.22

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,7 +1,7 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
3
3
  import { MessageRole, GENERATING_DASHBOARD_SYSTEM_TEXT } from '../Chat.types.js';
4
- import { isGraphIntakeAssistantStepComplete, matchUserTextToQuickReply, parseScriptLine, textHasQuickReplyMarkers, branchKeysUsedFromChatHistory, branchKeysUsedByUserMessages, extractQuickReplyLabelKeyPairsFromText, entryBranchKeyBeforeLastAssistant, isPresetScriptGraph, branchesFromPresetScriptGraph } from '../ChatMessage/presetScript.js';
4
+ import { isGraphIntakeAssistantStepComplete, matchUserTextToQuickReply, isPresetScriptGraph, branchesFromPresetScriptGraph, parseScriptLine, textHasQuickReplyMarkers, branchKeysUsedFromChatHistory, branchKeysUsedByUserMessages, extractQuickReplyLabelKeyPairsFromText, entryBranchKeyBeforeLastAssistant } from '../ChatMessage/presetScript.js';
5
5
  import { buildChatSendMessagePayload, displayTextFromSendPayload } from '../buildChatSendMessagePayload.js';
6
6
  import { usedPresetIdsFromMessages, formatChatTranscript } from '../chat-preset-utils.js';
7
7
  import { useChatsForScopeId, useChat, useChatOutboundPending, useSyncChatPanelBusy, isChatEmpty } from '../../../../contexts/chat-context.js';
@@ -425,7 +425,7 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
425
425
  onMessage,
426
426
  onScriptComplete,
427
427
  ]);
428
- const submitPreset = async (preset) => {
428
+ const submitPreset = useCallback(async (preset) => {
429
429
  const script = preset.script;
430
430
  const scriptGraph = isPresetScriptGraph(script);
431
431
  const hasLinearScript = Array.isArray(script) && script.length > 0;
@@ -518,7 +518,24 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
518
518
  finally {
519
519
  setLocalUiBusy(false);
520
520
  }
521
- };
521
+ }, [
522
+ currentChatId,
523
+ endLocalDemoFlow,
524
+ handlePromptSubmit,
525
+ addMessage,
526
+ presetsWithFreeform,
527
+ ]);
528
+ const resolvedEmptyState = useMemo(() => {
529
+ if (!emptyState)
530
+ return undefined;
531
+ const { additionalContent, ...rest } = emptyState;
532
+ return {
533
+ ...rest,
534
+ additionalContent: typeof additionalContent === 'function'
535
+ ? additionalContent({ submitPreset })
536
+ : additionalContent,
537
+ };
538
+ }, [emptyState, submitPreset]);
522
539
  const activeScript = currentChatId
523
540
  ? scriptByChatId[currentChatId]
524
541
  : undefined;
@@ -765,7 +782,7 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
765
782
  onPromptSubmit: handlePromptSubmit,
766
783
  onChatDeleted: endLocalDemoFlow,
767
784
  promptPrefill: promptLinkPrefill,
768
- emptyState,
785
+ emptyState: resolvedEmptyState,
769
786
  allowedAttachments,
770
787
  allowPdfAttachments,
771
788
  onAttachmentsDropped,
@@ -1,7 +1,15 @@
1
+ import type { ChatPreset } from '#uilib/components/ui/Chat/Chat.types';
2
+ export type ChatEmptyStateContext = {
3
+ submitPreset: (preset: ChatPreset) => void | Promise<void>;
4
+ };
1
5
  export interface ChatEmptyStateProps {
2
6
  icon?: React.ReactNode;
3
7
  title?: string;
4
8
  description?: string;
5
- /** Extra block below description (works when passed via `ChatChrome` / `ChatSheet` `emptyState`). */
9
+ /** Extra block below description (resolved before render in `ChatEmptyState`). */
6
10
  additionalContent?: React.ReactNode;
7
11
  }
12
+ /** Passed to `ChatSheet` / `useChatPanelChromeModel`; function form resolved before render. */
13
+ export interface ChatEmptyStateConfig extends Omit<ChatEmptyStateProps, 'additionalContent'> {
14
+ additionalContent?: React.ReactNode | ((ctx: ChatEmptyStateContext) => React.ReactNode);
15
+ }
@@ -1,7 +1,7 @@
1
1
  import { ChatPreset, type ScriptCompletePayload } from '#uilib/components/ui/Chat/Chat.types';
2
2
  import type { ChatChromeProps } from '../ChatChrome';
3
3
  import type { ChatAttachmentDropItem } from '../ChatChrome/ChatChrome.types';
4
- import type { ChatEmptyStateProps } from '../ChatEmptyState/ChatEmptyState.types';
4
+ import type { ChatEmptyStateConfig } from '../ChatEmptyState/ChatEmptyState.types';
5
5
  export type UseChatPanelChromeModelInput = {
6
6
  /** When true, skip sidebar chat slot, URL `?chat=`, and portal behavior (e.g. page main content). */
7
7
  embedAsPage: boolean;
@@ -16,7 +16,7 @@ export type UseChatPanelChromeModelInput = {
16
16
  /** Renders `[CHART]` tokens in assistant messages. */
17
17
  renderMessageChart?: () => React.ReactNode;
18
18
  /** Forwarded to `ChatChrome` when the thread is empty. */
19
- emptyState?: ChatEmptyStateProps;
19
+ emptyState?: ChatEmptyStateConfig;
20
20
  /** MIME types / extensions for text-only chat attachments (filtered by uilib allowlist). */
21
21
  allowedAttachments?: readonly string[];
22
22
  /** When true, PDF drops are accepted and parsed to plain text. */
@@ -12,6 +12,7 @@ export type { UseChatPanelChromeModelInput, UseChatPanelChromeModelResult, } fro
12
12
  export { ChatMessage } from './ChatMessage';
13
13
  export { ChatPrompt } from './ChatPrompt';
14
14
  export { ChatPresets } from './ChatPresets';
15
+ export type { ChatEmptyStateConfig, ChatEmptyStateContext, ChatEmptyStateProps, } from './ChatEmptyState/ChatEmptyState.types';
15
16
  export type { Chat as ChatType, ChatAttachmentDropItem, ChatSendMessagePayload, ChatProps, ChatPreset as ChatPresetType, Message, UserTextFileAttachment, } from './Chat.types';
16
17
  export { MessageRole } from './Chat.types';
17
18
  export { CsvIcon } from '../../icons/CsvIcon/CsvIcon';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sybilion/uilib",
3
- "version": "1.3.21",
3
+ "version": "1.3.22",
4
4
  "description": "Sybilion Design System — React UI components (Webpack + Stylus)",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -1,7 +1,23 @@
1
+ import type { ChatPreset } from '#uilib/components/ui/Chat/Chat.types';
2
+
3
+ export type ChatEmptyStateContext = {
4
+ submitPreset: (preset: ChatPreset) => void | Promise<void>;
5
+ };
6
+
1
7
  export interface ChatEmptyStateProps {
2
8
  icon?: React.ReactNode;
3
9
  title?: string;
4
10
  description?: string;
5
- /** Extra block below description (works when passed via `ChatChrome` / `ChatSheet` `emptyState`). */
11
+ /** Extra block below description (resolved before render in `ChatEmptyState`). */
6
12
  additionalContent?: React.ReactNode;
7
13
  }
14
+
15
+ /** Passed to `ChatSheet` / `useChatPanelChromeModel`; function form resolved before render. */
16
+ export interface ChatEmptyStateConfig extends Omit<
17
+ ChatEmptyStateProps,
18
+ 'additionalContent'
19
+ > {
20
+ additionalContent?:
21
+ | React.ReactNode
22
+ | ((ctx: ChatEmptyStateContext) => React.ReactNode);
23
+ }
@@ -45,6 +45,7 @@ import { useSidebar } from '../../Sidebar/Sidebar';
45
45
  import { Chat } from '../Chat';
46
46
  import type { ChatChromeProps } from '../ChatChrome';
47
47
  import type { ChatAttachmentDropItem } from '../ChatChrome/ChatChrome.types';
48
+ import type { ChatEmptyStateConfig } from '../ChatEmptyState/ChatEmptyState.types';
48
49
  import type { ChatEmptyStateProps } from '../ChatEmptyState/ChatEmptyState.types';
49
50
 
50
51
  export type UseChatPanelChromeModelInput = {
@@ -61,7 +62,7 @@ export type UseChatPanelChromeModelInput = {
61
62
  /** Renders `[CHART]` tokens in assistant messages. */
62
63
  renderMessageChart?: () => React.ReactNode;
63
64
  /** Forwarded to `ChatChrome` when the thread is empty. */
64
- emptyState?: ChatEmptyStateProps;
65
+ emptyState?: ChatEmptyStateConfig;
65
66
  /** MIME types / extensions for text-only chat attachments (filtered by uilib allowlist). */
66
67
  allowedAttachments?: readonly string[];
67
68
  /** When true, PDF drops are accepted and parsed to plain text. */
@@ -615,7 +616,7 @@ export function useChatPanelChromeModel({
615
616
  ],
616
617
  );
617
618
 
618
- const submitPreset = async (preset: ChatPreset) => {
619
+ const submitPreset = useCallback(async (preset: ChatPreset) => {
619
620
  const script = preset.script;
620
621
  const scriptGraph = isPresetScriptGraph(script);
621
622
  const hasLinearScript = Array.isArray(script) && script.length > 0;
@@ -705,7 +706,25 @@ export function useChatPanelChromeModel({
705
706
  } finally {
706
707
  setLocalUiBusy(false);
707
708
  }
708
- };
709
+ }, [
710
+ currentChatId,
711
+ endLocalDemoFlow,
712
+ handlePromptSubmit,
713
+ addMessage,
714
+ presetsWithFreeform,
715
+ ]);
716
+
717
+ const resolvedEmptyState = useMemo((): ChatEmptyStateProps | undefined => {
718
+ if (!emptyState) return undefined;
719
+ const { additionalContent, ...rest } = emptyState;
720
+ return {
721
+ ...rest,
722
+ additionalContent:
723
+ typeof additionalContent === 'function'
724
+ ? additionalContent({ submitPreset })
725
+ : additionalContent,
726
+ };
727
+ }, [emptyState, submitPreset]);
709
728
 
710
729
  const activeScript = currentChatId
711
730
  ? scriptByChatId[currentChatId]
@@ -1017,7 +1036,7 @@ export function useChatPanelChromeModel({
1017
1036
  onPromptSubmit: handlePromptSubmit,
1018
1037
  onChatDeleted: endLocalDemoFlow,
1019
1038
  promptPrefill: promptLinkPrefill,
1020
- emptyState,
1039
+ emptyState: resolvedEmptyState,
1021
1040
  allowedAttachments,
1022
1041
  allowPdfAttachments,
1023
1042
  onAttachmentsDropped,
@@ -25,6 +25,11 @@ export type {
25
25
  export { ChatMessage } from './ChatMessage';
26
26
  export { ChatPrompt } from './ChatPrompt';
27
27
  export { ChatPresets } from './ChatPresets';
28
+ export type {
29
+ ChatEmptyStateConfig,
30
+ ChatEmptyStateContext,
31
+ ChatEmptyStateProps,
32
+ } from './ChatEmptyState/ChatEmptyState.types';
28
33
  export type {
29
34
  Chat as ChatType,
30
35
  ChatAttachmentDropItem,