@aerogel/core 0.0.0-next.b3caf219a503ce9b8c65ef1463132c9507f56c0a → 0.0.0-next.b656a964404fbde17d9cce7668722596098e47fd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aerogel-core.d.ts +958 -491
- package/dist/aerogel-core.js +1987 -1828
- package/dist/aerogel-core.js.map +1 -1
- package/package.json +5 -2
- package/src/components/AppModals.vue +1 -1
- package/src/components/AppOverlays.vue +2 -7
- package/src/components/AppToasts.vue +16 -0
- package/src/components/contracts/Button.ts +1 -0
- package/src/components/contracts/DropdownMenu.ts +11 -0
- package/src/components/contracts/Input.ts +5 -5
- package/src/components/contracts/Modal.ts +4 -0
- package/src/components/contracts/Select.ts +36 -0
- package/src/components/contracts/Toast.ts +13 -0
- package/src/components/contracts/index.ts +2 -0
- package/src/components/headless/HeadlessButton.vue +7 -2
- package/src/components/headless/HeadlessInputDescription.vue +3 -3
- package/src/components/headless/HeadlessInputInput.vue +4 -4
- package/src/components/headless/HeadlessInputTextArea.vue +3 -3
- package/src/components/headless/HeadlessModal.vue +4 -2
- package/src/components/headless/HeadlessModalOverlay.vue +2 -2
- package/src/components/headless/HeadlessModalTitle.vue +2 -2
- package/src/components/headless/HeadlessSelect.vue +104 -0
- package/src/components/headless/{forms/AGHeadlessSelectError.vue → HeadlessSelectError.vue} +3 -4
- package/src/components/headless/HeadlessSelectLabel.vue +25 -0
- package/src/components/headless/HeadlessSelectOption.vue +34 -0
- package/src/components/headless/HeadlessSelectOptions.vue +30 -0
- package/src/components/headless/HeadlessSelectTrigger.vue +22 -0
- package/src/components/headless/HeadlessSelectValue.vue +15 -0
- package/src/components/headless/HeadlessToast.vue +18 -0
- package/src/components/headless/HeadlessToastAction.vue +13 -0
- package/src/components/headless/index.ts +7 -3
- package/src/components/index.ts +4 -9
- package/src/components/ui/AdvancedOptions.vue +18 -0
- package/src/components/ui/AlertModal.vue +3 -3
- package/src/components/ui/Button.vue +56 -16
- package/src/components/ui/Checkbox.vue +18 -11
- package/src/components/ui/ConfirmModal.vue +4 -4
- package/src/components/ui/DropdownMenu.vue +33 -0
- package/src/components/ui/EditableContent.vue +82 -0
- package/src/components/ui/ErrorMessage.vue +15 -0
- package/src/components/ui/ErrorReportModal.vue +3 -3
- package/src/components/ui/ErrorReportModalButtons.vue +6 -8
- package/src/components/ui/ErrorReportModalTitle.vue +2 -2
- package/src/components/ui/Input.vue +9 -5
- package/src/components/ui/Link.vue +2 -2
- package/src/components/ui/LoadingModal.vue +5 -5
- package/src/components/ui/Markdown.vue +69 -0
- package/src/components/ui/Modal.vue +26 -11
- package/src/components/ui/ProgressBar.vue +1 -1
- package/src/components/ui/PromptModal.vue +6 -6
- package/src/components/ui/Select.vue +21 -0
- package/src/components/ui/SelectLabel.vue +10 -0
- package/src/components/ui/SelectOptions.vue +31 -0
- package/src/components/ui/SelectTrigger.vue +29 -0
- package/src/components/ui/SettingsModal.vue +15 -0
- package/src/components/{lib/AGStartupCrash.vue → ui/StartupCrash.vue} +3 -3
- package/src/components/ui/Toast.vue +42 -0
- package/src/components/ui/index.ts +12 -0
- package/src/errors/Errors.ts +4 -5
- package/src/index.css +38 -0
- package/src/lang/index.ts +3 -0
- package/src/lang/settings/Language.vue +48 -0
- package/src/lang/settings/index.ts +10 -0
- package/src/services/App.state.ts +11 -1
- package/src/services/App.ts +3 -0
- package/src/services/index.ts +3 -0
- package/src/ui/UI.state.ts +2 -2
- package/src/ui/UI.ts +12 -20
- package/src/ui/index.ts +4 -4
- package/src/utils/classes.ts +49 -0
- package/src/utils/composition/forms.ts +10 -1
- package/src/utils/composition/state.ts +11 -2
- package/src/utils/index.ts +2 -1
- package/src/utils/vue.ts +22 -128
- package/src/components/AppSnackbars.vue +0 -13
- package/src/components/composition.ts +0 -23
- package/src/components/constants.ts +0 -8
- package/src/components/forms/AGSelect.story.vue +0 -46
- package/src/components/forms/AGSelect.vue +0 -54
- package/src/components/forms/index.ts +0 -1
- package/src/components/headless/forms/AGHeadlessSelect.ts +0 -42
- package/src/components/headless/forms/AGHeadlessSelect.vue +0 -77
- package/src/components/headless/forms/AGHeadlessSelectOption.ts +0 -4
- package/src/components/headless/forms/AGHeadlessSelectOption.vue +0 -31
- package/src/components/headless/forms/AGHeadlessSelectOptions.vue +0 -19
- package/src/components/headless/forms/AGHeadlessSelectTrigger.vue +0 -25
- package/src/components/headless/forms/composition.ts +0 -10
- package/src/components/headless/forms/index.ts +0 -8
- package/src/components/headless/snackbars/AGHeadlessSnackbar.vue +0 -10
- package/src/components/headless/snackbars/index.ts +0 -40
- package/src/components/lib/AGErrorMessage.vue +0 -16
- package/src/components/lib/AGMarkdown.vue +0 -54
- package/src/components/lib/AGMeasured.vue +0 -16
- package/src/components/lib/index.ts +0 -4
- package/src/components/snackbars/AGSnackbar.vue +0 -38
- package/src/components/snackbars/index.ts +0 -3
- package/src/components/utils.ts +0 -107
- package/src/utils/tailwindcss.test.ts +0 -26
- package/src/utils/tailwindcss.ts +0 -7
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<details class="group">
|
|
3
|
+
<summary
|
|
4
|
+
class="-ml-2 flex w-[max-content] cursor-pointer items-center rounded-lg py-2 pr-3 pl-1 hover:bg-gray-100 focus-visible:outline focus-visible:outline-gray-700"
|
|
5
|
+
>
|
|
6
|
+
<IconCheveronRight class="size-6 transition-transform group-open:rotate-90" />
|
|
7
|
+
<span>{{ $td('ui.advancedOptions', 'Advanced options') }}</span>
|
|
8
|
+
</summary>
|
|
9
|
+
|
|
10
|
+
<div class="pt-2 pl-4">
|
|
11
|
+
<slot />
|
|
12
|
+
</div>
|
|
13
|
+
</details>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
import IconCheveronRight from '~icons/zondicons/cheveron-right';
|
|
18
|
+
</script>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Modal :title
|
|
3
|
-
<
|
|
2
|
+
<Modal :title>
|
|
3
|
+
<Markdown :text="message" />
|
|
4
4
|
</Modal>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script setup lang="ts">
|
|
8
8
|
import Modal from '@aerogel/core/components/ui/Modal.vue';
|
|
9
|
-
import
|
|
9
|
+
import Markdown from '@aerogel/core/components/ui/Markdown.vue';
|
|
10
10
|
import type { AlertModalProps } from '@aerogel/core/components/contracts/AlertModal';
|
|
11
11
|
|
|
12
12
|
defineProps<AlertModalProps>();
|
|
@@ -1,38 +1,42 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<HeadlessButton :class="renderedClasses" v-bind="props">
|
|
2
|
+
<HeadlessButton :class="renderedClasses" :disabled v-bind="props">
|
|
3
3
|
<slot />
|
|
4
4
|
</HeadlessButton>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script setup lang="ts">
|
|
8
8
|
import HeadlessButton from '@aerogel/core/components/headless/HeadlessButton.vue';
|
|
9
|
-
import { computedVariantClasses } from '@aerogel/core/
|
|
9
|
+
import { computedVariantClasses } from '@aerogel/core/utils/classes';
|
|
10
10
|
import type { ButtonProps } from '@aerogel/core/components/contracts/Button';
|
|
11
|
-
import type { Variants } from '@aerogel/core/
|
|
11
|
+
import type { Variants } from '@aerogel/core/utils/classes';
|
|
12
12
|
|
|
13
|
-
const { class: baseClasses, size, variant, ...props } = defineProps<ButtonProps>();
|
|
13
|
+
const { class: baseClasses, size, variant, disabled, ...props } = defineProps<ButtonProps>();
|
|
14
14
|
|
|
15
15
|
/* eslint-disable vue/max-len */
|
|
16
16
|
// prettier-ignore
|
|
17
|
-
const renderedClasses = computedVariantClasses<Variants<Pick<ButtonProps, 'size' | 'variant'>>>(
|
|
18
|
-
{ baseClasses, variant, size },
|
|
17
|
+
const renderedClasses = computedVariantClasses<Variants<Pick<ButtonProps, 'size' | 'variant' | 'disabled'>>>(
|
|
18
|
+
{ baseClasses, variant, size, disabled },
|
|
19
19
|
{
|
|
20
|
-
baseClasses: 'focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
|
|
20
|
+
baseClasses: 'flex items-center justify-center gap-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
|
|
21
21
|
variants: {
|
|
22
22
|
variant: {
|
|
23
|
-
default: 'bg-primary text-white
|
|
24
|
-
secondary: 'bg-background text-gray-900 ring-gray-300
|
|
25
|
-
danger: 'bg-danger text-white
|
|
26
|
-
ghost: 'bg-
|
|
27
|
-
outline: 'bg-
|
|
28
|
-
link: 'text-primary
|
|
23
|
+
default: 'bg-primary text-white focus-visible:outline-primary',
|
|
24
|
+
secondary: 'bg-background text-gray-900 ring-gray-300',
|
|
25
|
+
danger: 'bg-danger text-white focus-visible:outline-danger',
|
|
26
|
+
ghost: 'bg-transparent',
|
|
27
|
+
outline: 'bg-transparent text-primary ring-primary',
|
|
28
|
+
link: 'text-primary',
|
|
29
29
|
},
|
|
30
30
|
size: {
|
|
31
|
-
small: '
|
|
32
|
-
default: '
|
|
33
|
-
large: '
|
|
31
|
+
small: 'text-xs',
|
|
32
|
+
default: 'text-sm',
|
|
33
|
+
large: 'text-base',
|
|
34
34
|
icon: 'rounded-full p-2.5',
|
|
35
35
|
},
|
|
36
|
+
disabled: {
|
|
37
|
+
false: null,
|
|
38
|
+
true: 'opacity-50 cursor-not-allowed',
|
|
39
|
+
},
|
|
36
40
|
},
|
|
37
41
|
compoundVariants: [
|
|
38
42
|
{
|
|
@@ -47,10 +51,46 @@ const renderedClasses = computedVariantClasses<Variants<Pick<ButtonProps, 'size'
|
|
|
47
51
|
variant: ['secondary', 'outline'],
|
|
48
52
|
class: 'ring-1 ring-inset',
|
|
49
53
|
},
|
|
54
|
+
{
|
|
55
|
+
variant: ['default', 'secondary', 'danger', 'ghost', 'outline'],
|
|
56
|
+
size: 'small',
|
|
57
|
+
class: 'rounded px-2 py-1',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
variant: ['default', 'secondary', 'danger', 'ghost', 'outline'],
|
|
61
|
+
size: 'default',
|
|
62
|
+
class: 'rounded-md px-2.5 py-1.5',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
variant: ['default', 'secondary', 'danger', 'ghost', 'outline'],
|
|
66
|
+
size: 'large',
|
|
67
|
+
class: 'rounded-md px-3 py-2',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
variant: 'default',
|
|
71
|
+
disabled: false,
|
|
72
|
+
class: 'hover:bg-primary/90',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
variant: ['secondary', 'ghost', 'outline'],
|
|
76
|
+
disabled: false,
|
|
77
|
+
class: 'hover:bg-accent',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
variant: 'danger',
|
|
81
|
+
disabled: false,
|
|
82
|
+
class: 'hover:bg-danger/80',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
variant: 'link',
|
|
86
|
+
disabled: false,
|
|
87
|
+
class: 'hover:underline',
|
|
88
|
+
},
|
|
50
89
|
],
|
|
51
90
|
defaultVariants: {
|
|
52
91
|
variant: 'default',
|
|
53
92
|
size: 'default',
|
|
93
|
+
disabled: false,
|
|
54
94
|
},
|
|
55
95
|
},
|
|
56
96
|
);
|
|
@@ -8,33 +8,39 @@
|
|
|
8
8
|
<div class="flex h-6 items-center">
|
|
9
9
|
<HeadlessInputInput v-bind="inputAttrs" type="checkbox" :class="renderedInputClasses" />
|
|
10
10
|
</div>
|
|
11
|
-
<div v-if="$slots.default" class="
|
|
11
|
+
<div v-if="$slots.default" :class="renderedLabelClasses">
|
|
12
12
|
<HeadlessInputLabel class="text-gray-900">
|
|
13
13
|
<slot />
|
|
14
14
|
</HeadlessInputLabel>
|
|
15
|
-
<HeadlessInputError class="text-
|
|
15
|
+
<HeadlessInputError class="text-red-600" />
|
|
16
16
|
</div>
|
|
17
|
-
<div v-else-if="label" class="
|
|
18
|
-
<HeadlessInputLabel />
|
|
19
|
-
<HeadlessInputError class="text-
|
|
17
|
+
<div v-else-if="label" :class="renderedLabelClasses">
|
|
18
|
+
<HeadlessInputLabel class="text-gray-900" />
|
|
19
|
+
<HeadlessInputError class="text-red-600" />
|
|
20
20
|
</div>
|
|
21
21
|
</HeadlessInput>
|
|
22
22
|
</template>
|
|
23
23
|
|
|
24
24
|
<script setup lang="ts">
|
|
25
|
-
import { computed } from 'vue';
|
|
25
|
+
import { computed, useTemplateRef } from 'vue';
|
|
26
26
|
import type { HTMLAttributes } from 'vue';
|
|
27
27
|
|
|
28
|
-
import
|
|
28
|
+
import HeadlessInput from '@aerogel/core/components/headless/HeadlessInput.vue';
|
|
29
|
+
import HeadlessInputError from '@aerogel/core/components/headless/HeadlessInputError.vue';
|
|
30
|
+
import HeadlessInputInput from '@aerogel/core/components/headless/HeadlessInputInput.vue';
|
|
31
|
+
import HeadlessInputLabel from '@aerogel/core/components/headless/HeadlessInputLabel.vue';
|
|
32
|
+
import { classes } from '@aerogel/core/utils/classes';
|
|
29
33
|
import { useInputAttrs } from '@aerogel/core/utils/composition/forms';
|
|
30
|
-
import {
|
|
31
|
-
import type { InputEmits, InputExpose, InputProps } from '@aerogel/core/components/contracts/Input';
|
|
34
|
+
import type { InputEmits, InputProps } from '@aerogel/core/components/contracts/Input';
|
|
32
35
|
|
|
33
36
|
defineOptions({ inheritAttrs: false });
|
|
34
37
|
defineEmits<InputEmits>();
|
|
35
|
-
const { inputClass, ...props } = defineProps<InputProps & { inputClass?: HTMLAttributes['class'] }>();
|
|
36
38
|
|
|
37
|
-
const
|
|
39
|
+
const { inputClass, labelClass, ...props } = defineProps<
|
|
40
|
+
InputProps & { inputClass?: HTMLAttributes['class']; labelClass?: HTMLAttributes['class'] }
|
|
41
|
+
>();
|
|
42
|
+
|
|
43
|
+
const $input = useTemplateRef('$input');
|
|
38
44
|
const [inputAttrs, rootClasses] = useInputAttrs();
|
|
39
45
|
const renderedClasses = computed(() => classes('relative flex items-start', rootClasses.value));
|
|
40
46
|
const renderedInputClasses = computed(() =>
|
|
@@ -46,4 +52,5 @@ const renderedInputClasses = computed(() =>
|
|
|
46
52
|
},
|
|
47
53
|
inputClass,
|
|
48
54
|
));
|
|
55
|
+
const renderedLabelClasses = computed(() => classes('ml-2 text-sm leading-6', labelClass));
|
|
49
56
|
</script>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Modal v-slot="{ close }" :title
|
|
3
|
-
<Form :form
|
|
4
|
-
<
|
|
2
|
+
<Modal v-slot="{ close }" :title persistent>
|
|
3
|
+
<Form :form @submit="close([true, form.data()])">
|
|
4
|
+
<Markdown :text="message" :actions />
|
|
5
5
|
|
|
6
6
|
<ul v-if="checkboxes" class="mt-4 flex flex-col text-sm text-gray-600">
|
|
7
7
|
<li v-for="(checkbox, name) of checkboxes" :key="name">
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
<script setup lang="ts">
|
|
33
33
|
import Form from '@aerogel/core/components/ui/Form.vue';
|
|
34
|
-
import
|
|
34
|
+
import Markdown from '@aerogel/core/components/ui/Markdown.vue';
|
|
35
35
|
import Button from '@aerogel/core/components/ui/Button.vue';
|
|
36
36
|
import Modal from '@aerogel/core/components/ui/Modal.vue';
|
|
37
37
|
import { useConfirmModal } from '@aerogel/core/components/contracts/ConfirmModal';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DropdownMenuRoot>
|
|
3
|
+
<DropdownMenuTrigger>
|
|
4
|
+
<slot />
|
|
5
|
+
</DropdownMenuTrigger>
|
|
6
|
+
<DropdownMenuPortal>
|
|
7
|
+
<DropdownMenuContent class="gap-y-0.5 rounded-lg bg-white p-1.5 shadow-lg ring-1 ring-black/5" :align>
|
|
8
|
+
<DropdownMenuItem
|
|
9
|
+
v-for="(option, key) in options"
|
|
10
|
+
:key
|
|
11
|
+
class="flex w-full items-center rounded-lg px-2 py-2 text-sm text-gray-900 data-[highlighted]:bg-gray-100"
|
|
12
|
+
@select="option.click"
|
|
13
|
+
>
|
|
14
|
+
{{ option.label }}
|
|
15
|
+
</DropdownMenuItem>
|
|
16
|
+
</DropdownMenuContent>
|
|
17
|
+
</DropdownMenuPortal>
|
|
18
|
+
</DropdownMenuRoot>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script setup lang="ts">
|
|
22
|
+
import {
|
|
23
|
+
DropdownMenuContent,
|
|
24
|
+
DropdownMenuItem,
|
|
25
|
+
DropdownMenuPortal,
|
|
26
|
+
DropdownMenuRoot,
|
|
27
|
+
DropdownMenuTrigger,
|
|
28
|
+
} from 'reka-ui';
|
|
29
|
+
|
|
30
|
+
import type { DropdownMenuProps } from '@aerogel/core/components/contracts/DropdownMenu';
|
|
31
|
+
|
|
32
|
+
defineProps<DropdownMenuProps>();
|
|
33
|
+
</script>
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="relative" :class="{ 'pointer-events-none!': disabled && !editing }">
|
|
3
|
+
<div v-if="!editing" :class="renderedContentClass">
|
|
4
|
+
<slot />
|
|
5
|
+
</div>
|
|
6
|
+
<span v-else :class="renderedFillerClass">
|
|
7
|
+
{{ draft }}
|
|
8
|
+
</span>
|
|
9
|
+
<span v-if="type === 'number'" class="inline-block transition-[width]" :class="editing ? 'w-5' : 'w-0'" />
|
|
10
|
+
<form class="w-full" :aria-hidden="formAriaHidden" @submit.prevent="$input?.blur()">
|
|
11
|
+
<input
|
|
12
|
+
ref="$input"
|
|
13
|
+
v-model="draft"
|
|
14
|
+
:tabindex="tabindex ?? undefined"
|
|
15
|
+
:aria-label="ariaLabel ?? undefined"
|
|
16
|
+
:type
|
|
17
|
+
:class="[
|
|
18
|
+
renderedInputClass,
|
|
19
|
+
{ 'opacity-0': !editing, 'appearance-textfield': !editing && type === 'number' },
|
|
20
|
+
]"
|
|
21
|
+
@keyup="$emit('update', draft)"
|
|
22
|
+
@focus="startEditing()"
|
|
23
|
+
@blur="stopEditing()"
|
|
24
|
+
>
|
|
25
|
+
</form>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<script setup lang="ts">
|
|
30
|
+
import { computed, ref, watchEffect } from 'vue';
|
|
31
|
+
import type { HTMLAttributes } from 'vue';
|
|
32
|
+
|
|
33
|
+
import { classes } from '@aerogel/core/utils/classes';
|
|
34
|
+
|
|
35
|
+
const emit = defineEmits<{ update: [value: string | number]; save: [] }>();
|
|
36
|
+
const {
|
|
37
|
+
type = 'text',
|
|
38
|
+
text,
|
|
39
|
+
contentClass,
|
|
40
|
+
ariaLabel,
|
|
41
|
+
formAriaHidden,
|
|
42
|
+
tabindex,
|
|
43
|
+
disabled,
|
|
44
|
+
} = defineProps<{
|
|
45
|
+
type?: string;
|
|
46
|
+
contentClass?: HTMLAttributes['class'];
|
|
47
|
+
ariaLabel?: string;
|
|
48
|
+
formAriaHidden?: boolean;
|
|
49
|
+
tabindex?: string;
|
|
50
|
+
text: string;
|
|
51
|
+
disabled?: boolean;
|
|
52
|
+
}>();
|
|
53
|
+
const $input = ref<HTMLElement>();
|
|
54
|
+
const editing = ref<string | null>(null);
|
|
55
|
+
const draft = ref(text);
|
|
56
|
+
const renderedContentClass = computed(() => classes('inline whitespace-pre', contentClass));
|
|
57
|
+
const renderedFillerClass = computed(() => classes('invisible whitespace-pre', contentClass));
|
|
58
|
+
const renderedInputClass = computed(() =>
|
|
59
|
+
classes('absolute inset-0 h-full w-full resize-none border-0 bg-transparent p-0 focus:ring-0', contentClass));
|
|
60
|
+
|
|
61
|
+
function startEditing() {
|
|
62
|
+
editing.value = text;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function stopEditing() {
|
|
66
|
+
if (!editing.value) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (type !== 'number' && draft.value.trim().length === 0) {
|
|
71
|
+
draft.value = editing.value;
|
|
72
|
+
|
|
73
|
+
emit('update', draft.value);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
editing.value = null;
|
|
77
|
+
|
|
78
|
+
emit('save');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
watchEffect(() => (draft.value = text));
|
|
82
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Markdown :text="message" inline />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import { computed } from 'vue';
|
|
7
|
+
|
|
8
|
+
import { getErrorMessage } from '@aerogel/core/errors/utils';
|
|
9
|
+
import type { ErrorSource } from '@aerogel/core/errors/Errors.state';
|
|
10
|
+
|
|
11
|
+
import Markdown from '@aerogel/core/components/ui/Markdown.vue';
|
|
12
|
+
|
|
13
|
+
const { error } = defineProps<{ error: ErrorSource }>();
|
|
14
|
+
const message = computed(() => getErrorMessage(error));
|
|
15
|
+
</script>
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
</Button>
|
|
34
34
|
</span>
|
|
35
35
|
</div>
|
|
36
|
-
<ErrorReportModalButtons :report
|
|
36
|
+
<ErrorReportModalButtons :report class="gap-0.5" />
|
|
37
37
|
</h2>
|
|
38
|
-
<
|
|
38
|
+
<Markdown v-if="report.description" :text="report.description" class="text-gray-600" />
|
|
39
39
|
</div>
|
|
40
40
|
<div class="-mt-2 max-h-[80vh] overflow-auto bg-red-800/10">
|
|
41
41
|
<pre class="p-4 text-xs text-red-800" v-text="details" />
|
|
@@ -48,7 +48,7 @@ import IconCheveronLeft from '~icons/zondicons/cheveron-left';
|
|
|
48
48
|
import IconCheveronRight from '~icons/zondicons/cheveron-right';
|
|
49
49
|
import IconExclamationSolid from '~icons/zondicons/exclamation-solid';
|
|
50
50
|
|
|
51
|
-
import
|
|
51
|
+
import Markdown from '@aerogel/core/components/ui/Markdown.vue';
|
|
52
52
|
import Button from '@aerogel/core/components/ui/Button.vue';
|
|
53
53
|
import ErrorReportModalButtons from '@aerogel/core/components/ui/ErrorReportModalButtons.vue';
|
|
54
54
|
import ErrorReportModalTitle from '@aerogel/core/components/ui/ErrorReportModalTitle.vue';
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
class="group whitespace-nowrap"
|
|
8
8
|
:href="button.url"
|
|
9
9
|
:title="$td(`errors.report_${button.id}`, button.description)"
|
|
10
|
-
@click="button.
|
|
10
|
+
@click="button.click"
|
|
11
11
|
>
|
|
12
12
|
<span class="sr-only">{{ $td(`errors.report_${button.id}`, button.description) }}</span>
|
|
13
13
|
<component :is="button.iconComponent" class="size-4" aria-hidden="true" />
|
|
@@ -36,7 +36,7 @@ interface ErrorReportModalButtonsDefaultSlotProps {
|
|
|
36
36
|
description: string;
|
|
37
37
|
iconComponent: Component;
|
|
38
38
|
url?: string;
|
|
39
|
-
|
|
39
|
+
click?(): void;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
defineSlots<{
|
|
@@ -75,19 +75,17 @@ const buttons = computed(() =>
|
|
|
75
75
|
id: 'clipboard',
|
|
76
76
|
description: 'Copy to clipboard',
|
|
77
77
|
iconComponent: IconCopy,
|
|
78
|
-
async
|
|
78
|
+
async click() {
|
|
79
79
|
await navigator.clipboard.writeText(`${summary.value}\n\n${props.report.details}`);
|
|
80
80
|
|
|
81
|
-
UI.
|
|
82
|
-
translateWithDefault('errors.copiedToClipboard', 'Debug information copied to clipboard'),
|
|
83
|
-
);
|
|
81
|
+
UI.toast(translateWithDefault('errors.copiedToClipboard', 'Debug information copied to clipboard'));
|
|
84
82
|
},
|
|
85
83
|
},
|
|
86
84
|
{
|
|
87
85
|
id: 'console',
|
|
88
86
|
description: 'Log to console',
|
|
89
87
|
iconComponent: IconConsole,
|
|
90
|
-
|
|
88
|
+
click() {
|
|
91
89
|
const error = props.report.error ?? props.report;
|
|
92
90
|
|
|
93
91
|
(window as { error?: unknown }).error = error;
|
|
@@ -95,7 +93,7 @@ const buttons = computed(() =>
|
|
|
95
93
|
// eslint-disable-next-line no-console
|
|
96
94
|
console.error(error);
|
|
97
95
|
|
|
98
|
-
UI.
|
|
96
|
+
UI.toast(
|
|
99
97
|
translateWithDefault(
|
|
100
98
|
'errors.addedToConsole',
|
|
101
99
|
'You can now use the **error** variable in the console',
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<Markdown :text inline />
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup lang="ts">
|
|
6
6
|
import { computed } from 'vue';
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import Markdown from '@aerogel/core/components/ui/Markdown.vue';
|
|
9
9
|
import type { ErrorReport } from '@aerogel/core/errors';
|
|
10
10
|
|
|
11
11
|
const { totalReports, currentReport, report } = defineProps<{
|
|
@@ -21,20 +21,24 @@
|
|
|
21
21
|
<script setup lang="ts">
|
|
22
22
|
import IconExclamationSolid from '~icons/zondicons/exclamation-solid';
|
|
23
23
|
|
|
24
|
-
import { computed } from 'vue';
|
|
24
|
+
import { computed, useTemplateRef } from 'vue';
|
|
25
25
|
import type { HTMLAttributes } from 'vue';
|
|
26
26
|
|
|
27
|
-
import
|
|
27
|
+
import HeadlessInput from '@aerogel/core/components/headless/HeadlessInput.vue';
|
|
28
|
+
import HeadlessInputLabel from '@aerogel/core/components/headless/HeadlessInputLabel.vue';
|
|
29
|
+
import HeadlessInputInput from '@aerogel/core/components/headless/HeadlessInputInput.vue';
|
|
30
|
+
import HeadlessInputDescription from '@aerogel/core/components/headless/HeadlessInputDescription.vue';
|
|
31
|
+
import HeadlessInputError from '@aerogel/core/components/headless/HeadlessInputError.vue';
|
|
32
|
+
import { classes } from '@aerogel/core/utils/classes';
|
|
28
33
|
import { useInputAttrs } from '@aerogel/core/utils/composition/forms';
|
|
29
|
-
import {
|
|
30
|
-
import type { InputEmits, InputExpose, InputProps } from '@aerogel/core/components/contracts/Input';
|
|
34
|
+
import type { InputEmits, InputProps } from '@aerogel/core/components/contracts/Input';
|
|
31
35
|
|
|
32
36
|
defineOptions({ inheritAttrs: false });
|
|
33
37
|
defineEmits<InputEmits>();
|
|
34
38
|
const { label, inputClass, wrapperClass, ...props } = defineProps<
|
|
35
39
|
InputProps & { inputClass?: HTMLAttributes['class']; wrapperClass?: HTMLAttributes['class'] }
|
|
36
40
|
>();
|
|
37
|
-
const $input =
|
|
41
|
+
const $input = useTemplateRef('$input');
|
|
38
42
|
const [inputAttrs, rootClasses] = useInputAttrs();
|
|
39
43
|
const renderedWrapperClasses = computed(() =>
|
|
40
44
|
classes('relative rounded-md shadow-2xs', { 'mt-1': label }, wrapperClass));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Button variant="link" v-bind="props">
|
|
2
|
+
<Button variant="link" v-bind="$props">
|
|
3
3
|
<slot />
|
|
4
4
|
</Button>
|
|
5
5
|
</template>
|
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
import Button from '@aerogel/core/components/ui/Button.vue';
|
|
9
9
|
import type { ButtonProps } from '@aerogel/core/components/contracts/Button';
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
defineProps<Omit<ButtonProps, 'variant'>>();
|
|
12
12
|
</script>
|
|
@@ -3,24 +3,24 @@
|
|
|
3
3
|
persistent
|
|
4
4
|
class="flex"
|
|
5
5
|
wrapper-class="w-auto"
|
|
6
|
-
:title
|
|
6
|
+
:title
|
|
7
7
|
:class="{ 'flex-col-reverse': showProgress, 'items-center justify-center gap-2': !showProgress }"
|
|
8
8
|
>
|
|
9
9
|
<ProgressBar
|
|
10
10
|
v-if="showProgress"
|
|
11
|
-
:progress
|
|
12
|
-
:job
|
|
11
|
+
:progress
|
|
12
|
+
:job
|
|
13
13
|
class="min-w-[min(400px,80vw)]"
|
|
14
14
|
/>
|
|
15
15
|
<IconSpinner v-else class="text-primary mr-1 size-6" />
|
|
16
|
-
<
|
|
16
|
+
<Markdown :text="renderedMessage" />
|
|
17
17
|
</Modal>
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
20
|
<script setup lang="ts">
|
|
21
21
|
import IconSpinner from '~icons/svg-spinners/90-ring-with-bg';
|
|
22
22
|
|
|
23
|
-
import
|
|
23
|
+
import Markdown from '@aerogel/core/components/ui/Markdown.vue';
|
|
24
24
|
import Modal from '@aerogel/core/components/ui/Modal.vue';
|
|
25
25
|
import ProgressBar from '@aerogel/core/components/ui/ProgressBar.vue';
|
|
26
26
|
import { useLoadingModal } from '@aerogel/core/components/contracts/LoadingModal';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<root />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import { computed, h, useAttrs } from 'vue';
|
|
7
|
+
import { isInstanceOf } from '@noeldemartin/utils';
|
|
8
|
+
import type { VNode } from 'vue';
|
|
9
|
+
|
|
10
|
+
import { renderMarkdown } from '@aerogel/core/utils/markdown';
|
|
11
|
+
import { translate, translateWithDefault } from '@aerogel/core/lang';
|
|
12
|
+
import { renderVNode } from '@aerogel/core/utils/vue';
|
|
13
|
+
|
|
14
|
+
const { as, inline, langKey, langParams, langDefault, text, actions } = defineProps<{
|
|
15
|
+
as?: string;
|
|
16
|
+
inline?: boolean;
|
|
17
|
+
langKey?: string;
|
|
18
|
+
langParams?: number | Record<string, unknown>;
|
|
19
|
+
langDefault?: string;
|
|
20
|
+
text?: string;
|
|
21
|
+
actions?: Record<string, () => unknown>;
|
|
22
|
+
}>();
|
|
23
|
+
|
|
24
|
+
const attrs = useAttrs();
|
|
25
|
+
const slots = defineSlots<{ default?(): VNode[] }>();
|
|
26
|
+
const markdown = computed(() => {
|
|
27
|
+
if (slots.default) {
|
|
28
|
+
return slots.default().map(renderVNode).join('');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
text ??
|
|
33
|
+
(langKey &&
|
|
34
|
+
(langDefault
|
|
35
|
+
? translateWithDefault(langKey, langDefault, langParams ?? {})
|
|
36
|
+
: translate(langKey, langParams ?? {})))
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
const html = computed(() => {
|
|
40
|
+
if (!markdown.value) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let renderedHtml = renderMarkdown(markdown.value);
|
|
45
|
+
|
|
46
|
+
if (inline) {
|
|
47
|
+
renderedHtml = renderedHtml.replace('<p>', '<span>').replace('</p>', '</span>');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return renderedHtml;
|
|
51
|
+
});
|
|
52
|
+
const root = () =>
|
|
53
|
+
h(as ?? (inline ? 'span' : 'div'), {
|
|
54
|
+
innerHTML: html.value,
|
|
55
|
+
onClick,
|
|
56
|
+
...attrs,
|
|
57
|
+
class: `${attrs.class ?? ''} ${inline ? '' : 'prose'}`,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
async function onClick(event: Event) {
|
|
61
|
+
const { target } = event;
|
|
62
|
+
|
|
63
|
+
if (isInstanceOf(target, HTMLElement) && target.dataset.markdownAction) {
|
|
64
|
+
actions?.[target.dataset.markdownAction]?.();
|
|
65
|
+
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
</script>
|