packages/form-render/src/widgets/fields/percentSlider/index.tsx (77 lines of code) (raw):

import * as React from 'react'; import { InputNumber, Slider } from 'antd'; interface Props { schema: { max?: number; min?: number; step?: number; }; options?: { hideNumber?: boolean; }; value: string; onChange: (value: string) => void; disabled?: boolean; readonly?: boolean; } const PercentSlider: React.FC<Props> = (p) => { const { max, min, step } = p.schema; let setting: { max?: number; min?: number; step?: number } = {}; if (max || max === 0) { setting = { max }; } if (min || min === 0) { setting = { ...setting, min }; } if (step) { setting = { ...setting, step }; } let hideNumber = false; if (p.options && p.options.hideNumber) { hideNumber = true; } const isPercent = (string: string): boolean => typeof string === 'string' && string.endsWith('%'); let numberValue = 100; if (isPercent(p.value)) { try { numberValue = Number(p.value.split('%')[0]); if (Number.isNaN(numberValue)) numberValue = 100; } catch (error) {} } const handleChange = (newNumber: number | undefined): void => { const a = newNumber + '%'; p.onChange(a); }; const renderNumber = p.readonly ? ( <span style={{ width: '80px' }}> {p.value === (undefined || '') ? '-' : p.value + '%'} </span> ) : ( <InputNumber {...p.options} {...setting} style={{ width: '80px' }} value={numberValue} disabled={p.disabled} onChange={handleChange} formatter={(value) => `${value}%`} parser={(value) => Number(value.replace('%', ''))} /> ); return ( <div className="fr-slider"> <Slider style={{ flexGrow: 1, marginRight: hideNumber ? 0 : 12 }} {...setting} onChange={handleChange} max={100} tooltip={{ formatter: (v) => v + '%' }} value={numberValue || 100} disabled={p.disabled || p.readonly} /> {hideNumber ? null : renderNumber} </div> ); }; export default PercentSlider;