@contentful/field-editor-date 2.0.8 → 2.0.10-canary.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.
@@ -11,12 +11,6 @@ Object.defineProperty(exports, "DatepickerInput", {
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _f36components = require("@contentful/f36-components");
13
13
  const _css = require("@emotion/css");
14
- const _moment = /*#__PURE__*/ _interop_require_default(require("moment"));
15
- function _interop_require_default(obj) {
16
- return obj && obj.__esModule ? obj : {
17
- default: obj
18
- };
19
- }
20
14
  function _getRequireWildcardCache(nodeInterop) {
21
15
  if (typeof WeakMap !== "function") return null;
22
16
  var cacheBabelInterop = new WeakMap();
@@ -75,14 +69,12 @@ const DatepickerInput = (props)=>{
75
69
  toDate
76
70
  ];
77
71
  }, []);
78
- const dateObj = props.value?.toObject();
79
- const selectedDate = dateObj ? new Date(dateObj.years, dateObj.months, dateObj.date) : undefined;
72
+ const selectedDate = props.value;
80
73
  return /*#__PURE__*/ _react.default.createElement(_f36components.Datepicker, {
81
74
  className: styles.root,
82
75
  selected: selectedDate,
83
76
  onSelect: (day)=>{
84
- const momentDay = day ? (0, _moment.default)(day) : undefined;
85
- props.onChange(momentDay);
77
+ props.onChange(day ?? undefined);
86
78
  },
87
79
  inputProps: {
88
80
  isDisabled: props.disabled,
@@ -11,12 +11,7 @@ Object.defineProperty(exports, "TimepickerInput", {
11
11
  const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
12
12
  const _f36components = require("@contentful/f36-components");
13
13
  const _css = require("@emotion/css");
14
- const _moment = /*#__PURE__*/ _interop_require_default(require("moment"));
15
- function _interop_require_default(obj) {
16
- return obj && obj.__esModule ? obj : {
17
- default: obj
18
- };
19
- }
14
+ const _datefns = require("date-fns");
20
15
  function _getRequireWildcardCache(nodeInterop) {
21
16
  if (typeof WeakMap !== "function") return null;
22
17
  var cacheBabelInterop = new WeakMap();
@@ -60,41 +55,31 @@ function _interop_require_wildcard(obj, nodeInterop) {
60
55
  }
61
56
  const validInputFormats = [
62
57
  'hh:mm a',
63
- 'hh:mm A',
64
58
  'h:mm a',
65
- 'h:mm A',
66
59
  'hh:mm',
67
- 'k:mm',
68
60
  'kk:mm',
61
+ 'k:mm',
69
62
  'h a',
70
- 'h A',
71
- 'h',
72
- 'hh',
73
- 'HH'
63
+ 'HH',
64
+ 'H:mm',
65
+ 'h'
74
66
  ];
67
+ const REF_DATE = new Date(2000, 0, 1);
75
68
  function parseRawInput(raw) {
76
- let time = null;
77
- for(let i = 0; i < validInputFormats.length; i++){
78
- const date = (0, _moment.default)(raw, validInputFormats[i]);
79
- if (date.isValid()) {
80
- time = date;
81
- break;
82
- }
69
+ for (const fmt of validInputFormats){
70
+ const parsed = (0, _datefns.parse)(raw, fmt, REF_DATE);
71
+ if ((0, _datefns.isValid)(parsed)) return parsed;
83
72
  }
84
- return time;
73
+ return null;
85
74
  }
86
- const getDefaultTime = ()=>{
87
- return (0, _moment.default)(`12:00 AM`, 'hh:mm A');
88
- };
89
- const formatToString = (uses12hClock, value)=>{
90
- return uses12hClock ? value.format('hh:mm A') : value.format('HH:mm');
91
- };
75
+ const getDefaultTime = ()=>(0, _datefns.parse)('12:00 AM', 'hh:mm a', REF_DATE);
76
+ const formatToString = (uses12hClock, value)=>(0, _datefns.format)(value, uses12hClock ? 'hh:mm a' : 'HH:mm');
92
77
  const TimepickerInput = ({ disabled, uses12hClock, time = '12:00', ampm = 'AM', onChange })=>{
93
78
  const [selectedTime, setSelectedTime] = (0, _react.useState)(()=>{
94
79
  return formatToString(uses12hClock, getDefaultTime());
95
80
  });
96
81
  (0, _react.useEffect)(()=>{
97
- setSelectedTime(formatToString(uses12hClock, (0, _moment.default)(`${time} ${ampm}`, 'hh:mm A')));
82
+ setSelectedTime(formatToString(uses12hClock, (0, _datefns.parse)(`${time} ${ampm}`, 'hh:mm a', REF_DATE)));
98
83
  }, [
99
84
  time,
100
85
  ampm,
@@ -106,8 +91,8 @@ const TimepickerInput = ({ disabled, uses12hClock, time = '12:00', ampm = 'AM',
106
91
  const parsedTime = parseRawInput(raw);
107
92
  if (parsedTime) {
108
93
  onChange({
109
- time: parsedTime.format('hh:mm'),
110
- ampm: parsedTime.format('A')
94
+ time: (0, _datefns.format)(parsedTime, 'hh:mm'),
95
+ ampm: (0, _datefns.format)(parsedTime, 'a').toUpperCase()
111
96
  });
112
97
  }
113
98
  }, [
@@ -122,8 +107,8 @@ const TimepickerInput = ({ disabled, uses12hClock, time = '12:00', ampm = 'AM',
122
107
  const value = parsedTime ?? getDefaultTime();
123
108
  setSelectedTime(formatToString(uses12hClock, value));
124
109
  onChange({
125
- time: value.format('hh:mm'),
126
- ampm: value.format('A')
110
+ time: (0, _datefns.format)(value, 'hh:mm'),
111
+ ampm: (0, _datefns.format)(value, 'a').toUpperCase()
127
112
  });
128
113
  }, [
129
114
  selectedTime,
@@ -2,19 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- const _moment = /*#__PURE__*/ _interop_require_default(require("moment"));
6
5
  const _date = require("./date");
7
- function _interop_require_default(obj) {
8
- return obj && obj.__esModule ? obj : {
9
- default: obj
10
- };
11
- }
12
6
  describe('date utils', ()=>{
13
7
  describe('buildFieldValue', ()=>{
14
8
  it('should work properly', ()=>{
15
9
  expect((0, _date.buildFieldValue)({
16
10
  data: {
17
- date: (0, _moment.default)('2018-02-02'),
11
+ date: new Date('2018-02-02'),
18
12
  time: '05:00',
19
13
  ampm: 'PM',
20
14
  utcOffset: '+03:00'
@@ -27,7 +21,7 @@ describe('date utils', ()=>{
27
21
  });
28
22
  expect((0, _date.buildFieldValue)({
29
23
  data: {
30
- date: (0, _moment.default)('2015-01-14'),
24
+ date: new Date('2015-01-14'),
31
25
  time: '05:00',
32
26
  ampm: 'AM',
33
27
  utcOffset: '-05:00'
@@ -40,7 +34,7 @@ describe('date utils', ()=>{
40
34
  });
41
35
  expect((0, _date.buildFieldValue)({
42
36
  data: {
43
- date: (0, _moment.default)('2015-01-14'),
37
+ date: new Date('2015-01-14'),
44
38
  time: '17:00',
45
39
  ampm: 'PM',
46
40
  utcOffset: '-05:00'
@@ -52,5 +46,338 @@ describe('date utils', ()=>{
52
46
  valid: '2015-01-14T17:00-05:00'
53
47
  });
54
48
  });
49
+ it('returns date-only format when usesTime and usesTimezone are false', ()=>{
50
+ expect((0, _date.buildFieldValue)({
51
+ data: {
52
+ date: new Date('2020-06-15'),
53
+ time: '10:30',
54
+ ampm: 'AM',
55
+ utcOffset: '+00:00'
56
+ },
57
+ usesTimezone: false,
58
+ usesTime: false
59
+ })).toEqual({
60
+ invalid: false,
61
+ valid: '2020-06-15'
62
+ });
63
+ });
64
+ it('returns datetime without timezone when usesTime=true, usesTimezone=false', ()=>{
65
+ expect((0, _date.buildFieldValue)({
66
+ data: {
67
+ date: new Date('2020-06-15'),
68
+ time: '14:30',
69
+ ampm: 'PM',
70
+ utcOffset: '+00:00'
71
+ },
72
+ usesTimezone: false,
73
+ usesTime: true
74
+ })).toEqual({
75
+ invalid: false,
76
+ valid: '2020-06-15T14:30'
77
+ });
78
+ });
79
+ it('returns valid: null when no date is provided', ()=>{
80
+ expect((0, _date.buildFieldValue)({
81
+ data: {
82
+ time: '10:00',
83
+ ampm: 'AM',
84
+ utcOffset: '+00:00'
85
+ },
86
+ usesTimezone: true,
87
+ usesTime: true
88
+ })).toEqual({
89
+ invalid: false,
90
+ valid: null
91
+ });
92
+ });
93
+ it('handles midnight (12:00 AM) correctly', ()=>{
94
+ expect((0, _date.buildFieldValue)({
95
+ data: {
96
+ date: new Date('2021-03-01'),
97
+ time: '12:00',
98
+ ampm: 'AM',
99
+ utcOffset: '+00:00'
100
+ },
101
+ usesTimezone: true,
102
+ usesTime: true
103
+ })).toEqual({
104
+ invalid: false,
105
+ valid: '2021-03-01T00:00+00:00'
106
+ });
107
+ });
108
+ it('handles noon (12:00 PM) correctly', ()=>{
109
+ expect((0, _date.buildFieldValue)({
110
+ data: {
111
+ date: new Date('2021-03-01'),
112
+ time: '12:00',
113
+ ampm: 'PM',
114
+ utcOffset: '+00:00'
115
+ },
116
+ usesTimezone: true,
117
+ usesTime: true
118
+ })).toEqual({
119
+ invalid: false,
120
+ valid: '2021-03-01T12:00+00:00'
121
+ });
122
+ });
123
+ it('preserves half-hour offset +05:30 (India)', ()=>{
124
+ expect((0, _date.buildFieldValue)({
125
+ data: {
126
+ date: new Date('2023-08-15'),
127
+ time: '10:00',
128
+ ampm: 'AM',
129
+ utcOffset: '+05:30'
130
+ },
131
+ usesTimezone: true,
132
+ usesTime: true
133
+ })).toEqual({
134
+ invalid: false,
135
+ valid: '2023-08-15T10:00+05:30'
136
+ });
137
+ });
138
+ it('preserves negative half-hour offset -09:30', ()=>{
139
+ expect((0, _date.buildFieldValue)({
140
+ data: {
141
+ date: new Date('2023-08-15'),
142
+ time: '03:30',
143
+ ampm: 'AM',
144
+ utcOffset: '-09:30'
145
+ },
146
+ usesTimezone: true,
147
+ usesTime: true
148
+ })).toEqual({
149
+ invalid: false,
150
+ valid: '2023-08-15T03:30-09:30'
151
+ });
152
+ });
153
+ it('preserves quarter-hour offset +05:45 (Nepal)', ()=>{
154
+ expect((0, _date.buildFieldValue)({
155
+ data: {
156
+ date: new Date('2023-08-15'),
157
+ time: '05:45',
158
+ ampm: 'AM',
159
+ utcOffset: '+05:45'
160
+ },
161
+ usesTimezone: true,
162
+ usesTime: true
163
+ })).toEqual({
164
+ invalid: false,
165
+ valid: '2023-08-15T05:45+05:45'
166
+ });
167
+ });
168
+ it('preserves UTC +00:00 offset', ()=>{
169
+ expect((0, _date.buildFieldValue)({
170
+ data: {
171
+ date: new Date('2023-01-01'),
172
+ time: '00:00',
173
+ ampm: 'AM',
174
+ utcOffset: '+00:00'
175
+ },
176
+ usesTimezone: true,
177
+ usesTime: true
178
+ })).toEqual({
179
+ invalid: false,
180
+ valid: '2023-01-01T00:00+00:00'
181
+ });
182
+ });
183
+ it('preserves far-west offset -12:00', ()=>{
184
+ expect((0, _date.buildFieldValue)({
185
+ data: {
186
+ date: new Date('2023-01-01'),
187
+ time: '23:59',
188
+ ampm: 'PM',
189
+ utcOffset: '-12:00'
190
+ },
191
+ usesTimezone: true,
192
+ usesTime: true
193
+ })).toEqual({
194
+ invalid: false,
195
+ valid: '2023-01-01T23:59-12:00'
196
+ });
197
+ });
198
+ it('preserves far-east offset +14:00', ()=>{
199
+ expect((0, _date.buildFieldValue)({
200
+ data: {
201
+ date: new Date('2023-01-01'),
202
+ time: '01:00',
203
+ ampm: 'AM',
204
+ utcOffset: '+14:00'
205
+ },
206
+ usesTimezone: true,
207
+ usesTime: true
208
+ })).toEqual({
209
+ invalid: false,
210
+ valid: '2023-01-01T01:00+14:00'
211
+ });
212
+ });
213
+ it('11:59 PM → 23:59', ()=>{
214
+ expect((0, _date.buildFieldValue)({
215
+ data: {
216
+ date: new Date('2023-06-01'),
217
+ time: '11:59',
218
+ ampm: 'PM',
219
+ utcOffset: '+00:00'
220
+ },
221
+ usesTimezone: true,
222
+ usesTime: true
223
+ })).toEqual({
224
+ invalid: false,
225
+ valid: '2023-06-01T23:59+00:00'
226
+ });
227
+ });
228
+ it('01:00 AM → 01:00 (no shift)', ()=>{
229
+ expect((0, _date.buildFieldValue)({
230
+ data: {
231
+ date: new Date('2023-06-01'),
232
+ time: '01:00',
233
+ ampm: 'AM',
234
+ utcOffset: '+00:00'
235
+ },
236
+ usesTimezone: true,
237
+ usesTime: true
238
+ })).toEqual({
239
+ invalid: false,
240
+ valid: '2023-06-01T01:00+00:00'
241
+ });
242
+ });
243
+ });
244
+ describe('userInputFromDatetime', ()=>{
245
+ it('parses a full ISO datetime string with timezone', ()=>{
246
+ const result = (0, _date.userInputFromDatetime)({
247
+ value: '2018-02-02T17:00+03:00',
248
+ uses12hClock: false
249
+ });
250
+ expect(result.time).toBe('17:00');
251
+ expect(result.ampm).toBe('PM');
252
+ expect(result.utcOffset).toBe('+03:00');
253
+ });
254
+ it('parses a full ISO datetime string with 12h clock', ()=>{
255
+ const result = (0, _date.userInputFromDatetime)({
256
+ value: '2018-02-02T05:00+03:00',
257
+ uses12hClock: true
258
+ });
259
+ expect(result.time).toBe('05:00');
260
+ expect(result.ampm).toBe('AM');
261
+ expect(result.utcOffset).toBe('+03:00');
262
+ });
263
+ it('returns defaults when value is null', ()=>{
264
+ const result = (0, _date.userInputFromDatetime)({
265
+ value: null,
266
+ uses12hClock: false
267
+ });
268
+ expect(result.date).toBeUndefined();
269
+ expect(result.ampm).toBe((0, _date.getDefaultAMPM)());
270
+ expect(result.utcOffset).toBe((0, _date.getDefaultUtcOffset)());
271
+ });
272
+ it('returns defaults when value is undefined', ()=>{
273
+ const result = (0, _date.userInputFromDatetime)({
274
+ value: undefined,
275
+ uses12hClock: false
276
+ });
277
+ expect(result.date).toBeUndefined();
278
+ expect(result.ampm).toBe((0, _date.getDefaultAMPM)());
279
+ });
280
+ it('returns defaults when value is empty string', ()=>{
281
+ const result = (0, _date.userInputFromDatetime)({
282
+ value: '',
283
+ uses12hClock: false
284
+ });
285
+ expect(result.date).toBeUndefined();
286
+ });
287
+ it('parses a date-only string', ()=>{
288
+ const result = (0, _date.userInputFromDatetime)({
289
+ value: '2022-09-16',
290
+ uses12hClock: false
291
+ });
292
+ expect(result.utcOffset).toBe('+00:00');
293
+ });
294
+ it('preserves raw time and does not shift by system timezone (positive offset)', ()=>{
295
+ const result = (0, _date.userInputFromDatetime)({
296
+ value: '2020-03-15T14:00+05:30',
297
+ uses12hClock: false
298
+ });
299
+ expect(result.time).toBe('14:00');
300
+ expect(result.ampm).toBe('PM');
301
+ expect(result.utcOffset).toBe('+05:30');
302
+ });
303
+ it('preserves raw time and does not shift by system timezone (negative offset)', ()=>{
304
+ const result = (0, _date.userInputFromDatetime)({
305
+ value: '2020-03-15T08:30-05:30',
306
+ uses12hClock: false
307
+ });
308
+ expect(result.time).toBe('08:30');
309
+ expect(result.ampm).toBe('AM');
310
+ expect(result.utcOffset).toBe('-05:30');
311
+ });
312
+ it('handles UTC "Z" suffix — normalizes offset to +00:00', ()=>{
313
+ const result = (0, _date.userInputFromDatetime)({
314
+ value: '2021-06-01T12:00Z',
315
+ uses12hClock: false
316
+ });
317
+ expect(result.time).toBe('12:00');
318
+ expect(result.ampm).toBe('PM');
319
+ expect(result.utcOffset).toBe('+00:00');
320
+ });
321
+ it('handles midnight UTC correctly', ()=>{
322
+ const result = (0, _date.userInputFromDatetime)({
323
+ value: '2021-06-01T00:00Z',
324
+ uses12hClock: false
325
+ });
326
+ expect(result.time).toBe('00:00');
327
+ expect(result.ampm).toBe('AM');
328
+ });
329
+ it('converts PM hour to 12h display (17:00 → 05:00 PM)', ()=>{
330
+ const result = (0, _date.userInputFromDatetime)({
331
+ value: '2018-02-02T17:00+03:00',
332
+ uses12hClock: true
333
+ });
334
+ expect(result.time).toBe('05:00');
335
+ expect(result.ampm).toBe('PM');
336
+ });
337
+ it('converts noon to 12h display (12:00 → 12:00 PM)', ()=>{
338
+ const result = (0, _date.userInputFromDatetime)({
339
+ value: '2021-03-01T12:00+00:00',
340
+ uses12hClock: true
341
+ });
342
+ expect(result.time).toBe('12:00');
343
+ expect(result.ampm).toBe('PM');
344
+ });
345
+ it('converts midnight to 12h display (00:00 → 12:00 AM)', ()=>{
346
+ const result = (0, _date.userInputFromDatetime)({
347
+ value: '2021-03-01T00:00+00:00',
348
+ uses12hClock: true
349
+ });
350
+ expect(result.time).toBe('12:00');
351
+ expect(result.ampm).toBe('AM');
352
+ });
353
+ it('handles quarter-hour offset +05:45 (Nepal)', ()=>{
354
+ const result = (0, _date.userInputFromDatetime)({
355
+ value: '2023-07-20T09:45+05:45',
356
+ uses12hClock: false
357
+ });
358
+ expect(result.time).toBe('09:45');
359
+ expect(result.utcOffset).toBe('+05:45');
360
+ });
361
+ it('handles -12:00 (far-west) offset without date shift', ()=>{
362
+ const result = (0, _date.userInputFromDatetime)({
363
+ value: '2023-01-01T23:59-12:00',
364
+ uses12hClock: false
365
+ });
366
+ expect(result.time).toBe('23:59');
367
+ expect(result.utcOffset).toBe('-12:00');
368
+ });
369
+ it('handles +14:00 (far-east) offset without date shift', ()=>{
370
+ const result = (0, _date.userInputFromDatetime)({
371
+ value: '2023-01-01T01:00+14:00',
372
+ uses12hClock: false
373
+ });
374
+ expect(result.time).toBe('01:00');
375
+ expect(result.utcOffset).toBe('+14:00');
376
+ });
377
+ });
378
+ describe('getDefaultAMPM', ()=>{
379
+ it('returns AM', ()=>{
380
+ expect((0, _date.getDefaultAMPM)()).toBe('AM');
381
+ });
55
382
  });
56
383
  });
@@ -22,32 +22,37 @@ _export(exports, {
22
22
  return userInputFromDatetime;
23
23
  }
24
24
  });
25
- const _moment = /*#__PURE__*/ _interop_require_default(require("moment"));
26
- function _interop_require_default(obj) {
27
- return obj && obj.__esModule ? obj : {
28
- default: obj
29
- };
30
- }
25
+ const _datefns = require("date-fns");
31
26
  const ZONE_RX = /(Z|[+-]\d{2}[:+]?\d{2})$/;
32
- function startOfToday(format) {
33
- return (0, _moment.default)().set({
34
- hours: 0,
35
- minutes: 0
36
- }).format(format);
27
+ function startOfTodayOffset() {
28
+ return (0, _datefns.format)(new Date(), 'xxx');
29
+ }
30
+ function parseUtcOffset(datetimeString) {
31
+ const match = datetimeString.match(ZONE_RX);
32
+ if (!match) return '+00:00';
33
+ return match[1] === 'Z' ? '+00:00' : match[1];
37
34
  }
38
- function fieldValueToMoment(datetimeString) {
35
+ function fieldValueToDate(datetimeString) {
39
36
  if (!datetimeString) {
40
37
  return null;
41
38
  }
42
- const datetime = (0, _moment.default)(datetimeString);
43
- if (ZONE_RX.test(datetimeString)) {
44
- datetime.utcOffset(datetimeString);
45
- }
46
- return datetime;
39
+ const date = (0, _datefns.parseISO)(datetimeString);
40
+ return (0, _datefns.isValid)(date) ? date : null;
47
41
  }
48
42
  function timeFromUserInput(input) {
49
43
  const timeInput = input.time || '00:00';
50
- return _moment.default.utc(timeInput + '!' + input.ampm, 'HH:mm!A');
44
+ const parsed = (0, _datefns.parse)(timeInput, 'HH:mm', new Date(0));
45
+ let hours = (0, _datefns.getHours)(parsed);
46
+ const minutes = (0, _datefns.getMinutes)(parsed);
47
+ if (input.ampm === 'PM' && hours < 12) {
48
+ hours += 12;
49
+ } else if (input.ampm === 'AM' && hours === 12) {
50
+ hours = 0;
51
+ }
52
+ return {
53
+ hours,
54
+ minutes
55
+ };
51
56
  }
52
57
  function datetimeFromUserInput(input) {
53
58
  if (!input.date) {
@@ -55,12 +60,14 @@ function datetimeFromUserInput(input) {
55
60
  valid: null
56
61
  };
57
62
  }
58
- const time = timeFromUserInput(input);
59
- const date = _moment.default.parseZone(input.utcOffset, 'Z').set(input.date.toObject()).set({
60
- hours: time.hours(),
61
- minutes: time.minutes()
63
+ const { hours, minutes } = timeFromUserInput(input);
64
+ const date = (0, _datefns.set)(input.date, {
65
+ hours,
66
+ minutes,
67
+ seconds: 0,
68
+ milliseconds: 0
62
69
  });
63
- if (date.isValid()) {
70
+ if ((0, _datefns.isValid)(date)) {
64
71
  return {
65
72
  valid: date
66
73
  };
@@ -78,34 +85,58 @@ function buildFieldValue({ data, usesTime, usesTimezone }) {
78
85
  invalid: true
79
86
  };
80
87
  }
81
- let format;
88
+ if (!date.valid) {
89
+ return {
90
+ valid: null,
91
+ invalid: false
92
+ };
93
+ }
82
94
  if (usesTimezone) {
83
- format = 'YYYY-MM-DDTHH:mmZ';
95
+ return {
96
+ valid: (0, _datefns.format)(date.valid, "yyyy-MM-dd'T'HH:mm") + data.utcOffset,
97
+ invalid: false
98
+ };
84
99
  } else if (usesTime) {
85
- format = 'YYYY-MM-DDTHH:mm';
100
+ return {
101
+ valid: (0, _datefns.format)(date.valid, "yyyy-MM-dd'T'HH:mm"),
102
+ invalid: false
103
+ };
86
104
  } else {
87
- format = 'YYYY-MM-DD';
105
+ return {
106
+ valid: (0, _datefns.format)(date.valid, 'yyyy-MM-dd'),
107
+ invalid: false
108
+ };
88
109
  }
89
- return {
90
- valid: date?.valid ? date.valid.format(format) : null,
91
- invalid: false
92
- };
93
110
  }
94
111
  function getDefaultAMPM() {
95
112
  return 'AM';
96
113
  }
97
114
  function getDefaultUtcOffset() {
98
- return startOfToday('Z');
115
+ return startOfTodayOffset();
116
+ }
117
+ function extractTimeFromIso(value) {
118
+ const match = value.match(/T(\d{2}:\d{2})/);
119
+ return match ? match[1] : undefined;
99
120
  }
100
121
  function userInputFromDatetime({ value, uses12hClock }) {
101
- const datetime = fieldValueToMoment(value);
102
- if (datetime) {
103
- const timeFormat = uses12hClock ? 'hh:mm' : 'HH:mm';
122
+ const datetime = fieldValueToDate(value);
123
+ if (datetime && value) {
124
+ const rawTime = extractTimeFromIso(value);
125
+ const timeDate = rawTime ? (0, _datefns.parse)(rawTime, 'HH:mm', new Date(0)) : datetime;
126
+ const hours = (0, _datefns.getHours)(timeDate);
127
+ const ampm = hours < 12 ? 'AM' : 'PM';
128
+ let time;
129
+ if (uses12hClock) {
130
+ const h12 = hours % 12 || 12;
131
+ time = `${String(h12).padStart(2, '0')}:${String((0, _datefns.getMinutes)(timeDate)).padStart(2, '0')}`;
132
+ } else {
133
+ time = rawTime ?? (0, _datefns.format)(datetime, 'HH:mm');
134
+ }
104
135
  return {
105
136
  date: datetime,
106
- time: datetime.format(timeFormat),
107
- ampm: datetime.format('A'),
108
- utcOffset: datetime.format('Z')
137
+ time,
138
+ ampm,
139
+ utcOffset: parseUtcOffset(value)
109
140
  };
110
141
  } else {
111
142
  return {
@@ -1,7 +1,6 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import { Datepicker } from '@contentful/f36-components';
3
3
  import { css } from '@emotion/css';
4
- import moment from 'moment';
5
4
  const YEARS_INTO_FUTURE = 100;
6
5
  const MIN_YEAR = '1000';
7
6
  const styles = {
@@ -19,14 +18,12 @@ export const DatepickerInput = (props)=>{
19
18
  toDate
20
19
  ];
21
20
  }, []);
22
- const dateObj = props.value?.toObject();
23
- const selectedDate = dateObj ? new Date(dateObj.years, dateObj.months, dateObj.date) : undefined;
21
+ const selectedDate = props.value;
24
22
  return /*#__PURE__*/ React.createElement(Datepicker, {
25
23
  className: styles.root,
26
24
  selected: selectedDate,
27
25
  onSelect: (day)=>{
28
- const momentDay = day ? moment(day) : undefined;
29
- props.onChange(momentDay);
26
+ props.onChange(day ?? undefined);
30
27
  },
31
28
  inputProps: {
32
29
  isDisabled: props.disabled,
@@ -1,44 +1,34 @@
1
1
  import React, { useState, useCallback, useEffect } from 'react';
2
2
  import { TextInput, Flex } from '@contentful/f36-components';
3
3
  import { css } from '@emotion/css';
4
- import moment from 'moment';
4
+ import { parse, format, isValid } from 'date-fns';
5
5
  const validInputFormats = [
6
6
  'hh:mm a',
7
- 'hh:mm A',
8
7
  'h:mm a',
9
- 'h:mm A',
10
8
  'hh:mm',
11
- 'k:mm',
12
9
  'kk:mm',
10
+ 'k:mm',
13
11
  'h a',
14
- 'h A',
15
- 'h',
16
- 'hh',
17
- 'HH'
12
+ 'HH',
13
+ 'H:mm',
14
+ 'h'
18
15
  ];
16
+ const REF_DATE = new Date(2000, 0, 1);
19
17
  function parseRawInput(raw) {
20
- let time = null;
21
- for(let i = 0; i < validInputFormats.length; i++){
22
- const date = moment(raw, validInputFormats[i]);
23
- if (date.isValid()) {
24
- time = date;
25
- break;
26
- }
18
+ for (const fmt of validInputFormats){
19
+ const parsed = parse(raw, fmt, REF_DATE);
20
+ if (isValid(parsed)) return parsed;
27
21
  }
28
- return time;
22
+ return null;
29
23
  }
30
- const getDefaultTime = ()=>{
31
- return moment(`12:00 AM`, 'hh:mm A');
32
- };
33
- const formatToString = (uses12hClock, value)=>{
34
- return uses12hClock ? value.format('hh:mm A') : value.format('HH:mm');
35
- };
24
+ const getDefaultTime = ()=>parse('12:00 AM', 'hh:mm a', REF_DATE);
25
+ const formatToString = (uses12hClock, value)=>format(value, uses12hClock ? 'hh:mm a' : 'HH:mm');
36
26
  export const TimepickerInput = ({ disabled, uses12hClock, time = '12:00', ampm = 'AM', onChange })=>{
37
27
  const [selectedTime, setSelectedTime] = useState(()=>{
38
28
  return formatToString(uses12hClock, getDefaultTime());
39
29
  });
40
30
  useEffect(()=>{
41
- setSelectedTime(formatToString(uses12hClock, moment(`${time} ${ampm}`, 'hh:mm A')));
31
+ setSelectedTime(formatToString(uses12hClock, parse(`${time} ${ampm}`, 'hh:mm a', REF_DATE)));
42
32
  }, [
43
33
  time,
44
34
  ampm,
@@ -50,8 +40,8 @@ export const TimepickerInput = ({ disabled, uses12hClock, time = '12:00', ampm =
50
40
  const parsedTime = parseRawInput(raw);
51
41
  if (parsedTime) {
52
42
  onChange({
53
- time: parsedTime.format('hh:mm'),
54
- ampm: parsedTime.format('A')
43
+ time: format(parsedTime, 'hh:mm'),
44
+ ampm: format(parsedTime, 'a').toUpperCase()
55
45
  });
56
46
  }
57
47
  }, [
@@ -66,8 +56,8 @@ export const TimepickerInput = ({ disabled, uses12hClock, time = '12:00', ampm =
66
56
  const value = parsedTime ?? getDefaultTime();
67
57
  setSelectedTime(formatToString(uses12hClock, value));
68
58
  onChange({
69
- time: value.format('hh:mm'),
70
- ampm: value.format('A')
59
+ time: format(value, 'hh:mm'),
60
+ ampm: format(value, 'a').toUpperCase()
71
61
  });
72
62
  }, [
73
63
  selectedTime,
@@ -1,11 +1,10 @@
1
- import moment from 'moment';
2
- import { buildFieldValue } from './date';
1
+ import { buildFieldValue, userInputFromDatetime, getDefaultAMPM, getDefaultUtcOffset } from './date';
3
2
  describe('date utils', ()=>{
4
3
  describe('buildFieldValue', ()=>{
5
4
  it('should work properly', ()=>{
6
5
  expect(buildFieldValue({
7
6
  data: {
8
- date: moment('2018-02-02'),
7
+ date: new Date('2018-02-02'),
9
8
  time: '05:00',
10
9
  ampm: 'PM',
11
10
  utcOffset: '+03:00'
@@ -18,7 +17,7 @@ describe('date utils', ()=>{
18
17
  });
19
18
  expect(buildFieldValue({
20
19
  data: {
21
- date: moment('2015-01-14'),
20
+ date: new Date('2015-01-14'),
22
21
  time: '05:00',
23
22
  ampm: 'AM',
24
23
  utcOffset: '-05:00'
@@ -31,7 +30,7 @@ describe('date utils', ()=>{
31
30
  });
32
31
  expect(buildFieldValue({
33
32
  data: {
34
- date: moment('2015-01-14'),
33
+ date: new Date('2015-01-14'),
35
34
  time: '17:00',
36
35
  ampm: 'PM',
37
36
  utcOffset: '-05:00'
@@ -43,5 +42,338 @@ describe('date utils', ()=>{
43
42
  valid: '2015-01-14T17:00-05:00'
44
43
  });
45
44
  });
45
+ it('returns date-only format when usesTime and usesTimezone are false', ()=>{
46
+ expect(buildFieldValue({
47
+ data: {
48
+ date: new Date('2020-06-15'),
49
+ time: '10:30',
50
+ ampm: 'AM',
51
+ utcOffset: '+00:00'
52
+ },
53
+ usesTimezone: false,
54
+ usesTime: false
55
+ })).toEqual({
56
+ invalid: false,
57
+ valid: '2020-06-15'
58
+ });
59
+ });
60
+ it('returns datetime without timezone when usesTime=true, usesTimezone=false', ()=>{
61
+ expect(buildFieldValue({
62
+ data: {
63
+ date: new Date('2020-06-15'),
64
+ time: '14:30',
65
+ ampm: 'PM',
66
+ utcOffset: '+00:00'
67
+ },
68
+ usesTimezone: false,
69
+ usesTime: true
70
+ })).toEqual({
71
+ invalid: false,
72
+ valid: '2020-06-15T14:30'
73
+ });
74
+ });
75
+ it('returns valid: null when no date is provided', ()=>{
76
+ expect(buildFieldValue({
77
+ data: {
78
+ time: '10:00',
79
+ ampm: 'AM',
80
+ utcOffset: '+00:00'
81
+ },
82
+ usesTimezone: true,
83
+ usesTime: true
84
+ })).toEqual({
85
+ invalid: false,
86
+ valid: null
87
+ });
88
+ });
89
+ it('handles midnight (12:00 AM) correctly', ()=>{
90
+ expect(buildFieldValue({
91
+ data: {
92
+ date: new Date('2021-03-01'),
93
+ time: '12:00',
94
+ ampm: 'AM',
95
+ utcOffset: '+00:00'
96
+ },
97
+ usesTimezone: true,
98
+ usesTime: true
99
+ })).toEqual({
100
+ invalid: false,
101
+ valid: '2021-03-01T00:00+00:00'
102
+ });
103
+ });
104
+ it('handles noon (12:00 PM) correctly', ()=>{
105
+ expect(buildFieldValue({
106
+ data: {
107
+ date: new Date('2021-03-01'),
108
+ time: '12:00',
109
+ ampm: 'PM',
110
+ utcOffset: '+00:00'
111
+ },
112
+ usesTimezone: true,
113
+ usesTime: true
114
+ })).toEqual({
115
+ invalid: false,
116
+ valid: '2021-03-01T12:00+00:00'
117
+ });
118
+ });
119
+ it('preserves half-hour offset +05:30 (India)', ()=>{
120
+ expect(buildFieldValue({
121
+ data: {
122
+ date: new Date('2023-08-15'),
123
+ time: '10:00',
124
+ ampm: 'AM',
125
+ utcOffset: '+05:30'
126
+ },
127
+ usesTimezone: true,
128
+ usesTime: true
129
+ })).toEqual({
130
+ invalid: false,
131
+ valid: '2023-08-15T10:00+05:30'
132
+ });
133
+ });
134
+ it('preserves negative half-hour offset -09:30', ()=>{
135
+ expect(buildFieldValue({
136
+ data: {
137
+ date: new Date('2023-08-15'),
138
+ time: '03:30',
139
+ ampm: 'AM',
140
+ utcOffset: '-09:30'
141
+ },
142
+ usesTimezone: true,
143
+ usesTime: true
144
+ })).toEqual({
145
+ invalid: false,
146
+ valid: '2023-08-15T03:30-09:30'
147
+ });
148
+ });
149
+ it('preserves quarter-hour offset +05:45 (Nepal)', ()=>{
150
+ expect(buildFieldValue({
151
+ data: {
152
+ date: new Date('2023-08-15'),
153
+ time: '05:45',
154
+ ampm: 'AM',
155
+ utcOffset: '+05:45'
156
+ },
157
+ usesTimezone: true,
158
+ usesTime: true
159
+ })).toEqual({
160
+ invalid: false,
161
+ valid: '2023-08-15T05:45+05:45'
162
+ });
163
+ });
164
+ it('preserves UTC +00:00 offset', ()=>{
165
+ expect(buildFieldValue({
166
+ data: {
167
+ date: new Date('2023-01-01'),
168
+ time: '00:00',
169
+ ampm: 'AM',
170
+ utcOffset: '+00:00'
171
+ },
172
+ usesTimezone: true,
173
+ usesTime: true
174
+ })).toEqual({
175
+ invalid: false,
176
+ valid: '2023-01-01T00:00+00:00'
177
+ });
178
+ });
179
+ it('preserves far-west offset -12:00', ()=>{
180
+ expect(buildFieldValue({
181
+ data: {
182
+ date: new Date('2023-01-01'),
183
+ time: '23:59',
184
+ ampm: 'PM',
185
+ utcOffset: '-12:00'
186
+ },
187
+ usesTimezone: true,
188
+ usesTime: true
189
+ })).toEqual({
190
+ invalid: false,
191
+ valid: '2023-01-01T23:59-12:00'
192
+ });
193
+ });
194
+ it('preserves far-east offset +14:00', ()=>{
195
+ expect(buildFieldValue({
196
+ data: {
197
+ date: new Date('2023-01-01'),
198
+ time: '01:00',
199
+ ampm: 'AM',
200
+ utcOffset: '+14:00'
201
+ },
202
+ usesTimezone: true,
203
+ usesTime: true
204
+ })).toEqual({
205
+ invalid: false,
206
+ valid: '2023-01-01T01:00+14:00'
207
+ });
208
+ });
209
+ it('11:59 PM → 23:59', ()=>{
210
+ expect(buildFieldValue({
211
+ data: {
212
+ date: new Date('2023-06-01'),
213
+ time: '11:59',
214
+ ampm: 'PM',
215
+ utcOffset: '+00:00'
216
+ },
217
+ usesTimezone: true,
218
+ usesTime: true
219
+ })).toEqual({
220
+ invalid: false,
221
+ valid: '2023-06-01T23:59+00:00'
222
+ });
223
+ });
224
+ it('01:00 AM → 01:00 (no shift)', ()=>{
225
+ expect(buildFieldValue({
226
+ data: {
227
+ date: new Date('2023-06-01'),
228
+ time: '01:00',
229
+ ampm: 'AM',
230
+ utcOffset: '+00:00'
231
+ },
232
+ usesTimezone: true,
233
+ usesTime: true
234
+ })).toEqual({
235
+ invalid: false,
236
+ valid: '2023-06-01T01:00+00:00'
237
+ });
238
+ });
239
+ });
240
+ describe('userInputFromDatetime', ()=>{
241
+ it('parses a full ISO datetime string with timezone', ()=>{
242
+ const result = userInputFromDatetime({
243
+ value: '2018-02-02T17:00+03:00',
244
+ uses12hClock: false
245
+ });
246
+ expect(result.time).toBe('17:00');
247
+ expect(result.ampm).toBe('PM');
248
+ expect(result.utcOffset).toBe('+03:00');
249
+ });
250
+ it('parses a full ISO datetime string with 12h clock', ()=>{
251
+ const result = userInputFromDatetime({
252
+ value: '2018-02-02T05:00+03:00',
253
+ uses12hClock: true
254
+ });
255
+ expect(result.time).toBe('05:00');
256
+ expect(result.ampm).toBe('AM');
257
+ expect(result.utcOffset).toBe('+03:00');
258
+ });
259
+ it('returns defaults when value is null', ()=>{
260
+ const result = userInputFromDatetime({
261
+ value: null,
262
+ uses12hClock: false
263
+ });
264
+ expect(result.date).toBeUndefined();
265
+ expect(result.ampm).toBe(getDefaultAMPM());
266
+ expect(result.utcOffset).toBe(getDefaultUtcOffset());
267
+ });
268
+ it('returns defaults when value is undefined', ()=>{
269
+ const result = userInputFromDatetime({
270
+ value: undefined,
271
+ uses12hClock: false
272
+ });
273
+ expect(result.date).toBeUndefined();
274
+ expect(result.ampm).toBe(getDefaultAMPM());
275
+ });
276
+ it('returns defaults when value is empty string', ()=>{
277
+ const result = userInputFromDatetime({
278
+ value: '',
279
+ uses12hClock: false
280
+ });
281
+ expect(result.date).toBeUndefined();
282
+ });
283
+ it('parses a date-only string', ()=>{
284
+ const result = userInputFromDatetime({
285
+ value: '2022-09-16',
286
+ uses12hClock: false
287
+ });
288
+ expect(result.utcOffset).toBe('+00:00');
289
+ });
290
+ it('preserves raw time and does not shift by system timezone (positive offset)', ()=>{
291
+ const result = userInputFromDatetime({
292
+ value: '2020-03-15T14:00+05:30',
293
+ uses12hClock: false
294
+ });
295
+ expect(result.time).toBe('14:00');
296
+ expect(result.ampm).toBe('PM');
297
+ expect(result.utcOffset).toBe('+05:30');
298
+ });
299
+ it('preserves raw time and does not shift by system timezone (negative offset)', ()=>{
300
+ const result = userInputFromDatetime({
301
+ value: '2020-03-15T08:30-05:30',
302
+ uses12hClock: false
303
+ });
304
+ expect(result.time).toBe('08:30');
305
+ expect(result.ampm).toBe('AM');
306
+ expect(result.utcOffset).toBe('-05:30');
307
+ });
308
+ it('handles UTC "Z" suffix — normalizes offset to +00:00', ()=>{
309
+ const result = userInputFromDatetime({
310
+ value: '2021-06-01T12:00Z',
311
+ uses12hClock: false
312
+ });
313
+ expect(result.time).toBe('12:00');
314
+ expect(result.ampm).toBe('PM');
315
+ expect(result.utcOffset).toBe('+00:00');
316
+ });
317
+ it('handles midnight UTC correctly', ()=>{
318
+ const result = userInputFromDatetime({
319
+ value: '2021-06-01T00:00Z',
320
+ uses12hClock: false
321
+ });
322
+ expect(result.time).toBe('00:00');
323
+ expect(result.ampm).toBe('AM');
324
+ });
325
+ it('converts PM hour to 12h display (17:00 → 05:00 PM)', ()=>{
326
+ const result = userInputFromDatetime({
327
+ value: '2018-02-02T17:00+03:00',
328
+ uses12hClock: true
329
+ });
330
+ expect(result.time).toBe('05:00');
331
+ expect(result.ampm).toBe('PM');
332
+ });
333
+ it('converts noon to 12h display (12:00 → 12:00 PM)', ()=>{
334
+ const result = userInputFromDatetime({
335
+ value: '2021-03-01T12:00+00:00',
336
+ uses12hClock: true
337
+ });
338
+ expect(result.time).toBe('12:00');
339
+ expect(result.ampm).toBe('PM');
340
+ });
341
+ it('converts midnight to 12h display (00:00 → 12:00 AM)', ()=>{
342
+ const result = userInputFromDatetime({
343
+ value: '2021-03-01T00:00+00:00',
344
+ uses12hClock: true
345
+ });
346
+ expect(result.time).toBe('12:00');
347
+ expect(result.ampm).toBe('AM');
348
+ });
349
+ it('handles quarter-hour offset +05:45 (Nepal)', ()=>{
350
+ const result = userInputFromDatetime({
351
+ value: '2023-07-20T09:45+05:45',
352
+ uses12hClock: false
353
+ });
354
+ expect(result.time).toBe('09:45');
355
+ expect(result.utcOffset).toBe('+05:45');
356
+ });
357
+ it('handles -12:00 (far-west) offset without date shift', ()=>{
358
+ const result = userInputFromDatetime({
359
+ value: '2023-01-01T23:59-12:00',
360
+ uses12hClock: false
361
+ });
362
+ expect(result.time).toBe('23:59');
363
+ expect(result.utcOffset).toBe('-12:00');
364
+ });
365
+ it('handles +14:00 (far-east) offset without date shift', ()=>{
366
+ const result = userInputFromDatetime({
367
+ value: '2023-01-01T01:00+14:00',
368
+ uses12hClock: false
369
+ });
370
+ expect(result.time).toBe('01:00');
371
+ expect(result.utcOffset).toBe('+14:00');
372
+ });
373
+ });
374
+ describe('getDefaultAMPM', ()=>{
375
+ it('returns AM', ()=>{
376
+ expect(getDefaultAMPM()).toBe('AM');
377
+ });
46
378
  });
47
379
  });
@@ -1,24 +1,34 @@
1
- import moment from 'moment';
1
+ import { format, getHours, getMinutes, isValid, parse, parseISO, set } from 'date-fns';
2
2
  const ZONE_RX = /(Z|[+-]\d{2}[:+]?\d{2})$/;
3
- function startOfToday(format) {
4
- return moment().set({
5
- hours: 0,
6
- minutes: 0
7
- }).format(format);
3
+ function startOfTodayOffset() {
4
+ return format(new Date(), 'xxx');
8
5
  }
9
- function fieldValueToMoment(datetimeString) {
6
+ function parseUtcOffset(datetimeString) {
7
+ const match = datetimeString.match(ZONE_RX);
8
+ if (!match) return '+00:00';
9
+ return match[1] === 'Z' ? '+00:00' : match[1];
10
+ }
11
+ function fieldValueToDate(datetimeString) {
10
12
  if (!datetimeString) {
11
13
  return null;
12
14
  }
13
- const datetime = moment(datetimeString);
14
- if (ZONE_RX.test(datetimeString)) {
15
- datetime.utcOffset(datetimeString);
16
- }
17
- return datetime;
15
+ const date = parseISO(datetimeString);
16
+ return isValid(date) ? date : null;
18
17
  }
19
18
  function timeFromUserInput(input) {
20
19
  const timeInput = input.time || '00:00';
21
- return moment.utc(timeInput + '!' + input.ampm, 'HH:mm!A');
20
+ const parsed = parse(timeInput, 'HH:mm', new Date(0));
21
+ let hours = getHours(parsed);
22
+ const minutes = getMinutes(parsed);
23
+ if (input.ampm === 'PM' && hours < 12) {
24
+ hours += 12;
25
+ } else if (input.ampm === 'AM' && hours === 12) {
26
+ hours = 0;
27
+ }
28
+ return {
29
+ hours,
30
+ minutes
31
+ };
22
32
  }
23
33
  function datetimeFromUserInput(input) {
24
34
  if (!input.date) {
@@ -26,12 +36,14 @@ function datetimeFromUserInput(input) {
26
36
  valid: null
27
37
  };
28
38
  }
29
- const time = timeFromUserInput(input);
30
- const date = moment.parseZone(input.utcOffset, 'Z').set(input.date.toObject()).set({
31
- hours: time.hours(),
32
- minutes: time.minutes()
39
+ const { hours, minutes } = timeFromUserInput(input);
40
+ const date = set(input.date, {
41
+ hours,
42
+ minutes,
43
+ seconds: 0,
44
+ milliseconds: 0
33
45
  });
34
- if (date.isValid()) {
46
+ if (isValid(date)) {
35
47
  return {
36
48
  valid: date
37
49
  };
@@ -49,34 +61,58 @@ export function buildFieldValue({ data, usesTime, usesTimezone }) {
49
61
  invalid: true
50
62
  };
51
63
  }
52
- let format;
64
+ if (!date.valid) {
65
+ return {
66
+ valid: null,
67
+ invalid: false
68
+ };
69
+ }
53
70
  if (usesTimezone) {
54
- format = 'YYYY-MM-DDTHH:mmZ';
71
+ return {
72
+ valid: format(date.valid, "yyyy-MM-dd'T'HH:mm") + data.utcOffset,
73
+ invalid: false
74
+ };
55
75
  } else if (usesTime) {
56
- format = 'YYYY-MM-DDTHH:mm';
76
+ return {
77
+ valid: format(date.valid, "yyyy-MM-dd'T'HH:mm"),
78
+ invalid: false
79
+ };
57
80
  } else {
58
- format = 'YYYY-MM-DD';
81
+ return {
82
+ valid: format(date.valid, 'yyyy-MM-dd'),
83
+ invalid: false
84
+ };
59
85
  }
60
- return {
61
- valid: date?.valid ? date.valid.format(format) : null,
62
- invalid: false
63
- };
64
86
  }
65
87
  export function getDefaultAMPM() {
66
88
  return 'AM';
67
89
  }
68
90
  export function getDefaultUtcOffset() {
69
- return startOfToday('Z');
91
+ return startOfTodayOffset();
92
+ }
93
+ function extractTimeFromIso(value) {
94
+ const match = value.match(/T(\d{2}:\d{2})/);
95
+ return match ? match[1] : undefined;
70
96
  }
71
97
  export function userInputFromDatetime({ value, uses12hClock }) {
72
- const datetime = fieldValueToMoment(value);
73
- if (datetime) {
74
- const timeFormat = uses12hClock ? 'hh:mm' : 'HH:mm';
98
+ const datetime = fieldValueToDate(value);
99
+ if (datetime && value) {
100
+ const rawTime = extractTimeFromIso(value);
101
+ const timeDate = rawTime ? parse(rawTime, 'HH:mm', new Date(0)) : datetime;
102
+ const hours = getHours(timeDate);
103
+ const ampm = hours < 12 ? 'AM' : 'PM';
104
+ let time;
105
+ if (uses12hClock) {
106
+ const h12 = hours % 12 || 12;
107
+ time = `${String(h12).padStart(2, '0')}:${String(getMinutes(timeDate)).padStart(2, '0')}`;
108
+ } else {
109
+ time = rawTime ?? format(datetime, 'HH:mm');
110
+ }
75
111
  return {
76
112
  date: datetime,
77
- time: datetime.format(timeFormat),
78
- ampm: datetime.format('A'),
79
- utcOffset: datetime.format('Z')
113
+ time,
114
+ ampm,
115
+ utcOffset: parseUtcOffset(value)
80
116
  };
81
117
  } else {
82
118
  return {
@@ -1,8 +1,7 @@
1
1
  import React from 'react';
2
- import moment from 'moment';
3
2
  export type DatePickerProps = {
4
- value?: moment.Moment;
5
- onChange: (val: moment.Moment | undefined) => void;
3
+ value?: Date;
4
+ onChange: (val: Date | undefined) => void;
6
5
  disabled?: boolean;
7
6
  };
8
7
  export declare const DatepickerInput: (props: DatePickerProps) => React.JSX.Element;
@@ -1,8 +1,7 @@
1
- import moment from 'moment';
2
1
  export type DateTimeFormat = 'dateonly' | 'time' | 'timeZ';
3
2
  export type TimeFormat = '12' | '24';
4
3
  export type TimeResult = {
5
- date?: moment.Moment;
4
+ date?: Date;
6
5
  time?: string;
7
6
  ampm: string;
8
7
  utcOffset: string;
@@ -13,7 +13,10 @@ export declare function buildFieldValue({ data, usesTime, usesTimezone, }: {
13
13
  invalid: boolean;
14
14
  valid?: undefined;
15
15
  } | {
16
- valid: string | null;
16
+ valid: null;
17
+ invalid: boolean;
18
+ } | {
19
+ valid: string;
17
20
  invalid: boolean;
18
21
  };
19
22
  export declare function getDefaultAMPM(): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/field-editor-date",
3
- "version": "2.0.8",
3
+ "version": "2.0.10-canary.2+3e8a82c8",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -39,13 +39,13 @@
39
39
  "dependencies": {
40
40
  "@contentful/f36-components": "^6.7.1",
41
41
  "@contentful/f36-tokens": "^6.1.2",
42
- "@contentful/field-editor-shared": "^3.1.4",
42
+ "@contentful/field-editor-shared": "^4.0.0",
43
43
  "@emotion/css": "^11.13.5",
44
- "moment": "^2.20.0"
44
+ "date-fns": "^2.30.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@babel/core": "^7.7.4",
48
- "@contentful/field-editor-test-utils": "^2.0.1",
48
+ "@contentful/field-editor-test-utils": "^3.0.0",
49
49
  "@lingui/core": "5.3.0",
50
50
  "@types/timezoned-date": "^3.0.0",
51
51
  "timezoned-date": "^3.0.2"
@@ -57,5 +57,5 @@
57
57
  "publishConfig": {
58
58
  "registry": "https://npm.pkg.github.com/"
59
59
  },
60
- "gitHead": "d4f28439b71dc035df4efd4fde6284e46961e4fd"
60
+ "gitHead": "3e8a82c8de70258d243f76d17b59ed6a2a315946"
61
61
  }