index.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { use } from '../utils';
  2. import { emit, inherit } from '../utils/functional';
  3. import { routeProps, RouteProps, functionalRoute } from '../utils/router';
  4. import Loading from '../loading';
  5. // Types
  6. import { CreateElement, RenderContext } from 'vue/types';
  7. import { DefaultSlots } from '../utils/use/sfc';
  8. export type ButtonType = 'default' | 'primary' | 'info' | 'warning' | 'danger';
  9. export type ButtonSize = 'large' | 'normal' | 'small' | 'mini';
  10. export type ButtonProps = RouteProps & {
  11. tag: keyof HTMLElementTagNameMap | string;
  12. type: ButtonType;
  13. size: ButtonSize;
  14. text?: string;
  15. block?: boolean;
  16. plain?: boolean;
  17. round?: boolean;
  18. square?: boolean;
  19. loading?: boolean;
  20. hairline?: boolean;
  21. disabled?: boolean;
  22. nativeType?: string;
  23. loadingSize: string;
  24. loadingText?: string;
  25. bottomAction?: boolean;
  26. };
  27. export type ButtonEvents = {
  28. onClick?(event: Event): void;
  29. };
  30. const [sfc, bem] = use('button');
  31. function Button(
  32. h: CreateElement,
  33. props: ButtonProps,
  34. slots: DefaultSlots,
  35. ctx: RenderContext<ButtonProps>
  36. ) {
  37. const { tag, type, disabled, loading, hairline, loadingText } = props;
  38. const onClick = (event: Event) => {
  39. if (!loading && !disabled) {
  40. emit(ctx, 'click', event);
  41. functionalRoute(ctx);
  42. }
  43. };
  44. const onTouchstart = (event: TouchEvent) => {
  45. emit(ctx, 'touchstart', event);
  46. };
  47. const classes = [
  48. bem([
  49. type,
  50. props.size,
  51. {
  52. loading,
  53. disabled,
  54. hairline,
  55. block: props.block,
  56. plain: props.plain,
  57. round: props.round,
  58. square: props.square,
  59. 'bottom-action': props.bottomAction
  60. }
  61. ]),
  62. { 'van-hairline--surround': hairline }
  63. ];
  64. return (
  65. <tag
  66. class={classes}
  67. type={props.nativeType}
  68. disabled={disabled}
  69. onClick={onClick}
  70. onTouchstart={onTouchstart}
  71. {...inherit(ctx)}
  72. >
  73. {loading ? (
  74. [
  75. <Loading
  76. size={props.loadingSize}
  77. color={type === 'default' ? undefined : ''}
  78. />,
  79. loadingText && <span class={bem('loading-text')}>{loadingText}</span>
  80. ]
  81. ) : (
  82. <span class={bem('text')}>{slots.default ? slots.default() : props.text}</span>
  83. )}
  84. </tag>
  85. );
  86. }
  87. Button.props = {
  88. ...routeProps,
  89. text: String,
  90. block: Boolean,
  91. plain: Boolean,
  92. round: Boolean,
  93. square: Boolean,
  94. loading: Boolean,
  95. hairline: Boolean,
  96. disabled: Boolean,
  97. nativeType: String,
  98. loadingText: String,
  99. bottomAction: Boolean,
  100. tag: {
  101. type: String,
  102. default: 'button'
  103. },
  104. type: {
  105. type: String,
  106. default: 'default'
  107. },
  108. size: {
  109. type: String,
  110. default: 'normal'
  111. },
  112. loadingSize: {
  113. type: String,
  114. default: '20px'
  115. }
  116. };
  117. export default sfc<ButtonProps, ButtonEvents>(Button);