index.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { use, isDef } from '../utils';
  2. import { cellProps, SharedCellProps } from './shared';
  3. import { emit, inherit } from '../utils/functional';
  4. import { routeProps, RouteProps, functionalRoute } from '../utils/router';
  5. import Icon from '../icon';
  6. // Types
  7. import { CreateElement, RenderContext } from 'vue/types';
  8. import { ScopedSlot, DefaultSlots } from '../utils/use/sfc';
  9. import { Mods } from '../utils/use/bem';
  10. export type CellProps = RouteProps &
  11. SharedCellProps & {
  12. clickable?: boolean;
  13. arrowDirection?: string;
  14. };
  15. export type CellSlots = DefaultSlots & {
  16. icon?: ScopedSlot;
  17. title?: ScopedSlot;
  18. label?: ScopedSlot;
  19. extra?: ScopedSlot;
  20. 'right-icon'?: ScopedSlot;
  21. };
  22. export type CellEvents = {
  23. onClick?(event: Event): void;
  24. };
  25. const [sfc, bem] = use('cell');
  26. function Cell(
  27. h: CreateElement,
  28. props: CellProps,
  29. slots: CellSlots,
  30. ctx: RenderContext<CellProps>
  31. ) {
  32. const { icon, size, title, label, value, isLink, arrowDirection } = props;
  33. const showTitle = slots.title || isDef(title);
  34. const showValue = slots.default || isDef(value);
  35. const showLabel = slots.label || isDef(label);
  36. const Label = showLabel && (
  37. <div class={[bem('label'), props.labelClass]}>
  38. {slots.label ? slots.label() : label}
  39. </div>
  40. );
  41. const Title = showTitle && (
  42. <div class={[bem('title'), props.titleClass]} style={props.titleStyle}>
  43. {slots.title ? slots.title() : <span>{title}</span>}
  44. {Label}
  45. </div>
  46. );
  47. const Value = showValue && (
  48. <div class={[bem('value', { alone: !slots.title && !title }), props.valueClass]}>
  49. {slots.default ? slots.default() : <span>{value}</span>}
  50. </div>
  51. );
  52. const LeftIcon = slots.icon
  53. ? slots.icon()
  54. : icon && <Icon class={bem('left-icon')} name={icon} />;
  55. const rightIconSlot = slots['right-icon'];
  56. const RightIcon = rightIconSlot
  57. ? rightIconSlot()
  58. : isLink && (
  59. <Icon
  60. class={bem('right-icon')}
  61. name={arrowDirection ? `arrow-${arrowDirection}` : 'arrow'}
  62. />
  63. );
  64. const onClick = (event: Event) => {
  65. emit(ctx, 'click', event);
  66. functionalRoute(ctx);
  67. };
  68. const classes: Mods = {
  69. center: props.center,
  70. required: props.required,
  71. borderless: !props.border,
  72. clickable: isLink || props.clickable
  73. };
  74. if (size) {
  75. classes[size] = size;
  76. }
  77. return (
  78. <div class={bem(classes)} onClick={onClick} {...inherit(ctx)}>
  79. {LeftIcon}
  80. {Title}
  81. {Value}
  82. {RightIcon}
  83. {slots.extra && slots.extra()}
  84. </div>
  85. );
  86. }
  87. Cell.props = {
  88. ...cellProps,
  89. ...routeProps,
  90. clickable: Boolean,
  91. arrowDirection: String
  92. };
  93. export default sfc<CellProps, CellEvents, CellSlots>(Cell);