cabloy 5.1.172 → 5.1.174
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 +12 -0
- package/package.json +2 -2
- package/repo-docs/frontend/component-guide.md +33 -0
- package/repo-docs/frontend/model-resource-cookbook.md +0 -8
- package/repo-docs/frontend/model-resource-usage-guide.md +0 -4
- package/repo-e2e/specs/cabloy-basic.spec.ts +158 -0
- package/repo-e2e/specs/controller-boundary.spec.ts +261 -0
- package/test-results/.last-run.json +1 -1
- package/vona/packages-utils/lint/package.json +1 -1
- package/vona/packages-utils/lint/src/oxc/lint.ts +1 -1
- package/vona/packages-utils/lint/src/oxc/lintVue.ts +1 -1
- package/vona/pnpm-lock.yaml +238 -46
- package/vona/pnpm-workspace.yaml +1 -1
- package/zova/package.original.json +1 -1
- package/zova/packages-cli/cli/package.json +2 -2
- package/zova/packages-cli/cli-set-front/package.json +3 -3
- package/zova/packages-utils/babel-plugin-zova-behavior/package.json +2 -1
- package/zova/packages-utils/babel-plugin-zova-behavior/src/index.ts +21 -8
- package/zova/packages-utils/babel-plugin-zova-behavior/test/behaviorSlots.test.ts +111 -0
- package/zova/packages-utils/zova-jsx/package.json +2 -2
- package/zova/packages-utils/zova-vite/package.json +2 -2
- package/zova/packages-zova/zova/package.json +3 -3
- package/zova/packages-zova/zova-core/package.json +1 -1
- package/zova/packages-zova/zova-core/src/bean/beanBase.ts +1 -1
- package/zova/packages-zova/zova-core/src/bean/beanContainer.ts +95 -39
- package/zova/packages-zova/zova-core/src/bean/resource/error/type.ts +9 -0
- package/zova/packages-zova/zova-core/src/bean/type.ts +18 -0
- package/zova/packages-zova/zova-core/src/components/component.ts +2 -1
- package/zova/packages-zova/zova-core/src/composables/useController.ts +155 -25
- package/zova/packages-zova/zova-core/src/core/component/error.ts +62 -5
- package/zova/packages-zova/zova-core/src/core/context/component.ts +37 -2
- package/zova/packages-zova/zova-core/src/core/context/hooks.ts +13 -2
- package/zova/packages-zova/zova-core/src/core/context/meta.ts +1 -0
- package/zova/packages-zova/zova-core/src/core/context/state.ts +161 -0
- package/zova/packages-zova/zova-core/src/core/sys/config.ts +32 -7
- package/zova/packages-zova/zova-core/src/types/interface/monkey.ts +15 -0
- package/zova/packages-zova/zova-core/src/types/utils/powerPartial.ts +1 -1
- package/zova/pnpm-lock.yaml +40 -25
- package/zova/src/front/config/config/config.ts +11 -0
- package/zova/src/front/config/config/render.tsx +79 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +0 -1
- package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/component/controllerBoundaryProbe.ts +31 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/component/controllerBoundaryProbeInline.ts +34 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/component/controllerBoundaryProbeOverride.ts +34 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/index.ts +58 -1
- package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/page/controllerBoundary.ts +23 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/component/controllerBoundaryProbe/controller.tsx +36 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/component/controllerBoundaryProbeInline/controller.tsx +34 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/component/controllerBoundaryProbeOverride/controller.tsx +46 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/page/controllerBoundary/controller.tsx +185 -0
- package/zova/src/suite/a-demo/modules/demo-basic/src/routes.ts +6 -0
- package/zova/src/suite/a-home/modules/home-base/src/config/locale/en-us.ts +1 -0
- package/zova/src/suite/a-home/modules/home-base/src/config/locale/zh-cn.ts +1 -0
- package/zova/src/suite/a-training/modules/training-student/src/model/student.ts +0 -3
- package/zova/src/suite/cabloy-basic/modules/basic-button/package.json +58 -0
- package/zova/src/suite/cabloy-basic/modules/basic-button/src/.metadata/component/button.ts +31 -0
- package/zova/src/suite/cabloy-basic/modules/basic-button/src/.metadata/index.ts +122 -0
- package/zova/src/suite/cabloy-basic/modules/basic-button/src/.metadata/this.ts +2 -0
- package/zova/src/suite/cabloy-basic/modules/basic-button/src/bean/behavior.perform.tsx +103 -0
- package/zova/src/suite/cabloy-basic/modules/basic-button/src/component/button/controller.tsx +39 -0
- package/zova/src/suite/cabloy-basic/modules/basic-button/src/index.ts +1 -0
- package/zova/src/suite/cabloy-basic/modules/basic-button/tsconfig.build.json +13 -0
- package/zova/src/suite/cabloy-basic/modules/basic-button/tsconfig.json +5 -0
- package/zova/src/suite/cabloy-basic/modules/basic-details/package.json +2 -1
- package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionDelete.tsx +4 -4
- package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockPage/controller.tsx +5 -1
- package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockPageEntry/controller.tsx +5 -1
- package/zova/src/suite/cabloy-basic/modules/basic-table/package.json +2 -1
- package/zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionDelete.tsx +4 -4
- package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/actionRefresh/controller.tsx +10 -8
- package/zova/src/suite/cabloy-basic/package.json +1 -0
- package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/package.json +1 -1
- package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/model/layoutprofile.ts +0 -3
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/.metadata/page/resource.ts +6 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +0 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/resource/controller.tsx +5 -1
- package/zova/src/suite-vendor/a-cabloy/package.json +3 -3
- package/zova/src/suite-vendor/a-zova/modules/a-bean/cli/controller/metadata/generateFilePage.ts +3 -1
- package/zova/src/suite-vendor/a-zova/modules/a-bean/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-model/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.useMutation.ts +1 -11
- package/zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.useQuery.ts +1 -17
- package/zova/src/suite-vendor/a-zova/modules/a-model/src/lib/utils.ts +2 -1
- package/zova/src/suite-vendor/a-zova/modules/a-model/src/types/query.ts +2 -7
- package/zova/src/suite-vendor/a-zova/modules/a-model/test/lib/mutation.types.ts +14 -0
- package/zova/src/suite-vendor/a-zova/modules/a-model/test/lib/queryEnsureLoaded.test.ts +56 -0
- package/zova/src/suite-vendor/a-zova/modules/a-router/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-router/src/monkey.ts +8 -0
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +85 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/monkey.ts +25 -1
- package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/types/ssr.ts +15 -1
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +6 -6
- /package/vona/patches/{zova-core@5.1.89.patch → zova-core@5.1.90.patch} +0 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BeanControllerBase, IComponentOptions } from 'zova';
|
|
2
|
+
import { Controller } from 'zova-module-a-bean';
|
|
3
|
+
|
|
4
|
+
export interface ControllerControllerBoundaryProbeProps {
|
|
5
|
+
mode: 'success' | 'failure' | 'serverFailure';
|
|
6
|
+
delayMs?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@Controller()
|
|
10
|
+
export class ControllerControllerBoundaryProbe extends BeanControllerBase {
|
|
11
|
+
static $propsDefault = {
|
|
12
|
+
delayMs: 800,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
static $componentOptions: IComponentOptions = {
|
|
16
|
+
boundary: { loading: { delay: 500 }, retry: true },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
ready = false;
|
|
20
|
+
|
|
21
|
+
protected async __init__() {
|
|
22
|
+
await new Promise(resolve => setTimeout(resolve, this.$props.delayMs));
|
|
23
|
+
if (
|
|
24
|
+
this.$props.mode === 'failure' ||
|
|
25
|
+
(this.$props.mode === 'serverFailure' && process.env.SERVER)
|
|
26
|
+
) {
|
|
27
|
+
throw new Error('Controller boundary probe initialization failed');
|
|
28
|
+
}
|
|
29
|
+
this.ready = true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
protected render() {
|
|
33
|
+
if (!this.ready) return null;
|
|
34
|
+
return <div>Controller boundary probe ready</div>;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { BeanControllerBase, IComponentOptions } from 'zova';
|
|
2
|
+
import { Controller } from 'zova-module-a-bean';
|
|
3
|
+
|
|
4
|
+
export interface ControllerControllerBoundaryProbeInlineProps {
|
|
5
|
+
mode: 'success' | 'failure' | 'serverFailure';
|
|
6
|
+
delayMs?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@Controller()
|
|
10
|
+
export class ControllerControllerBoundaryProbeInline extends BeanControllerBase {
|
|
11
|
+
static $propsDefault = {
|
|
12
|
+
delayMs: 800,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
static $componentOptions: IComponentOptions = {
|
|
16
|
+
boundary: { loading: { delay: 500 }, renderMode: 'inline', retry: true },
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
ready = false;
|
|
20
|
+
|
|
21
|
+
protected async __init__() {
|
|
22
|
+
const props = this.$props as ControllerControllerBoundaryProbeInlineProps;
|
|
23
|
+
await new Promise(resolve => setTimeout(resolve, props.delayMs));
|
|
24
|
+
if (props.mode === 'failure' || (props.mode === 'serverFailure' && process.env.SERVER)) {
|
|
25
|
+
throw new Error('Inline Controller boundary probe initialization failed');
|
|
26
|
+
}
|
|
27
|
+
this.ready = true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
protected render() {
|
|
31
|
+
if (!this.ready) return null;
|
|
32
|
+
return <span>Inline Controller boundary probe ready</span>;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { VNodeChild } from 'vue';
|
|
2
|
+
import type { TypeComponentBoundaryRenderMode } from 'zova';
|
|
3
|
+
|
|
4
|
+
import { BeanControllerBase, IComponentOptions } from 'zova';
|
|
5
|
+
import { Controller } from 'zova-module-a-bean';
|
|
6
|
+
|
|
7
|
+
export interface ControllerControllerBoundaryProbeOverrideProps {
|
|
8
|
+
mode: 'success' | 'failure';
|
|
9
|
+
delayMs?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Controller()
|
|
13
|
+
export class ControllerControllerBoundaryProbeOverride extends BeanControllerBase {
|
|
14
|
+
static $propsDefault = {
|
|
15
|
+
delayMs: 800,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
static $componentOptions: IComponentOptions = {
|
|
19
|
+
boundary: { loading: { delay: 500 }, renderMode: 'inline' },
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
ready = false;
|
|
23
|
+
|
|
24
|
+
protected async __init__() {
|
|
25
|
+
const props = this.$props as ControllerControllerBoundaryProbeOverrideProps;
|
|
26
|
+
await new Promise(resolve => setTimeout(resolve, props.delayMs));
|
|
27
|
+
if (props.mode === 'failure') {
|
|
28
|
+
throw new Error('Override Controller boundary probe initialization failed');
|
|
29
|
+
}
|
|
30
|
+
this.ready = true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
protected renderLoading(renderMode: TypeComponentBoundaryRenderMode): VNodeChild {
|
|
34
|
+
return <span role="status">Override loading mode: {renderMode}</span>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected renderError(error: unknown): VNodeChild {
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
+
return <span role="alert">Override legacy error: {message}</span>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
protected render() {
|
|
43
|
+
if (!this.ready) return null;
|
|
44
|
+
return <span>Override Controller boundary probe ready</span>;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BeanControllerPageBase } from 'zova';
|
|
3
|
+
import { Controller } from 'zova-module-a-bean';
|
|
4
|
+
import { ZPage } from 'zova-module-home-base';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
ZControllerBoundaryProbe,
|
|
8
|
+
ZControllerBoundaryProbeInline,
|
|
9
|
+
ZControllerBoundaryProbeOverride,
|
|
10
|
+
} from '../../.metadata/index.jsx';
|
|
11
|
+
|
|
12
|
+
export const ControllerPageControllerBoundarySchemaParams = z.object({});
|
|
13
|
+
|
|
14
|
+
export const ControllerPageControllerBoundarySchemaQuery = z.object({
|
|
15
|
+
mode: z.enum(['serverFailure', 'inlineServerFailure']).optional(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
type ProbeMode = 'success' | 'failure' | 'serverFailure';
|
|
19
|
+
type InlineProbeMode = 'success' | 'failure' | 'serverFailure';
|
|
20
|
+
|
|
21
|
+
@Controller()
|
|
22
|
+
export class ControllerPageControllerBoundary extends BeanControllerPageBase {
|
|
23
|
+
probe?: { mode: ProbeMode; delayMs: number };
|
|
24
|
+
inlineProbe?: { mode: InlineProbeMode; delayMs: number };
|
|
25
|
+
overrideProbe?: { mode: 'success' | 'failure'; delayMs: number };
|
|
26
|
+
probeKey = 0;
|
|
27
|
+
inlineProbeKey = 0;
|
|
28
|
+
overrideProbeKey = 0;
|
|
29
|
+
|
|
30
|
+
protected async __init__() {
|
|
31
|
+
if (this.$query.mode === 'serverFailure') {
|
|
32
|
+
this.probe = { mode: 'serverFailure', delayMs: 0 };
|
|
33
|
+
} else if (this.$query.mode === 'inlineServerFailure') {
|
|
34
|
+
this.inlineProbe = { mode: 'serverFailure', delayMs: 0 };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
mountFastSuccess() {
|
|
39
|
+
this._mountProbe('success', 300);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
mountFastFailure() {
|
|
43
|
+
this._mountProbe('failure', 300);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
mountDelayedSuccess() {
|
|
47
|
+
this._mountProbe('success', 800);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
mountFailingProbe() {
|
|
51
|
+
this._mountProbe('failure', 800);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
prepareProbeRetrySuccess() {
|
|
55
|
+
if (!this.probe) return;
|
|
56
|
+
this.probe = { mode: 'success', delayMs: 800 };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
clearProbe() {
|
|
60
|
+
this.probe = undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
mountInlineFailingProbe() {
|
|
64
|
+
this._mountInlineProbe('failure', 800);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
prepareInlineRetrySuccess() {
|
|
68
|
+
if (!this.inlineProbe) return;
|
|
69
|
+
this.inlineProbe = { mode: 'success', delayMs: 800 };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
clearInlineProbe() {
|
|
73
|
+
this.inlineProbe = undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
mountOverrideFailingProbe() {
|
|
77
|
+
this.overrideProbe = { mode: 'failure', delayMs: 800 };
|
|
78
|
+
this.overrideProbeKey++;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
recoverOverrideWithDelayedSuccess() {
|
|
82
|
+
this.overrideProbe = { mode: 'success', delayMs: 800 };
|
|
83
|
+
this.overrideProbeKey++;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
clearOverrideProbe() {
|
|
87
|
+
this.overrideProbe = undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private _mountProbe(mode: ProbeMode, delayMs: number) {
|
|
91
|
+
this.probe = { mode, delayMs };
|
|
92
|
+
this.probeKey++;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private _mountInlineProbe(mode: InlineProbeMode, delayMs: number) {
|
|
96
|
+
this.inlineProbe = { mode, delayMs };
|
|
97
|
+
this.inlineProbeKey++;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
protected render() {
|
|
101
|
+
return (
|
|
102
|
+
<ZPage>
|
|
103
|
+
<h1>Controller Boundary Manual Validation</h1>
|
|
104
|
+
<p>
|
|
105
|
+
Mount a fresh child Controller to exercise the global loading and error boundary
|
|
106
|
+
renderers.
|
|
107
|
+
</p>
|
|
108
|
+
<div class="flex flex-wrap gap-2">
|
|
109
|
+
<button class="btn btn-primary" onClick={() => this.mountFastSuccess()}>
|
|
110
|
+
Mount fast success probe
|
|
111
|
+
</button>
|
|
112
|
+
<button class="btn btn-error" onClick={() => this.mountFastFailure()}>
|
|
113
|
+
Mount fast failing probe
|
|
114
|
+
</button>
|
|
115
|
+
<button class="btn btn-primary" onClick={() => this.mountDelayedSuccess()}>
|
|
116
|
+
Mount delayed success probe
|
|
117
|
+
</button>
|
|
118
|
+
<button class="btn btn-error" onClick={() => this.mountFailingProbe()}>
|
|
119
|
+
Mount failing probe
|
|
120
|
+
</button>
|
|
121
|
+
<button class="btn btn-secondary" onClick={() => this.prepareProbeRetrySuccess()}>
|
|
122
|
+
Prepare probe retry success
|
|
123
|
+
</button>
|
|
124
|
+
<button class="btn" onClick={() => this.clearProbe()}>
|
|
125
|
+
Clear probe
|
|
126
|
+
</button>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="mt-4">
|
|
129
|
+
{this.probe && (
|
|
130
|
+
<ZControllerBoundaryProbe
|
|
131
|
+
key={this.probeKey}
|
|
132
|
+
mode={this.probe.mode}
|
|
133
|
+
delayMs={this.probe.delayMs}
|
|
134
|
+
/>
|
|
135
|
+
)}
|
|
136
|
+
</div>
|
|
137
|
+
<div class="mt-4">
|
|
138
|
+
<button class="btn btn-error" onClick={() => this.mountInlineFailingProbe()}>
|
|
139
|
+
Mount inline failing probe
|
|
140
|
+
</button>
|
|
141
|
+
<button class="btn btn-secondary ml-2" onClick={() => this.prepareInlineRetrySuccess()}>
|
|
142
|
+
Prepare inline retry success
|
|
143
|
+
</button>
|
|
144
|
+
<button class="btn ml-2" onClick={() => this.clearInlineProbe()}>
|
|
145
|
+
Clear inline probe
|
|
146
|
+
</button>
|
|
147
|
+
<p class="mt-2">
|
|
148
|
+
Inline boundary:{' '}
|
|
149
|
+
{this.inlineProbe && (
|
|
150
|
+
<ZControllerBoundaryProbeInline
|
|
151
|
+
key={this.inlineProbeKey}
|
|
152
|
+
mode={this.inlineProbe.mode}
|
|
153
|
+
delayMs={this.inlineProbe.delayMs}
|
|
154
|
+
/>
|
|
155
|
+
)}
|
|
156
|
+
</p>
|
|
157
|
+
</div>
|
|
158
|
+
<div class="mt-4">
|
|
159
|
+
<button class="btn btn-error" onClick={() => this.mountOverrideFailingProbe()}>
|
|
160
|
+
Mount override failing probe
|
|
161
|
+
</button>
|
|
162
|
+
<button
|
|
163
|
+
class="btn btn-secondary ml-2"
|
|
164
|
+
onClick={() => this.recoverOverrideWithDelayedSuccess()}
|
|
165
|
+
>
|
|
166
|
+
Recover override with delayed success
|
|
167
|
+
</button>
|
|
168
|
+
<button class="btn ml-2" onClick={() => this.clearOverrideProbe()}>
|
|
169
|
+
Clear override probe
|
|
170
|
+
</button>
|
|
171
|
+
<p class="mt-2">
|
|
172
|
+
Override boundary:{' '}
|
|
173
|
+
{this.overrideProbe && (
|
|
174
|
+
<ZControllerBoundaryProbeOverride
|
|
175
|
+
key={this.overrideProbeKey}
|
|
176
|
+
mode={this.overrideProbe.mode}
|
|
177
|
+
delayMs={this.overrideProbe.delayMs}
|
|
178
|
+
/>
|
|
179
|
+
)}
|
|
180
|
+
</p>
|
|
181
|
+
</div>
|
|
182
|
+
</ZPage>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { IModuleRoute } from 'zova-module-a-router';
|
|
2
2
|
|
|
3
3
|
import { ZPageComponent } from './.metadata/page/component.js';
|
|
4
|
+
import { ZPageControllerBoundary } from './.metadata/page/controllerBoundary.js';
|
|
4
5
|
import { ZPageLocale } from './.metadata/page/locale.js';
|
|
5
6
|
import { ZPageRoutedDialog } from './.metadata/page/routedDialog.js';
|
|
6
7
|
import { ZPageRoutedDialogDetail } from './.metadata/page/routedDialogDetail.js';
|
|
@@ -89,4 +90,9 @@ export const routes: IModuleRoute[] = [
|
|
|
89
90
|
component: ZPageRoutedDialogDetail,
|
|
90
91
|
meta: { requiresAuth: false },
|
|
91
92
|
},
|
|
93
|
+
{
|
|
94
|
+
path: 'controllerBoundary',
|
|
95
|
+
component: ZPageControllerBoundary,
|
|
96
|
+
meta: { requiresAuth: false, ssrProfile: 'public' },
|
|
97
|
+
},
|
|
92
98
|
];
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zova-module-basic-button",
|
|
3
|
+
"version": "5.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"Zova Module"
|
|
7
|
+
],
|
|
8
|
+
"author": "",
|
|
9
|
+
"files": [
|
|
10
|
+
"mock",
|
|
11
|
+
"dist",
|
|
12
|
+
"src",
|
|
13
|
+
"icons",
|
|
14
|
+
"assets"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": [
|
|
20
|
+
"./src/index.ts",
|
|
21
|
+
"./dist/index.d.ts"
|
|
22
|
+
],
|
|
23
|
+
"import": "./src/index.ts",
|
|
24
|
+
"default": "./dist/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./*": "./*"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"clean": "rimraf dist tsconfig.build.tsbuildinfo",
|
|
30
|
+
"tsc:publish": "npm run clean && node ../../../../../packages-cli/cli/src/bin/zova.ts :bin:buildModule --sourcemap && tsc -p tsconfig.build.json",
|
|
31
|
+
"prepublishOnly": "npm run tsc:publish",
|
|
32
|
+
"prepack": "clean-package",
|
|
33
|
+
"postpack": "clean-package restore"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"clean-package": "^2.2.0",
|
|
38
|
+
"rimraf": "^6.1.3"
|
|
39
|
+
},
|
|
40
|
+
"clean-package": {
|
|
41
|
+
"indent": 2,
|
|
42
|
+
"replace": {
|
|
43
|
+
"exports.\\..types": "./dist/index.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"remove": [
|
|
46
|
+
"clean-package",
|
|
47
|
+
"devDependencies",
|
|
48
|
+
"exports.\\..import"
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"title": "basic-button",
|
|
52
|
+
"zovaModule": {
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"basic-app": "5.0.0",
|
|
55
|
+
"basic-commands": "5.0.0"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TypeControllerInnerProps } from 'zova';
|
|
2
|
+
|
|
3
|
+
import { defineComponent } from 'vue';
|
|
4
|
+
import { prepareComponentOptions, useController } from 'zova';
|
|
5
|
+
|
|
6
|
+
import type { ControllerButtonProps } from '../../component/button/controller.jsx';
|
|
7
|
+
|
|
8
|
+
import { ControllerButton } from '../../component/button/controller.jsx';
|
|
9
|
+
export type ZButtonProps = {
|
|
10
|
+
controllerRef?: (ref: ControllerButton) => void;
|
|
11
|
+
} & ControllerButtonProps;
|
|
12
|
+
|
|
13
|
+
type ControllerInnerProps = TypeControllerInnerProps<
|
|
14
|
+
ControllerButtonProps,
|
|
15
|
+
keyof typeof ControllerButton.$propsDefault
|
|
16
|
+
>;
|
|
17
|
+
declare module 'zova-module-basic-button' {
|
|
18
|
+
export interface ControllerButton {
|
|
19
|
+
$props: ControllerInnerProps;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const ZButton = defineComponent((_props: ZButtonProps) => {
|
|
24
|
+
useController(ControllerButton, undefined, undefined);
|
|
25
|
+
return () => {};
|
|
26
|
+
}, prepareComponentOptions(ControllerButton.$componentOptions));
|
|
27
|
+
declare module 'zova-module-a-bean' {
|
|
28
|
+
export interface IVonaComponentRecord {
|
|
29
|
+
'basic-button:button': ControllerButtonProps;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// eslint-disable
|
|
2
|
+
/** controller: begin */
|
|
3
|
+
export * from '../component/button/controller.jsx';
|
|
4
|
+
|
|
5
|
+
import 'zova';
|
|
6
|
+
declare module 'zova' {
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
}
|
|
10
|
+
declare module 'zova-module-basic-button' {
|
|
11
|
+
|
|
12
|
+
export interface ControllerButton {
|
|
13
|
+
/** @internal */
|
|
14
|
+
get scope(): ScopeModuleBasicButton;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** controller: end */
|
|
18
|
+
/** controller: begin */
|
|
19
|
+
import type { ControllerButton } from '../component/button/controller.jsx';
|
|
20
|
+
import 'zova';
|
|
21
|
+
declare module 'zova' {
|
|
22
|
+
export interface IBeanRecordLocal {
|
|
23
|
+
'basic-button.controller.button': ControllerButton;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** controller: end */
|
|
27
|
+
|
|
28
|
+
/** components: begin */
|
|
29
|
+
export * from './component/button.js';
|
|
30
|
+
import { ZButton } from './component/button.js';
|
|
31
|
+
export const components = {
|
|
32
|
+
'button': ZButton,
|
|
33
|
+
};
|
|
34
|
+
import 'zova';
|
|
35
|
+
declare module 'zova' {
|
|
36
|
+
export interface IComponentRecord {
|
|
37
|
+
'basic-button:button': ControllerButton;
|
|
38
|
+
}
|
|
39
|
+
export interface IZovaComponentRecord {
|
|
40
|
+
'basic-button:button': typeof ZButton;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** components: end */
|
|
44
|
+
/** behavior: begin */
|
|
45
|
+
export * from '../bean/behavior.perform.jsx';
|
|
46
|
+
import { IBehaviorOptionsPerform } from '../bean/behavior.perform.jsx';
|
|
47
|
+
import 'zova-module-a-behavior';
|
|
48
|
+
declare module 'zova-module-a-behavior' {
|
|
49
|
+
|
|
50
|
+
export interface IBehaviorRecord {
|
|
51
|
+
'basic-button:perform': IBehaviorOptionsPerform;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
declare module 'zova-module-basic-button' {
|
|
57
|
+
|
|
58
|
+
export interface BehaviorPerform {
|
|
59
|
+
/** @internal */
|
|
60
|
+
get scope(): ScopeModuleBasicButton;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface BehaviorPerform {
|
|
64
|
+
get $beanFullName(): 'basic-button.behavior.perform';
|
|
65
|
+
get $onionName(): 'basic-button:perform';
|
|
66
|
+
get $onionOptions(): IBehaviorOptionsPerform;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** behavior: end */
|
|
70
|
+
/** behavior: begin */
|
|
71
|
+
import type { BehaviorPerform } from '../bean/behavior.perform.jsx';
|
|
72
|
+
import 'zova';
|
|
73
|
+
declare module 'zova' {
|
|
74
|
+
export interface IBeanRecordLocal {
|
|
75
|
+
'basic-button.behavior.perform': BehaviorPerform;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** behavior: end */
|
|
79
|
+
/** behaviors: begin */
|
|
80
|
+
import 'vue';
|
|
81
|
+
import 'vue/jsx-runtime';
|
|
82
|
+
|
|
83
|
+
declare module 'vue' {
|
|
84
|
+
export interface InputHTMLAttributes {
|
|
85
|
+
'bs-basic-button-perform'?: IBehaviorOptionsPerform | '' | boolean;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
declare module 'vue/jsx-runtime' {
|
|
90
|
+
namespace JSX {
|
|
91
|
+
// need define class/style in IntrinsicAttributes
|
|
92
|
+
export interface IntrinsicAttributes {
|
|
93
|
+
'bs-basic-button-perform'?: IBehaviorOptionsPerform | '' | boolean;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** behaviors: end */
|
|
98
|
+
/** scope: begin */
|
|
99
|
+
import { BeanScopeBase, type BeanScopeUtil } from 'zova';
|
|
100
|
+
import { Scope } from 'zova-module-a-bean';
|
|
101
|
+
|
|
102
|
+
@Scope()
|
|
103
|
+
export class ScopeModuleBasicButton extends BeanScopeBase {}
|
|
104
|
+
|
|
105
|
+
export interface ScopeModuleBasicButton {
|
|
106
|
+
util: BeanScopeUtil;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
import 'zova';
|
|
110
|
+
declare module 'zova' {
|
|
111
|
+
export interface IBeanScopeRecord {
|
|
112
|
+
'basic-button': ScopeModuleBasicButton;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** scope: end */
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { VNode } from 'vue';
|
|
2
|
+
import type { IDecoratorBehaviorOptions, NextBehavior } from 'zova-module-a-behavior';
|
|
3
|
+
|
|
4
|
+
import { isNavigationFailure } from '@cabloy/vue-router';
|
|
5
|
+
import { createVNode } from 'vue';
|
|
6
|
+
import { BeanBehaviorBase, Behavior } from 'zova-module-a-behavior';
|
|
7
|
+
|
|
8
|
+
export interface IBehaviorPropsInputPerform {
|
|
9
|
+
'class'?: unknown;
|
|
10
|
+
'disabled'?: boolean | '' | 'true' | 'false';
|
|
11
|
+
'onClick'?: (e: MouseEvent) => unknown;
|
|
12
|
+
['aria-busy']?: boolean | 'true' | 'false';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface IBehaviorPropsOutputPerform extends IBehaviorPropsInputPerform {
|
|
16
|
+
'disabled'?: boolean;
|
|
17
|
+
'onClick'?: (e: MouseEvent) => unknown;
|
|
18
|
+
['aria-busy']?: boolean | 'true' | 'false';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type TypeBehaviorOnError = (
|
|
22
|
+
error: unknown,
|
|
23
|
+
e: MouseEvent,
|
|
24
|
+
) => boolean | void | Promise<boolean | void>;
|
|
25
|
+
|
|
26
|
+
export interface IBehaviorOptionsPerform extends IDecoratorBehaviorOptions {
|
|
27
|
+
isLoading?: boolean;
|
|
28
|
+
onPerform?: (e: MouseEvent) => Promise<void> | void;
|
|
29
|
+
onError?: TypeBehaviorOnError;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Behavior<IBehaviorOptionsPerform>()
|
|
33
|
+
export class BehaviorPerform extends BeanBehaviorBase<
|
|
34
|
+
IBehaviorOptionsPerform,
|
|
35
|
+
IBehaviorPropsInputPerform,
|
|
36
|
+
IBehaviorPropsOutputPerform
|
|
37
|
+
> {
|
|
38
|
+
private _isLoading = false;
|
|
39
|
+
|
|
40
|
+
protected render(
|
|
41
|
+
props: IBehaviorPropsInputPerform,
|
|
42
|
+
next: NextBehavior<IBehaviorPropsOutputPerform>,
|
|
43
|
+
): VNode {
|
|
44
|
+
const isLoading = this._isLoading || this.$options.isLoading === true;
|
|
45
|
+
const propsPatch: IBehaviorPropsOutputPerform = {
|
|
46
|
+
...props,
|
|
47
|
+
'class': isLoading ? [props.class, 'btn-disabled'] : props.class,
|
|
48
|
+
'disabled':
|
|
49
|
+
props.disabled === true || props.disabled === '' || props.disabled === 'true' || isLoading,
|
|
50
|
+
'aria-busy': isLoading || props['aria-busy'],
|
|
51
|
+
'onClick': e => this._handleClick(e, props.onClick),
|
|
52
|
+
};
|
|
53
|
+
const vnode = next(propsPatch);
|
|
54
|
+
if (!isLoading) return vnode;
|
|
55
|
+
const children = vnode.children;
|
|
56
|
+
return createVNode(vnode.type as any, vnode.props as any, [
|
|
57
|
+
createVNode('span', {
|
|
58
|
+
'class': 'loading loading-spinner loading-xs',
|
|
59
|
+
'aria-hidden': 'true',
|
|
60
|
+
}),
|
|
61
|
+
...(Array.isArray(children)
|
|
62
|
+
? children
|
|
63
|
+
: children === undefined || children === null
|
|
64
|
+
? []
|
|
65
|
+
: [children]),
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private _handleClick(e: MouseEvent, onClick?: (e: MouseEvent) => unknown) {
|
|
70
|
+
if (this._isLoading || this.$options.isLoading === true) return;
|
|
71
|
+
return this._perform(e, onClick);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private async _perform(e: MouseEvent, onClick?: (e: MouseEvent) => unknown) {
|
|
75
|
+
try {
|
|
76
|
+
this._isLoading = true;
|
|
77
|
+
await onClick?.(e);
|
|
78
|
+
await this.$options.onPerform?.(e);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
if (isActionControlFlowError(error)) throw error;
|
|
81
|
+
const handled = await this.$options.onError?.(error, e);
|
|
82
|
+
if (handled === true) return;
|
|
83
|
+
await this.$performCommand('basic-commands:alert', {
|
|
84
|
+
type: 'error',
|
|
85
|
+
text: getActionErrorMessage(error),
|
|
86
|
+
});
|
|
87
|
+
} finally {
|
|
88
|
+
this._isLoading = false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function isActionControlFlowError(error: unknown) {
|
|
94
|
+
return isNavigationFailure(error) || [301, 302, 401, 600].includes(Number((error as any)?.code));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function getActionErrorMessage(error: unknown) {
|
|
98
|
+
if (error && (typeof error === 'object' || typeof error === 'function')) {
|
|
99
|
+
const message = (error as { message?: unknown }).message;
|
|
100
|
+
if (message !== undefined && message !== null) return String(message);
|
|
101
|
+
}
|
|
102
|
+
return String(error);
|
|
103
|
+
}
|