jj 2.8.0 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SKILL.md CHANGED
@@ -60,6 +60,8 @@ const nav = h(
60
60
 
61
61
  // Append to document body
62
62
  doc.body.ref.append(nav.ref)
63
+ // Or using the wrapper API
64
+ doc.body.addChild(nav.ref)
63
65
  ```
64
66
 
65
67
  For batch DOM operations, use `JJDF` (DocumentFragment) to avoid multiple reflows:
@@ -173,6 +175,20 @@ el.style('background-color', 'blue').style('padding', '10px')
173
175
  el.setAria('hidden', 'true').rmAria('label')
174
176
  ```
175
177
 
178
+ Node traversal and detach helpers on `JJN`:
179
+
180
+ ```typescript
181
+ const item = doc.find('#item', true)
182
+ const parent = item.parent // wrapped parent or null
183
+ const children = item.children // wrapped child nodes
184
+
185
+ children.forEach((child) => {
186
+ console.log(child.ref)
187
+ })
188
+
189
+ item.rm() // detach from its current parent
190
+ ```
191
+
176
192
  ### 3. Type-Safe Element Creation
177
193
 
178
194
  JJ leverages TypeScript generics to ensure type safety and prevent LLM hallucinations:
@@ -614,8 +630,10 @@ Output: `doc/` folder with HTML documentation
614
630
  1. **Accessing the Native Node**: Always use `.ref` to access the underlying DOM node for operations not exposed by JJ
615
631
  2. **Event Listeners**: Use `.on()` and `.off()` for proper cleanup. Event handlers are automatically bound to the JJ\* instance, so `this` refers to the wrapper, not the DOM element. Use `function` instead of arrow functions (`=>`) for `.bind()` to work correctly. Use `this.ref` to access the native element.
616
632
  3. **Type Safety**: Use `JJHE.create()` for automatic type inference instead of generic parameters
617
- 4. **Fragments**: Use JJDF for batch operations before appending
618
- 5. **Error Messages**: Read them carefully—they suggest the correct approach
633
+ 4. **Tree Navigation**: Use `node.parent` and `node.children` to stay in JJ wrappers while traversing the DOM tree
634
+ 5. **Detaching Nodes**: Use `node.rm()` instead of reaching for native removal APIs unless you specifically need them
635
+ 6. **Fragments**: Use JJDF for batch operations before appending
636
+ 7. **Error Messages**: Read them carefully—they suggest the correct approach
619
637
 
620
638
  ## Anti-patterns to Avoid
621
639
 
package/lib/bundle.cjs CHANGED
@@ -463,6 +463,44 @@ var JJN = class _JJN extends JJET {
463
463
  }
464
464
  super(ref);
465
465
  }
466
+ /**
467
+ * Gets the parent node wrapped in the most specific JJ wrapper available.
468
+ *
469
+ * @remarks
470
+ * Returns `null` when this node is detached and therefore has no parent.
471
+ *
472
+ * @example
473
+ * ```ts
474
+ * const text = JJT.fromStr('hello')
475
+ * JJHE.create('div').addChild(text)
476
+ * const parent = text.parent // JJHE
477
+ * ```
478
+ *
479
+ * @returns The wrapped parent node, or `null` if this node has no parent.
480
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode | Node.parentNode}
481
+ */
482
+ get parent() {
483
+ const { parentNode } = this.ref;
484
+ return parentNode ? _JJN.wrap(parentNode) : null;
485
+ }
486
+ /**
487
+ * Gets the child nodes wrapped in the most specific JJ wrappers available.
488
+ *
489
+ * @remarks
490
+ * Returns an empty array when this node has no children.
491
+ *
492
+ * @example
493
+ * ```ts
494
+ * const el = JJHE.create('div').addChild('hello', JJHE.create('span'))
495
+ * const children = el.children // [JJT, JJHE]
496
+ * ```
497
+ *
498
+ * @returns The wrapped child nodes.
499
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes | Node.childNodes}
500
+ */
501
+ get children() {
502
+ return _JJN.wrapAll(this.ref.childNodes);
503
+ }
466
504
  /**
467
505
  * Clones the Node.
468
506
  *
@@ -473,6 +511,29 @@ var JJN = class _JJN extends JJET {
473
511
  clone(deep) {
474
512
  return _JJN.wrap(this.ref.cloneNode(deep));
475
513
  }
514
+ /**
515
+ * Removes this node from its parent.
516
+ *
517
+ * @remarks
518
+ * If the node has no parent, this method does nothing.
519
+ *
520
+ * @example
521
+ * ```ts
522
+ * const el = JJHE.create('div')
523
+ * doc.body.addChild(el)
524
+ * el.rm()
525
+ * ```
526
+ *
527
+ * @returns This instance for chaining.
528
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild | Node.removeChild}
529
+ */
530
+ rm() {
531
+ const { parentNode } = this.ref;
532
+ if (parentNode) {
533
+ parentNode.removeChild(this.ref);
534
+ }
535
+ return this;
536
+ }
476
537
  /**
477
538
  * Creates a Text node from a string and appends it to this Node.
478
539
  *