Skip to content

Commit

Permalink
feat: 时间轴组件
Browse files Browse the repository at this point in the history
  • Loading branch information
yqllin committed Aug 10, 2023
1 parent 7f660ad commit d5f9987
Show file tree
Hide file tree
Showing 32 changed files with 1,531 additions and 3 deletions.
1 change: 1 addition & 0 deletions components/_style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ import './descriptions/style';
import './collapse/style';
import './radio-button/style';
import './card/style';
import './timeline/style';
8 changes: 5 additions & 3 deletions components/_util/use/useResize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,24 @@ import {
} from 'vue';
import { ResizeObserver } from '@juggle/resize-observer';

type ResizeObserverCallback = ConstructorParameters<typeof ResizeObserver>[0];

export default (
triggerRef: Ref<HTMLElement>,
callback?: () => void,
callback?: ResizeObserverCallback,
disabled?: boolean | Ref<boolean>,
immediate = true,
) => {
const disabledRef = computed(() => unref(disabled));
const handleResize = () => {
const handleResize: ResizeObserverCallback = (...params) => {
if (disabledRef.value) {
return;
}
if (!immediate) {
immediate = true;
return;
}
callback?.();
callback?.(...params);
};

const ro = new ResizeObserver(handleResize);
Expand Down
1 change: 1 addition & 0 deletions components/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ export * from './tooltip';
export * from './tree';
export * from './upload';
export * from './virtual-list';
export * from './timeline';
8 changes: 8 additions & 0 deletions components/timeline/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import getPrefixCls from '../_util/getPrefixCls';
import { TimelineNode } from './props';

export const COMPONENT_NAME = 'FTimeline';

export const prefixCls = getPrefixCls('timeline');

export const ICON_DEFAULT_COLOR = 'info' satisfies TimelineNode['icon'];
11 changes: 11 additions & 0 deletions components/timeline/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { withInstall } from '../_util/withInstall';
import Timeline from './timeline';
import type { SFCWithInstall } from '../_util/interface';

export { timelineProps } from './props';
export type { TimelineProps } from './props';

type TimelineType = SFCWithInstall<typeof Timeline>;
export const FTimeline = withInstall<TimelineType>(Timeline as TimelineType);

export default FTimeline;
103 changes: 103 additions & 0 deletions components/timeline/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {
CSSProperties,
ComponentObjectPropsOptions,
PropType,
SetupContext,
SlotsType,
VNodeChild,
} from 'vue';
import { ComponentInnerProps, ComponentProps } from './utilTypes';

/** 严格版本的 Extract */
type StrictExtract<Type, Union extends Type> = Extract<Type, Union>;

/** 时间轴的正方向,值同 flex 布局的 direction */
type TimelineDirection = 'column' | 'row' | 'row-reverse';

/**
* 时间轴结点中,「标题」相对「轴」的位置
*
* 视时间轴为 flex 布局中的主轴
* - start:表示交叉轴方向的 start 一侧
* - end:表示交叉轴方向的 end 一侧
* - alternate: 表示交替排列
*/
type TimelineTitlePosition = 'start' | 'end' | 'alternate';

/**
* 时间轴结点中,「辅助描述」相对「标题」的位置
*
* - under:在标题下方
* - inline:与标题同行
* - opposite:在标题对面(跨过时间轴)
*/
type TimelineDescPosition = 'under' | 'inline' | 'opposite';

/**
* 时间轴结点颜色
*
* - info: primary-color
* - success: success-color
* - warning: warning-color
* - error: danger-color
*
* ref: _theme/base.ts
*/
export type TimelineIconType = 'info' | 'success' | 'warning' | 'error';

type Color = CSSProperties['color'];
/**
* 时间轴结点插槽或渲染函数的共同参数
*
* - #desc
* - #icon
* */
export type TimelineNodeSlotCommonParams = { index: number };

/** 时间轴结点的参数 */
export type TimelineNode = {
title: string;
titlePosition?: StrictExtract<TimelineTitlePosition, 'start' | 'end'>;
desc?: string | ((params: TimelineNodeSlotCommonParams) => VNodeChild);
icon?:
| TimelineIconType
| Color
| ((params: TimelineNodeSlotCommonParams) => VNodeChild);
};

export const timelineProps = {
direction: {
type: String as PropType<TimelineDirection>,
default: 'column',
},
titlePosition: {
type: String as PropType<TimelineTitlePosition>,
default: 'end',
},
descPosition: {
type: String as PropType<TimelineDescPosition>,
default: 'under',
},
data: {
type: Array as PropType<TimelineNode[]>,
required: true,
},
titleClass: { type: String },
descClass: { type: String },
} as const satisfies ComponentObjectPropsOptions;

// 组件暴露给外部的 props 类型
export type TimelineProps = ComponentProps<typeof timelineProps>;

// 组件内部使用的 props 类型(包含了 default)
export type TimelineInnerProps = ComponentInnerProps<typeof timelineProps>;

export type TimelineSlots = {
desc: TimelineNodeSlotCommonParams;
icon: TimelineNodeSlotCommonParams;
};

export type TimelineUnboxSlots = SetupContext<
unknown,
SlotsType<TimelineSlots>
>['slots'];
Loading

0 comments on commit d5f9987

Please sign in to comment.