sprae 11.0.7 → 11.0.8
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 +48 -16
- package/directive/aria.js +4 -7
- package/directive/class.js +6 -7
- package/directive/data.js +2 -7
- package/directive/default.js +32 -34
- package/directive/each.js +41 -55
- package/directive/fx.js +2 -4
- package/directive/if.js +8 -6
- package/directive/ref.js +4 -5
- package/directive/style.js +6 -8
- package/directive/text.js +5 -10
- package/directive/value.js +13 -13
- package/directive/with.js +2 -8
- package/dist/sprae.js +103 -151
- package/dist/sprae.js.map +3 -3
- package/dist/sprae.min.js +2 -2
- package/dist/sprae.min.js.map +3 -3
- package/dist/sprae.umd.js +107 -153
- package/dist/sprae.umd.js.map +3 -3
- package/dist/sprae.umd.min.js +2 -2
- package/dist/sprae.umd.min.js.map +3 -3
- package/package.json +1 -1
- package/readme.md +15 -5
- package/signal.js +5 -16
- package/store.js +3 -3
package/dist/sprae.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// signal.js
|
|
2
2
|
var current;
|
|
3
|
-
var batched;
|
|
4
3
|
var signal = (v, s, obs = /* @__PURE__ */ new Set()) => (s = {
|
|
5
4
|
get value() {
|
|
6
5
|
current?.deps.push(obs.add(current));
|
|
@@ -9,7 +8,7 @@ var signal = (v, s, obs = /* @__PURE__ */ new Set()) => (s = {
|
|
|
9
8
|
set value(val) {
|
|
10
9
|
if (val === v) return;
|
|
11
10
|
v = val;
|
|
12
|
-
for (let sub of obs)
|
|
11
|
+
for (let sub of obs) sub();
|
|
13
12
|
},
|
|
14
13
|
peek() {
|
|
15
14
|
return v;
|
|
@@ -34,31 +33,19 @@ var computed = (fn, s = signal(), c, e) => (c = {
|
|
|
34
33
|
},
|
|
35
34
|
peek: s.peek
|
|
36
35
|
}, c.toJSON = c.then = c.toString = c.valueOf = () => c.value, c);
|
|
37
|
-
var batch = (fn) =>
|
|
38
|
-
|
|
39
|
-
if (!fxs) batched = /* @__PURE__ */ new Set();
|
|
40
|
-
try {
|
|
41
|
-
fn();
|
|
42
|
-
} finally {
|
|
43
|
-
if (!fxs) {
|
|
44
|
-
fxs = batched;
|
|
45
|
-
batched = null;
|
|
46
|
-
for (const fx of fxs) fx();
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
var untracked = (fn, prev, v) => (prev = current, current = null, v = fn(), current = prev, v);
|
|
36
|
+
var batch = (fn) => fn();
|
|
37
|
+
var untracked = batch;
|
|
51
38
|
function use(s) {
|
|
52
39
|
signal = s.signal;
|
|
53
40
|
effect = s.effect;
|
|
54
41
|
computed = s.computed;
|
|
55
|
-
batch = s.batch ||
|
|
42
|
+
batch = s.batch || batch;
|
|
56
43
|
untracked = s.untracked || batch;
|
|
57
44
|
}
|
|
58
45
|
|
|
59
46
|
// store.js
|
|
60
47
|
var _signals = Symbol("signals");
|
|
61
|
-
var _change = Symbol("
|
|
48
|
+
var _change = Symbol("change");
|
|
62
49
|
function store(values, parent) {
|
|
63
50
|
if (!values) return values;
|
|
64
51
|
if (values[_signals]) return values;
|
|
@@ -122,14 +109,13 @@ function set(signals, key, v) {
|
|
|
122
109
|
else if (s._set) s._set(v);
|
|
123
110
|
else if (Array.isArray(v) && Array.isArray(s.peek())) {
|
|
124
111
|
const cur = s.peek();
|
|
125
|
-
if (cur[_change])
|
|
112
|
+
if (cur[_change]) {
|
|
126
113
|
batch(() => {
|
|
127
114
|
let i = 0, l = v.length;
|
|
128
115
|
for (; i < l; i++) cur[i] = v[i];
|
|
129
116
|
cur.length = l;
|
|
130
117
|
});
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
118
|
+
} else {
|
|
133
119
|
s.value = v;
|
|
134
120
|
}
|
|
135
121
|
} else {
|
|
@@ -149,6 +135,7 @@ var _state = Symbol("state");
|
|
|
149
135
|
var _on = Symbol("on");
|
|
150
136
|
var _off = Symbol("off");
|
|
151
137
|
var directive = {};
|
|
138
|
+
var dir = (name, create, p = parse) => directive[name] = (el, expr, state, name2, update, evaluate) => (evaluate = p(expr), update = create(el, state, expr, name2), () => update(evaluate(state)));
|
|
152
139
|
function sprae(el, values) {
|
|
153
140
|
if (!el?.childNodes) return;
|
|
154
141
|
if (_state in el) {
|
|
@@ -168,13 +155,12 @@ function sprae(el, values) {
|
|
|
168
155
|
function init(el2) {
|
|
169
156
|
if (!el2.childNodes) return;
|
|
170
157
|
for (let i = 0; i < el2.attributes?.length; ) {
|
|
171
|
-
let attr2 = el2.attributes[i];
|
|
158
|
+
let attr2 = el2.attributes[i], update;
|
|
172
159
|
if (attr2.name[0] === ":") {
|
|
173
160
|
el2.removeAttribute(attr2.name);
|
|
174
161
|
for (let name of attr2.name.slice(1).split(":")) {
|
|
175
|
-
|
|
176
|
-
fx.push(update);
|
|
177
|
-
offs.push(effect(update));
|
|
162
|
+
update = (directive[name] || directive.default)(el2, attr2.value, state, name);
|
|
163
|
+
fx.push(update), offs.push(effect(update));
|
|
178
164
|
if (_state in el2) return;
|
|
179
165
|
}
|
|
180
166
|
} else i++;
|
|
@@ -184,19 +170,20 @@ function sprae(el, values) {
|
|
|
184
170
|
;
|
|
185
171
|
}
|
|
186
172
|
var memo = {};
|
|
187
|
-
var parse = (expr,
|
|
173
|
+
var parse = (expr, dir2) => {
|
|
174
|
+
let fn;
|
|
188
175
|
if (fn = memo[expr = expr.trim()]) return fn;
|
|
189
176
|
try {
|
|
190
177
|
fn = compile(expr);
|
|
191
178
|
} catch (e) {
|
|
192
|
-
err(e,
|
|
179
|
+
err(e, dir2, expr);
|
|
193
180
|
}
|
|
194
181
|
return memo[expr] = fn;
|
|
195
182
|
};
|
|
196
|
-
var err = (e,
|
|
183
|
+
var err = (e, dir2, expr = "") => {
|
|
197
184
|
throw Object.assign(e, { message: `\u2234 ${e.message}
|
|
198
185
|
|
|
199
|
-
${
|
|
186
|
+
${dir2}${expr ? `="${expr}"
|
|
200
187
|
|
|
201
188
|
` : ""}`, expr });
|
|
202
189
|
};
|
|
@@ -229,8 +216,9 @@ var frag = (tpl) => {
|
|
|
229
216
|
|
|
230
217
|
// directive/if.js
|
|
231
218
|
var _prevIf = Symbol("if");
|
|
232
|
-
|
|
233
|
-
|
|
219
|
+
dir("if", (el, state) => {
|
|
220
|
+
const holder = document.createTextNode("");
|
|
221
|
+
let next = el.nextElementSibling, curEl, ifEl, elseEl;
|
|
234
222
|
el.replaceWith(holder);
|
|
235
223
|
ifEl = el.content ? frag(el) : el;
|
|
236
224
|
ifEl[_state] = null;
|
|
@@ -238,8 +226,8 @@ directive.if = (el, evaluate, state) => {
|
|
|
238
226
|
next.removeAttribute(":else");
|
|
239
227
|
if (!next.hasAttribute(":if")) next.remove(), elseEl = next.content ? frag(next) : next, elseEl[_state] = null;
|
|
240
228
|
}
|
|
241
|
-
return () => {
|
|
242
|
-
const newEl =
|
|
229
|
+
return (value) => {
|
|
230
|
+
const newEl = value ? ifEl : el[_prevIf] ? null : elseEl;
|
|
243
231
|
if (next) next[_prevIf] = newEl === ifEl;
|
|
244
232
|
if (curEl != newEl) {
|
|
245
233
|
if (curEl) curEl.remove(), curEl[_off]?.();
|
|
@@ -250,41 +238,28 @@ directive.if = (el, evaluate, state) => {
|
|
|
250
238
|
}
|
|
251
239
|
}
|
|
252
240
|
};
|
|
253
|
-
};
|
|
241
|
+
});
|
|
254
242
|
|
|
255
243
|
// directive/each.js
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
tpl
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
let
|
|
264
|
-
|
|
265
|
-
if (items2?.constructor === Object) keys2 = Object.keys(items2), items2 = Object.values(items2);
|
|
266
|
-
return items2 || [];
|
|
267
|
-
});
|
|
268
|
-
const update = () => {
|
|
269
|
-
untracked(() => {
|
|
244
|
+
dir(
|
|
245
|
+
"each",
|
|
246
|
+
(tpl, state, expr) => {
|
|
247
|
+
const [itemVar, idxVar = "$"] = expr.split(/\s+in\s+/)[0].split(/\s*,\s*/);
|
|
248
|
+
const holder = document.createTextNode("");
|
|
249
|
+
tpl.replaceWith(holder);
|
|
250
|
+
tpl[_state] = null;
|
|
251
|
+
let cur, keys2, items, prevl = 0;
|
|
252
|
+
const update = () => {
|
|
270
253
|
var _a, _b;
|
|
271
|
-
let i = 0, newItems = items
|
|
254
|
+
let i = 0, newItems = items, newl = newItems.length;
|
|
272
255
|
if (cur && !cur[_change]) {
|
|
273
|
-
for (let s of cur[_signals] || [])
|
|
274
|
-
s[Symbol.dispose]();
|
|
275
|
-
}
|
|
256
|
+
for (let s of cur[_signals] || []) s[Symbol.dispose]();
|
|
276
257
|
cur = null, prevl = 0;
|
|
277
258
|
}
|
|
278
|
-
if (newl < prevl)
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
cur = newItems;
|
|
283
|
-
} else {
|
|
284
|
-
for (; i < prevl; i++) {
|
|
285
|
-
cur[i] = newItems[i];
|
|
286
|
-
}
|
|
287
|
-
}
|
|
259
|
+
if (newl < prevl) cur.length = newl;
|
|
260
|
+
else {
|
|
261
|
+
if (!cur) cur = newItems;
|
|
262
|
+
else while (i < prevl) cur[i] = newItems[i++];
|
|
288
263
|
for (; i < newl; i++) {
|
|
289
264
|
cur[i] = newItems[i];
|
|
290
265
|
let idx = i, scope = store({
|
|
@@ -299,48 +274,39 @@ directive.each = (tpl, [itemVar, idxVar, evaluate], state) => {
|
|
|
299
274
|
}
|
|
300
275
|
}
|
|
301
276
|
prevl = newl;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
277
|
+
};
|
|
278
|
+
return (value) => {
|
|
279
|
+
keys2 = null;
|
|
280
|
+
if (typeof value === "number") items = Array.from({ length: value }, (_, i) => i + 1);
|
|
281
|
+
else if (value?.constructor === Object) keys2 = Object.keys(value), items = Object.values(value);
|
|
282
|
+
else items = value || [];
|
|
283
|
+
let planned = 0;
|
|
284
|
+
return effect(() => {
|
|
285
|
+
items[_change]?.value;
|
|
286
|
+
if (!planned++) update(), queueMicrotask(() => (planned > 1 && update(), planned = 0));
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
},
|
|
290
|
+
// redefine evaluator to take second part of expression
|
|
291
|
+
(expr) => parse(expr.split(/\s+in\s+/)[1])
|
|
292
|
+
);
|
|
315
293
|
|
|
316
294
|
// directive/ref.js
|
|
317
|
-
|
|
318
|
-
return () => evaluate(state)?.call?.(null, el);
|
|
319
|
-
};
|
|
295
|
+
dir("ref", (el, state, expr) => (v) => v.call(null, el));
|
|
320
296
|
|
|
321
297
|
// directive/with.js
|
|
322
|
-
|
|
323
|
-
let state;
|
|
324
|
-
return () => {
|
|
325
|
-
let values = evaluate(rootState);
|
|
326
|
-
sprae(el, state ? values : state = store(values, rootState));
|
|
327
|
-
};
|
|
328
|
-
};
|
|
298
|
+
dir("with", (el, rootState, state) => (state = null, (values) => sprae(el, state ? values : state = store(values, rootState))));
|
|
329
299
|
|
|
330
300
|
// directive/text.js
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
el.textContent = value == null ? "" : value;
|
|
336
|
-
};
|
|
337
|
-
};
|
|
301
|
+
dir("text", (el) => (
|
|
302
|
+
// <template :text="a"/> or previously initialized template
|
|
303
|
+
(el.content && el.replaceWith(el = frag(el).childNodes[0]), (value) => el.textContent = value == null ? "" : value)
|
|
304
|
+
));
|
|
338
305
|
|
|
339
306
|
// directive/class.js
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
let v = evaluate(state);
|
|
307
|
+
dir(
|
|
308
|
+
"class",
|
|
309
|
+
(el, cur) => (cur = /* @__PURE__ */ new Set(), (v) => {
|
|
344
310
|
let clsx = /* @__PURE__ */ new Set();
|
|
345
311
|
if (v) {
|
|
346
312
|
if (typeof v === "string") v.split(" ").map((cls) => clsx.add(cls));
|
|
@@ -350,44 +316,36 @@ directive.class = (el, evaluate, state) => {
|
|
|
350
316
|
for (let cls of cur) if (clsx.has(cls)) clsx.delete(cls);
|
|
351
317
|
else el.classList.remove(cls);
|
|
352
318
|
for (let cls of cur = clsx) el.classList.add(cls);
|
|
353
|
-
}
|
|
354
|
-
|
|
319
|
+
})
|
|
320
|
+
);
|
|
355
321
|
|
|
356
322
|
// directive/style.js
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
let v = evaluate(state);
|
|
323
|
+
dir(
|
|
324
|
+
"style",
|
|
325
|
+
(el, initStyle) => (initStyle = el.getAttribute("style"), (v) => {
|
|
361
326
|
if (typeof v === "string") el.setAttribute("style", initStyle + (initStyle.endsWith(";") ? "" : "; ") + v);
|
|
362
327
|
else {
|
|
363
328
|
if (initStyle) el.setAttribute("style", initStyle);
|
|
364
329
|
for (let k in v) k[0] == "-" ? el.style.setProperty(k, v[k]) : el.style[k] = v[k];
|
|
365
330
|
}
|
|
366
|
-
}
|
|
367
|
-
|
|
331
|
+
})
|
|
332
|
+
);
|
|
368
333
|
|
|
369
334
|
// directive/default.js
|
|
370
|
-
|
|
371
|
-
if (!name.startsWith("on"))
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
};
|
|
335
|
+
dir("default", (target, state, expr, name) => {
|
|
336
|
+
if (!name.startsWith("on"))
|
|
337
|
+
return name ? (value) => attr(target, name, value) : (value) => {
|
|
338
|
+
for (let key in value) attr(target, dashcase(key), value[key]);
|
|
339
|
+
};
|
|
376
340
|
const ctxs = name.split("..").map((e) => {
|
|
377
341
|
let ctx = { evt: "", target, test: () => true };
|
|
378
342
|
ctx.evt = (e.startsWith("on") ? e.slice(2) : e).replace(
|
|
379
343
|
/\.(\w+)?-?([-\w]+)?/g,
|
|
380
|
-
(
|
|
344
|
+
(_, mod, param = "") => (ctx.test = mods[mod]?.(ctx, ...param.split("-")) || ctx.test, "")
|
|
381
345
|
);
|
|
382
346
|
return ctx;
|
|
383
347
|
});
|
|
384
|
-
|
|
385
|
-
let startFn, nextFn, off, idx = 0;
|
|
386
|
-
const nextListener = (fn) => {
|
|
387
|
-
off = addListener((e) => (off(), nextFn = fn?.(e), (idx = ++idx % ctxs.length) ? nextListener(nextFn) : startFn && nextListener(startFn)), ctxs[idx]);
|
|
388
|
-
};
|
|
389
|
-
return () => (startFn = evaluate(state), !off && nextListener(startFn), () => startFn = null);
|
|
390
|
-
function addListener(fn, { evt, target: target2, test, defer, stop, prevent, immediate, ...opts }) {
|
|
348
|
+
const addListener = (fn, { evt, target: target2, test, defer, stop, prevent, immediate, ...opts }) => {
|
|
391
349
|
if (defer) fn = defer(fn);
|
|
392
350
|
const cb = (e) => {
|
|
393
351
|
try {
|
|
@@ -398,9 +356,14 @@ directive.default = (target, evaluate, state, name) => {
|
|
|
398
356
|
};
|
|
399
357
|
target2.addEventListener(evt, cb, opts);
|
|
400
358
|
return () => target2.removeEventListener(evt, cb, opts);
|
|
401
|
-
}
|
|
402
|
-
;
|
|
403
|
-
|
|
359
|
+
};
|
|
360
|
+
if (ctxs.length == 1) return (v) => addListener(v, ctxs[0]);
|
|
361
|
+
let startFn, nextFn, off, idx = 0;
|
|
362
|
+
const nextListener = (fn) => {
|
|
363
|
+
off = addListener((e) => (off(), nextFn = fn?.(e), (idx = ++idx % ctxs.length) ? nextListener(nextFn) : startFn && nextListener(startFn)), ctxs[idx]);
|
|
364
|
+
};
|
|
365
|
+
return (value) => (startFn = value, !off && nextListener(startFn), () => startFn = null);
|
|
366
|
+
});
|
|
404
367
|
var mods = {
|
|
405
368
|
// actions
|
|
406
369
|
prevent(ctx) {
|
|
@@ -478,10 +441,6 @@ var keys = {
|
|
|
478
441
|
letter: (e) => /^\p{L}$/gu.test(e.key),
|
|
479
442
|
char: (e) => /^\S$/.test(e.key)
|
|
480
443
|
};
|
|
481
|
-
var attr = (el, name, v) => {
|
|
482
|
-
if (v == null || v === false) el.removeAttribute(name);
|
|
483
|
-
else el.setAttribute(name, v === true ? "" : typeof v === "number" || typeof v === "string" ? v : "");
|
|
484
|
-
};
|
|
485
444
|
var throttle = (fn, limit) => {
|
|
486
445
|
let pause, planned, block = (e) => {
|
|
487
446
|
pause = true;
|
|
@@ -506,12 +465,16 @@ var debounce = (fn, wait) => {
|
|
|
506
465
|
}, wait);
|
|
507
466
|
};
|
|
508
467
|
};
|
|
468
|
+
var attr = (el, name, v) => {
|
|
469
|
+
if (v == null || v === false) el.removeAttribute(name);
|
|
470
|
+
else el.setAttribute(name, v === true ? "" : typeof v === "number" || typeof v === "string" ? v : "");
|
|
471
|
+
};
|
|
509
472
|
var dashcase = (str) => {
|
|
510
473
|
return str.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g, (match, i) => (i ? "-" : "") + match.toLowerCase());
|
|
511
474
|
};
|
|
512
475
|
|
|
513
476
|
// directive/value.js
|
|
514
|
-
|
|
477
|
+
dir("value", (el, state, expr) => {
|
|
515
478
|
const update = el.type === "text" || el.type === "" ? (value) => el.setAttribute("value", el.value = value == null ? "" : value) : el.tagName === "TEXTAREA" || el.type === "text" || el.type === "" ? (value, from, to) => (
|
|
516
479
|
// we retain selection in input
|
|
517
480
|
(from = el.selectionStart, to = el.selectionEnd, el.setAttribute("value", el.value = value == null ? "" : value), from && el.setSelectionRange(from, to))
|
|
@@ -523,50 +486,39 @@ directive.value = (el, [getValue, setValue], state) => {
|
|
|
523
486
|
for (let o of el.options) o.removeAttribute("selected");
|
|
524
487
|
for (let v of value) el.querySelector(`[value="${v}"]`).setAttribute("selected", "");
|
|
525
488
|
} : (value) => el.value = value;
|
|
526
|
-
|
|
489
|
+
let set2 = setter(expr);
|
|
490
|
+
const handleChange = el.type === "checkbox" ? () => set2(state, el.checked) : el.type === "select-multiple" ? () => set2(state, [...el.selectedOptions].map((o) => o.value)) : () => set2(state, el.selectedIndex < 0 ? null : el.value);
|
|
527
491
|
el.oninput = el.onchange = handleChange;
|
|
528
492
|
if (el.type?.startsWith("select")) {
|
|
529
493
|
new MutationObserver(handleChange).observe(el, { childList: true, subtree: true, attributes: true });
|
|
530
494
|
sprae(el, state);
|
|
531
495
|
}
|
|
532
|
-
return
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
};
|
|
536
|
-
directive.value.parse = (expr) => {
|
|
537
|
-
let evaluate = [parse(expr)];
|
|
496
|
+
return update;
|
|
497
|
+
});
|
|
498
|
+
var setter = (expr) => {
|
|
538
499
|
try {
|
|
539
500
|
const set2 = parse(`${expr}=__`);
|
|
540
|
-
|
|
501
|
+
return (state, value) => {
|
|
541
502
|
state.__ = value;
|
|
542
503
|
set2(state, value);
|
|
543
504
|
delete state.__;
|
|
544
|
-
}
|
|
505
|
+
};
|
|
545
506
|
} catch (e) {
|
|
546
507
|
}
|
|
547
|
-
return evaluate;
|
|
548
508
|
};
|
|
549
509
|
|
|
550
510
|
// directive/fx.js
|
|
551
|
-
|
|
552
|
-
return () => evaluate(state);
|
|
553
|
-
};
|
|
511
|
+
dir("fx", (_) => (_2) => _2);
|
|
554
512
|
|
|
555
513
|
// directive/aria.js
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
};
|
|
560
|
-
return () => update(evaluate(state));
|
|
561
|
-
};
|
|
514
|
+
dir("aria", (el) => (value) => {
|
|
515
|
+
for (let key in value) attr(el, "aria-" + dashcase(key), value[key] == null ? null : value[key] + "");
|
|
516
|
+
});
|
|
562
517
|
|
|
563
518
|
// directive/data.js
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
for (let key in value) el.dataset[key] = value[key];
|
|
568
|
-
};
|
|
569
|
-
};
|
|
519
|
+
dir("data", (el) => (value) => {
|
|
520
|
+
for (let key in value) el.dataset[key] = value[key];
|
|
521
|
+
});
|
|
570
522
|
|
|
571
523
|
// sprae.js
|
|
572
524
|
sprae.use({ compile: (expr) => sprae.constructor(`with (arguments[0]) { return ${expr} };`) });
|