This commit is contained in:
dap
2024-09-13 10:28:23 +08:00
35 changed files with 478 additions and 161 deletions

View File

@@ -35,7 +35,7 @@
},
"dependencies": {
"@iconify/vue": "^4.1.2",
"lucide-vue-next": "^0.439.0",
"lucide-vue-next": "^0.441.0",
"vue": "^3.5.4"
}
}

View File

@@ -1 +1 @@
export { defu as merge } from 'defu';
export { createDefu as createMerge, defu as merge } from 'defu';

View File

@@ -10,7 +10,19 @@ import type { FormActions, VbenFormProps } from './types';
import { toRaw } from 'vue';
import { Store } from '@vben-core/shared/store';
import { bindMethods, isFunction, StateHandler } from '@vben-core/shared/utils';
import {
bindMethods,
createMerge,
isFunction,
StateHandler,
} from '@vben-core/shared/utils';
const merge = createMerge((originObj, key, updates) => {
if (Array.isArray(originObj[key]) && Array.isArray(updates)) {
originObj[key] = updates;
return true;
}
});
function getDefaultState(): VbenFormProps {
return {
@@ -138,9 +150,11 @@ export class FormApi {
| Partial<VbenFormProps>,
) {
if (isFunction(stateOrFn)) {
this.store.setState(stateOrFn as (prev: VbenFormProps) => VbenFormProps);
this.store.setState((prev) => {
return merge(stateOrFn(prev), prev);
});
} else {
this.store.setState((prev) => ({ ...prev, ...stateOrFn }));
this.store.setState((prev) => merge(stateOrFn, prev));
}
}

View File

@@ -22,7 +22,7 @@ export function useExpandable(props: FormRenderProps) {
for (let index = 1; index <= rows; index++) {
maxItem += mapping?.[index] ?? 0;
}
return maxItem - 1;
return maxItem - 1 || 1;
});
watch(
@@ -50,11 +50,11 @@ export function useExpandable(props: FormRenderProps) {
return;
}
// 小屏幕不计算
if (breakpoints.smaller('sm').value) {
// 保持一行
rowMapping.value = { 1: 2 };
return;
}
// if (breakpoints.smaller('sm').value) {
// // 保持一行
// rowMapping.value = { 1: 2 };
// return;
// }
const formItems = [...wrapperRef.value.children];

View File

@@ -29,10 +29,12 @@ export class DrawerApi {
} = options;
const defaultState: DrawerState = {
class: '',
closable: true,
closeOnClickModal: true,
closeOnPressEscape: true,
confirmLoading: false,
contentClass: '',
footer: true,
isOpen: false,
loading: false,

View File

@@ -7,6 +7,7 @@ export interface DrawerProps {
* 取消按钮文字
*/
cancelText?: string;
class?: string;
/**
* 是否显示右上角的关闭按钮
* @default true
@@ -31,6 +32,7 @@ export interface DrawerProps {
* 确定按钮文字
*/
confirmText?: string;
contentClass?: string;
/**
* 弹窗描述
*/

View File

@@ -26,14 +26,10 @@ import {
import { cn } from '@vben-core/shared/utils';
interface Props extends DrawerProps {
class?: string;
contentClass?: string;
drawerApi?: ExtendedDrawerApi;
}
const props = withDefaults(defineProps<Props>(), {
class: '',
contentClass: '',
drawerApi: undefined,
});
@@ -44,11 +40,13 @@ const state = props.drawerApi?.useStore?.();
const {
cancelText,
class: drawerClass,
closable,
closeOnClickModal,
closeOnPressEscape,
confirmLoading,
confirmText,
contentClass,
description,
footer: showFooter,
loading: showLoading,
@@ -98,7 +96,7 @@ function pointerDownOutside(e: Event) {
>
<SheetContent
:class="
cn('flex w-[520px] flex-col', props.class, {
cn('flex w-[520px] flex-col', drawerClass, {
'!w-full': isMobile,
})
"

View File

@@ -30,14 +30,18 @@ export class ModalApi {
const defaultState: ModalState = {
centered: false,
class: '',
closeOnClickModal: true,
closeOnPressEscape: true,
confirmLoading: false,
contentClass: '',
draggable: false,
footer: true,
footerClass: '',
fullscreen: false,
fullscreenButton: true,
header: true,
headerClass: '',
isOpen: false,
loading: false,
modal: true,

View File

@@ -12,6 +12,7 @@ export interface ModalProps {
* @default false
*/
centered?: boolean;
class?: string;
/**
* 是否显示右上角的关闭按钮
* @default true
@@ -36,6 +37,7 @@ export interface ModalProps {
* 确定按钮文字
*/
confirmText?: string;
contentClass?: string;
/**
* 弹窗描述
*/
@@ -50,6 +52,7 @@ export interface ModalProps {
* @default true
*/
footer?: boolean;
footerClass?: string;
/**
* 是否全屏
* @default false
@@ -65,6 +68,7 @@ export interface ModalProps {
* @default true
*/
header?: boolean;
headerClass?: string;
/**
* 弹窗是否显示
* @default false

View File

@@ -27,18 +27,10 @@ import { cn } from '@vben-core/shared/utils';
import { useModalDraggable } from './use-modal-draggable';
interface Props extends ModalProps {
class?: string;
contentClass?: string;
footerClass?: string;
headerClass?: string;
modalApi?: ExtendedModalApi;
}
const props = withDefaults(defineProps<Props>(), {
class: '',
contentClass: '',
footerClass: '',
headerClass: '',
modalApi: undefined,
});
@@ -55,17 +47,21 @@ const state = props.modalApi?.useStore?.();
const {
cancelText,
centered,
class: modalClass,
closable,
closeOnClickModal,
closeOnPressEscape,
confirmLoading,
confirmText,
contentClass,
description,
draggable,
footer: showFooter,
footerClass,
fullscreen,
fullscreenButton,
header,
headerClass,
loading: showLoading,
modal,
openAutoFocus,
@@ -161,7 +157,7 @@ function pointerDownOutside(e: Event) {
:class="
cn(
'border-border left-0 right-0 top-[10vh] mx-auto flex max-h-[80%] w-[520px] flex-col border p-0',
props.class,
modalClass,
{
'left-0 top-0 size-full max-h-full !translate-x-0 !translate-y-0':
shouldFullscreen,
@@ -186,7 +182,7 @@ function pointerDownOutside(e: Event) {
hidden: !header,
'cursor-move select-none': shouldDraggable,
},
props.headerClass,
headerClass,
)
"
>
@@ -240,10 +236,7 @@ function pointerDownOutside(e: Event) {
v-if="showFooter"
ref="footerRef"
:class="
cn(
'flex-row items-center justify-end border-t p-2',
props.footerClass,
)
cn('flex-row items-center justify-end border-t p-2', footerClass)
"
>
<slot name="prepend-footer"></slot>

View File

@@ -46,7 +46,7 @@
"@vben-core/typings": "workspace:*",
"@vueuse/core": "^11.0.3",
"class-variance-authority": "^0.7.0",
"lucide-vue-next": "^0.439.0",
"lucide-vue-next": "^0.441.0",
"radix-vue": "^1.9.5",
"vee-validate": "^4.13.2",
"vue": "^3.5.4"

View File

@@ -21,6 +21,7 @@ export * from './render-content';
export * from './scrollbar';
export * from './segmented';
export * from './select';
export * from './spine-text';
export * from './spinner';
export * from './swap';
export * from './tooltip';

View File

@@ -0,0 +1 @@
export { default as VbenSpineText } from './spine-text.vue';

View File

@@ -0,0 +1,31 @@
<template>
<div class="vben-spine-text !bg-clip-text text-transparent">
<slot></slot>
</div>
</template>
<style>
.vben-spine-text {
background:
radial-gradient(circle at center, rgb(255 255 255 / 80%), #f000) -200% 50% /
200% 100% no-repeat,
#000;
animation: shine 3s linear infinite;
}
.dark .vben-spine-text {
background:
radial-gradient(circle at center, rgb(24 24 26 / 80%), transparent) -200% 50% /
200% 100% no-repeat,
#f4f4f4;
}
@keyframes shine {
0% {
background-position: 200% 0%;
}
100% {
background-position: -200% 0%;
}
}
</style>

View File

@@ -96,7 +96,14 @@ function goToLogin() {
</template>
</Title>
<Form />
<VbenButton :loading="loading" class="w-full" @click="handleSubmit">
<VbenButton
:class="{
'cursor-wait': loading,
}"
:loading="loading"
class="w-full"
@click="handleSubmit"
>
<slot name="submitButtonText">
{{ submitButtonText || $t('common.login') }}
</slot>

View File

@@ -91,7 +91,13 @@ function goToLogin() {
<Form />
<div>
<VbenButton class="mt-2 w-full" @click="handleSubmit">
<VbenButton
:class="{
'cursor-wait': loading,
}"
class="mt-2 w-full"
@click="handleSubmit"
>
<slot name="submitButtonText">
{{ submitButtonText || $t('authentication.sendResetLink') }}
</slot>

View File

@@ -132,7 +132,14 @@ defineExpose({ setFieldValue });
{{ $t('authentication.forgetPassword') }}
</span>
</div>
<VbenButton :loading="loading" class="w-full" @click="handleSubmit">
<VbenButton
:class="{
'cursor-wait': loading,
}"
:loading="loading"
class="w-full"
@click="handleSubmit"
>
{{ submitButtonText || $t('common.login') }}
</VbenButton>

View File

@@ -92,7 +92,14 @@ function goToLogin() {
</Title>
<Form />
<VbenButton :loading="loading" class="mt-2 w-full" @click="handleSubmit">
<VbenButton
:class="{
'cursor-wait': loading,
}"
:loading="loading"
class="mt-2 w-full"
@click="handleSubmit"
>
<slot name="submitButtonText">
{{ submitButtonText || $t('authentication.signUp') }}
</slot>

View File

@@ -49,7 +49,7 @@
"requestTimeout": "请求超时,请稍后再试。",
"networkError": "网络异常,请检查您的网络连接后重试。",
"badRequest": "请求错误。请检查您的输入并重试。",
"unauthorized": "登录认证过期请重新登录后继续。",
"unauthorized": "登录认证过期请重新登录后继续。",
"forbidden": "禁止访问, 您没有权限访问此资源。",
"notFound": "未找到, 请求的资源不存在。",
"internalServerError": "内部服务器错误,请稍后再试。",