@codecademy/gamut
68.2.268.2.3-alpha.02a91b.0
dist/DatePicker/DatePickerInput/Segment/DatePickerInputSegment.js+
dist/DatePicker/DatePickerInput/Segment/DatePickerInputSegment.jsNew file+138
Index: package/dist/DatePicker/DatePickerInput/Segment/DatePickerInputSegment.js
===================================================================
--- package/dist/DatePicker/DatePickerInput/Segment/DatePickerInputSegment.js
+++ package/dist/DatePicker/DatePickerInput/Segment/DatePickerInputSegment.js
@@ -0,0 +1,138 @@
+import { useCallback, useId, useRef } from 'react';
+import { Segment } from './elements';
+import { appendSegmentDigit, getSegmentSpinBounds, parseSegmentNumericString, segmentMaxLength, segmentPlaceholder, spinSegment } from './segmentUtils';
+import { jsx as _jsx } from "react/jsx-runtime";
+/**
+ * Editable date unit (`role="spinbutton"`). Focus with Tab; type digits or use Arrow up/down.
+ */
+export const DatePickerInputSegment = ({
+ field,
+ segments,
+ disabled,
+ error,
+ handleOnClick,
+ handleOnFocus,
+ focusOrOpenCalendarGrid,
+ setSegments,
+ prevField,
+ nextField,
+ applySegments
+}) => {
+ const {
+ min,
+ max
+ } = getSegmentSpinBounds(field, segments);
+ const n = parseSegmentNumericString(segments[field]);
+ const ariaValue = segments[field].length > 0 && n != null ? n : undefined;
+ const display = segments[field].length > 0 ? segments[field] : segmentPlaceholder(field);
+ const inputID = useId();
+ const inputId = `datepicker-input-${inputID.replace(/:/g, '')}`;
+ const segmentRefs = useRef({});
+ const focusField = useCallback(field => {
+ segmentRefs.current[field]?.focus();
+ }, []);
+ const handleSegmentKeyDown = useCallback(field => e => {
+ if (disabled) return;
+ if (e.altKey && (e.key === 'ArrowDown' || e.key === 'Down')) {
+ e.preventDefault();
+ focusOrOpenCalendarGrid();
+ return;
+ }
+ if (e.key === 'ArrowLeft') {
+ if (prevField) {
+ e.preventDefault();
+ focusField(prevField);
+ }
+ return;
+ }
+ if (e.key === 'ArrowRight') {
+ if (nextField) {
+ e.preventDefault();
+ focusField(nextField);
+ }
+ return;
+ }
+ if (e.key === 'ArrowUp') {
+ e.preventDefault();
+ setSegments(prev => {
+ const next = {
+ ...prev,
+ [field]: spinSegment(field, prev, 1)
+ };
+ applySegments(next);
+ return next;
+ });
+ return;
+ }
+ if (e.key === 'ArrowDown') {
+ e.preventDefault();
+ setSegments(prev => {
+ const next = {
+ ...prev,
+ [field]: spinSegment(field, prev, -1)
+ };
+ applySegments(next);
+ return next;
+ });
+ return;
+ }
+ if (e.key === 'Backspace' || e.key === 'Delete') {
+ e.preventDefault();
+ setSegments(prev => {
+ if (prev[field].length > 0) {
+ const next = {
+ ...prev,
+ [field]: prev[field].slice(0, -1)
+ };
+ applySegments(next);
+ return next;
+ }
+ if (prevField) {
+ queueMicrotask(() => focusField(prevField));
+ }
+ return prev;
+ });
+ return;
+ }
+
+ // if the key is a single digit and is a number, append the digit to the segment
+ if (e.key.length === 1 && /^\d$/.test(e.key)) {
+ e.preventDefault();
+ setSegments(prev => {
+ const next = {
+ ...prev,
+ [field]: appendSegmentDigit(field, prev[field], e.key)
+ };
+ applySegments(next);
+ const maxLen = segmentMaxLength(field);
+ if (next[field].length >= maxLen && nextField) {
+ queueMicrotask(() => focusField(nextField));
+ }
+ return next;
+ });
+ }
+ }, [disabled, focusOrOpenCalendarGrid, prevField, focusField, nextField, setSegments, applySegments]);
+ return /*#__PURE__*/_jsx(Segment, {
+ "aria-disabled": disabled,
+ "aria-invalid": Boolean(error),
+ "aria-label": field,
+ "aria-valuemax": max,
+ "aria-valuemin": min,
+ "aria-valuenow": ariaValue,
+ "aria-valuetext": display,
+ contentEditable: false,
+ "data-segment": field,
+ default: segments[field].length === 0,
+ field: field,
+ id: `${inputId}-${field}`,
+ ref: el => {
+ segmentRefs.current[field] = el;
+ },
+ role: "spinbutton",
+ tabIndex: disabled ? -1 : 0,
+ onClick: handleOnClick,
+ onFocus: handleOnFocus,
+ onKeyDown: handleSegmentKeyDown(field),
+ children: display
+ });
+};
\ No newline at end of file