feat: add collapsible 组件,form表单增加单项可折叠,支持schema配置默认关闭/开启
feat: add collapsible 组件,form表单增加单项可折叠,支持schema配置默认关闭/开启 - shadcn-ui 增加 collapsible组件,collapsible-params组件 - form新增支持单项折叠 - collapsible-params组件在Form表单应用
This commit is contained in:
@@ -16,6 +16,7 @@ export {
|
||||
ChevronDown,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
ChevronsDown,
|
||||
ChevronsLeft,
|
||||
ChevronsRight,
|
||||
Circle,
|
||||
|
||||
@@ -30,10 +30,6 @@ const submitButtonOptions = computed(() => {
|
||||
};
|
||||
});
|
||||
|
||||
// const isQueryForm = computed(() => {
|
||||
// return !!unref(rootProps).showCollapseButton;
|
||||
// });
|
||||
|
||||
async function handleSubmit(e: Event) {
|
||||
e?.preventDefault();
|
||||
e?.stopPropagation();
|
||||
|
||||
@@ -7,15 +7,24 @@ import type {
|
||||
MaybeComponentProps,
|
||||
} from '../types';
|
||||
|
||||
import { computed, nextTick, onUnmounted, useTemplateRef, watch } from 'vue';
|
||||
|
||||
import { CircleAlert } from '@vben-core/icons';
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
onUnmounted,
|
||||
ref,
|
||||
useTemplateRef,
|
||||
watch,
|
||||
} from 'vue';
|
||||
|
||||
import { ChevronsDown, CircleAlert } from '@vben-core/icons';
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
FormDescription,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormMessage,
|
||||
VbenCollapsible,
|
||||
VbenRenderContent,
|
||||
VbenTooltip,
|
||||
} from '@vben-core/shadcn-ui';
|
||||
@@ -53,6 +62,8 @@ const {
|
||||
renderComponentContent,
|
||||
rules,
|
||||
help,
|
||||
collapsible,
|
||||
defaultCollapsed = false,
|
||||
} = defineProps<
|
||||
Props & {
|
||||
commonComponentProps: MaybeComponentProps;
|
||||
@@ -67,6 +78,7 @@ const fieldComponentRef = useTemplateRef<HTMLInputElement>('fieldComponentRef');
|
||||
const formApi = formRenderProps.form;
|
||||
const compact = computed(() => formRenderProps.compact);
|
||||
const isInValid = computed(() => errors.value?.length > 0);
|
||||
const collapseOpen = ref(!defaultCollapsed);
|
||||
|
||||
function getFormApi(): FormActions {
|
||||
if (!formApi) {
|
||||
@@ -296,6 +308,15 @@ function autofocus() {
|
||||
fieldComponentRef.value?.focus?.();
|
||||
}
|
||||
}
|
||||
|
||||
const shouldCollapsible = computed(() => {
|
||||
return collapsible; /* && isVertical.value; */
|
||||
});
|
||||
|
||||
function toggleCollapsed() {
|
||||
collapseOpen.value = !collapseOpen.value;
|
||||
}
|
||||
|
||||
const componentRefMap = injectComponentRefMap();
|
||||
watch(fieldComponentRef, (componentRef) => {
|
||||
componentRefMap?.set(fieldName, componentRef);
|
||||
@@ -335,6 +356,7 @@ onUnmounted(() => {
|
||||
{
|
||||
'mr-2 shrink-0 justify-end': !isVertical,
|
||||
'mb-1 flex-row': isVertical,
|
||||
'self-start': shouldCollapsible && !isVertical,
|
||||
},
|
||||
labelClass,
|
||||
)
|
||||
@@ -348,65 +370,87 @@ onUnmounted(() => {
|
||||
<template v-if="label">
|
||||
<VbenRenderContent :content="label" />
|
||||
</template>
|
||||
<template #extra>
|
||||
<Button
|
||||
class="ml-0.5"
|
||||
variant="icon"
|
||||
size="icon"
|
||||
@click.prevent="toggleCollapsed"
|
||||
v-if="shouldCollapsible"
|
||||
>
|
||||
<ChevronsDown
|
||||
:size="16"
|
||||
class="transition-transform"
|
||||
:class="{
|
||||
'rotate-180': !collapseOpen,
|
||||
}"
|
||||
/>
|
||||
</Button>
|
||||
</template>
|
||||
</FormLabel>
|
||||
<div class="flex-auto overflow-hidden p-px">
|
||||
<div :class="cn('relative flex w-full items-center', wrapperClass)">
|
||||
<FormControl :class="cn(controlClass)">
|
||||
<slot
|
||||
v-bind="{
|
||||
...slotProps,
|
||||
...createComponentProps(slotProps),
|
||||
disabled: shouldDisabled,
|
||||
isInValid,
|
||||
}"
|
||||
>
|
||||
<component
|
||||
:is="FieldComponent"
|
||||
ref="fieldComponentRef"
|
||||
:class="{
|
||||
'border-destructive hover:border-destructive/80 focus:border-destructive focus:shadow-[0_0_0_2px_rgba(255,38,5,0.06)]':
|
||||
<VbenCollapsible :show-trigger="false" v-model:open="collapseOpen">
|
||||
<template #collapsibleContent>
|
||||
<div :class="cn('relative flex w-full items-center', wrapperClass)">
|
||||
<FormControl :class="cn(controlClass)">
|
||||
<slot
|
||||
v-bind="{
|
||||
...slotProps,
|
||||
...createComponentProps(slotProps),
|
||||
disabled: shouldDisabled,
|
||||
isInValid,
|
||||
}"
|
||||
v-bind="createComponentProps(slotProps)"
|
||||
:disabled="shouldDisabled"
|
||||
>
|
||||
<template
|
||||
v-for="name in renderContentKey"
|
||||
:key="name"
|
||||
#[name]="renderSlotProps"
|
||||
}"
|
||||
>
|
||||
<VbenRenderContent
|
||||
:content="customContentRender[name]"
|
||||
v-bind="{ ...renderSlotProps, formContext: slotProps }"
|
||||
/>
|
||||
</template>
|
||||
<!-- <slot></slot> -->
|
||||
</component>
|
||||
<VbenTooltip
|
||||
v-if="compact && isInValid"
|
||||
:delay-duration="300"
|
||||
side="left"
|
||||
>
|
||||
<template #trigger>
|
||||
<slot name="trigger">
|
||||
<CircleAlert
|
||||
:class="
|
||||
cn(
|
||||
'inline-flex size-5 cursor-pointer text-foreground/80 hover:text-foreground',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<FormMessage />
|
||||
</VbenTooltip>
|
||||
</slot>
|
||||
</FormControl>
|
||||
<!-- 自定义后缀 -->
|
||||
<div v-if="suffix" class="ml-1">
|
||||
<VbenRenderContent :content="suffix" />
|
||||
</div>
|
||||
</div>
|
||||
<component
|
||||
:is="FieldComponent"
|
||||
ref="fieldComponentRef"
|
||||
:class="{
|
||||
'border-destructive hover:border-destructive/80 focus:border-destructive focus:shadow-[0_0_0_2px_rgba(255,38,5,0.06)]':
|
||||
isInValid,
|
||||
}"
|
||||
v-bind="createComponentProps(slotProps)"
|
||||
:disabled="shouldDisabled"
|
||||
>
|
||||
<template
|
||||
v-for="name in renderContentKey"
|
||||
:key="name"
|
||||
#[name]="renderSlotProps"
|
||||
>
|
||||
<VbenRenderContent
|
||||
:content="customContentRender[name]"
|
||||
v-bind="{ ...renderSlotProps, formContext: slotProps }"
|
||||
/>
|
||||
</template>
|
||||
<!-- <slot></slot> -->
|
||||
</component>
|
||||
<VbenTooltip
|
||||
v-if="compact && isInValid"
|
||||
:delay-duration="300"
|
||||
side="left"
|
||||
>
|
||||
<template #trigger>
|
||||
<slot name="trigger">
|
||||
<CircleAlert
|
||||
:class="
|
||||
cn(
|
||||
'inline-flex size-5 cursor-pointer text-foreground/80 hover:text-foreground',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<FormMessage />
|
||||
</VbenTooltip>
|
||||
</slot>
|
||||
</FormControl>
|
||||
<!-- 自定义后缀 -->
|
||||
<div v-if="suffix" class="ml-1">
|
||||
<VbenRenderContent :content="suffix" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</VbenCollapsible>
|
||||
|
||||
<FormDescription v-if="description" class="text-xs">
|
||||
<VbenRenderContent :content="description" />
|
||||
</FormDescription>
|
||||
|
||||
@@ -26,6 +26,7 @@ const props = defineProps<Props>();
|
||||
<VbenHelpTooltip v-if="help" trigger-class="size-3.5 ml-1">
|
||||
<VbenRenderContent :content="help" />
|
||||
</VbenHelpTooltip>
|
||||
<slot name="extra"></slot>
|
||||
<span v-if="colon && label" class="ml-0.5">:</span>
|
||||
</FormLabel>
|
||||
</template>
|
||||
|
||||
@@ -145,6 +145,10 @@ type ComponentProps =
|
||||
| MaybeComponentProps;
|
||||
|
||||
export interface FormCommonConfig {
|
||||
/**
|
||||
* 是否可折叠的
|
||||
*/
|
||||
collapsible?: boolean;
|
||||
/**
|
||||
* 在Label后显示一个冒号
|
||||
*/
|
||||
@@ -157,6 +161,11 @@ export interface FormCommonConfig {
|
||||
* 所有表单项的控件样式
|
||||
*/
|
||||
controlClass?: string;
|
||||
/**
|
||||
* 默认折叠
|
||||
* @default false
|
||||
*/
|
||||
defaultCollapsed?: boolean;
|
||||
/**
|
||||
* 所有表单项的禁用状态
|
||||
* @default false
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
<script setup lang="ts">
|
||||
import type { CollapsibleParamSchema } from './type';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { globalShareState } from '@vben-core/shared/global-state';
|
||||
|
||||
interface Props {
|
||||
data: CollapsibleParamSchema;
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const modelValue = defineModel('value');
|
||||
|
||||
const finalOption = computed(() => {
|
||||
const { type, ...otherOption } = props.data.option;
|
||||
|
||||
if (type === 'number') {
|
||||
return {
|
||||
step: props.data.option.step ?? 1,
|
||||
min: props.data.option.min,
|
||||
max: props.data.option.max,
|
||||
precision: props.data.option.precision ?? 0,
|
||||
};
|
||||
}
|
||||
|
||||
return otherOption;
|
||||
});
|
||||
|
||||
const components = globalShareState.getComponents();
|
||||
|
||||
const FieldComponent = computed(() => {
|
||||
switch (props.data.option.type) {
|
||||
case 'exponential':
|
||||
case 'number': {
|
||||
return components.InputNumber;
|
||||
}
|
||||
case 'select': {
|
||||
return components.Select;
|
||||
}
|
||||
case 'string': {
|
||||
return components.Input;
|
||||
}
|
||||
|
||||
default: {
|
||||
return components.InputNumber;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function reset() {
|
||||
modelValue.value = props.data.defaultValue;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
reset,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="body-row">
|
||||
<div class="body-cell">{{ data.key }}</div>
|
||||
<div class="body-cell">
|
||||
<div class="flex-auto w-full">
|
||||
<component
|
||||
:is="FieldComponent"
|
||||
v-bind="finalOption"
|
||||
v-model:value="modelValue"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center flex-none text-muted-foreground pl-2 gap-2">
|
||||
<span v-if="data.option.min && data.option.max">
|
||||
[{{ data.option.min }},{{ data.option.max }}]
|
||||
</span>
|
||||
<span v-if="data.option.step && data.option.step !== 1">
|
||||
step:{{ data.option.step }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body-cell w-full">
|
||||
<p
|
||||
class="line-clamp-2"
|
||||
v-tippy="{
|
||||
content: data.description,
|
||||
}"
|
||||
>
|
||||
{{ data.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="css" scoped>
|
||||
.body-row {
|
||||
&:not(:last-of-type) {
|
||||
@apply border-b;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,230 @@
|
||||
<script setup lang="ts">
|
||||
import type { CollapsibleParamSchema } from './type';
|
||||
|
||||
import { computed, nextTick, ref, useTemplateRef } from 'vue';
|
||||
|
||||
import { useNamespace } from '@vben-core/composables';
|
||||
|
||||
import { ChevronsDown } from 'lucide-vue-next';
|
||||
import {
|
||||
CollapsibleContent,
|
||||
CollapsibleRoot,
|
||||
CollapsibleTrigger,
|
||||
} from 'reka-ui';
|
||||
|
||||
import CollapsibleParamsItem from './collapsible-params-item.vue';
|
||||
|
||||
interface Props {
|
||||
defaultOpen?: boolean;
|
||||
maxHeight?: number | string;
|
||||
params: CollapsibleParamSchema[];
|
||||
visibleCount?: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
visibleCount: 3,
|
||||
defaultOpen: false,
|
||||
maxHeight: undefined,
|
||||
});
|
||||
|
||||
const emits = defineEmits<{ 'update:value': [any, string] }>();
|
||||
|
||||
const modelValue = defineModel('value');
|
||||
const visibleRefs = useTemplateRef('visibleRefs');
|
||||
const collapsibleRefs = useTemplateRef('collapsibleRefs');
|
||||
|
||||
const { b } = useNamespace('collapsible-params');
|
||||
|
||||
const open = ref(props.defaultOpen);
|
||||
|
||||
const visibleRows = computed(() => {
|
||||
return props.params.slice(0, props.visibleCount);
|
||||
});
|
||||
|
||||
const collapsibleRows = computed(() => {
|
||||
return props.params.slice(props.visibleCount);
|
||||
});
|
||||
|
||||
const bodyStyle = computed(() => {
|
||||
return {
|
||||
maxHeight:
|
||||
typeof props.maxHeight === 'number'
|
||||
? `${props.maxHeight}px`
|
||||
: props.maxHeight,
|
||||
};
|
||||
});
|
||||
|
||||
function init() {
|
||||
for (const param of props.params) {
|
||||
modelValue.value[param.key] = param.defaultValue ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleCollapsed() {
|
||||
open.value = !open.value;
|
||||
}
|
||||
|
||||
async function onParamValueChange(value: any, key: string) {
|
||||
await nextTick();
|
||||
emits('update:value', modelValue.value, key);
|
||||
}
|
||||
|
||||
function resetValue() {
|
||||
if (visibleRefs.value)
|
||||
for (const rowRef of visibleRefs.value) {
|
||||
rowRef.reset();
|
||||
}
|
||||
|
||||
if (collapsibleRefs.value)
|
||||
for (const rowRef of collapsibleRefs.value) {
|
||||
rowRef.reset();
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
defineExpose({
|
||||
toggleCollapsed,
|
||||
resetValue,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CollapsibleRoot v-model:open="open" :class="b()" :unmount-on-hide="false">
|
||||
<div class="wrapper">
|
||||
<div class="w-full min-w-fit">
|
||||
<div class="header">
|
||||
<div class="header-cell">参数名称</div>
|
||||
<div class="header-cell">配置</div>
|
||||
<div class="header-cell">说明</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="body"
|
||||
:class="[
|
||||
open && !!props.maxHeight ? 'overflow-y-auto' : 'overflow-y-hidden',
|
||||
]"
|
||||
:style="bodyStyle"
|
||||
>
|
||||
<CollapsibleParamsItem
|
||||
:data="row"
|
||||
v-for="row in visibleRows"
|
||||
:key="row.key"
|
||||
ref="visibleRefs"
|
||||
v-model:value="modelValue[row.key]"
|
||||
@update:value="(v) => onParamValueChange(v, row.key)"
|
||||
/>
|
||||
<CollapsibleContent
|
||||
class="data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up"
|
||||
>
|
||||
<CollapsibleParamsItem
|
||||
:data="row"
|
||||
v-for="row in collapsibleRows"
|
||||
:key="row.key"
|
||||
ref="collapsibleRefs"
|
||||
v-model:value="modelValue[row.key]"
|
||||
@update:value="(v) => onParamValueChange(v, row.key)"
|
||||
/>
|
||||
</CollapsibleContent>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gutter" v-if="!open && collapsibleRows.length > 0"></div>
|
||||
<div
|
||||
class="trigger-bar"
|
||||
:class="{
|
||||
collapsed: !open,
|
||||
}"
|
||||
v-if="collapsibleRows.length > 0"
|
||||
>
|
||||
<CollapsibleTrigger
|
||||
class="cursor-pointer h-[2rem] flex items-center gap-2"
|
||||
>
|
||||
<ChevronsDown
|
||||
class="transition-transform"
|
||||
:size="16"
|
||||
:class="{
|
||||
'rotate-180': open,
|
||||
}"
|
||||
/>
|
||||
{{ open ? '收起' : '展开' }}
|
||||
</CollapsibleTrigger>
|
||||
</div>
|
||||
</CollapsibleRoot>
|
||||
</template>
|
||||
<style lang="css">
|
||||
.vben-collapsible-params {
|
||||
@apply border rounded-[0.5rem] flex flex-col w-full overflow-hidden;
|
||||
|
||||
.wrapper {
|
||||
--column1: 11.25rem;
|
||||
--column2: 18.25rem;
|
||||
--column3: 27.5rem;
|
||||
|
||||
@apply w-full relative flex flex-col overflow-x-auto;
|
||||
|
||||
/* min-width: calc(var(--column1) + var(--column2) + var(--column3)); */
|
||||
|
||||
.header,
|
||||
.body {
|
||||
@apply w-full flex-none flex;
|
||||
}
|
||||
|
||||
.header {
|
||||
@apply bg-accent items-center rounded-t-[0.5rem] border-b;
|
||||
}
|
||||
|
||||
.body {
|
||||
@apply flex-col overflow-x-hidden;
|
||||
}
|
||||
|
||||
.body-row {
|
||||
@apply flex items-center w-full flex-nowrap;
|
||||
}
|
||||
|
||||
.header-cell,
|
||||
.body-cell {
|
||||
@apply py-2 px-5 leading-[1.5rem] flex items-center flex-nowrap;
|
||||
|
||||
&:nth-of-type(1) {
|
||||
flex: 0 0 var(--column1);
|
||||
|
||||
/* min-width: var(--column1); */
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
flex: 0 0 var(--column2);
|
||||
|
||||
/* min-width: var(--column2); */
|
||||
}
|
||||
|
||||
&:nth-of-type(3) {
|
||||
flex: 1 1 var(--column3);
|
||||
min-width: var(--column3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gutter {
|
||||
@apply h-[1.5rem];
|
||||
}
|
||||
|
||||
.trigger-bar {
|
||||
@apply flex min-h-[2rem] border-t px-5 py-1 rounded-b-[0.5rem] z-1;
|
||||
|
||||
&.collapsed {
|
||||
@apply absolute bottom-[1px] left-[1px] right-[1px] border-t-0 pt-6;
|
||||
|
||||
background-image: linear-gradient(
|
||||
hsl(var(--foreground) / 0%) 0%,
|
||||
hsl(var(--foreground) / 12%) 31.76%,
|
||||
var(--color-border) 31.76%,
|
||||
var(--color-border) 33.43%,
|
||||
var(--color-background) 31.76%
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
77
packages/@core/ui-kit/shadcn-ui/src/components/collapsible/collapsible.vue
Executable file
77
packages/@core/ui-kit/shadcn-ui/src/components/collapsible/collapsible.vue
Executable file
@@ -0,0 +1,77 @@
|
||||
<script setup lang="ts">
|
||||
import type { CollapsibleRootEmits, CollapsibleRootProps } from 'reka-ui';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { ChevronsDown } from 'lucide-vue-next';
|
||||
import {
|
||||
CollapsibleContent,
|
||||
CollapsibleRoot,
|
||||
CollapsibleTrigger,
|
||||
useForwardPropsEmits,
|
||||
} from 'reka-ui';
|
||||
|
||||
const props = defineProps<
|
||||
CollapsibleRootProps & {
|
||||
class?: ClassType;
|
||||
showTrigger?: boolean;
|
||||
}
|
||||
>();
|
||||
|
||||
const emits = defineEmits<CollapsibleRootEmits>();
|
||||
|
||||
const delegatedProps = computed(() => {
|
||||
const { class: _cls, ...delegated } = props;
|
||||
|
||||
return delegated;
|
||||
});
|
||||
|
||||
const forwarded = useForwardPropsEmits(delegatedProps, emits);
|
||||
|
||||
const open = defineModel('open', { default: true });
|
||||
|
||||
function toggle() {
|
||||
open.value = !open.value;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
toggle,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CollapsibleRoot
|
||||
v-bind="forwarded"
|
||||
v-model:open="open"
|
||||
class="flex flex-col"
|
||||
:unmount-on-hide="false"
|
||||
>
|
||||
<div
|
||||
class="flex items-center justify-between"
|
||||
v-if="$slots.label || showTrigger"
|
||||
>
|
||||
<slot name="label" v-if="$slots.label"> </slot>
|
||||
<CollapsibleTrigger
|
||||
v-if="showTrigger"
|
||||
class="cursor-pointer rounded-full h-[25px] w-[25px] inline-flex items-center justify-center outline-none data-[state=closed]:bg-white data-[state=open]:bg-primary/20 hover:bg-primary/20 text-primary"
|
||||
>
|
||||
<slot name="trigger" :open>
|
||||
<ChevronsDown
|
||||
class="h-3.5 w-3.5 transition-transform"
|
||||
:class="{
|
||||
'rotate-180': open,
|
||||
}"
|
||||
/>
|
||||
</slot>
|
||||
</CollapsibleTrigger>
|
||||
</div>
|
||||
|
||||
<slot name="visibleContent" :open></slot>
|
||||
|
||||
<CollapsibleContent
|
||||
class="data-[state=open]:animate-collapsible-down data-[state=closed]:animate-collapsible-up overflow-hidden justify-start"
|
||||
>
|
||||
<slot name="collapsibleContent" :open></slot>
|
||||
</CollapsibleContent>
|
||||
</CollapsibleRoot>
|
||||
</template>
|
||||
4
packages/@core/ui-kit/shadcn-ui/src/components/collapsible/index.ts
Executable file
4
packages/@core/ui-kit/shadcn-ui/src/components/collapsible/index.ts
Executable file
@@ -0,0 +1,4 @@
|
||||
export { default as VbenCollapsibleParams } from './collapsible-params.vue';
|
||||
export { default as VbenCollapsible } from './collapsible.vue';
|
||||
|
||||
export * from './type';
|
||||
@@ -0,0 +1,15 @@
|
||||
export interface CollapsibleParamOption {
|
||||
[key: string]: any;
|
||||
max?: number;
|
||||
min?: number;
|
||||
precision?: number;
|
||||
step?: number;
|
||||
type: 'exponential' | 'number' | 'select' | 'string';
|
||||
}
|
||||
|
||||
export interface CollapsibleParamSchema {
|
||||
defaultValue: number | number[] | string | string[];
|
||||
description: string;
|
||||
key: string;
|
||||
option: CollapsibleParamOption;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ export * from './back-top';
|
||||
export * from './breadcrumb';
|
||||
export * from './button';
|
||||
export * from './checkbox';
|
||||
export * from './collapsible';
|
||||
export * from './context-menu';
|
||||
export * from './count-to-animator';
|
||||
export * from './dropdown-menu';
|
||||
|
||||
Reference in New Issue
Block a user