feat: add VbenForm component (#4352)
* feat: add form component * fix: build error * feat: add form adapter * feat: add some component * feat: add some component * feat: add example * feat: suppoer custom action button * chore: update * feat: add example * feat: add formModel,formDrawer demo * fix: build error * fix: typo * fix: ci error --------- Co-authored-by: jinmao <jinmao88@qq.com> Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>
This commit is contained in:
@@ -5,7 +5,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { DrawerApi } from '../drawer-api';
|
||||
|
||||
// 模拟 Store 类
|
||||
vi.mock('@vben-core/shared', () => {
|
||||
vi.mock('@vben-core/shared/store', () => {
|
||||
return {
|
||||
isFunction: (fn: any) => typeof fn === 'function',
|
||||
Store: class {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import type { DrawerApiOptions, DrawerState } from './drawer';
|
||||
|
||||
import { isFunction, Store } from '@vben-core/shared';
|
||||
import { Store } from '@vben-core/shared/store';
|
||||
import { bindMethods, isFunction } from '@vben-core/shared/utils';
|
||||
|
||||
export class DrawerApi {
|
||||
private api: Pick<
|
||||
@@ -58,13 +59,14 @@ export class DrawerApi {
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
this.state = this.store.state;
|
||||
this.api = {
|
||||
onBeforeClose,
|
||||
onCancel,
|
||||
onConfirm,
|
||||
onOpenChange,
|
||||
};
|
||||
bindMethods(this);
|
||||
}
|
||||
|
||||
// 如果需要多次更新状态,可以使用 batch 方法
|
||||
|
@@ -5,10 +5,10 @@ import { ref, watch } from 'vue';
|
||||
|
||||
import {
|
||||
useIsMobile,
|
||||
usePriorityValue,
|
||||
usePriorityValues,
|
||||
useSimpleLocale,
|
||||
} from '@vben-core/composables';
|
||||
import { Info, X } from '@vben-core/icons';
|
||||
import { X } from '@vben-core/icons';
|
||||
import {
|
||||
Sheet,
|
||||
SheetClose,
|
||||
@@ -18,12 +18,12 @@ import {
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
VbenButton,
|
||||
VbenHelpTooltip,
|
||||
VbenIconButton,
|
||||
VbenLoading,
|
||||
VbenTooltip,
|
||||
VisuallyHidden,
|
||||
} from '@vben-core/shadcn-ui';
|
||||
import { cn } from '@vben-core/shared';
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
interface Props extends DrawerProps {
|
||||
class?: string;
|
||||
@@ -42,20 +42,22 @@ const { $t } = useSimpleLocale();
|
||||
const { isMobile } = useIsMobile();
|
||||
const state = props.drawerApi?.useStore?.();
|
||||
|
||||
const title = usePriorityValue('title', props, state);
|
||||
const description = usePriorityValue('description', props, state);
|
||||
const titleTooltip = usePriorityValue('titleTooltip', props, state);
|
||||
const showFooter = usePriorityValue('footer', props, state);
|
||||
const showLoading = usePriorityValue('loading', props, state);
|
||||
const closable = usePriorityValue('closable', props, state);
|
||||
const modal = usePriorityValue('modal', props, state);
|
||||
const confirmLoading = usePriorityValue('confirmLoading', props, state);
|
||||
const cancelText = usePriorityValue('cancelText', props, state);
|
||||
const confirmText = usePriorityValue('confirmText', props, state);
|
||||
const closeOnClickModal = usePriorityValue('closeOnClickModal', props, state);
|
||||
const closeOnPressEscape = usePriorityValue('closeOnPressEscape', props, state);
|
||||
const showCancelButton = usePriorityValue('showCancelButton', props, state);
|
||||
const showConfirmButton = usePriorityValue('showConfirmButton', props, state);
|
||||
const {
|
||||
cancelText,
|
||||
closable,
|
||||
closeOnClickModal,
|
||||
closeOnPressEscape,
|
||||
confirmLoading,
|
||||
confirmText,
|
||||
description,
|
||||
footer: showFooter,
|
||||
loading: showLoading,
|
||||
modal,
|
||||
showCancelButton,
|
||||
showConfirmButton,
|
||||
title,
|
||||
titleTooltip,
|
||||
} = usePriorityValues(props, state);
|
||||
|
||||
watch(
|
||||
() => showLoading.value,
|
||||
@@ -116,12 +118,9 @@ function pointerDownOutside(e: Event) {
|
||||
<slot name="title">
|
||||
{{ title }}
|
||||
|
||||
<VbenTooltip v-if="titleTooltip" side="right">
|
||||
<template #trigger>
|
||||
<Info class="inline-flex size-5 cursor-pointer pb-1" />
|
||||
</template>
|
||||
<VbenHelpTooltip v-if="titleTooltip" trigger-class="pb-1">
|
||||
{{ titleTooltip }}
|
||||
</VbenTooltip>
|
||||
</VbenHelpTooltip>
|
||||
</slot>
|
||||
</SheetTitle>
|
||||
<SheetDescription v-if="description" class="mt-1 text-xs">
|
||||
|
@@ -6,7 +6,7 @@ import type {
|
||||
|
||||
import { defineComponent, h, inject, nextTick, provide, reactive } from 'vue';
|
||||
|
||||
import { useStore } from '@vben-core/shared';
|
||||
import { useStore } from '@vben-core/shared/store';
|
||||
|
||||
import VbenDrawer from './drawer.vue';
|
||||
import { DrawerApi } from './drawer-api';
|
||||
|
@@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { ModalApi } from '../modal-api'; // 假设 ModalApi 位于同一目录
|
||||
import type { ModalState } from '../modal';
|
||||
|
||||
vi.mock('@vben-core/shared', () => {
|
||||
vi.mock('@vben-core/shared/store', () => {
|
||||
return {
|
||||
isFunction: (fn: any) => typeof fn === 'function',
|
||||
Store: class {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import type { ModalApiOptions, ModalState } from './modal';
|
||||
|
||||
import { isFunction, Store } from '@vben-core/shared';
|
||||
import { Store } from '@vben-core/shared/store';
|
||||
import { bindMethods, isFunction } from '@vben-core/shared/utils';
|
||||
|
||||
export class ModalApi {
|
||||
private api: Pick<
|
||||
@@ -65,12 +66,15 @@ export class ModalApi {
|
||||
},
|
||||
);
|
||||
|
||||
this.state = this.store.state;
|
||||
|
||||
this.api = {
|
||||
onBeforeClose,
|
||||
onCancel,
|
||||
onConfirm,
|
||||
onOpenChange,
|
||||
};
|
||||
bindMethods(this);
|
||||
}
|
||||
|
||||
// 如果需要多次更新状态,可以使用 batch 方法
|
||||
|
@@ -5,10 +5,10 @@ import { computed, nextTick, ref, watch } from 'vue';
|
||||
|
||||
import {
|
||||
useIsMobile,
|
||||
usePriorityValue,
|
||||
usePriorityValues,
|
||||
useSimpleLocale,
|
||||
} from '@vben-core/composables';
|
||||
import { Expand, Info, Shrink } from '@vben-core/icons';
|
||||
import { Expand, Shrink } from '@vben-core/icons';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -17,12 +17,12 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
VbenButton,
|
||||
VbenHelpTooltip,
|
||||
VbenIconButton,
|
||||
VbenLoading,
|
||||
VbenTooltip,
|
||||
VisuallyHidden,
|
||||
} from '@vben-core/shadcn-ui';
|
||||
import { cn } from '@vben-core/shared';
|
||||
import { cn } from '@vben-core/shared/utils';
|
||||
|
||||
import { useModalDraggable } from './use-modal-draggable';
|
||||
|
||||
@@ -52,25 +52,27 @@ const { $t } = useSimpleLocale();
|
||||
const { isMobile } = useIsMobile();
|
||||
const state = props.modalApi?.useStore?.();
|
||||
|
||||
const header = usePriorityValue('header', props, state);
|
||||
const title = usePriorityValue('title', props, state);
|
||||
const fullscreen = usePriorityValue('fullscreen', props, state);
|
||||
const description = usePriorityValue('description', props, state);
|
||||
const titleTooltip = usePriorityValue('titleTooltip', props, state);
|
||||
const showFooter = usePriorityValue('footer', props, state);
|
||||
const showLoading = usePriorityValue('loading', props, state);
|
||||
const closable = usePriorityValue('closable', props, state);
|
||||
const modal = usePriorityValue('modal', props, state);
|
||||
const centered = usePriorityValue('centered', props, state);
|
||||
const confirmLoading = usePriorityValue('confirmLoading', props, state);
|
||||
const cancelText = usePriorityValue('cancelText', props, state);
|
||||
const confirmText = usePriorityValue('confirmText', props, state);
|
||||
const draggable = usePriorityValue('draggable', props, state);
|
||||
const fullscreenButton = usePriorityValue('fullscreenButton', props, state);
|
||||
const closeOnClickModal = usePriorityValue('closeOnClickModal', props, state);
|
||||
const closeOnPressEscape = usePriorityValue('closeOnPressEscape', props, state);
|
||||
const showCancelButton = usePriorityValue('showCancelButton', props, state);
|
||||
const showConfirmButton = usePriorityValue('showConfirmButton', props, state);
|
||||
const {
|
||||
cancelText,
|
||||
centered,
|
||||
closable,
|
||||
closeOnClickModal,
|
||||
closeOnPressEscape,
|
||||
confirmLoading,
|
||||
confirmText,
|
||||
description,
|
||||
draggable,
|
||||
footer: showFooter,
|
||||
fullscreen,
|
||||
fullscreenButton,
|
||||
header,
|
||||
loading: showLoading,
|
||||
modal,
|
||||
showCancelButton,
|
||||
showConfirmButton,
|
||||
title,
|
||||
titleTooltip,
|
||||
} = usePriorityValues(props, state);
|
||||
|
||||
const shouldFullscreen = computed(
|
||||
() => (fullscreen.value && header.value) || isMobile.value,
|
||||
@@ -184,12 +186,9 @@ function pointerDownOutside(e: Event) {
|
||||
{{ title }}
|
||||
|
||||
<slot v-if="titleTooltip" name="titleTooltip">
|
||||
<VbenTooltip side="right">
|
||||
<template #trigger>
|
||||
<Info class="inline-flex size-5 cursor-pointer pb-1" />
|
||||
</template>
|
||||
<VbenHelpTooltip trigger-class="pb-1">
|
||||
{{ titleTooltip }}
|
||||
</VbenTooltip>
|
||||
</VbenHelpTooltip>
|
||||
</slot>
|
||||
</slot>
|
||||
</DialogTitle>
|
||||
|
@@ -2,7 +2,7 @@ import type { ExtendedModalApi, ModalApiOptions, ModalProps } from './modal';
|
||||
|
||||
import { defineComponent, h, inject, nextTick, provide, reactive } from 'vue';
|
||||
|
||||
import { useStore } from '@vben-core/shared';
|
||||
import { useStore } from '@vben-core/shared/store';
|
||||
|
||||
import VbenModal from './modal.vue';
|
||||
import { ModalApi } from './modal-api';
|
||||
@@ -33,7 +33,15 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
|
||||
...attrs,
|
||||
...slots,
|
||||
});
|
||||
return () => h(connectedComponent, { ...props, ...attrs }, slots);
|
||||
return () =>
|
||||
h(
|
||||
connectedComponent,
|
||||
{
|
||||
...props,
|
||||
...attrs,
|
||||
},
|
||||
slots,
|
||||
);
|
||||
},
|
||||
{
|
||||
inheritAttrs: false,
|
||||
@@ -65,7 +73,15 @@ export function useVbenModal<TParentModalProps extends ModalProps = ModalProps>(
|
||||
const Modal = defineComponent(
|
||||
(props: ModalProps, { attrs, slots }) => {
|
||||
return () =>
|
||||
h(VbenModal, { ...props, ...attrs, modalApi: extendedApi }, slots);
|
||||
h(
|
||||
VbenModal,
|
||||
{
|
||||
...props,
|
||||
...attrs,
|
||||
modalApi: extendedApi,
|
||||
},
|
||||
slots,
|
||||
);
|
||||
},
|
||||
{
|
||||
inheritAttrs: false,
|
||||
|
Reference in New Issue
Block a user