sprae 2.7.1 → 2.8.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 +2 -2
- package/r&d.md +68 -14
- package/readme.md +19 -4
- package/sprae.js +185 -61
- package/sprae.min.js +1 -1
- package/src/directives.js +120 -43
- package/test/test.js +66 -3
- package/todo.md +4 -1
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sprae",
|
|
3
3
|
"description": "DOM microhydration.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.8.1",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"module": "src/index.js",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@preact/signals-core": "^1.2.2",
|
|
10
10
|
"primitive-pool": "^2.0.0",
|
|
11
|
-
"signal-struct": "^1.
|
|
11
|
+
"signal-struct": "^1.10.0",
|
|
12
12
|
"swapdom": "^1.1.1"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
package/r&d.md
CHANGED
|
@@ -289,9 +289,9 @@
|
|
|
289
289
|
* @sprae/item: `<x :item="{type:a, scope:b}"` – provide microdata
|
|
290
290
|
- can be solved naturally, unless there's special meaning
|
|
291
291
|
* @sprae/hcodes: `<x :hcode=""` – provide microformats
|
|
292
|
-
* @sprae/with
|
|
293
|
-
* @sprae/onconnected
|
|
294
292
|
* @sprae/onvisible?
|
|
293
|
+
- can be solved externally
|
|
294
|
+
* @sprae/onintersects
|
|
295
295
|
|
|
296
296
|
## [x] Write any-attributes via `:<prop>? -> yep`
|
|
297
297
|
|
|
@@ -330,7 +330,7 @@
|
|
|
330
330
|
+ Provides precisely controlled sandbox
|
|
331
331
|
- Some limited lang opportunities
|
|
332
332
|
- need to match many syntax quirks, can be tedious
|
|
333
|
-
~ can be fine to limit expressions to meaningful default:
|
|
333
|
+
~ can be fine to limit expressions to meaningful default: no Proxy, generators, awaits, global access etc.
|
|
334
334
|
- Somewhat heavy to bundle
|
|
335
335
|
~ 1-2kb is not super-heavy, besides kicks out signal-struct (with preact signals?)
|
|
336
336
|
+ Scope is easier to provide: no need for signal proxy
|
|
@@ -340,6 +340,7 @@
|
|
|
340
340
|
+ Deps can be analyzed / implemented without signals
|
|
341
341
|
- Screwed up debugging / stacktrace (unless errored properly)
|
|
342
342
|
~+ can actually provide better trace since no internal framework stuff is shown
|
|
343
|
+
+ can let means to enhance subscript's logs
|
|
343
344
|
+ that "unlimits" returned struct, so that any property can be added/deleted.
|
|
344
345
|
- doesn't really save from `new (()=>{}).constructor` hack: we gotta substitute objects too.
|
|
345
346
|
+ allows easier handle of `:with="a=1,b=2,c=3"` - we just naturally get local variables without messup with global
|
|
@@ -347,11 +348,18 @@
|
|
|
347
348
|
- not having "comfy" compatible JS at hand: cognitive load of whole language "layer" in-between
|
|
348
349
|
+ allows `let a = 1; a;` case instead of `let a = 1; return a;`
|
|
349
350
|
|
|
351
|
+
-> We can benchmark if updating set of known dependencies is faster than using preact subscriptions.
|
|
352
|
+
+ it seems more logical min-ground to know in advance what we depend on, rather than detect by-call as signals do.
|
|
353
|
+
+ it's safer not to depend on external tech, considering there's so much competition and changes in reactive land
|
|
354
|
+
~ it indeed takes some reactive-struct, capable of notifying which paths have been changed
|
|
355
|
+
? maybe define setters such that when they're set
|
|
356
|
+
|
|
350
357
|
2. Use sandboxed proxy
|
|
351
358
|
- tough evaluation
|
|
352
|
-
-
|
|
359
|
+
- implementation hiccups
|
|
353
360
|
- screwed up data
|
|
354
361
|
- no full protection
|
|
362
|
+
- relatively slow
|
|
355
363
|
+ does minimal catch
|
|
356
364
|
|
|
357
365
|
## [x] :onclick="direct code" ? -> no: immediately invoked.
|
|
@@ -374,19 +382,23 @@
|
|
|
374
382
|
? maybe id should have same signature
|
|
375
383
|
? should it be very similar mechanism to `:with="a=1,b=2"`
|
|
376
384
|
|
|
377
|
-
## [
|
|
385
|
+
## [x] Event modifiers :ona.once, `:ona` -> let's try, there's a lot of use for both props and event
|
|
378
386
|
|
|
379
387
|
- .prevent,.stop - not needed since expects a function
|
|
380
388
|
? or should we just trigger it for user?
|
|
381
389
|
? :onclick.outside
|
|
382
390
|
? :onclick.window, :onclick.document
|
|
383
|
-
|
|
384
|
-
? :onclick.
|
|
385
|
-
|
|
391
|
+
+ can be needed, eg. mousedown..up can happen outside of current element (stop caret tracking in waveplay)
|
|
392
|
+
? :onclick.once, :onclick.passive, :onclick.capture
|
|
393
|
+
+ can pass props to event listener: there's no other way to do that
|
|
394
|
+
? :onclick.debounce-330
|
|
395
|
+
? :onclick.throttle-750
|
|
396
|
+
+ ...just handy everydayers and saves tons of noise
|
|
386
397
|
? :onclick.self
|
|
398
|
+
~ clicked on self, not the child
|
|
387
399
|
? :onspecial-event.camel, :onx-y.dot
|
|
388
|
-
|
|
389
|
-
? :onkeypress.shift.enter
|
|
400
|
+
~
|
|
401
|
+
? :onkeypress.shift.enter, :onmousemove.shift, :onmousemove.alt
|
|
390
402
|
.shift Shift
|
|
391
403
|
.enter Enter
|
|
392
404
|
.space Space
|
|
@@ -394,15 +406,57 @@
|
|
|
394
406
|
.cmd Cmd
|
|
395
407
|
.meta Cmd on Mac, Windows key on Windows
|
|
396
408
|
.alt Alt
|
|
397
|
-
.up .down .left .right
|
|
409
|
+
.up .down .left .right
|
|
398
410
|
.escape Escape
|
|
399
411
|
.tab Tab
|
|
400
412
|
.caps-lock Caps Lock
|
|
401
|
-
.equal Equal
|
|
402
|
-
.period Period
|
|
403
|
-
.slash Foward Slash
|
|
413
|
+
.equal Equal
|
|
414
|
+
.period Period
|
|
415
|
+
.slash Foward Slash
|
|
416
|
+
+ allows separating various key handlers: atm waveplay handles separate keys in the same method `handleKey`
|
|
417
|
+
+ allows tracking mouse interactions with shift hold
|
|
404
418
|
- conflict with dot-separated events
|
|
419
|
+
~not so popular nor encouraged
|
|
405
420
|
- lots of ad-hoc non-standard rules, can be handled in code
|
|
421
|
+
+ allow multiple setters for same props or multiple listeners for same events
|
|
422
|
+
+ oldschool jquery-compatible events
|
|
423
|
+
|
|
424
|
+
## [x] Mods design -> use event modifiers, not props modifiers
|
|
425
|
+
|
|
426
|
+
* [ ] ~~Prop modifiers~~
|
|
427
|
+
- overall seems code complication without much benefit
|
|
428
|
+
* [ ] value.bind? value.watch?
|
|
429
|
+
- let's wait for use-case: value can be too big to set it every time
|
|
430
|
+
* [ ] prop.reflect, prop.observe
|
|
431
|
+
- let's wait for use-case
|
|
432
|
+
* [ ] prop.boolean, .number, .string, .array, .object
|
|
433
|
+
- let's wait for use-case
|
|
434
|
+
* [ ] prop.once, prop.fx ? prop.init?
|
|
435
|
+
- doesn't seem required, let's wait for use case
|
|
436
|
+
* [ ] prop.change - run only if value changes
|
|
437
|
+
- seems like unnecessary manual optimization that must be done always automatically
|
|
438
|
+
? are there cases where force-update is necessary?
|
|
439
|
+
* [ ] prop.throttle-xxx, prop.debounce-xxx
|
|
440
|
+
- let's wait until that's really a problem
|
|
441
|
+
* [ ] prop.class
|
|
442
|
+
? what's the use-case
|
|
443
|
+
|
|
444
|
+
* [x] Event modifiers
|
|
445
|
+
* [x] onevt.x, onevt.y
|
|
446
|
+
+ jquery-like
|
|
447
|
+
+ multiple same events
|
|
448
|
+
* [x] onevt.once, onevt.passive, onevt.capture
|
|
449
|
+
+ standard props passing
|
|
450
|
+
* [x] onevt.prevent, onevt.stop
|
|
451
|
+
+ conventional mods
|
|
452
|
+
* [x] onevt.outside onevt.window, onevt.document, onevt.self
|
|
453
|
+
+ useful handlers, conventional mods
|
|
454
|
+
* [x] onevt.throttle-xxx, onevt.debounce-xxx
|
|
455
|
+
+ conventional
|
|
456
|
+
* [x] onevt.shift, onevt.cmd.shift, onevt.meta
|
|
457
|
+
+ conventional
|
|
458
|
+
* [x] onkey.enter, .space, .up|.down|.left|.right, .escape, .tab, .period, .slash, .caps-lock
|
|
459
|
+
+ conventional
|
|
406
460
|
|
|
407
461
|
## [x] Writing props on elements (like ones in :each) -> nah, just use `:x="this.x=abc"`
|
|
408
462
|
|
package/readme.md
CHANGED
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
> DOM microhydration with `:` attributes
|
|
4
4
|
|
|
5
|
-
A lightweight essential alternative to [alpine](https://github.com/alpinejs/alpine), [petite-vue](https://github.com/vuejs/petite-vue), [templize](https://github.com/dy/templize) or JSX with better ergonomics[*](#justification).<br>
|
|
6
|
-
It is reminiscent of [XSLT](https://www.w3schools.com/xml/xsl_intro.asp), considered a [buried treasure](https://github.com/bahrus/be-restated) by web-connoisseurs.
|
|
7
|
-
|
|
8
5
|
|
|
9
6
|
## Usage
|
|
10
7
|
|
|
@@ -163,10 +160,22 @@ Add event listeners.
|
|
|
163
160
|
}
|
|
164
161
|
}">
|
|
165
162
|
|
|
163
|
+
<!-- Event modifiers -->
|
|
164
|
+
<button :onclick.throttle-500="handler">Not too often</button>
|
|
165
|
+
|
|
166
166
|
<!-- Bulk/custom events -->
|
|
167
167
|
<button :on="{ click: handler, touch: handler, special: handler }">Submit</button>
|
|
168
168
|
```
|
|
169
169
|
|
|
170
|
+
##### Event modifiers
|
|
171
|
+
|
|
172
|
+
* `.once`, `.passive`, `.capture` – listener [options](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options).
|
|
173
|
+
* `.prevent`, `.stop` – prevent default or stop propagation.
|
|
174
|
+
* `.window`, `.document`, `.outside`, `.self` – specify event target.
|
|
175
|
+
* `.throttle-108`, `.debounce-108` – define throttling or postponing callback with (optional) timeout in ms.
|
|
176
|
+
* `.ctrl`, `.shift`, `.alt`, `.meta`, `.cmd`, `.down`, `.up`, `.left`, `.right`, `.end`, `.home`, `.pagedown`, `.pageup`, `.enter`, `.plus`, `.minus`, `.star`, `.slash`, `.period`, `.equal`, `.underscore`, `.esc`, `.escape`, `.tab`, `.space`, `.backspace`, `.delete` – filter by [`event.key`](https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values).
|
|
177
|
+
* `.*` – any other modifier has no effect, but allows binding multiple handlers to same event (like jQuery event classes).
|
|
178
|
+
|
|
170
179
|
#### `:data="values"`
|
|
171
180
|
|
|
172
181
|
Set [data-*](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-*) attributes. CamelCase is converted to dash-case.
|
|
@@ -334,11 +343,13 @@ This way, for example, _@preact/signals_ or _rxjs_ can be connected directly byp
|
|
|
334
343
|
|
|
335
344
|
## Justification
|
|
336
345
|
|
|
346
|
+
_Sprae_ is lightweight essential alternative to [alpine](https://github.com/alpinejs/alpine), [petite-vue](https://github.com/vuejs/petite-vue), [templize](https://github.com/dy/templize) or JSX with better ergonomics[*](#justification).
|
|
347
|
+
|
|
337
348
|
* [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.
|
|
338
349
|
* [Alpine](https://github.com/alpinejs/alpine) / [vue](https://github.com/vuejs/petite-vue) / [lit](https://github.com/lit/lit/tree/main/packages/lit-html) escapes native HTML quirks, but the syntax is a bit scattered: `:attr`, `v-*`,`x-*`, `@evt`, `{{}}` can be expressed with single convention. Besides, functionality is too broad and can be reduced to essence: perfection is when there's nothing to take away, not add. Also they tend to [self-encapsulate](https://github.com/alpinejs/alpine/discussions/3223), making interop hard.
|
|
339
350
|
* 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).
|
|
340
351
|
|
|
341
|
-
|
|
352
|
+
_Sprae_ takes convention of _templize directives_ (_alpine_/_vue_ attrs) and builds upon [_@preact/signals_](https://ghub.io/@preact/signals).
|
|
342
353
|
|
|
343
354
|
* It doesn't break static html markup.
|
|
344
355
|
* It falls back to element content if uninitialized.
|
|
@@ -349,4 +360,8 @@ _sprae_ takes convention of _templize directives_ (_alpine_/_vue_ attrs) and bui
|
|
|
349
360
|
* Input data may contain [signals](https://ghub.io/@preact/signals) or [reactive values](https://ghub.io/sube).
|
|
350
361
|
* Elements / data API is open and enable easy interop.
|
|
351
362
|
|
|
363
|
+
|
|
364
|
+
It is reminiscent of [XSLT](https://www.w3schools.com/xml/xsl_intro.asp), considered a [buried treasure](https://github.com/bahrus/be-restated) by web-connoisseurs.
|
|
365
|
+
|
|
366
|
+
|
|
352
367
|
<p align="center"><a href="https://github.com/krsnzd/license/">🕉</a></p>
|
package/sprae.js
CHANGED
|
@@ -71,16 +71,16 @@ function v(i2) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
function
|
|
74
|
+
function e2(i2) {
|
|
75
75
|
this.v = i2;
|
|
76
76
|
this.i = 0;
|
|
77
77
|
this.n = void 0;
|
|
78
78
|
this.t = void 0;
|
|
79
79
|
}
|
|
80
|
-
|
|
80
|
+
e2.prototype.h = function() {
|
|
81
81
|
return true;
|
|
82
82
|
};
|
|
83
|
-
|
|
83
|
+
e2.prototype.S = function(i2) {
|
|
84
84
|
if (this.t !== i2 && void 0 === i2.e) {
|
|
85
85
|
i2.x = this.t;
|
|
86
86
|
if (void 0 !== this.t)
|
|
@@ -88,7 +88,7 @@ e.prototype.S = function(i2) {
|
|
|
88
88
|
this.t = i2;
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
|
-
|
|
91
|
+
e2.prototype.U = function(i2) {
|
|
92
92
|
var t2 = i2.e, h2 = i2.x;
|
|
93
93
|
if (void 0 !== t2) {
|
|
94
94
|
t2.x = h2;
|
|
@@ -101,7 +101,7 @@ e.prototype.U = function(i2) {
|
|
|
101
101
|
if (i2 === this.t)
|
|
102
102
|
this.t = h2;
|
|
103
103
|
};
|
|
104
|
-
|
|
104
|
+
e2.prototype.subscribe = function(i2) {
|
|
105
105
|
var t2 = this;
|
|
106
106
|
return b(function() {
|
|
107
107
|
var h2 = t2.value, o2 = 32 & this.f;
|
|
@@ -113,16 +113,16 @@ e.prototype.subscribe = function(i2) {
|
|
|
113
113
|
}
|
|
114
114
|
});
|
|
115
115
|
};
|
|
116
|
-
|
|
116
|
+
e2.prototype.valueOf = function() {
|
|
117
117
|
return this.value;
|
|
118
118
|
};
|
|
119
|
-
|
|
119
|
+
e2.prototype.toString = function() {
|
|
120
120
|
return this.value + "";
|
|
121
121
|
};
|
|
122
|
-
|
|
122
|
+
e2.prototype.peek = function() {
|
|
123
123
|
return this.v;
|
|
124
124
|
};
|
|
125
|
-
Object.defineProperty(
|
|
125
|
+
Object.defineProperty(e2.prototype, "value", { get: function() {
|
|
126
126
|
var i2 = v(this);
|
|
127
127
|
if (void 0 !== i2)
|
|
128
128
|
i2.i = this.i;
|
|
@@ -144,7 +144,7 @@ Object.defineProperty(e.prototype, "value", { get: function() {
|
|
|
144
144
|
}
|
|
145
145
|
} });
|
|
146
146
|
function u(i2) {
|
|
147
|
-
return new
|
|
147
|
+
return new e2(i2);
|
|
148
148
|
}
|
|
149
149
|
function d(i2) {
|
|
150
150
|
for (var t2 = i2.s; void 0 !== t2; t2 = t2.n)
|
|
@@ -183,13 +183,13 @@ function a(i2) {
|
|
|
183
183
|
i2.s = h2;
|
|
184
184
|
}
|
|
185
185
|
function l(i2) {
|
|
186
|
-
|
|
186
|
+
e2.call(this, void 0);
|
|
187
187
|
this.x = i2;
|
|
188
188
|
this.s = void 0;
|
|
189
189
|
this.g = f - 1;
|
|
190
190
|
this.f = 4;
|
|
191
191
|
}
|
|
192
|
-
(l.prototype = new
|
|
192
|
+
(l.prototype = new e2()).h = function() {
|
|
193
193
|
this.f &= -3;
|
|
194
194
|
if (1 & this.f)
|
|
195
195
|
return false;
|
|
@@ -230,10 +230,10 @@ l.prototype.S = function(i2) {
|
|
|
230
230
|
for (var t2 = this.s; void 0 !== t2; t2 = t2.n)
|
|
231
231
|
t2.S.S(t2);
|
|
232
232
|
}
|
|
233
|
-
|
|
233
|
+
e2.prototype.S.call(this, i2);
|
|
234
234
|
};
|
|
235
235
|
l.prototype.U = function(i2) {
|
|
236
|
-
|
|
236
|
+
e2.prototype.U.call(this, i2);
|
|
237
237
|
if (void 0 === this.t) {
|
|
238
238
|
this.f &= -33;
|
|
239
239
|
for (var t2 = this.s; void 0 !== t2; t2 = t2.n)
|
|
@@ -408,7 +408,7 @@ function signalStruct(values, proto) {
|
|
|
408
408
|
try {
|
|
409
409
|
Object.assign(s2.value, v2);
|
|
410
410
|
return;
|
|
411
|
-
} catch (
|
|
411
|
+
} catch (e3) {
|
|
412
412
|
}
|
|
413
413
|
s2.value = Object.seal(signalStruct(v2));
|
|
414
414
|
} else if (Array.isArray(v2))
|
|
@@ -425,7 +425,8 @@ function signalStruct(values, proto) {
|
|
|
425
425
|
return state;
|
|
426
426
|
}
|
|
427
427
|
if (Array.isArray(values) && !isStruct(values[0])) {
|
|
428
|
-
|
|
428
|
+
for (let i2 = 0; i2 < values.length; i2++)
|
|
429
|
+
values[i2] = signalStruct(values[i2]);
|
|
429
430
|
}
|
|
430
431
|
return values;
|
|
431
432
|
}
|
|
@@ -623,6 +624,31 @@ secondary["text"] = (el, expr) => {
|
|
|
623
624
|
el.textContent = value == null ? "" : value;
|
|
624
625
|
};
|
|
625
626
|
};
|
|
627
|
+
secondary["data"] = (el, expr) => {
|
|
628
|
+
let evaluate = parseExpr(el, expr, ":data");
|
|
629
|
+
return (state) => {
|
|
630
|
+
let value = evaluate(state);
|
|
631
|
+
for (let key in value)
|
|
632
|
+
el.dataset[key] = value[key];
|
|
633
|
+
};
|
|
634
|
+
};
|
|
635
|
+
secondary["aria"] = (el, expr) => {
|
|
636
|
+
let evaluate = parseExpr(el, expr, ":aria");
|
|
637
|
+
const update = (value) => {
|
|
638
|
+
for (let key in value)
|
|
639
|
+
attr(el, "aria-" + dashcase(key), value[key] == null ? null : value[key] + "");
|
|
640
|
+
};
|
|
641
|
+
return (state) => update(evaluate(state));
|
|
642
|
+
};
|
|
643
|
+
secondary[""] = (el, expr) => {
|
|
644
|
+
let evaluate = parseExpr(el, expr, ":");
|
|
645
|
+
if (evaluate)
|
|
646
|
+
return (state) => {
|
|
647
|
+
let value = evaluate(state);
|
|
648
|
+
for (let key in value)
|
|
649
|
+
attr(el, dashcase(key), value[key]);
|
|
650
|
+
};
|
|
651
|
+
};
|
|
626
652
|
secondary["value"] = (el, expr) => {
|
|
627
653
|
let evaluate = parseExpr(el, expr, ":value");
|
|
628
654
|
let from, to;
|
|
@@ -646,16 +672,38 @@ secondary["on"] = (el, expr) => {
|
|
|
646
672
|
};
|
|
647
673
|
};
|
|
648
674
|
};
|
|
675
|
+
var directives_default = (el, expr, state, name) => {
|
|
676
|
+
let evt = name.startsWith("on") && name.slice(2);
|
|
677
|
+
let evaluate = parseExpr(el, expr, ":" + name);
|
|
678
|
+
if (!evaluate)
|
|
679
|
+
return;
|
|
680
|
+
if (evt)
|
|
681
|
+
return (state2) => {
|
|
682
|
+
let value = evaluate(state2);
|
|
683
|
+
if (value) {
|
|
684
|
+
addListener(el, evt, value);
|
|
685
|
+
return () => removeListener(el, evt, value);
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
return (state2) => attr(el, name, evaluate(state2));
|
|
689
|
+
};
|
|
649
690
|
var _stop = Symbol("stop");
|
|
650
691
|
var addListener = (el, evt, startFn) => {
|
|
651
|
-
|
|
652
|
-
|
|
692
|
+
let evts = evt.split("..").map((e3) => e3.startsWith("on") ? e3.slice(2) : e3), opts = {};
|
|
693
|
+
evts[0] = evts[0].replace(
|
|
694
|
+
/\.(\w+)?-?([\w]+)?/g,
|
|
695
|
+
(match, mod, param) => {
|
|
696
|
+
(mod = mods[mod]) ? ([el, startFn] = mod(el, startFn, opts, param), "") : "";
|
|
697
|
+
return "";
|
|
698
|
+
}
|
|
699
|
+
);
|
|
700
|
+
if (evts.length == 1)
|
|
701
|
+
el.addEventListener(evts[0], startFn, opts);
|
|
653
702
|
else {
|
|
654
|
-
const evts = evt.split("..").map((e2) => e2.startsWith("on") ? e2.slice(2) : e2);
|
|
655
703
|
const nextEvt = (fn, cur = 0) => {
|
|
656
|
-
let curListener = (
|
|
704
|
+
let curListener = (e3) => {
|
|
657
705
|
el.removeEventListener(evts[cur], curListener);
|
|
658
|
-
if (typeof (fn = fn.call(el,
|
|
706
|
+
if (typeof (fn = fn.call(el, e3)) !== "function")
|
|
659
707
|
fn = () => {
|
|
660
708
|
};
|
|
661
709
|
if (++cur < evts.length)
|
|
@@ -663,7 +711,7 @@ var addListener = (el, evt, startFn) => {
|
|
|
663
711
|
else if (!startFn[_stop])
|
|
664
712
|
nextEvt(startFn);
|
|
665
713
|
};
|
|
666
|
-
el.addEventListener(evts[cur], curListener);
|
|
714
|
+
el.addEventListener(evts[cur], curListener, opts);
|
|
667
715
|
};
|
|
668
716
|
nextEvt(startFn);
|
|
669
717
|
}
|
|
@@ -673,43 +721,119 @@ var removeListener = (el, evt, fn) => {
|
|
|
673
721
|
fn[_stop] = true;
|
|
674
722
|
el.removeEventListener(evt, fn);
|
|
675
723
|
};
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
let
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
const update = (value) => {
|
|
687
|
-
for (let key in value)
|
|
688
|
-
attr(el, "aria-" + dashcase(key), value[key] == null ? null : value[key] + "");
|
|
689
|
-
};
|
|
690
|
-
return (state) => update(evaluate(state));
|
|
691
|
-
};
|
|
692
|
-
secondary[""] = (el, expr) => {
|
|
693
|
-
let evaluate = parseExpr(el, expr, ":");
|
|
694
|
-
if (evaluate)
|
|
695
|
-
return (state) => {
|
|
696
|
-
let value = evaluate(state);
|
|
697
|
-
for (let key in value)
|
|
698
|
-
attr(el, dashcase(key), value[key]);
|
|
724
|
+
var mods = {
|
|
725
|
+
throttle(el, cb, opts, limit) {
|
|
726
|
+
limit = Number(limit) || 108;
|
|
727
|
+
let pause, planned, block = () => {
|
|
728
|
+
pause = true;
|
|
729
|
+
setTimeout(() => {
|
|
730
|
+
pause = false;
|
|
731
|
+
if (planned)
|
|
732
|
+
cb(e), planned = false, block();
|
|
733
|
+
});
|
|
699
734
|
};
|
|
735
|
+
return [el, (e3) => {
|
|
736
|
+
if (pause)
|
|
737
|
+
return planned = true, _stop;
|
|
738
|
+
cb(e3);
|
|
739
|
+
block();
|
|
740
|
+
}];
|
|
741
|
+
},
|
|
742
|
+
debounce(el, cb, opts, wait) {
|
|
743
|
+
wait = Number(wait) || 108;
|
|
744
|
+
let timeout, later = () => {
|
|
745
|
+
timeout = null;
|
|
746
|
+
cb(e);
|
|
747
|
+
};
|
|
748
|
+
return [el, (e3) => {
|
|
749
|
+
clearTimeout(timeout);
|
|
750
|
+
timeout = setTimeout(later, wait);
|
|
751
|
+
}];
|
|
752
|
+
},
|
|
753
|
+
window(el, cb) {
|
|
754
|
+
return [window, cb];
|
|
755
|
+
},
|
|
756
|
+
document(el, cb) {
|
|
757
|
+
return [document, cb];
|
|
758
|
+
},
|
|
759
|
+
outside(el, cb) {
|
|
760
|
+
return [el, (e3) => {
|
|
761
|
+
if (el.contains(e3.target))
|
|
762
|
+
return _stop;
|
|
763
|
+
if (e3.target.isConnected === false)
|
|
764
|
+
return _stop;
|
|
765
|
+
if (el.offsetWidth < 1 && el.offsetHeight < 1)
|
|
766
|
+
return _stop;
|
|
767
|
+
cb(e3);
|
|
768
|
+
}];
|
|
769
|
+
},
|
|
770
|
+
prevent(el, cb) {
|
|
771
|
+
return [el, (e3) => {
|
|
772
|
+
if (cb(e3) !== _stop)
|
|
773
|
+
e3.preventDefault();
|
|
774
|
+
}];
|
|
775
|
+
},
|
|
776
|
+
stop(el, cb) {
|
|
777
|
+
return [el, (e3) => {
|
|
778
|
+
if (cb(e3) !== _stop)
|
|
779
|
+
e3.stopPropagation();
|
|
780
|
+
}];
|
|
781
|
+
},
|
|
782
|
+
self(el, cb) {
|
|
783
|
+
return [el, (e3) => {
|
|
784
|
+
e3.target === el && cb(e3);
|
|
785
|
+
}];
|
|
786
|
+
},
|
|
787
|
+
once(el, cb, opts) {
|
|
788
|
+
opts.once = true;
|
|
789
|
+
return [el, cb];
|
|
790
|
+
},
|
|
791
|
+
passive(el, cb, opts) {
|
|
792
|
+
opts.passive = true;
|
|
793
|
+
return [el, cb];
|
|
794
|
+
},
|
|
795
|
+
capture(el, cb, opts) {
|
|
796
|
+
opts.capture = true;
|
|
797
|
+
return [el, cb];
|
|
798
|
+
}
|
|
700
799
|
};
|
|
701
|
-
var
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
800
|
+
var keys = {
|
|
801
|
+
ctrl: "Control Ctrl",
|
|
802
|
+
shift: "Shift",
|
|
803
|
+
alt: "Alt",
|
|
804
|
+
meta: "Meta",
|
|
805
|
+
cmd: "Meta",
|
|
806
|
+
down: "ArrowDown",
|
|
807
|
+
up: "ArrowUp",
|
|
808
|
+
left: "ArrowLeft",
|
|
809
|
+
right: "ArrowRight",
|
|
810
|
+
end: "End",
|
|
811
|
+
home: "Home",
|
|
812
|
+
pagedown: "PageDown",
|
|
813
|
+
pageup: "PageUp",
|
|
814
|
+
enter: "Enter",
|
|
815
|
+
plus: "+",
|
|
816
|
+
minus: "-",
|
|
817
|
+
star: "*",
|
|
818
|
+
slash: "/",
|
|
819
|
+
period: ".",
|
|
820
|
+
equal: "=",
|
|
821
|
+
underscore: "_",
|
|
822
|
+
esc: "Escape",
|
|
823
|
+
escape: "Escape",
|
|
824
|
+
tab: "Tab",
|
|
825
|
+
space: " ",
|
|
826
|
+
backspace: "Backspace",
|
|
827
|
+
delete: "Delete"
|
|
828
|
+
};
|
|
829
|
+
for (let keyAttr in keys) {
|
|
830
|
+
let keyName = keys[keyAttr];
|
|
831
|
+
mods[keyAttr] = (el, cb, opts, extraKey) => [el, (e3) => {
|
|
832
|
+
if (!e3.key || !keyName.includes(e3.key))
|
|
833
|
+
return _stop;
|
|
834
|
+
cb(e3);
|
|
835
|
+
}];
|
|
836
|
+
}
|
|
713
837
|
var attr = (el, name, v2) => {
|
|
714
838
|
if (v2 == null || v2 === false)
|
|
715
839
|
el.removeAttribute(name);
|
|
@@ -723,16 +847,16 @@ function parseExpr(el, expression, dir) {
|
|
|
723
847
|
let rightSideSafeExpression = /^[\n\s]*if.*\(.*\)/.test(expression) || /^(let|const)\s/.test(expression) ? `(() => { ${expression} })()` : expression;
|
|
724
848
|
try {
|
|
725
849
|
evaluate = evaluatorMemo[expression] = new Function(`__scope`, `with (__scope) { return ${rightSideSafeExpression} };`);
|
|
726
|
-
} catch (
|
|
727
|
-
return exprError(
|
|
850
|
+
} catch (e3) {
|
|
851
|
+
return exprError(e3, el, expression, dir);
|
|
728
852
|
}
|
|
729
853
|
}
|
|
730
854
|
return (state) => {
|
|
731
855
|
let result;
|
|
732
856
|
try {
|
|
733
857
|
result = evaluate.call(el, state);
|
|
734
|
-
} catch (
|
|
735
|
-
return exprError(
|
|
858
|
+
} catch (e3) {
|
|
859
|
+
return exprError(e3, el, expression, dir);
|
|
736
860
|
}
|
|
737
861
|
return result;
|
|
738
862
|
};
|
package/sprae.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function t(){throw new Error("Cycle detected")}function e(){if(n>1)n--;else{for(var t,e=!1;void 0!==r;){var i=r;for(r=void 0,o++;void 0!==i;){var s=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&u(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=s}}if(o=0,n--,e)throw t}}var i=void 0,r=void 0,n=0,o=0,s=0;function l(t){if(void 0!==i){var e=t.n;if(void 0===e||e.t!==i)return i.s=e={i:0,S:t,p:void 0,n:i.s,t:i,e:void 0,x:void 0,r:e},t.n=e,32&i.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=i.s,i.s.p=e,i.s=e),e}}function f(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function u(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function a(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function h(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function c(t){f.call(this,void 0),this.x=t,this.s=void 0,this.g=s-1,this.f=4}function v(t){var r=t.u;if(t.u=void 0,"function"==typeof r){n++;var o=i;i=void 0;try{r()}catch(e){throw t.f&=-2,t.f|=8,p(t),e}finally{i=o,e()}}}function p(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,v(t)}function d(t){if(i!==this)throw new Error("Out-of-order effect");h(this),i=t,this.f&=-2,8&this.f&&p(this),e()}function y(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function b(t){var e=new y(t);return e.c(),e.d.bind(e)}f.prototype.h=function(){return!0},f.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},f.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},f.prototype.subscribe=function(t){var e=this;return b((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},f.prototype.valueOf=function(){return this.value},f.prototype.toString=function(){return this.value+""},f.prototype.peek=function(){return this.v},Object.defineProperty(f.prototype,"value",{get:function(){var t=l(this);return void 0!==t&&(t.i=this.i),this.v},set:function(i){if(i!==this.v){o>100&&t(),this.v=i,this.i++,s++,n++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{e()}}}}),(c.prototype=new f).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===s)return!0;if(this.g=s,this.f|=1,this.i>0&&!u(this))return this.f&=-2,!0;var t=i;try{a(this),i=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return i=t,h(this),this.f&=-2,!0},c.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}f.prototype.S.call(this,t)},c.prototype.U=function(t){if(f.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},c.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},c.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(c.prototype,"value",{get:function(){1&this.f&&t();var e=l(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),y.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},y.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,v(this),a(this),n++;var e=i;return i=this,d.bind(this,e)},y.prototype.N=function(){2&this.f||(this.f|=2,this.o=r,r=this)},y.prototype.d=function(){this.f|=8,1&this.f||p(this)},Symbol.observable||=Symbol("observable");var m=new FinalizationRegistry((t=>t.call?.())),g=(t,e,i,r,n,o)=>{return t&&(s=(t[Symbol.observable]?.()||t).subscribe?.(e,i,r),o=s&&(()=>s.unsubscribe?.())||t.set&&t.call?.(n,e)||(t.then?.((t=>(!n&&e(t),r?.())),i)||(async o=>{try{for await(o of t){if(n)return;e(o)}r?.()}catch(t){i?.(t)}})())&&(t=>n=1),m.register(t,o),o);var s},S=t=>t&&t[A],A=Symbol("signal-struct");function w(t,e){if(S(t)&&!e)return t;if(x(t)){const n=Object.create(e||Object.getPrototypeOf(t)),o={},s=Object.getOwnPropertyDescriptors(t);for(let t in s){let e=s[t];if(e.get){let i=o[t]=new c(e.get.bind(n));Object.defineProperty(n,t,{get:()=>i.value,set:e.set?.bind(n),configurable:!1,enumerable:!0})}else{let s=e.value,l=(r=s)&&!!(r[Symbol.observable]||r[Symbol.asyncIterator]||r.call&&r.set||r.subscribe||r.then),u=o[t]=(i=s)&&i.peek?s:new f(l?void 0:x(s)?Object.seal(w(s)):Array.isArray(s)?w(s):s);l&&g(s,(t=>u.value=t)),Object.defineProperty(n,t,{get:()=>u.value,set(t){if(x(t)){if(x(u.value))try{return void Object.assign(u.value,t)}catch(t){}u.value=Object.seal(w(t))}else Array.isArray(t)?u.value=w(t):u.value=t},enumerable:!0,configurable:!1})}}return Object.defineProperty(n,A,{configurable:!1,enumerable:!1,value:!0}),n}var i,r;return Array.isArray(t)&&!S(t[0])?t.map((t=>w(t))):t}function x(t){return t&&t.constructor===Object}w.isStruct=S;var O=(t,e,i,r=null)=>{let n,o,s,l=0,f=i.length,u=e.length,{remove:a,same:h,insert:c,replace:v}=O;for(;l<f&&l<u&&h(e[l],i[l]);)l++;for(;l<f&&l<u&&h(i[f-1],e[u-1]);)r=i[(--u,--f)];if(l==u)for(;l<f;)c(r,i[l++],t);else{for(n=e[l];l<f;)s=i[l++],o=n?n.nextSibling:r,h(n,s)?n=o:l<f&&h(i[l],o)?(v(n,s,t),n=o):c(n,s,t);for(;!h(n,r);)o=n.nextSibling,a(n,t),n=o}return i};O.same=(t,e)=>t==e,O.replace=(t,e,i)=>i.replaceChild(e,t),O.insert=(t,e,i)=>i.insertBefore(e,t),O.remove=(t,e)=>e.removeChild(t);var j=O,N={},E={},k={},W=t=>null===t?E:void 0===t?k:"number"==typeof t||t instanceof Number?N[t]||(N[t]=new Number(t)):"string"==typeof t||t instanceof String?N[t]||(N[t]=new String(t)):"boolean"==typeof t||t instanceof Boolean?N[t]||(N[t]=new Boolean(t)):t,$={},P={};$.if=(t,e)=>{let i=document.createTextNode(""),r=[M(t,e,":if")],n=[t],o=t;for(;(o=t.nextElementSibling)&&o.hasAttribute(":else");)o.removeAttribute(":else"),(e=o.getAttribute(":if"))?(o.removeAttribute(":if"),o.remove(),n.push(o),r.push(M(t,e,":else :if"))):(o.remove(),n.push(o),r.push((()=>1)));return t.replaceWith(o=i),t=>{let e=r.findIndex((e=>e(t)));n[e]!=o&&((o[C]||o).replaceWith(o=n[e]||i),z(o,t))}},$.with=(t,e,i)=>{z(t,w(M(t,e,"with")(i),i))};var C=Symbol(":each");$.each=(t,e)=>{let i=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r=i[2].trim(),n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?[n.replace(e,"").trim(),o[1].trim(),r]:[n,"",r]}(e);if(!i)return R(new Error,t,e);const r=t[C]=document.createTextNode("");t.replaceWith(r);const n=M(t,i[2],":each"),o=t.getAttribute(":key"),s=o?M(null,o):null;t.removeAttribute(":key");const l=new WeakMap,f=new WeakMap;let u=[];return o=>{let a=n(o);a?"number"==typeof a?a=Array.from({length:a},((t,e)=>[e,e+1])):Array.isArray(a)?a=a.map(((t,e)=>[e+1,t])):"object"==typeof a?a=Object.entries(a):R(Error("Bad list value"),t,e,":each"):a=[];let h=[],c=[];for(let[e,r]of a){let n,u,a=s?.({[i[0]]:r,[i[1]]:e});("string"==typeof(v=a)||"boolean"==typeof v||"number"==typeof v)&&(a=W(a)),null==a?n=t.cloneNode(!0):(n=f.get(a))||f.set(a,n=t.cloneNode(!0)),h.push(n),null!=a&&(u=l.get(a))?u[i[0]]=r:(u=w({[i[0]]:r,[i[1]]:e},o),null!=a&&l.set(a,u)),c.push(u)}var v;j(r.parentNode,u,h,r),u=h;for(let t=0;t<h.length;t++)z(h[t],c[t])}},P.ref=(t,e,i)=>{i[e]=t},P.id=(t,e)=>{let i=M(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},P.class=(t,e)=>{let i=M(t,e,":class"),r=t.className;return e=>{let n=i(e);t.className=r+typeof n=="string"?n:(Array.isArray(n)?n:Object.entries(n).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},P.style=(t,e)=>{let i=M(t,e,":style"),r=t.getAttribute("style")||"";return r.endsWith(";")||(r+="; "),e=>{let n=i(e);if("string"==typeof n)t.setAttribute("style",r+n);else for(let e in n)t.style[e]=n[e]}},P.text=(t,e)=>{let i=M(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},P.value=(t,e)=>{let i,r,n=M(t,e,":value"),o="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"TEXTAREA"===t.tagName||"text"===t.type||""===t.type?e=>(i=t.selectionStart,r=t.selectionEnd,t.setAttribute("value",t.value=null==e?"":e),i&&t.setSelectionRange(i,r)):"checkbox"===t.type?e=>(t.value=e?"on":"",D(t,"checked",e)):"select-one"===t.type?e=>{for(let e in t.options)e.removeAttribute("selected");t.value=e,t.selectedOptions[0]?.setAttribute("selected","")}:e=>t.value=e;return t=>o(n(t))},P.on=(t,e)=>{let i=M(t,e,":on");return e=>{let r=i(e);for(let e in r)B(t,e,r[e]);return()=>{for(let e in r)L(t,e,r[e])}}};var U=Symbol("stop"),B=(t,e,i)=>{if(e.indexOf("..")<0)t.addEventListener(e,i);else{const r=e.split("..").map((t=>t.startsWith("on")?t.slice(2):t)),n=(e,o=0)=>{let s=l=>{t.removeEventListener(r[o],s),"function"!=typeof(e=e.call(t,l))&&(e=()=>{}),++o<r.length?n(e,o):i[U]||n(i)};t.addEventListener(r[o],s)};n(i)}},L=(t,e,i)=>{e.indexOf("..")>=0&&(i[U]=!0),t.removeEventListener(e,i)};P.data=(t,e)=>{let i=M(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},P.aria=(t,e)=>{let i=M(t,e,":aria");return e=>(e=>{for(let i in e)D(t,"aria-"+F(i),null==e[i]?null:e[i]+"")})(i(e))},P[""]=(t,e)=>{let i=M(t,e,":");if(i)return e=>{let r=i(e);for(let e in r)D(t,F(e),r[e])}};var T=(t,e,i,r)=>{let n=r.startsWith("on")&&r.slice(2),o=M(t,e,":"+r);if(o)return n?e=>{let i=o(e);if(i)return B(t,n,i),()=>L(t,n,i)}:e=>D(t,r,o(e))},D=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")},_={};function M(t,e,i){let r=_[e];if(!r){let n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=_[e]=new Function("__scope",`with (__scope) { return ${n} };`)}catch(r){return R(r,t,e,i)}}return n=>{let o;try{o=r.call(t,n)}catch(r){return R(r,t,e,i)}return o}}function R(t,e,i,r){Object.assign(t,{element:e,expression:i}),console.warn(`∴ ${t.message}\n\n${r}=${i?`"${i}"\n\n`:""}`,e),setTimeout((()=>{throw t}),0)}function F(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var I=new WeakMap;function z(t,i){if(!t.children)return;if(I.has(t)){let r=I.get(t);return function(t){if(n>0)return t();n++;try{t()}finally{e()}}((()=>Object.assign(r,i))),r}const r=w(i||{}),o=[],s=(t,e=t.parentNode)=>{for(let i in $){let n=":"+i;if(t.hasAttribute?.(n)){let s=t.getAttribute(n);if(t.removeAttribute(n),!s)continue;if(o.push($[i](t,s,r,i)),I.has(t)||t.parentNode!==e)return!1}}if(t.attributes)for(let i=0;i<t.attributes.length;){let n=t.attributes[i];if(":"!==n.name[0]){i++;continue}t.removeAttribute(n.name);let s=n.value;if(!s)continue;let l=n.name.slice(1).split(":");for(let i of l){let n=P[i]||T;if(o.push(n(t,s,r,i)),I.has(t)||t.parentNode!==e)return!1}}for(let e,i=0;e=t.children[i];i++)!1===s(e,t)&&i--};s(t);for(let t of o)if(t){let e;b((()=>{"function"==typeof e&&e(),e=t(r)}))}return Object.seal(r),I.set(t,r),r}var X=z;export{X as default};
|
|
1
|
+
function t(){throw new Error("Cycle detected")}function i(){if(o>1)o--;else{for(var t,e=!1;void 0!==n;){var i=n;for(n=void 0,s++;void 0!==i;){var r=i.o;if(i.o=void 0,i.f&=-3,!(8&i.f)&&f(i))try{i.c()}catch(i){e||(t=i,e=!0)}i=r}}if(s=0,o--,e)throw t}}var r=void 0,n=void 0,o=0,s=0,l=0;function a(t){if(void 0!==r){var e=t.n;if(void 0===e||e.t!==r)return r.s=e={i:0,S:t,p:void 0,n:r.s,t:r,e:void 0,x:void 0,r:e},t.n=e,32&r.f&&t.S(e),e;if(-1===e.i)return e.i=0,void 0!==e.p&&(e.p.n=e.n,void 0!==e.n&&(e.n.p=e.p),e.p=void 0,e.n=r.s,r.s.p=e,r.s=e),e}}function u(t){this.v=t,this.i=0,this.n=void 0,this.t=void 0}function f(t){for(var e=t.s;void 0!==e;e=e.n)if(e.S.i!==e.i||!e.S.h()||e.S.i!==e.i)return!0;return!1}function c(t){for(var e=t.s;void 0!==e;e=e.n){var i=e.S.n;void 0!==i&&(e.r=i),e.S.n=e,e.i=-1}}function h(t){for(var e=t.s,i=void 0;void 0!==e;){var r=e.n;-1===e.i?(e.S.U(e),e.n=void 0):(void 0!==i&&(i.p=e),e.p=void 0,e.n=i,i=e),e.S.n=e.r,void 0!==e.r&&(e.r=void 0),e=r}t.s=i}function v(t){u.call(this,void 0),this.x=t,this.s=void 0,this.g=l-1,this.f=4}function p(t){var e=t.u;if(t.u=void 0,"function"==typeof e){o++;var n=r;r=void 0;try{e()}catch(e){throw t.f&=-2,t.f|=8,d(t),e}finally{r=n,i()}}}function d(t){for(var e=t.s;void 0!==e;e=e.n)e.S.U(e);t.x=void 0,t.s=void 0,p(t)}function y(t){if(r!==this)throw new Error("Out-of-order effect");h(this),r=t,this.f&=-2,8&this.f&&d(this),i()}function b(t){this.x=t,this.u=void 0,this.s=void 0,this.o=void 0,this.f=32}function m(t){var e=new b(t);return e.c(),e.d.bind(e)}u.prototype.h=function(){return!0},u.prototype.S=function(t){this.t!==t&&void 0===t.e&&(t.x=this.t,void 0!==this.t&&(this.t.e=t),this.t=t)},u.prototype.U=function(t){var e=t.e,i=t.x;void 0!==e&&(e.x=i,t.e=void 0),void 0!==i&&(i.e=e,t.x=void 0),t===this.t&&(this.t=i)},u.prototype.subscribe=function(t){var e=this;return m((function(){var i=e.value,r=32&this.f;this.f&=-33;try{t(i)}finally{this.f|=r}}))},u.prototype.valueOf=function(){return this.value},u.prototype.toString=function(){return this.value+""},u.prototype.peek=function(){return this.v},Object.defineProperty(u.prototype,"value",{get:function(){var t=a(this);return void 0!==t&&(t.i=this.i),this.v},set:function(e){if(e!==this.v){s>100&&t(),this.v=e,this.i++,l++,o++;try{for(var r=this.t;void 0!==r;r=r.x)r.t.N()}finally{i()}}}}),(v.prototype=new u).h=function(){if(this.f&=-3,1&this.f)return!1;if(32==(36&this.f))return!0;if(this.f&=-5,this.g===l)return!0;if(this.g=l,this.f|=1,this.i>0&&!f(this))return this.f&=-2,!0;var t=r;try{c(this),r=this;var e=this.x();(16&this.f||this.v!==e||0===this.i)&&(this.v=e,this.f&=-17,this.i++)}catch(t){this.v=t,this.f|=16,this.i++}return r=t,h(this),this.f&=-2,!0},v.prototype.S=function(t){if(void 0===this.t){this.f|=36;for(var e=this.s;void 0!==e;e=e.n)e.S.S(e)}u.prototype.S.call(this,t)},v.prototype.U=function(t){if(u.prototype.U.call(this,t),void 0===this.t){this.f&=-33;for(var e=this.s;void 0!==e;e=e.n)e.S.U(e)}},v.prototype.N=function(){if(!(2&this.f)){this.f|=6;for(var t=this.t;void 0!==t;t=t.x)t.t.N()}},v.prototype.peek=function(){if(this.h()||t(),16&this.f)throw this.v;return this.v},Object.defineProperty(v.prototype,"value",{get:function(){1&this.f&&t();var e=a(this);if(this.h(),void 0!==e&&(e.i=this.i),16&this.f)throw this.v;return this.v}}),b.prototype.c=function(){var t=this.S();try{8&this.f||void 0===this.x||(this.u=this.x())}finally{t()}},b.prototype.S=function(){1&this.f&&t(),this.f|=1,this.f&=-9,p(this),c(this),o++;var e=r;return r=this,y.bind(this,e)},b.prototype.N=function(){2&this.f||(this.f|=2,this.o=n,n=this)},b.prototype.d=function(){this.f|=8,1&this.f||d(this)},Symbol.observable||=Symbol("observable");var g=new FinalizationRegistry((t=>t.call?.())),w=(t,e,i,r,n,o)=>{return t&&(s=(t[Symbol.observable]?.()||t).subscribe?.(e,i,r),o=s&&(()=>s.unsubscribe?.())||t.set&&t.call?.(n,e)||(t.then?.((t=>(!n&&e(t),r?.())),i)||(async o=>{try{for await(o of t){if(n)return;e(o)}r?.()}catch(t){i?.(t)}})())&&(t=>n=1),g.register(t,o),o);var s},S=t=>t&&t[A],A=Symbol("signal-struct");function x(t,e){if(S(t)&&!e)return t;if(O(t)){const n=Object.create(e||Object.getPrototypeOf(t)),o={},s=Object.getOwnPropertyDescriptors(t);for(let t in s){let e=s[t];if(e.get){let i=o[t]=new v(e.get.bind(n));Object.defineProperty(n,t,{get:()=>i.value,set:e.set?.bind(n),configurable:!1,enumerable:!0})}else{let s=e.value,l=(r=s)&&!!(r[Symbol.observable]||r[Symbol.asyncIterator]||r.call&&r.set||r.subscribe||r.then),a=o[t]=(i=s)&&i.peek?s:new u(l?void 0:O(s)?Object.seal(x(s)):Array.isArray(s)?x(s):s);l&&w(s,(t=>a.value=t)),Object.defineProperty(n,t,{get:()=>a.value,set(t){if(O(t)){if(O(a.value))try{return void Object.assign(a.value,t)}catch(t){}a.value=Object.seal(x(t))}else Array.isArray(t)?a.value=x(t):a.value=t},enumerable:!0,configurable:!1})}}return Object.defineProperty(n,A,{configurable:!1,enumerable:!1,value:!0}),n}var i,r;if(Array.isArray(t)&&!S(t[0]))for(let e=0;e<t.length;e++)t[e]=x(t[e]);return t}function O(t){return t&&t.constructor===Object}x.isStruct=S;var j=(t,e,i,r=null)=>{let n,o,s,l=0,a=i.length,u=e.length,{remove:f,same:c,insert:h,replace:v}=j;for(;l<a&&l<u&&c(e[l],i[l]);)l++;for(;l<a&&l<u&&c(i[a-1],e[u-1]);)r=i[(--u,--a)];if(l==u)for(;l<a;)h(r,i[l++],t);else{for(n=e[l];l<a;)s=i[l++],o=n?n.nextSibling:r,c(n,s)?n=o:l<a&&c(i[l],o)?(v(n,s,t),n=o):h(n,s,t);for(;!c(n,r);)o=n.nextSibling,f(n,t),n=o}return i};j.same=(t,e)=>t==e,j.replace=(t,e,i)=>i.replaceChild(e,t),j.insert=(t,e,i)=>i.insertBefore(e,t),j.remove=(t,e)=>e.removeChild(t);var N=j,E={},k={},P={},W=t=>null===t?k:void 0===t?P:"number"==typeof t||t instanceof Number?E[t]||(E[t]=new Number(t)):"string"==typeof t||t instanceof String?E[t]||(E[t]=new String(t)):"boolean"==typeof t||t instanceof Boolean?E[t]||(E[t]=new Boolean(t)):t,C={},T={};C.if=(t,e)=>{let i=document.createTextNode(""),r=[H(t,e,":if")],n=[t],o=t;for(;(o=t.nextElementSibling)&&o.hasAttribute(":else");)o.removeAttribute(":else"),(e=o.getAttribute(":if"))?(o.removeAttribute(":if"),o.remove(),n.push(o),r.push(H(t,e,":else :if"))):(o.remove(),n.push(o),r.push((()=>1)));return t.replaceWith(o=i),t=>{let e=r.findIndex((e=>e(t)));n[e]!=o&&((o[D]||o).replaceWith(o=n[e]||i),X(o,t))}},C.with=(t,e,i)=>{X(t,x(H(t,e,"with")(i),i))};var D=Symbol(":each");C.each=(t,e)=>{let i=function(t){let e=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,i=t.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!i)return;let r=i[2].trim(),n=i[1].replace(/^\s*\(|\)\s*$/g,"").trim(),o=n.match(e);return o?[n.replace(e,"").trim(),o[1].trim(),r]:[n,"",r]}(e);if(!i)return I(new Error,t,e);const r=t[D]=document.createTextNode("");t.replaceWith(r);const n=H(t,i[2],":each"),o=t.getAttribute(":key"),s=o?H(null,o):null;t.removeAttribute(":key");const l=new WeakMap,a=new WeakMap;let u=[];return o=>{let f=n(o);f?"number"==typeof f?f=Array.from({length:f},((t,e)=>[e,e+1])):Array.isArray(f)?f=f.map(((t,e)=>[e+1,t])):"object"==typeof f?f=Object.entries(f):I(Error("Bad list value"),t,e,":each"):f=[];let c=[],h=[];for(let[e,r]of f){let n,u,f=s?.({[i[0]]:r,[i[1]]:e});("string"==typeof(v=f)||"boolean"==typeof v||"number"==typeof v)&&(f=W(f)),null==f?n=t.cloneNode(!0):(n=a.get(f))||a.set(f,n=t.cloneNode(!0)),c.push(n),null!=f&&(u=l.get(f))?u[i[0]]=r:(u=x({[i[0]]:r,[i[1]]:e},o),null!=f&&l.set(f,u)),h.push(u)}var v;N(r.parentNode,u,c,r),u=c;for(let t=0;t<c.length;t++)X(c[t],h[t])}},T.ref=(t,e,i)=>{i[e]=t},T.id=(t,e)=>{let i=H(t,e,":id");return e=>{return r=i(e),t.id=r||0===r?r:"";var r}},T.class=(t,e)=>{let i=H(t,e,":class"),r=t.className;return e=>{let n=i(e);t.className=r+typeof n=="string"?n:(Array.isArray(n)?n:Object.entries(n).map((([t,e])=>e?t:""))).filter(Boolean).join(" ")}},T.style=(t,e)=>{let i=H(t,e,":style"),r=t.getAttribute("style")||"";return r.endsWith(";")||(r+="; "),e=>{let n=i(e);if("string"==typeof n)t.setAttribute("style",r+n);else for(let e in n)t.style[e]=n[e]}},T.text=(t,e)=>{let i=H(t,e,":text");return e=>{let r=i(e);t.textContent=null==r?"":r}},T.data=(t,e)=>{let i=H(t,e,":data");return e=>{let r=i(e);for(let e in r)t.dataset[e]=r[e]}},T.aria=(t,e)=>{let i=H(t,e,":aria");return e=>(e=>{for(let i in e)R(t,"aria-"+q(i),null==e[i]?null:e[i]+"")})(i(e))},T[""]=(t,e)=>{let i=H(t,e,":");if(i)return e=>{let r=i(e);for(let e in r)R(t,q(e),r[e])}},T.value=(t,e)=>{let i,r,n=H(t,e,":value"),o="text"===t.type||""===t.type?e=>t.setAttribute("value",t.value=null==e?"":e):"TEXTAREA"===t.tagName||"text"===t.type||""===t.type?e=>(i=t.selectionStart,r=t.selectionEnd,t.setAttribute("value",t.value=null==e?"":e),i&&t.setSelectionRange(i,r)):"checkbox"===t.type?e=>(t.value=e?"on":"",R(t,"checked",e)):"select-one"===t.type?e=>{for(let e in t.options)e.removeAttribute("selected");t.value=e,t.selectedOptions[0]?.setAttribute("selected","")}:e=>t.value=e;return t=>o(n(t))},T.on=(t,e)=>{let i=H(t,e,":on");return e=>{let r=i(e);for(let e in r)B(t,e,r[e]);return()=>{for(let e in r)L(t,e,r[e])}}};var U=(t,e,i,r)=>{let n=r.startsWith("on")&&r.slice(2),o=H(t,e,":"+r);if(o)return n?e=>{let i=o(e);if(i)return B(t,n,i),()=>L(t,n,i)}:e=>R(t,r,o(e))},$=Symbol("stop"),B=(t,e,i)=>{let r=e.split("..").map((t=>t.startsWith("on")?t.slice(2):t)),n={};if(r[0]=r[0].replace(/\.(\w+)?-?([\w]+)?/g,((e,r,o)=>((r=M[r])&&([t,i]=r(t,i,n,o)),""))),1==r.length)t.addEventListener(r[0],i,n);else{const e=(o,s=0)=>{let l=n=>{t.removeEventListener(r[s],l),"function"!=typeof(o=o.call(t,n))&&(o=()=>{}),++s<r.length?e(o,s):i[$]||e(i)};t.addEventListener(r[s],l,n)};e(i)}},L=(t,e,i)=>{e.indexOf("..")>=0&&(i[$]=!0),t.removeEventListener(e,i)},M={throttle(t,i,r,n){n=Number(n)||108;let o,s,l=()=>{o=!0,setTimeout((()=>{o=!1,s&&(i(e),s=!1,l())}))};return[t,t=>{if(o)return s=!0,$;i(t),l()}]},debounce(t,i,r,n){n=Number(n)||108;let o,s=()=>{o=null,i(e)};return[t,t=>{clearTimeout(o),o=setTimeout(s,n)}]},window:(t,e)=>[window,e],document:(t,e)=>[document,e],outside:(t,e)=>[t,i=>t.contains(i.target)||!1===i.target.isConnected||t.offsetWidth<1&&t.offsetHeight<1?$:void e(i)],prevent:(t,e)=>[t,t=>{e(t)!==$&&t.preventDefault()}],stop:(t,e)=>[t,t=>{e(t)!==$&&t.stopPropagation()}],self:(t,e)=>[t,i=>{i.target===t&&e(i)}],once:(t,e,i)=>(i.once=!0,[t,e]),passive:(t,e,i)=>(i.passive=!0,[t,e]),capture:(t,e,i)=>(i.capture=!0,[t,e])},_={ctrl:"Control Ctrl",shift:"Shift",alt:"Alt",meta:"Meta",cmd:"Meta",down:"ArrowDown",up:"ArrowUp",left:"ArrowLeft",right:"ArrowRight",end:"End",home:"Home",pagedown:"PageDown",pageup:"PageUp",enter:"Enter",plus:"+",minus:"-",star:"*",slash:"/",period:".",equal:"=",underscore:"_",esc:"Escape",escape:"Escape",tab:"Tab",space:" ",backspace:"Backspace",delete:"Delete"};for(let t in _){let e=_[t];M[t]=(t,i,r,n)=>[t,t=>{if(!t.key||!e.includes(t.key))return $;i(t)}]}var R=(t,e,i)=>{null==i||!1===i?t.removeAttribute(e):t.setAttribute(e,!0===i?"":"number"==typeof i||"string"==typeof i?i:"")},F={};function H(t,e,i){let r=F[e];if(!r){let n=/^[\n\s]*if.*\(.*\)/.test(e)||/^(let|const)\s/.test(e)?`(() => { ${e} })()`:e;try{r=F[e]=new Function("__scope",`with (__scope) { return ${n} };`)}catch(r){return I(r,t,e,i)}}return n=>{let o;try{o=r.call(t,n)}catch(r){return I(r,t,e,i)}return o}}function I(t,e,i,r){Object.assign(t,{element:e,expression:i}),console.warn(`∴ ${t.message}\n\n${r}=${i?`"${i}"\n\n`:""}`,e),setTimeout((()=>{throw t}),0)}function q(t){return t.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(t=>"-"+t.toLowerCase()))}var z=new WeakMap;function X(t,e){if(!t.children)return;if(z.has(t)){let r=z.get(t);return function(t){if(o>0)return t();o++;try{t()}finally{i()}}((()=>Object.assign(r,e))),r}const r=x(e||{}),n=[],s=(t,e=t.parentNode)=>{for(let i in C){let o=":"+i;if(t.hasAttribute?.(o)){let s=t.getAttribute(o);if(t.removeAttribute(o),!s)continue;if(n.push(C[i](t,s,r,i)),z.has(t)||t.parentNode!==e)return!1}}if(t.attributes)for(let i=0;i<t.attributes.length;){let o=t.attributes[i];if(":"!==o.name[0]){i++;continue}t.removeAttribute(o.name);let s=o.value;if(!s)continue;let l=o.name.slice(1).split(":");for(let i of l){let o=T[i]||U;if(n.push(o(t,s,r,i)),z.has(t)||t.parentNode!==e)return!1}}for(let e,i=0;e=t.children[i];i++)!1===s(e,t)&&i--};s(t);for(let t of n)if(t){let e;m((()=>{"function"==typeof e&&e(),e=t(r)}))}return Object.seal(r),z.set(t,r),r}var Z=X;export{Z as default};
|
package/src/directives.js
CHANGED
|
@@ -182,6 +182,32 @@ secondary['text'] = (el, expr) => {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
secondary['data'] = (el, expr) => {
|
|
186
|
+
let evaluate = parseExpr(el, expr, ':data')
|
|
187
|
+
|
|
188
|
+
return ((state) => {
|
|
189
|
+
let value = evaluate(state)
|
|
190
|
+
for (let key in value) el.dataset[key] = value[key];
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
secondary['aria'] = (el, expr) => {
|
|
195
|
+
let evaluate = parseExpr(el, expr, ':aria')
|
|
196
|
+
const update = (value) => {
|
|
197
|
+
for (let key in value) attr(el, 'aria-' + dashcase(key), value[key] == null ? null : value[key] + '');
|
|
198
|
+
}
|
|
199
|
+
return ((state) => update(evaluate(state)))
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// set props in-bulk or run effect
|
|
203
|
+
secondary[''] = (el, expr) => {
|
|
204
|
+
let evaluate = parseExpr(el, expr, ':')
|
|
205
|
+
if (evaluate) return (state) => {
|
|
206
|
+
let value = evaluate(state)
|
|
207
|
+
for (let key in value) attr(el, dashcase(key), value[key]);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
185
211
|
// connect expr to element value
|
|
186
212
|
secondary['value'] = (el, expr) => {
|
|
187
213
|
let evaluate = parseExpr(el, expr, ':value')
|
|
@@ -219,13 +245,41 @@ secondary['on'] = (el, expr) => {
|
|
|
219
245
|
}
|
|
220
246
|
}
|
|
221
247
|
|
|
248
|
+
// any unknown directive
|
|
249
|
+
export default (el, expr, state, name) => {
|
|
250
|
+
let evt = name.startsWith('on') && name.slice(2)
|
|
251
|
+
let evaluate = parseExpr(el, expr, ':'+name)
|
|
252
|
+
|
|
253
|
+
if (!evaluate) return
|
|
254
|
+
|
|
255
|
+
if (evt) return state => {
|
|
256
|
+
let value = evaluate(state)
|
|
257
|
+
if (value) {
|
|
258
|
+
addListener(el, evt, value)
|
|
259
|
+
return () => removeListener(el, evt, value)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return state => attr(el, name, evaluate(state))
|
|
264
|
+
}
|
|
265
|
+
|
|
222
266
|
const _stop = Symbol('stop')
|
|
223
267
|
const addListener = (el, evt, startFn) => {
|
|
224
|
-
|
|
268
|
+
// ona..onb
|
|
269
|
+
let evts = evt.split('..').map(e => e.startsWith('on') ? e.slice(2) : e),
|
|
270
|
+
opts = {}
|
|
271
|
+
|
|
272
|
+
// onevt.debounce-108
|
|
273
|
+
evts[0] = evts[0].replace(
|
|
274
|
+
/\.(\w+)?-?([\w]+)?/g,
|
|
275
|
+
(match, mod, param) => {
|
|
276
|
+
(mod=mods[mod]) ? ([el, startFn] = mod(el, startFn, opts, param), '') : ''
|
|
277
|
+
return ''
|
|
278
|
+
}
|
|
279
|
+
);
|
|
225
280
|
|
|
226
|
-
|
|
281
|
+
if (evts.length == 1) el.addEventListener(evts[0], startFn, opts);
|
|
227
282
|
else {
|
|
228
|
-
const evts = evt.split('..').map(e => e.startsWith('on') ? e.slice(2) : e)
|
|
229
283
|
const nextEvt = (fn, cur=0) => {
|
|
230
284
|
let curListener = e => {
|
|
231
285
|
el.removeEventListener(evts[cur], curListener)
|
|
@@ -233,7 +287,7 @@ const addListener = (el, evt, startFn) => {
|
|
|
233
287
|
if (++cur < evts.length) nextEvt(fn, cur);
|
|
234
288
|
else if (!startFn[_stop]) nextEvt(startFn); // update only if chain isn't stopped
|
|
235
289
|
}
|
|
236
|
-
el.addEventListener(evts[cur],curListener)
|
|
290
|
+
el.addEventListener(evts[cur], curListener, opts)
|
|
237
291
|
}
|
|
238
292
|
nextEvt(startFn)
|
|
239
293
|
}
|
|
@@ -243,44 +297,68 @@ const removeListener = (el, evt, fn) => {
|
|
|
243
297
|
el.removeEventListener(evt, fn);
|
|
244
298
|
}
|
|
245
299
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
let
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const update = (value) => {
|
|
258
|
-
for (let key in value) attr(el, 'aria-' + dashcase(key), value[key] == null ? null : value[key] + '');
|
|
259
|
-
}
|
|
260
|
-
return ((state) => update(evaluate(state)))
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// set props in-bulk or run effect
|
|
264
|
-
secondary[''] = (el, expr) => {
|
|
265
|
-
let evaluate = parseExpr(el, expr, ':')
|
|
266
|
-
if (evaluate) return (state) => {
|
|
267
|
-
let value = evaluate(state)
|
|
268
|
-
for (let key in value) attr(el, dashcase(key), value[key]);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// any other prop directive
|
|
273
|
-
export default (el, expr, values, name) => {
|
|
274
|
-
let evt = name.startsWith('on') && name.slice(2)
|
|
275
|
-
let evaluate = parseExpr(el, expr, ':'+name)
|
|
276
|
-
if (evaluate) return evt ? state => {
|
|
277
|
-
let value = evaluate(state)
|
|
278
|
-
if (value) {
|
|
279
|
-
addListener(el, evt, value)
|
|
280
|
-
return () => removeListener(el, evt, value)
|
|
300
|
+
// event modifiers
|
|
301
|
+
const mods = {
|
|
302
|
+
throttle(el, cb, opts, limit) {
|
|
303
|
+
limit = Number(limit) || 108
|
|
304
|
+
let pause, planned, block = () => {
|
|
305
|
+
pause = true
|
|
306
|
+
setTimeout(() => {
|
|
307
|
+
pause = false
|
|
308
|
+
// if event happened during blocked time, it schedules call by the end
|
|
309
|
+
if (planned) cb(e), planned = false, block();
|
|
310
|
+
})
|
|
281
311
|
}
|
|
282
|
-
|
|
283
|
-
|
|
312
|
+
return [el, e => {
|
|
313
|
+
if (pause) return (planned = true, _stop)
|
|
314
|
+
cb(e); block();
|
|
315
|
+
}]
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
debounce(el, cb, opts, wait) {
|
|
319
|
+
wait = Number(wait) || 108;
|
|
320
|
+
let timeout, later = () => { timeout = null; cb(e) }
|
|
321
|
+
return [el, (e) => {
|
|
322
|
+
clearTimeout(timeout)
|
|
323
|
+
timeout = setTimeout(later, wait)
|
|
324
|
+
}]
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
window(el, cb) { return [window, cb] },
|
|
328
|
+
document(el, cb) { return [document, cb] },
|
|
329
|
+
outside(el, cb) {
|
|
330
|
+
return [el, (e) => {
|
|
331
|
+
if (el.contains(e.target)) return _stop
|
|
332
|
+
if (e.target.isConnected === false) return _stop
|
|
333
|
+
if (el.offsetWidth < 1 && el.offsetHeight < 1) return _stop
|
|
334
|
+
cb(e)
|
|
335
|
+
}]
|
|
336
|
+
},
|
|
337
|
+
prevent(el, cb) { return [el, e => { if (cb(e) !== _stop) e.preventDefault(); } ]},
|
|
338
|
+
stop(el, cb) { return [el, e => { if (cb(e) !== _stop) e.stopPropagation(); } ]},
|
|
339
|
+
self(el, cb) { return [el, e => { e.target === el && cb(e) } ]},
|
|
340
|
+
once(el, cb, opts) { opts.once = true; return [el, cb] },
|
|
341
|
+
passive(el, cb, opts) { opts.passive = true; return [el, cb] },
|
|
342
|
+
capture(el, cb, opts) { opts.capture = true; return [el, cb] },
|
|
343
|
+
};
|
|
344
|
+
let keys = {
|
|
345
|
+
ctrl:'Control Ctrl',
|
|
346
|
+
shift:'Shift',
|
|
347
|
+
alt:'Alt',
|
|
348
|
+
meta:'Meta',cmd:'Meta',
|
|
349
|
+
down:'ArrowDown',up:'ArrowUp',left:'ArrowLeft',right:'ArrowRight',
|
|
350
|
+
end:'End',home:'Home',pagedown:'PageDown',pageup:'PageUp',
|
|
351
|
+
enter:'Enter',plus:'+',minus:'-',star:'*',slash:'/',period:'.',equal:'=',underscore:'_',
|
|
352
|
+
esc:'Escape',escape:'Escape',tab:'Tab',space:' ',
|
|
353
|
+
backspace:'Backspace', delete:'Delete'
|
|
354
|
+
}
|
|
355
|
+
for (let keyAttr in keys) {
|
|
356
|
+
let keyName = keys[keyAttr]
|
|
357
|
+
mods[keyAttr] = (el, cb, opts, extraKey) => [el, e => {
|
|
358
|
+
// _stop indicates skip subsequent modifiers
|
|
359
|
+
if (!e.key || !keyName.includes(e.key)) return _stop
|
|
360
|
+
cb(e)
|
|
361
|
+
}]
|
|
284
362
|
}
|
|
285
363
|
|
|
286
364
|
// set attr
|
|
@@ -289,7 +367,6 @@ const attr = (el, name, v) => {
|
|
|
289
367
|
else el.setAttribute(name, v === true ? '' : (typeof v === 'number' || typeof v === 'string') ? v : '')
|
|
290
368
|
}
|
|
291
369
|
|
|
292
|
-
|
|
293
370
|
let evaluatorMemo = {}
|
|
294
371
|
|
|
295
372
|
// borrowed from alpine: https://github.com/alpinejs/alpine/blob/main/packages/alpinejs/src/evaluator.js#L61
|
|
@@ -326,7 +403,7 @@ function parseExpr(el, expression, dir) {
|
|
|
326
403
|
}
|
|
327
404
|
}
|
|
328
405
|
|
|
329
|
-
|
|
406
|
+
function exprError(error, element, expression, dir) {
|
|
330
407
|
Object.assign( error, { element, expression } )
|
|
331
408
|
console.warn(`∴ ${error.message}\n\n${dir}=${ expression ? `"${expression}"\n\n` : '' }`, element)
|
|
332
409
|
setTimeout(() => { throw error }, 0)
|
package/test/test.js
CHANGED
|
@@ -424,12 +424,16 @@ test.todo('each: unmounted elements remove listeners', async () => {
|
|
|
424
424
|
|
|
425
425
|
test('each: internal children get updated by state update, also: update by running again', () => {
|
|
426
426
|
let el = h`<><x :each="item, idx in items" :text="item" :key="idx"></x></>`
|
|
427
|
-
sprae(el, { items: [1,2,3] })
|
|
427
|
+
let state = sprae(el, { items: [1,2,3] })
|
|
428
428
|
is(el.textContent, '123')
|
|
429
|
-
|
|
429
|
+
state.items = [2, 2, 3]
|
|
430
|
+
is(el.textContent, '223')
|
|
431
|
+
state = sprae(el, { items: [0,2,3] })
|
|
430
432
|
is(el.textContent, '023')
|
|
433
|
+
// NOTE: this doesn't update items, since they're new array
|
|
434
|
+
console.log('set items')
|
|
431
435
|
state.items[0] = 1
|
|
432
|
-
state.items = state.items
|
|
436
|
+
state.items = [...state.items]
|
|
433
437
|
is(el.textContent, '123')
|
|
434
438
|
})
|
|
435
439
|
|
|
@@ -569,6 +573,65 @@ test('on: state changes between chain of events', e => {
|
|
|
569
573
|
is(log, [1, 1.1, 2])
|
|
570
574
|
})
|
|
571
575
|
|
|
576
|
+
test('on: once', e => {
|
|
577
|
+
// NOTE: if callback updates it's still rebound
|
|
578
|
+
let el = h`<x :onx.once="(e=>x&&log.push(this))" ></x>`
|
|
579
|
+
let log = []
|
|
580
|
+
let state = sprae(el, {log, x:1})
|
|
581
|
+
el.dispatchEvent(new window.Event('x'));
|
|
582
|
+
is(log, [el])
|
|
583
|
+
el.dispatchEvent(new window.Event('x'));
|
|
584
|
+
is(log, [el])
|
|
585
|
+
state.x = 2
|
|
586
|
+
el.dispatchEvent(new window.Event('x'));
|
|
587
|
+
el.dispatchEvent(new window.Event('x'));
|
|
588
|
+
is(log, [el])
|
|
589
|
+
})
|
|
590
|
+
|
|
591
|
+
test('on: capture, stop, prevent', e => {
|
|
592
|
+
let el = h`<x :onx.capture="e=>log.push(1)"><y :onx="e=>log.push(2)"></y></x>`
|
|
593
|
+
let state = sprae(el, {log:[]})
|
|
594
|
+
el.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
|
|
595
|
+
is(state.log, [1,2])
|
|
596
|
+
|
|
597
|
+
let el2 = h`<x :onx="e=>log.push(1)"><y :onx.stop="e=>log.push(2)"></y></x>`
|
|
598
|
+
let state2 = sprae(el2, {log:[]})
|
|
599
|
+
el2.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
|
|
600
|
+
is(state2.log, [2])
|
|
601
|
+
})
|
|
602
|
+
|
|
603
|
+
test('on: window, self', e => {
|
|
604
|
+
let el = h`<x :onx.self="e=>log.push(1)"><y :onx.window="e=>log.push(2)"></y></x>`
|
|
605
|
+
let state = sprae(el, {log:[]})
|
|
606
|
+
el.firstChild.dispatchEvent(new window.Event('x', {bubbles:true}));
|
|
607
|
+
is(state.log, [])
|
|
608
|
+
el.dispatchEvent(new window.Event('x', {bubbles:true}));
|
|
609
|
+
is(state.log, [1])
|
|
610
|
+
window.dispatchEvent(new window.Event('x', {bubbles:true}));
|
|
611
|
+
is(state.log, [1,2])
|
|
612
|
+
})
|
|
613
|
+
|
|
614
|
+
test('on: keys', e => {
|
|
615
|
+
let el = h`<x :onkeydown.enter="e=>log.push(1)"></x>`
|
|
616
|
+
let state = {log:[]}
|
|
617
|
+
sprae(el, state)
|
|
618
|
+
el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
|
|
619
|
+
is(state.log,[])
|
|
620
|
+
el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
|
|
621
|
+
el.dispatchEvent(new window.KeyboardEvent('keydown', { key: '' }));
|
|
622
|
+
is(state.log,[1])
|
|
623
|
+
el.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
|
|
624
|
+
is(state.log,[1,1])
|
|
625
|
+
})
|
|
626
|
+
|
|
627
|
+
test('on: keys with prevent', e => {
|
|
628
|
+
let el = h`<y :onkeydown="e=>log.push(e.key)"><x :ref="x" :onkeydown.enter.stop="e=>1"></x></y>`
|
|
629
|
+
let state = sprae(el, {log:[]})
|
|
630
|
+
state.x.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'x', bubbles: true }));
|
|
631
|
+
state.x.dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
|
|
632
|
+
is(state.log,['x'])
|
|
633
|
+
})
|
|
634
|
+
|
|
572
635
|
test('with: inline', () => {
|
|
573
636
|
let el = h`<x :with="{foo:'bar'}"><y :text="foo + baz"></y></x>`
|
|
574
637
|
let state = sprae(el, {baz: 'qux'})
|