@twobirds/microcomponents 0.0.20 → 0.0.22

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 (122) hide show
  1. package/.gitlab-ci.yml +1 -0
  2. package/README.md +33 -14
  3. package/assets/documentation/MicroComponents.md +228 -0
  4. package/assets/my-tag.css +4 -0
  5. package/assets/test.html +5 -1
  6. package/dist/MC.d.ts +32 -0
  7. package/dist/MC.d.ts.map +1 -0
  8. package/dist/MC.min.js +414 -0
  9. package/dist/MC.ts +350 -0
  10. package/dist/MCbundle.d.ts +8 -0
  11. package/dist/MCbundle.d.ts.map +1 -0
  12. package/dist/MCbundle.min.js +1 -0
  13. package/dist/MCbundle.ts +8 -0
  14. package/dist/McEvent.d.ts +15 -0
  15. package/dist/McEvent.d.ts.map +1 -0
  16. package/dist/McEvent.ts +96 -0
  17. package/dist/autoloader.d.ts +2 -0
  18. package/dist/autoloader.d.ts.map +1 -0
  19. package/dist/autoloader.ts +98 -0
  20. package/dist/customElements.d.ts +5 -0
  21. package/dist/customElements.d.ts.map +1 -0
  22. package/dist/customElements.min.js +1 -0
  23. package/dist/customElements.ts +67 -0
  24. package/dist/customObservables.d.ts +3 -0
  25. package/dist/customObservables.d.ts.map +1 -0
  26. package/dist/customObservables.min.js +1 -0
  27. package/dist/customObservables.ts +340 -0
  28. package/dist/customSelectors.d.ts +108 -0
  29. package/dist/customSelectors.d.ts.map +1 -0
  30. package/dist/customSelectors.min.js +1 -0
  31. package/dist/customSelectors.ts +1634 -0
  32. package/dist/formValues.d.ts +4 -0
  33. package/dist/formValues.d.ts.map +1 -0
  34. package/dist/formValues.ts +275 -0
  35. package/dist/formvValues.min.js +1 -0
  36. package/dist/helpers.d.ts +11 -0
  37. package/dist/helpers.d.ts.map +1 -0
  38. package/dist/helpers.ts +173 -0
  39. package/dist/microcomponents.es3.d.ts +1 -20
  40. package/dist/microcomponents.es3.d.ts.map +1 -1
  41. package/dist/test.d.ts +2 -0
  42. package/dist/test.d.ts.map +1 -0
  43. package/package.json +11 -7
  44. package/public/MC.js +273 -0
  45. package/public/MC.min.js +414 -0
  46. package/public/MCbundle.js +8 -0
  47. package/public/MCbundle.min.js +1 -0
  48. package/public/McEvent.js +74 -0
  49. package/public/MicroComponents.svg +15 -0
  50. package/public/assets/search.js +1 -1
  51. package/public/autoloader.js +57 -0
  52. package/public/classes/MC.DC.html +247 -0
  53. package/public/classes/MC.MC.html +150 -0
  54. package/public/classes/MC.McBase.html +123 -0
  55. package/public/classes/MCbundle.McEvent.html +184 -0
  56. package/public/customElements.js +48 -0
  57. package/public/customElements.min.js +1 -0
  58. package/public/customObservables.js +255 -0
  59. package/public/customObservables.min.js +1 -0
  60. package/public/customSelectors.js +1088 -0
  61. package/public/customSelectors.min.js +1 -0
  62. package/public/documentation/MicroComponents.md +228 -0
  63. package/public/formValues.js +211 -0
  64. package/public/formvValues.min.js +1 -0
  65. package/public/functions/MC.addListener.html +73 -0
  66. package/public/functions/MC.removeListener.html +69 -0
  67. package/public/functions/MCbundle._d.html +85 -0
  68. package/public/functions/MCbundle._t.html +85 -0
  69. package/public/functions/MCbundle.debounce.html +85 -0
  70. package/public/functions/MCbundle.deepEqual.html +85 -0
  71. package/public/functions/MCbundle.defineCE.html +98 -0
  72. package/public/functions/MCbundle.formValues.html +89 -0
  73. package/public/functions/MCbundle.getCE.html +83 -0
  74. package/public/functions/MCbundle.htmlToElements.html +83 -0
  75. package/public/functions/MCbundle.isObject.html +83 -0
  76. package/public/functions/MCbundle.kebabToPascal.html +83 -0
  77. package/public/functions/MCbundle.makeCO.html +85 -0
  78. package/public/functions/MCbundle.nameSpace.html +89 -0
  79. package/public/functions/MCbundle.parse.html +85 -0
  80. package/public/helpers.js +128 -0
  81. package/public/index.html +22 -13
  82. package/public/interfaces/MC.HTMLMcElement.html +3605 -0
  83. package/public/interfaces/MCbundle.DSelector.html +1010 -0
  84. package/public/interfaces/MCbundle.LooseObject.html +80 -0
  85. package/public/interfaces/MCbundle.TSelector.html +709 -0
  86. package/public/microcomponents.es3.js +348 -0
  87. package/public/modules/MC.html +84 -0
  88. package/public/modules/MCbundle.html +133 -0
  89. package/public/modules.html +4 -4
  90. package/public/my-tag.css +4 -0
  91. package/public/test.html +5 -1
  92. package/public/test.js +100 -202
  93. package/public/types/MCbundle.selection.html +74 -0
  94. package/public/types/MCbundle.singleSelector.html +74 -0
  95. package/src/MC.ts +350 -0
  96. package/src/MCbundle.ts +8 -0
  97. package/src/McEvent.ts +96 -0
  98. package/src/autoloader.ts +98 -0
  99. package/src/customElements.ts +67 -0
  100. package/src/customObservables.ts +340 -0
  101. package/src/customSelectors.ts +1634 -0
  102. package/src/formValues.ts +275 -0
  103. package/src/helpers.ts +173 -0
  104. package/src/microcomponents.es3.js +353 -82
  105. package/src/test.js +137 -218
  106. package/tsconfig.json +2 -2
  107. package/typedoc.json +1 -1
  108. package/webpack.config.js +233 -0
  109. package/dist/microcomponents.d.ts +0 -26
  110. package/dist/microcomponents.d.ts.map +0 -1
  111. package/dist/microcomponents.es3.js +0 -96
  112. package/dist/microcomponents.es3.min.js +0 -15
  113. package/dist/microcomponents.js +0 -176
  114. package/dist/microcomponents.min.js +0 -38
  115. package/dist/microcomponents.ts +0 -216
  116. package/public/classes/microcomponents.MC.html +0 -313
  117. package/public/classes/microcomponents_es3.MC.html +0 -336
  118. package/public/functions/microcomponents_es3.__isEmpty.html +0 -60
  119. package/public/microcomponents.js +0 -176
  120. package/public/modules/microcomponents.html +0 -57
  121. package/public/modules/microcomponents_es3.html +0 -60
  122. package/src/microcomponents.ts +0 -216
@@ -0,0 +1,275 @@
1
+ "use strict";
2
+
3
+ import { LooseObject } from './helpers.js'
4
+ import { MC, addListener } from './MC.js'
5
+
6
+ type inputTypes = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
7
+
8
+ const getInputName = ( e: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement ): string => {
9
+
10
+ let ret = e instanceof HTMLInputElement
11
+ ? 'input'
12
+ : e instanceof HTMLSelectElement
13
+ ? 'select'
14
+ : e instanceof HTMLTextAreaElement
15
+ ? 'textarea'
16
+ : ''
17
+ ;
18
+
19
+ return ret;
20
+ }
21
+
22
+ abstract class InputBase{
23
+ constructor( e: any ){
24
+ }
25
+
26
+ abstract get val(): any;
27
+
28
+ abstract set val( value: any );
29
+
30
+ }
31
+
32
+ const getInputHandlers = ( e: HTMLElement | ShadowRoot ): LooseObject => {
33
+
34
+ let
35
+ //inputList = ( Array.from( e.querySelectorAll('*') ) as HTMLElement[] ).filter( i => isInputElement(i) ),
36
+ inputList = [ ...( e || document).querySelectorAll('input,select,textarea') ],
37
+ handlers: LooseObject = {};
38
+
39
+ inputList.forEach( (i) => {
40
+ const
41
+ name: string = ( i as inputTypes ).getAttribute('name') || 'undefined';
42
+
43
+ if ( name ){
44
+ let h: InputBase;
45
+ switch ( getInputName( i as inputTypes ) ){
46
+ case 'input':
47
+ //console.log( i, 'is HTMLInputElement');
48
+ h = new InputHandler( i as HTMLInputElement, e ); // e = element to search radios in = radioBase
49
+ Object.defineProperty( handlers, name, {
50
+ enumerable: true,
51
+ configurable: true,
52
+ get: (): any => { return h.val },
53
+ set: ( value: any ) => { h.val = value }
54
+ });
55
+ break;
56
+ case 'select':
57
+ //console.log( i, 'is HTMLSelectElement');
58
+ h = new SelectHandler( i as HTMLSelectElement );
59
+ Object.defineProperty( handlers, name, {
60
+ enumerable: true,
61
+ configurable: true,
62
+ get: (): any => { return h.val },
63
+ set: ( value: any ) => { h.val = value }
64
+ });
65
+ break;
66
+ case 'textarea':
67
+ //console.log( i, 'is HTMLTextAreaElement');
68
+ h = new TextAreaHandler( i as HTMLTextAreaElement );
69
+ Object.defineProperty( handlers, name, {
70
+ enumerable: true,
71
+ configurable: true,
72
+ get: (): any => { return h.val },
73
+ set: ( value: any ) => { h.val = value }
74
+ });
75
+ break;
76
+ default:
77
+ console.warn('handler missing:', name, 'for', i);
78
+ break;
79
+ }
80
+ }
81
+ });
82
+
83
+ return handlers;
84
+ }
85
+
86
+ class InputHandler extends InputBase {
87
+
88
+ #e: HTMLInputElement;
89
+ #type: string;
90
+ #radioBase: any;
91
+
92
+ constructor( e: HTMLInputElement, radioBase?: HTMLElement | ShadowRoot ){
93
+ super( e );
94
+ this.#e = e;
95
+ this.#type = e.type;
96
+ this.#radioBase = radioBase;
97
+ }
98
+
99
+ get val(): any{
100
+ let that = this,
101
+ type = that.#type,
102
+ ret: any;
103
+
104
+ switch (type){
105
+ case 'radio':
106
+ const check = [ ...(this.#radioBase || document).querySelectorAll( `input[type="radio"][name="${ this.#e.getAttribute('name') }"]` ) ]
107
+ .filter( e => e.checked );
108
+ if ( !check.length ) return '';
109
+ ret = check?.[0];
110
+ return ret.value;
111
+ case 'checkbox':
112
+ return that.#e.checked;
113
+ default:
114
+ return that.#e.value;
115
+ break;
116
+ }
117
+
118
+ return '';
119
+ }
120
+
121
+ set val( value: any ){
122
+ let that = this,
123
+ type = that.#type,
124
+ ret: any;
125
+
126
+ switch (type){
127
+ case 'radio':
128
+ const
129
+ radios = [ ...(this.#radioBase || document).querySelectorAll( `input[type="radio"][name="${ this.#e.getAttribute('name') }"]` ) ];
130
+
131
+ // console.log('set radios', selection, this.#radioBase, radios.array );
132
+
133
+ if ( !radios.length ) return;
134
+
135
+ if ( value === '' ){ // uncheck all
136
+ radios.forEach( r => { if (r.checked) r.checked = false } );
137
+ //console.log('unset all radios', radios.array );
138
+ return;
139
+ }
140
+
141
+ const setRadioElement = radios.filter( r => r.getAttribute('value') === value );
142
+
143
+ if ( !setRadioElement.length ) return;
144
+
145
+ // console.log('set this radio', setRadioElement.array );
146
+
147
+ (setRadioElement?.[0] as HTMLInputElement).checked = true;
148
+
149
+ // console.log('done', setRadioElement.array );
150
+ return;
151
+ break;
152
+ case 'checkbox':
153
+ that.#e.checked = value;
154
+ break;
155
+ default:
156
+ that.#e.value = value;
157
+ break;
158
+ }
159
+
160
+ return;
161
+ }
162
+
163
+ }
164
+
165
+ class SelectHandler extends InputBase {
166
+
167
+ #e: HTMLSelectElement;
168
+ #multi: boolean = false;
169
+
170
+ constructor( e: HTMLSelectElement ){
171
+ super( e );
172
+ this.#e = e;
173
+ this.#multi = e.type === 'select-multiple';
174
+ }
175
+
176
+ get val(): string[] | string{
177
+ const
178
+ that = this,
179
+ ret: string[] = [];
180
+
181
+ // get all options
182
+ const options = [ ...that.#e.querySelectorAll('option') ]
183
+ .filter( o => o.selected )
184
+ .forEach( o => { if ( o.selected ) ret.push( o.value ) } );
185
+
186
+ if ( this.#multi ) return ret;
187
+ return ret.length ? ret[0] : '';
188
+ }
189
+
190
+ set val( value: string[] | string ){
191
+ const
192
+ that = this;
193
+
194
+ value = typeof value === 'string' ? [ value ] : value;
195
+
196
+ //console.log('set values', value );
197
+
198
+ // set all options
199
+ const options = [ ...that.#e.querySelectorAll('option') ]
200
+ .forEach( o => {
201
+ if ( value.indexOf( o.value ) > -1 ) {
202
+ o.setAttribute( 'selected', 'selected' )
203
+ o.selected = true;
204
+ } else {
205
+ o.removeAttribute( 'selected' )
206
+ o.selected = false;
207
+ }
208
+ });
209
+
210
+ return;
211
+ }
212
+
213
+ }
214
+
215
+ class TextAreaHandler extends InputBase {
216
+ #e: HTMLTextAreaElement
217
+ constructor( e: HTMLTextAreaElement ){
218
+ super(e);
219
+ this.#e = e;
220
+ }
221
+
222
+ get val(): string{
223
+ return this.#e.value;
224
+ }
225
+
226
+ set val( value: string ){
227
+ this.#e.value = value;
228
+ return;
229
+ }
230
+
231
+ }
232
+
233
+ export const formValues = ( target: HTMLElement | ShadowRoot, values: Object = {}, mc?: typeof MC, observable?: string ): LooseObject => {
234
+
235
+ //console.log( 'values(', target, ',', values, ',', observable, ')' );
236
+
237
+ //console.log( 'values()', values );
238
+ let handlers = getInputHandlers( target );
239
+
240
+ function updateForm( values: Object ){
241
+ Object
242
+ .keys( values )
243
+ .forEach( (key) => {
244
+ if ( handlers.hasOwnProperty(key) && values.hasOwnProperty(key) ) {
245
+ //console.log( 'set value', key, values[key] );
246
+ handlers[key] = (values as LooseObject)[key];
247
+ }
248
+ });
249
+ }
250
+
251
+ if ( Object.keys(values).length > 0 ){
252
+ updateForm( values );
253
+ }
254
+
255
+ //console.log( 'set observable on form change', observable );
256
+ if ( observable !== undefined ){
257
+ let obs = ( mc as LooseObject )[observable];
258
+ if ( !obs.constructor?.hasFormHandler ){
259
+ obs.constructor.hasFormHandler = true;
260
+ obs.observe( updateForm );
261
+ }
262
+
263
+ ( mc as any)[observable].observe( () => { } );
264
+
265
+ [ ...target.querySelectorAll('input, textarea, select') ].forEach( ( e ) => {
266
+ addListener( (e as HTMLElement), 'keyup', () => { ( mc as any)[observable] = structuredClone( Object.assign( handlers ) ) } );
267
+ addListener( (e as HTMLElement), 'change', () => { ( mc as any)[observable] = structuredClone( Object.assign( handlers ) ) } );
268
+ if ( (e as HTMLElement) instanceof HTMLSelectElement ){
269
+ addListener( (e as HTMLElement), 'select', () => { ( mc as any)[observable] = structuredClone( Object.assign( handlers ) ) } );
270
+ };
271
+ });
272
+ }
273
+
274
+ return observable ? ( mc as any)[observable] : Object.assign( {}, handlers );
275
+ }
package/src/helpers.ts ADDED
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+
3
+ export function isObject( value: any ): boolean {
4
+ return value != null && typeof value === 'object';
5
+ }
6
+
7
+ export interface LooseObject {
8
+ [key: string | symbol]: any;
9
+ }
10
+
11
+ export function kebabToPascal(str: string) {
12
+ return str
13
+ .split('-') // Split by hyphens
14
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize each part
15
+ .join(''); // Join without spaces
16
+ }
17
+
18
+ export function debounce( func: Function, milliseconds: number ): Function {
19
+ let timeout: any;
20
+ return () => {
21
+
22
+ clearTimeout( timeout );
23
+
24
+ timeout = setTimeout(
25
+ function(){
26
+ func( ...arguments );
27
+ },
28
+ milliseconds
29
+ );
30
+ };
31
+ };
32
+
33
+ export function deepEqual( o1: any, o2:any): boolean {
34
+ const k1 = Object.keys(o1);
35
+ const k2 = Object.keys(o2);
36
+ if (k1.length !== k2.length) {
37
+ return false;
38
+ }
39
+ for (const key of k1) {
40
+ const
41
+ v1 = o1[key],
42
+ v2 = o2[key],
43
+ recurse = isObject(v1) && isObject(v2);
44
+ ;
45
+ if (
46
+ ( recurse && !deepEqual(v1, v2) )
47
+ || (!recurse && v1 !== v2)
48
+ ) {
49
+ return false;
50
+ }
51
+ }
52
+ return true;
53
+ }
54
+
55
+ export function nameSpace( ns: string, obj: LooseObject, val: any = null, orig?: any ): any {
56
+ let leftOver: Array<any> = ns.split('.');
57
+
58
+ if ( !orig ){
59
+ orig = obj;
60
+ }
61
+
62
+ // console.log( 'start', ns, obj, val, leftOver );
63
+
64
+ let
65
+ last: string = leftOver.shift(), // this property name
66
+ lns: string = leftOver.join('.') // the leftover namespace
67
+ ;
68
+
69
+ if ( val !== null && last.length && obj[last] === undefined ){ // extend if val given and ns leftover...
70
+ // console.log( 'add prop', last );
71
+ obj[last] = {};
72
+ }
73
+
74
+ let
75
+ lob: any = obj[last] // the leftover value or obj
76
+ ;
77
+
78
+ // console.log( 'lob', lob, 'last:', last, 'lns:', lns, 'obj:', obj );
79
+
80
+ if ( lns.length === 0 ){ // this should be the value to set or get
81
+ if ( val !== null ){
82
+ obj[last] = val;
83
+ return orig;
84
+ }
85
+ return obj[last];
86
+ }
87
+
88
+ if ( isObject( obj[last] ) ){
89
+ return nameSpace( lns, obj[last], val, orig );
90
+ } else {
91
+ if (val){
92
+ return orig;
93
+ }
94
+
95
+ return lob[last];
96
+ }
97
+
98
+ }
99
+
100
+ export function parse( what: string | Object | any[], parseThis: Object ){
101
+ var args = Array.from(arguments);
102
+
103
+ if (!args.length){
104
+ console.error('no arguments give to parse');
105
+ return;
106
+ }
107
+
108
+ if (args.length === 1){
109
+ return args[1];
110
+ } else if (args.length > 2) {
111
+ while (args.length > 1){
112
+ args[0] = parse( args[0], args[1]);
113
+ args.splice(1, 1);
114
+ }
115
+ return args[0];
116
+ }
117
+
118
+ // implicit else: exactly 2 arguments
119
+ if ( typeof what === 'string' ){
120
+ var vars = what.match( /\{[^\{\}]*\}/g );
121
+
122
+ if ( !!vars ) {
123
+ vars
124
+ .forEach(
125
+ function (pPropname) {
126
+ var propname = pPropname.substr(1, pPropname.length - 2),
127
+ value = nameSpace( propname, parseThis );
128
+
129
+ if ( typeof value !== 'undefined' ){
130
+ what = (what as string).replace( pPropname, value );
131
+ }
132
+ }
133
+ );
134
+ }
135
+ } else if ( isObject(what) ){
136
+ switch ( what.constructor ){
137
+ case Object:
138
+ Object
139
+ .keys( what )
140
+ .forEach(
141
+ function( pKey ){
142
+ if ( what.hasOwnProperty( pKey ) ){
143
+ ( what as LooseObject )[ pKey ] = parse( ( what as LooseObject )[ pKey ], parseThis );
144
+ }
145
+ }
146
+ );
147
+ break;
148
+ case Array:
149
+ ( what as Array<any> )
150
+ .forEach(
151
+ function( pValue, pKey, original ){
152
+ original[ pKey ] = parse( (what as any)[ pKey ], parseThis );
153
+ }
154
+ );
155
+ break;
156
+ }
157
+ }
158
+
159
+ return what;
160
+ };
161
+
162
+ export function htmlToElements( html: string ): HTMLElement[]{
163
+ let template = document.createElement('template');
164
+
165
+ html = html
166
+ .replace( /<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi, "<$1$2></$1>"); // replace XHTML closing tags by full closing tags
167
+
168
+ template.innerHTML = html;
169
+
170
+ template.content.normalize();
171
+
172
+ return ( Array.from(template.content.childNodes) as HTMLElement[] );
173
+ }