@fluentui/react-timepicker-compat 0.0.1

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 (37) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +15 -0
  3. package/README.md +38 -0
  4. package/dist/index.d.ts +147 -0
  5. package/lib/TimePicker.js +1 -0
  6. package/lib/TimePicker.js.map +1 -0
  7. package/lib/components/TimePicker/TimePicker.js +15 -0
  8. package/lib/components/TimePicker/TimePicker.js.map +1 -0
  9. package/lib/components/TimePicker/TimePicker.types.js +1 -0
  10. package/lib/components/TimePicker/TimePicker.types.js.map +1 -0
  11. package/lib/components/TimePicker/index.js +5 -0
  12. package/lib/components/TimePicker/index.js.map +1 -0
  13. package/lib/components/TimePicker/timeMath.js +169 -0
  14. package/lib/components/TimePicker/timeMath.js.map +1 -0
  15. package/lib/components/TimePicker/useTimePicker.js +193 -0
  16. package/lib/components/TimePicker/useTimePicker.js.map +1 -0
  17. package/lib/components/TimePicker/useTimePickerStyles.styles.js +32 -0
  18. package/lib/components/TimePicker/useTimePickerStyles.styles.js.map +1 -0
  19. package/lib/index.js +1 -0
  20. package/lib/index.js.map +1 -0
  21. package/lib-commonjs/TimePicker.js +6 -0
  22. package/lib-commonjs/TimePicker.js.map +1 -0
  23. package/lib-commonjs/components/TimePicker/TimePicker.js +24 -0
  24. package/lib-commonjs/components/TimePicker/TimePicker.js.map +1 -0
  25. package/lib-commonjs/components/TimePicker/TimePicker.types.js +6 -0
  26. package/lib-commonjs/components/TimePicker/TimePicker.types.js.map +1 -0
  27. package/lib-commonjs/components/TimePicker/index.js +16 -0
  28. package/lib-commonjs/components/TimePicker/index.js.map +1 -0
  29. package/lib-commonjs/components/TimePicker/timeMath.js +141 -0
  30. package/lib-commonjs/components/TimePicker/timeMath.js.map +1 -0
  31. package/lib-commonjs/components/TimePicker/useTimePicker.js +196 -0
  32. package/lib-commonjs/components/TimePicker/useTimePicker.js.map +1 -0
  33. package/lib-commonjs/components/TimePicker/useTimePickerStyles.styles.js +48 -0
  34. package/lib-commonjs/components/TimePicker/useTimePickerStyles.styles.js.map +1 -0
  35. package/lib-commonjs/index.js +28 -0
  36. package/lib-commonjs/index.js.map +1 -0
  37. package/package.json +73 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Change Log - @fluentui/react-timepicker-compat
2
+
3
+ This log was last generated on Thu, 04 Jan 2024 09:47:54 GMT and should not be manually modified.
4
+
5
+ <!-- Start content -->
6
+
7
+ ## [0.0.1](https://github.com/microsoft/fluentui/tree/@fluentui/react-timepicker-compat_v0.0.1)
8
+
9
+ Thu, 04 Jan 2024 09:47:54 GMT
10
+
11
+ ### Patches
12
+
13
+ - undefined ([PR #30199](https://github.com/microsoft/fluentui/pull/30199) by yuanboxue@microsoft.com)
14
+ - feat: release compat package ([PR #30201](https://github.com/microsoft/fluentui/pull/30201) by yuanboxue@microsoft.com)
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ @fluentui/react-timepicker-compat
2
+
3
+ Copyright (c) Microsoft Corporation
4
+
5
+ All rights reserved.
6
+
7
+ MIT License
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED _AS IS_, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
14
+
15
+ Note: Usage of the fonts and icons referenced in Fluent UI React is subject to the terms listed at https://aka.ms/fluentui-assets-license
package/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # @fluentui/react-timepicker-compat
2
+
3
+ **React Timepicker components for [Fluent UI React](https://react.fluentui.dev/)**
4
+
5
+ These are not production-ready components and **should never be used in product**. This space is useful for testing new components whose APIs might change before final release.
6
+
7
+ TimePicker offers a control that’s optimized for selecting a time from a drop-down list or using free-form input to enter a custom time.
8
+
9
+ ## Usage
10
+
11
+ To import Timepicker:
12
+
13
+ ```js
14
+ import { TimePicker } from '@fluentui/react-timepicker-compat';
15
+ ```
16
+
17
+ ### Examples
18
+
19
+ ```jsx
20
+ <TimePicker />
21
+ ```
22
+
23
+ # Compat component
24
+
25
+ ## What makes a compat component?
26
+
27
+ A compat component is a component taken from v8 and partially updated with the v9 toolset while keeping its original functionality and most of the original API surface. The most noticeable change being the removal of all v8 dependencies and using only v9 dependencies. While this is a good first step, this is not the final v9 component. We are working on a fully fleshed v9 replacement that will follow all v9 patterns and conventions.
28
+
29
+ ## How publishing the package will be handled
30
+
31
+ Compat components are not added in the `@fluentui/react-components` package suite. Instead, these components should be imported from their respective package as shown above. In contrast with components that live in `@fluentui/react-components`, compat components are to be released as `0.x.x` and there won't be an unstable release (`beta/alpha`) before this release. This is due to the way we will handle versioning for changes, allowing for breaking changes when necessary.
32
+
33
+ ### Versioning for changes
34
+
35
+ We will take a similar approach as v0 where we will follow this pattern:
36
+
37
+ - `breaking change (major)`: Since this is a compat component, we will allow breaking changes if absolutely necessary. To accommodate for this, we will denote those changes as a minor version in semver, i.e. `0.(change will be reflected here).x`.
38
+ - `minor and patch`: These changes will be reflected in the patch version in semver as `0.x.(change will be reflected here)`.
@@ -0,0 +1,147 @@
1
+ import type { ComboboxProps } from '@fluentui/react-combobox';
2
+ import type { ComboboxSlots } from '@fluentui/react-combobox';
3
+ import type { ComboboxState } from '@fluentui/react-combobox';
4
+ import type { ComponentProps } from '@fluentui/react-utilities';
5
+ import type { ForwardRefComponent } from '@fluentui/react-utilities';
6
+ import * as React_2 from 'react';
7
+ import type { SelectionEvents } from '@fluentui/react-combobox';
8
+ import type { SlotClassNames } from '@fluentui/react-utilities';
9
+
10
+ /**
11
+ * Formats a Date object into a time string based on provided options.
12
+ *
13
+ * @param date - The Date object to be formatted.
14
+ * @param options - Formatting options. It has two properties:
15
+ * 1. hourCycle (default: undefined): Determines if the time format should be 12-hour or 24-hour.
16
+ * 2. showSeconds (default: false): Determines if the seconds should be included in the formatted string.
17
+ * @returns Formatted time string based on the given options.
18
+ *
19
+ * @example
20
+ * const date = new Date(2023, 9, 6, 23, 45, 12);
21
+ * formatDateToTimeString(date); // Returns "23:45" in CET
22
+ * formatDateToTimeString(date, \{ showSeconds: true \}); // Returns "23:45:12" in CET
23
+ * formatDateToTimeString(date, \{ hourCycle: 'h12', showSeconds: true \}); // Returns "11:45:12 PM" in CET
24
+ */
25
+ export declare function formatDateToTimeString(date: Date, { hourCycle, showSeconds }?: TimeFormatOptions): string;
26
+
27
+ declare type Hour = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24;
28
+
29
+ declare type TimeFormatOptions = {
30
+ /**
31
+ * A string value indicating whether the 12-hour format ("h11", "h12") or the 24-hour format ("h23", "h24") should be used.
32
+ * - 'h11' and 'h23' start with hour 0 and go up to 11 and 23 respectively.
33
+ * - 'h12' and 'h24' start with hour 1 and go up to 12 and 24 respectively.
34
+ * @default undefined
35
+ */
36
+ hourCycle?: 'h11' | 'h12' | 'h23' | 'h24' | undefined;
37
+ /**
38
+ * If true, show seconds in the dropdown options and consider seconds for default validation purposes.
39
+ */
40
+ showSeconds?: boolean;
41
+ };
42
+
43
+ /**
44
+ * TimePicker Compat component
45
+ */
46
+ export declare const TimePicker: ForwardRefComponent<TimePickerProps>;
47
+
48
+ export declare const timePickerClassNames: SlotClassNames<TimePickerSlots>;
49
+
50
+ /**
51
+ * Error types returned by the `onValidationResult` callback.
52
+ */
53
+ export declare type TimePickerErrorType = 'invalid-input' | 'out-of-bounds' | 'required-input';
54
+
55
+ /**
56
+ * TimePicker Props
57
+ */
58
+ export declare type TimePickerProps = Omit<ComponentProps<Partial<ComboboxSlots>, 'input'>, 'children' | 'size'> & Pick<ComboboxProps, 'appearance' | 'defaultOpen' | 'defaultValue' | 'inlinePopup' | 'onOpenChange' | 'open' | 'placeholder' | 'positioning' | 'size' | 'value' | 'mountNode' | 'freeform'> & TimeFormatOptions & {
59
+ /**
60
+ * Start hour (inclusive) for the time range, 0-24.
61
+ */
62
+ startHour?: Hour;
63
+ /**
64
+ * End hour (exclusive) for the time range, 0-24.
65
+ */
66
+ endHour?: Hour;
67
+ /**
68
+ * Time increment, in minutes, of the options in the dropdown.
69
+ */
70
+ increment?: number;
71
+ /**
72
+ * The date in which all dropdown options are based off of.
73
+ */
74
+ dateAnchor?: Date;
75
+ /**
76
+ * Currently selected time in the TimePicker.
77
+ */
78
+ selectedTime?: Date | null;
79
+ /**
80
+ * Default selected time in the TimePicker, for uncontrolled scenarios.
81
+ */
82
+ defaultSelectedTime?: Date;
83
+ /**
84
+ * Callback for when a time selection is made.
85
+ */
86
+ onTimeChange?: (event: TimeSelectionEvents, data: TimeSelectionData) => void;
87
+ /**
88
+ * Customizes the formatting of date strings displayed in dropdown options.
89
+ */
90
+ formatDateToTimeString?: (date: Date) => string;
91
+ /**
92
+ * In the freeform TimePicker, customizes the parsing from the input time string into a Date and provides custom validation.
93
+ */
94
+ parseTimeStringToDate?: (time: string | undefined) => TimeStringValidationResult;
95
+ };
96
+
97
+ export declare type TimePickerSlots = ComboboxSlots;
98
+
99
+ /**
100
+ * State used in rendering TimePicker
101
+ */
102
+ export declare type TimePickerState = ComboboxState & Required<Pick<TimePickerProps, 'freeform' | 'parseTimeStringToDate'>> & {
103
+ /**
104
+ * Submitted text from the input field. It is used to determine if the input value has changed when user submit a new value on Enter or blur from input.
105
+ */
106
+ submittedText: string | undefined;
107
+ };
108
+
109
+ export declare type TimeSelectionData = {
110
+ /**
111
+ * The Date object associated with the selected option. For freeform TimePicker it can also be the Date object parsed from the user input.
112
+ */
113
+ selectedTime: Date | null;
114
+ /**
115
+ * The display text for the selected option. For freeform TimePicker it can also be the value in user input.
116
+ */
117
+ selectedTimeText: string | undefined;
118
+ /**
119
+ * The error type for the selected option.
120
+ */
121
+ errorType: TimePickerErrorType | undefined;
122
+ };
123
+
124
+ export declare type TimeSelectionEvents = SelectionEvents | React_2.FocusEvent<HTMLElement>;
125
+
126
+ declare type TimeStringValidationResult = {
127
+ date: Date | null;
128
+ errorType?: TimePickerErrorType;
129
+ };
130
+
131
+ /**
132
+ * Create the state required to render TimePicker.
133
+ *
134
+ * The returned state can be modified with hooks such as useTimePickerStyles_unstable,
135
+ * before being passed to renderTimePicker_unstable.
136
+ *
137
+ * @param props - props from this instance of TimePicker
138
+ * @param ref - reference to root HTMLElement of TimePicker
139
+ */
140
+ export declare const useTimePicker_unstable: (props: TimePickerProps, ref: React_2.Ref<HTMLInputElement>) => TimePickerState;
141
+
142
+ /**
143
+ * Apply styling to the TimePicker slots based on the state
144
+ */
145
+ export declare const useTimePickerStyles_unstable: (state: TimePickerState) => TimePickerState;
146
+
147
+ export { }
@@ -0,0 +1 @@
1
+ export * from './components/TimePicker/index';
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["TimePicker.ts"],"sourcesContent":["export * from './components/TimePicker/index';\n"],"names":[],"mappings":"AAAA,cAAc,gCAAgC"}
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import { useTimePicker_unstable } from './useTimePicker';
3
+ import { useTimePickerStyles_unstable } from './useTimePickerStyles.styles';
4
+ import { renderCombobox_unstable, useComboboxContextValues } from '@fluentui/react-combobox';
5
+ import { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';
6
+ /**
7
+ * TimePicker Compat component
8
+ */ export const TimePicker = /*#__PURE__*/ React.forwardRef((props, ref)=>{
9
+ const state = useTimePicker_unstable(props, ref);
10
+ const contextValues = useComboboxContextValues(state);
11
+ useTimePickerStyles_unstable(state);
12
+ useCustomStyleHook_unstable('useTimePickerCompatStyles_unstable')(state);
13
+ return renderCombobox_unstable(state, contextValues);
14
+ });
15
+ TimePicker.displayName = 'TimePicker';
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["TimePicker.tsx"],"sourcesContent":["import * as React from 'react';\nimport type { ForwardRefComponent } from '@fluentui/react-utilities';\nimport { useTimePicker_unstable } from './useTimePicker';\nimport { useTimePickerStyles_unstable } from './useTimePickerStyles.styles';\nimport type { TimePickerProps } from './TimePicker.types';\nimport { renderCombobox_unstable, useComboboxContextValues } from '@fluentui/react-combobox';\nimport { useCustomStyleHook_unstable } from '@fluentui/react-shared-contexts';\n\n/**\n * TimePicker Compat component\n */\nexport const TimePicker: ForwardRefComponent<TimePickerProps> = React.forwardRef((props, ref) => {\n const state = useTimePicker_unstable(props, ref);\n\n const contextValues = useComboboxContextValues(state);\n\n useTimePickerStyles_unstable(state);\n useCustomStyleHook_unstable('useTimePickerCompatStyles_unstable')(state);\n\n return renderCombobox_unstable(state, contextValues);\n});\n\nTimePicker.displayName = 'TimePicker';\n"],"names":["React","useTimePicker_unstable","useTimePickerStyles_unstable","renderCombobox_unstable","useComboboxContextValues","useCustomStyleHook_unstable","TimePicker","forwardRef","props","ref","state","contextValues","displayName"],"mappings":"AAAA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,sBAAsB,QAAQ,kBAAkB;AACzD,SAASC,4BAA4B,QAAQ,+BAA+B;AAE5E,SAASC,uBAAuB,EAAEC,wBAAwB,QAAQ,2BAA2B;AAC7F,SAASC,2BAA2B,QAAQ,kCAAkC;AAE9E;;CAEC,GACD,OAAO,MAAMC,2BAAmDN,MAAMO,UAAU,CAAC,CAACC,OAAOC;IACvF,MAAMC,QAAQT,uBAAuBO,OAAOC;IAE5C,MAAME,gBAAgBP,yBAAyBM;IAE/CR,6BAA6BQ;IAC7BL,4BAA4B,sCAAsCK;IAElE,OAAOP,wBAAwBO,OAAOC;AACxC,GAAG;AAEHL,WAAWM,WAAW,GAAG"}
@@ -0,0 +1 @@
1
+ import * as React from 'react';
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["TimePicker.types.ts"],"sourcesContent":["import * as React from 'react';\nimport type { ComboboxSlots, ComboboxState, ComboboxProps, SelectionEvents } from '@fluentui/react-combobox';\nimport type { ComponentProps } from '@fluentui/react-utilities';\n\nexport type Hour =\n | 0\n | 1\n | 2\n | 3\n | 4\n | 5\n | 6\n | 7\n | 8\n | 9\n | 10\n | 11\n | 12\n | 13\n | 14\n | 15\n | 16\n | 17\n | 18\n | 19\n | 20\n | 21\n | 22\n | 23\n | 24;\n\n/**\n * Data structure for rendering options in the TimePicker.\n */\nexport type TimePickerOption = {\n /**\n * The Date object associated with the option.\n */\n date: Date;\n\n /**\n * A unique identifier for the option.\n */\n key: string;\n\n /**\n * The display text for the option within the Combobox dropdown.\n */\n text: string;\n};\n\n/**\n * Error types returned by the `onValidationResult` callback.\n */\nexport type TimePickerErrorType = 'invalid-input' | 'out-of-bounds' | 'required-input';\n\nexport type TimeStringValidationResult = {\n date: Date | null;\n errorType?: TimePickerErrorType;\n};\n\nexport type TimePickerSlots = ComboboxSlots;\n\nexport type TimeSelectionEvents = SelectionEvents | React.FocusEvent<HTMLElement>;\nexport type TimeSelectionData = {\n /**\n * The Date object associated with the selected option. For freeform TimePicker it can also be the Date object parsed from the user input.\n */\n selectedTime: Date | null;\n /**\n * The display text for the selected option. For freeform TimePicker it can also be the value in user input.\n */\n selectedTimeText: string | undefined;\n /**\n * The error type for the selected option.\n */\n errorType: TimePickerErrorType | undefined;\n};\n\nexport type TimeFormatOptions = {\n /**\n * A string value indicating whether the 12-hour format (\"h11\", \"h12\") or the 24-hour format (\"h23\", \"h24\") should be used.\n * - 'h11' and 'h23' start with hour 0 and go up to 11 and 23 respectively.\n * - 'h12' and 'h24' start with hour 1 and go up to 12 and 24 respectively.\n * @default undefined\n */\n hourCycle?: 'h11' | 'h12' | 'h23' | 'h24' | undefined;\n\n /**\n * If true, show seconds in the dropdown options and consider seconds for default validation purposes.\n */\n showSeconds?: boolean;\n};\n\n/**\n * TimePicker Props\n */\nexport type TimePickerProps = Omit<ComponentProps<Partial<ComboboxSlots>, 'input'>, 'children' | 'size'> &\n Pick<\n ComboboxProps,\n | 'appearance'\n | 'defaultOpen'\n | 'defaultValue'\n | 'inlinePopup'\n | 'onOpenChange'\n | 'open'\n | 'placeholder'\n | 'positioning'\n | 'size'\n | 'value'\n | 'mountNode'\n | 'freeform'\n > &\n TimeFormatOptions & {\n /**\n * Start hour (inclusive) for the time range, 0-24.\n */\n startHour?: Hour;\n\n /**\n * End hour (exclusive) for the time range, 0-24.\n */\n endHour?: Hour;\n\n /**\n * Time increment, in minutes, of the options in the dropdown.\n */\n increment?: number;\n\n /**\n * The date in which all dropdown options are based off of.\n */\n dateAnchor?: Date;\n\n /**\n * Currently selected time in the TimePicker.\n */\n selectedTime?: Date | null;\n\n /**\n * Default selected time in the TimePicker, for uncontrolled scenarios.\n */\n defaultSelectedTime?: Date;\n\n /**\n * Callback for when a time selection is made.\n */\n onTimeChange?: (event: TimeSelectionEvents, data: TimeSelectionData) => void;\n\n /**\n * Customizes the formatting of date strings displayed in dropdown options.\n */\n formatDateToTimeString?: (date: Date) => string;\n\n /**\n * In the freeform TimePicker, customizes the parsing from the input time string into a Date and provides custom validation.\n */\n parseTimeStringToDate?: (time: string | undefined) => TimeStringValidationResult;\n };\n\n/**\n * State used in rendering TimePicker\n */\nexport type TimePickerState = ComboboxState &\n Required<Pick<TimePickerProps, 'freeform' | 'parseTimeStringToDate'>> & {\n /**\n * Submitted text from the input field. It is used to determine if the input value has changed when user submit a new value on Enter or blur from input.\n */\n submittedText: string | undefined;\n };\n"],"names":["React"],"mappings":"AAAA,YAAYA,WAAW,QAAQ"}
@@ -0,0 +1,5 @@
1
+ export * from './TimePicker';
2
+ export * from './TimePicker.types';
3
+ export * from './useTimePicker';
4
+ export * from './useTimePickerStyles.styles';
5
+ export { formatDateToTimeString } from './timeMath';
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["index.ts"],"sourcesContent":["export * from './TimePicker';\nexport * from './TimePicker.types';\nexport * from './useTimePicker';\nexport * from './useTimePickerStyles.styles';\nexport { formatDateToTimeString } from './timeMath';\n"],"names":["formatDateToTimeString"],"mappings":"AAAA,cAAc,eAAe;AAC7B,cAAc,qBAAqB;AACnC,cAAc,kBAAkB;AAChC,cAAc,+BAA+B;AAC7C,SAASA,sBAAsB,QAAQ,aAAa"}
@@ -0,0 +1,169 @@
1
+ function isValidDate(date) {
2
+ return !isNaN(date.getTime());
3
+ }
4
+ /**
5
+ * Converts a Date object to a string key.
6
+ */ export function dateToKey(date) {
7
+ if (!date) {
8
+ return '';
9
+ }
10
+ if (!isValidDate(date)) {
11
+ return 'invalid';
12
+ }
13
+ return date.toISOString();
14
+ }
15
+ /**
16
+ * Converts a string key back to a Date object.
17
+ * Returns undefined for keys that don't represent valid dates.
18
+ */ export function keyToDate(key) {
19
+ if (key === '' || key === 'invalid') {
20
+ return null;
21
+ }
22
+ const date = new Date(key);
23
+ return isValidDate(date) ? date : null;
24
+ }
25
+ /**
26
+ * Formats a Date object into a time string based on provided options.
27
+ *
28
+ * @param date - The Date object to be formatted.
29
+ * @param options - Formatting options. It has two properties:
30
+ * 1. hourCycle (default: undefined): Determines if the time format should be 12-hour or 24-hour.
31
+ * 2. showSeconds (default: false): Determines if the seconds should be included in the formatted string.
32
+ * @returns Formatted time string based on the given options.
33
+ *
34
+ * @example
35
+ * const date = new Date(2023, 9, 6, 23, 45, 12);
36
+ * formatDateToTimeString(date); // Returns "23:45" in CET
37
+ * formatDateToTimeString(date, \{ showSeconds: true \}); // Returns "23:45:12" in CET
38
+ * formatDateToTimeString(date, \{ hourCycle: 'h12', showSeconds: true \}); // Returns "11:45:12 PM" in CET
39
+ */ export function formatDateToTimeString(date, { hourCycle, showSeconds } = {}) {
40
+ return date.toLocaleTimeString(undefined, {
41
+ hour: 'numeric',
42
+ hourCycle,
43
+ minute: '2-digit',
44
+ second: showSeconds ? '2-digit' : undefined
45
+ });
46
+ }
47
+ /**
48
+ * Get the start date anchor based on the provided parameters.
49
+ * @example
50
+ * const date = new Date(2023, 9, 6); // October 6, 2023
51
+ * getStartAnchorDate(date, 5); // Returns a date for October 6, 2023, 05:00:00
52
+ */ export function getDateStartAnchor(dateAnchor, startHour) {
53
+ const startDate = new Date(dateAnchor);
54
+ startDate.setHours(startHour, 0, 0, 0);
55
+ return startDate;
56
+ }
57
+ /**
58
+ * Get the end date anchor based on the provided parameters.
59
+ * @example
60
+ * const date = new Date(2023, 9, 6); // October 6, 2023
61
+ * getEndAnchorDate(date, 5, 10); // Returns a date for October 6, 2023, 10:00:00
62
+ * getEndAnchorDate(date, 10, 5); // Returns a date for October 7, 2023, 05:00:00 (next day due to hour conditions)
63
+ */ export function getDateEndAnchor(dateAnchor, startHour, endHour) {
64
+ const endDate = new Date(dateAnchor);
65
+ if (startHour > endHour || endHour === 24) {
66
+ endDate.setDate(endDate.getDate() + 1);
67
+ }
68
+ endDate.setHours(endHour === 24 ? 0 : endHour, 0, 0, 0);
69
+ return endDate;
70
+ }
71
+ /**
72
+ * Generates an array of Date objects between two given Date anchors.
73
+ *
74
+ * @param dateStartAnchor - The starting Date anchor.
75
+ * @param dateEndAnchor - The ending Date anchor.
76
+ * @param increment - The minute increment between each Date in the resulting array.
77
+ * @returns - An array of Date objects.
78
+ *
79
+ * @example
80
+ * const start = new Date(2023, 0, 1, 10, 0); // Jan 1, 2023 10:00:00 AM
81
+ * const end = new Date(2023, 0, 1, 11, 0); // Jan 1, 2023 11:00:00 AM
82
+ * getTimesBetween(start, end, 15); // Returns array with Dates [10:00, 10:15, 10:30, 10:45]
83
+ */ export function getTimesBetween(dateStartAnchor, dateEndAnchor, increment) {
84
+ if (increment <= 0) {
85
+ // eslint-disable-next-line no-console
86
+ console.error('Increment value should be a positive number.');
87
+ return [];
88
+ }
89
+ const result = [];
90
+ const startDate = new Date(dateStartAnchor);
91
+ while(startDate < dateEndAnchor){
92
+ result.push(new Date(startDate));
93
+ startDate.setMinutes(startDate.getMinutes() + increment);
94
+ }
95
+ return result;
96
+ }
97
+ const REGEX_SHOW_SECONDS_HOUR_12 = /^((1[0-2]|0?[0-9]):([0-5][0-9]):([0-5][0-9])\s([AaPp][Mm]))$/;
98
+ const REGEX_HIDE_SECONDS_HOUR_12 = /^((1[0-2]|0?[0-9]):[0-5][0-9]\s([AaPp][Mm]))$/;
99
+ const REGEX_SHOW_SECONDS_HOUR_24 = /^([0-1]?[0-9]|2[0-4]):[0-5][0-9]:[0-5][0-9]$/;
100
+ const REGEX_HIDE_SECONDS_HOUR_24 = /^([0-1]?[0-9]|2[0-4]):[0-5][0-9]$/;
101
+ /**
102
+ * Calculates a new date from the user-selected time string based on anchor dates.
103
+ * Returns an object containing a date if the provided time string is valid, and an optional string indicating the type of error.
104
+ *
105
+ * @param time - The time string to be parsed (e.g., "2:30 PM", "15:45:20").
106
+ * @param dateStartAnchor - The start anchor date.
107
+ * @param dateEndAnchor - The end anchor date.
108
+ * @param timeFormatOptions - format options for the provided time string.
109
+ * @returns An object with either a 'date' or an 'errorType'.
110
+ *
111
+ * @example
112
+ * Input: time="2:30 PM", dateStartAnchor=2023-10-06T12:00:00Z, dateEndAnchor=2023-10-07T12:00:00Z, options={hourCycle: 'h12', showSeconds: false}
113
+ * Output: { date: 2023-10-06T14:30:00Z }
114
+ *
115
+ * Input: time="25:30"
116
+ * Output: { errorType: 'invalid-input' }
117
+ *
118
+ * Input: time="1:30 AM", dateStartAnchor=2023-10-06T03:00:00Z, dateEndAnchor=2023-10-07T03:00:00Z, options={hourCycle: 'h12', showSeconds: false}
119
+ * Output: { date: 2023-10-07T01:30:00Z, errorType: 'out-of-bounds' }
120
+ */ export function getDateFromTimeString(time, dateStartAnchor, dateEndAnchor, timeFormatOptions) {
121
+ if (!time) {
122
+ return {
123
+ date: null,
124
+ errorType: 'required-input'
125
+ };
126
+ }
127
+ const { hourCycle, showSeconds } = timeFormatOptions;
128
+ const hour12 = hourCycle === 'h11' || hourCycle === 'h12';
129
+ // Determine the regex based on format
130
+ const regex = hour12 ? showSeconds ? REGEX_SHOW_SECONDS_HOUR_12 : REGEX_HIDE_SECONDS_HOUR_12 : showSeconds ? REGEX_SHOW_SECONDS_HOUR_24 : REGEX_HIDE_SECONDS_HOUR_24;
131
+ if (!regex.test(time)) {
132
+ return {
133
+ date: null,
134
+ errorType: 'invalid-input'
135
+ };
136
+ }
137
+ const timeParts = /^(\d\d?):(\d\d):?(\d\d)? ?([ap]m)?/i.exec(time);
138
+ if (!timeParts) {
139
+ return {
140
+ date: null,
141
+ errorType: 'invalid-input'
142
+ };
143
+ }
144
+ const [, selectedHours, minutes, seconds, amPm] = timeParts;
145
+ let hours = selectedHours;
146
+ // Adjust for 12-hour time format if needed
147
+ if (hour12 && amPm) {
148
+ if (amPm.toLowerCase() === 'pm' && +hours !== 12) {
149
+ hours = (+hours + 12).toString();
150
+ } else if (amPm.toLowerCase() === 'am' && +hours === 12) {
151
+ hours = '0';
152
+ }
153
+ }
154
+ const adjustedDate = new Date(dateStartAnchor);
155
+ adjustedDate.setHours(+hours, +minutes, seconds ? +seconds : 0);
156
+ // Adjust to the next day if the selected time is before the anchor time
157
+ if (adjustedDate < dateStartAnchor) {
158
+ adjustedDate.setDate(adjustedDate.getDate() + 1);
159
+ }
160
+ if (adjustedDate >= dateEndAnchor) {
161
+ return {
162
+ date: adjustedDate,
163
+ errorType: 'out-of-bounds'
164
+ };
165
+ }
166
+ return {
167
+ date: adjustedDate
168
+ };
169
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["timeMath.ts"],"sourcesContent":["import type { TimeFormatOptions, TimeStringValidationResult } from './TimePicker.types';\n\nfunction isValidDate(date: Date): boolean {\n return !isNaN(date.getTime());\n}\n\n/**\n * Converts a Date object to a string key.\n */\nexport function dateToKey(date: Date | null): string {\n if (!date) {\n return '';\n }\n if (!isValidDate(date)) {\n return 'invalid';\n }\n return date.toISOString();\n}\n\n/**\n * Converts a string key back to a Date object.\n * Returns undefined for keys that don't represent valid dates.\n */\nexport function keyToDate(key: string): Date | null {\n if (key === '' || key === 'invalid') {\n return null;\n }\n const date = new Date(key);\n return isValidDate(date) ? date : null;\n}\n\n/**\n * Formats a Date object into a time string based on provided options.\n *\n * @param date - The Date object to be formatted.\n * @param options - Formatting options. It has two properties:\n * 1. hourCycle (default: undefined): Determines if the time format should be 12-hour or 24-hour.\n * 2. showSeconds (default: false): Determines if the seconds should be included in the formatted string.\n * @returns Formatted time string based on the given options.\n *\n * @example\n * const date = new Date(2023, 9, 6, 23, 45, 12);\n * formatDateToTimeString(date); // Returns \"23:45\" in CET\n * formatDateToTimeString(date, \\{ showSeconds: true \\}); // Returns \"23:45:12\" in CET\n * formatDateToTimeString(date, \\{ hourCycle: 'h12', showSeconds: true \\}); // Returns \"11:45:12 PM\" in CET\n */\nexport function formatDateToTimeString(date: Date, { hourCycle, showSeconds }: TimeFormatOptions = {}): string {\n return date.toLocaleTimeString(undefined, {\n hour: 'numeric',\n hourCycle,\n minute: '2-digit',\n second: showSeconds ? '2-digit' : undefined,\n });\n}\n\n/**\n * Get the start date anchor based on the provided parameters.\n * @example\n * const date = new Date(2023, 9, 6); // October 6, 2023\n * getStartAnchorDate(date, 5); // Returns a date for October 6, 2023, 05:00:00\n */\nexport function getDateStartAnchor(dateAnchor: Date, startHour: number): Date {\n const startDate = new Date(dateAnchor);\n startDate.setHours(startHour, 0, 0, 0);\n return startDate;\n}\n\n/**\n * Get the end date anchor based on the provided parameters.\n * @example\n * const date = new Date(2023, 9, 6); // October 6, 2023\n * getEndAnchorDate(date, 5, 10); // Returns a date for October 6, 2023, 10:00:00\n * getEndAnchorDate(date, 10, 5); // Returns a date for October 7, 2023, 05:00:00 (next day due to hour conditions)\n */\nexport function getDateEndAnchor(dateAnchor: Date, startHour: number, endHour: number): Date {\n const endDate = new Date(dateAnchor);\n if (startHour > endHour || endHour === 24) {\n endDate.setDate(endDate.getDate() + 1);\n }\n endDate.setHours(endHour === 24 ? 0 : endHour, 0, 0, 0);\n return endDate;\n}\n\n/**\n * Generates an array of Date objects between two given Date anchors.\n *\n * @param dateStartAnchor - The starting Date anchor.\n * @param dateEndAnchor - The ending Date anchor.\n * @param increment - The minute increment between each Date in the resulting array.\n * @returns - An array of Date objects.\n *\n * @example\n * const start = new Date(2023, 0, 1, 10, 0); // Jan 1, 2023 10:00:00 AM\n * const end = new Date(2023, 0, 1, 11, 0); // Jan 1, 2023 11:00:00 AM\n * getTimesBetween(start, end, 15); // Returns array with Dates [10:00, 10:15, 10:30, 10:45]\n */\nexport function getTimesBetween(dateStartAnchor: Date, dateEndAnchor: Date, increment: number) {\n if (increment <= 0) {\n // eslint-disable-next-line no-console\n console.error('Increment value should be a positive number.');\n return [];\n }\n\n const result: Date[] = [];\n\n const startDate = new Date(dateStartAnchor);\n while (startDate < dateEndAnchor) {\n result.push(new Date(startDate));\n startDate.setMinutes(startDate.getMinutes() + increment);\n }\n\n return result;\n}\n\nconst REGEX_SHOW_SECONDS_HOUR_12 = /^((1[0-2]|0?[0-9]):([0-5][0-9]):([0-5][0-9])\\s([AaPp][Mm]))$/;\nconst REGEX_HIDE_SECONDS_HOUR_12 = /^((1[0-2]|0?[0-9]):[0-5][0-9]\\s([AaPp][Mm]))$/;\nconst REGEX_SHOW_SECONDS_HOUR_24 = /^([0-1]?[0-9]|2[0-4]):[0-5][0-9]:[0-5][0-9]$/;\nconst REGEX_HIDE_SECONDS_HOUR_24 = /^([0-1]?[0-9]|2[0-4]):[0-5][0-9]$/;\n\n/**\n * Calculates a new date from the user-selected time string based on anchor dates.\n * Returns an object containing a date if the provided time string is valid, and an optional string indicating the type of error.\n *\n * @param time - The time string to be parsed (e.g., \"2:30 PM\", \"15:45:20\").\n * @param dateStartAnchor - The start anchor date.\n * @param dateEndAnchor - The end anchor date.\n * @param timeFormatOptions - format options for the provided time string.\n * @returns An object with either a 'date' or an 'errorType'.\n *\n * @example\n * Input: time=\"2:30 PM\", dateStartAnchor=2023-10-06T12:00:00Z, dateEndAnchor=2023-10-07T12:00:00Z, options={hourCycle: 'h12', showSeconds: false}\n * Output: { date: 2023-10-06T14:30:00Z }\n *\n * Input: time=\"25:30\"\n * Output: { errorType: 'invalid-input' }\n *\n * Input: time=\"1:30 AM\", dateStartAnchor=2023-10-06T03:00:00Z, dateEndAnchor=2023-10-07T03:00:00Z, options={hourCycle: 'h12', showSeconds: false}\n * Output: { date: 2023-10-07T01:30:00Z, errorType: 'out-of-bounds' }\n */\nexport function getDateFromTimeString(\n time: string | undefined,\n dateStartAnchor: Date,\n dateEndAnchor: Date,\n timeFormatOptions: TimeFormatOptions,\n): TimeStringValidationResult {\n if (!time) {\n return { date: null, errorType: 'required-input' };\n }\n\n const { hourCycle, showSeconds } = timeFormatOptions;\n const hour12 = hourCycle === 'h11' || hourCycle === 'h12';\n\n // Determine the regex based on format\n const regex = hour12\n ? showSeconds\n ? REGEX_SHOW_SECONDS_HOUR_12\n : REGEX_HIDE_SECONDS_HOUR_12\n : showSeconds\n ? REGEX_SHOW_SECONDS_HOUR_24\n : REGEX_HIDE_SECONDS_HOUR_24;\n\n if (!regex.test(time)) {\n return { date: null, errorType: 'invalid-input' };\n }\n\n const timeParts = /^(\\d\\d?):(\\d\\d):?(\\d\\d)? ?([ap]m)?/i.exec(time);\n if (!timeParts) {\n return { date: null, errorType: 'invalid-input' };\n }\n\n const [, selectedHours, minutes, seconds, amPm] = timeParts;\n let hours = selectedHours;\n\n // Adjust for 12-hour time format if needed\n if (hour12 && amPm) {\n if (amPm.toLowerCase() === 'pm' && +hours !== 12) {\n hours = (+hours + 12).toString();\n } else if (amPm.toLowerCase() === 'am' && +hours === 12) {\n hours = '0';\n }\n }\n\n const adjustedDate = new Date(dateStartAnchor);\n adjustedDate.setHours(+hours, +minutes, seconds ? +seconds : 0);\n\n // Adjust to the next day if the selected time is before the anchor time\n if (adjustedDate < dateStartAnchor) {\n adjustedDate.setDate(adjustedDate.getDate() + 1);\n }\n\n if (adjustedDate >= dateEndAnchor) {\n return { date: adjustedDate, errorType: 'out-of-bounds' };\n }\n\n return { date: adjustedDate };\n}\n"],"names":["isValidDate","date","isNaN","getTime","dateToKey","toISOString","keyToDate","key","Date","formatDateToTimeString","hourCycle","showSeconds","toLocaleTimeString","undefined","hour","minute","second","getDateStartAnchor","dateAnchor","startHour","startDate","setHours","getDateEndAnchor","endHour","endDate","setDate","getDate","getTimesBetween","dateStartAnchor","dateEndAnchor","increment","console","error","result","push","setMinutes","getMinutes","REGEX_SHOW_SECONDS_HOUR_12","REGEX_HIDE_SECONDS_HOUR_12","REGEX_SHOW_SECONDS_HOUR_24","REGEX_HIDE_SECONDS_HOUR_24","getDateFromTimeString","time","timeFormatOptions","errorType","hour12","regex","test","timeParts","exec","selectedHours","minutes","seconds","amPm","hours","toLowerCase","toString","adjustedDate"],"mappings":"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"}