kmod-cli 1.0.10
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 +53 -0
- package/bin/gen-components.js +68 -0
- package/bin/index.js +153 -0
- package/component-templates/components/access-denied.tsx +130 -0
- package/component-templates/components/breadcumb.tsx +42 -0
- package/component-templates/components/count-down.tsx +94 -0
- package/component-templates/components/count-input.tsx +221 -0
- package/component-templates/components/date-range-calendar/button.tsx +61 -0
- package/component-templates/components/date-range-calendar/calendar.tsx +132 -0
- package/component-templates/components/date-range-calendar/date-input.tsx +259 -0
- package/component-templates/components/date-range-calendar/date-range-picker.tsx +594 -0
- package/component-templates/components/date-range-calendar/label.tsx +31 -0
- package/component-templates/components/date-range-calendar/popover.tsx +32 -0
- package/component-templates/components/date-range-calendar/select.tsx +125 -0
- package/component-templates/components/date-range-calendar/switch.tsx +30 -0
- package/component-templates/components/datetime-picker/button.tsx +61 -0
- package/component-templates/components/datetime-picker/calendar.tsx +156 -0
- package/component-templates/components/datetime-picker/datetime-picker.tsx +75 -0
- package/component-templates/components/datetime-picker/input.tsx +20 -0
- package/component-templates/components/datetime-picker/label.tsx +18 -0
- package/component-templates/components/datetime-picker/period-input.tsx +62 -0
- package/component-templates/components/datetime-picker/popover.tsx +32 -0
- package/component-templates/components/datetime-picker/select.tsx +125 -0
- package/component-templates/components/datetime-picker/time-picker-input.tsx +131 -0
- package/component-templates/components/datetime-picker/time-picker-utils.tsx +204 -0
- package/component-templates/components/datetime-picker/time-picker.tsx +59 -0
- package/component-templates/components/gradient-outline.tsx +233 -0
- package/component-templates/components/gradient-svg.tsx +157 -0
- package/component-templates/components/grid-layout.tsx +69 -0
- package/component-templates/components/hydrate-guard.tsx +40 -0
- package/component-templates/components/image.tsx +92 -0
- package/component-templates/components/loader-slash-gradient.tsx +85 -0
- package/component-templates/components/masonry-gallery.tsx +221 -0
- package/component-templates/components/modal.tsx +110 -0
- package/component-templates/components/multi-select.tsx +447 -0
- package/component-templates/components/non-hydration.tsx +27 -0
- package/component-templates/components/portal.tsx +34 -0
- package/component-templates/components/segments-circle.tsx +235 -0
- package/component-templates/components/single-select.tsx +248 -0
- package/component-templates/components/stroke-circle.tsx +57 -0
- package/component-templates/components/table/column-table.tsx +15 -0
- package/component-templates/components/table/data-table.tsx +339 -0
- package/component-templates/components/table/readme.tsx +95 -0
- package/component-templates/components/table/table.tsx +60 -0
- package/component-templates/components/text-hover-effect.tsx +120 -0
- package/component-templates/components/timout-loader.tsx +52 -0
- package/component-templates/components/toast.tsx +994 -0
- package/component-templates/configs/config.ts +33 -0
- package/component-templates/configs/feature-config.tsx +432 -0
- package/component-templates/configs/keys.ts +7 -0
- package/component-templates/core/api-service.ts +202 -0
- package/component-templates/core/calculate.ts +18 -0
- package/component-templates/core/idb.ts +166 -0
- package/component-templates/core/storage.ts +213 -0
- package/component-templates/hooks/count-down.ts +38 -0
- package/component-templates/hooks/fade-on-scroll.ts +52 -0
- package/component-templates/hooks/safe-action.ts +59 -0
- package/component-templates/hooks/spam-guard.ts +31 -0
- package/component-templates/lib/utils.ts +6 -0
- package/component-templates/providers/feature-guard.tsx +432 -0
- package/component-templates/queries/query.tsx +775 -0
- package/component-templates/utils/colors/color-by-text.ts +307 -0
- package/component-templates/utils/colors/stripe-effect.ts +100 -0
- package/component-templates/utils/hash/hash-aes.ts +35 -0
- package/components.json +348 -0
- package/package.json +60 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
CheckIcon,
|
|
7
|
+
ChevronDownIcon,
|
|
8
|
+
} from '@radix-ui/react-icons';
|
|
9
|
+
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
10
|
+
|
|
11
|
+
import { cn } from '../../lib/utils';
|
|
12
|
+
|
|
13
|
+
const Select = SelectPrimitive.Root
|
|
14
|
+
|
|
15
|
+
const SelectGroup = SelectPrimitive.Group
|
|
16
|
+
|
|
17
|
+
const SelectValue = SelectPrimitive.Value
|
|
18
|
+
|
|
19
|
+
const SelectTrigger = React.forwardRef<
|
|
20
|
+
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
21
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
22
|
+
>(({ className, children, ...props }, ref) => (
|
|
23
|
+
<SelectPrimitive.Trigger
|
|
24
|
+
ref={ref}
|
|
25
|
+
className={cn(
|
|
26
|
+
'flex h-10 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
|
27
|
+
className
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
<SelectPrimitive.Icon asChild>
|
|
33
|
+
<ChevronDownIcon className="h-4 w-4 opacity-50" />
|
|
34
|
+
</SelectPrimitive.Icon>
|
|
35
|
+
</SelectPrimitive.Trigger>
|
|
36
|
+
))
|
|
37
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
|
|
38
|
+
|
|
39
|
+
const SelectContent = React.forwardRef<
|
|
40
|
+
React.ElementRef<typeof SelectPrimitive.Content>,
|
|
41
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
42
|
+
>(({ className, children, position = 'popper', ...props }, ref) => (
|
|
43
|
+
<SelectPrimitive.Portal>
|
|
44
|
+
<SelectPrimitive.Content
|
|
45
|
+
ref={ref}
|
|
46
|
+
className={cn(
|
|
47
|
+
'relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
48
|
+
position === 'popper' &&
|
|
49
|
+
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
position={position}
|
|
53
|
+
{...props}
|
|
54
|
+
>
|
|
55
|
+
<SelectPrimitive.Viewport
|
|
56
|
+
className={cn(
|
|
57
|
+
'p-1',
|
|
58
|
+
position === 'popper' &&
|
|
59
|
+
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]'
|
|
60
|
+
)}
|
|
61
|
+
>
|
|
62
|
+
{children}
|
|
63
|
+
</SelectPrimitive.Viewport>
|
|
64
|
+
</SelectPrimitive.Content>
|
|
65
|
+
</SelectPrimitive.Portal>
|
|
66
|
+
))
|
|
67
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName
|
|
68
|
+
|
|
69
|
+
const SelectLabel = React.forwardRef<
|
|
70
|
+
React.ElementRef<typeof SelectPrimitive.Label>,
|
|
71
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
|
72
|
+
>(({ className, ...props }, ref) => (
|
|
73
|
+
<SelectPrimitive.Label
|
|
74
|
+
ref={ref}
|
|
75
|
+
className={cn('py-1.5 pl-8 pr-2 text-sm font-semibold', className)}
|
|
76
|
+
{...props}
|
|
77
|
+
/>
|
|
78
|
+
))
|
|
79
|
+
SelectLabel.displayName = SelectPrimitive.Label.displayName
|
|
80
|
+
|
|
81
|
+
const SelectItem = React.forwardRef<
|
|
82
|
+
React.ElementRef<typeof SelectPrimitive.Item>,
|
|
83
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
84
|
+
>(({ className, children, ...props }, ref) => (
|
|
85
|
+
<SelectPrimitive.Item
|
|
86
|
+
ref={ref}
|
|
87
|
+
className={cn(
|
|
88
|
+
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
89
|
+
className
|
|
90
|
+
)}
|
|
91
|
+
{...props}
|
|
92
|
+
>
|
|
93
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
94
|
+
<SelectPrimitive.ItemIndicator>
|
|
95
|
+
<CheckIcon className="h-4 w-4" />
|
|
96
|
+
</SelectPrimitive.ItemIndicator>
|
|
97
|
+
</span>
|
|
98
|
+
|
|
99
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
100
|
+
</SelectPrimitive.Item>
|
|
101
|
+
))
|
|
102
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName
|
|
103
|
+
|
|
104
|
+
const SelectSeparator = React.forwardRef<
|
|
105
|
+
React.ElementRef<typeof SelectPrimitive.Separator>,
|
|
106
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
|
107
|
+
>(({ className, ...props }, ref) => (
|
|
108
|
+
<SelectPrimitive.Separator
|
|
109
|
+
ref={ref}
|
|
110
|
+
className={cn('-mx-1 my-1 h-px bg-muted', className)}
|
|
111
|
+
{...props}
|
|
112
|
+
/>
|
|
113
|
+
))
|
|
114
|
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
Select,
|
|
118
|
+
SelectContent,
|
|
119
|
+
SelectGroup,
|
|
120
|
+
SelectItem,
|
|
121
|
+
SelectLabel,
|
|
122
|
+
SelectSeparator,
|
|
123
|
+
SelectTrigger,
|
|
124
|
+
SelectValue,
|
|
125
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
6
|
+
|
|
7
|
+
import { cn } from '../../lib/utils';
|
|
8
|
+
|
|
9
|
+
const Switch = React.forwardRef<
|
|
10
|
+
React.ElementRef<typeof SwitchPrimitives.Root>,
|
|
11
|
+
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
|
12
|
+
>(({ className, ...props }, ref) => (
|
|
13
|
+
<SwitchPrimitives.Root
|
|
14
|
+
className={cn(
|
|
15
|
+
'peer inline-flex h-[20px] w-[36px] shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-not-allowed disabled:opacity-50 bg-indigo-200',
|
|
16
|
+
className
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
ref={ref}
|
|
20
|
+
>
|
|
21
|
+
<SwitchPrimitives.Thumb
|
|
22
|
+
className={cn(
|
|
23
|
+
'pointer-events-none block h-4 w-4 rounded-full data-[state=unchecked]:bg-white data-[state=checked]:bg-indigo-500 shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0'
|
|
24
|
+
)}
|
|
25
|
+
/>
|
|
26
|
+
</SwitchPrimitives.Root>
|
|
27
|
+
))
|
|
28
|
+
Switch.displayName = SwitchPrimitives.Root.displayName
|
|
29
|
+
|
|
30
|
+
export { Switch };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
cva,
|
|
5
|
+
type VariantProps,
|
|
6
|
+
} from 'class-variance-authority';
|
|
7
|
+
|
|
8
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
9
|
+
|
|
10
|
+
import { cn } from '../../lib/utils';
|
|
11
|
+
|
|
12
|
+
const buttonVariants = cva(
|
|
13
|
+
'inline-flex items-center justify-center rounded-full text-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
|
14
|
+
{
|
|
15
|
+
variants: {
|
|
16
|
+
variant: {
|
|
17
|
+
default: 'bg-black text-white',
|
|
18
|
+
destructive:
|
|
19
|
+
'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
20
|
+
outline:
|
|
21
|
+
'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
|
22
|
+
secondary:
|
|
23
|
+
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
24
|
+
ghost: 'hover:bg-hover-secondary hover:text-accent-foreground',
|
|
25
|
+
link: 'text-primary underline-offset-4 hover:underline'
|
|
26
|
+
},
|
|
27
|
+
size: {
|
|
28
|
+
default: 'h-10 px-4 py-2',
|
|
29
|
+
sm: 'h-9 rounded-full px-3',
|
|
30
|
+
lg: 'h-11 rounded-full px-8',
|
|
31
|
+
icon: 'h-10 w-10'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: 'default',
|
|
36
|
+
size: 'default'
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
export interface ButtonProps
|
|
42
|
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
43
|
+
VariantProps<typeof buttonVariants> {
|
|
44
|
+
asChild?: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
48
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
49
|
+
const Comp = asChild ? Slot : 'button'
|
|
50
|
+
return (
|
|
51
|
+
<Comp
|
|
52
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
53
|
+
ref={ref}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
Button.displayName = 'Button'
|
|
60
|
+
|
|
61
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
ChevronDownIcon,
|
|
7
|
+
ChevronLeftIcon,
|
|
8
|
+
ChevronRightIcon,
|
|
9
|
+
} from 'lucide-react';
|
|
10
|
+
import {
|
|
11
|
+
DayButton,
|
|
12
|
+
DayPicker,
|
|
13
|
+
getDefaultClassNames,
|
|
14
|
+
} from 'react-day-picker';
|
|
15
|
+
|
|
16
|
+
import { cn } from '../../lib/utils';
|
|
17
|
+
import {
|
|
18
|
+
Button,
|
|
19
|
+
buttonVariants,
|
|
20
|
+
} from './button';
|
|
21
|
+
|
|
22
|
+
function Calendar({
|
|
23
|
+
className,
|
|
24
|
+
classNames,
|
|
25
|
+
showOutsideDays = true,
|
|
26
|
+
captionLayout = "label",
|
|
27
|
+
buttonVariant = "ghost",
|
|
28
|
+
formatters,
|
|
29
|
+
components,
|
|
30
|
+
...props
|
|
31
|
+
}: React.ComponentProps<typeof DayPicker> & {
|
|
32
|
+
buttonVariant?: React.ComponentProps<typeof Button>["variant"];
|
|
33
|
+
}) {
|
|
34
|
+
const defaultClassNames = getDefaultClassNames();
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<DayPicker
|
|
38
|
+
showOutsideDays={showOutsideDays}
|
|
39
|
+
className={cn(
|
|
40
|
+
"bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
|
41
|
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
42
|
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
captionLayout={captionLayout}
|
|
46
|
+
formatters={{
|
|
47
|
+
formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
|
|
48
|
+
...formatters,
|
|
49
|
+
}}
|
|
50
|
+
classNames={{
|
|
51
|
+
root: cn("w-full", defaultClassNames.root),
|
|
52
|
+
months: cn("relative flex flex-col gap-4 md:flex-row", defaultClassNames.months),
|
|
53
|
+
month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
|
|
54
|
+
nav: cn("absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1", defaultClassNames.nav),
|
|
55
|
+
button_previous: cn(
|
|
56
|
+
buttonVariants({ variant: buttonVariant }),
|
|
57
|
+
"h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
|
|
58
|
+
defaultClassNames.button_previous,
|
|
59
|
+
),
|
|
60
|
+
button_next: cn(
|
|
61
|
+
buttonVariants({ variant: buttonVariant }),
|
|
62
|
+
"h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50",
|
|
63
|
+
defaultClassNames.button_next,
|
|
64
|
+
),
|
|
65
|
+
month_caption: cn("flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]", defaultClassNames.month_caption),
|
|
66
|
+
dropdowns: cn("flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium", defaultClassNames.dropdowns),
|
|
67
|
+
dropdown_root: cn(
|
|
68
|
+
"has-focus:border-ring border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border",
|
|
69
|
+
defaultClassNames.dropdown_root,
|
|
70
|
+
),
|
|
71
|
+
dropdown: cn("absolute inset-0 opacity-0", defaultClassNames.dropdown),
|
|
72
|
+
caption_label: cn(
|
|
73
|
+
"select-none font-medium",
|
|
74
|
+
captionLayout === "label"
|
|
75
|
+
? "text-sm"
|
|
76
|
+
: "[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5",
|
|
77
|
+
defaultClassNames.caption_label,
|
|
78
|
+
),
|
|
79
|
+
table: "w-full border-collapse",
|
|
80
|
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
81
|
+
weekday: cn("text-primary-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal", defaultClassNames.weekday),
|
|
82
|
+
week: cn("mt-2 flex w-full", defaultClassNames.week),
|
|
83
|
+
week_number_header: cn("w-[--cell-size] select-none", defaultClassNames.week_number_header),
|
|
84
|
+
week_number: cn("text-primary-foreground select-none text-[0.8rem]", defaultClassNames.week_number),
|
|
85
|
+
day: cn(
|
|
86
|
+
"group/day relative aspect-square h-full w-full select-none p-0 text-center data-[selected=true]:text-primary-foreground [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
|
|
87
|
+
defaultClassNames.day,
|
|
88
|
+
),
|
|
89
|
+
range_start: cn("bg-accent rounded-l-md", defaultClassNames.range_start),
|
|
90
|
+
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
|
91
|
+
range_end: cn("bg-accent rounded-r-md", defaultClassNames.range_end),
|
|
92
|
+
today: cn("bg-accent text-accent-foreground rounded-md data-[selected=true]:text-primary-foreground data-[selected=true]:rounded-none", defaultClassNames.today),
|
|
93
|
+
outside: cn("text-muted-foreground aria-selected:text-muted-foreground", defaultClassNames.outside),
|
|
94
|
+
disabled: cn("text-muted-foreground opacity-50", defaultClassNames.disabled),
|
|
95
|
+
hidden: cn("invisible", defaultClassNames.hidden),
|
|
96
|
+
...classNames,
|
|
97
|
+
}}
|
|
98
|
+
components={{
|
|
99
|
+
Root: ({ className, rootRef, ...props }) => {
|
|
100
|
+
return <div data-slot="calendar" ref={rootRef} className={cn(className)} {...props} />;
|
|
101
|
+
},
|
|
102
|
+
Chevron: ({ className, orientation, ...props }) => {
|
|
103
|
+
if (orientation === "left") {
|
|
104
|
+
return <ChevronLeftIcon className={cn("size-4", className)} {...props} />;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (orientation === "right") {
|
|
108
|
+
return <ChevronRightIcon className={cn("size-4", className)} {...props} />;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return <ChevronDownIcon className={cn("size-4", className)} {...props} />;
|
|
112
|
+
},
|
|
113
|
+
DayButton: CalendarDayButton,
|
|
114
|
+
WeekNumber: ({ children, ...props }) => {
|
|
115
|
+
return (
|
|
116
|
+
<td {...props}>
|
|
117
|
+
<div className="flex size-[--cell-size] items-center justify-center text-center">{children}</div>
|
|
118
|
+
</td>
|
|
119
|
+
);
|
|
120
|
+
},
|
|
121
|
+
...components,
|
|
122
|
+
}}
|
|
123
|
+
{...props}
|
|
124
|
+
/>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function CalendarDayButton({ className, day, modifiers, ...props }: React.ComponentProps<typeof DayButton>) {
|
|
129
|
+
const defaultClassNames = getDefaultClassNames();
|
|
130
|
+
|
|
131
|
+
const ref = React.useRef<HTMLButtonElement>(null);
|
|
132
|
+
React.useEffect(() => {
|
|
133
|
+
if (modifiers.focused) ref.current?.focus();
|
|
134
|
+
}, [modifiers.focused]);
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<Button
|
|
138
|
+
ref={ref}
|
|
139
|
+
variant="ghost"
|
|
140
|
+
size="icon"
|
|
141
|
+
data-day={day.date.toLocaleDateString()}
|
|
142
|
+
data-selected-single={modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle}
|
|
143
|
+
data-range-start={modifiers.range_start}
|
|
144
|
+
data-range-end={modifiers.range_end}
|
|
145
|
+
data-range-middle={modifiers.range_middle}
|
|
146
|
+
className={cn(
|
|
147
|
+
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md [&>span]:text-xs [&>span]:opacity-70",
|
|
148
|
+
defaultClassNames.day,
|
|
149
|
+
className,
|
|
150
|
+
)}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export { Calendar, CalendarDayButton };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
add,
|
|
7
|
+
format,
|
|
8
|
+
} from 'date-fns';
|
|
9
|
+
import { Calendar as CalendarIcon } from 'lucide-react';
|
|
10
|
+
|
|
11
|
+
import { cn } from '../../lib/utils';
|
|
12
|
+
import { Button } from './button';
|
|
13
|
+
import { Calendar } from './calendar';
|
|
14
|
+
import {
|
|
15
|
+
Popover,
|
|
16
|
+
PopoverContent,
|
|
17
|
+
PopoverTrigger,
|
|
18
|
+
} from './popover';
|
|
19
|
+
import { TimePicker } from './time-picker';
|
|
20
|
+
|
|
21
|
+
export function DateTimePicker({
|
|
22
|
+
date: selectedDate,
|
|
23
|
+
onSelectDate,
|
|
24
|
+
}: {
|
|
25
|
+
date: Date | undefined;
|
|
26
|
+
onSelectDate: (date: Date | undefined) => void;
|
|
27
|
+
}) {
|
|
28
|
+
const [date, setDate] = React.useState<Date | undefined>(selectedDate || new Date());
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* carry over the current time when a user clicks a new day
|
|
32
|
+
* instead of resetting to 00:00
|
|
33
|
+
*/
|
|
34
|
+
const handleSelect = (newDay: Date | undefined) => {
|
|
35
|
+
if (!newDay) return;
|
|
36
|
+
if (!date) {
|
|
37
|
+
setDate(newDay);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const diff = newDay.getTime() - date.getTime();
|
|
41
|
+
const diffInDays = diff / (1000 * 60 * 60 * 24);
|
|
42
|
+
const newDateFull = add(date, { days: Math.ceil(diffInDays) });
|
|
43
|
+
setDate(newDateFull);
|
|
44
|
+
onSelectDate(newDateFull);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Popover>
|
|
49
|
+
<PopoverTrigger asChild>
|
|
50
|
+
<Button
|
|
51
|
+
variant={"outline"}
|
|
52
|
+
className={cn(
|
|
53
|
+
"w-full shadow-none justify-start text-left ",
|
|
54
|
+
!date && "text-muted-foreground"
|
|
55
|
+
)}
|
|
56
|
+
>
|
|
57
|
+
<CalendarIcon className="mr-2 h-4 w-4" />
|
|
58
|
+
{date ? format(date, "PPP HH:mm:ss") : <span>MM/DD/YYYY HH:MM:SS</span>}
|
|
59
|
+
</Button>
|
|
60
|
+
</PopoverTrigger>
|
|
61
|
+
<PopoverContent className="w-full p-0 !z-[120] overflow-hidden">
|
|
62
|
+
<Calendar
|
|
63
|
+
mode="single"
|
|
64
|
+
selected={date}
|
|
65
|
+
className="min-w-[250px]"
|
|
66
|
+
onSelect={(d) => handleSelect(d)}
|
|
67
|
+
initialFocus
|
|
68
|
+
/>
|
|
69
|
+
<div className="p-3 border-t border-border">
|
|
70
|
+
<TimePicker setDate={setDate} date={date} />
|
|
71
|
+
</div>
|
|
72
|
+
</PopoverContent>
|
|
73
|
+
</Popover>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
|
+
|
|
5
|
+
const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(({ className, type, ...props }, ref) => {
|
|
6
|
+
return (
|
|
7
|
+
<input
|
|
8
|
+
type={type}
|
|
9
|
+
className={cn(
|
|
10
|
+
"border-input file:text-foreground placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-1 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
11
|
+
className,
|
|
12
|
+
)}
|
|
13
|
+
ref={ref}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
});
|
|
18
|
+
Input.displayName = "Input";
|
|
19
|
+
|
|
20
|
+
export { Input };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
+
|
|
7
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
8
|
+
import { cn } from "../../lib/utils";
|
|
9
|
+
|
|
10
|
+
const labelVariants = cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
|
|
11
|
+
|
|
12
|
+
const Label = React.forwardRef<
|
|
13
|
+
React.ElementRef<typeof LabelPrimitive.Root>,
|
|
14
|
+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & VariantProps<typeof labelVariants>
|
|
15
|
+
>(({ className, ...props }, ref) => <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />);
|
|
16
|
+
Label.displayName = LabelPrimitive.Root.displayName;
|
|
17
|
+
|
|
18
|
+
export { Label };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Select,
|
|
7
|
+
SelectContent,
|
|
8
|
+
SelectItem,
|
|
9
|
+
SelectTrigger,
|
|
10
|
+
SelectValue,
|
|
11
|
+
} from './select';
|
|
12
|
+
import {
|
|
13
|
+
display12HourValue,
|
|
14
|
+
Period,
|
|
15
|
+
setDateByType,
|
|
16
|
+
} from './time-picker-utils';
|
|
17
|
+
|
|
18
|
+
export interface PeriodSelectorProps {
|
|
19
|
+
period: Period;
|
|
20
|
+
setPeriod: (m: Period) => void;
|
|
21
|
+
date: Date | undefined;
|
|
22
|
+
setDate: (date: Date | undefined) => void;
|
|
23
|
+
onRightFocus?: () => void;
|
|
24
|
+
onLeftFocus?: () => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const TimePeriodSelect = React.forwardRef<HTMLButtonElement, PeriodSelectorProps>(({ period, setPeriod, date, setDate, onLeftFocus, onRightFocus }, ref) => {
|
|
28
|
+
const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {
|
|
29
|
+
if (e.key === "ArrowRight") onRightFocus?.();
|
|
30
|
+
if (e.key === "ArrowLeft") onLeftFocus?.();
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handleValueChange = (value: Period) => {
|
|
34
|
+
setPeriod(value);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* trigger an update whenever the user switches between AM and PM;
|
|
38
|
+
* otherwise user must manually change the hour each time
|
|
39
|
+
*/
|
|
40
|
+
if (date) {
|
|
41
|
+
const tempDate = new Date(date);
|
|
42
|
+
const hours = display12HourValue(date.getHours());
|
|
43
|
+
setDate(setDateByType(tempDate, hours.toString(), "12hours", period === "AM" ? "PM" : "AM"));
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div className="flex h-10 items-center">
|
|
49
|
+
<Select value={period} onValueChange={(value: Period) => handleValueChange(value)}>
|
|
50
|
+
<SelectTrigger ref={ref} className="w-[65px] focus:bg-accent focus:text-accent-foreground" onKeyDown={handleKeyDown}>
|
|
51
|
+
<SelectValue />
|
|
52
|
+
</SelectTrigger>
|
|
53
|
+
<SelectContent>
|
|
54
|
+
<SelectItem value="AM">AM</SelectItem>
|
|
55
|
+
<SelectItem value="PM">PM</SelectItem>
|
|
56
|
+
</SelectContent>
|
|
57
|
+
</Select>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
TimePeriodSelect.displayName = "TimePeriodSelect";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
6
|
+
|
|
7
|
+
import { cn } from '../../lib/utils';
|
|
8
|
+
|
|
9
|
+
const Popover = PopoverPrimitive.Root
|
|
10
|
+
|
|
11
|
+
const PopoverTrigger = PopoverPrimitive.Trigger
|
|
12
|
+
|
|
13
|
+
const PopoverContent = React.forwardRef<
|
|
14
|
+
React.ElementRef<typeof PopoverPrimitive.Content>,
|
|
15
|
+
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
|
16
|
+
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
|
|
17
|
+
<PopoverPrimitive.Portal>
|
|
18
|
+
<PopoverPrimitive.Content
|
|
19
|
+
ref={ref}
|
|
20
|
+
align={align}
|
|
21
|
+
sideOffset={sideOffset}
|
|
22
|
+
className={cn(
|
|
23
|
+
'z-50 w-72 rounded-md border bg-white p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
</PopoverPrimitive.Portal>
|
|
29
|
+
))
|
|
30
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
|
31
|
+
|
|
32
|
+
export { Popover, PopoverContent, PopoverTrigger };
|