@shapesos/clay 0.4.1 → 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 (65) hide show
  1. package/dist/chat.cjs +199 -87
  2. package/dist/chat.cjs.map +1 -1
  3. package/dist/chat.d.cts +6 -1
  4. package/dist/chat.d.ts +6 -1
  5. package/dist/chat.js +8 -4
  6. package/dist/chunk-DRBRT57F.js +1 -0
  7. package/dist/chunk-DRBRT57F.js.map +1 -0
  8. package/dist/chunk-JC2RQL5O.js +76 -0
  9. package/dist/chunk-JC2RQL5O.js.map +1 -0
  10. package/dist/{chunk-6HNZQ2BF.js → chunk-JF3P66JF.js} +2 -1
  11. package/dist/chunk-JF3P66JF.js.map +1 -0
  12. package/dist/chunk-K2Q5MQWJ.js +17 -0
  13. package/dist/chunk-K2Q5MQWJ.js.map +1 -0
  14. package/dist/chunk-MLCRDVQ2.js +89 -0
  15. package/dist/chunk-MLCRDVQ2.js.map +1 -0
  16. package/dist/chunk-OLJIJYB5.js +46 -0
  17. package/dist/chunk-OLJIJYB5.js.map +1 -0
  18. package/dist/{chunk-EPS4LOOW.js → chunk-PCBRMJJJ.js} +141 -65
  19. package/dist/chunk-PCBRMJJJ.js.map +1 -0
  20. package/dist/chunk-SMTOVZ3O.js +19 -0
  21. package/dist/chunk-SMTOVZ3O.js.map +1 -0
  22. package/dist/{chunk-A6DKIFWS.js → chunk-WQ2QTUYA.js} +9 -1
  23. package/dist/chunk-WQ2QTUYA.js.map +1 -0
  24. package/dist/chunk-WZHNMC6P.js +77 -0
  25. package/dist/chunk-WZHNMC6P.js.map +1 -0
  26. package/dist/icon.cjs +31 -16
  27. package/dist/icon.cjs.map +1 -1
  28. package/dist/icon.d.cts +6 -2
  29. package/dist/icon.d.ts +6 -2
  30. package/dist/icon.js +5 -3
  31. package/dist/index.cjs +297 -105
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +5 -20
  34. package/dist/index.d.ts +5 -20
  35. package/dist/index.js +32 -74
  36. package/dist/index.js.map +1 -1
  37. package/dist/keyboard-shortcut.cjs +238 -0
  38. package/dist/keyboard-shortcut.cjs.map +1 -0
  39. package/dist/keyboard-shortcut.d.cts +19 -0
  40. package/dist/keyboard-shortcut.d.ts +19 -0
  41. package/dist/keyboard-shortcut.js +14 -0
  42. package/dist/keyboard-shortcut.js.map +1 -0
  43. package/dist/text-area.cjs +497 -0
  44. package/dist/text-area.cjs.map +1 -0
  45. package/dist/text-area.d.cts +18 -0
  46. package/dist/text-area.d.ts +18 -0
  47. package/dist/text-area.js +11 -0
  48. package/dist/text-area.js.map +1 -0
  49. package/dist/tokens.cjs +9 -0
  50. package/dist/tokens.cjs.map +1 -1
  51. package/dist/tokens.d.cts +2 -0
  52. package/dist/tokens.d.ts +2 -0
  53. package/dist/tokens.js +2 -2
  54. package/dist/utils.cjs +60 -0
  55. package/dist/utils.cjs.map +1 -0
  56. package/dist/utils.d.cts +7 -0
  57. package/dist/utils.d.ts +7 -0
  58. package/dist/utils.js +13 -0
  59. package/dist/utils.js.map +1 -0
  60. package/package.json +17 -1
  61. package/dist/chunk-6HNZQ2BF.js.map +0 -1
  62. package/dist/chunk-A6DKIFWS.js.map +0 -1
  63. package/dist/chunk-AEXYOY5H.js +0 -115
  64. package/dist/chunk-AEXYOY5H.js.map +0 -1
  65. package/dist/chunk-EPS4LOOW.js.map +0 -1
@@ -1,95 +1,153 @@
1
+ import {
2
+ IconButton
3
+ } from "./chunk-MLCRDVQ2.js";
1
4
  import {
2
5
  typographyMixin,
3
6
  typographyTypes
4
- } from "./chunk-A6DKIFWS.js";
5
- import {
6
- IconButton
7
- } from "./chunk-AEXYOY5H.js";
7
+ } from "./chunk-WQ2QTUYA.js";
8
8
  import {
9
9
  colors
10
- } from "./chunk-6HNZQ2BF.js";
10
+ } from "./chunk-JF3P66JF.js";
11
+ import {
12
+ markdownToPlainText
13
+ } from "./chunk-SMTOVZ3O.js";
11
14
 
12
15
  // src/chat/chat-message-content/chat-message-content.tsx
13
16
  import ReactMarkdown from "react-markdown";
17
+ import remarkBreaks from "remark-breaks";
14
18
  import remarkGfm from "remark-gfm";
15
19
 
16
20
  // src/chat/chat-message-content/chat-message-content-styles.ts
17
21
  import styled from "styled-components";
18
22
  var ContentWrapper = styled.div`
19
- ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
23
+ ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
20
24
  color: ${colors["brown-100"]};
21
25
  word-break: break-word;
22
26
 
23
- & p {
24
- margin: 0;
27
+ & h1 {
28
+ ${typographyMixin(typographyTypes.GEIST_HEADING_S_BOLD)};
29
+ margin-block: 20px;
25
30
  }
26
31
 
27
- & p + p {
28
- margin-top: 8px;
32
+ & h2 {
33
+ ${typographyMixin(typographyTypes.GEIST_BODY_L_SEMI_BOLD)};
34
+ margin-block: 12px;
35
+ }
36
+
37
+ & h3,
38
+ & h4,
39
+ & h5,
40
+ & h6 {
41
+ ${typographyMixin(typographyTypes.GEIST_BODY_M_SEMI_BOLD)};
42
+ margin-block: 8px;
43
+ }
44
+
45
+ & strong {
46
+ ${typographyMixin(typographyTypes.GEIST_BODY_S_SEMI_BOLD)};
47
+ }
48
+
49
+ & p {
50
+ margin-block: 8px;
29
51
  }
30
52
 
31
53
  & ul,
32
54
  & ol {
33
- margin: 4px 0;
55
+ margin-block: 16px;
34
56
  padding-left: 20px;
35
57
  }
36
58
 
37
- & a {
38
- color: ${colors["brown-100"]};
39
- text-decoration: underline;
59
+ & li + li {
60
+ margin-block: 4px;
40
61
  }
41
62
 
42
- & pre {
43
- overflow-x: auto;
44
- padding: 8px;
45
- margin: 4px 0;
46
- background: ${colors["brown-10"]};
47
- border: 1px solid ${colors["brown-alpha-12"]};
48
- border-radius: 8px;
63
+ & ol {
64
+ list-style-type: decimal;
65
+ }
66
+
67
+ & ol ol {
68
+ list-style-type: lower-alpha;
49
69
  }
50
70
 
51
- & pre code {
52
- padding: 0;
53
- background: none;
54
- border-radius: 0;
71
+ & ol ol ol {
72
+ list-style-type: lower-roman;
55
73
  }
56
74
 
57
- & code {
58
- padding: 2px 4px;
59
- background: ${colors["brown-10"]};
60
- border-radius: 4px;
75
+ & a {
76
+ color: inherit;
77
+ text-decoration-line: underline;
78
+ text-decoration-style: dotted;
79
+ text-decoration-thickness: auto;
80
+ text-underline-offset: auto;
81
+ text-underline-position: from-font;
82
+ transition: color 75ms ease-in-out;
83
+
84
+ &:hover {
85
+ color: ${colors["blue-600"]};
86
+ }
87
+ }
88
+
89
+ & hr {
90
+ border: none;
91
+ border-top: 1px solid ${colors["brown-40"]};
92
+ margin-block: 20px;
61
93
  }
62
94
 
63
95
  & table {
64
- border-collapse: collapse;
65
- margin: 8px 0;
96
+ margin: 0;
66
97
  width: 100%;
98
+ border-collapse: collapse;
67
99
  }
68
100
 
69
101
  & th,
70
102
  & td {
71
- border: 1px solid ${colors["brown-alpha-12"]};
72
- padding: 6px 12px;
103
+ border: none;
104
+ border-bottom: 1px solid ${colors["brown-40"]};
73
105
  text-align: left;
74
106
  }
75
107
 
76
108
  & th {
77
- background: ${colors["brown-10"]};
78
- font-weight: 600;
109
+ ${typographyMixin(typographyTypes.GEIST_LABEL_CAPTION_MEDIUM)};
110
+ padding: 8px;
111
+ }
112
+
113
+ & td {
114
+ ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
115
+ padding: 16px 8px;
116
+ min-width: 150px;
117
+ width: 1%;
118
+ }
119
+
120
+ & td strong {
121
+ font-weight: inherit;
122
+ font-size: inherit;
123
+ line-height: inherit;
79
124
  }
80
125
 
81
126
  & blockquote {
82
- margin: 4px 0;
83
- padding-left: 12px;
84
- border-left: 3px solid ${colors["brown-30"]};
85
- color: ${colors["brown-70"]};
127
+ margin-block: 4px;
128
+ margin-inline: 0px;
129
+ padding-left: 16px;
130
+ border-left: 4px solid ${colors["brown-40"]};
131
+ color: ${colors["brown-80"]};
86
132
  }
87
133
  `;
134
+ var TableScroll = styled.div`
135
+ width: 100%;
136
+ overflow-x: auto;
137
+ overflow-y: hidden;
138
+ margin-block: 8px 16px;
139
+ `;
88
140
 
89
141
  // src/chat/chat-message-content/chat-message-content.tsx
90
142
  import { jsx } from "react/jsx-runtime";
143
+ function ScrollableTable({ node: _node, ...props }) {
144
+ return /* @__PURE__ */ jsx(TableScroll, { children: /* @__PURE__ */ jsx("table", { ...props }) });
145
+ }
146
+ var markdownComponents = {
147
+ table: ScrollableTable
148
+ };
91
149
  function ChatMessageContent({ content }) {
92
- return /* @__PURE__ */ jsx(ContentWrapper, { children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: content }) });
150
+ return /* @__PURE__ */ jsx(ContentWrapper, { children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm, remarkBreaks], components: markdownComponents, children: content }) });
93
151
  }
94
152
 
95
153
  // src/chat/chat-message-actions/chat-message-actions.tsx
@@ -200,7 +258,7 @@ function useCopyToClipboard() {
200
258
  };
201
259
  }, []);
202
260
  const copy = useCallback((text) => {
203
- copyToClipboard(text, {
261
+ copyToClipboard(markdownToPlainText(text), {
204
262
  onSuccess: () => {
205
263
  setIsCopied(true);
206
264
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
@@ -214,20 +272,33 @@ function useCopyToClipboard() {
214
272
  return { isCopied, copy };
215
273
  }
216
274
 
275
+ // src/chat/constants.ts
276
+ var MESSAGE_ROLE = {
277
+ USER: "user",
278
+ ASSISTANT: "assistant"
279
+ };
280
+
217
281
  // src/chat/chat-message-actions/chat-message-actions-styles.ts
218
282
  import styled2 from "styled-components";
283
+ var FADE_DURATION_MS = 150;
284
+ var ANIMATE_DURATION_MS = 200;
219
285
  var ActionsContainer = styled2.div`
220
286
  display: flex;
221
- gap: 2px;
222
- margin-top: 4px;
223
- opacity: 0;
224
- pointer-events: none;
225
- transition: opacity 150ms ease;
287
+ opacity: ${({ $role }) => $role === MESSAGE_ROLE.ASSISTANT ? 1 : 0};
288
+ pointer-events: ${({ $role }) => $role === MESSAGE_ROLE.ASSISTANT ? "auto" : "none"};
289
+ transition: opacity ${FADE_DURATION_MS}ms ease;
290
+ `;
291
+ var AnimatedAction = styled2.div`
292
+ display: flex;
293
+ overflow: hidden;
294
+ max-width: ${({ $visible }) => $visible ? "40px" : "0"};
295
+ opacity: ${({ $visible }) => $visible ? 1 : 0};
296
+ transition: max-width ${ANIMATE_DURATION_MS}ms ease, opacity ${ANIMATE_DURATION_MS}ms ease;
226
297
  `;
227
298
 
228
299
  // src/chat/chat-message-actions/chat-message-actions.tsx
229
300
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
230
- function ChatMessageActions({ messageId, content, role, isHelpful }) {
301
+ function ChatMessageActions({ className, messageId, content, role, isHelpful }) {
231
302
  const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();
232
303
  const { isCopied, copy } = useCopyToClipboard();
233
304
  const handleCopy = useCallback2(() => {
@@ -240,9 +311,9 @@ function ChatMessageActions({ messageId, content, role, isHelpful }) {
240
311
  const handleThumbDown = useCallback2(() => {
241
312
  onThumbDownClick?.(messageId, isHelpful === false ? null : false);
242
313
  }, [messageId, isHelpful, onThumbDownClick]);
243
- const isAssistant = role === "assistant";
314
+ const isAssistant = role === MESSAGE_ROLE.ASSISTANT;
244
315
  const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);
245
- return /* @__PURE__ */ jsxs(ActionsContainer, { children: [
316
+ return /* @__PURE__ */ jsxs(ActionsContainer, { $role: role, className, children: [
246
317
  /* @__PURE__ */ jsx2(
247
318
  IconButton,
248
319
  {
@@ -251,7 +322,7 @@ function ChatMessageActions({ messageId, content, role, isHelpful }) {
251
322
  "aria-label": isCopied ? "Copied" : "Copy message"
252
323
  }
253
324
  ),
254
- hasFeedback && /* @__PURE__ */ jsx2(
325
+ hasFeedback && /* @__PURE__ */ jsx2(AnimatedAction, { $visible: isHelpful !== false, children: /* @__PURE__ */ jsx2(
255
326
  IconButton,
256
327
  {
257
328
  icon: IconThumbUp,
@@ -259,8 +330,8 @@ function ChatMessageActions({ messageId, content, role, isHelpful }) {
259
330
  isSelected: isHelpful === true,
260
331
  "aria-label": "Good response"
261
332
  }
262
- ),
263
- hasFeedback && /* @__PURE__ */ jsx2(
333
+ ) }),
334
+ hasFeedback && /* @__PURE__ */ jsx2(AnimatedAction, { $visible: isHelpful !== true, children: /* @__PURE__ */ jsx2(
264
335
  IconButton,
265
336
  {
266
337
  icon: IconThumbDown,
@@ -268,7 +339,7 @@ function ChatMessageActions({ messageId, content, role, isHelpful }) {
268
339
  isSelected: isHelpful === false,
269
340
  "aria-label": "Bad response"
270
341
  }
271
- )
342
+ ) })
272
343
  ] });
273
344
  }
274
345
 
@@ -276,25 +347,29 @@ function ChatMessageActions({ messageId, content, role, isHelpful }) {
276
347
  import styled3 from "styled-components";
277
348
  var MessageRow = styled3.div`
278
349
  display: flex;
279
- justify-content: ${({ $role }) => $role === "user" ? "flex-end" : "flex-start"};
280
- `;
281
- var MessageContainer = styled3.div`
282
- display: flex;
283
- flex-direction: column;
284
- align-items: ${({ $role }) => $role === "user" ? "flex-end" : "flex-start"};
285
- max-width: 90%;
350
+ justify-content: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "flex-end" : "flex-start"};
286
351
 
287
352
  &:hover ${ActionsContainer} {
288
353
  opacity: 1;
289
354
  pointer-events: auto;
290
355
  }
291
356
  `;
357
+ var MessageContainer = styled3.div`
358
+ display: flex;
359
+ flex-direction: column;
360
+ align-items: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "flex-end" : "flex-start"};
361
+ max-width: 90%;
362
+ width: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "auto" : "100%"};
363
+ gap: 12px;
364
+ `;
292
365
  var MessageBubble = styled3.div`
293
- ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};
366
+ ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};
294
367
  color: ${colors["brown-100"]};
295
- background: ${({ $role }) => $role === "user" ? colors.white : "transparent"};
296
- padding: ${({ $role }) => $role === "user" ? "12px 16px" : "0"};
297
- border-radius: ${({ $role }) => $role === "user" ? "16px" : "0"};
368
+ background: ${({ $role }) => $role === MESSAGE_ROLE.USER ? colors.white : "transparent"};
369
+ padding: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "12px 16px" : "0"};
370
+ border-radius: ${({ $role }) => $role === MESSAGE_ROLE.USER ? "16px" : "0"};
371
+ max-width: 100%;
372
+ min-width: 0;
298
373
  `;
299
374
 
300
375
  // src/chat/chat-message/chat-message.tsx
@@ -318,6 +393,7 @@ export {
318
393
  ChatContext,
319
394
  useChatContext,
320
395
  useCopyToClipboard,
396
+ MESSAGE_ROLE,
321
397
  ChatMessage
322
398
  };
323
399
  /*! Bundled license information:
@@ -336,4 +412,4 @@ export {
336
412
  * See the LICENSE file in the root directory of this source tree.
337
413
  *)
338
414
  */
339
- //# sourceMappingURL=chunk-EPS4LOOW.js.map
415
+ //# sourceMappingURL=chunk-PCBRMJJJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/chat/chat-message-content/chat-message-content.tsx","../src/chat/chat-message-content/chat-message-content-styles.ts","../src/chat/chat-message-actions/chat-message-actions.tsx","../node_modules/@tabler/icons-react/src/defaultAttributes.ts","../node_modules/@tabler/icons-react/src/createReactComponent.ts","../node_modules/@tabler/icons-react/src/icons/IconCheck.ts","../node_modules/@tabler/icons-react/src/icons/IconCopy.ts","../node_modules/@tabler/icons-react/src/icons/IconThumbDown.ts","../node_modules/@tabler/icons-react/src/icons/IconThumbUp.ts","../src/chat/chat-context/chat-context.ts","../src/chat/hooks/use-copy-to-clipboard.ts","../src/utils/clipboard.ts","../src/chat/constants.ts","../src/chat/chat-message-actions/chat-message-actions-styles.ts","../src/chat/chat-message/chat-message-styles.ts","../src/chat/chat-message/chat-message.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport remarkBreaks from \"remark-breaks\";\nimport remarkGfm from \"remark-gfm\";\n\nimport { ContentWrapper, TableScroll } from \"./chat-message-content-styles\";\n\ninterface ChatMessageContentProps {\n content: string;\n}\n\nfunction ScrollableTable({ node: _node, ...props }: { node?: unknown; children?: ReactNode }): ReactNode {\n return (\n <TableScroll>\n <table {...props} />\n </TableScroll>\n );\n}\n\nconst markdownComponents = {\n table: ScrollableTable as React.ComponentType<unknown>,\n};\n\nexport function ChatMessageContent({ content }: ChatMessageContentProps) {\n return (\n <ContentWrapper>\n <ReactMarkdown remarkPlugins={[remarkGfm, remarkBreaks]} components={markdownComponents}>\n {content}\n </ReactMarkdown>\n </ContentWrapper>\n );\n}\n","import styled from \"styled-components\";\n\nimport { colors } from \"../../tokens/colors\";\nimport { typographyMixin, typographyTypes } from \"../../tokens/typography\";\n\nexport const ContentWrapper = styled.div`\n ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};\n color: ${colors[\"brown-100\"]};\n word-break: break-word;\n\n & h1 {\n ${typographyMixin(typographyTypes.GEIST_HEADING_S_BOLD)};\n margin-block: 20px;\n }\n\n & h2 {\n ${typographyMixin(typographyTypes.GEIST_BODY_L_SEMI_BOLD)};\n margin-block: 12px;\n }\n\n & h3,\n & h4,\n & h5,\n & h6 {\n ${typographyMixin(typographyTypes.GEIST_BODY_M_SEMI_BOLD)};\n margin-block: 8px;\n }\n\n & strong {\n ${typographyMixin(typographyTypes.GEIST_BODY_S_SEMI_BOLD)};\n }\n\n & p {\n margin-block: 8px;\n }\n\n & ul,\n & ol {\n margin-block: 16px;\n padding-left: 20px;\n }\n\n & li + li {\n margin-block: 4px;\n }\n\n & ol {\n list-style-type: decimal;\n }\n\n & ol ol {\n list-style-type: lower-alpha;\n }\n\n & ol ol ol {\n list-style-type: lower-roman;\n }\n\n & a {\n color: inherit;\n text-decoration-line: underline;\n text-decoration-style: dotted;\n text-decoration-thickness: auto;\n text-underline-offset: auto;\n text-underline-position: from-font;\n transition: color 75ms ease-in-out;\n\n &:hover {\n color: ${colors[\"blue-600\"]};\n }\n }\n\n & hr {\n border: none;\n border-top: 1px solid ${colors[\"brown-40\"]};\n margin-block: 20px;\n }\n\n & table {\n margin: 0;\n width: 100%;\n border-collapse: collapse;\n }\n\n & th,\n & td {\n border: none;\n border-bottom: 1px solid ${colors[\"brown-40\"]};\n text-align: left;\n }\n\n & th {\n ${typographyMixin(typographyTypes.GEIST_LABEL_CAPTION_MEDIUM)};\n padding: 8px;\n }\n\n & td {\n ${typographyMixin(typographyTypes.GEIST_BODY_XS_MEDIUM)};\n padding: 16px 8px;\n min-width: 150px;\n width: 1%;\n }\n\n & td strong {\n font-weight: inherit;\n font-size: inherit;\n line-height: inherit;\n }\n\n & blockquote {\n margin-block: 4px;\n margin-inline: 0px;\n padding-left: 16px;\n border-left: 4px solid ${colors[\"brown-40\"]};\n color: ${colors[\"brown-80\"]};\n }\n`;\n\nexport const TableScroll = styled.div`\n width: 100%;\n overflow-x: auto;\n overflow-y: hidden;\n margin-block: 8px 16px;\n`;\n","import { useCallback } from \"react\";\nimport { IconCopy, IconCheck, IconThumbUp, IconThumbDown } from \"@tabler/icons-react\";\n\nimport { IconButton } from \"../../components/icon-button/icon-button\";\nimport { useChatContext } from \"../chat-context/chat-context\";\nimport { useCopyToClipboard } from \"../hooks/use-copy-to-clipboard\";\nimport { MESSAGE_ROLE } from \"../constants\";\nimport type { MessageRole } from \"../types\";\nimport { ActionsContainer, AnimatedAction } from \"./chat-message-actions-styles\";\n\ninterface ChatMessageActionsProps {\n className?: string;\n messageId: string;\n content: string;\n role: MessageRole;\n isHelpful?: boolean | null;\n}\n\nexport function ChatMessageActions({ className, messageId, content, role, isHelpful }: ChatMessageActionsProps) {\n const { onCopyMessage, onThumbUpClick, onThumbDownClick } = useChatContext();\n const { isCopied, copy } = useCopyToClipboard();\n\n const handleCopy = useCallback(() => {\n copy(content);\n onCopyMessage?.(messageId);\n }, [content, messageId, copy, onCopyMessage]);\n\n const handleThumbUp = useCallback(() => {\n onThumbUpClick?.(messageId, isHelpful === true ? null : true);\n }, [messageId, isHelpful, onThumbUpClick]);\n\n const handleThumbDown = useCallback(() => {\n onThumbDownClick?.(messageId, isHelpful === false ? null : false);\n }, [messageId, isHelpful, onThumbDownClick]);\n\n const isAssistant = role === MESSAGE_ROLE.ASSISTANT;\n const hasFeedback = isAssistant && (onThumbUpClick || onThumbDownClick);\n\n return (\n <ActionsContainer $role={role} className={className}>\n <IconButton\n icon={isCopied ? IconCheck : IconCopy}\n onClick={handleCopy}\n aria-label={isCopied ? \"Copied\" : \"Copy message\"}\n />\n\n {hasFeedback && (\n <AnimatedAction $visible={isHelpful !== false}>\n <IconButton\n icon={IconThumbUp}\n onClick={handleThumbUp}\n isSelected={isHelpful === true}\n aria-label=\"Good response\"\n />\n </AnimatedAction>\n )}\n\n {hasFeedback && (\n <AnimatedAction $visible={isHelpful !== true}>\n <IconButton\n icon={IconThumbDown}\n onClick={handleThumbDown}\n isSelected={isHelpful === false}\n aria-label=\"Bad response\"\n />\n </AnimatedAction>\n )}\n </ActionsContainer>\n );\n}\n","export default {\n outline: {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n },\n filled: {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'currentColor',\n stroke: 'none',\n },\n};\n","import { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes';\nimport type { IconNode, IconProps, Icon } from './types';\n\nconst createReactComponent = (\n type: 'outline' | 'filled',\n iconName: string,\n iconNamePascal: string,\n iconNode: IconNode,\n) => {\n const Component = forwardRef<SVGSVGElement, IconProps>(\n (\n { color = 'currentColor', size = 24, stroke = 2, title, className, children, ...rest }: IconProps,\n ref,\n ) =>\n createElement(\n 'svg',\n {\n ref,\n ...defaultAttributes[type],\n width: size,\n height: size,\n className: [`tabler-icon`, `tabler-icon-${iconName}`, className].join(' '),\n ...(type === 'filled'\n ? {\n fill: color,\n }\n : {\n strokeWidth: stroke,\n stroke: color,\n }),\n ...rest,\n },\n [\n title && createElement('title', { key: 'svg-title' }, title),\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...(Array.isArray(children) ? children : [children]),\n ],\n ),\n );\n\n Component.displayName = `${iconNamePascal}`;\n\n return Component;\n};\n\nexport default createReactComponent;\n","import createReactComponent from '../createReactComponent';\nimport { IconNode } from '../types';\n\nexport const __iconNode: IconNode = [[\"path\",{\"d\":\"M5 12l5 5l10 -10\",\"key\":\"svg-0\"}]]\n\nconst IconCheck = createReactComponent('outline', 'check', 'Check', __iconNode);\n\nexport default IconCheck;","import createReactComponent from '../createReactComponent';\nimport { IconNode } from '../types';\n\nexport const __iconNode: IconNode = [[\"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\"}]]\n\nconst IconCopy = createReactComponent('outline', 'copy', 'Copy', __iconNode);\n\nexport default IconCopy;","import createReactComponent from '../createReactComponent';\nimport { IconNode } from '../types';\n\nexport const __iconNode: IconNode = [[\"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\"}]]\n\nconst IconThumbDown = createReactComponent('outline', 'thumb-down', 'ThumbDown', __iconNode);\n\nexport default IconThumbDown;","import createReactComponent from '../createReactComponent';\nimport { IconNode } from '../types';\n\nexport const __iconNode: IconNode = [[\"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\"}]]\n\nconst IconThumbUp = createReactComponent('outline', 'thumb-up', 'ThumbUp', __iconNode);\n\nexport default IconThumbUp;","import { createContext, useContext } from \"react\";\nimport type { ChatContextValue } from \"../types\";\n\nexport const ChatContext = createContext<ChatContextValue | null>(null);\n\nexport function useChatContext(): ChatContextValue {\n const context = useContext(ChatContext);\n if (!context) {\n throw new Error(\"useChatContext must be used within a Chat.Root component\");\n }\n return context;\n}\n","import { useState, useCallback, useRef, useEffect } from \"react\";\n\nimport { copyToClipboard } from \"@/utils/clipboard\";\nimport { markdownToPlainText } from \"@/utils/markdown-to-plain-text\";\n\nconst RESET_DELAY_MS = 2000;\n\ninterface UseCopyToClipboardResult {\n isCopied: boolean;\n copy: (text: string) => void;\n}\n\nexport function useCopyToClipboard(): UseCopyToClipboardResult {\n const [isCopied, setIsCopied] = useState(false);\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n return () => {\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n };\n }, []);\n\n const copy = useCallback((text: string) => {\n copyToClipboard(markdownToPlainText(text), {\n onSuccess: () => {\n setIsCopied(true);\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\n timeoutRef.current = setTimeout(() => {\n setIsCopied(false);\n timeoutRef.current = null;\n }, RESET_DELAY_MS);\n },\n });\n }, []);\n\n return { isCopied, copy };\n}\n","interface CopyToClipboardOptions {\n onSuccess?: () => void;\n onFailure?: (error: unknown) => void;\n}\n\nexport function copyToClipboard(text: string, options?: CopyToClipboardOptions): void {\n navigator.clipboard.writeText(text).then(\n () => options?.onSuccess?.(),\n (error) => options?.onFailure?.(error)\n );\n}\n","export const MESSAGE_ROLE = {\n USER: \"user\",\n ASSISTANT: \"assistant\",\n} as const;\n","import styled from \"styled-components\";\n\nimport { MESSAGE_ROLE } from \"../constants\";\nimport type { MessageRole } from \"../types\";\n\nconst FADE_DURATION_MS = 150;\nconst ANIMATE_DURATION_MS = 200;\n\nexport const ActionsContainer = styled.div<{ $role: MessageRole }>`\n display: flex;\n opacity: ${({ $role }) => ($role === MESSAGE_ROLE.ASSISTANT ? 1 : 0)};\n pointer-events: ${({ $role }) => ($role === MESSAGE_ROLE.ASSISTANT ? \"auto\" : \"none\")};\n transition: opacity ${FADE_DURATION_MS}ms ease;\n`;\n\nexport const AnimatedAction = styled.div<{ $visible: boolean }>`\n display: flex;\n overflow: hidden;\n max-width: ${({ $visible }) => ($visible ? \"40px\" : \"0\")};\n opacity: ${({ $visible }) => ($visible ? 1 : 0)};\n transition: max-width ${ANIMATE_DURATION_MS}ms ease, opacity ${ANIMATE_DURATION_MS}ms ease;\n`;\n","import styled from \"styled-components\";\n\nimport { colors } from \"../../tokens/colors\";\nimport { typographyMixin, typographyTypes } from \"../../tokens/typography\";\nimport { ActionsContainer } from \"../chat-message-actions/chat-message-actions-styles\";\nimport { MESSAGE_ROLE } from \"../constants\";\nimport type { MessageRole } from \"../types\";\n\nexport const MessageRow = styled.div<{ $role: MessageRole }>`\n display: flex;\n justify-content: ${({ $role }) => ($role === MESSAGE_ROLE.USER ? \"flex-end\" : \"flex-start\")};\n\n &:hover ${ActionsContainer} {\n opacity: 1;\n pointer-events: auto;\n }\n`;\n\nexport const MessageContainer = styled.div<{ $role: MessageRole }>`\n display: flex;\n flex-direction: column;\n align-items: ${({ $role }) => ($role === MESSAGE_ROLE.USER ? \"flex-end\" : \"flex-start\")};\n max-width: 90%;\n width: ${({ $role }) => ($role === MESSAGE_ROLE.USER ? \"auto\" : \"100%\")};\n gap: 12px;\n`;\n\nexport const MessageBubble = styled.div<{ $role: MessageRole }>`\n ${typographyMixin(typographyTypes.GEIST_BODY_S_REGULAR)};\n color: ${colors[\"brown-100\"]};\n background: ${({ $role }) => ($role === MESSAGE_ROLE.USER ? colors.white : \"transparent\")};\n padding: ${({ $role }) => ($role === MESSAGE_ROLE.USER ? \"12px 16px\" : \"0\")};\n border-radius: ${({ $role }) => ($role === MESSAGE_ROLE.USER ? \"16px\" : \"0\")};\n max-width: 100%;\n min-width: 0;\n`;\n","import type { ChatMessage as ChatMessageType } from \"../types\";\nimport { ChatMessageContent } from \"../chat-message-content/chat-message-content\";\nimport { ChatMessageActions } from \"../chat-message-actions/chat-message-actions\";\nimport { MessageRow, MessageBubble, MessageContainer } from \"./chat-message-styles\";\n\ninterface ChatMessageProps {\n message: ChatMessageType;\n}\n\nexport function ChatMessage({ message }: ChatMessageProps) {\n return (\n <MessageRow $role={message.role}>\n <MessageContainer $role={message.role}>\n <MessageBubble $role={message.role}>\n <ChatMessageContent content={message.content} />\n </MessageBubble>\n <ChatMessageActions\n messageId={message.id}\n content={message.content}\n role={message.role}\n isHelpful={message.isHelpful}\n />\n </MessageContainer>\n </MessageRow>\n );\n}\n"],"mappings":"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","names":["useCallback","__iconNode","__iconNode","__iconNode","styled","styled","jsx","useCallback","styled","styled","jsx","jsxs"]}
@@ -0,0 +1,19 @@
1
+ // src/utils/markdown-to-plain-text.ts
2
+ var PLACEHOLDER_PREFIX = "\u200B\u200BIC";
3
+ var PLACEHOLDER_SUFFIX = "\u200B\u200B";
4
+ var PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\d+)${PLACEHOLDER_SUFFIX}`, "g");
5
+ function markdownToPlainText(markdown) {
6
+ if (!markdown) return "";
7
+ const inlineCodeSnippets = [];
8
+ let result = markdown.replace(/```[\s\S]*?```/g, "").replace(/`([^`]+)`/g, (_match, code) => {
9
+ inlineCodeSnippets.push(code);
10
+ return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;
11
+ }).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();
12
+ result = result.replace(PLACEHOLDER_REGEX, (_match, index) => inlineCodeSnippets[Number(index)]);
13
+ return result;
14
+ }
15
+
16
+ export {
17
+ markdownToPlainText
18
+ };
19
+ //# sourceMappingURL=chunk-SMTOVZ3O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/markdown-to-plain-text.ts"],"sourcesContent":["const PLACEHOLDER_PREFIX = \"\\u200B\\u200BIC\";\nconst PLACEHOLDER_SUFFIX = \"\\u200B\\u200B\";\nconst PLACEHOLDER_REGEX = new RegExp(`${PLACEHOLDER_PREFIX}(\\\\d+)${PLACEHOLDER_SUFFIX}`, \"g\");\n\nexport function markdownToPlainText(markdown: string): string {\n if (!markdown) return \"\";\n\n // Protect inline code content from bold/italic stripping by replacing with placeholders\n const inlineCodeSnippets: string[] = [];\n let result = markdown\n // Code blocks (must come first)\n .replace(/```[\\s\\S]*?```/g, \"\")\n // Inline code → placeholder\n .replace(/`([^`]+)`/g, (_match, code: string) => {\n inlineCodeSnippets.push(code);\n return `${PLACEHOLDER_PREFIX}${inlineCodeSnippets.length - 1}${PLACEHOLDER_SUFFIX}`;\n })\n // Remove headings markers, keep text\n .replace(/^#{1,6}\\s+/gm, \"\")\n // Remove horizontal rules\n .replace(/^(?:---|\\*\\*\\*|___)\\s*$/gm, \"\")\n // Bold + italic\n .replace(/\\*{3}(.+?)\\*{3}/g, \"$1\")\n // Bold\n .replace(/\\*{2}(.+?)\\*{2}/g, \"$1\")\n .replace(/_{2}(.+?)_{2}/g, \"$1\")\n // Italic\n .replace(/\\*(.+?)\\*/g, \"$1\")\n .replace(/_(.+?)_/g, \"$1\")\n // Strikethrough\n .replace(/~~(.+?)~~/g, \"$1\")\n // Images: ![alt](url) → alt (must come before links)\n .replace(/!\\[([^\\]]*)\\]\\([^)]+\\)/g, \"$1\")\n // Links: [text](url) → text\n .replace(/\\[([^\\]]+)\\]\\([^)]+\\)/g, \"$1\")\n // Blockquote markers\n .replace(/^>\\s?/gm, \"\")\n // Table separator rows (|---|---|)\n .replace(/^\\|[-:\\s|]+\\|\\s*$/gm, \"\")\n // Table rows: | a | b | → a | b\n .replace(/^\\|\\s?/gm, \"\")\n .replace(/\\s?\\|$/gm, \"\")\n // Collapse multiple blank lines\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .trim();\n\n // Restore inline code content\n result = result.replace(PLACEHOLDER_REGEX, (_match, index: string) => inlineCodeSnippets[Number(index)]);\n\n return result;\n}\n"],"mappings":";AAAA,IAAM,qBAAqB;AAC3B,IAAM,qBAAqB;AAC3B,IAAM,oBAAoB,IAAI,OAAO,GAAG,kBAAkB,SAAS,kBAAkB,IAAI,GAAG;AAErF,SAAS,oBAAoB,UAA0B;AAC5D,MAAI,CAAC,SAAU,QAAO;AAGtB,QAAM,qBAA+B,CAAC;AACtC,MAAI,SAAS,SAEV,QAAQ,mBAAmB,EAAE,EAE7B,QAAQ,cAAc,CAAC,QAAQ,SAAiB;AAC/C,uBAAmB,KAAK,IAAI;AAC5B,WAAO,GAAG,kBAAkB,GAAG,mBAAmB,SAAS,CAAC,GAAG,kBAAkB;AAAA,EACnF,CAAC,EAEA,QAAQ,gBAAgB,EAAE,EAE1B,QAAQ,6BAA6B,EAAE,EAEvC,QAAQ,oBAAoB,IAAI,EAEhC,QAAQ,oBAAoB,IAAI,EAChC,QAAQ,kBAAkB,IAAI,EAE9B,QAAQ,cAAc,IAAI,EAC1B,QAAQ,YAAY,IAAI,EAExB,QAAQ,cAAc,IAAI,EAE1B,QAAQ,2BAA2B,IAAI,EAEvC,QAAQ,0BAA0B,IAAI,EAEtC,QAAQ,WAAW,EAAE,EAErB,QAAQ,uBAAuB,EAAE,EAEjC,QAAQ,YAAY,EAAE,EACtB,QAAQ,YAAY,EAAE,EAEtB,QAAQ,WAAW,MAAM,EACzB,KAAK;AAGR,WAAS,OAAO,QAAQ,mBAAmB,CAAC,QAAQ,UAAkB,mBAAmB,OAAO,KAAK,CAAC,CAAC;AAEvG,SAAO;AACT;","names":[]}
@@ -16,6 +16,7 @@ var typographyTypes = {
16
16
  GEIST_BODY_S_REGULAR: "GEIST_BODY_S_REGULAR",
17
17
  GEIST_BODY_S_MEDIUM: "GEIST_BODY_S_MEDIUM",
18
18
  GEIST_BODY_S_SEMI_BOLD: "GEIST_BODY_S_SEMI_BOLD",
19
+ GEIST_BODY_S_BOLD: "GEIST_BODY_S_BOLD",
19
20
  // Geist Body Medium (18px)
20
21
  GEIST_BODY_M_LIGHT: "GEIST_BODY_M_LIGHT",
21
22
  GEIST_BODY_M_REGULAR: "GEIST_BODY_M_REGULAR",
@@ -109,6 +110,13 @@ var typographyStyles = {
109
110
  lineHeight: 24,
110
111
  letterSpacing: -0.08
111
112
  },
113
+ [typographyTypes.GEIST_BODY_S_BOLD]: {
114
+ fontFamily: fontFamilies.GEIST,
115
+ fontSize: 16,
116
+ fontWeight: 700,
117
+ lineHeight: 24,
118
+ letterSpacing: -0.08
119
+ },
112
120
  // Geist Body Medium (18px)
113
121
  [typographyTypes.GEIST_BODY_M_LIGHT]: {
114
122
  fontFamily: fontFamilies.GEIST,
@@ -289,4 +297,4 @@ export {
289
297
  typographyStyles,
290
298
  typographyMixin
291
299
  };
292
- //# sourceMappingURL=chunk-A6DKIFWS.js.map
300
+ //# sourceMappingURL=chunk-WQ2QTUYA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tokens/typography.ts"],"sourcesContent":["export const fontFamilies = {\n GEIST: \"Geist\",\n CRIMSON_PRO: \"Crimson Pro\",\n} as const;\n\nexport const typographyTypes = {\n // Geist Label Caption (12px)\n GEIST_LABEL_CAPTION_REGULAR: \"GEIST_LABEL_CAPTION_REGULAR\",\n GEIST_LABEL_CAPTION_MEDIUM: \"GEIST_LABEL_CAPTION_MEDIUM\",\n GEIST_LABEL_CAPTION_SEMI_BOLD: \"GEIST_LABEL_CAPTION_SEMI_BOLD\",\n\n // Geist Body Extra Small (14px)\n GEIST_BODY_XS_REGULAR: \"GEIST_BODY_XS_REGULAR\",\n GEIST_BODY_XS_MEDIUM: \"GEIST_BODY_XS_MEDIUM\",\n GEIST_BODY_XS_BOLD: \"GEIST_BODY_XS_BOLD\",\n\n // Geist Body Small (16px)\n GEIST_BODY_S_REGULAR: \"GEIST_BODY_S_REGULAR\",\n GEIST_BODY_S_MEDIUM: \"GEIST_BODY_S_MEDIUM\",\n GEIST_BODY_S_SEMI_BOLD: \"GEIST_BODY_S_SEMI_BOLD\",\n GEIST_BODY_S_BOLD: \"GEIST_BODY_S_BOLD\",\n\n // Geist Body Medium (18px)\n GEIST_BODY_M_LIGHT: \"GEIST_BODY_M_LIGHT\",\n GEIST_BODY_M_REGULAR: \"GEIST_BODY_M_REGULAR\",\n GEIST_BODY_M_MEDIUM: \"GEIST_BODY_M_MEDIUM\",\n GEIST_BODY_M_SEMI_BOLD: \"GEIST_BODY_M_SEMI_BOLD\",\n\n // Geist Body Large (20px)\n GEIST_BODY_L_REGULAR: \"GEIST_BODY_L_REGULAR\",\n GEIST_BODY_L_MEDIUM: \"GEIST_BODY_L_MEDIUM\",\n GEIST_BODY_L_SEMI_BOLD: \"GEIST_BODY_L_SEMI_BOLD\",\n GEIST_BODY_L_BOLD: \"GEIST_BODY_L_BOLD\",\n\n // Geist Heading Small (24px)\n GEIST_HEADING_S_REGULAR: \"GEIST_HEADING_S_REGULAR\",\n GEIST_HEADING_S_MEDIUM: \"GEIST_HEADING_S_MEDIUM\",\n GEIST_HEADING_S_BOLD: \"GEIST_HEADING_S_BOLD\",\n\n // Geist Heading Medium (28px)\n GEIST_HEADING_M_BOLD: \"GEIST_HEADING_M_BOLD\",\n\n // Geist Heading Large (32px)\n GEIST_HEADING_L_REGULAR: \"GEIST_HEADING_L_REGULAR\",\n GEIST_HEADING_L_MEDIUM: \"GEIST_HEADING_L_MEDIUM\",\n GEIST_HEADING_L_SEMI_BOLD: \"GEIST_HEADING_L_SEMI_BOLD\",\n GEIST_HEADING_L_BOLD: \"GEIST_HEADING_L_BOLD\",\n\n // Geist Display Large (36px)\n GEIST_DISPLAY_L_MEDIUM: \"GEIST_DISPLAY_L_MEDIUM\",\n\n // Crimson Pro Body Small (16px)\n CRIMSON_PRO_BODY_S_LIGHT: \"CRIMSON_PRO_BODY_S_LIGHT\",\n\n // Crimson Pro Body Medium (18px)\n CRIMSON_PRO_BODY_M_LIGHT: \"CRIMSON_PRO_BODY_M_LIGHT\",\n\n // Crimson Pro Heading Medium (24px)\n CRIMSON_PRO_HEADING_M_MEDIUM: \"CRIMSON_PRO_HEADING_M_MEDIUM\",\n\n // Crimson Pro Display Extra Large (46px)\n CRIMSON_PRO_DISPLAY_XL_REGULAR: \"CRIMSON_PRO_DISPLAY_XL_REGULAR\",\n} as const;\n\nexport type TypographyType = (typeof typographyTypes)[keyof typeof typographyTypes];\n\nexport interface TypographyStyle {\n fontFamily: string;\n fontSize: number;\n fontWeight: number;\n lineHeight: number;\n letterSpacing?: number;\n fontStyle?: string;\n}\n\nexport const typographyStyles: Record<TypographyType, TypographyStyle> = {\n // Geist Label Caption (12px)\n [typographyTypes.GEIST_LABEL_CAPTION_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 12,\n fontWeight: 400,\n lineHeight: 16,\n },\n [typographyTypes.GEIST_LABEL_CAPTION_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 12,\n fontWeight: 500,\n lineHeight: 16,\n },\n [typographyTypes.GEIST_LABEL_CAPTION_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 12,\n fontWeight: 600,\n lineHeight: 16,\n },\n\n // Geist Body Extra Small (14px)\n [typographyTypes.GEIST_BODY_XS_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 14,\n fontWeight: 400,\n lineHeight: 20,\n },\n [typographyTypes.GEIST_BODY_XS_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 14,\n fontWeight: 500,\n lineHeight: 20,\n },\n [typographyTypes.GEIST_BODY_XS_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 14,\n fontWeight: 600,\n lineHeight: 20,\n },\n\n // Geist Body Small (16px)\n [typographyTypes.GEIST_BODY_S_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 16,\n fontWeight: 400,\n lineHeight: 24,\n letterSpacing: -0.08,\n },\n [typographyTypes.GEIST_BODY_S_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 16,\n fontWeight: 500,\n lineHeight: 24,\n letterSpacing: -0.08,\n },\n [typographyTypes.GEIST_BODY_S_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 16,\n fontWeight: 600,\n lineHeight: 24,\n letterSpacing: -0.08,\n },\n [typographyTypes.GEIST_BODY_S_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 16,\n fontWeight: 700,\n lineHeight: 24,\n letterSpacing: -0.08,\n },\n\n // Geist Body Medium (18px)\n [typographyTypes.GEIST_BODY_M_LIGHT]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 18,\n fontWeight: 300,\n lineHeight: 28,\n letterSpacing: -0.09,\n },\n [typographyTypes.GEIST_BODY_M_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 18,\n fontWeight: 400,\n lineHeight: 28,\n letterSpacing: -0.09,\n },\n [typographyTypes.GEIST_BODY_M_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 18,\n fontWeight: 500,\n lineHeight: 28,\n letterSpacing: -0.09,\n },\n [typographyTypes.GEIST_BODY_M_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 18,\n fontWeight: 600,\n lineHeight: 28,\n letterSpacing: -0.09,\n },\n\n // Geist Body Large (20px)\n [typographyTypes.GEIST_BODY_L_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 20,\n fontWeight: 400,\n lineHeight: 30,\n letterSpacing: -0.2,\n },\n [typographyTypes.GEIST_BODY_L_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 20,\n fontWeight: 500,\n lineHeight: 30,\n letterSpacing: -0.2,\n },\n [typographyTypes.GEIST_BODY_L_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 20,\n fontWeight: 600,\n lineHeight: 30,\n letterSpacing: -0.2,\n },\n [typographyTypes.GEIST_BODY_L_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 20,\n fontWeight: 700,\n lineHeight: 30,\n letterSpacing: -0.2,\n },\n\n // Geist Heading Small (24px)\n [typographyTypes.GEIST_HEADING_S_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 24,\n fontWeight: 400,\n lineHeight: 32,\n letterSpacing: -0.48,\n },\n [typographyTypes.GEIST_HEADING_S_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 24,\n fontWeight: 500,\n lineHeight: 32,\n letterSpacing: -0.48,\n },\n [typographyTypes.GEIST_HEADING_S_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 24,\n fontWeight: 700,\n lineHeight: 32,\n letterSpacing: -0.48,\n },\n\n // Geist Heading Medium (28px)\n [typographyTypes.GEIST_HEADING_M_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 28,\n fontWeight: 700,\n lineHeight: 36,\n letterSpacing: -0.6,\n },\n\n // Geist Heading Large (32px)\n [typographyTypes.GEIST_HEADING_L_REGULAR]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 32,\n fontWeight: 400,\n lineHeight: 40,\n letterSpacing: -0.64,\n },\n [typographyTypes.GEIST_HEADING_L_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 32,\n fontWeight: 500,\n lineHeight: 40,\n letterSpacing: -0.64,\n },\n [typographyTypes.GEIST_HEADING_L_SEMI_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 32,\n fontWeight: 600,\n lineHeight: 40,\n letterSpacing: -0.64,\n },\n [typographyTypes.GEIST_HEADING_L_BOLD]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 32,\n fontWeight: 700,\n lineHeight: 40,\n letterSpacing: -0.64,\n },\n\n // Geist Display Large (36px)\n [typographyTypes.GEIST_DISPLAY_L_MEDIUM]: {\n fontFamily: fontFamilies.GEIST,\n fontSize: 36,\n fontWeight: 500,\n lineHeight: 44,\n letterSpacing: -0.72,\n },\n\n // Crimson Pro Body Small (16px)\n [typographyTypes.CRIMSON_PRO_BODY_S_LIGHT]: {\n fontFamily: fontFamilies.CRIMSON_PRO,\n fontSize: 16,\n fontWeight: 300,\n lineHeight: 20,\n letterSpacing: -0.32,\n fontStyle: \"italic\",\n },\n\n // Crimson Pro Body Medium (18px)\n [typographyTypes.CRIMSON_PRO_BODY_M_LIGHT]: {\n fontFamily: fontFamilies.CRIMSON_PRO,\n fontSize: 18,\n fontWeight: 300,\n lineHeight: 28,\n letterSpacing: 0,\n fontStyle: \"italic\",\n },\n\n // Crimson Pro Heading Medium (24px)\n [typographyTypes.CRIMSON_PRO_HEADING_M_MEDIUM]: {\n fontFamily: fontFamilies.CRIMSON_PRO,\n fontSize: 24,\n fontWeight: 400,\n lineHeight: 32,\n letterSpacing: -0.48,\n fontStyle: \"italic\",\n },\n\n // Crimson Pro Display Extra Large (46px)\n [typographyTypes.CRIMSON_PRO_DISPLAY_XL_REGULAR]: {\n fontFamily: fontFamilies.CRIMSON_PRO,\n fontSize: 46,\n fontWeight: 400,\n lineHeight: 54,\n letterSpacing: -1.38,\n fontStyle: \"italic\",\n },\n};\n\nexport function typographyMixin(type: TypographyType): string {\n const style = typographyStyles[type];\n return [\n `font-family: \"${style.fontFamily}\", sans-serif`,\n `font-size: ${style.fontSize}px`,\n `font-weight: ${style.fontWeight}`,\n `line-height: ${style.lineHeight}px`,\n `letter-spacing: ${style.letterSpacing != null ? `${style.letterSpacing}px` : \"inherit\"}`,\n `font-style: ${style.fontStyle ?? \"normal\"}`,\n ].join(\";\\n \");\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,77 @@
1
+ import {
2
+ Icon
3
+ } from "./chunk-OLJIJYB5.js";
4
+ import {
5
+ colors
6
+ } from "./chunk-JF3P66JF.js";
7
+
8
+ // src/components/keyboard-shortcut/keyboard-shortcut-styles.ts
9
+ import styled, { css } from "styled-components";
10
+
11
+ // src/components/keyboard-shortcut/types.ts
12
+ var KEYBOARD_SHORTCUT_VARIANTS = {
13
+ OUTLINED: "outlined",
14
+ FILLED: "filled"
15
+ };
16
+
17
+ // src/components/keyboard-shortcut/keyboard-shortcut-styles.ts
18
+ var variantStyles = {
19
+ [KEYBOARD_SHORTCUT_VARIANTS.OUTLINED]: css`
20
+ border: 1px solid ${colors["white-alpha-40"]};
21
+ color: ${colors["brown-10"]};
22
+ `,
23
+ [KEYBOARD_SHORTCUT_VARIANTS.FILLED]: css`
24
+ background: ${colors["brown-80"]};
25
+ color: ${colors["brown-10"]};
26
+ `
27
+ };
28
+ var Wrapper = styled.div`
29
+ display: inline-flex;
30
+ align-items: center;
31
+ gap: 2px;
32
+ `;
33
+ var Key = styled.kbd`
34
+ display: inline-flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ padding: 2px;
38
+ border-radius: 6px;
39
+ ${({ $variant }) => variantStyles[$variant]};
40
+ `;
41
+
42
+ // src/components/keyboard-shortcut/keyboard-shortcut.tsx
43
+ import { jsx } from "react/jsx-runtime";
44
+ function KeyboardShortcut({
45
+ keys,
46
+ variant = KEYBOARD_SHORTCUT_VARIANTS.OUTLINED,
47
+ className
48
+ }) {
49
+ return /* @__PURE__ */ jsx(Wrapper, { className, children: keys.map((KeyComponent, index) => /* @__PURE__ */ jsx(Key, { $variant: variant, children: /* @__PURE__ */ jsx(Icon, { icon: KeyComponent, size: 12 }) }, index)) });
50
+ }
51
+
52
+ // src/components/keyboard-shortcut/icons/icon-ctrl.tsx
53
+ import { jsx as jsx2 } from "react/jsx-runtime";
54
+ function IconCtrl(props) {
55
+ const { width = 24, height = 24, ...rest } = props;
56
+ return /* @__PURE__ */ jsx2("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", width, height, fill: "none", ...rest, children: /* @__PURE__ */ jsx2(
57
+ "text",
58
+ {
59
+ x: "50%",
60
+ y: "50%",
61
+ dominantBaseline: "central",
62
+ textAnchor: "middle",
63
+ fill: "currentColor",
64
+ fontFamily: "Geist, sans-serif",
65
+ fontWeight: 300,
66
+ fontSize: 14,
67
+ children: "Ctrl"
68
+ }
69
+ ) });
70
+ }
71
+
72
+ export {
73
+ KEYBOARD_SHORTCUT_VARIANTS,
74
+ KeyboardShortcut,
75
+ IconCtrl
76
+ };
77
+ //# sourceMappingURL=chunk-WZHNMC6P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/keyboard-shortcut/keyboard-shortcut-styles.ts","../src/components/keyboard-shortcut/types.ts","../src/components/keyboard-shortcut/keyboard-shortcut.tsx","../src/components/keyboard-shortcut/icons/icon-ctrl.tsx"],"sourcesContent":["import styled, { css } from \"styled-components\";\n\nimport { colors } from \"../../tokens/colors\";\nimport { KEYBOARD_SHORTCUT_VARIANTS } from \"./types\";\nimport type { KeyboardShortcutVariant } from \"./types\";\n\nconst variantStyles: Record<KeyboardShortcutVariant, ReturnType<typeof css>> = {\n [KEYBOARD_SHORTCUT_VARIANTS.OUTLINED]: css`\n border: 1px solid ${colors[\"white-alpha-40\"]};\n color: ${colors[\"brown-10\"]};\n `,\n [KEYBOARD_SHORTCUT_VARIANTS.FILLED]: css`\n background: ${colors[\"brown-80\"]};\n color: ${colors[\"brown-10\"]};\n `,\n};\n\nexport const Wrapper = styled.div`\n display: inline-flex;\n align-items: center;\n gap: 2px;\n`;\n\nexport const Key = styled.kbd<{ $variant: KeyboardShortcutVariant }>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 2px;\n border-radius: 6px;\n ${({ $variant }) => variantStyles[$variant]};\n`;\n","import type { ComponentType, SVGProps } from \"react\";\n\nexport type KeyIcon = ComponentType<SVGProps<SVGSVGElement>>;\n\nexport const KEYBOARD_SHORTCUT_VARIANTS = {\n OUTLINED: \"outlined\",\n FILLED: \"filled\",\n} as const;\n\nexport type KeyboardShortcutVariant = (typeof KEYBOARD_SHORTCUT_VARIANTS)[keyof typeof KEYBOARD_SHORTCUT_VARIANTS];\n\nexport interface KeyboardShortcutProps {\n keys: KeyIcon[];\n variant?: KeyboardShortcutVariant;\n className?: string;\n}\n","import type { ReactElement } from \"react\";\n\nimport { Icon } from \"../icon/icon\";\nimport { Key, Wrapper } from \"./keyboard-shortcut-styles\";\nimport { KEYBOARD_SHORTCUT_VARIANTS } from \"./types\";\nimport type { KeyboardShortcutProps } from \"./types\";\n\nexport function KeyboardShortcut({\n keys,\n variant = KEYBOARD_SHORTCUT_VARIANTS.OUTLINED,\n className,\n}: KeyboardShortcutProps): ReactElement {\n return (\n <Wrapper className={className}>\n {keys.map((KeyComponent, index) => (\n <Key key={index} $variant={variant}>\n <Icon icon={KeyComponent} size={12} />\n </Key>\n ))}\n </Wrapper>\n );\n}\n","import type { ReactElement, SVGProps } from \"react\";\n\nexport function IconCtrl(props: SVGProps<SVGSVGElement>): ReactElement {\n const { width = 24, height = 24, ...rest } = props;\n\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width={width} height={height} fill=\"none\" {...rest}>\n <text\n x=\"50%\"\n y=\"50%\"\n dominantBaseline=\"central\"\n textAnchor=\"middle\"\n fill=\"currentColor\"\n fontFamily=\"Geist, sans-serif\"\n fontWeight={300}\n fontSize={14}\n >\n Ctrl\n </text>\n </svg>\n );\n}\n"],"mappings":";;;;;;;;AAAA,OAAO,UAAU,WAAW;;;ACIrB,IAAM,6BAA6B;AAAA,EACxC,UAAU;AAAA,EACV,QAAQ;AACV;;;ADDA,IAAM,gBAAyE;AAAA,EAC7E,CAAC,2BAA2B,QAAQ,GAAG;AAAA,wBACjB,OAAO,gBAAgB,CAAC;AAAA,aACnC,OAAO,UAAU,CAAC;AAAA;AAAA,EAE7B,CAAC,2BAA2B,MAAM,GAAG;AAAA,kBACrB,OAAO,UAAU,CAAC;AAAA,aACvB,OAAO,UAAU,CAAC;AAAA;AAE/B;AAEO,IAAM,UAAU,OAAO;AAAA;AAAA;AAAA;AAAA;AAMvB,IAAM,MAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMtB,CAAC,EAAE,SAAS,MAAM,cAAc,QAAQ,CAAC;AAAA;;;AEbnC;AATH,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA,UAAU,2BAA2B;AAAA,EACrC;AACF,GAAwC;AACtC,SACE,oBAAC,WAAQ,WACN,eAAK,IAAI,CAAC,cAAc,UACvB,oBAAC,OAAgB,UAAU,SACzB,8BAAC,QAAK,MAAM,cAAc,MAAM,IAAI,KAD5B,KAEV,CACD,GACH;AAEJ;;;ACdM,gBAAAA,YAAA;AALC,SAAS,SAAS,OAA8C;AACrE,QAAM,EAAE,QAAQ,IAAI,SAAS,IAAI,GAAG,KAAK,IAAI;AAE7C,SACE,gBAAAA,KAAC,SAAI,OAAM,8BAA6B,SAAQ,aAAY,OAAc,QAAgB,MAAK,QAAQ,GAAG,MACxG,0BAAAA;AAAA,IAAC;AAAA;AAAA,MACC,GAAE;AAAA,MACF,GAAE;AAAA,MACF,kBAAiB;AAAA,MACjB,YAAW;AAAA,MACX,MAAK;AAAA,MACL,YAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACX;AAAA;AAAA,EAED,GACF;AAEJ;","names":["jsx"]}