or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

calendar-components.mdcalendar-controllers.mdindex.mdinput-components.mdmain-pickers.mdutilities.md

input-components.mddocs/

0

# Input Components

1

2

Standalone input field components for custom layouts and advanced use cases. These components handle date input, validation, and formatting without the calendar interface, allowing you to build custom date picker experiences.

3

4

## Capabilities

5

6

### DateRangePickerInput

7

8

Input fields component for date range display and manual entry, providing dual input fields for start and end dates.

9

10

```jsx { .api }

11

/**

12

* Date range input fields without calendar

13

* @param props - DateRangePickerInput configuration

14

* @returns Input fields for date range entry

15

*/

16

function DateRangePickerInput(props: DateRangePickerInputProps): ReactElement;

17

18

interface DateRangePickerInputProps {

19

// Input field IDs (required)

20

startDateId: string;

21

endDateId: string;

22

23

// Display values

24

startDate?: string;

25

endDate?: string;

26

startDatePlaceholderText?: string;

27

endDatePlaceholderText?: string;

28

29

// State

30

isStartDateFocused?: boolean;

31

isEndDateFocused?: boolean;

32

isFocused?: boolean; // Actual DOM focus state

33

disabled?: boolean;

34

required?: boolean;

35

readOnly?: boolean;

36

showClearDates?: boolean;

37

showCaret?: boolean; // Show caret indicator

38

39

// Styling

40

noBorder?: boolean;

41

block?: boolean;

42

small?: boolean;

43

regular?: boolean;

44

isRTL?: boolean; // Right-to-left layout support

45

46

// Layout

47

openDirection?: 'up' | 'down'; // Direction to open calendar overlay

48

verticalSpacing?: number; // Vertical spacing in pixels (non-negative integer)

49

50

// Icons

51

showDefaultInputIcon?: boolean;

52

inputIconPosition?: 'before' | 'after';

53

customInputIcon?: ReactNode;

54

customArrowIcon?: ReactNode;

55

customCloseIcon?: ReactNode;

56

57

// Event handlers

58

onStartDateChange?: (dateString: string) => void;

59

onEndDateChange?: (dateString: string) => void;

60

onStartDateFocus?: () => void;

61

onEndDateFocus?: () => void;

62

onStartDateShiftTab?: () => void;

63

onEndDateTab?: () => void;

64

onClearDates?: () => void;

65

onKeyDownArrowDown?: () => void; // Arrow down key handler

66

onKeyDownQuestionMark?: () => void; // Question mark key handler

67

68

// Accessibility

69

startDateAriaLabel?: string;

70

endDateAriaLabel?: string;

71

screenReaderMessage?: string;

72

73

// Content

74

children?: ReactNode; // Child elements to render

75

76

// Internationalization

77

phrases?: object;

78

}

79

```

80

81

**Usage Examples:**

82

83

```jsx

84

import React, { useState } from "react";

85

import { DateRangePickerInput } from "react-dates";

86

87

// Basic date range input

88

function BasicDateRangeInput() {

89

const [startDate, setStartDate] = useState('');

90

const [endDate, setEndDate] = useState('');

91

const [startFocused, setStartFocused] = useState(false);

92

const [endFocused, setEndFocused] = useState(false);

93

94

return (

95

<DateRangePickerInput

96

startDateId="start_date"

97

endDateId="end_date"

98

startDate={startDate}

99

endDate={endDate}

100

onStartDateChange={setStartDate}

101

onEndDateChange={setEndDate}

102

isStartDateFocused={startFocused}

103

isEndDateFocused={endFocused}

104

onStartDateFocus={() => setStartFocused(true)}

105

onEndDateFocus={() => setEndFocused(true)}

106

startDatePlaceholderText="Check-in"

107

endDatePlaceholderText="Check-out"

108

showClearDates={true}

109

/>

110

);

111

}

112

113

// Custom styled input with validation

114

function CustomDateRangeInput({ onValidDatesChange }) {

115

const [startDate, setStartDate] = useState('');

116

const [endDate, setEndDate] = useState('');

117

const [startFocused, setStartFocused] = useState(false);

118

const [endFocused, setEndFocused] = useState(false);

119

const [errors, setErrors] = useState({});

120

121

const validateDate = (dateString) => {

122

const date = moment(dateString, 'MM/DD/YYYY', true);

123

return date.isValid() && date.isAfter(moment().subtract(1, 'day'));

124

};

125

126

const handleStartDateChange = (dateString) => {

127

setStartDate(dateString);

128

129

const isValid = validateDate(dateString);

130

setErrors(prev => ({ ...prev, start: !isValid }));

131

132

if (isValid && validateDate(endDate)) {

133

onValidDatesChange({

134

startDate: moment(dateString, 'MM/DD/YYYY'),

135

endDate: moment(endDate, 'MM/DD/YYYY')

136

});

137

}

138

};

139

140

const handleEndDateChange = (dateString) => {

141

setEndDate(dateString);

142

143

const isValid = validateDate(dateString);

144

setErrors(prev => ({ ...prev, end: !isValid }));

145

146

if (isValid && validateDate(startDate)) {

147

onValidDatesChange({

148

startDate: moment(startDate, 'MM/DD/YYYY'),

149

endDate: moment(dateString, 'MM/DD/YYYY')

150

});

151

}

152

};

153

154

return (

155

<div>

156

<DateRangePickerInput

157

startDateId="trip_start"

158

endDateId="trip_end"

159

startDate={startDate}

160

endDate={endDate}

161

onStartDateChange={handleStartDateChange}

162

onEndDateChange={handleEndDateChange}

163

isStartDateFocused={startFocused}

164

isEndDateFocused={endFocused}

165

onStartDateFocus={() => setStartFocused(true)}

166

onEndDateFocus={() => setEndFocused(true)}

167

showDefaultInputIcon={true}

168

block={true}

169

/>

170

{errors.start && <div style={{ color: 'red' }}>Invalid start date</div>}

171

{errors.end && <div style={{ color: 'red' }}>Invalid end date</div>}

172

</div>

173

);

174

}

175

```

176

177

### DateRangePickerInputController

178

179

Controller component that manages date range input logic, validation, and formatting.

180

181

```jsx { .api }

182

/**

183

* Controller for date range input logic and validation

184

* @param props - DateRangePickerInputController configuration

185

* @returns Managed date range input component

186

*/

187

function DateRangePickerInputController(props: DateRangePickerInputControllerProps): ReactElement;

188

189

interface DateRangePickerInputControllerProps {

190

// Date state

191

startDate?: moment.Moment | null;

192

endDate?: moment.Moment | null;

193

194

// Input field IDs (required)

195

startDateId: string;

196

endDateId: string;

197

198

// Display format and placeholders

199

startDatePlaceholderText?: string;

200

endDatePlaceholderText?: string;

201

displayFormat?: (() => string) | string;

202

203

// State management

204

isStartDateFocused?: boolean;

205

isEndDateFocused?: boolean;

206

isFocused?: boolean; // Actual DOM focus state

207

disabled?: boolean;

208

required?: boolean;

209

readOnly?: boolean;

210

showClearDates?: boolean;

211

showCaret?: boolean; // Show caret indicator

212

keepOpenOnDateSelect?: boolean; // Keep picker open after date selection

213

reopenPickerOnClearDates?: boolean; // Reopen picker when dates are cleared

214

215

// Portal and layout

216

withFullScreenPortal?: boolean; // Use full screen portal mode

217

openDirection?: 'up' | 'down'; // Direction to open calendar

218

verticalSpacing?: number; // Vertical spacing in pixels (non-negative integer)

219

isRTL?: boolean; // Right-to-left layout support

220

221

// Date validation

222

minimumNights?: number; // Minimum nights between dates (non-negative integer)

223

isOutsideRange?: (day: moment.Moment) => boolean; // Function to determine if day is outside selectable range

224

225

// Event handlers

226

onDatesChange?: ({ startDate, endDate }: {

227

startDate: moment.Moment | null;

228

endDate: moment.Moment | null;

229

}) => void;

230

onFocusChange?: (focusedInput: 'startDate' | 'endDate' | null) => void;

231

onClose?: () => void; // Callback when picker closes

232

onKeyDownArrowDown?: () => void; // Arrow down key handler

233

onKeyDownQuestionMark?: () => void; // Question mark key handler

234

235

// Styling

236

noBorder?: boolean;

237

block?: boolean;

238

small?: boolean;

239

regular?: boolean;

240

241

// Icons

242

showDefaultInputIcon?: boolean;

243

inputIconPosition?: 'before' | 'after';

244

customInputIcon?: ReactNode;

245

customArrowIcon?: ReactNode;

246

customCloseIcon?: ReactNode;

247

248

// Accessibility

249

startDateAriaLabel?: string;

250

endDateAriaLabel?: string;

251

screenReaderMessage?: string;

252

253

// Content

254

children?: ReactNode; // Child elements to render

255

256

// Internationalization

257

phrases?: object;

258

}

259

```

260

261

**Public Methods:**

262

263

```jsx { .api }

264

// Date handling methods (accessible via ref)

265

onStartDateChange(startDateString: string): void;

266

onEndDateChange(endDateString: string): void;

267

onStartDateFocus(): void;

268

onEndDateFocus(): void;

269

clearDates(): void;

270

getDisplayFormat(): string;

271

getDateString(date: moment.Moment | null): string;

272

```

273

274

**Usage Examples:**

275

276

```jsx

277

import React, { useState, useRef } from "react";

278

import { DateRangePickerInputController } from "react-dates";

279

import moment from "moment";

280

281

// Controlled date range input

282

function ControlledDateRangeInput() {

283

const [startDate, setStartDate] = useState(null);

284

const [endDate, setEndDate] = useState(null);

285

const [focusedInput, setFocusedInput] = useState(null);

286

const controllerRef = useRef(null);

287

288

const handleDatesChange = ({ startDate, endDate }) => {

289

setStartDate(startDate);

290

setEndDate(endDate);

291

292

// Custom validation

293

if (startDate && endDate && endDate.isBefore(startDate)) {

294

// Swap dates if end is before start

295

setStartDate(endDate);

296

setEndDate(startDate);

297

}

298

};

299

300

const clearAllDates = () => {

301

if (controllerRef.current) {

302

controllerRef.current.clearDates();

303

}

304

};

305

306

return (

307

<div>

308

<DateRangePickerInputController

309

ref={controllerRef}

310

startDate={startDate}

311

endDate={endDate}

312

startDateId="start_input"

313

endDateId="end_input"

314

onDatesChange={handleDatesChange}

315

onFocusChange={setFocusedInput}

316

isStartDateFocused={focusedInput === 'startDate'}

317

isEndDateFocused={focusedInput === 'endDate'}

318

displayFormat="MMM D, YYYY"

319

showClearDates={true}

320

/>

321

<button onClick={clearAllDates}>Clear All Dates</button>

322

</div>

323

);

324

}

325

```

326

327

### SingleDatePickerInput

328

329

Input field component for single date display and manual entry.

330

331

```jsx { .api }

332

/**

333

* Single date input field without calendar

334

* @param props - SingleDatePickerInput configuration

335

* @returns Input field for single date entry

336

*/

337

function SingleDatePickerInput(props: SingleDatePickerInputProps): ReactElement;

338

339

interface SingleDatePickerInputProps {

340

// Required

341

id: string;

342

343

// Display

344

placeholder?: string;

345

displayValue?: string;

346

ariaLabel?: string;

347

screenReaderMessage?: string;

348

349

// State

350

focused?: boolean;

351

disabled?: boolean;

352

required?: boolean;

353

readOnly?: boolean;

354

showClearDate?: boolean;

355

356

// Styling

357

noBorder?: boolean;

358

block?: boolean;

359

small?: boolean;

360

regular?: boolean;

361

362

// Icons

363

showDefaultInputIcon?: boolean;

364

inputIconPosition?: 'before' | 'after';

365

customInputIcon?: ReactNode;

366

customCloseIcon?: ReactNode;

367

368

// Event handlers

369

onChange?: (dateString: string) => void;

370

onClearDate?: () => void;

371

onFocus?: () => void;

372

onKeyDownShiftTab?: () => void;

373

onKeyDownTab?: () => void;

374

onKeyDownArrowDown?: () => void;

375

onKeyDownQuestionMark?: () => void;

376

377

// Internationalization

378

phrases?: object;

379

}

380

```

381

382

**Usage Examples:**

383

384

```jsx

385

import React, { useState } from "react";

386

import { SingleDatePickerInput } from "react-dates";

387

import moment from "moment";

388

389

// Basic single date input

390

function BasicSingleDateInput() {

391

const [date, setDate] = useState('');

392

const [focused, setFocused] = useState(false);

393

394

const handleDateChange = (dateString) => {

395

setDate(dateString);

396

397

// Validate date format

398

const parsedDate = moment(dateString, 'MM/DD/YYYY', true);

399

if (parsedDate.isValid()) {

400

console.log('Valid date selected:', parsedDate.format('YYYY-MM-DD'));

401

}

402

};

403

404

return (

405

<SingleDatePickerInput

406

id="birthday_input"

407

placeholder="Select your birthday"

408

displayValue={date}

409

onChange={handleDateChange}

410

focused={focused}

411

onFocus={() => setFocused(true)}

412

showClearDate={true}

413

showDefaultInputIcon={true}

414

/>

415

);

416

}

417

418

// Formatted date input with custom validation

419

function FormattedDateInput({ format = 'YYYY-MM-DD', onValidDate }) {

420

const [inputValue, setInputValue] = useState('');

421

const [isValid, setIsValid] = useState(true);

422

423

const handleChange = (dateString) => {

424

setInputValue(dateString);

425

426

const parsedDate = moment(dateString, format, true);

427

const valid = parsedDate.isValid();

428

setIsValid(valid);

429

430

if (valid) {

431

onValidDate(parsedDate);

432

}

433

};

434

435

return (

436

<div>

437

<SingleDatePickerInput

438

id="formatted_date"

439

placeholder={`Enter date (${format})`}

440

displayValue={inputValue}

441

onChange={handleChange}

442

block={true}

443

customInputIcon={

444

<span style={{ color: isValid ? 'green' : 'red' }}>๐Ÿ“…</span>

445

}

446

/>

447

{!isValid && inputValue && (

448

<div style={{ color: 'red', fontSize: '12px' }}>

449

Please enter a valid date in {format} format

450

</div>

451

)}

452

</div>

453

);

454

}

455

```

456

457

### SingleDatePickerInputController

458

459

Controller component that manages single date input logic, validation, and formatting with full picker integration.

460

461

```jsx { .api }

462

/**

463

* Controller for single date input logic with picker integration

464

* @param props - SingleDatePickerInputController configuration

465

* @returns Managed single date input component with picker

466

*/

467

function SingleDatePickerInputController(props: SingleDatePickerInputControllerProps): ReactElement;

468

469

interface SingleDatePickerInputControllerProps {

470

// Date state

471

date?: moment.Moment | null; // Selected date value

472

focused?: boolean; // Whether input is focused

473

474

// Required props

475

id: string; // Required input field ID

476

onDateChange: (date: moment.Moment | null) => void; // Required callback when date changes

477

onFocusChange: (arg: { focused: boolean }) => void; // Required callback for focus changes

478

479

// Display and placeholders

480

placeholder?: string; // Input placeholder text

481

displayFormat?: string | (() => string); // Date display format

482

483

// State management

484

isFocused?: boolean; // Actual DOM focus state

485

disabled?: boolean; // Disabled state

486

required?: boolean; // Required field

487

readOnly?: boolean; // Read-only state

488

showClearDate?: boolean; // Show clear date button

489

showCaret?: boolean; // Show caret indicator

490

491

// Portal and layout

492

openDirection?: 'up' | 'down'; // Direction to open calendar

493

verticalSpacing?: number; // Vertical spacing in pixels (non-negative integer)

494

isRTL?: boolean; // Right-to-left layout support

495

496

// Picker behavior

497

keepOpenOnDateSelect?: boolean; // Keep open after date selection

498

reopenPickerOnClearDate?: boolean; // Reopen after clearing date

499

500

// Date validation

501

isOutsideRange?: (day: moment.Moment) => boolean; // Outside range validation

502

503

// Event handlers

504

onClose?: () => void; // Callback when picker closes

505

onKeyDownArrowDown?: () => void; // Arrow down key handler

506

onKeyDownQuestionMark?: () => void; // Question mark key handler

507

508

// Styling

509

noBorder?: boolean; // Remove border styling

510

block?: boolean; // Block-level display

511

small?: boolean; // Small size variant

512

regular?: boolean; // Regular size variant

513

514

// Icons

515

showDefaultInputIcon?: boolean; // Show default calendar icon

516

inputIconPosition?: 'before' | 'after'; // Position of input icon

517

customInputIcon?: ReactNode; // Custom input icon

518

customCloseIcon?: ReactNode; // Custom close icon

519

520

// Accessibility

521

ariaLabel?: string; // Accessibility label

522

screenReaderMessage?: string; // Screen reader message

523

524

// Content

525

children?: ReactNode; // Child elements to render

526

527

// Internationalization

528

phrases?: object; // Internationalization phrases

529

}

530

```

531

532

**Usage Examples:**

533

534

```jsx

535

import React, { useState } from "react";

536

import { SingleDatePickerInputController } from "react-dates";

537

import moment from "moment";

538

539

// Controlled single date input with picker

540

function ControlledSingleDateInput() {

541

const [date, setDate] = useState(null);

542

const [focused, setFocused] = useState(false);

543

544

return (

545

<SingleDatePickerInputController

546

id="controlled_date"

547

date={date}

548

onDateChange={setDate}

549

focused={focused}

550

onFocusChange={({ focused }) => setFocused(focused)}

551

placeholder="Select a date"

552

showClearDate={true}

553

showDefaultInputIcon={true}

554

isOutsideRange={(day) => moment().diff(day) > 0} // No past dates

555

/>

556

);

557

}

558

559

// Advanced date picker with validation

560

function ValidatedDatePicker({ onValidDate, minDate, maxDate }) {

561

const [date, setDate] = useState(null);

562

const [focused, setFocused] = useState(false);

563

564

const isOutsideRange = (day) => {

565

if (minDate && day.isBefore(minDate, 'day')) return true;

566

if (maxDate && day.isAfter(maxDate, 'day')) return true;

567

return false;

568

};

569

570

const handleDateChange = (newDate) => {

571

setDate(newDate);

572

if (newDate && !isOutsideRange(newDate)) {

573

onValidDate(newDate);

574

}

575

};

576

577

return (

578

<SingleDatePickerInputController

579

id="validated_date"

580

date={date}

581

onDateChange={handleDateChange}

582

focused={focused}

583

onFocusChange={({ focused }) => setFocused(focused)}

584

isOutsideRange={isOutsideRange}

585

displayFormat="MMM D, YYYY"

586

block={true}

587

onClose={() => console.log('Picker closed')}

588

/>

589

);

590

}

591

```

592

593

## Common Input Features

594

595

### Icon Customization

596

597

All input components support custom icons:

598

599

```jsx

600

// Custom calendar icon

601

const customIcon = <CalendarIcon size={16} color="#007bff" />;

602

603

// Custom clear button

604

const customClearIcon = <XIcon size={14} color="#dc3545" />;

605

606

<SingleDatePickerInput

607

customInputIcon={customIcon}

608

customCloseIcon={customClearIcon}

609

inputIconPosition="before"

610

/>

611

```

612

613

### Accessibility Features

614

615

- ARIA labeling for screen readers

616

- Keyboard navigation support

617

- Focus management

618

- Screen reader announcements

619

- Customizable accessible text

620

621

### Validation Patterns

622

623

```jsx

624

// Date format validation

625

const validateDateFormat = (dateString, format = 'MM/DD/YYYY') => {

626

const date = moment(dateString, format, true);

627

return date.isValid();

628

};

629

630

// Date range validation

631

const validateDateRange = (date, minDate, maxDate) => {

632

const momentDate = moment(date);

633

return momentDate.isBetween(minDate, maxDate, 'day', '[]');

634

};

635

636

// Business day validation

637

const isBusinessDay = (dateString) => {

638

const date = moment(dateString);

639

const dayOfWeek = date.day();

640

return dayOfWeek !== 0 && dayOfWeek !== 6; // Not Sunday or Saturday

641

};

642

```