sprae 12.2.5 → 12.3.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 +47 -140
- package/directive/_.js +3 -0
- package/directive/class.js +9 -5
- package/directive/each.js +9 -11
- package/directive/else.js +2 -2
- package/directive/event.js +17 -0
- package/directive/if.js +3 -6
- package/directive/ref.js +6 -5
- package/directive/scope.js +7 -7
- package/directive/sequence.js +35 -0
- package/directive/style.js +11 -6
- package/directive/text.js +1 -1
- package/directive/value.js +1 -1
- package/dist/sprae.js +3 -3
- package/dist/sprae.js.map +4 -4
- package/dist/sprae.micro.js +5 -0
- package/dist/sprae.micro.js.map +7 -0
- package/dist/sprae.umd.js +3 -3
- package/dist/sprae.umd.js.map +4 -4
- package/micro.js +55 -1
- package/package.json +2 -2
- package/readme.md +7 -4
- package/signal.js +12 -11
- package/sprae.js +80 -37
- package/store.js +1 -1
- package/directive/default.js +0 -3
package/core.js
CHANGED
|
@@ -6,7 +6,6 @@ export const _dispose = (Symbol.dispose ||= Symbol("dispose")),
|
|
|
6
6
|
_off = Symbol('off'),
|
|
7
7
|
_add = Symbol('init');
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
export let prefix = ':', signal, effect, computed, batch = (fn) => fn(), untracked = batch;
|
|
11
10
|
|
|
12
11
|
export let directive = {}, modifier = {}
|
|
@@ -41,7 +40,7 @@ const sprae = (el = document.body, state) => {
|
|
|
41
40
|
el[_dispose] ||= () => (el[_off](), el[_off] = el[_on] = el[_dispose] = el[_add] = el[_state] = null)
|
|
42
41
|
|
|
43
42
|
const add = el[_add] = (el) => {
|
|
44
|
-
let _attrs = el.attributes,
|
|
43
|
+
let _attrs = el.attributes, start;
|
|
45
44
|
|
|
46
45
|
// we iterate live collection (subsprae can init args)
|
|
47
46
|
if (_attrs) for (let i = 0; i < _attrs.length;) {
|
|
@@ -50,8 +49,10 @@ const sprae = (el = document.body, state) => {
|
|
|
50
49
|
if (name.startsWith(prefix)) {
|
|
51
50
|
el.removeAttribute(name)
|
|
52
51
|
|
|
52
|
+
currentDir = name;
|
|
53
|
+
|
|
53
54
|
// directive initializer can be redefined
|
|
54
|
-
|
|
55
|
+
fx.push(start = dir(el, name.slice(prefix.length), value, state)), offs.push(start())
|
|
55
56
|
|
|
56
57
|
// stop after subsprae like :each, :if, :scope etc.
|
|
57
58
|
if (_state in el) return
|
|
@@ -73,120 +74,8 @@ const sprae = (el = document.body, state) => {
|
|
|
73
74
|
return state;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
* Initializes directive (defined by sprae build), returns "on" function that enables it
|
|
79
|
-
* Multiprop sequences initializer, eg. :a:b..c:d
|
|
80
|
-
* @type {(el: HTMLElement, name:string, value:string, state:Object) => Function}
|
|
81
|
-
* */
|
|
82
|
-
const initDirective = (el, dirName, expr, state) => {
|
|
83
|
-
let cur, // current step callback
|
|
84
|
-
off // current step disposal
|
|
85
|
-
|
|
86
|
-
let steps = dirName.slice(prefix.length).split('..').map((step, i, { length }) => (
|
|
87
|
-
// multiple attributes like :id:for=""
|
|
88
|
-
step.split(prefix).reduce((prev, str) => {
|
|
89
|
-
let [name, ...mods] = str.split('.');
|
|
90
|
-
let evaluate = parse(expr, directive[currentDir = name]?.parse).bind(el)
|
|
91
|
-
|
|
92
|
-
// a hack, but events have no signal-effects and can be sequenced
|
|
93
|
-
// FIXME: events are molded into core, but should be an optional directive
|
|
94
|
-
if (name.startsWith('on')) {
|
|
95
|
-
let type = name.slice(2),
|
|
96
|
-
fn = applyMods(
|
|
97
|
-
sx(
|
|
98
|
-
// single event vs chain
|
|
99
|
-
length == 1 ? e => evaluate(state, (fn) => call(fn, e)) :
|
|
100
|
-
(e => (cur = (!i ? e => call(evaluate(state), e) : cur)(e), off(), off = steps[(i + 1) % length]())),
|
|
101
|
-
{ target: el }
|
|
102
|
-
),
|
|
103
|
-
mods);
|
|
104
|
-
|
|
105
|
-
return (_poff) => (_poff = prev?.(), fn.target.addEventListener(type, fn, fn), () => (_poff?.(), fn.target.removeEventListener(type, fn)))
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
let fn, dispose, change, count;
|
|
109
|
-
|
|
110
|
-
if (mods.length) {
|
|
111
|
-
change = signal(-1), // signal authorized to trigger effect: 0 = init; >0 = trigger
|
|
112
|
-
count = -1 // called effect count
|
|
113
|
-
|
|
114
|
-
// effect applier - first time it applies the effect, next times effect is triggered by change signal
|
|
115
|
-
fn = applyMods(sx(throttle(() => {
|
|
116
|
-
if (++change.value) return // all calls except for the first one are handled by effect
|
|
117
|
-
dispose = effect(() => update && (
|
|
118
|
-
change.value == count ? fn() : // plan update: separate tick (via throttle) makes sure planner effect call is finished before eval call
|
|
119
|
-
(count = change.value, evaluate(state, update)) // if changed more than effect called - call it
|
|
120
|
-
));
|
|
121
|
-
}), {target: el}), mods)
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
fn = sx(() => dispose = effect(() => evaluate(state, update)), {target: el })
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// props have no sequences and can be sync
|
|
128
|
-
// it's nice to see directive as taking some part of current context and returning new or updated context
|
|
129
|
-
let update = (directive[name] || directive['*'])(fn.target, state, expr, name)
|
|
130
|
-
|
|
131
|
-
// some directives are effect-less
|
|
132
|
-
if (!update) return
|
|
133
|
-
|
|
134
|
-
// take over state if directive created it (mainly :scope)
|
|
135
|
-
if (el[_state]) state = el[_state]
|
|
136
|
-
|
|
137
|
-
return (_poff) => (
|
|
138
|
-
_poff = prev?.(),
|
|
139
|
-
// console.log('ON', name),
|
|
140
|
-
fn(),
|
|
141
|
-
() => (
|
|
142
|
-
// console.log('OFF', name, el),
|
|
143
|
-
_poff?.(), dispose?.(), change && (change.value = -1, count = dispose = null)
|
|
144
|
-
)
|
|
145
|
-
)
|
|
146
|
-
}, null)
|
|
147
|
-
));
|
|
148
|
-
|
|
149
|
-
// off can be changed on the go
|
|
150
|
-
return () => (off = steps[0]?.())
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Configure sprae
|
|
156
|
-
*/
|
|
157
|
-
export const use = (s) => (
|
|
158
|
-
s.compile && (compile = s.compile),
|
|
159
|
-
s.prefix && (prefix = s.prefix),
|
|
160
|
-
s.signal && (signal = s.signal),
|
|
161
|
-
s.effect && (effect = s.effect),
|
|
162
|
-
s.computed && (computed = s.computed),
|
|
163
|
-
s.batch && (batch = s.batch),
|
|
164
|
-
s.untracked && (untracked = s.untracked)
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Lifecycle hanger: spraes automatically any new nodes
|
|
170
|
-
*/
|
|
171
|
-
export const start = (root = document.body, values) => {
|
|
172
|
-
const state = store(values)
|
|
173
|
-
sprae(root, state);
|
|
174
|
-
const mo = new MutationObserver(mutations => {
|
|
175
|
-
for (const m of mutations) {
|
|
176
|
-
for (const el of m.addedNodes) {
|
|
177
|
-
// el can be spraed or removed by subsprae (like within :each/:if)
|
|
178
|
-
if (el.nodeType === 1 && el[_state] === undefined && root.contains(el)) {
|
|
179
|
-
// even if element has no spraeable attrs, some of its children can have
|
|
180
|
-
root[_add](el)
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
// for (const el of m.removedNodes) el[Symbol.dispose]?.()
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
mo.observe(root, { childList: true, subtree: true });
|
|
187
|
-
return state
|
|
188
|
-
}
|
|
189
|
-
|
|
77
|
+
// directive initializer
|
|
78
|
+
export let dir
|
|
190
79
|
|
|
191
80
|
/**
|
|
192
81
|
* Compiles an expression into an evaluator function.
|
|
@@ -200,14 +89,14 @@ export let compile
|
|
|
200
89
|
* @param {string} expr The expression to parse and compile into a function.
|
|
201
90
|
* @returns {Function} The compiled evaluator function for the expression.
|
|
202
91
|
*/
|
|
203
|
-
export const parse = (expr
|
|
204
|
-
|
|
92
|
+
export const parse = (expr) => {
|
|
93
|
+
let fn = cache[expr=expr.trim()]
|
|
94
|
+
if (fn) return fn
|
|
205
95
|
|
|
206
|
-
let _expr = expr
|
|
207
|
-
if (prepare) _expr = prepare(_expr)
|
|
96
|
+
let _expr = expr || 'undefined'
|
|
208
97
|
|
|
209
98
|
// if, const, let - no return
|
|
210
|
-
if (/^(if|let|const)\b/.test(_expr) || /;(?![^{]*})/.test(_expr))
|
|
99
|
+
if (/^(if|let|const)\b/.test(_expr) || /;(?![^{]*})/.test(_expr));
|
|
211
100
|
else _expr = `return ${_expr}`
|
|
212
101
|
|
|
213
102
|
// async expression
|
|
@@ -215,37 +104,54 @@ export const parse = (expr, prepare, _fn) => {
|
|
|
215
104
|
|
|
216
105
|
// static time errors
|
|
217
106
|
try {
|
|
218
|
-
|
|
219
|
-
Object.defineProperty(
|
|
220
|
-
} catch (e) { console.error(`∴ ${e}\n\n${
|
|
107
|
+
fn = compile(_expr)
|
|
108
|
+
// Object.defineProperty(fn, "name", { value: `∴ ${expr}` })
|
|
109
|
+
} catch (e) { console.error(`∴ ${e}\n\n${currentDir}="${expr}"`) }
|
|
221
110
|
|
|
222
111
|
// run time errors
|
|
223
112
|
return cache[expr] = function (state, cb, _out) {
|
|
224
113
|
try {
|
|
225
|
-
let result =
|
|
226
|
-
// if cb is given (to handle
|
|
227
|
-
if (cb) return result?.then ? result.then(v => _out = cb(v))
|
|
114
|
+
let result = fn?.call(this, state)
|
|
115
|
+
// if cb is given (to handle async/await exprs, usually directive update) - call it with result and return a cleanup function
|
|
116
|
+
if (cb) return result?.then ? (result.then(v => _out = cb(v)), () => _out && call(_out)) : cb(result)
|
|
228
117
|
else return result
|
|
229
118
|
} catch (e) {
|
|
230
|
-
console.error(`∴ ${e}\n\n${
|
|
119
|
+
console.error(`∴ ${e}\n\n${currentDir}="${expr}"`)
|
|
231
120
|
}
|
|
232
121
|
}
|
|
233
122
|
}
|
|
234
123
|
const cache = {};
|
|
235
124
|
|
|
236
125
|
|
|
237
|
-
|
|
238
|
-
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Configure sprae
|
|
129
|
+
*/
|
|
130
|
+
export const use = (s) => (
|
|
131
|
+
s.compile && (compile = s.compile),
|
|
132
|
+
s.prefix && (prefix = s.prefix),
|
|
133
|
+
s.signal && (signal = s.signal),
|
|
134
|
+
s.effect && (effect = s.effect),
|
|
135
|
+
s.computed && (computed = s.computed),
|
|
136
|
+
s.batch && (batch = s.batch),
|
|
137
|
+
s.untracked && (untracked = s.untracked),
|
|
138
|
+
s.dir && (dir = s.dir)
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
// modifier applier
|
|
142
|
+
export const decorate = (fn, mods) => {
|
|
239
143
|
while (mods.length) {
|
|
240
|
-
let [name, ...params] = mods.pop().split('-')
|
|
241
|
-
|
|
144
|
+
let [name, ...params] = mods.pop().split('-'), mod = modifier[name], wrapFn
|
|
145
|
+
if (mod) {
|
|
146
|
+
if ((wrapFn = mod(fn, ...params)) !== fn) {
|
|
147
|
+
for (let k in fn) wrapFn[k] ??= fn[k];
|
|
148
|
+
fn = wrapFn
|
|
149
|
+
}
|
|
150
|
+
}
|
|
242
151
|
}
|
|
243
152
|
return fn
|
|
244
153
|
}
|
|
245
154
|
|
|
246
|
-
// soft-extend missing props and ignoring signals
|
|
247
|
-
const sx = (a, b) => { if (a != b) for (let k in b) (a[k] ??= b[k]); return a }
|
|
248
|
-
|
|
249
155
|
// instantiated <template> fragment holder, like persisting fragment but with minimal API surface
|
|
250
156
|
export const frag = (tpl) => {
|
|
251
157
|
if (!tpl.nodeType) return tpl // existing tpl
|
|
@@ -289,16 +195,17 @@ export const clsx = (c, _out = []) => !c ? '' : typeof c === 'string' ? c : (
|
|
|
289
195
|
|
|
290
196
|
// throttle function to (once per tick or other custom scheduler)
|
|
291
197
|
export const throttle = (fn, schedule = queueMicrotask) => {
|
|
292
|
-
let _planned = 0;
|
|
198
|
+
let _planned = 0, arg;
|
|
293
199
|
const throttled = (e) => {
|
|
294
|
-
|
|
295
|
-
|
|
200
|
+
arg = e
|
|
201
|
+
if (!_planned++) fn(arg), schedule((_dirty = _planned > 1) => (
|
|
202
|
+
_planned = 0, _dirty && throttled(arg)
|
|
296
203
|
));
|
|
297
204
|
}
|
|
298
205
|
return throttled;
|
|
299
206
|
}
|
|
300
207
|
|
|
301
|
-
export const debounce = (fn, schedule = queueMicrotask, _count = 0) => (arg, _planned
|
|
208
|
+
export const debounce = (fn, schedule = queueMicrotask, _count = 0) => (arg, _planned = ++_count) => schedule(() => (_planned == _count && fn(arg)))
|
|
302
209
|
|
|
303
210
|
export * from './store.js';
|
|
304
211
|
|
package/directive/_.js
ADDED
package/directive/class.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { clsx, call } from "../core.js";
|
|
1
|
+
import { clsx, call, decorate } from "../core.js";
|
|
2
2
|
|
|
3
|
-
export default (el,
|
|
4
|
-
_cur = new Set,
|
|
5
|
-
|
|
3
|
+
export default (el, st, ex, name) => {
|
|
4
|
+
let _cur = new Set, _new
|
|
5
|
+
|
|
6
|
+
// redefine target, if modifiers have one
|
|
7
|
+
name.includes('.') && (el = decorate({target:el}, name.split('.').slice(1)).target ?? el)
|
|
8
|
+
|
|
9
|
+
return (v) => {
|
|
6
10
|
_new = new Set
|
|
7
11
|
if (v) clsx(call(v, el.className)).split(' ').map(c => c && _new.add(c))
|
|
8
12
|
for (let c of _cur) if (_new.has(c)) _new.delete(c); else el.classList.remove(c);
|
|
9
13
|
for (let c of _cur = _new) el.classList.add(c)
|
|
10
14
|
}
|
|
11
|
-
|
|
15
|
+
}
|
package/directive/each.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import sprae, { store, _state, effect, _change, _signals, frag, throttle } from "../core.js";
|
|
1
|
+
import sprae, { store, parse, _state, effect, _change, _signals, frag, throttle, debounce } from "../core.js";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
export default (tpl, state, expr) => {
|
|
4
|
+
const [lhs, rhs] = expr.split(/\bin\b/)
|
|
5
|
+
|
|
6
|
+
let [itemVar, idxVar = "$"] = lhs.trim().replace(/\(|\)/g, '').split(/\s*,\s*/);
|
|
5
7
|
|
|
6
8
|
// we need :if to be able to replace holder instead of tpl for :if :each case
|
|
7
9
|
let holder = document.createTextNode("");
|
|
@@ -19,6 +21,7 @@ const each = (tpl, state, expr) => {
|
|
|
19
21
|
cur = null, prevl = 0
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
|
|
22
25
|
// delete
|
|
23
26
|
if (newl < prevl) cur.length = newl
|
|
24
27
|
|
|
@@ -65,7 +68,7 @@ const each = (tpl, state, expr) => {
|
|
|
65
68
|
tpl.replaceWith(holder);
|
|
66
69
|
tpl[_state] = null // mark as fake-spraed, to preserve :-attribs for template
|
|
67
70
|
|
|
68
|
-
return value => {
|
|
71
|
+
return Object.assign(value => {
|
|
69
72
|
// resolve new items
|
|
70
73
|
keys = null
|
|
71
74
|
if (typeof value === "number") items = Array.from({ length: value }, (_, i) => i + 1)
|
|
@@ -74,16 +77,11 @@ const each = (tpl, state, expr) => {
|
|
|
74
77
|
|
|
75
78
|
// whenever list changes, we rebind internal change effect
|
|
76
79
|
return effect(() => {
|
|
77
|
-
// subscribe to items change (.length) - we do it every time (not just in update) since preact unsubscribes unused signals
|
|
80
|
+
// subscribe to items change (.length) - we do it every time (not just in update) since preact signals unsubscribes unused signals
|
|
78
81
|
items[_change]?.value
|
|
79
82
|
|
|
80
83
|
// make first render immediately, debounce subsequent renders
|
|
81
84
|
update()
|
|
82
85
|
})
|
|
83
|
-
}
|
|
86
|
+
}, {eval:parse(rhs)})
|
|
84
87
|
}
|
|
85
|
-
|
|
86
|
-
// :each directive skips v, k
|
|
87
|
-
each.parse = (str) => str.split(/\bin\b/)[1].trim()
|
|
88
|
-
|
|
89
|
-
export default each
|
package/directive/else.js
CHANGED
|
@@ -2,9 +2,9 @@ import { _on, _off, _state, frag } from '../core.js';
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
// NOTE: we can reach :else counterpart whereas prev :else :if is on hold
|
|
5
|
-
export default (el
|
|
5
|
+
export default (el) => {
|
|
6
|
+
let _el, _prev = el
|
|
6
7
|
|
|
7
|
-
// console.log(':else init', el)
|
|
8
8
|
_el = el.content ? frag(el) : el
|
|
9
9
|
|
|
10
10
|
// find holder
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { call, parse, decorate } from "../core.js"
|
|
2
|
+
|
|
3
|
+
export default (el, state, expr, name) => {
|
|
4
|
+
// wrap inline cb into function
|
|
5
|
+
// if (!/^(?:[\w$]+|\([^()]*\))\s*=>/.test(expr) && !/^function\b/.test(expr)) expr = `()=>{${expr}}`;
|
|
6
|
+
|
|
7
|
+
const [type, ...mods] = name.slice(2).split('.'),
|
|
8
|
+
evaluate = parse(expr).bind(el),
|
|
9
|
+
trigger = decorate(Object.assign(e => evaluate(state, (fn) => fn && call(fn, e)), { target: el }), mods);
|
|
10
|
+
|
|
11
|
+
trigger.target.addEventListener(type, trigger, trigger)
|
|
12
|
+
return {
|
|
13
|
+
[Symbol.dispose]() {
|
|
14
|
+
trigger.target.removeEventListener(type, trigger)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
package/directive/if.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import sprae, { throttle, _on, _off, _state, frag } from '../core.js';
|
|
3
3
|
|
|
4
4
|
// :if="a"
|
|
5
|
-
export default (el, state
|
|
5
|
+
export default (el, state) => {
|
|
6
|
+
let _holder, _el, _match
|
|
7
|
+
|
|
6
8
|
// new element :if
|
|
7
|
-
// console.log(':if init', el)
|
|
8
9
|
if (!el._holder) {
|
|
9
10
|
// mark el as fake-spraed to delay init, since we sprae rest when branch matches, both :if and :else :if
|
|
10
11
|
el[_state] ??= null
|
|
@@ -19,10 +20,8 @@ export default (el, state, _holder, _el, _match) => {
|
|
|
19
20
|
|
|
20
21
|
_holder.update = throttle(() => {
|
|
21
22
|
let match = _holder._clauses.find(([, s]) => s)
|
|
22
|
-
// console.group(':if update clauses', ..._holder._clauses)
|
|
23
23
|
|
|
24
24
|
if (match != _match) {
|
|
25
|
-
// console.log(':if match', match)
|
|
26
25
|
_match?.[0].remove()
|
|
27
26
|
_match?.[0][_off]?.()
|
|
28
27
|
if (_match = match) {
|
|
@@ -31,7 +30,6 @@ export default (el, state, _holder, _el, _match) => {
|
|
|
31
30
|
!_match[0][_state] ? (delete _match[0][_state], sprae(_match[0], state)) : _match[0][_on]?.()
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
|
-
// console.groupEnd()
|
|
35
33
|
})
|
|
36
34
|
}
|
|
37
35
|
// :else :if needs to be spraed all over to have clean list of offable effects
|
|
@@ -40,7 +38,6 @@ export default (el, state, _holder, _el, _match) => {
|
|
|
40
38
|
// :else may have children to init which is called after :if
|
|
41
39
|
// or preact can schedule :else after :if, so we ensure order of call by next tick
|
|
42
40
|
return value => {
|
|
43
|
-
// console.log(':if update', _el, value)
|
|
44
41
|
_el._clause[1] = value
|
|
45
42
|
_el._holder.update()
|
|
46
43
|
}
|
package/directive/ref.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { parse } from "../core.js"
|
|
2
2
|
// import { setter } from "./value.js"
|
|
3
3
|
|
|
4
|
-
export default (el, state, expr
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export default (el, state, expr) => {
|
|
5
|
+
let fn = parse(expr)(state)
|
|
6
|
+
|
|
7
|
+
if (typeof fn == 'function') return {[Symbol.dispose]:fn(el)}
|
|
7
8
|
|
|
8
9
|
// NOTE: we have to set element statically (outside of effect) to avoid parasitic sub - multiple els with same :ref can cause recursion (eg. :each :ref="x")
|
|
9
|
-
// (setter(expr)(state, el))
|
|
10
|
-
Object.defineProperty(state, expr, { value: el, configurable: true })
|
|
10
|
+
// FIXME: do via (setter(expr)(state, el))
|
|
11
|
+
else Object.defineProperty(state, expr, { value: el, configurable: true })
|
|
11
12
|
}
|
package/directive/scope.js
CHANGED
|
@@ -3,27 +3,27 @@ import sprae, { store, call, untracked, _state, _signals, signal } from '../core
|
|
|
3
3
|
export default (el, rootState) => {
|
|
4
4
|
// 0 run pre-creates state to provide scope for the first effect - it can write vars in it, so we should already have it
|
|
5
5
|
// el[_state] even replaces own :scope effect state
|
|
6
|
-
let
|
|
6
|
+
let state = el[_state] = store({}, rootState), init = false;
|
|
7
7
|
|
|
8
8
|
// 1st run spraes subtree with values from scope - it can be postponed by modifiers (we isolate reads from parent effect)
|
|
9
9
|
// 2nd+ runs update subscope
|
|
10
10
|
return values => {
|
|
11
|
-
values = call(values,
|
|
11
|
+
values = call(values, state);
|
|
12
12
|
|
|
13
13
|
// we bind to subscope to alleviate friction using scope method directly
|
|
14
14
|
// also returned props should force-create signals in subscope, not overwriting parent
|
|
15
|
-
if (values !==
|
|
15
|
+
if (values !== state) {
|
|
16
16
|
for (let k in values) {
|
|
17
17
|
// _add forces new prop, instead of checking parent
|
|
18
|
-
let v = typeof values[k] === 'function' ? values[k].bind(
|
|
18
|
+
let v = typeof values[k] === 'function' ? values[k].bind(state) : values[k]
|
|
19
19
|
// update
|
|
20
|
-
if (k in
|
|
20
|
+
if (k in state[_signals]) state[k] = v
|
|
21
21
|
// create
|
|
22
|
-
else (
|
|
22
|
+
else (state[_signals][k] = (k[0] == '_' || v?.peek) ? v : signal(store(v)))
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// Object.assign(subscope, call(values, subscope))
|
|
27
|
-
return !init && (init = true, delete el[_state], untracked(() => sprae(el,
|
|
27
|
+
return !init && (init = true, delete el[_state], untracked(() => sprae(el, state)))
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// events directive with enabled aliases and sequences like :onclick.ctrl.once..keyup.enter
|
|
2
|
+
import { _dispose, call, parse, decorate } from "../core.js"
|
|
3
|
+
|
|
4
|
+
export default (el, state, expr, names) => {
|
|
5
|
+
let cur, // current step callback
|
|
6
|
+
off // current step disposal
|
|
7
|
+
|
|
8
|
+
let steps = names.split('..').map((step, i, { length }) => step.split(':').reduce(
|
|
9
|
+
(prev, str) => {
|
|
10
|
+
const [name, ...mods] = str.slice(2).split('.')
|
|
11
|
+
|
|
12
|
+
const evaluate = parse(expr).bind(el)
|
|
13
|
+
|
|
14
|
+
const trigger = decorate(Object.assign(
|
|
15
|
+
e => (!i ? evaluate(state, (fn) => cur = fn && call(fn, e)) : (cur = cur(e)), off(), off = steps[(i + 1) % length]()),
|
|
16
|
+
{ target: el }
|
|
17
|
+
), mods)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
return (_poff) => (
|
|
21
|
+
_poff = prev?.(),
|
|
22
|
+
trigger.target.addEventListener(name, trigger, trigger),
|
|
23
|
+
() => (_poff?.(), trigger.target.removeEventListener(name, trigger))
|
|
24
|
+
)
|
|
25
|
+
}, null)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
off = steps[0]()
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
[Symbol.dispose]() {
|
|
32
|
+
off?.()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
package/directive/style.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { call, attr } from "../core.js";
|
|
1
|
+
import { call, attr, decorate } from "../core.js";
|
|
2
2
|
|
|
3
|
-
export default (el,
|
|
4
|
-
_static
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
export default (el, st, ex, name) => {
|
|
4
|
+
let _static;
|
|
5
|
+
|
|
6
|
+
// redefine target, if modifiers have one
|
|
7
|
+
if (name.includes('.')) el = decorate({target:el}, name.split('.').slice(1)).target ?? el;
|
|
8
|
+
|
|
9
|
+
return v => {
|
|
10
|
+
if (!_static) { _static = el.getAttribute("style") }
|
|
11
|
+
if (v) v = call(v, el.style)
|
|
7
12
|
if (typeof v === "string") attr(el, "style", _static + '; ' + v);
|
|
8
13
|
else {
|
|
9
14
|
if (_static) attr(el, "style", _static);
|
|
@@ -11,4 +16,4 @@ export default (el, _static) => (
|
|
|
11
16
|
for (let k in v) k[0] == '-' ? el.style.setProperty(k, v[k]) : k[0] > 'A' && (el.style[k] = v[k])
|
|
12
17
|
}
|
|
13
18
|
}
|
|
14
|
-
|
|
19
|
+
}
|
package/directive/text.js
CHANGED
|
@@ -3,5 +3,5 @@ import { frag, call } from "../core.js"
|
|
|
3
3
|
export default el => (
|
|
4
4
|
// <template :text="a"/> or previously initialized template
|
|
5
5
|
el.content && el.replaceWith(el = frag(el).childNodes[0]),
|
|
6
|
-
v => (v = call(v, el.textContent), el.textContent = v == null ? "" : v)
|
|
6
|
+
v => (v = v && call(v, el.textContent), el.textContent = v == null ? "" : v)
|
|
7
7
|
)
|
package/directive/value.js
CHANGED
|
@@ -7,7 +7,7 @@ export const setter = (expr, _set = parse(`${expr}=__`)) => (target, value) => {
|
|
|
7
7
|
target.__ = value; _set(target), delete target.__
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export default (el, state, expr
|
|
10
|
+
export default (el, state, expr) => {
|
|
11
11
|
// bind back to value, but some values can be not bindable, eg. `:value="7"`
|
|
12
12
|
try {
|
|
13
13
|
const set = setter(expr)
|
package/dist/sprae.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var
|
|
1
|
+
var ke=Object.defineProperty;var Ne=(e,r)=>{for(var t in r)ke(e,t,{get:r[t],enumerable:!0})};var T=Symbol.dispose||(Symbol.dispose=Symbol("dispose")),p=Symbol("state"),V=Symbol("on"),M=Symbol("off"),J=Symbol("init"),Z=":",y,P,B,q=e=>e(),v=q,K={},I={},z=null,Te=(e=document.body,r)=>{if(e[p])return Object.assign(e[p],r);r=R(r||{});let t=[],o=[];e[V]=()=>!o&&(o=t.map(i=>i())),e[M]=()=>(o?.map(i=>i()),o=null),e[T]||(e[T]=()=>(e[M](),e[M]=e[V]=e[T]=e[J]=e[p]=null));let s=e[J]=i=>{let n=i.attributes,a;if(n)for(let l=0;l<n.length;){let{name:c,value:m}=n[l];if(c.startsWith(Z)){if(i.removeAttribute(c),z=c,t.push(a=te(i,c.slice(Z.length),m,r)),o.push(a()),p in i)return}else l++}for(let l of[...i.childNodes])l.nodeType==1&&s(l)};return s(e),e[p]===void 0&&(e[p]=r),r},te,re,g=e=>{let r=ee[e=e.trim()];if(r)return r;let t=e||"undefined";/^(if|let|const)\b/.test(t)||/;(?![^{]*})/.test(t)||(t=`return ${t}`),/\bawait\s/.test(t)&&(t=`return (async()=>{ ${t} })()`);try{r=re(t)}catch(o){console.error(`\u2234 ${o}
|
|
2
2
|
|
|
3
|
-
${
|
|
3
|
+
${z}="${e}"`)}return ee[e]=function(o,s,i){try{let n=r?.call(this,o);return s?n?.then?(n.then(a=>i=s(a)),()=>i&&f(i)):s(n):n}catch(n){console.error(`\u2234 ${n}
|
|
4
4
|
|
|
5
|
-
${E+U}="${e}"`)}}},ie={},se=(e,r)=>{for(;r.length;){let[t,...o]=r.pop().split("-");e=H(J[t]?.(e,...o)??e,e)}return e},H=(e,r)=>{if(e!=r)for(let t in r)e[t]??(e[t]=r[t]);return e},k=e=>{if(!e.nodeType)return e;let r=e.content.cloneNode(!0),t=[...e.attributes],o=document.createTextNode(""),n=(r.append(o),[...r.childNodes]);return{childNodes:n,content:r,remove:()=>r.append(...n),replaceWith(i){i!==o&&(o.before(i),r.append(...n))},attributes:t,removeAttribute(i){t.splice(t.findIndex(s=>s.name===i),1)}}},d=(e,r)=>typeof e=="function"?e(r):e,le=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(r,t)=>(t?"-":"")+r.toLowerCase()),x=(e,r,t)=>t==null||t===!1?e.removeAttribute(r):e.setAttribute(r,t===!0?"":t),_=(e,r=[])=>e?typeof e=="string"?e:(Array.isArray(e)?e.map(_):Object.entries(e).reduce((t,[o,n])=>n?[...t,o]:t,[])).join(" "):"",T=(e,r=queueMicrotask)=>{let t=0,o=n=>{t++||(e(n),r((i=t>1)=>(t=0,i&&o(n))))};return o},fe=(e,r=queueMicrotask,t=0)=>(o,n=++t)=>r(()=>n==t&&e(o)),p=ae;var S=Symbol("signals"),O=Symbol("change"),te=Symbol("set"),ee=!0,D=(e,r)=>{if(!e||e[Symbol.toStringTag]||e[S])return e;if(e.constructor!==Object)return Array.isArray(e)?Pe(e):e;let t=Object.keys(e).length,o={},n=new Proxy(Object.assign(o,{[O]:A(t),[S]:o}),{get:(s,a)=>a in o?o[a]?o[a].valueOf():o[a]:r?r[a]:globalThis[a],set:(s,a,c,f)=>a in o?(pe(o,a,c),1):(ee=!1,r&&a in r?r[a]=c:(z(o,a,c),o[O].value=++t),ee=!0,1),deleteProperty:(s,a)=>(a in o&&(a[0]!="_"&&o[a]?.[Symbol.dispose]?.(),delete o[a],o[O].value=--t),1),ownKeys:()=>(o[O].value,Reflect.ownKeys(o)),has:(s,a)=>a in o?!0:r?a in r:ee}),i=Object.getOwnPropertyDescriptors(e);for(let s in e)i[s]?.get?(o[s]=Y(i[s].get.bind(n)))[te]=i[s].set?.bind(n):z(o,s,e[s]);return n},Pe=(e,r=globalThis)=>{let t=Array(e.length).fill(null),o=!1,n=a=>function(){return o=!0,a.apply(this,arguments)},i=A(e.length),s=new Proxy(Object.assign(t,{[O]:i,[S]:t,push:n(t.push),pop:n(t.pop),shift:n(t.shift),unshift:n(t.unshift),splice:n(t.splice)}),{get(a,c){return c==="length"?o?(o=!1,t.length):i.value:typeof c=="symbol"||isNaN(c)?t[c]?.valueOf()??r[c]:(t[c]??(t[c]=A(D(e[c])))).valueOf()},set(a,c,f){if(c==="length"){for(let y=f;y<t.length;y++)delete s[y];i.value=t.length=f}else c>=t.length?(z(t,c,f),s.length=+c+1):t[c]?pe(t,c,f):z(t,c,f);return 1},deleteProperty:(a,c)=>(t[c]?.[Symbol.dispose]?.(),delete t[c],1)});return s},z=(e,r,t)=>e[r]=r[0]=="_"||t?.peek?t:A(D(t)),pe=(e,r,t,o,n)=>r[0]==="_"?e[r]=t:t!==(n=(o=e[r]).peek())&&(o[te]?o[te](t):Array.isArray(t)&&Array.isArray(n)?O in n?V(()=>Z(()=>{for(let i=0;i<t.length;i++)n[i]=t[i];n.length=t.length})):o.value=t:o.value=D(t)),B=D;var j,de=0,M,re=(e,r,t=new Set,o=()=>r.value)=>r={get value(){return j?.deps.push(t.add(j)),e},set value(n){if(n!==e){e=n;for(let i of t)M?M.add(i):i()}},peek(){return e},toJSON:o,then:o,toString:o,valueOf:o},oe=(e,r,t,o,n)=>(t=i=>{if(n=r,r=null,n?.call?.(),i=j,j=t,de++>10)throw"Cycle detected";try{r=e()}finally{j=i,de--}},o=t.deps=[],t(),i=>{for(r?.call?.();i=o.pop();)i.delete(t)}),me=(e,r=re(),t,o,n=()=>t.value)=>t={get value(){return o||(o=oe(()=>r.value=e())),r.value},peek:r.peek,toJSON:n,then:n,toString:n,valueOf:n},ye=(e,r=!M)=>{M??(M=new Set);try{e()}finally{if(r){for(let t of M)t();M=null}}},he=(e,r,t)=>(r=j,j=null,t=e(),j=r,t);var ge=(e,r,t,o,n)=>{var i;return e._holder?p(o=e,r):(e[i=l]??(e[i]=null),o=e.content?k(e):e,e.replaceWith(t=document.createTextNode("")),o._holder=t._holder=t,t._clauses=[o._clause=[o,!1]],t.update=T(()=>{let s=t._clauses.find(([,a])=>a);s!=n&&(n?.[0].remove(),n?.[0][I]?.(),(n=s)&&(t.before(n[0].content||n[0]),n[0][l]?n[0][X]?.():(delete n[0][l],p(n[0],r))))})),s=>{o._clause[1]=s,o._holder.update()}};var be=(e,r,t,o,n=e)=>{for(t=e.content?k(e):e;n&&!(t._holder=n._holder);)n=n.previousSibling;return e.remove(),e[l]=null,t._holder._clauses.push(t._clause=[t,!0]),t._holder.update};var xe=e=>(e.content&&e.replaceWith(e=k(e).childNodes[0]),r=>(r=d(r,e.textContent),e.textContent=r??""));var Se=(e,r,t)=>(r=new Set,o=>{t=new Set,o&&_(d(o,e.className)).split(" ").map(n=>n&&t.add(n));for(let n of r)t.has(n)?t.delete(n):e.classList.remove(n);for(let n of r=t)e.classList.add(n)});var Ae=(e,r)=>(r=e.getAttribute("style"),t=>{if(t=d(t,e.style),typeof t=="string")x(e,"style",r+"; "+t);else{r&&x(e,"style",r);for(let o in t)o[0]=="-"?e.style.setProperty(o,t[o]):o[0]>"A"&&(e.style[o]=t[o])}});var Oe=()=>d;var We=(e,r=L(`${e}=__`))=>(t,o)=>{t.__=o,r(t),delete t.__},we=(e,r,t,o)=>{try{let n=We(t),i=e.type==="checkbox"?()=>n(r,e.checked):e.type==="select-multiple"?()=>n(r,[...e.selectedOptions].map(s=>s.value)):()=>n(r,e.selectedIndex<0?null:isNaN(e.valueAsNumber)?e.value:e.valueAsNumber);e.oninput=e.onchange=i,e.type?.startsWith("select")&&(new MutationObserver(i).observe(e,{childList:!0,subtree:!0,attributes:!0}),p(e,r)),L(t)(r)??i()}catch{}return e.type==="text"||e.type===""||e.tagName==="TEXTAREA"?(n,i,s)=>(i=e.selectionStart,s=e.selectionEnd,e.setAttribute("value",e.value=n??""),i&&e.setSelectionRange(i,s)):e.type==="checkbox"?n=>(e.checked=n,x(e,"checked",n)):e.type==="radio"?n=>e.value===n&&(e.checked=n,x(e,"checked",n)):e.type==="select-one"?n=>{for(let i of e.options)i.value==n?i.setAttribute("selected",""):i.removeAttribute("selected");e.value=n}:e.type==="select-multiple"?n=>{for(let i of e.options)i.removeAttribute("selected");for(let i of n)e.querySelector(`[value="${i}"]`).setAttribute("selected","")}:n=>e.value=n};var Ne=(e,r,t,o,n,i)=>{if(typeof L(t)(r)=="function")return s=>s(e);Object.defineProperty(r,t,{value:e,configurable:!0})};var ke=(e,r)=>{let t=e[l]=D({},r),o=!1;return n=>{if(n=d(n,t),n!==t)for(let i in n){let s=typeof n[i]=="function"?n[i].bind(t):n[i];i in t[S]?t[i]=s:t[S][i]=i[0]=="_"||s?.peek?s:A(D(s))}return!o&&(o=!0,delete e[l],V(()=>p(e,t)))}};var je=(e,r,t)=>{let[o,n="$"]=t.split(/\bin\b/)[0].trim().replace(/\(|\)/g,"").split(/\s*,\s*/),i=document.createTextNode(""),s,a,c,f=0,y=T(()=>{var $,w;let u=0,m=c,h=m.length;if(s&&!s[O]){for(let g of s[S]||[])g[Symbol.dispose]();s=null,f=0}if(h<f)s.length=h;else{if(!s)s=m;else for(;u<f;)s[u]=m[u++];for(;u<h;u++){s[u]=m[u];let g=u,N=Object.create(r,{[o]:{get:()=>s[g]},[n]:{value:a?a[g]:g}}),b=e.content?k(e):e.cloneNode(!0);i.before(b.content||b),p(b,N);let C=((w=s[$=S]||(s[$]=[]))[u]||(w[u]={}))[Symbol.dispose];s[S][u][Symbol.dispose]=()=>{C?.(),b[Symbol.dispose]?.(),b.remove()}}}f=h});return e.replaceWith(i),e[l]=null,u=>(a=null,typeof u=="number"?c=Array.from({length:u},(m,h)=>h+1):u?.constructor===Object?(a=Object.keys(u),c=Object.values(u)):c=u||[],R(()=>{c[O]?.value,y()}))};je.parse=e=>e.split(/\bin\b/)[1].trim();var $e=je;var Te=(e,r,t,o)=>n=>x(e,o,d(n,e.getAttribute(o)));var De=e=>r=>{for(let t in r)x(e,le(t),r[t])};Object.assign(W,{"*":Te,"":De,class:Se,text:xe,style:Ae,fx:Oe,value:we,ref:Ne,scope:ke,if:ge,else:be,each:$e});Object.assign(J,{debounce:(e,r=250)=>fe(e,(r||(r=0),t=>setTimeout(t,r))),throttle:(e,r=250)=>T(e,(r||(r=0),t=>setTimeout(t,r))),tick:e=>r=>queueMicrotask(()=>e(r)),raf:e=>r=>requestAnimationFrame(()=>e(r)),once:(e,r,t)=>Object.assign(o=>!r&&(r=1,e(o)),{once:!0}),window:e=>(e.target=e.target.ownerDocument.defaultView,e),document:e=>(e.target=e.target.ownerDocument,e),root:e=>(e.target=e.target.ownerDocument.documentElement,e),body:e=>(e.target=e.target.ownerDocument.body,e),parent:e=>(e.target=e.target.parentNode,e),self:e=>r=>r.target===e.target&&e(r),outside:e=>(r,t)=>(t=e.target,!t.contains(r.target)&&r.target.isConnected&&(t.offsetWidth||t.offsetHeight)),prevent:e=>r=>(r?.preventDefault(),e(r)),stop:e=>r=>(r?.stopPropagation(),e(r)),immediate:e=>r=>(r?.stopImmediatePropagation(),e(r)),passive:e=>(e.passive=!0,e),capture:e=>(e.capture=!0,e)});var ne={ctrl:e=>e.ctrlKey||e.key==="Control"||e.key==="Ctrl",shift:e=>e.shiftKey||e.key==="Shift",alt:e=>e.altKey||e.key==="Alt",meta:e=>e.metaKey||e.key==="Meta"||e.key==="Command",arrow:e=>e.key.startsWith("Arrow"),enter:e=>e.key==="Enter",esc:e=>e.key.startsWith("Esc"),tab:e=>e.key==="Tab",space:e=>e.key==="\xA0"||e.key==="Space"||e.key===" ",delete:e=>e.key==="Delete"||e.key==="Backspace",digit:e=>/^\d$/.test(e.key),letter:e=>/^\p{L}$/gu.test(e.key),char:e=>/^\S$/.test(e.key)};for(let e in ne)J[e]=(r,...t)=>o=>ne[e](o)&&t.every(n=>ne[n]?.(o)??o.key===n)&&r(o);v({compile:e=>p.constructor(`with (arguments[0]) { ${e} }`),signal:re,effect:oe,computed:me,batch:ye,untracked:he});p.use=v;p.store=B;p.directive=W;p.modifier=J;p.start=ce;p.version="12.2.4";var Lt=p;export{ye as batch,me as computed,Lt as default,oe as effect,re as signal,p as sprae,ce as start,B as store,he as untracked,v as use};
|
|
5
|
+
${z}="${e}"`)}}},ee={},F=e=>(e.compile&&(re=e.compile),e.prefix&&(Z=e.prefix),e.signal&&(y=e.signal),e.effect&&(P=e.effect),e.computed&&(B=e.computed),e.batch&&(q=e.batch),e.untracked&&(v=e.untracked),e.dir&&(te=e.dir)),b=(e,r)=>{for(;r.length;){let[t,...o]=r.pop().split("-"),s=I[t],i;if(s&&(i=s(e,...o))!==e){for(let n in e)i[n]??(i[n]=e[n]);e=i}}return e},O=e=>{if(!e.nodeType)return e;let r=e.content.cloneNode(!0),t=[...e.attributes],o=document.createTextNode(""),s=(r.append(o),[...r.childNodes]);return{childNodes:s,content:r,remove:()=>r.append(...s),replaceWith(i){i!==o&&(o.before(i),r.append(...s))},attributes:t,removeAttribute(i){t.splice(t.findIndex(n=>n.name===i),1)}}},f=(e,r)=>typeof e=="function"?e(r):e,oe=e=>e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(r,t)=>(t?"-":"")+r.toLowerCase()),x=(e,r,t)=>t==null||t===!1?e.removeAttribute(r):e.setAttribute(r,t===!0?"":t),G=(e,r=[])=>e?typeof e=="string"?e:(Array.isArray(e)?e.map(G):Object.entries(e).reduce((t,[o,s])=>s?[...t,o]:t,[])).join(" "):"",$=(e,r=queueMicrotask)=>{let t=0,o,s=i=>{o=i,t++||(e(o),r((n=t>1)=>(t=0,n&&s(o))))};return s},se=(e,r=queueMicrotask,t=0)=>(o,s=++t)=>r(()=>s==t&&e(o)),d=Te;var _=Symbol("signals"),j=Symbol("change"),U=Symbol("set"),Q=!0,D=(e,r)=>{if(!e||e[Symbol.toStringTag]||e[_])return e;if(e.constructor!==Object)return Array.isArray(e)?$e(e):e;let t=Object.keys(e).length,o={},s=new Proxy(Object.assign(o,{[j]:y(t),[_]:o}),{get:(n,a)=>a in o?o[a]?o[a].valueOf():o[a]:r?r[a]:globalThis[a],set:(n,a,l,c)=>a in o?(ie(o,a,l),1):(Q=!1,r&&a in r?r[a]=l:(H(o,a,l),o[j].value=++t),Q=!0,1),deleteProperty:(n,a)=>(a in o&&(a[0]!="_"&&o[a]?.[Symbol.dispose]?.(),delete o[a],o[j].value=--t),1),ownKeys:()=>(o[j].value,Reflect.ownKeys(o)),has:(n,a)=>a in o?!0:r?a in r:Q}),i=Object.getOwnPropertyDescriptors(e);for(let n in e)i[n]?.get?(o[n]=B(i[n].get.bind(s)))[U]=i[n].set?.bind(s):H(o,n,e[n]);return s},$e=(e,r=globalThis)=>{let t=Array(e.length).fill(null),o=!1,s=a=>function(){return o=!0,a.apply(this,arguments)},i=y(e.length),n=new Proxy(Object.assign(t,{[j]:i,[_]:t,push:s(t.push),pop:s(t.pop),shift:s(t.shift),unshift:s(t.unshift),splice:s(t.splice)}),{get(a,l){return l==="length"?o?(o=!1,t.length):i.value:typeof l=="symbol"||isNaN(l)?t[l]?.valueOf()??r[l]:(t[l]??(t[l]=y(D(e[l])))).valueOf()},set(a,l,c){if(l==="length"){for(let m=c;m<t.length;m++)delete n[m];i.value=t.length=c}else l>=t.length?(H(t,l,c),n.length=+l+1):t[l]?ie(t,l,c):H(t,l,c);return 1},deleteProperty:(a,l)=>(t[l]?.[Symbol.dispose]?.(),delete t[l],1)});return n},H=(e,r,t)=>e[r]=r[0]=="_"||t?.peek?t:y(D(t)),ie=(e,r,t,o,s)=>r[0]==="_"?e[r]=t:t!==(s=(o=e[r]).peek())&&(o[U]?o[U](t):Array.isArray(t)&&Array.isArray(s)?j in s?v(()=>q(()=>{for(let i=0;i<t.length;i++)s[i]=t[i];s.length=t.length})):o.value=t:o.value=D(t)),R=D;var Y={};Ne(Y,{batch:()=>ve,computed:()=>De,effect:()=>le,signal:()=>ae,untracked:()=>Ce});var k,ne=0,C,ae=(e,r,t=new Set,o=()=>r.value)=>r={get value(){return k?.deps.add(t.add(k)),e},set value(s){if(s!==e){e=s;for(let i of t)C?C.add(i):i()}},peek(){return e},toJSON:o,toString:o,valueOf:o},le=(e,r,t,o)=>(t=s=>{let i=r;if(r=null,i?.call?.(),s=k,k=t,ne++>10)throw"Cycle detected";try{r=e()}finally{k=s,ne--}},t.fn=e,o=t.deps=new Set,t(),s=>{r?.call?.();for(s of o)s.delete(t);o.clear()}),De=(e,r=ae(),t,o,s=()=>t.value)=>t={get value(){return o||(o=le(()=>r.value=e())),r.value},peek:r.peek,toJSON:s,toString:s,valueOf:s},ve=(e,r=!C,t)=>{C??(C=new Set);try{e()}finally{if(r){[C,t]=[null,C];for(let o of t)o()}}},Ce=(e,r,t)=>(r=k,k=null,t=e(),k=r,t);var ce={name:"sprae",description:"DOM microhydration",version:"12.3.0",main:"./sprae.js",module:"./sprae.js","umd:main":"dist/sprae.umd.js",unpkg:"dist/sprae.umd.js",types:"dist/sprae.d.ts",type:"module",files:["core.js","sprae.js","store.js","signal.js","micro.js","directive","dist"],devDependencies:{"@preact/signals":"^2.0.4","@preact/signals-core":"^1.8.0","@webreflection/signal":"^2.1.2","es-module-shims":"^1.10.0",esbuild:"^0.23.0","esbuild-plugin-umd-wrapper":"^2.0.3","esbuild-plugin-version-injector":"^1.2.1",hyperf:"^1.7.0",jsdom:"^27.0.0",requestidlecallback:"^0.3.0","signal-polyfill":"^0.1.1",subscript:"^9.1.0",tst:"^8.0.2",ulive:"^1.0.7",usignal:"^0.9.0","wait-please":"^3.1.0"},scripts:{test:"node -r ./test/register.cjs test/test.js",build:"node .esbuild.js"},repository:{type:"git",url:"git+https://github.com/dy/sprae.git"},keywords:["hydration","progressive","progressive enhancement","signals","directives","preact-signals","reactive","template-parts","petit-vue","alpinejs","templating"],author:"Dmitry Iv <df.creative@gmail.com>",license:"MIT",bugs:{url:"https://github.com/dy/sprae/issues"},homepage:"https://github.com/dy/sprae#readme"};var ue=(e,r)=>{var i;let t,o,s;return e._holder?d(o=e,r):(e[i=p]??(e[i]=null),o=e.content?O(e):e,e.replaceWith(t=document.createTextNode("")),o._holder=t._holder=t,t._clauses=[o._clause=[o,!1]],t.update=$(()=>{let n=t._clauses.find(([,a])=>a);n!=s&&(s?.[0].remove(),s?.[0][M]?.(),(s=n)&&(t.before(s[0].content||s[0]),s[0][p]?s[0][V]?.():(delete s[0][p],d(s[0],r))))})),n=>{o._clause[1]=n,o._holder.update()}};var pe=e=>{let r,t=e;for(r=e.content?O(e):e;t&&!(r._holder=t._holder);)t=t.previousSibling;return e.remove(),e[p]=null,r._holder._clauses.push(r._clause=[r,!0]),r._holder.update};var de=e=>(e.content&&e.replaceWith(e=O(e).childNodes[0]),r=>(r=r&&f(r,e.textContent),e.textContent=r??""));var fe=(e,r,t,o)=>{let s=new Set,i;return o.includes(".")&&(e=b({target:e},o.split(".").slice(1)).target??e),n=>{i=new Set,n&&G(f(n,e.className)).split(" ").map(a=>a&&i.add(a));for(let a of s)i.has(a)?i.delete(a):e.classList.remove(a);for(let a of s=i)e.classList.add(a)}};var me=(e,r,t,o)=>{let s;return o.includes(".")&&(e=b({target:e},o.split(".").slice(1)).target??e),i=>{if(s||(s=e.getAttribute("style")),i&&(i=f(i,e.style)),typeof i=="string")x(e,"style",s+"; "+i);else{s&&x(e,"style",s);for(let n in i)n[0]=="-"?e.style.setProperty(n,i[n]):n[0]>"A"&&(e.style[n]=i[n])}}};var ge=()=>f;var Le=(e,r=g(`${e}=__`))=>(t,o)=>{t.__=o,r(t),delete t.__},he=(e,r,t)=>{try{let o=Le(t),s=e.type==="checkbox"?()=>o(r,e.checked):e.type==="select-multiple"?()=>o(r,[...e.selectedOptions].map(i=>i.value)):()=>o(r,e.selectedIndex<0?null:isNaN(e.valueAsNumber)?e.value:e.valueAsNumber);e.oninput=e.onchange=s,e.type?.startsWith("select")&&(new MutationObserver(s).observe(e,{childList:!0,subtree:!0,attributes:!0}),d(e,r)),g(t)(r)??s()}catch{}return e.type==="text"||e.type===""||e.tagName==="TEXTAREA"?(o,s,i)=>(s=e.selectionStart,i=e.selectionEnd,e.setAttribute("value",e.value=o??""),s&&e.setSelectionRange(s,i)):e.type==="checkbox"?o=>(e.checked=o,x(e,"checked",o)):e.type==="radio"?o=>e.value===o&&(e.checked=o,x(e,"checked",o)):e.type==="select-one"?o=>{for(let s of e.options)s.value==o?s.setAttribute("selected",""):s.removeAttribute("selected");e.value=o}:e.type==="select-multiple"?o=>{for(let s of e.options)s.removeAttribute("selected");for(let s of o)e.querySelector(`[value="${s}"]`).setAttribute("selected","")}:o=>e.value=o};var ye=(e,r,t)=>{let o=g(t)(r);if(typeof o=="function")return{[Symbol.dispose]:o(e)};Object.defineProperty(r,t,{value:e,configurable:!0})};var be=(e,r)=>{let t=e[p]=D({},r),o=!1;return s=>{if(s=f(s,t),s!==t)for(let i in s){let n=typeof s[i]=="function"?s[i].bind(t):s[i];i in t[_]?t[i]=n:t[_][i]=i[0]=="_"||n?.peek?n:y(D(n))}return!o&&(o=!0,delete e[p],v(()=>d(e,t)))}};var xe=(e,r,t)=>{let[o,s]=t.split(/\bin\b/),[i,n="$"]=o.trim().replace(/\(|\)/g,"").split(/\s*,\s*/),a=document.createTextNode(""),l,c,m,w=0,S=$(()=>{var A,E;let u=0,N=m,h=N.length;if(l&&!l[j]){for(let L of l[_]||[])L[Symbol.dispose]();l=null,w=0}if(h<w)l.length=h;else{if(!l)l=N;else for(;u<w;)l[u]=N[u++];for(;u<h;u++){l[u]=N[u];let L=u,Ae=Object.create(r,{[i]:{get:()=>l[L]},[n]:{value:c?c[L]:L}}),W=e.content?O(e):e.cloneNode(!0);a.before(W.content||W),d(W,Ae);let Oe=((E=l[A=_]||(l[A]=[]))[u]||(E[u]={}))[Symbol.dispose];l[_][u][Symbol.dispose]=()=>{Oe?.(),W[Symbol.dispose]?.(),W.remove()}}}w=h});return e.replaceWith(a),e[p]=null,Object.assign(u=>(c=null,typeof u=="number"?m=Array.from({length:u},(N,h)=>h+1):u?.constructor===Object?(c=Object.keys(u),m=Object.values(u)):m=u||[],P(()=>{m[j]?.value,S()})),{eval:g(s)})};var _e=(e,r,t,o)=>s=>x(e,o,s&&f(s,e.getAttribute(o)));var Se=e=>r=>{for(let t in r)x(e,oe(t),r[t])};var je=(e,r,t,o)=>{let[s,...i]=o.slice(2).split("."),n=g(t).bind(e),a=b(Object.assign(l=>n(r,c=>c&&f(c,l)),{target:e}),i);return a.target.addEventListener(s,a,a),{[Symbol.dispose](){a.target.removeEventListener(s,a)}}};var we=(e,r,t,o)=>{let s,i,n=o.split("..").map((a,l,{length:c})=>a.split(":").reduce((m,w)=>{let[S,...u]=w.slice(2).split("."),N=g(t).bind(e),h=b(Object.assign(A=>(l?s=s(A):N(r,E=>s=E&&f(E,A)),i(),i=n[(l+1)%c]()),{target:e}),u);return A=>(A=m?.(),h.target.addEventListener(S,h,h),()=>(A?.(),h.target.removeEventListener(S,h)))},null));return i=n[0](),{[Symbol.dispose](){i?.()}}};Object.assign(K,{_:(e,r,t,o)=>(o.startsWith("on")?je:_e)(e,r,t,o),"":Se,class:fe,text:de,style:me,fx:ge,value:he,ref:ye,scope:be,if:ue,else:pe,each:xe});var We=(e,r,t,o)=>{let[s,...i]=r.split("."),n=K[s]||K._;return()=>{let a=n(e,o,t,r);if(!a?.call)return a?.[T];let l=b(Object.assign($(()=>c.value++),{target:e}),i),c=y(0),m=0,w=a.eval??g(t).bind(e),S,u=()=>(S&&f(S),S=null);return o=e[p]??o,P(()=>(c.value==m?l():(m=c.value,S=w(o,a)),u))}};Object.assign(I,{debounce:(e,r=250)=>se(e,(r||(r=0),t=>setTimeout(t,r))),throttle:(e,r=250)=>$(e,(r||(r=0),t=>setTimeout(t,r))),tick:e=>r=>queueMicrotask(()=>e(r)),raf:e=>r=>requestAnimationFrame(()=>e(r)),once:(e,r,t)=>(t=o=>!r&&(r=1,e(o)),t.once=!0,t),window:e=>(e.target=e.target.ownerDocument.defaultView,e),document:e=>(e.target=e.target.ownerDocument,e),root:e=>(e.target=e.target.ownerDocument.documentElement,e),body:e=>(e.target=e.target.ownerDocument.body,e),parent:e=>(e.target=e.target.parentNode,e),self:e=>r=>r.target===e.target&&e(r),outside:e=>(r,t)=>(t=e.target,!t.contains(r.target)&&r.target.isConnected&&(t.offsetWidth||t.offsetHeight)),prevent:e=>r=>(r?.preventDefault(),e(r)),stop:e=>r=>(r?.stopPropagation(),e(r)),immediate:e=>r=>(r?.stopImmediatePropagation(),e(r)),passive:e=>(e.passive=!0,e),capture:e=>(e.capture=!0,e)});var X={ctrl:e=>e.ctrlKey||e.key==="Control"||e.key==="Ctrl",shift:e=>e.shiftKey||e.key==="Shift",alt:e=>e.altKey||e.key==="Alt",meta:e=>e.metaKey||e.key==="Meta",cmd:e=>e.metaKey||e.key==="Command",arrow:e=>e.key.startsWith("Arrow"),enter:e=>e.key==="Enter",esc:e=>e.key.startsWith("Esc"),tab:e=>e.key==="Tab",space:e=>e.key==="\xA0"||e.key==="Space"||e.key===" ",delete:e=>e.key==="Delete"||e.key==="Backspace",digit:e=>/^\d$/.test(e.key),letter:e=>/^\p{L}$/gu.test(e.key),char:e=>/^\S$/.test(e.key)};for(let e in X)I[e]=(r,t,o)=>s=>X[e](s)&&(!t||X[t]?.(s))&&(!o||X[o]?.(s))&&r(s);F({compile:e=>d.constructor(`with (arguments[0]) { ${e} }`),dir:(e,r,t,o)=>r.includes("..")?()=>we(e,o,t,r)[T]:r.split(":").reduce((s,i)=>{let n=We(e,i,t,o);return s?(a,l)=>(a=s(),l=n(),()=>{a(),l()}):n},null),...Y});d.use=F;d.store=R;d.directive=K;d.modifier=I;d.version=ce.version;var Ht=d.start=(e=document.body,r)=>{let t=R(r);return d(e,t),new MutationObserver(s=>{for(let i of s)for(let n of i.addedNodes)n.nodeType===1&&n[p]===void 0&&e.contains(n)&&e[J](n)}).observe(e,{childList:!0,subtree:!0}),t};d.version="12.3.0";var Xt=d;export{q as batch,B as computed,Xt as default,P as effect,y as signal,d as sprae,Ht as start,R as store,v as untracked,F as use};
|