@social-mail/social-mail-client 1.0.113 → 1.0.115

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 (230) hide show
  1. package/content/editor/edit.html +159 -0
  2. package/content/templates/plain/index.html +32 -0
  3. package/dist/admin/AdminAppIndex.pack.js +2605 -269
  4. package/dist/admin/AdminAppIndex.pack.js.map +1 -1
  5. package/dist/admin/AdminAppIndex.pack.min.js +258 -9
  6. package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
  7. package/dist/common/Sql.d.ts +1 -0
  8. package/dist/common/Sql.d.ts.map +1 -1
  9. package/dist/common/Sql.js.map +1 -1
  10. package/dist/common/commands/CommonCommands.d.ts +7 -0
  11. package/dist/common/commands/CommonCommands.d.ts.map +1 -1
  12. package/dist/common/commands/CommonCommands.js +10 -0
  13. package/dist/common/commands/CommonCommands.js.map +1 -1
  14. package/dist/common/controls/html/grapes-js/GrapesJSEditor.d.ts +19 -0
  15. package/dist/common/controls/html/grapes-js/GrapesJSEditor.d.ts.map +1 -0
  16. package/dist/common/controls/html/grapes-js/GrapesJSEditor.js +119 -0
  17. package/dist/common/controls/html/grapes-js/GrapesJSEditor.js.map +1 -0
  18. package/dist/common/controls/tree/FileTreeView.d.ts +16 -0
  19. package/dist/common/controls/tree/FileTreeView.d.ts.map +1 -0
  20. package/dist/common/controls/tree/FileTreeView.js +100 -0
  21. package/dist/common/controls/tree/FileTreeView.js.map +1 -0
  22. package/dist/common/controls/tree/TreeView.d.ts +4 -1
  23. package/dist/common/controls/tree/TreeView.d.ts.map +1 -1
  24. package/dist/common/controls/tree/TreeView.js +35 -17
  25. package/dist/common/controls/tree/TreeView.js.map +1 -1
  26. package/dist/common/pages/websites/edit/WebSiteFolderEditor.d.ts.map +1 -1
  27. package/dist/common/pages/websites/edit/WebSiteFolderEditor.js +2 -1
  28. package/dist/common/pages/websites/edit/WebSiteFolderEditor.js.map +1 -1
  29. package/dist/common/pages/websites/manage/ManageWebSitePage.d.ts +10 -0
  30. package/dist/common/pages/websites/manage/ManageWebSitePage.d.ts.map +1 -0
  31. package/dist/common/pages/websites/manage/ManageWebSitePage.js +45 -0
  32. package/dist/common/pages/websites/manage/ManageWebSitePage.js.map +1 -0
  33. package/dist/common/pages/websites/studio/WebSiteStudioPage.d.ts +24 -0
  34. package/dist/common/pages/websites/studio/WebSiteStudioPage.d.ts.map +1 -0
  35. package/dist/common/pages/websites/studio/WebSiteStudioPage.js +244 -0
  36. package/dist/common/pages/websites/studio/WebSiteStudioPage.js.map +1 -0
  37. package/dist/common/pages/websites/templates/ChooseWebSiteTemplatePage.d.ts +9 -0
  38. package/dist/common/pages/websites/templates/ChooseWebSiteTemplatePage.d.ts.map +1 -0
  39. package/dist/common/pages/websites/templates/ChooseWebSiteTemplatePage.js +59 -0
  40. package/dist/common/pages/websites/templates/ChooseWebSiteTemplatePage.js.map +1 -0
  41. package/dist/model/model.d.ts +9 -0
  42. package/dist/model/model.d.ts.map +1 -1
  43. package/dist/model/model.js +2 -1
  44. package/dist/model/model.js.map +1 -1
  45. package/dist/services/websites/WebSiteService.d.ts +1 -0
  46. package/dist/services/websites/WebSiteService.d.ts.map +1 -1
  47. package/dist/services/websites/WebSiteService.js +8 -1
  48. package/dist/services/websites/WebSiteService.js.map +1 -1
  49. package/dist/site-editor/blocks/Block.d.ts +6 -0
  50. package/dist/site-editor/blocks/Block.d.ts.map +1 -0
  51. package/dist/site-editor/blocks/Block.js +48 -0
  52. package/dist/site-editor/blocks/Block.js.map +1 -0
  53. package/dist/site-editor/blocks/ImageBlock.d.ts +2 -0
  54. package/dist/site-editor/blocks/ImageBlock.d.ts.map +1 -0
  55. package/dist/site-editor/blocks/ImageBlock.js +23 -0
  56. package/dist/site-editor/blocks/ImageBlock.js.map +1 -0
  57. package/dist/site-editor/blocks/WrapGrid.d.ts +2 -0
  58. package/dist/site-editor/blocks/WrapGrid.d.ts.map +1 -0
  59. package/dist/site-editor/blocks/WrapGrid.js +22 -0
  60. package/dist/site-editor/blocks/WrapGrid.js.map +1 -0
  61. package/dist/site-editor/commands/CodeCommand.d.ts +2 -0
  62. package/dist/site-editor/commands/CodeCommand.d.ts.map +1 -0
  63. package/dist/site-editor/commands/CodeCommand.js +51 -0
  64. package/dist/site-editor/commands/CodeCommand.js.map +1 -0
  65. package/dist/site-editor/commands/EditorCommand.d.ts +6 -0
  66. package/dist/site-editor/commands/EditorCommand.d.ts.map +1 -0
  67. package/dist/site-editor/commands/EditorCommand.js +52 -0
  68. package/dist/site-editor/commands/EditorCommand.js.map +1 -0
  69. package/dist/site-editor/commands/IEditorCommandParameter.d.ts +5 -0
  70. package/dist/site-editor/commands/IEditorCommandParameter.d.ts.map +1 -0
  71. package/dist/site-editor/commands/IEditorCommandParameter.js +9 -0
  72. package/dist/site-editor/commands/IEditorCommandParameter.js.map +1 -0
  73. package/dist/site-editor/components/Component.d.ts +5 -0
  74. package/dist/site-editor/components/Component.d.ts.map +1 -0
  75. package/dist/site-editor/components/Component.js +21 -0
  76. package/dist/site-editor/components/Component.js.map +1 -0
  77. package/dist/site-editor/components/ImageComponent.d.ts +1 -0
  78. package/dist/site-editor/components/ImageComponent.d.ts.map +1 -0
  79. package/dist/site-editor/components/ImageComponent.js +9 -0
  80. package/dist/site-editor/components/ImageComponent.js.map +1 -0
  81. package/dist/site-editor/drag-drop/DragDropHelper.d.ts +3 -0
  82. package/dist/site-editor/drag-drop/DragDropHelper.d.ts.map +1 -0
  83. package/dist/site-editor/drag-drop/DragDropHelper.js +117 -0
  84. package/dist/site-editor/drag-drop/DragDropHelper.js.map +1 -0
  85. package/dist/site-editor/editor/HtmlPageEditor.d.ts +43 -0
  86. package/dist/site-editor/editor/HtmlPageEditor.d.ts.map +1 -0
  87. package/dist/site-editor/editor/HtmlPageEditor.js +500 -0
  88. package/dist/site-editor/editor/HtmlPageEditor.js.map +1 -0
  89. package/dist/site-editor/properties/ColorEditor.d.ts +6 -0
  90. package/dist/site-editor/properties/ColorEditor.d.ts.map +1 -0
  91. package/dist/site-editor/properties/ColorEditor.js +46 -0
  92. package/dist/site-editor/properties/ColorEditor.js.map +1 -0
  93. package/dist/site-editor/properties/Properties.d.ts +2 -0
  94. package/dist/site-editor/properties/Properties.d.ts.map +1 -0
  95. package/dist/site-editor/properties/Properties.js +48 -0
  96. package/dist/site-editor/properties/Properties.js.map +1 -0
  97. package/dist/site-editor/properties/ThicknessEditor.d.ts +4 -0
  98. package/dist/site-editor/properties/ThicknessEditor.d.ts.map +1 -0
  99. package/dist/site-editor/properties/ThicknessEditor.js +15 -0
  100. package/dist/site-editor/properties/ThicknessEditor.js.map +1 -0
  101. package/dist/site-editor/styler/IStylerPair.d.ts +10 -0
  102. package/dist/site-editor/styler/IStylerPair.d.ts.map +1 -0
  103. package/dist/site-editor/styler/IStylerPair.js +9 -0
  104. package/dist/site-editor/styler/IStylerPair.js.map +1 -0
  105. package/dist/site-editor/styler/Styler.d.ts +170 -0
  106. package/dist/site-editor/styler/Styler.d.ts.map +1 -0
  107. package/dist/site-editor/styler/Styler.js +137 -0
  108. package/dist/site-editor/styler/Styler.js.map +1 -0
  109. package/dist/site-editor/styler/StylerSet.d.ts +8 -0
  110. package/dist/site-editor/styler/StylerSet.d.ts.map +1 -0
  111. package/dist/site-editor/styler/StylerSet.js +51 -0
  112. package/dist/site-editor/styler/StylerSet.js.map +1 -0
  113. package/dist/site-editor/styler/properties/border.d.ts +3 -0
  114. package/dist/site-editor/styler/properties/border.d.ts.map +1 -0
  115. package/dist/site-editor/styler/properties/border.js +38 -0
  116. package/dist/site-editor/styler/properties/border.js.map +1 -0
  117. package/dist/site-editor/styler/properties/boxShadow.d.ts +3 -0
  118. package/dist/site-editor/styler/properties/boxShadow.d.ts.map +1 -0
  119. package/dist/site-editor/styler/properties/boxShadow.js +24 -0
  120. package/dist/site-editor/styler/properties/boxShadow.js.map +1 -0
  121. package/dist/site-editor/styler/properties/color.d.ts +3 -0
  122. package/dist/site-editor/styler/properties/color.d.ts.map +1 -0
  123. package/dist/site-editor/styler/properties/color.js +93 -0
  124. package/dist/site-editor/styler/properties/color.js.map +1 -0
  125. package/dist/site-editor/styler/properties/cursor.d.ts +3 -0
  126. package/dist/site-editor/styler/properties/cursor.d.ts.map +1 -0
  127. package/dist/site-editor/styler/properties/cursor.js +20 -0
  128. package/dist/site-editor/styler/properties/cursor.js.map +1 -0
  129. package/dist/site-editor/styler/properties/filter.d.ts +3 -0
  130. package/dist/site-editor/styler/properties/filter.d.ts.map +1 -0
  131. package/dist/site-editor/styler/properties/filter.js +24 -0
  132. package/dist/site-editor/styler/properties/filter.js.map +1 -0
  133. package/dist/site-editor/styler/properties/layout.d.ts +3 -0
  134. package/dist/site-editor/styler/properties/layout.d.ts.map +1 -0
  135. package/dist/site-editor/styler/properties/layout.js +78 -0
  136. package/dist/site-editor/styler/properties/layout.js.map +1 -0
  137. package/dist/site-editor/toolbars/EditorToolbar.d.ts +3 -0
  138. package/dist/site-editor/toolbars/EditorToolbar.d.ts.map +1 -0
  139. package/dist/site-editor/toolbars/EditorToolbar.js +49 -0
  140. package/dist/site-editor/toolbars/EditorToolbar.js.map +1 -0
  141. package/dist/site-editor/toolbars/UndoRedoToolbar.d.ts +2 -0
  142. package/dist/site-editor/toolbars/UndoRedoToolbar.d.ts.map +1 -0
  143. package/dist/site-editor/toolbars/UndoRedoToolbar.js +40 -0
  144. package/dist/site-editor/toolbars/UndoRedoToolbar.js.map +1 -0
  145. package/dist/style/GlobalStyle.js +1 -1
  146. package/dist/tsconfig.tsbuildinfo +1 -1
  147. package/dist/web/AppIndex.pack.js +5188 -2832
  148. package/dist/web/AppIndex.pack.js.map +1 -1
  149. package/dist/web/AppIndex.pack.min.js +399 -150
  150. package/dist/web/AppIndex.pack.min.js.map +1 -1
  151. package/dist/web/drawer/AppDrawer.d.ts +1 -0
  152. package/dist/web/drawer/AppDrawer.d.ts.map +1 -1
  153. package/dist/web/drawer/AppDrawer.js +24 -4
  154. package/dist/web/drawer/AppDrawer.js.map +1 -1
  155. package/dist/web/page/files/FolderPage.d.ts.map +1 -1
  156. package/dist/web/page/files/FolderPage.js.map +1 -1
  157. package/dist/web/page/files/media/ChooseMediaPage.d.ts +24 -0
  158. package/dist/web/page/files/media/ChooseMediaPage.d.ts.map +1 -0
  159. package/dist/web/page/files/media/ChooseMediaPage.js +165 -0
  160. package/dist/web/page/files/media/ChooseMediaPage.js.map +1 -0
  161. package/dist/web/page/files/service/CloudFileService.d.ts +6 -3
  162. package/dist/web/page/files/service/CloudFileService.d.ts.map +1 -1
  163. package/dist/web/page/files/service/CloudFileService.js +34 -5
  164. package/dist/web/page/files/service/CloudFileService.js.map +1 -1
  165. package/node_modules/@web-atoms/core/dist/core/AtomList.d.ts.map +1 -1
  166. package/node_modules/@web-atoms/core/dist/core/AtomList.js +5 -3
  167. package/node_modules/@web-atoms/core/dist/core/AtomList.js.map +1 -1
  168. package/node_modules/@web-atoms/core/dist/services/FetchBuilder.d.ts +3 -0
  169. package/node_modules/@web-atoms/core/dist/services/FetchBuilder.d.ts.map +1 -1
  170. package/node_modules/@web-atoms/core/dist/services/FetchBuilder.js +10 -0
  171. package/node_modules/@web-atoms/core/dist/services/FetchBuilder.js.map +1 -1
  172. package/node_modules/@web-atoms/core/dist/style/styled.d.ts +2 -2
  173. package/node_modules/@web-atoms/core/dist/style/styled.d.ts.map +1 -1
  174. package/node_modules/@web-atoms/core/dist/style/styled.js.map +1 -1
  175. package/node_modules/@web-atoms/core/dist/tsconfig.tsbuildinfo +1 -1
  176. package/node_modules/@web-atoms/core/package.json +1 -1
  177. package/node_modules/@web-atoms/core/src/core/AtomList.ts +5 -3
  178. package/node_modules/@web-atoms/core/src/services/FetchBuilder.ts +13 -0
  179. package/node_modules/@web-atoms/core/src/style/styled.ts +3 -1
  180. package/node_modules/@web-atoms/web-controls/dist/basic/AtomChips.d.ts +1 -0
  181. package/node_modules/@web-atoms/web-controls/dist/basic/AtomChips.d.ts.map +1 -1
  182. package/node_modules/@web-atoms/web-controls/dist/basic/AtomChips.js +2 -0
  183. package/node_modules/@web-atoms/web-controls/dist/basic/AtomChips.js.map +1 -1
  184. package/node_modules/@web-atoms/web-controls/dist/basic/AtomRepeater.js +3 -0
  185. package/node_modules/@web-atoms/web-controls/dist/basic/AtomRepeater.js.map +1 -1
  186. package/node_modules/@web-atoms/web-controls/dist/tsconfig.tsbuildinfo +1 -1
  187. package/node_modules/@web-atoms/web-controls/package.json +2 -2
  188. package/node_modules/@web-atoms/web-controls/src/basic/AtomChips.tsx +4 -0
  189. package/node_modules/@web-atoms/web-controls/src/basic/AtomRepeater.tsx +3 -0
  190. package/package.json +3 -3
  191. package/src/common/Sql.ts +1 -0
  192. package/src/common/commands/CommonCommands.ts +12 -0
  193. package/src/common/controls/html/grapes-js/GrapesJSEditor.tsx +97 -0
  194. package/src/common/controls/tree/FileTreeView.tsx +74 -0
  195. package/src/common/controls/tree/TreeView.tsx +34 -12
  196. package/src/common/pages/websites/edit/WebSiteFolderEditor.tsx +2 -1
  197. package/src/common/pages/websites/manage/ManageWebSitePage.tsx +44 -0
  198. package/src/common/pages/websites/studio/WebSiteStudioPage.tsx +205 -0
  199. package/src/common/pages/websites/templates/ChooseWebSiteTemplatePage.tsx +38 -0
  200. package/src/model/model.ts +11 -0
  201. package/src/services/websites/WebSiteService.ts +8 -1
  202. package/src/site-editor/blocks/Block.tsx +38 -0
  203. package/src/site-editor/blocks/ImageBlock.tsx +14 -0
  204. package/src/site-editor/blocks/WrapGrid.tsx +11 -0
  205. package/src/site-editor/commands/CodeCommand.tsx +36 -0
  206. package/src/site-editor/commands/EditorCommand.tsx +42 -0
  207. package/src/site-editor/commands/IEditorCommandParameter.ts +5 -0
  208. package/src/site-editor/components/Component.tsx +9 -0
  209. package/src/site-editor/components/ImageComponent.tsx +0 -0
  210. package/src/site-editor/drag-drop/DragDropHelper.ts +141 -0
  211. package/src/site-editor/editor/HtmlPageEditor.tsx +497 -0
  212. package/src/site-editor/properties/ColorEditor.tsx +36 -0
  213. package/src/site-editor/properties/Properties.tsx +35 -0
  214. package/src/site-editor/properties/ThicknessEditor.tsx +5 -0
  215. package/src/site-editor/styler/IStylerPair.ts +9 -0
  216. package/src/site-editor/styler/Styler.ts +169 -0
  217. package/src/site-editor/styler/StylerSet.ts +42 -0
  218. package/src/site-editor/styler/properties/border.ts +30 -0
  219. package/src/site-editor/styler/properties/boxShadow.ts +14 -0
  220. package/src/site-editor/styler/properties/color.ts +82 -0
  221. package/src/site-editor/styler/properties/cursor.ts +49 -0
  222. package/src/site-editor/styler/properties/filter.ts +14 -0
  223. package/src/site-editor/styler/properties/layout.ts +72 -0
  224. package/src/site-editor/toolbars/EditorToolbar.tsx +40 -0
  225. package/src/site-editor/toolbars/UndoRedoToolbar.tsx +27 -0
  226. package/src/style/GlobalStyle.ts +1 -1
  227. package/src/web/drawer/AppDrawer.tsx +21 -4
  228. package/src/web/page/files/FolderPage.tsx +0 -1
  229. package/src/web/page/files/media/ChooseMediaPage.tsx +135 -0
  230. package/src/web/page/files/service/CloudFileService.ts +33 -8
@@ -0,0 +1,42 @@
1
+ import type HtmlPageEditor from "../editor/HtmlPageEditor";
2
+ import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
3
+
4
+ export const EditorCommand = {
5
+
6
+ onClick(cb: (editor: HtmlPageEditor, e: Event) => any) {
7
+ return (e: Event) => {
8
+ let c = AtomControl.from(e.target);
9
+ while (c && !c.element?.hasAttribute("data-html-page-editor")) {
10
+ c = c.parent;
11
+ }
12
+ return cb(c as HtmlPageEditor, e);
13
+ };
14
+ },
15
+
16
+ insertContent(cb: (editor: HtmlPageEditor, e: Event) => any) {
17
+ return async (e: Event) => {
18
+ let c = AtomControl.from(e.target);
19
+ while (c && !c.element?.hasAttribute("data-html-page-editor")) {
20
+ c = c.parent;
21
+ }
22
+ const editor = c as HtmlPageEditor;
23
+ let content = cb(editor, e);
24
+ if (!content) {
25
+ return;
26
+ }
27
+ content = await content;
28
+ const document = editor.htmlDocument;
29
+ // if it is string..
30
+ if (typeof content === "string") {
31
+ const div = document.createElement("div");
32
+ div.innerHTML = content;
33
+ for (const iterator of Array.from(div.children)) {
34
+ editor.insertElement(iterator as HTMLElement);
35
+ }
36
+ return;
37
+ }
38
+ editor.insertElement(content as HTMLElement);
39
+ };
40
+ }
41
+
42
+ };
@@ -0,0 +1,5 @@
1
+ import type HtmlPageEditor from "../editor/HtmlPageEditor";
2
+
3
+ export default interface IEditorCommandParameter {
4
+ editor: HtmlPageEditor;
5
+ }
@@ -0,0 +1,9 @@
1
+ import { BindableProperty } from "@web-atoms/core/dist/core/BindableProperty";
2
+ import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
3
+
4
+ export default class Component extends AtomControl {
5
+
6
+ @BindableProperty
7
+ public host: HTMLElement;
8
+
9
+ }
File without changes
@@ -0,0 +1,141 @@
1
+ import type HtmlPageEditor from "../editor/HtmlPageEditor";
2
+
3
+ interface IPoint {
4
+ x: number;
5
+ y: number;
6
+ }
7
+
8
+ /**
9
+ * Drag and Drop Scenario.
10
+ *
11
+ * 1. Inside an empty container, drop the placeholder
12
+ * 2. Inside a container, within the padding
13
+ * @param editor HtmlPageEditor
14
+ */
15
+ export function InstallDragDropHelper(editor: HtmlPageEditor) {
16
+
17
+
18
+ let placeholder: HTMLElement;
19
+ let dragged: HTMLElement;
20
+
21
+ const document = editor.htmlDocument;
22
+
23
+ document.addEventListener("dragstart", (e) => {
24
+ dragged = e.target as HTMLElement;
25
+ e.dataTransfer.dropEffect = "move";
26
+ e.dataTransfer.setDragImage(dragged, 0, 0);
27
+ });
28
+
29
+ document.addEventListener("dragover", (e) => {
30
+ const target = e.target as HTMLElement;
31
+ e.preventDefault();
32
+ if (target === placeholder) {
33
+ return;
34
+ }
35
+ e.dataTransfer.dropEffect = "copy";
36
+ if(!placeholder) {
37
+ placeholder = document.createElement("div");
38
+ placeholder.style.display = "block";
39
+ placeholder.style.backgroundColor = "green";
40
+ document.body.appendChild(placeholder);
41
+ }
42
+
43
+ const insert = (where: InsertPosition, width = "5px", height = "5px") => {
44
+ const previous = where === "beforebegin"
45
+ ? target.previousElementSibling
46
+ : target.nextElementSibling;
47
+ if (previous === placeholder) {
48
+ return;
49
+ }
50
+ placeholder.remove();
51
+ target.insertAdjacentElement(where, placeholder);
52
+ placeholder.style.width = width;
53
+ placeholder.style.height = height;
54
+ };
55
+
56
+ const b = target.getBoundingClientRect();
57
+ const mp = { x: e.clientX, y: e.clientY };
58
+
59
+ const style = document.defaultView.getComputedStyle(target);
60
+ const isVertical = (style.display === "flex" && (style.flexDirection === "row" || style.flexWrap))
61
+ || style.display === "inline-block"
62
+ || target.tagName === "TD";
63
+
64
+
65
+ if (isVertical) {
66
+ if (target.childElementCount === 0) {
67
+ insert("afterbegin", void 0, "100%");
68
+ return;
69
+ }
70
+ if ((b.x + b.width * 0.2) > mp.x) {
71
+ insert("beforebegin", void 0, "100%");
72
+ return;
73
+ }
74
+ insert("afterend", void 0, "100%");
75
+ return;
76
+ }
77
+ if (target.childElementCount === 0) {
78
+ insert("afterbegin", "100%");
79
+ return;
80
+ }
81
+ if ((b.y + b.height * 0.2) > mp.y) {
82
+ // in the beginning...
83
+ insert("beforebegin", "100%");
84
+ return;
85
+ }
86
+ insert("afterend", "100%");
87
+ });
88
+
89
+ document.addEventListener("dragend", (e) => {
90
+ if (placeholder) {
91
+ if(dragged) {
92
+ dragged.style.display = "";
93
+ dragged.remove();
94
+ placeholder.parentElement.replaceChild(dragged, placeholder);
95
+ editor.setSelection(dragged, true);
96
+ } else {
97
+ // external drop..
98
+ const div = document.createElement("div");
99
+ div.innerHTML = e.dataTransfer.getData("text/html");
100
+ const node = div.firstElementChild;
101
+ placeholder.parentElement.replaceChild(node, placeholder);
102
+ editor.setSelection(node, true);
103
+ }
104
+ }
105
+ dragged = null;
106
+ placeholder?.remove();
107
+ placeholder = null;
108
+ });
109
+
110
+ document.addEventListener("drop", (e) => {
111
+ if (placeholder) {
112
+ if(dragged) {
113
+ dragged.style.display = "";
114
+ dragged.remove();
115
+ placeholder.parentElement.replaceChild(dragged, placeholder);
116
+ editor.setSelection(dragged, true);
117
+ } else {
118
+ // external drop..
119
+ const div = document.createElement("div");
120
+ div.innerHTML = e.dataTransfer.getData("text/html");
121
+ const node = div.firstElementChild;
122
+ placeholder.parentElement.replaceChild(node, placeholder);
123
+ editor.setSelection(node, true);
124
+ }
125
+ }
126
+ dragged = null;
127
+ placeholder?.remove();
128
+ placeholder = null;
129
+ });
130
+
131
+ document.addEventListener("dragleave", (e) => {
132
+ // turn off highlight
133
+ placeholder?.remove();
134
+ placeholder = null;
135
+ });
136
+
137
+ setTimeout(() => {
138
+ document.body.querySelectorAll("*").forEach((e: HTMLElement) => e.draggable = true);
139
+ }, 100);
140
+
141
+ }
@@ -0,0 +1,497 @@
1
+ import Bind from "@web-atoms/core/dist/core/Bind";
2
+ import XNode from "@web-atoms/core/dist/core/XNode";
3
+ import sleep from "@web-atoms/core/dist/core/sleep";
4
+ import styled from "@web-atoms/core/dist/style/styled";
5
+ import Action from "@web-atoms/core/dist/view-model/Action";
6
+ import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
7
+ import ChooseMediaPage from "../../web/page/files/media/ChooseMediaPage";
8
+ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
9
+ import { BindableProperty } from "@web-atoms/core/dist/core/BindableProperty";
10
+ import { IAppFile } from "../../model/model";
11
+ import { ImageBlock } from "../blocks/ImageBlock";
12
+ import ToggleButtonBar from "@web-atoms/web-controls/dist/basic/ToggleButtonBar";
13
+ import { InstallDragDropHelper } from "../drag-drop/DragDropHelper";
14
+ import { CodeCommand } from "../commands/CodeCommand";
15
+ import UndoRedoToolbar from "../toolbars/UndoRedoToolbar";
16
+ import { WrapGrid } from "../blocks/WrapGrid";
17
+ import EditorToolbar from "../toolbars/EditorToolbar";
18
+ import Properties from "../properties/Properties";
19
+ import { AtomBinder } from "@web-atoms/core/dist/core/AtomBinder";
20
+ import { StylerSet } from "../styler/StylerSet";
21
+
22
+ styled.css `
23
+ display: grid;
24
+ grid-template-columns: auto 1fr auto;
25
+ grid-template-rows: auto 1fr auto;
26
+ overflow: hidden !important;
27
+
28
+ & > [data-element=top] {
29
+ grid-row: 1;
30
+ grid-column: 2;
31
+ display: flex;
32
+ padding: 5px;
33
+ gap: 10px;
34
+ border-bottom: solid 1px lightgray;
35
+ border-radius: 0;
36
+ & > [data-element=max-width] {
37
+ display: flex;
38
+ gap: 10px;
39
+ }
40
+ }
41
+
42
+ & > [data-element=left] {
43
+ grid-row: 1 / span 3;
44
+ grid-column: 1;
45
+ border-right: solid 1px lightgray;
46
+ border-radius: 0;
47
+ width: 40px;
48
+ }
49
+
50
+ & > [data-element=right] {
51
+ grid-row: 1 / span 3;
52
+ grid-column: 3;
53
+ border-left: solid 1px lightgray;
54
+ border-radius: 0;
55
+ }
56
+
57
+ & > [data-element=editor] {
58
+ grid-row: 2;
59
+ grid-column: 2;
60
+ overflow: hidden;
61
+ align-self: stretch;
62
+ justify-self: center;
63
+ width: 100%;
64
+ height: 100%;
65
+ position: relative;
66
+ display: grid;
67
+ grid-template-columns: auto 1fr auto;
68
+ & > [data-element=content-frame] {
69
+ width: 100%;
70
+ height: 100%;
71
+ margin: 2px;
72
+ position: absolute;
73
+ & > iframe {
74
+ position: absolute;
75
+ width: 100%;
76
+ height: 100%;
77
+ border: none;
78
+ }
79
+ }
80
+ & > [data-element=selection] {
81
+ position: absolute;
82
+ pointer-events: none;
83
+ outline: solid 1px green;
84
+ z-index: 22;
85
+ & > div {
86
+ pointer-events: all;
87
+ position: absolute;
88
+ right: 0;
89
+ transform: translate(0, -100%);
90
+ background-color: #0000ff;
91
+ color: white;
92
+ font-size: smaller;
93
+ text-transform: capitalize;
94
+ padding: 2px;
95
+ padding-left: 5px;
96
+ padding-right: 5px;
97
+ display: flex;
98
+ gap: 5px;
99
+ & * {
100
+ cursor: pointer;
101
+ padding: 2px;
102
+ &:hover {
103
+ background-color: white;
104
+ color: blue;
105
+ }
106
+ }
107
+ }
108
+ }
109
+ & > [data-element=hover] {
110
+ position: absolute;
111
+ outline: solid 1px blue;
112
+ pointer-events: none;
113
+ transition: all 100ms ease;
114
+ z-index: 20;
115
+ & > label {
116
+ position: absolute;
117
+ transform: translate(0, -100%);
118
+ background-color: #0000ff6a;
119
+ color: white;
120
+ font-size: smaller;
121
+ text-transform: capitalize;
122
+ padding: 2px;
123
+ padding-left: 5px;
124
+ padding-right: 5px;
125
+ }
126
+ }
127
+ }
128
+ `.installGlobal("[data-html-page-editor=html-page-editor]");
129
+
130
+ const desktopWidth = 992;
131
+ const tabletWidth = 768;
132
+ const mobileWidth = 480;
133
+
134
+ class SelectedElement {
135
+
136
+ public name: string;
137
+
138
+ public top: string;
139
+ public left: string;
140
+ public width: string;
141
+ public height: string;
142
+
143
+ public isImage: boolean;
144
+
145
+ public get element() {
146
+ return this.e;
147
+ }
148
+
149
+ private mo: MutationObserver;
150
+ private e: HTMLElement;
151
+ private styles = new Map();
152
+
153
+ constructor(private editor: HtmlPageEditor) {
154
+ this.name = "";
155
+ this.isImage = false;
156
+ this.mo = new MutationObserver(() => {
157
+ AtomBinder.refreshValue(this, "element");
158
+ for (const iterator of this.styles.values()) {
159
+ AtomBinder.refreshValue(iterator, "value");
160
+ }
161
+ });
162
+ }
163
+
164
+ public style(name) {
165
+ let mapper = this.styles.get(name);
166
+ if (!mapper) {
167
+ const owner = this;
168
+ mapper = {
169
+ name,
170
+ get value() {
171
+ return owner.e?.getAttribute(name) ?? "";
172
+ },
173
+ set value(v) {
174
+ if (!owner.e) {
175
+ return;
176
+ }
177
+ if (!v) {
178
+ owner.e.removeAttribute(name);
179
+ } else {
180
+ owner.e.setAttribute(name, v);
181
+ }
182
+ owner.editor.commit();
183
+ AtomBinder.refreshValue(this, "value");
184
+ }
185
+ };
186
+ this.styles.set(name, mapper);
187
+ }
188
+ return mapper;
189
+ };
190
+
191
+
192
+ update(e?: HTMLElement) {
193
+ if (e) {
194
+ if (this.e) {
195
+ this.mo.disconnect();
196
+ }
197
+ this.e = e;
198
+ AtomBinder.refreshValue(this, "element");
199
+ this.mo.observe(e, { attributes: true });
200
+ }
201
+ e = this.e;
202
+ if (!e) {
203
+ return;
204
+ }
205
+ this.name = e.tagName.toLowerCase();
206
+ const r = e.getBoundingClientRect();
207
+ this.isImage = this.name === "img";
208
+ this.top = `${r.top + 2}px`;
209
+ this.left = `${r.left + 2}px`;
210
+ this.width = `${r.width}px`;
211
+ this.height = `${r.height}px`;
212
+ for (const iterator of this.styles.values()) {
213
+ AtomBinder.refreshValue(iterator, "value");
214
+ }
215
+ }
216
+ }
217
+
218
+ export default class HtmlPageEditor extends AtomControl {
219
+
220
+ public htmlDocument: Document;
221
+
222
+ public readonly selection: SelectedElement = new SelectedElement(this);
223
+
224
+ public undoList: string[] = [];
225
+ public redoList: string[] = [];
226
+
227
+ @BindableProperty
228
+ public folder: IAppFile;
229
+
230
+ public get htmlPage() {
231
+ return this.htmlDocument?.documentElement?.outerHTML;
232
+ }
233
+
234
+ public set htmlPage(v: string) {
235
+ if(!this.element) {
236
+ return;
237
+ }
238
+ if (!this.ready) {
239
+ setTimeout(() => {
240
+ this.htmlPage = v;
241
+ }, 100);
242
+ return;
243
+ }
244
+ void this.ready.then(() => {
245
+ if(!this.htmlDocument) {
246
+ return;
247
+ }
248
+ this.htmlDocument.open();
249
+ this.htmlDocument.write(v);
250
+ this.htmlDocument.addEventListener("click", (e) => {
251
+ const target = e.target as HTMLAnchorElement;
252
+ const previous = this.selection.element;
253
+ if (previous?.isContentEditable) {
254
+ let start = target;
255
+ while (start) {
256
+ if (previous === target) {
257
+ return;
258
+ }
259
+ start = start.parentElement as any;
260
+ }
261
+ previous.removeAttribute("contentEditable");
262
+ this.commit();
263
+ }
264
+ e.preventDefault();
265
+ this.setSelection(target);
266
+ });
267
+
268
+ this.htmlDocument.addEventListener("dblclick", (e) => {
269
+ const target = e.target as Node;
270
+ e.preventDefault();
271
+ const element: HTMLElement = target.nodeType === Node.ELEMENT_NODE ? target as HTMLElement : target.parentElement;
272
+ element.setAttribute("contentEditable", "true");
273
+ this.setSelection(element as any);
274
+ if (element.tagName === "IMG") {
275
+ this.changeImage().catch(console.error);
276
+ }
277
+ });
278
+
279
+ this.htmlDocument.addEventListener("scroll", (e) => {
280
+ this.hover.update();
281
+ this.selection.update();
282
+ }, { passive: true });
283
+
284
+ this.htmlDocument.addEventListener("pointerover", (e) => {
285
+ let target = e.target as HTMLElement;
286
+ target = target.nodeType === Node.ELEMENT_NODE && target.tagName ? target : target.parentElement;
287
+ if (this.hover.element === target) {
288
+ return;
289
+ }
290
+ this.hover.update(target);
291
+ }, { capture: true });
292
+
293
+ InstallDragDropHelper(this);
294
+
295
+ this.htmlDocument.close();
296
+
297
+ // install styler...
298
+ setTimeout(() => {
299
+ const document = this.htmlDocument;
300
+ let style = document.querySelector(`[styler-style-sheet]`);
301
+ if (!style) {
302
+ style = document.createElement("style");
303
+ style.setAttribute("styler-style-sheet", "inline");
304
+ document.head.appendChild(style);
305
+ }
306
+ style.textContent = StylerSet.instance.toString();
307
+ },10);
308
+
309
+
310
+ setTimeout(() => {
311
+ this.lastHtml = this.htmlDocument.documentElement.innerHTML;
312
+ }, 1);
313
+ });
314
+ }
315
+
316
+ private lastHtml: string;
317
+ private ready: Promise<void>;
318
+ private contentEditor: HTMLIFrameElement;
319
+
320
+ private readonly hover: SelectedElement = new SelectedElement(this);
321
+
322
+ private maxWidth = desktopWidth;
323
+
324
+ constructor(app, e) {
325
+ super(app, e);
326
+ this.folder = null;
327
+ this.ready = this.init();
328
+ }
329
+
330
+ async init() {
331
+ this.render(<div data-html-page-editor="html-page-editor">
332
+ <div data-element="top">
333
+ <EditorToolbar data-element="max-width" event-click={() => this.deferUpdate()}>
334
+ <i
335
+ data-selected={Bind.oneWay(() => this.maxWidth === desktopWidth)}
336
+ event-click={() => this.maxWidth = desktopWidth}
337
+ class="fas fa-desktop"/>
338
+ <i
339
+ data-selected={Bind.oneWay(() => this.maxWidth === tabletWidth)}
340
+ event-click={() => this.maxWidth = tabletWidth}
341
+ class="fas fa-tablet-screen"/>
342
+ <i
343
+ data-selected={Bind.oneWay(() => this.maxWidth === mobileWidth)}
344
+ event-click={() => this.maxWidth = mobileWidth}
345
+ class="fas fa-mobile-screen"/>
346
+ </EditorToolbar>
347
+ <UndoRedoToolbar/>
348
+ <EditorToolbar>
349
+ <CodeCommand/>
350
+ </EditorToolbar>
351
+ </div>
352
+ <EditorToolbar data-element="left">
353
+ <ImageBlock/>
354
+ <WrapGrid/>
355
+ </EditorToolbar>
356
+ <div data-element="editor"
357
+ style-max-width={Bind.oneWay(() => this.maxWidth > 768 ? "" : this.maxWidth + "px" )}>
358
+ <div data-element="resizer"></div>
359
+ <div data-element="selection"
360
+ style-left={Bind.oneWay(() => this.selection.left)}
361
+ style-top={Bind.oneWay(() => this.selection.top)}
362
+ style-width={Bind.oneWay(() => this.selection.width)}
363
+ style-height={Bind.oneWay(() => this.selection.height)}>
364
+ <div>
365
+ <i
366
+ class="fa-regular fa-arrow-up"
367
+ event-click={() => {
368
+ if (this.selection.element.parentElement !== this.htmlDocument.body) {
369
+ this.selection.update(this.selection.element.parentElement);
370
+ }
371
+ }}
372
+ />
373
+ <i
374
+ event-click={() => {
375
+ this.selection.element.draggable = true;
376
+ }}
377
+ class="fa-solid fa-up-down-left-right"
378
+ data-click-event="start-drag"/>
379
+ <i
380
+ style-display={Bind.oneWay(() => this.selection.isImage)}
381
+ data-click-event="change-image"
382
+ title="Change Image (Double Click)"
383
+ class="fa-solid fa-arrows-rotate-reverse"></i>
384
+ <i
385
+ title="Duplicate"
386
+ data-click-event="copy-element" class="fas fa-copy"/>
387
+ <i
388
+ title="Delete"
389
+ data-click-event="delete-element" class="fas fa-trash-can"/>
390
+ </div>
391
+ </div>
392
+ <div data-element="hover"
393
+ style-left={Bind.oneWay(() => this.hover.left)}
394
+ style-top={Bind.oneWay(() => this.hover.top)}
395
+ style-width={Bind.oneWay(() => this.hover.width)}
396
+ style-height={Bind.oneWay(() => this.hover.height)}>
397
+ <label text={Bind.oneWay(() => this.hover.name)}/>
398
+ </div>
399
+ <div
400
+ data-element="content-frame">
401
+ <iframe
402
+ data-element="content-editor"
403
+ />
404
+ </div>
405
+ </div>
406
+ <div data-element="right">
407
+ <Properties/>
408
+ </div>
409
+ </div>);
410
+
411
+ this.contentEditor = this.element.querySelector(`[data-element="content-editor"]`);
412
+ while(!this.htmlDocument) {
413
+ this.htmlDocument = this.contentEditor.contentDocument;
414
+ await sleep(100);
415
+ }
416
+ }
417
+
418
+ @Action({ onEvent: "delete-element"})
419
+ async deleteElement() {
420
+ const current = this.selection.element;
421
+ let previous = current.previousElementSibling ?? current.parentElement;
422
+ current.remove();
423
+ this.commit();
424
+ if (!previous.textContent) {
425
+ previous = previous.previousElementSibling.lastElementChild as any;
426
+ }
427
+ this.setSelection(previous);
428
+ await sleep(100);
429
+ this.selection.update();
430
+ }
431
+
432
+ @Action({ onEvent: "copy-element" , blockMultipleExecution: false})
433
+ copyElement() {
434
+ const current = this.selection.element;
435
+ const copy = current.cloneNode(true) as any;
436
+ current.insertAdjacentElement("afterend", copy);
437
+ this.commit();
438
+ }
439
+
440
+ @Action({ onEvent: "change-image"})
441
+ async changeImage() {
442
+ const { file, size } = await PageNavigator.pushPageForResult(ChooseMediaPage, { folder: this.folder, accept: "image/*" });
443
+ const src = `/api/site/asset/jpg(${size})/${this.folder.appFileID}/${file.appFileID}/${file.fileContentID}/${file.name}.${size}.jpg`;
444
+
445
+ if(this.selection.isImage) {
446
+ this.selection.element.setAttribute("src", src);
447
+ this.selection.element.onload = () => this.selection.update();
448
+ this.commit();
449
+ return;
450
+ }
451
+
452
+ const img = this.htmlDocument.createElement("img");
453
+ img.style.height = size + "px";
454
+ img.src = src;
455
+ this.selection.element.appendChild(img);
456
+ this.selection.element.onload = () => this.selection.update();
457
+ this.commit();
458
+ }
459
+
460
+ insertElement(e: HTMLElement , parent: HTMLElement = this.selection.element) {
461
+ parent.appendChild(e);
462
+ if(!e.id) {
463
+ e.id = "sm-" + Date.now().toString();
464
+ }
465
+ setTimeout(() => {
466
+ this.setSelection(e);
467
+ this.commit();
468
+ }, 100);
469
+ }
470
+
471
+ async deferUpdate() {
472
+ await sleep(100);
473
+ this.hover?.update();
474
+ this.selection?.update();
475
+ }
476
+
477
+ setSelection(element, commit = true) {
478
+ const old = this.selection?.element;
479
+ if (old) {
480
+ old.draggable = false;
481
+ }
482
+ this.selection.update(element);
483
+ if (commit) {
484
+ this.commit();
485
+ }
486
+ }
487
+
488
+ commit() {
489
+ this.redoList.clear();
490
+ const lastHtml = this.htmlDocument.documentElement.innerHTML;
491
+ if (lastHtml === this.lastHtml) {
492
+ return;
493
+ }
494
+ this.undoList.add(this.lastHtml);
495
+ this.lastHtml = lastHtml;
496
+ }
497
+ }