Skip to content
Merged
Show file tree
Hide file tree
Changes from 125 commits
Commits
Show all changes
149 commits
Select commit Hold shift + click to select a range
4f0dc24
refactor(date-picker): extract reusable logic from DateInputSegment, wip
shaneeza Oct 7, 2025
2771235
refactor(date-picker): extract reusable logic from DateInputSegment, wip
shaneeza Oct 7, 2025
4ebb946
refactor(date-picker): enhance InputSegment and DateInputSegment with…
shaneeza Oct 8, 2025
9f40cff
refactor(date-picker): update InputSegment types and enhance DateInpu…
shaneeza Oct 8, 2025
85351a3
refactor(date-picker): WIP enhance InputBox and DateInput components …
shaneeza Oct 21, 2025
ebdde67
refactor(date-picker): integrate InputBox into DateInputBox for impro…
shaneeza Oct 22, 2025
e19c926
refactor(date-picker): clean up DateInputBox and enhance InputBox typ…
shaneeza Oct 22, 2025
edce7cc
refactor(date-picker): enhance DatePicker components with improved ty…
shaneeza Oct 22, 2025
ad12567
refactor(date-picker): enhance InputSegment and DateInputSegment with…
shaneeza Oct 23, 2025
6be0c01
refactor(input-box): move utils into input-box
shaneeza Oct 23, 2025
97d84d4
refactor(input-box): move utils into input-box
shaneeza Oct 23, 2025
cf44545
refactor(date-picker): integrate InputBox and InputSegment into DateP…
shaneeza Oct 26, 2025
01a4072
refactor(date-picker): migrate utility functions to InputBox and enha…
shaneeza Oct 27, 2025
0d8a827
refactor(date-picker): improve type safety in DateInputSegment and cl…
shaneeza Oct 28, 2025
d62e92f
refactor(input-box): update exports in utils to include new segment v…
shaneeza Oct 28, 2025
9e63f3b
refactor(input-box): add devDependencies for palette and enhance Inpu…
shaneeza Oct 28, 2025
0a33907
refactor(input-box): simplify styling logic in InputBox and InputSegm…
shaneeza Oct 28, 2025
d4bc356
refactor(input-box): enhance type definitions in InputBox and InputSe…
shaneeza Oct 28, 2025
d36b02a
refactor(input-box): improve documentation for InputBox and InputSegm…
shaneeza Oct 28, 2025
dfd04ff
refactor(input-box): update documentation for segmentRefs and segment…
shaneeza Oct 28, 2025
853eea4
refactor(input-box, date-picker): streamline value formatting by upda…
shaneeza Oct 28, 2025
93d2c09
refactor(input-box, date-picker): update utils to allow zero values
shaneeza Oct 29, 2025
d2aa6ff
refactor(input-box, date-picker): introduce shouldSkipValidation flag…
shaneeza Oct 29, 2025
e3066f9
refactor(input-box): enhance renderSegment return type for improved t…
shaneeza Oct 29, 2025
ee819d6
refactor(input-box): improve InputBox tests to verify segment renderi…
shaneeza Oct 29, 2025
3eb786c
refactor(input-box): remove unused getLgIds utility and clean up Inpu…
shaneeza Oct 29, 2025
ec62658
refactor(input-box, date-picker): rename segmentObj to segmentEnum fo…
shaneeza Oct 29, 2025
d192456
refactor(input-box, date-picker): update type annotations and enhance…
shaneeza Oct 29, 2025
fb7837a
refactor(input-box): update README and improve InputBox documentation…
shaneeza Oct 29, 2025
40a106d
feat(input-box): adds input-box package and utils
shaneeza Oct 29, 2025
a773e7a
merge conflict
shaneeza Oct 29, 2025
2f600d9
refactor(input-box): consolidate InputBox stories into a single file …
shaneeza Oct 29, 2025
b8d410a
refactor(date-picker): remove input-box dependency and streamline dat…
shaneeza Oct 29, 2025
95de319
feat(date-picker): integrate input-box for date segment handling and …
shaneeza Oct 29, 2025
d7853dc
refactor(date-picker, input-box): implement context for segment manag…
shaneeza Nov 1, 2025
cae12d5
refactor(input-box): update InputBox and InputSegment components to u…
shaneeza Nov 2, 2025
b24d5bc
refactor(input-box): clarify type handling in InputBoxContext with de…
shaneeza Nov 2, 2025
b575531
refactor(input-box): enhance type handling in InputBox and InputSegme…
shaneeza Nov 2, 2025
8236c8d
refactor(input-box): update InputSegment and InputBox components to u…
shaneeza Nov 3, 2025
f3125b6
refactor(date-picker): implement DateInputBoxContext for improved sta…
shaneeza Nov 3, 2025
c40ad4c
refactor(date-picker, input-box): enhance DateInput components by int…
shaneeza Nov 3, 2025
8a76a79
refactor(date-picker, input-box): improve DateInputSegment tests and …
shaneeza Nov 4, 2025
2141a34
refactor(date-picker): reorganize DateInputBox context imports and re…
shaneeza Nov 4, 2025
8e4ada0
docs(input-box): expand README with detailed component descriptions, …
shaneeza Nov 4, 2025
cb9ec7f
docs(input-box): update README to reflect changes in component struct…
shaneeza Nov 4, 2025
015cf67
refactor(input-box): rename `shouldRollover` to `shouldWrap` for clar…
shaneeza Nov 4, 2025
4583b57
refactor(date-picker, input-box): reorganize imports and enhance prop…
shaneeza Nov 4, 2025
d552743
test(input-box): add comprehensive tests for segment navigation and r…
shaneeza Nov 4, 2025
941e93c
fix(input-box, date-picker): address validation and formatting issues…
shaneeza Nov 5, 2025
491ae48
refactor(input-box, date-picker): remove defaultMin prop and enhance …
shaneeza Nov 5, 2025
2ed06d6
refactor(input-box): standardize parameter naming from `allowsZero` t…
shaneeza Nov 5, 2025
15450a5
refactor(input-box): enhance createExplicitSegmentValidator documenta…
shaneeza Nov 5, 2025
94306ec
test(input-box): enhance mouse and keyboard interaction tests for seg…
shaneeza Nov 5, 2025
34ab4e6
test(input-box): add tests for Up and Down arrow key interactions to …
shaneeza Nov 6, 2025
762bc65
refactor(input-box, date-picker): streamline InputBoxContext structur…
shaneeza Nov 6, 2025
80c6c68
Merge branch 'shaneeza/time-picker-integration' of github.com:mongodb…
shaneeza Nov 6, 2025
e3f5a34
docs(input-box): update README.md to enhance installation instruction…
shaneeza Nov 6, 2025
09d117b
feat(input-box): enhance InputBox and InputSegment components with ne…
shaneeza Nov 6, 2025
3074847
Merge branch 'LG-5504/input-box-component' of github.com:mongodb/leaf…
shaneeza Nov 6, 2025
35d975b
feat(input-box): add '@leafygreen-ui/a11y' as a dependency in pnpm-lo…
shaneeza Nov 6, 2025
3a13648
Merge branch 'LG-5504/input-box-component' of github.com:mongodb/leaf…
shaneeza Nov 6, 2025
2f81c18
fix(input-box): fix lint errors
shaneeza Nov 6, 2025
86fbca9
feat(input-box): set default size for InputBox in stories and refacto…
shaneeza Nov 6, 2025
e4b54c5
Merge branch 'LG-5504/input-box-component' of github.com:mongodb/leaf…
shaneeza Nov 7, 2025
0fd74e6
refactor(date-picker): simplify ProviderWrapper in DateInputSegment s…
shaneeza Nov 7, 2025
7e6e4b4
feat(input-box): implement InputBoxContext and InputBoxProvider with …
shaneeza Nov 7, 2025
1c69f5d
remove segement files
shaneeza Nov 7, 2025
46746a5
Merge branch LG-5504/input-box-context of github.com:mongodb/leafygre…
shaneeza Nov 7, 2025
691bde9
feat(input-box): implement InputSegment component with styles, tests,…
shaneeza Nov 7, 2025
b2984f3
feat(input-box): add @leafygreen-ui/a11y dependency and update InputS…
shaneeza Nov 7, 2025
6be4fdf
Merge branch LG-5504/input-box-segment of github.com:mongodb/leafygre…
shaneeza Nov 7, 2025
b0d7bba
refactor(input-box): update createExplicitSegmentValidator tests to u…
shaneeza Nov 7, 2025
3986897
test(input-box): refactor InputBoxContext tests for improved readabil…
shaneeza Nov 7, 2025
2eda96e
refactor(input-box): update InputBoxContext types to extend SharedInp…
shaneeza Nov 10, 2025
fff0557
fix(input-box): correct comment formatting in testutils.mocks.ts for …
shaneeza Nov 10, 2025
959c5a1
feat(input-box): add InputSegment component for modular input handling
shaneeza Nov 10, 2025
e97d393
feat(input-box): add placeholder for InputSegment types
shaneeza Nov 10, 2025
0ab86c9
Merge branch 'LG-5504/input-box-context' of github.com:mongodb/leafyg…
shaneeza Nov 10, 2025
ad1f017
refactor(input-box): move InputSegmentChangeEventHandler import to sh…
shaneeza Nov 10, 2025
81a943c
refactor(input-box): rename min and max props to minSegmentValue and …
shaneeza Nov 10, 2025
8cfadbe
refactor(input-box): simplify placeholder logic in InputSegment stori…
shaneeza Nov 10, 2025
68fc653
refactor(input-box): update InputSegment styles to use dynamic theme …
shaneeza Nov 10, 2025
a04d5ec
feat(input-box): extend InputSegmentProps to include hours, minutes, …
shaneeza Nov 10, 2025
0101c32
refactor(input-box): rename onChange and onBlur props in InputSegment…
shaneeza Nov 10, 2025
662f2dd
refactor(input-box): rename shouldSkipValidation prop to shouldValida…
shaneeza Nov 10, 2025
967b33b
refactor(input-box): reorganize imports in testutils for better clari…
shaneeza Nov 11, 2025
a589e94
refactor(input-box): remove deprecated InputSegment types and update …
shaneeza Nov 11, 2025
4a03f0b
Merge branch 'LG-5504/input-box-context' of github.com:mongodb/leafyg…
shaneeza Nov 11, 2025
e8a3705
refactor(input-box): update InputSegmentChangeEventHandler import to …
shaneeza Nov 11, 2025
4cf138e
refactor(input-box): enhance InputSegment types and documentation, ad…
shaneeza Nov 11, 2025
a7062e2
refactor(input-box): streamline InputSegment exports by removing unus…
shaneeza Nov 11, 2025
dd132ea
test(input-box): add accessibility test for InputSegment to ensure no…
shaneeza Nov 11, 2025
0e9b9bd
refactor(input-box): update InputSegment to remove size prop and enha…
shaneeza Nov 12, 2025
5e73301
refactor(input-box): enhance InputSegment types by adding onChange an…
shaneeza Nov 12, 2025
0baa5dc
refactor(input-box): pull the latest from input-segment
shaneeza Nov 12, 2025
6db5451
refactor(input-box): update InputSegment types to extend from 'div' a…
shaneeza Nov 12, 2025
2d76c2c
Merge branch 'LG-5504/input-box-segment' of github.com:mongodb/leafyg…
shaneeza Nov 12, 2025
d4ec60d
refactor(input-box): simplify SharedInputBoxTypes by removing redunda…
shaneeza Nov 12, 2025
bf2eeda
refactor(input-box): remove InputBoxContext and related tests to stre…
shaneeza Nov 12, 2025
5c05dc1
refactor(input-box): remove InputBoxContext and related types to stre…
shaneeza Nov 12, 2025
9dd8437
Merge branch 'LG-5504/input-box-component' of github.com:mongodb/leaf…
shaneeza Nov 12, 2025
41b814c
wip
shaneeza Nov 12, 2025
904fb8c
refactor(input-box): simplify InputSegment types by removing Value ge…
shaneeza Nov 12, 2025
81e00e6
Merge branch 'LG-5504/input-box-segment' of github.com:mongodb/leafyg…
shaneeza Nov 12, 2025
3792f8b
refactor(input-box): update InputSegment and InputBox types to includ…
shaneeza Nov 12, 2025
4b96d3d
Merge branch 'LG-5504/input-box-component' of github.com:mongodb/leaf…
shaneeza Nov 12, 2025
a486f08
refactor(date-picker): streamline DateInput components by simplifying…
shaneeza Nov 12, 2025
7b1db76
refactor(input-box): update InputSegment types to include value prop …
shaneeza Nov 12, 2025
348faa3
Merge branch 'LG-5504/input-box-segment' of github.com:mongodb/leafyg…
shaneeza Nov 12, 2025
20da919
refactor(input-box): remove unused Size import from InputBox.spec.tsx…
shaneeza Nov 12, 2025
8627f35
Merge branch 'LG-5504/input-box-component' of github.com:mongodb/leaf…
shaneeza Nov 12, 2025
6942348
refactor(input-box): enhance InputBox and InputSegment documentation,…
shaneeza Nov 12, 2025
3a8af91
Merge branch LG-5504/input-box-component of github.com:mongodb/leafyg…
shaneeza Nov 12, 2025
3fe8f0b
Merge branch 'shaneeza/time-picker-integration' of github.com:mongodb…
shaneeza Nov 13, 2025
2dc0134
testing
shaneeza Nov 13, 2025
b4dd84d
refactor(input-box): remove unused dependencies and update InputSegme…
shaneeza Nov 13, 2025
f2cfaa3
update lock file
shaneeza Nov 13, 2025
c269b96
testing
shaneeza Nov 13, 2025
73ea273
testing build
shaneeza Nov 13, 2025
a55bf24
testing build
shaneeza Nov 13, 2025
717daa7
Merge branch 'LG-5504/input-box-segment' of github.com:mongodb/leafyg…
shaneeza Nov 13, 2025
67d8f9f
test(input-segment): add test for resetting value with complete zeros…
shaneeza Nov 13, 2025
d7c1fc2
refactor(input-box): update separator literal styles to use new token…
shaneeza Nov 13, 2025
f52ed19
fix(input-segment): add missing line to check for number input handling
shaneeza Nov 13, 2025
fddc207
Merge branch LG-5504/input-box-component of github.com:mongodb/leafyg…
shaneeza Nov 13, 2025
94f2900
Merge branch shaneeza/time-picker-integration of github.com:mongodb/l…
shaneeza Nov 14, 2025
68e5f2c
refactor(input-segment): update comments and variable name for clarit…
shaneeza Nov 14, 2025
3896c9c
refactor(input-box): update comment to reflect correct component resp…
shaneeza Nov 14, 2025
410813e
refactor(input-segment): utilize isSingleDigit utility for digit inpu…
shaneeza Nov 14, 2025
ed31fdc
refactor(input-box): enhance documentation for InputBox component to …
shaneeza Nov 14, 2025
adaa3b6
refactor(input-box): integrate size prop into InputBox and InputSegme…
shaneeza Nov 14, 2025
a106f71
refactor(input-box): migrate Size import to shared.types for consiste…
shaneeza Nov 14, 2025
df546c1
refactor(input-box): enhance InputBox and InputSegment tests with seg…
shaneeza Nov 14, 2025
ea4d8b8
feat(input-box): add comprehensive mocks for date and time segments i…
shaneeza Nov 17, 2025
4d1030b
feat(input-box): integrate lodash for utility functions and enhance I…
shaneeza Nov 17, 2025
f342d2f
refactor(input-box): remove unused props from InputBox stories and te…
shaneeza Nov 17, 2025
f7f28eb
fix(input-box): ensure segments prop is required and handle error log…
shaneeza Nov 18, 2025
ebd1fbb
Merge branch 'LG-5504/input-box-component' of github.com:mongodb/leaf…
shaneeza Nov 19, 2025
454b522
refactor(date-input): remove unused charsPerSegment prop and update r…
shaneeza Nov 19, 2025
2fc54a3
refactor(date-input): remove onKeyDown prop from DateInputBox and upd…
shaneeza Nov 19, 2025
56c13ea
fix(date-input): import DateType and add comment about allowing any 4…
shaneeza Nov 19, 2025
6ac1984
refactor(date-picker, input-box): standardize usage of charsCount ins…
shaneeza Nov 19, 2025
68cd5fb
refactor(date-input): simplify DateInputBox by removing unused props …
shaneeza Nov 19, 2025
b44f58b
fix(date-picker): correct parameter name from disableSnapshots to dis…
shaneeza Nov 19, 2025
8595a80
Merge branch 'shaneeza/time-picker-integration' of github.com:mongodb…
shaneeza Nov 20, 2025
f476dde
remove isSingleDigit utility and its associated tests
shaneeza Nov 20, 2025
faa3cf0
Merge branch 'shaneeza/time-picker-integration' of github.com:mongodb…
shaneeza Nov 20, 2025
8e4a4a4
test(date-picker): ensure real timers are used after tests in keyboar…
shaneeza Nov 20, 2025
7b02b54
refactor(date-picker): rename context value from `value` to `dateValu…
shaneeza Nov 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/input-box.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@leafygreen-ui/input-box': minor
---

Initial release of `InputBox`
1 change: 1 addition & 0 deletions packages/date-picker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@leafygreen-ui/hooks": "workspace:^",
"@leafygreen-ui/icon": "workspace:^",
"@leafygreen-ui/icon-button": "workspace:^",
"@leafygreen-ui/input-box": "workspace:^",
"@leafygreen-ui/lib": "workspace:^",
"@leafygreen-ui/palette": "workspace:^",
"@leafygreen-ui/popover": "workspace:^",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import userEvent from '@testing-library/user-event';

import { Month, newUTC } from '@leafygreen-ui/date-utils';
import { getLgIds as getLgFormFieldIds } from '@leafygreen-ui/form-field';
import { getValueFormatter } from '@leafygreen-ui/input-box';
import { eventContainingTargetValue } from '@leafygreen-ui/testing-lib';

import { DateSegment } from '../shared';
import { defaultMax, defaultMin } from '../shared/constants';
import { charsPerSegment, defaultMax, defaultMin } from '../shared/constants';
import {
getFormattedDateString,
getFormattedSegmentsFromDate,
getValueFormatter,
} from '../shared/utils';

import {
Expand Down Expand Up @@ -79,7 +79,9 @@ describe('DatePicker keyboard interaction', () => {

const segmentCases = ['year', 'month', 'day'] as Array<DateSegment>;
describe.each(segmentCases)('%p segment', segment => {
const formatter = getValueFormatter(segment);
const formatter = getValueFormatter({
charsPerSegment: charsPerSegment[segment],
});
/** Utility only for this suite. Returns the day|month|year element from the render result */
const getRelevantInput = (renderResult: RenderDatePickerResult) =>
segment === 'year'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import React, {
import isNull from 'lodash/isNull';

import { isInvalidDateObject, isSameUTCDay } from '@leafygreen-ui/date-utils';
import { isElementInputSegment } from '@leafygreen-ui/input-box';
import { createSyntheticEvent, keyMap } from '@leafygreen-ui/lib';

import {
Expand All @@ -17,11 +18,7 @@ import {
} from '../../shared/components/DateInput';
import { DateInputSegmentChangeEventHandler } from '../../shared/components/DateInput/DateInputSegment';
import { useSharedDatePickerContext } from '../../shared/context';
import {
getFormattedDateStringFromSegments,
getRelativeSegmentRef,
isElementInputSegment,
} from '../../shared/utils';
import { getFormattedDateStringFromSegments } from '../../shared/utils';
import { useDatePickerContext } from '../DatePickerContext';
import { getSegmentToFocus } from '../utils/getSegmentToFocus';

Expand Down Expand Up @@ -110,77 +107,11 @@ export const DatePickerInput = forwardRef<HTMLDivElement, DatePickerInputProps>(
// if target is not a segment, do nothing
if (!isSegment) return;

const isSegmentEmpty = !target.value;

switch (key) {
case keyMap.ArrowLeft: {
// Without this, the input ignores `.select()`
e.preventDefault();
// if input is empty,
// set focus to prev input (if it exists)
const segmentToFocus = getRelativeSegmentRef('prev', {
segment: target,
formatParts,
segmentRefs,
});

segmentToFocus?.current?.focus();
segmentToFocus?.current?.select();
// otherwise, use default behavior

break;
}

case keyMap.ArrowRight: {
// Without this, the input ignores `.select()`
e.preventDefault();
// if input is empty,
// set focus to next. input (if it exists)
const segmentToFocus = getRelativeSegmentRef('next', {
segment: target,
formatParts,
segmentRefs,
});

segmentToFocus?.current?.focus();
segmentToFocus?.current?.select();
// otherwise, use default behavior

break;
}

case keyMap.ArrowUp:
case keyMap.ArrowDown: {
// increment/decrement logic implemented by DateInputSegment
break;
}

case keyMap.Backspace: {
if (isSegmentEmpty) {
// prevent the backspace in the previous segment
e.preventDefault();

const segmentToFocus = getRelativeSegmentRef('prev', {
segment: target,
formatParts,
segmentRefs,
});
segmentToFocus?.current?.focus();
segmentToFocus?.current?.select();
}
break;
}

case keyMap.Space: {
openMenu();
break;
}

case keyMap.Enter:
case keyMap.Escape:
case keyMap.Tab:
// Behavior handled by parent or menu
break;
}

// call any handler that was passed in
Expand Down Expand Up @@ -232,17 +163,17 @@ export const DatePickerInput = forwardRef<HTMLDivElement, DatePickerInputProps>(
<DateFormField
ref={fwdRef}
buttonRef={calendarButtonRef}
onKeyDown={handleInputKeyDown}
onInputClick={handleInputClick}
onBlur={handleInputBlur}
onIconButtonClick={handleIconButtonClick}
onBlur={handleInputBlur}
{...rest}
>
<DateInputBox
value={value}
setValue={handleInputValueChange}
segmentRefs={segmentRefs}
onSegmentChange={handleSegmentChange}
onKeyDown={handleInputKeyDown}
/>
</DateFormField>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FocusEventHandler, useEffect } from 'react';
import React, { useEffect } from 'react';
import isEqual from 'lodash/isEqual';
import isNull from 'lodash/isNull';

Expand All @@ -7,37 +7,20 @@ import {
isInvalidDateObject,
isValidDate,
} from '@leafygreen-ui/date-utils';
import { cx } from '@leafygreen-ui/emotion';
import { useForwardedRef } from '@leafygreen-ui/hooks';
import { useDarkMode } from '@leafygreen-ui/leafygreen-provider';
import { keyMap } from '@leafygreen-ui/lib';
import { InputBox } from '@leafygreen-ui/input-box';

import { charsPerSegment, dateSegmentRules } from '../../../constants';
import { useSharedDatePickerContext } from '../../../context';
import { useDateSegments } from '../../../hooks';
import { DateSegment, DateSegmentsState } from '../../../types';
import {
DateSegment,
DateSegmentsState,
DateSegmentValue,
isDateSegment,
} from '../../../types';
import {
getMaxSegmentValue,
getMinSegmentValue,
getRelativeSegment,
getValueFormatter,
isEverySegmentFilled,
isEverySegmentValueExplicit,
isExplicitSegmentValue,
newDateFromSegments,
} from '../../../utils';
import { DateInputBoxProvider } from '../DateInputBoxContext';
import { DateInputSegment } from '../DateInputSegment';
import { DateInputSegmentChangeEventHandler } from '../DateInputSegment/DateInputSegment.types';

import {
segmentPartsWrapperStyles,
separatorLiteralDisabledStyles,
separatorLiteralStyles,
} from './DateInputBox.styles';
import { DateInputBoxProps } from './DateInputBox.types';

/**
Expand All @@ -62,25 +45,13 @@ export const DateInputBox = React.forwardRef<HTMLDivElement, DateInputBoxProps>(
labelledBy,
segmentRefs,
onSegmentChange,
onKeyDown,
...rest
}: DateInputBoxProps,
fwdRef,
) => {
const { isDirty, formatParts, disabled, min, max, setIsDirty } =
const { isDirty, formatParts, disabled, setIsDirty } =
useSharedDatePickerContext();
const { theme } = useDarkMode();

const containerRef = useForwardedRef(fwdRef, null);

/** Formats and sets the segment value */
const getFormattedSegmentValue = (
segmentName: DateSegment,
segmentValue: DateSegmentValue,
): DateSegmentValue => {
const formatter = getValueFormatter(segmentName);
const formattedValue = formatter(segmentValue);
return formattedValue;
};

/** if the value is a `Date` the component is dirty */
useEffect(() => {
Expand Down Expand Up @@ -118,92 +89,31 @@ export const DateInputBox = React.forwardRef<HTMLDivElement, DateInputBoxProps>(
}
};

/** State Management for segments using a useReducer instead of useState */
/** Keep track of each date segment */
const { segments, setSegment } = useDateSegments(value, {
onUpdate: handleSegmentUpdate,
});

/** Fired when an individual segment value changes */
const handleSegmentInputChange: DateInputSegmentChangeEventHandler =
segmentChangeEvent => {
let segmentValue = segmentChangeEvent.value;
const { segment: segmentName, meta } = segmentChangeEvent;
const changedViaArrowKeys =
meta?.key === keyMap.ArrowDown || meta?.key === keyMap.ArrowUp;

// Auto-format the segment if it is explicit and was not changed via arrow-keys
if (
!changedViaArrowKeys &&
isExplicitSegmentValue(segmentName, segmentValue)
) {
segmentValue = getFormattedSegmentValue(segmentName, segmentValue);

// Auto-advance focus (if possible)
const nextSegmentName = getRelativeSegment('next', {
segment: segmentName,
formatParts,
});

if (nextSegmentName) {
const nextSegmentRef = segmentRefs[nextSegmentName];
nextSegmentRef?.current?.focus();
nextSegmentRef?.current?.select();
}
}

setSegment(segmentName, segmentValue);
onSegmentChange?.(segmentChangeEvent);
};

/** Triggered when a segment is blurred */
const handleSegmentInputBlur: FocusEventHandler<HTMLInputElement> = e => {
const segmentName = e.target.getAttribute('id');
const segmentValue = e.target.value;

if (isDateSegment(segmentName)) {
const formattedValue = getFormattedSegmentValue(
segmentName,
segmentValue,
);
setSegment(segmentName, formattedValue);
}
};

return (
<div
className={cx(segmentPartsWrapperStyles, className)}
ref={containerRef}
{...rest}
>
{formatParts?.map((part, i) => {
if (part.type === 'literal') {
return (
<span
className={cx(separatorLiteralStyles, {
[separatorLiteralDisabledStyles[theme]]: disabled,
})}
key={'literal-' + i}
>
{part.value}
</span>
);
} else if (isDateSegment(part.type)) {
return (
<DateInputSegment
key={part.type}
ref={segmentRefs[part.type]}
aria-labelledby={labelledBy}
min={getMinSegmentValue(part.type, { date: value, min })}
max={getMaxSegmentValue(part.type, { date: value, max })}
segment={part.type}
value={segments[part.type]}
onChange={handleSegmentInputChange}
onBlur={handleSegmentInputBlur}
/>
);
}
})}
</div>
<DateInputBoxProvider value={value}>
<InputBox
ref={fwdRef}
onKeyDown={onKeyDown}
segmentRefs={segmentRefs}
segmentEnum={DateSegment}
charsPerSegment={charsPerSegment}
formatParts={formatParts}
segments={segments}
setSegment={setSegment}
disabled={disabled}
segmentRules={dateSegmentRules}
onSegmentChange={onSegmentChange}
labelledBy={labelledBy}
segmentComponent={DateInputSegment}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if there are props that are not used for component logic, can we instead pass them through to InputBox through the spread ...rest?

{...rest}
/>
</DateInputBoxProvider>
);
},
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

import { isReact17, renderHook } from '@leafygreen-ui/testing-lib';

import {
DateInputBoxProvider,
useDateInputBoxContext,
} from './DateInputBoxContext';

describe('DateInputBoxContext', () => {
test('throws error when used outside of DateInputBoxProvider', () => {
/**
* The version of `renderHook` imported from "@testing-library/react-hooks", (used in React 17)
* has an error boundary, and doesn't throw errors as expected:
* https://github.com/testing-library/react-hooks-testing-library/blob/main/src/index.ts#L5
* */
if (isReact17()) {
const { result } = renderHook(() => useDateInputBoxContext());
expect(result.error.message).toEqual(
'useDateInputBoxContext must be used within a DateInputBoxProvider',
);
} else {
expect(() => renderHook(() => useDateInputBoxContext())).toThrow(
'useDateInputBoxContext must be used within a DateInputBoxProvider',
);
}
});

test('provides context values that match the props passed to the provider', () => {
const value = new Date();
const { result } = renderHook(() => useDateInputBoxContext(), {
wrapper: ({ children }) => (
<DateInputBoxProvider value={value}>{children}</DateInputBoxProvider>
),
});
expect(result.current.value).toEqual(value);
});
});
Loading
Loading