@neeloong/form 0.9.0 → 0.10.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/README.md +240 -79
- package/index.d.mts +449 -46
- package/index.js +157 -99
- package/index.min.js +2 -2
- package/index.min.mjs +2 -2
- package/index.mjs +157 -99
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @neeloong/form v0.
|
|
2
|
+
* @neeloong/form v0.10.0
|
|
3
3
|
* (c) 2024-2025 Fierflame
|
|
4
4
|
* @license Apache-2.0
|
|
5
5
|
*/
|
|
@@ -283,13 +283,14 @@ function merge(...v) {
|
|
|
283
283
|
/** @import { AsyncValidator, Schema, Validator } from '../types.mjs' */
|
|
284
284
|
|
|
285
285
|
/**
|
|
286
|
+
* 管理单个表单字段的状态和行为
|
|
286
287
|
* @template [T=any]
|
|
287
288
|
*/
|
|
288
289
|
class Store {
|
|
289
290
|
/** @type {Map<string, Set<(value: any, store: any) => void | boolean | null>>} */
|
|
290
291
|
#events = new Map()
|
|
291
292
|
/**
|
|
292
|
-
*
|
|
293
|
+
* 触发事件并通知监听器
|
|
293
294
|
* @template {keyof Schema.Events} K
|
|
294
295
|
* @param {K} event
|
|
295
296
|
* @param {Schema.Events[K]} value
|
|
@@ -304,7 +305,7 @@ class Store {
|
|
|
304
305
|
return !canceled;
|
|
305
306
|
}
|
|
306
307
|
/**
|
|
307
|
-
*
|
|
308
|
+
* 监听事件
|
|
308
309
|
* @template {keyof Schema.Events} K
|
|
309
310
|
* @param {K} event
|
|
310
311
|
* @param {(this: this, p: Schema.Events[K], store: this) => void | boolean | null} listener
|
|
@@ -324,14 +325,16 @@ class Store {
|
|
|
324
325
|
|
|
325
326
|
}
|
|
326
327
|
/**
|
|
327
|
-
*
|
|
328
|
-
* @param {
|
|
329
|
-
* @param {
|
|
328
|
+
* 从数据结构模式创建存储
|
|
329
|
+
* @param {Schema} schema 数据结构模式
|
|
330
|
+
* @param {object} [options] 选项
|
|
331
|
+
* @param {boolean} [options.new] 是否为新建环境
|
|
330
332
|
*/
|
|
331
333
|
static create(schema, options = {}) {
|
|
332
334
|
return create({type: schema}, { ...options, parent: null });
|
|
333
335
|
}
|
|
334
336
|
/**
|
|
337
|
+
* 设置自定义类型的存储类
|
|
335
338
|
* @param {string} type
|
|
336
339
|
* @param {{new(...p: ConstructorParameters<typeof Store>): Store}} Class
|
|
337
340
|
*/
|
|
@@ -339,14 +342,16 @@ class Store {
|
|
|
339
342
|
return setStore$1(type, Class);
|
|
340
343
|
}
|
|
341
344
|
#null = false;
|
|
345
|
+
/** 是否为无效空存储 */
|
|
342
346
|
get null() { return this.#null; }
|
|
347
|
+
/** 存储类类别,继承的自定义类需要设置自定义的此只读属性 */
|
|
343
348
|
get kind() { return ''; }
|
|
344
349
|
/** @type {Ref?} */
|
|
345
350
|
#ref = null;
|
|
346
351
|
get ref() { return this.#ref || createRef(this); }
|
|
347
352
|
/**
|
|
348
|
-
* @param {Schema.Field} schema
|
|
349
|
-
* @param {object} [options]
|
|
353
|
+
* @param {Schema.Field} schema 字段的 Schema 定义
|
|
354
|
+
* @param {object} [options] 可选配置
|
|
350
355
|
* @param {*} [options.parent]
|
|
351
356
|
* @param {*} [options.state]
|
|
352
357
|
* @param {number | string | null} [options.index]
|
|
@@ -510,19 +515,28 @@ class Store {
|
|
|
510
515
|
#meta;
|
|
511
516
|
/** @readonly @type {any} */
|
|
512
517
|
#component;
|
|
518
|
+
/** 存储对象自身 */
|
|
513
519
|
get store() { return this; }
|
|
520
|
+
/** 父级存储对象 */
|
|
514
521
|
get parent() { return this.#parent; }
|
|
522
|
+
/** 根节点的存储对象 */
|
|
515
523
|
get root() { return this.#root; }
|
|
524
|
+
/** 字段类型 */
|
|
516
525
|
get type() { return this.#type; }
|
|
526
|
+
/** 字段元信息 */
|
|
517
527
|
get meta() { return this.#meta; }
|
|
528
|
+
/** 自定义渲染组件信息 */
|
|
518
529
|
get component() { return this.#component; }
|
|
519
530
|
|
|
520
531
|
/** @type {Signal.State<number> | Signal.Computed<number>} */
|
|
521
532
|
#length;
|
|
533
|
+
/** 长度信息 */
|
|
522
534
|
get length() { return this.#length.get(); }
|
|
523
535
|
#index = new Signal.State(/** @type {string | number} */(''));
|
|
536
|
+
/** 索引信息 */
|
|
524
537
|
get index() { return this.#index.get(); }
|
|
525
538
|
set index(v) { this.#index.set(v); }
|
|
539
|
+
/** 数组项目的序号 */
|
|
526
540
|
get no() {
|
|
527
541
|
if (this.#null) { return ''; }
|
|
528
542
|
const index = this.index;
|
|
@@ -530,8 +544,10 @@ class Store {
|
|
|
530
544
|
}
|
|
531
545
|
|
|
532
546
|
#creatable = true;
|
|
547
|
+
/** 值是否可创建(`$new` 为 `true` 时,字段只读) */
|
|
533
548
|
get creatable() { return this.#creatable; }
|
|
534
549
|
#immutable = false;
|
|
550
|
+
/** 值是否不可改变(`$new` 为 `false` 时,字段只读) */
|
|
535
551
|
get immutable() { return this.#immutable; }
|
|
536
552
|
|
|
537
553
|
/** @readonly @type {Signal.Computed<boolean>} */
|
|
@@ -540,6 +556,7 @@ class Store {
|
|
|
540
556
|
#selfNew
|
|
541
557
|
get selfNew() { return this.#selfNew.get(); }
|
|
542
558
|
set selfNew(v) { this.#selfNew.set(Boolean(v)); }
|
|
559
|
+
/** 是否新建项 */
|
|
543
560
|
get new() { return this.#new.get(); }
|
|
544
561
|
set new(v) { this.#selfNew.set(Boolean(v)); }
|
|
545
562
|
|
|
@@ -549,6 +566,7 @@ class Store {
|
|
|
549
566
|
#hidden
|
|
550
567
|
get selfHidden() { return this.#selfHidden.get(); }
|
|
551
568
|
set selfHidden(v) { this.#selfHidden.set(typeof v === 'boolean' ? v : null); }
|
|
569
|
+
/** 是否可隐藏 */
|
|
552
570
|
get hidden() { return this.#hidden.get(); }
|
|
553
571
|
set hidden(v) { this.#selfHidden.set(typeof v === 'boolean' ? v : null); }
|
|
554
572
|
|
|
@@ -558,6 +576,7 @@ class Store {
|
|
|
558
576
|
#clearable
|
|
559
577
|
get selfClearable() { return this.#selfClearable.get(); }
|
|
560
578
|
set selfClearable(v) { this.#selfClearable.set(typeof v === 'boolean' ? v : null); }
|
|
579
|
+
/** 是否可清除 */
|
|
561
580
|
get clearable() { return this.#clearable.get(); }
|
|
562
581
|
set clearable(v) { this.#selfClearable.set(typeof v === 'boolean' ? v : null); }
|
|
563
582
|
|
|
@@ -567,6 +586,7 @@ class Store {
|
|
|
567
586
|
#required
|
|
568
587
|
get selfRequired() { return this.#selfRequired.get(); }
|
|
569
588
|
set selfRequired(v) { this.#selfRequired.set(typeof v === 'boolean' ? v : null); }
|
|
589
|
+
/** 是否必填 */
|
|
570
590
|
get required() { return this.#required.get(); }
|
|
571
591
|
set required(v) { this.#selfRequired.set(typeof v === 'boolean' ? v : null); }
|
|
572
592
|
|
|
@@ -576,6 +596,7 @@ class Store {
|
|
|
576
596
|
#disabled
|
|
577
597
|
get selfDisabled() { return this.#selfDisabled.get(); }
|
|
578
598
|
set selfDisabled(v) { this.#selfDisabled.set(typeof v === 'boolean' ? v : null); }
|
|
599
|
+
/** 是否禁用字段 */
|
|
579
600
|
get disabled() { return this.#disabled.get(); }
|
|
580
601
|
set disabled(v) { this.#selfDisabled.set(typeof v === 'boolean' ? v : null); }
|
|
581
602
|
|
|
@@ -585,6 +606,7 @@ class Store {
|
|
|
585
606
|
#readonly
|
|
586
607
|
get selfReadonly() { return this.#selfReadonly.get(); }
|
|
587
608
|
set selfReadonly(v) { this.#selfReadonly.set(typeof v === 'boolean' ? v : null); }
|
|
609
|
+
/** 是否只读 */
|
|
588
610
|
get readonly() { return this.#readonly.get(); }
|
|
589
611
|
set readonly(v) { this.#selfReadonly.set(typeof v === 'boolean' ? v : null); }
|
|
590
612
|
|
|
@@ -597,6 +619,7 @@ class Store {
|
|
|
597
619
|
#label
|
|
598
620
|
get selfLabel() { return this.#selfLabel.get(); }
|
|
599
621
|
set selfLabel(v) { this.#selfLabel.set(string(v)); }
|
|
622
|
+
/** 字段的标签信息 */
|
|
600
623
|
get label() { return this.#label.get(); }
|
|
601
624
|
set label(v) { this.#selfLabel.set(string(v)); }
|
|
602
625
|
|
|
@@ -607,6 +630,7 @@ class Store {
|
|
|
607
630
|
#description
|
|
608
631
|
get selfDescription() { return this.#selfDescription.get(); }
|
|
609
632
|
set selfDescription(v) { this.#selfDescription.set(string(v)); }
|
|
633
|
+
/** 字段的描述信息 */
|
|
610
634
|
get description() { return this.#description.get(); }
|
|
611
635
|
set description(v) { this.#selfDescription.set(string(v)); }
|
|
612
636
|
|
|
@@ -616,6 +640,7 @@ class Store {
|
|
|
616
640
|
#placeholder
|
|
617
641
|
get selfPlaceholder() { return this.#selfPlaceholder.get(); }
|
|
618
642
|
set selfPlaceholder(v) { this.#selfPlaceholder.set(string(v)); }
|
|
643
|
+
/** 字段的占位符信息 */
|
|
619
644
|
get placeholder() { return this.#placeholder.get(); }
|
|
620
645
|
set placeholder(v) { this.#selfPlaceholder.set(string(v)); }
|
|
621
646
|
|
|
@@ -626,6 +651,7 @@ class Store {
|
|
|
626
651
|
#min
|
|
627
652
|
get selfMin() { return this.#selfMin.get(); }
|
|
628
653
|
set selfMin(v) { this.#selfMin.set(number(v)); }
|
|
654
|
+
/** 数值字段的最小值限制 */
|
|
629
655
|
get min() { return this.#min.get(); }
|
|
630
656
|
set min(v) { this.#selfMin.set(number(v)); }
|
|
631
657
|
|
|
@@ -636,6 +662,7 @@ class Store {
|
|
|
636
662
|
#max
|
|
637
663
|
get selfMax() { return this.#selfMax.get(); }
|
|
638
664
|
set selfMax(v) { this.#selfMax.set(number(v)); }
|
|
665
|
+
/** 数值字段的最大值限制 */
|
|
639
666
|
get max() { return this.#max.get(); }
|
|
640
667
|
set max(v) { this.#selfMax.set(number(v)); }
|
|
641
668
|
|
|
@@ -646,6 +673,7 @@ class Store {
|
|
|
646
673
|
#step
|
|
647
674
|
get selfStep() { return this.#selfStep.get(); }
|
|
648
675
|
set selfStep(v) { this.#selfStep.set(number(v)); }
|
|
676
|
+
/** 数值字段的步长 */
|
|
649
677
|
get step() { return this.#step.get(); }
|
|
650
678
|
set step(v) { this.#selfStep.set(number(v)); }
|
|
651
679
|
|
|
@@ -655,6 +683,7 @@ class Store {
|
|
|
655
683
|
#minLength
|
|
656
684
|
get selfMinLength() { return this.#selfMinLength.get(); }
|
|
657
685
|
set selfMinLength(v) { this.#selfMinLength.set(number(v)); }
|
|
686
|
+
/** 最小长度 */
|
|
658
687
|
get minLength() { return this.#minLength.get(); }
|
|
659
688
|
set minLength(v) { this.#selfMinLength.set(number(v)); }
|
|
660
689
|
|
|
@@ -664,6 +693,7 @@ class Store {
|
|
|
664
693
|
#maxLength
|
|
665
694
|
get selfMaxLength() { return this.#selfMaxLength.get(); }
|
|
666
695
|
set selfMaxLength(v) { this.#selfMaxLength.set(number(v)); }
|
|
696
|
+
/** 最大长度 */
|
|
667
697
|
get maxLength() { return this.#maxLength.get(); }
|
|
668
698
|
set maxLength(v) { this.#selfMaxLength.set(number(v)); }
|
|
669
699
|
|
|
@@ -673,6 +703,7 @@ class Store {
|
|
|
673
703
|
#pattern
|
|
674
704
|
get selfPattern() { return this.#selfPattern.get(); }
|
|
675
705
|
set selfPattern(v) { this.#selfPattern.set(regex(v)); }
|
|
706
|
+
/** 模式 */
|
|
676
707
|
get pattern() { return this.#pattern.get(); }
|
|
677
708
|
set pattern(v) { this.#selfPattern.set(regex(v)); }
|
|
678
709
|
|
|
@@ -683,6 +714,7 @@ class Store {
|
|
|
683
714
|
#values
|
|
684
715
|
get selfValues() { return this.#selfValues.get(); }
|
|
685
716
|
set selfValues(v) { this.#selfValues.set(values$1(v)); }
|
|
717
|
+
/** 可选值列表 */
|
|
686
718
|
get values() { return this.#values.get(); }
|
|
687
719
|
set values(v) { this.#selfValues.set(values$1(v)); }
|
|
688
720
|
|
|
@@ -699,13 +731,15 @@ class Store {
|
|
|
699
731
|
#cancelChange
|
|
700
732
|
/** @type {() => void} */
|
|
701
733
|
#cancelBlur
|
|
734
|
+
/** 所有校验错误列表 */
|
|
702
735
|
get errors() { return this.#errors.get(); }
|
|
736
|
+
/** 字段校验错误信息 */
|
|
703
737
|
get error() { return this.#errors.get()[0]; }
|
|
704
738
|
|
|
705
739
|
/** @returns {IterableIterator<[key: string | number, value: Store]>} */
|
|
706
740
|
*[Symbol.iterator]() {}
|
|
707
741
|
/**
|
|
708
|
-
*
|
|
742
|
+
* 获取子存储
|
|
709
743
|
* @param {string | number} key
|
|
710
744
|
* @returns {Store?}
|
|
711
745
|
*/
|
|
@@ -718,8 +752,10 @@ class Store {
|
|
|
718
752
|
|
|
719
753
|
#state = new Signal.State(/** @type {any} */(null));
|
|
720
754
|
|
|
755
|
+
/** 内容是否已改变 */
|
|
721
756
|
get changed() { return this.#value.get() === this.#initValue.get(); }
|
|
722
757
|
|
|
758
|
+
/** 字段当前值 */
|
|
723
759
|
get value() { return this.#value.get(); }
|
|
724
760
|
set value(v) {
|
|
725
761
|
const newValue = this.#setValue?.(v);
|
|
@@ -732,6 +768,7 @@ class Store {
|
|
|
732
768
|
this.#requestUpdate();
|
|
733
769
|
}
|
|
734
770
|
|
|
771
|
+
/** 字段状态 */
|
|
735
772
|
get state() { return this.#state.get(); }
|
|
736
773
|
set state(v) {
|
|
737
774
|
const newState = this.#setState?.(v);
|
|
@@ -749,6 +786,7 @@ class Store {
|
|
|
749
786
|
this.#runUpdate(oldValue, oldState);
|
|
750
787
|
});
|
|
751
788
|
}
|
|
789
|
+
/** 重置数据 */
|
|
752
790
|
reset(value = this.#initValue.get()) {
|
|
753
791
|
this.#reset(value);
|
|
754
792
|
}
|
|
@@ -841,18 +879,19 @@ class Store {
|
|
|
841
879
|
return [val, sta];
|
|
842
880
|
}
|
|
843
881
|
/**
|
|
844
|
-
*
|
|
882
|
+
* 异步校验
|
|
845
883
|
* @overload
|
|
846
884
|
* @param {null} [path]
|
|
847
885
|
* @returns {Promise<string[] | null>}
|
|
848
886
|
*/
|
|
849
887
|
/**
|
|
888
|
+
* 异步校验
|
|
850
889
|
* @overload
|
|
851
|
-
* @param {(string | number)[]} path
|
|
890
|
+
* @param {(string | number)[]} path 到当前层级的路径
|
|
852
891
|
* @returns {Promise<{ path: (string | number)[]; store: Store; errors: string[]}[]>}
|
|
853
892
|
*/
|
|
854
893
|
/**
|
|
855
|
-
*
|
|
894
|
+
* 异步校验
|
|
856
895
|
* @param {(string | number)[]?} [path]
|
|
857
896
|
* @returns {Promise<string[] | { path: (string | number)[]; store: Store; errors: string[] | null;}[] | null>}
|
|
858
897
|
*/
|
|
@@ -1280,9 +1319,11 @@ function parse$1(value, createCalc) {
|
|
|
1280
1319
|
/**
|
|
1281
1320
|
* @param {Layout.Node} node
|
|
1282
1321
|
* @param {Exclude<Layout.Options['createCalc'], undefined>} createCalc
|
|
1322
|
+
* @param {Exclude<Layout.Options['createInit'], undefined>} createInit
|
|
1283
1323
|
* @param {Exclude<Layout.Options['createEvent'], undefined>} createEvent
|
|
1324
|
+
* @param {boolean} enableHTML
|
|
1284
1325
|
*/
|
|
1285
|
-
function createAttributeAdder(node, createCalc, createEvent) {
|
|
1326
|
+
function createAttributeAdder(node, createCalc, createInit, createEvent, enableHTML) {
|
|
1286
1327
|
const { attrs, events, classes, styles, vars, aliases, params, enhancements } = node;
|
|
1287
1328
|
/**
|
|
1288
1329
|
* @param {string} qName
|
|
@@ -1338,7 +1379,7 @@ function createAttributeAdder(node, createCalc, createEvent) {
|
|
|
1338
1379
|
return;
|
|
1339
1380
|
}
|
|
1340
1381
|
if (decorator === '+') {
|
|
1341
|
-
vars[name] = !value ? {value: undefined} : parse$1(value,
|
|
1382
|
+
vars[name] = !value ? {value: undefined} : parse$1(value, createInit);
|
|
1342
1383
|
return;
|
|
1343
1384
|
}
|
|
1344
1385
|
if (decorator === '*') {
|
|
@@ -1366,7 +1407,7 @@ function createAttributeAdder(node, createCalc, createEvent) {
|
|
|
1366
1407
|
node.text = parse$1(value, createCalc);
|
|
1367
1408
|
break;
|
|
1368
1409
|
case 'html':
|
|
1369
|
-
node.html = parse$1(value, createCalc);
|
|
1410
|
+
if (enableHTML) { node.html = parse$1(value, createCalc); }
|
|
1370
1411
|
break;
|
|
1371
1412
|
case 'template': node.template = value; break;
|
|
1372
1413
|
case 'bind': node.bind = value || true; break;
|
|
@@ -1710,15 +1751,17 @@ function entityReplacer(a) {
|
|
|
1710
1751
|
return a;
|
|
1711
1752
|
}
|
|
1712
1753
|
/**
|
|
1713
|
-
*
|
|
1714
|
-
* @param {string} source
|
|
1715
|
-
* @param {Layout.Options} [options]
|
|
1754
|
+
* 解析模板内容
|
|
1755
|
+
* @param {string} source 输入源字符串
|
|
1756
|
+
* @param {Layout.Options} [options] 解析选项
|
|
1716
1757
|
* @returns {(Layout.Node | string)[]}
|
|
1717
1758
|
*/
|
|
1718
1759
|
function parse(source, {
|
|
1719
1760
|
createCalc = () => { throw new ParseError('CALC'); },
|
|
1761
|
+
createInit = createCalc,
|
|
1720
1762
|
createEvent = () => { throw new ParseError('EVENT'); },
|
|
1721
1763
|
simpleTag = new Set,
|
|
1764
|
+
enableHTML = false,
|
|
1722
1765
|
} = {}) {
|
|
1723
1766
|
/** @type {(Layout.Node | string)[]} */
|
|
1724
1767
|
const children = [];
|
|
@@ -1769,7 +1812,20 @@ function parse(source, {
|
|
|
1769
1812
|
if (tagStart > index) {
|
|
1770
1813
|
appendText(tagStart);
|
|
1771
1814
|
}
|
|
1772
|
-
|
|
1815
|
+
const nextChar = source.charAt(tagStart + 1);
|
|
1816
|
+
if (nextChar === '!') {
|
|
1817
|
+
let begin = tagStart + 2;
|
|
1818
|
+
let sign = '>';
|
|
1819
|
+
if (source.slice(tagStart + 2, tagStart + 4) === '--') {
|
|
1820
|
+
begin += 4;
|
|
1821
|
+
sign = '-->';
|
|
1822
|
+
}
|
|
1823
|
+
index = source.indexOf(sign, begin);
|
|
1824
|
+
if (index < 0) { break; }
|
|
1825
|
+
index++;
|
|
1826
|
+
continue;
|
|
1827
|
+
}
|
|
1828
|
+
if (nextChar === '/') {
|
|
1773
1829
|
index = source.indexOf('>', tagStart + 3);
|
|
1774
1830
|
let name = source.substring(tagStart + 2, index);
|
|
1775
1831
|
if (index < 0) {
|
|
@@ -1837,7 +1893,7 @@ function parse(source, {
|
|
|
1837
1893
|
currentNode = createElement(tagRes.name, tagRes.is);
|
|
1838
1894
|
current.children.push(currentNode);
|
|
1839
1895
|
current = currentNode;
|
|
1840
|
-
const addAttribute = createAttributeAdder(currentNode, createCalc, createEvent);
|
|
1896
|
+
const addAttribute = createAttributeAdder(currentNode, createCalc, createInit, createEvent, enableHTML);
|
|
1841
1897
|
|
|
1842
1898
|
let run = true;
|
|
1843
1899
|
let closed = false;
|
|
@@ -2041,12 +2097,12 @@ function* listToString(nodes, level = 0) {
|
|
|
2041
2097
|
}
|
|
2042
2098
|
}
|
|
2043
2099
|
/**
|
|
2044
|
-
*
|
|
2045
|
-
* @param {Layout.Node | (Layout.Node |string)[]} value
|
|
2046
|
-
* @param {boolean} [formable]
|
|
2100
|
+
* 将模板转为字符串
|
|
2101
|
+
* @param {Layout.Node | (Layout.Node |string)[]} value 要转换的节点或节点数组
|
|
2102
|
+
* @param {boolean} [formable] 是否对代码进行格式化
|
|
2047
2103
|
* @returns {string}
|
|
2048
2104
|
*/
|
|
2049
|
-
function
|
|
2105
|
+
function stringify(value, formable) {
|
|
2050
2106
|
const level = formable ? 0 : -1;
|
|
2051
2107
|
if (Array.isArray(value)) { return [...listToString(value, level)].join(''); }
|
|
2052
2108
|
return [nodeToString(value, level)].join();
|
|
@@ -2054,95 +2110,90 @@ function toString(value, formable) {
|
|
|
2054
2110
|
}
|
|
2055
2111
|
|
|
2056
2112
|
/**
|
|
2057
|
-
* @typedef {object}
|
|
2058
|
-
*
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
/**
|
|
2064
|
-
* @typedef {object} Enhancement
|
|
2065
|
-
* @property {Record<string, Node.Name | Node.Event>} events
|
|
2066
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} attrs
|
|
2067
|
-
* @property {Node.Name | Node.Calc | Node.Value} [value]
|
|
2068
|
-
* @property {boolean | string} [bind]
|
|
2113
|
+
* @typedef {object} Enhancement 增强信息
|
|
2114
|
+
* @property {Record<string, Node.Name | Node.Event>} events 事件
|
|
2115
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} attrs 属性
|
|
2116
|
+
* @property {Node.Name | Node.Calc | Node.Value} [value] 主值
|
|
2117
|
+
* @property {boolean | string} [bind] 绑定信息
|
|
2069
2118
|
*/
|
|
2070
2119
|
|
|
2071
2120
|
/**
|
|
2072
|
-
* @typedef {object} Options
|
|
2073
|
-
* @property {
|
|
2074
|
-
* @property {(t: string) =>
|
|
2075
|
-
* @property {
|
|
2121
|
+
* @typedef {object} Options 解析选项
|
|
2122
|
+
* @property {boolean} [enableHTML] 启用 `!html` 指令
|
|
2123
|
+
* @property {(t: string) => Calc} [createCalc] 创建计算属性的工厂函数
|
|
2124
|
+
* @property {(t: string) => Calc} [createInit] 创建变量初始化的工厂函数
|
|
2125
|
+
* @property {(t: string) => EventListener} [createEvent] 创建事件监听器的工厂函数
|
|
2126
|
+
* @property {Set<string>} [simpleTag] 简单标签的集合
|
|
2076
2127
|
*/
|
|
2077
2128
|
/**
|
|
2078
2129
|
* @template [T=any]
|
|
2079
|
-
* @typedef {{value: T; name?: undefined; calc?: undefined; event?: undefined}} Node.Value
|
|
2130
|
+
* @typedef {{value: T; name?: undefined; calc?: undefined; event?: undefined}} Node.Value 基础值
|
|
2080
2131
|
*/
|
|
2081
2132
|
/**
|
|
2082
|
-
* @typedef {{name: string; value?: undefined; calc?: undefined; event?: undefined}} Node.Name
|
|
2133
|
+
* @typedef {{name: string; value?: undefined; calc?: undefined; event?: undefined}} Node.Name 名称
|
|
2083
2134
|
*/
|
|
2084
2135
|
/**
|
|
2085
|
-
* @typedef {{event: EventListener; name?: undefined; calc?: undefined; value?: undefined}} Node.Event
|
|
2136
|
+
* @typedef {{event: EventListener; name?: undefined; calc?: undefined; value?: undefined}} Node.Event 事件
|
|
2086
2137
|
*/
|
|
2087
2138
|
/**
|
|
2088
|
-
* @typedef {{calc: Calc; name?: undefined; value?: undefined; event?: undefined}} Node.Calc
|
|
2139
|
+
* @typedef {{calc: Calc; name?: undefined; value?: undefined; event?: undefined}} Node.Calc 计算
|
|
2089
2140
|
*/
|
|
2090
2141
|
/**
|
|
2091
|
-
* @typedef {object} Node
|
|
2092
|
-
* @property {string} name
|
|
2142
|
+
* @typedef {object} Node 布局节点
|
|
2143
|
+
* @property {string} name 标签名
|
|
2093
2144
|
* @property {string?} [is]
|
|
2094
2145
|
* @property {string} [id]
|
|
2095
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} attrs
|
|
2096
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} params
|
|
2097
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} classes
|
|
2098
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} styles
|
|
2099
|
-
* @property {Record<string, Node.Name | Node.Event>} events
|
|
2100
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} vars
|
|
2101
|
-
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} aliases
|
|
2102
|
-
* @property {Record<string, Enhancement>} enhancements
|
|
2146
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} attrs 属性
|
|
2147
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} params 模板参数定义
|
|
2148
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} classes 类名
|
|
2149
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} styles 样式
|
|
2150
|
+
* @property {Record<string, Node.Name | Node.Event>} events 事件
|
|
2151
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} vars 局部变量
|
|
2152
|
+
* @property {Record<string, Node.Name | Node.Calc | Node.Value>} aliases 别名/计算名
|
|
2153
|
+
* @property {Record<string, Enhancement>} enhancements 增强
|
|
2103
2154
|
*
|
|
2104
|
-
* @property {string} [template]
|
|
2105
|
-
* @property {boolean | string} [fragment]
|
|
2155
|
+
* @property {string} [template] 模板定义的名称
|
|
2156
|
+
* @property {boolean | string} [fragment] 是否为片段或模板调用
|
|
2106
2157
|
*
|
|
2107
|
-
* @property {Node.Name | Node.Calc | Node.Value} [if]
|
|
2108
|
-
* @property {boolean} [else]
|
|
2158
|
+
* @property {Node.Name | Node.Calc | Node.Value} [if] 分歧条件
|
|
2159
|
+
* @property {boolean} [else] 否定
|
|
2109
2160
|
*
|
|
2110
2161
|
* @property {string} [value] 值关联
|
|
2111
2162
|
* @property {Node.Name | Node.Calc | Node.Value} [enum] 列表属性枚举
|
|
2112
2163
|
*
|
|
2113
|
-
* @property {boolean | string} [bind]
|
|
2114
|
-
* @property {Node.Name | Node.Value | Node.Calc} [text]
|
|
2115
|
-
* @property {Node.Name | Node.Value | Node.Calc} [html]
|
|
2164
|
+
* @property {boolean | string} [bind] 绑定内容
|
|
2165
|
+
* @property {Node.Name | Node.Value | Node.Calc} [text] 文本渲染
|
|
2166
|
+
* @property {Node.Name | Node.Value | Node.Calc} [html] HTML 渲染
|
|
2116
2167
|
*
|
|
2117
2168
|
* @property {string} [comment] 注释
|
|
2118
2169
|
*
|
|
2119
|
-
* @property {(Node | string)[]} children
|
|
2170
|
+
* @property {(Node | string)[]} children 子元素
|
|
2120
2171
|
*/
|
|
2121
2172
|
|
|
2122
2173
|
/**
|
|
2123
|
-
* @callback Calc
|
|
2124
|
-
* @param {Record<string, any>} env
|
|
2174
|
+
* @callback Calc 计算函数
|
|
2175
|
+
* @param {Record<string, any>} env 上下文环境
|
|
2125
2176
|
* @returns {any}
|
|
2126
2177
|
*/
|
|
2127
2178
|
|
|
2128
2179
|
|
|
2129
2180
|
/**
|
|
2130
|
-
* @callback EventListener
|
|
2131
|
-
* @param {*} $event
|
|
2132
|
-
* @param {Record<string, any>} env
|
|
2181
|
+
* @callback EventListener 事件监听器
|
|
2182
|
+
* @param {*} $event 事件
|
|
2183
|
+
* @param {Record<string, any>} env 上下文环境
|
|
2133
2184
|
* @returns {void}
|
|
2134
2185
|
*/
|
|
2135
2186
|
|
|
2136
2187
|
var index$1 = /*#__PURE__*/Object.freeze({
|
|
2137
2188
|
__proto__: null,
|
|
2138
2189
|
parse: parse,
|
|
2139
|
-
stringify:
|
|
2190
|
+
stringify: stringify
|
|
2140
2191
|
});
|
|
2141
2192
|
|
|
2142
2193
|
/**
|
|
2143
|
-
*
|
|
2144
|
-
* @param {() => void} fn
|
|
2145
|
-
* @returns {() => void}
|
|
2194
|
+
* 相应式执行
|
|
2195
|
+
* @param {() => void} fn 执行函数
|
|
2196
|
+
* @returns {() => void} 取消函数
|
|
2146
2197
|
*/
|
|
2147
2198
|
function effect(fn) {
|
|
2148
2199
|
let needsEnqueue = true;
|
|
@@ -2170,7 +2221,7 @@ function effect(fn) {
|
|
|
2170
2221
|
* @template T
|
|
2171
2222
|
* @param {() => T} getter 取值方法
|
|
2172
2223
|
* @param {(value: T) => void} callback 取值方法
|
|
2173
|
-
* @param {boolean} immediate
|
|
2224
|
+
* @param {boolean} immediate 是否立即执行一次
|
|
2174
2225
|
* @returns {() => void}
|
|
2175
2226
|
*/
|
|
2176
2227
|
function watch(getter, callback, immediate) {
|
|
@@ -2917,11 +2968,12 @@ class Environment {
|
|
|
2917
2968
|
}
|
|
2918
2969
|
|
|
2919
2970
|
/** @import { Component } from '../types.mjs' */
|
|
2971
|
+
/** @import { ComponentHandler } from './types.mjs' */
|
|
2920
2972
|
/** @import * as Layout from '../Layout/index.mjs' */
|
|
2921
2973
|
|
|
2922
2974
|
|
|
2923
2975
|
/**
|
|
2924
|
-
* @param {
|
|
2976
|
+
* @param {ComponentHandler} handler
|
|
2925
2977
|
* @param {Environment} envs
|
|
2926
2978
|
* @param {Record<string, Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value>} attrs
|
|
2927
2979
|
* @param {Record<string, Component.Attr>} componentAttrs
|
|
@@ -2990,12 +3042,12 @@ function bindAttrs(handler, envs, attrs, componentAttrs, bindValue) {
|
|
|
2990
3042
|
}
|
|
2991
3043
|
}
|
|
2992
3044
|
|
|
2993
|
-
/** @import {
|
|
3045
|
+
/** @import { ComponentHandler } from './types.mjs' */
|
|
2994
3046
|
/** @import * as Layout from '../Layout/index.mjs' */
|
|
2995
3047
|
|
|
2996
3048
|
|
|
2997
3049
|
/**
|
|
2998
|
-
* @param {
|
|
3050
|
+
* @param {ComponentHandler} handler
|
|
2999
3051
|
* @param {Environment} envs
|
|
3000
3052
|
* @param {Record<string, Layout.Node.Name | Layout.Node.Calc | Layout.Node.Value>} attrs
|
|
3001
3053
|
*/
|
|
@@ -3146,7 +3198,12 @@ function bindStyles(node, envs, styles, styleAttr) {
|
|
|
3146
3198
|
return () => {};
|
|
3147
3199
|
}
|
|
3148
3200
|
if (styleAttr) {
|
|
3149
|
-
|
|
3201
|
+
const oldStyle = node.getAttribute('style') || '';
|
|
3202
|
+
const newStyle = envs.exec(styleAttr) || '';
|
|
3203
|
+
const style = [oldStyle,newStyle].filter(Boolean).join(';');
|
|
3204
|
+
if (style) {
|
|
3205
|
+
node.setAttribute('style', style);
|
|
3206
|
+
}
|
|
3150
3207
|
}
|
|
3151
3208
|
|
|
3152
3209
|
/** @type {Set<() => void>?} */
|
|
@@ -3385,6 +3442,7 @@ function bindFilters(env, fn, filterFns) {
|
|
|
3385
3442
|
}
|
|
3386
3443
|
|
|
3387
3444
|
/** @import { Component, Relatedness } from '../types.mjs' */
|
|
3445
|
+
/** @import { ComponentHandler } from './types.mjs' */
|
|
3388
3446
|
/** @import Store from '../Store/index.mjs' */
|
|
3389
3447
|
/** @import Environment from './Environment/index.mjs' */
|
|
3390
3448
|
|
|
@@ -3419,8 +3477,8 @@ function createContext(component, env, store, relate) {
|
|
|
3419
3477
|
const context = {
|
|
3420
3478
|
events: allEvents,
|
|
3421
3479
|
props: attrs ? new Set(Object.entries(attrs).filter(([, a]) => a.isProp).map(([e]) => e)) : null,
|
|
3422
|
-
tagAttrs,
|
|
3423
|
-
|
|
3480
|
+
attrs: tagAttrs,
|
|
3481
|
+
watch(name, fn) {
|
|
3424
3482
|
if (destroyed) { return () => { }; }
|
|
3425
3483
|
const state = attrStates[name];
|
|
3426
3484
|
if (!state) { return () => { }; }
|
|
@@ -3456,7 +3514,7 @@ function createContext(component, env, store, relate) {
|
|
|
3456
3514
|
get init() { return mountedState.get(); },
|
|
3457
3515
|
listen(name, listener) { return stateEmitter.listen(name, listener); },
|
|
3458
3516
|
};
|
|
3459
|
-
/** @type {
|
|
3517
|
+
/** @type {ComponentHandler} */
|
|
3460
3518
|
const handler = {
|
|
3461
3519
|
tag,
|
|
3462
3520
|
set(name, value) {
|
|
@@ -3671,7 +3729,7 @@ const tagBindMap = {
|
|
|
3671
3729
|
*/
|
|
3672
3730
|
function createTagComponent (context, name, is) {
|
|
3673
3731
|
const node = document.createElement(name, {is: is || undefined});
|
|
3674
|
-
const {
|
|
3732
|
+
const { watch, props } = context;
|
|
3675
3733
|
if(['input', 'textarea', 'select'].includes(name.toLowerCase())) {
|
|
3676
3734
|
context.relate(node);
|
|
3677
3735
|
}
|
|
@@ -3692,8 +3750,8 @@ function createTagComponent (context, name, is) {
|
|
|
3692
3750
|
node.addEventListener(type, listener, options);
|
|
3693
3751
|
}
|
|
3694
3752
|
if (props) {
|
|
3695
|
-
for (const [name, attr] of Object.entries(context.
|
|
3696
|
-
|
|
3753
|
+
for (const [name, attr] of Object.entries(context.attrs)) {
|
|
3754
|
+
watch(name, v => {
|
|
3697
3755
|
// @ts-ignore
|
|
3698
3756
|
if (props.has(name)) { node[name] = v; } else {
|
|
3699
3757
|
const val = toAttrValue(v);
|
|
@@ -3715,7 +3773,7 @@ function createTagComponent (context, name, is) {
|
|
|
3715
3773
|
return;
|
|
3716
3774
|
|
|
3717
3775
|
}
|
|
3718
|
-
for (const [name, attr] of Object.entries(context.
|
|
3776
|
+
for (const [name, attr] of Object.entries(context.attrs)) {
|
|
3719
3777
|
if (node instanceof HTMLInputElement && name.toLocaleLowerCase() === 'type') {
|
|
3720
3778
|
const value = toAttrValue(attr);
|
|
3721
3779
|
if (value !== null) {
|
|
@@ -3725,7 +3783,7 @@ function createTagComponent (context, name, is) {
|
|
|
3725
3783
|
}
|
|
3726
3784
|
if (name === '$hidden') {
|
|
3727
3785
|
if (attr) { node.hidden = attr; }
|
|
3728
|
-
|
|
3786
|
+
watch(name, (val) => { node.hidden = val; });
|
|
3729
3787
|
continue;
|
|
3730
3788
|
}
|
|
3731
3789
|
|
|
@@ -3733,7 +3791,7 @@ function createTagComponent (context, name, is) {
|
|
|
3733
3791
|
const e = eAttrs[name];
|
|
3734
3792
|
if (e) {
|
|
3735
3793
|
e(attr, node);
|
|
3736
|
-
|
|
3794
|
+
watch(name, (attr) => e(attr, node));
|
|
3737
3795
|
}
|
|
3738
3796
|
continue;
|
|
3739
3797
|
}
|
|
@@ -3741,7 +3799,7 @@ function createTagComponent (context, name, is) {
|
|
|
3741
3799
|
if (typeof prop === 'function') {
|
|
3742
3800
|
// @ts-ignore
|
|
3743
3801
|
node[name] = prop(attr);
|
|
3744
|
-
|
|
3802
|
+
watch(name, (attr) => {
|
|
3745
3803
|
// @ts-ignore
|
|
3746
3804
|
node[name] = prop(attr);
|
|
3747
3805
|
});
|
|
@@ -3750,7 +3808,7 @@ function createTagComponent (context, name, is) {
|
|
|
3750
3808
|
if (prop) {
|
|
3751
3809
|
// @ts-ignore
|
|
3752
3810
|
node[name] = attr;
|
|
3753
|
-
|
|
3811
|
+
watch(name, (attr) => {
|
|
3754
3812
|
// @ts-ignore
|
|
3755
3813
|
node[name] = attr;
|
|
3756
3814
|
});
|
|
@@ -3760,7 +3818,7 @@ function createTagComponent (context, name, is) {
|
|
|
3760
3818
|
if (value !== null) {
|
|
3761
3819
|
node.setAttribute(name, value);
|
|
3762
3820
|
}
|
|
3763
|
-
|
|
3821
|
+
watch(name, (val) => {
|
|
3764
3822
|
const value = toAttrValue(val);
|
|
3765
3823
|
if (value === null) {
|
|
3766
3824
|
node.removeAttribute(name);
|
|
@@ -4105,11 +4163,11 @@ function renderEnum(parent, next, getter, env, renderItem) {
|
|
|
4105
4163
|
};
|
|
4106
4164
|
}
|
|
4107
4165
|
|
|
4108
|
-
/** @import {
|
|
4166
|
+
/** @import { ComponentHandler } from './types.mjs' */
|
|
4109
4167
|
|
|
4110
4168
|
|
|
4111
4169
|
/**
|
|
4112
|
-
* @param {
|
|
4170
|
+
* @param {ComponentHandler} handler
|
|
4113
4171
|
* @param {Environment} env
|
|
4114
4172
|
* @param {string | boolean | null} [bind]
|
|
4115
4173
|
*/
|
|
@@ -4225,7 +4283,7 @@ function bindEnhancements(tag, enhancementDefine, env, enhancements, root, slot)
|
|
|
4225
4283
|
get value() { return null; },
|
|
4226
4284
|
events: allEvents,
|
|
4227
4285
|
attrs: attrs,
|
|
4228
|
-
|
|
4286
|
+
watch(name, fn) {
|
|
4229
4287
|
if (destroyed) { return () => { }; }
|
|
4230
4288
|
let old = attrs[name];
|
|
4231
4289
|
const w = watch(() => attrs[name], v => {
|
|
@@ -4382,14 +4440,14 @@ function render(layout, parent, next, env, templates, componentPath, enhancement
|
|
|
4382
4440
|
}
|
|
4383
4441
|
|
|
4384
4442
|
/**
|
|
4385
|
-
* @param {Store} store
|
|
4386
|
-
* @param {(Layout.Node | string)[]} layouts
|
|
4387
|
-
* @param {Element} parent
|
|
4388
|
-
* @param {object} [options]
|
|
4389
|
-
* @param {Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }>} [options.global]
|
|
4390
|
-
* @param {
|
|
4391
|
-
* @param {(store: Store, el: Element | Relatedness) => () => void} [options.relate]
|
|
4392
|
-
* @param {Record<string, Enhancement>} [options.enhancements]
|
|
4443
|
+
* @param {Store} store 存储实例
|
|
4444
|
+
* @param {(Layout.Node | string)[]} layouts 布局信息
|
|
4445
|
+
* @param {Element} parent 渲染节点
|
|
4446
|
+
* @param {object} [options] 选项
|
|
4447
|
+
* @param {Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }>} [options.global] 全局数据
|
|
4448
|
+
* @param {Component.Getter?} [options.component] 自定义组件
|
|
4449
|
+
* @param {(store: Store, el: Element | Relatedness) => () => void} [options.relate] 关联函数
|
|
4450
|
+
* @param {Record<string, Enhancement>} [options.enhancements] 增强信息
|
|
4393
4451
|
* @returns {() => void}
|
|
4394
4452
|
*/
|
|
4395
4453
|
function index (store, layouts, parent, {component, global, relate, enhancements} = {}) {
|