@neeloong/form 0.23.0 → 0.25.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 +1105 -1099
- package/index.full.js +189 -185
- package/index.full.min.js +2 -2
- package/index.full.min.mjs +2 -2
- package/index.min.mjs +2 -2
- package/index.mjs +189 -185
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @neeloong/form v0.
|
|
2
|
+
* @neeloong/form v0.25.0
|
|
3
3
|
* (c) 2024-2026 Fierflame
|
|
4
4
|
* @license Apache-2.0
|
|
5
5
|
*/
|
|
@@ -36,7 +36,7 @@ function createBooleanStates(self, defState, fn, parent) {
|
|
|
36
36
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/** @import { Schema } from '../types.mjs' */
|
|
39
|
+
/** @import { Schema } from '../Schema.types.mjs' */
|
|
40
40
|
/** @param {*} v */
|
|
41
41
|
const string = v => typeof v === 'string' && v || null;
|
|
42
42
|
/** @param {*} v */
|
|
@@ -133,7 +133,7 @@ function createRef(store) {
|
|
|
133
133
|
return r;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
/** @import { Schema } from '../types.mjs' */
|
|
136
|
+
/** @import { Schema } from '../Schema.types.mjs' */
|
|
137
137
|
/** @import ArrayStore from './ArrayStore.mjs' */
|
|
138
138
|
|
|
139
139
|
|
|
@@ -185,7 +185,7 @@ function setStore$1(type, Class) {
|
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
/** @import Store from './Store.mjs' */
|
|
188
|
-
/** @import {
|
|
188
|
+
/** @import { Schema } from '../Schema.types.mjs' */
|
|
189
189
|
/**
|
|
190
190
|
*
|
|
191
191
|
* @param {*} v
|
|
@@ -200,7 +200,7 @@ function toResult(v) {
|
|
|
200
200
|
/**
|
|
201
201
|
*
|
|
202
202
|
* @param {Store} store
|
|
203
|
-
* @param {...Validator | undefined | null | (Validator | undefined | null)[]} validators
|
|
203
|
+
* @param {...Schema.Validator | undefined | null | (Schema.Validator | undefined | null)[]} validators
|
|
204
204
|
* @returns
|
|
205
205
|
*/
|
|
206
206
|
function createValidator(store, ...validators) {
|
|
@@ -223,7 +223,7 @@ function createValidator(store, ...validators) {
|
|
|
223
223
|
/**
|
|
224
224
|
*
|
|
225
225
|
* @param {Store} store
|
|
226
|
-
* @param {...AsyncValidator | undefined | null | (AsyncValidator | undefined | null)[]} validators
|
|
226
|
+
* @param {...Schema.AsyncValidator | undefined | null | (Schema.AsyncValidator | undefined | null)[]} validators
|
|
227
227
|
* @returns {[exec: () => Promise<string[]>, state: Signal.Computed<string[]>, stop: () => void]}
|
|
228
228
|
*/
|
|
229
229
|
function createAsyncValidator(store, ...validators) {
|
|
@@ -238,7 +238,7 @@ function createAsyncValidator(store, ...validators) {
|
|
|
238
238
|
const st = new Signal.State(/** @type {string[]} */([]));
|
|
239
239
|
/**
|
|
240
240
|
*
|
|
241
|
-
* @param {AsyncValidator} validator
|
|
241
|
+
* @param {Schema.AsyncValidator} validator
|
|
242
242
|
* @param {AbortSignal} signal
|
|
243
243
|
*/
|
|
244
244
|
async function run(validator, signal) {
|
|
@@ -292,7 +292,8 @@ function makeDefault(store, def) {
|
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
/** @import { Ref } from './ref.mjs' */
|
|
295
|
-
/** @import {
|
|
295
|
+
/** @import { Schema } from '../Schema.types.mjs' */
|
|
296
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
296
297
|
|
|
297
298
|
/**
|
|
298
299
|
* 管理单个表单字段的状态和行为
|
|
@@ -389,8 +390,8 @@ class Store {
|
|
|
389
390
|
* @param {number} [options.maxLength]
|
|
390
391
|
* @param {RegExp} [options.pattern]
|
|
391
392
|
* @param {(Schema.Value.Group | Schema.Value | string | number)[]} [options.values] 可选值
|
|
392
|
-
* @param {Validator | Validator[] | null} [options.validator]
|
|
393
|
-
* @param {{[k in keyof Schema.Events]?: AsyncValidator | AsyncValidator[] | null}} [options.validators]
|
|
393
|
+
* @param {Schema.Validator | Schema.Validator[] | null} [options.validator]
|
|
394
|
+
* @param {{[k in keyof Schema.Events]?: Schema.AsyncValidator | Schema.AsyncValidator[] | null}} [options.validators]
|
|
394
395
|
*
|
|
395
396
|
* @param {Ref?} [options.ref]
|
|
396
397
|
*
|
|
@@ -422,6 +423,7 @@ class Store {
|
|
|
422
423
|
this.#type = schema.type;
|
|
423
424
|
this.#meta = schema.meta;
|
|
424
425
|
this.#component = schema.component;
|
|
426
|
+
this.#layout = schema.layout || {};
|
|
425
427
|
|
|
426
428
|
const selfNewState = new Signal.State(Boolean(isNew));
|
|
427
429
|
this.#selfNew = selfNewState;
|
|
@@ -512,6 +514,9 @@ class Store {
|
|
|
512
514
|
this.listen(k, f);
|
|
513
515
|
}
|
|
514
516
|
}
|
|
517
|
+
/** @type {StoreLayout.Field<any>} */
|
|
518
|
+
#layout
|
|
519
|
+
get layout() { return this.#layout; }
|
|
515
520
|
#createDefault;
|
|
516
521
|
/** @param {any} [value] @returns {any} */
|
|
517
522
|
createDefault(value) { return this.#createDefault(value); }
|
|
@@ -899,7 +904,7 @@ class Store {
|
|
|
899
904
|
/**
|
|
900
905
|
* 异步校验
|
|
901
906
|
* @overload
|
|
902
|
-
* @param {true} [
|
|
907
|
+
* @param {true} [self]
|
|
903
908
|
* @returns {Promise<string[] | null>}
|
|
904
909
|
*/
|
|
905
910
|
/**
|
|
@@ -922,6 +927,7 @@ class Store {
|
|
|
922
927
|
});
|
|
923
928
|
}
|
|
924
929
|
const selfPath = Array.isArray(path) ? path : [];
|
|
930
|
+
if (this.#hidden.get()) { return Promise.resolve([]); }
|
|
925
931
|
const list = [this.validate(true).then(errors => {
|
|
926
932
|
if (!errors?.length) { return []; }
|
|
927
933
|
return [{ path: [...selfPath], store: /** @type {Store} */(this), errors }];
|
|
@@ -933,7 +939,7 @@ class Store {
|
|
|
933
939
|
}
|
|
934
940
|
}
|
|
935
941
|
|
|
936
|
-
/** @import { Schema } from '../types.mjs' */
|
|
942
|
+
/** @import { Schema } from '../Schema.types.mjs' */
|
|
937
943
|
|
|
938
944
|
/**
|
|
939
945
|
* @template {Record<string, any>} [T=Record<string, any>]
|
|
@@ -997,7 +1003,7 @@ class ObjectStore extends Store {
|
|
|
997
1003
|
// @ts-ignore
|
|
998
1004
|
setObjectStore(ObjectStore);
|
|
999
1005
|
|
|
1000
|
-
/** @import { Schema } from '../types.mjs' */
|
|
1006
|
+
/** @import { Schema } from '../Schema.types.mjs' */
|
|
1001
1007
|
|
|
1002
1008
|
|
|
1003
1009
|
|
|
@@ -1051,7 +1057,7 @@ class ArrayStore extends Store {
|
|
|
1051
1057
|
}
|
|
1052
1058
|
|
|
1053
1059
|
};
|
|
1054
|
-
super(schema, {
|
|
1060
|
+
super({ ...schema, immutable: false }, {
|
|
1055
1061
|
index, new: isNew, parent,
|
|
1056
1062
|
size: new Signal.Computed(() => childrenState.get().length),
|
|
1057
1063
|
setValue(v) {
|
|
@@ -1088,7 +1094,10 @@ class ArrayStore extends Store {
|
|
|
1088
1094
|
},
|
|
1089
1095
|
};
|
|
1090
1096
|
this.#create = (index, isNew) => {
|
|
1091
|
-
const child = create(
|
|
1097
|
+
const child = create(
|
|
1098
|
+
{ ...schema, creatable: true },
|
|
1099
|
+
{ ...childCommonOptions, index, new: isNew },
|
|
1100
|
+
);
|
|
1092
1101
|
child.index = index;
|
|
1093
1102
|
return child;
|
|
1094
1103
|
};
|
|
@@ -3486,8 +3495,7 @@ class EventEmitter {
|
|
|
3486
3495
|
}
|
|
3487
3496
|
}
|
|
3488
3497
|
|
|
3489
|
-
/** @import { Component
|
|
3490
|
-
/** @import Store from '../Store/index.mjs' */
|
|
3498
|
+
/** @import { Component } from '../types.mjs' */
|
|
3491
3499
|
/** @import Environment from './Environment/index.mjs' */
|
|
3492
3500
|
/** @import * as Layout from '../Layout/index.mjs' */
|
|
3493
3501
|
|
|
@@ -3657,7 +3665,8 @@ function bindFilters(env, fn, filterFns) {
|
|
|
3657
3665
|
}
|
|
3658
3666
|
}
|
|
3659
3667
|
|
|
3660
|
-
/** @import { Component
|
|
3668
|
+
/** @import { Component } from '../types.mjs' */
|
|
3669
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
3661
3670
|
/** @import { ComponentHandler } from './types.mjs' */
|
|
3662
3671
|
/** @import Store from '../Store/index.mjs' */
|
|
3663
3672
|
/** @import Environment from './Environment/index.mjs' */
|
|
@@ -3668,7 +3677,7 @@ function bindFilters(env, fn, filterFns) {
|
|
|
3668
3677
|
* @param {Component | string} component
|
|
3669
3678
|
* @param {Environment} env
|
|
3670
3679
|
* @param {Store?} store
|
|
3671
|
-
* @param {((store: Store, el: Element | Relatedness) => () => void)?} [relate]
|
|
3680
|
+
* @param {((store: Store, el: Element | StoreLayout.Relatedness) => () => void)?} [relate]
|
|
3672
3681
|
* @returns
|
|
3673
3682
|
*/
|
|
3674
3683
|
function createContext(component, env, store, relate) {
|
|
@@ -4546,7 +4555,7 @@ function divergent(layout, parent, next, env, renderItem) {
|
|
|
4546
4555
|
* @param {Record<string, [Layout.Template, Environment]>} templates
|
|
4547
4556
|
* @param {string[]} componentPath
|
|
4548
4557
|
* @param {Record<string, Enhancement>} enhancements
|
|
4549
|
-
* @param {((store: Store, el: Element | Relatedness) => () => void)?} [relate]
|
|
4558
|
+
* @param {((store: Store, el: Element | StoreLayout.Relatedness) => () => void)?} [relate]
|
|
4550
4559
|
* @param {Component.Getter?} [getComponent]
|
|
4551
4560
|
*/
|
|
4552
4561
|
function renderNode(layout, parent, next, env, templates, componentPath, enhancements, relate, getComponent) {
|
|
@@ -4628,7 +4637,7 @@ function createTemplates(env, parentTemplates, newTemplates) {
|
|
|
4628
4637
|
* @param {Record<string, [Layout.Template, Environment]>} parentTemplates
|
|
4629
4638
|
* @param {string[]} componentPath
|
|
4630
4639
|
* @param {Record<string, Enhancement>} enhancements
|
|
4631
|
-
* @param {((store: Store, el: Element | Relatedness) => () => void)?} [relate]
|
|
4640
|
+
* @param {((store: Store, el: Element | StoreLayout.Relatedness) => () => void)?} [relate]
|
|
4632
4641
|
* @param {Component.Getter?} [getComponent]
|
|
4633
4642
|
* @returns {() => void}
|
|
4634
4643
|
*/
|
|
@@ -4693,7 +4702,7 @@ function renderChild(layout, parent, next, parentEnv, parentTemplates, component
|
|
|
4693
4702
|
* @param {Record<string, [Layout.Template, Environment]>} templates
|
|
4694
4703
|
* @param {string[]} componentPath
|
|
4695
4704
|
* @param {Record<string, Enhancement>} enhancements
|
|
4696
|
-
* @param {((store: Store, el: Element | Relatedness) => () => void)?} [relate]
|
|
4705
|
+
* @param {((store: Store, el: Element | StoreLayout.Relatedness) => () => void)?} [relate]
|
|
4697
4706
|
* @param {Component.Getter?} [getComponent]
|
|
4698
4707
|
* @returns {() => void}
|
|
4699
4708
|
*/
|
|
@@ -4716,7 +4725,7 @@ function renderChildren(layouts, parent, next, env, templates, componentPath, en
|
|
|
4716
4725
|
* @param {object} [options] 选项
|
|
4717
4726
|
* @param {Record<string, Store | {get?(): any; set?(v: any): void; exec?(...p: any[]): any; calc?(...p: any[]): any }>} [options.global] 全局数据
|
|
4718
4727
|
* @param {Component.Getter?} [options.component] 自定义组件
|
|
4719
|
-
* @param {(store: Store, el: Element | Relatedness) => () => void} [options.relate] 关联函数
|
|
4728
|
+
* @param {(store: Store, el: Element | StoreLayout.Relatedness) => () => void} [options.relate] 关联函数
|
|
4720
4729
|
* @param {Record<string, Enhancement>} [options.enhancements] 增强信息
|
|
4721
4730
|
* @returns {() => void}
|
|
4722
4731
|
*/
|
|
@@ -4729,7 +4738,7 @@ function render(store, layouts, parent, { component, global, relate, enhancement
|
|
|
4729
4738
|
}
|
|
4730
4739
|
|
|
4731
4740
|
/** @import { Store } from '../Store/index.mjs' */
|
|
4732
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
4741
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
4733
4742
|
|
|
4734
4743
|
/**
|
|
4735
4744
|
*
|
|
@@ -4755,7 +4764,7 @@ function createFieldFilter(field) {
|
|
|
4755
4764
|
* @param {Store} store
|
|
4756
4765
|
* @param {Node} node
|
|
4757
4766
|
* @param {StoreLayout.Options?} options
|
|
4758
|
-
* @param {StoreLayout<T
|
|
4767
|
+
* @param {StoreLayout<T>} layout
|
|
4759
4768
|
* @param {Node} [anchor]
|
|
4760
4769
|
* @param {(child?: Store<any, any> | undefined) => void} [dragenter]
|
|
4761
4770
|
* @returns {void}
|
|
@@ -4769,8 +4778,10 @@ function renderHtml(store, fieldRenderer, node, options, layout, anchor, dragent
|
|
|
4769
4778
|
const field = node.getAttribute('name') || '';
|
|
4770
4779
|
const mode = node.getAttribute('mode') || '';
|
|
4771
4780
|
const fieldStore = field ? store.child(field) : store;
|
|
4772
|
-
const fieldLayout = field ? layout?.fields?.find(createFieldFilter(field)) || null : null;
|
|
4773
4781
|
if (!fieldStore) { return; }
|
|
4782
|
+
const fieldLayout = field
|
|
4783
|
+
? layout?.fields?.find(createFieldFilter(field)) || fieldStore.layout
|
|
4784
|
+
: { ...layout, html: '' };
|
|
4774
4785
|
switch (mode) {
|
|
4775
4786
|
case 'grid': {
|
|
4776
4787
|
const el = Form(store, fieldRenderer, fieldLayout, options);
|
|
@@ -4778,7 +4789,7 @@ function renderHtml(store, fieldRenderer, node, options, layout, anchor, dragent
|
|
|
4778
4789
|
return;
|
|
4779
4790
|
}
|
|
4780
4791
|
}
|
|
4781
|
-
const res = fieldRenderer(fieldStore, layout
|
|
4792
|
+
const res = fieldRenderer(fieldStore, layout.renderer, options);
|
|
4782
4793
|
if (res) {
|
|
4783
4794
|
node.replaceWith(res);
|
|
4784
4795
|
return;
|
|
@@ -4811,7 +4822,9 @@ function renderHtml(store, fieldRenderer, node, options, layout, anchor, dragent
|
|
|
4811
4822
|
return;
|
|
4812
4823
|
}
|
|
4813
4824
|
node.removeAttribute('nl-form-field');
|
|
4814
|
-
const fieldLayout = field
|
|
4825
|
+
const fieldLayout = field
|
|
4826
|
+
? layout.fields?.find(createFieldFilter(field)) || fieldStore.layout
|
|
4827
|
+
: { ...layout, html: '' };
|
|
4815
4828
|
if (!array) {
|
|
4816
4829
|
renderHtml(fieldStore, fieldRenderer, node, options, fieldLayout, anchor);
|
|
4817
4830
|
return;
|
|
@@ -4976,26 +4989,32 @@ function getHtmlContent(html) {
|
|
|
4976
4989
|
* @template T
|
|
4977
4990
|
* @param {Store<any, any>} store
|
|
4978
4991
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
4979
|
-
* @param {StoreLayout
|
|
4992
|
+
* @param {StoreLayout<T>} layout
|
|
4980
4993
|
* @param {StoreLayout.Options?} options
|
|
4981
4994
|
* @returns {ParentNode?}
|
|
4982
4995
|
*/
|
|
4983
4996
|
function FormFieldInline(store, fieldRenderer, layout, options) {
|
|
4984
4997
|
if (options?.signal?.aborted) { return null; }
|
|
4985
|
-
|
|
4998
|
+
const html = layout.html;
|
|
4999
|
+
if (html) {
|
|
5000
|
+
const content = getHtmlContent(html);
|
|
5001
|
+
renderHtml(store, fieldRenderer, content, options, layout);
|
|
5002
|
+
return content;
|
|
5003
|
+
}
|
|
5004
|
+
return fieldRenderer(store, layout.renderer, options);
|
|
4986
5005
|
}
|
|
4987
5006
|
|
|
4988
5007
|
/** @import { Store } from '../Store/index.mjs' */
|
|
4989
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
5008
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
4990
5009
|
|
|
4991
5010
|
/**
|
|
4992
5011
|
*
|
|
4993
5012
|
* @template T
|
|
4994
5013
|
* @param {Store<any, any>} store
|
|
4995
5014
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
4996
|
-
* @param {StoreLayout.Field<T
|
|
5015
|
+
* @param {StoreLayout.Field<T>} layout
|
|
4997
5016
|
* @param {object} option
|
|
4998
|
-
* @param {StoreLayout.Column[]} option.columns
|
|
5017
|
+
* @param {StoreLayout.Column<T>[]} option.columns
|
|
4999
5018
|
* @param {() => void} option.remove
|
|
5000
5019
|
* @param {() => void} option.dragenter
|
|
5001
5020
|
* @param {() => void} option.dragstart
|
|
@@ -5005,8 +5024,8 @@ function FormFieldInline(store, fieldRenderer, layout, options) {
|
|
|
5005
5024
|
* @returns {HTMLTableSectionElement}
|
|
5006
5025
|
*/
|
|
5007
5026
|
function Line(store, fieldRenderer, layout, {
|
|
5008
|
-
columns,
|
|
5009
|
-
remove, dragenter, dragstart, dragend,
|
|
5027
|
+
columns, deletable,
|
|
5028
|
+
remove, dragenter, dragstart, dragend,
|
|
5010
5029
|
}, options) {
|
|
5011
5030
|
const root = document.createElement('tbody');
|
|
5012
5031
|
root.addEventListener('dragenter', () => {
|
|
@@ -5030,6 +5049,7 @@ function Line(store, fieldRenderer, layout, {
|
|
|
5030
5049
|
const body = root.appendChild(document.createElement('tr'));
|
|
5031
5050
|
const main = body.appendChild(document.createElement('td'));
|
|
5032
5051
|
main.colSpan = columns.length;
|
|
5052
|
+
main.appendChild(form);
|
|
5033
5053
|
body.hidden = true;
|
|
5034
5054
|
trigger = () => {
|
|
5035
5055
|
if (body.hidden) {
|
|
@@ -5068,13 +5088,13 @@ function Line(store, fieldRenderer, layout, {
|
|
|
5068
5088
|
|
|
5069
5089
|
}
|
|
5070
5090
|
|
|
5071
|
-
for (const
|
|
5072
|
-
const { actions, field, pattern } =
|
|
5091
|
+
for (const column of columns) {
|
|
5092
|
+
const { actions, field, pattern } = column;
|
|
5073
5093
|
if (!actions?.length) {
|
|
5074
5094
|
const td = head.appendChild(document.createElement('td'));
|
|
5075
5095
|
const child = field && store.child(field);
|
|
5076
5096
|
if (child) {
|
|
5077
|
-
const el = FormFieldInline(child, fieldRenderer,
|
|
5097
|
+
const el = FormFieldInline(child, fieldRenderer, column, options);
|
|
5078
5098
|
if (el) { td.appendChild(el); }
|
|
5079
5099
|
}
|
|
5080
5100
|
continue;
|
|
@@ -5105,7 +5125,7 @@ function Line(store, fieldRenderer, layout, {
|
|
|
5105
5125
|
const del = handle.appendChild(document.createElement('button'));
|
|
5106
5126
|
del.classList.add('NeeloongForm-table-remove');
|
|
5107
5127
|
del.addEventListener('click', remove);
|
|
5108
|
-
watch(() => !deletable.get()
|
|
5128
|
+
watch(() => !deletable.get(), disabled => {
|
|
5109
5129
|
del.disabled = disabled;
|
|
5110
5130
|
}, true, options.signal);
|
|
5111
5131
|
continue;
|
|
@@ -5122,56 +5142,26 @@ function Line(store, fieldRenderer, layout, {
|
|
|
5122
5142
|
return root;
|
|
5123
5143
|
}
|
|
5124
5144
|
|
|
5125
|
-
/** @import {
|
|
5126
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
5145
|
+
/** @import { ArrayStore } from '../Store/index.mjs' */
|
|
5146
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
5127
5147
|
|
|
5128
|
-
/**
|
|
5129
|
-
*
|
|
5130
|
-
* @param {AbortSignal | null | undefined} signal
|
|
5131
|
-
* @param {HTMLElement} parent
|
|
5132
|
-
* @param {StoreLayout.Column[]} columns
|
|
5133
|
-
* @param {() => any} add
|
|
5134
|
-
* @param {{get(): boolean}} addable
|
|
5135
|
-
* @param {boolean?} [editable]
|
|
5136
|
-
* @returns {void}
|
|
5137
|
-
*/
|
|
5138
|
-
function renderHead(signal, parent, columns, add, addable, editable) {
|
|
5139
|
-
const tr = parent.appendChild(document.createElement('tr'));
|
|
5140
|
-
for (const { action, actions, width, label } of columns) {
|
|
5141
|
-
const th = tr.appendChild(document.createElement('th'));
|
|
5142
|
-
if (width) { th.setAttribute('width', `${width}`); }
|
|
5143
|
-
if (![action, actions].flat().includes('add')) {
|
|
5144
|
-
th.innerText = label || '';
|
|
5145
|
-
continue;
|
|
5146
|
-
}
|
|
5147
|
-
if (!editable) { continue; }
|
|
5148
|
-
const button = th.appendChild(document.createElement('button'));
|
|
5149
|
-
button.addEventListener('click', add);
|
|
5150
|
-
button.classList.add('NeeloongForm-table-add');
|
|
5151
|
-
watch(() => !addable.get(), disabled => { button.disabled = disabled; }, true, signal);
|
|
5152
|
-
}
|
|
5153
|
-
}
|
|
5154
5148
|
/**
|
|
5155
5149
|
*
|
|
5156
5150
|
* @template T
|
|
5157
5151
|
* @param {ArrayStore} store
|
|
5158
|
-
* @param {StoreLayout.
|
|
5159
|
-
* @param {StoreLayout.
|
|
5160
|
-
* @param {StoreLayout.
|
|
5161
|
-
* @returns {
|
|
5152
|
+
* @param {StoreLayout.Field<T>} layout
|
|
5153
|
+
* @param {StoreLayout.Action[]} actionOptions
|
|
5154
|
+
* @param {(fields: { field: string; width: any; label: any; }[]) => StoreLayout.Column<T>[]} createDefault
|
|
5155
|
+
* @returns {StoreLayout.Column<T>[]}
|
|
5162
5156
|
*/
|
|
5163
|
-
function
|
|
5164
|
-
if (options?.signal?.aborted) { return null; }
|
|
5165
|
-
const headerColumns = layout?.columns;
|
|
5157
|
+
function getColumns(store, layout, actionOptions, createDefault) {
|
|
5166
5158
|
const fieldList = Object.entries(store.type || {})
|
|
5167
5159
|
.filter(([k, v]) => typeof v?.type !== 'object')
|
|
5168
5160
|
.map(([field, { width, label }]) => ({ field, width, label }));
|
|
5169
|
-
|
|
5170
|
-
let columns = [];
|
|
5161
|
+
const headerColumns = layout.columns;
|
|
5171
5162
|
if (Array.isArray(headerColumns)) {
|
|
5172
5163
|
const map = new Map(fieldList.map(v => [v.field, v]));
|
|
5173
|
-
|
|
5174
|
-
/** @type {(StoreLayout.Column | null)[]} */
|
|
5164
|
+
/** @type {(StoreLayout.Column<T> | null)[]} */
|
|
5175
5165
|
const allColumns = headerColumns.map(v => {
|
|
5176
5166
|
if (!v) { return null; }
|
|
5177
5167
|
if (typeof v === 'number') { return { placeholder: v }; }
|
|
@@ -5179,7 +5169,7 @@ function Table(store, fieldRenderer, layout, options) {
|
|
|
5179
5169
|
if (typeof v !== 'object') { return null; }
|
|
5180
5170
|
if (Array.isArray(v)) {
|
|
5181
5171
|
/** @type {Set<StoreLayout.Action>} */
|
|
5182
|
-
const options = new Set(
|
|
5172
|
+
const options = new Set(actionOptions);
|
|
5183
5173
|
const actions = v.filter(v => options.delete(v));
|
|
5184
5174
|
if (!actions) { return null; }
|
|
5185
5175
|
return { actions };
|
|
@@ -5191,32 +5181,82 @@ function Table(store, fieldRenderer, layout, options) {
|
|
|
5191
5181
|
return { field, placeholder, width, label: label || define.label };
|
|
5192
5182
|
}
|
|
5193
5183
|
}
|
|
5194
|
-
const options = new Set(
|
|
5184
|
+
const options = new Set(actionOptions);
|
|
5195
5185
|
const allActions = [action, actions].flat().filter(v => v && options.delete(v));
|
|
5196
5186
|
if (allActions.length) {
|
|
5197
5187
|
return { actions: /** @type {StoreLayout.Action[]} */(allActions), width, label };
|
|
5198
5188
|
}
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5189
|
+
if (pattern) {
|
|
5190
|
+
return { pattern, placeholder, width, label };
|
|
5191
|
+
}
|
|
5192
|
+
if (placeholder || width) {
|
|
5193
|
+
return { placeholder, width, label };
|
|
5194
|
+
}
|
|
5202
5195
|
return null;
|
|
5203
5196
|
});
|
|
5204
|
-
columns = /** @type {StoreLayout.Column[]} */(allColumns.filter(Boolean));
|
|
5197
|
+
const columns = /** @type {StoreLayout.Column<T>[]} */(allColumns.filter(Boolean));
|
|
5198
|
+
if (columns.length) { return columns; }
|
|
5199
|
+
}
|
|
5200
|
+
return createDefault(fieldList);
|
|
5201
|
+
}
|
|
5202
|
+
|
|
5203
|
+
/** @import { Store, ArrayStore } from '../Store/index.mjs' */
|
|
5204
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
5205
5205
|
|
|
5206
|
+
/**
|
|
5207
|
+
*
|
|
5208
|
+
* @template T
|
|
5209
|
+
* @param {AbortSignal | null | undefined} signal
|
|
5210
|
+
* @param {HTMLElement} parent
|
|
5211
|
+
* @param {StoreLayout.Column<T>[]} columns
|
|
5212
|
+
* @param {() => any} add
|
|
5213
|
+
* @param {{get(): boolean}} addable
|
|
5214
|
+
* @param {boolean?} [editable]
|
|
5215
|
+
* @returns {void}
|
|
5216
|
+
*/
|
|
5217
|
+
function renderHead(signal, parent, columns, add, addable, editable) {
|
|
5218
|
+
const tr = parent.appendChild(document.createElement('tr'));
|
|
5219
|
+
for (const { action, actions, width, label } of columns) {
|
|
5220
|
+
const th = tr.appendChild(document.createElement('th'));
|
|
5221
|
+
if (width) { th.setAttribute('width', `${width}`); }
|
|
5222
|
+
if (![action, actions].flat().includes('add')) {
|
|
5223
|
+
th.innerText = label || '';
|
|
5224
|
+
continue;
|
|
5225
|
+
}
|
|
5226
|
+
if (!editable) { continue; }
|
|
5227
|
+
const button = th.appendChild(document.createElement('button'));
|
|
5228
|
+
button.addEventListener('click', add);
|
|
5229
|
+
button.classList.add('NeeloongForm-table-add');
|
|
5230
|
+
watch(() => !addable.get(), disabled => { button.disabled = disabled; }, true, signal);
|
|
5206
5231
|
}
|
|
5207
|
-
|
|
5208
|
-
|
|
5232
|
+
}
|
|
5233
|
+
|
|
5234
|
+
/**
|
|
5235
|
+
*
|
|
5236
|
+
* @template T
|
|
5237
|
+
* @param {ArrayStore} store
|
|
5238
|
+
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
5239
|
+
* @param {StoreLayout.Field<T>} layout
|
|
5240
|
+
* @param {StoreLayout.Options?} options
|
|
5241
|
+
* @returns {HTMLTableElement?}
|
|
5242
|
+
*/
|
|
5243
|
+
function Table(store, fieldRenderer, layout, options) {
|
|
5244
|
+
if (options?.signal?.aborted) { return null; }
|
|
5245
|
+
const columns = getColumns(
|
|
5246
|
+
store,
|
|
5247
|
+
layout,
|
|
5248
|
+
['add', 'move', 'trigger', 'remove', 'serial'],
|
|
5249
|
+
fields => [
|
|
5209
5250
|
{ actions: ['add', 'trigger', 'move', 'remove', 'serial'] },
|
|
5210
|
-
...
|
|
5211
|
-
]
|
|
5212
|
-
|
|
5251
|
+
...fields.slice(0, 3),
|
|
5252
|
+
],
|
|
5253
|
+
);
|
|
5213
5254
|
|
|
5214
5255
|
const table = document.createElement('table');
|
|
5215
5256
|
table.classList.add('NeeloongForm-table');
|
|
5216
5257
|
const thead = table.appendChild(document.createElement('thead'));
|
|
5217
5258
|
|
|
5218
|
-
const addable = new Signal.Computed(() => store.addable);
|
|
5219
|
-
const deletable = { get: () => Boolean(options?.editable) };
|
|
5259
|
+
const addable = new Signal.Computed(() => !store.readonly && !store.disabled && store.addable);
|
|
5220
5260
|
function add() {
|
|
5221
5261
|
const data = {};
|
|
5222
5262
|
store.add(data);
|
|
@@ -5254,7 +5294,7 @@ function Table(store, fieldRenderer, layout, options) {
|
|
|
5254
5294
|
|
|
5255
5295
|
}
|
|
5256
5296
|
renderHead(options?.signal, thead, columns, add, addable, Boolean(options?.editable));
|
|
5257
|
-
switch (layout
|
|
5297
|
+
switch (layout.tableFoot) {
|
|
5258
5298
|
default:
|
|
5259
5299
|
case 'header': {
|
|
5260
5300
|
const tfoot = table.appendChild(document.createElement('tfoot'));
|
|
@@ -5288,11 +5328,11 @@ function Table(store, fieldRenderer, layout, options) {
|
|
|
5288
5328
|
const ac = new AbortController();
|
|
5289
5329
|
const el = Line(child, fieldRenderer, layout, {
|
|
5290
5330
|
columns,
|
|
5331
|
+
deletable: new Signal.Computed(() => !store.readonly && !store.disabled && child.removable),
|
|
5291
5332
|
remove: remove.bind(null, child),
|
|
5292
5333
|
dragenter: dragenter.bind(null, child),
|
|
5293
5334
|
dragstart: dragstart.bind(null, child),
|
|
5294
5335
|
dragend,
|
|
5295
|
-
deletable,
|
|
5296
5336
|
}, {
|
|
5297
5337
|
...options,
|
|
5298
5338
|
signal: options?.signal ? AbortSignal.any([options?.signal, ac.signal]) : ac.signal,
|
|
@@ -5318,16 +5358,16 @@ function Table(store, fieldRenderer, layout, options) {
|
|
|
5318
5358
|
return table;
|
|
5319
5359
|
}
|
|
5320
5360
|
|
|
5321
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
5361
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
5322
5362
|
|
|
5323
5363
|
/**
|
|
5324
5364
|
*
|
|
5325
5365
|
* @param {HTMLElement} root
|
|
5326
|
-
* @param {StoreLayout.Grid
|
|
5366
|
+
* @param {StoreLayout.Grid} layout
|
|
5327
5367
|
* @returns {void}
|
|
5328
5368
|
*/
|
|
5329
5369
|
function bindGrid(root, layout) {
|
|
5330
|
-
const { colStart, colSpan, colEnd, rowStart, rowSpan, rowEnd } = layout
|
|
5370
|
+
const { colStart, colSpan, colEnd, rowStart, rowSpan, rowEnd } = layout;
|
|
5331
5371
|
root.classList.add(`NeeloongForm-item-grid`);
|
|
5332
5372
|
if (colStart && colEnd) {
|
|
5333
5373
|
root.style.gridColumn = `${colStart} / ${colEnd}`;
|
|
@@ -5345,7 +5385,7 @@ function bindGrid(root, layout) {
|
|
|
5345
5385
|
}
|
|
5346
5386
|
}
|
|
5347
5387
|
|
|
5348
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
5388
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
5349
5389
|
|
|
5350
5390
|
/**
|
|
5351
5391
|
* @typedef {object} CellValues
|
|
@@ -5383,7 +5423,7 @@ function createStdCell(signal, values) {
|
|
|
5383
5423
|
/**
|
|
5384
5424
|
*
|
|
5385
5425
|
* @param {AbortSignal | null | undefined} signal
|
|
5386
|
-
* @param {StoreLayout.Grid
|
|
5426
|
+
* @param {StoreLayout.Grid} layout
|
|
5387
5427
|
* @param {CellValues} [values]
|
|
5388
5428
|
* @param {StoreLayout.Grid['cell']?} [defCell]
|
|
5389
5429
|
* @param {boolean?} [blockOnly]
|
|
@@ -5429,7 +5469,7 @@ function createCell(signal, layout, values, defCell, blockOnly) {
|
|
|
5429
5469
|
}
|
|
5430
5470
|
return null;
|
|
5431
5471
|
}
|
|
5432
|
-
const [root, content] = create(layout
|
|
5472
|
+
const [root, content] = create(layout.cell) || create(defCell) || createStdCell(signal, values);
|
|
5433
5473
|
root.classList.add('NeeloongForm-item');
|
|
5434
5474
|
effect(() => {
|
|
5435
5475
|
if (values?.error) {
|
|
@@ -5450,7 +5490,7 @@ function createCell(signal, layout, values, defCell, blockOnly) {
|
|
|
5450
5490
|
|
|
5451
5491
|
/** @import { Store } from '../Store/index.mjs' */
|
|
5452
5492
|
/** @import { State } from './Tree.mjs' */
|
|
5453
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
5493
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
5454
5494
|
|
|
5455
5495
|
/**
|
|
5456
5496
|
*
|
|
@@ -5458,10 +5498,11 @@ function createCell(signal, layout, values, defCell, blockOnly) {
|
|
|
5458
5498
|
* @param {Store<any, any>} store
|
|
5459
5499
|
* @param {Signal.State<Store<any, any>?>} currentStore
|
|
5460
5500
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
5461
|
-
* @param {StoreLayout.Field<T
|
|
5501
|
+
* @param {StoreLayout.Field<T>} layout
|
|
5462
5502
|
* @param {Signal.State<State>} state
|
|
5463
5503
|
* @param {object} option
|
|
5464
|
-
* @param {
|
|
5504
|
+
* @param {{get(): boolean}} option.addable
|
|
5505
|
+
* @param {StoreLayout.Column<T>[]} option.columns
|
|
5465
5506
|
* @param {() => void} option.remove
|
|
5466
5507
|
* @param {(el: HTMLElement) => () => void} option.dragenter
|
|
5467
5508
|
* @param {() => void} option.dragstart
|
|
@@ -5475,8 +5516,8 @@ function createCell(signal, layout, values, defCell, blockOnly) {
|
|
|
5475
5516
|
*/
|
|
5476
5517
|
function TreeLine(
|
|
5477
5518
|
store, currentStore, fieldRenderer, layout, state, {
|
|
5478
|
-
columns,
|
|
5479
|
-
remove, dragenter, dragstart, dragend,
|
|
5519
|
+
columns, addable, deletable,
|
|
5520
|
+
remove, dragenter, dragstart, dragend, addNode, drop, createDetails,
|
|
5480
5521
|
}, options) {
|
|
5481
5522
|
const root = document.createElement('div');
|
|
5482
5523
|
root.addEventListener('dragstart', (event) => {
|
|
@@ -5537,9 +5578,9 @@ function TreeLine(
|
|
|
5537
5578
|
}
|
|
5538
5579
|
close = createDetails(store);
|
|
5539
5580
|
}
|
|
5540
|
-
const moveStart = layout
|
|
5541
|
-
const click = moveStart ? null : layout
|
|
5542
|
-
: layout
|
|
5581
|
+
const moveStart = layout.mainMethod === 'move' ? pointerdown : null;
|
|
5582
|
+
const click = moveStart ? null : layout.mainMethod === 'collapse' ? switchCollapsed
|
|
5583
|
+
: layout.mainMethod === 'trigger' ? trigger : open;
|
|
5543
5584
|
|
|
5544
5585
|
const line = root.appendChild(document.createElement('div'));
|
|
5545
5586
|
line.classList.add('NeeloongForm-tree-line');
|
|
@@ -5562,7 +5603,8 @@ function TreeLine(
|
|
|
5562
5603
|
dropFront.addEventListener('dragleave', () => dragleave());
|
|
5563
5604
|
dropChildren.addEventListener('dragleave', () => dragleave());
|
|
5564
5605
|
|
|
5565
|
-
for (const
|
|
5606
|
+
for (const column of columns) {
|
|
5607
|
+
const { actions, pattern, placeholder, width, field } = column;
|
|
5566
5608
|
if (!actions?.length) {
|
|
5567
5609
|
const td = line.appendChild(document.createElement('div'));
|
|
5568
5610
|
td.classList.add('NeeloongForm-tree-cell');
|
|
@@ -5571,7 +5613,7 @@ function TreeLine(
|
|
|
5571
5613
|
if (field) {
|
|
5572
5614
|
const child = store.child(field);
|
|
5573
5615
|
if (!child) { continue; }
|
|
5574
|
-
const el = FormFieldInline(child, fieldRenderer,
|
|
5616
|
+
const el = FormFieldInline(child, fieldRenderer, column, { ...options, editable: false });
|
|
5575
5617
|
if (el) { td.appendChild(el); }
|
|
5576
5618
|
continue;
|
|
5577
5619
|
}
|
|
@@ -5620,7 +5662,7 @@ function TreeLine(
|
|
|
5620
5662
|
const move = line.appendChild(document.createElement('button'));
|
|
5621
5663
|
move.classList.add('NeeloongForm-tree-add');
|
|
5622
5664
|
move.addEventListener('click', addNode);
|
|
5623
|
-
watch(() =>
|
|
5665
|
+
watch(() => !addable.get(), disabled => {
|
|
5624
5666
|
move.disabled = disabled;
|
|
5625
5667
|
}, true, options.signal);
|
|
5626
5668
|
continue;
|
|
@@ -5630,7 +5672,7 @@ function TreeLine(
|
|
|
5630
5672
|
const del = line.appendChild(document.createElement('button'));
|
|
5631
5673
|
del.classList.add('NeeloongForm-tree-remove');
|
|
5632
5674
|
del.addEventListener('click', remove);
|
|
5633
|
-
watch(() => !deletable.get()
|
|
5675
|
+
watch(() => !deletable.get(), disabled => {
|
|
5634
5676
|
del.disabled = disabled;
|
|
5635
5677
|
}, true, options.signal);
|
|
5636
5678
|
continue;
|
|
@@ -5670,7 +5712,7 @@ function TreeLine(
|
|
|
5670
5712
|
}
|
|
5671
5713
|
|
|
5672
5714
|
/** @import { Store, ArrayStore } from '../Store/index.mjs' */
|
|
5673
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
5715
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
5674
5716
|
|
|
5675
5717
|
const verticalWritingMode = new Set([
|
|
5676
5718
|
'vertical-lr', 'vertical-rl', 'sideways-lr', 'sideways-rl',
|
|
@@ -5779,62 +5821,22 @@ function createState(store, states, drag, levelKey, index) {
|
|
|
5779
5821
|
* @template T
|
|
5780
5822
|
* @param {ArrayStore} store
|
|
5781
5823
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
5782
|
-
* @param {StoreLayout.Field<T
|
|
5824
|
+
* @param {StoreLayout.Field<T>} layout
|
|
5783
5825
|
* @param {StoreLayout.Options?} options
|
|
5784
5826
|
* @returns {HTMLElement?}
|
|
5785
5827
|
*/
|
|
5786
5828
|
function Tree(store, fieldRenderer, layout, options) {
|
|
5787
5829
|
if (options?.signal?.aborted) { return null; }
|
|
5788
|
-
const
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
let columns = [];
|
|
5794
|
-
if (Array.isArray(headerColumns)) {
|
|
5795
|
-
const map = new Map(fieldList.map(v => [v.field, v]));
|
|
5796
|
-
/** @type {(StoreLayout.Column | null)[]} */
|
|
5797
|
-
const allColumns = headerColumns.map(v => {
|
|
5798
|
-
if (!v) { return null; }
|
|
5799
|
-
if (typeof v === 'number') { return { placeholder: v }; }
|
|
5800
|
-
if (typeof v === 'string') { return map.get(v) || null; }
|
|
5801
|
-
if (typeof v !== 'object') { return null; }
|
|
5802
|
-
if (Array.isArray(v)) {
|
|
5803
|
-
/** @type {Set<StoreLayout.Action>} */
|
|
5804
|
-
const options = new Set(['add', 'move', 'trigger', 'remove', 'serial', 'open', 'collapse']);
|
|
5805
|
-
const actions = v.filter(v => options.delete(v));
|
|
5806
|
-
if (!actions) { return null; }
|
|
5807
|
-
return { actions };
|
|
5808
|
-
}
|
|
5809
|
-
const { action, actions, field, placeholder, pattern, width, label } = v;
|
|
5810
|
-
if (field) {
|
|
5811
|
-
const define = map.get(field);
|
|
5812
|
-
if (define) {
|
|
5813
|
-
return { field, placeholder, width, label: label || define.label };
|
|
5814
|
-
}
|
|
5815
|
-
}
|
|
5816
|
-
const options = new Set(['add', 'move', 'trigger', 'remove', 'serial', 'open', 'collapse']);
|
|
5817
|
-
const allActions = [action, actions].flat().filter(v => v && options.delete(v));
|
|
5818
|
-
if (allActions.length) {
|
|
5819
|
-
return { actions: /** @type {StoreLayout.Action[]} */(allActions), width, label };
|
|
5820
|
-
}
|
|
5821
|
-
if (pattern) {
|
|
5822
|
-
return { pattern, placeholder, width, label };
|
|
5823
|
-
}
|
|
5824
|
-
if (placeholder || width) {
|
|
5825
|
-
return { placeholder, width, label };
|
|
5826
|
-
}
|
|
5827
|
-
return null;
|
|
5828
|
-
});
|
|
5829
|
-
columns = /** @type {StoreLayout.Column[]} */(allColumns.filter(Boolean));
|
|
5830
|
-
}
|
|
5831
|
-
if (!columns.length) {
|
|
5832
|
-
columns = [
|
|
5830
|
+
const columns = getColumns(
|
|
5831
|
+
store,
|
|
5832
|
+
layout,
|
|
5833
|
+
['add', 'move', 'trigger', 'remove', 'serial', 'open', 'collapse'],
|
|
5834
|
+
fields => [
|
|
5833
5835
|
{ actions: ['collapse', 'move'] },
|
|
5834
|
-
|
|
5836
|
+
fields[0],
|
|
5835
5837
|
{ actions: ['add', 'remove'] },
|
|
5836
|
-
]
|
|
5837
|
-
|
|
5838
|
+
]
|
|
5839
|
+
);
|
|
5838
5840
|
|
|
5839
5841
|
|
|
5840
5842
|
const root = document.createElement('div');
|
|
@@ -5951,9 +5953,8 @@ function Tree(store, fieldRenderer, layout, options) {
|
|
|
5951
5953
|
}
|
|
5952
5954
|
|
|
5953
5955
|
|
|
5954
|
-
const levelKey = layout
|
|
5955
|
-
const addable = new Signal.Computed(() => store.addable);
|
|
5956
|
-
const deletable = { get: () => Boolean(options?.editable) };
|
|
5956
|
+
const levelKey = layout.levelKey || 'level';
|
|
5957
|
+
const addable = new Signal.Computed(() => !store.readonly && !store.disabled && store.addable);
|
|
5957
5958
|
/**
|
|
5958
5959
|
*
|
|
5959
5960
|
* @param {number} parent
|
|
@@ -6126,12 +6127,12 @@ function Tree(store, fieldRenderer, layout, options) {
|
|
|
6126
6127
|
const elState = new Signal.State(state);
|
|
6127
6128
|
const ac = new AbortController();
|
|
6128
6129
|
const el = TreeLine(child, detailsStore, fieldRenderer, layout, elState, {
|
|
6129
|
-
columns,
|
|
6130
|
+
columns, addable,
|
|
6131
|
+
deletable: new Signal.Computed(() => !store.readonly && !store.disabled && child.removable),
|
|
6130
6132
|
remove: remove.bind(null, child),
|
|
6131
6133
|
dragenter,
|
|
6132
6134
|
dragstart: dragstart.bind(null, child),
|
|
6133
6135
|
dragend,
|
|
6134
|
-
deletable,
|
|
6135
6136
|
addNode: () => addNode(Number(child.index)),
|
|
6136
6137
|
createDetails,
|
|
6137
6138
|
drop: drop.bind(null, child),
|
|
@@ -6169,7 +6170,7 @@ function Tree(store, fieldRenderer, layout, options) {
|
|
|
6169
6170
|
* @param {Store<any, any>} store
|
|
6170
6171
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6171
6172
|
* @param {StoreLayout.Options?} options
|
|
6172
|
-
* @param {StoreLayout.Field<T
|
|
6173
|
+
* @param {StoreLayout.Field<T>} layout
|
|
6173
6174
|
* @returns {ParentNode}
|
|
6174
6175
|
*/
|
|
6175
6176
|
function Html(html, store, fieldRenderer, options, layout) {
|
|
@@ -6183,7 +6184,7 @@ function Html(html, store, fieldRenderer, options, layout) {
|
|
|
6183
6184
|
* @param {StoreLayout.Field<T>['arrayStyle']?} arrayStyle
|
|
6184
6185
|
* @param {ArrayStore} store
|
|
6185
6186
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6186
|
-
* @param {StoreLayout.Field<T
|
|
6187
|
+
* @param {StoreLayout.Field<T>} layout
|
|
6187
6188
|
* @param {StoreLayout.Options?} options
|
|
6188
6189
|
* @returns {HTMLElement?}
|
|
6189
6190
|
*/
|
|
@@ -6200,14 +6201,14 @@ function renderArrayCell(arrayStyle, store, fieldRenderer, layout, options) {
|
|
|
6200
6201
|
* @template T
|
|
6201
6202
|
* @param {Store<any, any>} store
|
|
6202
6203
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6203
|
-
* @param {StoreLayout.Field<T
|
|
6204
|
+
* @param {StoreLayout.Field<T>} layout
|
|
6204
6205
|
* @param {StoreLayout.Options?} options
|
|
6205
6206
|
* @returns {ParentNode}
|
|
6206
6207
|
*/
|
|
6207
6208
|
function FormField(store, fieldRenderer, layout, options) {
|
|
6208
6209
|
const { type } = store;
|
|
6209
6210
|
const isObject = Boolean(type && typeof type === 'object');
|
|
6210
|
-
const html = layout
|
|
6211
|
+
const html = layout.html;
|
|
6211
6212
|
/** @type {StoreLayout.Grid['cell']} */
|
|
6212
6213
|
const cellType = isObject
|
|
6213
6214
|
? store instanceof ArrayStore ? 'collapse' : 'fieldset'
|
|
@@ -6218,8 +6219,8 @@ function FormField(store, fieldRenderer, layout, options) {
|
|
|
6218
6219
|
/** @type {false | ParentNode | null} */
|
|
6219
6220
|
const r =
|
|
6220
6221
|
html && Html(html, store, fieldRenderer, options, layout)
|
|
6221
|
-
|| fieldRenderer(store, layout
|
|
6222
|
-
|| store instanceof ArrayStore && renderArrayCell(layout
|
|
6222
|
+
|| fieldRenderer(store, layout.renderer, options)
|
|
6223
|
+
|| store instanceof ArrayStore && renderArrayCell(layout.arrayStyle, store, fieldRenderer, layout, options)
|
|
6223
6224
|
|| isObject && Form(store, fieldRenderer, layout, options);
|
|
6224
6225
|
if (r) {
|
|
6225
6226
|
content.appendChild(r);
|
|
@@ -6228,7 +6229,7 @@ function FormField(store, fieldRenderer, layout, options) {
|
|
|
6228
6229
|
}
|
|
6229
6230
|
|
|
6230
6231
|
/** @import { Store } from '../Store/index.mjs' */
|
|
6231
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
6232
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
6232
6233
|
|
|
6233
6234
|
/**
|
|
6234
6235
|
*
|
|
@@ -6265,7 +6266,7 @@ function FormButton(store, layout, options) {
|
|
|
6265
6266
|
}
|
|
6266
6267
|
|
|
6267
6268
|
/** @import { Store } from '../Store/index.mjs' */
|
|
6268
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
6269
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
6269
6270
|
|
|
6270
6271
|
/**
|
|
6271
6272
|
*
|
|
@@ -6287,7 +6288,7 @@ function FormHtml(store, fieldRenderer, layout, options) {
|
|
|
6287
6288
|
}
|
|
6288
6289
|
|
|
6289
6290
|
/** @import { Store } from '../Store/index.mjs' */
|
|
6290
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
6291
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
6291
6292
|
|
|
6292
6293
|
/**
|
|
6293
6294
|
*
|
|
@@ -6305,7 +6306,9 @@ function FormItem(store, fieldRenderer, item, options) {
|
|
|
6305
6306
|
if (item.type === 'html') {
|
|
6306
6307
|
return FormHtml(store, fieldRenderer, item, options);
|
|
6307
6308
|
}
|
|
6308
|
-
const
|
|
6309
|
+
const field = item.field;
|
|
6310
|
+
if (!field) { return null; }
|
|
6311
|
+
const fieldStore = store.child(field);
|
|
6309
6312
|
if (fieldStore) {
|
|
6310
6313
|
return FormField(fieldStore, fieldRenderer, item, options);
|
|
6311
6314
|
}
|
|
@@ -6317,7 +6320,7 @@ function FormItem(store, fieldRenderer, item, options) {
|
|
|
6317
6320
|
* @template T
|
|
6318
6321
|
* @param {Store<any, any>} store
|
|
6319
6322
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6320
|
-
* @param {StoreLayout<T
|
|
6323
|
+
* @param {StoreLayout<T>} layout
|
|
6321
6324
|
* @param {StoreLayout.Options?} options
|
|
6322
6325
|
* @param {HTMLElement} [parent]
|
|
6323
6326
|
* @returns {HTMLElement?}
|
|
@@ -6326,8 +6329,8 @@ function Form(store, fieldRenderer, layout, options, parent) {
|
|
|
6326
6329
|
if (options?.signal?.aborted) { return null; }
|
|
6327
6330
|
const root = parent instanceof HTMLElement ? parent : document.createElement('div');
|
|
6328
6331
|
root.classList.add('NeeloongForm');
|
|
6329
|
-
const fieldLayouts = layout
|
|
6330
|
-
if (fieldLayouts) {
|
|
6332
|
+
const fieldLayouts = layout.fields || store.layout.fields;
|
|
6333
|
+
if (fieldLayouts?.length) {
|
|
6331
6334
|
for (const fieldTemplate of fieldLayouts) {
|
|
6332
6335
|
const el = FormItem(store, fieldRenderer, fieldTemplate, options);
|
|
6333
6336
|
if (el) { root.appendChild(el); }
|
|
@@ -6335,7 +6338,7 @@ function Form(store, fieldRenderer, layout, options, parent) {
|
|
|
6335
6338
|
} else {
|
|
6336
6339
|
const fields = [...store].map(([, v]) => v);
|
|
6337
6340
|
for (const field of fields) {
|
|
6338
|
-
const el = FormField(field, fieldRenderer,
|
|
6341
|
+
const el = FormField(field, fieldRenderer, field.layout, options);
|
|
6339
6342
|
if (el) { root.appendChild(el); }
|
|
6340
6343
|
}
|
|
6341
6344
|
}
|
|
@@ -6344,7 +6347,7 @@ function Form(store, fieldRenderer, layout, options, parent) {
|
|
|
6344
6347
|
}
|
|
6345
6348
|
|
|
6346
6349
|
/** @import { Store } from '../Store/index.mjs' */
|
|
6347
|
-
/** @import { StoreLayout } from '../types.mjs' */
|
|
6350
|
+
/** @import { StoreLayout } from '../StoreLayout.types.mjs' */
|
|
6348
6351
|
|
|
6349
6352
|
/**
|
|
6350
6353
|
*
|
|
@@ -6352,19 +6355,20 @@ function Form(store, fieldRenderer, layout, options, parent) {
|
|
|
6352
6355
|
* @param {Store} store
|
|
6353
6356
|
* @param {StoreLayout.Renderer<T>} fieldRenderer
|
|
6354
6357
|
* @param {HTMLElement} root
|
|
6355
|
-
* @param {StoreLayout<T
|
|
6358
|
+
* @param {StoreLayout<T>} layout
|
|
6356
6359
|
* @param {StoreLayout.Options & {clone?: boolean} | null} [options]
|
|
6357
6360
|
* @returns {void}
|
|
6358
6361
|
*/
|
|
6359
6362
|
function renderStore(store, fieldRenderer, root, layout, options) {
|
|
6360
6363
|
if (options?.signal?.aborted) { return; }
|
|
6361
|
-
const
|
|
6364
|
+
const storeLayout = layout || store.layout;
|
|
6365
|
+
const html = storeLayout.html;
|
|
6362
6366
|
if (!html) {
|
|
6363
|
-
Form(store, fieldRenderer,
|
|
6367
|
+
Form(store, fieldRenderer, storeLayout, options || null, root);
|
|
6364
6368
|
return;
|
|
6365
6369
|
}
|
|
6366
6370
|
const content = getHtmlContent(html);
|
|
6367
|
-
renderHtml(store, fieldRenderer, content, options || null,
|
|
6371
|
+
renderHtml(store, fieldRenderer, content, options || null, storeLayout);
|
|
6368
6372
|
root.appendChild(content);
|
|
6369
6373
|
options?.signal?.addEventListener('abort', () => {
|
|
6370
6374
|
root.removeChild(content);
|