drab 6.1.2 → 6.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.
@@ -54,13 +54,17 @@ export declare class Base extends HTMLElement {
54
54
  */
55
55
  swapContent(revert?: number | false): void;
56
56
  /**
57
- * Wrapper around `document.body.addEventListener` that ensures when the
58
- * element is removed from the DOM, these event listeners are cleaned up.
59
- * @param type
60
- * @param listener
61
- * @param options
57
+ * Wrapper around `addEventListener` that ensures when the element is
58
+ * removed from the DOM, these event listeners are cleaned up.
59
+ *
60
+ * @param type Event listener type - ex: `"keydown"`
61
+ * @param listener Listener to add to the target.
62
+ * @param target Event target to add the listener to - defaults to `document.body`.
63
+ * @param options Other options sans `signal`.
62
64
  */
63
- safeListener<K extends keyof DocumentEventMap, T extends HTMLElement | Window | Document = HTMLElement>(type: K, listener: (this: T, ev: DocumentEventMap[K]) => any, element?: T, options?: AddEventListenerOptions): void;
65
+ safeListener<T extends keyof HTMLElementEventMap>(type: T, listener: (this: HTMLElement, event: HTMLElementEventMap[T]) => any, element?: HTMLElement, options?: AddEventListenerOptions): void;
66
+ safeListener<T extends keyof DocumentEventMap>(type: T, listener: (this: Document, event: DocumentEventMap[T]) => any, document: Document, options?: AddEventListenerOptions): void;
67
+ safeListener<T extends keyof WindowEventMap>(type: T, listener: (this: Window, event: WindowEventMap[T]) => any, window: Window, options?: AddEventListenerOptions): void;
64
68
  /**
65
69
  * @param listener Listener to attach to all of the `trigger` elements.
66
70
  */
@@ -73,7 +73,7 @@ export class Base extends HTMLElement {
73
73
  const swap = this.querySelector(this.getAttribute("swap") ?? "[data-swap]");
74
74
  if (swap) {
75
75
  /** A copy of the content currently in `this.getContent()`. */
76
- const currentContent = Array.from(this.getContent().childNodes);
76
+ const currentContent = this.getContent().childNodes;
77
77
  /**
78
78
  * The contents of the swap element, set based on whether the
79
79
  * swap is a `template` or not.
@@ -99,17 +99,9 @@ export class Base extends HTMLElement {
99
99
  }
100
100
  }
101
101
  }
102
- /**
103
- * Wrapper around `document.body.addEventListener` that ensures when the
104
- * element is removed from the DOM, these event listeners are cleaned up.
105
- * @param type
106
- * @param listener
107
- * @param options
108
- */
109
- safeListener(type, listener, element = document.body, options = {}) {
102
+ safeListener(type, listener, target = document.body, options = {}) {
110
103
  options.signal = this.#listenerController.signal;
111
- //@ts-ignore - inferred listener type not working...?
112
- element.addEventListener(type, listener, options);
104
+ target.addEventListener(type, listener, options);
113
105
  }
114
106
  /**
115
107
  * @param listener Listener to attach to all of the `trigger` elements.
@@ -42,15 +42,13 @@ export type ContentElement = {
42
42
  * - Automatically increments/decrements ordered lists.
43
43
  * - Adds the starting character to the next line for `block` content.
44
44
  * - On double click, highlight is corrected to only highlight the current word without space around it.
45
- * - `tab` key will indent and not change focus if the selection is within a code block (three backticks).
45
+ * - `tab` key will indent or dedent (+shift) instead of focus change if the selection is within a code block (three backticks).
46
46
  * - When text is highlighted and a `wrap` character `keyPair` is typed, the highlighted text will be wrapped with the character instead of removing it. For example, if a word is highlighted and the `"` character is typed, the work will be surrounded by `"`s.
47
47
  */
48
48
  export declare class Editor extends Base {
49
49
  #private;
50
50
  /** Characters that will be automatically closed when typed. */
51
- keyPairs: {
52
- [key: string]: string;
53
- };
51
+ keyPairs: Record<string, string>;
54
52
  constructor();
55
53
  /** The `content`, expects an `HTMLTextAreaElement`. */
56
54
  get textArea(): HTMLTextAreaElement;
@@ -25,7 +25,7 @@ import { Base } from "../base/index.js";
25
25
  * - Automatically increments/decrements ordered lists.
26
26
  * - Adds the starting character to the next line for `block` content.
27
27
  * - On double click, highlight is corrected to only highlight the current word without space around it.
28
- * - `tab` key will indent and not change focus if the selection is within a code block (three backticks).
28
+ * - `tab` key will indent or dedent (+shift) instead of focus change if the selection is within a code block (three backticks).
29
29
  * - When text is highlighted and a `wrap` character `keyPair` is typed, the highlighted text will be wrapped with the character instead of removing it. For example, if a word is highlighted and the `"` character is typed, the work will be surrounded by `"`s.
30
30
  */
31
31
  export class Editor extends Base {
@@ -33,6 +33,7 @@ export class Editor extends Base {
33
33
  #openChars = [];
34
34
  /** Keys that will reset the type over for keyPairs */
35
35
  #resetKeys = new Set(["ArrowUp", "ArrowDown", "Delete"]);
36
+ #inputEvent = new Event("input", { bubbles: true, cancelable: true });
36
37
  /** Characters that will be automatically closed when typed. */
37
38
  keyPairs = {
38
39
  "(": ")",
@@ -60,6 +61,7 @@ export class Editor extends Base {
60
61
  }
61
62
  set text(value) {
62
63
  this.textArea.value = value;
64
+ this.textArea.dispatchEvent(this.#inputEvent);
63
65
  }
64
66
  /** Array of `ContentElement`s derived from each `trigger`'s data attributes. */
65
67
  get #contentElements() {
@@ -217,7 +219,7 @@ export class Editor extends Base {
217
219
  else {
218
220
  newNum = num + 1;
219
221
  }
220
- lines[lineNumber] = String(newNum) + line.slice(String(num).length);
222
+ lines[lineNumber] = newNum + line.slice(String(num).length);
221
223
  }
222
224
  else {
223
225
  break;
@@ -263,16 +265,26 @@ export class Editor extends Base {
263
265
  for (const [i, block] of blocks.entries()) {
264
266
  totalChars += block.length + 3;
265
267
  if (totalChars > this.#selStart) {
266
- // found
267
268
  if (i % 2) {
268
- // if caret is inside of a codeblock, indent
269
+ // caret is inside of a codeblock
269
270
  e.preventDefault();
270
- this.#addContent({ type: "inline", value: "\t" });
271
+ if (e.shiftKey) {
272
+ const { line, columnNumber } = this.#lineMeta();
273
+ if (line.startsWith("\t")) {
274
+ // dedent
275
+ const start = this.#selStart;
276
+ this.#removeStr(start - columnNumber);
277
+ this.#setSelection(start - 1);
278
+ }
279
+ }
280
+ else {
281
+ // indent
282
+ this.#addContent({ type: "inline", value: "\t" });
283
+ }
271
284
  }
272
285
  break;
273
286
  }
274
287
  }
275
- // TODO add shift tab backwards
276
288
  }
277
289
  else if (e.key === "Enter" && notHighlighted) {
278
290
  // autocomplete start of next line if block or number
@@ -328,7 +340,6 @@ export class Editor extends Base {
328
340
  else if (e.key in this.keyPairs) {
329
341
  e.preventDefault();
330
342
  this.#addContent({ type: "wrap", value: e.key });
331
- this.#openChars.push(e.key);
332
343
  }
333
344
  });
334
345
  // trims the selection if there is an extra space around it
@@ -344,8 +355,6 @@ export class Editor extends Base {
344
355
  });
345
356
  // reset #openChars on click since the cursor has changed position
346
357
  this.textArea.addEventListener("click", () => (this.#openChars = []));
347
- for (const trigger of this.getTrigger()) {
348
- trigger.addEventListener(this.event, () => this.#addContent(trigger.dataset));
349
- }
358
+ this.triggerListener((e) => this.#addContent(e.target.dataset));
350
359
  }
351
360
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "drab",
3
3
  "description": "Interactivity for You",
4
- "version": "6.1.2",
4
+ "version": "6.2.0",
5
5
  "homepage": "https://drab.robino.dev",
6
6
  "license": "MIT",
7
7
  "author": {