nucleus-core-ts 0.9.166 → 0.9.168

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,3 +1,3 @@
1
- import type { ReactElement } from 'react';
1
+ import { type ReactElement } from 'react';
2
2
  import type { ChatPanelProps } from '../types';
3
3
  export declare function ChatPanel(props: ChatPanelProps): ReactElement;
@@ -1,16 +1,27 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
3
4
  import { cn } from '../../../utils/cn';
4
5
  import { useChat } from '../hooks/useChat';
5
6
  import { chatPanelTheme } from '../theme';
6
7
  import { ConversationList } from './ConversationList';
7
8
  import { MessageComposer } from './MessageComposer';
8
9
  import { MessageThread } from './MessageThread';
10
+ import { NewConversationModal } from './NewConversationModal';
9
11
  export function ChatPanel(props) {
10
12
  const theme = chatPanelTheme;
11
13
  const chat = useChat(props);
12
14
  const { store } = chat;
15
+ const [pickerOpen, setPickerOpen] = useState(false);
13
16
  const active = store.conversations.find((c)=>c.id === store.activeConversationId) ?? null;
17
+ const handleNewConversation = ()=>{
18
+ if (props.directory) setPickerOpen(true);
19
+ else props.onNewConversation?.();
20
+ };
21
+ const handleStartDirect = (userId)=>{
22
+ chat.startDirect(userId);
23
+ setPickerOpen(false);
24
+ };
14
25
  const handleSendFiles = (files, text)=>{
15
26
  const conversationId = store.activeConversationId;
16
27
  if (!conversationId) return;
@@ -51,10 +62,10 @@ export function ChatPanel(props) {
51
62
  className: theme.sidebar.title,
52
63
  children: props.title ?? 'Messages'
53
64
  }),
54
- props.onNewConversation && /*#__PURE__*/ _jsx("button", {
65
+ (props.directory || props.onNewConversation) && /*#__PURE__*/ _jsx("button", {
55
66
  type: "button",
56
67
  className: theme.sidebar.newButton,
57
- onClick: props.onNewConversation,
68
+ onClick: handleNewConversation,
58
69
  "aria-label": "New conversation",
59
70
  children: /*#__PURE__*/ _jsxs("svg", {
60
71
  className: "h-4 w-4",
@@ -106,6 +117,15 @@ export function ChatPanel(props) {
106
117
  className: theme.error,
107
118
  children: store.error
108
119
  }),
120
+ props.directory && /*#__PURE__*/ _jsx(NewConversationModal, {
121
+ open: pickerOpen,
122
+ directory: props.directory,
123
+ currentUserId: props.currentUserId,
124
+ theme: theme,
125
+ isCreating: props.actions.createConversation.state.isPending,
126
+ onClose: ()=>setPickerOpen(false),
127
+ onStartDirect: handleStartDirect
128
+ }),
109
129
  active && /*#__PURE__*/ _jsx(MessageComposer, {
110
130
  theme: theme,
111
131
  value: store.composerText,
@@ -0,0 +1,17 @@
1
+ import { type ReactElement } from 'react';
2
+ import type { ChatPanelTheme } from '../theme';
3
+ import type { ChatDirectoryUser } from '../types';
4
+ type NewConversationModalProps = {
5
+ open: boolean;
6
+ directory: ChatDirectoryUser[];
7
+ currentUserId: string;
8
+ theme: ChatPanelTheme;
9
+ isCreating: boolean;
10
+ title?: string;
11
+ searchPlaceholder?: string;
12
+ emptyLabel?: string;
13
+ onClose: () => void;
14
+ onStartDirect: (userId: string) => void;
15
+ };
16
+ export declare function NewConversationModal({ open, directory, currentUserId, theme, isCreating, title, searchPlaceholder, emptyLabel, onClose, onStartDirect, }: NewConversationModalProps): ReactElement | null;
17
+ export {};
@@ -0,0 +1,107 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import { cn } from '../../../utils/cn';
5
+ import { initialsOf } from '../helpers';
6
+ export function NewConversationModal({ open, directory, currentUserId, theme, isCreating, title = 'New message', searchPlaceholder = 'Search people...', emptyLabel = 'No people found', onClose, onStartDirect }) {
7
+ const [query, setQuery] = useState('');
8
+ if (!open) return null;
9
+ const normalized = query.trim().toLowerCase();
10
+ const people = directory.filter((person)=>person.userId !== currentUserId).filter((person)=>normalized ? person.name.toLowerCase().includes(normalized) || (person.subtitle?.toLowerCase().includes(normalized) ?? false) : true);
11
+ return /*#__PURE__*/ _jsxs("div", {
12
+ className: theme.picker.overlay,
13
+ children: [
14
+ /*#__PURE__*/ _jsx("button", {
15
+ type: "button",
16
+ "aria-label": "Close",
17
+ className: "absolute inset-0 h-full w-full cursor-default",
18
+ onClick: onClose
19
+ }),
20
+ /*#__PURE__*/ _jsxs("div", {
21
+ className: cn('relative', theme.picker.panel),
22
+ role: "dialog",
23
+ "aria-modal": "true",
24
+ "aria-label": title,
25
+ children: [
26
+ /*#__PURE__*/ _jsxs("div", {
27
+ className: theme.picker.header,
28
+ children: [
29
+ /*#__PURE__*/ _jsx("span", {
30
+ className: theme.picker.title,
31
+ children: title
32
+ }),
33
+ /*#__PURE__*/ _jsx("button", {
34
+ type: "button",
35
+ className: theme.picker.closeButton,
36
+ onClick: onClose,
37
+ "aria-label": "Close",
38
+ children: /*#__PURE__*/ _jsxs("svg", {
39
+ className: "h-4 w-4",
40
+ fill: "none",
41
+ viewBox: "0 0 24 24",
42
+ stroke: "currentColor",
43
+ children: [
44
+ /*#__PURE__*/ _jsx("title", {
45
+ children: "Close"
46
+ }),
47
+ /*#__PURE__*/ _jsx("path", {
48
+ strokeLinecap: "round",
49
+ strokeLinejoin: "round",
50
+ strokeWidth: 2,
51
+ d: "M6 18L18 6M6 6l12 12"
52
+ })
53
+ ]
54
+ })
55
+ })
56
+ ]
57
+ }),
58
+ /*#__PURE__*/ _jsx("div", {
59
+ className: theme.picker.searchWrap,
60
+ children: /*#__PURE__*/ _jsx("input", {
61
+ type: "text",
62
+ className: theme.picker.search,
63
+ placeholder: searchPlaceholder,
64
+ value: query,
65
+ onChange: (event)=>setQuery(event.target.value)
66
+ })
67
+ }),
68
+ /*#__PURE__*/ _jsx("div", {
69
+ className: theme.picker.list,
70
+ children: people.length === 0 ? /*#__PURE__*/ _jsx("div", {
71
+ className: theme.picker.empty,
72
+ children: emptyLabel
73
+ }) : people.map((person)=>/*#__PURE__*/ _jsxs("button", {
74
+ type: "button",
75
+ className: theme.picker.item,
76
+ disabled: isCreating,
77
+ onClick: ()=>onStartDirect(person.userId),
78
+ children: [
79
+ /*#__PURE__*/ _jsx("span", {
80
+ className: theme.picker.avatar,
81
+ children: person.avatarUrl ? /*#__PURE__*/ _jsx("img", {
82
+ src: person.avatarUrl,
83
+ alt: person.name,
84
+ className: "h-full w-full rounded-full object-cover"
85
+ }) : initialsOf(person.name)
86
+ }),
87
+ /*#__PURE__*/ _jsxs("span", {
88
+ className: "min-w-0 flex-1",
89
+ children: [
90
+ /*#__PURE__*/ _jsx("span", {
91
+ className: cn('block', theme.picker.name),
92
+ children: person.name
93
+ }),
94
+ person.subtitle && /*#__PURE__*/ _jsx("span", {
95
+ className: cn('block', theme.picker.subtitle),
96
+ children: person.subtitle
97
+ })
98
+ ]
99
+ })
100
+ ]
101
+ }, person.userId))
102
+ })
103
+ ]
104
+ })
105
+ ]
106
+ });
107
+ }
@@ -2,7 +2,8 @@ export { ChatPanel } from './components/ChatPanel';
2
2
  export { ConversationList } from './components/ConversationList';
3
3
  export { MessageComposer } from './components/MessageComposer';
4
4
  export { MessageThread } from './components/MessageThread';
5
+ export { NewConversationModal } from './components/NewConversationModal';
5
6
  export { type UseChatReturn, useChat } from './hooks/useChat';
6
7
  export { useChatStore } from './store';
7
8
  export { type ChatPanelTheme, chatPanelTheme, extendChatPanelTheme } from './theme';
8
- export type { ChatAttachmentDTO, ChatConversationDTO, ChatMessageDTO, ChatPanelActions, ChatPanelProps, ChatPanelState, ChatParticipantDTO, TypingIndicator, } from './types';
9
+ export type { ChatAttachmentDTO, ChatConversationDTO, ChatDirectoryUser, ChatMessageDTO, ChatPanelActions, ChatPanelProps, ChatPanelState, ChatParticipantDTO, TypingIndicator, } from './types';
@@ -2,6 +2,7 @@ export { ChatPanel } from './components/ChatPanel';
2
2
  export { ConversationList } from './components/ConversationList';
3
3
  export { MessageComposer } from './components/MessageComposer';
4
4
  export { MessageThread } from './components/MessageThread';
5
+ export { NewConversationModal } from './components/NewConversationModal';
5
6
  export { useChat } from './hooks/useChat';
6
7
  export { useChatStore } from './store';
7
8
  export { chatPanelTheme, extendChatPanelTheme } from './theme';
@@ -9,8 +9,8 @@ export { Captcha, captchaTheme } from './components/Captcha';
9
9
  export type { ChangePasswordAction, ChangePasswordFormProps, ChangePasswordHeaderProps, ChangePasswordPageConfig, ChangePasswordStep, } from './components/ChangePasswordPage';
10
10
  export { ChangePasswordPage, useChangePasswordStore, } from './components/ChangePasswordPage';
11
11
  export { Checkbox } from './components/Checkbox';
12
- export { ChatPanel, chatPanelTheme, extendChatPanelTheme, useChat, useChatStore } from './components/ChatPanel';
13
- export type { ChatPanelActions, ChatPanelProps, ChatPanelState, ChatPanelTheme, TypingIndicator as ChatTypingIndicator, UseChatReturn, } from './components/ChatPanel';
12
+ export { ChatPanel, chatPanelTheme, extendChatPanelTheme, NewConversationModal, useChat, useChatStore, } from './components/ChatPanel';
13
+ export type { ChatDirectoryUser, ChatPanelActions, ChatPanelProps, ChatPanelState, ChatPanelTheme, TypingIndicator as ChatTypingIndicator, UseChatReturn, } from './components/ChatPanel';
14
14
  export { DataTable } from './components/DataTable';
15
15
  export { DatePicker } from './components/DatePicker';
16
16
  export type { ComponentCategory, ComponentEntry, ComponentExample, DesignSystemMethods, DesignSystemPageProps, DesignSystemState, PropControl, PropControlOption, PropControlType, ThemeMode, ViewportSize, } from './components/DesignSystem';
@@ -49,6 +49,8 @@ export { extendVerificationPanelTheme, PendingVerifications, usePendingVerificat
49
49
  export type { ResendVerificationAction, VerifyEmailAction, VerifyEmailPageConfig, VerifyEmailState, VerifyEmailStep, } from './components/VerifyEmailPage';
50
50
  export { useVerifyEmailStore, VerifyEmailPage, } from './components/VerifyEmailPage';
51
51
  export { useNucleusEntity } from './hooks/useNucleusEntity';
52
+ export type { PubSubConfig, PubSubConnectionState, PubSubEvent } from './hooks/usePubSub';
53
+ export { usePubSub, usePubSubStore } from './hooks/usePubSub';
52
54
  export type { BulkDeleteResponse, ColumnConfig, ColumnEnum, ColumnReference, ColumnType, ColumnValidation, DeleteResponse, FieldConfig, FilterCondition, ListResponse, MutationResponse, NucleusColumn, NucleusEntity, NucleusEntityShowcaseProps, PaginationMeta, QueryParams, SingleResponse, SortCondition, SortDirection, UseNucleusEntityOptions, UseNucleusEntityReturn, } from './types';
53
55
  export { cn } from './utils/cn';
54
56
  export { formatLabel, getColumnType, getDefaultValue, isArrayColumn, isJsonColumn, isReferenceColumn, shouldExcludeColumn, shouldExcludeFromForm, } from './utils/columnUtils';
package/dist/fe/index.js CHANGED
@@ -8,7 +8,7 @@ export { Captcha, captchaTheme } from './components/Captcha';
8
8
  export { ChangePasswordPage, useChangePasswordStore } from './components/ChangePasswordPage';
9
9
  export { Checkbox } from './components/Checkbox';
10
10
  // Chat
11
- export { ChatPanel, chatPanelTheme, extendChatPanelTheme, useChat, useChatStore } from './components/ChatPanel';
11
+ export { ChatPanel, chatPanelTheme, extendChatPanelTheme, NewConversationModal, useChat, useChatStore } from './components/ChatPanel';
12
12
  export { DataTable } from './components/DataTable';
13
13
  export { DatePicker } from './components/DatePicker';
14
14
  export { ComponentCanvas, ComponentSidebar, createDefaultRegistry, DesignSystemPage, designSystemTheme, extendDesignSystemTheme, PropsPanel, useDesignSystemStore } from './components/DesignSystem';
@@ -32,6 +32,7 @@ export { extendVerificationFlowPageTheme, NodePalette, NotificationFlowNode, Pen
32
32
  export { extendVerificationPanelTheme, PendingVerifications, usePendingVerificationsStore, useVerificationPanelStore, VerificationPanel, verificationPanelTheme } from './components/VerificationPanel';
33
33
  export { useVerifyEmailStore, VerifyEmailPage } from './components/VerifyEmailPage';
34
34
  export { useNucleusEntity } from './hooks/useNucleusEntity';
35
+ export { usePubSub, usePubSubStore } from './hooks/usePubSub';
35
36
  export { cn } from './utils/cn';
36
37
  export { formatLabel, getColumnType, getDefaultValue, isArrayColumn, isJsonColumn, isReferenceColumn, shouldExcludeColumn, shouldExcludeFromForm } from './utils/columnUtils';
37
38
  export { generateBulkEndpointKey, generateDistinctEndpointKey, generateEntityEndpointKey, generateGetByIdEndpointKey, singularize, toUpperSnakeCase } from './utils/endpointKeys';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nucleus-core-ts",
3
- "version": "0.9.166",
3
+ "version": "0.9.168",
4
4
  "description": "Production-ready, enterprise-grade TypeScript framework for building multi-tenant APIs",
5
5
  "author": "Hidayet Can Özcan <hidayetcan@gmail.com>",
6
6
  "license": "SEE LICENSE IN LICENSE",