@toptal/picasso-timepicker 100.0.3 → 100.1.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.
- package/dist-package/src/TimePicker/TimePicker.d.ts +4 -1
- package/dist-package/src/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist-package/src/TimePicker/TimePicker.js +60 -21
- package/dist-package/src/TimePicker/TimePicker.js.map +1 -1
- package/dist-package/src/TimePicker/use-time-picker-popover.d.ts +21 -0
- package/dist-package/src/TimePicker/use-time-picker-popover.d.ts.map +1 -0
- package/dist-package/src/TimePicker/use-time-picker-popover.js +96 -0
- package/dist-package/src/TimePicker/use-time-picker-popover.js.map +1 -0
- package/dist-package/src/TimePicker/utils/get-hour-cycle.d.ts +3 -0
- package/dist-package/src/TimePicker/utils/get-hour-cycle.d.ts.map +1 -0
- package/dist-package/src/TimePicker/utils/get-hour-cycle.js +42 -0
- package/dist-package/src/TimePicker/utils/get-hour-cycle.js.map +1 -0
- package/dist-package/src/TimePicker/utils/index.d.ts +5 -0
- package/dist-package/src/TimePicker/utils/index.d.ts.map +1 -0
- package/dist-package/src/TimePicker/utils/index.js +3 -0
- package/dist-package/src/TimePicker/utils/index.js.map +1 -0
- package/dist-package/src/TimePicker/utils/time.d.ts +16 -0
- package/dist-package/src/TimePicker/utils/time.d.ts.map +1 -0
- package/dist-package/src/TimePicker/utils/time.js +41 -0
- package/dist-package/src/TimePicker/utils/time.js.map +1 -0
- package/dist-package/src/TimePickerDropdown/TimePickerDropdown.d.ts +13 -0
- package/dist-package/src/TimePickerDropdown/TimePickerDropdown.d.ts.map +1 -0
- package/dist-package/src/TimePickerDropdown/TimePickerDropdown.js +28 -0
- package/dist-package/src/TimePickerDropdown/TimePickerDropdown.js.map +1 -0
- package/dist-package/src/TimePickerDropdown/index.d.ts +2 -0
- package/dist-package/src/TimePickerDropdown/index.d.ts.map +1 -0
- package/dist-package/src/TimePickerDropdown/index.js +2 -0
- package/dist-package/src/TimePickerDropdown/index.js.map +1 -0
- package/dist-package/src/TimePickerList/TimePickerList.d.ts +23 -0
- package/dist-package/src/TimePickerList/TimePickerList.d.ts.map +1 -0
- package/dist-package/src/TimePickerList/TimePickerList.js +97 -0
- package/dist-package/src/TimePickerList/TimePickerList.js.map +1 -0
- package/dist-package/src/TimePickerList/index.d.ts +4 -0
- package/dist-package/src/TimePickerList/index.d.ts.map +1 -0
- package/dist-package/src/TimePickerList/index.js +2 -0
- package/dist-package/src/TimePickerList/index.js.map +1 -0
- package/dist-package/src/TimePickerTrigger/TimePickerTrigger.d.ts +16 -0
- package/dist-package/src/TimePickerTrigger/TimePickerTrigger.d.ts.map +1 -0
- package/dist-package/src/TimePickerTrigger/TimePickerTrigger.js +11 -0
- package/dist-package/src/TimePickerTrigger/TimePickerTrigger.js.map +1 -0
- package/dist-package/src/TimePickerTrigger/index.d.ts +2 -0
- package/dist-package/src/TimePickerTrigger/index.d.ts.map +1 -0
- package/dist-package/src/TimePickerTrigger/index.js +2 -0
- package/dist-package/src/TimePickerTrigger/index.js.map +1 -0
- package/package.json +4 -1
- package/src/TimePicker/TimePicker.tsx +161 -65
- package/src/TimePicker/story/MinuteStep.example.tsx +16 -0
- package/src/TimePicker/story/index.jsx +10 -0
- package/src/TimePicker/test.tsx +649 -1
- package/src/TimePicker/use-time-picker-popover.ts +120 -0
- package/src/TimePicker/utils/get-hour-cycle.test.ts +76 -0
- package/src/TimePicker/utils/get-hour-cycle.ts +63 -0
- package/src/TimePicker/utils/index.ts +10 -0
- package/src/TimePicker/utils/time.test.ts +143 -0
- package/src/TimePicker/utils/time.ts +76 -0
- package/src/TimePickerDropdown/TimePickerDropdown.tsx +45 -0
- package/src/TimePickerDropdown/index.ts +1 -0
- package/src/TimePickerList/TimePickerList.tsx +190 -0
- package/src/TimePickerList/index.ts +4 -0
- package/src/TimePickerTrigger/TimePickerTrigger.tsx +53 -0
- package/src/TimePickerTrigger/index.ts +1 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from 'react';
|
|
1
2
|
import type { BaseProps } from '@toptal/picasso-shared';
|
|
2
3
|
import type { InputProps } from '@toptal/picasso-input';
|
|
3
4
|
import type { Status } from '@toptal/picasso-outlined-input';
|
|
@@ -8,9 +9,11 @@ export interface Props extends BaseProps, Omit<InputProps, 'id' | 'value' | 'onS
|
|
|
8
9
|
status?: Extract<Status, 'error' | 'warning' | 'default'>;
|
|
9
10
|
/** Called on input change */
|
|
10
11
|
onChange?: (value: string) => void;
|
|
12
|
+
/** Interval in minutes between the times offered in a dropdown list. When omitted, the browser's own time picker is used */
|
|
13
|
+
minuteStep?: 5 | 10 | 15 | 20 | 30 | 60;
|
|
11
14
|
}
|
|
12
15
|
export declare const TimePicker: {
|
|
13
|
-
({ status, ...props }: Props):
|
|
16
|
+
({ status, ...props }: Props): React.ReactElement;
|
|
14
17
|
displayName: string;
|
|
15
18
|
};
|
|
16
19
|
export default TimePicker;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimePicker.d.ts","sourceRoot":"","sources":["../../../src/TimePicker/TimePicker.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TimePicker.d.ts","sourceRoot":"","sources":["../../../src/TimePicker/TimePicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAKvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAA;AAQ5D,MAAM,WAAW,KACf,SAAQ,SAAS,EACf,IAAI,CACF,UAAU,EACR,IAAI,GACJ,OAAO,GACP,UAAU,GACV,UAAU,GACV,MAAM,GACN,WAAW,GACX,MAAM,GACN,cAAc,GACd,MAAM,GACN,MAAM,GACN,cAAc,GACd,SAAS,GACT,cAAc,GACd,gBAAgB,GAChB,oBAAoB,GACpB,SAAS,GACT,OAAO,GACP,aAAa,GACb,QAAQ,CACX;IACH,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gFAAgF;IAChF,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC,CAAA;IACzD,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,4HAA4H;IAC5H,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;CACxC;AAqBD,eAAO,MAAM,UAAU;2BAGpB,KAAK,GAAG,KAAK,CAAC,YAAY;;CAmL5B,CAAA;AAID,eAAe,UAAU,CAAA"}
|
|
@@ -15,19 +15,34 @@ import { detect } from 'detect-browser';
|
|
|
15
15
|
import { Input } from '@toptal/picasso-input';
|
|
16
16
|
import { Time16 } from '@toptal/picasso-icons';
|
|
17
17
|
import { twMerge } from '@toptal/picasso-tailwind-merge';
|
|
18
|
-
|
|
18
|
+
import { TimePickerDropdown } from '../TimePickerDropdown';
|
|
19
|
+
import { TimePickerTrigger } from '../TimePickerTrigger';
|
|
20
|
+
import { useTimePickerPopover } from './use-time-picker-popover';
|
|
21
|
+
import { VALID_TIME_REGEX, getHourCycle } from './utils';
|
|
22
|
+
const NATIVE_PICKER_CLASS_NAME = `-mr-2 [&::-webkit-calendar-picker-indicator]:absolute [&::-webkit-calendar-picker-indicator]:right-2
|
|
23
|
+
[&::-webkit-calendar-picker-indicator]:cursor-pointer [&::-webkit-calendar-picker-indicator]:bg-none`;
|
|
24
|
+
const TIME_LIST_CLASS_NAME = `${NATIVE_PICKER_CLASS_NAME} pointer-fine:[&::-webkit-calendar-picker-indicator]:hidden`;
|
|
25
|
+
const nativePickerIcon = (React.createElement(Time16, { classes: {
|
|
26
|
+
root: 'bg-white absolute right-[0.625rem] pointer-events-none m-0 select-none',
|
|
27
|
+
} }));
|
|
28
|
+
const getInputMask = (value) => {
|
|
29
|
+
const startsWithTwo = value && value[0] === '2';
|
|
30
|
+
return [/[0-2]/, startsWithTwo ? /[0-3]/ : /[0-9]/, ':', /[0-5]/, /[0-9]/];
|
|
31
|
+
};
|
|
19
32
|
export const TimePicker = (_a) => {
|
|
33
|
+
var _b;
|
|
20
34
|
var { status = 'default' } = _a, props = __rest(_a, ["status"]);
|
|
21
|
-
const { onChange: externalOnChange, value: externalValue, width, className, highlight, size } = props, rest = __rest(props, ["onChange", "value", "width", "className", "highlight", "size"]);
|
|
35
|
+
const { onChange: externalOnChange, onKeyDown: externalOnKeyDown, onBlur: externalOnBlur, onFocus: externalOnFocus, value: externalValue, width, className, highlight, size, minuteStep } = props, rest = __rest(props, ["onChange", "onKeyDown", "onBlur", "onFocus", "value", "width", "className", "highlight", "size", "minuteStep"]);
|
|
22
36
|
const [value, setValue] = useState(externalValue);
|
|
37
|
+
const hasTimeList = minuteStep !== undefined;
|
|
38
|
+
const interactive = hasTimeList && !rest.disabled && !rest.readOnly;
|
|
23
39
|
useEffect(() => {
|
|
24
40
|
// Set internal value based on the provided one if the later is correct
|
|
25
41
|
if (externalValue && VALID_TIME_REGEX.test(externalValue)) {
|
|
26
42
|
setValue(externalValue);
|
|
27
43
|
}
|
|
28
44
|
}, [externalValue]);
|
|
29
|
-
const
|
|
30
|
-
const newValue = event.target.value;
|
|
45
|
+
const changeValue = (newValue) => {
|
|
31
46
|
setValue(newValue);
|
|
32
47
|
if (newValue && VALID_TIME_REGEX.test(newValue)) {
|
|
33
48
|
externalOnChange === null || externalOnChange === void 0 ? void 0 : externalOnChange(newValue);
|
|
@@ -36,26 +51,50 @@ export const TimePicker = (_a) => {
|
|
|
36
51
|
externalOnChange === null || externalOnChange === void 0 ? void 0 : externalOnChange('');
|
|
37
52
|
}
|
|
38
53
|
};
|
|
39
|
-
const
|
|
40
|
-
const isSafari = (
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
54
|
+
const onChange = (event) => changeValue(event.target.value);
|
|
55
|
+
const isSafari = ((_b = detect()) === null || _b === void 0 ? void 0 : _b.name) === 'safari';
|
|
56
|
+
const { isOpen, hourCycle, anchorRef, listRef, focusList, isFocusChangeWithinList, handleTriggerClick, handleClickAway, closeAndFocusField, handleFieldFocus, handleFieldKeyDown, } = useTimePickerPopover({
|
|
57
|
+
enabled: interactive,
|
|
58
|
+
// Safari renders its own 24-hour masked field, so the list has to match it
|
|
59
|
+
getHourCycle: () => (isSafari ? 24 : getHourCycle()),
|
|
60
|
+
});
|
|
61
|
+
const handleTimePick = (time) => {
|
|
62
|
+
changeValue(time);
|
|
63
|
+
closeAndFocusField();
|
|
64
|
+
};
|
|
65
|
+
const handleKeyDown = (event) => {
|
|
66
|
+
externalOnKeyDown === null || externalOnKeyDown === void 0 ? void 0 : externalOnKeyDown(event);
|
|
67
|
+
handleFieldKeyDown(event);
|
|
68
|
+
};
|
|
69
|
+
const handleBlur = (event) => {
|
|
70
|
+
if (!isFocusChangeWithinList(event)) {
|
|
71
|
+
externalOnBlur === null || externalOnBlur === void 0 ? void 0 : externalOnBlur(event);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const handleFocus = (event) => {
|
|
75
|
+
handleFieldFocus();
|
|
76
|
+
if (!isFocusChangeWithinList(event)) {
|
|
77
|
+
externalOnFocus === null || externalOnFocus === void 0 ? void 0 : externalOnFocus(event);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const adornmentProps = hasTimeList
|
|
81
|
+
? {
|
|
82
|
+
endAdornment: (React.createElement(TimePickerTrigger, { open: isOpen, disabled: !interactive, onClick: handleTriggerClick })),
|
|
83
|
+
}
|
|
84
|
+
: { iconPosition: 'end', icon: nativePickerIcon };
|
|
85
|
+
const timeList = hasTimeList && (React.createElement(TimePickerDropdown, { ref: listRef, open: isOpen, anchorEl: anchorRef.current, onClickAway: handleClickAway, value: value, minuteStep: minuteStep, hourCycle: hourCycle, autoFocus: focusList, onChange: handleTimePick, onClose: closeAndFocusField }));
|
|
52
86
|
const inputClassName = twMerge('cursor-default', className);
|
|
53
|
-
const inputPropClassName =
|
|
54
|
-
|
|
87
|
+
const inputPropClassName = hasTimeList
|
|
88
|
+
? TIME_LIST_CLASS_NAME
|
|
89
|
+
: NATIVE_PICKER_CLASS_NAME;
|
|
55
90
|
if (isSafari) {
|
|
56
|
-
return (React.createElement(
|
|
91
|
+
return (React.createElement(React.Fragment, null,
|
|
92
|
+
React.createElement(Input, Object.assign({ type: 'text', readOnly: true }, adornmentProps, { width: width, status: status, className: inputClassName, highlight: highlight, size: size, outlineRef: anchorRef, inputProps: Object.assign({ className: inputPropClassName }, rest), startAdornment: React.createElement(InputMask, { mask: getInputMask(value), alwaysShowMask: true, maskPlaceholder: '-', value: value, onChange: onChange, onKeyDown: handleKeyDown, onBlur: handleBlur, onFocus: handleFocus, className: 'text-sm border-none p-0 m-0 outline-hidden' }) })),
|
|
93
|
+
timeList));
|
|
57
94
|
}
|
|
58
|
-
return (React.createElement(
|
|
95
|
+
return (React.createElement(React.Fragment, null,
|
|
96
|
+
React.createElement(Input, Object.assign({ type: 'time', value: value, className: inputClassName, onChange: onChange, onKeyDown: handleKeyDown, onBlur: handleBlur, onFocus: handleFocus }, adornmentProps, { highlight: highlight, width: width, size: size, status: status, outlineRef: anchorRef, inputProps: Object.assign({ className: inputPropClassName, step: 60 }, rest) })),
|
|
97
|
+
timeList));
|
|
59
98
|
};
|
|
60
99
|
TimePicker.displayName = 'TimePicker';
|
|
61
100
|
export default TimePicker;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimePicker.js","sourceRoot":"","sources":["../../../src/TimePicker/TimePicker.tsx"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAElD,OAAO,SAAS,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAG9C,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;
|
|
1
|
+
{"version":3,"file":"TimePicker.js","sourceRoot":"","sources":["../../../src/TimePicker/TimePicker.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import type { HourCycle } from './utils';
|
|
3
|
+
interface Options {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
getHourCycle: () => HourCycle;
|
|
6
|
+
}
|
|
7
|
+
export declare const useTimePickerPopover: ({ enabled, getHourCycle }: Options) => {
|
|
8
|
+
isOpen: boolean;
|
|
9
|
+
hourCycle: HourCycle;
|
|
10
|
+
anchorRef: React.RefObject<HTMLElement>;
|
|
11
|
+
listRef: React.RefObject<HTMLDivElement>;
|
|
12
|
+
focusList: boolean;
|
|
13
|
+
isFocusChangeWithinList: (event: React.FocusEvent) => boolean;
|
|
14
|
+
handleTriggerClick: () => void;
|
|
15
|
+
handleClickAway: (event: React.MouseEvent) => void;
|
|
16
|
+
closeAndFocusField: () => void;
|
|
17
|
+
handleFieldFocus: () => void;
|
|
18
|
+
handleFieldKeyDown: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=use-time-picker-popover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-time-picker-popover.d.ts","sourceRoot":"","sources":["../../../src/TimePicker/use-time-picker-popover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAExC,UAAU,OAAO;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,YAAY,EAAE,MAAM,SAAS,CAAA;CAC9B;AAMD,eAAO,MAAM,oBAAoB,8BAA+B,OAAO;;;;;;qCAgD7B,KAAK,CAAC,UAAU;;6BANxB,KAAK,CAAC,UAAU;;;gCAgBb,KAAK,CAAC,aAAa,CAAC,gBAAgB,CAAC;CA+CzE,CAAA"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
// The shortcuts a browser uses to open the native time picker
|
|
3
|
+
const isOpenShortcut = (event) => event.key === ' ' || (event.key === 'ArrowDown' && event.altKey);
|
|
4
|
+
export const useTimePickerPopover = ({ enabled, getHourCycle }) => {
|
|
5
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
6
|
+
const [focusList, setFocusList] = useState(false);
|
|
7
|
+
const [hourCycle, setHourCycle] = useState(24);
|
|
8
|
+
const anchorRef = useRef(null);
|
|
9
|
+
const listRef = useRef(null);
|
|
10
|
+
const focusField = () => {
|
|
11
|
+
var _a, _b;
|
|
12
|
+
return (_b = (_a = anchorRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('input:not([readonly])')) === null || _b === void 0 ? void 0 : _b.focus();
|
|
13
|
+
};
|
|
14
|
+
const open = ({ focusList: shouldFocusList }) => {
|
|
15
|
+
setFocusList(shouldFocusList);
|
|
16
|
+
setHourCycle(getHourCycle());
|
|
17
|
+
setIsOpen(true);
|
|
18
|
+
};
|
|
19
|
+
const close = () => setIsOpen(false);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (!enabled) {
|
|
22
|
+
close();
|
|
23
|
+
}
|
|
24
|
+
}, [enabled]);
|
|
25
|
+
const closeAndFocusField = () => {
|
|
26
|
+
close();
|
|
27
|
+
focusField();
|
|
28
|
+
};
|
|
29
|
+
const handleTriggerClick = () => {
|
|
30
|
+
if (isOpen) {
|
|
31
|
+
closeAndFocusField();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
open({ focusList: false });
|
|
35
|
+
focusField();
|
|
36
|
+
};
|
|
37
|
+
const handleClickAway = (event) => {
|
|
38
|
+
var _a;
|
|
39
|
+
if (!((_a = anchorRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target))) {
|
|
40
|
+
close();
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const isFocusChangeWithinList = (event) => {
|
|
44
|
+
var _a;
|
|
45
|
+
return event.relatedTarget instanceof Node &&
|
|
46
|
+
Boolean((_a = listRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.relatedTarget));
|
|
47
|
+
};
|
|
48
|
+
const handleFieldFocus = () => {
|
|
49
|
+
// Focus is back in the field, so the next shortcut must be able to move it
|
|
50
|
+
// into the list again
|
|
51
|
+
setFocusList(false);
|
|
52
|
+
};
|
|
53
|
+
const handleFieldKeyDown = (event) => {
|
|
54
|
+
if (!isOpen) {
|
|
55
|
+
if (enabled && isOpenShortcut(event)) {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
open({ focusList: true });
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (isOpenShortcut(event)) {
|
|
62
|
+
// Keeps the browser from opening its own time picker over the list
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
setFocusList(true);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
switch (event.key) {
|
|
68
|
+
case 'Escape':
|
|
69
|
+
// Keeps a surrounding Modal or Drawer open while the list closes
|
|
70
|
+
event.stopPropagation();
|
|
71
|
+
close();
|
|
72
|
+
break;
|
|
73
|
+
case 'Enter':
|
|
74
|
+
event.preventDefault();
|
|
75
|
+
close();
|
|
76
|
+
break;
|
|
77
|
+
case 'Tab':
|
|
78
|
+
close();
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
isOpen,
|
|
84
|
+
hourCycle,
|
|
85
|
+
anchorRef,
|
|
86
|
+
listRef,
|
|
87
|
+
focusList,
|
|
88
|
+
isFocusChangeWithinList,
|
|
89
|
+
handleTriggerClick,
|
|
90
|
+
handleClickAway,
|
|
91
|
+
closeAndFocusField,
|
|
92
|
+
handleFieldFocus,
|
|
93
|
+
handleFieldKeyDown,
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=use-time-picker-popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-time-picker-popover.js","sourceRoot":"","sources":["../../../src/TimePicker/use-time-picker-popover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-hour-cycle.d.ts","sourceRoot":"","sources":["../../../../src/TimePicker/utils/get-hour-cycle.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,CAAA;AA6D/B,eAAO,MAAM,YAAY,YAAa,MAAM,KAAG,SACU,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const PROBE_CLASS_NAME = 'fixed top-0 left-0 invisible pointer-events-none h-auto p-0 border-0';
|
|
2
|
+
// Blink calls the AM/PM segment `ampm-field`, WebKit calls it `meridiem-field`
|
|
3
|
+
const SEGMENT_CLASS_NAMES = {
|
|
4
|
+
hour: '[&::-webkit-datetime-edit-hour-field]:inline-block [&::-webkit-datetime-edit-hour-field]:h-screen',
|
|
5
|
+
ampm: '[&::-webkit-datetime-edit-ampm-field]:inline-block [&::-webkit-datetime-edit-ampm-field]:h-screen [&::-webkit-datetime-edit-meridiem-field]:inline-block [&::-webkit-datetime-edit-meridiem-field]:h-screen',
|
|
6
|
+
};
|
|
7
|
+
const measureProbe = (segment) => {
|
|
8
|
+
const probe = document.createElement('input');
|
|
9
|
+
probe.type = 'time';
|
|
10
|
+
probe.tabIndex = -1;
|
|
11
|
+
probe.setAttribute('aria-hidden', 'true');
|
|
12
|
+
probe.className = PROBE_CLASS_NAME;
|
|
13
|
+
if (segment) {
|
|
14
|
+
probe.className += ` ${SEGMENT_CLASS_NAMES[segment]}`;
|
|
15
|
+
probe.setAttribute('data-testid', `time-picker-probe-${segment}`);
|
|
16
|
+
}
|
|
17
|
+
document.body.appendChild(probe);
|
|
18
|
+
const height = probe.offsetHeight;
|
|
19
|
+
probe.remove();
|
|
20
|
+
return height;
|
|
21
|
+
};
|
|
22
|
+
// The native field follows the operating system's 12/24-hour setting, which
|
|
23
|
+
// `Intl` does not see, so the field itself is the only reliable source
|
|
24
|
+
const getNativeFieldHourCycle = () => {
|
|
25
|
+
if (typeof document === 'undefined') {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const stretchedHeight = measureProbe() * 2;
|
|
29
|
+
const rendersSegment = (segment) => measureProbe(segment) > stretchedHeight;
|
|
30
|
+
if (!rendersSegment('hour')) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return rendersSegment('ampm') ? 12 : 24;
|
|
34
|
+
};
|
|
35
|
+
const getLocaleHourCycle = (locale) => {
|
|
36
|
+
const { hour12 } = new Intl.DateTimeFormat(locale, {
|
|
37
|
+
hour: 'numeric',
|
|
38
|
+
}).resolvedOptions();
|
|
39
|
+
return hour12 ? 12 : 24;
|
|
40
|
+
};
|
|
41
|
+
export const getHourCycle = (locale) => { var _a; return (_a = getNativeFieldHourCycle()) !== null && _a !== void 0 ? _a : getLocaleHourCycle(locale); };
|
|
42
|
+
//# sourceMappingURL=get-hour-cycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-hour-cycle.js","sourceRoot":"","sources":["../../../../src/TimePicker/utils/get-hour-cycle.ts"],"names":[],"mappings":"AAIA,MAAM,gBAAgB,GACpB,sEAAsE,CAAA;AAExE,+EAA+E;AAC/E,MAAM,mBAAmB,GAA4B;IACnD,IAAI,EAAE,mGAAmG;IACzG,IAAI,EAAE,6MAA6M;CACpN,CAAA;AAED,MAAM,YAAY,GAAG,CAAC,OAAiB,EAAE,EAAE;IACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;IAE7C,KAAK,CAAC,IAAI,GAAG,MAAM,CAAA;IACnB,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAA;IACnB,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;IACzC,KAAK,CAAC,SAAS,GAAG,gBAAgB,CAAA;IAElC,IAAI,OAAO,EAAE,CAAC;QACZ,KAAK,CAAC,SAAS,IAAI,IAAI,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAA;QACrD,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,qBAAqB,OAAO,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IAEhC,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,CAAA;IAEjC,KAAK,CAAC,MAAM,EAAE,CAAA;IAEd,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,4EAA4E;AAC5E,uEAAuE;AACvE,MAAM,uBAAuB,GAAG,GAA0B,EAAE;IAC1D,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QACpC,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,eAAe,GAAG,YAAY,EAAE,GAAG,CAAC,CAAA;IAC1C,MAAM,cAAc,GAAG,CAAC,OAAgB,EAAE,EAAE,CAC1C,YAAY,CAAC,OAAO,CAAC,GAAG,eAAe,CAAA;IAEzC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACzC,CAAC,CAAA;AAED,MAAM,kBAAkB,GAAG,CAAC,MAAe,EAAa,EAAE;IACxD,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE;QACjD,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC,eAAe,EAAE,CAAA;IAEpB,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACzB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAe,EAAa,EAAE,WACzD,OAAA,MAAA,uBAAuB,EAAE,mCAAI,kBAAkB,CAAC,MAAM,CAAC,CAAA,EAAA,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { getHourCycle } from './get-hour-cycle';
|
|
2
|
+
export type { HourCycle } from './get-hour-cycle';
|
|
3
|
+
export { VALID_TIME_REGEX, getCurrentTime, getNearestOptionIndex, getTimeOptions, parseTime, } from './time';
|
|
4
|
+
export type { Time, TimeOption } from './time';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/TimePicker/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,SAAS,GACV,MAAM,QAAQ,CAAA;AACf,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/TimePicker/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,SAAS,GACV,MAAM,QAAQ,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { HourCycle } from './get-hour-cycle';
|
|
2
|
+
export interface Time {
|
|
3
|
+
hours: number;
|
|
4
|
+
minutes: number;
|
|
5
|
+
}
|
|
6
|
+
export interface TimeOption {
|
|
7
|
+
value: string;
|
|
8
|
+
label: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const VALID_TIME_REGEX: RegExp;
|
|
11
|
+
export declare const parseTime: (value?: string) => Time | undefined;
|
|
12
|
+
export declare const formatTime: ({ hours, minutes }: Time) => string;
|
|
13
|
+
export declare const getCurrentTime: () => Time;
|
|
14
|
+
export declare const getTimeOptions: (minuteStep: number, hourCycle: HourCycle) => TimeOption[];
|
|
15
|
+
export declare const getNearestOptionIndex: (time: Time, minuteStep: number) => number;
|
|
16
|
+
//# sourceMappingURL=time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../../../src/TimePicker/utils/time.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,eAAO,MAAM,gBAAgB,QAAqC,CAAA;AAQlE,eAAO,MAAM,SAAS,WAAY,MAAM,KAAG,IAAI,GAAG,SAQjD,CAAA;AAED,eAAO,MAAM,UAAU,uBAAwB,IAAI,WACF,CAAA;AAEjD,eAAO,MAAM,cAAc,QAAO,IAIjC,CAAA;AAaD,eAAO,MAAM,cAAc,eACb,MAAM,aACP,SAAS,KACnB,UAAU,EAgBZ,CAAA;AAED,eAAO,MAAM,qBAAqB,SAAU,IAAI,cAAc,MAAM,WAIjE,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export const VALID_TIME_REGEX = /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/;
|
|
2
|
+
const MINUTES_IN_HOUR = 60;
|
|
3
|
+
const MINUTES_IN_DAY = 24 * MINUTES_IN_HOUR;
|
|
4
|
+
const HALF_DAY = 12;
|
|
5
|
+
const padTimePart = (part) => String(part).padStart(2, '0');
|
|
6
|
+
export const parseTime = (value) => {
|
|
7
|
+
if (!value || !VALID_TIME_REGEX.test(value)) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
const [hours, minutes] = value.split(':').map(Number);
|
|
11
|
+
return { hours, minutes };
|
|
12
|
+
};
|
|
13
|
+
export const formatTime = ({ hours, minutes }) => `${padTimePart(hours)}:${padTimePart(minutes)}`;
|
|
14
|
+
export const getCurrentTime = () => {
|
|
15
|
+
const now = new Date();
|
|
16
|
+
return { hours: now.getHours(), minutes: now.getMinutes() };
|
|
17
|
+
};
|
|
18
|
+
const formatLabel = (time, hourCycle) => {
|
|
19
|
+
if (hourCycle === 24) {
|
|
20
|
+
return formatTime(time);
|
|
21
|
+
}
|
|
22
|
+
const hours = time.hours % HALF_DAY || HALF_DAY;
|
|
23
|
+
const period = time.hours < HALF_DAY ? 'AM' : 'PM';
|
|
24
|
+
return `${formatTime({ hours, minutes: time.minutes })} ${period}`;
|
|
25
|
+
};
|
|
26
|
+
export const getTimeOptions = (minuteStep, hourCycle) => {
|
|
27
|
+
const options = [];
|
|
28
|
+
for (let minutes = 0; minutes < MINUTES_IN_DAY; minutes += minuteStep) {
|
|
29
|
+
const time = {
|
|
30
|
+
hours: Math.floor(minutes / MINUTES_IN_HOUR),
|
|
31
|
+
minutes: minutes % MINUTES_IN_HOUR,
|
|
32
|
+
};
|
|
33
|
+
options.push({
|
|
34
|
+
value: formatTime(time),
|
|
35
|
+
label: formatLabel(time, hourCycle),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return options;
|
|
39
|
+
};
|
|
40
|
+
export const getNearestOptionIndex = (time, minuteStep) => Math.min(Math.round((time.hours * MINUTES_IN_HOUR + time.minutes) / minuteStep), Math.ceil(MINUTES_IN_DAY / minuteStep) - 1);
|
|
41
|
+
//# sourceMappingURL=time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.js","sourceRoot":"","sources":["../../../../src/TimePicker/utils/time.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,gBAAgB,GAAG,kCAAkC,CAAA;AAElE,MAAM,eAAe,GAAG,EAAE,CAAA;AAC1B,MAAM,cAAc,GAAG,EAAE,GAAG,eAAe,CAAA;AAC3C,MAAM,QAAQ,GAAG,EAAE,CAAA;AAEnB,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAEnE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAc,EAAoB,EAAE;IAC5D,IAAI,CAAC,KAAK,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAErD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAQ,EAAE,EAAE,CACrD,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAA;AAEjD,MAAM,CAAC,MAAM,cAAc,GAAG,GAAS,EAAE;IACvC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAA;IAEtB,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,EAAE,CAAA;AAC7D,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,CAAC,IAAU,EAAE,SAAoB,EAAE,EAAE;IACvD,IAAI,SAAS,KAAK,EAAE,EAAE,CAAC;QACrB,OAAO,UAAU,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,QAAQ,IAAI,QAAQ,CAAA;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;IAElD,OAAO,GAAG,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,MAAM,EAAE,CAAA;AACpE,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,UAAkB,EAClB,SAAoB,EACN,EAAE;IAChB,MAAM,OAAO,GAAiB,EAAE,CAAA;IAEhC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,cAAc,EAAE,OAAO,IAAI,UAAU,EAAE,CAAC;QACtE,MAAM,IAAI,GAAG;YACX,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,eAAe,CAAC;YAC5C,OAAO,EAAE,OAAO,GAAG,eAAe;SACnC,CAAA;QAED,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC;YACvB,KAAK,EAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC;SACpC,CAAC,CAAA;IACJ,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAU,EAAE,UAAkB,EAAE,EAAE,CACtE,IAAI,CAAC,GAAG,CACN,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,UAAU,CAAC,EACtE,IAAI,CAAC,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,CAAC,CAC3C,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { TimePickerListProps } from '../TimePickerList';
|
|
3
|
+
export interface Props extends TimePickerListProps {
|
|
4
|
+
/** Whether the dropdown is shown */
|
|
5
|
+
open: boolean;
|
|
6
|
+
/** Element the dropdown is positioned under */
|
|
7
|
+
anchorEl: HTMLElement | null;
|
|
8
|
+
/** Called when a click lands outside of the dropdown */
|
|
9
|
+
onClickAway: (event: React.MouseEvent) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const TimePickerDropdown: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLDivElement>>;
|
|
12
|
+
export default TimePickerDropdown;
|
|
13
|
+
//# sourceMappingURL=TimePickerDropdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePickerDropdown.d.ts","sourceRoot":"","sources":["../../../src/TimePickerDropdown/TimePickerDropdown.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqB,MAAM,OAAO,CAAA;AAKzC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE5D,MAAM,WAAW,KAAM,SAAQ,mBAAmB;IAChD,oCAAoC;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,+CAA+C;IAC/C,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,wDAAwD;IACxD,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAA;CAC/C;AAED,eAAO,MAAM,kBAAkB,8EAwB9B,CAAA;AAID,eAAe,kBAAkB,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React, { forwardRef } from 'react';
|
|
13
|
+
import { Popper } from '@toptal/picasso-popper';
|
|
14
|
+
import { ClickAwayListener } from '@toptal/picasso-utils';
|
|
15
|
+
import { TimePickerList } from '../TimePickerList';
|
|
16
|
+
export const TimePickerDropdown = forwardRef(function TimePickerDropdown(_a, ref) {
|
|
17
|
+
var { open, anchorEl, onClickAway } = _a, rest = __rest(_a, ["open", "anchorEl", "onClickAway"]);
|
|
18
|
+
if (!open || !anchorEl) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return (React.createElement(Popper, { open: true, role: 'presentation', anchorEl: anchorEl, placement: 'bottom-start' },
|
|
22
|
+
React.createElement(ClickAwayListener, { onClickAway: onClickAway },
|
|
23
|
+
React.createElement("div", { ref: ref },
|
|
24
|
+
React.createElement(TimePickerList, Object.assign({}, rest))))));
|
|
25
|
+
});
|
|
26
|
+
TimePickerDropdown.displayName = 'TimePickerDropdown';
|
|
27
|
+
export default TimePickerDropdown;
|
|
28
|
+
//# sourceMappingURL=TimePickerDropdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePickerDropdown.js","sourceRoot":"","sources":["../../../src/TimePickerDropdown/TimePickerDropdown.tsx"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAYlD,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAC1C,SAAS,kBAAkB,CACzB,EAA+C,EAC/C,GAAG;QADH,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,OAAkB,EAAb,IAAI,cAAtC,mCAAwC,CAAF;IAGtC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,CACL,oBAAC,MAAM,IACL,IAAI,QACJ,IAAI,EAAC,cAAc,EACnB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAC,cAAc;QAExB,oBAAC,iBAAiB,IAAC,WAAW,EAAE,WAAW;YACzC,6BAAK,GAAG,EAAE,GAAG;gBACX,oBAAC,cAAc,oBAAK,IAAI,EAAI,CACxB,CACY,CACb,CACV,CAAA;AACH,CAAC,CACF,CAAA;AAED,kBAAkB,CAAC,WAAW,GAAG,oBAAoB,CAAA;AAErD,eAAe,kBAAkB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/TimePickerDropdown/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/TimePickerDropdown/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { BaseProps } from '@toptal/picasso-shared';
|
|
3
|
+
import type { HourCycle } from '../TimePicker/utils';
|
|
4
|
+
export interface Props extends BaseProps {
|
|
5
|
+
/** Selected time in 24-hour `HH:mm` format */
|
|
6
|
+
value?: string;
|
|
7
|
+
/** Interval in minutes between the offered times */
|
|
8
|
+
minuteStep: number;
|
|
9
|
+
/** Whether the times are labelled on a 12-hour clock with AM/PM or a 24-hour clock */
|
|
10
|
+
hourCycle: HourCycle;
|
|
11
|
+
/** Moves focus to the selected or nearest time when the list appears */
|
|
12
|
+
autoFocus?: boolean;
|
|
13
|
+
/** Called with the picked time in 24-hour `HH:mm` format */
|
|
14
|
+
onChange: (value: string) => void;
|
|
15
|
+
/** Called when the keyboard asks to close the list */
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
}
|
|
18
|
+
export declare const TimePickerList: {
|
|
19
|
+
({ value, minuteStep, hourCycle, autoFocus, onChange, onClose, className, style, "data-testid": dataTestId, }: Props): React.ReactElement;
|
|
20
|
+
displayName: string;
|
|
21
|
+
};
|
|
22
|
+
export default TimePickerList;
|
|
23
|
+
//# sourceMappingURL=TimePickerList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimePickerList.d.ts","sourceRoot":"","sources":["../../../src/TimePickerList/TimePickerList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAA;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAWvD,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,qBAAqB,CAAA;AAEhE,MAAM,WAAW,KAAM,SAAQ,SAAS;IACtC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAA;IAClB,sFAAsF;IACtF,SAAS,EAAE,SAAS,CAAA;IACpB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4DAA4D;IAC5D,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,sDAAsD;IACtD,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AA4CD,eAAO,MAAM,cAAc;mHAUxB,KAAK,GAAG,KAAK,CAAC,YAAY;;CAwG5B,CAAA;AAID,eAAe,cAAc,CAAA"}
|