@tangle-network/ui 11.10.0 → 11.11.1

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 (132) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +4 -1
  3. package/dist/active-sessions-store-Gt1R0rFG.js +262 -0
  4. package/dist/{active-sessions-store-CeOmXgv5.d.ts → active-sessions-store-nl70ZnMC.d.ts} +40 -41
  5. package/dist/artifact-pane-BL_DFWNl.d.ts +32 -0
  6. package/dist/artifact-pane-DMXT9a8U.js +70 -0
  7. package/dist/auth-DOETfnd9.js +154 -0
  8. package/dist/auth.d.ts +2 -74
  9. package/dist/auth.js +2 -16
  10. package/dist/branding-26d5ARIr.d.ts +14 -0
  11. package/dist/button-C87nEe2R.js +78 -0
  12. package/dist/button-yoIv77e2.d.ts +16 -0
  13. package/dist/chat-D4jAfEmj.js +667 -0
  14. package/dist/chat.d.ts +2 -201
  15. package/dist/chat.js +2 -31
  16. package/dist/code-block-B36KVUSN.js +165 -0
  17. package/dist/code-block-B9miUPht.d.ts +23 -0
  18. package/dist/diff-preview-BcK3nRXb.js +533 -0
  19. package/dist/document-editor-pane-BcoABlhn.d.ts +131 -0
  20. package/dist/document-editor-pane-BxlPjaTP.js +1287 -0
  21. package/dist/dropdown-menu-BpcLa5vF.js +101 -0
  22. package/dist/editor.d.ts +76 -78
  23. package/dist/editor.js +2 -34
  24. package/dist/file-format-BgXbr-Ib.js +160 -0
  25. package/dist/files-Bug33qCl.js +743 -0
  26. package/dist/files.d.ts +2 -243
  27. package/dist/files.js +3 -41
  28. package/dist/focus-BcE_SHqz.js +57 -0
  29. package/dist/format-DfcLWqMa.js +54 -0
  30. package/dist/hooks.d.ts +30 -37
  31. package/dist/hooks.js +111 -46
  32. package/dist/index-2UntyjBb.d.ts +52 -0
  33. package/dist/index-BgUHilZm.d.ts +108 -0
  34. package/dist/index-COgqsFAQ.d.ts +42 -0
  35. package/dist/index-CPDET_s1.d.ts +549 -0
  36. package/dist/index-CUhfHT_V.d.ts +204 -0
  37. package/dist/index-Cg6gYAqh.d.ts +73 -0
  38. package/dist/index-Cq-EJzqW.d.ts +16 -0
  39. package/dist/index-DhYmSaLF.d.ts +245 -0
  40. package/dist/index-DjKxO357.d.ts +128 -0
  41. package/dist/index.d.ts +26 -43
  42. package/dist/index.js +35 -472
  43. package/dist/markdown-BGqicV82.js +45 -0
  44. package/dist/markdown.d.ts +3 -18
  45. package/dist/markdown.js +3 -15
  46. package/dist/message-vhUI0c5G.d.ts +16 -0
  47. package/dist/nav.d.ts +6 -8
  48. package/dist/nav.js +29 -11
  49. package/dist/openui-artifact-renderer-D3E5bIAI.d.ts +114 -0
  50. package/dist/openui-artifact-renderer-DrU1AdVk.js +266 -0
  51. package/dist/openui.d.ts +2 -115
  52. package/dist/openui.js +2 -13
  53. package/dist/parts-5mhy9yJ3.d.ts +37 -0
  54. package/dist/primitives-Cb8GGVKr.js +1239 -0
  55. package/dist/primitives.d.ts +5 -525
  56. package/dist/primitives.js +9 -212
  57. package/dist/redaction-CGGB2ENG.js +74 -0
  58. package/dist/redaction.d.ts +2 -42
  59. package/dist/redaction.js +2 -7
  60. package/dist/run-OyWmIDqu.d.ts +41 -0
  61. package/dist/run-ZsIKPA6J.js +17 -0
  62. package/dist/run-group-BACLbCFl.js +410 -0
  63. package/dist/run.d.ts +3 -126
  64. package/dist/run.js +5 -40
  65. package/dist/sdk-hooks.d.ts +2 -285
  66. package/dist/sdk-hooks.js +3 -36
  67. package/dist/stores.d.ts +13 -14
  68. package/dist/stores.js +34 -76
  69. package/dist/table-Bss73DhB.js +146 -0
  70. package/dist/tabs-BVHR6NkO.js +40 -0
  71. package/dist/text-shimmer-BUUo6I-g.js +64 -0
  72. package/dist/tool-call-feed-BeB1_4pX.d.ts +47 -0
  73. package/dist/tool-call-feed-Djt2q11V.js +109 -0
  74. package/dist/tool-call-step-DNebqhmX.js +434 -0
  75. package/dist/tool-display-BAuAVa43.js +158 -0
  76. package/dist/{tool-display-z4JcDmMQ.d.ts → tool-display-DgmL5rIU.d.ts} +16 -16
  77. package/dist/tool-previews.d.ts +2 -48
  78. package/dist/tool-previews.js +2 -23
  79. package/dist/types.d.ts +6 -19
  80. package/dist/types.js +0 -1
  81. package/dist/use-auto-scroll-C5Pjeqon.js +153 -0
  82. package/dist/use-sse-stream-BVgO1QBN.js +884 -0
  83. package/dist/use-sse-stream-Dm6R5YWz.d.ts +282 -0
  84. package/dist/utils-Bl_CZ0Qp.js +37 -0
  85. package/dist/{chunk-RQHJBTEU.js → utils-C_uf36nf.js} +4 -6
  86. package/dist/utils.d.ts +2 -104
  87. package/dist/utils.js +6 -44
  88. package/package.json +39 -41
  89. package/src/lib/focus.ts +2 -1
  90. package/dist/artifact-pane-DpuWcAiF.d.ts +0 -33
  91. package/dist/button-CMQuQEW_.d.ts +0 -17
  92. package/dist/chunk-34A66VBG.js +0 -214
  93. package/dist/chunk-3OI2QKFD.js +0 -0
  94. package/dist/chunk-3XXBZL53.js +0 -174
  95. package/dist/chunk-42PAH5D2.js +0 -112
  96. package/dist/chunk-4CLN43XT.js +0 -45
  97. package/dist/chunk-55WHV7SS.js +0 -1604
  98. package/dist/chunk-565EATZZ.js +0 -156
  99. package/dist/chunk-5Z5ZYMOJ.js +0 -0
  100. package/dist/chunk-6BGQA4BQ.js +0 -0
  101. package/dist/chunk-BEBXZPHW.js +0 -299
  102. package/dist/chunk-C5WF4WMV.js +0 -734
  103. package/dist/chunk-HFL6R6IF.js +0 -37
  104. package/dist/chunk-HGML45QH.js +0 -104
  105. package/dist/chunk-HMAPIH7L.js +0 -595
  106. package/dist/chunk-K5XFRUS4.js +0 -1401
  107. package/dist/chunk-KFQGHD73.js +0 -198
  108. package/dist/chunk-L57WRIND.js +0 -59
  109. package/dist/chunk-LTEKI7YJ.js +0 -59
  110. package/dist/chunk-M3QZK62R.js +0 -233
  111. package/dist/chunk-ND3ZFXQK.js +0 -179
  112. package/dist/chunk-OEX7NZE3.js +0 -321
  113. package/dist/chunk-OL5GYLHV.js +0 -60
  114. package/dist/chunk-QGFYBNSO.js +0 -133
  115. package/dist/chunk-R7B3UWPF.js +0 -550
  116. package/dist/chunk-R7SUY4E3.js +0 -65
  117. package/dist/chunk-REJESC5U.js +0 -117
  118. package/dist/chunk-RQGKSCEZ.js +0 -0
  119. package/dist/chunk-SNLR2AEA.js +0 -40
  120. package/dist/chunk-WKWBTL2V.js +0 -15
  121. package/dist/chunk-X7CU776B.js +0 -1048
  122. package/dist/chunk-XU3HB5QL.js +0 -127
  123. package/dist/chunk-YTO5V6QS.js +0 -19
  124. package/dist/chunk-YU4E5J2N.js +0 -437
  125. package/dist/chunk-YZ6AK25N.js +0 -886
  126. package/dist/code-block-0kSpWMnf.d.ts +0 -25
  127. package/dist/document-editor-pane-IAEQn_Dl.d.ts +0 -128
  128. package/dist/document-editor-pane-QHDOBA43.js +0 -13
  129. package/dist/message-BHWbxBtT.d.ts +0 -15
  130. package/dist/parts-dj7AcUg0.d.ts +0 -36
  131. package/dist/run-PfLmDAox.d.ts +0 -41
  132. package/dist/tool-call-feed-D9iofJgW.d.ts +0 -46
package/dist/chat.d.ts CHANGED
@@ -1,201 +1,2 @@
1
- import * as React from 'react';
2
- import { ReactNode } from 'react';
3
- import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { S as SessionMessage } from './message-BHWbxBtT.js';
5
- import { S as SessionPart, a as ToolPart } from './parts-dj7AcUg0.js';
6
- import { AgentBranding } from './types.js';
7
- import { C as CustomToolRenderer } from './tool-display-z4JcDmMQ.js';
8
- import { R as Run, G as GroupedMessage } from './run-PfLmDAox.js';
9
- import { OpenUIAction } from './openui.js';
10
- import { T as ToolCallData } from './tool-call-feed-D9iofJgW.js';
11
-
12
- /**
13
- * Transcript-only container: message list + auto-scroll. Composers are
14
- * composed BELOW this by the app (the canonical one is `AgentComposer` in
15
- * `@tangle-network/sandbox-ui`) — this component never renders an input.
16
- */
17
- interface ChatContainerProps {
18
- messages: SessionMessage[];
19
- partMap: Record<string, SessionPart[]>;
20
- isStreaming: boolean;
21
- branding?: AgentBranding;
22
- className?: string;
23
- /** Custom renderer for tool details. Return ReactNode to override, null to use default. */
24
- renderToolDetail?: CustomToolRenderer;
25
- /** Presentation mode for the session view. */
26
- presentation?: "runs" | "timeline";
27
- /** Callback when an OpenUI action button is pressed within inline OpenUI blocks. */
28
- onOpenUIAction?: (action: OpenUIAction) => void;
29
- /** Enable rendering OpenUI schemas inline in the chat timeline. Defaults to true. */
30
- enableOpenUI?: boolean;
31
- /** Optional actions rendered beside each grouped assistant run. */
32
- renderRunActions?: (run: Run) => ReactNode;
33
- /** Optional actions rendered below each user message bubble. */
34
- renderUserMessageActions?: (message: SessionMessage, parts: SessionPart[]) => ReactNode;
35
- /** Optional actions rendered beside individual tool items in the run-grouped
36
- * (`runs`) presentation. */
37
- renderToolActions?: (part: ToolPart, options: {
38
- run: Run;
39
- messageId: string;
40
- partIndex: number;
41
- }) => ReactNode;
42
- /** Optional actions rendered beside individual tool items in the `timeline`
43
- * presentation, which has no run/message grouping (hence part-only). */
44
- renderTimelineToolActions?: (part: ToolPart) => ReactNode;
45
- /** In the `timeline` presentation, collapse to the first N spine rows behind
46
- * a "Show N more steps" toggle. Omit to always show every row. */
47
- collapseTimelineAfter?: number;
48
- }
49
- /**
50
- * Chat transcript container: message list + auto-scroll.
51
- * Orchestrates useRunGroups, useRunCollapseState, and useAutoScroll.
52
- */
53
- declare const ChatContainer: React.MemoExoticComponent<({ messages, partMap, isStreaming, branding, className, renderToolDetail, presentation, onOpenUIAction, enableOpenUI, renderRunActions, renderUserMessageActions, renderToolActions, renderTimelineToolActions, collapseTimelineAfter, }: ChatContainerProps) => react_jsx_runtime.JSX.Element>;
54
-
55
- interface MessageListProps {
56
- groups: GroupedMessage[];
57
- partMap: Record<string, SessionPart[]>;
58
- isCollapsed: (runId: string) => boolean;
59
- onToggleCollapse: (runId: string) => void;
60
- branding?: AgentBranding;
61
- renderToolDetail?: CustomToolRenderer;
62
- renderRunActions?: (group: Extract<GroupedMessage, {
63
- type: "run";
64
- }>["run"]) => ReactNode;
65
- renderUserMessageActions?: (message: SessionMessage, parts: SessionPart[]) => ReactNode;
66
- renderToolActions?: (part: ToolPart, options: {
67
- run: Extract<GroupedMessage, {
68
- type: "run";
69
- }>["run"];
70
- messageId: string;
71
- partIndex: number;
72
- }) => ReactNode;
73
- }
74
- /**
75
- * Maps GroupedMessage[] to UserMessage and RunGroup components.
76
- * This is the main render list for the chat view.
77
- */
78
- declare const MessageList: React.MemoExoticComponent<({ groups, partMap, isCollapsed, onToggleCollapse, branding, renderToolDetail, renderRunActions, renderUserMessageActions, renderToolActions, }: MessageListProps) => react_jsx_runtime.JSX.Element>;
79
-
80
- interface UserMessageProps {
81
- /** Session-model input: text is derived from these parts. */
82
- message?: SessionMessage;
83
- parts?: SessionPart[];
84
- /** Direct-content input (e.g. AgentTimeline): explicit text + timestamp. */
85
- content?: string;
86
- timestamp?: Date;
87
- actions?: ReactNode;
88
- }
89
- /**
90
- * The single user message bubble — a quiet, right-aligned fill on the muted
91
- * surface (no border, no loud fill, no uppercase label). The timestamp sits
92
- * beside the bubble and appears on hover, so it costs no height. Used by both
93
- * the run/message list (session-model `parts`) and AgentTimeline (direct
94
- * `content`/`timestamp`).
95
- */
96
- declare const UserMessage: React.MemoExoticComponent<({ message: _message, parts, content, timestamp, actions }: UserMessageProps) => react_jsx_runtime.JSX.Element | null>;
97
-
98
- type MessageRole = "user" | "assistant" | "system";
99
- interface ChatMessageProps {
100
- role: MessageRole;
101
- content: string;
102
- /** Inline tool call activity rendered between text chunks */
103
- toolCalls?: ReactNode;
104
- /** Whether the message is still streaming */
105
- isStreaming?: boolean;
106
- /** Timestamp */
107
- timestamp?: Date;
108
- className?: string;
109
- /** Custom user label. Default: "You" */
110
- userLabel?: string;
111
- /** Custom assistant label. Default: "Agent" */
112
- assistantLabel?: string;
113
- /** Hide the role label row entirely */
114
- hideRoleLabel?: boolean;
115
- }
116
- declare function ChatMessage({ role, content, toolCalls, isStreaming, timestamp, className, userLabel, assistantLabel, hideRoleLabel, }: ChatMessageProps): react_jsx_runtime.JSX.Element;
117
-
118
- interface ThinkingIndicatorProps {
119
- className?: string;
120
- }
121
- declare function ThinkingIndicator({ className }: ThinkingIndicatorProps): react_jsx_runtime.JSX.Element;
122
-
123
- type AgentTimelineTone = "default" | "info" | "success" | "warning" | "error";
124
- interface AgentTimelineMessageItem {
125
- id: string;
126
- kind: "message";
127
- role: MessageRole;
128
- content: string;
129
- toolCalls?: ReactNode;
130
- isStreaming?: boolean;
131
- /** Shown beside a user bubble on hover. Assistant prose carries no
132
- * timestamp of its own — the turn's user message dates the exchange. */
133
- timestamp?: Date;
134
- after?: ReactNode;
135
- }
136
- interface AgentTimelineToolItem {
137
- id: string;
138
- kind: "tool";
139
- call: ToolCallData;
140
- /** Source tool part, so a consumer's `renderToolActions` gets the real
141
- * input/output (the flat `call` is display-only). */
142
- part?: ToolPart;
143
- }
144
- interface AgentTimelineToolGroupItem {
145
- id: string;
146
- kind: "tool_group";
147
- /** Accessible name of the group. Not drawn — the rows are the label. */
148
- title?: string;
149
- calls: ToolCallData[];
150
- /** Source tool parts, parallel to `calls`. */
151
- parts?: ToolPart[];
152
- }
153
- interface AgentTimelineStatusItem {
154
- id: string;
155
- kind: "status";
156
- label: string;
157
- detail?: string;
158
- tone?: AgentTimelineTone;
159
- }
160
- interface AgentTimelineArtifactItem {
161
- id: string;
162
- kind: "artifact";
163
- title: string;
164
- description?: string;
165
- meta?: ReactNode;
166
- icon?: ReactNode;
167
- tone?: AgentTimelineTone;
168
- action?: ReactNode;
169
- onClick?: () => void;
170
- }
171
- interface AgentTimelineCustomItem {
172
- id: string;
173
- kind: "custom";
174
- /** Laid out as a run row: it takes the same horizontal bleed as tool rows,
175
- * so a `RunRowShell`-based row (reasoning) aligns its glyph with the prose
176
- * edge. */
177
- content: ReactNode;
178
- }
179
- type AgentTimelineItem = AgentTimelineMessageItem | AgentTimelineToolItem | AgentTimelineToolGroupItem | AgentTimelineStatusItem | AgentTimelineArtifactItem | AgentTimelineCustomItem;
180
- interface AgentTimelineProps {
181
- items: AgentTimelineItem[];
182
- isThinking?: boolean;
183
- emptyState?: ReactNode;
184
- className?: string;
185
- /** Optional actions rendered beside each tool item (e.g. "open in artifacts").
186
- * Receives the source tool part carried on the item. */
187
- renderToolActions?: (part: ToolPart) => ReactNode;
188
- /** When set, collapse the timeline to the first N step rows (every item
189
- * except user messages) behind a "Show N more steps" toggle. Omit to always
190
- * show every row. */
191
- collapseAfter?: number;
192
- }
193
- /**
194
- * AgentTimeline — unified mixed-content transcript for agent-backed sandbox
195
- * sessions. Renders messages, tool rows, status cards, and artifact handoffs
196
- * as one plain column: prose at the reading size, tool calls as quiet
197
- * one-liners between the paragraphs, no connector chrome.
198
- */
199
- declare function AgentTimeline({ items, isThinking, emptyState, className, renderToolActions, collapseAfter, }: AgentTimelineProps): react_jsx_runtime.JSX.Element | null;
200
-
201
- export { AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, MessageList, type MessageListProps, type MessageRole, ThinkingIndicator, type ThinkingIndicatorProps, UserMessage, type UserMessageProps };
1
+ import { _ as UserMessageProps, a as AgentTimelineMessageItem, b as ChatContainer, c as AgentTimelineTone, d as ThinkingIndicator, f as ThinkingIndicatorProps, g as UserMessage, h as MessageRole, i as AgentTimelineItem, l as AgentTimelineToolGroupItem, m as ChatMessageProps, n as AgentTimelineArtifactItem, o as AgentTimelineProps, p as ChatMessage, r as AgentTimelineCustomItem, s as AgentTimelineStatusItem, t as AgentTimeline, u as AgentTimelineToolItem, v as MessageList, x as ChatContainerProps, y as MessageListProps } from "./index-CUhfHT_V.js";
2
+ export { AgentTimeline, type AgentTimelineArtifactItem, type AgentTimelineCustomItem, type AgentTimelineItem, type AgentTimelineMessageItem, type AgentTimelineProps, type AgentTimelineStatusItem, type AgentTimelineTone, type AgentTimelineToolGroupItem, type AgentTimelineToolItem, ChatContainer, type ChatContainerProps, ChatMessage, type ChatMessageProps, MessageList, type MessageListProps, type MessageRole, ThinkingIndicator, type ThinkingIndicatorProps, UserMessage, type UserMessageProps };
package/dist/chat.js CHANGED
@@ -1,31 +1,2 @@
1
- import {
2
- AgentTimeline,
3
- ChatContainer,
4
- ChatMessage,
5
- MessageList,
6
- ThinkingIndicator,
7
- UserMessage
8
- } from "./chunk-C5WF4WMV.js";
9
- import "./chunk-565EATZZ.js";
10
- import "./chunk-YU4E5J2N.js";
11
- import "./chunk-R7B3UWPF.js";
12
- import "./chunk-ND3ZFXQK.js";
13
- import "./chunk-HMAPIH7L.js";
14
- import "./chunk-L57WRIND.js";
15
- import "./chunk-BEBXZPHW.js";
16
- import "./chunk-M3QZK62R.js";
17
- import "./chunk-4CLN43XT.js";
18
- import "./chunk-XU3HB5QL.js";
19
- import "./chunk-42PAH5D2.js";
20
- import "./chunk-OL5GYLHV.js";
21
- import "./chunk-3XXBZL53.js";
22
- import "./chunk-WKWBTL2V.js";
23
- import "./chunk-RQHJBTEU.js";
24
- export {
25
- AgentTimeline,
26
- ChatContainer,
27
- ChatMessage,
28
- MessageList,
29
- ThinkingIndicator,
30
- UserMessage
31
- };
1
+ import { a as MessageList, i as ThinkingIndicator, n as ChatContainer, o as UserMessage, r as AgentTimeline, t as ChatMessage } from "./chat-D4jAfEmj.js";
2
+ export { AgentTimeline, ChatContainer, ChatMessage, MessageList, ThinkingIndicator, UserMessage };
@@ -0,0 +1,165 @@
1
+ import { i as focusRing } from "./focus-BcE_SHqz.js";
2
+ import { t as cn } from "./utils-C_uf36nf.js";
3
+ import { memo, useCallback, useEffect, useRef, useState } from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Check, Copy } from "lucide-react";
6
+ import SyntaxHighlighter from "react-syntax-highlighter";
7
+ //#region src/markdown/code-block.tsx
8
+ function getSyntaxTheme() {
9
+ const el = typeof document !== "undefined" ? document.documentElement : null;
10
+ const v = (name, fallback) => el ? getComputedStyle(el).getPropertyValue(name).trim() || fallback : fallback;
11
+ const comment = v("--syntax-comment", "#6B7094");
12
+ const keyword = v("--syntax-keyword", "#A78FFF");
13
+ const string = v("--syntax-string", "#10b981");
14
+ const fn = v("--syntax-function", "#6D9FFF");
15
+ const number = v("--syntax-number", "#FFB347");
16
+ const meta = v("--syntax-meta", "#8263FF");
17
+ const error = v("--syntax-error", "#FF4D6D");
18
+ const variable = v("--syntax-variable", "#C4C0D8");
19
+ const fg = v("--syntax-foreground", "#E8E6F6");
20
+ return {
21
+ "hljs-comment": {
22
+ color: comment,
23
+ fontStyle: "italic"
24
+ },
25
+ "hljs-quote": {
26
+ color: comment,
27
+ fontStyle: "italic"
28
+ },
29
+ "hljs-doctag": { color: comment },
30
+ "hljs-keyword": { color: keyword },
31
+ "hljs-selector-tag": { color: keyword },
32
+ "hljs-literal": { color: keyword },
33
+ "hljs-type": { color: keyword },
34
+ "hljs-class": { color: keyword },
35
+ "hljs-string": { color: string },
36
+ "hljs-template-tag": { color: string },
37
+ "hljs-template-variable": { color: string },
38
+ "hljs-addition": { color: string },
39
+ "hljs-regexp": { color: string },
40
+ "hljs-title": { color: fn },
41
+ "hljs-section": { color: fn },
42
+ "hljs-built_in": { color: fn },
43
+ "hljs-name": { color: fn },
44
+ "hljs-function": { color: fn },
45
+ "hljs-selector-id": { color: fn },
46
+ "hljs-selector-class": { color: fn },
47
+ "hljs-attribute": { color: fn },
48
+ "hljs-number": { color: number },
49
+ "hljs-symbol": { color: number },
50
+ "hljs-bullet": { color: number },
51
+ "hljs-link": {
52
+ color: number,
53
+ textDecoration: "underline"
54
+ },
55
+ "hljs-meta": { color: meta },
56
+ "hljs-selector-pseudo": { color: meta },
57
+ "hljs-deletion": { color: error },
58
+ "hljs-params": { color: variable },
59
+ "hljs-variable": { color: variable },
60
+ "hljs-tag": { color: variable },
61
+ "hljs-attr": { color: variable },
62
+ "hljs-subst": { color: variable },
63
+ "hljs-strong": { fontWeight: "bold" },
64
+ "hljs-emphasis": { fontStyle: "italic" },
65
+ "hljs": {
66
+ color: fg,
67
+ background: "transparent"
68
+ }
69
+ };
70
+ }
71
+ const LIGHT_THEMES = /* @__PURE__ */ new Set(["vault", "dawn"]);
72
+ function detectLightTheme() {
73
+ return typeof document !== "undefined" && LIGHT_THEMES.has(document.documentElement.getAttribute("data-sandbox-theme") ?? "");
74
+ }
75
+ function useIsLightTheme() {
76
+ const [isLight, setIsLight] = useState(detectLightTheme);
77
+ useEffect(() => {
78
+ if (typeof document === "undefined") return;
79
+ setIsLight(detectLightTheme());
80
+ const observer = new MutationObserver(() => setIsLight(detectLightTheme()));
81
+ observer.observe(document.documentElement, {
82
+ attributes: true,
83
+ attributeFilter: ["data-sandbox-theme"]
84
+ });
85
+ return () => observer.disconnect();
86
+ }, []);
87
+ return isLight;
88
+ }
89
+ const CodeBlock = memo(({ code, language, label, showLineNumbers = false, light: lightProp, className, children, ...props }) => {
90
+ const isLight = useIsLightTheme();
91
+ const light = lightProp ?? isLight;
92
+ const theme = getSyntaxTheme();
93
+ const bg = "bg-card border-border";
94
+ const headerBg = light ? "bg-muted/50 border-border" : "bg-background border-border";
95
+ const langColor = "text-muted-foreground";
96
+ const headerLabel = label ?? language;
97
+ return /* @__PURE__ */ jsxs("div", {
98
+ className: cn("group relative overflow-hidden rounded-lg border font-mono", bg, className),
99
+ ...props,
100
+ children: [
101
+ headerLabel && /* @__PURE__ */ jsxs("div", {
102
+ className: cn("flex items-center justify-between border-b px-3 py-1", headerBg),
103
+ children: [/* @__PURE__ */ jsx("span", {
104
+ className: cn("text-[calc(var(--font-size-xs)-1px)] font-mono font-medium uppercase tracking-widest", langColor),
105
+ children: headerLabel
106
+ }), children]
107
+ }),
108
+ !headerLabel && children && /* @__PURE__ */ jsx("div", {
109
+ className: "absolute right-2 top-2 z-10 flex items-center gap-2 opacity-0 transition-opacity group-hover:opacity-100",
110
+ children
111
+ }),
112
+ /* @__PURE__ */ jsx(SyntaxHighlighter, {
113
+ language: language ?? "text",
114
+ style: theme,
115
+ showLineNumbers,
116
+ lineNumberStyle: {
117
+ color: light ? "#8B92B8" : "#4A4D6A",
118
+ minWidth: "2.5em",
119
+ paddingRight: "1em"
120
+ },
121
+ customStyle: {
122
+ margin: 0,
123
+ padding: "var(--code-padding-y, 0.625rem) var(--code-padding-x, 0.75rem)",
124
+ background: "transparent",
125
+ fontSize: "var(--code-font-size, 0.8125rem)",
126
+ lineHeight: "var(--code-line-height, 1.5)",
127
+ overflowX: "auto"
128
+ },
129
+ codeTagProps: { style: { fontFamily: "var(--font-mono, 'JetBrains Mono', ui-monospace, monospace)" } },
130
+ wrapLines: false,
131
+ children: code
132
+ })
133
+ ]
134
+ });
135
+ });
136
+ CodeBlock.displayName = "CodeBlock";
137
+ /** Copy-to-clipboard button for use inside CodeBlock. */
138
+ const CopyButton = memo(({ text }) => {
139
+ const [copied, setCopied] = useState(false);
140
+ const timerRef = useRef(null);
141
+ useEffect(() => {
142
+ return () => {
143
+ if (timerRef.current) clearTimeout(timerRef.current);
144
+ };
145
+ }, []);
146
+ const handleCopy = useCallback(async () => {
147
+ try {
148
+ await navigator.clipboard.writeText(text);
149
+ setCopied(true);
150
+ if (timerRef.current) clearTimeout(timerRef.current);
151
+ timerRef.current = setTimeout(() => setCopied(false), 2e3);
152
+ } catch (err) {
153
+ console.warn("Clipboard write failed:", err);
154
+ }
155
+ }, [text]);
156
+ return /* @__PURE__ */ jsx("button", {
157
+ onClick: handleCopy,
158
+ className: cn("flex items-center justify-center w-6 h-6 rounded-md bg-muted border border-border hover:border-[var(--border-strong)] transition-colors", focusRing),
159
+ title: "Copy to clipboard",
160
+ children: copied ? /* @__PURE__ */ jsx(Check, { className: "w-3.5 h-3.5 text-emerald-500" }) : /* @__PURE__ */ jsx(Copy, { className: "w-3.5 h-3.5 text-muted-foreground" })
161
+ });
162
+ });
163
+ CopyButton.displayName = "CopyButton";
164
+ //#endregion
165
+ export { CopyButton as n, CodeBlock as t };
@@ -0,0 +1,23 @@
1
+ import { HTMLAttributes, ReactNode } from "react";
2
+ //#region src/markdown/code-block.d.ts
3
+ interface CodeBlockProps extends HTMLAttributes<HTMLDivElement> {
4
+ code: string;
5
+ language?: string;
6
+ /**
7
+ * Header text. Defaults to `language`. Set this when the display name differs
8
+ * from the highlight.js language id — e.g. a file extension ("BASHRC") whose
9
+ * content highlights as a known language, or none.
10
+ */
11
+ label?: string;
12
+ showLineNumbers?: boolean;
13
+ /** Force light theme; defaults to dark */
14
+ light?: boolean;
15
+ children?: ReactNode;
16
+ }
17
+ declare const CodeBlock: import("react").MemoExoticComponent<({ code, language, label, showLineNumbers, light: lightProp, className, children, ...props }: CodeBlockProps) => import("react").JSX.Element>;
18
+ /** Copy-to-clipboard button for use inside CodeBlock. */
19
+ declare const CopyButton: import("react").MemoExoticComponent<({ text }: {
20
+ text: string;
21
+ }) => import("react").JSX.Element>;
22
+ //#endregion
23
+ export { CodeBlockProps as n, CopyButton as r, CodeBlock as t };