@agentiffai/design 0.1.11 → 0.1.13

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.
@@ -4,8 +4,8 @@ var button = require('@react-aria/button');
4
4
  var react = require('react');
5
5
  var styled4 = require('styled-components');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
- var textfield = require('@react-aria/textfield');
8
7
  var reactUi = require('@copilotkit/react-ui');
8
+ var textfield = require('@react-aria/textfield');
9
9
 
10
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
@@ -133,6 +133,8 @@ var tokens = {
133
133
  lg: "0.75rem",
134
134
  // 12px
135
135
  xl: "1rem",
136
+ // 16px
137
+ "2xl": "1.5rem",
136
138
  // 24px
137
139
  full: "9999px"
138
140
  // Fully rounded
@@ -633,7 +635,16 @@ var ActionExecutionAdapter = ({ message, inProgress }) => {
633
635
  return null;
634
636
  }
635
637
  const toolName = message.name;
636
- const toolArgs = message.arguments || {};
638
+ let toolArgs = {};
639
+ if (typeof message.arguments === "string") {
640
+ try {
641
+ toolArgs = JSON.parse(message.arguments);
642
+ } catch {
643
+ toolArgs = {};
644
+ }
645
+ } else if (message.arguments && typeof message.arguments === "object") {
646
+ toolArgs = message.arguments;
647
+ }
637
648
  const state = inProgress ? "thinking" : "responding";
638
649
  const statusMessage = getToolMessage(toolName, toolArgs);
639
650
  return /* @__PURE__ */ jsxRuntime.jsxs(Container, { "data-testid": "action-execution-message", children: [
@@ -821,6 +832,9 @@ var Container3 = styled4__default.default.div`
821
832
  white-space: pre-wrap;
822
833
  word-break: break-word;
823
834
  line-height: ${tokens.typography.lineHeight.normal};
835
+ /* Performance optimizations for streaming text */
836
+ text-rendering: optimizeSpeed;
837
+ contain: content;
824
838
  `;
825
839
  var Cursor = styled4__default.default.span`
826
840
  display: inline-block;
@@ -880,20 +894,9 @@ var MessageContainer = styled4__default.default.div`
880
894
  align-items: flex-start;
881
895
  padding: ${tokens.spacing.sm} 0;
882
896
  max-width: 100%;
883
-
884
- /* Fade in and slide up animation */
885
- animation: fadeInSlideUp ${tokens.animation.duration.medium} ease-out;
886
-
887
- @keyframes fadeInSlideUp {
888
- from {
889
- opacity: 0;
890
- transform: translateY(${tokens.spacing.sm});
891
- }
892
- to {
893
- opacity: 1;
894
- transform: translateY(0);
895
- }
896
- }
897
+ /* GPU acceleration hint for smooth rendering during streaming */
898
+ will-change: contents;
899
+ contain: content;
897
900
  `;
898
901
  var AvatarContainer = styled4__default.default.div`
899
902
  flex-shrink: 0;
@@ -928,9 +931,8 @@ var ContentContainer = styled4__default.default.div`
928
931
  min-width: 0;
929
932
  `;
930
933
  var MessageContent = styled4__default.default.div`
931
- background-color: ${tokens.colors.surface.glass};
932
- backdrop-filter: blur(10px);
933
- -webkit-backdrop-filter: blur(10px);
934
+ /* Use solid color instead of backdrop-filter for performance during streaming */
935
+ background-color: ${tokens.colors.surface.elevated};
934
936
  padding: ${tokens.spacing.sm} ${tokens.spacing.md};
935
937
  border-radius: ${tokens.borderRadius.lg};
936
938
  border-top-left-radius: ${tokens.borderRadius.sm};
@@ -940,24 +942,25 @@ var MessageContent = styled4__default.default.div`
940
942
  font-family: ${tokens.typography.fontFamily.primary};
941
943
  word-wrap: break-word;
942
944
  white-space: pre-wrap;
945
+ /* Optimize text rendering */
946
+ text-rendering: optimizeSpeed;
943
947
  `;
944
948
  var LoadingDots3 = styled4__default.default.div`
945
949
  display: flex;
946
950
  gap: ${tokens.spacing.xs};
947
951
  padding: ${tokens.spacing.sm} ${tokens.spacing.md};
948
- background-color: ${tokens.colors.surface.glass};
949
- backdrop-filter: blur(10px);
950
- -webkit-backdrop-filter: blur(10px);
952
+ /* Use solid color instead of backdrop-filter for performance */
953
+ background-color: ${tokens.colors.surface.elevated};
951
954
  border-radius: ${tokens.borderRadius.lg};
952
955
  border-top-left-radius: ${tokens.borderRadius.sm};
953
956
  width: fit-content;
954
957
  `;
955
- var bounce = styled4.keyframes`
956
- 0%, 60%, 100% {
957
- transform: translateY(0);
958
+ var pulse2 = styled4.keyframes`
959
+ 0%, 100% {
960
+ opacity: 0.4;
958
961
  }
959
- 30% {
960
- transform: translateY(-${tokens.spacing.sm});
962
+ 50% {
963
+ opacity: 1;
961
964
  }
962
965
  `;
963
966
  var LoadingDot = styled4__default.default.div`
@@ -965,7 +968,8 @@ var LoadingDot = styled4__default.default.div`
965
968
  height: ${tokens.spacing.sm};
966
969
  border-radius: ${tokens.borderRadius.full};
967
970
  background-color: ${tokens.colors.text.tertiary};
968
- animation: ${bounce} 1.4s ease-in-out infinite;
971
+ /* Use simple opacity animation instead of transform bounce */
972
+ animation: ${pulse2} 1.4s ease-in-out infinite;
969
973
  animation-delay: ${(props) => props.delay}s;
970
974
  `;
971
975
  var FileAttachmentContainer = styled4__default.default.div`
@@ -1209,6 +1213,10 @@ var AssistantMessageBase = ({
1209
1213
  };
1210
1214
  var AssistantMessage = react.memo(AssistantMessageBase);
1211
1215
  AssistantMessage.displayName = "AssistantMessage";
1216
+ var GenerativeUIContainer = styled4__default.default.div`
1217
+ margin-top: ${tokens.spacing.sm};
1218
+ margin-bottom: ${tokens.spacing.sm};
1219
+ `;
1212
1220
  var AssistantMessageAdapterBase = ({
1213
1221
  message,
1214
1222
  isLoading,
@@ -1226,18 +1234,30 @@ var AssistantMessageAdapterBase = ({
1226
1234
  return /* @__PURE__ */ jsxRuntime.jsx(AssistantThinking, { message: "Thinking..." });
1227
1235
  }
1228
1236
  const content = message?.content || "";
1229
- const attachments = [];
1230
- return /* @__PURE__ */ jsxRuntime.jsx(
1231
- AssistantMessage,
1232
- {
1233
- content,
1234
- avatarInitials: "AI",
1235
- isLoading: false,
1236
- isStreaming: isGenerating,
1237
- attachments,
1238
- enableMarkdown: true
1237
+ let generativeUIOutput = null;
1238
+ const msgWithUI = message;
1239
+ if (msgWithUI && typeof msgWithUI.generativeUI === "function") {
1240
+ try {
1241
+ generativeUIOutput = msgWithUI.generativeUI();
1242
+ } catch (e) {
1243
+ console.warn("[AssistantMessageAdapter] Error rendering generativeUI:", e);
1239
1244
  }
1240
- );
1245
+ }
1246
+ const attachments = [];
1247
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1248
+ generativeUIOutput && /* @__PURE__ */ jsxRuntime.jsx(GenerativeUIContainer, { children: generativeUIOutput }),
1249
+ content && /* @__PURE__ */ jsxRuntime.jsx(
1250
+ AssistantMessage,
1251
+ {
1252
+ content,
1253
+ avatarInitials: "AI",
1254
+ isLoading: false,
1255
+ isStreaming: isGenerating,
1256
+ attachments,
1257
+ enableMarkdown: true
1258
+ }
1259
+ )
1260
+ ] });
1241
1261
  };
1242
1262
  var AssistantMessageAdapter = react.memo(AssistantMessageAdapterBase);
1243
1263
  AssistantMessageAdapter.displayName = "AssistantMessageAdapter";
@@ -1273,7 +1293,7 @@ var SuggestionButton = styled4__default.default.button`
1273
1293
  font-weight: ${tokens.typography.fontWeight.regular};
1274
1294
  text-align: center;
1275
1295
  border: 1px solid ${tokens.colors.border.default};
1276
- border-radius: 20px;
1296
+ border-radius: ${tokens.borderRadius.full};
1277
1297
  cursor: pointer;
1278
1298
  transition: all ${tokens.transitions.fast};
1279
1299
  white-space: nowrap;
@@ -1307,9 +1327,9 @@ var SuggestionButton = styled4__default.default.button`
1307
1327
  `;
1308
1328
  var InputWrapper = styled4__default.default.div`
1309
1329
  display: flex;
1310
- align-items: center;
1311
- gap: 10px;
1312
- padding: 10px 14px;
1330
+ align-items: flex-end; /* Align button to bottom when textarea expands */
1331
+ gap: ${tokens.spacing.sm};
1332
+ padding: ${tokens.spacing.sm} ${tokens.spacing.md};
1313
1333
  background-color: rgba(25, 25, 25, 0.4);
1314
1334
  border: 1px solid ${tokens.colors.border.subtle};
1315
1335
  border-radius: ${tokens.borderRadius.lg};
@@ -1323,7 +1343,7 @@ var InputWrapper = styled4__default.default.div`
1323
1343
  background-color: rgba(50, 50, 52, 0.6);
1324
1344
  }
1325
1345
  `;
1326
- var InputField = styled4__default.default.input`
1346
+ var InputField = styled4__default.default.textarea`
1327
1347
  flex: 1;
1328
1348
  border: none;
1329
1349
  outline: none;
@@ -1331,6 +1351,13 @@ var InputField = styled4__default.default.input`
1331
1351
  font-size: ${tokens.typography.fontSize.sm};
1332
1352
  color: ${tokens.colors.text.secondary};
1333
1353
  background: transparent;
1354
+ resize: none; /* Disable manual resize, we auto-resize */
1355
+ min-height: 24px; /* Single line height */
1356
+ max-height: 150px; /* Max ~6 lines before scrolling */
1357
+ overflow-y: auto;
1358
+ line-height: 1.5;
1359
+ padding: 0;
1360
+ margin: 0;
1334
1361
 
1335
1362
  &::placeholder {
1336
1363
  color: ${tokens.colors.text.tertiary};
@@ -1386,31 +1413,29 @@ var ChatInput = ({
1386
1413
  isReadOnly = false,
1387
1414
  autoFocus = false,
1388
1415
  className,
1389
- "aria-label": ariaLabel = "Chat message input",
1390
- ...ariaProps
1416
+ "aria-label": ariaLabel = "Chat message input"
1417
+ // Note: Additional AriaTextFieldProps are accepted but not spread to textarea
1418
+ // since useTextField is not compatible with textarea elements
1391
1419
  }) => {
1392
1420
  const [internalValue, setInternalValue] = react.useState(value);
1393
1421
  const inputRef = react.useRef(null);
1394
1422
  const currentValue = value !== void 0 ? value : internalValue;
1395
1423
  const setValue = onChange || setInternalValue;
1396
- const { inputProps } = textfield.useTextField(
1397
- {
1398
- ...ariaProps,
1399
- "aria-label": ariaLabel,
1400
- value: currentValue,
1401
- onChange: (newValue) => {
1402
- setValue(newValue);
1403
- },
1404
- isDisabled,
1405
- isReadOnly
1406
- },
1407
- inputRef
1408
- );
1424
+ const autoResize = react.useCallback(() => {
1425
+ const textarea = inputRef.current;
1426
+ if (textarea) {
1427
+ textarea.style.height = "auto";
1428
+ textarea.style.height = `${textarea.scrollHeight}px`;
1429
+ }
1430
+ }, []);
1431
+ react.useEffect(() => {
1432
+ autoResize();
1433
+ }, [currentValue, autoResize]);
1409
1434
  const handleDirectChange = (e) => {
1410
1435
  setValue(e.target.value);
1411
1436
  };
1412
1437
  const handleKeyDown = (e) => {
1413
- if (e.key === "Enter") {
1438
+ if (e.key === "Enter" && !e.shiftKey) {
1414
1439
  e.preventDefault();
1415
1440
  handleSubmit();
1416
1441
  }
@@ -1419,6 +1444,9 @@ var ChatInput = ({
1419
1444
  if (currentValue.trim() && onSubmit && !isDisabled && !isReadOnly) {
1420
1445
  onSubmit(currentValue.trim());
1421
1446
  setValue("");
1447
+ if (inputRef.current) {
1448
+ inputRef.current.style.height = "auto";
1449
+ }
1422
1450
  inputRef.current?.focus();
1423
1451
  }
1424
1452
  };
@@ -1442,16 +1470,16 @@ var ChatInput = ({
1442
1470
  /* @__PURE__ */ jsxRuntime.jsx(
1443
1471
  InputField,
1444
1472
  {
1445
- ...inputProps,
1446
1473
  ref: inputRef,
1447
- type: "text",
1474
+ "aria-label": ariaLabel,
1448
1475
  placeholder,
1449
1476
  onKeyDown: handleKeyDown,
1450
1477
  onChange: handleDirectChange,
1451
1478
  autoFocus,
1452
1479
  disabled: isDisabled,
1453
1480
  readOnly: isReadOnly,
1454
- value: currentValue
1481
+ value: currentValue,
1482
+ rows: 1
1455
1483
  }
1456
1484
  ),
1457
1485
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1599,7 +1627,7 @@ var StyledUserMessage = styled4__default.default.button`
1599
1627
  && {
1600
1628
  background: ${tokens.colors.message.user} !important;
1601
1629
  color: ${tokens.colors.text.primary} !important;
1602
- border-radius: ${tokens.borderRadius.full} !important; /* Pill shape - fully rounded ends */
1630
+ border-radius: ${tokens.borderRadius["2xl"]} !important; /* Rounded corners that work for multi-line */
1603
1631
  }
1604
1632
 
1605
1633
  /* Subtle shadow and glow effect */
@@ -1717,20 +1745,8 @@ var UserMessageWrapper = styled4__default.default.div`
1717
1745
  justify-content: flex-end;
1718
1746
  width: 100%;
1719
1747
  padding: ${tokens.spacing.sm} 0;
1720
-
1721
- /* Fade in and slide up animation */
1722
- animation: fadeInSlideUp ${tokens.animation.duration.medium} ease-out;
1723
-
1724
- @keyframes fadeInSlideUp {
1725
- from {
1726
- opacity: 0;
1727
- transform: translateY(${tokens.spacing.sm});
1728
- }
1729
- to {
1730
- opacity: 1;
1731
- transform: translateY(0);
1732
- }
1733
- }
1748
+ /* Performance optimization - isolate layout/paint */
1749
+ contain: content;
1734
1750
  `;
1735
1751
  var UserMessageAdapterBase = ({
1736
1752
  message,
@@ -1744,7 +1760,7 @@ var UserMessageAdapterBase = ({
1744
1760
  };
1745
1761
  var UserMessageAdapter = react.memo(UserMessageAdapterBase);
1746
1762
  UserMessageAdapter.displayName = "UserMessageAdapter";
1747
- var pulse2 = styled4.keyframes`
1763
+ var pulse3 = styled4.keyframes`
1748
1764
  0%, 100% {
1749
1765
  opacity: 1;
1750
1766
  transform: scale(1);
@@ -1828,7 +1844,7 @@ var StatusDot = styled4__default.default.div`
1828
1844
  return tokens.colors.connection.reconnecting;
1829
1845
  }
1830
1846
  }};
1831
- animation: ${(props) => props.status === "streaming" ? pulse2 : "none"} 2s ease-in-out infinite;
1847
+ animation: ${(props) => props.status === "streaming" ? pulse3 : "none"} 2s ease-in-out infinite;
1832
1848
  flex-shrink: 0;
1833
1849
  `;
1834
1850
  var Label = styled4__default.default.span`
@@ -2344,8 +2360,8 @@ var StyledChatButton = styled4__default.default.button`
2344
2360
  height: 36px;
2345
2361
  border-radius: 18px;
2346
2362
  border: none;
2347
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
2348
- box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
2363
+ background: linear-gradient(135deg, ${tokens.colors.primary} 0%, ${tokens.colors.accent} 100%);
2364
+ box-shadow: 0 4px 12px rgba(44, 176, 171, 0.4);
2349
2365
  display: flex;
2350
2366
  align-items: center;
2351
2367
  justify-content: center;
@@ -2355,7 +2371,7 @@ var StyledChatButton = styled4__default.default.button`
2355
2371
 
2356
2372
  &:hover {
2357
2373
  transform: scale(1.05);
2358
- box-shadow: 0 6px 16px rgba(102, 126, 234, 0.5);
2374
+ box-shadow: 0 6px 16px rgba(44, 176, 171, 0.5);
2359
2375
  }
2360
2376
 
2361
2377
  &:active {
@@ -2595,20 +2611,10 @@ var GlobalSidebarStyles2 = styled4.createGlobalStyle`
2595
2611
  background-color: transparent !important;
2596
2612
  }
2597
2613
 
2598
- /* Fade-in animation for new messages */
2599
- @keyframes messagesFadeIn {
2600
- from {
2601
- opacity: 0;
2602
- transform: translateY(${tokens.spacing.sm});
2603
- }
2604
- to {
2605
- opacity: 1;
2606
- transform: translateY(0);
2607
- }
2608
- }
2609
-
2614
+ /* Performance optimization for messages - no animations to reduce jitter during streaming */
2610
2615
  .copilotKitMessage {
2611
- animation: messagesFadeIn 0.3s ease-out;
2616
+ /* contain: content isolates layout/paint to this element */
2617
+ contain: content;
2612
2618
  }
2613
2619
 
2614
2620
  /* Override CopilotKit suggestions to be single-row with horizontal scroll */
@@ -2699,7 +2705,9 @@ function CustomCopilotSidebar2({
2699
2705
  instructions,
2700
2706
  className,
2701
2707
  disabled = false,
2702
- disabledReason = "Start a free trial to enable AI chat"
2708
+ disabledReason = "Start a free trial to enable AI chat",
2709
+ onError,
2710
+ renderError
2703
2711
  }) {
2704
2712
  const HeaderAdapterWithClose = (_props) => {
2705
2713
  const { setOpen } = reactUi.useChatContext();
@@ -2769,6 +2777,8 @@ function CustomCopilotSidebar2({
2769
2777
  clickOutsideToClose: true,
2770
2778
  hitEscapeToClose: true,
2771
2779
  onSetOpen,
2780
+ onError,
2781
+ renderError,
2772
2782
  className,
2773
2783
  children
2774
2784
  }