leksy-editor 1.0.21 → 1.2.0

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,6 +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. |
102
+ | `autoHeight` | Automatically adjusts height based on content. |
103
+ | `height` | Height for the editor. |
104
+ | `maxHeight` | Maximum height for the editor. |
105
+ | `minHeight` | Minimum height for the editor. |
106
+ | `iframeStyle` | To design inside iframe, pass your css here |
107
+ | `disabled` | To disabled editor |
101
108
 
102
109
  ### CSS Customization
103
110
 
@@ -118,6 +125,9 @@ cssVariables: {
118
125
  textColor: "hsl(216, 10%, 20%)",
119
126
  resizerPosition: "#fff",
120
127
  resizerPositionBackground: "#333",
128
+ linkColor: "#0000ff",
129
+ scrollbarThumb: "hsl(160, 100%, 40%)",
130
+ scrollbarTrack: "hsl(223, 5%, 76%)",
121
131
  }
122
132
  ```
123
133
 
@@ -169,9 +179,19 @@ Similarly, Pexels and Tenor can be integrated using `pexels` and `tenor` plugins
169
179
  | `onBlur(html)` | Triggered when the editor loses focus. |
170
180
  | `onAttachment(files)` | Fires when files are attached. |
171
181
  | `manipulateImage()` | Custom function for manipulating images. |
182
+ | `handleFilePicker()` | Custom function for file upload, useful for Android and iOS file upload. |
172
183
  | `uploadVideo(file)` | Handles video uploads, returns a promise with video URL. |
173
184
  | `focus()` | Focuses the editor. |
174
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. |
175
195
 
176
196
  ## License
177
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>',
@@ -167,13 +173,16 @@ const CSS_VARIABLES = {
167
173
  resizerBackground: "hsl(211, 100%, 62%, 0.3)",
168
174
  shadow: "rgba(0, 0, 0, 0.3)",
169
175
  mention: " #efefef",
170
- mentionHighlight: " #ddd",
176
+ mentionHighlight: "#ddd",
171
177
  dashedBorder: "gray",
172
178
  tableResizer: "cornsilk",
173
179
  tableResizerOutline: "darkblue",
174
180
  textColor: "hsl(216, 10%, 20%)",
175
181
  resizerPosition: "#fff",
176
- resizerPositionBackground: " #333",
182
+ resizerPositionBackground: "#333",
183
+ linkColor: "#0000ff",
184
+ scrollbarThumb: "hsl(160, 100%, 40%)",
185
+ scrollbarTrack: "hsl(223, 5%, 76%)",
177
186
  }
178
187
 
179
188
  const CSS = {
@@ -194,22 +203,29 @@ const CSS = {
194
203
  --text-color: #000000;
195
204
  --resizer-position: #ffffff;
196
205
  --resizer-position-background: #333;
206
+ --link-color: blue;
207
+ --scrollbar-thumb: hsl(160, 100%, 40%);
208
+ --scrollbar-track: hsl(223, 5%, 76%);
197
209
  }
198
210
  `,
199
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)}`,
200
212
  IFRAME_BODY: `
201
213
  body { margin: 0}
214
+ a {
215
+ color: var(--link-color);
216
+ }
202
217
  ::-webkit-scrollbar {
203
218
  width: 6px;
204
219
  height: 6px;
205
220
  }
206
221
  ::-webkit-scrollbar-thumb {
207
222
  -webkit-box-shadow: inset 0 0 6px var(--shadow);
208
- background-color: var(--primary);
223
+ background-color: var(--scrollbar-thumb);
224
+ border-radius: 3px;
209
225
  }
210
226
  ::-webkit-scrollbar-track {
211
227
  -webkit-box-shadow: inset 0 0 6px var(--shadow);
212
- background-color: var(--white-mid-darker);
228
+ background-color: var(--scrollbar-track);
213
229
  }
214
230
  `,
215
231
  IFRAME_EDITOR: `
@@ -234,7 +250,6 @@ const CSS = {
234
250
  cursor: pointer;
235
251
  }
236
252
  .content-editable td:hover:not(:has(*:hover)) {
237
- cursor: pointer;
238
253
  outline: 1px dashed var(--dashed-border);
239
254
  }
240
255
  .content-editable .iframe-wrapper {
@@ -367,7 +382,22 @@ const TABLE_PLUGINS = [
367
382
  { icon: SVG.INSERT_COLUMN_LEFT, title: 'Insert Column Left', event: 'insert-column-left' },
368
383
  { icon: SVG.INSERT_COLUMN_RIGHT, title: 'Insert Column Right', event: 'insert-column-right' },
369
384
  { icon: SVG.DELETE_COLUMN, title: 'Delete Column', event: 'delete-column' },
370
- { 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' },
371
401
 
372
402
  { icon: SVG.CELL_BORDER_FULL, title: 'Border Full', event: 'cell-border-full' },
373
403
  { icon: SVG.CELL_BORDER_TOP, title: 'Border Top', event: 'cell-border-top' },
@@ -601,6 +631,28 @@ const FORMATS = {
601
631
 
602
632
  const GIPHY_POWERED_IMAGE = "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"
603
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
+
604
656
  export {
605
657
  ERRORS,
606
658
  CLASSES,
@@ -621,4 +673,6 @@ export {
621
673
  SOCIAL_MEDIA_PATTERNS,
622
674
  GIPHY_POWERED_IMAGE,
623
675
  CSS_VARIABLES,
676
+ TAB_CATEGORIES,
677
+ RESIZE_MARGIN,
624
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 } 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
 
@@ -21,6 +21,12 @@ class LeksyEditor {
21
21
  * @property {String} tenorApiKey
22
22
  * @property {Object} cssVariables
23
23
  * @property {Boolean} disablePastedColorStyles
24
+ * @property {Boolean} autoHeight
25
+ * @property {String} height
26
+ * @property {String} maxHeight
27
+ * @property {String} minHeight
28
+ * @property {String} iframeStyle
29
+ * @property {Boolean} disabled
24
30
  */
25
31
  /**
26
32
  *
@@ -46,7 +52,7 @@ class LeksyEditor {
46
52
  base: baseElement,
47
53
  toolbar: {},
48
54
  },
49
- state: { isCodeViewOpen: false, page: 1, totalPages: null, next: null },
55
+ state: { isCodeViewOpen: false, page: 1, totalPages: null, next: null, tribute: null },
50
56
  html: options.value || '<div><br></div>',
51
57
  cursor: {
52
58
  startIndex: 0,
@@ -127,6 +133,7 @@ class LeksyEditor {
127
133
  }
128
134
  },
129
135
  onChange: (html = core.elements.editor.innerHTML) => {
136
+ updateHeight(core, options)
130
137
  updateTableResizerPosition(options, core)
131
138
  if (html === '<br>' || html === '<div><br></div>') html = ''
132
139
  core.html = html;
@@ -243,6 +250,7 @@ class LeksyEditor {
243
250
  setContents: (html) => {
244
251
  core.html = html
245
252
  core.elements.editor.innerHTML = html
253
+ updateHeight(core, options)
246
254
  },
247
255
  getContents: () => core.html,
248
256
  onChange: () => { },
@@ -253,6 +261,58 @@ class LeksyEditor {
253
261
  uploadVideo: async () => { },
254
262
  focus: () => { core.elements.editor.focus() },
255
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
+ },
274
+ updateCssVariables: (newVariables) => {
275
+ const variableMap = {
276
+ primary: '--primary',
277
+ midDarker: '--white-mid-darker',
278
+ baseWhite: '--base-white',
279
+ whiteDark: '--base-white-dark',
280
+ shadow: '--shadow',
281
+ resizer: '--resizer',
282
+ resizerBackground: '--resizer-background',
283
+ mention: '--mention',
284
+ mentionHighlight: '--mention-highlight',
285
+ dashedBorder: '--dashed-border',
286
+ tableResizer: '--table-resizer',
287
+ tableResizerOutline: '--table-resizer-outline',
288
+ textColor: '--text-color',
289
+ resizerPosition: '--resizer-position',
290
+ resizerPositionBackground: '--resizer-position-background',
291
+ linkColor: '--link-color',
292
+ scrollbarThumb: '--scrollbar-thumb',
293
+ scrollbarTrack: '--scrollbar-track',
294
+ };
295
+
296
+ const mergedVariables = {
297
+ ...CSS_VARIABLES,
298
+ ...newVariables
299
+ };
300
+
301
+ Object.keys(variableMap).forEach(key => {
302
+ const cssVar = variableMap[key];
303
+ const value = mergedVariables[key];
304
+
305
+ if (value !== undefined) {
306
+ core.elements.iframeWindow.documentElement.style.setProperty(cssVar, value);
307
+ }
308
+ });
309
+ },
310
+ updateLabels: (labels = []) => {
311
+ if (!core.state.tribute) return;
312
+
313
+ const values = buildTributeValues(labels);
314
+ core.state.tribute.append(0, values, true);
315
+ },
256
316
  getLocalCursor: () => core.cursor,
257
317
  setRemoteCursor: (user, cursor) => showRemoteCursor(core, user, cursor),
258
318
  onLocalCursorChange: () => { },
@@ -303,7 +363,7 @@ class LeksyEditor {
303
363
  if (_plugin.title === 'Tenor' && !options.tenorApiKey) throw Error(ERRORS.TENOR_KEY_NOT_FOUND);
304
364
 
305
365
  let toolbarPlugin
306
- if (_plugin.type === 'button') {
366
+ if (_plugin.type === 'button' || _plugin.type === 'reset-color') {
307
367
  toolbarPlugin = makeToolbarButton(_plugin, options, core)
308
368
  } else if (_plugin.type === 'dropdown' || _plugin.type === 'gallery' || _plugin.type === 'category' || _plugin.type === 'mention' || _plugin.type === 'table') {
309
369
  toolbarPlugin = makeToolbarDropdown(_plugin, options, core)
@@ -325,6 +385,8 @@ class LeksyEditor {
325
385
  toolbarContainer.appendChild(toolbarButtonSets)
326
386
  })
327
387
 
388
+ if (options.disabled) changeAllToolbarState(core, 'disabled')
389
+
328
390
  core.elements.toolbarContainer = toolbarContainer;
329
391
  core.elements.base.appendChild(toolbarContainer);
330
392
  }
@@ -349,29 +411,7 @@ class LeksyEditor {
349
411
  }
350
412
 
351
413
  static #initEditableContainer(options, core) {
352
- const makeOrderedList = () => {
353
- const textNode = core.state.range.startContainer;
354
- if (textNode.nodeType === Node.TEXT_NODE) {
355
- // Get the text typed so far
356
- let text = textNode.nodeValue.replace(/\u00A0/g, ' ');
357
- const haveLiNode = textNode.parentNode.closest('li')
358
-
359
- // Detect "1. " pattern
360
- if (!haveLiNode && text === "1. ") {
361
- text = text.slice(0, -3);
362
- textNode.nodeValue = text;
363
-
364
- // Update the caret position
365
- const newRange = document.createRange();
366
- newRange.setStart(textNode, text.length);
367
- newRange.setEnd(textNode, text.length);
368
- core.state.selection.removeAllRanges();
369
- core.state.selection.addRange(newRange);
370
- applyOrderList(core)
371
- }
372
- }
373
414
 
374
- }
375
415
  const handleCaretPositionAndPlugin = () => {
376
416
  try {
377
417
  const { parentTags, parentElements } = core.updateCaretPosition()
@@ -477,10 +517,15 @@ class LeksyEditor {
477
517
  childList: true,
478
518
  subtree: true
479
519
  });
520
+
521
+ // font / layout reflow
522
+ const ro = new ResizeObserver(() => {
523
+ updateHeight(core, options)
524
+ });
525
+ ro.observe(contentEditableDiv);
480
526
  }
481
527
 
482
528
  /***************************** for css theme variables ********************************* */
483
-
484
529
  if (options.cssVariables) {
485
530
  const cssVariable = options.cssVariables;
486
531
  const _CSS_VARIABLES = structuredClone(CSS_VARIABLES)
@@ -507,13 +552,21 @@ class LeksyEditor {
507
552
  --text-color: ${_CSS_VARIABLES.textColor};
508
553
  --resizer-position: ${_CSS_VARIABLES.resizerPosition};
509
554
  --resizer-position-background: ${_CSS_VARIABLES.resizerPositionBackground};
555
+ --link-color: ${_CSS_VARIABLES.linkColor};
556
+ --scrollbar-thumb: ${_CSS_VARIABLES.scrollbarThumb};
557
+ --scrollbar-track: ${_CSS_VARIABLES.scrollbarTrack};
510
558
  }
511
559
  `;
512
560
  }
513
561
 
514
562
  const iframe = document.createElement('iframe');
515
563
  iframe.style.flex = '1 1 auto';
516
- iframe.style.height = '250px'
564
+
565
+ if (options.autoHeight) iframe.style.height = 'auto';
566
+ else iframe.style.height = options.minHeight ?? options.height ?? '250px';
567
+ iframe.style.minHeight = options.minHeight ?? options.height ?? '250px';
568
+ if (options.maxHeight) iframe.style.maxHeight = options.maxHeight;
569
+
517
570
  iframe.style.border = '0';
518
571
  core.elements.base.appendChild(iframe)
519
572
 
@@ -531,6 +584,7 @@ class LeksyEditor {
531
584
  ${CSS.IFRAME_TRIBUTE}
532
585
  ${CSS.IFRAME_EDITOR}
533
586
  ${CSS.IFRAME_RESIZER}
587
+ ${options.iframeStyle || ''}
534
588
  </style>
535
589
  </head>
536
590
  <body></body>
@@ -550,10 +604,15 @@ class LeksyEditor {
550
604
  }
551
605
 
552
606
  const contentEditableDiv = iframeDoc.createElement('div');
553
- contentEditableDiv.contentEditable = true;
607
+ contentEditableDiv.contentEditable = !options.disabled;
554
608
  contentEditableDiv.spellcheck = !!options.spellcheck
555
609
  contentEditableDiv.innerHTML = core.html;
556
610
  contentEditableDiv.className = 'content-editable';
611
+ if (options.autoHeight) contentEditableDiv.style.height = 'auto';
612
+ else contentEditableDiv.style.height = options.minHeight ?? options.height ?? '250px';
613
+ contentEditableDiv.style.minHeight = options.minHeight ?? options.height ?? '250px';
614
+ if (options.maxHeight) contentEditableDiv.style.maxHeight = options.maxHeight;
615
+ if (options.autoHeight) iframe.contentDocument.body.style.overflow = 'hidden';
557
616
 
558
617
  contentEditableDiv.oninput = (e) => {
559
618
  core.onChange(e.target.innerHTML)
@@ -585,6 +644,86 @@ class LeksyEditor {
585
644
  }
586
645
  }
587
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
+
588
727
  if (event.key === 'Tab') {
589
728
  event.preventDefault();
590
729
 
@@ -615,7 +754,7 @@ class LeksyEditor {
615
754
  const after = node.textContent.slice(caretOffset);
616
755
 
617
756
  const a = document.createElement('a');
618
- a.href = cleanUrl.startsWith('http') ? cleanUrl : 'https://' + cleanUrl;
757
+ a.href = cleanUrl.toLowerCase().startsWith('http') ? cleanUrl : 'https://' + cleanUrl;
619
758
  a.textContent = cleanUrl;
620
759
  a.target = '_blank';
621
760
 
@@ -653,12 +792,19 @@ class LeksyEditor {
653
792
 
654
793
  if (!isLinkCreated) core.elements.lastCreatedLink = null
655
794
 
795
+ makeUnorderedList(event, core)
796
+ makeHeading(event, core)
797
+ makeBlockQuote(event, core)
798
+ makeStrikethrough(event, core)
799
+ makeCodeBlock(event, core)
800
+
656
801
  keyPressDebounce()
657
802
  }
658
803
  contentEditableDiv.onkeyup = () => {
659
- makeOrderedList()
804
+ makeOrderedList(event, core)
660
805
  }
661
806
  contentEditableDiv.onclick = (e) => {
807
+ if (options.disabled) return
662
808
  handleCaretPositionAndPlugin()
663
809
  let element = e.target; // The clicked element
664
810
 
@@ -668,7 +814,14 @@ class LeksyEditor {
668
814
  destroyTableEditPlugin(options, core)
669
815
  destroyAnchorPopover(core)
670
816
 
671
- 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
+ }
672
825
  if (element.tagName === 'IMG') initImageResizer('image', e.target, options, core)
673
826
  if (element.tagName === 'TD' || element.tagName === 'TH') initTableEditPlugin(e.target, options, core)
674
827
  if (element.tagName === "FIGURE") initImageResizer('figure', e.target, options, core)
@@ -718,18 +871,8 @@ class LeksyEditor {
718
871
  script.src = "https://cdnjs.cloudflare.com/ajax/libs/tributejs/5.1.3/tribute.js";
719
872
 
720
873
  script.onload = () => {
721
- const tribute = new iframe.contentWindow.Tribute({
722
- values: options.labels.flatMap(category => {
723
- const fields = [
724
- { key: category.name, isCategory: true },
725
- ...category.fields.map(field => ({
726
- key: field.name,
727
- value: field.value,
728
- }))
729
- ];
730
-
731
- return fields
732
- }),
874
+ core.state.tribute = new iframe.contentWindow.Tribute({
875
+ values: buildTributeValues(options.labels),
733
876
  noMatchTemplate: () => '<li>No match found</li>',
734
877
  menuItemTemplate: (item) => {
735
878
  if (item.original.isCategory) return `<div class="category">${item.original.key}</div>`;
@@ -741,7 +884,7 @@ class LeksyEditor {
741
884
  return `<span spellcheck="false" contentEditable="false" data-id="${item.original.value}">${item.original.key}</span>`;
742
885
  },
743
886
  });
744
- tribute.attach(contentEditableDiv);
887
+ core.state.tribute.attach(contentEditableDiv);
745
888
  makeObserver()
746
889
  };
747
890
  iframeDoc.body.appendChild(script);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leksy-editor",
3
- "version": "1.0.21",
3
+ "version": "1.2.0",
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": {