@sanity/rich-date-input 3.0.3 → 3.0.4
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/README.md +2 -2
- package/dist/index.esm.js +55 -52
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +52 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/RelativeDateTimePicker.tsx +49 -46
- package/src/components/RichDateInput.tsx +8 -5
- package/src/components/TimezoneButton.tsx +4 -2
- package/src/components/TimezoneSelector.tsx +34 -27
- package/src/index.ts +3 -2
- package/src/schema.ts +3 -2
- package/src/utils/index.ts +3 -2
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ import {defineConfig} from 'sanity'
|
|
|
22
22
|
import {richDate} from '@sanity/rich-date-input'
|
|
23
23
|
|
|
24
24
|
export default defineConfig({
|
|
25
|
-
|
|
25
|
+
// ...
|
|
26
26
|
plugins: [richDate()],
|
|
27
27
|
})
|
|
28
28
|
```
|
|
@@ -41,7 +41,7 @@ export default defineType({
|
|
|
41
41
|
name: 'scheduledAt',
|
|
42
42
|
title: 'Scheduled at',
|
|
43
43
|
type: 'richDate',
|
|
44
|
-
//this will take the same options available on the datetime type: https://www.sanity.io/docs/datetime-type
|
|
44
|
+
// this will take the same options available on the datetime type: https://www.sanity.io/docs/datetime-type
|
|
45
45
|
options: {
|
|
46
46
|
timeStep: 30,
|
|
47
47
|
},
|
package/dist/index.esm.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { unset, set, DateTimeInput, ObjectInputMember, defineType, defineField, definePlugin } from 'sanity';
|
|
2
2
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
-
import { Box, Autocomplete, Card, Text,
|
|
3
|
+
import { Button, Box, Autocomplete, Card, Text, Flex, Dialog } from '@sanity/ui';
|
|
4
|
+
import { useCallback, useState } from 'react';
|
|
5
|
+
import { formatInTimeZone, zonedTimeToUtc, getTimezoneOffset } from 'date-fns-tz';
|
|
4
6
|
import { getTimeZones } from '@vvo/tzdb';
|
|
5
|
-
import {
|
|
6
|
-
import { SearchIcon, EarthAmericasIcon } from '@sanity/icons';
|
|
7
|
-
import { useState, useCallback } from 'react';
|
|
7
|
+
import { EarthAmericasIcon, SearchIcon } from '@sanity/icons';
|
|
8
8
|
const unlocalizeDateTime = (datetime, timezone) => {
|
|
9
9
|
return formatInTimeZone(datetime, timezone, "yyyy-MM-dd HH:mm:ss");
|
|
10
10
|
};
|
|
11
11
|
const getConstructedUTCDate = (utc, offset) => {
|
|
12
12
|
const date = new Date(utc);
|
|
13
|
-
const currentOffset =
|
|
13
|
+
const currentOffset = date.getTimezoneOffset() * -1;
|
|
14
14
|
const diff = currentOffset - offset;
|
|
15
15
|
const fakeUTCDate = new Date(date.getTime() - diff * 60 * 1e3);
|
|
16
16
|
return fakeUTCDate.toISOString();
|
|
@@ -32,30 +32,33 @@ const allTimezones = getTimeZones().map(tz => {
|
|
|
32
32
|
};
|
|
33
33
|
});
|
|
34
34
|
const RelativeDateTimePicker = props => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const handleDateChange = patch => {
|
|
40
|
-
|
|
35
|
+
const {
|
|
36
|
+
dateValue: value,
|
|
37
|
+
onChange
|
|
38
|
+
} = props;
|
|
39
|
+
const handleDateChange = useCallback(patch => {
|
|
40
|
+
var _a;
|
|
41
|
+
const timezone = (_a = value == null ? void 0 : value.timezone) != null ? _a : Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
41
42
|
const newDatetime = patch == null ? void 0 : patch.value;
|
|
42
43
|
if (!newDatetime || !("type" in patch) || patch.type !== "set") {
|
|
43
|
-
|
|
44
|
+
onChange(unset());
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
47
|
const desiredDateTime = unlocalizeDateTime(newDatetime, Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
|
|
48
|
+
const newUtcDateObject = zonedTimeToUtc(desiredDateTime, timezone);
|
|
49
|
+
const newOffset = getTimezoneOffset(timezone, newUtcDateObject) / 60 / 1e3;
|
|
50
|
+
const localDate = formatInTimeZone(newUtcDateObject, timezone, "yyyy-MM-dd'T'HH:mm:ssXXX");
|
|
51
|
+
const patches = [];
|
|
52
|
+
patches.push(set(newUtcDateObject.toISOString(), ["utc"]));
|
|
50
53
|
patches.push(set(localDate, ["local"]));
|
|
51
54
|
if (!(value == null ? void 0 : value.timezone)) {
|
|
52
55
|
patches.push(set(timezone, ["timezone"]));
|
|
53
56
|
}
|
|
54
|
-
if (
|
|
55
|
-
patches.push(set(
|
|
57
|
+
if ((value == null ? void 0 : value.offset) !== newOffset) {
|
|
58
|
+
patches.push(set(newOffset, ["offset"]));
|
|
56
59
|
}
|
|
57
|
-
|
|
58
|
-
};
|
|
60
|
+
onChange(patches);
|
|
61
|
+
}, [onChange, value]);
|
|
59
62
|
const dateToDisplay = (value == null ? void 0 : value.utc) ? getConstructedUTCDate(value.utc, value.offset) : "";
|
|
60
63
|
return /* @__PURE__ */jsx(DateTimeInput, {
|
|
61
64
|
...props,
|
|
@@ -63,6 +66,27 @@ const RelativeDateTimePicker = props => {
|
|
|
63
66
|
value: dateToDisplay
|
|
64
67
|
});
|
|
65
68
|
};
|
|
69
|
+
const TimezoneButton = props => {
|
|
70
|
+
var _a, _b, _c, _d, _e;
|
|
71
|
+
const {
|
|
72
|
+
onClick,
|
|
73
|
+
timezone
|
|
74
|
+
} = props;
|
|
75
|
+
const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
76
|
+
const label = (_e = (_c = (_a = allTimezones.find(tz => tz.name === timezone)) == null ? void 0 : _a.abbreviation) != null ? _c : (_b = allTimezones.find(tz => tz.name === currentTimezone)) == null ? void 0 : _b.abbreviation) != null ? _e : (_d = allTimezones.find(tz => tz.group.includes(currentTimezone))) == null ? void 0 : _d.abbreviation;
|
|
77
|
+
return /* @__PURE__ */jsx(Button, {
|
|
78
|
+
fontSize: 1,
|
|
79
|
+
style: {
|
|
80
|
+
width: "100%"
|
|
81
|
+
},
|
|
82
|
+
justify: "flex-start",
|
|
83
|
+
icon: EarthAmericasIcon,
|
|
84
|
+
mode: "ghost",
|
|
85
|
+
onClick,
|
|
86
|
+
text: "".concat(label),
|
|
87
|
+
"aria-label": "Select a timezone"
|
|
88
|
+
});
|
|
89
|
+
};
|
|
66
90
|
const TimezoneSelector = props => {
|
|
67
91
|
var _a, _b;
|
|
68
92
|
const {
|
|
@@ -72,25 +96,25 @@ const TimezoneSelector = props => {
|
|
|
72
96
|
const currentTz = allTimezones.find(tz => tz.name === (value == null ? void 0 : value.timezone));
|
|
73
97
|
const userTzName = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
74
98
|
const userTz = (_a = allTimezones.find(tz => tz.name === userTzName)) != null ? _a : allTimezones.find(tz => tz.group.includes(userTzName));
|
|
75
|
-
const handleTimezoneChange = selectedTz => {
|
|
76
|
-
var _a2
|
|
99
|
+
const handleTimezoneChange = useCallback(selectedTz => {
|
|
100
|
+
var _a2;
|
|
77
101
|
const newTimezone = (_a2 = allTimezones.find(tz => tz.value === selectedTz)) != null ? _a2 : userTz;
|
|
78
|
-
const offset = (_b2 = newTimezone.currentTimeOffsetInMinutes) != null ? _b2 : 0;
|
|
79
102
|
const timezonePatch = set(newTimezone.name, ["timezone"]);
|
|
80
|
-
const
|
|
81
|
-
const patches = [timezonePatch, offsetPatch];
|
|
103
|
+
const patches = [timezonePatch];
|
|
82
104
|
if (value == null ? void 0 : value.utc) {
|
|
83
105
|
const desiredDateTime = unlocalizeDateTime(value.utc, value.timezone);
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
106
|
+
const newUtcDateObject = zonedTimeToUtc(desiredDateTime, newTimezone.name);
|
|
107
|
+
const newOffset = getTimezoneOffset(newTimezone.name, newUtcDateObject) / 60 / 1e3;
|
|
108
|
+
const newLocalDate = formatInTimeZone(newUtcDateObject.toISOString(), newTimezone.name, "yyyy-MM-dd'T'HH:mm:ssXXX");
|
|
109
|
+
patches.push(set(newUtcDateObject.toISOString(), ["utc"]));
|
|
87
110
|
patches.push(set(newLocalDate, ["local"]));
|
|
111
|
+
patches.push(set(newOffset, ["offset"]));
|
|
88
112
|
}
|
|
89
113
|
onChange(patches);
|
|
90
|
-
};
|
|
114
|
+
}, [onChange, userTz, value]);
|
|
91
115
|
return (
|
|
92
|
-
//taken from Scheduled Publishing, again!
|
|
93
|
-
//https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100
|
|
116
|
+
// taken from Scheduled Publishing, again!
|
|
117
|
+
// https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100
|
|
94
118
|
/* @__PURE__ */
|
|
95
119
|
jsx(Box, {
|
|
96
120
|
padding: 4,
|
|
@@ -142,27 +166,6 @@ const TimezoneSelector = props => {
|
|
|
142
166
|
})
|
|
143
167
|
);
|
|
144
168
|
};
|
|
145
|
-
const TimezoneButton = props => {
|
|
146
|
-
var _a, _b, _c, _d, _e;
|
|
147
|
-
const {
|
|
148
|
-
onClick,
|
|
149
|
-
timezone
|
|
150
|
-
} = props;
|
|
151
|
-
const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
152
|
-
const label = (_e = (_c = (_a = allTimezones.find(tz => tz.name === timezone)) == null ? void 0 : _a.abbreviation) != null ? _c : (_b = allTimezones.find(tz => tz.name === currentTimezone)) == null ? void 0 : _b.abbreviation) != null ? _e : (_d = allTimezones.find(tz => tz.group.includes(currentTimezone))) == null ? void 0 : _d.abbreviation;
|
|
153
|
-
return /* @__PURE__ */jsx(Button, {
|
|
154
|
-
fontSize: 1,
|
|
155
|
-
style: {
|
|
156
|
-
width: "100%"
|
|
157
|
-
},
|
|
158
|
-
justify: "flex-start",
|
|
159
|
-
icon: EarthAmericasIcon,
|
|
160
|
-
mode: "ghost",
|
|
161
|
-
onClick,
|
|
162
|
-
text: "".concat(label),
|
|
163
|
-
"aria-label": "Select a timezone"
|
|
164
|
-
});
|
|
165
|
-
};
|
|
166
169
|
const RichDateInput = props => {
|
|
167
170
|
const {
|
|
168
171
|
onChange,
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/utils/index.ts","../src/components/RelativeDateTimePicker.tsx","../src/components/TimezoneSelector.tsx","../src/components/TimezoneButton.tsx","../src/components/RichDateInput.tsx","../src/schema.ts","../src/index.ts"],"sourcesContent":["import {getTimeZones} from '@vvo/tzdb'\nimport {NormalizedTimeZone} from '../types'\nimport {formatInTimeZone} from 'date-fns-tz'\n\nexport const unlocalizeDateTime = (datetime: string, timezone: string): string => {\n return formatInTimeZone(datetime, timezone, 'yyyy-MM-dd HH:mm:ss')\n}\n\n/* We have to \"fake\" a UTC date to make the datepicker look \"right\"\n * to the user. For example, if someone sets 7:00AM PST, which is 3PM UTC\n * and I am on the east coast, I want to have 12:00PM UTC, which will look like 7:00AM to me\n * In other words, UTC minus 3 hours, or (UTC(my offset - their offset))\n * this is purely cosmetic and should not be saved at all\n */\nexport const getConstructedUTCDate = (utc: string, offset: number): string => {\n const date = new Date(utc)\n const currentOffset = new Date().getTimezoneOffset() * -1\n const diff = currentOffset - offset\n const fakeUTCDate = new Date(date.getTime() - diff * 60 * 1000)\n return fakeUTCDate.toISOString()\n}\n\n//keep some consistency with scheduled publishing\n//https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/hooks/useTimeZone.tsx#L17\nexport const allTimezones = getTimeZones().map((tz) => {\n return {\n abbreviation: tz.abbreviation,\n alternativeName: tz.alternativeName,\n mainCities: tz.mainCities.join(', '),\n // Main time zone name 'Africa/Dar_es_Salaam'\n name: tz.name,\n // Time zone name with underscores removed\n namePretty: tz.name.replaceAll('_', ' '),\n offset: tz.currentTimeFormat.split(' ')[0],\n // all searchable text - this is transformed before being rendered in `<AutoComplete>`\n value: `${tz.currentTimeFormat} ${tz.abbreviation} ${tz.name}`,\n currentTimeOffsetInMinutes: tz.currentTimeOffsetInMinutes,\n group: tz.group,\n } as NormalizedTimeZone\n})\n","import {DateTimeInput, FormPatch, PatchEvent, InputProps, set, unset} from 'sanity'\n\nimport {getConstructedUTCDate, unlocalizeDateTime} from '../utils'\nimport {RichDate} from '../types'\nimport {formatInTimeZone, zonedTimeToUtc} from 'date-fns-tz'\n\ninterface RelativeDateTimePickerProps extends Omit<InputProps, 'renderDefault'> {\n dateValue?: RichDate\n}\n\nexport const RelativeDateTimePicker = (props: RelativeDateTimePickerProps) => {\n const value = props.dateValue\n const timezone = value?.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone\n /*\n * if our offset is not coming from a lib, we have to reverse it\n * to get the real offset used everywhere\n * https://momentjscom.readthedocs.io/en/latest/moment/03-manipulating/09-utc-offset/\n */\n const offset = value?.offset ?? new Date().getTimezoneOffset() * -1\n const handleDateChange = (patch: FormPatch | PatchEvent | FormPatch[]) => {\n const patches = []\n const newDatetime = (patch as unknown as {value: string})?.value\n if (!newDatetime || !('type' in patch) || patch.type !== 'set') {\n props.onChange(unset())\n return\n }\n\n //get what time the user \"meant\" to set without tz info\n //since the datepicker always localizes to the user's timezone\n const desiredDateTime = unlocalizeDateTime(\n newDatetime,\n Intl.DateTimeFormat().resolvedOptions().timeZone,\n )\n\n //use the user-selected timezone here\n const utcDate = zonedTimeToUtc(desiredDateTime, timezone).toISOString()\n const localDate = formatInTimeZone(utcDate, timezone, \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n\n patches.push(set(utcDate, ['utc']))\n patches.push(set(localDate, ['local']))\n\n if (!value?.timezone) {\n patches.push(set(timezone, ['timezone']))\n }\n\n if (!value?.offset) {\n patches.push(set(offset, ['offset']))\n }\n\n props.onChange(patches)\n }\n\n const dateToDisplay = value?.utc ? getConstructedUTCDate(value.utc, value.offset) : ''\n //@ts-expect-error -- slight mismatch in elementProps and renderDefault, but should line up in practice\n return <DateTimeInput {...props} onChange={handleDateChange} value={dateToDisplay} />\n}\n","import {SearchIcon} from '@sanity/icons'\nimport {ObjectInputProps, set} from 'sanity'\nimport {allTimezones, unlocalizeDateTime} from '../utils'\nimport {NormalizedTimeZone, RichDate} from '../types'\nimport {Autocomplete, Card, Text, Box} from '@sanity/ui'\nimport {formatInTimeZone, zonedTimeToUtc} from 'date-fns-tz'\n\ninterface TimezoneSelectorProps {\n onChange: Pick<ObjectInputProps, 'onChange'>['onChange']\n value?: RichDate\n}\n\nexport const TimezoneSelector = (props: TimezoneSelectorProps) => {\n const {onChange, value} = props\n const currentTz = allTimezones.find((tz) => tz.name === value?.timezone)\n const userTzName = Intl.DateTimeFormat().resolvedOptions().timeZone\n const userTz = (allTimezones.find((tz) => tz.name === userTzName) ??\n allTimezones.find((tz) => tz.group.includes(userTzName)))!\n\n const handleTimezoneChange = (selectedTz: string) => {\n const newTimezone =\n allTimezones.find((tz) => tz.value === selectedTz) ?? (userTz as NormalizedTimeZone)\n\n const offset = newTimezone.currentTimeOffsetInMinutes ?? 0\n const timezonePatch = set(newTimezone.name, ['timezone'])\n const offsetPatch = set(offset, ['offset'])\n const patches = [timezonePatch, offsetPatch]\n\n //then, recalculate UTC and local from \"old\" time with the new offset\n if (value?.utc) {\n const desiredDateTime = unlocalizeDateTime(value.utc, value.timezone)\n const newUtcDate = zonedTimeToUtc(desiredDateTime, newTimezone.name).toISOString()\n const newLocalDate = formatInTimeZone(\n newUtcDate,\n newTimezone.name,\n \"yyyy-MM-dd'T'HH:mm:ssXXX\",\n )\n patches.push(set(newUtcDate, ['utc']))\n patches.push(set(newLocalDate, ['local']))\n }\n onChange(patches)\n }\n\n return (\n //taken from Scheduled Publishing, again!\n //https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100\n <Box padding={4}>\n <Autocomplete\n fontSize={2}\n icon={SearchIcon}\n id=\"timezone\"\n onChange={handleTimezoneChange}\n openButton\n options={allTimezones}\n padding={4}\n placeholder=\"Search for a city or time zone\"\n popover={{\n boundaryElement: document.querySelector('body'),\n constrainSize: true,\n placement: 'bottom-start',\n }}\n renderOption={(option) => {\n return (\n <Card as=\"button\" padding={3}>\n <Text size={1} textOverflow=\"ellipsis\">\n <span>GMT{option.offset}</span>\n <span style={{fontWeight: 500, marginLeft: '1em'}}>{option.alternativeName}</span>\n <span style={{marginLeft: '1em'}}>{option.mainCities}</span>\n </Text>\n </Card>\n )\n }}\n renderValue={(_, option) => {\n if (!option) return ''\n return `${option.alternativeName} (${option.namePretty})`\n }}\n tabIndex={-1}\n value={currentTz?.value ?? userTz.value}\n />\n </Box>\n )\n}\n","import {Button} from '@sanity/ui'\nimport {EarthAmericasIcon} from '@sanity/icons'\nimport {allTimezones} from '../utils'\n\ninterface TimezoneButtonProps {\n onClick: () => void\n timezone: string\n}\n\nexport const TimezoneButton = (props: TimezoneButtonProps) => {\n const {onClick, timezone} = props\n const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone\n\n const label =\n allTimezones.find((tz) => tz.name === timezone)?.abbreviation ??\n allTimezones.find((tz) => tz.name === currentTimezone)?.abbreviation ??\n allTimezones.find((tz) => tz.group.includes(currentTimezone))?.abbreviation\n\n return (\n <Button\n fontSize={1}\n style={{width: '100%'}}\n justify={'flex-start'}\n icon={EarthAmericasIcon}\n mode=\"ghost\"\n onClick={onClick}\n text={`${label}`}\n aria-label=\"Select a timezone\"\n />\n )\n}\n","import {ObjectInputMember, ObjectInputProps} from 'sanity'\nimport {Box, Flex, Dialog} from '@sanity/ui'\nimport {RelativeDateTimePicker} from './RelativeDateTimePicker'\nimport {TimezoneSelector} from './TimezoneSelector'\nimport {useCallback, useState} from 'react'\nimport {TimezoneButton} from './TimezoneButton'\nimport {RichDate} from '../types'\n\nexport const RichDateInput = (props: ObjectInputProps) => {\n const {onChange, value, members, schemaType} = props\n const {options} = schemaType\n const localMember = members.find((member) => member.kind === 'field' && member.name === 'local')\n const timezoneMember = members.find(\n (member) => member.kind === 'field' && member.name === 'timezone',\n )\n const [timezoneSelectorOpen, setTimezoneSelectorOpen] = useState(false)\n const onClose = useCallback(() => setTimezoneSelectorOpen(false), [])\n const onOpen = useCallback(() => setTimezoneSelectorOpen(true), [])\n\n return (\n <>\n <Flex>\n <Box flex={[1, 2, 4]}>\n {localMember && (\n <ObjectInputMember\n {...props}\n member={localMember}\n renderInput={(renderInputProps) => (\n <RelativeDateTimePicker\n {...renderInputProps}\n dateValue={value as RichDate}\n schemaType={{...renderInputProps.schemaType, options}}\n onChange={onChange}\n />\n )}\n />\n )}\n </Box>\n <Box flex={[1]} marginLeft={[2, 2, 3, 4]}>\n {timezoneMember && (\n <ObjectInputMember\n {...props}\n member={timezoneMember}\n renderInput={() => (\n <TimezoneButton onClick={onOpen} timezone={value?.timezone ?? ''} />\n )}\n />\n )}\n </Box>\n </Flex>\n {timezoneSelectorOpen && (\n <Dialog onClose={onClose} header=\"Select a timezone\" id=\"timezone-select\" width={1}>\n <TimezoneSelector onChange={onChange} value={value as RichDate} />\n </Dialog>\n )}\n </>\n )\n}\n","import {\n DatetimeDefinition,\n ObjectDefinition,\n ObjectSchemaType,\n defineField,\n defineType,\n} from 'sanity'\nimport {RichDateInput} from './components/RichDateInput'\n\nconst richDateTypeName = 'richDate' as const\n\nexport type RichDateSchemaType = Omit<ObjectSchemaType, 'options'> & {\n options?: DatetimeDefinition['options']\n}\n\n/**\n * @public\n */\nexport interface RichDateDefinition extends Omit<ObjectDefinition, 'type' | 'fields' | 'options'> {\n type: typeof richDateTypeName\n options?: DatetimeDefinition['options']\n}\n\ndeclare module 'sanity' {\n //allows the custom input to be valid for the schema def\n export interface IntrinsicDefinitions {\n richDate: RichDateDefinition\n }\n}\n\nexport const richDateSchema = defineType({\n name: richDateTypeName,\n title: 'Rich Date',\n type: 'object',\n fields: [\n defineField({\n name: 'local',\n title: 'Local',\n type: 'string',\n }),\n defineField({\n name: 'utc',\n title: 'UTC',\n type: 'string',\n }),\n defineField({\n name: 'timezone',\n title: 'Timezone',\n type: 'string',\n }),\n defineField({\n name: 'offset',\n title: 'Offset',\n type: 'number',\n }),\n ],\n\n components: {\n input: RichDateInput,\n },\n})\n","import {definePlugin} from 'sanity'\nimport {richDateSchema, RichDateDefinition, RichDateSchemaType} from './schema'\nimport {RichDate} from './types'\n\nexport const richDate = definePlugin({\n name: 'v3-rich-date-input',\n schema: {\n types: [richDateSchema],\n },\n})\n\nexport type {RichDateDefinition, RichDateSchemaType, RichDate}\n"],"names":["unlocalizeDateTime","datetime","timezone","formatInTimeZone","getConstructedUTCDate","utc","offset","date","Date","currentOffset","getTimezoneOffset","diff","fakeUTCDate","getTime","toISOString","allTimezones","getTimeZones","map","tz","abbreviation","alternativeName","mainCities","join","name","namePretty","replaceAll","currentTimeFormat","split","value","concat","currentTimeOffsetInMinutes","group","RelativeDateTimePicker","props","_a","_b","dateValue","Intl","DateTimeFormat","resolvedOptions","timeZone","handleDateChange","patch","patches","newDatetime","type","onChange","unset","desiredDateTime","utcDate","zonedTimeToUtc","localDate","push","set","dateToDisplay","DateTimeInput","TimezoneSelector","currentTz","find","userTzName","userTz","includes","handleTimezoneChange","selectedTz","newTimezone","timezonePatch","offsetPatch","newUtcDate","newLocalDate","jsx","Box","padding","children","Autocomplete","fontSize","icon","SearchIcon","id","openButton","options","placeholder","popover","boundaryElement","document","querySelector","constrainSize","placement","renderOption","option","Card","as","jsxs","Text","size","textOverflow","style","fontWeight","marginLeft","renderValue","_","tabIndex","TimezoneButton","_c","_d","_e","onClick","currentTimezone","label","Button","width","justify","EarthAmericasIcon","mode","text","RichDateInput","members","schemaType","localMember","member","kind","timezoneMember","timezoneSelectorOpen","setTimezoneSelectorOpen","useState","onClose","useCallback","onOpen","Fragment","Flex","flex","ObjectInputMember","renderInput","renderInputProps","Dialog","header","richDateTypeName","richDateSchema","defineType","title","fields","defineField","components","input","richDate","definePlugin","schema","types"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/utils/index.ts","../src/components/RelativeDateTimePicker.tsx","../src/components/TimezoneButton.tsx","../src/components/TimezoneSelector.tsx","../src/components/RichDateInput.tsx","../src/schema.ts","../src/index.ts"],"sourcesContent":["import {getTimeZones} from '@vvo/tzdb'\nimport {formatInTimeZone} from 'date-fns-tz'\n\nimport {NormalizedTimeZone} from '../types'\n\nexport const unlocalizeDateTime = (datetime: string, timezone: string): string => {\n return formatInTimeZone(datetime, timezone, 'yyyy-MM-dd HH:mm:ss')\n}\n\n/* We have to \"fake\" a UTC date to make the datepicker look \"right\"\n * to the user. For example, if someone sets 7:00AM PST, which is 3PM UTC\n * and I am on the east coast, I want to have 12:00PM UTC, which will look like 7:00AM to me\n * In other words, UTC minus 3 hours, or (UTC(my offset - their offset))\n * this is purely cosmetic and should not be saved at all\n */\nexport const getConstructedUTCDate = (utc: string, offset: number): string => {\n const date = new Date(utc)\n const currentOffset = date.getTimezoneOffset() * -1\n const diff = currentOffset - offset\n const fakeUTCDate = new Date(date.getTime() - diff * 60 * 1000)\n return fakeUTCDate.toISOString()\n}\n\n//keep some consistency with scheduled publishing\n//https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/hooks/useTimeZone.tsx#L17\nexport const allTimezones = getTimeZones().map((tz) => {\n return {\n abbreviation: tz.abbreviation,\n alternativeName: tz.alternativeName,\n mainCities: tz.mainCities.join(', '),\n // Main time zone name 'Africa/Dar_es_Salaam'\n name: tz.name,\n // Time zone name with underscores removed\n namePretty: tz.name.replaceAll('_', ' '),\n offset: tz.currentTimeFormat.split(' ')[0],\n // all searchable text - this is transformed before being rendered in `<AutoComplete>`\n value: `${tz.currentTimeFormat} ${tz.abbreviation} ${tz.name}`,\n currentTimeOffsetInMinutes: tz.currentTimeOffsetInMinutes,\n group: tz.group,\n } as NormalizedTimeZone\n})\n","import {formatInTimeZone, getTimezoneOffset, zonedTimeToUtc} from 'date-fns-tz'\nimport {type ReactNode, useCallback} from 'react'\nimport {DateTimeInput, FormPatch, InputProps, PatchEvent, set, unset} from 'sanity'\n\nimport {RichDate} from '../types'\nimport {getConstructedUTCDate, unlocalizeDateTime} from '../utils'\n\ninterface RelativeDateTimePickerProps extends Omit<InputProps, 'renderDefault'> {\n dateValue?: RichDate\n}\nexport const RelativeDateTimePicker = (props: RelativeDateTimePickerProps): ReactNode => {\n const {dateValue: value, onChange} = props\n\n const handleDateChange = useCallback(\n (patch: FormPatch | PatchEvent | FormPatch[]) => {\n const timezone = value?.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone\n const newDatetime = (patch as unknown as {value: string})?.value\n if (!newDatetime || !('type' in patch) || patch.type !== 'set') {\n onChange(unset())\n return\n }\n\n /* get what time the user \"meant\" to set without tz info\n * right now, newDatetime is the time the user set plus\n * their current offset, not the timezone offset\n */\n const desiredDateTime = unlocalizeDateTime(\n newDatetime,\n Intl.DateTimeFormat().resolvedOptions().timeZone,\n )\n\n const newUtcDateObject = zonedTimeToUtc(desiredDateTime, timezone)\n // offset may have changed based on DST, capture that\n const newOffset = getTimezoneOffset(timezone, newUtcDateObject) / 60 / 1000\n const localDate = formatInTimeZone(newUtcDateObject, timezone, \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n\n const patches = []\n\n patches.push(set(newUtcDateObject.toISOString(), ['utc']))\n patches.push(set(localDate, ['local']))\n\n if (!value?.timezone) {\n patches.push(set(timezone, ['timezone']))\n }\n\n if (value?.offset !== newOffset) {\n patches.push(set(newOffset, ['offset']))\n }\n\n onChange(patches)\n },\n [onChange, value],\n )\n\n const dateToDisplay = value?.utc ? getConstructedUTCDate(value.utc, value.offset) : ''\n\n // @ts-expect-error -- slight mismatch in elementProps and renderDefault, but should line up in practice\n return <DateTimeInput {...props} onChange={handleDateChange} value={dateToDisplay} />\n}\n","import {EarthAmericasIcon} from '@sanity/icons'\nimport {Button} from '@sanity/ui'\nimport {type ReactNode} from 'react'\n\nimport {allTimezones} from '../utils'\n\ninterface TimezoneButtonProps {\n onClick: () => void\n timezone: string\n}\n\nexport const TimezoneButton = (props: TimezoneButtonProps): ReactNode => {\n const {onClick, timezone} = props\n const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone\n\n const label =\n allTimezones.find((tz) => tz.name === timezone)?.abbreviation ??\n allTimezones.find((tz) => tz.name === currentTimezone)?.abbreviation ??\n allTimezones.find((tz) => tz.group.includes(currentTimezone))?.abbreviation\n\n return (\n <Button\n fontSize={1}\n style={{width: '100%'}}\n justify={'flex-start'}\n icon={EarthAmericasIcon}\n mode=\"ghost\"\n onClick={onClick}\n text={`${label}`}\n aria-label=\"Select a timezone\"\n />\n )\n}\n","import {SearchIcon} from '@sanity/icons'\nimport {Autocomplete, Box, Card, Text} from '@sanity/ui'\nimport {formatInTimeZone, getTimezoneOffset, zonedTimeToUtc} from 'date-fns-tz'\nimport {type ReactNode, useCallback} from 'react'\nimport {ObjectInputProps, set} from 'sanity'\n\nimport {NormalizedTimeZone, RichDate} from '../types'\nimport {allTimezones, unlocalizeDateTime} from '../utils'\n\ninterface TimezoneSelectorProps {\n onChange: Pick<ObjectInputProps, 'onChange'>['onChange']\n value?: RichDate\n}\n\nexport const TimezoneSelector = (props: TimezoneSelectorProps): ReactNode => {\n const {onChange, value} = props\n const currentTz = allTimezones.find((tz) => tz.name === value?.timezone)\n const userTzName = Intl.DateTimeFormat().resolvedOptions().timeZone\n const userTz = (allTimezones.find((tz) => tz.name === userTzName) ??\n allTimezones.find((tz) => tz.group.includes(userTzName)))!\n\n const handleTimezoneChange = useCallback(\n (selectedTz: string) => {\n const newTimezone =\n allTimezones.find((tz) => tz.value === selectedTz) ?? (userTz as NormalizedTimeZone)\n\n const timezonePatch = set(newTimezone.name, ['timezone'])\n const patches = [timezonePatch]\n\n // then, recalculate UTC and local from \"old\" time with the new offset\n if (value?.utc) {\n const desiredDateTime = unlocalizeDateTime(value.utc, value.timezone)\n const newUtcDateObject = zonedTimeToUtc(desiredDateTime, newTimezone.name)\n const newOffset = getTimezoneOffset(newTimezone.name, newUtcDateObject) / 60 / 1000\n const newLocalDate = formatInTimeZone(\n newUtcDateObject.toISOString(),\n newTimezone.name,\n \"yyyy-MM-dd'T'HH:mm:ssXXX\",\n )\n patches.push(set(newUtcDateObject.toISOString(), ['utc']))\n patches.push(set(newLocalDate, ['local']))\n patches.push(set(newOffset, ['offset']))\n }\n onChange(patches)\n },\n [onChange, userTz, value],\n )\n\n return (\n // taken from Scheduled Publishing, again!\n // https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100\n <Box padding={4}>\n <Autocomplete\n fontSize={2}\n icon={SearchIcon}\n id=\"timezone\"\n onChange={handleTimezoneChange}\n openButton\n options={allTimezones}\n padding={4}\n placeholder=\"Search for a city or time zone\"\n popover={{\n boundaryElement: document.querySelector('body'),\n constrainSize: true,\n placement: 'bottom-start',\n }}\n // eslint-disable-next-line react/jsx-no-bind\n renderOption={(option) => {\n return (\n <Card as=\"button\" padding={3}>\n <Text size={1} textOverflow=\"ellipsis\">\n <span>GMT{option.offset}</span>\n <span style={{fontWeight: 500, marginLeft: '1em'}}>{option.alternativeName}</span>\n <span style={{marginLeft: '1em'}}>{option.mainCities}</span>\n </Text>\n </Card>\n )\n }}\n // eslint-disable-next-line react/jsx-no-bind\n renderValue={(_, option) => {\n if (!option) return ''\n return `${option.alternativeName} (${option.namePretty})`\n }}\n tabIndex={-1}\n value={currentTz?.value ?? userTz.value}\n />\n </Box>\n )\n}\n","import {Box, Dialog, Flex} from '@sanity/ui'\nimport {type ReactNode, useCallback, useState} from 'react'\nimport {ObjectInputMember, ObjectInputProps} from 'sanity'\n\nimport {RichDate} from '../types'\nimport {RelativeDateTimePicker} from './RelativeDateTimePicker'\nimport {TimezoneButton} from './TimezoneButton'\nimport {TimezoneSelector} from './TimezoneSelector'\n\nexport const RichDateInput = (props: ObjectInputProps): ReactNode => {\n const {onChange, value, members, schemaType} = props\n const {options} = schemaType\n const localMember = members.find((member) => member.kind === 'field' && member.name === 'local')\n const timezoneMember = members.find(\n (member) => member.kind === 'field' && member.name === 'timezone',\n )\n const [timezoneSelectorOpen, setTimezoneSelectorOpen] = useState(false)\n const onClose = useCallback(() => setTimezoneSelectorOpen(false), [])\n const onOpen = useCallback(() => setTimezoneSelectorOpen(true), [])\n\n return (\n <>\n <Flex>\n <Box flex={[1, 2, 4]}>\n {localMember && (\n <ObjectInputMember\n {...props}\n member={localMember}\n // eslint-disable-next-line react/jsx-no-bind\n renderInput={(renderInputProps) => (\n <RelativeDateTimePicker\n {...renderInputProps}\n dateValue={value as RichDate}\n schemaType={{...renderInputProps.schemaType, options}}\n onChange={onChange}\n />\n )}\n />\n )}\n </Box>\n <Box flex={[1]} marginLeft={[2, 2, 3, 4]}>\n {timezoneMember && (\n <ObjectInputMember\n {...props}\n member={timezoneMember}\n // eslint-disable-next-line react/jsx-no-bind\n renderInput={() => (\n <TimezoneButton onClick={onOpen} timezone={value?.timezone ?? ''} />\n )}\n />\n )}\n </Box>\n </Flex>\n {timezoneSelectorOpen && (\n <Dialog onClose={onClose} header=\"Select a timezone\" id=\"timezone-select\" width={1}>\n <TimezoneSelector onChange={onChange} value={value as RichDate} />\n </Dialog>\n )}\n </>\n )\n}\n","import {\n DatetimeDefinition,\n defineField,\n defineType,\n ObjectDefinition,\n ObjectSchemaType,\n} from 'sanity'\n\nimport {RichDateInput} from './components/RichDateInput'\n\nconst richDateTypeName = 'richDate' as const\n\nexport type RichDateSchemaType = Omit<ObjectSchemaType, 'options'> & {\n options?: DatetimeDefinition['options']\n}\n\n/**\n * @public\n */\nexport interface RichDateDefinition extends Omit<ObjectDefinition, 'type' | 'fields' | 'options'> {\n type: typeof richDateTypeName\n options?: DatetimeDefinition['options']\n}\n\ndeclare module 'sanity' {\n //allows the custom input to be valid for the schema def\n export interface IntrinsicDefinitions {\n richDate: RichDateDefinition\n }\n}\n\nexport const richDateSchema = defineType({\n name: richDateTypeName,\n title: 'Rich Date',\n type: 'object',\n fields: [\n defineField({\n name: 'local',\n title: 'Local',\n type: 'string',\n }),\n defineField({\n name: 'utc',\n title: 'UTC',\n type: 'string',\n }),\n defineField({\n name: 'timezone',\n title: 'Timezone',\n type: 'string',\n }),\n defineField({\n name: 'offset',\n title: 'Offset',\n type: 'number',\n }),\n ],\n\n components: {\n input: RichDateInput,\n },\n})\n","import {definePlugin} from 'sanity'\n\nimport {RichDateDefinition, richDateSchema, RichDateSchemaType} from './schema'\nimport {RichDate} from './types'\n\nexport const richDate = definePlugin({\n name: 'v3-rich-date-input',\n schema: {\n types: [richDateSchema],\n },\n})\n\nexport type {RichDate, RichDateDefinition, RichDateSchemaType}\n"],"names":["unlocalizeDateTime","datetime","timezone","formatInTimeZone","getConstructedUTCDate","utc","offset","date","Date","currentOffset","getTimezoneOffset","diff","fakeUTCDate","getTime","toISOString","allTimezones","getTimeZones","map","tz","abbreviation","alternativeName","mainCities","join","name","namePretty","replaceAll","currentTimeFormat","split","value","concat","currentTimeOffsetInMinutes","group","RelativeDateTimePicker","props","dateValue","onChange","handleDateChange","useCallback","patch","_a","Intl","DateTimeFormat","resolvedOptions","timeZone","newDatetime","type","unset","desiredDateTime","newUtcDateObject","zonedTimeToUtc","newOffset","localDate","patches","push","set","dateToDisplay","DateTimeInput","TimezoneButton","_b","_c","_d","_e","onClick","currentTimezone","label","find","includes","jsx","Button","fontSize","style","width","justify","icon","EarthAmericasIcon","mode","text","TimezoneSelector","currentTz","userTzName","userTz","handleTimezoneChange","selectedTz","newTimezone","timezonePatch","newLocalDate","Box","padding","children","Autocomplete","SearchIcon","id","openButton","options","placeholder","popover","boundaryElement","document","querySelector","constrainSize","placement","renderOption","option","Card","as","jsxs","Text","size","textOverflow","fontWeight","marginLeft","renderValue","_","tabIndex","RichDateInput","members","schemaType","localMember","member","kind","timezoneMember","timezoneSelectorOpen","setTimezoneSelectorOpen","useState","onClose","onOpen","Fragment","Flex","flex","ObjectInputMember","renderInput","renderInputProps","Dialog","header","richDateTypeName","richDateSchema","defineType","title","fields","defineField","components","input","richDate","definePlugin","schema","types"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -6,16 +6,16 @@ Object.defineProperty(exports, '__esModule', {
|
|
|
6
6
|
var sanity = require('sanity');
|
|
7
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
8
|
var ui = require('@sanity/ui');
|
|
9
|
-
var
|
|
9
|
+
var react = require('react');
|
|
10
10
|
var dateFnsTz = require('date-fns-tz');
|
|
11
|
+
var tzdb = require('@vvo/tzdb');
|
|
11
12
|
var icons = require('@sanity/icons');
|
|
12
|
-
var react = require('react');
|
|
13
13
|
const unlocalizeDateTime = (datetime, timezone) => {
|
|
14
14
|
return dateFnsTz.formatInTimeZone(datetime, timezone, "yyyy-MM-dd HH:mm:ss");
|
|
15
15
|
};
|
|
16
16
|
const getConstructedUTCDate = (utc, offset) => {
|
|
17
17
|
const date = new Date(utc);
|
|
18
|
-
const currentOffset =
|
|
18
|
+
const currentOffset = date.getTimezoneOffset() * -1;
|
|
19
19
|
const diff = currentOffset - offset;
|
|
20
20
|
const fakeUTCDate = new Date(date.getTime() - diff * 60 * 1e3);
|
|
21
21
|
return fakeUTCDate.toISOString();
|
|
@@ -37,30 +37,33 @@ const allTimezones = tzdb.getTimeZones().map(tz => {
|
|
|
37
37
|
};
|
|
38
38
|
});
|
|
39
39
|
const RelativeDateTimePicker = props => {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const handleDateChange = patch => {
|
|
45
|
-
|
|
40
|
+
const {
|
|
41
|
+
dateValue: value,
|
|
42
|
+
onChange
|
|
43
|
+
} = props;
|
|
44
|
+
const handleDateChange = react.useCallback(patch => {
|
|
45
|
+
var _a;
|
|
46
|
+
const timezone = (_a = value == null ? void 0 : value.timezone) != null ? _a : Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
46
47
|
const newDatetime = patch == null ? void 0 : patch.value;
|
|
47
48
|
if (!newDatetime || !("type" in patch) || patch.type !== "set") {
|
|
48
|
-
|
|
49
|
+
onChange(sanity.unset());
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
51
52
|
const desiredDateTime = unlocalizeDateTime(newDatetime, Intl.DateTimeFormat().resolvedOptions().timeZone);
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
53
|
+
const newUtcDateObject = dateFnsTz.zonedTimeToUtc(desiredDateTime, timezone);
|
|
54
|
+
const newOffset = dateFnsTz.getTimezoneOffset(timezone, newUtcDateObject) / 60 / 1e3;
|
|
55
|
+
const localDate = dateFnsTz.formatInTimeZone(newUtcDateObject, timezone, "yyyy-MM-dd'T'HH:mm:ssXXX");
|
|
56
|
+
const patches = [];
|
|
57
|
+
patches.push(sanity.set(newUtcDateObject.toISOString(), ["utc"]));
|
|
55
58
|
patches.push(sanity.set(localDate, ["local"]));
|
|
56
59
|
if (!(value == null ? void 0 : value.timezone)) {
|
|
57
60
|
patches.push(sanity.set(timezone, ["timezone"]));
|
|
58
61
|
}
|
|
59
|
-
if (
|
|
60
|
-
patches.push(sanity.set(
|
|
62
|
+
if ((value == null ? void 0 : value.offset) !== newOffset) {
|
|
63
|
+
patches.push(sanity.set(newOffset, ["offset"]));
|
|
61
64
|
}
|
|
62
|
-
|
|
63
|
-
};
|
|
65
|
+
onChange(patches);
|
|
66
|
+
}, [onChange, value]);
|
|
64
67
|
const dateToDisplay = (value == null ? void 0 : value.utc) ? getConstructedUTCDate(value.utc, value.offset) : "";
|
|
65
68
|
return /* @__PURE__ */jsxRuntime.jsx(sanity.DateTimeInput, {
|
|
66
69
|
...props,
|
|
@@ -68,6 +71,27 @@ const RelativeDateTimePicker = props => {
|
|
|
68
71
|
value: dateToDisplay
|
|
69
72
|
});
|
|
70
73
|
};
|
|
74
|
+
const TimezoneButton = props => {
|
|
75
|
+
var _a, _b, _c, _d, _e;
|
|
76
|
+
const {
|
|
77
|
+
onClick,
|
|
78
|
+
timezone
|
|
79
|
+
} = props;
|
|
80
|
+
const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
81
|
+
const label = (_e = (_c = (_a = allTimezones.find(tz => tz.name === timezone)) == null ? void 0 : _a.abbreviation) != null ? _c : (_b = allTimezones.find(tz => tz.name === currentTimezone)) == null ? void 0 : _b.abbreviation) != null ? _e : (_d = allTimezones.find(tz => tz.group.includes(currentTimezone))) == null ? void 0 : _d.abbreviation;
|
|
82
|
+
return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
83
|
+
fontSize: 1,
|
|
84
|
+
style: {
|
|
85
|
+
width: "100%"
|
|
86
|
+
},
|
|
87
|
+
justify: "flex-start",
|
|
88
|
+
icon: icons.EarthAmericasIcon,
|
|
89
|
+
mode: "ghost",
|
|
90
|
+
onClick,
|
|
91
|
+
text: "".concat(label),
|
|
92
|
+
"aria-label": "Select a timezone"
|
|
93
|
+
});
|
|
94
|
+
};
|
|
71
95
|
const TimezoneSelector = props => {
|
|
72
96
|
var _a, _b;
|
|
73
97
|
const {
|
|
@@ -77,25 +101,25 @@ const TimezoneSelector = props => {
|
|
|
77
101
|
const currentTz = allTimezones.find(tz => tz.name === (value == null ? void 0 : value.timezone));
|
|
78
102
|
const userTzName = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
79
103
|
const userTz = (_a = allTimezones.find(tz => tz.name === userTzName)) != null ? _a : allTimezones.find(tz => tz.group.includes(userTzName));
|
|
80
|
-
const handleTimezoneChange = selectedTz => {
|
|
81
|
-
var _a2
|
|
104
|
+
const handleTimezoneChange = react.useCallback(selectedTz => {
|
|
105
|
+
var _a2;
|
|
82
106
|
const newTimezone = (_a2 = allTimezones.find(tz => tz.value === selectedTz)) != null ? _a2 : userTz;
|
|
83
|
-
const offset = (_b2 = newTimezone.currentTimeOffsetInMinutes) != null ? _b2 : 0;
|
|
84
107
|
const timezonePatch = sanity.set(newTimezone.name, ["timezone"]);
|
|
85
|
-
const
|
|
86
|
-
const patches = [timezonePatch, offsetPatch];
|
|
108
|
+
const patches = [timezonePatch];
|
|
87
109
|
if (value == null ? void 0 : value.utc) {
|
|
88
110
|
const desiredDateTime = unlocalizeDateTime(value.utc, value.timezone);
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
111
|
+
const newUtcDateObject = dateFnsTz.zonedTimeToUtc(desiredDateTime, newTimezone.name);
|
|
112
|
+
const newOffset = dateFnsTz.getTimezoneOffset(newTimezone.name, newUtcDateObject) / 60 / 1e3;
|
|
113
|
+
const newLocalDate = dateFnsTz.formatInTimeZone(newUtcDateObject.toISOString(), newTimezone.name, "yyyy-MM-dd'T'HH:mm:ssXXX");
|
|
114
|
+
patches.push(sanity.set(newUtcDateObject.toISOString(), ["utc"]));
|
|
92
115
|
patches.push(sanity.set(newLocalDate, ["local"]));
|
|
116
|
+
patches.push(sanity.set(newOffset, ["offset"]));
|
|
93
117
|
}
|
|
94
118
|
onChange(patches);
|
|
95
|
-
};
|
|
119
|
+
}, [onChange, userTz, value]);
|
|
96
120
|
return (
|
|
97
|
-
//taken from Scheduled Publishing, again!
|
|
98
|
-
//https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100
|
|
121
|
+
// taken from Scheduled Publishing, again!
|
|
122
|
+
// https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100
|
|
99
123
|
/* @__PURE__ */
|
|
100
124
|
jsxRuntime.jsx(ui.Box, {
|
|
101
125
|
padding: 4,
|
|
@@ -147,27 +171,6 @@ const TimezoneSelector = props => {
|
|
|
147
171
|
})
|
|
148
172
|
);
|
|
149
173
|
};
|
|
150
|
-
const TimezoneButton = props => {
|
|
151
|
-
var _a, _b, _c, _d, _e;
|
|
152
|
-
const {
|
|
153
|
-
onClick,
|
|
154
|
-
timezone
|
|
155
|
-
} = props;
|
|
156
|
-
const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
157
|
-
const label = (_e = (_c = (_a = allTimezones.find(tz => tz.name === timezone)) == null ? void 0 : _a.abbreviation) != null ? _c : (_b = allTimezones.find(tz => tz.name === currentTimezone)) == null ? void 0 : _b.abbreviation) != null ? _e : (_d = allTimezones.find(tz => tz.group.includes(currentTimezone))) == null ? void 0 : _d.abbreviation;
|
|
158
|
-
return /* @__PURE__ */jsxRuntime.jsx(ui.Button, {
|
|
159
|
-
fontSize: 1,
|
|
160
|
-
style: {
|
|
161
|
-
width: "100%"
|
|
162
|
-
},
|
|
163
|
-
justify: "flex-start",
|
|
164
|
-
icon: icons.EarthAmericasIcon,
|
|
165
|
-
mode: "ghost",
|
|
166
|
-
onClick,
|
|
167
|
-
text: "".concat(label),
|
|
168
|
-
"aria-label": "Select a timezone"
|
|
169
|
-
});
|
|
170
|
-
};
|
|
171
174
|
const RichDateInput = props => {
|
|
172
175
|
const {
|
|
173
176
|
onChange,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils/index.ts","../src/components/RelativeDateTimePicker.tsx","../src/components/TimezoneSelector.tsx","../src/components/TimezoneButton.tsx","../src/components/RichDateInput.tsx","../src/schema.ts","../src/index.ts"],"sourcesContent":["import {getTimeZones} from '@vvo/tzdb'\nimport {NormalizedTimeZone} from '../types'\nimport {formatInTimeZone} from 'date-fns-tz'\n\nexport const unlocalizeDateTime = (datetime: string, timezone: string): string => {\n return formatInTimeZone(datetime, timezone, 'yyyy-MM-dd HH:mm:ss')\n}\n\n/* We have to \"fake\" a UTC date to make the datepicker look \"right\"\n * to the user. For example, if someone sets 7:00AM PST, which is 3PM UTC\n * and I am on the east coast, I want to have 12:00PM UTC, which will look like 7:00AM to me\n * In other words, UTC minus 3 hours, or (UTC(my offset - their offset))\n * this is purely cosmetic and should not be saved at all\n */\nexport const getConstructedUTCDate = (utc: string, offset: number): string => {\n const date = new Date(utc)\n const currentOffset = new Date().getTimezoneOffset() * -1\n const diff = currentOffset - offset\n const fakeUTCDate = new Date(date.getTime() - diff * 60 * 1000)\n return fakeUTCDate.toISOString()\n}\n\n//keep some consistency with scheduled publishing\n//https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/hooks/useTimeZone.tsx#L17\nexport const allTimezones = getTimeZones().map((tz) => {\n return {\n abbreviation: tz.abbreviation,\n alternativeName: tz.alternativeName,\n mainCities: tz.mainCities.join(', '),\n // Main time zone name 'Africa/Dar_es_Salaam'\n name: tz.name,\n // Time zone name with underscores removed\n namePretty: tz.name.replaceAll('_', ' '),\n offset: tz.currentTimeFormat.split(' ')[0],\n // all searchable text - this is transformed before being rendered in `<AutoComplete>`\n value: `${tz.currentTimeFormat} ${tz.abbreviation} ${tz.name}`,\n currentTimeOffsetInMinutes: tz.currentTimeOffsetInMinutes,\n group: tz.group,\n } as NormalizedTimeZone\n})\n","import {DateTimeInput, FormPatch, PatchEvent, InputProps, set, unset} from 'sanity'\n\nimport {getConstructedUTCDate, unlocalizeDateTime} from '../utils'\nimport {RichDate} from '../types'\nimport {formatInTimeZone, zonedTimeToUtc} from 'date-fns-tz'\n\ninterface RelativeDateTimePickerProps extends Omit<InputProps, 'renderDefault'> {\n dateValue?: RichDate\n}\n\nexport const RelativeDateTimePicker = (props: RelativeDateTimePickerProps) => {\n const value = props.dateValue\n const timezone = value?.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone\n /*\n * if our offset is not coming from a lib, we have to reverse it\n * to get the real offset used everywhere\n * https://momentjscom.readthedocs.io/en/latest/moment/03-manipulating/09-utc-offset/\n */\n const offset = value?.offset ?? new Date().getTimezoneOffset() * -1\n const handleDateChange = (patch: FormPatch | PatchEvent | FormPatch[]) => {\n const patches = []\n const newDatetime = (patch as unknown as {value: string})?.value\n if (!newDatetime || !('type' in patch) || patch.type !== 'set') {\n props.onChange(unset())\n return\n }\n\n //get what time the user \"meant\" to set without tz info\n //since the datepicker always localizes to the user's timezone\n const desiredDateTime = unlocalizeDateTime(\n newDatetime,\n Intl.DateTimeFormat().resolvedOptions().timeZone,\n )\n\n //use the user-selected timezone here\n const utcDate = zonedTimeToUtc(desiredDateTime, timezone).toISOString()\n const localDate = formatInTimeZone(utcDate, timezone, \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n\n patches.push(set(utcDate, ['utc']))\n patches.push(set(localDate, ['local']))\n\n if (!value?.timezone) {\n patches.push(set(timezone, ['timezone']))\n }\n\n if (!value?.offset) {\n patches.push(set(offset, ['offset']))\n }\n\n props.onChange(patches)\n }\n\n const dateToDisplay = value?.utc ? getConstructedUTCDate(value.utc, value.offset) : ''\n //@ts-expect-error -- slight mismatch in elementProps and renderDefault, but should line up in practice\n return <DateTimeInput {...props} onChange={handleDateChange} value={dateToDisplay} />\n}\n","import {SearchIcon} from '@sanity/icons'\nimport {ObjectInputProps, set} from 'sanity'\nimport {allTimezones, unlocalizeDateTime} from '../utils'\nimport {NormalizedTimeZone, RichDate} from '../types'\nimport {Autocomplete, Card, Text, Box} from '@sanity/ui'\nimport {formatInTimeZone, zonedTimeToUtc} from 'date-fns-tz'\n\ninterface TimezoneSelectorProps {\n onChange: Pick<ObjectInputProps, 'onChange'>['onChange']\n value?: RichDate\n}\n\nexport const TimezoneSelector = (props: TimezoneSelectorProps) => {\n const {onChange, value} = props\n const currentTz = allTimezones.find((tz) => tz.name === value?.timezone)\n const userTzName = Intl.DateTimeFormat().resolvedOptions().timeZone\n const userTz = (allTimezones.find((tz) => tz.name === userTzName) ??\n allTimezones.find((tz) => tz.group.includes(userTzName)))!\n\n const handleTimezoneChange = (selectedTz: string) => {\n const newTimezone =\n allTimezones.find((tz) => tz.value === selectedTz) ?? (userTz as NormalizedTimeZone)\n\n const offset = newTimezone.currentTimeOffsetInMinutes ?? 0\n const timezonePatch = set(newTimezone.name, ['timezone'])\n const offsetPatch = set(offset, ['offset'])\n const patches = [timezonePatch, offsetPatch]\n\n //then, recalculate UTC and local from \"old\" time with the new offset\n if (value?.utc) {\n const desiredDateTime = unlocalizeDateTime(value.utc, value.timezone)\n const newUtcDate = zonedTimeToUtc(desiredDateTime, newTimezone.name).toISOString()\n const newLocalDate = formatInTimeZone(\n newUtcDate,\n newTimezone.name,\n \"yyyy-MM-dd'T'HH:mm:ssXXX\",\n )\n patches.push(set(newUtcDate, ['utc']))\n patches.push(set(newLocalDate, ['local']))\n }\n onChange(patches)\n }\n\n return (\n //taken from Scheduled Publishing, again!\n //https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100\n <Box padding={4}>\n <Autocomplete\n fontSize={2}\n icon={SearchIcon}\n id=\"timezone\"\n onChange={handleTimezoneChange}\n openButton\n options={allTimezones}\n padding={4}\n placeholder=\"Search for a city or time zone\"\n popover={{\n boundaryElement: document.querySelector('body'),\n constrainSize: true,\n placement: 'bottom-start',\n }}\n renderOption={(option) => {\n return (\n <Card as=\"button\" padding={3}>\n <Text size={1} textOverflow=\"ellipsis\">\n <span>GMT{option.offset}</span>\n <span style={{fontWeight: 500, marginLeft: '1em'}}>{option.alternativeName}</span>\n <span style={{marginLeft: '1em'}}>{option.mainCities}</span>\n </Text>\n </Card>\n )\n }}\n renderValue={(_, option) => {\n if (!option) return ''\n return `${option.alternativeName} (${option.namePretty})`\n }}\n tabIndex={-1}\n value={currentTz?.value ?? userTz.value}\n />\n </Box>\n )\n}\n","import {Button} from '@sanity/ui'\nimport {EarthAmericasIcon} from '@sanity/icons'\nimport {allTimezones} from '../utils'\n\ninterface TimezoneButtonProps {\n onClick: () => void\n timezone: string\n}\n\nexport const TimezoneButton = (props: TimezoneButtonProps) => {\n const {onClick, timezone} = props\n const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone\n\n const label =\n allTimezones.find((tz) => tz.name === timezone)?.abbreviation ??\n allTimezones.find((tz) => tz.name === currentTimezone)?.abbreviation ??\n allTimezones.find((tz) => tz.group.includes(currentTimezone))?.abbreviation\n\n return (\n <Button\n fontSize={1}\n style={{width: '100%'}}\n justify={'flex-start'}\n icon={EarthAmericasIcon}\n mode=\"ghost\"\n onClick={onClick}\n text={`${label}`}\n aria-label=\"Select a timezone\"\n />\n )\n}\n","import {ObjectInputMember, ObjectInputProps} from 'sanity'\nimport {Box, Flex, Dialog} from '@sanity/ui'\nimport {RelativeDateTimePicker} from './RelativeDateTimePicker'\nimport {TimezoneSelector} from './TimezoneSelector'\nimport {useCallback, useState} from 'react'\nimport {TimezoneButton} from './TimezoneButton'\nimport {RichDate} from '../types'\n\nexport const RichDateInput = (props: ObjectInputProps) => {\n const {onChange, value, members, schemaType} = props\n const {options} = schemaType\n const localMember = members.find((member) => member.kind === 'field' && member.name === 'local')\n const timezoneMember = members.find(\n (member) => member.kind === 'field' && member.name === 'timezone',\n )\n const [timezoneSelectorOpen, setTimezoneSelectorOpen] = useState(false)\n const onClose = useCallback(() => setTimezoneSelectorOpen(false), [])\n const onOpen = useCallback(() => setTimezoneSelectorOpen(true), [])\n\n return (\n <>\n <Flex>\n <Box flex={[1, 2, 4]}>\n {localMember && (\n <ObjectInputMember\n {...props}\n member={localMember}\n renderInput={(renderInputProps) => (\n <RelativeDateTimePicker\n {...renderInputProps}\n dateValue={value as RichDate}\n schemaType={{...renderInputProps.schemaType, options}}\n onChange={onChange}\n />\n )}\n />\n )}\n </Box>\n <Box flex={[1]} marginLeft={[2, 2, 3, 4]}>\n {timezoneMember && (\n <ObjectInputMember\n {...props}\n member={timezoneMember}\n renderInput={() => (\n <TimezoneButton onClick={onOpen} timezone={value?.timezone ?? ''} />\n )}\n />\n )}\n </Box>\n </Flex>\n {timezoneSelectorOpen && (\n <Dialog onClose={onClose} header=\"Select a timezone\" id=\"timezone-select\" width={1}>\n <TimezoneSelector onChange={onChange} value={value as RichDate} />\n </Dialog>\n )}\n </>\n )\n}\n","import {\n DatetimeDefinition,\n ObjectDefinition,\n ObjectSchemaType,\n defineField,\n defineType,\n} from 'sanity'\nimport {RichDateInput} from './components/RichDateInput'\n\nconst richDateTypeName = 'richDate' as const\n\nexport type RichDateSchemaType = Omit<ObjectSchemaType, 'options'> & {\n options?: DatetimeDefinition['options']\n}\n\n/**\n * @public\n */\nexport interface RichDateDefinition extends Omit<ObjectDefinition, 'type' | 'fields' | 'options'> {\n type: typeof richDateTypeName\n options?: DatetimeDefinition['options']\n}\n\ndeclare module 'sanity' {\n //allows the custom input to be valid for the schema def\n export interface IntrinsicDefinitions {\n richDate: RichDateDefinition\n }\n}\n\nexport const richDateSchema = defineType({\n name: richDateTypeName,\n title: 'Rich Date',\n type: 'object',\n fields: [\n defineField({\n name: 'local',\n title: 'Local',\n type: 'string',\n }),\n defineField({\n name: 'utc',\n title: 'UTC',\n type: 'string',\n }),\n defineField({\n name: 'timezone',\n title: 'Timezone',\n type: 'string',\n }),\n defineField({\n name: 'offset',\n title: 'Offset',\n type: 'number',\n }),\n ],\n\n components: {\n input: RichDateInput,\n },\n})\n","import {definePlugin} from 'sanity'\nimport {richDateSchema, RichDateDefinition, RichDateSchemaType} from './schema'\nimport {RichDate} from './types'\n\nexport const richDate = definePlugin({\n name: 'v3-rich-date-input',\n schema: {\n types: [richDateSchema],\n },\n})\n\nexport type {RichDateDefinition, RichDateSchemaType, RichDate}\n"],"names":["unlocalizeDateTime","datetime","timezone","formatInTimeZone","getConstructedUTCDate","utc","offset","date","Date","currentOffset","getTimezoneOffset","diff","fakeUTCDate","getTime","toISOString","allTimezones","getTimeZones","map","tz","abbreviation","alternativeName","mainCities","join","name","namePretty","replaceAll","currentTimeFormat","split","value","concat","currentTimeOffsetInMinutes","group","RelativeDateTimePicker","props","_a","_b","dateValue","Intl","DateTimeFormat","resolvedOptions","timeZone","handleDateChange","patch","patches","newDatetime","type","onChange","unset","desiredDateTime","utcDate","zonedTimeToUtc","localDate","push","set","dateToDisplay","DateTimeInput","TimezoneSelector","currentTz","find","userTzName","userTz","includes","handleTimezoneChange","selectedTz","newTimezone","timezonePatch","offsetPatch","newUtcDate","newLocalDate","jsx","Box","padding","children","Autocomplete","fontSize","icon","SearchIcon","id","openButton","options","placeholder","popover","boundaryElement","document","querySelector","constrainSize","placement","renderOption","option","Card","as","jsxs","Text","size","textOverflow","style","fontWeight","marginLeft","renderValue","_","tabIndex","TimezoneButton","_c","_d","_e","onClick","currentTimezone","label","Button","width","justify","EarthAmericasIcon","mode","text","RichDateInput","members","schemaType","localMember","member","kind","timezoneMember","timezoneSelectorOpen","setTimezoneSelectorOpen","useState","onClose","useCallback","onOpen","Fragment","Flex","flex","ObjectInputMember","renderInput","renderInputProps","Dialog","header","richDateTypeName","richDateSchema","defineType","title","fields","defineField","components","input","richDate","definePlugin","schema","types"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils/index.ts","../src/components/RelativeDateTimePicker.tsx","../src/components/TimezoneButton.tsx","../src/components/TimezoneSelector.tsx","../src/components/RichDateInput.tsx","../src/schema.ts","../src/index.ts"],"sourcesContent":["import {getTimeZones} from '@vvo/tzdb'\nimport {formatInTimeZone} from 'date-fns-tz'\n\nimport {NormalizedTimeZone} from '../types'\n\nexport const unlocalizeDateTime = (datetime: string, timezone: string): string => {\n return formatInTimeZone(datetime, timezone, 'yyyy-MM-dd HH:mm:ss')\n}\n\n/* We have to \"fake\" a UTC date to make the datepicker look \"right\"\n * to the user. For example, if someone sets 7:00AM PST, which is 3PM UTC\n * and I am on the east coast, I want to have 12:00PM UTC, which will look like 7:00AM to me\n * In other words, UTC minus 3 hours, or (UTC(my offset - their offset))\n * this is purely cosmetic and should not be saved at all\n */\nexport const getConstructedUTCDate = (utc: string, offset: number): string => {\n const date = new Date(utc)\n const currentOffset = date.getTimezoneOffset() * -1\n const diff = currentOffset - offset\n const fakeUTCDate = new Date(date.getTime() - diff * 60 * 1000)\n return fakeUTCDate.toISOString()\n}\n\n//keep some consistency with scheduled publishing\n//https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/hooks/useTimeZone.tsx#L17\nexport const allTimezones = getTimeZones().map((tz) => {\n return {\n abbreviation: tz.abbreviation,\n alternativeName: tz.alternativeName,\n mainCities: tz.mainCities.join(', '),\n // Main time zone name 'Africa/Dar_es_Salaam'\n name: tz.name,\n // Time zone name with underscores removed\n namePretty: tz.name.replaceAll('_', ' '),\n offset: tz.currentTimeFormat.split(' ')[0],\n // all searchable text - this is transformed before being rendered in `<AutoComplete>`\n value: `${tz.currentTimeFormat} ${tz.abbreviation} ${tz.name}`,\n currentTimeOffsetInMinutes: tz.currentTimeOffsetInMinutes,\n group: tz.group,\n } as NormalizedTimeZone\n})\n","import {formatInTimeZone, getTimezoneOffset, zonedTimeToUtc} from 'date-fns-tz'\nimport {type ReactNode, useCallback} from 'react'\nimport {DateTimeInput, FormPatch, InputProps, PatchEvent, set, unset} from 'sanity'\n\nimport {RichDate} from '../types'\nimport {getConstructedUTCDate, unlocalizeDateTime} from '../utils'\n\ninterface RelativeDateTimePickerProps extends Omit<InputProps, 'renderDefault'> {\n dateValue?: RichDate\n}\nexport const RelativeDateTimePicker = (props: RelativeDateTimePickerProps): ReactNode => {\n const {dateValue: value, onChange} = props\n\n const handleDateChange = useCallback(\n (patch: FormPatch | PatchEvent | FormPatch[]) => {\n const timezone = value?.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone\n const newDatetime = (patch as unknown as {value: string})?.value\n if (!newDatetime || !('type' in patch) || patch.type !== 'set') {\n onChange(unset())\n return\n }\n\n /* get what time the user \"meant\" to set without tz info\n * right now, newDatetime is the time the user set plus\n * their current offset, not the timezone offset\n */\n const desiredDateTime = unlocalizeDateTime(\n newDatetime,\n Intl.DateTimeFormat().resolvedOptions().timeZone,\n )\n\n const newUtcDateObject = zonedTimeToUtc(desiredDateTime, timezone)\n // offset may have changed based on DST, capture that\n const newOffset = getTimezoneOffset(timezone, newUtcDateObject) / 60 / 1000\n const localDate = formatInTimeZone(newUtcDateObject, timezone, \"yyyy-MM-dd'T'HH:mm:ssXXX\")\n\n const patches = []\n\n patches.push(set(newUtcDateObject.toISOString(), ['utc']))\n patches.push(set(localDate, ['local']))\n\n if (!value?.timezone) {\n patches.push(set(timezone, ['timezone']))\n }\n\n if (value?.offset !== newOffset) {\n patches.push(set(newOffset, ['offset']))\n }\n\n onChange(patches)\n },\n [onChange, value],\n )\n\n const dateToDisplay = value?.utc ? getConstructedUTCDate(value.utc, value.offset) : ''\n\n // @ts-expect-error -- slight mismatch in elementProps and renderDefault, but should line up in practice\n return <DateTimeInput {...props} onChange={handleDateChange} value={dateToDisplay} />\n}\n","import {EarthAmericasIcon} from '@sanity/icons'\nimport {Button} from '@sanity/ui'\nimport {type ReactNode} from 'react'\n\nimport {allTimezones} from '../utils'\n\ninterface TimezoneButtonProps {\n onClick: () => void\n timezone: string\n}\n\nexport const TimezoneButton = (props: TimezoneButtonProps): ReactNode => {\n const {onClick, timezone} = props\n const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone\n\n const label =\n allTimezones.find((tz) => tz.name === timezone)?.abbreviation ??\n allTimezones.find((tz) => tz.name === currentTimezone)?.abbreviation ??\n allTimezones.find((tz) => tz.group.includes(currentTimezone))?.abbreviation\n\n return (\n <Button\n fontSize={1}\n style={{width: '100%'}}\n justify={'flex-start'}\n icon={EarthAmericasIcon}\n mode=\"ghost\"\n onClick={onClick}\n text={`${label}`}\n aria-label=\"Select a timezone\"\n />\n )\n}\n","import {SearchIcon} from '@sanity/icons'\nimport {Autocomplete, Box, Card, Text} from '@sanity/ui'\nimport {formatInTimeZone, getTimezoneOffset, zonedTimeToUtc} from 'date-fns-tz'\nimport {type ReactNode, useCallback} from 'react'\nimport {ObjectInputProps, set} from 'sanity'\n\nimport {NormalizedTimeZone, RichDate} from '../types'\nimport {allTimezones, unlocalizeDateTime} from '../utils'\n\ninterface TimezoneSelectorProps {\n onChange: Pick<ObjectInputProps, 'onChange'>['onChange']\n value?: RichDate\n}\n\nexport const TimezoneSelector = (props: TimezoneSelectorProps): ReactNode => {\n const {onChange, value} = props\n const currentTz = allTimezones.find((tz) => tz.name === value?.timezone)\n const userTzName = Intl.DateTimeFormat().resolvedOptions().timeZone\n const userTz = (allTimezones.find((tz) => tz.name === userTzName) ??\n allTimezones.find((tz) => tz.group.includes(userTzName)))!\n\n const handleTimezoneChange = useCallback(\n (selectedTz: string) => {\n const newTimezone =\n allTimezones.find((tz) => tz.value === selectedTz) ?? (userTz as NormalizedTimeZone)\n\n const timezonePatch = set(newTimezone.name, ['timezone'])\n const patches = [timezonePatch]\n\n // then, recalculate UTC and local from \"old\" time with the new offset\n if (value?.utc) {\n const desiredDateTime = unlocalizeDateTime(value.utc, value.timezone)\n const newUtcDateObject = zonedTimeToUtc(desiredDateTime, newTimezone.name)\n const newOffset = getTimezoneOffset(newTimezone.name, newUtcDateObject) / 60 / 1000\n const newLocalDate = formatInTimeZone(\n newUtcDateObject.toISOString(),\n newTimezone.name,\n \"yyyy-MM-dd'T'HH:mm:ssXXX\",\n )\n patches.push(set(newUtcDateObject.toISOString(), ['utc']))\n patches.push(set(newLocalDate, ['local']))\n patches.push(set(newOffset, ['offset']))\n }\n onChange(patches)\n },\n [onChange, userTz, value],\n )\n\n return (\n // taken from Scheduled Publishing, again!\n // https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100\n <Box padding={4}>\n <Autocomplete\n fontSize={2}\n icon={SearchIcon}\n id=\"timezone\"\n onChange={handleTimezoneChange}\n openButton\n options={allTimezones}\n padding={4}\n placeholder=\"Search for a city or time zone\"\n popover={{\n boundaryElement: document.querySelector('body'),\n constrainSize: true,\n placement: 'bottom-start',\n }}\n // eslint-disable-next-line react/jsx-no-bind\n renderOption={(option) => {\n return (\n <Card as=\"button\" padding={3}>\n <Text size={1} textOverflow=\"ellipsis\">\n <span>GMT{option.offset}</span>\n <span style={{fontWeight: 500, marginLeft: '1em'}}>{option.alternativeName}</span>\n <span style={{marginLeft: '1em'}}>{option.mainCities}</span>\n </Text>\n </Card>\n )\n }}\n // eslint-disable-next-line react/jsx-no-bind\n renderValue={(_, option) => {\n if (!option) return ''\n return `${option.alternativeName} (${option.namePretty})`\n }}\n tabIndex={-1}\n value={currentTz?.value ?? userTz.value}\n />\n </Box>\n )\n}\n","import {Box, Dialog, Flex} from '@sanity/ui'\nimport {type ReactNode, useCallback, useState} from 'react'\nimport {ObjectInputMember, ObjectInputProps} from 'sanity'\n\nimport {RichDate} from '../types'\nimport {RelativeDateTimePicker} from './RelativeDateTimePicker'\nimport {TimezoneButton} from './TimezoneButton'\nimport {TimezoneSelector} from './TimezoneSelector'\n\nexport const RichDateInput = (props: ObjectInputProps): ReactNode => {\n const {onChange, value, members, schemaType} = props\n const {options} = schemaType\n const localMember = members.find((member) => member.kind === 'field' && member.name === 'local')\n const timezoneMember = members.find(\n (member) => member.kind === 'field' && member.name === 'timezone',\n )\n const [timezoneSelectorOpen, setTimezoneSelectorOpen] = useState(false)\n const onClose = useCallback(() => setTimezoneSelectorOpen(false), [])\n const onOpen = useCallback(() => setTimezoneSelectorOpen(true), [])\n\n return (\n <>\n <Flex>\n <Box flex={[1, 2, 4]}>\n {localMember && (\n <ObjectInputMember\n {...props}\n member={localMember}\n // eslint-disable-next-line react/jsx-no-bind\n renderInput={(renderInputProps) => (\n <RelativeDateTimePicker\n {...renderInputProps}\n dateValue={value as RichDate}\n schemaType={{...renderInputProps.schemaType, options}}\n onChange={onChange}\n />\n )}\n />\n )}\n </Box>\n <Box flex={[1]} marginLeft={[2, 2, 3, 4]}>\n {timezoneMember && (\n <ObjectInputMember\n {...props}\n member={timezoneMember}\n // eslint-disable-next-line react/jsx-no-bind\n renderInput={() => (\n <TimezoneButton onClick={onOpen} timezone={value?.timezone ?? ''} />\n )}\n />\n )}\n </Box>\n </Flex>\n {timezoneSelectorOpen && (\n <Dialog onClose={onClose} header=\"Select a timezone\" id=\"timezone-select\" width={1}>\n <TimezoneSelector onChange={onChange} value={value as RichDate} />\n </Dialog>\n )}\n </>\n )\n}\n","import {\n DatetimeDefinition,\n defineField,\n defineType,\n ObjectDefinition,\n ObjectSchemaType,\n} from 'sanity'\n\nimport {RichDateInput} from './components/RichDateInput'\n\nconst richDateTypeName = 'richDate' as const\n\nexport type RichDateSchemaType = Omit<ObjectSchemaType, 'options'> & {\n options?: DatetimeDefinition['options']\n}\n\n/**\n * @public\n */\nexport interface RichDateDefinition extends Omit<ObjectDefinition, 'type' | 'fields' | 'options'> {\n type: typeof richDateTypeName\n options?: DatetimeDefinition['options']\n}\n\ndeclare module 'sanity' {\n //allows the custom input to be valid for the schema def\n export interface IntrinsicDefinitions {\n richDate: RichDateDefinition\n }\n}\n\nexport const richDateSchema = defineType({\n name: richDateTypeName,\n title: 'Rich Date',\n type: 'object',\n fields: [\n defineField({\n name: 'local',\n title: 'Local',\n type: 'string',\n }),\n defineField({\n name: 'utc',\n title: 'UTC',\n type: 'string',\n }),\n defineField({\n name: 'timezone',\n title: 'Timezone',\n type: 'string',\n }),\n defineField({\n name: 'offset',\n title: 'Offset',\n type: 'number',\n }),\n ],\n\n components: {\n input: RichDateInput,\n },\n})\n","import {definePlugin} from 'sanity'\n\nimport {RichDateDefinition, richDateSchema, RichDateSchemaType} from './schema'\nimport {RichDate} from './types'\n\nexport const richDate = definePlugin({\n name: 'v3-rich-date-input',\n schema: {\n types: [richDateSchema],\n },\n})\n\nexport type {RichDate, RichDateDefinition, RichDateSchemaType}\n"],"names":["unlocalizeDateTime","datetime","timezone","formatInTimeZone","getConstructedUTCDate","utc","offset","date","Date","currentOffset","getTimezoneOffset","diff","fakeUTCDate","getTime","toISOString","allTimezones","getTimeZones","map","tz","abbreviation","alternativeName","mainCities","join","name","namePretty","replaceAll","currentTimeFormat","split","value","concat","currentTimeOffsetInMinutes","group","RelativeDateTimePicker","props","dateValue","onChange","handleDateChange","useCallback","patch","_a","Intl","DateTimeFormat","resolvedOptions","timeZone","newDatetime","type","unset","desiredDateTime","newUtcDateObject","zonedTimeToUtc","newOffset","localDate","patches","push","set","dateToDisplay","DateTimeInput","TimezoneButton","_b","_c","_d","_e","onClick","currentTimezone","label","find","includes","jsx","Button","fontSize","style","width","justify","icon","EarthAmericasIcon","mode","text","TimezoneSelector","currentTz","userTzName","userTz","handleTimezoneChange","selectedTz","newTimezone","timezonePatch","newLocalDate","Box","padding","children","Autocomplete","SearchIcon","id","openButton","options","placeholder","popover","boundaryElement","document","querySelector","constrainSize","placement","renderOption","option","Card","as","jsxs","Text","size","textOverflow","fontWeight","marginLeft","renderValue","_","tabIndex","RichDateInput","members","schemaType","localMember","member","kind","timezoneMember","timezoneSelectorOpen","setTimezoneSelectorOpen","useState","onClose","onOpen","Fragment","Flex","flex","ObjectInputMember","renderInput","renderInputProps","Dialog","header","richDateTypeName","richDateSchema","defineType","title","fields","defineField","components","input","richDate","definePlugin","schema","types"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,56 +1,59 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {formatInTimeZone, getTimezoneOffset, zonedTimeToUtc} from 'date-fns-tz'
|
|
2
|
+
import {type ReactNode, useCallback} from 'react'
|
|
3
|
+
import {DateTimeInput, FormPatch, InputProps, PatchEvent, set, unset} from 'sanity'
|
|
2
4
|
|
|
3
|
-
import {getConstructedUTCDate, unlocalizeDateTime} from '../utils'
|
|
4
5
|
import {RichDate} from '../types'
|
|
5
|
-
import {
|
|
6
|
+
import {getConstructedUTCDate, unlocalizeDateTime} from '../utils'
|
|
6
7
|
|
|
7
8
|
interface RelativeDateTimePickerProps extends Omit<InputProps, 'renderDefault'> {
|
|
8
9
|
dateValue?: RichDate
|
|
9
10
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
11
|
+
export const RelativeDateTimePicker = (props: RelativeDateTimePickerProps): ReactNode => {
|
|
12
|
+
const {dateValue: value, onChange} = props
|
|
13
|
+
|
|
14
|
+
const handleDateChange = useCallback(
|
|
15
|
+
(patch: FormPatch | PatchEvent | FormPatch[]) => {
|
|
16
|
+
const timezone = value?.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
17
|
+
const newDatetime = (patch as unknown as {value: string})?.value
|
|
18
|
+
if (!newDatetime || !('type' in patch) || patch.type !== 'set') {
|
|
19
|
+
onChange(unset())
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* get what time the user "meant" to set without tz info
|
|
24
|
+
* right now, newDatetime is the time the user set plus
|
|
25
|
+
* their current offset, not the timezone offset
|
|
26
|
+
*/
|
|
27
|
+
const desiredDateTime = unlocalizeDateTime(
|
|
28
|
+
newDatetime,
|
|
29
|
+
Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const newUtcDateObject = zonedTimeToUtc(desiredDateTime, timezone)
|
|
33
|
+
// offset may have changed based on DST, capture that
|
|
34
|
+
const newOffset = getTimezoneOffset(timezone, newUtcDateObject) / 60 / 1000
|
|
35
|
+
const localDate = formatInTimeZone(newUtcDateObject, timezone, "yyyy-MM-dd'T'HH:mm:ssXXX")
|
|
36
|
+
|
|
37
|
+
const patches = []
|
|
38
|
+
|
|
39
|
+
patches.push(set(newUtcDateObject.toISOString(), ['utc']))
|
|
40
|
+
patches.push(set(localDate, ['local']))
|
|
41
|
+
|
|
42
|
+
if (!value?.timezone) {
|
|
43
|
+
patches.push(set(timezone, ['timezone']))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (value?.offset !== newOffset) {
|
|
47
|
+
patches.push(set(newOffset, ['offset']))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
onChange(patches)
|
|
51
|
+
},
|
|
52
|
+
[onChange, value],
|
|
53
|
+
)
|
|
52
54
|
|
|
53
55
|
const dateToDisplay = value?.utc ? getConstructedUTCDate(value.utc, value.offset) : ''
|
|
54
|
-
|
|
56
|
+
|
|
57
|
+
// @ts-expect-error -- slight mismatch in elementProps and renderDefault, but should line up in practice
|
|
55
58
|
return <DateTimeInput {...props} onChange={handleDateChange} value={dateToDisplay} />
|
|
56
59
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import {Box, Dialog, Flex} from '@sanity/ui'
|
|
2
|
+
import {type ReactNode, useCallback, useState} from 'react'
|
|
1
3
|
import {ObjectInputMember, ObjectInputProps} from 'sanity'
|
|
2
|
-
|
|
4
|
+
|
|
5
|
+
import {RichDate} from '../types'
|
|
3
6
|
import {RelativeDateTimePicker} from './RelativeDateTimePicker'
|
|
4
|
-
import {TimezoneSelector} from './TimezoneSelector'
|
|
5
|
-
import {useCallback, useState} from 'react'
|
|
6
7
|
import {TimezoneButton} from './TimezoneButton'
|
|
7
|
-
import {
|
|
8
|
+
import {TimezoneSelector} from './TimezoneSelector'
|
|
8
9
|
|
|
9
|
-
export const RichDateInput = (props: ObjectInputProps) => {
|
|
10
|
+
export const RichDateInput = (props: ObjectInputProps): ReactNode => {
|
|
10
11
|
const {onChange, value, members, schemaType} = props
|
|
11
12
|
const {options} = schemaType
|
|
12
13
|
const localMember = members.find((member) => member.kind === 'field' && member.name === 'local')
|
|
@@ -25,6 +26,7 @@ export const RichDateInput = (props: ObjectInputProps) => {
|
|
|
25
26
|
<ObjectInputMember
|
|
26
27
|
{...props}
|
|
27
28
|
member={localMember}
|
|
29
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
28
30
|
renderInput={(renderInputProps) => (
|
|
29
31
|
<RelativeDateTimePicker
|
|
30
32
|
{...renderInputProps}
|
|
@@ -41,6 +43,7 @@ export const RichDateInput = (props: ObjectInputProps) => {
|
|
|
41
43
|
<ObjectInputMember
|
|
42
44
|
{...props}
|
|
43
45
|
member={timezoneMember}
|
|
46
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
44
47
|
renderInput={() => (
|
|
45
48
|
<TimezoneButton onClick={onOpen} timezone={value?.timezone ?? ''} />
|
|
46
49
|
)}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import {Button} from '@sanity/ui'
|
|
2
1
|
import {EarthAmericasIcon} from '@sanity/icons'
|
|
2
|
+
import {Button} from '@sanity/ui'
|
|
3
|
+
import {type ReactNode} from 'react'
|
|
4
|
+
|
|
3
5
|
import {allTimezones} from '../utils'
|
|
4
6
|
|
|
5
7
|
interface TimezoneButtonProps {
|
|
@@ -7,7 +9,7 @@ interface TimezoneButtonProps {
|
|
|
7
9
|
timezone: string
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
export const TimezoneButton = (props: TimezoneButtonProps) => {
|
|
12
|
+
export const TimezoneButton = (props: TimezoneButtonProps): ReactNode => {
|
|
11
13
|
const {onClick, timezone} = props
|
|
12
14
|
const currentTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
13
15
|
|
|
@@ -1,49 +1,54 @@
|
|
|
1
1
|
import {SearchIcon} from '@sanity/icons'
|
|
2
|
+
import {Autocomplete, Box, Card, Text} from '@sanity/ui'
|
|
3
|
+
import {formatInTimeZone, getTimezoneOffset, zonedTimeToUtc} from 'date-fns-tz'
|
|
4
|
+
import {type ReactNode, useCallback} from 'react'
|
|
2
5
|
import {ObjectInputProps, set} from 'sanity'
|
|
3
|
-
|
|
6
|
+
|
|
4
7
|
import {NormalizedTimeZone, RichDate} from '../types'
|
|
5
|
-
import {
|
|
6
|
-
import {formatInTimeZone, zonedTimeToUtc} from 'date-fns-tz'
|
|
8
|
+
import {allTimezones, unlocalizeDateTime} from '../utils'
|
|
7
9
|
|
|
8
10
|
interface TimezoneSelectorProps {
|
|
9
11
|
onChange: Pick<ObjectInputProps, 'onChange'>['onChange']
|
|
10
12
|
value?: RichDate
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
export const TimezoneSelector = (props: TimezoneSelectorProps) => {
|
|
15
|
+
export const TimezoneSelector = (props: TimezoneSelectorProps): ReactNode => {
|
|
14
16
|
const {onChange, value} = props
|
|
15
17
|
const currentTz = allTimezones.find((tz) => tz.name === value?.timezone)
|
|
16
18
|
const userTzName = Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
17
19
|
const userTz = (allTimezones.find((tz) => tz.name === userTzName) ??
|
|
18
20
|
allTimezones.find((tz) => tz.group.includes(userTzName)))!
|
|
19
21
|
|
|
20
|
-
const handleTimezoneChange = (
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
const handleTimezoneChange = useCallback(
|
|
23
|
+
(selectedTz: string) => {
|
|
24
|
+
const newTimezone =
|
|
25
|
+
allTimezones.find((tz) => tz.value === selectedTz) ?? (userTz as NormalizedTimeZone)
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const offsetPatch = set(offset, ['offset'])
|
|
27
|
-
const patches = [timezonePatch, offsetPatch]
|
|
27
|
+
const timezonePatch = set(newTimezone.name, ['timezone'])
|
|
28
|
+
const patches = [timezonePatch]
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
// then, recalculate UTC and local from "old" time with the new offset
|
|
31
|
+
if (value?.utc) {
|
|
32
|
+
const desiredDateTime = unlocalizeDateTime(value.utc, value.timezone)
|
|
33
|
+
const newUtcDateObject = zonedTimeToUtc(desiredDateTime, newTimezone.name)
|
|
34
|
+
const newOffset = getTimezoneOffset(newTimezone.name, newUtcDateObject) / 60 / 1000
|
|
35
|
+
const newLocalDate = formatInTimeZone(
|
|
36
|
+
newUtcDateObject.toISOString(),
|
|
37
|
+
newTimezone.name,
|
|
38
|
+
"yyyy-MM-dd'T'HH:mm:ssXXX",
|
|
39
|
+
)
|
|
40
|
+
patches.push(set(newUtcDateObject.toISOString(), ['utc']))
|
|
41
|
+
patches.push(set(newLocalDate, ['local']))
|
|
42
|
+
patches.push(set(newOffset, ['offset']))
|
|
43
|
+
}
|
|
44
|
+
onChange(patches)
|
|
45
|
+
},
|
|
46
|
+
[onChange, userTz, value],
|
|
47
|
+
)
|
|
43
48
|
|
|
44
49
|
return (
|
|
45
|
-
//taken from Scheduled Publishing, again!
|
|
46
|
-
//https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100
|
|
50
|
+
// taken from Scheduled Publishing, again!
|
|
51
|
+
// https://github.com/sanity-io/sanity-plugin-scheduled-publishing/blob/bb282e3df9a8a73df37fab8ee1fdd0e2430745be/src/components/dialogs/DialogTimeZone.tsx#L100
|
|
47
52
|
<Box padding={4}>
|
|
48
53
|
<Autocomplete
|
|
49
54
|
fontSize={2}
|
|
@@ -59,6 +64,7 @@ export const TimezoneSelector = (props: TimezoneSelectorProps) => {
|
|
|
59
64
|
constrainSize: true,
|
|
60
65
|
placement: 'bottom-start',
|
|
61
66
|
}}
|
|
67
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
62
68
|
renderOption={(option) => {
|
|
63
69
|
return (
|
|
64
70
|
<Card as="button" padding={3}>
|
|
@@ -70,6 +76,7 @@ export const TimezoneSelector = (props: TimezoneSelectorProps) => {
|
|
|
70
76
|
</Card>
|
|
71
77
|
)
|
|
72
78
|
}}
|
|
79
|
+
// eslint-disable-next-line react/jsx-no-bind
|
|
73
80
|
renderValue={(_, option) => {
|
|
74
81
|
if (!option) return ''
|
|
75
82
|
return `${option.alternativeName} (${option.namePretty})`
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {definePlugin} from 'sanity'
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import {RichDateDefinition, richDateSchema, RichDateSchemaType} from './schema'
|
|
3
4
|
import {RichDate} from './types'
|
|
4
5
|
|
|
5
6
|
export const richDate = definePlugin({
|
|
@@ -9,4 +10,4 @@ export const richDate = definePlugin({
|
|
|
9
10
|
},
|
|
10
11
|
})
|
|
11
12
|
|
|
12
|
-
export type {RichDateDefinition, RichDateSchemaType
|
|
13
|
+
export type {RichDate, RichDateDefinition, RichDateSchemaType}
|
package/src/schema.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DatetimeDefinition,
|
|
3
|
-
ObjectDefinition,
|
|
4
|
-
ObjectSchemaType,
|
|
5
3
|
defineField,
|
|
6
4
|
defineType,
|
|
5
|
+
ObjectDefinition,
|
|
6
|
+
ObjectSchemaType,
|
|
7
7
|
} from 'sanity'
|
|
8
|
+
|
|
8
9
|
import {RichDateInput} from './components/RichDateInput'
|
|
9
10
|
|
|
10
11
|
const richDateTypeName = 'richDate' as const
|
package/src/utils/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {getTimeZones} from '@vvo/tzdb'
|
|
2
|
-
import {NormalizedTimeZone} from '../types'
|
|
3
2
|
import {formatInTimeZone} from 'date-fns-tz'
|
|
4
3
|
|
|
4
|
+
import {NormalizedTimeZone} from '../types'
|
|
5
|
+
|
|
5
6
|
export const unlocalizeDateTime = (datetime: string, timezone: string): string => {
|
|
6
7
|
return formatInTimeZone(datetime, timezone, 'yyyy-MM-dd HH:mm:ss')
|
|
7
8
|
}
|
|
@@ -14,7 +15,7 @@ export const unlocalizeDateTime = (datetime: string, timezone: string): string =
|
|
|
14
15
|
*/
|
|
15
16
|
export const getConstructedUTCDate = (utc: string, offset: number): string => {
|
|
16
17
|
const date = new Date(utc)
|
|
17
|
-
const currentOffset =
|
|
18
|
+
const currentOffset = date.getTimezoneOffset() * -1
|
|
18
19
|
const diff = currentOffset - offset
|
|
19
20
|
const fakeUTCDate = new Date(date.getTime() - diff * 60 * 1000)
|
|
20
21
|
return fakeUTCDate.toISOString()
|