cabloy 5.1.209 → 5.1.210
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/.cabloy-version +1 -1
- package/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/zova/packages-zova/zova/package.json +2 -2
- package/zova/src/suite/cabloy-basic/modules/basic-input/src/component/formFieldInput/controller.tsx +2 -1
- package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/controller.tsx +4 -5
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/formField.ts +2 -0
- package/zova/src/suite-vendor/a-zova/modules/a-form/test/lib/schemaRefreshLifecycle.test.ts +130 -26
- package/zova/src/suite-vendor/a-zova/package.json +2 -2
package/.cabloy-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.1.
|
|
1
|
+
5.1.210
|
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zova",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.169",
|
|
4
4
|
"gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
|
|
5
5
|
"description": "A vue3 framework with ioc",
|
|
6
6
|
"keywords": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"zova-core": "^5.1.92",
|
|
49
|
-
"zova-suite-a-zova": "^5.1.
|
|
49
|
+
"zova-suite-a-zova": "^5.1.168"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"clean-package": "^2.2.0",
|
package/zova/src/suite/cabloy-basic/modules/basic-input/src/component/formFieldInput/controller.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import type { IResourceFormFieldOptionsBase } from 'zova-module-a-openapi';
|
|
|
5
5
|
import { classes } from 'typestyle';
|
|
6
6
|
import { BeanControllerBase } from 'zova';
|
|
7
7
|
import { Controller } from 'zova-module-a-bean';
|
|
8
|
-
import { ZFormField } from 'zova-module-a-form';
|
|
8
|
+
import { constFieldBindingSlot, ZFormField } from 'zova-module-a-form';
|
|
9
9
|
|
|
10
10
|
declare module 'zova-module-a-openapi' {
|
|
11
11
|
export interface IResourceFormFieldRecord {
|
|
@@ -37,6 +37,7 @@ export class ControllerFormFieldInput extends BeanControllerBase {
|
|
|
37
37
|
return (
|
|
38
38
|
<ZFormField
|
|
39
39
|
{...this.$props}
|
|
40
|
+
{...{ [constFieldBindingSlot]: true }}
|
|
40
41
|
slotDefault={({ propsBucket, props }, $$formField) => {
|
|
41
42
|
const className = !propsBucket.needHandleBorder
|
|
42
43
|
? props.class
|
|
@@ -12,6 +12,7 @@ import type { ControllerForm } from '../form/controller.jsx';
|
|
|
12
12
|
import { schemaRefreshFingerprint } from '../../lib/schemaRefresh.js';
|
|
13
13
|
import { TypeFormField } from '../../types/form.js';
|
|
14
14
|
import {
|
|
15
|
+
constFieldBindingSlot,
|
|
15
16
|
constFieldProps,
|
|
16
17
|
IFormFieldComponentOptions,
|
|
17
18
|
IFormFieldOptions,
|
|
@@ -105,6 +106,7 @@ export class ControllerFormField<TParentData extends {} = {}> extends BeanContro
|
|
|
105
106
|
props.behaviors,
|
|
106
107
|
!!props.onEffect,
|
|
107
108
|
!!props.slotDefault,
|
|
109
|
+
props[constFieldBindingSlot] === true,
|
|
108
110
|
]);
|
|
109
111
|
}
|
|
110
112
|
|
|
@@ -118,12 +120,9 @@ export class ControllerFormField<TParentData extends {} = {}> extends BeanContro
|
|
|
118
120
|
return;
|
|
119
121
|
}
|
|
120
122
|
const props = this.$props;
|
|
121
|
-
//
|
|
123
|
+
// Only explicitly renderer-owned binding slots qualify; custom slots remain opaque.
|
|
122
124
|
const inputBindingSlot =
|
|
123
|
-
props[constFieldProps] === true &&
|
|
124
|
-
(props.render
|
|
125
|
-
? this.$$form.getRenderProvider(props.render)
|
|
126
|
-
: this.formProvider.components?.Input) === 'basic-input:formFieldInput';
|
|
125
|
+
props[constFieldProps] === true && props[constFieldBindingSlot] === true;
|
|
127
126
|
const eligible =
|
|
128
127
|
!props.sys &&
|
|
129
128
|
!props.behaviors &&
|
|
@@ -28,6 +28,8 @@ export type HTMLInputElementType =
|
|
|
28
28
|
| 'tel'
|
|
29
29
|
| 'email';
|
|
30
30
|
export const constFieldProps = '$$FieldProps';
|
|
31
|
+
// Internal: the renderer supplies its own form-value binding slot.
|
|
32
|
+
export const constFieldBindingSlot = '$$FieldBindingSlot';
|
|
31
33
|
|
|
32
34
|
export interface IFormFieldScope<TParentData extends {} = {}> {
|
|
33
35
|
name: string;
|
|
@@ -22,7 +22,12 @@ function deferred<T = void>() {
|
|
|
22
22
|
|
|
23
23
|
// Like basic-pageentry's draftModel harness, execute the current source rather than a
|
|
24
24
|
// copied refresh algorithm. TSX requires transpileModule instead of native stripping.
|
|
25
|
-
function evaluateClass(
|
|
25
|
+
function evaluateClass(
|
|
26
|
+
path: string,
|
|
27
|
+
name: string,
|
|
28
|
+
bindings: Record<string, unknown>,
|
|
29
|
+
jsx = ts.JsxEmit.Preserve,
|
|
30
|
+
) {
|
|
26
31
|
const source = readFileSync(new URL(path, import.meta.url), 'utf8')
|
|
27
32
|
.replace(/^import[\s\S]*?;\n/gm, '')
|
|
28
33
|
.replace(/^\s*@(Controller|UseScope|Use)\([^\n]*\)\s*\n/gm, '');
|
|
@@ -32,7 +37,8 @@ function evaluateClass(path: string, name: string, bindings: Record<string, unkn
|
|
|
32
37
|
compilerOptions: {
|
|
33
38
|
target: ts.ScriptTarget.ES2022,
|
|
34
39
|
module: ts.ModuleKind.ESNext,
|
|
35
|
-
jsx
|
|
40
|
+
jsx,
|
|
41
|
+
jsxFactory: 'createElement',
|
|
36
42
|
},
|
|
37
43
|
});
|
|
38
44
|
assert.deepEqual(
|
|
@@ -85,7 +91,14 @@ class ControllerBase {
|
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
|
|
88
|
-
const
|
|
94
|
+
const fieldTypes = ts.transpileModule(
|
|
95
|
+
readFileSync(new URL('../../src/types/formField.ts', import.meta.url), 'utf8'),
|
|
96
|
+
{ compilerOptions: { module: ts.ModuleKind.CommonJS } },
|
|
97
|
+
).outputText;
|
|
98
|
+
const { constFieldProps, constFieldBindingSlot } = new Function(
|
|
99
|
+
'exports',
|
|
100
|
+
`${fieldTypes}\nreturn exports;`,
|
|
101
|
+
)({});
|
|
89
102
|
const commonBindings = {
|
|
90
103
|
markRaw: (value: unknown) => value,
|
|
91
104
|
useSelector: (store: any, selector: (state: any) => any) => ({
|
|
@@ -95,8 +108,32 @@ const commonBindings = {
|
|
|
95
108
|
isNil: (value: unknown) => value === undefined || value === null,
|
|
96
109
|
schemaRefreshFingerprint,
|
|
97
110
|
constFieldProps,
|
|
111
|
+
constFieldBindingSlot,
|
|
98
112
|
};
|
|
99
113
|
|
|
114
|
+
const ZFormField = {};
|
|
115
|
+
const ControllerFormFieldInput = evaluateClass(
|
|
116
|
+
'../../../../../../suite/cabloy-basic/modules/basic-input/src/component/formFieldInput/controller.tsx',
|
|
117
|
+
'ControllerFormFieldInput',
|
|
118
|
+
{
|
|
119
|
+
BeanControllerBase: ControllerBase,
|
|
120
|
+
constFieldBindingSlot,
|
|
121
|
+
ZFormField,
|
|
122
|
+
classes: (...values: unknown[]) => values.filter(Boolean).join(' '),
|
|
123
|
+
createElement: (type: unknown, props: any) => ({ type, props }),
|
|
124
|
+
},
|
|
125
|
+
ts.JsxEmit.React,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
function inputBindingProps(props: any = {}) {
|
|
129
|
+
const input = new ControllerFormFieldInput();
|
|
130
|
+
input.$props = props;
|
|
131
|
+
const rendered = input.render();
|
|
132
|
+
assert.equal(rendered.type, ZFormField);
|
|
133
|
+
assert.equal(rendered.props[constFieldBindingSlot], true);
|
|
134
|
+
return rendered.props;
|
|
135
|
+
}
|
|
136
|
+
|
|
100
137
|
const ControllerForm = evaluateClass('../../src/component/form/controller.tsx', 'ControllerForm', {
|
|
101
138
|
...commonBindings,
|
|
102
139
|
BeanControllerFormBase: ControllerBase,
|
|
@@ -732,6 +769,7 @@ test(
|
|
|
732
769
|
const before: unknown[] = [];
|
|
733
770
|
const after: unknown[] = [];
|
|
734
771
|
const owner = await initializedField(runtime, {
|
|
772
|
+
[constFieldBindingSlot]: true,
|
|
735
773
|
slotDefault: () => 'initial slot',
|
|
736
774
|
onFieldStateReady: (field: any) => before.push(field.form.getFieldValue(field.name)),
|
|
737
775
|
});
|
|
@@ -755,31 +793,30 @@ test(
|
|
|
755
793
|
);
|
|
756
794
|
|
|
757
795
|
test(
|
|
758
|
-
'
|
|
796
|
+
'explicit renderer-owned binding slots preserve live names independently of component selectors',
|
|
759
797
|
{ concurrency: false },
|
|
760
798
|
async () => {
|
|
761
|
-
for (const
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
runtime
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
render
|
|
773
|
-
|
|
799
|
+
for (const selector of ['basic-input:formFieldInput', 'start-input:formFieldInput']) {
|
|
800
|
+
for (const render of [
|
|
801
|
+
undefined,
|
|
802
|
+
'Input',
|
|
803
|
+
selector,
|
|
804
|
+
{ $$typeof: 'zova-jsx:component', type: selector },
|
|
805
|
+
]) {
|
|
806
|
+
await withRuntime({}, async runtime => {
|
|
807
|
+
runtime.form.$$scopeOpenapi.config.formProvider = {
|
|
808
|
+
components: { Input: selector },
|
|
809
|
+
};
|
|
810
|
+
const owner = await initializedField(runtime, inputBindingProps({ render }));
|
|
811
|
+
dirty(runtime, 'typed name');
|
|
812
|
+
runtime.select('zh-cn');
|
|
813
|
+
owner.refresh();
|
|
814
|
+
assert.deepEqual(lifecycle(runtime.events), ['update', 'reset', 'validate', 'ready']);
|
|
815
|
+
assert.equal(lastEvent(runtime.events).value, 'typed name');
|
|
816
|
+
assertResetMeta(lastEvent(runtime.events).meta);
|
|
817
|
+
assert.deepEqual(runtime.changed, []);
|
|
774
818
|
});
|
|
775
|
-
|
|
776
|
-
runtime.select('zh-cn');
|
|
777
|
-
owner.refresh();
|
|
778
|
-
assert.deepEqual(lifecycle(runtime.events), ['update', 'reset', 'validate', 'ready']);
|
|
779
|
-
assert.equal(lastEvent(runtime.events).value, 'typed name');
|
|
780
|
-
assertResetMeta(lastEvent(runtime.events).meta);
|
|
781
|
-
assert.deepEqual(runtime.changed, []);
|
|
782
|
-
});
|
|
819
|
+
}
|
|
783
820
|
}
|
|
784
821
|
},
|
|
785
822
|
);
|
|
@@ -789,9 +826,13 @@ test(
|
|
|
789
826
|
{ concurrency: false },
|
|
790
827
|
async () => {
|
|
791
828
|
for (const props of [
|
|
792
|
-
{ [constFieldProps]: false, render: 'basic-input:formFieldInput' },
|
|
829
|
+
inputBindingProps({ [constFieldProps]: false, render: 'basic-input:formFieldInput' }),
|
|
830
|
+
{ render: 'basic-input:formFieldInput' },
|
|
793
831
|
{ render: 'custom:formFieldInput' },
|
|
794
832
|
{ render: 'Input' },
|
|
833
|
+
{},
|
|
834
|
+
{ [constFieldBindingSlot]: false },
|
|
835
|
+
{ [constFieldBindingSlot]: 'true' },
|
|
795
836
|
]) {
|
|
796
837
|
await withRuntime({}, async runtime => {
|
|
797
838
|
runtime.form.$$scopeOpenapi.config.formProvider = {
|
|
@@ -812,6 +853,69 @@ test(
|
|
|
812
853
|
},
|
|
813
854
|
);
|
|
814
855
|
|
|
856
|
+
test('the input wrapper owns its marker and value/blur binding slot', () => {
|
|
857
|
+
const externalSlot = () => 'external slot';
|
|
858
|
+
const props = inputBindingProps({
|
|
859
|
+
name: 'name',
|
|
860
|
+
[constFieldBindingSlot]: false,
|
|
861
|
+
slotDefault: externalSlot,
|
|
862
|
+
});
|
|
863
|
+
assert.equal(props.name, 'name');
|
|
864
|
+
assert.notEqual(props.slotDefault, externalSlot);
|
|
865
|
+
const writes: unknown[] = [];
|
|
866
|
+
let blurred = false;
|
|
867
|
+
const input = props.slotDefault(
|
|
868
|
+
{ propsBucket: { value: 'current', disableNotifyChanged: true }, props: {} },
|
|
869
|
+
{
|
|
870
|
+
setValue: (...args: unknown[]) => writes.push(args),
|
|
871
|
+
handleBlur: () => {
|
|
872
|
+
blurred = true;
|
|
873
|
+
},
|
|
874
|
+
},
|
|
875
|
+
);
|
|
876
|
+
assert.equal(input.type, 'input');
|
|
877
|
+
assert.equal(input.props.value, 'current');
|
|
878
|
+
input.props.onInput({ target: { value: 'edited' } });
|
|
879
|
+
input.props.onBlur();
|
|
880
|
+
assert.deepEqual(writes, [['edited', true]]);
|
|
881
|
+
assert.equal(blurred, true);
|
|
882
|
+
});
|
|
883
|
+
|
|
884
|
+
test(
|
|
885
|
+
'a missing Input provider does not authorize an unmarked slot',
|
|
886
|
+
{ concurrency: false },
|
|
887
|
+
async () => {
|
|
888
|
+
await withRuntime({}, async runtime => {
|
|
889
|
+
const owner = await initializedField(runtime, { slotDefault: () => 'custom slot' });
|
|
890
|
+
dirty(runtime, 'typed name');
|
|
891
|
+
runtime.select('zh-cn');
|
|
892
|
+
owner.refresh();
|
|
893
|
+
assert.deepEqual(lifecycle(runtime.events), ['update', 'reset', 'ready']);
|
|
894
|
+
assert.equal(lastEvent(runtime.events).value, 'baseline');
|
|
895
|
+
});
|
|
896
|
+
},
|
|
897
|
+
);
|
|
898
|
+
|
|
899
|
+
test(
|
|
900
|
+
'binding-slot ownership changes invalidate the prior refresh configuration',
|
|
901
|
+
{ concurrency: false },
|
|
902
|
+
async () => {
|
|
903
|
+
for (const initiallyOwned of [false, true]) {
|
|
904
|
+
await withRuntime({}, async runtime => {
|
|
905
|
+
const owner = await initializedField(runtime, {
|
|
906
|
+
[constFieldBindingSlot]: initiallyOwned,
|
|
907
|
+
slotDefault: () => 'slot',
|
|
908
|
+
});
|
|
909
|
+
dirty(runtime, 'typed name');
|
|
910
|
+
owner.field.$props[constFieldBindingSlot] = !initiallyOwned;
|
|
911
|
+
owner.refresh();
|
|
912
|
+
assert.deepEqual(lifecycle(runtime.events), ['update', 'reset', 'ready']);
|
|
913
|
+
assert.equal(lastEvent(runtime.events).value, 'baseline');
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
},
|
|
917
|
+
);
|
|
918
|
+
|
|
815
919
|
test(
|
|
816
920
|
'disposal during awaited behavior initialization suppresses refresh and ready callbacks',
|
|
817
921
|
{ concurrency: false },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zova-suite-a-zova",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.168",
|
|
4
4
|
"gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
|
|
5
5
|
"description": "zova",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"zova-module-a-behaviors": "^5.1.22",
|
|
16
16
|
"zova-module-a-command": "^5.1.35",
|
|
17
17
|
"zova-module-a-fetch": "^5.1.25",
|
|
18
|
-
"zova-module-a-form": "^5.1.
|
|
18
|
+
"zova-module-a-form": "^5.1.53",
|
|
19
19
|
"zova-module-a-icon": "^5.1.27",
|
|
20
20
|
"zova-module-a-interceptor": "^5.1.31",
|
|
21
21
|
"zova-module-a-logger": "^5.1.28",
|