luciddom 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +30 -5
  2. package/lucidDOM.js +797 -0
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -2,9 +2,17 @@
2
2
 
3
3
  LucidDOM.js is a lightweight browser-side DOM helper. It wraps a parent element and provides methods for creating elements, selecting descendants, updating content, handling events, applying inline styles, and removing elements.
4
4
 
5
- ## Quick start
5
+ ## Installation
6
6
 
7
- Copy `lucidDOM.js` into your project and import its default export from a JavaScript module:
7
+ ### npm
8
+
9
+ Install LucidDOM from npm:
10
+
11
+ ```sh
12
+ npm install luciddom
13
+ ```
14
+
15
+ Import the default export in your app. Use a bundler that resolves npm packages:
8
16
 
9
17
  ```html
10
18
  <div id="app"></div>
@@ -13,7 +21,7 @@ Copy `lucidDOM.js` into your project and import its default export from a JavaSc
13
21
 
14
22
  ```js
15
23
  // app.js
16
- import LucidDOM from './lucidDOM.js';
24
+ import LucidDOM from 'luciddom';
17
25
 
18
26
  const app = new LucidDOM(document.querySelector('#app'));
19
27
 
@@ -26,6 +34,23 @@ const message = app.addElement({
26
34
  message.styles({ color: 'darkslateblue', fontWeight: 'bold' });
27
35
  ```
28
36
 
37
+ ### unpkg CDN
38
+
39
+ For a browser module without an npm install or bundler, import the package directly from unpkg:
40
+
41
+ ```html
42
+ <div id="app"></div>
43
+ <script type="module">
44
+ import LucidDOM from 'https://unpkg.com/luciddom@1.0.1/lucidDOM.js';
45
+
46
+ const app = new LucidDOM(document.querySelector('#app'));
47
+ app.addElement({
48
+ tag: 'p',
49
+ value: 'Hello from LucidDOM!'
50
+ });
51
+ </script>
52
+ ```
53
+
29
54
  The constructor accepts a DOM element and scopes queries and element creation to it. If no parent is passed, it defaults to `document.body`.
30
55
 
31
56
  ## Common operations
@@ -114,14 +139,14 @@ When nothing matches, `current` is an empty NodeList and helper methods do nothi
114
139
 
115
140
  ## Build
116
141
 
117
- The package includes an esbuild script to create a minified ES module bundle:
142
+ The package includes an esbuild script to create a minified browser bundle:
118
143
 
119
144
  ```sh
120
145
  npm install
121
146
  npm run build
122
147
  ```
123
148
 
124
- The output is written to `dist/lucid.min.js`.
149
+ The output is written to `dist/luciddom.min.js`.
125
150
 
126
151
  ## Documentation
127
152
 
package/lucidDOM.js ADDED
@@ -0,0 +1,797 @@
1
+ /**
2
+ * A lightweight DOM helper that wraps a parent element and exposes fluent
3
+ * methods for creating, selecting, styling, and removing elements.
4
+ *
5
+ * @example
6
+ * const app = new LucidDOM(document.querySelector('#root'));
7
+ *
8
+ * const header = app.select('header');
9
+ * header.update({ className: 'love' });
10
+ * header.styles({ backgroundColor: 'red' });
11
+ * header.on('click', () => console.log('clicked'));
12
+ */
13
+
14
+ class LucidDOM{
15
+ constructor(parent = document.querySelector('body')){
16
+ this.parent = parent;
17
+ this.element;
18
+ }
19
+
20
+ /**
21
+ * Creates an HTML element, applies attributes, appends it to the parent,
22
+ * and returns a small handle for interacting with the created element.
23
+ *
24
+ * @param {Object} options
25
+ * @param {string} options.tag - Tag name of the element to create (e.g. 'div', 'input').
26
+ * @param {string} [options.className] - Value for the element's `class` attribute.
27
+ * @param {string} [options.id] - Value for the element's `id` attribute.
28
+ * @param {string} [options.value] - Text content / value for the element.
29
+ * @param {string} [options.type] - `type` attribute (mainly for `<input>`).
30
+ * @param {string} [options.placeholder] - `placeholder` attribute (mainly for `<input>` / `<textarea>`).
31
+ * @param {string} [options.name] - `name` attribute.
32
+ * @param {string} [options.htmlFor] - `for` attribute (mainly for `<label>`).
33
+ * @param {string} [options.formAction] - `formaction` attribute (mainly for `<button>` / `<input>`).
34
+ * @param {string} [options.formMethod] - `formmethod` attribute (mainly for `<button>` / `<input>`).
35
+ * @param {string} [options.formTarget] - `formtarget` attribute (mainly for `<button>` / `<input>`).
36
+ * @param {string} [options.formEnctype] - `formenctype` attribute (mainly for `<button>` / `<input>`).
37
+ * @param {boolean} [options.formNoValidate] - `formnovalidate` attribute (mainly for `<button>` / `<input>`).
38
+ * @param {string} [options.ariaLabel] - Value for the `aria-label` attribute.
39
+ * @param {string} [options.title] - `title` attribute.
40
+ * @param {string} [options.html] - Raw HTML to inject via `innerHTML`.
41
+ *
42
+ * @returns {{
43
+ * on: (event?: string, callback?: (e: Event) => void) => void,
44
+ * addChildren: (attrs?: {
45
+ * className?: string,
46
+ * id?: string,
47
+ * value?: string,
48
+ * type?: string,
49
+ * placeholder?: string,
50
+ * name?: string,
51
+ * htmlFor?: string,
52
+ * formAction?: string,
53
+ * formMethod?: string,
54
+ * formTarget?: string,
55
+ * formEnctype?: string,
56
+ * formNoValidate?: boolean,
57
+ * ariaLabel?: string,
58
+ * title?: string,
59
+ * html?: string}),
60
+ * off: (event?: string, callback?: (e: Event) => void) => void,
61
+ * styles: (styles?: Partial<CSSStyleDeclaration>) => void,
62
+ * remove: () => void
63
+ * }} A handle exposing event, style, and removal helpers for the created element.
64
+ *
65
+ * @throws {Error} If element creation or attribute assignment fails
66
+ * (wraps a generic {@link DOMException}).
67
+ *
68
+ * @example
69
+ * const div = app.addElement({
70
+ * tag: 'div',
71
+ * className: 'card',
72
+ * value: 'Hello',
73
+ * html: '<strong>Hello</strong>'
74
+ * });
75
+ * div.styles({ padding: '8px', backgroundColor: 'red' });
76
+ * div.on('click', () => console.log('clicked'));
77
+ */
78
+ addElement({tag, className,id, value,type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html}){
79
+
80
+ try{
81
+ // ATTRIBUTES
82
+ this.element = document.createElement(tag);
83
+ className?this.element.className = className: '';
84
+ type?this.element.type = type: '';
85
+ value?this.element.innerText = value : '';
86
+ this.element.value = value;
87
+ id?this.element.id = id: '';
88
+ html?this.element.innerHTML = html: '';
89
+ placeholder? this.element.placeholder = placeholder: '';
90
+ this.element.name = name;
91
+ title?this.element.title = title: '';
92
+ ariaLabel?this.element.ariaLabel = ariaLabel: '';
93
+ this.element.htmlFor = htmlFor;
94
+ formAction?this.element.formAction = formAction: '';
95
+ formEnctype?this.element.formEnctype = formEnctype: '';
96
+ formMethod?this.element.formMethod =formMethod: '';
97
+ formTarget?this.element.formTarget = formTarget: '';
98
+ formNoValidate?this.element.formNoValidate =formNoValidate: '';
99
+
100
+
101
+
102
+
103
+ // APPENDING ELEMENT TO PARENT
104
+ this.parent.appendChild(this.element);
105
+
106
+
107
+
108
+ return{
109
+ on: (event = '', callback = () => {}) =>{
110
+ this.element.addEventListener(event, callback);
111
+
112
+ },
113
+
114
+ off: (event = '', callback = () => {}) => {
115
+ this.element.removeEventListener(event, callback)
116
+ },
117
+
118
+ styles : (styles = {}) => {
119
+ Object.assign(this.element.style, styles)
120
+ },
121
+ remove: ()=> {
122
+ this.element.remove();
123
+ },
124
+
125
+ /**
126
+ * Creates an HTML element, applies attributes, appends it to the parent,
127
+ * and returns a small handle for interacting with the created element.
128
+ *
129
+ * @param {Object} options
130
+ * @param {string} options.tag - Tag name of the element to create (e.g. 'div', 'input').
131
+ * @param {string} [options.className] - Value for the element's `class` attribute.
132
+ * @param {string} [options.id] - Value for the element's `id` attribute.
133
+ * @param {string} [options.value] - Text content / value for the element.
134
+ * @param {string} [options.type] - `type` attribute (mainly for `<input>`).
135
+ * @param {string} [options.placeholder] - `placeholder` attribute (mainly for `<input>` / `<textarea>`).
136
+ * @param {string} [options.name] - `name` attribute.
137
+ * @param {string} [options.htmlFor] - `for` attribute (mainly for `<label>`).
138
+ * @param {string} [options.formAction] - `formaction` attribute (mainly for `<button>` / `<input>`).
139
+ * @param {string} [options.formMethod] - `formmethod` attribute (mainly for `<button>` / `<input>`).
140
+ * @param {string} [options.formTarget] - `formtarget` attribute (mainly for `<button>` / `<input>`).
141
+ * @param {string} [options.formEnctype] - `formenctype` attribute (mainly for `<button>` / `<input>`).
142
+ * @param {boolean} [options.formNoValidate] - `formnovalidate` attribute (mainly for `<button>` / `<input>`).
143
+ * @param {string} [options.ariaLabel] - Value for the `aria-label` attribute.
144
+ * @param {string} [options.title] - `title` attribute.
145
+ * @param {string} [options.html] - Raw HTML to inject via `innerHTML`.
146
+ *
147
+ * @returns {{
148
+ * on: (event?: string, callback?: (e: Event) => void) => void,
149
+ * off: (event?: string, callback?: (e: Event) => void) => void,
150
+ * styles: (styles?: Partial<CSSStyleDeclaration>) => void,
151
+ * remove: () => void
152
+ * }} A handle exposing event, style, and removal helpers for the created element.
153
+ *
154
+ * @throws {Error} If element creation or attribute assignment fails
155
+ * (wraps a generic {@link DOMException}).
156
+ *
157
+ * @example
158
+ * const div = app.addElement({
159
+ * tag: 'div',
160
+ * className: 'card',
161
+ * value: 'Hello',
162
+ * html: '<strong>Hello</strong>'
163
+ * });
164
+ * div.styles({ padding: '8px', backgroundColor: 'red' });
165
+ * div.on('click', () => console.log('clicked'));
166
+ */
167
+ addChildren: ({tag, className,id, value,type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html}) =>{
168
+
169
+ // ATTRIBUTES
170
+ let element;
171
+ element = document.createElement(tag);
172
+ className?element.className = className: '';
173
+ type?element.type = type: '';
174
+ value?element.innerText = value : '';
175
+ element.value = value;
176
+ id?element.id = id: '';
177
+ html?element.innerHTML = html: '';
178
+ placeholder? element.placeholder = placeholder: '';
179
+ element.name = name;
180
+ title?element.title = title: '';
181
+ ariaLabel?element.ariaLabel = ariaLabel: '';
182
+ this.element.htmlFor = htmlFor;
183
+ formAction?element.formAction = formAction: '';
184
+ formEnctype?element.formEnctype = formEnctype: '';
185
+ formMethod?element.formMethod =formMethod: '';
186
+ formTarget?element.formTarget = formTarget: '';
187
+ formNoValidate?element.formNoValidate =formNoValidate: '';
188
+
189
+
190
+
191
+
192
+ // APPENDING ELEMENT TO PARENT
193
+ this.element.appendChild(element);
194
+
195
+
196
+
197
+ return{
198
+ on: (event = '', callback = () => {}) =>{
199
+ this.element.addEventListener(event, callback);
200
+
201
+ },
202
+
203
+ off: (event = '', callback = () => {}) => {
204
+ this.element.removeEventListener(event, callback)
205
+ },
206
+
207
+ styles : (styles = {}) => {
208
+ Object.assign(this.element.style, styles)
209
+ },
210
+ remove: ()=> {
211
+ this.element.remove();
212
+ }
213
+ }
214
+ }
215
+
216
+
217
+ }
218
+
219
+
220
+ }catch{
221
+ throw new Error(new DOMException);
222
+
223
+ }
224
+ }
225
+
226
+
227
+
228
+ /**
229
+ * Attaches an event listener to the parent element.
230
+ *
231
+ * @param {string} [event=''] - Event type to listen for (e.g. 'click', 'input').
232
+ * @param {(e: Event) => void} [callback=() => {}] - Handler invoked when the event fires.
233
+ * @returns {void}
234
+ *
235
+ * @example
236
+ * app.on('click', (e) => console.log('parent clicked'));
237
+ */
238
+ on(event = '', callback = () => {}){
239
+ this.parent.addEventListener(event, callback)
240
+ };
241
+
242
+
243
+ /**
244
+ * Removes a previously attached event listener from the parent element.
245
+ *
246
+ * @param {string} [event=''] - Event type the listener was registered for.
247
+ * @param {(e: Event) => void} [callback=() => {}] - The exact handler reference
248
+ * originally passed to `on`. Inline arrow functions cannot be removed.
249
+ * @returns {void}
250
+ *
251
+ * @example
252
+ * const handler = () => console.log('clicked');
253
+ * app.on('click', handler);
254
+ * app.off('click', handler);
255
+ */
256
+ off(event = '', callback = () => {}){
257
+ this.parent.removeEventListener(event, callback)
258
+ };
259
+
260
+ /**
261
+ * Merges the given styles into the parent element's inline style.
262
+ *
263
+ * @param {Partial<CSSStyleDeclaration>} [styles={}] - Object of camelCased CSS
264
+ * properties and their values (e.g. `{ backgroundColor: 'red' }`).
265
+ * @returns {void}
266
+ *
267
+ * @example
268
+ * app.styles({ width: '100vw', height: '2rem' });
269
+ */
270
+ styles(styles = {}){
271
+ Object.assign(this.parent.style, styles)
272
+ }
273
+
274
+
275
+ /**
276
+ * @param {ClassAccessorDecoratorContext} [className={}]
277
+ *The addClass() method adds the given tokens to the list, omitting any that are already present.
278
+ MDN Reference
279
+
280
+ * @returns {void}
281
+ */
282
+ addClass(className) {
283
+ this.element.classList.add(className);
284
+ }
285
+
286
+ /**
287
+ * @param {ClassAccessorDecoratorContext} [className={}]
288
+ *The removeClass() method removes the given tokens from the specified list.
289
+
290
+
291
+ * @returns {void}
292
+ */
293
+ removeClass (className) {
294
+ this.element.classList.remove(className);
295
+ }
296
+
297
+ // Element selector
298
+ /**
299
+ * Selects the first descendant of the parent matching `selector` and returns
300
+ * a handle for interacting with it.
301
+ *
302
+ * @param {string} selector - Any valid CSS selector (e.g. 'header', '.card', '#root').
303
+ * @returns {{
304
+ * current: Element | null,
305
+ * on: (event?: string, callback?: (e: Event) => void) => void,
306
+ * off: (event?: string, callback?: (e: Event) => void) => void,
307
+ * styles: (styles?: Partial<CSSStyleDeclaration>) => void,
308
+ * addChildren: (attrs?: {
309
+ * className?: string,
310
+ * id?: string,
311
+ * value?: string,
312
+ * type?: string,
313
+ * placeholder?: string,
314
+ * name?: string,
315
+ * htmlFor?: string,
316
+ * formAction?: string,
317
+ * formMethod?: string,
318
+ * formTarget?: string,
319
+ * formEnctype?: string,
320
+ * formNoValidate?: boolean,
321
+ * ariaLabel?: string,
322
+ * title?: string,
323
+ * html?: string}),
324
+ * remove: () => void,
325
+ * update: (attrs?: {
326
+ * className?: string,
327
+ * id?: string,
328
+ * value?: string,
329
+ * type?: string,
330
+ * placeholder?: string,
331
+ * name?: string,
332
+ * htmlFor?: string,
333
+ * formAction?: string,
334
+ * formMethod?: string,
335
+ * formTarget?: string,
336
+ * formEnctype?: string,
337
+ * formNoValidate?: boolean,
338
+ * ariaLabel?: string,
339
+ * title?: string,
340
+ * html?: string
341
+ * }) => void
342
+ * }} A wrapper around the matched element. `current` is `null` if nothing matched.
343
+ *
344
+ * @example
345
+ * const header = app.select('header');
346
+ * header.update({ className: 'love', id: 'hatred' });
347
+ * header.styles({ backgroundColor: 'red' });
348
+ * header.on('click', () => console.log('clicked'));
349
+ */
350
+ select(selector){
351
+ const element = this.parent.querySelector(selector);
352
+ return {
353
+ // Element
354
+ current: element,
355
+
356
+ /**
357
+ * Attaches an event listener to the matched element.
358
+ * @param {string} [event='']
359
+ * @param {(e: Event) => void} [callback=() => {}]
360
+ * @returns {void}
361
+ */
362
+ on: (event = '', callback = () => {}) =>{
363
+ element.addEventListener(event, callback)
364
+ },
365
+
366
+ /**
367
+ * Removes an event listener from the matched element.
368
+ * @param {string} [event='']
369
+ * @param {(e: Event) => void} [callback=() => {}]
370
+ * @returns {void}
371
+ */
372
+ off: (event = '', callback = () => {}) => {
373
+ element.removeEventListener(event, callback)
374
+ },
375
+
376
+ /**
377
+ * Merges styles into the matched element's inline style.
378
+ * @param {Partial<CSSStyleDeclaration>} [styles={}]
379
+ * @returns {void}
380
+ */
381
+ styles : (styles = {}) => {
382
+ Object.assign(element.style, styles)
383
+ },
384
+
385
+ /**
386
+ * Removes the matched element from the DOM.
387
+ * @returns {void}
388
+ */
389
+ remove: ()=> {
390
+ element.remove();
391
+ },
392
+
393
+ /**
394
+ * @param {ClassAccessorDecoratorContext} [className={}]
395
+ *The addClass() method adds the given tokens to the list, omitting any that are already present.
396
+ MDN Reference
397
+
398
+ * @returns {void}
399
+ */
400
+ addClass: (className) => {
401
+ element.classList.add(className);
402
+ },
403
+ /**
404
+ * @param {ClassAccessorDecoratorContext} [className={}]
405
+ *The removeClass() method removes the given tokens from the specified list.
406
+
407
+
408
+ * @returns {void}
409
+ */
410
+ removeClass: (className) => {
411
+ element.classList.remove(className);
412
+ },
413
+
414
+ /**
415
+ * Updates attributes and content on the matched element.
416
+ *
417
+ * @param {{
418
+ * className?: string,
419
+ * id?: string,
420
+ * value?: string,
421
+ * type?: string,
422
+ * placeholder?: string,
423
+ * name?: string,
424
+ * htmlFor?: string,
425
+ * formAction?: string,
426
+ * formMethod?: string,
427
+ * formTarget?: string,
428
+ * formEnctype?: string,
429
+ * formNoValidate?: boolean,
430
+ * ariaLabel?: string,
431
+ * title?: string,
432
+ * html?: string
433
+ * }} [attrs]
434
+ * @returns {void}
435
+ */
436
+ update: ({ className,id, value,type, placeholder, name, htmlFor,formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title,html}) => {
437
+ className?element.className = className: '';
438
+ id?element.id= id: '';
439
+ value?element.value = value: '';
440
+ value?element.innerText = value : '';
441
+ type?element.type = type: '';
442
+ html?element.innerHTML = html: '';
443
+ placeholder? element.placeholder = placeholder: '';
444
+ element.name = name;
445
+ element.htmlFor = htmlFor;
446
+ formAction?element.formAction = formAction: '';
447
+ formEnctype?element.formEnctype = formEnctype: '';
448
+ formMethod?element.formMethod =formMethod: '';
449
+ formTarget?element.formTarget = formTarget: '';
450
+ formNoValidate?element.formNoValidate =formNoValidate: '';
451
+ title?element.title = title: '';
452
+ ariaLabel?element.ariaLabel = ariaLabel: '';
453
+ },
454
+
455
+ /**
456
+ * Creates an HTML element, applies attributes, appends it to the parent,
457
+ * and returns a small handle for interacting with the created element.
458
+ *
459
+ * @param {Object} options
460
+ * @param {string} options.tag - Tag name of the element to create (e.g. 'div', 'input').
461
+ * @param {string} [options.className] - Value for the element's `class` attribute.
462
+ * @param {string} [options.id] - Value for the element's `id` attribute.
463
+ * @param {string} [options.value] - Text content / value for the element.
464
+ * @param {string} [options.type] - `type` attribute (mainly for `<input>`).
465
+ * @param {string} [options.placeholder] - `placeholder` attribute (mainly for `<input>` / `<textarea>`).
466
+ * @param {string} [options.name] - `name` attribute.
467
+ * @param {string} [options.htmlFor] - `for` attribute (mainly for `<label>`).
468
+ * @param {string} [options.formAction] - `formaction` attribute (mainly for `<button>` / `<input>`).
469
+ * @param {string} [options.formMethod] - `formmethod` attribute (mainly for `<button>` / `<input>`).
470
+ * @param {string} [options.formTarget] - `formtarget` attribute (mainly for `<button>` / `<input>`).
471
+ * @param {string} [options.formEnctype] - `formenctype` attribute (mainly for `<button>` / `<input>`).
472
+ * @param {boolean} [options.formNoValidate] - `formnovalidate` attribute (mainly for `<button>` / `<input>`).
473
+ * @param {string} [options.ariaLabel] - Value for the `aria-label` attribute.
474
+ * @param {string} [options.title] - `title` attribute.
475
+ * @param {string} [options.html] - Raw HTML to inject via `innerHTML`.
476
+ *
477
+ * @returns {{
478
+ * on: (event?: string, callback?: (e: Event) => void) => void,
479
+ * off: (event?: string, callback?: (e: Event) => void) => void,
480
+ * styles: (styles?: Partial<CSSStyleDeclaration>) => void,
481
+ * remove: () => void
482
+ * }} A handle exposing event, style, and removal helpers for the created element.
483
+ *
484
+ * @throws {Error} If element creation or attribute assignment fails
485
+ * (wraps a generic {@link DOMException}).
486
+ *
487
+ * @example
488
+ * const div = app.addElement({
489
+ * tag: 'div',
490
+ * className: 'card',
491
+ * value: 'Hello',
492
+ * html: '<strong>Hello</strong>'
493
+ * });
494
+ * div.styles({ padding: '8px', backgroundColor: 'red' });
495
+ * div.on('click', () => console.log('clicked'));
496
+ */
497
+ addChildren: ({tag, className,id, value,type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html}) =>{
498
+ try{
499
+ // ATTRIBUTES
500
+ this.element = document.createElement(tag);
501
+ className?this.element.className = className: '';
502
+ type?this.element.type = type: '';
503
+ value?this.element.innerText = value : '';
504
+ this.element.value = value;
505
+ id?this.element.id = id: '';
506
+ html?this.element.innerHTML = html: '';
507
+ placeholder? this.element.placeholder = placeholder: '';
508
+ this.element.name = name;
509
+ title?this.element.title = title: '';
510
+ ariaLabel?this.element.ariaLabel = ariaLabel: '';
511
+ this.element.htmlFor = htmlFor;
512
+ formAction?this.element.formAction = formAction: '';
513
+ formEnctype?this.element.formEnctype = formEnctype: '';
514
+ formMethod?this.element.formMethod =formMethod: '';
515
+ formTarget?this.element.formTarget = formTarget: '';
516
+ formNoValidate?this.element.formNoValidate =formNoValidate: '';
517
+
518
+
519
+
520
+
521
+ // APPENDING ELEMENT TO PARENT
522
+ element.appendChild(this.element);
523
+
524
+
525
+
526
+ return{
527
+ on: (event = '', callback = () => {}) =>{
528
+ this.element.addEventListener(event, callback);
529
+
530
+ },
531
+
532
+ off: (event = '', callback = () => {}) => {
533
+ this.element.removeEventListener(event, callback)
534
+ },
535
+
536
+ styles : (styles = {}) => {
537
+ Object.assign(this.element.style, styles)
538
+ },
539
+ remove: ()=> {
540
+ this.element.remove();
541
+ }
542
+ }
543
+
544
+
545
+ }catch{
546
+ throw new Error(new DOMException);
547
+
548
+ }
549
+ }
550
+ };
551
+ }
552
+
553
+
554
+ // Element selector bulk
555
+ /**
556
+ * Selects all descendants of the parent matching `selector` and returns a
557
+ * handle for interacting with the matched elements as a group.
558
+ *
559
+ * @param {string} selector - Any valid CSS selector (e.g. '.card', 'li', 'input[type="text"]').
560
+ * @returns {{
561
+ * current: NodeListOf<Element>,
562
+ * on: (event?: string, callback?: (e: Event) => void) => void,
563
+ * off: (event?: string, callback?: (e: Event) => void) => void,
564
+ * styles: (styles?: Partial<CSSStyleDeclaration>) => void,
565
+ * remove: () => void,
566
+ * addChildren: (attrs?: {
567
+ * className?: string,
568
+ * id?: string,
569
+ * value?: string,
570
+ * type?: string,
571
+ * placeholder?: string,
572
+ * name?: string,
573
+ * htmlFor?: string,
574
+ * formAction?: string,
575
+ * formMethod?: string,
576
+ * formTarget?: string,
577
+ * formEnctype?: string,
578
+ * formNoValidate?: boolean,
579
+ * ariaLabel?: string,
580
+ * title?: string,
581
+ * html?: string}),
582
+ * update: (attrs?: {
583
+ * className?: string,
584
+ * id?: string,
585
+ * value?: string,
586
+ * type?: string,
587
+ * placeholder?: string,
588
+ * name?: string,
589
+ * htmlFor?: string,
590
+ * formAction?: string,
591
+ * formMethod?: string,
592
+ * formTarget?: string,
593
+ * formEnctype?: string,
594
+ * formNoValidate?: boolean,
595
+ * ariaLabel?: string,
596
+ * title?: string,
597
+ * html?: string
598
+ * }) => void
599
+ * }} A wrapper around the matched elements. `current` is an empty `NodeList`
600
+ * if nothing matched.
601
+ *
602
+ * @example
603
+ * const items = app.selectAll('.item');
604
+ * items.styles({ color: 'red' });
605
+ * items.on('click', (e) => console.log('clicked', e.currentTarget));
606
+ */
607
+ selectAll(selector){
608
+ const elements = this.parent.querySelectorAll(selector);
609
+ return {
610
+ // Element
611
+ /** @type {NodeListOf<Element>} The matched elements (may be empty). */
612
+ current: elements,
613
+ /**
614
+ * Attaches an event listener to the matched elements.
615
+ * @param {string} [event='']
616
+ * @param {(e: Event) => void} [callback=() => {}]
617
+ * @returns {void}
618
+ */
619
+ on: (event = '', callback = () => {}) =>{
620
+ elements.forEach((element) => element.addEventListener(event, callback));
621
+ },
622
+
623
+ /**
624
+ * Removes an event listener from the matched elements.
625
+ * @param {string} [event='']
626
+ * @param {(e: Event) => void} [callback=() => {}]
627
+ * @returns {void}
628
+ */
629
+ off: (event = '', callback = () => {}) => {
630
+ elements.forEach((element) => element.removeEventListener(event, callback));
631
+ },
632
+
633
+ /**
634
+ * Merges styles into each matched element's inline style.
635
+ * @param {Partial<CSSStyleDeclaration>} [styles={}]
636
+ * @returns {void}
637
+ */
638
+ styles : (styles = {}) => {
639
+ elements.forEach((element) => Object.assign(element.style, styles));
640
+ },
641
+
642
+ /**
643
+ * Removes all matched elements from the DOM.
644
+ * @returns {void}
645
+ */
646
+ remove: ()=> {
647
+ elements.forEach((element) => element.remove());
648
+ },
649
+
650
+
651
+ /**
652
+ * @param {ClassAccessorDecoratorContext} [className={}]
653
+ *The addClass() method adds the given tokens to the list, omitting any that are already present.
654
+ MDN Reference
655
+
656
+ * @returns {void}
657
+ */
658
+ addClass: (className) => {
659
+ elements.forEach((element) => element.classList.add(className));
660
+ },
661
+
662
+ /**
663
+ * @param {ClassAccessorDecoratorContext} [className={}]
664
+ *The removeClass() method removes the given tokens from the specified list.
665
+
666
+
667
+ * @returns {void}
668
+ */
669
+ removeClass: (className) => {
670
+ elements.forEach((element) => element.classList.remove(className));
671
+ },
672
+
673
+ /**
674
+ * Updates attributes and content on each matched element.
675
+ *
676
+ * @param {{
677
+ * className?: string,
678
+ * id?: string,
679
+ * value?: string,
680
+ * type?: string,
681
+ * placeholder?: string,
682
+ * name?: string,
683
+ * htmlFor?: string,
684
+ * formAction?: string,
685
+ * formMethod?: string,
686
+ * formTarget?: string,
687
+ * formEnctype?: string,
688
+ * formNoValidate?: boolean,
689
+ * ariaLabel?: string,
690
+ * title?: string,
691
+ * html?: string
692
+ * }} [attrs]
693
+ * @returns {void}
694
+ */
695
+ update: (attrs = {}) => {
696
+ const { className, id, value, type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html } = attrs;
697
+ elements.forEach((element) => {
698
+ if (className !== undefined) element.className = className;
699
+ if (id !== undefined) element.id = id;
700
+ if (value !== undefined) {
701
+ element.value = value;
702
+ element.innerText = value;
703
+ }
704
+ if (type !== undefined) element.type = type;
705
+ if (placeholder !== undefined) element.placeholder = placeholder;
706
+ if (name !== undefined) element.name = name;
707
+ if (html !== undefined) element.innerHTML = html;
708
+ if (htmlFor !== undefined) element.htmlFor = htmlFor;
709
+ if (formAction !== undefined) element.formAction = formAction;
710
+ if (formEnctype !== undefined) element.formEnctype = formEnctype;
711
+ if (formMethod !== undefined) element.formMethod = formMethod;
712
+ if (formTarget !== undefined) element.formTarget = formTarget;
713
+ if (formNoValidate !== undefined) element.formNoValidate = formNoValidate;
714
+ if (title !== undefined) element.title = title;
715
+ if (ariaLabel !== undefined) element.ariaLabel = ariaLabel;
716
+ });
717
+ },
718
+
719
+ /**
720
+ * Creates an HTML element, applies attributes, appends it to the parent,
721
+ * and returns a small handle for interacting with the created element.
722
+ *
723
+ * @param {Object} options
724
+ * @param {string} options.tag - Tag name of the element to create (e.g. 'div', 'input').
725
+ * @param {string} [options.className] - Value for the element's `class` attribute.
726
+ * @param {string} [options.id] - Value for the element's `id` attribute.
727
+ * @param {string} [options.value] - Text content / value for the element.
728
+ * @param {string} [options.type] - `type` attribute (mainly for `<input>`).
729
+ * @param {string} [options.placeholder] - `placeholder` attribute (mainly for `<input>` / `<textarea>`).
730
+ * @param {string} [options.name] - `name` attribute.
731
+ * @param {string} [options.htmlFor] - `for` attribute (mainly for `<label>`).
732
+ * @param {string} [options.formAction] - `formaction` attribute (mainly for `<button>` / `<input>`).
733
+ * @param {string} [options.formMethod] - `formmethod` attribute (mainly for `<button>` / `<input>`).
734
+ * @param {string} [options.formTarget] - `formtarget` attribute (mainly for `<button>` / `<input>`).
735
+ * @param {string} [options.formEnctype] - `formenctype` attribute (mainly for `<button>` / `<input>`).
736
+ * @param {boolean} [options.formNoValidate] - `formnovalidate` attribute (mainly for `<button>` / `<input>`).
737
+ * @param {string} [options.ariaLabel] - Value for the `aria-label` attribute.
738
+ * @param {string} [options.title] - `title` attribute.
739
+ * @param {string} [options.html] - Raw HTML to inject via `innerHTML`.
740
+ *
741
+ * @returns {{
742
+ * on: (event?: string, callback?: (e: Event) => void) => void,
743
+ * off: (event?: string, callback?: (e: Event) => void) => void,
744
+ * styles: (styles?: Partial<CSSStyleDeclaration>) => void,
745
+ * remove: () => void
746
+ * }} A handle exposing event, style, and removal helpers for the created element.
747
+ *
748
+ * @throws {Error} If element creation or attribute assignment fails
749
+ * (wraps a generic {@link DOMException}).
750
+ *
751
+ * @example
752
+ * const div = app.addElement({
753
+ * tag: 'div',
754
+ * className: 'card',
755
+ * value: 'Hello',
756
+ * html: '<strong>Hello</strong>'
757
+ * });
758
+ * div.styles({ padding: '8px', backgroundColor: 'red' });
759
+ * div.on('click', () => console.log('clicked'));
760
+ */
761
+ addChildren: (attrs) => {
762
+ const children = [];
763
+ elements.forEach((parent) => {
764
+ const child = document.createElement(attrs.tag);
765
+ const { tag, className, id, value, type, placeholder, name, htmlFor, formAction, formMethod, formTarget, formEnctype, formNoValidate, ariaLabel, title, html } = attrs;
766
+ if (className !== undefined) child.className = className;
767
+ if (id !== undefined) child.id = id;
768
+ if (value !== undefined) {
769
+ child.innerText = value;
770
+ child.value = value;
771
+ }
772
+ if (type !== undefined) child.type = type;
773
+ if (placeholder !== undefined) child.placeholder = placeholder;
774
+ if (name !== undefined) child.name = name;
775
+ if (htmlFor !== undefined) child.htmlFor = htmlFor;
776
+ if (formAction !== undefined) child.formAction = formAction;
777
+ if (formMethod !== undefined) child.formMethod = formMethod;
778
+ if (formTarget !== undefined) child.formTarget = formTarget;
779
+ if (formEnctype !== undefined) child.formEnctype = formEnctype;
780
+ if (formNoValidate !== undefined) child.formNoValidate = formNoValidate;
781
+ if (ariaLabel !== undefined) child.ariaLabel = ariaLabel;
782
+ if (title !== undefined) child.title = title;
783
+ if (html !== undefined) child.innerHTML = html;
784
+
785
+ parent.appendChild(child);
786
+ children.push(child);
787
+ });
788
+
789
+ return children;
790
+ }
791
+ };
792
+ }
793
+
794
+
795
+ }
796
+
797
+ export default LucidDOM
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "luciddom",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "LucidDOM.js is a lightweight browser-side DOM helper. It wraps a parent element and provides methods for creating elements, selecting descendants, updating content, handling events, applying inline styles, and removing elements.",
5
- "main": "dist/lucid.min.js",
5
+ "main": "lucidDOM.js",
6
6
  "dependencies": {
7
7
  "esbuild": "^0.28.2"
8
8
  },
@@ -11,8 +11,8 @@
11
11
  "test": "echo \"Error: no test specified\" && exit 1",
12
12
  "build": "esbuild lucidDOM.js --bundle --minify --sourcemap --outfile=dist/luciddom.min.js"
13
13
  },
14
- "keywords": [],
15
- "author": "",
14
+ "keywords": ["LucidDOM", "DOM helper", "Jquery", "DOM", "javascript", "js", "helper lib", "New Dom Helper", "2026"],
15
+ "author": "Prince B. Adu",
16
16
  "license": "ISC",
17
17
  "type": "module"
18
18
  }