@agentiffai/design 0.1.9 → 0.1.11

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.
@@ -217,7 +217,7 @@ declare const FileAttachment: React__default.FC<FileAttachmentProps>;
217
217
  interface ActionButtonType$1 {
218
218
  label: string;
219
219
  onClick: () => void;
220
- icon?: React__default.ReactNode;
220
+ icon?: React.ReactNode;
221
221
  }
222
222
  interface AssistantMessageProps {
223
223
  /** Message content to display */
@@ -241,20 +241,7 @@ interface AssistantMessageProps {
241
241
  /** Action buttons to display */
242
242
  actions?: ActionButtonType$1[];
243
243
  }
244
- /**
245
- * AssistantMessage component displays AI assistant messages with avatar
246
- *
247
- * Features:
248
- * - Avatar with image or initials fallback
249
- * - Loading state with animated dots
250
- * - Streaming state indicator
251
- * - Markdown support (optional)
252
- * - Dark gray bubble (#2D2D3D) from Figma design
253
- * - Left-aligned layout
254
- * - Action buttons support
255
- * - Timestamp display
256
- */
257
- declare const AssistantMessage: React__default.FC<AssistantMessageProps>;
244
+ declare const AssistantMessage: React$1.NamedExoticComponent<AssistantMessageProps>;
258
245
 
259
246
  interface MessagesProps {
260
247
  /**
@@ -440,17 +427,7 @@ interface StreamingTextProps {
440
427
  /** Additional CSS class name */
441
428
  className?: string;
442
429
  }
443
- /**
444
- * StreamingText component with typewriter animation
445
- *
446
- * Features:
447
- * - Character-by-character streaming animation
448
- * - Configurable typing speed
449
- * - Optional blinking cursor
450
- * - Code and markdown variants
451
- * - Completion callback
452
- */
453
- declare const StreamingText: React.FC<StreamingTextProps>;
430
+ declare const StreamingText: React$1.NamedExoticComponent<StreamingTextProps>;
454
431
 
455
432
  /**
456
433
  * StreamStatusIndicator Component
@@ -217,7 +217,7 @@ declare const FileAttachment: React__default.FC<FileAttachmentProps>;
217
217
  interface ActionButtonType$1 {
218
218
  label: string;
219
219
  onClick: () => void;
220
- icon?: React__default.ReactNode;
220
+ icon?: React.ReactNode;
221
221
  }
222
222
  interface AssistantMessageProps {
223
223
  /** Message content to display */
@@ -241,20 +241,7 @@ interface AssistantMessageProps {
241
241
  /** Action buttons to display */
242
242
  actions?: ActionButtonType$1[];
243
243
  }
244
- /**
245
- * AssistantMessage component displays AI assistant messages with avatar
246
- *
247
- * Features:
248
- * - Avatar with image or initials fallback
249
- * - Loading state with animated dots
250
- * - Streaming state indicator
251
- * - Markdown support (optional)
252
- * - Dark gray bubble (#2D2D3D) from Figma design
253
- * - Left-aligned layout
254
- * - Action buttons support
255
- * - Timestamp display
256
- */
257
- declare const AssistantMessage: React__default.FC<AssistantMessageProps>;
244
+ declare const AssistantMessage: React$1.NamedExoticComponent<AssistantMessageProps>;
258
245
 
259
246
  interface MessagesProps {
260
247
  /**
@@ -440,17 +427,7 @@ interface StreamingTextProps {
440
427
  /** Additional CSS class name */
441
428
  className?: string;
442
429
  }
443
- /**
444
- * StreamingText component with typewriter animation
445
- *
446
- * Features:
447
- * - Character-by-character streaming animation
448
- * - Configurable typing speed
449
- * - Optional blinking cursor
450
- * - Code and markdown variants
451
- * - Completion callback
452
- */
453
- declare const StreamingText: React.FC<StreamingTextProps>;
430
+ declare const StreamingText: React$1.NamedExoticComponent<StreamingTextProps>;
454
431
 
455
432
  /**
456
433
  * StreamStatusIndicator Component
@@ -842,7 +842,7 @@ var Cursor = styled4__default.default.span`
842
842
  }
843
843
  }
844
844
  `;
845
- var StreamingText2 = ({
845
+ var StreamingTextBase = ({
846
846
  content,
847
847
  isStreaming = false,
848
848
  typingSpeed: _typingSpeed = 50,
@@ -852,25 +852,27 @@ var StreamingText2 = ({
852
852
  onStreamComplete,
853
853
  className
854
854
  }) => {
855
- const [displayedText, setDisplayedText] = react.useState("");
855
+ const [displayedText, setDisplayedText] = react.useState(content);
856
+ const wasStreamingRef = react.useRef(isStreaming);
857
+ const completionCalledRef = react.useRef(false);
856
858
  react.useEffect(() => {
857
- if (isStreaming) {
858
- setDisplayedText(content);
859
- return;
859
+ setDisplayedText(content);
860
+ if (wasStreamingRef.current && !isStreaming && !completionCalledRef.current) {
861
+ completionCalledRef.current = true;
862
+ onStreamComplete?.();
860
863
  }
861
- if (!isStreaming && displayedText !== content) {
862
- setDisplayedText(content);
863
- if (onStreamComplete) {
864
- onStreamComplete();
865
- }
864
+ if (isStreaming) {
865
+ completionCalledRef.current = false;
866
866
  }
867
- }, [content, isStreaming, onStreamComplete, displayedText]);
867
+ wasStreamingRef.current = isStreaming;
868
+ }, [content, isStreaming, onStreamComplete]);
868
869
  const showCursor = isStreaming && cursor;
869
870
  return /* @__PURE__ */ jsxRuntime.jsxs(Container3, { variant, className, children: [
870
871
  displayedText,
871
872
  showCursor && /* @__PURE__ */ jsxRuntime.jsx(Cursor, {})
872
873
  ] });
873
874
  };
875
+ var StreamingText2 = react.memo(StreamingTextBase);
874
876
  StreamingText2.displayName = "StreamingText";
875
877
  var MessageContainer = styled4__default.default.div`
876
878
  display: flex;
@@ -1158,7 +1160,7 @@ var StreamingIndicator = styled4__default.default.span`
1158
1160
  }
1159
1161
  }
1160
1162
  `;
1161
- var AssistantMessage = ({
1163
+ var AssistantMessageBase = ({
1162
1164
  content = "",
1163
1165
  avatarUrl,
1164
1166
  avatarInitials: _avatarInitials = "AI",
@@ -1205,7 +1207,9 @@ var AssistantMessage = ({
1205
1207
  /* @__PURE__ */ jsxRuntime.jsx(ContentContainer, { children: renderContent() })
1206
1208
  ] });
1207
1209
  };
1208
- var AssistantMessageAdapter = ({
1210
+ var AssistantMessage = react.memo(AssistantMessageBase);
1211
+ AssistantMessage.displayName = "AssistantMessage";
1212
+ var AssistantMessageAdapterBase = ({
1209
1213
  message,
1210
1214
  isLoading,
1211
1215
  isGenerating
@@ -1235,6 +1239,7 @@ var AssistantMessageAdapter = ({
1235
1239
  }
1236
1240
  );
1237
1241
  };
1242
+ var AssistantMessageAdapter = react.memo(AssistantMessageAdapterBase);
1238
1243
  AssistantMessageAdapter.displayName = "AssistantMessageAdapter";
1239
1244
  var ChatInputContainer = styled4__default.default.div`
1240
1245
  display: flex;
@@ -1674,7 +1679,7 @@ var StyledUserMessage = styled4__default.default.button`
1674
1679
  }
1675
1680
  }
1676
1681
  `;
1677
- function UserMessage({
1682
+ function UserMessageBase({
1678
1683
  children,
1679
1684
  className,
1680
1685
  isPressed = false,
@@ -1705,6 +1710,7 @@ function UserMessage({
1705
1710
  }
1706
1711
  );
1707
1712
  }
1713
+ var UserMessage = react.memo(UserMessageBase);
1708
1714
  UserMessage.displayName = "UserMessage";
1709
1715
  var UserMessageWrapper = styled4__default.default.div`
1710
1716
  display: flex;
@@ -1726,7 +1732,7 @@ var UserMessageWrapper = styled4__default.default.div`
1726
1732
  }
1727
1733
  }
1728
1734
  `;
1729
- var UserMessageAdapter = ({
1735
+ var UserMessageAdapterBase = ({
1730
1736
  message,
1731
1737
  ImageRenderer
1732
1738
  }) => {
@@ -1736,6 +1742,7 @@ var UserMessageAdapter = ({
1736
1742
  const content = message?.content || "";
1737
1743
  return /* @__PURE__ */ jsxRuntime.jsx(UserMessageWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(UserMessage, { children: content }) });
1738
1744
  };
1745
+ var UserMessageAdapter = react.memo(UserMessageAdapterBase);
1739
1746
  UserMessageAdapter.displayName = "UserMessageAdapter";
1740
1747
  var pulse2 = styled4.keyframes`
1741
1748
  0%, 100% {
@@ -2460,16 +2467,24 @@ var CustomCopilotSidebar = ({
2460
2467
  };
2461
2468
  CustomCopilotSidebar.displayName = "CustomCopilotSidebar";
2462
2469
  var GlobalSidebarStyles2 = styled4.createGlobalStyle`
2470
+ /* Override CopilotKit's content wrapper to respect safe areas in landscape */
2471
+ @media (orientation: landscape) {
2472
+ .copilotKitSidebarContentWrapper {
2473
+ right: env(safe-area-inset-right, 0px) !important;
2474
+ left: env(safe-area-inset-left, 0px) !important;
2475
+ }
2476
+ }
2477
+
2463
2478
  /* Override CopilotKit's default positioning - keep sidebar container in place */
2464
2479
  /* z-index must be higher than NavHorizontal (sticky: 1020) for button to show above nav */
2465
2480
  .copilotKitSidebar {
2466
2481
  position: fixed !important;
2467
- top: 0 !important;
2468
- right: 0 !important;
2469
- bottom: 0 !important;
2470
- left: 0 !important;
2471
- width: 100vw !important;
2472
- height: 100vh !important;
2482
+ top: calc(var(--safe-area-top, 0px) + 8px) !important;
2483
+ right: calc(var(--safe-area-right, 0px) + 8px) !important;
2484
+ bottom: calc(var(--safe-area-bottom, 0px) + 8px) !important;
2485
+ left: calc(var(--safe-area-left, 0px) + 8px) !important;
2486
+ width: auto !important;
2487
+ height: auto !important;
2473
2488
  pointer-events: none !important;
2474
2489
  z-index: ${tokens.zIndex.fixed} !important;
2475
2490
  }
@@ -2484,16 +2499,19 @@ var GlobalSidebarStyles2 = styled4.createGlobalStyle`
2484
2499
  .copilotKitSidebar [role="dialog"] {
2485
2500
  /* Override CopilotKit defaults for mobile */
2486
2501
  position: fixed !important;
2487
- top: ${tokens.spacing.sm} !important;
2488
- right: ${tokens.spacing.sm} !important;
2489
- /* Reserve space for Android nav buttons - matches NavHorizontal approach */
2490
- bottom: max(90px, env(safe-area-inset-bottom, 90px)) !important;
2491
- left: ${tokens.spacing.sm} !important;
2492
- width: calc(100vw - ${tokens.spacing.lg}) !important;
2493
- /* Adjust height to account for bottom safe area */
2494
- height: calc(100vh - ${tokens.spacing.lg} - max(80px, env(safe-area-inset-bottom, 80px))) !important;
2495
- max-width: calc(100vw - ${tokens.spacing.lg}) !important;
2496
- max-height: calc(100vh - ${tokens.spacing.lg} - max(80px, env(safe-area-inset-bottom, 80px))) !important;
2502
+ /* TOP: Account for status bar safe area (Android notch/status bar) */
2503
+ top: calc(${tokens.spacing.sm} + env(safe-area-inset-top, 0px)) !important;
2504
+ /* RIGHT: Account for landscape notch on right side */
2505
+ right: calc(${tokens.spacing.sm} + env(safe-area-inset-right, 0px)) !important;
2506
+ /* BOTTOM: Account for horizontal navbar (52px) + safe area for Android nav buttons */
2507
+ bottom: calc(52px + ${tokens.spacing.sm} + env(safe-area-inset-bottom, 0px)) !important;
2508
+ /* LEFT: Account for landscape notch on left side */
2509
+ left: calc(${tokens.spacing.sm} + env(safe-area-inset-left, 0px)) !important;
2510
+ width: calc(100vw - ${tokens.spacing.lg} - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)) !important;
2511
+ /* Adjust height to account for top, bottom safe areas, and navbar */
2512
+ height: calc(100vh - ${tokens.spacing.lg} - env(safe-area-inset-top, 0px) - 52px - env(safe-area-inset-bottom, 0px)) !important;
2513
+ max-width: calc(100vw - ${tokens.spacing.lg} - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px)) !important;
2514
+ max-height: calc(100vh - ${tokens.spacing.lg} - env(safe-area-inset-top, 0px) - 52px - env(safe-area-inset-bottom, 0px)) !important;
2497
2515
  margin: 0 !important;
2498
2516
  border-radius: ${tokens.borderRadius.xl} !important;
2499
2517
 
@@ -2529,16 +2547,18 @@ var GlobalSidebarStyles2 = styled4.createGlobalStyle`
2529
2547
  @media (min-width: ${tokens.breakpoints.mobile}px) {
2530
2548
  .copilotKitSidebar [role="dialog"] {
2531
2549
  inset: auto !important;
2532
- top: ${tokens.spacing.sm} !important;
2533
- right: ${tokens.spacing.sm} !important;
2534
- /* Reserve space for Android nav buttons on desktop too */
2535
- bottom: max(90px, env(safe-area-inset-bottom, 90px)) !important;
2550
+ /* TOP: Account for status bar safe area */
2551
+ top: calc(${tokens.spacing.sm} + env(safe-area-inset-top, 0px)) !important;
2552
+ /* RIGHT: Account for landscape notch on right side */
2553
+ right: calc(${tokens.spacing.sm} + env(safe-area-inset-right, 0px)) !important;
2554
+ /* BOTTOM: Account for horizontal navbar (52px) + safe area */
2555
+ bottom: calc(52px + ${tokens.spacing.sm} + env(safe-area-inset-bottom, 0px)) !important;
2536
2556
  left: auto !important;
2537
2557
  width: 28rem !important;
2538
- /* Adjust height to account for bottom safe area */
2539
- height: calc(100vh - ${tokens.spacing.lg} - max(80px, env(safe-area-inset-bottom, 80px))) !important;
2558
+ /* Adjust height to account for top, bottom safe areas, and navbar */
2559
+ height: calc(100vh - ${tokens.spacing.lg} - env(safe-area-inset-top, 0px) - 52px - env(safe-area-inset-bottom, 0px)) !important;
2540
2560
  max-width: 28rem !important;
2541
- max-height: calc(100vh - ${tokens.spacing.lg} - max(80px, env(safe-area-inset-bottom, 80px))) !important;
2561
+ max-height: calc(100vh - ${tokens.spacing.lg} - env(safe-area-inset-top, 0px) - 52px - env(safe-area-inset-bottom, 0px)) !important;
2542
2562
  }
2543
2563
  }
2544
2564
 
@@ -2558,6 +2578,18 @@ var GlobalSidebarStyles2 = styled4.createGlobalStyle`
2558
2578
  }
2559
2579
  }
2560
2580
 
2581
+ /* Position chat button with safe area on landscape (right side for Android controls) */
2582
+ @media (orientation: landscape) {
2583
+ .copilotKitSidebarContentWrapper {
2584
+ button[aria-label="Open chat"],
2585
+ button[aria-label="Close chat"] {
2586
+ bottom: calc(var(--safe-area-bottom, 0px) + 8px) !important;
2587
+ right: calc(var(--safe-area-right, 0px) + 8px) !important;
2588
+ z-index: 2000 !important;
2589
+ }
2590
+ }
2591
+ }
2592
+
2561
2593
  /* Fix messages container background */
2562
2594
  .copilotKitMessages {
2563
2595
  background-color: transparent !important;
@@ -2628,8 +2660,8 @@ var GlobalSidebarStyles2 = styled4.createGlobalStyle`
2628
2660
  `;
2629
2661
  var StyledChatButton2 = styled4__default.default.button`
2630
2662
  position: fixed;
2631
- bottom: ${tokens.spacing.sm};
2632
- right: ${tokens.spacing.sm};
2663
+ bottom: calc(${tokens.spacing.sm} + env(safe-area-inset-bottom, 0px));
2664
+ right: calc(${tokens.spacing.sm} + env(safe-area-inset-right, 0px));
2633
2665
  width: 36px;
2634
2666
  height: 36px;
2635
2667
  border-radius: ${tokens.borderRadius.full};