or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

base-component.mdindex.mdnumeric-formatting.mdpattern-formatting.mdreact-hooks.mdutility-functions.md

base-component.mddocs/

0

# Base Component System

1

2

Core component providing customizable formatting functionality that both NumericFormat and PatternFormat extend. Use NumberFormatBase when you need complete control over formatting logic or want to create custom formatting behaviors.

3

4

## Capabilities

5

6

### NumberFormatBase Component

7

8

The foundational component that provides the core formatting infrastructure with customizable format and removeFormatting functions.

9

10

```typescript { .api }

11

/**

12

* Base component providing core formatting functionality

13

* @param props - Configuration options for base formatting behavior

14

* @returns React element with customizable formatting logic

15

*/

16

function NumberFormatBase<BaseType = InputAttributes>(

17

props: NumberFormatBaseProps<BaseType>

18

): React.ReactElement;

19

20

interface NumberFormatBaseProps<BaseType = InputAttributes> {

21

/** Input type attribute */

22

type?: 'text' | 'tel' | 'password';

23

/** Whether to render as input or text display */

24

displayType?: 'input' | 'text';

25

/** Input mode for mobile keyboards */

26

inputMode?: InputAttributes['inputMode'];

27

/** Custom component to render instead of default input */

28

customInput?: React.ComponentType<BaseType>;

29

/** Custom render function for text display mode */

30

renderText?: (formattedValue: string, otherProps: Partial<NumberFormatBaseProps>) => React.ReactNode;

31

/** Function to format input values for display */

32

format?: (inputValue: string) => string;

33

/** Function to remove formatting and extract raw value */

34

removeFormatting?: (inputValue: string, changeMeta?: ChangeMeta) => string;

35

/** Ref callback or ref object for the input element */

36

getInputRef?: ((el: HTMLInputElement) => void) | React.Ref<any>;

37

/** Current value of the input */

38

value?: number | string | null;

39

/** Default value for uncontrolled usage */

40

defaultValue?: number | string | null;

41

/** Whether the value prop should be treated as numeric string */

42

valueIsNumericString?: boolean;

43

/** Callback when value changes with formatted and raw values */

44

onValueChange?: OnValueChange;

45

/** Function to validate if new values should be allowed */

46

isAllowed?: (values: NumberFormatValues) => boolean;

47

/** Function to determine valid caret positions */

48

getCaretBoundary?: (formattedValue: string) => boolean[];

49

/** Function to validate individual input characters */

50

isValidInputCharacter?: (character: string) => boolean;

51

/** Function to determine if characters at different positions represent the same logical character */

52

isCharacterSame?: IsCharacterSame;

53

/** Standard input event handlers */

54

onKeyDown?: InputAttributes['onKeyDown'];

55

onMouseUp?: InputAttributes['onMouseUp'];

56

onChange?: InputAttributes['onChange'];

57

onFocus?: InputAttributes['onFocus'];

58

onBlur?: InputAttributes['onBlur'];

59

}

60

```

61

62

**Usage Examples:**

63

64

```typescript

65

import React from "react";

66

import { NumberFormatBase } from "react-number-format";

67

68

// Custom hex color input

69

function HexColorInput({ value, onChange }) {

70

const formatHex = (inputValue: string) => {

71

const hex = inputValue.replace(/[^0-9A-Fa-f]/g, '').slice(0, 6);

72

return `#${hex.toUpperCase()}`;

73

};

74

75

const removeHexFormatting = (inputValue: string) => {

76

return inputValue.replace('#', '').replace(/[^0-9A-Fa-f]/g, '');

77

};

78

79

const validateHex = (character: string) => {

80

return /[0-9A-Fa-f]/.test(character);

81

};

82

83

return (

84

<NumberFormatBase

85

value={value}

86

format={formatHex}

87

removeFormatting={removeHexFormatting}

88

isValidInputCharacter={validateHex}

89

onValueChange={(values) => onChange(values.value)}

90

placeholder="#000000"

91

maxLength={7}

92

/>

93

);

94

}

95

96

// Custom uppercase text input

97

function UppercaseInput({ value, onChange }) {

98

return (

99

<NumberFormatBase

100

value={value}

101

format={(inputValue) => inputValue.toUpperCase()}

102

removeFormatting={(inputValue) => inputValue.toUpperCase()}

103

onValueChange={(values) => onChange(values.value)}

104

isAllowed={(values) => {

105

// Only allow alphabetic characters

106

return /^[A-Z]*$/.test(values.value);

107

}}

108

/>

109

);

110

}

111

112

// Custom input with Material-UI integration

113

function MaterialNumberInput({ value, onChange, ...props }) {

114

return (

115

<NumberFormatBase

116

{...props}

117

value={value}

118

onValueChange={(values) => onChange(values.floatValue)}

119

customInput={TextField} // Material-UI TextField

120

format={(value) => value} // No formatting

121

removeFormatting={(value) => value.replace(/[^0-9.-]/g, '')}

122

isValidInputCharacter={(char) => /[0-9.-]/.test(char)}

123

/>

124

);

125

}

126

```

127

128

### Display Type Options

129

130

NumberFormatBase supports both input and text display modes:

131

132

```typescript

133

// Input mode (default) - renders interactive input

134

<NumberFormatBase

135

displayType="input"

136

value="123.45"

137

format={(value) => `$${value}`}

138

/>

139

140

// Text mode - renders formatted text

141

<NumberFormatBase

142

displayType="text"

143

value="123.45"

144

format={(value) => `$${value}`}

145

renderText={(formattedValue, props) => (

146

<span className="currency" {...props}>

147

{formattedValue}

148

</span>

149

)}

150

/>

151

```

152

153

### Custom Input Components

154

155

Integrate with UI libraries and custom components:

156

157

```typescript

158

import { TextField } from '@mui/material';

159

import { Input } from 'antd';

160

161

// Material-UI integration

162

<NumberFormatBase

163

customInput={TextField}

164

format={formatFunction}

165

removeFormatting={removeFunction}

166

// TextField props

167

label="Amount"

168

variant="outlined"

169

size="small"

170

/>

171

172

// Ant Design integration

173

<NumberFormatBase

174

customInput={Input}

175

format={formatFunction}

176

removeFormatting={removeFunction}

177

// Input props

178

size="large"

179

prefix={<DollarOutlined />}

180

/>

181

182

// Custom styled component

183

const StyledInput = (props) => (

184

<input {...props} className="custom-formatted-input" />

185

);

186

187

<NumberFormatBase

188

customInput={StyledInput}

189

format={formatFunction}

190

removeFormatting={removeFunction}

191

/>

192

```

193

194

### Value Change Handling

195

196

The onValueChange callback provides comprehensive information about value changes:

197

198

```typescript { .api }

199

type OnValueChange = (values: NumberFormatValues, sourceInfo: SourceInfo) => void;

200

201

interface NumberFormatValues {

202

/** Parsed numeric value (undefined if not a valid number) */

203

floatValue: number | undefined;

204

/** Formatted display value */

205

formattedValue: string;

206

/** Raw input value without formatting */

207

value: string;

208

}

209

210

interface SourceInfo {

211

/** The DOM event that triggered the change (if applicable) */

212

event?: React.SyntheticEvent<HTMLInputElement>;

213

/** Whether change came from user input or props update */

214

source: 'event' | 'prop';

215

}

216

```

217

218

**Usage Examples:**

219

220

```typescript

221

function AdvancedInput({ onChange, onValidation }) {

222

const handleValueChange = (values, sourceInfo) => {

223

const { floatValue, formattedValue, value } = values;

224

const { event, source } = sourceInfo;

225

226

// Handle different value representations

227

onChange({

228

numeric: floatValue,

229

formatted: formattedValue,

230

raw: value

231

});

232

233

// Provide validation feedback

234

const isValid = floatValue !== undefined && floatValue > 0;

235

onValidation(isValid);

236

237

// Log changes from user input

238

if (source === 'event') {

239

console.log('User entered:', value);

240

}

241

};

242

243

return (

244

<NumberFormatBase

245

onValueChange={handleValueChange}

246

format={(value) => `$${value}`}

247

removeFormatting={(value) => value.replace('$', '')}

248

/>

249

);

250

}

251

```

252

253

### Validation and Filtering

254

255

Control what input is allowed with validation functions:

256

257

```typescript

258

// Restrict to positive numbers only

259

<NumberFormatBase

260

isAllowed={(values) => {

261

const { floatValue } = values;

262

return floatValue === undefined || floatValue >= 0;

263

}}

264

format={(value) => value}

265

removeFormatting={(value) => value}

266

/>

267

268

// Limit character input

269

<NumberFormatBase

270

isValidInputCharacter={(char) => /[0-9.]/.test(char)}

271

format={(value) => value}

272

removeFormatting={(value) => value}

273

/>

274

275

// Complex validation with error handling

276

function ValidatedInput({ max = 1000 }) {

277

const [error, setError] = useState('');

278

279

return (

280

<div>

281

<NumberFormatBase

282

isAllowed={(values) => {

283

const { floatValue } = values;

284

if (floatValue === undefined) return true;

285

286

if (floatValue > max) {

287

setError(`Value cannot exceed ${max}`);

288

return false;

289

}

290

291

setError('');

292

return true;

293

}}

294

format={(value) => value}

295

removeFormatting={(value) => value}

296

/>

297

{error && <div className="error">{error}</div>}

298

</div>

299

);

300

}

301

```

302

303

### Caret Positioning Control

304

305

Control cursor behavior with caret boundary functions:

306

307

```typescript { .api }

308

/**

309

* Function to determine valid caret positions

310

* @param formattedValue - The current formatted display value

311

* @returns Array of booleans where true indicates valid caret position

312

*/

313

type GetCaretBoundary = (formattedValue: string) => boolean[];

314

```

315

316

**Usage Examples:**

317

318

```typescript

319

// Only allow cursor in numeric positions of "$ 123.45"

320

function CurrencyCaretBoundary(formattedValue: string): boolean[] {

321

return formattedValue.split('').map((char, index) => {

322

// Allow cursor after $ and space, and at numeric positions

323

return index >= 2 || /[0-9.]/.test(char);

324

});

325

}

326

327

<NumberFormatBase

328

format={(value) => `$ ${value}`}

329

removeFormatting={(value) => value.replace(/[$ ]/g, '')}

330

getCaretBoundary={CurrencyCaretBoundary}

331

/>

332

```

333

334

### Character Comparison Logic

335

336

Define how characters are compared during formatting:

337

338

```typescript { .api }

339

/**

340

* Function to determine if characters represent the same logical value

341

*/

342

type IsCharacterSame = (compareProps: {

343

currentValue: string;

344

lastValue: string;

345

formattedValue: string;

346

currentValueIndex: number;

347

formattedValueIndex: number;

348

}) => boolean;

349

```

350

351

This is useful for advanced scenarios where logical characters might be represented differently in formatted vs unformatted states.