@twobirds/microcomponents 0.10.1 → 0.10.2
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/dist/MC.min.js +1 -1
- package/dist/autoload.min.js +1 -1
- package/dist/cli/index.js +18 -22
- package/dist/cli/inliner.d.ts +8 -5
- package/dist/cli/inliner.d.ts.map +1 -1
- package/dist/core/MC.d.ts +98 -50
- package/dist/core/MC.d.ts.map +1 -1
- package/dist/core/elements.js +134 -76
- package/dist/core/index.d.ts +5 -4
- package/dist/core/index.d.ts.map +1 -1
- package/dist/docs/api-external.d.ts +101 -0
- package/dist/docs/api-external.d.ts.map +1 -0
- package/dist/docs/cli.d.ts +115 -0
- package/dist/docs/cli.d.ts.map +1 -0
- package/dist/docs/concepts.d.ts +42 -0
- package/dist/docs/concepts.d.ts.map +1 -0
- package/dist/docs/installation.d.ts +74 -0
- package/dist/docs/installation.d.ts.map +1 -0
- package/dist/docs/mcp.d.ts +45 -0
- package/dist/docs/mcp.d.ts.map +1 -0
- package/dist/elements.min.js +1 -1
- package/dist/formValues.min.js +1 -1
- package/dist/mcp/api.json +325 -29
- package/dist/mcp/concepts/event-system.md +1 -1
- package/dist/mcp/index.js +13 -6
- package/dist/microcomponents.js +145 -82
- package/dist/microcomponents.min.js +1 -1
- package/dist/observables.min.js +1 -1
- package/dist/state/formValues.d.ts +3 -3
- package/dist/state/formValues.js +139 -81
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/observables.d.ts +2 -2
- package/dist/state/observables.js +136 -78
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/helpers.d.ts +12 -0
- package/dist/utils/helpers.d.ts.map +1 -1
- package/package.json +3 -2
package/dist/core/elements.js
CHANGED
|
@@ -286,6 +286,20 @@ function kebabToPascal(str) {
|
|
|
286
286
|
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
287
287
|
}
|
|
288
288
|
/**
|
|
289
|
+
* Converts a PascalCase string to kebab-case.
|
|
290
|
+
* Example: 'MyComponentName' -> 'my-component-name'
|
|
291
|
+
* @param str - The PascalCase string to convert.
|
|
292
|
+
* @returns The converted kebab-case string.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```ts
|
|
296
|
+
* console.log(pascalToKebab('MyElement'));
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
function pascalToKebab(str) {
|
|
300
|
+
return str.replace(/[A-Z]/g, (m, i) => (i ? "-" : "") + m.toLowerCase());
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
289
303
|
* Injects a CSS string into the given scope (document or shadow root) as an adopted stylesheet.
|
|
290
304
|
* Enables css-in-js so that every custom element is self-contained and importable.
|
|
291
305
|
*
|
|
@@ -509,13 +523,15 @@ function remove(target, key) {
|
|
|
509
523
|
if (!Object.keys(_mc).length && target instanceof HTMLElement && target.hasAttribute("data-mc")) target.removeAttribute("data-mc");
|
|
510
524
|
}
|
|
511
525
|
/**
|
|
512
|
-
Runs the "Init" lifecycle event on a DOM microcomponent instance
|
|
526
|
+
Runs the "Init" lifecycle event on a DOM microcomponent instance.
|
|
513
527
|
|
|
514
528
|
This function schedules the `trigger('Init')` call in a microtask, ensuring
|
|
515
529
|
that all synchronous initialization is complete before the lifecycle hook
|
|
516
|
-
executes.
|
|
517
|
-
|
|
518
|
-
|
|
530
|
+
executes. The {@link DC} constructor calls it once the declared assets are in
|
|
531
|
+
place — synchronously in a bundled build, after the fetch resolves in a
|
|
532
|
+
dev/autoload build — so `oneInit()` always sees the loaded assets. Only `DC`
|
|
533
|
+
instances have an Init lifecycle — the `DC` constructor calls this exclusively,
|
|
534
|
+
so the signature encodes that invariant instead of re-checking it at runtime.
|
|
519
535
|
|
|
520
536
|
@param element - The DOM microcomponent instance on which to trigger the Init event.
|
|
521
537
|
*/
|
|
@@ -583,16 +599,18 @@ function findMcAncestor(from, key) {
|
|
|
583
599
|
The base class for all microcomponents — shared root of both {@link MC} and {@link DC}.
|
|
584
600
|
|
|
585
601
|
Holds a `WeakRef` to the target (a DOM element for `DC`, or any plain object for `MC`)
|
|
586
|
-
to avoid circular references.
|
|
587
|
-
|
|
602
|
+
to avoid circular references. It starts loading any `static assets` for `MC` and `DC`
|
|
603
|
+
alike (shared per class through `_assetsPromise`), read through the {@link McBase.assets}
|
|
604
|
+
getter. For `DC` subclasses it bootstraps one automatic behaviour:
|
|
588
605
|
|
|
589
606
|
1. **Event listener auto-attachment** — methods whose names start with `on` or `one`
|
|
590
607
|
(e.g. `onClick`, `oneInit`) are wired to the target element via {@link on} / {@link one}.
|
|
591
|
-
2. **"Init" lifecycle event** — dispatched asynchronously in a microtask so that all
|
|
592
|
-
synchronous constructor work finishes first.
|
|
593
608
|
|
|
594
|
-
|
|
595
|
-
|
|
609
|
+
The **"Init" lifecycle event** and the DOM attach of auto-attached assets are dispatched
|
|
610
|
+
by the {@link DC} constructor — after the declared assets are in place — so that
|
|
611
|
+
`oneInit()` runs once the instance is fully constructed and its assets are loaded. Plain
|
|
612
|
+
`MC` instances fetch their assets server-side with no DOM attach and no `Init` lifecycle,
|
|
613
|
+
keeping server-side usage lightweight.
|
|
596
614
|
|
|
597
615
|
### Plugin extension points
|
|
598
616
|
|
|
@@ -645,20 +663,45 @@ runs once after the constructor.
|
|
|
645
663
|
var McBase = class {
|
|
646
664
|
_target;
|
|
647
665
|
/**
|
|
666
|
+
* Loaded asset cache, keyed by camelCase descriptor (`'targetHtml'` → `.target.html`).
|
|
667
|
+
* Inlined by the bundler in a bundled build, filled by `loadAssets()` in dev/autoload.
|
|
668
|
+
* Read through the {@link McBase.assets} getter.
|
|
669
|
+
*/
|
|
670
|
+
static _assets = {};
|
|
671
|
+
/**
|
|
672
|
+
* Declares companion files for auto-loading by convention (e.g. `['targetHtml', 'json']`).
|
|
673
|
+
* Asset names are camelCase and translated into file extensions: `'targetHtml'` → `.target.html`.
|
|
674
|
+
*/
|
|
675
|
+
static assets = [];
|
|
676
|
+
/**
|
|
677
|
+
* In-flight asset request, cached per class so that instances constructed while
|
|
678
|
+
* the first fetch is still pending (e.g. in a loop) share a single request
|
|
679
|
+
* instead of each triggering their own. Resolves to the freshly loaded assets.
|
|
680
|
+
*/
|
|
681
|
+
static _assetsPromise;
|
|
682
|
+
/**
|
|
648
683
|
The constructor for the base `McBase` class.
|
|
649
684
|
|
|
650
|
-
Initializes a weak reference to the target
|
|
651
|
-
|
|
685
|
+
Initializes a weak reference to the target, auto-attaches listeners for `DC`
|
|
686
|
+
subclasses, and starts loading any `static assets` for `MC` and `DC` alike —
|
|
687
|
+
a server-side `MC` fetches them with no DOM, a `DC` gets them attached by its
|
|
688
|
+
own constructor. The load is shared per class through `_assetsPromise`.
|
|
652
689
|
|
|
653
690
|
@param target - The object or element this microcomponent represents.
|
|
654
691
|
*/
|
|
655
692
|
constructor(target) {
|
|
656
693
|
this._target = new WeakRef(target || {});
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
694
|
+
const ctor = this.constructor;
|
|
695
|
+
if (this instanceof DC && this.constructor !== DC) autoAttachListeners(this);
|
|
696
|
+
const remaining = (ctor.assets ?? []).filter((key) => !ctor._assets[key]);
|
|
697
|
+
if (remaining.length && !ctor._assetsPromise) ctor._assetsPromise = loadAssets(ctor._originalTag || (this instanceof DC ? this.target.tagName.toLowerCase() : pascalToKebab(ctor.name)), remaining).then((res) => {
|
|
698
|
+
const loadedAssets = {};
|
|
699
|
+
remaining.forEach((key, i) => {
|
|
700
|
+
loadedAssets[key] = res[i];
|
|
701
|
+
});
|
|
702
|
+
ctor._assets = Object.assign({}, ctor._assets, loadedAssets);
|
|
703
|
+
return loadedAssets;
|
|
704
|
+
});
|
|
662
705
|
}
|
|
663
706
|
/**
|
|
664
707
|
Returns the current target object (DOM node or other data) referenced by this microcomponent.
|
|
@@ -676,6 +719,21 @@ var McBase = class {
|
|
|
676
719
|
get target() {
|
|
677
720
|
return this._target.deref();
|
|
678
721
|
}
|
|
722
|
+
/**
|
|
723
|
+
The loaded assets for this component instance.
|
|
724
|
+
|
|
725
|
+
`static assets` are loaded before `oneInit()` fires on a `DC`, so this getter is
|
|
726
|
+
ready inside the `oneInit()` callback. A server-side `MC` fills it from `loadAssets()`;
|
|
727
|
+
await `MC._assetsPromise` before reading it. It returns the merged asset record keyed
|
|
728
|
+
by descriptor: `css` / `targetCss` / `shadowCss` / `shadowHtml` / `targetHtml` arrive
|
|
729
|
+
as strings, `*Json` entries arrive parsed, and a plain `html` template is returned as a
|
|
730
|
+
string for `parse()`. An empty object when no assets are declared.
|
|
731
|
+
|
|
732
|
+
@returns A record mapping asset keys to their content.
|
|
733
|
+
*/
|
|
734
|
+
get assets() {
|
|
735
|
+
return this.constructor._assets || {};
|
|
736
|
+
}
|
|
679
737
|
};
|
|
680
738
|
/**
|
|
681
739
|
@class DC
|
|
@@ -733,14 +791,26 @@ and translated into file extensions: `'targetHtml'` → `.target.html`, `'json'`
|
|
|
733
791
|
The path is derived from the custom element tag segments, and the basename is the
|
|
734
792
|
last segment. For `<cart-container-checkout>`, assets load from `/cart/container/checkout.*`.
|
|
735
793
|
|
|
736
|
-
|
|
737
|
-
|
|
794
|
+
**Assets are loaded before `oneInit()` fires.** The constructor applies them to the
|
|
795
|
+
target, then dispatches the `Init` lifecycle event — synchronously in a bundled build
|
|
796
|
+
(assets inlined), after the fetch resolves in a dev/autoload build. Inside `oneInit()`
|
|
797
|
+
the loaded assets are read through the {@link DC.assets} getter. Everything ending in
|
|
798
|
+
`Json` arrives parsed; all other files arrive as text.
|
|
799
|
+
|
|
800
|
+
**Auto-attached assets**: `.css`, `.target.css`, `.shadow.css`, `.target.html` and
|
|
801
|
+
`.shadow.html` are attached automatically by `processAssets()` — CSS is injected into
|
|
802
|
+
the document or shadow scope, HTML is set as `target.innerHTML` / `shadowRoot.innerHTML`,
|
|
803
|
+
and native event handlers in the template (`<button click="this|go">`) are wired.
|
|
804
|
+
|
|
805
|
+
**Plain `.html` is NOT auto-attached.** It is a template held in {@link DC.assets} for
|
|
806
|
+
components created programmatically with a `data` parameter: in `oneInit()` you compile
|
|
807
|
+
the target markup from template + data with `parse()`.
|
|
738
808
|
|
|
739
809
|
**One-time global styles**: Assets named `'css'` and `'targetCss'` inject CSS into the
|
|
740
810
|
global document scope via `injectCSS(document, ...)`. Because these are idempotent
|
|
741
811
|
global side effects, they are processed only once — after the first instance loads them,
|
|
742
|
-
the entries are
|
|
743
|
-
|
|
812
|
+
the entries are dropped from `static _assets`. Subsequent instances skip re-processing
|
|
813
|
+
them entirely.
|
|
744
814
|
|
|
745
815
|
**CSS file roles**:
|
|
746
816
|
|
|
@@ -751,7 +821,9 @@ scope once, like `targetCss`.
|
|
|
751
821
|
component's own shadow root, so each instance gets its own copy.
|
|
752
822
|
|
|
753
823
|
Every declared asset — CSS, HTML, JSON — is inlined into `static _assets` at build time by
|
|
754
|
-
the
|
|
824
|
+
the bundler, which replaces the `static assets` declaration with `static _assets` (the
|
|
825
|
+
`static assets` line is deleted from the bundled `.js`) and collapses each inlined
|
|
826
|
+
`.[shadow/target].css` / `.html` to a single line, so a bundled build performs no fetches.
|
|
755
827
|
|
|
756
828
|
In a bundled build the plain `.css` files are additionally concatenated into a single
|
|
757
829
|
`bundle.css` by the bundling script. That file is a convenience listing of the available
|
|
@@ -763,14 +835,14 @@ The runtime decides whether an asset still needs fetching with `!ctor._assets[ke
|
|
|
763
835
|
inlined entry must never be an empty string: that would trigger a re-fetch of a file that
|
|
764
836
|
does not exist in a bundled build.
|
|
765
837
|
|
|
766
|
-
@example static assets
|
|
838
|
+
@example static assets read in oneInit
|
|
767
839
|
|
|
768
840
|
```ts
|
|
769
841
|
class CartCheckout extends DC {
|
|
770
842
|
static assets = ['targetHtml', 'targetCss', 'configJson'];
|
|
771
843
|
|
|
772
|
-
|
|
773
|
-
const { configJson } =
|
|
844
|
+
oneInit() {
|
|
845
|
+
const { configJson } = this.assets;
|
|
774
846
|
console.log(configJson);
|
|
775
847
|
}
|
|
776
848
|
}
|
|
@@ -779,6 +851,26 @@ defineCE('cart-checkout', CartCheckout);
|
|
|
779
851
|
|
|
780
852
|
`configJson` arrives already parsed into an object.
|
|
781
853
|
|
|
854
|
+
@example plain .html template compiled with data
|
|
855
|
+
|
|
856
|
+
```ts
|
|
857
|
+
class UserCard extends DC {
|
|
858
|
+
static assets = ['html', 'targetCss'];
|
|
859
|
+
|
|
860
|
+
constructor(target: HTMLElement, data: { name: string }) {
|
|
861
|
+
super(target);
|
|
862
|
+
this.data = data;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
oneInit() {
|
|
866
|
+
this.target.innerHTML = parse(this.assets.html, this.data);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
defineCE('user-card', UserCard);
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
`user-card.html` holds the `{name}` template; `parse()` fills it from `data`.
|
|
873
|
+
|
|
782
874
|
### `static attributes?: object`
|
|
783
875
|
|
|
784
876
|
Sets HTML attributes on every instance automatically.
|
|
@@ -832,8 +924,7 @@ internal events that can be caught with handler methods:
|
|
|
832
924
|
| `onDisconnected()` | Element was removed from the DOM (`disconnectedCallback`) |
|
|
833
925
|
| `onAdopted()` | Element was moved to a new document (`adoptedCallback`) |
|
|
834
926
|
| `onAttributeChanged()` | An observed attribute changed (`attributeChangedCallback`) |
|
|
835
|
-
| `oneInit()` | Constructor finished;
|
|
836
|
-
| `oneAssets()` | Constructor finished; all assets loaded and available; ev contains assets object |
|
|
927
|
+
| `oneInit()` | Constructor finished and declared assets loaded; read them via `this.assets` |
|
|
837
928
|
|
|
838
929
|
@example Event handlers in action
|
|
839
930
|
|
|
@@ -948,22 +1039,6 @@ var DC = class DC extends McBase {
|
|
|
948
1039
|
*/
|
|
949
1040
|
static tag;
|
|
950
1041
|
/**
|
|
951
|
-
* Result container for assets (e.g., `['targetHtml', 'json']`).
|
|
952
|
-
* Asset names (keys) are camelCase and translated into file extensions: `'targetHtml'` → `.target.html`.
|
|
953
|
-
*/
|
|
954
|
-
static _assets = {};
|
|
955
|
-
/**
|
|
956
|
-
* Declares companion files for auto-loading by convention (e.g., `['targetHtml', 'json']`).
|
|
957
|
-
* Asset names are camelCase and translated into file extensions: `'targetHtml'` → `.target.html`.
|
|
958
|
-
*/
|
|
959
|
-
static assets = [];
|
|
960
|
-
/**
|
|
961
|
-
* In-flight asset request, cached per class so that instances constructed while
|
|
962
|
-
* the first fetch is still pending (e.g. in a loop) share a single request
|
|
963
|
-
* instead of each triggering their own. Resolves to the freshly loaded assets.
|
|
964
|
-
*/
|
|
965
|
-
static _assetsPromise;
|
|
966
|
-
/**
|
|
967
1042
|
* Sets HTML attributes on every instance automatically.
|
|
968
1043
|
* Example: `{ role: 'listitem', 'aria-label': 'nav' }`.
|
|
969
1044
|
*/
|
|
@@ -975,8 +1050,10 @@ var DC = class DC extends McBase {
|
|
|
975
1050
|
* 1. Calls {@link McBase} to establish the target reference and auto-attach listeners.
|
|
976
1051
|
* 2. If `static tag` is set and differs from the current element, replaces the target
|
|
977
1052
|
* with a new built-in element (or removes it if `tag === ''`).
|
|
978
|
-
* 3.
|
|
979
|
-
* 4.
|
|
1053
|
+
* 3. Applies any `static attributes` to the target element.
|
|
1054
|
+
* 4. Loads `static assets` (inlined in a bundled build, fetched in dev/autoload),
|
|
1055
|
+
* applies the auto-attached ones to the target, then fires the `Init` lifecycle
|
|
1056
|
+
* event — so `oneInit()` runs with the assets loaded and readable via {@link DC.assets}.
|
|
980
1057
|
*
|
|
981
1058
|
* @param target - The host DOM element this component operates on.
|
|
982
1059
|
*/
|
|
@@ -999,43 +1076,24 @@ var DC = class DC extends McBase {
|
|
|
999
1076
|
if (ctor.attributes) Object.keys(ctor.attributes).forEach((key) => {
|
|
1000
1077
|
this.target.setAttribute(key, attributes[key]);
|
|
1001
1078
|
});
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
return loadedAssets;
|
|
1015
|
-
});
|
|
1016
|
-
ctor._assetsPromise.then((loadedAssets) => {
|
|
1017
|
-
processAssets(this, loadedAssets);
|
|
1018
|
-
that.trigger("assets", ctor._assets);
|
|
1019
|
-
});
|
|
1020
|
-
} else if ([...Object.keys(ctor._assets)].length) queueMicrotask(() => that.trigger("assets", ctor._assets));
|
|
1079
|
+
if (Object.keys(ctor._assets).length) {
|
|
1080
|
+
processAssets(this, ctor._assets);
|
|
1081
|
+
for (const onceKey of ["css", "targetCss"]) delete ctor._assets[onceKey];
|
|
1082
|
+
ctor.assets = ctor.assets.filter((key) => key !== "css" && key !== "targetCss");
|
|
1083
|
+
}
|
|
1084
|
+
if (ctor._assetsPromise) ctor._assetsPromise.then((loadedAssets) => {
|
|
1085
|
+
processAssets(this, loadedAssets);
|
|
1086
|
+
for (const onceKey of ["css", "targetCss"]) delete ctor._assets[onceKey];
|
|
1087
|
+
ctor.assets = ctor.assets.filter((key) => key !== "css" && key !== "targetCss");
|
|
1088
|
+
init(this);
|
|
1089
|
+
});
|
|
1090
|
+
else init(this);
|
|
1021
1091
|
if (ctor.tag === "") {
|
|
1022
1092
|
this.target.remove();
|
|
1023
1093
|
return;
|
|
1024
1094
|
}
|
|
1025
1095
|
}
|
|
1026
1096
|
/**
|
|
1027
|
-
Returns the loaded assets for this component instance.
|
|
1028
|
-
|
|
1029
|
-
Assets are loaded asynchronously when `static assets` is defined on the class.
|
|
1030
|
-
This method returns the resolved asset map keyed by filename, or `undefined`
|
|
1031
|
-
if assets have not yet been loaded.
|
|
1032
|
-
|
|
1033
|
-
@returns A record mapping asset keys to their content strings, or undefined.
|
|
1034
|
-
*/
|
|
1035
|
-
getAssets() {
|
|
1036
|
-
return this.constructor._assets || {};
|
|
1037
|
-
}
|
|
1038
|
-
/**
|
|
1039
1097
|
Static helper to attach a microcomponent instance to a DOM element.
|
|
1040
1098
|
|
|
1041
1099
|
Wrapper around the `add()` utility function, providing a class-level API
|
package/dist/core/index.d.ts
CHANGED
|
@@ -54,11 +54,12 @@ This `_mc` property is the **only** interference with the native DOM structure,
|
|
|
54
54
|
|
|
55
55
|
## Lifecycle
|
|
56
56
|
|
|
57
|
-
- DC instances
|
|
57
|
+
- DC instances trigger the `"Init"` lifecycle event after construction **and after their declared assets are loaded** — synchronously in a bundled build (assets inlined), after the fetch resolves in a dev/autoload build. A component with a `oneInit()` method catches that event; when it runs, the constructor has finished and the assets are readable through the `this.assets` getter.
|
|
58
58
|
- Methods prefixed with `on` or `one` (e.g., `onClick`, `oneUpdate`) are auto-attached as event listeners on the target element, supporting both native HTML events and custom microcomponent events.
|
|
59
|
-
- When using the static `assets` property to
|
|
60
|
-
-
|
|
61
|
-
-
|
|
59
|
+
- When using the static `assets` property to load companion files:
|
|
60
|
+
- `.css`, `.target.css`, `.shadow.css`, `.target.html` and `.shadow.html` are automatically attached to their respective target locations, and native event handlers in template code (`<button click="...">`) are wired automatically
|
|
61
|
+
- a plain `.html` is NOT auto-attached — it is a template held in `this.assets` for components created programmatically with a `data` parameter, compiled with `parse()` inside `oneInit()`
|
|
62
|
+
- assets are loaded before `oneInit()` fires, so `oneInit()` always sees them
|
|
62
63
|
---
|
|
63
64
|
|
|
64
65
|
@module Core
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkEE;AAEF,6BAA6B;AAC7B,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACzC,sBAAsB;AACtB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACxD,mBAAmB;AACnB,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAClF,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@page api-external Overview
|
|
3
|
+
@order 1
|
|
4
|
+
|
|
5
|
+
Micro Components are not a framework that owns the page — they are functions you can call
|
|
6
|
+
from anywhere. The library exports a plain-function API (Tier 2) that works on any DOM
|
|
7
|
+
node, in vanilla JS, inside React/Vue/Svelte lifecycle code, or in Node. Inside a `DC`
|
|
8
|
+
or `MC` class you use the instance conventions (Tier 1); outside, you use these exports.
|
|
9
|
+
|
|
10
|
+
The contract that makes coexistence safe: a host element gains only a `_mc` property and
|
|
11
|
+
a `data-mc` attribute. A framework that renders markup, diffing, hydration, or its own
|
|
12
|
+
event delegation is untouched by that.
|
|
13
|
+
|
|
14
|
+
## Talking to micro components from vanilla JS
|
|
15
|
+
|
|
16
|
+
`on()` and `trigger()` are the two ends of the wire. A custom event name is prefixed
|
|
17
|
+
with `_mc` automatically, so the same name works on both sides:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { on, trigger } from '@twobirds/microcomponents';
|
|
21
|
+
|
|
22
|
+
// a micro component listens for 'CartUpdate' with onCartUpdate()
|
|
23
|
+
on(document.querySelector('cart-summary'), 'CartUpdate', (ev) => {
|
|
24
|
+
console.log(ev.detail.data.count); // payload lives under detail.data
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// vanilla code fires it — the host's _mc receives the event
|
|
28
|
+
trigger('cart-summary', 'CartUpdate', { count: 1 });
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Direction is the third argument: `'l'` local only (default), `'u'` up to ancestors,
|
|
32
|
+
`'d'` down to descendants, combinable (`'lu'`, `'ld'`, `'lud'`). Prefer naming the
|
|
33
|
+
target — a single `querySelectorAll` reaches it in one step. Reserve `'u'`/`'d'` for
|
|
34
|
+
receivers you cannot name in advance. A receiver stops a bubbling event with
|
|
35
|
+
`ev.detail.control.stop()`.
|
|
36
|
+
|
|
37
|
+
`one()` attaches a listener that fires once, `off()` detaches any handler.
|
|
38
|
+
|
|
39
|
+
## Attaching logic to nodes a framework renders
|
|
40
|
+
|
|
41
|
+
React, Vue, or Svelte own the markup; an MC attaches to a node they rendered:
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
function Cart() {
|
|
45
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
DC.add(ref.current!, 'summary', new CartSummary(ref.current!));
|
|
48
|
+
}, []);
|
|
49
|
+
return <div ref={ref}></div>;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The framework keeps diffing the node; the MC reads `this.target` and wires its own
|
|
54
|
+
handlers. Nothing in the framework's virtual DOM sees the `_mc` property.
|
|
55
|
+
|
|
56
|
+
## Creating elements from the registry
|
|
57
|
+
|
|
58
|
+
`getCE()` returns the constructor registered by `defineCE()`, so code outside the
|
|
59
|
+
system can instantiate a component:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { getCE } from '@twobirds/microcomponents';
|
|
63
|
+
|
|
64
|
+
const ShopHeader = getCE('shop-header');
|
|
65
|
+
if (ShopHeader) document.querySelector('header')?.append(new ShopHeader());
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`listCE()` lists every tag registered through `defineCE()`. `defineCE()` also accepts a
|
|
69
|
+
class that does **not** extend `McBase` — the class becomes the element itself, with no
|
|
70
|
+
`_mc` registry. That is the escape hatch for interoperating with existing custom
|
|
71
|
+
elements.
|
|
72
|
+
|
|
73
|
+
## State and forms from plain code
|
|
74
|
+
|
|
75
|
+
`observe()` wraps an object's properties in Observable wrappers without any MC context;
|
|
76
|
+
`formValues()` binds a named form control to one of them:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
import { observe, formValues } from '@twobirds/microcomponents';
|
|
80
|
+
|
|
81
|
+
const form = observe({ email: '', qty: 1 });
|
|
82
|
+
form.subscribe('email', (v) => console.log('email is now', v));
|
|
83
|
+
formValues(form, 'email', document.querySelector('input[name=email]'));
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## No-build pages
|
|
87
|
+
|
|
88
|
+
`autoload(true)` makes a page load its own components: an undefined tag in the markup
|
|
89
|
+
resolves to a script URL by the tag-to-path rule (`<shop-header>` → `shop/header.js`)
|
|
90
|
+
and is fetched on demand. A dev page needs only an import map and one call.
|
|
91
|
+
|
|
92
|
+
## Implementation priority
|
|
93
|
+
|
|
94
|
+
- **Tier 1 — framework conventions**: auto-attached handlers, lifecycle, statics, plugin
|
|
95
|
+
methods. Use these first inside a `DC`/`MC`.
|
|
96
|
+
- **Tier 2 — exported functions**: `on`, `trigger`, `observe`, `formValues`, `autoload`
|
|
97
|
+
— the public API outside a class.
|
|
98
|
+
- **Tier 3 — vanilla JS**: native `addEventListener`, `querySelector`, raw `CustomEvent`
|
|
99
|
+
— last resort.
|
|
100
|
+
*/
|
|
101
|
+
//# sourceMappingURL=api-external.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-external.d.ts","sourceRoot":"","sources":["../../src/docs/api-external.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmGE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@page cli CLI
|
|
3
|
+
@order 1
|
|
4
|
+
|
|
5
|
+
A small command-line tool (`mc`) scaffolds components and runs the dev / build / preview
|
|
6
|
+
chain, with no Vite dependency in the generated project. Nothing has to be installed to
|
|
7
|
+
run it once — `npx` fetches the package into its own cache and runs the bin from there.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npx @twobirds/microcomponents --help
|
|
11
|
+
npx @twobirds/microcomponents new my-card --target-html --target-css
|
|
12
|
+
npx -p @twobirds/microcomponents mc new my-card --target-html --target-css
|
|
13
|
+
npx -p @twobirds/microcomponents microcomponents-mcp
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Once installed from npm the same tool is available as `mc`. Every command below is one
|
|
17
|
+
line of usage with a worked example.
|
|
18
|
+
|
|
19
|
+
## mc new
|
|
20
|
+
|
|
21
|
+
Scaffolds one micro component: the `.ts` file plus the companion assets you flag, wired
|
|
22
|
+
into a `static assets` declaration. The path is derived from the tag (`shop-app` →
|
|
23
|
+
`src/shop/app.ts`).
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
mc new shop-app --target-html --target-css
|
|
27
|
+
# created src/shop/app.ts
|
|
28
|
+
# created src/shop/app.target.html
|
|
29
|
+
# created src/shop/app.target.css
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Flags: `--css`, `--html`, `--target-html`, `--shadow-html`, `--target-css`,
|
|
33
|
+
`--shadow-css`, `--js` (plain JavaScript), `--dir <path>` (scaffold root, default `src`),
|
|
34
|
+
`--force` (overwrite), `--dry-run` (print the plan, touch nothing).
|
|
35
|
+
|
|
36
|
+
## mc create
|
|
37
|
+
|
|
38
|
+
Scaffolds a complete dev environment for a namespace — package.json, the two shells, the
|
|
39
|
+
starter component, the bundle barrel, and the `opencode.jsonc` that registers the MCP
|
|
40
|
+
server.
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
mc create --namespace shop
|
|
44
|
+
# project "shop" created in shop/ — run: cd shop && pnpm install && pnpm dev
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Flags: `--namespace <ns>` (1 to 4 lowercase letters, required), `--dir <path>` (default:
|
|
48
|
+
the namespace), `--force`, `--dry-run`.
|
|
49
|
+
|
|
50
|
+
## mc dev
|
|
51
|
+
|
|
52
|
+
Runs `tsc -w` plus a `node:http` server that serves `build/`. The page loads components
|
|
53
|
+
on demand through `autoload()` — nothing is bundled, and a new component is picked up
|
|
54
|
+
without restarting.
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
mc dev # dev server on port 5173
|
|
58
|
+
mc dev --port 3000
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## mc bundle
|
|
62
|
+
|
|
63
|
+
Assembles the production site in `public/`: one `bundle.js` with every companion asset
|
|
64
|
+
inlined, the concatenated `bundle.css`, and the production shell. A single script tag
|
|
65
|
+
loads it; the autoloader is not needed.
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
mc bundle
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## mc preview
|
|
72
|
+
|
|
73
|
+
Serves the production site in `public/`.
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
mc preview # preview server on port 5174
|
|
77
|
+
mc preview --port 8080
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## mc clean
|
|
81
|
+
|
|
82
|
+
Removes build artifacts (`dist`, `public`, `build`, `coverage`). A thin wrapper around
|
|
83
|
+
the package.json script of the same name, so the script stays the single source of
|
|
84
|
+
truth; when the project defines no such script, the CLI runs its own implementation.
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
mc clean
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## mc check
|
|
91
|
+
|
|
92
|
+
Type-checks the project. A thin wrapper around the package.json `check` script; with no
|
|
93
|
+
such script, the CLI type-checks the current project with its own `tsconfig.json`.
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
mc check
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## mc --version
|
|
100
|
+
|
|
101
|
+
Reports the version of the installed library, not the version of the project it runs in.
|
|
102
|
+
|
|
103
|
+
```sh
|
|
104
|
+
mc --version # 0.10.2
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## mc --help
|
|
108
|
+
|
|
109
|
+
Prints the full usage text, including every flag and companion asset.
|
|
110
|
+
|
|
111
|
+
```sh
|
|
112
|
+
mc --help
|
|
113
|
+
```
|
|
114
|
+
*/
|
|
115
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/docs/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiHE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@page concepts Overview
|
|
3
|
+
@order 1
|
|
4
|
+
|
|
5
|
+
Micro Components (MCs) are function blocks you attach to DOM nodes. The only interference
|
|
6
|
+
with the DOM is a single `_mc` property on a host element, marked with a `data-mc`
|
|
7
|
+
attribute — so any other system can coexist with it. MCs are built on OOP, favour
|
|
8
|
+
composition over inheritance, and work like building blocks.
|
|
9
|
+
|
|
10
|
+
The library ships helpers for five areas:
|
|
11
|
+
|
|
12
|
+
- **Web Components** — native custom elements, composed from inner MCs.
|
|
13
|
+
- **State** — observable objects with callbacks, 1-way binding to DOM placeholders.
|
|
14
|
+
- **Form Handling** — 2-way binding between an observable form object and input fields.
|
|
15
|
+
- **Communication** — direct-selected or directional bubbling CustomEvents between MCs.
|
|
16
|
+
- **Autoloading** — build-free pages that load JS requirements into elements on demand.
|
|
17
|
+
|
|
18
|
+
Prominent features: no-build development, a shallow learning curve, strict web-standards
|
|
19
|
+
compliance, and very little abstraction. It runs Vanilla JS or TypeScript, and works
|
|
20
|
+
alongside React, Angular, Vue, or on its own.
|
|
21
|
+
|
|
22
|
+
The functional principle — attach an MC to a plain element:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
class MyMC extends DC {
|
|
26
|
+
helloWorld() {
|
|
27
|
+
console.log('Hello World');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const element = document.querySelector('div');
|
|
32
|
+
DC.add(element, 'myMC', new MyMC(element));
|
|
33
|
+
|
|
34
|
+
// Hello World
|
|
35
|
+
element._mc.myMC.helloWorld();
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `<div>` gains a `data-mc` attribute; the `_mc` property is the only DOM touch-point.
|
|
39
|
+
Every visible element is a micro component extending `DC`, pure DOM-free logic extends
|
|
40
|
+
`MC`, and additional DOM logic is attached at runtime with `DC.add()`.
|
|
41
|
+
*/
|
|
42
|
+
//# sourceMappingURL=concepts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"concepts.d.ts","sourceRoot":"","sources":["../../src/docs/concepts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwCE"}
|