# Micro Component Management

This system allows you to attach, manage, and interact with micro components.

**Micro Components** can literally be anything you can put into an object as a property.

Also it has selectors to find micro components in the DOM. It consists of a single class `MC`.

## Summary of MC() Methods

- **Static Methods:**
  - `MC.add( target, key, element)`: Attach a top level micro component to an HTMLElement.
  - `MC.remove( target, key )`: Detach a top level micro component from an HTMLElement.
  - `MC.siblings( target )`: get top level micro components from an HTMLElement.

- **Instance Methods:**
  - `add( key, element )`: Attach a private Micro Component to a Micro Component.
  - `remove( key )`: Detach a private Micro Component from a Micro Component.
  - `siblings(search?)`: Retrieve sibling micro components.
  - `parent(search?)`: Get parent top level micro components.
  - `parents(search?)`: Get all ancestor top level micro components.
  - `children(search?)`: Retrieve child top level micro components.
  - `descendants(search?)`: Get all descendant top level micro components.

**Micro Components** will most likely be **class instances** that expose inner methods **or an observable collection** for data driven workflows, e.g. business process logic.

## Typical Workflow

1. **Attach micro components** to elements using `MC.add()`.
2. **Access** micro components by their property key or navigating through DOM (e.g., `siblings()`, `parents()`, `children()`, etc.) **and use their inner functionality**.
3. **Manipulate** micro components by adding or removing them as needed or change their properties/call their methods.


## Hints

- **All static methods handle top level Micro Components. These are PUBLIC, that is they are visible in the DOM elements _mc property and usually have an interface.**

- **All MC instance methods handle inner Micro Components. These are PRIVATE, that is they are not visible in the DOM elements _mc property.**

- **Micro Components can recursively contain Micro Components. Just like npm and the node_modules directory.**


## Attaching a top level Micro Component to a DOM element

To attach a micro component to an HTML element, use the `MC.add()` static function.

### Example Usage:
```javascript
const myElement = document.getElementById('myDiv');

// Attach a micro component (most often a class instance, here a simple object for simplicity) with a specific key
MC.add( myElement, 'myComponent', { name: 'Mike' } );
```

- After you added a micro component using this function, the HTMLElement will contain a  property `_mc` which is a MC() class instance that offers some methods.
- Also the HTMLElement then has an attribute _mc which will indicate that at least one micro component is attached to this dom element.

## Removing a top level Micro Component from a DOM element

Micro components can be removed using the `MC.remove()` static method.

### Removing a Micro component:
```javascript
MC.remove( myDomElement, 'myComponent');
```

**When all micro components are removed** (the _mc object has no more properties), the `_mc` **attribute is also removed** from the HTML element. The `_mc` **property persists**.


## Retrieve all top level Micro Components from a DOM element

The `MC.siblings()` method retrieves all top level micro components attached to the same DOM element.

### Example:
```javascript
const target = document.querySelector( 'div' );
const siblings = MC.siblings( target );
console.log(siblings);  // Logs an array of top level sibling micro components
```

To retrieve a specific micro component by its key:
```javascript
const target = document.querySelector( 'div' );
const siblings = MC.siblings( target, 'myOtherComponent' );
console.log(siblings);  // Logs an array containing a top level sibling micro component, if its key matches the search string
```


## Retrieving Sibling Micro components

The `.siblings()` method retrieves all micro components attached to the same DOM element.

### Example:
```javascript
const siblings = myElement._mc.siblings();
console.log(siblings);  // Logs an array of sibling micro components
```

To retrieve a specific micro component by its key:
```javascript
const specificSibling = myElement._mc.siblings('anotherComponent');
```


- **The following methods hop over HTMLElements that contain no micro component.**


## 4. Navigating Parent and Ancestor Micro components

The `_mc.parent()` and `_mc.parents()` methods allow you to retrieve micro components attached to parent elements.

### Example:
```javascript
const parentMc = myElement._mc.parent();
console.log(parentMc);  // Logs micro components closest nachestor that has microcomponents

const allAncestorsMc = myElement._mc.parents();
console.log(allAncestorsMc);  // Logs all ancestor micro components up to document
```

To retrieve a specific micro component attached to the parent or ancestors:
```javascript
const specificAncestorMc = myElement._mc.parents('myComponent');
```

## 5. Retrieving Child and Descendant Micro components

The `_mc.children()` and `_mc.descendants()` methods retrieve micro components attached to child elements or any descendants.

### Example:
```javascript
const childMicro components = myElement._mc.children();
console.log(childMicro components);  // Logs an array of nearest child micro components

const descendantMicro components = myElement._mc.descendants();
console.log(descendantMicro components);  // Logs micro components attached to all descendants
```

To search for a specific micro component by key:
```javascript
const specificMc = myElement._mc.<someComponent>;
```
