@neeloong/form 0.28.0 → 0.30.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.d.mts +116 -136
- package/index.full.js +298 -260
- package/index.full.min.js +2 -2
- package/index.full.min.mjs +2 -2
- package/index.min.mjs +2 -2
- package/index.mjs +297 -260
- package/package.json +1 -1
package/index.full.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @neeloong/form v0.
|
|
2
|
+
* @neeloong/form v0.30.0
|
|
3
3
|
* (c) 2024-2026 Fierflame
|
|
4
4
|
* @license Apache-2.0
|
|
5
5
|
*/
|
|
@@ -716,7 +716,7 @@
|
|
|
716
716
|
|
|
717
717
|
|
|
718
718
|
/** @type {{new(...p: ConstructorParameters<typeof Store>): Store}?} */
|
|
719
|
-
let ObjectStore$
|
|
719
|
+
let ObjectStore$1 = null;
|
|
720
720
|
/** @type {{new(...p: ConstructorParameters<typeof Store>): ArrayStore}?} */
|
|
721
721
|
let ArrayStoreClass = null;
|
|
722
722
|
/** @type {Record<string, {new(...p: ConstructorParameters<typeof Store>): Store}?>} */
|
|
@@ -741,14 +741,14 @@
|
|
|
741
741
|
const C = TypeStores[type];
|
|
742
742
|
if (C) { Class = C; }
|
|
743
743
|
} else if (type && typeof type === 'object') {
|
|
744
|
-
if (ObjectStore$
|
|
744
|
+
if (ObjectStore$1) { Class = ObjectStore$1; }
|
|
745
745
|
}
|
|
746
746
|
return new Class(schema, options);
|
|
747
747
|
}
|
|
748
748
|
|
|
749
749
|
/** @param {{new(...p: ConstructorParameters<typeof Store>): Store}} Class */
|
|
750
750
|
function setObjectStore(Class) {
|
|
751
|
-
ObjectStore$
|
|
751
|
+
ObjectStore$1 = Class;
|
|
752
752
|
}
|
|
753
753
|
|
|
754
754
|
/** @param {{new(...p: ConstructorParameters<typeof Store>): ArrayStore}} Class */
|
|
@@ -779,79 +779,127 @@
|
|
|
779
779
|
/**
|
|
780
780
|
*
|
|
781
781
|
* @param {Store} store
|
|
782
|
-
* @param
|
|
782
|
+
* @param {Schema.SyncValidator[]} syncValidators
|
|
783
783
|
* @returns
|
|
784
784
|
*/
|
|
785
|
-
function
|
|
786
|
-
const allValidators = validators.flat().filter(v => typeof v === 'function');
|
|
787
|
-
if (!allValidators.length) {
|
|
788
|
-
return new exports.Signal.Computed(() => /** @type {string[]} */([]));
|
|
789
|
-
}
|
|
785
|
+
function createSyncValidator(store, syncValidators) {
|
|
790
786
|
return new exports.Signal.Computed(() => {
|
|
791
787
|
const results = [];
|
|
792
|
-
for (const
|
|
788
|
+
for (const item of syncValidators) {
|
|
793
789
|
try {
|
|
794
|
-
results.push(
|
|
795
|
-
} catch (e){
|
|
790
|
+
results.push(item(store));
|
|
791
|
+
} catch (e) {
|
|
796
792
|
results.push(e);
|
|
797
793
|
}
|
|
798
794
|
}
|
|
799
795
|
return results.flat().map(toResult).filter(Boolean);
|
|
800
|
-
})
|
|
796
|
+
});
|
|
801
797
|
}
|
|
798
|
+
|
|
802
799
|
/**
|
|
803
800
|
*
|
|
804
801
|
* @param {Store} store
|
|
805
|
-
* @param
|
|
806
|
-
* @returns {[
|
|
802
|
+
* @param {Map<string, Schema.AsyncValidator[]>} eventsValidators
|
|
803
|
+
* @returns {[Record<string, () => Promise<string[]>>, results: Signal.State<string[]>[], stop: () => void]}
|
|
807
804
|
*/
|
|
808
|
-
function
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
805
|
+
function createEventsValidator(store, eventsValidators) {
|
|
806
|
+
/** @type {Record<string, () => Promise<string[]>>} */
|
|
807
|
+
const eventExecMap = {};
|
|
808
|
+
/** @type {(() => void)[]} */
|
|
809
|
+
const allCancels = [];
|
|
810
|
+
/** @type {Signal.State<string[]>[]} */
|
|
811
|
+
const results = [];
|
|
812
|
+
for (const [name, validators] of eventsValidators) {
|
|
813
|
+
const st = new exports.Signal.State(/** @type {string[]} */([]));
|
|
814
|
+
/**
|
|
815
|
+
*
|
|
816
|
+
* @param {Schema.AsyncValidator} validator
|
|
817
|
+
* @param {AbortSignal} signal
|
|
818
|
+
*/
|
|
819
|
+
async function run(validator, signal) {
|
|
820
|
+
let results = [];
|
|
821
|
+
try {
|
|
822
|
+
results.push(await validator(store, signal));
|
|
823
|
+
} catch (e) {
|
|
824
|
+
results.push(e);
|
|
825
|
+
}
|
|
826
|
+
const list = results.flat().map(toResult).filter(Boolean);
|
|
827
|
+
if (!signal.aborted && list.length) { st.set([...st.get(), ...list]); }
|
|
828
|
+
return list;
|
|
829
|
+
}
|
|
830
|
+
/** @type {AbortController?} */
|
|
831
|
+
let ac = null;
|
|
832
|
+
function exec() {
|
|
833
|
+
ac?.abort();
|
|
834
|
+
ac = new AbortController();
|
|
835
|
+
const signal = ac.signal;
|
|
836
|
+
st.set([]);
|
|
837
|
+
|
|
838
|
+
return Promise.all(validators.map(f => run(f, signal))).then(v => v.flat());
|
|
829
839
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
840
|
+
eventExecMap[name] = exec;
|
|
841
|
+
allCancels.push(() => { ac?.abort(); st.set([]); });
|
|
842
|
+
results.push(st);
|
|
833
843
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
}
|
|
844
|
-
return [exec, new exports.Signal.Computed(() => st.get()), () => {ac?.abort(); st.set([]);}]
|
|
844
|
+
|
|
845
|
+
function stop() {
|
|
846
|
+
for (const c of allCancels) {
|
|
847
|
+
c();
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
return [eventExecMap, results, stop];
|
|
845
853
|
}
|
|
846
854
|
|
|
847
855
|
/**
|
|
848
856
|
*
|
|
849
|
-
* @param
|
|
850
|
-
* @
|
|
857
|
+
* @param {Store} store
|
|
858
|
+
* @param {...Schema.Validator | undefined | null | (Schema.Validator | undefined | null)[]} validators
|
|
859
|
+
* @returns {[exec: () => Promise<string[]>, Record<string, () => Promise<string[]>>, state: Signal.Computed<string[]>, stop: () => void]}
|
|
851
860
|
*/
|
|
852
|
-
function
|
|
853
|
-
|
|
854
|
-
|
|
861
|
+
function createValidator(store, ...validators) {
|
|
862
|
+
|
|
863
|
+
/** @type {Schema.SyncValidator[]} */
|
|
864
|
+
const syncValidators = [];
|
|
865
|
+
/** @type {Map<string, Schema.AsyncValidator[]>} */
|
|
866
|
+
const eventsValidators = new Map();
|
|
867
|
+
for (const v of validators.flat()) {
|
|
868
|
+
if (!v) { continue; }
|
|
869
|
+
if (typeof v === 'function') {
|
|
870
|
+
syncValidators.push(v);
|
|
871
|
+
continue;
|
|
872
|
+
}
|
|
873
|
+
const { event, validator } = v;
|
|
874
|
+
if (typeof validator !== 'function') { continue; }
|
|
875
|
+
if (typeof event !== 'string') {
|
|
876
|
+
syncValidators.push(validator);
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
const list = eventsValidators.get(event);
|
|
880
|
+
if (list) {
|
|
881
|
+
list.push(validator);
|
|
882
|
+
} else {
|
|
883
|
+
eventsValidators.set(event, [validator]);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
const validatorResult = syncValidators.length
|
|
889
|
+
? createSyncValidator(store, syncValidators)
|
|
890
|
+
: new exports.Signal.Computed(() => /** @type {string[]} */([]));
|
|
891
|
+
if (!eventsValidators.size) {
|
|
892
|
+
return [() => Promise.resolve(validatorResult.get()), {}, validatorResult, () => {}];
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
const [eventExecMap, results, stop] = createEventsValidator(store, eventsValidators);
|
|
896
|
+
|
|
897
|
+
const errors = new exports.Signal.Computed(() => [validatorResult, ...results].flatMap(v => v.get()));
|
|
898
|
+
const execAll = () => Promise.all([
|
|
899
|
+
validatorResult.get(),
|
|
900
|
+
...Object.values(eventExecMap).map(exec => exec()),
|
|
901
|
+
]).then(v => v.flat());
|
|
902
|
+
return [execAll, eventExecMap, errors, stop];
|
|
855
903
|
}
|
|
856
904
|
|
|
857
905
|
/** @import Store from './Store.mjs' */
|
|
@@ -870,52 +918,6 @@
|
|
|
870
918
|
return (value) => structuredClone(def(store, value));
|
|
871
919
|
}
|
|
872
920
|
|
|
873
|
-
/** @import { Schema } from '../Schema.types.mjs' */
|
|
874
|
-
|
|
875
|
-
/**
|
|
876
|
-
* @template [T=any]
|
|
877
|
-
* @template [M=any]
|
|
878
|
-
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
879
|
-
* @extends {Store<T, M, S>}
|
|
880
|
-
*/
|
|
881
|
-
class BindObjectStore extends Store {
|
|
882
|
-
|
|
883
|
-
get kind() { return 'object'; }
|
|
884
|
-
/** @type {Record<string, Store>} */
|
|
885
|
-
#children = Object.create(null);
|
|
886
|
-
*[Symbol.iterator]() { yield* Object.entries(this.#children); }
|
|
887
|
-
/**
|
|
888
|
-
*
|
|
889
|
-
* @param {string | number} key
|
|
890
|
-
* @returns {Store?}
|
|
891
|
-
*/
|
|
892
|
-
child(key) { return this.#children[key] || null; }
|
|
893
|
-
/**
|
|
894
|
-
* @param {Schema<any, Object.<string, Schema.State>>} schema 数据结构模式
|
|
895
|
-
* @param {Store<T, M, S>} store
|
|
896
|
-
*/
|
|
897
|
-
constructor(schema, store) {
|
|
898
|
-
super(store);
|
|
899
|
-
const children = this.#children;
|
|
900
|
-
for (const [index, field] of Object.entries(schema)) {
|
|
901
|
-
const bindStore = create(field, {
|
|
902
|
-
index, parent: this,
|
|
903
|
-
/** @param {*} value @param {*} index @param {Store} store */
|
|
904
|
-
onUpdate: (value, index, store) => {
|
|
905
|
-
if (store !== children[index]) { return; }
|
|
906
|
-
const val = this.value ?? null;
|
|
907
|
-
if (typeof val !== 'object' || Array.isArray(val)) { return; }
|
|
908
|
-
// @ts-ignore
|
|
909
|
-
this.value = { ...val, [index]: value };
|
|
910
|
-
},
|
|
911
|
-
});
|
|
912
|
-
children[index] = bindStore;
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
// @ts-ignore
|
|
917
|
-
setObjectStore(ObjectStore);
|
|
918
|
-
|
|
919
921
|
/** @import { Ref } from './ref.mjs' */
|
|
920
922
|
/** @import { Schema } from '../Schema.types.mjs' */
|
|
921
923
|
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
@@ -956,10 +958,25 @@
|
|
|
956
958
|
/**
|
|
957
959
|
* 监听事件
|
|
958
960
|
* @template {keyof Schema.Events} K
|
|
961
|
+
* @overload
|
|
959
962
|
* @param {K} event
|
|
960
963
|
* @param {(this: this, p: Schema.Events[K], store: this) => void | boolean | null} listener
|
|
961
964
|
* @returns {() => void}
|
|
962
965
|
*/
|
|
966
|
+
/**
|
|
967
|
+
* 监听事件
|
|
968
|
+
* @template {keyof Schema.Events} K
|
|
969
|
+
* @overload
|
|
970
|
+
* @param {string} event
|
|
971
|
+
* @param {(this: this, p: unknown, store: this) => void | boolean | null} listener
|
|
972
|
+
* @returns {() => void}
|
|
973
|
+
*/
|
|
974
|
+
/**
|
|
975
|
+
* 监听事件
|
|
976
|
+
* @param {string} event
|
|
977
|
+
* @param {(this: this, p: unknown, store: this) => void | boolean | null} listener
|
|
978
|
+
* @returns {() => void}
|
|
979
|
+
*/
|
|
963
980
|
listen(event, listener) {
|
|
964
981
|
const originStore = this.#originStore;
|
|
965
982
|
if (originStore) { return originStore.listen(event, p => listener.call(this, p, this)); }
|
|
@@ -1004,116 +1021,87 @@
|
|
|
1004
1021
|
get ref() { return this.#ref || createRef(this); }
|
|
1005
1022
|
/**
|
|
1006
1023
|
* @param {Schema.Field<M, S> | Store<T,M,S>} schema 字段的 Schema 定义
|
|
1007
|
-
* @param {
|
|
1008
|
-
* @param {Store?} [options.parent]
|
|
1009
|
-
* @param {Partial<S>?} [options.states]
|
|
1010
|
-
* @param {((store: Store, value?: any) => any) | object | number | string | boolean | null | undefined} [options.default]
|
|
1011
|
-
* @param {number | string | null} [options.index]
|
|
1012
|
-
* @param {number | Signal.State<number> | Signal.Computed<number>} [options.size]
|
|
1013
|
-
* @param {boolean} [options.null]
|
|
1014
|
-
* @param {boolean} [options.new]
|
|
1015
|
-
* @param {boolean} [options.hidden]
|
|
1016
|
-
* @param {boolean} [options.clearable]
|
|
1017
|
-
* @param {boolean} [options.required]
|
|
1018
|
-
* @param {boolean} [options.disabled]
|
|
1019
|
-
* @param {boolean} [options.readonly]
|
|
1020
|
-
* @param {boolean} [options.removable]
|
|
1021
|
-
*
|
|
1022
|
-
* @param {string} [options.label] 字段标签
|
|
1023
|
-
* @param {string} [options.description] 字段描述
|
|
1024
|
-
* @param {string} [options.placeholder] 占位符
|
|
1025
|
-
* @param {number} [options.min] 日期、时间、数字的最小值
|
|
1026
|
-
* @param {number} [options.max] 日期、时间、数字的最大值
|
|
1027
|
-
* @param {number} [options.step] 日期、时间、数字的步长
|
|
1028
|
-
* @param {number} [options.minLength]
|
|
1029
|
-
* @param {number} [options.maxLength]
|
|
1030
|
-
* @param {RegExp} [options.pattern]
|
|
1031
|
-
* @param {(Schema.Value.Group | Schema.Value | string | number)[]} [options.values] 可选值
|
|
1032
|
-
* @param {Schema.Validator | Schema.Validator[] | null} [options.validator]
|
|
1033
|
-
* @param {{[k in keyof Schema.Events]?: Schema.AsyncValidator | Schema.AsyncValidator[] | null}} [options.validators]
|
|
1034
|
-
*
|
|
1035
|
-
* @param {Ref?} [options.ref]
|
|
1036
|
-
*
|
|
1037
|
-
* @param {((value: any) => any)?} [options.setValue]
|
|
1038
|
-
* @param {((value: any) => any)?} [options.convert]
|
|
1039
|
-
*
|
|
1040
|
-
* @param {((value: T?, index: any, store: Store) => void)?} [options.onUpdate]
|
|
1024
|
+
* @param {StoreOptions | AbortSignal | null} [options] 可选配置
|
|
1041
1025
|
*/
|
|
1042
|
-
constructor(schema, {
|
|
1043
|
-
null: isNull, ref, default: defaultValue,
|
|
1044
|
-
setValue, convert, onUpdate, states,
|
|
1045
|
-
validator, validators,
|
|
1046
|
-
index, size, new: isNew, parent: parentNode,
|
|
1047
|
-
hidden, clearable, required, disabled, readonly, removable,
|
|
1048
|
-
label, description, placeholder, min, max, step, minLength, maxLength, pattern, values: values$1
|
|
1049
|
-
} = {}) {
|
|
1026
|
+
constructor(schema, options) {
|
|
1050
1027
|
if (schema instanceof Store) {
|
|
1051
|
-
|
|
1052
|
-
this.#
|
|
1053
|
-
this.#
|
|
1054
|
-
this.#
|
|
1055
|
-
this.#
|
|
1056
|
-
this.#
|
|
1057
|
-
this.#
|
|
1058
|
-
this.#
|
|
1059
|
-
this.#
|
|
1060
|
-
this.#
|
|
1061
|
-
this.#
|
|
1062
|
-
this.#
|
|
1063
|
-
this.#
|
|
1064
|
-
this.#
|
|
1065
|
-
this.#
|
|
1066
|
-
this.#
|
|
1067
|
-
this.#
|
|
1068
|
-
this.#
|
|
1069
|
-
this.#
|
|
1070
|
-
this.#
|
|
1071
|
-
this.#
|
|
1072
|
-
this.#
|
|
1073
|
-
this.#
|
|
1074
|
-
this.#
|
|
1075
|
-
this.#
|
|
1076
|
-
this.#
|
|
1077
|
-
this.#
|
|
1078
|
-
this.#
|
|
1079
|
-
this.#
|
|
1080
|
-
this.#
|
|
1081
|
-
this.#
|
|
1082
|
-
this.#
|
|
1083
|
-
this.#
|
|
1084
|
-
this.#
|
|
1085
|
-
this.#
|
|
1086
|
-
this.#
|
|
1087
|
-
this.#
|
|
1088
|
-
this.#
|
|
1089
|
-
this.#
|
|
1090
|
-
this.#
|
|
1091
|
-
this.#
|
|
1092
|
-
this.#
|
|
1093
|
-
this.#
|
|
1094
|
-
this.#
|
|
1095
|
-
this.#
|
|
1096
|
-
this.#
|
|
1097
|
-
this.#
|
|
1098
|
-
this.#
|
|
1099
|
-
this.#
|
|
1100
|
-
this.#
|
|
1101
|
-
this.#
|
|
1102
|
-
this.#
|
|
1103
|
-
this.#
|
|
1104
|
-
this.#
|
|
1105
|
-
this.#
|
|
1106
|
-
this.#
|
|
1107
|
-
this.#
|
|
1108
|
-
this.#
|
|
1109
|
-
this.#
|
|
1110
|
-
this.#
|
|
1111
|
-
this.#
|
|
1112
|
-
this.#
|
|
1113
|
-
|
|
1114
|
-
|
|
1028
|
+
const store = schema.#originStore || schema;
|
|
1029
|
+
this.#originStore = store;
|
|
1030
|
+
this.#schema = store.#schema;
|
|
1031
|
+
this.#null = store.#null;
|
|
1032
|
+
this.#ref = store.#ref;
|
|
1033
|
+
this.#states = store.#states;
|
|
1034
|
+
this.#layout = store.#layout;
|
|
1035
|
+
this.#createDefault = store.#createDefault;
|
|
1036
|
+
this.#setValue = store.#setValue;
|
|
1037
|
+
this.#convert = store.#convert;
|
|
1038
|
+
this.#onUpdate = store.#onUpdate;
|
|
1039
|
+
this.#parent = store.#parent;
|
|
1040
|
+
this.#root = store.#root;
|
|
1041
|
+
this.#type = store.#type;
|
|
1042
|
+
this.#meta = store.#meta;
|
|
1043
|
+
this.#component = store.#component;
|
|
1044
|
+
this.#selfLoading = store.#selfLoading;
|
|
1045
|
+
this.#loading = store.#loading;
|
|
1046
|
+
this.#size = store.#size;
|
|
1047
|
+
this.#index = store.#index;
|
|
1048
|
+
this.#creatable = store.#creatable;
|
|
1049
|
+
this.#immutable = store.#immutable;
|
|
1050
|
+
this.#new = store.#new;
|
|
1051
|
+
this.#selfNew = store.#selfNew;
|
|
1052
|
+
this.#selfHidden = store.#selfHidden;
|
|
1053
|
+
this.#hidden = store.#hidden;
|
|
1054
|
+
this.#selfClearable = store.#selfClearable;
|
|
1055
|
+
this.#clearable = store.#clearable;
|
|
1056
|
+
this.#selfRequired = store.#selfRequired;
|
|
1057
|
+
this.#required = store.#required;
|
|
1058
|
+
this.#selfDisabled = store.#selfDisabled;
|
|
1059
|
+
this.#disabled = store.#disabled;
|
|
1060
|
+
this.#selfReadonly = store.#selfReadonly;
|
|
1061
|
+
this.#readonly = store.#readonly;
|
|
1062
|
+
this.#selfRemovable = store.#selfRemovable;
|
|
1063
|
+
this.#removable = store.#removable;
|
|
1064
|
+
this.#selfLabel = store.#selfLabel;
|
|
1065
|
+
this.#label = store.#label;
|
|
1066
|
+
this.#selfDescription = store.#selfDescription;
|
|
1067
|
+
this.#description = store.#description;
|
|
1068
|
+
this.#selfPlaceholder = store.#selfPlaceholder;
|
|
1069
|
+
this.#placeholder = store.#placeholder;
|
|
1070
|
+
this.#selfMin = store.#selfMin;
|
|
1071
|
+
this.#min = store.#min;
|
|
1072
|
+
this.#selfMax = store.#selfMax;
|
|
1073
|
+
this.#max = store.#max;
|
|
1074
|
+
this.#selfStep = store.#selfStep;
|
|
1075
|
+
this.#step = store.#step;
|
|
1076
|
+
this.#selfMinLength = store.#selfMinLength;
|
|
1077
|
+
this.#minLength = store.#minLength;
|
|
1078
|
+
this.#selfMaxLength = store.#selfMaxLength;
|
|
1079
|
+
this.#maxLength = store.#maxLength;
|
|
1080
|
+
this.#selfPattern = store.#selfPattern;
|
|
1081
|
+
this.#pattern = store.#pattern;
|
|
1082
|
+
this.#selfValues = store.#selfValues;
|
|
1083
|
+
this.#values = store.#values;
|
|
1084
|
+
this.#errors = store.#errors;
|
|
1085
|
+
this.#execValidators = store.#execValidators;
|
|
1086
|
+
this.#cancelEventValidator = store.#cancelEventValidator;
|
|
1087
|
+
this.#set = store.#set;
|
|
1088
|
+
this.#initValue = store.#initValue;
|
|
1089
|
+
this.#value = store.#value;
|
|
1090
|
+
const signal = options instanceof AbortSignal ? options : null;
|
|
1091
|
+
if (signal?.aborted) { return; }
|
|
1092
|
+
const subBindStores = store.#subBindStores;
|
|
1093
|
+
subBindStores.add(this);
|
|
1094
|
+
signal?.addEventListener('abort', () => subBindStores.delete(this));
|
|
1095
|
+
store.#requestUpdate();
|
|
1115
1096
|
return;
|
|
1116
1097
|
}
|
|
1098
|
+
const {
|
|
1099
|
+
null: isNull, ref, default: defaultValue,
|
|
1100
|
+
setValue, convert, onUpdate, states, validator,
|
|
1101
|
+
index, size, new: isNew, parent: parentNode,
|
|
1102
|
+
hidden, clearable, required, disabled, readonly, removable,
|
|
1103
|
+
label, description, placeholder, min, max, step, minLength, maxLength, pattern, values: values$1
|
|
1104
|
+
} = !(options instanceof AbortSignal) && options || {};
|
|
1117
1105
|
this.#schema = schema;
|
|
1118
1106
|
const parent = parentNode instanceof Store ? parentNode : null;
|
|
1119
1107
|
if (parent) {
|
|
@@ -1184,9 +1172,6 @@
|
|
|
1184
1172
|
|
|
1185
1173
|
[this.#selfRemovable, this.#removable] = createBooleanStates(this, removable, schema.removable ?? true);
|
|
1186
1174
|
|
|
1187
|
-
const validatorResult = createValidator(this, schema.validator, validator);
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
1175
|
const schemaStates = schema.states;
|
|
1191
1176
|
this.#states = schemaStates ? Object.defineProperties(Object.create(null),
|
|
1192
1177
|
Object.fromEntries(
|
|
@@ -1202,16 +1187,13 @@
|
|
|
1202
1187
|
})
|
|
1203
1188
|
)) : null;
|
|
1204
1189
|
|
|
1205
|
-
const [
|
|
1206
|
-
const [
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
this.#errors =
|
|
1210
|
-
this.#
|
|
1211
|
-
this.#
|
|
1212
|
-
this.#blurred = blurred;
|
|
1213
|
-
this.#cancelChange = cancelChange;
|
|
1214
|
-
this.#cancelBlur = cancelBlur;
|
|
1190
|
+
const [execValidators, eventExecMap, errors, cancelEventValidator] = createValidator(this, schema.validator, validator);
|
|
1191
|
+
for (const [name, exec] of Object.entries(eventExecMap)) {
|
|
1192
|
+
this.listen(name, () => { exec(); });
|
|
1193
|
+
}
|
|
1194
|
+
this.#errors = errors;
|
|
1195
|
+
this.#execValidators = execValidators;
|
|
1196
|
+
this.#cancelEventValidator = cancelEventValidator;
|
|
1215
1197
|
|
|
1216
1198
|
if (size instanceof exports.Signal.State || size instanceof exports.Signal.Computed) {
|
|
1217
1199
|
this.#size = size;
|
|
@@ -1496,16 +1478,10 @@
|
|
|
1496
1478
|
|
|
1497
1479
|
/** @type {Signal.Computed<string[]>} */
|
|
1498
1480
|
#errors;
|
|
1499
|
-
/** @type {Signal.Computed<string[]>} */
|
|
1500
|
-
#validatorResult;
|
|
1501
|
-
/** @type {() => Promise<string[]>} */
|
|
1502
|
-
#changed;
|
|
1503
1481
|
/** @type {() => Promise<string[]>} */
|
|
1504
|
-
#
|
|
1482
|
+
#execValidators;
|
|
1505
1483
|
/** @type {() => void} */
|
|
1506
|
-
#
|
|
1507
|
-
/** @type {() => void} */
|
|
1508
|
-
#cancelBlur;
|
|
1484
|
+
#cancelEventValidator;
|
|
1509
1485
|
/** 所有校验错误列表 */
|
|
1510
1486
|
get errors() { return this.#errors.get(); }
|
|
1511
1487
|
/** 字段校验错误信息 */
|
|
@@ -1526,24 +1502,6 @@
|
|
|
1526
1502
|
|
|
1527
1503
|
/** @type {Set<Store>} */
|
|
1528
1504
|
#subBindStores = new Set();
|
|
1529
|
-
/**
|
|
1530
|
-
* @template [M=any]
|
|
1531
|
-
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
1532
|
-
* @param {Schema<M, S>} schema 数据结构模式
|
|
1533
|
-
* @param {AbortSignal} [signal]
|
|
1534
|
-
* @returns {BindObjectStore}
|
|
1535
|
-
*/
|
|
1536
|
-
bindObject(schema, signal) {
|
|
1537
|
-
const originStore = this.#originStore;
|
|
1538
|
-
if (originStore) { return originStore.bindObject(schema, signal); }
|
|
1539
|
-
const store = new BindObjectStore(schema, this);
|
|
1540
|
-
if (signal?.aborted) { return store; }
|
|
1541
|
-
const subBindStores = this.#subBindStores;
|
|
1542
|
-
subBindStores.add(store);
|
|
1543
|
-
signal?.addEventListener('abort', () => subBindStores.delete(store));
|
|
1544
|
-
this.#requestUpdate();
|
|
1545
|
-
return store;
|
|
1546
|
-
}
|
|
1547
1505
|
|
|
1548
1506
|
/** 内容是否已改变 */
|
|
1549
1507
|
get changed() { return !Object.is(this.#value.get(), this.#initValue.get()); }
|
|
@@ -1587,8 +1545,7 @@
|
|
|
1587
1545
|
this.#selfNew.set(isNew);
|
|
1588
1546
|
const newValue = this.#setValue?.(v);
|
|
1589
1547
|
const value = newValue === undefined ? v : newValue;
|
|
1590
|
-
this.#
|
|
1591
|
-
this.#cancelBlur();
|
|
1548
|
+
this.#cancelEventValidator();
|
|
1592
1549
|
this.#set = true;
|
|
1593
1550
|
if (!value || typeof value !== 'object') {
|
|
1594
1551
|
for (const bind of [this, ...this.#subBindStores]) {
|
|
@@ -1640,7 +1597,7 @@
|
|
|
1640
1597
|
// @ts-ignore
|
|
1641
1598
|
let newValues = Array.isArray(val) ? [...val] : { ...val };
|
|
1642
1599
|
let updated = false;
|
|
1643
|
-
for (const bind of [this
|
|
1600
|
+
for (const bind of [this, ...this.#subBindStores]) {
|
|
1644
1601
|
for (const [key, field] of bind) {
|
|
1645
1602
|
// @ts-ignore
|
|
1646
1603
|
const data = Object.hasOwn(val, key) ? val[key] : undefined;
|
|
@@ -1684,11 +1641,7 @@
|
|
|
1684
1641
|
validate(path) {
|
|
1685
1642
|
if (path === true) {
|
|
1686
1643
|
if (this.#originStore) { return Promise.resolve(null); }
|
|
1687
|
-
return
|
|
1688
|
-
.then(v => {
|
|
1689
|
-
const errors = v.flat();
|
|
1690
|
-
return errors.length ? errors : null;
|
|
1691
|
-
});
|
|
1644
|
+
return this.#execValidators().then(errors => errors.length ? errors : null);
|
|
1692
1645
|
}
|
|
1693
1646
|
const selfPath = Array.isArray(path) ? path : [];
|
|
1694
1647
|
if (!this.#originStore && this.#hidden.get()) { return Promise.resolve([]); }
|
|
@@ -1706,6 +1659,45 @@
|
|
|
1706
1659
|
}
|
|
1707
1660
|
}
|
|
1708
1661
|
|
|
1662
|
+
/**
|
|
1663
|
+
* @template [T=any]
|
|
1664
|
+
* @template [M=any]
|
|
1665
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
1666
|
+
* @typedef {object} StoreOptions
|
|
1667
|
+
* @property {Store?} [parent]
|
|
1668
|
+
* @property {Partial<S>?} [states]
|
|
1669
|
+
* @property {((store: Store, value?: any) => any) | object | number | string | boolean | null | undefined} [default]
|
|
1670
|
+
* @property {number | string | null} [index]
|
|
1671
|
+
* @property {number | Signal.State<number> | Signal.Computed<number>} [size]
|
|
1672
|
+
* @property {boolean} [null]
|
|
1673
|
+
* @property {boolean} [new]
|
|
1674
|
+
* @property {boolean} [hidden]
|
|
1675
|
+
* @property {boolean} [clearable]
|
|
1676
|
+
* @property {boolean} [required]
|
|
1677
|
+
* @property {boolean} [disabled]
|
|
1678
|
+
* @property {boolean} [readonly]
|
|
1679
|
+
* @property {boolean} [removable]
|
|
1680
|
+
*
|
|
1681
|
+
* @property {string} [label] 字段标签
|
|
1682
|
+
* @property {string} [description] 字段描述
|
|
1683
|
+
* @property {string} [placeholder] 占位符
|
|
1684
|
+
* @property {number} [min] 日期、时间、数字的最小值
|
|
1685
|
+
* @property {number} [max] 日期、时间、数字的最大值
|
|
1686
|
+
* @property {number} [step] 日期、时间、数字的步长
|
|
1687
|
+
* @property {number} [minLength]
|
|
1688
|
+
* @property {number} [maxLength]
|
|
1689
|
+
* @property {RegExp} [pattern]
|
|
1690
|
+
* @property {(Schema.Value.Group | Schema.Value | string | number)[]} [values] 可选值
|
|
1691
|
+
* @property {Schema.Validator | Schema.Validator[] | null} [validator]
|
|
1692
|
+
*
|
|
1693
|
+
* @property {Ref?} [ref]
|
|
1694
|
+
*
|
|
1695
|
+
* @property {((value: any) => any)?} [setValue]
|
|
1696
|
+
* @property {((value: any) => any)?} [convert]
|
|
1697
|
+
*
|
|
1698
|
+
* @property {((value: T?, index: any, store: Store) => void)?} [onUpdate]
|
|
1699
|
+
*/
|
|
1700
|
+
|
|
1709
1701
|
/** @import { Schema } from '../Schema.types.mjs' */
|
|
1710
1702
|
|
|
1711
1703
|
/**
|
|
@@ -1714,7 +1706,7 @@
|
|
|
1714
1706
|
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
1715
1707
|
* @extends {Store<T, M, S>}
|
|
1716
1708
|
*/
|
|
1717
|
-
|
|
1709
|
+
class ObjectStore extends Store {
|
|
1718
1710
|
get kind() { return 'object'; }
|
|
1719
1711
|
/** @type {Record<string, Store>} */
|
|
1720
1712
|
#children;
|
|
@@ -1767,9 +1759,9 @@
|
|
|
1767
1759
|
}
|
|
1768
1760
|
this.#children = children;
|
|
1769
1761
|
}
|
|
1770
|
-
}
|
|
1762
|
+
}
|
|
1771
1763
|
// @ts-ignore
|
|
1772
|
-
setObjectStore(ObjectStore
|
|
1764
|
+
setObjectStore(ObjectStore);
|
|
1773
1765
|
|
|
1774
1766
|
/** @import { Schema } from '../Schema.types.mjs' */
|
|
1775
1767
|
|
|
@@ -2011,6 +2003,51 @@
|
|
|
2011
2003
|
// @ts-ignore
|
|
2012
2004
|
setArrayStore(ArrayStore);
|
|
2013
2005
|
|
|
2006
|
+
/** @import { Schema } from '../Schema.types.mjs' */
|
|
2007
|
+
|
|
2008
|
+
/**
|
|
2009
|
+
* @template [T=any]
|
|
2010
|
+
* @template [M=any]
|
|
2011
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
2012
|
+
* @extends {Store<T, M, S>}
|
|
2013
|
+
*/
|
|
2014
|
+
class BindObjectStore extends Store {
|
|
2015
|
+
|
|
2016
|
+
get kind() { return 'object'; }
|
|
2017
|
+
/** @type {Record<string, Store>} */
|
|
2018
|
+
#children = Object.create(null);
|
|
2019
|
+
*[Symbol.iterator]() { yield* Object.entries(this.#children); }
|
|
2020
|
+
/**
|
|
2021
|
+
*
|
|
2022
|
+
* @param {string | number} key
|
|
2023
|
+
* @returns {Store?}
|
|
2024
|
+
*/
|
|
2025
|
+
child(key) { return this.#children[key] || null; }
|
|
2026
|
+
/**
|
|
2027
|
+
* @param {Schema<any, Object.<string, Schema.State>>} schema 数据结构模式
|
|
2028
|
+
* @param {Store<T, M, S>} store
|
|
2029
|
+
* @param {AbortSignal} [signal]
|
|
2030
|
+
*/
|
|
2031
|
+
constructor(schema, store, signal) {
|
|
2032
|
+
super(store, signal);
|
|
2033
|
+
const children = this.#children;
|
|
2034
|
+
for (const [index, field] of Object.entries(schema)) {
|
|
2035
|
+
const bindStore = create(field, {
|
|
2036
|
+
index, parent: this,
|
|
2037
|
+
/** @param {*} value @param {*} index @param {Store} store */
|
|
2038
|
+
onUpdate: (value, index, store) => {
|
|
2039
|
+
if (store !== children[index]) { return; }
|
|
2040
|
+
const val = this.value ?? null;
|
|
2041
|
+
if (typeof val !== 'object' || Array.isArray(val)) { return; }
|
|
2042
|
+
// @ts-ignore
|
|
2043
|
+
this.value = { ...val, [index]: value };
|
|
2044
|
+
},
|
|
2045
|
+
});
|
|
2046
|
+
children[index] = bindStore;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2014
2051
|
/** @import * as Layout from './index.mjs' */
|
|
2015
2052
|
|
|
2016
2053
|
/** @import { OldNode } from './createElement.mjs' */
|
|
@@ -5439,7 +5476,7 @@
|
|
|
5439
5476
|
if (list instanceof ArrayStore) {
|
|
5440
5477
|
return renderArray(parent, next, list, env, r, layout.sort);
|
|
5441
5478
|
}
|
|
5442
|
-
if (list instanceof ObjectStore
|
|
5479
|
+
if (list instanceof ObjectStore) {
|
|
5443
5480
|
return renderObject(parent, next, list, env, r, layout.sort);
|
|
5444
5481
|
}
|
|
5445
5482
|
if (typeof list === 'function') {
|
|
@@ -7172,8 +7209,9 @@
|
|
|
7172
7209
|
}
|
|
7173
7210
|
|
|
7174
7211
|
exports.ArrayStore = ArrayStore;
|
|
7212
|
+
exports.BindObjectStore = BindObjectStore;
|
|
7175
7213
|
exports.Layout = index;
|
|
7176
|
-
exports.ObjectStore = ObjectStore
|
|
7214
|
+
exports.ObjectStore = ObjectStore;
|
|
7177
7215
|
exports.Store = Store;
|
|
7178
7216
|
exports.effect = effect;
|
|
7179
7217
|
exports.render = render;
|