Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | 3x 3x 1x 15x 15x 15x 15x 13x 4x 1x 3x 3x 1x 3x 3x 3x 3x 1x 1x 1x 15x 15x 12x 15x 1x 15x 1x 15x 15x 15x 4x 15x 1x | import React from 'react'; import { useRef, useEffect, useState } from 'react'; const validHex = (hex: string): boolean => /^#?([A-Fa-f0-9]{3,4}){1,2}$/.test(hex); const getNumberValue = (value: string) => Number(String(value).replace(/%/g, '')); export interface EditableInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> { prefixCls?: string; value?: string | number; label?: React.ReactNode; labelStyle?: React.CSSProperties; placement?: 'top' | 'left' | 'bottom' | 'right'; inputStyle?: React.CSSProperties; onChange?: (evn: React.ChangeEvent<HTMLInputElement>, value: string | number) => void; renderInput?: (props: React.InputHTMLAttributes<HTMLInputElement>, ref: React.Ref<HTMLInputElement>) => React.ReactNode; } const EditableInput = React.forwardRef<HTMLInputElement, EditableInputProps>((props, ref) => { const { prefixCls = 'w-color-editable-input', placement = 'bottom', label, value: initValue, className, style, labelStyle, inputStyle, onChange, onBlur, renderInput, ...other } = props; const [value, setValue] = useState<string | number | undefined>(initValue); const isFocus = useRef(false); useEffect(() => { if (props.value !== value) { if (!isFocus.current) { setValue(props.value); } } }, [props.value]); function handleChange(evn: React.FocusEvent<HTMLInputElement>, valInit?: string) { const value = (valInit || evn.target.value).trim().replace(/^#/, ''); if (validHex(value)) { onChange && onChange(evn, value); } const val = getNumberValue(value); Eif (!isNaN(val)) { onChange && onChange(evn, val); } setValue(value); } function handleBlur(evn: React.FocusEvent<HTMLInputElement>) { isFocus.current = false; setValue(props.value); onBlur && onBlur(evn); } const placementStyle: React.CSSProperties = {}; if (placement === 'bottom') { placementStyle['flexDirection'] = 'column'; } if (placement === 'top') { placementStyle['flexDirection'] = 'column-reverse'; } if (placement === 'left') { placementStyle['flexDirection'] = 'row-reverse'; } const wrapperStyle = { '--editable-input-label-color': 'rgb(153, 153, 153)', '--editable-input-box-shadow': 'rgb(204 204 204) 0px 0px 0px 1px inset', '--editable-input-color': '#666', position: 'relative', alignItems: 'center', display: 'flex', fontSize: 11, ...placementStyle, ...style, } as React.CSSProperties; const editableStyle = { width: '100%', paddingTop: 2, paddingBottom: 2, paddingLeft: 3, paddingRight: 3, fontSize: 11, background: 'transparent', boxSizing: 'border-box', border: 'none', color: 'var(--editable-input-color)', boxShadow: 'var(--editable-input-box-shadow)', ...inputStyle, } as React.CSSProperties; const inputProps: React.InputHTMLAttributes<HTMLInputElement> = { value, onChange: handleChange, onBlur: handleBlur, autoComplete: 'off', onFocus: () => (isFocus.current = true), ...other, style: editableStyle, }; return ( <div className={[prefixCls, className || ''].filter(Boolean).join(' ')} style={wrapperStyle}> {renderInput ? renderInput(inputProps, ref) : <input ref={ref} {...inputProps} />} {label && ( <span style={{ color: 'var(--editable-input-label-color)', textTransform: 'capitalize', ...labelStyle, }} children={label} /> )} </div> ); }); EditableInput.displayName = 'EditableInput'; export default EditableInput; |