@contentful/field-editor-date 1.3.4 → 1.4.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.
- package/CHANGELOG.md +12 -0
- package/dist/field-editor-date.cjs.development.js +124 -158
- package/dist/field-editor-date.cjs.development.js.map +1 -1
- package/dist/field-editor-date.cjs.production.min.js +1 -1
- package/dist/field-editor-date.cjs.production.min.js.map +1 -1
- package/dist/field-editor-date.esm.js +124 -158
- package/dist/field-editor-date.esm.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),
|
|
1
|
+
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),a=e(t),n=require("@contentful/f36-components"),l=e(require("@contentful/f36-tokens")),s=require("@contentful/field-editor-shared"),i=require("emotion"),r=e(require("moment"));const o={root:i.css({maxWidth:"270px"})},m=e=>{var l;const[s,i]=t.useMemo(()=>{const e=new Date;e.setFullYear(e.getFullYear()-100);const t=new Date;return t.setFullYear(t.getFullYear()+100),[e,t]},[]),m=null==(l=e.value)?void 0:l.toObject(),u=m?new Date(m.years,m.months,m.date):void 0;return a.createElement(n.Datepicker,{className:o.root,selected:u,onSelect:t=>{const a=t?r(t):void 0;e.onChange(a)},inputProps:{isDisabled:e.disabled,placeholder:""},fromDate:s,toDate:i})},u=["hh:mm a","hh:mm A","h:mm a","h:mm A","hh:mm","k:mm","kk:mm","h a","h A","h","hh","HH"],c=()=>r("12:00 AM","hh:mm A"),d=(e,t)=>t.format(e?"hh:mm A":"HH:mm"),f=({disabled:e,uses12hClock:l,time:s="12:00",ampm:o="AM",onChange:m})=>{const[f,h]=t.useState(()=>d(l,c()));t.useEffect(()=>{h(d(l,r(`${s} ${o}`,"hh:mm A")))},[s,o,l]);const v=t.useCallback(e=>{h(e.currentTarget.value)},[]),p=t.useCallback(e=>{e.preventDefault(),e.target.select()},[]);return a.createElement(n.Flex,{className:i.css({width:"145px"})},a.createElement(n.TextInput,{"aria-label":"Select time",placeholder:l?"12:00 AM":"00:00","date-time-type":l?"12":"24",testId:"time-input",value:f,isDisabled:e,onFocus:p,onBlur:()=>{const e=function(e){let t=null;for(let a=0;a<u.length;a++){const n=r(e,u[a]);if(n.isValid()){t=n;break}}return t}(f)??c();h(d(l,e)),m({time:e.format("hh:mm"),ampm:e.format("A")})},onChange:v}))},h=["-12:00","-11:00","-10:00","-09:30","-09:00","-08:00","-07:00","-06:00","-05:00","-04:30","-04:00","-03:30","-03:00","-02:00","-01:00","+00:00","+01:00","+02:00","+03:00","+03:30","+04:00","+04:30","+05:00","+05:30","+05:45","+06:00","+06:30","+07:00","+08:00","+08:45","+09:00","+09:30","+10:00","+10:30","+11:00","+11:30","+12:00","+12:45","+13:00","+14:00"],v=({disabled:e,onChange:t,value:l="+00:00"})=>a.createElement(n.Select,{"aria-label":"Select timezone",testId:"timezone-input",value:l,isDisabled:e,onChange:e=>{t(e.currentTarget.value)}},h.map(e=>a.createElement(n.Select.Option,{key:e,value:e},"UTC",e))),p=/(Z|[+-]\d{2}[:+]?\d{2})$/;function b(){return r().set({hours:0,minutes:0}).format("Z")}const C={root:i.css({display:"flex",alignItems:"center"}),separator:i.css({marginLeft:l.spacingM})};function D({initialValue:e,usesTime:a,usesTimezone:l,uses12hClock:s,disabled:i,hasClear:r,onChange:o}){const[u,c]=t.useState(()=>e);return function(e,a){const n=t.useRef(!0);t.useEffect(()=>{n.current?n.current=!1:o(u)},a)}(0,[u]),t.createElement("div",{"data-test-id":"date-editor",className:C.root},t.createElement(m,{disabled:i,value:u.date,onChange:e=>{c(t=>({...t,date:e}))}}),a&&t.createElement(t.Fragment,null,t.createElement("div",{className:C.separator}),t.createElement(f,{disabled:i,time:u.time,ampm:u.ampm,onChange:({time:e,ampm:t})=>{c(a=>({...a,time:e,ampm:t}))},uses12hClock:s})),l&&t.createElement(t.Fragment,null,t.createElement("div",{className:C.separator}),t.createElement(v,{disabled:i,value:u.utcOffset,onChange:e=>{c(t=>({...t,utcOffset:e}))}})),r&&t.createElement(t.Fragment,null,t.createElement("div",{className:C.separator}),t.createElement(n.TextLink,{as:"button",isDisabled:i,testId:"date-clear",onClick:()=>{c({date:void 0,time:void 0,ampm:"AM",utcOffset:b()})}},"Clear")))}function g(e){var a,n;const{field:l,parameters:i}=e,o=(null==i||null==(a=i.instance)?void 0:a.format)??"timeZ",m=(null==i||null==(n=i.instance)?void 0:n.ampm)??"24",u="dateonly"!==o,c="timeZ"===o,d="12"===m;return t.createElement(s.FieldConnector,{field:l,isInitiallyDisabled:e.isInitiallyDisabled,isDisabled:e.isDisabled,throttle:0},({value:e,disabled:a,setValue:n,externalReset:l})=>{const s=function({value:e,uses12hClock:t}){const a=function(e){if(!e)return null;const t=r(e);return p.test(e)&&t.utcOffset(e),t}(e);return a?{date:a,time:a.format(t?"hh:mm":"HH:mm"),ampm:a.format("A"),utcOffset:a.format("Z")}:{ampm:"AM",utcOffset:b()}}({value:e,uses12hClock:d});return t.createElement(D,{initialValue:s,uses12hClock:d,usesTimezone:c,usesTime:u,disabled:a,hasClear:Boolean(e),onChange:t=>{const a=function({data:e,usesTime:t,usesTimezone:a}){const n=function(e){if(!e.date)return{valid:null};const t=function(e){return r.utc((e.time||"00:00")+"!"+e.ampm,"HH:mm!A")}(e),a=r.parseZone(e.utcOffset,"Z").set(e.date.toObject()).set({hours:t.hours(),minutes:t.minutes()});return a.isValid()?{valid:a}:{invalid:!0,valid:null}}(e);if(n.invalid)return{invalid:!0};let l;return l=a?"YYYY-MM-DDTHH:mmZ":t?"YYYY-MM-DDTHH:mm":"YYYY-MM-DD",{valid:null!=n&&n.valid?n.valid.format(l):null,invalid:!1}}({data:t,usesTime:u,usesTimezone:c});a.invalid||(Boolean(e)||!e&&Boolean(a.valid))&&n(a.valid)},key:"date-container-"+l})})}g.defaultProps={isInitiallyDisabled:!0},exports.DateEditor=g,exports.zoneOffsets=h;
|
|
2
2
|
//# sourceMappingURL=field-editor-date.cjs.production.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-editor-date.cjs.production.min.js","sources":["../src/DatepickerInput.tsx","../src/TimepickerInput.tsx","../src/utils/zoneOffsets.ts","../src/TimezonePickerInput.tsx","../src/utils/date.ts","../src/DateEditor.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\n\nimport { Datepicker } from '@contentful/f36-components';\nimport { css } from 'emotion';\n// eslint-disable-next-line -- TODO: move to date-fns\nimport moment from 'moment';\n\nconst YEAR_RANGE = 100;\n\nconst styles = {\n root: css({\n maxWidth: '270px',\n }),\n};\n\nexport type DatePickerProps = {\n value?: moment.Moment;\n onChange: (val: moment.Moment | undefined) => void;\n disabled?: boolean;\n};\n\nexport const DatepickerInput = (props: DatePickerProps) => {\n const [fromDate, toDate] = useMemo(() => {\n const fromDate = new Date();\n fromDate.setFullYear(fromDate.getFullYear() - YEAR_RANGE);\n const toDate = new Date();\n toDate.setFullYear(toDate.getFullYear() + YEAR_RANGE);\n\n return [fromDate, toDate];\n }, []);\n\n // The DatepickerInput should be time and timezone agnostic,\n // thats why we don't use moment().toDate() to get Date object.\n // moment().toDate() takes into account time and timezone and converts it\n // based on your system timezone which can result in the date change.\n // e.g. if user has a timezone +02:00, moment('2022-09-16T00:00+04:00').toDate()\n // will return September 15 instead of September 16\n const dateObj = props.value?.toObject();\n const selectedDate = dateObj ? new Date(dateObj.years, dateObj.months, dateObj.date) : undefined;\n\n return (\n <Datepicker\n className={styles.root}\n selected={selectedDate}\n onSelect={(day) => {\n const momentDay = day ? moment(day) : undefined;\n props.onChange(momentDay);\n }}\n inputProps={{ isDisabled: props.disabled, placeholder: '' }}\n fromDate={fromDate}\n toDate={toDate}\n />\n );\n};\n","import React, { useState, useCallback, useEffect } from 'react';\n// eslint-disable-next-line -- TODO: move to date-fns\nimport moment from 'moment';\nimport { css } from 'emotion';\n\nimport { TextInput, Flex } from '@contentful/f36-components';\n\nexport type TimepickerProps = {\n disabled: boolean;\n uses12hClock: boolean;\n onChange: (value: { time: string; ampm: string }) => void;\n time?: string;\n ampm?: string;\n};\n\nconst validInputFormats = [\n 'hh:mm a',\n 'hh:mm A',\n 'h:mm a',\n 'h:mm A',\n 'hh:mm',\n 'k:mm',\n 'kk:mm',\n 'h a',\n 'h A',\n 'h',\n 'hh',\n 'HH',\n];\n\nfunction parseRawInput(raw: string): moment.Moment | null {\n let time: moment.Moment | null = null;\n\n // eslint-disable-next-line -- TODO: refactor to use for of loop\n for (let i = 0; i < validInputFormats.length; i++) {\n const date = moment(raw, validInputFormats[i]);\n if (date.isValid()) {\n time = date;\n break;\n }\n }\n\n return time;\n}\n\nconst getDefaultTime = () => {\n return moment(`12:00 AM`, 'hh:mm A');\n};\n\nconst formatToString = (uses12hClock: boolean, value: moment.Moment): string => {\n return uses12hClock ? value.format('hh:mm A') : value.format('HH:mm');\n};\n\nexport const TimepickerInput = ({\n disabled,\n uses12hClock,\n time = '12:00',\n ampm = 'AM',\n onChange,\n}: TimepickerProps) => {\n const [selectedTime, setSelectedTime] = useState<string>(() => {\n return formatToString(uses12hClock, getDefaultTime());\n });\n\n useEffect(() => {\n setSelectedTime(formatToString(uses12hClock, moment(`${time} ${ampm}`, 'hh:mm A')));\n }, [time, ampm, uses12hClock]);\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setSelectedTime(e.currentTarget.value);\n }, []);\n\n const handleFocus = useCallback((e) => {\n e.preventDefault();\n e.target.select();\n }, []);\n\n const handleBlur = () => {\n const parsedTime = parseRawInput(selectedTime);\n const value = parsedTime ?? getDefaultTime();\n setSelectedTime(formatToString(uses12hClock, value));\n onChange({ time: value.format('hh:mm'), ampm: value.format('A') });\n };\n\n return (\n <Flex className={css({ width: '145px' })}>\n <TextInput\n aria-label=\"Select time\"\n placeholder={uses12hClock ? '12:00 AM' : '00:00'}\n date-time-type={uses12hClock ? '12' : '24'}\n testId=\"time-input\"\n value={selectedTime}\n isDisabled={disabled}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n />\n </Flex>\n );\n};\n","export const defaultZoneOffset = '+00:00';\n\nexport const zoneOffsets = [\n '-12:00',\n '-11:00',\n '-10:00',\n '-09:30',\n '-09:00',\n '-08:00',\n '-07:00',\n '-06:00',\n '-05:00',\n '-04:30',\n '-04:00',\n '-03:30',\n '-03:00',\n '-02:00',\n '-01:00',\n '+00:00',\n '+01:00',\n '+02:00',\n '+03:00',\n '+03:30',\n '+04:00',\n '+04:30',\n '+05:00',\n '+05:30',\n '+05:45',\n '+06:00',\n '+06:30',\n '+07:00',\n '+08:00',\n '+08:45',\n '+09:00',\n '+09:30',\n '+10:00',\n '+10:30',\n '+11:00',\n '+11:30',\n '+12:00',\n '+12:45',\n '+13:00',\n '+14:00',\n];\n","import React, { ChangeEvent } from 'react';\nimport { zoneOffsets, defaultZoneOffset } from './utils/zoneOffsets';\n\nimport { Select } from '@contentful/f36-components';\n\nexport type TimezonepickerProps = {\n disabled: boolean;\n onChange: (value: string) => void;\n value?: string;\n};\nexport const TimezonepickerInput = ({\n disabled,\n onChange,\n value = defaultZoneOffset,\n}: TimezonepickerProps) => {\n return (\n <Select\n aria-label=\"Select timezone\"\n testId=\"timezone-input\"\n value={value}\n isDisabled={disabled}\n onChange={(e: ChangeEvent<HTMLSelectElement>) => {\n onChange(e.currentTarget.value);\n }}>\n {zoneOffsets.map((offset) => (\n <Select.Option key={offset} value={offset}>\n UTC{offset}\n </Select.Option>\n ))}\n </Select>\n );\n};\n","// eslint-disable-next-line -- TODO: move to date-fns\nimport moment from 'moment';\nimport { TimeResult } from '../types';\n\nconst ZONE_RX = /(Z|[+-]\\d{2}[:+]?\\d{2})$/;\n\nfunction startOfToday(format: string) {\n return moment().set({ hours: 0, minutes: 0 }).format(format);\n}\n\nfunction fieldValueToMoment(datetimeString: string | null | undefined): moment.Moment | null {\n if (!datetimeString) {\n return null;\n }\n\n const datetime = moment(datetimeString);\n if (ZONE_RX.test(datetimeString)) {\n datetime.utcOffset(datetimeString);\n }\n return datetime;\n}\n\nfunction timeFromUserInput(input: TimeResult) {\n const timeInput = input.time || '00:00';\n return moment.utc(timeInput + '!' + input.ampm, 'HH:mm!A');\n}\n\n/**\n * Convert the user input object into either a 'moment' value or an\n * invalid symbol.\n *\n * Success is indicated by returning '{valid: value}' and failure is\n * indicated by returning '{invalid: true}'. If 'input.date' is\n * 'null' we return '{valid: null}'\n */\nfunction datetimeFromUserInput(input: TimeResult): {\n invalid?: boolean;\n valid: moment.Moment | null;\n} {\n if (!input.date) {\n return { valid: null };\n }\n\n const time = timeFromUserInput(input);\n\n const date = moment\n .parseZone(input.utcOffset, 'Z')\n .set(input.date.toObject())\n .set({ hours: time.hours(), minutes: time.minutes() });\n\n if (date.isValid()) {\n return { valid: date };\n } else {\n return { invalid: true, valid: null };\n }\n}\n\n/**\n * Parse user input into a string that is stored in the API.\n *\n * Returns a sum type with either the string as the `valid` property\n * or the `invalid` property set to `false`.\n */\nexport function buildFieldValue({\n data,\n usesTime,\n usesTimezone,\n}: {\n data: TimeResult;\n usesTime: boolean;\n usesTimezone: boolean;\n}) {\n const date = datetimeFromUserInput(data);\n if (date.invalid) {\n return {\n invalid: true,\n };\n }\n\n let format;\n if (usesTimezone) {\n format = 'YYYY-MM-DDTHH:mmZ';\n } else if (usesTime) {\n format = 'YYYY-MM-DDTHH:mm';\n } else {\n format = 'YYYY-MM-DD';\n }\n return { valid: date?.valid ? date.valid.format(format) : null, invalid: false };\n}\n\nexport function getDefaultAMPM() {\n return 'AM';\n}\n\nexport function getDefaultUtcOffset() {\n return startOfToday('Z');\n}\n\n/**\n * Create the user input object from the field value.\n */\nexport function userInputFromDatetime({\n value,\n uses12hClock,\n}: {\n value: string | undefined | null;\n uses12hClock: boolean;\n}): TimeResult {\n const datetime = fieldValueToMoment(value);\n\n if (datetime) {\n const timeFormat = uses12hClock ? 'hh:mm' : 'HH:mm';\n return {\n date: datetime,\n time: datetime.format(timeFormat),\n ampm: datetime.format('A'),\n utcOffset: datetime.format('Z'),\n };\n } else {\n return {\n ampm: getDefaultAMPM(),\n utcOffset: getDefaultUtcOffset(),\n };\n }\n}\n","import * as React from 'react';\n\nimport { TextLink } from '@contentful/f36-components';\nimport tokens from '@contentful/f36-tokens';\nimport { FieldAPI, FieldConnector, ParametersAPI } from '@contentful/field-editor-shared';\nimport { css } from 'emotion';\n\nimport { DatepickerInput } from './DatepickerInput';\nimport { TimepickerInput } from './TimepickerInput';\nimport { TimezonepickerInput } from './TimezonePickerInput';\nimport { TimeFormat, DateTimeFormat, TimeResult } from './types';\nimport {\n userInputFromDatetime,\n buildFieldValue,\n getDefaultAMPM,\n getDefaultUtcOffset,\n} from './utils/date';\n\n\nexport interface DateEditorProps {\n /**\n * is the field disabled initially\n */\n isInitiallyDisabled: boolean;\n\n /*\n * is the field manually disabled\n */\n isDisabled?: boolean;\n\n /**\n * sdk.field\n */\n field: FieldAPI;\n\n /**\n * sdk.parameters\n */\n parameters?: ParametersAPI & {\n instance?: {\n format?: DateTimeFormat;\n ampm?: TimeFormat;\n };\n };\n}\n\nconst styles = {\n root: css({\n display: 'flex',\n alignItems: 'center',\n }),\n separator: css({\n marginLeft: tokens.spacingM,\n }),\n};\n\nfunction useEffectWithoutFirstRender(callback: Function, deps: Array<any>) {\n const isFirstRun = React.useRef(true);\n React.useEffect(() => {\n if (isFirstRun.current) {\n isFirstRun.current = false;\n return;\n }\n callback();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies\n }, deps);\n}\n\nfunction DateEditorContainer({\n initialValue,\n usesTime,\n usesTimezone,\n uses12hClock,\n disabled,\n hasClear,\n onChange,\n}: {\n initialValue: TimeResult;\n usesTime: boolean;\n usesTimezone: boolean;\n uses12hClock: boolean;\n disabled: boolean;\n hasClear: boolean;\n onChange: (value: TimeResult) => void;\n}) {\n const [value, setValue] = React.useState<TimeResult>(() => initialValue);\n\n useEffectWithoutFirstRender(() => {\n onChange(value);\n }, [value]);\n\n return (\n <div data-test-id=\"date-editor\" className={styles.root}>\n <DatepickerInput\n disabled={disabled}\n value={value.date}\n onChange={(date) => {\n setValue((value) => ({\n ...value,\n date,\n }));\n }}\n />\n {usesTime && (\n <>\n <div className={styles.separator} />\n <TimepickerInput\n disabled={disabled}\n time={value.time}\n ampm={value.ampm}\n onChange={({ time, ampm }) => {\n setValue((value) => ({\n ...value,\n time,\n ampm,\n }));\n }}\n uses12hClock={uses12hClock}\n />\n </>\n )}\n {usesTimezone && (\n <>\n <div className={styles.separator} />\n <TimezonepickerInput\n disabled={disabled}\n value={value.utcOffset}\n onChange={(utcOffset) => {\n setValue((value) => ({\n ...value,\n utcOffset,\n }));\n }}\n />\n </>\n )}\n {hasClear && (\n <>\n <div className={styles.separator} />\n <TextLink\n as=\"button\"\n isDisabled={disabled}\n testId=\"date-clear\"\n onClick={() => {\n setValue({\n date: undefined,\n time: undefined,\n ampm: getDefaultAMPM(),\n utcOffset: getDefaultUtcOffset(),\n });\n }}\n >\n Clear\n </TextLink>\n </>\n )}\n </div>\n );\n}\n\nexport function DateEditor(props: DateEditorProps) {\n const { field, parameters } = props;\n\n const formatParam = parameters?.instance?.format ?? 'timeZ';\n const ampmParam = parameters?.instance?.ampm ?? '24';\n\n const usesTime = formatParam !== 'dateonly';\n const usesTimezone = formatParam === 'timeZ';\n const uses12hClock = ampmParam === '12';\n\n return (\n <FieldConnector<string>\n field={field}\n isInitiallyDisabled={props.isInitiallyDisabled}\n throttle={0}\n >\n {({ value, disabled, setValue, externalReset }) => {\n const datetimeValue = userInputFromDatetime({\n value,\n uses12hClock,\n });\n return (\n <DateEditorContainer\n initialValue={datetimeValue}\n uses12hClock={uses12hClock}\n usesTimezone={usesTimezone}\n usesTime={usesTime}\n disabled={props.isDisabled ?? disabled}\n hasClear={Boolean(value)}\n onChange={(data) => {\n const fieldValue = buildFieldValue({ data, usesTime, usesTimezone });\n if (fieldValue.invalid) {\n return;\n }\n // if value is present - then override it with a new one\n // if value is not present - then set a new one if it's not nullable only\n if (Boolean(value) || (!value && Boolean(fieldValue.valid))) {\n setValue(fieldValue.valid);\n }\n }}\n key={`date-container-${externalReset}`}\n />\n );\n }}\n </FieldConnector>\n );\n}\n\nDateEditor.defaultProps = {\n isInitiallyDisabled: true,\n};\n"],"names":["styles","root","css","maxWidth","DatepickerInput","props","useMemo","fromDate","Date","setFullYear","getFullYear","toDate","dateObj","value","_props$value","toObject","selectedDate","years","months","date","undefined","React","Datepicker","className","selected","onSelect","day","momentDay","moment","onChange","inputProps","isDisabled","disabled","placeholder","validInputFormats","getDefaultTime","formatToString","uses12hClock","format","TimepickerInput","time","ampm","useState","selectedTime","setSelectedTime","useEffect","handleChange","useCallback","e","currentTarget","handleFocus","preventDefault","target","select","Flex","width","TextInput","testId","onFocus","onBlur","parsedTime","raw","i","length","isValid","parseRawInput","zoneOffsets","TimezonepickerInput","Select","map","offset","Option","key","ZONE_RX","getDefaultUtcOffset","set","hours","minutes","display","alignItems","separator","marginLeft","tokens","spacingM","DateEditorContainer","callback","deps","isFirstRun","initialValue","usesTime","usesTimezone","hasClear","setValue","current","utcOffset","TextLink","as","onClick","DateEditor","parameters","formatParam","instance","_parameters$instance","ampmParam","_parameters$instance2","FieldConnector","field","isInitiallyDisabled","throttle","externalReset","datetimeValue","datetime","datetimeString","test","fieldValueToMoment","userInputFromDatetime","Boolean","data","fieldValue","input","valid","utc","timeFromUserInput","parseZone","invalid","datetimeFromUserInput","buildFieldValue","defaultProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"field-editor-date.cjs.production.min.js","sources":["../src/DatepickerInput.tsx","../src/TimepickerInput.tsx","../src/utils/zoneOffsets.ts","../src/TimezonePickerInput.tsx","../src/utils/date.ts","../src/DateEditor.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\n\nimport { Datepicker } from '@contentful/f36-components';\nimport { css } from 'emotion';\n// eslint-disable-next-line -- TODO: move to date-fns\nimport moment from 'moment';\n\nconst YEAR_RANGE = 100;\n\nconst styles = {\n root: css({\n maxWidth: '270px',\n }),\n};\n\nexport type DatePickerProps = {\n value?: moment.Moment;\n onChange: (val: moment.Moment | undefined) => void;\n disabled?: boolean;\n};\n\nexport const DatepickerInput = (props: DatePickerProps) => {\n const [fromDate, toDate] = useMemo(() => {\n const fromDate = new Date();\n fromDate.setFullYear(fromDate.getFullYear() - YEAR_RANGE);\n const toDate = new Date();\n toDate.setFullYear(toDate.getFullYear() + YEAR_RANGE);\n\n return [fromDate, toDate];\n }, []);\n\n // The DatepickerInput should be time and timezone agnostic,\n // thats why we don't use moment().toDate() to get Date object.\n // moment().toDate() takes into account time and timezone and converts it\n // based on your system timezone which can result in the date change.\n // e.g. if user has a timezone +02:00, moment('2022-09-16T00:00+04:00').toDate()\n // will return September 15 instead of September 16\n const dateObj = props.value?.toObject();\n const selectedDate = dateObj ? new Date(dateObj.years, dateObj.months, dateObj.date) : undefined;\n\n return (\n <Datepicker\n className={styles.root}\n selected={selectedDate}\n onSelect={(day) => {\n const momentDay = day ? moment(day) : undefined;\n props.onChange(momentDay);\n }}\n inputProps={{ isDisabled: props.disabled, placeholder: '' }}\n fromDate={fromDate}\n toDate={toDate}\n />\n );\n};\n","import React, { useState, useCallback, useEffect } from 'react';\n\n// eslint-disable-next-line -- TODO: move to date-fns\nimport { TextInput, Flex } from '@contentful/f36-components';\nimport { css } from 'emotion';\n// eslint-disable-next-line no-restricted-imports -- will change\nimport moment from 'moment';\n\nexport type TimepickerProps = {\n disabled: boolean;\n uses12hClock: boolean;\n onChange: (value: { time: string; ampm: string }) => void;\n time?: string;\n ampm?: string;\n};\n\nconst validInputFormats = [\n 'hh:mm a',\n 'hh:mm A',\n 'h:mm a',\n 'h:mm A',\n 'hh:mm',\n 'k:mm',\n 'kk:mm',\n 'h a',\n 'h A',\n 'h',\n 'hh',\n 'HH',\n];\n\nfunction parseRawInput(raw: string): moment.Moment | null {\n let time: moment.Moment | null = null;\n\n // eslint-disable-next-line -- TODO: refactor to use for of loop\n for (let i = 0; i < validInputFormats.length; i++) {\n const date = moment(raw, validInputFormats[i]);\n if (date.isValid()) {\n time = date;\n break;\n }\n }\n\n return time;\n}\n\nconst getDefaultTime = () => {\n return moment(`12:00 AM`, 'hh:mm A');\n};\n\nconst formatToString = (uses12hClock: boolean, value: moment.Moment): string => {\n return uses12hClock ? value.format('hh:mm A') : value.format('HH:mm');\n};\n\nexport const TimepickerInput = ({\n disabled,\n uses12hClock,\n time = '12:00',\n ampm = 'AM',\n onChange,\n}: TimepickerProps) => {\n const [selectedTime, setSelectedTime] = useState<string>(() => {\n return formatToString(uses12hClock, getDefaultTime());\n });\n\n useEffect(() => {\n setSelectedTime(formatToString(uses12hClock, moment(`${time} ${ampm}`, 'hh:mm A')));\n }, [time, ampm, uses12hClock]);\n\n const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n setSelectedTime(e.currentTarget.value);\n }, []);\n\n const handleFocus = useCallback((e) => {\n e.preventDefault();\n e.target.select();\n }, []);\n\n const handleBlur = () => {\n const parsedTime = parseRawInput(selectedTime);\n const value = parsedTime ?? getDefaultTime();\n setSelectedTime(formatToString(uses12hClock, value));\n onChange({ time: value.format('hh:mm'), ampm: value.format('A') });\n };\n\n return (\n <Flex className={css({ width: '145px' })}>\n <TextInput\n aria-label=\"Select time\"\n placeholder={uses12hClock ? '12:00 AM' : '00:00'}\n date-time-type={uses12hClock ? '12' : '24'}\n testId=\"time-input\"\n value={selectedTime}\n isDisabled={disabled}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onChange={handleChange}\n />\n </Flex>\n );\n};\n","export const defaultZoneOffset = '+00:00';\n\nexport const zoneOffsets = [\n '-12:00',\n '-11:00',\n '-10:00',\n '-09:30',\n '-09:00',\n '-08:00',\n '-07:00',\n '-06:00',\n '-05:00',\n '-04:30',\n '-04:00',\n '-03:30',\n '-03:00',\n '-02:00',\n '-01:00',\n '+00:00',\n '+01:00',\n '+02:00',\n '+03:00',\n '+03:30',\n '+04:00',\n '+04:30',\n '+05:00',\n '+05:30',\n '+05:45',\n '+06:00',\n '+06:30',\n '+07:00',\n '+08:00',\n '+08:45',\n '+09:00',\n '+09:30',\n '+10:00',\n '+10:30',\n '+11:00',\n '+11:30',\n '+12:00',\n '+12:45',\n '+13:00',\n '+14:00',\n];\n","import React, { ChangeEvent } from 'react';\n\nimport { Select } from '@contentful/f36-components';\n\nimport { zoneOffsets, defaultZoneOffset } from './utils/zoneOffsets';\n\n\nexport type TimezonepickerProps = {\n disabled: boolean;\n onChange: (value: string) => void;\n value?: string;\n};\nexport const TimezonepickerInput = ({\n disabled,\n onChange,\n value = defaultZoneOffset,\n}: TimezonepickerProps) => {\n return (\n <Select\n aria-label=\"Select timezone\"\n testId=\"timezone-input\"\n value={value}\n isDisabled={disabled}\n onChange={(e: ChangeEvent<HTMLSelectElement>) => {\n onChange(e.currentTarget.value);\n }}>\n {zoneOffsets.map((offset) => (\n <Select.Option key={offset} value={offset}>\n UTC{offset}\n </Select.Option>\n ))}\n </Select>\n );\n};\n","// eslint-disable-next-line -- TODO: move to date-fns\nimport moment from 'moment';\nimport { TimeResult } from '../types';\n\nconst ZONE_RX = /(Z|[+-]\\d{2}[:+]?\\d{2})$/;\n\nfunction startOfToday(format: string) {\n return moment().set({ hours: 0, minutes: 0 }).format(format);\n}\n\nfunction fieldValueToMoment(datetimeString: string | null | undefined): moment.Moment | null {\n if (!datetimeString) {\n return null;\n }\n\n const datetime = moment(datetimeString);\n if (ZONE_RX.test(datetimeString)) {\n datetime.utcOffset(datetimeString);\n }\n return datetime;\n}\n\nfunction timeFromUserInput(input: TimeResult) {\n const timeInput = input.time || '00:00';\n return moment.utc(timeInput + '!' + input.ampm, 'HH:mm!A');\n}\n\n/**\n * Convert the user input object into either a 'moment' value or an\n * invalid symbol.\n *\n * Success is indicated by returning '{valid: value}' and failure is\n * indicated by returning '{invalid: true}'. If 'input.date' is\n * 'null' we return '{valid: null}'\n */\nfunction datetimeFromUserInput(input: TimeResult): {\n invalid?: boolean;\n valid: moment.Moment | null;\n} {\n if (!input.date) {\n return { valid: null };\n }\n\n const time = timeFromUserInput(input);\n\n const date = moment\n .parseZone(input.utcOffset, 'Z')\n .set(input.date.toObject())\n .set({ hours: time.hours(), minutes: time.minutes() });\n\n if (date.isValid()) {\n return { valid: date };\n } else {\n return { invalid: true, valid: null };\n }\n}\n\n/**\n * Parse user input into a string that is stored in the API.\n *\n * Returns a sum type with either the string as the `valid` property\n * or the `invalid` property set to `false`.\n */\nexport function buildFieldValue({\n data,\n usesTime,\n usesTimezone,\n}: {\n data: TimeResult;\n usesTime: boolean;\n usesTimezone: boolean;\n}) {\n const date = datetimeFromUserInput(data);\n if (date.invalid) {\n return {\n invalid: true,\n };\n }\n\n let format;\n if (usesTimezone) {\n format = 'YYYY-MM-DDTHH:mmZ';\n } else if (usesTime) {\n format = 'YYYY-MM-DDTHH:mm';\n } else {\n format = 'YYYY-MM-DD';\n }\n return { valid: date?.valid ? date.valid.format(format) : null, invalid: false };\n}\n\nexport function getDefaultAMPM() {\n return 'AM';\n}\n\nexport function getDefaultUtcOffset() {\n return startOfToday('Z');\n}\n\n/**\n * Create the user input object from the field value.\n */\nexport function userInputFromDatetime({\n value,\n uses12hClock,\n}: {\n value: string | undefined | null;\n uses12hClock: boolean;\n}): TimeResult {\n const datetime = fieldValueToMoment(value);\n\n if (datetime) {\n const timeFormat = uses12hClock ? 'hh:mm' : 'HH:mm';\n return {\n date: datetime,\n time: datetime.format(timeFormat),\n ampm: datetime.format('A'),\n utcOffset: datetime.format('Z'),\n };\n } else {\n return {\n ampm: getDefaultAMPM(),\n utcOffset: getDefaultUtcOffset(),\n };\n }\n}\n","import * as React from 'react';\n\nimport { TextLink } from '@contentful/f36-components';\nimport tokens from '@contentful/f36-tokens';\nimport { FieldAPI, FieldConnector, ParametersAPI } from '@contentful/field-editor-shared';\nimport { css } from 'emotion';\n\nimport { DatepickerInput } from './DatepickerInput';\nimport { TimepickerInput } from './TimepickerInput';\nimport { TimezonepickerInput } from './TimezonePickerInput';\nimport { TimeFormat, DateTimeFormat, TimeResult } from './types';\nimport {\n userInputFromDatetime,\n buildFieldValue,\n getDefaultAMPM,\n getDefaultUtcOffset,\n} from './utils/date';\n\nexport interface DateEditorProps {\n /**\n * is the field disabled initially\n */\n isInitiallyDisabled: boolean;\n\n /*\n * is the field manually disabled\n */\n isDisabled?: boolean;\n\n /**\n * sdk.field\n */\n field: FieldAPI;\n\n /**\n * sdk.parameters\n */\n parameters?: ParametersAPI & {\n instance?: {\n format?: DateTimeFormat;\n ampm?: TimeFormat;\n };\n };\n}\n\nconst styles = {\n root: css({\n display: 'flex',\n alignItems: 'center',\n }),\n separator: css({\n marginLeft: tokens.spacingM,\n }),\n};\n\nfunction useEffectWithoutFirstRender(callback: Function, deps: Array<any>) {\n const isFirstRun = React.useRef(true);\n React.useEffect(() => {\n if (isFirstRun.current) {\n isFirstRun.current = false;\n return;\n }\n callback();\n // eslint-disable-next-line react-hooks/exhaustive-deps -- TODO: Evaluate the dependencies\n }, deps);\n}\n\nfunction DateEditorContainer({\n initialValue,\n usesTime,\n usesTimezone,\n uses12hClock,\n disabled,\n hasClear,\n onChange,\n}: {\n initialValue: TimeResult;\n usesTime: boolean;\n usesTimezone: boolean;\n uses12hClock: boolean;\n disabled: boolean;\n hasClear: boolean;\n onChange: (value: TimeResult) => void;\n}) {\n const [value, setValue] = React.useState<TimeResult>(() => initialValue);\n\n useEffectWithoutFirstRender(() => {\n onChange(value);\n }, [value]);\n\n return (\n <div data-test-id=\"date-editor\" className={styles.root}>\n <DatepickerInput\n disabled={disabled}\n value={value.date}\n onChange={(date) => {\n setValue((value) => ({\n ...value,\n date,\n }));\n }}\n />\n {usesTime && (\n <>\n <div className={styles.separator} />\n <TimepickerInput\n disabled={disabled}\n time={value.time}\n ampm={value.ampm}\n onChange={({ time, ampm }) => {\n setValue((value) => ({\n ...value,\n time,\n ampm,\n }));\n }}\n uses12hClock={uses12hClock}\n />\n </>\n )}\n {usesTimezone && (\n <>\n <div className={styles.separator} />\n <TimezonepickerInput\n disabled={disabled}\n value={value.utcOffset}\n onChange={(utcOffset) => {\n setValue((value) => ({\n ...value,\n utcOffset,\n }));\n }}\n />\n </>\n )}\n {hasClear && (\n <>\n <div className={styles.separator} />\n <TextLink\n as=\"button\"\n isDisabled={disabled}\n testId=\"date-clear\"\n onClick={() => {\n setValue({\n date: undefined,\n time: undefined,\n ampm: getDefaultAMPM(),\n utcOffset: getDefaultUtcOffset(),\n });\n }}>\n Clear\n </TextLink>\n </>\n )}\n </div>\n );\n}\n\nexport function DateEditor(props: DateEditorProps) {\n const { field, parameters } = props;\n\n const formatParam = parameters?.instance?.format ?? 'timeZ';\n const ampmParam = parameters?.instance?.ampm ?? '24';\n\n const usesTime = formatParam !== 'dateonly';\n const usesTimezone = formatParam === 'timeZ';\n const uses12hClock = ampmParam === '12';\n\n return (\n <FieldConnector<string>\n field={field}\n isInitiallyDisabled={props.isInitiallyDisabled}\n isDisabled={props.isDisabled}\n throttle={0}>\n {({ value, disabled, setValue, externalReset }) => {\n const datetimeValue = userInputFromDatetime({\n value,\n uses12hClock,\n });\n return (\n <DateEditorContainer\n initialValue={datetimeValue}\n uses12hClock={uses12hClock}\n usesTimezone={usesTimezone}\n usesTime={usesTime}\n disabled={disabled}\n hasClear={Boolean(value)}\n onChange={(data) => {\n const fieldValue = buildFieldValue({ data, usesTime, usesTimezone });\n if (fieldValue.invalid) {\n return;\n }\n // if value is present - then override it with a new one\n // if value is not present - then set a new one if it's not nullable only\n if (Boolean(value) || (!value && Boolean(fieldValue.valid))) {\n setValue(fieldValue.valid);\n }\n }}\n key={`date-container-${externalReset}`}\n />\n );\n }}\n </FieldConnector>\n );\n}\n\nDateEditor.defaultProps = {\n isInitiallyDisabled: true,\n};\n"],"names":["styles","root","css","maxWidth","DatepickerInput","props","fromDate","toDate","useMemo","Date","setFullYear","getFullYear","dateObj","value","_props$value","toObject","selectedDate","years","months","date","undefined","React","Datepicker","className","selected","onSelect","day","momentDay","moment","onChange","inputProps","isDisabled","disabled","placeholder","validInputFormats","getDefaultTime","formatToString","uses12hClock","format","TimepickerInput","time","ampm","selectedTime","setSelectedTime","useState","useEffect","handleChange","useCallback","e","currentTarget","handleFocus","preventDefault","target","select","Flex","width","TextInput","testId","onFocus","onBlur","raw","i","length","isValid","parseRawInput","zoneOffsets","TimezonepickerInput","Select","map","offset","Option","key","ZONE_RX","getDefaultUtcOffset","set","hours","minutes","display","alignItems","separator","marginLeft","tokens","spacingM","DateEditorContainer","initialValue","usesTime","usesTimezone","hasClear","setValue","callback","deps","isFirstRun","current","useEffectWithoutFirstRender","utcOffset","TextLink","as","onClick","DateEditor","field","parameters","formatParam","instance","ampmParam","FieldConnector","isInitiallyDisabled","throttle","externalReset","datetimeValue","datetime","datetimeString","test","fieldValueToMoment","userInputFromDatetime","Boolean","data","fieldValue","input","valid","utc","timeFromUserInput","parseZone","invalid","datetimeFromUserInput","buildFieldValue","defaultProps"],"mappings":"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"}
|
|
@@ -5,56 +5,35 @@ import { FieldConnector } from '@contentful/field-editor-shared';
|
|
|
5
5
|
import { css } from 'emotion';
|
|
6
6
|
import moment from 'moment';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
11
|
-
var source = arguments[i];
|
|
12
|
-
|
|
13
|
-
for (var key in source) {
|
|
14
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
15
|
-
target[key] = source[key];
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return target;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
return _extends.apply(this, arguments);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
var YEAR_RANGE = 100;
|
|
27
|
-
var styles = {
|
|
8
|
+
const YEAR_RANGE = 100;
|
|
9
|
+
const styles = {
|
|
28
10
|
root: /*#__PURE__*/css({
|
|
29
11
|
maxWidth: '270px'
|
|
30
12
|
})
|
|
31
13
|
};
|
|
32
|
-
|
|
14
|
+
const DatepickerInput = props => {
|
|
33
15
|
var _props$value;
|
|
34
16
|
|
|
35
|
-
|
|
36
|
-
|
|
17
|
+
const [fromDate, toDate] = useMemo(() => {
|
|
18
|
+
const fromDate = new Date();
|
|
37
19
|
fromDate.setFullYear(fromDate.getFullYear() - YEAR_RANGE);
|
|
38
|
-
|
|
20
|
+
const toDate = new Date();
|
|
39
21
|
toDate.setFullYear(toDate.getFullYear() + YEAR_RANGE);
|
|
40
22
|
return [fromDate, toDate];
|
|
41
|
-
}, []),
|
|
42
|
-
fromDate = _useMemo[0],
|
|
43
|
-
toDate = _useMemo[1]; // The DatepickerInput should be time and timezone agnostic,
|
|
23
|
+
}, []); // The DatepickerInput should be time and timezone agnostic,
|
|
44
24
|
// thats why we don't use moment().toDate() to get Date object.
|
|
45
25
|
// moment().toDate() takes into account time and timezone and converts it
|
|
46
26
|
// based on your system timezone which can result in the date change.
|
|
47
27
|
// e.g. if user has a timezone +02:00, moment('2022-09-16T00:00+04:00').toDate()
|
|
48
28
|
// will return September 15 instead of September 16
|
|
49
29
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
var selectedDate = dateObj ? new Date(dateObj.years, dateObj.months, dateObj.date) : undefined;
|
|
30
|
+
const dateObj = (_props$value = props.value) == null ? void 0 : _props$value.toObject();
|
|
31
|
+
const selectedDate = dateObj ? new Date(dateObj.years, dateObj.months, dateObj.date) : undefined;
|
|
53
32
|
return React__default.createElement(Datepicker, {
|
|
54
33
|
className: styles.root,
|
|
55
34
|
selected: selectedDate,
|
|
56
|
-
onSelect:
|
|
57
|
-
|
|
35
|
+
onSelect: day => {
|
|
36
|
+
const momentDay = day ? moment(day) : undefined;
|
|
58
37
|
props.onChange(momentDay);
|
|
59
38
|
},
|
|
60
39
|
inputProps: {
|
|
@@ -66,13 +45,13 @@ var DatepickerInput = function DatepickerInput(props) {
|
|
|
66
45
|
});
|
|
67
46
|
};
|
|
68
47
|
|
|
69
|
-
|
|
48
|
+
const validInputFormats = ['hh:mm a', 'hh:mm A', 'h:mm a', 'h:mm A', 'hh:mm', 'k:mm', 'kk:mm', 'h a', 'h A', 'h', 'hh', 'HH'];
|
|
70
49
|
|
|
71
50
|
function parseRawInput(raw) {
|
|
72
|
-
|
|
51
|
+
let time = null; // eslint-disable-next-line -- TODO: refactor to use for of loop
|
|
73
52
|
|
|
74
|
-
for (
|
|
75
|
-
|
|
53
|
+
for (let i = 0; i < validInputFormats.length; i++) {
|
|
54
|
+
const date = moment(raw, validInputFormats[i]);
|
|
76
55
|
|
|
77
56
|
if (date.isValid()) {
|
|
78
57
|
time = date;
|
|
@@ -83,43 +62,38 @@ function parseRawInput(raw) {
|
|
|
83
62
|
return time;
|
|
84
63
|
}
|
|
85
64
|
|
|
86
|
-
|
|
87
|
-
return moment(
|
|
65
|
+
const getDefaultTime = () => {
|
|
66
|
+
return moment(`12:00 AM`, 'hh:mm A');
|
|
88
67
|
};
|
|
89
68
|
|
|
90
|
-
|
|
69
|
+
const formatToString = (uses12hClock, value) => {
|
|
91
70
|
return uses12hClock ? value.format('hh:mm A') : value.format('HH:mm');
|
|
92
71
|
};
|
|
93
72
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
var _useState = useState(function () {
|
|
73
|
+
const TimepickerInput = ({
|
|
74
|
+
disabled,
|
|
75
|
+
uses12hClock,
|
|
76
|
+
time = '12:00',
|
|
77
|
+
ampm = 'AM',
|
|
78
|
+
onChange
|
|
79
|
+
}) => {
|
|
80
|
+
const [selectedTime, setSelectedTime] = useState(() => {
|
|
104
81
|
return formatToString(uses12hClock, getDefaultTime());
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
useEffect(function () {
|
|
110
|
-
setSelectedTime(formatToString(uses12hClock, moment(time + " " + ampm, 'hh:mm A')));
|
|
82
|
+
});
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
setSelectedTime(formatToString(uses12hClock, moment(`${time} ${ampm}`, 'hh:mm A')));
|
|
111
85
|
}, [time, ampm, uses12hClock]);
|
|
112
|
-
|
|
86
|
+
const handleChange = useCallback(e => {
|
|
113
87
|
setSelectedTime(e.currentTarget.value);
|
|
114
88
|
}, []);
|
|
115
|
-
|
|
89
|
+
const handleFocus = useCallback(e => {
|
|
116
90
|
e.preventDefault();
|
|
117
91
|
e.target.select();
|
|
118
92
|
}, []);
|
|
119
93
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
94
|
+
const handleBlur = () => {
|
|
95
|
+
const parsedTime = parseRawInput(selectedTime);
|
|
96
|
+
const value = parsedTime ?? getDefaultTime();
|
|
123
97
|
setSelectedTime(formatToString(uses12hClock, value));
|
|
124
98
|
onChange({
|
|
125
99
|
time: value.format('hh:mm'),
|
|
@@ -144,32 +118,30 @@ var TimepickerInput = function TimepickerInput(_ref) {
|
|
|
144
118
|
}));
|
|
145
119
|
};
|
|
146
120
|
|
|
147
|
-
|
|
148
|
-
|
|
121
|
+
const defaultZoneOffset = '+00:00';
|
|
122
|
+
const zoneOffsets = ['-12:00', '-11:00', '-10:00', '-09:30', '-09:00', '-08:00', '-07:00', '-06:00', '-05:00', '-04:30', '-04:00', '-03:30', '-03:00', '-02:00', '-01:00', '+00:00', '+01:00', '+02:00', '+03:00', '+03:30', '+04:00', '+04:30', '+05:00', '+05:30', '+05:45', '+06:00', '+06:30', '+07:00', '+08:00', '+08:45', '+09:00', '+09:30', '+10:00', '+10:30', '+11:00', '+11:30', '+12:00', '+12:45', '+13:00', '+14:00'];
|
|
149
123
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
124
|
+
const TimezonepickerInput = ({
|
|
125
|
+
disabled,
|
|
126
|
+
onChange,
|
|
127
|
+
value = defaultZoneOffset
|
|
128
|
+
}) => {
|
|
155
129
|
return React__default.createElement(Select, {
|
|
156
130
|
"aria-label": "Select timezone",
|
|
157
131
|
testId: "timezone-input",
|
|
158
132
|
value: value,
|
|
159
133
|
isDisabled: disabled,
|
|
160
|
-
onChange:
|
|
161
|
-
|
|
134
|
+
onChange: e => {
|
|
135
|
+
onChange(e.currentTarget.value);
|
|
162
136
|
}
|
|
163
|
-
}, zoneOffsets.map(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}, "UTC", offset);
|
|
168
|
-
}));
|
|
137
|
+
}, zoneOffsets.map(offset => React__default.createElement(Select.Option, {
|
|
138
|
+
key: offset,
|
|
139
|
+
value: offset
|
|
140
|
+
}, "UTC", offset)));
|
|
169
141
|
};
|
|
170
142
|
|
|
171
143
|
// eslint-disable-next-line -- TODO: move to date-fns
|
|
172
|
-
|
|
144
|
+
const ZONE_RX = /(Z|[+-]\d{2}[:+]?\d{2})$/;
|
|
173
145
|
|
|
174
146
|
function startOfToday(format) {
|
|
175
147
|
return moment().set({
|
|
@@ -183,7 +155,7 @@ function fieldValueToMoment(datetimeString) {
|
|
|
183
155
|
return null;
|
|
184
156
|
}
|
|
185
157
|
|
|
186
|
-
|
|
158
|
+
const datetime = moment(datetimeString);
|
|
187
159
|
|
|
188
160
|
if (ZONE_RX.test(datetimeString)) {
|
|
189
161
|
datetime.utcOffset(datetimeString);
|
|
@@ -193,7 +165,7 @@ function fieldValueToMoment(datetimeString) {
|
|
|
193
165
|
}
|
|
194
166
|
|
|
195
167
|
function timeFromUserInput(input) {
|
|
196
|
-
|
|
168
|
+
const timeInput = input.time || '00:00';
|
|
197
169
|
return moment.utc(timeInput + '!' + input.ampm, 'HH:mm!A');
|
|
198
170
|
}
|
|
199
171
|
/**
|
|
@@ -213,8 +185,8 @@ function datetimeFromUserInput(input) {
|
|
|
213
185
|
};
|
|
214
186
|
}
|
|
215
187
|
|
|
216
|
-
|
|
217
|
-
|
|
188
|
+
const time = timeFromUserInput(input);
|
|
189
|
+
const date = moment.parseZone(input.utcOffset, 'Z').set(input.date.toObject()).set({
|
|
218
190
|
hours: time.hours(),
|
|
219
191
|
minutes: time.minutes()
|
|
220
192
|
});
|
|
@@ -238,11 +210,12 @@ function datetimeFromUserInput(input) {
|
|
|
238
210
|
*/
|
|
239
211
|
|
|
240
212
|
|
|
241
|
-
function buildFieldValue(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
213
|
+
function buildFieldValue({
|
|
214
|
+
data,
|
|
215
|
+
usesTime,
|
|
216
|
+
usesTimezone
|
|
217
|
+
}) {
|
|
218
|
+
const date = datetimeFromUserInput(data);
|
|
246
219
|
|
|
247
220
|
if (date.invalid) {
|
|
248
221
|
return {
|
|
@@ -250,7 +223,7 @@ function buildFieldValue(_ref) {
|
|
|
250
223
|
};
|
|
251
224
|
}
|
|
252
225
|
|
|
253
|
-
|
|
226
|
+
let format;
|
|
254
227
|
|
|
255
228
|
if (usesTimezone) {
|
|
256
229
|
format = 'YYYY-MM-DDTHH:mmZ';
|
|
@@ -275,13 +248,14 @@ function getDefaultUtcOffset() {
|
|
|
275
248
|
* Create the user input object from the field value.
|
|
276
249
|
*/
|
|
277
250
|
|
|
278
|
-
function userInputFromDatetime(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
251
|
+
function userInputFromDatetime({
|
|
252
|
+
value,
|
|
253
|
+
uses12hClock
|
|
254
|
+
}) {
|
|
255
|
+
const datetime = fieldValueToMoment(value);
|
|
282
256
|
|
|
283
257
|
if (datetime) {
|
|
284
|
-
|
|
258
|
+
const timeFormat = uses12hClock ? 'hh:mm' : 'HH:mm';
|
|
285
259
|
return {
|
|
286
260
|
date: datetime,
|
|
287
261
|
time: datetime.format(timeFormat),
|
|
@@ -296,7 +270,7 @@ function userInputFromDatetime(_ref2) {
|
|
|
296
270
|
}
|
|
297
271
|
}
|
|
298
272
|
|
|
299
|
-
|
|
273
|
+
const styles$1 = {
|
|
300
274
|
root: /*#__PURE__*/css({
|
|
301
275
|
display: 'flex',
|
|
302
276
|
alignItems: 'center'
|
|
@@ -307,8 +281,8 @@ var styles$1 = {
|
|
|
307
281
|
};
|
|
308
282
|
|
|
309
283
|
function useEffectWithoutFirstRender(callback, deps) {
|
|
310
|
-
|
|
311
|
-
useEffect(
|
|
284
|
+
const isFirstRun = useRef(true);
|
|
285
|
+
useEffect(() => {
|
|
312
286
|
if (isFirstRun.current) {
|
|
313
287
|
isFirstRun.current = false;
|
|
314
288
|
return;
|
|
@@ -318,22 +292,17 @@ function useEffectWithoutFirstRender(callback, deps) {
|
|
|
318
292
|
}, deps);
|
|
319
293
|
}
|
|
320
294
|
|
|
321
|
-
function DateEditorContainer(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}),
|
|
333
|
-
value = _React$useState[0],
|
|
334
|
-
setValue = _React$useState[1];
|
|
335
|
-
|
|
336
|
-
useEffectWithoutFirstRender(function () {
|
|
295
|
+
function DateEditorContainer({
|
|
296
|
+
initialValue,
|
|
297
|
+
usesTime,
|
|
298
|
+
usesTimezone,
|
|
299
|
+
uses12hClock,
|
|
300
|
+
disabled,
|
|
301
|
+
hasClear,
|
|
302
|
+
onChange
|
|
303
|
+
}) {
|
|
304
|
+
const [value, setValue] = useState(() => initialValue);
|
|
305
|
+
useEffectWithoutFirstRender(() => {
|
|
337
306
|
onChange(value);
|
|
338
307
|
}, [value]);
|
|
339
308
|
return createElement("div", {
|
|
@@ -342,12 +311,10 @@ function DateEditorContainer(_ref) {
|
|
|
342
311
|
}, createElement(DatepickerInput, {
|
|
343
312
|
disabled: disabled,
|
|
344
313
|
value: value.date,
|
|
345
|
-
onChange:
|
|
346
|
-
setValue(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
});
|
|
350
|
-
});
|
|
314
|
+
onChange: date => {
|
|
315
|
+
setValue(value => ({ ...value,
|
|
316
|
+
date
|
|
317
|
+
}));
|
|
351
318
|
}
|
|
352
319
|
}), usesTime && createElement(Fragment, null, createElement("div", {
|
|
353
320
|
className: styles$1.separator
|
|
@@ -355,15 +322,14 @@ function DateEditorContainer(_ref) {
|
|
|
355
322
|
disabled: disabled,
|
|
356
323
|
time: value.time,
|
|
357
324
|
ampm: value.ampm,
|
|
358
|
-
onChange:
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
});
|
|
325
|
+
onChange: ({
|
|
326
|
+
time,
|
|
327
|
+
ampm
|
|
328
|
+
}) => {
|
|
329
|
+
setValue(value => ({ ...value,
|
|
330
|
+
time,
|
|
331
|
+
ampm
|
|
332
|
+
}));
|
|
367
333
|
},
|
|
368
334
|
uses12hClock: uses12hClock
|
|
369
335
|
})), usesTimezone && createElement(Fragment, null, createElement("div", {
|
|
@@ -371,12 +337,10 @@ function DateEditorContainer(_ref) {
|
|
|
371
337
|
}), createElement(TimezonepickerInput, {
|
|
372
338
|
disabled: disabled,
|
|
373
339
|
value: value.utcOffset,
|
|
374
|
-
onChange:
|
|
375
|
-
setValue(
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
});
|
|
379
|
-
});
|
|
340
|
+
onChange: utcOffset => {
|
|
341
|
+
setValue(value => ({ ...value,
|
|
342
|
+
utcOffset
|
|
343
|
+
}));
|
|
380
344
|
}
|
|
381
345
|
})), hasClear && createElement(Fragment, null, createElement("div", {
|
|
382
346
|
className: styles$1.separator
|
|
@@ -384,7 +348,7 @@ function DateEditorContainer(_ref) {
|
|
|
384
348
|
as: "button",
|
|
385
349
|
isDisabled: disabled,
|
|
386
350
|
testId: "date-clear",
|
|
387
|
-
onClick:
|
|
351
|
+
onClick: () => {
|
|
388
352
|
setValue({
|
|
389
353
|
date: undefined,
|
|
390
354
|
time: undefined,
|
|
@@ -396,42 +360,44 @@ function DateEditorContainer(_ref) {
|
|
|
396
360
|
}
|
|
397
361
|
|
|
398
362
|
function DateEditor(props) {
|
|
399
|
-
var _parameters$instance
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
363
|
+
var _parameters$instance, _parameters$instance2;
|
|
364
|
+
|
|
365
|
+
const {
|
|
366
|
+
field,
|
|
367
|
+
parameters
|
|
368
|
+
} = props;
|
|
369
|
+
const formatParam = (parameters == null ? void 0 : (_parameters$instance = parameters.instance) == null ? void 0 : _parameters$instance.format) ?? 'timeZ';
|
|
370
|
+
const ampmParam = (parameters == null ? void 0 : (_parameters$instance2 = parameters.instance) == null ? void 0 : _parameters$instance2.ampm) ?? '24';
|
|
371
|
+
const usesTime = formatParam !== 'dateonly';
|
|
372
|
+
const usesTimezone = formatParam === 'timeZ';
|
|
373
|
+
const uses12hClock = ampmParam === '12';
|
|
408
374
|
return createElement(FieldConnector, {
|
|
409
375
|
field: field,
|
|
410
376
|
isInitiallyDisabled: props.isInitiallyDisabled,
|
|
377
|
+
isDisabled: props.isDisabled,
|
|
411
378
|
throttle: 0
|
|
412
|
-
},
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
uses12hClock: uses12hClock
|
|
379
|
+
}, ({
|
|
380
|
+
value,
|
|
381
|
+
disabled,
|
|
382
|
+
setValue,
|
|
383
|
+
externalReset
|
|
384
|
+
}) => {
|
|
385
|
+
const datetimeValue = userInputFromDatetime({
|
|
386
|
+
value,
|
|
387
|
+
uses12hClock
|
|
422
388
|
});
|
|
423
389
|
return createElement(DateEditorContainer, {
|
|
424
390
|
initialValue: datetimeValue,
|
|
425
391
|
uses12hClock: uses12hClock,
|
|
426
392
|
usesTimezone: usesTimezone,
|
|
427
393
|
usesTime: usesTime,
|
|
428
|
-
disabled:
|
|
394
|
+
disabled: disabled,
|
|
429
395
|
hasClear: Boolean(value),
|
|
430
|
-
onChange:
|
|
431
|
-
|
|
432
|
-
data
|
|
433
|
-
usesTime
|
|
434
|
-
usesTimezone
|
|
396
|
+
onChange: data => {
|
|
397
|
+
const fieldValue = buildFieldValue({
|
|
398
|
+
data,
|
|
399
|
+
usesTime,
|
|
400
|
+
usesTimezone
|
|
435
401
|
});
|
|
436
402
|
|
|
437
403
|
if (fieldValue.invalid) {
|
|
@@ -444,7 +410,7 @@ function DateEditor(props) {
|
|
|
444
410
|
setValue(fieldValue.valid);
|
|
445
411
|
}
|
|
446
412
|
},
|
|
447
|
-
key:
|
|
413
|
+
key: `date-container-${externalReset}`
|
|
448
414
|
});
|
|
449
415
|
});
|
|
450
416
|
}
|