fix: 修复管理端前端 lint 与构建问题

- 收敛 easyflow-ui-admin 的 lint、格式和类型问题

- 修正 demo 页面与管理端前端构建失败点

- 验证 pnpm lint 与 pnpm build 均已通过
This commit is contained in:
2026-04-05 21:39:13 +08:00
parent bb72e19c84
commit 7e7c236c2a
240 changed files with 5151 additions and 4701 deletions

View File

@@ -3,7 +3,11 @@ import { computed, toRaw, unref, watch } from 'vue';
import { useSimpleLocale } from '@easyflow-core/composables';
import { EasyFlowExpandableArrow } from '@easyflow-core/shadcn-ui';
import { cn, isFunction, triggerWindowResize } from '@easyflow-core/shared/utils';
import {
cn,
isFunction,
triggerWindowResize,
} from '@easyflow-core/shared/utils';
import { COMPONENT_MAP } from '../config';
import { injectFormProps } from '../use-form-context';

View File

@@ -2,8 +2,8 @@ import type { Component } from 'vue';
import type {
BaseFormComponentType,
FormCommonConfig,
EasyFlowFormAdapterOptions,
FormCommonConfig,
} from './types';
import { h } from 'vue';

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { Recordable } from '@easyflow-core/typings';
import type { ExtendedFormApi, EasyFlowFormProps } from './types';
import type { EasyFlowFormProps, ExtendedFormApi } from './types';
// import { toRaw, watch } from 'vue';
import { nextTick, onMounted, watch } from 'vue';

View File

@@ -9,7 +9,7 @@ import type { ComponentPublicInstance } from 'vue';
import type { Recordable } from '@easyflow-core/typings';
import type { FormActions, FormSchema, EasyFlowFormProps } from './types';
import type { EasyFlowFormProps, FormActions, FormSchema } from './types';
import { isRef, toRaw } from 'vue';
@@ -55,7 +55,7 @@ export class FormApi {
public form = {} as FormActions;
isMounted = false;
public state: null | EasyFlowFormProps = null;
public state: EasyFlowFormProps | null = null;
stateHandler: StateHandler;
public store: Store<EasyFlowFormProps>;
@@ -68,7 +68,7 @@ export class FormApi {
// 最后一次点击提交时的表单值
private latestSubmissionValues: null | Recordable<any> = null;
private prevState: null | EasyFlowFormProps = null;
private prevState: EasyFlowFormProps | null = null;
constructor(options: EasyFlowFormProps = {}) {
const { ...storeState } = options;

View File

@@ -15,7 +15,12 @@ import {
FormItem,
FormMessage,
} from '@easyflow-core/shadcn-ui';
import { cn, isFunction, isObject, isString } from '@easyflow-core/shared/utils';
import {
cn,
isFunction,
isObject,
isString,
} from '@easyflow-core/shared/utils';
import { toTypedSchema } from '@vee-validate/zod';
import { useFieldError, useFormValues } from 'vee-validate';

View File

@@ -2,9 +2,9 @@
import type { CustomRenderType } from '../types';
import {
FormLabel,
EasyFlowHelpTooltip,
EasyFlowRenderContent,
FormLabel,
} from '@easyflow-core/shadcn-ui';
import { cn } from '@easyflow-core/shared/utils';

View File

@@ -2,9 +2,9 @@ export { setupEasyFlowForm } from './config';
export type {
BaseFormComponentType,
ExtendedFormApi,
EasyFlowFormProps,
FormSchema as EasyFlowFormSchema,
ExtendedFormApi,
} from './types';
export * from './use-easyflow-form';

View File

@@ -12,12 +12,12 @@ export type FormLayout = 'horizontal' | 'inline' | 'vertical';
export type BaseFormComponentType =
| 'DefaultButton'
| 'PrimaryButton'
| 'EasyFlowCheckbox'
| 'EasyFlowInput'
| 'EasyFlowInputPassword'
| 'EasyFlowPinInput'
| 'EasyFlowSelect'
| 'PrimaryButton'
| (Record<never, never> & string);
type Breakpoints = '2xl:' | '3xl:' | '' | 'lg:' | 'md:' | 'sm:' | 'xl:';

View File

@@ -1,15 +1,15 @@
import type {
BaseFormComponentType,
ExtendedFormApi,
EasyFlowFormProps,
ExtendedFormApi,
} from './types';
import { defineComponent, h, isReactive, onBeforeUnmount, watch } from 'vue';
import { useStore } from '@easyflow-core/shared/store';
import { FormApi } from './form-api';
import EasyFlowUseForm from './easyflow-use-form.vue';
import { FormApi } from './form-api';
export function useEasyFlowForm<
T extends BaseFormComponentType = BaseFormComponentType,

View File

@@ -2,12 +2,16 @@ import type { ZodRawShape } from 'zod';
import type { ComputedRef } from 'vue';
import type { ExtendedFormApi, FormActions, EasyFlowFormProps } from './types';
import type { EasyFlowFormProps, ExtendedFormApi, FormActions } from './types';
import { computed, unref, useSlots } from 'vue';
import { createContext } from '@easyflow-core/shadcn-ui';
import { isString, mergeWithArrayOverride, set } from '@easyflow-core/shared/utils';
import {
isString,
mergeWithArrayOverride,
set,
} from '@easyflow-core/shared/utils';
import { useForm } from 'vee-validate';
import { object, ZodIntersection, ZodNumber, ZodObject, ZodString } from 'zod';

View File

@@ -1,11 +1,12 @@
<script setup lang="ts">
import type {CSSProperties} from 'vue';
import {computed} from 'vue';
import type { CSSProperties } from 'vue';
import type {ContentCompactType} from '@easyflow-core/typings';
import type { ContentCompactType } from '@easyflow-core/typings';
import {useLayoutContentStyle} from '@easyflow-core/composables';
import {Slot} from '@easyflow-core/shadcn-ui';
import { computed } from 'vue';
import { useLayoutContentStyle } from '@easyflow-core/composables';
import { Slot } from '@easyflow-core/shadcn-ui';
interface Props {
/**

View File

@@ -1,6 +1,7 @@
<script setup lang="ts">
import type {CSSProperties} from 'vue';
import {computed, useSlots} from 'vue';
import type { CSSProperties } from 'vue';
import { computed, useSlots } from 'vue';
interface Props {
/**

View File

@@ -1,12 +1,13 @@
<script setup lang="ts">
import type {CSSProperties} from 'vue';
import {computed, shallowRef, useSlots, watchEffect} from 'vue';
import type { CSSProperties } from 'vue';
import {EasyFlowScrollbar} from '@easyflow-core/shadcn-ui';
import { computed, shallowRef, useSlots, watchEffect } from 'vue';
import {useScrollLock} from '@vueuse/core';
import { EasyFlowScrollbar } from '@easyflow-core/shadcn-ui';
import {SidebarCollapseButton, SidebarFixedButton} from './widgets';
import { useScrollLock } from '@vueuse/core';
import { SidebarCollapseButton, SidebarFixedButton } from './widgets';
interface Props {
/**
@@ -295,15 +296,11 @@ function handleFixedToggle(nextValue: boolean) {
},
]"
:style="style"
class="fixed left-0 top-0 h-full overflow-hidden transition-all duration-150"
class="fixed left-0 top-0 h-full overflow-hidden transition-all duration-150"
@mouseenter="handleMouseenter"
@mouseleave="handleMouseleave"
>
<div
v-if="slots.logo"
:style="headerStyle"
class="relative z-10 px-2 pt-2"
>
<div v-if="slots.logo" :style="headerStyle" class="relative z-10 px-2 pt-2">
<slot name="logo"></slot>
</div>
<EasyFlowScrollbar :style="contentStyle" class="relative z-10">
@@ -333,17 +330,14 @@ function handleFixedToggle(nextValue: boolean) {
>
<slot name="extra-title"></slot>
</div>
<EasyFlowScrollbar
:style="extraContentStyle"
class="relative z-10 py-2"
>
<EasyFlowScrollbar :style="extraContentStyle" class="relative z-10 py-2">
<slot name="extra"></slot>
</EasyFlowScrollbar>
<div
v-if="expandOnHover || !extraCollapse"
:style="toolStyle"
class="absolute right-3 z-20 flex flex-col gap-2"
>
v-if="expandOnHover || !extraCollapse"
:style="toolStyle"
class="absolute right-3 z-20 flex flex-col gap-2"
>
<SidebarCollapseButton
v-if="expandOnHover"
v-model:collapsed="extraCollapse"

View File

@@ -1,6 +1,7 @@
<script setup lang="ts">
import type {CSSProperties} from 'vue';
import {computed} from 'vue';
import type { CSSProperties } from 'vue';
import { computed } from 'vue';
interface Props {
/**

View File

@@ -21,7 +21,7 @@ function handleCollapsed() {
<button
aria-label="切换侧边栏折叠状态"
:style="buttonStyle"
class="flex-center h-9 w-9 rounded-2xl text-[hsl(var(--nav-item-muted-foreground))] backdrop-blur-xl transition-[background-color,color,transform,box-shadow,border-color] duration-200 hover:-translate-y-0.5 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--primary))/0.2]"
class="flex-center hover:text-foreground h-9 w-9 rounded-2xl text-[hsl(var(--nav-item-muted-foreground))] backdrop-blur-xl transition-[background-color,color,transform,box-shadow,border-color] duration-200 hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--primary))/0.2]"
@click.stop="handleCollapsed"
>
<ChevronsRight v-if="collapsed" class="size-4" />

View File

@@ -1,12 +1,12 @@
<script setup lang="ts">
import type {CSSProperties} from 'vue';
import type { CSSProperties } from 'vue';
import {Pin, PinOff} from '@easyflow-core/icons';
import { Pin, PinOff } from '@easyflow-core/icons';
const expandOnHover = defineModel<boolean>('expandOnHover');
const emit = defineEmits<{
toggle: [value: boolean];
}>();
const expandOnHover = defineModel<boolean>('expandOnHover');
const buttonStyle: CSSProperties = {
backgroundColor: 'hsl(var(--nav-tool-bg) / 0.92)',
backgroundImage:
@@ -26,7 +26,7 @@ function toggleFixed() {
<button
aria-label="切换侧边栏固定状态"
:style="buttonStyle"
class="flex-center h-9 w-9 rounded-2xl text-[hsl(var(--nav-item-muted-foreground))] backdrop-blur-xl transition-[background-color,color,transform,box-shadow,border-color] duration-200 hover:-translate-y-0.5 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--primary))/0.2]"
class="flex-center hover:text-foreground h-9 w-9 rounded-2xl text-[hsl(var(--nav-item-muted-foreground))] backdrop-blur-xl transition-[background-color,color,transform,box-shadow,border-color] duration-200 hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--primary))/0.2]"
@click="toggleFixed"
>
<PinOff v-if="!expandOnHover" class="size-3.5" />

View File

@@ -1,19 +1,20 @@
<script setup lang="ts">
import type {CSSProperties} from 'vue';
import {computed, ref, watch} from 'vue';
import type { CSSProperties } from 'vue';
import type {EasyFlowLayoutProps} from './easyflow-layout';
import type { EasyFlowLayoutProps } from './easyflow-layout';
import { computed, ref, watch } from 'vue';
import {
SCROLL_FIXED_CLASS,
useLayoutFooterStyle,
useLayoutHeaderStyle,
} from '@easyflow-core/composables';
import {IconifyIcon} from '@easyflow-core/icons';
import {EasyFlowIconButton} from '@easyflow-core/shadcn-ui';
import {ELEMENT_ID_MAIN_CONTENT} from '@easyflow-core/shared/constants';
import { IconifyIcon } from '@easyflow-core/icons';
import { EasyFlowIconButton } from '@easyflow-core/shadcn-ui';
import { ELEMENT_ID_MAIN_CONTENT } from '@easyflow-core/shared/constants';
import {useMouse, useScroll, useThrottleFn} from '@vueuse/core';
import { useMouse, useScroll, useThrottleFn } from '@vueuse/core';
import {
LayoutContent,
@@ -22,7 +23,7 @@ import {
LayoutSidebar,
LayoutTabbar,
} from './components';
import {useLayout} from './hooks/use-layout';
import { useLayout } from './hooks/use-layout';
interface Props extends EasyFlowLayoutProps {}
@@ -30,24 +31,6 @@ defineOptions({
name: 'EasyFlowLayout',
});
const headerToggleButtonClass =
'my-0 mr-1 flex h-9 w-9 items-center justify-center rounded-2xl text-[hsl(var(--nav-item-muted-foreground))] backdrop-blur-xl transition-[background-color,color,transform,box-shadow,border-color] hover:-translate-y-0.5 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--primary))/0.2]';
const headerToggleButtonStyle: CSSProperties = {
backgroundColor: 'hsl(var(--nav-tool-bg) / 0.92)',
backgroundImage:
'linear-gradient(180deg, hsl(var(--nav-tool-bg) / 0.96), hsl(var(--glass-tint) / 0.8))',
border: '1px solid hsl(var(--glass-border) / 0.2)',
boxShadow: '0 18px 36px -28px hsl(var(--primary) / 0.24)',
};
const layoutFlowFieldStyle: CSSProperties = {
backgroundImage:
'radial-gradient(ellipse 14% 18% at 5% 3%, hsl(var(--nav-flow-core) / 0.34) 0%, hsl(var(--nav-flow-core) / 0.14) 34%, transparent 74%), radial-gradient(ellipse 48% 18% at 16% 8%, hsl(var(--nav-flow-core) / 0.12) 0%, transparent 68%), radial-gradient(ellipse 68% 34% at 28% 18%, hsl(var(--nav-flow-secondary) / 0.1) 0%, transparent 70%), linear-gradient(122deg, hsl(var(--nav-flow-trace) / 0.13) 0%, hsl(var(--nav-flow-trace) / 0.1) 8%, hsl(var(--nav-flow-core) / 0.08) 14%, transparent 24%, transparent 42%, hsl(var(--nav-flow-secondary) / 0.06) 58%, hsl(var(--nav-flow-trace) / 0.04) 70%, transparent 88%), radial-gradient(ellipse 84% 34% at 34% 26%, hsl(var(--nav-flow-core) / 0.08) 0%, transparent 72%), radial-gradient(ellipse 74% 30% at 48% 38%, hsl(var(--nav-flow-secondary) / 0.06) 0%, transparent 74%), radial-gradient(ellipse 62% 26% at 60% 48%, hsl(var(--nav-flow-accent) / 0.04) 0%, transparent 76%)',
};
const layoutFlowGlowStyle: CSSProperties = {
backgroundImage:
'radial-gradient(ellipse 18% 20% at 6% 4%, hsl(var(--nav-flow-core) / 0.18) 0%, transparent 74%), radial-gradient(ellipse 72% 28% at 26% 16%, hsl(var(--nav-flow-trace) / 0.08) 0%, transparent 70%), radial-gradient(ellipse 68% 26% at 44% 28%, hsl(var(--nav-flow-secondary) / 0.05) 0%, transparent 72%), radial-gradient(ellipse 58% 22% at 62% 42%, hsl(var(--nav-flow-trace) / 0.04) 0%, transparent 74%)',
};
const props = withDefaults(defineProps<Props>(), {
contentCompact: 'wide',
contentCompactWidth: 1200,
@@ -79,8 +62,25 @@ const props = withDefaults(defineProps<Props>(), {
tabbarHeight: 40,
zIndex: 200,
});
const emit = defineEmits<{ sideMouseLeave: []; toggleSidebar: [] }>();
const headerToggleButtonClass =
'my-0 mr-1 flex h-9 w-9 items-center justify-center rounded-2xl text-[hsl(var(--nav-item-muted-foreground))] backdrop-blur-xl transition-[background-color,color,transform,box-shadow,border-color] hover:-translate-y-0.5 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--primary))/0.2]';
const headerToggleButtonStyle: CSSProperties = {
backgroundColor: 'hsl(var(--nav-tool-bg) / 0.92)',
backgroundImage:
'linear-gradient(180deg, hsl(var(--nav-tool-bg) / 0.96), hsl(var(--glass-tint) / 0.8))',
border: '1px solid hsl(var(--glass-border) / 0.2)',
boxShadow: '0 18px 36px -28px hsl(var(--primary) / 0.24)',
};
const layoutFlowFieldStyle: CSSProperties = {
backgroundImage:
'radial-gradient(ellipse 14% 18% at 5% 3%, hsl(var(--nav-flow-core) / 0.34) 0%, hsl(var(--nav-flow-core) / 0.14) 34%, transparent 74%), radial-gradient(ellipse 48% 18% at 16% 8%, hsl(var(--nav-flow-core) / 0.12) 0%, transparent 68%), radial-gradient(ellipse 68% 34% at 28% 18%, hsl(var(--nav-flow-secondary) / 0.1) 0%, transparent 70%), linear-gradient(122deg, hsl(var(--nav-flow-trace) / 0.13) 0%, hsl(var(--nav-flow-trace) / 0.1) 8%, hsl(var(--nav-flow-core) / 0.08) 14%, transparent 24%, transparent 42%, hsl(var(--nav-flow-secondary) / 0.06) 58%, hsl(var(--nav-flow-trace) / 0.04) 70%, transparent 88%), radial-gradient(ellipse 84% 34% at 34% 26%, hsl(var(--nav-flow-core) / 0.08) 0%, transparent 72%), radial-gradient(ellipse 74% 30% at 48% 38%, hsl(var(--nav-flow-secondary) / 0.06) 0%, transparent 74%), radial-gradient(ellipse 62% 26% at 60% 48%, hsl(var(--nav-flow-accent) / 0.04) 0%, transparent 76%)',
};
const layoutFlowGlowStyle: CSSProperties = {
backgroundImage:
'radial-gradient(ellipse 18% 20% at 6% 4%, hsl(var(--nav-flow-core) / 0.18) 0%, transparent 74%), radial-gradient(ellipse 72% 28% at 26% 16%, hsl(var(--nav-flow-trace) / 0.08) 0%, transparent 70%), radial-gradient(ellipse 68% 26% at 44% 28%, hsl(var(--nav-flow-secondary) / 0.05) 0%, transparent 72%), radial-gradient(ellipse 58% 22% at 62% 42%, hsl(var(--nav-flow-trace) / 0.04) 0%, transparent 74%)',
};
const sidebarCollapse = defineModel<boolean>('sidebarCollapse', {
default: false,
});

View File

@@ -434,8 +434,8 @@ $namespace: easyflow;
&:focus-visible {
box-shadow:
0 0 0 1px hsl(var(--glass-border) / 0.72),
0 0 0 4px hsl(var(--ring) / 0.16);
0 0 0 1px hsl(var(--glass-border) / 72%),
0 0 0 4px hsl(var(--ring) / 16%);
}
* {
@@ -472,8 +472,8 @@ $namespace: easyflow;
--menu-item-collapse-margin-x: 8px;
--menu-item-radius: 14px;
--menu-item-shadow:
inset 0 1px 0 hsl(var(--nav-sheen) / 0.54),
0 22px 40px -30px hsl(var(--primary) / 0.24);
inset 0 1px 0 hsl(var(--nav-sheen) / 54%),
0 22px 40px -30px hsl(var(--primary) / 24%);
--menu-item-indent: 18px;
--menu-font-size: 14px;
--menu-item-indicator-width: 0px;
@@ -485,28 +485,28 @@ $namespace: easyflow;
--menu-item-hover-color: hsl(var(--foreground));
--menu-item-hover-background-color: linear-gradient(
180deg,
hsl(var(--nav-item-hover) / 0.78),
hsl(var(--glass-tint) / 0.46)
hsl(var(--nav-item-hover) / 78%),
hsl(var(--glass-tint) / 46%)
);
--menu-item-active-color: hsl(var(--nav-item-active-foreground));
--menu-item-active-background-color: linear-gradient(
135deg,
hsl(var(--nav-item-active) / 0.92) 0%,
hsl(var(--nav-item-hover) / 0.72) 54%,
hsl(var(--glass-tint) / 0.52) 100%
hsl(var(--nav-item-active) / 92%) 0%,
hsl(var(--nav-item-hover) / 72%) 54%,
hsl(var(--glass-tint) / 52%) 100%
);
--menu-submenu-hover-color: hsl(var(--foreground));
--menu-submenu-hover-background-color: linear-gradient(
180deg,
hsl(var(--nav-item-hover) / 0.78),
hsl(var(--glass-tint) / 0.46)
hsl(var(--nav-item-hover) / 78%),
hsl(var(--glass-tint) / 46%)
);
--menu-submenu-active-color: hsl(var(--nav-item-active-foreground));
--menu-submenu-active-background-color: linear-gradient(
135deg,
hsl(var(--nav-item-active) / 0.92) 0%,
hsl(var(--nav-item-hover) / 0.72) 54%,
hsl(var(--glass-tint) / 0.52) 100%
hsl(var(--nav-item-active) / 92%) 0%,
hsl(var(--nav-item-hover) / 72%) 54%,
hsl(var(--glass-tint) / 52%) 100%
);
--menu-submenu-background-color: var(--menu-background-color);
}
@@ -518,28 +518,28 @@ $namespace: easyflow;
--menu-item-hover-color: hsl(var(--foreground));
--menu-item-hover-background-color: linear-gradient(
180deg,
hsl(var(--nav-item-hover) / 0.78),
hsl(var(--glass-tint) / 0.46)
hsl(var(--nav-item-hover) / 78%),
hsl(var(--glass-tint) / 46%)
);
--menu-item-active-color: hsl(var(--nav-item-active-foreground));
--menu-item-active-background-color: linear-gradient(
135deg,
hsl(var(--nav-item-active) / 0.92) 0%,
hsl(var(--nav-item-hover) / 0.72) 54%,
hsl(var(--glass-tint) / 0.52) 100%
hsl(var(--nav-item-active) / 92%) 0%,
hsl(var(--nav-item-hover) / 72%) 54%,
hsl(var(--glass-tint) / 52%) 100%
);
--menu-submenu-hover-color: hsl(var(--foreground));
--menu-submenu-hover-background-color: linear-gradient(
180deg,
hsl(var(--nav-item-hover) / 0.78),
hsl(var(--glass-tint) / 0.46)
hsl(var(--nav-item-hover) / 78%),
hsl(var(--glass-tint) / 46%)
);
--menu-submenu-active-color: hsl(var(--nav-item-active-foreground));
--menu-submenu-active-background-color: linear-gradient(
135deg,
hsl(var(--nav-item-active) / 0.92) 0%,
hsl(var(--nav-item-hover) / 0.72) 54%,
hsl(var(--glass-tint) / 0.52) 100%
hsl(var(--nav-item-active) / 92%) 0%,
hsl(var(--nav-item-hover) / 72%) 54%,
hsl(var(--glass-tint) / 52%) 100%
);
--menu-submenu-background-color: var(--menu-background-color);
}
@@ -573,28 +573,28 @@ $namespace: easyflow;
--menu-item-hover-color: hsl(var(--foreground));
--menu-item-hover-background-color: linear-gradient(
180deg,
hsl(var(--nav-item-hover) / 0.98),
hsl(var(--nav-surface-subtle) / 0.84)
hsl(var(--nav-item-hover) / 98%),
hsl(var(--nav-surface-subtle) / 84%)
);
--menu-item-active-color: hsl(var(--nav-item-active-foreground));
--menu-item-active-background-color: linear-gradient(
135deg,
hsl(var(--nav-item-active)) 0%,
hsl(var(--nav-item-hover) / 0.98) 55%,
hsl(var(--glass-tint) / 0.98) 100%
hsl(var(--nav-item-hover) / 98%) 55%,
hsl(var(--glass-tint) / 98%) 100%
);
--menu-submenu-active-color: hsl(var(--nav-item-active-foreground));
--menu-submenu-active-background-color: linear-gradient(
135deg,
hsl(var(--nav-item-active)) 0%,
hsl(var(--nav-item-hover) / 0.98) 55%,
hsl(var(--glass-tint) / 0.98) 100%
hsl(var(--nav-item-hover) / 98%) 55%,
hsl(var(--glass-tint) / 98%) 100%
);
--menu-submenu-hover-color: hsl(var(--foreground));
--menu-submenu-hover-background-color: linear-gradient(
180deg,
hsl(var(--nav-item-hover) / 0.98),
hsl(var(--nav-surface-subtle) / 0.84)
hsl(var(--nav-item-hover) / 98%),
hsl(var(--nav-surface-subtle) / 84%)
);
}
@@ -603,27 +603,27 @@ $namespace: easyflow;
--menu-item-active-background-color: linear-gradient(
135deg,
hsl(var(--nav-item-active)) 0%,
hsl(var(--nav-item-hover) / 0.98) 55%,
hsl(var(--glass-tint) / 0.98) 100%
hsl(var(--nav-item-hover) / 98%) 55%,
hsl(var(--glass-tint) / 98%) 100%
);
--menu-item-hover-background-color: linear-gradient(
180deg,
hsl(var(--nav-item-hover) / 0.98),
hsl(var(--nav-surface-subtle) / 0.84)
hsl(var(--nav-item-hover) / 98%),
hsl(var(--nav-surface-subtle) / 84%)
);
--menu-item-hover-color: hsl(var(--foreground));
--menu-submenu-active-color: hsl(var(--nav-item-active-foreground));
--menu-submenu-active-background-color: linear-gradient(
135deg,
hsl(var(--nav-item-active)) 0%,
hsl(var(--nav-item-hover) / 0.98) 55%,
hsl(var(--glass-tint) / 0.98) 100%
hsl(var(--nav-item-hover) / 98%) 55%,
hsl(var(--glass-tint) / 98%) 100%
);
--menu-submenu-hover-color: hsl(var(--foreground));
--menu-submenu-hover-background-color: linear-gradient(
180deg,
hsl(var(--nav-item-hover) / 0.98),
hsl(var(--nav-surface-subtle) / 0.84)
hsl(var(--nav-item-hover) / 98%),
hsl(var(--nav-surface-subtle) / 84%)
);
}
}
@@ -829,10 +829,10 @@ $namespace: easyflow;
&__content {
display: inline-flex;
gap: 10px;
align-items: center;
width: 100%;
height: var(--menu-item-height);
gap: 10px;
span {
@include menu-title;
@@ -867,7 +867,7 @@ $namespace: easyflow;
text-decoration: none;
cursor: pointer;
background: var(--menu-item-hover-background-color) !important;
box-shadow: 0 18px 34px -30px hsl(var(--primary) / 0.18);
box-shadow: 0 18px 34px -30px hsl(var(--primary) / 18%);
transform: translateX(2px);
}
@@ -902,8 +902,8 @@ $namespace: easyflow;
text-decoration: none;
cursor: pointer;
background: var(--menu-submenu-active-background-color);
fill: var(--menu-submenu-active-color);
box-shadow: var(--menu-item-shadow);
fill: var(--menu-submenu-active-color);
}
}
@@ -914,8 +914,8 @@ $namespace: easyflow;
&:focus-visible > .#{$namespace}-sub-menu-content,
&:focus-within > .#{$namespace}-sub-menu-content {
box-shadow:
0 0 0 1px hsl(var(--glass-border) / 0.72),
0 0 0 4px hsl(var(--ring) / 0.16);
0 0 0 1px hsl(var(--glass-border) / 72%),
0 0 0 4px hsl(var(--ring) / 16%);
}
}
@@ -938,8 +938,9 @@ $namespace: easyflow;
}
&__title {
@include menu-title;
font-weight: 500;
@include menu-title;
}
&.is-collapse-show-title {
@@ -973,7 +974,7 @@ $namespace: easyflow;
text-decoration: none;
cursor: pointer;
background: var(--menu-submenu-hover-background-color) !important;
box-shadow: 0 18px 34px -30px hsl(var(--primary) / 0.18);
box-shadow: 0 18px 34px -30px hsl(var(--primary) / 18%);
transform: translateX(2px);
}
}

View File

@@ -7,7 +7,7 @@ import type { AlertProps, BeforeCloseScope, PromptProps } from './alert';
import { h, nextTick, ref, render } from 'vue';
import { useSimpleLocale } from '@easyflow-core/composables';
import { Input, EasyFlowRenderContent } from '@easyflow-core/shadcn-ui';
import { EasyFlowRenderContent, Input } from '@easyflow-core/shadcn-ui';
import { isFunction, isString } from '@easyflow-core/shared/utils';
import Alert from './alert.vue';

View File

@@ -177,7 +177,10 @@ async function handleOpenChange(val: boolean) {
<div class="m-4 min-h-[30px]">
<EasyFlowRenderContent :content="content" render-br />
</div>
<EasyFlowLoading v-if="loading && contentMasking" :spinning="loading" />
<EasyFlowLoading
v-if="loading && contentMasking"
:spinning="loading"
/>
</AlertDialogDescription>
<div
class="flex items-center justify-end gap-x-2"

View File

@@ -18,6 +18,10 @@ import {
} from '@easyflow-core/composables';
import { X } from '@easyflow-core/icons';
import {
EasyFlowButton,
EasyFlowHelpTooltip,
EasyFlowIconButton,
EasyFlowLoading,
Separator,
Sheet,
SheetClose,
@@ -26,10 +30,6 @@ import {
SheetFooter,
SheetHeader,
SheetTitle,
EasyFlowButton,
EasyFlowHelpTooltip,
EasyFlowIconButton,
EasyFlowLoading,
VisuallyHidden,
} from '@easyflow-core/shadcn-ui';
import { ELEMENT_ID_MAIN_CONTENT } from '@easyflow-core/shared/constants';
@@ -184,11 +184,16 @@ const getForceMount = computed(() => {
<SheetContent
:append-to="getAppendTo"
:class="
cn('flex w-[520px] flex-col overflow-hidden border border-[hsl(var(--glass-border))/0.18] bg-[hsl(var(--glass-tint))/0.84] shadow-[var(--shadow-float)] supports-[backdrop-filter]:bg-[hsl(var(--glass-tint))/0.62]', drawerClass, {
'!w-full': isMobile || placement === 'bottom' || placement === 'top',
'max-h-[100vh]': placement === 'bottom' || placement === 'top',
hidden: isClosed,
})
cn(
'flex w-[520px] flex-col overflow-hidden border border-[hsl(var(--glass-border))/0.18] bg-[hsl(var(--glass-tint))/0.84] shadow-[var(--shadow-float)] supports-[backdrop-filter]:bg-[hsl(var(--glass-tint))/0.62]',
drawerClass,
{
'!w-full':
isMobile || placement === 'bottom' || placement === 'top',
'max-h-[100vh]': placement === 'bottom' || placement === 'top',
hidden: isClosed,
},
)
"
:modal="modal"
:open="state?.isOpen"
@@ -223,7 +228,7 @@ const getForceMount = computed(() => {
v-if="closable && closeIconPlacement === 'left'"
as-child
:disabled="submitting"
class="data-[state=open]:bg-[hsl(var(--surface-contrast-soft))/0.92] ml-[2px] cursor-pointer rounded-full opacity-84 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none"
class="opacity-84 ml-[2px] cursor-pointer rounded-full transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none data-[state=open]:bg-[hsl(var(--surface-contrast-soft))/0.92]"
>
<slot name="close-icon">
<EasyFlowIconButton>
@@ -264,7 +269,7 @@ const getForceMount = computed(() => {
v-if="closable && closeIconPlacement === 'right'"
as-child
:disabled="submitting"
class="data-[state=open]:bg-[hsl(var(--surface-contrast-soft))/0.92] ml-[2px] cursor-pointer rounded-full opacity-84 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none"
class="opacity-84 ml-[2px] cursor-pointer rounded-full transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none data-[state=open]:bg-[hsl(var(--surface-contrast-soft))/0.92]"
>
<slot name="close-icon">
<EasyFlowIconButton>

View File

@@ -105,7 +105,11 @@ export function useEasyFlowDrawer<
const Drawer = defineComponent(
(props: DrawerProps, { attrs, slots }) => {
return () =>
h(EasyFlowDrawer, { ...props, ...attrs, drawerApi: extendedApi }, slots);
h(
EasyFlowDrawer,
{ ...props, ...attrs, drawerApi: extendedApi },
slots,
);
},
// eslint-disable-next-line vue/one-component-per-file
{

View File

@@ -23,9 +23,9 @@ export function setDefaultModalProps(props: Partial<ModalProps>) {
Object.assign(DEFAULT_MODAL_PROPS, props);
}
export function useEasyFlowModal<TParentModalProps extends ModalProps = ModalProps>(
options: ModalApiOptions = {},
) {
export function useEasyFlowModal<
TParentModalProps extends ModalProps = ModalProps,
>(options: ModalApiOptions = {}) {
// Modal一般会抽离出来所以如果有传入 connectedComponent则表示为外部调用与内部组件进行连接
// 外部的Modal通过provide/inject传递api

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type {BreadcrumbProps} from './types';
import type { BreadcrumbProps } from './types';
import {ChevronDown} from '@easyflow-core/icons';
import { ChevronDown } from '@easyflow-core/icons';
import {
Breadcrumb,
@@ -15,7 +15,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from '../../ui';
import {EasyFlowIcon} from '../icon';
import { EasyFlowIcon } from '../icon';
interface Props extends BreadcrumbProps {}
@@ -106,18 +106,18 @@ function handleClick(path?: string) {
<style scoped>
.easyflow-breadcrumb {
gap: 4px;
color: hsl(var(--breadcrumb-muted));
font-size: 13px;
color: hsl(var(--breadcrumb-muted));
}
.easyflow-breadcrumb__link {
display: inline-flex;
align-items: center;
gap: 4px;
align-items: center;
min-width: 0;
padding: 4px 8px;
border-radius: 999px;
color: hsl(var(--breadcrumb-muted));
border-radius: 999px;
transition:
color 0.16s ease,
background-color 0.16s ease,
@@ -125,20 +125,20 @@ function handleClick(path?: string) {
}
.easyflow-breadcrumb__link:hover {
background: hsl(var(--nav-item-hover) / 0.7);
color: hsl(var(--nav-item-active-foreground));
background: hsl(var(--nav-item-hover) / 70%);
transform: translateY(-0.5px);
}
.easyflow-breadcrumb__current {
position: relative;
display: inline-flex;
align-items: center;
gap: 4px;
align-items: center;
min-width: 0;
padding: 4px 8px 6px;
color: hsl(var(--breadcrumb-current));
font-weight: 600;
color: hsl(var(--breadcrumb-current));
letter-spacing: 0.01em;
isolation: isolate;
}
@@ -150,17 +150,17 @@ function handleClick(path?: string) {
content: '';
background: linear-gradient(
180deg,
hsl(var(--nav-item-active) / 0.36) 0%,
hsl(var(--nav-item-active) / 0.18) 42%,
hsl(var(--glass-tint) / 0.08) 82%,
hsl(var(--nav-item-active) / 36%) 0%,
hsl(var(--nav-item-active) / 18%) 42%,
hsl(var(--glass-tint) / 8%) 82%,
transparent 100%
);
border-radius: 14px 14px 10px 10px;
box-shadow:
inset 1px 0 0 hsl(var(--nav-border) / 0.54),
inset -1px 0 0 hsl(var(--nav-border) / 0.54),
inset 0 1px 0 hsl(var(--nav-sheen) / 0.68),
0 10px 22px -22px hsl(var(--primary) / 0.2);
inset 1px 0 0 hsl(var(--nav-border) / 54%),
inset -1px 0 0 hsl(var(--nav-border) / 54%),
inset 0 1px 0 hsl(var(--nav-sheen) / 68%),
0 10px 22px -22px hsl(var(--primary) / 20%);
}
.easyflow-breadcrumb__current::after {
@@ -168,22 +168,22 @@ function handleClick(path?: string) {
right: -6px;
bottom: 0;
left: -6px;
height: 1px;
z-index: -1;
height: 1px;
content: '';
background: linear-gradient(
90deg,
transparent,
hsl(var(--nav-item-active) / 0.2) 22%,
hsl(var(--nav-item-active) / 0.26) 50%,
hsl(var(--nav-item-active) / 0.2) 78%,
hsl(var(--nav-item-active) / 20%) 22%,
hsl(var(--nav-item-active) / 26%) 50%,
hsl(var(--nav-item-active) / 20%) 78%,
transparent
);
opacity: 0.72;
}
.easyflow-breadcrumb__separator {
color: hsl(var(--breadcrumb-muted) / 0.72);
color: hsl(var(--breadcrumb-muted) / 72%);
}
.easyflow-breadcrumb__separator :deep(svg) {

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import type { Arrayable } from '@vueuse/core';
import type { ValueType, EasyFlowButtonGroupProps } from './button';
import type { EasyFlowButtonGroupProps, ValueType } from './button';
import { computed, ref, watch } from 'vue';

View File

@@ -16,7 +16,10 @@ const style = computed(() => {
});
</script>
<template>
<div :style="style" class="easyflow-spine-text !bg-clip-text text-transparent">
<div
:style="style"
class="easyflow-spine-text !bg-clip-text text-transparent"
>
<slot></slot>
</div>
</template>

View File

@@ -1,12 +1,12 @@
<script setup lang="ts">
import type {TabDefinition} from '@easyflow-core/typings';
import type { TabDefinition } from '@easyflow-core/typings';
import type {TabConfig, TabsProps} from '../../types';
import type { TabConfig, TabsProps } from '../../types';
import {computed, ref} from 'vue';
import { computed, ref } from 'vue';
import {Pin, X} from '@easyflow-core/icons';
import {EasyFlowContextMenu, EasyFlowIcon} from '@easyflow-core/shadcn-ui';
import { Pin, X } from '@easyflow-core/icons';
import { EasyFlowContextMenu, EasyFlowIcon } from '@easyflow-core/shadcn-ui';
interface Props extends TabsProps {}
@@ -167,10 +167,10 @@ function onMouseDown(e: MouseEvent, tab: TabConfig) {
inset: 1px -5px -1px;
content: '';
background: hsl(var(--background));
border-top: 2px solid hsl(var(--primary) / 38%);
border-right: 1px solid hsl(var(--primary) / 16%);
border-left: 1px solid hsl(var(--primary) / 16%);
border-radius: 15px 15px 0 0;
border-top: 2px solid hsl(var(--primary) / 0.38);
border-right: 1px solid hsl(var(--primary) / 0.16);
border-left: 1px solid hsl(var(--primary) / 0.16);
}
&__background-content.is-active::after {

View File

@@ -38,7 +38,7 @@ const typeWithClass = computed(() => {
},
plain: {
content:
"h-[calc(100%-8px)] rounded-2xl border border-transparent bg-transparent transition-all duration-150 [&.is-active]:bg-[hsl(var(--glass-tint))/0.72] [&.is-active]:shadow-[0_16px_28px_-24px_hsl(var(--foreground)/0.34)] [&:not(.is-active)]:hover:bg-[hsl(var(--nav-item-hover))/0.9]",
'h-[calc(100%-8px)] rounded-2xl border border-transparent bg-transparent transition-all duration-150 [&.is-active]:bg-[hsl(var(--glass-tint))/0.72] [&.is-active]:shadow-[0_16px_28px_-24px_hsl(var(--foreground)/0.34)] [&:not(.is-active)]:hover:bg-[hsl(var(--nav-item-hover))/0.9]',
},
};
@@ -136,7 +136,9 @@ function onMouseDown(e: MouseEvent, tab: TabConfig) {
fallback
/>
<span class="flex-1 overflow-hidden whitespace-nowrap text-[13px]">
<span
class="flex-1 overflow-hidden whitespace-nowrap text-[13px]"
>
{{ tab.title }}
</span>
</div>

View File

@@ -10,7 +10,7 @@ defineProps<DropdownMenuProps>();
<template>
<EasyFlowDropdownMenu :menus="menus" :modal="false">
<div
class="flex-center mr-1 h-8 w-8 cursor-pointer rounded-2xl border border-transparent bg-[hsl(var(--glass-tint))/0.52] text-[hsl(var(--nav-item-muted-foreground))] shadow-[0_10px_24px_-24px_hsl(var(--foreground)/0.3)] backdrop-blur-xl transition-[background-color,color,transform] hover:-translate-y-0.5 hover:bg-[hsl(var(--surface-contrast-soft))/0.92] hover:text-foreground"
class="flex-center hover:text-foreground mr-1 h-8 w-8 cursor-pointer rounded-2xl border border-transparent bg-[hsl(var(--glass-tint))/0.52] text-[hsl(var(--nav-item-muted-foreground))] shadow-[0_10px_24px_-24px_hsl(var(--foreground)/0.3)] backdrop-blur-xl transition-[background-color,color,transform] hover:-translate-y-0.5 hover:bg-[hsl(var(--surface-contrast-soft))/0.92]"
>
<ChevronDown class="size-4" />
</div>

View File

@@ -10,7 +10,7 @@ function toggleScreen() {
<template>
<div
class="flex-center h-8 w-8 cursor-pointer rounded-2xl border border-transparent bg-[hsl(var(--glass-tint))/0.52] text-[hsl(var(--nav-item-muted-foreground))] shadow-[0_10px_24px_-24px_hsl(var(--foreground)/0.3)] backdrop-blur-xl transition-[background-color,color,transform] hover:-translate-y-0.5 hover:bg-[hsl(var(--surface-contrast-soft))/0.92] hover:text-foreground"
class="flex-center hover:text-foreground h-8 w-8 cursor-pointer rounded-2xl border border-transparent bg-[hsl(var(--glass-tint))/0.52] text-[hsl(var(--nav-item-muted-foreground))] shadow-[0_10px_24px_-24px_hsl(var(--foreground)/0.3)] backdrop-blur-xl transition-[background-color,color,transform] hover:-translate-y-0.5 hover:bg-[hsl(var(--surface-contrast-soft))/0.92]"
@click="toggleScreen"
>
<Minimize2 v-if="screen" class="size-4" />

View File

@@ -1,13 +1,13 @@
<script setup lang="ts">
import type {TabsEmits, TabsProps} from './types';
import type { TabsEmits, TabsProps } from './types';
import {useForwardPropsEmits} from '@easyflow-core/composables';
import {ChevronLeft, ChevronRight} from '@easyflow-core/icons';
import {EasyFlowScrollbar} from '@easyflow-core/shadcn-ui';
import { useForwardPropsEmits } from '@easyflow-core/composables';
import { ChevronLeft, ChevronRight } from '@easyflow-core/icons';
import { EasyFlowScrollbar } from '@easyflow-core/shadcn-ui';
import {Tabs, TabsChrome} from './components';
import {useTabsDrag} from './use-tabs-drag';
import {useTabsViewScroll} from './use-tabs-view-scroll';
import { Tabs, TabsChrome } from './components';
import { useTabsDrag } from './use-tabs-drag';
import { useTabsViewScroll } from './use-tabs-view-scroll';
interface Props extends TabsProps {}
@@ -53,7 +53,8 @@ useTabsDrag(props, emit);
<span
v-show="showScrollButton"
:class="{
'cursor-pointer text-[hsl(var(--nav-item-muted-foreground))] hover:bg-[hsl(var(--surface-contrast-soft))] hover:text-foreground': !scrollIsAtLeft,
'hover:text-foreground cursor-pointer text-[hsl(var(--nav-item-muted-foreground))] hover:bg-[hsl(var(--surface-contrast-soft))]':
!scrollIsAtLeft,
'pointer-events-none opacity-30': scrollIsAtLeft,
}"
class="mx-1 my-1 flex items-center rounded-2xl border border-transparent bg-[hsl(var(--glass-tint))/0.18] px-2 shadow-none backdrop-blur-xl transition-[background-color,color,transform]"
@@ -94,7 +95,8 @@ useTabsDrag(props, emit);
<span
v-show="showScrollButton"
:class="{
'cursor-pointer text-[hsl(var(--nav-item-muted-foreground))] hover:bg-[hsl(var(--surface-contrast-soft))] hover:text-foreground': !scrollIsAtRight,
'hover:text-foreground cursor-pointer text-[hsl(var(--nav-item-muted-foreground))] hover:bg-[hsl(var(--surface-contrast-soft))]':
!scrollIsAtRight,
'pointer-events-none opacity-30': scrollIsAtRight,
}"
class="mx-1 my-1 flex items-center rounded-2xl border border-transparent bg-[hsl(var(--glass-tint))/0.18] px-2 shadow-none backdrop-blur-xl transition-[background-color,color,transform]"

View File

@@ -1,7 +1,7 @@
import type { TabsProps } from './types';
import type { ComponentPublicInstance } from 'vue';
import type { TabsProps } from './types';
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import { useDebounceFn } from '@vueuse/core';
@@ -13,7 +13,7 @@ export function useTabsViewScroll(props: TabsProps) {
let resizeObserver: null | ResizeObserver = null;
let mutationObserver: MutationObserver | null = null;
let tabItemCount = 0;
const scrollbarRef = ref<ScrollbarInstance | null>(null);
const scrollbarRef = ref<null | ScrollbarInstance>(null);
const scrollViewportEl = ref<DomElement>(null);
const showScrollButton = ref(false);
const scrollIsAtLeft = ref(true);