doccupine 0.0.83 → 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 +7 -2
- package/dist/lib/structures.js +6 -0
- 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/DocsSideBar.d.ts +1 -1
- package/dist/templates/components/DocsSideBar.js +2 -2
- 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 +1 -1
- package/dist/templates/mdx/theme.mdx.d.ts +1 -1
- package/dist/templates/mdx/theme.mdx.js +1 -1
- package/dist/templates/package.js +10 -10
- 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 +3 -3
|
@@ -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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const themeMdxTemplate = "---\ntitle: \"Theme\"\ndescription: \"Customize the documentation UI colors with a theme.json file.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 5\n---\n# Theme\nDefine your site\u2019s color system with a `theme.json` file. This lets you tailor the look and feel of your documentation without changing content.\n\n## theme.json\nPlace a `theme.json` at your project root (the same folder where you execute `npx doccupine`). It supports multiple modes. Define a `default` mode and a `dark` mode.\n\n```json\n{\n \"default\": {\n \"primaryLight\": \"#93c5fd\",\n \"primary\": \"#
|
|
1
|
+
export declare const themeMdxTemplate = "---\ntitle: \"Theme\"\ndescription: \"Customize the documentation UI colors with a theme.json file.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 5\n---\n# Theme\nDefine your site\u2019s color system with a `theme.json` file. This lets you tailor the look and feel of your documentation without changing content.\n\n## theme.json\nPlace a `theme.json` at your project root (the same folder where you execute `npx doccupine`). It supports multiple modes. Define a `default` mode and a `dark` mode.\n\n```json\n{\n \"default\": {\n \"primaryLight\": \"#93c5fd\",\n \"primary\": \"#2563eb\",\n \"primaryDark\": \"#1e40af\",\n \"secondaryLight\": \"#c4b5fd\",\n \"secondary\": \"#8b5cf6\",\n \"secondaryDark\": \"#5b21b6\",\n \"tertiaryLight\": \"#fbbf24\",\n \"tertiary\": \"#f59e0b\",\n \"tertiaryDark\": \"#d97706\",\n \"grayLight\": \"#f3f4f6\",\n \"gray\": \"#9ca3af\",\n \"grayDark\": \"#374151\",\n \"success\": \"#10b981\",\n \"error\": \"#f43f5e\",\n \"warning\": \"#f59e0b\",\n \"info\": \"#3b82f6\",\n \"dark\": \"#000000\",\n \"light\": \"#ffffff\"\n },\n \"dark\": {\n \"primaryLight\": \"#9bcaff\",\n \"primary\": \"#1e7ae0\",\n \"primaryDark\": \"#033d7e\",\n \"secondaryLight\": \"#ddd6fe\",\n \"secondary\": \"#a78bfa\",\n \"secondaryDark\": \"#7c3aed\",\n \"tertiaryLight\": \"#fed7aa\",\n \"tertiary\": \"#fb923c\",\n \"tertiaryDark\": \"#ea580c\",\n \"grayLight\": \"#1f2937\",\n \"gray\": \"#6b7280\",\n \"grayDark\": \"#9ca3af\",\n \"success\": \"#10b981\",\n \"error\": \"#f43f5e\",\n \"warning\": \"#f59e0b\",\n \"info\": \"#3b82f6\",\n \"dark\": \"#ffffff\",\n \"light\": \"#000000\"\n },\n \"logo\": {\n \"dark\": \"https://docs.doccupine.com/logo-dark.svg\",\n \"light\": \"https://docs.doccupine.com/logo-light.svg\"\n }\n}\n```\n\n## Modes\n- **default**: The base color palette for your site.\n- **dark**: Dark\u2011mode palette.\n\n## Fields\n- **primaryLight**: A lighter variant of your brand color, used for subtle accents and backgrounds.\n- **primary**: The main brand color.\n- **primaryDark**: A darker variant of your brand color for emphasis and hover states.\n- **secondaryLight**: A lighter variant of your secondary color, used for subtle accents and backgrounds.\n- **secondary**: The secondary brand color used for highlights and UI accents.\n- **secondaryDark**: A darker variant of your secondary color for emphasis and hover states.\n- **tertiaryLight**: A lighter variant of your tertiary color, used for subtle accents and backgrounds.\n- **tertiary**: The tertiary accent color.\n- **tertiaryDark**: A darker variant of your tertiary color for emphasis and hover states.\n- **grayLight**: Light gray for surfaces and borders.\n- **gray**: Neutral gray for text and UI elements.\n- **grayDark**: Dark gray for headings or high\u2011contrast text.\n- **success**: Positive/confirmation color.\n- **error**: Error/destructive color.\n- **warning**: Warning/attention color.\n- **info**: Informational/highlight color.\n- **dark**: The darkest/base color (often page background in dark mode).\n- **light**: The lightest/base color (often page background in light mode).\n- **logo.light**: Path or URL to the logo used on light backgrounds. Recommended size: 164\u00D730 px.\n- **logo.dark**: Path or URL to the logo used on dark backgrounds. Recommended size: 164\u00D730 px.\n\n## Behavior\n- **Placement**: Put `theme.json` in the project root alongside `config.json`.\n- **Partial palettes**: If a key is missing in a mode, consumers may fall back to the `default` value.\n- **Logo size**: Recommended dimensions are 164px width and 30px height.\n\n<Callout type=\"warning\">\n Use valid hex colors (e.g., `#22c55e`). Invalid color values may cause unexpected rendering.\n</Callout>\n\n## Tips\n- **Contrast**: Ensure sufficient contrast between text and backgrounds for readability.\n- **Branding**: Start with your brand\u2019s `primary` color, then derive `primaryLight` and `primaryDark`.\n- **Iterate**: Adjust colors and refresh the site to preview changes quickly.\n\n# Demo\nIn the following demos, you can see how the theme can be changed. To override the theme, create a `theme.json` file in the project root and copy paste the code below.\n\n<DemoTheme variant=\"purple\" />\n<DemoTheme variant=\"green\" />\n<DemoTheme variant=\"yellow\" />\n<DemoTheme />\n\n## Purple\n\n```json\n{\n \"default\": {\n \"primaryLight\": \"#c4b5fd\",\n \"primary\": \"#8b5cf6\",\n \"primaryDark\": \"#5b21b6\",\n \"secondaryLight\": \"#86efac\",\n \"secondary\": \"#22c55e\",\n \"secondaryDark\": \"#15803d\",\n \"tertiaryLight\": \"#fbbf24\",\n \"tertiary\": \"#f59e0b\",\n \"tertiaryDark\": \"#d97706\",\n \"grayLight\": \"#f3f4f6\",\n \"gray\": \"#9ca3af\",\n \"grayDark\": \"#374151\",\n \"success\": \"#10b981\",\n \"error\": \"#f43f5e\",\n \"warning\": \"#f59e0b\",\n \"info\": \"#3b82f6\",\n \"dark\": \"#000000\",\n \"light\": \"#ffffff\"\n },\n \"dark\": {\n \"primaryLight\": \"#ddd6fe\",\n \"primary\": \"#a78bfa\",\n \"primaryDark\": \"#7c3aed\",\n \"secondaryLight\": \"#6ee7b7\",\n \"secondary\": \"#10b981\",\n \"secondaryDark\": \"#065f46\",\n \"tertiaryLight\": \"#fed7aa\",\n \"tertiary\": \"#fb923c\",\n \"tertiaryDark\": \"#ea580c\",\n \"grayLight\": \"#1f2937\",\n \"gray\": \"#6b7280\",\n \"grayDark\": \"#9ca3af\",\n \"success\": \"#10b981\",\n \"error\": \"#f43f5e\",\n \"warning\": \"#f59e0b\",\n \"info\": \"#3b82f6\",\n \"dark\": \"#ffffff\",\n \"light\": \"#000000\"\n }\n}\n```\n<DemoTheme variant=\"purple\" />\n\n## Green\n\n```json\n{\n \"default\": {\n \"primaryLight\": \"#86efac\",\n \"primary\": \"#22c55e\",\n \"primaryDark\": \"#15803d\",\n \"secondaryLight\": \"#c4b5fd\",\n \"secondary\": \"#8b5cf6\",\n \"secondaryDark\": \"#5b21b6\",\n \"tertiaryLight\": \"#fbbf24\",\n \"tertiary\": \"#f59e0b\",\n \"tertiaryDark\": \"#d97706\",\n \"grayLight\": \"#f3f4f6\",\n \"gray\": \"#9ca3af\",\n \"grayDark\": \"#374151\",\n \"success\": \"#10b981\",\n \"error\": \"#f43f5e\",\n \"warning\": \"#f59e0b\",\n \"info\": \"#3b82f6\",\n \"dark\": \"#000000\",\n \"light\": \"#ffffff\"\n },\n \"dark\": {\n \"primaryLight\": \"#6ee7b7\",\n \"primary\": \"#10b981\",\n \"primaryDark\": \"#065f46\",\n \"secondaryLight\": \"#ddd6fe\",\n \"secondary\": \"#a78bfa\",\n \"secondaryDark\": \"#7c3aed\",\n \"tertiaryLight\": \"#fed7aa\",\n \"tertiary\": \"#fb923c\",\n \"tertiaryDark\": \"#ea580c\",\n \"grayLight\": \"#1f2937\",\n \"gray\": \"#6b7280\",\n \"grayDark\": \"#9ca3af\",\n \"success\": \"#10b981\",\n \"error\": \"#f43f5e\",\n \"warning\": \"#f59e0b\",\n \"info\": \"#3b82f6\",\n \"dark\": \"#ffffff\",\n \"light\": \"#000000\"\n }\n}\n```\n<DemoTheme variant=\"green\" />\n\n## Yellow\n\n```json\n{\n \"default\": {\n \"primaryLight\": \"#fbbf24\",\n \"primary\": \"#f59e0b\",\n \"primaryDark\": \"#d97706\",\n \"secondaryLight\": \"#c4b5fd\",\n \"secondary\": \"#8b5cf6\",\n \"secondaryDark\": \"#5b21b6\",\n \"tertiaryLight\": \"#86efac\",\n \"tertiary\": \"#22c55e\",\n \"tertiaryDark\": \"#15803d\",\n \"grayLight\": \"#f3f4f6\",\n \"gray\": \"#9ca3af\",\n \"grayDark\": \"#374151\",\n \"success\": \"#10b981\",\n \"error\": \"#f43f5e\",\n \"warning\": \"#f59e0b\",\n \"info\": \"#3b82f6\",\n \"dark\": \"#000000\",\n \"light\": \"#ffffff\"\n },\n \"dark\": {\n \"primaryLight\": \"#fed7aa\",\n \"primary\": \"#fb923c\",\n \"primaryDark\": \"#ea580c\",\n \"secondaryLight\": \"#ddd6fe\",\n \"secondary\": \"#a78bfa\",\n \"secondaryDark\": \"#7c3aed\",\n \"tertiaryLight\": \"#6ee7b7\",\n \"tertiary\": \"#10b981\",\n \"tertiaryDark\": \"#065f46\",\n \"grayLight\": \"#1f2937\",\n \"gray\": \"#6b7280\",\n \"grayDark\": \"#9ca3af\",\n \"success\": \"#10b981\",\n \"error\": \"#f43f5e\",\n \"warning\": \"#f59e0b\",\n \"info\": \"#3b82f6\",\n \"dark\": \"#ffffff\",\n \"light\": \"#000000\"\n }\n}\n```\n\n<DemoTheme variant=\"yellow\" />";
|
|
@@ -16,7 +16,7 @@ Place a \`theme.json\` at your project root (the same folder where you execute \
|
|
|
16
16
|
{
|
|
17
17
|
"default": {
|
|
18
18
|
"primaryLight": "#93c5fd",
|
|
19
|
-
"primary": "#
|
|
19
|
+
"primary": "#2563eb",
|
|
20
20
|
"primaryDark": "#1e40af",
|
|
21
21
|
"secondaryLight": "#c4b5fd",
|
|
22
22
|
"secondary": "#8b5cf6",
|