@twobirds/microcomponents 0.0.33 → 0.0.37

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 (118) hide show
  1. package/README.md +40 -27
  2. package/assets/documentation/{MicroComponents.md → MC.md} +17 -17
  3. package/assets/documentation/comparision.md +0 -0
  4. package/assets/documentation/elements.md +276 -0
  5. package/assets/documentation/magic.md +10 -68
  6. package/dist/MC.d.ts +2 -3
  7. package/dist/MC.d.ts.map +1 -1
  8. package/dist/MC.min.js +45 -43
  9. package/dist/MC.ts +173 -175
  10. package/dist/autoloader.ts +1 -1
  11. package/dist/{customElements.d.ts → elements.d.ts} +1 -1
  12. package/dist/elements.d.ts.map +1 -0
  13. package/dist/elements.min.js +1 -0
  14. package/dist/{customElements.ts → elements.ts} +23 -14
  15. package/dist/helpers.d.ts +6 -4
  16. package/dist/helpers.d.ts.map +1 -1
  17. package/dist/helpers.ts +95 -128
  18. package/dist/microcomponents.d.ts +3 -3
  19. package/dist/microcomponents.d.ts.map +1 -1
  20. package/dist/microcomponents.min.js +1 -1
  21. package/dist/microcomponents.ts +3 -3
  22. package/dist/{customObservables.d.ts → observables.d.ts} +3 -3
  23. package/dist/observables.d.ts.map +1 -0
  24. package/dist/observables.min.js +1 -0
  25. package/dist/observables.ts +354 -0
  26. package/dist/{customSelectors.d.ts → selectors.d.ts} +1 -1
  27. package/dist/selectors.d.ts.map +1 -0
  28. package/dist/selectors.min.js +1 -0
  29. package/dist/test.ts +133 -157
  30. package/klemmstein.png +0 -0
  31. package/package.json +52 -52
  32. package/public/MC.js +46 -44
  33. package/public/MC.js.map +1 -1
  34. package/public/MC.min.js +45 -43
  35. package/public/assets/search.js +1 -1
  36. package/public/autoloader.js +1 -1
  37. package/public/autoloader.js.map +1 -1
  38. package/public/classes/{DC.html → MC.DC.html} +60 -59
  39. package/public/classes/{MC.html → MC.MC.html} +41 -35
  40. package/public/classes/{McBase.html → MC.McBase.html} +28 -20
  41. package/public/classes/{McEvent.html → MC.McEvent.html} +48 -42
  42. package/public/documentation/{MicroComponents.md → MC.md} +17 -17
  43. package/public/documentation/comparision.md +0 -0
  44. package/public/documentation/elements.md +276 -0
  45. package/public/documentation/magic.md +10 -68
  46. package/public/{customElements.js → elements.js} +9 -10
  47. package/public/elements.js.map +1 -0
  48. package/public/elements.min.js +1 -0
  49. package/public/functions/{addListener.html → MC.addListener.html} +18 -12
  50. package/public/functions/{removeListener.html → MC.removeListener.html} +18 -12
  51. package/public/functions/elements.defineCE.html +78 -0
  52. package/public/functions/elements.getCE.html +63 -0
  53. package/public/functions/formValues.formValues.html +68 -0
  54. package/public/functions/observables.observe.html +65 -0
  55. package/public/functions/selectors._d.html +69 -0
  56. package/public/functions/selectors._t.html +69 -0
  57. package/public/helpers.js +66 -89
  58. package/public/helpers.js.map +1 -1
  59. package/public/index.html +48 -33
  60. package/public/interfaces/{HTMLMcElement.html → MC.HTMLMcElement.html} +601 -595
  61. package/public/interfaces/selectors.DSelector.html +1013 -0
  62. package/public/interfaces/selectors.TSelector.html +712 -0
  63. package/public/microcomponents.js +3 -3
  64. package/public/microcomponents.js.map +1 -1
  65. package/public/microcomponents.min.js +1 -1
  66. package/public/modules/MC.html +78 -0
  67. package/public/modules/elements.html +62 -0
  68. package/public/modules/formValues.html +60 -0
  69. package/public/modules/observables.html +65 -0
  70. package/public/modules/selectors.html +76 -0
  71. package/public/modules.html +11 -23
  72. package/public/observables.js +255 -0
  73. package/public/observables.js.map +1 -0
  74. package/public/observables.min.js +1 -0
  75. package/public/{customSelectors.js → selectors.js} +1 -1
  76. package/public/selectors.js.map +1 -0
  77. package/public/selectors.min.js +1 -0
  78. package/public/src/MC.ts +376 -0
  79. package/public/src/McEvent.ts +96 -0
  80. package/public/src/autoloader.ts +98 -0
  81. package/{src/customElements.ts → public/src/elements.ts} +23 -14
  82. package/public/src/formValues.ts +275 -0
  83. package/public/src/helpers.ts +140 -0
  84. package/public/src/microcomponents.ts +8 -0
  85. package/public/src/observables.ts +354 -0
  86. package/public/src/test.ts +187 -0
  87. package/public/test.js +99 -115
  88. package/public/test.js.map +1 -1
  89. package/public/types/observables.Observable.html +91 -0
  90. package/public/types/selectors.selection.html +58 -0
  91. package/public/types/selectors.singleSelector.html +58 -0
  92. package/src/MC.ts +173 -175
  93. package/src/autoloader.ts +1 -1
  94. package/src/elements.ts +76 -0
  95. package/src/helpers.ts +95 -128
  96. package/src/microcomponents.ts +3 -3
  97. package/src/observables.ts +354 -0
  98. package/src/selectors.ts +1634 -0
  99. package/src/test.ts +133 -157
  100. package/typedoc.json +1 -1
  101. package/webpack.config.js +9 -9
  102. package/dist/customElements.d.ts.map +0 -1
  103. package/dist/customElements.min.js +0 -1
  104. package/dist/customObservables.d.ts.map +0 -1
  105. package/dist/customObservables.min.js +0 -1
  106. package/dist/customObservables.ts +0 -348
  107. package/dist/customSelectors.d.ts.map +0 -1
  108. package/dist/customSelectors.min.js +0 -1
  109. package/public/customElements.js.map +0 -1
  110. package/public/customElements.min.js +0 -1
  111. package/public/customObservables.js +0 -256
  112. package/public/customObservables.js.map +0 -1
  113. package/public/customObservables.min.js +0 -1
  114. package/public/customSelectors.js.map +0 -1
  115. package/public/customSelectors.min.js +0 -1
  116. package/src/customObservables.ts +0 -348
  117. /package/dist/{customSelectors.ts → selectors.ts} +0 -0
  118. /package/{src/customSelectors.ts → public/src/selectors.ts} +0 -0
@@ -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
+ }
@@ -0,0 +1,140 @@
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
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ export * from './helpers.js';
3
+ export * from './MC.js';
4
+ export * from './McEvent.js';
5
+ export * from './elements.js';
6
+ export * from './observables.js';
7
+ export * from './selectors.js';
8
+ export * from './formValues.js';