@aerogel/core 0.0.0-next.d824b40e5d06757cd9f47c9f771d916185df4f05 → 0.0.0-next.f1f5a990033d966dc0bb12d251110fbc9350dcc7
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.cjs.js +1 -1
- package/dist/aerogel-core.cjs.js.map +1 -1
- package/dist/aerogel-core.d.ts +641 -110
- package/dist/aerogel-core.esm.js +1 -1
- package/dist/aerogel-core.esm.js.map +1 -1
- package/histoire.config.ts +7 -0
- package/package.json +14 -5
- package/postcss.config.js +6 -0
- package/src/assets/histoire.css +3 -0
- package/src/bootstrap/bootstrap.test.ts +4 -3
- package/src/bootstrap/index.ts +18 -3
- package/src/components/AGAppLayout.vue +7 -2
- package/src/components/AGAppOverlays.vue +5 -1
- package/src/components/AGAppSnackbars.vue +1 -1
- package/src/components/forms/AGSelect.story.vue +28 -0
- package/src/components/forms/AGSelect.vue +53 -0
- package/src/components/forms/index.ts +5 -6
- package/src/components/headless/forms/AGHeadlessInput.ts +21 -1
- package/src/components/headless/forms/AGHeadlessInput.vue +8 -5
- package/src/components/headless/forms/AGHeadlessInputLabel.vue +8 -2
- package/src/components/headless/forms/AGHeadlessSelect.ts +39 -0
- package/src/components/headless/forms/AGHeadlessSelect.vue +76 -0
- package/src/components/headless/forms/AGHeadlessSelectButton.vue +24 -0
- package/src/components/headless/forms/AGHeadlessSelectError.vue +26 -0
- package/src/components/headless/forms/AGHeadlessSelectLabel.vue +24 -0
- package/src/components/headless/forms/AGHeadlessSelectOption.ts +4 -0
- package/src/components/headless/forms/AGHeadlessSelectOption.vue +39 -0
- package/src/components/headless/forms/AGHeadlessSelectOptions.ts +3 -0
- package/src/components/headless/forms/index.ts +9 -1
- package/src/components/headless/modals/AGHeadlessModal.ts +27 -0
- package/src/components/headless/modals/AGHeadlessModal.vue +3 -5
- package/src/components/headless/modals/index.ts +4 -6
- package/src/components/headless/snackbars/index.ts +23 -8
- package/src/components/index.ts +1 -1
- package/src/components/lib/AGMeasured.vue +15 -0
- package/src/components/lib/AGStartupCrash.vue +31 -0
- package/src/components/lib/index.ts +5 -0
- package/src/components/modals/AGAlertModal.ts +15 -0
- package/src/components/modals/AGAlertModal.vue +4 -15
- package/src/components/modals/AGConfirmModal.ts +27 -0
- package/src/components/modals/AGConfirmModal.vue +7 -11
- package/src/components/modals/AGErrorReportModal.ts +27 -1
- package/src/components/modals/AGErrorReportModal.vue +8 -16
- package/src/components/modals/AGErrorReportModalButtons.vue +4 -2
- package/src/components/modals/AGErrorReportModalTitle.vue +1 -1
- package/src/components/modals/AGLoadingModal.ts +23 -0
- package/src/components/modals/AGLoadingModal.vue +4 -8
- package/src/components/modals/AGModal.ts +1 -1
- package/src/components/modals/AGModal.vue +14 -12
- package/src/components/modals/index.ts +3 -0
- package/src/components/snackbars/AGSnackbar.vue +3 -9
- package/src/components/utils.ts +10 -0
- package/src/directives/index.ts +3 -1
- package/src/directives/measure.ts +12 -0
- package/src/errors/Errors.ts +10 -5
- package/src/errors/index.ts +9 -13
- package/src/forms/Form.ts +11 -3
- package/src/main.histoire.ts +1 -0
- package/src/services/App.state.ts +3 -3
- package/src/services/App.ts +10 -1
- package/src/services/Service.ts +8 -4
- package/src/services/index.ts +1 -1
- package/src/ui/UI.ts +77 -14
- package/src/ui/index.ts +6 -3
- package/src/utils/composition/events.ts +1 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/tailwindcss.test.ts +26 -0
- package/src/utils/tailwindcss.ts +7 -0
- package/src/utils/vue.ts +13 -4
- package/tailwind.config.js +4 -0
- package/tsconfig.json +1 -1
- package/.eslintrc.js +0 -3
- package/dist/virtual.d.ts +0 -11
- package/src/components/basic/index.ts +0 -5
- package/src/types/virtual.d.ts +0 -11
- /package/src/components/{basic → lib}/AGErrorMessage.vue +0 -0
- /package/src/components/{basic → lib}/AGLink.vue +0 -0
- /package/src/components/{basic → lib}/AGMarkdown.vue +0 -0
package/src/errors/Errors.ts
CHANGED
|
@@ -7,7 +7,9 @@ import { translateWithDefault } from '@/lang/utils';
|
|
|
7
7
|
|
|
8
8
|
import Service from './Errors.state';
|
|
9
9
|
import { Colors } from '@/components/constants';
|
|
10
|
+
import type { AGErrorReportModalProps } from '@/components/modals/AGErrorReportModal';
|
|
10
11
|
import type { ErrorReport, ErrorReportLog, ErrorSource } from './Errors.state';
|
|
12
|
+
import type { ModalComponent } from '@/ui/UI.state';
|
|
11
13
|
|
|
12
14
|
export class ErrorsService extends Service {
|
|
13
15
|
|
|
@@ -23,7 +25,7 @@ export class ErrorsService extends Service {
|
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
public async inspect(error: ErrorSource | ErrorReport[]): Promise<void> {
|
|
26
|
-
const reports = Array.isArray(error) ? error : [await this.createErrorReport(error)];
|
|
28
|
+
const reports = Array.isArray(error) ? (error as ErrorReport[]) : [await this.createErrorReport(error)];
|
|
27
29
|
|
|
28
30
|
if (reports.length === 0) {
|
|
29
31
|
UI.alert(translateWithDefault('errors.inspectEmpty', 'Nothing to inspect!'));
|
|
@@ -31,7 +33,9 @@ export class ErrorsService extends Service {
|
|
|
31
33
|
return;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
UI.openModal(UI.requireComponent(UIComponents.ErrorReportModal), {
|
|
36
|
+
UI.openModal<ModalComponent<AGErrorReportModalProps>>(UI.requireComponent(UIComponents.ErrorReportModal), {
|
|
37
|
+
reports,
|
|
38
|
+
});
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
public async report(error: ErrorSource, message?: string): Promise<void> {
|
|
@@ -70,9 +74,10 @@ export class ErrorsService extends Service {
|
|
|
70
74
|
text: translateWithDefault('errors.viewDetails', 'View details'),
|
|
71
75
|
dismiss: true,
|
|
72
76
|
handler: () =>
|
|
73
|
-
UI.openModal(
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
UI.openModal<ModalComponent<AGErrorReportModalProps>>(
|
|
78
|
+
UI.requireComponent(UIComponents.ErrorReportModal),
|
|
79
|
+
{ reports: [report] },
|
|
80
|
+
),
|
|
76
81
|
},
|
|
77
82
|
],
|
|
78
83
|
},
|
package/src/errors/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { App } from 'vue';
|
|
2
2
|
|
|
3
3
|
import { bootServices } from '@/services';
|
|
4
4
|
import { definePlugin } from '@/plugins';
|
|
@@ -25,14 +25,12 @@ const frameworkHandler: ErrorHandler = (error) => {
|
|
|
25
25
|
return true;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
function setUpErrorHandler(baseHandler: ErrorHandler = () => false):
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
},
|
|
35
|
-
);
|
|
28
|
+
function setUpErrorHandler(app: App, baseHandler: ErrorHandler = () => false): void {
|
|
29
|
+
const errorHandler: ErrorHandler = (error) => baseHandler(error) || frameworkHandler(error);
|
|
30
|
+
|
|
31
|
+
app.config.errorHandler = errorHandler;
|
|
32
|
+
globalThis.onerror = (event, _, __, ___, error) => errorHandler(error ?? event);
|
|
33
|
+
globalThis.onunhandledrejection = (event) => errorHandler(event.reason);
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
export type ErrorHandler = (error: ErrorSource) => boolean;
|
|
@@ -40,16 +38,14 @@ export type ErrorsServices = typeof services;
|
|
|
40
38
|
|
|
41
39
|
export default definePlugin({
|
|
42
40
|
async install(app, options) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
app.config.errorHandler = errorHandler;
|
|
41
|
+
setUpErrorHandler(app, options.handleError);
|
|
46
42
|
|
|
47
43
|
await bootServices(app, services);
|
|
48
44
|
},
|
|
49
45
|
});
|
|
50
46
|
|
|
51
47
|
declare module '@/bootstrap/options' {
|
|
52
|
-
interface AerogelOptions {
|
|
48
|
+
export interface AerogelOptions {
|
|
53
49
|
handleError?(error: ErrorSource): boolean;
|
|
54
50
|
}
|
|
55
51
|
}
|
package/src/forms/Form.ts
CHANGED
|
@@ -7,6 +7,7 @@ export const FormFieldTypes = {
|
|
|
7
7
|
String: 'string',
|
|
8
8
|
Number: 'number',
|
|
9
9
|
Boolean: 'boolean',
|
|
10
|
+
Object: 'object',
|
|
10
11
|
} as const;
|
|
11
12
|
|
|
12
13
|
export interface FormFieldDefinition<TType extends FormFieldType = FormFieldType, TRules extends string = string> {
|
|
@@ -36,15 +37,18 @@ export type GetFormFieldValue<TType> = TType extends typeof FormFieldTypes.Strin
|
|
|
36
37
|
? number
|
|
37
38
|
: TType extends typeof FormFieldTypes.Boolean
|
|
38
39
|
? boolean
|
|
40
|
+
: TType extends typeof FormFieldTypes.Object
|
|
41
|
+
? object
|
|
39
42
|
: never;
|
|
40
43
|
|
|
44
|
+
const validForms: WeakMap<Form, ComputedRef<boolean>> = new WeakMap();
|
|
45
|
+
|
|
41
46
|
export default class Form<Fields extends FormFieldDefinitions = FormFieldDefinitions> extends MagicObject {
|
|
42
47
|
|
|
43
48
|
public errors: DeepReadonly<UnwrapNestedRefs<FormErrors<Fields>>>;
|
|
44
49
|
|
|
45
50
|
private _fields: Fields;
|
|
46
51
|
private _data: FormData<Fields>;
|
|
47
|
-
private _valid: ComputedRef<boolean>;
|
|
48
52
|
private _submitted: Ref<boolean>;
|
|
49
53
|
private _errors: FormErrors<Fields>;
|
|
50
54
|
|
|
@@ -55,13 +59,17 @@ export default class Form<Fields extends FormFieldDefinitions = FormFieldDefinit
|
|
|
55
59
|
this._submitted = ref(false);
|
|
56
60
|
this._data = this.getInitialData(fields);
|
|
57
61
|
this._errors = this.getInitialErrors(fields);
|
|
58
|
-
|
|
62
|
+
|
|
63
|
+
validForms.set(
|
|
64
|
+
this,
|
|
65
|
+
computed(() => !Object.values(this._errors).some((error) => error !== null)),
|
|
66
|
+
);
|
|
59
67
|
|
|
60
68
|
this.errors = readonly(this._errors);
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
public get valid(): boolean {
|
|
64
|
-
return this
|
|
72
|
+
return !!validForms.get(this)?.value;
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
public get submitted(): boolean {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './assets/histoire.css';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Aerogel from 'virtual:aerogel';
|
|
2
2
|
|
|
3
3
|
import { defineServiceState } from '@/services/Service';
|
|
4
4
|
import type { Plugin } from '@/plugins/Plugin';
|
|
@@ -7,8 +7,8 @@ export default defineServiceState({
|
|
|
7
7
|
name: 'app',
|
|
8
8
|
initialState: {
|
|
9
9
|
plugins: {} as Record<string, Plugin>,
|
|
10
|
-
environment:
|
|
11
|
-
sourceUrl:
|
|
10
|
+
environment: Aerogel.environment,
|
|
11
|
+
sourceUrl: Aerogel.sourceUrl,
|
|
12
12
|
isMounted: false,
|
|
13
13
|
},
|
|
14
14
|
computed: {
|
package/src/services/App.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { facade } from '@noeldemartin/utils';
|
|
1
|
+
import { facade, forever, updateLocationQueryParameters } from '@noeldemartin/utils';
|
|
2
2
|
|
|
3
3
|
import Events from '@/services/Events';
|
|
4
4
|
import type { Plugin } from '@/plugins';
|
|
@@ -7,6 +7,15 @@ import Service from './App.state';
|
|
|
7
7
|
|
|
8
8
|
export class AppService extends Service {
|
|
9
9
|
|
|
10
|
+
public async reload(queryParameters?: Record<string, string | undefined>): Promise<void> {
|
|
11
|
+
queryParameters && updateLocationQueryParameters(queryParameters);
|
|
12
|
+
|
|
13
|
+
location.reload();
|
|
14
|
+
|
|
15
|
+
// Stall until the reload happens
|
|
16
|
+
await forever();
|
|
17
|
+
}
|
|
18
|
+
|
|
10
19
|
public plugin<T extends Plugin = Plugin>(name: string): T | null {
|
|
11
20
|
return (this.plugins[name] as T) ?? null;
|
|
12
21
|
}
|
package/src/services/Service.ts
CHANGED
|
@@ -162,7 +162,11 @@ export default class Service<
|
|
|
162
162
|
return;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
const storage = Storage.
|
|
165
|
+
const storage = Storage.get<ServiceStorage>(this._name);
|
|
166
|
+
|
|
167
|
+
if (!storage) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
166
170
|
|
|
167
171
|
Storage.set(this._name, {
|
|
168
172
|
...storage,
|
|
@@ -191,14 +195,14 @@ export default class Service<
|
|
|
191
195
|
}
|
|
192
196
|
|
|
193
197
|
protected async frameworkBoot(): Promise<void> {
|
|
194
|
-
this.
|
|
198
|
+
this.initializePersistedState();
|
|
195
199
|
}
|
|
196
200
|
|
|
197
201
|
protected async boot(): Promise<void> {
|
|
198
|
-
//
|
|
202
|
+
// Placeholder for overrides, don't place any functionality here.
|
|
199
203
|
}
|
|
200
204
|
|
|
201
|
-
protected
|
|
205
|
+
protected initializePersistedState(): void {
|
|
202
206
|
// TODO fix this.static()
|
|
203
207
|
const persist = (this.constructor as unknown as { persist: string[] }).persist;
|
|
204
208
|
|
package/src/services/index.ts
CHANGED
package/src/ui/UI.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { facade, fail, uuid } from '@noeldemartin/utils';
|
|
1
|
+
import { after, facade, fail, 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';
|
|
@@ -8,6 +8,7 @@ import type { SnackbarAction, SnackbarColor } from '@/components/headless/snackb
|
|
|
8
8
|
|
|
9
9
|
import Service from './UI.state';
|
|
10
10
|
import type { Modal, ModalComponent, Snackbar } from './UI.state';
|
|
11
|
+
import type { AGAlertModalProps, AGConfirmModalProps, AGLoadingModalProps } from '@/components';
|
|
11
12
|
|
|
12
13
|
interface ModalCallbacks<T = unknown> {
|
|
13
14
|
willClose(result: T | undefined): void;
|
|
@@ -25,10 +26,16 @@ export const UIComponents = {
|
|
|
25
26
|
ErrorReportModal: 'error-report-modal',
|
|
26
27
|
LoadingModal: 'loading-modal',
|
|
27
28
|
Snackbar: 'snackbar',
|
|
29
|
+
StartupCrash: 'startup-crash',
|
|
28
30
|
} as const;
|
|
29
31
|
|
|
30
32
|
export type UIComponent = ObjectValues<typeof UIComponents>;
|
|
31
33
|
|
|
34
|
+
export interface ConfirmOptions {
|
|
35
|
+
acceptText?: string;
|
|
36
|
+
cancelText?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
32
39
|
export interface ShowSnackbarOptions {
|
|
33
40
|
component?: Component;
|
|
34
41
|
color?: SnackbarColor;
|
|
@@ -47,18 +54,45 @@ export class UIService extends Service {
|
|
|
47
54
|
public alert(message: string): void;
|
|
48
55
|
public alert(title: string, message: string): void;
|
|
49
56
|
public alert(messageOrTitle: string, message?: string): void {
|
|
50
|
-
const
|
|
57
|
+
const getProperties = (): AGAlertModalProps => {
|
|
58
|
+
if (typeof message !== 'string') {
|
|
59
|
+
return { message: messageOrTitle };
|
|
60
|
+
}
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
return {
|
|
63
|
+
title: messageOrTitle,
|
|
64
|
+
message,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
this.openModal(this.requireComponent(UIComponents.AlertModal), getProperties());
|
|
53
69
|
}
|
|
54
70
|
|
|
55
|
-
public async confirm(message: string): Promise<boolean>;
|
|
56
|
-
public async confirm(title: string, message: string): Promise<boolean>;
|
|
57
|
-
public async confirm(
|
|
58
|
-
|
|
71
|
+
public async confirm(message: string, options?: ConfirmOptions): Promise<boolean>;
|
|
72
|
+
public async confirm(title: string, message: string, options?: ConfirmOptions): Promise<boolean>;
|
|
73
|
+
public async confirm(
|
|
74
|
+
messageOrTitle: string,
|
|
75
|
+
messageOrOptions?: string | ConfirmOptions,
|
|
76
|
+
options?: ConfirmOptions,
|
|
77
|
+
): Promise<boolean> {
|
|
78
|
+
const getProperties = (): AGConfirmModalProps => {
|
|
79
|
+
if (typeof messageOrOptions !== 'string') {
|
|
80
|
+
return {
|
|
81
|
+
message: messageOrTitle,
|
|
82
|
+
...(messageOrOptions ?? {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
title: messageOrTitle,
|
|
88
|
+
message: messageOrOptions,
|
|
89
|
+
...(options ?? {}),
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
59
93
|
const modal = await this.openModal<ModalComponent<{ message: string }, boolean>>(
|
|
60
94
|
this.requireComponent(UIComponents.ConfirmModal),
|
|
61
|
-
|
|
95
|
+
getProperties(),
|
|
62
96
|
);
|
|
63
97
|
const result = await modal.beforeClose;
|
|
64
98
|
|
|
@@ -68,15 +102,25 @@ export class UIService extends Service {
|
|
|
68
102
|
public async loading<T>(operation: Promise<T>): Promise<T>;
|
|
69
103
|
public async loading<T>(message: string, operation: Promise<T>): Promise<T>;
|
|
70
104
|
public async loading<T>(messageOrOperation: string | Promise<T>, operation?: Promise<T>): Promise<T> {
|
|
71
|
-
|
|
105
|
+
const getProperties = (): AGLoadingModalProps => {
|
|
106
|
+
if (typeof messageOrOperation !== 'string') {
|
|
107
|
+
return {};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return { message: messageOrOperation };
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const modal = await this.openModal(this.requireComponent(UIComponents.LoadingModal), getProperties());
|
|
72
114
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const result = await operation;
|
|
115
|
+
try {
|
|
116
|
+
operation = typeof messageOrOperation === 'string' ? (operation as Promise<T>) : messageOrOperation;
|
|
76
117
|
|
|
77
|
-
|
|
118
|
+
const [result] = await Promise.all([operation, after({ seconds: 1 })]);
|
|
78
119
|
|
|
79
|
-
|
|
120
|
+
return result;
|
|
121
|
+
} finally {
|
|
122
|
+
await this.closeModal(modal.id);
|
|
123
|
+
}
|
|
80
124
|
}
|
|
81
125
|
|
|
82
126
|
public showSnackbar(message: string, options: ShowSnackbarOptions = {}): void {
|
|
@@ -138,6 +182,7 @@ export class UIService extends Service {
|
|
|
138
182
|
|
|
139
183
|
protected async boot(): Promise<void> {
|
|
140
184
|
this.watchModalEvents();
|
|
185
|
+
this.watchMountedEvent();
|
|
141
186
|
}
|
|
142
187
|
|
|
143
188
|
private watchModalEvents(): void {
|
|
@@ -165,6 +210,24 @@ export class UIService extends Service {
|
|
|
165
210
|
});
|
|
166
211
|
}
|
|
167
212
|
|
|
213
|
+
private watchMountedEvent(): void {
|
|
214
|
+
Events.once('application-mounted', async () => {
|
|
215
|
+
const splash = document.getElementById('splash');
|
|
216
|
+
|
|
217
|
+
if (!splash) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (window.getComputedStyle(splash).opacity !== '0') {
|
|
222
|
+
splash.style.opacity = '0';
|
|
223
|
+
|
|
224
|
+
await after({ ms: 600 });
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
splash.remove();
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
168
231
|
}
|
|
169
232
|
|
|
170
233
|
export default facade(new UIService());
|
package/src/ui/index.ts
CHANGED
|
@@ -9,12 +9,14 @@ import AGConfirmModal from '../components/modals/AGConfirmModal.vue';
|
|
|
9
9
|
import AGErrorReportModal from '../components/modals/AGErrorReportModal.vue';
|
|
10
10
|
import AGLoadingModal from '../components/modals/AGLoadingModal.vue';
|
|
11
11
|
import AGSnackbar from '../components/snackbars/AGSnackbar.vue';
|
|
12
|
+
import AGStartupCrash from '../components/lib/AGStartupCrash.vue';
|
|
12
13
|
import type { UIComponent } from './UI';
|
|
13
14
|
|
|
14
|
-
export { UI, UIComponents, UIComponent };
|
|
15
|
-
|
|
16
15
|
const services = { $ui: UI };
|
|
17
16
|
|
|
17
|
+
export * from './UI';
|
|
18
|
+
export { default as UI } from './UI';
|
|
19
|
+
|
|
18
20
|
export type UIServices = typeof services;
|
|
19
21
|
|
|
20
22
|
export default definePlugin({
|
|
@@ -25,6 +27,7 @@ export default definePlugin({
|
|
|
25
27
|
[UIComponents.ErrorReportModal]: AGErrorReportModal,
|
|
26
28
|
[UIComponents.LoadingModal]: AGLoadingModal,
|
|
27
29
|
[UIComponents.Snackbar]: AGSnackbar,
|
|
30
|
+
[UIComponents.StartupCrash]: AGStartupCrash,
|
|
28
31
|
};
|
|
29
32
|
|
|
30
33
|
Object.entries({
|
|
@@ -37,7 +40,7 @@ export default definePlugin({
|
|
|
37
40
|
});
|
|
38
41
|
|
|
39
42
|
declare module '@/bootstrap/options' {
|
|
40
|
-
interface AerogelOptions {
|
|
43
|
+
export interface AerogelOptions {
|
|
41
44
|
components?: Partial<Record<UIComponent, Component>>;
|
|
42
45
|
}
|
|
43
46
|
}
|
|
@@ -14,6 +14,7 @@ export function useEvent<Event extends EventWithPayload>(
|
|
|
14
14
|
event: Event,
|
|
15
15
|
listener: EventListener<EventsPayload[Event]>
|
|
16
16
|
): void;
|
|
17
|
+
export function useEvent<Payload>(event: string, listener: (payload: Payload) => unknown): void;
|
|
17
18
|
export function useEvent<Event extends string>(event: UnknownEvent<Event>, listener: EventListener): void;
|
|
18
19
|
|
|
19
20
|
export function useEvent(event: string, listener: EventListener): void {
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { removeInteractiveClasses } from './tailwindcss';
|
|
4
|
+
|
|
5
|
+
describe('TailwindCSS utils', () => {
|
|
6
|
+
|
|
7
|
+
it('Removes interactive classes', () => {
|
|
8
|
+
const cases: [string, string][] = [
|
|
9
|
+
['text-red hover:text-green', 'text-red'],
|
|
10
|
+
['text-red hover:text-green text-lg', 'text-red text-lg'],
|
|
11
|
+
[
|
|
12
|
+
`
|
|
13
|
+
text-red text-lg
|
|
14
|
+
focus:text-yellow
|
|
15
|
+
hover:focus:text-black
|
|
16
|
+
`,
|
|
17
|
+
'text-red text-lg',
|
|
18
|
+
],
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
cases.forEach(([original, expected]) => {
|
|
22
|
+
expect(removeInteractiveClasses(original)).toEqual(expected);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
});
|
package/src/utils/vue.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { fail } from '@noeldemartin/utils';
|
|
2
|
-
import { inject, reactive, ref } from 'vue';
|
|
2
|
+
import { computed, inject, reactive, ref, watch } from 'vue';
|
|
3
3
|
import type { Directive, InjectionKey, PropType, Ref, UnwrapNestedRefs } from 'vue';
|
|
4
4
|
|
|
5
5
|
type BaseProp<T> = {
|
|
6
|
-
type
|
|
6
|
+
type?: PropType<T>;
|
|
7
7
|
validator?(value: unknown): boolean;
|
|
8
8
|
};
|
|
9
9
|
|
|
@@ -30,6 +30,15 @@ export function componentRef<T>(): Ref<UnwrapNestedRefs<T> | undefined> {
|
|
|
30
30
|
return ref<UnwrapNestedRefs<T>>();
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
export function computedAsync<T>(getter: () => Promise<T>): Ref<T | undefined> {
|
|
34
|
+
const result = ref<T>();
|
|
35
|
+
const asyncValue = computed(getter);
|
|
36
|
+
|
|
37
|
+
watch(asyncValue, async () => (result.value = await asyncValue.value), { immediate: true });
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
33
42
|
export function defineDirective(directive: Directive): Directive {
|
|
34
43
|
return directive;
|
|
35
44
|
}
|
|
@@ -64,7 +73,7 @@ export function injectOrFail<T>(key: InjectionKey<T> | string, errorMessage?: st
|
|
|
64
73
|
return inject(key) ?? fail(errorMessage ?? `Could not resolve '${key}' injection key`);
|
|
65
74
|
}
|
|
66
75
|
|
|
67
|
-
export function mixedProp<T>(type
|
|
76
|
+
export function mixedProp<T>(type?: PropType<T>): OptionalProp<T | null> {
|
|
68
77
|
return {
|
|
69
78
|
type,
|
|
70
79
|
default: null,
|
|
@@ -108,7 +117,7 @@ export function requiredEnumProp<Enum extends Record<string, unknown>>(
|
|
|
108
117
|
};
|
|
109
118
|
}
|
|
110
119
|
|
|
111
|
-
export function requiredMixedProp<T>(type
|
|
120
|
+
export function requiredMixedProp<T>(type?: PropType<T>): RequiredProp<T> {
|
|
112
121
|
return {
|
|
113
122
|
type,
|
|
114
123
|
required: true,
|
package/tsconfig.json
CHANGED
package/.eslintrc.js
DELETED
package/dist/virtual.d.ts
DELETED
package/src/types/virtual.d.ts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|