@aerogel/core 0.0.0-next.c29ffcd25bffdbed37ecce3aac1ba14cde3e9d39 → 0.0.0-next.c2e6acc000e97a1020c2e232678563c53884dd0e

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 (154) hide show
  1. package/dist/aerogel-core.d.ts +1223 -1792
  2. package/dist/aerogel-core.js +2968 -0
  3. package/dist/aerogel-core.js.map +1 -0
  4. package/package.json +27 -37
  5. package/src/bootstrap/bootstrap.test.ts +4 -7
  6. package/src/bootstrap/index.ts +14 -15
  7. package/src/bootstrap/options.ts +1 -1
  8. package/src/components/{AGAppLayout.vue → AppLayout.vue} +4 -4
  9. package/src/components/{AGAppModals.vue → AppModals.vue} +3 -4
  10. package/src/components/{AGAppOverlays.vue → AppOverlays.vue} +5 -5
  11. package/src/components/composition.ts +1 -1
  12. package/src/components/contracts/AlertModal.ts +4 -0
  13. package/src/components/contracts/Button.ts +15 -0
  14. package/src/components/contracts/ConfirmModal.ts +41 -0
  15. package/src/components/contracts/ErrorReportModal.ts +29 -0
  16. package/src/components/contracts/Input.ts +26 -0
  17. package/src/components/contracts/LoadingModal.ts +18 -0
  18. package/src/components/contracts/Modal.ts +9 -0
  19. package/src/components/contracts/PromptModal.ts +28 -0
  20. package/src/components/contracts/index.ts +7 -0
  21. package/src/components/contracts/shared.ts +9 -0
  22. package/src/components/forms/AGSelect.vue +11 -17
  23. package/src/components/forms/index.ts +0 -4
  24. package/src/components/headless/HeadlessButton.vue +45 -0
  25. package/src/components/headless/HeadlessInput.vue +59 -0
  26. package/src/components/headless/{forms/AGHeadlessInputDescription.vue → HeadlessInputDescription.vue} +6 -7
  27. package/src/components/headless/{forms/AGHeadlessInputError.vue → HeadlessInputError.vue} +4 -8
  28. package/src/components/headless/{forms/AGHeadlessInputInput.vue → HeadlessInputInput.vue} +10 -19
  29. package/src/components/headless/{forms/AGHeadlessInputLabel.vue → HeadlessInputLabel.vue} +3 -7
  30. package/src/components/headless/{forms/AGHeadlessInputTextArea.vue → HeadlessInputTextArea.vue} +6 -9
  31. package/src/components/headless/{modals/AGHeadlessModal.vue → HeadlessModal.vue} +16 -24
  32. package/src/components/headless/HeadlessModalContent.vue +24 -0
  33. package/src/components/headless/HeadlessModalOverlay.vue +12 -0
  34. package/src/components/headless/HeadlessModalTitle.vue +12 -0
  35. package/src/components/headless/forms/AGHeadlessSelect.ts +3 -3
  36. package/src/components/headless/forms/AGHeadlessSelect.vue +16 -16
  37. package/src/components/headless/forms/AGHeadlessSelectError.vue +2 -2
  38. package/src/components/headless/forms/AGHeadlessSelectOption.vue +10 -18
  39. package/src/components/headless/forms/AGHeadlessSelectOptions.vue +19 -0
  40. package/src/components/headless/forms/AGHeadlessSelectTrigger.vue +25 -0
  41. package/src/components/headless/forms/composition.ts +2 -2
  42. package/src/components/headless/forms/index.ts +2 -12
  43. package/src/components/headless/index.ts +12 -1
  44. package/src/components/headless/snackbars/index.ts +3 -3
  45. package/src/components/index.ts +5 -5
  46. package/src/components/lib/AGErrorMessage.vue +5 -5
  47. package/src/components/lib/AGMeasured.vue +2 -2
  48. package/src/components/lib/AGStartupCrash.vue +8 -8
  49. package/src/components/lib/index.ts +0 -3
  50. package/src/components/snackbars/AGSnackbar.vue +10 -8
  51. package/src/components/ui/AlertModal.vue +13 -0
  52. package/src/components/ui/Button.vue +58 -0
  53. package/src/components/ui/Checkbox.vue +49 -0
  54. package/src/components/ui/ConfirmModal.vue +42 -0
  55. package/src/components/ui/ErrorReportModal.vue +62 -0
  56. package/src/components/{modals/AGErrorReportModalButtons.vue → ui/ErrorReportModalButtons.vue} +29 -20
  57. package/src/components/ui/ErrorReportModalTitle.vue +24 -0
  58. package/src/components/{forms/AGForm.vue → ui/Form.vue} +4 -5
  59. package/src/components/ui/Input.vue +52 -0
  60. package/src/components/ui/Link.vue +12 -0
  61. package/src/components/ui/LoadingModal.vue +32 -0
  62. package/src/components/ui/Markdown.vue +62 -0
  63. package/src/components/ui/Modal.vue +55 -0
  64. package/src/components/{modals/AGModalContext.vue → ui/ModalContext.vue} +7 -9
  65. package/src/components/ui/ProgressBar.vue +50 -0
  66. package/src/components/ui/PromptModal.vue +35 -0
  67. package/src/components/ui/index.ts +16 -0
  68. package/src/components/utils.ts +106 -9
  69. package/src/directives/index.ts +9 -5
  70. package/src/directives/measure.ts +1 -1
  71. package/src/errors/Errors.state.ts +1 -1
  72. package/src/errors/Errors.ts +14 -14
  73. package/src/errors/index.ts +9 -6
  74. package/src/errors/utils.ts +1 -1
  75. package/src/forms/{Form.test.ts → FormController.test.ts} +5 -4
  76. package/src/forms/{Form.ts → FormController.ts} +22 -19
  77. package/src/forms/composition.ts +4 -4
  78. package/src/forms/index.ts +2 -2
  79. package/src/forms/utils.ts +2 -2
  80. package/src/index.css +8 -0
  81. package/src/jobs/Job.ts +2 -2
  82. package/src/lang/DefaultLangProvider.ts +7 -4
  83. package/src/lang/Lang.state.ts +1 -1
  84. package/src/lang/Lang.ts +1 -1
  85. package/src/lang/index.ts +8 -6
  86. package/src/plugins/Plugin.ts +1 -1
  87. package/src/plugins/index.ts +10 -7
  88. package/src/services/App.state.ts +4 -3
  89. package/src/services/App.ts +4 -4
  90. package/src/services/Cache.ts +1 -1
  91. package/src/services/Events.ts +2 -2
  92. package/src/services/Service.ts +21 -21
  93. package/src/services/Storage.ts +3 -3
  94. package/src/services/index.ts +5 -4
  95. package/src/services/utils.ts +2 -2
  96. package/src/testing/index.ts +4 -3
  97. package/src/testing/setup.ts +3 -19
  98. package/src/ui/UI.state.ts +10 -5
  99. package/src/ui/UI.ts +53 -40
  100. package/src/ui/index.ts +16 -16
  101. package/src/utils/composition/events.ts +2 -2
  102. package/src/utils/composition/forms.ts +4 -3
  103. package/src/utils/markdown.ts +3 -5
  104. package/src/utils/vdom.ts +31 -0
  105. package/src/utils/vue.ts +7 -12
  106. package/dist/aerogel-core.cjs.js +0 -2
  107. package/dist/aerogel-core.cjs.js.map +0 -1
  108. package/dist/aerogel-core.esm.js +0 -2
  109. package/dist/aerogel-core.esm.js.map +0 -1
  110. package/histoire.config.ts +0 -7
  111. package/noeldemartin.config.js +0 -5
  112. package/postcss.config.js +0 -6
  113. package/src/assets/histoire.css +0 -3
  114. package/src/components/forms/AGButton.vue +0 -44
  115. package/src/components/forms/AGCheckbox.vue +0 -41
  116. package/src/components/forms/AGInput.vue +0 -40
  117. package/src/components/headless/forms/AGHeadlessButton.ts +0 -3
  118. package/src/components/headless/forms/AGHeadlessButton.vue +0 -62
  119. package/src/components/headless/forms/AGHeadlessInput.ts +0 -34
  120. package/src/components/headless/forms/AGHeadlessInput.vue +0 -70
  121. package/src/components/headless/forms/AGHeadlessSelectButton.vue +0 -24
  122. package/src/components/headless/forms/AGHeadlessSelectLabel.vue +0 -24
  123. package/src/components/headless/forms/AGHeadlessSelectOptions.ts +0 -3
  124. package/src/components/headless/modals/AGHeadlessModal.ts +0 -36
  125. package/src/components/headless/modals/AGHeadlessModalPanel.vue +0 -32
  126. package/src/components/headless/modals/AGHeadlessModalTitle.vue +0 -23
  127. package/src/components/headless/modals/index.ts +0 -4
  128. package/src/components/interfaces.ts +0 -24
  129. package/src/components/lib/AGLink.vue +0 -9
  130. package/src/components/lib/AGMarkdown.vue +0 -54
  131. package/src/components/lib/AGProgressBar.vue +0 -45
  132. package/src/components/modals/AGAlertModal.ts +0 -18
  133. package/src/components/modals/AGAlertModal.vue +0 -14
  134. package/src/components/modals/AGConfirmModal.ts +0 -42
  135. package/src/components/modals/AGConfirmModal.vue +0 -26
  136. package/src/components/modals/AGErrorReportModal.ts +0 -49
  137. package/src/components/modals/AGErrorReportModal.vue +0 -54
  138. package/src/components/modals/AGErrorReportModalTitle.vue +0 -25
  139. package/src/components/modals/AGLoadingModal.ts +0 -29
  140. package/src/components/modals/AGLoadingModal.vue +0 -15
  141. package/src/components/modals/AGModal.ts +0 -11
  142. package/src/components/modals/AGModal.vue +0 -39
  143. package/src/components/modals/AGModalContext.ts +0 -8
  144. package/src/components/modals/AGModalTitle.vue +0 -9
  145. package/src/components/modals/AGPromptModal.ts +0 -41
  146. package/src/components/modals/AGPromptModal.vue +0 -34
  147. package/src/components/modals/index.ts +0 -17
  148. package/src/directives/initial-focus.ts +0 -11
  149. package/src/main.histoire.ts +0 -1
  150. package/tailwind.config.js +0 -4
  151. package/tsconfig.json +0 -11
  152. package/vite.config.ts +0 -17
  153. /package/src/components/{AGAppSnackbars.vue → AppSnackbars.vue} +0 -0
  154. /package/src/{main.ts → index.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { PromisedValue, facade, tap } from '@noeldemartin/utils';
2
2
 
3
- import Service from '@/services/Service';
3
+ import Service from '@aerogel/core/services/Service';
4
4
 
5
5
  export class CacheService extends Service {
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { arrayRemove, facade, fail, tap } from '@noeldemartin/utils';
2
2
 
3
- import Service from '@/services/Service';
3
+ import Service from '@aerogel/core/services/Service';
4
4
 
5
5
  export interface EventsPayload {}
6
6
  export interface EventListenerOptions {
@@ -32,7 +32,7 @@ export class EventsService extends Service {
32
32
 
33
33
  private listeners: Record<string, { priorities: number[]; handlers: Record<number, EventListener[]> }> = {};
34
34
 
35
- protected async boot(): Promise<void> {
35
+ protected override async boot(): Promise<void> {
36
36
  Object.entries(globalThis.__aerogelEvents__ ?? {}).forEach(([event, listener]) =>
37
37
  this.on(event as string, listener as EventListener));
38
38
  }
@@ -11,9 +11,9 @@ import {
11
11
  import type { Constructor, Nullable } from '@noeldemartin/utils';
12
12
  import type { Store } from 'pinia';
13
13
 
14
- import ServiceBootError from '@/errors/ServiceBootError';
15
- import { defineServiceStore } from '@/services/store';
16
- import type { Unref } from '@/utils/vue';
14
+ import ServiceBootError from '@aerogel/core/errors/ServiceBootError';
15
+ import { defineServiceStore } from '@aerogel/core/services/store';
16
+ import type { Unref } from '@aerogel/core/utils/vue';
17
17
 
18
18
  export type ServiceState = Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
19
19
  export type DefaultServiceState = any; // eslint-disable-line @typescript-eslint/no-explicit-any
@@ -32,7 +32,7 @@ export type StateWatchers<TService extends Service, TState extends ServiceState>
32
32
  export type ServiceWithState<
33
33
  State extends ServiceState = ServiceState,
34
34
  ComputedState extends ServiceState = {},
35
- ServiceStorage = Partial<State>
35
+ ServiceStorage = Partial<State>,
36
36
  > = Constructor<Unref<State>> &
37
37
  Constructor<ComputedState> &
38
38
  Constructor<Service<Unref<State>, ComputedState, Unref<ServiceStorage>>>;
@@ -40,7 +40,7 @@ export type ServiceWithState<
40
40
  export function defineServiceState<
41
41
  State extends ServiceState = ServiceState,
42
42
  ComputedState extends ServiceState = {},
43
- ServiceStorage = Partial<State>
43
+ ServiceStorage = Partial<State>,
44
44
  >(options: {
45
45
  name: string;
46
46
  initialState: State | (() => State);
@@ -52,17 +52,17 @@ export function defineServiceState<
52
52
  }): ServiceWithState<State, ComputedState, ServiceStorage> {
53
53
  return class extends Service<Unref<State>, ComputedState, ServiceStorage> {
54
54
 
55
- public static persist = (options.persist as string[]) ?? [];
55
+ public static override persist = (options.persist as string[]) ?? [];
56
56
 
57
- protected usesStore(): boolean {
57
+ protected override usesStore(): boolean {
58
58
  return true;
59
59
  }
60
60
 
61
- protected getName(): string | null {
61
+ protected override getName(): string | null {
62
62
  return options.name ?? null;
63
63
  }
64
64
 
65
- protected getInitialState(): Unref<State> {
65
+ protected override getInitialState(): Unref<State> {
66
66
  if (typeof options.initialState === 'function') {
67
67
  return options.initialState();
68
68
  }
@@ -86,19 +86,19 @@ export function defineServiceState<
86
86
  }, {} as Unref<State>);
87
87
  }
88
88
 
89
- protected getComputedStateDefinition(): ComputedStateDefinition<Unref<State>, ComputedState> {
89
+ protected override getComputedStateDefinition(): ComputedStateDefinition<Unref<State>, ComputedState> {
90
90
  return (options.computed ?? {}) as ComputedStateDefinition<Unref<State>, ComputedState>;
91
91
  }
92
92
 
93
- protected getStateWatchers(): StateWatchers<Service, Unref<State>> {
93
+ protected override getStateWatchers(): StateWatchers<Service, Unref<State>> {
94
94
  return (options.watch ?? {}) as StateWatchers<Service, Unref<State>>;
95
95
  }
96
96
 
97
- protected serializePersistedState(state: Partial<State>): ServiceStorage {
97
+ protected override serializePersistedState(state: Partial<State>): ServiceStorage {
98
98
  return options.serialize?.(state) ?? (state as ServiceStorage);
99
99
  }
100
100
 
101
- protected deserializePersistedState(state: ServiceStorage): Partial<State> {
101
+ protected override deserializePersistedState(state: ServiceStorage): Partial<State> {
102
102
  return options.restore?.(state) ?? (state as Partial<State>);
103
103
  }
104
104
 
@@ -108,7 +108,7 @@ export function defineServiceState<
108
108
  export default class Service<
109
109
  State extends ServiceState = DefaultServiceState,
110
110
  ComputedState extends ServiceState = {},
111
- ServiceStorage = Partial<State>
111
+ ServiceStorage = Partial<State>,
112
112
  > extends MagicObject {
113
113
 
114
114
  public static persist: string[] = [];
@@ -142,9 +142,9 @@ export default class Service<
142
142
  return this._booted;
143
143
  }
144
144
 
145
- public static<T extends typeof Service>(): T;
146
- public static<T extends typeof Service, K extends keyof T>(property: K): T[K];
147
- public static<T extends typeof Service, K extends keyof T>(property?: K): T | T[K] {
145
+ public override static<T extends typeof Service>(): T;
146
+ public override static<T extends typeof Service, K extends keyof T>(property: K): T[K];
147
+ public override static<T extends typeof Service, K extends keyof T>(property?: K): T | T[K] {
148
148
  return super.static<T, K>(property as K);
149
149
  }
150
150
 
@@ -182,10 +182,10 @@ export default class Service<
182
182
  const store = this._store as any;
183
183
 
184
184
  if (property) {
185
- return store ? store[property] : undefined;
185
+ return store ? store[property] : (undefined as State[P]);
186
186
  }
187
187
 
188
- return store ? store : {};
188
+ return store ? store : ({} as State);
189
189
  }
190
190
 
191
191
  public setState<P extends keyof State>(property: P, value: State[P]): void;
@@ -219,7 +219,7 @@ export default class Service<
219
219
  this.onPersistentStateUpdated(state);
220
220
  }
221
221
 
222
- protected __get(property: string): unknown {
222
+ protected override __get(property: string): unknown {
223
223
  if (this.hasState(property)) {
224
224
  return this.getState(property);
225
225
  }
@@ -227,7 +227,7 @@ export default class Service<
227
227
  return super.__get(property);
228
228
  }
229
229
 
230
- protected __set(property: string, value: unknown): void {
230
+ protected override __set(property: string, value: unknown): void {
231
231
  this.setState({ [property]: value } as Partial<State>);
232
232
  }
233
233
 
@@ -1,7 +1,7 @@
1
1
  import { facade } from '@noeldemartin/utils';
2
2
 
3
- import Events from '@/services/Events';
4
- import Service from '@/services/Service';
3
+ import Events from '@aerogel/core/services/Events';
4
+ import Service from '@aerogel/core/services/Service';
5
5
 
6
6
  export class StorageService extends Service {
7
7
 
@@ -13,7 +13,7 @@ export class StorageService extends Service {
13
13
 
14
14
  export default facade(StorageService);
15
15
 
16
- declare module '@/services/Events' {
16
+ declare module '@aerogel/core/services/Events' {
17
17
  export interface EventsPayload {
18
18
  'purge-storage': void;
19
19
  }
@@ -1,6 +1,7 @@
1
1
  import type { App as VueApp } from 'vue';
2
2
 
3
- import { definePlugin } from '@/plugins';
3
+ import { definePlugin } from '@aerogel/core/plugins';
4
+ import { isDevelopment, isTesting } from '@noeldemartin/utils';
4
5
 
5
6
  import App from './App';
6
7
  import Cache from './Cache';
@@ -39,7 +40,7 @@ export async function bootServices(app: VueApp, services: Record<string, Service
39
40
 
40
41
  Object.assign(app.config.globalProperties, services);
41
42
 
42
- if (App.development || App.testing) {
43
+ if (isDevelopment() || isTesting()) {
43
44
  Object.assign(globalThis, services);
44
45
  }
45
46
  }
@@ -57,12 +58,12 @@ export default definePlugin({
57
58
  },
58
59
  });
59
60
 
60
- declare module '@/bootstrap/options' {
61
+ declare module '@aerogel/core/bootstrap/options' {
61
62
  export interface AerogelOptions {
62
63
  services?: Record<string, Service>;
63
64
  }
64
65
  }
65
66
 
66
- declare module '@vue/runtime-core' {
67
+ declare module 'vue' {
67
68
  interface ComponentCustomProperties extends Services {}
68
69
  }
@@ -2,14 +2,14 @@ import { objectOnly } from '@noeldemartin/utils';
2
2
 
3
3
  export type Replace<
4
4
  TOriginal extends Record<string, unknown>,
5
- TReplacements extends Partial<Record<keyof TOriginal, unknown>>
5
+ TReplacements extends Partial<Record<keyof TOriginal, unknown>>,
6
6
  > = {
7
7
  [K in keyof TOriginal]: TReplacements extends Record<K, infer Replacement> ? Replacement : TOriginal[K];
8
8
  };
9
9
 
10
10
  export function replaceExisting<
11
11
  TOriginal extends Record<string, unknown>,
12
- TReplacements extends Partial<Record<keyof TOriginal, unknown>>
12
+ TReplacements extends Partial<Record<keyof TOriginal, unknown>>,
13
13
  >(original: TOriginal, replacements: TReplacements): Replace<TOriginal, TReplacements> {
14
14
  return {
15
15
  ...original,
@@ -1,7 +1,8 @@
1
+ import { isTesting } from '@noeldemartin/utils';
1
2
  import type { GetClosureArgs } from '@noeldemartin/utils';
2
3
 
3
- import Events from '@/services/Events';
4
- import { definePlugin } from '@/plugins';
4
+ import Events from '@aerogel/core/services/Events';
5
+ import { definePlugin } from '@aerogel/core/plugins';
5
6
 
6
7
  export interface AerogelTestingRuntime {
7
8
  on: (typeof Events)['on'];
@@ -9,7 +10,7 @@ export interface AerogelTestingRuntime {
9
10
 
10
11
  export default definePlugin({
11
12
  async install() {
12
- if (import.meta.env.MODE !== 'testing') {
13
+ if (!isTesting()) {
13
14
  return;
14
15
  }
15
16
 
@@ -1,27 +1,11 @@
1
- import { mock, tap, toString } from '@noeldemartin/utils';
1
+ import { FakeLocalStorage } from '@noeldemartin/testing';
2
2
  import { beforeEach, vi } from 'vitest';
3
3
 
4
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
- tap(globalThis, (global: any) => {
6
- const localStorage: Record<string, string> = {};
7
-
8
- global.jest = vi;
9
- global.navigator = { languages: ['en'] };
10
- global.localStorage = mock<Storage>({
11
- getItem: (key) => localStorage[key] ?? null,
12
- setItem(key, value) {
13
- localStorage[key] = toString(value);
14
- },
15
- });
16
- });
17
-
18
4
  vi.mock('dompurify', async () => {
19
5
  return { default: { sanitize: (html: string) => html } };
20
6
  });
21
7
 
22
8
  beforeEach(() => {
23
- vi.stubGlobal('document', {
24
- querySelector: () => null,
25
- getElementById: () => null,
26
- });
9
+ FakeLocalStorage.reset();
10
+ FakeLocalStorage.patchGlobal();
27
11
  });
@@ -1,10 +1,10 @@
1
1
  import type { Component } from 'vue';
2
2
 
3
- import { defineServiceState } from '@/services/Service';
3
+ import { defineServiceState } from '@aerogel/core/services/Service';
4
4
 
5
5
  import { Layouts, getCurrentLayout } from './utils';
6
6
 
7
- export interface Modal<T = unknown> {
7
+ export interface UIModal<T = unknown> {
8
8
  id: string;
9
9
  properties: Record<string, unknown>;
10
10
  component: Component;
@@ -12,11 +12,16 @@ export interface Modal<T = unknown> {
12
12
  afterClose: Promise<T | undefined>;
13
13
  }
14
14
 
15
+ export interface UIModalContext {
16
+ modal: UIModal;
17
+ childIndex?: number;
18
+ }
19
+
15
20
  export interface ModalComponent<
16
21
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
- Properties extends Record<string, unknown> = Record<string, unknown>,
22
+ Properties extends object = object,
18
23
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
19
- Result = unknown
24
+ Result = unknown,
20
25
  > {}
21
26
 
22
27
  export interface Snackbar {
@@ -28,7 +33,7 @@ export interface Snackbar {
28
33
  export default defineServiceState({
29
34
  name: 'ui',
30
35
  initialState: {
31
- modals: [] as Modal[],
36
+ modals: [] as UIModal[],
32
37
  snackbars: [] as Snackbar[],
33
38
  layout: getCurrentLayout(),
34
39
  },
package/src/ui/UI.ts CHANGED
@@ -1,18 +1,21 @@
1
- import { after, facade, fail, required, uuid } from '@noeldemartin/utils';
1
+ import { after, facade, fail, isDevelopment, required, uuid } from '@noeldemartin/utils';
2
2
  import { markRaw, nextTick } from 'vue';
3
3
  import type { Component } from 'vue';
4
4
  import type { ObjectValues } from '@noeldemartin/utils';
5
5
 
6
- import App from '@/services/App';
7
- import Events from '@/services/Events';
8
- import type { AcceptRefs } from '@/utils';
9
- import type { Color } from '@/components/constants';
10
- import type { SnackbarAction, SnackbarColor } from '@/components/headless/snackbars';
11
- import type { AGAlertModalProps, AGConfirmModalProps, AGLoadingModalProps, AGPromptModalProps } from '@/components';
6
+ import App from '@aerogel/core/services/App';
7
+ import Events from '@aerogel/core/services/Events';
8
+ import type { AcceptRefs } from '@aerogel/core/utils';
9
+ import type { AlertModalProps } from '@aerogel/core/components/contracts/AlertModal';
10
+ import type { ButtonVariant } from '@aerogel/core/components/contracts/Button';
11
+ import type { ConfirmModalCheckboxes, ConfirmModalProps } from '@aerogel/core/components/contracts/ConfirmModal';
12
+ import type { LoadingModalProps } from '@aerogel/core/components/contracts/LoadingModal';
13
+ import type { PromptModalProps } from '@aerogel/core/components/contracts/PromptModal';
14
+ import type { SnackbarAction, SnackbarColor } from '@aerogel/core/components/headless/snackbars';
12
15
 
13
16
  import Service from './UI.state';
14
17
  import { MOBILE_BREAKPOINT, getCurrentLayout } from './utils';
15
- import type { Modal, ModalComponent, Snackbar } from './UI.state';
18
+ import type { ModalComponent, Snackbar, UIModal } from './UI.state';
16
19
 
17
20
  interface ModalCallbacks<T = unknown> {
18
21
  willClose(result: T | undefined): void;
@@ -20,9 +23,8 @@ interface ModalCallbacks<T = unknown> {
20
23
  }
21
24
 
22
25
  type ModalProperties<TComponent> = TComponent extends ModalComponent<infer TProperties, unknown> ? TProperties : never;
23
- type ModalResult<TComponent> = TComponent extends ModalComponent<Record<string, unknown>, infer TResult>
24
- ? TResult
25
- : never;
26
+ type ModalResult<TComponent> =
27
+ TComponent extends ModalComponent<Record<string, unknown>, infer TResult> ? TResult : never;
26
28
 
27
29
  export const UIComponents = {
28
30
  AlertModal: 'alert-modal',
@@ -36,13 +38,11 @@ export const UIComponents = {
36
38
 
37
39
  export type UIComponent = ObjectValues<typeof UIComponents>;
38
40
 
39
- export type ConfirmCheckboxes = Record<string, { label: string; default?: boolean; required?: boolean }>;
40
-
41
41
  export type ConfirmOptions = AcceptRefs<{
42
42
  acceptText?: string;
43
- acceptColor?: Color;
43
+ acceptVariant?: ButtonVariant;
44
44
  cancelText?: string;
45
- cancelColor?: Color;
45
+ cancelVariant?: ButtonVariant;
46
46
  actions?: Record<string, () => unknown>;
47
47
  required?: boolean;
48
48
  }>;
@@ -53,7 +53,8 @@ export type LoadingOptions = AcceptRefs<{
53
53
  progress?: number;
54
54
  }>;
55
55
 
56
- export interface ConfirmOptionsWithCheckboxes<T extends ConfirmCheckboxes = ConfirmCheckboxes> extends ConfirmOptions {
56
+ export interface ConfirmOptionsWithCheckboxes<T extends ConfirmModalCheckboxes = ConfirmModalCheckboxes>
57
+ extends ConfirmOptions {
57
58
  checkboxes?: T;
58
59
  }
59
60
 
@@ -62,9 +63,9 @@ export type PromptOptions = AcceptRefs<{
62
63
  defaultValue?: string;
63
64
  placeholder?: string;
64
65
  acceptText?: string;
65
- acceptColor?: Color;
66
+ acceptVariant?: ButtonVariant;
66
67
  cancelText?: string;
67
- cancelColor?: Color;
68
+ cancelVariant?: ButtonVariant;
68
69
  trim?: boolean;
69
70
  }>;
70
71
 
@@ -86,7 +87,7 @@ export class UIService extends Service {
86
87
  public alert(message: string): void;
87
88
  public alert(title: string, message: string): void;
88
89
  public alert(messageOrTitle: string, message?: string): void {
89
- const getProperties = (): AGAlertModalProps => {
90
+ const getProperties = (): AlertModalProps => {
90
91
  if (typeof message !== 'string') {
91
92
  return { message: messageOrTitle };
92
93
  }
@@ -97,14 +98,17 @@ export class UIService extends Service {
97
98
  };
98
99
  };
99
100
 
100
- this.openModal(this.requireComponent(UIComponents.AlertModal), getProperties());
101
+ this.openModal<ModalComponent<AlertModalProps>>(
102
+ this.requireComponent(UIComponents.AlertModal),
103
+ getProperties(),
104
+ );
101
105
  }
102
106
 
103
107
  /* eslint-disable max-len */
104
108
  public async confirm(message: string, options?: ConfirmOptions): Promise<boolean>;
105
109
  public async confirm(title: string, message: string, options?: ConfirmOptions): Promise<boolean>;
106
- public async confirm<T extends ConfirmCheckboxes>(message: string, options?: ConfirmOptionsWithCheckboxes<T>): Promise<[boolean, Record<keyof T, boolean>]>; // prettier-ignore
107
- public async confirm<T extends ConfirmCheckboxes>(title: string, message: string, options?: ConfirmOptionsWithCheckboxes<T>): Promise<[boolean, Record<keyof T, boolean>]>; // prettier-ignore
110
+ public async confirm<T extends ConfirmModalCheckboxes>(message: string, options?: ConfirmOptionsWithCheckboxes<T>): Promise<[boolean, Record<keyof T, boolean>]>; // prettier-ignore
111
+ public async confirm<T extends ConfirmModalCheckboxes>(title: string, message: string, options?: ConfirmOptionsWithCheckboxes<T>): Promise<[boolean, Record<keyof T, boolean>]>; // prettier-ignore
108
112
  /* eslint-enable max-len */
109
113
 
110
114
  public async confirm(
@@ -112,7 +116,7 @@ export class UIService extends Service {
112
116
  messageOrOptions?: string | ConfirmOptions | ConfirmOptionsWithCheckboxes,
113
117
  options?: ConfirmOptions | ConfirmOptionsWithCheckboxes,
114
118
  ): Promise<boolean | [boolean, Record<string, boolean>]> {
115
- const getProperties = (): AGConfirmModalProps => {
119
+ const getProperties = (): AcceptRefs<ConfirmModalProps> => {
116
120
  if (typeof messageOrOptions !== 'string') {
117
121
  return {
118
122
  ...(messageOrOptions ?? {}),
@@ -128,13 +132,20 @@ export class UIService extends Service {
128
132
  required: !!options?.required,
129
133
  };
130
134
  };
135
+
136
+ type ConfirmModalComponent = ModalComponent<
137
+ AcceptRefs<ConfirmModalProps>,
138
+ boolean | [boolean, Record<string, boolean>]
139
+ >;
140
+
131
141
  const properties = getProperties();
132
- const modal = await this.openModal<
133
- ModalComponent<AGConfirmModalProps, boolean | [boolean, Record<string, boolean>]>
134
- >(this.requireComponent(UIComponents.ConfirmModal), properties);
142
+ const modal = await this.openModal<ConfirmModalComponent>(
143
+ this.requireComponent(UIComponents.ConfirmModal),
144
+ properties,
145
+ );
135
146
  const result = await modal.beforeClose;
136
147
 
137
- const confirmed = typeof result === 'object' ? result[0] : result ?? false;
148
+ const confirmed = typeof result === 'object' ? result[0] : (result ?? false);
138
149
  const checkboxes =
139
150
  typeof result === 'object'
140
151
  ? result[1]
@@ -151,7 +162,7 @@ export class UIService extends Service {
151
162
  continue;
152
163
  }
153
164
 
154
- if (confirmed && App.development) {
165
+ if (confirmed && isDevelopment()) {
155
166
  // eslint-disable-next-line no-console
156
167
  console.warn(`Confirmed confirm modal was suppressed because required '${name}' checkbox was missing`);
157
168
  }
@@ -170,22 +181,22 @@ export class UIService extends Service {
170
181
  options?: PromptOptions,
171
182
  ): Promise<string | null> {
172
183
  const trim = options?.trim ?? true;
173
- const getProperties = (): AGPromptModalProps => {
184
+ const getProperties = (): PromptModalProps => {
174
185
  if (typeof messageOrOptions !== 'string') {
175
186
  return {
176
187
  message: messageOrTitle,
177
188
  ...(messageOrOptions ?? {}),
178
- } as AGPromptModalProps;
189
+ } as PromptModalProps;
179
190
  }
180
191
 
181
192
  return {
182
193
  title: messageOrTitle,
183
194
  message: messageOrOptions,
184
195
  ...(options ?? {}),
185
- } as AGPromptModalProps;
196
+ } as PromptModalProps;
186
197
  };
187
198
 
188
- const modal = await this.openModal<ModalComponent<AGPromptModalProps, string | null>>(
199
+ const modal = await this.openModal<ModalComponent<PromptModalProps, string | null>>(
189
200
  this.requireComponent(UIComponents.PromptModal),
190
201
  getProperties(),
191
202
  );
@@ -203,7 +214,7 @@ export class UIService extends Service {
203
214
  operation?: Promise<T> | (() => T),
204
215
  ): Promise<T> {
205
216
  const processOperation = (o: Promise<T> | (() => T)) => (typeof o === 'function' ? Promise.resolve(o()) : o);
206
- const processArgs = (): { operationPromise: Promise<T>; props?: AGLoadingModalProps } => {
217
+ const processArgs = (): { operationPromise: Promise<T>; props?: AcceptRefs<LoadingModalProps> } => {
207
218
  if (typeof operationOrMessageOrOptions === 'string') {
208
219
  return {
209
220
  props: { message: operationOrMessageOrOptions },
@@ -225,7 +236,9 @@ export class UIService extends Service {
225
236
  const modal = await this.openModal(this.requireComponent(UIComponents.LoadingModal), props);
226
237
 
227
238
  try {
228
- const [result] = await Promise.all([operationPromise, after({ seconds: 1 })]);
239
+ const result = await operationPromise;
240
+
241
+ await after({ ms: 500 });
229
242
 
230
243
  return result;
231
244
  } finally {
@@ -259,10 +272,10 @@ export class UIService extends Service {
259
272
  public async openModal<TModalComponent extends ModalComponent>(
260
273
  component: TModalComponent,
261
274
  properties?: ModalProperties<TModalComponent>,
262
- ): Promise<Modal<ModalResult<TModalComponent>>> {
275
+ ): Promise<UIModal<ModalResult<TModalComponent>>> {
263
276
  const id = uuid();
264
277
  const callbacks: Partial<ModalCallbacks<ModalResult<TModalComponent>>> = {};
265
- const modal: Modal<ModalResult<TModalComponent>> = {
278
+ const modal: UIModal<ModalResult<TModalComponent>> = {
266
279
  id,
267
280
  properties: properties ?? {},
268
281
  component: markRaw(component),
@@ -302,7 +315,7 @@ export class UIService extends Service {
302
315
  }
303
316
  }
304
317
 
305
- protected async boot(): Promise<void> {
318
+ protected override async boot(): Promise<void> {
306
319
  this.watchModalEvents();
307
320
  this.watchMountedEvent();
308
321
  this.watchViewportBreakpoints();
@@ -373,13 +386,13 @@ export class UIService extends Service {
373
386
 
374
387
  export default facade(UIService);
375
388
 
376
- declare module '@/services/Events' {
389
+ declare module '@aerogel/core/services/Events' {
377
390
  export interface EventsPayload {
378
391
  'close-modal': { id: string; result?: unknown };
379
392
  'hide-modal': { id: string };
380
393
  'hide-overlays-backdrop': void;
381
- 'modal-closed': { modal: Modal; result?: unknown };
382
- 'modal-will-close': { modal: Modal; result?: unknown };
394
+ 'modal-closed': { modal: UIModal; result?: unknown };
395
+ 'modal-will-close': { modal: UIModal; result?: unknown };
383
396
  'show-modal': { id: string };
384
397
  'show-overlays-backdrop': void;
385
398
  }
package/src/ui/index.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import type { Component } from 'vue';
2
2
 
3
- import { bootServices } from '@/services';
4
- import { definePlugin } from '@/plugins';
3
+ import AGSnackbar from '@aerogel/core/components/snackbars/AGSnackbar.vue';
4
+ import AGStartupCrash from '@aerogel/core/components/lib/AGStartupCrash.vue';
5
+ import AlertModal from '@aerogel/core/components/ui/AlertModal.vue';
6
+ import ConfirmModal from '@aerogel/core/components/ui/ConfirmModal.vue';
7
+ import ErrorReportModal from '@aerogel/core/components/ui/ErrorReportModal.vue';
8
+ import LoadingModal from '@aerogel/core/components/ui/LoadingModal.vue';
9
+ import PromptModal from '@aerogel/core/components/ui/PromptModal.vue';
10
+ import { bootServices } from '@aerogel/core/services';
11
+ import { definePlugin } from '@aerogel/core/plugins';
5
12
 
6
13
  import UI, { UIComponents } from './UI';
7
- import AGAlertModal from '../components/modals/AGAlertModal.vue';
8
- import AGConfirmModal from '../components/modals/AGConfirmModal.vue';
9
- import AGErrorReportModal from '../components/modals/AGErrorReportModal.vue';
10
- import AGLoadingModal from '../components/modals/AGLoadingModal.vue';
11
- import AGPromptModal from '../components/modals/AGPromptModal.vue';
12
- import AGSnackbar from '../components/snackbars/AGSnackbar.vue';
13
- import AGStartupCrash from '../components/lib/AGStartupCrash.vue';
14
14
  import type { UIComponent } from './UI';
15
15
 
16
16
  const services = { $ui: UI };
@@ -24,11 +24,11 @@ export type UIServices = typeof services;
24
24
  export default definePlugin({
25
25
  async install(app, options) {
26
26
  const defaultComponents = {
27
- [UIComponents.AlertModal]: AGAlertModal,
28
- [UIComponents.ConfirmModal]: AGConfirmModal,
29
- [UIComponents.ErrorReportModal]: AGErrorReportModal,
30
- [UIComponents.LoadingModal]: AGLoadingModal,
31
- [UIComponents.PromptModal]: AGPromptModal,
27
+ [UIComponents.AlertModal]: AlertModal,
28
+ [UIComponents.ConfirmModal]: ConfirmModal,
29
+ [UIComponents.ErrorReportModal]: ErrorReportModal,
30
+ [UIComponents.LoadingModal]: LoadingModal,
31
+ [UIComponents.PromptModal]: PromptModal,
32
32
  [UIComponents.Snackbar]: AGSnackbar,
33
33
  [UIComponents.StartupCrash]: AGStartupCrash,
34
34
  };
@@ -42,12 +42,12 @@ export default definePlugin({
42
42
  },
43
43
  });
44
44
 
45
- declare module '@/bootstrap/options' {
45
+ declare module '@aerogel/core/bootstrap/options' {
46
46
  export interface AerogelOptions {
47
47
  components?: Partial<Record<UIComponent, Component>>;
48
48
  }
49
49
  }
50
50
 
51
- declare module '@/services' {
51
+ declare module '@aerogel/core/services' {
52
52
  export interface Services extends UIServices {}
53
53
  }
@@ -1,13 +1,13 @@
1
1
  import { onUnmounted } from 'vue';
2
2
 
3
- import Events from '@/services/Events';
3
+ import Events from '@aerogel/core/services/Events';
4
4
  import type {
5
5
  EventListener,
6
6
  EventWithPayload,
7
7
  EventWithoutPayload,
8
8
  EventsPayload,
9
9
  UnknownEvent,
10
- } from '@/services/Events';
10
+ } from '@aerogel/core/services/Events';
11
11
 
12
12
  export function useEvent<Event extends EventWithoutPayload>(event: Event, listener: () => unknown): void;
13
13
  export function useEvent<Event extends EventWithPayload>(
@@ -1,11 +1,12 @@
1
1
  import { objectWithout } from '@noeldemartin/utils';
2
2
  import { computed, useAttrs } from 'vue';
3
+ import type { ClassValue } from 'clsx';
3
4
  import type { ComputedRef } from 'vue';
4
5
 
5
- export function useInputAttrs(): [ComputedRef<{}>, ComputedRef<unknown>] {
6
+ export function useInputAttrs(): [ComputedRef<{}>, ComputedRef<ClassValue>] {
6
7
  const attrs = useAttrs();
7
- const className = computed(() => attrs.class);
8
+ const classes = computed(() => attrs.class);
8
9
  const inputAttrs = computed(() => objectWithout(attrs, 'class'));
9
10
 
10
- return [inputAttrs, className];
11
+ return [inputAttrs, classes as ComputedRef<ClassValue>];
11
12
  }