@atlaskit/datetime-picker 17.6.5 → 17.8.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 (149) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/date-picker/package.json +17 -0
  3. package/date-time-picker/package.json +17 -0
  4. package/dist/cjs/components/date-picker.js +20 -15
  5. package/dist/cjs/components/date-time-picker-class.js +7 -9
  6. package/dist/cjs/components/date-time-picker-fc.js +468 -7
  7. package/dist/cjs/components/time-picker.js +11 -8
  8. package/dist/cjs/entry-points/date-picker.js +13 -0
  9. package/dist/cjs/entry-points/date-time-picker.js +13 -0
  10. package/dist/cjs/entry-points/time-picker.js +13 -0
  11. package/dist/cjs/entry-points/types.js +1 -0
  12. package/dist/cjs/internal/convert-to24hr-time.js +66 -0
  13. package/dist/cjs/internal/default-date-format.js +7 -0
  14. package/dist/cjs/internal/default-times.js +7 -0
  15. package/dist/cjs/internal/empty-component.js +12 -0
  16. package/dist/cjs/internal/format-date-time-zone-into-iso.js +15 -0
  17. package/dist/cjs/internal/format-date.js +39 -0
  18. package/dist/cjs/internal/{date-picker-migration.js → get-parsed-iso.js} +4 -48
  19. package/dist/cjs/internal/get-placeholder.js +32 -0
  20. package/dist/cjs/internal/get-safe-calendar-value.js +18 -0
  21. package/dist/cjs/internal/get-short-iso-string.js +13 -0
  22. package/dist/cjs/internal/is-date-disabled.js +29 -0
  23. package/dist/cjs/internal/is-valid.js +39 -0
  24. package/dist/cjs/internal/pad-two.js +9 -0
  25. package/dist/cjs/internal/parse-date.js +31 -20
  26. package/dist/cjs/internal/parse-time.js +6 -102
  27. package/dist/cjs/internal/placeholder-date-time.js +9 -0
  28. package/dist/cjs/internal/remove-spacer.js +9 -0
  29. package/dist/es2019/components/date-picker.js +9 -4
  30. package/dist/es2019/components/date-time-picker-class.js +4 -6
  31. package/dist/es2019/components/date-time-picker-fc.js +451 -5
  32. package/dist/es2019/components/time-picker.js +5 -2
  33. package/dist/es2019/entry-points/date-picker.js +1 -0
  34. package/dist/es2019/entry-points/date-time-picker.js +1 -0
  35. package/dist/es2019/entry-points/time-picker.js +1 -0
  36. package/dist/es2019/entry-points/types.js +0 -0
  37. package/dist/es2019/internal/convert-to24hr-time.js +60 -0
  38. package/dist/es2019/internal/default-date-format.js +1 -0
  39. package/dist/es2019/internal/default-times.js +1 -0
  40. package/dist/es2019/internal/empty-component.js +4 -0
  41. package/dist/es2019/internal/format-date-time-zone-into-iso.js +9 -0
  42. package/dist/es2019/internal/format-date.js +34 -0
  43. package/dist/es2019/internal/{date-picker-migration.js → get-parsed-iso.js} +2 -54
  44. package/dist/es2019/internal/get-placeholder.js +28 -0
  45. package/dist/es2019/internal/get-safe-calendar-value.js +11 -0
  46. package/dist/es2019/internal/get-short-iso-string.js +6 -0
  47. package/dist/es2019/internal/is-date-disabled.js +25 -0
  48. package/dist/es2019/internal/is-valid.js +33 -0
  49. package/dist/es2019/internal/pad-two.js +3 -0
  50. package/dist/es2019/internal/parse-date.js +33 -18
  51. package/dist/es2019/internal/parse-time.js +3 -96
  52. package/dist/es2019/internal/placeholder-date-time.js +3 -0
  53. package/dist/es2019/internal/remove-spacer.js +3 -0
  54. package/dist/esm/components/date-picker.js +9 -4
  55. package/dist/esm/components/date-time-picker-class.js +4 -6
  56. package/dist/esm/components/date-time-picker-fc.js +468 -7
  57. package/dist/esm/components/time-picker.js +5 -2
  58. package/dist/esm/entry-points/date-picker.js +1 -0
  59. package/dist/esm/entry-points/date-time-picker.js +1 -0
  60. package/dist/esm/entry-points/time-picker.js +1 -0
  61. package/dist/esm/entry-points/types.js +0 -0
  62. package/dist/esm/internal/convert-to24hr-time.js +60 -0
  63. package/dist/esm/internal/default-date-format.js +1 -0
  64. package/dist/esm/internal/default-times.js +1 -0
  65. package/dist/esm/internal/empty-component.js +6 -0
  66. package/dist/esm/internal/format-date-time-zone-into-iso.js +9 -0
  67. package/dist/esm/internal/format-date.js +32 -0
  68. package/dist/esm/internal/{date-picker-migration.js → get-parsed-iso.js} +2 -46
  69. package/dist/esm/internal/get-placeholder.js +26 -0
  70. package/dist/esm/internal/get-safe-calendar-value.js +11 -0
  71. package/dist/esm/internal/get-short-iso-string.js +6 -0
  72. package/dist/esm/internal/is-date-disabled.js +23 -0
  73. package/dist/esm/internal/is-valid.js +33 -0
  74. package/dist/esm/internal/pad-two.js +3 -0
  75. package/dist/esm/internal/parse-date.js +31 -18
  76. package/dist/esm/internal/parse-time.js +3 -96
  77. package/dist/esm/internal/placeholder-date-time.js +3 -0
  78. package/dist/esm/internal/remove-spacer.js +3 -0
  79. package/dist/types/components/date-time-picker-class.d.ts +0 -2
  80. package/dist/types/components/date-time-picker-fc.d.ts +4 -2
  81. package/dist/types/entry-points/date-picker.d.ts +2 -0
  82. package/dist/types/entry-points/date-time-picker.d.ts +1 -0
  83. package/dist/types/entry-points/time-picker.d.ts +1 -0
  84. package/dist/types/entry-points/types.d.ts +1 -0
  85. package/dist/types/internal/convert-to24hr-time.d.ts +7 -0
  86. package/dist/types/internal/default-date-format.d.ts +1 -0
  87. package/dist/types/internal/default-times.d.ts +1 -0
  88. package/dist/types/internal/empty-component.d.ts +4 -0
  89. package/dist/types/internal/format-date-time-zone-into-iso.d.ts +4 -0
  90. package/dist/{types-ts4.5/internal/date-picker-migration.d.ts → types/internal/format-date.d.ts} +0 -28
  91. package/dist/types/internal/get-parsed-iso.d.ts +20 -0
  92. package/dist/types/internal/get-placeholder.d.ts +22 -0
  93. package/dist/types/internal/get-safe-calendar-value.d.ts +1 -0
  94. package/dist/types/internal/get-short-iso-string.d.ts +1 -0
  95. package/dist/types/internal/is-date-disabled.d.ts +20 -0
  96. package/dist/types/internal/is-valid.d.ts +1 -0
  97. package/dist/types/internal/pad-two.d.ts +1 -0
  98. package/dist/types/internal/parse-date.d.ts +26 -5
  99. package/dist/types/internal/parse-time.d.ts +0 -9
  100. package/dist/types/internal/placeholder-date-time.d.ts +1 -0
  101. package/dist/types/internal/remove-spacer.d.ts +1 -0
  102. package/dist/types-ts4.5/components/date-time-picker-class.d.ts +0 -2
  103. package/dist/types-ts4.5/components/date-time-picker-fc.d.ts +4 -2
  104. package/dist/types-ts4.5/entry-points/date-picker.d.ts +2 -0
  105. package/dist/types-ts4.5/entry-points/date-time-picker.d.ts +1 -0
  106. package/dist/types-ts4.5/entry-points/time-picker.d.ts +1 -0
  107. package/dist/types-ts4.5/entry-points/types.d.ts +1 -0
  108. package/dist/types-ts4.5/internal/convert-to24hr-time.d.ts +7 -0
  109. package/dist/types-ts4.5/internal/default-date-format.d.ts +1 -0
  110. package/dist/types-ts4.5/internal/default-times.d.ts +1 -0
  111. package/dist/types-ts4.5/internal/empty-component.d.ts +4 -0
  112. package/dist/types-ts4.5/internal/format-date-time-zone-into-iso.d.ts +4 -0
  113. package/dist/{types/internal/date-picker-migration.d.ts → types-ts4.5/internal/format-date.d.ts} +0 -28
  114. package/dist/types-ts4.5/internal/get-parsed-iso.d.ts +20 -0
  115. package/dist/types-ts4.5/internal/get-placeholder.d.ts +22 -0
  116. package/dist/types-ts4.5/internal/get-safe-calendar-value.d.ts +1 -0
  117. package/dist/types-ts4.5/internal/get-short-iso-string.d.ts +1 -0
  118. package/dist/types-ts4.5/internal/is-date-disabled.d.ts +20 -0
  119. package/dist/types-ts4.5/internal/is-valid.d.ts +1 -0
  120. package/dist/types-ts4.5/internal/pad-two.d.ts +1 -0
  121. package/dist/types-ts4.5/internal/parse-date.d.ts +26 -5
  122. package/dist/types-ts4.5/internal/parse-time.d.ts +0 -9
  123. package/dist/types-ts4.5/internal/placeholder-date-time.d.ts +1 -0
  124. package/dist/types-ts4.5/internal/remove-spacer.d.ts +1 -0
  125. package/package.json +11 -14
  126. package/time-picker/package.json +17 -0
  127. package/types/package.json +5 -5
  128. package/dist/cjs/components/date-time-picker-fc-new.js +0 -479
  129. package/dist/cjs/components/date-time-picker-fc-old.js +0 -370
  130. package/dist/cjs/internal/index.js +0 -31
  131. package/dist/es2019/components/date-time-picker-fc-new.js +0 -456
  132. package/dist/es2019/components/date-time-picker-fc-old.compiled.css +0 -6
  133. package/dist/es2019/components/date-time-picker-fc-old.js +0 -336
  134. package/dist/es2019/internal/index.js +0 -20
  135. package/dist/esm/components/date-time-picker-fc-new.compiled.css +0 -6
  136. package/dist/esm/components/date-time-picker-fc-new.js +0 -473
  137. package/dist/esm/components/date-time-picker-fc-old.compiled.css +0 -6
  138. package/dist/esm/components/date-time-picker-fc-old.js +0 -364
  139. package/dist/esm/internal/index.js +0 -22
  140. package/dist/types/components/date-time-picker-fc-new.d.ts +0 -6
  141. package/dist/types/components/date-time-picker-fc-old.d.ts +0 -6
  142. package/dist/types/internal/index.d.ts +0 -10
  143. package/dist/types-ts4.5/components/date-time-picker-fc-new.d.ts +0 -6
  144. package/dist/types-ts4.5/components/date-time-picker-fc-old.d.ts +0 -6
  145. package/dist/types-ts4.5/internal/index.d.ts +0 -10
  146. package/offerings.json +0 -98
  147. /package/dist/cjs/components/{date-time-picker-fc-new.compiled.css → date-time-picker-fc.compiled.css} +0 -0
  148. /package/dist/{cjs/components/date-time-picker-fc-old.compiled.css → es2019/components/date-time-picker-fc.compiled.css} +0 -0
  149. /package/dist/{es2019/components/date-time-picker-fc-new.compiled.css → esm/components/date-time-picker-fc.compiled.css} +0 -0
@@ -1,7 +1,63 @@
1
- import { fg } from '@atlaskit/platform-feature-flags';
2
- import { componentWithCondition } from '../internal/ff-component';
3
- import DateTimePickerNew from './date-time-picker-fc-new';
4
- import DateTimePickerOld from './date-time-picker-fc-old';
1
+ /* date-time-picker-fc.tsx generated by @compiled/babel-plugin v0.39.1 */
2
+ import _extends from "@babel/runtime/helpers/extends";
3
+ import "./date-time-picker-fc.compiled.css";
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ /// <reference types="node" />
6
+ // for typing `process`
7
+
8
+ import React, { forwardRef, useCallback, useEffect, useReducer, useState } from 'react';
9
+
10
+ // oxlint-disable-next-line @atlassian/no-restricted-imports
11
+ import { format, isValid, parseISO } from 'date-fns';
12
+ import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next';
13
+ import { IconButton } from '@atlaskit/button/new';
14
+ import SelectClearIcon from '@atlaskit/icon/core/cross-circle';
15
+ import { Box, Inline } from '@atlaskit/primitives/compiled';
16
+ import { mergeStyles } from '@atlaskit/select';
17
+ import { DateTimePickerContainer } from '../internal/date-time-picker-container';
18
+ import { formatDateTimeZoneIntoIso } from '../internal/format-date-time-zone-into-iso';
19
+ import { convertTokens } from '../internal/parse-tokens';
20
+ import DatePicker from './date-picker';
21
+ import TimePicker from './time-picker';
22
+ const packageName = "@atlaskit/datetime-picker";
23
+ const packageVersion = "17.7.0";
24
+ const analyticsAttributes = {
25
+ componentName: 'dateTimePicker',
26
+ packageName,
27
+ packageVersion
28
+ };
29
+ const compiledStyles = {
30
+ datePickerContainerStyles: "_i0dl1ssb _16jlkb7n _1o9zidpf",
31
+ timePickerContainerStyles: "_i0dl1ssb _16jlkb7n",
32
+ iconContainerStyles: "_1e0c1txw _4cvr1h6o _i0dl1kw7"
33
+ };
34
+
35
+ // react-select overrides (via @atlaskit/select).
36
+ const styles = {
37
+ control: style => ({
38
+ ...style,
39
+ backgroundColor: 'transparent',
40
+ border: 2,
41
+ borderRadius: 0,
42
+ paddingLeft: 0,
43
+ ':hover': {
44
+ backgroundColor: 'transparent',
45
+ cursor: 'inherit'
46
+ }
47
+ })
48
+ };
49
+
50
+ /**
51
+ * Two action types keep the reducer focused:
52
+ *
53
+ * - APPLY: used by user-interaction handlers. The handler computes the full
54
+ * next state (including the new ISO value) and applies it atomically. This
55
+ * guarantees a single re-render with no cascades regardless of React version.
56
+ *
57
+ * - SET_VALUE: used by the `providedValue` prop effect. The reducer owns all
58
+ * parsing logic for external value changes, including the empty-string case
59
+ * that the previous useState approach missed.
60
+ */
5
61
 
6
62
  /**
7
63
  * __Date time picker__
@@ -12,4 +68,394 @@ import DateTimePickerOld from './date-time-picker-fc-old';
12
68
  * - [Code](https://atlassian.design/components/datetime-picker/code)
13
69
  * - [Usage](https://atlassian.design/components/datetime-picker/usage)
14
70
  */
15
- export default componentWithCondition(() => fg('dst-a11y_fix-dtp-value-calculation'), DateTimePickerNew, DateTimePickerOld);
71
+ const DateTimePicker = /*#__PURE__*/forwardRef(({
72
+ 'aria-describedby': ariaDescribedBy,
73
+ appearance = 'default',
74
+ autoFocus = false,
75
+ clearControlLabel = 'clear',
76
+ datePickerProps: datePickerPropsWithSelectProps = {},
77
+ defaultValue = '',
78
+ id = '',
79
+ innerProps = {},
80
+ isDisabled = false,
81
+ isInvalid = false,
82
+ isRequired = false,
83
+ name = '',
84
+ // These disables are here for proper typing when used as defaults. They
85
+ // should *not* use the `noop` function.
86
+ /* eslint-disable @repo/internal/react/use-noop */
87
+ onBlur = _event => {},
88
+ onChange: onChangeProp = _value => {},
89
+ onFocus = _event => {},
90
+ /* eslint-enable @repo/internal/react/use-noop */
91
+ parseValue: providedParseValue,
92
+ spacing = 'default',
93
+ locale = 'en-US',
94
+ testId,
95
+ timePickerProps: timePickerPropsWithSelectProps = {},
96
+ value: providedValue
97
+ }, _ref) => {
98
+ const [isFocused, setIsFocused] = useState(false);
99
+
100
+ /**
101
+ * Defined inside the component so the reducer closes over `providedParseValue`
102
+ * without needing to smuggle it through every action payload. React always
103
+ * calls the reducer from the latest render, so stale-closure is not a concern.
104
+ */
105
+ const reducer = (state, action) => {
106
+ switch (action.type) {
107
+ case 'APPLY':
108
+ return action.payload;
109
+ case 'SET_VALUE':
110
+ {
111
+ const newValue = action.payload;
112
+
113
+ // Explicit empty-string handling: clear all sub-fields so the date
114
+ // and time pickers visually reset when a controlled value is cleared.
115
+ if (!newValue) {
116
+ return {
117
+ value: '',
118
+ dateValue: '',
119
+ timeValue: '',
120
+ zoneValue: ''
121
+ };
122
+ }
123
+ if (providedParseValue) {
124
+ const parsed = providedParseValue(newValue, state.dateValue, state.timeValue, state.zoneValue);
125
+ return parsed ? {
126
+ value: newValue,
127
+ ...parsed
128
+ } : {
129
+ value: newValue,
130
+ dateValue: state.dateValue,
131
+ timeValue: state.timeValue,
132
+ zoneValue: state.zoneValue
133
+ };
134
+ }
135
+ const parsed = parseISO(newValue);
136
+ return isValid(parsed) ? {
137
+ value: newValue,
138
+ dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
139
+ timeValue: format(parsed, convertTokens('HH:mm')),
140
+ zoneValue: format(parsed, convertTokens('ZZ'))
141
+ } : {
142
+ value: newValue,
143
+ dateValue: '',
144
+ timeValue: '',
145
+ zoneValue: ''
146
+ };
147
+ }
148
+ default:
149
+ return state;
150
+ }
151
+ };
152
+ const [dtState, dispatch] = useReducer(reducer, null, () => {
153
+ const initialValue = providedValue || defaultValue || '';
154
+ const initialDate = (datePickerPropsWithSelectProps === null || datePickerPropsWithSelectProps === void 0 ? void 0 : datePickerPropsWithSelectProps.defaultValue) || '';
155
+ const initialTime = (timePickerPropsWithSelectProps === null || timePickerPropsWithSelectProps === void 0 ? void 0 : timePickerPropsWithSelectProps.defaultValue) || '';
156
+ if (!initialValue) {
157
+ return {
158
+ value: '',
159
+ dateValue: initialDate,
160
+ timeValue: initialTime,
161
+ zoneValue: ''
162
+ };
163
+ }
164
+ if (providedParseValue) {
165
+ const parsed = providedParseValue(initialValue, initialDate, initialTime, '');
166
+ return parsed ? {
167
+ value: initialValue,
168
+ ...parsed
169
+ } : {
170
+ value: initialValue,
171
+ dateValue: initialDate,
172
+ timeValue: initialTime,
173
+ zoneValue: ''
174
+ };
175
+ }
176
+ const parsed = parseISO(initialValue);
177
+ return isValid(parsed) ? {
178
+ value: initialValue,
179
+ dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
180
+ timeValue: format(parsed, convertTokens('HH:mm')),
181
+ zoneValue: format(parsed, convertTokens('ZZ'))
182
+ } : {
183
+ value: initialValue,
184
+ dateValue: initialDate,
185
+ timeValue: initialTime,
186
+ zoneValue: ''
187
+ };
188
+ });
189
+ useEffect(() => {
190
+ if (providedValue !== undefined) {
191
+ dispatch({
192
+ type: 'SET_VALUE',
193
+ payload: providedValue
194
+ });
195
+ }
196
+ // eslint-disable-next-line react-hooks/exhaustive-deps
197
+ }, [providedValue]);
198
+ const parseValue = useCallback((value, providedDateValue, providedTimeValue, providedZoneValue) => {
199
+ if (providedParseValue) {
200
+ const parsedFromFn = providedParseValue(value, providedDateValue, providedTimeValue, providedZoneValue);
201
+ // This handles cases found in Jira where the parse function actually does
202
+ // nothing and returns undefined. The previous `getSafeState` function
203
+ // just spread the values over the state, but if it returned `undefined`,
204
+ // it would just rely on the previous state values. Considering this is
205
+ // what is input to this function anyway, this is a safe way to handle
206
+ // this, colocate the behavior, and not rely on `getSafeState`.
207
+ return parsedFromFn || {
208
+ dateValue: providedDateValue,
209
+ timeValue: providedTimeValue,
210
+ zoneValue: providedZoneValue
211
+ };
212
+ }
213
+ const parsed = parseISO(value);
214
+ return isValid(parsed) ? {
215
+ dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
216
+ timeValue: format(parsed, convertTokens('HH:mm')),
217
+ zoneValue: format(parsed, convertTokens('ZZ'))
218
+ } : {
219
+ dateValue: dtState.dateValue,
220
+ timeValue: dtState.timeValue,
221
+ zoneValue: dtState.zoneValue
222
+ };
223
+ }, [providedParseValue, dtState.dateValue, dtState.timeValue, dtState.zoneValue]);
224
+ const onDateBlur = event => {
225
+ setIsFocused(false);
226
+ onBlur(event);
227
+ if (datePickerPropsWithSelectProps !== null && datePickerPropsWithSelectProps !== void 0 && datePickerPropsWithSelectProps.onBlur) {
228
+ datePickerPropsWithSelectProps.onBlur(event);
229
+ }
230
+ };
231
+ const onTimeBlur = event => {
232
+ setIsFocused(false);
233
+ onBlur(event);
234
+ if (timePickerPropsWithSelectProps !== null && timePickerPropsWithSelectProps !== void 0 && timePickerPropsWithSelectProps.onBlur) {
235
+ timePickerPropsWithSelectProps.onBlur(event);
236
+ }
237
+ };
238
+ const onDateFocus = event => {
239
+ setIsFocused(false);
240
+ onFocus(event);
241
+ if (datePickerPropsWithSelectProps !== null && datePickerPropsWithSelectProps !== void 0 && datePickerPropsWithSelectProps.onFocus) {
242
+ datePickerPropsWithSelectProps.onFocus(event);
243
+ }
244
+ };
245
+ const onTimeFocus = event => {
246
+ setIsFocused(false);
247
+ onFocus(event);
248
+ if (timePickerPropsWithSelectProps !== null && timePickerPropsWithSelectProps !== void 0 && timePickerPropsWithSelectProps.onFocus) {
249
+ timePickerPropsWithSelectProps.onFocus(event);
250
+ }
251
+ };
252
+ const onDateChange = newDateValue => {
253
+ const parsedValues = parseValue(dtState.value, newDateValue, dtState.timeValue, dtState.zoneValue);
254
+ onValueChange({
255
+ providedDateValue: newDateValue,
256
+ providedTimeValue: parsedValues.timeValue,
257
+ providedZoneValue: parsedValues.zoneValue
258
+ });
259
+ if (datePickerPropsWithSelectProps !== null && datePickerPropsWithSelectProps !== void 0 && datePickerPropsWithSelectProps.onChange) {
260
+ datePickerPropsWithSelectProps.onChange(newDateValue);
261
+ }
262
+ };
263
+ const onTimeChange = newTimeValue => {
264
+ const parsedValues = parseValue(dtState.value, dtState.dateValue, newTimeValue, dtState.zoneValue);
265
+ onValueChange({
266
+ providedDateValue: parsedValues.dateValue,
267
+ providedTimeValue: newTimeValue,
268
+ providedZoneValue: parsedValues.zoneValue
269
+ });
270
+ if (timePickerPropsWithSelectProps !== null && timePickerPropsWithSelectProps !== void 0 && timePickerPropsWithSelectProps.onChange) {
271
+ timePickerPropsWithSelectProps.onChange(newTimeValue);
272
+ }
273
+ };
274
+ const onClear = () => {
275
+ const parsedValues = parseValue(dtState.value, dtState.dateValue, dtState.timeValue, dtState.zoneValue);
276
+ onValueChange({
277
+ providedDateValue: '',
278
+ providedTimeValue: '',
279
+ providedZoneValue: parsedValues.zoneValue
280
+ });
281
+ if (datePickerPropsWithSelectProps !== null && datePickerPropsWithSelectProps !== void 0 && datePickerPropsWithSelectProps.onChange) {
282
+ datePickerPropsWithSelectProps.onChange('');
283
+ }
284
+ if (timePickerPropsWithSelectProps !== null && timePickerPropsWithSelectProps !== void 0 && timePickerPropsWithSelectProps.onChange) {
285
+ timePickerPropsWithSelectProps.onChange('');
286
+ }
287
+ };
288
+ const onChangePropWithAnalytics = usePlatformLeafEventHandler({
289
+ fn: onChangeProp,
290
+ action: 'selectedDate',
291
+ actionSubject: 'datePicker',
292
+ ...analyticsAttributes
293
+ });
294
+ const onValueChange = ({
295
+ providedDateValue,
296
+ providedTimeValue,
297
+ providedZoneValue
298
+ }) => {
299
+ if (providedDateValue && providedTimeValue) {
300
+ const isoValue = formatDateTimeZoneIntoIso(providedDateValue, providedTimeValue, providedZoneValue);
301
+ const {
302
+ zoneValue: parsedZone
303
+ } = parseValue(isoValue, providedDateValue, providedTimeValue, providedZoneValue);
304
+ const valueWithValidZone = formatDateTimeZoneIntoIso(providedDateValue, providedTimeValue, parsedZone);
305
+ dispatch({
306
+ type: 'APPLY',
307
+ payload: {
308
+ value: valueWithValidZone,
309
+ dateValue: providedDateValue,
310
+ timeValue: providedTimeValue,
311
+ zoneValue: parsedZone
312
+ }
313
+ });
314
+ onChangePropWithAnalytics(valueWithValidZone);
315
+ // If the date or time value was cleared when there is an existing datetime value, then clear the value.
316
+ } else if (dtState.value) {
317
+ dispatch({
318
+ type: 'APPLY',
319
+ payload: {
320
+ value: '',
321
+ dateValue: providedDateValue,
322
+ timeValue: providedTimeValue,
323
+ zoneValue: providedZoneValue
324
+ }
325
+ });
326
+ onChangePropWithAnalytics('');
327
+ } else {
328
+ dispatch({
329
+ type: 'APPLY',
330
+ payload: {
331
+ value: '',
332
+ dateValue: providedDateValue,
333
+ timeValue: providedTimeValue,
334
+ zoneValue: providedZoneValue
335
+ }
336
+ });
337
+ }
338
+ };
339
+ const {
340
+ selectProps: datePickerSelectProps,
341
+ ...datePickerProps
342
+ } = datePickerPropsWithSelectProps;
343
+ const datePickerAriaDescribedBy = datePickerProps['aria-describedby'] || ariaDescribedBy;
344
+ const datePickerLabel = datePickerProps.label || 'Date';
345
+ const mergedDatePickerSelectProps = {
346
+ ...datePickerSelectProps,
347
+ styles: mergeStyles(styles, datePickerSelectProps === null || datePickerSelectProps === void 0 ? void 0 : datePickerSelectProps.styles)
348
+ };
349
+ const {
350
+ selectProps: timePickerSelectProps,
351
+ ...timePickerProps
352
+ } = timePickerPropsWithSelectProps;
353
+ const timePickerAriaDescribedBy = timePickerProps['aria-describedby'] || ariaDescribedBy;
354
+ const timePickerLabel = timePickerProps.label || 'Time';
355
+ const mergedTimePickerSelectProps = {
356
+ ...timePickerSelectProps,
357
+ styles: mergeStyles(styles, timePickerSelectProps === null || timePickerSelectProps === void 0 ? void 0 : timePickerSelectProps.styles)
358
+ };
359
+
360
+ // Render DateTimePicker's IconContainer when a value has been filled
361
+ // Don't use Date or TimePicker's because they can't be customised
362
+ const isClearable = Boolean(dtState.dateValue || dtState.timeValue);
363
+ return /*#__PURE__*/React.createElement(DateTimePickerContainer, {
364
+ appearance: appearance,
365
+ isDisabled: isDisabled,
366
+ isFocused: isFocused,
367
+ isInvalid: isInvalid,
368
+ testId: testId,
369
+ innerProps: innerProps
370
+ }, /*#__PURE__*/React.createElement("input", {
371
+ name: name,
372
+ type: "hidden",
373
+ value: dtState.value,
374
+ "data-testid": testId && `${testId}--input`
375
+ }), /*#__PURE__*/React.createElement(Box, {
376
+ xcss: compiledStyles.datePickerContainerStyles
377
+ }, /*#__PURE__*/React.createElement(DatePicker, {
378
+ appearance: appearance,
379
+ "aria-describedby": datePickerAriaDescribedBy,
380
+ autoFocus: datePickerProps.autoFocus || autoFocus,
381
+ dateFormat: datePickerProps.dateFormat,
382
+ defaultIsOpen: datePickerProps.defaultIsOpen,
383
+ defaultValue: datePickerProps.defaultValue,
384
+ disabled: datePickerProps.disabled,
385
+ disabledDateFilter: datePickerProps.disabledDateFilter,
386
+ formatDisplayLabel: datePickerProps.formatDisplayLabel,
387
+ hideIcon: datePickerProps.hideIcon || true,
388
+ icon: datePickerProps.icon,
389
+ id: datePickerProps.id || id,
390
+ innerProps: datePickerProps.innerProps,
391
+ inputLabel: datePickerProps.inputLabel,
392
+ inputLabelId: datePickerProps.inputLabelId,
393
+ isDisabled: datePickerProps.isDisabled || isDisabled,
394
+ isInvalid: datePickerProps.isInvalid || isInvalid,
395
+ isOpen: datePickerProps.isOpen,
396
+ isRequired: datePickerProps.isRequired || isRequired,
397
+ label: datePickerLabel,
398
+ locale: datePickerProps.locale || locale,
399
+ maxDate: datePickerProps.maxDate,
400
+ minDate: datePickerProps.minDate,
401
+ name: datePickerProps.name,
402
+ nextMonthLabel: datePickerProps.nextMonthLabel,
403
+ onBlur: onDateBlur,
404
+ onChange: onDateChange,
405
+ onFocus: onDateFocus,
406
+ openCalendarLabel: datePickerProps.openCalendarLabel,
407
+ parseInputValue: datePickerProps.parseInputValue,
408
+ placeholder: datePickerProps.placeholder,
409
+ previousMonthLabel: datePickerProps.previousMonthLabel,
410
+ selectProps: mergedDatePickerSelectProps,
411
+ shouldShowCalendarButton: datePickerProps.shouldShowCalendarButton,
412
+ spacing: datePickerProps.spacing || spacing,
413
+ testId: testId && `${testId}--datepicker` || datePickerProps.testId,
414
+ value: dtState.dateValue,
415
+ weekStartDay: datePickerProps.weekStartDay
416
+ })), /*#__PURE__*/React.createElement(Box, {
417
+ xcss: compiledStyles.timePickerContainerStyles
418
+ }, /*#__PURE__*/React.createElement(TimePicker, {
419
+ appearance: timePickerProps.appearance || appearance,
420
+ "aria-describedby": timePickerAriaDescribedBy,
421
+ autoFocus: timePickerProps.autoFocus,
422
+ defaultIsOpen: timePickerProps.defaultIsOpen,
423
+ defaultValue: timePickerProps.defaultValue,
424
+ formatDisplayLabel: timePickerProps.formatDisplayLabel,
425
+ hideIcon: timePickerProps.hideIcon || true,
426
+ id: timePickerProps.id,
427
+ innerProps: timePickerProps.innerProps,
428
+ isDisabled: timePickerProps.isDisabled || isDisabled,
429
+ isInvalid: timePickerProps.isInvalid || isInvalid,
430
+ isOpen: timePickerProps.isOpen,
431
+ isRequired: timePickerProps.isRequired || isRequired,
432
+ label: timePickerLabel,
433
+ locale: timePickerProps.locale || locale,
434
+ name: timePickerProps.name,
435
+ onBlur: onTimeBlur,
436
+ onChange: onTimeChange,
437
+ onFocus: onTimeFocus,
438
+ parseInputValue: timePickerProps.parseInputValue,
439
+ placeholder: timePickerProps.placeholder,
440
+ selectProps: mergedTimePickerSelectProps,
441
+ spacing: timePickerProps.spacing || spacing,
442
+ testId: timePickerProps.testId || testId && `${testId}--timepicker`,
443
+ timeFormat: timePickerProps.timeFormat,
444
+ timeIsEditable: timePickerProps.timeIsEditable,
445
+ times: timePickerProps.times,
446
+ value: dtState.timeValue
447
+ })), isClearable && !isDisabled ? /*#__PURE__*/React.createElement(Inline, {
448
+ xcss: compiledStyles.iconContainerStyles
449
+ }, /*#__PURE__*/React.createElement(IconButton, {
450
+ appearance: "subtle",
451
+ label: clearControlLabel,
452
+ icon: iconProps => /*#__PURE__*/React.createElement(SelectClearIcon, _extends({}, iconProps, {
453
+ color: "var(--ds-text-subtlest, #6B6E76)",
454
+ size: "small"
455
+ })),
456
+ onClick: onClear,
457
+ testId: testId && `${testId}--icon--container`,
458
+ tabIndex: -1
459
+ })) : null);
460
+ });
461
+ export default DateTimePicker;
@@ -7,13 +7,16 @@ import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next';
7
7
  import __noop from '@atlaskit/ds-lib/noop';
8
8
  import { createLocalizationProvider } from '@atlaskit/locale';
9
9
  import Select, { CreatableSelect, mergeStyles } from '@atlaskit/select';
10
- import { defaultTimeFormat, defaultTimes, EmptyComponent, placeholderDatetime } from '../internal';
10
+ import { defaultTimes } from '../internal/default-times';
11
+ import { EmptyComponent } from '../internal/empty-component';
11
12
  import { FixedLayerMenu } from '../internal/fixed-layer-menu';
12
13
  import parseTime from '../internal/parse-time';
13
14
  import { convertTokens } from '../internal/parse-tokens';
15
+ import { placeholderDatetime } from '../internal/placeholder-date-time';
14
16
  import { makeSingleValue } from '../internal/single-value';
15
17
  const packageName = "@atlaskit/datetime-picker";
16
- const packageVersion = "17.6.5";
18
+ const packageVersion = "17.7.0";
19
+ const defaultTimeFormat = 'h:mma';
17
20
  const menuStyles = {
18
21
  /* Need to remove default absolute positioning as that causes issues with position fixed */
19
22
  position: 'static',
@@ -0,0 +1 @@
1
+ export { default } from '../components/date-picker';
@@ -0,0 +1 @@
1
+ export { default } from '../components/date-time-picker';
@@ -0,0 +1 @@
1
+ export { default } from '../components/time-picker';
File without changes
@@ -0,0 +1,60 @@
1
+ const map24 = {
2
+ '12': '12',
3
+ '01': '13',
4
+ '02': '14',
5
+ '03': '15',
6
+ '04': '16',
7
+ '05': '17',
8
+ '06': '18',
9
+ '07': '19',
10
+ '08': '20',
11
+ '09': '21',
12
+ '10': '22',
13
+ '11': '23'
14
+ };
15
+ function formatSemi24(time) {
16
+ if (time.length === 1) {
17
+ return `0${time}00`;
18
+ }
19
+ if (time.length === 2) {
20
+ return `${time}00`;
21
+ }
22
+ if (time.length === 3 || time.length === 5) {
23
+ return `0${time}`;
24
+ }
25
+ return time;
26
+ }
27
+ function checkHour(hour, meridiem) {
28
+ if (hour > '24') {
29
+ return null;
30
+ }
31
+ if (hour === '12' && meridiem === 'a') {
32
+ return '00';
33
+ }
34
+ if (hour < '12' && meridiem === 'p') {
35
+ return map24[hour];
36
+ }
37
+ return hour;
38
+ }
39
+ function checkMinuteSecond(value) {
40
+ if (value > '59') {
41
+ return null;
42
+ }
43
+ return value;
44
+ }
45
+ export function convertTo24hrTime(time) {
46
+ const timeArray = time.toLowerCase().split(/(p|a)/i);
47
+ const meridiem = timeArray[1];
48
+ const semi24 = formatSemi24(timeArray[0].trim());
49
+ const hour = checkHour(semi24.substring(0, 2), meridiem);
50
+ const minute = checkMinuteSecond(semi24.substring(2, 4));
51
+ const seconds = semi24.length === 6 && checkMinuteSecond(semi24.substring(4, 6));
52
+ if (!hour || !minute) {
53
+ return null;
54
+ }
55
+ return {
56
+ hour: parseInt(hour, 10),
57
+ minute: parseInt(minute, 10),
58
+ seconds: parseInt(seconds || '0', 10) || 0
59
+ };
60
+ }
@@ -0,0 +1 @@
1
+ export const defaultDateFormat = 'YYYY/MM/DD';
@@ -0,0 +1 @@
1
+ export const defaultTimes = ['09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00', '17:30', '18:00'];
@@ -0,0 +1,4 @@
1
+ /**
2
+ * This component is used to hide portions of Select component.
3
+ */
4
+ export const EmptyComponent = () => null;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Formats a date, time, and zone into a ISO string.
3
+ */
4
+ export function formatDateTimeZoneIntoIso(date, time, zone) {
5
+ // 12:00 => 12:00, 1:00 => 01:00
6
+ const needsLeadingZero = /^\d:/;
7
+ const sanitizedTime = needsLeadingZero.test(time) ? `0${time}` : time;
8
+ return `${date}T${sanitizedTime}${zone}`;
9
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Everything in this file is to smooth out the migration of the new date picker
3
+ * (https://product-fabric.atlassian.net/browse/DSP-20682). When that ticket is
4
+ * complete, all of these functions will ilkely be merged back into the date
5
+ * picker. Please do not pre-optimize and put these back into the date picker
6
+ * unless you are working on the DTP Refresh and you have a good reason to do
7
+ * so, thank you!
8
+ *
9
+ * All variables within the `di` objects are dependency injections. They should
10
+ * be read from within the component at the end of the day. But because we are
11
+ * extracting them, we have to inject them in every place manually. When we
12
+ * re-introduce them to the components, we can likely remove the `di` variables
13
+ * and instead use internal variables.
14
+ *
15
+ * If component _only_ has injected variables, it is fully internal and was
16
+ * broken out to be it's own function.
17
+ */
18
+
19
+ // oxlint-disable-next-line @atlassian/no-restricted-imports
20
+ import { format, parseISO } from 'date-fns';
21
+ import { defaultDateFormat } from './default-date-format';
22
+ import { convertTokens } from './parse-tokens';
23
+ export const formatDate = (value, di) => {
24
+ const {
25
+ formatDisplayLabel,
26
+ dateFormat,
27
+ l10n
28
+ } = di;
29
+ if (formatDisplayLabel) {
30
+ return formatDisplayLabel(value, dateFormat || defaultDateFormat);
31
+ }
32
+ const date = parseISO(value);
33
+ return dateFormat ? format(date, convertTokens(dateFormat)) : l10n.formatDate(date);
34
+ };
@@ -17,15 +17,8 @@
17
17
  */
18
18
 
19
19
  // oxlint-disable-next-line @atlassian/no-restricted-imports
20
- import { format, lastDayOfMonth, parseISO } from 'date-fns';
21
- import { convertTokens } from './parse-tokens';
22
- import { defaultDateFormat, padToTwo, placeholderDatetime } from './index';
23
- export const isDateDisabled = (date, di) => {
24
- const {
25
- disabled
26
- } = di;
27
- return disabled.indexOf(date) > -1;
28
- };
20
+ import { lastDayOfMonth } from 'date-fns';
21
+ import { padToTwo } from './pad-two';
29
22
  export const getParsedISO = di => {
30
23
  const {
31
24
  iso
@@ -43,49 +36,4 @@ export const getParsedISO = di => {
43
36
  newIso = `${parsedYear}-${padToTwo(parsedMonth)}-${padToTwo(parsedDate)}`;
44
37
  }
45
38
  return newIso;
46
- };
47
-
48
- /**
49
- * There are two props that can change how the date is parsed.
50
- * The priority of props used is:
51
- * 1. `parseInputValue`
52
- * 2. `locale`
53
- */
54
- export const parseDate = (date, di) => {
55
- const {
56
- parseInputValue,
57
- dateFormat,
58
- l10n
59
- } = di;
60
- if (parseInputValue) {
61
- return parseInputValue(date, dateFormat || defaultDateFormat);
62
- }
63
- return l10n.parseDate(date);
64
- };
65
-
66
- /**
67
- * There are multiple props that can change how the date is formatted.
68
- * The priority of props used is:
69
- * 1. `formatDisplayLabel`
70
- * 2. `dateFormat`
71
- * 3. `locale`
72
- */
73
- export const formatDate = (value, di) => {
74
- const {
75
- formatDisplayLabel,
76
- dateFormat,
77
- l10n
78
- } = di;
79
- if (formatDisplayLabel) {
80
- return formatDisplayLabel(value, dateFormat || defaultDateFormat);
81
- }
82
- const date = parseISO(value);
83
- return dateFormat ? format(date, convertTokens(dateFormat)) : l10n.formatDate(date);
84
- };
85
- export const getPlaceholder = di => {
86
- const {
87
- placeholder,
88
- l10n
89
- } = di;
90
- return placeholder || l10n.formatDate(placeholderDatetime);
91
39
  };