micra.js 1.1.0 → 2.1.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 +37 -30
- package/dist/dom/query.d.ts +6 -0
- package/dist/index.d.ts +1 -1
- package/dist/micra.cjs.js +32 -9
- package/dist/micra.cjs.js.map +2 -2
- package/dist/micra.esm.js +32 -9
- package/dist/micra.esm.js.map +2 -2
- package/dist/micra.js +32 -9
- package/dist/micra.js.map +2 -2
- package/dist/micra.min.js +2 -2
- package/dist/types.d.ts +9 -1
- package/package.json +1 -1
- package/src/dom/directives.ts +40 -5
- package/src/dom/each.ts +4 -1
- package/src/dom/events.ts +2 -2
- package/src/dom/query.ts +15 -1
- package/src/index.ts +1 -1
- package/src/types.ts +10 -1
- package/src/utils/fetch.ts +5 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Micra.js
|
|
2
2
|
|
|
3
|
-
Micra.js is a lightweight reactive TypeScript framework for small sites and SaaS apps. It gives you reactive state, DOM directives, keyed list rendering, an event bus, SSR-friendly props, and auto-mounting in about
|
|
3
|
+
Micra.js is a lightweight reactive TypeScript framework for small sites and SaaS apps. It gives you reactive state, DOM directives, keyed list rendering, an event bus, SSR-friendly props, and auto-mounting in about 5 KB gzip.
|
|
4
4
|
|
|
5
5
|
## What is Micra.js?
|
|
6
6
|
|
|
@@ -27,15 +27,19 @@ Use it when you want:
|
|
|
27
27
|
<button @click="increment">+</button>
|
|
28
28
|
</div>
|
|
29
29
|
|
|
30
|
-
<script src="https://
|
|
30
|
+
<script src="https://cdn.jsdelivr.net/npm/micra.js/dist/micra.min.js"></script>
|
|
31
31
|
<script>
|
|
32
|
-
Micra.define(
|
|
32
|
+
Micra.define("counter", {
|
|
33
33
|
state: { count: 0 },
|
|
34
|
-
increment() {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
increment() {
|
|
35
|
+
this.state.count++;
|
|
36
|
+
},
|
|
37
|
+
decrement() {
|
|
38
|
+
this.state.count--;
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
Micra.start();
|
|
39
43
|
</script>
|
|
40
44
|
```
|
|
41
45
|
|
|
@@ -44,7 +48,7 @@ Use it when you want:
|
|
|
44
48
|
### CDN
|
|
45
49
|
|
|
46
50
|
```html
|
|
47
|
-
<script src="https://
|
|
51
|
+
<script src="https://cdn.jsdelivr.net/npm/micra.js/dist/micra.min.js"></script>
|
|
48
52
|
```
|
|
49
53
|
|
|
50
54
|
### npm
|
|
@@ -54,7 +58,7 @@ npm install micra.js
|
|
|
54
58
|
```
|
|
55
59
|
|
|
56
60
|
```ts
|
|
57
|
-
import * as Micra from
|
|
61
|
+
import * as Micra from "micra.js";
|
|
58
62
|
```
|
|
59
63
|
|
|
60
64
|
## Basic usage
|
|
@@ -71,42 +75,42 @@ A counter mounted automatically from `data-component`:
|
|
|
71
75
|
```
|
|
72
76
|
|
|
73
77
|
```ts
|
|
74
|
-
import * as Micra from
|
|
78
|
+
import * as Micra from "micra.js";
|
|
75
79
|
|
|
76
|
-
Micra.define(
|
|
80
|
+
Micra.define("counter", {
|
|
77
81
|
state: { count: 0 },
|
|
78
82
|
|
|
79
83
|
increment() {
|
|
80
|
-
this.state.count
|
|
84
|
+
this.state.count++;
|
|
81
85
|
},
|
|
82
86
|
|
|
83
87
|
decrement() {
|
|
84
|
-
this.state.count
|
|
88
|
+
this.state.count--;
|
|
85
89
|
},
|
|
86
90
|
|
|
87
91
|
reset() {
|
|
88
|
-
this.state.count = 0
|
|
92
|
+
this.state.count = 0;
|
|
89
93
|
},
|
|
90
|
-
})
|
|
94
|
+
});
|
|
91
95
|
|
|
92
|
-
Micra.start()
|
|
96
|
+
Micra.start();
|
|
93
97
|
```
|
|
94
98
|
|
|
95
99
|
## Directives
|
|
96
100
|
|
|
97
|
-
| Directive
|
|
98
|
-
|
|
99
|
-
| `data-text`
|
|
100
|
-
| `data-html`
|
|
101
|
-
| `data-if`
|
|
102
|
-
| `data-show`
|
|
103
|
-
| `data-bind`
|
|
104
|
-
| `data-model` | `data-model="search"`
|
|
105
|
-
| `data-each`
|
|
106
|
-
| `data-ref`
|
|
107
|
-
| `data-class` | `data-class="active:isActive"`
|
|
108
|
-
| `data-on`
|
|
109
|
-
| `@event`
|
|
101
|
+
| Directive | Example | Description |
|
|
102
|
+
| ------------ | ---------------------------------------- | ------------------------- |
|
|
103
|
+
| `data-text` | `data-text="name"` | Set `textContent` |
|
|
104
|
+
| `data-html` | `data-html="content"` | Set `innerHTML` |
|
|
105
|
+
| `data-if` | `data-if="count > 0"` | Toggle display |
|
|
106
|
+
| `data-show` | `data-show="loaded"` | Alias of `data-if` |
|
|
107
|
+
| `data-bind` | `data-bind="href:url, disabled:loading"` | Bind attributes |
|
|
108
|
+
| `data-model` | `data-model="search"` | Two-way input binding |
|
|
109
|
+
| `data-each` | `data-each="items" data-key="id"` | List rendering |
|
|
110
|
+
| `data-ref` | `data-ref="chart"` | DOM ref in `this.refs` |
|
|
111
|
+
| `data-class` | `data-class="active:isActive"` | Toggle classes additively |
|
|
112
|
+
| `data-on` | `data-on="click:save"` | Bind DOM events |
|
|
113
|
+
| `@event` | `@click="increment"` | Shorthand event binding |
|
|
110
114
|
|
|
111
115
|
## API reference summary
|
|
112
116
|
|
|
@@ -164,3 +168,6 @@ this.on(event, handler)
|
|
|
164
168
|
- [SSR](./docs/ssr.md)
|
|
165
169
|
- [Examples](./docs/examples.md)
|
|
166
170
|
- [API reference](./docs/api-reference.md)
|
|
171
|
+
- Recipes:
|
|
172
|
+
- [Todo app](./docs/recipes/todo-app.md)
|
|
173
|
+
- [Server-sent events (SSE)](./docs/recipes/sse.md)
|
package/dist/dom/query.d.ts
CHANGED
|
@@ -21,3 +21,9 @@ export declare function queryAll(root: ParentNode, sel: string): Element[];
|
|
|
21
21
|
* owned by that nested component, not by root's component — so we skip it.
|
|
22
22
|
*/
|
|
23
23
|
export declare function queryOwn(root: Element, attr: string): Element[];
|
|
24
|
+
/**
|
|
25
|
+
* Like queryOwn but accepts an arbitrary CSS selector. Used by bindAtEvents
|
|
26
|
+
* which scans `*` for `@`-prefixed attribute names (no attribute selector exists
|
|
27
|
+
* for those).
|
|
28
|
+
*/
|
|
29
|
+
export declare function queryOwnAll(root: Element, sel: string): Element[];
|
package/dist/index.d.ts
CHANGED
package/dist/micra.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Micra.js
|
|
1
|
+
/* Micra.js v2.1.0 — https://github.com/micra-js/micra — MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -62,17 +62,19 @@ async function micraFetch(url, options = {}) {
|
|
|
62
62
|
if (method === "GET" || method === "HEAD") {
|
|
63
63
|
const params = {};
|
|
64
64
|
for (const [k, v] of Object.entries(options)) {
|
|
65
|
-
if (k !== "method" && k !== "headers" && v != null)
|
|
65
|
+
if (k !== "method" && k !== "headers" && k !== "signal" && v != null)
|
|
66
|
+
params[k] = String(v);
|
|
66
67
|
}
|
|
67
68
|
if (Object.keys(params).length)
|
|
68
69
|
finalUrl += (url.includes("?") ? "&" : "?") + new URLSearchParams(params);
|
|
69
|
-
} else {
|
|
70
|
+
} else if (options.body !== void 0) {
|
|
70
71
|
headers["Content-Type"] = "application/json";
|
|
71
|
-
body = JSON.stringify(options.body
|
|
72
|
+
body = JSON.stringify(options.body);
|
|
72
73
|
}
|
|
73
74
|
const res = await fetch(finalUrl, {
|
|
74
75
|
method,
|
|
75
76
|
headers,
|
|
77
|
+
...options.signal !== void 0 ? { signal: options.signal } : {},
|
|
76
78
|
...body !== void 0 ? { body } : {}
|
|
77
79
|
});
|
|
78
80
|
if (!res.ok)
|
|
@@ -259,7 +261,13 @@ function queryAll(root, sel) {
|
|
|
259
261
|
return Array.from(root.querySelectorAll(sel));
|
|
260
262
|
}
|
|
261
263
|
function queryOwn(root, attr) {
|
|
262
|
-
return queryAll(root, `[${attr}]`)
|
|
264
|
+
return filterOwn(root, queryAll(root, `[${attr}]`));
|
|
265
|
+
}
|
|
266
|
+
function queryOwnAll(root, sel) {
|
|
267
|
+
return filterOwn(root, queryAll(root, sel));
|
|
268
|
+
}
|
|
269
|
+
function filterOwn(root, els) {
|
|
270
|
+
return els.filter((el) => {
|
|
263
271
|
let node = el.parentElement;
|
|
264
272
|
while (node && node !== root) {
|
|
265
273
|
if (node.hasAttribute("data-component")) return false;
|
|
@@ -279,7 +287,21 @@ function applyHtml(el, expr, state) {
|
|
|
279
287
|
var _a;
|
|
280
288
|
el.innerHTML = String((_a = evalExpr(expr, state)) != null ? _a : "");
|
|
281
289
|
}
|
|
282
|
-
function applyIf(
|
|
290
|
+
function applyIf(binding, state) {
|
|
291
|
+
const el = binding.el;
|
|
292
|
+
const truthy = !!evalExpr(binding.expr, state);
|
|
293
|
+
if (truthy) {
|
|
294
|
+
const ph = binding.placeholder;
|
|
295
|
+
if (ph && ph.parentNode) ph.parentNode.replaceChild(el, ph);
|
|
296
|
+
} else {
|
|
297
|
+
const parent = el.parentNode;
|
|
298
|
+
if (parent) {
|
|
299
|
+
if (!binding.placeholder) binding.placeholder = document.createComment("if");
|
|
300
|
+
parent.replaceChild(binding.placeholder, el);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function applyShow(el, expr, state) {
|
|
283
305
|
el.style.display = evalExpr(expr, state) ? "" : "none";
|
|
284
306
|
}
|
|
285
307
|
function applyBind(el, pairs, state) {
|
|
@@ -354,10 +376,10 @@ function applyDirectives(root, state, rawState, _instance) {
|
|
|
354
376
|
applyFromList(el.__micraCache, state, rawState);
|
|
355
377
|
}
|
|
356
378
|
function applyFromList(cache, state, rawState) {
|
|
379
|
+
cache.if.forEach((b) => applyIf(b, state));
|
|
357
380
|
cache.text.forEach((b) => applyText(b.el, b.expr, state));
|
|
358
381
|
cache.html.forEach((b) => applyHtml(b.el, b.expr, state));
|
|
359
|
-
cache.
|
|
360
|
-
cache.show.forEach((b) => applyIf(b.el, b.expr, state));
|
|
382
|
+
cache.show.forEach((b) => applyShow(b.el, b.expr, state));
|
|
361
383
|
cache.bind.forEach((b) => applyBind(b.el, b.pairs, state));
|
|
362
384
|
cache.model.forEach((b) => applyModel(b.el, b.expr.trim(), rawState));
|
|
363
385
|
cache.class.forEach((b) => applyClass(b.el, b.pairs, state));
|
|
@@ -432,7 +454,7 @@ function bindDataOn(root, instance) {
|
|
|
432
454
|
}
|
|
433
455
|
function bindAtEvents(root, instance) {
|
|
434
456
|
const isFragment = root.nodeType === 11;
|
|
435
|
-
const all = isFragment ? queryAll(root, "*") :
|
|
457
|
+
const all = isFragment ? queryAll(root, "*") : queryOwnAll(root, "*");
|
|
436
458
|
if (!isFragment && !all.includes(root)) all.unshift(root);
|
|
437
459
|
for (const el of all) {
|
|
438
460
|
const mEl = el;
|
|
@@ -503,6 +525,7 @@ function renderList(root, state, rawState, instance) {
|
|
|
503
525
|
const marker = tmpl.__micraMarker;
|
|
504
526
|
const keyMap = tmpl.__micraNodes;
|
|
505
527
|
const parent = marker.parentNode;
|
|
528
|
+
if (!parent) return;
|
|
506
529
|
if (!Array.isArray(items)) {
|
|
507
530
|
tmpl.__micraList.forEach((n) => n.remove());
|
|
508
531
|
tmpl.__micraList = [];
|