sprae 11.1.2 → 11.2.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/core.js +7 -5
- package/dist/sprae.js +6 -6
- package/dist/sprae.js.map +3 -3
- package/dist/sprae.min.js +2 -2
- package/dist/sprae.min.js.map +3 -3
- package/dist/sprae.umd.js +6 -6
- package/dist/sprae.umd.js.map +3 -3
- package/dist/sprae.umd.min.js +2 -2
- package/dist/sprae.umd.min.js.map +3 -3
- package/package.json +1 -1
- package/readme.md +49 -19
package/readme.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> DOM tree microhydration
|
|
4
4
|
|
|
5
5
|
_Sprae_ is open & minimalistic progressive enhancement framework with _preact-signals_ based reactivity.<br/>
|
|
6
|
-
Perfect for small-scale websites, static pages, landings, prototypes, or
|
|
6
|
+
Perfect for small-scale websites, static pages, landings, prototypes, lightweight UI or as [nextjs / SSR companion](#JSX).<br/>
|
|
7
7
|
A light and fast alternative to _alpine_, _petite-vue_ etc (see [why](#justification)).
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
@@ -32,17 +32,18 @@ Sprae evaluates `:`-directives and evaporates them, returning reactive state for
|
|
|
32
32
|
UMD version enables sprae via CDN, as CJS, AMD etc.
|
|
33
33
|
|
|
34
34
|
```html
|
|
35
|
-
<!-- `init`
|
|
35
|
+
<!-- `init` autoinits sprae on document with initial state (optional) -->
|
|
36
36
|
<script src="https://cdn.jsdelivr.net/npm/sprae/dist/sprae.umd.js" init="{ user: 'buddy' }"></script>
|
|
37
37
|
|
|
38
38
|
<script>
|
|
39
|
-
window.sprae
|
|
39
|
+
window.sprae; // global standalone
|
|
40
40
|
</script>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
44
43
|
## Directives
|
|
45
44
|
|
|
45
|
+
Directives can be either `:` or `s-` prefixed, which is identical.
|
|
46
|
+
|
|
46
47
|
#### `:if="condition"`, `:else`
|
|
47
48
|
|
|
48
49
|
Control flow of elements.
|
|
@@ -61,8 +62,7 @@ Control flow of elements.
|
|
|
61
62
|
Multiply element.
|
|
62
63
|
|
|
63
64
|
```html
|
|
64
|
-
|
|
65
|
-
<ul><li :each="item in items" :text="item"/></ul>
|
|
65
|
+
<ul><li :each="item in items" :text="item" /></ul>
|
|
66
66
|
|
|
67
67
|
<!-- cases -->
|
|
68
68
|
<li :each="item, idx in array" />
|
|
@@ -84,7 +84,7 @@ Set text content of an element.
|
|
|
84
84
|
Welcome, <span :text="user.name">Guest</span>.
|
|
85
85
|
|
|
86
86
|
<!-- fragment -->
|
|
87
|
-
Welcome, <template :text="user.name"
|
|
87
|
+
Welcome, <template :text="user.name"><template>.
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
#### `:class="value"`
|
|
@@ -92,11 +92,13 @@ Welcome, <template :text="user.name" />.
|
|
|
92
92
|
Set class value.
|
|
93
93
|
|
|
94
94
|
```html
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
<div :class="foo"></div>
|
|
96
|
+
|
|
97
|
+
<!-- appends to static class -->
|
|
98
|
+
<div class="bar" :class="baz"></div>
|
|
97
99
|
|
|
98
100
|
<!-- array/object, a-la clsx -->
|
|
99
|
-
<div :class="[foo && '
|
|
101
|
+
<div :class="['foo', bar && 'bar', { baz }]"></div>
|
|
100
102
|
```
|
|
101
103
|
|
|
102
104
|
#### `:style="value"`
|
|
@@ -104,13 +106,15 @@ Set class value.
|
|
|
104
106
|
Set style value.
|
|
105
107
|
|
|
106
108
|
```html
|
|
107
|
-
|
|
109
|
+
<span style="'display: inline-block'"></span>
|
|
110
|
+
|
|
111
|
+
<!-- extends static style -->
|
|
108
112
|
<div style="foo: bar" :style="'bar-baz: qux'">
|
|
109
113
|
|
|
110
114
|
<!-- object -->
|
|
111
115
|
<div :style="{barBaz: 'qux'}"></div>
|
|
112
116
|
|
|
113
|
-
<!-- CSS variable -->
|
|
117
|
+
<!-- set CSS variable -->
|
|
114
118
|
<div :style="{'--bar-baz': qux}"></div>
|
|
115
119
|
```
|
|
116
120
|
|
|
@@ -194,7 +198,7 @@ Attach event(s) listener with optional modifiers.
|
|
|
194
198
|
<input :value="text" :oninput:onchange="e => text = e.target.value">
|
|
195
199
|
|
|
196
200
|
<!-- sequence of events -->
|
|
197
|
-
<button :onfocus..onblur="e => (
|
|
201
|
+
<button :onfocus..onblur="e => (handleFocus(), e => handleBlur())">
|
|
198
202
|
|
|
199
203
|
<!-- modifiers -->
|
|
200
204
|
<button :onclick.throttle-500="handler">Not too often</button>
|
|
@@ -309,9 +313,10 @@ sprae.use({compile: justin}) // set up justin as default compiler
|
|
|
309
313
|
|
|
310
314
|
###### Operators:
|
|
311
315
|
|
|
312
|
-
`++ -- ! - +
|
|
316
|
+
`++ -- ! - + * / % ** && || ??`<br/>
|
|
313
317
|
`= < <= > >= == != === !==`<br/>
|
|
314
|
-
`<< >> & ^ | ~ ?: . ?. [] ()=>{} in
|
|
318
|
+
`<< >> >>> & ^ | ~ ?: . ?. [] ()=>{} in`<br/>
|
|
319
|
+
`= += -= *= /= %= **= &&= ||= ??= ... ,`
|
|
315
320
|
|
|
316
321
|
###### Primitives:
|
|
317
322
|
|
|
@@ -352,7 +357,7 @@ sprae.use({ compile })
|
|
|
352
357
|
|
|
353
358
|
* To prevent [FOUC](https://en.wikipedia.org/wiki/Flash_of_unstyled_content) add `<style>[:each],[:if],[:else] {visibility: hidden}</style>`.
|
|
354
359
|
* Attributes order matters, eg. `<li :each="el in els" :text="el.name"></li>` is not the same as `<li :text="el.name" :each="el in els"></li>`.
|
|
355
|
-
* Invalid self-closing tags like `<a :text="item" />` will cause error. Valid self-closing tags are: `li`, `p`, `dt`, `dd`, `option`, `tr`, `td`, `th`.
|
|
360
|
+
* Invalid self-closing tags like `<a :text="item" />` will cause error. Valid self-closing tags are: `li`, `p`, `dt`, `dd`, `option`, `tr`, `td`, `th`, `input`, `img`, `br`.
|
|
356
361
|
* Properties prefixed with `_` are untracked: `let state = sprae(el, {_x:2}); state._x++; // no effect`.
|
|
357
362
|
* To destroy state and detach sprae handlers, call `element[Symbol.dispose]()`.
|
|
358
363
|
* State getters/setters work as computed effects, eg. `sprae(el, { x:1, get x2(){ return this.x * 2} })`.
|
|
@@ -360,22 +365,27 @@ sprae.use({ compile })
|
|
|
360
365
|
* `event` is not used, `:on*` attributes expect a function with event argument `:onevt="event => handle()"`, see [#46](https://github.com/dy/sprae/issues/46).
|
|
361
366
|
* `key` is not used, `:each` uses direct list mapping instead of DOM diffing.
|
|
362
367
|
* `await` is not supported in attributes, it’s a strong indicator you need to put these methods into state.
|
|
368
|
+
* `:ref` comes after `:if` for mount/unmount events `<div :if="cond" :ref="(init(), ()=>dispose())"></div>`.
|
|
369
|
+
* Directives be `s-` prefixed instead of `:` for JSX.
|
|
363
370
|
|
|
364
371
|
## Justification
|
|
365
372
|
|
|
366
|
-
Modern frontend stack is obese and unhealthy, like non-organic processed food. There are
|
|
373
|
+
Modern frontend stack is obese and unhealthy, like non-organic processed food. There are healthy alternatives, but:
|
|
367
374
|
|
|
368
375
|
* [Template-parts](https://github.com/dy/template-parts) 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).
|
|
369
376
|
* [Alpine](https://github.com/alpinejs/alpine) / [petite-vue](https://github.com/vuejs/petite-vue) / [lucia](https://github.com/aidenyabi/lucia) escape native HTML quirks, but have excessive API (`:`, `x-`, `{}`, `@`, `$`), tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223) and not care about size/performance.
|
|
370
377
|
|
|
371
378
|
_Sprae_ holds open & minimalistic philosophy:
|
|
372
379
|
|
|
373
|
-
*
|
|
374
|
-
*
|
|
380
|
+
* Minimal syntax `:`.
|
|
381
|
+
* _Signals_ for reactivity.
|
|
382
|
+
* Pluggable directives, configurable internals.
|
|
375
383
|
* Small, safe & performant.
|
|
376
384
|
* Bits of organic sugar.
|
|
377
385
|
* Aims at making developers happy 🫰
|
|
378
386
|
|
|
387
|
+
> Perfection is not when there is nothing to add, but when there is nothing to take away.
|
|
388
|
+
|
|
379
389
|
<!--
|
|
380
390
|
| | [AlpineJS](https://github.com/alpinejs/alpine) | [Petite-Vue](https://github.com/vuejs/petite-vue) | Sprae |
|
|
381
391
|
|-----------------------|-------------------|-------------------|------------------|
|
|
@@ -445,6 +455,26 @@ npm run results
|
|
|
445
455
|
* [nuejs](https://github.com/nuejs/nuejs)
|
|
446
456
|
-->
|
|
447
457
|
|
|
458
|
+
## JSX
|
|
459
|
+
|
|
460
|
+
Sprae works with JSX, eg. Next.js companion for SSR via `s-` prefixed attributes.
|
|
461
|
+
|
|
462
|
+
Next.js server components fall short for dynamic UI, like active nav items, collapsible sections, tabs etc. That forces into client components, which screws up data fetching, bloats hydration and adds overhead.`<Script>` is heavy and clunky hack.
|
|
463
|
+
|
|
464
|
+
Sprae can offload UI logic to keep server components intact.
|
|
465
|
+
|
|
466
|
+
```jsx
|
|
467
|
+
// app/page.jsx
|
|
468
|
+
export default function Page() {
|
|
469
|
+
return <>
|
|
470
|
+
<nav id="nav">
|
|
471
|
+
<a href="/" s-class="location.path === '/' && 'active'">Home</a>
|
|
472
|
+
<a href="/about" s-class="location.path === '/about' && 'active'">About</a>
|
|
473
|
+
</nav>
|
|
474
|
+
<script src="https://unpkg.com/sprae" init></script>
|
|
475
|
+
</>
|
|
476
|
+
}
|
|
477
|
+
```
|
|
448
478
|
|
|
449
479
|
## Examples
|
|
450
480
|
|