@twobirds/microcomponents 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +2 -16
  2. package/dist/cli/bundle.d.ts +106 -0
  3. package/dist/cli/bundle.d.ts.map +1 -0
  4. package/dist/cli/bundler.d.ts +44 -0
  5. package/dist/cli/bundler.d.ts.map +1 -0
  6. package/dist/cli/create.d.ts.map +1 -1
  7. package/dist/cli/dev.d.ts +87 -0
  8. package/dist/cli/dev.d.ts.map +1 -0
  9. package/dist/cli/dispatch.d.ts +6 -2
  10. package/dist/cli/dispatch.d.ts.map +1 -1
  11. package/dist/cli/index.js +1807 -1
  12. package/dist/cli/inliner.d.ts +42 -0
  13. package/dist/cli/inliner.d.ts.map +1 -0
  14. package/dist/cli/preview.d.ts +48 -0
  15. package/dist/cli/preview.d.ts.map +1 -0
  16. package/dist/core/elements.js +1294 -75
  17. package/dist/core/mcGuards.js +5 -8
  18. package/dist/mcp/api.json +2 -17
  19. package/dist/mcp/concepts/project-layout.md +9 -8
  20. package/dist/mcp/index.js +450 -230
  21. package/dist/microcomponents.js +2882 -9
  22. package/dist/state/formValues.js +2236 -281
  23. package/dist/state/observables.js +1794 -342
  24. package/dist/utils/events.js +171 -197
  25. package/package.json +7 -8
  26. package/dist/cli/create.js +0 -653
  27. package/dist/cli/dispatch.js +0 -316
  28. package/dist/cli/scaffold.js +0 -109
  29. package/dist/cli/writeScaffold.js +0 -114
  30. package/dist/core/MC.js +0 -837
  31. package/dist/core/index.js +0 -72
  32. package/dist/state/index.js +0 -5
  33. package/dist/state/placeholders.js +0 -187
  34. package/dist/types/index.js +0 -1
  35. package/dist/types/mcTypes.js +0 -9
  36. package/dist/utils/autoload.js +0 -160
  37. package/dist/utils/helpers.js +0 -532
  38. package/dist/utils/index.js +0 -12
  39. package/dist/utils/resolveComponentPath.js +0 -39
  40. package/dist/vite/index.d.ts +0 -7
  41. package/dist/vite/index.d.ts.map +0 -1
  42. package/dist/vite/index.js +0 -6
  43. package/dist/vite/loadAssets.d.ts +0 -36
  44. package/dist/vite/loadAssets.d.ts.map +0 -1
  45. package/dist/vite/loadAssets.js +0 -221
@@ -1,532 +0,0 @@
1
- /**
2
- @module Helpers
3
-
4
- Small runtime-agnostic utilities shared across the library: environment
5
- detection, object flattening/comparison, debouncing, accessor copying, and
6
- kebab-to-PascalCase conversion.
7
- */
8
- import { on, trigger } from './events.js';
9
- /**
10
- * Determines whether the current runtime environment is a web browser.
11
- *
12
- * This function works by attempting to access `this` within an anonymous function
13
- * and checking if it refers to the global `window` object. It returns `true`
14
- * when executed in a browser context, and `false` otherwise (e.g., Node.js).
15
- *
16
- * Note: While modern environments typically provide more reliable detection mechanisms,
17
- * this fallback remains compatible across older runtimes where other detection techniques
18
- * may be unreliable.
19
- *
20
- * @returns `true` if the code is running in a browser environment, `false` otherwise.
21
- *
22
- * @example
23
- * ```ts
24
- * if (isBrowser()) {
25
- * console.log('Running in a browser');
26
- * }
27
- * ```
28
- */
29
- export function isBrowser() {
30
- return typeof window !== 'undefined' && typeof window.document !== 'undefined';
31
- }
32
- /**
33
- * Checks if a value is a native JavaScript object (created via {} or new Object()).
34
- * @param value - The value to check.
35
- * @returns True if the value is a plain object, false otherwise.
36
- *
37
- * @example
38
- * ```ts
39
- * console.log(isNativeObject({}));
40
- * console.log(isNativeObject(new Object()));
41
- * console.log(isNativeObject([]));
42
- * console.log(isNativeObject(null));
43
- * ```
44
- */
45
- export function isNativeObject(value) {
46
- return typeof value === 'object' && value !== null && value.constructor === Object;
47
- }
48
- /**
49
- * Recursively sorts all keys in an object alphabetically, preserving nested structure.
50
- * @param source - The object to sort.
51
- * @returns A new object with sorted keys at all levels.
52
- *
53
- * @example
54
- * ```ts
55
- * const obj = { z: 1, a: { y: 2, b: 3 } };
56
- * console.log(JSON.stringify(sortObject(obj)));
57
- * ```
58
- */
59
- export function sortObject(source) {
60
- const result = {}, keys = Object.keys(source).sort();
61
- // Indexed for: no per-key callback/iterator overhead. ~15x faster than .forEach,
62
- // ~10x faster than for-of over the loop body itself (V8, 5M elems), and ~15x faster than .forEach()
63
- for (let i = 0; i < keys.length; i++) {
64
- const key = keys[i], value = source[key];
65
- if (isNativeObject(value)) {
66
- result[key] = sortObject(value);
67
- }
68
- else {
69
- result[key] = value;
70
- }
71
- }
72
- return result;
73
- }
74
- /**
75
- * Flattens a nested object into a single-level object with dot-separated keys.
76
- * Optionally sorts the resulting flat keys alphabetically (default: true).
77
- * @param source - The object to flatten.
78
- * @param doSort - Whether to sort the resulting keys (default: true).
79
- * @returns A flattened object with dot-notation keys.
80
- *
81
- * @example
82
- * ```ts
83
- * const obj = { user: { name: 'Alice', age: 30 } };
84
- * console.log(JSON.stringify(flattenObject(obj)));
85
- * ```
86
- */
87
- export function flattenObject(source, doSort = true) {
88
- const result = {};
89
- const record = source;
90
- const names = Object.getOwnPropertyNames(source);
91
- // Indexed for: no per-key callback overhead, and no extra copy from spreading
92
- // ~10x faster than for-of over the loop body itself (V8, 5M elems), and ~15x faster than .forEach()
93
- for (let i = 0; i < names.length; i++) {
94
- const propName = names[i], value = record[propName];
95
- if (value instanceof Object) {
96
- const temp = flattenObject(value, false);
97
- for (const j in temp) {
98
- result[propName + '.' + j] = temp[j];
99
- }
100
- }
101
- else {
102
- result[propName] = value;
103
- }
104
- }
105
- return doSort ? sortObject(result) : result;
106
- }
107
- /**
108
- * Structural deep-equality using SameValueZero for primitives.
109
- *
110
- * See {@link https://tc39.es/ecma262/multipage/abstract-operations.html#sec-samevaluezero}.
111
- *
112
- * Note: `Map`/`Set` are not structurally compared.
113
- *
114
- * @param a - The first value to compare.
115
- * @param b - The second value to compare.
116
- * @returns True if the values are deeply equal, false otherwise.
117
- *
118
- * @example
119
- * ```ts
120
- * console.log(deepEqual({ a: 1 }, { a: 1 }));
121
- * console.log(deepEqual({ a: { b: 2 } }, { a: {} }));
122
- * console.log(deepEqual({ a: NaN }, { a: NaN }));
123
- * console.log(deepEqual({ a: NaN }, { a: null }));
124
- * ```
125
- */
126
- export function deepEqual(a, b) {
127
- // SameValueZero: identical primitives/refs, plus NaN === NaN.
128
- if (a === b || (a !== a && b !== b))
129
- return true;
130
- /* v8 ignore start */
131
- // Beyond SameValueZero, equality needs two non-null objects of the same kind.
132
- if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null)
133
- return false;
134
- if (a.constructor !== b.constructor)
135
- return false;
136
- if (a instanceof Date)
137
- return a.getTime() === b.getTime();
138
- if (a instanceof RegExp)
139
- return a.toString() === b.toString();
140
- /* v8 ignore end */
141
- if (Array.isArray(a)) {
142
- const bArr = b;
143
- /* v8 ignore next */
144
- if (a.length !== bArr.length)
145
- return false;
146
- for (let i = 0; i < a.length; i++) {
147
- if (!deepEqual(a[i], bArr[i]))
148
- return false;
149
- }
150
- return true;
151
- }
152
- const aObj = a, bObj = b, keys = Object.keys(aObj);
153
- if (keys.length !== Object.keys(bObj).length)
154
- return false;
155
- for (let i = 0; i < keys.length; i++) {
156
- const key = keys[i];
157
- if (!Object.prototype.hasOwnProperty.call(bObj, key) || !deepEqual(aObj[key], bObj[key]))
158
- return false;
159
- }
160
- return true;
161
- }
162
- /**
163
- * Retrieves a nested value from an object using a namespace path (dot-separated).
164
- * @param ns - The namespace string or array of keys representing the path.
165
- * @param obj - The object to traverse.
166
- * @returns The value at the specified namespace path, or undefined if not found.
167
- *
168
- * @example
169
- * ```ts
170
- * const data = { user: { profile: { name: 'Alice' } } };
171
- * console.log(nameSpace('user.profile.name', data));
172
- * console.log(nameSpace(['user', 'profile'], data));
173
- * ```
174
- */
175
- export function nameSpace(ns, obj = {}) {
176
- const source = obj;
177
- const nsa = typeof ns === 'string' ? ns.split('.') : ns;
178
- if (!source || !nsa[0] || !source[nsa[0]]) {
179
- return undefined;
180
- }
181
- if (nsa.length > 1) {
182
- const next = source[nsa[0]];
183
- if (isNativeObject(next)) {
184
- return nameSpace(nsa.slice(1), next);
185
- }
186
- return undefined;
187
- }
188
- return source[nsa[0]];
189
- }
190
- /**
191
- * Parses a template string or object, replacing placeholders in the form of {key.path} with
192
- * corresponding values from the provided data object using namespace resolution.
193
- * Also recursively processes objects and arrays within the input.
194
- * @param template - The string or object to parse (can contain {{placeholder}} expressions).
195
- * @param parseThis - The object containing values for placeholder substitution.
196
- * @returns The parsed result, with placeholders replaced by actual values.
197
- *
198
- * @example
199
- * ```ts
200
- * const data = { user: { name: 'Alice' } };
201
- * console.log(parse('Hello {user.name}!', data));
202
- * console.log(parse(['Hi {user.name}', 'Bye {user.name}'], data));
203
- * ```
204
- */
205
- export function parse(template, parseThis, ...rest) {
206
- const args = [template, parseThis, ...rest];
207
- if (args.length > 2) {
208
- while (args.length > 1) {
209
- args[0] = parse(args[0], args[1]);
210
- args.splice(1, 1);
211
- }
212
- return args[0];
213
- }
214
- if (typeof template === 'string') {
215
- let result = template;
216
- template.match(/\{[^\{\}]*\}/g)?.forEach((pPropname) => {
217
- const propname = pPropname.substring(1, pPropname.length - 1), value = nameSpace(propname, parseThis);
218
- if (typeof value !== 'undefined') {
219
- result = result.replace(pPropname, String(value));
220
- }
221
- });
222
- return result;
223
- }
224
- else if (isNativeObject(template)) {
225
- const record = template;
226
- Object.keys(record).forEach((pKey) => {
227
- /* v8 ignore next */
228
- if (Object.prototype.hasOwnProperty.call(record, pKey)) {
229
- record[pKey] = parse(record[pKey], parseThis);
230
- }
231
- });
232
- }
233
- return template;
234
- }
235
- /**
236
- * Converts a kebab-case string to PascalCase.
237
- * Example: 'my-component-name' -> 'MyComponentName'
238
- * @param str - The kebab-case string to convert.
239
- * @returns The converted PascalCase string.
240
- *
241
- * @example
242
- * ```ts
243
- * console.log(kebabToPascal('my-element'));
244
- * ```
245
- */
246
- export function kebabToPascal(str) {
247
- return str
248
- .split('-') // Split by hyphens
249
- .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) // Capitalize each part
250
- .join(''); // Join without spaces
251
- }
252
- /**
253
- * Creates a debounced version of a function that delays execution until after the specified
254
- * number of milliseconds have elapsed since the last time this function was invoked.
255
- * Useful for rate-limiting expensive operations like event handlers or API calls.
256
- * @param func - The function to debounce.
257
- * @param milliseconds - The number of milliseconds to delay execution.
258
- * @returns A debounced version of the input function.
259
- *
260
- * @example
261
- * ```ts
262
- * const log = debounce(() => console.log('called'), 300);
263
- * log();
264
- * log();
265
- * ```
266
- */
267
- export function debounce(func, milliseconds) {
268
- let timeout;
269
- return (...args) => {
270
- clearTimeout(timeout);
271
- timeout = setTimeout(() => {
272
- func(...args);
273
- }, milliseconds);
274
- };
275
- }
276
- /**
277
- * Parses an HTML string and returns an array of DOM elements.
278
- * Handles self-closing tags (XHTML style) by converting them to full closing tags first.
279
- * @hidden
280
- * @param html - The HTML string to parse.
281
- * @returns An array of HTMLElement objects representing the parsed HTML nodes.
282
- *
283
- * @example
284
- * ```ts
285
- * const elems = htmlToElements('<div>Hello</div><span>World</span>');
286
- * console.log(elems.map((el) => el.tagName));
287
- * ```
288
- */
289
- export function htmlToElements(html) {
290
- const template = document.createElement('template');
291
- html = html.replace(/<([A-Za-z0-9\-]*)([^>\/]*)(\/>)/gi, '<$1$2></$1>'); // replace XHTML closing tags by full closing tags
292
- template.innerHTML = html;
293
- template.content.normalize();
294
- return Array.from(template.content.childNodes);
295
- }
296
- /**
297
- * Copies all getter and setter properties from a source object to a target object.
298
- * Does not copy methods or regular data properties—only accessor properties (get/set).
299
- * @hidden
300
- * @param source - The source object with getters and/or setters to copy.
301
- * @param target - The target object to which the accessors will be copied.
302
- *
303
- * @example
304
- * ```ts
305
- * const src = { get name() { return 'Alice'; } };
306
- * const tgt = {};
307
- * copyGettersSetters(src, tgt);
308
- * console.log(tgt.name);
309
- * ```
310
- */
311
- export function copyGettersSetters(source, target) {
312
- const descriptors = Object.getOwnPropertyDescriptors(source);
313
- for (const [key, descriptor] of Object.entries(descriptors)) {
314
- if ('get' in descriptor || 'set' in descriptor) {
315
- Object.defineProperty(target, key, descriptor);
316
- }
317
- }
318
- }
319
- /**
320
- * Injects a CSS string into the given scope (document or shadow root) as an adopted stylesheet.
321
- * Enables css-in-js so that every custom element is self-contained and importable.
322
- *
323
- * @hidden
324
- * @param target - The scope to inject styles into: `document` for global styles, or a `ShadowRoot` for encapsulated component internals.
325
- * @param css - The CSS string to inject.
326
- * @returns The created `CSSStyleSheet` instance that was adopted into the target scope.
327
- *
328
- * When targeting **document**: selectors like `:host`, `::slotted()`, and shadow-internal classes are **not allowed** — they have no effect outside a shadow root. Use only global selectors, element tags, or layout presets.
329
- * When targeting **shadowRoot**: use `:host` for the custom element itself, standard selectors (`.inner`, `#id`) for internal structure, and `::slotted()` for projected light-DOM content.
330
- *
331
- * @example Inject global styles into the document:
332
- * ```ts
333
- * import { injectCSS } from '@twobirds/mc/utils/helpers';
334
- * injectCSS(document, 'body { display: block; }');
335
- * ```
336
- *
337
- * @example Inject global styles for a micro component into the document:
338
- * ```ts
339
- * import { injectCSS } from '@twobirds/mc/utils/helpers';
340
- * injectCSS(document, 'my-microcomponent { display: block; }');
341
- * ```
342
- *
343
- * @example Inject scoped styles into a shadow root:
344
- * ```ts
345
- * const shadow = element.attachShadow({ mode: 'open' });
346
- * injectCSS(shadow, ':host { color: var(--text); } .inner { padding: 8px; }');
347
- * ```
348
- * Styles can also be added using a compound innerHTML statement: `shadow.innerHTML = \`<style>${style}</style>${template}\``
349
- */
350
- const _injectedCSS = new WeakMap();
351
- export function injectCSS(target, css) {
352
- const injected = _injectedCSS.get(target) ?? new Set();
353
- if (injected.has(css))
354
- return target.adoptedStyleSheets[0];
355
- injected.add(css);
356
- _injectedCSS.set(target, injected);
357
- const sheet = new CSSStyleSheet();
358
- sheet.replaceSync(css);
359
- target.adoptedStyleSheets.push(sheet);
360
- return sheet;
361
- }
362
- /**
363
- * Processes a record of asset strings and applies them to the given target element.
364
- * Supports injecting CSS into document or shadow root, and setting innerHTML for
365
- * both target and shadow DOM. Automatically attaches a shadow root if any key starts
366
- * with `'shadow'`.
367
- *
368
- * Recognized keys: `'css'`, `'targetCss'` (document-level styles), `'shadowCss'`
369
- * (shadow-root styles), `'shadowHtml'` (shadow innerHTML), `'targetHtml'` (target innerHTML).
370
- *
371
- * @param instance - The micro component to apply assets onto.
372
- * @param assets - A record mapping asset type keys to their string content.
373
- *
374
- * @example
375
- * ```ts
376
- * processAssets(this, {
377
- * css: 'body { margin: 0; }',
378
- * shadowCss: ':host { display: block; }',
379
- * shadowHtml: '<slot></slot>'
380
- * });
381
- * ```
382
- */
383
- export function processAssets(instance, assets) {
384
- const target = instance.target;
385
- let shadow = target.shadowRoot;
386
- if (!shadow && Object.keys(assets).some((key) => key.indexOf('shadow') === 0)) {
387
- shadow = target.attachShadow({ mode: 'open' });
388
- }
389
- Object.keys(assets).forEach((key) => {
390
- switch (key) {
391
- case 'css':
392
- injectCSS(document, assets[key]);
393
- break;
394
- case 'targetCss':
395
- injectCSS(document, assets[key]);
396
- break;
397
- case 'shadowCss':
398
- injectCSS(shadow, assets[key]);
399
- break;
400
- case 'shadowHtml':
401
- shadow.innerHTML = assets[key];
402
- bindTemplateEvents(shadow, instance);
403
- break;
404
- case 'targetHtml':
405
- target.innerHTML = assets[key];
406
- bindTemplateEvents(target, instance);
407
- break;
408
- }
409
- });
410
- }
411
- /**
412
- * Loads companion asset files (CSS, HTML) for a given component basename from the server.
413
- *
414
- * Each entry in `assets` encodes an optional variant and extension in camelCase, e.g. `'shadowCss'` → `{name}.shadow.css`,
415
- * `'targetHtml'` → `{name}.target.html`. Plain entries like `'css'` or `'html'` resolve to
416
- * `{name}.css` / `{name}.html`.
417
- *
418
- * In bundled mode the Vite plugin replaces this call with an inline array literal, so `.then()`
419
- * fires synchronously — no async overhead.
420
- *
421
- * @hidden
422
- * @param name - The component basename (e.g. `'shop-catalog'`).
423
- * @param assets - Array of asset descriptors such as `'shadowCss'`, `'targetHtml'`, `'shadowHtml'`, `'css'`, `'html'`.
424
- * @returns A promise resolving to an array of file contents in the same order as `assets`. If a file is not found, the corresponding entry is `'file not found: ' + filename`.
425
- *
426
- * @example
427
- * ```ts
428
- * export const MyComponent = loadAssets('my-component', ['shadowCss', 'shadowHtml']).then(([shadowCss, shadowHtml]) => {
429
- * class _MyComponent extends DC { ... }
430
- * defineCE('my-component', _MyComponent);
431
- * return _MyComponent;
432
- * });
433
- * ```
434
- */
435
- export function loadAssets(name, assets) {
436
- const parseAsset = (asset) => {
437
- // Match camelCase variant+ext, e.g. 'shadowCss' → ['shadow','css']
438
- const m = asset.match(/^([a-z]+)([A-Z][a-z]*)$/);
439
- if (m) {
440
- return `./${name.replace(/-/g, '/')}.${m[1]}.${m[2].toLowerCase()}`;
441
- }
442
- // Plain extension, e.g. 'css' → 'catalog.css'
443
- return `./${name.replace(/-/g, '/')}.${asset.toLowerCase()}`;
444
- };
445
- return Promise.all(assets.map(async (asset) => {
446
- const filename = parseAsset(asset);
447
- //console.log(filename);
448
- try {
449
- const resp = await fetch(filename);
450
- if (!resp.ok) {
451
- return `file not found: ${filename}`;
452
- }
453
- if (filename.endsWith('json')) {
454
- const text = await resp.text();
455
- try {
456
- return JSON.parse(text);
457
- }
458
- catch {
459
- console.error(`could not JSON.parse() asset '${asset}' from ${filename}:\n`, text);
460
- return null;
461
- }
462
- }
463
- return resp.text();
464
- }
465
- catch {
466
- return `file not found: ${filename}`;
467
- }
468
- }));
469
- }
470
- /**
471
- * Binds declarative event attributes in a template fragment to microcomponent triggers.
472
- *
473
- * Scans all elements under `root` for attributes whose names correspond to native DOM
474
- * events (e.g. `click`, `submit`, `change`). The attribute value encodes the target and
475
- * handler method in the form `target|methodName`:
476
- *
477
- * - `this|myHandler` — triggers locally on the component attached to this element.
478
- * - `other-comp|submit` — resolves elements via `querySelectorAll('other-comp')` and
479
- * triggers the event on each matched host's `_mc`.
480
- *
481
- * An optional sibling `payload` attribute supplies the data argument for `trigger()`.
482
- * After binding, both the event attribute and the payload attribute are removed from the DOM.
483
- *
484
- * @param rootElement - The container element whose descendants should be scanned for bindings.
485
- * @param instance - The instance to trigger events on.
486
- *
487
- * @example
488
- * ```html
489
- * <button click='this|onSubmit|{"action":"go"}'>Submit</button>
490
- * <input change="|cart-form|refresh">
491
- * ```
492
- */
493
- export function bindTemplateEvents(rootElement, instance) {
494
- // Collect all elements that carry at least one attribute matching a native event name.
495
- const allElements = [...rootElement.querySelectorAll('*')];
496
- for (const el of allElements) {
497
- if (!(el instanceof HTMLElement))
498
- continue;
499
- const attrs = [...el.attributes];
500
- for (const attr of attrs) {
501
- const lowerName = attr.name.toLowerCase();
502
- // Check if this attribute name maps to a native event handler property.
503
- if (!('on' + lowerName in el))
504
- continue;
505
- const parts = attr.value.trim().split('|');
506
- if (parts.length < 2)
507
- continue; // need at least selector and eventname
508
- const [selector, event, payload] = parts;
509
- // Clean up binding attributes from the DOM.
510
- el.removeAttribute(attr.name);
511
- // Resolve payload from sibling attribute if present.
512
- let payloadData; // intentional
513
- if (payload) {
514
- try {
515
- payloadData = JSON.parse(payload);
516
- }
517
- catch {
518
- payloadData = payload;
519
- }
520
- }
521
- // Wire the native event listener.
522
- if (selector === 'this' || selector === '') {
523
- // Local trigger — fire on the _mc attached to this element.
524
- on(el, lowerName, () => instance.trigger(event, payloadData));
525
- }
526
- else {
527
- // Selector-based trigger — query and fire on every match.
528
- on(el, lowerName, () => trigger(selector, event, payloadData));
529
- }
530
- }
531
- }
532
- }
@@ -1,12 +0,0 @@
1
- /**
2
- Utils module — events, autoload, and helper utilities.
3
-
4
- @module Utilities
5
- @showGroups
6
- */
7
- /** @group Events */
8
- export { getMcEventName, trueEventName, off, on, one, trigger, BubbleController, } from './events.js';
9
- /** @group Autoload */
10
- export { autoload } from './autoload.js';
11
- /** @group Helpers */
12
- export { isBrowser, isNativeObject, sortObject, flattenObject, deepEqual, nameSpace, parse, kebabToPascal, debounce, htmlToElements, copyGettersSetters, injectCSS, processAssets, loadAssets, bindTemplateEvents, } from './helpers.js';
@@ -1,39 +0,0 @@
1
- /**
2
- @module Autoload
3
-
4
- Single source of truth for the tag-to-file convention: hyphens become path
5
- separators, so `my-card` resolves to `./my/card.js`. Imported by the runtime
6
- autoload loader and by build-time tooling so both agree on the path without
7
- either duplicating the rule.
8
- */
9
- /**
10
- The tag-to-path primitive: hyphens become path separators, with no prefix or
11
- extension. `my-card` → `my/card`. The single source of truth for the
12
- convention; {@link resolveComponentPath} and build-time tooling both derive
13
- their paths from it so neither duplicates the rule.
14
-
15
- @example Returns `'my/card'` for `my-card`, and `'app/header'` for `app-header`.
16
- ```ts
17
- tagPath('my-card');
18
- tagPath('app-header');
19
- ```
20
- @hidden
21
- @group Autoload
22
- */
23
- export function tagPath(tag) {
24
- return tag.split('-').join('/');
25
- }
26
- /**
27
- Resolves a microcomponent tag name to its autoload module path by prefixing and
28
- suffixing {@link tagPath}: `my-card` → `./my/card.js`.
29
-
30
- @example Returns `'./my/card.js'` for `my-card`, and `'./app/header.js'` for `app-header`.
31
- ```ts
32
- resolveComponentPath('my-card');
33
- resolveComponentPath('app-header');
34
- ```
35
- @group Autoload
36
- */
37
- export function resolveComponentPath(tag) {
38
- return './' + tagPath(tag) + '.js';
39
- }
@@ -1,7 +0,0 @@
1
- /**
2
- Vite module — build-time plugins for a bundled Micro Components project.
3
-
4
- @module Vite
5
- */
6
- export { loadAssetsPlugin } from './loadAssets.js';
7
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAAA;;;;EAIE;AAEF,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,6 +0,0 @@
1
- /**
2
- Vite module — build-time plugins for a bundled Micro Components project.
3
-
4
- @module Vite
5
- */
6
- export { loadAssetsPlugin } from './loadAssets.js';
@@ -1,36 +0,0 @@
1
- /**
2
- Inlines `static assets = [...]` declarations on DC classes for a bundled build: companion
3
- `.css` / `.html` files are read at build time and embedded as a `static _assets = { ... }`
4
- property inserted as the first line inside the class body, so `loadAssets()` never fetches
5
- them at runtime. The original `static assets` line is preserved for debugging purposes.
6
-
7
- The plugin ships as its own entry, `@twobirds/microcomponents/vite`, so a project that
8
- bundles to `public/` imports it without copying the source.
9
-
10
- @example
11
- ```ts
12
- import { loadAssetsPlugin } from '@twobirds/microcomponents/vite';
13
-
14
- export default defineConfig({
15
- plugins: [loadAssetsPlugin(sourceRoot)],
16
- });
17
- ```
18
-
19
- @module Vite
20
- */
21
- import type { PluginOption } from 'vite';
22
- /**
23
- * Vite plugin factory that inlines companion `.css` / `.html` assets into the
24
- * DC classes declaring them through `static assets = [...]`.
25
- *
26
- * @example Register the plugin in a Vite config, pointing at the source root.
27
- * ```ts
28
- * import { loadAssetsPlugin } from './vite-plugin-load-assets';
29
- * export default defineConfig({ plugins: [loadAssetsPlugin(__dirname)] });
30
- * ```
31
- *
32
- * @param rootDir Directory holding the component source files.
33
- * @returns A Vite plugin option.
34
- */
35
- export declare function loadAssetsPlugin(rootDir: string): PluginOption;
36
- //# sourceMappingURL=loadAssets.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loadAssets.d.ts","sourceRoot":"","sources":["../../src/vite/loadAssets.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;EAmBE;AAIF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,MAAM,CAAC;AAgJzC;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAiE9D"}