@shapesos/clay 0.7.0 → 0.8.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.cjs CHANGED
@@ -16357,9 +16357,11 @@ __export(src_exports, {
16357
16357
  MESSAGE_ROLE: () => MESSAGE_ROLE,
16358
16358
  TextArea: () => TextArea,
16359
16359
  colors: () => colors,
16360
+ convertTableToCSV: () => convertTableToCSV,
16360
16361
  fontFamilies: () => fontFamilies,
16361
16362
  markdownToPlainText: () => markdownToPlainText,
16362
16363
  mergeRefs: () => mergeRefs,
16364
+ parseMarkdownTable: () => parseMarkdownTable,
16363
16365
  typographyMixin: () => typographyMixin,
16364
16366
  typographyStyles: () => typographyStyles,
16365
16367
  typographyTypes: () => typographyTypes,
@@ -16752,13 +16754,68 @@ function typographyMixin(type) {
16752
16754
  }
16753
16755
 
16754
16756
  // src/components/chat/chat-message-content/chat-message-content.tsx
16757
+ var import_react3 = require("react");
16755
16758
  var import_react_markdown = __toESM(require("react-markdown"), 1);
16756
16759
  var import_remark_breaks = __toESM(require("remark-breaks"), 1);
16757
16760
  var import_remark_gfm = __toESM(require("remark-gfm"), 1);
16758
16761
 
16759
- // src/components/chat/chat-message-content/chat-message-content-styles.ts
16762
+ // src/components/chat/scrollable-table/scrollable-table.tsx
16763
+ var import_react2 = require("react");
16764
+
16765
+ // src/components/chat/chat-context/chat-context.ts
16766
+ var import_react = require("react");
16767
+ var ChatContext = (0, import_react.createContext)(null);
16768
+ function useChatContext() {
16769
+ const context = (0, import_react.useContext)(ChatContext);
16770
+ if (!context) {
16771
+ throw new Error("useChatContext must be used within a Chat.Root component");
16772
+ }
16773
+ return context;
16774
+ }
16775
+
16776
+ // src/components/chat/scrollable-table/scrollable-table-styles.ts
16760
16777
  var import_styled_components = __toESM(require("styled-components"), 1);
16761
- var ContentWrapper = import_styled_components.default.div`
16778
+ var TableContainer = import_styled_components.default.div`
16779
+ position: relative;
16780
+ margin-block: 8px 16px;
16781
+ `;
16782
+ var TableScroll = import_styled_components.default.div`
16783
+ width: 100%;
16784
+ overflow-x: auto;
16785
+ overflow-y: hidden;
16786
+ `;
16787
+ var TableActionsWrapper = import_styled_components.default.div`
16788
+ display: flex;
16789
+ justify-content: flex-start;
16790
+ margin-block: 8px 0;
16791
+ `;
16792
+ var TableActionsDivider = import_styled_components.default.div`
16793
+ height: 1px;
16794
+ background: ${colors["brown-40"]};
16795
+ margin-block: 8px 0;
16796
+ `;
16797
+
16798
+ // src/components/chat/scrollable-table/scrollable-table.tsx
16799
+ var import_jsx_runtime = require("react/jsx-runtime");
16800
+ function ScrollableTable({ node: _node, messageId, counter, ...props }) {
16801
+ const currentIndex = counter ? counter.value : 0;
16802
+ if (counter) {
16803
+ counter.value += 1;
16804
+ }
16805
+ const context = (0, import_react2.useContext)(ChatContext);
16806
+ const TableActions = context?.TableActions;
16807
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableContainer, { children: [
16808
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { ...props }) }),
16809
+ TableActions && messageId && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
16810
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActionsWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActions, { messageId, tableIndex: currentIndex }) }),
16811
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableActionsDivider, {})
16812
+ ] })
16813
+ ] });
16814
+ }
16815
+
16816
+ // src/components/chat/chat-message-content/chat-message-content-styles.ts
16817
+ var import_styled_components2 = __toESM(require("styled-components"), 1);
16818
+ var ContentWrapper = import_styled_components2.default.div`
16762
16819
  ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
16763
16820
  color: ${colors["brown-100"]};
16764
16821
  word-break: break-word;
@@ -16874,30 +16931,30 @@ var ContentWrapper = import_styled_components.default.div`
16874
16931
  color: ${colors["brown-80"]};
16875
16932
  }
16876
16933
  `;
16877
- var TableScroll = import_styled_components.default.div`
16878
- width: 100%;
16879
- overflow-x: auto;
16880
- overflow-y: hidden;
16881
- margin-block: 8px 16px;
16882
- `;
16883
16934
 
16884
16935
  // src/components/chat/chat-message-content/chat-message-content.tsx
16885
- var import_jsx_runtime = require("react/jsx-runtime");
16886
- function ScrollableTable({ node: _node, ...props }) {
16887
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableScroll, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { ...props }) });
16888
- }
16889
- var markdownComponents = {
16890
- table: ScrollableTable
16891
- };
16892
- function ChatMessageContent({ content: content2 }) {
16893
- 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: content2 }) });
16936
+ var import_jsx_runtime2 = require("react/jsx-runtime");
16937
+ function ChatMessageContent({ content: content2, messageId }) {
16938
+ const counter = { value: 0 };
16939
+ const sanitizedContent = content2.split("\n").filter((line) => {
16940
+ const t = line.trim();
16941
+ return !(t.startsWith("<!-- table-title:") && t.endsWith("-->"));
16942
+ }).join("\n");
16943
+ const markdownComponents = (0, import_react3.useMemo)(
16944
+ () => ({
16945
+ table: ((tableProps) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ScrollableTable, { ...tableProps, messageId, counter }))
16946
+ }),
16947
+ // eslint-disable-next-line react-hooks/exhaustive-deps -- counter is intentionally a fresh object each render for sequential table indexing
16948
+ [messageId]
16949
+ );
16950
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ContentWrapper, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default, import_remark_breaks.default], components: markdownComponents, children: sanitizedContent }) });
16894
16951
  }
16895
16952
 
16896
16953
  // src/components/chat/chat-message-actions/chat-message-actions.tsx
16897
- var import_react5 = require("react");
16954
+ var import_react7 = require("react");
16898
16955
 
16899
16956
  // node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
16900
- var import_react = require("react");
16957
+ var import_react4 = require("react");
16901
16958
 
16902
16959
  // node_modules/@tabler/icons-react/dist/esm/defaultAttributes.mjs
16903
16960
  var defaultAttributes = {
@@ -16924,8 +16981,8 @@ var defaultAttributes = {
16924
16981
 
16925
16982
  // node_modules/@tabler/icons-react/dist/esm/createReactComponent.mjs
16926
16983
  var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
16927
- const Component = (0, import_react.forwardRef)(
16928
- ({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0, import_react.createElement)(
16984
+ const Component = (0, import_react4.forwardRef)(
16985
+ ({ color = "currentColor", size = 24, stroke = 2, title, className, children, ...rest }, ref) => (0, import_react4.createElement)(
16929
16986
  "svg",
16930
16987
  {
16931
16988
  ref,
@@ -16942,8 +16999,8 @@ var createReactComponent = (type, iconName, iconNamePascal, iconNode) => {
16942
16999
  ...rest
16943
17000
  },
16944
17001
  [
16945
- title && (0, import_react.createElement)("title", { key: "svg-title" }, title),
16946
- ...iconNode.map(([tag, attrs]) => (0, import_react.createElement)(tag, attrs)),
17002
+ title && (0, import_react4.createElement)("title", { key: "svg-title" }, title),
17003
+ ...iconNode.map(([tag, attrs]) => (0, import_react4.createElement)(tag, attrs)),
16947
17004
  ...Array.isArray(children) ? children : [children]
16948
17005
  ]
16949
17006
  )
@@ -16969,10 +17026,10 @@ var __iconNode4 = [["path", { "d": "M7 11v8a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-7
16969
17026
  var IconThumbUp = createReactComponent("outline", "thumb-up", "ThumbUp", __iconNode4);
16970
17027
 
16971
17028
  // src/components/icon/icon.tsx
16972
- var import_react2 = require("react");
17029
+ var import_react5 = require("react");
16973
17030
 
16974
17031
  // src/components/icon/icon-styles.ts
16975
- var import_styled_components2 = __toESM(require("styled-components"), 1);
17032
+ var import_styled_components3 = __toESM(require("styled-components"), 1);
16976
17033
  var STROKE_WIDTH_BY_SIZE = {
16977
17034
  12: 1.4,
16978
17035
  14: 1.4,
@@ -16985,7 +17042,7 @@ var DEFAULT_STROKE_WIDTH = 1.8;
16985
17042
  function getStrokeWidth(size) {
16986
17043
  return STROKE_WIDTH_BY_SIZE[size] ?? DEFAULT_STROKE_WIDTH;
16987
17044
  }
16988
- var IconWrapper = import_styled_components2.default.span`
17045
+ var IconWrapper = import_styled_components3.default.span`
16989
17046
  display: inline-flex;
16990
17047
  align-items: center;
16991
17048
  justify-content: center;
@@ -16994,10 +17051,10 @@ var IconWrapper = import_styled_components2.default.span`
16994
17051
  `;
16995
17052
 
16996
17053
  // src/components/icon/icon.tsx
16997
- var import_jsx_runtime2 = require("react/jsx-runtime");
17054
+ var import_jsx_runtime3 = require("react/jsx-runtime");
16998
17055
  var DEFAULT_SIZE = 16;
16999
- var Icon = (0, import_react2.forwardRef)(function Icon2({ icon: IconComponent, size = DEFAULT_SIZE, color, className, "aria-label": ariaLabel }, ref) {
17000
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
17056
+ var Icon = (0, import_react5.forwardRef)(function Icon2({ icon: IconComponent, size = DEFAULT_SIZE, color, className, "aria-label": ariaLabel }, ref) {
17057
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
17001
17058
  IconWrapper,
17002
17059
  {
17003
17060
  ref,
@@ -17005,13 +17062,13 @@ var Icon = (0, import_react2.forwardRef)(function Icon2({ icon: IconComponent, s
17005
17062
  $color: color,
17006
17063
  "aria-label": ariaLabel,
17007
17064
  role: ariaLabel ? "img" : void 0,
17008
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconComponent, { width: size, height: size, strokeWidth: getStrokeWidth(size) })
17065
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(IconComponent, { width: size, height: size, strokeWidth: getStrokeWidth(size) })
17009
17066
  }
17010
17067
  );
17011
17068
  });
17012
17069
 
17013
17070
  // src/components/icon-button/icon-button-styles.ts
17014
- var import_styled_components3 = __toESM(require("styled-components"), 1);
17071
+ var import_styled_components4 = __toESM(require("styled-components"), 1);
17015
17072
  var PADDING = {
17016
17073
  short: {
17017
17074
  small: "4px",
@@ -17026,7 +17083,7 @@ var BORDER_RADIUS = {
17026
17083
  small: 6,
17027
17084
  medium: 10
17028
17085
  };
17029
- var Button = import_styled_components3.default.button`
17086
+ var Button = import_styled_components4.default.button`
17030
17087
  display: inline-flex;
17031
17088
  align-items: center;
17032
17089
  justify-content: center;
@@ -17054,7 +17111,7 @@ var Button = import_styled_components3.default.button`
17054
17111
  `;
17055
17112
 
17056
17113
  // src/components/icon-button/icon-button.tsx
17057
- var import_jsx_runtime3 = require("react/jsx-runtime");
17114
+ var import_jsx_runtime4 = require("react/jsx-runtime");
17058
17115
  var ICON_SIZE_BY_BUTTON_SIZE = {
17059
17116
  small: 16,
17060
17117
  medium: 20
@@ -17071,7 +17128,7 @@ function IconButton({
17071
17128
  as,
17072
17129
  "aria-label": ariaLabel
17073
17130
  }) {
17074
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
17131
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
17075
17132
  Button,
17076
17133
  {
17077
17134
  className,
@@ -17083,24 +17140,13 @@ function IconButton({
17083
17140
  disabled,
17084
17141
  onClick: disabled ? void 0 : onClick,
17085
17142
  "aria-label": ariaLabel,
17086
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { icon, size: ICON_SIZE_BY_BUTTON_SIZE[size] })
17143
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Icon, { icon, size: ICON_SIZE_BY_BUTTON_SIZE[size] })
17087
17144
  }
17088
17145
  );
17089
17146
  }
17090
17147
 
17091
- // src/components/chat/chat-context/chat-context.ts
17092
- var import_react3 = require("react");
17093
- var ChatContext = (0, import_react3.createContext)(null);
17094
- function useChatContext() {
17095
- const context = (0, import_react3.useContext)(ChatContext);
17096
- if (!context) {
17097
- throw new Error("useChatContext must be used within a Chat.Root component");
17098
- }
17099
- return context;
17100
- }
17101
-
17102
17148
  // src/components/chat/hooks/use-copy-to-clipboard.ts
17103
- var import_react4 = require("react");
17149
+ var import_react6 = require("react");
17104
17150
 
17105
17151
  // src/utils/clipboard.ts
17106
17152
  function copyToClipboard(text2, options) {
@@ -17117,7 +17163,7 @@ var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUF
17117
17163
  function markdownToPlainText(markdown) {
17118
17164
  if (!markdown) return "";
17119
17165
  const inlineCodeSnippets = [];
17120
- let result = markdown.replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
17166
+ let result = markdown.replace(/^<!--[\s\S]*?--!?>\n?/gm, "").replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
17121
17167
  inlineCodeSnippets.push(code);
17122
17168
  return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
17123
17169
  }).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();
@@ -17128,14 +17174,14 @@ function markdownToPlainText(markdown) {
17128
17174
  // src/components/chat/hooks/use-copy-to-clipboard.ts
17129
17175
  var RESET_DELAY_MS = 2e3;
17130
17176
  function useCopyToClipboard() {
17131
- const [isCopied, setIsCopied] = (0, import_react4.useState)(false);
17132
- const timeoutRef = (0, import_react4.useRef)(null);
17133
- (0, import_react4.useEffect)(() => {
17177
+ const [isCopied, setIsCopied] = (0, import_react6.useState)(false);
17178
+ const timeoutRef = (0, import_react6.useRef)(null);
17179
+ (0, import_react6.useEffect)(() => {
17134
17180
  return () => {
17135
17181
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
17136
17182
  };
17137
17183
  }, []);
17138
- const copy = (0, import_react4.useCallback)((text2) => {
17184
+ const copy = (0, import_react6.useCallback)((text2) => {
17139
17185
  copyToClipboard(markdownToPlainText(text2), {
17140
17186
  onSuccess: () => {
17141
17187
  setIsCopied(true);
@@ -17157,16 +17203,16 @@ var MESSAGE_ROLE = {
17157
17203
  };
17158
17204
 
17159
17205
  // src/components/chat/chat-message-actions/chat-message-actions-styles.ts
17160
- var import_styled_components4 = __toESM(require("styled-components"), 1);
17206
+ var import_styled_components5 = __toESM(require("styled-components"), 1);
17161
17207
  var FADE_DURATION_MS = 150;
17162
17208
  var ANIMATE_DURATION_MS = 200;
17163
- var ActionsContainer = import_styled_components4.default.div`
17209
+ var ActionsContainer = import_styled_components5.default.div`
17164
17210
  display: flex;
17165
17211
  opacity: ${({ $role }) => $role === MESSAGE_ROLE.ASSISTANT ? 1 : 0};
17166
17212
  pointer-events: ${({ $role }) => $role === MESSAGE_ROLE.ASSISTANT ? "auto" : "none"};
17167
17213
  transition: opacity ${FADE_DURATION_MS}ms ease;
17168
17214
  `;
17169
- var AnimatedAction = import_styled_components4.default.div`
17215
+ var AnimatedAction = import_styled_components5.default.div`
17170
17216
  display: flex;
17171
17217
  overflow: hidden;
17172
17218
  max-width: ${({ $visible }) => $visible ? "40px" : "0"};
@@ -17175,24 +17221,24 @@ var AnimatedAction = import_styled_components4.default.div`
17175
17221
  `;
17176
17222
 
17177
17223
  // src/components/chat/chat-message-actions/chat-message-actions.tsx
17178
- var import_jsx_runtime4 = require("react/jsx-runtime");
17224
+ var import_jsx_runtime5 = require("react/jsx-runtime");
17179
17225
  function ChatMessageActions({ className, messageId, content: content2, role, isHelpful }) {
17180
17226
  const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
17181
17227
  const { isCopied, copy } = useCopyToClipboard();
17182
- const handleCopy = (0, import_react5.useCallback)(() => {
17228
+ const handleCopy = (0, import_react7.useCallback)(() => {
17183
17229
  copy(content2);
17184
17230
  onCopyMessage?.(messageId);
17185
17231
  }, [content2, messageId, copy, onCopyMessage]);
17186
- const handleThumbUp = (0, import_react5.useCallback)(() => {
17232
+ const handleThumbUp = (0, import_react7.useCallback)(() => {
17187
17233
  onThumbUpClick?.(messageId, isHelpful === true ? null : true);
17188
17234
  }, [messageId, isHelpful, onThumbUpClick]);
17189
- const handleThumbDown = (0, import_react5.useCallback)(() => {
17235
+ const handleThumbDown = (0, import_react7.useCallback)(() => {
17190
17236
  onThumbDownClick?.(messageId, isHelpful === false ? null : false);
17191
17237
  }, [messageId, isHelpful, onThumbDownClick]);
17192
17238
  const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
17193
17239
  const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
17194
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(ActionsContainer, { $role: role, className, children: [
17195
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
17240
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(ActionsContainer, { $role: role, className, children: [
17241
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
17196
17242
  IconButton,
17197
17243
  {
17198
17244
  icon: isCopied ? IconCheck : IconCopy,
@@ -17200,7 +17246,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
17200
17246
  "aria-label": isCopied ? "Copied" : "Copy message"
17201
17247
  }
17202
17248
  ),
17203
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
17249
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
17204
17250
  IconButton,
17205
17251
  {
17206
17252
  icon: IconThumbUp,
@@ -17209,7 +17255,7 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
17209
17255
  "aria-label": "Good response"
17210
17256
  }
17211
17257
  ) }),
17212
- hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
17258
+ hasFeedback && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
17213
17259
  IconButton,
17214
17260
  {
17215
17261
  icon: IconThumbDown,
@@ -17222,8 +17268,8 @@ function ChatMessageActions({ className, messageId, content: content2, role, isH
17222
17268
  }
17223
17269
 
17224
17270
  // src/components/chat/chat-message/chat-message-styles.ts
17225
- var import_styled_components5 = __toESM(require("styled-components"), 1);
17226
- var MessageRow = import_styled_components5.default.div`
17271
+ var import_styled_components6 = __toESM(require("styled-components"), 1);
17272
+ var MessageRow = import_styled_components6.default.div`
17227
17273
  display: flex;
17228
17274
  justify-content: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "flex-end" : "flex-start"};
17229
17275
 
@@ -17232,7 +17278,7 @@ var MessageRow = import_styled_components5.default.div`
17232
17278
  pointer-events: auto;
17233
17279
  }
17234
17280
  `;
17235
- var MessageContainer = import_styled_components5.default.div`
17281
+ var MessageContainer = import_styled_components6.default.div`
17236
17282
  display: flex;
17237
17283
  flex-direction: column;
17238
17284
  align-items: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "flex-end" : "flex-start"};
@@ -17240,7 +17286,7 @@ var MessageContainer = import_styled_components5.default.div`
17240
17286
  width: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "auto" : "100%"};
17241
17287
  gap: 12px;
17242
17288
  `;
17243
- var MessageBubble = import_styled_components5.default.div`
17289
+ var MessageBubble = import_styled_components6.default.div`
17244
17290
  ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
17245
17291
  color: ${colors["brown-100"]};
17246
17292
  background: ${({ $role }) => $role === MESSAGE_ROLE.USER ? colors.white : "transparent"};
@@ -17251,11 +17297,11 @@ var MessageBubble = import_styled_components5.default.div`
17251
17297
  `;
17252
17298
 
17253
17299
  // src/components/chat/chat-message/chat-message.tsx
17254
- var import_jsx_runtime5 = require("react/jsx-runtime");
17300
+ var import_jsx_runtime6 = require("react/jsx-runtime");
17255
17301
  function ChatMessage({ message }) {
17256
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(MessageContainer, { $role: message.role, children: [
17257
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MessageBubble, { $role: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ChatMessageContent, { content: message.content }) }),
17258
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
17302
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageRow, { $role: message.role, role: "article", "aria-label": `${message.role} message`, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(MessageContainer, { $role: message.role, children: [
17303
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MessageBubble, { $role: message.role, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatMessageContent, { content: message.content, messageId: message.id }) }),
17304
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
17259
17305
  ChatMessageActions,
17260
17306
  {
17261
17307
  messageId: message.id,
@@ -17268,7 +17314,7 @@ function ChatMessage({ message }) {
17268
17314
  }
17269
17315
 
17270
17316
  // src/components/keyboard-shortcut/keyboard-shortcut-styles.ts
17271
- var import_styled_components6 = __toESM(require("styled-components"), 1);
17317
+ var import_styled_components7 = __toESM(require("styled-components"), 1);
17272
17318
 
17273
17319
  // src/components/keyboard-shortcut/types.ts
17274
17320
  var KEYBOARD_SHORTCUT_VARIANTS = {
@@ -17280,21 +17326,21 @@ var KEYBOARD_SHORTCUT_VARIANTS = {
17280
17326
 
17281
17327
  // src/components/keyboard-shortcut/keyboard-shortcut-styles.ts
17282
17328
  var variantStyles = {
17283
- [KEYBOARD_SHORTCUT_VARIANTS.OUTLINED]: import_styled_components6.css`
17329
+ [KEYBOARD_SHORTCUT_VARIANTS.OUTLINED]: import_styled_components7.css`
17284
17330
  border: 1px solid ${colors["white-alpha-40"]};
17285
17331
  color: ${colors["brown-10"]};
17286
17332
  `,
17287
- [KEYBOARD_SHORTCUT_VARIANTS.FILLED]: import_styled_components6.css`
17333
+ [KEYBOARD_SHORTCUT_VARIANTS.FILLED]: import_styled_components7.css`
17288
17334
  background: ${colors["brown-80"]};
17289
17335
  color: ${colors["brown-10"]};
17290
17336
  `
17291
17337
  };
17292
- var Wrapper = import_styled_components6.default.div`
17338
+ var Wrapper = import_styled_components7.default.div`
17293
17339
  display: inline-flex;
17294
17340
  align-items: center;
17295
17341
  gap: 2px;
17296
17342
  `;
17297
- var Key = import_styled_components6.default.kbd`
17343
+ var Key = import_styled_components7.default.kbd`
17298
17344
  display: inline-flex;
17299
17345
  align-items: center;
17300
17346
  justify-content: center;
@@ -17304,20 +17350,20 @@ var Key = import_styled_components6.default.kbd`
17304
17350
  `;
17305
17351
 
17306
17352
  // src/components/keyboard-shortcut/keyboard-shortcut.tsx
17307
- var import_jsx_runtime6 = require("react/jsx-runtime");
17353
+ var import_jsx_runtime7 = require("react/jsx-runtime");
17308
17354
  function KeyboardShortcut({
17309
17355
  keys,
17310
17356
  variant = KEYBOARD_SHORTCUT_VARIANTS.OUTLINED,
17311
17357
  className
17312
17358
  }) {
17313
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Wrapper, { className, children: keys.map((KeyComponent, index2) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Key, { $variant: variant, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Icon, { icon: KeyComponent, size: 12 }) }, index2)) });
17359
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Wrapper, { className, children: keys.map((KeyComponent, index2) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Key, { $variant: variant, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { icon: KeyComponent, size: 12 }) }, index2)) });
17314
17360
  }
17315
17361
 
17316
17362
  // src/components/keyboard-shortcut/icons/icon-ctrl.tsx
17317
- var import_jsx_runtime7 = require("react/jsx-runtime");
17363
+ var import_jsx_runtime8 = require("react/jsx-runtime");
17318
17364
  function IconCtrl(props) {
17319
17365
  const { width: width2 = 24, height: height2 = 24, ...rest } = props;
17320
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: width2, height: height2, fill: "none", ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
17366
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width: width2, height: height2, fill: "none", ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
17321
17367
  "text",
17322
17368
  {
17323
17369
  x: "50%",
@@ -17334,11 +17380,11 @@ function IconCtrl(props) {
17334
17380
  }
17335
17381
 
17336
17382
  // src/components/lottie/lottie.tsx
17337
- var import_react7 = require("react");
17383
+ var import_react9 = require("react");
17338
17384
 
17339
17385
  // src/components/lottie/lottie-styles.ts
17340
- var import_styled_components7 = __toESM(require("styled-components"), 1);
17341
- var LottieContainer = import_styled_components7.default.div`
17386
+ var import_styled_components8 = __toESM(require("styled-components"), 1);
17387
+ var LottieContainer = import_styled_components8.default.div`
17342
17388
  display: inline-flex;
17343
17389
  width: ${({ $width }) => typeof $width === "number" ? `${$width}px` : $width};
17344
17390
  height: ${({ $height }) => typeof $height === "number" ? `${$height}px` : $height};
@@ -17350,7 +17396,7 @@ var LottieContainer = import_styled_components7.default.div`
17350
17396
  `;
17351
17397
 
17352
17398
  // src/components/lottie/use-lottie.ts
17353
- var import_react6 = require("react");
17399
+ var import_react8 = require("react");
17354
17400
  var import_lottie_web = __toESM(require_lottie(), 1);
17355
17401
  function useLottie({
17356
17402
  animationData: animationData2,
@@ -17365,17 +17411,17 @@ function useLottie({
17365
17411
  onLoopComplete,
17366
17412
  onEnterFrame
17367
17413
  }) {
17368
- const containerRef = (0, import_react6.useRef)(null);
17369
- const animationRef = (0, import_react6.useRef)(null);
17370
- const onAnimationLoadedRef = (0, import_react6.useRef)(onAnimationLoaded);
17371
- const onCompleteRef = (0, import_react6.useRef)(onComplete);
17372
- const onLoopCompleteRef = (0, import_react6.useRef)(onLoopComplete);
17373
- const onEnterFrameRef = (0, import_react6.useRef)(onEnterFrame);
17414
+ const containerRef = (0, import_react8.useRef)(null);
17415
+ const animationRef = (0, import_react8.useRef)(null);
17416
+ const onAnimationLoadedRef = (0, import_react8.useRef)(onAnimationLoaded);
17417
+ const onCompleteRef = (0, import_react8.useRef)(onComplete);
17418
+ const onLoopCompleteRef = (0, import_react8.useRef)(onLoopComplete);
17419
+ const onEnterFrameRef = (0, import_react8.useRef)(onEnterFrame);
17374
17420
  onAnimationLoadedRef.current = onAnimationLoaded;
17375
17421
  onCompleteRef.current = onComplete;
17376
17422
  onLoopCompleteRef.current = onLoopComplete;
17377
17423
  onEnterFrameRef.current = onEnterFrame;
17378
- (0, import_react6.useEffect)(() => {
17424
+ (0, import_react8.useEffect)(() => {
17379
17425
  if (!containerRef.current) return;
17380
17426
  const anim = import_lottie_web.default.loadAnimation({
17381
17427
  container: containerRef.current,
@@ -17467,8 +17513,8 @@ function createLottieRef(animationRef) {
17467
17513
  }
17468
17514
 
17469
17515
  // src/components/lottie/lottie.tsx
17470
- var import_jsx_runtime8 = require("react/jsx-runtime");
17471
- var Lottie = (0, import_react7.forwardRef)(function Lottie2({
17516
+ var import_jsx_runtime9 = require("react/jsx-runtime");
17517
+ var Lottie = (0, import_react9.forwardRef)(function Lottie2({
17472
17518
  animationData: animationData2,
17473
17519
  autoplay,
17474
17520
  loop,
@@ -17498,8 +17544,8 @@ var Lottie = (0, import_react7.forwardRef)(function Lottie2({
17498
17544
  onLoopComplete,
17499
17545
  onEnterFrame
17500
17546
  });
17501
- (0, import_react7.useImperativeHandle)(ref, () => createLottieRef(animationRef), [animationRef]);
17502
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
17547
+ (0, import_react9.useImperativeHandle)(ref, () => createLottieRef(animationRef), [animationRef]);
17548
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
17503
17549
  LottieContainer,
17504
17550
  {
17505
17551
  ref: containerRef,
@@ -17513,7 +17559,7 @@ var Lottie = (0, import_react7.forwardRef)(function Lottie2({
17513
17559
  });
17514
17560
 
17515
17561
  // src/components/text-area/text-area.tsx
17516
- var import_react8 = require("react");
17562
+ var import_react10 = require("react");
17517
17563
 
17518
17564
  // src/utils/merge-refs.ts
17519
17565
  function mergeRefs(...refs) {
@@ -17529,8 +17575,8 @@ function mergeRefs(...refs) {
17529
17575
  }
17530
17576
 
17531
17577
  // src/components/text-area/text-area-styles.ts
17532
- var import_styled_components8 = __toESM(require("styled-components"), 1);
17533
- var StyledTextArea = import_styled_components8.default.textarea`
17578
+ var import_styled_components9 = __toESM(require("styled-components"), 1);
17579
+ var StyledTextArea = import_styled_components9.default.textarea`
17534
17580
  ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
17535
17581
  color: ${colors["brown-100"]};
17536
17582
  border: none;
@@ -17553,23 +17599,23 @@ var StyledTextArea = import_styled_components8.default.textarea`
17553
17599
  `;
17554
17600
 
17555
17601
  // src/components/text-area/text-area.tsx
17556
- var import_jsx_runtime9 = require("react/jsx-runtime");
17557
- var TextArea = (0, import_react8.forwardRef)(function TextArea2({ value: value2, onChange, placeholder, maxHeight, rows = 1, autoFocus, onKeyDown, disabled, className }, externalRef) {
17558
- const internalRef = (0, import_react8.useRef)(null);
17559
- (0, import_react8.useLayoutEffect)(() => {
17602
+ var import_jsx_runtime10 = require("react/jsx-runtime");
17603
+ var TextArea = (0, import_react10.forwardRef)(function TextArea2({ value: value2, onChange, placeholder, maxHeight, rows = 1, autoFocus, onKeyDown, disabled, className }, externalRef) {
17604
+ const internalRef = (0, import_react10.useRef)(null);
17605
+ (0, import_react10.useLayoutEffect)(() => {
17560
17606
  const el = internalRef.current;
17561
17607
  if (el) {
17562
17608
  el.style.height = "auto";
17563
17609
  el.style.height = `${el.scrollHeight}px`;
17564
17610
  }
17565
17611
  }, [value2]);
17566
- const handleChange = (0, import_react8.useCallback)(
17612
+ const handleChange = (0, import_react10.useCallback)(
17567
17613
  (e) => {
17568
17614
  onChange(e.target.value);
17569
17615
  },
17570
17616
  [onChange]
17571
17617
  );
17572
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
17618
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
17573
17619
  StyledTextArea,
17574
17620
  {
17575
17621
  ref: mergeRefs(internalRef, externalRef),
@@ -17586,30 +17632,96 @@ var TextArea = (0, import_react8.forwardRef)(function TextArea2({ value: value2,
17586
17632
  );
17587
17633
  });
17588
17634
 
17635
+ // src/utils/parse-markdown-table.ts
17636
+ function parseCells(line) {
17637
+ const trimmed = line.trim();
17638
+ const stripped = trimmed.startsWith("|") ? trimmed.slice(1) : trimmed;
17639
+ const withoutTrailing = stripped.endsWith("|") ? stripped.slice(0, -1) : stripped;
17640
+ return withoutTrailing.split("|").map((cell) => cell.trim());
17641
+ }
17642
+ function isSeparatorRow(line) {
17643
+ const cells = parseCells(line);
17644
+ return cells.length > 0 && cells.every((cell) => /^:?-{1,}:?$/.test(cell));
17645
+ }
17646
+ function isTableRow(line) {
17647
+ return line.includes("|");
17648
+ }
17649
+ var TABLE_TITLE_PREFIX = "<!-- table-title:";
17650
+ var TABLE_TITLE_SUFFIX = "-->";
17651
+ function extractTableTitle(line) {
17652
+ const trimmed = line.trim();
17653
+ if (!trimmed.startsWith(TABLE_TITLE_PREFIX) || !trimmed.endsWith(TABLE_TITLE_SUFFIX)) {
17654
+ return void 0;
17655
+ }
17656
+ return trimmed.slice(TABLE_TITLE_PREFIX.length, -TABLE_TITLE_SUFFIX.length).trim() || void 0;
17657
+ }
17658
+ function parseMarkdownTable(markdown, tableIndex = 0) {
17659
+ const lines = markdown.split("\n");
17660
+ let tableCount = 0;
17661
+ for (let i = 0; i < lines.length - 1; i++) {
17662
+ const headerLine = lines[i];
17663
+ const separatorLine = lines[i + 1];
17664
+ if (!isTableRow(headerLine) || !isSeparatorRow(separatorLine)) {
17665
+ continue;
17666
+ }
17667
+ if (tableCount === tableIndex) {
17668
+ const columns = parseCells(headerLine);
17669
+ const rows = [];
17670
+ const title = i > 0 ? extractTableTitle(lines[i - 1]) : void 0;
17671
+ for (let j = i + 2; j < lines.length; j++) {
17672
+ if (!isTableRow(lines[j]) || isSeparatorRow(lines[j])) {
17673
+ break;
17674
+ }
17675
+ const trimmedLine = lines[j].trim();
17676
+ if (trimmedLine === "") {
17677
+ break;
17678
+ }
17679
+ rows.push(parseCells(lines[j]));
17680
+ }
17681
+ return { columns, rows, ...title ? { title } : {} };
17682
+ }
17683
+ tableCount++;
17684
+ }
17685
+ return null;
17686
+ }
17687
+
17688
+ // src/utils/convert-table-to-csv.ts
17689
+ function escapeField(field) {
17690
+ if (field.includes(",") || field.includes('"') || field.includes("\n") || field.includes("\r")) {
17691
+ return `"${field.replace(/"/g, '""')}"`;
17692
+ }
17693
+ return field;
17694
+ }
17695
+ function convertTableToCSV(table) {
17696
+ const headerRow = table.columns.map(escapeField).join(",");
17697
+ const dataRows = table.rows.map((row) => row.map(escapeField).join(","));
17698
+ return [headerRow, ...dataRows].join("\r\n");
17699
+ }
17700
+
17589
17701
  // src/components/button/button.tsx
17590
- var import_react9 = require("react");
17702
+ var import_react11 = require("react");
17591
17703
 
17592
17704
  // src/components/button/button-styles.ts
17593
- var import_styled_components9 = __toESM(require("styled-components"), 1);
17705
+ var import_styled_components10 = __toESM(require("styled-components"), 1);
17594
17706
  var sizeStyles = {
17595
- xs: import_styled_components9.css`
17707
+ xs: import_styled_components10.css`
17596
17708
  padding: 6px 10px;
17597
17709
  border-radius: 8px;
17598
17710
  gap: 4px;
17599
17711
  `,
17600
- s: import_styled_components9.css`
17712
+ s: import_styled_components10.css`
17601
17713
  padding: 8px 12px;
17602
17714
  border-radius: 10px;
17603
17715
  gap: 6px;
17604
17716
  `,
17605
- m: import_styled_components9.css`
17717
+ m: import_styled_components10.css`
17606
17718
  padding: 10px 14px;
17607
17719
  border-radius: 10px;
17608
17720
  gap: 6px;
17609
17721
  `
17610
17722
  };
17611
17723
  var variantStyles2 = {
17612
- solid: import_styled_components9.css`
17724
+ solid: import_styled_components10.css`
17613
17725
  background: ${colors["brown-100"]};
17614
17726
  color: ${colors.white};
17615
17727
  border: none;
@@ -17623,7 +17735,7 @@ var variantStyles2 = {
17623
17735
  color: ${colors["brown-50"]};
17624
17736
  }
17625
17737
  `,
17626
- outline: import_styled_components9.css`
17738
+ outline: import_styled_components10.css`
17627
17739
  background: ${colors.white};
17628
17740
  color: ${colors["brown-100"]};
17629
17741
  border: 1px solid ${colors["brown-40"]};
@@ -17637,7 +17749,7 @@ var variantStyles2 = {
17637
17749
  color: ${colors["brown-50"]};
17638
17750
  }
17639
17751
  `,
17640
- ghost: import_styled_components9.css`
17752
+ ghost: import_styled_components10.css`
17641
17753
  background: transparent;
17642
17754
  color: ${colors["brown-100"]};
17643
17755
  border: none;
@@ -17651,7 +17763,7 @@ var variantStyles2 = {
17651
17763
  }
17652
17764
  `
17653
17765
  };
17654
- var StyledButton = import_styled_components9.default.button`
17766
+ var StyledButton = import_styled_components10.default.button`
17655
17767
  display: inline-flex;
17656
17768
  align-items: center;
17657
17769
  justify-content: center;
@@ -17684,8 +17796,8 @@ var ICON_POSITION = {
17684
17796
  };
17685
17797
 
17686
17798
  // src/components/button/button.tsx
17687
- var import_jsx_runtime10 = require("react/jsx-runtime");
17688
- var Button2 = (0, import_react9.forwardRef)(function Button3({
17799
+ var import_jsx_runtime11 = require("react/jsx-runtime");
17800
+ var Button2 = (0, import_react11.forwardRef)(function Button3({
17689
17801
  children,
17690
17802
  variant = BUTTON_VARIANT.SOLID,
17691
17803
  size = BUTTON_SIZE.M,
@@ -17696,8 +17808,8 @@ var Button2 = (0, import_react9.forwardRef)(function Button3({
17696
17808
  className,
17697
17809
  "aria-label": ariaLabel
17698
17810
  }, ref) {
17699
- const iconElement = icon ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Icon, { icon, size: 16 }) : null;
17700
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
17811
+ const iconElement = icon ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Icon, { icon, size: 16 }) : null;
17812
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
17701
17813
  StyledButton,
17702
17814
  {
17703
17815
  ref,
@@ -17710,7 +17822,7 @@ var Button2 = (0, import_react9.forwardRef)(function Button3({
17710
17822
  "aria-label": ariaLabel,
17711
17823
  children: [
17712
17824
  iconPosition === ICON_POSITION.LEADING && iconElement,
17713
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children }),
17825
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children }),
17714
17826
  iconPosition === ICON_POSITION.TRAILING && iconElement
17715
17827
  ]
17716
17828
  }
@@ -17733,9 +17845,11 @@ var Button2 = (0, import_react9.forwardRef)(function Button3({
17733
17845
  MESSAGE_ROLE,
17734
17846
  TextArea,
17735
17847
  colors,
17848
+ convertTableToCSV,
17736
17849
  fontFamilies,
17737
17850
  markdownToPlainText,
17738
17851
  mergeRefs,
17852
+ parseMarkdownTable,
17739
17853
  typographyMixin,
17740
17854
  typographyStyles,
17741
17855
  typographyTypes,