@xyd-js/components 0.1.0-build.168

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 (314) 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 +1369 -0
  6. package/LICENSE +21 -0
  7. package/README.md +3 -0
  8. package/TODO.md +1 -0
  9. package/coder.ts +1 -0
  10. package/content.ts +1 -0
  11. package/dist/Button-BLA2ghHZ.js +2 -0
  12. package/dist/Button-BLA2ghHZ.js.map +1 -0
  13. package/dist/Button-BTJ2hIal.js +2 -0
  14. package/dist/Button-BTJ2hIal.js.map +1 -0
  15. package/dist/Button-r4BCrEjy.js +2 -0
  16. package/dist/Button-r4BCrEjy.js.map +1 -0
  17. package/dist/CodeSample-BZ5tvyWY.js +2 -0
  18. package/dist/CodeSample-BZ5tvyWY.js.map +1 -0
  19. package/dist/CodeSample-BqXDbWdi.js +2 -0
  20. package/dist/CodeSample-BqXDbWdi.js.map +1 -0
  21. package/dist/CodeSample-Cqv86IdN.js +2 -0
  22. package/dist/CodeSample-Cqv86IdN.js.map +1 -0
  23. package/dist/Icon--77MqplU.js +2 -0
  24. package/dist/Icon--77MqplU.js.map +1 -0
  25. package/dist/Icon-DbNmvK_Q.js +2 -0
  26. package/dist/Icon-DbNmvK_Q.js.map +1 -0
  27. package/dist/Icon-uVIU1LW6.js +2 -0
  28. package/dist/Icon-uVIU1LW6.js.map +1 -0
  29. package/dist/PageFirstSlide-BDNmCTiJ.js +2 -0
  30. package/dist/PageFirstSlide-BDNmCTiJ.js.map +1 -0
  31. package/dist/PageFirstSlide-BpZ42bEU.js +2 -0
  32. package/dist/PageFirstSlide-BpZ42bEU.js.map +1 -0
  33. package/dist/PageFirstSlide-CqxiyK57.js +2 -0
  34. package/dist/PageFirstSlide-CqxiyK57.js.map +1 -0
  35. package/dist/TabsAnalytics-B_JYpawG.js +2 -0
  36. package/dist/TabsAnalytics-B_JYpawG.js.map +1 -0
  37. package/dist/TabsAnalytics-DAOfTZgv.js +2 -0
  38. package/dist/TabsAnalytics-DAOfTZgv.js.map +1 -0
  39. package/dist/TabsAnalytics-Dhyadlbu.js +2 -0
  40. package/dist/TabsAnalytics-Dhyadlbu.js.map +1 -0
  41. package/dist/Update-53fEhmjh.js +2 -0
  42. package/dist/Update-53fEhmjh.js.map +1 -0
  43. package/dist/Update-CFi6uapq.js +2 -0
  44. package/dist/Update-CFi6uapq.js.map +1 -0
  45. package/dist/Update-CiMIOgZi.js +2 -0
  46. package/dist/Update-CiMIOgZi.js.map +1 -0
  47. package/dist/VideoGuide-C0K9fFar.js +2 -0
  48. package/dist/VideoGuide-C0K9fFar.js.map +1 -0
  49. package/dist/VideoGuide-CJYkuLst.js +2 -0
  50. package/dist/VideoGuide-CJYkuLst.js.map +1 -0
  51. package/dist/VideoGuide-DBY-EyxG.js +2 -0
  52. package/dist/VideoGuide-DBY-EyxG.js.map +1 -0
  53. package/dist/_rollupPluginBabelHelpers-CvhQFv1t.js +4 -0
  54. package/dist/_rollupPluginBabelHelpers-CvhQFv1t.js.map +1 -0
  55. package/dist/_rollupPluginBabelHelpers-DSwDY1Dm.js +4 -0
  56. package/dist/_rollupPluginBabelHelpers-DSwDY1Dm.js.map +1 -0
  57. package/dist/_rollupPluginBabelHelpers-Dc-ocx4G.js +4 -0
  58. package/dist/_rollupPluginBabelHelpers-Dc-ocx4G.js.map +1 -0
  59. package/dist/coder/themes/classic.css +57 -0
  60. package/dist/coder/themes/classic.d.ts +96 -0
  61. package/dist/coder/themes/classic.js +2 -0
  62. package/dist/coder/themes/classic.js.map +1 -0
  63. package/dist/coder/themes/cosmo.css +64 -0
  64. package/dist/coder/themes/cosmo.d.ts +96 -0
  65. package/dist/coder/themes/cosmo.js +2 -0
  66. package/dist/coder/themes/cosmo.js.map +1 -0
  67. package/dist/coder.d.ts +94 -0
  68. package/dist/coder.js +2 -0
  69. package/dist/coder.js.map +1 -0
  70. package/dist/content.d.ts +411 -0
  71. package/dist/content.js +2 -0
  72. package/dist/content.js.map +1 -0
  73. package/dist/index.css +282 -0
  74. package/dist/index.d.ts +2 -0
  75. package/dist/index.js +2 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/layouts.d.ts +33 -0
  78. package/dist/layouts.js +2 -0
  79. package/dist/layouts.js.map +1 -0
  80. package/dist/pages.d.ts +176 -0
  81. package/dist/pages.js +2 -0
  82. package/dist/pages.js.map +1 -0
  83. package/dist/system.d.ts +45 -0
  84. package/dist/system.js +2 -0
  85. package/dist/system.js.map +1 -0
  86. package/dist/useUXClick-DK3cTAMR.js +2 -0
  87. package/dist/useUXClick-DK3cTAMR.js.map +1 -0
  88. package/dist/useUXClick-DO6qBcRy.js +2 -0
  89. package/dist/useUXClick-DO6qBcRy.js.map +1 -0
  90. package/dist/useUXClick-NwpsiuK9.js +2 -0
  91. package/dist/useUXClick-NwpsiuK9.js.map +1 -0
  92. package/dist/useUXEvents-CJtgGV4R.js +2 -0
  93. package/dist/useUXEvents-CJtgGV4R.js.map +1 -0
  94. package/dist/useUXEvents-Cxgl7xb-.js +2 -0
  95. package/dist/useUXEvents-Cxgl7xb-.js.map +1 -0
  96. package/dist/useUXEvents-XqAGxoEj.js +2 -0
  97. package/dist/useUXEvents-XqAGxoEj.js.map +1 -0
  98. package/dist/useUXScrollDepth-3rk3Z95r.js +2 -0
  99. package/dist/useUXScrollDepth-3rk3Z95r.js.map +1 -0
  100. package/dist/useUXScrollDepth-BwK-XOBg.js +2 -0
  101. package/dist/useUXScrollDepth-BwK-XOBg.js.map +1 -0
  102. package/dist/useUXScrollDepth-DKre7PBz.js +2 -0
  103. package/dist/useUXScrollDepth-DKre7PBz.js.map +1 -0
  104. package/dist/uxsdk.d.ts +53 -0
  105. package/dist/uxsdk.js +2 -0
  106. package/dist/uxsdk.js.map +1 -0
  107. package/dist/views.d.ts +18 -0
  108. package/dist/views.js +2 -0
  109. package/dist/views.js.map +1 -0
  110. package/dist/writer.d.ts +580 -0
  111. package/dist/writer.js +2 -0
  112. package/dist/writer.js.map +1 -0
  113. package/docs/.nojekyll +1 -0
  114. package/docs/assets/hierarchy.js +1 -0
  115. package/docs/assets/highlight.css +22 -0
  116. package/docs/assets/icons.js +18 -0
  117. package/docs/assets/icons.svg +1 -0
  118. package/docs/assets/main.js +60 -0
  119. package/docs/assets/navigation.js +1 -0
  120. package/docs/assets/search.js +1 -0
  121. package/docs/assets/style.css +1640 -0
  122. package/docs/functions/GuideCard.html +6 -0
  123. package/docs/hierarchy.html +1 -0
  124. package/docs/index.html +2 -0
  125. package/docs/interfaces/GuideCardProps.html +18 -0
  126. package/docs/modules.html +1 -0
  127. package/index.ts +0 -0
  128. package/layouts.ts +1 -0
  129. package/output.txt +13 -0
  130. package/package.json +81 -0
  131. package/pages.ts +1 -0
  132. package/postcss.config.cjs +5 -0
  133. package/rollup.config.js +195 -0
  134. package/src/coder/Code/Code.styles.tsx +151 -0
  135. package/src/coder/Code/Code.tsx +171 -0
  136. package/src/coder/Code/CodeLoader.tsx +10 -0
  137. package/src/coder/Code/annotations.tsx +51 -0
  138. package/src/coder/Code/highlight.ts +208 -0
  139. package/src/coder/Code/index.ts +16 -0
  140. package/src/coder/CodeCopy/CodeCopy.styles.tsx +21 -0
  141. package/src/coder/CodeCopy/CodeCopy.tsx +36 -0
  142. package/src/coder/CodeCopy/index.ts +7 -0
  143. package/src/coder/CodeSample/CodeSample.tsx +118 -0
  144. package/src/coder/CodeSample/CodeSampleAnalytics.tsx +112 -0
  145. package/src/coder/CodeSample/index.ts +11 -0
  146. package/src/coder/CodeSample/withLocalStored.tsx +50 -0
  147. package/src/coder/CodeTabs/CodeTabs.styles.tsx +126 -0
  148. package/src/coder/CodeTabs/CodeTabs.tsx +128 -0
  149. package/src/coder/CodeTabs/index.ts +6 -0
  150. package/src/coder/CodeTheme/CodeTheme.tsx +126 -0
  151. package/src/coder/CodeTheme/index.ts +7 -0
  152. package/src/coder/CoderProvider.tsx +26 -0
  153. package/src/coder/README.md +1 -0
  154. package/src/coder/hooks/highlight.ts +182 -0
  155. package/src/coder/index.ts +37 -0
  156. package/src/coder/themes/classic.css +57 -0
  157. package/src/coder/themes/classic.ts +270 -0
  158. package/src/coder/themes/cosmo.css +64 -0
  159. package/src/coder/themes/cosmo.ts +264 -0
  160. package/src/content/AppearanceDecorator.styles.tsx +11 -0
  161. package/src/content/ContentDecoator.styles.tsx +180 -0
  162. package/src/content/ContentDecorator.tsx +17 -0
  163. package/src/content/GridDecorator.styles.tsx +86 -0
  164. package/src/content/GridDecorator.tsx +23 -0
  165. package/src/content/ReactContent.tsx +671 -0
  166. package/src/content/TODO.md +1 -0
  167. package/src/content/index.ts +13 -0
  168. package/src/kit/Loader/Loader.styles.tsx +53 -0
  169. package/src/kit/Loader/Loader.tsx +22 -0
  170. package/src/kit/TODO.md +2 -0
  171. package/src/kit/index.ts +1 -0
  172. package/src/layouts/LayoutPrimary/LayoutPrimary.styles.tsx +325 -0
  173. package/src/layouts/LayoutPrimary/LayoutPrimary.tsx +252 -0
  174. package/src/layouts/LayoutPrimary/index.ts +3 -0
  175. package/src/layouts/index.ts +6 -0
  176. package/src/pages/PageBlogHome/PageBlogHome.styles.tsx +67 -0
  177. package/src/pages/PageBlogHome/PageBlogHome.tsx +64 -0
  178. package/src/pages/PageBlogHome/index.ts +3 -0
  179. package/src/pages/PageBlogHome/types.ts +35 -0
  180. package/src/pages/PageBlogPost/PageBlogPost.styles.tsx +4 -0
  181. package/src/pages/PageBlogPost/PageBlogPost.tsx +9 -0
  182. package/src/pages/PageBlogPost/index.ts +3 -0
  183. package/src/pages/PageFirstSlide/PageFirstSlide.styles.tsx +134 -0
  184. package/src/pages/PageFirstSlide/PageFirstSlide.tsx +56 -0
  185. package/src/pages/PageFirstSlide/index.ts +1 -0
  186. package/src/pages/PageFirstSlide/types.ts +67 -0
  187. package/src/pages/PageHome/PageHome.styles.tsx +51 -0
  188. package/src/pages/PageHome/PageHome.tsx +62 -0
  189. package/src/pages/PageHome/index.ts +3 -0
  190. package/src/pages/PageHome/types.ts +79 -0
  191. package/src/pages/index.ts +7 -0
  192. package/src/system/Baseline/Baseline.styles.tsx +128 -0
  193. package/src/system/Baseline/Baseline.tsx +40 -0
  194. package/src/system/Baseline/bun.svg +1 -0
  195. package/src/system/Baseline/check.svg +1 -0
  196. package/src/system/Baseline/index.ts +1 -0
  197. package/src/system/Baseline/logo.svg +1 -0
  198. package/src/system/Baseline/node.svg +7 -0
  199. package/src/system/Baseline/npm.svg +5 -0
  200. package/src/system/Baseline/pnpm.svg +1 -0
  201. package/src/system/Footer/Footer.styles.tsx +213 -0
  202. package/src/system/Footer/Footer.tsx +105 -0
  203. package/src/system/Footer/index.ts +1 -0
  204. package/src/system/SearchButton/SearchButton.styles.tsx +89 -0
  205. package/src/system/SearchButton/SearchButton.tsx +118 -0
  206. package/src/system/SearchButton/index.ts +1 -0
  207. package/src/system/index.ts +3 -0
  208. package/src/utils/useStyle.ts +19 -0
  209. package/src/uxsdk/const.ts +1 -0
  210. package/src/uxsdk/index.ts +21 -0
  211. package/src/uxsdk/useUXClick.ts +21 -0
  212. package/src/uxsdk/useUXEvents.ts +105 -0
  213. package/src/uxsdk/useUXScrollDepth.ts +49 -0
  214. package/src/uxsdk/useUXUnreachableElementTracker.ts +100 -0
  215. package/src/views/HomeView/HomeView.styles.tsx +37 -0
  216. package/src/views/HomeView/HomeView.tsx +34 -0
  217. package/src/views/HomeView/index.ts +3 -0
  218. package/src/writer/Anchor/Anchor.styles.tsx +26 -0
  219. package/src/writer/Anchor/Anchor.tsx +51 -0
  220. package/src/writer/Anchor/index.tsx +1 -0
  221. package/src/writer/Badge/Badge.styles.tsx +44 -0
  222. package/src/writer/Badge/Badge.tsx +47 -0
  223. package/src/writer/Badge/index.ts +7 -0
  224. package/src/writer/Banner/Banner.styles.tsx +111 -0
  225. package/src/writer/Banner/Banner.tsx +151 -0
  226. package/src/writer/Banner/index.ts +1 -0
  227. package/src/writer/Blockquote/Blockquote.styles.tsx +20 -0
  228. package/src/writer/Blockquote/Blockquote.tsx +38 -0
  229. package/src/writer/Blockquote/index.ts +7 -0
  230. package/src/writer/BlogCard/BlogCard.styles.tsx +4 -0
  231. package/src/writer/BlogCard/BlogCard.tsx +9 -0
  232. package/src/writer/BlogCard/index.ts +3 -0
  233. package/src/writer/Breadcrumbs/Breadcrumbs.styles.ts +24 -0
  234. package/src/writer/Breadcrumbs/Breadcrumbs.tsx +57 -0
  235. package/src/writer/Breadcrumbs/index.ts +7 -0
  236. package/src/writer/Button/Button.styles.tsx +149 -0
  237. package/src/writer/Button/Button.tsx +82 -0
  238. package/src/writer/Button/index.ts +2 -0
  239. package/src/writer/Callout/Callout.styles.tsx +102 -0
  240. package/src/writer/Callout/Callout.tsx +166 -0
  241. package/src/writer/Callout/index.tsx +3 -0
  242. package/src/writer/Card/Card.styles.tsx +110 -0
  243. package/src/writer/Card/Card.tsx +94 -0
  244. package/src/writer/Card/index.ts +1 -0
  245. package/src/writer/Code/Code.styles.tsx +16 -0
  246. package/src/writer/Code/Code.tsx +16 -0
  247. package/src/writer/Code/index.ts +3 -0
  248. package/src/writer/ColorSchemeButton/ColorSchemeButton.tsx +191 -0
  249. package/src/writer/ColorSchemeButton/index.ts +1 -0
  250. package/src/writer/Details/Details.styles.tsx +101 -0
  251. package/src/writer/Details/Details.tsx +168 -0
  252. package/src/writer/Details/DetailsProps.tsx +34 -0
  253. package/src/writer/Details/index.ts +6 -0
  254. package/src/writer/GuideCard/GuideCard.styles.tsx +129 -0
  255. package/src/writer/GuideCard/GuideCard.tsx +123 -0
  256. package/src/writer/GuideCard/index.ts +1 -0
  257. package/src/writer/Heading/Heading.styles.tsx +93 -0
  258. package/src/writer/Heading/Heading.tsx +123 -0
  259. package/src/writer/Heading/index.ts +7 -0
  260. package/src/writer/Hr/Hr.styles.tsx +7 -0
  261. package/src/writer/Hr/Hr.tsx +10 -0
  262. package/src/writer/Hr/index.ts +3 -0
  263. package/src/writer/Icon/Icon.styles.tsx +15 -0
  264. package/src/writer/Icon/Icon.tsx +99 -0
  265. package/src/writer/Icon/index.ts +1 -0
  266. package/src/writer/IconSocial/IconSocial.tsx +107 -0
  267. package/src/writer/IconSocial/index.ts +1 -0
  268. package/src/writer/Image/Image.styles.tsx +9 -0
  269. package/src/writer/Image/Image.tsx +35 -0
  270. package/src/writer/Image/index.ts +1 -0
  271. package/src/writer/List/List.styles.tsx +47 -0
  272. package/src/writer/List/List.tsx +29 -0
  273. package/src/writer/List/index.ts +4 -0
  274. package/src/writer/NavLinks/NavLinks.styles.ts +32 -0
  275. package/src/writer/NavLinks/NavLinks.tsx +95 -0
  276. package/src/writer/NavLinks/index.ts +7 -0
  277. package/src/writer/Pre/Pre.styles.tsx +13 -0
  278. package/src/writer/Pre/Pre.tsx +14 -0
  279. package/src/writer/Pre/index.ts +3 -0
  280. package/src/writer/README.md +1 -0
  281. package/src/writer/Steps/Steps.styles.tsx +91 -0
  282. package/src/writer/Steps/Steps.tsx +75 -0
  283. package/src/writer/Steps/index.ts +5 -0
  284. package/src/writer/Table/Table.styles.tsx +100 -0
  285. package/src/writer/Table/Table.tsx +158 -0
  286. package/src/writer/Table/index.ts +3 -0
  287. package/src/writer/Tabs/Tabs.tsx +67 -0
  288. package/src/writer/Tabs/TabsAnalytics.tsx +25 -0
  289. package/src/writer/Tabs/TabsPrimary.styles.tsx +187 -0
  290. package/src/writer/Tabs/TabsPrimary.tsx +215 -0
  291. package/src/writer/Tabs/TabsProps.tsx +13 -0
  292. package/src/writer/Tabs/TabsSecondary.styles.tsx +78 -0
  293. package/src/writer/Tabs/TabsSecondary.tsx +176 -0
  294. package/src/writer/Tabs/index.ts +2 -0
  295. package/src/writer/Tabs/useValueChange.ts +84 -0
  296. package/src/writer/Text/Text.styles.tsx +66 -0
  297. package/src/writer/Text/Text.tsx +79 -0
  298. package/src/writer/Text/index.ts +3 -0
  299. package/src/writer/TocCard/TocCard.module.css +44 -0
  300. package/src/writer/TocCard/TocCard.tsx +42 -0
  301. package/src/writer/TocCard/index.ts +3 -0
  302. package/src/writer/Update/Update.styles.tsx +33 -0
  303. package/src/writer/Update/Update.tsx +37 -0
  304. package/src/writer/Update/index.ts +1 -0
  305. package/src/writer/VideoGuide/VideoGuide.module.css +105 -0
  306. package/src/writer/VideoGuide/VideoGuide.tsx +75 -0
  307. package/src/writer/VideoGuide/index.ts +1 -0
  308. package/src/writer/index.ts +53 -0
  309. package/system.ts +1 -0
  310. package/tsconfig.json +46 -0
  311. package/types.d.ts +52 -0
  312. package/uxsdk.ts +1 -0
  313. package/views.ts +2 -0
  314. package/writer.ts +1 -0
@@ -0,0 +1,215 @@
1
+ import React, { useState, useRef, useEffect, createContext, useContext } from "react"
2
+ import { Tabs as RadixTabs } from "radix-ui"; // TODO: remove and use separation
3
+
4
+ import * as cn from "./TabsPrimary.styles"
5
+ import { useValueChange } from "./useValueChange";
6
+ import { useTabsAnalytics } from "./TabsAnalytics";
7
+
8
+ /**
9
+ * Context for managing the navigation direction in the TabsPrimary component
10
+ */
11
+ const TabsPrimaryContext = createContext<{
12
+ direction: 'forward' | 'backward'
13
+ }>({
14
+ direction: 'forward'
15
+ });
16
+
17
+ /**
18
+ * Props for the TabsPrimary component
19
+ */
20
+ export interface TabsPrimaryProps {
21
+ /** Child elements to be rendered within the navigation */
22
+ children: React.ReactNode
23
+
24
+ /** The currently selected tab value */
25
+ value?: string
26
+
27
+ /** Callback function triggered when a tab is selected */
28
+ onChange?: (value: string) => void
29
+
30
+ /** Whether to enable sliding animation between tabs */
31
+ slide?: boolean
32
+
33
+ /** Additional CSS class name for the component */
34
+ className?: string
35
+ }
36
+
37
+ /**
38
+ * A navigation component that displays tabs with an underline indicator
39
+ *
40
+ * @category Component
41
+ */
42
+ export function TabsPrimary({
43
+ children,
44
+ value: controlledValue,
45
+ onChange,
46
+ slide = true,
47
+ className,
48
+ }: TabsPrimaryProps) {
49
+ const tabsAnalytics = useTabsAnalytics()
50
+ const childrenArray = React.Children.toArray(children);
51
+ const navItems = childrenArray.filter(
52
+ child => {
53
+ return React.isValidElement(child) &&
54
+ (child.type === TabsPrimary.Item ||
55
+ (typeof child.type === 'function' && 'displayName' in child.type && child.type.displayName === "Tabs.Item"))
56
+ }
57
+ );
58
+ const otherChildren = childrenArray.filter(
59
+ child => !React.isValidElement(child) ||
60
+ (child.type !== TabsPrimary.Item &&
61
+ !(typeof child.type === 'function' && 'displayName' in child.type && child.type.displayName === "Tabs.Item"))
62
+ );
63
+
64
+ const [direction, value, handleValueChange] = useValueChange(
65
+ controlledValue,
66
+ onChange,
67
+ navItems
68
+ );
69
+
70
+ useEffect(() => {
71
+ tabsAnalytics.setValue(value)
72
+ }, [value])
73
+
74
+ return (
75
+ <TabsPrimaryContext.Provider value={{ direction }}>
76
+ <RadixTabs.Root value={value} onValueChange={handleValueChange}>
77
+ <xyd-tabs
78
+ ref={tabsAnalytics.tabsRef}
79
+ className={`${cn.TabsPrimaryHost} ${className || ""}`}
80
+ >
81
+ <nav part="nav">
82
+ <RadixTabs.List asChild>
83
+ <ul part="list">
84
+ {navItems}
85
+ </ul>
86
+ </RadixTabs.List>
87
+ </nav>
88
+ <div
89
+ part="content"
90
+ data-slide={slide ? "true" : "false"}
91
+ >
92
+ {otherChildren}
93
+ </div>
94
+ </xyd-tabs>
95
+ </RadixTabs.Root>
96
+ </TabsPrimaryContext.Provider>
97
+ );
98
+ }
99
+
100
+ /**
101
+ * Props for the TabsPrimary.Item component
102
+ */
103
+ export interface TabsPrimaryItemProps {
104
+ /** Child elements to be rendered within the navigation item */
105
+ children: React.ReactNode
106
+
107
+ /** Unique identifier for the navigation item */
108
+ value: string
109
+
110
+ /** URL for the navigation item link */
111
+ href?: string
112
+
113
+ /** Custom component to render as the link element */
114
+ as?: React.ElementType
115
+
116
+ /** Whether this item should be active by default */
117
+ defaultActive?: boolean
118
+ }
119
+
120
+ /**
121
+ * Individual navigation item component
122
+ *
123
+ * @category Component
124
+ */
125
+ TabsPrimary.Item = function TabsPrimaryItem({ children, value, href, as, defaultActive }: TabsPrimaryItemProps) {
126
+ const Link = as || _Link;
127
+ const controlByItem = typeof defaultActive === "boolean"
128
+ const [defaultActiveState, setDefaultActiveState] = useState(controlByItem ? (defaultActive ? "active" : "inactive") : undefined)
129
+
130
+ let activeProps = controlByItem && defaultActiveState != undefined
131
+ ? { "data-state": defaultActiveState }
132
+ : undefined
133
+
134
+ useEffect(() => {
135
+ if (!controlByItem) {
136
+ return
137
+ }
138
+
139
+ setDefaultActiveState(undefined)
140
+ }, [])
141
+
142
+ return (
143
+ <RadixTabs.Trigger value={value} asChild {...activeProps}>
144
+ <li part="item">
145
+ <Link part="link" href={href}>
146
+ {children}
147
+ </Link>
148
+ </li>
149
+ </RadixTabs.Trigger>
150
+ );
151
+ }
152
+
153
+ /**
154
+ * Props for the TabsPrimary.Content component
155
+ */
156
+ export interface TabsPrimaryContentProps {
157
+ /** Child elements to be rendered within the content area */
158
+ children: React.ReactNode
159
+
160
+ /** Unique identifier for the content section */
161
+ value: string
162
+
163
+ /** Whether this content should be active by default */
164
+ defaultActive?: boolean
165
+ }
166
+
167
+ /**
168
+ * Content section component for the TabsPrimary
169
+ *
170
+ * @category Component
171
+ */
172
+ TabsPrimary.Content = function TabsPrimaryContent({
173
+ children,
174
+ value,
175
+ defaultActive
176
+ }: TabsPrimaryContentProps) {
177
+ const { direction } = useContext(TabsPrimaryContext);
178
+
179
+ const controlByItem = typeof defaultActive === "boolean"
180
+ const [defaultActiveState, setDefaultActiveState] = useState(controlByItem ? (defaultActive ? "active" : "inactive") : undefined)
181
+
182
+ let activeProps = controlByItem && defaultActiveState != undefined
183
+ ? { "data-state": defaultActiveState }
184
+ : undefined
185
+
186
+ useEffect(() => {
187
+ if (!controlByItem) {
188
+ return
189
+ }
190
+
191
+ setDefaultActiveState(undefined)
192
+ }, [])
193
+
194
+ return (
195
+ <RadixTabs.Content
196
+ value={value}
197
+ forceMount={true}
198
+ asChild
199
+ {...activeProps}
200
+ >
201
+ <div
202
+ className={cn.TabsPrimaryContent}
203
+ data-direction={direction}
204
+ >
205
+ <div part="child">
206
+ {children}
207
+ </div>
208
+ </div>
209
+ </RadixTabs.Content>
210
+ );
211
+ }
212
+
213
+ function _Link({ ...props }) {
214
+ return <a {...props}>{props.children}</a>
215
+ }
@@ -0,0 +1,13 @@
1
+ export interface TabsProps {
2
+ /** The kind of tabs to render. If not provided, the component will render the primary tabs. */
3
+ kind?: 'secondary' | null
4
+ }
5
+
6
+ /**
7
+ * Props for the Tabs component
8
+ *
9
+ * @category Component
10
+ */
11
+ export function TabsProps(props: TabsProps) {
12
+ return props
13
+ }
@@ -0,0 +1,78 @@
1
+ import { css } from "@linaria/core";
2
+
3
+ export const TabsSecondaryHost = css`
4
+ @layer defaults {
5
+ display: block;
6
+ position: relative;
7
+ max-width: 100%;
8
+
9
+ [part="buttons"] {
10
+ display: flex;
11
+ align-items: center;
12
+ }
13
+
14
+ [part="arrow"] {
15
+ padding: 8px;
16
+ background-color: var(--xyd-tabs-arrow-bgcolor);
17
+ box-shadow: 0 1px 2px 0 var(--xyd-tabs-shadow-color--active);
18
+ }
19
+
20
+ [part="arrow-icon"] {
21
+ width: 16px;
22
+ height: 16px;
23
+ }
24
+
25
+ [part="scroller"] {
26
+ overflow-x: auto;
27
+ flex-grow: 1;
28
+ }
29
+
30
+ [part="scroller-container"] {
31
+ display: inline-flex;
32
+ gap: 4px;
33
+
34
+ border-radius: 8px;
35
+ background-color: var(--xyd-tabs-bgcolor);
36
+
37
+ padding: 4px;
38
+ margin-left: 4px;
39
+ }
40
+
41
+ [part="content"] {
42
+ margin-top: 16px;
43
+ }
44
+ }
45
+ `;
46
+
47
+ export const TabsSecondaryItem = css`
48
+ @layer defaults {
49
+ cursor: pointer;
50
+ &[data-state="inactive"] {
51
+ a, button {
52
+ color: unset;
53
+ }
54
+ }
55
+
56
+ display: inline-block;
57
+ padding: 5px 16px;
58
+
59
+ border-radius: 0.375rem;
60
+ white-space: nowrap;
61
+
62
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
63
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
64
+ transition-duration: 300ms;
65
+
66
+ color: var(--xyd-tabs-color);
67
+
68
+ &:hover {
69
+ color: var(--xyd-tabs-color--active);
70
+ }
71
+
72
+ &[data-state="active"] {
73
+ color: var(--xyd-tabs-color--active);
74
+ background-color: var(--xyd-tabs-bgcolor--active);
75
+ box-shadow: 0 1px 2px 0 var(--xyd-tabs-shadow-color--active);
76
+ }
77
+ }
78
+ `
@@ -0,0 +1,176 @@
1
+ import React, { useState, useRef, useEffect } from 'react'
2
+ import { Tabs as RadixTabs } from "radix-ui"; // TODO: remove and use separation
3
+ import { ChevronLeft, ChevronRight } from "lucide-react"
4
+
5
+ import * as cn from "./TabsSecondary.styles";
6
+ import { useValueChange } from './useValueChange';
7
+ import { useTabsAnalytics } from './TabsAnalytics';
8
+
9
+ export interface TabsSecondaryProps {
10
+ /** The currently selected tab value */
11
+ value?: string
12
+ children: React.ReactNode;
13
+ className?: string;
14
+ onChange?: (value: string) => void
15
+ }
16
+
17
+ export function TabsSecondary({ children, value: controlledValue, onChange, className }: TabsSecondaryProps) {
18
+ const tabsAnalytics = useTabsAnalytics()
19
+ const [showLeftArrow, setShowLeftArrow] = useState(false)
20
+ const [showRightArrow, setShowRightArrow] = useState(false)
21
+ const scrollContainerRef = useRef<HTMLDivElement>(null)
22
+
23
+ const childrenArray = React.Children.toArray(children);
24
+ const navItems = childrenArray.filter(
25
+ child => {
26
+ return React.isValidElement(child) &&
27
+ (child.type === TabsSecondary.Item ||
28
+ (typeof child.type === 'function' && 'displayName' in child.type && child.type.displayName === "Tabs.Item"))
29
+ }
30
+ );
31
+ const otherChildren = childrenArray.filter(
32
+ child => !React.isValidElement(child) ||
33
+ (child.type !== TabsSecondary.Item &&
34
+ !(typeof child.type === 'function' && 'displayName' in child.type && child.type.displayName === "Tabs.Item"))
35
+ );
36
+
37
+ const [_, value, handleValueChange] = useValueChange(
38
+ controlledValue,
39
+ onChange,
40
+ navItems,
41
+ );
42
+
43
+ useEffect(() => {
44
+ tabsAnalytics.setValue(value)
45
+ }, [value])
46
+
47
+ const handleScroll = () => {
48
+ if (scrollContainerRef.current) {
49
+ const { scrollLeft, scrollWidth, clientWidth } = scrollContainerRef.current
50
+ setShowLeftArrow(scrollLeft > 0)
51
+ setShowRightArrow(scrollLeft < scrollWidth - clientWidth)
52
+ }
53
+ }
54
+
55
+ useEffect(() => {
56
+ handleScroll()
57
+ window.addEventListener('resize', handleScroll)
58
+ return () => window.removeEventListener('resize', handleScroll)
59
+ }, [])
60
+
61
+ const scroll = (direction: 'left' | 'right') => {
62
+ if (scrollContainerRef.current) {
63
+ const scrollAmount = direction === 'left' ? -200 : 200
64
+ scrollContainerRef.current.scrollBy({ left: scrollAmount, behavior: 'smooth' })
65
+ }
66
+ }
67
+
68
+ return (
69
+ <RadixTabs.Root asChild value={value} onValueChange={handleValueChange}>
70
+ <xyd-tabs
71
+ ref={tabsAnalytics.tabsRef}
72
+ data-kind="secondary"
73
+ className={`${cn.TabsSecondaryHost} ${className || ""}`}
74
+ >
75
+ <div part="buttons">
76
+ {showLeftArrow && (
77
+ <button
78
+ onClick={() => scroll('left')}
79
+ part="arrow"
80
+ >
81
+ <ChevronLeft part="arrow-icon" />
82
+ </button>
83
+ )}
84
+
85
+ <div
86
+ ref={scrollContainerRef}
87
+ onScroll={handleScroll}
88
+ part="scroller"
89
+ >
90
+ <div
91
+ part="scroller-container"
92
+ >
93
+ <RadixTabs.List>
94
+ {navItems}
95
+ </RadixTabs.List>
96
+ </div>
97
+ </div>
98
+
99
+ {showRightArrow && (
100
+ <button
101
+ onClick={() => scroll('right')}
102
+ part="arrow"
103
+ >
104
+ <ChevronRight part="arrow-icon" />
105
+ </button>
106
+ )}
107
+ </div>
108
+ <div part="content">
109
+ {otherChildren}
110
+ </div>
111
+ </xyd-tabs>
112
+ </RadixTabs.Root>
113
+ );
114
+ }
115
+
116
+ /**
117
+ * Props for the TabsPrimary.Item component
118
+ */
119
+ export interface TabsSecondaryItemProps {
120
+ /** Child elements to be rendered within the navigation item */
121
+ children: React.ReactNode
122
+
123
+ /** Unique identifier for the navigation item */
124
+ value: string
125
+
126
+ /** URL for the navigation item link */
127
+ href?: string
128
+
129
+ /** Custom component to render as the link element */
130
+ as?: React.ElementType
131
+
132
+ /** Whether this item should be active by default */
133
+ defaultActive?: boolean
134
+ }
135
+
136
+ TabsSecondary.Item = function TabsPrimaryItem({ children, value, href, as, defaultActive }: TabsSecondaryItemProps) {
137
+ const Link = as || _Link;
138
+ const controlByItem = typeof defaultActive === "boolean"
139
+ const [defaultActiveState, setDefaultActiveState] = useState(controlByItem ? (defaultActive ? "active" : "inactive") : undefined)
140
+
141
+ let activeProps = controlByItem && defaultActiveState != undefined
142
+ ? { "data-state": defaultActiveState }
143
+ : undefined
144
+
145
+ useEffect(() => {
146
+ if (!controlByItem) {
147
+ return
148
+ }
149
+
150
+ setDefaultActiveState(undefined)
151
+ }, [])
152
+
153
+ return (
154
+ <RadixTabs.Trigger className={cn.TabsSecondaryItem} value={value} asChild {...activeProps}>
155
+ <div>
156
+ <Link href={href}>
157
+ {children}
158
+ </Link>
159
+ </div>
160
+ </RadixTabs.Trigger>
161
+ );
162
+ }
163
+
164
+ function _Link({ ...props }) {
165
+ return <a {...props}>{props.children}</a>
166
+ }
167
+
168
+
169
+ TabsSecondary.Content = function TabsContent({ children, value }) {
170
+ return <RadixTabs.Content asChild value={value}>
171
+ <div>
172
+ {children}
173
+ </div>
174
+ </RadixTabs.Content>
175
+ }
176
+
@@ -0,0 +1,2 @@
1
+ export {Tabs} from "./Tabs"
2
+ export {TabsProps} from "./TabsProps"
@@ -0,0 +1,84 @@
1
+ import React, {useRef, useState} from "react";
2
+
3
+ import { useTabsAnalytics } from "./TabsAnalytics";
4
+
5
+ import {EVENT_COMPONENT_TAB_CHANGE} from "../../uxsdk";
6
+
7
+ /**
8
+ * Custom hook to handle value changes and determine navigation direction
9
+ * @param controlledValue - The controlled value from props
10
+ * @param onChange - Callback function for value changes
11
+ * @param navItems - Array of navigation items
12
+ * @returns Tuple containing direction, current value, and change handler
13
+ */
14
+ export function useValueChange(
15
+ controlledValue: string | undefined,
16
+ onChange: ((value: string) => void) | undefined,
17
+ navItems: React.ReactNode[],
18
+ ) {
19
+ const tabsAnalytics = useTabsAnalytics()
20
+ const tabsRef = tabsAnalytics.tabsRef
21
+
22
+ // Determine if we're in controlled or uncontrolled mode
23
+ const isControlled = controlledValue !== undefined && onChange !== undefined;
24
+
25
+ // For uncontrolled mode, use internal state
26
+ const [internalValue, setInternalValue] = useState(
27
+ navItems.length > 0 && React.isValidElement(navItems[0]) ?
28
+ navItems[0].props.value : ''
29
+ );
30
+
31
+ // Use either controlled or internal value
32
+ const value = isControlled ? controlledValue : internalValue;
33
+
34
+ // Track previous value to determine navigation direction
35
+ const prevValueRef = useRef(value);
36
+ const [direction, setDirection] = useState<'forward' | 'backward'>('forward');
37
+
38
+ // Handle value change and determine direction
39
+ const handleValueChange = (newValue: string) => {
40
+ // Find indices of current and new values
41
+ const currentIndex = navItems.findIndex(
42
+ item => React.isValidElement(item) && item.props.value === prevValueRef.current
43
+ );
44
+ const newIndex = navItems.findIndex(
45
+ item => React.isValidElement(item) && item.props.value === newValue
46
+ );
47
+
48
+ // Set direction based on indices
49
+ const newDirection = newIndex > currentIndex ? 'forward' : 'backward';
50
+ setDirection(newDirection);
51
+
52
+ // Update previous value
53
+ prevValueRef.current = newValue;
54
+
55
+ // Update internal state if uncontrolled
56
+ if (!isControlled) {
57
+ setInternalValue(newValue);
58
+ }
59
+
60
+ // Call the original onChange if provided
61
+ if (onChange) {
62
+ onChange(newValue);
63
+ }
64
+
65
+ // Dispatch custom event if tabsRef is provided
66
+ console.log(tabsRef)
67
+ if (tabsRef?.current) {
68
+ const eventData = {
69
+ value: newValue,
70
+ previousValue: prevValueRef.current,
71
+ direction: newDirection as 'forward' | 'backward'
72
+ };
73
+
74
+ const tabChangeEvent = new CustomEvent(EVENT_COMPONENT_TAB_CHANGE, {
75
+ detail: eventData,
76
+ bubbles: true
77
+ });
78
+ tabsRef.current.dispatchEvent(tabChangeEvent);
79
+ }
80
+ };
81
+
82
+ return [direction, value, handleValueChange] as const;
83
+ }
84
+
@@ -0,0 +1,66 @@
1
+ import { css } from "@linaria/core";
2
+
3
+ export const TextHost = css`
4
+ @layer defaults {
5
+ display: inline-block;
6
+ margin: 0;
7
+
8
+ &[data-size="xsmall"] {
9
+ font-size: var(--xyd-font-size-xsmall);
10
+ line-height: var(--xyd-line-height-xsmall);
11
+ }
12
+ &[data-size="small"] {
13
+ font-size: var(--xyd-font-size-small);
14
+ line-height: var(--xyd-line-height-small);
15
+ }
16
+ &[data-size="medium"] {
17
+ font-size: var(--xyd-font-size-medium);
18
+ line-height: var(--xyd-line-height-medium);
19
+ }
20
+ &[data-size="large"] {
21
+ font-size: var(--xyd-font-size-large);
22
+ line-height: var(--xyd-line-height-large);
23
+ }
24
+ &[data-size="xlarge"] {
25
+ font-size: var(--xyd-font-size-xlarge);
26
+ line-height: var(--xyd-line-height-xlarge);
27
+ }
28
+ &[data-size="xxlarge"] {
29
+ font-size: var(--xyd-font-size-xxlarge);
30
+ line-height: var(--xyd-line-height-xxlarge);
31
+ }
32
+
33
+ &[data-kind="default"] {
34
+ color: var(--xyd-text-color--default);
35
+ }
36
+ &[data-kind="ghost"] {
37
+ color: var(--xyd-text-color--ghost);
38
+ }
39
+ &[data-kind="success"] {
40
+ color: var(--xyd-text-color--success);
41
+ }
42
+ &[data-kind="warn"] {
43
+ color: var(--xyd-text-color--warn);
44
+ }
45
+ &[data-kind="error"] {
46
+ color: var(--xyd-text-color--error);
47
+ }
48
+ &[data-kind="primary"] {
49
+ color: var(--xyd-text-color--primary);
50
+ }
51
+ &[data-kind="secondary"] {
52
+ color: var(--xyd-text-color--secondary);
53
+ }
54
+
55
+ &[data-weight="normal"] {
56
+ font-weight: var(--xyd-font-weight-normal);
57
+ }
58
+ &[data-weight="bold"] {
59
+ font-weight: bold;
60
+ }
61
+ &[data-weight="extra-bold"] {
62
+ font-weight: var(--xyd-font-weight-extrabold);
63
+ }
64
+ }
65
+ `;
66
+