@aerogel/core 0.0.0-next.9a02fcd3bcf698211dd7a71d4c48257c96dd7832 → 0.0.0-next.9a1c5ba39a454b316eba36ec7bdf579fed3d95d2
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 +2130 -1361
- package/dist/aerogel-core.js +2763 -0
- package/dist/aerogel-core.js.map +1 -0
- package/package.json +23 -37
- package/src/bootstrap/bootstrap.test.ts +4 -8
- package/src/bootstrap/index.ts +25 -16
- package/src/bootstrap/options.ts +1 -1
- package/src/components/AGAppLayout.vue +1 -1
- package/src/components/AGAppModals.vue +1 -1
- package/src/components/AGAppOverlays.vue +1 -1
- package/src/components/AGAppSnackbars.vue +1 -1
- package/src/components/composition.ts +23 -0
- package/src/components/contracts/Modal.ts +16 -0
- package/src/components/contracts/index.ts +2 -0
- package/src/components/contracts/shared.ts +9 -0
- package/src/components/forms/AGButton.vue +2 -2
- package/src/components/forms/AGCheckbox.vue +4 -3
- package/src/components/forms/AGForm.vue +11 -12
- package/src/components/forms/AGInput.vue +8 -4
- package/src/components/forms/AGSelect.vue +11 -17
- package/src/components/headless/forms/AGHeadlessButton.ts +3 -0
- package/src/components/headless/forms/AGHeadlessButton.vue +16 -5
- package/src/components/headless/forms/AGHeadlessInput.ts +18 -5
- package/src/components/headless/forms/AGHeadlessInput.vue +19 -6
- package/src/components/headless/forms/AGHeadlessInputDescription.vue +28 -0
- package/src/components/headless/forms/AGHeadlessInputError.vue +2 -2
- package/src/components/headless/forms/AGHeadlessInputInput.vue +43 -6
- package/src/components/headless/forms/AGHeadlessInputLabel.vue +1 -1
- package/src/components/headless/forms/AGHeadlessInputTextArea.vue +43 -0
- package/src/components/headless/forms/AGHeadlessSelect.ts +3 -3
- package/src/components/headless/forms/AGHeadlessSelect.vue +15 -15
- package/src/components/headless/forms/AGHeadlessSelectError.vue +2 -2
- package/src/components/headless/forms/AGHeadlessSelectOption.vue +10 -18
- package/src/components/headless/forms/AGHeadlessSelectOptions.vue +19 -0
- package/src/components/headless/forms/AGHeadlessSelectTrigger.vue +25 -0
- package/src/components/headless/forms/composition.ts +10 -0
- package/src/components/headless/forms/index.ts +6 -3
- package/src/components/headless/modals/AGHeadlessModal.ts +17 -18
- package/src/components/headless/modals/AGHeadlessModal.vue +12 -10
- package/src/components/headless/modals/AGHeadlessModalContent.vue +25 -0
- package/src/components/headless/modals/index.ts +3 -2
- package/src/components/headless/snackbars/index.ts +3 -3
- package/src/components/index.ts +2 -0
- package/src/components/lib/AGErrorMessage.vue +3 -3
- package/src/components/lib/AGMarkdown.vue +24 -6
- package/src/components/lib/AGMeasured.vue +3 -2
- package/src/components/lib/AGProgressBar.vue +55 -0
- package/src/components/lib/AGStartupCrash.vue +1 -1
- package/src/components/lib/index.ts +1 -0
- package/src/components/modals/AGAlertModal.ts +6 -3
- package/src/components/modals/AGConfirmModal.ts +19 -4
- package/src/components/modals/AGConfirmModal.vue +6 -5
- package/src/components/modals/AGErrorReportModal.ts +8 -5
- package/src/components/modals/AGErrorReportModal.vue +2 -2
- package/src/components/modals/AGErrorReportModalButtons.vue +10 -10
- package/src/components/modals/AGErrorReportModalTitle.vue +2 -2
- package/src/components/modals/AGLoadingModal.ts +11 -5
- package/src/components/modals/AGModal.vue +20 -19
- package/src/components/modals/AGModalContext.ts +1 -1
- package/src/components/modals/AGModalContext.vue +15 -5
- package/src/components/modals/AGModalTitle.vue +1 -1
- package/src/components/modals/AGPromptModal.ts +15 -4
- package/src/components/modals/AGPromptModal.vue +5 -4
- package/src/components/modals/index.ts +0 -1
- package/src/components/snackbars/AGSnackbar.vue +2 -2
- package/src/components/utils.ts +62 -9
- package/src/directives/index.ts +11 -5
- package/src/directives/measure.ts +34 -6
- package/src/errors/Errors.state.ts +1 -1
- package/src/errors/Errors.ts +12 -12
- package/src/errors/JobCancelledError.ts +3 -0
- package/src/errors/index.ts +9 -6
- package/src/errors/utils.ts +17 -1
- package/src/forms/Form.test.ts +32 -3
- package/src/forms/Form.ts +80 -20
- package/src/forms/composition.ts +2 -2
- package/src/forms/index.ts +3 -1
- package/src/forms/utils.ts +34 -3
- package/src/forms/validation.ts +19 -0
- package/src/{main.ts → index.ts} +1 -0
- package/src/jobs/Job.ts +144 -2
- package/src/jobs/index.ts +4 -1
- package/src/jobs/listeners.ts +3 -0
- package/src/jobs/status.ts +4 -0
- package/src/lang/DefaultLangProvider.ts +46 -0
- package/src/lang/Lang.state.ts +11 -0
- package/src/lang/Lang.ts +48 -21
- package/src/lang/index.ts +8 -6
- package/src/plugins/Plugin.ts +1 -1
- package/src/plugins/index.ts +10 -7
- package/src/services/App.state.ts +26 -3
- package/src/services/App.ts +11 -3
- package/src/services/Cache.ts +43 -0
- package/src/services/Events.ts +15 -5
- package/src/services/Service.ts +125 -54
- package/src/services/Storage.ts +20 -0
- package/src/services/index.ts +13 -5
- package/src/services/utils.ts +18 -0
- package/src/testing/index.ts +4 -3
- package/src/testing/setup.ts +11 -0
- package/src/ui/UI.state.ts +9 -2
- package/src/ui/UI.ts +157 -52
- package/src/ui/index.ts +5 -4
- package/src/ui/utils.ts +16 -0
- package/src/utils/composition/events.ts +2 -2
- package/src/utils/composition/persistent.test.ts +33 -0
- package/src/utils/composition/persistent.ts +11 -0
- package/src/utils/composition/state.test.ts +47 -0
- package/src/utils/composition/state.ts +24 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/markdown.test.ts +50 -0
- package/src/utils/markdown.ts +19 -6
- package/src/utils/vue.ts +22 -15
- package/dist/aerogel-core.cjs.js +0 -2
- package/dist/aerogel-core.cjs.js.map +0 -1
- package/dist/aerogel-core.esm.js +0 -2
- package/dist/aerogel-core.esm.js.map +0 -1
- package/histoire.config.ts +0 -7
- package/noeldemartin.config.js +0 -5
- package/postcss.config.js +0 -6
- package/src/assets/histoire.css +0 -3
- package/src/components/headless/forms/AGHeadlessSelectButton.vue +0 -24
- package/src/components/headless/forms/AGHeadlessSelectLabel.vue +0 -24
- package/src/components/headless/forms/AGHeadlessSelectOptions.ts +0 -3
- package/src/components/headless/modals/AGHeadlessModalPanel.vue +0 -28
- package/src/components/headless/modals/AGHeadlessModalTitle.vue +0 -13
- package/src/components/modals/AGModal.ts +0 -10
- package/src/directives/initial-focus.ts +0 -11
- package/src/main.histoire.ts +0 -1
- package/tailwind.config.js +0 -4
- package/tsconfig.json +0 -11
- package/vite.config.ts +0 -14
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { ExtractPropTypes } from 'vue';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ObjectWithout, Pretty } from '@noeldemartin/utils';
|
|
3
3
|
|
|
4
|
-
import { requiredStringProp, stringProp } from '
|
|
4
|
+
import { requiredStringProp, stringProp } from '@aerogel/core/utils';
|
|
5
|
+
import type { AcceptRefs } from '@aerogel/core/utils';
|
|
5
6
|
|
|
6
7
|
export const alertModalProps = {
|
|
7
8
|
title: stringProp(),
|
|
8
9
|
message: requiredStringProp(),
|
|
9
10
|
};
|
|
10
11
|
|
|
11
|
-
export type AGAlertModalProps =
|
|
12
|
+
export type AGAlertModalProps = Pretty<
|
|
13
|
+
AcceptRefs<ObjectWithout<ExtractPropTypes<typeof alertModalProps>, null | undefined>>
|
|
14
|
+
>;
|
|
12
15
|
|
|
13
16
|
export function useAlertModalProps(): typeof alertModalProps {
|
|
14
17
|
return alertModalProps;
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
import { computed } from 'vue';
|
|
2
2
|
import type { ExtractPropTypes } from 'vue';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ObjectWithout, Pretty, SubPartial } from '@noeldemartin/utils';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { Colors } from '@aerogel/core/components/constants';
|
|
6
|
+
import { booleanProp, enumProp, objectProp, requiredStringProp, stringProp } from '@aerogel/core/utils';
|
|
7
|
+
import { translateWithDefault } from '@aerogel/core/lang';
|
|
8
|
+
import type { AcceptRefs } from '@aerogel/core/utils';
|
|
9
|
+
import type { ConfirmCheckboxes } from '@aerogel/core/ui';
|
|
7
10
|
|
|
8
11
|
export const confirmModalProps = {
|
|
9
12
|
title: stringProp(),
|
|
10
13
|
message: requiredStringProp(),
|
|
11
14
|
acceptText: stringProp(),
|
|
15
|
+
acceptColor: enumProp(Colors, Colors.Primary),
|
|
12
16
|
cancelText: stringProp(),
|
|
17
|
+
cancelColor: enumProp(Colors, Colors.Clear),
|
|
18
|
+
checkboxes: objectProp<ConfirmCheckboxes>(),
|
|
19
|
+
actions: objectProp<Record<string, () => unknown>>(),
|
|
20
|
+
required: booleanProp(false),
|
|
13
21
|
};
|
|
14
22
|
|
|
15
|
-
export type AGConfirmModalProps =
|
|
23
|
+
export type AGConfirmModalProps = Pretty<
|
|
24
|
+
AcceptRefs<
|
|
25
|
+
SubPartial<
|
|
26
|
+
ObjectWithout<ExtractPropTypes<typeof confirmModalProps>, null | undefined>,
|
|
27
|
+
'acceptColor' | 'cancelColor'
|
|
28
|
+
>
|
|
29
|
+
>
|
|
30
|
+
>;
|
|
16
31
|
|
|
17
32
|
export function useConfirmModalProps(): typeof confirmModalProps {
|
|
18
33
|
return confirmModalProps;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<AGModal v-slot="{ close }:
|
|
3
|
-
<AGMarkdown :text="message" />
|
|
2
|
+
<AGModal v-slot="{ close }: IModalDefaultSlotProps" :cancellable="false" :title="title">
|
|
3
|
+
<AGMarkdown :text="message" :actions="actions" />
|
|
4
4
|
|
|
5
5
|
<div class="mt-2 flex flex-row-reverse gap-2">
|
|
6
|
-
<AGButton @click="close(true)">
|
|
6
|
+
<AGButton :color="acceptColor" @click="close(true)">
|
|
7
7
|
{{ renderedAcceptText }}
|
|
8
8
|
</AGButton>
|
|
9
|
-
<AGButton color="
|
|
9
|
+
<AGButton v-if="!required" :color="cancelColor" @click="close()">
|
|
10
10
|
{{ renderedCancelText }}
|
|
11
11
|
</AGButton>
|
|
12
12
|
</div>
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
</template>
|
|
15
15
|
|
|
16
16
|
<script setup lang="ts">
|
|
17
|
+
import type { IModalDefaultSlotProps } from '@aerogel/core/components/contracts/Modal';
|
|
18
|
+
|
|
17
19
|
import AGModal from './AGModal.vue';
|
|
18
20
|
import { useConfirmModal, useConfirmModalProps } from './AGConfirmModal';
|
|
19
|
-
import type { IAGModalDefaultSlotProps } from './AGModal';
|
|
20
21
|
|
|
21
22
|
import AGButton from '../forms/AGButton.vue';
|
|
22
23
|
import AGMarkdown from '../lib/AGMarkdown.vue';
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { computed, ref } from 'vue';
|
|
2
2
|
import type { Component, ExtractPropTypes } from 'vue';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ObjectWithout, Pretty } from '@noeldemartin/utils';
|
|
4
4
|
|
|
5
|
-
import { requiredArrayProp } from '
|
|
6
|
-
import { translateWithDefault } from '
|
|
7
|
-
import type {
|
|
5
|
+
import { requiredArrayProp } from '@aerogel/core/utils/vue';
|
|
6
|
+
import { translateWithDefault } from '@aerogel/core/lang';
|
|
7
|
+
import type { AcceptRefs } from '@aerogel/core/utils/vue';
|
|
8
|
+
import type { ErrorReport } from '@aerogel/core/errors';
|
|
8
9
|
|
|
9
10
|
export interface IAGErrorReportModalButtonsDefaultSlotProps {
|
|
10
11
|
id: string;
|
|
@@ -18,7 +19,9 @@ export const errorReportModalProps = {
|
|
|
18
19
|
reports: requiredArrayProp<ErrorReport>(),
|
|
19
20
|
};
|
|
20
21
|
|
|
21
|
-
export type AGErrorReportModalProps =
|
|
22
|
+
export type AGErrorReportModalProps = Pretty<
|
|
23
|
+
AcceptRefs<ObjectWithout<ExtractPropTypes<typeof errorReportModalProps>, null | undefined>>
|
|
24
|
+
>;
|
|
22
25
|
|
|
23
26
|
export function useErrorReportModalProps(): typeof errorReportModalProps {
|
|
24
27
|
return errorReportModalProps;
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
:aria-label="previousReportText"
|
|
17
17
|
@click="activeReportIndex--"
|
|
18
18
|
>
|
|
19
|
-
<IconCheveronLeft aria-hidden="true" class="
|
|
19
|
+
<IconCheveronLeft aria-hidden="true" class="size-4" />
|
|
20
20
|
</AGButton>
|
|
21
21
|
<AGButton
|
|
22
22
|
color="clear"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
:aria-label="nextReportText"
|
|
26
26
|
@click="activeReportIndex++"
|
|
27
27
|
>
|
|
28
|
-
<IconCheveronRight aria-hidden="true" class="
|
|
28
|
+
<IconCheveronRight aria-hidden="true" class="size-4" />
|
|
29
29
|
</AGButton>
|
|
30
30
|
</template>
|
|
31
31
|
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="flex">
|
|
3
|
-
<slot v-for="(button, i) of buttons" v-bind="
|
|
3
|
+
<slot v-for="(button, i) of buttons" v-bind="button as unknown as ComponentProps" :key="i">
|
|
4
4
|
<AGButton
|
|
5
5
|
color="clear"
|
|
6
6
|
:url="button.url"
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
:aria-label="$td(`errors.report_${button.id}`, button.description)"
|
|
9
9
|
@click="button.handler"
|
|
10
10
|
>
|
|
11
|
-
<component :is="button.iconComponent" class="
|
|
11
|
+
<component :is="button.iconComponent" class="size-4" aria-hidden="true" />
|
|
12
12
|
</AGButton>
|
|
13
13
|
</slot>
|
|
14
14
|
</div>
|
|
@@ -22,12 +22,12 @@ import IconGitHub from '~icons/mdi/github';
|
|
|
22
22
|
import { computed } from 'vue';
|
|
23
23
|
import { stringExcerpt, tap } from '@noeldemartin/utils';
|
|
24
24
|
|
|
25
|
-
import App from '
|
|
26
|
-
import UI from '
|
|
27
|
-
import { requiredObjectProp } from '
|
|
28
|
-
import { translateWithDefault } from '
|
|
29
|
-
import type { ComponentProps } from '
|
|
30
|
-
import type { ErrorReport } from '
|
|
25
|
+
import App from '@aerogel/core/services/App';
|
|
26
|
+
import UI from '@aerogel/core/ui/UI';
|
|
27
|
+
import { requiredObjectProp } from '@aerogel/core/utils/vue';
|
|
28
|
+
import { translateWithDefault } from '@aerogel/core/lang/utils';
|
|
29
|
+
import type { ComponentProps } from '@aerogel/core/utils/vue';
|
|
30
|
+
import type { ErrorReport } from '@aerogel/core/errors';
|
|
31
31
|
|
|
32
32
|
import AGButton from '../forms/AGButton.vue';
|
|
33
33
|
import type { IAGErrorReportModalButtonsDefaultSlotProps } from './AGErrorReportModal';
|
|
@@ -94,8 +94,8 @@ const buttons = computed(() =>
|
|
|
94
94
|
);
|
|
95
95
|
},
|
|
96
96
|
},
|
|
97
|
-
],
|
|
98
|
-
(reportButtons
|
|
97
|
+
] as IAGErrorReportModalButtonsDefaultSlotProps[],
|
|
98
|
+
(reportButtons) => {
|
|
99
99
|
if (!githubReportUrl.value) {
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<script setup lang="ts">
|
|
6
6
|
import { computed } from 'vue';
|
|
7
7
|
|
|
8
|
-
import { numberProp, requiredObjectProp } from '
|
|
9
|
-
import type { ErrorReport } from '
|
|
8
|
+
import { numberProp, requiredObjectProp } from '@aerogel/core/utils/vue';
|
|
9
|
+
import type { ErrorReport } from '@aerogel/core/errors';
|
|
10
10
|
|
|
11
11
|
import AGMarkdown from '../lib/AGMarkdown.vue';
|
|
12
12
|
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { computed } from 'vue';
|
|
2
2
|
import type { ExtractPropTypes } from 'vue';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ObjectWithout } from '@noeldemartin/utils';
|
|
4
4
|
|
|
5
|
-
import { stringProp } from '
|
|
6
|
-
import { translateWithDefault } from '
|
|
5
|
+
import { numberProp, stringProp } from '@aerogel/core/utils';
|
|
6
|
+
import { translateWithDefault } from '@aerogel/core/lang';
|
|
7
|
+
import type { AcceptRefs } from '@aerogel/core/utils';
|
|
7
8
|
|
|
8
9
|
export const loadingModalProps = {
|
|
10
|
+
title: stringProp(),
|
|
9
11
|
message: stringProp(),
|
|
12
|
+
progress: numberProp(),
|
|
10
13
|
};
|
|
11
14
|
|
|
12
|
-
export type AGLoadingModalProps =
|
|
15
|
+
export type AGLoadingModalProps = AcceptRefs<
|
|
16
|
+
ObjectWithout<ExtractPropTypes<typeof loadingModalProps>, null | undefined>
|
|
17
|
+
>;
|
|
13
18
|
|
|
14
19
|
export function useLoadingModalProps(): typeof loadingModalProps {
|
|
15
20
|
return loadingModalProps;
|
|
@@ -18,6 +23,7 @@ export function useLoadingModalProps(): typeof loadingModalProps {
|
|
|
18
23
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
19
24
|
export function useLoadingModal(props: ExtractPropTypes<typeof loadingModalProps>) {
|
|
20
25
|
const renderedMessage = computed(() => props.message ?? translateWithDefault('ui.loading', 'Loading...'));
|
|
26
|
+
const showProgress = computed(() => typeof props.progress === 'number');
|
|
21
27
|
|
|
22
|
-
return { renderedMessage };
|
|
28
|
+
return { renderedMessage, showProgress };
|
|
23
29
|
}
|
|
@@ -3,37 +3,38 @@
|
|
|
3
3
|
ref="$modal"
|
|
4
4
|
v-slot="{ close }: IAGHeadlessModalDefaultSlotProps"
|
|
5
5
|
v-bind="props"
|
|
6
|
-
class="relative
|
|
6
|
+
class="relative"
|
|
7
7
|
>
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
</
|
|
17
|
-
</
|
|
8
|
+
<AGHeadlessModalContent
|
|
9
|
+
class="fixed top-1/2 left-1/2 z-50 max-w-lg -translate-x-1/2 -translate-y-1/2 bg-white p-4"
|
|
10
|
+
>
|
|
11
|
+
<AGHeadlessModalTitle v-if="title" class="mb-2 text-lg font-semibold">
|
|
12
|
+
<AGMarkdown :text="title" inline />
|
|
13
|
+
</AGHeadlessModalTitle>
|
|
14
|
+
<div class="flex max-h-full flex-col overflow-auto" v-bind="$attrs">
|
|
15
|
+
<slot :close="close" />
|
|
16
|
+
</div>
|
|
17
|
+
</AGHeadlessModalContent>
|
|
18
18
|
</AGHeadlessModal>
|
|
19
19
|
</template>
|
|
20
20
|
|
|
21
21
|
<script setup lang="ts">
|
|
22
22
|
import { ref } from 'vue';
|
|
23
23
|
|
|
24
|
-
import {
|
|
25
|
-
import
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
import { AGHeadlessModalTitle } from '@aerogel/core/components/headless/modals';
|
|
25
|
+
import { modalExpose, modalProps } from '@aerogel/core/components/headless/modals/AGHeadlessModal';
|
|
26
|
+
import type {
|
|
27
|
+
IAGHeadlessModal,
|
|
28
|
+
IAGHeadlessModalDefaultSlotProps,
|
|
29
|
+
} from '@aerogel/core/components/headless/modals/AGHeadlessModal';
|
|
28
30
|
|
|
29
31
|
import AGHeadlessModal from '../headless/modals/AGHeadlessModal.vue';
|
|
30
|
-
import
|
|
31
|
-
import AGHeadlessModalTitle from '../headless/modals/AGHeadlessModalTitle.vue';
|
|
32
|
+
import AGHeadlessModalContent from '../headless/modals/AGHeadlessModalContent.vue';
|
|
32
33
|
import AGMarkdown from '../lib/AGMarkdown.vue';
|
|
33
34
|
|
|
34
|
-
const props = defineProps(
|
|
35
|
+
const props = defineProps(modalProps());
|
|
35
36
|
const $modal = ref<IAGHeadlessModal>();
|
|
36
37
|
|
|
37
38
|
defineOptions({ inheritAttrs: false });
|
|
38
|
-
defineExpose
|
|
39
|
+
defineExpose(modalExpose($modal));
|
|
39
40
|
</script>
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<component :is="modal.component" v-bind="
|
|
2
|
+
<component :is="modal.component" v-bind="modalProperties" />
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup lang="ts">
|
|
6
|
-
import { provide, toRef } from 'vue';
|
|
6
|
+
import { computed, provide, toRef, unref } from 'vue';
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import type { Modal } from '
|
|
8
|
+
import { numberProp, requiredObjectProp } from '@aerogel/core/utils/vue';
|
|
9
|
+
import type { Modal } from '@aerogel/core/ui/UI.state';
|
|
10
10
|
|
|
11
11
|
import type { IAGModalContext } from './AGModalContext';
|
|
12
12
|
|
|
13
13
|
const props = defineProps({
|
|
14
14
|
modal: requiredObjectProp<Modal>(),
|
|
15
|
-
childIndex:
|
|
15
|
+
childIndex: numberProp(0),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const modalProperties = computed(() => {
|
|
19
|
+
const properties = {} as typeof props.modal.properties;
|
|
20
|
+
|
|
21
|
+
for (const property in props.modal.properties) {
|
|
22
|
+
properties[property] = unref(props.modal.properties[property]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return properties;
|
|
16
26
|
});
|
|
17
27
|
|
|
18
28
|
provide<IAGModalContext>('modal', {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { computed } from 'vue';
|
|
2
2
|
import type { ExtractPropTypes } from 'vue';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ObjectWithout, Pretty, SubPartial } from '@noeldemartin/utils';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { Colors } from '@aerogel/core/components/constants';
|
|
6
|
+
import { enumProp, requiredStringProp, stringProp } from '@aerogel/core/utils';
|
|
7
|
+
import { translateWithDefault } from '@aerogel/core/lang';
|
|
8
|
+
import type { AcceptRefs } from '@aerogel/core/utils';
|
|
7
9
|
|
|
8
10
|
export const promptModalProps = {
|
|
9
11
|
title: stringProp(),
|
|
@@ -12,10 +14,19 @@ export const promptModalProps = {
|
|
|
12
14
|
defaultValue: stringProp(),
|
|
13
15
|
placeholder: stringProp(),
|
|
14
16
|
acceptText: stringProp(),
|
|
17
|
+
acceptColor: enumProp(Colors, Colors.Primary),
|
|
15
18
|
cancelText: stringProp(),
|
|
19
|
+
cancelColor: enumProp(Colors, Colors.Clear),
|
|
16
20
|
};
|
|
17
21
|
|
|
18
|
-
export type AGPromptModalProps =
|
|
22
|
+
export type AGPromptModalProps = Pretty<
|
|
23
|
+
AcceptRefs<
|
|
24
|
+
SubPartial<
|
|
25
|
+
ObjectWithout<ExtractPropTypes<typeof promptModalProps>, null | undefined>,
|
|
26
|
+
'acceptColor' | 'cancelColor'
|
|
27
|
+
>
|
|
28
|
+
>
|
|
29
|
+
>;
|
|
19
30
|
|
|
20
31
|
export function usePromptModalProps(): typeof promptModalProps {
|
|
21
32
|
return promptModalProps;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<AGModal v-slot="{ close }:
|
|
2
|
+
<AGModal v-slot="{ close }: IModalDefaultSlotProps" :cancellable="false" :title="title">
|
|
3
3
|
<AGMarkdown :text="message" />
|
|
4
4
|
|
|
5
5
|
<AGForm :form="form" @submit="close(form.draft)">
|
|
6
6
|
<AGInput name="draft" :placeholder="placeholder" :label="label" />
|
|
7
7
|
|
|
8
8
|
<div class="mt-2 flex flex-row-reverse gap-2">
|
|
9
|
-
<AGButton submit>
|
|
9
|
+
<AGButton :color="acceptColor" submit>
|
|
10
10
|
{{ renderedAcceptText }}
|
|
11
11
|
</AGButton>
|
|
12
|
-
<AGButton color="
|
|
12
|
+
<AGButton :color="cancelColor" @click="close()">
|
|
13
13
|
{{ renderedCancelText }}
|
|
14
14
|
</AGButton>
|
|
15
15
|
</div>
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
20
|
<script setup lang="ts">
|
|
21
|
+
import type { IModalDefaultSlotProps } from '@aerogel/core/components/contracts/Modal';
|
|
22
|
+
|
|
21
23
|
import AGModal from './AGModal.vue';
|
|
22
24
|
import { usePromptModal, usePromptModalProps } from './AGPromptModal';
|
|
23
|
-
import type { IAGModalDefaultSlotProps } from './AGModal';
|
|
24
25
|
|
|
25
26
|
import AGButton from '../forms/AGButton.vue';
|
|
26
27
|
import AGForm from '../forms/AGForm.vue';
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
<script setup lang="ts">
|
|
16
16
|
import { computed } from 'vue';
|
|
17
17
|
|
|
18
|
-
import { Colors } from '
|
|
19
|
-
import { useSnackbar, useSnackbarProps } from '
|
|
18
|
+
import { Colors } from '@aerogel/core/components/constants';
|
|
19
|
+
import { useSnackbar, useSnackbarProps } from '@aerogel/core/components/headless/snackbars';
|
|
20
20
|
|
|
21
21
|
import AGButton from '../forms/AGButton.vue';
|
|
22
22
|
import AGHeadlessSnackbar from '../headless/snackbars/AGHeadlessSnackbar.vue';
|
package/src/components/utils.ts
CHANGED
|
@@ -1,10 +1,63 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { isObject } from '@noeldemartin/utils';
|
|
2
|
+
import { customRef } from 'vue';
|
|
3
|
+
import type { ExtractPropTypes, PropType, Ref, UnwrapNestedRefs } from 'vue';
|
|
4
|
+
|
|
5
|
+
import type { HasElement } from '@aerogel/core/components/contracts/shared';
|
|
6
|
+
|
|
7
|
+
export type ComponentPropDefinitions<T> = {
|
|
8
|
+
[K in keyof T]: {
|
|
9
|
+
type?: PropType<T[K]>;
|
|
10
|
+
default: T[K] | (() => T[K]) | null;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type PickComponentProps<TValues, TDefinitions> = {
|
|
15
|
+
[K in keyof TValues]: K extends keyof TDefinitions ? TValues[K] : never;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function elementRef(): Ref<HTMLElement | undefined> {
|
|
19
|
+
return customRef((track, trigger) => {
|
|
20
|
+
let value: HTMLElement | undefined = undefined;
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
get() {
|
|
24
|
+
track();
|
|
25
|
+
|
|
26
|
+
return value;
|
|
27
|
+
},
|
|
28
|
+
set(newValue) {
|
|
29
|
+
value = getElement(newValue);
|
|
30
|
+
|
|
31
|
+
trigger();
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function extractComponentProps<TDefinitions extends {}, TValues extends ExtractPropTypes<TDefinitions>>(
|
|
38
|
+
values: TValues,
|
|
39
|
+
definitions: TDefinitions,
|
|
40
|
+
): PickComponentProps<TValues, TDefinitions> {
|
|
41
|
+
return Object.keys(definitions).reduce(
|
|
42
|
+
(extracted, prop) => {
|
|
43
|
+
extracted[prop] = values[prop as keyof TValues];
|
|
44
|
+
|
|
45
|
+
return extracted;
|
|
46
|
+
},
|
|
47
|
+
{} as Record<string, unknown>,
|
|
48
|
+
) as PickComponentProps<TValues, TDefinitions>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function getElement(value: unknown): HTMLElement | undefined {
|
|
52
|
+
if (value instanceof HTMLElement) {
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (hasElement(value)) {
|
|
57
|
+
return value.$el;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function hasElement(value: unknown): value is UnwrapNestedRefs<HasElement> {
|
|
62
|
+
return isObject(value) && '$el' in value;
|
|
10
63
|
}
|
package/src/directives/index.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { Directive } from 'vue';
|
|
2
2
|
|
|
3
|
-
import { definePlugin } from '
|
|
3
|
+
import { definePlugin } from '@aerogel/core/plugins';
|
|
4
4
|
|
|
5
|
-
import initialFocus from './initial-focus';
|
|
6
5
|
import measure from './measure';
|
|
7
6
|
|
|
8
7
|
const builtInDirectives: Record<string, Directive> = {
|
|
9
|
-
|
|
10
|
-
'measure': measure,
|
|
8
|
+
measure: measure,
|
|
11
9
|
};
|
|
12
10
|
|
|
11
|
+
export * from './measure';
|
|
12
|
+
|
|
13
13
|
export default definePlugin({
|
|
14
14
|
install(app, options) {
|
|
15
15
|
const directives = {
|
|
@@ -23,8 +23,14 @@ export default definePlugin({
|
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
declare module '
|
|
26
|
+
declare module '@aerogel/core/bootstrap/options' {
|
|
27
27
|
export interface AerogelOptions {
|
|
28
28
|
directives?: Record<string, Directive>;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
|
|
32
|
+
declare module 'vue' {
|
|
33
|
+
interface ComponentCustomDirectives {
|
|
34
|
+
measure: Directive<string, string>;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,12 +1,40 @@
|
|
|
1
|
-
import { defineDirective } from '
|
|
1
|
+
import { defineDirective } from '@aerogel/core/utils/vue';
|
|
2
|
+
import { tap } from '@noeldemartin/utils';
|
|
3
|
+
|
|
4
|
+
const resizeObservers: WeakMap<HTMLElement, ResizeObserver> = new WeakMap();
|
|
5
|
+
|
|
6
|
+
export interface ElementSize {
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type MeasureDirectiveListener = (size: ElementSize) => unknown;
|
|
2
12
|
|
|
3
13
|
export default defineDirective({
|
|
4
|
-
mounted(element: HTMLElement, { value }
|
|
5
|
-
|
|
14
|
+
mounted(element: HTMLElement, { value }) {
|
|
15
|
+
// TODO replace with argument when typed properly
|
|
16
|
+
const modifiers = { css: true, watch: true };
|
|
17
|
+
|
|
18
|
+
const listener = typeof value === 'function' ? (value as MeasureDirectiveListener) : null;
|
|
19
|
+
const update = () => {
|
|
20
|
+
const sizes = element.getBoundingClientRect();
|
|
6
21
|
|
|
7
|
-
|
|
8
|
-
|
|
22
|
+
if (modifiers.css) {
|
|
23
|
+
element.style.setProperty('--width', `${sizes.width}px`);
|
|
24
|
+
element.style.setProperty('--height', `${sizes.height}px`);
|
|
25
|
+
}
|
|
9
26
|
|
|
10
|
-
|
|
27
|
+
listener?.({ width: sizes.width, height: sizes.height });
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
if (modifiers.watch) {
|
|
31
|
+
resizeObservers.set(element, tap(new ResizeObserver(update)).observe(element));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
update();
|
|
35
|
+
},
|
|
36
|
+
unmounted(element) {
|
|
37
|
+
resizeObservers.get(element)?.unobserve(element);
|
|
38
|
+
resizeObservers.delete(element);
|
|
11
39
|
},
|
|
12
40
|
});
|
package/src/errors/Errors.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { JSError, facade, isObject, objectWithoutEmpty, toString } from '@noeldemartin/utils';
|
|
1
|
+
import { JSError, facade, isDevelopment, isObject, isTesting, objectWithoutEmpty, toString } from '@noeldemartin/utils';
|
|
2
2
|
|
|
3
|
-
import App from '
|
|
4
|
-
import ServiceBootError from '
|
|
5
|
-
import UI, { UIComponents } from '
|
|
6
|
-
import { translateWithDefault } from '
|
|
3
|
+
import App from '@aerogel/core/services/App';
|
|
4
|
+
import ServiceBootError from '@aerogel/core/errors/ServiceBootError';
|
|
5
|
+
import UI, { UIComponents } from '@aerogel/core/ui/UI';
|
|
6
|
+
import { translateWithDefault } from '@aerogel/core/lang/utils';
|
|
7
7
|
|
|
8
8
|
import Service from './Errors.state';
|
|
9
|
-
import { Colors } from '
|
|
10
|
-
import { Events } from '
|
|
11
|
-
import type { AGErrorReportModalProps } from '
|
|
9
|
+
import { Colors } from '@aerogel/core/components/constants';
|
|
10
|
+
import { Events } from '@aerogel/core/services';
|
|
11
|
+
import type { AGErrorReportModalProps } from '@aerogel/core/components/modals/AGErrorReportModal';
|
|
12
12
|
import type { ErrorReport, ErrorReportLog, ErrorSource } from './Errors.state';
|
|
13
|
-
import type { ModalComponent } from '
|
|
13
|
+
import type { ModalComponent } from '@aerogel/core/ui/UI.state';
|
|
14
14
|
|
|
15
15
|
export class ErrorsService extends Service {
|
|
16
16
|
|
|
@@ -42,11 +42,11 @@ export class ErrorsService extends Service {
|
|
|
42
42
|
public async report(error: ErrorSource, message?: string): Promise<void> {
|
|
43
43
|
await Events.emit('error', { error, message });
|
|
44
44
|
|
|
45
|
-
if (
|
|
45
|
+
if (isTesting('unit')) {
|
|
46
46
|
throw error;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
if (
|
|
49
|
+
if (isDevelopment()) {
|
|
50
50
|
this.logError(error);
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -178,7 +178,7 @@ export class ErrorsService extends Service {
|
|
|
178
178
|
|
|
179
179
|
export default facade(ErrorsService);
|
|
180
180
|
|
|
181
|
-
declare module '
|
|
181
|
+
declare module '@aerogel/core/services/Events' {
|
|
182
182
|
export interface EventsPayload {
|
|
183
183
|
error: { error: ErrorSource; message?: string };
|
|
184
184
|
}
|