@admin-layout/tailwind-ui 12.2.4-alpha.15 → 12.2.4-alpha.17
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/lib/components/InputToolBar/InputToolBar.d.ts +3 -4
- package/lib/components/InputToolBar/InputToolBar.d.ts.map +1 -1
- package/lib/components/InputToolBar/InputToolBar.js +206 -30
- package/lib/components/InputToolBar/InputToolBar.js.map +1 -1
- package/lib/components/InputToolBar/defaults.d.ts +1 -1
- package/lib/components/InputToolBar/defaults.d.ts.map +1 -1
- package/lib/components/InputToolBar/defaults.js +9 -4
- package/lib/components/InputToolBar/defaults.js.map +1 -1
- package/lib/components/InputToolBar/index.d.ts +1 -1
- package/lib/components/InputToolBar/index.d.ts.map +1 -1
- package/lib/components/InputToolBar/types.d.ts +72 -19
- package/lib/components/InputToolBar/types.d.ts.map +1 -1
- package/lib/components/Markdown/MarkdownBreadcrumbs.d.ts +13 -0
- package/lib/components/Markdown/MarkdownBreadcrumbs.d.ts.map +1 -0
- package/lib/components/Markdown/MarkdownBreadcrumbs.js +27 -0
- package/lib/components/Markdown/MarkdownBreadcrumbs.js.map +1 -0
- package/lib/components/Markdown/MarkdownCopyButton.d.ts +10 -0
- package/lib/components/Markdown/MarkdownCopyButton.d.ts.map +1 -0
- package/lib/components/Markdown/MarkdownCopyButton.js +200 -0
- package/lib/components/Markdown/MarkdownCopyButton.js.map +1 -0
- package/lib/components/Markdown/MarkdownHeader.d.ts +13 -0
- package/lib/components/Markdown/MarkdownHeader.d.ts.map +1 -0
- package/lib/components/Markdown/MarkdownHeader.js +29 -0
- package/lib/components/Markdown/MarkdownHeader.js.map +1 -0
- package/lib/components/Markdown/MarkdownNavigation.d.ts +15 -0
- package/lib/components/Markdown/MarkdownNavigation.d.ts.map +1 -0
- package/lib/components/Markdown/MarkdownNavigation.js +31 -0
- package/lib/components/Markdown/MarkdownNavigation.js.map +1 -0
- package/lib/components/Markdown/MarkdownPage.d.ts +41 -0
- package/lib/components/Markdown/MarkdownPage.d.ts.map +1 -0
- package/lib/components/Markdown/MarkdownPage.js +221 -0
- package/lib/components/Markdown/MarkdownPage.js.map +1 -0
- package/lib/components/Markdown/MarkdownTableOfContents.d.ts +15 -0
- package/lib/components/Markdown/MarkdownTableOfContents.d.ts.map +1 -0
- package/lib/components/Markdown/MarkdownTableOfContents.js +51 -0
- package/lib/components/Markdown/MarkdownTableOfContents.js.map +1 -0
- package/lib/components/Markdown/index.d.ts +7 -0
- package/lib/components/Markdown/index.d.ts.map +1 -0
- package/lib/components/index.d.ts +1 -0
- package/lib/components/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React__default from'react';import {Link}from'@remix-run/react';import'../../utils/isBrowser/index.js';import {cn}from'../../utils/util.js';import'fast-deep-equal/react.js';const MarkdownBreadcrumbs = ({
|
|
2
|
+
categoryId,
|
|
3
|
+
categoryTitle,
|
|
4
|
+
markdownTitle,
|
|
5
|
+
className,
|
|
6
|
+
getHelpCenterLink,
|
|
7
|
+
getCategoryLink,
|
|
8
|
+
helpCenterLabel
|
|
9
|
+
}) => {
|
|
10
|
+
return React__default.createElement("div", {
|
|
11
|
+
className: cn('w-full max-w-[90rem] mx-auto px-4 sm:px-6 lg:px-8 xl:px-16', className)
|
|
12
|
+
}, React__default.createElement("nav", {
|
|
13
|
+
className: "flex items-center space-x-2 text-sm text-muted-foreground"
|
|
14
|
+
}, React__default.createElement(Link, {
|
|
15
|
+
to: getHelpCenterLink(),
|
|
16
|
+
className: "hover:text-foreground transition-colors"
|
|
17
|
+
}, helpCenterLabel), React__default.createElement("span", {
|
|
18
|
+
className: "text-muted-foreground/60"
|
|
19
|
+
}, "\u203A"), React__default.createElement(Link, {
|
|
20
|
+
to: getCategoryLink(categoryId),
|
|
21
|
+
className: "hover:text-foreground transition-colors"
|
|
22
|
+
}, categoryTitle || categoryId), React__default.createElement("span", {
|
|
23
|
+
className: "text-muted-foreground/60"
|
|
24
|
+
}, "\u203A"), React__default.createElement("span", {
|
|
25
|
+
className: "text-primary"
|
|
26
|
+
}, markdownTitle)));
|
|
27
|
+
};export{MarkdownBreadcrumbs};//# sourceMappingURL=MarkdownBreadcrumbs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownBreadcrumbs.js","sources":["../../../src/components/Markdown/MarkdownBreadcrumbs.tsx"],"sourcesContent":[null],"names":[],"mappings":"mLAMI,MAAA,mBAAuB,GAAA,CAAA;YACvB;eACU;eACV;AACA,EAAA,SAAA;mBACe;AAClB,EAAA,eAAA;AAED,EAAA;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface MarkdownCopyButtonProps {
|
|
3
|
+
markdownTitle: string;
|
|
4
|
+
markdownContent: string;
|
|
5
|
+
markdownUrl?: string;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const MarkdownCopyButton: React.FC<MarkdownCopyButtonProps>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=MarkdownCopyButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownCopyButton.d.ts","sourceRoot":"","sources":["../../../src/components/Markdown/MarkdownCopyButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAG3D,UAAU,uBAAuB;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAsQhE,CAAC"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import React__default,{useState,useRef,useEffect}from'react';import'../../utils/isBrowser/index.js';import {cn}from'../../utils/util.js';import'fast-deep-equal/react.js';const MarkdownCopyButton = ({
|
|
2
|
+
markdownTitle,
|
|
3
|
+
markdownContent,
|
|
4
|
+
markdownUrl,
|
|
5
|
+
className
|
|
6
|
+
}) => {
|
|
7
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
8
|
+
const [copySuccess, setCopySuccess] = useState(false);
|
|
9
|
+
const dropdownRef = useRef(null);
|
|
10
|
+
// Close dropdown when clicking outside
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const handleClickOutside = event => {
|
|
13
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
14
|
+
setIsOpen(false);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
if (isOpen) {
|
|
18
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
19
|
+
}
|
|
20
|
+
return () => {
|
|
21
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
22
|
+
};
|
|
23
|
+
}, [isOpen]);
|
|
24
|
+
// Convert HTML to Markdown (simplified version)
|
|
25
|
+
const htmlToMarkdown = html => {
|
|
26
|
+
// Remove script and style tags
|
|
27
|
+
let text = html.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '');
|
|
28
|
+
text = text.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '');
|
|
29
|
+
// Convert headings
|
|
30
|
+
text = text.replace(/<h([1-6])[^>]*>(.*?)<\/h\1>/gi, (match, level, content) => {
|
|
31
|
+
const hashes = '#'.repeat(parseInt(level));
|
|
32
|
+
return `\n${hashes} ${content.trim()}\n`;
|
|
33
|
+
});
|
|
34
|
+
// Convert bold
|
|
35
|
+
text = text.replace(/<strong[^>]*>(.*?)<\/strong>/gi, '**$1**');
|
|
36
|
+
text = text.replace(/<b[^>]*>(.*?)<\/b>/gi, '**$1**');
|
|
37
|
+
// Convert italic
|
|
38
|
+
text = text.replace(/<em[^>]*>(.*?)<\/em>/gi, '*$1*');
|
|
39
|
+
text = text.replace(/<i[^>]*>(.*?)<\/i>/gi, '*$1*');
|
|
40
|
+
// Convert links
|
|
41
|
+
text = text.replace(/<a[^>]*href=["']([^"']*)["'][^>]*>(.*?)<\/a>/gi, '[$2]($1)');
|
|
42
|
+
// Convert code blocks
|
|
43
|
+
text = text.replace(/<pre[^>]*><code[^>]*>(.*?)<\/code><\/pre>/gis, '```\n$1\n```');
|
|
44
|
+
text = text.replace(/<code[^>]*>(.*?)<\/code>/gi, '`$1`');
|
|
45
|
+
// Convert lists
|
|
46
|
+
text = text.replace(/<ul[^>]*>(.*?)<\/ul>/gis, (match, content) => {
|
|
47
|
+
const items = content.match(/<li[^>]*>(.*?)<\/li>/gis) || [];
|
|
48
|
+
return '\n' + items.map(item => {
|
|
49
|
+
const cleanItem = item.replace(/<li[^>]*>|<\/li>/gi, '').trim();
|
|
50
|
+
return `- ${cleanItem}`;
|
|
51
|
+
}).join('\n') + '\n';
|
|
52
|
+
});
|
|
53
|
+
text = text.replace(/<ol[^>]*>(.*?)<\/ol>/gis, (match, content) => {
|
|
54
|
+
const items = content.match(/<li[^>]*>(.*?)<\/li>/gis) || [];
|
|
55
|
+
return '\n' + items.map((item, index) => {
|
|
56
|
+
const cleanItem = item.replace(/<li[^>]*>|<\/li>/gi, '').trim();
|
|
57
|
+
return `${index + 1}. ${cleanItem}`;
|
|
58
|
+
}).join('\n') + '\n';
|
|
59
|
+
});
|
|
60
|
+
// Convert paragraphs
|
|
61
|
+
text = text.replace(/<p[^>]*>(.*?)<\/p>/gi, '$1\n\n');
|
|
62
|
+
// Remove remaining HTML tags
|
|
63
|
+
text = text.replace(/<[^>]+>/g, '');
|
|
64
|
+
// Decode HTML entities
|
|
65
|
+
const textarea = document.createElement('textarea');
|
|
66
|
+
textarea.innerHTML = text;
|
|
67
|
+
text = textarea.value;
|
|
68
|
+
// Clean up extra whitespace
|
|
69
|
+
text = text.replace(/\n{3,}/g, '\n\n').trim();
|
|
70
|
+
return `# ${markdownTitle}\n\n${text}`;
|
|
71
|
+
};
|
|
72
|
+
const handleCopyMarkdown = async () => {
|
|
73
|
+
try {
|
|
74
|
+
const markdown = htmlToMarkdown(markdownContent);
|
|
75
|
+
await navigator.clipboard.writeText(markdown);
|
|
76
|
+
setCopySuccess(true);
|
|
77
|
+
setIsOpen(false);
|
|
78
|
+
setTimeout(() => setCopySuccess(false), 2000);
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.error('Failed to copy:', err);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const handleOpenChatGPT = () => {
|
|
84
|
+
const url = `https://chat.openai.com/?q=${encodeURIComponent(markdownTitle)}`;
|
|
85
|
+
window.open(url, '_blank');
|
|
86
|
+
setIsOpen(false);
|
|
87
|
+
};
|
|
88
|
+
const handleOpenClaude = () => {
|
|
89
|
+
const url = `https://claude.ai/?q=${encodeURIComponent(markdownTitle)}`;
|
|
90
|
+
window.open(url, '_blank');
|
|
91
|
+
setIsOpen(false);
|
|
92
|
+
};
|
|
93
|
+
return React__default.createElement("div", {
|
|
94
|
+
className: cn('relative inline-flex items-center rounded-md border border-border bg-background', className),
|
|
95
|
+
ref: dropdownRef
|
|
96
|
+
}, React__default.createElement("div", {
|
|
97
|
+
className: "flex items-center overflow-hidden rounded-md"
|
|
98
|
+
}, React__default.createElement("button", {
|
|
99
|
+
onClick: handleCopyMarkdown,
|
|
100
|
+
className: cn('flex items-center gap-2 px-3 py-1.5', 'bg-background hover:bg-muted/50 transition-colors', 'text-sm text-foreground', 'border-0')
|
|
101
|
+
}, React__default.createElement("svg", {
|
|
102
|
+
className: "w-4 h-4",
|
|
103
|
+
fill: "none",
|
|
104
|
+
stroke: "currentColor",
|
|
105
|
+
viewBox: "0 0 24 24",
|
|
106
|
+
xmlns: "http://www.w3.org/2000/svg"
|
|
107
|
+
}, React__default.createElement("path", {
|
|
108
|
+
strokeLinecap: "round",
|
|
109
|
+
strokeLinejoin: "round",
|
|
110
|
+
strokeWidth: 2,
|
|
111
|
+
d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
|
|
112
|
+
})), React__default.createElement("span", null, copySuccess ? 'Copied' : 'Copy page')), React__default.createElement("div", {
|
|
113
|
+
className: "h-5 w-px bg-border"
|
|
114
|
+
}), React__default.createElement("button", {
|
|
115
|
+
onClick: e => {
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
setIsOpen(!isOpen);
|
|
118
|
+
},
|
|
119
|
+
className: cn('flex items-center justify-center px-2 py-1.5', 'bg-background hover:bg-muted/50 transition-colors', 'text-sm text-foreground', 'border-0')
|
|
120
|
+
}, React__default.createElement("svg", {
|
|
121
|
+
className: cn('w-3 h-3 transition-transform', isOpen && 'rotate-180'),
|
|
122
|
+
fill: "none",
|
|
123
|
+
stroke: "currentColor",
|
|
124
|
+
viewBox: "0 0 24 24"
|
|
125
|
+
}, React__default.createElement("path", {
|
|
126
|
+
strokeLinecap: "round",
|
|
127
|
+
strokeLinejoin: "round",
|
|
128
|
+
strokeWidth: 2,
|
|
129
|
+
d: "M19 9l-7 7-7-7"
|
|
130
|
+
})))), isOpen && React__default.createElement("div", {
|
|
131
|
+
className: "absolute right-0 top-full mt-2 w-64 bg-background border border-border rounded-lg shadow-lg z-[100] overflow-hidden"
|
|
132
|
+
}, React__default.createElement("div", {
|
|
133
|
+
className: "py-1"
|
|
134
|
+
}, React__default.createElement("button", {
|
|
135
|
+
onClick: handleCopyMarkdown,
|
|
136
|
+
className: "w-full px-4 py-3 text-left hover:bg-muted/50 transition-colors flex items-start gap-3 group"
|
|
137
|
+
}, React__default.createElement("svg", {
|
|
138
|
+
className: "w-5 h-5 text-muted-foreground group-hover:text-foreground mt-0.5 flex-shrink-0",
|
|
139
|
+
fill: "none",
|
|
140
|
+
stroke: "currentColor",
|
|
141
|
+
viewBox: "0 0 24 24"
|
|
142
|
+
}, React__default.createElement("path", {
|
|
143
|
+
strokeLinecap: "round",
|
|
144
|
+
strokeLinejoin: "round",
|
|
145
|
+
strokeWidth: 2,
|
|
146
|
+
d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
|
|
147
|
+
})), React__default.createElement("div", {
|
|
148
|
+
className: "flex-1 min-w-0"
|
|
149
|
+
}, React__default.createElement("div", {
|
|
150
|
+
className: "text-sm font-medium text-foreground"
|
|
151
|
+
}, "Copy page"), React__default.createElement("div", {
|
|
152
|
+
className: "text-xs text-muted-foreground mt-0.5"
|
|
153
|
+
}, "Copy page as Markdown for LLMs"))), React__default.createElement("button", {
|
|
154
|
+
onClick: handleOpenChatGPT,
|
|
155
|
+
className: "w-full px-4 py-3 text-left hover:bg-muted/50 transition-colors flex items-start gap-3 group"
|
|
156
|
+
}, React__default.createElement("div", {
|
|
157
|
+
className: "w-5 h-5 mt-0.5 flex-shrink-0 flex items-center justify-center"
|
|
158
|
+
}, React__default.createElement("span", {
|
|
159
|
+
className: "text-lg"
|
|
160
|
+
}, "\uD83E\uDD16")), React__default.createElement("div", {
|
|
161
|
+
className: "flex-1 min-w-0"
|
|
162
|
+
}, React__default.createElement("div", {
|
|
163
|
+
className: "text-sm font-medium text-foreground"
|
|
164
|
+
}, "Open in ChatGPT"), React__default.createElement("div", {
|
|
165
|
+
className: "text-xs text-muted-foreground mt-0.5"
|
|
166
|
+
}, "Ask questions about this page")), React__default.createElement("svg", {
|
|
167
|
+
className: "w-4 h-4 text-muted-foreground group-hover:text-foreground mt-1 flex-shrink-0",
|
|
168
|
+
fill: "none",
|
|
169
|
+
stroke: "currentColor",
|
|
170
|
+
viewBox: "0 0 24 24"
|
|
171
|
+
}, React__default.createElement("path", {
|
|
172
|
+
strokeLinecap: "round",
|
|
173
|
+
strokeLinejoin: "round",
|
|
174
|
+
strokeWidth: 2,
|
|
175
|
+
d: "M9 5l7 7-7 7"
|
|
176
|
+
}))), React__default.createElement("button", {
|
|
177
|
+
onClick: handleOpenClaude,
|
|
178
|
+
className: "w-full px-4 py-3 text-left hover:bg-muted/50 transition-colors flex items-start gap-3 group"
|
|
179
|
+
}, React__default.createElement("div", {
|
|
180
|
+
className: "w-5 h-5 mt-0.5 flex-shrink-0 flex items-center justify-center"
|
|
181
|
+
}, React__default.createElement("span", {
|
|
182
|
+
className: "text-lg"
|
|
183
|
+
}, "\u2744\uFE0F")), React__default.createElement("div", {
|
|
184
|
+
className: "flex-1 min-w-0"
|
|
185
|
+
}, React__default.createElement("div", {
|
|
186
|
+
className: "text-sm font-medium text-foreground"
|
|
187
|
+
}, "Open in Claude"), React__default.createElement("div", {
|
|
188
|
+
className: "text-xs text-muted-foreground mt-0.5"
|
|
189
|
+
}, "Ask questions about this page")), React__default.createElement("svg", {
|
|
190
|
+
className: "w-4 h-4 text-muted-foreground group-hover:text-foreground mt-1 flex-shrink-0",
|
|
191
|
+
fill: "none",
|
|
192
|
+
stroke: "currentColor",
|
|
193
|
+
viewBox: "0 0 24 24"
|
|
194
|
+
}, React__default.createElement("path", {
|
|
195
|
+
strokeLinecap: "round",
|
|
196
|
+
strokeLinejoin: "round",
|
|
197
|
+
strokeWidth: 2,
|
|
198
|
+
d: "M9 5l7 7-7 7"
|
|
199
|
+
}))))));
|
|
200
|
+
};export{MarkdownCopyButton};//# sourceMappingURL=MarkdownCopyButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownCopyButton.js","sources":["../../../src/components/Markdown/MarkdownCopyButton.tsx"],"sourcesContent":[null],"names":[],"mappings":"0KAII,MAAA,kBAAsB,GAAA,CAAA;eACtB;iBACY;aACH;AACZ,EAAA;AAED,CAAA,KAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface MarkdownHeaderProps {
|
|
3
|
+
categoryTitle?: string;
|
|
4
|
+
title: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
author?: string;
|
|
7
|
+
updatedAt?: string;
|
|
8
|
+
markdownContent: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const MarkdownHeader: React.FC<MarkdownHeaderProps>;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=MarkdownHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownHeader.d.ts","sourceRoot":"","sources":["../../../src/components/Markdown/MarkdownHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,mBAAmB;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAmDxD,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React__default from'react';import'../../utils/isBrowser/index.js';import {cn}from'../../utils/util.js';import'fast-deep-equal/react.js';const MarkdownHeader = ({
|
|
2
|
+
categoryTitle,
|
|
3
|
+
title,
|
|
4
|
+
description,
|
|
5
|
+
author,
|
|
6
|
+
updatedAt,
|
|
7
|
+
markdownContent,
|
|
8
|
+
className
|
|
9
|
+
}) => {
|
|
10
|
+
return React__default.createElement("div", {
|
|
11
|
+
className: cn('mb-10', className)
|
|
12
|
+
}, categoryTitle && React__default.createElement("div", {
|
|
13
|
+
className: "text-[11px] font-semibold tracking-[0.16em] uppercase text-primary mb-3"
|
|
14
|
+
}, categoryTitle), React__default.createElement("div", {
|
|
15
|
+
className: "flex items-start justify-between gap-4 mb-5"
|
|
16
|
+
}, React__default.createElement("h1", {
|
|
17
|
+
className: "text-[2.4rem] md:text-[2.9rem] lg:text-[3.1rem] font-semibold text-foreground leading-tight tracking-tight flex-1"
|
|
18
|
+
}, title)), description && React__default.createElement("p", {
|
|
19
|
+
className: "text-[1.15rem] md:text-[1.3rem] text-muted-foreground mb-8 leading-relaxed font-normal max-w-3xl"
|
|
20
|
+
}, description), (author || updatedAt) && React__default.createElement("div", {
|
|
21
|
+
className: "flex items-center space-x-4 text-sm text-muted-foreground"
|
|
22
|
+
}, author && React__default.createElement(React__default.Fragment, null, React__default.createElement("div", {
|
|
23
|
+
className: "flex items-center"
|
|
24
|
+
}, React__default.createElement("div", {
|
|
25
|
+
className: "mr-2 flex h-6 w-6 items-center justify-center rounded-full bg-muted text-xs text-foreground font-medium"
|
|
26
|
+
}, author.charAt(0)), React__default.createElement("span", null, "Written by ", author)), updatedAt && React__default.createElement("span", {
|
|
27
|
+
className: "text-muted-foreground/60"
|
|
28
|
+
}, "\u2022")), updatedAt && React__default.createElement("span", null, "Updated ", updatedAt)));
|
|
29
|
+
};export{MarkdownHeader};//# sourceMappingURL=MarkdownHeader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownHeader.js","sources":["../../../src/components/Markdown/MarkdownHeader.tsx"],"sourcesContent":[null],"names":[],"mappings":"+IAII,MAAA,cAAuB,GAAA,CAAA;;OAEvB;aACS;QACT;WACA;iBACY;AACf,EAAA;AAED,CAAA,KAAA;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface Markdown {
|
|
3
|
+
categoryId: string;
|
|
4
|
+
slug: string;
|
|
5
|
+
title: string;
|
|
6
|
+
}
|
|
7
|
+
interface MarkdownNavigationProps {
|
|
8
|
+
previousMarkdown?: Markdown | null;
|
|
9
|
+
nextMarkdown?: Markdown | null;
|
|
10
|
+
className?: string;
|
|
11
|
+
getMarkdownLink: (categoryId: string, slug: string) => string;
|
|
12
|
+
}
|
|
13
|
+
export declare const MarkdownNavigation: React.FC<MarkdownNavigationProps>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=MarkdownNavigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownNavigation.d.ts","sourceRoot":"","sources":["../../../src/components/Markdown/MarkdownNavigation.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,QAAQ;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,uBAAuB;IAC7B,gBAAgB,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACnC,YAAY,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACjE;AAED,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA+ChE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React__default from'react';import {Link}from'@remix-run/react';import'../../utils/isBrowser/index.js';import {cn}from'../../utils/util.js';import'fast-deep-equal/react.js';const MarkdownNavigation = ({
|
|
2
|
+
previousMarkdown,
|
|
3
|
+
nextMarkdown,
|
|
4
|
+
className,
|
|
5
|
+
getMarkdownLink
|
|
6
|
+
}) => {
|
|
7
|
+
if (!previousMarkdown && !nextMarkdown) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return React__default.createElement("div", {
|
|
11
|
+
className: cn('mt-16 pt-8 border-t border-border grid grid-cols-1 md:grid-cols-2 gap-6', className)
|
|
12
|
+
}, previousMarkdown ? React__default.createElement(Link, {
|
|
13
|
+
to: getMarkdownLink(previousMarkdown.categoryId, previousMarkdown.slug),
|
|
14
|
+
className: cn('group rounded-lg border border-border bg-background px-6 py-5', 'hover:bg-muted/30 transition-colors')
|
|
15
|
+
}, React__default.createElement("div", {
|
|
16
|
+
className: "text-sm text-muted-foreground mb-1"
|
|
17
|
+
}, "Previous"), React__default.createElement("div", {
|
|
18
|
+
className: "text-primary font-semibold group-hover:underline text-base"
|
|
19
|
+
}, "\u00AB ", previousMarkdown.title)) : React__default.createElement("div", {
|
|
20
|
+
className: "hidden md:block"
|
|
21
|
+
}), nextMarkdown ? React__default.createElement(Link, {
|
|
22
|
+
to: getMarkdownLink(nextMarkdown.categoryId, nextMarkdown.slug),
|
|
23
|
+
className: cn('group rounded-lg border border-border bg-background px-6 py-5', 'hover:bg-muted/30 transition-colors md:text-right')
|
|
24
|
+
}, React__default.createElement("div", {
|
|
25
|
+
className: "text-sm text-muted-foreground mb-1"
|
|
26
|
+
}, "Next"), React__default.createElement("div", {
|
|
27
|
+
className: "text-primary font-semibold group-hover:underline text-base"
|
|
28
|
+
}, nextMarkdown.title, " \u00BB")) : React__default.createElement("div", {
|
|
29
|
+
className: "hidden md:block"
|
|
30
|
+
}));
|
|
31
|
+
};export{MarkdownNavigation};//# sourceMappingURL=MarkdownNavigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownNavigation.js","sources":["../../../src/components/Markdown/MarkdownNavigation.tsx"],"sourcesContent":[null],"names":["React"],"mappings":"2MAMiB,GAAA,CAAA;kBACC;AACjB,EAAA,YAAA;AAED,EAAA,SAAU;AACN,EAAA;AACA,CAAA,KAAA;MACA,CAAA,gBAAmB,IAAA,CAAA,YAAA,EAAA;IACnB,OAAA,IAAA;AACH,EAAA;AAED,EAAA,OAAAA,cAAA,CAAO;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface Heading {
|
|
3
|
+
id: string;
|
|
4
|
+
text: string;
|
|
5
|
+
level: number;
|
|
6
|
+
}
|
|
7
|
+
export interface Markdown {
|
|
8
|
+
id: string;
|
|
9
|
+
title: string;
|
|
10
|
+
description: string;
|
|
11
|
+
slug: string;
|
|
12
|
+
author: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
categoryId: string;
|
|
15
|
+
content: string;
|
|
16
|
+
htmlContent: string;
|
|
17
|
+
headings: Heading[];
|
|
18
|
+
}
|
|
19
|
+
export interface NavigationItem {
|
|
20
|
+
categoryId: string;
|
|
21
|
+
slug: string;
|
|
22
|
+
title: string;
|
|
23
|
+
}
|
|
24
|
+
interface MarkdownPageProps {
|
|
25
|
+
article?: Markdown | null;
|
|
26
|
+
categoryId?: string;
|
|
27
|
+
categoryTitle?: string;
|
|
28
|
+
articleSlug?: string;
|
|
29
|
+
loadArticle?: (slug: string) => Promise<Markdown | null>;
|
|
30
|
+
previousMarkdown?: NavigationItem | null;
|
|
31
|
+
nextMarkdown?: NavigationItem | null;
|
|
32
|
+
getMarkdownLink: (categoryId: string, slug: string) => string;
|
|
33
|
+
getCategoryLink: (categoryId: string) => string;
|
|
34
|
+
getHelpCenterLink: () => string;
|
|
35
|
+
helpCenterLabel: string;
|
|
36
|
+
backToHelpCenterLabel?: string;
|
|
37
|
+
className?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare const MarkdownPage: React.FC<MarkdownPageProps>;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=MarkdownPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownPage.d.ts","sourceRoot":"","sources":["../../../src/components/Markdown/MarkdownPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAS3D,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,iBAAiB;IACvB,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IACzD,gBAAgB,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACzC,YAAY,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9D,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAChD,iBAAiB,EAAE,MAAM,MAAM,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAwQpD,CAAC"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import React__default,{useState,useRef,useEffect}from'react';import {Link}from'@remix-run/react';import'../../utils/isBrowser/index.js';import {cn}from'../../utils/util.js';import'fast-deep-equal/react.js';import {MarkdownTableOfContents}from'./MarkdownTableOfContents.js';import {MarkdownNavigation}from'./MarkdownNavigation.js';import {MarkdownBreadcrumbs}from'./MarkdownBreadcrumbs.js';import {MarkdownCopyButton}from'./MarkdownCopyButton.js';const MarkdownPage = ({
|
|
2
|
+
article: articleProp,
|
|
3
|
+
categoryId: categoryIdProp,
|
|
4
|
+
categoryTitle: categoryTitleProp,
|
|
5
|
+
articleSlug,
|
|
6
|
+
loadArticle,
|
|
7
|
+
previousMarkdown: previousMarkdownProp,
|
|
8
|
+
nextMarkdown: nextMarkdownProp,
|
|
9
|
+
getMarkdownLink,
|
|
10
|
+
getCategoryLink,
|
|
11
|
+
getHelpCenterLink,
|
|
12
|
+
helpCenterLabel,
|
|
13
|
+
backToHelpCenterLabel,
|
|
14
|
+
className
|
|
15
|
+
}) => {
|
|
16
|
+
const [article, setArticle] = useState(articleProp || null);
|
|
17
|
+
const [loading, setLoading] = useState(!articleProp && !!articleSlug);
|
|
18
|
+
const [activeHeadingId, setActiveHeadingId] = useState('');
|
|
19
|
+
const observerRef = useRef(null);
|
|
20
|
+
const isScrollingRef = useRef(false);
|
|
21
|
+
const scrollTimeoutRef = useRef(null);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (articleProp) {
|
|
24
|
+
setArticle(articleProp);
|
|
25
|
+
setLoading(false);
|
|
26
|
+
} else if (articleSlug && loadArticle) {
|
|
27
|
+
const loadContent = async () => {
|
|
28
|
+
const articleData = await loadArticle(articleSlug);
|
|
29
|
+
setArticle(articleData);
|
|
30
|
+
setLoading(false);
|
|
31
|
+
};
|
|
32
|
+
loadContent();
|
|
33
|
+
} else if (!articleProp && !articleSlug) {
|
|
34
|
+
setLoading(false);
|
|
35
|
+
}
|
|
36
|
+
}, [articleProp, articleSlug, loadArticle]);
|
|
37
|
+
// Scroll spy functionality
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!article?.headings || article.headings.length === 0) return;
|
|
40
|
+
// Clean up previous observer
|
|
41
|
+
if (observerRef.current) {
|
|
42
|
+
observerRef.current.disconnect();
|
|
43
|
+
}
|
|
44
|
+
// Create new intersection observer
|
|
45
|
+
observerRef.current = new IntersectionObserver(entries => {
|
|
46
|
+
// Don't update if we're programmatically scrolling
|
|
47
|
+
if (isScrollingRef.current) return;
|
|
48
|
+
// Find the heading that's most visible in the viewport
|
|
49
|
+
const visibleEntries = entries.filter(entry => entry.isIntersecting);
|
|
50
|
+
if (visibleEntries.length === 0) return;
|
|
51
|
+
// Find the heading that's closest to the top of the viewport (within the top 30%)
|
|
52
|
+
// Prioritize headings that are in the upper portion of the viewport
|
|
53
|
+
let bestEntry = visibleEntries[0];
|
|
54
|
+
let bestScore = Infinity;
|
|
55
|
+
visibleEntries.forEach(entry => {
|
|
56
|
+
const rect = entry.boundingClientRect;
|
|
57
|
+
const viewportHeight = window.innerHeight;
|
|
58
|
+
const top30Percent = viewportHeight * 0.3;
|
|
59
|
+
// Calculate a score: lower is better
|
|
60
|
+
// Headings in the top 30% of viewport get priority
|
|
61
|
+
let score;
|
|
62
|
+
if (rect.top >= 0 && rect.top <= top30Percent) {
|
|
63
|
+
// Heading is in the top 30% - prioritize by distance from top
|
|
64
|
+
score = rect.top;
|
|
65
|
+
} else if (rect.top >= 0) {
|
|
66
|
+
// Heading is below top 30% but visible - lower priority
|
|
67
|
+
score = 1000 + rect.top;
|
|
68
|
+
} else {
|
|
69
|
+
// Heading is above viewport - lowest priority unless it's the only one
|
|
70
|
+
score = 2000 + Math.abs(rect.top);
|
|
71
|
+
}
|
|
72
|
+
if (score < bestScore) {
|
|
73
|
+
bestScore = score;
|
|
74
|
+
bestEntry = entry;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
setActiveHeadingId(bestEntry.target.id);
|
|
78
|
+
}, {
|
|
79
|
+
rootMargin: '-10% 0px -70% 0px',
|
|
80
|
+
threshold: [0, 0.1, 0.5, 1]
|
|
81
|
+
});
|
|
82
|
+
// Observe all headings
|
|
83
|
+
article.headings.forEach(heading => {
|
|
84
|
+
const element = document.getElementById(heading.id);
|
|
85
|
+
if (element && observerRef.current) {
|
|
86
|
+
observerRef.current.observe(element);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
// Cleanup function
|
|
90
|
+
return () => {
|
|
91
|
+
if (observerRef.current) {
|
|
92
|
+
observerRef.current.disconnect();
|
|
93
|
+
}
|
|
94
|
+
if (scrollTimeoutRef.current) {
|
|
95
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}, [article]);
|
|
99
|
+
if (loading) {
|
|
100
|
+
return React__default.createElement("div", {
|
|
101
|
+
className: "min-h-screen bg-background text-foreground overflow-x-hidden"
|
|
102
|
+
}, React__default.createElement("div", {
|
|
103
|
+
className: "w-full max-w-[90rem] mx-auto px-4 sm:px-6 lg:px-8 xl:px-16 py-16"
|
|
104
|
+
}, React__default.createElement("div", {
|
|
105
|
+
className: "animate-pulse"
|
|
106
|
+
}, React__default.createElement("div", {
|
|
107
|
+
className: "h-8 bg-muted rounded w-1/3 mb-4"
|
|
108
|
+
}), React__default.createElement("div", {
|
|
109
|
+
className: "h-4 bg-muted rounded w-1/2 mb-8"
|
|
110
|
+
}), React__default.createElement("div", {
|
|
111
|
+
className: "space-y-4"
|
|
112
|
+
}, React__default.createElement("div", {
|
|
113
|
+
className: "h-4 bg-muted rounded"
|
|
114
|
+
}), React__default.createElement("div", {
|
|
115
|
+
className: "h-4 bg-muted rounded w-5/6"
|
|
116
|
+
}), React__default.createElement("div", {
|
|
117
|
+
className: "h-4 bg-muted rounded w-4/6"
|
|
118
|
+
})))));
|
|
119
|
+
}
|
|
120
|
+
if (!article) {
|
|
121
|
+
return React__default.createElement("div", {
|
|
122
|
+
className: "min-h-screen bg-background text-foreground mt-20 overflow-x-hidden"
|
|
123
|
+
}, React__default.createElement("div", {
|
|
124
|
+
className: "w-full max-w-[90rem] mx-auto px-4 sm:px-6 lg:px-8 xl:px-16 py-16"
|
|
125
|
+
}, React__default.createElement("h1", {
|
|
126
|
+
className: "text-2xl font-bold"
|
|
127
|
+
}, "Article not found"), React__default.createElement(Link, {
|
|
128
|
+
to: getHelpCenterLink(),
|
|
129
|
+
className: "mt-4 text-primary hover:text-primary/80"
|
|
130
|
+
}, backToHelpCenterLabel || `← Back to ${helpCenterLabel}`)));
|
|
131
|
+
}
|
|
132
|
+
// Use previous/next articles from props
|
|
133
|
+
const previousMarkdown = previousMarkdownProp;
|
|
134
|
+
const nextMarkdown = nextMarkdownProp;
|
|
135
|
+
return React__default.createElement("div", {
|
|
136
|
+
className: cn('min-h-screen bg-background text-foreground scroll-smooth overflow-x-hidden', className)
|
|
137
|
+
}, React__default.createElement("div", {
|
|
138
|
+
className: "flex w-full justify-center gap-10"
|
|
139
|
+
}, React__default.createElement("div", {
|
|
140
|
+
className: "flex-1 max-w-3xl w-full"
|
|
141
|
+
}, React__default.createElement("div", {
|
|
142
|
+
className: "flex items-center justify-between"
|
|
143
|
+
}, React__default.createElement(MarkdownBreadcrumbs, {
|
|
144
|
+
categoryId: article.categoryId || categoryIdProp || '',
|
|
145
|
+
categoryTitle: categoryTitleProp,
|
|
146
|
+
markdownTitle: article.title,
|
|
147
|
+
className: "pb-4",
|
|
148
|
+
getHelpCenterLink: getHelpCenterLink,
|
|
149
|
+
getCategoryLink: getCategoryLink,
|
|
150
|
+
helpCenterLabel: helpCenterLabel
|
|
151
|
+
}), React__default.createElement(MarkdownCopyButton, {
|
|
152
|
+
markdownTitle: article.title,
|
|
153
|
+
markdownContent: article.htmlContent,
|
|
154
|
+
className: "flex-shrink-0"
|
|
155
|
+
})), React__default.createElement("main", {
|
|
156
|
+
className: "w-full py-2"
|
|
157
|
+
}, React__default.createElement("div", {
|
|
158
|
+
className: "max-w-[90rem] mx-auto px-4 sm:px-6 lg:px-8 xl:px-16 relative"
|
|
159
|
+
}, React__default.createElement("div", {
|
|
160
|
+
className: "flex flex-col xl:flex-row gap-12 xl:gap-16 align-start"
|
|
161
|
+
}, React__default.createElement("div", {
|
|
162
|
+
className: "flex-1 min-w-0 max-w-5xl"
|
|
163
|
+
}, React__default.createElement("div", {
|
|
164
|
+
className: "prose prose-lg max-w-none w-full overflow-x-hidden"
|
|
165
|
+
}, React__default.createElement("div", {
|
|
166
|
+
className: cn(
|
|
167
|
+
// Base prose styles
|
|
168
|
+
'prose-headings:font-semibold prose-headings:text-foreground prose-headings:tracking-tight',
|
|
169
|
+
// Body H1 styles (within article) - slightly smaller than page title
|
|
170
|
+
'prose-h1:text-[1.5rem] prose-h1:md:text-[1.75rem] prose-h1:mb-4 prose-h1:mt-5 prose-h1:leading-tight',
|
|
171
|
+
// H2 styles - strong section headings
|
|
172
|
+
'prose-h2:text-[1.2rem] prose-h2:md:text-[1.5rem] prose-h2:mb-4 prose-h2:mt-5 prose-h2:leading-tight',
|
|
173
|
+
// H3 styles - sub section headings
|
|
174
|
+
'prose-h3:text-[1.05rem] prose-h3:md:text-[1.25rem] prose-h3:mb-3 prose-h3:mt-4 prose-h3:leading-snug',
|
|
175
|
+
// H4 styles
|
|
176
|
+
'prose-h4:text-lg prose-h4:md:text-xl prose-h4:mb-3 prose-h4:mt-4',
|
|
177
|
+
// Paragraph styles
|
|
178
|
+
'prose-p:text-[0.85rem] prose-p:md:text-[0.95rem] prose-p:text-muted-foreground prose-p:leading-relaxed prose-p:mb-5',
|
|
179
|
+
// Strong text
|
|
180
|
+
'prose-strong:text-foreground prose-strong:font-semibold',
|
|
181
|
+
// Links
|
|
182
|
+
'prose-a:text-primary prose-a:no-underline hover:prose-a:underline prose-a:font-medium',
|
|
183
|
+
// Lists
|
|
184
|
+
'prose-ul:text-muted-foreground prose-ol:text-muted-foreground prose-li:text-muted-foreground prose-li:mb-2 prose-li:text-base prose-li:md:text-lg',
|
|
185
|
+
// Blockquotes
|
|
186
|
+
'prose-blockquote:text-muted-foreground prose-blockquote:border-l-primary prose-blockquote:pl-4 prose-blockquote:my-6',
|
|
187
|
+
// Code
|
|
188
|
+
'prose-code:text-foreground prose-code:bg-muted prose-code:px-1.5 prose-code:py-0.5 prose-code:rounded prose-code:text-sm prose-code:font-mono',
|
|
189
|
+
// Pre blocks
|
|
190
|
+
'prose-pre:bg-muted prose-pre:text-foreground prose-pre:overflow-x-auto prose-pre:rounded-lg prose-pre:p-4 prose-pre:my-6',
|
|
191
|
+
// Images
|
|
192
|
+
'prose-img:rounded-lg prose-img:my-8',
|
|
193
|
+
// Tables
|
|
194
|
+
'prose-table:text-muted-foreground prose-th:text-foreground prose-th:font-semibold',
|
|
195
|
+
// Horizontal rules
|
|
196
|
+
'prose-hr:border-border prose-hr:my-8'),
|
|
197
|
+
dangerouslySetInnerHTML: {
|
|
198
|
+
__html: article.htmlContent
|
|
199
|
+
}
|
|
200
|
+
})), React__default.createElement(MarkdownNavigation, {
|
|
201
|
+
previousMarkdown: previousMarkdown,
|
|
202
|
+
nextMarkdown: nextMarkdown,
|
|
203
|
+
getMarkdownLink: getMarkdownLink
|
|
204
|
+
})))))), React__default.createElement(MarkdownTableOfContents, {
|
|
205
|
+
headings: article.headings || [],
|
|
206
|
+
activeHeadingId: activeHeadingId,
|
|
207
|
+
onHeadingClick: headingId => {
|
|
208
|
+
// Set scrolling flag to prevent observer from overriding
|
|
209
|
+
isScrollingRef.current = true;
|
|
210
|
+
setActiveHeadingId(headingId);
|
|
211
|
+
// Clear any existing timeout
|
|
212
|
+
if (scrollTimeoutRef.current) {
|
|
213
|
+
clearTimeout(scrollTimeoutRef.current);
|
|
214
|
+
}
|
|
215
|
+
// Re-enable observer after scroll completes (smooth scroll takes ~500ms)
|
|
216
|
+
scrollTimeoutRef.current = setTimeout(() => {
|
|
217
|
+
isScrollingRef.current = false;
|
|
218
|
+
}, 800);
|
|
219
|
+
}
|
|
220
|
+
})));
|
|
221
|
+
};export{MarkdownPage};//# sourceMappingURL=MarkdownPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownPage.js","sources":["../../../src/components/Markdown/MarkdownPage.tsx"],"sourcesContent":[null],"names":[],"mappings":"gdAiBkB,GAAA,CAAA;SACd,EAAA;4BACa;kCACE;aACN;aACT;oBACgB,oBAAA;cAChB,EAAW,gBAAS;iBACV;AACb,EAAA,eAAA;AAED,EAAA,iBAAiB;;uBAEA;;AAEhB,CAAA,KAAA;AAED,EAAA,MAAA,CAAA,OAAU,EAAA,UAAiB,CAAA,GAAA,QAAA,CAAA,WAAA,IAAA,IAAA,CAAA;AACvB,EAAA,MAAA,CAAA,OAAU,EAAA,WAAe,GAAC,QAAA,CAAA,CAAA,WAAA,IAAA,CAAA,CAAA,WAAA,CAAA;QAC1B,CAAA,eAAoB,EAAA,kBAAA,CAAA,GAAA,QAAA,CAAA,EAAA,CAAA;QACpB,WAAc,GAAE,MAAO,CAAA,IAAA,CAAA;QACvB,cAAc,GAAO,MAAA,CAAA,KAAA,CAAA;AACrB,EAAA,MAAA,gBAAmB,GAAE,MAAM,CAAA,IAAK,CAAA;AAChC,EAAA,SAAA,CAAA,MAAA;AACA,IAAA,IAAA,WAAe,EAAA;MACf,UAAA,CAAA,WAAkB,CAAA;AAClB,MAAA,UAAA,CAAA,KAAkB,CAAA;IAClB,CAAA,MAAA,IAAA,WAAmB,IAAM,WAAO,EAAA;MAChC,MAAA,0BAAwB;QACxB,MAAA,WAAqB,GAAG,MAAM,WAAC,CAAA,WAAA,CAAA;QAC/B,UAAY,CAAA,WAAO,CAAA;AACtB,QAAA,UAAA,CAAA,KAAA,CAAA;AAED,MAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface Heading {
|
|
3
|
+
id: string;
|
|
4
|
+
text: string;
|
|
5
|
+
level: number;
|
|
6
|
+
}
|
|
7
|
+
interface MarkdownTableOfContentsProps {
|
|
8
|
+
headings: Heading[];
|
|
9
|
+
activeHeadingId: string;
|
|
10
|
+
onHeadingClick?: (headingId: string) => void;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare const MarkdownTableOfContents: React.FC<MarkdownTableOfContentsProps>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=MarkdownTableOfContents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownTableOfContents.d.ts","sourceRoot":"","sources":["../../../src/components/Markdown/MarkdownTableOfContents.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,UAAU,OAAO;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,4BAA4B;IAClC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC,4BAA4B,CA6E1E,CAAC"}
|