@react-spectrum/datepicker 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,90 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {classNames} from '@react-spectrum/utils';
14
+ import {DatePickerBase, DateValue} from '@react-types/datepicker';
15
+ import {DatePickerFieldState, DateSegment} from '@react-stately/datepicker';
16
+ import {NumberParser} from '@internationalized/number';
17
+ import React, {useMemo, useRef} from 'react';
18
+ import styles from './index.css';
19
+ import {useDateSegment} from '@react-aria/datepicker';
20
+ import {useFocusManager} from '@react-aria/focus';
21
+ import {useLocale} from '@react-aria/i18n';
22
+ import {usePress} from '@react-aria/interactions';
23
+
24
+ interface DatePickerSegmentProps extends DatePickerBase<DateValue> {
25
+ segment: DateSegment,
26
+ state: DatePickerFieldState
27
+ }
28
+
29
+ interface LiteralSegmentProps {
30
+ segment: DateSegment
31
+ }
32
+
33
+ export function DatePickerSegment({segment, state, ...otherProps}: DatePickerSegmentProps) {
34
+ switch (segment.type) {
35
+ // A separator, e.g. punctuation
36
+ case 'literal':
37
+ return <LiteralSegment segment={segment} />;
38
+
39
+ // Editable segment
40
+ default:
41
+ return <EditableSegment segment={segment} state={state} {...otherProps} />;
42
+ }
43
+ }
44
+
45
+ function LiteralSegment({segment}: LiteralSegmentProps) {
46
+ let focusManager = useFocusManager();
47
+ let {pressProps} = usePress({
48
+ onPressStart: (e) => {
49
+ if (e.pointerType === 'mouse') {
50
+ let res = focusManager.focusNext({from: e.target as HTMLElement});
51
+ if (!res) {
52
+ focusManager.focusPrevious({from: e.target as HTMLElement});
53
+ }
54
+ }
55
+ }
56
+ });
57
+
58
+ return (
59
+ <span
60
+ aria-hidden="true"
61
+ className={classNames(styles, 'react-spectrum-Datepicker-literal')}
62
+ {...pressProps}
63
+ data-testid={segment.type === 'literal' ? undefined : segment.type}>
64
+ {segment.text}
65
+ </span>
66
+ );
67
+ }
68
+
69
+ function EditableSegment({segment, state, ...otherProps}: DatePickerSegmentProps) {
70
+ let ref = useRef();
71
+ let {segmentProps} = useDateSegment(otherProps, segment, state, ref);
72
+ let {locale} = useLocale();
73
+ let parser = useMemo(() => new NumberParser(locale), [locale]);
74
+ let isNumeric = useMemo(() => parser.isValidPartialNumber(segment.text), [segment.text, parser]);
75
+ return (
76
+ <div
77
+ ref={ref}
78
+ className={classNames(styles, 'react-spectrum-DatePicker-cell', {
79
+ 'is-placeholder': segment.isPlaceholder,
80
+ 'is-read-only': !segment.isEditable
81
+ })}
82
+ style={{
83
+ minWidth: !isNumeric ? null : String(segment.maxValue).length + 'ch'
84
+ }}
85
+ data-testid={segment.type}
86
+ {...segmentProps}>
87
+ {segment.isPlaceholder ? '' : segment.text}
88
+ </div>
89
+ );
90
+ }
@@ -0,0 +1,226 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import CalendarIcon from '@spectrum-icons/workflow/Calendar';
14
+ import {classNames, useStyleProps} from '@react-spectrum/utils';
15
+ import {Content} from '@react-spectrum/view';
16
+ import {DatePickerField} from './DatePickerField';
17
+ import datepickerStyles from './index.css';
18
+ import {DateValue, SpectrumDateRangePickerProps} from '@react-types/datepicker';
19
+ import {Dialog, DialogTrigger} from '@react-spectrum/dialog';
20
+ import {Field} from '@react-spectrum/label';
21
+ import {FieldButton} from '@react-spectrum/button';
22
+ import {Flex} from '@react-spectrum/layout';
23
+ import {Input} from './Input';
24
+ import {mergeProps} from '@react-aria/utils';
25
+ import {RangeCalendar} from '@react-spectrum/calendar';
26
+ import React, {useRef} from 'react';
27
+ import styles from '@adobe/spectrum-css-temp/components/inputgroup/vars.css';
28
+ import {TimeField} from './TimeField';
29
+ import {useDateRangePicker} from '@react-aria/datepicker';
30
+ import {useDateRangePickerState} from '@react-stately/datepicker';
31
+ import {useFocusRing} from '@react-aria/focus';
32
+ import {useFormatHelpText, useVisibleMonths} from './utils';
33
+ import {useHover} from '@react-aria/interactions';
34
+ import {useLocale} from '@react-aria/i18n';
35
+ import {useProviderProps} from '@react-spectrum/provider';
36
+
37
+ export function DateRangePicker<T extends DateValue>(props: SpectrumDateRangePickerProps<T>) {
38
+ props = useProviderProps(props);
39
+ let {
40
+ isQuiet,
41
+ isDisabled,
42
+ isReadOnly,
43
+ isRequired,
44
+ autoFocus,
45
+ placeholderValue,
46
+ maxVisibleMonths = 1,
47
+ ...otherProps
48
+ } = props;
49
+ let {styleProps} = useStyleProps(otherProps);
50
+ let {hoverProps, isHovered} = useHover({isDisabled});
51
+ let targetRef = useRef<HTMLDivElement>();
52
+ let state = useDateRangePickerState(props);
53
+ let {labelProps, groupProps, buttonProps, dialogProps, startFieldProps, endFieldProps, descriptionProps, errorMessageProps} = useDateRangePicker(props, state, targetRef);
54
+ let {value, isOpen, setOpen} = state;
55
+ let {direction} = useLocale();
56
+
57
+ let {isFocused, isFocusVisible, focusProps} = useFocusRing({
58
+ within: true,
59
+ isTextInput: true,
60
+ autoFocus
61
+ });
62
+
63
+ let className = classNames(
64
+ styles,
65
+ 'spectrum-InputGroup',
66
+ {
67
+ 'spectrum-InputGroup--quiet': isQuiet,
68
+ 'spectrum-InputGroup--invalid': state.validationState === 'invalid',
69
+ 'is-disabled': isDisabled,
70
+ 'is-hovered': isHovered,
71
+ 'is-focused': isFocused,
72
+ 'focus-ring': isFocusVisible
73
+ },
74
+ styleProps.className
75
+ );
76
+
77
+ let fieldClassName = classNames(
78
+ styles,
79
+ 'spectrum-InputGroup-input',
80
+ {
81
+ 'is-disabled': isDisabled,
82
+ 'is-invalid': state.validationState === 'invalid'
83
+ }
84
+ );
85
+
86
+ // Note: this description is intentionally not passed to useDatePicker.
87
+ // The format help text is unnecessary for screen reader users because each segment already has a label.
88
+ let description = useFormatHelpText(props);
89
+ if (description && !props.description) {
90
+ descriptionProps.id = null;
91
+ }
92
+
93
+ let placeholder: DateValue = placeholderValue;
94
+ let timePlaceholder = placeholder && 'hour' in placeholder ? placeholder : null;
95
+ let timeMinValue = props.minValue && 'hour' in props.minValue ? props.minValue : null;
96
+ let timeMaxValue = props.maxValue && 'hour' in props.maxValue ? props.maxValue : null;
97
+ let timeGranularity = state.granularity === 'hour' || state.granularity === 'minute' || state.granularity === 'second' || state.granularity === 'millisecond' ? state.granularity : null;
98
+ let showTimeField = !!timeGranularity;
99
+
100
+ let visibleMonths = useVisibleMonths(maxVisibleMonths);
101
+
102
+ return (
103
+ <Field
104
+ {...props}
105
+ ref={targetRef}
106
+ description={description}
107
+ labelProps={labelProps}
108
+ descriptionProps={descriptionProps}
109
+ errorMessageProps={errorMessageProps}
110
+ validationState={state.validationState}
111
+ UNSAFE_className={classNames(datepickerStyles, 'react-spectrum-Datepicker-fieldWrapper')}>
112
+ <div
113
+ {...styleProps}
114
+ {...mergeProps(groupProps, hoverProps, focusProps)}
115
+ className={className}>
116
+ <Input
117
+ isDisabled={isDisabled}
118
+ isQuiet={isQuiet}
119
+ validationState={state.validationState}
120
+ autoFocus={autoFocus}
121
+ className={classNames(styles, 'spectrum-InputGroup-field')}
122
+ inputClassName={fieldClassName}>
123
+ <DatePickerField
124
+ {...startFieldProps}
125
+ isQuiet={props.isQuiet}
126
+ isDisabled={isDisabled}
127
+ isReadOnly={isReadOnly}
128
+ isRequired={isRequired}
129
+ validationState={state.validationState}
130
+ placeholderValue={placeholderValue}
131
+ value={value?.start || null}
132
+ defaultValue={null}
133
+ onChange={start => state.setDateTime('start', start)}
134
+ granularity={props.granularity}
135
+ hourCycle={props.hourCycle}
136
+ inputClassName={classNames(datepickerStyles, 'react-spectrum-Datepicker-startField')} />
137
+ <DateRangeDash />
138
+ <DatePickerField
139
+ {...endFieldProps}
140
+ isQuiet={props.isQuiet}
141
+ isDisabled={isDisabled}
142
+ isReadOnly={isReadOnly}
143
+ isRequired={isRequired}
144
+ validationState={state.validationState}
145
+ placeholderValue={placeholderValue}
146
+ value={value?.end || null}
147
+ defaultValue={null}
148
+ onChange={end => state.setDateTime('end', end)}
149
+ granularity={props.granularity}
150
+ hourCycle={props.hourCycle}
151
+ inputClassName={classNames(
152
+ styles,
153
+ 'spectrum-Datepicker-endField',
154
+ classNames(
155
+ datepickerStyles,
156
+ 'react-spectrum-Datepicker-endField'
157
+ )
158
+ )} />
159
+ </Input>
160
+ <DialogTrigger
161
+ type="popover"
162
+ mobileType="tray"
163
+ placement={direction === 'rtl' ? 'bottom right' : 'bottom left'}
164
+ targetRef={targetRef}
165
+ hideArrow
166
+ isOpen={isOpen}
167
+ onOpenChange={setOpen}>
168
+ <FieldButton
169
+ {...buttonProps}
170
+ UNSAFE_className={classNames(styles, 'spectrum-FieldButton')}
171
+ isQuiet={isQuiet}
172
+ validationState={state.validationState}
173
+ isDisabled={isDisabled || isReadOnly}>
174
+ <CalendarIcon />
175
+ </FieldButton>
176
+ <Dialog UNSAFE_className={classNames(datepickerStyles, 'react-spectrum-Datepicker-dialog')} {...dialogProps}>
177
+ <Content UNSAFE_className={classNames(datepickerStyles, 'react-spectrum-Datepicker-dialogContent')}>
178
+ <RangeCalendar
179
+ autoFocus
180
+ value={state.dateRange}
181
+ onChange={state.setDateRange}
182
+ visibleMonths={visibleMonths}
183
+ minValue={props.minValue}
184
+ maxValue={props.maxValue} />
185
+ {showTimeField &&
186
+ <Flex gap="size-100" marginTop="size-100" UNSAFE_className={classNames(datepickerStyles, 'react-spectrum-Datepicker-timeFields')}>
187
+ <TimeField
188
+ label="Start time"
189
+ value={state.timeRange?.start || null}
190
+ onChange={v => state.setTime('start', v)}
191
+ placeholderValue={timePlaceholder}
192
+ granularity={timeGranularity}
193
+ minValue={timeMinValue}
194
+ maxValue={timeMaxValue}
195
+ hourCycle={props.hourCycle}
196
+ hideTimeZone={props.hideTimeZone}
197
+ flex />
198
+ <TimeField
199
+ label="End time"
200
+ value={state.timeRange?.end || null}
201
+ onChange={v => state.setTime('end', v)}
202
+ placeholderValue={timePlaceholder}
203
+ granularity={timeGranularity}
204
+ minValue={timeMinValue}
205
+ maxValue={timeMaxValue}
206
+ hourCycle={props.hourCycle}
207
+ hideTimeZone={props.hideTimeZone}
208
+ flex />
209
+ </Flex>
210
+ }
211
+ </Content>
212
+ </Dialog>
213
+ </DialogTrigger>
214
+ </div>
215
+ </Field>
216
+ );
217
+ }
218
+
219
+ function DateRangeDash() {
220
+ return (
221
+ <div
222
+ aria-hidden="true"
223
+ data-testid="date-range-dash"
224
+ className={classNames(datepickerStyles, 'react-spectrum-Datepicker-rangeDash')} />
225
+ );
226
+ }
package/src/Input.tsx ADDED
@@ -0,0 +1,129 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import Alert from '@spectrum-icons/ui/AlertMedium';
14
+ import Checkmark from '@spectrum-icons/ui/CheckmarkMedium';
15
+ import {classNames, useValueEffect} from '@react-spectrum/utils';
16
+ import datepickerStyles from './index.css';
17
+ import {FocusRing, FocusScope} from '@react-aria/focus';
18
+ import {mergeProps, useEvent, useLayoutEffect, useResizeObserver} from '@react-aria/utils';
19
+ import React, {useCallback, useRef} from 'react';
20
+ import textfieldStyles from '@adobe/spectrum-css-temp/components/textfield/vars.css';
21
+
22
+ export function Input(props) {
23
+ let defaultRef = useRef();
24
+ let {
25
+ isDisabled,
26
+ isQuiet,
27
+ inputClassName,
28
+ validationState,
29
+ children,
30
+ fieldProps,
31
+ inputRef = defaultRef,
32
+ className,
33
+ autoFocus,
34
+ style
35
+ } = props;
36
+
37
+ // Reserve padding for the error icon when the width of the input is unconstrained.
38
+ // When constrained, don't reserve space because adding it only when invalid will
39
+ // not cause a layout shift.
40
+ let [reservePadding, setReservePadding] = useValueEffect(false);
41
+ let onResize = useCallback(() => setReservePadding(function *(reservePadding) {
42
+ if (reservePadding) {
43
+ // Try to collapse padding if the content is clipped.
44
+ if (inputRef.current.scrollWidth > inputRef.current.offsetWidth) {
45
+ let width = inputRef.current.parentElement.offsetWidth;
46
+ yield false;
47
+
48
+ // If removing padding causes a layout shift, add it back.
49
+ if (inputRef.current.parentElement.offsetWidth !== width) {
50
+ yield true;
51
+ }
52
+ }
53
+ } else {
54
+ // Try to add padding if the content is not clipped.
55
+ if (inputRef.current.offsetWidth >= inputRef.current.scrollWidth) {
56
+ let width = inputRef.current.parentElement.offsetWidth;
57
+ yield true;
58
+
59
+ // If adding padding does not change the width (i.e. width is constrained), remove it again.
60
+ if (inputRef.current.parentElement.offsetWidth === width) {
61
+ yield false;
62
+ }
63
+ }
64
+ }
65
+ }), [inputRef, setReservePadding]);
66
+
67
+ useLayoutEffect(onResize, [onResize]);
68
+ useResizeObserver({
69
+ ref: inputRef,
70
+ onResize
71
+ });
72
+
73
+ // We also need to listen for resize events of the window so we can detect
74
+ // when there is enough space for the padding to be re-added. Ideally we'd
75
+ // use a resize observer on a parent element, but it's hard to know _what_
76
+ // parent element.
77
+ useEvent(useRef(window), 'resize', onResize);
78
+
79
+ let isInvalid = validationState === 'invalid';
80
+ let textfieldClass = classNames(
81
+ textfieldStyles,
82
+ 'spectrum-Textfield',
83
+ {
84
+ 'spectrum-Textfield--invalid': isInvalid,
85
+ 'spectrum-Textfield--valid': validationState === 'valid',
86
+ 'spectrum-Textfield--quiet': isQuiet
87
+ },
88
+ classNames(datepickerStyles, 'react-spectrum-Datepicker-field'),
89
+ className
90
+ );
91
+
92
+ let inputClass = classNames(
93
+ textfieldStyles,
94
+ 'spectrum-Textfield-input',
95
+ {
96
+ 'is-disabled': isDisabled,
97
+ 'is-invalid': isInvalid
98
+ },
99
+ reservePadding && classNames(datepickerStyles, 'react-spectrum-Datepicker-input'),
100
+ inputClassName
101
+ );
102
+
103
+ let iconClass = classNames(
104
+ textfieldStyles,
105
+ 'spectrum-Textfield-validationIcon'
106
+ );
107
+
108
+ let validationIcon = null;
109
+ if (validationState === 'invalid') {
110
+ validationIcon = <Alert data-testid="invalid-icon" UNSAFE_className={iconClass} />;
111
+ } else if (validationState === 'valid') {
112
+ validationIcon = <Checkmark data-testid="valid-icon" UNSAFE_className={iconClass} />;
113
+ }
114
+
115
+ return (
116
+ <div {...mergeProps(fieldProps)} className={textfieldClass} style={style}>
117
+ <FocusRing focusClass={classNames(textfieldStyles, 'is-focused')} focusRingClass={classNames(textfieldStyles, 'focus-ring')} isTextInput within>
118
+ <div role="presentation" className={inputClass}>
119
+ <div role="presentation" className={classNames(datepickerStyles, 'react-spectrum-Datepicker-inputContents')} ref={inputRef}>
120
+ <FocusScope autoFocus={autoFocus}>
121
+ {children}
122
+ </FocusScope>
123
+ </div>
124
+ </div>
125
+ </FocusRing>
126
+ {validationIcon}
127
+ </div>
128
+ );
129
+ }
@@ -0,0 +1,74 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import {classNames} from '@react-spectrum/utils';
14
+ import {createCalendar} from '@internationalized/date';
15
+ import {DatePickerSegment} from './DatePickerSegment';
16
+ import datepickerStyles from './index.css';
17
+ import {Field} from '@react-spectrum/label';
18
+ import {Input} from './Input';
19
+ import React, {useRef} from 'react';
20
+ import {SpectrumTimePickerProps, TimeValue} from '@react-types/datepicker';
21
+ import {useDateField} from '@react-aria/datepicker';
22
+ import {useLocale} from '@react-aria/i18n';
23
+ import {useProviderProps} from '@react-spectrum/provider';
24
+ import {useTimeFieldState} from '@react-stately/datepicker';
25
+
26
+ export function TimeField<T extends TimeValue>(props: SpectrumTimePickerProps<T>) {
27
+ props = useProviderProps(props);
28
+ let {
29
+ autoFocus,
30
+ isDisabled,
31
+ isReadOnly,
32
+ isRequired,
33
+ isQuiet
34
+ } = props;
35
+
36
+ let ref = useRef();
37
+ let {locale} = useLocale();
38
+ let state = useTimeFieldState({
39
+ ...props,
40
+ locale,
41
+ createCalendar
42
+ });
43
+
44
+ let {labelProps, fieldProps, descriptionProps, errorMessageProps} = useDateField(props, state, ref);
45
+
46
+ return (
47
+ <Field
48
+ {...props}
49
+ labelProps={labelProps}
50
+ descriptionProps={descriptionProps}
51
+ errorMessageProps={errorMessageProps}
52
+ validationState={state.validationState}
53
+ UNSAFE_className={classNames(datepickerStyles, 'react-spectrum-TimeField-fieldWrapper')}>
54
+ <Input
55
+ fieldProps={fieldProps}
56
+ isDisabled={isDisabled}
57
+ isQuiet={isQuiet}
58
+ autoFocus={autoFocus}
59
+ validationState={state.validationState}
60
+ inputRef={ref}
61
+ className={classNames(datepickerStyles, 'react-spectrum-TimeField')}>
62
+ {state.segments.map((segment, i) =>
63
+ (<DatePickerSegment
64
+ key={i}
65
+ segment={segment}
66
+ state={state}
67
+ isDisabled={isDisabled}
68
+ isReadOnly={isReadOnly}
69
+ isRequired={isRequired} />)
70
+ )}
71
+ </Input>
72
+ </Field>
73
+ );
74
+ }
package/src/index.css ADDED
@@ -0,0 +1,161 @@
1
+ /*
2
+ * Copyright 2020 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ .react-spectrum-Datepicker-fieldWrapper.react-spectrum-Datepicker-fieldWrapper {
14
+ width: auto;
15
+ min-width: var(--spectrum-global-dimension-size-2000);
16
+ }
17
+
18
+ .react-spectrum-Datepicker-startField {
19
+ width: auto;
20
+ padding-inline-end: var(--spectrum-global-dimension-size-100);
21
+ }
22
+
23
+ .react-spectrum-Datepicker-endField {
24
+ width: auto;
25
+ flex: 1;
26
+ padding-inline-start: var(--spectrum-global-dimension-size-100);
27
+ }
28
+
29
+ .react-spectrum-Datepicker-field ~ .react-spectrum-Datepicker-endField > .react-spectrum-Datepicker-input {
30
+ border-inline-start-width: 0;
31
+ border-start-start-radius: 0;
32
+ border-end-start-radius: 0;
33
+ }
34
+
35
+ .react-spectrum-Datepicker-field.react-spectrum-Datepicker-field {
36
+ width: auto;
37
+ }
38
+
39
+ /* specificity war with .spectrum-Field--positionSide etc. */
40
+ .react-spectrum-DateField.react-spectrum-DateField.react-spectrum-DateField.react-spectrum-DateField {
41
+ min-width: var(--spectrum-global-dimension-size-2000)
42
+ }
43
+
44
+ .react-spectrum-TimeField.react-spectrum-TimeField.react-spectrum-TimeField.react-spectrum-TimeField {
45
+ min-width: var(--spectrum-global-dimension-size-1250);
46
+ }
47
+
48
+ .react-spectrum-TimeField-fieldWrapper.react-spectrum-TimeField-fieldWrapper {
49
+ width: auto;
50
+ min-width: var(--spectrum-global-dimension-size-1250);
51
+ }
52
+
53
+ .react-spectrum-Datepicker-input.react-spectrum-Datepicker-input {
54
+ /* always reserve space for the validation icon */
55
+ padding-inline-end: calc(var(--spectrum-textfield-padding-x) + var(--spectrum-icon-alert-medium-width) + var(--spectrum-textfield-icon-margin-left));
56
+ }
57
+
58
+ .react-spectrum-Datepicker-inputContents {
59
+ display: flex;
60
+ align-items: center;
61
+ /* width: auto; */
62
+ overflow-x: auto;
63
+ scrollbar-width: none; /* Firefox */
64
+ -ms-overflow-style: none; /* Internet Explorer 10+ */
65
+
66
+ &::-webkit-scrollbar { /* WebKit */
67
+ width: 0;
68
+ height: 0;
69
+ display: none;
70
+ }
71
+ }
72
+
73
+ .react-spectrum-Datepicker-rangeDash {
74
+ &:before {
75
+ content: '–';
76
+ }
77
+ }
78
+
79
+ .react-spectrum-Datepicker-segments {
80
+ display: flex;
81
+ align-items: center;
82
+ }
83
+
84
+ .react-spectrum-Datepicker-literal {
85
+ white-space: pre;
86
+ user-select: none;
87
+ color: var(--spectrum-textfield-text-color);
88
+ }
89
+
90
+ .react-spectrum-DatePicker-cell {
91
+ border: none;
92
+ background: none;
93
+ padding: 0 2px;
94
+ border-radius: 2px;
95
+ font-variant-numeric: tabular-nums;
96
+ text-align: end;
97
+ box-sizing: content-box;
98
+ white-space: nowrap;
99
+ color: var(--spectrum-textfield-text-color);
100
+
101
+ &::selection {
102
+ /* hide the selection because there is no way to fully prevent it in Firefox */
103
+ /* https://bugzilla.mozilla.org/show_bug.cgi?id=1742153 */
104
+ background: transparent;
105
+ }
106
+ }
107
+
108
+ .react-spectrum-DatePicker-cell:focus {
109
+ background-color: var(--spectrum-global-color-static-blue);
110
+ color: white;
111
+ caret-color: transparent;
112
+ outline: none;
113
+ }
114
+
115
+ .react-spectrum-DatePicker-cell.is-placeholder {
116
+ color: var(--spectrum-textfield-placeholder-text-color, var(--spectrum-global-color-gray-600));
117
+
118
+ &:before {
119
+ content: attr(aria-placeholder);
120
+ }
121
+ }
122
+
123
+ .react-spectrum-DatePicker-cell.is-placeholder ~ .react-spectrum-Datepicker-literal {
124
+ color: var(--spectrum-textfield-placeholder-text-color, var(--spectrum-global-color-gray-600));
125
+ }
126
+
127
+ .react-spectrum-DatePicker-cell.is-placeholder:focus {
128
+ color: var(--spectrum-global-color-static-gray-400);
129
+ }
130
+
131
+ .react-spectrum-DatePicker-cell.is-read-only {
132
+ color: var(--spectrum-global-color-gray-700);
133
+ &:focus {
134
+ color: var(--spectrum-global-color-static-gray-300);
135
+ }
136
+ }
137
+
138
+ .react-spectrum-Datepicker-dialog {
139
+ width: auto;
140
+ }
141
+
142
+ /* when displayed in a tray, reduce the padding of the dialog */
143
+ @media (max-width: 700px) {
144
+ .react-spectrum-Datepicker-dialog {
145
+ --spectrum-dialog-padding-x: 8px;
146
+
147
+ .react-spectrum-Datepicker-dialogContent {
148
+ display: flex;
149
+ flex-direction: column;
150
+ align-items: center;
151
+ }
152
+ }
153
+ }
154
+
155
+ .react-spectrum-Datepicker-timeFields {
156
+ width: 100%;
157
+ min-width: calc(var(--spectrum-calendar-day-width) * 7);
158
+ max-width: calc((var(--spectrum-calendar-day-width) * 7) + (var(--spectrum-calendar-day-padding) * 12));
159
+ padding: 0 var(--spectrum-calendar-day-padding);
160
+ box-sizing: border-box;
161
+ }