@soul-refiner/design-system 0.0.14 → 0.0.15

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 +149 -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,177 @@
1
+ import React from "react";
2
+ import styles from "./Drawer.module.scss";
3
+ import { sortChildrenByType } from "@soul-refiner/utils/src";
4
+ import { Close } from "@soul-refiner/icons/src";
5
+
6
+ import { MenuTabs } from "../MenuTabs";
7
+ import { IconHeader, IconHeaderProps } from "../../iconography";
8
+ import { Button, ButtonProps } from "../../actions";
9
+
10
+ export interface DrawerProps extends React.PropsWithChildren {
11
+ activeTab?: number;
12
+ background?: string;
13
+ className?: string;
14
+ heading?: React.ReactNode;
15
+ open?: boolean;
16
+ toggle?: (open: boolean) => void;
17
+ }
18
+
19
+ const Drawer = ({
20
+ activeTab: controlledActiveTab,
21
+ background = "#F2F5F6",
22
+ className,
23
+ children,
24
+ open,
25
+ toggle,
26
+ }: DrawerProps) => {
27
+ const [activeTab, setActiveTab] = React.useState(0);
28
+
29
+ const tabs: string[] = [];
30
+ const _children = sortChildrenByType(children);
31
+
32
+ React.Children.forEach(_children["Drawer.Tab"], (child) => {
33
+ tabs.push((child as { props: { name: string } })?.props.name);
34
+ });
35
+
36
+ const handleTabChange = (index: number) => setActiveTab(index);
37
+
38
+ React.useEffect(() => {
39
+ if (typeof controlledActiveTab === "number") {
40
+ setActiveTab(controlledActiveTab);
41
+ }
42
+ }, [controlledActiveTab]);
43
+
44
+ return (
45
+ <>
46
+ {open && (
47
+ <div
48
+ onClick={() => toggle && toggle(false)}
49
+ className={styles.background}
50
+ />
51
+ )}
52
+ <div
53
+ className={`${styles.drawer} ${open ? "" : "closed"} ${
54
+ className ? " " + className : ""
55
+ }`}
56
+ style={
57
+ {
58
+ "--background-color": background,
59
+ } as React.CSSProperties
60
+ }
61
+ >
62
+ {React.Children.map(_children["Drawer.Heading"], (child) => {
63
+ if (React.isValidElement(child)) {
64
+ return React.cloneElement(child, {
65
+ toggleDrawer: () => toggle && toggle(!open),
66
+ } as Partial<unknown> & React.Attributes);
67
+ }
68
+ return child;
69
+ })}
70
+ <div
71
+ className={`children-wrapper ${
72
+ _children["Drawer.Action"] ? " with-actions" : ""
73
+ }`}
74
+ >
75
+ {_children["General"]}
76
+ {_children["undefined"]}
77
+ {!!tabs.length && (
78
+ <div className="tabs-wrapper">
79
+ <MenuTabs
80
+ activeItem={activeTab}
81
+ onTabClick={handleTabChange}
82
+ tabItems={tabs}
83
+ />
84
+ </div>
85
+ )}
86
+ {_children["Drawer.Tab"] &&
87
+ React.Children.map(
88
+ (_children["Drawer.Tab"][activeTab] as React.ReactElement).props
89
+ .children,
90
+ (child, index) => {
91
+ return React.cloneElement(child, {
92
+ key: "menu-item-" + index.toString(36),
93
+ });
94
+ }
95
+ )}
96
+ </div>
97
+ <div className="actions-wrapper">
98
+ {_children["Drawer.Action"] &&
99
+ _children["Drawer.Action"].map((button, index) => {
100
+ if (
101
+ React.isValidElement(button) &&
102
+ index === _children["Drawer.Action"].length - 1
103
+ ) {
104
+ return React.cloneElement(button, {
105
+ buttonColor: "var(--color-blue-3)",
106
+ color: "var(--color-blue-10)",
107
+ } as Partial<ButtonProps> & React.Attributes);
108
+ }
109
+ return React.cloneElement(button as React.ReactElement, {
110
+ buttonType: "secondary",
111
+ });
112
+ })}
113
+ </div>
114
+ </div>
115
+ </>
116
+ );
117
+ };
118
+
119
+ const Heading = ({
120
+ children,
121
+ toggleDrawer,
122
+ }: {
123
+ children: React.ReactNode;
124
+ toggleDrawer?: () => void;
125
+ }) => (
126
+ <div className={styles.heading}>
127
+ {children}
128
+ <Close
129
+ as="button"
130
+ fill="var(--color-grey-4)"
131
+ iconColor="#FFFFFF"
132
+ iconSize={18}
133
+ onClick={toggleDrawer}
134
+ size={32}
135
+ style={{ borderRadius: "50%" }}
136
+ />
137
+ </div>
138
+ );
139
+
140
+ Heading.displayName = "Drawer.Heading";
141
+ Drawer.Heading = Heading;
142
+
143
+ export interface DrawerTabProps extends React.PropsWithChildren {
144
+ name: string;
145
+ }
146
+
147
+ const Tab = ({ children }: DrawerTabProps) => {
148
+ return <>{React.Children.toArray(children)}</>;
149
+ };
150
+
151
+ Tab.displayName = "Drawer.Tab";
152
+ Drawer.Tab = Tab;
153
+
154
+ export interface DrawerItemProps extends React.PropsWithChildren {
155
+ header: IconHeaderProps;
156
+ }
157
+
158
+ const Item = ({ children, header }: DrawerItemProps) => {
159
+ return (
160
+ <div className={styles.item}>
161
+ {header && <IconHeader {...header} />}
162
+ {children}
163
+ </div>
164
+ );
165
+ };
166
+
167
+ Item.displayName = "Drawer.Item";
168
+ Drawer.Item = Item;
169
+
170
+ const Action = ({ children, ...rest }: Omit<ButtonProps, "size">) => {
171
+ return <Button {...rest}>{children}</Button>;
172
+ };
173
+
174
+ Action.displayName = "Drawer.Action";
175
+ Drawer.Action = Action;
176
+
177
+ export { Drawer };
@@ -0,0 +1 @@
1
+ export { Drawer, type DrawerProps } from "./Drawer";
@@ -0,0 +1,118 @@
1
+ @use "@soul-refiner/styles/_mixins";
2
+
3
+ .editornav {
4
+ position: fixed;
5
+ z-index: 2;
6
+ left: 0;
7
+ right: 0;
8
+ top: 0;
9
+ background-color: #ffffff;
10
+ }
11
+
12
+ .menubarWrapper {
13
+ border-bottom: 1px solid var(--color-grey-9);
14
+ }
15
+
16
+ .menubar {
17
+ @include mixins.flex($gap: 5px, $justify: center);
18
+ max-width: 1200px;
19
+ width: fit-content;
20
+ min-width: 1000px;
21
+ margin: 0 auto;
22
+ padding: 8px;
23
+
24
+ .divider {
25
+ width: 1px;
26
+ height: 32px;
27
+ background-color: var(--color-grey-8);
28
+ margin: 0px 7px;
29
+ }
30
+
31
+ button.icon {
32
+ padding: 6px;
33
+ height: 32px !important;
34
+ width: 34px !important;
35
+ }
36
+
37
+ & > button,
38
+ & > span,
39
+ & > div > button,
40
+ & > div > span,
41
+ & > label > span {
42
+ border-radius: var(--border-radius-tiny);
43
+ border: 1px solid transparent !important;
44
+ height: 32px;
45
+ width: 34px;
46
+
47
+ &:hover:not(&[class~="slate-ToolbarButton-active"]) {
48
+ background-color: var(--color-grey-10) !important;
49
+ border: 1px solid var(--color-grey-8) !important;
50
+ color: var(--color-grey-3);
51
+ }
52
+ &[class~="slate-ToolbarButton-active"] {
53
+ background-color: var(--color-grey-4);
54
+ & > div {
55
+ & > svg > path {
56
+ stroke: var(--color-grey-10);
57
+ }
58
+ &[class~="fill"] > svg > path {
59
+ fill: var(--color-grey-10);
60
+ }
61
+ }
62
+ .nostroke > svg > path {
63
+ stroke: none;
64
+ }
65
+ }
66
+ }
67
+
68
+ [class~="options"] {
69
+ z-index: 5;
70
+ [class~="selected"] {
71
+ background-color: var(--color-grey-3);
72
+ color: #ffffff;
73
+ & > button > svg {
74
+ fill: #ffffff;
75
+ }
76
+ }
77
+ div {
78
+ padding: 5px 0px;
79
+ }
80
+ }
81
+ }
82
+
83
+ .buttonoptions {
84
+ margin-bottom: 16px;
85
+ cursor: pointer;
86
+ &:last-of-type {
87
+ margin-bottom: 0px;
88
+ }
89
+ }
90
+
91
+ .option {
92
+ cursor: pointer;
93
+ display: flex;
94
+ justify-content: center;
95
+ align-items: center;
96
+ }
97
+
98
+ .moredropdown {
99
+ @include mixins.flex($align: center, $gap: 16px);
100
+ p {
101
+ line-height: 28px;
102
+ }
103
+ margin-bottom: 16px;
104
+ cursor: pointer;
105
+ &:last-of-type {
106
+ margin-bottom: 0px;
107
+ }
108
+ }
109
+
110
+ .inputContainer {
111
+ position: relative;
112
+ input {
113
+ display: none;
114
+ }
115
+ }
116
+ .audio {
117
+ cursor: pointer;
118
+ }
@@ -0,0 +1,416 @@
1
+ import React from "react";
2
+ import ReactTooltip from "react-tooltip";
3
+ import {
4
+ focusEditor,
5
+ getPluginType,
6
+ getPreventDefaultHandler,
7
+ ImageToolbarButton,
8
+ insertImage,
9
+ insertNodes,
10
+ LinkToolbarButton,
11
+ MarkToolbarButton,
12
+ setMarks,
13
+ toggleIndentList,
14
+ toggleNodeType,
15
+ ToolbarButton,
16
+ usePlateEditorRef,
17
+ usePlateEditorState,
18
+ } from "@udecode/plate";
19
+
20
+ import styles from "./EditorBar.module.scss";
21
+ import {
22
+ Audio,
23
+ BlockQuote,
24
+ Bold,
25
+ Bookmark,
26
+ Code,
27
+ CurrencyUSD,
28
+ Highlighter,
29
+ Image,
30
+ Italic,
31
+ Link,
32
+ OrderedList,
33
+ Note,
34
+ Preferences,
35
+ QA,
36
+ Redo,
37
+ Strikethrough,
38
+ Undo,
39
+ Underline,
40
+ UnorderedList,
41
+ Video,
42
+ } from "@soul-refiner/icons/src";
43
+
44
+ import {
45
+ EditorContext,
46
+ BUTTON_SUBSCRIBE,
47
+ ELEMENT_BLOCKQUOTE,
48
+ ELEMENT_BUTTON,
49
+ ELEMENT_DEFAULT,
50
+ ELEMENT_H2,
51
+ ELEMENT_PARAGRAPH,
52
+ ELEMENT_PAYWALL,
53
+ ELEMENT_QA,
54
+ MARK_BOLD,
55
+ MARK_CODE,
56
+ MARK_ITALIC,
57
+ MARK_HIGHLIGHT,
58
+ MARK_STRIKETHROUGH,
59
+ MARK_SUBSCRIPT,
60
+ MARK_SUPERSCRIPT,
61
+ MARK_UNDERLINE,
62
+ } from "../../editor";
63
+ import { Dropdown } from "../../actions";
64
+ import { Modal } from "../../surfaces";
65
+
66
+ import {
67
+ AlignmentDropdown,
68
+ ButtonModal,
69
+ FontDropdown,
70
+ MoreDropdown,
71
+ OutlineDropdown,
72
+ TextTypeDropdown,
73
+ VideoModal,
74
+ } from "./components";
75
+
76
+ export interface EditorBarProps {
77
+ buttonsMenu?: boolean;
78
+ editable: boolean;
79
+ mediaMenu?: boolean;
80
+ moreMenu?: boolean;
81
+ notes?: boolean;
82
+ }
83
+
84
+ export const EditorBar = ({
85
+ buttonsMenu = true,
86
+ editable,
87
+ mediaMenu = true,
88
+ moreMenu = true,
89
+ notes = false,
90
+ }: EditorBarProps) => {
91
+ const { handleUploadImage, pageName, outline } =
92
+ React.useContext(EditorContext);
93
+ const editorRef = usePlateEditorRef("main");
94
+ const stateEditor = usePlateEditorState();
95
+ const audioRef = React.useRef<HTMLInputElement>(null);
96
+ const imageRef = React.useRef<HTMLInputElement>(null);
97
+ const videoRef = React.useRef<HTMLInputElement>(null);
98
+
99
+ const handleAudioChange = async (event: React.FormEvent) => {
100
+ const file = (event.target as HTMLInputElement)?.files?.[0];
101
+ if (!file) return;
102
+ /**
103
+ * TODO: Insert audio component
104
+ */
105
+ };
106
+
107
+ const handleBlockquote = (event: React.MouseEvent) => {
108
+ getPreventDefaultHandler(toggleNodeType, stateEditor, {
109
+ activeType: ELEMENT_BLOCKQUOTE,
110
+ })(event);
111
+ };
112
+
113
+ const handleImageChange = async (event: React.FormEvent) => {
114
+ const file = (event.target as HTMLInputElement)?.files?.[0];
115
+ if (!file) return;
116
+ const imageurl = await handleUploadImage(file);
117
+ if (imageurl) {
118
+ insertImage(editorRef, imageurl);
119
+ }
120
+ };
121
+
122
+ const handleFont = (value: string) => {
123
+ const type = getPluginType(editorRef, "fontSize");
124
+ focusEditor(editorRef);
125
+ setMarks(stateEditor, { [type]: `${value}px` });
126
+ };
127
+
128
+ const handleOrderedList = (event: any) => {
129
+ event.preventDefault();
130
+ toggleIndentList(editorRef, {
131
+ listStyleType: "decimals",
132
+ });
133
+ };
134
+
135
+ const handleUnorderedList = (event: any) => {
136
+ event.preventDefault();
137
+ toggleIndentList(editorRef, {
138
+ listStyleType: "disc",
139
+ });
140
+ };
141
+
142
+ const handleVideoChange = async (event: React.FormEvent) => {
143
+ const file = (event.target as HTMLInputElement)?.files?.[0];
144
+ if (!file) return;
145
+ /**
146
+ * TODO: Insert video component
147
+ */
148
+ };
149
+
150
+ const handlePaywall = () => {
151
+ insertNodes(editorRef, [
152
+ {
153
+ type: ELEMENT_PAYWALL,
154
+ children: [
155
+ {
156
+ type: ELEMENT_H2,
157
+ children: [
158
+ {
159
+ text: "Keep reading with a paid subscription",
160
+ },
161
+ ],
162
+ },
163
+ {
164
+ type: ELEMENT_PARAGRAPH,
165
+ children: [
166
+ {
167
+ text: "Subscribe to ",
168
+ },
169
+ {
170
+ text: pageName,
171
+ italic: true,
172
+ },
173
+ {
174
+ text: " to keep reading this content.",
175
+ },
176
+ ],
177
+ },
178
+ {
179
+ type: ELEMENT_BUTTON,
180
+ buttonType: BUTTON_SUBSCRIBE,
181
+ children: [
182
+ {
183
+ text: "Get Access",
184
+ },
185
+ ],
186
+ },
187
+ ],
188
+ },
189
+ {
190
+ type: ELEMENT_DEFAULT,
191
+ children: [
192
+ {
193
+ text: "",
194
+ },
195
+ ],
196
+ },
197
+ ]);
198
+ focusEditor(editorRef);
199
+ };
200
+
201
+ const handleQA = () => {
202
+ insertNodes(editorRef, {
203
+ type: ELEMENT_QA,
204
+ children: [
205
+ {
206
+ type: ELEMENT_PARAGRAPH,
207
+ children: [
208
+ {
209
+ text: "Ask your question here...",
210
+ },
211
+ ],
212
+ },
213
+ ],
214
+ });
215
+ };
216
+
217
+ return (
218
+ <div className={styles.editornav}>
219
+ <ReactTooltip place="top" type="dark" effect="solid" html />
220
+ <div className={styles.menubarWrapper}>
221
+ <nav
222
+ aria-label="editor-navigation"
223
+ className={styles.menubar}
224
+ data-testid="editor-bar-top"
225
+ >
226
+ {outline && <OutlineDropdown editable={editable} outline={outline} />}
227
+ {!editable && (
228
+ <>
229
+ <Dropdown
230
+ onChange={() => undefined}
231
+ trigger={
232
+ <Highlighter
233
+ as="button"
234
+ size={32}
235
+ iconSize={22}
236
+ fill={"var(--color-grey-6)"}
237
+ />
238
+ }
239
+ ></Dropdown>
240
+ <Dropdown
241
+ onChange={() => undefined}
242
+ trigger={
243
+ <Bookmark
244
+ as="button"
245
+ size={32}
246
+ iconSize={18}
247
+ fill={"var(--color-grey-6)"}
248
+ />
249
+ }
250
+ ></Dropdown>
251
+ <Modal>
252
+ <Modal.Trigger>
253
+ <Note
254
+ as="button"
255
+ size={32}
256
+ iconSize={20}
257
+ fill="var(--color-grey-6)"
258
+ />
259
+ </Modal.Trigger>
260
+ </Modal>
261
+ <Modal>
262
+ <Modal.Trigger>
263
+ <Preferences
264
+ as="button"
265
+ size={32}
266
+ iconSize={22}
267
+ fill="var(--color-grey-6)"
268
+ />
269
+ </Modal.Trigger>
270
+ </Modal>
271
+ </>
272
+ )}
273
+ </nav>
274
+ </div>
275
+ <div className={styles.menubarWrapper}>
276
+ <nav
277
+ aria-label="editor-navigation"
278
+ className={styles.menubar}
279
+ data-testid="editor-bar"
280
+ >
281
+ <Undo
282
+ as="button"
283
+ data-tip="Undo"
284
+ fill={"var(--color-grey-1)"}
285
+ onClick={() => editorRef.undo()}
286
+ size={32}
287
+ iconSize={22}
288
+ />
289
+ <Redo
290
+ as="button"
291
+ data-tip="Redo"
292
+ fill={"var(--color-grey-1)"}
293
+ onClick={() => editorRef.redo()}
294
+ size={32}
295
+ iconSize={22}
296
+ />
297
+ <div className={styles.divider} />
298
+ <TextTypeDropdown editorRef={editorRef} />
299
+ <div className={styles.divider} />
300
+ <FontDropdown editorRef={editorRef} onChange={handleFont} />
301
+ <div data-tip="Bold">
302
+ <MarkToolbarButton
303
+ type={getPluginType(editorRef, MARK_BOLD)}
304
+ icon={<Bold fill={"var(--color-grey-1)"} />}
305
+ />
306
+ </div>
307
+ <div data-tip="Italic">
308
+ <MarkToolbarButton
309
+ type={getPluginType(editorRef, MARK_ITALIC)}
310
+ icon={<Italic fill={"var(--color-grey-1)"} />}
311
+ />
312
+ </div>
313
+ <div data-tip="Strikethrough">
314
+ <MarkToolbarButton
315
+ type={getPluginType(editorRef, MARK_STRIKETHROUGH)}
316
+ icon={<Strikethrough fill={"var(--color-grey-1)"} />}
317
+ />
318
+ </div>
319
+ <div data-tip="Underline">
320
+ <MarkToolbarButton
321
+ type={getPluginType(editorRef, MARK_UNDERLINE)}
322
+ icon={
323
+ <Underline
324
+ fill={"var(--color-grey-1)"}
325
+ className="fill"
326
+ size={32}
327
+ iconSize={22}
328
+ />
329
+ }
330
+ />
331
+ </div>
332
+ <div data-tip="Inline code">
333
+ <MarkToolbarButton
334
+ type={getPluginType(editorRef, MARK_CODE)}
335
+ icon={
336
+ <Code fill={"var(--color-grey-1)"} size={32} iconSize={22} />
337
+ }
338
+ />
339
+ </div>
340
+ <AlignmentDropdown stateEditor={stateEditor} editorRef={editorRef} />
341
+ <div className={styles.divider} />
342
+ <div data-tip="Link">
343
+ <LinkToolbarButton
344
+ icon={
345
+ <Link
346
+ fill="var(--color-grey-1)"
347
+ className={`fill ${styles.nostroke}`}
348
+ />
349
+ }
350
+ />
351
+ </div>
352
+ <label
353
+ data-tip="Insert image"
354
+ onChange={handleImageChange}
355
+ className={styles.inputContainer}
356
+ >
357
+ <ImageToolbarButton
358
+ icon={<Image fill="var(--color-grey-1)" />}
359
+ onMouseDown={() => imageRef.current?.click()}
360
+ />
361
+ <input accept="image/*" type="file" ref={imageRef} />
362
+ </label>
363
+ <VideoModal editorRef={editorRef} />
364
+ <div
365
+ className={`${styles.inputContainer} ${styles.audio}`}
366
+ data-tip="Insert Audio"
367
+ >
368
+ <Audio
369
+ as="span"
370
+ fill="var(--color-grey-1)"
371
+ size={32}
372
+ iconSize={18}
373
+ />
374
+ </div>
375
+ <span
376
+ className={styles.option}
377
+ data-tip="Blockquote"
378
+ onClick={handleBlockquote}
379
+ >
380
+ <BlockQuote fill="var(--color-grey-4)" size={32} iconSize={18} />
381
+ </span>
382
+ <ButtonModal editorRef={editorRef} pageName={pageName} />
383
+ <span
384
+ className={styles.option}
385
+ data-tip="Insert Q&A"
386
+ onClick={handleQA}
387
+ >
388
+ <QA fill="var(--color-grey-4)" />
389
+ </span>
390
+ <span
391
+ className={styles.option}
392
+ data-tip="Insert Paywall"
393
+ onClick={handlePaywall}
394
+ >
395
+ <CurrencyUSD fill="var(--color-grey-4)" />
396
+ </span>
397
+ <div className={styles.divider} />
398
+ <div data-tip="Unordered List">
399
+ <ToolbarButton
400
+ onMouseDown={handleUnorderedList}
401
+ icon={<UnorderedList fill="var(--color-grey-1)" />}
402
+ />
403
+ </div>
404
+ <div data-tip="Ordered List">
405
+ <ToolbarButton
406
+ onMouseDown={handleOrderedList}
407
+ icon={<OrderedList fill="var(--color-grey-1)" />}
408
+ />
409
+ </div>
410
+ <div className={styles.divider} />
411
+ <MoreDropdown editorRef={editorRef} stateEditor={stateEditor} />
412
+ </nav>
413
+ </div>
414
+ </div>
415
+ );
416
+ };