leksy-editor 1.1.0 → 1.2.1

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.
package/README.md CHANGED
@@ -98,9 +98,13 @@ const app = createApp({
98
98
  | `pexelsApiKey` | API key for Pexels integration. |
99
99
  | `tenorApiKey` | API key for Tenor integration. |
100
100
  | `cssVariables` | Custom CSS styling variables for multiple themes and modes. |
101
+ | `disablePastedColorStyles` | Remove color-related CSS while pasting. |
101
102
  | `autoHeight` | Automatically adjusts height based on content. |
103
+ | `height` | Height for the editor. |
102
104
  | `maxHeight` | Maximum height for the editor. |
103
105
  | `minHeight` | Minimum height for the editor. |
106
+ | `iframeStyle` | To design inside iframe, pass your css here |
107
+ | `disabled` | To disabled editor |
104
108
 
105
109
  ### CSS Customization
106
110
 
@@ -122,6 +126,8 @@ cssVariables: {
122
126
  resizerPosition: "#fff",
123
127
  resizerPositionBackground: "#333",
124
128
  linkColor: "#0000ff",
129
+ scrollbarThumb: "hsl(160, 100%, 40%)",
130
+ scrollbarTrack: "hsl(223, 5%, 76%)",
125
131
  }
126
132
  ```
127
133
 
@@ -173,9 +179,19 @@ Similarly, Pexels and Tenor can be integrated using `pexels` and `tenor` plugins
173
179
  | `onBlur(html)` | Triggered when the editor loses focus. |
174
180
  | `onAttachment(files)` | Fires when files are attached. |
175
181
  | `manipulateImage()` | Custom function for manipulating images. |
182
+ | `handleFilePicker()` | Custom function for file upload, useful for Android and iOS file upload. |
176
183
  | `uploadVideo(file)` | Handles video uploads, returns a promise with video URL. |
177
184
  | `focus()` | Focuses the editor. |
178
185
  | `getCore()` | Returns the core editor instance. |
186
+ | `updateHeight()` | To update editor container height. |
187
+ | `updateCssVariables()` | To update cssVariables. |
188
+ | `updateLabels()` | To update label. |
189
+ | `getLocalCursor()` | Return local cursor position |
190
+ | `setRemoteCursor()` | Sets remote cursor position |
191
+ | `onLocalCursorChange()` | Trigger when local cursor change. |
192
+ | `onLocalSyncChanges()` | Trigger on content change, returns in chunks. |
193
+ | `applyRemoteSyncChanges()` | Apply remote chunks. |
194
+ | `setDisabled()` | Pass true/false to disable/enable editor. |
179
195
 
180
196
  ## License
181
197
 
package/constant.js CHANGED
@@ -2,7 +2,7 @@ const WHILE_LISTED_TAG = "br|p|div|pre|blockquote|h|h1|h2|h3|h4|h5|h6|ol|ul|li|h
2
2
  const WHILE_LISTED_ATTRIBUTES = "align|alt|bgcolor|border|cellpadding|cellspacing|color|colspan|contenteditable|dir|download|face|height|href|lang|name|rowspan|size|src|style|target|title|valign|width|background|media|sizes|srcset|spellcheck";
3
3
 
4
4
  const REGEX = {
5
- TEXT_URL: /(https?:\/\/[^\s]+|www\.[^\s]+)$/i,
5
+ TEXT_URL: /(https?:\/\/[^\s]+|www\.[^\s]+)$/i,
6
6
  URL: /^(https?:\/\/)([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(\/.*)?$/,
7
7
  MAILTO: /^mailto:[\w.-]+@[\w.-]+\.\w+$/,
8
8
  TEL: /^tel:\+?[0-9\s()-]+$/,
@@ -34,6 +34,9 @@ const CLASSES = {
34
34
  STEPPER: '-stepper',
35
35
  DROPDOWN_CONTENT: '-dropdown-content',
36
36
  POPOVER_CONTENT: '-popover-content',
37
+ POPOVER_TABS: '-popover-tabs',
38
+ POPOVER_TAB: '-popover-tab',
39
+ POPOVER_TAB_CONTENT: '-popover-tab-content',
37
40
  RESIZE_ITEMS: '-resize-items',
38
41
  RESIZE_ITEM: '-resize-item',
39
42
  MODAL: '-modal',
@@ -99,6 +102,9 @@ const SVG = {
99
102
  MERGE_CELLS_VERTICAL: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21 20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3H20C20.5523 3 21 3.44772 21 4V20ZM19 11V5H13.001V7H15L12 10L9 7H11V5H5V11H7V13H5V19H11V17H9L12 14L15 17H13.001V19H19V13H17V11H19ZM11 13H9V11H11V13ZM15 13H13V11H15V13Z"></path></svg>',
100
103
  SPLIT_CELLS_HORIZONTAL: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 3C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3H20ZM11 5H5V19H11V15H13V19H19V5H13V9H11V5ZM15 9L18 12L15 15V13H9V15L6 12L9 9V11H15V9Z"></path></svg>',
101
104
  SPLIT_CELLS_VERTICAL: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 3C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4C3 3.44772 3.44772 3 4 3H20ZM19 5H5V10.999L9 11V13H5V19H19V13H15V11L19 10.999V5ZM12 6L15 9H13V15H15L12 18L9 15H11V9H9L12 6Z"></path></svg>',
105
+ CELL_WIDTH: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M4 12H20M4 12L8 8M4 12L8 16M20 12L16 8M20 12L16 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
106
+ CELL_HEIGHT: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12 4V20M12 4L8 8M12 4L16 8M12 20L8 16M12 20L16 16" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
107
+ CELL_PADDING: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><rect x="3" y="3" width="18" height="18" rx="2" stroke="currentColor" stroke-width="2"/><path d="M7 7H17V17H7V7Z" stroke="currentColor" stroke-width="2" stroke-dasharray="2 2"/></svg>',
102
108
  CELL_BORDER_BOTTOM: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13,19 L19.5,19 C19.7761424,19 20,19.2238576 20,19.5 C20,19.7761424 19.7761424,20 19.5,20 L5.5,20 C5.22385763,20 5,19.7761424 5,19.5 C5,19.2238576 5.22385763,19 5.5,19 L12,19 L12,18.5 C12,18.2238576 12.2238576,18 12.5,18 C12.7761424,18 13,18.2238576 13,18.5 L13,19 Z M13,12 L13.5,12 C13.7761424,12 14,12.2238576 14,12.5 C14,12.7761424 13.7761424,13 13.5,13 L13,13 L13,13.5 C13,13.7761424 12.7761424,14 12.5,14 C12.2238576,14 12,13.7761424 12,13.5 L12,13 L11.5,13 C11.2238576,13 11,12.7761424 11,12.5 C11,12.2238576 11.2238576,12 11.5,12 L12,12 L12,11.5 C12,11.2238576 12.2238576,11 12.5,11 C12.7761424,11 13,11.2238576 13,11.5 L13,12 Z M15.5,13 C15.2238576,13 15,12.7761424 15,12.5 C15,12.2238576 15.2238576,12 15.5,12 L16.5,12 C16.7761424,12 17,12.2238576 17,12.5 C17,12.7761424 16.7761424,13 16.5,13 L15.5,13 Z M18.5,13 C18.2238576,13 18,12.7761424 18,12.5 C18,12.2238576 18.2238576,12 18.5,12 L19.5,12 C19.7761424,12 20,12.2238576 20,12.5 C20,12.7761424 19.7761424,13 19.5,13 L18.5,13 Z M5.5,13 C5.22385763,13 5,12.7761424 5,12.5 C5,12.2238576 5.22385763,12 5.5,12 L6.5,12 C6.77614237,12 7,12.2238576 7,12.5 C7,12.7761424 6.77614237,13 6.5,13 L5.5,13 Z M8.5,13 C8.22385763,13 8,12.7761424 8,12.5 C8,12.2238576 8.22385763,12 8.5,12 L9.5,12 C9.77614237,12 10,12.2238576 10,12.5 C10,12.7761424 9.77614237,13 9.5,13 L8.5,13 Z M12,5.5 C12,5.22385763 12.2238576,5 12.5,5 C12.7761424,5 13,5.22385763 13,5.5 L13,6.5 C13,6.77614237 12.7761424,7 12.5,7 C12.2238576,7 12,6.77614237 12,6.5 L12,5.5 Z M12,8.5 C12,8.22385763 12.2238576,8 12.5,8 C12.7761424,8 13,8.22385763 13,8.5 L13,9.5 C13,9.77614237 12.7761424,10 12.5,10 C12.2238576,10 12,9.77614237 12,9.5 L12,8.5 Z M12,15.5 C12,15.2238576 12.2238576,15 12.5,15 C12.7761424,15 13,15.2238576 13,15.5 L13,16.5 C13,16.7761424 12.7761424,17 12.5,17 C12.2238576,17 12,16.7761424 12,16.5 L12,15.5 Z M5.5,3 C5.77614237,3 6,3.22385763 6,3.5 C6,3.77614237 5.77614237,4 5.5,4 C4.67157288,4 4,4.67157288 4,5.5 C4,5.77614237 3.77614237,6 3.5,6 C3.22385763,6 3,5.77614237 3,5.5 C3,4.11928813 4.11928813,3 5.5,3 Z M16.5,4 C16.2238576,4 16,3.77614237 16,3.5 C16,3.22385763 16.2238576,3 16.5,3 L17.5,3 C17.7761424,3 18,3.22385763 18,3.5 C18,3.77614237 17.7761424,4 17.5,4 L16.5,4 Z M13.5,4 C13.2238576,4 13,3.77614237 13,3.5 C13,3.22385763 13.2238576,3 13.5,3 L14.5,3 C14.7761424,3 15,3.22385763 15,3.5 C15,3.77614237 14.7761424,4 14.5,4 L13.5,4 Z M10.5,4 C10.2238576,4 10,3.77614237 10,3.5 C10,3.22385763 10.2238576,3 10.5,3 L11.5,3 C11.7761424,3 12,3.22385763 12,3.5 C12,3.77614237 11.7761424,4 11.5,4 L10.5,4 Z M7.5,4 C7.22385763,4 7,3.77614237 7,3.5 C7,3.22385763 7.22385763,3 7.5,3 L8.5,3 C8.77614237,3 9,3.22385763 9,3.5 C9,3.77614237 8.77614237,4 8.5,4 L7.5,4 Z M19.5,4 C19.2238576,4 19,3.77614237 19,3.5 C19,3.22385763 19.2238576,3 19.5,3 C20.8807119,3 22,4.11928813 22,5.5 L22,5.56155281 C22,5.83769519 21.7761424,6.06155281 21.5,6.06155281 C21.2238576,6.06155281 21,5.83769519 21,5.56155281 L21,5.5 C21,4.67157288 20.3284271,4 19.5,4 Z M21,7.5 C21,7.22385763 21.2238576,7 21.5,7 C21.7761424,7 22,7.22385763 22,7.5 L22,8.5 C22,8.77614237 21.7761424,9 21.5,9 C21.2238576,9 21,8.77614237 21,8.5 L21,7.5 Z M21,10.5 C21,10.2238576 21.2238576,10 21.5,10 C21.7761424,10 22,10.2238576 22,10.5 L22,11.5 C22,11.7761424 21.7761424,12 21.5,12 C21.2238576,12 21,11.7761424 21,11.5 L21,10.5 Z M21,13.5 C21,13.2238576 21.2238576,13 21.5,13 C21.7761424,13 22,13.2238576 22,13.5 L22,14.5 C22,14.7761424 21.7761424,15 21.5,15 C21.2238576,15 21,14.7761424 21,14.5 L21,13.5 Z M21,16.5 C21,16.2238576 21.2238576,16 21.5,16 C21.7761424,16 22,16.2238576 22,16.5 L22,17.5 C22,17.7761424 21.7761424,18 21.5,18 C21.2238576,18 21,17.7761424 21,17.5 L21,16.5 Z M3,7.5 C3,7.22385763 3.22385763,7 3.5,7 C3.77614237,7 4,7.22385763 4,7.5 L4,8.5 C4,8.77614237 3.77614237,9 3.5,9 C3.22385763,9 3,8.77614237 3,8.5 L3,7.5 Z M3,10.5 C3,10.2238576 3.22385763,10 3.5,10 C3.77614237,10 4,10.2238576 4,10.5 L4,11.5 C4,11.7761424 3.77614237,12 3.5,12 C3.22385763,12 3,11.7761424 3,11.5 L3,10.5 Z M3,13.5 C3,13.2238576 3.22385763,13 3.5,13 C3.77614237,13 4,13.2238576 4,13.5 L4,14.5 C4,14.7761424 3.77614237,15 3.5,15 C3.22385763,15 3,14.7761424 3,14.5 L3,13.5 Z M3,16.5 C3,16.2238576 3.22385763,16 3.5,16 C3.77614237,16 4,16.2238576 4,16.5 L4,17.5 C4,17.7761424 3.77614237,18 3.5,18 C3.22385763,18 3,17.7761424 3,17.5 L3,16.5 Z M21,19.5 C21,19.2238576 21.2238576,19 21.5,19 C21.7761424,19 22,19.2238576 22,19.5 C22,20.8807119 20.8807119,22 19.5,22 L5.5,22 C4.11928813,22 3,20.8807119 3,19.5 C3,19.2238576 3.22385763,19 3.5,19 C3.77614237,19 4,19.2238576 4,19.5 C4,20.3284271 4.67157288,21 5.5,21 L19.5,21 C20.3284271,21 21,20.3284271 21,19.5 Z"/></svg>',
103
109
  CELL_BORDER_LEFT: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13,13 L13,13.5 C13,13.7761424 12.7761424,14 12.5,14 C12.2238576,14 12,13.7761424 12,13.5 L12,13 L11.5,13 C11.2238576,13 11,12.7761424 11,12.5 C11,12.2238576 11.2238576,12 11.5,12 L12,12 L12,11.5 C12,11.2238576 12.2238576,11 12.5,11 C12.7761424,11 13,11.2238576 13,11.5 L13,12 L13.5,12 C13.7761424,12 14,12.2238576 14,12.5 C14,12.7761424 13.7761424,13 13.5,13 L13,13 L13,13 Z M6,12 L6.5,12 C6.77614237,12 7,12.2238576 7,12.5 C7,12.7761424 6.77614237,13 6.5,13 L6,13 L6,19.5 C6,19.7761424 5.77614237,20 5.5,20 C5.22385763,20 5,19.7761424 5,19.5 L5,5.5 C5,5.22385763 5.22385763,5 5.5,5 C5.77614237,5 6,5.22385763 6,5.5 L6,12 Z M22,5.5 C22,5.77614237 21.7761424,6 21.5,6 C21.2238576,6 21,5.77614237 21,5.5 C21,4.67157288 20.3284271,4 19.5,4 C19.2238576,4 19,3.77614237 19,3.5 C19,3.22385763 19.2238576,3 19.5,3 C20.8807119,3 22,4.11928813 22,5.5 Z M21,19.5 C21,19.2238576 21.2238576,19 21.5,19 C21.7761424,19 22,19.2238576 22,19.5 C22,20.8807119 20.8807119,22 19.5,22 L19.4384472,22 C19.1623048,22 18.9384472,21.7761424 18.9384472,21.5 C18.9384472,21.2238576 19.1623048,21 19.4384472,21 L19.5,21 C20.3284271,21 21,20.3284271 21,19.5 Z M5.5,21 C5.77614237,21 6,21.2238576 6,21.5 C6,21.7761424 5.77614237,22 5.5,22 C4.11928813,22 3,20.8807119 3,19.5 L3,5.5 C3,4.11928813 4.11928813,3 5.5,3 C5.77614237,3 6,3.22385763 6,3.5 C6,3.77614237 5.77614237,4 5.5,4 C4.67157288,4 4,4.67157288 4,5.5 L4,19.5 C4,20.3284271 4.67157288,21 5.5,21 Z M7.5,22 C7.22385763,22 7,21.7761424 7,21.5 C7,21.2238576 7.22385763,21 7.5,21 L8.5,21 C8.77614237,21 9,21.2238576 9,21.5 C9,21.7761424 8.77614237,22 8.5,22 L7.5,22 Z M10.5,22 C10.2238576,22 10,21.7761424 10,21.5 C10,21.2238576 10.2238576,21 10.5,21 L11.5,21 C11.7761424,21 12,21.2238576 12,21.5 C12,21.7761424 11.7761424,22 11.5,22 L10.5,22 Z M13.5,22 C13.2238576,22 13,21.7761424 13,21.5 C13,21.2238576 13.2238576,21 13.5,21 L14.5,21 C14.7761424,21 15,21.2238576 15,21.5 C15,21.7761424 14.7761424,22 14.5,22 L13.5,22 Z M16.5,22 C16.2238576,22 16,21.7761424 16,21.5 C16,21.2238576 16.2238576,21 16.5,21 L17.5,21 C17.7761424,21 18,21.2238576 18,21.5 C18,21.7761424 17.7761424,22 17.5,22 L16.5,22 Z M7.5,4 C7.22385763,4 7,3.77614237 7,3.5 C7,3.22385763 7.22385763,3 7.5,3 L8.5,3 C8.77614237,3 9,3.22385763 9,3.5 C9,3.77614237 8.77614237,4 8.5,4 L7.5,4 Z M10.5,4 C10.2238576,4 10,3.77614237 10,3.5 C10,3.22385763 10.2238576,3 10.5,3 L11.5,3 C11.7761424,3 12,3.22385763 12,3.5 C12,3.77614237 11.7761424,4 11.5,4 L10.5,4 Z M13.5,4 C13.2238576,4 13,3.77614237 13,3.5 C13,3.22385763 13.2238576,3 13.5,3 L14.5,3 C14.7761424,3 15,3.22385763 15,3.5 C15,3.77614237 14.7761424,4 14.5,4 L13.5,4 Z M16.5,4 C16.2238576,4 16,3.77614237 16,3.5 C16,3.22385763 16.2238576,3 16.5,3 L17.5,3 C17.7761424,3 18,3.22385763 18,3.5 C18,3.77614237 17.7761424,4 17.5,4 L16.5,4 Z M12,5.5 C12,5.22385763 12.2238576,5 12.5,5 C12.7761424,5 13,5.22385763 13,5.5 L13,6.5 C13,6.77614237 12.7761424,7 12.5,7 C12.2238576,7 12,6.77614237 12,6.5 L12,5.5 Z M21,7.5 C21,7.22385763 21.2238576,7 21.5,7 C21.7761424,7 22,7.22385763 22,7.5 L22,8.5 C22,8.77614237 21.7761424,9 21.5,9 C21.2238576,9 21,8.77614237 21,8.5 L21,7.5 Z M21,10.5 C21,10.2238576 21.2238576,10 21.5,10 C21.7761424,10 22,10.2238576 22,10.5 L22,11.5 C22,11.7761424 21.7761424,12 21.5,12 C21.2238576,12 21,11.7761424 21,11.5 L21,10.5 Z M21,13.5 C21,13.2238576 21.2238576,13 21.5,13 C21.7761424,13 22,13.2238576 22,13.5 L22,14.5 C22,14.7761424 21.7761424,15 21.5,15 C21.2238576,15 21,14.7761424 21,14.5 L21,13.5 Z M21,16.5 C21,16.2238576 21.2238576,16 21.5,16 C21.7761424,16 22,16.2238576 22,16.5 L22,17.5 C22,17.7761424 21.7761424,18 21.5,18 C21.2238576,18 21,17.7761424 21,17.5 L21,16.5 Z M12,8.5 C12,8.22385763 12.2238576,8 12.5,8 C12.7761424,8 13,8.22385763 13,8.5 L13,9.5 C13,9.77614237 12.7761424,10 12.5,10 C12.2238576,10 12,9.77614237 12,9.5 L12,8.5 Z M12,15.5 C12,15.2238576 12.2238576,15 12.5,15 C12.7761424,15 13,15.2238576 13,15.5 L13,16.5 C13,16.7761424 12.7761424,17 12.5,17 C12.2238576,17 12,16.7761424 12,16.5 L12,15.5 Z M12,18.5 C12,18.2238576 12.2238576,18 12.5,18 C12.7761424,18 13,18.2238576 13,18.5 L13,19.5 C13,19.7761424 12.7761424,20 12.5,20 C12.2238576,20 12,19.7761424 12,19.5 L12,18.5 Z M8.5,13 C8.22385763,13 8,12.7761424 8,12.5 C8,12.2238576 8.22385763,12 8.5,12 L9.5,12 C9.77614237,12 10,12.2238576 10,12.5 C10,12.7761424 9.77614237,13 9.5,13 L8.5,13 Z M15.5,13 C15.2238576,13 15,12.7761424 15,12.5 C15,12.2238576 15.2238576,12 15.5,12 L16.5,12 C16.7761424,12 17,12.2238576 17,12.5 C17,12.7761424 16.7761424,13 16.5,13 L15.5,13 Z M18.5,13 C18.2238576,13 18,12.7761424 18,12.5 C18,12.2238576 18.2238576,12 18.5,12 L19.5,12 C19.7761424,12 20,12.2238576 20,12.5 C20,12.7761424 19.7761424,13 19.5,13 L18.5,13 Z"/></svg>',
104
110
  CELL_BORDER_FULL: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M13,12 L13.5,12 C13.7761424,12 14,12.2238576 14,12.5 C14,12.7761424 13.7761424,13 13.5,13 L13,13 L13,13.5 C13,13.7761424 12.7761424,14 12.5,14 C12.2238576,14 12,13.7761424 12,13.5 L12,13 L11.5,13 C11.2238576,13 11,12.7761424 11,12.5 C11,12.2238576 11.2238576,12 11.5,12 L12,12 L12,11.5 C12,11.2238576 12.2238576,11 12.5,11 C12.7761424,11 13,11.2238576 13,11.5 L13,12 Z M3,5.5 C3,4.11928813 4.11928813,3 5.5,3 L19.5000013,3 C20.8807132,3 22.0000013,4.11928813 22.0000013,5.5 L22.0000013,19.5069431 C22.0000013,20.887655 20.8807132,22.0069431 19.5000013,22.0069431 L5.5,22.0069431 C4.11928813,22.0069431 3,20.887655 3,19.5069431 L3,5.5 Z M4,5.5 L4,19.5069431 C4,20.3353702 4.67157288,21.0069431 5.5,21.0069431 L19.5000013,21.0069431 C20.3284285,21.0069431 21.0000013,20.3353702 21.0000013,19.5069431 L21.0000013,5.5 C21.0000013,4.67157288 20.3284285,4 19.5000013,4 L5.5,4 C4.67157288,4 4,4.67157288 4,5.5 Z M15.5,13 C15.2238576,13 15,12.7761424 15,12.5 C15,12.2238576 15.2238576,12 15.5,12 L16.5,12 C16.7761424,12 17,12.2238576 17,12.5 C17,12.7761424 16.7761424,13 16.5,13 L15.5,13 Z M18.5,13 C18.2238576,13 18,12.7761424 18,12.5 C18,12.2238576 18.2238576,12 18.5,12 L19.5,12 C19.7761424,12 20,12.2238576 20,12.5 C20,12.7761424 19.7761424,13 19.5,13 L18.5,13 Z M5.5,13 C5.22385763,13 5,12.7761424 5,12.5 C5,12.2238576 5.22385763,12 5.5,12 L6.5,12 C6.77614237,12 7,12.2238576 7,12.5 C7,12.7761424 6.77614237,13 6.5,13 L5.5,13 Z M8.5,13 C8.22385763,13 8,12.7761424 8,12.5 C8,12.2238576 8.22385763,12 8.5,12 L9.5,12 C9.77614237,12 10,12.2238576 10,12.5 C10,12.7761424 9.77614237,13 9.5,13 L8.5,13 Z M12,5.5 C12,5.22385763 12.2238576,5 12.5,5 C12.7761424,5 13,5.22385763 13,5.5 L13,6.5 C13,6.77614237 12.7761424,7 12.5,7 C12.2238576,7 12,6.77614237 12,6.5 L12,5.5 Z M12,8.5 C12,8.22385763 12.2238576,8 12.5,8 C12.7761424,8 13,8.22385763 13,8.5 L13,9.5 C13,9.77614237 12.7761424,10 12.5,10 C12.2238576,10 12,9.77614237 12,9.5 L12,8.5 Z M12,18.5 C12,18.2238576 12.2238576,18 12.5,18 C12.7761424,18 13,18.2238576 13,18.5 L13,19.5 C13,19.7761424 12.7761424,20 12.5,20 C12.2238576,20 12,19.7761424 12,19.5 L12,18.5 Z M12,15.5 C12,15.2238576 12.2238576,15 12.5,15 C12.7761424,15 13,15.2238576 13,15.5 L13,16.5 C13,16.7761424 12.7761424,17 12.5,17 C12.2238576,17 12,16.7761424 12,16.5 L12,15.5 Z"/></svg>',
@@ -175,6 +181,8 @@ const CSS_VARIABLES = {
175
181
  resizerPosition: "#fff",
176
182
  resizerPositionBackground: "#333",
177
183
  linkColor: "#0000ff",
184
+ scrollbarThumb: "hsl(160, 100%, 40%)",
185
+ scrollbarTrack: "hsl(223, 5%, 76%)",
178
186
  }
179
187
 
180
188
  const CSS = {
@@ -196,6 +204,8 @@ const CSS = {
196
204
  --resizer-position: #ffffff;
197
205
  --resizer-position-background: #333;
198
206
  --link-color: blue;
207
+ --scrollbar-thumb: hsl(160, 100%, 40%);
208
+ --scrollbar-track: hsl(223, 5%, 76%);
199
209
  }
200
210
  `,
201
211
  IFRAME_TRIBUTE: `.tribute{height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:100;border:1px solid var(--base-white-dark)}.tribute ul{margin:2px 0 0;padding:0;list-style:none;background-color:var(--mention); color:var(--text-color)}.tribute .category{color:var(--text-color); padding:5px;color:var(--primary);background-color:var(--base-white)}.tribute .item{padding:5px;cursor:pointer}.tribute .highlight{background-color:var(--mention-highlight)}`,
@@ -210,11 +220,12 @@ const CSS = {
210
220
  }
211
221
  ::-webkit-scrollbar-thumb {
212
222
  -webkit-box-shadow: inset 0 0 6px var(--shadow);
213
- background-color: var(--primary);
223
+ background-color: var(--scrollbar-thumb);
224
+ border-radius: 3px;
214
225
  }
215
226
  ::-webkit-scrollbar-track {
216
227
  -webkit-box-shadow: inset 0 0 6px var(--shadow);
217
- background-color: var(--white-mid-darker);
228
+ background-color: var(--scrollbar-track);
218
229
  }
219
230
  `,
220
231
  IFRAME_EDITOR: `
@@ -239,7 +250,6 @@ const CSS = {
239
250
  cursor: pointer;
240
251
  }
241
252
  .content-editable td:hover:not(:has(*:hover)) {
242
- cursor: pointer;
243
253
  outline: 1px dashed var(--dashed-border);
244
254
  }
245
255
  .content-editable .iframe-wrapper {
@@ -372,7 +382,22 @@ const TABLE_PLUGINS = [
372
382
  { icon: SVG.INSERT_COLUMN_LEFT, title: 'Insert Column Left', event: 'insert-column-left' },
373
383
  { icon: SVG.INSERT_COLUMN_RIGHT, title: 'Insert Column Right', event: 'insert-column-right' },
374
384
  { icon: SVG.DELETE_COLUMN, title: 'Delete Column', event: 'delete-column' },
375
- { icon: SVG.MERGE_CELLS_VERTICAL, title: 'Merge Column', event: 'merge-cells-vertical' },
385
+
386
+ { icon: SVG.MERGE_CELLS_VERTICAL, title: 'Merge Up', event: 'merge-cell-up' },
387
+ { icon: SVG.MERGE_CELLS_HORIZONTAL, title: 'Merge Right', event: 'merge-cell-right' },
388
+ { icon: SVG.MERGE_CELLS_VERTICAL, title: 'Merge Down', event: 'merge-cell-down' },
389
+ { icon: SVG.MERGE_CELLS_HORIZONTAL, title: 'Merge Left', event: 'merge-cell-left' },
390
+
391
+ { icon: SVG.SPLIT_CELLS_VERTICAL, title: 'Split Vertically', event: 'split-cell-vertical' },
392
+ { icon: SVG.SPLIT_CELLS_HORIZONTAL, title: 'Split Horizontally', event: 'split-cell-horizontal' },
393
+
394
+ { icon: SVG.CELL_WIDTH, title: 'Cell Width (px)', event: 'cell-width' },
395
+ { icon: SVG.CELL_HEIGHT, title: 'Cell Height (px)', event: 'cell-height' },
396
+ { icon: SVG.CELL_PADDING, title: 'Cell Padding (px)', event: 'cell-padding' },
397
+
398
+ { icon: SVG.ALIGN_LEFT, title: 'Align Left', event: 'align-left' },
399
+ { icon: SVG.ALIGN_CENTER, title: 'Align Center', event: 'align-center' },
400
+ { icon: SVG.ALIGN_RIGHT, title: 'Align Right', event: 'align-right' },
376
401
 
377
402
  { icon: SVG.CELL_BORDER_FULL, title: 'Border Full', event: 'cell-border-full' },
378
403
  { icon: SVG.CELL_BORDER_TOP, title: 'Border Top', event: 'cell-border-top' },
@@ -606,6 +631,28 @@ const FORMATS = {
606
631
 
607
632
  const GIPHY_POWERED_IMAGE = "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"
608
633
 
634
+ const TAB_CATEGORIES = {
635
+ 'Row': {
636
+ '': ['insert-row-above', 'insert-row-below', 'delete-row', 'row-background-color']
637
+ },
638
+ 'Column': {
639
+ '': ['insert-column-left', 'insert-column-right', 'delete-column', 'fixed-column-width', 'column-background-color']
640
+ },
641
+ 'Merge': {
642
+ '': ['merge-cell-up', 'merge-cell-right', 'merge-cell-down', 'merge-cell-left', 'split-cell-vertical', 'split-cell-horizontal']
643
+ },
644
+ 'Cell Property': {
645
+ 'Dimension': ['cell-width', 'cell-height', 'cell-padding'],
646
+ 'Border': ['cell-border-full', 'cell-border-top', 'cell-border-right', 'cell-border-bottom', 'cell-border-left', 'cell-border-none', 'border-color'],
647
+ 'Background': ['background-color']
648
+ },
649
+ 'Table Property': {
650
+ 'Alignment': ['align-left', 'align-center', 'align-right']
651
+ }
652
+ };
653
+
654
+ const RESIZE_MARGIN = 10;
655
+
609
656
  export {
610
657
  ERRORS,
611
658
  CLASSES,
@@ -626,4 +673,6 @@ export {
626
673
  SOCIAL_MEDIA_PATTERNS,
627
674
  GIPHY_POWERED_IMAGE,
628
675
  CSS_VARIABLES,
676
+ TAB_CATEGORIES,
677
+ RESIZE_MARGIN,
629
678
  }
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import './style.css'
2
2
  import { CLASSES, CSS, CSS_VARIABLES, ERRORS, REGEX, SVG } from "./constant"
3
- import PLUGINS, { applyOrderList, applyTextFormat } from './plugin';
4
- import { showAnchorPopover, changeAllToolbarState, changeToolbarStateByName, changeToolbarValueByName, cleanHTML, debounce, destroyImageResizer, destroyTableEditPlugin, initImageResizer, initTableEditPlugin, makeToolbarButton, makeToolbarColor, makeToolbarDropdown, makeToolbarSelect, rgbToHex, updateTableResizerPosition, destroyAnchorPopover, changeToolbarHtmlByName, showRemoteCursor, syncRemoteChangesDebounce, applyRemoteChanges, updateCursorPositionDebounce, buildTributeValues, updateHeight } from './utilities';
3
+ import PLUGINS, { applyOrderList, applyTextFormat, applyUnorderedList } from './plugin';
4
+ import { showAnchorPopover, changeAllToolbarState, changeToolbarStateByName, changeToolbarValueByName, cleanHTML, debounce, destroyImageResizer, destroyTableEditPlugin, initImageResizer, initTableEditPlugin, makeToolbarButton, makeToolbarColor, makeToolbarDropdown, makeToolbarSelect, rgbToHex, updateTableResizerPosition, destroyAnchorPopover, changeToolbarHtmlByName, showRemoteCursor, syncRemoteChangesDebounce, applyRemoteChanges, updateCursorPositionDebounce, buildTributeValues, updateHeight, getTableGrid, getCellPosition, makeUnorderedList, makeOrderedList, makeHeading, makeBlockQuote, makeStrikethrough, makeCodeBlock } from './utilities';
5
5
 
6
6
  class LeksyEditor {
7
7
 
@@ -22,8 +22,11 @@ class LeksyEditor {
22
22
  * @property {Object} cssVariables
23
23
  * @property {Boolean} disablePastedColorStyles
24
24
  * @property {Boolean} autoHeight
25
+ * @property {String} height
25
26
  * @property {String} maxHeight
26
27
  * @property {String} minHeight
28
+ * @property {String} iframeStyle
29
+ * @property {Boolean} disabled
27
30
  */
28
31
  /**
29
32
  *
@@ -258,6 +261,16 @@ class LeksyEditor {
258
261
  uploadVideo: async () => { },
259
262
  focus: () => { core.elements.editor.focus() },
260
263
  getCore: () => core,
264
+ updateHeight: (height) => {
265
+ core.elements.iframeContainer.style.setProperty('height', height);
266
+ core.elements.editor.style.setProperty('height', height);
267
+ },
268
+ setDisabled: (disabled) => {
269
+ options.disabled = disabled;
270
+ core.elements.editor.contentEditable = !disabled;
271
+ if (disabled) changeAllToolbarState(core, 'disabled')
272
+ else changeAllToolbarState(core, 'enabled')
273
+ },
261
274
  updateCssVariables: (newVariables) => {
262
275
  const variableMap = {
263
276
  primary: '--primary',
@@ -276,6 +289,8 @@ class LeksyEditor {
276
289
  resizerPosition: '--resizer-position',
277
290
  resizerPositionBackground: '--resizer-position-background',
278
291
  linkColor: '--link-color',
292
+ scrollbarThumb: '--scrollbar-thumb',
293
+ scrollbarTrack: '--scrollbar-track',
279
294
  };
280
295
 
281
296
  const mergedVariables = {
@@ -348,7 +363,7 @@ class LeksyEditor {
348
363
  if (_plugin.title === 'Tenor' && !options.tenorApiKey) throw Error(ERRORS.TENOR_KEY_NOT_FOUND);
349
364
 
350
365
  let toolbarPlugin
351
- if (_plugin.type === 'button') {
366
+ if (_plugin.type === 'button' || _plugin.type === 'reset-color') {
352
367
  toolbarPlugin = makeToolbarButton(_plugin, options, core)
353
368
  } else if (_plugin.type === 'dropdown' || _plugin.type === 'gallery' || _plugin.type === 'category' || _plugin.type === 'mention' || _plugin.type === 'table') {
354
369
  toolbarPlugin = makeToolbarDropdown(_plugin, options, core)
@@ -370,6 +385,8 @@ class LeksyEditor {
370
385
  toolbarContainer.appendChild(toolbarButtonSets)
371
386
  })
372
387
 
388
+ if (options.disabled) changeAllToolbarState(core, 'disabled')
389
+
373
390
  core.elements.toolbarContainer = toolbarContainer;
374
391
  core.elements.base.appendChild(toolbarContainer);
375
392
  }
@@ -394,29 +411,7 @@ class LeksyEditor {
394
411
  }
395
412
 
396
413
  static #initEditableContainer(options, core) {
397
- const makeOrderedList = () => {
398
- const textNode = core.state.range.startContainer;
399
- if (textNode.nodeType === Node.TEXT_NODE) {
400
- // Get the text typed so far
401
- let text = textNode.nodeValue.replace(/\u00A0/g, ' ');
402
- const haveLiNode = textNode.parentNode.closest('li')
403
-
404
- // Detect "1. " pattern
405
- if (!haveLiNode && text === "1. ") {
406
- text = text.slice(0, -3);
407
- textNode.nodeValue = text;
408
-
409
- // Update the caret position
410
- const newRange = document.createRange();
411
- newRange.setStart(textNode, text.length);
412
- newRange.setEnd(textNode, text.length);
413
- core.state.selection.removeAllRanges();
414
- core.state.selection.addRange(newRange);
415
- applyOrderList(core)
416
- }
417
- }
418
414
 
419
- }
420
415
  const handleCaretPositionAndPlugin = () => {
421
416
  try {
422
417
  const { parentTags, parentElements } = core.updateCaretPosition()
@@ -558,6 +553,8 @@ class LeksyEditor {
558
553
  --resizer-position: ${_CSS_VARIABLES.resizerPosition};
559
554
  --resizer-position-background: ${_CSS_VARIABLES.resizerPositionBackground};
560
555
  --link-color: ${_CSS_VARIABLES.linkColor};
556
+ --scrollbar-thumb: ${_CSS_VARIABLES.scrollbarThumb};
557
+ --scrollbar-track: ${_CSS_VARIABLES.scrollbarTrack};
561
558
  }
562
559
  `;
563
560
  }
@@ -566,8 +563,8 @@ class LeksyEditor {
566
563
  iframe.style.flex = '1 1 auto';
567
564
 
568
565
  if (options.autoHeight) iframe.style.height = 'auto';
569
- else iframe.style.height = options.minHeight ?? '250px';
570
- iframe.style.minHeight = options.minHeight ?? '250px';
566
+ else iframe.style.height = options.minHeight ?? options.height ?? '250px';
567
+ iframe.style.minHeight = options.minHeight ?? options.height ?? '250px';
571
568
  if (options.maxHeight) iframe.style.maxHeight = options.maxHeight;
572
569
 
573
570
  iframe.style.border = '0';
@@ -587,6 +584,7 @@ class LeksyEditor {
587
584
  ${CSS.IFRAME_TRIBUTE}
588
585
  ${CSS.IFRAME_EDITOR}
589
586
  ${CSS.IFRAME_RESIZER}
587
+ ${options.iframeStyle || ''}
590
588
  </style>
591
589
  </head>
592
590
  <body></body>
@@ -606,13 +604,13 @@ class LeksyEditor {
606
604
  }
607
605
 
608
606
  const contentEditableDiv = iframeDoc.createElement('div');
609
- contentEditableDiv.contentEditable = true;
607
+ contentEditableDiv.contentEditable = !options.disabled;
610
608
  contentEditableDiv.spellcheck = !!options.spellcheck
611
609
  contentEditableDiv.innerHTML = core.html;
612
610
  contentEditableDiv.className = 'content-editable';
613
611
  if (options.autoHeight) contentEditableDiv.style.height = 'auto';
614
- else contentEditableDiv.style.height = options.minHeight ?? '250px';
615
- contentEditableDiv.style.minHeight = options.minHeight ?? '250px';
612
+ else contentEditableDiv.style.height = options.minHeight ?? options.height ?? '250px';
613
+ contentEditableDiv.style.minHeight = options.minHeight ?? options.height ?? '250px';
616
614
  if (options.maxHeight) contentEditableDiv.style.maxHeight = options.maxHeight;
617
615
  if (options.autoHeight) iframe.contentDocument.body.style.overflow = 'hidden';
618
616
 
@@ -646,6 +644,86 @@ class LeksyEditor {
646
644
  }
647
645
  }
648
646
 
647
+ if (event.shiftKey && ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
648
+ const selection = core.elements.iframeWindow.getSelection();
649
+ if (selection.rangeCount > 0) {
650
+ let element = selection.focusNode;
651
+ if (element.nodeType === Node.TEXT_NODE) element = element.parentElement;
652
+ const td = element.closest('td, th');
653
+
654
+ if (td) {
655
+ const table = td.closest('table');
656
+ if (table) {
657
+ const grid = getTableGrid(table);
658
+ const pos = getCellPosition(grid, td);
659
+
660
+ if (pos) {
661
+ let { r, c } = pos;
662
+
663
+ if (event.key === 'ArrowLeft') {
664
+ const targetCell = grid[r][c - 1];
665
+ if (c === 0) return;
666
+ if (targetCell && targetCell !== td &&
667
+ (targetCell.rowSpan || 1) === (td.rowSpan || 1) &&
668
+ getCellPosition(grid, targetCell).r === r
669
+ ) {
670
+ if (targetCell.innerHTML.trim() !== '') {
671
+ td.innerHTML = targetCell.innerHTML + '<br/>' + td.innerHTML;
672
+ }
673
+ td.colSpan = (td.colSpan || 1) + (targetCell.colSpan || 1);
674
+ targetCell.parentNode.insertBefore(td, targetCell);
675
+ targetCell.remove();
676
+ }
677
+ } else if (event.key === 'ArrowRight') {
678
+ const targetCell = grid[r][c + (td.colSpan || 1)];
679
+ if (targetCell && targetCell !== td &&
680
+ (targetCell.rowSpan || 1) === (td.rowSpan || 1) &&
681
+ getCellPosition(grid, targetCell).r === r
682
+ ) {
683
+ if (targetCell.innerHTML.trim() !== '') {
684
+ td.innerHTML += '<br/>' + targetCell.innerHTML;
685
+ }
686
+ td.colSpan = (td.colSpan || 1) + (targetCell.colSpan || 1);
687
+ targetCell.remove();
688
+ }
689
+ } else if (event.key === 'ArrowUp') {
690
+ if (r === 0) return;
691
+ const targetCell = grid[r - 1][c];
692
+
693
+ if (targetCell && targetCell !== td &&
694
+ (targetCell.colSpan || 1) === (td.colSpan || 1) &&
695
+ getCellPosition(grid, targetCell).c === c
696
+ ) {
697
+ if (targetCell.innerHTML.trim() !== '') {
698
+ td.innerHTML = targetCell.innerHTML + '<br/>' + td.innerHTML;
699
+ }
700
+ td.rowSpan = (td.rowSpan || 1) + (targetCell.rowSpan || 1);
701
+ targetCell.parentNode.insertBefore(td, targetCell);
702
+ targetCell.remove();
703
+ }
704
+ } else if (event.key === 'ArrowDown') {
705
+ const targetRowIdx = r + (td.rowSpan || 1);
706
+ if (targetRowIdx >= grid.length) return;
707
+ const targetCell = grid[targetRowIdx][c];
708
+
709
+ if (targetCell && targetCell !== td &&
710
+ (targetCell.colSpan || 1) === (td.colSpan || 1) &&
711
+ getCellPosition(grid, targetCell).c === c
712
+ ) {
713
+ if (targetCell.innerHTML.trim() !== '') {
714
+ td.innerHTML += '<br/>' + targetCell.innerHTML;
715
+ }
716
+ td.rowSpan = (td.rowSpan || 1) + (targetCell.rowSpan || 1);
717
+ targetCell.remove();
718
+ }
719
+ }
720
+ core.updateCaretPosition();
721
+ }
722
+ }
723
+ }
724
+ }
725
+ }
726
+
649
727
  if (event.key === 'Tab') {
650
728
  event.preventDefault();
651
729
 
@@ -676,7 +754,7 @@ class LeksyEditor {
676
754
  const after = node.textContent.slice(caretOffset);
677
755
 
678
756
  const a = document.createElement('a');
679
- a.href = cleanUrl.startsWith('http') ? cleanUrl : 'https://' + cleanUrl;
757
+ a.href = cleanUrl.toLowerCase().startsWith('http') ? cleanUrl : 'https://' + cleanUrl;
680
758
  a.textContent = cleanUrl;
681
759
  a.target = '_blank';
682
760
 
@@ -714,12 +792,19 @@ class LeksyEditor {
714
792
 
715
793
  if (!isLinkCreated) core.elements.lastCreatedLink = null
716
794
 
795
+ makeUnorderedList(event, core)
796
+ makeHeading(event, core)
797
+ makeBlockQuote(event, core)
798
+ makeStrikethrough(event, core)
799
+ makeCodeBlock(event, core)
800
+
717
801
  keyPressDebounce()
718
802
  }
719
803
  contentEditableDiv.onkeyup = () => {
720
- makeOrderedList()
804
+ makeOrderedList(event, core)
721
805
  }
722
806
  contentEditableDiv.onclick = (e) => {
807
+ if (options.disabled) return
723
808
  handleCaretPositionAndPlugin()
724
809
  let element = e.target; // The clicked element
725
810
 
@@ -729,7 +814,14 @@ class LeksyEditor {
729
814
  destroyTableEditPlugin(options, core)
730
815
  destroyAnchorPopover(core)
731
816
 
732
- if (element.tagName === "A") showAnchorPopover(e.target, e.pageX, e.pageY, options, core)
817
+ if (e.target.closest("a")?.tagName === 'A') {
818
+ const anchor = e.target.closest("a");
819
+ if (anchor) {
820
+ core.elements.selectedElement = anchor;
821
+ showAnchorPopover(anchor, e.pageX, e.pageY, options, core);
822
+ }
823
+
824
+ }
733
825
  if (element.tagName === 'IMG') initImageResizer('image', e.target, options, core)
734
826
  if (element.tagName === 'TD' || element.tagName === 'TH') initTableEditPlugin(e.target, options, core)
735
827
  if (element.tagName === "FIGURE") initImageResizer('figure', e.target, options, core)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leksy-editor",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Leksy Editor is an alternative to traditional WYSIWYG editors, designed primarily for creating mail templates, blogs, and documents without any content manipulation.",
5
5
  "main": "index.js",
6
6
  "directories": {
package/plugin.js CHANGED
@@ -23,6 +23,17 @@ const applyOrderList = (core) => {
23
23
  changeToolbarStateByName(core, 'inactive', ['unordered_list'])
24
24
  }
25
25
 
26
+ const applyUnorderedList = (core) => {
27
+ core.elements.iframeWindow.execCommand('insertUnorderedList');
28
+ core.elements.editor.focus();
29
+ core.updateCaretPosition()
30
+
31
+ const isActive = core.elements.iframeWindow.queryCommandState('insertUnorderedList');
32
+ if (isActive) changeToolbarStateByName(core, 'active', ['unordered_list'])
33
+ else changeToolbarStateByName(core, 'inactive', ['unordered_list'])
34
+ changeToolbarStateByName(core, 'inactive', ['ordered_list'])
35
+ }
36
+
26
37
  const PLUGINS = {
27
38
  'undo': {
28
39
  title: 'Undo',
@@ -273,14 +284,7 @@ const PLUGINS = {
273
284
  icon: SVG.LIST_BULLETS,
274
285
  type: 'button',
275
286
  click: (event, core, options) => {
276
- core.elements.editor.focus();
277
- core.elements.iframeWindow.execCommand('insertUnorderedList');
278
- core.updateCaretPosition()
279
-
280
- const isActive = core.elements.iframeWindow.queryCommandState('insertUnorderedList');
281
- if (isActive) changeToolbarStateByName(core, 'active', ['unordered_list'])
282
- else changeToolbarStateByName(core, 'inactive', ['unordered_list'])
283
- changeToolbarStateByName(core, 'inactive', ['ordered_list'])
287
+ applyUnorderedList(core)
284
288
  }
285
289
  },
286
290
  'line_height': {
@@ -323,7 +327,7 @@ const PLUGINS = {
323
327
  'remove_font_color': {
324
328
  title: 'Remove Font Color',
325
329
  icon: `${SVG.REMOVE_FORMAT}${SVG.FONT_COLOR}`,
326
- type: "button",
330
+ type: "reset-color",
327
331
  click: (event, core, options) => {
328
332
  if (!core.state.range) return;
329
333
  core.elements.editor.focus();
@@ -369,7 +373,7 @@ const PLUGINS = {
369
373
  'remove_highlight_color': {
370
374
  title: 'Remove Highlight Color',
371
375
  icon: `${SVG.REMOVE_FORMAT}${SVG.HIGHLIGHT_COLOR}`,
372
- type: "button",
376
+ type: "reset-color",
373
377
  click: (event, core, options) => {
374
378
  core.elements.editor.focus();
375
379
  core.elements.iframeWindow.execCommand('hiliteColor', false, "transparent"); // Apply color to selected text
@@ -1204,4 +1208,5 @@ export default PLUGINS
1204
1208
  export {
1205
1209
  applyTextFormat,
1206
1210
  applyOrderList,
1211
+ applyUnorderedList
1207
1212
  }
package/style.css CHANGED
@@ -119,6 +119,11 @@
119
119
  width: unset;
120
120
  }
121
121
 
122
+ .leksy-editor-toolbar-item.reset-color {
123
+ width: unset;
124
+ padding: 4px 8px;
125
+ }
126
+
122
127
  .leksy-editor-toolbar-item.color {
123
128
  width: unset;
124
129
  padding: 4px 8px;
@@ -223,6 +228,11 @@
223
228
  visibility: visible;
224
229
  }
225
230
 
231
+ .leksy-editor-resize-item:not([data-title])::after,
232
+ .leksy-editor-resize-item[data-title=""]::after {
233
+ display: none;
234
+ }
235
+
226
236
  .leksy-editor-resize-item::after {
227
237
  content: attr(data-title);
228
238
  position: absolute;
@@ -361,6 +371,28 @@
361
371
  background-color: white;
362
372
  }
363
373
 
374
+ .leksy-editor-popover-tabs {
375
+ display: flex;
376
+ background: #f1f1f1;
377
+ border-bottom: 1px solid #ccc;
378
+ }
379
+
380
+ button.leksy-editor-popover-tab {
381
+ padding: 8px 12px;
382
+ border: none;
383
+ background: transparent;
384
+ cursor: pointer;
385
+ }
386
+
387
+ button.leksy-editor-popover-tab.active {
388
+ border-bottom: 2px solid black;
389
+ font-weight: bold;
390
+ }
391
+
392
+ .leksy-editor-popover-tabs .leksy-editor-popover-tab:not(:last-child) {
393
+ border-right: 1px solid #ccc;
394
+ }
395
+
364
396
  .leksy-editor-codeview {
365
397
  flex: 1 1 auto;
366
398
  padding: 4px;