@zero-dependency/dom 1.7.1 → 1.8.1

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/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function a(n,e,...c){const t=document.createElement(n);return e instanceof Node?t.append(e):typeof e=="string"?t.append(r(e)):Array.isArray(e)?t.append(...e):(Object.assign(t,e),Object.assign(t.style,e?.style)),t.append(...c),t}function r(n){return document.createTextNode(n)}function u(){return r(" ")}function d(n){const{history:e,location:c}=window,{pushState:t,replaceState:i}=e;e.pushState=(...o)=>{t.apply(e,o),n.onPush(c,o[0])},e.replaceState=(...o)=>{i.apply(e,o),n.onReplace(c,o[0])}}function s(n,e,c){const t=new MutationObserver((i,o)=>{for(const l of i)e(l,o)});return t.observe(n,{childList:!0,subtree:!0,...c}),()=>t.disconnect()}function b(n,e=document.body){return new Promise(c=>{s(e,(t,i)=>{const o=e.querySelector(n);o&&(i.disconnect(),c(o))})})}exports.el=a;exports.locationObserver=d;exports.nbsp=u;exports.observeElement=s;exports.text=r;exports.waitElement=b;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function v(n,t,...o){const e=document.createElement(n);return t instanceof Node?e.append(t):typeof t=="string"?e.append(u(t)):Array.isArray(t)?e.append(...t):(Object.assign(e,t),Object.assign(e.style,t?.style)),e.append(...o),e}function u(n){return document.createTextNode(n)}function y(){return u(" ")}function l(n,t,o){const e=new MutationObserver((i,c)=>{for(const s of i)t(s,c)});return e.observe(n,{childList:!0,subtree:!0,...o}),()=>e.disconnect()}function f({selector:n,target:t=document.body,rejectTimeoutMs:o,signal:e}){return new Promise((i,c)=>{const s=l(t,(b,m)=>{const d=t.querySelector(n);d&&(m.disconnect(),i(d))}),r={timeout:null,abort:null},a=b=>{r.timeout&&clearTimeout(r.timeout),r.abort&&e.removeEventListener("abort",r.abort),s(),c(b)};o>0&&(r.timeout=setTimeout(()=>a(`${f.name} rejected (${o}ms)`),o)),e&&!e.aborted&&(r.abort=()=>a(e.reason),e.addEventListener("abort",r.abort))})}exports.el=v;exports.nbsp=y;exports.observeElement=l;exports.text=u;exports.waitElement=f;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/html.ts","../src/location-observer.ts","../src/mutation-observer.ts"],"sourcesContent":["import * as CSS from 'csstype'\n\n// prettier-ignore\ntype Properties<T extends keyof HTMLElementTagNameMap> = Partial<{\n style: CSS.Properties\n} & Omit<HTMLElementTagNameMap[T], 'style'>>\n\ntype Children = (string | Node | HTMLElement)[]\n\n/**\n * Creates a new HTML element of the specified type and with the given attributes and children nodes.\n *\n * @param {T} tag\n * The type of HTML element to create.\n *\n * @param {Properties<T> | Children | HTMLElement} [props]\n * The properties or children nodes to add to the element.\n *\n * @param {...Children} children\n * The children nodes to add to the element.\n *\n * @return {HTMLElementTagNameMap[T]}\n * The newly created HTML element of the specified type.\n *\n * @example\n * el('div', { id: 'foo' }, 'Hello world')\n * el('div', 'Hello world')\n * el('div', [el('span', 'Hello'), el('span', 'world')])\n * el('div', el('span', 'Hello world'))\n * el('div', el('span', 'Hello'), el('span', 'world'))\n * el('div', el('span', 'Hello world'), 'world')\n */\nexport function el<T extends keyof HTMLElementTagNameMap>(\n tag: T,\n props?: Properties<T> | Children | HTMLElement,\n ...children: Children\n): HTMLElementTagNameMap[T] {\n const el = document.createElement(tag)\n\n if (props instanceof Node) {\n el.append(props)\n } else if (typeof props === 'string') {\n el.append(text(props))\n } else if (Array.isArray(props)) {\n el.append(...props)\n } else {\n Object.assign(el, props)\n Object.assign(el.style, props?.style)\n }\n\n el.append(...children)\n\n return el\n}\n\n/**\n * Creates a new Text node with the provided text.\n *\n * @param {string} text\n * The text to create the Text node with.\n *\n * @return {Text}\n * A new Text node with the provided text.\n */\nexport function text(text: string): Text {\n return document.createTextNode(text)\n}\n\n/**\n * Returns a Text object containing a non-breaking space character.\n *\n * @return {Text}\n * A Text object containing a non-breaking space character.\n */\nexport function nbsp(): Text {\n return text('\\u00a0')\n}\n","type LocationCallback<T = any> = (location: Location, args: T) => void\n\ntype Events<T> = {\n onPush: LocationCallback<T>\n onReplace: LocationCallback<T>\n}\n\n/**\n * Observes changes to the browser's location and history, and invokes\n * the specified callbacks when the user navigates to a new page or updates the\n * current page's state.\n *\n * @param {Events<T>} events\n * An object that contains optional callback functions for push and replace actions.\n *\n * @example\n * locationObserver<{ id: string }>({\n * onPush: (location, args) => {},\n * onReplace: (location, args) => {}\n * })\n */\nexport function locationObserver<T>(events: Events<T>): void {\n const { history, location } = window\n const { pushState, replaceState } = history\n\n history.pushState = (...args) => {\n pushState.apply(history, args)\n events.onPush(location, args[0])\n }\n\n history.replaceState = (...args) => {\n replaceState.apply(history, args)\n events.onReplace(location, args[0])\n }\n}\n","type Disconnect = () => void\n\n/**\n * Observes changes to an element and invokes a callback function for each mutation.\n *\n * @param {T extends Element} el\n * The element to observe.\n *\n * @param {(mutation: MutationRecord, observer: MutationObserver) => void} callback\n * The function to call when a mutation occurs.\n *\n * @param {MutationObserverInit} [options]\n * Optional configuration options for the MutationObserver.\n *\n * @returns {Disconnect}\n * A function that disconnects the observer.\n *\n * @example\n * const disconnect = observeElement(document.body, (mutation, observer) => {\n * console.log(mutation)\n * })\n */\nexport function observeElement<T extends Element = Element>(\n el: T,\n callback: (mutation: MutationRecord, observer: MutationObserver) => void,\n options?: MutationObserverInit\n): Disconnect {\n const observe = new MutationObserver((mutations, observer) => {\n for (const mutation of mutations) {\n callback(mutation, observer)\n }\n })\n\n observe.observe(el, {\n childList: true,\n subtree: true,\n ...options\n })\n\n return () => observe.disconnect()\n}\n\n/**\n * Returns a Promise that resolves with the first element matching the given selector\n * in the specified target, or rejects if no matches are found.\n *\n * @param {string} selector\n * The CSS selector to match.\n *\n * @param {Element} [target=document.documentElement]\n * The element to search in.\n *\n * @returns {Promise<T>}\n * A Promise that resolves with the first matching element.\n *\n * @example\n * const el = await waitElement('.foo')\n */\nexport function waitElement<T extends Element = Element>(\n selector: string,\n target: Element = document.body\n): Promise<T> {\n return new Promise((resolve) => {\n observeElement(target, (_, observer) => {\n const el = target.querySelector<T>(selector)\n if (el) {\n observer.disconnect()\n resolve(el)\n }\n })\n })\n}\n"],"names":["el","tag","props","children","text","nbsp","locationObserver","events","history","location","pushState","replaceState","args","observeElement","callback","options","observe","mutations","observer","mutation","waitElement","selector","target","resolve","_"],"mappings":"gFAgCgB,SAAAA,EACdC,EACAC,KACGC,EACuB,CACpBH,MAAAA,EAAK,SAAS,cAAcC,CAAG,EAErC,OAAIC,aAAiB,KACnBF,EAAG,OAAOE,CAAK,EACN,OAAOA,GAAU,SAC1BF,EAAG,OAAOI,EAAKF,CAAK,CAAC,EACZ,MAAM,QAAQA,CAAK,EAC5BF,EAAG,OAAO,GAAGE,CAAK,GAEX,OAAA,OAAOF,EAAIE,CAAK,EACvB,OAAO,OAAOF,EAAG,MAAOE,GAAO,KAAK,GAGtCF,EAAG,OAAO,GAAGG,CAAQ,EAEdH,CACT,CAWO,SAASI,EAAKA,EAAoB,CAChC,OAAA,SAAS,eAAeA,CAAI,CACrC,CAQO,SAASC,GAAa,CAC3B,OAAOD,EAAK,GAAQ,CACtB,CCvDO,SAASE,EAAoBC,EAAyB,CACrD,KAAA,CAAE,QAAAC,EAAS,SAAAC,CAAa,EAAA,OACxB,CAAE,UAAAC,EAAW,aAAAC,CAAiB,EAAAH,EAE5BA,EAAA,UAAY,IAAII,IAAS,CACrBF,EAAA,MAAMF,EAASI,CAAI,EAC7BL,EAAO,OAAOE,EAAUG,EAAK,CAAC,CAAC,CAAA,EAGzBJ,EAAA,aAAe,IAAII,IAAS,CACrBD,EAAA,MAAMH,EAASI,CAAI,EAChCL,EAAO,UAAUE,EAAUG,EAAK,CAAC,CAAC,CAAA,CAEtC,CCZgB,SAAAC,EACdb,EACAc,EACAC,EACY,CACZ,MAAMC,EAAU,IAAI,iBAAiB,CAACC,EAAWC,IAAa,CAC5D,UAAWC,KAAYF,EACrBH,EAASK,EAAUD,CAAQ,CAC7B,CACD,EAED,OAAAF,EAAQ,QAAQhB,EAAI,CAClB,UAAW,GACX,QAAS,GACT,GAAGe,CAAA,CACJ,EAEM,IAAMC,EAAQ,YACvB,CAkBO,SAASI,EACdC,EACAC,EAAkB,SAAS,KACf,CACL,OAAA,IAAI,QAASC,GAAY,CACfV,EAAAS,EAAQ,CAACE,EAAGN,IAAa,CAChC,MAAAlB,EAAKsB,EAAO,cAAiBD,CAAQ,EACvCrB,IACFkB,EAAS,WAAW,EACpBK,EAAQvB,CAAE,EACZ,CACD,CAAA,CACF,CACH"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/html.ts","../src/observe-element.ts","../src/wait-element.ts"],"sourcesContent":["import * as CSS from 'csstype'\n\n// prettier-ignore\ntype Properties<T extends keyof HTMLElementTagNameMap> = Partial<{\n style: CSS.Properties\n} & Omit<HTMLElementTagNameMap[T], 'style'>>\n\ntype Children = (string | Node | HTMLElement)[]\n\n/**\n * Creates a new HTML element of the specified type and with the given attributes and children nodes.\n *\n * @param {T} tag\n * The type of HTML element to create.\n *\n * @param {Properties<T> | Children | HTMLElement} [props]\n * The properties or children nodes to add to the element.\n *\n * @param {...Children} children\n * The children nodes to add to the element.\n *\n * @return {HTMLElementTagNameMap[T]}\n * The newly created HTML element of the specified type.\n *\n * @example\n * el('div', { id: 'foo' }, 'Hello world')\n * el('div', 'Hello world')\n * el('div', [el('span', 'Hello'), el('span', 'world')])\n * el('div', el('span', 'Hello world'))\n * el('div', el('span', 'Hello'), el('span', 'world'))\n * el('div', el('span', 'Hello world'), 'world')\n */\nexport function el<T extends keyof HTMLElementTagNameMap>(\n tag: T,\n props?: Properties<T> | Children | HTMLElement,\n ...children: Children\n): HTMLElementTagNameMap[T] {\n const el = document.createElement(tag)\n\n if (props instanceof Node) {\n el.append(props)\n } else if (typeof props === 'string') {\n el.append(text(props))\n } else if (Array.isArray(props)) {\n el.append(...props)\n } else {\n Object.assign(el, props)\n Object.assign(el.style, props?.style)\n }\n\n el.append(...children)\n\n return el\n}\n\n/**\n * Creates a new Text node with the provided text.\n *\n * @param {string} text\n * The text to create the Text node with.\n *\n * @return {Text}\n * A new Text node with the provided text.\n */\nexport function text(text: string): Text {\n return document.createTextNode(text)\n}\n\n/**\n * Returns a Text object containing a non-breaking space character.\n *\n * @return {Text}\n * A Text object containing a non-breaking space character.\n */\nexport function nbsp(): Text {\n return text('\\u00a0')\n}\n","type Disconnect = () => void\n\n/**\n * Observes changes to an element and invokes a callback function for each mutation.\n *\n * @param {T extends Element} el\n * The element to observe.\n *\n * @param {(mutation: MutationRecord, observer: MutationObserver) => void} callback\n * The function to call when a mutation occurs.\n *\n * @param {MutationObserverInit} [options]\n * Optional configuration options for the MutationObserver.\n *\n * @returns {Disconnect}\n * A function that disconnects the observer.\n *\n * @example\n * const disconnect = observeElement(document.body, (mutation, observer) => {\n * console.log(mutation)\n * })\n */\nexport function observeElement<T extends Element = Element>(\n el: T,\n callback: (mutation: MutationRecord, observer: MutationObserver) => void,\n options?: MutationObserverInit\n): Disconnect {\n const observe = new MutationObserver((mutations, observer) => {\n for (const mutation of mutations) {\n callback(mutation, observer)\n }\n })\n\n observe.observe(el, {\n childList: true,\n subtree: true,\n ...options\n })\n\n return () => observe.disconnect()\n}\n","import { observeElement } from './observe-element.js'\n\nexport interface WaitElementParams {\n selector: string\n target?: Element\n rejectTimeoutMs?: number\n signal?: AbortSignal\n}\n\n/**\n * Waits for the specified element to be present in the DOM and returns it.\n *\n * @param {WaitElementParams} params\n * The parameters for waiting and locating the element.\n *\n * @param {string} params.selector\n * The CSS selector to locate the element.\n *\n * @param {Element} [params.target=document.body]\n * The target element to search for the element in.\n *\n * @param {number} [params.rejectTimeoutMs]\n * The timeout in milliseconds after which the promise is rejected.\n *\n * @param {AbortSignal} [params.signal]\n * An optional AbortSignal instance to abort the waiting.\n *\n * @return {Promise<T>}\n * A promise that resolves with the found element.\n *\n * @throws {Error}\n * If the promise is rejected due to the element not being found within the specified time.\n *\n * @example\n * const fooElement = await waitElement({ selector: '.foo' })\n */\nexport function waitElement<T extends Element = Element>({\n selector,\n target = document.body,\n rejectTimeoutMs,\n signal\n}: WaitElementParams): Promise<T> {\n return new Promise((resolve, reject) => {\n const disconnect = observeElement(target, (_, observer) => {\n const el = target.querySelector<T>(selector)\n if (el) {\n observer.disconnect()\n resolve(el)\n }\n })\n\n const listeners: {\n timeout: ReturnType<typeof setTimeout> | null\n abort: (() => void) | null\n } = {\n timeout: null,\n abort: null\n }\n\n const dispose = (message: string) => {\n if (listeners.timeout) {\n clearTimeout(listeners.timeout)\n }\n\n if (listeners.abort) {\n signal.removeEventListener('abort', listeners.abort)\n }\n\n disconnect()\n reject(message)\n }\n\n if (rejectTimeoutMs > 0) {\n listeners.timeout = setTimeout(\n () => dispose(`${waitElement.name} rejected (${rejectTimeoutMs}ms)`),\n rejectTimeoutMs\n )\n }\n\n if (signal && !signal.aborted) {\n listeners.abort = () => dispose(signal.reason)\n signal.addEventListener('abort', listeners.abort)\n }\n })\n}\n"],"names":["el","tag","props","children","text","nbsp","observeElement","callback","options","observe","mutations","observer","mutation","waitElement","selector","target","rejectTimeoutMs","signal","resolve","reject","disconnect","_","listeners","dispose","message"],"mappings":"gFAgCgB,SAAAA,EACdC,EACAC,KACGC,EACuB,CACpBH,MAAAA,EAAK,SAAS,cAAcC,CAAG,EAErC,OAAIC,aAAiB,KACnBF,EAAG,OAAOE,CAAK,EACN,OAAOA,GAAU,SAC1BF,EAAG,OAAOI,EAAKF,CAAK,CAAC,EACZ,MAAM,QAAQA,CAAK,EAC5BF,EAAG,OAAO,GAAGE,CAAK,GAEX,OAAA,OAAOF,EAAIE,CAAK,EACvB,OAAO,OAAOF,EAAG,MAAOE,GAAO,KAAK,GAGtCF,EAAG,OAAO,GAAGG,CAAQ,EAEdH,CACT,CAWO,SAASI,EAAKA,EAAoB,CAChC,OAAA,SAAS,eAAeA,CAAI,CACrC,CAQO,SAASC,GAAa,CAC3B,OAAOD,EAAK,GAAQ,CACtB,CCtDgB,SAAAE,EACdN,EACAO,EACAC,EACY,CACZ,MAAMC,EAAU,IAAI,iBAAiB,CAACC,EAAWC,IAAa,CAC5D,UAAWC,KAAYF,EACrBH,EAASK,EAAUD,CAAQ,CAC7B,CACD,EAED,OAAAF,EAAQ,QAAQT,EAAI,CAClB,UAAW,GACX,QAAS,GACT,GAAGQ,CAAA,CACJ,EAEM,IAAMC,EAAQ,YACvB,CCJO,SAASI,EAAyC,CACvD,SAAAC,EACA,OAAAC,EAAS,SAAS,KAClB,gBAAAC,EACA,OAAAC,CACF,EAAkC,CAChC,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,MAAMC,EAAad,EAAeS,EAAQ,CAACM,EAAGV,IAAa,CACnD,MAAAX,EAAKe,EAAO,cAAiBD,CAAQ,EACvCd,IACFW,EAAS,WAAW,EACpBO,EAAQlB,CAAE,EACZ,CACD,EAEKsB,EAGF,CACF,QAAS,KACT,MAAO,IAAA,EAGHC,EAAWC,GAAoB,CAC/BF,EAAU,SACZ,aAAaA,EAAU,OAAO,EAG5BA,EAAU,OACLL,EAAA,oBAAoB,QAASK,EAAU,KAAK,EAG1CF,IACXD,EAAOK,CAAO,CAAA,EAGZR,EAAkB,IACpBM,EAAU,QAAU,WAClB,IAAMC,EAAQ,GAAGV,EAAY,kBAAkBG,MAAoB,EACnEA,CAAA,GAIAC,GAAU,CAACA,EAAO,UACpBK,EAAU,MAAQ,IAAMC,EAAQN,EAAO,MAAM,EACtCA,EAAA,iBAAiB,QAASK,EAAU,KAAK,EAClD,CACD,CACH"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from './html.js';
2
- export * from './location-observer.js';
3
- export * from './mutation-observer.js';
2
+ export * from './observe-element.js';
3
+ export * from './wait-element.js';
package/dist/index.js CHANGED
@@ -1,46 +1,51 @@
1
- function a(n, e, ...c) {
2
- const t = document.createElement(n);
3
- return e instanceof Node ? t.append(e) : typeof e == "string" ? t.append(r(e)) : Array.isArray(e) ? t.append(...e) : (Object.assign(t, e), Object.assign(t.style, e?.style)), t.append(...c), t;
1
+ function v(n, t, ...o) {
2
+ const e = document.createElement(n);
3
+ return t instanceof Node ? e.append(t) : typeof t == "string" ? e.append(b(t)) : Array.isArray(t) ? e.append(...t) : (Object.assign(e, t), Object.assign(e.style, t?.style)), e.append(...o), e;
4
4
  }
5
- function r(n) {
5
+ function b(n) {
6
6
  return document.createTextNode(n);
7
7
  }
8
- function l() {
9
- return r(" ");
8
+ function y() {
9
+ return b(" ");
10
10
  }
11
- function d(n) {
12
- const { history: e, location: c } = window, { pushState: t, replaceState: i } = e;
13
- e.pushState = (...o) => {
14
- t.apply(e, o), n.onPush(c, o[0]);
15
- }, e.replaceState = (...o) => {
16
- i.apply(e, o), n.onReplace(c, o[0]);
17
- };
18
- }
19
- function u(n, e, c) {
20
- const t = new MutationObserver((i, o) => {
11
+ function l(n, t, o) {
12
+ const e = new MutationObserver((i, c) => {
21
13
  for (const s of i)
22
- e(s, o);
14
+ t(s, c);
23
15
  });
24
- return t.observe(n, {
16
+ return e.observe(n, {
25
17
  childList: !0,
26
18
  subtree: !0,
27
- ...c
28
- }), () => t.disconnect();
19
+ ...o
20
+ }), () => e.disconnect();
29
21
  }
30
- function f(n, e = document.body) {
31
- return new Promise((c) => {
32
- u(e, (t, i) => {
33
- const o = e.querySelector(n);
34
- o && (i.disconnect(), c(o));
35
- });
22
+ function m({
23
+ selector: n,
24
+ target: t = document.body,
25
+ rejectTimeoutMs: o,
26
+ signal: e
27
+ }) {
28
+ return new Promise((i, c) => {
29
+ const s = l(t, (a, f) => {
30
+ const d = t.querySelector(n);
31
+ d && (f.disconnect(), i(d));
32
+ }), r = {
33
+ timeout: null,
34
+ abort: null
35
+ }, u = (a) => {
36
+ r.timeout && clearTimeout(r.timeout), r.abort && e.removeEventListener("abort", r.abort), s(), c(a);
37
+ };
38
+ o > 0 && (r.timeout = setTimeout(
39
+ () => u(`${m.name} rejected (${o}ms)`),
40
+ o
41
+ )), e && !e.aborted && (r.abort = () => u(e.reason), e.addEventListener("abort", r.abort));
36
42
  });
37
43
  }
38
44
  export {
39
- a as el,
40
- d as locationObserver,
41
- l as nbsp,
42
- u as observeElement,
43
- r as text,
44
- f as waitElement
45
+ v as el,
46
+ y as nbsp,
47
+ l as observeElement,
48
+ b as text,
49
+ m as waitElement
45
50
  };
46
51
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/html.ts","../src/location-observer.ts","../src/mutation-observer.ts"],"sourcesContent":["import * as CSS from 'csstype'\n\n// prettier-ignore\ntype Properties<T extends keyof HTMLElementTagNameMap> = Partial<{\n style: CSS.Properties\n} & Omit<HTMLElementTagNameMap[T], 'style'>>\n\ntype Children = (string | Node | HTMLElement)[]\n\n/**\n * Creates a new HTML element of the specified type and with the given attributes and children nodes.\n *\n * @param {T} tag\n * The type of HTML element to create.\n *\n * @param {Properties<T> | Children | HTMLElement} [props]\n * The properties or children nodes to add to the element.\n *\n * @param {...Children} children\n * The children nodes to add to the element.\n *\n * @return {HTMLElementTagNameMap[T]}\n * The newly created HTML element of the specified type.\n *\n * @example\n * el('div', { id: 'foo' }, 'Hello world')\n * el('div', 'Hello world')\n * el('div', [el('span', 'Hello'), el('span', 'world')])\n * el('div', el('span', 'Hello world'))\n * el('div', el('span', 'Hello'), el('span', 'world'))\n * el('div', el('span', 'Hello world'), 'world')\n */\nexport function el<T extends keyof HTMLElementTagNameMap>(\n tag: T,\n props?: Properties<T> | Children | HTMLElement,\n ...children: Children\n): HTMLElementTagNameMap[T] {\n const el = document.createElement(tag)\n\n if (props instanceof Node) {\n el.append(props)\n } else if (typeof props === 'string') {\n el.append(text(props))\n } else if (Array.isArray(props)) {\n el.append(...props)\n } else {\n Object.assign(el, props)\n Object.assign(el.style, props?.style)\n }\n\n el.append(...children)\n\n return el\n}\n\n/**\n * Creates a new Text node with the provided text.\n *\n * @param {string} text\n * The text to create the Text node with.\n *\n * @return {Text}\n * A new Text node with the provided text.\n */\nexport function text(text: string): Text {\n return document.createTextNode(text)\n}\n\n/**\n * Returns a Text object containing a non-breaking space character.\n *\n * @return {Text}\n * A Text object containing a non-breaking space character.\n */\nexport function nbsp(): Text {\n return text('\\u00a0')\n}\n","type LocationCallback<T = any> = (location: Location, args: T) => void\n\ntype Events<T> = {\n onPush: LocationCallback<T>\n onReplace: LocationCallback<T>\n}\n\n/**\n * Observes changes to the browser's location and history, and invokes\n * the specified callbacks when the user navigates to a new page or updates the\n * current page's state.\n *\n * @param {Events<T>} events\n * An object that contains optional callback functions for push and replace actions.\n *\n * @example\n * locationObserver<{ id: string }>({\n * onPush: (location, args) => {},\n * onReplace: (location, args) => {}\n * })\n */\nexport function locationObserver<T>(events: Events<T>): void {\n const { history, location } = window\n const { pushState, replaceState } = history\n\n history.pushState = (...args) => {\n pushState.apply(history, args)\n events.onPush(location, args[0])\n }\n\n history.replaceState = (...args) => {\n replaceState.apply(history, args)\n events.onReplace(location, args[0])\n }\n}\n","type Disconnect = () => void\n\n/**\n * Observes changes to an element and invokes a callback function for each mutation.\n *\n * @param {T extends Element} el\n * The element to observe.\n *\n * @param {(mutation: MutationRecord, observer: MutationObserver) => void} callback\n * The function to call when a mutation occurs.\n *\n * @param {MutationObserverInit} [options]\n * Optional configuration options for the MutationObserver.\n *\n * @returns {Disconnect}\n * A function that disconnects the observer.\n *\n * @example\n * const disconnect = observeElement(document.body, (mutation, observer) => {\n * console.log(mutation)\n * })\n */\nexport function observeElement<T extends Element = Element>(\n el: T,\n callback: (mutation: MutationRecord, observer: MutationObserver) => void,\n options?: MutationObserverInit\n): Disconnect {\n const observe = new MutationObserver((mutations, observer) => {\n for (const mutation of mutations) {\n callback(mutation, observer)\n }\n })\n\n observe.observe(el, {\n childList: true,\n subtree: true,\n ...options\n })\n\n return () => observe.disconnect()\n}\n\n/**\n * Returns a Promise that resolves with the first element matching the given selector\n * in the specified target, or rejects if no matches are found.\n *\n * @param {string} selector\n * The CSS selector to match.\n *\n * @param {Element} [target=document.documentElement]\n * The element to search in.\n *\n * @returns {Promise<T>}\n * A Promise that resolves with the first matching element.\n *\n * @example\n * const el = await waitElement('.foo')\n */\nexport function waitElement<T extends Element = Element>(\n selector: string,\n target: Element = document.body\n): Promise<T> {\n return new Promise((resolve) => {\n observeElement(target, (_, observer) => {\n const el = target.querySelector<T>(selector)\n if (el) {\n observer.disconnect()\n resolve(el)\n }\n })\n })\n}\n"],"names":["el","tag","props","children","text","nbsp","locationObserver","events","history","location","pushState","replaceState","args","observeElement","callback","options","observe","mutations","observer","mutation","waitElement","selector","target","resolve","_"],"mappings":"AAgCgB,SAAAA,EACdC,GACAC,MACGC,GACuB;AACpBH,QAAAA,IAAK,SAAS,cAAcC,CAAG;AAErC,SAAIC,aAAiB,OACnBF,EAAG,OAAOE,CAAK,IACN,OAAOA,KAAU,WAC1BF,EAAG,OAAOI,EAAKF,CAAK,CAAC,IACZ,MAAM,QAAQA,CAAK,IAC5BF,EAAG,OAAO,GAAGE,CAAK,KAEX,OAAA,OAAOF,GAAIE,CAAK,GACvB,OAAO,OAAOF,EAAG,OAAOE,GAAO,KAAK,IAGtCF,EAAG,OAAO,GAAGG,CAAQ,GAEdH;AACT;AAWO,SAASI,EAAKA,GAAoB;AAChC,SAAA,SAAS,eAAeA,CAAI;AACrC;AAQO,SAASC,IAAa;AAC3B,SAAOD,EAAK,GAAQ;AACtB;ACvDO,SAASE,EAAoBC,GAAyB;AACrD,QAAA,EAAE,SAAAC,GAAS,UAAAC,EAAa,IAAA,QACxB,EAAE,WAAAC,GAAW,cAAAC,EAAiB,IAAAH;AAE5B,EAAAA,EAAA,YAAY,IAAII,MAAS;AACrB,IAAAF,EAAA,MAAMF,GAASI,CAAI,GAC7BL,EAAO,OAAOE,GAAUG,EAAK,CAAC,CAAC;AAAA,EAAA,GAGzBJ,EAAA,eAAe,IAAII,MAAS;AACrB,IAAAD,EAAA,MAAMH,GAASI,CAAI,GAChCL,EAAO,UAAUE,GAAUG,EAAK,CAAC,CAAC;AAAA,EAAA;AAEtC;ACZgB,SAAAC,EACdb,GACAc,GACAC,GACY;AACZ,QAAMC,IAAU,IAAI,iBAAiB,CAACC,GAAWC,MAAa;AAC5D,eAAWC,KAAYF;AACrB,MAAAH,EAASK,GAAUD,CAAQ;AAAA,EAC7B,CACD;AAED,SAAAF,EAAQ,QAAQhB,GAAI;AAAA,IAClB,WAAW;AAAA,IACX,SAAS;AAAA,IACT,GAAGe;AAAA,EAAA,CACJ,GAEM,MAAMC,EAAQ;AACvB;AAkBO,SAASI,EACdC,GACAC,IAAkB,SAAS,MACf;AACL,SAAA,IAAI,QAAQ,CAACC,MAAY;AACf,IAAAV,EAAAS,GAAQ,CAACE,GAAGN,MAAa;AAChC,YAAAlB,IAAKsB,EAAO,cAAiBD,CAAQ;AAC3C,MAAIrB,MACFkB,EAAS,WAAW,GACpBK,EAAQvB,CAAE;AAAA,IACZ,CACD;AAAA,EAAA,CACF;AACH;"}
1
+ {"version":3,"file":"index.js","sources":["../src/html.ts","../src/observe-element.ts","../src/wait-element.ts"],"sourcesContent":["import * as CSS from 'csstype'\n\n// prettier-ignore\ntype Properties<T extends keyof HTMLElementTagNameMap> = Partial<{\n style: CSS.Properties\n} & Omit<HTMLElementTagNameMap[T], 'style'>>\n\ntype Children = (string | Node | HTMLElement)[]\n\n/**\n * Creates a new HTML element of the specified type and with the given attributes and children nodes.\n *\n * @param {T} tag\n * The type of HTML element to create.\n *\n * @param {Properties<T> | Children | HTMLElement} [props]\n * The properties or children nodes to add to the element.\n *\n * @param {...Children} children\n * The children nodes to add to the element.\n *\n * @return {HTMLElementTagNameMap[T]}\n * The newly created HTML element of the specified type.\n *\n * @example\n * el('div', { id: 'foo' }, 'Hello world')\n * el('div', 'Hello world')\n * el('div', [el('span', 'Hello'), el('span', 'world')])\n * el('div', el('span', 'Hello world'))\n * el('div', el('span', 'Hello'), el('span', 'world'))\n * el('div', el('span', 'Hello world'), 'world')\n */\nexport function el<T extends keyof HTMLElementTagNameMap>(\n tag: T,\n props?: Properties<T> | Children | HTMLElement,\n ...children: Children\n): HTMLElementTagNameMap[T] {\n const el = document.createElement(tag)\n\n if (props instanceof Node) {\n el.append(props)\n } else if (typeof props === 'string') {\n el.append(text(props))\n } else if (Array.isArray(props)) {\n el.append(...props)\n } else {\n Object.assign(el, props)\n Object.assign(el.style, props?.style)\n }\n\n el.append(...children)\n\n return el\n}\n\n/**\n * Creates a new Text node with the provided text.\n *\n * @param {string} text\n * The text to create the Text node with.\n *\n * @return {Text}\n * A new Text node with the provided text.\n */\nexport function text(text: string): Text {\n return document.createTextNode(text)\n}\n\n/**\n * Returns a Text object containing a non-breaking space character.\n *\n * @return {Text}\n * A Text object containing a non-breaking space character.\n */\nexport function nbsp(): Text {\n return text('\\u00a0')\n}\n","type Disconnect = () => void\n\n/**\n * Observes changes to an element and invokes a callback function for each mutation.\n *\n * @param {T extends Element} el\n * The element to observe.\n *\n * @param {(mutation: MutationRecord, observer: MutationObserver) => void} callback\n * The function to call when a mutation occurs.\n *\n * @param {MutationObserverInit} [options]\n * Optional configuration options for the MutationObserver.\n *\n * @returns {Disconnect}\n * A function that disconnects the observer.\n *\n * @example\n * const disconnect = observeElement(document.body, (mutation, observer) => {\n * console.log(mutation)\n * })\n */\nexport function observeElement<T extends Element = Element>(\n el: T,\n callback: (mutation: MutationRecord, observer: MutationObserver) => void,\n options?: MutationObserverInit\n): Disconnect {\n const observe = new MutationObserver((mutations, observer) => {\n for (const mutation of mutations) {\n callback(mutation, observer)\n }\n })\n\n observe.observe(el, {\n childList: true,\n subtree: true,\n ...options\n })\n\n return () => observe.disconnect()\n}\n","import { observeElement } from './observe-element.js'\n\nexport interface WaitElementParams {\n selector: string\n target?: Element\n rejectTimeoutMs?: number\n signal?: AbortSignal\n}\n\n/**\n * Waits for the specified element to be present in the DOM and returns it.\n *\n * @param {WaitElementParams} params\n * The parameters for waiting and locating the element.\n *\n * @param {string} params.selector\n * The CSS selector to locate the element.\n *\n * @param {Element} [params.target=document.body]\n * The target element to search for the element in.\n *\n * @param {number} [params.rejectTimeoutMs]\n * The timeout in milliseconds after which the promise is rejected.\n *\n * @param {AbortSignal} [params.signal]\n * An optional AbortSignal instance to abort the waiting.\n *\n * @return {Promise<T>}\n * A promise that resolves with the found element.\n *\n * @throws {Error}\n * If the promise is rejected due to the element not being found within the specified time.\n *\n * @example\n * const fooElement = await waitElement({ selector: '.foo' })\n */\nexport function waitElement<T extends Element = Element>({\n selector,\n target = document.body,\n rejectTimeoutMs,\n signal\n}: WaitElementParams): Promise<T> {\n return new Promise((resolve, reject) => {\n const disconnect = observeElement(target, (_, observer) => {\n const el = target.querySelector<T>(selector)\n if (el) {\n observer.disconnect()\n resolve(el)\n }\n })\n\n const listeners: {\n timeout: ReturnType<typeof setTimeout> | null\n abort: (() => void) | null\n } = {\n timeout: null,\n abort: null\n }\n\n const dispose = (message: string) => {\n if (listeners.timeout) {\n clearTimeout(listeners.timeout)\n }\n\n if (listeners.abort) {\n signal.removeEventListener('abort', listeners.abort)\n }\n\n disconnect()\n reject(message)\n }\n\n if (rejectTimeoutMs > 0) {\n listeners.timeout = setTimeout(\n () => dispose(`${waitElement.name} rejected (${rejectTimeoutMs}ms)`),\n rejectTimeoutMs\n )\n }\n\n if (signal && !signal.aborted) {\n listeners.abort = () => dispose(signal.reason)\n signal.addEventListener('abort', listeners.abort)\n }\n })\n}\n"],"names":["el","tag","props","children","text","nbsp","observeElement","callback","options","observe","mutations","observer","mutation","waitElement","selector","target","rejectTimeoutMs","signal","resolve","reject","disconnect","_","listeners","dispose","message"],"mappings":"AAgCgB,SAAAA,EACdC,GACAC,MACGC,GACuB;AACpBH,QAAAA,IAAK,SAAS,cAAcC,CAAG;AAErC,SAAIC,aAAiB,OACnBF,EAAG,OAAOE,CAAK,IACN,OAAOA,KAAU,WAC1BF,EAAG,OAAOI,EAAKF,CAAK,CAAC,IACZ,MAAM,QAAQA,CAAK,IAC5BF,EAAG,OAAO,GAAGE,CAAK,KAEX,OAAA,OAAOF,GAAIE,CAAK,GACvB,OAAO,OAAOF,EAAG,OAAOE,GAAO,KAAK,IAGtCF,EAAG,OAAO,GAAGG,CAAQ,GAEdH;AACT;AAWO,SAASI,EAAKA,GAAoB;AAChC,SAAA,SAAS,eAAeA,CAAI;AACrC;AAQO,SAASC,IAAa;AAC3B,SAAOD,EAAK,GAAQ;AACtB;ACtDgB,SAAAE,EACdN,GACAO,GACAC,GACY;AACZ,QAAMC,IAAU,IAAI,iBAAiB,CAACC,GAAWC,MAAa;AAC5D,eAAWC,KAAYF;AACrB,MAAAH,EAASK,GAAUD,CAAQ;AAAA,EAC7B,CACD;AAED,SAAAF,EAAQ,QAAQT,GAAI;AAAA,IAClB,WAAW;AAAA,IACX,SAAS;AAAA,IACT,GAAGQ;AAAA,EAAA,CACJ,GAEM,MAAMC,EAAQ;AACvB;ACJO,SAASI,EAAyC;AAAA,EACvD,UAAAC;AAAA,EACA,QAAAC,IAAS,SAAS;AAAA,EAClB,iBAAAC;AAAA,EACA,QAAAC;AACF,GAAkC;AAChC,SAAO,IAAI,QAAQ,CAACC,GAASC,MAAW;AACtC,UAAMC,IAAad,EAAeS,GAAQ,CAACM,GAAGV,MAAa;AACnD,YAAAX,IAAKe,EAAO,cAAiBD,CAAQ;AAC3C,MAAId,MACFW,EAAS,WAAW,GACpBO,EAAQlB,CAAE;AAAA,IACZ,CACD,GAEKsB,IAGF;AAAA,MACF,SAAS;AAAA,MACT,OAAO;AAAA,IAAA,GAGHC,IAAU,CAACC,MAAoB;AACnC,MAAIF,EAAU,WACZ,aAAaA,EAAU,OAAO,GAG5BA,EAAU,SACLL,EAAA,oBAAoB,SAASK,EAAU,KAAK,GAG1CF,KACXD,EAAOK,CAAO;AAAA,IAAA;AAGhB,IAAIR,IAAkB,MACpBM,EAAU,UAAU;AAAA,MAClB,MAAMC,EAAQ,GAAGV,EAAY,kBAAkBG,MAAoB;AAAA,MACnEA;AAAA,IAAA,IAIAC,KAAU,CAACA,EAAO,YACpBK,EAAU,QAAQ,MAAMC,EAAQN,EAAO,MAAM,GACtCA,EAAA,iBAAiB,SAASK,EAAU,KAAK;AAAA,EAClD,CACD;AACH;"}
@@ -20,21 +20,4 @@ type Disconnect = () => void;
20
20
  * })
21
21
  */
22
22
  export declare function observeElement<T extends Element = Element>(el: T, callback: (mutation: MutationRecord, observer: MutationObserver) => void, options?: MutationObserverInit): Disconnect;
23
- /**
24
- * Returns a Promise that resolves with the first element matching the given selector
25
- * in the specified target, or rejects if no matches are found.
26
- *
27
- * @param {string} selector
28
- * The CSS selector to match.
29
- *
30
- * @param {Element} [target=document.documentElement]
31
- * The element to search in.
32
- *
33
- * @returns {Promise<T>}
34
- * A Promise that resolves with the first matching element.
35
- *
36
- * @example
37
- * const el = await waitElement('.foo')
38
- */
39
- export declare function waitElement<T extends Element = Element>(selector: string, target?: Element): Promise<T>;
40
23
  export {};
@@ -0,0 +1,34 @@
1
+ export interface WaitElementParams {
2
+ selector: string;
3
+ target?: Element;
4
+ rejectTimeoutMs?: number;
5
+ signal?: AbortSignal;
6
+ }
7
+ /**
8
+ * Waits for the specified element to be present in the DOM and returns it.
9
+ *
10
+ * @param {WaitElementParams} params
11
+ * The parameters for waiting and locating the element.
12
+ *
13
+ * @param {string} params.selector
14
+ * The CSS selector to locate the element.
15
+ *
16
+ * @param {Element} [params.target=document.body]
17
+ * The target element to search for the element in.
18
+ *
19
+ * @param {number} [params.rejectTimeoutMs]
20
+ * The timeout in milliseconds after which the promise is rejected.
21
+ *
22
+ * @param {AbortSignal} [params.signal]
23
+ * An optional AbortSignal instance to abort the waiting.
24
+ *
25
+ * @return {Promise<T>}
26
+ * A promise that resolves with the found element.
27
+ *
28
+ * @throws {Error}
29
+ * If the promise is rejected due to the element not being found within the specified time.
30
+ *
31
+ * @example
32
+ * const fooElement = await waitElement({ selector: '.foo' })
33
+ */
34
+ export declare function waitElement<T extends Element = Element>({ selector, target, rejectTimeoutMs, signal }: WaitElementParams): Promise<T>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zero-dependency/dom",
3
- "version": "1.7.1",
3
+ "version": "1.8.1",
4
4
  "description": "DOM utils",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -1,21 +0,0 @@
1
- type LocationCallback<T = any> = (location: Location, args: T) => void;
2
- type Events<T> = {
3
- onPush: LocationCallback<T>;
4
- onReplace: LocationCallback<T>;
5
- };
6
- /**
7
- * Observes changes to the browser's location and history, and invokes
8
- * the specified callbacks when the user navigates to a new page or updates the
9
- * current page's state.
10
- *
11
- * @param {Events<T>} events
12
- * An object that contains optional callback functions for push and replace actions.
13
- *
14
- * @example
15
- * locationObserver<{ id: string }>({
16
- * onPush: (location, args) => {},
17
- * onReplace: (location, args) => {}
18
- * })
19
- */
20
- export declare function locationObserver<T>(events: Events<T>): void;
21
- export {};