@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.
Files changed (39) hide show
  1. package/dist/MC.min.js +1 -1
  2. package/dist/autoload.min.js +1 -1
  3. package/dist/cli/index.js +18 -22
  4. package/dist/cli/inliner.d.ts +8 -5
  5. package/dist/cli/inliner.d.ts.map +1 -1
  6. package/dist/core/MC.d.ts +98 -50
  7. package/dist/core/MC.d.ts.map +1 -1
  8. package/dist/core/elements.js +134 -76
  9. package/dist/core/index.d.ts +5 -4
  10. package/dist/core/index.d.ts.map +1 -1
  11. package/dist/docs/api-external.d.ts +101 -0
  12. package/dist/docs/api-external.d.ts.map +1 -0
  13. package/dist/docs/cli.d.ts +115 -0
  14. package/dist/docs/cli.d.ts.map +1 -0
  15. package/dist/docs/concepts.d.ts +42 -0
  16. package/dist/docs/concepts.d.ts.map +1 -0
  17. package/dist/docs/installation.d.ts +74 -0
  18. package/dist/docs/installation.d.ts.map +1 -0
  19. package/dist/docs/mcp.d.ts +45 -0
  20. package/dist/docs/mcp.d.ts.map +1 -0
  21. package/dist/elements.min.js +1 -1
  22. package/dist/formValues.min.js +1 -1
  23. package/dist/mcp/api.json +325 -29
  24. package/dist/mcp/concepts/event-system.md +1 -1
  25. package/dist/mcp/index.js +13 -6
  26. package/dist/microcomponents.js +145 -82
  27. package/dist/microcomponents.min.js +1 -1
  28. package/dist/observables.min.js +1 -1
  29. package/dist/state/formValues.d.ts +3 -3
  30. package/dist/state/formValues.js +139 -81
  31. package/dist/state/index.d.ts +3 -0
  32. package/dist/state/index.d.ts.map +1 -1
  33. package/dist/state/observables.d.ts +2 -2
  34. package/dist/state/observables.js +136 -78
  35. package/dist/types/index.d.ts +1 -0
  36. package/dist/types/index.d.ts.map +1 -1
  37. package/dist/utils/helpers.d.ts +12 -0
  38. package/dist/utils/helpers.d.ts.map +1 -1
  39. package/package.json +3 -2
@@ -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 asynchronously.
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. Only `DC` instances have an Init lifecycle — the `McBase`
517
- constructor calls this exclusively behind an `instanceof DC` check, so the
518
- signature encodes that invariant instead of re-checking it at runtime.
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. For `DC` subclasses it also bootstraps two automatic
587
- behaviours:
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
- Both mechanisms run only when the instance is a `DC` (checked with `instanceof DC`).
595
- Plain `MC` instances skip them entirely, keeping server-side usage lightweight.
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 and triggers auto-attachment
651
- of listeners and initialization lifecycle events.
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
- if (this instanceof DC && this.constructor !== DC) {
658
- autoAttachListeners(this);
659
- const tag = this.constructor.tag;
660
- if (tag === void 0 || tag.toUpperCase() === this.target.tagName) init(this);
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
- When assets finish loading, an `'assets'` event fires so that `oneAssets(ev)` can
737
- process them. Everything ending in `Json` arrives parsed; all other files arrive as text.
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 removed from both `static assets` and `static _assets`. Subsequent
743
- instances skip loading and re-processing them entirely.
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 load-assets plugin, so a bundled build performs no fetches at all.
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 with autoload
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
- oneAssets(ev) {
773
- const { configJson } = ev.detail.data;
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; all synchronous setup complete (microtask) |
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. If `static assets` has entries, initiates asynchronous loading, fires an `'assets'` event when complete handled by `oneAssets(ev)`.
979
- * 4. Applies any `static attributes` to the target element.
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
- const that = this;
1003
- const remainingAssets = ctor.assets.filter((key) => !ctor._assets[key]);
1004
- if (Object.keys(ctor._assets).length) processAssets(this, ctor._assets);
1005
- if (remainingAssets.length) {
1006
- if (!ctor._assetsPromise) ctor._assetsPromise = loadAssets(ctor._originalTag || tagName, remainingAssets).then((res) => {
1007
- const loadedAssets = {};
1008
- remainingAssets.forEach((key, i) => {
1009
- loadedAssets[key] = res[i];
1010
- });
1011
- ctor._assets = Object.assign({}, ctor._assets, loadedAssets);
1012
- for (const onceKey of ["css", "targetCss"]) if (loadedAssets[onceKey] !== void 0) delete ctor._assets[onceKey];
1013
- ctor.assets = ctor.assets.filter((key) => key !== "css" && key !== "targetCss");
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
@@ -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 automatically trigger an `"Init"` lifecycle event asynchronously - using queueMicrotask() - after construction. A component with a 'oneInit()' method will catch that lifecycle event, and when it runs it is guaranteed that the constructor() has run.
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 on-demand load shadow/target templates and css
60
- - those are automatically attached to their respective target locations
61
- - and all native event handlers in template code (&lt;button click="..."&gt;) are automatically attached also
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiEE;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"}
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"}