@toptal/picasso-timepicker 100.0.4-alpha-pf-react-19-improvements-970580a42.0 → 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.
Files changed (61) hide show
  1. package/dist-package/src/TimePicker/TimePicker.d.ts +4 -1
  2. package/dist-package/src/TimePicker/TimePicker.d.ts.map +1 -1
  3. package/dist-package/src/TimePicker/TimePicker.js +64 -10
  4. package/dist-package/src/TimePicker/TimePicker.js.map +1 -1
  5. package/dist-package/src/TimePicker/use-time-picker-popover.d.ts +21 -0
  6. package/dist-package/src/TimePicker/use-time-picker-popover.d.ts.map +1 -0
  7. package/dist-package/src/TimePicker/use-time-picker-popover.js +96 -0
  8. package/dist-package/src/TimePicker/use-time-picker-popover.js.map +1 -0
  9. package/dist-package/src/TimePicker/utils/get-hour-cycle.d.ts +3 -0
  10. package/dist-package/src/TimePicker/utils/get-hour-cycle.d.ts.map +1 -0
  11. package/dist-package/src/TimePicker/utils/get-hour-cycle.js +42 -0
  12. package/dist-package/src/TimePicker/utils/get-hour-cycle.js.map +1 -0
  13. package/dist-package/src/TimePicker/utils/index.d.ts +5 -0
  14. package/dist-package/src/TimePicker/utils/index.d.ts.map +1 -0
  15. package/dist-package/src/TimePicker/utils/index.js +3 -0
  16. package/dist-package/src/TimePicker/utils/index.js.map +1 -0
  17. package/dist-package/src/TimePicker/utils/time.d.ts +16 -0
  18. package/dist-package/src/TimePicker/utils/time.d.ts.map +1 -0
  19. package/dist-package/src/TimePicker/utils/time.js +41 -0
  20. package/dist-package/src/TimePicker/utils/time.js.map +1 -0
  21. package/dist-package/src/TimePickerDropdown/TimePickerDropdown.d.ts +13 -0
  22. package/dist-package/src/TimePickerDropdown/TimePickerDropdown.d.ts.map +1 -0
  23. package/dist-package/src/TimePickerDropdown/TimePickerDropdown.js +28 -0
  24. package/dist-package/src/TimePickerDropdown/TimePickerDropdown.js.map +1 -0
  25. package/dist-package/src/TimePickerDropdown/index.d.ts +2 -0
  26. package/dist-package/src/TimePickerDropdown/index.d.ts.map +1 -0
  27. package/dist-package/src/TimePickerDropdown/index.js +2 -0
  28. package/dist-package/src/TimePickerDropdown/index.js.map +1 -0
  29. package/dist-package/src/TimePickerList/TimePickerList.d.ts +23 -0
  30. package/dist-package/src/TimePickerList/TimePickerList.d.ts.map +1 -0
  31. package/dist-package/src/TimePickerList/TimePickerList.js +97 -0
  32. package/dist-package/src/TimePickerList/TimePickerList.js.map +1 -0
  33. package/dist-package/src/TimePickerList/index.d.ts +4 -0
  34. package/dist-package/src/TimePickerList/index.d.ts.map +1 -0
  35. package/dist-package/src/TimePickerList/index.js +2 -0
  36. package/dist-package/src/TimePickerList/index.js.map +1 -0
  37. package/dist-package/src/TimePickerTrigger/TimePickerTrigger.d.ts +16 -0
  38. package/dist-package/src/TimePickerTrigger/TimePickerTrigger.d.ts.map +1 -0
  39. package/dist-package/src/TimePickerTrigger/TimePickerTrigger.js +11 -0
  40. package/dist-package/src/TimePickerTrigger/TimePickerTrigger.js.map +1 -0
  41. package/dist-package/src/TimePickerTrigger/index.d.ts +2 -0
  42. package/dist-package/src/TimePickerTrigger/index.d.ts.map +1 -0
  43. package/dist-package/src/TimePickerTrigger/index.js +2 -0
  44. package/dist-package/src/TimePickerTrigger/index.js.map +1 -0
  45. package/package.json +14 -9
  46. package/src/TimePicker/TimePicker.tsx +173 -33
  47. package/src/TimePicker/story/MinuteStep.example.tsx +16 -0
  48. package/src/TimePicker/story/index.jsx +10 -0
  49. package/src/TimePicker/test.tsx +649 -1
  50. package/src/TimePicker/use-time-picker-popover.ts +120 -0
  51. package/src/TimePicker/utils/get-hour-cycle.test.ts +76 -0
  52. package/src/TimePicker/utils/get-hour-cycle.ts +63 -0
  53. package/src/TimePicker/utils/index.ts +10 -0
  54. package/src/TimePicker/utils/time.test.ts +143 -0
  55. package/src/TimePicker/utils/time.ts +76 -0
  56. package/src/TimePickerDropdown/TimePickerDropdown.tsx +45 -0
  57. package/src/TimePickerDropdown/index.ts +1 -0
  58. package/src/TimePickerList/TimePickerList.tsx +190 -0
  59. package/src/TimePickerList/index.ts +4 -0
  60. package/src/TimePickerTrigger/TimePickerTrigger.tsx +53 -0
  61. 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): JSX.Element;
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":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gCAAgC,CAAA;AAG5D,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;CACnC;AAID,eAAO,MAAM,UAAU;2BAAsC,KAAK;;CAoEjE,CAAA;AAID,eAAe,UAAU,CAAA"}
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"}
@@ -10,22 +10,39 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import React, { useEffect, useState } from 'react';
13
+ import InputMask from 'react-input-mask';
14
+ import { detect } from 'detect-browser';
13
15
  import { Input } from '@toptal/picasso-input';
14
16
  import { Time16 } from '@toptal/picasso-icons';
15
17
  import { twMerge } from '@toptal/picasso-tailwind-merge';
16
- const VALID_TIME_REGEX = new RegExp(/^([0-1][0-9]|2[0-3]):[0-5][0-9]$/);
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
+ };
17
32
  export const TimePicker = (_a) => {
33
+ var _b;
18
34
  var { status = 'default' } = _a, props = __rest(_a, ["status"]);
19
- 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"]);
20
36
  const [value, setValue] = useState(externalValue);
37
+ const hasTimeList = minuteStep !== undefined;
38
+ const interactive = hasTimeList && !rest.disabled && !rest.readOnly;
21
39
  useEffect(() => {
22
40
  // Set internal value based on the provided one if the later is correct
23
41
  if (externalValue && VALID_TIME_REGEX.test(externalValue)) {
24
42
  setValue(externalValue);
25
43
  }
26
44
  }, [externalValue]);
27
- const onChange = (event) => {
28
- const newValue = event.target.value;
45
+ const changeValue = (newValue) => {
29
46
  setValue(newValue);
30
47
  if (newValue && VALID_TIME_REGEX.test(newValue)) {
31
48
  externalOnChange === null || externalOnChange === void 0 ? void 0 : externalOnChange(newValue);
@@ -34,13 +51,50 @@ export const TimePicker = (_a) => {
34
51
  externalOnChange === null || externalOnChange === void 0 ? void 0 : externalOnChange('');
35
52
  }
36
53
  };
37
- const icon = (React.createElement(Time16, { classes: {
38
- root: 'bg-white absolute right-[0.625rem] pointer-events-none m-0 select-none',
39
- } }));
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 }));
40
86
  const inputClassName = twMerge('cursor-default', className);
41
- const inputPropClassName = `-mr-[8px] [&::-webkit-calendar-picker-indicator]:absolute [&::-webkit-calendar-picker-indicator]:right-2
42
- [&::-webkit-calendar-picker-indicator]:cursor-pointer [&::-webkit-calendar-picker-indicator]:bg-none`;
43
- return (React.createElement(Input, { type: 'time', value: value, className: inputClassName, onChange: onChange, iconPosition: 'end', highlight: highlight, icon: icon, width: width, size: size, status: status, inputProps: Object.assign({ className: inputPropClassName, step: 60 }, rest) }));
87
+ const inputPropClassName = hasTimeList
88
+ ? TIME_LIST_CLASS_NAME
89
+ : NATIVE_PICKER_CLASS_NAME;
90
+ if (isSafari) {
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));
94
+ }
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));
44
98
  };
45
99
  TimePicker.displayName = 'TimePicker';
46
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,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAG9C,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAkCxD,MAAM,gBAAgB,GAAG,IAAI,MAAM,CAAC,kCAAkC,CAAC,CAAA;AAEvE,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAuC,EAAE,EAAE;QAA3C,EAAE,MAAM,GAAG,SAAS,OAAmB,EAAd,KAAK,cAA9B,UAAgC,CAAF;IACvD,MAAM,EACJ,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,aAAa,EACpB,KAAK,EACL,SAAS,EACT,SAAS,EACT,IAAI,KAEF,KAAK,EADJ,IAAI,UACL,KAAK,EARH,gEAQL,CAAQ,CAAA;IAET,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAA;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,uEAAuE;QACvE,IAAI,aAAa,IAAI,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,QAAQ,CAAC,aAAa,CAAC,CAAA;QACzB,CAAC;IACH,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAA;IAEnB,MAAM,QAAQ,GAAG,CACf,KAEC,EACD,EAAE;QACF,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAA;QAEnC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAElB,IAAI,QAAQ,IAAI,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChD,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAG,QAAQ,CAAC,CAAA;QAC9B,CAAC;aAAM,CAAC;YACN,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAG,EAAE,CAAC,CAAA;QACxB,CAAC;IACH,CAAC,CAAA;IAED,MAAM,IAAI,GAAG,CACX,oBAAC,MAAM,IACL,OAAO,EAAE;YACP,IAAI,EAAE,wEAAwE;SAC/E,GACD,CACH,CAAA;IAED,MAAM,cAAc,GAAG,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAA;IAE3D,MAAM,kBAAkB,GAAG;yGAC4E,CAAA;IAEvG,OAAO,CACL,oBAAC,KAAK,IACJ,IAAI,EAAC,MAAM,EACX,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,cAAc,EACzB,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAC,KAAK,EAClB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,UAAU,kBACR,SAAS,EAAE,kBAAkB,EAC7B,IAAI,EAAE,EAAE,IACL,IAAI,IAET,CACH,CAAA;AACH,CAAC,CAAA;AAED,UAAU,CAAC,WAAW,GAAG,YAAY,CAAA;AAErC,eAAe,UAAU,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,3 @@
1
+ export type HourCycle = 12 | 24;
2
+ export declare const getHourCycle: (locale?: string) => HourCycle;
3
+ //# sourceMappingURL=get-hour-cycle.d.ts.map
@@ -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,3 @@
1
+ export { getHourCycle } from './get-hour-cycle';
2
+ export { VALID_TIME_REGEX, getCurrentTime, getNearestOptionIndex, getTimeOptions, parseTime, } from './time';
3
+ //# sourceMappingURL=index.js.map
@@ -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,2 @@
1
+ export { default as TimePickerDropdown } from './TimePickerDropdown';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { default as TimePickerDropdown } from './TimePickerDropdown';
2
+ //# sourceMappingURL=index.js.map
@@ -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"}
@@ -0,0 +1,97 @@
1
+ import React, { useMemo, useRef, useState } from 'react';
2
+ import { Menu, MenuItem } from '@toptal/picasso-menu';
3
+ import { useIsomorphicLayoutEffect } from '@toptal/picasso-utils';
4
+ import { twMerge } from '@toptal/picasso-tailwind-merge';
5
+ import { getCurrentTime, getNearestOptionIndex, getTimeOptions, parseTime, } from '../TimePicker/utils';
6
+ const OPTION = '[role="option"]';
7
+ const preventFocusLoss = (event) => {
8
+ // Clicking a time must keep the caret in the field, like the browser picker does
9
+ event.preventDefault();
10
+ };
11
+ const getStartingIndex = (options, minuteStep, value) => {
12
+ var _a;
13
+ const selectedIndex = options.findIndex(option => option.value === value);
14
+ return selectedIndex >= 0
15
+ ? selectedIndex
16
+ : getNearestOptionIndex((_a = parseTime(value)) !== null && _a !== void 0 ? _a : getCurrentTime(), minuteStep);
17
+ };
18
+ const scrollToOption = (list, option) => {
19
+ const listRect = list.getBoundingClientRect();
20
+ const optionRect = option.getBoundingClientRect();
21
+ list.scrollTop +=
22
+ optionRect.top - listRect.top - (listRect.height - optionRect.height) / 2;
23
+ };
24
+ const getNextIndex = (key, index, count) => {
25
+ switch (key) {
26
+ case 'ArrowDown':
27
+ return Math.min(index + 1, count - 1);
28
+ case 'ArrowUp':
29
+ return Math.max(index - 1, 0);
30
+ case 'Home':
31
+ return 0;
32
+ case 'End':
33
+ return count - 1;
34
+ default:
35
+ return undefined;
36
+ }
37
+ };
38
+ export const TimePickerList = ({ value, minuteStep, hourCycle, autoFocus = false, onChange, onClose, className, style, 'data-testid': dataTestId, }) => {
39
+ const listRef = useRef(null);
40
+ const options = useMemo(() => getTimeOptions(minuteStep, hourCycle), [minuteStep, hourCycle]);
41
+ const [initialIndex] = useState(() => getStartingIndex(options, minuteStep, value));
42
+ const getOptionElements = () => { var _a, _b; return Array.from((_b = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll(OPTION)) !== null && _b !== void 0 ? _b : []); };
43
+ useIsomorphicLayoutEffect(() => {
44
+ const list = listRef.current;
45
+ const option = getOptionElements()[initialIndex];
46
+ if (list && option) {
47
+ scrollToOption(list, option);
48
+ }
49
+ }, [initialIndex]);
50
+ useIsomorphicLayoutEffect(() => {
51
+ if (!autoFocus) {
52
+ return;
53
+ }
54
+ // The value may have been typed since the list opened, so the time to
55
+ // focus is looked up at the moment focus is requested
56
+ const list = listRef.current;
57
+ const option = getOptionElements()[getStartingIndex(options, minuteStep, value)];
58
+ if (list && option) {
59
+ scrollToOption(list, option);
60
+ option.focus({ preventScroll: true });
61
+ }
62
+ }, [autoFocus]);
63
+ const handleKeyDown = (event) => {
64
+ var _a;
65
+ const optionElements = getOptionElements();
66
+ const index = optionElements.indexOf(event.target.closest(OPTION));
67
+ switch (event.key) {
68
+ case 'Enter':
69
+ case ' ':
70
+ event.preventDefault();
71
+ event.stopPropagation();
72
+ if (index >= 0) {
73
+ onChange(options[index].value);
74
+ }
75
+ break;
76
+ case 'Escape':
77
+ // Keeps a surrounding Modal or Drawer open while the list closes
78
+ event.stopPropagation();
79
+ onClose();
80
+ break;
81
+ case 'Tab':
82
+ onClose();
83
+ break;
84
+ default: {
85
+ const nextIndex = getNextIndex(event.key, index, options.length);
86
+ if (nextIndex !== undefined) {
87
+ event.preventDefault();
88
+ (_a = optionElements[nextIndex]) === null || _a === void 0 ? void 0 : _a.focus();
89
+ }
90
+ }
91
+ }
92
+ };
93
+ return (React.createElement(Menu, { ref: listRef, role: 'listbox', "aria-label": 'Choose time', allowNestedNavigation: false, onKeyDown: handleKeyDown, onMouseDown: preventFocusLoss, className: twMerge('bg-white shadow-5 max-h-[15rem] overflow-y-auto', className), style: style, "data-testid": dataTestId }, options.map(option => (React.createElement(MenuItem, { key: option.value, role: 'option', "aria-selected": option.value === value, checkmarked: option.value === value, titleCase: false, className: 'tabular-nums', onClick: () => onChange(option.value) }, option.label)))));
94
+ };
95
+ TimePickerList.displayName = 'TimePickerList';
96
+ export default TimePickerList;
97
+ //# sourceMappingURL=TimePickerList.js.map