sanity-plugin-recurring-dates 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +489 -350
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +488 -349
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/components/CustomRule/CustomRule.tsx +26 -11
- package/src/components/DateInputs/DateInput.tsx +5 -5
- package/src/components/RecurringDate.tsx +12 -1
- package/src/components/RecurringDatesPreview.tsx +14 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sanity-plugin-recurring-dates",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
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
|
|
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(
|
|
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
|
|
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}>
|
|
133
|
-
<option value={RRule.MONTHLY}>
|
|
134
|
-
<option value={RRule.WEEKLY}>
|
|
135
|
-
<option value={RRule.DAILY}>
|
|
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={
|
|
183
|
-
|
|
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'}}>
|
|
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
|
-
|
|
20
|
-
value:
|
|
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,
|
|
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={
|
|
75
|
+
readOnly={readOnly}
|
|
76
76
|
selectTime={false}
|
|
77
77
|
serialize={serialize}
|
|
78
78
|
value={value}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {Box, Flex, Grid, Select, Stack, Text} from '@sanity/ui'
|
|
2
2
|
import {upperFirst} from 'lodash'
|
|
3
3
|
import React, {useCallback, useState} from 'react'
|
|
4
|
-
import {rrulestr} from 'rrule'
|
|
4
|
+
import {datetime, rrulestr} from 'rrule'
|
|
5
5
|
import {
|
|
6
6
|
ObjectInputMember,
|
|
7
7
|
type ObjectInputProps,
|
|
@@ -157,6 +157,17 @@ export function RecurringDates(props: RecurringDatesProps): React.JSX.Element {
|
|
|
157
157
|
}
|
|
158
158
|
const rule = rrulestr(recurrence)
|
|
159
159
|
|
|
160
|
+
rule.options.until =
|
|
161
|
+
rule?.options?.until &&
|
|
162
|
+
datetime(
|
|
163
|
+
rule?.options?.until?.getFullYear(),
|
|
164
|
+
rule?.options?.until?.getMonth() + 1,
|
|
165
|
+
rule?.options?.until?.getDate(),
|
|
166
|
+
rule?.options?.until?.getHours(),
|
|
167
|
+
rule?.options?.until?.getMinutes(),
|
|
168
|
+
rule?.options?.until?.getSeconds(),
|
|
169
|
+
)
|
|
170
|
+
|
|
160
171
|
return (
|
|
161
172
|
<option key={recurrence} value={recurrence}>
|
|
162
173
|
{upperFirst(rule.toText())}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {DEFAULT_DATE_FORMAT, DEFAULT_TIME_FORMAT, format} from '@sanity/util/legacyDateFormat'
|
|
2
2
|
import {upperFirst} from 'lodash'
|
|
3
3
|
import React from 'react'
|
|
4
|
-
import {rrulestr} from 'rrule'
|
|
4
|
+
import {datetime, rrulestr} from 'rrule'
|
|
5
5
|
import type {ObjectSchemaType, PreviewProps} from 'sanity'
|
|
6
6
|
|
|
7
7
|
import type {PluginConfig, RecurringDate, WithRequiredProperty} from '../types'
|
|
@@ -26,6 +26,19 @@ export function RecurringDatesPreview(props: CastPreviewProps): React.JSX.Elemen
|
|
|
26
26
|
|
|
27
27
|
const rule = rrule && rrulestr(rrule)
|
|
28
28
|
|
|
29
|
+
if (rule) {
|
|
30
|
+
rule.options.until =
|
|
31
|
+
rule?.options?.until &&
|
|
32
|
+
datetime(
|
|
33
|
+
rule?.options?.until?.getFullYear(),
|
|
34
|
+
rule?.options?.until?.getMonth() + 1,
|
|
35
|
+
rule?.options?.until?.getDate(),
|
|
36
|
+
rule?.options?.until?.getHours(),
|
|
37
|
+
rule?.options?.until?.getMinutes(),
|
|
38
|
+
rule?.options?.until?.getSeconds(),
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
29
42
|
const dateFormat = dateTimeOptions?.dateFormat || DEFAULT_DATE_FORMAT
|
|
30
43
|
const timeFormat = dateTimeOptions?.timeFormat || DEFAULT_TIME_FORMAT
|
|
31
44
|
|