@xyd-js/components 0.1.0-xyd.7 → 0.1.0-xyd.94

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 (251) hide show
  1. package/.idea/git_toolbox_blame.xml +6 -0
  2. package/.idea/modules.xml +8 -0
  3. package/.idea/vcs.xml +6 -0
  4. package/.idea/xyd-components.iml +12 -0
  5. package/CHANGELOG.md +718 -0
  6. package/LICENSE +21 -0
  7. package/TODO.md +1 -0
  8. package/content.ts +0 -2
  9. package/dist/CTABanner-Bc77pnms.js +2 -0
  10. package/dist/CTABanner-Bc77pnms.js.map +1 -0
  11. package/dist/CTABanner-DzO62aGj.js +2 -0
  12. package/dist/CTABanner-DzO62aGj.js.map +1 -0
  13. package/dist/CodeSample-BWPDgd2G.js +2 -0
  14. package/dist/CodeSample-BWPDgd2G.js.map +1 -0
  15. package/dist/CodeSample-DLnR-knP.js +2 -0
  16. package/dist/CodeSample-DLnR-knP.js.map +1 -0
  17. package/dist/HomeView-C8QlNdKh.js +2 -0
  18. package/dist/HomeView-C8QlNdKh.js.map +1 -0
  19. package/dist/HomeView-ZAP5saNy.js +2 -0
  20. package/dist/HomeView-ZAP5saNy.js.map +1 -0
  21. package/dist/Icon-BESh23UN.js +2 -0
  22. package/dist/Icon-BESh23UN.js.map +1 -0
  23. package/dist/Icon-xNucOqd2.js +2 -0
  24. package/dist/Icon-xNucOqd2.js.map +1 -0
  25. package/dist/Text-CfN9RkYA.js +2 -0
  26. package/dist/Text-CfN9RkYA.js.map +1 -0
  27. package/dist/Text-DKycD2zu.js +2 -0
  28. package/dist/Text-DKycD2zu.js.map +1 -0
  29. package/dist/Update-0XruJHjj.js +2 -0
  30. package/dist/Update-0XruJHjj.js.map +1 -0
  31. package/dist/Update-DKOAw8p9.js +2 -0
  32. package/dist/Update-DKOAw8p9.js.map +1 -0
  33. package/dist/VideoGuide-BUyomFVz.js +2 -0
  34. package/dist/VideoGuide-BUyomFVz.js.map +1 -0
  35. package/dist/VideoGuide-B_iUKKv7.js +2 -0
  36. package/dist/VideoGuide-B_iUKKv7.js.map +1 -0
  37. package/dist/_rollupPluginBabelHelpers-CxSUtGup.js +4 -0
  38. package/dist/_rollupPluginBabelHelpers-CxSUtGup.js.map +1 -0
  39. package/dist/_rollupPluginBabelHelpers-DZ-ucadG.js +4 -0
  40. package/dist/_rollupPluginBabelHelpers-DZ-ucadG.js.map +1 -0
  41. package/dist/brand.d.ts +9 -9
  42. package/dist/brand.js +1 -1
  43. package/dist/brand.js.map +1 -1
  44. package/dist/coder/themes/cosmo-light.js.map +1 -1
  45. package/dist/coder.d.ts +29 -9
  46. package/dist/coder.js +1 -1
  47. package/dist/coder.js.map +1 -1
  48. package/dist/content.d.ts +268 -204
  49. package/dist/content.js +1 -1
  50. package/dist/content.js.map +1 -1
  51. package/dist/index.css +267 -216
  52. package/dist/layouts.d.ts +20 -21
  53. package/dist/layouts.js +1 -1
  54. package/dist/layouts.js.map +1 -1
  55. package/dist/pages.js +1 -1
  56. package/dist/pages.js.map +1 -1
  57. package/dist/system.d.ts +10 -0
  58. package/dist/system.js +2 -0
  59. package/dist/system.js.map +1 -0
  60. package/dist/tslib.es6-DyL9kPq9.js +2 -0
  61. package/dist/{tslib.es6-DDIOdJiV.js.map → tslib.es6-DyL9kPq9.js.map} +1 -1
  62. package/dist/tslib.es6-Hqk-Mdr9.js +2 -0
  63. package/dist/{tslib.es6-DUrRPhZd.js.map → tslib.es6-Hqk-Mdr9.js.map} +1 -1
  64. package/dist/views.js +1 -1
  65. package/dist/writer.d.ts +411 -78
  66. package/dist/writer.js +1 -1
  67. package/dist/writer.js.map +1 -1
  68. package/docs/.nojekyll +1 -0
  69. package/docs/assets/hierarchy.js +1 -0
  70. package/docs/assets/highlight.css +22 -0
  71. package/docs/assets/icons.js +18 -0
  72. package/docs/assets/icons.svg +1 -0
  73. package/docs/assets/main.js +60 -0
  74. package/docs/assets/navigation.js +1 -0
  75. package/docs/assets/search.js +1 -0
  76. package/docs/assets/style.css +1640 -0
  77. package/docs/functions/GuideCard.html +6 -0
  78. package/docs/hierarchy.html +1 -0
  79. package/docs/index.html +2 -0
  80. package/docs/interfaces/GuideCardProps.html +18 -0
  81. package/docs/modules.html +1 -0
  82. package/index.ts +0 -1
  83. package/package.json +13 -18
  84. package/project.json +677 -0
  85. package/rollup.config.js +32 -3
  86. package/src/brand/Button/Button.styles.tsx +28 -0
  87. package/src/brand/Button/Button.tsx +3 -35
  88. package/src/brand/CTABanner/CTABanner.styles.tsx +80 -0
  89. package/src/brand/CTABanner/CTABanner.tsx +34 -112
  90. package/src/brand/Footer/Footer.styles.tsx +18 -0
  91. package/src/brand/Footer/Footer.tsx +4 -24
  92. package/src/brand/TODO.md +1 -0
  93. package/src/coder/Code/Code.styles.tsx +134 -35
  94. package/src/coder/Code/Code.tsx +131 -40
  95. package/src/coder/Code/CodeLoader.tsx +4 -4
  96. package/src/coder/Code/annotations.tsx +28 -8
  97. package/src/coder/Code/highlight.ts +38 -0
  98. package/src/coder/Code/index.ts +2 -1
  99. package/src/coder/CodeCopy/{CodeCopy.style.tsx → CodeCopy.styles.tsx} +6 -6
  100. package/src/coder/CodeCopy/CodeCopy.tsx +6 -6
  101. package/src/coder/CodeSample/CodeSample.tsx +83 -27
  102. package/src/coder/CodeTabs/CodeTabs.styles.tsx +99 -78
  103. package/src/coder/CodeTabs/CodeTabs.tsx +71 -56
  104. package/src/coder/CodeTheme/CodeTheme.tsx +89 -49
  105. package/src/coder/CodeTheme/index.ts +0 -1
  106. package/src/coder/CoderProvider.tsx +26 -0
  107. package/src/coder/index.ts +8 -4
  108. package/src/content/ContentDecoator.styles.tsx +113 -0
  109. package/src/content/ContentDecorator.tsx +17 -0
  110. package/src/content/GridDecorator.styles.tsx +67 -0
  111. package/src/content/GridDecorator.tsx +21 -0
  112. package/src/content/ReactContent.tsx +575 -0
  113. package/src/content/index.ts +10 -2
  114. package/src/icons/index.ts +0 -0
  115. package/src/kit/Loader/Loader.styles.tsx +53 -0
  116. package/src/kit/Loader/Loader.tsx +22 -0
  117. package/src/kit/TODO.md +2 -0
  118. package/src/kit/index.ts +1 -0
  119. package/src/layouts/LayoutPrimary/LayoutPrimary.styles.tsx +263 -278
  120. package/src/layouts/LayoutPrimary/LayoutPrimary.tsx +173 -96
  121. package/src/layouts/LayoutPrimary/index.ts +0 -2
  122. package/src/layouts/index.ts +0 -7
  123. package/src/pages/HomePage/HomePage.styles.tsx +16 -0
  124. package/src/pages/HomePage/HomePage.tsx +7 -21
  125. package/src/pages/TODO.md +1 -0
  126. package/src/system/SearchButton/SearchButton.styles.tsx +86 -0
  127. package/src/system/SearchButton/SearchButton.tsx +116 -0
  128. package/src/system/SearchButton/index.ts +1 -0
  129. package/src/system/index.ts +1 -0
  130. package/src/utils/useStyle.ts +19 -0
  131. package/src/views/HomeView/HomeView.styles.tsx +37 -0
  132. package/src/views/HomeView/HomeView.tsx +5 -45
  133. package/src/views/TODO.md +1 -0
  134. package/src/writer/Anchor/Anchor.styles.tsx +11 -0
  135. package/src/writer/Anchor/Anchor.tsx +51 -0
  136. package/src/writer/Anchor/index.tsx +1 -0
  137. package/src/writer/Badge/Badge.styles.tsx +39 -28
  138. package/src/writer/Badge/Badge.tsx +37 -20
  139. package/src/writer/Banner/Banner.styles.tsx +91 -0
  140. package/src/writer/Banner/Banner.tsx +70 -0
  141. package/src/writer/Banner/index.ts +1 -0
  142. package/src/writer/Blockquote/Blockquote.styles.tsx +4 -4
  143. package/src/writer/Blockquote/Blockquote.tsx +6 -3
  144. package/src/writer/Breadcrumbs/Breadcrumbs.styles.ts +22 -21
  145. package/src/writer/Breadcrumbs/Breadcrumbs.tsx +19 -13
  146. package/src/writer/Button/Button.styles.tsx +137 -0
  147. package/src/writer/Button/Button.tsx +75 -0
  148. package/src/writer/Button/index.ts +2 -0
  149. package/src/writer/Callout/Callout.styles.tsx +29 -40
  150. package/src/writer/Callout/Callout.tsx +31 -16
  151. package/src/writer/Card/Card.styles.tsx +47 -0
  152. package/src/writer/Card/Card.tsx +69 -0
  153. package/src/writer/Card/index.ts +1 -0
  154. package/src/writer/Code/Code.styles.tsx +10 -11
  155. package/src/writer/Code/Code.tsx +7 -4
  156. package/src/writer/ColorSchemeButton/ColorSchemeButton.tsx +172 -0
  157. package/src/writer/ColorSchemeButton/index.ts +1 -0
  158. package/src/writer/Details/Details.styles.tsx +84 -84
  159. package/src/writer/Details/Details.tsx +71 -51
  160. package/src/writer/Example/index.tsx +5 -0
  161. package/src/writer/GuideCard/GuideCard.styles.tsx +108 -107
  162. package/src/writer/GuideCard/GuideCard.tsx +72 -37
  163. package/src/writer/Heading/Heading.styles.tsx +69 -49
  164. package/src/writer/Heading/Heading.tsx +92 -22
  165. package/src/writer/Hr/Hr.styles.tsx +5 -5
  166. package/src/writer/Hr/Hr.tsx +3 -6
  167. package/src/writer/Icon/Icon.tsx +48 -0
  168. package/src/writer/Icon/index.ts +1 -0
  169. package/src/writer/Image/Image.styles.tsx +9 -0
  170. package/src/writer/Image/Image.tsx +19 -0
  171. package/src/writer/Image/index.ts +1 -0
  172. package/src/writer/List/List.styles.tsx +47 -0
  173. package/src/writer/List/List.tsx +29 -0
  174. package/src/writer/List/index.ts +4 -0
  175. package/src/writer/NavLinks/NavLinks.styles.ts +23 -24
  176. package/src/writer/NavLinks/NavLinks.tsx +66 -19
  177. package/src/writer/Pre/Pre.styles.tsx +5 -5
  178. package/src/writer/Pre/Pre.tsx +4 -3
  179. package/src/writer/Steps/Steps.styles.tsx +14 -12
  180. package/src/writer/Steps/Steps.tsx +39 -10
  181. package/src/writer/Table/Table.styles.tsx +62 -30
  182. package/src/writer/Table/Table.tsx +121 -11
  183. package/src/writer/Table/index.ts +0 -11
  184. package/src/writer/Tabs/Tabs.styles.tsx +63 -70
  185. package/src/writer/Tabs/Tabs.tsx +31 -29
  186. package/src/writer/Text/Text.styles.tsx +66 -0
  187. package/src/writer/Text/Text.tsx +79 -0
  188. package/src/writer/Text/index.ts +3 -0
  189. package/src/writer/TocCard/TocCard.module.css +44 -0
  190. package/src/writer/TocCard/TocCard.tsx +42 -0
  191. package/src/writer/TocCard/index.ts +3 -0
  192. package/src/writer/UnderlineNav/Tabs.tsx +51 -0
  193. package/src/writer/UnderlineNav/TabsPrimary.styles.tsx +184 -0
  194. package/src/writer/UnderlineNav/TabsPrimary.tsx +209 -0
  195. package/src/writer/UnderlineNav/TabsSecondary.styles.tsx +77 -0
  196. package/src/writer/UnderlineNav/TabsSecondary.tsx +171 -0
  197. package/src/writer/UnderlineNav/UnderlineNav.styles.tsx +181 -45
  198. package/src/writer/UnderlineNav/UnderlineNav.tsx +258 -23
  199. package/src/writer/UnderlineNav/index.ts +2 -1
  200. package/src/writer/UnderlineNav/useValueChange.ts +60 -0
  201. package/src/writer/Update/Update.styles.tsx +33 -0
  202. package/src/writer/Update/Update.tsx +37 -0
  203. package/src/writer/Update/index.ts +1 -0
  204. package/src/writer/VideoGuide/VideoGuide.module.css +105 -0
  205. package/src/writer/VideoGuide/VideoGuide.tsx +75 -0
  206. package/src/writer/VideoGuide/index.ts +1 -0
  207. package/src/writer/index.ts +23 -1
  208. package/tsconfig.json +11 -6
  209. package/types.d.ts +50 -0
  210. package/writer.ts +1 -1
  211. package/dist/CTABanner-BrdYlhnD.js +0 -2
  212. package/dist/CTABanner-BrdYlhnD.js.map +0 -1
  213. package/dist/CTABanner-XQNnnpUx.js +0 -2
  214. package/dist/CTABanner-XQNnnpUx.js.map +0 -1
  215. package/dist/CodeSample-Cp42Adjc.js +0 -2
  216. package/dist/CodeSample-Cp42Adjc.js.map +0 -1
  217. package/dist/CodeSample-DxPp80ID.js +0 -2
  218. package/dist/CodeSample-DxPp80ID.js.map +0 -1
  219. package/dist/HomeView-BN9mZXh9.js +0 -2
  220. package/dist/HomeView-BN9mZXh9.js.map +0 -1
  221. package/dist/HomeView-BVaaV0uE.js +0 -2
  222. package/dist/HomeView-BVaaV0uE.js.map +0 -1
  223. package/dist/UnderlineNav-Bs7Ot9Ch.js +0 -2
  224. package/dist/UnderlineNav-Bs7Ot9Ch.js.map +0 -1
  225. package/dist/UnderlineNav-C2aEVraN.js +0 -2
  226. package/dist/UnderlineNav-C2aEVraN.js.map +0 -1
  227. package/dist/_rollupPluginBabelHelpers-BMmCG_qQ.js +0 -2
  228. package/dist/_rollupPluginBabelHelpers-BMmCG_qQ.js.map +0 -1
  229. package/dist/_rollupPluginBabelHelpers-DsEzE6Ab.js +0 -2
  230. package/dist/_rollupPluginBabelHelpers-DsEzE6Ab.js.map +0 -1
  231. package/dist/index-BVUz77Tm.js +0 -2
  232. package/dist/index-BVUz77Tm.js.map +0 -1
  233. package/dist/index-jxd3nv2J.js +0 -2
  234. package/dist/index-jxd3nv2J.js.map +0 -1
  235. package/dist/tslib.es6-DDIOdJiV.js +0 -2
  236. package/dist/tslib.es6-DUrRPhZd.js +0 -2
  237. package/src/content/Anchor/Anchor.tsx +0 -63
  238. package/src/content/Anchor/index.tsx +0 -3
  239. package/src/content/Content/Content.tsx +0 -21
  240. package/src/content/Content/index.tsx +0 -3
  241. package/src/content/Content.tsx +0 -180
  242. package/src/content/Subtitle/Subtitle.tsx +0 -21
  243. package/src/content/Subtitle/index.tsx +0 -3
  244. package/src/layouts/Layout.styles.tsx +0 -151
  245. package/src/layouts/Layout.tsx +0 -121
  246. package/src/ui/Loader/Loader.styles.tsx +0 -52
  247. package/src/ui/Loader/Loader.tsx +0 -26
  248. package/src/ui/index.ts +0 -1
  249. package/src/writer/Icon/index.tsx +0 -355
  250. package/src/writer/Table/TableV2.styles.tsx +0 -117
  251. package/src/writer/Table/TableV2.tsx +0 -83
@@ -1,158 +1,235 @@
1
- import React, {useEffect, useState} from "react"
1
+ import * as React from 'react'
2
+ import { useContext, useEffect, useRef, useState } from "react"
2
3
 
3
- import {$layout, $page, $article, globalHeaderHeight} from "./LayoutPrimary.styles.tsx"
4
+ import { PageLayout } from '@xyd-js/core';
5
+
6
+ import * as cn from "./LayoutPrimary.styles"
4
7
 
5
8
  export interface LayoutPrimaryProps {
6
- header: React.ReactNode;
7
- aside: React.ReactNode;
8
- content: React.ReactNode;
9
- contentNav: React.ReactNode;
9
+ children: React.ReactNode;
10
10
 
11
- subheader?: React.ReactNode;
12
- layoutSize?: "large"
11
+ subheader?: boolean;
12
+ className?: string;
13
+ layout?: PageLayout
14
+ scrollKey?: string
13
15
  }
14
16
 
17
+ const LayoutPrimaryContext = React.createContext<{
18
+ scrollRef: React.RefObject<HTMLDivElement | Window | null>;
19
+ isMobileNavOpen: boolean;
20
+ setIsMobileNavOpen: (isOpen: boolean) => void;
21
+ }>({
22
+ scrollRef: React.createRef(),
23
+ isMobileNavOpen: false,
24
+ setIsMobileNavOpen: () => { },
25
+ })
26
+
15
27
  // TODO: move scroller to xyd-foo
16
28
  export function LayoutPrimary(props: LayoutPrimaryProps) {
29
+ const scrollRef = useRef<HTMLDivElement | Window>(null)
17
30
  const [isMobileNavOpen, setIsMobileNavOpen] = useState(false)
31
+ const { hideMainHeader } = useSubHeader(props.subheader ? scrollRef : null, props.scrollKey)
18
32
 
19
- const {hideMainHeader} = props.subheader ? useSubHeader() : {hideMainHeader: false}
33
+ useEffect(() => {
34
+ scrollRef.current = window
35
+ }, [])
36
+
37
+ return <LayoutPrimaryContext value={{
38
+ scrollRef,
39
+ isMobileNavOpen,
40
+ setIsMobileNavOpen
41
+ }}
42
+ >
43
+ <xyd-layout-primary
44
+ className={`${cn.LayoutPrimaryHost} ${props.className || ""}`}
45
+ data-subheader={String(!!props.subheader)}
46
+ data-hide-subheader={String(hideMainHeader)}
47
+ data-layout={props.layout}
48
+ >
49
+ {props.children}
50
+ </xyd-layout-primary>
51
+ </LayoutPrimaryContext>
52
+ }
53
+
54
+ interface LayoutPrimaryHeaderProps {
55
+ header: React.ReactNode;
56
+
57
+ subheader?: React.ReactNode;
58
+ }
59
+ LayoutPrimary.Header = function LayoutPrimaryHeader(props: LayoutPrimaryHeaderProps) {
60
+ const { isMobileNavOpen, setIsMobileNavOpen } = useContext(LayoutPrimaryContext)
20
61
 
21
- return <div className={$layout.host}>
22
- <header className={`
23
- ${$layout.header}
24
- ${props.subheader && $layout.header$$sub}
25
- ${hideMainHeader && $layout.header$$hideMain}
26
- `}>
27
- <div className={$layout.primaryHeaderContent}>
62
+ return <>
63
+ <header part="header">
64
+ <div part="header-content">
28
65
  {props.header}
29
66
  <button
30
- className={$layout.hamburgerButton}
31
- onClick={() => setIsMobileNavOpen(!isMobileNavOpen)}
67
+ part="hamburger-button"
32
68
  aria-label="Toggle navigation menu"
69
+ onClick={() => setIsMobileNavOpen(!isMobileNavOpen)}
33
70
  >
34
- <div className={$layout.hamburgerIcon}>
35
- <span className={`${$layout.hamburgerLine} ${isMobileNavOpen ? $layout.hamburgerLine$$open : ''}`}/>
36
- <span className={`${$layout.hamburgerLine} ${isMobileNavOpen ? $layout.hamburgerLine$$open : ''}`}/>
37
- <span className={`${$layout.hamburgerLine} ${isMobileNavOpen ? $layout.hamburgerLine$$open : ''}`}/>
71
+ <div part="hamburger-icon">
72
+ <$HamburgerLine active={isMobileNavOpen} />
73
+ <$HamburgerLine active={isMobileNavOpen} />
74
+ <$HamburgerLine active={isMobileNavOpen} />
38
75
  </div>
39
76
  </button>
40
77
  </div>
78
+
41
79
  {props.subheader}
42
80
  </header>
81
+ </>
82
+ }
43
83
 
44
- {/* Mobile Drawer Sidebar */}
84
+ interface LayoutPrimaryMobileAsideProps {
85
+ aside: React.ReactNode;
86
+ }
87
+ LayoutPrimary.MobileAside = function LayoutPrimaryAside(props: LayoutPrimaryMobileAsideProps) {
88
+ const { isMobileNavOpen, setIsMobileNavOpen } = useContext(LayoutPrimaryContext)
89
+ return <>
45
90
  <div
46
- className={`${$layout.overlay} ${isMobileNavOpen ? $layout.overlay$$visible : ''}`}
91
+ part="mobile-overlay"
92
+ data-active={isMobileNavOpen}
47
93
  onClick={() => setIsMobileNavOpen(false)}
48
94
  />
49
- <aside className={`
50
- ${$layout.mobileSidebar}
51
- ${isMobileNavOpen ? $layout.mobileSidebar$$open : ''}
52
- `}>
53
- <div className={$layout.sidebarContent}>
95
+ <aside
96
+ part="mobile-sidebar"
97
+ data-active={isMobileNavOpen}
98
+ >
99
+ <div part="mobile-sidebar-aside">
54
100
  {props.aside}
55
101
  </div>
56
102
  <button
57
- className={$layout.closeButton}
58
- onClick={() => setIsMobileNavOpen(false)}
103
+ part="mobile-sidebar-close-button"
59
104
  aria-label="Close navigation menu"
105
+ onClick={() => setIsMobileNavOpen(false)}
60
106
  >
61
- <div className={$layout.closeIcon}/>
107
+ <div part="mobile-sidebar-close-icon" />
62
108
  </button>
63
109
  </aside>
110
+ </>
111
+ }
64
112
 
65
- <main className={`
66
- ${$layout.main}
67
- ${!hideMainHeader && props.subheader && $layout.main$$sub}
68
- `}>
69
- {/* Desktop Static Sidebar */}
70
- <aside className={$layout.staticSidebar}>
71
- {props.aside}
72
- </aside>
73
-
74
- <div className={$page.host}>
75
- <div className={$page.scroll}>
76
- <div className={`
77
- ${$page.container}
78
- ${props.layoutSize == "large" && $page.container$$large}
79
- `}>
80
- <div className={`
81
- ${$page.articleContainer}
82
- `}>
83
- <article className={$article.host}>
84
- <section className={$article.content}>
85
- {props.content}
86
- </section>
87
- {
88
- props.contentNav && <nav className={`
89
- ${$article.nav}
90
- `}>
91
- {props.contentNav}
92
- </nav>
93
- }
94
- </article>
95
- </div>
113
+ interface LayoutPrimaryPageProps {
114
+ children: React.ReactNode;
115
+ contentNav?: React.ReactNode;
116
+ }
117
+ LayoutPrimary.Page = function LayoutPrimaryPage(props: LayoutPrimaryPageProps) {
118
+ return <>
119
+ <div part="page">
120
+ <div part="page-scroll">
121
+ <div part="page-container">
122
+ <div part="page-article-container">
123
+
124
+ <article part="page-article">
125
+ <section part="page-article-content">
126
+ {props.children}
127
+ </section>
128
+ </article>
129
+
130
+ {
131
+ props.contentNav && <nav part="page-article-nav">
132
+ {props.contentNav}
133
+ </nav>
134
+ }
96
135
  </div>
97
136
  </div>
98
137
  </div>
99
- </main>
100
- </div>
138
+ </div>
139
+ </>
140
+ }
141
+
142
+ function $HamburgerLine({ active }: { active: boolean }) {
143
+ return <span
144
+ part="hamburger-line"
145
+ data-active={active}
146
+ />
101
147
  }
102
148
 
149
+ const SCROLL_DOWN_TRIGGER_THRESHOLD = 200;
150
+ const SCROLL_UP_TRIGGER_THRESHOLD = 100;
151
+
103
152
  // TODO: move to `xyd-foo` or somewhere else
104
- function useSubHeader() {
153
+ // TODO better solution than `key`
154
+ function useSubHeader(ref: React.RefObject<HTMLDivElement | Window | null> | null, key?: any) {
105
155
  const [hideMainHeader, setHideMainHeader] = useState(false)
106
- const [scrollTop, setScrollTop] = useState(0)
107
- const [controlScrollPos, setControlScrollPos] = useState(0)
156
+ const [lastScrollTop, setLastScrollTop] = useState(0)
157
+ const [scrollDirection, setScrollDirection] = useState<'up' | 'down' | null>(null)
158
+ const [scrollThreshold, setScrollThreshold] = useState(0)
159
+ const [scrollStartPosition, setScrollStartPosition] = useState(0)
160
+ const [isScrolling, setIsScrolling] = useState(false)
161
+
162
+ function reset() {
163
+ setHideMainHeader(false)
164
+ setLastScrollTop(0)
165
+ setScrollDirection(null)
166
+ setScrollThreshold(0)
167
+ setScrollStartPosition(0)
168
+ setIsScrolling(false)
169
+ }
108
170
 
109
171
  useEffect(() => {
110
- if (scrollTop === controlScrollPos) {
172
+ reset()
173
+ }, [key])
174
+
175
+ function onScroll(e: Event) {
176
+ if (!(e.target instanceof HTMLElement)) {
111
177
  return
112
178
  }
113
179
 
114
- const checkpoint = parseInt(globalHeaderHeight, 10) / 2
115
- const diff = scrollTop - controlScrollPos
116
- const reversePosDiff = Math.abs(scrollTop - controlScrollPos)
180
+ const currentScrollTop = e.target.scrollTop
117
181
 
118
- if (diff > checkpoint) {
119
- setHideMainHeader(true)
120
- } else if (reversePosDiff > checkpoint) {
182
+ // Always show header when near the top of the page
183
+ if (currentScrollTop < SCROLL_UP_TRIGGER_THRESHOLD) {
121
184
  setHideMainHeader(false)
185
+ setScrollThreshold(0)
186
+ setLastScrollTop(currentScrollTop)
187
+ setIsScrolling(false)
188
+ return
122
189
  }
123
- }, [
124
- scrollTop,
125
- controlScrollPos,
126
- ]);
127
190
 
128
- function onScroll(e: Event) {
129
- if (!(e.target instanceof HTMLElement)) {
130
- return
191
+ // Determine scroll direction
192
+ const direction = currentScrollTop > lastScrollTop ? 'down' : 'up'
193
+
194
+ // If direction changed, reset scroll tracking
195
+ if (direction !== scrollDirection) {
196
+ setScrollDirection(direction)
197
+ setScrollStartPosition(currentScrollTop)
198
+ setIsScrolling(true)
131
199
  }
132
200
 
133
- const scroll = e.target?.scrollTop
134
- setScrollTop(scroll)
135
- }
201
+ // Calculate total scroll distance from start position
202
+ const totalScrollDistance = Math.abs(currentScrollTop - scrollStartPosition)
136
203
 
137
- function onScrollFinish(e: Event) {
138
- if (!(e.target instanceof HTMLElement)) {
139
- return
204
+ // Only trigger header changes if we've scrolled enough distance in the current direction
205
+ if (direction === 'down' && totalScrollDistance > SCROLL_DOWN_TRIGGER_THRESHOLD) {
206
+ // When scrolling down, hide header
207
+ setHideMainHeader(true)
208
+ setScrollThreshold(currentScrollTop)
209
+ // Reset scroll tracking after triggering
210
+ setScrollStartPosition(currentScrollTop)
211
+ } else if (direction === 'up' && totalScrollDistance > SCROLL_UP_TRIGGER_THRESHOLD) {
212
+ // When scrolling up, show header
213
+ setHideMainHeader(false)
214
+ setScrollThreshold(currentScrollTop)
215
+ // Reset scroll tracking after triggering
216
+ setScrollStartPosition(currentScrollTop)
140
217
  }
141
218
 
142
- setControlScrollPos(e.target?.scrollTop)
219
+ setLastScrollTop(currentScrollTop)
143
220
  }
144
221
 
145
- // TODO: by ref?
146
- // TODO: MOVE SOMEWHERE ELSE BECAUSE IT DECREASE PERFORMANCE (RERENDER)
147
222
  useEffect(() => {
148
- document.querySelector(`.${$page.scroll}`)?.addEventListener("scroll", onScroll)
149
- document.querySelector(`.${$page.scroll}`)?.addEventListener("scrollend", onScrollFinish)
223
+ if (!ref?.current) {
224
+ return
225
+ }
226
+
227
+ ref.current.addEventListener("scroll", onScroll)
150
228
 
151
229
  return () => {
152
- document.querySelector(`.${$page.scroll}`)?.removeEventListener("scroll", onScroll)
153
- document.querySelector(`.${$page.scroll}`)?.removeEventListener("scrollend", onScrollFinish)
230
+ ref.current?.removeEventListener("scroll", onScroll)
154
231
  }
155
- }, []);
232
+ }, [ref, key, lastScrollTop, scrollDirection, scrollThreshold, scrollStartPosition]);
156
233
 
157
234
  return {
158
235
  hideMainHeader,
@@ -1,5 +1,3 @@
1
1
  export {
2
2
  LayoutPrimary
3
3
  } from "./LayoutPrimary";
4
-
5
- export type {LayoutPrimaryProps} from "./LayoutPrimary";
@@ -2,12 +2,5 @@
2
2
 
3
3
  export {
4
4
  LayoutPrimary,
5
- type LayoutPrimaryProps
6
5
  } from "./LayoutPrimary";
7
6
 
8
- export {
9
- Layout
10
- } from "./Layout";
11
-
12
- export type {LayoutProps} from "./Layout";
13
-
@@ -0,0 +1,16 @@
1
+ import {css} from "@linaria/core";
2
+
3
+ export const HomePageCardsHost = css`
4
+ display: grid;
5
+ grid-template-columns: repeat(2, 500px);
6
+ justify-content: center;
7
+ gap: 30px;
8
+
9
+ @media (max-width: 1200px) {
10
+ grid-template-columns: repeat(2, 1fr);
11
+ }
12
+
13
+ @media (max-width: 768px) {
14
+ grid-template-columns: 1fr;
15
+ }
16
+ `;
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import {css} from "@linaria/core";
2
+ import * as cn from "./HomePage.styles";
3
3
 
4
4
  import {
5
5
  GuideCard,
@@ -9,23 +9,6 @@ import {HomeView} from "../../views"
9
9
 
10
10
  import {IHomePageHero, IHomePageFeature} from "./types";
11
11
 
12
- const $cards = {
13
- host: css`
14
- display: grid;
15
- grid-template-columns: repeat(2, 500px);
16
- justify-content: center;
17
- gap: 30px;
18
-
19
- @media (max-width: 1200px) {
20
- grid-template-columns: repeat(2, 1fr);
21
- }
22
-
23
- @media (max-width: 768px) {
24
- grid-template-columns: 1fr;
25
- }
26
- `,
27
- }
28
-
29
12
  export interface HomePageProps {
30
13
  header: React.ReactNode
31
14
 
@@ -50,11 +33,14 @@ export function HomePage(props: HomePageProps) {
50
33
  }
51
34
 
52
35
  function $Hero(props: HomePageProps) {
36
+ const subtitle = typeof props.hero?.subtitle === 'string'
37
+ ? props.hero.subtitle
38
+ : props.hero?.subtitle?.toString() || "";
39
+
53
40
  return <CTABanner>
54
41
  <CTABanner.Heading
55
42
  title={props.hero?.text || ""}
56
- headingEffect={props.hero?.textEffect}
57
- subtitle={props.hero?.subtitle}
43
+ subtitle={subtitle}
58
44
  />
59
45
  {props?.hero?.actions && <CTABanner.ButtonGroup>
60
46
  {props?.hero?.actions.map((action, index) => (
@@ -72,7 +58,7 @@ function $Cards(props: HomePageProps) {
72
58
  // TODO: cards gridTemplateColumns based on elements
73
59
  return <div
74
60
  className={`
75
- ${$cards.host}
61
+ ${cn.HomePageCardsHost}
76
62
  xyd_page-comp-homepage-cards
77
63
  `}>
78
64
  {props.features?.map((feat, index) => (
@@ -0,0 +1 @@
1
+ move to `@xyd-js/pages` ?
@@ -0,0 +1,86 @@
1
+ import { css } from "@linaria/core";
2
+
3
+ export const SearchButton = css`
4
+ @layer defaults {
5
+ background-color: transparent;
6
+ border-radius: 8px;
7
+ border: 1px solid var(--dark32);
8
+ color: var(--text-primary);
9
+ background: var(--dark16);
10
+ font-size: var(--xyd-font-size-small);
11
+ font-weight: var(--xyd-font-weight-semibold);
12
+ height: 36px;
13
+ justify-content: space-between;
14
+ display: flex;
15
+ align-items: center;
16
+ flex: 1;
17
+
18
+ padding: 0 8px;
19
+ margin: 12px 0 0;
20
+ user-select: none;
21
+ width: 100%;
22
+ transition: border-color .15s ease;
23
+
24
+
25
+ max-width: 300px;
26
+ margin: 0;
27
+
28
+ cursor: pointer;
29
+
30
+ &:hover {
31
+ background: var(--dark16);
32
+ box-shadow: none;
33
+ color: var(--dark48);
34
+ outline: none;
35
+
36
+ box-shadow: none;
37
+ border-color: var(--dark48);
38
+ }
39
+
40
+ [part="container"] {
41
+ align-items: center;
42
+ display: flex;
43
+ }
44
+
45
+ [part="placeholder"] {
46
+ display: block !important;
47
+ font-size: var(--xyd-font-size-small);
48
+ color: var(--dark48);
49
+ font-weight: var(--xyd-font-weight-normal);
50
+ }
51
+
52
+ [part="icon"] {
53
+ stroke-width: 1.4;
54
+ color: var(--dark48) !important;
55
+ height: 15px;
56
+ transition: color .15s var(--cubic-enter);
57
+ }
58
+
59
+
60
+ [part="keys"] {
61
+ display: flex;
62
+ gap: 4px;
63
+ min-width: auto;
64
+ }
65
+
66
+ [part="key"] {
67
+ align-items: center;
68
+ background: var(--dark16);
69
+ border-radius: 3px;
70
+ box-shadow: none;
71
+ color: var(--dark48);
72
+ display: flex;
73
+ height: 18px;
74
+ line-height: 18px;
75
+ justify-content: center;
76
+ font-size: 12px;
77
+ letter-spacing: 1px;
78
+ position: relative;
79
+ padding: 0;
80
+ margin: 0;
81
+ border: 0px;
82
+ top: 0;
83
+ width: 20px;
84
+ }
85
+ }
86
+ `
@@ -0,0 +1,116 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+
3
+ import * as cn from "./SearchButton.styles";
4
+
5
+ interface SearchButtonProps {
6
+ onClick?: () => void;
7
+ placeholder?: string;
8
+ shortcutKeys?: string[];
9
+ }
10
+
11
+ export function SearchButton({
12
+ shortcutKeys = ['⌘', 'K'],
13
+ ...props
14
+ }: SearchButtonProps) {
15
+ useShortcuts(shortcutKeys, () => props.onClick?.());
16
+
17
+ useEffect(() => {
18
+ // @ts-ignore - !!! FIX IN THE FUTURE !!! its a fix for loading virtual-component:Search twice? original and from plugin - check if exists on prod
19
+ window.__UNSAFE_xyd_search_button_inited = true
20
+
21
+ return () => {
22
+ // @ts-ignore
23
+ window.__UNSAFE_xyd_search_button_inited = false
24
+ }
25
+ }, [])
26
+
27
+ return (
28
+ <xyd-search-button
29
+ className={cn.SearchButton}
30
+ aria-label="Search"
31
+ onClick={props.onClick}
32
+ >
33
+ <span part="container">
34
+ <svg
35
+ width={20}
36
+ height={20}
37
+ part="icon"
38
+ viewBox="0 0 20 20"
39
+ >
40
+ <path
41
+ d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
42
+ stroke="currentColor"
43
+ fill="none"
44
+ fillRule="evenodd"
45
+ strokeLinecap="round"
46
+ strokeLinejoin="round"
47
+ />
48
+ </svg>
49
+ <span part="placeholder">{props.placeholder || "Search"}</span>
50
+ </span>
51
+
52
+ {
53
+ shortcutKeys.length > 0 && (
54
+ <span part="keys">
55
+ {shortcutKeys.map((key, index) => (
56
+ <kbd key={index} part="key">{key}</kbd>
57
+ ))}
58
+ </span>
59
+ )
60
+ }
61
+ </xyd-search-button>
62
+ )
63
+ }
64
+
65
+ function useShortcuts(shortcutKeys: string[], onTrigger: () => void): void {
66
+ // Keep latest handler reference to avoid stale closures
67
+ const savedHandler = useRef(onTrigger);
68
+
69
+ useEffect(() => {
70
+ savedHandler.current = onTrigger;
71
+ }, [onTrigger]);
72
+
73
+ useEffect(() => {
74
+ // @ts-ignore
75
+ if (window.__UNSAFE_xyd_search_button_inited) {
76
+ return
77
+ }
78
+
79
+ const listener = (event: KeyboardEvent) => {
80
+ // For single key shortcuts
81
+ if (shortcutKeys.length === 1) {
82
+ if (event.key.toLowerCase() === shortcutKeys[0].toLowerCase()) {
83
+ event.preventDefault();
84
+
85
+ savedHandler.current();
86
+ }
87
+ return;
88
+ }
89
+
90
+ // For modifier combinations
91
+ if (shortcutKeys.length === 2) {
92
+ const [modifier, key] = shortcutKeys;
93
+ const pressedKey = event.key.toLowerCase();
94
+
95
+ const isModifierMatch =
96
+ (modifier === '⌘' && event.metaKey) ||
97
+ (modifier === 'Ctrl' && event.ctrlKey);
98
+
99
+ if (isModifierMatch && pressedKey === key.toLowerCase()) {
100
+ event.preventDefault();
101
+
102
+ savedHandler.current();
103
+ }
104
+ }
105
+ };
106
+
107
+ // Use capture phase and listen to both keydown and keyup
108
+ window.addEventListener('keydown', listener, { capture: true });
109
+ window.addEventListener('keyup', listener, { capture: true });
110
+
111
+ return () => {
112
+ window.removeEventListener('keydown', listener, { capture: true });
113
+ window.removeEventListener('keyup', listener, { capture: true });
114
+ };
115
+ }, []);
116
+ }
@@ -0,0 +1 @@
1
+ export { SearchButton } from "./SearchButton";
@@ -0,0 +1 @@
1
+ export { SearchButton } from "./SearchButton";
@@ -0,0 +1,19 @@
1
+ import {css} from '@linaria/core';
2
+
3
+ type StyleObject = Record<string, string>;
4
+ type StyleFunction = (strings: TemplateStringsArray, ...values: any[]) => string;
5
+
6
+ export function useStyle<T extends StyleObject>(component: { styles: T }) {
7
+ const styled = {} as Record<keyof T, StyleFunction>;
8
+
9
+ for (const key of Object.keys(component.styles)) {
10
+ styled[key as keyof T] = (strings: TemplateStringsArray, ...values: any[]) => {
11
+ const customStyles = css`
12
+ ${strings.reduce((result, str, i) => result + str + (values[i] || ''), '')}
13
+ `;
14
+ return `${component.styles[key]} ${customStyles}`;
15
+ };
16
+ }
17
+
18
+ return styled;
19
+ }