mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
improvement(starter): added date/time picker
This commit is contained in:
@@ -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
@@ -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',
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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 }
|
||||
Generated
+167
-8
@@ -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
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user