@twobirds/microcomponents 0.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.
@@ -0,0 +1,34 @@
1
+ ### RFC Proposal to WHATWG
2
+
3
+ **Title:** Proposal for a **Micro Component Interface** in the DOM
4
+
5
+ **Abstract:**
6
+
7
+ This proposal introduces a standardized interface for managing micro components within HTML elements, enhancing modularity and reusability in web development.
8
+
9
+ **Introduction:**
10
+
11
+ Microcomponents provide a way to encapsulate functionality and state within a target DOM element. This proposal outlines methods for adding, removing, and querying micro components.
12
+
13
+ **Proposed API:**
14
+
15
+ - **Static Methods:**
16
+ - `MC.add(target, key, element)`: Attach a micro component.
17
+ - `MC.remove(target, key)`: Detach a micro component.
18
+
19
+ - **Instance Methods:**
20
+ - `siblings(search)`: Retrieve sibling micro components.
21
+ - `parent(search)`: Get parent micro components.
22
+ - `parents(search)`: Get all ancestor micro components.
23
+ - `children(search)`: Retrieve child micro components.
24
+ - `descendants(search)`: Get all descendant micro components.
25
+
26
+ **Use Cases:**
27
+ 1. Modular web applications.
28
+ 2. Enhancing component-based architecture.
29
+
30
+ **Conclusion:**
31
+ Implementing this interface will streamline microcomponent management, fostering cleaner code and improved performance.
32
+
33
+ **References:**
34
+ - [Microcomponents Repository](https://gitlab.com/twoBirds/microcomponents) for a polyfill implementation and usage examples.
@@ -0,0 +1,15 @@
1
+ <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
2
+ <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
3
+ <title>test</title>
4
+ <rect fill="transparent" x="0" y="0" width="200" height="200" fill-opacity="1"/>
5
+ <g style="fill:transparent">
6
+ <title>first bird</title>
7
+ <path fill="#18829c" d="
8
+ m15,160
9
+ a30,75 45 1 0 160,-150
10
+ a20,50 225 1 1 -110,100
11
+ a12,25 45 1 1 60,-50
12
+ a20,50 225 1 0 -110,100
13
+ " />
14
+ </g>
15
+ </svg>
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ ## MICRO COMPONENTS
2
+
3
+ ![Micro Components Logo](./MicroComponents.svg)
4
+
5
+ This code aims at **improving Javascript modularity**. It does not describe a specific Micro Component itself but rather describes they way they are **organized**. A typical example of a **Micro Component** can be found in "additional concepts" below.
6
+
7
+ Using micro components enforces **DRY, KISS and SOLID** principles in Javascript programming. Read this [RFC](./MicroComponentProposal_draft.md?ref_type=heads) for the shortest info.
8
+
9
+ This is a low-level approach. It consists of a single class with 2 static methods and 5 selector methods, and weights less than 2 kB. Also there is an ES3 version to help e.g. [hbbtv](https://en.wikipedia.org/wiki/Hybrid_Broadcast_Broadband_TV) modular JS coding, or any other device that relies on ES3.
10
+
11
+ For an overview, continue reading.
12
+
13
+ For a detailed functional description goto [Micro Component Usage](https://gitlab.com/twoBirds/microcomponents/-/blob/main/microcomponents_usage.md?ref_type=heads).
14
+
15
+ To see what can be done, go to [additional concepts](https://gitlab.com/twoBirds/microcomponents/-/blob/main/microcomponents_magic.md?ref_type=heads) which delve a little deeper into how to use it, and what it already has been used for.
16
+
17
+
18
+ ## Why would I give this a try in my company?
19
+
20
+ It is lightweight, proven and can yield positive results immediatly.
21
+
22
+
23
+ ### **As the CTO**:
24
+ - **Reusability**: this works with every Javascript framework that allows for DOM access, and it will work as long as the DOM exists in browsers. That is, forever.
25
+ - **Scalability**: scales perfectly by design.
26
+ - **Interoperability**: where many teams in different projects should share specific business or UI logic, you want to have something that works in any JS framework you use.
27
+
28
+ ### **As a Project Manager**:
29
+ - **Separation of Concerns**: since this is a modular approach you can **split UI logic from Business logic** and let diffent teams work on each.
30
+ - using this, you can **work with external developers without the need to give them access to your projects code repository**.
31
+ - you will find out that this allows your project to **become independent from the "tools hell"**. You tend to use **DIY** modules where you had tools before.
32
+
33
+ ### **As a Javascript Developer**:
34
+ - The learning curve to use this is more than shallow. 1 hour should be enough.
35
+ - This is based on **plain Javascript/Typescript, HTML and CSS**. There is no abstraction layer.
36
+ - From the very start **it is fun to work with**. You are back in control of your code without bigger frameworks, but you are able to interact with them.
37
+ - You can **work for any customer right away**. **No training on their system required**, just fulfill their micro component requirements.
38
+ - Over time, you can **build your own framework or functional libraries** from scratch.
39
+
40
+
41
+ ## Functional Requirements
42
+
43
+ - I want to **enrich a standard HTMLElement instance with encapsuled and modular javascript**, without having to resort to web components or big frameworks.
44
+ - I want to have an **interface** into this functionality that I can both tight and loosely couple.
45
+ - I want to **import and use Micro Components in any framework** that allows for direct DOM access.
46
+ - I want **a single location** in an HTMLElement instance where all this functionality is **stored and sufficiently organized**.
47
+ - I want to be able to use **selectors** to find those instances in the DOM.
48
+ - All this must stricly follow **web standards**.
49
+
50
+
51
+ ## Simple Usage:
52
+
53
+ **Micro Components** can be added to to a DOM element like this:
54
+
55
+ before:
56
+ ```HTML
57
+ <button></button>
58
+ ```
59
+
60
+ code: (assume "Button" is some class in a library)
61
+ ```javascript
62
+ import 'MC' from 'twobirds/microcomponents';
63
+ import 'Button' from 'tb/ui'; // made-up example library
64
+
65
+ // select first button element in DOM
66
+ let myButton = document.querySelector('button');
67
+
68
+ // this will add the micro component to the myButton._mc property:
69
+ MC.add( myButton, 'tb_ui_button', new Button( myButton, { ...config data } ) );
70
+ ```
71
+
72
+ after:
73
+ ```HTML
74
+ <button _mc></button>
75
+ ```
76
+ _mc indicates that this HTML element contains at least one micro component. This is needed for the **selectors**.
77
+
78
+
79
+ ```javascript
80
+ console.log( myButton._mc );
81
+ // { tb_ui_button: { target: <button>, onClick: <function> } }
82
+ ```
83
+
84
+ For detailed information jump to [Micro Component Usage](https://gitlab.com/twoBirds/microcomponents/-/blob/main/microcomponents_usage.md?ref_type=heads);
85
+
86
+ ## History
87
+
88
+ I have been working with this since 2004. I used this as core principle inside my twoBirds framework.
89
+
90
+ This functionality has been used in very big and complicated data processing projects:
91
+ - to allow for web component like programming (as early as 2004)
92
+ - to encapsule UI handling
93
+ - to represent business processes and their tasks
94
+ - and lately to compose very complex native web components from distinct modular functionality.
95
+
96
+ I decided extract this from the [twoBirds framework](https://www.npmjs.com/package/twobirds-core), since it is framework agnostic and relies solely on the standard DOM and native javascript or typescript.
97
+
98
+ ## Contact
99
+ Feel free to contact me for any questions or inquiries:
100
+
101
+ email [Frank Thürigen](mailto:fthuerigen@gmail.com?subject=Micro%20Components) or [Skype](skype:frank.thuerigen)
102
+
103
+ And yes, you can [fund this](https://gofund.me/076c614c).
package/checklist.md ADDED
@@ -0,0 +1,93 @@
1
+ # MicroComponents
2
+
3
+
4
+
5
+ ## Getting started
6
+
7
+ To make it easy for you to get started with GitLab, here's a list of recommended next steps.
8
+
9
+ Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
10
+
11
+ ## Add your files
12
+
13
+ - [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
14
+ - [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
15
+
16
+ ```
17
+ cd existing_repo
18
+ git remote add origin https://gitlab.com/twoBirds/microcomponents.git
19
+ git branch -M main
20
+ git push -uf origin main
21
+ ```
22
+
23
+ ## Integrate with your tools
24
+
25
+ - [ ] [Set up project integrations](https://gitlab.com/twoBirds/microcomponents/-/settings/integrations)
26
+
27
+ ## Collaborate with your team
28
+
29
+ - [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
30
+ - [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
31
+ - [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
32
+ - [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
33
+ - [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
34
+
35
+ ## Test and Deploy
36
+
37
+ Use the built-in continuous integration in GitLab.
38
+
39
+ - [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
40
+ - [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
41
+ - [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
42
+ - [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
43
+ - [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
44
+
45
+ ***
46
+
47
+ # Editing this README
48
+
49
+ When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
50
+
51
+ ## Suggestions for a good README
52
+
53
+ Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
54
+
55
+ ## Name
56
+ Choose a self-explaining name for your project.
57
+
58
+ ## Description
59
+ Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
60
+
61
+ ## Badges
62
+ On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
63
+
64
+ ## Visuals
65
+ Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
66
+
67
+ ## Installation
68
+ Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
69
+
70
+ ## Usage
71
+ Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
72
+
73
+ ## Support
74
+ Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
75
+
76
+ ## Roadmap
77
+ If you have ideas for releases in the future, it is a good idea to list them in the README.
78
+
79
+ ## Contributing
80
+ State if you are open to contributions and what your requirements are for accepting them.
81
+
82
+ For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
83
+
84
+ You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
85
+
86
+ ## Authors and acknowledgment
87
+ Show your appreciation to those who have contributed to the project.
88
+
89
+ ## License
90
+ For open source projects, say how it is licensed.
91
+
92
+ ## Project status
93
+ If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
@@ -0,0 +1,15 @@
1
+ <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
2
+ <!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
3
+ <title>test</title>
4
+ <rect fill="transparent" x="0" y="0" width="200" height="200" fill-opacity="1"/>
5
+ <g style="fill:transparent">
6
+ <title>first bird</title>
7
+ <path fill="#18829c" d="
8
+ m15,160
9
+ a30,75 45 1 0 160,-150
10
+ a20,50 225 1 1 -110,100
11
+ a12,25 45 1 1 60,-50
12
+ a20,50 225 1 0 -110,100
13
+ " />
14
+ </g>
15
+ </svg>
@@ -0,0 +1,21 @@
1
+ export declare class MC {
2
+ private target;
3
+ private privateMCs;
4
+ static debug: boolean;
5
+ constructor(target?: HTMLElement | null);
6
+ static add(element?: any, key?: string, target?: HTMLElement): any;
7
+ add(element?: any, key?: string, target?: HTMLElement): any;
8
+ static remove(target: HTMLElement, key: string): void;
9
+ remove(key: string): void;
10
+ private getMicroComponents;
11
+ private traverseNodes;
12
+ siblings(search?: string): any[];
13
+ parent(search?: string): any[];
14
+ parents(search?: string): any[];
15
+ children(search?: string): any[];
16
+ descendants(search?: string): any[];
17
+ }
18
+ export interface HTMLElementMc extends HTMLElement {
19
+ _mc: MC;
20
+ }
21
+ //# sourceMappingURL=microcomponents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"microcomponents.d.ts","sourceRoot":"","sources":["../src/microcomponents.ts"],"names":[],"mappings":"AACA,qBAAa,EAAE;IAEd,OAAO,CAAC,MAAM,CAAqB;IAEnC,OAAO,CAAC,UAAU,CAA8B;IAEhD,MAAM,CAAC,KAAK,EAAE,OAAO,CAAS;gBAElB,MAAM,GAAE,WAAW,GAAG,IAAW;IAM7C,MAAM,CAAC,GAAG,CAAE,OAAO,GAAE,GAAQ,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAI,GAAG;IAuBxE,GAAG,CAAE,OAAO,GAAE,GAAQ,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAI,GAAG;IAcjE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAkBrD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAiBzB,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,aAAa;IAwBrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE;IAKhC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE;IAQ9B,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE;IAQ/B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE;IAUhC,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,EAAE;CAInC;AAED,MAAM,WAAW,aAAc,SAAQ,WAAW;IACjD,GAAG,EAAE,EAAE,CAAC;CACR"}
@@ -0,0 +1,16 @@
1
+ declare function __isEmpty(obj: any): boolean;
2
+ declare function MC(target: any): void;
3
+ declare class MC {
4
+ constructor(target: any);
5
+ _target: any;
6
+ siblings(search: any): any[];
7
+ parent(search: any): any;
8
+ parents(search: any): any[];
9
+ children(search: any): any[];
10
+ descendants(search: any): any[];
11
+ }
12
+ declare namespace MC {
13
+ function add(domElement: any, key: any, element: any): typeof MC;
14
+ function remove(domElement: any, key: any): typeof MC;
15
+ }
16
+ //# sourceMappingURL=microcomponents.es3.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"microcomponents.es3.d.ts","sourceRoot":"","sources":["../src/microcomponents.es3.js"],"names":[],"mappings":"AAEA,8CAQC;AAED,uCAEC;;IAFD,yBAEC;IADA,aAAqB;IAqBtB,6BAcC;IAED,yBAUC;IAED,4BAUC;IAED,6BAeC;IAED,gCAcC;;;IAxFD,iEAMC;IAED,sDAMC"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ function __isEmpty(obj) {
3
+ if (!obj)
4
+ return false;
5
+ for (var key in obj) {
6
+ if (obj.hasOwnProperty(key) && key !== "_target") {
7
+ return false;
8
+ }
9
+ }
10
+ return true;
11
+ }
12
+ function MC(target) {
13
+ this._target = target;
14
+ }
15
+ // static functions, chainable
16
+ MC.add = function (domElement, key, element) {
17
+ if (key && typeof key === "string" && domElement && !domElement._mc[key]) {
18
+ domElement.mc[key] = element;
19
+ domElement.setAttribute("_mc", "");
20
+ }
21
+ return this;
22
+ };
23
+ MC.remove = function (domElement, key) {
24
+ delete domElement._mc[key];
25
+ if (isEmpty(this)) {
26
+ this._target.removeAttribute("_mc");
27
+ }
28
+ return this;
29
+ };
30
+ // other methods, not chainable
31
+ MC.prototype.siblings = function (search) {
32
+ var mcValues = [];
33
+ if (this._target._mc) {
34
+ for (var key in this._target._mc) {
35
+ if (key !== "_target" &&
36
+ this._target._mc.hasOwnProperty(key) &&
37
+ (!search || key === search)) {
38
+ mcValues.push(this._target._mc[key]);
39
+ }
40
+ }
41
+ }
42
+ return mcValues;
43
+ };
44
+ MC.prototype.parent = function (search) {
45
+ var mcValues = [];
46
+ var current = this._target.parentNode;
47
+ while (current) {
48
+ if (current._mc) {
49
+ return current._mc.siblings(search);
50
+ }
51
+ current = current.parentNode;
52
+ }
53
+ return mcValues;
54
+ };
55
+ MC.prototype.parents = function (search) {
56
+ var mcValues = [];
57
+ var current = this._target.parentNode;
58
+ while (current) {
59
+ if (current._mc) {
60
+ mcValues = mcValues.concat(current._mc.siblings(search));
61
+ }
62
+ current = current.parentNode;
63
+ }
64
+ return mcValues;
65
+ };
66
+ MC.prototype.children = function (search) {
67
+ var mcValues = [];
68
+ function traverseTree(element) {
69
+ var children = element.children;
70
+ for (var i = 0; i < children.length; i++) {
71
+ var child = children[i];
72
+ if (child._mc) {
73
+ mcValues = mcValues.concat(child._mc.siblings(search));
74
+ continue;
75
+ }
76
+ traverseTree(child);
77
+ }
78
+ }
79
+ traverseTree(this._target);
80
+ return mcValues;
81
+ };
82
+ MC.prototype.descendants = function (search) {
83
+ var mcValues = [];
84
+ function traverseTree(element) {
85
+ var children = element.children;
86
+ for (var i = 0; i < children.length; i++) {
87
+ var child = children[i];
88
+ if (child._mc) {
89
+ mcValues = mcValues.concat(child._mc.siblings(search));
90
+ }
91
+ traverseTree(child);
92
+ }
93
+ }
94
+ traverseTree(this._target);
95
+ return mcValues;
96
+ };
@@ -0,0 +1,15 @@
1
+ "use strict";function __isEmpty(obj){if(!obj)return false;for(var key in obj){if(obj.hasOwnProperty(key)&&key!=="_target"){return false;}}
2
+ return true;}
3
+ function MC(target){this._target=target;}
4
+ MC.add=function(domElement,key,element){if(key&&typeof key==="string"&&domElement&&!domElement._mc[key]){domElement.mc[key]=element;domElement.setAttribute("_mc","");}
5
+ return this;};MC.remove=function(domElement,key){delete domElement._mc[key];if(isEmpty(this)){this._target.removeAttribute("_mc");}
6
+ return this;};MC.prototype.siblings=function(search){var mcValues=[];if(this._target._mc){for(var key in this._target._mc){if(key!=="_target"&&this._target._mc.hasOwnProperty(key)&&(!search||key===search)){mcValues.push(this._target._mc[key]);}}}
7
+ return mcValues;};MC.prototype.parent=function(search){var mcValues=[];var current=this._target.parentNode;while(current){if(current._mc){return current._mc.siblings(search);}
8
+ current=current.parentNode;}
9
+ return mcValues;};MC.prototype.parents=function(search){var mcValues=[];var current=this._target.parentNode;while(current){if(current._mc){mcValues=mcValues.concat(current._mc.siblings(search));}
10
+ current=current.parentNode;}
11
+ return mcValues;};MC.prototype.children=function(search){var mcValues=[];function traverseTree(element){var children=element.children;for(var i=0;i<children.length;i++){var child=children[i];if(child._mc){mcValues=mcValues.concat(child._mc.siblings(search));continue;}
12
+ traverseTree(child);}}
13
+ traverseTree(this._target);return mcValues;};MC.prototype.descendants=function(search){var mcValues=[];function traverseTree(element){var children=element.children;for(var i=0;i<children.length;i++){var child=children[i];if(child._mc){mcValues=mcValues.concat(child._mc.siblings(search));}
14
+ traverseTree(child);}}
15
+ traverseTree(this._target);return mcValues;};
@@ -0,0 +1,133 @@
1
+ 'use strict';
2
+ export class MC {
3
+ target;
4
+ privateMCs = {};
5
+ static debug = false;
6
+ constructor(target = null) {
7
+ this.target = target;
8
+ this.privateMCs = {};
9
+ }
10
+ // add a microcomponent to a target DOM node
11
+ static add(element = {}, key, target) {
12
+ const mc = target;
13
+ if (key && target) {
14
+ // create the _mc property if necessary
15
+ if (!mc._mc) {
16
+ mc._mc = new MC();
17
+ }
18
+ // add the element with the given property key to the _mc property object
19
+ if (key && !mc._mc[key]) {
20
+ mc._mc[key] = element;
21
+ if (target) {
22
+ target.setAttribute('_mc', '');
23
+ }
24
+ }
25
+ }
26
+ return element;
27
+ }
28
+ // add a microcomponent to the DOM or to the private microcomponent collection
29
+ add(element = {}, key, target) {
30
+ // add the element
31
+ if (target && key) {
32
+ // ...to the DOM
33
+ MC.add(element, key, target);
34
+ }
35
+ else if (key) {
36
+ // ... to the private element collection
37
+ this.privateMCs[key] = element;
38
+ }
39
+ return element;
40
+ }
41
+ // remove a micro component from the DOM
42
+ static remove(target, key) {
43
+ const mc = target;
44
+ // delete the property from the DOM
45
+ if (mc._mc && mc._mc[key]) {
46
+ delete mc._mc[key];
47
+ }
48
+ // remove the _mc attribute if the DOM collection is empty
49
+ if (!Object.keys(mc._mc).length && target.hasAttribute('_mc')) {
50
+ target.removeAttribute('_mc');
51
+ }
52
+ return;
53
+ }
54
+ // remove a micro component from the DOM or the private microcomponent collection
55
+ remove(key) {
56
+ // remove the component from the private collection
57
+ if (key in this.privateMCs) {
58
+ delete this.privateMCs[key];
59
+ }
60
+ if (MC.debug && this.target) {
61
+ MC.remove(this.target, key);
62
+ }
63
+ }
64
+ /*
65
+ helper methods
66
+ */
67
+ // get all microcomponents from a list of HTMLElements
68
+ getMicroComponents(elements, search) {
69
+ let mcValues = [];
70
+ elements.forEach(e => {
71
+ if (e) {
72
+ if (!search && e._mc) {
73
+ mcValues = mcValues.concat(Object.values(e._mc));
74
+ }
75
+ else if (search && e._mc && e._mc[search]) {
76
+ mcValues.push(e._mc[search]);
77
+ }
78
+ }
79
+ });
80
+ return mcValues;
81
+ }
82
+ // get all ancestor DOM nodes up to the document
83
+ traverseNodes(node, search, firstonly = true) {
84
+ let mcValues = [];
85
+ while (node) {
86
+ if (node._mc) {
87
+ if (!search) {
88
+ mcValues = mcValues.concat(Object.values(node._mc));
89
+ }
90
+ else if (search && node._mc[search]) {
91
+ mcValues.push(node._mc[search]);
92
+ }
93
+ if (firstonly)
94
+ return mcValues;
95
+ }
96
+ node = node.parentNode;
97
+ }
98
+ return mcValues;
99
+ }
100
+ /*
101
+ selector methods, non-chainable
102
+ */
103
+ // all public _mc members and private collection members
104
+ siblings(search) {
105
+ return this.getMicroComponents([this.target], search).concat(Object.entries(this.privateMCs));
106
+ }
107
+ // first anchestor DOM node, all puclic MCs
108
+ parent(search) {
109
+ if (!this.target)
110
+ return [];
111
+ return this.traverseNodes(this.target.parentNode, search, true);
112
+ }
113
+ // all anchestor DOM nodes, beginning with the closest, all puclic MCs
114
+ parents(search) {
115
+ if (!this.target)
116
+ return [];
117
+ return this.traverseNodes(this.target.parentNode, search, false);
118
+ }
119
+ // nearest child DOM nodes, all puclic MCs
120
+ children(search) {
121
+ const id = crypto.randomUUID();
122
+ this.target.setAttribute('temp-id', id);
123
+ const myDomElements = this.target.querySelectorAll(`*[_mc]:not([temp-id="${id}"] [_mc] [_mc])`);
124
+ const mcValues = this.getMicroComponents([...myDomElements], search);
125
+ this.target.removeAttribute('temp-id');
126
+ return mcValues;
127
+ }
128
+ // all descendant DOM nodes, all puclic MCs
129
+ descendants(search) {
130
+ const myDomElements = this.target.querySelectorAll('*[_mc]');
131
+ return this.getMicroComponents([...myDomElements], search);
132
+ }
133
+ }
@@ -0,0 +1,27 @@
1
+ 'use strict';export class MC{target;privateMCs={};static debug=false;constructor(target=null){this.target=target;this.privateMCs={};}
2
+ static add(element={},key,target){const mc=target;if(key&&target){if(!mc._mc){mc._mc=new MC();}
3
+ if(key&&!mc._mc[key]){mc._mc[key]=element;if(target){target.setAttribute('_mc','');}}}
4
+ return element;}
5
+ add(element={},key,target){if(target&&key){MC.add(element,key,target);}
6
+ else if(key){this.privateMCs[key]=element;}
7
+ return element;}
8
+ static remove(target,key){const mc=target;if(mc._mc&&mc._mc[key]){delete mc._mc[key];}
9
+ if(!Object.keys(mc._mc).length&&target.hasAttribute('_mc')){target.removeAttribute('_mc');}
10
+ return;}
11
+ remove(key){if(key in this.privateMCs){delete this.privateMCs[key];}
12
+ if(MC.debug&&this.target){MC.remove(this.target,key);}}
13
+ getMicroComponents(elements,search){let mcValues=[];elements.forEach(e=>{if(e){if(!search&&e._mc){mcValues=mcValues.concat(Object.values(e._mc));}
14
+ else if(search&&e._mc&&e._mc[search]){mcValues.push(e._mc[search]);}}});return mcValues;}
15
+ traverseNodes(node,search,firstonly=true){let mcValues=[];while(node){if(node._mc){if(!search){mcValues=mcValues.concat(Object.values(node._mc));}
16
+ else if(search&&node._mc[search]){mcValues.push(node._mc[search]);}
17
+ if(firstonly)
18
+ return mcValues;}
19
+ node=node.parentNode;}
20
+ return mcValues;}
21
+ siblings(search){return this.getMicroComponents([this.target],search).concat(Object.entries(this.privateMCs));}
22
+ parent(search){if(!this.target)
23
+ return[];return this.traverseNodes(this.target.parentNode,search,true);}
24
+ parents(search){if(!this.target)
25
+ return[];return this.traverseNodes(this.target.parentNode,search,false);}
26
+ children(search){const id=crypto.randomUUID();this.target.setAttribute('temp-id',id);const myDomElements=this.target.querySelectorAll(`*[_mc]:not([temp-id="${id}"][_mc][_mc])`);const mcValues=this.getMicroComponents([...myDomElements],search);this.target.removeAttribute('temp-id');return mcValues;}
27
+ descendants(search){const myDomElements=this.target.querySelectorAll('*[_mc]');return this.getMicroComponents([...myDomElements],search);}}
package/docs/.nojekyll ADDED
@@ -0,0 +1 @@
1
+ TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.