@neeloong/form 0.1.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/index.js ADDED
@@ -0,0 +1,3658 @@
1
+ /*!
2
+ * @neeloong/form v0.1.0
3
+ * (c) 2024-2025 Fierflame
4
+ * @license Apache-2.0
5
+ */
6
+
7
+ (function (global, factory) {
8
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
9
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
10
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.neeloongForm = {}));
11
+ })(this, (function (exports) { 'use strict';
12
+
13
+ var __defProp = Object.defineProperty;
14
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
15
+ var __publicField = (obj, key, value) => {
16
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
17
+ return value;
18
+ };
19
+ var __accessCheck = (obj, member, msg) => {
20
+ if (!member.has(obj))
21
+ throw TypeError("Cannot " + msg);
22
+ };
23
+ var __privateIn = (member, obj) => {
24
+ if (Object(obj) !== obj)
25
+ throw TypeError('Cannot use the "in" operator on this value');
26
+ return member.has(obj);
27
+ };
28
+ var __privateAdd = (obj, member, value) => {
29
+ if (member.has(obj))
30
+ throw TypeError("Cannot add the same private member more than once");
31
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
32
+ };
33
+ var __privateMethod = (obj, member, method) => {
34
+ __accessCheck(obj, member, "access private method");
35
+ return method;
36
+ };
37
+ /**
38
+ * @license
39
+ * Copyright Google LLC All Rights Reserved.
40
+ *
41
+ * Use of this source code is governed by an MIT-style license that can be
42
+ * found in the LICENSE file at https://angular.io/license
43
+ */
44
+ function defaultEquals(a, b) {
45
+ return Object.is(a, b);
46
+ }
47
+ /**
48
+ * @license
49
+ * Copyright Google LLC All Rights Reserved.
50
+ *
51
+ * Use of this source code is governed by an MIT-style license that can be
52
+ * found in the LICENSE file at https://angular.io/license
53
+ */
54
+ let activeConsumer = null;
55
+ let inNotificationPhase = false;
56
+ let epoch = 1;
57
+ const SIGNAL = /* @__PURE__ */ Symbol("SIGNAL");
58
+ function setActiveConsumer(consumer) {
59
+ const prev = activeConsumer;
60
+ activeConsumer = consumer;
61
+ return prev;
62
+ }
63
+ function getActiveConsumer() {
64
+ return activeConsumer;
65
+ }
66
+ function isInNotificationPhase() {
67
+ return inNotificationPhase;
68
+ }
69
+ const REACTIVE_NODE = {
70
+ version: 0,
71
+ lastCleanEpoch: 0,
72
+ dirty: false,
73
+ producerNode: void 0,
74
+ producerLastReadVersion: void 0,
75
+ producerIndexOfThis: void 0,
76
+ nextProducerIndex: 0,
77
+ liveConsumerNode: void 0,
78
+ liveConsumerIndexOfThis: void 0,
79
+ consumerAllowSignalWrites: false,
80
+ consumerIsAlwaysLive: false,
81
+ producerMustRecompute: () => false,
82
+ producerRecomputeValue: () => {
83
+ },
84
+ consumerMarkedDirty: () => {
85
+ },
86
+ consumerOnSignalRead: () => {
87
+ }
88
+ };
89
+ function producerAccessed(node) {
90
+ if (inNotificationPhase) {
91
+ throw new Error(
92
+ typeof ngDevMode !== "undefined" && ngDevMode ? `Assertion error: signal read during notification phase` : ""
93
+ );
94
+ }
95
+ if (activeConsumer === null) {
96
+ return;
97
+ }
98
+ activeConsumer.consumerOnSignalRead(node);
99
+ const idx = activeConsumer.nextProducerIndex++;
100
+ assertConsumerNode(activeConsumer);
101
+ if (idx < activeConsumer.producerNode.length && activeConsumer.producerNode[idx] !== node) {
102
+ if (consumerIsLive(activeConsumer)) {
103
+ const staleProducer = activeConsumer.producerNode[idx];
104
+ producerRemoveLiveConsumerAtIndex(staleProducer, activeConsumer.producerIndexOfThis[idx]);
105
+ }
106
+ }
107
+ if (activeConsumer.producerNode[idx] !== node) {
108
+ activeConsumer.producerNode[idx] = node;
109
+ activeConsumer.producerIndexOfThis[idx] = consumerIsLive(activeConsumer) ? producerAddLiveConsumer(node, activeConsumer, idx) : 0;
110
+ }
111
+ activeConsumer.producerLastReadVersion[idx] = node.version;
112
+ }
113
+ function producerIncrementEpoch() {
114
+ epoch++;
115
+ }
116
+ function producerUpdateValueVersion(node) {
117
+ if (!node.dirty && node.lastCleanEpoch === epoch) {
118
+ return;
119
+ }
120
+ if (!node.producerMustRecompute(node) && !consumerPollProducersForChange(node)) {
121
+ node.dirty = false;
122
+ node.lastCleanEpoch = epoch;
123
+ return;
124
+ }
125
+ node.producerRecomputeValue(node);
126
+ node.dirty = false;
127
+ node.lastCleanEpoch = epoch;
128
+ }
129
+ function producerNotifyConsumers(node) {
130
+ if (node.liveConsumerNode === void 0) {
131
+ return;
132
+ }
133
+ const prev = inNotificationPhase;
134
+ inNotificationPhase = true;
135
+ try {
136
+ for (const consumer of node.liveConsumerNode) {
137
+ if (!consumer.dirty) {
138
+ consumerMarkDirty(consumer);
139
+ }
140
+ }
141
+ } finally {
142
+ inNotificationPhase = prev;
143
+ }
144
+ }
145
+ function producerUpdatesAllowed() {
146
+ return (activeConsumer == null ? void 0 : activeConsumer.consumerAllowSignalWrites) !== false;
147
+ }
148
+ function consumerMarkDirty(node) {
149
+ var _a;
150
+ node.dirty = true;
151
+ producerNotifyConsumers(node);
152
+ (_a = node.consumerMarkedDirty) == null ? void 0 : _a.call(node.wrapper ?? node);
153
+ }
154
+ function consumerBeforeComputation(node) {
155
+ node && (node.nextProducerIndex = 0);
156
+ return setActiveConsumer(node);
157
+ }
158
+ function consumerAfterComputation(node, prevConsumer) {
159
+ setActiveConsumer(prevConsumer);
160
+ if (!node || node.producerNode === void 0 || node.producerIndexOfThis === void 0 || node.producerLastReadVersion === void 0) {
161
+ return;
162
+ }
163
+ if (consumerIsLive(node)) {
164
+ for (let i = node.nextProducerIndex; i < node.producerNode.length; i++) {
165
+ producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
166
+ }
167
+ }
168
+ while (node.producerNode.length > node.nextProducerIndex) {
169
+ node.producerNode.pop();
170
+ node.producerLastReadVersion.pop();
171
+ node.producerIndexOfThis.pop();
172
+ }
173
+ }
174
+ function consumerPollProducersForChange(node) {
175
+ assertConsumerNode(node);
176
+ for (let i = 0; i < node.producerNode.length; i++) {
177
+ const producer = node.producerNode[i];
178
+ const seenVersion = node.producerLastReadVersion[i];
179
+ if (seenVersion !== producer.version) {
180
+ return true;
181
+ }
182
+ producerUpdateValueVersion(producer);
183
+ if (seenVersion !== producer.version) {
184
+ return true;
185
+ }
186
+ }
187
+ return false;
188
+ }
189
+ function producerAddLiveConsumer(node, consumer, indexOfThis) {
190
+ var _a;
191
+ assertProducerNode(node);
192
+ assertConsumerNode(node);
193
+ if (node.liveConsumerNode.length === 0) {
194
+ (_a = node.watched) == null ? void 0 : _a.call(node.wrapper);
195
+ for (let i = 0; i < node.producerNode.length; i++) {
196
+ node.producerIndexOfThis[i] = producerAddLiveConsumer(node.producerNode[i], node, i);
197
+ }
198
+ }
199
+ node.liveConsumerIndexOfThis.push(indexOfThis);
200
+ return node.liveConsumerNode.push(consumer) - 1;
201
+ }
202
+ function producerRemoveLiveConsumerAtIndex(node, idx) {
203
+ var _a;
204
+ assertProducerNode(node);
205
+ assertConsumerNode(node);
206
+ if (typeof ngDevMode !== "undefined" && ngDevMode && idx >= node.liveConsumerNode.length) {
207
+ throw new Error(
208
+ `Assertion error: active consumer index ${idx} is out of bounds of ${node.liveConsumerNode.length} consumers)`
209
+ );
210
+ }
211
+ if (node.liveConsumerNode.length === 1) {
212
+ (_a = node.unwatched) == null ? void 0 : _a.call(node.wrapper);
213
+ for (let i = 0; i < node.producerNode.length; i++) {
214
+ producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
215
+ }
216
+ }
217
+ const lastIdx = node.liveConsumerNode.length - 1;
218
+ node.liveConsumerNode[idx] = node.liveConsumerNode[lastIdx];
219
+ node.liveConsumerIndexOfThis[idx] = node.liveConsumerIndexOfThis[lastIdx];
220
+ node.liveConsumerNode.length--;
221
+ node.liveConsumerIndexOfThis.length--;
222
+ if (idx < node.liveConsumerNode.length) {
223
+ const idxProducer = node.liveConsumerIndexOfThis[idx];
224
+ const consumer = node.liveConsumerNode[idx];
225
+ assertConsumerNode(consumer);
226
+ consumer.producerIndexOfThis[idxProducer] = idx;
227
+ }
228
+ }
229
+ function consumerIsLive(node) {
230
+ var _a;
231
+ return node.consumerIsAlwaysLive || (((_a = node == null ? void 0 : node.liveConsumerNode) == null ? void 0 : _a.length) ?? 0) > 0;
232
+ }
233
+ function assertConsumerNode(node) {
234
+ node.producerNode ?? (node.producerNode = []);
235
+ node.producerIndexOfThis ?? (node.producerIndexOfThis = []);
236
+ node.producerLastReadVersion ?? (node.producerLastReadVersion = []);
237
+ }
238
+ function assertProducerNode(node) {
239
+ node.liveConsumerNode ?? (node.liveConsumerNode = []);
240
+ node.liveConsumerIndexOfThis ?? (node.liveConsumerIndexOfThis = []);
241
+ }
242
+ /**
243
+ * @license
244
+ * Copyright Google LLC All Rights Reserved.
245
+ *
246
+ * Use of this source code is governed by an MIT-style license that can be
247
+ * found in the LICENSE file at https://angular.io/license
248
+ */
249
+ function computedGet(node) {
250
+ producerUpdateValueVersion(node);
251
+ producerAccessed(node);
252
+ if (node.value === ERRORED) {
253
+ throw node.error;
254
+ }
255
+ return node.value;
256
+ }
257
+ function createComputed(computation) {
258
+ const node = Object.create(COMPUTED_NODE);
259
+ node.computation = computation;
260
+ const computed = () => computedGet(node);
261
+ computed[SIGNAL] = node;
262
+ return computed;
263
+ }
264
+ const UNSET = /* @__PURE__ */ Symbol("UNSET");
265
+ const COMPUTING = /* @__PURE__ */ Symbol("COMPUTING");
266
+ const ERRORED = /* @__PURE__ */ Symbol("ERRORED");
267
+ const COMPUTED_NODE = /* @__PURE__ */ (() => {
268
+ return {
269
+ ...REACTIVE_NODE,
270
+ value: UNSET,
271
+ dirty: true,
272
+ error: null,
273
+ equal: defaultEquals,
274
+ producerMustRecompute(node) {
275
+ return node.value === UNSET || node.value === COMPUTING;
276
+ },
277
+ producerRecomputeValue(node) {
278
+ if (node.value === COMPUTING) {
279
+ throw new Error("Detected cycle in computations.");
280
+ }
281
+ const oldValue = node.value;
282
+ node.value = COMPUTING;
283
+ const prevConsumer = consumerBeforeComputation(node);
284
+ let newValue;
285
+ let wasEqual = false;
286
+ try {
287
+ newValue = node.computation.call(node.wrapper);
288
+ const oldOk = oldValue !== UNSET && oldValue !== ERRORED;
289
+ wasEqual = oldOk && node.equal.call(node.wrapper, oldValue, newValue);
290
+ } catch (err) {
291
+ newValue = ERRORED;
292
+ node.error = err;
293
+ } finally {
294
+ consumerAfterComputation(node, prevConsumer);
295
+ }
296
+ if (wasEqual) {
297
+ node.value = oldValue;
298
+ return;
299
+ }
300
+ node.value = newValue;
301
+ node.version++;
302
+ }
303
+ };
304
+ })();
305
+ /**
306
+ * @license
307
+ * Copyright Google LLC All Rights Reserved.
308
+ *
309
+ * Use of this source code is governed by an MIT-style license that can be
310
+ * found in the LICENSE file at https://angular.io/license
311
+ */
312
+ function defaultThrowError() {
313
+ throw new Error();
314
+ }
315
+ let throwInvalidWriteToSignalErrorFn = defaultThrowError;
316
+ function throwInvalidWriteToSignalError() {
317
+ throwInvalidWriteToSignalErrorFn();
318
+ }
319
+ /**
320
+ * @license
321
+ * Copyright Google LLC All Rights Reserved.
322
+ *
323
+ * Use of this source code is governed by an MIT-style license that can be
324
+ * found in the LICENSE file at https://angular.io/license
325
+ */
326
+ function createSignal(initialValue) {
327
+ const node = Object.create(SIGNAL_NODE);
328
+ node.value = initialValue;
329
+ const getter = () => {
330
+ producerAccessed(node);
331
+ return node.value;
332
+ };
333
+ getter[SIGNAL] = node;
334
+ return getter;
335
+ }
336
+ function signalGetFn() {
337
+ producerAccessed(this);
338
+ return this.value;
339
+ }
340
+ function signalSetFn(node, newValue) {
341
+ if (!producerUpdatesAllowed()) {
342
+ throwInvalidWriteToSignalError();
343
+ }
344
+ if (!node.equal.call(node.wrapper, node.value, newValue)) {
345
+ node.value = newValue;
346
+ signalValueChanged(node);
347
+ }
348
+ }
349
+ const SIGNAL_NODE = /* @__PURE__ */ (() => {
350
+ return {
351
+ ...REACTIVE_NODE,
352
+ equal: defaultEquals,
353
+ value: void 0
354
+ };
355
+ })();
356
+ function signalValueChanged(node) {
357
+ node.version++;
358
+ producerIncrementEpoch();
359
+ producerNotifyConsumers(node);
360
+ }
361
+ /**
362
+ * @license
363
+ * Copyright 2024 Bloomberg Finance L.P.
364
+ *
365
+ * Licensed under the Apache License, Version 2.0 (the "License");
366
+ * you may not use this file except in compliance with the License.
367
+ * You may obtain a copy of the License at
368
+ *
369
+ * http://www.apache.org/licenses/LICENSE-2.0
370
+ *
371
+ * Unless required by applicable law or agreed to in writing, software
372
+ * distributed under the License is distributed on an "AS IS" BASIS,
373
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
374
+ * See the License for the specific language governing permissions and
375
+ * limitations under the License.
376
+ */
377
+ const NODE = Symbol("node");
378
+ exports.Signal = void 0;
379
+ ((Signal2) => {
380
+ var _a, _brand, _b, _brand2;
381
+ class State {
382
+ constructor(initialValue, options = {}) {
383
+ __privateAdd(this, _brand);
384
+ __publicField(this, _a);
385
+ const ref = createSignal(initialValue);
386
+ const node = ref[SIGNAL];
387
+ this[NODE] = node;
388
+ node.wrapper = this;
389
+ if (options) {
390
+ const equals = options.equals;
391
+ if (equals) {
392
+ node.equal = equals;
393
+ }
394
+ node.watched = options[Signal2.subtle.watched];
395
+ node.unwatched = options[Signal2.subtle.unwatched];
396
+ }
397
+ }
398
+ get() {
399
+ if (!(0, Signal2.isState)(this))
400
+ throw new TypeError("Wrong receiver type for Signal.State.prototype.get");
401
+ return signalGetFn.call(this[NODE]);
402
+ }
403
+ set(newValue) {
404
+ if (!(0, Signal2.isState)(this))
405
+ throw new TypeError("Wrong receiver type for Signal.State.prototype.set");
406
+ if (isInNotificationPhase()) {
407
+ throw new Error("Writes to signals not permitted during Watcher callback");
408
+ }
409
+ const ref = this[NODE];
410
+ signalSetFn(ref, newValue);
411
+ }
412
+ }
413
+ _a = NODE;
414
+ _brand = new WeakSet();
415
+ Signal2.isState = (s) => __privateIn(_brand, s);
416
+ Signal2.State = State;
417
+ class Computed {
418
+ // Create a Signal which evaluates to the value returned by the callback.
419
+ // Callback is called with this signal as the parameter.
420
+ constructor(computation, options) {
421
+ __privateAdd(this, _brand2);
422
+ __publicField(this, _b);
423
+ const ref = createComputed(computation);
424
+ const node = ref[SIGNAL];
425
+ node.consumerAllowSignalWrites = true;
426
+ this[NODE] = node;
427
+ node.wrapper = this;
428
+ if (options) {
429
+ const equals = options.equals;
430
+ if (equals) {
431
+ node.equal = equals;
432
+ }
433
+ node.watched = options[Signal2.subtle.watched];
434
+ node.unwatched = options[Signal2.subtle.unwatched];
435
+ }
436
+ }
437
+ get() {
438
+ if (!(0, Signal2.isComputed)(this))
439
+ throw new TypeError("Wrong receiver type for Signal.Computed.prototype.get");
440
+ return computedGet(this[NODE]);
441
+ }
442
+ }
443
+ _b = NODE;
444
+ _brand2 = new WeakSet();
445
+ Signal2.isComputed = (c) => __privateIn(_brand2, c);
446
+ Signal2.Computed = Computed;
447
+ ((subtle2) => {
448
+ var _a2, _brand3, _assertSignals, assertSignals_fn;
449
+ function untrack(cb) {
450
+ let output;
451
+ let prevActiveConsumer = null;
452
+ try {
453
+ prevActiveConsumer = setActiveConsumer(null);
454
+ output = cb();
455
+ } finally {
456
+ setActiveConsumer(prevActiveConsumer);
457
+ }
458
+ return output;
459
+ }
460
+ subtle2.untrack = untrack;
461
+ function introspectSources(sink) {
462
+ var _a3;
463
+ if (!(0, Signal2.isComputed)(sink) && !(0, Signal2.isWatcher)(sink)) {
464
+ throw new TypeError("Called introspectSources without a Computed or Watcher argument");
465
+ }
466
+ return ((_a3 = sink[NODE].producerNode) == null ? void 0 : _a3.map((n) => n.wrapper)) ?? [];
467
+ }
468
+ subtle2.introspectSources = introspectSources;
469
+ function introspectSinks(signal) {
470
+ var _a3;
471
+ if (!(0, Signal2.isComputed)(signal) && !(0, Signal2.isState)(signal)) {
472
+ throw new TypeError("Called introspectSinks without a Signal argument");
473
+ }
474
+ return ((_a3 = signal[NODE].liveConsumerNode) == null ? void 0 : _a3.map((n) => n.wrapper)) ?? [];
475
+ }
476
+ subtle2.introspectSinks = introspectSinks;
477
+ function hasSinks(signal) {
478
+ if (!(0, Signal2.isComputed)(signal) && !(0, Signal2.isState)(signal)) {
479
+ throw new TypeError("Called hasSinks without a Signal argument");
480
+ }
481
+ const liveConsumerNode = signal[NODE].liveConsumerNode;
482
+ if (!liveConsumerNode)
483
+ return false;
484
+ return liveConsumerNode.length > 0;
485
+ }
486
+ subtle2.hasSinks = hasSinks;
487
+ function hasSources(signal) {
488
+ if (!(0, Signal2.isComputed)(signal) && !(0, Signal2.isWatcher)(signal)) {
489
+ throw new TypeError("Called hasSources without a Computed or Watcher argument");
490
+ }
491
+ const producerNode = signal[NODE].producerNode;
492
+ if (!producerNode)
493
+ return false;
494
+ return producerNode.length > 0;
495
+ }
496
+ subtle2.hasSources = hasSources;
497
+ class Watcher {
498
+ // When a (recursive) source of Watcher is written to, call this callback,
499
+ // if it hasn't already been called since the last `watch` call.
500
+ // No signals may be read or written during the notify.
501
+ constructor(notify) {
502
+ __privateAdd(this, _brand3);
503
+ __privateAdd(this, _assertSignals);
504
+ __publicField(this, _a2);
505
+ let node = Object.create(REACTIVE_NODE);
506
+ node.wrapper = this;
507
+ node.consumerMarkedDirty = notify;
508
+ node.consumerIsAlwaysLive = true;
509
+ node.consumerAllowSignalWrites = false;
510
+ node.producerNode = [];
511
+ this[NODE] = node;
512
+ }
513
+ // Add these signals to the Watcher's set, and set the watcher to run its
514
+ // notify callback next time any signal in the set (or one of its dependencies) changes.
515
+ // Can be called with no arguments just to reset the "notified" state, so that
516
+ // the notify callback will be invoked again.
517
+ watch(...signals) {
518
+ if (!(0, Signal2.isWatcher)(this)) {
519
+ throw new TypeError("Called unwatch without Watcher receiver");
520
+ }
521
+ __privateMethod(this, _assertSignals, assertSignals_fn).call(this, signals);
522
+ const node = this[NODE];
523
+ node.dirty = false;
524
+ const prev = setActiveConsumer(node);
525
+ for (const signal of signals) {
526
+ producerAccessed(signal[NODE]);
527
+ }
528
+ setActiveConsumer(prev);
529
+ }
530
+ // Remove these signals from the watched set (e.g., for an effect which is disposed)
531
+ unwatch(...signals) {
532
+ if (!(0, Signal2.isWatcher)(this)) {
533
+ throw new TypeError("Called unwatch without Watcher receiver");
534
+ }
535
+ __privateMethod(this, _assertSignals, assertSignals_fn).call(this, signals);
536
+ const node = this[NODE];
537
+ assertConsumerNode(node);
538
+ for (let i = node.producerNode.length - 1; i >= 0; i--) {
539
+ if (signals.includes(node.producerNode[i].wrapper)) {
540
+ producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
541
+ const lastIdx = node.producerNode.length - 1;
542
+ node.producerNode[i] = node.producerNode[lastIdx];
543
+ node.producerIndexOfThis[i] = node.producerIndexOfThis[lastIdx];
544
+ node.producerNode.length--;
545
+ node.producerIndexOfThis.length--;
546
+ node.nextProducerIndex--;
547
+ if (i < node.producerNode.length) {
548
+ const idxConsumer = node.producerIndexOfThis[i];
549
+ const producer = node.producerNode[i];
550
+ assertProducerNode(producer);
551
+ producer.liveConsumerIndexOfThis[idxConsumer] = i;
552
+ }
553
+ }
554
+ }
555
+ }
556
+ // Returns the set of computeds in the Watcher's set which are still yet
557
+ // to be re-evaluated
558
+ getPending() {
559
+ if (!(0, Signal2.isWatcher)(this)) {
560
+ throw new TypeError("Called getPending without Watcher receiver");
561
+ }
562
+ const node = this[NODE];
563
+ return node.producerNode.filter((n) => n.dirty).map((n) => n.wrapper);
564
+ }
565
+ }
566
+ _a2 = NODE;
567
+ _brand3 = new WeakSet();
568
+ _assertSignals = new WeakSet();
569
+ assertSignals_fn = function(signals) {
570
+ for (const signal of signals) {
571
+ if (!(0, Signal2.isComputed)(signal) && !(0, Signal2.isState)(signal)) {
572
+ throw new TypeError("Called watch/unwatch without a Computed or State argument");
573
+ }
574
+ }
575
+ };
576
+ Signal2.isWatcher = (w) => __privateIn(_brand3, w);
577
+ subtle2.Watcher = Watcher;
578
+ function currentComputed() {
579
+ var _a3;
580
+ return (_a3 = getActiveConsumer()) == null ? void 0 : _a3.wrapper;
581
+ }
582
+ subtle2.currentComputed = currentComputed;
583
+ subtle2.watched = Symbol("watched");
584
+ subtle2.unwatched = Symbol("unwatched");
585
+ })(Signal2.subtle || (Signal2.subtle = {}));
586
+ })(exports.Signal || (exports.Signal = {}));
587
+
588
+ /** @import Store from './index.mjs' */
589
+
590
+ /**
591
+ *
592
+ * @param {Store} self
593
+ * @param {boolean?} [defState]
594
+ * @param {boolean | ((store: Store) => boolean) | null} [fn]
595
+ * @param {Signal.Computed<boolean>?} [parent]
596
+ * @returns {[Signal.State<boolean?>, Signal.Computed<boolean>]}
597
+ */
598
+ const createBooleanStates = (self, defState, fn, parent) => {
599
+
600
+ const selfState = new exports.Signal.State(typeof defState === 'boolean' ? defState : null);
601
+ const scriptState = typeof fn === 'function' ? new exports.Signal.Computed(() => fn(self)) : fn ? new exports.Signal.Computed(() => true) : new exports.Signal.Computed(() => false);
602
+
603
+ const getState = () => {
604
+ const s = selfState.get();
605
+ return s === null ? scriptState.get() : s;
606
+ };
607
+ const state = parent
608
+ ? new exports.Signal.Computed(() => parent.get() || getState())
609
+ : new exports.Signal.Computed(getState);
610
+
611
+ return [selfState, state];
612
+
613
+ };
614
+
615
+ /** @import { Schema } from '../types.mjs' */
616
+ /**
617
+ * @template [T=any]
618
+ */
619
+ class Store {
620
+ /**
621
+ * @param {Schema} schema
622
+ * @param {object} [options]
623
+ * @param {boolean} [options.new]
624
+ */
625
+ static create(schema, options = {}) {
626
+ return new ObjectStore({type: null, props: schema}, { ...options, parent: null });
627
+ }
628
+ #null = false;
629
+ get null() { return this.#null; }
630
+ /**
631
+ * @param {Schema.Field} schema
632
+ * @param {object} options
633
+ * @param {*} [options.parent]
634
+ * @param {*} [options.state]
635
+ * @param {number | string | null} [options.index]
636
+ * @param {number} [options.length]
637
+ * @param {boolean} [options.null]
638
+ * @param {boolean} [options.new]
639
+ * @param {boolean} [options.hidden]
640
+ * @param {boolean} [options.clearable]
641
+ * @param {boolean} [options.required]
642
+ * @param {boolean} [options.readonly]
643
+ * @param {boolean} [options.disabled]
644
+ * @param {((value: any) => any)?} [options.setValue]
645
+ * @param {((value: any) => any)?} [options.setState]
646
+ * @param {((value: any, state: any) => [value: any, state: any])?} [options.convert]
647
+ * @param {((value: T?, index: any) => void)?} [options.onUpdate]
648
+ * @param {((value: T?, index: any) => void)?} [options.onUpdateState]
649
+ */
650
+ constructor(schema, {
651
+ null: isNull, state,
652
+ setValue, setState, convert, onUpdate, onUpdateState,
653
+ index, length, new: isNew, parent: parentNode,
654
+ hidden, clearable, required, disabled, readonly,
655
+ }) {
656
+ this.schema = schema;
657
+ this.#state.set(typeof state === 'object' && state || {});
658
+ const parent = parentNode instanceof Store ? parentNode : null;
659
+ if (parent) {
660
+ this.#parent = parent;
661
+ this.#root = parent.#root;
662
+ // TODO: 事件向上冒泡
663
+ }
664
+
665
+ const selfNewState = new exports.Signal.State(Boolean(isNew));
666
+ this.#selfNew = selfNewState;
667
+ /** @type {Signal.Computed<boolean>} */
668
+ const newState = parent
669
+ ? new exports.Signal.Computed(() => parent.#new.get() || selfNewState.get())
670
+ : new exports.Signal.Computed(() => selfNewState.get());
671
+
672
+ this.#new = newState;
673
+ const immutable = Boolean(schema.immutable);
674
+ const creatable = schema.creatable !== false;
675
+ this.#immutable = immutable;
676
+ this.#creatable = creatable;
677
+ this.#editable = new exports.Signal.Computed(() => newState.get() ? creatable : !immutable);
678
+
679
+ [this.#selfHidden, this.#hidden] = createBooleanStates(this, hidden, schema.hidden, parent ? parent.#hidden : null);
680
+ [this.#selfClearable, this.#clearable] = createBooleanStates(this, clearable, schema.clearable, parent ? parent.#clearable : null);
681
+ [this.#selfRequired, this.#required] = createBooleanStates(this, required, schema.required, parent ? parent.#required : null);
682
+ [this.#selfDisabled, this.#disabled] = createBooleanStates(this, disabled, schema.disabled, parent ? parent.#disabled : null);
683
+ [this.#selfReadonly, this.#readonly] = createBooleanStates(this, readonly, schema.readonly, parent ? parent.#readonly : null);
684
+
685
+ if (isNull) {
686
+ this.#null = true;
687
+ return;
688
+ }
689
+ this.#onUpdate = onUpdate || null;
690
+ this.#onUpdateState = onUpdateState || null;
691
+ this.#setValue = typeof setValue === 'function' ? setValue : null;
692
+ this.#setState = typeof setState === 'function' ? setState : null;
693
+ this.#convert = typeof convert === 'function' ? convert : null;
694
+ this.#length.set(length || 0);
695
+ this.#index.set(index ?? '');
696
+
697
+ }
698
+ #destroyed = false;
699
+ /** @type {((value: any) => any)?} */
700
+ #setValue = null
701
+ /** @type {((value: any) => any)?} */
702
+ #setState = null
703
+ /** @type {((value: any, state: any) => [value: any, state: any])?} */
704
+ #convert = null
705
+ /** @type {((value: any, index: any) => void)?} */
706
+ #onUpdate = null
707
+ /** @type {((value: any, index: any) => void)?} */
708
+ #onUpdateState = null
709
+ /** @readonly @type {Store?} */
710
+ #parent = null;
711
+ /** @readonly @type {Store} */
712
+ #root = this;
713
+ get parent() { return this.#parent; }
714
+ get root() { return this.#root; }
715
+
716
+ #length = new exports.Signal.State(0);
717
+ get length() { return this.#length.get(); }
718
+ set length(v) { this.#length.set(v); }
719
+ #index = new exports.Signal.State(/** @type {string | number} */(''));
720
+ get index() { return this.#index.get(); }
721
+ set index(v) { this.#index.set(v); }
722
+ get no() {
723
+ if (this.#null) { return ''; }
724
+ const index = this.index;
725
+ return typeof index === 'number' ? index + 1 : index;
726
+ }
727
+
728
+ #creatable = true;
729
+ get creatable() { return this.#creatable; }
730
+ #immutable = false;
731
+ get immutable() { return this.#immutable; }
732
+
733
+ /** @readonly @type {Signal.Computed<boolean>} */
734
+ #new
735
+ /** @readonly @type {Signal.State<boolean>} */
736
+ #selfNew
737
+ /** @readonly @type {Signal.Computed<boolean>} */
738
+ #editable
739
+ get selfNew() { return this.#selfNew.get(); }
740
+ set selfNew(v) { this.#selfNew.set(Boolean(v)); }
741
+ get new() { return this.#new.get(); }
742
+ set new(v) { this.#selfNew.set(Boolean(v)); }
743
+ get editable() { return this.#editable.get(); }
744
+
745
+ /** @readonly @type {Signal.State<boolean?>} */
746
+ #selfHidden
747
+ /** @readonly @type {Signal.Computed<boolean>} */
748
+ #hidden
749
+ get selfHidden() { return this.#selfHidden.get(); }
750
+ set selfHidden(v) { this.#selfHidden.set(typeof v === 'boolean' ? v : null); }
751
+ get hidden() { return this.#hidden.get(); }
752
+ set hidden(v) { this.#selfHidden.set(typeof v === 'boolean' ? v : null); }
753
+
754
+ /** @readonly @type {Signal.State<boolean?>} */
755
+ #selfClearable
756
+ /** @readonly @type {Signal.Computed<boolean>} */
757
+ #clearable
758
+ get selfClearable() { return this.#selfClearable.get(); }
759
+ set selfClearable(v) { this.#selfClearable.set(typeof v === 'boolean' ? v : null); }
760
+ get clearable() { return this.#clearable.get(); }
761
+ set clearable(v) { this.#selfClearable.set(typeof v === 'boolean' ? v : null); }
762
+
763
+ /** @readonly @type {Signal.State<boolean?>} */
764
+ #selfRequired
765
+ /** @readonly @type {Signal.Computed<boolean>} */
766
+ #required
767
+ get selfRequired() { return this.#selfRequired.get(); }
768
+ set selfRequired(v) { this.#selfRequired.set(typeof v === 'boolean' ? v : null); }
769
+ get required() { return this.#required.get(); }
770
+ set required(v) { this.#selfRequired.set(typeof v === 'boolean' ? v : null); }
771
+
772
+ /** @readonly @type {Signal.State<boolean?>} */
773
+ #selfDisabled
774
+ /** @readonly @type {Signal.Computed<boolean>} */
775
+ #disabled
776
+ get selfDisabled() { return this.#selfDisabled.get(); }
777
+ set selfDisabled(v) { this.#selfDisabled.set(typeof v === 'boolean' ? v : null); }
778
+ get disabled() { return this.#disabled.get(); }
779
+ set disabled(v) { this.#selfDisabled.set(typeof v === 'boolean' ? v : null); }
780
+
781
+ /** @readonly @type {Signal.State<boolean?>} */
782
+ #selfReadonly
783
+ /** @readonly @type {Signal.Computed<boolean>} */
784
+ #readonly
785
+ get selfReadonly() { return this.#selfReadonly.get(); }
786
+ set selfReadonly(v) { this.#selfReadonly.set(typeof v === 'boolean' ? v : null); }
787
+ get readonly() { return this.#readonly.get(); }
788
+ set readonly(v) { this.#selfReadonly.set(typeof v === 'boolean' ? v : null); }
789
+
790
+
791
+
792
+
793
+
794
+ /** @returns {IterableIterator<[key: string | number, value: Store]>} */
795
+ *[Symbol.iterator]() {}
796
+ /**
797
+ *
798
+ * @param {string | number} key
799
+ * @returns {Store?}
800
+ */
801
+ child(key) { return null; }
802
+
803
+ #set = false;
804
+ /** @type {T?} */
805
+ #initValue = null;
806
+ #lastValue = this.#initValue;
807
+ #value = new exports.Signal.State(this.#initValue);
808
+
809
+
810
+ #state = new exports.Signal.State(/** @type {any} */(null));
811
+ #lastState = this.#state.get();
812
+
813
+
814
+ get changed() { return this.#value.get() === this.#lastValue; }
815
+ get saved() { return this.#value.get() === this.#initValue; }
816
+
817
+ get value() { return this.#value.get(); }
818
+ set value(v) {
819
+ if (this.#destroyed) { return; }
820
+ const val = this.#setValue?.(v) || v;
821
+ this.#value.set(val);
822
+ if (!this.#set) {
823
+ this.#set = true;
824
+ this.#initValue = v;
825
+ }
826
+ this.#onUpdate?.(this.#value.get(), this.#index.get());
827
+ this.#requestUpdate();
828
+ }
829
+
830
+ get state() { return this.#state.get(); }
831
+ set state(v) {
832
+ if (this.#destroyed) { return; }
833
+ const sta = this.#setState?.(v) || v;
834
+ this.#state.set(sta);
835
+ this.#set = true;
836
+ this.#onUpdateState?.(this.#state.get(), this.#index.get());
837
+ this.#requestUpdate();
838
+ }
839
+ #requestUpdate() {
840
+ if (this.#needUpdate) { return; }
841
+ this.#needUpdate = true;
842
+ queueMicrotask(() => {
843
+ const oldValue = this.#value.get();
844
+ const oldState = this.#state.get();
845
+ return this.#runUpdate(oldValue, oldState);
846
+ });
847
+ }
848
+
849
+
850
+ #needUpdate = false;
851
+ /**
852
+ *
853
+ * @param {T} value
854
+ * @param {*} state
855
+ * @returns
856
+ */
857
+ #toUpdate(value, state) {
858
+ if (this.#destroyed) { return value; }
859
+ const [val,sta] = this.#convert?.(value, state) || [value, state];
860
+ if(this.#value.get() === val && this.#state.get() === sta) { return [val,sta] }
861
+ this.#value.set(val);
862
+ this.#state.set(sta);
863
+ if (!this.#set) {
864
+ this.#set = true;
865
+ this.#initValue = val;
866
+ }
867
+ return this.#runUpdate(val, sta);
868
+ }
869
+ /**
870
+ *
871
+ * @param {*} val
872
+ * @param {*} sta
873
+ * @returns
874
+ */
875
+ #runUpdate(val, sta) {
876
+ if (this.#destroyed) { return [val, sta]; }
877
+ this.#needUpdate = false;
878
+ if (val && typeof val === 'object') {
879
+ /** @type {T} */
880
+ // @ts-ignore
881
+ let newValues = Array.isArray(val) ? [...val] : {...val};
882
+ let newStates = Array.isArray(val) ? Array.isArray(sta) ? [...sta] : [] : {...sta};
883
+ let updated = false;
884
+ for (const [key, field] of this) {
885
+ // @ts-ignore
886
+ const data = val[key];
887
+ const state = sta?.[key];
888
+ const [newData, newState] = field.#toUpdate(data, state);
889
+ if (data !== newData) {
890
+ // @ts-ignore
891
+ newValues[key] = newData;
892
+ updated = true;
893
+ }
894
+ if (state !== newState) {
895
+ newStates[key] = newState;
896
+ updated = true;
897
+ }
898
+ }
899
+ if (updated) {
900
+ val = newValues;
901
+ sta = newStates;
902
+ this.#value.set(val);
903
+ this.#state.set(newStates);
904
+ }
905
+ }
906
+ if (this.#lastValue === val && this.#lastState === sta) {
907
+ return [val, sta];
908
+ }
909
+ this.#lastValue = val;
910
+ this.#lastState = sta;
911
+ return [val, sta];
912
+
913
+ }
914
+
915
+
916
+
917
+ get destroyed() { return this.#destroyed; }
918
+ destroy() {
919
+ if (this.#destroyed) { return; }
920
+ this.#destroyed = true;
921
+ for (const [, field] of this) {
922
+ field.destroy();
923
+ }
924
+ }
925
+
926
+ }
927
+
928
+
929
+
930
+ class ObjectStore extends Store {
931
+ /** @type {Record<string, Store>} */
932
+ #children
933
+ *[Symbol.iterator]() {yield* Object.entries(this.#children);}
934
+ /**
935
+ *
936
+ * @param {string | number} key
937
+ * @returns {Store?}
938
+ */
939
+ child(key) { return this.#children[key] || null; }
940
+ /**
941
+ * @param {Schema.Field} schema
942
+ * @param {object} [options]
943
+ * @param {Store?} [options.parent]
944
+ * @param {string | number} [options.index]
945
+ * @param {boolean} [options.new]
946
+ * @param {(value: any, index: any) => void} [options.onUpdate]
947
+ * @param {(value: any, index: any) => void} [options.onUpdateState]
948
+ */
949
+ constructor(schema,{ parent, index, new: isNew, onUpdate, onUpdateState } = {}) {
950
+ super(schema, {
951
+ parent, index, new: isNew, onUpdate, onUpdateState,
952
+ setValue(v) {
953
+ if (typeof v !== 'object') { return {}; }
954
+ return v;
955
+ },
956
+ setState(v) {
957
+ if (typeof v !== 'object') { return {}; }
958
+ return v;
959
+ },
960
+ convert(v, state) {
961
+ return [
962
+ typeof v === 'object' ? v : {},
963
+ typeof state === 'object' ? state : {},
964
+ ]
965
+ },
966
+ });
967
+ const children = Object.create(null);
968
+ const childCommonOptions = {
969
+ parent: this,
970
+ /** @param {*} value @param {*} index */
971
+ onUpdate: (value, index) => {
972
+ this.value = {...this.value, [index]: value};
973
+ },
974
+ /** @param {*} state @param {*} index */
975
+ onUpdateState: (state, index) => {
976
+ this.state = {...this.state, [index]: state};
977
+ }
978
+ };
979
+
980
+ for (const [index, field] of Object.entries(schema.props || {})) {
981
+ let child;
982
+ if (typeof field.type === 'string') {
983
+ if (field.array) {
984
+ child = new ArrayStore(field, {...childCommonOptions, index});
985
+ } else {
986
+ child = new Store(field, {...childCommonOptions, index});
987
+ }
988
+ } else if (field.array) {
989
+ child = new ArrayStore(field, {...childCommonOptions, index});
990
+ } else {
991
+ child = new ObjectStore(field, { ...childCommonOptions, index});
992
+ }
993
+ children[index] = child;
994
+ }
995
+ this.#children = children;
996
+ }
997
+ }
998
+
999
+ /**
1000
+ * @template [T=any]
1001
+ * @extends {Store<(T | null)[]>}
1002
+ */
1003
+ class ArrayStore extends Store {
1004
+ /** @type {(index: number, isNew?: boolean) => Store} */
1005
+ #create = () => {throw new Error}
1006
+ #children = new exports.Signal.State(/** @type {Store[]} */([]));
1007
+ get children() { return [...this.#children.get()]; }
1008
+ *[Symbol.iterator]() { return yield*[...this.#children.get().entries()]; }
1009
+ /**
1010
+ *
1011
+ * @param {string | number} key
1012
+ * @returns {Store?}
1013
+ */
1014
+ child(key) {
1015
+ const children = this.#children.get();
1016
+ if (typeof key === 'number' && key < 0) {
1017
+ return children[children.length + key] || null;
1018
+ }
1019
+ return children[Number(key)] || null;
1020
+ }
1021
+ /**
1022
+ * @param {Schema.Field} schema
1023
+ * @param {object} [options]
1024
+ * @param {Store?} [options.parent]
1025
+ * @param {string | number | null} [options.index]
1026
+ * @param {boolean} [options.new]
1027
+ * @param {(value: any, index: any) => void} [options.onUpdate]
1028
+ * @param {(value: any, index: any) => void} [options.onUpdateState]
1029
+ */
1030
+ constructor(schema, { parent, onUpdate, onUpdateState, index, new: isNew} = {}) {
1031
+ // @ts-ignore
1032
+ const updateChildren = (list) => {
1033
+ if (this.destroyed) { return; }
1034
+ const length = Array.isArray(list) && list.length || 0;
1035
+ const children = [...this.#children.get()];
1036
+ const oldLength = children.length;
1037
+ for (let i = children.length; i < length; i++) {
1038
+ children.push(this.#create(i));
1039
+ }
1040
+ for (const schema of children.splice(length)) {
1041
+ schema.destroy();
1042
+ }
1043
+ if (oldLength !== length) {
1044
+ this.length = children.length;
1045
+ this.#children.set(children);
1046
+ }
1047
+
1048
+ };
1049
+ super(schema, {
1050
+ index, new: isNew, parent,
1051
+ state: [],
1052
+ setValue(v) { return Array.isArray(v) ? v : v == null ? [] : [v] },
1053
+ setState(v) { return Array.isArray(v) ? v : v == null ? [] : [v] },
1054
+ convert(v, state) {
1055
+ const val = Array.isArray(v) ? v : v == null ? [] : [v];
1056
+ updateChildren(val);
1057
+ return [
1058
+ val,
1059
+ (Array.isArray(state) ? state : v == null ? [] : [state]),
1060
+ ];
1061
+ },
1062
+ onUpdate:(value, index) => {
1063
+ updateChildren(value);
1064
+ onUpdate?.(value, index);
1065
+ },
1066
+ onUpdateState,
1067
+ });
1068
+ const childCommonOptions = {
1069
+ parent: this,
1070
+ /** @param {*} value @param {*} index */
1071
+ onUpdate: (value, index) => {
1072
+ const val = [...this.value || []];
1073
+ if (val.length < index) {
1074
+ val.length = index;
1075
+ }
1076
+ val[index] = value;
1077
+ this.value = val;
1078
+ },
1079
+ /** @param {*} state @param {*} index */
1080
+ onUpdateState: (state, index) => {
1081
+ const sta = [...this.state || []];
1082
+ if (sta.length < index) {
1083
+ sta.length = index;
1084
+ }
1085
+ sta[index] = state;
1086
+ this.state = sta;
1087
+ },
1088
+ };
1089
+ if (typeof schema.type === 'string') {
1090
+ this.#create = (index, isNew) => {
1091
+ const child = new Store(schema, {...childCommonOptions, index, new: isNew });
1092
+ child.index = index;
1093
+ return child
1094
+ };
1095
+ } else if (!Array.isArray(schema.props)) {
1096
+ this.#create = (index, isNew) => {
1097
+ const child = new ObjectStore(schema, { ...childCommonOptions, index, new: isNew});
1098
+ child.index = index;
1099
+ return child
1100
+ };
1101
+ } else {
1102
+ throw new Error();
1103
+ }
1104
+
1105
+ }
1106
+ /**
1107
+ *
1108
+ * @param {number} index
1109
+ * @param {T} value
1110
+ * @param {boolean} [isNew]
1111
+ * @returns
1112
+ */
1113
+ insert(index, value, isNew) {
1114
+ if (this.destroyed) { return false; }
1115
+ const data = this.value;
1116
+ if (!Array.isArray(data)) { return false; }
1117
+ const children = [...this.#children.get()];
1118
+ const insertIndex = Math.max(0, Math.min(Math.floor(index), children.length));
1119
+ const item = this.#create(insertIndex, isNew);
1120
+ item.new = true;
1121
+ children.splice(insertIndex, 0, item);
1122
+ for (let i = index + 1; i < children.length; i++) {
1123
+ children[i].index = i;
1124
+ }
1125
+ const val = [...data];
1126
+ val.splice(insertIndex, 0, value);
1127
+ const state = this.state;
1128
+ if (Array.isArray(state)) {
1129
+ const sta = [...state];
1130
+ sta.splice(insertIndex, 0, {});
1131
+ this.state = sta;
1132
+ }
1133
+ this.value = val;
1134
+ this.length = children.length;
1135
+ this.#children.set(children);
1136
+ return true;
1137
+ }
1138
+ /**
1139
+ *
1140
+ * @param {T} value
1141
+ * @returns
1142
+ */
1143
+ add(value) {
1144
+ return this.insert(this.#children.get().length, value);
1145
+ }
1146
+ /**
1147
+ *
1148
+ * @param {number} index
1149
+ * @returns
1150
+ */
1151
+ remove(index) {
1152
+ if (this.destroyed) { return; }
1153
+ const data = this.value;
1154
+ if (!Array.isArray(data)) { return; }
1155
+ const children = [...this.#children.get()];
1156
+ const removeIndex = Math.max(0, Math.min(Math.floor(index), children.length));
1157
+ const [item] = children.splice(removeIndex, 1);
1158
+ if (!item) { return; }
1159
+ for (let i = index; i < children.length; i++) {
1160
+ children[i].index = i;
1161
+ }
1162
+ item.destroy();
1163
+ const val = [...data];
1164
+ const [value] = val.splice(removeIndex, 1);
1165
+ const state = this.state;
1166
+ if (Array.isArray(state)) {
1167
+ const sta = [...this.state];
1168
+ sta.splice(removeIndex, 1);
1169
+ this.state = sta;
1170
+ }
1171
+ this.value = val;
1172
+ this.length = children.length;
1173
+ this.#children.set(children);
1174
+ return value;
1175
+
1176
+ }
1177
+ /**
1178
+ *
1179
+ * @param {number} from
1180
+ * @param {number} to
1181
+ * @returns
1182
+ */
1183
+ move(from, to) {
1184
+ if (this.destroyed) { return false; }
1185
+ const data = this.value;
1186
+ if (!Array.isArray(data)) { return false; }
1187
+ const children = [...this.#children.get()];
1188
+ const [item] = children.splice(from, 1);
1189
+ if (!item) { return false; }
1190
+ children.splice(to, 0, item);
1191
+ let lft = Math.min(from, to);
1192
+ let rgt = Math.max(from, to);
1193
+ for (let i = lft; i <= rgt; i++) {
1194
+ children[i].index = i;
1195
+ }
1196
+ const val = [...data];
1197
+ const [value] = val.splice(from, 1);
1198
+ val.splice(to, 0, value);
1199
+ const state = this.state;
1200
+ if (Array.isArray(state)) {
1201
+ const sta = [...state];
1202
+ const [value = {}] = sta.splice(from, 1);
1203
+ if (to <= sta.length) {
1204
+ sta.splice(to, 0, value);
1205
+ } else {
1206
+ sta[to] = value;
1207
+ }
1208
+ this.state = sta;
1209
+ }
1210
+ this.value = val;
1211
+ this.#children.set(children);
1212
+ return true;
1213
+
1214
+ }
1215
+ /**
1216
+ *
1217
+ * @param {number} a
1218
+ * @param {number} b
1219
+ * @returns
1220
+ */
1221
+ exchange(a, b) {
1222
+ if (this.destroyed) { return false; }
1223
+ const data = this.value;
1224
+ if (!Array.isArray(data)) { return false; }
1225
+ const children = [...this.#children.get()];
1226
+ const aItem = children[a];
1227
+ const bItem = children[b];
1228
+ if (!aItem || !bItem) { return false; }
1229
+ children[b] = aItem;
1230
+ children[a] = bItem;
1231
+ aItem.index = b;
1232
+ bItem.index = a;
1233
+ const val = [...data];
1234
+ const aValue = val[a];
1235
+ const bValue = val[b];
1236
+ val[b] = aValue;
1237
+ val[a] = bValue;
1238
+ const state = this.state;
1239
+ if (Array.isArray(state)) {
1240
+ const sta = [...state];
1241
+ const aValue = sta[a];
1242
+ const bValue = sta[b];
1243
+ sta[b] = aValue;
1244
+ sta[a] = bValue;
1245
+ this.state = sta;
1246
+ }
1247
+ this.value = val;
1248
+ this.#children.set(children);
1249
+ return true;
1250
+ }
1251
+ }
1252
+
1253
+ const errors = {
1254
+ CALC: 'no `creteCalc` option, no expression parsing support',
1255
+ EVENT: 'no `creteEvent`, options, no event parsing support',
1256
+ /** @param {string} endTag @param {string} startTag */
1257
+ CLOSE: (endTag, startTag) => `end tag name: ${endTag} is not match the current start tagName: ${startTag}`,
1258
+ /** @param {string} name */
1259
+ UNCLOSE: (name) => `end tag name: ${name} maybe not complete`,
1260
+ /** @param {string} char */
1261
+ QUOTE: (char) => `attribute value no end \'${char}\' match`,
1262
+ CLOSE_SYMBOL: `elements closed character '/' and '>' must be connected to`,
1263
+ /** @param {string} endTag @param {string} [startTag] */
1264
+ UNCOMPLETED: (endTag, startTag) => startTag
1265
+ ? `end tag name: ${endTag} is not complete: ${startTag}`
1266
+ : `end tag name: ${endTag} maybe not complete`,
1267
+ /** @param {string} entity */
1268
+ ENTITY: entity => `entity not found: ${entity}`,
1269
+ /** @param {string} symbol */
1270
+ SYMBOL: symbol => `unexpected symbol: ${symbol}`,
1271
+ /** @param {string} tag */
1272
+ TAG: tag => `invalid tagName: ${tag}`,
1273
+ /** @param {string} attr */
1274
+ ATTR: attr => `invalid attribute: ${attr}`,
1275
+ EQUAL: 'attribute equal must after attrName',
1276
+ ATTR_VALUE: 'attribute value must after "="',
1277
+ EOF: `unexpected end of file`,
1278
+ };
1279
+ class ParseError extends Error {
1280
+ /**
1281
+ * @param {keyof typeof errors} code
1282
+ * @param {...*} p
1283
+ */
1284
+ constructor(code, ...p) {
1285
+ /** @type {*} */
1286
+ const f = errors[code];
1287
+ if (typeof f === 'function') {
1288
+ super(f(...p));
1289
+
1290
+ } else {
1291
+ super(f);
1292
+ }
1293
+ this.code = code;
1294
+ }
1295
+ }
1296
+
1297
+ /** @import * as Layout from './index.mjs' */
1298
+
1299
+ const attrPattern = /^(?<decorator>[:@!+*\.]|style:|样式:)?(?<name>-?[\w\p{Unified_Ideograph}_][-\w\p{Unified_Ideograph}_:\d\.]*)$/u;
1300
+ const nameRegex = /^(?<name>[a-zA-Z$\p{Unified_Ideograph}_][\da-zA-Z$\p{Unified_Ideograph}_]*)?$/u;
1301
+ /**
1302
+ * @param {Layout.Node} node
1303
+ * @param {Exclude<Layout.Options['creteCalc'], undefined>} creteCalc
1304
+ * @param {Exclude<Layout.Options['creteEvent'], undefined>} creteEvent
1305
+ */
1306
+ function createAttributeAdder(node, creteCalc, creteEvent) {
1307
+ const { attrs, directives, events, classes, styles, vars, aliases } = node;
1308
+ /**
1309
+ * @param {string} qName
1310
+ * @param {string} value
1311
+ */
1312
+ function addAttribute(qName, value) {
1313
+ const attr = attrPattern.exec(qName
1314
+ .replace(/./g,'.')
1315
+ .replace(/:/g,':')
1316
+ .replace(/@/g,'@')
1317
+ .replace(/+/g,'+')
1318
+ .replace(/-/g,'-')
1319
+ .replace(/[*×]/g,'*')
1320
+ .replace(/!/g, '!'))?.groups;
1321
+ if (!attr) { throw new ParseError('ATTR', qName); }
1322
+ const { name } = attr;
1323
+ const decorator = attr.decorator?.toLowerCase();
1324
+ if (!decorator) {
1325
+ attrs[name] = value;
1326
+ } else if (decorator === ':') {
1327
+ attrs[name] = nameRegex.test(value) ? {name: value} : creteCalc(value);
1328
+ } else if (decorator === '.') {
1329
+ classes[name] = !value ? true : nameRegex.test(value) ? value : creteCalc(value);
1330
+ } else if (decorator === 'style:') {
1331
+ styles[name] = nameRegex.test(value) ? value : creteCalc(value);
1332
+ } else if (decorator === '@') {
1333
+ events[name] = nameRegex.test(value) ? value : creteEvent(value);
1334
+ } else if (decorator === '+') {
1335
+ vars[name] = !value ? '' : nameRegex.test(value) ? value : creteCalc(value);
1336
+ } else if (decorator === '*') {
1337
+ aliases[name] = nameRegex.test(value) ? value : creteEvent(value);
1338
+ } else if (decorator === '!') {
1339
+ const key = name.toString();
1340
+ switch (key) {
1341
+ case 'fragment':
1342
+ case 'else':
1343
+ case 'enum':
1344
+ directives[key] = true;
1345
+ break;
1346
+ case 'if':
1347
+ case 'text':
1348
+ case 'html':
1349
+ directives[key] = nameRegex.test(value) ? value : creteCalc(value);
1350
+ break;
1351
+ case 'bind':
1352
+ case 'value':
1353
+ case 'comment':
1354
+ directives[key] = value;
1355
+ break;
1356
+ }
1357
+ }
1358
+ }
1359
+ return addAttribute;
1360
+ }
1361
+
1362
+ /** @import * as Layout from './index.mjs' */
1363
+
1364
+ /**
1365
+ * @param {string} name
1366
+ * @param {string?} [is]
1367
+ * @returns {Layout.Node}
1368
+ *
1369
+ */
1370
+ function createElement(name, is) {
1371
+ return {
1372
+ name,
1373
+ is,
1374
+ children: [],
1375
+ attrs: Object.create(null),
1376
+ events: Object.create(null),
1377
+ directives: Object.create(null),
1378
+ classes: Object.create(null),
1379
+ styles: Object.create(null),
1380
+ vars: Object.create(null),
1381
+ aliases: Object.create(null),
1382
+ };
1383
+ }
1384
+
1385
+ /** @type {Record<string, string>} */
1386
+ var entityMap = {
1387
+ lt: '<',
1388
+ gt: '>',
1389
+ amp: '&',
1390
+ quot: '"',
1391
+ apos: "'",
1392
+
1393
+ Agrave: 'À',
1394
+ Aacute: 'Á',
1395
+ Acirc: 'Â',
1396
+ Atilde: 'Ã',
1397
+ Auml: 'Ä',
1398
+ Aring: 'Å',
1399
+ AElig: 'Æ',
1400
+ Ccedil: 'Ç',
1401
+ Egrave: 'È',
1402
+ Eacute: 'É',
1403
+ Ecirc: 'Ê',
1404
+ Euml: 'Ë',
1405
+ Igrave: 'Ì',
1406
+ Iacute: 'Í',
1407
+ Icirc: 'Î',
1408
+ Iuml: 'Ï',
1409
+ ETH: 'Ð',
1410
+ Ntilde: 'Ñ',
1411
+ Ograve: 'Ò',
1412
+ Oacute: 'Ó',
1413
+ Ocirc: 'Ô',
1414
+ Otilde: 'Õ',
1415
+ Ouml: 'Ö',
1416
+ Oslash: 'Ø',
1417
+ Ugrave: 'Ù',
1418
+ Uacute: 'Ú',
1419
+ Ucirc: 'Û',
1420
+ Uuml: 'Ü',
1421
+ Yacute: 'Ý',
1422
+ THORN: 'Þ',
1423
+ szlig: 'ß',
1424
+ agrave: 'à',
1425
+ aacute: 'á',
1426
+ acirc: 'â',
1427
+ atilde: 'ã',
1428
+ auml: 'ä',
1429
+ aring: 'å',
1430
+ aelig: 'æ',
1431
+ ccedil: 'ç',
1432
+ egrave: 'è',
1433
+ eacute: 'é',
1434
+ ecirc: 'ê',
1435
+ euml: 'ë',
1436
+ igrave: 'ì',
1437
+ iacute: 'í',
1438
+ icirc: 'î',
1439
+ iuml: 'ï',
1440
+ eth: 'ð',
1441
+ ntilde: 'ñ',
1442
+ ograve: 'ò',
1443
+ oacute: 'ó',
1444
+ ocirc: 'ô',
1445
+ otilde: 'õ',
1446
+ ouml: 'ö',
1447
+ oslash: 'ø',
1448
+ ugrave: 'ù',
1449
+ uacute: 'ú',
1450
+ ucirc: 'û',
1451
+ uuml: 'ü',
1452
+ yacute: 'ý',
1453
+ thorn: 'þ',
1454
+ yuml: 'ÿ',
1455
+ nbsp: '\u00a0',
1456
+ iexcl: '¡',
1457
+ cent: '¢',
1458
+ pound: '£',
1459
+ curren: '¤',
1460
+ yen: '¥',
1461
+ brvbar: '¦',
1462
+ sect: '§',
1463
+ uml: '¨',
1464
+ copy: '©',
1465
+ ordf: 'ª',
1466
+ laquo: '«',
1467
+ not: '¬',
1468
+ shy: '­­',
1469
+ reg: '®',
1470
+ macr: '¯',
1471
+ deg: '°',
1472
+ plusmn: '±',
1473
+ sup2: '²',
1474
+ sup3: '³',
1475
+ acute: '´',
1476
+ micro: 'µ',
1477
+ para: '¶',
1478
+ middot: '·',
1479
+ cedil: '¸',
1480
+ sup1: '¹',
1481
+ ordm: 'º',
1482
+ raquo: '»',
1483
+ frac14: '¼',
1484
+ frac12: '½',
1485
+ frac34: '¾',
1486
+ iquest: '¿',
1487
+ times: '×',
1488
+ divide: '÷',
1489
+ forall: '∀',
1490
+ part: '∂',
1491
+ exist: '∃',
1492
+ empty: '∅',
1493
+ nabla: '∇',
1494
+ isin: '∈',
1495
+ notin: '∉',
1496
+ ni: '∋',
1497
+ prod: '∏',
1498
+ sum: '∑',
1499
+ minus: '−',
1500
+ lowast: '∗',
1501
+ radic: '√',
1502
+ prop: '∝',
1503
+ infin: '∞',
1504
+ ang: '∠',
1505
+ and: '∧',
1506
+ or: '∨',
1507
+ cap: '∩',
1508
+ cup: '∪',
1509
+ 'int': '∫',
1510
+ there4: '∴',
1511
+ sim: '∼',
1512
+ cong: '≅',
1513
+ asymp: '≈',
1514
+ ne: '≠',
1515
+ equiv: '≡',
1516
+ le: '≤',
1517
+ ge: '≥',
1518
+ sub: '⊂',
1519
+ sup: '⊃',
1520
+ nsub: '⊄',
1521
+ sube: '⊆',
1522
+ supe: '⊇',
1523
+ oplus: '⊕',
1524
+ otimes: '⊗',
1525
+ perp: '⊥',
1526
+ sdot: '⋅',
1527
+ Alpha: 'Α',
1528
+ Beta: 'Β',
1529
+ Gamma: 'Γ',
1530
+ Delta: 'Δ',
1531
+ Epsilon: 'Ε',
1532
+ Zeta: 'Ζ',
1533
+ Eta: 'Η',
1534
+ Theta: 'Θ',
1535
+ Iota: 'Ι',
1536
+ Kappa: 'Κ',
1537
+ Lambda: 'Λ',
1538
+ Mu: 'Μ',
1539
+ Nu: 'Ν',
1540
+ Xi: 'Ξ',
1541
+ Omicron: 'Ο',
1542
+ Pi: 'Π',
1543
+ Rho: 'Ρ',
1544
+ Sigma: 'Σ',
1545
+ Tau: 'Τ',
1546
+ Upsilon: 'Υ',
1547
+ Phi: 'Φ',
1548
+ Chi: 'Χ',
1549
+ Psi: 'Ψ',
1550
+ Omega: 'Ω',
1551
+ alpha: 'α',
1552
+ beta: 'β',
1553
+ gamma: 'γ',
1554
+ delta: 'δ',
1555
+ epsilon: 'ε',
1556
+ zeta: 'ζ',
1557
+ eta: 'η',
1558
+ theta: 'θ',
1559
+ iota: 'ι',
1560
+ kappa: 'κ',
1561
+ lambda: 'λ',
1562
+ mu: 'μ',
1563
+ nu: 'ν',
1564
+ xi: 'ξ',
1565
+ omicron: 'ο',
1566
+ pi: 'π',
1567
+ rho: 'ρ',
1568
+ sigmaf: 'ς',
1569
+ sigma: 'σ',
1570
+ tau: 'τ',
1571
+ upsilon: 'υ',
1572
+ phi: 'φ',
1573
+ chi: 'χ',
1574
+ psi: 'ψ',
1575
+ omega: 'ω',
1576
+ thetasym: 'ϑ',
1577
+ upsih: 'ϒ',
1578
+ piv: 'ϖ',
1579
+ OElig: 'Œ',
1580
+ oelig: 'œ',
1581
+ Scaron: 'Š',
1582
+ scaron: 'š',
1583
+ Yuml: 'Ÿ',
1584
+ fnof: 'ƒ',
1585
+ circ: 'ˆ',
1586
+ tilde: '˜',
1587
+ ensp: ' ',
1588
+ emsp: ' ',
1589
+ thinsp: ' ',
1590
+ zwnj: '‌',
1591
+ zwj: '‍',
1592
+ lrm: '‎',
1593
+ rlm: '‏',
1594
+ ndash: '–',
1595
+ mdash: '—',
1596
+ lsquo: '‘',
1597
+ rsquo: '’',
1598
+ sbquo: '‚',
1599
+ ldquo: '“',
1600
+ rdquo: '”',
1601
+ bdquo: '„',
1602
+ dagger: '†',
1603
+ Dagger: '‡',
1604
+ bull: '•',
1605
+ hellip: '…',
1606
+ permil: '‰',
1607
+ prime: '′',
1608
+ Prime: '″',
1609
+ lsaquo: '‹',
1610
+ rsaquo: '›',
1611
+ oline: '‾',
1612
+ euro: '€',
1613
+ trade: '™',
1614
+ larr: '←',
1615
+ uarr: '↑',
1616
+ rarr: '→',
1617
+ darr: '↓',
1618
+ harr: '↔',
1619
+ crarr: '↵',
1620
+ lceil: '⌈',
1621
+ rceil: '⌉',
1622
+ lfloor: '⌊',
1623
+ rfloor: '⌋',
1624
+ loz: '◊',
1625
+ spades: '♠',
1626
+ clubs: '♣',
1627
+ hearts: '♥',
1628
+ diams: '♦'
1629
+ };
1630
+
1631
+ /** @import * as Layout from './index.mjs' */
1632
+
1633
+ const tagNamePattern = /^(?<name>[\w\p{Unified_Ideograph}_][-\.\|:|d\w\p{Unified_Ideograph}_:]*)(?:|(?<is>[\w\p{Unified_Ideograph}_][-\.\|:|d\w\p{Unified_Ideograph}_]*))?$/u;
1634
+
1635
+ /**
1636
+ *
1637
+ * @param {string} c
1638
+ * @returns
1639
+ */
1640
+ function isSpace(c) {
1641
+ return c === '0x80' || c <= ' ';
1642
+ }
1643
+ /**
1644
+ *
1645
+ * @param {string} c
1646
+ * @returns
1647
+ */
1648
+ function isIdCode(c) {
1649
+ return c !== '=' && c !== '/' && c !== '>' && c && c !== '\'' && c !== '"' && !isSpace(c);
1650
+ }
1651
+
1652
+ /**
1653
+ *
1654
+ * @param {string} source
1655
+ * @param {number} elStartEnd
1656
+ * @param {string} name
1657
+ * @param {*} closeMap
1658
+ * @returns
1659
+ */
1660
+ function fixSelfClosed(source, elStartEnd, name, closeMap) {
1661
+ let pos = closeMap[name];
1662
+ if (pos == null) {
1663
+ pos = source.lastIndexOf('</' + name + '>');
1664
+ if (pos < elStartEnd) {
1665
+ pos = source.lastIndexOf('</' + name);
1666
+ }
1667
+ closeMap[name] = pos;
1668
+ }
1669
+ return pos < elStartEnd;
1670
+ }
1671
+
1672
+ /**
1673
+ * @param {ConstructorParameters<typeof ParseError>} p
1674
+ */
1675
+ function error(...p) {
1676
+ console.error(new ParseError(...p));
1677
+ }
1678
+
1679
+ /**
1680
+ *
1681
+ * @param {string} a
1682
+ * @returns {string}
1683
+ */
1684
+ function entityReplacer(a) {
1685
+ const k = a.slice(1, -1);
1686
+ if (k.charAt(0) === '#') {
1687
+ return String.fromCodePoint(parseInt(k.substring(1).replace('x', '0x')));
1688
+ }
1689
+ if (k in entityMap) { return entityMap[k]; }
1690
+ error('ENTITY', a);
1691
+ return a;
1692
+ }
1693
+ /**
1694
+ *
1695
+ * @param {string} source
1696
+ * @param {Layout.Options} [options]
1697
+ * @returns {(Layout.Node | string)[]}
1698
+ */
1699
+ function parse(source, {
1700
+ creteCalc = () => { throw new ParseError('CALC'); },
1701
+ creteEvent = () => { throw new ParseError('EVENT'); },
1702
+ simpleTag = new Set,
1703
+ } = {}) {
1704
+ /** @type {(Layout.Node | string)[]} */
1705
+ const children = [];
1706
+
1707
+ const doc = { children };
1708
+ /** @type {(Layout.Node | null)[]} */
1709
+ const stack = [];
1710
+ /** @type {Layout.Node?} */
1711
+ let currentNode = null;
1712
+ /** @type {typeof doc | Layout.Node} */
1713
+ let current = doc;
1714
+ function endElement() {
1715
+ currentNode = stack.pop() || null;
1716
+ current = currentNode || doc;
1717
+ }
1718
+ /**
1719
+ *
1720
+ * @param {string} chars
1721
+ * @returns
1722
+ */
1723
+ function characters(chars) {
1724
+ chars = chars.replace(/^\n|(?<=\n)\t+|\n\t*$/g, '');
1725
+ if (!chars) { return; }
1726
+ current.children.push(chars);
1727
+ }
1728
+
1729
+ let closeMap = {};
1730
+ let index = 0;
1731
+ /**
1732
+ *
1733
+ * @param {number} end
1734
+ */
1735
+ function appendText(end) {
1736
+ if (end <= index) { return; }
1737
+ const xt = source.substring(index, end).replace(/&#?\w+;/g, entityReplacer);
1738
+ characters(xt);
1739
+ index = end;
1740
+ }
1741
+ for (; ;) {
1742
+ const tagStart = source.indexOf('<', index);
1743
+ if (tagStart < 0) {
1744
+ const text = source.substring(index);
1745
+ if (!text.match(/^\s*$/)) {
1746
+ characters(text);
1747
+ }
1748
+ break;
1749
+ }
1750
+ if (tagStart > index) {
1751
+ appendText(tagStart);
1752
+ }
1753
+ if (source.charAt(tagStart + 1) === '/') {
1754
+ index = source.indexOf('>', tagStart + 3);
1755
+ let name = source.substring(tagStart + 2, index);
1756
+ if (index < 0) {
1757
+ name = source.substring(tagStart + 2).replace(/[\s<].*/, '');
1758
+ error('UNCOMPLETED', name, currentNode?.name);
1759
+ index = tagStart + 1 + name.length;
1760
+ } else if (name.match(/\s</)) {
1761
+ name = name.replace(/[\s<].*/, '');
1762
+ error('UNCOMPLETED', name);
1763
+ index = tagStart + 1 + name.length;
1764
+ }
1765
+ if (currentNode) {
1766
+ const currentName = currentNode.name;
1767
+ if (currentName === name) {
1768
+ endElement();
1769
+ } else if (currentName.toLowerCase() == name.toLowerCase()) {
1770
+ endElement();
1771
+ } else {
1772
+ throw new ParseError('CLOSE', name, currentNode.name);
1773
+ }
1774
+ }
1775
+ index++;
1776
+ continue;
1777
+ }
1778
+ index = tagStart + 1;
1779
+ /**
1780
+ *
1781
+ * @param {string} c
1782
+ * @returns
1783
+ */
1784
+ function getQuote(c) {
1785
+ let start = index + 1;
1786
+ index = source.indexOf(c, start);
1787
+ if (index < 0) { throw new ParseError('QUOTE', c); }
1788
+ const value = source.slice(start, index).replace(/&#?\w+;/g, entityReplacer);
1789
+ index++;
1790
+ return value;
1791
+ }
1792
+ function skipSpace() {
1793
+ let c = source.charAt(index);
1794
+ for (; c <= ' ' || c === '\u0080'; c = source.charAt(++index)) { }
1795
+ return c;
1796
+
1797
+ }
1798
+ function getId() {
1799
+ let start = index;
1800
+ let c = source.charAt(index);
1801
+ while (isIdCode(c)) {
1802
+ index++;
1803
+ c = source.charAt(index);
1804
+ }
1805
+ return source.slice(start, index);
1806
+ }
1807
+ let c = source.charAt(index);
1808
+ switch (c) {
1809
+ case '=': throw new ParseError('EQUAL');
1810
+ case '"': case '\'': throw new ParseError('ATTR_VALUE');
1811
+ case '>': case '/': throw new ParseError('SYMBOL', c);
1812
+ case '': throw new ParseError('EOF');
1813
+ }
1814
+ const name = getId();
1815
+ const tagRes = tagNamePattern.exec(name)?.groups;
1816
+ if (!tagRes) { throw new ParseError('TAG', name); }
1817
+ stack.push(currentNode);
1818
+ currentNode = createElement(tagRes.name, tagRes.is);
1819
+ current.children.push(currentNode);
1820
+ current = currentNode;
1821
+ const addAttribute = createAttributeAdder(currentNode, creteCalc, creteEvent);
1822
+
1823
+ let run = true;
1824
+ let closed = false;
1825
+ parseAttr: for (; run;) {
1826
+ let c = skipSpace();
1827
+ switch (c) {
1828
+ case '': error('EOF'); index++; break parseAttr;
1829
+ case '>': index++; break parseAttr;
1830
+ case '/': closed = true; break parseAttr;
1831
+ case '"': case '\'': throw new ParseError('ATTR_VALUE');
1832
+ case '=': throw new ParseError('SYMBOL', c);
1833
+ }
1834
+ const id = getId();
1835
+ if (!id) { error('EOF'); index++; break parseAttr; }
1836
+ c = skipSpace();
1837
+ switch (c) {
1838
+ case '': error('EOF'); index++; break parseAttr;
1839
+ case '>': addAttribute(id, ''); index++; break parseAttr;
1840
+ case '/': addAttribute(id, ''); closed = true; break parseAttr;
1841
+ case '=': index++; break;
1842
+ case '\'': case '"': addAttribute(id, getQuote(c)); continue;
1843
+ default: addAttribute(id, ''); continue;
1844
+ }
1845
+ c = skipSpace();
1846
+ switch (c) {
1847
+ case '': addAttribute(id, ''); error('EOF'); index++; break parseAttr;
1848
+ case '>': addAttribute(id, ''); index++; break parseAttr;
1849
+ case '/': addAttribute(id, ''); closed = true; break parseAttr;
1850
+ case '\'': case '"': addAttribute(id, getQuote(c)); continue;
1851
+ }
1852
+ addAttribute(id, getId());
1853
+ }
1854
+ if (closed) {
1855
+ while (true) {
1856
+ index++;
1857
+ const c = source.charAt(index);
1858
+ if (c === '/') { continue; }
1859
+ if (c <= ' ' || c === '\u0080') { continue; }
1860
+ break;
1861
+ }
1862
+ const c = source.charAt(index);
1863
+ switch (c) {
1864
+ case '=': throw new ParseError('EQUAL');
1865
+ case '"': case '\'': throw new ParseError('ATTR_VALUE'); // No known test case
1866
+ case '': error('EOF'); break;
1867
+ case '>': index++; break;
1868
+ default: throw new ParseError('CLOSE_SYMBOL');
1869
+ }
1870
+ endElement();
1871
+ } else if (simpleTag.has(name) || fixSelfClosed(source, index, name, closeMap)) {
1872
+ endElement();
1873
+ }
1874
+ }
1875
+ return children;
1876
+ }
1877
+
1878
+ /** @import * as Layout from './index.mjs' */
1879
+
1880
+ /**
1881
+ *
1882
+ * @param {*} c
1883
+ * @returns
1884
+ */
1885
+ function _xmlEncoder(c) {
1886
+ return c == '<' && '&lt;' ||
1887
+ c == '>' && '&gt;' ||
1888
+ c == '&' && '&amp;' ||
1889
+ c == '"' && '&quot;' ||
1890
+ '&#' + c.charCodeAt() + ';';
1891
+ }
1892
+
1893
+ /**
1894
+ *
1895
+ * @param {Layout.Node} node
1896
+ * @param {number} [level]
1897
+ * @returns {Iterable<string>}
1898
+ */
1899
+ function* nodeToString(node, level = 0) {
1900
+ const { attrs, events, directives, children, is, name, classes, styles, aliases, vars } = node;
1901
+ const pad = level > 0 ? ''.padEnd(level, '\t') : '';
1902
+
1903
+ yield pad;
1904
+ yield* ['<', name || '-'];
1905
+ if (is) { yield* ['|', is]; }
1906
+
1907
+ for (const [name, value] of Object.entries(directives)) {
1908
+ if (value === false || value == null) { continue; }
1909
+ const val = typeof value === 'function' ? String(value) : value;
1910
+ yield* [' !', name];
1911
+ if (val && typeof val === 'string') {
1912
+ yield* ['="', val.replace(/[<&"]/g, _xmlEncoder), '"'];
1913
+ }
1914
+ }
1915
+ for (const [name, value] of Object.entries(aliases)) {
1916
+ if (value == null) { continue; }
1917
+ const val = typeof value === 'function' ? String(value) : value;
1918
+ yield* [' *', name];
1919
+ if (val && typeof val === 'string') {
1920
+ yield* ['="', val.replace(/[<&"]/g, _xmlEncoder), '"'];
1921
+ }
1922
+ }
1923
+ for (const [name, value] of Object.entries(vars)) {
1924
+ if (value == null) { continue; }
1925
+ const val = typeof value === 'function' ? String(value) : value;
1926
+ yield* [' +', name];
1927
+ if (val && typeof val === 'string') {
1928
+ yield* ['="', val.replace(/[<&"]/g, _xmlEncoder), '"'];
1929
+ }
1930
+ }
1931
+ for (const [name, value] of Object.entries(attrs)) {
1932
+ if (value == null) { continue; }
1933
+ if (typeof value === 'string') {
1934
+ yield* [' ', name];
1935
+ if (value) {
1936
+ yield* ['="', value.replace(/[<&"]/g, _xmlEncoder), '"'];
1937
+ }
1938
+ continue;
1939
+ }
1940
+ const val = typeof value === 'function' ? String(value) : typeof value === 'object' ? value.name : value;
1941
+ if (val && typeof val === 'string') {
1942
+ yield* [' :', name, '="', val.replace(/[<&"]/g, _xmlEncoder) || '', '"'];
1943
+ }
1944
+ }
1945
+ for (const [name, value] of Object.entries(events)) {
1946
+ if (value == null) { continue; }
1947
+ const val = typeof value === 'function' ? String(value) : value;
1948
+ if (val && typeof val === 'string') {
1949
+ yield* [' @', name, '="', val.replace(/[<&"]/g, _xmlEncoder), '"'];
1950
+ }
1951
+ }
1952
+ for (const [name, value] of Object.entries(classes)) {
1953
+ if (value == null || value == false) { continue; }
1954
+ const val = typeof value === 'function' ? String(value) : value;
1955
+ yield* [' .', name];
1956
+ if (val && typeof val === 'string') {
1957
+ yield* [' .', name, '="', val.replace(/[<&"]/g, _xmlEncoder), '"'];
1958
+ }
1959
+ }
1960
+ for (const [name, value] of Object.entries(styles)) {
1961
+ if (value == null) { continue; }
1962
+ const val = typeof value === 'function' ? String(value) : value;
1963
+ if (val && typeof val === 'string') {
1964
+ yield* [' style:', name, '="', val.replace(/[<&"]/g, _xmlEncoder), '"'];
1965
+ }
1966
+ }
1967
+ if (!children.length) {
1968
+ yield '/>';
1969
+ if (level >= 0) { yield '\n'; }
1970
+ return;
1971
+ }
1972
+ if (children.length === 1) {
1973
+ const [child] = children;
1974
+ if (typeof child === 'string' && child.length < 80 && !child.includes('\n')) {
1975
+ yield '>';
1976
+ yield* [child.replace(/[<&\t]/g, _xmlEncoder).replace(/]]>/g, ']]&gt;')];
1977
+ yield* ['</', name, '>'];
1978
+ if (level >= 0) { yield '\n'; }
1979
+ return;
1980
+ }
1981
+ }
1982
+ yield '>';
1983
+ if (level >= 0) { yield '\n'; }
1984
+ yield* listToString(children, level >= 0 ? level + 1 : -1);
1985
+ yield* [pad, '</', name, '>'];
1986
+ if (level >= 0) { yield '\n'; }
1987
+
1988
+ }
1989
+ /**
1990
+ *
1991
+ * @param {(Layout.Node |string)[]} nodes
1992
+ * @param {number} [level]
1993
+ * @returns {Iterable<string>}
1994
+ */
1995
+ function* listToString(nodes, level = 0) {
1996
+ if (!nodes.length) { return ''; }
1997
+
1998
+ const pad = level > 0 ? ''.padEnd(level, '\t') : '';
1999
+ for (const child of nodes) {
2000
+ if (typeof child === 'string') {
2001
+ let text = child.replace(/[<&\t]/g, _xmlEncoder).replace(/]]>/g, ']]&gt;');
2002
+ if (pad) {
2003
+ text = text.replace(/(?<=^|\n)/g, pad);
2004
+ }
2005
+ yield text;
2006
+ if (level >= 0) { yield '\n'; }
2007
+ } else {
2008
+ yield* nodeToString(child, level);
2009
+ }
2010
+ }
2011
+ }
2012
+ /**
2013
+ *
2014
+ * @param {Layout.Node | (Layout.Node |string)[]} value
2015
+ * @param {boolean} [formable]
2016
+ * @returns {string}
2017
+ */
2018
+ function toString(value, formable) {
2019
+ const level = formable ? 0 : -1;
2020
+ if (Array.isArray(value)) { return [...listToString(value, level)].join(''); }
2021
+ return [nodeToString(value, level)].join();
2022
+
2023
+ }
2024
+
2025
+ /**
2026
+ * @typedef {object} Directives
2027
+ *
2028
+ * @property {boolean} [fragment]
2029
+ *
2030
+ * @property {string | Function} [if]
2031
+ * @property {boolean} [else]
2032
+ *
2033
+ * @property {string} [value] 值关联(关联为列表)
2034
+ * @property {boolean} [enum] 列表属性枚举
2035
+ *
2036
+ * @property {string} [bind]
2037
+ * @property {string | Function} [text]
2038
+ * @property {string | Function} [html]
2039
+ *
2040
+ * @property {string | Function} [comment] 注释
2041
+ */
2042
+
2043
+
2044
+
2045
+ /**
2046
+ * @typedef {object} Options
2047
+ * @property {(t: string) => (vars: Record<string, any>) => any} [options.creteCalc]
2048
+ * @property {(t: string) => ($event: any, vars: Record<string, any>) => any} [options.creteEvent]
2049
+ * @property {Set<string>} [options.simpleTag]
2050
+ */
2051
+ /**
2052
+ * @typedef {object} Node
2053
+ * @property {string} name
2054
+ * @property {string?} [is]
2055
+ * @property {string} [id]
2056
+ * @property {Record<string, string | {name: string} | ((global: any) => void)>} attrs
2057
+ * @property {Record<string, string | boolean | ((global: any) => void)>} classes
2058
+ * @property {Record<string, string | ((global: any) => void)>} styles
2059
+ * @property {Record<string, string | (($event: any, global: any) => void)>} events
2060
+ * @property {Record<string, string | ((global: any) => void)>} vars
2061
+ * @property {Record<string, string | Function>} aliases
2062
+ * @property {Directives} directives
2063
+ * @property {(Node | string)[]} children
2064
+ */
2065
+
2066
+ var index$1 = /*#__PURE__*/Object.freeze({
2067
+ __proto__: null,
2068
+ parse: parse,
2069
+ stringify: toString
2070
+ });
2071
+
2072
+ let needsEnqueue = true;
2073
+
2074
+ const w = new exports.Signal.subtle.Watcher(() => {
2075
+ if (needsEnqueue) {
2076
+ needsEnqueue = false;
2077
+ queueMicrotask(processPending);
2078
+ }
2079
+ });
2080
+
2081
+ function processPending() {
2082
+ needsEnqueue = true;
2083
+
2084
+ for (const s of w.getPending()) {
2085
+ s.get();
2086
+ }
2087
+
2088
+ w.watch();
2089
+ }
2090
+
2091
+ /**
2092
+ * 创建可赋值计算值
2093
+ * @template T
2094
+ * @param {() => T} getter 取值方法
2095
+ * @param {(value: T) => void} callback 取值方法
2096
+ * @returns {() => void}
2097
+ */
2098
+ function watch(getter, callback) {
2099
+
2100
+ let run = false;
2101
+ /** @type {any} */
2102
+ let value;
2103
+ const computed = new exports.Signal.Computed(() => {
2104
+ const val = getter();
2105
+ if (run && Object.is(val, value)) { return; }
2106
+ value = val;
2107
+ run = true;
2108
+ callback(val);
2109
+ });
2110
+
2111
+ w.watch(computed);
2112
+ computed.get();
2113
+
2114
+ return () => { w.unwatch(computed); };
2115
+ }
2116
+
2117
+ /** @typedef {{get(): any; set?(v: any): void; exec?: null; store?: Store; calc?: null; }} ValueDefine */
2118
+ /** @typedef {{get?: null; exec(...p: any[]): any; calc?: null}} ExecDefine */
2119
+ /** @typedef {{get?: null; calc(...p: any[]): any; exec?: null;}} CalcDefine */
2120
+ /**
2121
+ *
2122
+ * @param {Store} val
2123
+ * @param {string | number} [key]
2124
+ * @returns {Iterable<[string, ValueDefine | ExecDefine | CalcDefine]>}
2125
+ */
2126
+ function *toItem(val, key = '', sign = '$') {
2127
+ yield [`${key}`, {get: () => val.value, set: v => val.value = v, store: val}];
2128
+ yield [`${key}${sign}value`, {get: () => val.value, set: v => val.value = v}];
2129
+ yield [`${key}${sign}state`, {get: () => val.state, set: v => val.state = v}];
2130
+ yield [`${key}${sign}null`, {get: () => val.null}];
2131
+ yield [`${key}${sign}index`, {get: () => val.index}];
2132
+ yield [`${key}${sign}no`, {get: () => val.no}];
2133
+ yield [`${key}${sign}length`, {get: () => val.length}];
2134
+ yield [`${key}${sign}creatable`, {get: () => val.creatable}];
2135
+ yield [`${key}${sign}immutable`, {get: () => val.immutable}];
2136
+ yield [`${key}${sign}new`, {get: () => val.new}];
2137
+ yield [`${key}${sign}editable`, {get: () => val.editable}];
2138
+ yield [`${key}${sign}hidden`, {get: () => val.hidden}];
2139
+ yield [`${key}${sign}clearable`, {get: () => val.clearable}];
2140
+ yield [`${key}${sign}required`, {get: () => val.required}];
2141
+ yield [`${key}${sign}disabled`, {get: () => val.disabled}];
2142
+ yield [`${key}${sign}readonly`, {get: () => val.readonly}];
2143
+ if (!(val instanceof ArrayStore)) { return; }
2144
+ yield [`${key}${sign}insert`, {exec: (index, value) => val.insert(index, value)}];
2145
+ yield [`${key}${sign}add`, {exec: (v) => val.add(v)}];
2146
+ yield [`${key}${sign}remove`, {exec: (index) => val.remove(index)}];
2147
+ yield [`${key}${sign}move`, {exec: (from, to) => val.move(from, to)}];
2148
+ yield [`${key}${sign}exchange`, {exec: (a, b) => val.exchange(a, b)}];
2149
+ }
2150
+ /**
2151
+ *
2152
+ * @param {Store?} parent
2153
+ * @param {Store} val
2154
+ * @param {string | number} [key]
2155
+ * @returns {Iterable<[string, ValueDefine | ExecDefine | CalcDefine]>}
2156
+ */
2157
+ function *toParentItem(parent, val, key = '', sign = '$') {
2158
+ if (!(parent instanceof ArrayStore)) {
2159
+ yield [`${key}${sign}upMovable`, {get: () => false}];
2160
+ yield [`${key}${sign}downMovable`, {get: () => false}];
2161
+ return
2162
+ }
2163
+ yield [`${key}${sign}upMovable`, {get: () => {
2164
+ const s = val.index;
2165
+ if (typeof s !== 'number') { return false; }
2166
+ if (s <= 0) { return false; }
2167
+ return true;
2168
+ }}];
2169
+ yield [`${key}${sign}downMovable`, {get: () => {
2170
+ const s = val.index;
2171
+ if (typeof s !== 'number') { return false; }
2172
+ if (s >= parent.length - 1) { return false; }
2173
+ return true;
2174
+ }}];
2175
+ yield [`${key}${sign}remove`, {exec: () => parent.remove(Number(val.index))}];
2176
+ yield [`${key}${sign}upMove`, {exec: () => {
2177
+ const s = val.index;
2178
+ if (typeof s !== 'number') { return; }
2179
+ if (s <= 0) { return; }
2180
+ parent.move(s, s - 1);
2181
+ }}];
2182
+ yield [`${key}${sign}downMove`, {exec: () => {
2183
+ const s = val.index;
2184
+ if (typeof s !== 'number') { return; }
2185
+ if (s >= parent.length - 1) { return; }
2186
+ parent.move(s, s + 1);
2187
+ }}];
2188
+ }
2189
+ class Environment {
2190
+ /**
2191
+ * @param {string | Function} value
2192
+ */
2193
+ exec(value) {
2194
+ if (typeof value === 'string') {
2195
+ const item = this.#items[value];
2196
+ if (typeof item?.get !== 'function') { return }
2197
+ return item.get();
2198
+ }
2199
+ if (typeof value === 'function') {
2200
+ return value(this.getters);
2201
+ }
2202
+ }
2203
+ /**
2204
+ * @param {string | Function} value
2205
+ * @param {(value: any) => void} cb
2206
+ */
2207
+ watch(value, cb) { return watch(() => this.exec(value), cb); }
2208
+
2209
+ /**
2210
+ * @param {string} name
2211
+ * @param {string} type
2212
+ * @param {(value: any) => void} cb
2213
+ */
2214
+ bind(name, type, cb) {
2215
+ const item = this.#items[name];
2216
+ if (!item?.get) { return; }
2217
+ const { store } = item;
2218
+ if (!store) { return; }
2219
+ switch(type) {
2220
+ case 'value': return watch(() => store.value, cb);
2221
+ case 'state': return watch(() => store.state, cb);
2222
+ case 'required': return watch(() => store.required, cb);
2223
+ case 'clearable': return watch(() => store.clearable, cb);
2224
+ case 'hidden': return watch(() => store.hidden, cb);
2225
+ case 'disabled': return watch(() => store.disabled, cb);
2226
+ case 'readonly': return watch(() => store.readonly || !store.editable, cb);
2227
+ }
2228
+ }
2229
+ /**
2230
+ * @param {string} name
2231
+ * @returns {Record<string, ((cb: (value: any) => void) => () => void) | void> | void}
2232
+ */
2233
+ bindAll(name) {
2234
+ const item = this.#items[name];
2235
+ if (!item?.get) { return; }
2236
+ const { store } = item;
2237
+ if (!store) {
2238
+ const get = item.get;
2239
+ if (typeof get !== 'function') { return; }
2240
+ return { '$value': cb => watch(get, cb) }
2241
+ }
2242
+ return {
2243
+ '$value': cb => watch(() => store.value, cb),
2244
+ '$state': cb => watch(() => store.state, cb),
2245
+ '$required': cb => watch(() => store.required, cb),
2246
+ '$clearable': cb => watch(() => store.clearable, cb),
2247
+ '$hidden': cb => watch(() => store.hidden, cb),
2248
+ '$disabled': cb => watch(() => store.disabled, cb),
2249
+ '$readonly': cb => watch(() => store.readonly || !store.editable, cb),
2250
+ }
2251
+ }
2252
+ /**
2253
+ * @param {string} name
2254
+ * @param {string} type
2255
+ * @returns {((value: any) => void) | void}
2256
+ */
2257
+ bindSet(name, type) {
2258
+ const item = this.#items[name];
2259
+ if (!item?.get) { return; }
2260
+ const { store } = item;
2261
+ if (!store) { return; }
2262
+ switch(type) {
2263
+ case 'value': return v => {store.value = v; };
2264
+ case 'state': return v => {store.state = v; };
2265
+ }
2266
+ }
2267
+ /**
2268
+ * @param {string} name
2269
+ * @returns {Record<string, ((value: any) => void) | void> | void}
2270
+ */
2271
+ bindStateAllSet(name) {
2272
+ const item = this.#items[name];
2273
+ if (!item?.get) { return; }
2274
+ const { store } = item;
2275
+ if (!store) {
2276
+ const set = item.set;
2277
+ if (typeof set !== 'function') { return; }
2278
+ return { '$value': set }
2279
+ }
2280
+ return {
2281
+ '$value': v => {store.value = v; },
2282
+ '$state': v => {store.state = v; },
2283
+ }
2284
+ }
2285
+
2286
+ /**
2287
+ * @param {string | (($event: any, global: any) => any)} event
2288
+ * @returns {(($event: any, global: any) => any)?}
2289
+ */
2290
+ getEvent(event) {
2291
+ if (typeof event === 'function') { return event }
2292
+ const item = this.#items[event];
2293
+ if (!item) { return null }
2294
+ const {exec, calc} = item;
2295
+ if (typeof exec === 'function') { return exec }
2296
+ if (typeof calc === 'function') { return calc }
2297
+ return null
2298
+
2299
+ }
2300
+ /**
2301
+ *
2302
+ * @param {Environment | Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }>?} [global]
2303
+ */
2304
+ constructor(global) {
2305
+ if (global instanceof Environment) {
2306
+ this.#global = global.#global;
2307
+ const schemaItems = this.#schemaItems;
2308
+ for (const [k, v] of Object.entries(global.#schemaItems)) {
2309
+ schemaItems[k] = v;
2310
+ }
2311
+ const explicit = this.#explicit;
2312
+ for (const [k, v] of Object.entries(global.#explicit)) {
2313
+ explicit[k] = v;
2314
+ }
2315
+ return;
2316
+ }
2317
+ const items = Object.create(null);
2318
+ this.#global = items;
2319
+ if (!global) { return }
2320
+ if (typeof global !== 'object') { return; }
2321
+ for (const [key, value] of Object.entries(global)) {
2322
+ if (!key || key.includes('$')) { continue; }
2323
+ if (!value || typeof value !== 'object') { return; }
2324
+ if (value instanceof Store) {
2325
+ for (const [k, v] of toItem(value, key)) {
2326
+ items[k] = v;
2327
+ }
2328
+ continue;
2329
+ }
2330
+ const {get,set,exec,calc} = value;
2331
+ if (typeof get === 'function') {
2332
+ items[key] = typeof set === 'function' ? {get,set} : {get};
2333
+ continue;
2334
+ }
2335
+ if (typeof calc === 'function') {
2336
+ items[key] = {calc};
2337
+ continue;
2338
+ }
2339
+ if (typeof exec === 'function') {
2340
+ items[key] = {exec};
2341
+ continue;
2342
+ }
2343
+ }
2344
+ }
2345
+ /** @type {Record<string, ValueDefine | ExecDefine | CalcDefine>} */
2346
+ #global
2347
+ /** @type {Record<string, ValueDefine | ExecDefine | CalcDefine>} */
2348
+ #schemaItems = Object.create(null);
2349
+ /** @type {Record<string, ValueDefine | ExecDefine | CalcDefine>} */
2350
+ #explicit = Object.create(null);
2351
+ /** @type {Store?} */
2352
+ #store = null
2353
+ /** @type {Store?} */
2354
+ #parent = null
2355
+ /** @type {Record<string, ValueDefine | ExecDefine | CalcDefine>?} */
2356
+ #allItems = null
2357
+ get #items() {
2358
+ const ai = this.#allItems;
2359
+ if (ai) { return ai; }
2360
+ /** @type {Record<string, ValueDefine | ExecDefine | CalcDefine>} */
2361
+ const ais = Object.create(null, Object.getOwnPropertyDescriptors({
2362
+ ...this.#schemaItems,
2363
+ ...this.#global,
2364
+ ...this.#explicit,
2365
+ }));
2366
+ const store = this.#store;
2367
+ const parent = this.#parent;
2368
+ if (store) {
2369
+ for (const [key, item] of toItem(store)) {
2370
+ ais[key] = item;
2371
+ }
2372
+ for (const [key, item] of toParentItem(parent, store)) {
2373
+ ais[key] = item;
2374
+ }
2375
+ }
2376
+ this.#allItems = ais;
2377
+ return ais;
2378
+ }
2379
+ /**
2380
+ *
2381
+ * @param {Store} store
2382
+ * @param {Store} [parent]
2383
+ */
2384
+ setValue(store, parent) {
2385
+ const cloned = new Environment(this);
2386
+ cloned.#store = store;
2387
+ if (parent) { cloned.#parent = parent; }
2388
+ if (store instanceof ArrayStore) { return cloned; }
2389
+ const items = cloned.#schemaItems;
2390
+ for (const [name, val] of store) {
2391
+ for (const [b, x] of toItem(val, name)) {
2392
+ items[b] = x;
2393
+ }
2394
+ for (const [b, x] of toItem(val, name, '$$')) {
2395
+ items[b] = x;
2396
+ }
2397
+ }
2398
+ return cloned;
2399
+ }
2400
+ /**
2401
+ *
2402
+ * @param {Record<string, string | Function>} aliases
2403
+ * @param {Record<string, any>} vars
2404
+ */
2405
+ set(aliases, vars) {
2406
+ if (Object.keys(aliases).length + Object.keys(vars).length === 0) { return this; }
2407
+ const cloned = new Environment(this);
2408
+ cloned.#store = this.#store;
2409
+ cloned.#parent = this.#parent;
2410
+ const explicit = cloned.#explicit;
2411
+ const items = cloned.#items;
2412
+ for (const [key, name] of Object.entries(aliases)) {
2413
+ if (typeof name === 'function') {
2414
+ const getters = cloned.getters;
2415
+ cloned.#getters = null;
2416
+ const val = new exports.Signal.Computed(() => name(getters));
2417
+ explicit[key] = items[key] = {
2418
+ get: () => { return val.get(); },
2419
+ };
2420
+ continue;
2421
+ }
2422
+ const item = items[name];
2423
+ if (!item) { continue; }
2424
+ if (!item.get || !item.store) {
2425
+ explicit[key] = items[key] = item;
2426
+ continue;
2427
+ }
2428
+ for (const [k, it] of toItem(item.store, key)) {
2429
+ explicit[k] = items[k] = it;
2430
+ }
2431
+ }
2432
+ for (const [k,v] of Object.entries(vars)) {
2433
+
2434
+ const val = new exports.Signal.State(/** @type {any} */(null));
2435
+ if (typeof v === 'function') {
2436
+ const settable = cloned.settable;
2437
+ cloned.#settable = null;
2438
+ val.set(v(settable));
2439
+ } else if (v && typeof v === 'string') {
2440
+ const item = items[v];
2441
+ if (!item?.get) { continue }
2442
+ val.set(item.get());
2443
+ }
2444
+ explicit[k] = items[k] = {
2445
+ get: () => { return val.get(); },
2446
+ set: (v) => { val.set(v); },
2447
+ };
2448
+ }
2449
+ return cloned;
2450
+ }
2451
+
2452
+ /** @type {Record<string, any>?} */
2453
+ #all = null;
2454
+ get all() {
2455
+ const gt = this.#all;
2456
+ if (gt) { return gt; }
2457
+ /** @type {Record<string, any>} */
2458
+ const ngt = {};
2459
+ for (const [key, item] of Object.entries(this.#items)) {
2460
+ if (item.get) {
2461
+ Object.defineProperty(ngt, key, {
2462
+ get: item.get,
2463
+ set: item.set,
2464
+ configurable: true,
2465
+ enumerable: true,
2466
+ });
2467
+ } else if (item.calc) {
2468
+ Object.defineProperty(ngt, key, {
2469
+ value: item.calc,
2470
+ writable: false,
2471
+ configurable: true,
2472
+ enumerable: false,
2473
+ });
2474
+ } else {
2475
+ Object.defineProperty(ngt, key, {
2476
+ value: item.exec,
2477
+ writable: false,
2478
+ configurable: true,
2479
+ enumerable: false,
2480
+ });
2481
+ }
2482
+ }
2483
+ this.#all = ngt;
2484
+ return ngt;
2485
+ }
2486
+ /** @type {Record<string, any>?} */
2487
+ #settable = null;
2488
+ get settable() {
2489
+ const gt = this.#settable;
2490
+ if (gt) { return gt; }
2491
+ /** @type {Record<string, any>} */
2492
+ const ngt = {};
2493
+ for (const [key, item] of Object.entries(this.#items)) {
2494
+ if (item.get) {
2495
+ Object.defineProperty(ngt, key, {
2496
+ get: item.get,
2497
+ set: item.set,
2498
+ configurable: true,
2499
+ enumerable: true,
2500
+ });
2501
+ } else if (item.calc) {
2502
+ Object.defineProperty(ngt, key, {
2503
+ value: item.calc,
2504
+ writable: false,
2505
+ configurable: true,
2506
+ enumerable: false,
2507
+ });
2508
+ }
2509
+ }
2510
+ this.#settable = ngt;
2511
+ return ngt;
2512
+ }
2513
+ /** @type {Record<string, any>?} */
2514
+ #getters = null;
2515
+ get getters() {
2516
+ const gt = this.#getters;
2517
+ if (gt) { return gt; }
2518
+ /** @type {Record<string, any>} */
2519
+ const ngt = {};
2520
+ for (const [key, item] of Object.entries(this.#items)) {
2521
+ if (item.get) {
2522
+ Object.defineProperty(ngt, key, {
2523
+ get: item.get,
2524
+ configurable: true,
2525
+ enumerable: true,
2526
+ });
2527
+ } else if (item.calc) {
2528
+ Object.defineProperty(ngt, key, {
2529
+ value: item.calc,
2530
+ writable: false,
2531
+ configurable: true,
2532
+ enumerable: false,
2533
+ });
2534
+ }
2535
+ }
2536
+ this.#getters = ngt;
2537
+ return ngt;
2538
+ }
2539
+ }
2540
+
2541
+ /** @import { Component } from '../types.mjs' */
2542
+
2543
+ /**
2544
+ * @param {Component.Handler} handler
2545
+ * @param {Environment} envs
2546
+ * @param {Record<string, string | {name: string} | ((...any: any) => void)>} attrs
2547
+ * @param {Record<string, Component.Attr>} componentAttrs
2548
+ * @param {string?} [bindValue]
2549
+ */
2550
+ function bindAttrs(handler, envs, attrs, componentAttrs, bindValue) {
2551
+
2552
+ let bk = new Set();
2553
+ for (const [name, attr] of Object.entries(componentAttrs)) {
2554
+ const attrValue = attrs[name];
2555
+ if (name in attrs) {
2556
+ if (typeof attrValue !== 'function' && typeof attrValue !== 'object') {
2557
+ handler.set(name, attrValue);
2558
+ continue;
2559
+ }
2560
+ const attrSchema = typeof attrValue === 'function' ? attrValue : attrValue.name;
2561
+ if (attr.immutable) {
2562
+ handler.set(name, envs.exec(attrSchema));
2563
+ continue;
2564
+ }
2565
+ bk.add(envs.watch(attrSchema, v => handler.set(name, v)));
2566
+ continue;
2567
+ }
2568
+ const bind = attr.bind;
2569
+ if (!bindValue || !bind) {
2570
+ handler.set(name, attr.default);
2571
+ continue;
2572
+ }
2573
+ if (typeof bind === 'string') {
2574
+ const r = envs.bind(bindValue, bind, v => handler.set(name, v));
2575
+ if (r) {
2576
+ bk.add(r);
2577
+ } else {
2578
+ handler.set(name, attr.default);
2579
+ }
2580
+ continue;
2581
+ }
2582
+ if (!Array.isArray(bind)) {
2583
+ handler.set(name, attr.default);
2584
+ continue;
2585
+ }
2586
+ const [event, set, isState] = bind;
2587
+ if (!event || typeof set !== 'function') {
2588
+ continue;
2589
+ }
2590
+ if (!isState) {
2591
+ bk.add(envs.watch(bindValue, v => handler.set(name, v)));
2592
+ handler.addEvent(event, (...args) => { envs.all[bindValue] = set(...args);});
2593
+ continue;
2594
+ }
2595
+ const r = envs.bind(bindValue, 'state', v => handler.set(name, v));
2596
+ if (!r) { continue; }
2597
+ bk.add(r);
2598
+ const s = envs.bindSet(bindValue, 'state');
2599
+ if (!s) { continue; }
2600
+ handler.addEvent(event, (...args) => { s(set(...args));});
2601
+ }
2602
+ // TODO: 创建组件
2603
+ return ()=> {
2604
+ const list = bk;
2605
+ bk = new Set();
2606
+ for (const s of list) {
2607
+ s();
2608
+ }
2609
+ }
2610
+ }
2611
+
2612
+ /** @import { Component } from '../types.mjs' */
2613
+
2614
+ /**
2615
+ * @param {Component.Handler} handler
2616
+ * @param {Environment} envs
2617
+ * @param {Record<string, string | {name: string} | ((...any: any) => void)>} attrs
2618
+ * @param {string?} [bindValue]
2619
+ */
2620
+ function bindBaseAttrs(handler, envs, attrs, bindValue) {
2621
+ const tag = handler.tag;
2622
+ let bk = new Set();
2623
+ for (const [name, attr] of Object.entries(attrs)) {
2624
+ if (typeof attr !== 'function' && typeof attr !== 'object') {
2625
+ handler.set(name, attr);
2626
+ continue;
2627
+ }
2628
+ const attrSchema = typeof attr === 'function' ? attr : attr.name;
2629
+ if (typeof tag === 'string' && tag.toLocaleLowerCase() === 'input' && name.toLocaleLowerCase() === 'type') {
2630
+ const value = envs.exec(attrSchema);
2631
+ handler.set(name, value);
2632
+ continue;
2633
+ }
2634
+ bk.add(envs.watch(attrSchema, val => handler.set(name, val)));
2635
+ }
2636
+ if (bindValue) {
2637
+ for (const [key, effect] of Object.entries(envs.bindAll(bindValue) || {})) {
2638
+ if (typeof effect !== 'function') { continue; }
2639
+ bk.add(effect(val => handler.set(key, val)));
2640
+ }
2641
+ for (const [key, setter] of Object.entries(envs.bindStateAllSet(bindValue) || {})) {
2642
+ if (typeof setter !== 'function') { continue; }
2643
+ handler.addEvent(key, $event => setter($event));
2644
+ }
2645
+ }
2646
+
2647
+ return ()=> {
2648
+ const list = bk;
2649
+ bk = new Set();
2650
+ for (const s of list) {
2651
+ s();
2652
+ }
2653
+ }
2654
+ }
2655
+
2656
+ /**
2657
+ * @param {Node} node
2658
+ * @param {Environment} envs
2659
+ * @param {Record<string, string | boolean | ((...any: any) => void)>} classes
2660
+ */
2661
+ function bindClasses(node, classes, envs) {
2662
+ if (!(node instanceof Element)) {
2663
+ return () => {};
2664
+ }
2665
+
2666
+ /** @type {Set<() => void>?} */
2667
+ let bk = new Set();
2668
+ for (const [name, attr] of Object.entries(classes)) {
2669
+ if (!attr) { continue; }
2670
+ if (attr === true) {
2671
+ node.classList.add(name);
2672
+ continue;
2673
+ }
2674
+ bk.add(watch(() => Boolean(envs.exec(attr)), value => {
2675
+ if (value) {
2676
+ node.classList.add(name);
2677
+ } else {
2678
+ node.classList.remove(name);
2679
+ }
2680
+ }));
2681
+ }
2682
+ // TODO: 创建组件
2683
+ return ()=> {
2684
+ if (!bk) { return; }
2685
+ const list = bk;
2686
+ bk = null;
2687
+ for (const s of list) {
2688
+ s();
2689
+ }
2690
+ }
2691
+ }
2692
+
2693
+ /** @type {Record<string, string>} */
2694
+ const unit = {
2695
+ 'width': 'px',
2696
+ 'height': 'px',
2697
+ 'top': 'px',
2698
+ 'right': 'px',
2699
+ 'bottom': 'px',
2700
+ 'left': 'px',
2701
+ 'border': 'px',
2702
+ 'border-top': 'px',
2703
+ 'border-right': 'px',
2704
+ 'border-left': 'px',
2705
+ 'border-bottom': 'px',
2706
+ 'border-width': 'px',
2707
+ 'border-top-width': 'px',
2708
+ 'border-right-width': 'px',
2709
+ 'border-left-width': 'px',
2710
+ 'border-bottom-width': 'px',
2711
+ 'border-radius': 'px',
2712
+ 'border-top-left-radius': 'px',
2713
+ 'border-top-right-radius': 'px',
2714
+ 'border-bottom-left-radius': 'px',
2715
+ 'border-bottom-right-radius': 'px',
2716
+ 'padding': 'px',
2717
+ 'padding-top': 'px',
2718
+ 'padding-right': 'px',
2719
+ 'padding-left': 'px',
2720
+ 'padding-bottom': 'px',
2721
+ 'margin': 'px',
2722
+ 'margin-top': 'px',
2723
+ 'margin-right': 'px',
2724
+ 'margin-left': 'px',
2725
+ 'margin-bottom': 'px',
2726
+ };
2727
+ /**
2728
+ *
2729
+ * @param {string} name
2730
+ * @param {any} value
2731
+ * @returns {[string, 'important' | undefined]?}
2732
+ */
2733
+ function toStyle(name, value) {
2734
+ let important = Array.isArray(value) ? Boolean(value[1]) : false;
2735
+ let style = '';
2736
+ /** @typedef {[string, 'important' | undefined]} Result */
2737
+ if (typeof value === 'string') {
2738
+ style = value.replace(/!important\s*$/, '');
2739
+ if (!style) { return null; }
2740
+ important = style !== value;
2741
+ return [style, important ? 'important' : undefined];
2742
+ }
2743
+ const val = Array.isArray(value) ? value[0] : value;
2744
+ if (typeof val === 'number' || typeof val === 'bigint') {
2745
+ style = val && name in unit ? `${ val }${ unit[name] }` : `${ val }`;
2746
+ } else if (typeof val === 'string') {
2747
+ style = val;
2748
+ }
2749
+ if (!style) { return null; }
2750
+ return [style, important ? 'important' : undefined];
2751
+
2752
+
2753
+ }
2754
+
2755
+
2756
+ /**
2757
+ * @param {Element} node
2758
+ * @param {Environment} envs
2759
+ * @param {Record<string, string | ((...any: any) => void)>} classes
2760
+ */
2761
+ function bindStyles(node, classes, envs) {
2762
+ if (!(node instanceof HTMLElement) && !(node instanceof SVGElement)) {
2763
+ return () => {};
2764
+ }
2765
+
2766
+ /** @type {Set<() => void>?} */
2767
+ let bk = new Set();
2768
+ for (const [name, attr] of Object.entries(classes)) {
2769
+ bk.add(watch(() => toStyle(name, envs.exec(attr)), value => {
2770
+ if (value) {
2771
+ node.style.setProperty(name, ...value);
2772
+ } else {
2773
+ node.style.removeProperty(name);
2774
+ }
2775
+ }));
2776
+ }
2777
+ // TODO: 创建组件
2778
+ return ()=> {
2779
+ if (!bk) { return; }
2780
+ const list = bk;
2781
+ bk = null;
2782
+ for (const s of list) {
2783
+ s();
2784
+ }
2785
+ }
2786
+ }
2787
+
2788
+ /**
2789
+ * @template {Record<string, any[]>} T
2790
+ */
2791
+ class EventEmitter {
2792
+ /** @type {Map<keyof T, Set<(...p: any[]) => void>>} */
2793
+ #events = new Map()
2794
+ /**
2795
+ *
2796
+ * @template {keyof T} K
2797
+ * @param {K} event
2798
+ * @param {T[K]} p
2799
+ */
2800
+ emit(event, ...p) {
2801
+ const key = typeof event === 'number' ? String(event) : event;
2802
+ const events = this.#events;
2803
+ for (const d of [...events.get(key) || []]) {
2804
+ d(...p);
2805
+ }
2806
+ }
2807
+ /**
2808
+ *
2809
+ * @template {keyof T} K
2810
+ * @param {K} event
2811
+ * @param {(...p: T[K]) => void} listener
2812
+ * @returns {() => void}
2813
+ */
2814
+ listen(event, listener) {
2815
+ /** @type {any} */
2816
+ const fn = listener.bind(this);
2817
+ const events = this.#events;
2818
+ const key = typeof event === 'number' ? String(event) : event;
2819
+ let set = events.get(key);
2820
+ if (!set) {
2821
+ set = new Set();
2822
+ events.set(key, set);
2823
+ }
2824
+ set.add(fn);
2825
+ return () => { set?.delete(fn); }
2826
+
2827
+ }
2828
+ }
2829
+
2830
+ /** @import { Component } from '../types.mjs' */
2831
+ /** @import Environment from './Environment.mjs' */
2832
+
2833
+
2834
+ /** @type {Record<string, (evt: any, param: string[], global: any) => boolean | null | void>} */
2835
+ const eventFilters = {
2836
+ stop(evt) {
2837
+ if (evt instanceof Event) { evt.stopPropagation(); }
2838
+ },
2839
+ prevent(evt) {
2840
+ if (evt instanceof Event) { evt.preventDefault(); }
2841
+ },
2842
+ self(evt) {
2843
+ if (evt instanceof Event) { return evt.target === evt.currentTarget; }
2844
+ },
2845
+ enter(evt) {
2846
+ if (evt instanceof KeyboardEvent) { return evt.key === 'Enter'; }
2847
+ },
2848
+ tab(evt) {
2849
+ if (evt instanceof KeyboardEvent) { return evt.key === 'Tab'; }
2850
+ },
2851
+ esc(evt) {
2852
+ if (evt instanceof KeyboardEvent) { return evt.key === 'Escape'; }
2853
+ },
2854
+ space(evt) {
2855
+ if (evt instanceof KeyboardEvent) { return evt.key === ' '; }
2856
+ },
2857
+ backspace(evt) {
2858
+ if (evt instanceof KeyboardEvent) { return evt.key === 'Backspace'; }
2859
+ },
2860
+ delete(evt) {
2861
+ if (evt instanceof KeyboardEvent) { return evt.key === 'Delete'; }
2862
+ },
2863
+ delBack(evt) {
2864
+ if (evt instanceof KeyboardEvent) { return evt.key === 'Delete' || evt.key === 'Backspace'; }
2865
+ },
2866
+ 'del-back'(evt) {
2867
+ if (evt instanceof KeyboardEvent) { return evt.key === 'Delete' || evt.key === 'Backspace'; }
2868
+ },
2869
+ insert(evt) {
2870
+ if (evt instanceof KeyboardEvent) { return evt.key === 'Insert'; }
2871
+ },
2872
+ repeat(evt) {
2873
+ if (evt instanceof KeyboardEvent) { return evt.repeat; }
2874
+ },
2875
+
2876
+ key(evt, param) {
2877
+ if (evt instanceof KeyboardEvent) {
2878
+ const key = evt.code.toLowerCase().replace(/-/g, '');
2879
+ for (const k of param) {
2880
+ if (key === k.toLowerCase().replace(/-/g, '')) { return true }
2881
+ }
2882
+ return false;
2883
+ }
2884
+ },
2885
+ main(evt) {
2886
+ if (evt instanceof MouseEvent) { return evt.button === 0; }
2887
+ },
2888
+ auxiliary(evt) {
2889
+ if (evt instanceof MouseEvent) { return evt.button === 1; }
2890
+ },
2891
+ secondary(evt) {
2892
+ if (evt instanceof MouseEvent) { return evt.button === 2; }
2893
+ },
2894
+ left(evt) {
2895
+ if (evt instanceof MouseEvent) { return evt.button === 0; }
2896
+ },
2897
+ middle(evt) {
2898
+ if (evt instanceof MouseEvent) { return evt.button === 1; }
2899
+ },
2900
+ right(evt) {
2901
+ if (evt instanceof MouseEvent) { return evt.button === 2; }
2902
+ },
2903
+ primary(evt) {
2904
+ if (evt instanceof PointerEvent) { return evt.isPrimary; }
2905
+ },
2906
+ mouse(evt) {
2907
+ if (evt instanceof PointerEvent) { return evt.pointerType === 'mouse'; }
2908
+ },
2909
+ pen(evt) {
2910
+ if (evt instanceof PointerEvent) { return evt.pointerType === 'pen'; }
2911
+ },
2912
+ touch(evt) {
2913
+ if (evt instanceof PointerEvent) { return evt.pointerType === 'touch'; }
2914
+ },
2915
+ pointer(evt, param) {
2916
+ if (evt instanceof PointerEvent) {
2917
+ const pointerType = evt.pointerType.toLowerCase().replace(/-/g, '');
2918
+ for (const k of param) {
2919
+ if (pointerType === k.toLowerCase().replace(/-/g, '')) { return true }
2920
+ }
2921
+ return false;
2922
+ }
2923
+ },
2924
+
2925
+ ctrl(evt) {
2926
+ if (evt instanceof MouseEvent|| evt instanceof KeyboardEvent || evt instanceof TouchEvent) {
2927
+ return evt.ctrlKey;
2928
+ }
2929
+ },
2930
+ alt(evt) {
2931
+ if (evt instanceof MouseEvent|| evt instanceof KeyboardEvent || evt instanceof TouchEvent) {
2932
+ return evt.altKey;
2933
+ }
2934
+ },
2935
+ shift(evt) {
2936
+ if (evt instanceof MouseEvent|| evt instanceof KeyboardEvent || evt instanceof TouchEvent) {
2937
+ return evt.shiftKey;
2938
+ }
2939
+ },
2940
+ meta(evt) {
2941
+ if (evt instanceof MouseEvent|| evt instanceof KeyboardEvent || evt instanceof TouchEvent) {
2942
+ return evt.metaKey;
2943
+ }
2944
+ },
2945
+ cmd(evt) {
2946
+ if (evt instanceof MouseEvent|| evt instanceof KeyboardEvent || evt instanceof TouchEvent) {
2947
+ return evt.ctrlKey || evt.metaKey;
2948
+ }
2949
+ },
2950
+ };
2951
+ /**
2952
+ *
2953
+ * @param {Component | string} component
2954
+ * @param {Environment} env
2955
+ * @returns
2956
+ */
2957
+ function createContext(component, env) {
2958
+ const tag = typeof component === 'string' ? component : component.tag;
2959
+ const { attrs, events } = typeof component !== 'string' && component || {attrs: null, events: null };
2960
+
2961
+ let destroyed = false;
2962
+ let init = false;
2963
+ const tagAttrs = Object.create(null);
2964
+
2965
+ /** @type {[string, ($event: any) => void, AddEventListenerOptions][]} */
2966
+ const allEvents = [];
2967
+ const stateEmitter = new EventEmitter();
2968
+ /** @type {EventEmitter<Record<string, [any, any, string]>>} */
2969
+ const attrEmitter = new EventEmitter();
2970
+ /** @type {Component.Context} */
2971
+ const context = {
2972
+ events: allEvents,
2973
+ props: attrs ? new Set(Object.entries(attrs).filter(([,a]) => a.isProp).map(([e]) => e)) : null,
2974
+ tagAttrs,
2975
+ watchAttr(name, fn) { return attrEmitter.listen(name, fn); },
2976
+ get destroyed() { return destroyed},
2977
+ get init() { return init},
2978
+ listen(name, listener) { return stateEmitter.listen(name, listener); },
2979
+ };
2980
+ /** @type {Component.Handler} */
2981
+ const handler = {
2982
+ tag,
2983
+ set(name, value) {
2984
+ if (attrs && !(name in attrs)) { return; }
2985
+ if (!(name in tagAttrs)) { tagAttrs[name] = void 0; }
2986
+ const old = tagAttrs[name];
2987
+ if (old === value) { return; }
2988
+ tagAttrs[name] = value;
2989
+ attrEmitter.emit(name, value, old, name);
2990
+ },
2991
+ addEvent(name, fn) {
2992
+ if (typeof fn !== 'function') { return; }
2993
+ const [e, ...fs] = name.split('.').filter(Boolean);
2994
+ const filters = events ? events[e].filters : {};
2995
+ if (!filters) { return; }
2996
+ /** @type {AddEventListenerOptions} */
2997
+ const options = {};
2998
+ /** @type {[($event: any, param: string[], env: any) => boolean | null | void, string[], boolean][]} */
2999
+ const filterFns = [];
3000
+ if (filters) for (let f = fs.shift();f;f = fs.shift()) {
3001
+ const paramIndex = f.indexOf(':');
3002
+ const noParamName = paramIndex >= 0 ? f.slice(0, paramIndex) : f;
3003
+ const param = paramIndex >= 0 ? f.slice(paramIndex + 1).split(':') : [];
3004
+ const filterName = noParamName.replace(/^-+/, '');
3005
+ const sub = (noParamName.length - filterName.length) % 2 === 1;
3006
+ let filter = filters[filterName] || filterName;
3007
+ switch(filter) {
3008
+ case 'once':
3009
+ options.once = !sub;
3010
+ break;
3011
+ case 'passive':
3012
+ options.passive = !sub;
3013
+ break;
3014
+ case 'capture':
3015
+ options.capture = !sub;
3016
+ break;
3017
+ default:
3018
+ if (typeof filter === 'string') {
3019
+ filter = eventFilters[filter];
3020
+ }
3021
+ }
3022
+ if (typeof filter !== 'function') { continue; }
3023
+ filterFns.push([filter, param, sub]);
3024
+ }
3025
+ allEvents.push([e, $event => {
3026
+ const global = env.all;
3027
+ for (const [filter, param, sub] of filterFns) {
3028
+ if (filter($event, param, global) === sub) { return}
3029
+ }
3030
+ fn($event, global);
3031
+ }, options]);
3032
+ },
3033
+ destroy() {
3034
+ if (destroyed) { return }
3035
+ destroyed = true;
3036
+ stateEmitter.emit('destroy');
3037
+ },
3038
+ init() {
3039
+ if (init) { return }
3040
+ init = true;
3041
+ stateEmitter.emit('init', {events: allEvents});
3042
+ },
3043
+
3044
+ };
3045
+ return { context, handler };
3046
+ }
3047
+
3048
+ /** @import { Component } from '../types.mjs' */
3049
+ /**
3050
+ *
3051
+ * @param {any} val
3052
+ * @returns
3053
+ */
3054
+ function toAttrValue(val) {
3055
+ if (typeof val === 'number') {
3056
+ return String(val);
3057
+ }
3058
+ if (typeof val === 'bigint') {
3059
+ return String(val);
3060
+ }
3061
+ if (typeof val === 'boolean') {
3062
+ return val ? '' : null;
3063
+ }
3064
+ if (typeof val === 'string') {
3065
+ return val;
3066
+ }
3067
+ if ((val ?? null) === null) {
3068
+ return null;
3069
+ }
3070
+ return String(val);
3071
+ }
3072
+ /**
3073
+ *
3074
+ * @param {any} val
3075
+ * @returns
3076
+ */
3077
+ function toText$1(val) {
3078
+ if ((val ?? null) === null) {
3079
+ return '';
3080
+ }
3081
+ return String(val);
3082
+ }
3083
+
3084
+
3085
+ /**
3086
+ *
3087
+ * @param {Element} el
3088
+ * @param {string} attr
3089
+ */
3090
+ function getAttrs(el, attr) {
3091
+ if (el instanceof HTMLInputElement && 'checked' === attr) {
3092
+ switch (el.type.toLowerCase()) {
3093
+ case 'checkbox':
3094
+ case 'radio':
3095
+ return Boolean;
3096
+ }
3097
+ }
3098
+ if ((
3099
+ el instanceof HTMLSelectElement
3100
+ || el instanceof HTMLInputElement
3101
+ || el instanceof HTMLTextAreaElement
3102
+ ) && 'value' === attr) {
3103
+ return toText$1;
3104
+ }
3105
+ if ((el instanceof HTMLDetailsElement) && 'open' === attr) {
3106
+ return Boolean;
3107
+ }
3108
+ if (el instanceof HTMLMediaElement) {
3109
+ if ('muted' === attr) {
3110
+ return Boolean;
3111
+ }
3112
+ if ('paused' === attr) {
3113
+ return Boolean;
3114
+ }
3115
+ if ('currentTime' === attr) {
3116
+ return true;
3117
+ }
3118
+ if ('playbackRate' === attr) {
3119
+ return true;
3120
+ }
3121
+ if ('volume' === attr) {
3122
+ return true;
3123
+ }
3124
+ }
3125
+ return false;
3126
+ }
3127
+
3128
+ /**
3129
+ * @typedef {object} TagBind
3130
+ * @property {Record<string, (value: any, el: any) => void>} attrs
3131
+ * @property {Record<string, [name: string, set: (event: any, el: any) => any]>} events
3132
+ */
3133
+ /** @type {Record<string, TagBind>} */
3134
+ const tagBindMap = {
3135
+ input: {
3136
+ attrs: {
3137
+ /** @param {any} v @param {HTMLInputElement} e */
3138
+ $disabled: (v, e) => {e.disabled = v;},
3139
+ /** @param {any} v @param {HTMLInputElement} e */
3140
+ $readonly: (v, e) => {e.readOnly = v;},
3141
+ /** @param {any} v @param {HTMLInputElement} e */
3142
+ $required: (v, e) => {e.required = v;},
3143
+ /** @param {any} v @param {HTMLInputElement} e */
3144
+ $value: (v, e) => {
3145
+ switch(e.type) {
3146
+ case 'checkbox':
3147
+ case 'radio':
3148
+ e.checked = Boolean(v);
3149
+ break;
3150
+ }
3151
+ e.value = toText$1(v);
3152
+ },
3153
+ },
3154
+ events: {
3155
+ $value: ['input', (v, e) => {
3156
+ switch(e.type) {
3157
+ case 'checkbox':
3158
+ case 'radio':
3159
+ return e.checked;
3160
+ case 'number':
3161
+ return Number(e.value);
3162
+ }
3163
+ return e.value;
3164
+ }],
3165
+ },
3166
+ },
3167
+ textarea: {
3168
+ attrs: {
3169
+ /** @param {any} v @param {HTMLInputElement} e */
3170
+ $disabled: (v, e) => {e.disabled = v;},
3171
+ /** @param {any} v @param {HTMLInputElement} e */
3172
+ $readonly: (v, e) => {e.readOnly = v;},
3173
+ /** @param {any} v @param {HTMLInputElement} e */
3174
+ $required: (v, e) => {e.required = v;},
3175
+ /** @param {any} v @param {HTMLInputElement} e */
3176
+ $value: (v, e) => { e.value = toText$1(v); },
3177
+ },
3178
+ events: {
3179
+ $value: ['input', (v, e) => { return e.value; }],
3180
+ },
3181
+ },
3182
+ select: {
3183
+ attrs: {
3184
+ /** @param {any} v @param {HTMLInputElement} e */
3185
+ $disabled: (v, e) => {e.disabled = v;},
3186
+ /** @param {any} v @param {HTMLInputElement} e */
3187
+ $readonly: (v, e) => {e.readOnly = v;},
3188
+ /** @param {any} v @param {HTMLInputElement} e */
3189
+ $required: (v, e) => {e.required = v;},
3190
+ /** @param {any} v @param {HTMLInputElement} e */
3191
+ $value: (v, e) => { e.value = toText$1(v); },
3192
+ },
3193
+ events: {
3194
+ $value: ['change', (v, e) => { return e.value; }],
3195
+ },
3196
+ },
3197
+ };
3198
+
3199
+ /**
3200
+ *
3201
+ * @param {Component.Context} context
3202
+ * @param {string} name
3203
+ * @param {string?} [is]
3204
+ */
3205
+ function createTagComponent (context, name, is) {
3206
+ const node = document.createElement(name, {is: is || undefined});
3207
+ const { watchAttr, props } = context;
3208
+
3209
+ context.listen('init', ({events})=> {
3210
+ const e = tagBindMap[name.toLowerCase()];
3211
+ const eAttrs = e?.attrs || {};
3212
+ const eEvents = e?.events || {};
3213
+ for (const [type, listener, options] of events) {
3214
+ if (type[0] === '$') {
3215
+ const e = eEvents[type];
3216
+ if (e) {
3217
+ const [evt, set] = e;
3218
+ node.addEventListener(evt, e => listener(set(e, node)), options);
3219
+ }
3220
+ continue;
3221
+ }
3222
+ node.addEventListener(type, listener, options);
3223
+ }
3224
+ if (props) {
3225
+ for (const [name, attr] of Object.entries(context.tagAttrs)) {
3226
+ watchAttr(name, v => {
3227
+ // @ts-ignore
3228
+ if (props.has(name)) { node[name] = v; } else {
3229
+ const val = toAttrValue(v);
3230
+ if (val == null) {
3231
+ node.removeAttribute(name);
3232
+ } else {
3233
+ node.setAttribute(name, val);
3234
+ }
3235
+ }
3236
+ });
3237
+ // @ts-ignore
3238
+ if (props.has(name)) { node[name] = attr; } else {
3239
+ const val = toAttrValue(attr);
3240
+ if (val !== null) {
3241
+ node.setAttribute(name, val);
3242
+ }
3243
+ }
3244
+ }
3245
+ return;
3246
+
3247
+ }
3248
+ for (const [name, attr] of Object.entries(context.tagAttrs)) {
3249
+ if (node instanceof HTMLInputElement && name.toLocaleLowerCase() === 'type') {
3250
+ const value = toAttrValue(attr);
3251
+ if (value !== null) {
3252
+ node.setAttribute(name, value);
3253
+ }
3254
+ continue;
3255
+ }
3256
+ if (name === '$hidden') {
3257
+ if (attr) { node.hidden = attr; }
3258
+ watchAttr(name, (val) => { node.hidden = val; });
3259
+ continue;
3260
+ }
3261
+
3262
+ if (name[0] === '$') {
3263
+ const e = eAttrs[name];
3264
+ if (e) {
3265
+ e(attr, node);
3266
+ watchAttr(name, (attr) => e(attr, node));
3267
+ }
3268
+ continue;
3269
+ }
3270
+ const prop = getAttrs(node, name);
3271
+ if (typeof prop === 'function') {
3272
+ // @ts-ignore
3273
+ node[name] = prop(attr);
3274
+ watchAttr(name, (attr) => {
3275
+ // @ts-ignore
3276
+ node[name] = prop(attr);
3277
+ });
3278
+ continue;
3279
+ }
3280
+ if (prop) {
3281
+ // @ts-ignore
3282
+ node[name] = attr;
3283
+ watchAttr(name, (attr) => {
3284
+ // @ts-ignore
3285
+ node[name] = attr;
3286
+ });
3287
+ continue;
3288
+ }
3289
+ let value = toAttrValue(attr);
3290
+ if (value !== null) {
3291
+ node.setAttribute(name, value);
3292
+ }
3293
+ watchAttr(name, (val) => {
3294
+ const value = toAttrValue(val);
3295
+ if (value === null) {
3296
+ node.removeAttribute(name);
3297
+ } else {
3298
+ node.setAttribute(name, value);
3299
+ }
3300
+ });
3301
+ }
3302
+ });
3303
+ return node;
3304
+ }
3305
+
3306
+ /** @import * as Layout from '../Layout/index.mjs' */
3307
+ /** @import Store, { ArrayStore } from '../Store/index.mjs' */
3308
+
3309
+ /**
3310
+ *
3311
+ * @param {Layout.Node} layout
3312
+ * @param {Element} parent
3313
+ * @param {Node?} next
3314
+ * @param {ArrayStore} store
3315
+ * @param {Environment} env
3316
+ * @param {(layout: Layout.Node, parent: Element, next: Node | null, store: Store, env: any) => () => void} renderItem
3317
+ */
3318
+ function renderArray(layout, parent, next, store, env, renderItem) {
3319
+ const start = parent.insertBefore(document.createComment(''), next);
3320
+ /** @type {Map<Store, [Comment, Comment, () => void]>} */
3321
+ let seMap = new Map();
3322
+ /** @param {Map<Store, [Comment, Comment, () => void]>} map */
3323
+ function destroyMap(map) {
3324
+ for (const [s, e, d] of map.values()) {
3325
+ d();
3326
+ s.remove();
3327
+ e.remove();
3328
+ }
3329
+
3330
+ }
3331
+ const childrenResult = watch(() => store.children, function render(children) {
3332
+ if (!start.parentNode) { return; }
3333
+ let nextNode = start.nextSibling;
3334
+ const oldSeMap = seMap;
3335
+ seMap = new Map();
3336
+ for (let child of children) {
3337
+ const old = oldSeMap.get(child);
3338
+ if (!old) {
3339
+ const ItemStart = parent.insertBefore(document.createComment(''), nextNode);
3340
+ const itemEnd = parent.insertBefore(document.createComment(''), nextNode);
3341
+ const d = renderItem(layout, parent, itemEnd, child, env.setValue(child, store));
3342
+ seMap.set(child, [ItemStart, itemEnd, d]);
3343
+ continue;
3344
+ }
3345
+ oldSeMap.delete(child);
3346
+ seMap.set(child, old);
3347
+ if (nextNode === old[0]) {
3348
+ nextNode = old[1].nextSibling;
3349
+ continue;
3350
+ }
3351
+ /** @type {Node?} */
3352
+ let c = old[0];
3353
+ while (c && c !== old[1]) {
3354
+ const o = c;
3355
+ c = c.nextSibling;
3356
+ parent.insertBefore(o, nextNode);
3357
+ }
3358
+ parent.insertBefore(old[1], nextNode);
3359
+ }
3360
+ destroyMap(oldSeMap);
3361
+ });
3362
+
3363
+ return () => {
3364
+ start.remove();
3365
+ childrenResult();
3366
+ };
3367
+ }
3368
+
3369
+ /** @import * as Layout from '../Layout/index.mjs' */
3370
+ /**
3371
+ *
3372
+ * @param {any} val
3373
+ * @returns
3374
+ */
3375
+ function toText(val) {
3376
+ if ((val ?? null) === null) {
3377
+ return '';
3378
+ }
3379
+ return String(val);
3380
+ }
3381
+
3382
+
3383
+ /**
3384
+ * @param {Element} parent
3385
+ * @param {Node?} next
3386
+ * @param {Environment} envs
3387
+ * @param {Layout.Directives} layout
3388
+ */
3389
+ function renderFillDirectives(parent, next, envs, { text, html }) {
3390
+ if (text != null) {
3391
+ const node = parent.insertBefore(document.createTextNode(''), next);
3392
+ const stop = envs.watch(text, val => node.textContent = toText(val));
3393
+ return () => {
3394
+ node.remove();
3395
+ stop();
3396
+ };
3397
+ }
3398
+ if (html == null) { return; }
3399
+ const start = parent.insertBefore(document.createComment(''), next);
3400
+ const end = parent.insertBefore(document.createComment(''), next);
3401
+ const div = document.createElement('div');
3402
+ /** @param {string} html */
3403
+ function add(html) {
3404
+ div.innerHTML = html;
3405
+ for (let node = div.firstChild; node; node = start.firstChild) {
3406
+ parent.insertBefore(node, end);
3407
+ }
3408
+ }
3409
+ function remove() {
3410
+ for (let node = start.nextSibling; node && node !== end; node = start.nextSibling) {
3411
+ node.remove();
3412
+ }
3413
+ }
3414
+ const result = envs.watch(html, val => {
3415
+ remove();
3416
+ add(toText(val));
3417
+ });
3418
+ return () => {
3419
+ result();
3420
+ remove();
3421
+ start.remove();
3422
+ end.remove();
3423
+ };
3424
+ }
3425
+
3426
+ /** @import * as Layout from '../Layout/index.mjs' */
3427
+
3428
+ /**
3429
+ * @param {(Layout.Node | string)[]} layouts
3430
+ * @param {Element} parent
3431
+ * @param {Node?} next
3432
+ * @param {Environment} envs
3433
+ * @param {(layout: Layout.Node) => () => void} renderItem
3434
+ * @returns {() => void}
3435
+ */
3436
+ function renderList(layouts, parent, next, envs, renderItem) {
3437
+
3438
+ /** @type {Set<() => void>?} */
3439
+ let bkList = new Set();
3440
+ /** @type {[string | Function | null, Layout.Node][]} */
3441
+ let ifList = [];
3442
+
3443
+ /** @param {[string | Function | null, Layout.Node][]} list */
3444
+ function renderIf(list) {
3445
+ if (!list.length || !bkList) { return; }
3446
+ const end = parent.insertBefore(document.createComment(''), next);
3447
+
3448
+
3449
+ let lastIndex = -1;
3450
+ let destroy = () => { };
3451
+ /**
3452
+ *
3453
+ * @param {number} index
3454
+ * @returns
3455
+ */
3456
+ function renderIndex(index) {
3457
+ const layout = list[index]?.[1];
3458
+ if (!layout) { return; }
3459
+ destroy = renderItem(layout);
3460
+ }
3461
+ bkList.add(() => {
3462
+ destroy();
3463
+ destroy = () => { };
3464
+ end.remove();
3465
+ });
3466
+ bkList.add(watch(
3467
+ () => list.findIndex(([ifv]) => ifv === null || envs.exec(ifv)),
3468
+ index => {
3469
+ if (index === lastIndex) { return; }
3470
+ lastIndex = index;
3471
+ destroy();
3472
+ destroy = () => { };
3473
+ renderIndex(lastIndex);
3474
+ },
3475
+ ));
3476
+ }
3477
+ for (const layout of layouts) {
3478
+ if (typeof layout === 'string') {
3479
+ renderIf(ifList);
3480
+ ifList = [];
3481
+ const node = document.createTextNode(layout);
3482
+ parent.insertBefore(node, next);
3483
+ bkList.add(() => node.remove());
3484
+ continue;
3485
+ }
3486
+ if (ifList.length && layout.directives.else) {
3487
+ const ifv = layout.directives.if || null;
3488
+ ifList.push([ifv, layout]);
3489
+ if (!ifv) {
3490
+ renderIf(ifList);
3491
+ ifList = [];
3492
+ }
3493
+ continue;
3494
+ }
3495
+ renderIf(ifList);
3496
+ ifList = [];
3497
+ const ifv = layout.directives.if;
3498
+ if (ifv) {
3499
+ ifList.push([ifv, layout]);
3500
+ continue;
3501
+ }
3502
+ bkList.add(
3503
+ renderItem(layout)
3504
+ );
3505
+ }
3506
+
3507
+ return () => {
3508
+ if (!bkList) { return; }
3509
+ const list = bkList;
3510
+ bkList = null;
3511
+ for (const s of list) {
3512
+ s();
3513
+ }
3514
+ };
3515
+ }
3516
+
3517
+ /** @import Store from '../Store/index.mjs' */
3518
+
3519
+ /**
3520
+ * @param {Layout.Node} layout
3521
+ * @param {Element} parent
3522
+ * @param {Node?} next
3523
+ * @param {Environment} env
3524
+ * @param {(layout: Layout.Node) => () => void} renderItem
3525
+ * @returns {() => void}
3526
+ */
3527
+ function renderFragment(layout, parent, next, env, renderItem) {
3528
+ return renderFillDirectives(parent, next, env, layout.directives) ||
3529
+ renderList(layout.children || [], parent, next, env, renderItem);
3530
+
3531
+ }
3532
+ /**
3533
+ * @param {Layout.Node} layout
3534
+ * @param {Element} parent
3535
+ * @param {Node?} next
3536
+ * @param {Store} store
3537
+ * @param {Environment} env
3538
+ * @param {string[]} componentPath
3539
+ * @param {((path: string[]) => Component?)?} [getComponent]
3540
+ */
3541
+ function renderItem(layout, parent, next, store, env, componentPath, getComponent) {
3542
+ env = env.set(layout.aliases, layout.vars);
3543
+ if (!layout.name || layout.directives.fragment) {
3544
+ return renderFragment(layout, parent, next, env, l => {
3545
+ return render(l, parent, next, store, env, componentPath, getComponent);
3546
+ });
3547
+ }
3548
+ const path = [...componentPath, layout.name];
3549
+ const component = getComponent?.(path);
3550
+ if (getComponent && !component) { return () => { }; }
3551
+ const { context, handler } = createContext(component ? component : layout.name, env);
3552
+
3553
+
3554
+ const componentAttrs = component?.attrs;
3555
+ const attrs = componentAttrs
3556
+ ? bindAttrs(handler, env, layout.attrs, componentAttrs, layout.directives.bind)
3557
+ : bindBaseAttrs(handler, env, layout.attrs, layout.directives.bind);
3558
+
3559
+ for (const [name, event] of Object.entries(layout.events)) {
3560
+ const fn = env.getEvent(event);
3561
+ if (fn) { handler.addEvent(name, fn); }
3562
+ }
3563
+
3564
+ const r = component ?
3565
+ typeof component.tag === 'function'
3566
+ ? component.tag(context)
3567
+ : createTagComponent(context, component.tag, component.is)
3568
+ : createTagComponent(context, layout.name, layout.is);
3569
+ const root = Array.isArray(r) ? r[0] : r;
3570
+ const slot = Array.isArray(r) && r[1] || root;
3571
+ parent.insertBefore(root, next);
3572
+ const children =
3573
+ renderFillDirectives(slot, null, env, layout.directives)
3574
+ || renderList(layout.children || [], slot, null, env, l => {
3575
+ return render(l, slot, null, store, env, componentPath, getComponent);
3576
+ });
3577
+
3578
+
3579
+ bindClasses(root, layout.classes, env);
3580
+ bindStyles(root, layout.styles, env);
3581
+
3582
+ handler.init();
3583
+ // TODO: 创建组件
3584
+ return () => {
3585
+ root.remove();
3586
+ handler.destroy();
3587
+ attrs();
3588
+ children();
3589
+ };
3590
+ }
3591
+ /**
3592
+ *
3593
+ * @param {Layout.Node} layout
3594
+ * @param {Element} parent
3595
+ * @param {Node?} next
3596
+ * @param {Store} store
3597
+ * @param {Environment} env
3598
+ * @param {string[]} componentPath
3599
+ * @param {((path: string[]) => Component?)?} [getComponent]
3600
+ * @returns {() => void}
3601
+ */
3602
+ function render(layout, parent, next, store, env, componentPath, getComponent) {
3603
+ const { directives } = layout;
3604
+ const { value } = directives;
3605
+ if (value) {
3606
+ const newStore = store.child(value);
3607
+ if (!newStore) { return () => {}; }
3608
+ store = newStore;
3609
+ env = env.setValue(store);
3610
+ }
3611
+ if (!directives.enum) {
3612
+ return renderItem(layout, parent, next, store, env, componentPath, getComponent);
3613
+ }
3614
+ if (!(store instanceof ArrayStore)) { return () => { }; }
3615
+ return renderArray(layout, parent, next, store, env, (a, b, c, store, env) => {
3616
+ return renderItem(a, b, c, store, env, componentPath, getComponent);
3617
+ });
3618
+ }
3619
+
3620
+ /**
3621
+ * @overload
3622
+ * @param {Store} store
3623
+ * @param {(Layout.Node | string)[]} layouts
3624
+ * @param {Element} parent
3625
+ * @param {Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }>} [global]
3626
+ * @param {(path: string[]) => Component?} [components]
3627
+ * @returns {() => void}
3628
+ */
3629
+ /**
3630
+ * @overload
3631
+ * @param {Store} store
3632
+ * @param {(Layout.Node | string)[]} layouts
3633
+ * @param {Element} parent
3634
+ * @param {((path: string[]) => Component?)?} [components]
3635
+ * @returns {() => void}
3636
+ */
3637
+ /**
3638
+ * @param {Store} store
3639
+ * @param {(Layout.Node | string)[]} layouts
3640
+ * @param {Element} parent
3641
+ * @param {((path: string[]) => Component?) | Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }> | null} [opt1]
3642
+ * @param {((path: string[]) => Component?) | Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }> | null} [opt2]
3643
+ */
3644
+ function index (store, layouts, parent, opt1, opt2) {
3645
+ const options = [opt1, opt2];
3646
+ const components = options.find(v => typeof v === 'function');
3647
+ const global = options.find(v => typeof v === 'object');
3648
+ const env = new Environment(global).setValue(store);
3649
+ return renderList(layouts, parent, null, env, l => {
3650
+ return render(l, parent, null, store, env, [], components);
3651
+ });
3652
+ }
3653
+
3654
+ exports.Layout = index$1;
3655
+ exports.Store = Store;
3656
+ exports.render = index;
3657
+
3658
+ }));