@neeloong/form 0.24.0 → 0.26.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 +132 -46
- package/index.full.js +231 -141
- package/index.full.min.js +4 -4
- package/index.full.min.mjs +7 -7
- package/index.min.mjs +2 -2
- package/index.mjs +231 -141
- package/package.json +1 -1
package/index.full.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @neeloong/form v0.
|
|
2
|
+
* @neeloong/form v0.26.0
|
|
3
3
|
* (c) 2024-2026 Fierflame
|
|
4
4
|
* @license Apache-2.0
|
|
5
5
|
*/
|
|
@@ -723,7 +723,8 @@
|
|
|
723
723
|
let TypeStores = Object.create(null);
|
|
724
724
|
/**
|
|
725
725
|
* @template [M=any]
|
|
726
|
-
* @
|
|
726
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
727
|
+
* @param {Schema.Field<M, S>} schema
|
|
727
728
|
* @param {object} [options]
|
|
728
729
|
* @param {Store?} [options.parent]
|
|
729
730
|
* @param {string | number | null} [options.index]
|
|
@@ -877,6 +878,7 @@
|
|
|
877
878
|
* 管理单个表单字段的状态和行为
|
|
878
879
|
* @template [T=any]
|
|
879
880
|
* @template [M=any]
|
|
881
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
880
882
|
*/
|
|
881
883
|
class Store {
|
|
882
884
|
/** @type {Map<string, Set<(value: any, store: any) => void | boolean | null>>} */
|
|
@@ -919,7 +921,8 @@
|
|
|
919
921
|
/**
|
|
920
922
|
* 从数据结构模式创建存储
|
|
921
923
|
* @template [M=any]
|
|
922
|
-
* @
|
|
924
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
925
|
+
* @param {Schema<M, S>} schema 数据结构模式
|
|
923
926
|
* @param {object} [options] 选项
|
|
924
927
|
* @param {boolean} [options.new] 是否为新建环境
|
|
925
928
|
*/
|
|
@@ -943,9 +946,10 @@
|
|
|
943
946
|
#ref = null;
|
|
944
947
|
get ref() { return this.#ref || createRef(this); }
|
|
945
948
|
/**
|
|
946
|
-
* @param {Schema.Field<M>} schema 字段的 Schema 定义
|
|
949
|
+
* @param {Schema.Field<M, S>} schema 字段的 Schema 定义
|
|
947
950
|
* @param {object} [options] 可选配置
|
|
948
951
|
* @param {Store?} [options.parent]
|
|
952
|
+
* @param {Partial<S>?} [options.states]
|
|
949
953
|
* @param {((store: Store, value?: any) => any) | object | number | string | boolean | null | undefined} [options.default]
|
|
950
954
|
* @param {number | string | null} [options.index]
|
|
951
955
|
* @param {number | Signal.State<number> | Signal.Computed<number>} [options.size]
|
|
@@ -980,7 +984,7 @@
|
|
|
980
984
|
*/
|
|
981
985
|
constructor(schema, {
|
|
982
986
|
null: isNull, ref, default: defaultValue,
|
|
983
|
-
setValue, convert, onUpdate,
|
|
987
|
+
setValue, convert, onUpdate, states,
|
|
984
988
|
validator, validators,
|
|
985
989
|
index, size, new: isNew, parent: parentNode,
|
|
986
990
|
hidden, clearable, required, disabled, readonly, removable,
|
|
@@ -1058,6 +1062,22 @@
|
|
|
1058
1062
|
|
|
1059
1063
|
const validatorResult = createValidator(this, schema.validator, validator);
|
|
1060
1064
|
|
|
1065
|
+
|
|
1066
|
+
const schemaStates = schema.states;
|
|
1067
|
+
this.#states = schemaStates ? Object.defineProperties(Object.create(null),
|
|
1068
|
+
Object.fromEntries(
|
|
1069
|
+
Object.entries(schemaStates).map(([k, { get, set, toState }]) => {
|
|
1070
|
+
const state = new exports.Signal.State(toState?.(states?.[k]));
|
|
1071
|
+
const computed = new exports.Signal.Computed(() => get(this, state));
|
|
1072
|
+
return [k, {
|
|
1073
|
+
configurable: true,
|
|
1074
|
+
enumerable: true,
|
|
1075
|
+
get() { return computed.get(); },
|
|
1076
|
+
set(v) { return set?.(this, state, v); },
|
|
1077
|
+
}];
|
|
1078
|
+
})
|
|
1079
|
+
)) : null;
|
|
1080
|
+
|
|
1061
1081
|
const [changed, changedResult, cancelChange] = createAsyncValidator(this, schema.validators?.change, validators?.change);
|
|
1062
1082
|
const [blurred, blurredResult, cancelBlur] = createAsyncValidator(this, schema.validators?.blur, validators?.blur);
|
|
1063
1083
|
this.listen('change', () => { changed(); });
|
|
@@ -1092,8 +1112,11 @@
|
|
|
1092
1112
|
this.listen(k, f);
|
|
1093
1113
|
}
|
|
1094
1114
|
}
|
|
1115
|
+
/** @type {S?} */
|
|
1116
|
+
#states;
|
|
1117
|
+
get states() { return this.#states; }
|
|
1095
1118
|
/** @type {StoreLayout.Field<any>} */
|
|
1096
|
-
#layout
|
|
1119
|
+
#layout;
|
|
1097
1120
|
get layout() { return this.#layout; }
|
|
1098
1121
|
#createDefault;
|
|
1099
1122
|
/** @param {any} [value] @returns {any} */
|
|
@@ -1269,9 +1292,10 @@
|
|
|
1269
1292
|
#selfMin;
|
|
1270
1293
|
/** @readonly @type {Signal.Computed<number?>} */
|
|
1271
1294
|
#min;
|
|
1295
|
+
/** @deprecated */
|
|
1272
1296
|
get selfMin() { return this.#selfMin.get(); }
|
|
1273
1297
|
set selfMin(v) { this.#selfMin.set(number(v)); }
|
|
1274
|
-
/** 数值字段的最小值限制 */
|
|
1298
|
+
/** @deprecated 数值字段的最小值限制 */
|
|
1275
1299
|
get min() { return this.#min.get(); }
|
|
1276
1300
|
set min(v) { this.#selfMin.set(number(v)); }
|
|
1277
1301
|
|
|
@@ -1280,9 +1304,10 @@
|
|
|
1280
1304
|
#selfMax;
|
|
1281
1305
|
/** @readonly @type {Signal.Computed<number?>} */
|
|
1282
1306
|
#max;
|
|
1307
|
+
/** @deprecated */
|
|
1283
1308
|
get selfMax() { return this.#selfMax.get(); }
|
|
1284
1309
|
set selfMax(v) { this.#selfMax.set(number(v)); }
|
|
1285
|
-
/** 数值字段的最大值限制 */
|
|
1310
|
+
/** @deprecated 数值字段的最大值限制 */
|
|
1286
1311
|
get max() { return this.#max.get(); }
|
|
1287
1312
|
set max(v) { this.#selfMax.set(number(v)); }
|
|
1288
1313
|
|
|
@@ -1291,9 +1316,10 @@
|
|
|
1291
1316
|
#selfStep;
|
|
1292
1317
|
/** @readonly @type {Signal.Computed<number?>} */
|
|
1293
1318
|
#step;
|
|
1319
|
+
/** @deprecated */
|
|
1294
1320
|
get selfStep() { return this.#selfStep.get(); }
|
|
1295
1321
|
set selfStep(v) { this.#selfStep.set(number(v)); }
|
|
1296
|
-
/** 数值字段的步长 */
|
|
1322
|
+
/** @deprecated 数值字段的步长 */
|
|
1297
1323
|
get step() { return this.#step.get(); }
|
|
1298
1324
|
set step(v) { this.#selfStep.set(number(v)); }
|
|
1299
1325
|
|
|
@@ -1301,9 +1327,10 @@
|
|
|
1301
1327
|
#selfMinLength;
|
|
1302
1328
|
/** @readonly @type {Signal.Computed<number?>} */
|
|
1303
1329
|
#minLength;
|
|
1330
|
+
/** @deprecated */
|
|
1304
1331
|
get selfMinLength() { return this.#selfMinLength.get(); }
|
|
1305
1332
|
set selfMinLength(v) { this.#selfMinLength.set(number(v)); }
|
|
1306
|
-
/** 最小长度 */
|
|
1333
|
+
/** @deprecated 最小长度 */
|
|
1307
1334
|
get minLength() { return this.#minLength.get(); }
|
|
1308
1335
|
set minLength(v) { this.#selfMinLength.set(number(v)); }
|
|
1309
1336
|
|
|
@@ -1311,9 +1338,10 @@
|
|
|
1311
1338
|
#selfMaxLength;
|
|
1312
1339
|
/** @readonly @type {Signal.Computed<number?>} */
|
|
1313
1340
|
#maxLength;
|
|
1341
|
+
/** @deprecated */
|
|
1314
1342
|
get selfMaxLength() { return this.#selfMaxLength.get(); }
|
|
1315
1343
|
set selfMaxLength(v) { this.#selfMaxLength.set(number(v)); }
|
|
1316
|
-
/** 最大长度 */
|
|
1344
|
+
/** @deprecated 最大长度 */
|
|
1317
1345
|
get maxLength() { return this.#maxLength.get(); }
|
|
1318
1346
|
set maxLength(v) { this.#selfMaxLength.set(number(v)); }
|
|
1319
1347
|
|
|
@@ -1321,9 +1349,10 @@
|
|
|
1321
1349
|
#selfPattern;
|
|
1322
1350
|
/** @readonly @type {Signal.Computed<RegExp?>} */
|
|
1323
1351
|
#pattern;
|
|
1352
|
+
/** @deprecated */
|
|
1324
1353
|
get selfPattern() { return this.#selfPattern.get(); }
|
|
1325
1354
|
set selfPattern(v) { this.#selfPattern.set(regex(v)); }
|
|
1326
|
-
/** 模式 */
|
|
1355
|
+
/** @deprecated 模式 */
|
|
1327
1356
|
get pattern() { return this.#pattern.get(); }
|
|
1328
1357
|
set pattern(v) { this.#selfPattern.set(regex(v)); }
|
|
1329
1358
|
|
|
@@ -1332,9 +1361,10 @@
|
|
|
1332
1361
|
#selfValues;
|
|
1333
1362
|
/** @readonly @type {Signal.Computed<(Schema.Value.Group | Schema.Value)[] | null>} */
|
|
1334
1363
|
#values;
|
|
1364
|
+
/** @deprecated */
|
|
1335
1365
|
get selfValues() { return this.#selfValues.get(); }
|
|
1336
1366
|
set selfValues(v) { this.#selfValues.set(values(v)); }
|
|
1337
|
-
/** 可选值列表 */
|
|
1367
|
+
/** @deprecated 可选值列表 */
|
|
1338
1368
|
get values() { return this.#values.get(); }
|
|
1339
1369
|
set values(v) { this.#selfValues.set(values(v)); }
|
|
1340
1370
|
|
|
@@ -1369,6 +1399,40 @@
|
|
|
1369
1399
|
#initValue = new exports.Signal.State(/** @type {T?} */(null));
|
|
1370
1400
|
#value = new exports.Signal.State(this.#initValue.get());
|
|
1371
1401
|
|
|
1402
|
+
/**
|
|
1403
|
+
* @template [M=any]
|
|
1404
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
1405
|
+
* @param {Schema<M, S>} schema 数据结构模式
|
|
1406
|
+
*/
|
|
1407
|
+
bindObject(schema) {
|
|
1408
|
+
const bindStores = this.#bindStores;
|
|
1409
|
+
/** @type {Store[]} */
|
|
1410
|
+
const list = [];
|
|
1411
|
+
for (const [index, field] of Object.entries(schema)) {
|
|
1412
|
+
const bindStore = create(field, {
|
|
1413
|
+
index, parent: this,
|
|
1414
|
+
/** @param {*} value @param {*} currentIndex @param {Store} store */
|
|
1415
|
+
onUpdate: (value, currentIndex, store) => {
|
|
1416
|
+
if (index !== currentIndex) { return; }
|
|
1417
|
+
if (bindStores.has(store)) { return; }
|
|
1418
|
+
const val = this.#value ?? null;
|
|
1419
|
+
if (typeof val !== 'object' || Array.isArray(val)) { return }
|
|
1420
|
+
// @ts-ignore
|
|
1421
|
+
this.value = { ...val, [currentIndex]: value };
|
|
1422
|
+
},
|
|
1423
|
+
});
|
|
1424
|
+
list.push(bindStore);
|
|
1425
|
+
bindStores.set(bindStore, index);
|
|
1426
|
+
}
|
|
1427
|
+
this.#requestUpdate();
|
|
1428
|
+
return () => {
|
|
1429
|
+
for (const bindStore of list) {
|
|
1430
|
+
bindStores.delete(bindStore);
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
/** @type {Map<Store, string>} */
|
|
1435
|
+
#bindStores = new Map();
|
|
1372
1436
|
|
|
1373
1437
|
/** 内容是否已改变 */
|
|
1374
1438
|
get changed() { return !Object.is(this.#value.get(), this.#initValue.get()); }
|
|
@@ -1415,6 +1479,9 @@
|
|
|
1415
1479
|
for (const [, field] of this) {
|
|
1416
1480
|
field.#reset(null, false);
|
|
1417
1481
|
}
|
|
1482
|
+
for (const [field] of this.#bindStores) {
|
|
1483
|
+
field.#reset(null, false);
|
|
1484
|
+
}
|
|
1418
1485
|
this.#value.set(value);
|
|
1419
1486
|
this.#initValue.set(value);
|
|
1420
1487
|
this.#onUpdate?.(value, this.#index.get(), this);
|
|
@@ -1425,6 +1492,9 @@
|
|
|
1425
1492
|
for (const [key, field] of this) {
|
|
1426
1493
|
newValues[key] = field.#reset(Object.hasOwn(newValues, key) ? newValues[key] : undefined, false);
|
|
1427
1494
|
}
|
|
1495
|
+
for (const [field, key] of this.#bindStores) {
|
|
1496
|
+
newValues[key] = field.#reset(Object.hasOwn(newValues, key) ? newValues[key] : undefined, false);
|
|
1497
|
+
}
|
|
1428
1498
|
this.#value.set(newValues);
|
|
1429
1499
|
this.#initValue.set(newValues);
|
|
1430
1500
|
this.#onUpdate?.(newValues, this.#index.get(), this);
|
|
@@ -1466,6 +1536,15 @@
|
|
|
1466
1536
|
newValues[key] = newData;
|
|
1467
1537
|
updated = true;
|
|
1468
1538
|
}
|
|
1539
|
+
for (const [field, key] of this.#bindStores) {
|
|
1540
|
+
// @ts-ignore
|
|
1541
|
+
const data = Object.hasOwn(val, key) ? val[key] : undefined;
|
|
1542
|
+
const newData = field.#toUpdate(data);
|
|
1543
|
+
if (Object.is(data, newData)) { continue; }
|
|
1544
|
+
// @ts-ignore
|
|
1545
|
+
newValues[key] = newData;
|
|
1546
|
+
updated = true;
|
|
1547
|
+
}
|
|
1469
1548
|
if (updated) {
|
|
1470
1549
|
val = newValues;
|
|
1471
1550
|
initValue = val;
|
|
@@ -1482,7 +1561,7 @@
|
|
|
1482
1561
|
/**
|
|
1483
1562
|
* 异步校验
|
|
1484
1563
|
* @overload
|
|
1485
|
-
* @param {true} [
|
|
1564
|
+
* @param {true} [self]
|
|
1486
1565
|
* @returns {Promise<string[] | null>}
|
|
1487
1566
|
*/
|
|
1488
1567
|
/**
|
|
@@ -1505,6 +1584,7 @@
|
|
|
1505
1584
|
});
|
|
1506
1585
|
}
|
|
1507
1586
|
const selfPath = Array.isArray(path) ? path : [];
|
|
1587
|
+
if (this.#hidden.get()) { return Promise.resolve([]); }
|
|
1508
1588
|
const list = [this.validate(true).then(errors => {
|
|
1509
1589
|
if (!errors?.length) { return []; }
|
|
1510
1590
|
return [{ path: [...selfPath], store: /** @type {Store} */(this), errors }];
|
|
@@ -1512,6 +1592,9 @@
|
|
|
1512
1592
|
for (const [key, field] of this) {
|
|
1513
1593
|
list.push(field.validate([...selfPath, key]));
|
|
1514
1594
|
}
|
|
1595
|
+
for (const [field, key] of this.#bindStores) {
|
|
1596
|
+
list.push(field.validate([...selfPath, key]));
|
|
1597
|
+
}
|
|
1515
1598
|
return Promise.all(list).then(v => v.flat());
|
|
1516
1599
|
}
|
|
1517
1600
|
}
|
|
@@ -1521,7 +1604,8 @@
|
|
|
1521
1604
|
/**
|
|
1522
1605
|
* @template {Record<string, any>} [T=Record<string, any>]
|
|
1523
1606
|
* @template [M=any]
|
|
1524
|
-
* @
|
|
1607
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
1608
|
+
* @extends {Store<T, M, S>}
|
|
1525
1609
|
*/
|
|
1526
1610
|
class ObjectStore extends Store {
|
|
1527
1611
|
get kind() { return 'object'; }
|
|
@@ -1535,7 +1619,7 @@
|
|
|
1535
1619
|
*/
|
|
1536
1620
|
child(key) { return this.#children[key] || null; }
|
|
1537
1621
|
/**
|
|
1538
|
-
* @param {Schema.Object<M> & Schema.Attr<M>} schema
|
|
1622
|
+
* @param {Schema.Object<M, S> & Schema.Attr<M, S>} schema
|
|
1539
1623
|
* @param {object} [options]
|
|
1540
1624
|
* @param {Store?} [options.parent]
|
|
1541
1625
|
* @param {number | string | null} [options.index]
|
|
@@ -1587,7 +1671,8 @@
|
|
|
1587
1671
|
/**
|
|
1588
1672
|
* @template [T=any]
|
|
1589
1673
|
* @template [M=any]
|
|
1590
|
-
* @
|
|
1674
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
1675
|
+
* @extends {Store<(T | null)[], M, S>}
|
|
1591
1676
|
*/
|
|
1592
1677
|
class ArrayStore extends Store {
|
|
1593
1678
|
/** @type {(index: number, isNew?: boolean) => Store} */
|
|
@@ -1610,7 +1695,7 @@
|
|
|
1610
1695
|
}
|
|
1611
1696
|
get kind() { return 'array'; }
|
|
1612
1697
|
/**
|
|
1613
|
-
* @param {Schema.Field<M>} schema
|
|
1698
|
+
* @param {Schema.Field<M, S>} schema
|
|
1614
1699
|
* @param {object} [options]
|
|
1615
1700
|
* @param {Store?} [options.parent]
|
|
1616
1701
|
* @param {string | number | null} [options.index]
|
|
@@ -1679,6 +1764,8 @@
|
|
|
1679
1764
|
return child;
|
|
1680
1765
|
};
|
|
1681
1766
|
}
|
|
1767
|
+
/** @returns {never} */
|
|
1768
|
+
bindObject() { throw new Error(`ArrayStore 不支持 bindObject()方法`); }
|
|
1682
1769
|
|
|
1683
1770
|
|
|
1684
1771
|
/** @readonly @type {Signal.State<boolean?>} */
|
|
@@ -4796,7 +4883,7 @@
|
|
|
4796
4883
|
const children = [];
|
|
4797
4884
|
const childStores = [...store];
|
|
4798
4885
|
const count = childStores.length;
|
|
4799
|
-
/** @type {[string, Store<any, any>, number][]} */
|
|
4886
|
+
/** @type {[string, Store<any, any, any>, number][]} */
|
|
4800
4887
|
const stores = sort
|
|
4801
4888
|
? childStores
|
|
4802
4889
|
.map(([k,v]) => [k,v,env.setStore(v, store).exec(sort)])
|
|
@@ -5343,7 +5430,7 @@
|
|
|
5343
5430
|
* @param {StoreLayout.Options?} options
|
|
5344
5431
|
* @param {StoreLayout<T>} layout
|
|
5345
5432
|
* @param {Node} [anchor]
|
|
5346
|
-
* @param {(child?: Store<any, any> | undefined) => void} [dragenter]
|
|
5433
|
+
* @param {(child?: Store<any, any, any> | undefined) => void} [dragenter]
|
|
5347
5434
|
* @returns {void}
|
|
5348
5435
|
*/
|
|
5349
5436
|
function renderHtml(store, fieldRenderer, node, options, layout, anchor, dragenter) {
|
|
@@ -5356,27 +5443,49 @@
|
|
|
5356
5443
|
const mode = node.getAttribute('mode') || '';
|
|
5357
5444
|
const fieldStore = field ? store.child(field) : store;
|
|
5358
5445
|
if (!fieldStore) { return; }
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
: { ...layout, html: '' };
|
|
5446
|
+
/** @type {HTMLElement?} */
|
|
5447
|
+
let el = null;
|
|
5362
5448
|
switch (mode) {
|
|
5363
5449
|
case 'grid': {
|
|
5364
|
-
const
|
|
5365
|
-
|
|
5366
|
-
|
|
5450
|
+
const fieldLayout = field
|
|
5451
|
+
? layout?.fields?.find(createFieldFilter(field)) || fieldStore.layout
|
|
5452
|
+
: { ...layout, html: '' };
|
|
5453
|
+
el = Form(fieldStore, fieldRenderer, fieldLayout, options);
|
|
5454
|
+
break;
|
|
5455
|
+
}
|
|
5456
|
+
default: {
|
|
5457
|
+
el = fieldRenderer(fieldStore, layout.renderer, options);
|
|
5458
|
+
break;
|
|
5367
5459
|
}
|
|
5368
5460
|
}
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
node.replaceWith(
|
|
5461
|
+
if (!el) {
|
|
5462
|
+
const value = node.getAttribute('placeholder') || '';
|
|
5463
|
+
node.replaceWith(document.createTextNode(value));
|
|
5372
5464
|
return;
|
|
5373
5465
|
}
|
|
5374
|
-
const
|
|
5375
|
-
|
|
5466
|
+
const className = node.getAttribute('class') || '';
|
|
5467
|
+
if (className) {
|
|
5468
|
+
el.setAttribute('class', [
|
|
5469
|
+
el.getAttribute('class') || '',
|
|
5470
|
+
className,
|
|
5471
|
+
].filter(Boolean).join(' '));
|
|
5472
|
+
}
|
|
5473
|
+
const style = node.getAttribute('style') || '';
|
|
5474
|
+
if (style) {
|
|
5475
|
+
el.setAttribute('style', [
|
|
5476
|
+
el.getAttribute('style') || '',
|
|
5477
|
+
style,
|
|
5478
|
+
].filter(Boolean).join(' '));
|
|
5479
|
+
}
|
|
5480
|
+
node.replaceWith(el);
|
|
5376
5481
|
return;
|
|
5377
5482
|
}
|
|
5378
5483
|
if (tagName === 'nl-form-button') {
|
|
5379
5484
|
const button = document.createElement('button');
|
|
5485
|
+
const className = node.getAttribute('class') || '';
|
|
5486
|
+
const style = node.getAttribute('style') || '';
|
|
5487
|
+
if (className) { button.setAttribute('class', className); }
|
|
5488
|
+
if (style) { button.setAttribute('style', style); }
|
|
5380
5489
|
button.classList.add('NeeloongForm-item-button');
|
|
5381
5490
|
const click = node.getAttribute('click') || '';
|
|
5382
5491
|
const call = options?.call;
|
|
@@ -5564,7 +5673,7 @@
|
|
|
5564
5673
|
/**
|
|
5565
5674
|
*
|
|
5566
5675
|
* @template T
|
|
5567
|
-
* @param {Store<any, any>} store
|
|
5676
|
+
* @param {Store<any, any, any>} store
|
|
5568
5677
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
5569
5678
|
* @param {StoreLayout<T>} layout
|
|
5570
5679
|
* @param {StoreLayout.Options?} options
|
|
@@ -5587,7 +5696,7 @@
|
|
|
5587
5696
|
/**
|
|
5588
5697
|
*
|
|
5589
5698
|
* @template T
|
|
5590
|
-
* @param {Store<any, any>} store
|
|
5699
|
+
* @param {Store<any, any, any>} store
|
|
5591
5700
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
5592
5701
|
* @param {StoreLayout.Field<T>} layout
|
|
5593
5702
|
* @param {object} option
|
|
@@ -5626,6 +5735,7 @@
|
|
|
5626
5735
|
const body = root.appendChild(document.createElement('tr'));
|
|
5627
5736
|
const main = body.appendChild(document.createElement('td'));
|
|
5628
5737
|
main.colSpan = columns.length;
|
|
5738
|
+
main.appendChild(form);
|
|
5629
5739
|
body.hidden = true;
|
|
5630
5740
|
trigger = () => {
|
|
5631
5741
|
if (body.hidden) {
|
|
@@ -5665,12 +5775,12 @@
|
|
|
5665
5775
|
}
|
|
5666
5776
|
|
|
5667
5777
|
for (const column of columns) {
|
|
5668
|
-
const { actions, field, pattern } = column;
|
|
5778
|
+
const { actions, field, pattern, editable } = column;
|
|
5669
5779
|
if (!actions?.length) {
|
|
5670
5780
|
const td = head.appendChild(document.createElement('td'));
|
|
5671
5781
|
const child = field && store.child(field);
|
|
5672
5782
|
if (child) {
|
|
5673
|
-
const el = FormFieldInline(child, fieldRenderer, column, options);
|
|
5783
|
+
const el = FormFieldInline(child, fieldRenderer, column, {...options, editable: options?.editable && (editable !== false)});
|
|
5674
5784
|
if (el) { td.appendChild(el); }
|
|
5675
5785
|
}
|
|
5676
5786
|
continue;
|
|
@@ -5718,6 +5828,64 @@
|
|
|
5718
5828
|
return root;
|
|
5719
5829
|
}
|
|
5720
5830
|
|
|
5831
|
+
/** @import { ArrayStore } from '../Store/index.mjs' */
|
|
5832
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
5833
|
+
|
|
5834
|
+
/**
|
|
5835
|
+
*
|
|
5836
|
+
* @template T
|
|
5837
|
+
* @param {ArrayStore} store
|
|
5838
|
+
* @param {StoreLayout.Field<T>} layout
|
|
5839
|
+
* @param {StoreLayout.Action[]} actionOptions
|
|
5840
|
+
* @param {(fields: { field: string; width: any; label: any; editable?: boolean? }[]) => StoreLayout.Column<T>[]} createDefault
|
|
5841
|
+
* @returns {StoreLayout.Column<T>[]}
|
|
5842
|
+
*/
|
|
5843
|
+
function getColumns(store, layout, actionOptions, createDefault) {
|
|
5844
|
+
const fieldList = Object.entries(store.type || {})
|
|
5845
|
+
.filter(([k, v]) => typeof v?.type !== 'object')
|
|
5846
|
+
.map(([field, { width, label }]) => ({ field, width, label }));
|
|
5847
|
+
const headerColumns = layout.columns;
|
|
5848
|
+
if (Array.isArray(headerColumns)) {
|
|
5849
|
+
const map = new Map(fieldList.map(v => [v.field, v]));
|
|
5850
|
+
/** @type {(StoreLayout.Column<T> | null)[]} */
|
|
5851
|
+
const allColumns = headerColumns.map(v => {
|
|
5852
|
+
if (!v) { return null; }
|
|
5853
|
+
if (typeof v === 'number') { return { placeholder: v }; }
|
|
5854
|
+
if (typeof v === 'string') { return map.get(v) || null; }
|
|
5855
|
+
if (typeof v !== 'object') { return null; }
|
|
5856
|
+
if (Array.isArray(v)) {
|
|
5857
|
+
/** @type {Set<StoreLayout.Action>} */
|
|
5858
|
+
const options = new Set(actionOptions);
|
|
5859
|
+
const actions = v.filter(v => options.delete(v));
|
|
5860
|
+
if (!actions) { return null; }
|
|
5861
|
+
return { actions };
|
|
5862
|
+
}
|
|
5863
|
+
const { action, actions, field, placeholder, pattern, width, label, editable } = v;
|
|
5864
|
+
if (field) {
|
|
5865
|
+
const define = map.get(field);
|
|
5866
|
+
if (define) {
|
|
5867
|
+
return { field, placeholder, width, label: label || define.label, editable };
|
|
5868
|
+
}
|
|
5869
|
+
}
|
|
5870
|
+
const options = new Set(actionOptions);
|
|
5871
|
+
const allActions = [action, actions].flat().filter(v => v && options.delete(v));
|
|
5872
|
+
if (allActions.length) {
|
|
5873
|
+
return { actions: /** @type {StoreLayout.Action[]} */(allActions), width, label, editable };
|
|
5874
|
+
}
|
|
5875
|
+
if (pattern) {
|
|
5876
|
+
return { pattern, placeholder, width, label, editable };
|
|
5877
|
+
}
|
|
5878
|
+
if (placeholder || width) {
|
|
5879
|
+
return { placeholder, width, label, editable };
|
|
5880
|
+
}
|
|
5881
|
+
return null;
|
|
5882
|
+
});
|
|
5883
|
+
const columns = /** @type {StoreLayout.Column<T>[]} */(allColumns.filter(Boolean));
|
|
5884
|
+
if (columns.length) { return columns; }
|
|
5885
|
+
}
|
|
5886
|
+
return createDefault(fieldList);
|
|
5887
|
+
}
|
|
5888
|
+
|
|
5721
5889
|
/** @import { Store, ArrayStore } from '../Store/index.mjs' */
|
|
5722
5890
|
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
5723
5891
|
|
|
@@ -5748,6 +5916,7 @@
|
|
|
5748
5916
|
watch(() => !addable.get(), disabled => { button.disabled = disabled; }, true, signal);
|
|
5749
5917
|
}
|
|
5750
5918
|
}
|
|
5919
|
+
|
|
5751
5920
|
/**
|
|
5752
5921
|
*
|
|
5753
5922
|
* @template T
|
|
@@ -5759,54 +5928,15 @@
|
|
|
5759
5928
|
*/
|
|
5760
5929
|
function Table(store, fieldRenderer, layout, options) {
|
|
5761
5930
|
if (options?.signal?.aborted) { return null; }
|
|
5762
|
-
const
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
let columns = [];
|
|
5768
|
-
if (Array.isArray(headerColumns)) {
|
|
5769
|
-
const map = new Map(fieldList.map(v => [v.field, v]));
|
|
5770
|
-
|
|
5771
|
-
/** @type {(StoreLayout.Column<T> | null)[]} */
|
|
5772
|
-
const allColumns = headerColumns.map(v => {
|
|
5773
|
-
if (!v) { return null; }
|
|
5774
|
-
if (typeof v === 'number') { return { placeholder: v }; }
|
|
5775
|
-
if (typeof v === 'string') { return map.get(v) || null; }
|
|
5776
|
-
if (typeof v !== 'object') { return null; }
|
|
5777
|
-
if (Array.isArray(v)) {
|
|
5778
|
-
/** @type {Set<StoreLayout.Action>} */
|
|
5779
|
-
const options = new Set(['add', 'move', 'trigger', 'remove', 'serial', 'open', 'collapse']);
|
|
5780
|
-
const actions = v.filter(v => options.delete(v));
|
|
5781
|
-
if (!actions) { return null; }
|
|
5782
|
-
return { actions };
|
|
5783
|
-
}
|
|
5784
|
-
const { action, actions, field, placeholder, pattern, width, label } = v;
|
|
5785
|
-
if (field) {
|
|
5786
|
-
const define = map.get(field);
|
|
5787
|
-
if (define) {
|
|
5788
|
-
return { field, placeholder, width, label: label || define.label };
|
|
5789
|
-
}
|
|
5790
|
-
}
|
|
5791
|
-
const options = new Set(['add', 'move', 'trigger', 'remove', 'serial']);
|
|
5792
|
-
const allActions = [action, actions].flat().filter(v => v && options.delete(v));
|
|
5793
|
-
if (allActions.length) {
|
|
5794
|
-
return { actions: /** @type {StoreLayout.Action[]} */(allActions), width, label };
|
|
5795
|
-
}
|
|
5796
|
-
// if (pattern) {
|
|
5797
|
-
// return { pattern, placeholder, width, label };
|
|
5798
|
-
// }
|
|
5799
|
-
return null;
|
|
5800
|
-
});
|
|
5801
|
-
columns = /** @type {StoreLayout.Column<T>[]} */(allColumns.filter(Boolean));
|
|
5802
|
-
|
|
5803
|
-
}
|
|
5804
|
-
if (!columns.length) {
|
|
5805
|
-
columns = [
|
|
5931
|
+
const columns = getColumns(
|
|
5932
|
+
store,
|
|
5933
|
+
layout,
|
|
5934
|
+
['add', 'move', 'trigger', 'remove', 'serial'],
|
|
5935
|
+
fields => [
|
|
5806
5936
|
{ actions: ['add', 'trigger', 'move', 'remove', 'serial'] },
|
|
5807
|
-
...
|
|
5808
|
-
]
|
|
5809
|
-
|
|
5937
|
+
...fields.slice(0, 3),
|
|
5938
|
+
],
|
|
5939
|
+
);
|
|
5810
5940
|
|
|
5811
5941
|
const table = document.createElement('table');
|
|
5812
5942
|
table.classList.add('NeeloongForm-table');
|
|
@@ -6051,8 +6181,8 @@
|
|
|
6051
6181
|
/**
|
|
6052
6182
|
*
|
|
6053
6183
|
* @template T
|
|
6054
|
-
* @param {Store<any, any>} store
|
|
6055
|
-
* @param {Signal.State<Store<any, any>?>} currentStore
|
|
6184
|
+
* @param {Store<any, any, any>} store
|
|
6185
|
+
* @param {Signal.State<Store<any, any, any>?>} currentStore
|
|
6056
6186
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6057
6187
|
* @param {StoreLayout.Field<T>} layout
|
|
6058
6188
|
* @param {Signal.State<State>} state
|
|
@@ -6066,7 +6196,7 @@
|
|
|
6066
6196
|
* @param {() => void} option.dragend
|
|
6067
6197
|
* @param {{get(): boolean}} option.deletable
|
|
6068
6198
|
* @param {() => void} option.addNode
|
|
6069
|
-
* @param {(store: Store<any, any>) => () => void} option.createDetails
|
|
6199
|
+
* @param {(store: Store<any, any, any>) => () => void} option.createDetails
|
|
6070
6200
|
* @param {StoreLayout.Options?} options
|
|
6071
6201
|
* @returns {HTMLElement}
|
|
6072
6202
|
*/
|
|
@@ -6383,56 +6513,16 @@
|
|
|
6383
6513
|
*/
|
|
6384
6514
|
function Tree(store, fieldRenderer, layout, options) {
|
|
6385
6515
|
if (options?.signal?.aborted) { return null; }
|
|
6386
|
-
const
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
let columns = [];
|
|
6392
|
-
if (Array.isArray(headerColumns)) {
|
|
6393
|
-
const map = new Map(fieldList.map(v => [v.field, v]));
|
|
6394
|
-
/** @type {(StoreLayout.Column<T> | null)[]} */
|
|
6395
|
-
const allColumns = headerColumns.map(v => {
|
|
6396
|
-
if (!v) { return null; }
|
|
6397
|
-
if (typeof v === 'number') { return { placeholder: v }; }
|
|
6398
|
-
if (typeof v === 'string') { return map.get(v) || null; }
|
|
6399
|
-
if (typeof v !== 'object') { return null; }
|
|
6400
|
-
if (Array.isArray(v)) {
|
|
6401
|
-
/** @type {Set<StoreLayout.Action>} */
|
|
6402
|
-
const options = new Set(['add', 'move', 'trigger', 'remove', 'serial', 'open', 'collapse']);
|
|
6403
|
-
const actions = v.filter(v => options.delete(v));
|
|
6404
|
-
if (!actions) { return null; }
|
|
6405
|
-
return { actions };
|
|
6406
|
-
}
|
|
6407
|
-
const { action, actions, field, placeholder, pattern, width, label } = v;
|
|
6408
|
-
if (field) {
|
|
6409
|
-
const define = map.get(field);
|
|
6410
|
-
if (define) {
|
|
6411
|
-
return { field, placeholder, width, label: label || define.label };
|
|
6412
|
-
}
|
|
6413
|
-
}
|
|
6414
|
-
const options = new Set(['add', 'move', 'trigger', 'remove', 'serial', 'open', 'collapse']);
|
|
6415
|
-
const allActions = [action, actions].flat().filter(v => v && options.delete(v));
|
|
6416
|
-
if (allActions.length) {
|
|
6417
|
-
return { actions: /** @type {StoreLayout.Action[]} */(allActions), width, label };
|
|
6418
|
-
}
|
|
6419
|
-
if (pattern) {
|
|
6420
|
-
return { pattern, placeholder, width, label };
|
|
6421
|
-
}
|
|
6422
|
-
if (placeholder || width) {
|
|
6423
|
-
return { placeholder, width, label };
|
|
6424
|
-
}
|
|
6425
|
-
return null;
|
|
6426
|
-
});
|
|
6427
|
-
columns = /** @type {StoreLayout.Column<T>[]} */(allColumns.filter(Boolean));
|
|
6428
|
-
}
|
|
6429
|
-
if (!columns.length) {
|
|
6430
|
-
columns = [
|
|
6516
|
+
const columns = getColumns(
|
|
6517
|
+
store,
|
|
6518
|
+
layout,
|
|
6519
|
+
['add', 'move', 'trigger', 'remove', 'serial', 'open', 'collapse'],
|
|
6520
|
+
fields => [
|
|
6431
6521
|
{ actions: ['collapse', 'move'] },
|
|
6432
|
-
|
|
6522
|
+
fields[0],
|
|
6433
6523
|
{ actions: ['add', 'remove'] },
|
|
6434
|
-
]
|
|
6435
|
-
|
|
6524
|
+
]
|
|
6525
|
+
);
|
|
6436
6526
|
|
|
6437
6527
|
|
|
6438
6528
|
const root = document.createElement('div');
|
|
@@ -6508,10 +6598,10 @@
|
|
|
6508
6598
|
|
|
6509
6599
|
/** @type {AbortController?} */
|
|
6510
6600
|
let detailAbortController = null;
|
|
6511
|
-
const detailsStore = new exports.Signal.State(/** @type{Store<any, any>?}*/(null));
|
|
6601
|
+
const detailsStore = new exports.Signal.State(/** @type{Store<any, any, any>?}*/(null));
|
|
6512
6602
|
/**
|
|
6513
6603
|
*
|
|
6514
|
-
* @param {Store<any, any>} store
|
|
6604
|
+
* @param {Store<any, any, any>} store
|
|
6515
6605
|
* @returns
|
|
6516
6606
|
*/
|
|
6517
6607
|
function createDetails(store) {
|
|
@@ -6763,7 +6853,7 @@
|
|
|
6763
6853
|
*
|
|
6764
6854
|
* @template T
|
|
6765
6855
|
* @param {string | ParentNode} html
|
|
6766
|
-
* @param {Store<any, any>} store
|
|
6856
|
+
* @param {Store<any, any, any>} store
|
|
6767
6857
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6768
6858
|
* @param {StoreLayout.Options?} options
|
|
6769
6859
|
* @param {StoreLayout.Field<T>} layout
|
|
@@ -6795,7 +6885,7 @@
|
|
|
6795
6885
|
/**
|
|
6796
6886
|
*
|
|
6797
6887
|
* @template T
|
|
6798
|
-
* @param {Store<any, any>} store
|
|
6888
|
+
* @param {Store<any, any, any>} store
|
|
6799
6889
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6800
6890
|
* @param {StoreLayout.Field<T>} layout
|
|
6801
6891
|
* @param {StoreLayout.Options?} options
|
|
@@ -6829,7 +6919,7 @@
|
|
|
6829
6919
|
|
|
6830
6920
|
/**
|
|
6831
6921
|
*
|
|
6832
|
-
* @param {Store<any, any>} store
|
|
6922
|
+
* @param {Store<any, any, any>} store
|
|
6833
6923
|
* @param {StoreLayout.Button} layout
|
|
6834
6924
|
* @param {StoreLayout.Options?} options
|
|
6835
6925
|
* @returns {ParentNode}
|
|
@@ -6867,7 +6957,7 @@
|
|
|
6867
6957
|
/**
|
|
6868
6958
|
*
|
|
6869
6959
|
* @template T
|
|
6870
|
-
* @param {Store<any, any>} store
|
|
6960
|
+
* @param {Store<any, any, any>} store
|
|
6871
6961
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6872
6962
|
* @param {StoreLayout.Html} layout
|
|
6873
6963
|
* @param {StoreLayout.Options?} options
|
|
@@ -6889,7 +6979,7 @@
|
|
|
6889
6979
|
/**
|
|
6890
6980
|
*
|
|
6891
6981
|
* @template T
|
|
6892
|
-
* @param {Store<any, any>} store
|
|
6982
|
+
* @param {Store<any, any, any>} store
|
|
6893
6983
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6894
6984
|
* @param {StoreLayout.Item<T>} item
|
|
6895
6985
|
* @param {StoreLayout.Options?} options
|
|
@@ -6914,7 +7004,7 @@
|
|
|
6914
7004
|
/**
|
|
6915
7005
|
*
|
|
6916
7006
|
* @template T
|
|
6917
|
-
* @param {Store<any, any>} store
|
|
7007
|
+
* @param {Store<any, any, any>} store
|
|
6918
7008
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6919
7009
|
* @param {StoreLayout<T>} layout
|
|
6920
7010
|
* @param {StoreLayout.Options?} options
|