@twobirds/microcomponents 0.0.67 → 0.0.68
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/.vscode/settings.json +1 -1
- package/README.md +3 -3
- package/assets/documentation/formvalues.md +26 -0
- package/assets/test/MicroComponents.svg +15 -0
- package/assets/test/test.html +5 -5
- package/dist/microcomponents.d.ts +0 -1
- package/dist/microcomponents.d.ts.map +1 -1
- package/dist/microcomponents.min.js +1 -0
- package/dist/microcomponents.ts +1 -1
- package/package.json +6 -5
- package/public/MC.d.ts +36 -0
- package/public/MC.d.ts.map +1 -0
- package/public/MC.ts +605 -0
- package/public/McEvent.d.ts +15 -0
- package/public/McEvent.d.ts.map +1 -0
- package/public/McEvent.ts +96 -0
- package/public/documentation/formvalues.md +26 -0
- package/public/elements.d.ts +5 -0
- package/public/elements.d.ts.map +1 -0
- package/public/elements.ts +76 -0
- package/public/formValues.d.ts +3 -0
- package/public/formValues.d.ts.map +1 -0
- package/public/formValues.ts +233 -0
- package/public/helpers.d.ts +14 -0
- package/public/helpers.d.ts.map +1 -0
- package/public/helpers.ts +149 -0
- package/public/microcomponents.d.ts +7 -0
- package/public/microcomponents.d.ts.map +1 -0
- package/public/microcomponents.es3.d.ts +2 -0
- package/public/microcomponents.es3.d.ts.map +1 -0
- package/public/microcomponents.js +0 -1
- package/public/microcomponents.js.map +1 -1
- package/public/microcomponents.min.js +1 -0
- package/public/microcomponents.ts +8 -0
- package/public/observables.d.ts +10 -0
- package/public/observables.d.ts.map +1 -0
- package/public/observables.ts +401 -0
- package/public/selectors.d.ts +108 -0
- package/public/selectors.d.ts.map +1 -0
- package/public/selectors.ts +1634 -0
- package/public/src/microcomponents.ts +1 -1
- package/public/test/MC.d.ts +36 -0
- package/public/test/MC.d.ts.map +1 -0
- package/public/test/MC.js +378 -0
- package/public/test/MC.js.map +1 -0
- package/public/test/MC.ts +605 -0
- package/public/test/McEvent.d.ts +15 -0
- package/public/test/McEvent.d.ts.map +1 -0
- package/public/test/McEvent.js +71 -0
- package/public/test/McEvent.js.map +1 -0
- package/public/test/McEvent.ts +96 -0
- package/public/test/MicroComponents.svg +15 -0
- package/public/test/elements.d.ts +5 -0
- package/public/test/elements.d.ts.map +1 -0
- package/public/test/elements.js +48 -0
- package/public/test/elements.js.map +1 -0
- package/public/test/elements.ts +76 -0
- package/public/test/formValues.d.ts +3 -0
- package/public/test/formValues.d.ts.map +1 -0
- package/public/test/formValues.js +168 -0
- package/public/test/formValues.js.map +1 -0
- package/public/test/formValues.ts +233 -0
- package/public/test/helpers.d.ts +14 -0
- package/public/test/helpers.d.ts.map +1 -0
- package/public/test/helpers.js +113 -0
- package/public/test/helpers.js.map +1 -0
- package/public/test/helpers.ts +149 -0
- package/public/test/microcomponents.d.ts +7 -0
- package/public/test/microcomponents.d.ts.map +1 -0
- package/public/test/microcomponents.es3.d.ts +2 -0
- package/public/test/microcomponents.es3.d.ts.map +1 -0
- package/public/test/microcomponents.es3.js +303 -0
- package/public/test/microcomponents.es3.js.map +1 -0
- package/public/test/microcomponents.js +8 -0
- package/public/test/microcomponents.js.map +1 -0
- package/public/test/microcomponents.min.js +1 -0
- package/public/test/microcomponents.ts +8 -0
- package/public/test/observables.d.ts +10 -0
- package/public/test/observables.d.ts.map +1 -0
- package/public/test/observables.js +250 -0
- package/public/test/observables.js.map +1 -0
- package/public/test/observables.ts +401 -0
- package/public/test/selectors.d.ts +108 -0
- package/public/test/selectors.d.ts.map +1 -0
- package/public/test/selectors.js +971 -0
- package/public/test/selectors.js.map +1 -0
- package/public/test/selectors.ts +1634 -0
- package/public/test/test/child.d.ts +2 -0
- package/public/test/test/child.d.ts.map +1 -0
- package/public/test/{child.js → test/child.js} +1 -1
- package/public/test/test/child.js.map +1 -0
- package/public/test/test/grandchild.d.ts +2 -0
- package/public/test/test/grandchild.d.ts.map +1 -0
- package/public/test/{grandchild.js → test/grandchild.js} +1 -1
- package/public/test/test/grandchild.js.map +1 -0
- package/public/test/test/grandparent.d.ts +2 -0
- package/public/test/test/grandparent.d.ts.map +1 -0
- package/public/test/test/grandparent.js.map +1 -0
- package/public/test/test/greatgrandchild.d.ts +2 -0
- package/public/test/test/greatgrandchild.d.ts.map +1 -0
- package/public/test/{greatgrandchild.js → test/greatgrandchild.js} +1 -1
- package/public/test/test/greatgrandchild.js.map +1 -0
- package/public/test/test/parent.d.ts +2 -0
- package/public/test/test/parent.d.ts.map +1 -0
- package/public/test/{parent.js → test/parent.js} +1 -1
- package/public/test/test/parent.js.map +1 -0
- package/public/test/test/testform.d.ts +2 -0
- package/public/test/test/testform.d.ts.map +1 -0
- package/public/test/test/testform.js.map +1 -0
- package/public/test/test/testmc.d.ts +6 -0
- package/public/test/test/testmc.d.ts.map +1 -0
- package/public/test/{testmc.js → test/testmc.js} +1 -1
- package/public/test/test/testmc.js.map +1 -0
- package/public/test/test.d.ts +2 -0
- package/public/test/test.d.ts.map +1 -0
- package/public/test/test.html +5 -5
- package/public/test/test.ts +193 -0
- package/public/typedoc/classes/MC.DC.html +2 -2
- package/public/typedoc/classes/MC.MC.html +2 -2
- package/public/typedoc/classes/MC.McBase.html +2 -2
- package/public/typedoc/classes/MC.McEvent.html +2 -2
- package/public/typedoc/functions/MC.addListener.html +1 -1
- package/public/typedoc/functions/MC.autoload.html +1 -1
- package/public/typedoc/functions/MC.removeListener.html +1 -1
- package/public/typedoc/functions/elements.defineCE.html +1 -1
- package/public/typedoc/functions/elements.getCE.html +1 -1
- package/public/typedoc/functions/formValues.formValues.html +1 -1
- package/public/typedoc/functions/observables.observe.html +1 -1
- package/public/typedoc/functions/selectors._d.html +1 -1
- package/public/typedoc/functions/selectors._t.html +1 -1
- package/public/typedoc/index.html +3 -3
- package/public/typedoc/interfaces/MC.HTMLMcElement.html +2 -2
- package/public/typedoc/interfaces/selectors.DSelector.html +2 -2
- package/public/typedoc/interfaces/selectors.TSelector.html +2 -2
- package/public/typedoc/modules/MC.html +1 -1
- package/public/typedoc/modules/elements.html +1 -1
- package/public/typedoc/modules/formValues.html +1 -1
- package/public/typedoc/modules/observables.html +1 -1
- package/public/typedoc/modules/selectors.html +1 -1
- package/public/typedoc/types/observables.Observable.html +1 -1
- package/public/typedoc/types/selectors.selection.html +1 -1
- package/public/typedoc/types/selectors.singleSelector.html +1 -1
- package/src/microcomponents.ts +1 -1
- package/src/test/{child.ts → test/child.ts} +1 -1
- package/src/test/{grandchild.ts → test/grandchild.ts} +1 -1
- package/src/test/{grandparent.ts → test/grandparent.ts} +1 -1
- package/src/test/{greatgrandchild.ts → test/greatgrandchild.ts} +1 -1
- package/src/test/{parent.ts → test/parent.ts} +1 -1
- package/src/test/{testform.ts → test/testform.ts} +1 -1
- package/src/test/{testmc.ts → test/testmc.ts} +1 -1
- package/tsconfig.json +2 -2
- package/webpack.config.js +5 -5
- package/dist/microcomponents.js +0 -1
- package/public/test/child.js.map +0 -1
- package/public/test/grandchild.js.map +0 -1
- package/public/test/grandparent.js.map +0 -1
- package/public/test/greatgrandchild.js.map +0 -1
- package/public/test/parent.js.map +0 -1
- package/public/test/testform.js.map +0 -1
- package/public/test/testmc.js.map +0 -1
- /package/public/test/{grandparent.js → test/grandparent.js} +0 -0
- /package/public/test/{testform.js → test/testform.js} +0 -0
- /package/public/{test.js → test/test.js} +0 -0
- /package/public/{test.js.map → test/test.js.map} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var isBrowser=new Function("try {return this===window;}catch(e){ return false;}");
|
|
4
|
+
|
|
5
|
+
let nativeEventNames: Set<string> = new Set();
|
|
6
|
+
|
|
7
|
+
// HTMLElement native event names
|
|
8
|
+
if ( isBrowser() ){
|
|
9
|
+
Object.keys( HTMLElement.prototype ).filter( key => /^on/.test(key) ).forEach( eventName => nativeEventNames.add( eventName ) );
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function isDOM(element: { [key:string]: any } ) {
|
|
13
|
+
return element && element instanceof HTMLElement;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface McEvent {
|
|
17
|
+
data: any;
|
|
18
|
+
bubble: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class McEvent{
|
|
22
|
+
|
|
23
|
+
#type: string;
|
|
24
|
+
#stopped: boolean = false;
|
|
25
|
+
#immediateStopped: boolean = false;
|
|
26
|
+
|
|
27
|
+
constructor( type: string, data: any = {}, bubble: string = 'l' ){
|
|
28
|
+
// bubble standard = local only, options = any combination of'uld' characters: up to root, local, down
|
|
29
|
+
this.#type = type;
|
|
30
|
+
this.data = data;
|
|
31
|
+
this.bubble = bubble;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get type(): string {
|
|
35
|
+
return this.#type;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get stopped(): boolean {
|
|
39
|
+
return this.#stopped;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get immediateStopped(): boolean {
|
|
43
|
+
return this.#immediateStopped;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
stopPropagation(){
|
|
47
|
+
this.#stopped = true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
stopImmediatePropagation(){
|
|
51
|
+
this.stopPropagation();
|
|
52
|
+
this.#immediateStopped = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// get all microcomponents from a list of HTMLElements
|
|
58
|
+
function getMicroComponents( elements: any[], search: string): any[] {
|
|
59
|
+
let mcValues: any[] = [];
|
|
60
|
+
|
|
61
|
+
elements.forEach( e => {
|
|
62
|
+
if (e) {
|
|
63
|
+
if (e instanceof HTMLElement) {
|
|
64
|
+
const _mc = ( e as any )?._mc;
|
|
65
|
+
if ( !search && _mc ) {
|
|
66
|
+
mcValues = mcValues.concat(Object.values(( e as any )._mc));
|
|
67
|
+
}
|
|
68
|
+
else if ( search && _mc && _mc[search] ) {
|
|
69
|
+
mcValues.push( _mc[search] );
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
return mcValues;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// get all ancestor DOM nodes up to the document root
|
|
78
|
+
function traverseNodes(node: { [key:string]: any }, search: string, firstonly = true): any[] {
|
|
79
|
+
let mcValues: any[] = [];
|
|
80
|
+
while (node) {
|
|
81
|
+
if (node._mc) {
|
|
82
|
+
if (!search) {
|
|
83
|
+
mcValues = mcValues.concat(Object.values(node._mc));
|
|
84
|
+
}
|
|
85
|
+
else if (search && node._mc[search]) {
|
|
86
|
+
mcValues.push(node._mc[search]);
|
|
87
|
+
}
|
|
88
|
+
if (firstonly)
|
|
89
|
+
return mcValues;
|
|
90
|
+
}
|
|
91
|
+
node = node.parentNode;
|
|
92
|
+
}
|
|
93
|
+
return mcValues;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export { McEvent };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Form Values Module Documentation
|
|
2
|
+
|
|
3
|
+
This module provides a way to bind form input elements (text, radio, checkbox, select, textarea) to a JavaScript object, enabling two-way data binding and change observation.
|
|
4
|
+
|
|
5
|
+
## Key Components
|
|
6
|
+
|
|
7
|
+
### InputBase (Abstract Class)
|
|
8
|
+
- Base class for all input handlers
|
|
9
|
+
- Defines `val` getter/setter interface
|
|
10
|
+
|
|
11
|
+
### Input Handlers
|
|
12
|
+
- **RadioHandler**: Manages radio button groups
|
|
13
|
+
- **CheckboxHandler**: Handles checkbox state
|
|
14
|
+
- **InputHandler**: For standard text inputs
|
|
15
|
+
- **SelectHandler**: Manages select dropdowns (single/multi-select)
|
|
16
|
+
- **TextAreaHandler**: For textarea elements
|
|
17
|
+
|
|
18
|
+
### getInputHandlers
|
|
19
|
+
- Scans DOM for form elements
|
|
20
|
+
- Returns object with name-to-handler mappings
|
|
21
|
+
- Automatically creates appropriate handler type
|
|
22
|
+
|
|
23
|
+
### formValues Function
|
|
24
|
+
Binds form elements to a target object:
|
|
25
|
+
```ts
|
|
26
|
+
formValues(targetObject: LooseObject, propertyName: string, dom: HTMLElement | ShadowRoot)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elements.d.ts","sourceRoot":"","sources":["../src/elements.ts"],"names":[],"mappings":"AAkCA,wBAAgB,QAAQ,CACvB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE;IAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAA;CAAE,EAC9C,kBAAkB,GAAE,MAAM,EAAO,QAkCjC;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS,CAE3E"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { DC } from './MC.js';
|
|
4
|
+
import { kebabToPascal } from './helpers.js';
|
|
5
|
+
|
|
6
|
+
class CeBaseClass extends HTMLElement {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
connectedCallback() {
|
|
12
|
+
(DC as any).trigger(this, 'Connected');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
disconnectedCallback() {
|
|
16
|
+
(DC as any).trigger(this, 'Disconnected');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
adoptedCallback() {
|
|
20
|
+
(DC as any).trigger(this, 'Adopted');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
attributeChangedCallback(name: string, oldValue: any, newValue: any) {
|
|
24
|
+
(DC as any).trigger(this, 'AttributeChanged', { name, oldValue, newValue });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function createNamedClass(
|
|
29
|
+
name: string,
|
|
30
|
+
ClassBody: { new (...args: any[]): any }
|
|
31
|
+
) {
|
|
32
|
+
return Object.defineProperty(ClassBody, 'name', { value: name });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function defineCE(
|
|
36
|
+
tagName: string,
|
|
37
|
+
DefinitionClass: { new (...args: any[]): any },
|
|
38
|
+
observedAttributes: string[] = []
|
|
39
|
+
) {
|
|
40
|
+
if (customElements.get(tagName)) {
|
|
41
|
+
console.warn(`IGNORED: Custom element "${tagName}" is already defined!`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!tagName.includes('-')) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
'createCustomElement: tagName must contain at least one hyphen ("-").'
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let name = kebabToPascal(tagName);
|
|
52
|
+
|
|
53
|
+
customElements.define(
|
|
54
|
+
tagName,
|
|
55
|
+
createNamedClass(
|
|
56
|
+
name,
|
|
57
|
+
class extends CeBaseClass {
|
|
58
|
+
instance: any;
|
|
59
|
+
|
|
60
|
+
constructor(data?: any) {
|
|
61
|
+
super();
|
|
62
|
+
let instance = new DefinitionClass(this, data);
|
|
63
|
+
DC.add(this, name, instance);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static get observedAttributes() {
|
|
67
|
+
return observedAttributes;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function getCE(tagName: string): CustomElementConstructor | undefined {
|
|
75
|
+
return customElements.get(tagName);
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formValues.d.ts","sourceRoot":"","sources":["../src/formValues.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAsB,MAAM,cAAc,CAAC;AA0M/D,wBAAgB,UAAU,CACzB,YAAY,EAAE,WAAW,EACzB,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,WAAW,GAAG,UAAU,QAwB7B"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { LooseObject, copyGettersSetters } from './helpers.js';
|
|
4
|
+
import { DC, addListener } from './MC.js';
|
|
5
|
+
import { observe } from './observables.js';
|
|
6
|
+
|
|
7
|
+
type inputTypes = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
8
|
+
|
|
9
|
+
const getInputName = (
|
|
10
|
+
e: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
|
|
11
|
+
): string => {
|
|
12
|
+
return e.tagName.toLowerCase();
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
abstract class InputBase {
|
|
16
|
+
constructor(e: inputTypes) {}
|
|
17
|
+
|
|
18
|
+
abstract get val(): any;
|
|
19
|
+
|
|
20
|
+
abstract set val(value: any);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class RadioHandler extends InputBase {
|
|
24
|
+
#e: HTMLInputElement;
|
|
25
|
+
|
|
26
|
+
constructor(e: HTMLInputElement) {
|
|
27
|
+
super(e);
|
|
28
|
+
this.#e = e;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
get val(): string {
|
|
32
|
+
let ret = new FormData(this.#e.form as HTMLFormElement).get(this.#e.name);
|
|
33
|
+
|
|
34
|
+
//console.log('radio[', this.#e.name, '] = "' + ret + '"');
|
|
35
|
+
return ret as string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
set val(value: string) {
|
|
39
|
+
let arr = [
|
|
40
|
+
...(this.#e.form as HTMLFormElement).querySelectorAll(
|
|
41
|
+
`input[type="radio"][name="${this.#e.name}"]`
|
|
42
|
+
),
|
|
43
|
+
] as HTMLInputElement[];
|
|
44
|
+
|
|
45
|
+
(
|
|
46
|
+
arr
|
|
47
|
+
.filter((e) => e.getAttribute('value') === value)
|
|
48
|
+
.shift() as HTMLInputElement
|
|
49
|
+
).checked = true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
class CheckboxHandler extends InputBase {
|
|
54
|
+
#e: HTMLInputElement;
|
|
55
|
+
|
|
56
|
+
constructor(e: HTMLInputElement) {
|
|
57
|
+
super(e);
|
|
58
|
+
this.#e = e;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get val(): boolean {
|
|
62
|
+
return this.#e.checked;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
set val(value: boolean) {
|
|
66
|
+
this.#e.checked = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
class InputHandler extends InputBase {
|
|
71
|
+
#e: HTMLInputElement;
|
|
72
|
+
|
|
73
|
+
constructor(e: HTMLInputElement) {
|
|
74
|
+
super(e);
|
|
75
|
+
this.#e = e;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
get val(): string {
|
|
79
|
+
return this.#e.value;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
set val(value: string) {
|
|
83
|
+
this.#e.value = value;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
class SelectHandler extends InputBase {
|
|
88
|
+
#e: HTMLSelectElement;
|
|
89
|
+
#multi: boolean = false;
|
|
90
|
+
|
|
91
|
+
constructor(e: HTMLSelectElement) {
|
|
92
|
+
super(e);
|
|
93
|
+
this.#e = e;
|
|
94
|
+
this.#multi = e.multiple;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get val(): string[] | string {
|
|
98
|
+
const that = this,
|
|
99
|
+
ret: string[] = [];
|
|
100
|
+
|
|
101
|
+
// get all options
|
|
102
|
+
[...that.#e.querySelectorAll('option')]
|
|
103
|
+
.filter((o) => o.selected)
|
|
104
|
+
.forEach((o) => {
|
|
105
|
+
ret.push(o.value);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
if (this.#multi) return ret;
|
|
109
|
+
return ret.length ? ret[0] : '';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
set val(value: string[] | string) {
|
|
113
|
+
const that = this;
|
|
114
|
+
|
|
115
|
+
value = typeof value === 'string' ? [value] : value;
|
|
116
|
+
|
|
117
|
+
// set all options
|
|
118
|
+
[...that.#e.querySelectorAll('option')].forEach((o) => {
|
|
119
|
+
if (value.indexOf(o.value) > -1) {
|
|
120
|
+
o.selected = true;
|
|
121
|
+
} else {
|
|
122
|
+
o.selected = false;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
class TextAreaHandler extends InputBase {
|
|
129
|
+
#e: HTMLTextAreaElement;
|
|
130
|
+
constructor(e: HTMLTextAreaElement) {
|
|
131
|
+
super(e);
|
|
132
|
+
this.#e = e;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get val(): string {
|
|
136
|
+
return this.#e.value || '';
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
set val(value: string) {
|
|
140
|
+
this.#e.value = value;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const getInputHandlers = (e: HTMLElement | ShadowRoot): LooseObject => {
|
|
145
|
+
let inputList = [
|
|
146
|
+
...(e || document).querySelectorAll('input,select,textarea'),
|
|
147
|
+
],
|
|
148
|
+
handlers: LooseObject = {};
|
|
149
|
+
|
|
150
|
+
inputList.forEach((i) => {
|
|
151
|
+
const name: string | null = (i as inputTypes).getAttribute('name');
|
|
152
|
+
if (name) {
|
|
153
|
+
let handler: any = false;
|
|
154
|
+
switch (getInputName(i as inputTypes)) {
|
|
155
|
+
case 'input':
|
|
156
|
+
switch ((i as HTMLInputElement).type) {
|
|
157
|
+
case 'radio':
|
|
158
|
+
handler = new RadioHandler(i as HTMLInputElement);
|
|
159
|
+
break;
|
|
160
|
+
case 'checkbox':
|
|
161
|
+
handler = new CheckboxHandler(i as HTMLInputElement);
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
handler = new InputHandler(i as HTMLInputElement);
|
|
165
|
+
}
|
|
166
|
+
break;
|
|
167
|
+
case 'select':
|
|
168
|
+
handler = new SelectHandler(i as HTMLSelectElement);
|
|
169
|
+
break;
|
|
170
|
+
case 'textarea':
|
|
171
|
+
handler = new TextAreaHandler(i as HTMLTextAreaElement);
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
console.warn(
|
|
175
|
+
'handler missing:',
|
|
176
|
+
name,
|
|
177
|
+
'for',
|
|
178
|
+
i.tagName.toLowerCase(),
|
|
179
|
+
i
|
|
180
|
+
);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (handler) {
|
|
185
|
+
DC.add(i, name, handler);
|
|
186
|
+
Object.defineProperty(handlers, name, {
|
|
187
|
+
enumerable: true,
|
|
188
|
+
configurable: true,
|
|
189
|
+
get: (): any => {
|
|
190
|
+
return handler.val;
|
|
191
|
+
},
|
|
192
|
+
set: (value: any) => {
|
|
193
|
+
if (handler.val !== value) {
|
|
194
|
+
handler.val = value;
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
return handlers;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export function formValues(
|
|
206
|
+
targetObject: LooseObject,
|
|
207
|
+
propertyName: string,
|
|
208
|
+
dom: HTMLElement | ShadowRoot
|
|
209
|
+
) {
|
|
210
|
+
let handlers = getInputHandlers(dom);
|
|
211
|
+
|
|
212
|
+
targetObject[propertyName] = Object.assign({}, handlers);
|
|
213
|
+
|
|
214
|
+
observe(targetObject, propertyName);
|
|
215
|
+
|
|
216
|
+
copyGettersSetters(handlers, targetObject[propertyName]);
|
|
217
|
+
|
|
218
|
+
[...dom.querySelectorAll('input, textarea, select')].forEach((input) => {
|
|
219
|
+
addListener(input as inputTypes, 'keyup', (ev: Event) => {
|
|
220
|
+
//console.log('keyup', ev);
|
|
221
|
+
targetObject[propertyName].notify();
|
|
222
|
+
});
|
|
223
|
+
addListener(input as HTMLElement, 'change', (ev: Event) => {
|
|
224
|
+
//console.log('change', ev);
|
|
225
|
+
targetObject[propertyName].notify();
|
|
226
|
+
});
|
|
227
|
+
addListener(input as inputTypes, 'select', (ev: Event) => {
|
|
228
|
+
//console.log('select', ev);
|
|
229
|
+
targetObject[propertyName].notify();
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface LooseObject {
|
|
2
|
+
[key: string | symbol]: any;
|
|
3
|
+
}
|
|
4
|
+
export declare function isNativeObject(value: any): boolean;
|
|
5
|
+
export declare function sortObject(o: LooseObject): LooseObject;
|
|
6
|
+
export declare function flattenObject(o: LooseObject, doSort?: boolean): LooseObject;
|
|
7
|
+
export declare function deepEqual(o1: LooseObject, o2: LooseObject): boolean;
|
|
8
|
+
export declare function nameSpace(ns: string | string[], obj?: LooseObject): any;
|
|
9
|
+
export declare function parse(what: string | Object | any[], parseThis: Object): any;
|
|
10
|
+
export declare function kebabToPascal(str: string): string;
|
|
11
|
+
export declare function debounce(func: Function, milliseconds: number): Function;
|
|
12
|
+
export declare function htmlToElements(html: string): HTMLElement[];
|
|
13
|
+
export declare function copyGettersSetters(source: LooseObject, target: LooseObject): void;
|
|
14
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAElD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,WAAW,GAAG,WAAW,CAatD;AAED,wBAAgB,aAAa,CAC5B,CAAC,EAAE,WAAW,EACd,MAAM,GAAE,OAAc,GACpB,WAAW,CAmBb;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,GAAG,OAAO,CAInE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,GAAG,GAAE,WAAgB,GAAG,GAAG,CAW3E;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,GAAG,EAAE,EAAE,SAAS,EAAE,MAAM,OAyCrE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,UAKxC;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAG,QAAQ,CASvE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,EAAE,CAU1D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,QAO1E"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
export interface LooseObject {
|
|
4
|
+
[key: string | symbol]: any;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function isNativeObject(value: any): boolean {
|
|
8
|
+
return value && value['constructor'] && value.constructor === Object;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function sortObject(o: LooseObject): LooseObject {
|
|
12
|
+
let result: LooseObject = {},
|
|
13
|
+
keys = [...Object.keys(o)].sort();
|
|
14
|
+
|
|
15
|
+
keys.forEach((key) => {
|
|
16
|
+
if (isNativeObject(o[key])) {
|
|
17
|
+
result[key] = sortObject(o[key]);
|
|
18
|
+
} else {
|
|
19
|
+
result[key] = o[key];
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function flattenObject(
|
|
27
|
+
o: LooseObject,
|
|
28
|
+
doSort: boolean = true
|
|
29
|
+
): LooseObject {
|
|
30
|
+
let result: LooseObject = {};
|
|
31
|
+
|
|
32
|
+
[...Object.getOwnPropertyNames(o)].forEach((propName) => {
|
|
33
|
+
if (
|
|
34
|
+
o[propName] &&
|
|
35
|
+
o[propName]['constructor'] &&
|
|
36
|
+
o[propName].constructor === Object
|
|
37
|
+
) {
|
|
38
|
+
const temp = flattenObject(o[propName], false);
|
|
39
|
+
for (const j in temp) {
|
|
40
|
+
result[propName + '.' + j] = temp[j];
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
result[propName] = o[propName];
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return doSort ? sortObject(result) : result;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function deepEqual(o1: LooseObject, o2: LooseObject): boolean {
|
|
51
|
+
return (
|
|
52
|
+
JSON.stringify(flattenObject(o1)) === JSON.stringify(flattenObject(o2))
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function nameSpace(ns: string | string[], obj: LooseObject = {}): any {
|
|
57
|
+
let nsa = ns.constructor === String ? ns.split('.') : ns;
|
|
58
|
+
|
|
59
|
+
if (!obj || !nsa[0] || !obj[nsa[0]]) {
|
|
60
|
+
console.warn('ns', nsa[0], 'not in', obj);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (obj[nsa[0]].constructor === Object && nsa.length > 1) {
|
|
64
|
+
return nameSpace((nsa as string[]).splice(1), obj[nsa[0]]);
|
|
65
|
+
}
|
|
66
|
+
return obj[nsa[0]];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function parse(what: string | Object | any[], parseThis: Object) {
|
|
70
|
+
var args = Array.from(arguments);
|
|
71
|
+
|
|
72
|
+
if (args.length > 2) {
|
|
73
|
+
while (args.length > 1) {
|
|
74
|
+
args[0] = parse(args[0], args[1]);
|
|
75
|
+
args.splice(1, 1);
|
|
76
|
+
}
|
|
77
|
+
return args[0];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (typeof what === 'string') {
|
|
81
|
+
what.match(/\{[^\{\}]*\}/g)?.forEach(function (pPropname) {
|
|
82
|
+
var propname = pPropname.substring(1, pPropname.length - 1),
|
|
83
|
+
value = nameSpace(propname, parseThis);
|
|
84
|
+
//console.log(propname, value);
|
|
85
|
+
if (typeof value !== 'undefined') {
|
|
86
|
+
what = (what as string).replace(pPropname, value);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
} else if (isNativeObject(what)) {
|
|
90
|
+
switch (what.constructor) {
|
|
91
|
+
case Object:
|
|
92
|
+
Object.keys(what).forEach(function (pKey) {
|
|
93
|
+
if (what.hasOwnProperty(pKey)) {
|
|
94
|
+
(what as LooseObject)[pKey] = parse(
|
|
95
|
+
(what as LooseObject)[pKey],
|
|
96
|
+
parseThis
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
break;
|
|
101
|
+
case Array:
|
|
102
|
+
(what as Array<any>).forEach(function (pValue, pKey, original) {
|
|
103
|
+
original[pKey] = parse((what as any)[pKey], parseThis);
|
|
104
|
+
});
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return what;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function kebabToPascal(str: string) {
|
|
113
|
+
return str
|
|
114
|
+
.split('-') // Split by hyphens
|
|
115
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize each part
|
|
116
|
+
.join(''); // Join without spaces
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function debounce(func: Function, milliseconds: number): Function {
|
|
120
|
+
let timeout: any;
|
|
121
|
+
return () => {
|
|
122
|
+
clearTimeout(timeout);
|
|
123
|
+
|
|
124
|
+
timeout = setTimeout(function () {
|
|
125
|
+
func(...arguments);
|
|
126
|
+
}, milliseconds);
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function htmlToElements(html: string): HTMLElement[] {
|
|
131
|
+
let template = document.createElement('template');
|
|
132
|
+
|
|
133
|
+
html = html.replace(/<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi, '<$1$2></$1>'); // replace XHTML closing tags by full closing tags
|
|
134
|
+
|
|
135
|
+
template.innerHTML = html;
|
|
136
|
+
|
|
137
|
+
template.content.normalize();
|
|
138
|
+
|
|
139
|
+
return Array.from(template.content.childNodes) as HTMLElement[];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function copyGettersSetters(source: LooseObject, target: LooseObject) {
|
|
143
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
144
|
+
for (const [key, descriptor] of Object.entries(descriptors)) {
|
|
145
|
+
if ('get' in descriptor || 'set' in descriptor) {
|
|
146
|
+
Object.defineProperty(target, key, descriptor);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microcomponents.d.ts","sourceRoot":"","sources":["../src/microcomponents.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"microcomponents.es3.d.ts","sourceRoot":"","sources":["../src/microcomponents.es3.js"],"names":[],"mappings":"AAgWA,mFAwBC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microcomponents.js","sourceRoot":"","sources":["../src/microcomponents.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"microcomponents.js","sourceRoot":"","sources":["../src/microcomponents.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,iBAAiB,CAAC"}
|