kempo-ui 0.0.43 → 0.0.63

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 (194) hide show
  1. package/.github/copilot-instructions.md +11 -0
  2. package/.github/workflows/publish.yml +66 -0
  3. package/CONTRIBUTING.md +70 -0
  4. package/dist/components/Dialog.js +9 -8
  5. package/dist/components/HtmlEditor.js +91 -0
  6. package/dist/components/Icon.js +2 -2
  7. package/dist/components/Main.js +5 -9
  8. package/dist/components/ShadowComponent.js +1 -1
  9. package/dist/components/SideMenu.js +1 -1
  10. package/dist/components/SidePanel.js +46 -35
  11. package/dist/components/htmlEditorControls/AlignCenter.js +12 -0
  12. package/dist/components/htmlEditorControls/AlignJustify.js +12 -0
  13. package/dist/components/htmlEditorControls/AlignLeft.js +12 -0
  14. package/dist/components/htmlEditorControls/AlignRight.js +12 -0
  15. package/dist/components/htmlEditorControls/Bold.js +12 -0
  16. package/dist/components/htmlEditorControls/BulletList.js +12 -0
  17. package/dist/components/htmlEditorControls/CharacterCount.js +18 -0
  18. package/dist/components/htmlEditorControls/ClearFormatting.js +12 -0
  19. package/dist/components/htmlEditorControls/CodeBlock.js +12 -0
  20. package/dist/components/htmlEditorControls/ControlGroup.js +14 -0
  21. package/dist/components/htmlEditorControls/ControlSpacer.js +6 -0
  22. package/dist/components/htmlEditorControls/CreateLink.js +15 -0
  23. package/dist/components/htmlEditorControls/DropdownControl.js +57 -0
  24. package/dist/components/htmlEditorControls/FormatBlock.js +12 -0
  25. package/dist/components/htmlEditorControls/HtmlEditorControl.js +44 -0
  26. package/dist/components/htmlEditorControls/InlineCode.js +12 -0
  27. package/dist/components/htmlEditorControls/InsertTable.js +15 -0
  28. package/dist/components/htmlEditorControls/Italic.js +12 -0
  29. package/dist/components/htmlEditorControls/Mode.js +9 -0
  30. package/dist/components/htmlEditorControls/NumberList.js +12 -0
  31. package/dist/components/htmlEditorControls/Strikethrough.js +12 -0
  32. package/dist/components/htmlEditorControls/TextBackgroundColor.js +97 -0
  33. package/dist/components/htmlEditorControls/TextColor.js +97 -0
  34. package/dist/components/htmlEditorControls/Underline.js +12 -0
  35. package/dist/components/htmlEditorControls/WordCount.js +18 -0
  36. package/dist/utils/formatCode.js +1 -0
  37. package/docs/components/dropdown.html +2 -2
  38. package/docs/components/html-editor.html +442 -0
  39. package/docs/components/icon.html +2 -7
  40. package/docs/components/photo-viewer.html +14 -14
  41. package/docs/components/side-menu.html +32 -0
  42. package/docs/components/side-panel-dual.html +70 -0
  43. package/docs/components/side-panel-scroll.html +176 -0
  44. package/docs/components/side-panel.html +41 -1
  45. package/docs/icons/arrow_drop_down.svg +1 -0
  46. package/docs/icons/circle.svg +1 -0
  47. package/docs/icons/code.svg +1 -0
  48. package/docs/icons/code_blocks.svg +1 -0
  49. package/docs/icons/copy.svg +1 -0
  50. package/docs/icons/dot.svg +1 -0
  51. package/docs/icons/format_align_center.svg +1 -0
  52. package/docs/icons/format_align_justify.svg +1 -0
  53. package/docs/icons/format_align_left.svg +1 -0
  54. package/docs/icons/format_align_right.svg +1 -0
  55. package/docs/icons/format_bold.svg +1 -0
  56. package/docs/icons/format_clear.svg +1 -0
  57. package/docs/icons/format_color_fill.svg +1 -0
  58. package/docs/icons/format_color_text.svg +1 -0
  59. package/docs/icons/format_h1.svg +1 -0
  60. package/docs/icons/format_h2.svg +1 -0
  61. package/docs/icons/format_h3.svg +1 -0
  62. package/docs/icons/format_h4.svg +1 -0
  63. package/docs/icons/format_h5.svg +1 -0
  64. package/docs/icons/format_h6.svg +1 -0
  65. package/docs/icons/format_italic.svg +1 -0
  66. package/docs/icons/format_list_bulleted.svg +1 -0
  67. package/docs/icons/format_list_numbered.svg +1 -0
  68. package/docs/icons/format_paragraph.svg +1 -0
  69. package/docs/icons/format_underlined.svg +1 -0
  70. package/docs/icons/help.svg +1 -0
  71. package/docs/icons/link.svg +1 -0
  72. package/docs/icons/more_vert.svg +1 -0
  73. package/docs/icons/strikethrough_s.svg +1 -0
  74. package/docs/icons/table.svg +1 -0
  75. package/docs/icons/wysiwyg.svg +1 -0
  76. package/docs/index.html +6 -0
  77. package/docs/nav-1.inc.html +1 -0
  78. package/docs/nav.inc.html +1 -0
  79. package/docs/src/components/Dialog.js +9 -8
  80. package/docs/src/components/HtmlEditor.js +91 -0
  81. package/docs/src/components/Icon.js +2 -2
  82. package/docs/src/components/Main.js +5 -9
  83. package/docs/src/components/ShadowComponent.js +1 -1
  84. package/docs/src/components/SideMenu.js +1 -1
  85. package/docs/src/components/SidePanel.js +46 -35
  86. package/docs/src/components/htmlEditorControls/AlignCenter.js +12 -0
  87. package/docs/src/components/htmlEditorControls/AlignJustify.js +12 -0
  88. package/docs/src/components/htmlEditorControls/AlignLeft.js +12 -0
  89. package/docs/src/components/htmlEditorControls/AlignRight.js +12 -0
  90. package/docs/src/components/htmlEditorControls/Bold.js +12 -0
  91. package/docs/src/components/htmlEditorControls/BulletList.js +12 -0
  92. package/docs/src/components/htmlEditorControls/CharacterCount.js +18 -0
  93. package/docs/src/components/htmlEditorControls/ClearFormatting.js +12 -0
  94. package/docs/src/components/htmlEditorControls/CodeBlock.js +12 -0
  95. package/docs/src/components/htmlEditorControls/ControlGroup.js +14 -0
  96. package/docs/src/components/htmlEditorControls/ControlSpacer.js +6 -0
  97. package/docs/src/components/htmlEditorControls/CreateLink.js +15 -0
  98. package/docs/src/components/htmlEditorControls/DropdownControl.js +57 -0
  99. package/docs/src/components/htmlEditorControls/FormatBlock.js +12 -0
  100. package/docs/src/components/htmlEditorControls/HtmlEditorControl.js +44 -0
  101. package/docs/src/components/htmlEditorControls/InlineCode.js +12 -0
  102. package/docs/src/components/htmlEditorControls/InsertTable.js +15 -0
  103. package/docs/src/components/htmlEditorControls/Italic.js +12 -0
  104. package/docs/src/components/htmlEditorControls/Mode.js +9 -0
  105. package/docs/src/components/htmlEditorControls/NumberList.js +12 -0
  106. package/docs/src/components/htmlEditorControls/Strikethrough.js +12 -0
  107. package/docs/src/components/htmlEditorControls/TextBackgroundColor.js +97 -0
  108. package/docs/src/components/htmlEditorControls/TextColor.js +97 -0
  109. package/docs/src/components/htmlEditorControls/Underline.js +12 -0
  110. package/docs/src/components/htmlEditorControls/WordCount.js +18 -0
  111. package/docs/src/utils/formatCode.js +1 -0
  112. package/icons/arrow_drop_down.svg +1 -0
  113. package/icons/circle.svg +1 -0
  114. package/icons/code.svg +1 -0
  115. package/icons/code_blocks.svg +1 -0
  116. package/icons/copy.svg +1 -0
  117. package/icons/dot.svg +1 -0
  118. package/icons/format_align_center.svg +1 -0
  119. package/icons/format_align_justify.svg +1 -0
  120. package/icons/format_align_left.svg +1 -0
  121. package/icons/format_align_right.svg +1 -0
  122. package/icons/format_bold.svg +1 -0
  123. package/icons/format_clear.svg +1 -0
  124. package/icons/format_color_fill.svg +1 -0
  125. package/icons/format_color_text.svg +1 -0
  126. package/icons/format_h1.svg +1 -0
  127. package/icons/format_h2.svg +1 -0
  128. package/icons/format_h3.svg +1 -0
  129. package/icons/format_h4.svg +1 -0
  130. package/icons/format_h5.svg +1 -0
  131. package/icons/format_h6.svg +1 -0
  132. package/icons/format_italic.svg +1 -0
  133. package/icons/format_list_bulleted.svg +1 -0
  134. package/icons/format_list_numbered.svg +1 -0
  135. package/icons/format_paragraph.svg +1 -0
  136. package/icons/format_underlined.svg +1 -0
  137. package/icons/help.svg +1 -0
  138. package/icons/link.svg +1 -0
  139. package/icons/more_vert.svg +1 -0
  140. package/icons/strikethrough_s.svg +1 -0
  141. package/icons/table.svg +1 -0
  142. package/icons/wysiwyg.svg +1 -0
  143. package/package.json +6 -5
  144. package/scripts/getIcon.js +52 -0
  145. package/src/components/Dialog.js +25 -10
  146. package/src/components/HtmlEditor.js +1548 -0
  147. package/src/components/Icon.js +6 -3
  148. package/src/components/Main.js +22 -23
  149. package/src/components/ShadowComponent.js +0 -1
  150. package/src/components/SideMenu.js +10 -0
  151. package/src/components/SidePanel.js +78 -37
  152. package/src/components/htmlEditorControls/AlignCenter.js +65 -0
  153. package/src/components/htmlEditorControls/AlignJustify.js +65 -0
  154. package/src/components/htmlEditorControls/AlignLeft.js +65 -0
  155. package/src/components/htmlEditorControls/AlignRight.js +65 -0
  156. package/src/components/htmlEditorControls/Bold.js +65 -0
  157. package/src/components/htmlEditorControls/BulletList.js +65 -0
  158. package/src/components/htmlEditorControls/CharacterCount.js +75 -0
  159. package/src/components/htmlEditorControls/ClearFormatting.js +65 -0
  160. package/src/components/htmlEditorControls/CodeBlock.js +72 -0
  161. package/src/components/htmlEditorControls/ControlGroup.js +95 -0
  162. package/src/components/htmlEditorControls/ControlSpacer.js +23 -0
  163. package/src/components/htmlEditorControls/CreateLink.js +121 -0
  164. package/src/components/htmlEditorControls/DropdownControl.js +149 -0
  165. package/src/components/htmlEditorControls/FormatBlock.js +108 -0
  166. package/src/components/htmlEditorControls/HtmlEditorControl.js +126 -0
  167. package/src/components/htmlEditorControls/InlineCode.js +77 -0
  168. package/src/components/htmlEditorControls/InsertTable.js +171 -0
  169. package/src/components/htmlEditorControls/Italic.js +65 -0
  170. package/src/components/htmlEditorControls/Mode.js +66 -0
  171. package/src/components/htmlEditorControls/NumberList.js +65 -0
  172. package/src/components/htmlEditorControls/Strikethrough.js +65 -0
  173. package/src/components/htmlEditorControls/TextBackgroundColor.js +195 -0
  174. package/src/components/htmlEditorControls/TextColor.js +195 -0
  175. package/src/components/htmlEditorControls/Underline.js +65 -0
  176. package/src/components/htmlEditorControls/WordCount.js +76 -0
  177. package/src/utils/formatCode.js +87 -0
  178. package/tests/components/Main.browser-test.js +166 -105
  179. package/tests/components/SidePanel.browser-test.js +62 -8
  180. package/.github/workflows/publish-major.yml +0 -39
  181. package/.github/workflows/publish-minor.yml +0 -39
  182. package/.github/workflows/publish-patch.yml +0 -45
  183. package/docs/icons/arrow-back.svg +0 -1
  184. package/docs/icons/arrow-down-double.svg +0 -1
  185. package/docs/icons/arrow-down.svg +0 -1
  186. package/docs/icons/arrow-forward.svg +0 -1
  187. package/docs/icons/arrow-menu-close.svg +0 -1
  188. package/docs/icons/arrow-menu-open.svg +0 -1
  189. package/docs/icons/arrow-right.svg +0 -1
  190. package/docs/icons/arrow-up-double.svg +0 -1
  191. package/docs/icons/arrow-up.svg +0 -1
  192. package/docs/icons/chevron-left.svg +0 -1
  193. package/docs/icons/chevron-right.svg +0 -1
  194. package/docs/icons/chevron-up.svg +0 -1
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M120-280v-400h80v160h160v-160h80v400h-80v-160H200v160h-80Zm400 0v-160q0-33 23.5-56.5T600-520h160v-80H520v-80h240q33 0 56.5 23.5T840-600v80q0 33-23.5 56.5T760-440H600v80h240v80H520Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M120-280v-400h80v160h160v-160h80v400h-80v-160H200v160h-80Zm400 0v-80h240v-80H600v-80h160v-80H520v-80h240q33 0 56.5 23.5T840-600v240q0 33-23.5 56.5T760-280H520Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M120-280v-400h80v160h160v-160h80v400h-80v-160H200v160h-80Zm600 0v-120H520v-280h80v200h120v-200h80v200h80v80h-80v120h-80Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M120-280v-400h80v160h160v-160h80v400h-80v-160H200v160h-80Zm400 0v-80h240v-80H520v-240h320v80H600v80h160q33 0 56.5 23.5T840-440v80q0 33-23.5 56.5T760-280H520Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M120-280v-400h80v160h160v-160h80v400h-80v-160H200v160h-80Zm480 0q-33 0-56.5-23.5T520-360v-240q0-33 23.5-56.5T600-680h240v80H600v80h160q33 0 56.5 23.5T840-440v80q0 33-23.5 56.5T760-280H600Zm0-160v80h160v-80H600Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M200-200v-100h160l120-360H320v-100h400v100H580L460-300h140v100H200Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M360-200v-80h480v80H360Zm0-240v-80h480v80H360Zm0-240v-80h480v80H360ZM200-160q-33 0-56.5-23.5T120-240q0-33 23.5-56.5T200-320q33 0 56.5 23.5T280-240q0 33-23.5 56.5T200-160Zm0-240q-33 0-56.5-23.5T120-480q0-33 23.5-56.5T200-560q33 0 56.5 23.5T280-480q0 33-23.5 56.5T200-400Zm0-240q-33 0-56.5-23.5T120-720q0-33 23.5-56.5T200-800q33 0 56.5 23.5T280-720q0 33-23.5 56.5T200-640Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M120-80v-60h100v-30h-60v-60h60v-30H120v-60h120q17 0 28.5 11.5T280-280v40q0 17-11.5 28.5T240-200q17 0 28.5 11.5T280-160v40q0 17-11.5 28.5T240-80H120Zm0-280v-110q0-17 11.5-28.5T160-510h60v-30H120v-60h120q17 0 28.5 11.5T280-560v70q0 17-11.5 28.5T240-450h-60v30h100v60H120Zm60-280v-180h-60v-60h120v240h-60Zm180 440v-80h480v80H360Zm0-240v-80h480v80H360Zm0-240v-80h480v80H360Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M360-160v-240q-83 0-141.5-58.5T160-600q0-83 58.5-141.5T360-800h360v80h-80v560h-80v-560H440v560h-80Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M200-120v-80h560v80H200Zm280-160q-101 0-157-63t-56-167v-330h103v336q0 56 28 91t82 35q54 0 82-35t28-91v-336h103v330q0 104-56 167t-157 63Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M478-240q21 0 35.5-14.5T528-290q0-21-14.5-35.5T478-340q-21 0-35.5 14.5T428-290q0 21 14.5 35.5T478-240Zm-36-154h74q0-33 7.5-52t42.5-52q26-26 41-49.5t15-56.5q0-56-41-86t-97-30q-57 0-92.5 30T342-618l66 26q5-18 22.5-39t53.5-21q32 0 48 17.5t16 38.5q0 20-12 37.5T506-526q-44 39-54 59t-10 73Zm38 314q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M440-280H280q-83 0-141.5-58.5T80-480q0-83 58.5-141.5T280-680h160v80H280q-50 0-85 35t-35 85q0 50 35 85t85 35h160v80ZM320-440v-80h320v80H320Zm200 160v-80h160q50 0 85-35t35-85q0-50-35-85t-85-35H520v-80h160q83 0 141.5 58.5T880-480q0 83-58.5 141.5T680-280H520Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M480-160q-33 0-56.5-23.5T400-240q0-33 23.5-56.5T480-320q33 0 56.5 23.5T560-240q0 33-23.5 56.5T480-160Zm0-240q-33 0-56.5-23.5T400-480q0-33 23.5-56.5T480-560q33 0 56.5 23.5T560-480q0 33-23.5 56.5T480-400Zm0-240q-33 0-56.5-23.5T400-720q0-33 23.5-56.5T480-800q33 0 56.5 23.5T560-720q0 33-23.5 56.5T480-640Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M486-160q-76 0-135-45t-85-123l88-38q14 48 48.5 79t85.5 31q42 0 76-20t34-64q0-18-7-33t-19-27h112q5 14 7.5 28.5T694-340q0 86-61.5 133T486-160ZM80-480v-80h800v80H80Zm402-326q66 0 115.5 32.5T674-674l-88 39q-9-29-33.5-52T484-710q-41 0-68 18.5T386-640h-96q2-69 54.5-117.5T482-806Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm240-240H200v160h240v-160Zm80 0v160h240v-160H520Zm-80-80v-160H200v160h240Zm80 0h240v-160H520v160ZM200-680h560v-80H200v80Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-480H200v480Zm80-280v-80h400v80H280Zm0 160v-80h240v80H280Z"/></svg>
package/docs/index.html CHANGED
@@ -89,6 +89,12 @@
89
89
  <p class="tc-muted">Trap keyboard focus within a container for accessibility.</p>
90
90
  </a>
91
91
  </div>
92
+ <div class="span-12 t-span-6 d-span-4 px">
93
+ <a href="./components/html-editor.html" class="card mb no-link d-b">
94
+ <h3 class="tc-primary">HTML Editor</h3>
95
+ <p class="tc-muted">WYSIWYG editor with formatting tools and dual editing modes.</p>
96
+ </a>
97
+ </div>
92
98
  <div class="span-12 t-span-6 d-span-4 px">
93
99
  <a href="./components/icon.html" class="card mb no-link d-b">
94
100
  <h3 class="tc-primary">Icon</h3>
@@ -38,6 +38,7 @@
38
38
  <a href="../components/dialog.html">Dialog</a>
39
39
  <a href="../components/dropdown.html">Dropdown</a>
40
40
  <a href="../components/focus-capture.html">FocusCapture</a>
41
+ <a href="../components/html-editor.html">HTML Editor</a>
41
42
  <a href="../components/icon.html">Icon</a>
42
43
  <a href="../components/import.html">Import</a>
43
44
  <a href="../components/photo-viewer.html">Photo Viewer</a>
package/docs/nav.inc.html CHANGED
@@ -38,6 +38,7 @@
38
38
  <a href="./components/content-slider.html">Content Slider</a>
39
39
  <a href="./components/dialog.html">Dialog</a>
40
40
  <a href="./components/focus-capture.html">FocusCapture</a>
41
+ <a href="./components/html-editor.html">HTML Editor</a>
41
42
  <a href="./components/icon.html">Icon</a>
42
43
  <a href="./components/import.html">Import</a>
43
44
  <a href="./components/photo-viewer.html">Photo Viewer</a>
@@ -1,4 +1,4 @@
1
- import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-all.min.js";import{boolExists}from"../utils/propConverters.js";import"./Icon.js";import"./FocusCapture.js";const firstFocusable=e=>e.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')[0];export default class Dialog extends ShadowComponent{static properties={opened:{type:Boolean,reflect:!0,converter:boolExists},closeBtn:{type:Boolean,reflect:!0,attribute:"close-btn",converter:boolExists},overlayClose:{type:Boolean,reflect:!0,attribute:"overlay-close",converter:boolExists},disableKeyboardClose:{type:Boolean,reflect:!0,attribute:"disable-keyboard-close",converter:boolExists},confirmText:{type:String,reflect:!0,attribute:"confirm-text"},confirmClasses:{type:String,reflect:!0,attribute:"confirm-classes"},cancelText:{type:String,reflect:!0,attribute:"cancel-text"},cancelClasses:{type:String,reflect:!0,attribute:"cancel-classes"}};constructor(){super(),this.opened=!1,this.closeBtn=!0,this.overlayClose=!0,this.disableKeyboardClose=!1,this.confirmText="",this.confirmClasses="success ml",this.cancelText="",this.cancelClasses="",this.confirmAction=()=>{},this.cancelAction=()=>{},this.closeCallback=()=>{},this.previousFocus=null}handleClick=e=>{const{target:t}=e,o=t.id||t.closest("[id]")?.id;"overlay"===o&&this.overlayClose||"close"===o?this.close():"cancel"===o?(this.cancelAction(e),e.defaultPrevented||this.close()):"confirm"===o&&(this.confirmAction(e),e.defaultPrevented||this.close())};handleKeydown=e=>{this.disableKeyboardClose||27!==e.keyCode||this.close()};connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("keydown",this.handleKeydown)}updated(e){super.updated(e),e.has("opened")&&this.dispatchEvent(new CustomEvent(this.opened?"opened":"close"))}open(){this.opened=!0,window.addEventListener("keydown",this.handleKeydown),document.body.classList.add("no-scroll");const e=this.updateComplete||this.requestUpdate();e&&e.then?e.then(()=>{const e=this.shadowRoot.querySelector("[autofocus]")||firstFocusable(this.shadowRoot);e&&e.focus()}):setTimeout(()=>{const e=this.shadowRoot.querySelector("[autofocus]")||firstFocusable(this.shadowRoot);e&&e.focus()},0)}close(){this.opened=!1,this.blur(),this.closeCallback(),window.removeEventListener("keydown",this.handleKeydown),document.body.classList.remove("no-scroll")}toggle(){this.opened?this.close():this.open()}focus(){const e=firstFocusable(this.shadowRoot);e&&(this.previousFocus=document.activeElement,e.focus())}blur(){this.previousFocus&&this.previousFocus.focus()}hasTitle(){return!!this.querySelector('[slot="title"]')}static styles=css`
1
+ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-all.min.js";import{boolExists}from"../utils/propConverters.js";import"./Icon.js";import"./FocusCapture.js";const firstFocusable=e=>e.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')[0];export default class Dialog extends ShadowComponent{static properties={opened:{type:Boolean,reflect:!0,converter:boolExists},closeBtn:{type:Boolean,reflect:!0,attribute:"close-btn",converter:boolExists},overlayClose:{type:Boolean,reflect:!0,attribute:"overlay-close",converter:boolExists},disableKeyboardClose:{type:Boolean,reflect:!0,attribute:"disable-keyboard-close",converter:boolExists},confirmText:{type:String,reflect:!0,attribute:"confirm-text"},confirmClasses:{type:String,reflect:!0,attribute:"confirm-classes"},cancelText:{type:String,reflect:!0,attribute:"cancel-text"},cancelClasses:{type:String,reflect:!0,attribute:"cancel-classes"}};constructor(){super(),this.opened=!1,this.closeBtn=!0,this.overlayClose=!0,this.disableKeyboardClose=!1,this.confirmText="",this.confirmClasses="success ml",this.cancelText="",this.cancelClasses="",this.confirmAction=()=>{},this.cancelAction=()=>{},this.closeCallback=()=>{},this.previousFocus=null}handleClick=e=>{const{target:t}=e,o=t.id||t.closest("[id]")?.id;"overlay"===o&&this.overlayClose||"close"===o?this.close():"cancel"===o&&(this.cancelAction(e),e.defaultPrevented||this.close())};handleSubmit=e=>{e.preventDefault(),this.confirmAction(e),e.keepDialogOpen||this.close()};handleSlotKeydown=e=>{if("Enter"===e.key&&this.confirmText){const t=e.target;if("INPUT"===t.tagName||"TEXTAREA"===t.tagName){e.preventDefault();const t=this.shadowRoot.querySelector("form");t&&t.requestSubmit()}}};handleKeydown=e=>{this.disableKeyboardClose||27!==e.keyCode||this.close()};connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("keydown",this.handleKeydown)}updated(e){super.updated(e),e.has("opened")&&this.dispatchEvent(new CustomEvent(this.opened?"opened":"close"))}open(){this.opened=!0,window.addEventListener("keydown",this.handleKeydown),document.body.classList.add("no-scroll");const e=this.updateComplete||this.requestUpdate();e&&e.then?e.then(()=>{const e=this.shadowRoot.querySelector("[autofocus]")||firstFocusable(this.shadowRoot);e&&e.focus()}):setTimeout(()=>{const e=this.shadowRoot.querySelector("[autofocus]")||firstFocusable(this.shadowRoot);e&&e.focus()},0)}close(){this.opened=!1,this.blur(),this.closeCallback(),window.removeEventListener("keydown",this.handleKeydown),document.body.classList.remove("no-scroll")}toggle(){this.opened?this.close():this.open()}focus(){const e=firstFocusable(this.shadowRoot);e&&(this.previousFocus=document.activeElement,e.focus())}blur(){this.previousFocus&&this.previousFocus.focus()}hasTitle(){return!!this.querySelector('[slot="title"]')}static styles=css`
2
2
  :host {
3
3
  position: fixed;
4
4
  top: 0;
@@ -75,14 +75,15 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
75
75
  padding: var(--spacer_h);
76
76
  }
77
77
  `;render(){return html`
78
- <button id="overlay" aria-label="Close the Dialog" @click=${this.handleClick}></button>
78
+ <button id="overlay" type="button" aria-label="Close the Dialog" @click=${this.handleClick}></button>
79
79
  <div id="wrapper">
80
80
  <k-focus-capture>
81
- <div
81
+ <form
82
82
  id="dialog"
83
83
  role="dialog"
84
84
  aria-modal="true"
85
85
  aria-labelledby="title"
86
+ @submit=${this.handleSubmit}
86
87
  >
87
88
  <div
88
89
  id="header"
@@ -92,29 +93,29 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
92
93
  <slot name="title"></slot>
93
94
  </div>
94
95
  ${this.closeBtn?html`
95
- <button id="close" @click=${this.handleClick}>
96
+ <button id="close" type="button" @click=${this.handleClick}>
96
97
  <k-icon name="close"></k-icon>
97
98
  </button>
98
99
  `:""}
99
100
  </div>
100
101
  <div id="body">
101
- <slot></slot>
102
+ <slot @keydown=${this.handleSlotKeydown}></slot>
102
103
  </div>
103
104
  ${this.cancelText||this.confirmText?html`
104
105
  <div id="footer">
105
106
  ${this.cancelText?html`
106
- <button id="cancel" class="${this.cancelClasses}" @click=${this.handleClick}>
107
+ <button id="cancel" type="button" class="${this.cancelClasses}" @click=${this.handleClick}>
107
108
  ${this.cancelText}
108
109
  </button>
109
110
  `:""}
110
111
  ${this.confirmText?html`
111
- <button id="confirm" class="${this.confirmClasses}" @click=${this.handleClick}>
112
+ <button id="confirm" type="submit" class="${this.confirmClasses}">
112
113
  ${this.confirmText}
113
114
  </button>
114
115
  `:""}
115
116
  </div>
116
117
  `:""}
117
- </div>
118
+ </form>
118
119
  </k-focus-capture>
119
120
  </div>
120
121
  `}static create(e="",t={}){!1!==t.closeExisting&&document.querySelectorAll("k-dialog").forEach(e=>e.close());const{removeOnClose:o=!0,closeCallback:s=()=>{},title:i="",titleClasses:l="pyh px m0"}=t,a=new Dialog;if(Object.assign(a,{opened:!0,...t,closeCallback:(...e)=>{o&&a.remove(),s(...e)}}),i){const e=document.createElement("h5");e.slot="title",e.className=l,i instanceof HTMLElement?e.appendChild(i):e.innerHTML=i,a.appendChild(e)}if(e instanceof HTMLElement||e instanceof DocumentFragment)a.appendChild(e);else if(e){if(/<[^>]+>/.test(e))a.innerHTML+=e;else{const t=document.createElement("p");t.className="p",t.textContent=e,a.appendChild(t)}}return t.width&&a.style.setProperty("--width",t.width),t.minWidth&&a.style.setProperty("--min_width",t.minWidth),t.maxWidth&&a.style.setProperty("--max_width",t.maxWidth),t.height&&a.style.setProperty("--height",t.height),t.minHeight&&a.style.setProperty("--min_height",t.minHeight),t.maxHeight&&a.style.setProperty("--max_height",t.maxHeight),document.body.appendChild(a),a.open(),a}static confirm(e,t,o={}){return Dialog.create(e,{title:o.title||"Confirm",closeBtn:!1,overlayClose:!1,disableKeyboardClose:!0,confirmText:"Yes",confirmClasses:"success ml",confirmAction:()=>t(!0),cancelText:"No",cancelClasses:"danger",cancelAction:()=>t(!1),...o})}static alert(e,t=()=>{},o={}){return Dialog.create(e,{title:o.title||"Alert",closeCallback:t,cancelText:"Ok",...o})}static error(e,t=()=>{},o={}){return Dialog.create(e,{title:o.title||"Error",titleClasses:"pyh px m0 tc-danger",closeCallback:t,cancelText:"Ok",...o})}static success(e,t=()=>{},o={}){return Dialog.create(e,{title:o.title||"Success",titleClasses:"pyh px m0 tc-success",closeCallback:t,cancelText:"Ok",...o})}}customElements.define("k-dialog",Dialog);
@@ -0,0 +1,91 @@
1
+ import{html,css}from"../lit-all.min.js";import ShadowComponent from"./ShadowComponent.js";import formatCode from"../utils/formatCode.js";import debounce from"../utils/debounce.js";export default class HtmlEditor extends ShadowComponent{static formAssociated=!0;static properties={name:{type:String,reflect:!0},value:{type:String,reflect:!0},selection:{type:Object,state:!0},mode:{type:String,reflect:!0},hasTopToolbar:{type:Boolean,state:!0},hasBottomToolbar:{type:Boolean,state:!0}};constructor(){super(),this.internals=this.attachInternals(),this.name="",this.value="",this.selection=null,this.cursor=null,this.mode="visual",this.hasTopToolbar=!1,this.hasBottomToolbar=!1,this.skipSync=!1,this.savedSelection=null,this.debouncedDispatchChange=debounce(()=>{this.value=this.editorEl.innerHTML},300)}connectedCallback(){super.connectedCallback(),this.hasAttribute("value")&&(this.value=this.getAttribute("value")),this.slotObserver=new MutationObserver(()=>{this.updateToolbarVisibility()}),this.slotObserver.observe(this,{childList:!0,subtree:!0}),this.updateToolbarVisibility()}disconnectedCallback(){super.disconnectedCallback(),this.slotObserver?.disconnect(),this.boundUpdateSelection&&(this.shadowRoot.removeEventListener("selectionchange",this.boundUpdateSelection),this.editorEl&&(this.editorEl.removeEventListener("mouseup",this.boundUpdateSelection),this.editorEl.removeEventListener("keyup",this.boundUpdateSelection),this.editorEl.removeEventListener("focus",this.boundUpdateSelection)))}updateToolbarVisibility(){const e=Array.from(this.children).filter(e=>"toolbar-top"===e.getAttribute("slot")),t=Array.from(this.children).filter(e=>"toolbar-bottom"===e.getAttribute("slot"));this.hasTopToolbar=e.length>0,this.hasBottomToolbar=t.length>0}updated(e){super.updated(e),e.has("value")&&(this.syncContent(),this.updateFormValue(),this.dispatchEvent(new CustomEvent("change",{detail:{value:this.value},bubbles:!0}))),e.has("mode")&&(this.syncContent(),this.dispatchEvent(new CustomEvent("mode-changed",{detail:{mode:this.mode},bubbles:!0})))}firstUpdated(){this.editorEl=this.shadowRoot.querySelector(".editor"),this.textareaEl=this.shadowRoot.querySelector("textarea"),this.value&&this.syncContent(),this.boundUpdateSelection=this.updateSelection.bind(this),this.shadowRoot.addEventListener("selectionchange",this.boundUpdateSelection),this.editorEl.addEventListener("mouseup",this.boundUpdateSelection),this.editorEl.addEventListener("keyup",this.boundUpdateSelection),this.editorEl.addEventListener("focus",this.boundUpdateSelection),this.editorEl.addEventListener("keydown",this.handleTableNavigation),this.dispatchEvent(new CustomEvent("ready",{detail:{value:this.value},bubbles:!0}))}updateFormValue(){this.internals.setFormValue(this.getValue())}formResetCallback(){this.value=""}formStateRestoreCallback(e){this.value=e}handleTableNavigation=e=>{if("Tab"!==e.key&&"Enter"!==e.key)return;if("visual"!==this.mode)return;const t=this.shadowRoot.getSelection()||window.getSelection();if(!t.rangeCount)return;let n=t.getRangeAt(0).startContainer;n.nodeType===Node.TEXT_NODE&&(n=n.parentElement);const o=n.closest("td, th");if(o)if(e.preventDefault(),"Tab"===e.key){const n=o.parentElement,i=Array.from(n.cells),r=i.indexOf(o);if(e.shiftKey){let e=i[r-1];if(!e){const t=n.previousElementSibling;t&&(e=t.cells[t.cells.length-1])}if(e){const n=document.createRange();n.selectNodeContents(e),n.collapse(!1),t.removeAllRanges(),t.addRange(n),e.focus()}}else{let e=i[r+1];if(!e){const t=n.nextElementSibling;t&&(e=t.cells[0])}if(e){const n=document.createRange();n.selectNodeContents(e),n.collapse(!1),t.removeAllRanges(),t.addRange(n),e.focus()}}}else if("Enter"===e.key){const n=o.parentElement,i=Array.from(n.cells).indexOf(o);if(e.shiftKey){const e=n.previousElementSibling;if(e&&e.cells[i]){const n=e.cells[i],o=document.createRange();o.selectNodeContents(n),o.collapse(!1),t.removeAllRanges(),t.addRange(o),n.focus()}}else{const e=n.nextElementSibling;if(e&&e.cells[i]){const n=e.cells[i],o=document.createRange();o.selectNodeContents(n),o.collapse(!1),t.removeAllRanges(),t.addRange(o),n.focus()}else{const e=o.closest("table");if(e){const n=document.createElement("p");n.innerHTML="<br>",e.nextSibling?e.parentNode.insertBefore(n,e.nextSibling):e.parentNode.appendChild(n);const o=document.createRange();o.setStart(n,0),o.setEnd(n,0),t.removeAllRanges(),t.addRange(o),n.focus()}}}}};updateSelection=()=>{if("visual"!==this.mode)return void(this.selection=null);const e=this.shadowRoot.getSelection()||window.getSelection();if(!e.rangeCount)return void(this.selection=null);const t=e.getRangeAt(0),n=this.editorEl.contains(t.startContainer)||this.editorEl===t.startContainer,o=this.editorEl.contains(t.endContainer)||this.editorEl===t.endContainer;if(!n||!o)return void(this.selection=null);const i=t.toString();t.collapsed?(this.selection=null,this.cursor={container:t.startContainer,offset:t.startOffset}):(this.cursor=null,this.selection={startContainer:t.startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset,text:i,collapsed:!1})};handleEditorInput=()=>{this.debouncedDispatchChange(),this.dispatchEvent(new CustomEvent("input",{detail:{value:this.editorEl.innerHTML}}))};handleTextareaInput=e=>{"code"===this.mode&&(this.value=e.target.value)};handleEditorPaste=e=>{e.preventDefault();const t=e.clipboardData.getData("text/plain");document.execCommand("insertText",!1,t)};handleEditorBlur=()=>{if("visual"===this.mode){const e=this.shadowRoot.getSelection()||window.getSelection();if(e.rangeCount>0){const t=e.getRangeAt(0);this.editorEl.contains(t.commonAncestorContainer)&&(this.savedSelection={startContainer:t.startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset,collapsed:t.collapsed})}const t=this.cleanupHtml(this.editorEl.innerHTML);t!==this.value&&(this.value=t,this.syncContent())}};setMode(e){return["visual","code"].includes(e)&&("visual"===this.mode&&"code"===e&&(this.value=this.cleanupHtml(this.editorEl.innerHTML)),this.mode=e),this}toggleMode(){const e="visual"===this.mode?"code":"visual";return this.setMode(e),this}getValue(){if("visual"===this.mode){return(this.editorEl?this.editorEl.innerHTML:this.value).replace(/\u200B/g,"")}return this.value}setValue(e){return this.value=e,this.syncContent(),this}clear(){return this.value="",this.syncContent(),this}cleanupHtml(e){const t=document.createElement("div");t.innerHTML=e;const n=(e,t)=>{e.querySelectorAll(t).forEach(n=>{let o=n.parentElement;for(;o&&o!==e;){if(o.tagName.toLowerCase()===t){for(;n.firstChild;)n.parentNode.insertBefore(n.firstChild,n);n.parentNode.removeChild(n);break}o=o.parentElement}})};return["code","a","span","strong","em","b","i","u","s"].forEach(e=>n(t,e)),["pre","div","p","h1","h2","h3","h4","h5","h6","blockquote"].forEach(e=>n(t,e)),t.querySelectorAll("*").forEach(e=>{if(!e.hasAttribute("style"))return;const t=e.style,n=["inherit","rgba(0, 0, 0, 0)","transparent","initial","unset"];["font-size","font-family","background-color","line-height","font-weight","font-style"].forEach(e=>{const o=t.getPropertyValue(e);o&&n.some(e=>o.includes(e))&&t.removeProperty(e)}),0===t.length&&e.removeAttribute("style")}),(e=>{e.querySelectorAll("span").forEach(e=>{if(!e.className&&!e.id&&!e.hasAttribute("style")){for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.parentNode.removeChild(e)}})})(t),(e=>{const t=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null),n=[];for(;t.nextNode();)n.push(t.currentNode);n.forEach(e=>{e.textContent=e.textContent.replace(/\u00A0/g," ")})})(t),t.innerHTML}bold(){return this.execCommand("bold"),this}italic(){return this.execCommand("italic"),this}underline(){return this.execCommand("underline"),this}strikethrough(){return this.execCommand("strikeThrough"),this}orderedList(){return this.execCommand("insertOrderedList"),this}unorderedList(){return this.execCommand("insertUnorderedList"),this}alignLeft(){return this.execCommand("justifyLeft"),this}alignCenter(){return this.execCommand("justifyCenter"),this}alignRight(){return this.execCommand("justifyRight"),this}alignJustify(){return this.execCommand("justifyFull"),this}setTextColor(e){return this.execCommand("foreColor",e),this}removeTextColor(){return this.execCommand("removeFormat"),this}setTextBackgroundColor(e){return this.execCommand("backColor",e),this}removeTextBackgroundColor(){const e=this.shadowRoot.getSelection();if(!e||0===e.rangeCount)return this;const t=e.getRangeAt(0);if(t.collapsed)return this;const n=t.extractContents(),o=document.createTreeWalker(n,NodeFilter.SHOW_ELEMENT,null),i=e=>{e.style&&(e.style.backgroundColor="",e.style.cssText||e.removeAttribute("style"))};let r;for(;r=o.nextNode();)i(r);return i(n.firstChild),t.insertNode(n),this.editorEl.dispatchEvent(new Event("input",{bubbles:!0})),this}removeFormat(){if("visual"!==this.mode)return this;if(this.selection)return this.execCommand("removeFormat"),this;const e=this.shadowRoot.getSelection()||window.getSelection();if(!e.rangeCount)return this;let t=e.getRangeAt(0).startContainer;t.nodeType===Node.TEXT_NODE&&(t=t.parentElement);const n=t.closest(["B","I","U","S","STRONG","EM","CODE","MARK","SUB","SUP","SPAN"].map(e=>e.toLowerCase()).join(","));if(n&&this.editorEl.contains(n)){const t=n.textContent,o=document.createTextNode(t);n.replaceWith(o);const i=document.createRange();i.setStart(o,t.length),i.setEnd(o,t.length),e.removeAllRanges(),e.addRange(i),this.value=this.editorEl.innerHTML}return this}formatBlock(e){return this.execCommand("formatBlock",e),this}insertHTML(e){return this.execCommand("insertHTML",e),this}insertTable(e,t,n=!1,o=null){if("visual"!==this.mode)return this;const i=this.getValueWithSelectionMarkers();let r=i.html;const s=document.createElement("table");if(s.style.cssText="border-collapse: collapse; width: 100%;",n){const e=document.createElement("thead"),n=document.createElement("tr");for(let e=0;e<t;e++){const t=document.createElement("th");t.style.cssText="border: 1px solid var(--border-color, #ccc); padding: 0.5rem; text-align: left; background-color: var(--background-secondary, #f5f5f5);",o&&o[0]&&void 0!==o[0][e]?t.innerHTML=o[0][e]:t.innerHTML=`Header ${e+1}`,n.appendChild(t)}e.appendChild(n),s.appendChild(e)}const l=document.createElement("tbody"),a=n?1:0;for(let n=0;n<e;n++){const e=document.createElement("tr");for(let i=0;i<t;i++){const t=document.createElement("td");t.style.cssText="border: 1px solid var(--border-color, #ccc); padding: 0.5rem;",o&&o[n+a]&&void 0!==o[n+a][i]?t.innerHTML=o[n+a][i]:t.innerHTML="​",e.appendChild(t)}l.appendChild(e)}s.appendChild(l);const d=document.createElement("div");d.appendChild(s);const c=d.innerHTML,h=document.createElement("p");h.innerHTML="<br>";const u=c+h.outerHTML;i.hasCursor?r=r.replace("￰",u+"￰"):i.hasSelection?(r=r.replace(i.selectionStart,"").replace(i.selectionEnd,""),r+=u):r+=u;const m={hasCursor:i.hasCursor,hasSelection:!1,cursorMarker:"￰"};return this.setValueFromSelectionMarkers(r,m),this}insertElementAtCursor(e,t=!0){if("visual"!==this.mode)return this;const n=this.getValueWithSelectionMarkers();let o=n.html;t&&(e.textContent="￱"+(e.textContent||"")+"￲");const i=e.outerHTML;if(n.hasCursor)o=o.replace("￰",i);else{const t=["code","a","span","strong","em","b","i","u","s","mark","sub","sup"],n=e.tagName.toLowerCase();t.includes(n)?o=o+"<p>"+i+"</p>":o+=i}const r={hasCursor:!1,hasSelection:t,selectionStart:"￱",selectionEnd:"￲",selectedText:e.textContent||""};return this.setValueFromSelectionMarkers(o,r),this}replaceSelectionWithElement(e,t=!0){if("visual"!==this.mode)return this;const n=this.getValueWithSelectionMarkers();if(!n.hasSelection)return this;let o=n.html;t&&(e.textContent="￱"+e.textContent+"￲");const i=e.outerHTML,r="￱"+n.selectedText+"￲";o=o.replace(r,i);const s={hasCursor:!1,hasSelection:t,selectionStart:"￱",selectionEnd:"￲",selectedText:n.selectedText};return this.setValueFromSelectionMarkers(o,s),this}getSelection(){if("visual"!==this.mode)return null;this.editorEl.focus();const e=window.getSelection();if(!e.rangeCount)return null;const t=e.getRangeAt(0);return this.editorEl.contains(t.commonAncestorContainer)?{text:e.toString(),html:t.cloneContents().textContent?(new XMLSerializer).serializeToString(t.cloneContents()):"",range:t,selection:e}:null}getSelectedText(){const e=this.getSelection();return e?e.text:""}getSelectedHTML(){const e=this.getSelection();return e?e.html:""}setSelection(e,t,n,o){if("visual"!==this.mode)return this;this.editorEl.focus();const i=window.getSelection(),r=document.createRange();return r.setStart(e,t),r.setEnd(n,o),i.removeAllRanges(),i.addRange(r),this}selectAll(){return"visual"===this.mode?this.execCommand("selectAll"):this.textareaEl.select(),this}replaceSelection(e){if("visual"!==this.mode)return this;const t=this.getSelection();if(!t)return this;t.range.deleteContents();const n=t.range.createContextualFragment(e);return t.range.insertNode(n),this.value=this.editorEl.innerHTML,this}deleteSelection(){if("visual"===this.mode)this.execCommand("delete");else{const e=this.textareaEl.selectionStart,t=this.textareaEl.selectionEnd;this.textareaEl.value=this.textareaEl.value.substring(0,e)+this.textareaEl.value.substring(t),this.value=this.textareaEl.value}return this}getTextPosition(e,t){const n=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null);let o=0;for(;n.nextNode();){const e=n.currentNode;if(t.contains(e))return o;o+=e.textContent.length}return o}wrapSelection(e,t,n=null){if("visual"!==this.mode)return this;let o;if(n)o=n;else{const e=window.getSelection();if(!e.rangeCount||e.isCollapsed)return this;const t=e.getRangeAt(0);if(!this.editorEl.contains(t.commonAncestorContainer))return this;o=e.toString()}if(!o)return this;this.editorEl.focus();const i=e.match(/<([a-zA-Z]+)/);if(!i)return this;const r=i[1],s=document.createElement("div");s.innerHTML=this.getValue();const l=s.textContent.indexOf(o);if(-1===l)return this;const a=document.createTreeWalker(s,NodeFilter.SHOW_TEXT|NodeFilter.SHOW_ELEMENT,null);let d=0,c=null,h=0,u=null,m=0;const f=[];for(;a.nextNode();){const e=a.currentNode;if(e.nodeType===Node.ELEMENT_NODE){if(e.tagName.toLowerCase()===r){const t=this.getTextPosition(s,e),n=t+e.textContent.length,i=l+o.length;!(n<=l||t>=i)&&f.push(e)}continue}const t=e.textContent.length,n=d,i=d+t;if(!c&&i>l&&(c=e,h=l-n),i>=l+o.length){u=e,m=l+o.length-n;break}d+=t}if(f.length>0)f.forEach(e=>{const t=e.parentNode,n="pre"===e.tagName.toLowerCase(),o=[],i=e=>{o.push(e),Array.from(e.children).forEach(e=>i(e))};if(i(e),n){const n=document.createElement("p");for(;e.firstChild;)n.appendChild(e.firstChild);t.replaceChild(n,e)}else o.reverse().forEach(e=>{if(e.parentNode){for(;e.firstChild;)e.parentNode.insertBefore(e.firstChild,e);e.parentNode.removeChild(e)}})});else if(c&&u){const n=document.createRange();n.setStart(c,h),n.setEnd(u,m);const o=n.extractContents(),i=document.createElement("div");i.innerHTML=e+t;const l=i.firstChild;let a=l;for(;a.firstChild&&a.firstChild.nodeType===Node.ELEMENT_NODE;)a=a.firstChild;if(a.appendChild(o),n.insertNode(l),"pre"===r){let e=l.parentNode;for(;e&&e!==s;){if(e.tagName&&"p"===e.tagName.toLowerCase()){const t=[];let n=l.nextSibling;for(;n;){const e=n.nextSibling;t.push(n),n=e}if(e.parentNode.insertBefore(l,e.nextSibling),t.length>0&&t.some(e=>e.textContent.trim())){const e=document.createElement("p");t.forEach(t=>e.appendChild(t)),l.parentNode.insertBefore(e,l.nextSibling)}break}e=e.parentNode}}}return this.setValue(s.innerHTML),this.editorEl.focus(),setTimeout(()=>{const e=this.editorEl.textContent.indexOf(o);if(-1===e)return;const t=document.createTreeWalker(this.editorEl,NodeFilter.SHOW_TEXT,null);let n=0,i=null,r=0,s=null,l=0;for(;t.nextNode();){const a=t.currentNode,d=a.textContent.length,c=n,h=n+d;if(null===i&&h>e&&(i=a,r=e-c),h>=e+o.length){s=a,l=e+o.length-c;break}n+=d}if(i&&s){const e=document.createRange();e.setStart(i,r),e.setEnd(s,l);const t=window.getSelection();t.removeAllRanges(),t.addRange(e)}},0),this}insertAtCursor(e){return this.insertHTML(e),this}createLink(e){return this.execCommand("createLink",e),this}unlink(){return this.execCommand("unlink"),this}insertImage(e){return this.execCommand("insertImage",e),this}undo(){return this.execCommand("undo"),this}redo(){return this.execCommand("redo"),this}execCommand(e,t=null){"visual"===this.mode&&(this.editorEl.focus(),document.execCommand(e,!1,t),this.value=this.editorEl.innerHTML)}captureSelection(){if("visual"!==this.mode)return null;const e=window.getSelection();if(!e.rangeCount)return null;const t=e.getRangeAt(0);if(!this.editorEl.contains(t.commonAncestorContainer))return null;const n=t.toString();return t.collapsed?null:{startContainer:t.startContainer,startOffset:t.startOffset,endContainer:t.endContainer,endOffset:t.endOffset,text:n,collapsed:t.collapsed}}restoreSavedSelection(){if(!this.savedSelection)return!1;const e=this.shadowRoot.getSelection()||window.getSelection(),t=document.createRange();try{return t.setStart(this.savedSelection.startContainer,this.savedSelection.startOffset),t.setEnd(this.savedSelection.endContainer,this.savedSelection.endOffset),e.removeAllRanges(),e.addRange(t),!0}catch(e){return this.savedSelection=null,!1}}clearSavedSelection(){this.savedSelection=null}getValueWithSelectionMarkers(){if("visual"!==this.mode)return{html:this.value,hasCursor:!1,hasSelection:!1};const e=this.shadowRoot.getSelection()||window.getSelection();if(!e.rangeCount&&!this.restoreSavedSelection())return{html:this.editorEl.innerHTML,hasCursor:!1,hasSelection:!1};if(!e.rangeCount)return{html:this.editorEl.innerHTML,hasCursor:!1,hasSelection:!1};const t=e.getRangeAt(0);if(!this.editorEl.contains(t.commonAncestorContainer))return{html:this.editorEl.innerHTML,hasCursor:!1,hasSelection:!1};const n=t.toString();if(t.collapsed){const e=document.createTextNode("￰"),n=document.createRange();n.setStart(t.startContainer,t.startOffset),n.insertNode(e);const o=this.editorEl.innerHTML;return e.remove(),{html:o,hasCursor:!0,hasSelection:!1,cursorMarker:"￰",selectedText:""}}{const e=document.createTextNode("￱"),o=document.createTextNode("￲"),i=document.createRange();i.setStart(t.endContainer,t.endOffset),i.insertNode(o),i.setStart(t.startContainer,t.startOffset),i.insertNode(e);const r=this.editorEl.innerHTML;return e.remove(),o.remove(),{html:r,hasCursor:!1,hasSelection:!0,selectionStart:"￱",selectionEnd:"￲",selectedText:n}}}setValueFromSelectionMarkers(e,t){if("visual"!==this.mode)return this;const n=t.cursorMarker||"￰",o=t.selectionStart||"￱",i=t.selectionEnd||"￲";if(this.editorEl.innerHTML=e,t.hasCursor){const e=document.createTreeWalker(this.editorEl,NodeFilter.SHOW_TEXT,null);for(;e.nextNode();){const t=e.currentNode,o=t.textContent.indexOf(n);if(-1!==o){t.textContent=t.textContent.replace(n,"");const e=document.createRange();e.setStart(t,o),e.setEnd(t,o);const i=this.shadowRoot.getSelection()||window.getSelection();i.removeAllRanges(),i.addRange(e);break}}}else if(t.hasSelection){const e=document.createTreeWalker(this.editorEl,NodeFilter.SHOW_TEXT,null);let t=null,n=0,r=null,s=0;for(;e.nextNode();){const l=e.currentNode,a=l.textContent.indexOf(o);-1!==a&&(t=l,n=a,l.textContent=l.textContent.replace(o,""));const d=l.textContent.indexOf(i);if(-1!==d&&(r=l,s=d,l.textContent=l.textContent.replace(i,"")),t&&r)break}if(t&&r){const e=document.createRange();e.setStart(t,n),e.setEnd(r,s);const o=this.shadowRoot.getSelection()||window.getSelection();o.removeAllRanges(),o.addRange(e)}}return this.editorEl.focus(),this}syncContent(){if(this.editorEl&&this.textareaEl&&!this.skipSync)if("visual"===this.mode)this.editorEl.innerHTML!==this.value&&(this.editorEl.innerHTML=this.value);else{const e=formatCode(this.value);this.textareaEl.value!==e&&(this.textareaEl.value=e)}}static styles=css`
2
+ :host {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 0;
6
+ height: 300px;
7
+ }
8
+
9
+ .toolbar-top,
10
+ .toolbar-bottom {
11
+ display: flex;
12
+ flex-wrap: wrap;
13
+ align-items: center;
14
+ gap: 0;
15
+ background: var(--bg-secondary);
16
+ min-height: 40px;
17
+ }
18
+
19
+ .editor-container {
20
+ position: relative;
21
+ flex: 1;
22
+ min-height: 0;
23
+ overflow: hidden;
24
+ }
25
+
26
+ .editor,
27
+ textarea {
28
+ width: 100%;
29
+ height: 100%;
30
+ padding: 1rem;
31
+ border: 1px solid var(--border-color);
32
+ background: var(--bg-primary);
33
+ color: var(--text-primary);
34
+ font-family: inherit;
35
+ font-size: inherit;
36
+ line-height: 1.5;
37
+ overflow: auto;
38
+ box-sizing: border-box;
39
+ }
40
+
41
+ .editor {
42
+ outline: none;
43
+ }
44
+
45
+ .editor:focus {
46
+ border-color: var(--primary-color);
47
+ }
48
+
49
+ textarea {
50
+ resize: none;
51
+ font-family: monospace;
52
+ }
53
+
54
+ textarea:focus {
55
+ outline: none;
56
+ border-color: var(--primary-color);
57
+ }
58
+
59
+ .editor[hidden],
60
+ textarea[hidden] {
61
+ display: none;
62
+ }
63
+ `;render(){return html`
64
+ ${this.hasTopToolbar?html`
65
+ <div class="toolbar-top bb">
66
+ <slot name="toolbar-top"></slot>
67
+ </div>
68
+ `:""}
69
+
70
+ <div class="editor-container">
71
+ <div
72
+ class="editor"
73
+ contenteditable="true"
74
+ ?hidden=${"visual"!==this.mode}
75
+ @input=${this.handleEditorInput}
76
+ @paste=${this.handleEditorPaste}
77
+ @blur=${this.handleEditorBlur}
78
+ ></div>
79
+
80
+ <textarea
81
+ ?hidden=${"code"!==this.mode}
82
+ @input=${this.handleTextareaInput}
83
+ ></textarea>
84
+ </div>
85
+
86
+ ${this.hasBottomToolbar?html`
87
+ <div class="toolbar-bottom bt">
88
+ <slot name="toolbar-bottom"></slot>
89
+ </div>
90
+ `:""}
91
+ `}}customElements.define("k-html-editor",HtmlEditor);
@@ -1,4 +1,4 @@
1
- import ShadowComponent from"./ShadowComponent.js";import{html,css,unsafeHTML}from"../lit-all.min.js";const cache={},getIconByPath=async t=>(cache[t]||(cache[t]=new Promise(async(n,e)=>{const i=(new AbortController).signal;try{const e=await fetch(t,{signal:i});200===e.status?n(await e.text()):404===e.status&&n(null)}catch(t){"AbortError"!==t.name&&e(t)}}).catch(()=>null)),await cache[t]),getIconByName=t=>{const n=async n=>{const e=n.endsWith("/")?n.slice(0,-1):n;return getIconByPath(`${e}/${t}.svg`)};return new Promise(async(t,e)=>{let i;const o=window.kempo?.pathsToIcons||["/icons","../../icons","https://cdn.jsdelivr.net/npm/kempo-ui@0.0.32/icons/"];for(let t=0;t<o.length&&!i;t++)try{i=await n(o[t])}catch(t){}t(i||null)})};export default class Icon extends ShadowComponent{static properties={src:{type:String,reflect:!0},name:{type:String,reflect:!0},rotation:{type:String,reflect:!0},direction:{type:String,reflect:!0},animation:{type:String,reflect:!0},iconContent:{type:String}};constructor(t=""){super(),this.src="",this.name=t,this.rotation="",this.direction="",this.animation="",this.iconContent=""}updated(t){super.updated(),(t.has("src")||t.has("name"))&&this.loadIcon()}async loadIcon(){let t;if(this.src?t=await getIconByPath(this.src):this.name&&(t=await getIconByName(this.name)),t)this.iconContent=this.fixSVG(t);else{const t=this.innerHTML.trim();this.iconContent=t?this.fixSVG(t):window.kempo?.fallbackIcon||'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M480-79q-16 0-30.5-6T423-102L102-423q-11-12-17-26.5T79-480q0-16 6-31t17-26l321-321q12-12 26.5-17.5T480-881q16 0 31 5.5t26 17.5l321 321q12 11 17.5 26t5.5 31q0 16-5.5 30.5T858-423L537-102q-11 11-26 17t-31 6Zm0-80 321-321-321-321-321 321 321 321Zm-40-281h80v-240h-80v240Zm40 120q17 0 28.5-11.5T520-360q0-17-11.5-28.5T480-400q-17 0-28.5 11.5T440-360q0 17 11.5 28.5T480-320Zm0-160Z"/></svg>'}}fixSVG(t){if(!t)return t;const n=(new DOMParser).parseFromString(t,"image/svg+xml").querySelector("svg");return n?(n.removeAttribute("width"),n.removeAttribute("height"),n.querySelectorAll("path, rect, circle").forEach(t=>{t.setAttribute("fill","currentColor")}),(new XMLSerializer).serializeToString(n)):t}getRotationDegrees(){if(this.rotation)return this.rotation;return{down:"90",left:"180",up:"270"}[this.direction]||"0"}static styles=css`
1
+ import ShadowComponent from"./ShadowComponent.js";import{html,css,unsafeHTML}from"../lit-all.min.js";const cache={},getIconByPath=async t=>(cache[t]||(cache[t]=new Promise(async(e,n)=>{const i=(new AbortController).signal;try{const n=await fetch(t,{signal:i});200===n.status?e(await n.text()):e(null)}catch(t){"AbortError"!==t.name&&n(t)}}).catch(()=>null)),await cache[t]),getIconByName=t=>{const e=async e=>{const n=e.endsWith("/")?e.slice(0,-1):e;return getIconByPath(`${n}/${t}.svg`)};return new Promise(async(t,n)=>{let i;const o=window.kempo?.pathsToIcons||["./icons","/icons","../icons","../../icons"];for(let t=0;t<o.length&&!i;t++)try{i=await e(o[t])}catch(t){}t(i||null)})};export default class Icon extends ShadowComponent{static properties={src:{type:String,reflect:!0},name:{type:String,reflect:!0},rotation:{type:String,reflect:!0},direction:{type:String,reflect:!0},animation:{type:String,reflect:!0},iconContent:{type:String}};constructor(t=""){super(),this.src="",this.name=t,this.rotation="",this.direction="",this.animation="",this.iconContent=""}updated(t){super.updated(),(t.has("src")||t.has("name"))&&this.loadIcon()}async loadIcon(){let t;if(this.src?t=await getIconByPath(this.src):this.name&&(t=await getIconByName(this.name)),t)this.iconContent=this.fixSVG(t),this.requestUpdate();else{const t=this.innerHTML.trim();t?(this.iconContent=this.fixSVG(t),this.requestUpdate()):(this.iconContent=window.kempo?.fallbackIcon||'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960"><path fill="currentColor" d="M480-79q-16 0-30.5-6T423-102L102-423q-11-12-17-26.5T79-480q0-16 6-31t17-26l321-321q12-12 26.5-17.5T480-881q16 0 31 5.5t26 17.5l321 321q12 11 17.5 26t5.5 31q0 16-5.5 30.5T858-423L537-102q-11 11-26 17t-31 6Zm0-80 321-321-321-321-321 321 321 321Zm-40-281h80v-240h-80v240Zm40 120q17 0 28.5-11.5T520-360q0-17-11.5-28.5T480-400q-17 0-28.5 11.5T440-360q0 17 11.5 28.5T480-320Zm0-160Z"/></svg>',this.requestUpdate())}}fixSVG(t){if(!t)return t;const e=(new DOMParser).parseFromString(t,"image/svg+xml").querySelector("svg");return e?(e.removeAttribute("width"),e.removeAttribute("height"),e.querySelectorAll("path, rect, circle").forEach(t=>{t.setAttribute("fill","currentColor")}),(new XMLSerializer).serializeToString(e)):t}getRotationDegrees(){if(this.rotation)return this.rotation;return{down:"90",left:"180",up:"270"}[this.direction]||"0"}static styles=css`
2
2
  :host {
3
3
  display: inline-block;
4
4
  vertical-align: bottom;
@@ -39,4 +39,4 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css,unsafeHTML}fro
39
39
  0%, 100% { transform: scale(1); }
40
40
  50% { transform: scale(1.2); }
41
41
  }
42
- `;render(){const t=this.getRotationDegrees(),n="0"!==t?`--icon-rotation: ${t}deg;`:"";return this.iconContent?html`<div style="${n}">${unsafeHTML(this.iconContent)}</div>`:html`<div style="${n}"><slot></slot></div>`}}window.customElements.define("k-icon",Icon);
42
+ `;render(){const t=this.getRotationDegrees(),e="0"!==t?`--icon-rotation: ${t}deg;`:"";return this.iconContent?html`<div style="${e}">${unsafeHTML(this.iconContent)}</div>`:html`<div style="${e}"><slot></slot></div>`}}window.customElements.define("k-icon",Icon);
@@ -1,17 +1,13 @@
1
- import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-all.min.js";export default class Main extends ShadowComponent{static properties={panelWidth:{type:String,state:!0},panelSide:{type:String,state:!0}};constructor(){super(),this.panelWidth="0px",this.panelSide="left",this.handlePanelChange=this.handlePanelChange.bind(this)}connectedCallback(){super.connectedCallback(),window.addEventListener("side-panel-change",this.handlePanelChange);const e=document.querySelector("k-side-panel");e&&(this.panelWidth=e.collapsed?"3.5rem":"16rem",this.panelSide=e.side||"left")}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("side-panel-change",this.handlePanelChange)}handlePanelChange(e){this.panelWidth=e.detail.width,this.panelSide=e.detail.side}render(){return html`
1
+ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-all.min.js";export default class Main extends ShadowComponent{static properties={leftPanelWidth:{type:String,state:!0},rightPanelWidth:{type:String,state:!0}};constructor(){super(),this.leftPanelWidth="0px",this.rightPanelWidth="0px",this.handlePanelChange=this.handlePanelChange.bind(this)}connectedCallback(){super.connectedCallback(),window.addEventListener("side-panel-change",this.handlePanelChange);const t=document.querySelector('k-side-panel:not([side="right"])');t&&(this.leftPanelWidth=t.collapsed?"3.5rem":"16rem");const e=document.querySelector('k-side-panel[side="right"]');e&&(this.rightPanelWidth=e.collapsed?"3.5rem":"16rem")}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("side-panel-change",this.handlePanelChange)}handlePanelChange(t){"right"===t.detail.side?this.rightPanelWidth=t.detail.width:this.leftPanelWidth=t.detail.width}render(){return html`
2
2
  <main>
3
3
  <slot></slot>
4
4
  </main>
5
5
  `}static styles=css`
6
6
  :host {
7
7
  display: block;
8
- margin-left: var(--panel-width, 0px);
9
- transition: margin-left var(--animation_ms, 256ms);
10
- }
11
- :host([panel-side="right"]) {
12
- margin-left: 0;
13
- margin-right: var(--panel-width, 0px);
14
- transition: margin-right var(--animation_ms, 256ms);
8
+ margin-left: var(--left-panel-width, 0px);
9
+ margin-right: var(--right-panel-width, 0px);
10
+ transition: margin-left var(--animation_ms, 256ms), margin-right var(--animation_ms, 256ms);
15
11
  }
16
12
  main {
17
13
  max-width: var(--container_width, 90rem);
@@ -21,4 +17,4 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
21
17
  padding-left: var(--spacer);
22
18
  padding-right: var(--spacer);
23
19
  }
24
- `;updated(){super.updated(),this.style.setProperty("--panel-width",this.panelWidth),"right"===this.panelSide?this.setAttribute("panel-side","right"):this.removeAttribute("panel-side")}}window.customElements.define("k-main",Main);
20
+ `;updated(){super.updated(),this.style.setProperty("--left-panel-width",this.leftPanelWidth),this.style.setProperty("--right-panel-width",this.rightPanelWidth)}}window.customElements.define("k-main",Main);
@@ -1 +1 @@
1
- import{LitElement}from"../lit-all.min.js";export default class ShadowComponent extends LitElement{#e;connectedCallback(){super.connectedCallback(),this.#e=new MutationObserver(()=>{console.log("MutationObserver fired for",this.constructor.name),this.childrenUpdated(),this.requestUpdate()}),this.#e.observe(this,{childList:!0})}disconnectedCallback(){super.disconnectedCallback(),this.#e?.disconnect()}childrenUpdated(){}createRenderRoot(){const e=this.attachShadow({mode:"open"}),t=document.createElement("link");t.rel="stylesheet",t.href=window.kempo?.pathToStylesheet||"https://cdn.jsdelivr.net/npm/kempo-css@1.3.2/dist/kempo.min.css",e.appendChild(t);const n=this.constructor.styles;if(n){const t=document.createElement("style");Array.isArray(n)?t.textContent=n.map(e=>e.cssText||e).join("\n"):t.textContent=n.cssText||n,e.appendChild(t)}const s=document.createElement("div");return s.style.display="contents",e.appendChild(s),s}}
1
+ import{LitElement}from"../lit-all.min.js";export default class ShadowComponent extends LitElement{#e;connectedCallback(){super.connectedCallback(),this.#e=new MutationObserver(()=>{this.childrenUpdated(),this.requestUpdate()}),this.#e.observe(this,{childList:!0})}disconnectedCallback(){super.disconnectedCallback(),this.#e?.disconnect()}childrenUpdated(){}createRenderRoot(){const e=this.attachShadow({mode:"open"}),t=document.createElement("link");t.rel="stylesheet",t.href=window.kempo?.pathToStylesheet||"https://cdn.jsdelivr.net/npm/kempo-css@1.3.2/dist/kempo.min.css",e.appendChild(t);const n=this.constructor.styles;if(n){const t=document.createElement("style");Array.isArray(n)?t.textContent=n.map(e=>e.cssText||e).join("\n"):t.textContent=n.cssText||n,e.appendChild(t)}const s=document.createElement("div");return s.style.display="contents",e.appendChild(s),s}}
@@ -1,4 +1,4 @@
1
- import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-all.min.js";import{boolTrueFalse}from"../utils/propConverters.js";import"./FocusCapture.js";import"./Icon.js";export default class SideMenu extends ShadowComponent{static properties={opened:{type:Boolean,reflect:!0},overlayClose:{type:Boolean,reflect:!0,attribute:"overlay-close",converter:boolTrueFalse},side:{type:String,reflect:!0}};constructor(){super(),this.opened=!1,this.overlayClose=!0,this.side="left"}overlayClick=()=>{this.overlayClose&&this.close()};updated(e){super.updated(e),e.has("opened")&&(this.opened?(document.body.classList.add("no-scroll"),this.dispatchEvent(new CustomEvent("change",{detail:"open"})),this.dispatchEvent(new CustomEvent("open"))):(document.body.classList.remove("no-scroll"),this.dispatchEvent(new CustomEvent("change",{detail:"close"})),this.dispatchEvent(new CustomEvent("close"))))}open(){this.opened=!0}close(){this.opened=!1}toggle(){this.opened?this.close():this.open(),this.dispatchEvent(new CustomEvent("toggle"))}render(){return html`
1
+ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-all.min.js";import{boolTrueFalse}from"../utils/propConverters.js";import"./FocusCapture.js";import"./Icon.js";export default class SideMenu extends ShadowComponent{static properties={opened:{type:Boolean,reflect:!0},overlayClose:{type:Boolean,reflect:!0,attribute:"overlay-close",converter:boolTrueFalse},escClose:{type:Boolean,reflect:!0,attribute:"esc-close",converter:boolTrueFalse},side:{type:String,reflect:!0}};constructor(){super(),this.opened=!1,this.overlayClose=!0,this.escClose=!0,this.side="left"}overlayClick=()=>{this.overlayClose&&this.close()};handleKeyDown=e=>{this.escClose&&"Escape"===e.key&&this.close()};updated(e){super.updated(e),e.has("opened")&&(this.opened?(document.body.classList.add("no-scroll"),document.addEventListener("keydown",this.handleKeyDown),this.dispatchEvent(new CustomEvent("change",{detail:"open"})),this.dispatchEvent(new CustomEvent("open"))):(document.body.classList.remove("no-scroll"),document.removeEventListener("keydown",this.handleKeyDown),this.dispatchEvent(new CustomEvent("change",{detail:"close"})),this.dispatchEvent(new CustomEvent("close"))))}open(){this.opened=!0}close(){this.opened=!1}toggle(){this.opened?this.close():this.open(),this.dispatchEvent(new CustomEvent("toggle"))}render(){return html`
2
2
  <k-focus-capture>
3
3
  <div id="container">
4
4
  <button id="overlay" @click=${this.overlayClick}>
@@ -1,8 +1,8 @@
1
- import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-all.min.js";import"./Icon.js";class SidePanel extends ShadowComponent{static properties={collapsed:{type:Boolean,reflect:!0},side:{type:String,reflect:!0}};constructor(){super(),this.collapsed=!1,this.side="left"}toggleClick=()=>this.toggle();updated(e){if(super.updated(e),e.has("collapsed")){const e=this.collapsed?"collapse":"expand";this.dispatchEvent(new CustomEvent(e)),this.dispatchEvent(new CustomEvent("change",{detail:e})),window.dispatchEvent(new CustomEvent("side-panel-change",{detail:{collapsed:this.collapsed,width:this.collapsed?"3.5rem":"16rem",side:this.side}}))}}expand=()=>this.collapsed=!1;collapse=()=>this.collapsed=!0;toggle(){this.collapsed=!this.collapsed,this.dispatchEvent(new CustomEvent("toggle"))}render(){return html`
1
+ import ShadowComponent from"./ShadowComponent.js";import{html,css,nothing}from"../lit-all.min.js";import"./Icon.js";class SidePanel extends ShadowComponent{static properties={collapsed:{type:Boolean,reflect:!0},side:{type:String,reflect:!0}};constructor(){super(),this.collapsed=!1,this.side="left"}toggleClick=()=>this.toggle();updated(e){if(super.updated(e),e.has("collapsed")){const e=this.collapsed?"collapse":"expand";this.dispatchEvent(new CustomEvent(e)),this.dispatchEvent(new CustomEvent("change",{detail:e})),window.dispatchEvent(new CustomEvent("side-panel-change",{detail:{collapsed:this.collapsed,width:this.collapsed?"3.5rem":"16rem",side:this.side}}))}}expand=()=>this.collapsed=!1;collapse=()=>this.collapsed=!0;toggle(){this.collapsed=!this.collapsed,this.dispatchEvent(new CustomEvent("toggle"))}render(){return html`
2
2
  <div id="header">
3
3
  <slot name="logo"></slot>
4
4
  <button id="toggle" @click=${this.toggleClick} aria-label="${this.collapsed?"Expand panel":"Collapse panel"}">
5
- <k-icon name="arrow-line" direction="${this.collapsed?"right":"left"}"></k-icon>
5
+ <k-icon name="arrow-line" direction="${(()=>"right"===this.side?this.collapsed?"left":"right":this.collapsed?"right":"left")()}"></k-icon>
6
6
  </button>
7
7
  </div>
8
8
  <div id="content">
@@ -12,9 +12,9 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
12
12
  :host {
13
13
  --bg: var(--c_bg);
14
14
  --width-expanded: 16rem;
15
- --width-collapsed: 3.5rem;
16
15
  --transition-duration: var(--animation_ms, 256ms);
17
- display: block;
16
+ display: flex;
17
+ flex-direction: column;
18
18
  position: fixed;
19
19
  top: 0;
20
20
  left: 0;
@@ -26,7 +26,7 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
26
26
  z-index: 1000;
27
27
  }
28
28
  :host([collapsed]) {
29
- width: var(--width-collapsed);
29
+ width: auto;
30
30
  }
31
31
  :host([side="right"]) {
32
32
  left: auto;
@@ -41,20 +41,17 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
41
41
  gap: var(--spacer_h);
42
42
  padding: var(--spacer_h);
43
43
  border-bottom: 1px solid var(--c_border);
44
+ flex-shrink: 0;
44
45
  }
45
46
  ::slotted([slot="logo"]) {
46
47
  margin-right: auto;
47
- }
48
- ::slotted([slot="logo"]) {
49
48
  flex: 1;
50
49
  min-width: 0;
51
50
  opacity: 1;
52
51
  transition: opacity var(--transition-duration);
53
52
  }
54
53
  :host([collapsed]) ::slotted([slot="logo"]) {
55
- opacity: 0;
56
- width: 0;
57
- overflow: hidden;
54
+ display: none;
58
55
  }
59
56
  #toggle {
60
57
  flex-shrink: 0;
@@ -73,23 +70,31 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
73
70
  background: var(--c_bg_hover);
74
71
  }
75
72
  #content {
76
- height: calc(100% - 3rem);
73
+ flex: 1;
74
+ min-height: 0;
77
75
  overflow-y: auto;
78
76
  overflow-x: hidden;
79
77
  display: flex;
80
78
  flex-direction: column;
81
79
  }
82
- `}class SidePanelItem extends ShadowComponent{static properties={icon:{type:String},href:{type:String},active:{type:Boolean,reflect:!0}};constructor(){super(),this.icon="",this.href="#",this.active=!1,this.collapsed=!1}connectedCallback(){super.connectedCallback(),this.panel=this.closest("k-side-panel"),this.panel&&(this.collapsed=this.panel.collapsed,this.panel.addEventListener("collapse",this.handleCollapse),this.panel.addEventListener("expand",this.handleExpand))}disconnectedCallback(){super.disconnectedCallback(),this.panel&&(this.panel.removeEventListener("collapse",this.handleCollapse),this.panel.removeEventListener("expand",this.handleExpand))}handleCollapse=()=>{this.collapsed=!0,this.requestUpdate()};handleExpand=()=>{this.collapsed=!1,this.requestUpdate()};render(){return html`
83
- <a href="${this.href}" class="item ${this.active?"active bg-primary":""}">
84
- ${this.icon?html`<k-icon name="${this.icon}"></k-icon>`:""}
85
- <span class="label ${this.collapsed?"hidden":""}">
86
- <slot></slot>
87
- </span>
80
+ :host([collapsed]) #content {
81
+ align-items: flex-start;
82
+ }
83
+ :host(:not([collapsed])) #content {
84
+ /* scrollbar-gutter: stable; */
85
+ }
86
+ `}class SidePanelItem extends ShadowComponent{static properties={icon:{type:String},href:{type:String},active:{type:Boolean,reflect:!0},collapsed:{type:Boolean,reflect:!0},"no-expand":{type:Boolean,attribute:"no-expand"},"hide-when-collapsed":{type:Boolean,attribute:"hide-when-collapsed"}};constructor(){super(),this.icon="",this.href="#",this.active=!1,this.collapsed=!1,this["no-expand"]=!1,this["hide-when-collapsed"]=!1}connectedCallback(){super.connectedCallback(),this.panel=this.closest("k-side-panel"),this.panel&&(this.collapsed=this.panel.collapsed,this.panel.addEventListener("collapse",this.handleCollapse),this.panel.addEventListener("expand",this.handleExpand))}disconnectedCallback(){super.disconnectedCallback(),this.panel&&(this.panel.removeEventListener("collapse",this.handleCollapse),this.panel.removeEventListener("expand",this.handleExpand))}handleCollapse=()=>{this.collapsed=!0,this.requestUpdate()};handleExpand=()=>{this.collapsed=!1,this.requestUpdate()};handleClick=e=>{this.collapsed&&!this["no-expand"]&&this.panel&&(e.preventDefault(),this.panel.expand())};render(){return html`
87
+ <a href="${this.href}" class="item ${this.active?"active bg-primary":""}" @click=${this.handleClick}>
88
+ ${this.icon?html`<k-icon name="${this.icon}"></k-icon>`:this.collapsed?html`<k-icon name="dot"></k-icon>`:nothing}
89
+ ${this.collapsed?nothing:html`<span class="label"><slot></slot></span>`}
88
90
  </a>
89
91
  `}static styles=css`
90
92
  :host {
91
93
  display: block;
92
94
  }
95
+ :host([collapsed][hide-when-collapsed]) {
96
+ display: none;
97
+ }
93
98
  .item {
94
99
  display: flex;
95
100
  align-items: center;
@@ -102,6 +107,8 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
102
107
  transition: background var(--animation_ms), color var(--animation_ms);
103
108
  white-space: nowrap;
104
109
  }
110
+ :host([collapsed]) .item {
111
+ }
105
112
  .item:hover {
106
113
  background: var(--c_bg_hover);
107
114
  }
@@ -119,18 +126,16 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
119
126
  min-width: 0;
120
127
  overflow: hidden;
121
128
  text-overflow: ellipsis;
122
- opacity: 1;
123
- transition: opacity var(--animation_ms);
124
- }
125
- .label.hidden {
126
- opacity: 0;
127
- width: 0;
128
129
  }
129
- `}class SidePanelLabel extends ShadowComponent{constructor(){super(),this.collapsed=!1}connectedCallback(){super.connectedCallback(),this.panel=this.closest("k-side-panel"),this.panel&&(this.collapsed=this.panel.collapsed,this.panel.addEventListener("collapse",this.handleCollapse),this.panel.addEventListener("expand",this.handleExpand))}disconnectedCallback(){super.disconnectedCallback(),this.panel&&(this.panel.removeEventListener("collapse",this.handleCollapse),this.panel.removeEventListener("expand",this.handleExpand))}handleCollapse=()=>{this.collapsed=!0,this.requestUpdate()};handleExpand=()=>{this.collapsed=!1,this.requestUpdate()};render(){return this.collapsed?html`<hr>`:html`<div class="label"><slot></slot></div>`}static styles=css`
130
+ `}class SidePanelLabel extends ShadowComponent{static properties={collapsed:{type:Boolean,reflect:!0}};constructor(){super(),this.collapsed=!1}connectedCallback(){super.connectedCallback(),this.panel=this.closest("k-side-panel"),this.panel&&(this.collapsed=this.panel.collapsed,this.panel.addEventListener("collapse",this.handleCollapse),this.panel.addEventListener("expand",this.handleExpand))}disconnectedCallback(){super.disconnectedCallback(),this.panel&&(this.panel.removeEventListener("collapse",this.handleCollapse),this.panel.removeEventListener("expand",this.handleExpand))}handleCollapse=()=>{this.collapsed=!0,this.requestUpdate()};handleExpand=()=>{this.collapsed=!1,this.requestUpdate()};render(){return this.collapsed?html`<hr>`:html`<div class="label"><slot></slot></div>`}static styles=css`
130
131
  :host {
131
132
  display: block;
132
133
  margin: var(--spacer_h) 0;
133
134
  }
135
+ :host([collapsed]) {
136
+ margin: 0 var(--spacer_h);
137
+ align-self: stretch;
138
+ }
134
139
  .label {
135
140
  padding: 0 var(--spacer);
136
141
  font-size: 0.75rem;
@@ -144,12 +149,15 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
144
149
  border-top: 1px solid var(--c_border);
145
150
  margin: var(--spacer_h) var(--spacer);
146
151
  }
147
- `}class SidePanelMenu extends ShadowComponent{static properties={icon:{type:String},label:{type:String},open:{type:Boolean,reflect:!0}};constructor(){super(),this.icon="",this.label="",this.open=!1,this.collapsed=!1}connectedCallback(){super.connectedCallback(),this.panel=this.closest("k-side-panel"),this.panel&&(this.collapsed=this.panel.collapsed,this.panel.addEventListener("collapse",this.handleCollapse),this.panel.addEventListener("expand",this.handleExpand))}disconnectedCallback(){super.disconnectedCallback(),this.panel&&(this.panel.removeEventListener("collapse",this.handleCollapse),this.panel.removeEventListener("expand",this.handleExpand))}handleCollapse=()=>{this.collapsed=!0,this.open=!1,this.requestUpdate()};handleExpand=()=>{this.collapsed=!1,this.requestUpdate()};toggleMenu=()=>{this.collapsed||(this.open=!this.open)};render(){return html`
152
+ :host([collapsed]) hr {
153
+ margin: var(--spacer_h) 0;
154
+ }
155
+ `}class SidePanelMenu extends ShadowComponent{static properties={icon:{type:String},label:{type:String},open:{type:Boolean,reflect:!0},collapsed:{type:Boolean,reflect:!0},"no-expand":{type:Boolean,attribute:"no-expand"},"hide-when-collapsed":{type:Boolean,attribute:"hide-when-collapsed"}};constructor(){super(),this.icon="",this.label="",this.open=!1,this.collapsed=!1,this["no-expand"]=!1,this["hide-when-collapsed"]=!1}connectedCallback(){super.connectedCallback(),this.panel=this.closest("k-side-panel"),this.panel&&(this.collapsed=this.panel.collapsed,this.panel.addEventListener("collapse",this.handleCollapse),this.panel.addEventListener("expand",this.handleExpand))}disconnectedCallback(){super.disconnectedCallback(),this.panel&&(this.panel.removeEventListener("collapse",this.handleCollapse),this.panel.removeEventListener("expand",this.handleExpand))}handleCollapse=()=>{this.collapsed=!0,this.open=!1,this.requestUpdate()};handleExpand=()=>{this.collapsed=!1,this.requestUpdate()};toggleMenu=()=>{this.collapsed&&!this["no-expand"]&&this.panel?this.panel.expand():this.collapsed||(this.open=!this.open)};render(){return html`
148
156
  <div class="menu-container">
149
- <button class="menu-header ${this.open?"open":""}" @click=${this.toggleMenu}>
150
- ${this.icon?html`<k-icon name="${this.icon}"></k-icon>`:""}
151
- <span class="label ${this.collapsed?"hidden":""}">${this.label}</span>
152
- ${this.collapsed?"":html`<k-icon class="chevron" name="chevron" direction="${this.open?"down":"right"}"></k-icon>`}
157
+ <button class="no-btn menu-header ${this.open?"open":""}" @click=${this.toggleMenu}>
158
+ ${this.icon?html`<k-icon name="${this.icon}"></k-icon>`:this.collapsed?html`<k-icon name="dot"></k-icon>`:nothing}
159
+ ${this.collapsed?nothing:html`<span class="label">${this.label}</span>`}
160
+ ${this.collapsed?nothing:html`<k-icon class="chevron" name="chevron" direction="${this.open?"down":"right"}"></k-icon>`}
153
161
  </button>
154
162
  <div class="menu-content ${this.open&&!this.collapsed?"open":""}">
155
163
  <slot></slot>
@@ -159,6 +167,9 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
159
167
  :host {
160
168
  display: block;
161
169
  }
170
+ :host([collapsed][hide-when-collapsed]) {
171
+ display: none;
172
+ }
162
173
  .menu-container {
163
174
  margin: 0;
164
175
  }
@@ -181,6 +192,9 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
181
192
  white-space: nowrap;
182
193
  transition: background var(--animation_ms);
183
194
  }
195
+ :host([collapsed]) .menu-header {
196
+ width: auto;
197
+ }
184
198
  .menu-header:hover {
185
199
  background: var(--c_bg_hover);
186
200
  }
@@ -192,12 +206,6 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
192
206
  min-width: 0;
193
207
  overflow: hidden;
194
208
  text-overflow: ellipsis;
195
- opacity: 1;
196
- transition: opacity var(--animation_ms);
197
- }
198
- .label.hidden {
199
- opacity: 0;
200
- width: 0;
201
209
  }
202
210
  .chevron {
203
211
  transition: transform var(--animation_ms);
@@ -208,6 +216,9 @@ import ShadowComponent from"./ShadowComponent.js";import{html,css}from"../lit-al
208
216
  transition: max-height var(--animation_ms);
209
217
  padding-left: calc(var(--spacer_h) * 2);
210
218
  }
219
+ :host([collapsed]) .menu-content {
220
+ padding-left: 0;
221
+ }
211
222
  .menu-content.open {
212
223
  max-height: 500px;
213
224
  }
@@ -0,0 +1,12 @@
1
+ import HtmlEditorControl from"./HtmlEditorControl.js";import{html,css}from"../../lit-all.min.js";import"../Icon.js";export default class AlignCenter extends HtmlEditorControl{static properties={editorMode:{type:String,state:!0}};static styles=[HtmlEditorControl.styles,css`
2
+ :host {
3
+ display: inline-flex;
4
+ }
5
+ `];connectedCallback(){super.connectedCallback(),this.updateEditorMode(),this.editor?.addEventListener("mode-changed",()=>this.updateEditorMode())}handleClick=()=>{this.editor&&this.editor.alignCenter()};updateEditorMode(){this.editor&&(this.editorMode=this.editor.mode)}render(){return this.hidden="code"===this.editorMode,html`
6
+ <button class="${this.buttonClasses}" @click="${this.handleClick}">
7
+ <slot name="icon">
8
+ <k-icon name="format_align_center"></k-icon>
9
+ </slot>
10
+ <slot></slot>
11
+ </button>
12
+ `}}customElements.define("k-hec-align-center",AlignCenter);
@@ -0,0 +1,12 @@
1
+ import HtmlEditorControl from"./HtmlEditorControl.js";import{html,css}from"../../lit-all.min.js";import"../Icon.js";export default class AlignJustify extends HtmlEditorControl{static properties={editorMode:{type:String,state:!0}};static styles=[HtmlEditorControl.styles,css`
2
+ :host {
3
+ display: inline-flex;
4
+ }
5
+ `];connectedCallback(){super.connectedCallback(),this.updateEditorMode(),this.editor?.addEventListener("mode-changed",()=>this.updateEditorMode())}handleClick=()=>{this.editor&&this.editor.alignJustify()};updateEditorMode(){this.editor&&(this.editorMode=this.editor.mode)}render(){return this.hidden="code"===this.editorMode,html`
6
+ <button class="${this.buttonClasses}" @click="${this.handleClick}">
7
+ <slot name="icon">
8
+ <k-icon name="format_align_justify"></k-icon>
9
+ </slot>
10
+ <slot></slot>
11
+ </button>
12
+ `}}customElements.define("k-hec-align-justify",AlignJustify);