@mars-stack/cli 6.0.4 → 7.0.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/dist/index.js +28 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1421,7 +1421,7 @@ interface UseNotificationsOptions {
|
|
|
1421
1421
|
interface UseNotificationsReturn {
|
|
1422
1422
|
notifications: NotificationItem[];
|
|
1423
1423
|
unreadCount: number;
|
|
1424
|
-
|
|
1424
|
+
status: 'idle' | 'loading';
|
|
1425
1425
|
error: string | null;
|
|
1426
1426
|
markAsRead: (id: string) => Promise<void>;
|
|
1427
1427
|
markAllAsRead: () => Promise<void>;
|
|
@@ -1433,7 +1433,7 @@ export function useNotifications({
|
|
|
1433
1433
|
}: UseNotificationsOptions = {}): UseNotificationsReturn {
|
|
1434
1434
|
const [notifications, setNotifications] = useState<NotificationItem[]>([]);
|
|
1435
1435
|
const [unreadCount, setUnreadCount] = useState(0);
|
|
1436
|
-
const [
|
|
1436
|
+
const [status, setStatus] = useState<'idle' | 'loading'>('loading');
|
|
1437
1437
|
const [error, setError] = useState<string | null>(null);
|
|
1438
1438
|
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
1439
1439
|
|
|
@@ -1461,9 +1461,9 @@ export function useNotifications({
|
|
|
1461
1461
|
}, []);
|
|
1462
1462
|
|
|
1463
1463
|
const refresh = useCallback(async () => {
|
|
1464
|
-
|
|
1464
|
+
setStatus('loading');
|
|
1465
1465
|
await Promise.all([fetchNotifications(), fetchUnreadCount()]);
|
|
1466
|
-
|
|
1466
|
+
setStatus('idle');
|
|
1467
1467
|
}, [fetchNotifications, fetchUnreadCount]);
|
|
1468
1468
|
|
|
1469
1469
|
const markAsRead = useCallback(
|
|
@@ -1512,7 +1512,7 @@ export function useNotifications({
|
|
|
1512
1512
|
return {
|
|
1513
1513
|
notifications,
|
|
1514
1514
|
unreadCount,
|
|
1515
|
-
|
|
1515
|
+
status,
|
|
1516
1516
|
error,
|
|
1517
1517
|
markAsRead,
|
|
1518
1518
|
markAllAsRead,
|
|
@@ -1532,7 +1532,7 @@ import { NotificationPanel } from './NotificationPanel';
|
|
|
1532
1532
|
export function NotificationBell() {
|
|
1533
1533
|
const [isOpen, setIsOpen] = useState(false);
|
|
1534
1534
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
1535
|
-
const { notifications, unreadCount,
|
|
1535
|
+
const { notifications, unreadCount, status, markAsRead, markAllAsRead, refresh } =
|
|
1536
1536
|
useNotifications();
|
|
1537
1537
|
|
|
1538
1538
|
useEffect(() => {
|
|
@@ -1583,7 +1583,7 @@ export function NotificationBell() {
|
|
|
1583
1583
|
{isOpen && (
|
|
1584
1584
|
<NotificationPanel
|
|
1585
1585
|
notifications={notifications}
|
|
1586
|
-
|
|
1586
|
+
status={status}
|
|
1587
1587
|
onMarkAsRead={markAsRead}
|
|
1588
1588
|
onMarkAllAsRead={markAllAsRead}
|
|
1589
1589
|
onClose={() => setIsOpen(false)}
|
|
@@ -1602,7 +1602,7 @@ import type { NotificationItem } from '../types';
|
|
|
1602
1602
|
|
|
1603
1603
|
interface NotificationPanelProps {
|
|
1604
1604
|
notifications: NotificationItem[];
|
|
1605
|
-
|
|
1605
|
+
status: 'idle' | 'loading';
|
|
1606
1606
|
onMarkAsRead: (id: string) => Promise<void>;
|
|
1607
1607
|
onMarkAllAsRead: () => Promise<void>;
|
|
1608
1608
|
onClose: () => void;
|
|
@@ -1636,7 +1636,7 @@ function formatRelativeTime(date: Date | string): string {
|
|
|
1636
1636
|
|
|
1637
1637
|
export function NotificationPanel({
|
|
1638
1638
|
notifications,
|
|
1639
|
-
|
|
1639
|
+
status,
|
|
1640
1640
|
onMarkAsRead,
|
|
1641
1641
|
onMarkAllAsRead,
|
|
1642
1642
|
onClose,
|
|
@@ -1659,7 +1659,7 @@ export function NotificationPanel({
|
|
|
1659
1659
|
</div>
|
|
1660
1660
|
|
|
1661
1661
|
<div className="max-h-96 overflow-y-auto">
|
|
1662
|
-
{
|
|
1662
|
+
{status === 'loading' && notifications.length === 0 ? (
|
|
1663
1663
|
<div className="flex items-center justify-center py-12">
|
|
1664
1664
|
<div className="size-5 animate-spin rounded-full border-2 border-border-default border-t-brand-primary" />
|
|
1665
1665
|
</div>
|
|
@@ -3640,7 +3640,7 @@ interface UseSearchReturn<T> {
|
|
|
3640
3640
|
query: string;
|
|
3641
3641
|
setQuery: (q: string) => void;
|
|
3642
3642
|
results: SearchResult<T>[];
|
|
3643
|
-
|
|
3643
|
+
status: 'idle' | 'loading';
|
|
3644
3644
|
page: number;
|
|
3645
3645
|
setPage: (p: number) => void;
|
|
3646
3646
|
error: string | null;
|
|
@@ -3653,7 +3653,7 @@ export function useSearch<T = Record<string, unknown>>(
|
|
|
3653
3653
|
|
|
3654
3654
|
const [query, setQuery] = useState('');
|
|
3655
3655
|
const [results, setResults] = useState<SearchResult<T>[]>([]);
|
|
3656
|
-
const [
|
|
3656
|
+
const [status, setStatus] = useState<'idle' | 'loading'>('idle');
|
|
3657
3657
|
const [page, setPage] = useState(1);
|
|
3658
3658
|
const [error, setError] = useState<string | null>(null);
|
|
3659
3659
|
const abortRef = useRef<AbortController | null>(null);
|
|
@@ -3662,7 +3662,7 @@ export function useSearch<T = Record<string, unknown>>(
|
|
|
3662
3662
|
async (q: string, p: number) => {
|
|
3663
3663
|
if (!q.trim()) {
|
|
3664
3664
|
setResults([]);
|
|
3665
|
-
|
|
3665
|
+
setStatus('idle');
|
|
3666
3666
|
return;
|
|
3667
3667
|
}
|
|
3668
3668
|
|
|
@@ -3670,7 +3670,7 @@ export function useSearch<T = Record<string, unknown>>(
|
|
|
3670
3670
|
const controller = new AbortController();
|
|
3671
3671
|
abortRef.current = controller;
|
|
3672
3672
|
|
|
3673
|
-
|
|
3673
|
+
setStatus('loading');
|
|
3674
3674
|
setError(null);
|
|
3675
3675
|
|
|
3676
3676
|
try {
|
|
@@ -3698,7 +3698,7 @@ export function useSearch<T = Record<string, unknown>>(
|
|
|
3698
3698
|
setResults([]);
|
|
3699
3699
|
} finally {
|
|
3700
3700
|
if (!controller.signal.aborted) {
|
|
3701
|
-
|
|
3701
|
+
setStatus('idle');
|
|
3702
3702
|
}
|
|
3703
3703
|
}
|
|
3704
3704
|
},
|
|
@@ -3717,7 +3717,7 @@ export function useSearch<T = Record<string, unknown>>(
|
|
|
3717
3717
|
setPage(1);
|
|
3718
3718
|
}, [query]);
|
|
3719
3719
|
|
|
3720
|
-
return { query, setQuery, results,
|
|
3720
|
+
return { query, setQuery, results, status, page, setPage, error };
|
|
3721
3721
|
}
|
|
3722
3722
|
`;
|
|
3723
3723
|
}
|
|
@@ -4573,7 +4573,7 @@ interface UseChatOptions {
|
|
|
4573
4573
|
|
|
4574
4574
|
interface UseChatReturn {
|
|
4575
4575
|
messages: ChatMessage[];
|
|
4576
|
-
|
|
4576
|
+
status: 'idle' | 'loading';
|
|
4577
4577
|
error: string | null;
|
|
4578
4578
|
send: (content: string) => Promise<void>;
|
|
4579
4579
|
reset: () => void;
|
|
@@ -4582,13 +4582,13 @@ interface UseChatReturn {
|
|
|
4582
4582
|
export function useChat(options: UseChatOptions = {}): UseChatReturn {
|
|
4583
4583
|
const { apiUrl = '/api/protected/ai/chat' } = options;
|
|
4584
4584
|
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
|
4585
|
-
const [
|
|
4585
|
+
const [status, setStatus] = useState<'idle' | 'loading'>('idle');
|
|
4586
4586
|
const [error, setError] = useState<string | null>(null);
|
|
4587
4587
|
const abortRef = useRef<AbortController | null>(null);
|
|
4588
4588
|
|
|
4589
4589
|
const send = useCallback(async (content: string) => {
|
|
4590
4590
|
setError(null);
|
|
4591
|
-
|
|
4591
|
+
setStatus('loading');
|
|
4592
4592
|
|
|
4593
4593
|
const userMessage: ChatMessage = { role: 'user', content };
|
|
4594
4594
|
setMessages((prev) => [...prev, userMessage]);
|
|
@@ -4642,7 +4642,7 @@ export function useChat(options: UseChatOptions = {}): UseChatReturn {
|
|
|
4642
4642
|
|
|
4643
4643
|
setMessages((prev) => prev.slice(0, -1));
|
|
4644
4644
|
} finally {
|
|
4645
|
-
|
|
4645
|
+
setStatus('idle');
|
|
4646
4646
|
abortRef.current = null;
|
|
4647
4647
|
}
|
|
4648
4648
|
}, [apiUrl, messages]);
|
|
@@ -4651,10 +4651,10 @@ export function useChat(options: UseChatOptions = {}): UseChatReturn {
|
|
|
4651
4651
|
abortRef.current?.abort();
|
|
4652
4652
|
setMessages([]);
|
|
4653
4653
|
setError(null);
|
|
4654
|
-
|
|
4654
|
+
setStatus('idle');
|
|
4655
4655
|
}, []);
|
|
4656
4656
|
|
|
4657
|
-
return { messages,
|
|
4657
|
+
return { messages, status, error, send, reset };
|
|
4658
4658
|
}
|
|
4659
4659
|
`;
|
|
4660
4660
|
}
|
|
@@ -4668,10 +4668,10 @@ import { Spinner } from '@mars-stack/ui';
|
|
|
4668
4668
|
|
|
4669
4669
|
interface ChatMessagesProps {
|
|
4670
4670
|
messages: ChatMessage[];
|
|
4671
|
-
|
|
4671
|
+
status: 'idle' | 'loading';
|
|
4672
4672
|
}
|
|
4673
4673
|
|
|
4674
|
-
export function ChatMessages({ messages,
|
|
4674
|
+
export function ChatMessages({ messages, status }: ChatMessagesProps) {
|
|
4675
4675
|
const bottomRef = useRef<HTMLDivElement>(null);
|
|
4676
4676
|
|
|
4677
4677
|
useEffect(() => {
|
|
@@ -4718,7 +4718,7 @@ export function ChatMessages({ messages, isLoading }: ChatMessagesProps) {
|
|
|
4718
4718
|
>
|
|
4719
4719
|
{message.content ? (
|
|
4720
4720
|
<p className="text-sm whitespace-pre-wrap">{message.content}</p>
|
|
4721
|
-
) :
|
|
4721
|
+
) : status === 'loading' && index === messages.length - 1 ? (
|
|
4722
4722
|
<div className="flex items-center gap-1.5 py-1">
|
|
4723
4723
|
<Spinner size="sm" />
|
|
4724
4724
|
<span className="text-xs text-text-muted">Thinking...</span>
|
|
@@ -4836,7 +4836,7 @@ interface ChatProps {
|
|
|
4836
4836
|
}
|
|
4837
4837
|
|
|
4838
4838
|
export function Chat({ placeholder, className }: ChatProps) {
|
|
4839
|
-
const { messages,
|
|
4839
|
+
const { messages, status, error, send, reset } = useChat();
|
|
4840
4840
|
|
|
4841
4841
|
return (
|
|
4842
4842
|
<div className={\`flex flex-col h-full \${className ?? ''}\`}>
|
|
@@ -4855,11 +4855,11 @@ export function Chat({ placeholder, className }: ChatProps) {
|
|
|
4855
4855
|
</div>
|
|
4856
4856
|
)}
|
|
4857
4857
|
|
|
4858
|
-
<ChatMessages messages={messages}
|
|
4858
|
+
<ChatMessages messages={messages} status={status} />
|
|
4859
4859
|
|
|
4860
4860
|
<ChatInput
|
|
4861
4861
|
onSend={send}
|
|
4862
|
-
disabled={
|
|
4862
|
+
disabled={status === 'loading'}
|
|
4863
4863
|
placeholder={placeholder}
|
|
4864
4864
|
/>
|
|
4865
4865
|
</div>
|