@soul-refiner/design-system 0.0.14 → 0.0.16

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 (271) hide show
  1. package/.eslintrc.js +4 -0
  2. package/.turbo/turbo-build.log +12 -0
  3. package/.turbo/turbo-test.log +4417 -0
  4. package/CHANGELOG.md +7 -0
  5. package/babel.config.js +6 -0
  6. package/custom.d.ts +4 -0
  7. package/package.json +1 -7
  8. package/src/actions/Button/Button.module.scss +205 -0
  9. package/src/actions/Button/Button.spec.js +56 -0
  10. package/src/actions/Button/Button.tsx +143 -0
  11. package/src/actions/Button/index.ts +1 -0
  12. package/src/actions/Dropdown/Dropdown.module.scss +77 -0
  13. package/src/actions/Dropdown/Dropdown.spec.js +149 -0
  14. package/src/actions/Dropdown/Dropdown.tsx +224 -0
  15. package/src/actions/Dropdown/index.ts +6 -0
  16. package/src/actions/Dropzone/Dropzone.module.scss +48 -0
  17. package/src/actions/Dropzone/Dropzone.spec.js +60 -0
  18. package/src/actions/Dropzone/Dropzone.tsx +191 -0
  19. package/src/actions/Dropzone/index.ts +1 -0
  20. package/src/actions/Rate/Rate.module.scss +17 -0
  21. package/src/actions/Rate/Rate.tsx +53 -0
  22. package/src/actions/Rate/index.ts +1 -0
  23. package/src/actions/Switch/Switch.module.scss +35 -0
  24. package/src/actions/Switch/Switch.spec.js +31 -0
  25. package/src/actions/Switch/Switch.tsx +34 -0
  26. package/src/actions/Switch/index.ts +1 -0
  27. package/src/actions/index.ts +5 -0
  28. package/src/cards/CourseCard/CourseCard.module.scss +219 -0
  29. package/src/cards/CourseCard/CourseCard.spec.js +60 -0
  30. package/src/cards/CourseCard/CourseCard.tsx +145 -0
  31. package/src/cards/CourseCard/index.ts +1 -0
  32. package/src/cards/EpisodeCard/EpisodeCard.module.scss +69 -0
  33. package/src/cards/EpisodeCard/EpisodeCard.tsx +53 -0
  34. package/src/cards/EpisodeCard/index.ts +1 -0
  35. package/src/cards/FeatureCard/FeatureCard.module.scss +116 -0
  36. package/src/cards/FeatureCard/FeatureCard.spec.js +70 -0
  37. package/src/cards/FeatureCard/FeatureCard.tsx +123 -0
  38. package/src/cards/FeatureCard/index.ts +1 -0
  39. package/src/cards/index.ts +3 -0
  40. package/src/data/Bar/Bar.module.scss +105 -0
  41. package/src/data/Bar/Bar.tsx +161 -0
  42. package/src/data/Bar/index.ts +1 -0
  43. package/src/data/Line/Line.module.scss +102 -0
  44. package/src/data/Line/Line.tsx +162 -0
  45. package/src/data/Line/index.ts +1 -0
  46. package/src/data/Pie/Pie.module.scss +56 -0
  47. package/src/data/Pie/Pie.spec.js +72 -0
  48. package/src/data/Pie/Pie.tsx +111 -0
  49. package/src/data/Pie/index.ts +1 -0
  50. package/src/data/index.ts +3 -0
  51. package/src/editor/Editor.module.scss +125 -0
  52. package/src/editor/Editor.tsx +327 -0
  53. package/src/editor/common/elements.ts +50 -0
  54. package/src/editor/common/index.ts +2 -0
  55. package/src/editor/common/marks.ts +27 -0
  56. package/src/editor/components/MediaDrawer/MediaDrawer.module.scss +316 -0
  57. package/src/editor/components/MediaDrawer/MediaDrawer.tsx +457 -0
  58. package/src/editor/components/MediaDrawer/index.ts +1 -0
  59. package/src/editor/components/index.ts +1 -0
  60. package/src/editor/config/default.ts +213 -0
  61. package/src/editor/config/index.ts +2 -0
  62. package/src/editor/config/props.ts +9 -0
  63. package/src/editor/index.ts +2 -0
  64. package/src/editor/plateUI.ts +82 -0
  65. package/src/editor/plugins/blocks.tsx +71 -0
  66. package/src/editor/plugins/custom/assets/DefaultThumbnail.tsx +57 -0
  67. package/src/editor/plugins/custom/assets/index.ts +1 -0
  68. package/src/editor/plugins/custom/buttons.tsx +289 -0
  69. package/src/editor/plugins/custom/example.tsx +64 -0
  70. package/src/editor/plugins/custom/exitBreak.ts +41 -0
  71. package/src/editor/plugins/custom/footnote.tsx +185 -0
  72. package/src/editor/plugins/custom/index.ts +14 -0
  73. package/src/editor/plugins/custom/paywall.tsx +156 -0
  74. package/src/editor/plugins/custom/qa.tsx +390 -0
  75. package/src/editor/plugins/custom/resetBlockType.ts +29 -0
  76. package/src/editor/plugins/custom/selectOnBackspace.ts +7 -0
  77. package/src/editor/plugins/custom/softBreak.ts +20 -0
  78. package/src/editor/plugins/custom/styles/Button.module.scss +51 -0
  79. package/src/editor/plugins/custom/styles/Footnote.module.scss +58 -0
  80. package/src/editor/plugins/custom/styles/Paywall.module.scss +67 -0
  81. package/src/editor/plugins/custom/styles/QA.module.scss +140 -0
  82. package/src/editor/plugins/custom/styles/Video.module.scss +79 -0
  83. package/src/editor/plugins/custom/video.tsx +163 -0
  84. package/src/editor/plugins/index.ts +18 -0
  85. package/src/editor/plugins/inline.ts +46 -0
  86. package/src/editor/plugins/marks.ts +25 -0
  87. package/src/editor/plugins/utils.ts +22 -0
  88. package/src/feedback/Chip/Chip.module.scss +23 -0
  89. package/src/feedback/Chip/Chip.tsx +58 -0
  90. package/src/feedback/Chip/index.ts +1 -0
  91. package/src/feedback/Loader/Loader.module.scss +18 -0
  92. package/src/feedback/Loader/Loader.spec.js +18 -0
  93. package/src/feedback/Loader/Loader.tsx +53 -0
  94. package/src/feedback/Loader/index.ts +1 -0
  95. package/src/feedback/ProgressBar/ProgressBar.module.scss +13 -0
  96. package/src/feedback/ProgressBar/ProgressBar.tsx +32 -0
  97. package/src/feedback/ProgressBar/index.ts +1 -0
  98. package/src/feedback/Toast/Toast.module.scss +44 -0
  99. package/src/feedback/Toast/Toast.tsx +76 -0
  100. package/src/feedback/Toast/index.ts +1 -0
  101. package/src/feedback/Tooltip/Tooltip.module.scss +47 -0
  102. package/src/feedback/Tooltip/Tooltip.tsx +10 -0
  103. package/src/feedback/Tooltip/index.ts +1 -0
  104. package/src/feedback/index.ts +5 -0
  105. package/src/global.d.ts +6 -0
  106. package/src/iconography/Avatar/Avatar.module.scss +90 -0
  107. package/src/iconography/Avatar/Avatar.spec.js +75 -0
  108. package/src/iconography/Avatar/Avatar.tsx +96 -0
  109. package/src/iconography/Avatar/DefaultIcon.svg +4 -0
  110. package/src/iconography/Avatar/DefaultIcon.tsx +12 -0
  111. package/src/iconography/Avatar/iconHelpers.tsx +186 -0
  112. package/src/iconography/Avatar/index.ts +1 -0
  113. package/src/iconography/ColoredIcon/ColoredIcon.module.scss +40 -0
  114. package/src/iconography/ColoredIcon/ColoredIcon.tsx +30 -0
  115. package/src/iconography/ColoredIcon/index.ts +5 -0
  116. package/src/iconography/DevicePreview/DevicePreview.module.scss +143 -0
  117. package/src/iconography/DevicePreview/DevicePreview.tsx +592 -0
  118. package/src/iconography/DevicePreview/index.ts +1 -0
  119. package/src/iconography/IconHeader/IconHeader.module.scss +42 -0
  120. package/src/iconography/IconHeader/IconHeader.tsx +42 -0
  121. package/src/iconography/IconHeader/index.ts +1 -0
  122. package/src/iconography/StarRating/StarRating.tsx +99 -0
  123. package/src/iconography/StarRating/index.ts +1 -0
  124. package/src/iconography/index.ts +5 -0
  125. package/src/implementations/BodyContent/BodyContent.module.scss +38 -0
  126. package/src/implementations/BodyContent/BodyContent.tsx +78 -0
  127. package/src/implementations/BodyContent/index.ts +2 -0
  128. package/src/implementations/JoinGroupModal/JoinGroupModal.module.scss +83 -0
  129. package/src/implementations/JoinGroupModal/JoinGroupModal.tsx +176 -0
  130. package/src/implementations/JoinGroupModal/index.ts +1 -0
  131. package/src/implementations/index.ts +2 -0
  132. package/src/index.ts +86 -0
  133. package/src/inputs/CalendarInput/CalendarInput.module.scss +38 -0
  134. package/src/inputs/CalendarInput/CalendarInput.spec.js +19 -0
  135. package/src/inputs/CalendarInput/CalendarInput.tsx +29 -0
  136. package/src/inputs/CalendarInput/index.ts +1 -0
  137. package/src/inputs/CheckboxInput/CheckboxInput.module.scss +23 -0
  138. package/src/inputs/CheckboxInput/CheckboxInput.tsx +39 -0
  139. package/src/inputs/CheckboxInput/index.ts +1 -0
  140. package/src/inputs/FeedInput/FeedInput.module.scss +48 -0
  141. package/src/inputs/FeedInput/FeedInput.spec.js +16 -0
  142. package/src/inputs/FeedInput/FeedInput.tsx +197 -0
  143. package/src/inputs/FeedInput/index.ts +1 -0
  144. package/src/inputs/InboxInput/InboxInput.module.scss +48 -0
  145. package/src/inputs/InboxInput/InboxInput.spec.js +19 -0
  146. package/src/inputs/InboxInput/InboxInput.tsx +97 -0
  147. package/src/inputs/InboxInput/index.ts +1 -0
  148. package/src/inputs/PostInput/PostInput.module.scss +49 -0
  149. package/src/inputs/PostInput/PostInput.spec.js +19 -0
  150. package/src/inputs/PostInput/PostInput.tsx +54 -0
  151. package/src/inputs/PostInput/index.ts +1 -0
  152. package/src/inputs/RadioInput/RadioInput.module.scss +68 -0
  153. package/src/inputs/RadioInput/RadioInput.tsx +55 -0
  154. package/src/inputs/RadioInput/index.ts +1 -0
  155. package/src/inputs/SearchInput/SearchInput.module.scss +40 -0
  156. package/src/inputs/SearchInput/SearchInput.tsx +61 -0
  157. package/src/inputs/SearchInput/index.ts +1 -0
  158. package/src/inputs/SelectInput/SelectInput.module.scss +66 -0
  159. package/src/inputs/SelectInput/SelectInput.tsx +145 -0
  160. package/src/inputs/SelectInput/index.ts +1 -0
  161. package/src/inputs/TagInput/TagInput.module.scss +75 -0
  162. package/src/inputs/TagInput/TagInput.tsx +115 -0
  163. package/src/inputs/TagInput/index.ts +1 -0
  164. package/src/inputs/TextInput/TextInput.module.scss +35 -0
  165. package/src/inputs/TextInput/TextInput.tsx +46 -0
  166. package/src/inputs/TextInput/index.ts +1 -0
  167. package/src/inputs/index.ts +10 -0
  168. package/src/lists/ContactDetails/ContactDetails.module.scss +70 -0
  169. package/src/lists/ContactDetails/ContactDetails.spec.js +69 -0
  170. package/src/lists/ContactDetails/ContactDetails.tsx +185 -0
  171. package/src/lists/ContactDetails/index.ts +1 -0
  172. package/src/lists/index.ts +1 -0
  173. package/src/navigation/Breadcrumbs/Breadcrumbs.module.scss +18 -0
  174. package/src/navigation/Breadcrumbs/Breadcrumbs.spec.js +38 -0
  175. package/src/navigation/Breadcrumbs/Breadcrumbs.tsx +43 -0
  176. package/src/navigation/Breadcrumbs/index.ts +1 -0
  177. package/src/navigation/Drawer/Drawer.module.scss +104 -0
  178. package/src/navigation/Drawer/Drawer.tsx +177 -0
  179. package/src/navigation/Drawer/index.ts +1 -0
  180. package/src/navigation/EditorBar/EditorBar.module.scss +118 -0
  181. package/src/navigation/EditorBar/EditorBar.tsx +416 -0
  182. package/src/navigation/EditorBar/components/AlignmentDropdown/AlignmentDropdown.tsx +106 -0
  183. package/src/navigation/EditorBar/components/AlignmentDropdown/index.ts +1 -0
  184. package/src/navigation/EditorBar/components/ButtonModal/ButtonModal.module.scss +85 -0
  185. package/src/navigation/EditorBar/components/ButtonModal/ButtonModal.tsx +314 -0
  186. package/src/navigation/EditorBar/components/ButtonModal/assets/Comment.tsx +28 -0
  187. package/src/navigation/EditorBar/components/ButtonModal/assets/GiftSubscription.tsx +28 -0
  188. package/src/navigation/EditorBar/components/ButtonModal/assets/Link.tsx +28 -0
  189. package/src/navigation/EditorBar/components/ButtonModal/assets/Share.tsx +28 -0
  190. package/src/navigation/EditorBar/components/ButtonModal/assets/ShareCommunity.tsx +42 -0
  191. package/src/navigation/EditorBar/components/ButtonModal/assets/Signup.tsx +68 -0
  192. package/src/navigation/EditorBar/components/ButtonModal/assets/Special.tsx +24 -0
  193. package/src/navigation/EditorBar/components/ButtonModal/assets/Subscribe.tsx +28 -0
  194. package/src/navigation/EditorBar/components/ButtonModal/assets/index.ts +8 -0
  195. package/src/navigation/EditorBar/components/ButtonModal/index.ts +1 -0
  196. package/src/navigation/EditorBar/components/FontDropdown/FontDropdown.module.scss +16 -0
  197. package/src/navigation/EditorBar/components/FontDropdown/FontDropdown.tsx +137 -0
  198. package/src/navigation/EditorBar/components/FontDropdown/index.ts +1 -0
  199. package/src/navigation/EditorBar/components/MoreDropdown/MoreDropdown.module.scss +43 -0
  200. package/src/navigation/EditorBar/components/MoreDropdown/MoreDropdown.tsx +124 -0
  201. package/src/navigation/EditorBar/components/MoreDropdown/index.ts +1 -0
  202. package/src/navigation/EditorBar/components/OutlineDropdown/OutlineDropdown.module.scss +21 -0
  203. package/src/navigation/EditorBar/components/OutlineDropdown/OutlineDropdown.tsx +37 -0
  204. package/src/navigation/EditorBar/components/OutlineDropdown/index.ts +1 -0
  205. package/src/navigation/EditorBar/components/TextTypeDropdown/TextTypeDropdown.module.scss +51 -0
  206. package/src/navigation/EditorBar/components/TextTypeDropdown/TextTypeDropdown.tsx +80 -0
  207. package/src/navigation/EditorBar/components/TextTypeDropdown/index.ts +1 -0
  208. package/src/navigation/EditorBar/components/VideoModal/VideoModal.module.scss +150 -0
  209. package/src/navigation/EditorBar/components/VideoModal/VideoModal.tsx +163 -0
  210. package/src/navigation/EditorBar/components/VideoModal/index.ts +1 -0
  211. package/src/navigation/EditorBar/components/index.ts +7 -0
  212. package/src/navigation/EditorBar/index.ts +1 -0
  213. package/src/navigation/MenuTabs/MenuTabs.module.scss +34 -0
  214. package/src/navigation/MenuTabs/MenuTabs.spec.js +36 -0
  215. package/src/navigation/MenuTabs/MenuTabs.tsx +52 -0
  216. package/src/navigation/MenuTabs/index.ts +1 -0
  217. package/src/navigation/Navigation/Navigation.module.scss +92 -0
  218. package/src/navigation/Navigation/Navigation.spec.js +144 -0
  219. package/src/navigation/Navigation/Navigation.tsx +111 -0
  220. package/src/navigation/Navigation/SubNavigation.module.scss +255 -0
  221. package/src/navigation/Navigation/SubNavigation.spec.js +112 -0
  222. package/src/navigation/Navigation/SubNavigation.tsx +443 -0
  223. package/src/navigation/Navigation/index.ts +15 -0
  224. package/src/navigation/Pagination/Pagination.module.scss +49 -0
  225. package/src/navigation/Pagination/Pagination.tsx +115 -0
  226. package/src/navigation/Pagination/index.ts +1 -0
  227. package/src/navigation/index.ts +21 -0
  228. package/src/surfaces/Comment/Comment.module.scss +106 -0
  229. package/src/surfaces/Comment/Comment.spec.js +105 -0
  230. package/src/surfaces/Comment/Comment.tsx +157 -0
  231. package/src/surfaces/Comment/index.ts +1 -0
  232. package/src/surfaces/Faq/Faq.module.scss +91 -0
  233. package/src/surfaces/Faq/Faq.spec.js +38 -0
  234. package/src/surfaces/Faq/Faq.tsx +156 -0
  235. package/src/surfaces/Faq/index.ts +1 -0
  236. package/src/surfaces/Message/Message.module.scss +37 -0
  237. package/src/surfaces/Message/Message.spec.js +47 -0
  238. package/src/surfaces/Message/Message.tsx +54 -0
  239. package/src/surfaces/Message/index.ts +1 -0
  240. package/src/surfaces/Modal/Modal.module.scss +52 -0
  241. package/src/surfaces/Modal/Modal.spec.js +38 -0
  242. package/src/surfaces/Modal/Modal.tsx +131 -0
  243. package/src/surfaces/Modal/index.ts +5 -0
  244. package/src/surfaces/Plan/Plan.module.scss +79 -0
  245. package/src/surfaces/Plan/Plan.tsx +75 -0
  246. package/src/surfaces/Plan/index.ts +1 -0
  247. package/src/surfaces/Post/Post.module.scss +46 -0
  248. package/src/surfaces/Post/Post.spec.js +103 -0
  249. package/src/surfaces/Post/Post.tsx +185 -0
  250. package/src/surfaces/Post/index.ts +1 -0
  251. package/src/surfaces/Post/postHelpers.ts +20 -0
  252. package/src/surfaces/ProfileHeader/ProfileHeader.module.scss +202 -0
  253. package/src/surfaces/ProfileHeader/ProfileHeader.tsx +103 -0
  254. package/src/surfaces/ProfileHeader/index.ts +1 -0
  255. package/src/surfaces/RatingsOverview/RatingsOverview.module.scss +54 -0
  256. package/src/surfaces/RatingsOverview/RatingsOverview.tsx +69 -0
  257. package/src/surfaces/RatingsOverview/index.ts +1 -0
  258. package/src/surfaces/Review/Review.module.scss +73 -0
  259. package/src/surfaces/Review/Review.tsx +88 -0
  260. package/src/surfaces/Review/index.ts +1 -0
  261. package/src/surfaces/index.ts +9 -0
  262. package/src/tables/Filter/Filter.module.scss +34 -0
  263. package/src/tables/Filter/Filter.tsx +30 -0
  264. package/src/tables/Filter/index.ts +1 -0
  265. package/src/tables/Table/Table.module.scss +126 -0
  266. package/src/tables/Table/Table.spec.js +113 -0
  267. package/src/tables/Table/Table.tsx +251 -0
  268. package/src/tables/Table/index.ts +7 -0
  269. package/src/tables/index.ts +7 -0
  270. package/tsconfig.json +14 -0
  271. package/vite.config.ts +28 -0
@@ -0,0 +1,443 @@
1
+ import React, { UIEventHandler } from "react";
2
+ import { Component, sortChildrenByType } from "@soul-refiner/utils/src";
3
+ import { abbrRelativeTimeString } from "@soul-refiner/utils/src";
4
+ import {
5
+ ArrowLeft,
6
+ ChevronDown,
7
+ ChevronUp,
8
+ EllipsisHorizontal,
9
+ Plus,
10
+ } from "@soul-refiner/icons/src";
11
+ import styles from "./SubNavigation.module.scss";
12
+ import { MenuTabs } from "../MenuTabs";
13
+ import { SearchInput } from "../../inputs";
14
+ import { Button, ButtonProps } from "../../actions";
15
+ import { Dropdown, DropdownOptionProps } from "../../actions/Dropdown";
16
+ import { Avatar, AvatarProps } from "../../iconography";
17
+
18
+ /********************************************************
19
+ * Sub Navigation
20
+ */
21
+ export interface SubNavigationProps extends React.PropsWithChildren {
22
+ onSearch: (query: string) => void;
23
+ onScrollEnd?: () => void;
24
+ show: boolean;
25
+ title: string;
26
+ }
27
+
28
+ const SubNavigation = ({
29
+ children,
30
+ onSearch,
31
+ onScrollEnd,
32
+ show,
33
+ title,
34
+ }: SubNavigationProps) => {
35
+ const tabsRef = React.useRef<HTMLDivElement>(null);
36
+ const [prevLoc, setPrevLoc] = React.useState(0);
37
+ const [clickLoc, setClickLoc] = React.useState(0);
38
+ const [scrolling, setScrolling] = React.useState(false);
39
+ const [activeTab, setActiveTab] = React.useState(0);
40
+ const [activeSubMenu, setActiveSubMenu] = React.useState<
41
+ number | undefined
42
+ >();
43
+ const [query, setQuery] = React.useState("");
44
+
45
+ const _children = sortChildrenByType(children);
46
+ let tabs: string[] = [];
47
+
48
+ React.Children.forEach(_children["SubNavigation.Tab"], (child) => {
49
+ tabs.push((child as { props: { name: string } })?.props.name);
50
+ });
51
+
52
+ const handleChange = (event: React.FormEvent) => {
53
+ setQuery((event.target as HTMLInputElement).value);
54
+ };
55
+
56
+ const handleSubmit = (event: React.FormEvent) => {
57
+ event.preventDefault();
58
+ onSearch(query);
59
+ };
60
+
61
+ const handleTabChange = (index: number) => setActiveTab(index);
62
+
63
+ const handleTabMouseDown = (event: React.MouseEvent) => {
64
+ setScrolling(true);
65
+ setClickLoc(event.clientX);
66
+ };
67
+
68
+ const handleTabDrag = (event: React.MouseEvent) => {
69
+ if (tabsRef.current && scrolling) {
70
+ tabsRef.current.scrollLeft = prevLoc + clickLoc - event.clientX;
71
+ }
72
+ };
73
+
74
+ const handleTabMouseUp = () => {
75
+ setScrolling(false);
76
+ setPrevLoc(tabsRef.current?.scrollLeft ?? 0);
77
+ };
78
+
79
+ const handleScroll = (event: React.WheelEvent<HTMLDivElement>) => {
80
+ const target = event.target as HTMLDivElement;
81
+ const scrollDistance = target.scrollHeight - target.scrollTop;
82
+ // Margin of 10 for browser differences
83
+ if (scrollDistance - target.clientHeight < 11 && onScrollEnd) {
84
+ onScrollEnd();
85
+ }
86
+ };
87
+
88
+ submenu: if (activeSubMenu !== undefined) {
89
+ const activeTabElement = React.Children.toArray(
90
+ _children?.["SubNavigation.Tab"]?.[activeTab]
91
+ );
92
+ if (!activeTabElement || activeSubMenu === undefined) break submenu;
93
+ let parentProps = (activeTabElement[0] as any)?.props?.children?.props;
94
+ let activeSubMenuElement = parentProps?.submenu;
95
+
96
+ if (!activeSubMenuElement) {
97
+ // if there is more than one child
98
+ parentProps = (activeTabElement[0] as any)?.props?.children?.[
99
+ activeSubMenu
100
+ ]?.props;
101
+ activeSubMenuElement = parentProps?.submenu;
102
+ if (
103
+ !activeSubMenuElement ||
104
+ activeSubMenuElement.type.displayName !== "SubNavigation.SubMenu"
105
+ )
106
+ break submenu;
107
+ }
108
+
109
+ return (
110
+ <div
111
+ data-testid="submenu"
112
+ className={`${styles.secondary}${show ? " show" : " hidden"}`}
113
+ >
114
+ <div className="header">
115
+ <div
116
+ className="title-wrapper submenu"
117
+ onClick={() => setActiveSubMenu(undefined)}
118
+ >
119
+ <ArrowLeft fill="var(--color-grey-1)" iconSize={16} size={30} />
120
+ <h4>{activeSubMenuElement.props.title}</h4>
121
+ </div>
122
+ <Avatar size={40} title={parentProps.title} url={parentProps.url} />
123
+ </div>
124
+ <div className="contents">{activeSubMenuElement}</div>
125
+ </div>
126
+ );
127
+ }
128
+
129
+ return (
130
+ <div
131
+ data-testid="subnavigation"
132
+ className={`${styles.secondary}${show ? " show" : " hidden"}`}
133
+ >
134
+ <div className="header">
135
+ <div className="title-wrapper">
136
+ <h4>{title}</h4>
137
+ <SearchInput
138
+ expandable
139
+ onChange={handleChange}
140
+ onSubmit={handleSubmit as () => undefined}
141
+ value={query}
142
+ />
143
+ </div>
144
+ <div className="buttons-wrapper">
145
+ {_children["SubNavigation.Button"]}
146
+ </div>
147
+ </div>
148
+ <div
149
+ className="tab-wrapper"
150
+ onMouseDown={handleTabMouseDown}
151
+ onMouseMove={handleTabDrag}
152
+ onMouseUp={handleTabMouseUp}
153
+ ref={tabsRef}
154
+ >
155
+ <MenuTabs
156
+ activeItem={activeTab}
157
+ onTabClick={handleTabChange}
158
+ tabItems={tabs}
159
+ />
160
+ </div>
161
+ <div
162
+ className="contents"
163
+ onScroll={
164
+ onScrollEnd
165
+ ? (handleScroll as unknown as UIEventHandler<HTMLDivElement>)
166
+ : undefined
167
+ }
168
+ >
169
+ {React.Children.map(
170
+ (_children["SubNavigation.Tab"][activeTab] as React.ReactElement)
171
+ .props.children,
172
+ (child, index) => {
173
+ if (child.props.submenu) {
174
+ return React.cloneElement(child, {
175
+ key: "menu-item-" + index.toString(36),
176
+ onClick: (event: React.MouseEvent) => {
177
+ event.stopPropagation();
178
+ setActiveSubMenu(index);
179
+ },
180
+ });
181
+ }
182
+ return React.cloneElement(child, {
183
+ key: "menu-item-" + index.toString(36),
184
+ });
185
+ }
186
+ )}
187
+ </div>
188
+ <div className="create-wrapper">{_children["SubNavigation.Create"]}</div>
189
+ </div>
190
+ );
191
+ };
192
+
193
+ /********************************************************
194
+ * Item - Renders individual items of the sub navigation
195
+ */
196
+ export interface SubNavigationItemProps
197
+ extends Omit<AvatarProps, "as" | "size"> {
198
+ as?: React.ElementType;
199
+ active?: boolean;
200
+ /**
201
+ * The time stamp renders only if isMessage is true
202
+ */
203
+ dateCreated?: Date;
204
+ /**
205
+ * Dropdown options render only if isMessage is false
206
+ */
207
+ dropdownOptions?: DropdownOptionProps[];
208
+ dropdownElements?: React.ReactNode[];
209
+ isMessage?: boolean;
210
+ onClick?: () => void;
211
+ submenu?: React.ReactNode;
212
+ /**
213
+ * The unread props is for messages only
214
+ */
215
+ unread?: boolean;
216
+ }
217
+
218
+ const Item = ({
219
+ as,
220
+ active,
221
+ dateCreated,
222
+ dropdownOptions,
223
+ dropdownElements,
224
+ isMessage,
225
+ onClick,
226
+ subtitle,
227
+ title,
228
+ unread,
229
+ url,
230
+ }: SubNavigationItemProps) => {
231
+ return (
232
+ <Component
233
+ as={as ?? "a"}
234
+ className={`${styles.subitem}${active ? " active" : ""}${
235
+ unread ? " unread" : ""
236
+ }`}
237
+ onClick={onClick}
238
+ >
239
+ {isMessage && unread && <div className="notification" />}
240
+ <Avatar size={36} subtitle={subtitle} title={title} url={url} />
241
+ {!isMessage && dropdownOptions && (
242
+ <Dropdown
243
+ onChange={() => undefined}
244
+ open="left"
245
+ options={dropdownOptions}
246
+ style={{ marginLeft: "auto" }}
247
+ trigger={
248
+ <EllipsisHorizontal
249
+ iconSize={18}
250
+ size={18}
251
+ fill="var(--color-blue-6)"
252
+ />
253
+ }
254
+ >
255
+ {dropdownElements}
256
+ </Dropdown>
257
+ )}
258
+ {isMessage && dateCreated && (
259
+ <p className="time-stamp">
260
+ {abbrRelativeTimeString(dateCreated, { message: true })}
261
+ </p>
262
+ )}
263
+ </Component>
264
+ );
265
+ };
266
+
267
+ Item.displayName = "SubNavigation.Item";
268
+ SubNavigation.Item = Item;
269
+
270
+ /********************************************************
271
+ * Button - Renders one of the call to actions at the top of the inner drawer navigation
272
+ */
273
+ export interface SubNavigationButtonProps
274
+ extends Omit<ButtonProps, "size" | "buttonColor" | "bold" | "uppercase"> {
275
+ active?: boolean;
276
+ }
277
+
278
+ const SubNavButton = ({
279
+ active,
280
+ children,
281
+ ...rest
282
+ }: SubNavigationButtonProps) => {
283
+ return (
284
+ <Button
285
+ buttonColor="#F5F8FF"
286
+ color="var(--color-blue-3)"
287
+ className="sub-nav-button"
288
+ size="small"
289
+ style={active ? { border: "1px solid var(--color-blue-3)" } : {}}
290
+ uppercase={false}
291
+ {...rest}
292
+ >
293
+ {children}
294
+ </Button>
295
+ );
296
+ };
297
+
298
+ SubNavButton.displayName = "SubNavigation.Button";
299
+ SubNavigation.Button = SubNavButton;
300
+
301
+ /********************************************************
302
+ * Create - Renders the CTA to create something at the bottom of the inner drawer navigation
303
+ */
304
+ export interface SubNavigationCreateProps
305
+ extends Omit<
306
+ ButtonProps,
307
+ "size" | "buttonColor" | "bold" | "uppercase" | "icon"
308
+ > {
309
+ active?: boolean;
310
+ }
311
+
312
+ const SubNavCreate = ({
313
+ active,
314
+ children,
315
+ ...rest
316
+ }: SubNavigationCreateProps) => {
317
+ return (
318
+ <Button
319
+ bold={false}
320
+ buttonColor="var(--color-blue-3)"
321
+ className="create"
322
+ color="var(--color-blue-10)"
323
+ icon={
324
+ <Plus
325
+ iconSize={11}
326
+ fill="#FFFFFF"
327
+ size={29}
328
+ style={{
329
+ borderRadius: "50%",
330
+ border: "1px dashed var(--color-blue-10)",
331
+ }}
332
+ />
333
+ }
334
+ uppercase={false}
335
+ {...rest}
336
+ >
337
+ {children}
338
+ </Button>
339
+ );
340
+ };
341
+
342
+ SubNavCreate.displayName = "SubNavigation.Create";
343
+ SubNavigation.Create = SubNavCreate;
344
+
345
+ /********************************************************
346
+ * Tab - Renders both the tabs in the header and the content of each tab
347
+ */
348
+ export interface SubNavigationTabProps extends React.PropsWithChildren {
349
+ name: string;
350
+ }
351
+
352
+ const Tab = ({ children }: SubNavigationTabProps) => {
353
+ return <>{React.Children.toArray(children)}</>;
354
+ };
355
+
356
+ Tab.displayName = "SubNavigation.Tab";
357
+ SubNavigation.Tab = Tab;
358
+
359
+ /********************************************************
360
+ * Sub Menu - Renders a sub menu that navigates to a new page of the inner drawer navigation
361
+ */
362
+ export interface SubNavigationSubMenuProps extends React.PropsWithChildren {
363
+ title: string;
364
+ }
365
+
366
+ const SubMenu = ({ children }: SubNavigationSubMenuProps) => {
367
+ return <>{React.Children.toArray(children)}</>;
368
+ };
369
+
370
+ SubMenu.displayName = "SubNavigation.SubMenu";
371
+ SubNavigation.SubMenu = SubMenu;
372
+
373
+ /********************************************************
374
+ * Sub Menu Item - Renders a child element of the sub menu
375
+ */
376
+ export interface SubNavigationSubMenuItemProps extends React.PropsWithChildren {
377
+ as?: React.ElementType;
378
+ icon?: React.ReactElement;
379
+ href?: string;
380
+ onClick?: () => void;
381
+ title: string;
382
+ }
383
+
384
+ const SubMenuItem = ({
385
+ as,
386
+ children,
387
+ icon,
388
+ href,
389
+ onClick,
390
+ title,
391
+ }: SubNavigationSubMenuItemProps) => {
392
+ const [open, setOpen] = React.useState(false);
393
+
394
+ const handleClick = () => {
395
+ if (children) {
396
+ setOpen((prev) => !prev);
397
+ }
398
+ if (onClick) {
399
+ onClick();
400
+ }
401
+ };
402
+
403
+ return (
404
+ <>
405
+ <Component
406
+ as={as ?? "div"}
407
+ className={`${styles.submenuitem}`}
408
+ href={href}
409
+ onClick={children || onClick ? handleClick : undefined}
410
+ >
411
+ {icon &&
412
+ React.cloneElement(icon, {
413
+ fill: "var(--color-blue-2)",
414
+ iconSize: 21,
415
+ size: 24,
416
+ })}
417
+ <p>{title}</p>
418
+ {!!children &&
419
+ (open ? (
420
+ <ChevronUp
421
+ fill="var(--color-blue-2)"
422
+ iconSize={12}
423
+ size={24}
424
+ style={{ marginLeft: "auto" }}
425
+ />
426
+ ) : (
427
+ <ChevronDown
428
+ fill="var(--color-blue-2)"
429
+ iconSize={12}
430
+ size={24}
431
+ style={{ marginLeft: "auto" }}
432
+ />
433
+ ))}
434
+ </Component>
435
+ {children && open && <div className="children-wrapper">{children}</div>}
436
+ </>
437
+ );
438
+ };
439
+
440
+ SubMenuItem.displayName = "SubNavigation.SubMenuItem";
441
+ SubNavigation.SubMenuItem = SubMenuItem;
442
+
443
+ export { SubNavigation };
@@ -0,0 +1,15 @@
1
+ export {
2
+ Navigation,
3
+ type NavigationProps,
4
+ type NavigationItemProps,
5
+ } from "./Navigation";
6
+ export {
7
+ SubNavigation,
8
+ type SubNavigationProps,
9
+ type SubNavigationItemProps,
10
+ type SubNavigationButtonProps,
11
+ type SubNavigationCreateProps,
12
+ type SubNavigationTabProps,
13
+ type SubNavigationSubMenuProps,
14
+ type SubNavigationSubMenuItemProps,
15
+ } from "./SubNavigation";
@@ -0,0 +1,49 @@
1
+ @use "@soul-refiner/styles/mixins";
2
+
3
+ .pagination {
4
+ @include mixins.flex($gap: 10px, $align: center, $justify: center);
5
+ padding: 10px 20px;
6
+
7
+ & > * {
8
+ width: 35px;
9
+ height: 35px;
10
+ border-radius: 50%;
11
+ color: var(--color-grey-4);
12
+ &:first-child > svg {
13
+ padding-right: 3px;
14
+ }
15
+ &:last-child > svg {
16
+ padding-left: 3px;
17
+ }
18
+ }
19
+
20
+ & > *:not([class~="break"]) {
21
+ &:not([class~="active"]):hover {
22
+ background-color: var(--color-grey-9);
23
+ color: var(--color-blue-3);
24
+ & > svg {
25
+ fill: var(--color-blue-3);
26
+ }
27
+ }
28
+ }
29
+
30
+ & > [class~="active"] {
31
+ background-color: var(--color-blue-3);
32
+ color: #ffffff;
33
+ }
34
+
35
+ & > [class~="break"] {
36
+ flex-shrink: 0;
37
+ display: flex;
38
+ align-items: center;
39
+ justify-content: center;
40
+ background-color: white;
41
+ }
42
+
43
+ & > [class~="disabled"] {
44
+ pointer-events: none;
45
+ & > svg {
46
+ fill: var(--color-grey-8);
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,115 @@
1
+ import React from "react";
2
+ import { ChevronLeft, ChevronRight } from "@soul-refiner/icons/src";
3
+
4
+ import styles from "./Pagination.module.scss";
5
+
6
+ export interface PaginationProps {
7
+ currentPage: number;
8
+ /**
9
+ * The max number of pages visible from which one may select
10
+ * @default 3
11
+ */
12
+ visibilityInterval: number;
13
+ numPages: number;
14
+ onNavigate: (page: number) => void;
15
+ }
16
+
17
+ export const Pagination = ({
18
+ currentPage,
19
+ visibilityInterval = 3,
20
+ numPages,
21
+ onNavigate,
22
+ }: PaginationProps) => {
23
+ const generatePages = () => {
24
+ if (numPages <= 2 * visibilityInterval)
25
+ return [...Array(numPages + 1).keys()].slice(1).map((num) => num + "");
26
+ else {
27
+ const firstSet = [...Array(visibilityInterval + 1).keys()].slice(1);
28
+ const secondSet = Array.from(
29
+ firstSet,
30
+ (num) => num + numPages - visibilityInterval
31
+ );
32
+ if (currentPage === visibilityInterval + 1) {
33
+ firstSet.push(visibilityInterval + 1);
34
+ }
35
+ if (
36
+ currentPage === numPages - visibilityInterval &&
37
+ numPages - visibilityInterval !== firstSet[firstSet.length - 1]
38
+ ) {
39
+ secondSet.splice(0, 0, numPages - visibilityInterval);
40
+ }
41
+ if (
42
+ currentPage > visibilityInterval + 1 &&
43
+ currentPage < numPages - visibilityInterval
44
+ ) {
45
+ const middleSet: (string | number)[] = [currentPage];
46
+ if (!firstSet.includes(currentPage - 1)) {
47
+ if (firstSet[firstSet.length - 1] === currentPage - 2) {
48
+ firstSet.pop();
49
+ }
50
+ middleSet.splice(0, 0, "break", currentPage - 1);
51
+ }
52
+ if (!secondSet.includes(currentPage + 1)) {
53
+ if (secondSet[0] === currentPage + 2) {
54
+ secondSet.shift();
55
+ }
56
+ middleSet.push(currentPage + 1, "break");
57
+ }
58
+ return [...firstSet, ...middleSet, ...secondSet];
59
+ }
60
+ return [...firstSet, "break", ...secondSet];
61
+ }
62
+ };
63
+
64
+ const handleDecrement = () => {
65
+ if (currentPage > 1) {
66
+ onNavigate(currentPage - 1);
67
+ }
68
+ };
69
+
70
+ const handleIncrement = () => {
71
+ if (currentPage < numPages - 1) {
72
+ onNavigate(currentPage + 1);
73
+ }
74
+ };
75
+
76
+ return (
77
+ <nav className={styles.pagination}>
78
+ <ChevronLeft
79
+ as="button"
80
+ className={currentPage === 1 ? "disabled" : ""}
81
+ fill="var(--color-grey-5)"
82
+ iconSize={18}
83
+ onClick={handleDecrement}
84
+ size={35}
85
+ />
86
+ {generatePages().map((page, index) => {
87
+ if (page === "break") {
88
+ return (
89
+ <div key={"break-" + index.toString(36)} className="break">
90
+ ...
91
+ </div>
92
+ );
93
+ } else {
94
+ return (
95
+ <button
96
+ key={"page-" + index.toString(36)}
97
+ className={page === currentPage ? "active" : ""}
98
+ onClick={() => onNavigate(page as number)}
99
+ >
100
+ {page}
101
+ </button>
102
+ );
103
+ }
104
+ })}
105
+ <ChevronRight
106
+ as="button"
107
+ className={currentPage === numPages ? "disabled" : ""}
108
+ fill="var(--color-grey-5)"
109
+ iconSize={18}
110
+ onClick={handleIncrement}
111
+ size={35}
112
+ />
113
+ </nav>
114
+ );
115
+ };
@@ -0,0 +1 @@
1
+ export { Pagination, type PaginationProps } from "./Pagination";
@@ -0,0 +1,21 @@
1
+ export { Breadcrumbs, type BreadcrumbsProps } from "./Breadcrumbs";
2
+ export { Drawer, type DrawerProps } from "./Drawer";
3
+ export { EditorBar, type EditorBarProps } from "./EditorBar";
4
+ export { MenuTabs, type MenuTabsProps } from "./MenuTabs";
5
+ export {
6
+ Navigation,
7
+ SubNavigation,
8
+ type NavigationProps,
9
+ type NavigationItemProps,
10
+ type SubNavigationProps,
11
+ type SubNavigationItemProps,
12
+ type SubNavigationButtonProps,
13
+ type SubNavigationCreateProps,
14
+ type SubNavigationTabProps,
15
+ type SubNavigationSubMenuProps,
16
+ type SubNavigationSubMenuItemProps,
17
+ } from "./Navigation";
18
+ export {
19
+ Pagination,
20
+ type PaginationProps
21
+ } from "./Pagination";