@aerogel/core 0.0.0-next.9a1c5ba39a454b316eba36ec7bdf579fed3d95d2 → 0.0.0-next.9d1e54cc195274e9dd7d57a73fcb8a9a51927dcb

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 (159) hide show
  1. package/dist/aerogel-core.css +1 -0
  2. package/dist/aerogel-core.d.ts +1309 -1587
  3. package/dist/aerogel-core.js +2637 -1991
  4. package/dist/aerogel-core.js.map +1 -1
  5. package/package.json +10 -2
  6. package/src/components/AppLayout.vue +14 -0
  7. package/src/components/{AGAppModals.vue → AppModals.vue} +2 -3
  8. package/src/components/AppOverlays.vue +9 -0
  9. package/src/components/AppToasts.vue +16 -0
  10. package/src/components/contracts/AlertModal.ts +19 -0
  11. package/src/components/contracts/Button.ts +16 -0
  12. package/src/components/contracts/ConfirmModal.ts +48 -0
  13. package/src/components/contracts/DropdownMenu.ts +25 -0
  14. package/src/components/contracts/ErrorReportModal.ts +33 -0
  15. package/src/components/contracts/Input.ts +26 -0
  16. package/src/components/contracts/LoadingModal.ts +26 -0
  17. package/src/components/contracts/Modal.ts +15 -10
  18. package/src/components/contracts/PromptModal.ts +34 -0
  19. package/src/components/contracts/Select.ts +45 -0
  20. package/src/components/contracts/Toast.ts +15 -0
  21. package/src/components/contracts/index.ts +10 -1
  22. package/src/components/headless/HeadlessButton.vue +51 -0
  23. package/src/components/headless/HeadlessInput.vue +59 -0
  24. package/src/components/headless/{forms/AGHeadlessInputDescription.vue → HeadlessInputDescription.vue} +6 -7
  25. package/src/components/headless/{forms/AGHeadlessInputError.vue → HeadlessInputError.vue} +2 -6
  26. package/src/components/headless/{forms/AGHeadlessInputInput.vue → HeadlessInputInput.vue} +16 -25
  27. package/src/components/headless/{forms/AGHeadlessInputLabel.vue → HeadlessInputLabel.vue} +2 -6
  28. package/src/components/headless/{forms/AGHeadlessInputTextArea.vue → HeadlessInputTextArea.vue} +9 -12
  29. package/src/components/headless/HeadlessModal.vue +57 -0
  30. package/src/components/headless/HeadlessModalContent.vue +30 -0
  31. package/src/components/headless/HeadlessModalDescription.vue +12 -0
  32. package/src/components/headless/HeadlessModalOverlay.vue +12 -0
  33. package/src/components/headless/HeadlessModalTitle.vue +12 -0
  34. package/src/components/headless/HeadlessSelect.vue +120 -0
  35. package/src/components/headless/{forms/AGHeadlessSelectError.vue → HeadlessSelectError.vue} +3 -4
  36. package/src/components/headless/HeadlessSelectLabel.vue +25 -0
  37. package/src/components/headless/HeadlessSelectOption.vue +34 -0
  38. package/src/components/headless/HeadlessSelectOptions.vue +42 -0
  39. package/src/components/headless/HeadlessSelectTrigger.vue +22 -0
  40. package/src/components/headless/HeadlessSelectValue.vue +18 -0
  41. package/src/components/headless/HeadlessToast.vue +18 -0
  42. package/src/components/headless/HeadlessToastAction.vue +13 -0
  43. package/src/components/headless/index.ts +19 -3
  44. package/src/components/index.ts +5 -10
  45. package/src/components/ui/AdvancedOptions.vue +18 -0
  46. package/src/components/ui/AlertModal.vue +17 -0
  47. package/src/components/ui/Button.vue +100 -0
  48. package/src/components/ui/Checkbox.vue +56 -0
  49. package/src/components/ui/ConfirmModal.vue +50 -0
  50. package/src/components/ui/DropdownMenu.vue +32 -0
  51. package/src/components/ui/DropdownMenuOption.vue +22 -0
  52. package/src/components/ui/DropdownMenuOptions.vue +44 -0
  53. package/src/components/ui/EditableContent.vue +82 -0
  54. package/src/components/ui/ErrorLogs.vue +19 -0
  55. package/src/components/ui/ErrorLogsModal.vue +48 -0
  56. package/src/components/ui/ErrorMessage.vue +15 -0
  57. package/src/components/ui/ErrorReportModal.vue +73 -0
  58. package/src/components/{modals/AGErrorReportModalButtons.vue → ui/ErrorReportModalButtons.vue} +28 -21
  59. package/src/components/ui/ErrorReportModalTitle.vue +24 -0
  60. package/src/components/{forms/AGForm.vue → ui/Form.vue} +4 -5
  61. package/src/components/ui/Input.vue +56 -0
  62. package/src/components/ui/Link.vue +12 -0
  63. package/src/components/ui/LoadingModal.vue +34 -0
  64. package/src/components/ui/Markdown.vue +85 -0
  65. package/src/components/ui/Modal.vue +123 -0
  66. package/src/components/{modals/AGModalContext.vue → ui/ModalContext.vue} +8 -9
  67. package/src/components/ui/ProgressBar.vue +51 -0
  68. package/src/components/ui/PromptModal.vue +38 -0
  69. package/src/components/ui/Select.vue +27 -0
  70. package/src/components/ui/SelectLabel.vue +17 -0
  71. package/src/components/ui/SelectOption.vue +29 -0
  72. package/src/components/ui/SelectOptions.vue +35 -0
  73. package/src/components/ui/SelectTrigger.vue +29 -0
  74. package/src/components/ui/SettingsModal.vue +15 -0
  75. package/src/components/{lib/AGStartupCrash.vue → ui/StartupCrash.vue} +7 -7
  76. package/src/components/ui/Toast.vue +46 -0
  77. package/src/components/ui/index.ts +32 -0
  78. package/src/directives/measure.ts +11 -5
  79. package/src/errors/Errors.ts +22 -20
  80. package/src/forms/{Form.test.ts → FormController.test.ts} +32 -9
  81. package/src/forms/{Form.ts → FormController.ts} +28 -27
  82. package/src/forms/index.ts +2 -3
  83. package/src/forms/utils.ts +35 -35
  84. package/src/index.css +73 -0
  85. package/src/lang/index.ts +4 -0
  86. package/src/lang/settings/Language.vue +48 -0
  87. package/src/lang/settings/index.ts +10 -0
  88. package/src/services/App.state.ts +11 -1
  89. package/src/services/App.ts +9 -1
  90. package/src/services/Events.test.ts +8 -8
  91. package/src/services/Events.ts +2 -8
  92. package/src/services/index.ts +3 -0
  93. package/src/ui/UI.state.ts +7 -12
  94. package/src/ui/UI.ts +115 -106
  95. package/src/ui/index.ts +23 -24
  96. package/src/utils/classes.ts +41 -0
  97. package/src/utils/composition/events.ts +2 -4
  98. package/src/utils/composition/forms.ts +20 -4
  99. package/src/utils/composition/state.ts +11 -2
  100. package/src/utils/index.ts +3 -1
  101. package/src/utils/types.ts +3 -0
  102. package/src/utils/vue.ts +28 -129
  103. package/src/components/AGAppLayout.vue +0 -16
  104. package/src/components/AGAppOverlays.vue +0 -41
  105. package/src/components/AGAppSnackbars.vue +0 -13
  106. package/src/components/composition.ts +0 -23
  107. package/src/components/constants.ts +0 -8
  108. package/src/components/contracts/shared.ts +0 -9
  109. package/src/components/forms/AGButton.vue +0 -44
  110. package/src/components/forms/AGCheckbox.vue +0 -42
  111. package/src/components/forms/AGInput.vue +0 -42
  112. package/src/components/forms/AGSelect.story.vue +0 -46
  113. package/src/components/forms/AGSelect.vue +0 -54
  114. package/src/components/forms/index.ts +0 -5
  115. package/src/components/headless/forms/AGHeadlessButton.ts +0 -3
  116. package/src/components/headless/forms/AGHeadlessButton.vue +0 -62
  117. package/src/components/headless/forms/AGHeadlessInput.ts +0 -41
  118. package/src/components/headless/forms/AGHeadlessInput.vue +0 -70
  119. package/src/components/headless/forms/AGHeadlessSelect.ts +0 -42
  120. package/src/components/headless/forms/AGHeadlessSelect.vue +0 -77
  121. package/src/components/headless/forms/AGHeadlessSelectOption.ts +0 -4
  122. package/src/components/headless/forms/AGHeadlessSelectOption.vue +0 -31
  123. package/src/components/headless/forms/AGHeadlessSelectOptions.vue +0 -19
  124. package/src/components/headless/forms/AGHeadlessSelectTrigger.vue +0 -25
  125. package/src/components/headless/forms/composition.ts +0 -10
  126. package/src/components/headless/forms/index.ts +0 -17
  127. package/src/components/headless/modals/AGHeadlessModal.ts +0 -33
  128. package/src/components/headless/modals/AGHeadlessModal.vue +0 -88
  129. package/src/components/headless/modals/AGHeadlessModalContent.vue +0 -25
  130. package/src/components/headless/modals/index.ts +0 -5
  131. package/src/components/headless/snackbars/AGHeadlessSnackbar.vue +0 -10
  132. package/src/components/headless/snackbars/index.ts +0 -40
  133. package/src/components/lib/AGErrorMessage.vue +0 -16
  134. package/src/components/lib/AGLink.vue +0 -9
  135. package/src/components/lib/AGMarkdown.vue +0 -54
  136. package/src/components/lib/AGMeasured.vue +0 -16
  137. package/src/components/lib/AGProgressBar.vue +0 -55
  138. package/src/components/lib/index.ts +0 -6
  139. package/src/components/modals/AGAlertModal.ts +0 -18
  140. package/src/components/modals/AGAlertModal.vue +0 -14
  141. package/src/components/modals/AGConfirmModal.ts +0 -42
  142. package/src/components/modals/AGConfirmModal.vue +0 -27
  143. package/src/components/modals/AGErrorReportModal.ts +0 -49
  144. package/src/components/modals/AGErrorReportModal.vue +0 -54
  145. package/src/components/modals/AGErrorReportModalTitle.vue +0 -25
  146. package/src/components/modals/AGLoadingModal.ts +0 -29
  147. package/src/components/modals/AGLoadingModal.vue +0 -15
  148. package/src/components/modals/AGModal.vue +0 -40
  149. package/src/components/modals/AGModalContext.ts +0 -8
  150. package/src/components/modals/AGModalTitle.vue +0 -9
  151. package/src/components/modals/AGPromptModal.ts +0 -41
  152. package/src/components/modals/AGPromptModal.vue +0 -35
  153. package/src/components/modals/index.ts +0 -16
  154. package/src/components/snackbars/AGSnackbar.vue +0 -36
  155. package/src/components/snackbars/index.ts +0 -3
  156. package/src/components/utils.ts +0 -63
  157. package/src/forms/composition.ts +0 -6
  158. package/src/utils/tailwindcss.test.ts +0 -26
  159. package/src/utils/tailwindcss.ts +0 -7
package/src/ui/index.ts CHANGED
@@ -1,17 +1,16 @@
1
- import type { Component } from 'vue';
2
-
1
+ import AlertModal from '@aerogel/core/components/ui/AlertModal.vue';
2
+ import ConfirmModal from '@aerogel/core/components/ui/ConfirmModal.vue';
3
+ import ErrorReportModal from '@aerogel/core/components/ui/ErrorReportModal.vue';
4
+ import LoadingModal from '@aerogel/core/components/ui/LoadingModal.vue';
5
+ import PromptModal from '@aerogel/core/components/ui/PromptModal.vue';
6
+ import StartupCrash from '@aerogel/core/components/ui/StartupCrash.vue';
7
+ import Toast from '@aerogel/core/components/ui/Toast.vue';
3
8
  import { bootServices } from '@aerogel/core/services';
4
9
  import { definePlugin } from '@aerogel/core/plugins';
5
10
 
6
- 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
- import type { UIComponent } from './UI';
11
+ import UI from './UI';
12
+ import type { UIComponents } from './UI';
13
+ import type { Component } from 'vue';
15
14
 
16
15
  const services = { $ui: UI };
17
16
 
@@ -23,20 +22,20 @@ export type UIServices = typeof services;
23
22
 
24
23
  export default definePlugin({
25
24
  async install(app, options) {
26
- const defaultComponents = {
27
- [UIComponents.AlertModal]: AGAlertModal,
28
- [UIComponents.ConfirmModal]: AGConfirmModal,
29
- [UIComponents.ErrorReportModal]: AGErrorReportModal,
30
- [UIComponents.LoadingModal]: AGLoadingModal,
31
- [UIComponents.PromptModal]: AGPromptModal,
32
- [UIComponents.Snackbar]: AGSnackbar,
33
- [UIComponents.StartupCrash]: AGStartupCrash,
25
+ const components: Partial<Record<keyof UIComponents, Component>> = {
26
+ 'alert-modal': AlertModal,
27
+ 'confirm-modal': ConfirmModal,
28
+ 'error-report-modal': ErrorReportModal,
29
+ 'loading-modal': LoadingModal,
30
+ 'prompt-modal': PromptModal,
31
+ 'startup-crash': StartupCrash,
32
+ 'toast': Toast,
33
+ ...options.components,
34
34
  };
35
35
 
36
- Object.entries({
37
- ...defaultComponents,
38
- ...options.components,
39
- }).forEach(([name, component]) => UI.registerComponent(name as UIComponent, component));
36
+ for (const [name, component] of Object.entries(components)) {
37
+ UI.registerComponent(name as keyof UIComponents, component as UIComponents[keyof UIComponents]);
38
+ }
40
39
 
41
40
  await bootServices(app, services);
42
41
  },
@@ -44,7 +43,7 @@ export default definePlugin({
44
43
 
45
44
  declare module '@aerogel/core/bootstrap/options' {
46
45
  export interface AerogelOptions {
47
- components?: Partial<Record<UIComponent, Component>>;
46
+ components?: Partial<Partial<UIComponents>>;
48
47
  }
49
48
  }
50
49
 
@@ -0,0 +1,41 @@
1
+ import clsx from 'clsx';
2
+ import { unref } from 'vue';
3
+ import { cva } from 'class-variance-authority';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import type { ClassValue } from 'clsx';
6
+ import type { PropType } from 'vue';
7
+ import type { GetClosureArgs, GetClosureResult } from '@noeldemartin/utils';
8
+
9
+ export type CVAConfig<T> = NonNullable<GetClosureArgs<typeof cva<T>>[1]>;
10
+ export type CVAProps<T> = NonNullable<GetClosureArgs<GetClosureResult<typeof cva<T>>>[0]>;
11
+ export type Variants<T extends Record<string, string | boolean>> = Required<{
12
+ [K in keyof T]: Exclude<T[K], undefined> extends string
13
+ ? { [key in Exclude<T[K], undefined>]: string | null }
14
+ : { true: string | null; false: string | null };
15
+ }>;
16
+
17
+ export type ComponentPropDefinitions<T> = {
18
+ [K in keyof T]: {
19
+ type?: PropType<T[K]>;
20
+ default: T[K] | (() => T[K]) | null;
21
+ };
22
+ };
23
+
24
+ export type PickComponentProps<TValues, TDefinitions> = {
25
+ [K in keyof TValues]: K extends keyof TDefinitions ? TValues[K] : never;
26
+ };
27
+
28
+ export function variantClasses<T>(
29
+ value: { baseClasses?: string } & CVAProps<T>,
30
+ config: { baseClasses?: string } & CVAConfig<T>,
31
+ ): string {
32
+ const { baseClasses: valueBaseClasses, ...values } = value;
33
+ const { baseClasses: configBaseClasses, ...configs } = config;
34
+ const variants = cva(configBaseClasses, configs as CVAConfig<T>);
35
+
36
+ return classes(variants(values as CVAProps<T>), unref(valueBaseClasses));
37
+ }
38
+
39
+ export function classes(...inputs: ClassValue[]): string {
40
+ return twMerge(clsx(inputs));
41
+ }
@@ -6,7 +6,6 @@ import type {
6
6
  EventWithPayload,
7
7
  EventWithoutPayload,
8
8
  EventsPayload,
9
- UnknownEvent,
10
9
  } from '@aerogel/core/services/Events';
11
10
 
12
11
  export function useEvent<Event extends EventWithoutPayload>(event: Event, listener: () => unknown): void;
@@ -14,11 +13,10 @@ export function useEvent<Event extends EventWithPayload>(
14
13
  event: Event,
15
14
  listener: EventListener<EventsPayload[Event]>
16
15
  ): void;
17
- export function useEvent<Payload>(event: string, listener: (payload: Payload) => unknown): void;
18
- export function useEvent<Event extends string>(event: UnknownEvent<Event>, listener: EventListener): void;
19
16
 
20
17
  export function useEvent(event: string, listener: EventListener): void {
21
- const unsubscribe = Events.on(event, listener);
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ const unsubscribe = Events.on(event as any, listener);
22
20
 
23
21
  onUnmounted(() => unsubscribe());
24
22
  }
@@ -1,11 +1,27 @@
1
1
  import { objectWithout } from '@noeldemartin/utils';
2
- import { computed, useAttrs } from 'vue';
2
+ import { computed, inject, onUnmounted, useAttrs } from 'vue';
3
+ import type { ClassValue } from 'clsx';
3
4
  import type { ComputedRef } from 'vue';
5
+ import type { Nullable } from '@noeldemartin/utils';
4
6
 
5
- export function useInputAttrs(): [ComputedRef<{}>, ComputedRef<unknown>] {
7
+ import FormController from '@aerogel/core/forms/FormController';
8
+ import type { FormData, FormFieldDefinitions } from '@aerogel/core/forms/FormController';
9
+
10
+ export function onFormFocus(input: { name: Nullable<string> }, listener: () => unknown): void {
11
+ const form = inject<FormController | null>('form', null);
12
+ const stop = form?.on('focus', (name) => input.name === name && listener());
13
+
14
+ onUnmounted(() => stop?.());
15
+ }
16
+
17
+ export function useForm<const T extends FormFieldDefinitions>(fields: T): FormController<T> & FormData<T> {
18
+ return new FormController(fields) as FormController<T> & FormData<T>;
19
+ }
20
+
21
+ export function useInputAttrs(): [ComputedRef<{}>, ComputedRef<ClassValue>] {
6
22
  const attrs = useAttrs();
7
- const className = computed(() => attrs.class);
23
+ const classes = computed(() => attrs.class);
8
24
  const inputAttrs = computed(() => objectWithout(attrs, 'class'));
9
25
 
10
- return [inputAttrs, className];
26
+ return [inputAttrs, classes as ComputedRef<ClassValue>];
11
27
  }
@@ -1,12 +1,21 @@
1
1
  import { debounce } from '@noeldemartin/utils';
2
- import { ref, watchEffect } from 'vue';
3
- import type { ComputedGetter, ComputedRef } from '@vue/runtime-core';
2
+ import { computed, ref, watch, watchEffect } from 'vue';
3
+ import type { ComputedGetter, ComputedRef, Ref } from 'vue';
4
4
 
5
5
  export interface ComputedDebounceOptions<T> {
6
6
  initial?: T;
7
7
  delay?: number;
8
8
  }
9
9
 
10
+ export function computedAsync<T>(getter: () => Promise<T>): Ref<T | undefined> {
11
+ const result = ref<T>();
12
+ const asyncValue = computed(getter);
13
+
14
+ watch(asyncValue, async () => (result.value = await asyncValue.value), { immediate: true });
15
+
16
+ return result;
17
+ }
18
+
10
19
  export function computedDebounce<T>(options: ComputedDebounceOptions<T>, getter: ComputedGetter<T>): ComputedRef<T>;
11
20
  export function computedDebounce<T>(getter: ComputedGetter<T>): ComputedRef<T | null>;
12
21
  export function computedDebounce<T>(
@@ -1,7 +1,9 @@
1
+ export * from './classes';
1
2
  export * from './composition/events';
2
3
  export * from './composition/forms';
3
4
  export * from './composition/hooks';
4
5
  export * from './composition/persistent';
6
+ export * from './composition/state';
5
7
  export * from './markdown';
6
- export * from './tailwindcss';
8
+ export * from './types';
7
9
  export * from './vue';
@@ -0,0 +1,3 @@
1
+ import type { Nullable } from '@noeldemartin/utils';
2
+
3
+ export type Falsifiable<T> = Nullable<T> | false;
package/src/utils/vue.ts CHANGED
@@ -1,59 +1,26 @@
1
1
  import { fail, toString } from '@noeldemartin/utils';
2
- import { computed, inject, reactive, ref, watch } from 'vue';
3
- import type { Directive, InjectionKey, MaybeRef, PropType, Ref, UnwrapNestedRefs } from 'vue';
2
+ import { Comment, Static, Text, inject, reactive } from 'vue';
3
+ import type { Directive, InjectionKey, MaybeRef, Ref, UnwrapNestedRefs, VNode } from 'vue';
4
4
 
5
5
  export type AcceptRefs<T> = { [K in keyof T]: T[K] | RefUnion<T[K]> };
6
- export type BaseProp<T> = { type?: PropType<T>; validator?(value: unknown): boolean };
7
- export type ComponentProps<T = {}> = T & Record<string, unknown>;
8
- export type OptionalProp<T> = BaseProp<T> & { default: T | (() => T) | null };
9
6
  export type RefUnion<T> = T extends infer R ? Ref<R> : never;
10
- export type RequiredProp<T> = BaseProp<T> & { required: true };
11
7
  export type Unref<T> = { [K in keyof T]: T[K] extends MaybeRef<infer Value> ? Value : T[K] };
12
8
 
13
- export function arrayProp<T>(defaultValue?: () => T[]): OptionalProp<T[]> {
14
- return {
15
- type: Array as PropType<T[]>,
16
- default: defaultValue ?? (() => []),
17
- };
9
+ function renderVNodeAttrs(node: VNode): string {
10
+ return Object.entries(node.props ?? {}).reduce((attrs, [name, value]) => {
11
+ return attrs + `${name}="${toString(value)}"`;
12
+ }, '');
18
13
  }
19
14
 
20
- export function booleanProp(defaultValue: boolean = false): OptionalProp<boolean> {
21
- return {
22
- type: Boolean,
23
- default: defaultValue,
24
- };
25
- }
26
-
27
- export function componentRef<T>(): Ref<UnwrapNestedRefs<T> | undefined> {
28
- return ref<UnwrapNestedRefs<T>>();
29
- }
30
-
31
- export function computedAsync<T>(getter: () => Promise<T>): Ref<T | undefined> {
32
- const result = ref<T>();
33
- const asyncValue = computed(getter);
34
-
35
- watch(asyncValue, async () => (result.value = await asyncValue.value), { immediate: true });
36
-
37
- return result;
38
- }
39
-
40
- export function defineDirective(directive: Directive): Directive {
15
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
16
+ export function defineDirective<TValue = any, TModifiers extends string = string>(
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ directive: Directive<any, TValue, TModifiers>,
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ ): Directive<any, TValue, TModifiers> {
41
21
  return directive;
42
22
  }
43
23
 
44
- export function enumProp<Enum extends Record<string, unknown>>(
45
- enumeration: Enum,
46
- defaultValue?: Enum[keyof Enum],
47
- ): OptionalProp<Enum[keyof Enum]> {
48
- const values = Object.values(enumeration) as Enum[keyof Enum][];
49
-
50
- return {
51
- type: String as unknown as PropType<Enum[keyof Enum]>,
52
- default: defaultValue ?? values[0] ?? null,
53
- validator: (value) => values.includes(value as Enum[keyof Enum]),
54
- };
55
- }
56
-
57
24
  export function injectReactive<T extends object>(key: InjectionKey<T> | string): UnwrapNestedRefs<T> | undefined {
58
25
  const value = inject(key);
59
26
 
@@ -71,92 +38,24 @@ export function injectOrFail<T>(key: InjectionKey<T> | string, errorMessage?: st
71
38
  return inject(key) ?? fail(errorMessage ?? `Could not resolve '${toString(key)}' injection key`);
72
39
  }
73
40
 
74
- export function listenerProp<T extends Function = Function>(): OptionalProp<T | null> {
75
- return {
76
- type: Function as PropType<T>,
77
- default: null,
78
- };
79
- }
80
-
81
- export function mixedProp<T>(type?: PropType<T>): OptionalProp<T | null>;
82
- export function mixedProp<T>(type: PropType<T>, defaultValue: T): OptionalProp<T>;
83
- export function mixedProp<T>(type?: PropType<T>, defaultValue?: T): OptionalProp<T | null> {
84
- return {
85
- type,
86
- default: defaultValue ?? null,
87
- };
88
- }
89
-
90
- export function numberProp(): OptionalProp<number | null>;
91
- export function numberProp(defaultValue: number): OptionalProp<number>;
92
- export function numberProp(defaultValue: number | null = null): OptionalProp<number | null> {
93
- return {
94
- type: Number,
95
- default: defaultValue,
96
- };
97
- }
98
-
99
- export function objectProp<T = Object>(): OptionalProp<T | null>;
100
- export function objectProp<T>(defaultValue: () => T): OptionalProp<T>;
101
- export function objectProp<T = Object>(defaultValue: (() => T) | null = null): OptionalProp<T | null> {
102
- return {
103
- type: Object,
104
- default: defaultValue,
105
- };
106
- }
107
-
108
- export function requiredArrayProp<T>(): RequiredProp<T[]> {
109
- return {
110
- type: Array as PropType<T[]>,
111
- required: true,
112
- };
113
- }
114
-
115
- export function requiredEnumProp<Enum extends Record<string, unknown>>(
116
- enumeration: Enum,
117
- ): RequiredProp<Enum[keyof Enum]> {
118
- const values = Object.values(enumeration);
41
+ export function renderVNode(node: VNode | string): string {
42
+ if (typeof node === 'string') {
43
+ return node;
44
+ }
119
45
 
120
- return {
121
- type: String as unknown as PropType<Enum[keyof Enum]>,
122
- required: true,
123
- validator: (value) => values.includes(value),
124
- };
125
- }
126
-
127
- export function requiredMixedProp<T>(type?: PropType<T>): RequiredProp<T> {
128
- return {
129
- type,
130
- required: true,
131
- };
132
- }
46
+ if (node.type === Comment) {
47
+ return '';
48
+ }
133
49
 
134
- export function requiredNumberProp(): RequiredProp<number> {
135
- return {
136
- type: Number,
137
- required: true,
138
- };
139
- }
50
+ if (node.type === Text || node.type === Static) {
51
+ return node.children as string;
52
+ }
140
53
 
141
- export function requiredObjectProp<T = Object>(): RequiredProp<T> {
142
- return {
143
- type: Object,
144
- required: true,
145
- };
146
- }
147
-
148
- export function requiredStringProp(): RequiredProp<string> {
149
- return {
150
- type: String,
151
- required: true,
152
- };
153
- }
54
+ if (node.type === 'br') {
55
+ return '\n\n';
56
+ }
154
57
 
155
- export function stringProp(): OptionalProp<string | null>;
156
- export function stringProp(defaultValue: string): OptionalProp<string>;
157
- export function stringProp(defaultValue: string | null = null): OptionalProp<string | null> {
158
- return {
159
- type: String,
160
- default: defaultValue,
161
- };
58
+ return `<${node.type} ${renderVNodeAttrs(node)}>${Array.from(node.children as Array<VNode | string>)
59
+ .map(renderVNode)
60
+ .join('')}</${node.type}>`;
162
61
  }
@@ -1,16 +0,0 @@
1
- <template>
2
- <div class="flex min-h-full flex-col text-base font-normal leading-tight text-gray-900 antialiased">
3
- <slot v-if="$errors.hasStartupErrors" name="startup-crash">
4
- <component :is="$ui.requireComponent(UIComponents.StartupCrash)" />
5
- </slot>
6
- <slot v-else />
7
-
8
- <AGAppOverlays />
9
- </div>
10
- </template>
11
-
12
- <script setup lang="ts">
13
- import { UIComponents } from '@aerogel/core/ui/UI';
14
-
15
- import AGAppOverlays from './AGAppOverlays.vue';
16
- </script>
@@ -1,41 +0,0 @@
1
- <template>
2
- <div
3
- id="aerogel-overlays-backdrop"
4
- ref="$backdrop"
5
- class="pointer-events-none fixed inset-0 z-50 bg-black/30 opacity-0"
6
- />
7
- <AGAppModals />
8
- <AGAppSnackbars />
9
- </template>
10
-
11
- <script setup lang="ts">
12
- import { ref } from 'vue';
13
-
14
- import { useEvent } from '@aerogel/core/utils/composition/events';
15
-
16
- import AGAppModals from './AGAppModals.vue';
17
- import AGAppSnackbars from './AGAppSnackbars.vue';
18
-
19
- const $backdrop = ref<HTMLElement | null>(null);
20
- const backdropHidden = ref(true);
21
-
22
- useEvent('show-overlays-backdrop', async () => {
23
- if (!$backdrop.value || !backdropHidden.value) {
24
- return;
25
- }
26
-
27
- backdropHidden.value = false;
28
-
29
- $backdrop.value.classList.remove('opacity-0');
30
- });
31
-
32
- useEvent('hide-overlays-backdrop', async () => {
33
- if (!$backdrop.value || backdropHidden.value) {
34
- return;
35
- }
36
-
37
- backdropHidden.value = true;
38
-
39
- $backdrop.value.classList.add('opacity-0');
40
- });
41
- </script>
@@ -1,13 +0,0 @@
1
- <template>
2
- <div aria-live="assertive" class="pointer-events-none fixed inset-0 z-50 flex items-end px-4 py-6 sm:p-6">
3
- <div class="flex w-full flex-col items-end space-y-4">
4
- <component
5
- :is="snackbar.component"
6
- v-for="snackbar of $ui.snackbars"
7
- :id="snackbar.id"
8
- :key="snackbar.id"
9
- v-bind="snackbar.properties"
10
- />
11
- </div>
12
- </div>
13
- </template>
@@ -1,23 +0,0 @@
1
- import { customRef } from 'vue';
2
- import type { Ref } from 'vue';
3
-
4
- import { getElement } from '@aerogel/core/components/utils';
5
-
6
- export function elementRef(): Ref<HTMLElement | undefined> {
7
- return customRef((track, trigger) => {
8
- let value: HTMLElement | undefined = undefined;
9
-
10
- return {
11
- get() {
12
- track();
13
-
14
- return value;
15
- },
16
- set(newValue) {
17
- value = getElement(newValue);
18
-
19
- trigger();
20
- },
21
- };
22
- });
23
- }
@@ -1,8 +0,0 @@
1
- export const Colors = {
2
- Primary: 'primary',
3
- Secondary: 'secondary',
4
- Danger: 'danger',
5
- Clear: 'clear',
6
- } as const;
7
-
8
- export type Color = (typeof Colors)[keyof typeof Colors];
@@ -1,9 +0,0 @@
1
- import type { Ref } from 'vue';
2
-
3
- export interface HasElement {
4
- $el: Readonly<Ref<HTMLElement | undefined>>;
5
- }
6
-
7
- export interface __SetsElement {
8
- __setElement(element?: HTMLElement): void;
9
- }
@@ -1,44 +0,0 @@
1
- <template>
2
- <AGHeadlessButton class="px-2.5 py-1.5 focus-visible:outline focus-visible:outline-2" :class="colorClasses">
3
- <slot />
4
- </AGHeadlessButton>
5
- </template>
6
-
7
- <script setup lang="ts">
8
- import { computed } from 'vue';
9
-
10
- import { enumProp } from '@aerogel/core/utils/vue';
11
- import { Colors } from '@aerogel/core/components/constants';
12
-
13
- import AGHeadlessButton from '../headless/forms/AGHeadlessButton.vue';
14
-
15
- const props = defineProps({
16
- color: enumProp(Colors, Colors.Primary),
17
- });
18
-
19
- const colorClasses = computed(() => {
20
- switch (props.color) {
21
- case Colors.Secondary:
22
- return [
23
- 'text-white bg-gray-600',
24
- 'hover:bg-gray-500',
25
- 'focus-visible:outline-offset-2 focus-visible:outline-gray-600',
26
- ].join(' ');
27
- case Colors.Clear:
28
- return 'hover:bg-gray-500/20 focus-visible:outline-gray-500/60';
29
- case Colors.Danger:
30
- return [
31
- 'text-white bg-red-600',
32
- 'hover:bg-red-500',
33
- 'focus-visible:outline-offset-2 focus-visible:outline-red-600',
34
- ].join(' ');
35
- case Colors.Primary:
36
- default:
37
- return [
38
- 'text-white bg-indigo-600',
39
- 'hover:bg-indigo-500',
40
- 'focus-visible:outline-offset-2 focus-visible:outline-indigo-600',
41
- ].join(' ');
42
- }
43
- });
44
- </script>
@@ -1,42 +0,0 @@
1
- <template>
2
- <AGHeadlessInput
3
- ref="$input"
4
- :name="name"
5
- class="flex"
6
- @update:model-value="$emit('update:modelValue', $event)"
7
- >
8
- <AGHeadlessInputInput
9
- v-bind="$attrs"
10
- type="checkbox"
11
- :class="{
12
- 'text-indigo-600 focus:ring-indigo-600': !$input?.errors,
13
- 'border-red-200 text-red-600 focus:ring-red-600': $input?.errors,
14
- }"
15
- />
16
-
17
- <div class="ml-2">
18
- <AGHeadlessInputLabel v-if="$slots.default">
19
- <slot />
20
- </AGHeadlessInputLabel>
21
- <AGHeadlessInputError class="text-sm text-red-600" />
22
- </div>
23
- </AGHeadlessInput>
24
- </template>
25
-
26
- <script setup lang="ts">
27
- import { componentRef, stringProp } from '@aerogel/core/utils/vue';
28
-
29
- import { useInputEmits } from '@aerogel/core/components/headless/forms/AGHeadlessInput';
30
- import type { IAGHeadlessInput } from '@aerogel/core/components/headless/forms/AGHeadlessInput';
31
-
32
- import AGHeadlessInput from '../headless/forms/AGHeadlessInput.vue';
33
- import AGHeadlessInputError from '../headless/forms/AGHeadlessInputError.vue';
34
- import AGHeadlessInputInput from '../headless/forms/AGHeadlessInputInput.vue';
35
- import AGHeadlessInputLabel from '../headless/forms/AGHeadlessInputLabel.vue';
36
-
37
- defineProps({ name: stringProp() });
38
- defineOptions({ inheritAttrs: false });
39
- defineEmits(useInputEmits());
40
-
41
- const $input = componentRef<IAGHeadlessInput>();
42
- </script>
@@ -1,42 +0,0 @@
1
- <template>
2
- <AGHeadlessInput
3
- ref="$input"
4
- class="relative flex flex-col items-center"
5
- :class="className"
6
- v-bind="props"
7
- @update:model-value="$emit('update:modelValue', $event)"
8
- >
9
- <AGHeadlessInputLabel class="sr-only" />
10
- <AGHeadlessInputInput
11
- v-bind="attrs"
12
- class="block w-full border-0 py-1.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600"
13
- :class="{
14
- 'ring-1 ring-red-500': $input?.errors,
15
- }"
16
- />
17
- <AGHeadlessInputDescription />
18
- <div class="absolute bottom-0 left-0 translate-y-full">
19
- <AGHeadlessInputError class="mt-1 text-sm text-red-500" />
20
- </div>
21
- </AGHeadlessInput>
22
- </template>
23
-
24
- <script setup lang="ts">
25
- import { componentRef } from '@aerogel/core/utils/vue';
26
- import { useInputAttrs } from '@aerogel/core/utils/composition/forms';
27
- import { useInputEmits, useInputProps } from '@aerogel/core/components/headless/forms/AGHeadlessInput';
28
- import type { IAGHeadlessInput } from '@aerogel/core/components/headless/forms/AGHeadlessInput';
29
-
30
- import AGHeadlessInput from '../headless/forms/AGHeadlessInput.vue';
31
- import AGHeadlessInputDescription from '../headless/forms/AGHeadlessInputDescription.vue';
32
- import AGHeadlessInputError from '../headless/forms/AGHeadlessInputError.vue';
33
- import AGHeadlessInputInput from '../headless/forms/AGHeadlessInputInput.vue';
34
- import AGHeadlessInputLabel from '../headless/forms/AGHeadlessInputLabel.vue';
35
-
36
- defineOptions({ inheritAttrs: false });
37
- defineEmits(useInputEmits());
38
-
39
- const props = defineProps(useInputProps());
40
- const $input = componentRef<IAGHeadlessInput>();
41
- const [attrs, className] = useInputAttrs();
42
- </script>