overtype 2.3.7 → 2.3.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overtype",
3
- "version": "2.3.7",
3
+ "version": "2.3.8",
4
4
  "description": "A lightweight markdown editor library with perfect WYSIWYG alignment using an invisible textarea overlay",
5
5
  "main": "dist/overtype.cjs",
6
6
  "module": "dist/overtype.esm.js",
package/src/overtype.d.ts CHANGED
@@ -140,6 +140,8 @@ export interface Options {
140
140
  // Callbacks
141
141
  onChange?: (value: string, instance: OverTypeInstance) => void;
142
142
  onKeydown?: (event: KeyboardEvent, instance: OverTypeInstance) => void;
143
+ onFocus?: (event: FocusEvent, instance: OverTypeInstance) => void;
144
+ onBlur?: (event: FocusEvent, instance: OverTypeInstance) => void;
143
145
  }
144
146
 
145
147
  // Interface for constructor that returns array
@@ -158,7 +160,8 @@ export interface OverTypeConstructor {
158
160
  MarkdownParser: any;
159
161
  ShortcutsManager: any;
160
162
  init(target: string | Element | NodeList | Element[], options?: Options): OverTypeInstance[];
161
- getInstance(element: Element): OverTypeInstance | null;
163
+ initFromData(target: string | Element | NodeList | Element[], defaults?: Options): OverTypeInstance[];
164
+ getInstance(target: string | Element | NodeList | Element[]): OverTypeInstance | null;
162
165
  destroyAll(): void;
163
166
  injectStyles(force?: boolean): void;
164
167
  setTheme(theme: string | Theme, customColors?: Partial<Theme['colors']>): void;
@@ -225,6 +228,26 @@ export type OverType = OverTypeInstance;
225
228
  // Module exports - default export is the constructor
226
229
  export default OverType;
227
230
 
231
+ /** Re-exported markdown-actions. Useful for custom toolbar implementations */
232
+ export const markdownActions: {
233
+ toggleBold(textarea: HTMLTextAreaElement): void;
234
+ toggleItalic(textarea: HTMLTextAreaElement): void;
235
+ toggleCode(textarea: HTMLTextAreaElement): void;
236
+ insertLink(textarea: HTMLTextAreaElement, options?: { url?: string; text?: string }): void;
237
+ toggleBulletList(textarea: HTMLTextAreaElement): void;
238
+ toggleNumberedList(textarea: HTMLTextAreaElement): void;
239
+ toggleQuote(textarea: HTMLTextAreaElement): void;
240
+ toggleTaskList(textarea: HTMLTextAreaElement): void;
241
+ insertHeader(textarea: HTMLTextAreaElement, level?: number, toggle?: boolean): void;
242
+ toggleH1(textarea: HTMLTextAreaElement): void;
243
+ toggleH2(textarea: HTMLTextAreaElement): void;
244
+ toggleH3(textarea: HTMLTextAreaElement): void;
245
+ getActiveFormats(textarea: HTMLTextAreaElement): string[];
246
+ hasFormat(textarea: HTMLTextAreaElement, format: string): boolean;
247
+ expandSelection(textarea: HTMLTextAreaElement, options?: object): void;
248
+ applyCustomFormat(textarea: HTMLTextAreaElement, format: object): void;
249
+ };
250
+
228
251
  /**
229
252
  * Pre-defined toolbar buttons
230
253
  */
package/src/overtype.js CHANGED
@@ -93,23 +93,9 @@ class OverType {
93
93
  * @returns {Array} Array of OverType instances
94
94
  */
95
95
  constructor(target, options = {}) {
96
- // Convert target to array of elements
97
- let elements;
98
-
99
- if (typeof target === 'string') {
100
- elements = document.querySelectorAll(target);
101
- if (elements.length === 0) {
102
- throw new Error(`No elements found for selector: ${target}`);
103
- }
104
- elements = Array.from(elements);
105
- } else if (target instanceof Element) {
106
- elements = [target];
107
- } else if (target instanceof NodeList) {
108
- elements = Array.from(target);
109
- } else if (Array.isArray(target)) {
110
- elements = target;
111
- } else {
112
- throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');
96
+ const elements = OverType._resolveTargets(target);
97
+ if (typeof target === 'string' && elements.length === 0) {
98
+ throw new Error(`No elements found for selector: ${target}`);
113
99
  }
114
100
 
115
101
  // Initialize all elements and return array
@@ -228,6 +214,8 @@ class OverType {
228
214
  onChange: null,
229
215
  onKeydown: null,
230
216
  onRender: null,
217
+ onFocus: null,
218
+ onBlur: null,
231
219
 
232
220
  // Features
233
221
  showActiveLineRaw: false,
@@ -813,6 +801,26 @@ class OverType {
813
801
  this._notifyChange();
814
802
  }
815
803
 
804
+ /**
805
+ * Handle focus events
806
+ * @private
807
+ */
808
+ handleFocus(event) {
809
+ if (this.options.onFocus) {
810
+ this.options.onFocus(event, this);
811
+ }
812
+ }
813
+
814
+ /**
815
+ * Handle blur events
816
+ * @private
817
+ */
818
+ handleBlur(event) {
819
+ if (this.options.onBlur) {
820
+ this.options.onBlur(event, this);
821
+ }
822
+ }
823
+
816
824
  /**
817
825
  * Handle keydown events
818
826
  * @private
@@ -1532,9 +1540,9 @@ class OverType {
1532
1540
  * // HTML: <div class="editor" data-ot-toolbar="true" data-ot-theme="cave"></div>
1533
1541
  * OverType.initFromData('.editor', { fontSize: '14px' });
1534
1542
  */
1535
- static initFromData(selector, defaults = {}) {
1536
- const elements = document.querySelectorAll(selector);
1537
- return Array.from(elements).map(el => {
1543
+ static initFromData(target, defaults = {}) {
1544
+ const elements = OverType._resolveTargets(target);
1545
+ return elements.map(el => {
1538
1546
  const options = { ...defaults };
1539
1547
 
1540
1548
  // Parse data-ot-* attributes (kebab-case to camelCase)
@@ -1550,6 +1558,35 @@ class OverType {
1550
1558
  });
1551
1559
  }
1552
1560
 
1561
+ /**
1562
+ * Normalize various target shapes to an array of Elements
1563
+ * @private
1564
+ * @param {string|Element|NodeList|Element[]} target
1565
+ * @returns {Element[]}
1566
+ */
1567
+ static _resolveTargets(target) {
1568
+ if (target == null) {
1569
+ throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');
1570
+ }
1571
+ if (typeof target === 'string') {
1572
+ return Array.from(document.querySelectorAll(target));
1573
+ }
1574
+ if (target instanceof Element) {
1575
+ return [target];
1576
+ }
1577
+ if (target instanceof NodeList) {
1578
+ return Array.from(target);
1579
+ }
1580
+ if (Array.isArray(target)) {
1581
+ return target;
1582
+ }
1583
+ // Array-like (e.g. jQuery objects expose numeric indices and length)
1584
+ if (typeof target.length === 'number') {
1585
+ return Array.from(target);
1586
+ }
1587
+ throw new Error('Invalid target: must be selector string, Element, NodeList, or Array');
1588
+ }
1589
+
1553
1590
  /**
1554
1591
  * Parse a data attribute value to the appropriate type
1555
1592
  * @private
@@ -1563,11 +1600,21 @@ class OverType {
1563
1600
  }
1564
1601
 
1565
1602
  /**
1566
- * Get instance from element
1567
- * @param {Element} element - DOM element
1568
- * @returns {OverType|null} OverType instance or null
1603
+ * Get instance from a target. Accepts the same shapes as the constructor;
1604
+ * for multi-element targets, returns the instance for the first matching
1605
+ * element, or null if none.
1606
+ * @param {string|Element|NodeList|Element[]} target
1607
+ * @returns {OverType|null}
1569
1608
  */
1570
- static getInstance(element) {
1609
+ static getInstance(target) {
1610
+ let element;
1611
+ if (target instanceof Element) {
1612
+ element = target;
1613
+ } else {
1614
+ const elements = OverType._resolveTargets(target);
1615
+ element = elements[0];
1616
+ }
1617
+ if (!element) return null;
1571
1618
  return element.overTypeInstance || OverType.instances.get(element) || null;
1572
1619
  }
1573
1620
 
@@ -1777,6 +1824,24 @@ class OverType {
1777
1824
  }
1778
1825
  });
1779
1826
 
1827
+ // Focus event (capture: true because focus does not bubble)
1828
+ document.addEventListener('focus', (e) => {
1829
+ if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {
1830
+ const wrapper = e.target.closest('.overtype-wrapper');
1831
+ const instance = wrapper?._instance;
1832
+ if (instance) instance.handleFocus(e);
1833
+ }
1834
+ }, true);
1835
+
1836
+ // Blur event (capture: true because blur does not bubble)
1837
+ document.addEventListener('blur', (e) => {
1838
+ if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {
1839
+ const wrapper = e.target.closest('.overtype-wrapper');
1840
+ const instance = wrapper?._instance;
1841
+ if (instance) instance.handleBlur(e);
1842
+ }
1843
+ }, true);
1844
+
1780
1845
  // Scroll event
1781
1846
  document.addEventListener('scroll', (e) => {
1782
1847
  if (e.target && e.target.classList && e.target.classList.contains('overtype-input')) {
@@ -1827,3 +1892,7 @@ export { OverType };
1827
1892
 
1828
1893
  // Export toolbar buttons for custom toolbar configurations
1829
1894
  export { toolbarButtons, defaultToolbarButtons } from './toolbar-buttons.js';
1895
+
1896
+ // Re-export markdown-actions. Useful for custom toolbar implementations
1897
+ export * as markdownActions from 'markdown-actions';
1898
+