@neeloong/form 0.25.0 → 0.27.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 +131 -44
- package/index.full.js +168 -57
- package/index.full.min.js +4 -4
- package/index.full.min.mjs +6 -6
- package/index.min.mjs +2 -2
- package/index.mjs +168 -57
- package/package.json +1 -1
package/index.full.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @neeloong/form v0.
|
|
2
|
+
* @neeloong/form v0.27.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;
|
|
@@ -1513,6 +1592,9 @@
|
|
|
1513
1592
|
for (const [key, field] of this) {
|
|
1514
1593
|
list.push(field.validate([...selfPath, key]));
|
|
1515
1594
|
}
|
|
1595
|
+
for (const [field, key] of this.#bindStores) {
|
|
1596
|
+
list.push(field.validate([...selfPath, key]));
|
|
1597
|
+
}
|
|
1516
1598
|
return Promise.all(list).then(v => v.flat());
|
|
1517
1599
|
}
|
|
1518
1600
|
}
|
|
@@ -1522,7 +1604,8 @@
|
|
|
1522
1604
|
/**
|
|
1523
1605
|
* @template {Record<string, any>} [T=Record<string, any>]
|
|
1524
1606
|
* @template [M=any]
|
|
1525
|
-
* @
|
|
1607
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
1608
|
+
* @extends {Store<T, M, S>}
|
|
1526
1609
|
*/
|
|
1527
1610
|
class ObjectStore extends Store {
|
|
1528
1611
|
get kind() { return 'object'; }
|
|
@@ -1536,7 +1619,7 @@
|
|
|
1536
1619
|
*/
|
|
1537
1620
|
child(key) { return this.#children[key] || null; }
|
|
1538
1621
|
/**
|
|
1539
|
-
* @param {Schema.Object<M> & Schema.Attr<M>} schema
|
|
1622
|
+
* @param {Schema.Object<M, S> & Schema.Attr<M, S>} schema
|
|
1540
1623
|
* @param {object} [options]
|
|
1541
1624
|
* @param {Store?} [options.parent]
|
|
1542
1625
|
* @param {number | string | null} [options.index]
|
|
@@ -1588,7 +1671,8 @@
|
|
|
1588
1671
|
/**
|
|
1589
1672
|
* @template [T=any]
|
|
1590
1673
|
* @template [M=any]
|
|
1591
|
-
* @
|
|
1674
|
+
* @template {Object.<string, Schema.State>} [S=Object.<string, Schema.State>]
|
|
1675
|
+
* @extends {Store<(T | null)[], M, S>}
|
|
1592
1676
|
*/
|
|
1593
1677
|
class ArrayStore extends Store {
|
|
1594
1678
|
/** @type {(index: number, isNew?: boolean) => Store} */
|
|
@@ -1611,7 +1695,7 @@
|
|
|
1611
1695
|
}
|
|
1612
1696
|
get kind() { return 'array'; }
|
|
1613
1697
|
/**
|
|
1614
|
-
* @param {Schema.Field<M>} schema
|
|
1698
|
+
* @param {Schema.Field<M, S>} schema
|
|
1615
1699
|
* @param {object} [options]
|
|
1616
1700
|
* @param {Store?} [options.parent]
|
|
1617
1701
|
* @param {string | number | null} [options.index]
|
|
@@ -1680,6 +1764,8 @@
|
|
|
1680
1764
|
return child;
|
|
1681
1765
|
};
|
|
1682
1766
|
}
|
|
1767
|
+
/** @returns {never} */
|
|
1768
|
+
bindObject() { throw new Error(`ArrayStore 不支持 bindObject()方法`); }
|
|
1683
1769
|
|
|
1684
1770
|
|
|
1685
1771
|
/** @readonly @type {Signal.State<boolean?>} */
|
|
@@ -4797,7 +4883,7 @@
|
|
|
4797
4883
|
const children = [];
|
|
4798
4884
|
const childStores = [...store];
|
|
4799
4885
|
const count = childStores.length;
|
|
4800
|
-
/** @type {[string, Store<any, any>, number][]} */
|
|
4886
|
+
/** @type {[string, Store<any, any, any>, number][]} */
|
|
4801
4887
|
const stores = sort
|
|
4802
4888
|
? childStores
|
|
4803
4889
|
.map(([k,v]) => [k,v,env.setStore(v, store).exec(sort)])
|
|
@@ -5344,7 +5430,7 @@
|
|
|
5344
5430
|
* @param {StoreLayout.Options?} options
|
|
5345
5431
|
* @param {StoreLayout<T>} layout
|
|
5346
5432
|
* @param {Node} [anchor]
|
|
5347
|
-
* @param {(child?: Store<any, any> | undefined) => void} [dragenter]
|
|
5433
|
+
* @param {(child?: Store<any, any, any> | undefined) => void} [dragenter]
|
|
5348
5434
|
* @returns {void}
|
|
5349
5435
|
*/
|
|
5350
5436
|
function renderHtml(store, fieldRenderer, node, options, layout, anchor, dragenter) {
|
|
@@ -5355,29 +5441,53 @@
|
|
|
5355
5441
|
if (tagName === 'nl-form-field') {
|
|
5356
5442
|
const field = node.getAttribute('name') || '';
|
|
5357
5443
|
const mode = node.getAttribute('mode') || '';
|
|
5444
|
+
const renderer = node.getAttribute('renderer') || '';
|
|
5445
|
+
const editable = options?.editable && !node.hasAttribute('non-editable');
|
|
5358
5446
|
const fieldStore = field ? store.child(field) : store;
|
|
5359
5447
|
if (!fieldStore) { return; }
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
: { ...layout, html: '' };
|
|
5448
|
+
/** @type {HTMLElement?} */
|
|
5449
|
+
let el = null;
|
|
5363
5450
|
switch (mode) {
|
|
5364
5451
|
case 'grid': {
|
|
5365
|
-
const
|
|
5366
|
-
|
|
5367
|
-
|
|
5452
|
+
const fieldLayout = field
|
|
5453
|
+
? layout?.fields?.find(createFieldFilter(field)) || fieldStore.layout
|
|
5454
|
+
: { ...layout, html: '' };
|
|
5455
|
+
el = Form(fieldStore, fieldRenderer, fieldLayout, {...options, editable});
|
|
5456
|
+
break;
|
|
5457
|
+
}
|
|
5458
|
+
default: {
|
|
5459
|
+
el = fieldRenderer(fieldStore, renderer || layout.renderer, {...options, editable});
|
|
5460
|
+
break;
|
|
5368
5461
|
}
|
|
5369
5462
|
}
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
node.replaceWith(
|
|
5463
|
+
if (!el) {
|
|
5464
|
+
const value = node.getAttribute('placeholder') || '';
|
|
5465
|
+
node.replaceWith(document.createTextNode(value));
|
|
5373
5466
|
return;
|
|
5374
5467
|
}
|
|
5375
|
-
const
|
|
5376
|
-
|
|
5468
|
+
const className = node.getAttribute('class') || '';
|
|
5469
|
+
if (className) {
|
|
5470
|
+
el.setAttribute('class', [
|
|
5471
|
+
el.getAttribute('class') || '',
|
|
5472
|
+
className,
|
|
5473
|
+
].filter(Boolean).join(' '));
|
|
5474
|
+
}
|
|
5475
|
+
const style = node.getAttribute('style') || '';
|
|
5476
|
+
if (style) {
|
|
5477
|
+
el.setAttribute('style', [
|
|
5478
|
+
el.getAttribute('style') || '',
|
|
5479
|
+
style,
|
|
5480
|
+
].filter(Boolean).join(' '));
|
|
5481
|
+
}
|
|
5482
|
+
node.replaceWith(el);
|
|
5377
5483
|
return;
|
|
5378
5484
|
}
|
|
5379
5485
|
if (tagName === 'nl-form-button') {
|
|
5380
5486
|
const button = document.createElement('button');
|
|
5487
|
+
const className = node.getAttribute('class') || '';
|
|
5488
|
+
const style = node.getAttribute('style') || '';
|
|
5489
|
+
if (className) { button.setAttribute('class', className); }
|
|
5490
|
+
if (style) { button.setAttribute('style', style); }
|
|
5381
5491
|
button.classList.add('NeeloongForm-item-button');
|
|
5382
5492
|
const click = node.getAttribute('click') || '';
|
|
5383
5493
|
const call = options?.call;
|
|
@@ -5548,9 +5658,10 @@
|
|
|
5548
5658
|
/**
|
|
5549
5659
|
*
|
|
5550
5660
|
* @param {string | ParentNode | null} [html]
|
|
5661
|
+
* @param {function(string): string} [sanitize]
|
|
5551
5662
|
* @returns {ParentNode}
|
|
5552
5663
|
*/
|
|
5553
|
-
function getHtmlContent(html) {
|
|
5664
|
+
function getHtmlContent(html, sanitize) {
|
|
5554
5665
|
if (!html) {
|
|
5555
5666
|
return document.createElement('template').content;
|
|
5556
5667
|
}
|
|
@@ -5558,14 +5669,14 @@
|
|
|
5558
5669
|
return /** @type {ParentNode} */(html.cloneNode(true));
|
|
5559
5670
|
}
|
|
5560
5671
|
const template = document.createElement('template');
|
|
5561
|
-
template.innerHTML = html;
|
|
5672
|
+
template.innerHTML = sanitize ? sanitize(html) : html;
|
|
5562
5673
|
return template.content;
|
|
5563
5674
|
}
|
|
5564
5675
|
|
|
5565
5676
|
/**
|
|
5566
5677
|
*
|
|
5567
5678
|
* @template T
|
|
5568
|
-
* @param {Store<any, any>} store
|
|
5679
|
+
* @param {Store<any, any, any>} store
|
|
5569
5680
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
5570
5681
|
* @param {StoreLayout<T>} layout
|
|
5571
5682
|
* @param {StoreLayout.Options?} options
|
|
@@ -5575,7 +5686,7 @@
|
|
|
5575
5686
|
if (options?.signal?.aborted) { return null; }
|
|
5576
5687
|
const html = layout.html;
|
|
5577
5688
|
if (html) {
|
|
5578
|
-
const content = getHtmlContent(html);
|
|
5689
|
+
const content = getHtmlContent(html, options?.sanitizeHtml);
|
|
5579
5690
|
renderHtml(store, fieldRenderer, content, options, layout);
|
|
5580
5691
|
return content;
|
|
5581
5692
|
}
|
|
@@ -5588,7 +5699,7 @@
|
|
|
5588
5699
|
/**
|
|
5589
5700
|
*
|
|
5590
5701
|
* @template T
|
|
5591
|
-
* @param {Store<any, any>} store
|
|
5702
|
+
* @param {Store<any, any, any>} store
|
|
5592
5703
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
5593
5704
|
* @param {StoreLayout.Field<T>} layout
|
|
5594
5705
|
* @param {object} option
|
|
@@ -5667,12 +5778,12 @@
|
|
|
5667
5778
|
}
|
|
5668
5779
|
|
|
5669
5780
|
for (const column of columns) {
|
|
5670
|
-
const { actions, field, pattern } = column;
|
|
5781
|
+
const { actions, field, pattern, editable } = column;
|
|
5671
5782
|
if (!actions?.length) {
|
|
5672
5783
|
const td = head.appendChild(document.createElement('td'));
|
|
5673
5784
|
const child = field && store.child(field);
|
|
5674
5785
|
if (child) {
|
|
5675
|
-
const el = FormFieldInline(child, fieldRenderer, column, options);
|
|
5786
|
+
const el = FormFieldInline(child, fieldRenderer, column, {...options, editable: options?.editable && (editable !== false)});
|
|
5676
5787
|
if (el) { td.appendChild(el); }
|
|
5677
5788
|
}
|
|
5678
5789
|
continue;
|
|
@@ -5729,7 +5840,7 @@
|
|
|
5729
5840
|
* @param {ArrayStore} store
|
|
5730
5841
|
* @param {StoreLayout.Field<T>} layout
|
|
5731
5842
|
* @param {StoreLayout.Action[]} actionOptions
|
|
5732
|
-
* @param {(fields: { field: string; width: any; label: any; }[]) => StoreLayout.Column<T>[]} createDefault
|
|
5843
|
+
* @param {(fields: { field: string; width: any; label: any; editable?: boolean? }[]) => StoreLayout.Column<T>[]} createDefault
|
|
5733
5844
|
* @returns {StoreLayout.Column<T>[]}
|
|
5734
5845
|
*/
|
|
5735
5846
|
function getColumns(store, layout, actionOptions, createDefault) {
|
|
@@ -5752,23 +5863,23 @@
|
|
|
5752
5863
|
if (!actions) { return null; }
|
|
5753
5864
|
return { actions };
|
|
5754
5865
|
}
|
|
5755
|
-
const { action, actions, field, placeholder, pattern, width, label } = v;
|
|
5866
|
+
const { action, actions, field, placeholder, pattern, width, label, editable } = v;
|
|
5756
5867
|
if (field) {
|
|
5757
5868
|
const define = map.get(field);
|
|
5758
5869
|
if (define) {
|
|
5759
|
-
return { field, placeholder, width, label: label || define.label };
|
|
5870
|
+
return { field, placeholder, width, label: label || define.label, editable };
|
|
5760
5871
|
}
|
|
5761
5872
|
}
|
|
5762
5873
|
const options = new Set(actionOptions);
|
|
5763
5874
|
const allActions = [action, actions].flat().filter(v => v && options.delete(v));
|
|
5764
5875
|
if (allActions.length) {
|
|
5765
|
-
return { actions: /** @type {StoreLayout.Action[]} */(allActions), width, label };
|
|
5876
|
+
return { actions: /** @type {StoreLayout.Action[]} */(allActions), width, label, editable };
|
|
5766
5877
|
}
|
|
5767
5878
|
if (pattern) {
|
|
5768
|
-
return { pattern, placeholder, width, label };
|
|
5879
|
+
return { pattern, placeholder, width, label, editable };
|
|
5769
5880
|
}
|
|
5770
5881
|
if (placeholder || width) {
|
|
5771
|
-
return { placeholder, width, label };
|
|
5882
|
+
return { placeholder, width, label, editable };
|
|
5772
5883
|
}
|
|
5773
5884
|
return null;
|
|
5774
5885
|
});
|
|
@@ -6073,8 +6184,8 @@
|
|
|
6073
6184
|
/**
|
|
6074
6185
|
*
|
|
6075
6186
|
* @template T
|
|
6076
|
-
* @param {Store<any, any>} store
|
|
6077
|
-
* @param {Signal.State<Store<any, any>?>} currentStore
|
|
6187
|
+
* @param {Store<any, any, any>} store
|
|
6188
|
+
* @param {Signal.State<Store<any, any, any>?>} currentStore
|
|
6078
6189
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6079
6190
|
* @param {StoreLayout.Field<T>} layout
|
|
6080
6191
|
* @param {Signal.State<State>} state
|
|
@@ -6088,7 +6199,7 @@
|
|
|
6088
6199
|
* @param {() => void} option.dragend
|
|
6089
6200
|
* @param {{get(): boolean}} option.deletable
|
|
6090
6201
|
* @param {() => void} option.addNode
|
|
6091
|
-
* @param {(store: Store<any, any>) => () => void} option.createDetails
|
|
6202
|
+
* @param {(store: Store<any, any, any>) => () => void} option.createDetails
|
|
6092
6203
|
* @param {StoreLayout.Options?} options
|
|
6093
6204
|
* @returns {HTMLElement}
|
|
6094
6205
|
*/
|
|
@@ -6490,10 +6601,10 @@
|
|
|
6490
6601
|
|
|
6491
6602
|
/** @type {AbortController?} */
|
|
6492
6603
|
let detailAbortController = null;
|
|
6493
|
-
const detailsStore = new exports.Signal.State(/** @type{Store<any, any>?}*/(null));
|
|
6604
|
+
const detailsStore = new exports.Signal.State(/** @type{Store<any, any, any>?}*/(null));
|
|
6494
6605
|
/**
|
|
6495
6606
|
*
|
|
6496
|
-
* @param {Store<any, any>} store
|
|
6607
|
+
* @param {Store<any, any, any>} store
|
|
6497
6608
|
* @returns
|
|
6498
6609
|
*/
|
|
6499
6610
|
function createDetails(store) {
|
|
@@ -6745,14 +6856,14 @@
|
|
|
6745
6856
|
*
|
|
6746
6857
|
* @template T
|
|
6747
6858
|
* @param {string | ParentNode} html
|
|
6748
|
-
* @param {Store<any, any>} store
|
|
6859
|
+
* @param {Store<any, any, any>} store
|
|
6749
6860
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6750
6861
|
* @param {StoreLayout.Options?} options
|
|
6751
6862
|
* @param {StoreLayout.Field<T>} layout
|
|
6752
6863
|
* @returns {ParentNode}
|
|
6753
6864
|
*/
|
|
6754
6865
|
function Html(html, store, fieldRenderer, options, layout) {
|
|
6755
|
-
const htmlContent = getHtmlContent(html);
|
|
6866
|
+
const htmlContent = getHtmlContent(html, options?.sanitizeHtml);
|
|
6756
6867
|
renderHtml(store, fieldRenderer, htmlContent, options, layout);
|
|
6757
6868
|
return htmlContent;
|
|
6758
6869
|
}
|
|
@@ -6777,7 +6888,7 @@
|
|
|
6777
6888
|
/**
|
|
6778
6889
|
*
|
|
6779
6890
|
* @template T
|
|
6780
|
-
* @param {Store<any, any>} store
|
|
6891
|
+
* @param {Store<any, any, any>} store
|
|
6781
6892
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6782
6893
|
* @param {StoreLayout.Field<T>} layout
|
|
6783
6894
|
* @param {StoreLayout.Options?} options
|
|
@@ -6811,7 +6922,7 @@
|
|
|
6811
6922
|
|
|
6812
6923
|
/**
|
|
6813
6924
|
*
|
|
6814
|
-
* @param {Store<any, any>} store
|
|
6925
|
+
* @param {Store<any, any, any>} store
|
|
6815
6926
|
* @param {StoreLayout.Button} layout
|
|
6816
6927
|
* @param {StoreLayout.Options?} options
|
|
6817
6928
|
* @returns {ParentNode}
|
|
@@ -6849,7 +6960,7 @@
|
|
|
6849
6960
|
/**
|
|
6850
6961
|
*
|
|
6851
6962
|
* @template T
|
|
6852
|
-
* @param {Store<any, any>} store
|
|
6963
|
+
* @param {Store<any, any, any>} store
|
|
6853
6964
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6854
6965
|
* @param {StoreLayout.Html} layout
|
|
6855
6966
|
* @param {StoreLayout.Options?} options
|
|
@@ -6859,7 +6970,7 @@
|
|
|
6859
6970
|
const html = layout.html;
|
|
6860
6971
|
if (!html) { return null; }
|
|
6861
6972
|
const [root, content] = createCell(options?.signal, layout, store);
|
|
6862
|
-
const htmlContent = getHtmlContent(html);
|
|
6973
|
+
const htmlContent = getHtmlContent(html, options?.sanitizeHtml);
|
|
6863
6974
|
renderHtml(store, fieldRenderer, htmlContent, options, layout);
|
|
6864
6975
|
content.appendChild(htmlContent);
|
|
6865
6976
|
return root;
|
|
@@ -6871,7 +6982,7 @@
|
|
|
6871
6982
|
/**
|
|
6872
6983
|
*
|
|
6873
6984
|
* @template T
|
|
6874
|
-
* @param {Store<any, any>} store
|
|
6985
|
+
* @param {Store<any, any, any>} store
|
|
6875
6986
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6876
6987
|
* @param {StoreLayout.Item<T>} item
|
|
6877
6988
|
* @param {StoreLayout.Options?} options
|
|
@@ -6896,7 +7007,7 @@
|
|
|
6896
7007
|
/**
|
|
6897
7008
|
*
|
|
6898
7009
|
* @template T
|
|
6899
|
-
* @param {Store<any, any>} store
|
|
7010
|
+
* @param {Store<any, any, any>} store
|
|
6900
7011
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6901
7012
|
* @param {StoreLayout<T>} layout
|
|
6902
7013
|
* @param {StoreLayout.Options?} options
|
|
@@ -6945,7 +7056,7 @@
|
|
|
6945
7056
|
Form(store, fieldRenderer, storeLayout, options || null, root);
|
|
6946
7057
|
return;
|
|
6947
7058
|
}
|
|
6948
|
-
const content = getHtmlContent(html);
|
|
7059
|
+
const content = getHtmlContent(html, options?.sanitizeHtml);
|
|
6949
7060
|
renderHtml(store, fieldRenderer, content, options || null, storeLayout);
|
|
6950
7061
|
root.appendChild(content);
|
|
6951
7062
|
options?.signal?.addEventListener('abort', () => {
|