@tangle-network/ui 11.1.0 → 11.2.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/CHANGELOG.md +15 -0
- package/dist/{artifact-pane-DvJyPWV4.d.ts → artifact-pane-DpuWcAiF.d.ts} +10 -1
- package/dist/chat.js +4 -4
- package/dist/{chunk-52Y3FMFI.js → chunk-3M7BPSSW.js} +1 -1
- package/dist/{chunk-LELGOLFV.js → chunk-GGDYWMFF.js} +15 -7
- package/dist/{chunk-EWIWYC2I.js → chunk-HW4ROISY.js} +1 -1
- package/dist/{chunk-F22SQTBP.js → chunk-J3YZIQNI.js} +1 -1
- package/dist/{chunk-CSAIKY36.js → chunk-LTEKI7YJ.js} +12 -7
- package/dist/{chunk-FIFE5HCW.js → chunk-OTZWQJ5W.js} +3 -3
- package/dist/{chunk-FJBTCTZM.js → chunk-P5F43A65.js} +1 -1
- package/dist/{chunk-SZ44QDA6.js → chunk-RADUPP44.js} +12 -5
- package/dist/{chunk-PX5KV5HI.js → chunk-SRAKCVPO.js} +2 -2
- package/dist/{document-editor-pane-DyDEX_Zm.d.ts → document-editor-pane-C3cYEDWZ.d.ts} +2 -2
- package/dist/{document-editor-pane-WCTA3ZOE.js → document-editor-pane-OQNGM4RJ.js} +3 -3
- package/dist/editor.d.ts +3 -3
- package/dist/editor.js +3 -3
- package/dist/files.d.ts +5 -3
- package/dist/files.js +3 -3
- package/dist/hooks.js +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +8 -8
- package/dist/markdown.js +1 -1
- package/dist/openui.js +2 -2
- package/dist/primitives.d.ts +1 -1
- package/dist/primitives.js +1 -1
- package/dist/run.js +4 -4
- package/dist/sdk-hooks.js +3 -3
- package/package.json +1 -1
- package/src/editor/document-editor-pane.stories.tsx +74 -0
- package/src/editor/document-editor-pane.tsx +10 -3
- package/src/files/file-artifact-pane.tsx +14 -2
- package/src/files/file-preview.stories.tsx +22 -1
- package/src/files/file-preview.tsx +2 -2
- package/src/markdown/markdown.stories.tsx +55 -1
- package/src/markdown/markdown.test.tsx +23 -0
- package/src/markdown/markdown.tsx +1 -1
- package/src/primitives/artifact-pane.tsx +52 -26
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @tangle-network/ui
|
|
2
2
|
|
|
3
|
+
## 11.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ac4eaf4: feat(files): host-aligned artifact surface props
|
|
8
|
+
|
|
9
|
+
- `ArtifactPane`: `headerClassName` + `hideTitleBlock` (header row collapses when empty).
|
|
10
|
+
- `FileArtifactPane`: threads both through all render paths; `headerActions` is `undefined` (not an empty fragment) when there are no actions.
|
|
11
|
+
- `DocumentEditorPane`: `previewClassName` now governs the whole preview box (gutter/border/surface/padding), enabling a full-bleed document body.
|
|
12
|
+
- `FilePreview`: text previews sit on `bg-card` for a white surface in light theme.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- c5dfc7d: Use tokenized Tangle prose styling for markdown previews so light themes stay readable.
|
|
17
|
+
|
|
3
18
|
## 11.1.0
|
|
4
19
|
|
|
5
20
|
### Minor Changes
|
|
@@ -14,11 +14,20 @@ interface ArtifactPaneProps {
|
|
|
14
14
|
children?: ReactNode;
|
|
15
15
|
className?: string;
|
|
16
16
|
contentClassName?: string;
|
|
17
|
+
/** Extra classes for the header band (e.g. to align its surface with the host chrome). */
|
|
18
|
+
headerClassName?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Suppress the eyebrow/title/subtitle/meta block. Use when the host already
|
|
21
|
+
* shows the artifact's identity elsewhere (e.g. a surrounding path row), so the
|
|
22
|
+
* pane keeps only its tabs, toolbar, and header actions. The whole header row
|
|
23
|
+
* collapses when nothing else would render in it.
|
|
24
|
+
*/
|
|
25
|
+
hideTitleBlock?: boolean;
|
|
17
26
|
}
|
|
18
27
|
/**
|
|
19
28
|
* ArtifactPane — shared frame for files, previews, documents, inspectors, and
|
|
20
29
|
* other artifact-like surfaces inside sandbox applications.
|
|
21
30
|
*/
|
|
22
|
-
declare function ArtifactPane({ eyebrow, title, subtitle, meta, headerActions, tabs, toolbar, footer, emptyState, children, className, contentClassName, }: ArtifactPaneProps): react_jsx_runtime.JSX.Element;
|
|
31
|
+
declare function ArtifactPane({ eyebrow, title, subtitle, meta, headerActions, tabs, toolbar, footer, emptyState, children, className, contentClassName, headerClassName, hideTitleBlock, }: ArtifactPaneProps): react_jsx_runtime.JSX.Element;
|
|
23
32
|
|
|
24
33
|
export { ArtifactPane as A, type ArtifactPaneProps as a };
|
package/dist/chat.js
CHANGED
|
@@ -5,17 +5,17 @@ import {
|
|
|
5
5
|
MessageList,
|
|
6
6
|
ThinkingIndicator,
|
|
7
7
|
UserMessage
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-OTZWQJ5W.js";
|
|
9
9
|
import "./chunk-AZWDI2JG.js";
|
|
10
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-SRAKCVPO.js";
|
|
11
11
|
import "./chunk-4ORVXSMU.js";
|
|
12
12
|
import "./chunk-ULDNFLIM.js";
|
|
13
13
|
import "./chunk-AAUNOHVL.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-3M7BPSSW.js";
|
|
15
15
|
import "./chunk-GYPQXTJU.js";
|
|
16
16
|
import "./chunk-MKTSMWVD.js";
|
|
17
17
|
import "./chunk-ZRVH3WCA.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-P5F43A65.js";
|
|
19
19
|
import "./chunk-WUQDUBJG.js";
|
|
20
20
|
import "./chunk-RQHJBTEU.js";
|
|
21
21
|
export {
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
} from "./chunk-ZRVH3WCA.js";
|
|
7
7
|
import {
|
|
8
8
|
ArtifactPane
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LTEKI7YJ.js";
|
|
10
10
|
import {
|
|
11
11
|
Markdown
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-P5F43A65.js";
|
|
13
13
|
import {
|
|
14
14
|
CodeBlock,
|
|
15
15
|
CopyButton
|
|
@@ -407,7 +407,7 @@ function PdfPreview({ blobUrl, filename }) {
|
|
|
407
407
|
) });
|
|
408
408
|
}
|
|
409
409
|
function TextPreview({ content }) {
|
|
410
|
-
return /* @__PURE__ */ jsx3("pre", { className: "bg-
|
|
410
|
+
return /* @__PURE__ */ jsx3("pre", { className: "bg-card rounded-[var(--radius-md)] border border-border p-4 overflow-auto max-h-[70vh] text-sm text-foreground font-mono leading-[1.55]", children: content });
|
|
411
411
|
}
|
|
412
412
|
function UnsupportedPreview({
|
|
413
413
|
filename,
|
|
@@ -422,7 +422,7 @@ function UnsupportedPreview({
|
|
|
422
422
|
] });
|
|
423
423
|
}
|
|
424
424
|
function MarkdownPreview({ content }) {
|
|
425
|
-
return /* @__PURE__ */ jsx3("div", { className: "rounded-[var(--radius-md)] border border-border bg-background p-5", children: /* @__PURE__ */ jsx3(Markdown, {
|
|
425
|
+
return /* @__PURE__ */ jsx3("div", { className: "rounded-[var(--radius-md)] border border-border bg-background p-5", children: /* @__PURE__ */ jsx3(Markdown, { children: content }) });
|
|
426
426
|
}
|
|
427
427
|
function EmptyPreview({ filename }) {
|
|
428
428
|
return /* @__PURE__ */ jsxs2("div", { className: "flex flex-col items-center justify-center py-16 text-muted-foreground", children: [
|
|
@@ -560,7 +560,7 @@ import { lazy, Suspense } from "react";
|
|
|
560
560
|
import { Download as Download2, X as X3 } from "lucide-react";
|
|
561
561
|
import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
562
562
|
var LazyDocumentEditorPane = lazy(async () => {
|
|
563
|
-
const module = await import("./document-editor-pane-
|
|
563
|
+
const module = await import("./document-editor-pane-OQNGM4RJ.js");
|
|
564
564
|
return { default: module.DocumentEditorPane };
|
|
565
565
|
});
|
|
566
566
|
function FileArtifactPane({
|
|
@@ -580,6 +580,8 @@ function FileArtifactPane({
|
|
|
580
580
|
toolbar,
|
|
581
581
|
footer,
|
|
582
582
|
className,
|
|
583
|
+
headerClassName,
|
|
584
|
+
hideTitleBlock,
|
|
583
585
|
editor
|
|
584
586
|
}) {
|
|
585
587
|
const showTabs = tabs.length > 0 && onTabSelect && onTabClose;
|
|
@@ -594,7 +596,7 @@ function FileArtifactPane({
|
|
|
594
596
|
) : void 0;
|
|
595
597
|
const isMarkdown = detectFileFormat(filename, mimeType) === "markdown" || (path ? detectFileFormat(path, mimeType) === "markdown" : false);
|
|
596
598
|
const isEditableMarkdown = isMarkdown && editor?.enabled;
|
|
597
|
-
const headerActions = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
599
|
+
const headerActions = onDownload || onClose ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
598
600
|
onDownload && /* @__PURE__ */ jsx5(
|
|
599
601
|
"button",
|
|
600
602
|
{
|
|
@@ -615,7 +617,7 @@ function FileArtifactPane({
|
|
|
615
617
|
children: /* @__PURE__ */ jsx5(X3, { className: "h-4 w-4" })
|
|
616
618
|
}
|
|
617
619
|
)
|
|
618
|
-
] });
|
|
620
|
+
] }) : void 0;
|
|
619
621
|
if (isEditableMarkdown) {
|
|
620
622
|
return /* @__PURE__ */ jsx5(
|
|
621
623
|
Suspense,
|
|
@@ -632,6 +634,8 @@ function FileArtifactPane({
|
|
|
632
634
|
className,
|
|
633
635
|
tabs: paneTabs,
|
|
634
636
|
headerActions,
|
|
637
|
+
headerClassName,
|
|
638
|
+
hideTitleBlock,
|
|
635
639
|
children: /* @__PURE__ */ jsx5("div", { className: "flex min-h-[12rem] items-center justify-center rounded-[var(--radius-lg)] border border-dashed border-border bg-muted text-sm text-muted-foreground", children: "Loading editor\u2026" })
|
|
636
640
|
}
|
|
637
641
|
),
|
|
@@ -647,6 +651,8 @@ function FileArtifactPane({
|
|
|
647
651
|
className,
|
|
648
652
|
tabs: paneTabs,
|
|
649
653
|
headerActions,
|
|
654
|
+
headerClassName,
|
|
655
|
+
hideTitleBlock,
|
|
650
656
|
markdown: content ?? "",
|
|
651
657
|
mode: editor.mode,
|
|
652
658
|
defaultMode: editor.defaultMode,
|
|
@@ -679,6 +685,8 @@ function FileArtifactPane({
|
|
|
679
685
|
className,
|
|
680
686
|
tabs: paneTabs,
|
|
681
687
|
headerActions,
|
|
688
|
+
headerClassName,
|
|
689
|
+
hideTitleBlock,
|
|
682
690
|
children: /* @__PURE__ */ jsx5(
|
|
683
691
|
FilePreview,
|
|
684
692
|
{
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-RQHJBTEU.js";
|
|
4
4
|
|
|
5
5
|
// src/primitives/artifact-pane.tsx
|
|
6
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
function ArtifactPane({
|
|
8
8
|
eyebrow,
|
|
9
9
|
title,
|
|
@@ -16,9 +16,14 @@ function ArtifactPane({
|
|
|
16
16
|
emptyState,
|
|
17
17
|
children,
|
|
18
18
|
className,
|
|
19
|
-
contentClassName
|
|
19
|
+
contentClassName,
|
|
20
|
+
headerClassName,
|
|
21
|
+
hideTitleBlock = false
|
|
20
22
|
}) {
|
|
21
23
|
const hasContent = children !== void 0 && children !== null;
|
|
24
|
+
const showTitleRow = !hideTitleBlock || Boolean(headerActions);
|
|
25
|
+
const hasHeader = showTitleRow || Boolean(tabs) || Boolean(toolbar);
|
|
26
|
+
const toolbarNeedsDivider = showTitleRow || Boolean(tabs);
|
|
22
27
|
return /* @__PURE__ */ jsxs(
|
|
23
28
|
"section",
|
|
24
29
|
{
|
|
@@ -27,20 +32,20 @@ function ArtifactPane({
|
|
|
27
32
|
className
|
|
28
33
|
),
|
|
29
34
|
children: [
|
|
30
|
-
/* @__PURE__ */ jsxs("header", { className: "border-b border-border bg-muted/10", children: [
|
|
31
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 px-3 py-2", children: [
|
|
32
|
-
/* @__PURE__ */
|
|
35
|
+
hasHeader && /* @__PURE__ */ jsxs("header", { className: cn("border-b border-border bg-muted/10", headerClassName), children: [
|
|
36
|
+
showTitleRow && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 px-3 py-2", children: [
|
|
37
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: !hideTitleBlock && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
33
38
|
eyebrow && /* @__PURE__ */ jsx("div", { className: "mb-1 inline-flex max-w-full items-center px-1 py-0.5 text-[10px] font-bold uppercase tracking-wider text-muted-foreground", children: eyebrow }),
|
|
34
39
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 text-[13px] font-medium text-foreground", children: title }),
|
|
35
40
|
(subtitle || meta) && /* @__PURE__ */ jsxs("div", { className: "mt-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs leading-relaxed text-muted-foreground", children: [
|
|
36
41
|
subtitle && /* @__PURE__ */ jsx("span", { className: "truncate", children: subtitle }),
|
|
37
42
|
meta && /* @__PURE__ */ jsx("span", { className: "flex items-center gap-2", children: meta })
|
|
38
43
|
] })
|
|
39
|
-
] }),
|
|
44
|
+
] }) }),
|
|
40
45
|
headerActions && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1.5", children: headerActions })
|
|
41
46
|
] }),
|
|
42
47
|
tabs,
|
|
43
|
-
toolbar && /* @__PURE__ */ jsx("div", { className: "
|
|
48
|
+
toolbar && /* @__PURE__ */ jsx("div", { className: cn("px-3 py-2", toolbarNeedsDivider && "border-t border-border"), children: toolbar })
|
|
44
49
|
] }),
|
|
45
50
|
/* @__PURE__ */ jsx("div", { className: cn("min-h-0 flex-1 overflow-auto", contentClassName), children: hasContent ? children : emptyState ? /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center p-6", children: emptyState }) : null }),
|
|
46
51
|
footer && /* @__PURE__ */ jsx("footer", { className: "shrink-0 border-t border-border bg-card px-3 py-2", children: footer })
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
InlineThinkingItem,
|
|
8
8
|
RunGroup
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-SRAKCVPO.js";
|
|
10
10
|
import {
|
|
11
11
|
ToolCallGroup,
|
|
12
12
|
ToolCallStep
|
|
@@ -16,10 +16,10 @@ import {
|
|
|
16
16
|
} from "./chunk-ULDNFLIM.js";
|
|
17
17
|
import {
|
|
18
18
|
OpenUIArtifactRenderer
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-3M7BPSSW.js";
|
|
20
20
|
import {
|
|
21
21
|
Markdown
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-P5F43A65.js";
|
|
23
23
|
import {
|
|
24
24
|
cn
|
|
25
25
|
} from "./chunk-RQHJBTEU.js";
|
|
@@ -16,7 +16,7 @@ var Markdown = memo(({ children, className }) => {
|
|
|
16
16
|
return /* @__PURE__ */ jsx(
|
|
17
17
|
"div",
|
|
18
18
|
{
|
|
19
|
-
className: cn("
|
|
19
|
+
className: cn("tangle-prose max-w-none text-sm", className),
|
|
20
20
|
children: /* @__PURE__ */ jsx(
|
|
21
21
|
ReactMarkdown,
|
|
22
22
|
{
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
} from "./chunk-Q56BYXQF.js";
|
|
7
7
|
import {
|
|
8
8
|
ArtifactPane
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LTEKI7YJ.js";
|
|
10
10
|
import {
|
|
11
11
|
Markdown
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-P5F43A65.js";
|
|
13
13
|
import {
|
|
14
14
|
cn
|
|
15
15
|
} from "./chunk-RQHJBTEU.js";
|
|
@@ -1030,6 +1030,8 @@ function DocumentEditorPane({
|
|
|
1030
1030
|
footer,
|
|
1031
1031
|
className,
|
|
1032
1032
|
contentClassName,
|
|
1033
|
+
headerClassName,
|
|
1034
|
+
hideTitleBlock,
|
|
1033
1035
|
tabs,
|
|
1034
1036
|
toolbar,
|
|
1035
1037
|
markdown = "",
|
|
@@ -1126,10 +1128,13 @@ function DocumentEditorPane({
|
|
|
1126
1128
|
"div",
|
|
1127
1129
|
{
|
|
1128
1130
|
className: cn(
|
|
1129
|
-
|
|
1131
|
+
// The outer margin is the card's gutter (rather than padding on the tab
|
|
1132
|
+
// panel) so `previewClassName` can govern the whole box — gutter, border,
|
|
1133
|
+
// surface, and inner padding — e.g. to render the document full-bleed.
|
|
1134
|
+
"m-4 rounded-[var(--radius-lg)] border border-border bg-card p-5",
|
|
1130
1135
|
previewClassName
|
|
1131
1136
|
),
|
|
1132
|
-
children: /* @__PURE__ */ jsx5(Markdown, {
|
|
1137
|
+
children: /* @__PURE__ */ jsx5(Markdown, { children: draft })
|
|
1133
1138
|
}
|
|
1134
1139
|
);
|
|
1135
1140
|
const localEditor = /* @__PURE__ */ jsx5(
|
|
@@ -1174,9 +1179,11 @@ function DocumentEditorPane({
|
|
|
1174
1179
|
tabs,
|
|
1175
1180
|
className,
|
|
1176
1181
|
contentClassName,
|
|
1182
|
+
headerClassName,
|
|
1177
1183
|
toolbar: editorToolbar,
|
|
1184
|
+
hideTitleBlock,
|
|
1178
1185
|
children: [
|
|
1179
|
-
/* @__PURE__ */ jsx5(TabsContent, { value: "preview", className: "mt-0 h-full
|
|
1186
|
+
/* @__PURE__ */ jsx5(TabsContent, { value: "preview", className: "mt-0 h-full", children: preview }),
|
|
1180
1187
|
/* @__PURE__ */ jsx5(TabsContent, { value: "edit", className: "mt-0 h-full px-4 py-4", children: isCollaborative ? collaborativeEditor : localEditor })
|
|
1181
1188
|
]
|
|
1182
1189
|
}
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
} from "./chunk-ULDNFLIM.js";
|
|
10
10
|
import {
|
|
11
11
|
OpenUIArtifactRenderer
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3M7BPSSW.js";
|
|
13
13
|
import {
|
|
14
14
|
Markdown
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-P5F43A65.js";
|
|
16
16
|
import {
|
|
17
17
|
cn
|
|
18
18
|
} from "./chunk-RQHJBTEU.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { a as ArtifactPaneProps } from './artifact-pane-
|
|
3
|
+
import { a as ArtifactPaneProps } from './artifact-pane-DpuWcAiF.js';
|
|
4
4
|
import { HocuspocusProvider } from '@hocuspocus/provider';
|
|
5
5
|
import * as Y from 'yjs';
|
|
6
6
|
|
|
@@ -119,6 +119,6 @@ interface DocumentEditorPaneProps extends Omit<ArtifactPaneProps, "children" | "
|
|
|
119
119
|
* DocumentEditorPane — reusable markdown document surface with preview/edit
|
|
120
120
|
* modes and optional collaborative editing backed by Yjs/Hocuspocus.
|
|
121
121
|
*/
|
|
122
|
-
declare function DocumentEditorPane({ eyebrow, title, subtitle, meta, headerActions, footer, className, contentClassName, tabs, toolbar, markdown, mode, defaultMode, onModeChange, backend, placeholder, autoFocus, readOnly, onChange, onSave, saving, saveLabel, previewClassName, editorClassName, collaboration, }: DocumentEditorPaneProps): react_jsx_runtime.JSX.Element;
|
|
122
|
+
declare function DocumentEditorPane({ eyebrow, title, subtitle, meta, headerActions, footer, className, contentClassName, headerClassName, hideTitleBlock, tabs, toolbar, markdown, mode, defaultMode, onModeChange, backend, placeholder, autoFocus, readOnly, onChange, onSave, saving, saveLabel, previewClassName, editorClassName, collaboration, }: DocumentEditorPaneProps): react_jsx_runtime.JSX.Element;
|
|
123
123
|
|
|
124
124
|
export { type Collaborator as C, type DocumentEditorBackend as D, type EditorContextValue as E, type ConnectionState as a, type DocumentEditorMode as b, DocumentEditorPane as c, type DocumentEditorPaneCollaborationConfig as d, type DocumentEditorPaneProps as e, EditorProvider as f, type EditorProviderProps as g, type EditorTokenRefreshResult as h, type EditorUser as i, useEditorContext as u };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
DocumentEditorPane
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RADUPP44.js";
|
|
5
5
|
import "./chunk-Q56BYXQF.js";
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-LTEKI7YJ.js";
|
|
7
|
+
import "./chunk-P5F43A65.js";
|
|
8
8
|
import "./chunk-WUQDUBJG.js";
|
|
9
9
|
import "./chunk-RQHJBTEU.js";
|
|
10
10
|
export {
|
package/dist/editor.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { C as Collaborator, a as ConnectionState } from './document-editor-pane-
|
|
2
|
-
export { D as DocumentEditorBackend, b as DocumentEditorMode, c as DocumentEditorPane, d as DocumentEditorPaneCollaborationConfig, e as DocumentEditorPaneProps, E as EditorContextValue, f as EditorProvider, g as EditorProviderProps, h as EditorTokenRefreshResult, i as EditorUser, u as useEditorContext } from './document-editor-pane-
|
|
1
|
+
import { C as Collaborator, a as ConnectionState } from './document-editor-pane-C3cYEDWZ.js';
|
|
2
|
+
export { D as DocumentEditorBackend, b as DocumentEditorMode, c as DocumentEditorPane, d as DocumentEditorPaneCollaborationConfig, e as DocumentEditorPaneProps, E as EditorContextValue, f as EditorProvider, g as EditorProviderProps, h as EditorTokenRefreshResult, i as EditorUser, u as useEditorContext } from './document-editor-pane-C3cYEDWZ.js';
|
|
3
3
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
4
|
import { Editor } from '@tiptap/react';
|
|
5
5
|
import { HocuspocusProvider } from '@hocuspocus/provider';
|
|
6
6
|
import 'react';
|
|
7
|
-
import './artifact-pane-
|
|
7
|
+
import './artifact-pane-DpuWcAiF.js';
|
|
8
8
|
import 'yjs';
|
|
9
9
|
|
|
10
10
|
/**
|
package/dist/editor.js
CHANGED
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
useEditorConnection,
|
|
12
12
|
useEditorContext,
|
|
13
13
|
useYjsState
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-RADUPP44.js";
|
|
15
15
|
import "./chunk-Q56BYXQF.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-LTEKI7YJ.js";
|
|
17
|
+
import "./chunk-P5F43A65.js";
|
|
18
18
|
import "./chunk-WUQDUBJG.js";
|
|
19
19
|
import "./chunk-RQHJBTEU.js";
|
|
20
20
|
export {
|
package/dist/files.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { GitStatusEntry, ContextMenuItem, ContextMenuOpenContext, GitStatus } from '@pierre/trees';
|
|
3
3
|
import { ReactNode, CSSProperties } from 'react';
|
|
4
|
-
import { b as DocumentEditorMode, D as DocumentEditorBackend, d as DocumentEditorPaneCollaborationConfig } from './document-editor-pane-
|
|
5
|
-
import { a as ArtifactPaneProps } from './artifact-pane-
|
|
4
|
+
import { b as DocumentEditorMode, D as DocumentEditorBackend, d as DocumentEditorPaneCollaborationConfig } from './document-editor-pane-C3cYEDWZ.js';
|
|
5
|
+
import { a as ArtifactPaneProps } from './artifact-pane-DpuWcAiF.js';
|
|
6
6
|
import '@hocuspocus/provider';
|
|
7
7
|
import 'yjs';
|
|
8
8
|
|
|
@@ -164,13 +164,15 @@ interface FileArtifactPaneProps extends Omit<FilePreviewProps, "className"> {
|
|
|
164
164
|
toolbar?: ArtifactPaneProps["toolbar"];
|
|
165
165
|
footer?: ArtifactPaneProps["footer"];
|
|
166
166
|
className?: string;
|
|
167
|
+
headerClassName?: ArtifactPaneProps["headerClassName"];
|
|
168
|
+
hideTitleBlock?: ArtifactPaneProps["hideTitleBlock"];
|
|
167
169
|
editor?: FileArtifactPaneEditorOptions;
|
|
168
170
|
}
|
|
169
171
|
/**
|
|
170
172
|
* FileArtifactPane — opinionated artifact frame for file previews with tabs and
|
|
171
173
|
* header actions.
|
|
172
174
|
*/
|
|
173
|
-
declare function FileArtifactPane({ filename, content, blobUrl, mimeType, onClose, onDownload, path, tabs, activeTabId, onTabSelect, onTabClose, eyebrow, meta, toolbar, footer, className, editor, }: FileArtifactPaneProps): react_jsx_runtime.JSX.Element;
|
|
175
|
+
declare function FileArtifactPane({ filename, content, blobUrl, mimeType, onClose, onDownload, path, tabs, activeTabId, onTabSelect, onTabClose, eyebrow, meta, toolbar, footer, className, headerClassName, hideTitleBlock, editor, }: FileArtifactPaneProps): react_jsx_runtime.JSX.Element;
|
|
174
176
|
|
|
175
177
|
/**
|
|
176
178
|
* Shared file-format detection for every file surface — the preview pane, the
|
package/dist/files.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
FileTree,
|
|
6
6
|
RichFileTree,
|
|
7
7
|
filterFileTree
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GGDYWMFF.js";
|
|
9
9
|
import {
|
|
10
10
|
detectFileFormat,
|
|
11
11
|
fileExtension,
|
|
@@ -13,8 +13,8 @@ import {
|
|
|
13
13
|
getFormatLabel,
|
|
14
14
|
getSyntaxLanguage
|
|
15
15
|
} from "./chunk-ZRVH3WCA.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-LTEKI7YJ.js";
|
|
17
|
+
import "./chunk-P5F43A65.js";
|
|
18
18
|
import "./chunk-WUQDUBJG.js";
|
|
19
19
|
import "./chunk-RQHJBTEU.js";
|
|
20
20
|
export {
|
package/dist/hooks.js
CHANGED
|
@@ -11,19 +11,19 @@ import {
|
|
|
11
11
|
useSSEStream,
|
|
12
12
|
useSdkSession,
|
|
13
13
|
useToolCallStream
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-HW4ROISY.js";
|
|
15
15
|
import "./chunk-OEX7NZE3.js";
|
|
16
16
|
import {
|
|
17
17
|
useAutoScroll,
|
|
18
18
|
useRunCollapseState,
|
|
19
19
|
useRunGroups
|
|
20
20
|
} from "./chunk-AZWDI2JG.js";
|
|
21
|
-
import "./chunk-
|
|
21
|
+
import "./chunk-J3YZIQNI.js";
|
|
22
22
|
import "./chunk-4ORVXSMU.js";
|
|
23
23
|
import "./chunk-ULDNFLIM.js";
|
|
24
24
|
import "./chunk-AAUNOHVL.js";
|
|
25
25
|
import "./chunk-ZRVH3WCA.js";
|
|
26
|
-
import "./chunk-
|
|
26
|
+
import "./chunk-P5F43A65.js";
|
|
27
27
|
import "./chunk-WUQDUBJG.js";
|
|
28
28
|
import "./chunk-RQHJBTEU.js";
|
|
29
29
|
export {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { B as Button, a as ButtonProps, b as buttonVariants } from './button-CMQuQEW_.js';
|
|
2
2
|
export { Avatar, AvatarFallback, AvatarImage, Badge, BadgeProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateProps, InlineCode, InlineCodeProps, Input, InputProps, Label, Progress, SegmentedControl, SegmentedControlOption, SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatCardProps, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, Textarea, TextareaProps, ThemeToggle, Toast, ToastContainer, ToastProvider, UploadFile, UploadProgress, UploadProgressProps, badgeVariants, useTheme, useToast } from './primitives.js';
|
|
3
3
|
export { Logo, LogoProps, TangleKnot } from '@tangle-network/brand';
|
|
4
|
-
export { A as ArtifactPane, a as ArtifactPaneProps } from './artifact-pane-
|
|
4
|
+
export { A as ArtifactPane, a as ArtifactPaneProps } from './artifact-pane-DpuWcAiF.js';
|
|
5
5
|
export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from './chat.js';
|
|
6
6
|
export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps } from './run.js';
|
|
7
7
|
export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallStatus, d as ToolCallType, p as parseToolEvent } from './tool-call-feed-D9iofJgW.js';
|
|
@@ -34,7 +34,7 @@ import '@radix-ui/react-progress';
|
|
|
34
34
|
import '@radix-ui/react-switch';
|
|
35
35
|
import '@radix-ui/react-label';
|
|
36
36
|
import '@pierre/trees';
|
|
37
|
-
import './document-editor-pane-
|
|
37
|
+
import './document-editor-pane-C3cYEDWZ.js';
|
|
38
38
|
import '@hocuspocus/provider';
|
|
39
39
|
import 'yjs';
|
|
40
40
|
import 'nanostores';
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
useSSEStream,
|
|
18
18
|
useSdkSession,
|
|
19
19
|
useToolCallStream
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-HW4ROISY.js";
|
|
21
21
|
import {
|
|
22
22
|
addMessage,
|
|
23
23
|
addParts,
|
|
@@ -137,7 +137,7 @@ import {
|
|
|
137
137
|
MessageList,
|
|
138
138
|
ThinkingIndicator,
|
|
139
139
|
UserMessage
|
|
140
|
-
} from "./chunk-
|
|
140
|
+
} from "./chunk-OTZWQJ5W.js";
|
|
141
141
|
import {
|
|
142
142
|
useAutoScroll,
|
|
143
143
|
useRunCollapseState,
|
|
@@ -147,11 +147,11 @@ import "./chunk-47XH56SV.js";
|
|
|
147
147
|
import {
|
|
148
148
|
ToolCallFeed,
|
|
149
149
|
parseToolEvent
|
|
150
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-J3YZIQNI.js";
|
|
151
151
|
import {
|
|
152
152
|
InlineThinkingItem,
|
|
153
153
|
RunGroup
|
|
154
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-SRAKCVPO.js";
|
|
155
155
|
import {
|
|
156
156
|
ExpandedToolDetail,
|
|
157
157
|
InlineToolItem,
|
|
@@ -179,7 +179,7 @@ import {
|
|
|
179
179
|
import "./chunk-RQGKSCEZ.js";
|
|
180
180
|
import {
|
|
181
181
|
OpenUIArtifactRenderer
|
|
182
|
-
} from "./chunk-
|
|
182
|
+
} from "./chunk-3M7BPSSW.js";
|
|
183
183
|
import {
|
|
184
184
|
Badge,
|
|
185
185
|
Card,
|
|
@@ -210,7 +210,7 @@ import {
|
|
|
210
210
|
FileTree,
|
|
211
211
|
RichFileTree,
|
|
212
212
|
filterFileTree
|
|
213
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-GGDYWMFF.js";
|
|
214
214
|
import {
|
|
215
215
|
detectFileFormat,
|
|
216
216
|
fileExtension,
|
|
@@ -226,11 +226,11 @@ import {
|
|
|
226
226
|
} from "./chunk-Q56BYXQF.js";
|
|
227
227
|
import {
|
|
228
228
|
ArtifactPane
|
|
229
|
-
} from "./chunk-
|
|
229
|
+
} from "./chunk-LTEKI7YJ.js";
|
|
230
230
|
import "./chunk-5Z5ZYMOJ.js";
|
|
231
231
|
import {
|
|
232
232
|
Markdown
|
|
233
|
-
} from "./chunk-
|
|
233
|
+
} from "./chunk-P5F43A65.js";
|
|
234
234
|
import {
|
|
235
235
|
CodeBlock,
|
|
236
236
|
CopyButton
|
package/dist/markdown.js
CHANGED
package/dist/openui.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import "./chunk-RQGKSCEZ.js";
|
|
2
2
|
import {
|
|
3
3
|
OpenUIArtifactRenderer
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3M7BPSSW.js";
|
|
5
5
|
import "./chunk-GYPQXTJU.js";
|
|
6
6
|
import "./chunk-MKTSMWVD.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-P5F43A65.js";
|
|
8
8
|
import "./chunk-WUQDUBJG.js";
|
|
9
9
|
import "./chunk-RQHJBTEU.js";
|
|
10
10
|
export {
|
package/dist/primitives.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import * as ProgressPrimitive from '@radix-ui/react-progress';
|
|
|
13
13
|
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
14
14
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
15
15
|
export { Logo, LogoProps, TangleKnot } from '@tangle-network/brand';
|
|
16
|
-
export { A as ArtifactPane, a as ArtifactPaneProps } from './artifact-pane-
|
|
16
|
+
export { A as ArtifactPane, a as ArtifactPaneProps } from './artifact-pane-DpuWcAiF.js';
|
|
17
17
|
export { C as CodeBlock, a as CodeBlockProps, b as CopyButton } from './code-block-0kSpWMnf.js';
|
|
18
18
|
|
|
19
19
|
declare const Card: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & {
|
package/dist/primitives.js
CHANGED
package/dist/run.js
CHANGED
|
@@ -2,11 +2,11 @@ import "./chunk-47XH56SV.js";
|
|
|
2
2
|
import {
|
|
3
3
|
ToolCallFeed,
|
|
4
4
|
parseToolEvent
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-J3YZIQNI.js";
|
|
6
6
|
import {
|
|
7
7
|
InlineThinkingItem,
|
|
8
8
|
RunGroup
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-SRAKCVPO.js";
|
|
10
10
|
import {
|
|
11
11
|
ExpandedToolDetail,
|
|
12
12
|
InlineToolItem,
|
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
} from "./chunk-4ORVXSMU.js";
|
|
15
15
|
import "./chunk-ULDNFLIM.js";
|
|
16
16
|
import "./chunk-AAUNOHVL.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-3M7BPSSW.js";
|
|
18
18
|
import "./chunk-GYPQXTJU.js";
|
|
19
19
|
import "./chunk-MKTSMWVD.js";
|
|
20
20
|
import "./chunk-ZRVH3WCA.js";
|
|
21
|
-
import "./chunk-
|
|
21
|
+
import "./chunk-P5F43A65.js";
|
|
22
22
|
import "./chunk-WUQDUBJG.js";
|
|
23
23
|
import "./chunk-RQHJBTEU.js";
|
|
24
24
|
export {
|
package/dist/sdk-hooks.js
CHANGED
|
@@ -5,19 +5,19 @@ import {
|
|
|
5
5
|
useSSEStream,
|
|
6
6
|
useSdkSession,
|
|
7
7
|
useToolCallStream
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HW4ROISY.js";
|
|
9
9
|
import "./chunk-OEX7NZE3.js";
|
|
10
10
|
import {
|
|
11
11
|
useAutoScroll,
|
|
12
12
|
useRunCollapseState,
|
|
13
13
|
useRunGroups
|
|
14
14
|
} from "./chunk-AZWDI2JG.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-J3YZIQNI.js";
|
|
16
16
|
import "./chunk-4ORVXSMU.js";
|
|
17
17
|
import "./chunk-ULDNFLIM.js";
|
|
18
18
|
import "./chunk-AAUNOHVL.js";
|
|
19
19
|
import "./chunk-ZRVH3WCA.js";
|
|
20
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-P5F43A65.js";
|
|
21
21
|
import "./chunk-WUQDUBJG.js";
|
|
22
22
|
import "./chunk-RQHJBTEU.js";
|
|
23
23
|
export {
|
package/package.json
CHANGED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
2
|
+
import { DocumentEditorPane } from './document-editor-pane'
|
|
3
|
+
|
|
4
|
+
const MARKDOWN_SOURCE = `# GTM Agent Repository Overview
|
|
5
|
+
|
|
6
|
+
Source: \`github.com/tangle-network/gtm-agent\`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## What It Is
|
|
11
|
+
|
|
12
|
+
GTM Agent is an AI-powered go-to-market workspace where founders get a sandboxed environment.
|
|
13
|
+
|
|
14
|
+
## Architecture
|
|
15
|
+
|
|
16
|
+
| Layer | Owns | Location |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| Engine | Stream normalization | \`@tangle-network/agent-app\` |
|
|
19
|
+
| Shell | Auth, billing, RBAC, vault | \`src/routes/**\` |
|
|
20
|
+
|
|
21
|
+
## Tech Stack
|
|
22
|
+
|
|
23
|
+
- Frontend: Remix + Tailwind v4
|
|
24
|
+
- Database: SQLite + Drizzle ORM
|
|
25
|
+
- Sandbox: \`@tangle-network/sandbox\`
|
|
26
|
+
|
|
27
|
+
[Launch](https://gtm.tangle.tools)
|
|
28
|
+
`
|
|
29
|
+
|
|
30
|
+
const meta: Meta<typeof DocumentEditorPane> = {
|
|
31
|
+
title: 'Editor/DocumentEditorPane',
|
|
32
|
+
component: DocumentEditorPane,
|
|
33
|
+
parameters: { layout: 'fullscreen', backgrounds: { default: 'dark' } },
|
|
34
|
+
decorators: [
|
|
35
|
+
(Story) => (
|
|
36
|
+
<div className="h-[620px] w-[900px] bg-background text-foreground">
|
|
37
|
+
<Story />
|
|
38
|
+
</div>
|
|
39
|
+
),
|
|
40
|
+
],
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default meta
|
|
44
|
+
type Story = StoryObj<typeof DocumentEditorPane>
|
|
45
|
+
|
|
46
|
+
export const PreviewDark: Story = {
|
|
47
|
+
name: 'Preview (dark theme)',
|
|
48
|
+
args: {
|
|
49
|
+
title: 'gtm-agent-repo.md',
|
|
50
|
+
subtitle: 'knowledge/gtm-agent-repo.md',
|
|
51
|
+
eyebrow: 'Artifact',
|
|
52
|
+
markdown: MARKDOWN_SOURCE,
|
|
53
|
+
mode: 'preview',
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const PreviewLight: Story = {
|
|
58
|
+
name: 'Preview (light theme)',
|
|
59
|
+
parameters: { backgrounds: { default: 'light' } },
|
|
60
|
+
decorators: [
|
|
61
|
+
(Story) => (
|
|
62
|
+
<div data-theme="tangle-light" className="h-[620px] w-[900px] bg-background text-foreground">
|
|
63
|
+
<Story />
|
|
64
|
+
</div>
|
|
65
|
+
),
|
|
66
|
+
],
|
|
67
|
+
args: {
|
|
68
|
+
title: 'gtm-agent-repo.md',
|
|
69
|
+
subtitle: 'knowledge/gtm-agent-repo.md',
|
|
70
|
+
eyebrow: 'Artifact',
|
|
71
|
+
markdown: MARKDOWN_SOURCE,
|
|
72
|
+
mode: 'preview',
|
|
73
|
+
},
|
|
74
|
+
}
|
|
@@ -182,6 +182,8 @@ export function DocumentEditorPane({
|
|
|
182
182
|
footer,
|
|
183
183
|
className,
|
|
184
184
|
contentClassName,
|
|
185
|
+
headerClassName,
|
|
186
|
+
hideTitleBlock,
|
|
185
187
|
tabs,
|
|
186
188
|
toolbar,
|
|
187
189
|
markdown = "",
|
|
@@ -287,11 +289,14 @@ export function DocumentEditorPane({
|
|
|
287
289
|
const preview = (
|
|
288
290
|
<div
|
|
289
291
|
className={cn(
|
|
290
|
-
|
|
292
|
+
// The outer margin is the card's gutter (rather than padding on the tab
|
|
293
|
+
// panel) so `previewClassName` can govern the whole box — gutter, border,
|
|
294
|
+
// surface, and inner padding — e.g. to render the document full-bleed.
|
|
295
|
+
"m-4 rounded-[var(--radius-lg)] border border-border bg-card p-5",
|
|
291
296
|
previewClassName,
|
|
292
297
|
)}
|
|
293
298
|
>
|
|
294
|
-
<Markdown
|
|
299
|
+
<Markdown>{draft}</Markdown>
|
|
295
300
|
</div>
|
|
296
301
|
);
|
|
297
302
|
|
|
@@ -337,9 +342,11 @@ export function DocumentEditorPane({
|
|
|
337
342
|
tabs={tabs}
|
|
338
343
|
className={className}
|
|
339
344
|
contentClassName={contentClassName}
|
|
345
|
+
headerClassName={headerClassName}
|
|
340
346
|
toolbar={editorToolbar}
|
|
347
|
+
hideTitleBlock={hideTitleBlock}
|
|
341
348
|
>
|
|
342
|
-
<TabsContent value="preview" className="mt-0 h-full
|
|
349
|
+
<TabsContent value="preview" className="mt-0 h-full">
|
|
343
350
|
{preview}
|
|
344
351
|
</TabsContent>
|
|
345
352
|
<TabsContent value="edit" className="mt-0 h-full px-4 py-4">
|
|
@@ -44,6 +44,8 @@ export interface FileArtifactPaneProps extends Omit<FilePreviewProps, "className
|
|
|
44
44
|
toolbar?: ArtifactPaneProps["toolbar"];
|
|
45
45
|
footer?: ArtifactPaneProps["footer"];
|
|
46
46
|
className?: string;
|
|
47
|
+
headerClassName?: ArtifactPaneProps["headerClassName"];
|
|
48
|
+
hideTitleBlock?: ArtifactPaneProps["hideTitleBlock"];
|
|
47
49
|
editor?: FileArtifactPaneEditorOptions;
|
|
48
50
|
}
|
|
49
51
|
|
|
@@ -68,6 +70,8 @@ export function FileArtifactPane({
|
|
|
68
70
|
toolbar,
|
|
69
71
|
footer,
|
|
70
72
|
className,
|
|
73
|
+
headerClassName,
|
|
74
|
+
hideTitleBlock,
|
|
71
75
|
editor,
|
|
72
76
|
}: FileArtifactPaneProps) {
|
|
73
77
|
const showTabs = tabs.length > 0 && onTabSelect && onTabClose;
|
|
@@ -83,7 +87,9 @@ export function FileArtifactPane({
|
|
|
83
87
|
detectFileFormat(filename, mimeType) === "markdown" ||
|
|
84
88
|
(path ? detectFileFormat(path, mimeType) === "markdown" : false);
|
|
85
89
|
const isEditableMarkdown = isMarkdown && editor?.enabled;
|
|
86
|
-
|
|
90
|
+
// Undefined (not an empty fragment) when there are no actions, so ArtifactPane
|
|
91
|
+
// can collapse the header row entirely under hideTitleBlock.
|
|
92
|
+
const headerActions = onDownload || onClose ? (
|
|
87
93
|
<>
|
|
88
94
|
{onDownload && (
|
|
89
95
|
<button
|
|
@@ -106,7 +112,7 @@ export function FileArtifactPane({
|
|
|
106
112
|
</button>
|
|
107
113
|
)}
|
|
108
114
|
</>
|
|
109
|
-
);
|
|
115
|
+
) : undefined;
|
|
110
116
|
|
|
111
117
|
if (isEditableMarkdown) {
|
|
112
118
|
return (
|
|
@@ -122,6 +128,8 @@ export function FileArtifactPane({
|
|
|
122
128
|
className={className}
|
|
123
129
|
tabs={paneTabs}
|
|
124
130
|
headerActions={headerActions}
|
|
131
|
+
headerClassName={headerClassName}
|
|
132
|
+
hideTitleBlock={hideTitleBlock}
|
|
125
133
|
>
|
|
126
134
|
<div className="flex min-h-[12rem] items-center justify-center rounded-[var(--radius-lg)] border border-dashed border-border bg-muted text-sm text-muted-foreground">
|
|
127
135
|
Loading editor…
|
|
@@ -139,6 +147,8 @@ export function FileArtifactPane({
|
|
|
139
147
|
className={className}
|
|
140
148
|
tabs={paneTabs}
|
|
141
149
|
headerActions={headerActions}
|
|
150
|
+
headerClassName={headerClassName}
|
|
151
|
+
hideTitleBlock={hideTitleBlock}
|
|
142
152
|
markdown={content ?? ""}
|
|
143
153
|
mode={editor.mode}
|
|
144
154
|
defaultMode={editor.defaultMode}
|
|
@@ -170,6 +180,8 @@ export function FileArtifactPane({
|
|
|
170
180
|
className={className}
|
|
171
181
|
tabs={paneTabs}
|
|
172
182
|
headerActions={headerActions}
|
|
183
|
+
headerClassName={headerClassName}
|
|
184
|
+
hideTitleBlock={hideTitleBlock}
|
|
173
185
|
>
|
|
174
186
|
<FilePreview
|
|
175
187
|
filename={filename}
|
|
@@ -43,7 +43,15 @@ Markdown still renders as **prose**, not as a code block.
|
|
|
43
43
|
|
|
44
44
|
- Themed headings
|
|
45
45
|
- \`inline code\`
|
|
46
|
-
- [links](https://tangle.tools)
|
|
46
|
+
- [links](https://tangle.tools)
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
| Element | Expected |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| Body | readable foreground |
|
|
53
|
+
| Table | subtle borders |
|
|
54
|
+
| Code | tokenized accent |`
|
|
47
55
|
|
|
48
56
|
const meta: Meta<typeof FilePreview> = {
|
|
49
57
|
title: 'Files/FilePreview',
|
|
@@ -85,3 +93,16 @@ export const MarkdownProse: Story = {
|
|
|
85
93
|
name: 'Markdown (rendered prose)',
|
|
86
94
|
args: { filename: 'README.md', content: MARKDOWN_SOURCE },
|
|
87
95
|
}
|
|
96
|
+
|
|
97
|
+
export const MarkdownProseLight: Story = {
|
|
98
|
+
name: 'Markdown (light theme)',
|
|
99
|
+
parameters: { backgrounds: { default: 'light' } },
|
|
100
|
+
decorators: [
|
|
101
|
+
(Story) => (
|
|
102
|
+
<div data-theme="tangle-light" className="h-[560px] w-[760px] bg-background text-foreground">
|
|
103
|
+
<Story />
|
|
104
|
+
</div>
|
|
105
|
+
),
|
|
106
|
+
],
|
|
107
|
+
args: { filename: 'README.md', content: MARKDOWN_SOURCE },
|
|
108
|
+
}
|
|
@@ -171,7 +171,7 @@ function PdfPreview({ blobUrl, filename }: { blobUrl: string; filename: string }
|
|
|
171
171
|
|
|
172
172
|
function TextPreview({ content }: { content: string }) {
|
|
173
173
|
return (
|
|
174
|
-
<pre className="bg-
|
|
174
|
+
<pre className="bg-card rounded-[var(--radius-md)] border border-border p-4 overflow-auto max-h-[70vh] text-sm text-foreground font-mono leading-[1.55]">
|
|
175
175
|
{content}
|
|
176
176
|
</pre>
|
|
177
177
|
);
|
|
@@ -199,7 +199,7 @@ function UnsupportedPreview({
|
|
|
199
199
|
function MarkdownPreview({ content }: { content: string }) {
|
|
200
200
|
return (
|
|
201
201
|
<div className="rounded-[var(--radius-md)] border border-border bg-background p-5">
|
|
202
|
-
<Markdown
|
|
202
|
+
<Markdown>{content}</Markdown>
|
|
203
203
|
</div>
|
|
204
204
|
);
|
|
205
205
|
}
|
|
@@ -10,7 +10,7 @@ const markdownMeta: Meta<typeof Markdown> = {
|
|
|
10
10
|
parameters: { layout: 'centered', backgrounds: { default: 'dark' } },
|
|
11
11
|
decorators: [
|
|
12
12
|
(Story) => (
|
|
13
|
-
<div className="w-[680px]
|
|
13
|
+
<div className="w-[680px] rounded-xl bg-card p-6 text-foreground">
|
|
14
14
|
<Story />
|
|
15
15
|
</div>
|
|
16
16
|
),
|
|
@@ -20,6 +20,60 @@ const markdownMeta: Meta<typeof Markdown> = {
|
|
|
20
20
|
export default markdownMeta
|
|
21
21
|
type Story = StoryObj<typeof Markdown>
|
|
22
22
|
|
|
23
|
+
const CONTRAST_MARKDOWN = `# GTM Agent Repository Overview
|
|
24
|
+
|
|
25
|
+
Source: \`github.com/tangle-network/gtm-agent\` Live at: [gtm.tangle.tools](https://gtm.tangle.tools)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## What It Is
|
|
30
|
+
|
|
31
|
+
GTM Agent is an AI-powered go-to-market workspace where founders get a sandboxed environment with an AI co-founder.
|
|
32
|
+
|
|
33
|
+
## Architecture
|
|
34
|
+
|
|
35
|
+
| Layer | Owns | Location |
|
|
36
|
+
|------|------|----------|
|
|
37
|
+
| Engine | Stream normalization, DB port, harness | \`@tangle-network/agent-app\` |
|
|
38
|
+
| Shell | Auth, billing, RBAC, vault | \`src/routes/**\` |
|
|
39
|
+
| Runtime | Customer motion | Live sandbox |
|
|
40
|
+
|
|
41
|
+
## Tech Stack
|
|
42
|
+
|
|
43
|
+
- **Frontend:** Remix + Tailwind v4
|
|
44
|
+
- **Database:** SQLite + Drizzle ORM
|
|
45
|
+
- **Sandbox:** \`@tangle-network/sandbox\`
|
|
46
|
+
|
|
47
|
+
> Prime directive: ship the shell, never hardcode customer motion.
|
|
48
|
+
|
|
49
|
+
\`inline code\` stays readable beside paragraphs.
|
|
50
|
+
|
|
51
|
+
\`\`\`ts
|
|
52
|
+
export function readable(theme: 'light' | 'dark') {
|
|
53
|
+
return theme
|
|
54
|
+
}
|
|
55
|
+
\`\`\`
|
|
56
|
+
`
|
|
57
|
+
|
|
58
|
+
export const LightThemeRegression: Story = {
|
|
59
|
+
name: 'Light theme regression',
|
|
60
|
+
parameters: { backgrounds: { default: 'light' } },
|
|
61
|
+
render: () => (
|
|
62
|
+
<div data-theme="tangle-light" className="rounded-xl bg-background p-6 text-foreground">
|
|
63
|
+
<Markdown>{CONTRAST_MARKDOWN}</Markdown>
|
|
64
|
+
</div>
|
|
65
|
+
),
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const DarkThemeRegression: Story = {
|
|
69
|
+
name: 'Dark theme regression',
|
|
70
|
+
render: () => (
|
|
71
|
+
<div className="rounded-xl bg-background p-6 text-foreground">
|
|
72
|
+
<Markdown>{CONTRAST_MARKDOWN}</Markdown>
|
|
73
|
+
</div>
|
|
74
|
+
),
|
|
75
|
+
}
|
|
76
|
+
|
|
23
77
|
export const Prose: Story = {
|
|
24
78
|
name: 'Prose',
|
|
25
79
|
args: {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { render } from "@testing-library/react";
|
|
3
|
+
import { Markdown } from "./markdown";
|
|
4
|
+
|
|
5
|
+
describe("Markdown", () => {
|
|
6
|
+
it("uses the tokenized Tangle prose class instead of host typography defaults", () => {
|
|
7
|
+
const { container } = render(<Markdown>{"# Heading\n\nBody with `code`."}</Markdown>);
|
|
8
|
+
const surface = container.firstElementChild;
|
|
9
|
+
|
|
10
|
+
expect(surface).toHaveClass("tangle-prose");
|
|
11
|
+
expect(surface).not.toHaveClass("prose");
|
|
12
|
+
expect(surface).not.toHaveClass("dark:prose-invert");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("keeps inline code on semantic tokens", () => {
|
|
16
|
+
const { container } = render(<Markdown>{"Use `token` values."}</Markdown>);
|
|
17
|
+
const inlineCode = container.querySelector("code");
|
|
18
|
+
|
|
19
|
+
expect(inlineCode).toHaveClass("border-border");
|
|
20
|
+
expect(inlineCode).toHaveClass("bg-card");
|
|
21
|
+
expect(inlineCode).toHaveClass("text-[var(--code-keyword)]");
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -17,7 +17,7 @@ export interface MarkdownProps {
|
|
|
17
17
|
export const Markdown = memo(({ children, className }: MarkdownProps) => {
|
|
18
18
|
return (
|
|
19
19
|
<div
|
|
20
|
-
className={cn("
|
|
20
|
+
className={cn("tangle-prose max-w-none text-sm", className)}
|
|
21
21
|
>
|
|
22
22
|
<ReactMarkdown
|
|
23
23
|
remarkPlugins={[remarkGfm]}
|
|
@@ -14,6 +14,15 @@ export interface ArtifactPaneProps {
|
|
|
14
14
|
children?: ReactNode;
|
|
15
15
|
className?: string;
|
|
16
16
|
contentClassName?: string;
|
|
17
|
+
/** Extra classes for the header band (e.g. to align its surface with the host chrome). */
|
|
18
|
+
headerClassName?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Suppress the eyebrow/title/subtitle/meta block. Use when the host already
|
|
21
|
+
* shows the artifact's identity elsewhere (e.g. a surrounding path row), so the
|
|
22
|
+
* pane keeps only its tabs, toolbar, and header actions. The whole header row
|
|
23
|
+
* collapses when nothing else would render in it.
|
|
24
|
+
*/
|
|
25
|
+
hideTitleBlock?: boolean;
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
/**
|
|
@@ -33,8 +42,17 @@ export function ArtifactPane({
|
|
|
33
42
|
children,
|
|
34
43
|
className,
|
|
35
44
|
contentClassName,
|
|
45
|
+
headerClassName,
|
|
46
|
+
hideTitleBlock = false,
|
|
36
47
|
}: ArtifactPaneProps) {
|
|
37
48
|
const hasContent = children !== undefined && children !== null;
|
|
49
|
+
// With the title block hidden, still render the top row if there are header
|
|
50
|
+
// actions to place; the block itself just collapses to empty.
|
|
51
|
+
const showTitleRow = !hideTitleBlock || Boolean(headerActions);
|
|
52
|
+
const hasHeader = showTitleRow || Boolean(tabs) || Boolean(toolbar);
|
|
53
|
+
// The toolbar's top divider only reads as a separator when something sits
|
|
54
|
+
// above it; as the header's first row it would double the host's own border.
|
|
55
|
+
const toolbarNeedsDivider = showTitleRow || Boolean(tabs);
|
|
38
56
|
|
|
39
57
|
return (
|
|
40
58
|
<section
|
|
@@ -43,35 +61,43 @@ export function ArtifactPane({
|
|
|
43
61
|
className,
|
|
44
62
|
)}
|
|
45
63
|
>
|
|
46
|
-
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<div className="
|
|
51
|
-
{
|
|
64
|
+
{hasHeader && (
|
|
65
|
+
<header className={cn("border-b border-border bg-muted/10", headerClassName)}>
|
|
66
|
+
{showTitleRow && (
|
|
67
|
+
<div className="flex items-start justify-between gap-3 px-3 py-2">
|
|
68
|
+
<div className="min-w-0 flex-1">
|
|
69
|
+
{!hideTitleBlock && (
|
|
70
|
+
<>
|
|
71
|
+
{eyebrow && (
|
|
72
|
+
<div className="mb-1 inline-flex max-w-full items-center px-1 py-0.5 text-[10px] font-bold uppercase tracking-wider text-muted-foreground">
|
|
73
|
+
{eyebrow}
|
|
74
|
+
</div>
|
|
75
|
+
)}
|
|
76
|
+
<div className="min-w-0 text-[13px] font-medium text-foreground">
|
|
77
|
+
{title}
|
|
78
|
+
</div>
|
|
79
|
+
{(subtitle || meta) && (
|
|
80
|
+
<div className="mt-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs leading-relaxed text-muted-foreground">
|
|
81
|
+
{subtitle && <span className="truncate">{subtitle}</span>}
|
|
82
|
+
{meta && <span className="flex items-center gap-2">{meta}</span>}
|
|
83
|
+
</div>
|
|
84
|
+
)}
|
|
85
|
+
</>
|
|
86
|
+
)}
|
|
52
87
|
</div>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
88
|
+
{headerActions && (
|
|
89
|
+
<div className="flex shrink-0 items-center gap-1.5">{headerActions}</div>
|
|
90
|
+
)}
|
|
91
|
+
</div>
|
|
92
|
+
)}
|
|
93
|
+
{tabs}
|
|
94
|
+
{toolbar && (
|
|
95
|
+
<div className={cn("px-3 py-2", toolbarNeedsDivider && "border-t border-border")}>
|
|
96
|
+
{toolbar}
|
|
56
97
|
</div>
|
|
57
|
-
{(subtitle || meta) && (
|
|
58
|
-
<div className="mt-1 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-xs leading-relaxed text-muted-foreground">
|
|
59
|
-
{subtitle && <span className="truncate">{subtitle}</span>}
|
|
60
|
-
{meta && <span className="flex items-center gap-2">{meta}</span>}
|
|
61
|
-
</div>
|
|
62
|
-
)}
|
|
63
|
-
</div>
|
|
64
|
-
{headerActions && (
|
|
65
|
-
<div className="flex shrink-0 items-center gap-1.5">{headerActions}</div>
|
|
66
98
|
)}
|
|
67
|
-
</
|
|
68
|
-
|
|
69
|
-
{toolbar && (
|
|
70
|
-
<div className="border-t border-border px-3 py-2">
|
|
71
|
-
{toolbar}
|
|
72
|
-
</div>
|
|
73
|
-
)}
|
|
74
|
-
</header>
|
|
99
|
+
</header>
|
|
100
|
+
)}
|
|
75
101
|
|
|
76
102
|
<div className={cn("min-h-0 flex-1 overflow-auto", contentClassName)}>
|
|
77
103
|
{hasContent ? (
|