您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

Slider.web.tsx 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import React from 'react';
  2. import { makeStyles } from 'tss-react/mui';
  3. interface IProps {
  4. /**
  5. * The 'aria-label' text.
  6. */
  7. ariaLabel: string;
  8. /**
  9. * The maximum value for slider value.
  10. */
  11. max: number;
  12. /**
  13. * The minimum value for slider value.
  14. */
  15. min: number;
  16. /**
  17. * Callback invoked on change.
  18. */
  19. onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  20. /**
  21. * The granularity that the value must adhere to.
  22. */
  23. step: number;
  24. /**
  25. * The current value where the knob is positioned.
  26. */
  27. value: number;
  28. }
  29. const useStyles = makeStyles()(theme => {
  30. // keep the same height for all elements:
  31. // input, input track & fake track(div)
  32. const height = 6;
  33. const inputTrack = {
  34. background: 'transparent',
  35. height
  36. };
  37. const inputThumb = {
  38. background: theme.palette.text01,
  39. border: 0,
  40. borderRadius: '50%',
  41. height: 24,
  42. width: 24
  43. };
  44. const focused = { // @ts-ignore
  45. outline: `1px solid ${theme.palette.action03Focus}`
  46. };
  47. return {
  48. sliderContainer: {
  49. cursor: 'pointer',
  50. width: '100%',
  51. position: 'relative',
  52. textAlign: 'center'
  53. },
  54. knobContainer: {
  55. display: 'flex',
  56. justifyContent: 'space-between',
  57. marginLeft: 2,
  58. marginRight: 2,
  59. position: 'absolute',
  60. width: '100%'
  61. },
  62. knob: {
  63. background: theme.palette.text01,
  64. borderRadius: '50%',
  65. display: 'inline-block',
  66. height,
  67. width: 6
  68. },
  69. track: {
  70. background: theme.palette.ui02,
  71. borderRadius: Number(theme.shape.borderRadius) / 2,
  72. height
  73. },
  74. slider: {
  75. // Use an additional class here to override global CSS specificity
  76. '&.custom-slider': {
  77. '-webkit-appearance': 'none',
  78. background: 'transparent',
  79. height,
  80. left: 0,
  81. position: 'absolute',
  82. top: 0,
  83. width: '100%',
  84. '&:focus': {
  85. // override global styles in order to use our own color
  86. outline: 'none !important',
  87. '&::-webkit-slider-runnable-track': focused,
  88. '&::ms-track': focused,
  89. '&::-moz-range-track': focused
  90. },
  91. '&::-webkit-slider-runnable-track': {
  92. '-webkit-appearance': 'none',
  93. ...inputTrack
  94. },
  95. '&::-webkit-slider-thumb': {
  96. '-webkit-appearance': 'none',
  97. position: 'relative',
  98. top: -6,
  99. ...inputThumb
  100. },
  101. '&::ms-track': {
  102. ...inputTrack
  103. },
  104. '&::-ms-thumb': {
  105. ...inputThumb
  106. },
  107. '&::-moz-range-track': {
  108. ...inputTrack
  109. },
  110. '&::-moz-range-thumb': {
  111. ...inputThumb
  112. }
  113. }
  114. }
  115. };
  116. });
  117. /**
  118. * Custom slider.
  119. *
  120. * @returns {ReactElement}
  121. */
  122. function Slider({ ariaLabel, max, min, onChange, step, value }: IProps) {
  123. const { classes, cx } = useStyles();
  124. const knobs = [ ...Array(Math.floor((max - min) / step) + 1) ];
  125. return (
  126. <div className = { classes.sliderContainer }>
  127. <ul className = { cx('empty-list', classes.knobContainer) }>
  128. {knobs.map((_, i) => (
  129. <li
  130. className = { classes.knob }
  131. key = { `knob-${i}` } />))}
  132. </ul>
  133. <div className = { classes.track } />
  134. <input
  135. aria-label = { ariaLabel }
  136. className = { cx(classes.slider, 'custom-slider') }
  137. max = { max }
  138. min = { min }
  139. onChange = { onChange }
  140. step = { step }
  141. type = 'range'
  142. value = { value } />
  143. </div>
  144. );
  145. }
  146. export default Slider;