Skip to content

Commit 478c4a2

Browse files
committed
closest(), clone(), before(), after(), isVisible(), boundingClientRect()
1 parent 9d40cc2 commit 478c4a2

File tree

6 files changed

+78
-0
lines changed

6 files changed

+78
-0
lines changed

src/Component.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,18 @@ export class Component<T extends HTMLElement = HTMLElement> extends ElementCompo
7777
return [...this.node.querySelectorAll<T>(selectors)].map(e => new Component<T>(e));
7878
}
7979

80+
/**
81+
* Traverse the component and its parents (heading toward the document root) until it finds a component that matches
82+
* the specified {@link https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors CSS selector}.
83+
* @param selectors
84+
* @typeParam T Component element type
85+
*/
86+
public closest<T extends HTMLElement = HTMLElement>(selectors: string): Component<T> | null {
87+
const element = this.node.closest<T>(selectors);
88+
if (element == null) return null;
89+
return new Component<T>(element);
90+
}
91+
8092
/**
8193
* Set style property
8294
* @param name Property name
@@ -113,6 +125,10 @@ export class Component<T extends HTMLElement = HTMLElement> extends ElementCompo
113125
return this;
114126
}
115127

128+
public override clone(deep = true) {
129+
return new Component<T>(this.node.cloneNode(deep) as T);
130+
}
131+
116132
public override on<K extends keyof HTMLElementEventMap>(type: K, listener: (ev: HTMLElementEventMap[K], component: this) => any): typeof this;
117133
public override on<K extends keyof HTMLElementEventMap>(type: K, listener: (ev: HTMLElementEventMap[K], component: this) => any, options: AddEventListenerOptions): typeof this;
118134
public override on<K extends keyof HTMLElementEventMap>(type: K, listener: (ev: HTMLElementEventMap[K], component: this) => any, useCapture: boolean): typeof this;

src/DocumentComponent.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@ export class DocumentComponent extends NodeComponent<DocumentFragment> {
4444
component.slot(idPrefix + index, doc.node);
4545
return doc;
4646
}
47+
48+
public override clone(deep = true) {
49+
const doc = new DocumentComponent();
50+
const node = this.node.cloneNode(deep);
51+
doc.node.append(node);
52+
return doc;
53+
}
4754
}

src/ElementComponent.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,25 @@ export abstract class ElementComponent<T extends Element> extends NodeComponent<
5858
return this;
5959
}
6060

61+
/**
62+
* Insert components in the children list of this `ElementComponent`’s parent, just before this `ElementComponent`.
63+
* @param components Components to insert
64+
*/
65+
public before(...components: NodeComponent<any>[]) {
66+
this.node.before(...components.map(c => c.node));
67+
return this;
68+
}
69+
70+
/**
71+
* Insert components in the children list of this `ElementComponent`’s parent, just after this `ElementComponent`.
72+
* @param components Components to insert
73+
*/
74+
public after(...components: NodeComponent<any>[]) {
75+
this.node.after(...components.map(c => c.node));
76+
return this;
77+
}
78+
79+
6180
/**
6281
* Add classes
6382
*/
@@ -162,6 +181,23 @@ export abstract class ElementComponent<T extends Element> extends NodeComponent<
162181
return this.node[name];
163182
}
164183

184+
/**
185+
* Check whether the component is visible.
186+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/checkVisibility Element: checkVisibility() - MDN}
187+
*/
188+
public isVisible() {
189+
return this.node.checkVisibility();
190+
}
191+
192+
/**
193+
* Get a {@link !DOMRect} object providing information about the size of a component and its position relative to
194+
* the {@link https://developer.mozilla.org/en-US/docs/Glossary/Viewport viewport}.
195+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect Element: getBoundingClientRect() - MDN}
196+
*/
197+
public boundingClientRect() {
198+
return this.node.getBoundingClientRect();
199+
}
200+
165201
/**
166202
* Remove the element
167203
*/

src/NodeComponent.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ export abstract class NodeComponent<T extends Node> {
5858
return this;
5959
}
6060

61+
/**
62+
* Clone this component. Event listeners are not cloned.
63+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode Node: cloneNode() - MDN}
64+
* @param [deep] Whether to clone the whole subtree.
65+
* @returns A duplicate of this component.
66+
*/
67+
public abstract clone(deep?: boolean): NodeComponent<T>;
68+
6169
/**
6270
* Add event listener
6371
* @param type A case-sensitive string representing the event type to listen for.

src/SvgComponent.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,8 @@ export class SvgComponent extends ElementComponent<SVGSVGElement> {
3030
public static from(svg: string) {
3131
return new SvgComponent(document.createRange().createContextualFragment(svg).children[0] as SVGSVGElement);
3232
}
33+
34+
public override clone(deep = true) {
35+
return new SvgComponent(this.node.cloneNode(deep) as SVGSVGElement);
36+
}
3337
}

src/TextComponent.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ export class TextComponent extends NodeComponent<Text> {
3737
throw new DOMException(`NodeComponent.append: Cannot add children to a ${this.constructor.name}`);
3838
}
3939

40+
/**
41+
* Clone this text component.
42+
*/
43+
public override clone() {
44+
return new TextComponent(this.node.cloneNode() as Text);
45+
}
46+
4047
/**
4148
* Get the text content
4249
*/

0 commit comments

Comments
 (0)