增加一个用于拣选数值的滑杆组件。
This commit is contained in:
		
							
								
								
									
										23
									
								
								src/components/LabeledPicker.module.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/components/LabeledPicker.module.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| @layer components { | ||||
|   .labeled_picker { | ||||
|     width: 100%; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     align-items: stretch; | ||||
|     gap: var(--spacing-xs); | ||||
|     .title_row { | ||||
|       width: 100%; | ||||
|       display: flex; | ||||
|       flex-direction: row; | ||||
|       align-items: baseline; | ||||
|       label { | ||||
|         flex: 1; | ||||
|         font-size: var(--font-size-xs); | ||||
|       } | ||||
|       & > span { | ||||
|         text-align: right; | ||||
|         font-size: var(--font-size-xs); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										58
									
								
								src/components/LabeledPicker.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/components/LabeledPicker.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| import cx from 'clsx'; | ||||
| import { isEqual, isNil } from 'lodash-es'; | ||||
| import { useEffect, useState } from 'react'; | ||||
| import styles from './LabeledPicker.module.css'; | ||||
|  | ||||
| type LabeledPickerProps = { | ||||
|   title?: string; | ||||
|   value?: number; | ||||
|   unit?: string; | ||||
|   onChange: (value: number) => void; | ||||
|   min?: number; | ||||
|   max?: number; | ||||
|   step?: number; | ||||
| }; | ||||
|  | ||||
| export function LabeledPicker({ | ||||
|   title, | ||||
|   value, | ||||
|   unit, | ||||
|   onChange, | ||||
|   min = 0, | ||||
|   max = 100, | ||||
|   step = 1, | ||||
| }: LabeledPickerProps) { | ||||
|   const [pickerValue, setPickerValue] = useState(value ?? min); | ||||
|   const handlePickerChange = (event: React.ChangeEvent<HTMLInputElement>) => { | ||||
|     const value = event.target.value as number; | ||||
|     setPickerValue(value); | ||||
|     onChange?.(value); | ||||
|   }; | ||||
|  | ||||
|   useEffect(() => { | ||||
|     if (!isEqual(value, pickerValue)) { | ||||
|       setPickerValue(value); | ||||
|     } | ||||
|   }, [value]); | ||||
|  | ||||
|   return ( | ||||
|     <div className={styles.labeled_picker}> | ||||
|       <div className={styles.title_row}> | ||||
|         {!isNil(title) && <label>{title}</label>} | ||||
|         <div className="spacer" /> | ||||
|         <span> | ||||
|           {pickerValue} {unit} | ||||
|         </span> | ||||
|       </div> | ||||
|       <input | ||||
|         type="range" | ||||
|         className={cx('picker')} | ||||
|         value={pickerValue} | ||||
|         onChange={handlePickerChange} | ||||
|         min={min} | ||||
|         max={max} | ||||
|         step={step} | ||||
|       /> | ||||
|     </div> | ||||
|   ); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user