doccupine 0.0.82 → 0.0.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/layout.js +16 -11
- package/dist/lib/structures.js +8 -2
- package/dist/templates/app/robots.d.ts +1 -0
- package/dist/templates/app/robots.js +11 -0
- package/dist/templates/app/theme.d.ts +1 -1
- package/dist/templates/app/theme.js +1 -1
- package/dist/templates/components/Docs.d.ts +1 -1
- package/dist/templates/components/Docs.js +1 -1
- package/dist/templates/components/DocsSideBar.d.ts +1 -1
- package/dist/templates/components/DocsSideBar.js +11 -8
- package/dist/templates/components/PostHogProvider.d.ts +1 -1
- package/dist/templates/components/PostHogProvider.js +9 -62
- package/dist/templates/components/PostHogProviderLazy.d.ts +1 -0
- package/dist/templates/components/PostHogProviderLazy.js +70 -0
- package/dist/templates/components/SearchDocs.d.ts +1 -1
- package/dist/templates/components/SearchDocs.js +40 -270
- package/dist/templates/components/SearchModalContent.d.ts +1 -0
- package/dist/templates/components/SearchModalContent.js +326 -0
- package/dist/templates/components/SideBar.d.ts +1 -1
- package/dist/templates/components/SideBar.js +5 -1
- package/dist/templates/components/layout/DocsComponents.d.ts +1 -1
- package/dist/templates/components/layout/DocsComponents.js +1 -1
- package/dist/templates/components/layout/DocsNavigation.d.ts +1 -1
- package/dist/templates/components/layout/DocsNavigation.js +1 -1
- package/dist/templates/components/layout/Footer.d.ts +1 -1
- package/dist/templates/components/layout/Footer.js +8 -3
- package/dist/templates/components/layout/SharedStyles.d.ts +1 -1
- package/dist/templates/components/layout/SharedStyles.js +2 -1
- package/dist/templates/components/layout/StaticLinks.d.ts +1 -1
- package/dist/templates/components/layout/StaticLinks.js +3 -3
- package/dist/templates/mdx/lists-and-tables.mdx.d.ts +1 -0
- package/dist/templates/mdx/lists-and-tables.mdx.js +78 -0
- package/dist/templates/mdx/navigation.mdx.d.ts +1 -1
- package/dist/templates/mdx/navigation.mdx.js +7 -4
- package/dist/templates/mdx/theme.mdx.d.ts +1 -1
- package/dist/templates/mdx/theme.mdx.js +1 -1
- package/dist/templates/package.js +12 -12
- package/dist/templates/services/mcp/tools.d.ts +1 -1
- package/dist/templates/services/mcp/tools.js +9 -10
- package/dist/templates/tsconfig.d.ts +1 -1
- package/dist/templates/tsconfig.js +0 -1
- package/package.json +4 -4
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
export const searchModalContentTemplate = `"use client";
|
|
2
|
+
import React, { useCallback } from "react";
|
|
3
|
+
import styled, { css, keyframes } from "styled-components";
|
|
4
|
+
import { rgba } from "polished";
|
|
5
|
+
import { Search } from "lucide-react";
|
|
6
|
+
import { mq, Theme } from "@/app/theme";
|
|
7
|
+
import { Spinner } from "@/components/Spinner";
|
|
8
|
+
|
|
9
|
+
export interface PageItem {
|
|
10
|
+
slug: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
category: string;
|
|
14
|
+
section?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface MergedResult {
|
|
18
|
+
page: PageItem;
|
|
19
|
+
snippet?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface SearchModalContentProps {
|
|
23
|
+
isClosing: boolean;
|
|
24
|
+
closeSearch: () => void;
|
|
25
|
+
onCloseAnimationEnd: () => void;
|
|
26
|
+
query: string;
|
|
27
|
+
setQuery: (q: string) => void;
|
|
28
|
+
activeIndex: number;
|
|
29
|
+
setActiveIndex: (i: number | ((prev: number) => number)) => void;
|
|
30
|
+
inputRef: React.RefObject<HTMLInputElement | null>;
|
|
31
|
+
resultsRef: React.RefObject<HTMLUListElement | null>;
|
|
32
|
+
onKeyDown: (e: React.KeyboardEvent) => void;
|
|
33
|
+
merged: MergedResult[];
|
|
34
|
+
sectionLabels: Record<string, string>;
|
|
35
|
+
isSearching: boolean;
|
|
36
|
+
navigate: (slug: string) => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const ANIMATION_MS = 150;
|
|
40
|
+
|
|
41
|
+
const backdropIn = keyframes\`
|
|
42
|
+
from { opacity: 0; }
|
|
43
|
+
to { opacity: 1; }
|
|
44
|
+
\`;
|
|
45
|
+
|
|
46
|
+
const backdropOut = keyframes\`
|
|
47
|
+
from { opacity: 1; }
|
|
48
|
+
to { opacity: 0; }
|
|
49
|
+
\`;
|
|
50
|
+
|
|
51
|
+
const modalIn = keyframes\`
|
|
52
|
+
from { opacity: 0; transform: scale(0.96) translateY(-8px); }
|
|
53
|
+
to { opacity: 1; transform: scale(1) translateY(0); }
|
|
54
|
+
\`;
|
|
55
|
+
|
|
56
|
+
const modalOut = keyframes\`
|
|
57
|
+
from { opacity: 1; transform: scale(1) translateY(0); }
|
|
58
|
+
to { opacity: 0; transform: scale(0.96) translateY(-8px); }
|
|
59
|
+
\`;
|
|
60
|
+
|
|
61
|
+
const StyledBackdrop = styled.div<{ theme: Theme; $isClosing: boolean }>\`
|
|
62
|
+
position: fixed;
|
|
63
|
+
inset: 0;
|
|
64
|
+
z-index: 9999;
|
|
65
|
+
background: \${({ theme }) =>
|
|
66
|
+
rgba(theme.isDark ? theme.colors.light : theme.colors.dark, 0.5)};
|
|
67
|
+
backdrop-filter: blur(4px);
|
|
68
|
+
-webkit-backdrop-filter: blur(4px);
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: flex-start;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
padding: 20px;
|
|
73
|
+
animation: \${({ $isClosing }) => ($isClosing ? backdropOut : backdropIn)}
|
|
74
|
+
\${ANIMATION_MS}ms ease forwards;
|
|
75
|
+
|
|
76
|
+
\${mq("lg")} {
|
|
77
|
+
padding: 120px 20px 20px 20px;
|
|
78
|
+
}
|
|
79
|
+
\`;
|
|
80
|
+
|
|
81
|
+
const StyledModal = styled.div<{ theme: Theme; $isClosing: boolean }>\`
|
|
82
|
+
background: \${({ theme }) => theme.colors.light};
|
|
83
|
+
border-radius: \${({ theme }) => theme.spacing.radius.lg};
|
|
84
|
+
box-shadow: \${({ theme }) => theme.shadows.xs};
|
|
85
|
+
width: 100%;
|
|
86
|
+
max-width: 560px;
|
|
87
|
+
max-height: calc(100dvh - 40px);
|
|
88
|
+
display: flex;
|
|
89
|
+
flex-direction: column;
|
|
90
|
+
border: solid 1px \${({ theme }) => theme.colors.grayLight};
|
|
91
|
+
padding-bottom: 8px;
|
|
92
|
+
animation: \${({ $isClosing }) => ($isClosing ? modalOut : modalIn)}
|
|
93
|
+
\${ANIMATION_MS}ms ease forwards;
|
|
94
|
+
|
|
95
|
+
\${mq("lg")} {
|
|
96
|
+
max-height: calc(100dvh - 240px);
|
|
97
|
+
}
|
|
98
|
+
\`;
|
|
99
|
+
|
|
100
|
+
const StyledInputWrapper = styled.div<{ theme: Theme }>\`
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
gap: 12px;
|
|
104
|
+
padding: 16px;
|
|
105
|
+
flex-shrink: 0;
|
|
106
|
+
border-bottom: solid 1px \${({ theme }) => theme.colors.grayLight};
|
|
107
|
+
|
|
108
|
+
& svg.lucide {
|
|
109
|
+
color: \${({ theme }) => theme.colors.gray};
|
|
110
|
+
flex-shrink: 0;
|
|
111
|
+
}
|
|
112
|
+
\`;
|
|
113
|
+
|
|
114
|
+
const StyledInput = styled.input<{ theme: Theme }>\`
|
|
115
|
+
flex: 1;
|
|
116
|
+
border: none;
|
|
117
|
+
outline: none;
|
|
118
|
+
background: transparent;
|
|
119
|
+
font-size: \${({ theme }) => theme.fontSizes.text.lg};
|
|
120
|
+
line-height: \${({ theme }) => theme.lineHeights.text.lg};
|
|
121
|
+
color: \${({ theme }) => theme.colors.dark};
|
|
122
|
+
font-family: inherit;
|
|
123
|
+
|
|
124
|
+
&::placeholder {
|
|
125
|
+
color: \${({ theme }) => theme.colors.gray};
|
|
126
|
+
}
|
|
127
|
+
\`;
|
|
128
|
+
|
|
129
|
+
const StyledResults = styled.ul<{ theme: Theme }>\`
|
|
130
|
+
list-style: none;
|
|
131
|
+
margin: 8px 0 0 0;
|
|
132
|
+
padding: 0 8px;
|
|
133
|
+
overflow-y: auto;
|
|
134
|
+
flex: 1;
|
|
135
|
+
min-height: 0;
|
|
136
|
+
-webkit-overflow-scrolling: touch;
|
|
137
|
+
|
|
138
|
+
&::-webkit-scrollbar {
|
|
139
|
+
display: none;
|
|
140
|
+
}
|
|
141
|
+
\`;
|
|
142
|
+
|
|
143
|
+
const StyledResultItem = styled.li<{ theme: Theme; $isActive: boolean }>\`
|
|
144
|
+
padding: 10px 12px;
|
|
145
|
+
border-radius: \${({ theme }) => theme.spacing.radius.xs};
|
|
146
|
+
cursor: pointer;
|
|
147
|
+
transition: background 0.15s ease;
|
|
148
|
+
|
|
149
|
+
\${({ $isActive, theme }) =>
|
|
150
|
+
$isActive &&
|
|
151
|
+
css\`
|
|
152
|
+
background: \${rgba(theme.colors.primaryLight, 0.2)};
|
|
153
|
+
\`}
|
|
154
|
+
|
|
155
|
+
&:hover {
|
|
156
|
+
background: \${({ theme }) => rgba(theme.colors.primaryLight, 0.15)};
|
|
157
|
+
}
|
|
158
|
+
\`;
|
|
159
|
+
|
|
160
|
+
const StyledResultTitle = styled.span<{ theme: Theme }>\`
|
|
161
|
+
font-size: \${({ theme }) => theme.fontSizes.text.lg};
|
|
162
|
+
font-weight: 500;
|
|
163
|
+
color: \${({ theme }) => theme.colors.dark};
|
|
164
|
+
display: block;
|
|
165
|
+
\`;
|
|
166
|
+
|
|
167
|
+
const StyledResultMeta = styled.span<{ theme: Theme }>\`
|
|
168
|
+
font-size: \${({ theme }) => theme.fontSizes.small.lg};
|
|
169
|
+
color: \${({ theme }) => theme.colors.gray};
|
|
170
|
+
display: block;
|
|
171
|
+
margin-top: 2px;
|
|
172
|
+
\`;
|
|
173
|
+
|
|
174
|
+
const StyledSnippet = styled.span<{ theme: Theme }>\`
|
|
175
|
+
font-size: \${({ theme }) => theme.fontSizes.small.lg};
|
|
176
|
+
color: \${({ theme }) => theme.colors.grayDark};
|
|
177
|
+
display: block;
|
|
178
|
+
margin-top: 4px;
|
|
179
|
+
line-height: 1.4;
|
|
180
|
+
overflow: hidden;
|
|
181
|
+
text-overflow: ellipsis;
|
|
182
|
+
white-space: nowrap;
|
|
183
|
+
|
|
184
|
+
& mark {
|
|
185
|
+
background: \${({ theme }) => rgba(theme.colors.primaryLight, 0.35)};
|
|
186
|
+
color: inherit;
|
|
187
|
+
border-radius: 4px;
|
|
188
|
+
padding: 0 1px;
|
|
189
|
+
}
|
|
190
|
+
\`;
|
|
191
|
+
|
|
192
|
+
const StyledEmpty = styled.div<{ theme: Theme }>\`
|
|
193
|
+
padding: 20px 20px 12px;
|
|
194
|
+
min-height: 40px;
|
|
195
|
+
display: flex;
|
|
196
|
+
align-items: center;
|
|
197
|
+
justify-content: center;
|
|
198
|
+
text-align: center;
|
|
199
|
+
font-size: \${({ theme }) => theme.fontSizes.small.lg};
|
|
200
|
+
color: \${({ theme }) => theme.colors.gray};
|
|
201
|
+
\`;
|
|
202
|
+
|
|
203
|
+
const StyledKbd = styled.kbd<{ theme: Theme }>\`
|
|
204
|
+
font-size: 11px;
|
|
205
|
+
font-family: inherit;
|
|
206
|
+
background: \${({ theme }) => theme.colors.grayLight};
|
|
207
|
+
color: \${({ theme }) => theme.colors.grayDark};
|
|
208
|
+
padding: 2px 6px;
|
|
209
|
+
border-radius: 4px;
|
|
210
|
+
margin-left: auto;
|
|
211
|
+
font-weight: 600;
|
|
212
|
+
display: none;
|
|
213
|
+
|
|
214
|
+
\${mq("lg")} {
|
|
215
|
+
display: initial;
|
|
216
|
+
}
|
|
217
|
+
\`;
|
|
218
|
+
|
|
219
|
+
function escapeHtml(str: string): string {
|
|
220
|
+
return str
|
|
221
|
+
.replace(/&/g, "&")
|
|
222
|
+
.replace(/</g, "<")
|
|
223
|
+
.replace(/>/g, ">")
|
|
224
|
+
.replace(/"/g, """);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function highlightMatch(snippet: string, query: string): string {
|
|
228
|
+
const escaped = escapeHtml(snippet);
|
|
229
|
+
if (!query.trim()) return escaped;
|
|
230
|
+
const q = escapeHtml(query.trim());
|
|
231
|
+
const regex = new RegExp(
|
|
232
|
+
\`(\${q.replace(/[.*+?^\${}()|[\\]\\\\]/g, "\\\\$&")})\`,
|
|
233
|
+
"gi",
|
|
234
|
+
);
|
|
235
|
+
return escaped.replace(regex, "<mark>$1</mark>");
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export function SearchModalContent({
|
|
239
|
+
isClosing,
|
|
240
|
+
closeSearch,
|
|
241
|
+
onCloseAnimationEnd,
|
|
242
|
+
query,
|
|
243
|
+
setQuery,
|
|
244
|
+
activeIndex,
|
|
245
|
+
setActiveIndex,
|
|
246
|
+
inputRef,
|
|
247
|
+
resultsRef,
|
|
248
|
+
onKeyDown,
|
|
249
|
+
merged,
|
|
250
|
+
sectionLabels,
|
|
251
|
+
isSearching,
|
|
252
|
+
navigate,
|
|
253
|
+
}: SearchModalContentProps) {
|
|
254
|
+
const setInputRef = useCallback(
|
|
255
|
+
(node: HTMLInputElement | null) => {
|
|
256
|
+
// Sync with parent ref
|
|
257
|
+
if (inputRef) {
|
|
258
|
+
(inputRef as React.RefObject<HTMLInputElement | null>).current = node;
|
|
259
|
+
}
|
|
260
|
+
// Auto-focus on mount
|
|
261
|
+
if (node && !isClosing) {
|
|
262
|
+
node.focus();
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
[inputRef, isClosing],
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
return (
|
|
269
|
+
<StyledBackdrop
|
|
270
|
+
$isClosing={isClosing}
|
|
271
|
+
onClick={closeSearch}
|
|
272
|
+
onAnimationEnd={onCloseAnimationEnd}
|
|
273
|
+
>
|
|
274
|
+
<StyledModal $isClosing={isClosing} onClick={(e) => e.stopPropagation()}>
|
|
275
|
+
<StyledInputWrapper>
|
|
276
|
+
<Search size={18} />
|
|
277
|
+
<StyledInput
|
|
278
|
+
ref={setInputRef}
|
|
279
|
+
value={query}
|
|
280
|
+
onChange={(e) => {
|
|
281
|
+
setQuery(e.target.value);
|
|
282
|
+
setActiveIndex(0);
|
|
283
|
+
}}
|
|
284
|
+
onKeyDown={onKeyDown}
|
|
285
|
+
placeholder="Search docs..."
|
|
286
|
+
autoComplete="off"
|
|
287
|
+
spellCheck={false}
|
|
288
|
+
/>
|
|
289
|
+
<StyledKbd>Esc</StyledKbd>
|
|
290
|
+
</StyledInputWrapper>
|
|
291
|
+
{merged.length > 0 ? (
|
|
292
|
+
<StyledResults ref={resultsRef}>
|
|
293
|
+
{merged.map((result, index) => (
|
|
294
|
+
<StyledResultItem
|
|
295
|
+
key={result.page.slug + result.page.section}
|
|
296
|
+
$isActive={index === activeIndex}
|
|
297
|
+
onClick={() => navigate(result.page.slug)}
|
|
298
|
+
onMouseEnter={() => setActiveIndex(index)}
|
|
299
|
+
>
|
|
300
|
+
<StyledResultTitle>{result.page.title}</StyledResultTitle>
|
|
301
|
+
<StyledResultMeta>
|
|
302
|
+
{result.page.section
|
|
303
|
+
? \`\${sectionLabels[result.page.section] || result.page.section} / \`
|
|
304
|
+
: ""}
|
|
305
|
+
{result.page.category}
|
|
306
|
+
</StyledResultMeta>
|
|
307
|
+
{result.snippet && (
|
|
308
|
+
<StyledSnippet
|
|
309
|
+
dangerouslySetInnerHTML={{
|
|
310
|
+
__html: highlightMatch(result.snippet, query),
|
|
311
|
+
}}
|
|
312
|
+
/>
|
|
313
|
+
)}
|
|
314
|
+
</StyledResultItem>
|
|
315
|
+
))}
|
|
316
|
+
</StyledResults>
|
|
317
|
+
) : (
|
|
318
|
+
<StyledEmpty>
|
|
319
|
+
{isSearching ? <Spinner size={18} /> : "No results found"}
|
|
320
|
+
</StyledEmpty>
|
|
321
|
+
)}
|
|
322
|
+
</StyledModal>
|
|
323
|
+
</StyledBackdrop>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const sideBarTemplate = "\"use client\";\nimport { useContext, useState, Suspense } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport { Flex, Space } from \"cherry-styled-components\";\nimport {\n DocsSidebar,\n SectionBarContext,\n StyledSidebar,\n StyledSidebarList,\n StyledSidebarListItem,\n StyledStrong,\n StyledSidebarListItemLink,\n StyledSidebarFooter,\n StyleMobileBar,\n StyledMobileBurger,\n} from \"@/components/layout/DocsComponents\";\nimport {\n ToggleTheme,\n ToggleThemeLoading,\n} from \"@/components/layout/ThemeToggle\";\nimport { useLockBodyScroll } from \"@/components/LockBodyScroll\";\n\ntype NavItem = {\n label: string;\n links: NavItemLink[];\n};\n\ntype NavItemLink = {\n slug: string;\n title: string;\n};\n\ninterface SideBarProps {\n result: NavItem[];\n}\n\nfunction SideBar({ result }: SideBarProps) {\n const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);\n const hasSectionBar = useContext(SectionBarContext);\n const pathname = usePathname();\n\n useLockBodyScroll(isMobileMenuOpen);\n\n return (\n <DocsSidebar>\n <StyleMobileBar\n onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}\n $isActive={isMobileMenuOpen}\n >\n <StyledMobileBurger $isActive={isMobileMenuOpen} />\n </StyleMobileBar>\n\n <StyledSidebar\n $isActive={isMobileMenuOpen}\n $hasSectionBar={hasSectionBar}\n >\n {result &&\n result.map((item: NavItem, index: number) => {\n return (\n <StyledSidebarList key={index}>\n <StyledSidebarListItem>\n <StyledStrong>{item.label}</StyledStrong>{\" \"}\n </StyledSidebarListItem>\n <li>\n <Space $size={20} />\n </li>\n {item.links &&\n item.links.map((link: NavItemLink, indexChild: number) => {\n return (\n <StyledSidebarListItem key={indexChild}>\n <StyledSidebarListItemLink\n href={`/${link.slug}`}\n $isActive={pathname === `/${link.slug}`}\n onClick={() => setIsMobileMenuOpen(false)}\n >\n {link.title}\n </StyledSidebarListItemLink>\n </StyledSidebarListItem>\n );\n })}\n <Space $size={20} />\n </StyledSidebarList>\n );\n })}\n <StyledSidebarFooter>\n <Flex $xsJustifyContent=\"flex-start\" $lgJustifyContent=\"flex-end\">\n <Suspense fallback={<ToggleThemeLoading />}>\n <ToggleTheme />\n </Suspense>\n </Flex>\n </StyledSidebarFooter>\n </StyledSidebar>\n </DocsSidebar>\n );\n}\n\nexport { SideBar };\n";
|
|
1
|
+
export declare const sideBarTemplate = "\"use client\";\nimport { useContext, useState, Suspense } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport { Flex, Space } from \"cherry-styled-components\";\nimport {\n DocsSidebar,\n SectionBarContext,\n StyledSidebar,\n StyledSidebarList,\n StyledSidebarListItem,\n StyledStrong,\n StyledSidebarListItemLink,\n StyledSidebarFooter,\n StyleMobileBar,\n StyledMobileBurger,\n} from \"@/components/layout/DocsComponents\";\nimport {\n ToggleTheme,\n ToggleThemeLoading,\n} from \"@/components/layout/ThemeToggle\";\nimport { useLockBodyScroll } from \"@/components/LockBodyScroll\";\n\ntype NavItem = {\n label: string;\n links: NavItemLink[];\n};\n\ntype NavItemLink = {\n slug: string;\n title: string;\n};\n\ninterface SideBarProps {\n result: NavItem[];\n}\n\nfunction SideBar({ result }: SideBarProps) {\n const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);\n const hasSectionBar = useContext(SectionBarContext);\n const pathname = usePathname();\n\n useLockBodyScroll(isMobileMenuOpen);\n\n return (\n <DocsSidebar>\n <StyleMobileBar\n onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}\n $isActive={isMobileMenuOpen}\n aria-label={isMobileMenuOpen ? \"Close navigation menu\" : \"Open navigation menu\"}\n aria-expanded={isMobileMenuOpen}\n >\n <StyledMobileBurger $isActive={isMobileMenuOpen} />\n </StyleMobileBar>\n\n <StyledSidebar\n $isActive={isMobileMenuOpen}\n $hasSectionBar={hasSectionBar}\n >\n {result &&\n result.map((item: NavItem, index: number) => {\n return (\n <StyledSidebarList key={index}>\n <StyledSidebarListItem>\n <StyledStrong>{item.label}</StyledStrong>{\" \"}\n </StyledSidebarListItem>\n <li>\n <Space $size={20} />\n </li>\n {item.links &&\n item.links.map((link: NavItemLink, indexChild: number) => {\n return (\n <StyledSidebarListItem key={indexChild}>\n <StyledSidebarListItemLink\n href={`/${link.slug}`}\n $isActive={pathname === `/${link.slug}`}\n onClick={() => setIsMobileMenuOpen(false)}\n >\n {link.title}\n </StyledSidebarListItemLink>\n </StyledSidebarListItem>\n );\n })}\n <li aria-hidden=\"true\">\n <Space $size={20} />\n </li>\n </StyledSidebarList>\n );\n })}\n <StyledSidebarFooter>\n <Flex $xsJustifyContent=\"flex-start\" $lgJustifyContent=\"flex-end\">\n <Suspense fallback={<ToggleThemeLoading />}>\n <ToggleTheme />\n </Suspense>\n </Flex>\n </StyledSidebarFooter>\n </StyledSidebar>\n </DocsSidebar>\n );\n}\n\nexport { SideBar };\n";
|
|
@@ -46,6 +46,8 @@ function SideBar({ result }: SideBarProps) {
|
|
|
46
46
|
<StyleMobileBar
|
|
47
47
|
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
|
48
48
|
$isActive={isMobileMenuOpen}
|
|
49
|
+
aria-label={isMobileMenuOpen ? "Close navigation menu" : "Open navigation menu"}
|
|
50
|
+
aria-expanded={isMobileMenuOpen}
|
|
49
51
|
>
|
|
50
52
|
<StyledMobileBurger $isActive={isMobileMenuOpen} />
|
|
51
53
|
</StyleMobileBar>
|
|
@@ -78,7 +80,9 @@ function SideBar({ result }: SideBarProps) {
|
|
|
78
80
|
</StyledSidebarListItem>
|
|
79
81
|
);
|
|
80
82
|
})}
|
|
81
|
-
<
|
|
83
|
+
<li aria-hidden="true">
|
|
84
|
+
<Space $size={20} />
|
|
85
|
+
</li>
|
|
82
86
|
</StyledSidebarList>
|
|
83
87
|
);
|
|
84
88
|
})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const docsComponentsTemplate = "\"use client\";\nimport { darken, lighten, rgba } from \"polished\";\nimport React, { createContext, useContext } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport {\n resetButton,\n styledSmall,\n styledStrong,\n styledText,\n} from \"cherry-styled-components\";\nimport Link from \"next/link\";\nimport { mq, Theme } from \"@/app/theme\";\nimport {\n styledAnchor,\n styledTable,\n stylesLists,\n} from \"@/components/layout/SharedStyled\";\nimport { ChatContext } from \"@/components/Chat\";\n\nconst SectionBarContext = createContext(false);\n\nfunction SectionBarProvider({\n hasSectionBar,\n children,\n}: {\n hasSectionBar: boolean;\n children: React.ReactNode;\n}) {\n return (\n <SectionBarContext.Provider value={hasSectionBar}>\n {children}\n </SectionBarContext.Provider>\n );\n}\n\ninterface DocsProps {\n children: React.ReactNode;\n}\n\nconst StyledDocsWrapper = styled.
|
|
1
|
+
export declare const docsComponentsTemplate = "\"use client\";\nimport { darken, lighten, rgba } from \"polished\";\nimport React, { createContext, useContext } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport {\n resetButton,\n styledSmall,\n styledStrong,\n styledText,\n} from \"cherry-styled-components\";\nimport Link from \"next/link\";\nimport { mq, Theme } from \"@/app/theme\";\nimport {\n styledAnchor,\n styledTable,\n stylesLists,\n} from \"@/components/layout/SharedStyled\";\nimport { ChatContext } from \"@/components/Chat\";\n\nconst SectionBarContext = createContext(false);\n\nfunction SectionBarProvider({\n hasSectionBar,\n children,\n}: {\n hasSectionBar: boolean;\n children: React.ReactNode;\n}) {\n return (\n <SectionBarContext.Provider value={hasSectionBar}>\n {children}\n </SectionBarContext.Provider>\n );\n}\n\ninterface DocsProps {\n children: React.ReactNode;\n}\n\nconst StyledDocsWrapper = styled.main<{ theme: Theme }>`\n position: relative;\n`;\n\nconst StyledDocsSidebar = styled.div<{ theme: Theme }>`\n clear: both;\n`;\n\nconst StyledDocsContainer = styled.div<{ theme: Theme; $isChatOpen?: boolean }>`\n position: relative;\n padding: 0 20px 100px 20px;\n width: 100%;\n ${({ theme }) => styledText(theme)};\n transition: all 0.3s ease;\n\n ${mq(\"lg\")} {\n padding: 0 300px 80px 300px;\n\n ${({ $isChatOpen }) =>\n $isChatOpen &&\n css`\n padding: 0 440px 80px 300px;\n `}\n }\n\n & p {\n color: ${({ theme }) => theme.colors.grayDark};\n hyphens: auto;\n }\n\n & pre {\n max-width: 100%;\n }\n\n ${styledAnchor};\n ${stylesLists};\n ${styledTable};\n\n & img,\n & video,\n & iframe {\n max-width: 100%;\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n }\n\n & code:not([class]) {\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.2)};\n color: ${({ theme }) => theme.colors.dark};\n padding: 2px 4px;\n border-radius: ${({ theme }) => theme.spacing.radius.xs};\n white-space: pre;\n }\n\n & .lucide {\n color: ${({ theme }) => theme.colors.primary};\n }\n\n & .aspect-video {\n aspect-ratio: 16 / 9;\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n }\n`;\n\nexport const StyledMarkdownContainer = styled.div`\n display: flex;\n flex-direction: column;\n gap: 20px;\n flex-wrap: wrap;\n flex: 1;\n max-width: 640px;\n margin: auto;\n`;\n\ninterface Props {\n theme?: Theme;\n $isActive?: boolean;\n $hasSectionBar?: boolean;\n}\n\nexport const StyledSidebar = styled.nav<Props>`\n position: fixed;\n overflow-y: auto;\n max-height: calc(\n 100dvh - ${({ $hasSectionBar }) => ($hasSectionBar ? 104 : 62)}px\n );\n width: 100%;\n z-index: 99;\n top: ${({ $hasSectionBar }) => ($hasSectionBar ? 104 : 62)}px;\n height: 100%;\n padding: 20px;\n opacity: 0;\n pointer-events: none;\n transition: all 0.3s ease;\n transform: translateY(30px);\n left: 0;\n background: ${({ theme }) => theme.colors.light};\n -webkit-overflow-scrolling: touch;\n display: flex;\n flex-direction: column;\n\n &::-webkit-scrollbar {\n display: none;\n }\n\n ${mq(\"lg\")} {\n border-right: solid 1px ${({ theme }) => theme.colors.grayLight};\n transition: none;\n max-height: 100dvh;\n width: 220px;\n background: transparent;\n padding: 82px 20px 20px 20px;\n opacity: 1;\n pointer-events: all;\n transform: translateY(0);\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.05)};\n top: 0;\n width: 280px;\n }\n\n ${({ $isActive }) =>\n $isActive &&\n css`\n transform: translateY(0);\n opacity: 1;\n pointer-events: all;\n `}\n`;\n\nexport const StyledSidebarFooter = styled.div`\n padding: 22px 20px;\n position: sticky;\n border-top: 1px solid ${({ theme }) => theme.colors.grayLight};\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.05)};\n margin: 0 -20px -20px;\n bottom: -20px;\n backdrop-filter: blur(10px);\n\n ${mq(\"lg\")} {\n padding: 16px 20px;\n }\n`;\n\nexport const StyledIndexSidebar = styled.ul<{ theme: Theme }>`\n display: none;\n list-style: none;\n margin: 0;\n padding: 0;\n position: fixed;\n top: 0;\n right: 0;\n width: 280px;\n height: 100dvh;\n overflow-y: auto;\n z-index: 1;\n padding: 82px 20px 20px 20px;\n background: ${({ theme }) => theme.colors.light};\n border-left: solid 1px ${({ theme }) => theme.colors.grayLight};\n -webkit-overflow-scrolling: touch;\n\n &::-webkit-scrollbar {\n display: none;\n }\n\n ${mq(\"lg\")} {\n display: block;\n }\n\n & li {\n padding: 5px 0;\n }\n`;\n\nexport const StyledIndexSidebarLabel = styled.span<{ theme: Theme }>`\n ${({ theme }) => styledSmall(theme)};\n color: ${({ theme }) => theme.colors.grayDark};\n`;\n\nexport const StyledIndexSidebarLi = styled.li<{\n theme: Theme;\n $isActive: boolean;\n}>`\n &::before {\n content: \"\";\n display: block;\n position: absolute;\n left: 0;\n height: 20px;\n width: 1px;\n background: transparent;\n transition: all 0.3s ease;\n }\n\n ${({ $isActive, theme }) =>\n $isActive &&\n css`\n &::before {\n background: ${theme.colors.primary};\n }\n `}\n`;\n\nexport const StyledIndexSidebarLink = styled.a<{\n theme: Theme;\n $isActive: boolean;\n}>`\n ${({ theme }) => styledSmall(theme)};\n color: ${({ theme, $isActive }) =>\n $isActive ? theme.colors.primary : theme.colors.dark};\n font-weight: ${({ $isActive }) => ($isActive ? \"600\" : \"400\")};\n text-decoration: none;\n transition: all 0.3s ease;\n\n &:hover {\n color: ${({ theme }) => theme.colors.primary};\n }\n`;\n\nexport const StyledSidebarList = styled.ul`\n list-style: none;\n margin: 0;\n padding: 0;\n\n &:last-of-type {\n margin-bottom: auto;\n }\n`;\n\nexport const StyledStrong = styled.strong<{ theme: Theme }>`\n font-weight: 600;\n ${({ theme }) => styledStrong(theme)};\n color: ${({ theme }) =>\n theme.isDark\n ? lighten(0.1, theme.colors.primaryLight)\n : darken(0.1, theme.colors.primaryDark)};\n`;\n\nexport const StyledSidebarListItem = styled.li`\n display: flex;\n gap: 10px;\n clear: both;\n`;\n\nexport const StyledSidebarListItemLink = styled(Link)<Props>`\n text-decoration: none;\n font-size: ${({ theme }) => theme.fontSizes.small.lg};\n line-height: 1.6;\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.grayDark : theme.colors.primary};\n padding: 5px 0 5px 20px;\n display: flex;\n transition: all 0.3s ease;\n border-left: solid 1px ${({ theme }) => theme.colors.grayLight};\n\n &:hover {\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n border-color: ${({ theme }) => theme.colors.primary};\n }\n\n ${({ $isActive, theme }) =>\n $isActive &&\n `\n\t\t\tcolor: ${theme.isDark ? lighten(0.1, theme.colors.primaryLight) : darken(0.1, theme.colors.primaryDark)};\n\t\t\tborder-color: ${theme.colors.primary};\n\t\t\tfont-weight: 600;\n\t`};\n`;\n\nexport const StyleMobileBar = styled.button<Props>`\n ${resetButton};\n position: fixed;\n z-index: 999;\n bottom: 0;\n right: 20px;\n font-size: ${({ theme }) => theme.fontSizes.strong.lg};\n line-height: ${({ theme }) => theme.fontSizes.strong.lg};\n box-shadow: ${({ theme }) => theme.shadows.sm};\n background: ${({ theme }) => theme.colors.primary};\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.dark : theme.colors.light};\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n padding: 10px;\n border-radius: 100px;\n margin: 0 0 20px 0;\n font-weight: 600;\n display: flex;\n justify-content: flex-start;\n width: auto;\n\n ${mq(\"lg\")} {\n display: none;\n }\n\n ${({ $isActive }) => $isActive && `position: fixed;`};\n`;\n\nexport const StyledMobileBurger = styled.span<Props>`\n display: block;\n margin: auto 0;\n width: 18px;\n height: 18px;\n position: relative;\n overflow: hidden;\n background: transparent;\n position: relative;\n transform: scale(0.8);\n\n &::before,\n &::after {\n content: \"\";\n display: block;\n position: absolute;\n width: 18px;\n height: 3px;\n border-radius: 3px;\n background: ${({ theme }) =>\n theme.isDark ? theme.colors.dark : theme.colors.light};\n transition: all 0.3s ease;\n }\n\n &::before {\n top: 3px;\n }\n\n &::after {\n bottom: 3px;\n }\n\n ${({ $isActive }) =>\n $isActive &&\n css`\n &::before {\n transform: translateY(5px) rotate(45deg);\n }\n\n &::after {\n transform: translateY(-4px) rotate(-45deg);\n }\n `};\n`;\n\nexport const StyledMissingComponent = styled.div`\n background: ${({ theme }) => theme.colors.error};\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n padding: 20px;\n font-size: ${({ theme }) => theme.fontSizes.small.lg};\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.dark : theme.colors.light};\n font-weight: 600;\n display: flex;\n gap: 10px;\n align-items: center;\n`;\n\ninterface DocsWrapperProps {\n children: React.ReactNode;\n}\n\nfunction DocsWrapper({ children }: DocsWrapperProps) {\n return <StyledDocsWrapper>{children}</StyledDocsWrapper>;\n}\n\nfunction DocsSidebar({ children }: DocsProps) {\n return <StyledDocsSidebar>{children}</StyledDocsSidebar>;\n}\n\nfunction DocsContainer({ children }: DocsProps) {\n const { isOpen } = useContext(ChatContext);\n\n return (\n <StyledDocsContainer $isChatOpen={isOpen}>{children}</StyledDocsContainer>\n );\n}\n\nexport {\n DocsWrapper,\n DocsSidebar,\n DocsContainer,\n SectionBarContext,\n SectionBarProvider,\n};\n";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const docsNavigationTemplate = "\"use client\";\nimport { useContext } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport Link from \"next/link\";\nimport styled, { css } from \"styled-components\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { interactiveStyles } from \"@/components/layout/SharedStyled\";\nimport { ChatContext } from \"@/components/Chat\";\n\nconst StyledNavigationWrapper = styled.div<{\n $isChatOpen?: boolean;\n}>`\n transition: all 0.3s ease;\n padding: 0 20px 100px 20px;\n ${mq(\"lg\")} {\n padding: 0 300px 80px 300px;\n ${({ $isChatOpen }) =>\n $isChatOpen &&\n css`\n padding: 0 440px 80px 300px;\n `}\n }\n`;\n\nconst StyledNavigationInner = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 20px;\n max-width: 640px;\n margin: auto;\n`;\n\nconst StyledNavButton = styled(Link)<{ theme: Theme }>`\n ${interactiveStyles};\n display: flex;\n flex-direction: column;\n text-decoration: none;\n padding: 20px;\n flex: 50%;\n max-width: 50%;\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n color: ${({ theme }) => theme.colors.dark};\n\n &:hover {\n border-color: ${({ theme }) => theme.colors.primary};\n }\n\n &[data-direction=\"prev\"] {\n align-items: flex-start;\n }\n\n &[data-direction=\"next\"] {\n align-items: flex-end;\n margin-left: auto;\n text-align: right;\n }\n`;\n\nconst StyledNavLabel = styled.span<{ theme: Theme }>`\n color: ${({ theme }) => theme.colors.
|
|
1
|
+
export declare const docsNavigationTemplate = "\"use client\";\nimport { useContext } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport Link from \"next/link\";\nimport styled, { css } from \"styled-components\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { interactiveStyles } from \"@/components/layout/SharedStyled\";\nimport { ChatContext } from \"@/components/Chat\";\n\nconst StyledNavigationWrapper = styled.div<{\n $isChatOpen?: boolean;\n}>`\n transition: all 0.3s ease;\n padding: 0 20px 100px 20px;\n ${mq(\"lg\")} {\n padding: 0 300px 80px 300px;\n ${({ $isChatOpen }) =>\n $isChatOpen &&\n css`\n padding: 0 440px 80px 300px;\n `}\n }\n`;\n\nconst StyledNavigationInner = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 20px;\n max-width: 640px;\n margin: auto;\n`;\n\nconst StyledNavButton = styled(Link)<{ theme: Theme }>`\n ${interactiveStyles};\n display: flex;\n flex-direction: column;\n text-decoration: none;\n padding: 20px;\n flex: 50%;\n max-width: 50%;\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n color: ${({ theme }) => theme.colors.dark};\n\n &:hover {\n border-color: ${({ theme }) => theme.colors.primary};\n }\n\n &[data-direction=\"prev\"] {\n align-items: flex-start;\n }\n\n &[data-direction=\"next\"] {\n align-items: flex-end;\n margin-left: auto;\n text-align: right;\n }\n`;\n\nconst StyledNavLabel = styled.span<{ theme: Theme }>`\n color: ${({ theme }) => theme.colors.grayDark};\n display: flex;\n flex-direction: row;\n gap: 4px;\n\n & svg {\n margin: auto 0;\n }\n`;\n\nconst StyledNavTitle = styled.span<{ theme: Theme }>`\n color: ${({ theme }) => theme.colors.dark};\n font-weight: 600;\n margin: 0 0 4px 0;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n max-width: 100%;\n`;\n\nconst StyledSpacer = styled.div`\n flex: 1;\n`;\n\ninterface Page {\n slug: string;\n title: string;\n category?: string;\n [key: string]: unknown;\n}\n\ninterface NavigationItem {\n category?: string;\n slug?: string;\n title?: string;\n links?: Page[];\n items?: Page[];\n [key: string]: unknown;\n}\n\ninterface DocsNavigationProps {\n result: NavigationItem[];\n}\n\nfunction DocsNavigation({ result }: DocsNavigationProps) {\n const { isOpen } = useContext(ChatContext);\n const pathname = usePathname();\n const allPages: Page[] = result.flatMap((item) => {\n if (item.links && Array.isArray(item.links)) {\n return item.links;\n }\n if (item.items && Array.isArray(item.items)) {\n return item.items;\n }\n if (item.slug !== undefined) {\n return [item as Page];\n }\n return [];\n });\n const currentSlug = pathname.replace(/^\\//, \"\").replace(/\\/$/, \"\");\n const currentIndex = allPages.findIndex((page) => page.slug === currentSlug);\n const prevPage = currentIndex > 0 ? allPages[currentIndex - 1] : null;\n const nextPage =\n currentIndex < allPages.length - 1 ? allPages[currentIndex + 1] : null;\n if (currentIndex === -1 || allPages.length === 0) {\n return null;\n }\n if (!prevPage && !nextPage) {\n return null;\n }\n return (\n <StyledNavigationWrapper $isChatOpen={isOpen}>\n <StyledNavigationInner>\n {prevPage ? (\n <StyledNavButton href={`/${prevPage.slug}`} data-direction=\"prev\">\n <StyledNavTitle>{prevPage.title}</StyledNavTitle>\n <StyledNavLabel>\n <Icon name=\"arrow-left\" size={16} /> Previous\n </StyledNavLabel>\n </StyledNavButton>\n ) : (\n <StyledSpacer />\n )}\n {nextPage && (\n <StyledNavButton href={`/${nextPage.slug}`} data-direction=\"next\">\n <StyledNavTitle>{nextPage.title}</StyledNavTitle>\n <StyledNavLabel>\n Next <Icon name=\"arrow-right\" size={16} />\n </StyledNavLabel>\n </StyledNavButton>\n )}\n </StyledNavigationInner>\n </StyledNavigationWrapper>\n );\n}\n\nexport { DocsNavigation };\n";
|
|
@@ -61,7 +61,7 @@ const StyledNavButton = styled(Link)<{ theme: Theme }>\`
|
|
|
61
61
|
\`;
|
|
62
62
|
|
|
63
63
|
const StyledNavLabel = styled.span<{ theme: Theme }>\`
|
|
64
|
-
color: \${({ theme }) => theme.colors.
|
|
64
|
+
color: \${({ theme }) => theme.colors.grayDark};
|
|
65
65
|
display: flex;
|
|
66
66
|
flex-direction: row;
|
|
67
67
|
gap: 4px;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const footerTemplate = "\"use client\";\nimport { useContext } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport { Space, styledSmall } from \"cherry-styled-components\";\nimport { ChatContext } from \"@/components/Chat\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { GitHubLogo } from \"@/components/layout/Pictograms\";\nimport linksData from \"@/links.json\";\n\ninterface LinkProps {\n title: string;\n url: string;\n icon?: string;\n}\n\nconst links = linksData as LinkProps[];\n\nconst StyledFooter = styled.footer<{\n theme: Theme;\n $isChatOpen?: boolean;\n $hasLinks?: boolean;\n}>`\n padding: 0 20px;\n transition: all 0.3s ease;\n\n ${({ $hasLinks }) =>\n $hasLinks &&\n css`\n margin-top: 20px;\n `}\n\n ${mq(\"lg\")} {\n margin: 0;\n padding: 0 300px 0 300px;\n\n ${({ $isChatOpen }) =>\n $isChatOpen &&\n css`\n padding: 0 440px 0 300px;\n `}\n }\n`;\n\nconst StyledFooterInner = styled.div<{ theme: Theme }>`\n border-top: solid 1px ${({ theme }) => theme.colors.grayLight};\n max-width: 640px;\n margin: 0 auto;\n padding: 28px 0;\n color: ${({ theme }) => theme.colors.
|
|
1
|
+
export declare const footerTemplate = "\"use client\";\nimport { useContext } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport { Space, styledSmall } from \"cherry-styled-components\";\nimport { ChatContext } from \"@/components/Chat\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { GitHubLogo } from \"@/components/layout/Pictograms\";\nimport linksData from \"@/links.json\";\n\ninterface LinkProps {\n title: string;\n url: string;\n icon?: string;\n}\n\nconst links = linksData as LinkProps[];\n\nconst StyledFooter = styled.footer<{\n theme: Theme;\n $isChatOpen?: boolean;\n $hasLinks?: boolean;\n}>`\n padding: 0 20px;\n transition: all 0.3s ease;\n\n ${({ $hasLinks }) =>\n $hasLinks &&\n css`\n margin-top: 20px;\n `}\n\n ${mq(\"lg\")} {\n margin: 0;\n padding: 0 300px 0 300px;\n\n ${({ $isChatOpen }) =>\n $isChatOpen &&\n css`\n padding: 0 440px 0 300px;\n `}\n }\n`;\n\nconst StyledFooterInner = styled.div<{ theme: Theme }>`\n border-top: solid 1px ${({ theme }) => theme.colors.grayLight};\n max-width: 640px;\n margin: 0 auto;\n padding: 28px 0;\n color: ${({ theme }) => theme.colors.grayDark};\n ${({ theme }) => styledSmall(theme)};\n\n ${mq(\"lg\")} {\n padding: 20px 0;\n }\n\n & a {\n font-weight: 700;\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n text-decoration: none;\n transition: all 0.3s ease;\n display: inline-flex;\n\n &:hover {\n color: ${({ theme }) => theme.colors.primaryDark};\n }\n\n & svg {\n width: 18px;\n height: 18px;\n }\n }\n`;\n\nconst StyledFooterFlex = styled.div`\n display: flex;\n justify-content: flex-start;\n align-items: center;\n gap: 20px;\n\n ${mq(\"lg\")} {\n justify-content: space-between;\n }\n`;\n\nfunction Footer({ hideBranding }: { hideBranding?: boolean }) {\n const { isOpen } = useContext(ChatContext);\n\n if (hideBranding) return <Space $xs={80} $lg=\"none\" />;\n\n return (\n <StyledFooter $isChatOpen={isOpen} $hasLinks={links.length > 0}>\n <StyledFooterInner>\n <StyledFooterFlex>\n <span>\n Powered by <a href=\"https://doccupine.com\">Doccupine</a>\n </span>\n <a\n href=\"https://github.com/doccupine/cli\"\n target=\"_blank\"\n aria-label=\"Doccupine on GitHub\"\n >\n <GitHubLogo />\n </a>\n </StyledFooterFlex>\n </StyledFooterInner>\n </StyledFooter>\n );\n}\n\nexport { Footer };\n";
|
|
@@ -47,7 +47,7 @@ const StyledFooterInner = styled.div<{ theme: Theme }>\`
|
|
|
47
47
|
max-width: 640px;
|
|
48
48
|
margin: 0 auto;
|
|
49
49
|
padding: 28px 0;
|
|
50
|
-
color: \${({ theme }) => theme.colors.
|
|
50
|
+
color: \${({ theme }) => theme.colors.grayDark};
|
|
51
51
|
\${({ theme }) => styledSmall(theme)};
|
|
52
52
|
|
|
53
53
|
\${mq("lg")} {
|
|
@@ -56,7 +56,8 @@ const StyledFooterInner = styled.div<{ theme: Theme }>\`
|
|
|
56
56
|
|
|
57
57
|
& a {
|
|
58
58
|
font-weight: 700;
|
|
59
|
-
color: \${({ theme }) =>
|
|
59
|
+
color: \${({ theme }) =>
|
|
60
|
+
theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
|
|
60
61
|
text-decoration: none;
|
|
61
62
|
transition: all 0.3s ease;
|
|
62
63
|
display: inline-flex;
|
|
@@ -95,7 +96,11 @@ function Footer({ hideBranding }: { hideBranding?: boolean }) {
|
|
|
95
96
|
<span>
|
|
96
97
|
Powered by <a href="https://doccupine.com">Doccupine</a>
|
|
97
98
|
</span>
|
|
98
|
-
<a
|
|
99
|
+
<a
|
|
100
|
+
href="https://github.com/doccupine/cli"
|
|
101
|
+
target="_blank"
|
|
102
|
+
aria-label="Doccupine on GitHub"
|
|
103
|
+
>
|
|
99
104
|
<GitHubLogo />
|
|
100
105
|
</a>
|
|
101
106
|
</StyledFooterFlex>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const sharedStyledTemplate = "\"use client\";\nimport { mq, styledSmall, styledText, Theme } from \"cherry-styled-components\";\nimport styled, { css } from \"styled-components\";\n\nexport const interactiveStyles = css<{ theme: Theme }>`\n transition: all 0.3s ease;\n border: solid 1px transparent;\n box-shadow: 0 0 0 0px ${({ theme }) => theme.colors.primary};\n\n &:hover {\n border-color: ${({ theme }) => theme.colors.primary};\n }\n\n &:focus {\n border-color: ${({ theme }) => theme.colors.primary};\n box-shadow: 0 0 0 4px ${({ theme }) => theme.colors.primaryLight};\n }\n\n &:active {\n box-shadow: 0 0 0 2px ${({ theme }) => theme.colors.primaryLight};\n }\n`;\n\nexport const styledAnchor = css<{ theme: Theme }>`\n & a:not([class]):not(:has(img)) {\n color: inherit;\n transition: all 0.3s ease;\n text-decoration: none;\n box-shadow: 0 2px 0 0 ${({ theme }) => theme.colors.primary};\n\n &:hover {\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n box-shadow: 0 1px 0 0 ${({ theme }) => theme.colors.primary};\n }\n }\n`;\n\nexport const stylesLists = css<{ theme: Theme }>`\n & ul,\n & ol {\n & li {\n & > .code-wrapper {\n margin: 10px 0;\n }\n }\n }\n\n & ul {\n list-style: none;\n padding: 0;\n margin: 0;\n\n & li {\n text-indent: 0;\n display: block;\n position: relative;\n padding: 0 0 0 15px;\n margin: 0;\n ${({ theme }) => styledText(theme)};\n min-height: 23px;\n\n ${mq(\"lg\")} {\n min-height: 27px;\n }\n\n &::before {\n content: \"\";\n display: block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: ${({ theme }) => theme.colors.primary};\n position: absolute;\n top: 8px;\n left: 2px;\n\n ${mq(\"lg\")} {\n top: 10px;\n }\n }\n }\n }\n\n & ol {\n padding: 0;\n margin: 0;\n\n & ul {\n padding-left: 15px;\n }\n\n & > li {\n position: relative;\n padding: 0;\n counter-increment: item;\n margin: 0;\n ${({ theme }) => styledText(theme)};\n\n &::before {\n content: counter(item) \".\";\n display: inline-block;\n margin: 0 4px 0 0;\n font-weight: 700;\n color: ${({ theme }) => theme.colors.primary};\n min-width: max-content;\n }\n }\n }\n`;\n\nexport const styledTable = css<{ theme: Theme }>`\n & .table-wrapper {\n overflow-x: auto;\n width: 100%;\n }\n\n & table {\n margin: 0;\n padding: 0;\n border-collapse: collapse;\n width: 100%;\n text-align: left;\n\n & tr {\n margin: 0;\n padding: 0;\n }\n\n & th {\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n padding: 10px 10px 10px 0;\n ${({ theme }) => styledSmall(theme)};\n font-weight: 600;\n color: ${({ theme }) => theme.colors.dark};\n }\n\n & td {\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n padding: 10px 10px 10px 0;\n color: ${({ theme }) => theme.colors.grayDark};\n ${({ theme }) => styledSmall(theme)};\n }\n }\n`;\n\nexport const StyledSmallButton = styled.button<{ theme: Theme }>`\n ${interactiveStyles};\n background: ${({ theme }) => theme.colors.light};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n color: ${({ theme })
|
|
1
|
+
export declare const sharedStyledTemplate = "\"use client\";\nimport { mq, styledSmall, styledText, Theme } from \"cherry-styled-components\";\nimport styled, { css } from \"styled-components\";\n\nexport const interactiveStyles = css<{ theme: Theme }>`\n transition: all 0.3s ease;\n border: solid 1px transparent;\n box-shadow: 0 0 0 0px ${({ theme }) => theme.colors.primary};\n\n &:hover {\n border-color: ${({ theme }) => theme.colors.primary};\n }\n\n &:focus {\n border-color: ${({ theme }) => theme.colors.primary};\n box-shadow: 0 0 0 4px ${({ theme }) => theme.colors.primaryLight};\n }\n\n &:active {\n box-shadow: 0 0 0 2px ${({ theme }) => theme.colors.primaryLight};\n }\n`;\n\nexport const styledAnchor = css<{ theme: Theme }>`\n & a:not([class]):not(:has(img)) {\n color: inherit;\n transition: all 0.3s ease;\n text-decoration: none;\n box-shadow: 0 2px 0 0 ${({ theme }) => theme.colors.primary};\n\n &:hover {\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n box-shadow: 0 1px 0 0 ${({ theme }) => theme.colors.primary};\n }\n }\n`;\n\nexport const stylesLists = css<{ theme: Theme }>`\n & ul,\n & ol {\n & li {\n & > .code-wrapper {\n margin: 10px 0;\n }\n }\n }\n\n & ul {\n list-style: none;\n padding: 0;\n margin: 0;\n\n & li {\n text-indent: 0;\n display: block;\n position: relative;\n padding: 0 0 0 15px;\n margin: 0;\n ${({ theme }) => styledText(theme)};\n min-height: 23px;\n\n ${mq(\"lg\")} {\n min-height: 27px;\n }\n\n &::before {\n content: \"\";\n display: block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: ${({ theme }) => theme.colors.primary};\n position: absolute;\n top: 8px;\n left: 2px;\n\n ${mq(\"lg\")} {\n top: 10px;\n }\n }\n }\n }\n\n & ol {\n padding: 0;\n margin: 0;\n\n & ul {\n padding-left: 15px;\n }\n\n & > li {\n position: relative;\n padding: 0;\n counter-increment: item;\n margin: 0;\n ${({ theme }) => styledText(theme)};\n\n &::before {\n content: counter(item) \".\";\n display: inline-block;\n margin: 0 4px 0 0;\n font-weight: 700;\n color: ${({ theme }) => theme.colors.primary};\n min-width: max-content;\n }\n }\n }\n`;\n\nexport const styledTable = css<{ theme: Theme }>`\n & .table-wrapper {\n overflow-x: auto;\n width: 100%;\n }\n\n & table {\n margin: 0;\n padding: 0;\n border-collapse: collapse;\n width: 100%;\n text-align: left;\n\n & tr {\n margin: 0;\n padding: 0;\n }\n\n & th {\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n padding: 10px 10px 10px 0;\n ${({ theme }) => styledSmall(theme)};\n font-weight: 600;\n color: ${({ theme }) => theme.colors.dark};\n }\n\n & td {\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n padding: 10px 10px 10px 0;\n color: ${({ theme }) => theme.colors.grayDark};\n ${({ theme }) => styledSmall(theme)};\n }\n }\n`;\n\nexport const StyledSmallButton = styled.button<{ theme: Theme }>`\n ${interactiveStyles};\n background: ${({ theme }) => theme.colors.light};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n border-radius: ${({ theme }) => theme.spacing.radius.xs};\n padding: 6px 8px;\n font-size: 12px;\n font-family: inherit;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.2s ease;\n display: flex;\n align-items: center;\n gap: 6px;\n margin-right: -6px;\n\n & svg.lucide {\n color: inherit;\n }\n`;\n";
|
|
@@ -148,7 +148,8 @@ export const StyledSmallButton = styled.button<{ theme: Theme }>\`
|
|
|
148
148
|
\${interactiveStyles};
|
|
149
149
|
background: \${({ theme }) => theme.colors.light};
|
|
150
150
|
border: solid 1px \${({ theme }) => theme.colors.grayLight};
|
|
151
|
-
color: \${({ theme }) =>
|
|
151
|
+
color: \${({ theme }) =>
|
|
152
|
+
theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
|
|
152
153
|
border-radius: \${({ theme }) => theme.spacing.radius.xs};
|
|
153
154
|
padding: 6px 8px;
|
|
154
155
|
font-size: 12px;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const staticLinksTemplate = "\"use client\";\nimport styled, { css } from \"styled-components\";\nimport { rgba } from \"polished\";\nimport { useContext } from \"react\";\nimport { ChatContext } from \"@/components/Chat\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { interactiveStyles } from \"@/components/layout/SharedStyled\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport linksData from \"@/links.json\";\n\ninterface LinkProps {\n title: string;\n url: string;\n icon?: string;\n}\n\nconst links = linksData as LinkProps[];\n\nconst StyledStaticLinks = styled.div<{ theme: Theme; $isChatOpen: boolean }>`\n display: flex;\n margin: 0 auto;\n transition: all 0.3s ease;\n padding: 0 20px;\n margin-bottom: 20px;\n\n ${mq(\"lg\")} {\n margin: 0;\n padding: 0 300px 20px 300px;\n\n ${({ $isChatOpen }) =>\n $isChatOpen &&\n css`\n padding: 0 440px 20px 300px;\n `}\n }\n`;\n\nconst StyledStaticLinksContent = styled.div`\n max-width: 640px;\n margin: auto 0;\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n width: 100%;\n margin: 0 auto;\n`;\n\nconst StyledLink = styled.a<{ theme: Theme; $hasIcon?: boolean }>`\n position: relative;\n text-decoration: none;\n font-size: ${({ theme }) => theme.fontSizes.small.lg};\n line-height: 1;\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.
|
|
1
|
+
export declare const staticLinksTemplate = "\"use client\";\nimport styled, { css } from \"styled-components\";\nimport { rgba } from \"polished\";\nimport { useContext } from \"react\";\nimport { ChatContext } from \"@/components/Chat\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { interactiveStyles } from \"@/components/layout/SharedStyled\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport linksData from \"@/links.json\";\n\ninterface LinkProps {\n title: string;\n url: string;\n icon?: string;\n}\n\nconst links = linksData as LinkProps[];\n\nconst StyledStaticLinks = styled.div<{ theme: Theme; $isChatOpen: boolean }>`\n display: flex;\n margin: 0 auto;\n transition: all 0.3s ease;\n padding: 0 20px;\n margin-bottom: 20px;\n\n ${mq(\"lg\")} {\n margin: 0;\n padding: 0 300px 20px 300px;\n\n ${({ $isChatOpen }) =>\n $isChatOpen &&\n css`\n padding: 0 440px 20px 300px;\n `}\n }\n`;\n\nconst StyledStaticLinksContent = styled.div`\n max-width: 640px;\n margin: auto 0;\n display: flex;\n gap: 16px;\n flex-wrap: wrap;\n width: 100%;\n margin: 0 auto;\n`;\n\nconst StyledLink = styled.a<{ theme: Theme; $hasIcon?: boolean }>`\n position: relative;\n text-decoration: none;\n font-size: ${({ theme }) => theme.fontSizes.small.lg};\n line-height: 1;\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n padding: 0;\n display: flex;\n gap: 6px;\n transition: all 0.3s ease;\n font-weight: 600;\n white-space: nowrap;\n min-width: fit-content;\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.1)};\n padding: 6px 8px;\n border-radius: ${({ theme }) => theme.spacing.radius.xs};\n ${interactiveStyles};\n\n ${({ $hasIcon }) =>\n $hasIcon &&\n css`\n padding-left: 30px;\n `}\n\n & * {\n margin: auto 0;\n }\n\n & svg {\n position: absolute;\n top: 50%;\n left: 8px;\n transform: translateY(-50%);\n }\n\n &:hover {\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n }\n`;\n\nfunction StaticLinks() {\n const { isOpen } = useContext(ChatContext);\n\n if (links.length === 0) {\n return null;\n }\n\n return (\n <>\n <StyledStaticLinks $isChatOpen={isOpen}>\n <StyledStaticLinksContent>\n {links.map((link, index) => (\n <StyledLink\n key={index}\n href={link.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n $hasIcon={link.icon ? true : false}\n >\n {link.icon && <Icon name={link.icon} size={16} />}\n <span>{link.title}</span>\n </StyledLink>\n ))}\n </StyledStaticLinksContent>\n </StyledStaticLinks>\n </>\n );\n}\n\nexport { StaticLinks };\n";
|
|
@@ -52,7 +52,7 @@ const StyledLink = styled.a<{ theme: Theme; $hasIcon?: boolean }>\`
|
|
|
52
52
|
font-size: \${({ theme }) => theme.fontSizes.small.lg};
|
|
53
53
|
line-height: 1;
|
|
54
54
|
color: \${({ theme }) =>
|
|
55
|
-
theme.isDark ? theme.colors.
|
|
55
|
+
theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
|
|
56
56
|
padding: 0;
|
|
57
57
|
display: flex;
|
|
58
58
|
gap: 6px;
|
|
@@ -89,12 +89,12 @@ const StyledLink = styled.a<{ theme: Theme; $hasIcon?: boolean }>\`
|
|
|
89
89
|
\`;
|
|
90
90
|
|
|
91
91
|
function StaticLinks() {
|
|
92
|
+
const { isOpen } = useContext(ChatContext);
|
|
93
|
+
|
|
92
94
|
if (links.length === 0) {
|
|
93
95
|
return null;
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
const { isOpen } = useContext(ChatContext);
|
|
97
|
-
|
|
98
98
|
return (
|
|
99
99
|
<>
|
|
100
100
|
<StyledStaticLinks $isChatOpen={isOpen}>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const listsAndTablesMdxTemplate = "---\ntitle: \"Lists and tables\"\ndescription: \"Present structured information using lists or tables.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 2\n---\n# Lists and Tables\nPresent structured information using lists or tables.\n\n## Lists\nMarkdown supports both *ordered* and *unordered* lists, as well as nested list structures.\n\n### Ordered List\nStart each item with a number followed by a period to create an ordered list.\n\n```md\n1. First item\n2. Second item\n3. Third item\n4. Fourth item\n```\n\n1. First item\n2. Second item\n3. Third item\n4. Fourth item\n\n\n### Unordered List\nUse dashes (`-`), asterisks (`*`), or plus signs (`+`) before each item for unordered lists.\n\n```md\n- First item\n- Second item\n- Third item\n- Fourth item\n```\n\n- First item\n- Second item\n- Third item\n- Fourth item\n\n### Nested List\nIndent items under another to create nested lists.\n\n```md\n- First item\n- Second item\n - Additional item\n - Additional item\n- Third item\n```\n\n- First item\n- Second item\n - Additional item\n - Additional item\n- Third item\n\n## Tables\nMarkdown tables use pipes (`|`) to separate columns and hyphens (`---`) to define the header row. Place a pipe at the start and end of each row for better compatibility.\n\n```md\n| Property | Description |\n| -------- | -------------------------------------- |\n| Name | Full name of the user |\n| Age | Age in years |\n| Joined | Indicates if user joined the community |\n```\n\n| Property | Description |\n| -------- | -------------------------------------- |\n| Name | Full name of the user |\n| Age | Age in years |\n| Joined | Indicates if user joined the community |";
|