# Secret Field

> SecretField shows a stored credential without exposing it; MoneyInput takes amounts in the locale's format with a VAT rate.

Component · Forms · Pro kit · [Live page](https://ui.twentyfirst.media/pro/components/SecretField/)

`SecretField` shows a stored credential without exposing it; `MoneyInput` takes amounts in the locale's format with a VAT rate.

SecretField: `prefix`, `last4`, `value` (shown only after `onReveal` resolves truthy; ask for a passkey there), `meta`, `onCopy`, `onRotate`.
MoneyInput: `label`, `value` / `onChange(number)`, `currency`, `vat` + `onVat` + `vatOptions`, `showGross`, `hint`, `error`. Parses and formats with setLocale.

- Never render a full secret by default; reveal is a step-up action.
- Amounts are right-aligned tabular mono so columns line up.

## Example

```tsx
import * as React from "react";
import { MoneyInput, SecretField } from "@twentyfirstmedia/pro";

function App() {
  const vat = React.useState("19"),
    v = React.useState<number | null>(1240);
  return (
    <div
      className="tf-panel"
      style={{
        gap: 24,
      }}
    >
      <SecretField
        prefix="sk_live_"
        last4="4f2a"
        meta="Added Mar 12"
        onReveal={() => true}
        value="sk_live_51Hx…demo…4f2a"
        onCopy={() => {}}
        onRotate={() => {}}
      />
      <MoneyInput
        label="Amount"
        value={v[0]}
        onChange={v[1]}
        vat={vat[0]}
        onVat={vat[1]}
        vatOptions={[
          {
            value: "19",
            label: "19%",
          },
          {
            value: "7",
            label: "7%",
          },
          {
            value: "0",
            label: "0%",
          },
          {
            value: "rc",
            label: "Reverse charge",
          },
        ]}
        showGross
        hint="Net, as on the invoice"
      />
    </div>
  );
}
export default App;
```

## Props

### MoneyInput

| Prop | Type | Notes |
| --- | --- | --- |
| `label?` | `string` |  |
| `value?` | `number \| null` |  |
| `onChange?` | `(v: number \| null) => void` |  |
| `currency?` | `string` |  |
| `vat?` | `string` |  |
| `onVat?` | `(v: string) => void` |  |
| `vatOptions?` | `{ value: string; label: string; rate?: number }[]` |  |
| `showGross?` | `boolean` |  |
| `hint?` | `ReactNode` |  |
| `error?` | `ReactNode` |  |
| `defaultValue?` | `number \| null` |  |
| `required?` | `boolean` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### SecretField

| Prop | Type | Notes |
| --- | --- | --- |
| `prefix?` | `string` |  |
| `last4?` | `string` |  |
| `value?` | `string` |  |
| `meta?` | `ReactNode` |  |
| `onReveal?` | `() => boolean \| Promise<boolean>` |  |
| `onCopy?` | `() => void` |  |
| `onRotate?` | `() => void` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |
