overtype 2.1.0 → 2.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 +26 -18
- package/dist/overtype-webcomponent.esm.js +3672 -2122
- package/dist/overtype-webcomponent.esm.js.map +4 -4
- package/dist/overtype-webcomponent.js +3667 -2117
- package/dist/overtype-webcomponent.js.map +4 -4
- package/dist/overtype-webcomponent.min.js +106 -93
- package/dist/overtype.cjs +3644 -2121
- package/dist/overtype.cjs.map +4 -4
- package/dist/overtype.d.ts +16 -0
- package/dist/overtype.esm.js +3644 -2121
- package/dist/overtype.esm.js.map +4 -4
- package/dist/overtype.js +3621 -2098
- package/dist/overtype.js.map +4 -4
- package/dist/overtype.min.js +107 -94
- package/package.json +4 -4
- package/src/icons.js +6 -0
- package/src/link-tooltip.js +40 -71
- package/src/overtype-webcomponent.js +32 -3
- package/src/overtype.d.ts +16 -0
- package/src/overtype.js +403 -38
- package/src/parser.js +9 -3
- package/src/shortcuts.js +11 -76
- package/src/styles.js +36 -28
- package/src/themes.js +14 -0
- package/src/toolbar-buttons.js +48 -12
- package/src/toolbar.js +39 -48
package/src/shortcuts.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Keyboard shortcuts handler for OverType editor
|
|
3
|
-
*
|
|
3
|
+
* Delegates to editor.performAction for consistent behavior
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import * as markdownActions from 'markdown-actions';
|
|
7
|
-
|
|
8
6
|
/**
|
|
9
7
|
* ShortcutsManager - Handles keyboard shortcuts for the editor
|
|
10
8
|
*/
|
|
11
9
|
export class ShortcutsManager {
|
|
12
10
|
constructor(editor) {
|
|
13
11
|
this.editor = editor;
|
|
14
|
-
this.textarea = editor.textarea;
|
|
15
|
-
// No need to add our own listener - OverType will call handleKeydown
|
|
16
12
|
}
|
|
17
13
|
|
|
18
14
|
/**
|
|
@@ -26,100 +22,39 @@ export class ShortcutsManager {
|
|
|
26
22
|
|
|
27
23
|
if (!modKey) return false;
|
|
28
24
|
|
|
29
|
-
let
|
|
25
|
+
let actionId = null;
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
switch(event.key.toLowerCase()) {
|
|
27
|
+
switch (event.key.toLowerCase()) {
|
|
33
28
|
case 'b':
|
|
34
|
-
if (!event.shiftKey)
|
|
35
|
-
action = 'toggleBold';
|
|
36
|
-
}
|
|
29
|
+
if (!event.shiftKey) actionId = 'toggleBold';
|
|
37
30
|
break;
|
|
38
|
-
|
|
39
31
|
case 'i':
|
|
40
|
-
if (!event.shiftKey)
|
|
41
|
-
action = 'toggleItalic';
|
|
42
|
-
}
|
|
32
|
+
if (!event.shiftKey) actionId = 'toggleItalic';
|
|
43
33
|
break;
|
|
44
|
-
|
|
45
34
|
case 'k':
|
|
46
|
-
if (!event.shiftKey)
|
|
47
|
-
action = 'insertLink';
|
|
48
|
-
}
|
|
35
|
+
if (!event.shiftKey) actionId = 'insertLink';
|
|
49
36
|
break;
|
|
50
|
-
|
|
51
37
|
case '7':
|
|
52
|
-
if (event.shiftKey)
|
|
53
|
-
action = 'toggleNumberedList';
|
|
54
|
-
}
|
|
38
|
+
if (event.shiftKey) actionId = 'toggleNumberedList';
|
|
55
39
|
break;
|
|
56
|
-
|
|
57
40
|
case '8':
|
|
58
|
-
if (event.shiftKey)
|
|
59
|
-
action = 'toggleBulletList';
|
|
60
|
-
}
|
|
41
|
+
if (event.shiftKey) actionId = 'toggleBulletList';
|
|
61
42
|
break;
|
|
62
43
|
}
|
|
63
44
|
|
|
64
|
-
|
|
65
|
-
if (action) {
|
|
45
|
+
if (actionId) {
|
|
66
46
|
event.preventDefault();
|
|
67
|
-
|
|
68
|
-
// If toolbar exists, use its handleAction method (exact same code path)
|
|
69
|
-
if (this.editor.toolbar) {
|
|
70
|
-
this.editor.toolbar.handleAction(action);
|
|
71
|
-
} else {
|
|
72
|
-
// Fallback: duplicate the toolbar's handleAction logic
|
|
73
|
-
this.handleAction(action);
|
|
74
|
-
}
|
|
75
|
-
|
|
47
|
+
this.editor.performAction(actionId, event);
|
|
76
48
|
return true;
|
|
77
49
|
}
|
|
78
50
|
|
|
79
51
|
return false;
|
|
80
52
|
}
|
|
81
53
|
|
|
82
|
-
/**
|
|
83
|
-
* Handle action - fallback when no toolbar exists
|
|
84
|
-
* This duplicates toolbar.handleAction for consistency
|
|
85
|
-
*/
|
|
86
|
-
async handleAction(action) {
|
|
87
|
-
const textarea = this.textarea;
|
|
88
|
-
if (!textarea) return;
|
|
89
|
-
|
|
90
|
-
// Focus textarea
|
|
91
|
-
textarea.focus();
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
switch (action) {
|
|
95
|
-
case 'toggleBold':
|
|
96
|
-
markdownActions.toggleBold(textarea);
|
|
97
|
-
break;
|
|
98
|
-
case 'toggleItalic':
|
|
99
|
-
markdownActions.toggleItalic(textarea);
|
|
100
|
-
break;
|
|
101
|
-
case 'insertLink':
|
|
102
|
-
markdownActions.insertLink(textarea);
|
|
103
|
-
break;
|
|
104
|
-
case 'toggleBulletList':
|
|
105
|
-
markdownActions.toggleBulletList(textarea);
|
|
106
|
-
break;
|
|
107
|
-
case 'toggleNumberedList':
|
|
108
|
-
markdownActions.toggleNumberedList(textarea);
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Trigger input event to update preview
|
|
113
|
-
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
114
|
-
} catch (error) {
|
|
115
|
-
console.error('Error in markdown action:', error);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
54
|
/**
|
|
120
55
|
* Cleanup
|
|
121
56
|
*/
|
|
122
57
|
destroy() {
|
|
123
58
|
// Nothing to clean up since we don't add our own listener
|
|
124
59
|
}
|
|
125
|
-
}
|
|
60
|
+
}
|
package/src/styles.js
CHANGED
|
@@ -211,17 +211,36 @@ export function generateStyles(options = {}) {
|
|
|
211
211
|
/* Prevent mobile zoom on focus */
|
|
212
212
|
touch-action: manipulation !important;
|
|
213
213
|
|
|
214
|
-
/* Disable autofill
|
|
214
|
+
/* Disable autofill */
|
|
215
215
|
autocomplete: off !important;
|
|
216
216
|
autocorrect: off !important;
|
|
217
217
|
autocapitalize: off !important;
|
|
218
|
-
spellcheck: false !important;
|
|
219
218
|
}
|
|
220
219
|
|
|
221
220
|
.overtype-wrapper .overtype-input::selection {
|
|
222
221
|
background-color: var(--selection, rgba(244, 211, 94, 0.4));
|
|
223
222
|
}
|
|
224
223
|
|
|
224
|
+
/* Placeholder shim - visible when textarea is empty */
|
|
225
|
+
.overtype-wrapper .overtype-placeholder {
|
|
226
|
+
position: absolute !important;
|
|
227
|
+
top: 0 !important;
|
|
228
|
+
left: 0 !important;
|
|
229
|
+
width: 100% !important;
|
|
230
|
+
z-index: 0 !important;
|
|
231
|
+
pointer-events: none !important;
|
|
232
|
+
user-select: none !important;
|
|
233
|
+
font-family: ${fontFamily} !important;
|
|
234
|
+
font-size: var(--instance-font-size, ${fontSize}) !important;
|
|
235
|
+
line-height: var(--instance-line-height, ${lineHeight}) !important;
|
|
236
|
+
padding: var(--instance-padding, ${padding}) !important;
|
|
237
|
+
box-sizing: border-box !important;
|
|
238
|
+
color: var(--placeholder, #999) !important;
|
|
239
|
+
overflow: hidden !important;
|
|
240
|
+
white-space: nowrap !important;
|
|
241
|
+
text-overflow: ellipsis !important;
|
|
242
|
+
}
|
|
243
|
+
|
|
225
244
|
/* Preview layer styles */
|
|
226
245
|
.overtype-wrapper .overtype-preview {
|
|
227
246
|
/* Layer positioning */
|
|
@@ -489,6 +508,10 @@ export function generateStyles(options = {}) {
|
|
|
489
508
|
|
|
490
509
|
|
|
491
510
|
/* Toolbar Styles */
|
|
511
|
+
.overtype-toolbar.overtype-toolbar-hidden {
|
|
512
|
+
display: none !important;
|
|
513
|
+
}
|
|
514
|
+
|
|
492
515
|
.overtype-toolbar {
|
|
493
516
|
display: flex !important;
|
|
494
517
|
align-items: center !important;
|
|
@@ -763,19 +786,14 @@ export function generateStyles(options = {}) {
|
|
|
763
786
|
|
|
764
787
|
/* Code blocks - proper pre/code styling in preview mode */
|
|
765
788
|
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block {
|
|
766
|
-
background:
|
|
767
|
-
color: #
|
|
789
|
+
background: var(--code-bg, rgba(244, 211, 94, 0.4)) !important;
|
|
790
|
+
color: var(--code, #0d3b66) !important;
|
|
768
791
|
padding: 1.2em !important;
|
|
769
792
|
border-radius: 3px !important;
|
|
770
793
|
overflow-x: auto !important;
|
|
771
794
|
margin: 0 !important;
|
|
772
795
|
display: block !important;
|
|
773
796
|
}
|
|
774
|
-
|
|
775
|
-
/* Cave theme code block background in preview mode */
|
|
776
|
-
.overtype-container[data-theme="cave"][data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block {
|
|
777
|
-
background: #11171F !important;
|
|
778
|
-
}
|
|
779
797
|
|
|
780
798
|
.overtype-container[data-mode="preview"] .overtype-wrapper .overtype-preview pre.code-block code {
|
|
781
799
|
background: transparent !important;
|
|
@@ -840,16 +858,17 @@ export function generateStyles(options = {}) {
|
|
|
840
858
|
height: 2px !important;
|
|
841
859
|
}
|
|
842
860
|
|
|
843
|
-
/* Link Tooltip
|
|
861
|
+
/* Link Tooltip */
|
|
844
862
|
.overtype-link-tooltip {
|
|
845
|
-
/* Visual styles that work for both positioning methods */
|
|
846
863
|
background: #333 !important;
|
|
847
864
|
color: white !important;
|
|
848
865
|
padding: 6px 10px !important;
|
|
849
866
|
border-radius: 16px !important;
|
|
850
867
|
font-size: 12px !important;
|
|
851
868
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif !important;
|
|
852
|
-
display:
|
|
869
|
+
display: flex !important;
|
|
870
|
+
visibility: hidden !important;
|
|
871
|
+
pointer-events: none !important;
|
|
853
872
|
z-index: 10000 !important;
|
|
854
873
|
cursor: pointer !important;
|
|
855
874
|
box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important;
|
|
@@ -857,25 +876,14 @@ export function generateStyles(options = {}) {
|
|
|
857
876
|
white-space: nowrap !important;
|
|
858
877
|
overflow: hidden !important;
|
|
859
878
|
text-overflow: ellipsis !important;
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
879
|
+
position: fixed;
|
|
880
|
+
top: 0;
|
|
881
|
+
left: 0;
|
|
863
882
|
}
|
|
864
883
|
|
|
865
884
|
.overtype-link-tooltip.visible {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
/* CSS Anchor Positioning (modern browsers only) */
|
|
870
|
-
@supports (position-anchor: --x) and (position-area: center) {
|
|
871
|
-
.overtype-link-tooltip {
|
|
872
|
-
/* Only anchor positioning specific properties */
|
|
873
|
-
position-anchor: var(--target-anchor, --link-0);
|
|
874
|
-
position-area: block-end center;
|
|
875
|
-
margin-top: 8px !important;
|
|
876
|
-
position-try: most-width block-end inline-end, flip-inline, block-start center;
|
|
877
|
-
position-visibility: anchors-visible;
|
|
878
|
-
}
|
|
885
|
+
visibility: visible !important;
|
|
886
|
+
pointer-events: auto !important;
|
|
879
887
|
}
|
|
880
888
|
|
|
881
889
|
${mobileStyles}
|
package/src/themes.js
CHANGED
|
@@ -39,6 +39,7 @@ export const solar = {
|
|
|
39
39
|
toolbarIcon: '#0d3b66', // Yale Blue - icon color
|
|
40
40
|
toolbarHover: '#f5f5f5', // Light gray - hover background
|
|
41
41
|
toolbarActive: '#faf0ca', // Lemon Chiffon - active button background
|
|
42
|
+
placeholder: '#999999', // Gray - placeholder text
|
|
42
43
|
}
|
|
43
44
|
};
|
|
44
45
|
|
|
@@ -78,6 +79,7 @@ export const cave = {
|
|
|
78
79
|
toolbarIcon: '#c5dde8', // Light blue-gray - icon color
|
|
79
80
|
toolbarHover: '#243546', // Slightly lighter charcoal - hover background
|
|
80
81
|
toolbarActive: '#2a3f52', // Even lighter - active button background
|
|
82
|
+
placeholder: '#6a7a88', // Muted blue-gray - placeholder text
|
|
81
83
|
}
|
|
82
84
|
};
|
|
83
85
|
|
|
@@ -87,6 +89,7 @@ export const cave = {
|
|
|
87
89
|
export const themes = {
|
|
88
90
|
solar,
|
|
89
91
|
cave,
|
|
92
|
+
auto: solar,
|
|
90
93
|
// Aliases for backward compatibility
|
|
91
94
|
light: solar,
|
|
92
95
|
dark: cave
|
|
@@ -106,6 +109,17 @@ export function getTheme(theme) {
|
|
|
106
109
|
return theme;
|
|
107
110
|
}
|
|
108
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Resolve auto theme to actual theme based on system color scheme
|
|
114
|
+
* @param {string} themeName - Theme name to resolve
|
|
115
|
+
* @returns {string} Resolved theme name ('solar' or 'cave' if auto, otherwise unchanged)
|
|
116
|
+
*/
|
|
117
|
+
export function resolveAutoTheme(themeName) {
|
|
118
|
+
if (themeName !== 'auto') return themeName;
|
|
119
|
+
const mq = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)');
|
|
120
|
+
return mq?.matches ? 'cave' : 'solar';
|
|
121
|
+
}
|
|
122
|
+
|
|
109
123
|
/**
|
|
110
124
|
* Apply theme colors to CSS variables
|
|
111
125
|
* @param {Object} colors - Theme colors object
|
package/src/toolbar-buttons.js
CHANGED
|
@@ -8,15 +8,18 @@ import * as markdownActions from 'markdown-actions';
|
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Built-in toolbar button definitions
|
|
11
|
-
* Each button has: name, icon, title, action
|
|
11
|
+
* Each button has: name, actionId, icon, title, action
|
|
12
|
+
* - name: DOM identifier for the button element
|
|
13
|
+
* - actionId: Canonical action identifier used by performAction
|
|
12
14
|
* Action signature: ({ editor, getValue, setValue, event }) => void
|
|
13
15
|
*/
|
|
14
16
|
export const toolbarButtons = {
|
|
15
17
|
bold: {
|
|
16
18
|
name: 'bold',
|
|
19
|
+
actionId: 'toggleBold',
|
|
17
20
|
icon: icons.boldIcon,
|
|
18
21
|
title: 'Bold (Ctrl+B)',
|
|
19
|
-
action: ({ editor
|
|
22
|
+
action: ({ editor }) => {
|
|
20
23
|
markdownActions.toggleBold(editor.textarea);
|
|
21
24
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
22
25
|
}
|
|
@@ -24,9 +27,10 @@ export const toolbarButtons = {
|
|
|
24
27
|
|
|
25
28
|
italic: {
|
|
26
29
|
name: 'italic',
|
|
30
|
+
actionId: 'toggleItalic',
|
|
27
31
|
icon: icons.italicIcon,
|
|
28
32
|
title: 'Italic (Ctrl+I)',
|
|
29
|
-
action: ({ editor
|
|
33
|
+
action: ({ editor }) => {
|
|
30
34
|
markdownActions.toggleItalic(editor.textarea);
|
|
31
35
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
32
36
|
}
|
|
@@ -34,9 +38,10 @@ export const toolbarButtons = {
|
|
|
34
38
|
|
|
35
39
|
code: {
|
|
36
40
|
name: 'code',
|
|
41
|
+
actionId: 'toggleCode',
|
|
37
42
|
icon: icons.codeIcon,
|
|
38
43
|
title: 'Inline Code',
|
|
39
|
-
action: ({ editor
|
|
44
|
+
action: ({ editor }) => {
|
|
40
45
|
markdownActions.toggleCode(editor.textarea);
|
|
41
46
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
42
47
|
}
|
|
@@ -49,9 +54,10 @@ export const toolbarButtons = {
|
|
|
49
54
|
|
|
50
55
|
link: {
|
|
51
56
|
name: 'link',
|
|
57
|
+
actionId: 'insertLink',
|
|
52
58
|
icon: icons.linkIcon,
|
|
53
59
|
title: 'Insert Link',
|
|
54
|
-
action: ({ editor
|
|
60
|
+
action: ({ editor }) => {
|
|
55
61
|
markdownActions.insertLink(editor.textarea);
|
|
56
62
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
57
63
|
}
|
|
@@ -59,9 +65,10 @@ export const toolbarButtons = {
|
|
|
59
65
|
|
|
60
66
|
h1: {
|
|
61
67
|
name: 'h1',
|
|
68
|
+
actionId: 'toggleH1',
|
|
62
69
|
icon: icons.h1Icon,
|
|
63
70
|
title: 'Heading 1',
|
|
64
|
-
action: ({ editor
|
|
71
|
+
action: ({ editor }) => {
|
|
65
72
|
markdownActions.toggleH1(editor.textarea);
|
|
66
73
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
67
74
|
}
|
|
@@ -69,9 +76,10 @@ export const toolbarButtons = {
|
|
|
69
76
|
|
|
70
77
|
h2: {
|
|
71
78
|
name: 'h2',
|
|
79
|
+
actionId: 'toggleH2',
|
|
72
80
|
icon: icons.h2Icon,
|
|
73
81
|
title: 'Heading 2',
|
|
74
|
-
action: ({ editor
|
|
82
|
+
action: ({ editor }) => {
|
|
75
83
|
markdownActions.toggleH2(editor.textarea);
|
|
76
84
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
77
85
|
}
|
|
@@ -79,9 +87,10 @@ export const toolbarButtons = {
|
|
|
79
87
|
|
|
80
88
|
h3: {
|
|
81
89
|
name: 'h3',
|
|
90
|
+
actionId: 'toggleH3',
|
|
82
91
|
icon: icons.h3Icon,
|
|
83
92
|
title: 'Heading 3',
|
|
84
|
-
action: ({ editor
|
|
93
|
+
action: ({ editor }) => {
|
|
85
94
|
markdownActions.toggleH3(editor.textarea);
|
|
86
95
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
87
96
|
}
|
|
@@ -89,9 +98,10 @@ export const toolbarButtons = {
|
|
|
89
98
|
|
|
90
99
|
bulletList: {
|
|
91
100
|
name: 'bulletList',
|
|
101
|
+
actionId: 'toggleBulletList',
|
|
92
102
|
icon: icons.bulletListIcon,
|
|
93
103
|
title: 'Bullet List',
|
|
94
|
-
action: ({ editor
|
|
104
|
+
action: ({ editor }) => {
|
|
95
105
|
markdownActions.toggleBulletList(editor.textarea);
|
|
96
106
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
97
107
|
}
|
|
@@ -99,9 +109,10 @@ export const toolbarButtons = {
|
|
|
99
109
|
|
|
100
110
|
orderedList: {
|
|
101
111
|
name: 'orderedList',
|
|
112
|
+
actionId: 'toggleNumberedList',
|
|
102
113
|
icon: icons.orderedListIcon,
|
|
103
114
|
title: 'Numbered List',
|
|
104
|
-
action: ({ editor
|
|
115
|
+
action: ({ editor }) => {
|
|
105
116
|
markdownActions.toggleNumberedList(editor.textarea);
|
|
106
117
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
107
118
|
}
|
|
@@ -109,9 +120,10 @@ export const toolbarButtons = {
|
|
|
109
120
|
|
|
110
121
|
taskList: {
|
|
111
122
|
name: 'taskList',
|
|
123
|
+
actionId: 'toggleTaskList',
|
|
112
124
|
icon: icons.taskListIcon,
|
|
113
125
|
title: 'Task List',
|
|
114
|
-
action: ({ editor
|
|
126
|
+
action: ({ editor }) => {
|
|
115
127
|
if (markdownActions.toggleTaskList) {
|
|
116
128
|
markdownActions.toggleTaskList(editor.textarea);
|
|
117
129
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
@@ -121,14 +133,38 @@ export const toolbarButtons = {
|
|
|
121
133
|
|
|
122
134
|
quote: {
|
|
123
135
|
name: 'quote',
|
|
136
|
+
actionId: 'toggleQuote',
|
|
124
137
|
icon: icons.quoteIcon,
|
|
125
138
|
title: 'Quote',
|
|
126
|
-
action: ({ editor
|
|
139
|
+
action: ({ editor }) => {
|
|
127
140
|
markdownActions.toggleQuote(editor.textarea);
|
|
128
141
|
editor.textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
129
142
|
}
|
|
130
143
|
},
|
|
131
144
|
|
|
145
|
+
upload: {
|
|
146
|
+
name: 'upload',
|
|
147
|
+
actionId: 'uploadFile',
|
|
148
|
+
icon: icons.uploadIcon,
|
|
149
|
+
title: 'Upload File',
|
|
150
|
+
action: ({ editor }) => {
|
|
151
|
+
if (!editor.options.fileUpload?.enabled) return;
|
|
152
|
+
const input = document.createElement('input');
|
|
153
|
+
input.type = 'file';
|
|
154
|
+
input.multiple = true;
|
|
155
|
+
if (editor.options.fileUpload.mimeTypes?.length > 0) {
|
|
156
|
+
input.accept = editor.options.fileUpload.mimeTypes.join(',');
|
|
157
|
+
}
|
|
158
|
+
input.onchange = () => {
|
|
159
|
+
if (!input.files?.length) return;
|
|
160
|
+
const dt = new DataTransfer();
|
|
161
|
+
for (const f of input.files) dt.items.add(f);
|
|
162
|
+
editor._handleDataTransfer(dt);
|
|
163
|
+
};
|
|
164
|
+
input.click();
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
|
|
132
168
|
viewMode: {
|
|
133
169
|
name: 'viewMode',
|
|
134
170
|
icon: icons.eyeIcon,
|
package/src/toolbar.js
CHANGED
|
@@ -73,39 +73,11 @@ export class Toolbar {
|
|
|
73
73
|
return button;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
// Standard button click handler
|
|
77
|
-
button._clickHandler =
|
|
76
|
+
// Standard button click handler - delegate to performAction
|
|
77
|
+
button._clickHandler = (e) => {
|
|
78
78
|
e.preventDefault();
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
this.editor.textarea.focus();
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
if (buttonConfig.action) {
|
|
85
|
-
// Call action with consistent context object
|
|
86
|
-
await buttonConfig.action({
|
|
87
|
-
editor: this.editor,
|
|
88
|
-
getValue: () => this.editor.getValue(),
|
|
89
|
-
setValue: (value) => this.editor.setValue(value),
|
|
90
|
-
event: e
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
} catch (error) {
|
|
94
|
-
console.error(`Button "${buttonConfig.name}" error:`, error);
|
|
95
|
-
|
|
96
|
-
// Dispatch error event
|
|
97
|
-
this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {
|
|
98
|
-
detail: { buttonName: buttonConfig.name, error }
|
|
99
|
-
}));
|
|
100
|
-
|
|
101
|
-
// Visual feedback
|
|
102
|
-
button.classList.add('button-error');
|
|
103
|
-
button.style.animation = 'buttonError 0.3s';
|
|
104
|
-
setTimeout(() => {
|
|
105
|
-
button.classList.remove('button-error');
|
|
106
|
-
button.style.animation = '';
|
|
107
|
-
}, 300);
|
|
108
|
-
}
|
|
79
|
+
const actionId = buttonConfig.actionId || buttonConfig.name;
|
|
80
|
+
this.editor.performAction(actionId, e);
|
|
109
81
|
};
|
|
110
82
|
|
|
111
83
|
button.addEventListener('click', button._clickHandler);
|
|
@@ -113,31 +85,38 @@ export class Toolbar {
|
|
|
113
85
|
}
|
|
114
86
|
|
|
115
87
|
/**
|
|
116
|
-
* Handle button action programmatically
|
|
117
|
-
*
|
|
88
|
+
* Handle button action programmatically
|
|
89
|
+
* Accepts either an actionId string or a buttonConfig object (backwards compatible)
|
|
90
|
+
* @param {string|Object} actionIdOrConfig - Action identifier string or button config object
|
|
91
|
+
* @returns {Promise<boolean>} Whether the action was executed
|
|
118
92
|
*/
|
|
119
|
-
async handleAction(
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// Call action with consistent context object
|
|
126
|
-
await buttonConfig.action({
|
|
93
|
+
async handleAction(actionIdOrConfig) {
|
|
94
|
+
// Old style: buttonConfig object with .action function - execute directly
|
|
95
|
+
if (actionIdOrConfig && typeof actionIdOrConfig === 'object' && typeof actionIdOrConfig.action === 'function') {
|
|
96
|
+
this.editor.textarea.focus();
|
|
97
|
+
try {
|
|
98
|
+
await actionIdOrConfig.action({
|
|
127
99
|
editor: this.editor,
|
|
128
100
|
getValue: () => this.editor.getValue(),
|
|
129
101
|
setValue: (value) => this.editor.setValue(value),
|
|
130
102
|
event: null
|
|
131
103
|
});
|
|
104
|
+
return true;
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error(`Action "${actionIdOrConfig.name}" error:`, error);
|
|
107
|
+
this.editor.wrapper.dispatchEvent(new CustomEvent('button-error', {
|
|
108
|
+
detail: { buttonName: actionIdOrConfig.name, error }
|
|
109
|
+
}));
|
|
110
|
+
return false;
|
|
132
111
|
}
|
|
133
|
-
}
|
|
134
|
-
console.error(`Action "${buttonConfig.name}" error:`, error);
|
|
112
|
+
}
|
|
135
113
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}));
|
|
114
|
+
// New style: string actionId - delegate to performAction
|
|
115
|
+
if (typeof actionIdOrConfig === 'string') {
|
|
116
|
+
return this.editor.performAction(actionIdOrConfig, null);
|
|
140
117
|
}
|
|
118
|
+
|
|
119
|
+
return false;
|
|
141
120
|
}
|
|
142
121
|
|
|
143
122
|
/**
|
|
@@ -308,6 +287,18 @@ export class Toolbar {
|
|
|
308
287
|
}
|
|
309
288
|
}
|
|
310
289
|
|
|
290
|
+
show() {
|
|
291
|
+
if (this.container) {
|
|
292
|
+
this.container.classList.remove('overtype-toolbar-hidden');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
hide() {
|
|
297
|
+
if (this.container) {
|
|
298
|
+
this.container.classList.add('overtype-toolbar-hidden');
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
311
302
|
/**
|
|
312
303
|
* Destroy toolbar and cleanup
|
|
313
304
|
*/
|