sprae 7.0.0 → 8.0.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.
- package/package.json +3 -6
- package/readme.md +44 -15
- package/sprae.auto.js +192 -201
- package/sprae.auto.min.js +1 -1
- package/sprae.js +192 -201
- package/sprae.min.js +1 -1
- package/src/core.js +22 -16
- package/src/directives.js +111 -85
- package/src/domdiff.js +10 -7
- package/src/state.proxy.js +4 -2
- package/src/state.signals-proxy.js +74 -49
- package/src/state.signals.js +2 -2
- package/src/util.js +0 -30
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sprae",
|
|
3
3
|
"description": "DOM microhydration.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "8.0.1",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"module": "src/index.js",
|
|
7
7
|
"type": "module",
|
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
"src"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@preact/signals-core": "^1.5.0"
|
|
17
|
-
"swapdom": "^1.1.1"
|
|
16
|
+
"@preact/signals-core": "^1.5.0"
|
|
18
17
|
},
|
|
19
18
|
"devDependencies": {
|
|
20
19
|
"@preact/signals": "^1.1.3",
|
|
@@ -22,11 +21,9 @@
|
|
|
22
21
|
"esbuild": "^0.15.14",
|
|
23
22
|
"hyperf": "^1.6.2",
|
|
24
23
|
"jsdom": "^21.1.0",
|
|
25
|
-
"signal-struct": "^1.10.0",
|
|
26
24
|
"terser": "^5.15.1",
|
|
27
25
|
"tst": "^7.1.1",
|
|
28
26
|
"usignal": "^0.8.9",
|
|
29
|
-
"value-ref": "^2.1.0",
|
|
30
27
|
"wait-please": "^3.1.0"
|
|
31
28
|
},
|
|
32
29
|
"scripts": {
|
|
@@ -54,7 +51,7 @@
|
|
|
54
51
|
"directives",
|
|
55
52
|
"templating"
|
|
56
53
|
],
|
|
57
|
-
"author": "Dmitry
|
|
54
|
+
"author": "Dmitry Iv <df.creative@gmail.com>",
|
|
58
55
|
"license": "MIT",
|
|
59
56
|
"bugs": {
|
|
60
57
|
"url": "https://github.com/dy/sprae/issues"
|
package/readme.md
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
> DOM tree hydration with reactivity.
|
|
4
4
|
|
|
5
|
-
_Sprae_ is
|
|
5
|
+
_Sprae_ is compact ergonomic[*](#justification--alternatives) progressive enhancement framework.<br/>
|
|
6
|
+
It provides reactive `:`-attributes that enable simple markup logic without need for complex scripts.<br/>
|
|
7
|
+
Perfect for small-scale websites, prototypes or UI logic.<br/>
|
|
8
|
+
It is tiny and performant alternative to [alpine](https://github.com/alpinejs/alpine), [petite-vue](https://github.com/vuejs/petite-vue) or [template-parts](https://github.com/github/template-parts).
|
|
6
9
|
|
|
7
|
-
##
|
|
10
|
+
## Usage
|
|
8
11
|
|
|
9
12
|
### Autoinit
|
|
10
13
|
|
|
@@ -40,8 +43,27 @@ To init manually as module, import [`sprae.js`](./sprae.js):
|
|
|
40
43
|
```
|
|
41
44
|
|
|
42
45
|
Sprae evaluates `:`-attributes and evaporates them.<br/>
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
|
|
47
|
+
## State
|
|
48
|
+
|
|
49
|
+
Sprae creates reactive state that mirrors current DOM values.<br/>
|
|
50
|
+
It is based on [signals](https://github.com/preactjs/signals) and can take them as inputs.
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
const version = signal('alpha')
|
|
54
|
+
|
|
55
|
+
// Sprae container with initial state values
|
|
56
|
+
const state = sprae(container, { foo: 'bar', version })
|
|
57
|
+
|
|
58
|
+
// Modify state property 'foo', triggering a DOM update
|
|
59
|
+
state.foo = 'baz'
|
|
60
|
+
|
|
61
|
+
// Update the version signal, which also triggers a DOM refresh
|
|
62
|
+
version.value = 'beta'
|
|
63
|
+
|
|
64
|
+
// For batch update, re-sprae with new state values
|
|
65
|
+
sprae(container, { foo: 'qux', version: 'gamma' })
|
|
66
|
+
```
|
|
45
67
|
|
|
46
68
|
## Attributes
|
|
47
69
|
|
|
@@ -57,7 +79,7 @@ Control flow of elements.
|
|
|
57
79
|
|
|
58
80
|
#### `:each="item, index in items"`
|
|
59
81
|
|
|
60
|
-
Multiply element.
|
|
82
|
+
Multiply element.
|
|
61
83
|
|
|
62
84
|
```html
|
|
63
85
|
<ul><li :each="item in items" :text="item"></ul>
|
|
@@ -65,14 +87,11 @@ Multiply element. `index` value starts from 1.
|
|
|
65
87
|
<!-- Cases -->
|
|
66
88
|
<li :each="item, idx in list" />
|
|
67
89
|
<li :each="val, key in obj" />
|
|
68
|
-
<li :each="
|
|
90
|
+
<li :each="idx in number" />
|
|
69
91
|
|
|
70
92
|
<!-- Loop by condition -->
|
|
71
93
|
<li :if="items" :each="item in items" :text="item" />
|
|
72
94
|
<li :else>Empty list</li>
|
|
73
|
-
|
|
74
|
-
<!-- Key items to reuse elements -->
|
|
75
|
-
<li :each="item in items" :key="item.id" :text="item.value" />
|
|
76
95
|
```
|
|
77
96
|
|
|
78
97
|
#### `:text="value"`
|
|
@@ -94,8 +113,8 @@ Set class value from either a string, array or object.
|
|
|
94
113
|
<!-- extends existing class as "foo bar" -->
|
|
95
114
|
<div class="foo" :class="`bar`"></div>
|
|
96
115
|
|
|
97
|
-
<!-- object
|
|
98
|
-
<div :class="
|
|
116
|
+
<!-- clsx: object / list -->
|
|
117
|
+
<div :class="[foo && 'foo', {bar: bar}]"></div>
|
|
99
118
|
```
|
|
100
119
|
|
|
101
120
|
#### `:style="value"`
|
|
@@ -239,7 +258,10 @@ Expressions are sandboxed, ie. don't access global/window scope by default (sinc
|
|
|
239
258
|
<!-- scrollY is undefined -->
|
|
240
259
|
```
|
|
241
260
|
|
|
242
|
-
Default sandbox provides:
|
|
261
|
+
Default sandbox provides most popular global objects: _Array_, _Object_, _Number_, _String_, _Boolean_, _Date_,
|
|
262
|
+
_console_, _window_, _document_, _history_, _navigator_, _location_, _screen_, _localStorage_, _sessionStorage_,
|
|
263
|
+
_alert_, _prompt_, _confirm_, _fetch_, _performance_,
|
|
264
|
+
_setTimeout_, _setInterval_, _requestAnimationFrame_.
|
|
243
265
|
|
|
244
266
|
Sandbox can be extended as `Object.assign(sprae.globals, { BigInt })`.
|
|
245
267
|
|
|
@@ -252,10 +274,17 @@ To avoid _flash of unstyled content_, you can hide sprae attribute or add a cust
|
|
|
252
274
|
<style>[:each],[:hidden] {visibility: hidden}</style>
|
|
253
275
|
```
|
|
254
276
|
|
|
277
|
+
## Dispose
|
|
278
|
+
|
|
279
|
+
To destroy state and detach sprae handlers, call `element[Symbol.dispose]()`.
|
|
280
|
+
|
|
255
281
|
## Benchmark
|
|
256
282
|
|
|
257
283
|
Done via [js-framework-benchmark](https://github.com/krausest/js-framework-benchmark).
|
|
258
284
|
|
|
285
|
+
<details>
|
|
286
|
+
<summary>How to run</summary>
|
|
287
|
+
|
|
259
288
|
```sh
|
|
260
289
|
# prerequisite
|
|
261
290
|
npm ci
|
|
@@ -282,6 +311,7 @@ cd ..
|
|
|
282
311
|
cd webdriver-ts
|
|
283
312
|
npm run results
|
|
284
313
|
```
|
|
314
|
+
</details>
|
|
285
315
|
|
|
286
316
|
## Examples
|
|
287
317
|
|
|
@@ -289,14 +319,13 @@ npm run results
|
|
|
289
319
|
* Wavearea: [demo](https://dy.github.io/wavearea?src=//cdn.freesound.org/previews/586/586281_2332564-lq.mp3), [code](https://github.com/dy/wavearea)
|
|
290
320
|
* Prostogreen [demo](http://web-being.org/prostogreen/), [code](https://github.com/web-being/prostogreen/)
|
|
291
321
|
|
|
292
|
-
|
|
293
322
|
## Justification
|
|
294
323
|
|
|
295
324
|
* [Template-parts](https://github.com/dy/template-parts) / [templize](https://github.com/dy/templize) is progressive, but is stuck with native HTML quirks ([parsing table](https://github.com/github/template-parts/issues/24), [SVG attributes](https://github.com/github/template-parts/issues/25), [liquid syntax](https://shopify.github.io/liquid/tags/template/#raw) conflict etc). Also ergonomics of `attr="{{}}"` is inferior to `:attr=""` since it creates flash of uninitialized values. Also it's just nice to keep `{{}}` generic, regardless of markup, and attributes as part of markup.
|
|
296
325
|
* [Alpine](https://github.com/alpinejs/alpine) / [vue](https://github.com/vuejs/petite-vue) / [lit](https://github.com/lit/lit/tree/main/packages/lit-html) escape native HTML quirks, but the syntax space (`:attr`, `v-*`,`x-*`, `l-*` `@evt`, `{{}}`) is too broad, as well as functionality. Perfection is when there's nothing to take away, not add (c). Also they tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223) making interop hard, invent own tooling or complex reactivity.
|
|
297
|
-
* React/[preact](https://ghub.io/preact) does the job wiring up JS to HTML, but with an extreme of migrating HTML to JSX and enforcing SPA, which is not organic for HTML. Also it doesn't support reactive fields (needs render call).
|
|
326
|
+
* React / [preact](https://ghub.io/preact) does the job wiring up JS to HTML, but with an extreme of migrating HTML to JSX and enforcing SPA, which is not organic for HTML. Also it doesn't support reactive fields (needs render call).
|
|
298
327
|
|
|
299
|
-
_Sprae_ takes idea of
|
|
328
|
+
_Sprae_ takes idea of _templize_ / _alpine_ / _vue_ attributes and builds simple reactive state based on [_@preact/signals_](https://ghub.io/@preact/signals).
|
|
300
329
|
|
|
301
330
|
* It doesn't break or modify static html markup.
|
|
302
331
|
* It falls back to element content if uninitialized.
|