1414 * You should have received a copy of the GNU Lesser General Public License along with @cldn/components.
1515 * If not, see <https://www.gnu.org/licenses/>.
1616 */
17+ import { NodeComponent } from "./NodeComponent.js" ;
1718
1819/**
1920 * Non-readonly non-method keys
2021 */
21- type WritableKeys < T > = Extract <
22- {
23- [ Prop in keyof T ] : (
24- ( < G > ( ) => G extends Pick < T , Prop > ? 1 : 2 ) extends
25- ( < G > ( ) => G extends Record < Prop , T [ Prop ] > ? 1 : 2 )
26- ? true
27- : false
22+ type WritableKeys < T > = {
23+ [ Prop in keyof T ] : (
24+ ( < G > ( ) => G extends Pick < T , Prop > ? 1 : 2 ) extends (
25+ < G > ( ) => G extends Record < Prop , T [ Prop ] > ? 1 : 2
26+ ) ? true : false
2827 ) extends false
2928 ? never
30- : Prop ;
31- } [ keyof T ] ,
32- {
33- [ K in keyof T ] : T [ K ] extends Function ? never : K ;
34- } [ keyof T ]
35- > ;
29+ : ( T [ Prop ] extends Function | null | undefined ? never : Prop ) ;
30+ } [ keyof T ] ;
31+
32+ /**
33+ * Non-method keys
34+ */
35+ type ReadableKeys < T > = {
36+ [ Prop in keyof T ] : T [ Prop ] extends Function | null | undefined ? never : Prop ;
37+ } [ keyof T ] ;
3638
3739
3840/**
3941 * An {@link !Element} component
4042 * @typeParam T Component element type
4143 */
42- export abstract class BaseComponent < T extends Element > {
43- /**
44- * This component's element
45- */
46- public readonly element : T ;
47-
44+ export abstract class ElementComponent < T extends Element > extends NodeComponent < T > {
4845 /**
4946 * @param element Initial element for this component
5047 * @protected
5148 */
5249 protected constructor ( element : T ) {
53- this . element = element ;
54- }
55-
56- /**
57- * Insert component after the last child
58- */
59- public append ( ...components : BaseComponent < any > [ ] ) {
60- components . forEach ( ( component ) => this . element . appendChild ( component . element ) )
61- return this ;
50+ super ( element ) ;
6251 }
6352
6453 /**
6554 * Insert component before the first child
6655 */
67- public prepend ( ...components : BaseComponent < any > [ ] ) {
68- components . forEach ( ( component ) => this . element . prepend ( component . element ) )
56+ public prepend ( ...components : NodeComponent < any > [ ] ) {
57+ components . forEach ( ( component ) => this . node . prepend ( component . node ) )
6958 return this ;
7059 }
7160
7261 /**
7362 * Add classes
7463 */
7564 public class ( ...classes : string [ ] ) {
76- this . element . classList . add ( ...classes . flatMap ( c => c . split ( " " ) ) ) ;
65+ this . node . classList . add ( ...classes . flatMap ( c => c . split ( " " ) ) ) ;
7766 return this ;
7867 }
7968
8069 /**
8170 * Remove classes
8271 */
8372 public removeClass ( ...classes : string [ ] ) {
84- this . element . classList . remove ( ...classes . flatMap ( c => c . split ( " " ) ) ) ;
73+ this . node . classList . remove ( ...classes . flatMap ( c => c . split ( " " ) ) ) ;
8574 return this ;
8675 }
8776
@@ -90,7 +79,7 @@ export abstract class BaseComponent<T extends Element> {
9079 */
9180 public toggleClass ( ...classes : string [ ] ) {
9281 for ( const c of new Set ( classes . flatMap ( c => c . split ( " " ) ) ) )
93- this . element . classList . toggle ( c ) ;
82+ this . node . classList . toggle ( c ) ;
9483 return this ;
9584 }
9685
@@ -115,7 +104,7 @@ export abstract class BaseComponent<T extends Element> {
115104 * @returns true if component has all the specified classes
116105 */
117106 public hasClass ( ...classes : string [ ] ) {
118- return classes . every ( c => this . element . classList . contains ( c ) ) ;
107+ return classes . every ( c => this . node . classList . contains ( c ) ) ;
119108 }
120109
121110 /**
@@ -124,7 +113,7 @@ export abstract class BaseComponent<T extends Element> {
124113 * @param [value] attribute value
125114 */
126115 public attr ( name : string , value ?: string ) {
127- this . element . setAttribute ( name , value ?? "" ) ;
116+ this . node . setAttribute ( name , value ?? "" ) ;
128117 return this ;
129118 }
130119
@@ -133,23 +122,15 @@ export abstract class BaseComponent<T extends Element> {
133122 * @param name attribute name
134123 */
135124 public removeAttr ( name : string ) {
136- this . element . removeAttribute ( name ) ;
137- return this ;
138- }
139-
140- /**
141- * Set text content
142- */
143- public text ( text : string ) {
144- this . element . textContent = text ;
125+ this . node . removeAttribute ( name ) ;
145126 return this ;
146127 }
147128
148129 /**
149130 * Set inner HTML
150131 */
151132 public html ( html : string ) {
152- this . element . innerHTML = html ;
133+ this . node . innerHTML = html ;
153134 return this ;
154135 }
155136
@@ -159,41 +140,37 @@ export abstract class BaseComponent<T extends Element> {
159140 * @param value property value
160141 */
161142 public set < K extends WritableKeys < T > > ( name : K , value : T [ K ] ) {
162- this . element [ name ] = value ;
143+ this . node [ name ] = value ;
163144 return this ;
164145 }
165146
166147 /**
167148 * Get element property
168149 * @param name property name
169150 */
170- public get < K extends WritableKeys < T > > ( name : K ) : T [ K ] {
171- return this . element [ name ] ;
151+ public get < K extends ReadableKeys < T > > ( name : K ) : T [ K ] {
152+ return this . node [ name ] ;
172153 }
173154
174155 /**
175156 * Remove the element
176157 */
177158 public remove ( ) : this {
178- this . element . remove ( ) ;
159+ this . node . remove ( ) ;
179160 return this ;
180161 }
181162
182- /**
183- * Add event listener
184- * @param type
185- * @param listener
186- * @param options
187- */
188- public on < K extends keyof ElementEventMap > ( type : K , listener : ( ev : ElementEventMap [ K ] , component : this) => any , options ?: boolean | AddEventListenerOptions ) {
189- this . element . addEventListener ( type , e => listener ( e , this ) , options ) ;
190- return this ;
163+ public override on < K extends keyof ElementEventMap > ( type : K , listener : ( ev : ElementEventMap [ K ] , component : this) => any ) : typeof this ;
164+ public override on < K extends keyof ElementEventMap > ( type : K , listener : ( ev : ElementEventMap [ K ] , component : this) => any , options : AddEventListenerOptions ) : typeof this ;
165+ public override on < K extends keyof ElementEventMap > ( type : K , listener : ( ev : ElementEventMap [ K ] , component : this) => any , useCapture : boolean ) : typeof this ;
166+ public override on < K extends keyof ElementEventMap > ( type : K , listener : ( ev : ElementEventMap [ K ] , component : this) => any , c ?: boolean | AddEventListenerOptions ) : typeof this {
167+ return super . on ( type as any , listener , c as any ) ;
191168 }
192169
193170 /**
194171 * Get this component's outer HTML
195172 */
196- public toString ( ) {
197- return this . element . outerHTML ;
173+ public override toString ( ) {
174+ return this . node . outerHTML ;
198175 }
199176}
0 commit comments