@churchapps/apphelper 0.1.2 → 0.1.4

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 (193) hide show
  1. package/.eslintignore +3 -3
  2. package/.eslintrc.json +22 -22
  3. package/LICENSE +21 -21
  4. package/README.md +22 -22
  5. package/dist/components/FormSubmissionEdit.d.ts.map +1 -1
  6. package/dist/components/FormSubmissionEdit.js +2 -9
  7. package/dist/components/FormSubmissionEdit.js.map +1 -1
  8. package/dist/components/QuestionEdit.js +2 -2
  9. package/dist/components/QuestionEdit.js.map +1 -1
  10. package/dist/components/markdownEditor/editor.css +787 -787
  11. package/dist/components/markdownEditor/images/icons/arrow-clockwise.svg +3 -3
  12. package/dist/components/markdownEditor/images/icons/arrow-counterclockwise.svg +3 -3
  13. package/dist/components/markdownEditor/images/icons/chat-square-quote.svg +3 -3
  14. package/dist/components/markdownEditor/images/icons/chevron-down.svg +2 -2
  15. package/dist/components/markdownEditor/images/icons/code.svg +2 -2
  16. package/dist/components/markdownEditor/images/icons/journal-code.svg +4 -4
  17. package/dist/components/markdownEditor/images/icons/journal-text.svg +4 -4
  18. package/dist/components/markdownEditor/images/icons/justify.svg +2 -2
  19. package/dist/components/markdownEditor/images/icons/link.svg +3 -3
  20. package/dist/components/markdownEditor/images/icons/list-ol.svg +3 -3
  21. package/dist/components/markdownEditor/images/icons/list-ul.svg +2 -2
  22. package/dist/components/markdownEditor/images/icons/pencil-fill.svg +2 -2
  23. package/dist/components/markdownEditor/images/icons/text-center.svg +2 -2
  24. package/dist/components/markdownEditor/images/icons/text-left.svg +2 -2
  25. package/dist/components/markdownEditor/images/icons/text-paragraph.svg +2 -2
  26. package/dist/components/markdownEditor/images/icons/text-right.svg +2 -2
  27. package/dist/components/markdownEditor/images/icons/type-bold.svg +2 -2
  28. package/dist/components/markdownEditor/images/icons/type-h1.svg +2 -2
  29. package/dist/components/markdownEditor/images/icons/type-h2.svg +2 -2
  30. package/dist/components/markdownEditor/images/icons/type-h3.svg +2 -2
  31. package/dist/components/markdownEditor/images/icons/type-h4.svg +12 -12
  32. package/dist/components/markdownEditor/images/icons/type-italic.svg +2 -2
  33. package/dist/components/markdownEditor/images/icons/type-strikethrough.svg +2 -2
  34. package/dist/components/markdownEditor/images/icons/type-underline.svg +2 -2
  35. package/dist/pageComponents/components/SelectChurchRegister.js +3 -3
  36. package/dist/pageComponents/components/SelectChurchRegister.js.map +1 -1
  37. package/package.json +85 -85
  38. package/src/components/CreatePerson.tsx +80 -80
  39. package/src/components/DisplayBox.tsx +68 -68
  40. package/src/components/ErrorMessages.tsx +26 -26
  41. package/src/components/ExportLink.tsx +67 -67
  42. package/src/components/FloatingSupport.tsx +16 -16
  43. package/src/components/FormSubmissionEdit.tsx +120 -129
  44. package/src/components/HelpIcon.tsx +10 -10
  45. package/src/components/ImageEditor.tsx +126 -126
  46. package/src/components/InputBox.tsx +73 -73
  47. package/src/components/Loading.tsx +29 -29
  48. package/src/components/PersonAdd.tsx +75 -75
  49. package/src/components/QuestionEdit.tsx +63 -63
  50. package/src/components/SmallButton.tsx +39 -39
  51. package/src/components/SupportModal.tsx +26 -26
  52. package/src/components/TabPanel.tsx +34 -34
  53. package/src/components/gallery/GalleryModal.tsx +102 -102
  54. package/src/components/gallery/StockPhotos.tsx +74 -74
  55. package/src/components/gallery/index.ts +1 -1
  56. package/src/components/iconPicker/IconNamesList.ts +2240 -2240
  57. package/src/components/iconPicker/IconPicker.tsx +153 -153
  58. package/src/components/index.tsx +24 -24
  59. package/src/components/markdownEditor/Editor.tsx +132 -132
  60. package/src/components/markdownEditor/MarkdownEditor.tsx +16 -16
  61. package/src/components/markdownEditor/MarkdownModal.tsx +46 -46
  62. package/src/components/markdownEditor/MarkdownPreview.tsx +14 -14
  63. package/src/components/markdownEditor/editor.css +787 -787
  64. package/src/components/markdownEditor/images/icons/arrow-clockwise.svg +3 -3
  65. package/src/components/markdownEditor/images/icons/arrow-counterclockwise.svg +3 -3
  66. package/src/components/markdownEditor/images/icons/chat-square-quote.svg +3 -3
  67. package/src/components/markdownEditor/images/icons/chevron-down.svg +2 -2
  68. package/src/components/markdownEditor/images/icons/code.svg +2 -2
  69. package/src/components/markdownEditor/images/icons/journal-code.svg +4 -4
  70. package/src/components/markdownEditor/images/icons/journal-text.svg +4 -4
  71. package/src/components/markdownEditor/images/icons/justify.svg +2 -2
  72. package/src/components/markdownEditor/images/icons/link.svg +3 -3
  73. package/src/components/markdownEditor/images/icons/list-ol.svg +3 -3
  74. package/src/components/markdownEditor/images/icons/list-ul.svg +2 -2
  75. package/src/components/markdownEditor/images/icons/pencil-fill.svg +2 -2
  76. package/src/components/markdownEditor/images/icons/text-center.svg +2 -2
  77. package/src/components/markdownEditor/images/icons/text-left.svg +2 -2
  78. package/src/components/markdownEditor/images/icons/text-paragraph.svg +2 -2
  79. package/src/components/markdownEditor/images/icons/text-right.svg +2 -2
  80. package/src/components/markdownEditor/images/icons/type-bold.svg +2 -2
  81. package/src/components/markdownEditor/images/icons/type-h1.svg +2 -2
  82. package/src/components/markdownEditor/images/icons/type-h2.svg +2 -2
  83. package/src/components/markdownEditor/images/icons/type-h3.svg +2 -2
  84. package/src/components/markdownEditor/images/icons/type-h4.svg +12 -12
  85. package/src/components/markdownEditor/images/icons/type-italic.svg +2 -2
  86. package/src/components/markdownEditor/images/icons/type-strikethrough.svg +2 -2
  87. package/src/components/markdownEditor/images/icons/type-underline.svg +2 -2
  88. package/src/components/markdownEditor/index.ts +2 -2
  89. package/src/components/markdownEditor/plugins/AutoLinkPlugin.tsx +35 -35
  90. package/src/components/markdownEditor/plugins/ControlledEditorPlugin.tsx +24 -24
  91. package/src/components/markdownEditor/plugins/ListMaxIndentLevelPlugin.tsx +68 -68
  92. package/src/components/markdownEditor/plugins/MarkdownTransformers.ts +106 -106
  93. package/src/components/markdownEditor/plugins/ReadOnlyPlugin.tsx +15 -15
  94. package/src/components/markdownEditor/plugins/ToolbarPlugin.tsx +401 -401
  95. package/src/components/markdownEditor/plugins/customLink/CustomLinkNode.tsx +224 -224
  96. package/src/components/markdownEditor/plugins/customLink/CustomLinkNodePlugin.tsx +32 -32
  97. package/src/components/markdownEditor/plugins/customLink/CustomLinkNodeTransformer.tsx +102 -102
  98. package/src/components/markdownEditor/plugins/customLink/FloatingLinkEditor.tsx +243 -243
  99. package/src/components/markdownEditor/plugins/customLink/FloatingLinkEditor.types.ts +11 -11
  100. package/src/components/markdownEditor/plugins/emoji/EmojiNode.tsx +95 -95
  101. package/src/components/markdownEditor/plugins/emoji/EmojiNodeTransform.ts +41 -41
  102. package/src/components/markdownEditor/plugins/emoji/EmojiPickerPlugin.tsx +152 -152
  103. package/src/components/markdownEditor/plugins/emoji/EmojisPlugin.tsx +65 -65
  104. package/src/components/markdownEditor/plugins/index.ts +6 -6
  105. package/src/components/markdownEditor/theme.ts +65 -65
  106. package/src/components/notes/AddNote.tsx +90 -90
  107. package/src/components/notes/Conversation.tsx +82 -82
  108. package/src/components/notes/Conversations.tsx +58 -58
  109. package/src/components/notes/NewConversation.tsx +78 -78
  110. package/src/components/notes/Note.tsx +44 -44
  111. package/src/components/notes/Notes.tsx +68 -68
  112. package/src/components/notes/index.ts +5 -5
  113. package/src/components/reporting/ChartReport.tsx +98 -98
  114. package/src/components/reporting/ReportFilter.tsx +54 -54
  115. package/src/components/reporting/ReportFilterField.tsx +160 -160
  116. package/src/components/reporting/ReportOutput.tsx +79 -79
  117. package/src/components/reporting/ReportWithFilter.tsx +70 -70
  118. package/src/components/reporting/TableReport.tsx +57 -57
  119. package/src/components/reporting/TreeReport.tsx +111 -111
  120. package/src/components/reporting/index.ts +4 -4
  121. package/src/components/wrapper/AppList.tsx +20 -20
  122. package/src/components/wrapper/ChurchList.tsx +22 -22
  123. package/src/components/wrapper/Drawers.tsx +60 -60
  124. package/src/components/wrapper/NavItem.tsx +41 -41
  125. package/src/components/wrapper/NewPrivateMessage.tsx +103 -103
  126. package/src/components/wrapper/NotificationMenu.tsx +85 -85
  127. package/src/components/wrapper/Notifications.tsx +50 -50
  128. package/src/components/wrapper/PrivateMessageDetails.tsx +23 -23
  129. package/src/components/wrapper/PrivateMessages.tsx +87 -87
  130. package/src/components/wrapper/SiteWrapper.tsx +96 -96
  131. package/src/components/wrapper/TabPanel.tsx +30 -30
  132. package/src/components/wrapper/UserMenu.tsx +106 -106
  133. package/src/components/wrapper/index.tsx +5 -5
  134. package/src/donationComponents/DonationPage.tsx +136 -136
  135. package/src/donationComponents/components/BankForm.tsx +159 -159
  136. package/src/donationComponents/components/CardForm.tsx +104 -104
  137. package/src/donationComponents/components/DonationForm.tsx +235 -235
  138. package/src/donationComponents/components/FundDonation.tsx +49 -49
  139. package/src/donationComponents/components/FundDonations.tsx +39 -39
  140. package/src/donationComponents/components/NonAuthDonation.tsx +31 -31
  141. package/src/donationComponents/components/NonAuthDonationInner.tsx +259 -259
  142. package/src/donationComponents/components/PaymentMethods.tsx +135 -135
  143. package/src/donationComponents/components/RecurringDonations.tsx +121 -121
  144. package/src/donationComponents/components/RecurringDonationsEdit.tsx +93 -93
  145. package/src/donationComponents/components/index.tsx +9 -9
  146. package/src/donationComponents/index.ts +3 -3
  147. package/src/donationComponents/modals/DonationPreviewModal.tsx +66 -66
  148. package/src/helpers/AnalyticsHelper.ts +33 -33
  149. package/src/helpers/ApiHelper.ts +125 -125
  150. package/src/helpers/AppearanceHelper.ts +69 -69
  151. package/src/helpers/ArrayHelper.ts +81 -81
  152. package/src/helpers/CommonEnvironmentHelper.ts +80 -80
  153. package/src/helpers/CurrencyHelper.ts +10 -10
  154. package/src/helpers/DateHelper.ts +108 -108
  155. package/src/helpers/DonationHelper.ts +26 -26
  156. package/src/helpers/ErrorHelper.ts +36 -36
  157. package/src/helpers/EventHelper.ts +52 -52
  158. package/src/helpers/FileHelper.ts +31 -31
  159. package/src/helpers/PersonHelper.ts +60 -60
  160. package/src/helpers/SocketHelper.ts +76 -76
  161. package/src/helpers/Themes.ts +14 -14
  162. package/src/helpers/UniqueIdHelper.ts +36 -36
  163. package/src/helpers/UserHelper.ts +59 -59
  164. package/src/helpers/createEmotionCache.ts +17 -17
  165. package/src/helpers/index.ts +18 -18
  166. package/src/hooks/index.ts +1 -1
  167. package/src/hooks/useMountedState.ts +16 -16
  168. package/src/index.ts +6 -6
  169. package/src/interfaces/Access.ts +24 -24
  170. package/src/interfaces/Attendance.ts +8 -8
  171. package/src/interfaces/Content.ts +10 -10
  172. package/src/interfaces/Doing.ts +24 -24
  173. package/src/interfaces/Donation.ts +45 -45
  174. package/src/interfaces/Error.ts +17 -17
  175. package/src/interfaces/Membership.ts +51 -51
  176. package/src/interfaces/Messaging.ts +21 -21
  177. package/src/interfaces/Permissions.ts +68 -68
  178. package/src/interfaces/Reporting.ts +7 -7
  179. package/src/interfaces/UserContextInterface.ts +13 -13
  180. package/src/interfaces/index.ts +13 -13
  181. package/src/pageComponents/LoginPage.tsx +244 -244
  182. package/src/pageComponents/LogoutPage.tsx +28 -28
  183. package/src/pageComponents/components/Forgot.tsx +79 -79
  184. package/src/pageComponents/components/Login.tsx +54 -54
  185. package/src/pageComponents/components/LoginSetPassword.tsx +63 -63
  186. package/src/pageComponents/components/Register.tsx +107 -107
  187. package/src/pageComponents/components/SelectChurchModal.tsx +41 -41
  188. package/src/pageComponents/components/SelectChurchRegister.tsx +88 -88
  189. package/src/pageComponents/components/SelectChurchSearch.tsx +69 -69
  190. package/src/pageComponents/components/SelectableChurch.tsx +38 -38
  191. package/src/pageComponents/index.ts +3 -3
  192. package/tsconfig.json +34 -34
  193. package/tslint.json +14 -14
@@ -1,243 +1,243 @@
1
- import React, { useCallback, useRef, FC, useEffect } from "react";
2
- import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
3
- import { mergeRegister } from "@lexical/utils";
4
- import { $isCustomLinkNode } from "./CustomLinkNode";
5
- import { $getSelection, SELECTION_CHANGE_COMMAND, $isRangeSelection, $getNodeByKey } from "lexical";
6
- import { TOGGLE_CUSTOM_LINK_NODE_COMMAND } from "./CustomLinkNode";
7
- import { FloatingLinkEditorProps } from "./FloatingLinkEditor.types";
8
- import { getSelectedNode } from "../ToolbarPlugin";
9
- import { FormControl, InputLabel, Select, MenuItem, TextField, Button } from "@mui/material";
10
-
11
- const positionEditorElement = (editor: HTMLElement, rect: DOMRect | null) => {
12
- if (rect === null) {
13
- editor.style.opacity = "0";
14
- editor.style.top = "-1000px";
15
- editor.style.left = "-1000px";
16
- } else {
17
- editor.style.opacity = "1";
18
- editor.style.top = `${rect.top + rect.height + window.pageYOffset + 10}px`;
19
- editor.style.left = `${
20
- rect.left + window.pageXOffset - editor.offsetWidth / 2 + rect.width / 2 < 0
21
- ? 0
22
- : rect.left
23
- + window.pageXOffset
24
- - editor.offsetWidth / 2
25
- + rect.width / 2
26
- }px`;
27
- }
28
- };
29
-
30
- const LowPriority = 1;
31
-
32
- const FloatingLinkEditor: FC<FloatingLinkEditorProps> = ({
33
- linkUrl,
34
- setLinkUrl,
35
- classNamesList,
36
- setClassNamesList,
37
- targetAttribute,
38
- setTargetAttribute,
39
- selectedElementKey
40
- }) => {
41
- const [editor] = useLexicalComposerContext();
42
-
43
- const editorRef = useRef(null);
44
-
45
- const mouseDownRef = useRef(false);
46
-
47
- /*
48
- const [lastSelection, setLastSelection] = useState<
49
- GridSelection | NodeSelection | RangeSelection | null
50
- >(null);
51
- */
52
-
53
- const updateLinkEditor = useCallback(() => {
54
- const selection = $getSelection();
55
- if ($isRangeSelection(selection)) {
56
- const node = getSelectedNode(selection);
57
-
58
- const parent = node.getParent();
59
- if ($isCustomLinkNode(parent)) {
60
- const _url = editor.getElementByKey(parent.__key)?.getAttribute("href");
61
- if (_url) {
62
- setLinkUrl(_url);
63
- }
64
- } else if ($isCustomLinkNode(node)) {
65
- const _url = editor.getElementByKey(node.__key)?.getAttribute("href");
66
- if (_url) {
67
- setLinkUrl(_url);
68
- }
69
- }
70
- }
71
- const editorElem = editorRef.current;
72
- const nativeSelection = window.getSelection();
73
-
74
- if (!nativeSelection) return;
75
-
76
- const activeElement = document.activeElement;
77
-
78
- if (editorElem === null) {
79
- return;
80
- }
81
-
82
- const rootElement = editor.getRootElement();
83
- if (
84
- selection !== null
85
- && !nativeSelection?.isCollapsed
86
- && rootElement !== null
87
- && rootElement.contains(nativeSelection.anchorNode)
88
- ) {
89
- const domRange = nativeSelection.getRangeAt(0);
90
- let rect;
91
- if (nativeSelection.anchorNode === rootElement) {
92
- let inner: Element | HTMLElement = rootElement;
93
- while (inner.firstElementChild != null) {
94
- inner = inner.firstElementChild;
95
- }
96
- rect = inner.getBoundingClientRect();
97
- } else {
98
- rect = domRange.getBoundingClientRect();
99
- }
100
-
101
- if (!mouseDownRef.current) {
102
- positionEditorElement(editorElem, rect);
103
- }
104
- //setLastSelection(selection);
105
- } else if (!activeElement || activeElement.className !== "link-input") {
106
- positionEditorElement(editorElem, null);
107
- //setLastSelection(null);
108
- }
109
-
110
- return true;
111
- }, [editor]); //eslint-disable-line
112
-
113
- useEffect(() => (
114
- mergeRegister(
115
- editor.registerUpdateListener(({ editorState }) => {
116
- editorState.read(() => {
117
- updateLinkEditor();
118
- });
119
- }),
120
-
121
- editor.registerCommand(
122
- SELECTION_CHANGE_COMMAND,
123
- () => {
124
- editor.getEditorState().read(() => {
125
- updateLinkEditor();
126
- });
127
- return true;
128
- },
129
- LowPriority
130
- )
131
- )
132
- ), [editor, updateLinkEditor]);
133
-
134
- useEffect(() => {
135
- editor.getEditorState().read(() => {
136
- updateLinkEditor();
137
- });
138
- }, [editor, updateLinkEditor]);
139
-
140
- useEffect(() => {
141
- editor.getEditorState().read(() => {
142
- updateLinkEditor();
143
- });
144
- }, []); //eslint-disable-line
145
-
146
- const variants = ["Primary", "Secondary", "Success", "Danger", "Warning", "Info", "Light", "Dark"];
147
- const sizes = ["Small", "Medium", "Large"];
148
- let appearance = "link";
149
- if (classNamesList[0].indexOf("btn")>-1) appearance="btn";
150
- if (classNamesList[0].indexOf("btn-block")>-1) appearance="btn btn-block";
151
-
152
- const handleSave = () => {
153
- editor.dispatchCommand(TOGGLE_CUSTOM_LINK_NODE_COMMAND, {
154
- url: linkUrl,
155
- classNames: classNamesList,
156
- target: targetAttribute
157
- });
158
-
159
- editor.update(() => {
160
- if (!selectedElementKey) return;
161
-
162
- const selectedNode = $getNodeByKey(selectedElementKey);
163
-
164
- selectedNode?.selectEnd();
165
- });
166
- }
167
-
168
- return (
169
- <div ref={editorRef} className="link-editor">
170
-
171
- <TextField label="Url" value={linkUrl} onChange={e => { setLinkUrl(e.target.value) }} fullWidth size="small" />
172
-
173
- <FormControl fullWidth>
174
- <InputLabel>Appearance</InputLabel>
175
- <Select name="classNames" fullWidth label="Appearance" size="small" value={appearance} onChange={(e) => {
176
- let className = "";
177
- if (e.target.value.toString()!=="link") className = e.target.value.toString();
178
- setClassNamesList([className, "btn-primary", "btn-medium"])
179
- }}>
180
- <MenuItem value="link">Standard Link</MenuItem>
181
- <MenuItem value="btn">Button</MenuItem>
182
- <MenuItem value="btn btn-block">Full Width Button</MenuItem>
183
- </Select>
184
- </FormControl>
185
-
186
- {appearance!=="link"
187
- && <div>
188
- <FormControl fullWidth>
189
- <InputLabel>Variant</InputLabel>
190
- <Select name="classNames" fullWidth label="Variant" size="small" value={ classNamesList[1] } onChange={(e) => {
191
- const newArray = [...classNamesList];
192
- let index = 0;
193
- newArray.forEach((item, i) => {
194
- variants.forEach((element) => {
195
- if (item.includes(element.toLowerCase())) {
196
- index = i;
197
- };
198
- })
199
- })
200
- newArray.splice(index, 1, e.target.value.toString());
201
- setClassNamesList(newArray);
202
- }}>
203
- {variants.map((optionValue: string) => (
204
- <MenuItem key={appearance + " btn-" + optionValue.toLowerCase()} value={"btn-" + optionValue.toLowerCase()}>{optionValue}</MenuItem>
205
- ))}
206
- </Select>
207
- </FormControl>
208
- <FormControl fullWidth>
209
- <InputLabel>Size</InputLabel>
210
- <Select name="classNames" fullWidth label="Size" size="small" value={ classNamesList[2] } onChange={(e) => {
211
- const newArray = [...classNamesList];
212
- let index = 0;
213
- newArray.forEach((item, i) => {
214
- sizes.forEach((element) => {
215
- if(item.includes(element.toLowerCase())) {
216
- index = i;
217
- };
218
- })
219
- })
220
- newArray.splice(index, 1, e.target.value.toString());
221
- setClassNamesList(newArray);
222
- }}>
223
- {sizes.map((optionValue: string) => (
224
- <MenuItem key={appearance + " btn-" + optionValue.toLowerCase()} value={"btn-" + optionValue.toLowerCase()}>{optionValue}</MenuItem>
225
- ))}
226
- </Select>
227
- </FormControl>
228
- </div>
229
- }
230
-
231
- <div className="target-check">
232
- <input type="checkbox" checked={targetAttribute === "_blank"} onChange={(e) => {
233
- setTargetAttribute((currentValue: string) => currentValue === "_blank" ? "_self" : "_blank" );
234
- }} />
235
- - Open in new window
236
- </div><br />
237
-
238
- <Button fullWidth={true} variant="contained" onClick={handleSave}>Save</Button>
239
- </div>
240
- );
241
- };
242
-
243
- export default FloatingLinkEditor;
1
+ import React, { useCallback, useRef, FC, useEffect } from "react";
2
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
3
+ import { mergeRegister } from "@lexical/utils";
4
+ import { $isCustomLinkNode } from "./CustomLinkNode";
5
+ import { $getSelection, SELECTION_CHANGE_COMMAND, $isRangeSelection, $getNodeByKey } from "lexical";
6
+ import { TOGGLE_CUSTOM_LINK_NODE_COMMAND } from "./CustomLinkNode";
7
+ import { FloatingLinkEditorProps } from "./FloatingLinkEditor.types";
8
+ import { getSelectedNode } from "../ToolbarPlugin";
9
+ import { FormControl, InputLabel, Select, MenuItem, TextField, Button } from "@mui/material";
10
+
11
+ const positionEditorElement = (editor: HTMLElement, rect: DOMRect | null) => {
12
+ if (rect === null) {
13
+ editor.style.opacity = "0";
14
+ editor.style.top = "-1000px";
15
+ editor.style.left = "-1000px";
16
+ } else {
17
+ editor.style.opacity = "1";
18
+ editor.style.top = `${rect.top + rect.height + window.pageYOffset + 10}px`;
19
+ editor.style.left = `${
20
+ rect.left + window.pageXOffset - editor.offsetWidth / 2 + rect.width / 2 < 0
21
+ ? 0
22
+ : rect.left
23
+ + window.pageXOffset
24
+ - editor.offsetWidth / 2
25
+ + rect.width / 2
26
+ }px`;
27
+ }
28
+ };
29
+
30
+ const LowPriority = 1;
31
+
32
+ const FloatingLinkEditor: FC<FloatingLinkEditorProps> = ({
33
+ linkUrl,
34
+ setLinkUrl,
35
+ classNamesList,
36
+ setClassNamesList,
37
+ targetAttribute,
38
+ setTargetAttribute,
39
+ selectedElementKey
40
+ }) => {
41
+ const [editor] = useLexicalComposerContext();
42
+
43
+ const editorRef = useRef(null);
44
+
45
+ const mouseDownRef = useRef(false);
46
+
47
+ /*
48
+ const [lastSelection, setLastSelection] = useState<
49
+ GridSelection | NodeSelection | RangeSelection | null
50
+ >(null);
51
+ */
52
+
53
+ const updateLinkEditor = useCallback(() => {
54
+ const selection = $getSelection();
55
+ if ($isRangeSelection(selection)) {
56
+ const node = getSelectedNode(selection);
57
+
58
+ const parent = node.getParent();
59
+ if ($isCustomLinkNode(parent)) {
60
+ const _url = editor.getElementByKey(parent.__key)?.getAttribute("href");
61
+ if (_url) {
62
+ setLinkUrl(_url);
63
+ }
64
+ } else if ($isCustomLinkNode(node)) {
65
+ const _url = editor.getElementByKey(node.__key)?.getAttribute("href");
66
+ if (_url) {
67
+ setLinkUrl(_url);
68
+ }
69
+ }
70
+ }
71
+ const editorElem = editorRef.current;
72
+ const nativeSelection = window.getSelection();
73
+
74
+ if (!nativeSelection) return;
75
+
76
+ const activeElement = document.activeElement;
77
+
78
+ if (editorElem === null) {
79
+ return;
80
+ }
81
+
82
+ const rootElement = editor.getRootElement();
83
+ if (
84
+ selection !== null
85
+ && !nativeSelection?.isCollapsed
86
+ && rootElement !== null
87
+ && rootElement.contains(nativeSelection.anchorNode)
88
+ ) {
89
+ const domRange = nativeSelection.getRangeAt(0);
90
+ let rect;
91
+ if (nativeSelection.anchorNode === rootElement) {
92
+ let inner: Element | HTMLElement = rootElement;
93
+ while (inner.firstElementChild != null) {
94
+ inner = inner.firstElementChild;
95
+ }
96
+ rect = inner.getBoundingClientRect();
97
+ } else {
98
+ rect = domRange.getBoundingClientRect();
99
+ }
100
+
101
+ if (!mouseDownRef.current) {
102
+ positionEditorElement(editorElem, rect);
103
+ }
104
+ //setLastSelection(selection);
105
+ } else if (!activeElement || activeElement.className !== "link-input") {
106
+ positionEditorElement(editorElem, null);
107
+ //setLastSelection(null);
108
+ }
109
+
110
+ return true;
111
+ }, [editor]); //eslint-disable-line
112
+
113
+ useEffect(() => (
114
+ mergeRegister(
115
+ editor.registerUpdateListener(({ editorState }) => {
116
+ editorState.read(() => {
117
+ updateLinkEditor();
118
+ });
119
+ }),
120
+
121
+ editor.registerCommand(
122
+ SELECTION_CHANGE_COMMAND,
123
+ () => {
124
+ editor.getEditorState().read(() => {
125
+ updateLinkEditor();
126
+ });
127
+ return true;
128
+ },
129
+ LowPriority
130
+ )
131
+ )
132
+ ), [editor, updateLinkEditor]);
133
+
134
+ useEffect(() => {
135
+ editor.getEditorState().read(() => {
136
+ updateLinkEditor();
137
+ });
138
+ }, [editor, updateLinkEditor]);
139
+
140
+ useEffect(() => {
141
+ editor.getEditorState().read(() => {
142
+ updateLinkEditor();
143
+ });
144
+ }, []); //eslint-disable-line
145
+
146
+ const variants = ["Primary", "Secondary", "Success", "Danger", "Warning", "Info", "Light", "Dark"];
147
+ const sizes = ["Small", "Medium", "Large"];
148
+ let appearance = "link";
149
+ if (classNamesList[0].indexOf("btn")>-1) appearance="btn";
150
+ if (classNamesList[0].indexOf("btn-block")>-1) appearance="btn btn-block";
151
+
152
+ const handleSave = () => {
153
+ editor.dispatchCommand(TOGGLE_CUSTOM_LINK_NODE_COMMAND, {
154
+ url: linkUrl,
155
+ classNames: classNamesList,
156
+ target: targetAttribute
157
+ });
158
+
159
+ editor.update(() => {
160
+ if (!selectedElementKey) return;
161
+
162
+ const selectedNode = $getNodeByKey(selectedElementKey);
163
+
164
+ selectedNode?.selectEnd();
165
+ });
166
+ }
167
+
168
+ return (
169
+ <div ref={editorRef} className="link-editor">
170
+
171
+ <TextField label="Url" value={linkUrl} onChange={e => { setLinkUrl(e.target.value) }} fullWidth size="small" />
172
+
173
+ <FormControl fullWidth>
174
+ <InputLabel>Appearance</InputLabel>
175
+ <Select name="classNames" fullWidth label="Appearance" size="small" value={appearance} onChange={(e) => {
176
+ let className = "";
177
+ if (e.target.value.toString()!=="link") className = e.target.value.toString();
178
+ setClassNamesList([className, "btn-primary", "btn-medium"])
179
+ }}>
180
+ <MenuItem value="link">Standard Link</MenuItem>
181
+ <MenuItem value="btn">Button</MenuItem>
182
+ <MenuItem value="btn btn-block">Full Width Button</MenuItem>
183
+ </Select>
184
+ </FormControl>
185
+
186
+ {appearance!=="link"
187
+ && <div>
188
+ <FormControl fullWidth>
189
+ <InputLabel>Variant</InputLabel>
190
+ <Select name="classNames" fullWidth label="Variant" size="small" value={ classNamesList[1] } onChange={(e) => {
191
+ const newArray = [...classNamesList];
192
+ let index = 0;
193
+ newArray.forEach((item, i) => {
194
+ variants.forEach((element) => {
195
+ if (item.includes(element.toLowerCase())) {
196
+ index = i;
197
+ };
198
+ })
199
+ })
200
+ newArray.splice(index, 1, e.target.value.toString());
201
+ setClassNamesList(newArray);
202
+ }}>
203
+ {variants.map((optionValue: string) => (
204
+ <MenuItem key={appearance + " btn-" + optionValue.toLowerCase()} value={"btn-" + optionValue.toLowerCase()}>{optionValue}</MenuItem>
205
+ ))}
206
+ </Select>
207
+ </FormControl>
208
+ <FormControl fullWidth>
209
+ <InputLabel>Size</InputLabel>
210
+ <Select name="classNames" fullWidth label="Size" size="small" value={ classNamesList[2] } onChange={(e) => {
211
+ const newArray = [...classNamesList];
212
+ let index = 0;
213
+ newArray.forEach((item, i) => {
214
+ sizes.forEach((element) => {
215
+ if(item.includes(element.toLowerCase())) {
216
+ index = i;
217
+ };
218
+ })
219
+ })
220
+ newArray.splice(index, 1, e.target.value.toString());
221
+ setClassNamesList(newArray);
222
+ }}>
223
+ {sizes.map((optionValue: string) => (
224
+ <MenuItem key={appearance + " btn-" + optionValue.toLowerCase()} value={"btn-" + optionValue.toLowerCase()}>{optionValue}</MenuItem>
225
+ ))}
226
+ </Select>
227
+ </FormControl>
228
+ </div>
229
+ }
230
+
231
+ <div className="target-check">
232
+ <input type="checkbox" checked={targetAttribute === "_blank"} onChange={(e) => {
233
+ setTargetAttribute((currentValue: string) => currentValue === "_blank" ? "_self" : "_blank" );
234
+ }} />
235
+ - Open in new window
236
+ </div><br />
237
+
238
+ <Button fullWidth={true} variant="contained" onClick={handleSave}>Save</Button>
239
+ </div>
240
+ );
241
+ };
242
+
243
+ export default FloatingLinkEditor;
@@ -1,11 +1,11 @@
1
- import { Dispatch, SetStateAction } from "react";
2
-
3
- export interface FloatingLinkEditorProps {
4
- linkUrl: string;
5
- setLinkUrl: (value: string) => void;
6
- targetAttribute: string;
7
- setTargetAttribute: Dispatch<SetStateAction<string>>;
8
- classNamesList: Array<string>;
9
- setClassNamesList: (value: Array<string>) => void;
10
- selectedElementKey: string | null;
11
- }
1
+ import { Dispatch, SetStateAction } from "react";
2
+
3
+ export interface FloatingLinkEditorProps {
4
+ linkUrl: string;
5
+ setLinkUrl: (value: string) => void;
6
+ targetAttribute: string;
7
+ setTargetAttribute: Dispatch<SetStateAction<string>>;
8
+ classNamesList: Array<string>;
9
+ setClassNamesList: (value: Array<string>) => void;
10
+ selectedElementKey: string | null;
11
+ }