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

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 (148) hide show
  1. package/dist/aerogel-core.d.ts +1615 -1452
  2. package/dist/aerogel-core.js +2505 -2003
  3. package/dist/aerogel-core.js.map +1 -1
  4. package/package.json +10 -3
  5. package/src/components/{AGAppLayout.vue → AppLayout.vue} +3 -3
  6. package/src/components/{AGAppModals.vue → AppModals.vue} +2 -3
  7. package/src/components/{AGAppOverlays.vue → AppOverlays.vue} +4 -9
  8. package/src/components/AppToasts.vue +16 -0
  9. package/src/components/contracts/AlertModal.ts +4 -0
  10. package/src/components/contracts/Button.ts +16 -0
  11. package/src/components/contracts/ConfirmModal.ts +41 -0
  12. package/src/components/contracts/DropdownMenu.ts +20 -0
  13. package/src/components/{modals/AGErrorReportModal.ts → contracts/ErrorReportModal.ts} +3 -23
  14. package/src/components/contracts/Input.ts +26 -0
  15. package/src/components/contracts/LoadingModal.ts +22 -0
  16. package/src/components/contracts/Modal.ts +14 -9
  17. package/src/components/contracts/PromptModal.ts +30 -0
  18. package/src/components/contracts/Select.ts +44 -0
  19. package/src/components/contracts/Toast.ts +13 -0
  20. package/src/components/contracts/index.ts +10 -1
  21. package/src/components/headless/HeadlessButton.vue +51 -0
  22. package/src/components/headless/HeadlessInput.vue +59 -0
  23. package/src/components/headless/{forms/AGHeadlessInputDescription.vue → HeadlessInputDescription.vue} +6 -7
  24. package/src/components/headless/{forms/AGHeadlessInputError.vue → HeadlessInputError.vue} +2 -6
  25. package/src/components/headless/{forms/AGHeadlessInputInput.vue → HeadlessInputInput.vue} +16 -25
  26. package/src/components/headless/{forms/AGHeadlessInputLabel.vue → HeadlessInputLabel.vue} +2 -6
  27. package/src/components/headless/{forms/AGHeadlessInputTextArea.vue → HeadlessInputTextArea.vue} +9 -12
  28. package/src/components/headless/{modals/AGHeadlessModal.vue → HeadlessModal.vue} +47 -43
  29. package/src/components/headless/HeadlessModalContent.vue +30 -0
  30. package/src/components/headless/HeadlessModalDescription.vue +12 -0
  31. package/src/components/headless/HeadlessModalOverlay.vue +12 -0
  32. package/src/components/headless/HeadlessModalTitle.vue +12 -0
  33. package/src/components/headless/HeadlessSelect.vue +113 -0
  34. package/src/components/headless/{forms/AGHeadlessSelectError.vue → HeadlessSelectError.vue} +3 -4
  35. package/src/components/headless/HeadlessSelectLabel.vue +25 -0
  36. package/src/components/headless/HeadlessSelectOption.vue +34 -0
  37. package/src/components/headless/HeadlessSelectOptions.vue +37 -0
  38. package/src/components/headless/HeadlessSelectTrigger.vue +22 -0
  39. package/src/components/headless/HeadlessSelectValue.vue +18 -0
  40. package/src/components/headless/HeadlessToast.vue +18 -0
  41. package/src/components/headless/HeadlessToastAction.vue +13 -0
  42. package/src/components/headless/index.ts +19 -3
  43. package/src/components/index.ts +5 -10
  44. package/src/components/ui/AdvancedOptions.vue +18 -0
  45. package/src/components/ui/AlertModal.vue +13 -0
  46. package/src/components/ui/Button.vue +98 -0
  47. package/src/components/ui/Checkbox.vue +56 -0
  48. package/src/components/ui/ConfirmModal.vue +42 -0
  49. package/src/components/ui/DropdownMenu.vue +32 -0
  50. package/src/components/ui/DropdownMenuOption.vue +14 -0
  51. package/src/components/ui/DropdownMenuOptions.vue +27 -0
  52. package/src/components/ui/EditableContent.vue +82 -0
  53. package/src/components/ui/ErrorMessage.vue +15 -0
  54. package/src/components/ui/ErrorReportModal.vue +62 -0
  55. package/src/components/{modals/AGErrorReportModalButtons.vue → ui/ErrorReportModalButtons.vue} +28 -21
  56. package/src/components/ui/ErrorReportModalTitle.vue +24 -0
  57. package/src/components/{forms/AGForm.vue → ui/Form.vue} +4 -5
  58. package/src/components/ui/Input.vue +56 -0
  59. package/src/components/ui/Link.vue +12 -0
  60. package/src/components/ui/LoadingModal.vue +32 -0
  61. package/src/components/ui/Markdown.vue +69 -0
  62. package/src/components/ui/Modal.vue +91 -0
  63. package/src/components/{modals/AGModalContext.vue → ui/ModalContext.vue} +7 -9
  64. package/src/components/ui/ProgressBar.vue +51 -0
  65. package/src/components/ui/PromptModal.vue +35 -0
  66. package/src/components/ui/Select.vue +25 -0
  67. package/src/components/ui/SelectLabel.vue +17 -0
  68. package/src/components/ui/SelectOption.vue +29 -0
  69. package/src/components/ui/SelectOptions.vue +30 -0
  70. package/src/components/ui/SelectTrigger.vue +29 -0
  71. package/src/components/ui/SettingsModal.vue +15 -0
  72. package/src/components/{lib/AGStartupCrash.vue → ui/StartupCrash.vue} +7 -7
  73. package/src/components/ui/Toast.vue +42 -0
  74. package/src/components/ui/index.ts +30 -0
  75. package/src/errors/Errors.ts +9 -10
  76. package/src/forms/{Form.test.ts → FormController.test.ts} +2 -2
  77. package/src/forms/{Form.ts → FormController.ts} +5 -5
  78. package/src/forms/composition.ts +4 -4
  79. package/src/forms/index.ts +2 -2
  80. package/src/forms/utils.ts +2 -2
  81. package/src/index.css +54 -0
  82. package/src/lang/index.ts +4 -0
  83. package/src/lang/settings/Language.vue +48 -0
  84. package/src/lang/settings/index.ts +10 -0
  85. package/src/services/App.state.ts +11 -1
  86. package/src/services/App.ts +9 -1
  87. package/src/services/index.ts +3 -0
  88. package/src/ui/UI.state.ts +10 -5
  89. package/src/ui/UI.ts +59 -53
  90. package/src/ui/index.ts +14 -14
  91. package/src/utils/classes.ts +49 -0
  92. package/src/utils/composition/forms.ts +14 -4
  93. package/src/utils/composition/state.ts +11 -2
  94. package/src/utils/index.ts +3 -1
  95. package/src/utils/types.ts +3 -0
  96. package/src/utils/vue.ts +22 -128
  97. package/src/components/AGAppSnackbars.vue +0 -13
  98. package/src/components/composition.ts +0 -23
  99. package/src/components/constants.ts +0 -8
  100. package/src/components/contracts/shared.ts +0 -9
  101. package/src/components/forms/AGButton.vue +0 -44
  102. package/src/components/forms/AGCheckbox.vue +0 -42
  103. package/src/components/forms/AGInput.vue +0 -42
  104. package/src/components/forms/AGSelect.story.vue +0 -46
  105. package/src/components/forms/AGSelect.vue +0 -54
  106. package/src/components/forms/index.ts +0 -5
  107. package/src/components/headless/forms/AGHeadlessButton.ts +0 -3
  108. package/src/components/headless/forms/AGHeadlessButton.vue +0 -62
  109. package/src/components/headless/forms/AGHeadlessInput.ts +0 -41
  110. package/src/components/headless/forms/AGHeadlessInput.vue +0 -70
  111. package/src/components/headless/forms/AGHeadlessSelect.ts +0 -42
  112. package/src/components/headless/forms/AGHeadlessSelect.vue +0 -77
  113. package/src/components/headless/forms/AGHeadlessSelectOption.ts +0 -4
  114. package/src/components/headless/forms/AGHeadlessSelectOption.vue +0 -31
  115. package/src/components/headless/forms/AGHeadlessSelectOptions.vue +0 -19
  116. package/src/components/headless/forms/AGHeadlessSelectTrigger.vue +0 -25
  117. package/src/components/headless/forms/composition.ts +0 -10
  118. package/src/components/headless/forms/index.ts +0 -17
  119. package/src/components/headless/modals/AGHeadlessModal.ts +0 -33
  120. package/src/components/headless/modals/AGHeadlessModalContent.vue +0 -25
  121. package/src/components/headless/modals/index.ts +0 -5
  122. package/src/components/headless/snackbars/AGHeadlessSnackbar.vue +0 -10
  123. package/src/components/headless/snackbars/index.ts +0 -40
  124. package/src/components/lib/AGErrorMessage.vue +0 -16
  125. package/src/components/lib/AGLink.vue +0 -9
  126. package/src/components/lib/AGMarkdown.vue +0 -54
  127. package/src/components/lib/AGMeasured.vue +0 -16
  128. package/src/components/lib/AGProgressBar.vue +0 -55
  129. package/src/components/lib/index.ts +0 -6
  130. package/src/components/modals/AGAlertModal.ts +0 -18
  131. package/src/components/modals/AGAlertModal.vue +0 -14
  132. package/src/components/modals/AGConfirmModal.ts +0 -42
  133. package/src/components/modals/AGConfirmModal.vue +0 -27
  134. package/src/components/modals/AGErrorReportModal.vue +0 -54
  135. package/src/components/modals/AGErrorReportModalTitle.vue +0 -25
  136. package/src/components/modals/AGLoadingModal.ts +0 -29
  137. package/src/components/modals/AGLoadingModal.vue +0 -15
  138. package/src/components/modals/AGModal.vue +0 -40
  139. package/src/components/modals/AGModalContext.ts +0 -8
  140. package/src/components/modals/AGModalTitle.vue +0 -9
  141. package/src/components/modals/AGPromptModal.ts +0 -41
  142. package/src/components/modals/AGPromptModal.vue +0 -35
  143. package/src/components/modals/index.ts +0 -16
  144. package/src/components/snackbars/AGSnackbar.vue +0 -36
  145. package/src/components/snackbars/index.ts +0 -3
  146. package/src/components/utils.ts +0 -63
  147. package/src/utils/tailwindcss.test.ts +0 -26
  148. package/src/utils/tailwindcss.ts +0 -7
package/src/ui/index.ts CHANGED
@@ -1,16 +1,16 @@
1
1
  import type { Component } from 'vue';
2
2
 
3
+ import AlertModal from '@aerogel/core/components/ui/AlertModal.vue';
4
+ import ConfirmModal from '@aerogel/core/components/ui/ConfirmModal.vue';
5
+ import ErrorReportModal from '@aerogel/core/components/ui/ErrorReportModal.vue';
6
+ import LoadingModal from '@aerogel/core/components/ui/LoadingModal.vue';
7
+ import PromptModal from '@aerogel/core/components/ui/PromptModal.vue';
8
+ import StartupCrash from '@aerogel/core/components/ui/StartupCrash.vue';
9
+ import Toast from '@aerogel/core/components/ui/Toast.vue';
3
10
  import { bootServices } from '@aerogel/core/services';
4
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,13 +24,13 @@ export type UIServices = typeof services;
24
24
  export default definePlugin({
25
25
  async install(app, options) {
26
26
  const defaultComponents = {
27
- [UIComponents.AlertModal]: AGAlertModal,
28
- [UIComponents.ConfirmModal]: AGConfirmModal,
29
- [UIComponents.ErrorReportModal]: AGErrorReportModal,
30
- [UIComponents.LoadingModal]: AGLoadingModal,
31
- [UIComponents.PromptModal]: AGPromptModal,
32
- [UIComponents.Snackbar]: AGSnackbar,
33
- [UIComponents.StartupCrash]: AGStartupCrash,
27
+ [UIComponents.AlertModal]: AlertModal,
28
+ [UIComponents.ConfirmModal]: ConfirmModal,
29
+ [UIComponents.ErrorReportModal]: ErrorReportModal,
30
+ [UIComponents.LoadingModal]: LoadingModal,
31
+ [UIComponents.PromptModal]: PromptModal,
32
+ [UIComponents.Toast]: Toast,
33
+ [UIComponents.StartupCrash]: StartupCrash,
34
34
  };
35
35
 
36
36
  Object.entries({
@@ -0,0 +1,49 @@
1
+ import clsx from 'clsx';
2
+ import { computed, 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 { ComputedRef, PropType, Ref } 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 RefsObject<T> = { [K in keyof T]: Ref<T[K]> | T[K] };
12
+ export type Variants<T extends Record<string, string | boolean>> = Required<{
13
+ [K in keyof T]: Exclude<T[K], undefined> extends string
14
+ ? { [key in Exclude<T[K], undefined>]: string | null }
15
+ : { true: string | null; false: string | null };
16
+ }>;
17
+
18
+ export type ComponentPropDefinitions<T> = {
19
+ [K in keyof T]: {
20
+ type?: PropType<T[K]>;
21
+ default: T[K] | (() => T[K]) | null;
22
+ };
23
+ };
24
+
25
+ export type PickComponentProps<TValues, TDefinitions> = {
26
+ [K in keyof TValues]: K extends keyof TDefinitions ? TValues[K] : never;
27
+ };
28
+
29
+ export function computedVariantClasses<T>(
30
+ value: RefsObject<{ baseClasses?: string } & CVAProps<T>>,
31
+ config: { baseClasses?: string } & CVAConfig<T>,
32
+ ): ComputedRef<string> {
33
+ return computed(() => {
34
+ const { baseClasses: valueBaseClasses, ...valueRefs } = value;
35
+ const { baseClasses: configBaseClasses, ...configs } = config;
36
+ const variants = cva(configBaseClasses, configs as CVAConfig<T>);
37
+ const values = Object.entries(valueRefs).reduce((extractedValues, [name, valueRef]) => {
38
+ extractedValues[name as keyof CVAProps<T>] = unref(valueRef);
39
+
40
+ return extractedValues;
41
+ }, {} as CVAProps<T>);
42
+
43
+ return classes(variants(values), unref(valueBaseClasses));
44
+ });
45
+ }
46
+
47
+ export function classes(...inputs: ClassValue[]): string {
48
+ return twMerge(clsx(inputs));
49
+ }
@@ -1,11 +1,21 @@
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 { FormController } from '@aerogel/core/forms';
6
+ import type { Nullable } from '@noeldemartin/utils';
4
7
 
5
- export function useInputAttrs(): [ComputedRef<{}>, ComputedRef<unknown>] {
8
+ export function onFormFocus(input: { name: Nullable<string> }, listener: () => unknown): void {
9
+ const form = inject<FormController | null>('form', null);
10
+ const stop = form?.on('focus', (name) => input.name === name && listener());
11
+
12
+ onUnmounted(() => stop?.());
13
+ }
14
+
15
+ export function useInputAttrs(): [ComputedRef<{}>, ComputedRef<ClassValue>] {
6
16
  const attrs = useAttrs();
7
- const className = computed(() => attrs.class);
17
+ const classes = computed(() => attrs.class);
8
18
  const inputAttrs = computed(() => objectWithout(attrs, 'class'));
9
19
 
10
- return [inputAttrs, className];
20
+ return [inputAttrs, classes as ComputedRef<ClassValue>];
11
21
  }
@@ -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,21 @@
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
- };
18
- }
19
-
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;
9
+ function renderVNodeAttrs(node: VNode): string {
10
+ return Object.entries(node.props ?? {}).reduce((attrs, [name, value]) => {
11
+ return attrs + `${name}="${toString(value)}"`;
12
+ }, '');
38
13
  }
39
14
 
40
15
  export function defineDirective(directive: Directive): Directive {
41
16
  return directive;
42
17
  }
43
18
 
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
19
  export function injectReactive<T extends object>(key: InjectionKey<T> | string): UnwrapNestedRefs<T> | undefined {
58
20
  const value = inject(key);
59
21
 
@@ -71,92 +33,24 @@ export function injectOrFail<T>(key: InjectionKey<T> | string, errorMessage?: st
71
33
  return inject(key) ?? fail(errorMessage ?? `Could not resolve '${toString(key)}' injection key`);
72
34
  }
73
35
 
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);
36
+ export function renderVNode(node: VNode | string): string {
37
+ if (typeof node === 'string') {
38
+ return node;
39
+ }
119
40
 
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
- }
41
+ if (node.type === Comment) {
42
+ return '';
43
+ }
133
44
 
134
- export function requiredNumberProp(): RequiredProp<number> {
135
- return {
136
- type: Number,
137
- required: true,
138
- };
139
- }
45
+ if (node.type === Text || node.type === Static) {
46
+ return node.children as string;
47
+ }
140
48
 
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
- }
49
+ if (node.type === 'br') {
50
+ return '\n\n';
51
+ }
154
52
 
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
- };
53
+ return `<${node.type} ${renderVNodeAttrs(node)}>${Array.from(node.children as Array<VNode | string>)
54
+ .map(renderVNode)
55
+ .join('')}</${node.type}>`;
162
56
  }
@@ -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>
@@ -1,46 +0,0 @@
1
- <template>
2
- <Story>
3
- <div class="h-96">
4
- <AGSelect v-model="bestMugiwara" :label="bestMugiwaraLabel" :options="bestMugiwaraOptions" />
5
- <AGSelect
6
- v-model="bestFood"
7
- :label="bestFoodLabel"
8
- :options="bestFoodOptions"
9
- options-text="name"
10
- />
11
- </div>
12
- </Story>
13
- </template>
14
-
15
- <script setup lang="ts">
16
- import { ref } from 'vue';
17
-
18
- import AGSelect from './AGSelect.vue';
19
-
20
- const bestMugiwara = ref(null);
21
- const bestFood = ref(null);
22
- const bestMugiwaraLabel = 'Who\'s the best Mugiwara?';
23
- const bestFoodLabel = 'What\'s the best food?';
24
- const bestMugiwaraOptions = [
25
- 'Monkey D. Luffy',
26
- 'Roronoa Zoro',
27
- 'Nami',
28
- 'Usopp',
29
- 'Sanji',
30
- 'Tony Tony Chopper',
31
- 'Nico Robin',
32
- 'Franky',
33
- 'Brook',
34
- 'Jinbe',
35
- ];
36
- const bestFoodOptions = [
37
- {
38
- id: 'ramen',
39
- name: 'Ramen',
40
- },
41
- {
42
- id: 'pizza',
43
- name: 'Pizza',
44
- },
45
- ];
46
- </script>
@@ -1,54 +0,0 @@
1
- <template>
2
- <AGHeadlessSelect
3
- v-bind="props"
4
- ref="$select"
5
- as="div"
6
- @update:model-value="$emit('update:modelValue', $event)"
7
- >
8
- <div class="relative" :class="{ 'mt-2': $select?.label }">
9
- <AGHeadlessSelectTrigger
10
- class="relative w-full cursor-default bg-white py-1.5 pr-10 pl-3 text-left text-gray-900 ring-1 ring-gray-300 ring-inset focus:ring-2 focus:ring-indigo-600 focus:outline-hidden"
11
- text-class="block truncate"
12
- :class="{
13
- 'ring-1 ring-red-500': $select?.errors,
14
- }"
15
- >
16
- <template #icon>
17
- <span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
18
- <IconCheveronDown class="size-5 text-gray-400" />
19
- </span>
20
- </template>
21
- </AGHeadlessSelectTrigger>
22
- <AGHeadlessSelectOptions
23
- class="absolute z-10 mt-1 max-h-60 w-full overflow-auto border border-gray-300 bg-white py-1 text-base ring-1 ring-black/5 focus:outline-hidden"
24
- >
25
- <AGHeadlessSelectOption
26
- v-for="(option, index) in $select?.options ?? []"
27
- :key="index"
28
- :value="option"
29
- class="relative block cursor-default truncate py-2 pr-9 pl-3 text-gray-900 select-none data-[highlighted]:bg-indigo-600 data-[highlighted]:text-white data-[state=checked]:font-semibold data-[state=unchecked]:font-normal"
30
- />
31
- </AGHeadlessSelectOptions>
32
- </div>
33
- <AGHeadlessSelectError class="mt-2 text-sm text-red-600" />
34
- </AGHeadlessSelect>
35
- </template>
36
-
37
- <script setup lang="ts">
38
- import IconCheveronDown from '~icons/zondicons/cheveron-down';
39
-
40
- import { componentRef } from '@aerogel/core/utils/vue';
41
- import { useSelectEmits, useSelectProps } from '@aerogel/core/components/headless/forms/AGHeadlessSelect';
42
- import type { IAGHeadlessSelect } from '@aerogel/core/components/headless/forms/AGHeadlessSelect';
43
-
44
- import AGHeadlessSelect from '../headless/forms/AGHeadlessSelect.vue';
45
- import AGHeadlessSelectTrigger from '../headless/forms/AGHeadlessSelectTrigger.vue';
46
- import AGHeadlessSelectError from '../headless/forms/AGHeadlessSelectError.vue';
47
- import AGHeadlessSelectOption from '../headless/forms/AGHeadlessSelectOption.vue';
48
- import AGHeadlessSelectOptions from '../headless/forms/AGHeadlessSelectOptions.vue';
49
-
50
- defineEmits(useSelectEmits());
51
-
52
- const props = defineProps(useSelectProps());
53
- const $select = componentRef<IAGHeadlessSelect>();
54
- </script>
@@ -1,5 +0,0 @@
1
- export { default as AGButton } from './AGButton.vue';
2
- export { default as AGCheckbox } from './AGCheckbox.vue';
3
- export { default as AGForm } from './AGForm.vue';
4
- export { default as AGInput } from './AGInput.vue';
5
- export { default as AGSelect } from './AGSelect.vue';
@@ -1,3 +0,0 @@
1
- import type { HasElement } from '@aerogel/core/components/contracts/shared';
2
-
3
- export interface IAGHeadlessButton extends HasElement {}