@aerogel/core 0.0.0-next.c8f032a868370824898e171969aec1bb6827688e → 0.0.0-next.f16bd1d894543c5303039c49f6f33488a1ffe931

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 (64) hide show
  1. package/dist/aerogel-core.cjs.js +1 -1
  2. package/dist/aerogel-core.cjs.js.map +1 -1
  3. package/dist/aerogel-core.d.ts +501 -83
  4. package/dist/aerogel-core.esm.js +1 -1
  5. package/dist/aerogel-core.esm.js.map +1 -1
  6. package/dist/virtual.d.ts +11 -0
  7. package/noeldemartin.config.js +4 -1
  8. package/package.json +3 -2
  9. package/src/bootstrap/index.ts +4 -1
  10. package/src/components/AGAppModals.vue +15 -0
  11. package/src/components/AGAppOverlays.vue +5 -7
  12. package/src/components/AGAppSnackbars.vue +13 -0
  13. package/src/components/basic/AGMarkdown.vue +10 -5
  14. package/src/components/constants.ts +8 -0
  15. package/src/components/forms/AGButton.vue +33 -10
  16. package/src/components/forms/AGCheckbox.vue +35 -0
  17. package/src/components/forms/AGInput.vue +8 -4
  18. package/src/components/forms/index.ts +2 -1
  19. package/src/components/headless/forms/AGHeadlessButton.vue +3 -4
  20. package/src/components/headless/forms/AGHeadlessInput.ts +2 -2
  21. package/src/components/headless/forms/AGHeadlessInput.vue +3 -3
  22. package/src/components/headless/forms/AGHeadlessInputError.vue +1 -1
  23. package/src/components/headless/forms/AGHeadlessInputInput.vue +15 -3
  24. package/src/components/headless/index.ts +1 -0
  25. package/src/components/headless/modals/AGHeadlessModalPanel.vue +5 -1
  26. package/src/components/headless/snackbars/AGHeadlessSnackbar.vue +10 -0
  27. package/src/components/headless/snackbars/index.ts +25 -0
  28. package/src/components/index.ts +2 -0
  29. package/src/components/modals/AGConfirmModal.vue +1 -1
  30. package/src/components/modals/AGErrorReportModal.ts +20 -0
  31. package/src/components/modals/AGErrorReportModal.vue +62 -0
  32. package/src/components/modals/AGErrorReportModalButtons.vue +106 -0
  33. package/src/components/modals/AGErrorReportModalTitle.vue +25 -0
  34. package/src/components/modals/AGLoadingModal.vue +19 -0
  35. package/src/components/modals/AGModal.vue +21 -3
  36. package/src/components/modals/index.ts +16 -2
  37. package/src/components/snackbars/AGSnackbar.vue +42 -0
  38. package/src/components/snackbars/index.ts +3 -0
  39. package/src/directives/index.ts +16 -3
  40. package/src/errors/Errors.state.ts +31 -0
  41. package/src/errors/Errors.ts +161 -0
  42. package/src/errors/index.ts +59 -0
  43. package/src/forms/Form.test.ts +21 -0
  44. package/src/forms/Form.ts +20 -10
  45. package/src/forms/utils.ts +17 -0
  46. package/src/lang/Lang.ts +11 -3
  47. package/src/lang/index.ts +3 -5
  48. package/src/lang/utils.ts +4 -0
  49. package/src/main.ts +1 -2
  50. package/src/services/App.state.ts +7 -1
  51. package/src/services/App.ts +11 -1
  52. package/src/services/Service.ts +126 -44
  53. package/src/services/index.ts +18 -4
  54. package/src/services/store.ts +27 -0
  55. package/src/types/virtual.d.ts +11 -0
  56. package/src/ui/UI.state.ts +11 -1
  57. package/src/ui/UI.ts +52 -6
  58. package/src/ui/index.ts +7 -1
  59. package/src/utils/composition/forms.ts +11 -0
  60. package/src/utils/index.ts +1 -0
  61. package/src/utils/vue.ts +2 -0
  62. package/tsconfig.json +1 -0
  63. package/vite.config.ts +2 -1
  64. package/src/globals.ts +0 -6
package/src/ui/UI.ts CHANGED
@@ -4,9 +4,10 @@ import type { Component } from 'vue';
4
4
  import type { ObjectValues } from '@noeldemartin/utils';
5
5
 
6
6
  import Events from '@/services/Events';
7
+ import type { SnackbarAction, SnackbarColor } from '@/components/headless/snackbars';
7
8
 
8
9
  import Service from './UI.state';
9
- import type { Modal, ModalComponent } from './UI.state';
10
+ import type { Modal, ModalComponent, Snackbar } from './UI.state';
10
11
 
11
12
  interface ModalCallbacks<T = unknown> {
12
13
  willClose(result: T | undefined): void;
@@ -21,15 +22,28 @@ type ModalResult<TComponent> = TComponent extends ModalComponent<Record<string,
21
22
  export const UIComponents = {
22
23
  AlertModal: 'alert-modal',
23
24
  ConfirmModal: 'confirm-modal',
25
+ ErrorReportModal: 'error-report-modal',
26
+ LoadingModal: 'loading-modal',
27
+ Snackbar: 'snackbar',
24
28
  } as const;
25
29
 
26
30
  export type UIComponent = ObjectValues<typeof UIComponents>;
27
31
 
32
+ export interface ShowSnackbarOptions {
33
+ component?: Component;
34
+ color?: SnackbarColor;
35
+ actions?: SnackbarAction[];
36
+ }
37
+
28
38
  export class UIService extends Service {
29
39
 
30
40
  private modalCallbacks: Record<string, Partial<ModalCallbacks>> = {};
31
41
  private components: Partial<Record<UIComponent, Component>> = {};
32
42
 
43
+ public requireComponent(name: UIComponent): Component {
44
+ return this.components[name] ?? fail(`UI Component '${name}' is not defined!`);
45
+ }
46
+
33
47
  public alert(message: string): void;
34
48
  public alert(title: string, message: string): void;
35
49
  public alert(messageOrTitle: string, message?: string): void {
@@ -51,6 +65,39 @@ export class UIService extends Service {
51
65
  return result ?? false;
52
66
  }
53
67
 
68
+ public async loading<T>(operation: Promise<T>): Promise<T>;
69
+ public async loading<T>(message: string, operation: Promise<T>): Promise<T>;
70
+ public async loading<T>(messageOrOperation: string | Promise<T>, operation?: Promise<T>): Promise<T> {
71
+ operation = typeof messageOrOperation === 'string' ? (operation as Promise<T>) : messageOrOperation;
72
+
73
+ const message = typeof messageOrOperation === 'string' ? messageOrOperation : undefined;
74
+ const modal = await this.openModal(this.requireComponent(UIComponents.LoadingModal), { message });
75
+ const result = await operation;
76
+
77
+ await this.closeModal(modal.id);
78
+
79
+ return result;
80
+ }
81
+
82
+ public showSnackbar(message: string, options: ShowSnackbarOptions = {}): void {
83
+ const snackbar: Snackbar = {
84
+ id: uuid(),
85
+ properties: { message, ...options },
86
+ component: options.component ?? markRaw(this.requireComponent(UIComponents.Snackbar)),
87
+ };
88
+
89
+ this.setState('snackbars', this.snackbars.concat(snackbar));
90
+
91
+ setTimeout(() => this.hideSnackbar(snackbar.id), 5000);
92
+ }
93
+
94
+ public hideSnackbar(id: string): void {
95
+ this.setState(
96
+ 'snackbars',
97
+ this.snackbars.filter((snackbar) => snackbar.id !== id),
98
+ );
99
+ }
100
+
54
101
  public registerComponent(name: UIComponent, component: Component): void {
55
102
  this.components[name] = component;
56
103
  }
@@ -95,10 +142,6 @@ export class UIService extends Service {
95
142
  this.watchModalEvents();
96
143
  }
97
144
 
98
- private requireComponent(name: UIComponent): Component {
99
- return this.components[name] ?? fail(`UI Component '${name}' is not defined!`);
100
- }
101
-
102
145
  private watchModalEvents(): void {
103
146
  Events.on('modal-will-close', ({ modal, result }) => {
104
147
  this.modalCallbacks[modal.id]?.willClose?.(result);
@@ -109,7 +152,10 @@ export class UIService extends Service {
109
152
  });
110
153
 
111
154
  Events.on('modal-closed', async ({ modal, result }) => {
112
- this.setState({ modals: this.modals.filter((m) => m.id !== modal.id) });
155
+ this.setState(
156
+ 'modals',
157
+ this.modals.filter((m) => m.id !== modal.id),
158
+ );
113
159
 
114
160
  this.modalCallbacks[modal.id]?.closed?.(result);
115
161
 
package/src/ui/index.ts CHANGED
@@ -6,6 +6,9 @@ import { definePlugin } from '@/plugins';
6
6
  import UI, { UIComponents } from './UI';
7
7
  import AGAlertModal from '../components/modals/AGAlertModal.vue';
8
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 AGSnackbar from '../components/snackbars/AGSnackbar.vue';
9
12
  import type { UIComponent } from './UI';
10
13
 
11
14
  export { UI, UIComponents, UIComponent };
@@ -19,6 +22,9 @@ export default definePlugin({
19
22
  const defaultComponents = {
20
23
  [UIComponents.AlertModal]: AGAlertModal,
21
24
  [UIComponents.ConfirmModal]: AGConfirmModal,
25
+ [UIComponents.ErrorReportModal]: AGErrorReportModal,
26
+ [UIComponents.LoadingModal]: AGLoadingModal,
27
+ [UIComponents.Snackbar]: AGSnackbar,
22
28
  };
23
29
 
24
30
  Object.entries({
@@ -37,5 +43,5 @@ declare module '@/bootstrap/options' {
37
43
  }
38
44
 
39
45
  declare module '@/services' {
40
- interface Services extends UIServices {}
46
+ export interface Services extends UIServices {}
41
47
  }
@@ -0,0 +1,11 @@
1
+ import { objectWithout } from '@noeldemartin/utils';
2
+ import { computed, useAttrs } from 'vue';
3
+ import type { ComputedRef } from 'vue';
4
+
5
+ export function useInputAttrs(): [ComputedRef<{}>, ComputedRef<unknown>] {
6
+ const attrs = useAttrs();
7
+ const className = computed(() => attrs.class);
8
+ const inputAttrs = computed(() => objectWithout(attrs, 'class'));
9
+
10
+ return [inputAttrs, className];
11
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './composition/events';
2
+ export * from './composition/forms';
2
3
  export * from './composition/hooks';
3
4
  export * from './vue';
package/src/utils/vue.ts CHANGED
@@ -10,6 +10,8 @@ type BaseProp<T> = {
10
10
  type RequiredProp<T> = BaseProp<T> & { required: true };
11
11
  type OptionalProp<T> = BaseProp<T> & { default: T | (() => T) | null };
12
12
 
13
+ export type ComponentProps = Record<string, unknown>;
14
+
13
15
  export function arrayProp<T>(defaultValue?: () => T[]): OptionalProp<T[]> {
14
16
  return {
15
17
  type: Array as PropType<T[]>,
package/tsconfig.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "extends": "../../tsconfig.json",
3
3
  "compilerOptions": {
4
+ "types": ["unplugin-icons/types/vue3"],
4
5
  "baseUrl": ".",
5
6
  "paths": {
6
7
  "@/*": ["./src/*"]
package/vite.config.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import Aerogel from '@aerogel/vite';
2
+ import Icons from 'unplugin-icons/vite';
2
3
  import { defineConfig } from 'vitest/config';
3
4
  import { resolve } from 'path';
4
5
 
5
6
  export default defineConfig({
6
7
  test: { clearMocks: true },
7
- plugins: [Aerogel()],
8
+ plugins: [Aerogel(), Icons()],
8
9
  resolve: {
9
10
  alias: {
10
11
  '@': resolve(__dirname, './src'),
package/src/globals.ts DELETED
@@ -1,6 +0,0 @@
1
- export {};
2
-
3
- declare global {
4
- export const __AG_BASE_PATH: string | undefined;
5
- export const __AG_ENV: 'production' | 'development' | 'testing';
6
- }