simplyflow 0.8.1 → 0.9.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/dist/simply.flow.js +272 -152
- package/dist/simply.flow.min.js +1 -1
- package/dist/simply.flow.min.js.map +4 -4
- package/package.json +1 -1
- package/src/bind.mjs +3 -5
- package/src/bind.render.mjs +21 -64
- package/src/dom.mjs +107 -6
- package/src/edit/anchor.mjs +130 -0
- package/src/edit/toolbars.mjs +315 -0
- package/src/edit.mjs +168 -83
- package/src/model.mjs +2 -1
- package/src/state.mjs +205 -95
- package/src/symbols.mjs +8 -0
package/dist/simply.flow.js
CHANGED
|
@@ -23,47 +23,83 @@
|
|
|
23
23
|
trace: () => trace,
|
|
24
24
|
untracked: () => untracked
|
|
25
25
|
});
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
// src/symbols.mjs
|
|
28
|
+
var DEP = {
|
|
29
|
+
ITERATE: Symbol.for("@simplyedit/simplyflow.iterate"),
|
|
30
|
+
XRAY: Symbol.for("@simplyedit/simplyflow.xRay"),
|
|
31
|
+
SIGNAL: Symbol.for("@simplyedit/simplyflow.Signal"),
|
|
32
|
+
TEMPLATE: Symbol.for("@simplyedit/simplyflow.bindTemplate"),
|
|
33
|
+
LENGTH: "length",
|
|
34
|
+
SIZE: "size"
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/state.mjs
|
|
38
|
+
function wrapMapMethod(target, property, receiver, value) {
|
|
39
|
+
return (...args) => {
|
|
40
|
+
if (property === "get" || property === "has") {
|
|
41
|
+
notifyGet(receiver, args[0]);
|
|
42
|
+
}
|
|
43
|
+
if (["keys", "values", "entries", "forEach", Symbol.iterator].includes(property)) {
|
|
44
|
+
notifyGet(receiver, DEP.ITERATE);
|
|
45
|
+
}
|
|
46
|
+
const oldSize = target.size;
|
|
47
|
+
const result = value.apply(target, args);
|
|
48
|
+
if (property === "set") {
|
|
49
|
+
notifySet(receiver, makeContext(args[0], { now: args[1] }));
|
|
50
|
+
}
|
|
51
|
+
if (property === "delete") {
|
|
52
|
+
notifySet(receiver, makeContext(args[0], { delete: true }));
|
|
53
|
+
}
|
|
54
|
+
if (oldSize !== target.size) {
|
|
55
|
+
notifySet(receiver, makeContext(DEP.SIZE, {}));
|
|
56
|
+
}
|
|
57
|
+
if (["set", "delete", "clear"].includes(property) || oldSize !== target.size) {
|
|
58
|
+
notifySet(receiver, makeContext(DEP.ITERATE, {}));
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
};
|
|
28
62
|
}
|
|
29
|
-
|
|
30
|
-
|
|
63
|
+
function wrapArrayMethod(target, property, receiver, value) {
|
|
64
|
+
return (...args) => {
|
|
65
|
+
let l = target.length;
|
|
66
|
+
let result = value.apply(receiver, args);
|
|
67
|
+
if (l != target.length) {
|
|
68
|
+
notifySet(receiver, makeContext(DEP.LENGTH, { was: l, now: target.length }));
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
};
|
|
31
72
|
}
|
|
32
|
-
|
|
33
|
-
|
|
73
|
+
function wrapSetMethod(target, property, receiver, value) {
|
|
74
|
+
return (...args) => {
|
|
75
|
+
let s = target.size;
|
|
76
|
+
let result = value.apply(target, args);
|
|
77
|
+
if (s != target.size) {
|
|
78
|
+
notifySet(receiver, makeContext(DEP.SIZE, { was: s, now: target.size }));
|
|
79
|
+
}
|
|
80
|
+
if (["set", "add", "clear", "delete"].includes(property)) {
|
|
81
|
+
notifySet(receiver, makeContext({ entries: {}, forEach: {}, has: {}, keys: {}, values: {}, [Symbol.iterator]: {} }));
|
|
82
|
+
}
|
|
83
|
+
return result;
|
|
84
|
+
};
|
|
34
85
|
}
|
|
35
86
|
var signalHandler = {
|
|
36
87
|
get: (target, property, receiver) => {
|
|
37
|
-
if (property ===
|
|
88
|
+
if (property === DEP.XRAY) {
|
|
38
89
|
return target;
|
|
39
90
|
}
|
|
40
|
-
if (property ===
|
|
91
|
+
if (property === DEP.SIGNAL) {
|
|
41
92
|
return true;
|
|
42
93
|
}
|
|
43
94
|
const value = target?.[property];
|
|
44
95
|
notifyGet(receiver, property);
|
|
45
96
|
if (typeof value === "function") {
|
|
46
97
|
if (Array.isArray(target)) {
|
|
47
|
-
return (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
return result;
|
|
54
|
-
};
|
|
55
|
-
} else if (target instanceof Set || target instanceof Map) {
|
|
56
|
-
return (...args) => {
|
|
57
|
-
let s = target.size;
|
|
58
|
-
let result = value.apply(target, args);
|
|
59
|
-
if (s != target.size) {
|
|
60
|
-
notifySet(receiver, makeContext("size", { was: s, now: target.size }));
|
|
61
|
-
}
|
|
62
|
-
if (["set", "add", "clear", "delete"].includes(property)) {
|
|
63
|
-
notifySet(receiver, makeContext({ entries: {}, forEach: {}, has: {}, keys: {}, values: {}, [Symbol.iterator]: {} }));
|
|
64
|
-
}
|
|
65
|
-
return result;
|
|
66
|
-
};
|
|
98
|
+
return wrapArrayMethod(target, property, receiver, value);
|
|
99
|
+
} else if (target instanceof Map) {
|
|
100
|
+
return wrapMapMethod(target, property, receiver, value);
|
|
101
|
+
} else if (target instanceof Set) {
|
|
102
|
+
return wrapSetMethod(target, property, receiver, value);
|
|
67
103
|
} else if (target instanceof HTMLElement || target instanceof Number || target instanceof String || target instanceof Boolean) {
|
|
68
104
|
return value.bind(target);
|
|
69
105
|
} else {
|
|
@@ -82,8 +118,8 @@
|
|
|
82
118
|
notifySet(receiver, makeContext(property, { was: current, now: value }));
|
|
83
119
|
}
|
|
84
120
|
if (typeof current === "undefined") {
|
|
85
|
-
notifySet(receiver, makeContext(
|
|
86
|
-
notifySet(receiver, makeContext(
|
|
121
|
+
notifySet(receiver, makeContext(DEP.ITERATE, {}));
|
|
122
|
+
notifySet(receiver, makeContext(DEP.LENGTH, {}));
|
|
87
123
|
}
|
|
88
124
|
return true;
|
|
89
125
|
},
|
|
@@ -100,28 +136,34 @@
|
|
|
100
136
|
delete target[property];
|
|
101
137
|
let receiver = signals.get(target);
|
|
102
138
|
notifySet(receiver, makeContext(property, { delete: true, was: current }));
|
|
139
|
+
notifySet(
|
|
140
|
+
receiver,
|
|
141
|
+
makeContext(DEP.ITERATE, { delete: true, property })
|
|
142
|
+
);
|
|
103
143
|
}
|
|
104
144
|
return true;
|
|
105
145
|
},
|
|
106
146
|
defineProperty: (target, property, descriptor) => {
|
|
107
147
|
if (typeof target[property] === "undefined") {
|
|
108
148
|
let receiver = signals.get(target);
|
|
109
|
-
notifySet(receiver, makeContext(
|
|
149
|
+
notifySet(receiver, makeContext(DEP.ITERATE, {}));
|
|
110
150
|
}
|
|
111
151
|
return Object.defineProperty(target, property, descriptor);
|
|
112
152
|
},
|
|
113
153
|
ownKeys: (target) => {
|
|
114
154
|
let receiver = signals.get(target);
|
|
115
|
-
notifyGet(receiver,
|
|
155
|
+
notifyGet(receiver, DEP.ITERATE);
|
|
116
156
|
return Reflect.ownKeys(target);
|
|
117
157
|
}
|
|
118
158
|
};
|
|
119
159
|
var signals = /* @__PURE__ */ new WeakMap();
|
|
120
|
-
function signal(v) {
|
|
121
|
-
if (
|
|
122
|
-
|
|
160
|
+
function signal(v = {}) {
|
|
161
|
+
if (v === null || typeof v !== "object" && typeof v !== "function") {
|
|
162
|
+
throw new TypeError(
|
|
163
|
+
`simplyflow/state: signal() expects an object, array, Map, Set, class instance, or function; received ${typeof v}`
|
|
164
|
+
);
|
|
123
165
|
}
|
|
124
|
-
if (v[
|
|
166
|
+
if (v[DEP.SIGNAL]) {
|
|
125
167
|
return v;
|
|
126
168
|
}
|
|
127
169
|
if (!signals.has(v)) {
|
|
@@ -131,23 +173,33 @@
|
|
|
131
173
|
}
|
|
132
174
|
var tracers = [];
|
|
133
175
|
var tracing = false;
|
|
134
|
-
function trace(
|
|
135
|
-
if (typeof
|
|
176
|
+
function trace(target, prop) {
|
|
177
|
+
if (typeof target === "function") {
|
|
136
178
|
tracing = true;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
179
|
+
try {
|
|
180
|
+
return target();
|
|
181
|
+
} finally {
|
|
182
|
+
tracing = false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (!target || !target[DEP.SIGNAL]) {
|
|
186
|
+
throw new TypeError(
|
|
187
|
+
"simplyflow/state: trace() expects either a function or a signal"
|
|
188
|
+
);
|
|
148
189
|
}
|
|
190
|
+
const listeners = getListeners(target, prop);
|
|
191
|
+
return listeners.map((listener) => {
|
|
192
|
+
return {
|
|
193
|
+
effect: listener.effectType,
|
|
194
|
+
fn: listener.effectFunction,
|
|
195
|
+
signal: signals.get(listener.effectFunction)
|
|
196
|
+
};
|
|
197
|
+
});
|
|
149
198
|
}
|
|
150
199
|
function addTracer(tracer) {
|
|
200
|
+
if (!tracer || typeof tracer !== "object") {
|
|
201
|
+
throw new TypeError("simplyflow/state: addTracer() expects a tracer object");
|
|
202
|
+
}
|
|
151
203
|
if (!tracer.get && !tracer.set) {
|
|
152
204
|
throw new Error('simply.state: addTracer: missing "get" or "set" property in tracer', tracer);
|
|
153
205
|
}
|
|
@@ -168,7 +220,13 @@
|
|
|
168
220
|
}
|
|
169
221
|
var batchedListeners = /* @__PURE__ */ new Set();
|
|
170
222
|
var batchMode = 0;
|
|
171
|
-
function notifySet(self, context =
|
|
223
|
+
function notifySet(self, context = /* @__PURE__ */ new Map()) {
|
|
224
|
+
if (!self || !self[DEP.SIGNAL]) {
|
|
225
|
+
throw new TypeError("simplyflow/state: notifySet() expects a signal as first argument");
|
|
226
|
+
}
|
|
227
|
+
if (!(context instanceof Map)) {
|
|
228
|
+
throw new TypeError("simplyflow/state: notifySet() expects context to be a Map; use makeContext()");
|
|
229
|
+
}
|
|
172
230
|
let listeners = [];
|
|
173
231
|
context.forEach((change, property) => {
|
|
174
232
|
let propListeners = getListeners(self, property);
|
|
@@ -199,8 +257,14 @@
|
|
|
199
257
|
}
|
|
200
258
|
function makeContext(property, change) {
|
|
201
259
|
let context = /* @__PURE__ */ new Map();
|
|
202
|
-
if (
|
|
203
|
-
|
|
260
|
+
if (property instanceof Map) {
|
|
261
|
+
property.forEach((change2, prop) => {
|
|
262
|
+
context.set(prop, change2);
|
|
263
|
+
});
|
|
264
|
+
return context;
|
|
265
|
+
}
|
|
266
|
+
if (property !== null && typeof property === "object") {
|
|
267
|
+
for (const prop of Reflect.ownKeys(property)) {
|
|
204
268
|
context.set(prop, property[prop]);
|
|
205
269
|
}
|
|
206
270
|
} else {
|
|
@@ -256,23 +320,31 @@
|
|
|
256
320
|
connectedSignals.get(property).add(self);
|
|
257
321
|
}
|
|
258
322
|
function clearListeners(compute) {
|
|
259
|
-
|
|
260
|
-
if (connectedSignals) {
|
|
261
|
-
|
|
262
|
-
property.forEach((s) => {
|
|
263
|
-
let listeners = listenersMap.get(s);
|
|
264
|
-
if (listeners.has(property)) {
|
|
265
|
-
listeners.get(property).delete(compute);
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
});
|
|
323
|
+
const connectedSignals = computeMap.get(compute);
|
|
324
|
+
if (!connectedSignals) {
|
|
325
|
+
return;
|
|
269
326
|
}
|
|
327
|
+
connectedSignals.forEach((signals2, property) => {
|
|
328
|
+
signals2.forEach((signal3) => {
|
|
329
|
+
const listeners = listenersMap.get(signal3);
|
|
330
|
+
if (listeners?.has(property)) {
|
|
331
|
+
listeners.get(property).delete(compute);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
computeMap.delete(compute);
|
|
270
336
|
}
|
|
271
337
|
var computeStack = [];
|
|
272
338
|
var effectStack = [];
|
|
273
339
|
var effectMap = /* @__PURE__ */ new WeakMap();
|
|
274
340
|
var signalStack = [];
|
|
341
|
+
function assertFunction(fn, name) {
|
|
342
|
+
if (typeof fn !== "function") {
|
|
343
|
+
throw new TypeError(`simplyflow/state: ${name}() expects a function`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
275
346
|
function effect(fn) {
|
|
347
|
+
assertFunction(fn, "effect");
|
|
276
348
|
if (effectStack.findIndex((f) => fn == f) !== -1) {
|
|
277
349
|
throw new Error("Recursive update() call", { cause: fn });
|
|
278
350
|
}
|
|
@@ -314,16 +386,21 @@
|
|
|
314
386
|
return connectedSignal;
|
|
315
387
|
}
|
|
316
388
|
function destroy(connectedSignal) {
|
|
317
|
-
|
|
389
|
+
if (!connectedSignal || !connectedSignal[DEP.SIGNAL]) {
|
|
390
|
+
throw new TypeError("simplyflow/state: destroy() expects an effect signal");
|
|
391
|
+
}
|
|
392
|
+
const computeEffect = effectMap.get(connectedSignal);
|
|
318
393
|
if (!computeEffect) {
|
|
319
394
|
return;
|
|
320
395
|
}
|
|
321
396
|
clearListeners(computeEffect);
|
|
322
|
-
|
|
323
|
-
|
|
397
|
+
if (computeEffect.fn) {
|
|
398
|
+
signals.delete(computeEffect.fn);
|
|
399
|
+
}
|
|
324
400
|
effectMap.delete(connectedSignal);
|
|
325
401
|
}
|
|
326
402
|
function batch(fn) {
|
|
403
|
+
assertFunction(fn, "batch");
|
|
327
404
|
batchMode++;
|
|
328
405
|
let result;
|
|
329
406
|
try {
|
|
@@ -357,6 +434,12 @@
|
|
|
357
434
|
}
|
|
358
435
|
}
|
|
359
436
|
function throttledEffect(fn, throttleTime) {
|
|
437
|
+
assertFunction(fn, "throttledEffect");
|
|
438
|
+
if (!Number.isFinite(throttleTime) || throttleTime < 0) {
|
|
439
|
+
throw new TypeError(
|
|
440
|
+
`simplyflow/state: throttledEffect() expects throttleTime to be a non-negative number`
|
|
441
|
+
);
|
|
442
|
+
}
|
|
360
443
|
if (effectStack.findIndex((f) => fn == f) !== -1) {
|
|
361
444
|
throw new Error("Recursive update() call", { cause: fn });
|
|
362
445
|
}
|
|
@@ -368,16 +451,31 @@
|
|
|
368
451
|
});
|
|
369
452
|
signals.set(fn, connectedSignal);
|
|
370
453
|
}
|
|
371
|
-
let
|
|
454
|
+
let throttledUntil = 0;
|
|
372
455
|
let hasChange = true;
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
456
|
+
let timeout = null;
|
|
457
|
+
function schedule() {
|
|
458
|
+
if (timeout) {
|
|
459
|
+
return;
|
|
376
460
|
}
|
|
377
|
-
|
|
461
|
+
const delay = Math.max(0, throttledUntil - Date.now());
|
|
462
|
+
timeout = globalThis.setTimeout(() => {
|
|
463
|
+
timeout = null;
|
|
464
|
+
if (hasChange) {
|
|
465
|
+
computeEffect();
|
|
466
|
+
}
|
|
467
|
+
}, delay);
|
|
468
|
+
}
|
|
469
|
+
const computeEffect = function computeEffect2() {
|
|
470
|
+
const now = Date.now();
|
|
471
|
+
if (throttledUntil > now) {
|
|
378
472
|
hasChange = true;
|
|
473
|
+
schedule();
|
|
379
474
|
return;
|
|
380
475
|
}
|
|
476
|
+
if (signalStack.findIndex((s) => s == connectedSignal) !== -1) {
|
|
477
|
+
throw new Error("Cyclical dependency in update() call", { cause: fn });
|
|
478
|
+
}
|
|
381
479
|
clearListeners(computeEffect2);
|
|
382
480
|
computeEffect2.effectFunction = fn;
|
|
383
481
|
computeEffect2.effectType = throttledEffect;
|
|
@@ -398,17 +496,19 @@
|
|
|
398
496
|
connectedSignal.current = result;
|
|
399
497
|
}
|
|
400
498
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
if (hasChange) {
|
|
404
|
-
computeEffect2();
|
|
405
|
-
}
|
|
406
|
-
}, throttleTime);
|
|
499
|
+
throttledUntil = Date.now() + throttleTime;
|
|
500
|
+
schedule();
|
|
407
501
|
};
|
|
408
502
|
computeEffect();
|
|
409
503
|
return connectedSignal;
|
|
410
504
|
}
|
|
411
505
|
function clockEffect(fn, clock) {
|
|
506
|
+
assertFunction(fn, "clockEffect");
|
|
507
|
+
if (!clock || typeof clock !== "object" || typeof clock.time !== "number") {
|
|
508
|
+
throw new TypeError(
|
|
509
|
+
`simplyflow/state: clockEffect() expects a clock object with a numeric .time property`
|
|
510
|
+
);
|
|
511
|
+
}
|
|
412
512
|
let connectedSignal = signals.get(fn);
|
|
413
513
|
if (!connectedSignal) {
|
|
414
514
|
connectedSignal = signal({
|
|
@@ -451,6 +551,7 @@
|
|
|
451
551
|
return connectedSignal;
|
|
452
552
|
}
|
|
453
553
|
function untracked(fn) {
|
|
554
|
+
assertFunction(fn, "untracked");
|
|
454
555
|
const pos = computeStack.length - 1;
|
|
455
556
|
const remember = computeStack[pos];
|
|
456
557
|
computeStack[pos] = false;
|
|
@@ -472,16 +573,15 @@
|
|
|
472
573
|
return value2;
|
|
473
574
|
}
|
|
474
575
|
if (Array.isArray(value2)) {
|
|
475
|
-
|
|
576
|
+
const result = [];
|
|
476
577
|
if (!deep) {
|
|
477
|
-
|
|
478
|
-
seen.set(value2, result);
|
|
479
|
-
return result;
|
|
578
|
+
return value2.slice();
|
|
480
579
|
}
|
|
481
580
|
seen.set(value2, result);
|
|
482
|
-
for (
|
|
483
|
-
result[
|
|
581
|
+
for (let i = 0; i < value2.length; i++) {
|
|
582
|
+
result[i] = innerClone(value2[i]);
|
|
484
583
|
}
|
|
584
|
+
return result;
|
|
485
585
|
} else if (!value2.constructor || value2.constructor === Object) {
|
|
486
586
|
let result = {};
|
|
487
587
|
if (!value2.constructor) {
|
|
@@ -497,7 +597,7 @@
|
|
|
497
597
|
}
|
|
498
598
|
break;
|
|
499
599
|
default:
|
|
500
|
-
return
|
|
600
|
+
return value2;
|
|
501
601
|
break;
|
|
502
602
|
}
|
|
503
603
|
};
|
|
@@ -529,14 +629,18 @@
|
|
|
529
629
|
// src/dom.mjs
|
|
530
630
|
var dom_exports = {};
|
|
531
631
|
__export(dom_exports, {
|
|
532
|
-
signal: () => signal2
|
|
632
|
+
signal: () => signal2,
|
|
633
|
+
trackDomField: () => trackDomField,
|
|
634
|
+
trackDomList: () => trackDomList
|
|
533
635
|
});
|
|
636
|
+
var domSignals = /* @__PURE__ */ new WeakMap();
|
|
637
|
+
var observers = /* @__PURE__ */ new WeakMap();
|
|
534
638
|
var domSignalHandler = {
|
|
535
639
|
get: (target, property, receiver) => {
|
|
536
|
-
if (property ===
|
|
640
|
+
if (property === DEP.XRAY) {
|
|
537
641
|
return target;
|
|
538
642
|
}
|
|
539
|
-
if (property ===
|
|
643
|
+
if (property === DEP.SIGNAL) {
|
|
540
644
|
return true;
|
|
541
645
|
}
|
|
542
646
|
const value = target?.[property];
|
|
@@ -565,7 +669,7 @@
|
|
|
565
669
|
}
|
|
566
670
|
};
|
|
567
671
|
function signal2(el, options) {
|
|
568
|
-
if (el[
|
|
672
|
+
if (el[DEP.XRAY]) {
|
|
569
673
|
return el;
|
|
570
674
|
}
|
|
571
675
|
if (!signals.has(el)) {
|
|
@@ -574,7 +678,6 @@
|
|
|
574
678
|
}
|
|
575
679
|
return signals.get(el);
|
|
576
680
|
}
|
|
577
|
-
var observers = /* @__PURE__ */ new WeakMap();
|
|
578
681
|
function domListen(el, signal3, options) {
|
|
579
682
|
const defaultOptions = {
|
|
580
683
|
characterData: true,
|
|
@@ -634,6 +737,67 @@
|
|
|
634
737
|
}
|
|
635
738
|
}
|
|
636
739
|
}
|
|
740
|
+
function trackDomList(element2) {
|
|
741
|
+
const path = this.getBindingPath(element2);
|
|
742
|
+
if (!path) {
|
|
743
|
+
throw new Error("Could not find binding path for element", { cause: element2 });
|
|
744
|
+
}
|
|
745
|
+
const s = signal2(element2, {
|
|
746
|
+
childList: true
|
|
747
|
+
});
|
|
748
|
+
throttledEffect(() => {
|
|
749
|
+
const children = Array.from(s.children);
|
|
750
|
+
untracked(() => {
|
|
751
|
+
batch(() => {
|
|
752
|
+
let key = 0;
|
|
753
|
+
const currentList = getValueByPath(this.options.root, path);
|
|
754
|
+
const source = currentList.slice();
|
|
755
|
+
for (const item of children) {
|
|
756
|
+
if (item.tagName === "TEMPLATE") {
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
if (item.dataset.flowKey) {
|
|
760
|
+
if (item.dataset.flowKey != key) {
|
|
761
|
+
setValueByPath(
|
|
762
|
+
this.options.root,
|
|
763
|
+
path + "." + key,
|
|
764
|
+
source[item.dataset.flowKey]
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
key++;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
if (currentList.length > key) {
|
|
771
|
+
currentList.length = key;
|
|
772
|
+
}
|
|
773
|
+
});
|
|
774
|
+
});
|
|
775
|
+
});
|
|
776
|
+
return s;
|
|
777
|
+
}
|
|
778
|
+
function trackDomField(element2, props, valueIsString) {
|
|
779
|
+
if (domSignals.has(element2)) {
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
const path = this.getBindingPath(element2);
|
|
783
|
+
if (!path) {
|
|
784
|
+
throw new Error("Could not find binding path for element", { cause: element2 });
|
|
785
|
+
}
|
|
786
|
+
const s = signal2(element2);
|
|
787
|
+
domSignals.set(element2, s);
|
|
788
|
+
batch(() => {
|
|
789
|
+
throttledEffect(() => {
|
|
790
|
+
let updateValue = s.innerHTML;
|
|
791
|
+
if (!valueIsString) {
|
|
792
|
+
updateValue = getProperties(s, ...props);
|
|
793
|
+
}
|
|
794
|
+
untracked(() => {
|
|
795
|
+
setValueByPath(this.options.root, path, updateValue);
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
});
|
|
799
|
+
return s;
|
|
800
|
+
}
|
|
637
801
|
|
|
638
802
|
// src/bind.render.mjs
|
|
639
803
|
function field(context) {
|
|
@@ -732,6 +896,8 @@
|
|
|
732
896
|
}
|
|
733
897
|
function arrayByTemplates(context) {
|
|
734
898
|
const attribute = this.options.attribute;
|
|
899
|
+
const attributes = [attribute + "-field", attribute + "-list", attribute + "-map"];
|
|
900
|
+
const attrQuery = "[" + attributes.join("],[") + "]";
|
|
735
901
|
let items = context.element.querySelectorAll(":scope > [" + attribute + "-key]");
|
|
736
902
|
let lastKey = 0;
|
|
737
903
|
let skipped = 0;
|
|
@@ -744,18 +910,23 @@
|
|
|
744
910
|
} else if (currentKey < lastKey) {
|
|
745
911
|
item.remove();
|
|
746
912
|
} else {
|
|
747
|
-
let bindings = Array.from(item.querySelectorAll(
|
|
748
|
-
if (item.matches(
|
|
913
|
+
let bindings = Array.from(item.querySelectorAll(attrQuery));
|
|
914
|
+
if (item.matches(attrQuery)) {
|
|
749
915
|
bindings.unshift(item);
|
|
750
916
|
}
|
|
751
917
|
let needsReplacement = bindings.find((b) => {
|
|
752
|
-
let
|
|
753
|
-
|
|
918
|
+
for (let attr of attributes) {
|
|
919
|
+
let databind = b.getAttribute(attr);
|
|
920
|
+
if (databind && databind.substr(0, 5) !== ":root" && databind.substr(0, context.path.length) !== context.path) {
|
|
921
|
+
return true;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return false;
|
|
754
925
|
});
|
|
755
926
|
if (!needsReplacement) {
|
|
756
|
-
if (item[
|
|
927
|
+
if (item[DEP.TEMPLATE]) {
|
|
757
928
|
let newTemplate = this.findTemplate(context.templates, context.list[lastKey]);
|
|
758
|
-
if (newTemplate != item[
|
|
929
|
+
if (newTemplate != item[DEP.TEMPLATE]) {
|
|
759
930
|
needsReplacement = true;
|
|
760
931
|
if (!newTemplate) {
|
|
761
932
|
skipped++;
|
|
@@ -789,37 +960,7 @@
|
|
|
789
960
|
}
|
|
790
961
|
}
|
|
791
962
|
if (this.options.twoway) {
|
|
792
|
-
|
|
793
|
-
childList: true
|
|
794
|
-
});
|
|
795
|
-
throttledEffect(() => {
|
|
796
|
-
const children = Array.from(s.children);
|
|
797
|
-
batch(() => {
|
|
798
|
-
untracked(() => {
|
|
799
|
-
let key = 0;
|
|
800
|
-
const currentList = context.value.slice();
|
|
801
|
-
for (const item of children) {
|
|
802
|
-
if (item.tagName === "TEMPLATE") {
|
|
803
|
-
continue;
|
|
804
|
-
}
|
|
805
|
-
if (item.dataset.flowKey) {
|
|
806
|
-
if (item.dataset.flowKey != key) {
|
|
807
|
-
setValueByPath(
|
|
808
|
-
this.options.root,
|
|
809
|
-
context.path + "." + key,
|
|
810
|
-
currentList[item.dataset.flowKey]
|
|
811
|
-
);
|
|
812
|
-
}
|
|
813
|
-
key++;
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
if (context.value.length > key) {
|
|
817
|
-
const source = getValueByPath(this.options.root, context.path);
|
|
818
|
-
source.length = key;
|
|
819
|
-
}
|
|
820
|
-
});
|
|
821
|
-
});
|
|
822
|
-
});
|
|
963
|
+
trackDomList.call(this, context.element);
|
|
823
964
|
}
|
|
824
965
|
}
|
|
825
966
|
function objectByTemplates(context) {
|
|
@@ -848,7 +989,7 @@
|
|
|
848
989
|
}
|
|
849
990
|
}
|
|
850
991
|
let newTemplate = this.findTemplate(context.templates, context.list[context.index]);
|
|
851
|
-
if (newTemplate != item[
|
|
992
|
+
if (newTemplate != item[DEP.TEMPLATE]) {
|
|
852
993
|
let clone2 = this.applyTemplate(context);
|
|
853
994
|
context.element.replaceChild(clone2, item);
|
|
854
995
|
}
|
|
@@ -864,7 +1005,7 @@
|
|
|
864
1005
|
context.parent = getParentPath(context.element);
|
|
865
1006
|
if (rendered) {
|
|
866
1007
|
if (template) {
|
|
867
|
-
if (rendered?.[
|
|
1008
|
+
if (rendered?.[DEP.TEMPLATE] != template) {
|
|
868
1009
|
const clone2 = this.applyTemplate(context);
|
|
869
1010
|
context.element.replaceChild(clone2, rendered);
|
|
870
1011
|
}
|
|
@@ -996,7 +1137,6 @@
|
|
|
996
1137
|
});
|
|
997
1138
|
}
|
|
998
1139
|
}
|
|
999
|
-
var domSignals = /* @__PURE__ */ new WeakMap();
|
|
1000
1140
|
function element(context, ...extraprops) {
|
|
1001
1141
|
const el = context.element;
|
|
1002
1142
|
let value = context.value;
|
|
@@ -1011,27 +1151,9 @@
|
|
|
1011
1151
|
const props = ["innerHTML", "title", "id", "className"].concat(extraprops);
|
|
1012
1152
|
setProperties(el, value, ...props);
|
|
1013
1153
|
if (this.options.twoway) {
|
|
1014
|
-
|
|
1015
|
-
updateProperties.call(this, context, props, valueIsString);
|
|
1016
|
-
});
|
|
1154
|
+
trackDomField.call(this, context.element, props, valueIsString);
|
|
1017
1155
|
}
|
|
1018
1156
|
}
|
|
1019
|
-
function updateProperties(context, props, valueIsString) {
|
|
1020
|
-
if (domSignals.has(context.element)) {
|
|
1021
|
-
return;
|
|
1022
|
-
}
|
|
1023
|
-
const s = signal2(context.element);
|
|
1024
|
-
domSignals.set(context.element, s);
|
|
1025
|
-
throttledEffect(() => {
|
|
1026
|
-
let updateValue = s.innerHTML;
|
|
1027
|
-
if (!valueIsString) {
|
|
1028
|
-
updateValue = getProperties(s, ...props);
|
|
1029
|
-
}
|
|
1030
|
-
untracked(() => {
|
|
1031
|
-
setValueByPath(this.options.root, context.path, updateValue);
|
|
1032
|
-
});
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
1157
|
function setProperties(el, data, ...properties) {
|
|
1036
1158
|
if (!data || typeof data !== "object") {
|
|
1037
1159
|
return;
|
|
@@ -1075,9 +1197,6 @@
|
|
|
1075
1197
|
}
|
|
1076
1198
|
|
|
1077
1199
|
// src/bind.mjs
|
|
1078
|
-
if (!Symbol.bindTemplate) {
|
|
1079
|
-
Symbol.bindTemplate = Symbol("bindTemplate");
|
|
1080
|
-
}
|
|
1081
1200
|
var SimplyBind = class {
|
|
1082
1201
|
/**
|
|
1083
1202
|
* @param Object options - a set of options for this instance, options may include:
|
|
@@ -1104,6 +1223,7 @@
|
|
|
1104
1223
|
},
|
|
1105
1224
|
renderers: {
|
|
1106
1225
|
"INPUT": input,
|
|
1226
|
+
"TEXTAREA": input,
|
|
1107
1227
|
"BUTTON": button,
|
|
1108
1228
|
"SELECT": select,
|
|
1109
1229
|
"A": anchor,
|
|
@@ -1273,7 +1393,7 @@
|
|
|
1273
1393
|
if (typeof index !== "undefined") {
|
|
1274
1394
|
clone2.children[0].setAttribute(attribute + "-key", index);
|
|
1275
1395
|
}
|
|
1276
|
-
clone2.children[0][
|
|
1396
|
+
clone2.children[0][DEP.TEMPLATE] = template;
|
|
1277
1397
|
return clone2;
|
|
1278
1398
|
}
|
|
1279
1399
|
parseLinks(links) {
|
|
@@ -1460,7 +1580,7 @@
|
|
|
1460
1580
|
}
|
|
1461
1581
|
const dataSignal = this.effects[this.effects.length - 1];
|
|
1462
1582
|
const connectedSignal = fn.call(this, dataSignal);
|
|
1463
|
-
if (!connectedSignal || !connectedSignal[
|
|
1583
|
+
if (!connectedSignal || !connectedSignal[DEP.SIGNAL]) {
|
|
1464
1584
|
throw new Error("addEffect function parameter must return a Signal", { cause: fn });
|
|
1465
1585
|
}
|
|
1466
1586
|
this.view = connectedSignal;
|