improvement(starter): added date/time picker

This commit is contained in:
Emir Karabeg
2025-02-19 20:41:15 -08:00
parent abee3090f4
commit 4edd0ee3bf
8 changed files with 461 additions and 129 deletions
@@ -0,0 +1,47 @@
'use client'
import * as React from 'react'
import { format } from 'date-fns'
import { Calendar as CalendarIcon } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Calendar } from '@/components/ui/calendar'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { cn } from '@/lib/utils'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
interface DateInputProps {
blockId: string
subBlockId: string
placeholder?: string
}
export function DateInput({ blockId, subBlockId, placeholder }: DateInputProps) {
const [value, setValue] = useSubBlockValue<string>(blockId, subBlockId, true)
const date = value ? new Date(value) : undefined
return (
<Popover>
<PopoverTrigger asChild>
<Button
variant="outline"
className={cn(
'w-full justify-start text-left font-normal',
!date && 'text-muted-foreground'
)}
>
<CalendarIcon className="mr-2 h-4 w-4" />
{date ? format(date, 'MMM d, yy') : <span>{placeholder || 'Pick a date'}</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={date}
onSelect={(date) => setValue(date?.toISOString() || '')}
initialFocus
/>
</PopoverContent>
</Popover>
)
}
@@ -0,0 +1,153 @@
'use client'
import * as React from 'react'
import { Clock } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
import { cn } from '@/lib/utils'
import { useSubBlockValue } from '../hooks/use-sub-block-value'
interface TimeInputProps {
blockId: string
subBlockId: string
placeholder?: string
}
export function TimeInput({ blockId, subBlockId, placeholder }: TimeInputProps) {
const [value, setValue] = useSubBlockValue<string>(blockId, subBlockId, true)
const [isOpen, setIsOpen] = React.useState(false)
// Convert 24h time string to display format (12h with AM/PM)
const formatDisplayTime = (time: string) => {
if (!time) return ''
const [hours, minutes] = time.split(':')
const hour = parseInt(hours, 10)
const ampm = hour >= 12 ? 'PM' : 'AM'
const displayHour = hour % 12 || 12
return `${displayHour}:${minutes} ${ampm}`
}
// Convert display time to 24h format for storage
const formatStorageTime = (hour: number, minute: number, ampm: string) => {
const hours24 = ampm === 'PM' ? (hour === 12 ? 12 : hour + 12) : hour === 12 ? 0 : hour
return `${hours24.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`
}
const [hour, setHour] = React.useState<string>('12')
const [minute, setMinute] = React.useState<string>('00')
const [ampm, setAmpm] = React.useState<'AM' | 'PM'>('AM')
// Update the time when any component changes
const updateTime = (newHour?: string, newMinute?: string, newAmpm?: 'AM' | 'PM') => {
const h = parseInt(newHour ?? hour) || 12
const m = parseInt(newMinute ?? minute) || 0
const p = newAmpm ?? ampm
setValue(formatStorageTime(h, m, p))
}
// Initialize from existing value
React.useEffect(() => {
if (value) {
const [hours, minutes] = value.split(':')
const hour24 = parseInt(hours, 10)
const minute = parseInt(minutes, 10)
const isAM = hour24 < 12
setHour((hour24 % 12 || 12).toString())
setMinute(minutes)
setAmpm(isAM ? 'AM' : 'PM')
}
}, [value])
const handleBlur = () => {
updateTime()
setIsOpen(false)
}
return (
<Popover
open={isOpen}
onOpenChange={(open) => {
setIsOpen(open)
if (!open) {
handleBlur()
}
}}
>
<PopoverTrigger asChild>
<Button
variant="outline"
className={cn(
'w-full justify-start text-left font-normal',
!value && 'text-muted-foreground'
)}
>
<Clock className="mr-2 h-4 w-4" />
{value ? formatDisplayTime(value) : <span>{placeholder || 'Select time'}</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-4">
<div className="flex items-center space-x-2">
<Input
className="w-[4rem]"
value={hour}
onChange={(e) => {
const val = e.target.value.replace(/[^0-9]/g, '')
if (val === '') {
setHour('')
return
}
const numVal = parseInt(val)
if (!isNaN(numVal)) {
const newHour = Math.min(12, Math.max(1, numVal)).toString()
setHour(newHour)
updateTime(newHour)
}
}}
onBlur={() => {
const numVal = parseInt(hour) || 12
setHour(numVal.toString())
updateTime(numVal.toString())
}}
type="text"
/>
<span>:</span>
<Input
className="w-[4rem]"
value={minute}
onChange={(e) => {
const val = e.target.value.replace(/[^0-9]/g, '')
if (val === '') {
setMinute('')
return
}
const numVal = parseInt(val)
if (!isNaN(numVal)) {
const newMinute = Math.min(59, Math.max(0, numVal)).toString().padStart(2, '0')
setMinute(newMinute)
updateTime(undefined, newMinute)
}
}}
onBlur={() => {
const numVal = parseInt(minute) || 0
setMinute(numVal.toString().padStart(2, '0'))
updateTime(undefined, numVal.toString())
}}
type="text"
/>
<Button
variant="outline"
className="w-[4rem]"
onClick={() => {
const newAmpm = ampm === 'AM' ? 'PM' : 'AM'
setAmpm(newAmpm)
updateTime(undefined, undefined, newAmpm)
}}
>
{ampm}
</Button>
</div>
</PopoverContent>
</Popover>
)
}
@@ -3,6 +3,7 @@ import { SubBlockConfig } from '../../../../../../../blocks/types'
import { CheckboxList } from './components/checkbox-list'
import { Code } from './components/code'
import { ConditionInput } from './components/condition-input'
import { DateInput } from './components/date-input'
import { Dropdown } from './components/dropdown'
import { EvalInput } from './components/eval-input'
import { LongInput } from './components/long-input'
@@ -10,6 +11,7 @@ import { ShortInput } from './components/short-input'
import { SliderInput } from './components/slider-input'
import { Switch } from './components/switch'
import { Table } from './components/table'
import { TimeInput } from './components/time-input'
import { ToolInput } from './components/tool-input'
interface SubBlockProps {
@@ -97,6 +99,14 @@ export function SubBlock({ blockId, config, isConnecting }: SubBlockProps) {
)
case 'eval-input':
return <EvalInput blockId={blockId} subBlockId={config.id} />
case 'date-input':
return (
<DateInput blockId={blockId} subBlockId={config.id} placeholder={config.placeholder} />
)
case 'time-input':
return (
<TimeInput blockId={blockId} subBlockId={config.id} placeholder={config.placeholder} />
)
default:
return null
}
+17 -119
View File
@@ -40,7 +40,23 @@ export const StarterBlock: BlockConfig = {
password: true,
condition: { field: 'startWorkflow', value: 'webhook' },
},
// Schedule configuration
// Common schedule fields for all frequency types
{
id: 'scheduleStartAt',
title: 'Start At',
type: 'date-input',
layout: 'half',
placeholder: 'Select day',
condition: { field: 'startWorkflow', value: 'schedule' },
},
{
id: 'scheduleTime',
title: 'Time',
type: 'time-input',
layout: 'half',
condition: { field: 'startWorkflow', value: 'schedule' },
},
// Frequency configuration
{
id: 'scheduleType',
title: 'Frequency',
@@ -73,124 +89,6 @@ export const StarterBlock: BlockConfig = {
},
},
},
{
id: 'minutesStartingAt',
title: 'Starting At',
type: 'short-input',
layout: 'full',
placeholder: '14:30 (24-hour format)',
condition: {
field: 'scheduleType',
value: 'minutes',
and: {
field: 'startWorkflow',
value: 'schedule',
},
},
},
// Hourly schedule options
{
id: 'hourlyMinute',
title: 'Start at Minute',
type: 'short-input',
layout: 'full',
placeholder: '00-59',
condition: {
field: 'scheduleType',
value: 'hourly',
and: {
field: 'startWorkflow',
value: 'schedule',
},
},
},
// Daily schedule options
{
id: 'dailyTime',
title: 'Time',
type: 'short-input',
layout: 'full',
placeholder: '14:30 (24-hour format)',
condition: {
field: 'scheduleType',
value: 'daily',
and: {
field: 'startWorkflow',
value: 'schedule',
},
},
},
// Weekly schedule options
{
id: 'weeklyDay',
title: 'Day of Week',
type: 'dropdown',
layout: 'half',
options: [
{ label: 'Monday', id: 'MON' },
{ label: 'Tuesday', id: 'TUE' },
{ label: 'Wednesday', id: 'WED' },
{ label: 'Thursday', id: 'THU' },
{ label: 'Friday', id: 'FRI' },
{ label: 'Saturday', id: 'SAT' },
{ label: 'Sunday', id: 'SUN' },
],
value: () => 'MON',
condition: {
field: 'scheduleType',
value: 'weekly',
and: {
field: 'startWorkflow',
value: 'schedule',
},
},
},
{
id: 'weeklyDayTime',
title: 'Time',
type: 'short-input',
layout: 'half',
placeholder: '14:30 (24-hour format)',
condition: {
field: 'scheduleType',
value: 'weekly',
and: {
field: 'startWorkflow',
value: 'schedule',
},
},
},
// Monthly schedule options
{
id: 'monthlyDay',
title: 'Day of Month',
type: 'short-input',
layout: 'half',
placeholder: '1-31',
condition: {
field: 'scheduleType',
value: 'monthly',
and: {
field: 'startWorkflow',
value: 'schedule',
},
},
},
{
id: 'monthlyTime',
title: 'Time',
type: 'short-input',
layout: 'half',
placeholder: '14:30 (24-hour format)',
condition: {
field: 'scheduleType',
value: 'monthly',
and: {
field: 'startWorkflow',
value: 'schedule',
},
},
},
// Custom cron options
{
id: 'cronExpression',
+2
View File
@@ -23,6 +23,8 @@ export type SubBlockType =
| 'checkbox-list' // Multiple selection
| 'condition-input' // Conditional logic
| 'eval-input' // Evaluation input
| 'date-input' // Date input
| 'time-input' // Time input
// Component width setting
export type SubBlockLayout = 'full' | 'half'
+62
View File
@@ -0,0 +1,62 @@
'use client'
import * as React from 'react'
import { ChevronLeft, ChevronRight } from 'lucide-react'
import { DayPicker } from 'react-day-picker'
import { buttonVariants } from '@/components/ui/button'
import { cn } from '@/lib/utils'
export type CalendarProps = React.ComponentProps<typeof DayPicker>
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn('p-3', className)}
classNames={{
months: 'flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0',
month: 'space-y-4',
caption: 'flex justify-center pt-1 relative items-center',
caption_label: 'text-sm font-medium',
nav: 'space-x-1 flex items-center',
nav_button: cn(
buttonVariants({ variant: 'outline' }),
'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'
),
nav_button_previous: 'absolute left-1',
nav_button_next: 'absolute right-1',
table: 'w-full border-collapse space-y-1',
head_row: 'flex',
head_cell: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]',
row: 'flex w-full mt-2',
cell: 'h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20',
day: cn(
buttonVariants({ variant: 'ghost' }),
'h-9 w-9 p-0 font-normal aria-selected:opacity-100'
),
day_range_end: 'day-range-end',
day_selected:
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
day_today: 'bg-accent text-accent-foreground',
day_outside:
'day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground',
day_disabled: 'text-muted-foreground opacity-50',
day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground',
day_hidden: 'invisible',
...classNames,
}}
components={{
IconLeft: ({ className, ...props }) => (
<ChevronLeft className={cn('h-4 w-4', className)} {...props} />
),
IconRight: ({ className, ...props }) => (
<ChevronRight className={cn('h-4 w-4', className)} {...props} />
),
}}
{...props}
/>
)
}
Calendar.displayName = 'Calendar'
export { Calendar }
+167 -8
View File
@@ -17,7 +17,7 @@
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-slider": "^1.2.2",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.6",
@@ -28,7 +28,7 @@
"cmdk": "^1.0.0",
"cron-parser": "^5.0.2",
"croner": "^9.0.0",
"date-fns": "^4.1.0",
"date-fns": "^3.6.0",
"drizzle-orm": "^0.39.3",
"lodash.debounce": "^4.0.8",
"lucide-react": "^0.469.0",
@@ -37,6 +37,7 @@
"postgres": "^3.4.5",
"prismjs": "^1.29.0",
"react": "^18.2.0",
"react-day-picker": "^8.10.1",
"react-dom": "^18.2.0",
"react-simple-code-editor": "^0.14.1",
"reactflow": "^11.11.4",
@@ -3005,6 +3006,24 @@
}
}
},
"node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-arrow": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz",
@@ -3084,6 +3103,24 @@
}
}
},
"node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
@@ -3177,6 +3214,24 @@
}
}
},
"node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-direction": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
@@ -3369,6 +3424,24 @@
}
}
},
"node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-popover": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.5.tgz",
@@ -3433,6 +3506,24 @@
}
}
},
"node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-popper": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz",
@@ -3536,6 +3627,24 @@
}
}
},
"node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz",
@@ -3641,6 +3750,24 @@
}
}
},
"node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-slider": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slider/-/react-slider-1.2.2.tgz",
@@ -3675,9 +3802,9 @@
}
},
"node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz",
"integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
@@ -3785,6 +3912,24 @@
}
}
},
"node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
"integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.1"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
@@ -6138,9 +6283,9 @@
}
},
"node_modules/date-fns": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"license": "MIT",
"funding": {
"type": "github",
@@ -9761,6 +9906,20 @@
"node": ">=0.10.0"
}
},
"node_modules/react-day-picker": {
"version": "8.10.1",
"resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
"integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==",
"license": "MIT",
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/gpbl"
},
"peerDependencies": {
"date-fns": "^2.28.0 || ^3.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+3 -2
View File
@@ -25,7 +25,7 @@
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-slider": "^1.2.2",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.6",
@@ -36,7 +36,7 @@
"cmdk": "^1.0.0",
"cron-parser": "^5.0.2",
"croner": "^9.0.0",
"date-fns": "^4.1.0",
"date-fns": "^3.6.0",
"drizzle-orm": "^0.39.3",
"lodash.debounce": "^4.0.8",
"lucide-react": "^0.469.0",
@@ -45,6 +45,7 @@
"postgres": "^3.4.5",
"prismjs": "^1.29.0",
"react": "^18.2.0",
"react-day-picker": "^8.10.1",
"react-dom": "^18.2.0",
"react-simple-code-editor": "^0.14.1",
"reactflow": "^11.11.4",