@twobirds/microcomponents 0.2.5 → 0.4.0
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/README.md +91 -34
- package/dist/MC.min.js +1 -1
- package/dist/autoload.min.js +1 -1
- package/dist/cli/create.d.ts +53 -0
- package/dist/cli/create.d.ts.map +1 -0
- package/dist/cli/create.js +419 -0
- package/dist/cli/dispatch.d.ts +43 -0
- package/dist/cli/dispatch.d.ts.map +1 -0
- package/dist/cli/dispatch.js +251 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +12 -0
- package/dist/cli/scaffold.d.ts +68 -0
- package/dist/cli/scaffold.d.ts.map +1 -0
- package/dist/cli/scaffold.js +109 -0
- package/dist/cli/writeScaffold.d.ts +37 -0
- package/dist/cli/writeScaffold.d.ts.map +1 -0
- package/dist/cli/writeScaffold.js +60 -0
- package/dist/core/MC.d.ts +50 -9
- package/dist/core/MC.d.ts.map +1 -1
- package/dist/core/MC.js +78 -33
- package/dist/core/elements.d.ts +11 -8
- package/dist/core/elements.d.ts.map +1 -1
- package/dist/core/elements.js +12 -7
- package/dist/core/mcGuards.d.ts +2 -2
- package/dist/elements.min.js +1 -1
- package/dist/formValues.min.js +1 -1
- package/dist/microcomponents.min.js +1 -1
- package/dist/observables.min.js +1 -1
- package/dist/state/formValues.d.ts +11 -5
- package/dist/state/formValues.d.ts.map +1 -1
- package/dist/state/formValues.js +18 -11
- package/dist/state/observables.d.ts +30 -13
- package/dist/state/observables.d.ts.map +1 -1
- package/dist/state/observables.js +64 -35
- package/dist/state/placeholders.d.ts.map +1 -1
- package/dist/state/placeholders.js +16 -11
- package/dist/types/mcTypes.d.ts +16 -7
- package/dist/types/mcTypes.d.ts.map +1 -1
- package/dist/utils/autoload.d.ts +6 -3
- package/dist/utils/autoload.d.ts.map +1 -1
- package/dist/utils/autoload.js +2 -2
- package/dist/utils/events.d.ts +21 -28
- package/dist/utils/events.d.ts.map +1 -1
- package/dist/utils/events.js +23 -29
- package/dist/utils/helpers.d.ts +19 -19
- package/dist/utils/helpers.d.ts.map +1 -1
- package/dist/utils/helpers.js +19 -19
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -2
- package/dist/utils/resolveComponentPath.d.ts +36 -0
- package/dist/utils/resolveComponentPath.d.ts.map +1 -0
- package/dist/utils/resolveComponentPath.js +39 -0
- package/package.json +20 -13
package/README.md
CHANGED
|
@@ -30,22 +30,84 @@ The distinguishing feature is its **minimalism**, **portability** and **granular
|
|
|
30
30
|
|
|
31
31
|
## Links
|
|
32
32
|
|
|
33
|
-
[demo shop (on-demand loading)](https://twobirds.gitlab.io/microcomponents/shop/index.html). No build, on-demand loading elements. Check code in debugger.
|
|
33
|
+
[demo shop (on-demand loading)](https://twobirds.gitlab.io/microcomponents/shop/index-dev.html). No build, on-demand loading elements. Check code in debugger.
|
|
34
34
|
|
|
35
|
-
[demo shop (bundled in one JS file)](https://twobirds.gitlab.io/microcomponents/shop/index
|
|
35
|
+
[demo shop (bundled in one JS file)](https://twobirds.gitlab.io/microcomponents/shop/index.html). 9 kB including the library.
|
|
36
36
|
|
|
37
37
|
Check the [typedoc API reference](https://twobirds.gitlab.io/microcomponents/typedoc/index.html) if you want to drill into the source code.
|
|
38
38
|
|
|
39
39
|
The progress of coding is occasionally being streamed on [twitch](https://twitch.tv/frankieth).
|
|
40
40
|
|
|
41
|
+
## MCP Server
|
|
42
|
+
|
|
43
|
+
An MCP (Model Context Protocol) server ships with this repo so AI assistants can look the library up instead of answering from memory: `microcomponents-mcp-server.ts` at the repo root.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm run mcp:run # start the server on stdio
|
|
47
|
+
pnpm run mcp:dev # restart it whenever src/ changes
|
|
48
|
+
pnpm run mcp:docs # regenerate docs/api.json and report undocumented exports
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Tools: `list-components`, `get-component-docs`, `search-components`, `get-core-concept`, `get-source-file`, `list-undocumented`.
|
|
52
|
+
|
|
53
|
+
There is no hand-written API list in the server. The whole index is extracted at startup from the JSDoc blocks of the public exports (the names re-exported by each `src/*/index.ts`), so it can never drift away from the code it documents — and `list-undocumented` tells you when a source file still lacks a doc block. Concept essays are hand-authored markdown, one file per concept under `docs/concepts/`, which is also where the tool's list of available concepts comes from.
|
|
54
|
+
|
|
55
|
+
## CLI
|
|
56
|
+
|
|
57
|
+
A small command-line tool scaffolds new components so the tag-to-file convention is never hand-written:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pnpm run cli -- new my-card --target-html --target-css
|
|
61
|
+
# created my/card.ts
|
|
62
|
+
# created my/card.target.html
|
|
63
|
+
# created my/card.target.css
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`--dry-run` prints the plan without touching disk, so you can check the derived paths first:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pnpm run cli -- new my-card --target-html --target-css --dry-run
|
|
70
|
+
# would create my/card.ts
|
|
71
|
+
# would create my/card.target.html
|
|
72
|
+
# would create my/card.target.css
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`mc create` scaffolds a complete dev environment for a namespace — a Vite dev server serving `src/` straight, a page shell that turns on `autoload(true)`, and a starter component with companion assets:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pnpm run cli -- create --namespace mc --dir mc-app
|
|
79
|
+
# created package.json
|
|
80
|
+
# created src/index.html
|
|
81
|
+
# created src/mc/app.ts
|
|
82
|
+
# created src/mc/app.target.html
|
|
83
|
+
# created src/mc/app.target.css
|
|
84
|
+
# ...
|
|
85
|
+
# project "mc" created in mc-app/ — run: cd mc-app && pnpm install && pnpm dev
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The namespace (1 to 4 lowercase letters) becomes the `src/<namespace>/` folder and the first segment of every component tag, so `mc` is the home of tags like `<mc-app>`. Because the page shell is the autoload base, `import.meta.url` + the tag-to-path rule resolves `<mc-app>` to `src/mc/app.js` — the compiled starter. `--dir` defaults to the namespace, `--dry-run` prints the plan without touching disk.
|
|
89
|
+
|
|
90
|
+
Once installed from npm the same command is available as `mc`:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
mc new my-card [--css] [--html] [--target-html] [--shadow-html] [--target-css] [--shadow-css] [--js] [--dir <path>] [--dry-run]
|
|
94
|
+
mc create --namespace <ns> [--dir <path>] [--dry-run]
|
|
95
|
+
mc clean
|
|
96
|
+
mc check
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
`clean` and `check` are thin wrappers around the package.json scripts of the same name, so the scripts remain the single source of truth for what they do — `mc check` type-checks every project context (lib, cli, test, demo, node) and exits with the script's exit code.
|
|
100
|
+
|
|
101
|
+
The scaffold derives the file path from the tag using the same rule the runtime autoload loader uses (`my-card` → `my/card.ts`), names companion assets after the runtime's asset descriptors (`targetHtml` → `card.target.html`), and wires them into a `static assets` declaration. `--js` emits a plain JavaScript file for the rapid-prototyping path.
|
|
102
|
+
|
|
41
103
|
## Examples
|
|
42
104
|
|
|
43
105
|
### **Functional Principle**
|
|
44
106
|
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
107
|
+
- _This section only shows the priciple: how Micro Components are stored in the DOM_
|
|
108
|
+
- _The section after this shows Web Components / Custom Elements_
|
|
109
|
+
- _All examples on this page are **Javascript**._
|
|
110
|
+
- _The package has full **Typescript** support_
|
|
49
111
|
|
|
50
112
|
html before:
|
|
51
113
|
|
|
@@ -70,10 +132,7 @@ const element = document.querySelector('div');
|
|
|
70
132
|
DC.add(element, 'myMC', new MyMC(element));
|
|
71
133
|
|
|
72
134
|
// Hello World
|
|
73
|
-
element
|
|
74
|
-
._mc
|
|
75
|
-
.myMC
|
|
76
|
-
.helloWorld();
|
|
135
|
+
element._mc.myMC.helloWorld();
|
|
77
136
|
```
|
|
78
137
|
|
|
79
138
|
html after:
|
|
@@ -87,7 +146,7 @@ html after:
|
|
|
87
146
|
|
|
88
147
|
### **Web Components / Custom Elements**
|
|
89
148
|
|
|
90
|
-
You can define a custom element using a micro component as its primary functional instance.
|
|
149
|
+
You can define a custom element using a micro component as its primary functional instance. You are still free to add many more micro components to the custom element at runtime.
|
|
91
150
|
|
|
92
151
|
code:
|
|
93
152
|
|
|
@@ -114,8 +173,8 @@ const body = document.body;
|
|
|
114
173
|
body.append(new ctor());
|
|
115
174
|
```
|
|
116
175
|
|
|
117
|
-
- For more examples regarding web components, go to the [typedocs](https://twobirds.gitlab.io/microcomponents/typedoc/)
|
|
118
|
-
- Check the sources of the [demo shop](https://twobirds.gitlab.io/microcomponents/shop/index.html) in the browser debugger
|
|
176
|
+
- For more examples regarding web components, go to the [typedocs](https://twobirds.gitlab.io/microcomponents/typedoc/)
|
|
177
|
+
- Check the sources of the [demo shop](https://twobirds.gitlab.io/microcomponents/shop/index-dev.html) in the browser debugger
|
|
119
178
|
|
|
120
179
|
### **State and 1-way-binding**
|
|
121
180
|
|
|
@@ -127,7 +186,6 @@ code:
|
|
|
127
186
|
observePlugin(DC);
|
|
128
187
|
// create a custom micro component class
|
|
129
188
|
class MyMC extends DC {
|
|
130
|
-
|
|
131
189
|
state = { text: 'Hello world!' };
|
|
132
190
|
|
|
133
191
|
constructor(target) {
|
|
@@ -135,11 +193,11 @@ class MyMC extends DC {
|
|
|
135
193
|
|
|
136
194
|
this.target.innerHTML = '{text}'; // simplicity, there are other methods
|
|
137
195
|
|
|
138
|
-
this
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
196
|
+
this.bind('state', target) // one way binding
|
|
197
|
+
.subscribe('state', (value) => {
|
|
198
|
+
// attach your own callbacks
|
|
199
|
+
console.log(value);
|
|
200
|
+
});
|
|
143
201
|
|
|
144
202
|
// changing the state will change the DOM
|
|
145
203
|
this.state.text = 'Hallo Welt'; // also triggers console.log()
|
|
@@ -149,38 +207,37 @@ class MyMC extends DC {
|
|
|
149
207
|
|
|
150
208
|
### **Forms and 2-way-binding**
|
|
151
209
|
|
|
152
|
-
Similar to observables above, you can 2-way-bind an observable object to form input fields.
|
|
210
|
+
Similar to observables above, you can 2-way-bind an observable object to form input fields.
|
|
153
211
|
|
|
154
212
|
Changes in the object properties trigger input field changes and vice versa.
|
|
155
213
|
|
|
156
214
|
code:
|
|
157
215
|
|
|
158
216
|
```javascript
|
|
159
|
-
|
|
217
|
+
formValuePlugin(DC);
|
|
160
218
|
// create a custom micro component class
|
|
161
|
-
targetHtml =
|
|
219
|
+
const targetHtml = `
|
|
162
220
|
<form>
|
|
163
221
|
<input name="textInput" value="Hallo Welt!"/>
|
|
164
222
|
</form>
|
|
165
223
|
`;
|
|
166
224
|
class MyMC extends DC {
|
|
225
|
+
formData = { textInput: '' };
|
|
226
|
+
|
|
167
227
|
constructor(target) {
|
|
168
228
|
super(target);
|
|
169
229
|
|
|
170
230
|
this.target.innerHTML = targetHtml;
|
|
171
231
|
|
|
172
|
-
this.formData
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
.subscribe( 'formData', (data) => {
|
|
177
|
-
console.log(data); // the form data object
|
|
178
|
-
});
|
|
232
|
+
this.formValues(target, 'formData') // link the form property to the DOM input fields
|
|
233
|
+
.subscribe('formData', (data) => {
|
|
234
|
+
console.log(data); // the form data object
|
|
235
|
+
});
|
|
179
236
|
|
|
180
237
|
// now simply changing the form property will change the DOM input fields
|
|
181
|
-
this.
|
|
238
|
+
this.formData.textInput = 'Hello World!';
|
|
182
239
|
|
|
183
|
-
// ... and editing the form input will change the '
|
|
240
|
+
// ... and editing the form input will change the 'formData' property
|
|
184
241
|
}
|
|
185
242
|
}
|
|
186
243
|
```
|
|
@@ -189,7 +246,7 @@ class MyMC extends DC {
|
|
|
189
246
|
|
|
190
247
|
#### Native Events
|
|
191
248
|
|
|
192
|
-
Events and there handlers are defined and triggered inside the system automatically.
|
|
249
|
+
Events and there handlers are defined and triggered inside the system automatically.
|
|
193
250
|
|
|
194
251
|
You can use events separately in vanilla JS to communicate with micro components.
|
|
195
252
|
|
|
@@ -232,7 +289,7 @@ class MyMC extends DC {
|
|
|
232
289
|
constructor(target) {
|
|
233
290
|
super(target);
|
|
234
291
|
|
|
235
|
-
payload = {
|
|
292
|
+
const payload = {
|
|
236
293
|
test: 42,
|
|
237
294
|
};
|
|
238
295
|
|
|
@@ -243,7 +300,7 @@ class MyMC extends DC {
|
|
|
243
300
|
|
|
244
301
|
// this event handler is attached automatically
|
|
245
302
|
onCustomEvent(ev) {
|
|
246
|
-
console.log('onCustomEvent called with', ev.data.test); // "42"
|
|
303
|
+
console.log('onCustomEvent called with', ev.detail.data.test); // "42"
|
|
247
304
|
}
|
|
248
305
|
}
|
|
249
306
|
```
|
package/dist/MC.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,t){let n=t.toLowerCase();return`on`+n in e?n:`_mc`+t[0].toUpperCase()+t.substring(1)}function t(n,r,i){if(n){if(typeof n==`string`){document.querySelectorAll(n).forEach(e=>t(e,r,i));return}n.removeEventListener(e(n,r),i)}}function n(t,r,i,a=!1){if(t){if(typeof t==`string`){document.querySelectorAll(t).forEach(e=>n(e,r,i));return}return t.addEventListener(e(t,r),i,{capture:!1,once:a}),i}}function r(e,t,i){if(e){if(typeof e==`string`){document.querySelectorAll(e).forEach(e=>r(e,t,i));return}return n(e,t,i,!0),i}}var i=class{stopped=!1;constructor(){}stop(){this.stopped=!0}};function a(t,n,r={},o=`l`,s){if(!t)return;if(typeof t==`string`){document.querySelectorAll(t).forEach(e=>a(e,n,r,o));return}let c=/^_mc/.test(n)?n:e(t,n),l=s||new i,u=new CustomEvent(c,{detail:{data:r,control:l},bubbles:!1});l.stopped||/l/.test(o)&&(t.dispatchEvent(u),l.stopped)||/[ud]/.test(o)&&queueMicrotask(()=>{if(o.indexOf(`u`)>-1&&a(t.parentElement,c,r,`lu`,l),o.indexOf(`d`)>-1)for(let e of t.children)a(e,c,r,`ld`)})}var o=new WeakMap;function s(e,t){let n=o.get(e)??new Set;if(n.has(t))return e.adoptedStyleSheets[0];n.add(t),o.set(e,n);let r=new CSSStyleSheet;return r.replaceSync(t),e.adoptedStyleSheets.push(r),r}function c(e,t){let n=e.target,r=n.shadowRoot;!r&&Object.keys(t).some(e=>e.indexOf(`shadow`)===0)&&(r=n.attachShadow({mode:`open`})),Object.keys(t).forEach(i=>{switch(i){case`css`:s(document,t[i]);break;case`targetCss`:s(document,t[i]);break;case`shadowCss`:s(r,t[i]);break;case`shadowHtml`:r.innerHTML=t[i],u(r,e);break;case`targetHtml`:n.innerHTML=t[i],u(n,e);break}})}function l(e,t){let n=t=>{let n=t.match(/^([a-z]+)([A-Z][a-z]*)$/);return n?`./${e.replace(/-/g,`/`)}.${n[1]}.${n[2].toLowerCase()}`:`./${e.replace(/-/g,`/`)}.${t.toLowerCase()}`};return Promise.all(t.map(async e=>{let t=n(e);try{let n=await fetch(t);if(!n.ok)return`file not found: ${t}`;if(t.endsWith(`json`)){let r=await n.text();try{return JSON.parse(r)}catch{return console.error(`could not JSON.parse() asset '${e}' from ${t}:\n`,r),null}}return n.text()}catch{return`file not found: ${t}`}}))}function u(e,t){let r=[...e.querySelectorAll(`*`)];for(let e of r){if(!(e instanceof HTMLElement))continue;let r=[...e.attributes];for(let i of r){let r=i.name.toLowerCase();if(!(`on`+r in e))continue;let o=i.value.trim().split(`|`);if(o.length<2)continue;let[s,c,l]=o;e.removeAttribute(i.name);let u;if(l)try{u=JSON.parse(l)}catch{u=l}s===`this`||s===``?n(e,r,()=>t.trigger(c,u)):n(e,r,()=>a(s,c,u))}}}function d(e,t){return typeof HTMLElement<`u`&&e instanceof HTMLElement&&`_mc`in e&&(t===void 0||t in e._mc)}function f(e,t,n={}){let r=e;`_mc`in e||(r._mc=new b(e));let i=r._mc;return t.length&&!i[t]&&(i[t]=n,e instanceof HTMLElement&&!e.getAttribute(`data-mc`)&&e.setAttribute(`data-mc`,``)),r}function p(e,t){if(!t)return;let n=e._mc;n&&(n[t]&&delete n[t],!Object.keys(n).length&&e instanceof HTMLElement&&e.hasAttribute(`data-mc`)&&e.removeAttribute(`data-mc`))}function m(e){queueMicrotask(()=>{e.trigger(`Init`,null)})}function h(e){let t=e.target,r=Object.getPrototypeOf(e),i=e,a=Object.getOwnPropertyNames(r).filter(e=>/^(on[A-Z]|one[A-Z])/.test(e)&&typeof r[e]==`function`);for(let e of a){let r=/^one/.test(e);n(t,e.replace(/^one?/,``),t=>i[e](t),r)}}function g(e){return Array.from(e.querySelectorAll(`[data-mc]:not(:scope [data-mc] [data-mc])`)).filter(e=>e instanceof HTMLElement&&`_mc`in e).map(e=>e._mc)}function _(e,t){let n=e.parentElement?.closest(`[data-mc]`);for(;n instanceof HTMLElement;){if(`_mc`in n){let e=n._mc;if(t===void 0||t in e)return e}n=n.parentElement?.closest(`[data-mc]`)}return null}var v=class{_target;constructor(e){if(this._target=new WeakRef(e||{}),this instanceof b&&this.constructor!==b){h(this);let e=this.constructor.tag;(e===void 0||e.toUpperCase()===this.target.tagName)&&m(this)}}get target(){return this._target.deref()}},y=class extends v{constructor(e){super(e)}},b=class e extends v{static tag;static _assets={};static assets=[];static attributes={};constructor(t){super(t);let n=this.constructor;if(n===e)return;let r=this.target.tagName.toLowerCase();if(n.tag!==void 0&&r!==n.tag&&n.tag!==``){let t=document.createElement(n.tag);t.classList.add(r),n._originalTag=r,e.add(t,n.name,new n(t)),delete n._originalTag,r.includes(`-`)&&!this.target.isConnected?this.on(`connected`,()=>this.target.replaceWith(t)):this.target.replaceWith(t);return}let i=n.attributes;n.attributes&&Object.keys(n.attributes).forEach(e=>{this.target.setAttribute(e,i[e])});let a=n.assets.filter(e=>!n._assets[e])
|
|
1
|
+
function e(e,t){let n=t.toLowerCase();return`on`+n in e?n:`_mc`+t[0].toUpperCase()+t.substring(1)}function t(n,r,i){if(n){if(typeof n==`string`){document.querySelectorAll(n).forEach(e=>t(e,r,i));return}n.removeEventListener(e(n,r),i)}}function n(t,r,i,a=!1){if(t){if(typeof t==`string`){document.querySelectorAll(t).forEach(e=>n(e,r,i));return}return t.addEventListener(e(t,r),i,{capture:!1,once:a}),i}}function r(e,t,i){if(e){if(typeof e==`string`){document.querySelectorAll(e).forEach(e=>r(e,t,i));return}return n(e,t,i,!0),i}}var i=class{stopped=!1;constructor(){}stop(){this.stopped=!0}};function a(t,n,r={},o=`l`,s){if(!t)return;if(typeof t==`string`){document.querySelectorAll(t).forEach(e=>a(e,n,r,o));return}let c=/^_mc/.test(n)?n:e(t,n),l=s||new i,u=new CustomEvent(c,{detail:{data:r,control:l},bubbles:!1});l.stopped||/l/.test(o)&&(t.dispatchEvent(u),l.stopped)||/[ud]/.test(o)&&queueMicrotask(()=>{if(o.indexOf(`u`)>-1&&a(t.parentElement,c,r,`lu`,l),o.indexOf(`d`)>-1)for(let e of t.children)a(e,c,r,`ld`)})}var o=new WeakMap;function s(e,t){let n=o.get(e)??new Set;if(n.has(t))return e.adoptedStyleSheets[0];n.add(t),o.set(e,n);let r=new CSSStyleSheet;return r.replaceSync(t),e.adoptedStyleSheets.push(r),r}function c(e,t){let n=e.target,r=n.shadowRoot;!r&&Object.keys(t).some(e=>e.indexOf(`shadow`)===0)&&(r=n.attachShadow({mode:`open`})),Object.keys(t).forEach(i=>{switch(i){case`css`:s(document,t[i]);break;case`targetCss`:s(document,t[i]);break;case`shadowCss`:s(r,t[i]);break;case`shadowHtml`:r.innerHTML=t[i],u(r,e);break;case`targetHtml`:n.innerHTML=t[i],u(n,e);break}})}function l(e,t){let n=t=>{let n=t.match(/^([a-z]+)([A-Z][a-z]*)$/);return n?`./${e.replace(/-/g,`/`)}.${n[1]}.${n[2].toLowerCase()}`:`./${e.replace(/-/g,`/`)}.${t.toLowerCase()}`};return Promise.all(t.map(async e=>{let t=n(e);try{let n=await fetch(t);if(!n.ok)return`file not found: ${t}`;if(t.endsWith(`json`)){let r=await n.text();try{return JSON.parse(r)}catch{return console.error(`could not JSON.parse() asset '${e}' from ${t}:\n`,r),null}}return n.text()}catch{return`file not found: ${t}`}}))}function u(e,t){let r=[...e.querySelectorAll(`*`)];for(let e of r){if(!(e instanceof HTMLElement))continue;let r=[...e.attributes];for(let i of r){let r=i.name.toLowerCase();if(!(`on`+r in e))continue;let o=i.value.trim().split(`|`);if(o.length<2)continue;let[s,c,l]=o;e.removeAttribute(i.name);let u;if(l)try{u=JSON.parse(l)}catch{u=l}s===`this`||s===``?n(e,r,()=>t.trigger(c,u)):n(e,r,()=>a(s,c,u))}}}function d(e,t){return typeof HTMLElement<`u`&&e instanceof HTMLElement&&`_mc`in e&&(t===void 0||t in e._mc)}function f(e,t,n={}){let r=e;`_mc`in e||(r._mc=new b(e));let i=r._mc;return t.length&&!i[t]&&(i[t]=n,e instanceof HTMLElement&&!e.getAttribute(`data-mc`)&&e.setAttribute(`data-mc`,``)),r}function p(e,t){if(!t)return;let n=e._mc;n&&(n[t]&&delete n[t],!Object.keys(n).length&&e instanceof HTMLElement&&e.hasAttribute(`data-mc`)&&e.removeAttribute(`data-mc`))}function m(e){queueMicrotask(()=>{e.trigger(`Init`,null)})}function h(e){let t=e.target,r=Object.getPrototypeOf(e),i=e,a=Object.getOwnPropertyNames(r).filter(e=>/^(on[A-Z]|one[A-Z])/.test(e)&&typeof r[e]==`function`);for(let e of a){let r=/^one/.test(e);n(t,e.replace(/^one?/,``),t=>i[e](t),r)}}function g(e){return Array.from(e.querySelectorAll(`[data-mc]:not(:scope [data-mc] [data-mc])`)).filter(e=>e instanceof HTMLElement&&`_mc`in e).map(e=>e._mc)}function _(e,t){let n=e.parentElement?.closest(`[data-mc]`);for(;n instanceof HTMLElement;){if(`_mc`in n){let e=n._mc;if(t===void 0||t in e)return e}n=n.parentElement?.closest(`[data-mc]`)}return null}var v=class{_target;constructor(e){if(this._target=new WeakRef(e||{}),this instanceof b&&this.constructor!==b){h(this);let e=this.constructor.tag;(e===void 0||e.toUpperCase()===this.target.tagName)&&m(this)}}get target(){return this._target.deref()}},y=class extends v{constructor(e){super(e)}},b=class e extends v{static tag;static _assets={};static assets=[];static _assetsPromise;static attributes={};constructor(t){super(t);let n=this.constructor;if(n===e)return;let r=this.target.tagName.toLowerCase();if(n.tag!==void 0&&r!==n.tag&&n.tag!==``){let t=document.createElement(n.tag);t.classList.add(r),n._originalTag=r,e.add(t,n.name,new n(t)),delete n._originalTag,r.includes(`-`)&&!this.target.isConnected?this.on(`connected`,()=>this.target.replaceWith(t)):this.target.replaceWith(t);return}let i=n.attributes;n.attributes&&Object.keys(n.attributes).forEach(e=>{this.target.setAttribute(e,i[e])});let a=this,o=n.assets.filter(e=>!n._assets[e]);if(Object.keys(n._assets).length&&c(this,n._assets),o.length?(n._assetsPromise||=l(n._originalTag||r,o).then(e=>{let t={};o.forEach((n,r)=>{t[n]=e[r]}),n._assets=Object.assign({},n._assets,t);for(let e of[`css`,`targetCss`])t[e]!==void 0&&delete n._assets[e];return n.assets=n.assets.filter(e=>e!==`css`&&e!==`targetCss`),t}),n._assetsPromise.then(e=>{c(this,e),a.trigger(`assets`,n._assets)})):[...Object.keys(n._assets)].length&&queueMicrotask(()=>a.trigger(`assets`,n._assets)),n.tag===``){this.target.remove();return}}getAssets(){return this.constructor._assets||{}}static add(e,t,n={}){return f(e,t,n)}static remove(e,t){p(e,t)}static get(e,t,n){if(!d(e))return;let r=e._mc[t];return r instanceof n?r:void 0}off(e,n){t(this.target,e,n)}on(e,t){return n(this.target,e,t)}one(e,t){return r(this.target,e,t)}trigger(e,t={},n=`l`,r){a(this.target,e,t,n,r)}ancestors(e){let t=[],n=_(this.target,e);for(;n;)t.push(n),n=_(n.target,e);return t}closest(e){return _(this.target,e)}children(e){let t=g(this.target);return e===void 0?t:t.filter(t=>e in t)}descendants(e){return Array.from(this.target.querySelectorAll(`[data-mc]`)).filter(e=>e instanceof HTMLElement&&`_mc`in e).map(e=>e._mc).filter(t=>e===void 0||e in t)}};export{b as DC,y as MC,v as McBase,d as isMcHost};
|
package/dist/autoload.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(e,t){let n=t.toLowerCase();return`on`+n in e?n:`_mc`+t[0].toUpperCase()+t.substring(1)}function t(n,r,i){if(n){if(typeof n==`string`){document.querySelectorAll(n).forEach(e=>t(e,r,i));return}n.removeEventListener(e(n,r),i)}}function n(t,r,i,a=!1){if(t){if(typeof t==`string`){document.querySelectorAll(t).forEach(e=>n(e,r,i));return}return t.addEventListener(e(t,r),i,{capture:!1,once:a}),i}}function r(e,t,i){if(e){if(typeof e==`string`){document.querySelectorAll(e).forEach(e=>r(e,t,i));return}return n(e,t,i,!0),i}}var i=class{stopped=!1;constructor(){}stop(){this.stopped=!0}};function a(t,n,r={},o=`l`,s){if(!t)return;if(typeof t==`string`){document.querySelectorAll(t).forEach(e=>a(e,n,r,o));return}let c=/^_mc/.test(n)?n:e(t,n),l=s||new i,u=new CustomEvent(c,{detail:{data:r,control:l},bubbles:!1});l.stopped||/l/.test(o)&&(t.dispatchEvent(u),l.stopped)||/[ud]/.test(o)&&queueMicrotask(()=>{if(o.indexOf(`u`)>-1&&a(t.parentElement,c,r,`lu`,l),o.indexOf(`d`)>-1)for(let e of t.children)a(e,c,r,`ld`)})}var o=new WeakMap;function s(e,t){let n=o.get(e)??new Set;if(n.has(t))return e.adoptedStyleSheets[0];n.add(t),o.set(e,n);let r=new CSSStyleSheet;return r.replaceSync(t),e.adoptedStyleSheets.push(r),r}function c(e,t){let n=e.target,r=n.shadowRoot;!r&&Object.keys(t).some(e=>e.indexOf(`shadow`)===0)&&(r=n.attachShadow({mode:`open`})),Object.keys(t).forEach(i=>{switch(i){case`css`:s(document,t[i]);break;case`targetCss`:s(document,t[i]);break;case`shadowCss`:s(r,t[i]);break;case`shadowHtml`:r.innerHTML=t[i],u(r,e);break;case`targetHtml`:n.innerHTML=t[i],u(n,e);break}})}function l(e,t){let n=t=>{let n=t.match(/^([a-z]+)([A-Z][a-z]*)$/);return n?`./${e.replace(/-/g,`/`)}.${n[1]}.${n[2].toLowerCase()}`:`./${e.replace(/-/g,`/`)}.${t.toLowerCase()}`};return Promise.all(t.map(async e=>{let t=n(e);try{let n=await fetch(t);if(!n.ok)return`file not found: ${t}`;if(t.endsWith(`json`)){let r=await n.text();try{return JSON.parse(r)}catch{return console.error(`could not JSON.parse() asset '${e}' from ${t}:\n`,r),null}}return n.text()}catch{return`file not found: ${t}`}}))}function u(e,t){let r=[...e.querySelectorAll(`*`)];for(let e of r){if(!(e instanceof HTMLElement))continue;let r=[...e.attributes];for(let i of r){let r=i.name.toLowerCase();if(!(`on`+r in e))continue;let o=i.value.trim().split(`|`);if(o.length<2)continue;let[s,c,l]=o;e.removeAttribute(i.name);let u;if(l)try{u=JSON.parse(l)}catch{u=l}s===`this`||s===``?n(e,r,()=>t.trigger(c,u)):n(e,r,()=>a(s,c,u))}}}function d(e,t){return typeof HTMLElement<`u`&&e instanceof HTMLElement&&`_mc`in e&&(t===void 0||t in e._mc)}function f(e,t,n={}){let r=e;`_mc`in e||(r._mc=new y(e));let i=r._mc;return t.length&&!i[t]&&(i[t]=n,e instanceof HTMLElement&&!e.getAttribute(`data-mc`)&&e.setAttribute(`data-mc`,``)),r}function p(e,t){if(!t)return;let n=e._mc;n&&(n[t]&&delete n[t],!Object.keys(n).length&&e instanceof HTMLElement&&e.hasAttribute(`data-mc`)&&e.removeAttribute(`data-mc`))}function m(e){queueMicrotask(()=>{e.trigger(`Init`,null)})}function h(e){let t=e.target,r=Object.getPrototypeOf(e),i=e,a=Object.getOwnPropertyNames(r).filter(e=>/^(on[A-Z]|one[A-Z])/.test(e)&&typeof r[e]==`function`);for(let e of a){let r=/^one/.test(e);n(t,e.replace(/^one?/,``),t=>i[e](t),r)}}function g(e){return Array.from(e.querySelectorAll(`[data-mc]:not(:scope [data-mc] [data-mc])`)).filter(e=>e instanceof HTMLElement&&`_mc`in e).map(e=>e._mc)}function _(e,t){let n=e.parentElement?.closest(`[data-mc]`);for(;n instanceof HTMLElement;){if(`_mc`in n){let e=n._mc;if(t===void 0||t in e)return e}n=n.parentElement?.closest(`[data-mc]`)}return null}var v=class{_target;constructor(e){if(this._target=new WeakRef(e||{}),this instanceof y&&this.constructor!==y){h(this);let e=this.constructor.tag;(e===void 0||e.toUpperCase()===this.target.tagName)&&m(this)}}get target(){return this._target.deref()}},y=class e extends v{static tag;static _assets={};static assets=[];static attributes={};constructor(t){super(t);let n=this.constructor;if(n===e)return;let r=this.target.tagName.toLowerCase();if(n.tag!==void 0&&r!==n.tag&&n.tag!==``){let t=document.createElement(n.tag);t.classList.add(r),n._originalTag=r,e.add(t,n.name,new n(t)),delete n._originalTag,r.includes(`-`)&&!this.target.isConnected?this.on(`connected`,()=>this.target.replaceWith(t)):this.target.replaceWith(t);return}let i=n.attributes;n.attributes&&Object.keys(n.attributes).forEach(e=>{this.target.setAttribute(e,i[e])});let a=n.assets.filter(e=>!n._assets[e])
|
|
1
|
+
function e(e,t){let n=t.toLowerCase();return`on`+n in e?n:`_mc`+t[0].toUpperCase()+t.substring(1)}function t(n,r,i){if(n){if(typeof n==`string`){document.querySelectorAll(n).forEach(e=>t(e,r,i));return}n.removeEventListener(e(n,r),i)}}function n(t,r,i,a=!1){if(t){if(typeof t==`string`){document.querySelectorAll(t).forEach(e=>n(e,r,i));return}return t.addEventListener(e(t,r),i,{capture:!1,once:a}),i}}function r(e,t,i){if(e){if(typeof e==`string`){document.querySelectorAll(e).forEach(e=>r(e,t,i));return}return n(e,t,i,!0),i}}var i=class{stopped=!1;constructor(){}stop(){this.stopped=!0}};function a(t,n,r={},o=`l`,s){if(!t)return;if(typeof t==`string`){document.querySelectorAll(t).forEach(e=>a(e,n,r,o));return}let c=/^_mc/.test(n)?n:e(t,n),l=s||new i,u=new CustomEvent(c,{detail:{data:r,control:l},bubbles:!1});l.stopped||/l/.test(o)&&(t.dispatchEvent(u),l.stopped)||/[ud]/.test(o)&&queueMicrotask(()=>{if(o.indexOf(`u`)>-1&&a(t.parentElement,c,r,`lu`,l),o.indexOf(`d`)>-1)for(let e of t.children)a(e,c,r,`ld`)})}var o=new WeakMap;function s(e,t){let n=o.get(e)??new Set;if(n.has(t))return e.adoptedStyleSheets[0];n.add(t),o.set(e,n);let r=new CSSStyleSheet;return r.replaceSync(t),e.adoptedStyleSheets.push(r),r}function c(e,t){let n=e.target,r=n.shadowRoot;!r&&Object.keys(t).some(e=>e.indexOf(`shadow`)===0)&&(r=n.attachShadow({mode:`open`})),Object.keys(t).forEach(i=>{switch(i){case`css`:s(document,t[i]);break;case`targetCss`:s(document,t[i]);break;case`shadowCss`:s(r,t[i]);break;case`shadowHtml`:r.innerHTML=t[i],u(r,e);break;case`targetHtml`:n.innerHTML=t[i],u(n,e);break}})}function l(e,t){let n=t=>{let n=t.match(/^([a-z]+)([A-Z][a-z]*)$/);return n?`./${e.replace(/-/g,`/`)}.${n[1]}.${n[2].toLowerCase()}`:`./${e.replace(/-/g,`/`)}.${t.toLowerCase()}`};return Promise.all(t.map(async e=>{let t=n(e);try{let n=await fetch(t);if(!n.ok)return`file not found: ${t}`;if(t.endsWith(`json`)){let r=await n.text();try{return JSON.parse(r)}catch{return console.error(`could not JSON.parse() asset '${e}' from ${t}:\n`,r),null}}return n.text()}catch{return`file not found: ${t}`}}))}function u(e,t){let r=[...e.querySelectorAll(`*`)];for(let e of r){if(!(e instanceof HTMLElement))continue;let r=[...e.attributes];for(let i of r){let r=i.name.toLowerCase();if(!(`on`+r in e))continue;let o=i.value.trim().split(`|`);if(o.length<2)continue;let[s,c,l]=o;e.removeAttribute(i.name);let u;if(l)try{u=JSON.parse(l)}catch{u=l}s===`this`||s===``?n(e,r,()=>t.trigger(c,u)):n(e,r,()=>a(s,c,u))}}}function d(e,t){return typeof HTMLElement<`u`&&e instanceof HTMLElement&&`_mc`in e&&(t===void 0||t in e._mc)}function f(e,t,n={}){let r=e;`_mc`in e||(r._mc=new y(e));let i=r._mc;return t.length&&!i[t]&&(i[t]=n,e instanceof HTMLElement&&!e.getAttribute(`data-mc`)&&e.setAttribute(`data-mc`,``)),r}function p(e,t){if(!t)return;let n=e._mc;n&&(n[t]&&delete n[t],!Object.keys(n).length&&e instanceof HTMLElement&&e.hasAttribute(`data-mc`)&&e.removeAttribute(`data-mc`))}function m(e){queueMicrotask(()=>{e.trigger(`Init`,null)})}function h(e){let t=e.target,r=Object.getPrototypeOf(e),i=e,a=Object.getOwnPropertyNames(r).filter(e=>/^(on[A-Z]|one[A-Z])/.test(e)&&typeof r[e]==`function`);for(let e of a){let r=/^one/.test(e);n(t,e.replace(/^one?/,``),t=>i[e](t),r)}}function g(e){return Array.from(e.querySelectorAll(`[data-mc]:not(:scope [data-mc] [data-mc])`)).filter(e=>e instanceof HTMLElement&&`_mc`in e).map(e=>e._mc)}function _(e,t){let n=e.parentElement?.closest(`[data-mc]`);for(;n instanceof HTMLElement;){if(`_mc`in n){let e=n._mc;if(t===void 0||t in e)return e}n=n.parentElement?.closest(`[data-mc]`)}return null}var v=class{_target;constructor(e){if(this._target=new WeakRef(e||{}),this instanceof y&&this.constructor!==y){h(this);let e=this.constructor.tag;(e===void 0||e.toUpperCase()===this.target.tagName)&&m(this)}}get target(){return this._target.deref()}},y=class e extends v{static tag;static _assets={};static assets=[];static _assetsPromise;static attributes={};constructor(t){super(t);let n=this.constructor;if(n===e)return;let r=this.target.tagName.toLowerCase();if(n.tag!==void 0&&r!==n.tag&&n.tag!==``){let t=document.createElement(n.tag);t.classList.add(r),n._originalTag=r,e.add(t,n.name,new n(t)),delete n._originalTag,r.includes(`-`)&&!this.target.isConnected?this.on(`connected`,()=>this.target.replaceWith(t)):this.target.replaceWith(t);return}let i=n.attributes;n.attributes&&Object.keys(n.attributes).forEach(e=>{this.target.setAttribute(e,i[e])});let a=this,o=n.assets.filter(e=>!n._assets[e]);if(Object.keys(n._assets).length&&c(this,n._assets),o.length?(n._assetsPromise||=l(n._originalTag||r,o).then(e=>{let t={};o.forEach((n,r)=>{t[n]=e[r]}),n._assets=Object.assign({},n._assets,t);for(let e of[`css`,`targetCss`])t[e]!==void 0&&delete n._assets[e];return n.assets=n.assets.filter(e=>e!==`css`&&e!==`targetCss`),t}),n._assetsPromise.then(e=>{c(this,e),a.trigger(`assets`,n._assets)})):[...Object.keys(n._assets)].length&&queueMicrotask(()=>a.trigger(`assets`,n._assets)),n.tag===``){this.target.remove();return}}getAssets(){return this.constructor._assets||{}}static add(e,t,n={}){return f(e,t,n)}static remove(e,t){p(e,t)}static get(e,t,n){if(!d(e))return;let r=e._mc[t];return r instanceof n?r:void 0}off(e,n){t(this.target,e,n)}on(e,t){return n(this.target,e,t)}one(e,t){return r(this.target,e,t)}trigger(e,t={},n=`l`,r){a(this.target,e,t,n,r)}ancestors(e){let t=[],n=_(this.target,e);for(;n;)t.push(n),n=_(n.target,e);return t}closest(e){return _(this.target,e)}children(e){let t=g(this.target);return e===void 0?t:t.filter(t=>e in t)}descendants(e){return Array.from(this.target.querySelectorAll(`[data-mc]`)).filter(e=>e instanceof HTMLElement&&`_mc`in e).map(e=>e._mc).filter(t=>e===void 0||e in t)}};function b(e){return e.split(`-`).join(`/`)}function x(e){return`./`+b(e)+`.js`}var S=new Set;function C(e){return()=>{let t=Array.from(document.querySelectorAll(`[data-mc*="${e}"]`)).filter(e=>e instanceof HTMLElement);if(t.length===0)return;let n=customElements.get(e);for(let r of t){try{y.add(r,n.name,new n(r))}catch{if(`create`in n&&typeof n.create==`function`){let e=n.create(r);if(!d(e))throw`create() of Class ${n.name} did not return a McHost.`;e.setAttribute(`data-mc`,r.getAttribute(`data-mc`)??``),r.replaceWith(e),r=e}else throw`Class ${n.name} doesn't have a callable constructor AND class doesn't have a static .create() method.`}let t=r.getAttribute(`data-mc`).split(` `).filter(t=>t!==e&&t!==``).join(` `).trim();r.setAttribute(`data-mc`,t)}}}function w(e){if(S.has(e))return;S.add(e);let t=x(e),n=document.createElement(`script`);n.setAttribute(`src`,t),n.setAttribute(`blocking`,`render`),n.async=!0,n.setAttribute(`type`,`module`),n.setAttribute(`data-name`,e),n.setAttribute(`loading`,``),customElements.whenDefined(e).then(C(e)),n.addEventListener(`load`,t=>{S.delete(e),document.head.querySelector(`script[data-name="${e}"]`)?.remove()}),n.addEventListener(`error`,e=>{console.error(`could not load DC code from`,t)}),document.head.append(n)}function T(){[...document.querySelectorAll(`:not(:defined)`)].filter(e=>!!e&&!customElements.get(e.tagName.toLowerCase())&&!S.has(e.tagName.toLowerCase())).forEach(e=>{w(e.tagName.toLowerCase())}),[...document.querySelectorAll(`[data-mc]:not([data-mc=""]`)].filter(e=>!!e).forEach(e=>{(e.getAttribute(`data-mc`)?.split(` `).filter(e=>e!==``))?.forEach(e=>{let t=customElements.get(e);!S.has(e)&&!t?w(e):t&&C(e)()})})}var E=null;function D(e=!0){return e?E?!0:(E=new MutationObserver(T),setTimeout(()=>{E.observe(document.body,{childList:!0,subtree:!0}),T()},5),window.autoload??=D,!0):(E&&=(E.disconnect(),null),!1)}D.state=S;export{D as autoload};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Project scaffolding for `mc create --namespace xxx`.
|
|
3
|
+
|
|
4
|
+
Pure, filesystem-free logic: given a namespace it returns the files of a complete,
|
|
5
|
+
working Micro Components dev environment and their contents. The starter component's
|
|
6
|
+
path is not re-derived here — it comes from {@link tagPath}, the same primitive the
|
|
7
|
+
runtime autoload loader uses, so the scaffold and the runtime can never disagree about
|
|
8
|
+
where a component lives.
|
|
9
|
+
|
|
10
|
+
The namespace is the first segment of every component tag, so `xxx` makes `src/xxx/`
|
|
11
|
+
the home of tags like `<xxx-app>` (tagPath `xxx-app` → `xxx/app`). The generated
|
|
12
|
+
environment mirrors the repo's own demos: a Vite dev server serving `src/` straight,
|
|
13
|
+
a page shell at that root that turns on `autoload(true)`, and a starter component with
|
|
14
|
+
companion `targetHtml` / `targetCss` assets. Because the page shell is the autoload
|
|
15
|
+
base, `import.meta.url` + `tagPath('xxx-app')` resolves to `src/xxx/app.js` — the
|
|
16
|
+
compiled starter.
|
|
17
|
+
|
|
18
|
+
@module CLI/Project
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
Whether a string is a valid project namespace: 1 to 4 lowercase letters.
|
|
22
|
+
|
|
23
|
+
@example
|
|
24
|
+
```ts
|
|
25
|
+
console.log(isValidNamespace('mc'));
|
|
26
|
+
console.log(isValidNamespace('mcxyz'));
|
|
27
|
+
console.log(isValidNamespace('toolong'));
|
|
28
|
+
```
|
|
29
|
+
@param ns - Candidate namespace.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isValidNamespace(ns: string): boolean;
|
|
32
|
+
/** Result of {@link scaffoldProject}. */
|
|
33
|
+
export interface ProjectResult {
|
|
34
|
+
/** Files to write, keyed by path relative to the project root. */
|
|
35
|
+
files: Record<string, string>;
|
|
36
|
+
/** The validated namespace. */
|
|
37
|
+
namespace: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
Builds the files of a complete dev environment for a namespace.
|
|
41
|
+
|
|
42
|
+
@example
|
|
43
|
+
```ts
|
|
44
|
+
const { namespace, files } = scaffoldProject('mc');
|
|
45
|
+
console.log(namespace);
|
|
46
|
+
console.log(Object.keys(files));
|
|
47
|
+
```
|
|
48
|
+
@param namespace - 1 to 4 lowercase letters; becomes the `src/<namespace>/` folder and
|
|
49
|
+
the first segment of every component tag.
|
|
50
|
+
@throws If `namespace` is not 1 to 4 lowercase letters.
|
|
51
|
+
*/
|
|
52
|
+
export declare function scaffoldProject(namespace: string): ProjectResult;
|
|
53
|
+
//# sourceMappingURL=create.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/cli/create.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;EAkBE;AAUF;;;;;;;;;;EAUE;AACF,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC7B,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;EAYE;AACF,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAuBhE"}
|