jj 2.4.0 → 2.5.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.
Files changed (68) hide show
  1. package/README.md +18 -57
  2. package/lib/JJD.d.ts +36 -25
  3. package/lib/JJD.js +56 -28
  4. package/lib/JJD.js.map +1 -1
  5. package/lib/JJDF.d.ts +19 -5
  6. package/lib/JJDF.js +32 -2
  7. package/lib/JJDF.js.map +1 -1
  8. package/lib/JJE.d.ts +96 -110
  9. package/lib/JJE.js +143 -154
  10. package/lib/JJE.js.map +1 -1
  11. package/lib/JJET.d.ts +79 -0
  12. package/lib/JJET.js +114 -0
  13. package/lib/JJET.js.map +1 -0
  14. package/lib/JJEx.d.ts +63 -0
  15. package/lib/JJEx.js +83 -0
  16. package/lib/JJEx.js.map +1 -0
  17. package/lib/JJHE.d.ts +26 -37
  18. package/lib/JJHE.js +34 -62
  19. package/lib/JJHE.js.map +1 -1
  20. package/lib/JJN-wrap.js +46 -0
  21. package/lib/JJN-wrap.js.map +1 -0
  22. package/lib/JJN.d.ts +10 -118
  23. package/lib/JJN.js +19 -176
  24. package/lib/JJN.js.map +1 -1
  25. package/lib/JJNx.d.ts +126 -0
  26. package/lib/JJNx.js +157 -0
  27. package/lib/JJNx.js.map +1 -0
  28. package/lib/JJSE.d.ts +32 -10
  29. package/lib/JJSE.js +36 -9
  30. package/lib/JJSE.js.map +1 -1
  31. package/lib/JJSR.d.ts +8 -4
  32. package/lib/JJSR.js +10 -5
  33. package/lib/JJSR.js.map +1 -1
  34. package/lib/JJT.d.ts +26 -13
  35. package/lib/JJT.js +38 -30
  36. package/lib/JJT.js.map +1 -1
  37. package/lib/bundle.js +755 -741
  38. package/lib/bundle.js.map +3 -3
  39. package/lib/bundle.min.js +1 -2
  40. package/lib/components.js +5 -4
  41. package/lib/components.js.map +1 -1
  42. package/lib/helpers.d.ts +3 -2
  43. package/lib/helpers.js +11 -9
  44. package/lib/helpers.js.map +1 -1
  45. package/lib/index.d.ts +20 -2
  46. package/lib/index.js +21 -2
  47. package/lib/index.js.map +1 -1
  48. package/lib/internal.d.ts +30 -0
  49. package/lib/internal.js +35 -0
  50. package/lib/internal.js.map +1 -0
  51. package/lib/types.d.ts +18 -30
  52. package/lib/util.d.ts +0 -28
  53. package/lib/util.js +0 -32
  54. package/lib/util.js.map +1 -1
  55. package/llms.txt +214 -0
  56. package/package.json +11 -3
  57. package/lib/case.test.js +0 -79
  58. package/lib/case.test.js.map +0 -1
  59. package/lib/mixin-types.d.ts +0 -143
  60. package/lib/mixin-types.js +0 -2
  61. package/lib/mixin-types.js.map +0 -1
  62. package/lib/mixins.d.ts +0 -77
  63. package/lib/mixins.js +0 -336
  64. package/lib/mixins.js.map +0 -1
  65. package/lib/util.test.d.ts +0 -1
  66. package/lib/util.test.js +0 -46
  67. package/lib/util.test.js.map +0 -1
  68. /package/lib/{case.test.d.ts → JJN-wrap.d.ts} +0 -0
package/lib/bundle.js CHANGED
@@ -97,12 +97,6 @@ function nextAnimationFrame() {
97
97
  function sleep(ms = 0) {
98
98
  return new Promise((resolve) => setTimeout(resolve, ms));
99
99
  }
100
- function on(target, eventName, handler) {
101
- target.addEventListener(eventName, handler);
102
- }
103
- function off(target, eventName, handler) {
104
- target.removeEventListener(eventName, handler);
105
- }
106
100
  async function cssToStyle(css) {
107
101
  const sheet = new CSSStyleSheet();
108
102
  return await sheet.replace(css);
@@ -132,8 +126,101 @@ function keb2cam(str) {
132
126
  return str.replace(/^-+|-+$/g, "").replace(/-+([a-z])/g, (g, c) => c.toUpperCase());
133
127
  }
134
128
 
129
+ // src/JJET.ts
130
+ var JJET = class _JJET {
131
+ static from(ref) {
132
+ return new _JJET(ref);
133
+ }
134
+ #ref;
135
+ /**
136
+ * Creates a JJET instance.
137
+ *
138
+ * @param ref - The EventTarget to wrap.
139
+ * @throws {TypeError} If `ref` is not an EventTarget.
140
+ */
141
+ constructor(ref) {
142
+ if (!isA(ref, EventTarget)) {
143
+ throw new TypeError(`JJET expects an EventTarget instance. Got ${ref} (${typeof ref}). `);
144
+ }
145
+ this.#ref = ref;
146
+ }
147
+ /**
148
+ * Gets the underlying DOM object.
149
+ */
150
+ get ref() {
151
+ return this.#ref;
152
+ }
153
+ /**
154
+ * Adds an event listener.
155
+ *
156
+ * * @example
157
+ * ```ts
158
+ * JJET.from(window).on('resize', () => console.log('resized'))
159
+ * ```
160
+ * @param eventName - The name of the event.
161
+ * @param handler - The event handler.
162
+ * @param options - Optional event listener options.
163
+ * @returns This instance for chaining.
164
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener | EventTarget.addEventListener}
165
+ */
166
+ on(eventName, handler, options) {
167
+ this.ref.addEventListener(eventName, handler, options);
168
+ return this;
169
+ }
170
+ /**
171
+ * Removes an event listener.
172
+ *
173
+ * * @example
174
+ * ```ts
175
+ * JJET.from(window).off('resize', previouslyAttachedHandler)
176
+ * ```
177
+ * @param eventName - The name of the event.
178
+ * @param handler - The event handler.
179
+ * @param options - Optional event listener options or boolean.
180
+ * @returns This instance for chaining.
181
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener | EventTarget.removeEventListener}
182
+ */
183
+ off(eventName, handler, options) {
184
+ this.ref.removeEventListener(eventName, handler, options);
185
+ return this;
186
+ }
187
+ /**
188
+ * Dispatches an Event at the specified EventTarget.
189
+ *
190
+ * @param event - The Event object to dispatch.
191
+ * @returns This instance for chaining.
192
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent | EventTarget.dispatchEvent}
193
+ */
194
+ trigger(event) {
195
+ this.ref.dispatchEvent(event);
196
+ return this;
197
+ }
198
+ /**
199
+ * Runs a function in the context of this JJET instance.
200
+ *
201
+ * @example
202
+ * ```ts
203
+ * node.run(function() {
204
+ * console.log(this.ref)
205
+ * })
206
+ * ```
207
+ * @remarks
208
+ * If you want to access the current JJ* instance using `this` keyword, you SHOULD use a `function` not an arrow function.
209
+ * If the function throws, `run()` doesn't swallow the exception.
210
+ * So if you're expecting an error, make sure to wrap it in a `try..catch` block and handle the exception.
211
+ * If the function returns a promise, you can `await` on the response.
212
+ *
213
+ * @param fn - The function to run. `this` inside the function will refer to this JJET instance.
214
+ * @param args - Arguments to pass to the function.
215
+ * @returns The return value of the function.
216
+ */
217
+ run(fn, ...args) {
218
+ return fn.call(this, ...args);
219
+ }
220
+ };
221
+
135
222
  // src/JJN.ts
136
- var JJN = class _JJN {
223
+ var JJN = class _JJN extends JJET {
137
224
  /**
138
225
  * Creates a JJN instance from a Node reference.
139
226
  *
@@ -201,7 +288,7 @@ var JJN = class _JJN {
201
288
  return document.createTextNode(obj);
202
289
  }
203
290
  if (!isObj(obj)) {
204
- throw new TypeError(`Expected an object. Got ${obj} (${typeof obj})`);
291
+ throw new TypeError(`JJN.unwrap() expects a string, DOM Node, or JJ wrapper. Got ${obj} (${typeof obj}). `);
205
292
  }
206
293
  if (isA(obj, Node)) {
207
294
  return obj;
@@ -209,7 +296,9 @@ var JJN = class _JJN {
209
296
  if (isA(obj, _JJN)) {
210
297
  return obj.ref;
211
298
  }
212
- throw new TypeError(`Could not unwrap ${obj} (${typeof obj})`);
299
+ throw new TypeError(
300
+ `Could not unwrap ${obj} (${typeof obj}). Expected a string, Node, or JJ wrapper. Make sure you're passing a valid DOM element or JJ wrapper.`
301
+ );
213
302
  }
214
303
  /**
215
304
  * Wraps an iterable object (e.g. an array of wrapped or DOM elements).
@@ -239,7 +328,6 @@ var JJN = class _JJN {
239
328
  static unwrapAll(iterable) {
240
329
  return Array.from(iterable, _JJN.unwrap);
241
330
  }
242
- #ref;
243
331
  /**
244
332
  * Creates an instance of JJN.
245
333
  *
@@ -248,18 +336,14 @@ var JJN = class _JJN {
248
336
  */
249
337
  constructor(ref) {
250
338
  if (!isA(ref, Node)) {
251
- throw new TypeError(`Expected a Node. Got ${ref} (${typeof ref})`);
339
+ throw new TypeError(
340
+ `JJN expects a Node instance. Got ${ref} (${typeof ref}). Use JJN.from(node) with a DOM Node, or check that you're passing a valid DOM element.`
341
+ );
252
342
  }
253
- this.#ref = ref;
254
- }
255
- /**
256
- * Gets the underlying DOM Node.
257
- */
258
- get ref() {
259
- return this.#ref;
343
+ super(ref);
260
344
  }
261
345
  /**
262
- * Clones the node.
346
+ * Clones the Node.
263
347
  *
264
348
  * @param deep - If true, clones the subtree.
265
349
  * @returns A new wrapped instance of the clone.
@@ -269,266 +353,197 @@ var JJN = class _JJN {
269
353
  return _JJN.wrap(this.ref.cloneNode(deep));
270
354
  }
271
355
  /**
272
- * Appends children to this node.
356
+ * Creates a Text node from a string and appends it to this Node.
273
357
  *
274
358
  * @remarks
275
- * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
359
+ * This method is overridden in JJT to append to the existing text content instead.
276
360
  *
277
- * @param children - The children to append (Nodes, strings, or Wrappers).
361
+ * @example
362
+ * ```ts
363
+ * el.addText('Hello ')
364
+ * el.addText('World')
365
+ * ```
366
+ *
367
+ * @param text - The text to add. If null or undefined, nothing is added.
278
368
  * @returns This instance for chaining.
279
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/append | Element.append}
280
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild | Node.appendChild}
369
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/createTextNode | document.createTextNode}
281
370
  */
282
- append(...children) {
283
- const nodes = _JJN.unwrapAll(children.filter(_JJN.isWrapable));
284
- const ref = this.ref;
285
- for (const node of nodes) {
286
- if (node) {
287
- ref.appendChild(node);
288
- }
371
+ addText(text) {
372
+ if (text) {
373
+ this.ref.appendChild(document.createTextNode(text));
289
374
  }
290
375
  return this;
291
376
  }
377
+ };
378
+
379
+ // src/JJNx.ts
380
+ var JJNx = class extends JJN {
292
381
  /**
293
- * Maps an array to children and appends them.
382
+ * Finds the first element matching a selector within this Element.
294
383
  *
295
384
  * @example
296
385
  * ```ts
297
- * list.mapAppend(['a', 'b'], item => h('li', null, item))
386
+ * const span = el.query('span') // Returns null if not found
387
+ * const span = el.query('span', true) // Throws if not found
298
388
  * ```
299
389
  *
300
- * @remarks
301
- * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
302
- *
303
- * @param array - The source array.
304
- * @param mapFn - The mapping function returning a Wrappable.
305
- * @returns This instance for chaining.
306
- */
307
- mapAppend(array, mapFn) {
308
- return this.append(...array.map(mapFn));
309
- }
310
- /**
311
- * Prepends children to this node.
312
- *
313
- * @remarks
314
- * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
315
- *
316
- * @param children - The children to prepend.
317
- * @returns This instance for chaining.
318
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/prepend | Element.prepend}
390
+ * @param selector - The CSS selector.
391
+ * @param required - Whether to throw an error if not found. Defaults to false.
392
+ * @returns The wrapped element, or null if not found and required is false.
393
+ * @throws {TypeError} If selector is not a string or element not found and required is true.
394
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector | Element.querySelector}
319
395
  */
320
- prepend(...children) {
321
- const nodes = _JJN.unwrapAll(children.filter(_JJN.isWrapable));
322
- const ref = this.ref;
323
- const first = ref.firstChild;
324
- for (const node of nodes) {
325
- if (node) {
326
- ref.insertBefore(node, first);
327
- }
396
+ query(selector, required = false) {
397
+ const queryResult = this.ref.querySelector(selector);
398
+ if (queryResult) {
399
+ return JJN.wrap(queryResult);
328
400
  }
329
- return this;
401
+ if (required) {
402
+ throw new TypeError(
403
+ `Element with selector "${selector}" not found. Did you mean to call .query("${selector}", false) to return null instead? `
404
+ );
405
+ }
406
+ return null;
330
407
  }
331
408
  /**
332
- * Maps an array to children and prepends them.
409
+ * Finds all elements matching a selector within this Element.
333
410
  *
334
411
  * @example
335
412
  * ```ts
336
- * list.mapPrepend(['a', 'b'], item => JJHE.fromTag('li').setText(item))
413
+ * const items = el.queryAll('li')
337
414
  * ```
338
415
  *
339
- * @remarks
340
- * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
341
- *
342
- * @param array - The source array.
343
- * @param mapFn - The mapping function.
344
- * @returns This instance for chaining.
416
+ * @param selector - The CSS selector.
417
+ * @returns An array of wrapped elements.
418
+ * @throws {TypeError} If selector is not a string.
419
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll | Element.querySelectorAll}
345
420
  */
346
- mapPrepend(array, mapFn) {
347
- return this.prepend(...array.map(mapFn));
421
+ queryAll(selector) {
422
+ return JJN.wrapAll(this.ref.querySelectorAll(selector));
348
423
  }
349
424
  /**
350
- * Replaces the existing children of this node with a specified new set of children.
425
+ * Appends children to this Element.
426
+ *
427
+ * @example
428
+ * ```ts
429
+ * el.append(h('span', null, 'hello'))
430
+ * ```
351
431
  *
352
432
  * @remarks
353
- * If no children are specified, it essentially empties the node
354
433
  * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
355
434
  *
356
- * @param children - The new children to set.
357
- * @returns This instance for chaining.
358
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren | Element.replaceChildren}
359
- */
360
- setChildren(...children) {
361
- return this.empty().append(...children.filter(_JJN.isWrapable));
362
- }
363
- /**
364
- * Adds an event listener.
365
- *
366
- * @param eventName - The event name.
367
- * @param handler - The event handler.
435
+ * @param children - The children to append.
368
436
  * @returns This instance for chaining.
369
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener | EventTarget.addEventListener}
437
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/append | Element.append}
370
438
  */
371
- on(eventName, handler) {
372
- on(this.ref, eventName, handler);
439
+ append(...children) {
440
+ const nodes = JJN.unwrapAll(children.filter(JJN.isWrapable));
441
+ this.ref.append(...nodes);
373
442
  return this;
374
443
  }
375
444
  /**
376
- * Removes an event listener.
445
+ * Prepends children to this Element.
377
446
  *
378
- * @param eventName - The event name.
379
- * @param handler - The event handler.
380
- * @returns This instance for chaining.
381
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener | EventTarget.removeEventListener}
382
- */
383
- off(eventName, handler) {
384
- off(this.ref, eventName, handler);
385
- return this;
386
- }
387
- /**
388
- * Removes this node from the DOM.
447
+ * @example
448
+ * ```ts
449
+ * el.prepend(h('span', null, 'first'))
450
+ * ```
389
451
  *
390
- * @returns This instance for chaining.
391
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild | Node.removeChild}
392
- */
393
- rm() {
394
- this.ref.parentNode?.removeChild(this.ref);
395
- return this;
396
- }
397
- /**
398
- * Removes all children from this node.
452
+ * @remarks
453
+ * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
399
454
  *
455
+ * @param children - The children to prepend.
400
456
  * @returns This instance for chaining.
401
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren | Element.replaceChildren}
457
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/prepend | Element.prepend}
402
458
  */
403
- empty() {
404
- const element = this.ref;
405
- while (element.firstChild) {
406
- element.removeChild(element.firstChild);
407
- }
459
+ prepend(...children) {
460
+ const nodes = JJN.unwrapAll(children.filter(JJN.isWrapable));
461
+ this.ref.prepend(...nodes);
408
462
  return this;
409
463
  }
410
464
  /**
411
- * Runs a function in the context of this JJN instance.
465
+ * Maps an array to children and appends them.
412
466
  *
413
467
  * @example
414
468
  * ```ts
415
- * div.run(function() {
416
- * this.addClass('active')
417
- * console.log(this.ref)
418
- * })
469
+ * node.mapAppend(['a', 'b'], item => h('li', null, item))
419
470
  * ```
471
+ *
420
472
  * @remarks
421
- * If you want to access the current JJ* instance using `this` keyword, you SHOULD use a `function` not an arrow function.
422
- * If the function throws, `run()` doesn't swallow the exception.
423
- * So if you're expecting an error, make sure to wrap it in a `try..catch` block and handle the exception.
424
- * If the function returns a promise, you can `await` on the response.
473
+ * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
425
474
  *
426
- * @param fn - The function to run. `this` inside the function will refer to this JJN instance.
427
- * @param args - Arguments to pass to the function.
428
- * @returns The return value of the function.
475
+ * @param array - The source array.
476
+ * @param mapFn - The mapping function returning a Wrappable.
477
+ * @returns This instance for chaining.
429
478
  */
430
- run(fn, ...args) {
431
- return fn.call(this, ...args);
479
+ mapAppend(array, mapFn) {
480
+ return this.append(...array.map(mapFn));
432
481
  }
433
- };
434
-
435
- // src/JJT.ts
436
- var JJT = class _JJT extends JJN {
437
482
  /**
438
- * Creates a JJT instance from a Text node.
483
+ * Maps an array to children and prepends them.
439
484
  *
440
485
  * @example
441
486
  * ```ts
442
- * const textNode = document.createTextNode('foo')
443
- * const jjText = JJT.from(textNode)
487
+ * node.mapPrepend(['a', 'b'], item => JJHE.fromTag('li').setText(item))
444
488
  * ```
445
489
  *
446
- * @param text - The Text node.
447
- * @returns A new JJT instance.
448
- * @throws {TypeError} If `text` is not a Text node.
449
- */
450
- static from(text) {
451
- if (!isA(text, Text)) {
452
- throw new TypeError(`Expected a Text object. Got: ${text} (${typeof text})`);
453
- }
454
- return new _JJT(text);
455
- }
456
- /**
457
- * Creates an instance of JJT.
458
- *
459
- * @example
460
- * ```ts
461
- * const text = new JJT('Hello World')
462
- * ```
490
+ * @remarks
491
+ * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
463
492
  *
464
- * @param ref - The Text node or a string to create a Text node from.
465
- * @throws {TypeError} If `ref` is not a Text node or string.
493
+ * @param array - The source array.
494
+ * @param mapFn - The mapping function.
495
+ * @returns This instance for chaining.
466
496
  */
467
- constructor(ref) {
468
- if (isStr(ref)) {
469
- super(document.createTextNode(ref));
470
- } else if (isA(ref, Text)) {
471
- super(ref);
472
- } else {
473
- throw new TypeError(`Expected a Text. Got: ${ref} (${typeof ref})`);
474
- }
497
+ mapPrepend(array, mapFn) {
498
+ return this.prepend(...array.map(mapFn));
475
499
  }
476
500
  /**
477
- * Gets the text content.
501
+ * Replaces the existing children of an Element with a specified new set of children.
478
502
  *
479
- * @returns The text content.
480
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
481
- */
482
- getText() {
483
- return this.ref.textContent ?? "";
484
- }
485
- /**
486
- * Sets the text content.
503
+ * @remarks
504
+ * If no children are provided, it empties the Element.
505
+ * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
487
506
  *
488
507
  * @example
489
508
  * ```ts
490
- * text.setText('New content')
509
+ * el.setChildren(h('p', null, 'New Content'))
491
510
  * ```
492
- *
493
- * @param text - The text to set.
511
+ * @param children - The children to replace with.
494
512
  * @returns This instance for chaining.
495
- * @throws {TypeError} If `text` is not a string.
496
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
513
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren | Element.replaceChildren}
497
514
  */
498
- setText(text) {
499
- if (!isStr(text)) {
500
- throw new TypeError(`Expected a string. Got: ${text} (${typeof text})`);
501
- }
502
- this.ref.textContent = text;
515
+ setChildren(...children) {
516
+ const nodes = JJN.unwrapAll(children.filter(JJN.isWrapable));
517
+ this.ref.replaceChildren(...nodes);
503
518
  return this;
504
519
  }
505
520
  /**
506
- * Clears the text content.
507
- *
508
- * @returns This instance for chaining.
509
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
510
- */
511
- empty() {
512
- return this.setText("");
513
- }
514
- /**
515
- * Sets the text content to multiple lines joined by newline.
521
+ * Removes all children from this Element.
516
522
  *
517
523
  * @example
518
524
  * ```ts
519
- * text.addLines('Line 1', 'Line 2')
525
+ * el.empty()
520
526
  * ```
521
527
  *
522
- * @param lines - The lines of text.
523
528
  * @returns This instance for chaining.
529
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren | Element.setChildren}
524
530
  */
525
- addLines(...lines) {
526
- return this.setText(lines.join("\n"));
531
+ empty() {
532
+ this.setChildren();
533
+ return this;
527
534
  }
528
535
  };
529
536
 
537
+ // src/internal.ts
538
+ function errMsg(varName, expected, received) {
539
+ return `Expected '${varName}' to be ${expected}. Got ${received} (${typeof received})`;
540
+ }
541
+ function typeErr(varName, expected, received) {
542
+ return new TypeError(errMsg(varName, expected, received));
543
+ }
544
+
530
545
  // src/JJDF.ts
531
- var JJDF = class _JJDF extends JJN {
546
+ var JJDF = class _JJDF extends JJNx {
532
547
  /**
533
548
  * Creates a JJDF instance from a DocumentFragment reference.
534
549
  *
@@ -571,6 +586,34 @@ var JJDF = class _JJDF extends JJN {
571
586
  }
572
587
  super(ref);
573
588
  }
589
+ /**
590
+ * Finds an element by ID within this DocumentFragment.
591
+ *
592
+ * @example
593
+ * ```ts
594
+ * const el = frag.byId('header') // Returns null if not found
595
+ * const el = frag.byId('header', true) // Throws if not found
596
+ * ```
597
+ *
598
+ * @param id - The ID to search for.
599
+ * @param required - Whether to throw an error if not found. Defaults to false.
600
+ * @returns The wrapped element, or null if not found and required is false.
601
+ * @throws {TypeError} If id is not a string or element not found and required is true.
602
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/getElementById | DocumentFragment.getElementById}
603
+ */
604
+ byId(id, required = false) {
605
+ if (!isStr(id)) {
606
+ throw typeErr("id", "a string", id);
607
+ }
608
+ const el = this.ref.getElementById(id);
609
+ if (el) {
610
+ return JJN.wrap(el);
611
+ }
612
+ if (required) {
613
+ throw new TypeError(`Element with id ${id} not found`);
614
+ }
615
+ return null;
616
+ }
574
617
  };
575
618
 
576
619
  // src/JJSR.ts
@@ -597,12 +640,14 @@ var JJSR = class _JJSR extends JJDF {
597
640
  */
598
641
  constructor(shadowRoot) {
599
642
  if (!isA(shadowRoot, ShadowRoot)) {
600
- throw new TypeError(`Expected a ShadowRoot. Got ${shadowRoot} (${typeof shadowRoot})`);
643
+ throw new TypeError(
644
+ `JJSR expects a ShadowRoot instance. Got ${shadowRoot} (${typeof shadowRoot}). Access a shadow root using element.shadowRoot after calling element.attachShadow().`
645
+ );
601
646
  }
602
647
  super(shadowRoot);
603
648
  }
604
649
  /**
605
- * Gets the inner HTML of the shadow root.
650
+ * Gets the inner HTML of the ShadowRoot.
606
651
  *
607
652
  * @returns The inner HTML string.
608
653
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML | Element.innerHTML}
@@ -611,7 +656,7 @@ var JJSR = class _JJSR extends JJDF {
611
656
  return this.ref.innerHTML;
612
657
  }
613
658
  /**
614
- * Sets the inner HTML of the shadow root.
659
+ * Sets the inner HTML of the ShadowRoot.
615
660
  *
616
661
  * @example
617
662
  * ```ts
@@ -628,7 +673,7 @@ var JJSR = class _JJSR extends JJDF {
628
673
  return this;
629
674
  }
630
675
  /**
631
- * Adds constructed stylesheets to the shadow root.
676
+ * Adds constructed stylesheets to the ShadowRoot.
632
677
  *
633
678
  * @example
634
679
  * ```ts
@@ -648,7 +693,7 @@ var JJSR = class _JJSR extends JJDF {
648
693
  };
649
694
 
650
695
  // src/JJE.ts
651
- var JJE = class _JJE extends JJN {
696
+ var JJE = class _JJE extends JJNx {
652
697
  /**
653
698
  * Creates a JJE instance from an Element reference.
654
699
  *
@@ -671,35 +716,24 @@ var JJE = class _JJE extends JJN {
671
716
  */
672
717
  constructor(ref) {
673
718
  if (!isA(ref, Element)) {
674
- throw new TypeError(`Expected an Element. Got: ${ref} (${typeof ref})`);
719
+ throw new TypeError(
720
+ `JJE expects an Element instance. Got ${ref} (${typeof ref}). Use JJE.from(element) with a DOM Element, or use the specific wrapper (JJHE for HTMLElement, JJSE for SVGElement).`
721
+ );
675
722
  }
676
723
  super(ref);
677
724
  }
678
- /**
679
- * Finds an element by ID within this element's context
680
- *
681
- * @remarks
682
- * This method uses `Element.querySelector()` under the hood.
683
- *
684
- * @param id - The ID to search for.
685
- * @param throwIfNotFound - Whether to throw an error if not found. Defaults to true.
686
- * @returns The wrapped element, or null if not found and throwIfNotFound is false.
687
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector | Element.querySelector}
688
- */
689
- byId(id, throwIfNotFound = true) {
690
- if (!isStr(id)) {
691
- throw new TypeError(`Expected a string id. Got ${id} (${typeof id})`);
692
- }
693
- return this.query(`#${id}`, throwIfNotFound);
694
- }
695
725
  /**
696
726
  * Gets the value of an attribute.
697
727
  *
698
728
  * @param name - The name of the attribute.
699
729
  * @returns The attribute value, or null if not present.
730
+ * @throws {TypeError} If `name` is not a string.
700
731
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute | Element.getAttribute}
701
732
  */
702
733
  getAttr(name) {
734
+ if (!isStr(name)) {
735
+ throw typeErr("name", "a string", name);
736
+ }
703
737
  return this.ref.getAttribute(name);
704
738
  }
705
739
  /**
@@ -707,62 +741,46 @@ var JJE = class _JJE extends JJN {
707
741
  *
708
742
  * @param name - The name of the attribute.
709
743
  * @returns `true` if the attribute exists, otherwise `false`.
744
+ * @throws {TypeError} If `name` is not a string.
710
745
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/hasAttribute | Element.hasAttribute}
711
746
  */
712
747
  hasAttr(name) {
713
- return this.ref.hasAttribute(name);
714
- }
715
- /**
716
- * Sets the value of an attribute.
717
- *
718
- * @param name - The name of the attribute.
719
- * @param value - The value to set.
720
- * @returns This instance for chaining.
721
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute | Element.setAttribute}
722
- */
723
- setAttr(name, value) {
724
- this.ref.setAttribute(name, value);
725
- return this;
726
- }
727
- /**
728
- * Sets multiple attributes at once.
729
- *
730
- * @example
731
- * ```ts
732
- * el.setAttrs({ id: 'my-id', class: 'my-class' })
733
- * ```
734
- *
735
- * @param obj - An object where keys are attribute names and values are attribute values.
736
- * @returns This instance for chaining.
737
- * @throws {TypeError} If `obj` is not an object.
738
- */
739
- setAttrs(obj) {
740
- if (!isObj(obj)) {
741
- throw new TypeError(`Expected an object. Got: ${obj} (${typeof obj})`);
748
+ if (!isStr(name)) {
749
+ throw typeErr("name", "a string", name);
742
750
  }
743
- for (const [name, value] of Object.entries(obj)) {
744
- this.setAttr(name, value);
751
+ return this.ref.hasAttribute(name);
752
+ }
753
+ setAttr(nameOrObj, value) {
754
+ if (typeof nameOrObj === "string") {
755
+ this.ref.setAttribute(nameOrObj, value);
756
+ } else if (isObj(nameOrObj)) {
757
+ for (const [k, v] of Object.entries(nameOrObj)) {
758
+ this.ref.setAttribute(k, v);
759
+ }
760
+ } else {
761
+ throw typeErr("nameOrObj", "a string or object", nameOrObj);
745
762
  }
746
763
  return this;
747
764
  }
748
765
  /**
749
- * Removes an attribute.
766
+ * Removes one or more attributes from the Element.
750
767
  *
751
- * @param name - The name of the attribute to remove.
752
- * @returns This instance for chaining.
753
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute | Element.removeAttribute}
754
- */
755
- rmAttr(name) {
756
- return this.rmAttrs(name);
757
- }
758
- /**
759
- * Removes multiple attributes.
768
+ * @example
769
+ * ```ts
770
+ * el.rmAttr('disabled') // Remove single
771
+ * el.rmAttr('hidden', 'aria-hidden') // Remove multiple
772
+ * ```
760
773
  *
761
- * @param names - The names of the attributes to remove.
774
+ * @param names - The name(s) of the attribute(s) to remove.
762
775
  * @returns This instance for chaining.
776
+ * @throws {TypeError} If any name is not a string.
777
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/removeAttribute | Element.removeAttribute}
763
778
  */
764
- rmAttrs(...names) {
779
+ rmAttr(...names) {
765
780
  for (const name of names) {
781
+ if (!isStr(name)) {
782
+ throw typeErr("name", "a string", name);
783
+ }
766
784
  this.ref.removeAttribute(name);
767
785
  }
768
786
  return this;
@@ -780,9 +798,13 @@ var JJE = class _JJE extends JJN {
780
798
  *
781
799
  * @param name - The ARIA attribute suffix (e.g., 'label' for 'aria-label').
782
800
  * @returns The attribute value, or null if not present.
801
+ * @throws {TypeError} If `name` is not a string.
783
802
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes | ARIA Attributes}
784
803
  */
785
804
  getAria(name) {
805
+ if (!isStr(name)) {
806
+ throw typeErr("name", "a string", name);
807
+ }
786
808
  return this.ref.getAttribute(`aria-${name}`);
787
809
  }
788
810
  /**
@@ -790,34 +812,46 @@ var JJE = class _JJE extends JJN {
790
812
  *
791
813
  * @param name - The ARIA attribute suffix.
792
814
  * @returns `true` if the attribute exists.
815
+ * @throws {TypeError} If `name` is not a string.
793
816
  */
794
817
  hasAria(name) {
818
+ if (!isStr(name)) {
819
+ throw typeErr("name", "a string", name);
820
+ }
795
821
  return this.ref.hasAttribute(`aria-${name}`);
796
822
  }
823
+ setAria(nameOrObj, value) {
824
+ if (isStr(nameOrObj)) {
825
+ this.ref.setAttribute(`aria-${nameOrObj}`, value);
826
+ } else if (isObj(nameOrObj)) {
827
+ for (const [k, v] of Object.entries(nameOrObj)) {
828
+ this.ref.setAttribute(`aria-${k}`, v);
829
+ }
830
+ } else {
831
+ throw typeErr("nameOrObj", "a string or object", nameOrObj);
832
+ }
833
+ return this;
834
+ }
797
835
  /**
798
- * Sets an ARIA attribute.
836
+ * Removes one or more ARIA attributes from the Element.
799
837
  *
800
838
  * @example
801
839
  * ```ts
802
- * el.setAria('hidden', 'true') // sets aria-hidden="true"
840
+ * el.rmAria('hidden') // Remove single
841
+ * el.rmAria('label', 'hidden') // Remove multiple
803
842
  * ```
804
843
  *
805
- * @param name - The ARIA attribute suffix.
806
- * @param value - The value to set.
807
- * @returns This instance for chaining.
808
- */
809
- setAria(name, value) {
810
- this.ref.setAttribute(`aria-${name}`, value);
811
- return this;
812
- }
813
- /**
814
- * Removes an ARIA attribute.
815
- *
816
- * @param name - The ARIA attribute suffix.
844
+ * @param names - The ARIA attribute suffix(es) to remove.
817
845
  * @returns This instance for chaining.
846
+ * @throws {TypeError} If any name is not a string.
818
847
  */
819
- rmAria(name) {
820
- this.ref.removeAttribute(`aria-${name}`);
848
+ rmAria(...names) {
849
+ for (const name of names) {
850
+ if (!isStr(name)) {
851
+ throw typeErr("name", "a string", name);
852
+ }
853
+ this.ref.removeAttribute(`aria-${name}`);
854
+ }
821
855
  return this;
822
856
  }
823
857
  /**
@@ -829,71 +863,94 @@ var JJE = class _JJE extends JJN {
829
863
  getClass() {
830
864
  return this.getAttr("class");
831
865
  }
832
- /**
833
- * Sets the class attribute.
834
- *
835
- * @param className - The class string to set.
836
- * @returns This instance for chaining.
837
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/className | Element.className}
838
- */
839
- setClass(className) {
840
- return this.setAttr("class", className);
866
+ setClass(classNameOrMap) {
867
+ if (typeof classNameOrMap === "string") {
868
+ return this.setAttr("class", classNameOrMap);
869
+ }
870
+ for (const [className, condition] of Object.entries(classNameOrMap)) {
871
+ if (condition) {
872
+ this.ref.classList.add(className);
873
+ } else {
874
+ this.ref.classList.remove(className);
875
+ }
876
+ }
877
+ return this;
841
878
  }
842
879
  /**
843
- * Removes the `class` attribute of the element.
844
- *
845
- * @remarks
846
- * If you want to remove a few specific class instead of all, use `rmClasses`
880
+ * Adds one or more classes to the Element.
847
881
  *
848
- * @returns This instance for chaining.
849
- */
850
- rmClass() {
851
- return this.rmAttr("class");
852
- }
853
- /**
854
- * Adds one or more classes to the element.
882
+ * @example
883
+ * ```ts
884
+ * el.addClass('btn', 'btn-primary')
885
+ * ```
855
886
  *
856
887
  * @param classNames - The classes to add.
857
888
  * @returns This instance for chaining.
889
+ * @throws {TypeError} If any class name is not a string.
858
890
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | Element.classList}
859
891
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/add | DOMTokenList.add}
860
892
  */
861
893
  addClass(...classNames) {
894
+ for (const className of classNames) {
895
+ if (!isStr(className)) {
896
+ throw typeErr("className", "a string", className);
897
+ }
898
+ }
862
899
  this.ref.classList.add(...classNames);
863
900
  return this;
864
901
  }
865
902
  /**
866
- * Removes one or more classes from the element.
903
+ * Removes one or more classes from the Element.
904
+ *
905
+ * @example
906
+ * ```ts
907
+ * el.rmClass('active') // Remove single
908
+ * el.rmClass('btn', 'btn-primary') // Remove multiple
909
+ * ```
867
910
  *
868
911
  * @param classNames - The classes to remove.
869
912
  * @returns This instance for chaining.
913
+ * @throws {TypeError} If any class name is not a string.
870
914
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | Element.classList}
871
915
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/remove | DOMTokenList.remove}
872
916
  */
873
- rmClasses(...classNames) {
917
+ rmClass(...classNames) {
918
+ for (const className of classNames) {
919
+ if (!isStr(className)) {
920
+ throw typeErr("className", "a string", className);
921
+ }
922
+ }
874
923
  this.ref.classList.remove(...classNames);
875
924
  return this;
876
925
  }
877
926
  /**
878
- * Checks if the element has a specific class.
927
+ * Checks if the Element has a specific class.
879
928
  *
880
929
  * @param className - The class to check for.
881
930
  * @returns `true` if the element has the class.
931
+ * @throws {TypeError} If `className` is not a string.
882
932
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | Element.classList}
883
933
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/contains | DOMTokenList.contains}
884
934
  */
885
935
  hasClass(className) {
936
+ if (!isStr(className)) {
937
+ throw typeErr("className", "a string", className);
938
+ }
886
939
  return this.ref.classList.contains(className);
887
940
  }
888
941
  /**
889
- * Toggles a class on the element.
942
+ * Toggles a class on the Element.
890
943
  *
891
944
  * @param className - The class to toggle.
892
945
  * @returns This instance for chaining.
946
+ * @throws {TypeError} If `className` is not a string.
893
947
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/classList | Element.classList}
894
948
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle | DOMTokenList.toggle}
895
949
  */
896
950
  toggleClass(className) {
951
+ if (!isStr(className)) {
952
+ throw typeErr("className", "a string", className);
953
+ }
897
954
  this.ref.classList.toggle(className);
898
955
  return this;
899
956
  }
@@ -905,41 +962,39 @@ var JJE = class _JJE extends JJN {
905
962
  *
906
963
  * @param oldClassName - The class name to remove
907
964
  * @param newClassName - The class name to add
965
+ * @throws {TypeError} If either className is not a string.
908
966
  */
909
967
  replaceClass(oldClassName, newClassName) {
968
+ if (!isStr(oldClassName)) {
969
+ throw typeErr("oldClassName", "a string", oldClassName);
970
+ }
971
+ if (!isStr(newClassName)) {
972
+ throw typeErr("newClassName", "a string", newClassName);
973
+ }
910
974
  this.ref.classList.replace(oldClassName, newClassName);
911
975
  return this;
912
976
  }
913
977
  /**
914
- * Adds a click event listener.
915
- *
916
- * @param handler - The event handler.
917
- * @returns This instance for chaining.
918
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener | EventTarget.addEventListener}
919
- */
920
- onClick(handler) {
921
- return this.on("click", handler);
922
- }
923
- /**
924
- * Hides the element by setting the `hidden` attribute and `aria-hidden="true"`.
925
- *
926
- * @returns This instance for chaining.
927
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden | hidden attribute}
928
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden | aria-hidden}
929
- */
978
+
979
+ * Hides the Element by setting the `hidden` attribute and `aria-hidden="true"`.
980
+ *
981
+ * @returns This instance for chaining.
982
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden | hidden attribute}
983
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden | aria-hidden}
984
+ */
930
985
  hide() {
931
986
  return this.setAttr("hidden", "").setAttr("aria-hidden", "true");
932
987
  }
933
988
  /**
934
- * Shows the element by removing the `hidden` and `aria-hidden` attributes.
989
+ * Shows the Element by removing the `hidden` and `aria-hidden` attributes.
935
990
  *
936
991
  * @returns This instance for chaining.
937
992
  */
938
993
  show() {
939
- return this.rmAttrs("hidden", "aria-hidden");
994
+ return this.rmAttr("hidden", "aria-hidden");
940
995
  }
941
996
  /**
942
- * Disables the element by setting the `disabled` attribute and `aria-disabled="true"`.
997
+ * Disables the Element by setting the `disabled` attribute and `aria-disabled="true"`.
943
998
  *
944
999
  * @returns This instance for chaining.
945
1000
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled | disabled attribute}
@@ -949,49 +1004,18 @@ var JJE = class _JJE extends JJN {
949
1004
  return this.setAttr("disabled", "").setAttr("aria-disabled", "true");
950
1005
  }
951
1006
  /**
952
- * Enables the element by removing the `disabled` and `aria-disabled` attributes.
1007
+ * Enables the Element by removing the `disabled` and `aria-disabled` attributes.
953
1008
  *
954
1009
  * @returns This instance for chaining.
955
1010
  */
956
1011
  enable() {
957
- return this.rmAttrs("disabled", "aria-disabled");
958
- }
959
- /**
960
- * Gets the title attribute.
961
- *
962
- * @returns The title, or null if not set.
963
- */
964
- getTitle() {
965
- return this.getAttr("title");
966
- }
967
- /**
968
- * Sets the title attribute.
969
- *
970
- * @param title - The title to set.
971
- * @returns This instance for chaining.
972
- */
973
- setTitle(title) {
974
- return this.setAttr("title", title);
975
- }
976
- /**
977
- * Sets the id attribute.
978
- *
979
- * @param id - The id to set.
980
- * @returns This instance for chaining.
981
- */
982
- setId(id) {
983
- return this.setAttr("id", id);
1012
+ return this.rmAttr("disabled", "aria-disabled");
984
1013
  }
985
1014
  /**
986
- * Gets the id attribute.
1015
+ * Gets the inner HTML of the Element.
987
1016
  *
988
- * @returns The id, or null if not set.
989
- */
990
- getId() {
991
- return this.getAttr("id");
992
- }
993
- /**
994
- * Gets the inner HTML of the element.
1017
+ * @remarks
1018
+ * This method operates on `innerHTML`. The method name is kept short for convenience.
995
1019
  *
996
1020
  * @returns The inner HTML string.
997
1021
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML | Element.innerHTML}
@@ -1000,18 +1024,22 @@ var JJE = class _JJE extends JJN {
1000
1024
  return this.ref.innerHTML;
1001
1025
  }
1002
1026
  /**
1003
- * Sets the inner HTML of the element.
1027
+ * Sets the inner HTML of the Element.
1028
+ *
1029
+ * @remarks
1030
+ * This method operates on `innerHTML`. The method name is kept short for convenience.
1031
+ * Pass an empty string, `null`, or `undefined` to clear the content.
1004
1032
  *
1005
- * @param html - The HTML string to set.
1033
+ * @param html - The HTML string to set, or null/undefined to clear.
1006
1034
  * @returns This instance for chaining.
1007
1035
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML | Element.innerHTML}
1008
1036
  */
1009
1037
  setHTML(html) {
1010
- this.ref.innerHTML = html;
1038
+ this.ref.innerHTML = html ?? "";
1011
1039
  return this;
1012
1040
  }
1013
1041
  /**
1014
- * Attaches a Shadow DOM to the element and optionally sets its content and styles.
1042
+ * Attaches a Shadow DOM to the Element and optionally sets its content and styles.
1015
1043
  *
1016
1044
  * @remarks
1017
1045
  * We prevent FOUC by assigning the template and CSS in one go.
@@ -1039,7 +1067,7 @@ var JJE = class _JJE extends JJN {
1039
1067
  return this;
1040
1068
  }
1041
1069
  /**
1042
- * Gets a wrapper around the element's Shadow Root, if it exists.
1070
+ * Gets a wrapper around the Element's Shadow Root, if it exists.
1043
1071
  *
1044
1072
  * @returns A JJSR instance wrapping the shadow root, or null if no shadow root exists.
1045
1073
  */
@@ -1048,40 +1076,107 @@ var JJE = class _JJE extends JJN {
1048
1076
  }
1049
1077
  };
1050
1078
 
1051
- // src/JJHE.ts
1052
- var JJHE = class _JJHE extends JJE {
1079
+ // src/JJEx.ts
1080
+ var JJEx = class extends JJE {
1053
1081
  /**
1054
- * Creates a JJHE instance from an HTMLElement reference.
1082
+ * Gets a data attribute from the HTMLElement.
1055
1083
  *
1056
1084
  * @example
1057
1085
  * ```ts
1058
- * const el = JJHE.from(document.getElementById('my-id'))
1086
+ * const value = el.getData('my-key')
1059
1087
  * ```
1060
1088
  *
1061
- * @param ref - The HTMLElement.
1062
- * @returns A new JJHE instance.
1089
+ * @param name - The data attribute name (in camelCase).
1090
+ * @returns The value of the attribute, or undefined if not set.
1091
+ * @throws {TypeError} If `name` is not a string.
1092
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset | HTMLElement.dataset}
1063
1093
  */
1064
- static from(ref) {
1065
- return new _JJHE(ref);
1094
+ getData(name) {
1095
+ if (!isStr(name)) {
1096
+ throw typeErr("name", "a string", name);
1097
+ }
1098
+ return this.ref.dataset[name];
1066
1099
  }
1067
1100
  /**
1068
- * Creates a JJHE instance from a tag name.
1101
+ * Checks if a data attribute exists on the HTMLElement.
1069
1102
  *
1070
1103
  * @example
1071
1104
  * ```ts
1072
- * const div = JJHE.fromTag('div')
1073
- * const input = JJHE.fromTag('input', { is: 'custom-input' })
1105
+ * if (el.hasData('my-key')) {
1106
+ * // ...
1107
+ * }
1074
1108
  * ```
1075
1109
  *
1076
- * @param tagName - The tag name.
1077
- * @param options - Element creation options.
1110
+ * @param name - The data attribute name (in camelCase).
1111
+ * @returns True if the attribute exists, false otherwise.
1112
+ * @throws {TypeError} If `name` is not a string.
1113
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset | HTMLElement.dataset}
1114
+ */
1115
+ hasData(name) {
1116
+ if (!isStr(name)) {
1117
+ throw typeErr("name", "a string", name);
1118
+ }
1119
+ return hasProp(this.ref.dataset, name);
1120
+ }
1121
+ setData(nameOrObj, value) {
1122
+ if (typeof nameOrObj === "string") {
1123
+ this.ref.dataset[nameOrObj] = value;
1124
+ } else if (isObj(nameOrObj)) {
1125
+ for (const [k, v] of Object.entries(nameOrObj)) {
1126
+ this.ref.dataset[k] = v;
1127
+ }
1128
+ } else {
1129
+ throw typeErr("nameOrObj", "a string or object", nameOrObj);
1130
+ }
1131
+ return this;
1132
+ }
1133
+ /**
1134
+ * Removes one or more data attributes from the HTMLElement.
1135
+ *
1136
+ * @example
1137
+ * ```ts
1138
+ * el.rmData('myKey') // Remove single
1139
+ * el.rmData('myKey', 'otherKey') // Remove multiple
1140
+ * ```
1141
+ *
1142
+ * @param names - The data attribute name(s) (in camelCase).
1143
+ * @returns This instance for chaining.
1144
+ * @throws {TypeError} If any name is not a string.
1145
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset | HTMLElement.dataset}
1146
+ */
1147
+ rmData(...names) {
1148
+ for (const name of names) {
1149
+ if (!isStr(name)) {
1150
+ throw typeErr("name", "a string", name);
1151
+ }
1152
+ delete this.ref.dataset[name];
1153
+ }
1154
+ return this;
1155
+ }
1156
+ };
1157
+
1158
+ // src/JJHE.ts
1159
+ var JJHE = class _JJHE extends JJEx {
1160
+ /**
1161
+ * Creates a JJHE instance from an HTMLElement reference.
1162
+ *
1163
+ * @example
1164
+ * ```ts
1165
+ * const el = JJHE.from(document.getElementById('my-id')) // from an existing HTMLElement
1166
+ * const el = JJHE.from(new document.createElement('div')) // from a new HTMLElement
1167
+ * ```
1168
+ *
1169
+ * @param ref - The HTMLElement.
1078
1170
  * @returns A new JJHE instance.
1079
- * @throws {TypeError} If `tagName` is not a string.
1080
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement | document.createElement}
1081
1171
  */
1172
+ static from(ref) {
1173
+ return new _JJHE(ref);
1174
+ }
1082
1175
  static fromTag(tagName, options) {
1083
1176
  if (!isStr(tagName)) {
1084
- throw new TypeError(`Expected a string for tagName. Got: ${tagName} (${typeof tagName})`);
1177
+ throw new TypeError(
1178
+ `JJHE.fromTag() expects tagName to be a string (e.g., 'div', 'button'). Got ${tagName} (${typeof tagName}). Did you mean to use a string literal like 'div'?`
1179
+ );
1085
1180
  }
1086
1181
  return new _JJHE(document.createElement(tagName, options));
1087
1182
  }
@@ -1093,45 +1188,52 @@ var JJHE = class _JJHE extends JJE {
1093
1188
  */
1094
1189
  constructor(ref) {
1095
1190
  if (!isA(ref, HTMLElement)) {
1096
- throw new TypeError(`Expected an HTMLElement. Got ${ref} (${typeof ref})`);
1191
+ throw new TypeError(
1192
+ `JJHE expects an HTMLElement. Got ${ref} (${typeof ref}). If you have a DOM node, use JJHE.from(element). If creating a new element, use JJHE.fromTag('div').`
1193
+ );
1097
1194
  }
1098
1195
  super(ref);
1099
1196
  }
1100
1197
  /**
1101
- * Gets the value property of the element (e.g. for inputs).
1198
+ * Gets the value property of the HTMLElement (e.g. for inputs).
1102
1199
  *
1103
1200
  * @returns The value.
1104
- * @throws {Error} If the element does not have a value property.
1201
+ * @throws {Error} If the HTMLElement does not have a value property.
1105
1202
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/value | HTMLInputElement.value}
1106
1203
  */
1107
1204
  getValue() {
1108
1205
  if (!hasProp(this.ref, "value")) {
1109
- throw new Error("Element does not have a value property");
1206
+ throw new Error(
1207
+ `Cannot get value from <${this.ref.tagName.toLowerCase()}>. The value property only exists on form elements (input, textarea, select). If you need text content, try .getText() instead.`
1208
+ );
1110
1209
  }
1111
1210
  return this.ref.value;
1112
1211
  }
1113
1212
  /**
1114
- * Sets the value property of the element.
1213
+ * Sets the value property of the HTMLElement.
1115
1214
  *
1116
1215
  * @example
1117
1216
  * ```ts
1118
1217
  * input.setValue('new value')
1218
+ * input.setValue(42) // Numbers are automatically converted
1119
1219
  * ```
1120
1220
  *
1121
1221
  * @param value - The value to set.
1122
1222
  * @returns This instance for chaining.
1123
- * @throws {Error} If the element does not have a value property.
1223
+ * @throws {Error} If the HTMLElement does not have a value property.
1124
1224
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/value | HTMLInputElement.value}
1125
1225
  */
1126
1226
  setValue(value) {
1127
1227
  if (!hasProp(this.ref, "value")) {
1128
- throw new Error("Element does not have a value property");
1228
+ throw new Error(
1229
+ `Cannot set value on <${this.ref.tagName.toLowerCase()}>. The value property only exists on form elements (input, textarea, select). If you need to set text content, try .setText() instead.`
1230
+ );
1129
1231
  }
1130
1232
  this.ref.value = value;
1131
1233
  return this;
1132
1234
  }
1133
1235
  /**
1134
- * Focuses the element.
1236
+ * Focuses the HTMLElement.
1135
1237
  *
1136
1238
  * @returns This instance for chaining.
1137
1239
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus | HTMLElement.focus}
@@ -1141,7 +1243,7 @@ var JJHE = class _JJHE extends JJE {
1141
1243
  return this;
1142
1244
  }
1143
1245
  /**
1144
- * Clicks the element.
1246
+ * Clicks the HTMLElement.
1145
1247
  *
1146
1248
  * @returns This instance for chaining.
1147
1249
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click | HTMLElement.click}
@@ -1151,7 +1253,10 @@ var JJHE = class _JJHE extends JJE {
1151
1253
  return this;
1152
1254
  }
1153
1255
  /**
1154
- * Gets the inner text of the element.
1256
+ * Gets the inner text of the HTMLElement.
1257
+ *
1258
+ * @remarks
1259
+ * This method operates on `innerText`. The method name is kept short for convenience.
1155
1260
  *
1156
1261
  * @returns The inner text.
1157
1262
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText | HTMLElement.innerText}
@@ -1160,50 +1265,230 @@ var JJHE = class _JJHE extends JJE {
1160
1265
  return this.ref.innerText;
1161
1266
  }
1162
1267
  /**
1163
- * Sets the inner text of the element.
1268
+ * Sets the inner text of the HTMLElement.
1269
+ *
1270
+ * @remarks
1271
+ * This method operates on `innerText`. The method name is kept short for convenience.
1272
+ * Pass an empty string, `null`, or `undefined` to clear the content.
1273
+ * Numbers and booleans are automatically converted to strings.
1274
+ *
1275
+ * @param text - The text to set, or null/undefined to clear.
1276
+ * @returns This instance for chaining.
1277
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText | HTMLElement.innerText}
1278
+ */
1279
+ setText(text) {
1280
+ this.ref.innerText = text ?? "";
1281
+ return this;
1282
+ }
1283
+ };
1284
+
1285
+ // src/JJT.ts
1286
+ var JJT = class _JJT extends JJN {
1287
+ /**
1288
+ * Creates a JJT instance from a Text node.
1289
+ *
1290
+ * @example
1291
+ * ```ts
1292
+ * const textNode = document.createTextNode('foo')
1293
+ * const text = JJT.from(textNode)
1294
+ * ```
1295
+ *
1296
+ * @param text - The Text node.
1297
+ * @returns A new JJT instance.
1298
+ * @throws {TypeError} If `text` is not a Text node.
1299
+ */
1300
+ static from(text) {
1301
+ return new _JJT(text);
1302
+ }
1303
+ static fromStr(text) {
1304
+ return new _JJT(document.createTextNode(text));
1305
+ }
1306
+ /**
1307
+ * Creates an instance of JJT.
1308
+ *
1309
+ * @example
1310
+ * ```ts
1311
+ * const text = new JJT('Hello World')
1312
+ * ```
1313
+ *
1314
+ * @param ref - The Text node or a string to create a Text node from.
1315
+ * @throws {TypeError} If `ref` is not a Text node or string.
1316
+ */
1317
+ constructor(ref) {
1318
+ if (!isA(ref, Text)) {
1319
+ throw new TypeError(
1320
+ `JJT expects a Text node. Got ${ref} (${typeof ref}). Create a Text node with JJT.fromStr() or document.createTextNode('text').`
1321
+ );
1322
+ }
1323
+ super(ref);
1324
+ }
1325
+ /**
1326
+ * Gets the text content of the Text node.
1327
+ *
1328
+ * @example
1329
+ * ```ts
1330
+ * const content = text.getText()
1331
+ * ```
1332
+ *
1333
+ * @returns The text content.
1334
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
1335
+ */
1336
+ getText() {
1337
+ return this.ref.textContent;
1338
+ }
1339
+ /**
1340
+ * Sets the text content of the Text node.
1341
+ *
1342
+ * @example
1343
+ * ```ts
1344
+ * text.setText('New content')
1345
+ * ```
1346
+ *
1347
+ * @param text - The text to set. Set it to null or undefined to remove all text
1348
+ * @returns This instance for chaining.
1349
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
1350
+ */
1351
+ setText(text) {
1352
+ this.ref.textContent = text ?? null;
1353
+ return this;
1354
+ }
1355
+ /**
1356
+ * Appends text to the existing content.
1357
+ *
1358
+ * @example
1359
+ * ```ts
1360
+ * text.setText('hello')
1361
+ * text.addText(' world')
1362
+ * console.log(text.getText()) // 'hello world'
1363
+ * ```
1364
+ *
1365
+ * @param text - The string to add to the existing contents. If null or undefined, nothing is added.
1366
+ * @returns This instance for chaining.
1367
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
1368
+ */
1369
+ addText(text) {
1370
+ if (text != null) {
1371
+ this.ref.textContent += text;
1372
+ }
1373
+ return this;
1374
+ }
1375
+ /**
1376
+ * Clears the text content of the Text node.
1377
+ *
1378
+ * @example
1379
+ * ```ts
1380
+ * text.empty()
1381
+ * ```
1382
+ *
1383
+ * @returns This instance for chaining.
1384
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
1385
+ */
1386
+ empty() {
1387
+ return this.setText("");
1388
+ }
1389
+ };
1390
+
1391
+ // src/JJD.ts
1392
+ var JJD = class _JJD extends JJNx {
1393
+ /**
1394
+ * Creates a JJD instance from a Document reference.
1395
+ *
1396
+ * @example
1397
+ * ```ts
1398
+ * const doc = JJD.from(document)
1399
+ * ```
1400
+ *
1401
+ * @param ref - The Document instance.
1402
+ * @returns A new JJD instance.
1403
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document | Document}
1404
+ */
1405
+ static from(ref) {
1406
+ return new _JJD(ref);
1407
+ }
1408
+ /**
1409
+ * Creates an instance of JJD.
1164
1410
  *
1165
- * @param text - The text to set.
1166
- * @returns This instance for chaining.
1167
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText | HTMLElement.innerText}
1411
+ * @param ref - The Document instance to wrap.
1412
+ * @throws {TypeError} If `ref` is not a Document.
1168
1413
  */
1169
- setText(text) {
1170
- this.ref.innerText = text;
1171
- return this;
1414
+ constructor(ref) {
1415
+ if (!isA(ref, Document)) {
1416
+ throw new TypeError(`JJD expects a Document instance. Got ${ref} (${typeof ref}). `);
1417
+ }
1418
+ super(ref);
1172
1419
  }
1173
1420
  /**
1174
- * Finds the first element matching a selector within this element's context.
1421
+ * Finds an element by ID within this Document.
1175
1422
  *
1176
- * @param selector - The CSS selector.
1177
- * @param throwIfNotFound - Whether to throw an error if not found. Defaults to true.
1178
- * @returns The wrapped element, or null.
1179
- * @throws {TypeError} If the element is not found and `throwIfNotFound` is true.
1180
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector | Element.querySelector}
1423
+ * @example
1424
+ * ```ts
1425
+ * const el = doc.byId('my-id') // Returns null if not found
1426
+ * const el = doc.byId('my-id', true) // Throws if not found
1427
+ * ```
1428
+ *
1429
+ * @param id - The ID to search for.
1430
+ * @param required - Whether to throw an error if not found. Defaults to false.
1431
+ * @returns The wrapped element, or null if not found and required is false.
1432
+ * @throws {TypeError} If id is not a string or element not found and required is true.
1433
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById | Document.getElementById}
1181
1434
  */
1182
- query(selector, throwIfNotFound = true) {
1183
- const el = this.ref.querySelector(selector);
1435
+ byId(id, required = false) {
1436
+ if (!isStr(id)) {
1437
+ throw typeErr("id", "a string", id);
1438
+ }
1439
+ const el = this.ref.getElementById(id);
1184
1440
  if (el) {
1185
1441
  return JJN.wrap(el);
1186
1442
  }
1187
- if (throwIfNotFound) {
1188
- throw new TypeError(`Element with selector ${selector} not found`);
1443
+ if (required) {
1444
+ throw new TypeError(
1445
+ `Element with id "${id}" not found in the document. Did you mean to call .byId("${id}", false) to return null instead? `
1446
+ );
1189
1447
  }
1190
1448
  return null;
1191
1449
  }
1192
1450
  /**
1193
- * Finds all elements matching a selector within this element's context.
1451
+ * Finds elements by class name in the Document.
1194
1452
  *
1195
- * @param selector - The CSS selector.
1453
+ * @example
1454
+ * ```ts
1455
+ * const items = byClass('list-item')
1456
+ * ```
1457
+ *
1458
+ * @param className - The class name to search for.
1196
1459
  * @returns An array of wrapped elements.
1197
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll | Element.querySelectorAll}
1460
+ * @throws {TypeError} If className is not a string.
1461
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName | Document.getElementsByClassName}
1198
1462
  */
1199
- queryAll(selector) {
1200
- return JJN.wrapAll(this.ref.querySelectorAll(selector));
1463
+ byClass(className) {
1464
+ if (!isStr(className)) {
1465
+ throw typeErr("className", "a string", className);
1466
+ }
1467
+ return JJN.wrapAll(this.ref.getElementsByClassName(className));
1468
+ }
1469
+ /**
1470
+ * Gets the `<head>` element of the document wrapped in a `JJHE` instance.
1471
+ *
1472
+ * @returns The wrapped head element.
1473
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/head | Document.head}
1474
+ */
1475
+ get head() {
1476
+ return JJN.wrap(this.ref.head);
1477
+ }
1478
+ /**
1479
+ * Gets the `<body>` element of the document wrapped in a `JJHE` instance.
1480
+ *
1481
+ * @returns The wrapped body element.
1482
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/body | Document.body}
1483
+ */
1484
+ get body() {
1485
+ return JJN.wrap(this.ref.body);
1201
1486
  }
1202
1487
  };
1203
1488
 
1204
1489
  // src/JJSE.ts
1205
1490
  var SVG_NAMESPACE_URI = "http://www.w3.org/2000/svg";
1206
- var JJSE = class _JJSE extends JJE {
1491
+ var JJSE = class _JJSE extends JJEx {
1207
1492
  /**
1208
1493
  * Creates a JJSE instance from an SVGElement reference.
1209
1494
  *
@@ -1238,7 +1523,9 @@ var JJSE = class _JJSE extends JJE {
1238
1523
  */
1239
1524
  static fromTag(tagName, options) {
1240
1525
  if (!isStr(tagName)) {
1241
- throw new TypeError(`Expected a string for tagName. Got: ${tagName} (${typeof tagName})`);
1526
+ throw new TypeError(
1527
+ `JJSE.fromTag() expects tagName to be a string (e.g., 'circle', 'path'). Got ${tagName} (${typeof tagName}). Did you mean to pass a string literal like 'circle'?`
1528
+ );
1242
1529
  }
1243
1530
  const element = document.createElementNS(SVG_NAMESPACE_URI, tagName, options);
1244
1531
  return new _JJSE(element);
@@ -1251,12 +1538,22 @@ var JJSE = class _JJSE extends JJE {
1251
1538
  */
1252
1539
  constructor(ref) {
1253
1540
  if (!isA(ref, SVGElement)) {
1254
- throw new TypeError(`Expected an SVGElement. Got ${ref} (${typeof ref})`);
1541
+ throw new TypeError(
1542
+ `JJSE expects an SVGElement. Got ${ref} (${typeof ref}). Use JJSE.from(element) with an SVG element, or JJSE.fromTag('circle') to create one.`
1543
+ );
1255
1544
  }
1256
1545
  super(ref);
1257
1546
  }
1258
1547
  /**
1259
- * Gets the text content of the element.
1548
+ * Gets the text content of the SVGElement.
1549
+ *
1550
+ * @remarks
1551
+ * This method operates on `textContent`. The method name is kept short for convenience.
1552
+ *
1553
+ * @example
1554
+ * ```ts
1555
+ * const text = svg.getText()
1556
+ * ```
1260
1557
  *
1261
1558
  * @returns The text content.
1262
1559
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
@@ -1265,18 +1562,35 @@ var JJSE = class _JJSE extends JJE {
1265
1562
  return this.ref.textContent ?? "";
1266
1563
  }
1267
1564
  /**
1268
- * Sets the text content of the element.
1565
+ * Sets the text content of the SVGElement.
1566
+ *
1567
+ * @remarks
1568
+ * This method operates on `textContent`. The method name is kept short for convenience.
1569
+ * Pass an empty string, `null`, or `undefined` to clear the content.
1570
+ * Numbers and booleans are automatically converted to strings.
1269
1571
  *
1270
- * @param text - The text to set.
1572
+ * @example
1573
+ * ```ts
1574
+ * svg.setText('Hello SVG')
1575
+ * svg.setText(null) // Clear content
1576
+ * svg.setText(42) // Numbers are converted
1577
+ * ```
1578
+ *
1579
+ * @param text - The text to set, or null/undefined to clear.
1271
1580
  * @returns This instance for chaining.
1272
1581
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
1273
1582
  */
1274
1583
  setText(text) {
1275
- this.ref.textContent = text;
1584
+ this.ref.textContent = text ?? "";
1276
1585
  return this;
1277
1586
  }
1278
1587
  /**
1279
- * Clears the text content of the element.
1588
+ * Clears the text content of the SVGElement.
1589
+ *
1590
+ * @example
1591
+ * ```ts
1592
+ * svg.empty()
1593
+ * ```
1280
1594
  *
1281
1595
  * @returns This instance for chaining.
1282
1596
  * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent | Node.textContent}
@@ -1380,85 +1694,10 @@ var JJSE = class _JJSE extends JJE {
1380
1694
  }
1381
1695
  };
1382
1696
 
1383
- // src/JJD.ts
1384
- var JJD = class _JJD extends JJN {
1385
- /**
1386
- * Creates a JJD instance from a Document reference.
1387
- *
1388
- * @example
1389
- * ```ts
1390
- * const doc = JJD.from(document)
1391
- * ```
1392
- *
1393
- * @param ref - The Document instance.
1394
- * @returns A new JJD instance.
1395
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document | Document}
1396
- */
1397
- static from(ref) {
1398
- return new _JJD(ref);
1399
- }
1400
- /**
1401
- * Creates an instance of JJD.
1402
- *
1403
- * @param ref - The Document instance to wrap.
1404
- * @throws {TypeError} If `ref` is not a Document.
1405
- */
1406
- constructor(ref) {
1407
- if (!isA(ref, Document)) {
1408
- throw new TypeError(`Expected a Document. Got ${ref} (${typeof ref})`);
1409
- }
1410
- super(ref);
1411
- }
1412
- /**
1413
- * Gets the `<head>` element of the document wrapped in a `JJHE` instance.
1414
- *
1415
- * @returns The wrapped head element.
1416
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/head | Document.head}
1417
- */
1418
- get head() {
1419
- return JJN.wrap(this.ref.head);
1420
- }
1421
- /**
1422
- * Gets the `<body>` element of the document wrapped in a `JJHE` instance.
1423
- *
1424
- * @returns The wrapped body element.
1425
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/body | Document.body}
1426
- */
1427
- get body() {
1428
- return JJN.wrap(this.ref.body);
1429
- }
1430
- /**
1431
- * Sets the document title.
1432
- *
1433
- * @example
1434
- * ```ts
1435
- * JJD.from(document).setTitle('New Page Title')
1436
- * ```
1437
- *
1438
- * @param title - The new title string.
1439
- * @returns This instance for chaining.
1440
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/title | Document.title}
1441
- */
1442
- setTitle(title) {
1443
- this.ref.title = title;
1444
- return this;
1445
- }
1446
- /**
1447
- * Gets the document title.
1448
- *
1449
- * @returns The current title of the document.
1450
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/title | Document.title}
1451
- */
1452
- getTitle() {
1453
- return this.ref.title;
1454
- }
1455
- };
1456
-
1457
- // src/mixins.ts
1458
- var { wrapAll, unwrap, unwrapAll, isWrapable } = JJN;
1459
- function wrap(raw) {
1697
+ // src/JJN-wrap.ts
1698
+ JJN.wrap = function wrap(raw) {
1460
1699
  if (isStr(raw)) {
1461
- return JJT.from(document.createTextNode(raw));
1700
+ return JJT.fromStr(raw);
1462
1701
  }
1463
1702
  if (!isObj(raw)) {
1464
1703
  throw new TypeError(`Expected an object to wrap. Got ${raw} (${typeof raw})`);
@@ -1491,233 +1730,13 @@ function wrap(raw) {
1491
1730
  return JJN.from(raw);
1492
1731
  }
1493
1732
  throw new TypeError(`Expected a Node to wrap. Got ${raw} (${typeof raw})`);
1494
- }
1495
- function byId(id, throwIfNotFound = true) {
1496
- const el = document.getElementById(id);
1497
- if (el) {
1498
- return wrap(el);
1499
- }
1500
- if (throwIfNotFound) {
1501
- throw new TypeError(`Found no element with id ${id} in the document.`);
1502
- }
1503
- return null;
1504
- }
1505
- function byClass(className) {
1506
- return wrapAll(document.getElementsByClassName(className));
1507
- }
1508
- function query(selector, throwIfNotFound = true) {
1509
- const queryResult = document.querySelector(selector);
1510
- if (queryResult) {
1511
- return wrap(queryResult);
1512
- }
1513
- if (throwIfNotFound) {
1514
- throw new TypeError(`Element with selector ${selector} not found`);
1515
- }
1516
- return null;
1517
- }
1518
- function queryAll(selector) {
1519
- return wrapAll(document.querySelectorAll(selector));
1520
- }
1521
- var DDF = {
1522
- /**
1523
- * Finds an element by ID within this Document or DocumentFragment.
1524
- *
1525
- * @example
1526
- * ```ts
1527
- * const el = doc.byId('header')
1528
- * ```
1529
- *
1530
- * @param this - The JJD or JJDF instance.
1531
- * @param id - The ID to search for.
1532
- * @param throwIfNotFound - Whether to throw an error if not found. Defaults to true.
1533
- * @returns The wrapped element, or null if not found and throwIfNotFound is false.
1534
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById | Document.getElementById}
1535
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/getElementById | DocumentFragment.getElementById}
1536
- */
1537
- byId(id, throwIfNotFound = true) {
1538
- const el = this.ref.getElementById(id);
1539
- if (el) {
1540
- return wrap(el);
1541
- }
1542
- if (throwIfNotFound) {
1543
- throw new TypeError(`Element with id ${id} not found`);
1544
- }
1545
- return null;
1546
- }
1547
- };
1548
- var EDDF = {
1549
- /**
1550
- * Finds the first element matching a selector within this element's context.
1551
- *
1552
- * @example
1553
- * ```ts
1554
- * const span = div.query('span')
1555
- * ```
1556
- *
1557
- * @param this - The JJE, JJD or JJDF instance.
1558
- * @param selector - The CSS selector.
1559
- * @param throwIfNotFound - Whether to throw an error if not found. Defaults to true.
1560
- * @returns The wrapped element, or null.
1561
- * @throws {TypeError} If context is invalid or element not found (when requested).
1562
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector | Element.querySelector}
1563
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector | Document.querySelector}
1564
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/querySelector | DocumentFragment.querySelector}
1565
- */
1566
- query(selector, throwIfNotFound = true) {
1567
- const queryResult = this.ref.querySelector(selector);
1568
- if (queryResult) {
1569
- return wrap(queryResult);
1570
- }
1571
- if (throwIfNotFound) {
1572
- throw new TypeError(`Element with selector ${selector} not found`);
1573
- }
1574
- return null;
1575
- },
1576
- /**
1577
- * Finds all elements matching a selector within this element's context.
1578
- *
1579
- * @example
1580
- * ```ts
1581
- * const items = list.queryAll('li')
1582
- * ```
1583
- *
1584
- * @param this - The JJE, JJD or JJDF instance.
1585
- * @param selector - The CSS selector.
1586
- * @returns An array of wrapped elements.
1587
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll | Element.querySelectorAll}
1588
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll | Document.querySelectorAll}
1589
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/querySelectorAll | DocumentFragment.querySelectorAll}
1590
- */
1591
- queryAll(selector) {
1592
- return wrapAll(this.ref.querySelectorAll(selector));
1593
- },
1594
- /**
1595
- * Appends children to this node using native append.
1596
- *
1597
- * @example
1598
- * ```ts
1599
- * myDiv.append(h('span', null, 'hello'))
1600
- * ```
1601
- *
1602
- * @remarks
1603
- * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
1604
- *
1605
- * @param this - The JJE, JJD or JJDF instance.
1606
- * @param children - The children to append.
1607
- * @returns This instance for chaining.
1608
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/append | Element.append}
1609
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/append | Document.append}
1610
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/append | DocumentFragment.append}
1611
- */
1612
- append(...children) {
1613
- const nodes = unwrapAll(children.filter(isWrapable));
1614
- this.ref.append(...nodes);
1615
- return this;
1616
- },
1617
- /**
1618
- * Prepends children to this node using native prepend.
1619
- *
1620
- * @example
1621
- * ```ts
1622
- * div.prepend(h('span', null, 'first'))
1623
- * ```
1624
- *
1625
- * @remarks
1626
- * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
1627
- *
1628
- * @param this - The JJE, JJD or JJDF instance.
1629
- * @param children - The children to prepend.
1630
- * @returns This instance for chaining.
1631
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/prepend | Element.prepend}
1632
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/prepend | Document.prepend}
1633
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/prepend | DocumentFragment.prepend}
1634
- */
1635
- prepend(...children) {
1636
- const nodes = unwrapAll(children.filter(isWrapable));
1637
- this.ref.prepend(...nodes);
1638
- return this;
1639
- },
1640
- /**
1641
- * Replaces the existing children of a node with a specified new set of children.
1642
- *
1643
- * @remarks
1644
- * If no children are provided, it empties the node.
1645
- *
1646
- * @example
1647
- * ```ts
1648
- * div.setChildren(h('p', null, 'New Content'))
1649
- * ```
1650
- *
1651
- * @remarks
1652
- * To make template codes easier, this function ignores any child that is not possible to `wrap()` (e.g. undefined, null, false).
1653
- *
1654
- * @param this - The JJE, JJD or JJDF instance.
1655
- * @param children - The children to replace with.
1656
- * @returns This instance for chaining.
1657
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren | Element.replaceChildren}
1658
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Document/replaceChildren | Document.replaceChildren}
1659
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment/replaceChildren | DocumentFragment.replaceChildren}
1660
- */
1661
- setChildren(...children) {
1662
- const nodes = unwrapAll(children.filter(isWrapable));
1663
- this.ref.replaceChildren(...nodes);
1664
- return this;
1665
- },
1666
- /**
1667
- * Removes all children from this node.
1668
- *
1669
- * @example
1670
- * ```ts
1671
- * div.empty()
1672
- * ```
1673
- *
1674
- * @returns This instance for chaining.
1675
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/replaceChildren | Element.setChildren}
1676
- */
1677
- empty() {
1678
- this.setChildren();
1679
- return this;
1680
- }
1681
1733
  };
1682
- var HESE = {
1683
- getData(name) {
1684
- return this.ref.dataset[name];
1685
- },
1686
- hasData(name) {
1687
- return hasProp(this.ref.dataset, name);
1688
- },
1689
- setData(name, value) {
1690
- this.ref.dataset[name] = value;
1691
- return this;
1692
- },
1693
- setDataObj(obj) {
1694
- for (const [name, value] of Object.entries(obj)) {
1695
- this.setData(name, value);
1696
- }
1697
- return this;
1698
- },
1699
- rmData(name) {
1700
- delete this.ref.dataset[name];
1701
- return this;
1702
- }
1703
- };
1704
- function assignPrototype(Class, ...mixins) {
1705
- for (const mixin of mixins) {
1706
- Object.assign(Class.prototype, mixin);
1707
- }
1708
- }
1709
- JJN.wrap = wrap;
1710
- assignPrototype(JJE, EDDF);
1711
- assignPrototype(JJD, DDF, EDDF);
1712
- assignPrototype(JJDF, DDF, EDDF);
1713
- assignPrototype(JJHE, HESE);
1714
- assignPrototype(JJSE, HESE);
1715
1734
 
1716
1735
  // src/helpers.ts
1717
1736
  function h(tagName, attributes, ...children) {
1718
1737
  const ret = JJHE.fromTag(tagName).append(...children);
1719
1738
  if (attributes) {
1720
- ret.setAttrs(attributes);
1739
+ ret.setAttr(attributes);
1721
1740
  }
1722
1741
  return ret;
1723
1742
  }
@@ -1737,28 +1756,28 @@ function linkAs(href) {
1737
1756
  throw new Error(`No 'as' attribute was specified and we failed to guess it from the URL: ${href}`);
1738
1757
  }
1739
1758
  }
1740
- function createLinkPre(rel, href, as) {
1759
+ function createLinkPre(href, rel, as) {
1741
1760
  if (!isStr(href)) {
1742
1761
  if (!isA(href, URL)) {
1743
- throw new TypeError(`Expected a string or URL. Got ${href} (${typeof href})`);
1762
+ throw typeErr("href", "a string or URL", href);
1744
1763
  }
1745
1764
  href = href.toString();
1746
1765
  }
1747
1766
  if (!["prefetch", "preload"].includes(rel)) {
1748
- throw new RangeError(`rel should be one of 'prefetch' or 'preload'. Got ${rel} (${typeof rel})`);
1767
+ throw new RangeError(errMsg("rel", `'prefetch' or 'preload'`, rel));
1749
1768
  }
1750
1769
  if (!as) {
1751
1770
  as = linkAs(href);
1752
1771
  if (!as) {
1753
- throw new Error(`No 'as' attribute was specified and we failed to guess it from the URL: ${href}`);
1772
+ throw new Error(`Could not guess 'as' attribute from URL: ${href}`);
1754
1773
  }
1755
1774
  }
1756
1775
  if (!["fetch", "style", "script"].includes(as)) {
1757
- throw new RangeError(`as should be one of 'fetch' or 'style'. Got ${as} (${typeof as})`);
1776
+ throw new RangeError(errMsg("as", `'fetch', 'style', or 'script'`, as));
1758
1777
  }
1759
- return JJHE.fromTag("link").setAttrs({
1760
- rel,
1778
+ return JJHE.fromTag("link").setAttr({
1761
1779
  href,
1780
+ rel,
1762
1781
  as
1763
1782
  });
1764
1783
  }
@@ -1805,7 +1824,7 @@ async function templatePromise(templateConfig) {
1805
1824
  if (isA(templateConfig, HTMLElement)) {
1806
1825
  return templateConfig.outerHTML;
1807
1826
  }
1808
- throw new TypeError(`Expected a string, JJHE or HTMLElement. Got ${templateConfig} (${typeof templateConfig})`);
1827
+ throw new TypeError(`Expected template to be a string, JJHE, or HTMLElement. Got ${typeof templateConfig}`);
1809
1828
  }
1810
1829
  async function stylePromise(styleConfig) {
1811
1830
  if (isFn(styleConfig)) {
@@ -1818,7 +1837,7 @@ async function stylePromise(styleConfig) {
1818
1837
  if (isStr(styleConfig)) {
1819
1838
  return await cssToStyle(styleConfig);
1820
1839
  }
1821
- throw new TypeError(`Expected a css string or CSSStyleSheet. Got ${styleConfig} (${typeof styleConfig})`);
1840
+ throw new TypeError(`Expected style to be a CSS string or CSSStyleSheet. Got ${typeof styleConfig}`);
1822
1841
  }
1823
1842
  function stylePromises(styleConfigs) {
1824
1843
  if (!isArr(styleConfigs)) {
@@ -1912,20 +1931,25 @@ function attr2prop(instance, name, oldValue, newValue) {
1912
1931
  }
1913
1932
  async function registerComponent(name, constructor, options) {
1914
1933
  if (!isStr(name)) {
1915
- throw new TypeError(`Expected a string name. Got ${name} (${typeof name})`);
1934
+ throw typeErr("name", "a string", name);
1916
1935
  }
1917
1936
  if (!isFn(constructor)) {
1918
- throw new TypeError(`Expected a constructor function. Got ${constructor} (${typeof constructor})`);
1937
+ throw typeErr("constructor", "a function", constructor);
1919
1938
  }
1920
1939
  if (!customElements.get(name)) {
1921
1940
  customElements.define(name, constructor, options);
1922
1941
  await customElements.whenDefined(name);
1923
1942
  }
1924
1943
  }
1944
+
1945
+ // src/index.ts
1946
+ var doc = JJD.from(document);
1947
+ var index_default = doc;
1925
1948
  export {
1926
1949
  JJD,
1927
1950
  JJDF,
1928
1951
  JJE,
1952
+ JJET,
1929
1953
  JJHE,
1930
1954
  JJN,
1931
1955
  JJSE,
@@ -1934,30 +1958,20 @@ export {
1934
1958
  ShadowMaster,
1935
1959
  addLinkPre,
1936
1960
  attr2prop,
1937
- byClass,
1938
- byId,
1939
1961
  createLinkPre,
1940
1962
  cssToStyle,
1963
+ index_default as default,
1941
1964
  fetchCss,
1942
1965
  fetchHtml,
1943
1966
  fetchStyle,
1944
1967
  fetchText,
1945
1968
  fileExt,
1946
1969
  h,
1947
- isWrapable,
1948
1970
  keb2cam,
1949
1971
  keb2pas,
1950
1972
  nextAnimationFrame,
1951
- off,
1952
- on,
1953
1973
  pas2keb,
1954
- query,
1955
- queryAll,
1956
1974
  registerComponent,
1957
- sleep,
1958
- unwrap,
1959
- unwrapAll,
1960
- wrap,
1961
- wrapAll
1975
+ sleep
1962
1976
  };
1963
1977
  //# sourceMappingURL=bundle.js.map