@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.full.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @neeloong/form v0.25.0
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
- * @param {Schema.Field<M>} schema
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
- * @param {Schema<M>} schema 数据结构模式
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
- * @extends {Store<T, M>}
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
- * @extends {Store<(T | null)[], M>}
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
- const fieldLayout = field
5361
- ? layout?.fields?.find(createFieldFilter(field)) || fieldStore.layout
5362
- : { ...layout, html: '' };
5448
+ /** @type {HTMLElement?} */
5449
+ let el = null;
5363
5450
  switch (mode) {
5364
5451
  case 'grid': {
5365
- const el = Form(store, fieldRenderer, fieldLayout, options);
5366
- if (el) { node.replaceWith(el); }
5367
- return;
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
- const res = fieldRenderer(fieldStore, layout.renderer, options);
5371
- if (res) {
5372
- node.replaceWith(res);
5463
+ if (!el) {
5464
+ const value = node.getAttribute('placeholder') || '';
5465
+ node.replaceWith(document.createTextNode(value));
5373
5466
  return;
5374
5467
  }
5375
- const value = node.getAttribute('placeholder') || '';
5376
- node.replaceWith(document.createTextNode(value));
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', () => {