doccupine 0.0.88 → 0.0.90

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 (160) hide show
  1. package/README.md +15 -2
  2. package/dist/index.js +206 -5
  3. package/dist/lib/layout.js +38 -24
  4. package/dist/lib/metadata.d.ts +30 -0
  5. package/dist/lib/metadata.js +98 -1
  6. package/dist/templates/app/theme.d.ts +1 -1
  7. package/dist/templates/app/theme.js +84 -19
  8. package/dist/templates/components/Chat.d.ts +1 -1
  9. package/dist/templates/components/Chat.js +26 -27
  10. package/dist/templates/components/SearchModalContent.d.ts +1 -1
  11. package/dist/templates/components/SearchModalContent.js +12 -6
  12. package/dist/templates/components/SideBar.d.ts +1 -1
  13. package/dist/templates/components/SideBar.js +3 -1
  14. package/dist/templates/components/layout/Accordion.d.ts +1 -1
  15. package/dist/templates/components/layout/Accordion.js +2 -1
  16. package/dist/templates/components/layout/ActionBar.d.ts +1 -1
  17. package/dist/templates/components/layout/ActionBar.js +4 -6
  18. package/dist/templates/components/layout/Button.d.ts +1 -1
  19. package/dist/templates/components/layout/Button.js +19 -0
  20. package/dist/templates/components/layout/Callout.d.ts +1 -1
  21. package/dist/templates/components/layout/Callout.js +75 -20
  22. package/dist/templates/components/layout/Card.d.ts +1 -1
  23. package/dist/templates/components/layout/Card.js +2 -1
  24. package/dist/templates/components/layout/CherryThemeProvider.d.ts +1 -1
  25. package/dist/templates/components/layout/CherryThemeProvider.js +6 -12
  26. package/dist/templates/components/layout/ClientThemeProvider.d.ts +1 -1
  27. package/dist/templates/components/layout/ClientThemeProvider.js +45 -40
  28. package/dist/templates/components/layout/Code.d.ts +1 -1
  29. package/dist/templates/components/layout/Code.js +223 -255
  30. package/dist/templates/components/layout/ColorSwatch.d.ts +1 -1
  31. package/dist/templates/components/layout/ColorSwatch.js +2 -2
  32. package/dist/templates/components/layout/Columns.d.ts +1 -1
  33. package/dist/templates/components/layout/Columns.js +1 -1
  34. package/dist/templates/components/layout/DemoTheme.d.ts +1 -1
  35. package/dist/templates/components/layout/DemoTheme.js +65 -167
  36. package/dist/templates/components/layout/DocsComponents.d.ts +1 -1
  37. package/dist/templates/components/layout/DocsComponents.js +13 -19
  38. package/dist/templates/components/layout/Field.d.ts +1 -1
  39. package/dist/templates/components/layout/Field.js +6 -4
  40. package/dist/templates/components/layout/Footer.d.ts +1 -1
  41. package/dist/templates/components/layout/Footer.js +2 -3
  42. package/dist/templates/components/layout/GlobalStyles.d.ts +1 -1
  43. package/dist/templates/components/layout/GlobalStyles.js +63 -10
  44. package/dist/templates/components/layout/Header.d.ts +1 -1
  45. package/dist/templates/components/layout/Header.js +14 -11
  46. package/dist/templates/components/layout/SharedStyles.d.ts +1 -1
  47. package/dist/templates/components/layout/SharedStyles.js +4 -5
  48. package/dist/templates/components/layout/StaticLinks.d.ts +1 -1
  49. package/dist/templates/components/layout/StaticLinks.js +4 -6
  50. package/dist/templates/components/layout/Steps.d.ts +1 -1
  51. package/dist/templates/components/layout/Steps.js +3 -3
  52. package/dist/templates/components/layout/Tabs.d.ts +1 -1
  53. package/dist/templates/components/layout/Tabs.js +5 -2
  54. package/dist/templates/components/layout/ThemeToggle.d.ts +1 -1
  55. package/dist/templates/components/layout/ThemeToggle.js +17 -19
  56. package/dist/templates/components/layout/Typography.d.ts +1 -1
  57. package/dist/templates/components/layout/Typography.js +1 -1
  58. package/dist/templates/components/layout/Update.d.ts +1 -1
  59. package/dist/templates/components/layout/Update.js +4 -3
  60. package/dist/templates/llms/llmsFull.d.ts +12 -0
  61. package/dist/templates/llms/llmsFull.js +59 -0
  62. package/dist/templates/llms/llmsIndex.d.ts +9 -0
  63. package/dist/templates/llms/llmsIndex.js +105 -0
  64. package/dist/templates/llms/llmsPage.d.ts +2 -0
  65. package/dist/templates/llms/llmsPage.js +20 -0
  66. package/dist/templates/mdx/accordion.mdx.d.ts +1 -1
  67. package/dist/templates/mdx/accordion.mdx.js +21 -16
  68. package/dist/templates/mdx/ai-assistant.mdx.d.ts +1 -1
  69. package/dist/templates/mdx/ai-assistant.mdx.js +22 -5
  70. package/dist/templates/mdx/analytics.mdx.d.ts +1 -1
  71. package/dist/templates/mdx/analytics.mdx.js +15 -4
  72. package/dist/templates/mdx/buttons.mdx.d.ts +1 -1
  73. package/dist/templates/mdx/buttons.mdx.js +10 -2
  74. package/dist/templates/mdx/callouts.mdx.d.ts +1 -1
  75. package/dist/templates/mdx/callouts.mdx.js +10 -17
  76. package/dist/templates/mdx/cards.mdx.d.ts +1 -1
  77. package/dist/templates/mdx/cards.mdx.js +10 -5
  78. package/dist/templates/mdx/code.mdx.d.ts +1 -1
  79. package/dist/templates/mdx/code.mdx.js +7 -3
  80. package/dist/templates/mdx/color-swatches.mdx.d.ts +1 -1
  81. package/dist/templates/mdx/color-swatches.mdx.js +7 -4
  82. package/dist/templates/mdx/columns.mdx.d.ts +1 -1
  83. package/dist/templates/mdx/columns.mdx.js +3 -0
  84. package/dist/templates/mdx/commands.mdx.d.ts +1 -1
  85. package/dist/templates/mdx/commands.mdx.js +7 -4
  86. package/dist/templates/mdx/components.mdx.d.ts +1 -1
  87. package/dist/templates/mdx/components.mdx.js +1 -0
  88. package/dist/templates/mdx/deployment-and-hosting.mdx.d.ts +1 -1
  89. package/dist/templates/mdx/deployment-and-hosting.mdx.js +6 -0
  90. package/dist/templates/mdx/fields.mdx.d.ts +1 -1
  91. package/dist/templates/mdx/fields.mdx.js +3 -0
  92. package/dist/templates/mdx/fonts.mdx.d.ts +1 -1
  93. package/dist/templates/mdx/fonts.mdx.js +13 -2
  94. package/dist/templates/mdx/footer-links.mdx.d.ts +1 -1
  95. package/dist/templates/mdx/footer-links.mdx.js +5 -0
  96. package/dist/templates/mdx/globals.mdx.d.ts +1 -1
  97. package/dist/templates/mdx/globals.mdx.js +16 -13
  98. package/dist/templates/mdx/headers-and-text.mdx.d.ts +1 -1
  99. package/dist/templates/mdx/headers-and-text.mdx.js +22 -2
  100. package/dist/templates/mdx/icons.mdx.d.ts +1 -1
  101. package/dist/templates/mdx/icons.mdx.js +3 -0
  102. package/dist/templates/mdx/image-and-embeds.mdx.d.ts +1 -1
  103. package/dist/templates/mdx/image-and-embeds.mdx.js +19 -10
  104. package/dist/templates/mdx/index.mdx.d.ts +1 -1
  105. package/dist/templates/mdx/index.mdx.js +2 -2
  106. package/dist/templates/mdx/lists-and-tables.mdx.d.ts +1 -1
  107. package/dist/templates/mdx/lists-and-tables.mdx.js +8 -2
  108. package/dist/templates/mdx/media-and-assets.mdx.d.ts +1 -1
  109. package/dist/templates/mdx/media-and-assets.mdx.js +14 -5
  110. package/dist/templates/mdx/model-context-protocol.mdx.d.ts +1 -1
  111. package/dist/templates/mdx/model-context-protocol.mdx.js +31 -15
  112. package/dist/templates/mdx/navigation.mdx.d.ts +1 -1
  113. package/dist/templates/mdx/navigation.mdx.js +9 -0
  114. package/dist/templates/mdx/platform/ai-assistant.mdx.d.ts +1 -1
  115. package/dist/templates/mdx/platform/ai-assistant.mdx.js +7 -0
  116. package/dist/templates/mdx/platform/analytics.mdx.d.ts +1 -1
  117. package/dist/templates/mdx/platform/analytics.mdx.js +7 -0
  118. package/dist/templates/mdx/platform/billing.mdx.d.ts +1 -1
  119. package/dist/templates/mdx/platform/billing.mdx.js +8 -0
  120. package/dist/templates/mdx/platform/build-and-deploy.mdx.d.ts +1 -1
  121. package/dist/templates/mdx/platform/build-and-deploy.mdx.js +6 -0
  122. package/dist/templates/mdx/platform/creating-a-project.mdx.d.ts +1 -1
  123. package/dist/templates/mdx/platform/creating-a-project.mdx.js +7 -0
  124. package/dist/templates/mdx/platform/custom-domains.mdx.d.ts +1 -1
  125. package/dist/templates/mdx/platform/custom-domains.mdx.js +5 -0
  126. package/dist/templates/mdx/platform/external-links.mdx.d.ts +1 -1
  127. package/dist/templates/mdx/platform/external-links.mdx.js +5 -0
  128. package/dist/templates/mdx/platform/file-editor.mdx.d.ts +1 -1
  129. package/dist/templates/mdx/platform/file-editor.mdx.js +7 -0
  130. package/dist/templates/mdx/platform/fonts-settings.mdx.d.ts +1 -1
  131. package/dist/templates/mdx/platform/fonts-settings.mdx.js +5 -0
  132. package/dist/templates/mdx/platform/index.mdx.d.ts +1 -1
  133. package/dist/templates/mdx/platform/index.mdx.js +5 -0
  134. package/dist/templates/mdx/platform/navigation-settings.mdx.d.ts +1 -1
  135. package/dist/templates/mdx/platform/navigation-settings.mdx.js +20 -4
  136. package/dist/templates/mdx/platform/project-settings.mdx.d.ts +1 -1
  137. package/dist/templates/mdx/platform/project-settings.mdx.js +4 -0
  138. package/dist/templates/mdx/platform/publishing.mdx.d.ts +1 -1
  139. package/dist/templates/mdx/platform/publishing.mdx.js +6 -0
  140. package/dist/templates/mdx/platform/site-settings.mdx.d.ts +1 -1
  141. package/dist/templates/mdx/platform/site-settings.mdx.js +13 -1
  142. package/dist/templates/mdx/platform/team-members.mdx.d.ts +1 -1
  143. package/dist/templates/mdx/platform/team-members.mdx.js +8 -0
  144. package/dist/templates/mdx/platform/theme-settings.mdx.d.ts +1 -1
  145. package/dist/templates/mdx/platform/theme-settings.mdx.js +7 -0
  146. package/dist/templates/mdx/sections.mdx.d.ts +1 -1
  147. package/dist/templates/mdx/sections.mdx.js +22 -1
  148. package/dist/templates/mdx/steps.mdx.d.ts +1 -1
  149. package/dist/templates/mdx/steps.mdx.js +7 -5
  150. package/dist/templates/mdx/tabs.mdx.d.ts +1 -1
  151. package/dist/templates/mdx/tabs.mdx.js +7 -2
  152. package/dist/templates/mdx/theme.mdx.d.ts +1 -1
  153. package/dist/templates/mdx/theme.mdx.js +10 -0
  154. package/dist/templates/mdx/update.mdx.d.ts +1 -1
  155. package/dist/templates/mdx/update.mdx.js +17 -14
  156. package/dist/templates/package.js +14 -15
  157. package/dist/templates/pnpmWorkspace.d.ts +1 -0
  158. package/dist/templates/pnpmWorkspace.js +7 -0
  159. package/dist/templates/proxy.js +14 -20
  160. package/package.json +6 -7
@@ -1 +1 @@
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 { Search } from \"lucide-react\";\nimport { Logo } from \"@/components/layout/Pictograms\";\nimport { ChatContext, ChatButtonCTA } from \"@/components/Chat\";\nimport {\n SearchContext,\n SearchKbd,\n StyledSearchButton,\n} from \"@/components/SearchDocs\";\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: 10px;\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 const { openSearch } = useContext(SearchContext);\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 <StyledSearchButton onClick={openSearch} aria-label=\"Search docs\">\n <Search size={14} />\n <SearchKbd>&#8984;K</SearchKbd>\n </StyledSearchButton>\n {isChatActive && <ChatButtonCTA />}\n </StyledLeftWrapper>\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 } from \"styled-components\";\nimport Link from \"next/link\";\nimport { mq, Theme } from \"@/app/theme\";\nimport { useOnClickOutside } from \"@/components/ClickOutside\";\nimport { Search } from \"lucide-react\";\nimport { Logo } from \"@/components/layout/Pictograms\";\nimport { ChatContext, ChatButtonCTA } from \"@/components/Chat\";\nimport {\n SearchContext,\n SearchKbd,\n StyledSearchButton,\n} from \"@/components/SearchDocs\";\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 }) =>\n `color-mix(in srgb, ${theme.colors.primaryLight} 5%, transparent)`};\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: 10px;\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 { isChatActive } = useContext(ChatContext);\n const { openSearch } = useContext(SearchContext);\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 <>\n {/* Both logos render; .light-only and .dark-only classes in\n GlobalStyles hide the inactive one based on the \"dark\" class\n on <html>. Avoids a JS-driven swap so no flash on first load. */}\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img\n className=\"light-only\"\n src={customThemeJson.logo.light}\n alt=\"Logo\"\n width=\"100\"\n height=\"100\"\n />\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img\n className=\"dark-only\"\n src={customThemeJson.logo.dark}\n alt=\"Logo\"\n width=\"100\"\n height=\"100\"\n />\n </>\n ) : (\n <Logo />\n )}\n </Link>\n {children}\n <StyledLeftWrapper>\n <StyledSearchButton onClick={openSearch} aria-label=\"Search docs\">\n <Search size={14} />\n <SearchKbd>&#8984;K</SearchKbd>\n </StyledSearchButton>\n {isChatActive && <ChatButtonCTA />}\n </StyledLeftWrapper>\n </StyledHeaderInner>\n </StyledHeader>\n );\n}\n\nexport { Header };\n";
@@ -1,9 +1,8 @@
1
1
  export const headerTemplate = `"use client";
2
2
  import React from "react";
3
3
  import { useCallback, useContext, useRef, useState } from "react";
4
- import styled, { css, useTheme } from "styled-components";
4
+ import styled, { css } from "styled-components";
5
5
  import Link from "next/link";
6
- import { rgba } from "polished";
7
6
  import { mq, Theme } from "@/app/theme";
8
7
  import { useOnClickOutside } from "@/components/ClickOutside";
9
8
  import { Search } from "lucide-react";
@@ -52,7 +51,8 @@ const StyledHeader = styled.header<{ theme: Theme; $hasChildren: boolean }>\`
52
51
  }
53
52
 
54
53
  &::after {
55
- background: \${({ theme }) => rgba(theme.colors.primaryLight, 0.05)};
54
+ background: \${({ theme }) =>
55
+ \`color-mix(in srgb, \${theme.colors.primaryLight} 5%, transparent)\`};
56
56
  z-index: -1;
57
57
  }
58
58
 
@@ -127,7 +127,6 @@ function Header({ children }: HeaderProps) {
127
127
  isOptionActive ? closeMenu : () => {},
128
128
  );
129
129
  useOnClickOutside([langRef, wrapperRef], isLangActive ? closeMenu : () => {});
130
- const theme = useTheme() as Theme;
131
130
  const { isChatActive } = useContext(ChatContext);
132
131
  const { openSearch } = useContext(SearchContext);
133
132
 
@@ -136,23 +135,27 @@ function Header({ children }: HeaderProps) {
136
135
  <StyledHeaderInner $hasChildren={children ? true : false}>
137
136
  <Link href="/" className="logo" aria-label="Logo">
138
137
  {customThemeJson.logo ? (
139
- theme.isDark ? (
140
- // eslint-disable-next-line @next/next/no-img-element
138
+ <>
139
+ {/* Both logos render; .light-only and .dark-only classes in
140
+ GlobalStyles hide the inactive one based on the "dark" class
141
+ on <html>. Avoids a JS-driven swap so no flash on first load. */}
142
+ {/* eslint-disable-next-line @next/next/no-img-element */}
141
143
  <img
142
- src={customThemeJson.logo.dark}
144
+ className="light-only"
145
+ src={customThemeJson.logo.light}
143
146
  alt="Logo"
144
147
  width="100"
145
148
  height="100"
146
149
  />
147
- ) : (
148
- // eslint-disable-next-line @next/next/no-img-element
150
+ {/* eslint-disable-next-line @next/next/no-img-element */}
149
151
  <img
150
- src={customThemeJson.logo.light}
152
+ className="dark-only"
153
+ src={customThemeJson.logo.dark}
151
154
  alt="Logo"
152
155
  width="100"
153
156
  height="100"
154
157
  />
155
- )
158
+ </>
156
159
  ) : (
157
160
  <Logo />
158
161
  )}
@@ -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 }) =>\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";
1
+ export declare const sharedStyledTemplate = "\"use client\";\nimport { styledSmall, styledText } from \"cherry-styled-components\";\nimport { mq, Theme } from \"@/app/theme\";\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 }) => theme.colors.accent};\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 }) => theme.colors.accent};\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,5 +1,6 @@
1
1
  export const sharedStyledTemplate = `"use client";
2
- import { mq, styledSmall, styledText, Theme } from "cherry-styled-components";
2
+ import { styledSmall, styledText } from "cherry-styled-components";
3
+ import { mq, Theme } from "@/app/theme";
3
4
  import styled, { css } from "styled-components";
4
5
 
5
6
  export const interactiveStyles = css<{ theme: Theme }>\`
@@ -29,8 +30,7 @@ export const styledAnchor = css<{ theme: Theme }>\`
29
30
  box-shadow: 0 2px 0 0 \${({ theme }) => theme.colors.primary};
30
31
 
31
32
  &:hover {
32
- color: \${({ theme }) =>
33
- theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
33
+ color: \${({ theme }) => theme.colors.accent};
34
34
  box-shadow: 0 1px 0 0 \${({ theme }) => theme.colors.primary};
35
35
  }
36
36
  }
@@ -148,8 +148,7 @@ 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 }) =>
152
- theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
151
+ color: \${({ theme }) => theme.colors.accent};
153
152
  border-radius: \${({ theme }) => theme.spacing.radius.xs};
154
153
  padding: 6px 8px;
155
154
  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.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";
1
+ export declare const staticLinksTemplate = "\"use client\";\nimport styled, { css } from \"styled-components\";\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 }) => theme.colors.accent};\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 }) =>\n `color-mix(in srgb, ${theme.colors.primaryLight} 10%, transparent)`};\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 }) => theme.colors.accent};\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";
@@ -1,7 +1,6 @@
1
1
  import { SIDEBAR_WIDTH, CHAT_WIDTH } from "../../app/theme.js";
2
2
  export const staticLinksTemplate = `"use client";
3
3
  import styled, { css } from "styled-components";
4
- import { rgba } from "polished";
5
4
  import { useContext } from "react";
6
5
  import { ChatContext } from "@/components/Chat";
7
6
  import { mq, Theme } from "@/app/theme";
@@ -51,8 +50,7 @@ const StyledLink = styled.a<{ theme: Theme; $hasIcon?: boolean }>\`
51
50
  text-decoration: none;
52
51
  font-size: \${({ theme }) => theme.fontSizes.small.lg};
53
52
  line-height: 1;
54
- color: \${({ theme }) =>
55
- theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
53
+ color: \${({ theme }) => theme.colors.accent};
56
54
  padding: 0;
57
55
  display: flex;
58
56
  gap: 6px;
@@ -60,7 +58,8 @@ const StyledLink = styled.a<{ theme: Theme; $hasIcon?: boolean }>\`
60
58
  font-weight: 600;
61
59
  white-space: nowrap;
62
60
  min-width: fit-content;
63
- background: \${({ theme }) => rgba(theme.colors.primaryLight, 0.1)};
61
+ background: \${({ theme }) =>
62
+ \`color-mix(in srgb, \${theme.colors.primaryLight} 10%, transparent)\`};
64
63
  padding: 6px 8px;
65
64
  border-radius: \${({ theme }) => theme.spacing.radius.xs};
66
65
  \${interactiveStyles};
@@ -83,8 +82,7 @@ const StyledLink = styled.a<{ theme: Theme; $hasIcon?: boolean }>\`
83
82
  }
84
83
 
85
84
  &:hover {
86
- color: \${({ theme }) =>
87
- theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
85
+ color: \${({ theme }) => theme.colors.accent};
88
86
  }
89
87
  \`;
90
88
 
@@ -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 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";
1
+ export declare const stepsTemplate = "\"use client\";\nimport React from \"react\";\nimport styled, { useTheme } from \"styled-components\";\nimport { styledText } from \"cherry-styled-components\";\nimport { Theme } from \"@/app/theme\";\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 transparent\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";
@@ -1,8 +1,8 @@
1
1
  export const stepsTemplate = `"use client";
2
2
  import React from "react";
3
3
  import styled, { useTheme } from "styled-components";
4
- import { styledText, Theme } from "cherry-styled-components";
5
- import { rgba } from "polished";
4
+ import { styledText } from "cherry-styled-components";
5
+ import { Theme } from "@/app/theme";
6
6
  import { Icon, IconProps } from "@/components/layout/Icon";
7
7
 
8
8
  const StyledStepsContainer = styled.div<{ theme: Theme }>\`
@@ -30,7 +30,7 @@ const StyledStep = styled.div<{ theme: Theme }>\`
30
30
  background: linear-gradient(
31
31
  180deg,
32
32
  \${({ theme }) => theme.colors.primary},
33
- \${({ theme }) => rgba(theme.colors.primary, 0)}
33
+ transparent
34
34
  );
35
35
  border-radius: 4px;
36
36
  }
@@ -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\";\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";
1
+ export declare const tabsTemplate = "\"use client\";\nimport { Theme } from \"@/app/theme\";\nimport { styledText } from \"cherry-styled-components\";\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: color-mix(\n in srgb,\n ${theme.colors.primaryLight} 10%,\n transparent\n );\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,7 +1,6 @@
1
1
  export const tabsTemplate = `"use client";
2
2
  import { Theme } from "@/app/theme";
3
3
  import { styledText } from "cherry-styled-components";
4
- import { rgba } from "polished";
5
4
  import React, { useState, ReactNode } from "react";
6
5
  import styled, { css } from "styled-components";
7
6
  interface TabContentProps {
@@ -49,7 +48,11 @@ const TabButton = styled.button<{ theme: Theme; $isActive?: boolean }>\`
49
48
  !$isActive &&
50
49
  css\`
51
50
  color: \${theme.colors.primary};
52
- background-color: \${rgba(theme.colors.primaryLight, 0.1)};
51
+ background-color: color-mix(
52
+ in srgb,
53
+ \${theme.colors.primaryLight} 10%,
54
+ transparent
55
+ );
53
56
  \`}
54
57
  }
55
58
  &:focus {
@@ -1 +1 @@
1
- export declare const themeToggleTemplate = "\"use client\";\nimport { Theme, resetButton } from \"cherry-styled-components\";\nimport styled, { css, useTheme } from \"styled-components\";\nimport { rgba } from \"polished\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport { theme as themeLight, themeDark } from \"@/app/theme\";\nimport { useThemeOverride } from \"@/components/layout/ClientThemeProvider\";\n\nconst StyledThemeToggle = styled.button<{ theme: Theme; $hidden?: boolean }>`\n ${resetButton}\n width: 59px;\n height: 32px;\n border-radius: 30px;\n display: flex;\n position: relative;\n margin: auto 0;\n transform: scale(1);\n background: ${({ theme }) => theme.colors.light};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n\n &::after {\n content: \"\";\n position: absolute;\n top: 3px;\n left: 3px;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: ${({ theme }) => rgba(theme.colors.primaryLight, 0.2)};\n transition: all 0.3s ease;\n z-index: 1;\n ${({ theme }) =>\n theme.isDark &&\n css`\n transform: translateX(27px);\n `}\n }\n\n ${({ $hidden }) =>\n $hidden &&\n css`\n display: none;\n `}\n\n & svg {\n width: 16px;\n height: 16px;\n object-fit: contain;\n margin: auto;\n transition: all 0.3s ease;\n position: relative;\n z-index: 2;\n }\n\n & .lucide-sun {\n transform: translateX(1px);\n }\n\n & .lucide-moon-star {\n transform: translateX(-1px);\n }\n\n & svg[stroke] {\n stroke: ${({ theme }) => theme.colors.primary};\n }\n\n &:hover {\n transform: scale(1.05);\n color: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n\n & svg[stroke] {\n stroke: ${({ theme }) =>\n theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};\n }\n }\n\n &:active {\n transform: scale(0.97);\n }\n`;\n\nfunction ToggleTheme({ $hidden }: { $hidden?: boolean }) {\n const { setTheme } = useThemeOverride();\n const theme = useTheme() as Theme;\n\n return (\n <StyledThemeToggle\n onClick={async () => {\n const nextTheme = theme.isDark ? \"light\" : \"dark\";\n setTheme(nextTheme === \"light\" ? themeLight : themeDark);\n await fetch(\"/api/theme\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ theme: nextTheme }),\n }).catch((err) => console.error(\"Failed to persist theme:\", err));\n }}\n $hidden={$hidden}\n aria-label=\"Toggle Theme\"\n >\n <Icon name=\"Sun\" className=\"light\" />\n <Icon name=\"MoonStar\" className=\"dark\" />\n </StyledThemeToggle>\n );\n}\n\nfunction ToggleThemeLoading() {\n return (\n <StyledThemeToggle $hidden aria-label=\"Toggle Theme\">\n <Icon name=\"MoonStar\" className=\"dark\" />\n <Icon name=\"Sun\" className=\"light\" />\n </StyledThemeToggle>\n );\n}\n\nexport { ToggleTheme, ToggleThemeLoading };\n";
1
+ export declare const themeToggleTemplate = "\"use client\";\nimport { resetButton } from \"cherry-styled-components\";\nimport styled, { css } from \"styled-components\";\nimport { Theme } from \"@/app/theme\";\nimport { Icon } from \"@/components/layout/Icon\";\nimport { useThemeOverride } from \"@/components/layout/ClientThemeProvider\";\n\nconst StyledThemeToggle = styled.button<{ theme: Theme; $hidden?: boolean }>`\n ${resetButton}\n width: 59px;\n height: 32px;\n border-radius: 30px;\n display: flex;\n position: relative;\n margin: auto 0;\n transform: scale(1);\n background: ${({ theme }) => theme.colors.light};\n border: solid 1px ${({ theme }) => theme.colors.grayLight};\n\n &::after {\n content: \"\";\n position: absolute;\n top: 3px;\n left: 3px;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: ${({ theme }) =>\n `color-mix(in srgb, ${theme.colors.primaryLight} 20%, transparent)`};\n transition: all 0.3s ease;\n z-index: 1;\n }\n\n /* Knob position depends on the active mode, signaled by the \"dark\" class\n on <html>. Pure CSS \u2014 no JS conditional needed for the visual swap. */\n :root.dark &::after {\n transform: translateX(27px);\n }\n\n ${({ $hidden }) =>\n $hidden &&\n css`\n display: none;\n `}\n\n & svg {\n width: 16px;\n height: 16px;\n object-fit: contain;\n margin: auto;\n transition: all 0.3s ease;\n position: relative;\n z-index: 2;\n }\n\n & .lucide-sun {\n transform: translateX(1px);\n }\n\n & .lucide-moon-star {\n transform: translateX(-1px);\n }\n\n & svg[stroke] {\n stroke: ${({ theme }) => theme.colors.primary};\n }\n\n &:hover {\n transform: scale(1.05);\n color: ${({ theme }) => theme.colors.accent};\n\n & svg[stroke] {\n stroke: ${({ theme }) => theme.colors.accent};\n }\n }\n\n &:active {\n transform: scale(0.97);\n }\n`;\n\nfunction ToggleTheme({ $hidden }: { $hidden?: boolean }) {\n const { mode, setMode } = useThemeOverride();\n\n return (\n <StyledThemeToggle\n onClick={async () => {\n const next = mode === \"dark\" ? \"light\" : \"dark\";\n setMode(next);\n await fetch(\"/api/theme\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ theme: next }),\n }).catch((err) => console.error(\"Failed to persist theme:\", err));\n }}\n $hidden={$hidden}\n aria-label=\"Toggle Theme\"\n >\n <Icon name=\"Sun\" className=\"light\" />\n <Icon name=\"MoonStar\" className=\"dark\" />\n </StyledThemeToggle>\n );\n}\n\nfunction ToggleThemeLoading() {\n return (\n <StyledThemeToggle $hidden aria-label=\"Toggle Theme\">\n <Icon name=\"MoonStar\" className=\"dark\" />\n <Icon name=\"Sun\" className=\"light\" />\n </StyledThemeToggle>\n );\n}\n\nexport { ToggleTheme, ToggleThemeLoading };\n";
@@ -1,9 +1,8 @@
1
1
  export const themeToggleTemplate = `"use client";
2
- import { Theme, resetButton } from "cherry-styled-components";
3
- import styled, { css, useTheme } from "styled-components";
4
- import { rgba } from "polished";
2
+ import { resetButton } from "cherry-styled-components";
3
+ import styled, { css } from "styled-components";
4
+ import { Theme } from "@/app/theme";
5
5
  import { Icon } from "@/components/layout/Icon";
6
- import { theme as themeLight, themeDark } from "@/app/theme";
7
6
  import { useThemeOverride } from "@/components/layout/ClientThemeProvider";
8
7
 
9
8
  const StyledThemeToggle = styled.button<{ theme: Theme; $hidden?: boolean }>\`
@@ -26,14 +25,16 @@ const StyledThemeToggle = styled.button<{ theme: Theme; $hidden?: boolean }>\`
26
25
  width: 24px;
27
26
  height: 24px;
28
27
  border-radius: 50%;
29
- background: \${({ theme }) => rgba(theme.colors.primaryLight, 0.2)};
28
+ background: \${({ theme }) =>
29
+ \`color-mix(in srgb, \${theme.colors.primaryLight} 20%, transparent)\`};
30
30
  transition: all 0.3s ease;
31
31
  z-index: 1;
32
- \${({ theme }) =>
33
- theme.isDark &&
34
- css\`
35
- transform: translateX(27px);
36
- \`}
32
+ }
33
+
34
+ /* Knob position depends on the active mode, signaled by the "dark" class
35
+ on <html>. Pure CSS — no JS conditional needed for the visual swap. */
36
+ :root.dark &::after {
37
+ transform: translateX(27px);
37
38
  }
38
39
 
39
40
  \${({ $hidden }) =>
@@ -66,12 +67,10 @@ const StyledThemeToggle = styled.button<{ theme: Theme; $hidden?: boolean }>\`
66
67
 
67
68
  &:hover {
68
69
  transform: scale(1.05);
69
- color: \${({ theme }) =>
70
- theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
70
+ color: \${({ theme }) => theme.colors.accent};
71
71
 
72
72
  & svg[stroke] {
73
- stroke: \${({ theme }) =>
74
- theme.isDark ? theme.colors.primaryLight : theme.colors.primaryDark};
73
+ stroke: \${({ theme }) => theme.colors.accent};
75
74
  }
76
75
  }
77
76
 
@@ -81,18 +80,17 @@ const StyledThemeToggle = styled.button<{ theme: Theme; $hidden?: boolean }>\`
81
80
  \`;
82
81
 
83
82
  function ToggleTheme({ $hidden }: { $hidden?: boolean }) {
84
- const { setTheme } = useThemeOverride();
85
- const theme = useTheme() as Theme;
83
+ const { mode, setMode } = useThemeOverride();
86
84
 
87
85
  return (
88
86
  <StyledThemeToggle
89
87
  onClick={async () => {
90
- const nextTheme = theme.isDark ? "light" : "dark";
91
- setTheme(nextTheme === "light" ? themeLight : themeDark);
88
+ const next = mode === "dark" ? "light" : "dark";
89
+ setMode(next);
92
90
  await fetch("/api/theme", {
93
91
  method: "POST",
94
92
  headers: { "Content-Type": "application/json" },
95
- body: JSON.stringify({ theme: nextTheme }),
93
+ body: JSON.stringify({ theme: next }),
96
94
  }).catch((err) => console.error("Failed to persist theme:", err));
97
95
  }}
98
96
  $hidden={$hidden}
@@ -1 +1 @@
1
- export declare const typographyTemplate = "\"use client\";\nimport {\n styledH1,\n styledH2,\n styledH3,\n styledH4,\n styledH5,\n styledH6,\n styledText,\n Theme,\n} from \"cherry-styled-components\";\nimport styled, { css } from \"styled-components\";\n\nconst StyledHeading = css`\n font-weight: 900;\n`;\n\nexport const StyledH1 = styled.h1<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH1(theme)}\n`;\n\nexport const StyledH2 = styled.h2<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH2(theme)}\n`;\n\nexport const StyledH3 = styled.h3<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH3(theme)}\n`;\n\nexport const StyledH4 = styled.h4<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH4(theme)}\n`;\n\nexport const StyledH5 = styled.h5<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH5(theme)}\n`;\n\nexport const StyledH6 = styled.h6<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH6(theme)}\n`;\n\nexport const StyledText = styled.p<{ theme: Theme }>`\n ${({ theme }) => styledText(theme)}\n`;\n";
1
+ export declare const typographyTemplate = "\"use client\";\nimport {\n styledH1,\n styledH2,\n styledH3,\n styledH4,\n styledH5,\n styledH6,\n styledText,\n} from \"cherry-styled-components\";\nimport styled, { css } from \"styled-components\";\nimport { Theme } from \"@/app/theme\";\n\nconst StyledHeading = css`\n font-weight: 900;\n`;\n\nexport const StyledH1 = styled.h1<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH1(theme)}\n`;\n\nexport const StyledH2 = styled.h2<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH2(theme)}\n`;\n\nexport const StyledH3 = styled.h3<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH3(theme)}\n`;\n\nexport const StyledH4 = styled.h4<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH4(theme)}\n`;\n\nexport const StyledH5 = styled.h5<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH5(theme)}\n`;\n\nexport const StyledH6 = styled.h6<{ theme: Theme }>`\n ${StyledHeading};\n ${({ theme }) => styledH6(theme)}\n`;\n\nexport const StyledText = styled.p<{ theme: Theme }>`\n ${({ theme }) => styledText(theme)}\n`;\n";
@@ -7,9 +7,9 @@ import {
7
7
  styledH5,
8
8
  styledH6,
9
9
  styledText,
10
- Theme,
11
10
  } from "cherry-styled-components";
12
11
  import styled, { css } from "styled-components";
12
+ import { Theme } from "@/app/theme";
13
13
 
14
14
  const StyledHeading = css\`
15
15
  font-weight: 900;
@@ -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\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";
1
+ export declare const updateTemplate = "\"use client\";\nimport styled from \"styled-components\";\nimport { styledSmall } from \"cherry-styled-components\";\nimport { mq, Theme } from \"@/app/theme\";\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 }) =>\n `color-mix(in srgb, ${theme.colors.primaryLight} 20%, transparent)`};\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";
@@ -1,7 +1,7 @@
1
1
  export const updateTemplate = `"use client";
2
2
  import styled from "styled-components";
3
- import { mq, styledSmall, Theme } from "cherry-styled-components";
4
- import { rgba } from "polished";
3
+ import { styledSmall } from "cherry-styled-components";
4
+ import { mq, Theme } from "@/app/theme";
5
5
 
6
6
  const StyledUpdate = styled.div<{ theme: Theme; $columns?: number }>\`
7
7
  position: relative;
@@ -16,7 +16,8 @@ const StyledUpdate = styled.div<{ theme: Theme; $columns?: number }>\`
16
16
  \`;
17
17
 
18
18
  const StyledUpdateLabel = styled.span<{ theme: Theme }>\`
19
- background: \${({ theme }) => rgba(theme.colors.primaryLight, 0.2)};
19
+ background: \${({ theme }) =>
20
+ \`color-mix(in srgb, \${theme.colors.primaryLight} 20%, transparent)\`};
20
21
  color: \${({ theme }) => theme.colors.primary};
21
22
  padding: 2px 4px;
22
23
  border-radius: \${({ theme }) => theme.spacing.radius.xs};
@@ -0,0 +1,12 @@
1
+ import type { PageMeta, SectionConfig } from "../../lib/types.js";
2
+ export interface PageWithBody extends PageMeta {
3
+ body: string;
4
+ }
5
+ export interface LlmsFullArgs {
6
+ siteName: string;
7
+ siteDescription?: string;
8
+ baseUrl: string | null;
9
+ pages: PageWithBody[];
10
+ sectionsConfig: SectionConfig[] | null;
11
+ }
12
+ export declare function llmsFullTemplate(args: LlmsFullArgs): string;
@@ -0,0 +1,59 @@
1
+ function pageUrl(slug, baseUrl) {
2
+ if (baseUrl) {
3
+ return slug === "" ? `${baseUrl}/` : `${baseUrl}/${slug}`;
4
+ }
5
+ return slug === "" ? "/" : `/${slug}`;
6
+ }
7
+ function orderedPages(pages, sectionsConfig) {
8
+ const sectionOrderIndex = new Map();
9
+ sectionOrderIndex.set("", 0);
10
+ if (sectionsConfig) {
11
+ sectionsConfig.forEach((section, idx) => {
12
+ sectionOrderIndex.set(section.slug, idx + 1);
13
+ });
14
+ }
15
+ return [...pages].sort((a, b) => {
16
+ const sa = sectionOrderIndex.get(a.section) ?? 999;
17
+ const sb = sectionOrderIndex.get(b.section) ?? 999;
18
+ if (sa !== sb)
19
+ return sa - sb;
20
+ if (a.categoryOrder !== b.categoryOrder)
21
+ return a.categoryOrder - b.categoryOrder;
22
+ if (a.category !== b.category)
23
+ return a.category.localeCompare(b.category);
24
+ if (a.order !== b.order)
25
+ return a.order - b.order;
26
+ return a.title.localeCompare(b.title);
27
+ });
28
+ }
29
+ export function llmsFullTemplate(args) {
30
+ const { siteName, siteDescription, baseUrl, pages, sectionsConfig } = args;
31
+ const lines = [];
32
+ lines.push(`# ${siteName}`);
33
+ lines.push("");
34
+ lines.push(`> Full documentation for ${siteName}.`);
35
+ if (siteDescription && siteDescription.trim() !== "") {
36
+ lines.push("");
37
+ lines.push(siteDescription.trim());
38
+ }
39
+ lines.push("");
40
+ if (pages.length === 0) {
41
+ return lines.join("\n") + "\n";
42
+ }
43
+ const sorted = orderedPages(pages, sectionsConfig);
44
+ for (const page of sorted) {
45
+ lines.push("---");
46
+ lines.push("");
47
+ lines.push(`# ${page.title}`);
48
+ lines.push("");
49
+ if (page.description && page.description.trim() !== "") {
50
+ lines.push(`> ${page.description.trim()}`);
51
+ lines.push("");
52
+ }
53
+ lines.push(`Source: ${pageUrl(page.slug, baseUrl)}`);
54
+ lines.push("");
55
+ lines.push(page.body.trim());
56
+ lines.push("");
57
+ }
58
+ return lines.join("\n").replace(/\n+$/, "\n");
59
+ }
@@ -0,0 +1,9 @@
1
+ import type { PageMeta, SectionConfig } from "../../lib/types.js";
2
+ export interface LlmsIndexArgs {
3
+ siteName: string;
4
+ siteDescription?: string;
5
+ baseUrl: string | null;
6
+ pages: PageMeta[];
7
+ sectionsConfig: SectionConfig[] | null;
8
+ }
9
+ export declare function llmsIndexTemplate(args: LlmsIndexArgs): string;
@@ -0,0 +1,105 @@
1
+ function pageUrl(slug, baseUrl) {
2
+ if (baseUrl) {
3
+ return slug === "" ? `${baseUrl}/` : `${baseUrl}/${slug}`;
4
+ }
5
+ return slug === "" ? "/" : `/${slug}`;
6
+ }
7
+ function comparePages(a, b) {
8
+ if (a.order !== b.order)
9
+ return a.order - b.order;
10
+ return a.title.localeCompare(b.title);
11
+ }
12
+ function buildSectionGroups(pages, sectionsConfig) {
13
+ const sectionOrderIndex = new Map();
14
+ sectionOrderIndex.set("", 0);
15
+ if (sectionsConfig) {
16
+ sectionsConfig.forEach((section, idx) => {
17
+ sectionOrderIndex.set(section.slug, idx + 1);
18
+ });
19
+ }
20
+ const sectionLabelByslug = new Map();
21
+ if (sectionsConfig) {
22
+ for (const section of sectionsConfig) {
23
+ sectionLabelByslug.set(section.slug, section.label);
24
+ }
25
+ }
26
+ const bySection = new Map();
27
+ for (const page of pages) {
28
+ const key = page.section || "";
29
+ const list = bySection.get(key) ?? [];
30
+ list.push(page);
31
+ bySection.set(key, list);
32
+ }
33
+ const groups = [];
34
+ for (const [sectionSlug, sectionPages] of bySection) {
35
+ const byCategory = new Map();
36
+ for (const page of sectionPages) {
37
+ const key = page.category || "";
38
+ const list = byCategory.get(key) ?? [];
39
+ list.push(page);
40
+ byCategory.set(key, list);
41
+ }
42
+ const categories = [];
43
+ for (const [category, catPages] of byCategory) {
44
+ catPages.sort(comparePages);
45
+ const minCategoryOrder = catPages.reduce((min, p) => Math.min(min, p.categoryOrder), Number.POSITIVE_INFINITY);
46
+ categories.push({
47
+ category,
48
+ minCategoryOrder: Number.isFinite(minCategoryOrder)
49
+ ? minCategoryOrder
50
+ : 0,
51
+ pages: catPages,
52
+ });
53
+ }
54
+ categories.sort((a, b) => {
55
+ if (a.minCategoryOrder !== b.minCategoryOrder) {
56
+ return a.minCategoryOrder - b.minCategoryOrder;
57
+ }
58
+ return a.category.localeCompare(b.category);
59
+ });
60
+ groups.push({
61
+ sectionSlug,
62
+ sectionLabel: sectionLabelByslug.get(sectionSlug) ??
63
+ (sectionSlug === "" ? "Documentation" : sectionSlug),
64
+ sectionOrder: sectionOrderIndex.get(sectionSlug) ?? 999,
65
+ categories,
66
+ });
67
+ }
68
+ groups.sort((a, b) => a.sectionOrder - b.sectionOrder);
69
+ return groups;
70
+ }
71
+ export function llmsIndexTemplate(args) {
72
+ const { siteName, siteDescription, baseUrl, pages, sectionsConfig } = args;
73
+ const lines = [];
74
+ lines.push(`# ${siteName}`);
75
+ lines.push("");
76
+ if (siteDescription && siteDescription.trim() !== "") {
77
+ lines.push(`> ${siteDescription.trim()}`);
78
+ lines.push("");
79
+ }
80
+ if (pages.length === 0) {
81
+ return lines.join("\n") + "\n";
82
+ }
83
+ const groups = buildSectionGroups(pages, sectionsConfig);
84
+ for (const group of groups) {
85
+ lines.push(`## ${group.sectionLabel}`);
86
+ lines.push("");
87
+ const useCategoryHeadings = group.categories.length > 1 ||
88
+ (group.categories.length === 1 && group.categories[0].category !== "");
89
+ for (const cat of group.categories) {
90
+ if (useCategoryHeadings && cat.category !== "") {
91
+ lines.push(`### ${cat.category}`);
92
+ lines.push("");
93
+ }
94
+ for (const page of cat.pages) {
95
+ const url = pageUrl(page.slug, baseUrl);
96
+ const desc = page.description && page.description.trim() !== ""
97
+ ? `: ${page.description.trim()}`
98
+ : "";
99
+ lines.push(`- [${page.title}](${url})${desc}`);
100
+ }
101
+ lines.push("");
102
+ }
103
+ }
104
+ return lines.join("\n").replace(/\n+$/, "\n");
105
+ }
@@ -0,0 +1,2 @@
1
+ import type { PageWithBody } from "./llmsFull.js";
2
+ export declare function llmsPageTemplate(page: PageWithBody, baseUrl: string | null): string;