@atlaskit/datetime-picker 19.4.0 → 19.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlaskit/datetime-picker
2
2
 
3
+ ## 19.4.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+
9
+ ## 19.4.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [`efaa75ad1bb94`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/efaa75ad1bb94) -
14
+ Preserve supplied ISO offsets when editing datetime values behind
15
+ `platform-dst-dtp-preserve-offset`.
16
+
3
17
  ## 19.4.0
4
18
 
5
19
  ### Minor Changes
@@ -47,7 +47,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
47
47
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
48
48
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
49
49
  var packageName = "@atlaskit/datetime-picker";
50
- var packageVersion = "19.3.2";
50
+ var packageVersion = "19.4.1";
51
51
  var styles = {
52
52
  pickerContainerStyle: "_kqswh2mm",
53
53
  dropdownIndicatorStyles: "_1ul91k8s _1tke1k8s _1e0c1txw _4cvr1h6o _1bah1h6o",
@@ -35,7 +35,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
35
35
  // for typing `process`
36
36
  // oxlint-disable-next-line @atlassian/no-restricted-imports
37
37
  var packageName = "@atlaskit/datetime-picker";
38
- var packageVersion = "19.3.2";
38
+ var packageVersion = "19.4.1";
39
39
  var analyticsAttributes = {
40
40
  componentName: 'dateTimePicker',
41
41
  packageName: packageName,
@@ -83,6 +83,38 @@ var getStyles = function getStyles(isInputMotionEnabled, roundedCorners) {
83
83
  }
84
84
  };
85
85
  };
86
+ var hasExplicitZone = function hasExplicitZone(value) {
87
+ return value.endsWith('Z') || Math.max(value.lastIndexOf('+'), value.lastIndexOf('-')) > 15;
88
+ };
89
+ var parseDateTimeValueWithOffset = function parseDateTimeValueWithOffset(value) {
90
+ var parsed = (0, _dateFns.parseISO)(value);
91
+ var zoneStart = value.endsWith('Z') ? value.length - 1 : Math.max(value.lastIndexOf('+'), value.lastIndexOf('-'));
92
+ if (!(0, _dateFns.isValid)(parsed) || value[10] !== 'T' || zoneStart <= 15) {
93
+ return undefined;
94
+ }
95
+ var zoneValue = value.slice(zoneStart);
96
+ if (!/^(?:Z|[+-]\d{2}(?::?\d{2})?)$/.test(zoneValue)) {
97
+ return undefined;
98
+ }
99
+ return {
100
+ dateValue: value.slice(0, 10),
101
+ timeValue: value.slice(11, 16),
102
+ zoneValue: zoneValue
103
+ };
104
+ };
105
+ var parseDateTimeValue = function parseDateTimeValue(value) {
106
+ if ((0, _fg.fg)('platform-dst-dtp-preserve-offset')) {
107
+ if (hasExplicitZone(value)) {
108
+ return parseDateTimeValueWithOffset(value);
109
+ }
110
+ }
111
+ var parsed = (0, _dateFns.parseISO)(value);
112
+ return (0, _dateFns.isValid)(parsed) ? {
113
+ dateValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('YYYY-MM-DD')),
114
+ timeValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('HH:mm')),
115
+ zoneValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('ZZ'))
116
+ } : undefined;
117
+ };
86
118
 
87
119
  /**
88
120
  * Two action types keep the reducer focused:
@@ -152,6 +184,7 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
152
184
  isFocused = _useState2[0],
153
185
  setIsFocused = _useState2[1];
154
186
  var isInputMotionEnabled = (0, _fg.fg)('platform-dst-motion-uplift-input');
187
+ var isZoneExplicitRef = (0, _react.useRef)(false);
155
188
 
156
189
  /**
157
190
  * Defined inside the component so the reducer closes over `providedParseValue`
@@ -187,13 +220,10 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
187
220
  zoneValue: state.zoneValue
188
221
  };
189
222
  }
190
- var parsed = (0, _dateFns.parseISO)(newValue);
191
- return (0, _dateFns.isValid)(parsed) ? {
192
- value: newValue,
193
- dateValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('YYYY-MM-DD')),
194
- timeValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('HH:mm')),
195
- zoneValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('ZZ'))
196
- } : {
223
+ var parsed = parseDateTimeValue(newValue);
224
+ return parsed ? _objectSpread({
225
+ value: newValue
226
+ }, parsed) : {
197
227
  value: newValue,
198
228
  dateValue: '',
199
229
  timeValue: '',
@@ -207,6 +237,7 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
207
237
  var _useReducer = (0, _react.useReducer)(reducer, null, function () {
208
238
  var _ref3;
209
239
  var initialValue = (_ref3 = providedValue !== null && providedValue !== void 0 ? providedValue : defaultValue) !== null && _ref3 !== void 0 ? _ref3 : '';
240
+ isZoneExplicitRef.current = hasExplicitZone(initialValue);
210
241
  var initialDate = (datePickerPropsWithSelectProps === null || datePickerPropsWithSelectProps === void 0 ? void 0 : datePickerPropsWithSelectProps.defaultValue) || '';
211
242
  var initialTime = (timePickerPropsWithSelectProps === null || timePickerPropsWithSelectProps === void 0 ? void 0 : timePickerPropsWithSelectProps.defaultValue) || '';
212
243
  if (!initialValue) {
@@ -228,13 +259,10 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
228
259
  zoneValue: ''
229
260
  };
230
261
  }
231
- var parsed = (0, _dateFns.parseISO)(initialValue);
232
- return (0, _dateFns.isValid)(parsed) ? {
233
- value: initialValue,
234
- dateValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('YYYY-MM-DD')),
235
- timeValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('HH:mm')),
236
- zoneValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('ZZ'))
237
- } : {
262
+ var parsed = parseDateTimeValue(initialValue);
263
+ return parsed ? _objectSpread({
264
+ value: initialValue
265
+ }, parsed) : {
238
266
  value: initialValue,
239
267
  dateValue: initialDate,
240
268
  timeValue: initialTime,
@@ -251,6 +279,7 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
251
279
  // `undefined` to the `value` prop will not clear the hidden input and will
252
280
  // cause unexpected issues.
253
281
  var hasReceivedProvidedValue = (0, _react.useRef)(providedValue !== undefined);
282
+ var lastEmittedValueRef = (0, _react.useRef)();
254
283
  // We don't want to set the state on the first render, as it would
255
284
  // needlessly be a duplicate.
256
285
  var isFirstRender = (0, _react.useRef)(true);
@@ -261,12 +290,17 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
261
290
  }
262
291
  if (providedValue !== undefined) {
263
292
  hasReceivedProvidedValue.current = true;
293
+ if (providedValue !== lastEmittedValueRef.current) {
294
+ isZoneExplicitRef.current = hasExplicitZone(providedValue);
295
+ }
264
296
  dispatch({
265
297
  type: 'SET_VALUE',
266
298
  payload: providedValue
267
299
  });
268
300
  } else if (hasReceivedProvidedValue.current) {
269
301
  hasReceivedProvidedValue.current = false;
302
+ isZoneExplicitRef.current = false;
303
+ lastEmittedValueRef.current = undefined;
270
304
  dispatch({
271
305
  type: 'SET_VALUE',
272
306
  payload: ''
@@ -288,12 +322,8 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
288
322
  zoneValue: providedZoneValue
289
323
  };
290
324
  }
291
- var parsed = (0, _dateFns.parseISO)(value);
292
- return (0, _dateFns.isValid)(parsed) ? {
293
- dateValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('YYYY-MM-DD')),
294
- timeValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('HH:mm')),
295
- zoneValue: (0, _dateFns.format)(parsed, (0, _parseTokens.convertTokens)('ZZ'))
296
- } : {
325
+ var parsed = parseDateTimeValue(value);
326
+ return parsed || {
297
327
  dateValue: dtState.dateValue,
298
328
  timeValue: dtState.timeValue,
299
329
  zoneValue: dtState.zoneValue
@@ -374,7 +404,8 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
374
404
  providedZoneValue = _ref4.providedZoneValue;
375
405
  if (providedDateValue && providedTimeValue) {
376
406
  var isoValue = (0, _formatDateTimeZoneIntoIso.formatDateTimeZoneIntoIso)(providedDateValue, providedTimeValue, providedZoneValue);
377
- var _parseValue = parseValue(isoValue, providedDateValue, providedTimeValue, providedZoneValue),
407
+ var valueToParse = (0, _fg.fg)('platform-dst-dtp-preserve-offset') && !providedParseValue && !isZoneExplicitRef.current ? (0, _formatDateTimeZoneIntoIso.formatDateTimeZoneIntoIso)(providedDateValue, providedTimeValue, '') : isoValue;
408
+ var _parseValue = parseValue(valueToParse, providedDateValue, providedTimeValue, providedZoneValue),
378
409
  parsedZone = _parseValue.zoneValue;
379
410
  var valueWithValidZone = (0, _formatDateTimeZoneIntoIso.formatDateTimeZoneIntoIso)(providedDateValue, providedTimeValue, parsedZone);
380
411
  dispatch({
@@ -386,6 +417,7 @@ var DateTimePicker = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
386
417
  zoneValue: parsedZone
387
418
  }
388
419
  });
420
+ lastEmittedValueRef.current = valueWithValidZone;
389
421
  onChangePropWithAnalytics(valueWithValidZone);
390
422
  // If the date or time value was cleared when there is an existing datetime value, then clear the value.
391
423
  } else if (dtState.value) {
@@ -38,7 +38,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
38
38
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
39
39
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } // oxlint-disable-next-line @atlassian/no-restricted-imports
40
40
  var packageName = "@atlaskit/datetime-picker";
41
- var packageVersion = "19.3.2";
41
+ var packageVersion = "19.4.1";
42
42
  var defaultTimeFormat = 'h:mma';
43
43
  var menuStyles = {
44
44
  /* Need to remove default absolute positioning as that causes issues with position fixed */
@@ -32,7 +32,7 @@ import { parseDate } from '../internal/parse-date';
32
32
  import { PickerButtonContainer } from '../internal/picker-button-container';
33
33
  import { makeSingleValue } from '../internal/single-value';
34
34
  const packageName = "@atlaskit/datetime-picker";
35
- const packageVersion = "19.3.2";
35
+ const packageVersion = "19.4.1";
36
36
  const styles = {
37
37
  pickerContainerStyle: "_kqswh2mm",
38
38
  dropdownIndicatorStyles: "_1ul91k8s _1tke1k8s _1e0c1txw _4cvr1h6o _1bah1h6o",
@@ -22,7 +22,7 @@ import { convertTokens } from '../internal/parse-tokens';
22
22
  import DatePicker from './date-picker';
23
23
  import TimePicker from './time-picker';
24
24
  const packageName = "@atlaskit/datetime-picker";
25
- const packageVersion = "19.3.2";
25
+ const packageVersion = "19.4.1";
26
26
  const analyticsAttributes = {
27
27
  componentName: 'dateTimePicker',
28
28
  packageName,
@@ -70,6 +70,36 @@ const getStyles = (isInputMotionEnabled, roundedCorners) => ({
70
70
  }
71
71
  })
72
72
  });
73
+ const hasExplicitZone = value => value.endsWith('Z') || Math.max(value.lastIndexOf('+'), value.lastIndexOf('-')) > 15;
74
+ const parseDateTimeValueWithOffset = value => {
75
+ const parsed = parseISO(value);
76
+ const zoneStart = value.endsWith('Z') ? value.length - 1 : Math.max(value.lastIndexOf('+'), value.lastIndexOf('-'));
77
+ if (!isValid(parsed) || value[10] !== 'T' || zoneStart <= 15) {
78
+ return undefined;
79
+ }
80
+ const zoneValue = value.slice(zoneStart);
81
+ if (!/^(?:Z|[+-]\d{2}(?::?\d{2})?)$/.test(zoneValue)) {
82
+ return undefined;
83
+ }
84
+ return {
85
+ dateValue: value.slice(0, 10),
86
+ timeValue: value.slice(11, 16),
87
+ zoneValue
88
+ };
89
+ };
90
+ const parseDateTimeValue = value => {
91
+ if (fg('platform-dst-dtp-preserve-offset')) {
92
+ if (hasExplicitZone(value)) {
93
+ return parseDateTimeValueWithOffset(value);
94
+ }
95
+ }
96
+ const parsed = parseISO(value);
97
+ return isValid(parsed) ? {
98
+ dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
99
+ timeValue: format(parsed, convertTokens('HH:mm')),
100
+ zoneValue: format(parsed, convertTokens('ZZ'))
101
+ } : undefined;
102
+ };
73
103
 
74
104
  /**
75
105
  * Two action types keep the reducer focused:
@@ -124,6 +154,7 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
124
154
  }, ref) => {
125
155
  const [isFocused, setIsFocused] = useState(false);
126
156
  const isInputMotionEnabled = fg('platform-dst-motion-uplift-input');
157
+ const isZoneExplicitRef = useRef(false);
127
158
 
128
159
  /**
129
160
  * Defined inside the component so the reducer closes over `providedParseValue`
@@ -160,12 +191,10 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
160
191
  zoneValue: state.zoneValue
161
192
  };
162
193
  }
163
- const parsed = parseISO(newValue);
164
- return isValid(parsed) ? {
194
+ const parsed = parseDateTimeValue(newValue);
195
+ return parsed ? {
165
196
  value: newValue,
166
- dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
167
- timeValue: format(parsed, convertTokens('HH:mm')),
168
- zoneValue: format(parsed, convertTokens('ZZ'))
197
+ ...parsed
169
198
  } : {
170
199
  value: newValue,
171
200
  dateValue: '',
@@ -180,6 +209,7 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
180
209
  const [dtState, dispatch] = useReducer(reducer, null, () => {
181
210
  var _ref;
182
211
  const initialValue = (_ref = providedValue !== null && providedValue !== void 0 ? providedValue : defaultValue) !== null && _ref !== void 0 ? _ref : '';
212
+ isZoneExplicitRef.current = hasExplicitZone(initialValue);
183
213
  const initialDate = (datePickerPropsWithSelectProps === null || datePickerPropsWithSelectProps === void 0 ? void 0 : datePickerPropsWithSelectProps.defaultValue) || '';
184
214
  const initialTime = (timePickerPropsWithSelectProps === null || timePickerPropsWithSelectProps === void 0 ? void 0 : timePickerPropsWithSelectProps.defaultValue) || '';
185
215
  if (!initialValue) {
@@ -202,12 +232,10 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
202
232
  zoneValue: ''
203
233
  };
204
234
  }
205
- const parsed = parseISO(initialValue);
206
- return isValid(parsed) ? {
235
+ const parsed = parseDateTimeValue(initialValue);
236
+ return parsed ? {
207
237
  value: initialValue,
208
- dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
209
- timeValue: format(parsed, convertTokens('HH:mm')),
210
- zoneValue: format(parsed, convertTokens('ZZ'))
238
+ ...parsed
211
239
  } : {
212
240
  value: initialValue,
213
241
  dateValue: initialDate,
@@ -222,6 +250,7 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
222
250
  // `undefined` to the `value` prop will not clear the hidden input and will
223
251
  // cause unexpected issues.
224
252
  const hasReceivedProvidedValue = useRef(providedValue !== undefined);
253
+ const lastEmittedValueRef = useRef();
225
254
  // We don't want to set the state on the first render, as it would
226
255
  // needlessly be a duplicate.
227
256
  const isFirstRender = useRef(true);
@@ -232,12 +261,17 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
232
261
  }
233
262
  if (providedValue !== undefined) {
234
263
  hasReceivedProvidedValue.current = true;
264
+ if (providedValue !== lastEmittedValueRef.current) {
265
+ isZoneExplicitRef.current = hasExplicitZone(providedValue);
266
+ }
235
267
  dispatch({
236
268
  type: 'SET_VALUE',
237
269
  payload: providedValue
238
270
  });
239
271
  } else if (hasReceivedProvidedValue.current) {
240
272
  hasReceivedProvidedValue.current = false;
273
+ isZoneExplicitRef.current = false;
274
+ lastEmittedValueRef.current = undefined;
241
275
  dispatch({
242
276
  type: 'SET_VALUE',
243
277
  payload: ''
@@ -259,12 +293,8 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
259
293
  zoneValue: providedZoneValue
260
294
  };
261
295
  }
262
- const parsed = parseISO(value);
263
- return isValid(parsed) ? {
264
- dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
265
- timeValue: format(parsed, convertTokens('HH:mm')),
266
- zoneValue: format(parsed, convertTokens('ZZ'))
267
- } : {
296
+ const parsed = parseDateTimeValue(value);
297
+ return parsed || {
268
298
  dateValue: dtState.dateValue,
269
299
  timeValue: dtState.timeValue,
270
300
  zoneValue: dtState.zoneValue
@@ -347,9 +377,10 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
347
377
  }) => {
348
378
  if (providedDateValue && providedTimeValue) {
349
379
  const isoValue = formatDateTimeZoneIntoIso(providedDateValue, providedTimeValue, providedZoneValue);
380
+ const valueToParse = fg('platform-dst-dtp-preserve-offset') && !providedParseValue && !isZoneExplicitRef.current ? formatDateTimeZoneIntoIso(providedDateValue, providedTimeValue, '') : isoValue;
350
381
  const {
351
382
  zoneValue: parsedZone
352
- } = parseValue(isoValue, providedDateValue, providedTimeValue, providedZoneValue);
383
+ } = parseValue(valueToParse, providedDateValue, providedTimeValue, providedZoneValue);
353
384
  const valueWithValidZone = formatDateTimeZoneIntoIso(providedDateValue, providedTimeValue, parsedZone);
354
385
  dispatch({
355
386
  type: 'APPLY',
@@ -360,6 +391,7 @@ const DateTimePicker = /*#__PURE__*/forwardRef(({
360
391
  zoneValue: parsedZone
361
392
  }
362
393
  });
394
+ lastEmittedValueRef.current = valueWithValidZone;
363
395
  onChangePropWithAnalytics(valueWithValidZone);
364
396
  // If the date or time value was cleared when there is an existing datetime value, then clear the value.
365
397
  } else if (dtState.value) {
@@ -25,7 +25,7 @@ import { PickerButtonContainer } from '../internal/picker-button-container';
25
25
  import { placeholderDatetime } from '../internal/placeholder-date-time';
26
26
  import { makeSingleValue } from '../internal/single-value';
27
27
  const packageName = "@atlaskit/datetime-picker";
28
- const packageVersion = "19.3.2";
28
+ const packageVersion = "19.4.1";
29
29
  const defaultTimeFormat = 'h:mma';
30
30
  const menuStyles = {
31
31
  /* Need to remove default absolute positioning as that causes issues with position fixed */
@@ -40,7 +40,7 @@ import { parseDate } from '../internal/parse-date';
40
40
  import { PickerButtonContainer } from '../internal/picker-button-container';
41
41
  import { makeSingleValue } from '../internal/single-value';
42
42
  var packageName = "@atlaskit/datetime-picker";
43
- var packageVersion = "19.3.2";
43
+ var packageVersion = "19.4.1";
44
44
  var styles = {
45
45
  pickerContainerStyle: "_kqswh2mm",
46
46
  dropdownIndicatorStyles: "_1ul91k8s _1tke1k8s _1e0c1txw _4cvr1h6o _1bah1h6o",
@@ -29,7 +29,7 @@ import { convertTokens } from '../internal/parse-tokens';
29
29
  import DatePicker from './date-picker';
30
30
  import TimePicker from './time-picker';
31
31
  var packageName = "@atlaskit/datetime-picker";
32
- var packageVersion = "19.3.2";
32
+ var packageVersion = "19.4.1";
33
33
  var analyticsAttributes = {
34
34
  componentName: 'dateTimePicker',
35
35
  packageName: packageName,
@@ -77,6 +77,38 @@ var getStyles = function getStyles(isInputMotionEnabled, roundedCorners) {
77
77
  }
78
78
  };
79
79
  };
80
+ var hasExplicitZone = function hasExplicitZone(value) {
81
+ return value.endsWith('Z') || Math.max(value.lastIndexOf('+'), value.lastIndexOf('-')) > 15;
82
+ };
83
+ var parseDateTimeValueWithOffset = function parseDateTimeValueWithOffset(value) {
84
+ var parsed = parseISO(value);
85
+ var zoneStart = value.endsWith('Z') ? value.length - 1 : Math.max(value.lastIndexOf('+'), value.lastIndexOf('-'));
86
+ if (!isValid(parsed) || value[10] !== 'T' || zoneStart <= 15) {
87
+ return undefined;
88
+ }
89
+ var zoneValue = value.slice(zoneStart);
90
+ if (!/^(?:Z|[+-]\d{2}(?::?\d{2})?)$/.test(zoneValue)) {
91
+ return undefined;
92
+ }
93
+ return {
94
+ dateValue: value.slice(0, 10),
95
+ timeValue: value.slice(11, 16),
96
+ zoneValue: zoneValue
97
+ };
98
+ };
99
+ var parseDateTimeValue = function parseDateTimeValue(value) {
100
+ if (fg('platform-dst-dtp-preserve-offset')) {
101
+ if (hasExplicitZone(value)) {
102
+ return parseDateTimeValueWithOffset(value);
103
+ }
104
+ }
105
+ var parsed = parseISO(value);
106
+ return isValid(parsed) ? {
107
+ dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
108
+ timeValue: format(parsed, convertTokens('HH:mm')),
109
+ zoneValue: format(parsed, convertTokens('ZZ'))
110
+ } : undefined;
111
+ };
80
112
 
81
113
  /**
82
114
  * Two action types keep the reducer focused:
@@ -146,6 +178,7 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
146
178
  isFocused = _useState2[0],
147
179
  setIsFocused = _useState2[1];
148
180
  var isInputMotionEnabled = fg('platform-dst-motion-uplift-input');
181
+ var isZoneExplicitRef = useRef(false);
149
182
 
150
183
  /**
151
184
  * Defined inside the component so the reducer closes over `providedParseValue`
@@ -181,13 +214,10 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
181
214
  zoneValue: state.zoneValue
182
215
  };
183
216
  }
184
- var parsed = parseISO(newValue);
185
- return isValid(parsed) ? {
186
- value: newValue,
187
- dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
188
- timeValue: format(parsed, convertTokens('HH:mm')),
189
- zoneValue: format(parsed, convertTokens('ZZ'))
190
- } : {
217
+ var parsed = parseDateTimeValue(newValue);
218
+ return parsed ? _objectSpread({
219
+ value: newValue
220
+ }, parsed) : {
191
221
  value: newValue,
192
222
  dateValue: '',
193
223
  timeValue: '',
@@ -201,6 +231,7 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
201
231
  var _useReducer = useReducer(reducer, null, function () {
202
232
  var _ref3;
203
233
  var initialValue = (_ref3 = providedValue !== null && providedValue !== void 0 ? providedValue : defaultValue) !== null && _ref3 !== void 0 ? _ref3 : '';
234
+ isZoneExplicitRef.current = hasExplicitZone(initialValue);
204
235
  var initialDate = (datePickerPropsWithSelectProps === null || datePickerPropsWithSelectProps === void 0 ? void 0 : datePickerPropsWithSelectProps.defaultValue) || '';
205
236
  var initialTime = (timePickerPropsWithSelectProps === null || timePickerPropsWithSelectProps === void 0 ? void 0 : timePickerPropsWithSelectProps.defaultValue) || '';
206
237
  if (!initialValue) {
@@ -222,13 +253,10 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
222
253
  zoneValue: ''
223
254
  };
224
255
  }
225
- var parsed = parseISO(initialValue);
226
- return isValid(parsed) ? {
227
- value: initialValue,
228
- dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
229
- timeValue: format(parsed, convertTokens('HH:mm')),
230
- zoneValue: format(parsed, convertTokens('ZZ'))
231
- } : {
256
+ var parsed = parseDateTimeValue(initialValue);
257
+ return parsed ? _objectSpread({
258
+ value: initialValue
259
+ }, parsed) : {
232
260
  value: initialValue,
233
261
  dateValue: initialDate,
234
262
  timeValue: initialTime,
@@ -245,6 +273,7 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
245
273
  // `undefined` to the `value` prop will not clear the hidden input and will
246
274
  // cause unexpected issues.
247
275
  var hasReceivedProvidedValue = useRef(providedValue !== undefined);
276
+ var lastEmittedValueRef = useRef();
248
277
  // We don't want to set the state on the first render, as it would
249
278
  // needlessly be a duplicate.
250
279
  var isFirstRender = useRef(true);
@@ -255,12 +284,17 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
255
284
  }
256
285
  if (providedValue !== undefined) {
257
286
  hasReceivedProvidedValue.current = true;
287
+ if (providedValue !== lastEmittedValueRef.current) {
288
+ isZoneExplicitRef.current = hasExplicitZone(providedValue);
289
+ }
258
290
  dispatch({
259
291
  type: 'SET_VALUE',
260
292
  payload: providedValue
261
293
  });
262
294
  } else if (hasReceivedProvidedValue.current) {
263
295
  hasReceivedProvidedValue.current = false;
296
+ isZoneExplicitRef.current = false;
297
+ lastEmittedValueRef.current = undefined;
264
298
  dispatch({
265
299
  type: 'SET_VALUE',
266
300
  payload: ''
@@ -282,12 +316,8 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
282
316
  zoneValue: providedZoneValue
283
317
  };
284
318
  }
285
- var parsed = parseISO(value);
286
- return isValid(parsed) ? {
287
- dateValue: format(parsed, convertTokens('YYYY-MM-DD')),
288
- timeValue: format(parsed, convertTokens('HH:mm')),
289
- zoneValue: format(parsed, convertTokens('ZZ'))
290
- } : {
319
+ var parsed = parseDateTimeValue(value);
320
+ return parsed || {
291
321
  dateValue: dtState.dateValue,
292
322
  timeValue: dtState.timeValue,
293
323
  zoneValue: dtState.zoneValue
@@ -368,7 +398,8 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
368
398
  providedZoneValue = _ref4.providedZoneValue;
369
399
  if (providedDateValue && providedTimeValue) {
370
400
  var isoValue = formatDateTimeZoneIntoIso(providedDateValue, providedTimeValue, providedZoneValue);
371
- var _parseValue = parseValue(isoValue, providedDateValue, providedTimeValue, providedZoneValue),
401
+ var valueToParse = fg('platform-dst-dtp-preserve-offset') && !providedParseValue && !isZoneExplicitRef.current ? formatDateTimeZoneIntoIso(providedDateValue, providedTimeValue, '') : isoValue;
402
+ var _parseValue = parseValue(valueToParse, providedDateValue, providedTimeValue, providedZoneValue),
372
403
  parsedZone = _parseValue.zoneValue;
373
404
  var valueWithValidZone = formatDateTimeZoneIntoIso(providedDateValue, providedTimeValue, parsedZone);
374
405
  dispatch({
@@ -380,6 +411,7 @@ var DateTimePicker = /*#__PURE__*/forwardRef(function (_ref2, ref) {
380
411
  zoneValue: parsedZone
381
412
  }
382
413
  });
414
+ lastEmittedValueRef.current = valueWithValidZone;
383
415
  onChangePropWithAnalytics(valueWithValidZone);
384
416
  // If the date or time value was cleared when there is an existing datetime value, then clear the value.
385
417
  } else if (dtState.value) {
@@ -31,7 +31,7 @@ import { PickerButtonContainer } from '../internal/picker-button-container';
31
31
  import { placeholderDatetime } from '../internal/placeholder-date-time';
32
32
  import { makeSingleValue } from '../internal/single-value';
33
33
  var packageName = "@atlaskit/datetime-picker";
34
- var packageVersion = "19.3.2";
34
+ var packageVersion = "19.4.1";
35
35
  var defaultTimeFormat = 'h:mma';
36
36
  var menuStyles = {
37
37
  /* Need to remove default absolute positioning as that causes issues with position fixed */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/datetime-picker",
3
- "version": "19.4.0",
3
+ "version": "19.4.2",
4
4
  "description": "A date time picker allows the user to select an associated date and time.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -48,8 +48,8 @@
48
48
  "@atlaskit/react-compiler-gating": "^0.2.0",
49
49
  "@atlaskit/react-select": "^4.12.0",
50
50
  "@atlaskit/select": "^23.1.0",
51
- "@atlaskit/tokens": "^20.7.0",
52
- "@atlaskit/top-layer": "^6.6.0",
51
+ "@atlaskit/tokens": "^20.8.0",
52
+ "@atlaskit/top-layer": "^7.0.0",
53
53
  "@babel/runtime": "^7.0.0",
54
54
  "@compiled/react": "^1.0.2",
55
55
  "date-fns": "^2.17.0"
@@ -64,15 +64,15 @@
64
64
  "@atlaskit/code": "^20.0.0",
65
65
  "@atlaskit/codemod-utils": "^5.1.0",
66
66
  "@atlaskit/docs": "^12.3.0",
67
- "@atlaskit/form": "^18.2.0",
67
+ "@atlaskit/form": "^18.3.0",
68
68
  "@atlaskit/heading": "^8.0.0",
69
69
  "@atlaskit/link": "^5.1.0",
70
70
  "@atlaskit/menu": "^11.0.0",
71
71
  "@atlaskit/modal-dialog": "^17.1.0",
72
- "@atlaskit/popup": "^10.0.0",
72
+ "@atlaskit/popup": "^10.1.0",
73
73
  "@atlaskit/range": "^12.2.0",
74
74
  "@atlaskit/section-message": "^10.2.0",
75
- "@atlaskit/textfield": "^10.2.0",
75
+ "@atlaskit/textfield": "^10.3.0",
76
76
  "@atlaskit/toggle": "^17.3.0",
77
77
  "@atlassian/feature-flags-test-utils": "^1.3.0",
78
78
  "@atlassian/ssr-tests": "workspace:^",
@@ -92,6 +92,9 @@
92
92
  "platform-dst-top-layer": {
93
93
  "type": "boolean"
94
94
  },
95
+ "platform-dst-dtp-preserve-offset": {
96
+ "type": "boolean"
97
+ },
95
98
  "platform-dst-motion-uplift-input": {
96
99
  "type": "boolean",
97
100
  "referenceOnly": true