doccupine 0.0.63 → 0.0.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +4 -3
  2. package/dist/lib/structures.js +2 -0
  3. package/dist/templates/app/theme.d.ts +3 -1
  4. package/dist/templates/app/theme.js +17 -15
  5. package/dist/templates/components/Chat.d.ts +1 -1
  6. package/dist/templates/components/Chat.js +251 -158
  7. package/dist/templates/components/DocsSideBar.d.ts +1 -1
  8. package/dist/templates/components/DocsSideBar.js +34 -11
  9. package/dist/templates/components/SideBar.d.ts +1 -1
  10. package/dist/templates/components/SideBar.js +12 -2
  11. package/dist/templates/components/layout/Accordion.d.ts +1 -1
  12. package/dist/templates/components/layout/Accordion.js +1 -1
  13. package/dist/templates/components/layout/ActionBar.d.ts +1 -1
  14. package/dist/templates/components/layout/ActionBar.js +15 -60
  15. package/dist/templates/components/layout/Callout.d.ts +1 -1
  16. package/dist/templates/components/layout/Callout.js +1 -1
  17. package/dist/templates/components/layout/Card.d.ts +1 -1
  18. package/dist/templates/components/layout/Card.js +26 -7
  19. package/dist/templates/components/layout/Columns.d.ts +1 -1
  20. package/dist/templates/components/layout/Columns.js +1 -1
  21. package/dist/templates/components/layout/DocsComponents.d.ts +1 -1
  22. package/dist/templates/components/layout/DocsComponents.js +37 -11
  23. package/dist/templates/components/layout/DocsNavigation.d.ts +1 -1
  24. package/dist/templates/components/layout/DocsNavigation.js +3 -2
  25. package/dist/templates/components/layout/Field.d.ts +1 -1
  26. package/dist/templates/components/layout/Field.js +1 -1
  27. package/dist/templates/components/layout/Footer.d.ts +1 -1
  28. package/dist/templates/components/layout/Footer.js +28 -6
  29. package/dist/templates/components/layout/Header.d.ts +1 -1
  30. package/dist/templates/components/layout/Header.js +10 -12
  31. package/dist/templates/components/layout/SharedStyles.d.ts +1 -1
  32. package/dist/templates/components/layout/SharedStyles.js +26 -2
  33. package/dist/templates/components/layout/StaticLinks.d.ts +1 -1
  34. package/dist/templates/components/layout/StaticLinks.js +7 -3
  35. package/dist/templates/components/layout/Steps.d.ts +1 -1
  36. package/dist/templates/components/layout/Steps.js +7 -2
  37. package/dist/templates/components/layout/Tabs.d.ts +1 -1
  38. package/dist/templates/components/layout/Tabs.js +2 -2
  39. package/dist/templates/components/layout/Update.d.ts +1 -1
  40. package/dist/templates/components/layout/Update.js +1 -1
  41. package/dist/templates/mdx/ai-assistant.mdx.d.ts +1 -1
  42. package/dist/templates/mdx/ai-assistant.mdx.js +8 -0
  43. package/dist/templates/mdx/callouts.mdx.d.ts +1 -1
  44. package/dist/templates/mdx/callouts.mdx.js +6 -2
  45. package/dist/templates/mdx/cards.mdx.d.ts +1 -1
  46. package/dist/templates/mdx/cards.mdx.js +19 -3
  47. package/dist/templates/mdx/columns.mdx.d.ts +1 -1
  48. package/dist/templates/mdx/columns.mdx.js +2 -2
  49. package/dist/templates/mdx/commands.mdx.d.ts +1 -1
  50. package/dist/templates/mdx/commands.mdx.js +10 -2
  51. package/dist/templates/mdx/components.mdx.d.ts +1 -0
  52. package/dist/templates/mdx/components.mdx.js +56 -0
  53. package/dist/templates/mdx/deployment.mdx.d.ts +1 -1
  54. package/dist/templates/mdx/deployment.mdx.js +1 -1
  55. package/dist/templates/mdx/globals.mdx.d.ts +1 -1
  56. package/dist/templates/mdx/globals.mdx.js +5 -0
  57. package/dist/templates/mdx/index.mdx.d.ts +1 -1
  58. package/dist/templates/mdx/index.mdx.js +5 -5
  59. package/dist/templates/mdx/model-context-protocol.mdx.d.ts +1 -1
  60. package/dist/templates/mdx/model-context-protocol.mdx.js +2 -2
  61. package/dist/templates/mdx/navigation.mdx.d.ts +1 -1
  62. package/dist/templates/mdx/navigation.mdx.js +1 -1
  63. package/dist/templates/mdx/platform/external-links.mdx.d.ts +1 -1
  64. package/dist/templates/mdx/platform/external-links.mdx.js +2 -0
  65. package/dist/templates/mdx/platform/fonts-settings.mdx.d.ts +1 -1
  66. package/dist/templates/mdx/platform/fonts-settings.mdx.js +8 -5
  67. package/dist/templates/mdx/platform/index.mdx.d.ts +1 -1
  68. package/dist/templates/mdx/platform/index.mdx.js +10 -1
  69. package/dist/templates/mdx/platform/site-settings.mdx.d.ts +1 -1
  70. package/dist/templates/mdx/platform/site-settings.mdx.js +4 -4
  71. package/dist/templates/mdx/sections.mdx.d.ts +1 -1
  72. package/dist/templates/mdx/sections.mdx.js +2 -2
  73. package/dist/templates/mdx/steps.mdx.d.ts +1 -1
  74. package/dist/templates/mdx/steps.mdx.js +4 -0
  75. package/dist/templates/mdx/tabs.mdx.d.ts +1 -1
  76. package/dist/templates/mdx/tabs.mdx.js +1 -1
  77. package/dist/templates/package.js +4 -4
  78. package/dist/templates/services/llm/types.d.ts +1 -1
  79. package/dist/templates/services/llm/types.js +1 -1
  80. package/dist/templates/services/mcp/server.d.ts +1 -1
  81. package/dist/templates/services/mcp/server.js +1 -1
  82. package/dist/templates/services/mcp/tools.d.ts +1 -1
  83. package/dist/templates/services/mcp/tools.js +1 -5
  84. package/dist/templates/utils/config.d.ts +1 -1
  85. package/dist/templates/utils/config.js +1 -1
  86. package/package.json +1 -1
@@ -1,3 +1,4 @@
1
+ import { SIDEBAR_WIDTH, CHAT_WIDTH } from "../../app/theme.js";
1
2
  export const footerTemplate = `"use client";
2
3
  import { useContext } from "react";
3
4
  import styled, { css } from "styled-components";
@@ -5,17 +6,38 @@ import { Space, styledSmall } from "cherry-styled-components";
5
6
  import { ChatContext } from "@/components/Chat";
6
7
  import { mq, Theme } from "@/app/theme";
7
8
  import { GitHubLogo } from "@/components/layout/Pictograms";
9
+ import linksData from "@/links.json";
8
10
 
9
- const StyledFooter = styled.footer<{ theme: Theme; $isChatOpen?: boolean }>\`
10
- padding: 20px;
11
+ interface LinkProps {
12
+ title: string;
13
+ url: string;
14
+ icon?: string;
15
+ }
16
+
17
+ const links = linksData as LinkProps[];
18
+
19
+ const StyledFooter = styled.footer<{
20
+ theme: Theme;
21
+ $isChatOpen?: boolean;
22
+ $hasLinks?: boolean;
23
+ }>\`
24
+ padding: 0 20px 20px 20px;
11
25
  transition: all 0.3s ease;
12
26
 
27
+ \${({ $hasLinks }) =>
28
+ $hasLinks &&
29
+ css\`
30
+ margin-top: 20px;
31
+ \`}
32
+
13
33
  \${mq("lg")} {
14
- padding: 0 340px 0 340px;
34
+ margin: 0;
35
+ padding: 0 ${SIDEBAR_WIDTH + 20}px 0 ${SIDEBAR_WIDTH + 20}px;
36
+
15
37
  \${({ $isChatOpen }) =>
16
38
  $isChatOpen &&
17
39
  css\`
18
- padding: 0 440px 0 340px;
40
+ padding: 0 ${CHAT_WIDTH + 20}px 0 ${SIDEBAR_WIDTH + 20}px;
19
41
  \`}
20
42
  }
21
43
  \`;
@@ -58,10 +80,10 @@ const StyledFooterFlex = styled.div\`
58
80
  function Footer({ hideBranding }: { hideBranding?: boolean }) {
59
81
  const { isOpen } = useContext(ChatContext);
60
82
 
61
- if (hideBranding) return <Space $xs={70} $lg="none" />;
83
+ if (hideBranding) return <Space $xs={80} $lg="none" />;
62
84
 
63
85
  return (
64
- <StyledFooter $isChatOpen={isOpen}>
86
+ <StyledFooter $isChatOpen={isOpen} $hasLinks={links.length > 0}>
65
87
  <StyledFooterInner>
66
88
  <StyledFooterFlex>
67
89
  <span>
@@ -1 +1 @@
1
- export declare const headerTemplate = "\"use client\";\nimport React from \"react\";\nimport { useCallback, useRef, useState, Suspense } from \"react\";\nimport styled, { css, useTheme } from \"styled-components\";\nimport Link from \"next/link\";\nimport { rgba } from \"polished\";\nimport { mq, Theme } from \"@/app/theme\";\nimport {\n ToggleTheme,\n ToggleThemeLoading,\n} from \"@/components/layout/ThemeToggle\";\nimport { useOnClickOutside } from \"@/components/ClickOutside\";\nimport { Logo } from \"@/components/layout/Pictograms\";\nimport themeJson from \"@/theme.json\";\n\nconst customThemeJson = themeJson as typeof themeJson & {\n logo?: { dark: string; light: string };\n};\n\nconst StyledHeader = styled.header<{ theme: Theme; $hasChildren: boolean }>`\n position: sticky;\n top: 0;\n margin: 0;\n z-index: 1000;\n width: 100%;\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n\n ${({ $hasChildren }) =>\n !$hasChildren &&\n css`\n ${mq(\"lg\")} {\n padding-bottom: 16px;\n padding-top: 16px;\n }\n `}\n\n &::before,\n &::after {\n display: block;\n content: \"\";\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n background: ${({ theme }) => theme.colors.light};\n z-index: -2;\n }\n\n &::after {\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.05)};\n z-index: -1;\n }\n\n & .logo {\n display: flex;\n\n & svg,\n & img {\n margin: auto;\n height: auto;\n width: fit-content;\n min-width: fit-content;\n max-width: 182px;\n max-height: 30px;\n\n & path[fill] {\n fill: ${({ theme }) => theme.colors.primary};\n }\n }\n }\n`;\n\nconst StyledHeaderInner = styled.div<{ $hasChildren: boolean }>`\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-wrap: wrap;\n padding: 16px 0 0 20px;\n\n ${({ $hasChildren }) =>\n !$hasChildren &&\n css`\n padding-bottom: 16px;\n `}\n\n ${mq(\"lg\")} {\n flex-wrap: nowrap;\n padding: 0 20px;\n }\n`;\n\nconst StyledThemeWrapper = styled.div`\n display: block;\n min-width: fit-content;\n padding-right: 20px;\n\n ${mq(\"lg\")} {\n padding-right: 0;\n }\n`;\n\ninterface HeaderProps {\n children?: React.ReactNode;\n}\n\nfunction Header({ children }: HeaderProps) {\n const [isOptionActive, setIsOptionActive] = useState(false);\n const [isLangActive, setIsLangActive] = useState(false);\n\n const wrapperRef = useRef<HTMLSpanElement>(null);\n const elmRef = useRef<HTMLDivElement>(null);\n const langRef = useRef<HTMLSpanElement>(null);\n const closeMenu = useCallback(() => {\n setIsOptionActive(false);\n setIsLangActive(false);\n }, []);\n\n useOnClickOutside(\n [elmRef, wrapperRef],\n isOptionActive ? closeMenu : () => {},\n );\n useOnClickOutside([langRef, wrapperRef], isLangActive ? closeMenu : () => {});\n const theme = useTheme() as Theme;\n\n return (\n <StyledHeader $hasChildren={children ? true : false} id=\"header\">\n <StyledHeaderInner $hasChildren={children ? true : false}>\n <Link href=\"/\" className=\"logo\" aria-label=\"Logo\">\n {customThemeJson.logo ? (\n theme.isDark ? (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={customThemeJson.logo.dark}\n alt=\"Logo\"\n width=\"100\"\n height=\"100\"\n />\n ) : (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={customThemeJson.logo.light}\n alt=\"Logo\"\n width=\"100\"\n height=\"100\"\n />\n )\n ) : (\n <Logo />\n )}\n </Link>\n {children}\n <StyledThemeWrapper>\n <Suspense fallback={<ToggleThemeLoading />}>\n <ToggleTheme />\n </Suspense>\n </StyledThemeWrapper>\n </StyledHeaderInner>\n </StyledHeader>\n );\n}\n\nexport { Header };\n";
1
+ export declare const headerTemplate = "\"use client\";\nimport React from \"react\";\nimport { useCallback, useContext, useRef, useState } from \"react\";\nimport styled, { css, useTheme } from \"styled-components\";\nimport Link from \"next/link\";\nimport { rgba } from \"polished\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { useOnClickOutside } from \"@/components/ClickOutside\";\nimport { Logo } from \"@/components/layout/Pictograms\";\nimport { ChatContext, ChatButtonCTA } from \"@/components/Chat\";\nimport themeJson from \"@/theme.json\";\n\nconst customThemeJson = themeJson as typeof themeJson & {\n logo?: { dark: string; light: string };\n};\n\nconst StyledHeader = styled.header<{ theme: Theme; $hasChildren: boolean }>`\n position: sticky;\n top: 0;\n margin: 0;\n z-index: 1000;\n width: 100%;\n border-bottom: solid 1px ${({ theme }) => theme.colors.grayLight};\n\n ${({ $hasChildren }) =>\n !$hasChildren &&\n css`\n ${mq(\"lg\")} {\n padding-bottom: 16px;\n padding-top: 16px;\n }\n `}\n\n &::before,\n &::after {\n display: block;\n content: \"\";\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n background: ${({ theme }) => theme.colors.light};\n z-index: -2;\n }\n\n &::after {\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.05)};\n z-index: -1;\n }\n\n & .logo {\n display: flex;\n\n & svg,\n & img {\n margin: auto;\n height: auto;\n width: fit-content;\n min-width: fit-content;\n max-width: 182px;\n max-height: 30px;\n\n & path[fill] {\n fill: ${({ theme }) => theme.colors.primary};\n }\n }\n }\n`;\n\nconst StyledHeaderInner = styled.div<{ $hasChildren: boolean }>`\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-wrap: wrap;\n padding: 16px 0 0 20px;\n\n ${({ $hasChildren }) =>\n !$hasChildren &&\n css`\n padding-bottom: 16px;\n `}\n\n ${mq(\"lg\")} {\n flex-wrap: nowrap;\n padding: 0 20px;\n }\n`;\n\nconst StyledLeftWrapper = styled.div`\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: fit-content;\n padding-right: 20px;\n\n ${mq(\"lg\")} {\n padding-right: 0;\n }\n`;\n\ninterface HeaderProps {\n children?: React.ReactNode;\n}\n\nfunction Header({ children }: HeaderProps) {\n const [isOptionActive, setIsOptionActive] = useState(false);\n const [isLangActive, setIsLangActive] = useState(false);\n\n const wrapperRef = useRef<HTMLSpanElement>(null);\n const elmRef = useRef<HTMLDivElement>(null);\n const langRef = useRef<HTMLSpanElement>(null);\n const closeMenu = useCallback(() => {\n setIsOptionActive(false);\n setIsLangActive(false);\n }, []);\n\n useOnClickOutside(\n [elmRef, wrapperRef],\n isOptionActive ? closeMenu : () => {},\n );\n useOnClickOutside([langRef, wrapperRef], isLangActive ? closeMenu : () => {});\n const theme = useTheme() as Theme;\n const { isChatActive } = useContext(ChatContext);\n\n return (\n <StyledHeader $hasChildren={children ? true : false} id=\"header\">\n <StyledHeaderInner $hasChildren={children ? true : false}>\n <Link href=\"/\" className=\"logo\" aria-label=\"Logo\">\n {customThemeJson.logo ? (\n theme.isDark ? (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={customThemeJson.logo.dark}\n alt=\"Logo\"\n width=\"100\"\n height=\"100\"\n />\n ) : (\n // eslint-disable-next-line @next/next/no-img-element\n <img\n src={customThemeJson.logo.light}\n alt=\"Logo\"\n width=\"100\"\n height=\"100\"\n />\n )\n ) : (\n <Logo />\n )}\n </Link>\n {children}\n <StyledLeftWrapper>\n {isChatActive && <ChatButtonCTA />}\n </StyledLeftWrapper>\n </StyledHeaderInner>\n </StyledHeader>\n );\n}\n\nexport { Header };\n";
@@ -1,16 +1,13 @@
1
1
  export const headerTemplate = `"use client";
2
2
  import React from "react";
3
- import { useCallback, useRef, useState, Suspense } from "react";
3
+ import { useCallback, useContext, useRef, useState } from "react";
4
4
  import styled, { css, useTheme } from "styled-components";
5
5
  import Link from "next/link";
6
6
  import { rgba } from "polished";
7
7
  import { mq, Theme } from "@/app/theme";
8
- import {
9
- ToggleTheme,
10
- ToggleThemeLoading,
11
- } from "@/components/layout/ThemeToggle";
12
8
  import { useOnClickOutside } from "@/components/ClickOutside";
13
9
  import { Logo } from "@/components/layout/Pictograms";
10
+ import { ChatContext, ChatButtonCTA } from "@/components/Chat";
14
11
  import themeJson from "@/theme.json";
15
12
 
16
13
  const customThemeJson = themeJson as typeof themeJson & {
@@ -91,8 +88,10 @@ const StyledHeaderInner = styled.div<{ $hasChildren: boolean }>\`
91
88
  }
92
89
  \`;
93
90
 
94
- const StyledThemeWrapper = styled.div\`
95
- display: block;
91
+ const StyledLeftWrapper = styled.div\`
92
+ display: flex;
93
+ align-items: center;
94
+ gap: 8px;
96
95
  min-width: fit-content;
97
96
  padding-right: 20px;
98
97
 
@@ -123,6 +122,7 @@ function Header({ children }: HeaderProps) {
123
122
  );
124
123
  useOnClickOutside([langRef, wrapperRef], isLangActive ? closeMenu : () => {});
125
124
  const theme = useTheme() as Theme;
125
+ const { isChatActive } = useContext(ChatContext);
126
126
 
127
127
  return (
128
128
  <StyledHeader $hasChildren={children ? true : false} id="header">
@@ -151,11 +151,9 @@ function Header({ children }: HeaderProps) {
151
151
  )}
152
152
  </Link>
153
153
  {children}
154
- <StyledThemeWrapper>
155
- <Suspense fallback={<ToggleThemeLoading />}>
156
- <ToggleTheme />
157
- </Suspense>
158
- </StyledThemeWrapper>
154
+ <StyledLeftWrapper>
155
+ {isChatActive && <ChatButtonCTA />}
156
+ </StyledLeftWrapper>
159
157
  </StyledHeaderInner>
160
158
  </StyledHeader>
161
159
  );
@@ -1 +1 @@
1
- export declare const sharedStyledTemplate = "\"use client\";\nimport { mq, styledSmall, styledText, Theme } from \"cherry-styled-components\";\nimport { 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]) {\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 {\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 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";
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]) {\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 {\n margin: 0;\n padding: 0;\n border-collapse: collapse;\n width: 100%;\n text-align: left;\n display: block;\n overflow-x: auto;\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: transparent;\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n color: ${({ theme }) => theme.colors.primary};\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";
@@ -1,6 +1,6 @@
1
1
  export const sharedStyledTemplate = `"use client";
2
2
  import { mq, styledSmall, styledText, Theme } from "cherry-styled-components";
3
- import { css } from "styled-components";
3
+ import styled, { css } from "styled-components";
4
4
 
5
5
  export const interactiveStyles = css<{ theme: Theme }>\`
6
6
  transition: all 0.3s ease;
@@ -116,6 +116,8 @@ export const styledTable = css<{ theme: Theme }>\`
116
116
  border-collapse: collapse;
117
117
  width: 100%;
118
118
  text-align: left;
119
+ display: block;
120
+ overflow-x: auto;
119
121
 
120
122
  & tr {
121
123
  margin: 0;
@@ -124,7 +126,7 @@ export const styledTable = css<{ theme: Theme }>\`
124
126
 
125
127
  & th {
126
128
  border-bottom: solid 1px \${({ theme }) => theme.colors.grayLight};
127
- padding: 10px 0;
129
+ padding: 10px 10px 10px 0;
128
130
  \${({ theme }) => styledSmall(theme)};
129
131
  font-weight: 600;
130
132
  color: \${({ theme }) => theme.colors.dark};
@@ -138,4 +140,26 @@ export const styledTable = css<{ theme: Theme }>\`
138
140
  }
139
141
  }
140
142
  \`;
143
+
144
+ export const StyledSmallButton = styled.button<{ theme: Theme }>\`
145
+ \${interactiveStyles};
146
+ background: transparent;
147
+ border: solid 1px \${({ theme }) => theme.colors.grayLight};
148
+ color: \${({ theme }) => theme.colors.primary};
149
+ border-radius: \${({ theme }) => theme.spacing.radius.xs};
150
+ padding: 6px 8px;
151
+ font-size: 12px;
152
+ font-family: inherit;
153
+ font-weight: 600;
154
+ cursor: pointer;
155
+ transition: all 0.2s ease;
156
+ display: flex;
157
+ align-items: center;
158
+ gap: 6px;
159
+ margin-right: -6px;
160
+
161
+ & svg.lucide {
162
+ color: inherit;
163
+ }
164
+ \`;
141
165
  `;
@@ -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 20px 20px;\n\n ${mq(\"lg\")} {\n padding: 0 340px 20px 340px;\n ${({ $isChatOpen }) =>\n $isChatOpen &&\n css`\n padding: 0 440px 20px 340px;\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.primary : theme.colors.primary};\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 if (links.length === 0) {\n return null;\n }\n\n const { isOpen } = useContext(ChatContext);\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";
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.primary : theme.colors.primary};\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 if (links.length === 0) {\n return null;\n }\n\n const { isOpen } = useContext(ChatContext);\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";
@@ -1,3 +1,4 @@
1
+ import { SIDEBAR_WIDTH, CHAT_WIDTH } from "../../app/theme.js";
1
2
  export const staticLinksTemplate = `"use client";
2
3
  import styled, { css } from "styled-components";
3
4
  import { rgba } from "polished";
@@ -20,14 +21,17 @@ const StyledStaticLinks = styled.div<{ theme: Theme; $isChatOpen: boolean }>\`
20
21
  display: flex;
21
22
  margin: 0 auto;
22
23
  transition: all 0.3s ease;
23
- padding: 0 20px 20px 20px;
24
+ padding: 0 20px;
25
+ margin-bottom: 20px;
24
26
 
25
27
  \${mq("lg")} {
26
- padding: 0 340px 20px 340px;
28
+ margin: 0;
29
+ padding: 0 ${SIDEBAR_WIDTH + 20}px 20px ${SIDEBAR_WIDTH + 20}px;
30
+
27
31
  \${({ $isChatOpen }) =>
28
32
  $isChatOpen &&
29
33
  css\`
30
- padding: 0 440px 20px 340px;
34
+ padding: 0 ${CHAT_WIDTH + 20}px 20px ${SIDEBAR_WIDTH + 20}px;
31
35
  \`}
32
36
  }
33
37
  \`;
@@ -1 +1 @@
1
- export declare const stepsTemplate = "\"use client\";\nimport React from \"react\";\nimport styled, { useTheme } from \"styled-components\";\nimport { styledText, Theme } from \"cherry-styled-components\";\nimport { rgba } from \"polished\";\nimport { Icon, IconProps } from \"@/components/layout/Icon\";\n\nconst StyledStepsContainer = styled.div<{ theme: Theme }>`\n position: relative;\n width: 100%;\n`;\n\nconst StyledStep = styled.div<{ theme: Theme }>`\n background: ${({ theme }) => theme.colors.light};\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n padding: 0 0 20px 52px;\n margin: 0;\n position: relative;\n ${({ theme }) => styledText(theme)}\n color: ${({ theme }) => theme.colors.grayDark};\n\n &::after {\n content: \"\";\n position: absolute;\n left: 16px;\n top: 0;\n width: 1px;\n height: 100%;\n background: ${({ theme }) => theme.colors.primary};\n background: linear-gradient(\n 180deg,\n ${({ theme }) => theme.colors.primary},\n ${({ theme }) => rgba(theme.colors.primary, 0)}\n );\n border-radius: 4px;\n }\n`;\n\nconst StepNumber = styled.div<{ theme: Theme }>`\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: ${({ theme }) => theme.colors.primary};\n color: ${({ theme }) => theme.colors.light};\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n margin-bottom: 12px;\n ${({ theme }) => styledText(theme)};\n position: absolute;\n left: 0;\n top: 0;\n z-index: 1;\n`;\n\nconst StyledStepTitle = styled.h3<{ theme: Theme }>`\n margin: 0 0 10px 0;\n padding: 2px 0 0 0;\n color: ${({ theme }) => theme.colors.dark};\n ${({ theme }) => styledText(theme)};\n`;\n\nconst StepContent = styled.div<{ theme: Theme }>`\n color: ${({ theme }) => theme.colors.grayDark};\n ${({ theme }) => styledText(theme)};\n\n & > .code-wrapper {\n margin: 10px 0;\n }\n`;\n\ninterface StepProps extends React.HTMLAttributes<HTMLDivElement> {\n title: string;\n children: React.ReactNode;\n icon?: IconProps;\n}\n\nfunction Step(_props: StepProps) {\n return null;\n}\n\ninterface StepsProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nfunction Steps({ children }: StepsProps) {\n const theme = useTheme() as Theme;\n\n const steps = React.Children.toArray(children).filter(\n (child): child is React.ReactElement<StepProps> =>\n React.isValidElement(child),\n );\n\n return (\n <StyledStepsContainer theme={theme}>\n {steps.map((step, index) => {\n const { title, children: stepContent, icon } = step.props;\n\n return (\n <StyledStep key={index} theme={theme}>\n <StepNumber theme={theme}>{index + 1}</StepNumber>\n {icon && <Icon name={icon} color={theme.colors.primary} />}\n <StyledStepTitle theme={theme}>{title}</StyledStepTitle>\n <StepContent theme={theme}>{stepContent}</StepContent>\n </StyledStep>\n );\n })}\n </StyledStepsContainer>\n );\n}\n\nexport { Steps, Step };\n";
1
+ export declare const stepsTemplate = "\"use client\";\nimport React from \"react\";\nimport styled, { useTheme } from \"styled-components\";\nimport { styledText, Theme } from \"cherry-styled-components\";\nimport { rgba } from \"polished\";\nimport { Icon, IconProps } from \"@/components/layout/Icon\";\n\nconst StyledStepsContainer = styled.div<{ theme: Theme }>`\n position: relative;\n width: 100%;\n`;\n\nconst StyledStep = styled.div<{ theme: Theme }>`\n background: ${({ theme }) => theme.colors.light};\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n padding: 0 0 20px 52px;\n margin: 0;\n position: relative;\n ${({ theme }) => styledText(theme)}\n color: ${({ theme }) => theme.colors.grayDark};\n\n &::after {\n content: \"\";\n position: absolute;\n left: 16px;\n top: 0;\n width: 1px;\n height: 100%;\n background: ${({ theme }) => theme.colors.primary};\n background: linear-gradient(\n 180deg,\n ${({ theme }) => theme.colors.primary},\n ${({ theme }) => rgba(theme.colors.primary, 0)}\n );\n border-radius: 4px;\n }\n`;\n\nconst StepNumber = styled.div<{ theme: Theme }>`\n width: 32px;\n height: 32px;\n border-radius: 50%;\n background: ${({ theme }) => theme.colors.primary};\n color: ${({ theme }) => theme.colors.light};\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n margin-bottom: 12px;\n ${({ theme }) => styledText(theme)};\n position: absolute;\n left: 0;\n top: 0;\n z-index: 1;\n`;\n\nconst StyledStepTitle = styled.h3<{ theme: Theme }>`\n margin: 0 0 10px 0;\n padding: 2px 0 0 0;\n color: ${({ theme }) => theme.colors.dark};\n ${({ theme }) => styledText(theme)};\n display: flex;\n align-items: center;\n gap: 10px;\n`;\n\nconst StepContent = styled.div<{ theme: Theme }>`\n color: ${({ theme }) => theme.colors.grayDark};\n ${({ theme }) => styledText(theme)};\n\n & > .code-wrapper {\n margin: 10px 0;\n }\n`;\n\ninterface StepProps extends React.HTMLAttributes<HTMLDivElement> {\n title: string;\n children: React.ReactNode;\n icon?: IconProps;\n}\n\nfunction Step(_props: StepProps) {\n return null;\n}\n\ninterface StepsProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nfunction Steps({ children }: StepsProps) {\n const theme = useTheme() as Theme;\n\n const steps = React.Children.toArray(children).filter(\n (child): child is React.ReactElement<StepProps> =>\n React.isValidElement(child),\n );\n\n return (\n <StyledStepsContainer theme={theme}>\n {steps.map((step, index) => {\n const { title, children: stepContent, icon } = step.props;\n\n return (\n <StyledStep key={index} theme={theme}>\n <StepNumber theme={theme}>{index + 1}</StepNumber>\n <StyledStepTitle theme={theme}>\n {icon && <Icon name={icon} color={theme.colors.primary} />}\n {title}\n </StyledStepTitle>\n <StepContent theme={theme}>{stepContent}</StepContent>\n </StyledStep>\n );\n })}\n </StyledStepsContainer>\n );\n}\n\nexport { Steps, Step };\n";
@@ -59,6 +59,9 @@ const StyledStepTitle = styled.h3<{ theme: Theme }>\`
59
59
  padding: 2px 0 0 0;
60
60
  color: \${({ theme }) => theme.colors.dark};
61
61
  \${({ theme }) => styledText(theme)};
62
+ display: flex;
63
+ align-items: center;
64
+ gap: 10px;
62
65
  \`;
63
66
 
64
67
  const StepContent = styled.div<{ theme: Theme }>\`
@@ -100,8 +103,10 @@ function Steps({ children }: StepsProps) {
100
103
  return (
101
104
  <StyledStep key={index} theme={theme}>
102
105
  <StepNumber theme={theme}>{index + 1}</StepNumber>
103
- {icon && <Icon name={icon} color={theme.colors.primary} />}
104
- <StyledStepTitle theme={theme}>{title}</StyledStepTitle>
106
+ <StyledStepTitle theme={theme}>
107
+ {icon && <Icon name={icon} color={theme.colors.primary} />}
108
+ {title}
109
+ </StyledStepTitle>
105
110
  <StepContent theme={theme}>{stepContent}</StepContent>
106
111
  </StyledStep>
107
112
  );
@@ -1 +1 @@
1
- export declare const tabsTemplate = "\"use client\";\nimport { Theme } from \"@/app/theme\";\nimport { styledText } from \"cherry-styled-components\";\nimport { rgba } from \"polished\";\nimport React, { useState, ReactNode } from \"react\";\nimport styled, { css } from \"styled-components\";\nexport interface TabContentProps {\n title: string;\n children: ReactNode;\n}\nexport interface TabsProps {\n children: React.ReactElement<TabContentProps>[];\n}\nconst TabsContainer = styled.div`\n width: 100%;\n margin: 0 auto;\n`;\nconst TabsList = styled.div<{ theme: Theme }>`\n display: flex;\n overflow: hidden;\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n background-color: ${({ theme }) => theme.colors.light};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n overflow-x: auto;\n`;\nconst TabButton = styled.button<{ theme: Theme; $isActive?: boolean }>`\n flex: 1;\n padding: 12px 20px;\n border: none;\n background: ${({ theme }) => theme.colors.light};\n cursor: pointer;\n transition: all 0.2s ease;\n border-bottom: 3px solid transparent;\n min-width: fit-content;\n ${({ theme }) => styledText(theme)};\n color: ${({ theme }) => theme.colors.dark};\n font-weight: 600;\n ${({ theme, $isActive }) =>\n $isActive &&\n css`\n color: ${theme.colors.primary};\n border-bottom: 3px solid ${theme.colors.primary};\n `}\n position: relative;\n &:hover {\n ${({ theme, $isActive }) =>\n !$isActive &&\n css`\n color: ${theme.colors.primary};\n background-color: ${rgba(theme.colors.primaryLight, 0.1)};\n `}\n }\n &:focus {\n outline: none;\n }\n &:not(:last-child) {\n border-right: 1px solid ${({ theme }) => theme.colors.grayLight};\n }\n`;\nconst TabPanel = styled.div<{ theme: Theme }>`\n background-color: ${({ theme }) => theme.colors.light};\n padding: 20px;\n border-radius: 0 0 ${({ theme }) => theme.spacing.radius.lg}\n ${({ theme }) => theme.spacing.radius.lg};\n color: ${({ theme }) => theme.colors.grayDark};\n ${({ theme }) => styledText(theme)}\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n border-top: none;\n display: flex;\n flex-direction: column;\n gap: 20px;\n flex-wrap: wrap;\n flex: 1;\n`;\nconst TabContent: React.FC<TabContentProps> = ({ children }) => {\n return <>{children}</>;\n};\nconst Tabs: React.FC<TabsProps> = ({ children }) => {\n const [activeTab, setActiveTab] = useState(0);\n const tabs = React.Children.toArray(children).filter(\n (child): child is React.ReactElement<TabContentProps> =>\n Boolean(\n React.isValidElement(child) &&\n child.props &&\n typeof child.props === \"object\" &&\n \"title\" in child.props &&\n typeof child.props.title === \"string\" &&\n child.props.title.trim() !== \"\",\n ),\n );\n return (\n <TabsContainer>\n <TabsList>\n {tabs.map((tab, index) => (\n <TabButton\n key={index}\n $isActive={activeTab === index}\n onClick={() => setActiveTab(index)}\n type=\"button\"\n >\n {tab.props.title}\n </TabButton>\n ))}\n </TabsList>\n <TabPanel>{tabs[activeTab]?.props.children}</TabPanel>\n </TabsContainer>\n );\n};\nexport { Tabs, TabContent };\n";
1
+ export declare const tabsTemplate = "\"use client\";\nimport { Theme } from \"@/app/theme\";\nimport { styledText } from \"cherry-styled-components\";\nimport { rgba } from \"polished\";\nimport React, { useState, ReactNode } from \"react\";\nimport styled, { css } from \"styled-components\";\ninterface TabContentProps {\n title: string;\n children: ReactNode;\n}\ninterface TabsProps {\n children: React.ReactElement<TabContentProps>[];\n}\nconst TabsContainer = styled.div`\n width: 100%;\n margin: 0 auto;\n`;\nconst TabsList = styled.div<{ theme: Theme }>`\n display: flex;\n overflow: hidden;\n border-radius: ${({ theme }) => theme.spacing.radius.lg};\n border-bottom-left-radius: 0;\n border-bottom-right-radius: 0;\n background-color: ${({ theme }) => theme.colors.light};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n overflow-x: auto;\n`;\nconst TabButton = styled.button<{ theme: Theme; $isActive?: boolean }>`\n flex: 1;\n padding: 12px 20px;\n border: none;\n background: ${({ theme }) => theme.colors.light};\n cursor: pointer;\n transition: all 0.2s ease;\n border-bottom: 3px solid transparent;\n min-width: fit-content;\n ${({ theme }) => styledText(theme)};\n color: ${({ theme }) => theme.colors.dark};\n font-weight: 600;\n ${({ theme, $isActive }) =>\n $isActive &&\n css`\n color: ${theme.colors.primary};\n border-bottom: 3px solid ${theme.colors.primary};\n `}\n position: relative;\n &:hover {\n ${({ theme, $isActive }) =>\n !$isActive &&\n css`\n color: ${theme.colors.primary};\n background-color: ${rgba(theme.colors.primaryLight, 0.1)};\n `}\n }\n &:focus {\n outline: none;\n }\n &:not(:last-child) {\n border-right: 1px solid ${({ theme }) => theme.colors.grayLight};\n }\n`;\nconst TabPanel = styled.div<{ theme: Theme }>`\n background-color: ${({ theme }) => theme.colors.light};\n padding: 20px;\n border-radius: 0 0 ${({ theme }) => theme.spacing.radius.lg}\n ${({ theme }) => theme.spacing.radius.lg};\n color: ${({ theme }) => theme.colors.grayDark};\n ${({ theme }) => styledText(theme)}\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n border-top: none;\n display: flex;\n flex-direction: column;\n gap: 20px;\n flex-wrap: wrap;\n flex: 1;\n`;\nconst TabContent: React.FC<TabContentProps> = ({ children }) => {\n return <>{children}</>;\n};\nconst Tabs: React.FC<TabsProps> = ({ children }) => {\n const [activeTab, setActiveTab] = useState(0);\n const tabs = React.Children.toArray(children).filter(\n (child): child is React.ReactElement<TabContentProps> =>\n Boolean(\n React.isValidElement(child) &&\n child.props &&\n typeof child.props === \"object\" &&\n \"title\" in child.props &&\n typeof child.props.title === \"string\" &&\n child.props.title.trim() !== \"\",\n ),\n );\n return (\n <TabsContainer>\n <TabsList>\n {tabs.map((tab, index) => (\n <TabButton\n key={index}\n $isActive={activeTab === index}\n onClick={() => setActiveTab(index)}\n type=\"button\"\n >\n {tab.props.title}\n </TabButton>\n ))}\n </TabsList>\n <TabPanel>{tabs[activeTab]?.props.children}</TabPanel>\n </TabsContainer>\n );\n};\nexport { Tabs, TabContent };\n";
@@ -4,11 +4,11 @@ import { styledText } from "cherry-styled-components";
4
4
  import { rgba } from "polished";
5
5
  import React, { useState, ReactNode } from "react";
6
6
  import styled, { css } from "styled-components";
7
- export interface TabContentProps {
7
+ interface TabContentProps {
8
8
  title: string;
9
9
  children: ReactNode;
10
10
  }
11
- export interface TabsProps {
11
+ interface TabsProps {
12
12
  children: React.ReactElement<TabContentProps>[];
13
13
  }
14
14
  const TabsContainer = styled.div\`
@@ -1 +1 @@
1
- export declare const updateTemplate = "\"use client\";\nimport styled from \"styled-components\";\nimport { mq, styledSmall, Theme } from \"cherry-styled-components\";\nimport { rgba } from \"polished\";\n\nconst StyledUpdate = styled.div<{ theme: Theme; $columns?: number }>`\n position: relative;\n display: flex;\n gap: 20px;\n flex-direction: column;\n\n ${mq(\"lg\")} {\n margin: 20px 0;\n flex-direction: row;\n }\n`;\n\nconst StyledUpdateLabel = styled.span<{ theme: Theme }>`\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.2)};\n color: ${({ theme }) => theme.colors.primary};\n padding: 2px 4px;\n border-radius: ${({ theme }) => theme.spacing.radius.xs};\n font-weight: 600;\n ${({ theme }) => styledSmall(theme)};\n`;\n\nconst StyledUpdateDescription = styled.div<{ theme: Theme }>`\n ${({ theme }) => styledSmall(theme)};\n color: ${({ theme }) => theme.colors.gray};\n`;\n\nconst StyledUpdateSidebar = styled.div`\n display: flex;\n flex-direction: column;\n gap: 10px;\n\n ${mq(\"lg\")} {\n min-width: 160px;\n }\n`;\n\nconst StyledUpdateChildren = styled.div`\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 20px;\n`;\n\nexport interface UpdateProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n label: string;\n description: string;\n}\n\nfunction Update({ children, label, description }: UpdateProps) {\n return (\n <StyledUpdate>\n <StyledUpdateSidebar>\n <div>\n <StyledUpdateLabel>{label}</StyledUpdateLabel>\n </div>\n <StyledUpdateDescription>{description}</StyledUpdateDescription>\n </StyledUpdateSidebar>\n <StyledUpdateChildren>{children}</StyledUpdateChildren>\n </StyledUpdate>\n );\n}\n\nexport { Update };\n";
1
+ export declare const updateTemplate = "\"use client\";\nimport styled from \"styled-components\";\nimport { mq, styledSmall, Theme } from \"cherry-styled-components\";\nimport { rgba } from \"polished\";\n\nconst StyledUpdate = styled.div<{ theme: Theme; $columns?: number }>`\n position: relative;\n display: flex;\n gap: 20px;\n flex-direction: column;\n\n ${mq(\"lg\")} {\n margin: 20px 0;\n flex-direction: row;\n }\n`;\n\nconst StyledUpdateLabel = styled.span<{ theme: Theme }>`\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.2)};\n color: ${({ theme }) => theme.colors.primary};\n padding: 2px 4px;\n border-radius: ${({ theme }) => theme.spacing.radius.xs};\n font-weight: 600;\n ${({ theme }) => styledSmall(theme)};\n`;\n\nconst StyledUpdateDescription = styled.div<{ theme: Theme }>`\n ${({ theme }) => styledSmall(theme)};\n color: ${({ theme }) => theme.colors.gray};\n`;\n\nconst StyledUpdateSidebar = styled.div`\n display: flex;\n flex-direction: column;\n gap: 10px;\n\n ${mq(\"lg\")} {\n min-width: 160px;\n }\n`;\n\nconst StyledUpdateChildren = styled.div`\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: 20px;\n`;\n\ninterface UpdateProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n label: string;\n description: string;\n}\n\nfunction Update({ children, label, description }: UpdateProps) {\n return (\n <StyledUpdate>\n <StyledUpdateSidebar>\n <div>\n <StyledUpdateLabel>{label}</StyledUpdateLabel>\n </div>\n <StyledUpdateDescription>{description}</StyledUpdateDescription>\n </StyledUpdateSidebar>\n <StyledUpdateChildren>{children}</StyledUpdateChildren>\n </StyledUpdate>\n );\n}\n\nexport { Update };\n";
@@ -46,7 +46,7 @@ const StyledUpdateChildren = styled.div\`
46
46
  gap: 20px;
47
47
  \`;
48
48
 
49
- export interface UpdateProps extends React.HTMLAttributes<HTMLDivElement> {
49
+ interface UpdateProps extends React.HTMLAttributes<HTMLDivElement> {
50
50
  children: React.ReactNode;
51
51
  label: string;
52
52
  description: string;
@@ -1 +1 @@
1
- export declare const aiAssistantMdxTemplate = "---\ntitle: \"AI Assistant\"\ndescription: \"Integrate AI capabilities into your Doccupine documentation using OpenAI, Anthropic, or Google Gemini.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 8\n---\n# AI Assistant\nDoccupine supports AI integration to enhance your documentation experience. You can use OpenAI, Anthropic, or Google Gemini to power AI features in your documentation site. The AI assistant uses your documentation content as context, allowing users to ask questions about your docs and receive accurate answers based on the documentation.\n\n## Setup\nTo enable AI features, create an `.env` file in the directory where your website is generated. By default, this is the `nextjs-app/` directory.\n\n## Configuration\nCreate an `.env` file with the following configuration options:\n\n```env\n# LLM Provider Configuration\n# Choose your preferred LLM provider: openai, anthropic, or google\nLLM_PROVIDER=openai\n\n# API Keys (set the one matching your provider)\nOPENAI_API_KEY=your_openai_api_key_here\nANTHROPIC_API_KEY=your_anthropic_api_key_here\nGOOGLE_API_KEY=your_google_api_key_here\n\n# Optional: Override default chat model (see your provider's docs for available models)\n# LLM_CHAT_MODEL=your-model-id\n\n# Optional: Override default embedding model (see your provider's docs for available models)\n# Note: Anthropic doesn't provide embeddings, will fallback to OpenAI\n# LLM_EMBEDDING_MODEL=your-embedding-model-id\n\n# Optional: Set temperature (0-1, default: 0)\n# LLM_TEMPERATURE=0\n```\n\n## Provider Selection\nSet `LLM_PROVIDER` to one of the following values:\n- `openai` - Use OpenAI's models\n- `anthropic` - Use Anthropic's models\n- `google` - Use Google's models\n\n## API Keys\nYou need to set the API key that matches your chosen provider:\n- For OpenAI: Set `OPENAI_API_KEY`\n- For Anthropic: Set `ANTHROPIC_API_KEY`\n- For Google: Set `GOOGLE_API_KEY`\n\n<Callout type=\"warning\">\n Keep your API keys secure. Never commit your `.env` file to version control.\n</Callout>\n\n<Callout type=\"note\">\n Doccupine automatically adds `.env` to your `.gitignore` file.\n</Callout>\n\n## Using Anthropic with OpenAI\nIf you want to use Anthropic as your LLM provider, you must also have an OpenAI API key set. Here's why:\n\n### The Situation\nAnthropic (Claude) does not provide an embeddings API. They only offer chat/completion models, not text embeddings.\n\nYour RAG (Retrieval-Augmented Generation) system has two components:\n- **Chat/Completion** - Generates answers, works with Anthropic.\n- **Embeddings** - Creates vector representations of text for search, Anthropic doesn't provide this.\n\nWhen using Anthropic as your `LLM_PROVIDER`, Doccupine will use Anthropic for chat/completion tasks, but will automatically fallback to OpenAI for embeddings. This means you need both API keys configured:\n\n```env\nLLM_PROVIDER=anthropic\nANTHROPIC_API_KEY=your_anthropic_api_key_here\nOPENAI_API_KEY=your_openai_api_key_here\n```\n\nThis hybrid approach allows you to leverage Anthropic's powerful chat models while still having access to embeddings functionality through OpenAI.\n\n## Optional Settings\n\n### Chat Model\nOverride the default chat model by uncommenting and setting `LLM_CHAT_MODEL`. You can use any available model from your chosen provider. For a complete list of available models, refer to the official documentation:\n- [OpenAI Models](https://platform.openai.com/docs/models)\n- [Anthropic Models](https://docs.anthropic.com/claude/docs/models-overview)\n- [Google Gemini Models](https://ai.google.dev/models/gemini)\n\n### Embedding Model\nOverride the default embedding model by uncommenting and setting `LLM_EMBEDDING_MODEL`. For a complete list of available embedding models, refer to the official documentation:\n- [OpenAI Embeddings](https://platform.openai.com/docs/guides/embeddings)\n- [Google Gemini Embeddings](https://ai.google.dev/gemini-api/docs/embeddings)\n- **Anthropic**: Anthropic doesn't provide embeddings. If you use Anthropic as your provider, Doccupine will fallback to OpenAI for embeddings.\n\n### Temperature\nControl the randomness of AI responses by setting `LLM_TEMPERATURE` to a value between 0 and 1:\n- `0` - More deterministic and focused responses (default)\n- `1` - More creative and varied responses";
1
+ export declare const aiAssistantMdxTemplate = "---\ntitle: \"AI Assistant\"\ndescription: \"Integrate AI capabilities into your Doccupine documentation using OpenAI, Anthropic, or Google Gemini.\"\ndate: \"2026-02-19\"\ncategory: \"Configuration\"\ncategoryOrder: 3\norder: 8\n---\n# AI Assistant\nDoccupine supports AI integration to enhance your documentation experience. You can use OpenAI, Anthropic, or Google Gemini to power AI features in your documentation site. The AI assistant uses your documentation content as context, allowing users to ask questions about your docs and receive accurate answers based on the documentation.\n\n## Setup\nTo enable AI features, create an `.env` file in the directory where your website is generated. By default, this is the `nextjs-app/` directory.\n\n## Configuration\nCreate an `.env` file with the following configuration options:\n\n```env\n# LLM Provider Configuration\n# Choose your preferred LLM provider: openai, anthropic, or google\nLLM_PROVIDER=openai\n\n# API Keys (set the one matching your provider)\nOPENAI_API_KEY=your_openai_api_key_here\nANTHROPIC_API_KEY=your_anthropic_api_key_here\nGOOGLE_API_KEY=your_google_api_key_here\n\n# Optional: Override default chat model (see your provider's docs for available models)\n# LLM_CHAT_MODEL=your-model-id\n\n# Optional: Override default embedding model (see your provider's docs for available models)\n# Note: Anthropic doesn't provide embeddings, will fallback to OpenAI\n# LLM_EMBEDDING_MODEL=your-embedding-model-id\n\n# Optional: Set temperature (0-1, default: 0)\n# LLM_TEMPERATURE=0\n```\n\n## Provider Selection\nSet `LLM_PROVIDER` to one of the following values:\n- `openai` - Use OpenAI's models\n- `anthropic` - Use Anthropic's models\n- `google` - Use Google's models\n\n## API Keys\nYou need to set the API key that matches your chosen provider:\n- For OpenAI: Set `OPENAI_API_KEY`\n- For Anthropic: Set `ANTHROPIC_API_KEY`\n- For Google: Set `GOOGLE_API_KEY`\n\n<Callout type=\"warning\">\n Keep your API keys secure. Never commit your `.env` file to version control.\n</Callout>\n\n<Callout type=\"note\">\n Doccupine automatically adds `.env` to your `.gitignore` file.\n</Callout>\n\n## Using Anthropic with OpenAI\nIf you want to use Anthropic as your LLM provider, you must also have an OpenAI API key set. Here's why:\n\n### The Situation\nAnthropic (Claude) does not provide an embeddings API. They only offer chat/completion models, not text embeddings.\n\nYour RAG (Retrieval-Augmented Generation) system has two components:\n- **Chat/Completion** - Generates answers, works with Anthropic.\n- **Embeddings** - Creates vector representations of text for search, Anthropic doesn't provide this.\n\nWhen using Anthropic as your `LLM_PROVIDER`, Doccupine will use Anthropic for chat/completion tasks, but will automatically fallback to OpenAI for embeddings. This means you need both API keys configured:\n\n```env\nLLM_PROVIDER=anthropic\nANTHROPIC_API_KEY=your_anthropic_api_key_here\nOPENAI_API_KEY=your_openai_api_key_here\n```\n\nThis hybrid approach allows you to leverage Anthropic's powerful chat models while still having access to embeddings functionality through OpenAI.\n\n## Default models\n\n| Provider | Chat model | Embedding model |\n|---|---|---|\n| OpenAI | `gpt-4.1-nano` | `text-embedding-3-small` |\n| Anthropic | `claude-sonnet-4-5-20250929` | OpenAI fallback |\n| Google | `gemini-2.5-flash-lite` | `gemini-embedding-001` |\n\n## Optional Settings\n\n### Chat Model\nOverride the default chat model by uncommenting and setting `LLM_CHAT_MODEL`. You can use any available model from your chosen provider. For a complete list of available models, refer to the official documentation:\n- [OpenAI Models](https://platform.openai.com/docs/models)\n- [Anthropic Models](https://docs.anthropic.com/claude/docs/models-overview)\n- [Google Gemini Models](https://ai.google.dev/models/gemini)\n\n### Embedding Model\nOverride the default embedding model by uncommenting and setting `LLM_EMBEDDING_MODEL`. For a complete list of available embedding models, refer to the official documentation:\n- [OpenAI Embeddings](https://platform.openai.com/docs/guides/embeddings)\n- [Google Gemini Embeddings](https://ai.google.dev/gemini-api/docs/embeddings)\n- **Anthropic**: Anthropic doesn't provide embeddings. If you use Anthropic as your provider, Doccupine will fallback to OpenAI for embeddings.\n\n### Temperature\nControl the randomness of AI responses by setting `LLM_TEMPERATURE` to a value between 0 and 1:\n- `0` - More deterministic and focused responses (default)\n- `1` - More creative and varied responses";
@@ -76,6 +76,14 @@ OPENAI_API_KEY=your_openai_api_key_here
76
76
 
77
77
  This hybrid approach allows you to leverage Anthropic's powerful chat models while still having access to embeddings functionality through OpenAI.
78
78
 
79
+ ## Default models
80
+
81
+ | Provider | Chat model | Embedding model |
82
+ |---|---|---|
83
+ | OpenAI | \`gpt-4.1-nano\` | \`text-embedding-3-small\` |
84
+ | Anthropic | \`claude-sonnet-4-5-20250929\` | OpenAI fallback |
85
+ | Google | \`gemini-2.5-flash-lite\` | \`gemini-embedding-001\` |
86
+
79
87
  ## Optional Settings
80
88
 
81
89
  ### Chat Model
@@ -1 +1 @@
1
- export declare const calloutsMdxTemplate = "---\ntitle: \"Callouts\"\ndescription: \"Make your content stand out by using callouts for extra emphasis.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 7\n---\n# Callouts\nMake your content stand out by using callouts for extra emphasis.\n\nYou can format them as Note, Warning, Info, Danger and Success.\n\n## Callouts Usage\nYou can use the Callouts component directly within your MDX files without any import. The following example shows a basic usage:\n\n~~~mdx\n<Callout type=\"note\">\n This is a note callout\n</Callout>\n\n<Callout type=\"warning\">\n This is a warning callout\n</Callout>\n\n<Callout type=\"info\">\n This is an info callout\n</Callout>\n\n<Callout type=\"danger\">\n This is a danger callout\n</Callout>\n\n<Callout type=\"success\">\n This is a success callout\n</Callout>\n~~~\n\n<Callout type=\"note\">\n This is a note callout\n</Callout>\n\n<Callout type=\"warning\">\n This is a warning callout\n</Callout>\n\n<Callout type=\"info\">\n This is an info callout\n</Callout>\n\n<Callout type=\"danger\">\n This is a danger callout\n</Callout>\n\n<Callout type=\"success\">\n This is a success callout\n</Callout>\n\n## Properties\n\n<Field value=\"type\" type=\"string\" required>\n The type of the callout.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the callout.\n</Field>";
1
+ export declare const calloutsMdxTemplate = "---\ntitle: \"Callouts\"\ndescription: \"Make your content stand out by using callouts for extra emphasis.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 7\n---\n# Callouts\nMake your content stand out by using callouts for extra emphasis.\n\nYou can format them as Note, Warning, Info, Danger and Success.\n\n## Callouts Usage\nYou can use the Callouts component directly within your MDX files without any import. The following example shows a basic usage:\n\n~~~mdx\n<Callout type=\"note\">\n This is a note callout\n</Callout>\n\n<Callout type=\"warning\">\n This is a warning callout\n</Callout>\n\n<Callout type=\"info\">\n This is an info callout\n</Callout>\n\n<Callout type=\"danger\">\n This is a danger callout\n</Callout>\n\n<Callout type=\"success\">\n This is a success callout\n</Callout>\n~~~\n\n<Callout type=\"note\">\n This is a note callout\n</Callout>\n\n<Callout type=\"warning\">\n This is a warning callout\n</Callout>\n\n<Callout type=\"info\">\n This is an info callout\n</Callout>\n\n<Callout type=\"danger\">\n This is a danger callout\n</Callout>\n\n<Callout type=\"success\">\n This is a success callout\n</Callout>\n\n## Properties\n\n<Field value=\"type\" type=\"string\">\n The type of the callout: `note`, `info`, `warning`, `danger`, or `success`.\n</Field>\n\n<Field value=\"icon\" type=\"string\">\n A custom [Lucide](https://lucide.dev/icons) icon name. Overrides the default icon for the callout type.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the callout.\n</Field>";
@@ -58,8 +58,12 @@ You can use the Callouts component directly within your MDX files without any im
58
58
 
59
59
  ## Properties
60
60
 
61
- <Field value="type" type="string" required>
62
- The type of the callout.
61
+ <Field value="type" type="string">
62
+ The type of the callout: \`note\`, \`info\`, \`warning\`, \`danger\`, or \`success\`.
63
+ </Field>
64
+
65
+ <Field value="icon" type="string">
66
+ A custom [Lucide](https://lucide.dev/icons) icon name. Overrides the default icon for the callout type.
63
67
  </Field>
64
68
 
65
69
  <Field value="children" type="node" required>
@@ -1 +1 @@
1
- export declare const cardsMdxTemplate = "---\ntitle: \"Cards\"\ndescription: \"Cards act as visual containers for your content, giving you flexibility to combine text, icons, images, and links in a clean and organized way.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 6\n---\n# Cards\nDuplicate a page or section with ease, then emphasize important information or links using customizable layouts and icons.\n\nCards act as visual containers for your content, giving you flexibility to combine text, icons, images, and links in a clean and organized way.\n\n## Cards Usage\nYou can use the Cards component directly within your MDX files without any import. The following example shows a basic usage:\n\n~~~mdx\n<Card title=\"Note\" icon=\"badge-info\">\n Doccupine CLI is a command-line tool that helps you create and manage your Doccupine project. It provides a simple and intuitive interface for creating and configuring your project.\n</Card>\n~~~\n\n<Card title=\"Note\" icon=\"badge-info\">\n Doccupine CLI is a command-line tool that helps you create and manage your Doccupine project. It provides a simple and intuitive interface for creating and configuring your project.\n</Card>\n\n## Properties\n\n<Field value=\"title\" type=\"string\" required>\n The title of the card.\n</Field>\n\n<Field value=\"icon\" type=\"string\" required>\n The icon to display in the card.\n</Field>\n\n- [**Lucide icon**](https://lucide.dev/icons) name\n\n<Field value=\"children\" type=\"node\" required>\n The content of the card.\n</Field>";
1
+ export declare const cardsMdxTemplate = "---\ntitle: \"Cards\"\ndescription: \"Cards act as visual containers for your content, giving you flexibility to combine text, icons, images, and links in a clean and organized way.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 6\n---\n# Cards\nDuplicate a page or section with ease, then emphasize important information or links using customizable layouts and icons.\n\nCards act as visual containers for your content, giving you flexibility to combine text, icons, images, and links in a clean and organized way.\n\n## Cards Usage\nYou can use the Cards component directly within your MDX files without any import. The following example shows a basic usage:\n\n~~~mdx\n<Card title=\"Note\" icon=\"badge-info\">\n Doccupine CLI is a command-line tool that helps you create and manage your Doccupine project. It provides a simple and intuitive interface for creating and configuring your project.\n</Card>\n~~~\n\n<Card title=\"Note\" icon=\"badge-info\">\n Doccupine CLI is a command-line tool that helps you create and manage your Doccupine project. It provides a simple and intuitive interface for creating and configuring your project.\n</Card>\n\n## Link Card\n\nPass a `href` prop to turn the card into a clickable link. The card will display interactive hover and focus styles automatically.\n\n~~~mdx\n<Card title=\"Getting Started\" icon=\"rocket\" href=\"/cards\">\n Learn how to set up Doccupine and create your first documentation site.\n</Card>\n~~~\n\n<Card title=\"Getting Started\" icon=\"rocket\" href=\"/cards\">\n Learn how to set up Doccupine and create your first documentation site.\n</Card>\n\n## Properties\n\n<Field value=\"title\" type=\"string\" required>\n The title of the card.\n</Field>\n\n<Field value=\"icon\" type=\"string\">\n The [Lucide](https://lucide.dev/icons) icon name to display in the card.\n</Field>\n\n<Field value=\"href\" type=\"string\">\n A URL or path to link to. When provided, the card becomes a clickable link with interactive styles.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the card.\n</Field>";
@@ -24,17 +24,33 @@ You can use the Cards component directly within your MDX files without any impor
24
24
  Doccupine CLI is a command-line tool that helps you create and manage your Doccupine project. It provides a simple and intuitive interface for creating and configuring your project.
25
25
  </Card>
26
26
 
27
+ ## Link Card
28
+
29
+ Pass a \`href\` prop to turn the card into a clickable link. The card will display interactive hover and focus styles automatically.
30
+
31
+ ~~~mdx
32
+ <Card title="Getting Started" icon="rocket" href="/cards">
33
+ Learn how to set up Doccupine and create your first documentation site.
34
+ </Card>
35
+ ~~~
36
+
37
+ <Card title="Getting Started" icon="rocket" href="/cards">
38
+ Learn how to set up Doccupine and create your first documentation site.
39
+ </Card>
40
+
27
41
  ## Properties
28
42
 
29
43
  <Field value="title" type="string" required>
30
44
  The title of the card.
31
45
  </Field>
32
46
 
33
- <Field value="icon" type="string" required>
34
- The icon to display in the card.
47
+ <Field value="icon" type="string">
48
+ The [Lucide](https://lucide.dev/icons) icon name to display in the card.
35
49
  </Field>
36
50
 
37
- - [**Lucide icon**](https://lucide.dev/icons) name
51
+ <Field value="href" type="string">
52
+ A URL or path to link to. When provided, the card becomes a clickable link with interactive styles.
53
+ </Field>
38
54
 
39
55
  <Field value="children" type="node" required>
40
56
  The content of the card.
@@ -1 +1 @@
1
- export declare const columnsMdxTemplate = "---\ntitle: \"Columns\"\ndescription: \"Columns are used to organize content in a grid-like structure.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 12\n---\n# Columns\nArrange multiple cards neatly in a side-by-side grid layout.\n\nThe `Columns` component helps you organize several `Card` elements into a visually balanced grid. By choosing how many columns you want, you can control the layout and spacing of your cards.\n\n## Columns Usage\nYou can use the `Columns` component to create a grid of cards with a specified number of columns.\n\n```mdx\n<Columns cols={2}>\n <Card title=\"Getting Started\" icon=\"rocket\">\n Kick off your project using our easy quickstart guide.\n </Card>\n\n <Card title=\"API Reference\" icon=\"code\">\n Browse all endpoints, parameters, and code examples for your API integration.\n </Card>\n</Columns>\n```\n\n<Columns cols={2}>\n <Card title=\"Getting Started\" icon=\"rocket\">\n Kick off your project using our easy quickstart guide.\n </Card>\n\n <Card title=\"API Reference\" icon=\"code\">\n Browse all endpoints, parameters, and code examples for your API integration.\n </Card>\n</Columns>\n\n## Properties\n\n<Field value=\"cols\" type=\"number\" required>\n The number of columns in the grid.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the columns.\n</Field>";
1
+ export declare const columnsMdxTemplate = "---\ntitle: \"Columns\"\ndescription: \"Columns are used to organize content in a grid-like structure.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 12\n---\n# Columns\nArrange multiple cards neatly in a side-by-side grid layout.\n\nThe `Columns` component helps you organize several `Card` elements into a visually balanced grid. By choosing how many columns you want, you can control the layout and spacing of your cards.\n\n## Columns Usage\nYou can use the `Columns` component to create a grid of cards with a specified number of columns.\n\n```mdx\n<Columns cols={2}>\n <Card title=\"Getting Started\" icon=\"rocket\">\n Kick off your project using our easy quickstart guide.\n </Card>\n\n <Card title=\"API Reference\" icon=\"code\">\n Browse all endpoints, parameters, and code examples for your API integration.\n </Card>\n</Columns>\n```\n\n<Columns cols={2}>\n <Card title=\"Getting Started\" icon=\"rocket\">\n Kick off your project using our easy quickstart guide.\n </Card>\n\n <Card title=\"API Reference\" icon=\"code\">\n Browse all endpoints, parameters, and code examples for your API integration.\n </Card>\n</Columns>\n\n## Properties\n\n<Field value=\"cols\" type=\"number\">\n The number of columns in the grid. Defaults to 1.\n</Field>\n\n<Field value=\"children\" type=\"node\" required>\n The content of the columns.\n</Field>";
@@ -38,8 +38,8 @@ You can use the \`Columns\` component to create a grid of cards with a specified
38
38
 
39
39
  ## Properties
40
40
 
41
- <Field value="cols" type="number" required>
42
- The number of columns in the grid.
41
+ <Field value="cols" type="number">
42
+ The number of columns in the grid. Defaults to 1.
43
43
  </Field>
44
44
 
45
45
  <Field value="children" type="node" required>
@@ -1 +1 @@
1
- export declare const commandsMdxTemplate = "---\ntitle: \"Commands\"\ndescription: \"In this page, you can find all the commands available in Doccupine CLI.\"\ndate: \"2026-02-19\"\ncategory: \"Getting Started\"\ncategoryOrder: 0\norder: 1\n---\n# Commands\nIn this page, you can find all the commands available in Doccupine CLI.\n\n## Run Doccupine CLI\nCreate a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:\n\n```bash\nnpx doccupine\n```\n\nOnce you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.\nAfter selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.\n\nThis will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.\n\n## Verbose mode\n\n```bash\nnpx doccupine --verbose\n```\n\n<Callout type=\"note\">\n This will show Next.js errors in the terminal console logs, providing more detailed output useful for debugging during development.\n</Callout>\n\n## Generate the website\n\n```bash\nnpx doccupine build\n```\n\nThis will generate the build files for your documentation website without starting the development server. You can then deploy the generated files to a hosting service of your choice.\n\n## Show current configuration\n\n```bash\nnpx doccupine config --show\n```\n\nThis will show the current configuration for Doccupine.\n\n## Reset configuration\n\n```bash\nnpx doccupine config --reset\n```\n\nThis will reset the current configuration for Doccupine.";
1
+ export declare const commandsMdxTemplate = "---\ntitle: \"Commands\"\ndescription: \"In this page, you can find all the commands available in Doccupine CLI.\"\ndate: \"2026-02-19\"\ncategory: \"Getting Started\"\ncategoryOrder: 0\norder: 1\n---\n# Commands\nIn this page, you can find all the commands available in Doccupine CLI.\n\n## Run Doccupine CLI\nCreate a new directory for your project and navigate to it in your terminal. Run the following command to create a new Doccupine project:\n\n```bash\nnpx doccupine\n```\n\nOnce you run the command, Doccupine will ask you to select a directory to store your MDX files. Choose the directory where you want to create your documentation files.\nAfter selecting the directory, Doccupine will ask you to enter the name of the directory for the generated website. Enter the name of the directory where you want to create your website.\n\nThis will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.\n\n## Options\n\n| Flag | Description |\n|---|---|\n| `--port <port>` | Port for the dev server (default: `3000`). Auto-increments if taken. |\n| `--verbose` | Show all Next.js output including compilation details. |\n| `--reset` | Re-prompt for watch/output directories. |\n\n## Verbose mode\n\n```bash\nnpx doccupine --verbose\n```\n\n<Callout type=\"note\">\n This will show Next.js output in the terminal, providing detailed logs useful for debugging during development.\n</Callout>\n\n## Generate the website\n\n```bash\nnpx doccupine build\n```\n\nThis scaffolds the Next.js app from your MDX files without starting the development server. To produce a production build, run `npm install && npm run build` in the generated output directory.\n\n## Show current configuration\n\n```bash\nnpx doccupine config --show\n```\n\nThis will show the current configuration for Doccupine.\n\n## Reset configuration\n\n```bash\nnpx doccupine config --reset\n```\n\nThis will reset the current configuration for Doccupine.";
@@ -21,6 +21,14 @@ After selecting the directory, Doccupine will ask you to enter the name of the d
21
21
 
22
22
  This will start the development server on port 3000. Open your browser and navigate to http://localhost:3000 to view your documentation.
23
23
 
24
+ ## Options
25
+
26
+ | Flag | Description |
27
+ |---|---|
28
+ | \`--port <port>\` | Port for the dev server (default: \`3000\`). Auto-increments if taken. |
29
+ | \`--verbose\` | Show all Next.js output including compilation details. |
30
+ | \`--reset\` | Re-prompt for watch/output directories. |
31
+
24
32
  ## Verbose mode
25
33
 
26
34
  \`\`\`bash
@@ -28,7 +36,7 @@ npx doccupine --verbose
28
36
  \`\`\`
29
37
 
30
38
  <Callout type="note">
31
- This will show Next.js errors in the terminal console logs, providing more detailed output useful for debugging during development.
39
+ This will show Next.js output in the terminal, providing detailed logs useful for debugging during development.
32
40
  </Callout>
33
41
 
34
42
  ## Generate the website
@@ -37,7 +45,7 @@ npx doccupine --verbose
37
45
  npx doccupine build
38
46
  \`\`\`
39
47
 
40
- This will generate the build files for your documentation website without starting the development server. You can then deploy the generated files to a hosting service of your choice.
48
+ This scaffolds the Next.js app from your MDX files without starting the development server. To produce a production build, run \`npm install && npm run build\` in the generated output directory.
41
49
 
42
50
  ## Show current configuration
43
51
 
@@ -0,0 +1 @@
1
+ export declare const componentsMdxTemplate = "---\ntitle: \"Components\"\ndescription: \"Explore the full library of built-in components available in your documentation pages.\"\ndate: \"2026-02-19\"\ncategory: \"Components\"\ncategoryOrder: 1\norder: 0\n---\n# Components\n\nDoccupine includes a rich set of built-in components you can use directly in your MDX files - no imports needed. Browse the full library below.\n\n<Columns cols={3}>\n <Card title=\"Headers and Text\" icon=\"heading\" href=\"/headers-and-text\">\n Headings, paragraphs, bold, italic, links, and other text formatting.\n </Card>\n <Card title=\"Lists and Tables\" icon=\"list\" href=\"/lists-and-tables\">\n Ordered lists, unordered lists, and data tables.\n </Card>\n <Card title=\"Code\" icon=\"code\" href=\"/code\">\n Inline code, fenced code blocks, and syntax highlighting.\n </Card>\n <Card title=\"Accordion\" icon=\"chevrons-down\" href=\"/accordion\">\n Collapsible sections for organizing lengthy content.\n </Card>\n <Card title=\"Tabs\" icon=\"panel-top\" href=\"/tabs\">\n Tabbed interfaces for grouping related content.\n </Card>\n <Card title=\"Cards\" icon=\"square\" href=\"/cards\">\n Visual containers for content, icons, and links.\n </Card>\n <Card title=\"Buttons\" icon=\"mouse-pointer-click\" href=\"/buttons\">\n Action components with variants, sizes, and icons.\n </Card>\n <Card title=\"Callouts\" icon=\"megaphone\" href=\"/callouts\">\n Highlighted blocks for tips, warnings, and important notes.\n </Card>\n <Card title=\"Images and Embeds\" icon=\"image\" href=\"/images-and-embeds\">\n Images, videos, and embedded content.\n </Card>\n <Card title=\"Icons\" icon=\"smile\" href=\"/icons\">\n Lucide icons you can use anywhere in your docs.\n </Card>\n <Card title=\"Fields\" icon=\"text-cursor-input\" href=\"/fields\">\n Property and parameter documentation blocks.\n </Card>\n <Card title=\"Update\" icon=\"bell\" href=\"/update\">\n Changelog and update announcement blocks.\n </Card>\n <Card title=\"Columns\" icon=\"columns-3\" href=\"/columns\">\n Grid layouts for arranging cards and content side by side.\n </Card>\n <Card title=\"Steps\" icon=\"footprints\" href=\"/steps\">\n Numbered step-by-step guides and walkthroughs.\n </Card>\n</Columns>";
@@ -0,0 +1,56 @@
1
+ export const componentsMdxTemplate = `---
2
+ title: "Components"
3
+ description: "Explore the full library of built-in components available in your documentation pages."
4
+ date: "2026-02-19"
5
+ category: "Components"
6
+ categoryOrder: 1
7
+ order: 0
8
+ ---
9
+ # Components
10
+
11
+ Doccupine includes a rich set of built-in components you can use directly in your MDX files - no imports needed. Browse the full library below.
12
+
13
+ <Columns cols={3}>
14
+ <Card title="Headers and Text" icon="heading" href="/headers-and-text">
15
+ Headings, paragraphs, bold, italic, links, and other text formatting.
16
+ </Card>
17
+ <Card title="Lists and Tables" icon="list" href="/lists-and-tables">
18
+ Ordered lists, unordered lists, and data tables.
19
+ </Card>
20
+ <Card title="Code" icon="code" href="/code">
21
+ Inline code, fenced code blocks, and syntax highlighting.
22
+ </Card>
23
+ <Card title="Accordion" icon="chevrons-down" href="/accordion">
24
+ Collapsible sections for organizing lengthy content.
25
+ </Card>
26
+ <Card title="Tabs" icon="panel-top" href="/tabs">
27
+ Tabbed interfaces for grouping related content.
28
+ </Card>
29
+ <Card title="Cards" icon="square" href="/cards">
30
+ Visual containers for content, icons, and links.
31
+ </Card>
32
+ <Card title="Buttons" icon="mouse-pointer-click" href="/buttons">
33
+ Action components with variants, sizes, and icons.
34
+ </Card>
35
+ <Card title="Callouts" icon="megaphone" href="/callouts">
36
+ Highlighted blocks for tips, warnings, and important notes.
37
+ </Card>
38
+ <Card title="Images and Embeds" icon="image" href="/images-and-embeds">
39
+ Images, videos, and embedded content.
40
+ </Card>
41
+ <Card title="Icons" icon="smile" href="/icons">
42
+ Lucide icons you can use anywhere in your docs.
43
+ </Card>
44
+ <Card title="Fields" icon="text-cursor-input" href="/fields">
45
+ Property and parameter documentation blocks.
46
+ </Card>
47
+ <Card title="Update" icon="bell" href="/update">
48
+ Changelog and update announcement blocks.
49
+ </Card>
50
+ <Card title="Columns" icon="columns-3" href="/columns">
51
+ Grid layouts for arranging cards and content side by side.
52
+ </Card>
53
+ <Card title="Steps" icon="footprints" href="/steps">
54
+ Numbered step-by-step guides and walkthroughs.
55
+ </Card>
56
+ </Columns>`;