sanity-plugin-recurring-dates 1.3.0 → 1.3.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanity-plugin-recurring-dates",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "Add a custom input component to your Sanity Studio to manage recurring dates (e.g. for events)",
5
5
  "keywords": [
6
6
  "sanity",
@@ -48,6 +48,7 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@sanity/incompatible-plugin": "^1.0.4",
51
+ "date-fns-tz": "^3.2.0",
51
52
  "lodash": "^4.17.21",
52
53
  "rrule": "^2.7.2",
53
54
  "sanity-plugin-utils": "^1.6.2"
@@ -1,4 +1,5 @@
1
1
  import {Box, Button, Dialog, Flex, Radio, Select, Stack, Text, TextInput} from '@sanity/ui'
2
+ import {format, toDate} from 'date-fns-tz'
2
3
  import React, {useCallback, useMemo, useState} from 'react'
3
4
  import {Options, RRule, rrulestr, Weekday} from 'rrule'
4
5
  import {type ObjectInputProps, set} from 'sanity'
@@ -30,7 +31,9 @@ export function CustomRule({
30
31
 
31
32
  const [frequency, setFrequency] = useState<Options['freq']>(initialRule.origOptions.freq || 1)
32
33
  const [interval, setInterval] = useState<Options['interval']>(
33
- initialRule.origOptions.interval || 1,
34
+ initialRule.origOptions.interval && initialRule.origOptions.interval > 0
35
+ ? initialRule.origOptions.interval
36
+ : 1,
34
37
  )
35
38
  const [count, setCount] = useState<Options['count']>(initialRule.origOptions.count || null)
36
39
  const [until, setUntil] = useState<Options['until'] | number>(
@@ -47,7 +50,7 @@ export function CustomRule({
47
50
  if (name === 'freq') {
48
51
  setFrequency(Number(value))
49
52
  } else if (name === 'interval') {
50
- setInterval(Number(value))
53
+ setInterval(Number(value) > 1 ? Number(value) : 1)
51
54
  } else if (name === 'count') {
52
55
  setCount(Number(value))
53
56
  }
@@ -68,12 +71,14 @@ export function CustomRule({
68
71
  fromDate.setDate(fromDate.getDate() + DEFAULT_COUNTS[frequency])
69
72
  }
70
73
 
74
+ fromDate.setHours(23, 59, 59, 999)
75
+
71
76
  return fromDate
72
77
  }, [frequency, startDate])
73
78
 
74
79
  const handleUntilChange = useCallback((date: string | null) => {
75
80
  if (date) {
76
- setUntil(new Date(date))
81
+ setUntil(toDate(`${date}T23:59:59`))
77
82
  }
78
83
  }, [])
79
84
 
@@ -111,6 +116,8 @@ export function CustomRule({
111
116
  onChange(set(newRule.toString(), ['rrule']))
112
117
  }, [byweekday, count, frequency, interval, onChange, onClose, until])
113
118
 
119
+ const formatUntilValue = useCallback((date: Date) => format(date, 'yyyy-MM-dd'), [])
120
+
114
121
  return open ? (
115
122
  <Dialog
116
123
  header="Custom recurrence"
@@ -125,14 +132,20 @@ export function CustomRule({
125
132
  <Flex gap={2} align="center">
126
133
  <Text style={{whiteSpace: 'nowrap'}}>Repeat every</Text>
127
134
  <Box style={{width: '75px'}}>
128
- <TextInput name="interval" type="number" value={interval} onChange={handleChange} />
135
+ <TextInput
136
+ name="interval"
137
+ type="number"
138
+ min={1}
139
+ value={interval}
140
+ onChange={handleChange}
141
+ />
129
142
  </Box>
130
143
  <Box>
131
144
  <Select name="freq" value={frequency} onChange={handleChange}>
132
- <option value={RRule.YEARLY}>years</option>
133
- <option value={RRule.MONTHLY}>months</option>
134
- <option value={RRule.WEEKLY}>weeks</option>
135
- <option value={RRule.DAILY}>days</option>
145
+ <option value={RRule.YEARLY}>year(s)</option>
146
+ <option value={RRule.MONTHLY}>month(s)</option>
147
+ <option value={RRule.WEEKLY}>week(s)</option>
148
+ <option value={RRule.DAILY}>day(s)</option>
136
149
  </Select>
137
150
  </Box>
138
151
  </Flex>
@@ -179,8 +192,10 @@ export function CustomRule({
179
192
  title: 'Date',
180
193
  options: dateTimeOptions,
181
194
  }}
182
- value={until ? new Date(until) : getUntilDate()}
183
- disabled={!until}
195
+ value={
196
+ until ? formatUntilValue(new Date(until)) : formatUntilValue(getUntilDate())
197
+ }
198
+ readOnly={!until}
184
199
  />
185
200
  </Box>
186
201
  </Flex>
@@ -204,7 +219,7 @@ export function CustomRule({
204
219
  disabled={!count}
205
220
  />
206
221
  </Box>
207
- <Text style={{whiteSpace: 'nowrap'}}>occurrences</Text>
222
+ <Text style={{whiteSpace: 'nowrap'}}>occurrence(s)</Text>
208
223
  </Flex>
209
224
  </Stack>
210
225
  </Stack>
@@ -16,8 +16,8 @@ interface SchemaOptions {
16
16
  type DateInputProps = {
17
17
  id: string
18
18
  onChange: (date: string | null) => void
19
- disabled?: boolean
20
- value: number | Date | null
19
+ readOnly?: boolean
20
+ value: string | undefined
21
21
  type: {
22
22
  name: string
23
23
  title: string
@@ -46,13 +46,13 @@ const serialize = (date: Date) => format(date, VALUE_FORMAT)
46
46
  * @hidden
47
47
  * @beta */
48
48
  export function DateInput(props: DateInputProps): React.JSX.Element {
49
- const {id, onChange, type, value, disabled, ...rest} = props
49
+ const {id, onChange, type, value, readOnly, ...rest} = props
50
50
 
51
51
  const {dateFormat} = parseOptions(type.options)
52
52
 
53
53
  const handleChange = useCallback(
54
54
  (nextDate: string | null) => {
55
- onChange(nextDate)
55
+ onChange(nextDate || null)
56
56
  },
57
57
  [onChange],
58
58
  )
@@ -72,7 +72,7 @@ export function DateInput(props: DateInputProps): React.JSX.Element {
72
72
  formatInputValue={formatInputValue}
73
73
  onChange={handleChange}
74
74
  parseInputValue={parseInputValue}
75
- readOnly={disabled}
75
+ readOnly={readOnly}
76
76
  selectTime={false}
77
77
  serialize={serialize}
78
78
  value={value}