overtype 2.3.10 → 2.4.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 +103 -11
- package/dist/overtype-webcomponent.esm.js +454 -96
- package/dist/overtype-webcomponent.esm.js.map +3 -3
- package/dist/overtype-webcomponent.js +454 -96
- package/dist/overtype-webcomponent.js.map +3 -3
- package/dist/overtype-webcomponent.min.js +57 -56
- package/dist/overtype.cjs +454 -96
- package/dist/overtype.cjs.map +3 -3
- package/dist/overtype.d.ts +12 -0
- package/dist/overtype.esm.js +454 -96
- package/dist/overtype.esm.js.map +3 -3
- package/dist/overtype.js +454 -96
- package/dist/overtype.js.map +3 -3
- package/dist/overtype.min.js +53 -52
- package/package.json +3 -3
- package/src/link-tooltip.js +18 -2
- package/src/overtype.d.ts +12 -0
- package/src/overtype.js +196 -70
- package/src/shortcuts.js +12 -0
- package/src/toolbar-buttons.js +10 -0
- package/src/toolbar.js +308 -49
package/dist/overtype.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OverType v2.
|
|
2
|
+
* OverType v2.4.0
|
|
3
3
|
* A lightweight markdown editor library with perfect WYSIWYG alignment
|
|
4
4
|
* @license MIT
|
|
5
5
|
* @author David Miranda
|
|
@@ -781,6 +781,16 @@ var ShortcutsManager = class {
|
|
|
781
781
|
const modKey = isMac ? event.metaKey : event.ctrlKey;
|
|
782
782
|
if (!modKey)
|
|
783
783
|
return false;
|
|
784
|
+
if (event.key === "]") {
|
|
785
|
+
event.preventDefault();
|
|
786
|
+
this.editor.indentSelection();
|
|
787
|
+
return true;
|
|
788
|
+
}
|
|
789
|
+
if (event.key === "[") {
|
|
790
|
+
event.preventDefault();
|
|
791
|
+
this.editor.outdentSelection();
|
|
792
|
+
return true;
|
|
793
|
+
}
|
|
784
794
|
let actionId = null;
|
|
785
795
|
switch (event.key.toLowerCase()) {
|
|
786
796
|
case "b":
|
|
@@ -2893,6 +2903,10 @@ var Toolbar = class {
|
|
|
2893
2903
|
this.editor = editor;
|
|
2894
2904
|
this.container = null;
|
|
2895
2905
|
this.buttons = {};
|
|
2906
|
+
this.currentItemIndex = 0;
|
|
2907
|
+
this.handleDocumentClick = null;
|
|
2908
|
+
this.activeDropdown = null;
|
|
2909
|
+
this.activeDropdownButton = null;
|
|
2896
2910
|
this.toolbarButtons = options.toolbarButtons || [];
|
|
2897
2911
|
}
|
|
2898
2912
|
/**
|
|
@@ -2901,8 +2915,10 @@ var Toolbar = class {
|
|
|
2901
2915
|
create() {
|
|
2902
2916
|
this.container = document.createElement("div");
|
|
2903
2917
|
this.container.className = "overtype-toolbar";
|
|
2918
|
+
this.container.id = this.getInstanceElementId("toolbar");
|
|
2904
2919
|
this.container.setAttribute("role", "toolbar");
|
|
2905
2920
|
this.container.setAttribute("aria-label", "Formatting toolbar");
|
|
2921
|
+
this.container.setAttribute("aria-controls", this.editor.textarea.id);
|
|
2906
2922
|
this.toolbarButtons.forEach((buttonConfig) => {
|
|
2907
2923
|
if (buttonConfig.name === "separator") {
|
|
2908
2924
|
const separator = this.createSeparator();
|
|
@@ -2913,8 +2929,116 @@ var Toolbar = class {
|
|
|
2913
2929
|
this.container.appendChild(button);
|
|
2914
2930
|
}
|
|
2915
2931
|
});
|
|
2932
|
+
this.setupRovingTabIndex();
|
|
2933
|
+
this.updateButtonStates();
|
|
2916
2934
|
this.editor.container.insertBefore(this.container, this.editor.wrapper);
|
|
2917
2935
|
}
|
|
2936
|
+
/**
|
|
2937
|
+
* Build a stable id from the owning OverType instance
|
|
2938
|
+
*/
|
|
2939
|
+
getInstanceElementId(name) {
|
|
2940
|
+
return `overtype-${this.editor.instanceId}-${name}`;
|
|
2941
|
+
}
|
|
2942
|
+
/**
|
|
2943
|
+
* Configure toolbar focus management per the ARIA toolbar pattern
|
|
2944
|
+
*/
|
|
2945
|
+
setupRovingTabIndex() {
|
|
2946
|
+
const toolbarItems = this.getToolbarItems();
|
|
2947
|
+
if (toolbarItems.length === 0) {
|
|
2948
|
+
return;
|
|
2949
|
+
}
|
|
2950
|
+
this.currentItemIndex = this.getValidItemIndex(this.currentItemIndex);
|
|
2951
|
+
this.updateTabIndexes();
|
|
2952
|
+
this.container.addEventListener("keydown", (e) => {
|
|
2953
|
+
this.onToolbarKeydown(e);
|
|
2954
|
+
});
|
|
2955
|
+
this.container.addEventListener("focusin", (e) => {
|
|
2956
|
+
this.onToolbarFocusin(e);
|
|
2957
|
+
});
|
|
2958
|
+
}
|
|
2959
|
+
/**
|
|
2960
|
+
* Get toolbar buttons in DOM order for keyboard navigation
|
|
2961
|
+
*/
|
|
2962
|
+
getToolbarItems() {
|
|
2963
|
+
if (!this.container) {
|
|
2964
|
+
return [];
|
|
2965
|
+
}
|
|
2966
|
+
return Array.from(this.container.querySelectorAll(".overtype-toolbar-button"));
|
|
2967
|
+
}
|
|
2968
|
+
/**
|
|
2969
|
+
* Handle keyboard navigation within the toolbar
|
|
2970
|
+
*/
|
|
2971
|
+
onToolbarKeydown(e) {
|
|
2972
|
+
const toolbarItems = this.getToolbarItems();
|
|
2973
|
+
if (!toolbarItems.includes(e.target)) {
|
|
2974
|
+
return;
|
|
2975
|
+
}
|
|
2976
|
+
switch (e.key) {
|
|
2977
|
+
case "ArrowRight":
|
|
2978
|
+
e.preventDefault();
|
|
2979
|
+
this.focusItem(this.currentItemIndex + 1);
|
|
2980
|
+
break;
|
|
2981
|
+
case "ArrowLeft":
|
|
2982
|
+
e.preventDefault();
|
|
2983
|
+
this.focusItem(this.currentItemIndex - 1);
|
|
2984
|
+
break;
|
|
2985
|
+
case "Home":
|
|
2986
|
+
e.preventDefault();
|
|
2987
|
+
this.focusItem(0);
|
|
2988
|
+
break;
|
|
2989
|
+
case "End":
|
|
2990
|
+
e.preventDefault();
|
|
2991
|
+
this.focusItem(toolbarItems.length - 1);
|
|
2992
|
+
break;
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
/**
|
|
2996
|
+
* Remember the focused toolbar item as the toolbar tab stop
|
|
2997
|
+
*/
|
|
2998
|
+
onToolbarFocusin(e) {
|
|
2999
|
+
const focusedItemIndex = this.getToolbarItems().indexOf(e.target);
|
|
3000
|
+
if (focusedItemIndex === -1) {
|
|
3001
|
+
return;
|
|
3002
|
+
}
|
|
3003
|
+
this.currentItemIndex = focusedItemIndex;
|
|
3004
|
+
this.updateTabIndexes();
|
|
3005
|
+
}
|
|
3006
|
+
/**
|
|
3007
|
+
* Move focus to a toolbar item and make it the only tab stop
|
|
3008
|
+
*/
|
|
3009
|
+
focusItem(index) {
|
|
3010
|
+
const toolbarItems = this.getToolbarItems();
|
|
3011
|
+
if (toolbarItems.length === 0) {
|
|
3012
|
+
return;
|
|
3013
|
+
}
|
|
3014
|
+
this.currentItemIndex = this.getValidItemIndex(index, toolbarItems);
|
|
3015
|
+
this.updateTabIndexes();
|
|
3016
|
+
toolbarItems[this.currentItemIndex].focus();
|
|
3017
|
+
}
|
|
3018
|
+
/**
|
|
3019
|
+
* Normalize toolbar item indexes with wrapping
|
|
3020
|
+
*/
|
|
3021
|
+
getValidItemIndex(index, toolbarItems = this.getToolbarItems()) {
|
|
3022
|
+
const itemCount = toolbarItems.length;
|
|
3023
|
+
if (itemCount === 0) {
|
|
3024
|
+
return 0;
|
|
3025
|
+
}
|
|
3026
|
+
if (index < 0) {
|
|
3027
|
+
return itemCount - 1;
|
|
3028
|
+
}
|
|
3029
|
+
if (index >= itemCount) {
|
|
3030
|
+
return 0;
|
|
3031
|
+
}
|
|
3032
|
+
return index;
|
|
3033
|
+
}
|
|
3034
|
+
/**
|
|
3035
|
+
* Keep exactly one toolbar item in the page tab sequence
|
|
3036
|
+
*/
|
|
3037
|
+
updateTabIndexes() {
|
|
3038
|
+
this.getToolbarItems().forEach((item, index) => {
|
|
3039
|
+
item.tabIndex = index === this.currentItemIndex ? 0 : -1;
|
|
3040
|
+
});
|
|
3041
|
+
}
|
|
2918
3042
|
/**
|
|
2919
3043
|
* Create a toolbar separator
|
|
2920
3044
|
*/
|
|
@@ -2938,10 +3062,22 @@ var Toolbar = class {
|
|
|
2938
3062
|
if (buttonConfig.name === "viewMode") {
|
|
2939
3063
|
button.classList.add("has-dropdown");
|
|
2940
3064
|
button.dataset.dropdown = "true";
|
|
2941
|
-
button.
|
|
3065
|
+
button.setAttribute("aria-haspopup", "menu");
|
|
3066
|
+
button.setAttribute("aria-expanded", "false");
|
|
3067
|
+
button._clickHandler = (e) => {
|
|
2942
3068
|
e.preventDefault();
|
|
2943
3069
|
this.toggleViewModeDropdown(button);
|
|
2944
|
-
}
|
|
3070
|
+
};
|
|
3071
|
+
button._keydownHandler = (e) => {
|
|
3072
|
+
if (!["ArrowDown", "ArrowUp", "Enter", " "].includes(e.key)) {
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
e.preventDefault();
|
|
3076
|
+
const placement = e.key === "ArrowUp" ? "last" : "current";
|
|
3077
|
+
this.openViewModeDropdown(button, placement);
|
|
3078
|
+
};
|
|
3079
|
+
button.addEventListener("click", button._clickHandler);
|
|
3080
|
+
button.addEventListener("keydown", button._keydownHandler);
|
|
2945
3081
|
return button;
|
|
2946
3082
|
}
|
|
2947
3083
|
button._clickHandler = (e) => {
|
|
@@ -2996,12 +3132,17 @@ var Toolbar = class {
|
|
|
2996
3132
|
* Not exposed to users - viewMode button behavior is fixed
|
|
2997
3133
|
*/
|
|
2998
3134
|
toggleViewModeDropdown(button) {
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
existingDropdown.remove();
|
|
3002
|
-
button.classList.remove("dropdown-active");
|
|
3135
|
+
if (this.activeDropdown) {
|
|
3136
|
+
this.closeViewModeDropdown(button);
|
|
3003
3137
|
return;
|
|
3004
3138
|
}
|
|
3139
|
+
this.openViewModeDropdown(button);
|
|
3140
|
+
}
|
|
3141
|
+
/**
|
|
3142
|
+
* Open the view mode dropdown
|
|
3143
|
+
*/
|
|
3144
|
+
openViewModeDropdown(button, focusPlacement = null) {
|
|
3145
|
+
this.closeViewModeDropdown(button);
|
|
3005
3146
|
button.classList.add("dropdown-active");
|
|
3006
3147
|
const dropdown = this.createViewModeDropdown(button);
|
|
3007
3148
|
const rect = button.getBoundingClientRect();
|
|
@@ -3009,16 +3150,42 @@ var Toolbar = class {
|
|
|
3009
3150
|
dropdown.style.top = `${rect.bottom + 5}px`;
|
|
3010
3151
|
dropdown.style.left = `${rect.left}px`;
|
|
3011
3152
|
document.body.appendChild(dropdown);
|
|
3153
|
+
this.activeDropdown = dropdown;
|
|
3154
|
+
this.activeDropdownButton = button;
|
|
3155
|
+
button.setAttribute("aria-controls", dropdown.id);
|
|
3156
|
+
button.setAttribute("aria-expanded", "true");
|
|
3012
3157
|
this.handleDocumentClick = (e) => {
|
|
3013
3158
|
if (!dropdown.contains(e.target) && !button.contains(e.target)) {
|
|
3014
|
-
|
|
3015
|
-
button.classList.remove("dropdown-active");
|
|
3016
|
-
document.removeEventListener("click", this.handleDocumentClick);
|
|
3159
|
+
this.closeViewModeDropdown(button);
|
|
3017
3160
|
}
|
|
3018
3161
|
};
|
|
3019
3162
|
setTimeout(() => {
|
|
3020
3163
|
document.addEventListener("click", this.handleDocumentClick);
|
|
3021
3164
|
}, 0);
|
|
3165
|
+
if (focusPlacement) {
|
|
3166
|
+
this.focusViewModeMenuItem(dropdown, focusPlacement);
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
/**
|
|
3170
|
+
* Close the view mode dropdown
|
|
3171
|
+
*/
|
|
3172
|
+
closeViewModeDropdown(button = this.activeDropdownButton, returnFocus = false) {
|
|
3173
|
+
if (this.activeDropdown) {
|
|
3174
|
+
this.activeDropdown.remove();
|
|
3175
|
+
this.activeDropdown = null;
|
|
3176
|
+
}
|
|
3177
|
+
if (button) {
|
|
3178
|
+
button.classList.remove("dropdown-active");
|
|
3179
|
+
button.setAttribute("aria-expanded", "false");
|
|
3180
|
+
}
|
|
3181
|
+
if (this.handleDocumentClick) {
|
|
3182
|
+
document.removeEventListener("click", this.handleDocumentClick);
|
|
3183
|
+
this.handleDocumentClick = null;
|
|
3184
|
+
}
|
|
3185
|
+
this.activeDropdownButton = null;
|
|
3186
|
+
if (returnFocus && button) {
|
|
3187
|
+
button.focus();
|
|
3188
|
+
}
|
|
3022
3189
|
}
|
|
3023
3190
|
/**
|
|
3024
3191
|
* Create view mode dropdown menu (internal implementation)
|
|
@@ -3026,6 +3193,12 @@ var Toolbar = class {
|
|
|
3026
3193
|
createViewModeDropdown(button) {
|
|
3027
3194
|
const dropdown = document.createElement("div");
|
|
3028
3195
|
dropdown.className = "overtype-dropdown-menu";
|
|
3196
|
+
dropdown.id = this.getInstanceElementId("toolbar-view-mode-menu");
|
|
3197
|
+
dropdown.setAttribute("role", "menu");
|
|
3198
|
+
dropdown.setAttribute("aria-label", "View mode");
|
|
3199
|
+
dropdown.addEventListener("keydown", (e) => {
|
|
3200
|
+
this.onViewModeMenuKeydown(e, button);
|
|
3201
|
+
});
|
|
3029
3202
|
const items = [
|
|
3030
3203
|
{ id: "normal", label: "Normal Edit", icon: "\u2713" },
|
|
3031
3204
|
{ id: "plain", label: "Plain Textarea", icon: "\u2713" },
|
|
@@ -3036,12 +3209,15 @@ var Toolbar = class {
|
|
|
3036
3209
|
const menuItem = document.createElement("button");
|
|
3037
3210
|
menuItem.className = "overtype-dropdown-item";
|
|
3038
3211
|
menuItem.type = "button";
|
|
3212
|
+
menuItem.tabIndex = -1;
|
|
3213
|
+
menuItem.setAttribute("role", "menuitemradio");
|
|
3214
|
+
menuItem.setAttribute("aria-checked", String(item.id === currentMode));
|
|
3039
3215
|
menuItem.textContent = item.label;
|
|
3040
3216
|
if (item.id === currentMode) {
|
|
3041
3217
|
menuItem.classList.add("active");
|
|
3042
|
-
menuItem.setAttribute("aria-current", "true");
|
|
3043
3218
|
const checkmark = document.createElement("span");
|
|
3044
3219
|
checkmark.className = "overtype-dropdown-icon";
|
|
3220
|
+
checkmark.setAttribute("aria-hidden", "true");
|
|
3045
3221
|
checkmark.textContent = item.icon;
|
|
3046
3222
|
menuItem.prepend(checkmark);
|
|
3047
3223
|
}
|
|
@@ -3059,14 +3235,77 @@ var Toolbar = class {
|
|
|
3059
3235
|
this.editor.showNormalEditMode();
|
|
3060
3236
|
break;
|
|
3061
3237
|
}
|
|
3062
|
-
|
|
3063
|
-
button.classList.remove("dropdown-active");
|
|
3064
|
-
document.removeEventListener("click", this.handleDocumentClick);
|
|
3238
|
+
this.closeViewModeDropdown(button, true);
|
|
3065
3239
|
});
|
|
3066
3240
|
dropdown.appendChild(menuItem);
|
|
3067
3241
|
});
|
|
3068
3242
|
return dropdown;
|
|
3069
3243
|
}
|
|
3244
|
+
/**
|
|
3245
|
+
* Handle keyboard navigation inside the view mode menu
|
|
3246
|
+
*/
|
|
3247
|
+
onViewModeMenuKeydown(e, button) {
|
|
3248
|
+
const menuItems = this.getViewModeMenuItems();
|
|
3249
|
+
const currentIndex = menuItems.indexOf(e.target);
|
|
3250
|
+
if (currentIndex === -1) {
|
|
3251
|
+
return;
|
|
3252
|
+
}
|
|
3253
|
+
switch (e.key) {
|
|
3254
|
+
case "ArrowDown":
|
|
3255
|
+
e.preventDefault();
|
|
3256
|
+
this.focusViewModeMenuItem(this.activeDropdown, currentIndex + 1);
|
|
3257
|
+
break;
|
|
3258
|
+
case "ArrowUp":
|
|
3259
|
+
e.preventDefault();
|
|
3260
|
+
this.focusViewModeMenuItem(this.activeDropdown, currentIndex - 1);
|
|
3261
|
+
break;
|
|
3262
|
+
case "Home":
|
|
3263
|
+
e.preventDefault();
|
|
3264
|
+
this.focusViewModeMenuItem(this.activeDropdown, "first");
|
|
3265
|
+
break;
|
|
3266
|
+
case "End":
|
|
3267
|
+
e.preventDefault();
|
|
3268
|
+
this.focusViewModeMenuItem(this.activeDropdown, "last");
|
|
3269
|
+
break;
|
|
3270
|
+
case "Escape":
|
|
3271
|
+
e.preventDefault();
|
|
3272
|
+
this.closeViewModeDropdown(button, true);
|
|
3273
|
+
break;
|
|
3274
|
+
}
|
|
3275
|
+
}
|
|
3276
|
+
/**
|
|
3277
|
+
* Focus a view mode menu item by index or placement
|
|
3278
|
+
*/
|
|
3279
|
+
focusViewModeMenuItem(dropdown, placement) {
|
|
3280
|
+
const menuItems = this.getViewModeMenuItems(dropdown);
|
|
3281
|
+
if (menuItems.length === 0) {
|
|
3282
|
+
return;
|
|
3283
|
+
}
|
|
3284
|
+
let index = placement;
|
|
3285
|
+
if (placement === "first") {
|
|
3286
|
+
index = 0;
|
|
3287
|
+
} else if (placement === "last") {
|
|
3288
|
+
index = menuItems.length - 1;
|
|
3289
|
+
} else if (placement === "current") {
|
|
3290
|
+
index = menuItems.findIndex((item) => item.getAttribute("aria-checked") === "true");
|
|
3291
|
+
}
|
|
3292
|
+
if (index < 0) {
|
|
3293
|
+
index = menuItems.length - 1;
|
|
3294
|
+
}
|
|
3295
|
+
if (index >= menuItems.length) {
|
|
3296
|
+
index = 0;
|
|
3297
|
+
}
|
|
3298
|
+
menuItems[index].focus();
|
|
3299
|
+
}
|
|
3300
|
+
/**
|
|
3301
|
+
* Get the current view mode menu items
|
|
3302
|
+
*/
|
|
3303
|
+
getViewModeMenuItems(dropdown = this.activeDropdown) {
|
|
3304
|
+
if (!dropdown) {
|
|
3305
|
+
return [];
|
|
3306
|
+
}
|
|
3307
|
+
return Array.from(dropdown.querySelectorAll('[role="menuitemradio"]'));
|
|
3308
|
+
}
|
|
3070
3309
|
/**
|
|
3071
3310
|
* Update active states of toolbar buttons
|
|
3072
3311
|
*/
|
|
@@ -3080,39 +3319,14 @@ var Toolbar = class {
|
|
|
3080
3319
|
Object.entries(this.buttons).forEach(([name, button]) => {
|
|
3081
3320
|
if (name === "viewMode")
|
|
3082
3321
|
return;
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
isActive = activeFormats.includes("bold");
|
|
3087
|
-
break;
|
|
3088
|
-
case "italic":
|
|
3089
|
-
isActive = activeFormats.includes("italic");
|
|
3090
|
-
break;
|
|
3091
|
-
case "code":
|
|
3092
|
-
isActive = false;
|
|
3093
|
-
break;
|
|
3094
|
-
case "bulletList":
|
|
3095
|
-
isActive = activeFormats.includes("bullet-list");
|
|
3096
|
-
break;
|
|
3097
|
-
case "orderedList":
|
|
3098
|
-
isActive = activeFormats.includes("numbered-list");
|
|
3099
|
-
break;
|
|
3100
|
-
case "taskList":
|
|
3101
|
-
isActive = activeFormats.includes("task-list");
|
|
3102
|
-
break;
|
|
3103
|
-
case "quote":
|
|
3104
|
-
isActive = activeFormats.includes("quote");
|
|
3105
|
-
break;
|
|
3106
|
-
case "h1":
|
|
3107
|
-
isActive = activeFormats.includes("header");
|
|
3108
|
-
break;
|
|
3109
|
-
case "h2":
|
|
3110
|
-
isActive = activeFormats.includes("header-2");
|
|
3111
|
-
break;
|
|
3112
|
-
case "h3":
|
|
3113
|
-
isActive = activeFormats.includes("header-3");
|
|
3114
|
-
break;
|
|
3322
|
+
const buttonConfig = this.toolbarButtons.find((buttonConfig2) => buttonConfig2.name === name);
|
|
3323
|
+
if (!(buttonConfig == null ? void 0 : buttonConfig.isActive)) {
|
|
3324
|
+
return;
|
|
3115
3325
|
}
|
|
3326
|
+
const isActive = Boolean(buttonConfig.isActive({
|
|
3327
|
+
editor: this.editor,
|
|
3328
|
+
activeFormats
|
|
3329
|
+
}));
|
|
3116
3330
|
button.classList.toggle("active", isActive);
|
|
3117
3331
|
button.setAttribute("aria-pressed", isActive.toString());
|
|
3118
3332
|
});
|
|
@@ -3134,14 +3348,21 @@ var Toolbar = class {
|
|
|
3134
3348
|
*/
|
|
3135
3349
|
destroy() {
|
|
3136
3350
|
if (this.container) {
|
|
3137
|
-
if (this.
|
|
3351
|
+
if (this.activeDropdown) {
|
|
3352
|
+
this.closeViewModeDropdown();
|
|
3353
|
+
} else if (this.handleDocumentClick) {
|
|
3138
3354
|
document.removeEventListener("click", this.handleDocumentClick);
|
|
3355
|
+
this.handleDocumentClick = null;
|
|
3139
3356
|
}
|
|
3140
3357
|
Object.values(this.buttons).forEach((button) => {
|
|
3141
3358
|
if (button._clickHandler) {
|
|
3142
3359
|
button.removeEventListener("click", button._clickHandler);
|
|
3143
3360
|
delete button._clickHandler;
|
|
3144
3361
|
}
|
|
3362
|
+
if (button._keydownHandler) {
|
|
3363
|
+
button.removeEventListener("keydown", button._keydownHandler);
|
|
3364
|
+
delete button._keydownHandler;
|
|
3365
|
+
}
|
|
3145
3366
|
});
|
|
3146
3367
|
this.container.remove();
|
|
3147
3368
|
this.container = null;
|
|
@@ -4408,7 +4629,10 @@ var LinkTooltip = class {
|
|
|
4408
4629
|
e.preventDefault();
|
|
4409
4630
|
e.stopPropagation();
|
|
4410
4631
|
if (this.currentLink) {
|
|
4411
|
-
|
|
4632
|
+
const safeUrl = MarkdownParser.sanitizeUrl(this.currentLink.url);
|
|
4633
|
+
if (safeUrl !== "#") {
|
|
4634
|
+
window.open(safeUrl, "_blank");
|
|
4635
|
+
}
|
|
4412
4636
|
this.hide();
|
|
4413
4637
|
}
|
|
4414
4638
|
});
|
|
@@ -4436,7 +4660,7 @@ var LinkTooltip = class {
|
|
|
4436
4660
|
if (position >= start && position <= end) {
|
|
4437
4661
|
return {
|
|
4438
4662
|
text: match[1],
|
|
4439
|
-
url: match[2],
|
|
4663
|
+
url: this.transformUrl(match[2]),
|
|
4440
4664
|
index: linkIndex,
|
|
4441
4665
|
start,
|
|
4442
4666
|
end
|
|
@@ -4446,6 +4670,18 @@ var LinkTooltip = class {
|
|
|
4446
4670
|
}
|
|
4447
4671
|
return null;
|
|
4448
4672
|
}
|
|
4673
|
+
transformUrl(url) {
|
|
4674
|
+
const transform = this.editor.options.transformLinkUrl;
|
|
4675
|
+
if (typeof transform !== "function")
|
|
4676
|
+
return url;
|
|
4677
|
+
try {
|
|
4678
|
+
const result = transform(url);
|
|
4679
|
+
return typeof result === "string" ? result : url;
|
|
4680
|
+
} catch (e) {
|
|
4681
|
+
console.warn("transformLinkUrl threw:", e);
|
|
4682
|
+
return url;
|
|
4683
|
+
}
|
|
4684
|
+
}
|
|
4449
4685
|
async show(linkInfo) {
|
|
4450
4686
|
this.currentLink = linkInfo;
|
|
4451
4687
|
this.cancelHide();
|
|
@@ -4597,6 +4833,7 @@ var toolbarButtons = {
|
|
|
4597
4833
|
actionId: "toggleBold",
|
|
4598
4834
|
icon: boldIcon,
|
|
4599
4835
|
title: "Bold (Ctrl+B)",
|
|
4836
|
+
isActive: ({ activeFormats }) => activeFormats.includes("bold"),
|
|
4600
4837
|
action: ({ editor }) => {
|
|
4601
4838
|
toggleBold(editor.textarea);
|
|
4602
4839
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4607,6 +4844,7 @@ var toolbarButtons = {
|
|
|
4607
4844
|
actionId: "toggleItalic",
|
|
4608
4845
|
icon: italicIcon,
|
|
4609
4846
|
title: "Italic (Ctrl+I)",
|
|
4847
|
+
isActive: ({ activeFormats }) => activeFormats.includes("italic"),
|
|
4610
4848
|
action: ({ editor }) => {
|
|
4611
4849
|
toggleItalic(editor.textarea);
|
|
4612
4850
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4617,6 +4855,7 @@ var toolbarButtons = {
|
|
|
4617
4855
|
actionId: "toggleCode",
|
|
4618
4856
|
icon: codeIcon,
|
|
4619
4857
|
title: "Inline Code",
|
|
4858
|
+
isActive: () => false,
|
|
4620
4859
|
action: ({ editor }) => {
|
|
4621
4860
|
toggleCode(editor.textarea);
|
|
4622
4861
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4641,6 +4880,7 @@ var toolbarButtons = {
|
|
|
4641
4880
|
actionId: "toggleH1",
|
|
4642
4881
|
icon: h1Icon,
|
|
4643
4882
|
title: "Heading 1",
|
|
4883
|
+
isActive: ({ activeFormats }) => activeFormats.includes("header"),
|
|
4644
4884
|
action: ({ editor }) => {
|
|
4645
4885
|
toggleH1(editor.textarea);
|
|
4646
4886
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4651,6 +4891,7 @@ var toolbarButtons = {
|
|
|
4651
4891
|
actionId: "toggleH2",
|
|
4652
4892
|
icon: h2Icon,
|
|
4653
4893
|
title: "Heading 2",
|
|
4894
|
+
isActive: ({ activeFormats }) => activeFormats.includes("header-2"),
|
|
4654
4895
|
action: ({ editor }) => {
|
|
4655
4896
|
toggleH2(editor.textarea);
|
|
4656
4897
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4661,6 +4902,7 @@ var toolbarButtons = {
|
|
|
4661
4902
|
actionId: "toggleH3",
|
|
4662
4903
|
icon: h3Icon,
|
|
4663
4904
|
title: "Heading 3",
|
|
4905
|
+
isActive: ({ activeFormats }) => activeFormats.includes("header-3"),
|
|
4664
4906
|
action: ({ editor }) => {
|
|
4665
4907
|
toggleH3(editor.textarea);
|
|
4666
4908
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4671,6 +4913,7 @@ var toolbarButtons = {
|
|
|
4671
4913
|
actionId: "toggleBulletList",
|
|
4672
4914
|
icon: bulletListIcon,
|
|
4673
4915
|
title: "Bullet List",
|
|
4916
|
+
isActive: ({ activeFormats }) => activeFormats.includes("bullet-list"),
|
|
4674
4917
|
action: ({ editor }) => {
|
|
4675
4918
|
toggleBulletList(editor.textarea);
|
|
4676
4919
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4681,6 +4924,7 @@ var toolbarButtons = {
|
|
|
4681
4924
|
actionId: "toggleNumberedList",
|
|
4682
4925
|
icon: orderedListIcon,
|
|
4683
4926
|
title: "Numbered List",
|
|
4927
|
+
isActive: ({ activeFormats }) => activeFormats.includes("numbered-list"),
|
|
4684
4928
|
action: ({ editor }) => {
|
|
4685
4929
|
toggleNumberedList(editor.textarea);
|
|
4686
4930
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4691,6 +4935,7 @@ var toolbarButtons = {
|
|
|
4691
4935
|
actionId: "toggleTaskList",
|
|
4692
4936
|
icon: taskListIcon,
|
|
4693
4937
|
title: "Task List",
|
|
4938
|
+
isActive: ({ activeFormats }) => activeFormats.includes("task-list"),
|
|
4694
4939
|
action: ({ editor }) => {
|
|
4695
4940
|
if (toggleTaskList) {
|
|
4696
4941
|
toggleTaskList(editor.textarea);
|
|
@@ -4703,6 +4948,7 @@ var toolbarButtons = {
|
|
|
4703
4948
|
actionId: "toggleQuote",
|
|
4704
4949
|
icon: quoteIcon,
|
|
4705
4950
|
title: "Quote",
|
|
4951
|
+
isActive: ({ activeFormats }) => activeFormats.includes("quote"),
|
|
4706
4952
|
action: ({ editor }) => {
|
|
4707
4953
|
toggleQuote(editor.textarea);
|
|
4708
4954
|
editor.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
@@ -4764,6 +5010,17 @@ var defaultToolbarButtons = [
|
|
|
4764
5010
|
];
|
|
4765
5011
|
|
|
4766
5012
|
// src/overtype.js
|
|
5013
|
+
var _isSafariCache;
|
|
5014
|
+
function isSafariBrowser() {
|
|
5015
|
+
if (_isSafariCache !== void 0)
|
|
5016
|
+
return _isSafariCache;
|
|
5017
|
+
_isSafariCache = false;
|
|
5018
|
+
if (typeof navigator !== "undefined") {
|
|
5019
|
+
const ua = navigator.userAgent || "";
|
|
5020
|
+
_isSafariCache = /^((?!chrome|android|crios|fxios|edg|opr).)*safari/i.test(ua) || /iPad|iPhone|iPod/.test(ua) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1 && /Safari/.test(ua);
|
|
5021
|
+
}
|
|
5022
|
+
return _isSafariCache;
|
|
5023
|
+
}
|
|
4767
5024
|
function buildActionsMap(buttons) {
|
|
4768
5025
|
const map = {};
|
|
4769
5026
|
(buttons || []).forEach((btn) => {
|
|
@@ -4838,6 +5095,8 @@ var _OverType = class _OverType {
|
|
|
4838
5095
|
this.options = this._mergeOptions(options);
|
|
4839
5096
|
this.instanceId = ++_OverType.instanceCount;
|
|
4840
5097
|
this.initialized = false;
|
|
5098
|
+
this._isSafari = isSafariBrowser();
|
|
5099
|
+
this._safariReflowRaf = null;
|
|
4841
5100
|
_OverType.injectStyles();
|
|
4842
5101
|
_OverType.initGlobalListeners();
|
|
4843
5102
|
const container = element.querySelector(".overtype-container");
|
|
@@ -4912,8 +5171,10 @@ var _OverType = class _OverType {
|
|
|
4912
5171
|
// Enable smart list continuation
|
|
4913
5172
|
codeHighlighter: null,
|
|
4914
5173
|
// Per-instance code highlighter
|
|
4915
|
-
spellcheck: false
|
|
5174
|
+
spellcheck: false,
|
|
4916
5175
|
// Browser spellcheck (disabled by default)
|
|
5176
|
+
transformLinkUrl: null
|
|
5177
|
+
// Transform URLs shown/opened in the link tooltip
|
|
4917
5178
|
};
|
|
4918
5179
|
const { theme, colors, ...cleanOptions } = options;
|
|
4919
5180
|
return {
|
|
@@ -4966,6 +5227,8 @@ var _OverType = class _OverType {
|
|
|
4966
5227
|
this.wrapper._instance = this;
|
|
4967
5228
|
this._applyInstanceCSSVars();
|
|
4968
5229
|
this._configureTextarea();
|
|
5230
|
+
this._ensureTextareaId();
|
|
5231
|
+
this._syncPreviewInteractivity();
|
|
4969
5232
|
this._applyOptions();
|
|
4970
5233
|
}
|
|
4971
5234
|
/**
|
|
@@ -5029,6 +5292,7 @@ var _OverType = class _OverType {
|
|
|
5029
5292
|
}
|
|
5030
5293
|
});
|
|
5031
5294
|
}
|
|
5295
|
+
this._ensureTextareaId();
|
|
5032
5296
|
this.preview = document.createElement("div");
|
|
5033
5297
|
this.preview.className = "overtype-preview";
|
|
5034
5298
|
this.preview.setAttribute("aria-hidden", "true");
|
|
@@ -5052,6 +5316,7 @@ var _OverType = class _OverType {
|
|
|
5052
5316
|
} else {
|
|
5053
5317
|
this.container.classList.remove("overtype-auto-resize");
|
|
5054
5318
|
}
|
|
5319
|
+
this._syncPreviewInteractivity();
|
|
5055
5320
|
}
|
|
5056
5321
|
/**
|
|
5057
5322
|
* Configure textarea attributes
|
|
@@ -5066,6 +5331,31 @@ var _OverType = class _OverType {
|
|
|
5066
5331
|
this.textarea.setAttribute("data-gramm_editor", "false");
|
|
5067
5332
|
this.textarea.setAttribute("data-enable-grammarly", "false");
|
|
5068
5333
|
}
|
|
5334
|
+
/**
|
|
5335
|
+
* Ensure the textarea can be referenced by aria-controls
|
|
5336
|
+
* @private
|
|
5337
|
+
*/
|
|
5338
|
+
_ensureTextareaId() {
|
|
5339
|
+
if (!this.textarea.id) {
|
|
5340
|
+
this.textarea.id = `overtype-${this.instanceId}-input`;
|
|
5341
|
+
}
|
|
5342
|
+
}
|
|
5343
|
+
/**
|
|
5344
|
+
* Keep rendered preview content out of keyboard navigation until Preview mode.
|
|
5345
|
+
* @private
|
|
5346
|
+
*/
|
|
5347
|
+
_syncPreviewInteractivity() {
|
|
5348
|
+
if (!this.preview || !this.container)
|
|
5349
|
+
return;
|
|
5350
|
+
const isPreviewMode = this.container.dataset.mode === "preview";
|
|
5351
|
+
this.preview.inert = !isPreviewMode;
|
|
5352
|
+
this.preview.toggleAttribute("inert", !isPreviewMode);
|
|
5353
|
+
if (isPreviewMode) {
|
|
5354
|
+
this.preview.removeAttribute("aria-hidden");
|
|
5355
|
+
return;
|
|
5356
|
+
}
|
|
5357
|
+
this.preview.setAttribute("aria-hidden", "true");
|
|
5358
|
+
}
|
|
5069
5359
|
/**
|
|
5070
5360
|
* Create and setup toolbar
|
|
5071
5361
|
* @private
|
|
@@ -5404,6 +5694,29 @@ var _OverType = class _OverType {
|
|
|
5404
5694
|
handleInput(event) {
|
|
5405
5695
|
this.updatePreview();
|
|
5406
5696
|
this._notifyChange();
|
|
5697
|
+
this._scheduleSafariReflow();
|
|
5698
|
+
}
|
|
5699
|
+
/**
|
|
5700
|
+
* Force Safari to re-shape stale textarea text after an edit.
|
|
5701
|
+
* Safari can leave a textarea's glyph layout cached after incremental edits,
|
|
5702
|
+
* desyncing the caret/wrap from the styled preview overlay. Toggling
|
|
5703
|
+
* letter-spacing (with !important to beat the stylesheet rule) and reading
|
|
5704
|
+
* offsetHeight forces a synchronous re-shape. Safari-only, coalesced to one
|
|
5705
|
+
* run per animation frame.
|
|
5706
|
+
* @private
|
|
5707
|
+
*/
|
|
5708
|
+
_scheduleSafariReflow() {
|
|
5709
|
+
if (!this._isSafari || this._safariReflowRaf)
|
|
5710
|
+
return;
|
|
5711
|
+
this._safariReflowRaf = requestAnimationFrame(() => {
|
|
5712
|
+
this._safariReflowRaf = null;
|
|
5713
|
+
const ta = this.textarea;
|
|
5714
|
+
if (!ta)
|
|
5715
|
+
return;
|
|
5716
|
+
ta.style.setProperty("letter-spacing", "-0.001px", "important");
|
|
5717
|
+
void ta.offsetHeight;
|
|
5718
|
+
ta.style.removeProperty("letter-spacing");
|
|
5719
|
+
});
|
|
5407
5720
|
}
|
|
5408
5721
|
/**
|
|
5409
5722
|
* Handle focus events
|
|
@@ -5431,49 +5744,11 @@ var _OverType = class _OverType {
|
|
|
5431
5744
|
if (event.key === "Tab") {
|
|
5432
5745
|
const start = this.textarea.selectionStart;
|
|
5433
5746
|
const end = this.textarea.selectionEnd;
|
|
5434
|
-
|
|
5435
|
-
|
|
5747
|
+
if (start !== end && this._canEditTextarea()) {
|
|
5748
|
+
event.preventDefault();
|
|
5749
|
+
event.shiftKey ? this.outdentSelection() : this.indentSelection();
|
|
5436
5750
|
return;
|
|
5437
5751
|
}
|
|
5438
|
-
event.preventDefault();
|
|
5439
|
-
if (start !== end && event.shiftKey) {
|
|
5440
|
-
const before = value.substring(0, start);
|
|
5441
|
-
const selection = value.substring(start, end);
|
|
5442
|
-
const after = value.substring(end);
|
|
5443
|
-
const lines = selection.split("\n");
|
|
5444
|
-
const outdented = lines.map((line) => line.replace(/^ /, "")).join("\n");
|
|
5445
|
-
if (document.execCommand) {
|
|
5446
|
-
this.textarea.setSelectionRange(start, end);
|
|
5447
|
-
document.execCommand("insertText", false, outdented);
|
|
5448
|
-
} else {
|
|
5449
|
-
this.textarea.value = before + outdented + after;
|
|
5450
|
-
this.textarea.selectionStart = start;
|
|
5451
|
-
this.textarea.selectionEnd = start + outdented.length;
|
|
5452
|
-
}
|
|
5453
|
-
} else if (start !== end) {
|
|
5454
|
-
const before = value.substring(0, start);
|
|
5455
|
-
const selection = value.substring(start, end);
|
|
5456
|
-
const after = value.substring(end);
|
|
5457
|
-
const lines = selection.split("\n");
|
|
5458
|
-
const indented = lines.map((line) => " " + line).join("\n");
|
|
5459
|
-
if (document.execCommand) {
|
|
5460
|
-
this.textarea.setSelectionRange(start, end);
|
|
5461
|
-
document.execCommand("insertText", false, indented);
|
|
5462
|
-
} else {
|
|
5463
|
-
this.textarea.value = before + indented + after;
|
|
5464
|
-
this.textarea.selectionStart = start;
|
|
5465
|
-
this.textarea.selectionEnd = start + indented.length;
|
|
5466
|
-
}
|
|
5467
|
-
} else {
|
|
5468
|
-
if (document.execCommand) {
|
|
5469
|
-
document.execCommand("insertText", false, " ");
|
|
5470
|
-
} else {
|
|
5471
|
-
this.textarea.value = value.substring(0, start) + " " + value.substring(end);
|
|
5472
|
-
this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;
|
|
5473
|
-
}
|
|
5474
|
-
}
|
|
5475
|
-
this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
5476
|
-
return;
|
|
5477
5752
|
}
|
|
5478
5753
|
if (event.key === "Enter" && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {
|
|
5479
5754
|
if (this.handleSmartListContinuation()) {
|
|
@@ -5610,6 +5885,7 @@ var _OverType = class _OverType {
|
|
|
5610
5885
|
}
|
|
5611
5886
|
if (didChange) {
|
|
5612
5887
|
this._notifyChange();
|
|
5888
|
+
this._scheduleSafariReflow();
|
|
5613
5889
|
}
|
|
5614
5890
|
}
|
|
5615
5891
|
/**
|
|
@@ -5670,6 +5946,63 @@ var _OverType = class _OverType {
|
|
|
5670
5946
|
getPreviewHTML() {
|
|
5671
5947
|
return this.preview.innerHTML;
|
|
5672
5948
|
}
|
|
5949
|
+
/**
|
|
5950
|
+
* Indent the current line or selected lines by two spaces.
|
|
5951
|
+
*/
|
|
5952
|
+
indentSelection() {
|
|
5953
|
+
this._replaceSelectedLines((line) => ` ${line}`);
|
|
5954
|
+
}
|
|
5955
|
+
/**
|
|
5956
|
+
* Outdent the current line or selected lines by up to two spaces or one tab.
|
|
5957
|
+
*/
|
|
5958
|
+
outdentSelection() {
|
|
5959
|
+
this._replaceSelectedLines((line) => line.replace(/^( {1,2}|\t)/, ""));
|
|
5960
|
+
}
|
|
5961
|
+
/**
|
|
5962
|
+
* Replace full lines touched by the current selection.
|
|
5963
|
+
* @private
|
|
5964
|
+
*/
|
|
5965
|
+
_replaceSelectedLines(transformLine) {
|
|
5966
|
+
if (!this._canEditTextarea())
|
|
5967
|
+
return false;
|
|
5968
|
+
const textarea = this.textarea;
|
|
5969
|
+
const { selectionStart, selectionEnd, value } = textarea;
|
|
5970
|
+
const lineStart = value.lastIndexOf("\n", selectionStart - 1) + 1;
|
|
5971
|
+
const effectiveEnd = this._effectiveSelectionEnd(value, selectionStart, selectionEnd);
|
|
5972
|
+
const lineEndOffset = value.indexOf("\n", effectiveEnd);
|
|
5973
|
+
const lineEnd = lineEndOffset === -1 ? value.length : lineEndOffset;
|
|
5974
|
+
const selectedLines = value.slice(lineStart, lineEnd);
|
|
5975
|
+
const replacement = selectedLines.split("\n").map(transformLine).join("\n");
|
|
5976
|
+
if (replacement === selectedLines)
|
|
5977
|
+
return false;
|
|
5978
|
+
textarea.setSelectionRange(lineStart, lineEnd);
|
|
5979
|
+
let inserted = false;
|
|
5980
|
+
try {
|
|
5981
|
+
inserted = document.execCommand("insertText", false, replacement);
|
|
5982
|
+
} catch (_) {
|
|
5983
|
+
}
|
|
5984
|
+
if (!inserted) {
|
|
5985
|
+
textarea.setRangeText(replacement, lineStart, lineEnd, "preserve");
|
|
5986
|
+
}
|
|
5987
|
+
textarea.setSelectionRange(lineStart, lineStart + replacement.length);
|
|
5988
|
+
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
5989
|
+
return true;
|
|
5990
|
+
}
|
|
5991
|
+
/**
|
|
5992
|
+
* @private
|
|
5993
|
+
*/
|
|
5994
|
+
_effectiveSelectionEnd(value, selectionStart, selectionEnd) {
|
|
5995
|
+
if (selectionEnd > selectionStart && value[selectionEnd - 1] === "\n") {
|
|
5996
|
+
return selectionEnd - 1;
|
|
5997
|
+
}
|
|
5998
|
+
return selectionEnd;
|
|
5999
|
+
}
|
|
6000
|
+
/**
|
|
6001
|
+
* @private
|
|
6002
|
+
*/
|
|
6003
|
+
_canEditTextarea() {
|
|
6004
|
+
return this.textarea && !this.textarea.disabled && !this.textarea.readOnly;
|
|
6005
|
+
}
|
|
5673
6006
|
/**
|
|
5674
6007
|
* Get clean HTML without any OverType-specific markup
|
|
5675
6008
|
* Useful for exporting to other formats or storage
|
|
@@ -5893,6 +6226,7 @@ var _OverType = class _OverType {
|
|
|
5893
6226
|
*/
|
|
5894
6227
|
showNormalEditMode() {
|
|
5895
6228
|
this.container.dataset.mode = "normal";
|
|
6229
|
+
this._syncPreviewInteractivity();
|
|
5896
6230
|
this.updatePreview();
|
|
5897
6231
|
this._updateAutoHeight();
|
|
5898
6232
|
requestAnimationFrame(() => {
|
|
@@ -5907,6 +6241,7 @@ var _OverType = class _OverType {
|
|
|
5907
6241
|
*/
|
|
5908
6242
|
showPlainTextarea() {
|
|
5909
6243
|
this.container.dataset.mode = "plain";
|
|
6244
|
+
this._syncPreviewInteractivity();
|
|
5910
6245
|
this._updateAutoHeight();
|
|
5911
6246
|
if (this.toolbar) {
|
|
5912
6247
|
const toggleBtn = this.container.querySelector('[data-action="toggle-plain"]');
|
|
@@ -5923,6 +6258,7 @@ var _OverType = class _OverType {
|
|
|
5923
6258
|
*/
|
|
5924
6259
|
showPreviewMode() {
|
|
5925
6260
|
this.container.dataset.mode = "preview";
|
|
6261
|
+
this._syncPreviewInteractivity();
|
|
5926
6262
|
this.updatePreview();
|
|
5927
6263
|
this._updateAutoHeight();
|
|
5928
6264
|
return this;
|
|
@@ -5941,6 +6277,10 @@ var _OverType = class _OverType {
|
|
|
5941
6277
|
if (this.shortcuts) {
|
|
5942
6278
|
this.shortcuts.destroy();
|
|
5943
6279
|
}
|
|
6280
|
+
if (this._safariReflowRaf) {
|
|
6281
|
+
cancelAnimationFrame(this._safariReflowRaf);
|
|
6282
|
+
this._safariReflowRaf = null;
|
|
6283
|
+
}
|
|
5944
6284
|
if (this.wrapper) {
|
|
5945
6285
|
const content = this.getValue();
|
|
5946
6286
|
this.wrapper.remove();
|
|
@@ -5972,11 +6312,16 @@ var _OverType = class _OverType {
|
|
|
5972
6312
|
return elements.map((el) => {
|
|
5973
6313
|
const options = { ...defaults };
|
|
5974
6314
|
for (const attr of el.attributes) {
|
|
5975
|
-
if (attr.name.startsWith("data-ot-"))
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
6315
|
+
if (!attr.name.startsWith("data-ot-"))
|
|
6316
|
+
continue;
|
|
6317
|
+
const kebab = attr.name.slice(8);
|
|
6318
|
+
if (kebab.startsWith("textarea-") && kebab !== "textarea-props") {
|
|
6319
|
+
const propKey = kebab.slice(9).replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
6320
|
+
options.textareaProps = { ...options.textareaProps || {}, [propKey]: _OverType._parseDataValue(attr.value) };
|
|
6321
|
+
continue;
|
|
5979
6322
|
}
|
|
6323
|
+
const key = kebab.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
6324
|
+
options[key] = _OverType._parseDataValue(attr.value);
|
|
5980
6325
|
}
|
|
5981
6326
|
return new _OverType(el, options)[0];
|
|
5982
6327
|
});
|
|
@@ -6021,6 +6366,14 @@ var _OverType = class _OverType {
|
|
|
6021
6366
|
return null;
|
|
6022
6367
|
if (value !== "" && !isNaN(Number(value)))
|
|
6023
6368
|
return Number(value);
|
|
6369
|
+
const trimmed = value.trim();
|
|
6370
|
+
if (trimmed[0] === "{" || trimmed[0] === "[") {
|
|
6371
|
+
try {
|
|
6372
|
+
return JSON.parse(trimmed);
|
|
6373
|
+
} catch (e) {
|
|
6374
|
+
return value;
|
|
6375
|
+
}
|
|
6376
|
+
}
|
|
6024
6377
|
return value;
|
|
6025
6378
|
}
|
|
6026
6379
|
/**
|
|
@@ -6199,8 +6552,13 @@ var _OverType = class _OverType {
|
|
|
6199
6552
|
* Initialize global event listeners
|
|
6200
6553
|
*/
|
|
6201
6554
|
static initGlobalListeners() {
|
|
6202
|
-
|
|
6555
|
+
const globalScope = typeof window !== "undefined" ? window : globalThis;
|
|
6556
|
+
const globalListenersKey = "__overtypeGlobalListenersInitialized";
|
|
6557
|
+
if (_OverType.globalListenersInitialized || globalScope[globalListenersKey]) {
|
|
6558
|
+
_OverType.globalListenersInitialized = true;
|
|
6203
6559
|
return;
|
|
6560
|
+
}
|
|
6561
|
+
globalScope[globalListenersKey] = true;
|
|
6204
6562
|
document.addEventListener("input", (e) => {
|
|
6205
6563
|
if (e.target && e.target.classList && e.target.classList.contains("overtype-input")) {
|
|
6206
6564
|
const wrapper = e.target.closest(".overtype-wrapper");
|