Merge branch 'next' of github.com:vueComponent/ant-design-vue into next
commit
dbb67a7b81
|
@ -2,7 +2,7 @@ export interface RefObject extends Function {
|
|||
current?: any;
|
||||
}
|
||||
|
||||
function createRef(): RefObject {
|
||||
function createRef(): any {
|
||||
const func: RefObject = (node: any) => {
|
||||
func.current = node;
|
||||
};
|
||||
|
|
|
@ -42,7 +42,7 @@ const responsiveObserve = {
|
|||
if (!subscribers.size) this.unregister();
|
||||
},
|
||||
unregister() {
|
||||
Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
|
||||
Object.keys(responsiveMap).forEach((screen: string) => {
|
||||
const matchMediaQuery = responsiveMap[screen]!;
|
||||
const handler = this.matchHandlers[matchMediaQuery];
|
||||
handler?.mql.removeListener(handler?.listener);
|
||||
|
@ -50,7 +50,7 @@ const responsiveObserve = {
|
|||
subscribers.clear();
|
||||
},
|
||||
register() {
|
||||
Object.keys(responsiveMap).forEach((screen: Breakpoint) => {
|
||||
Object.keys(responsiveMap).forEach((screen: string) => {
|
||||
const matchMediaQuery = responsiveMap[screen]!;
|
||||
const listener = ({ matches }: { matches: boolean }) => {
|
||||
this.dispatch({
|
||||
|
|
|
@ -19,17 +19,10 @@ const AffixMounter = {
|
|||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div ref="container" class="container">
|
||||
<Affix
|
||||
class="fixed"
|
||||
target={() => this.$refs.container}
|
||||
ref="affix"
|
||||
{...{ props: this.$props }}
|
||||
>
|
||||
<Button type="primary">Fixed at the top of container</Button>
|
||||
</Affix>
|
||||
</div>
|
||||
<div ref="container" class="container">
|
||||
<Affix class="fixed" target={() => this.$refs.container} ref="affix">
|
||||
<Button type="primary">Fixed at the top of container</Button>
|
||||
</Affix>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -150,6 +150,6 @@ AutoComplete.install = function(app: App) {
|
|||
};
|
||||
|
||||
export default AutoComplete as typeof AutoComplete & {
|
||||
readonly Option: typeof AutoComplete.Option;
|
||||
readonly OptGroup: typeof AutoComplete.OptGroup;
|
||||
readonly Option: typeof Option;
|
||||
readonly OptGroup: typeof OptGroup;
|
||||
};
|
||||
|
|
|
@ -59,7 +59,7 @@ exports[`Button should not render as link button when href is undefined 1`] = `
|
|||
`;
|
||||
|
||||
exports[`Button should support link button 1`] = `
|
||||
<a target="_blank" href="http://ant.design" class="ant-btn">
|
||||
<a target="_blank" class="ant-btn" href="http://ant.design">
|
||||
<!----><span>link button</span>
|
||||
</a>
|
||||
`;
|
||||
|
|
|
@ -96,7 +96,7 @@ const Card = defineComponent({
|
|||
} = this.$props;
|
||||
const { $slots } = this;
|
||||
const children = getSlot(this);
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const { getPrefixCls } = this.configProvider;
|
||||
const prefixCls = getPrefixCls('card', customizePrefixCls);
|
||||
|
||||
const tabBarExtraContent = getComponent(this, 'tabBarExtraContent');
|
||||
|
|
|
@ -19,9 +19,9 @@ export default defineComponent({
|
|||
props: {
|
||||
name: PropTypes.string,
|
||||
prefixCls: PropTypes.string,
|
||||
defaultValue: { type: Array as PropType<Array<CheckboxValueType>>},
|
||||
value: { type: Array as PropType<Array<CheckboxValueType>>},
|
||||
options: {type: Array as PropType<Array<CheckboxOptionType | string>>},
|
||||
defaultValue: { type: Array as PropType<Array<CheckboxValueType>> },
|
||||
value: { type: Array as PropType<Array<CheckboxValueType>> },
|
||||
options: { type: Array as PropType<Array<CheckboxOptionType | string>> },
|
||||
disabled: PropTypes.looseBool,
|
||||
onChange: PropTypes.func,
|
||||
},
|
||||
|
@ -48,7 +48,7 @@ export default defineComponent({
|
|||
},
|
||||
methods: {
|
||||
getOptions() {
|
||||
const { options, $slots } = this;
|
||||
const { options = [], $slots } = this;
|
||||
return options.map(option => {
|
||||
if (typeof option === 'string') {
|
||||
return {
|
||||
|
|
|
@ -8,11 +8,11 @@ describe('ConfigProvider', () => {
|
|||
mountTest({
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<ConfigProvider>
|
||||
<div />
|
||||
</ConfigProvider>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -89,16 +89,16 @@ const ACol = defineComponent<ColProps>({
|
|||
let mergedStyle: CSSProperties = {};
|
||||
if (gutter) {
|
||||
mergedStyle = {
|
||||
...(gutter[0]! > 0
|
||||
...(gutter[0] > 0
|
||||
? {
|
||||
paddingLeft: gutter[0]! / 2,
|
||||
paddingRight: gutter[0]! / 2,
|
||||
paddingLeft: `${gutter[0] / 2}px`,
|
||||
paddingRight: `${gutter[0] / 2}px`,
|
||||
}
|
||||
: {}),
|
||||
...(gutter[1]! > 0
|
||||
...(gutter[1] > 0
|
||||
? {
|
||||
paddingTop: gutter[1]! / 2,
|
||||
paddingBottom: gutter[1]! / 2,
|
||||
paddingTop: `${gutter[1] / 2}px`,
|
||||
paddingBottom: `${gutter[1] / 2}px`,
|
||||
}
|
||||
: {}),
|
||||
...mergedStyle,
|
||||
|
@ -109,7 +109,7 @@ const ACol = defineComponent<ColProps>({
|
|||
}
|
||||
|
||||
return (
|
||||
<div style={mergedStyle} class={classes}>
|
||||
<div class={classes} style={mergedStyle}>
|
||||
{slots.default?.()}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -104,16 +104,16 @@ const ARow = defineComponent<RowProps>({
|
|||
[`${prefixCls}-${align}`]: align,
|
||||
});
|
||||
const rowStyle = {
|
||||
...(gutter[0]! > 0
|
||||
...(gutter[0] > 0
|
||||
? {
|
||||
marginLeft: gutter[0]! / -2,
|
||||
marginRight: gutter[0]! / -2,
|
||||
marginLeft: `${gutter[0] / -2}px`,
|
||||
marginRight: `${gutter[0] / -2}px`,
|
||||
}
|
||||
: {}),
|
||||
...(gutter[1]! > 0
|
||||
...(gutter[1] > 0
|
||||
? {
|
||||
marginTop: gutter[1]! / -2,
|
||||
marginBottom: gutter[1]! / 2,
|
||||
marginTop: `${gutter[1] / -2}px`,
|
||||
marginBottom: `${gutter[1] / -2}px`,
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
|
|
@ -3,12 +3,24 @@
|
|||
exports[`Grid renders wrapped Col correctly 1`] = `
|
||||
<div class="ant-row" style="margin-left: -10px; margin-right: -10px;">
|
||||
<div>
|
||||
<div class="ant-col ant-col-12" style="padding-left: 10px; padding-right: 10px;"></div>
|
||||
<div class="ant-col ant-col-12" style="padding-left: 10px; padding-right: 10px;">
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
<div class="ant-col ant-col-12" style="padding-left: 10px; padding-right: 10px;">
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-col ant-col-12" style="padding-left: 10px; padding-right: 10px;"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Grid should render Col 1`] = `<div class="ant-col ant-col-2"></div>`;
|
||||
exports[`Grid should render Col 1`] = `
|
||||
<div class="ant-col ant-col-2">
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Grid should render Row 1`] = `<div class="ant-row"></div>`;
|
||||
exports[`Grid should render Row 1`] = `
|
||||
<div class="ant-row">
|
||||
<!---->
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -121,7 +121,7 @@ describe('message', () => {
|
|||
}, 0);
|
||||
});
|
||||
it('should allow custom icon', async () => {
|
||||
message.open({ content: 'Message', icon: () => <SmileOutlined /> }); // eslint-disable-line
|
||||
message.open({ content: 'Message', icon: <SmileOutlined /> });
|
||||
await asyncExpect(() => {
|
||||
expect(document.querySelectorAll('.anticon-smile').length).toBe(1);
|
||||
}, 0);
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
import { Circle as VCCircle } from '../vc-progress';
|
||||
import { validProgress } from './utils';
|
||||
|
||||
const statusColorMap = {
|
||||
normal: '#108ee9',
|
||||
exception: '#ff5500',
|
||||
success: '#87d068',
|
||||
};
|
||||
|
||||
function getPercentage({ percent, successPercent }) {
|
||||
const ptg = validProgress(percent);
|
||||
if (!successPercent) return ptg;
|
||||
|
||||
const successPtg = validProgress(successPercent);
|
||||
return [successPercent, validProgress(ptg - successPtg)];
|
||||
}
|
||||
|
||||
function getStrokeColor({ progressStatus, successPercent, strokeColor }) {
|
||||
const color = strokeColor || statusColorMap[progressStatus];
|
||||
if (!successPercent) return color;
|
||||
return [statusColorMap.success, color];
|
||||
}
|
||||
|
||||
const Circle = (_, { attrs, slots }) => {
|
||||
const {
|
||||
prefixCls,
|
||||
width,
|
||||
strokeWidth,
|
||||
trailColor,
|
||||
strokeLinecap,
|
||||
gapPosition,
|
||||
gapDegree,
|
||||
type,
|
||||
} = attrs;
|
||||
const circleSize = width || 120;
|
||||
const circleStyle = {
|
||||
width: typeof circleSize === 'number' ? `${circleSize}px` : circleSize,
|
||||
height: typeof circleSize === 'number' ? `${circleSize}px` : circleSize,
|
||||
fontSize: `${circleSize * 0.15 + 6}px`,
|
||||
};
|
||||
const circleWidth = strokeWidth || 6;
|
||||
const gapPos = gapPosition || (type === 'dashboard' && 'bottom') || 'top';
|
||||
const gapDeg = gapDegree || (type === 'dashboard' && 75);
|
||||
const strokeColor = getStrokeColor(attrs);
|
||||
const isGradient = Object.prototype.toString.call(strokeColor) === '[object Object]';
|
||||
|
||||
const wrapperClassName = {
|
||||
[`${prefixCls}-inner`]: true,
|
||||
[`${prefixCls}-circle-gradient`]: isGradient,
|
||||
};
|
||||
|
||||
return (
|
||||
<div class={wrapperClassName} style={circleStyle}>
|
||||
<VCCircle
|
||||
percent={getPercentage(attrs)}
|
||||
strokeWidth={circleWidth}
|
||||
trailWidth={circleWidth}
|
||||
strokeColor={strokeColor}
|
||||
strokeLinecap={strokeLinecap}
|
||||
trailColor={trailColor}
|
||||
prefixCls={prefixCls}
|
||||
gapDegree={gapDeg}
|
||||
gapPosition={gapPos}
|
||||
/>
|
||||
{slots?.default()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Circle;
|
|
@ -0,0 +1,85 @@
|
|||
import { defineComponent, ExtractPropTypes } from 'vue';
|
||||
import { Circle as VCCircle } from '../vc-progress';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { validProgress } from './utils';
|
||||
import { ProgressProps } from './props';
|
||||
|
||||
const CircleProps = {
|
||||
...ProgressProps,
|
||||
progressStatus: PropTypes.string,
|
||||
};
|
||||
|
||||
const statusColorMap: Record<string, string> = {
|
||||
normal: '#108ee9',
|
||||
exception: '#ff5500',
|
||||
success: '#87d068',
|
||||
};
|
||||
|
||||
export type ICircleProps = ExtractPropTypes<typeof CircleProps>;
|
||||
|
||||
function getPercentage({ percent, successPercent }: ICircleProps) {
|
||||
const ptg = validProgress(percent);
|
||||
if (!successPercent) return ptg;
|
||||
|
||||
const successPtg = validProgress(successPercent);
|
||||
return [successPercent, validProgress(ptg - successPtg)];
|
||||
}
|
||||
|
||||
function getStrokeColor({ progressStatus, successPercent, strokeColor }: ICircleProps) {
|
||||
const color = strokeColor || statusColorMap[progressStatus];
|
||||
if (!successPercent) return color;
|
||||
return [statusColorMap.success, color];
|
||||
}
|
||||
|
||||
const Circle = defineComponent({
|
||||
props: CircleProps,
|
||||
setup(props, { slots }) {
|
||||
return () => {
|
||||
const {
|
||||
prefixCls,
|
||||
width,
|
||||
strokeWidth,
|
||||
trailColor,
|
||||
strokeLinecap,
|
||||
gapPosition,
|
||||
gapDegree,
|
||||
type,
|
||||
} = props;
|
||||
const circleSize = width || 120;
|
||||
const circleStyle = {
|
||||
width: typeof circleSize === 'number' ? `${circleSize}px` : circleSize,
|
||||
height: typeof circleSize === 'number' ? `${circleSize}px` : circleSize,
|
||||
fontSize: `${circleSize * 0.15 + 6}px`,
|
||||
};
|
||||
const circleWidth = strokeWidth || 6;
|
||||
const gapPos = gapPosition || (type === 'dashboard' && 'bottom') || 'top';
|
||||
const gapDeg = gapDegree || (type === 'dashboard' && 75);
|
||||
const strokeColor = getStrokeColor(props);
|
||||
const isGradient = Object.prototype.toString.call(strokeColor) === '[object Object]';
|
||||
|
||||
const wrapperClassName = {
|
||||
[`${prefixCls}-inner`]: true,
|
||||
[`${prefixCls}-circle-gradient`]: isGradient,
|
||||
};
|
||||
|
||||
return (
|
||||
<div class={wrapperClassName} style={circleStyle}>
|
||||
<VCCircle
|
||||
percent={getPercentage(props)}
|
||||
strokeWidth={circleWidth}
|
||||
trailWidth={circleWidth}
|
||||
strokeColor={strokeColor}
|
||||
strokeLinecap={strokeLinecap}
|
||||
trailColor={trailColor}
|
||||
prefixCls={prefixCls}
|
||||
gapDegree={gapDeg}
|
||||
gapPosition={gapPos}
|
||||
/>
|
||||
{slots?.default()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default Circle;
|
|
@ -1,9 +1,10 @@
|
|||
import { App } from 'vue';
|
||||
import Progress from './progress';
|
||||
|
||||
export { ProgressProps } from './progress';
|
||||
export { ProgressProps } from './props';
|
||||
|
||||
/* istanbul ignore next */
|
||||
Progress.install = function(app) {
|
||||
Progress.install = function(app: App) {
|
||||
app.component(Progress.name, Progress);
|
||||
return app;
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import { inject } from 'vue';
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import classNames from '../_util/classNames';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { getOptionProps, initDefaultProps } from '../_util/props-util';
|
||||
import { getOptionProps } from '../_util/props-util';
|
||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import CloseOutlined from '@ant-design/icons-vue/CloseOutlined';
|
||||
import CheckOutlined from '@ant-design/icons-vue/CheckOutlined';
|
||||
|
@ -10,30 +10,9 @@ import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
|
|||
import Line from './line';
|
||||
import Circle from './circle';
|
||||
import { validProgress } from './utils';
|
||||
import { ProgressProps, ProgressStatuses } from './props';
|
||||
|
||||
const ProgressStatuses = ['normal', 'exception', 'active', 'success'];
|
||||
export const ProgressType = PropTypes.oneOf(['line', 'circle', 'dashboard']);
|
||||
export const ProgressSize = PropTypes.oneOf(['default', 'small']);
|
||||
|
||||
export const ProgressProps = {
|
||||
prefixCls: PropTypes.string,
|
||||
type: ProgressType,
|
||||
percent: PropTypes.number,
|
||||
successPercent: PropTypes.number,
|
||||
format: PropTypes.func,
|
||||
status: PropTypes.oneOf(ProgressStatuses),
|
||||
showInfo: PropTypes.looseBool,
|
||||
strokeWidth: PropTypes.number,
|
||||
strokeLinecap: PropTypes.oneOf(['butt', 'round', 'square']),
|
||||
strokeColor: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
trailColor: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
gapDegree: PropTypes.number,
|
||||
gapPosition: PropTypes.oneOf(['top', 'bottom', 'left', 'right']),
|
||||
size: ProgressSize,
|
||||
};
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'AProgress',
|
||||
props: initDefaultProps(ProgressProps, {
|
||||
type: 'line',
|
||||
|
@ -65,7 +44,7 @@ export default {
|
|||
}
|
||||
return status || 'normal';
|
||||
},
|
||||
renderProcessInfo(prefixCls, progressStatus) {
|
||||
renderProcessInfo(prefixCls: string, progressStatus: typeof ProgressStatuses[number]) {
|
||||
const { showInfo, format, type, percent, successPercent } = this.$props;
|
||||
if (!showInfo) return null;
|
||||
|
||||
|
@ -93,7 +72,7 @@ export default {
|
|||
render() {
|
||||
const props = getOptionProps(this);
|
||||
const { prefixCls: customizePrefixCls, size, type, showInfo } = props;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const { getPrefixCls } = this.configProvider;
|
||||
const prefixCls = getPrefixCls('progress', customizePrefixCls);
|
||||
const progressStatus = this.getProgressStatus();
|
||||
const progressInfo = this.renderProcessInfo(prefixCls, progressStatus);
|
||||
|
@ -128,4 +107,4 @@ export default {
|
|||
};
|
||||
return <div {...progressProps}>{progress}</div>;
|
||||
},
|
||||
};
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
import PropTypes from '../_util/vue-types';
|
||||
import { tuple } from '../_util/type';
|
||||
|
||||
export const ProgressStatuses = tuple('normal', 'exception', 'active', 'success');
|
||||
export const ProgressType = PropTypes.oneOf(tuple('line', 'circle', 'dashboard'));
|
||||
export const ProgressSize = PropTypes.oneOf(tuple('default', 'small'));
|
||||
|
||||
export const ProgressProps = {
|
||||
prefixCls: PropTypes.string,
|
||||
type: ProgressType,
|
||||
percent: PropTypes.number,
|
||||
successPercent: PropTypes.number,
|
||||
format: PropTypes.func,
|
||||
status: PropTypes.oneOf(ProgressStatuses),
|
||||
showInfo: PropTypes.looseBool,
|
||||
strokeWidth: PropTypes.number,
|
||||
strokeLinecap: PropTypes.oneOf(['butt', 'round', 'square']),
|
||||
strokeColor: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
trailColor: PropTypes.string,
|
||||
width: PropTypes.number,
|
||||
gapDegree: PropTypes.number,
|
||||
gapPosition: PropTypes.oneOf(tuple('top', 'bottom', 'left', 'right')),
|
||||
size: ProgressSize,
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
export function validProgress(progress) {
|
||||
export function validProgress(progress?: number) {
|
||||
if (!progress || progress < 0) {
|
||||
return 0;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import { inject, App, CSSProperties, SetupContext } from 'vue';
|
||||
import { inject, App, defineComponent, PropType } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { filterEmpty } from '../_util/props-util';
|
||||
import { defaultConfigProvider, SizeType } from '../config-provider';
|
||||
import { tuple } from '../_util/type';
|
||||
|
||||
const spaceSize = {
|
||||
small: 8,
|
||||
|
@ -8,67 +10,74 @@ const spaceSize = {
|
|||
large: 24,
|
||||
};
|
||||
|
||||
export interface SpaceProps {
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
style?: CSSProperties;
|
||||
size?: SizeType | number;
|
||||
direction?: 'horizontal' | 'vertical';
|
||||
// No `stretch` since many components do not support that.
|
||||
align?: 'start' | 'end' | 'center' | 'baseline';
|
||||
}
|
||||
const Space = defineComponent({
|
||||
name: 'ASpace',
|
||||
props: {
|
||||
prefixCls: PropTypes.string,
|
||||
size: {
|
||||
type: [String, Number] as PropType<number | SizeType>,
|
||||
},
|
||||
direction: PropTypes.oneOf(tuple('horizontal', 'vertical')),
|
||||
align: PropTypes.oneOf(tuple('start', 'end', 'center', 'baseline')),
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const configProvider = inject('configProvider', defaultConfigProvider);
|
||||
const {
|
||||
align,
|
||||
size = 'small',
|
||||
direction = 'horizontal',
|
||||
prefixCls: customizePrefixCls,
|
||||
} = props;
|
||||
|
||||
const Space = (props: SpaceProps, { slots }: SetupContext) => {
|
||||
const configProvider = inject('configProvider', defaultConfigProvider);
|
||||
const { align, size = 'small', direction = 'horizontal', prefixCls: customizePrefixCls } = props;
|
||||
const { getPrefixCls } = configProvider;
|
||||
|
||||
const { getPrefixCls } = configProvider;
|
||||
const prefixCls = getPrefixCls('space', customizePrefixCls);
|
||||
const items = filterEmpty(slots.default?.());
|
||||
const len = items.length;
|
||||
return () => {
|
||||
const prefixCls = getPrefixCls('space', customizePrefixCls);
|
||||
const items = filterEmpty(slots.default?.());
|
||||
const len = items.length;
|
||||
|
||||
if (len === 0) {
|
||||
return null;
|
||||
}
|
||||
if (len === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const mergedAlign = align === undefined && direction === 'horizontal' ? 'center' : align;
|
||||
const mergedAlign = align === undefined && direction === 'horizontal' ? 'center' : align;
|
||||
|
||||
const someSpaceClass = {
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-${direction}`]: true,
|
||||
[`${prefixCls}-align-${mergedAlign}`]: mergedAlign,
|
||||
};
|
||||
const someSpaceClass = {
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-${direction}`]: true,
|
||||
[`${prefixCls}-align-${mergedAlign}`]: mergedAlign,
|
||||
};
|
||||
|
||||
const itemClassName = `${prefixCls}-item`;
|
||||
const marginDirection = 'marginRight'; // directionConfig === 'rtl' ? 'marginLeft' : 'marginRight';
|
||||
const itemClassName = `${prefixCls}-item`;
|
||||
const marginDirection = 'marginRight'; // directionConfig === 'rtl' ? 'marginLeft' : 'marginRight';
|
||||
|
||||
return (
|
||||
<div class={someSpaceClass}>
|
||||
{items.map((child, i) => (
|
||||
<div
|
||||
class={itemClassName}
|
||||
key={`${itemClassName}-${i}`}
|
||||
style={
|
||||
i === len - 1
|
||||
? {}
|
||||
: {
|
||||
[direction === 'vertical' ? 'marginBottom' : marginDirection]:
|
||||
typeof size === 'string' ? `${spaceSize[size]}px` : `${size}px`,
|
||||
}
|
||||
}
|
||||
>
|
||||
{child}
|
||||
return (
|
||||
<div class={someSpaceClass}>
|
||||
{items.map((child, i) => (
|
||||
<div
|
||||
class={itemClassName}
|
||||
key={`${itemClassName}-${i}`}
|
||||
style={
|
||||
i === len - 1
|
||||
? {}
|
||||
: {
|
||||
[direction === 'vertical' ? 'marginBottom' : marginDirection]:
|
||||
typeof size === 'string' ? `${spaceSize[size]}px` : `${size}px`,
|
||||
}
|
||||
}
|
||||
>
|
||||
{child}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Space.displayName = 'ASpace';
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/* istanbul ignore next */
|
||||
Space.install = function(app: App) {
|
||||
app.component(Space.displayName, Space);
|
||||
app.component(Space.name, Space);
|
||||
return app;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
import { defineComponent } from 'vue';
|
||||
import moment from 'moment';
|
||||
import interopDefault from '../_util/interopDefault';
|
||||
import { initDefaultProps } from '../_util/props-util';
|
||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||
import Statistic, { StatisticProps } from './Statistic';
|
||||
import { formatCountdown } from './utils';
|
||||
import { formatCountdown, countdownValueType, FormatConfig } from './utils';
|
||||
|
||||
const REFRESH_INTERVAL = 1000 / 30;
|
||||
|
||||
function getTime(value) {
|
||||
function getTime(value?: countdownValueType) {
|
||||
return interopDefault(moment)(value).valueOf();
|
||||
}
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'AStatisticCountdown',
|
||||
props: initDefaultProps(StatisticProps, {
|
||||
format: 'HH:mm:ss',
|
||||
}),
|
||||
|
||||
created() {
|
||||
this.countdownId = undefined;
|
||||
setup() {
|
||||
return {
|
||||
countdownId: undefined,
|
||||
} as { countdownId: number };
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.syncTimer();
|
||||
},
|
||||
|
@ -46,7 +47,7 @@ export default {
|
|||
startTimer() {
|
||||
if (this.countdownId) return;
|
||||
this.countdownId = window.setInterval(() => {
|
||||
this.$refs.statistic.$forceUpdate();
|
||||
(this.$refs.statistic as any).$forceUpdate();
|
||||
this.syncTimer();
|
||||
}, REFRESH_INTERVAL);
|
||||
},
|
||||
|
@ -64,7 +65,7 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
formatCountdown({ value, config }) {
|
||||
formatCountdown({ value, config }: { value: countdownValueType; config: FormatConfig }) {
|
||||
const { format } = this.$props;
|
||||
return formatCountdown(value, { ...config, format });
|
||||
},
|
||||
|
@ -84,4 +85,4 @@ export default {
|
|||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
});
|
|
@ -1,13 +1,18 @@
|
|||
import padEnd from 'lodash-es/padEnd';
|
||||
import { createVNode } from 'vue';
|
||||
import { FunctionalComponent, VNodeTypes } from 'vue';
|
||||
import { FormatConfig, valueType } from './utils';
|
||||
|
||||
const Number = (_, { attrs }) => {
|
||||
const { value, formatter, precision, decimalSeparator, groupSeparator = '', prefixCls } = attrs;
|
||||
let valueNode;
|
||||
interface NumberProps extends FormatConfig {
|
||||
value: valueType;
|
||||
}
|
||||
|
||||
const Number: FunctionalComponent<NumberProps> = props => {
|
||||
const { value, formatter, precision, decimalSeparator, groupSeparator = '', prefixCls } = props;
|
||||
let valueNode: VNodeTypes;
|
||||
|
||||
if (typeof formatter === 'function') {
|
||||
// Customize formatter
|
||||
valueNode = formatter({ value, h: createVNode });
|
||||
valueNode = formatter({ value });
|
||||
} else {
|
||||
// Internal formatter
|
||||
const val = String(value);
|
|
@ -1,26 +1,30 @@
|
|||
import { inject } from 'vue';
|
||||
import { defineComponent, inject, PropType } from 'vue';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import { getComponent, initDefaultProps } from '../_util/props-util';
|
||||
import { getComponent } from '../_util/props-util';
|
||||
import initDefaultProps from '../_util/props-util/initDefaultProps';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import StatisticNumber from './Number';
|
||||
import { countdownValueType } from './utils';
|
||||
|
||||
export const StatisticProps = {
|
||||
prefixCls: PropTypes.string,
|
||||
decimalSeparator: PropTypes.string,
|
||||
groupSeparator: PropTypes.string,
|
||||
format: PropTypes.string,
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]),
|
||||
valueStyle: PropTypes.any,
|
||||
value: {
|
||||
type: [String, Number, Object] as PropType<countdownValueType>,
|
||||
},
|
||||
valueStyle: PropTypes.style,
|
||||
valueRender: PropTypes.any,
|
||||
formatter: PropTypes.any,
|
||||
precision: PropTypes.number,
|
||||
prefix: PropTypes.any,
|
||||
suffix: PropTypes.any,
|
||||
title: PropTypes.any,
|
||||
prefix: PropTypes.VNodeChild,
|
||||
suffix: PropTypes.VNodeChild,
|
||||
title: PropTypes.VNodeChild,
|
||||
onFinish: PropTypes.func,
|
||||
};
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'AStatistic',
|
||||
props: initDefaultProps(StatisticProps, {
|
||||
decimalSeparator: '.',
|
||||
|
@ -35,7 +39,7 @@ export default {
|
|||
|
||||
render() {
|
||||
const { prefixCls: customizePrefixCls, value = 0, valueStyle, valueRender } = this.$props;
|
||||
const getPrefixCls = this.configProvider.getPrefixCls;
|
||||
const { getPrefixCls } = this.configProvider;
|
||||
const prefixCls = getPrefixCls('statistic', customizePrefixCls);
|
||||
|
||||
const title = getComponent(this, 'title');
|
||||
|
@ -64,4 +68,4 @@ export default {
|
|||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
});
|
|
@ -1,9 +1,10 @@
|
|||
import Statistic from './Statistic';
|
||||
import Countdown from './Countdown';
|
||||
import { App } from 'vue';
|
||||
|
||||
Statistic.Countdown = Countdown;
|
||||
/* istanbul ignore next */
|
||||
Statistic.install = function(app) {
|
||||
Statistic.install = function(app: App) {
|
||||
app.component(Statistic.name, Statistic);
|
||||
app.component(Statistic.Countdown.name, Statistic.Countdown);
|
||||
return app;
|
|
@ -1,10 +1,32 @@
|
|||
import { VNodeTypes } from 'vue';
|
||||
import moment from 'moment';
|
||||
import padStart from 'lodash-es/padStart';
|
||||
|
||||
import interopDefault from '../_util/interopDefault';
|
||||
|
||||
export type valueType = number | string;
|
||||
export type countdownValueType = valueType | string;
|
||||
|
||||
export type Formatter =
|
||||
| false
|
||||
| 'number'
|
||||
| 'countdown'
|
||||
| (({ value, config }: { value: valueType; config?: FormatConfig }) => VNodeTypes);
|
||||
|
||||
export interface FormatConfig {
|
||||
formatter?: Formatter;
|
||||
decimalSeparator?: string;
|
||||
groupSeparator?: string;
|
||||
precision?: number;
|
||||
prefixCls?: string;
|
||||
}
|
||||
|
||||
export interface CountdownFormatConfig extends FormatConfig {
|
||||
format?: string;
|
||||
}
|
||||
|
||||
// Countdown
|
||||
const timeUnits = [
|
||||
const timeUnits: [string, number][] = [
|
||||
['Y', 1000 * 60 * 60 * 24 * 365], // years
|
||||
['M', 1000 * 60 * 60 * 24 * 30], // months
|
||||
['D', 1000 * 60 * 60 * 24], // days
|
||||
|
@ -14,8 +36,8 @@ const timeUnits = [
|
|||
['S', 1], // million seconds
|
||||
];
|
||||
|
||||
export function formatTimeStr(duration, format) {
|
||||
let leftDuration = duration;
|
||||
export function formatTimeStr(duration: number, format: string) {
|
||||
let leftDuration: number = duration;
|
||||
|
||||
const escapeRegex = /\[[^\]]*\]/g;
|
||||
const keepList = (format.match(escapeRegex) || []).map(str => str.slice(1, -1));
|
||||
|
@ -41,7 +63,7 @@ export function formatTimeStr(duration, format) {
|
|||
});
|
||||
}
|
||||
|
||||
export function formatCountdown(value, config) {
|
||||
export function formatCountdown(value: countdownValueType, config: CountdownFormatConfig) {
|
||||
const { format = '' } = config;
|
||||
const target = interopDefault(moment)(value).valueOf();
|
||||
const current = interopDefault(moment)().valueOf();
|
|
@ -75,7 +75,6 @@ export const BaseProps = () => ({
|
|||
|
||||
// Options
|
||||
options: PropTypes.array,
|
||||
children: PropTypes.array.def([]),
|
||||
mode: PropTypes.string,
|
||||
|
||||
// Value
|
||||
|
|
|
@ -9,7 +9,7 @@ const Item: FunctionalComponent<ItemProps> = ({ setRef }, { slots }) => {
|
|||
|
||||
return children && children.length
|
||||
? cloneVNode(children[0], {
|
||||
ref: setRef,
|
||||
ref: setRef as any,
|
||||
})
|
||||
: children;
|
||||
};
|
||||
|
@ -19,4 +19,5 @@ Item.props = {
|
|||
default: () => {},
|
||||
},
|
||||
};
|
||||
|
||||
export default Item;
|
||||
|
|
|
@ -45,7 +45,7 @@ function renderChildren<T>(
|
|||
});
|
||||
const key = getKey(item);
|
||||
return (
|
||||
<Item key={key} setRef={ele => setNodeRef(item, ele)}>
|
||||
<Item key={key} setRef={ele => setNodeRef(item, ele as HTMLElement)}>
|
||||
{node}
|
||||
</Item>
|
||||
);
|
||||
|
@ -102,7 +102,7 @@ const List = defineComponent({
|
|||
mergedData: computed(() => props.data || EMPTY_DATA) as any,
|
||||
});
|
||||
|
||||
const componentRef = ref<Element>();
|
||||
const componentRef = ref<HTMLDivElement>();
|
||||
|
||||
// =============================== Item Key ===============================
|
||||
const getKey = (item: Record<string, any>) => {
|
||||
|
@ -257,8 +257,8 @@ const List = defineComponent({
|
|||
const removeEventListener = () => {
|
||||
if (componentRef.value) {
|
||||
componentRef.value.removeEventListener('wheel', onRawWheel);
|
||||
componentRef.value.removeEventListener('DOMMouseScroll' as any, onFireFoxScroll);
|
||||
componentRef.value.removeEventListener('MozMousePixelScroll', onMozMousePixelScroll);
|
||||
componentRef.value.removeEventListener('DOMMouseScroll', onFireFoxScroll as any);
|
||||
componentRef.value.removeEventListener('MozMousePixelScroll', onMozMousePixelScroll as any);
|
||||
}
|
||||
};
|
||||
watchEffect(() => {
|
||||
|
@ -266,8 +266,8 @@ const List = defineComponent({
|
|||
if (componentRef.value) {
|
||||
removeEventListener();
|
||||
componentRef.value.addEventListener('wheel', onRawWheel);
|
||||
componentRef.value.addEventListener('DOMMouseScroll' as any, onFireFoxScroll);
|
||||
componentRef.value.addEventListener('MozMousePixelScroll', onMozMousePixelScroll);
|
||||
componentRef.value.addEventListener('DOMMouseScroll', onFireFoxScroll as any);
|
||||
componentRef.value.addEventListener('MozMousePixelScroll', onMozMousePixelScroll as any);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ const SMOOTH_PTG = 14 / 15;
|
|||
|
||||
export default function useMobileTouchMove(
|
||||
inVirtual: Ref<boolean>,
|
||||
listRef: Ref<Element | undefined>,
|
||||
listRef: Ref<HTMLDivElement | undefined>,
|
||||
callback: (offsetY: number, smoothOffset?: boolean) => boolean,
|
||||
) {
|
||||
let touched = false;
|
||||
|
|
Loading…
Reference in New Issue