@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.
- package/dist/aerogel-core.d.ts +1223 -1792
- package/dist/aerogel-core.js +2968 -0
- package/dist/aerogel-core.js.map +1 -0
- package/package.json +27 -37
- package/src/bootstrap/bootstrap.test.ts +4 -7
- package/src/bootstrap/index.ts +14 -15
- package/src/bootstrap/options.ts +1 -1
- package/src/components/{AGAppLayout.vue → AppLayout.vue} +4 -4
- package/src/components/{AGAppModals.vue → AppModals.vue} +3 -4
- package/src/components/{AGAppOverlays.vue → AppOverlays.vue} +5 -5
- package/src/components/composition.ts +1 -1
- package/src/components/contracts/AlertModal.ts +4 -0
- package/src/components/contracts/Button.ts +15 -0
- package/src/components/contracts/ConfirmModal.ts +41 -0
- package/src/components/contracts/ErrorReportModal.ts +29 -0
- package/src/components/contracts/Input.ts +26 -0
- package/src/components/contracts/LoadingModal.ts +18 -0
- package/src/components/contracts/Modal.ts +9 -0
- package/src/components/contracts/PromptModal.ts +28 -0
- package/src/components/contracts/index.ts +7 -0
- package/src/components/contracts/shared.ts +9 -0
- package/src/components/forms/AGSelect.vue +11 -17
- package/src/components/forms/index.ts +0 -4
- package/src/components/headless/HeadlessButton.vue +45 -0
- package/src/components/headless/HeadlessInput.vue +59 -0
- package/src/components/headless/{forms/AGHeadlessInputDescription.vue → HeadlessInputDescription.vue} +6 -7
- package/src/components/headless/{forms/AGHeadlessInputError.vue → HeadlessInputError.vue} +4 -8
- package/src/components/headless/{forms/AGHeadlessInputInput.vue → HeadlessInputInput.vue} +10 -19
- package/src/components/headless/{forms/AGHeadlessInputLabel.vue → HeadlessInputLabel.vue} +3 -7
- package/src/components/headless/{forms/AGHeadlessInputTextArea.vue → HeadlessInputTextArea.vue} +6 -9
- package/src/components/headless/{modals/AGHeadlessModal.vue → HeadlessModal.vue} +16 -24
- package/src/components/headless/HeadlessModalContent.vue +24 -0
- package/src/components/headless/HeadlessModalOverlay.vue +12 -0
- package/src/components/headless/HeadlessModalTitle.vue +12 -0
- package/src/components/headless/forms/AGHeadlessSelect.ts +3 -3
- package/src/components/headless/forms/AGHeadlessSelect.vue +16 -16
- package/src/components/headless/forms/AGHeadlessSelectError.vue +2 -2
- package/src/components/headless/forms/AGHeadlessSelectOption.vue +10 -18
- package/src/components/headless/forms/AGHeadlessSelectOptions.vue +19 -0
- package/src/components/headless/forms/AGHeadlessSelectTrigger.vue +25 -0
- package/src/components/headless/forms/composition.ts +2 -2
- package/src/components/headless/forms/index.ts +2 -12
- package/src/components/headless/index.ts +12 -1
- package/src/components/headless/snackbars/index.ts +3 -3
- package/src/components/index.ts +5 -5
- package/src/components/lib/AGErrorMessage.vue +5 -5
- package/src/components/lib/AGMeasured.vue +2 -2
- package/src/components/lib/AGStartupCrash.vue +8 -8
- package/src/components/lib/index.ts +0 -3
- package/src/components/snackbars/AGSnackbar.vue +10 -8
- package/src/components/ui/AlertModal.vue +13 -0
- package/src/components/ui/Button.vue +58 -0
- package/src/components/ui/Checkbox.vue +49 -0
- package/src/components/ui/ConfirmModal.vue +42 -0
- package/src/components/ui/ErrorReportModal.vue +62 -0
- package/src/components/{modals/AGErrorReportModalButtons.vue → ui/ErrorReportModalButtons.vue} +29 -20
- package/src/components/ui/ErrorReportModalTitle.vue +24 -0
- package/src/components/{forms/AGForm.vue → ui/Form.vue} +4 -5
- package/src/components/ui/Input.vue +52 -0
- package/src/components/ui/Link.vue +12 -0
- package/src/components/ui/LoadingModal.vue +32 -0
- package/src/components/ui/Markdown.vue +62 -0
- package/src/components/ui/Modal.vue +55 -0
- package/src/components/{modals/AGModalContext.vue → ui/ModalContext.vue} +7 -9
- package/src/components/ui/ProgressBar.vue +50 -0
- package/src/components/ui/PromptModal.vue +35 -0
- package/src/components/ui/index.ts +16 -0
- package/src/components/utils.ts +106 -9
- package/src/directives/index.ts +9 -5
- package/src/directives/measure.ts +1 -1
- package/src/errors/Errors.state.ts +1 -1
- package/src/errors/Errors.ts +14 -14
- package/src/errors/index.ts +9 -6
- package/src/errors/utils.ts +1 -1
- package/src/forms/{Form.test.ts → FormController.test.ts} +5 -4
- package/src/forms/{Form.ts → FormController.ts} +22 -19
- package/src/forms/composition.ts +4 -4
- package/src/forms/index.ts +2 -2
- package/src/forms/utils.ts +2 -2
- package/src/index.css +8 -0
- package/src/jobs/Job.ts +2 -2
- package/src/lang/DefaultLangProvider.ts +7 -4
- package/src/lang/Lang.state.ts +1 -1
- package/src/lang/Lang.ts +1 -1
- package/src/lang/index.ts +8 -6
- package/src/plugins/Plugin.ts +1 -1
- package/src/plugins/index.ts +10 -7
- package/src/services/App.state.ts +4 -3
- package/src/services/App.ts +4 -4
- package/src/services/Cache.ts +1 -1
- package/src/services/Events.ts +2 -2
- package/src/services/Service.ts +21 -21
- package/src/services/Storage.ts +3 -3
- package/src/services/index.ts +5 -4
- package/src/services/utils.ts +2 -2
- package/src/testing/index.ts +4 -3
- package/src/testing/setup.ts +3 -19
- package/src/ui/UI.state.ts +10 -5
- package/src/ui/UI.ts +53 -40
- package/src/ui/index.ts +16 -16
- package/src/utils/composition/events.ts +2 -2
- package/src/utils/composition/forms.ts +4 -3
- package/src/utils/markdown.ts +3 -5
- package/src/utils/vdom.ts +31 -0
- package/src/utils/vue.ts +7 -12
- package/dist/aerogel-core.cjs.js +0 -2
- package/dist/aerogel-core.cjs.js.map +0 -1
- package/dist/aerogel-core.esm.js +0 -2
- package/dist/aerogel-core.esm.js.map +0 -1
- package/histoire.config.ts +0 -7
- package/noeldemartin.config.js +0 -5
- package/postcss.config.js +0 -6
- package/src/assets/histoire.css +0 -3
- package/src/components/forms/AGButton.vue +0 -44
- package/src/components/forms/AGCheckbox.vue +0 -41
- package/src/components/forms/AGInput.vue +0 -40
- package/src/components/headless/forms/AGHeadlessButton.ts +0 -3
- package/src/components/headless/forms/AGHeadlessButton.vue +0 -62
- package/src/components/headless/forms/AGHeadlessInput.ts +0 -34
- package/src/components/headless/forms/AGHeadlessInput.vue +0 -70
- package/src/components/headless/forms/AGHeadlessSelectButton.vue +0 -24
- package/src/components/headless/forms/AGHeadlessSelectLabel.vue +0 -24
- package/src/components/headless/forms/AGHeadlessSelectOptions.ts +0 -3
- package/src/components/headless/modals/AGHeadlessModal.ts +0 -36
- package/src/components/headless/modals/AGHeadlessModalPanel.vue +0 -32
- package/src/components/headless/modals/AGHeadlessModalTitle.vue +0 -23
- package/src/components/headless/modals/index.ts +0 -4
- package/src/components/interfaces.ts +0 -24
- package/src/components/lib/AGLink.vue +0 -9
- package/src/components/lib/AGMarkdown.vue +0 -54
- package/src/components/lib/AGProgressBar.vue +0 -45
- package/src/components/modals/AGAlertModal.ts +0 -18
- package/src/components/modals/AGAlertModal.vue +0 -14
- package/src/components/modals/AGConfirmModal.ts +0 -42
- package/src/components/modals/AGConfirmModal.vue +0 -26
- package/src/components/modals/AGErrorReportModal.ts +0 -49
- package/src/components/modals/AGErrorReportModal.vue +0 -54
- package/src/components/modals/AGErrorReportModalTitle.vue +0 -25
- package/src/components/modals/AGLoadingModal.ts +0 -29
- package/src/components/modals/AGLoadingModal.vue +0 -15
- package/src/components/modals/AGModal.ts +0 -11
- package/src/components/modals/AGModal.vue +0 -39
- package/src/components/modals/AGModalContext.ts +0 -8
- package/src/components/modals/AGModalTitle.vue +0 -9
- package/src/components/modals/AGPromptModal.ts +0 -41
- package/src/components/modals/AGPromptModal.vue +0 -34
- package/src/components/modals/index.ts +0 -17
- package/src/directives/initial-focus.ts +0 -11
- package/src/main.histoire.ts +0 -1
- package/tailwind.config.js +0 -4
- package/tsconfig.json +0 -11
- package/vite.config.ts +0 -17
- /package/src/components/{AGAppSnackbars.vue → AppSnackbars.vue} +0 -0
- /package/src/{main.ts → index.ts} +0 -0
package/src/services/Cache.ts
CHANGED
package/src/services/Events.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { arrayRemove, facade, fail, tap } from '@noeldemartin/utils';
|
|
2
2
|
|
|
3
|
-
import Service from '
|
|
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
|
}
|
package/src/services/Service.ts
CHANGED
|
@@ -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 '
|
|
15
|
-
import { defineServiceStore } from '
|
|
16
|
-
import type { Unref } from '
|
|
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
|
|
package/src/services/Storage.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { facade } from '@noeldemartin/utils';
|
|
2
2
|
|
|
3
|
-
import Events from '
|
|
4
|
-
import Service from '
|
|
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 '
|
|
16
|
+
declare module '@aerogel/core/services/Events' {
|
|
17
17
|
export interface EventsPayload {
|
|
18
18
|
'purge-storage': void;
|
|
19
19
|
}
|
package/src/services/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { App as VueApp } from 'vue';
|
|
2
2
|
|
|
3
|
-
import { definePlugin } from '
|
|
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 (
|
|
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 '
|
|
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 '
|
|
67
|
+
declare module 'vue' {
|
|
67
68
|
interface ComponentCustomProperties extends Services {}
|
|
68
69
|
}
|
package/src/services/utils.ts
CHANGED
|
@@ -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,
|
package/src/testing/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { isTesting } from '@noeldemartin/utils';
|
|
1
2
|
import type { GetClosureArgs } from '@noeldemartin/utils';
|
|
2
3
|
|
|
3
|
-
import Events from '
|
|
4
|
-
import { definePlugin } from '
|
|
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 (
|
|
13
|
+
if (!isTesting()) {
|
|
13
14
|
return;
|
|
14
15
|
}
|
|
15
16
|
|
package/src/testing/setup.ts
CHANGED
|
@@ -1,27 +1,11 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
getElementById: () => null,
|
|
26
|
-
});
|
|
9
|
+
FakeLocalStorage.reset();
|
|
10
|
+
FakeLocalStorage.patchGlobal();
|
|
27
11
|
});
|
package/src/ui/UI.state.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Component } from 'vue';
|
|
2
2
|
|
|
3
|
-
import { defineServiceState } from '
|
|
3
|
+
import { defineServiceState } from '@aerogel/core/services/Service';
|
|
4
4
|
|
|
5
5
|
import { Layouts, getCurrentLayout } from './utils';
|
|
6
6
|
|
|
7
|
-
export interface
|
|
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
|
|
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
|
|
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 '
|
|
7
|
-
import Events from '
|
|
8
|
-
import type { AcceptRefs } from '
|
|
9
|
-
import type {
|
|
10
|
-
import type {
|
|
11
|
-
import type {
|
|
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 {
|
|
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> =
|
|
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
|
-
|
|
43
|
+
acceptVariant?: ButtonVariant;
|
|
44
44
|
cancelText?: string;
|
|
45
|
-
|
|
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
|
|
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
|
-
|
|
66
|
+
acceptVariant?: ButtonVariant;
|
|
66
67
|
cancelText?: string;
|
|
67
|
-
|
|
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 = ():
|
|
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(
|
|
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
|
|
107
|
-
public async confirm<T extends
|
|
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 = ():
|
|
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
|
-
|
|
134
|
-
|
|
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 &&
|
|
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 = ():
|
|
184
|
+
const getProperties = (): PromptModalProps => {
|
|
174
185
|
if (typeof messageOrOptions !== 'string') {
|
|
175
186
|
return {
|
|
176
187
|
message: messageOrTitle,
|
|
177
188
|
...(messageOrOptions ?? {}),
|
|
178
|
-
} as
|
|
189
|
+
} as PromptModalProps;
|
|
179
190
|
}
|
|
180
191
|
|
|
181
192
|
return {
|
|
182
193
|
title: messageOrTitle,
|
|
183
194
|
message: messageOrOptions,
|
|
184
195
|
...(options ?? {}),
|
|
185
|
-
} as
|
|
196
|
+
} as PromptModalProps;
|
|
186
197
|
};
|
|
187
198
|
|
|
188
|
-
const modal = await this.openModal<ModalComponent<
|
|
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?:
|
|
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
|
|
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<
|
|
275
|
+
): Promise<UIModal<ModalResult<TModalComponent>>> {
|
|
263
276
|
const id = uuid();
|
|
264
277
|
const callbacks: Partial<ModalCallbacks<ModalResult<TModalComponent>>> = {};
|
|
265
|
-
const modal:
|
|
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 '
|
|
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:
|
|
382
|
-
'modal-will-close': { modal:
|
|
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
|
|
4
|
-
import
|
|
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]:
|
|
28
|
-
[UIComponents.ConfirmModal]:
|
|
29
|
-
[UIComponents.ErrorReportModal]:
|
|
30
|
-
[UIComponents.LoadingModal]:
|
|
31
|
-
[UIComponents.PromptModal]:
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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<
|
|
6
|
+
export function useInputAttrs(): [ComputedRef<{}>, ComputedRef<ClassValue>] {
|
|
6
7
|
const attrs = useAttrs();
|
|
7
|
-
const
|
|
8
|
+
const classes = computed(() => attrs.class);
|
|
8
9
|
const inputAttrs = computed(() => objectWithout(attrs, 'class'));
|
|
9
10
|
|
|
10
|
-
return [inputAttrs,
|
|
11
|
+
return [inputAttrs, classes as ComputedRef<ClassValue>];
|
|
11
12
|
}
|