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.
Files changed (97) hide show
  1. package/.cabloy-version +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/package.json +2 -2
  4. package/repo-docs/frontend/component-guide.md +33 -0
  5. package/repo-docs/frontend/model-resource-cookbook.md +0 -8
  6. package/repo-docs/frontend/model-resource-usage-guide.md +0 -4
  7. package/repo-e2e/specs/cabloy-basic.spec.ts +158 -0
  8. package/repo-e2e/specs/controller-boundary.spec.ts +261 -0
  9. package/test-results/.last-run.json +1 -1
  10. package/vona/packages-utils/lint/package.json +1 -1
  11. package/vona/packages-utils/lint/src/oxc/lint.ts +1 -1
  12. package/vona/packages-utils/lint/src/oxc/lintVue.ts +1 -1
  13. package/vona/pnpm-lock.yaml +238 -46
  14. package/vona/pnpm-workspace.yaml +1 -1
  15. package/zova/package.original.json +1 -1
  16. package/zova/packages-cli/cli/package.json +2 -2
  17. package/zova/packages-cli/cli-set-front/package.json +3 -3
  18. package/zova/packages-utils/babel-plugin-zova-behavior/package.json +2 -1
  19. package/zova/packages-utils/babel-plugin-zova-behavior/src/index.ts +21 -8
  20. package/zova/packages-utils/babel-plugin-zova-behavior/test/behaviorSlots.test.ts +111 -0
  21. package/zova/packages-utils/zova-jsx/package.json +2 -2
  22. package/zova/packages-utils/zova-vite/package.json +2 -2
  23. package/zova/packages-zova/zova/package.json +3 -3
  24. package/zova/packages-zova/zova-core/package.json +1 -1
  25. package/zova/packages-zova/zova-core/src/bean/beanBase.ts +1 -1
  26. package/zova/packages-zova/zova-core/src/bean/beanContainer.ts +95 -39
  27. package/zova/packages-zova/zova-core/src/bean/resource/error/type.ts +9 -0
  28. package/zova/packages-zova/zova-core/src/bean/type.ts +18 -0
  29. package/zova/packages-zova/zova-core/src/components/component.ts +2 -1
  30. package/zova/packages-zova/zova-core/src/composables/useController.ts +155 -25
  31. package/zova/packages-zova/zova-core/src/core/component/error.ts +62 -5
  32. package/zova/packages-zova/zova-core/src/core/context/component.ts +37 -2
  33. package/zova/packages-zova/zova-core/src/core/context/hooks.ts +13 -2
  34. package/zova/packages-zova/zova-core/src/core/context/meta.ts +1 -0
  35. package/zova/packages-zova/zova-core/src/core/context/state.ts +161 -0
  36. package/zova/packages-zova/zova-core/src/core/sys/config.ts +32 -7
  37. package/zova/packages-zova/zova-core/src/types/interface/monkey.ts +15 -0
  38. package/zova/packages-zova/zova-core/src/types/utils/powerPartial.ts +1 -1
  39. package/zova/pnpm-lock.yaml +40 -25
  40. package/zova/src/front/config/config/config.ts +11 -0
  41. package/zova/src/front/config/config/render.tsx +79 -0
  42. package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +0 -1
  43. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/component/controllerBoundaryProbe.ts +31 -0
  44. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/component/controllerBoundaryProbeInline.ts +34 -0
  45. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/component/controllerBoundaryProbeOverride.ts +34 -0
  46. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/index.ts +58 -1
  47. package/zova/src/suite/a-demo/modules/demo-basic/src/.metadata/page/controllerBoundary.ts +23 -0
  48. package/zova/src/suite/a-demo/modules/demo-basic/src/component/controllerBoundaryProbe/controller.tsx +36 -0
  49. package/zova/src/suite/a-demo/modules/demo-basic/src/component/controllerBoundaryProbeInline/controller.tsx +34 -0
  50. package/zova/src/suite/a-demo/modules/demo-basic/src/component/controllerBoundaryProbeOverride/controller.tsx +46 -0
  51. package/zova/src/suite/a-demo/modules/demo-basic/src/page/controllerBoundary/controller.tsx +185 -0
  52. package/zova/src/suite/a-demo/modules/demo-basic/src/routes.ts +6 -0
  53. package/zova/src/suite/a-home/modules/home-base/src/config/locale/en-us.ts +1 -0
  54. package/zova/src/suite/a-home/modules/home-base/src/config/locale/zh-cn.ts +1 -0
  55. package/zova/src/suite/a-training/modules/training-student/src/model/student.ts +0 -3
  56. package/zova/src/suite/cabloy-basic/modules/basic-button/package.json +58 -0
  57. package/zova/src/suite/cabloy-basic/modules/basic-button/src/.metadata/component/button.ts +31 -0
  58. package/zova/src/suite/cabloy-basic/modules/basic-button/src/.metadata/index.ts +122 -0
  59. package/zova/src/suite/cabloy-basic/modules/basic-button/src/.metadata/this.ts +2 -0
  60. package/zova/src/suite/cabloy-basic/modules/basic-button/src/bean/behavior.perform.tsx +103 -0
  61. package/zova/src/suite/cabloy-basic/modules/basic-button/src/component/button/controller.tsx +39 -0
  62. package/zova/src/suite/cabloy-basic/modules/basic-button/src/index.ts +1 -0
  63. package/zova/src/suite/cabloy-basic/modules/basic-button/tsconfig.build.json +13 -0
  64. package/zova/src/suite/cabloy-basic/modules/basic-button/tsconfig.json +5 -0
  65. package/zova/src/suite/cabloy-basic/modules/basic-details/package.json +2 -1
  66. package/zova/src/suite/cabloy-basic/modules/basic-details/src/bean/tableCell.actionDelete.tsx +4 -4
  67. package/zova/src/suite/cabloy-basic/modules/basic-page/src/component/blockPage/controller.tsx +5 -1
  68. package/zova/src/suite/cabloy-basic/modules/basic-pageentry/src/component/blockPageEntry/controller.tsx +5 -1
  69. package/zova/src/suite/cabloy-basic/modules/basic-table/package.json +2 -1
  70. package/zova/src/suite/cabloy-basic/modules/basic-table/src/bean/tableCell.actionDelete.tsx +4 -4
  71. package/zova/src/suite/cabloy-basic/modules/basic-table/src/component/actionRefresh/controller.tsx +10 -8
  72. package/zova/src/suite/cabloy-basic/package.json +1 -0
  73. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/package.json +1 -1
  74. package/zova/src/suite-vendor/a-cabloy/modules/a-layoutprofile/src/model/layoutprofile.ts +0 -3
  75. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
  76. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/.metadata/page/resource.ts +6 -1
  77. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +0 -1
  78. package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/page/resource/controller.tsx +5 -1
  79. package/zova/src/suite-vendor/a-cabloy/package.json +3 -3
  80. package/zova/src/suite-vendor/a-zova/modules/a-bean/cli/controller/metadata/generateFilePage.ts +3 -1
  81. package/zova/src/suite-vendor/a-zova/modules/a-bean/package.json +1 -1
  82. package/zova/src/suite-vendor/a-zova/modules/a-model/package.json +1 -1
  83. package/zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.useMutation.ts +1 -11
  84. package/zova/src/suite-vendor/a-zova/modules/a-model/src/bean/bean.model/bean.model.useQuery.ts +1 -17
  85. package/zova/src/suite-vendor/a-zova/modules/a-model/src/lib/utils.ts +2 -1
  86. package/zova/src/suite-vendor/a-zova/modules/a-model/src/types/query.ts +2 -7
  87. package/zova/src/suite-vendor/a-zova/modules/a-model/test/lib/mutation.types.ts +14 -0
  88. package/zova/src/suite-vendor/a-zova/modules/a-model/test/lib/queryEnsureLoaded.test.ts +56 -0
  89. package/zova/src/suite-vendor/a-zova/modules/a-router/package.json +1 -1
  90. package/zova/src/suite-vendor/a-zova/modules/a-router/src/monkey.ts +8 -0
  91. package/zova/src/suite-vendor/a-zova/modules/a-ssr/package.json +1 -1
  92. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/lib/ssr.ts +85 -1
  93. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/monkey.ts +25 -1
  94. package/zova/src/suite-vendor/a-zova/modules/a-ssr/src/types/ssr.ts +15 -1
  95. package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
  96. package/zova/src/suite-vendor/a-zova/package.json +6 -6
  97. /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
  ];
@@ -1,6 +1,7 @@
1
1
  export default {
2
2
  Home: 'Home',
3
3
  GoHome: 'Go Home',
4
+ Retry: 'Retry',
4
5
  LanguageEnglish: 'English',
5
6
  LanguageChinese: 'Chinese',
6
7
  VonaIntegratedSsr: 'Vona integrated SSR',
@@ -1,6 +1,7 @@
1
1
  export default {
2
2
  Home: '主页',
3
3
  GoHome: '返回首页',
4
+ Retry: '重试',
4
5
  LanguageEnglish: '英语',
5
6
  LanguageChinese: '简体中文',
6
7
  VonaIntegratedSsr: 'Vona 集成式 SSR',
@@ -24,9 +24,6 @@ export class ModelStudent extends BeanModelBase {
24
24
  const res = await this.scope.api.trainingStudent.summary({ params: { id } });
25
25
  return res ?? null;
26
26
  },
27
- meta: {
28
- disableErrorEffect: true,
29
- },
30
27
  });
31
28
  }
32
29
 
@@ -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,2 @@
1
+ export const __ThisModule__ = 'basic-button';
2
+ export { ScopeModuleBasicButton as ScopeModule } from './index.js';
@@ -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
+ }