44 lines
1.4 KiB
TypeScript
44 lines
1.4 KiB
TypeScript
'use client'
|
|
import type { TextFieldClientComponent } from 'payload'
|
|
import { useState } from 'react'
|
|
|
|
export const MaskedField: TextFieldClientComponent = (props: any) => {
|
|
const { field, path, value: propValue, setValue: propSetValue, onChange: propOnChange } = props || {}
|
|
const [internalValue, setInternalValue] = useState(propValue ?? '')
|
|
const [revealed, setRevealed] = useState(false)
|
|
const label = typeof field?.label === 'string' ? field.label : (field?.name ?? path)
|
|
|
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
const newVal = e.target.value
|
|
setInternalValue(newVal)
|
|
if (typeof propSetValue === 'function') {
|
|
propSetValue(newVal)
|
|
}
|
|
if (typeof propOnChange === 'function') {
|
|
propOnChange(e)
|
|
}
|
|
}
|
|
|
|
const currentValue = propValue !== undefined ? propValue : internalValue
|
|
|
|
return (
|
|
<div className="field-type text">
|
|
{label && <label className="field-label">{label}</label>}
|
|
<div style={{ display: 'flex', gap: '.5rem' }}>
|
|
<input
|
|
autoComplete="off"
|
|
onChange={handleChange}
|
|
style={{ flex: 1 }}
|
|
type={revealed ? 'text' : 'password'}
|
|
value={currentValue ?? ''}
|
|
/>
|
|
<button onClick={() => setRevealed((r) => !r)} type="button">
|
|
{revealed ? 'Hide' : 'Reveal'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default MaskedField
|