@shapesos/clay 0.4.0 → 0.5.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.
Files changed (75) hide show
  1. package/dist/chat.cjs +259 -417
  2. package/dist/chat.cjs.map +1 -1
  3. package/dist/chat.d.cts +16 -22
  4. package/dist/chat.d.ts +16 -22
  5. package/dist/chat.js +16 -6
  6. package/dist/chunk-72TJUKMV.js +1 -0
  7. package/dist/{chunk-UKM5VQKW.js → chunk-BIATJTD4.js} +5 -5
  8. package/dist/chunk-BIATJTD4.js.map +1 -0
  9. package/dist/chunk-DRBRT57F.js +1 -0
  10. package/dist/chunk-DRBRT57F.js.map +1 -0
  11. package/dist/chunk-JC2RQL5O.js +76 -0
  12. package/dist/chunk-JC2RQL5O.js.map +1 -0
  13. package/dist/{chunk-6HNZQ2BF.js → chunk-JF3P66JF.js} +2 -1
  14. package/dist/chunk-JF3P66JF.js.map +1 -0
  15. package/dist/chunk-K2Q5MQWJ.js +17 -0
  16. package/dist/chunk-K2Q5MQWJ.js.map +1 -0
  17. package/dist/chunk-MLCRDVQ2.js +89 -0
  18. package/dist/chunk-MLCRDVQ2.js.map +1 -0
  19. package/dist/chunk-OLJIJYB5.js +46 -0
  20. package/dist/chunk-OLJIJYB5.js.map +1 -0
  21. package/dist/chunk-PCBRMJJJ.js +415 -0
  22. package/dist/chunk-PCBRMJJJ.js.map +1 -0
  23. package/dist/chunk-SMTOVZ3O.js +19 -0
  24. package/dist/chunk-SMTOVZ3O.js.map +1 -0
  25. package/dist/{chunk-A6DKIFWS.js → chunk-WQ2QTUYA.js} +9 -1
  26. package/dist/chunk-WQ2QTUYA.js.map +1 -0
  27. package/dist/chunk-WZHNMC6P.js +77 -0
  28. package/dist/chunk-WZHNMC6P.js.map +1 -0
  29. package/dist/icon.cjs +38 -23
  30. package/dist/icon.cjs.map +1 -1
  31. package/dist/icon.d.cts +6 -2
  32. package/dist/icon.d.ts +6 -2
  33. package/dist/icon.js +6 -4
  34. package/dist/index.cjs +417 -449
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +5 -11
  37. package/dist/index.d.ts +5 -11
  38. package/dist/index.js +42 -34
  39. package/dist/index.js.map +1 -1
  40. package/dist/keyboard-shortcut.cjs +238 -0
  41. package/dist/keyboard-shortcut.cjs.map +1 -0
  42. package/dist/keyboard-shortcut.d.cts +19 -0
  43. package/dist/keyboard-shortcut.d.ts +19 -0
  44. package/dist/keyboard-shortcut.js +14 -0
  45. package/dist/keyboard-shortcut.js.map +1 -0
  46. package/dist/lottie.cjs +5 -5
  47. package/dist/lottie.cjs.map +1 -1
  48. package/dist/lottie.js +1 -1
  49. package/dist/text-area.cjs +497 -0
  50. package/dist/text-area.cjs.map +1 -0
  51. package/dist/text-area.d.cts +18 -0
  52. package/dist/text-area.d.ts +18 -0
  53. package/dist/text-area.js +11 -0
  54. package/dist/text-area.js.map +1 -0
  55. package/dist/tokens.cjs +9 -0
  56. package/dist/tokens.cjs.map +1 -1
  57. package/dist/tokens.d.cts +2 -0
  58. package/dist/tokens.d.ts +2 -0
  59. package/dist/tokens.js +2 -2
  60. package/dist/utils.cjs +60 -0
  61. package/dist/utils.cjs.map +1 -0
  62. package/dist/utils.d.cts +7 -0
  63. package/dist/utils.d.ts +7 -0
  64. package/dist/utils.js +13 -0
  65. package/dist/utils.js.map +1 -0
  66. package/package.json +17 -1
  67. package/dist/chunk-2GFOESHR.js +0 -613
  68. package/dist/chunk-2GFOESHR.js.map +0 -1
  69. package/dist/chunk-6HNZQ2BF.js.map +0 -1
  70. package/dist/chunk-7AJSQJQ5.js +0 -1
  71. package/dist/chunk-A6DKIFWS.js.map +0 -1
  72. package/dist/chunk-P7NISN4V.js +0 -115
  73. package/dist/chunk-P7NISN4V.js.map +0 -1
  74. package/dist/chunk-UKM5VQKW.js.map +0 -1
  75. /package/dist/{chunk-7AJSQJQ5.js.map → chunk-72TJUKMV.js.map} +0 -0
package/dist/chat.cjs CHANGED
@@ -30,64 +30,28 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/chat/index.ts
31
31
  var chat_exports = {};
32
32
  __export(chat_exports, {
33
- Chat: () => Chat
33
+ ChatContext: () => ChatContext,
34
+ ChatMessage: () => ChatMessage,
35
+ MESSAGE_ROLE: () => MESSAGE_ROLE,
36
+ useChatContext: () => useChatContext,
37
+ useCopyToClipboard: () => useCopyToClipboard
34
38
  });
35
39
  module.exports = __toCommonJS(chat_exports);
36
40
 
37
- // src/chat/chat-root/chat-root.tsx
38
- var import_react2 = require("react");
39
-
40
- // src/chat/chat-context/chat-context.ts
41
- var import_react = require("react");
42
- var ChatContext = (0, import_react.createContext)(null);
43
- function useChatContext() {
44
- const context = (0, import_react.useContext)(ChatContext);
45
- if (!context) {
46
- throw new Error("useChatContext must be used within a Chat.Root component");
47
- }
48
- return context;
49
- }
50
-
51
- // src/chat/chat-root/chat-root-styles.ts
52
- var import_styled_components = __toESM(require("styled-components"), 1);
53
- var RootContainer = import_styled_components.default.div`
54
- display: flex;
55
- flex-direction: column;
56
- height: 100%;
57
- overflow: hidden;
58
- `;
59
-
60
- // src/chat/chat-root/chat-root.tsx
61
- var import_jsx_runtime = require("react/jsx-runtime");
62
- function ChatRoot({
63
- messages,
64
- onSendMessage,
65
- isLoading = false,
66
- onStop,
67
- onCopyMessage,
68
- onThumbUpClick,
69
- onThumbDownClick,
70
- children
71
- }) {
72
- const contextValue = (0, import_react2.useMemo)(
73
- () => ({ messages, onSendMessage, isLoading, onStop, onCopyMessage, onThumbUpClick, onThumbDownClick }),
74
- [messages, onSendMessage, isLoading, onStop, onCopyMessage, onThumbUpClick, onThumbDownClick]
75
- );
76
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RootContainer, { children }) });
77
- }
78
-
79
41
  // src/chat/chat-message-content/chat-message-content.tsx
80
42
  var import_react_markdown = __toESM(require("react-markdown"), 1);
43
+ var import_remark_breaks = __toESM(require("remark-breaks"), 1);
81
44
  var import_remark_gfm = __toESM(require("remark-gfm"), 1);
82
45
 
83
46
  // src/chat/chat-message-content/chat-message-content-styles.ts
84
- var import_styled_components2 = __toESM(require("styled-components"), 1);
47
+ var import_styled_components = __toESM(require("styled-components"), 1);
85
48
 
86
49
  // src/tokens/colors.ts
87
50
  var colors = {
88
51
  // White
89
52
  white: "#FFFFFF",
90
53
  "white-alpha-85": "rgba(255, 255, 255, 0.85)",
54
+ "white-alpha-40": "rgba(255, 255, 255, 0.40)",
91
55
  // Brown
92
56
  "brown-10": "#FAF9F8",
93
57
  "brown-20": "#F5F3F0",
@@ -188,6 +152,7 @@ var typographyTypes = {
188
152
  GEIST_BODY_S_REGULAR: "GEIST_BODY_S_REGULAR",
189
153
  GEIST_BODY_S_MEDIUM: "GEIST_BODY_S_MEDIUM",
190
154
  GEIST_BODY_S_SEMI_BOLD: "GEIST_BODY_S_SEMI_BOLD",
155
+ GEIST_BODY_S_BOLD: "GEIST_BODY_S_BOLD",
191
156
  // Geist Body Medium (18px)
192
157
  GEIST_BODY_M_LIGHT: "GEIST_BODY_M_LIGHT",
193
158
  GEIST_BODY_M_REGULAR: "GEIST_BODY_M_REGULAR",
@@ -281,6 +246,13 @@ var typographyStyles = {
281
246
  lineHeight: 24,
282
247
  letterSpacing: -0.08
283
248
  },
249
+ [typographyTypes.GEIST_BODY_S_BOLD]: {
250
+ fontFamily: fontFamilies.GEIST,
251
+ fontSize: 16,
252
+ fontWeight: 700,
253
+ lineHeight: 24,
254
+ letterSpacing: -0.08
255
+ },
284
256
  // Geist Body Medium (18px)
285
257
  [typographyTypes.GEIST_BODY_M_LIGHT]: {
286
258
  fontFamily: fontFamilies.GEIST,
@@ -456,88 +428,142 @@ function typographyMixin(type) {
456
428
  }
457
429
 
458
430
  // src/chat/chat-message-content/chat-message-content-styles.ts
459
- var ContentWrapper = import_styled_components2.default.div`
460
- ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
431
+ var ContentWrapper = import_styled_components.default.div`
432
+ ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
461
433
  color: ${colors["brown-100"]};
462
434
  word-break: break-word;
463
435
 
464
- & p {
465
- margin: 0;
436
+ & h1 {
437
+ ${typographyMixin(typographyTypes.GEIST_HEADING_S_BOLD)};
438
+ margin-block: 20px;
439
+ }
440
+
441
+ & h2 {
442
+ ${typographyMixin(typographyTypes.GEIST_BODY_L_SEMI_BOLD)};
443
+ margin-block: 12px;
444
+ }
445
+
446
+ & h3,
447
+ & h4,
448
+ & h5,
449
+ & h6 {
450
+ ${typographyMixin(typographyTypes.GEIST_BODY_M_SEMI_BOLD)};
451
+ margin-block: 8px;
466
452
  }
467
453
 
468
- & p + p {
469
- margin-top: 8px;
454
+ & strong {
455
+ ${typographyMixin(typographyTypes.GEIST_BODY_S_SEMI_BOLD)};
456
+ }
457
+
458
+ & p {
459
+ margin-block: 8px;
470
460
  }
471
461
 
472
462
  & ul,
473
463
  & ol {
474
- margin: 4px 0;
464
+ margin-block: 16px;
475
465
  padding-left: 20px;
476
466
  }
477
467
 
478
- & a {
479
- color: ${colors["brown-100"]};
480
- text-decoration: underline;
468
+ & li + li {
469
+ margin-block: 4px;
481
470
  }
482
471
 
483
- & pre {
484
- overflow-x: auto;
485
- padding: 8px;
486
- margin: 4px 0;
487
- background: ${colors["brown-10"]};
488
- border: 1px solid ${colors["brown-alpha-12"]};
489
- border-radius: 8px;
472
+ & ol {
473
+ list-style-type: decimal;
490
474
  }
491
475
 
492
- & pre code {
493
- padding: 0;
494
- background: none;
495
- border-radius: 0;
476
+ & ol ol {
477
+ list-style-type: lower-alpha;
478
+ }
479
+
480
+ & ol ol ol {
481
+ list-style-type: lower-roman;
482
+ }
483
+
484
+ & a {
485
+ color: inherit;
486
+ text-decoration-line: underline;
487
+ text-decoration-style: dotted;
488
+ text-decoration-thickness: auto;
489
+ text-underline-offset: auto;
490
+ text-underline-position: from-font;
491
+ transition: color 75ms ease-in-out;
492
+
493
+ &:hover {
494
+ color: ${colors["blue-600"]};
495
+ }
496
496
  }
497
497
 
498
- & code {
499
- padding: 2px 4px;
500
- background: ${colors["brown-10"]};
501
- border-radius: 4px;
498
+ & hr {
499
+ border: none;
500
+ border-top: 1px solid ${colors["brown-40"]};
501
+ margin-block: 20px;
502
502
  }
503
503
 
504
504
  & table {
505
- border-collapse: collapse;
506
- margin: 8px 0;
505
+ margin: 0;
507
506
  width: 100%;
507
+ border-collapse: collapse;
508
508
  }
509
509
 
510
510
  & th,
511
511
  & td {
512
- border: 1px solid ${colors["brown-alpha-12"]};
513
- padding: 6px 12px;
512
+ border: none;
513
+ border-bottom: 1px solid ${colors["brown-40"]};
514
514
  text-align: left;
515
515
  }
516
516
 
517
517
  & th {
518
- background: ${colors["brown-10"]};
519
- font-weight: 600;
518
+ ${typographyMixin(typographyTypes.GEIST_LABEL_CAPTION_MEDIUM)};
519
+ padding: 8px;
520
+ }
521
+
522
+ & td {
523
+ ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
524
+ padding: 16px 8px;
525
+ min-width: 150px;
526
+ width: 1%;
527
+ }
528
+
529
+ & td strong {
530
+ font-weight: inherit;
531
+ font-size: inherit;
532
+ line-height: inherit;
520
533
  }
521
534
 
522
535
  & blockquote {
523
- margin: 4px 0;
524
- padding-left: 12px;
525
- border-left: 3px solid ${colors["brown-30"]};
526
- color: ${colors["brown-70"]};
536
+ margin-block: 4px;
537
+ margin-inline: 0px;
538
+ padding-left: 16px;
539
+ border-left: 4px solid ${colors["brown-40"]};
540
+ color: ${colors["brown-80"]};
527
541
  }
528
542
  `;
543
+ var TableScroll = import_styled_components.default.div`
544
+ width: 100%;
545
+ overflow-x: auto;
546
+ overflow-y: hidden;
547
+ margin-block: 8px 16px;
548
+ `;
529
549
 
530
550
  // src/chat/chat-message-content/chat-message-content.tsx
531
- var import_jsx_runtime2 = require("react/jsx-runtime");
551
+ var import_jsx_runtime = require("react/jsx-runtime");
552
+ function ScrollableTable({ node: _node, ...props }) {
553
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { ...props }) });
554
+ }
555
+ var markdownComponents = {
556
+ table: ScrollableTable
557
+ };
532
558
  function ChatMessageContent({ content }) {
533
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ContentWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default], children: content }) });
559
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ContentWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: markdownComponents, children: content }) });
534
560
  }
535
561
 
536
562
  // src/chat/chat-message-actions/chat-message-actions.tsx
537
- var import_react7 = require("react");
563
+ var import_react5 = require("react");
538
564
 
539
565
  // node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
540
- var import_react3 = require("react");
566
+ var import_react = require("react");
541
567
 
542
568
  // node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs
543
569
  var defaultAttributes = {
@@ -564,8 +590,8 @@ var defaultAttributes = {
564
590
 
565
591
  // node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
566
592
  var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
567
- const Component = (0, import_react3.forwardRef)(
568
- ({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0, import_react3.createElement)(
593
+ const Component = (0, import_react.forwardRef)(
594
+ ({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0, import_react.createElement)(
569
595
  "svg",
570
596
  {
571
597
  ref,
@@ -582,8 +608,8 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
582
608
  ...rest
583
609
  },
584
610
  [
585
- title && (0, import_react3.createElement)("title", { key: "svg-title" }, title),
586
- ...iconNode.map(([tag, attrs]) => (0, import_react3.createElement)(tag, attrs)),
611
+ title && (0, import_react.createElement)("title", { key: "svg-title" }, title),
612
+ ...iconNode.map(([tag, attrs]) => (0, import_react.createElement)(tag, attrs)),
587
613
  ...Array.isArray(children) ? children : [children]
588
614
  ]
589
615
  )
@@ -592,41 +618,30 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
592
618
  return Component;
593
619
  };
594
620
 
595
- // node_modules/@tabler/icons-react/dist/esm/icons/IconArrowUp.mjs
596
- var __iconNode = [["path", { "d": "M12 5l0 14", "key": "svg-0" }], ["path", { "d": "M18 11l-6 -6", "key": "svg-1" }], ["path", { "d": "M6 11l6 -6", "key": "svg-2" }]];
597
- var IconArrowUp = createReactComponent("outline", "arrow-up", "ArrowUp", __iconNode);
598
-
599
621
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCheck.mjs
600
- var __iconNode2 = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
601
- var IconCheck = createReactComponent("outline", "check", "Check", __iconNode2);
622
+ var __iconNode = [["path", { "d": "M5 12l5 5l10 -10", "key": "svg-0" }]];
623
+ var IconCheck = createReactComponent("outline", "check", "Check", __iconNode);
602
624
 
603
625
  // node_modules/@tabler/icons-react/dist/esm/icons/IconCopy.mjs
604
- var __iconNode3 = [["path", { "d": "M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666", "key": "svg-0" }], ["path", { "d": "M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1", "key": "svg-1" }]];
605
- var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode3);
626
+ var __iconNode2 = [["path", { "d": "M7 9.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667l0 -8.666", "key": "svg-0" }], ["path", { "d": "M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1", "key": "svg-1" }]];
627
+ var IconCopy = createReactComponent("outline", "copy", "Copy", __iconNode2);
606
628
 
607
629
  // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbDown.mjs
608
- var __iconNode4 = [["path", { "d": "M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3", "key": "svg-0" }]];
609
- var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode4);
630
+ var __iconNode3 = [["path", { "d": "M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3", "key": "svg-0" }]];
631
+ var IconThumbDown = createReactComponent("outline", "thumb-down", "ThumbDown", __iconNode3);
610
632
 
611
633
  // node_modules/@tabler/icons-react/dist/esm/icons/IconThumbUp.mjs
612
- var __iconNode5 = [["path", { "d": "M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3", "key": "svg-0" }]];
613
- var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode5);
614
-
615
- // node_modules/@tabler/icons-react/dist/esm/icons/IconPlayerStopFilled.mjs
616
- var __iconNode6 = [["path", { "d": "M17 4h-10a3 3 0 0 0 -3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3 -3v-10a3 3 0 0 0 -3 -3z", "key": "svg-0" }]];
617
- var IconPlayerStopFilled = createReactComponent("filled", "player-stop-filled", "PlayerStopFilled", __iconNode6);
618
-
619
- // src/icon-button/icon-button.tsx
620
- var import_react5 = require("react");
634
+ var __iconNode4 = [["path", { "d": "M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7a1 1 0 0 1 1 -1h3a4 4 0 0 0 4 -4v-1a2 2 0 0 1 4 0v5h3a2 2 0 0 1 2 2l-1 5a2 3 0 0 1 -2 2h-7a3 3 0 0 1 -3 -3", "key": "svg-0" }]];
635
+ var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode4);
621
636
 
622
- // src/icon/icon.tsx
623
- var import_react4 = require("react");
637
+ // src/components/icon/icon.tsx
638
+ var import_react2 = require("react");
624
639
 
625
- // src/icon/icon-styles.ts
626
- var import_styled_components3 = __toESM(require("styled-components"), 1);
640
+ // src/components/icon/icon-styles.ts
641
+ var import_styled_components2 = __toESM(require("styled-components"), 1);
627
642
  var STROKE_WIDTH_BY_SIZE = {
628
- 12: 1.2,
629
- 14: 1.2,
643
+ 12: 1.4,
644
+ 14: 1.4,
630
645
  16: 1.8,
631
646
  18: 1.8,
632
647
  20: 1.8,
@@ -636,7 +651,7 @@ var DEFAULT_STROKE_WIDTH = 1.8;
636
651
  function getStrokeWidth(size) {
637
652
  return STROKE_WIDTH_BY_SIZE[size] ?? DEFAULT_STROKE_WIDTH;
638
653
  }
639
- var IconWrapper = import_styled_components3.default.span`
654
+ var IconWrapper = import_styled_components2.default.span`
640
655
  display: inline-flex;
641
656
  align-items: center;
642
657
  justify-content: center;
@@ -644,11 +659,11 @@ var IconWrapper = import_styled_components3.default.span`
644
659
  flex-shrink: 0;
645
660
  `;
646
661
 
647
- // src/icon/icon.tsx
648
- var import_jsx_runtime3 = require("react/jsx-runtime");
662
+ // src/components/icon/icon.tsx
663
+ var import_jsx_runtime2 = require("react/jsx-runtime");
649
664
  var DEFAULT_SIZE = 16;
650
- var Icon = (0, import_react4.forwardRef)(function Icon2({ icon: IconComponent, size = DEFAULT_SIZE, color, className, "aria-label": ariaLabel }, ref) {
651
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
665
+ var Icon = (0, import_react2.forwardRef)(function Icon2({ icon: IconComponent, size = DEFAULT_SIZE, color, className, "aria-label": ariaLabel }, ref) {
666
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
652
667
  IconWrapper,
653
668
  {
654
669
  ref,
@@ -656,28 +671,32 @@ var Icon = (0, import_react4.forwardRef)(function Icon2({ icon: IconComponent, s
656
671
  $color: color,
657
672
  "aria-label": ariaLabel,
658
673
  role: ariaLabel ? "img" : void 0,
659
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconComponent, { width: size, height: size, strokeWidth: getStrokeWidth(size) })
674
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconComponent, { width: size, height: size, strokeWidth: getStrokeWidth(size) })
660
675
  }
661
676
  );
662
677
  });
663
678
 
664
- // src/icon-button/icon-button-styles.ts
665
- var import_styled_components4 = __toESM(require("styled-components"), 1);
666
- var DIMENSIONS = {
667
- small: 28,
668
- medium: 32
679
+ // src/components/icon-button/icon-button-styles.ts
680
+ var import_styled_components3 = __toESM(require("styled-components"), 1);
681
+ var PADDING = {
682
+ short: {
683
+ small: "4px",
684
+ medium: "6px"
685
+ },
686
+ long: {
687
+ small: "4px 6px",
688
+ medium: "6px 10px"
689
+ }
669
690
  };
670
691
  var BORDER_RADIUS = {
671
692
  small: 6,
672
693
  medium: 10
673
694
  };
674
- var Button = import_styled_components4.default.button`
695
+ var Button = import_styled_components3.default.button`
675
696
  display: inline-flex;
676
697
  align-items: center;
677
698
  justify-content: center;
678
- width: ${({ $size }) => DIMENSIONS[$size]}px;
679
- height: ${({ $size }) => DIMENSIONS[$size]}px;
680
- padding: 0;
699
+ padding: ${({ $size, $variant }) => PADDING[$variant][$size]};
681
700
  border: none;
682
701
  border-radius: ${({ $size }) => BORDER_RADIUS[$size]}px;
683
702
  background: ${({ $isSelected }) => $isSelected ? colors["brown-40"] : "transparent"};
@@ -700,30 +719,54 @@ var Button = import_styled_components4.default.button`
700
719
  }
701
720
  `;
702
721
 
703
- // src/icon-button/icon-button.tsx
704
- var import_jsx_runtime4 = require("react/jsx-runtime");
722
+ // src/components/icon-button/icon-button.tsx
723
+ var import_jsx_runtime3 = require("react/jsx-runtime");
705
724
  var ICON_SIZE_BY_BUTTON_SIZE = {
706
- small: 14,
707
- medium: 16
725
+ small: 16,
726
+ medium: 20
708
727
  };
709
- var IconButton = (0, import_react5.forwardRef)(function IconButton2({ icon, size = "small", isSelected = false, disabled = false, onClick, className, "aria-label": ariaLabel }, ref) {
710
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
728
+ function IconButton({
729
+ icon,
730
+ size = "small",
731
+ variant = "short",
732
+ isSelected = false,
733
+ disabled = false,
734
+ onClick,
735
+ className,
736
+ id,
737
+ as,
738
+ "aria-label": ariaLabel
739
+ }) {
740
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
711
741
  Button,
712
742
  {
713
- ref,
714
743
  className,
744
+ id,
745
+ as,
715
746
  $size: size,
747
+ $variant: variant,
716
748
  $isSelected: isSelected,
717
749
  disabled,
718
750
  onClick: disabled ? void 0 : onClick,
719
751
  "aria-label": ariaLabel,
720
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { icon, size: ICON_SIZE_BY_BUTTON_SIZE[size] })
752
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { icon, size: ICON_SIZE_BY_BUTTON_SIZE[size] })
721
753
  }
722
754
  );
723
- });
755
+ }
756
+
757
+ // src/chat/chat-context/chat-context.ts
758
+ var import_react3 = require("react");
759
+ var ChatContext = (0, import_react3.createContext)(null);
760
+ function useChatContext() {
761
+ const context = (0, import_react3.useContext)(ChatContext);
762
+ if (!context) {
763
+ throw new Error("useChatContext must be used within a Chat.Root component");
764
+ }
765
+ return context;
766
+ }
724
767
 
725
768
  // src/chat/hooks/use-copy-to-clipboard.ts
726
- var import_react6 = require("react");
769
+ var import_react4 = require("react");
727
770
 
728
771
  // src/utils/clipboard.ts
729
772
  function copyToClipboard(text, options) {
@@ -733,18 +776,33 @@ function copyToClipboard(text, options) {
733
776
  );
734
777
  }
735
778
 
779
+ // src/utils/markdown-to-plain-text.ts
780
+ var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
781
+ var PLACEHOLDER_SUFFIX = "\u200B\u200B";
782
+ var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
783
+ function markdownToPlainText(markdown) {
784
+ if (!markdown) return "";
785
+ const inlineCodeSnippets = [];
786
+ let result = markdown.replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
787
+ inlineCodeSnippets.push(code);
788
+ return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
789
+ }).replace(/^#{1,6}\s+/gm, "").replace(/^(?:---|\*\*\*|___)\s*$/gm, "").replace(/\*{3}(.+?)\*{3}/g, "$1").replace(/\*{2}(.+?)\*{2}/g, "$1").replace(/_{2}(.+?)_{2}/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/_(.+?)_/g, "$1").replace(/~~(.+?)~~/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/^>\s?/gm, "").replace(/^\|[-:\s|]+\|\s*$/gm, "").replace(/^\|\s?/gm, "").replace(/\s?\|$/gm, "").replace(/\n{3,}/g, "\n\n").trim();
790
+ result = result.replace(PLACEHOLDER_REGEX, (_match, index) => inlineCodeSnippets[Number(index)]);
791
+ return result;
792
+ }
793
+
736
794
  // src/chat/hooks/use-copy-to-clipboard.ts
737
795
  var RESET_DELAY_MS = 2e3;
738
796
  function useCopyToClipboard() {
739
- const [isCopied, setIsCopied] = (0, import_react6.useState)(false);
740
- const timeoutRef = (0, import_react6.useRef)(null);
741
- (0, import_react6.useEffect)(() => {
797
+ const [isCopied, setIsCopied] = (0, import_react4.useState)(false);
798
+ const timeoutRef = (0, import_react4.useRef)(null);
799
+ (0, import_react4.useEffect)(() => {
742
800
  return () => {
743
801
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
744
802
  };
745
803
  }, []);
746
- const copy = (0, import_react6.useCallback)((text) => {
747
- copyToClipboard(text, {
804
+ const copy = (0, import_react4.useCallback)((text) => {
805
+ copyToClipboard(markdownToPlainText(text), {
748
806
  onSuccess: () => {
749
807
  setIsCopied(true);
750
808
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
@@ -758,36 +816,49 @@ function useCopyToClipboard() {
758
816
  return { isCopied, copy };
759
817
  }
760
818
 
819
+ // src/chat/constants.ts
820
+ var MESSAGE_ROLE = {
821
+ USER: "user",
822
+ ASSISTANT: "assistant"
823
+ };
824
+
761
825
  // src/chat/chat-message-actions/chat-message-actions-styles.ts
762
- var import_styled_components5 = __toESM(require("styled-components"), 1);
763
- var ActionsContainer = import_styled_components5.default.div`
826
+ var import_styled_components4 = __toESM(require("styled-components"), 1);
827
+ var FADE_DURATION_MS = 150;
828
+ var ANIMATE_DURATION_MS = 200;
829
+ var ActionsContainer = import_styled_components4.default.div`
764
830
  display: flex;
765
- gap: 2px;
766
- margin-top: 4px;
767
- opacity: 0;
768
- pointer-events: none;
769
- transition: opacity 150ms ease;
831
+ opacity: ${({ $role }) => $role === MESSAGE_ROLE.ASSISTANT ? 1 : 0};
832
+ pointer-events: ${({ $role }) => $role === MESSAGE_ROLE.ASSISTANT ? "auto" : "none"};
833
+ transition: opacity ${FADE_DURATION_MS}ms ease;
834
+ `;
835
+ var AnimatedAction = import_styled_components4.default.div`
836
+ display: flex;
837
+ overflow: hidden;
838
+ max-width: ${({ $visible }) => $visible ? "40px" : "0"};
839
+ opacity: ${({ $visible }) => $visible ? 1 : 0};
840
+ transition: max-width ${ANIMATE_DURATION_MS}ms ease, opacity ${ANIMATE_DURATION_MS}ms ease;
770
841
  `;
771
842
 
772
843
  // src/chat/chat-message-actions/chat-message-actions.tsx
773
- var import_jsx_runtime5 = require("react/jsx-runtime");
774
- function ChatMessageActions({ messageId, content, role, isHelpful }) {
844
+ var import_jsx_runtime4 = require("react/jsx-runtime");
845
+ function ChatMessageActions({ className, messageId, content, role, isHelpful }) {
775
846
  const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
776
847
  const { isCopied, copy } = useCopyToClipboard();
777
- const handleCopy = (0, import_react7.useCallback)(() => {
848
+ const handleCopy = (0, import_react5.useCallback)(() => {
778
849
  copy(content);
779
850
  onCopyMessage?.(messageId);
780
851
  }, [content, messageId, copy, onCopyMessage]);
781
- const handleThumbUp = (0, import_react7.useCallback)(() => {
852
+ const handleThumbUp = (0, import_react5.useCallback)(() => {
782
853
  onThumbUpClick?.(messageId, isHelpful === true ? null : true);
783
854
  }, [messageId, isHelpful, onThumbUpClick]);
784
- const handleThumbDown = (0, import_react7.useCallback)(() => {
855
+ const handleThumbDown = (0, import_react5.useCallback)(() => {
785
856
  onThumbDownClick?.(messageId, isHelpful === false ? null : false);
786
857
  }, [messageId, isHelpful, onThumbDownClick]);
787
- const isAssistant = role === "assistant";
858
+ const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
788
859
  const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
789
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(ActionsContainer, { children: [
790
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
860
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(ActionsContainer, { $role: role, className, children: [
861
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
791
862
  IconButton,
792
863
  {
793
864
  icon: isCopied ? IconCheck : IconCopy,
@@ -795,7 +866,7 @@ function ChatMessageActions({ messageId, content, role, isHelpful }) {
795
866
  "aria-label": isCopied ? "Copied" : "Copy message"
796
867
  }
797
868
  ),
798
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
869
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
799
870
  IconButton,
800
871
  {
801
872
  icon: IconThumbUp,
@@ -803,8 +874,8 @@ function ChatMessageActions({ messageId, content, role, isHelpful }) {
803
874
  isSelected: isHelpful === true,
804
875
  "aria-label": "Good response"
805
876
  }
806
- ),
807
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
877
+ ) }),
878
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
808
879
  IconButton,
809
880
  {
810
881
  icon: IconThumbDown,
@@ -812,41 +883,45 @@ function ChatMessageActions({ messageId, content, role, isHelpful }) {
812
883
  isSelected: isHelpful === false,
813
884
  "aria-label": "Bad response"
814
885
  }
815
- )
886
+ ) })
816
887
  ] });
817
888
  }
818
889
 
819
890
  // src/chat/chat-message/chat-message-styles.ts
820
- var import_styled_components6 = __toESM(require("styled-components"), 1);
821
- var MessageRow = import_styled_components6.default.div`
822
- display: flex;
823
- justify-content: ${({ $role }) => $role === "user" ? "flex-end" : "flex-start"};
824
- `;
825
- var MessageContainer = import_styled_components6.default.div`
891
+ var import_styled_components5 = __toESM(require("styled-components"), 1);
892
+ var MessageRow = import_styled_components5.default.div`
826
893
  display: flex;
827
- flex-direction: column;
828
- align-items: ${({ $role }) => $role === "user" ? "flex-end" : "flex-start"};
829
- max-width: 90%;
894
+ justify-content: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "flex-end" : "flex-start"};
830
895
 
831
896
  &:hover ${ActionsContainer} {
832
897
  opacity: 1;
833
898
  pointer-events: auto;
834
899
  }
835
900
  `;
836
- var MessageBubble = import_styled_components6.default.div`
837
- ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
901
+ var MessageContainer = import_styled_components5.default.div`
902
+ display: flex;
903
+ flex-direction: column;
904
+ align-items: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "flex-end" : "flex-start"};
905
+ max-width: 90%;
906
+ width: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "auto" : "100%"};
907
+ gap: 12px;
908
+ `;
909
+ var MessageBubble = import_styled_components5.default.div`
910
+ ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
838
911
  color: ${colors["brown-100"]};
839
- background: ${({ $role }) => $role === "user" ? colors.white : "transparent"};
840
- padding: ${({ $role }) => $role === "user" ? "12px 16px" : "0"};
841
- border-radius: ${({ $role }) => $role === "user" ? "16px" : "0"};
912
+ background: ${({ $role }) => $role === MESSAGE_ROLE.USER ? colors.white : "transparent"};
913
+ padding: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "12px 16px" : "0"};
914
+ border-radius: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "16px" : "0"};
915
+ max-width: 100%;
916
+ min-width: 0;
842
917
  `;
843
918
 
844
919
  // src/chat/chat-message/chat-message.tsx
845
- var import_jsx_runtime6 = require("react/jsx-runtime");
920
+ var import_jsx_runtime5 = require("react/jsx-runtime");
846
921
  function ChatMessage({ message }) {
847
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageRow, { $role: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(MessageContainer, { $role: message.role, children: [
848
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageBubble, { $role: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatMessageContent, { content: message.content }) }),
849
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
922
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageRow, { $role: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(MessageContainer, { $role: message.role, children: [
923
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageBubble, { $role: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChatMessageContent, { content: message.content }) }),
924
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
850
925
  ChatMessageActions,
851
926
  {
852
927
  messageId: message.id,
@@ -857,255 +932,22 @@ function ChatMessage({ message }) {
857
932
  )
858
933
  ] }) });
859
934
  }
860
-
861
- // src/chat/hooks/use-auto-scroll.ts
862
- var import_react8 = require("react");
863
- function useAutoScroll(messageCount) {
864
- const scrollContainerRef = (0, import_react8.useRef)(null);
865
- const sentinelRef = (0, import_react8.useRef)(null);
866
- const [isAtBottom, setIsAtBottom] = (0, import_react8.useState)(true);
867
- const prevMessageCountRef = (0, import_react8.useRef)(messageCount);
868
- const hasInitializedRef = (0, import_react8.useRef)(false);
869
- (0, import_react8.useLayoutEffect)(() => {
870
- const el = scrollContainerRef.current;
871
- if (el) {
872
- el.scrollTop = el.scrollHeight;
873
- }
874
- }, []);
875
- (0, import_react8.useEffect)(() => {
876
- if (!hasInitializedRef.current) {
877
- hasInitializedRef.current = true;
878
- requestAnimationFrame(() => {
879
- const el = scrollContainerRef.current;
880
- if (el) {
881
- el.scrollTop = el.scrollHeight;
882
- }
883
- });
884
- }
885
- }, []);
886
- (0, import_react8.useEffect)(() => {
887
- const sentinel = sentinelRef.current;
888
- const scrollContainer = scrollContainerRef.current;
889
- if (!sentinel || !scrollContainer) return;
890
- const observer = new IntersectionObserver(
891
- ([entry]) => {
892
- setIsAtBottom(entry.isIntersecting);
893
- },
894
- { root: scrollContainer, threshold: 0 }
895
- );
896
- observer.observe(sentinel);
897
- return () => observer.disconnect();
898
- }, []);
899
- (0, import_react8.useEffect)(() => {
900
- if (!hasInitializedRef.current) return;
901
- if (messageCount > prevMessageCountRef.current) {
902
- requestAnimationFrame(() => {
903
- const el = scrollContainerRef.current;
904
- if (el) {
905
- el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
906
- }
907
- });
908
- }
909
- prevMessageCountRef.current = messageCount;
910
- }, [messageCount]);
911
- const scrollToBottom = (0, import_react8.useCallback)(() => {
912
- const el = scrollContainerRef.current;
913
- if (el) {
914
- el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
915
- }
916
- }, []);
917
- return { scrollContainerRef, sentinelRef, isAtBottom, scrollToBottom };
918
- }
919
-
920
- // src/chat/chat-message-list/chat-message-list-styles.ts
921
- var import_styled_components7 = __toESM(require("styled-components"), 1);
922
- var ListContainer = import_styled_components7.default.div`
923
- display: flex;
924
- flex-direction: column;
925
- flex: 1;
926
- overflow-y: auto;
927
-
928
- &::-webkit-scrollbar {
929
- width: 6px;
930
- }
931
-
932
- &::-webkit-scrollbar-track {
933
- background: transparent;
934
- }
935
-
936
- &::-webkit-scrollbar-thumb {
937
- background: ${colors["brown-30"]};
938
- border-radius: 3px;
939
- }
940
- `;
941
- var MessagesList = import_styled_components7.default.div`
942
- display: flex;
943
- flex-direction: column;
944
- gap: 40px;
945
- padding: 0 16px 32px 16px;
946
- `;
947
- var ScrollSentinel = import_styled_components7.default.div`
948
- flex-shrink: 0;
949
- height: 16px;
950
- `;
951
-
952
- // src/chat/chat-message-list/chat-message-list.tsx
953
- var import_jsx_runtime7 = require("react/jsx-runtime");
954
- function ChatMessageList() {
955
- const { messages } = useChatContext();
956
- const { scrollContainerRef, sentinelRef } = useAutoScroll(messages.length);
957
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(ListContainer, { ref: scrollContainerRef, "data-testid": "chat-list-container", children: [
958
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MessagesList, { children: messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChatMessage, { message }, message.id)) }),
959
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ScrollSentinel, { ref: sentinelRef, "data-testid": "chat-scroll-sentinel" })
960
- ] });
961
- }
962
-
963
- // src/chat/chat-composer/chat-composer.tsx
964
- var import_react9 = require("react");
965
-
966
- // src/chat/chat-composer/chat-composer-styles.ts
967
- var import_styled_components8 = __toESM(require("styled-components"), 1);
968
- var ComposerContainer = import_styled_components8.default.div`
969
- position: relative;
970
- background: ${colors.white};
971
- border-radius: 12px;
972
- box-shadow: 0 0 4px 0 ${colors["brown-alpha-12"]};
973
- padding: 8px 0;
974
- `;
975
- var TextArea = import_styled_components8.default.textarea`
976
- display: block;
977
- width: 100%;
978
- resize: none;
979
- border: none;
980
- background: transparent;
981
- ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
982
- color: ${colors["brown-90"]};
983
- padding: 4px 46px 4px 16px;
984
- min-height: 20px;
985
- max-height: 200px;
986
- overflow-y: auto;
987
- box-sizing: border-box;
988
-
989
- &::placeholder {
990
- color: ${colors["brown-60"]};
991
- }
992
-
993
- &:focus {
994
- outline: none;
995
- }
996
- `;
997
- var SendButton = import_styled_components8.default.button`
998
- position: absolute;
999
- bottom: 8px;
1000
- right: 8px;
1001
- width: 30px;
1002
- height: 30px;
1003
- border: none;
1004
- border-radius: 12px;
1005
- cursor: pointer;
1006
- display: flex;
1007
- align-items: center;
1008
- justify-content: center;
1009
- background: ${colors["brown-100"]};
1010
- color: ${colors.white};
1011
- transition: background-color 75ms;
1012
- padding: 0;
1013
-
1014
- &:disabled {
1015
- background: ${colors["brown-50"]};
1016
- cursor: default;
1017
- }
1018
- `;
1019
-
1020
- // src/chat/chat-composer/chat-composer.tsx
1021
- var import_jsx_runtime8 = require("react/jsx-runtime");
1022
- function ChatComposer({ placeholder = "Type a message..." }) {
1023
- const { onSendMessage, isLoading, onStop } = useChatContext();
1024
- const [value, setValue] = (0, import_react9.useState)("");
1025
- const textAreaRef = (0, import_react9.useRef)(null);
1026
- const isEmpty = value.trim().length === 0;
1027
- const resizeTextArea = (0, import_react9.useCallback)(() => {
1028
- const el = textAreaRef.current;
1029
- if (!el) return;
1030
- el.style.height = "auto";
1031
- el.style.height = `${el.scrollHeight}px`;
1032
- }, []);
1033
- (0, import_react9.useEffect)(() => {
1034
- resizeTextArea();
1035
- }, [value, resizeTextArea]);
1036
- (0, import_react9.useEffect)(() => {
1037
- textAreaRef.current?.focus();
1038
- }, []);
1039
- const handleSend = (0, import_react9.useCallback)(() => {
1040
- const trimmed = value.trim();
1041
- if (!trimmed) return;
1042
- onSendMessage(trimmed);
1043
- setValue("");
1044
- requestAnimationFrame(() => textAreaRef.current?.focus());
1045
- }, [value, onSendMessage]);
1046
- const handleKeyDown = (0, import_react9.useCallback)(
1047
- (e) => {
1048
- if (e.key === "Enter" && !e.shiftKey) {
1049
- e.preventDefault();
1050
- handleSend();
1051
- }
1052
- },
1053
- [handleSend]
1054
- );
1055
- const handleChange = (0, import_react9.useCallback)((e) => {
1056
- setValue(e.target.value);
1057
- }, []);
1058
- const handleButtonClick = (0, import_react9.useCallback)(() => {
1059
- if (isLoading && onStop) {
1060
- onStop();
1061
- } else {
1062
- handleSend();
1063
- }
1064
- }, [isLoading, onStop, handleSend]);
1065
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(ComposerContainer, { children: [
1066
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1067
- TextArea,
1068
- {
1069
- ref: textAreaRef,
1070
- value,
1071
- onChange: handleChange,
1072
- onKeyDown: handleKeyDown,
1073
- placeholder,
1074
- rows: 1
1075
- }
1076
- ),
1077
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1078
- SendButton,
1079
- {
1080
- onClick: handleButtonClick,
1081
- disabled: !isLoading && isEmpty,
1082
- "aria-label": isLoading ? "Stop generating" : "Send message",
1083
- children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Icon, { icon: IconPlayerStopFilled, size: 16 }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Icon, { icon: IconArrowUp, size: 16 })
1084
- }
1085
- )
1086
- ] });
1087
- }
1088
-
1089
- // src/chat/chat-namespace.ts
1090
- var Chat = {
1091
- Root: ChatRoot,
1092
- MessageList: ChatMessageList,
1093
- Composer: ChatComposer
1094
- };
1095
935
  // Annotate the CommonJS export names for ESM import in node:
1096
936
  0 && (module.exports = {
1097
- Chat
937
+ ChatContext,
938
+ ChatMessage,
939
+ MESSAGE_ROLE,
940
+ useChatContext,
941
+ useCopyToClipboard
1098
942
  });
1099
943
  /*! Bundled license information:
1100
944
 
1101
945
  @tabler/icons-react/dist/esm/defaultAttributes.mjs:
1102
946
  @tabler/icons-react/dist/esm/createReactComponent.mjs:
1103
- @tabler/icons-react/dist/esm/icons/IconArrowUp.mjs:
1104
947
  @tabler/icons-react/dist/esm/icons/IconCheck.mjs:
1105
948
  @tabler/icons-react/dist/esm/icons/IconCopy.mjs:
1106
949
  @tabler/icons-react/dist/esm/icons/IconThumbDown.mjs:
1107
950
  @tabler/icons-react/dist/esm/icons/IconThumbUp.mjs:
1108
- @tabler/icons-react/dist/esm/icons/IconPlayerStopFilled.mjs:
1109
951
  @tabler/icons-react/dist/esm/tabler-icons-react.mjs:
1110
952
  (**
1111
953
  * @license @tabler/icons-react v3.37.1 - MIT