@xyd-js/components 0.1.0-xyd.11 → 0.1.0-xyd.13

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 (256) 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 +16 -0
  6. package/TODO.md +1 -0
  7. package/content.ts +0 -2
  8. package/dist/CTABanner-BD4wweO5.js +2 -0
  9. package/dist/CTABanner-BD4wweO5.js.map +1 -0
  10. package/dist/CTABanner-DLG0_gv8.js +2 -0
  11. package/dist/CTABanner-DLG0_gv8.js.map +1 -0
  12. package/dist/CTABanner-DpPtA-FL.js +2 -0
  13. package/dist/CTABanner-DpPtA-FL.js.map +1 -0
  14. package/dist/CodeSample--qfqZ1hL.js +2 -0
  15. package/dist/CodeSample--qfqZ1hL.js.map +1 -0
  16. package/dist/CodeSample-CqFaFwwz.js +2 -0
  17. package/dist/CodeSample-CqFaFwwz.js.map +1 -0
  18. package/dist/CodeSample-GbqwRbcO.js +2 -0
  19. package/dist/CodeSample-GbqwRbcO.js.map +1 -0
  20. package/dist/HomeView-BZdY0g_7.js +2 -0
  21. package/dist/{HomeView-DHdqouwJ.js.map → HomeView-BZdY0g_7.js.map} +1 -1
  22. package/dist/HomeView-C_mEMzjV.js +2 -0
  23. package/dist/{HomeView-TDx2tcP_.js.map → HomeView-C_mEMzjV.js.map} +1 -1
  24. package/dist/HomeView-RATm-3zT.js +2 -0
  25. package/dist/HomeView-RATm-3zT.js.map +1 -0
  26. package/dist/Icon-BkXdTctK.js +2 -0
  27. package/dist/Icon-BkXdTctK.js.map +1 -0
  28. package/dist/Icon-BoKcRZAF.js +2 -0
  29. package/dist/Icon-BoKcRZAF.js.map +1 -0
  30. package/dist/Icon-CouPZRkJ.js +2 -0
  31. package/dist/Icon-CouPZRkJ.js.map +1 -0
  32. package/dist/Text-B-E3eaWW.js +2 -0
  33. package/dist/Text-B-E3eaWW.js.map +1 -0
  34. package/dist/Text-B5Ba_pci.js +2 -0
  35. package/dist/Text-B5Ba_pci.js.map +1 -0
  36. package/dist/Text-QH4jjPUM.js +2 -0
  37. package/dist/Text-QH4jjPUM.js.map +1 -0
  38. package/dist/Update-BlhP2VFR.js +2 -0
  39. package/dist/Update-BlhP2VFR.js.map +1 -0
  40. package/dist/Update-CMM38Snc.js +2 -0
  41. package/dist/Update-CMM38Snc.js.map +1 -0
  42. package/dist/Update-D5e_yqty.js +2 -0
  43. package/dist/Update-D5e_yqty.js.map +1 -0
  44. package/dist/VideoGuide-C5aW4OXW.js +2 -0
  45. package/dist/VideoGuide-C5aW4OXW.js.map +1 -0
  46. package/dist/VideoGuide-CoQXlHjQ.js +2 -0
  47. package/dist/VideoGuide-CoQXlHjQ.js.map +1 -0
  48. package/dist/VideoGuide-CwkedH8b.js +2 -0
  49. package/dist/VideoGuide-CwkedH8b.js.map +1 -0
  50. package/dist/_rollupPluginBabelHelpers-9wcO9jN6.js +4 -0
  51. package/dist/_rollupPluginBabelHelpers-9wcO9jN6.js.map +1 -0
  52. package/dist/_rollupPluginBabelHelpers-CiqSP2w-.js +4 -0
  53. package/dist/_rollupPluginBabelHelpers-CiqSP2w-.js.map +1 -0
  54. package/dist/_rollupPluginBabelHelpers-DmvUE1MU.js +4 -0
  55. package/dist/_rollupPluginBabelHelpers-DmvUE1MU.js.map +1 -0
  56. package/dist/brand.js +1 -1
  57. package/dist/brand.js.map +1 -1
  58. package/dist/coder/themes/cosmo-light.js.map +1 -1
  59. package/dist/coder.d.ts +32 -10
  60. package/dist/coder.js +1 -1
  61. package/dist/coder.js.map +1 -1
  62. package/dist/content.d.ts +264 -201
  63. package/dist/content.js +1 -1
  64. package/dist/content.js.map +1 -1
  65. package/dist/index.css +260 -210
  66. package/dist/layouts.d.ts +20 -21
  67. package/dist/layouts.js +1 -1
  68. package/dist/layouts.js.map +1 -1
  69. package/dist/pages.js +1 -1
  70. package/dist/pages.js.map +1 -1
  71. package/dist/system.d.ts +10 -0
  72. package/dist/system.js +2 -0
  73. package/dist/system.js.map +1 -0
  74. package/dist/tslib.es6-Bb9zBh0L.js +2 -0
  75. package/dist/{tslib.es6-BI9zka_a.js.map → tslib.es6-Bb9zBh0L.js.map} +1 -1
  76. package/dist/tslib.es6-Bd9lzVn6.js +2 -0
  77. package/dist/{tslib.es6-sxmRJynD.js.map → tslib.es6-Bd9lzVn6.js.map} +1 -1
  78. package/dist/tslib.es6-DwnOrHRg.js +2 -0
  79. package/dist/tslib.es6-DwnOrHRg.js.map +1 -0
  80. package/dist/views.js +1 -1
  81. package/dist/writer.d.ts +409 -77
  82. package/dist/writer.js +1 -1
  83. package/dist/writer.js.map +1 -1
  84. package/docs/.nojekyll +1 -0
  85. package/docs/assets/hierarchy.js +1 -0
  86. package/docs/assets/highlight.css +22 -0
  87. package/docs/assets/icons.js +18 -0
  88. package/docs/assets/icons.svg +1 -0
  89. package/docs/assets/main.js +60 -0
  90. package/docs/assets/navigation.js +1 -0
  91. package/docs/assets/search.js +1 -0
  92. package/docs/assets/style.css +1640 -0
  93. package/docs/functions/GuideCard.html +6 -0
  94. package/docs/hierarchy.html +1 -0
  95. package/docs/index.html +2 -0
  96. package/docs/interfaces/GuideCardProps.html +18 -0
  97. package/docs/modules.html +1 -0
  98. package/index.ts +0 -1
  99. package/package.json +10 -6
  100. package/project.json +677 -0
  101. package/rollup.config.js +30 -20
  102. package/src/brand/Button/Button.styles.tsx +0 -3
  103. package/src/brand/CTABanner/CTABanner.styles.tsx +2 -4
  104. package/src/brand/Footer/Footer.styles.tsx +0 -3
  105. package/src/coder/Code/Code.styles.tsx +132 -33
  106. package/src/coder/Code/Code.tsx +129 -38
  107. package/src/coder/Code/CodeLoader.tsx +3 -3
  108. package/src/coder/Code/annotations.tsx +28 -8
  109. package/src/coder/Code/highlight.ts +38 -0
  110. package/src/coder/Code/index.ts +2 -1
  111. package/src/coder/CodeCopy/CodeCopy.styles.tsx +13 -11
  112. package/src/coder/CodeCopy/CodeCopy.tsx +5 -3
  113. package/src/coder/CodeSample/CodeSample.tsx +83 -27
  114. package/src/coder/CodeTabs/CodeTabs.styles.tsx +111 -94
  115. package/src/coder/CodeTabs/CodeTabs.tsx +69 -51
  116. package/src/coder/CodeTheme/CodeTheme.tsx +89 -49
  117. package/src/coder/CodeTheme/index.ts +0 -1
  118. package/src/coder/CoderProvider.tsx +26 -0
  119. package/src/coder/index.ts +8 -4
  120. package/src/content/ContentDecoator.styles.tsx +113 -0
  121. package/src/content/ContentDecorator.tsx +17 -0
  122. package/src/content/GridDecorator.styles.tsx +67 -0
  123. package/src/content/GridDecorator.tsx +21 -0
  124. package/src/content/ReactContent.tsx +575 -0
  125. package/src/content/index.ts +10 -2
  126. package/src/icons/index.ts +0 -0
  127. package/src/kit/Loader/Loader.styles.tsx +53 -0
  128. package/src/kit/Loader/Loader.tsx +22 -0
  129. package/src/kit/index.ts +1 -0
  130. package/src/layouts/LayoutPrimary/LayoutPrimary.styles.tsx +270 -306
  131. package/src/layouts/LayoutPrimary/LayoutPrimary.tsx +171 -91
  132. package/src/layouts/LayoutPrimary/index.ts +0 -2
  133. package/src/layouts/index.ts +0 -7
  134. package/src/system/SearchButton/SearchButton.styles.tsx +86 -0
  135. package/src/system/SearchButton/SearchButton.tsx +116 -0
  136. package/src/system/SearchButton/index.ts +1 -0
  137. package/src/system/index.ts +1 -0
  138. package/src/writer/Anchor/Anchor.styles.tsx +11 -0
  139. package/src/{content → writer}/Anchor/Anchor.tsx +20 -22
  140. package/src/writer/Anchor/index.tsx +1 -0
  141. package/src/writer/Badge/Badge.styles.tsx +37 -27
  142. package/src/writer/Badge/Badge.tsx +34 -48
  143. package/src/writer/Banner/Banner.styles.tsx +91 -0
  144. package/src/writer/Banner/Banner.tsx +70 -0
  145. package/src/writer/Banner/index.ts +1 -0
  146. package/src/writer/Blockquote/Blockquote.styles.tsx +6 -4
  147. package/src/writer/Blockquote/Blockquote.tsx +5 -2
  148. package/src/writer/Breadcrumbs/Breadcrumbs.styles.ts +25 -25
  149. package/src/writer/Breadcrumbs/Breadcrumbs.tsx +18 -12
  150. package/src/writer/Button/Button.styles.tsx +137 -0
  151. package/src/writer/Button/Button.tsx +75 -0
  152. package/src/writer/Button/index.ts +2 -0
  153. package/src/writer/Callout/Callout.styles.tsx +35 -42
  154. package/src/writer/Callout/Callout.tsx +30 -15
  155. package/src/writer/Card/Card.styles.tsx +47 -0
  156. package/src/writer/Card/Card.tsx +69 -0
  157. package/src/writer/Card/index.ts +1 -0
  158. package/src/writer/Code/Code.styles.tsx +12 -11
  159. package/src/writer/Code/Code.tsx +6 -3
  160. package/src/writer/ColorSchemeButton/ColorSchemeButton.tsx +172 -0
  161. package/src/writer/ColorSchemeButton/index.ts +1 -0
  162. package/src/writer/Details/Details.styles.tsx +87 -98
  163. package/src/writer/Details/Details.tsx +65 -44
  164. package/src/writer/Example/index.tsx +5 -0
  165. package/src/writer/GuideCard/GuideCard.styles.tsx +100 -103
  166. package/src/writer/GuideCard/GuideCard.tsx +72 -37
  167. package/src/writer/Heading/Heading.styles.tsx +76 -60
  168. package/src/writer/Heading/Heading.tsx +92 -22
  169. package/src/writer/Hr/Hr.styles.tsx +3 -1
  170. package/src/writer/Hr/Hr.tsx +2 -5
  171. package/src/writer/Icon/Icon.tsx +48 -0
  172. package/src/writer/Icon/index.ts +1 -0
  173. package/src/writer/Image/Image.styles.tsx +9 -0
  174. package/src/writer/Image/Image.tsx +19 -0
  175. package/src/writer/Image/index.ts +1 -0
  176. package/src/writer/List/List.styles.tsx +47 -0
  177. package/src/writer/List/List.tsx +29 -0
  178. package/src/writer/List/index.ts +4 -0
  179. package/src/writer/NavLinks/NavLinks.styles.ts +26 -26
  180. package/src/writer/NavLinks/NavLinks.tsx +65 -18
  181. package/src/writer/Pre/Pre.styles.tsx +8 -6
  182. package/src/writer/Pre/Pre.tsx +3 -2
  183. package/src/writer/Steps/Steps.styles.tsx +27 -24
  184. package/src/writer/Steps/Steps.tsx +38 -8
  185. package/src/writer/Table/Table.styles.tsx +65 -34
  186. package/src/writer/Table/Table.tsx +121 -11
  187. package/src/writer/Table/index.ts +0 -11
  188. package/src/writer/Tabs/Tabs.styles.tsx +51 -55
  189. package/src/writer/Tabs/Tabs.tsx +30 -23
  190. package/src/writer/Text/Text.styles.tsx +66 -0
  191. package/src/writer/Text/Text.tsx +79 -0
  192. package/src/writer/Text/index.ts +3 -0
  193. package/src/writer/TocCard/TocCard.module.css +44 -0
  194. package/src/writer/TocCard/TocCard.tsx +42 -0
  195. package/src/writer/TocCard/index.ts +3 -0
  196. package/src/writer/UnderlineNav/Tabs.tsx +51 -0
  197. package/src/writer/UnderlineNav/TabsPrimary.styles.tsx +184 -0
  198. package/src/writer/UnderlineNav/TabsPrimary.tsx +209 -0
  199. package/src/writer/UnderlineNav/TabsSecondary.styles.tsx +77 -0
  200. package/src/writer/UnderlineNav/TabsSecondary.tsx +171 -0
  201. package/src/writer/UnderlineNav/UnderlineNav.styles.tsx +165 -31
  202. package/src/writer/UnderlineNav/UnderlineNav.tsx +257 -22
  203. package/src/writer/UnderlineNav/index.ts +2 -1
  204. package/src/writer/UnderlineNav/useValueChange.ts +60 -0
  205. package/src/writer/Update/Update.styles.tsx +33 -0
  206. package/src/writer/Update/Update.tsx +37 -0
  207. package/src/writer/Update/index.ts +1 -0
  208. package/src/writer/VideoGuide/VideoGuide.module.css +105 -0
  209. package/src/writer/VideoGuide/VideoGuide.tsx +75 -0
  210. package/src/writer/VideoGuide/index.ts +1 -0
  211. package/src/writer/index.ts +23 -1
  212. package/tsconfig.json +9 -3
  213. package/types.d.ts +50 -0
  214. package/writer.ts +1 -1
  215. package/dist/CTABanner-BLDHbq5h.js +0 -2
  216. package/dist/CTABanner-BLDHbq5h.js.map +0 -1
  217. package/dist/CTABanner-n3vc4xW5.js +0 -2
  218. package/dist/CTABanner-n3vc4xW5.js.map +0 -1
  219. package/dist/CodeSample-CVki5fdQ.js +0 -2
  220. package/dist/CodeSample-CVki5fdQ.js.map +0 -1
  221. package/dist/CodeSample-Dkob5gWa.js +0 -2
  222. package/dist/CodeSample-Dkob5gWa.js.map +0 -1
  223. package/dist/HomeView-DHdqouwJ.js +0 -2
  224. package/dist/HomeView-TDx2tcP_.js +0 -2
  225. package/dist/UnderlineNav-9lJPvnIp.js +0 -2
  226. package/dist/UnderlineNav-9lJPvnIp.js.map +0 -1
  227. package/dist/UnderlineNav-VqB7jDQD.js +0 -2
  228. package/dist/UnderlineNav-VqB7jDQD.js.map +0 -1
  229. package/dist/_rollupPluginBabelHelpers-C8nLsqZ7.js +0 -2
  230. package/dist/_rollupPluginBabelHelpers-C8nLsqZ7.js.map +0 -1
  231. package/dist/_rollupPluginBabelHelpers-CrdNG0jb.js +0 -2
  232. package/dist/_rollupPluginBabelHelpers-CrdNG0jb.js.map +0 -1
  233. package/dist/index-TkBHKzGT.js +0 -2
  234. package/dist/index-TkBHKzGT.js.map +0 -1
  235. package/dist/index-YH6Q3iH2.js +0 -2
  236. package/dist/index-YH6Q3iH2.js.map +0 -1
  237. package/dist/tslib.es6-BI9zka_a.js +0 -2
  238. package/dist/tslib.es6-sxmRJynD.js +0 -2
  239. package/src/content/Anchor/Anchor.styles.tsx +0 -5
  240. package/src/content/Anchor/index.tsx +0 -3
  241. package/src/content/Content/Content.styles.tsx +0 -9
  242. package/src/content/Content/Content.tsx +0 -13
  243. package/src/content/Content/index.tsx +0 -3
  244. package/src/content/Content.tsx +0 -179
  245. package/src/content/Subtitle/Subtitle.styles.ts +0 -8
  246. package/src/content/Subtitle/Subtitle.tsx +0 -12
  247. package/src/content/Subtitle/index.tsx +0 -3
  248. package/src/layouts/Layout.styles.tsx +0 -155
  249. package/src/layouts/Layout.tsx +0 -119
  250. package/src/ui/Loader/Loader.styles.tsx +0 -54
  251. package/src/ui/Loader/Loader.tsx +0 -26
  252. package/src/ui/index.ts +0 -1
  253. package/src/writer/Icon/index.tsx +0 -355
  254. package/src/writer/Table/TableV2.styles.tsx +0 -117
  255. package/src/writer/Table/TableV2.tsx +0 -83
  256. /package/src/{ui → kit}/TODO.md +0 -0
@@ -1,155 +1,235 @@
1
- import React, {useEffect, useState} from "react"
1
+ import * as React from 'react'
2
+ import { useContext, useEffect, useRef, useState } from "react"
3
+
4
+ import { PageLayout } from '@xyd-js/core';
2
5
 
3
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;
20
56
 
21
- return <div className={cn.LayoutPrimaryHost}>
22
- <header className={`
23
- ${cn.LayoutPrimaryHeader}
24
- ${props.subheader && cn.LayoutPrimaryHeaderSub}
25
- ${hideMainHeader && cn.LayoutPrimaryHeaderHideMain}
26
- `}>
27
- <div className={cn.LayoutPrimaryHeaderContent}>
57
+ subheader?: React.ReactNode;
58
+ }
59
+ LayoutPrimary.Header = function LayoutPrimaryHeader(props: LayoutPrimaryHeaderProps) {
60
+ const { isMobileNavOpen, setIsMobileNavOpen } = useContext(LayoutPrimaryContext)
61
+
62
+ return <>
63
+ <header part="header">
64
+ <div part="header-content">
28
65
  {props.header}
29
66
  <button
30
- className={cn.LayoutPrimaryHamburgerButton}
31
- onClick={() => setIsMobileNavOpen(!isMobileNavOpen)}
67
+ part="hamburger-button"
32
68
  aria-label="Toggle navigation menu"
69
+ onClick={() => setIsMobileNavOpen(!isMobileNavOpen)}
33
70
  >
34
- <div className={cn.LayoutPrimaryHamburgerIcon}>
35
- <span
36
- className={`${cn.LayoutPrimaryHamburgerLine} ${isMobileNavOpen ? cn.LayoutPrimaryHamburgerLineOpen : ''}`}/>
37
- <span
38
- className={`${cn.LayoutPrimaryHamburgerLine} ${isMobileNavOpen ? cn.LayoutPrimaryHamburgerLineOpen : ''}`}/>
39
- <span
40
- className={`${cn.LayoutPrimaryHamburgerLine} ${isMobileNavOpen ? cn.LayoutPrimaryHamburgerLineOpen : ''}`}/>
71
+ <div part="hamburger-icon">
72
+ <$HamburgerLine active={isMobileNavOpen} />
73
+ <$HamburgerLine active={isMobileNavOpen} />
74
+ <$HamburgerLine active={isMobileNavOpen} />
41
75
  </div>
42
76
  </button>
43
77
  </div>
78
+
44
79
  {props.subheader}
45
80
  </header>
81
+ </>
82
+ }
46
83
 
47
- {/* 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 <>
48
90
  <div
49
- className={`${cn.LayoutPrimaryOverlay} ${isMobileNavOpen ? cn.LayoutPrimaryOverlayVisible : ''}`}
91
+ part="mobile-overlay"
92
+ data-active={isMobileNavOpen}
50
93
  onClick={() => setIsMobileNavOpen(false)}
51
94
  />
52
- <aside className={`
53
- ${cn.LayoutPrimaryMobileSidebar}
54
- ${isMobileNavOpen ? cn.LayoutPrimaryMobileSidebarOpen : ''}
55
- `}>
56
- <div className={cn.LayoutPrimarySidebarContent}>
95
+ <aside
96
+ part="mobile-sidebar"
97
+ data-active={isMobileNavOpen}
98
+ >
99
+ <div part="mobile-sidebar-aside">
57
100
  {props.aside}
58
101
  </div>
59
102
  <button
60
- className={cn.LayoutPrimaryCloseButton}
61
- onClick={() => setIsMobileNavOpen(false)}
103
+ part="mobile-sidebar-close-button"
62
104
  aria-label="Close navigation menu"
105
+ onClick={() => setIsMobileNavOpen(false)}
63
106
  >
64
- <div className={cn.LayoutPrimaryCloseIcon}/>
107
+ <div part="mobile-sidebar-close-icon" />
65
108
  </button>
66
109
  </aside>
110
+ </>
111
+ }
67
112
 
68
- <main className={`
69
- ${cn.LayoutPrimaryMain}
70
- ${!hideMainHeader && props.subheader && cn.LayoutPrimaryMainSub}
71
- `}>
72
- {/* Desktop Static Sidebar */}
73
- <aside className={cn.LayoutPrimaryStaticSidebar}>
74
- {props.aside}
75
- </aside>
76
-
77
- <div className={cn.LayoutPrimaryPageHost}>
78
- <div className={cn.LayoutPrimaryPageScroll}>
79
- <div className={`
80
- ${cn.LayoutPrimaryPageContainer}
81
- ${props.layoutSize == "large" && cn.LayoutPrimaryPageContainerLarge}
82
- `}>
83
- <div className={cn.LayoutPrimaryPageArticleContainer}>
84
- <article className={cn.LayoutPrimaryArticleHost}>
85
- <section className={cn.LayoutPrimaryArticleContent}>
86
- {props.content}
87
- </section>
88
- </article>
89
- {props.contentNav && <nav className={cn.LayoutPrimaryArticleNav}>
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">
90
132
  {props.contentNav}
91
- </nav>}
92
- </div>
133
+ </nav>
134
+ }
93
135
  </div>
94
136
  </div>
95
137
  </div>
96
- </main>
97
- </div>
138
+ </div>
139
+ </>
140
+ }
141
+
142
+ function $HamburgerLine({ active }: { active: boolean }) {
143
+ return <span
144
+ part="hamburger-line"
145
+ data-active={active}
146
+ />
98
147
  }
99
148
 
149
+ const SCROLL_DOWN_TRIGGER_THRESHOLD = 200;
150
+ const SCROLL_UP_TRIGGER_THRESHOLD = 100;
151
+
100
152
  // TODO: move to `xyd-foo` or somewhere else
101
- function useSubHeader() {
153
+ // TODO better solution than `key`
154
+ function useSubHeader(ref: React.RefObject<HTMLDivElement | Window | null> | null, key?: any) {
102
155
  const [hideMainHeader, setHideMainHeader] = useState(false)
103
- const [scrollTop, setScrollTop] = useState(0)
104
- 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
+ }
105
170
 
106
171
  useEffect(() => {
107
- if (scrollTop === controlScrollPos) {
172
+ reset()
173
+ }, [key])
174
+
175
+ function onScroll(e: Event) {
176
+ if (!(e.target instanceof HTMLElement)) {
108
177
  return
109
178
  }
110
179
 
111
- const checkpoint = parseInt(cn.globalHeaderHeight, 10) / 2
112
- const diff = scrollTop - controlScrollPos
113
- const reversePosDiff = Math.abs(scrollTop - controlScrollPos)
180
+ const currentScrollTop = e.target.scrollTop
114
181
 
115
- if (diff > checkpoint) {
116
- setHideMainHeader(true)
117
- } else if (reversePosDiff > checkpoint) {
182
+ // Always show header when near the top of the page
183
+ if (currentScrollTop < SCROLL_UP_TRIGGER_THRESHOLD) {
118
184
  setHideMainHeader(false)
185
+ setScrollThreshold(0)
186
+ setLastScrollTop(currentScrollTop)
187
+ setIsScrolling(false)
188
+ return
119
189
  }
120
- }, [
121
- scrollTop,
122
- controlScrollPos,
123
- ]);
124
190
 
125
- function onScroll(e: Event) {
126
- if (!(e.target instanceof HTMLElement)) {
127
- 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)
128
199
  }
129
200
 
130
- const scroll = e.target?.scrollTop
131
- setScrollTop(scroll)
132
- }
201
+ // Calculate total scroll distance from start position
202
+ const totalScrollDistance = Math.abs(currentScrollTop - scrollStartPosition)
133
203
 
134
- function onScrollFinish(e: Event) {
135
- if (!(e.target instanceof HTMLElement)) {
136
- 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)
137
217
  }
138
218
 
139
- setControlScrollPos(e.target?.scrollTop)
219
+ setLastScrollTop(currentScrollTop)
140
220
  }
141
221
 
142
- // TODO: by ref?
143
- // TODO: MOVE SOMEWHERE ELSE BECAUSE IT DECREASE PERFORMANCE (RERENDER)
144
222
  useEffect(() => {
145
- document.querySelector(`.${cn.LayoutPrimaryPageScroll}`)?.addEventListener("scroll", onScroll)
146
- document.querySelector(`.${cn.LayoutPrimaryPageScroll}`)?.addEventListener("scrollend", onScrollFinish)
223
+ if (!ref?.current) {
224
+ return
225
+ }
226
+
227
+ ref.current.addEventListener("scroll", onScroll)
147
228
 
148
229
  return () => {
149
- document.querySelector(`.${cn.LayoutPrimaryPageScroll}`)?.removeEventListener("scroll", onScroll)
150
- document.querySelector(`.${cn.LayoutPrimaryPageScroll}`)?.removeEventListener("scrollend", onScrollFinish)
230
+ ref.current?.removeEventListener("scroll", onScroll)
151
231
  }
152
- }, []);
232
+ }, [ref, key, lastScrollTop, scrollDirection, scrollThreshold, scrollStartPosition]);
153
233
 
154
234
  return {
155
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,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,11 @@
1
+ import {css} from "@linaria/core";
2
+
3
+ export const AnchorHost = css`
4
+ @layer defaults {
5
+ color: var(--xyd-anchor-color);
6
+
7
+ &:hover {
8
+ color: var(--xyd-anchor-color--hover);
9
+ }
10
+ }
11
+ `;
@@ -1,53 +1,51 @@
1
- import React, {forwardRef} from 'react'
2
- import type {ComponentProps, ReactElement} from 'react'
1
+ import React, { forwardRef } from 'react'
2
+ import type { ComponentProps, ReactElement } from 'react'
3
+
3
4
  import * as cn from "./Anchor.styles";
4
5
 
5
6
  export type AnchorProps = Omit<ComponentProps<'a'>, 'ref'> & {
6
7
  newWindow?: boolean
8
+ as?: React.ElementType
7
9
  }
8
10
 
9
- // TODO: where react-router?
10
-
11
11
  export const Anchor = forwardRef<HTMLAnchorElement, AnchorProps>(function (
12
- {href = '', children, newWindow},
12
+ { href = '', children, newWindow, as, ...props },
13
13
  // ref is used in <NavbarMenu />
14
14
  forwardedRef
15
15
  ): ReactElement {
16
+ const Link = as || $Anchor
17
+
16
18
  if (newWindow) {
17
19
  return (
18
- <a
20
+ <Link
19
21
  ref={forwardedRef}
20
22
  href={href}
21
23
  target="_blank"
22
24
  rel="noreferrer"
23
25
  className={cn.AnchorHost}
26
+ {...props}
24
27
  >
25
28
  {children}
26
- </a>
27
- )
28
- }
29
-
30
- if (!href) {
31
- return (
32
- <a
33
- ref={forwardedRef}
34
- href={href}
35
- className={cn.AnchorHost}
36
- >
37
- {children}
38
- </a>
29
+ </Link>
39
30
  )
40
31
  }
41
32
 
42
33
  return (
43
- <a
34
+ <Link
44
35
  ref={forwardedRef}
45
- href={href}
46
36
  className={cn.AnchorHost}
37
+ href={href || undefined}
38
+ {...props}
47
39
  >
48
40
  {children}
49
- </a>
41
+ </Link>
50
42
  )
51
43
  })
52
44
 
53
45
  Anchor.displayName = 'Anchor'
46
+
47
+ function $Anchor({ children, ...rest }) {
48
+ return <a {...rest}>
49
+ {children}
50
+ </a>
51
+ }
@@ -0,0 +1 @@
1
+ export {Anchor} from "./Anchor";