refactor: table
parent
b8319bdb38
commit
c9db47533f
|
@ -0,0 +1,14 @@
|
||||||
|
import type { UnwrapRef } from 'vue';
|
||||||
|
import { reactive, toRef } from 'vue';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reactively pick fields from a reactive object
|
||||||
|
*
|
||||||
|
* @see https://vueuse.js.org/reactivePick
|
||||||
|
*/
|
||||||
|
export function reactivePick<T extends object, K extends keyof T>(
|
||||||
|
obj: T,
|
||||||
|
...keys: K[]
|
||||||
|
): { [S in K]: UnwrapRef<T[S]> } {
|
||||||
|
return reactive(Object.fromEntries(keys.map(k => [k, toRef(obj, k)]))) as any;
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
import classNames from 'ant-design-vue/es/_util/classNames';
|
||||||
|
import { isValidElement } from 'ant-design-vue/es/_util/props-util';
|
||||||
|
import { CSSProperties, defineComponent, HTMLAttributes } from 'vue';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
DataIndex,
|
||||||
|
ColumnType,
|
||||||
|
RenderedCell,
|
||||||
|
CustomizeComponent,
|
||||||
|
CellType,
|
||||||
|
DefaultRecordType,
|
||||||
|
AlignType,
|
||||||
|
CellEllipsisType,
|
||||||
|
} from '../interface';
|
||||||
|
import { getPathValue, validateValue } from '../utils/valueUtil';
|
||||||
|
|
||||||
|
function isRenderCell<RecordType = DefaultRecordType>(
|
||||||
|
data: RenderedCell<RecordType>,
|
||||||
|
): data is RenderedCell<RecordType> {
|
||||||
|
return data && typeof data === 'object' && !Array.isArray(data) && !isValidElement(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CellProps<RecordType = DefaultRecordType> {
|
||||||
|
prefixCls?: string;
|
||||||
|
className?: string;
|
||||||
|
record?: RecordType;
|
||||||
|
/** `record` index. Not `column` index. */
|
||||||
|
index?: number;
|
||||||
|
dataIndex?: DataIndex;
|
||||||
|
customRender?: ColumnType<RecordType>['customRender'];
|
||||||
|
component?: CustomizeComponent;
|
||||||
|
children?: any;
|
||||||
|
colSpan?: number;
|
||||||
|
rowSpan?: number;
|
||||||
|
ellipsis?: CellEllipsisType;
|
||||||
|
align?: AlignType;
|
||||||
|
|
||||||
|
// Fixed
|
||||||
|
fixLeft?: number | false;
|
||||||
|
fixRight?: number | false;
|
||||||
|
firstFixLeft?: boolean;
|
||||||
|
lastFixLeft?: boolean;
|
||||||
|
firstFixRight?: boolean;
|
||||||
|
lastFixRight?: boolean;
|
||||||
|
|
||||||
|
// Additional
|
||||||
|
/** @private Used for `expandable` with nest tree */
|
||||||
|
appendNode?: any;
|
||||||
|
additionalProps?: Omit<HTMLAttributes, 'style'> & { style?: CSSProperties };
|
||||||
|
|
||||||
|
rowType?: 'header' | 'body' | 'footer';
|
||||||
|
|
||||||
|
isSticky?: boolean;
|
||||||
|
|
||||||
|
column?: ColumnType<RecordType>;
|
||||||
|
}
|
||||||
|
export default defineComponent<CellProps>({
|
||||||
|
name: 'Cell',
|
||||||
|
props: [] as any,
|
||||||
|
slots: ['appendNode'],
|
||||||
|
setup(props) {
|
||||||
|
return () => {
|
||||||
|
const {
|
||||||
|
prefixCls,
|
||||||
|
className,
|
||||||
|
record,
|
||||||
|
index,
|
||||||
|
dataIndex,
|
||||||
|
customRender,
|
||||||
|
children,
|
||||||
|
component: Component = 'td',
|
||||||
|
colSpan,
|
||||||
|
rowSpan,
|
||||||
|
fixLeft,
|
||||||
|
fixRight,
|
||||||
|
firstFixLeft,
|
||||||
|
lastFixLeft,
|
||||||
|
firstFixRight,
|
||||||
|
lastFixRight,
|
||||||
|
appendNode,
|
||||||
|
additionalProps = {},
|
||||||
|
ellipsis,
|
||||||
|
align,
|
||||||
|
rowType,
|
||||||
|
isSticky,
|
||||||
|
column,
|
||||||
|
} = props;
|
||||||
|
const cellPrefixCls = `${prefixCls}-cell`;
|
||||||
|
|
||||||
|
// ==================== Child Node ====================
|
||||||
|
let cellProps: CellType;
|
||||||
|
let childNode;
|
||||||
|
|
||||||
|
if (validateValue(children)) {
|
||||||
|
childNode = children;
|
||||||
|
} else {
|
||||||
|
const value = getPathValue(record, dataIndex);
|
||||||
|
|
||||||
|
// Customize render node
|
||||||
|
childNode = value;
|
||||||
|
if (customRender) {
|
||||||
|
const renderData = customRender({ text: value, value, record, index, column });
|
||||||
|
|
||||||
|
if (isRenderCell(renderData)) {
|
||||||
|
childNode = renderData.children;
|
||||||
|
cellProps = renderData.props;
|
||||||
|
} else {
|
||||||
|
childNode = renderData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not crash if final `childNode` is not validate ReactNode
|
||||||
|
if (
|
||||||
|
typeof childNode === 'object' &&
|
||||||
|
!Array.isArray(childNode) &&
|
||||||
|
!isValidElement(childNode)
|
||||||
|
) {
|
||||||
|
childNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ellipsis && (lastFixLeft || firstFixRight)) {
|
||||||
|
childNode = <span class={`${cellPrefixCls}-content`}>{childNode}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const {
|
||||||
|
colSpan: cellColSpan,
|
||||||
|
rowSpan: cellRowSpan,
|
||||||
|
style: cellStyle,
|
||||||
|
className: cellClassName,
|
||||||
|
class: cellClass,
|
||||||
|
...restCellProps
|
||||||
|
} = cellProps || {};
|
||||||
|
const mergedColSpan = cellColSpan !== undefined ? cellColSpan : colSpan;
|
||||||
|
const mergedRowSpan = cellRowSpan !== undefined ? cellRowSpan : rowSpan;
|
||||||
|
|
||||||
|
if (mergedColSpan === 0 || mergedRowSpan === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== Fixed =======================
|
||||||
|
const fixedStyle: CSSProperties = {};
|
||||||
|
const isFixLeft = typeof fixLeft === 'number';
|
||||||
|
const isFixRight = typeof fixRight === 'number';
|
||||||
|
|
||||||
|
if (isFixLeft) {
|
||||||
|
fixedStyle.position = 'sticky';
|
||||||
|
fixedStyle.left = `${fixLeft}px`;
|
||||||
|
}
|
||||||
|
if (isFixRight) {
|
||||||
|
fixedStyle.position = 'sticky';
|
||||||
|
|
||||||
|
fixedStyle.right = `${fixRight}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== Align =======================
|
||||||
|
const alignStyle: CSSProperties = {};
|
||||||
|
if (align) {
|
||||||
|
alignStyle.textAlign = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================== Render ======================
|
||||||
|
let title: string;
|
||||||
|
const ellipsisConfig: CellEllipsisType = ellipsis === true ? { showTitle: true } : ellipsis;
|
||||||
|
if (ellipsisConfig && (ellipsisConfig.showTitle || rowType === 'header')) {
|
||||||
|
debugger;
|
||||||
|
if (typeof childNode === 'string' || typeof childNode === 'number') {
|
||||||
|
title = childNode.toString();
|
||||||
|
} else if (isValidElement(childNode) && typeof childNode.props.children === 'string') {
|
||||||
|
title = childNode.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const componentProps = {
|
||||||
|
title,
|
||||||
|
...restCellProps,
|
||||||
|
...additionalProps,
|
||||||
|
colSpan: mergedColSpan && mergedColSpan !== 1 ? mergedColSpan : null,
|
||||||
|
rowSpan: mergedRowSpan && mergedRowSpan !== 1 ? mergedRowSpan : null,
|
||||||
|
class: classNames(
|
||||||
|
cellPrefixCls,
|
||||||
|
className,
|
||||||
|
{
|
||||||
|
[`${cellPrefixCls}-fix-left`]: isFixLeft,
|
||||||
|
[`${cellPrefixCls}-fix-left-first`]: firstFixLeft,
|
||||||
|
[`${cellPrefixCls}-fix-left-last`]: lastFixLeft,
|
||||||
|
[`${cellPrefixCls}-fix-right`]: isFixRight,
|
||||||
|
[`${cellPrefixCls}-fix-right-first`]: firstFixRight,
|
||||||
|
[`${cellPrefixCls}-fix-right-last`]: lastFixRight,
|
||||||
|
[`${cellPrefixCls}-ellipsis`]: ellipsis,
|
||||||
|
[`${cellPrefixCls}-with-append`]: appendNode,
|
||||||
|
[`${cellPrefixCls}-fix-sticky`]: (isFixLeft || isFixRight) && isSticky,
|
||||||
|
},
|
||||||
|
additionalProps.class,
|
||||||
|
cellClassName,
|
||||||
|
cellClass,
|
||||||
|
),
|
||||||
|
style: {
|
||||||
|
...additionalProps.style,
|
||||||
|
...alignStyle,
|
||||||
|
...fixedStyle,
|
||||||
|
...cellStyle,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Component {...componentProps}>
|
||||||
|
{appendNode}
|
||||||
|
{childNode}
|
||||||
|
</Component>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,37 @@
|
||||||
|
import type { ColumnType } from './interface';
|
||||||
|
import { INTERNAL_COL_DEFINE } from './utils/legacyUtil';
|
||||||
|
|
||||||
|
export interface ColGroupProps<RecordType> {
|
||||||
|
colWidths: readonly (number | string)[];
|
||||||
|
columns?: readonly ColumnType<RecordType>[];
|
||||||
|
columCount?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ColGroup<RecordType>({ colWidths, columns, columCount }: ColGroupProps<RecordType>) {
|
||||||
|
const cols = [];
|
||||||
|
const len = columCount || columns.length;
|
||||||
|
|
||||||
|
// Only insert col with width & additional props
|
||||||
|
// Skip if rest col do not have any useful info
|
||||||
|
let mustInsert = false;
|
||||||
|
for (let i = len - 1; i >= 0; i -= 1) {
|
||||||
|
const width = colWidths[i];
|
||||||
|
const column = columns && columns[i];
|
||||||
|
const additionalProps = column && column[INTERNAL_COL_DEFINE];
|
||||||
|
|
||||||
|
if (width || additionalProps || mustInsert) {
|
||||||
|
cols.unshift(
|
||||||
|
<col
|
||||||
|
key={i}
|
||||||
|
style={{ width: typeof width === 'number' ? `${width}px` : width }}
|
||||||
|
{...additionalProps}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
mustInsert = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <colgroup>{cols}</colgroup>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ColGroup;
|
|
@ -0,0 +1,127 @@
|
||||||
|
import classNames from 'ant-design-vue/es/_util/classNames';
|
||||||
|
import { computed, defineComponent } from 'vue';
|
||||||
|
import { useInjectTable } from '../context/TableContext';
|
||||||
|
import type {
|
||||||
|
ColumnsType,
|
||||||
|
CellType,
|
||||||
|
StickyOffsets,
|
||||||
|
ColumnType,
|
||||||
|
GetComponentProps,
|
||||||
|
ColumnGroupType,
|
||||||
|
DefaultRecordType,
|
||||||
|
} from '../interface';
|
||||||
|
import HeaderRow from './HeaderRow';
|
||||||
|
|
||||||
|
function parseHeaderRows<RecordType>(
|
||||||
|
rootColumns: ColumnsType<RecordType>,
|
||||||
|
): CellType<RecordType>[][] {
|
||||||
|
const rows: CellType<RecordType>[][] = [];
|
||||||
|
|
||||||
|
function fillRowCells(
|
||||||
|
columns: ColumnsType<RecordType>,
|
||||||
|
colIndex: number,
|
||||||
|
rowIndex: number = 0,
|
||||||
|
): number[] {
|
||||||
|
// Init rows
|
||||||
|
rows[rowIndex] = rows[rowIndex] || [];
|
||||||
|
|
||||||
|
let currentColIndex = colIndex;
|
||||||
|
const colSpans: number[] = columns.filter(Boolean).map(column => {
|
||||||
|
const cell: CellType<RecordType> = {
|
||||||
|
key: column.key,
|
||||||
|
className: classNames(column.className, column.class),
|
||||||
|
children: column.title,
|
||||||
|
column,
|
||||||
|
colStart: currentColIndex,
|
||||||
|
};
|
||||||
|
|
||||||
|
let colSpan: number = 1;
|
||||||
|
|
||||||
|
const subColumns = (column as ColumnGroupType<RecordType>).children;
|
||||||
|
if (subColumns && subColumns.length > 0) {
|
||||||
|
colSpan = fillRowCells(subColumns, currentColIndex, rowIndex + 1).reduce(
|
||||||
|
(total, count) => total + count,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
cell.hasSubColumns = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('colSpan' in column) {
|
||||||
|
({ colSpan } = column);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('rowSpan' in column) {
|
||||||
|
cell.rowSpan = column.rowSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.colSpan = colSpan;
|
||||||
|
cell.colEnd = cell.colStart + colSpan - 1;
|
||||||
|
rows[rowIndex].push(cell);
|
||||||
|
|
||||||
|
currentColIndex += colSpan;
|
||||||
|
|
||||||
|
return colSpan;
|
||||||
|
});
|
||||||
|
|
||||||
|
return colSpans;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate `rows` cell data
|
||||||
|
fillRowCells(rootColumns, 0);
|
||||||
|
|
||||||
|
// Handle `rowSpan`
|
||||||
|
const rowCount = rows.length;
|
||||||
|
for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
|
||||||
|
rows[rowIndex].forEach(cell => {
|
||||||
|
if (!('rowSpan' in cell) && !cell.hasSubColumns) {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
cell.rowSpan = rowCount - rowIndex;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HeaderProps<RecordType = DefaultRecordType> {
|
||||||
|
columns: ColumnsType<RecordType>;
|
||||||
|
flattenColumns: readonly ColumnType<RecordType>[];
|
||||||
|
stickyOffsets: StickyOffsets;
|
||||||
|
onHeaderRow: GetComponentProps<readonly ColumnType<RecordType>[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent<HeaderProps>({
|
||||||
|
name: 'Header',
|
||||||
|
props: ['columns', 'flattenColumns', 'stickyOffsets', 'onHeaderRow'] as any,
|
||||||
|
setup(props) {
|
||||||
|
const tableContext = useInjectTable();
|
||||||
|
const rows = computed(() => parseHeaderRows(props.columns));
|
||||||
|
return () => {
|
||||||
|
const { prefixCls, getComponent } = tableContext;
|
||||||
|
const { stickyOffsets, flattenColumns, onHeaderRow } = props;
|
||||||
|
const WrapperComponent = getComponent(['header', 'wrapper'], 'thead');
|
||||||
|
const trComponent = getComponent(['header', 'row'], 'tr');
|
||||||
|
const thComponent = getComponent(['header', 'cell'], 'th');
|
||||||
|
return (
|
||||||
|
<WrapperComponent class={`${prefixCls}-thead`}>
|
||||||
|
{rows.value.map((row, rowIndex) => {
|
||||||
|
const rowNode = (
|
||||||
|
<HeaderRow
|
||||||
|
key={rowIndex}
|
||||||
|
flattenColumns={flattenColumns}
|
||||||
|
cells={row}
|
||||||
|
stickyOffsets={stickyOffsets}
|
||||||
|
rowComponent={trComponent}
|
||||||
|
cellComponent={thComponent}
|
||||||
|
onHeaderRow={onHeaderRow}
|
||||||
|
index={rowIndex}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
return rowNode;
|
||||||
|
})}
|
||||||
|
</WrapperComponent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,96 @@
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import Cell from '../Cell';
|
||||||
|
import { useInjectTable } from '../context/TableContext';
|
||||||
|
import {
|
||||||
|
CellType,
|
||||||
|
StickyOffsets,
|
||||||
|
ColumnType,
|
||||||
|
CustomizeComponent,
|
||||||
|
GetComponentProps,
|
||||||
|
DefaultRecordType,
|
||||||
|
} from '../interface';
|
||||||
|
import { getCellFixedInfo } from '../utils/fixUtil';
|
||||||
|
import { getColumnsKey } from '../utils/valueUtil';
|
||||||
|
|
||||||
|
export interface RowProps<RecordType = DefaultRecordType> {
|
||||||
|
cells: readonly CellType<RecordType>[];
|
||||||
|
stickyOffsets: StickyOffsets;
|
||||||
|
flattenColumns: readonly ColumnType<RecordType>[];
|
||||||
|
rowComponent: CustomizeComponent;
|
||||||
|
cellComponent: CustomizeComponent;
|
||||||
|
onHeaderRow: GetComponentProps<readonly ColumnType<RecordType>[]>;
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent<RowProps>({
|
||||||
|
name: 'HeaderRow',
|
||||||
|
props: [
|
||||||
|
'cells',
|
||||||
|
'stickyOffsets',
|
||||||
|
'flattenColumns',
|
||||||
|
'rowComponent',
|
||||||
|
'cellComponent',
|
||||||
|
'index',
|
||||||
|
'onHeaderRow',
|
||||||
|
] as any,
|
||||||
|
setup(props: RowProps) {
|
||||||
|
const tableContext = useInjectTable();
|
||||||
|
return () => {
|
||||||
|
const { prefixCls, direction } = tableContext;
|
||||||
|
const {
|
||||||
|
cells,
|
||||||
|
stickyOffsets,
|
||||||
|
flattenColumns,
|
||||||
|
rowComponent: RowComponent,
|
||||||
|
cellComponent: CellComponent,
|
||||||
|
onHeaderRow,
|
||||||
|
index,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
let rowProps;
|
||||||
|
if (onHeaderRow) {
|
||||||
|
rowProps = onHeaderRow(
|
||||||
|
cells.map(cell => cell.column),
|
||||||
|
index,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnsKey = getColumnsKey(cells.map(cell => cell.column));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RowComponent {...rowProps}>
|
||||||
|
{cells.map((cell: CellType, cellIndex) => {
|
||||||
|
const { column } = cell;
|
||||||
|
const fixedInfo = getCellFixedInfo(
|
||||||
|
cell.colStart,
|
||||||
|
cell.colEnd,
|
||||||
|
flattenColumns,
|
||||||
|
stickyOffsets,
|
||||||
|
direction,
|
||||||
|
);
|
||||||
|
|
||||||
|
let additionalProps;
|
||||||
|
if (column && column.onHeaderCell) {
|
||||||
|
additionalProps = cell.column.onHeaderCell(column);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Cell
|
||||||
|
{...cell}
|
||||||
|
ellipsis={column.ellipsis}
|
||||||
|
align={column.align}
|
||||||
|
component={CellComponent}
|
||||||
|
prefixCls={prefixCls}
|
||||||
|
key={columnsKey[cellIndex]}
|
||||||
|
{...fixedInfo}
|
||||||
|
additionalProps={additionalProps}
|
||||||
|
rowType="header"
|
||||||
|
column={column}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</RowComponent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
function Panel(_, { slots }) {
|
||||||
|
return <div>{slots.default?.()}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
Panel.displayName = 'Panel';
|
||||||
|
|
||||||
|
export default Panel;
|
|
@ -0,0 +1,43 @@
|
||||||
|
import {
|
||||||
|
ColumnType,
|
||||||
|
DefaultRecordType,
|
||||||
|
ColumnsType,
|
||||||
|
TableLayout,
|
||||||
|
RenderExpandIcon,
|
||||||
|
ExpandableType,
|
||||||
|
RowClassName,
|
||||||
|
TriggerEventHandler,
|
||||||
|
ExpandedRowRender,
|
||||||
|
} from '../interface';
|
||||||
|
import { inject, InjectionKey, provide } from 'vue';
|
||||||
|
|
||||||
|
export interface BodyContextProps<RecordType = DefaultRecordType> {
|
||||||
|
rowClassName: string | RowClassName<RecordType>;
|
||||||
|
expandedRowClassName: RowClassName<RecordType>;
|
||||||
|
|
||||||
|
columns: ColumnsType<RecordType>;
|
||||||
|
flattenColumns: readonly ColumnType<RecordType>[];
|
||||||
|
|
||||||
|
componentWidth: number;
|
||||||
|
tableLayout: TableLayout;
|
||||||
|
fixHeader: boolean;
|
||||||
|
fixColumn: boolean;
|
||||||
|
horizonScroll: boolean;
|
||||||
|
|
||||||
|
indentSize: number;
|
||||||
|
expandableType: ExpandableType;
|
||||||
|
expandRowByClick: boolean;
|
||||||
|
expandedRowRender: ExpandedRowRender<RecordType>;
|
||||||
|
expandIcon: RenderExpandIcon<RecordType>;
|
||||||
|
onTriggerExpand: TriggerEventHandler<RecordType>;
|
||||||
|
expandIconColumnIndex: number;
|
||||||
|
}
|
||||||
|
export const BodyContextKey: InjectionKey<BodyContextProps> = Symbol('BodyContextProps');
|
||||||
|
|
||||||
|
export const useProvideBody = (props: BodyContextProps) => {
|
||||||
|
provide(BodyContextKey, props);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useInjectBody = () => {
|
||||||
|
return inject(BodyContextKey, {} as BodyContextProps);
|
||||||
|
};
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { inject, InjectionKey, provide } from 'vue';
|
||||||
|
import { Key } from '../interface';
|
||||||
|
|
||||||
|
interface ResizeContextProps {
|
||||||
|
onColumnResize: (columnKey: Key, width: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ResizeContextKey: InjectionKey<ResizeContextProps> = Symbol('ResizeContextProps');
|
||||||
|
|
||||||
|
export const useProvideResize = (props: ResizeContextProps) => {
|
||||||
|
provide(ResizeContextKey, props);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useInjectResize = () => {
|
||||||
|
return inject(ResizeContextKey, { onColumnResize: () => {} });
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { inject, InjectionKey, provide } from 'vue';
|
||||||
|
import { GetComponent } from '../interface';
|
||||||
|
import { FixedInfo } from '../utils/fixUtil';
|
||||||
|
|
||||||
|
export interface TableContextProps {
|
||||||
|
// Table context
|
||||||
|
prefixCls: string;
|
||||||
|
|
||||||
|
getComponent: GetComponent;
|
||||||
|
|
||||||
|
scrollbarSize: number;
|
||||||
|
|
||||||
|
direction: 'ltr' | 'rtl';
|
||||||
|
|
||||||
|
fixedInfoList: readonly FixedInfo[];
|
||||||
|
|
||||||
|
isSticky: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BodyContextKey: InjectionKey<TableContextProps> = Symbol('TableContextProps');
|
||||||
|
|
||||||
|
export const useProvideTable = (props: TableContextProps) => {
|
||||||
|
provide(BodyContextKey, props);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useInjectTable = () => {
|
||||||
|
return inject(BodyContextKey, {} as TableContextProps);
|
||||||
|
};
|
|
@ -0,0 +1,238 @@
|
||||||
|
import { warning } from 'ant-design-vue/es/vc-util/warning';
|
||||||
|
import { computed, ComputedRef, Ref, watchEffect } from 'vue';
|
||||||
|
import type {
|
||||||
|
ColumnsType,
|
||||||
|
ColumnType,
|
||||||
|
FixedType,
|
||||||
|
Key,
|
||||||
|
GetRowKey,
|
||||||
|
TriggerEventHandler,
|
||||||
|
RenderExpandIcon,
|
||||||
|
ColumnGroupType,
|
||||||
|
} from '../interface';
|
||||||
|
import { INTERNAL_COL_DEFINE } from '../utils/legacyUtil';
|
||||||
|
|
||||||
|
export function convertChildrenToColumns<RecordType>(
|
||||||
|
children: any[] = [],
|
||||||
|
): ColumnsType<RecordType> {
|
||||||
|
return children.map(({ key, props }) => {
|
||||||
|
const { children: nodeChildren, ...restProps } = props;
|
||||||
|
const column = {
|
||||||
|
key,
|
||||||
|
...restProps,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (nodeChildren) {
|
||||||
|
column.children = convertChildrenToColumns(nodeChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
return column;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function flatColumns<RecordType>(columns: ColumnsType<RecordType>): ColumnType<RecordType>[] {
|
||||||
|
return columns.reduce((list, column) => {
|
||||||
|
const { fixed } = column;
|
||||||
|
|
||||||
|
// Convert `fixed='true'` to `fixed='left'` instead
|
||||||
|
const parsedFixed = fixed === true ? 'left' : fixed;
|
||||||
|
|
||||||
|
const subColumns = (column as ColumnGroupType<RecordType>).children;
|
||||||
|
if (subColumns && subColumns.length > 0) {
|
||||||
|
return [
|
||||||
|
...list,
|
||||||
|
...flatColumns(subColumns).map(subColum => ({
|
||||||
|
fixed: parsedFixed,
|
||||||
|
...subColum,
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
...list,
|
||||||
|
{
|
||||||
|
...column,
|
||||||
|
fixed: parsedFixed,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function warningFixed(flattenColumns: readonly { fixed?: FixedType }[]) {
|
||||||
|
let allFixLeft = true;
|
||||||
|
for (let i = 0; i < flattenColumns.length; i += 1) {
|
||||||
|
const col = flattenColumns[i];
|
||||||
|
if (allFixLeft && col.fixed !== 'left') {
|
||||||
|
allFixLeft = false;
|
||||||
|
} else if (!allFixLeft && col.fixed === 'left') {
|
||||||
|
warning(false, `Index ${i - 1} of \`columns\` missing \`fixed='left'\` prop.`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let allFixRight = true;
|
||||||
|
for (let i = flattenColumns.length - 1; i >= 0; i -= 1) {
|
||||||
|
const col = flattenColumns[i];
|
||||||
|
if (allFixRight && col.fixed !== 'right') {
|
||||||
|
allFixRight = false;
|
||||||
|
} else if (!allFixRight && col.fixed === 'right') {
|
||||||
|
warning(false, `Index ${i + 1} of \`columns\` missing \`fixed='right'\` prop.`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function revertForRtl<RecordType>(columns: ColumnsType<RecordType>): ColumnsType<RecordType> {
|
||||||
|
return columns.map(column => {
|
||||||
|
const { fixed, ...restProps } = column;
|
||||||
|
|
||||||
|
// Convert `fixed='left'` to `fixed='right'` instead
|
||||||
|
let parsedFixed = fixed;
|
||||||
|
if (fixed === 'left') {
|
||||||
|
parsedFixed = 'right';
|
||||||
|
} else if (fixed === 'right') {
|
||||||
|
parsedFixed = 'left';
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
fixed: parsedFixed,
|
||||||
|
...restProps,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse `columns` & `children` into `columns`.
|
||||||
|
*/
|
||||||
|
function useColumns<RecordType>(
|
||||||
|
{
|
||||||
|
prefixCls,
|
||||||
|
columns: baseColumns,
|
||||||
|
// children,
|
||||||
|
expandable,
|
||||||
|
expandedKeys,
|
||||||
|
getRowKey,
|
||||||
|
onTriggerExpand,
|
||||||
|
expandIcon,
|
||||||
|
rowExpandable,
|
||||||
|
expandIconColumnIndex,
|
||||||
|
direction,
|
||||||
|
expandRowByClick,
|
||||||
|
columnWidth,
|
||||||
|
fixed,
|
||||||
|
}: {
|
||||||
|
prefixCls?: Ref<string>;
|
||||||
|
columns?: Ref<ColumnsType<RecordType>>;
|
||||||
|
// children?: React.ReactNode;
|
||||||
|
expandable: Ref<boolean>;
|
||||||
|
expandedKeys: Ref<Set<Key>>;
|
||||||
|
getRowKey: GetRowKey<RecordType>;
|
||||||
|
onTriggerExpand: TriggerEventHandler<RecordType>;
|
||||||
|
expandIcon?: Ref<RenderExpandIcon<RecordType>>;
|
||||||
|
rowExpandable?: Ref<(record: RecordType) => boolean>;
|
||||||
|
expandIconColumnIndex?: Ref<number>;
|
||||||
|
direction?: Ref<'ltr' | 'rtl'>;
|
||||||
|
expandRowByClick?: Ref<boolean>;
|
||||||
|
columnWidth?: Ref<number | string>;
|
||||||
|
fixed?: Ref<FixedType>;
|
||||||
|
},
|
||||||
|
transformColumns: (columns: ColumnsType<RecordType>) => ColumnsType<RecordType>,
|
||||||
|
): [ComputedRef<ColumnsType<RecordType>>, ComputedRef<readonly ColumnType<RecordType>[]>] {
|
||||||
|
// const baseColumns = React.useMemo<ColumnsType<RecordType>>(
|
||||||
|
// () => columns || convertChildrenToColumns(children),
|
||||||
|
// [columns, children],
|
||||||
|
// );
|
||||||
|
|
||||||
|
// Add expand column
|
||||||
|
const withExpandColumns = computed<ColumnsType<RecordType>>(() => {
|
||||||
|
if (expandable.value) {
|
||||||
|
const expandColIndex = expandIconColumnIndex.value || 0;
|
||||||
|
const prevColumn = baseColumns[expandColIndex];
|
||||||
|
|
||||||
|
let fixedColumn: FixedType | null;
|
||||||
|
if ((fixed.value === 'left' || fixed.value) && !expandIconColumnIndex.value) {
|
||||||
|
fixedColumn = 'left';
|
||||||
|
} else if (
|
||||||
|
(fixed.value === 'right' || fixed.value) &&
|
||||||
|
expandIconColumnIndex.value === baseColumns.value.length
|
||||||
|
) {
|
||||||
|
fixedColumn = 'right';
|
||||||
|
} else {
|
||||||
|
fixedColumn = prevColumn ? prevColumn.fixed : null;
|
||||||
|
}
|
||||||
|
const expandedKeysValue = expandedKeys.value;
|
||||||
|
const rowExpandableValue = rowExpandable.value;
|
||||||
|
const expandIconValue = expandIcon.value;
|
||||||
|
const prefixClsValue = prefixCls.value;
|
||||||
|
const expandRowByClickValue = expandRowByClick.value;
|
||||||
|
const expandColumn = {
|
||||||
|
[INTERNAL_COL_DEFINE]: {
|
||||||
|
class: `${prefixCls.value}-expand-icon-col`,
|
||||||
|
},
|
||||||
|
title: '',
|
||||||
|
fixed: fixedColumn,
|
||||||
|
class: `${prefixCls.value}-row-expand-icon-cell`,
|
||||||
|
width: columnWidth.value,
|
||||||
|
render: (_, record, index) => {
|
||||||
|
const rowKey = getRowKey(record, index);
|
||||||
|
const expanded = expandedKeysValue.has(rowKey);
|
||||||
|
const recordExpandable = rowExpandableValue ? rowExpandableValue(record) : true;
|
||||||
|
|
||||||
|
const icon = expandIconValue({
|
||||||
|
prefixCls: prefixClsValue,
|
||||||
|
expanded,
|
||||||
|
expandable: recordExpandable,
|
||||||
|
record,
|
||||||
|
onExpand: onTriggerExpand,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (expandRowByClickValue) {
|
||||||
|
return <span onClick={e => e.stopPropagation()}>{icon}</span>;
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Insert expand column in the target position
|
||||||
|
const cloneColumns = baseColumns.value.slice();
|
||||||
|
if (expandColIndex >= 0) {
|
||||||
|
cloneColumns.splice(expandColIndex, 0, expandColumn);
|
||||||
|
}
|
||||||
|
return cloneColumns;
|
||||||
|
}
|
||||||
|
return baseColumns.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const mergedColumns = computed(() => {
|
||||||
|
let finalColumns = withExpandColumns.value;
|
||||||
|
if (transformColumns) {
|
||||||
|
finalColumns = transformColumns(finalColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always provides at least one column for table display
|
||||||
|
if (!finalColumns.length) {
|
||||||
|
finalColumns = [
|
||||||
|
{
|
||||||
|
customRender: () => null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return finalColumns;
|
||||||
|
});
|
||||||
|
|
||||||
|
const flattenColumns = computed(() => {
|
||||||
|
if (direction.value === 'rtl') {
|
||||||
|
return revertForRtl(flatColumns(mergedColumns.value));
|
||||||
|
}
|
||||||
|
return flatColumns(mergedColumns.value);
|
||||||
|
});
|
||||||
|
// Only check out of production since it's waste for each render
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
watchEffect(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
warningFixed(flattenColumns.value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return [mergedColumns, flattenColumns];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useColumns;
|
|
@ -0,0 +1,85 @@
|
||||||
|
import type { Ref } from 'vue';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import type { GetRowKey, Key } from '../interface';
|
||||||
|
|
||||||
|
// recursion (flat tree structure)
|
||||||
|
function flatRecord<T>(
|
||||||
|
record: T,
|
||||||
|
indent: number,
|
||||||
|
childrenColumnName: string,
|
||||||
|
expandedKeys: Set<Key>,
|
||||||
|
getRowKey: GetRowKey<T>,
|
||||||
|
) {
|
||||||
|
const arr = [];
|
||||||
|
|
||||||
|
arr.push({
|
||||||
|
record,
|
||||||
|
indent,
|
||||||
|
});
|
||||||
|
|
||||||
|
const key = getRowKey(record);
|
||||||
|
|
||||||
|
const expanded = expandedKeys?.has(key);
|
||||||
|
|
||||||
|
if (record && Array.isArray(record[childrenColumnName]) && expanded) {
|
||||||
|
// expanded state, flat record
|
||||||
|
for (let i = 0; i < record[childrenColumnName].length; i += 1) {
|
||||||
|
const tempArr = flatRecord(
|
||||||
|
record[childrenColumnName][i],
|
||||||
|
indent + 1,
|
||||||
|
childrenColumnName,
|
||||||
|
expandedKeys,
|
||||||
|
getRowKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
arr.push(...tempArr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* flat tree data on expanded state
|
||||||
|
*
|
||||||
|
* @export
|
||||||
|
* @template T
|
||||||
|
* @param {*} data : table data
|
||||||
|
* @param {string} childrenColumnName : 指定树形结构的列名
|
||||||
|
* @param {Set<Key>} expandedKeys : 展开的行对应的keys
|
||||||
|
* @param {GetRowKey<T>} getRowKey : 获取当前rowKey的方法
|
||||||
|
* @returns flattened data
|
||||||
|
*/
|
||||||
|
export default function useFlattenRecords<T>(
|
||||||
|
dataRef: Ref<[]>,
|
||||||
|
childrenColumnNameRef: Ref<string>,
|
||||||
|
expandedKeysRef: Ref<Set<Key>>,
|
||||||
|
getRowKey: GetRowKey<T>,
|
||||||
|
) {
|
||||||
|
const arr: Ref<{ record: T; indent: number }[]> = computed(() => {
|
||||||
|
const childrenColumnName = childrenColumnNameRef.value;
|
||||||
|
const expandedKeys = expandedKeysRef.value;
|
||||||
|
const data = dataRef.value;
|
||||||
|
if (expandedKeys?.size) {
|
||||||
|
const temp: { record: T; indent: number }[] = [];
|
||||||
|
|
||||||
|
// collect flattened record
|
||||||
|
for (let i = 0; i < data?.length; i += 1) {
|
||||||
|
const record = data[i];
|
||||||
|
|
||||||
|
temp.push(...flatRecord<T>(record, 0, childrenColumnName, expandedKeys, getRowKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data?.map(item => {
|
||||||
|
return {
|
||||||
|
record: item,
|
||||||
|
indent: 0,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
import type { Ref, UnwrapRef } from 'vue';
|
||||||
|
import { getCurrentInstance, onBeforeUnmount, ref } from 'vue';
|
||||||
|
|
||||||
|
export type Updater<State> = (prev: State) => State;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute code before next frame but async
|
||||||
|
*/
|
||||||
|
export function useLayoutState<State>(
|
||||||
|
defaultState: State,
|
||||||
|
): [Ref<State>, (updater: Updater<State>) => void] {
|
||||||
|
const stateRef = ref<State>(defaultState);
|
||||||
|
// const [, forceUpdate] = useState({});
|
||||||
|
|
||||||
|
const lastPromiseRef = ref<Promise<void>>(null);
|
||||||
|
const updateBatchRef = ref<Updater<State>[]>([]);
|
||||||
|
const instance = getCurrentInstance();
|
||||||
|
function setFrameState(updater: Updater<State>) {
|
||||||
|
updateBatchRef.value.push(updater);
|
||||||
|
|
||||||
|
const promise = Promise.resolve();
|
||||||
|
lastPromiseRef.value = promise;
|
||||||
|
|
||||||
|
promise.then(() => {
|
||||||
|
if (lastPromiseRef.value === promise) {
|
||||||
|
const prevBatch = updateBatchRef.value;
|
||||||
|
const prevState = stateRef.value;
|
||||||
|
updateBatchRef.value = [];
|
||||||
|
|
||||||
|
prevBatch.forEach(batchUpdater => {
|
||||||
|
stateRef.value = batchUpdater(stateRef.value as State) as UnwrapRef<State>;
|
||||||
|
});
|
||||||
|
|
||||||
|
lastPromiseRef.value = null;
|
||||||
|
|
||||||
|
if (prevState !== stateRef.value) {
|
||||||
|
instance.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
lastPromiseRef.value = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return [stateRef as Ref<State>, setFrameState];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Lock frame, when frame pass reset the lock. */
|
||||||
|
export function useTimeoutLock<State>(
|
||||||
|
defaultState?: State,
|
||||||
|
): [(state: UnwrapRef<State>) => void, () => UnwrapRef<State> | null] {
|
||||||
|
const frameRef = ref<State | null>(defaultState || null);
|
||||||
|
const timeoutRef = ref<number>();
|
||||||
|
|
||||||
|
function cleanUp() {
|
||||||
|
window.clearTimeout(timeoutRef.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setState(newState: UnwrapRef<State>) {
|
||||||
|
frameRef.value = newState;
|
||||||
|
cleanUp();
|
||||||
|
|
||||||
|
timeoutRef.value = window.setTimeout(() => {
|
||||||
|
frameRef.value = null;
|
||||||
|
timeoutRef.value = undefined;
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getState() {
|
||||||
|
return frameRef.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
cleanUp();
|
||||||
|
});
|
||||||
|
|
||||||
|
return [setState, getState];
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
import canUseDom from '../../_util/canUseDom';
|
||||||
|
import type { ComputedRef, Ref } from 'vue';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import type { TableSticky } from '../interface';
|
||||||
|
|
||||||
|
// fix ssr render
|
||||||
|
const defaultContainer = canUseDom() ? window : null;
|
||||||
|
|
||||||
|
/** Sticky header hooks */
|
||||||
|
export default function useSticky(
|
||||||
|
stickyRef: Ref<boolean | TableSticky>,
|
||||||
|
prefixClsRef: Ref<string>,
|
||||||
|
): ComputedRef<{
|
||||||
|
isSticky: boolean;
|
||||||
|
offsetHeader: number;
|
||||||
|
offsetSummary: number;
|
||||||
|
offsetScroll: number;
|
||||||
|
stickyClassName: string;
|
||||||
|
container: Window | HTMLElement;
|
||||||
|
}> {
|
||||||
|
return computed(() => {
|
||||||
|
const {
|
||||||
|
offsetHeader = 0,
|
||||||
|
offsetSummary = 0,
|
||||||
|
offsetScroll = 0,
|
||||||
|
getContainer = () => defaultContainer,
|
||||||
|
} = typeof stickyRef.value === 'object' ? stickyRef.value : {};
|
||||||
|
|
||||||
|
const container = getContainer() || defaultContainer;
|
||||||
|
const isSticky = !!stickyRef.value;
|
||||||
|
return {
|
||||||
|
isSticky,
|
||||||
|
stickyClassName: isSticky ? `${prefixClsRef.value}-sticky-holder` : '',
|
||||||
|
offsetHeader,
|
||||||
|
offsetSummary,
|
||||||
|
offsetScroll,
|
||||||
|
container,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
import type { ComputedRef, Ref } from 'vue';
|
||||||
|
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import type { StickyOffsets } from '../interface';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get sticky column offset width
|
||||||
|
*/
|
||||||
|
function useStickyOffsets(
|
||||||
|
colWidthsRef: Ref<number[]>,
|
||||||
|
columnCountRef: Ref<number>,
|
||||||
|
directionRef: Ref<'ltr' | 'rtl'>,
|
||||||
|
) {
|
||||||
|
const stickyOffsets: ComputedRef<StickyOffsets> = computed(() => {
|
||||||
|
const leftOffsets: number[] = [];
|
||||||
|
const rightOffsets: number[] = [];
|
||||||
|
let left = 0;
|
||||||
|
let right = 0;
|
||||||
|
|
||||||
|
const colWidths = colWidthsRef.value;
|
||||||
|
const columnCount = columnCountRef.value;
|
||||||
|
const direction = directionRef.value;
|
||||||
|
|
||||||
|
for (let start = 0; start < columnCount; start += 1) {
|
||||||
|
if (direction === 'rtl') {
|
||||||
|
// Left offset
|
||||||
|
rightOffsets[start] = right;
|
||||||
|
right += colWidths[start] || 0;
|
||||||
|
|
||||||
|
// Right offset
|
||||||
|
const end = columnCount - start - 1;
|
||||||
|
leftOffsets[end] = left;
|
||||||
|
left += colWidths[end] || 0;
|
||||||
|
} else {
|
||||||
|
// Left offset
|
||||||
|
leftOffsets[start] = left;
|
||||||
|
left += colWidths[start] || 0;
|
||||||
|
|
||||||
|
// Right offset
|
||||||
|
const end = columnCount - start - 1;
|
||||||
|
rightOffsets[end] = right;
|
||||||
|
right += colWidths[end] || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
left: leftOffsets,
|
||||||
|
right: rightOffsets,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return stickyOffsets;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useStickyOffsets;
|
|
@ -0,0 +1,10 @@
|
||||||
|
// base rc-table@7.17.2
|
||||||
|
import Table from './Table';
|
||||||
|
import { FooterComponents as Summary } from './Footer';
|
||||||
|
import Column from './sugar/Column';
|
||||||
|
import ColumnGroup from './sugar/ColumnGroup';
|
||||||
|
import { INTERNAL_COL_DEFINE } from './utils/legacyUtil';
|
||||||
|
|
||||||
|
export { Summary, Column, ColumnGroup, INTERNAL_COL_DEFINE };
|
||||||
|
|
||||||
|
export default Table;
|
|
@ -0,0 +1,226 @@
|
||||||
|
/**
|
||||||
|
* ColumnType which applied in antd: https://ant.design/components/table-cn/#Column
|
||||||
|
* - defaultSortOrder
|
||||||
|
* - filterDropdown
|
||||||
|
* - filterDropdownVisible
|
||||||
|
* - filtered
|
||||||
|
* - filteredValue
|
||||||
|
* - filterIcon
|
||||||
|
* - filterMultiple
|
||||||
|
* - filters
|
||||||
|
* - sorter
|
||||||
|
* - sortOrder
|
||||||
|
* - sortDirections
|
||||||
|
* - onFilter
|
||||||
|
* - onFilterDropdownVisibleChange
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { CSSProperties, DefineComponent, FunctionalComponent, HTMLAttributes, Ref } from 'vue';
|
||||||
|
|
||||||
|
export type Key = number | string;
|
||||||
|
|
||||||
|
export type FixedType = 'left' | 'right' | boolean;
|
||||||
|
|
||||||
|
export type DefaultRecordType = Record<string, any>;
|
||||||
|
|
||||||
|
export type TableLayout = 'auto' | 'fixed';
|
||||||
|
|
||||||
|
// ==================== Row =====================
|
||||||
|
export type RowClassName<RecordType> = (
|
||||||
|
record: RecordType,
|
||||||
|
index: number,
|
||||||
|
indent: number,
|
||||||
|
) => string;
|
||||||
|
|
||||||
|
// =================== Column ===================
|
||||||
|
export interface CellType<RecordType = DefaultRecordType> {
|
||||||
|
key?: Key;
|
||||||
|
class?: string;
|
||||||
|
className?: string;
|
||||||
|
style?: CSSProperties;
|
||||||
|
children?: any;
|
||||||
|
column?: ColumnsType<RecordType>[number];
|
||||||
|
colSpan?: number;
|
||||||
|
rowSpan?: number;
|
||||||
|
|
||||||
|
/** Only used for table header */
|
||||||
|
hasSubColumns?: boolean;
|
||||||
|
colStart?: number;
|
||||||
|
colEnd?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RenderedCell<RecordType> {
|
||||||
|
props?: CellType<RecordType>;
|
||||||
|
children?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DataIndex = string | number | readonly (string | number)[];
|
||||||
|
|
||||||
|
export type CellEllipsisType = { showTitle?: boolean } | boolean;
|
||||||
|
|
||||||
|
interface ColumnSharedType<RecordType> {
|
||||||
|
title?: any;
|
||||||
|
key?: Key;
|
||||||
|
class?: string;
|
||||||
|
className?: string;
|
||||||
|
fixed?: FixedType;
|
||||||
|
onHeaderCell?: GetComponentProps<ColumnsType<RecordType>[number]>;
|
||||||
|
ellipsis?: CellEllipsisType;
|
||||||
|
align?: AlignType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ColumnGroupType<RecordType> extends ColumnSharedType<RecordType> {
|
||||||
|
children: ColumnsType<RecordType>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AlignType = 'left' | 'center' | 'right';
|
||||||
|
|
||||||
|
export interface ColumnType<RecordType> extends ColumnSharedType<RecordType> {
|
||||||
|
colSpan?: number;
|
||||||
|
dataIndex?: DataIndex;
|
||||||
|
customRender?: (opt: {
|
||||||
|
value: any;
|
||||||
|
text: any; // 兼容 V2
|
||||||
|
record: RecordType;
|
||||||
|
index: number;
|
||||||
|
column: ColumnType<RecordType>;
|
||||||
|
}) => any | RenderedCell<RecordType>;
|
||||||
|
rowSpan?: number;
|
||||||
|
width?: number | string;
|
||||||
|
onCell?: GetComponentProps<RecordType>;
|
||||||
|
/** @deprecated Please use `onCell` instead */
|
||||||
|
onCellClick?: (record: RecordType, e: MouseEvent) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ColumnsType<RecordType = unknown> = readonly (
|
||||||
|
| ColumnGroupType<RecordType>
|
||||||
|
| ColumnType<RecordType>
|
||||||
|
)[];
|
||||||
|
|
||||||
|
export type GetRowKey<RecordType> = (record: RecordType, index?: number) => Key;
|
||||||
|
|
||||||
|
// ================= Fix Column =================
|
||||||
|
export interface StickyOffsets {
|
||||||
|
left: readonly number[];
|
||||||
|
right: readonly number[];
|
||||||
|
isSticky?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= Customized =================
|
||||||
|
export type GetComponentProps<DataType> = (
|
||||||
|
data: DataType,
|
||||||
|
index?: number,
|
||||||
|
) => Omit<HTMLAttributes, 'style'> & { style?: CSSProperties };
|
||||||
|
|
||||||
|
type Component<P> = DefineComponent<P> | FunctionalComponent<P> | string;
|
||||||
|
|
||||||
|
export type CustomizeComponent = Component<any>;
|
||||||
|
|
||||||
|
export type CustomizeScrollBody<RecordType> = (
|
||||||
|
data: readonly RecordType[],
|
||||||
|
info: {
|
||||||
|
scrollbarSize: number;
|
||||||
|
ref: Ref<{ scrollLeft: number }>;
|
||||||
|
onScroll: (info: { currentTarget?: HTMLElement; scrollLeft?: number }) => void;
|
||||||
|
},
|
||||||
|
) => any;
|
||||||
|
|
||||||
|
export interface TableComponents<RecordType> {
|
||||||
|
table?: CustomizeComponent;
|
||||||
|
header?: {
|
||||||
|
wrapper?: CustomizeComponent;
|
||||||
|
row?: CustomizeComponent;
|
||||||
|
cell?: CustomizeComponent;
|
||||||
|
};
|
||||||
|
body?:
|
||||||
|
| CustomizeScrollBody<RecordType>
|
||||||
|
| {
|
||||||
|
wrapper?: CustomizeComponent;
|
||||||
|
row?: CustomizeComponent;
|
||||||
|
cell?: CustomizeComponent;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type GetComponent = (
|
||||||
|
path: readonly string[],
|
||||||
|
defaultComponent?: CustomizeComponent,
|
||||||
|
) => CustomizeComponent;
|
||||||
|
|
||||||
|
// =================== Expand ===================
|
||||||
|
export type ExpandableType = false | 'row' | 'nest';
|
||||||
|
|
||||||
|
export interface LegacyExpandableProps<RecordType> {
|
||||||
|
/** @deprecated Use `expandable.expandedRowKeys` instead */
|
||||||
|
expandedRowKeys?: Key[];
|
||||||
|
/** @deprecated Use `expandable.defaultExpandedRowKeys` instead */
|
||||||
|
defaultExpandedRowKeys?: Key[];
|
||||||
|
/** @deprecated Use `expandable.expandedRowRender` instead */
|
||||||
|
expandedRowRender?: ExpandedRowRender<RecordType>;
|
||||||
|
/** @deprecated Use `expandable.expandRowByClick` instead */
|
||||||
|
expandRowByClick?: boolean;
|
||||||
|
/** @deprecated Use `expandable.expandIcon` instead */
|
||||||
|
expandIcon?: RenderExpandIcon<RecordType>;
|
||||||
|
/** @deprecated Use `expandable.onExpand` instead */
|
||||||
|
onExpand?: (expanded: boolean, record: RecordType) => void;
|
||||||
|
/** @deprecated Use `expandable.onExpandedRowsChange` instead */
|
||||||
|
onExpandedRowsChange?: (expandedKeys: Key[]) => void;
|
||||||
|
/** @deprecated Use `expandable.defaultExpandAllRows` instead */
|
||||||
|
defaultExpandAllRows?: boolean;
|
||||||
|
/** @deprecated Use `expandable.indentSize` instead */
|
||||||
|
indentSize?: number;
|
||||||
|
/** @deprecated Use `expandable.expandIconColumnIndex` instead */
|
||||||
|
expandIconColumnIndex?: number;
|
||||||
|
/** @deprecated Use `expandable.expandedRowClassName` instead */
|
||||||
|
expandedRowClassName?: RowClassName<RecordType>;
|
||||||
|
/** @deprecated Use `expandable.childrenColumnName` instead */
|
||||||
|
childrenColumnName?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ExpandedRowRender<ValueType> = (
|
||||||
|
record: ValueType,
|
||||||
|
index: number,
|
||||||
|
indent: number,
|
||||||
|
expanded: boolean,
|
||||||
|
) => any;
|
||||||
|
|
||||||
|
export interface RenderExpandIconProps<RecordType> {
|
||||||
|
prefixCls: string;
|
||||||
|
expanded: boolean;
|
||||||
|
record: RecordType;
|
||||||
|
expandable: boolean;
|
||||||
|
onExpand: TriggerEventHandler<RecordType>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RenderExpandIcon<RecordType> = (props: RenderExpandIconProps<RecordType>) => any;
|
||||||
|
|
||||||
|
export interface ExpandableConfig<RecordType> {
|
||||||
|
expandedRowKeys?: readonly Key[];
|
||||||
|
defaultExpandedRowKeys?: readonly Key[];
|
||||||
|
expandedRowRender?: ExpandedRowRender<RecordType>;
|
||||||
|
expandRowByClick?: boolean;
|
||||||
|
expandIcon?: RenderExpandIcon<RecordType>;
|
||||||
|
onExpand?: (expanded: boolean, record: RecordType) => void;
|
||||||
|
onExpandedRowsChange?: (expandedKeys: readonly Key[]) => void;
|
||||||
|
defaultExpandAllRows?: boolean;
|
||||||
|
indentSize?: number;
|
||||||
|
expandIconColumnIndex?: number;
|
||||||
|
expandedRowClassName?: RowClassName<RecordType>;
|
||||||
|
childrenColumnName?: string;
|
||||||
|
rowExpandable?: (record: RecordType) => boolean;
|
||||||
|
columnWidth?: number | string;
|
||||||
|
fixed?: FixedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =================== Render ===================
|
||||||
|
export type PanelRender<RecordType> = (data: readonly RecordType[]) => any;
|
||||||
|
|
||||||
|
// =================== Events ===================
|
||||||
|
export type TriggerEventHandler<RecordType> = (record: RecordType, event: MouseEvent) => void;
|
||||||
|
|
||||||
|
// =================== Sticky ===================
|
||||||
|
export interface TableSticky {
|
||||||
|
offsetHeader?: number;
|
||||||
|
offsetSummary?: number;
|
||||||
|
offsetScroll?: number;
|
||||||
|
getContainer?: () => Window | HTMLElement;
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { FunctionalComponent } from 'vue';
|
||||||
|
import { ColumnType } from '../interface';
|
||||||
|
|
||||||
|
export type ColumnProps<RecordType> = ColumnType<RecordType>;
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
/**
|
||||||
|
* This is a syntactic sugar for `columns` prop.
|
||||||
|
* So HOC will not work on this.
|
||||||
|
*/
|
||||||
|
const Column: { <T>(arg: T): FunctionalComponent<ColumnProps<T>> } = () => null;
|
||||||
|
|
||||||
|
export default Column;
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { ColumnType } from '../interface';
|
||||||
|
import { FunctionalComponent } from 'vue';
|
||||||
|
/* istanbul ignore next */
|
||||||
|
/**
|
||||||
|
* This is a syntactic sugar for `columns` prop.
|
||||||
|
* So HOC will not work on this.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export type ColumnGroupProps<RecordType> = ColumnType<RecordType>;
|
||||||
|
|
||||||
|
const ColumnGroup: { <T>(arg: T): FunctionalComponent<ColumnGroupProps<T>> } = () => null;
|
||||||
|
|
||||||
|
export default ColumnGroup;
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { RenderExpandIconProps, Key, GetRowKey } from '../interface';
|
||||||
|
|
||||||
|
export function renderExpandIcon<RecordType>({
|
||||||
|
prefixCls,
|
||||||
|
record,
|
||||||
|
onExpand,
|
||||||
|
expanded,
|
||||||
|
expandable,
|
||||||
|
}: RenderExpandIconProps<RecordType>) {
|
||||||
|
const expandClassName = `${prefixCls}-row-expand-icon`;
|
||||||
|
|
||||||
|
if (!expandable) {
|
||||||
|
return <span class={[expandClassName, `${prefixCls}-row-spaced`]} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onClick = event => {
|
||||||
|
onExpand(record, event);
|
||||||
|
event.stopPropagation();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
class={{
|
||||||
|
[expandClassName]: true,
|
||||||
|
[`${prefixCls}-row-expanded`]: expanded,
|
||||||
|
[`${prefixCls}-row-collapsed`]: !expanded,
|
||||||
|
}}
|
||||||
|
onClick={onClick}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findAllChildrenKeys<RecordType>(
|
||||||
|
data: readonly RecordType[],
|
||||||
|
getRowKey: GetRowKey<RecordType>,
|
||||||
|
childrenColumnName: string,
|
||||||
|
): Key[] {
|
||||||
|
const keys: Key[] = [];
|
||||||
|
|
||||||
|
function dig(list: readonly RecordType[]) {
|
||||||
|
(list || []).forEach((item, index) => {
|
||||||
|
keys.push(getRowKey(item, index));
|
||||||
|
|
||||||
|
dig((item as any)[childrenColumnName]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dig(data);
|
||||||
|
|
||||||
|
return keys;
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
import type { StickyOffsets, FixedType } from '../interface';
|
||||||
|
|
||||||
|
export interface FixedInfo {
|
||||||
|
fixLeft: number | false;
|
||||||
|
fixRight: number | false;
|
||||||
|
lastFixLeft: boolean;
|
||||||
|
firstFixRight: boolean;
|
||||||
|
|
||||||
|
// For Rtl Direction
|
||||||
|
lastFixRight: boolean;
|
||||||
|
firstFixLeft: boolean;
|
||||||
|
|
||||||
|
isSticky: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCellFixedInfo(
|
||||||
|
colStart: number,
|
||||||
|
colEnd: number,
|
||||||
|
columns: readonly { fixed?: FixedType }[],
|
||||||
|
stickyOffsets: StickyOffsets,
|
||||||
|
direction: 'ltr' | 'rtl',
|
||||||
|
): FixedInfo {
|
||||||
|
const startColumn = columns[colStart] || {};
|
||||||
|
const endColumn = columns[colEnd] || {};
|
||||||
|
|
||||||
|
let fixLeft: number;
|
||||||
|
let fixRight: number;
|
||||||
|
|
||||||
|
if (startColumn.fixed === 'left') {
|
||||||
|
fixLeft = stickyOffsets.left[colStart];
|
||||||
|
} else if (endColumn.fixed === 'right') {
|
||||||
|
fixRight = stickyOffsets.right[colEnd];
|
||||||
|
}
|
||||||
|
|
||||||
|
let lastFixLeft = false;
|
||||||
|
let firstFixRight = false;
|
||||||
|
|
||||||
|
let lastFixRight = false;
|
||||||
|
let firstFixLeft = false;
|
||||||
|
|
||||||
|
const nextColumn = columns[colEnd + 1];
|
||||||
|
const prevColumn = columns[colStart - 1];
|
||||||
|
|
||||||
|
if (direction === 'rtl') {
|
||||||
|
if (fixLeft !== undefined) {
|
||||||
|
const prevFixLeft = prevColumn && prevColumn.fixed === 'left';
|
||||||
|
firstFixLeft = !prevFixLeft;
|
||||||
|
} else if (fixRight !== undefined) {
|
||||||
|
const nextFixRight = nextColumn && nextColumn.fixed === 'right';
|
||||||
|
lastFixRight = !nextFixRight;
|
||||||
|
}
|
||||||
|
} else if (fixLeft !== undefined) {
|
||||||
|
const nextFixLeft = nextColumn && nextColumn.fixed === 'left';
|
||||||
|
lastFixLeft = !nextFixLeft;
|
||||||
|
} else if (fixRight !== undefined) {
|
||||||
|
const prevFixRight = prevColumn && prevColumn.fixed === 'right';
|
||||||
|
firstFixRight = !prevFixRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
fixLeft,
|
||||||
|
fixRight,
|
||||||
|
lastFixLeft,
|
||||||
|
firstFixRight,
|
||||||
|
lastFixRight,
|
||||||
|
firstFixLeft,
|
||||||
|
isSticky: stickyOffsets.isSticky,
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { warning } from '../../vc-util/warning';
|
||||||
|
import type { ExpandableConfig, LegacyExpandableProps } from '../interface';
|
||||||
|
|
||||||
|
export const INTERNAL_COL_DEFINE = 'RC_TABLE_INTERNAL_COL_DEFINE';
|
||||||
|
|
||||||
|
export function getExpandableProps<RecordType>(
|
||||||
|
props: LegacyExpandableProps<RecordType> & {
|
||||||
|
expandable?: ExpandableConfig<RecordType>;
|
||||||
|
},
|
||||||
|
): ExpandableConfig<RecordType> {
|
||||||
|
const { expandable, ...legacyExpandableConfig } = props;
|
||||||
|
|
||||||
|
if ('expandable' in props) {
|
||||||
|
return {
|
||||||
|
...legacyExpandableConfig,
|
||||||
|
...expandable,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
process.env.NODE_ENV !== 'production' &&
|
||||||
|
[
|
||||||
|
'indentSize',
|
||||||
|
'expandedRowKeys',
|
||||||
|
'defaultExpandedRowKeys',
|
||||||
|
'defaultExpandAllRows',
|
||||||
|
'expandedRowRender',
|
||||||
|
'expandRowByClick',
|
||||||
|
'expandIcon',
|
||||||
|
'onExpand',
|
||||||
|
'onExpandedRowsChange',
|
||||||
|
'expandedRowClassName',
|
||||||
|
'expandIconColumnIndex',
|
||||||
|
].some(prop => prop in props)
|
||||||
|
) {
|
||||||
|
warning(false, 'expanded related props have been moved into `expandable`.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return legacyExpandableConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns only data- and aria- key/value pairs
|
||||||
|
* @param {object} props
|
||||||
|
*/
|
||||||
|
export function getDataAndAriaProps(props: object) {
|
||||||
|
/* eslint-disable no-param-reassign */
|
||||||
|
return Object.keys(props).reduce((memo, key) => {
|
||||||
|
if (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-') {
|
||||||
|
memo[key] = props[key];
|
||||||
|
}
|
||||||
|
return memo;
|
||||||
|
}, {});
|
||||||
|
/* eslint-enable */
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
import { Key, DataIndex } from '../interface';
|
||||||
|
|
||||||
|
const INTERNAL_KEY_PREFIX = 'RC_TABLE_KEY';
|
||||||
|
|
||||||
|
function toArray<T>(arr: T | readonly T[]): T[] {
|
||||||
|
if (arr === undefined || arr === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return (Array.isArray(arr) ? arr : [arr]) as T[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPathValue<ValueType, ObjectType extends object>(
|
||||||
|
record: ObjectType,
|
||||||
|
path: DataIndex,
|
||||||
|
): ValueType {
|
||||||
|
// Skip if path is empty
|
||||||
|
if (!path && typeof path !== 'number') {
|
||||||
|
return record as unknown as ValueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pathList = toArray(path);
|
||||||
|
|
||||||
|
let current: ValueType | ObjectType = record;
|
||||||
|
|
||||||
|
for (let i = 0; i < pathList.length; i += 1) {
|
||||||
|
if (!current) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prop = pathList[i];
|
||||||
|
current = current[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
return current as ValueType;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GetColumnKeyColumn {
|
||||||
|
key?: Key;
|
||||||
|
dataIndex?: DataIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getColumnsKey(columns: readonly GetColumnKeyColumn[]) {
|
||||||
|
const columnKeys: Key[] = [];
|
||||||
|
const keys: Record<Key, boolean> = {};
|
||||||
|
|
||||||
|
columns.forEach(column => {
|
||||||
|
const { key, dataIndex } = column || {};
|
||||||
|
|
||||||
|
let mergedKey = key || toArray(dataIndex).join('-') || INTERNAL_KEY_PREFIX;
|
||||||
|
while (keys[mergedKey]) {
|
||||||
|
mergedKey = `${mergedKey}_next`;
|
||||||
|
}
|
||||||
|
keys[mergedKey] = true;
|
||||||
|
|
||||||
|
columnKeys.push(mergedKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
return columnKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function mergeObject<ReturnObject extends object>(
|
||||||
|
...objects: Partial<ReturnObject>[]
|
||||||
|
): ReturnObject {
|
||||||
|
const merged: Partial<ReturnObject> = {};
|
||||||
|
|
||||||
|
/* eslint-disable no-param-reassign */
|
||||||
|
function fillProps(obj: object, clone: object) {
|
||||||
|
if (clone) {
|
||||||
|
Object.keys(clone).forEach(key => {
|
||||||
|
const value = clone[key];
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
obj[key] = obj[key] || {};
|
||||||
|
fillProps(obj[key], value);
|
||||||
|
} else {
|
||||||
|
obj[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
|
objects.forEach(clone => {
|
||||||
|
fillProps(merged, clone);
|
||||||
|
});
|
||||||
|
|
||||||
|
return merged as ReturnObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function validateValue<T>(val: T) {
|
||||||
|
return val !== null && val !== undefined;
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
"ant-design-vue": ["components/index.ts"],
|
"ant-design-vue": ["components/index.ts"],
|
||||||
"ant-design-vue/es/*": ["components/*"]
|
"ant-design-vue/es/*": ["components/*"]
|
||||||
},
|
},
|
||||||
|
"lib": ["ESNext", "DOM", "DOM.Iterable"],
|
||||||
"strictNullChecks": false,
|
"strictNullChecks": false,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
@ -14,7 +15,6 @@
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"lib": ["dom", "es2017"],
|
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"importsNotUsedAsValues": "preserve"
|
"importsNotUsedAsValues": "preserve"
|
||||||
|
|
Loading…
Reference in New Issue