zova-core 5.0.110 → 5.0.113

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 (133) hide show
  1. package/dist/bean/beanBaseSimple.d.ts.map +1 -1
  2. package/dist/bean/beanBaseSimple.js +10 -2
  3. package/dist/bean/beanBaseSimple.js.map +1 -1
  4. package/dist/core/resource.d.ts +6 -6
  5. package/dist/core/resource.d.ts.map +1 -1
  6. package/dist/core/resource.js +2 -6
  7. package/dist/core/resource.js.map +1 -1
  8. package/dist/decorator/class/use.js +8 -5
  9. package/dist/decorator/class/use.js.map +1 -1
  10. package/package.json +4 -3
  11. package/src/bean/beanBase.ts +53 -0
  12. package/src/bean/beanBaseSimple.ts +38 -0
  13. package/src/bean/beanContainer.ts +963 -0
  14. package/src/bean/beanControllerBase.ts +58 -0
  15. package/src/bean/beanControllerLike.ts +29 -0
  16. package/src/bean/beanControllerPageBase.ts +18 -0
  17. package/src/bean/beanRenderBase.ts +7 -0
  18. package/src/bean/beanRenderLike.ts +33 -0
  19. package/src/bean/beanSimple.ts +11 -0
  20. package/src/bean/beanStyleBase.ts +3 -0
  21. package/src/bean/index.ts +13 -0
  22. package/src/bean/resource/component/index.ts +1 -0
  23. package/src/bean/resource/component/type.ts +5 -0
  24. package/src/bean/resource/config/index.ts +1 -0
  25. package/src/bean/resource/config/type.ts +32 -0
  26. package/src/bean/resource/constant/index.ts +1 -0
  27. package/src/bean/resource/constant/type.ts +1 -0
  28. package/src/bean/resource/error/beanScopeError.ts +21 -0
  29. package/src/bean/resource/error/errorClass.ts +57 -0
  30. package/src/bean/resource/error/errorGlobal.ts +7 -0
  31. package/src/bean/resource/error/errorInternal.ts +66 -0
  32. package/src/bean/resource/error/errorObject.ts +4 -0
  33. package/src/bean/resource/error/index.ts +6 -0
  34. package/src/bean/resource/error/type.ts +10 -0
  35. package/src/bean/resource/icon/icon.ts +161 -0
  36. package/src/bean/resource/icon/iconGroup.ts +10 -0
  37. package/src/bean/resource/icon/index.ts +4 -0
  38. package/src/bean/resource/icon/types.ts +21 -0
  39. package/src/bean/resource/icon/useZovaIcon.ts +20 -0
  40. package/src/bean/resource/icon/utils.ts +20 -0
  41. package/src/bean/resource/icon/zovaIcon.ts +52 -0
  42. package/src/bean/resource/index.ts +8 -0
  43. package/src/bean/resource/locale/beanScopeLocale.ts +22 -0
  44. package/src/bean/resource/locale/index.ts +2 -0
  45. package/src/bean/resource/locale/type.ts +21 -0
  46. package/src/bean/resource/page/index.ts +1 -0
  47. package/src/bean/resource/page/type.ts +12 -0
  48. package/src/bean/resource/service/beanScopeService.ts +24 -0
  49. package/src/bean/resource/service/index.ts +2 -0
  50. package/src/bean/resource/service/type.ts +8 -0
  51. package/src/bean/scope/beanScopeBase.ts +74 -0
  52. package/src/bean/scope/index.ts +4 -0
  53. package/src/bean/scope/type.ts +23 -0
  54. package/src/bean/type.ts +31 -0
  55. package/src/composables/index.ts +4 -0
  56. package/src/composables/onControllerMounted.ts +12 -0
  57. package/src/composables/useApp.ts +7 -0
  58. package/src/composables/useContext.ts +7 -0
  59. package/src/composables/useController.ts +125 -0
  60. package/src/core/app/application.ts +76 -0
  61. package/src/core/app/config.ts +68 -0
  62. package/src/core/app/constant.ts +11 -0
  63. package/src/core/app/index.ts +6 -0
  64. package/src/core/app/locale.ts +12 -0
  65. package/src/core/app/meta.ts +44 -0
  66. package/src/core/app/util.ts +31 -0
  67. package/src/core/component/component.ts +44 -0
  68. package/src/core/component/cookie.ts +16 -0
  69. package/src/core/component/error.ts +18 -0
  70. package/src/core/component/event.ts +87 -0
  71. package/src/core/component/index.ts +3 -0
  72. package/src/core/component/locale.ts +97 -0
  73. package/src/core/component/module.ts +281 -0
  74. package/src/core/context/component.ts +34 -0
  75. package/src/core/context/context.ts +38 -0
  76. package/src/core/context/index.ts +4 -0
  77. package/src/core/context/meta.ts +26 -0
  78. package/src/core/context/state.ts +28 -0
  79. package/src/core/context/util.ts +20 -0
  80. package/src/core/index.ts +5 -0
  81. package/src/core/metadata.ts +54 -0
  82. package/src/core/resource.ts +186 -0
  83. package/src/decorator/class/bean.ts +19 -0
  84. package/src/decorator/class/index.ts +12 -0
  85. package/src/decorator/class/local.ts +18 -0
  86. package/src/decorator/class/model.ts +18 -0
  87. package/src/decorator/class/scope.ts +18 -0
  88. package/src/decorator/class/store.ts +18 -0
  89. package/src/decorator/class/style.ts +18 -0
  90. package/src/decorator/class/theme.ts +18 -0
  91. package/src/decorator/class/tool.ts +18 -0
  92. package/src/decorator/class/use.ts +37 -0
  93. package/src/decorator/class/useComposable.ts +16 -0
  94. package/src/decorator/class/useScope.ts +21 -0
  95. package/src/decorator/class/virtual.ts +20 -0
  96. package/src/decorator/index.ts +7 -0
  97. package/src/decorator/interface/beanOptions.ts +80 -0
  98. package/src/decorator/interface/useOptions.ts +37 -0
  99. package/src/decorator/type/constructable.ts +1 -0
  100. package/src/decorator/type/containerScope.ts +1 -0
  101. package/src/decorator/type/functionable.ts +1 -0
  102. package/src/decorator/type/injectionScope.ts +1 -0
  103. package/src/index.ts +9 -0
  104. package/src/plugins/bean.ts +16 -0
  105. package/src/plugins/index.ts +2 -0
  106. package/src/plugins/zova.ts +28 -0
  107. package/src/types/index.ts +2 -0
  108. package/src/types/interface/component.ts +36 -0
  109. package/src/types/interface/event.ts +28 -0
  110. package/src/types/interface/index.ts +6 -0
  111. package/src/types/interface/inject.ts +2 -0
  112. package/src/types/interface/module.ts +38 -0
  113. package/src/types/interface/monkey.ts +38 -0
  114. package/src/types/interface/pluginZova.ts +17 -0
  115. package/src/types/utils/cast.ts +8 -0
  116. package/src/types/utils/env.ts +35 -0
  117. package/src/types/utils/index.ts +3 -0
  118. package/src/types/utils/powerPartial.ts +3 -0
  119. package/src/utils/index.ts +1 -0
  120. package/src/utils/isClass.ts +17 -0
  121. package/src/utils/stateLock.ts +47 -0
  122. package/src/utils/uuid.ts +84 -0
  123. package/src/vue/composable.ts +10 -0
  124. package/src/vue/computed.ts +7 -0
  125. package/src/vue/customRef.ts +5 -0
  126. package/src/vue/index.ts +4 -0
  127. package/src/vue/ref.ts +12 -0
  128. package/src/zod/index.ts +2 -0
  129. package/src/zod/zz.ts +77 -0
  130. package/dist/decorator/class/data.d.ts +0 -3
  131. package/dist/decorator/class/data.d.ts.map +0 -1
  132. package/dist/decorator/class/data.js +0 -18
  133. package/dist/decorator/class/data.js.map +0 -1
@@ -0,0 +1,58 @@
1
+ import { useModel } from 'vue';
2
+ import { BeanBase } from './beanBase.js';
3
+ import { IControllerData } from './type.js';
4
+ import { Cast } from '../types/utils/cast.js';
5
+ import { useRef } from '../vue/ref.js';
6
+
7
+ type Data = Record<string, unknown>;
8
+
9
+ type DefineModelOptions<T = any> = {
10
+ get?: (v: T) => any;
11
+ set?: (v: T) => any;
12
+ };
13
+
14
+ export interface PropsBase<Controller = unknown, Slots = unknown> {
15
+ controllerRef?: (ref: Controller) => void;
16
+ slots?: Slots;
17
+ }
18
+
19
+ export class BeanControllerBase<
20
+ TScopeModule = unknown,
21
+ Props = unknown,
22
+ Emits = unknown,
23
+ Slots = unknown,
24
+ > extends BeanBase<TScopeModule> {
25
+ public $props: Props;
26
+ public $emit: Emits;
27
+ public $slots: Slots;
28
+ public $attrs: Data;
29
+
30
+ /** @internal */
31
+ public __initControllerData(controllerData: IControllerData) {
32
+ this.$props = controllerData.props as Props;
33
+ this.$emit = controllerData.context.emit as Emits;
34
+ this.$attrs = controllerData.context.attrs as Data;
35
+ this.$slots = useRef(() => {
36
+ const propSlots = Cast(this.$props).slots;
37
+ const contextSlots = controllerData.context.slots;
38
+ if (!propSlots) {
39
+ return contextSlots;
40
+ } else {
41
+ return contextSlots ? Object.assign({}, propSlots, contextSlots) : propSlots;
42
+ }
43
+ });
44
+ this.app.meta.module._monkeyModuleSync('controllerDataInit', undefined, controllerData, this);
45
+ }
46
+
47
+ // @ts-ignore ignore
48
+ protected $useModel(options?: DefineModelOptions<Props['modelValue']>): Props['modelValue'];
49
+ protected $useModel<K extends keyof Props>(name: K, options?: DefineModelOptions<Props[K]>): Props[K];
50
+ protected $useModel(name?, options?) {
51
+ if (typeof name === 'object') {
52
+ options = name;
53
+ name = 'modelValue';
54
+ }
55
+ if (!name) name = 'modelValue';
56
+ return useModel(this.$props as any, name, options);
57
+ }
58
+ }
@@ -0,0 +1,29 @@
1
+ import { Cast } from '../types/utils/cast.js';
2
+ import { BeanBase } from './beanBase.js';
3
+ import { BeanControllerIdentifier } from './type.js';
4
+
5
+ const SymbolController = Symbol('SymbolController');
6
+
7
+ export class BeanControllerLike<TScopeModule = unknown> extends BeanBase<TScopeModule> {
8
+ protected get [SymbolController](): unknown | undefined {
9
+ return this.bean._getBeanSyncOnly(BeanControllerIdentifier);
10
+ }
11
+
12
+ /** @internal */
13
+ public __get__(prop): unknown {
14
+ const controller = Cast(this[SymbolController]);
15
+ return controller?.[prop];
16
+ }
17
+
18
+ /** @internal */
19
+ public __set__(prop, value): boolean {
20
+ const controller = Cast(this[SymbolController]);
21
+ if (!controller) return false;
22
+ if (prop in controller) {
23
+ controller[prop] = value;
24
+ return true;
25
+ } else {
26
+ return false;
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,18 @@
1
+ import { BeanBase } from './beanBase.js';
2
+ import { IControllerData } from './type.js';
3
+
4
+ export class BeanControllerPageBase<
5
+ TScopeModule = unknown,
6
+ Query = unknown,
7
+ Params = unknown,
8
+ > extends BeanBase<TScopeModule> {
9
+ public $params: Params;
10
+ public $query: Query;
11
+
12
+ /** @internal */
13
+ public __initControllerData(controllerData: IControllerData) {
14
+ if (this.app) {
15
+ this.app.meta.module._monkeyModuleSync('controllerDataInit', undefined, controllerData, this);
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,7 @@
1
+ import { BeanRenderLike } from './beanRenderLike.js';
2
+
3
+ export class BeanRenderBase<TScopeModule = unknown> extends BeanRenderLike<TScopeModule> {
4
+ render() {
5
+ return;
6
+ }
7
+ }
@@ -0,0 +1,33 @@
1
+ import { Cast } from '../types/utils/cast.js';
2
+ import { BeanControllerLike } from './beanControllerLike.js';
3
+ import { BeanStyleIdentifier } from './type.js';
4
+
5
+ const SymbolStyle = Symbol('SymbolStyle');
6
+
7
+ export class BeanRenderLike<TScopeModule = unknown> extends BeanControllerLike<TScopeModule> {
8
+ private get [SymbolStyle](): unknown | undefined {
9
+ return this.bean._getBeanSyncOnly(BeanStyleIdentifier);
10
+ }
11
+
12
+ /** @internal */
13
+ public __get__(prop): unknown {
14
+ const value = super.__get__(prop);
15
+ if (value !== undefined) return value;
16
+ const style = Cast(this[SymbolStyle]);
17
+ return style?.[prop];
18
+ }
19
+
20
+ /** @internal */
21
+ public __set__(prop, value): boolean {
22
+ const res = super.__set__(prop, value);
23
+ if (res) return res;
24
+ const style = Cast(this[SymbolStyle]);
25
+ if (!style) return false;
26
+ if (prop in style) {
27
+ style[prop] = value;
28
+ return true;
29
+ } else {
30
+ return false;
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,11 @@
1
+ import { ZovaApplication } from '../core/app/index.js';
2
+ import { ZovaContext } from '../core/context/index.js';
3
+
4
+ export class BeanSimple {
5
+ protected app: ZovaApplication;
6
+ protected ctx: ZovaContext;
7
+
8
+ protected get bean() {
9
+ return this.ctx.bean;
10
+ }
11
+ }
@@ -0,0 +1,3 @@
1
+ import { BeanControllerLike } from './beanControllerLike.js';
2
+
3
+ export class BeanStyleBase<TScopeModule = unknown> extends BeanControllerLike<TScopeModule> {}
@@ -0,0 +1,13 @@
1
+ export * from './resource/index.js';
2
+ export * from './scope/index.js';
3
+ export * from './beanBase.js';
4
+ export * from './beanBaseSimple.js';
5
+ export * from './beanContainer.js';
6
+ export * from './beanControllerBase.js';
7
+ export * from './beanControllerLike.js';
8
+ export * from './beanControllerPageBase.js';
9
+ export * from './beanRenderBase.js';
10
+ export * from './beanRenderLike.js';
11
+ export * from './beanStyleBase.js';
12
+ export * from './beanSimple.js';
13
+ export * from './type.js';
@@ -0,0 +1 @@
1
+ export * from './type.js';
@@ -0,0 +1,5 @@
1
+ export type TypeModuleComponents<T> = T;
2
+
3
+ export interface IComponentRecord {}
4
+
5
+ export interface IComponentLayoutRecord {}
@@ -0,0 +1 @@
1
+ export * from './type.js';
@@ -0,0 +1,32 @@
1
+ import { ZovaApplication } from '../../../core/app/application.js';
2
+
3
+ export type TypeModuleConfig<T extends (app: ZovaApplication) => object> = ReturnType<T>;
4
+
5
+ export interface IModuleConfigBroadcast {
6
+ bean: string | { module: string; name: string };
7
+ }
8
+
9
+ export interface IModuleConfigMiddleware {
10
+ bean: string | { module: string; name: string };
11
+ global?: boolean;
12
+ dependencies?: string | string[];
13
+ }
14
+
15
+ export interface IModuleConfigQueue {
16
+ bean: string | { module: string; name: string };
17
+ }
18
+
19
+ export interface IModuleConfigStartup {
20
+ bean: string | { module: string; name: string };
21
+ instance?: boolean;
22
+ debounce?: boolean;
23
+ }
24
+
25
+ export interface IModuleConfigSchedule {
26
+ bean: string | { module: string; name: string };
27
+ repeat: {
28
+ every?: number;
29
+ cron?: string;
30
+ };
31
+ disable?: boolean;
32
+ }
@@ -0,0 +1 @@
1
+ export * from './type.js';
@@ -0,0 +1 @@
1
+ export type TypeModuleConstants<T> = T;
@@ -0,0 +1,21 @@
1
+ import { IModuleError } from './type.js';
2
+ import { BeanSimple } from '../../beanSimple.js';
3
+
4
+ const BeanModuleScope = Symbol('BeanScopeError#ModuleScope');
5
+
6
+ export class BeanScopeError extends BeanSimple {
7
+ private [BeanModuleScope]: string;
8
+ private __instances: Record<string, IModuleError> = {};
9
+
10
+ constructor(moduleScope) {
11
+ super();
12
+ this[BeanModuleScope] = moduleScope;
13
+ }
14
+
15
+ protected __get__(prop) {
16
+ if (!this.__instances[prop]) {
17
+ this.__instances[prop] = this.app.meta.error.createScopeError(this[BeanModuleScope], prop);
18
+ }
19
+ return this.__instances[prop];
20
+ }
21
+ }
@@ -0,0 +1,57 @@
1
+ import { TypeModuleResourceErrorModules } from '../../../types/interface/module.js';
2
+ import { BeanSimple } from '../../beanSimple.js';
3
+ import { errorsInternal } from './errorInternal.js';
4
+
5
+ export class ErrorClass extends BeanSimple {
6
+ /** @internal */
7
+ public errors: TypeModuleResourceErrorModules;
8
+
9
+ /** @internal */
10
+ public async initialize() {
11
+ this.errors = {};
12
+ }
13
+
14
+ // code/message,args
15
+ throw(module, code, ...args): never {
16
+ const body = this.parseFail(module, code, ...args);
17
+ const err = new Error();
18
+ err.code = body.code;
19
+ err.message = body.message;
20
+ if (body.code < 500) err.status = body.code;
21
+ throw err;
22
+ }
23
+ // code/message,args
24
+ parseFail(module, code, ...args) {
25
+ if (typeof code === 'object') return code;
26
+ return this.parseCode(module, 1, code, ...args);
27
+ }
28
+ // parseCode
29
+ parseCode(module, codeDefault, code, ...args) {
30
+ const ebError = this.errors[module];
31
+
32
+ // convert from enum
33
+ if (code && typeof code === 'string') {
34
+ code = ebError[code];
35
+ }
36
+
37
+ if (code === undefined || code === null || code === '') {
38
+ code = codeDefault;
39
+ }
40
+
41
+ let message: string;
42
+ if (code <= 1000) {
43
+ // todo:
44
+ message = this.app.meta.locale.getText(undefined, undefined, errorsInternal[code], ...args);
45
+ } else {
46
+ message = this.app.meta.locale.getText(module, undefined, ebError[code], ...args);
47
+ }
48
+
49
+ code = __combineErrorCode(module, code);
50
+ return { code, message };
51
+ }
52
+ }
53
+
54
+ function __combineErrorCode(module, code) {
55
+ if (typeof code !== 'number' || code <= 1000) return code;
56
+ return module ? `${module}:${code}` : code;
57
+ }
@@ -0,0 +1,7 @@
1
+ declare global {
2
+ export interface Error {
3
+ code?: number | string | undefined;
4
+ status?: number | string | undefined;
5
+ }
6
+ }
7
+ export {};
@@ -0,0 +1,66 @@
1
+ export const errorsInternal = {
2
+ 0: 'Success',
3
+ 1: 'Unknown Error',
4
+ 100: 'Continue',
5
+ 101: 'Switching Protocols',
6
+ 102: 'Processing',
7
+ 200: 'OK',
8
+ 201: 'Created',
9
+ 202: 'Accepted',
10
+ 203: 'Non-Authoritative Information',
11
+ 204: 'No Content',
12
+ 205: 'Reset Content',
13
+ 206: 'Partial Content',
14
+ 207: 'Multi-Status',
15
+ 208: 'Already Reported',
16
+ 226: 'IM Used',
17
+ 300: 'Multiple Choices',
18
+ 301: 'Moved Permanently',
19
+ 302: 'Found',
20
+ 303: 'See Other',
21
+ 304: 'Not Modified',
22
+ 305: 'Use Proxy',
23
+ 307: 'Temporary Redirect',
24
+ 308: 'Permanent Redirect',
25
+ 400: 'Bad Request',
26
+ 401: 'Unauthorized',
27
+ 402: 'Payment Required',
28
+ 403: 'Forbidden',
29
+ 404: 'Not Found',
30
+ 405: 'Method Not Allowed',
31
+ 406: 'Not Acceptable',
32
+ 407: 'Proxy Authentication Required',
33
+ 408: 'Request Timeout',
34
+ 409: 'Conflict',
35
+ 410: 'Gone',
36
+ 411: 'Length Required',
37
+ 412: 'Precondition Failed',
38
+ 413: 'Payload Too Large',
39
+ 414: 'URI Too Long',
40
+ 415: 'Unsupported Media Type',
41
+ 416: 'Range Not Satisfiable',
42
+ 417: 'Expectation Failed',
43
+ 418: "I'm a teapot",
44
+ 421: 'Misdirected Request',
45
+ 422: 'Unprocessable Entity',
46
+ 423: 'Locked',
47
+ 424: 'Failed Dependency',
48
+ 425: 'Unordered Collection',
49
+ 426: 'Upgrade Required',
50
+ 428: 'Precondition Required',
51
+ 429: 'Too Many Requests',
52
+ 431: 'Request Header Fields Too Large',
53
+ 451: 'Unavailable For Legal Reasons',
54
+ 500: 'Internal Server Error',
55
+ 501: 'Not Implemented',
56
+ 502: 'Bad Gateway',
57
+ 503: 'Service Unavailable',
58
+ 504: 'Gateway Timeout',
59
+ 505: 'HTTP Version Not Supported',
60
+ 506: 'Variant Also Negotiates',
61
+ 507: 'Insufficient Storage',
62
+ 508: 'Loop Detected',
63
+ 509: 'Bandwidth Limit Exceeded',
64
+ 510: 'Not Extended',
65
+ 511: 'Network Authentication Required',
66
+ };
@@ -0,0 +1,4 @@
1
+ export interface IErrorObject {
2
+ code: number | string;
3
+ message: string;
4
+ }
@@ -0,0 +1,6 @@
1
+ export * from './beanScopeError.js';
2
+ export * from './errorClass.js';
3
+ export * from './errorGlobal.js';
4
+ export * from './errorInternal.js';
5
+ export * from './errorObject.js';
6
+ export * from './type.js';
@@ -0,0 +1,10 @@
1
+ import { IErrorObject } from './errorObject.js';
2
+
3
+ export interface IModuleError {
4
+ throw(...args: any[]): never;
5
+ parseFail(...args: any[]): IErrorObject;
6
+ }
7
+
8
+ export type TypeModuleErrors<T> = {
9
+ [prop in string & keyof T]: IModuleError;
10
+ };
@@ -0,0 +1,161 @@
1
+ import { reactive } from 'vue';
2
+ import { BeanSimple } from '../../beanSimple.js';
3
+ import { IIconInfo, IIconMeta, TypeIconModules, TypeIconSymbols } from './types.js';
4
+ import { IconGroup } from './iconGroup.js';
5
+
6
+ const XMLNS = 'http://www.w3.org/2000/svg';
7
+ const XMLNS_LINK = 'http://www.w3.org/1999/xlink';
8
+
9
+ export class AppIcon extends BeanSimple {
10
+ private _iconSymbols: TypeIconSymbols = reactive({});
11
+ private _iconMoudles: TypeIconModules = {};
12
+
13
+ // undefined: ignore
14
+ // '': empty icon
15
+ parseIconInfoSync(iconName?: string): IIconInfo | undefined {
16
+ // parts
17
+ const meta = this.parseIconMeta(iconName);
18
+ if (!meta) return undefined;
19
+ // empty
20
+ const iconEmpty = { meta, symbolId: '' };
21
+ // check if exists
22
+ if (this._iconSymbols[meta.fullName] === undefined) {
23
+ this.parseIconInfo(iconName);
24
+ return iconEmpty;
25
+ }
26
+ return { meta, symbolId: meta.symbolId };
27
+ }
28
+
29
+ async parseIconInfo(iconName?: string): Promise<IIconInfo | undefined> {
30
+ // parts
31
+ const meta = this.parseIconMeta(iconName);
32
+ if (!meta) return undefined;
33
+ // check if exists
34
+ if (this._iconSymbols[meta.fullName]) {
35
+ return { meta, symbolId: this._iconSymbols[meta.fullName] };
36
+ }
37
+ // pre set
38
+ this._iconSymbols[meta.fullName] = '';
39
+ // icon group
40
+ const iconGroup = await this.parseIconGroup(meta.module, meta.group);
41
+ if (!iconGroup) return undefined;
42
+ // icon inject
43
+ const symbolId = this._injectIcon(meta);
44
+ this._iconSymbols[meta.fullName] = symbolId;
45
+ // ok
46
+ return { meta, symbolId };
47
+ }
48
+
49
+ public async parseIconGroup(moduleName: string, groupName: string): Promise<string | undefined> {
50
+ // check if exists
51
+ const iconModule = this._getIconModule(moduleName);
52
+ if (iconModule[groupName]) {
53
+ await iconModule[groupName].loaded.wait();
54
+ return iconModule[groupName].svg;
55
+ }
56
+ // record
57
+ iconModule[groupName] = new IconGroup();
58
+ // parse
59
+ const svg = await this._parseIconGroupInner(moduleName, groupName);
60
+ // touch
61
+ iconModule[groupName].svg = svg;
62
+ iconModule[groupName].loaded.touch();
63
+ // ok
64
+ return iconModule[groupName].svg;
65
+ }
66
+
67
+ private async _parseIconGroupInner(moduleName: string, groupName: string): Promise<string | undefined> {
68
+ // module
69
+ const module = await this.app.meta.module.use(moduleName);
70
+ if (!module) return;
71
+ // icons
72
+ const icons = module.resource.icons;
73
+ const groupUrl = icons[groupName];
74
+ if (!groupUrl) return;
75
+ // fetch
76
+ const res = await fetch(groupUrl);
77
+ if (!res.ok) return;
78
+ const svg = await res.text();
79
+ return svg;
80
+ }
81
+
82
+ private _injectIcon(meta: IIconMeta) {
83
+ const iconModule = this._getIconModule(meta.module);
84
+ const iconGroup = iconModule[meta.group];
85
+ // inject container
86
+ let domContainer = document.getElementById('zova-svg-container');
87
+ if (!domContainer) {
88
+ domContainer = document.createElement('div');
89
+ domContainer.style.position = 'absolute';
90
+ domContainer.style.width = '0';
91
+ domContainer.style.height = '0';
92
+ domContainer.style.display = 'none';
93
+ domContainer.id = 'zova-svg-container';
94
+ document.body.appendChild(domContainer);
95
+ }
96
+ // inject module
97
+ let domModule = document.getElementById(`zova-svg-module-${meta.module}`);
98
+ if (!domModule) {
99
+ domModule = document.createElement('div');
100
+ domModule.id = `zova-svg-module-${meta.module}`;
101
+ domContainer.appendChild(domModule);
102
+ }
103
+ // inject group
104
+ let domGroup = document.getElementById(`zova-svg-group-${meta.module}-${meta.group}`) as unknown as SVGSVGElement;
105
+ if (!domGroup) {
106
+ domGroup = document.createElementNS(XMLNS, 'svg');
107
+ domGroup.id = `zova-svg-group-${meta.module}-${meta.group}`;
108
+ domGroup.setAttribute('xmlns', XMLNS);
109
+ domGroup.setAttribute('xmlns:link', XMLNS_LINK);
110
+ domModule.appendChild(domGroup);
111
+ }
112
+ // inject icon
113
+ const domIcon = document.getElementById(meta.symbolId) as unknown as SVGElement;
114
+ if (!domIcon) {
115
+ const symbolPattern = new RegExp(`<symbol.*?id="${meta.symbolId}".*?>.*?</symbol>`);
116
+ const matched = symbolPattern.exec(iconGroup.svg || '');
117
+ if (matched) {
118
+ domGroup.insertAdjacentHTML('beforeend', matched[0]);
119
+ }
120
+ }
121
+ // ok
122
+ return meta.symbolId;
123
+ }
124
+
125
+ private _getIconModule(moduleName: string) {
126
+ if (!this._iconMoudles[moduleName]) {
127
+ this._iconMoudles[moduleName] = {};
128
+ }
129
+ return this._iconMoudles[moduleName];
130
+ }
131
+
132
+ parseIconMeta(iconName?: string): IIconMeta | undefined {
133
+ if (!iconName) return;
134
+ // split module:group:name
135
+ const parts = iconName.split(':');
136
+ if (parts.length !== 3) {
137
+ return;
138
+ }
139
+ const module = parts[0] || this.app.config.icon.defaultModule;
140
+ const group = parts[1] || 'default';
141
+ const name = parts[2] || '';
142
+ if (module.indexOf('-') === -1 || !name) {
143
+ return;
144
+ }
145
+ return {
146
+ module,
147
+ group,
148
+ name,
149
+ fullName: this._getFullName(module, group, name),
150
+ symbolId: this._getSymbolId(module, group, name),
151
+ };
152
+ }
153
+
154
+ private _getSymbolId(module: string, group: string, name: string) {
155
+ return `zova-svg-icon-${module}-${group}-${name}`;
156
+ }
157
+
158
+ private _getFullName(module: string, group: string, name: string) {
159
+ return `${module}:${group}:${name}`;
160
+ }
161
+ }
@@ -0,0 +1,10 @@
1
+ import { StateLock } from '../../../utils/stateLock.js';
2
+
3
+ export class IconGroup {
4
+ public svg: string | undefined;
5
+ public loaded: StateLock;
6
+
7
+ constructor() {
8
+ this.loaded = StateLock.create();
9
+ }
10
+ }
@@ -0,0 +1,4 @@
1
+ export * from './zovaIcon.js';
2
+ export * from './types.js';
3
+ export * from './useZovaIcon.js';
4
+ export * from './utils.js';
@@ -0,0 +1,21 @@
1
+ import { IconGroup } from './iconGroup.js';
2
+
3
+ export interface IIconRecord {}
4
+ export type TypeIcon = keyof IIconRecord;
5
+
6
+ export interface IIconMeta {
7
+ module: string;
8
+ group: string;
9
+ name: string;
10
+ fullName: string;
11
+ symbolId: string;
12
+ }
13
+
14
+ export interface IIconInfo {
15
+ meta: IIconMeta;
16
+ symbolId: string; // '' or valid icon
17
+ }
18
+
19
+ export type TypeIconGroups = Record<string, IconGroup>;
20
+ export type TypeIconModules = Record<string, TypeIconGroups>;
21
+ export type TypeIconSymbols = Record<string, string>;
@@ -0,0 +1,20 @@
1
+ import { ref, watchEffect } from 'vue';
2
+ import { useApp } from '../../../composables/useApp.js';
3
+ import { ZovaApplication } from '../../../core/index.js';
4
+ import { IIconInfo } from './types.js';
5
+
6
+ export function getZovaIcon(iconName?: string, app?: ZovaApplication): IIconInfo | undefined {
7
+ if (!app) app = useApp();
8
+ return app.meta.icon.parseIconInfoSync(iconName);
9
+ }
10
+
11
+ export function useZovaIcon(iconGetter: () => string | undefined) {
12
+ const iconInfo = ref<IIconInfo>();
13
+ const app = useApp();
14
+
15
+ watchEffect(() => {
16
+ iconInfo.value = getZovaIcon(iconGetter(), app);
17
+ });
18
+
19
+ return { iconInfo };
20
+ }
@@ -0,0 +1,20 @@
1
+ import { createVNode, VNode } from 'vue';
2
+ import { IIconRecord } from './types.js';
3
+ import { ZovaIcon } from './zovaIcon.js';
4
+
5
+ // should not provide name?: string
6
+ //export function iconh(name?: string, color?: string, size?: string | number);
7
+ export function iconh<K extends keyof IIconRecord>(name: K, color?: string, size?: string | number): VNode;
8
+ export function iconh(name?, color?, size?): VNode {
9
+ size = size ?? 24;
10
+ return createVNode(ZovaIcon, {
11
+ name,
12
+ color,
13
+ width: size,
14
+ height: size,
15
+ });
16
+ }
17
+
18
+ export function icon<K extends keyof IIconRecord>(name: K): K {
19
+ return name;
20
+ }