@gram-ai/elements 1.27.3 → 1.27.5
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 +72 -60
- package/README.typedoc.md +6 -6
- package/bin/cli.js +74 -74
- package/dist/compat-shims-CO9JXXV4.cjs.map +1 -1
- package/dist/{compat-shims-BPJ7Q68c.js → compat-shims-DxtUrORi.js} +4 -2
- package/dist/compat-shims-DxtUrORi.js.map +1 -0
- package/dist/components/ShareButton/index.d.ts +2 -2
- package/dist/components/assistant-ui/message-feedback.d.ts +1 -1
- package/dist/components/assistant-ui/tooltip-icon-button.d.ts +2 -2
- package/dist/components/ui/avatar.d.ts +2 -2
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/calendar.d.ts +1 -1
- package/dist/components/ui/collapsible.d.ts +1 -1
- package/dist/components/ui/dialog.d.ts +4 -4
- package/dist/components/ui/popover.d.ts +2 -2
- package/dist/components/ui/skeleton.d.ts +1 -1
- package/dist/components/ui/time-range-picker.d.ts +4 -2
- package/dist/components/ui/tool-ui.d.ts +7 -7
- package/dist/components/ui/tooltip.d.ts +2 -2
- package/dist/contexts/ConnectionStatusContext.d.ts +1 -1
- package/dist/elements.cjs +1 -1
- package/dist/elements.css +1 -1
- package/dist/elements.js +2 -2
- package/dist/hooks/useDensity.d.ts +73 -73
- package/dist/hooks/useMCPTools.d.ts +1 -1
- package/dist/hooks/useRadius.d.ts +1 -1
- package/dist/{index-BpJstUh1.cjs → index-C4bFBGfl.cjs} +4 -4
- package/dist/{index-BpJstUh1.cjs.map → index-C4bFBGfl.cjs.map} +1 -1
- package/dist/{index-CUitXazZ.js → index-D93pV0_o.js} +55 -55
- package/dist/{index-CUitXazZ.js.map → index-D93pV0_o.js.map} +1 -1
- package/dist/{index-DBrhzauj.js → index-DuCQRbcQ.js} +6386 -6337
- package/dist/index-DuCQRbcQ.js.map +1 -0
- package/dist/{index-DxfW52oA.cjs → index-y_PNN5vK.cjs} +64 -46
- package/dist/index-y_PNN5vK.cjs.map +1 -0
- package/dist/lib/cassette.d.ts +4 -4
- package/dist/lib/errorTracking.d.ts +1 -1
- package/dist/lib/messageConverter.d.ts +1 -1
- package/dist/lib/models.d.ts +1 -1
- package/dist/plugins/chart/ui/bar-chart.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/accordion-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/accordion.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/action-button.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/alert-wrapper.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/alert.d.ts +4 -4
- package/dist/plugins/generative-ui/ui/avatar.d.ts +5 -5
- package/dist/plugins/generative-ui/ui/badge.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/button-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/button.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/card-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/card.d.ts +8 -8
- package/dist/plugins/generative-ui/ui/checkbox.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/data-table.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/dialog.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/dropdown-menu.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/grid.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/input-wrapper.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/input.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/label.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/metric.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/pagination.d.ts +6 -6
- package/dist/plugins/generative-ui/ui/popover.d.ts +4 -4
- package/dist/plugins/generative-ui/ui/progress.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/radio-group.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/select.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/separator.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/skeleton.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/stack.d.ts +6 -6
- package/dist/plugins/generative-ui/ui/switch.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/table.d.ts +9 -9
- package/dist/plugins/generative-ui/ui/tabs-wrapper.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/tabs.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/text.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/textarea.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/tooltip.d.ts +1 -1
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.js +1 -1
- package/dist/{profiler-D6ndqfsd.js → profiler-FpBY9eRv.js} +2 -2
- package/dist/{profiler-D6ndqfsd.js.map → profiler-FpBY9eRv.js.map} +1 -1
- package/dist/{profiler-DhnzZ34c.cjs → profiler-_mthyjvo.cjs} +2 -2
- package/dist/{profiler-DhnzZ34c.cjs.map → profiler-_mthyjvo.cjs.map} +1 -1
- package/dist/react-shim.js +1 -1
- package/dist/server/express.cjs.map +1 -1
- package/dist/server/express.js.map +1 -1
- package/dist/{startRecording-BwXmdmy1.cjs → startRecording-NJcpiHw-.cjs} +2 -2
- package/dist/{startRecording-BwXmdmy1.cjs.map → startRecording-NJcpiHw-.cjs.map} +1 -1
- package/dist/{startRecording-B_9CRZ_P.js → startRecording-r5MXQ2Dm.js} +2 -2
- package/dist/{startRecording-B_9CRZ_P.js.map → startRecording-r5MXQ2Dm.js.map} +1 -1
- package/dist/types/index.d.ts +2 -2
- package/package.json +1 -5
- package/src/compat-plugin.ts +14 -14
- package/src/compat-shims.ts +33 -31
- package/src/compat.test.ts +48 -48
- package/src/compat.ts +6 -6
- package/src/components/Chat/index.tsx +17 -17
- package/src/components/Chat/stories/Charts.stories.tsx +98 -98
- package/src/components/Chat/stories/Composer.stories.tsx +15 -15
- package/src/components/Chat/stories/ConnectionConfiguration.stories.tsx +44 -44
- package/src/components/Chat/stories/CustomComponents.stories.tsx +17 -17
- package/src/components/Chat/stories/Density.stories.tsx +20 -20
- package/src/components/Chat/stories/ErrorBoundary.stories.tsx +47 -47
- package/src/components/Chat/stories/FrontendTools.stories.tsx +39 -39
- package/src/components/Chat/stories/GenerativeUI.stories.tsx +48 -48
- package/src/components/Chat/stories/MessageFeedback.stories.tsx +52 -52
- package/src/components/Chat/stories/Modal.stories.tsx +28 -28
- package/src/components/Chat/stories/Model.stories.tsx +11 -11
- package/src/components/Chat/stories/Radius.stories.tsx +20 -20
- package/src/components/Chat/stories/Sidecar.stories.tsx +13 -13
- package/src/components/Chat/stories/StyleIsolation.stories.tsx +11 -11
- package/src/components/Chat/stories/Theme.stories.tsx +25 -25
- package/src/components/Chat/stories/Thread.stories.tsx +25 -25
- package/src/components/Chat/stories/ToolApproval.stories.tsx +55 -55
- package/src/components/Chat/stories/ToolMentions.stories.tsx +17 -17
- package/src/components/Chat/stories/Tools.stories.tsx +88 -88
- package/src/components/Chat/stories/Variants.stories.tsx +32 -32
- package/src/components/Chat/stories/Welcome.stories.tsx +14 -14
- package/src/components/ChatHistory.tsx +7 -7
- package/src/components/FrontendTools/index.tsx +5 -5
- package/src/components/Replay.stories.tsx +157 -157
- package/src/components/Replay.tsx +76 -73
- package/src/components/ShadowRoot.tsx +40 -40
- package/src/components/ShareButton/index.tsx +32 -32
- package/src/components/assistant-ui/assistant-modal.tsx +92 -87
- package/src/components/assistant-ui/assistant-sidecar.tsx +35 -35
- package/src/components/assistant-ui/attachment.tsx +80 -80
- package/src/components/assistant-ui/connection-status-indicator.tsx +33 -33
- package/src/components/assistant-ui/error-boundary.tsx +34 -34
- package/src/components/assistant-ui/follow-on-suggestions.tsx +26 -26
- package/src/components/assistant-ui/markdown-text.tsx +69 -69
- package/src/components/assistant-ui/mentioned-tools-badges.tsx +38 -38
- package/src/components/assistant-ui/message-feedback.tsx +74 -61
- package/src/components/assistant-ui/reasoning.tsx +83 -83
- package/src/components/assistant-ui/thread-list.tsx +45 -45
- package/src/components/assistant-ui/thread.tsx +278 -278
- package/src/components/assistant-ui/tool-fallback.tsx +37 -37
- package/src/components/assistant-ui/tool-group.tsx +26 -26
- package/src/components/assistant-ui/tool-mention-autocomplete.tsx +122 -122
- package/src/components/assistant-ui/tooltip-icon-button.tsx +18 -18
- package/src/components/ui/avatar.tsx +12 -12
- package/src/components/ui/button.tsx +12 -12
- package/src/components/ui/buttonVariants.ts +17 -17
- package/src/components/ui/calendar.tsx +106 -106
- package/src/components/ui/charts.stories.tsx +56 -56
- package/src/components/ui/collapsible.tsx +5 -5
- package/src/components/ui/dialog.tsx +30 -30
- package/src/components/ui/generative-ui.stories.tsx +200 -200
- package/src/components/ui/generative-ui.tsx +26 -26
- package/src/components/ui/popover.tsx +14 -14
- package/src/components/ui/skeleton.tsx +5 -5
- package/src/components/ui/time-range-picker.stories.tsx +80 -80
- package/src/components/ui/time-range-picker.tsx +272 -235
- package/src/components/ui/tool-ui.stories.tsx +37 -37
- package/src/components/ui/tool-ui.tsx +221 -215
- package/src/components/ui/tooltip.tsx +15 -15
- package/src/constants/tailwind.ts +1 -1
- package/src/contexts/ChatIdContext.tsx +7 -7
- package/src/contexts/ConnectionStatusContext.tsx +64 -64
- package/src/contexts/ElementsProvider.tsx +222 -211
- package/src/contexts/ReplayContext.ts +3 -3
- package/src/contexts/ToolApprovalContext.tsx +54 -54
- package/src/contexts/ToolExecutionContext.tsx +34 -34
- package/src/contexts/contexts.ts +7 -7
- package/src/contexts/portal-container-context.ts +2 -2
- package/src/contexts/portal-container.tsx +7 -7
- package/src/embedded.ts +1 -1
- package/src/global.css +25 -25
- package/src/hooks/useAuth.ts +72 -72
- package/src/hooks/useDensity.ts +79 -79
- package/src/hooks/useElements.ts +6 -6
- package/src/hooks/useExpanded.ts +12 -12
- package/src/hooks/useFollowOnSuggestions.ts +87 -82
- package/src/hooks/useGramThreadListAdapter.tsx +99 -99
- package/src/hooks/useMCPTools.ts +47 -47
- package/src/hooks/useModel.ts +14 -14
- package/src/hooks/usePluginComponents.ts +11 -11
- package/src/hooks/usePortalContainer.ts +5 -5
- package/src/hooks/useRadius.ts +23 -23
- package/src/hooks/useRecordCassette.ts +34 -34
- package/src/hooks/useSession.ts +11 -11
- package/src/hooks/useThemeProps.ts +13 -13
- package/src/hooks/useThreadId.ts +4 -4
- package/src/hooks/useToolApproval.ts +7 -7
- package/src/hooks/useToolMentions.ts +40 -40
- package/src/index.ts +26 -26
- package/src/lib/api.test.ts +61 -61
- package/src/lib/api.ts +4 -3
- package/src/lib/auth.ts +13 -13
- package/src/lib/cassette.ts +84 -84
- package/src/lib/easing.ts +1 -1
- package/src/lib/errorTracking.config.ts +5 -5
- package/src/lib/errorTracking.ts +29 -29
- package/src/lib/generative-ui.ts +7 -7
- package/src/lib/humanize.ts +3 -3
- package/src/lib/messageConverter.test.ts +130 -127
- package/src/lib/messageConverter.ts +196 -196
- package/src/lib/models.ts +21 -20
- package/src/lib/token.test.ts +56 -56
- package/src/lib/token.ts +14 -14
- package/src/lib/tool-mentions.ts +45 -45
- package/src/lib/tools.ts +66 -62
- package/src/lib/utils.ts +5 -5
- package/src/lib.d.ts +1 -1
- package/src/plugins/README.md +5 -5
- package/src/plugins/chart/catalog.ts +18 -18
- package/src/plugins/chart/chart.test.ts +31 -31
- package/src/plugins/chart/component.tsx +34 -34
- package/src/plugins/chart/index.ts +4 -4
- package/src/plugins/chart/ui/area-chart.tsx +42 -42
- package/src/plugins/chart/ui/bar-chart.tsx +46 -46
- package/src/plugins/chart/ui/donut-chart.tsx +48 -48
- package/src/plugins/chart/ui/index.ts +7 -7
- package/src/plugins/chart/ui/line-chart.tsx +43 -43
- package/src/plugins/chart/ui/pie-chart.tsx +44 -44
- package/src/plugins/chart/ui/radar-chart.tsx +33 -33
- package/src/plugins/chart/ui/scatter-chart.tsx +43 -43
- package/src/plugins/components/MacOSWindowFrame.tsx +15 -15
- package/src/plugins/components/PluginLoadingState.tsx +10 -10
- package/src/plugins/components/index.ts +1 -1
- package/src/plugins/generative-ui/catalog.ts +54 -54
- package/src/plugins/generative-ui/component.tsx +85 -85
- package/src/plugins/generative-ui/index.ts +4 -4
- package/src/plugins/generative-ui/ui/accordion-wrapper.tsx +16 -16
- package/src/plugins/generative-ui/ui/accordion.tsx +16 -16
- package/src/plugins/generative-ui/ui/action-button.tsx +28 -28
- package/src/plugins/generative-ui/ui/alert-wrapper.tsx +8 -8
- package/src/plugins/generative-ui/ui/alert.tsx +20 -20
- package/src/plugins/generative-ui/ui/avatar-wrapper.tsx +7 -7
- package/src/plugins/generative-ui/ui/avatar.tsx +30 -30
- package/src/plugins/generative-ui/ui/badge.tsx +22 -22
- package/src/plugins/generative-ui/ui/button-wrapper.tsx +12 -12
- package/src/plugins/generative-ui/ui/button.tsx +28 -28
- package/src/plugins/generative-ui/ui/card-wrapper.tsx +8 -8
- package/src/plugins/generative-ui/ui/card.tsx +27 -27
- package/src/plugins/generative-ui/ui/checkbox-wrapper.tsx +9 -9
- package/src/plugins/generative-ui/ui/checkbox.tsx +9 -9
- package/src/plugins/generative-ui/ui/data-table.tsx +8 -8
- package/src/plugins/generative-ui/ui/dialog.tsx +31 -31
- package/src/plugins/generative-ui/ui/dropdown-menu.tsx +44 -44
- package/src/plugins/generative-ui/ui/grid.tsx +12 -12
- package/src/plugins/generative-ui/ui/index.ts +40 -40
- package/src/plugins/generative-ui/ui/input-wrapper.tsx +11 -11
- package/src/plugins/generative-ui/ui/input.tsx +9 -9
- package/src/plugins/generative-ui/ui/label.tsx +8 -8
- package/src/plugins/generative-ui/ui/list.tsx +11 -11
- package/src/plugins/generative-ui/ui/metric.tsx +23 -23
- package/src/plugins/generative-ui/ui/pagination.tsx +28 -28
- package/src/plugins/generative-ui/ui/popover.tsx +21 -21
- package/src/plugins/generative-ui/ui/progress.tsx +13 -13
- package/src/plugins/generative-ui/ui/radio-group.tsx +12 -12
- package/src/plugins/generative-ui/ui/select-wrapper.tsx +7 -7
- package/src/plugins/generative-ui/ui/select.tsx +37 -37
- package/src/plugins/generative-ui/ui/separator.tsx +9 -9
- package/src/plugins/generative-ui/ui/skeleton-wrapper.tsx +10 -10
- package/src/plugins/generative-ui/ui/skeleton.tsx +5 -5
- package/src/plugins/generative-ui/ui/stack.tsx +28 -28
- package/src/plugins/generative-ui/ui/switch.tsx +11 -11
- package/src/plugins/generative-ui/ui/table.tsx +32 -32
- package/src/plugins/generative-ui/ui/tabs-wrapper.tsx +11 -11
- package/src/plugins/generative-ui/ui/tabs.tsx +26 -26
- package/src/plugins/generative-ui/ui/text.tsx +12 -12
- package/src/plugins/generative-ui/ui/textarea.tsx +7 -7
- package/src/plugins/generative-ui/ui/tooltip.tsx +12 -12
- package/src/plugins/index.ts +7 -7
- package/src/react-shim.ts +6 -6
- package/src/server/bun.ts +12 -12
- package/src/server/core.ts +25 -25
- package/src/server/express.ts +17 -15
- package/src/server/fastify.ts +14 -14
- package/src/server/hono.ts +9 -9
- package/src/server/nextjs.ts +12 -12
- package/src/server/tanstack-start.ts +12 -12
- package/src/server.ts +27 -27
- package/src/storybook.d.ts +4 -4
- package/src/types/index.ts +122 -122
- package/src/types/plugins.ts +7 -7
- package/src/vite-env.d.ts +12 -12
- package/dist/compat-shims-BPJ7Q68c.js.map +0 -1
- package/dist/index-DBrhzauj.js.map +0 -1
- package/dist/index-DxfW52oA.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import * as AvatarPrimitive from
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
3
3
|
|
|
4
|
-
import { cn } from
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
5
|
|
|
6
6
|
function Avatar({
|
|
7
7
|
className,
|
|
@@ -11,12 +11,12 @@ function Avatar({
|
|
|
11
11
|
<AvatarPrimitive.Root
|
|
12
12
|
data-slot="avatar"
|
|
13
13
|
className={cn(
|
|
14
|
-
|
|
15
|
-
className
|
|
14
|
+
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
|
|
15
|
+
className,
|
|
16
16
|
)}
|
|
17
17
|
{...props}
|
|
18
18
|
/>
|
|
19
|
-
)
|
|
19
|
+
);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function AvatarImage({
|
|
@@ -26,10 +26,10 @@ function AvatarImage({
|
|
|
26
26
|
return (
|
|
27
27
|
<AvatarPrimitive.Image
|
|
28
28
|
data-slot="avatar-image"
|
|
29
|
-
className={cn(
|
|
29
|
+
className={cn("aspect-square size-full", className)}
|
|
30
30
|
{...props}
|
|
31
31
|
/>
|
|
32
|
-
)
|
|
32
|
+
);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function AvatarFallback({
|
|
@@ -40,12 +40,12 @@ function AvatarFallback({
|
|
|
40
40
|
<AvatarPrimitive.Fallback
|
|
41
41
|
data-slot="avatar-fallback"
|
|
42
42
|
className={cn(
|
|
43
|
-
|
|
44
|
-
className
|
|
43
|
+
"flex size-full items-center justify-center rounded-full bg-muted",
|
|
44
|
+
className,
|
|
45
45
|
)}
|
|
46
46
|
{...props}
|
|
47
47
|
/>
|
|
48
|
-
)
|
|
48
|
+
);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
export { Avatar, AvatarImage, AvatarFallback }
|
|
51
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import { Slot } from
|
|
3
|
-
import { type VariantProps } from
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { type VariantProps } from "class-variance-authority";
|
|
4
4
|
|
|
5
|
-
import { cn } from
|
|
6
|
-
import { buttonVariants } from
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import { buttonVariants } from "./buttonVariants";
|
|
7
7
|
|
|
8
8
|
const Button = React.forwardRef<
|
|
9
9
|
HTMLButtonElement,
|
|
10
|
-
React.ComponentProps<
|
|
10
|
+
React.ComponentProps<"button"> &
|
|
11
11
|
VariantProps<typeof buttonVariants> & {
|
|
12
|
-
asChild?: boolean
|
|
12
|
+
asChild?: boolean;
|
|
13
13
|
}
|
|
14
14
|
>(({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
15
|
-
const Comp = asChild ? Slot :
|
|
15
|
+
const Comp = asChild ? Slot : "button";
|
|
16
16
|
return (
|
|
17
17
|
<Comp
|
|
18
18
|
data-slot="button"
|
|
@@ -20,8 +20,8 @@ const Button = React.forwardRef<
|
|
|
20
20
|
ref={ref}
|
|
21
21
|
{...props}
|
|
22
22
|
/>
|
|
23
|
-
)
|
|
24
|
-
})
|
|
25
|
-
Button.displayName =
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
Button.displayName = "Button";
|
|
26
26
|
|
|
27
|
-
export { Button }
|
|
27
|
+
export { Button };
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import { cva } from
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
2
|
|
|
3
3
|
export const buttonVariants = cva(
|
|
4
4
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
5
5
|
{
|
|
6
6
|
variants: {
|
|
7
7
|
variant: {
|
|
8
|
-
default:
|
|
8
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
9
9
|
destructive:
|
|
10
|
-
|
|
10
|
+
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
11
11
|
outline:
|
|
12
|
-
|
|
12
|
+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
13
13
|
secondary:
|
|
14
|
-
|
|
14
|
+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
15
15
|
ghost:
|
|
16
|
-
|
|
17
|
-
link:
|
|
16
|
+
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
17
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
18
18
|
},
|
|
19
19
|
size: {
|
|
20
|
-
default:
|
|
21
|
-
sm:
|
|
22
|
-
lg:
|
|
23
|
-
icon:
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
21
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
22
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
23
|
+
icon: "size-9",
|
|
24
|
+
"icon-sm": "size-8",
|
|
25
|
+
"icon-lg": "size-10",
|
|
26
26
|
},
|
|
27
27
|
},
|
|
28
28
|
defaultVariants: {
|
|
29
|
-
variant:
|
|
30
|
-
size:
|
|
29
|
+
variant: "default",
|
|
30
|
+
size: "default",
|
|
31
31
|
},
|
|
32
|
-
}
|
|
33
|
-
)
|
|
32
|
+
},
|
|
33
|
+
);
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import { ChevronLeft, ChevronRight } from
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
3
3
|
|
|
4
|
-
import { cn } from
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
5
|
|
|
6
6
|
export interface CalendarProps {
|
|
7
7
|
/** Selected date range */
|
|
8
|
-
selected?: { start: Date | null; end: Date | null }
|
|
8
|
+
selected?: { start: Date | null; end: Date | null };
|
|
9
9
|
/** Called when a date or range is selected */
|
|
10
|
-
onSelect?: (range: { start: Date; end: Date | null }) => void
|
|
10
|
+
onSelect?: (range: { start: Date; end: Date | null }) => void;
|
|
11
11
|
/** Whether range selection is enabled */
|
|
12
|
-
mode?:
|
|
12
|
+
mode?: "single" | "range";
|
|
13
13
|
/** Disable dates before this */
|
|
14
|
-
minDate?: Date
|
|
14
|
+
minDate?: Date;
|
|
15
15
|
/** Disable dates after this */
|
|
16
|
-
maxDate?: Date
|
|
16
|
+
maxDate?: Date;
|
|
17
17
|
/** Additional className */
|
|
18
|
-
className?: string
|
|
18
|
+
className?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
interface CalendarDay {
|
|
22
|
-
date: Date
|
|
23
|
-
isCurrentMonth: boolean
|
|
24
|
-
isToday: boolean
|
|
25
|
-
isSelected: boolean
|
|
26
|
-
isInRange: boolean
|
|
27
|
-
isRangeStart: boolean
|
|
28
|
-
isRangeEnd: boolean
|
|
29
|
-
isDisabled: boolean
|
|
22
|
+
date: Date;
|
|
23
|
+
isCurrentMonth: boolean;
|
|
24
|
+
isToday: boolean;
|
|
25
|
+
isSelected: boolean;
|
|
26
|
+
isInRange: boolean;
|
|
27
|
+
isRangeStart: boolean;
|
|
28
|
+
isRangeEnd: boolean;
|
|
29
|
+
isDisabled: boolean;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const WEEKDAYS = [
|
|
32
|
+
const WEEKDAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
33
33
|
const MONTHS = [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
]
|
|
34
|
+
"January",
|
|
35
|
+
"February",
|
|
36
|
+
"March",
|
|
37
|
+
"April",
|
|
38
|
+
"May",
|
|
39
|
+
"June",
|
|
40
|
+
"July",
|
|
41
|
+
"August",
|
|
42
|
+
"September",
|
|
43
|
+
"October",
|
|
44
|
+
"November",
|
|
45
|
+
"December",
|
|
46
|
+
];
|
|
47
47
|
|
|
48
48
|
function isSameDay(a: Date, b: Date): boolean {
|
|
49
49
|
return (
|
|
50
50
|
a.getFullYear() === b.getFullYear() &&
|
|
51
51
|
a.getMonth() === b.getMonth() &&
|
|
52
52
|
a.getDate() === b.getDate()
|
|
53
|
-
)
|
|
53
|
+
);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function isInRange(date: Date, start: Date | null, end: Date | null): boolean {
|
|
57
|
-
if (!start || !end) return false
|
|
58
|
-
const time = date.getTime()
|
|
59
|
-
return time >= start.getTime() && time <= end.getTime()
|
|
57
|
+
if (!start || !end) return false;
|
|
58
|
+
const time = date.getTime();
|
|
59
|
+
return time >= start.getTime() && time <= end.getTime();
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
function getCalendarDays(
|
|
@@ -64,35 +64,35 @@ function getCalendarDays(
|
|
|
64
64
|
month: number,
|
|
65
65
|
selected: { start: Date | null; end: Date | null },
|
|
66
66
|
minDate?: Date,
|
|
67
|
-
maxDate?: Date
|
|
67
|
+
maxDate?: Date,
|
|
68
68
|
): CalendarDay[] {
|
|
69
|
-
const today = new Date()
|
|
70
|
-
const firstDay = new Date(year, month, 1)
|
|
71
|
-
const lastDay = new Date(year, month + 1, 0)
|
|
72
|
-
const startPadding = firstDay.getDay()
|
|
73
|
-
const days: CalendarDay[] = []
|
|
69
|
+
const today = new Date();
|
|
70
|
+
const firstDay = new Date(year, month, 1);
|
|
71
|
+
const lastDay = new Date(year, month + 1, 0);
|
|
72
|
+
const startPadding = firstDay.getDay();
|
|
73
|
+
const days: CalendarDay[] = [];
|
|
74
74
|
|
|
75
75
|
// Add days from previous month
|
|
76
|
-
const prevMonthLastDay = new Date(year, month, 0)
|
|
76
|
+
const prevMonthLastDay = new Date(year, month, 0);
|
|
77
77
|
for (let i = startPadding - 1; i >= 0; i--) {
|
|
78
|
-
const date = new Date(year, month - 1, prevMonthLastDay.getDate() - i)
|
|
79
|
-
days.push(createDay(date, false, today, selected, minDate, maxDate))
|
|
78
|
+
const date = new Date(year, month - 1, prevMonthLastDay.getDate() - i);
|
|
79
|
+
days.push(createDay(date, false, today, selected, minDate, maxDate));
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// Add days from current month
|
|
83
83
|
for (let d = 1; d <= lastDay.getDate(); d++) {
|
|
84
|
-
const date = new Date(year, month, d)
|
|
85
|
-
days.push(createDay(date, true, today, selected, minDate, maxDate))
|
|
84
|
+
const date = new Date(year, month, d);
|
|
85
|
+
days.push(createDay(date, true, today, selected, minDate, maxDate));
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// Add days from next month to fill the grid
|
|
89
|
-
const remaining = 42 - days.length // 6 rows of 7 days
|
|
89
|
+
const remaining = 42 - days.length; // 6 rows of 7 days
|
|
90
90
|
for (let d = 1; d <= remaining; d++) {
|
|
91
|
-
const date = new Date(year, month + 1, d)
|
|
92
|
-
days.push(createDay(date, false, today, selected, minDate, maxDate))
|
|
91
|
+
const date = new Date(year, month + 1, d);
|
|
92
|
+
days.push(createDay(date, false, today, selected, minDate, maxDate));
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
return days
|
|
95
|
+
return days;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function createDay(
|
|
@@ -101,15 +101,15 @@ function createDay(
|
|
|
101
101
|
today: Date,
|
|
102
102
|
selected: { start: Date | null; end: Date | null },
|
|
103
103
|
minDate?: Date,
|
|
104
|
-
maxDate?: Date
|
|
104
|
+
maxDate?: Date,
|
|
105
105
|
): CalendarDay {
|
|
106
|
-
const isStart = selected.start ? isSameDay(date, selected.start) : false
|
|
107
|
-
const isEnd = selected.end ? isSameDay(date, selected.end) : false
|
|
108
|
-
const inRange = isInRange(date, selected.start, selected.end)
|
|
106
|
+
const isStart = selected.start ? isSameDay(date, selected.start) : false;
|
|
107
|
+
const isEnd = selected.end ? isSameDay(date, selected.end) : false;
|
|
108
|
+
const inRange = isInRange(date, selected.start, selected.end);
|
|
109
109
|
|
|
110
|
-
let isDisabled = false
|
|
111
|
-
if (minDate && date < minDate) isDisabled = true
|
|
112
|
-
if (maxDate && date > maxDate) isDisabled = true
|
|
110
|
+
let isDisabled = false;
|
|
111
|
+
if (minDate && date < minDate) isDisabled = true;
|
|
112
|
+
if (maxDate && date > maxDate) isDisabled = true;
|
|
113
113
|
|
|
114
114
|
return {
|
|
115
115
|
date,
|
|
@@ -120,83 +120,83 @@ function createDay(
|
|
|
120
120
|
isRangeStart: isStart,
|
|
121
121
|
isRangeEnd: isEnd,
|
|
122
122
|
isDisabled,
|
|
123
|
-
}
|
|
123
|
+
};
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
function Calendar({
|
|
127
127
|
selected = { start: null, end: null },
|
|
128
128
|
onSelect,
|
|
129
|
-
mode =
|
|
129
|
+
mode = "range",
|
|
130
130
|
minDate,
|
|
131
131
|
maxDate,
|
|
132
132
|
className,
|
|
133
133
|
}: CalendarProps) {
|
|
134
134
|
const [viewDate, setViewDate] = React.useState(() => {
|
|
135
|
-
if (selected.start) return new Date(selected.start)
|
|
136
|
-
return new Date()
|
|
137
|
-
})
|
|
135
|
+
if (selected.start) return new Date(selected.start);
|
|
136
|
+
return new Date();
|
|
137
|
+
});
|
|
138
138
|
|
|
139
139
|
const [rangeSelection, setRangeSelection] = React.useState<{
|
|
140
|
-
start: Date | null
|
|
141
|
-
end: Date | null
|
|
142
|
-
}>(selected)
|
|
140
|
+
start: Date | null;
|
|
141
|
+
end: Date | null;
|
|
142
|
+
}>(selected);
|
|
143
143
|
|
|
144
144
|
React.useEffect(() => {
|
|
145
|
-
setRangeSelection(selected)
|
|
146
|
-
}, [selected])
|
|
145
|
+
setRangeSelection(selected);
|
|
146
|
+
}, [selected]);
|
|
147
147
|
|
|
148
|
-
const year = viewDate.getFullYear()
|
|
149
|
-
const month = viewDate.getMonth()
|
|
150
|
-
const days = getCalendarDays(year, month, rangeSelection, minDate, maxDate)
|
|
148
|
+
const year = viewDate.getFullYear();
|
|
149
|
+
const month = viewDate.getMonth();
|
|
150
|
+
const days = getCalendarDays(year, month, rangeSelection, minDate, maxDate);
|
|
151
151
|
|
|
152
152
|
const goToPreviousMonth = () => {
|
|
153
|
-
setViewDate(new Date(year, month - 1, 1))
|
|
154
|
-
}
|
|
153
|
+
setViewDate(new Date(year, month - 1, 1));
|
|
154
|
+
};
|
|
155
155
|
|
|
156
156
|
const goToNextMonth = () => {
|
|
157
|
-
setViewDate(new Date(year, month + 1, 1))
|
|
158
|
-
}
|
|
157
|
+
setViewDate(new Date(year, month + 1, 1));
|
|
158
|
+
};
|
|
159
159
|
|
|
160
160
|
const handleDayClick = (day: CalendarDay) => {
|
|
161
|
-
if (day.isDisabled) return
|
|
161
|
+
if (day.isDisabled) return;
|
|
162
162
|
|
|
163
|
-
if (mode ===
|
|
164
|
-
const newSelection = { start: day.date, end: day.date }
|
|
165
|
-
setRangeSelection(newSelection)
|
|
166
|
-
onSelect?.(newSelection)
|
|
167
|
-
return
|
|
163
|
+
if (mode === "single") {
|
|
164
|
+
const newSelection = { start: day.date, end: day.date };
|
|
165
|
+
setRangeSelection(newSelection);
|
|
166
|
+
onSelect?.(newSelection);
|
|
167
|
+
return;
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
// Range mode
|
|
171
171
|
if (!rangeSelection.start || (rangeSelection.start && rangeSelection.end)) {
|
|
172
172
|
// Start new range
|
|
173
|
-
const newSelection = { start: day.date, end: null }
|
|
174
|
-
setRangeSelection(newSelection)
|
|
175
|
-
onSelect?.(newSelection as { start: Date; end: Date | null })
|
|
173
|
+
const newSelection = { start: day.date, end: null };
|
|
174
|
+
setRangeSelection(newSelection);
|
|
175
|
+
onSelect?.(newSelection as { start: Date; end: Date | null });
|
|
176
176
|
} else {
|
|
177
177
|
// Complete range
|
|
178
|
-
let start = rangeSelection.start
|
|
179
|
-
let end = day.date
|
|
178
|
+
let start = rangeSelection.start;
|
|
179
|
+
let end = day.date;
|
|
180
180
|
|
|
181
181
|
// Ensure start is before end
|
|
182
182
|
if (end < start) {
|
|
183
|
-
|
|
183
|
+
[start, end] = [end, start];
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
const newSelection = { start, end }
|
|
187
|
-
setRangeSelection(newSelection)
|
|
188
|
-
onSelect?.(newSelection)
|
|
186
|
+
const newSelection = { start, end };
|
|
187
|
+
setRangeSelection(newSelection);
|
|
188
|
+
onSelect?.(newSelection);
|
|
189
189
|
}
|
|
190
|
-
}
|
|
190
|
+
};
|
|
191
191
|
|
|
192
192
|
return (
|
|
193
|
-
<div data-slot="calendar" className={cn(
|
|
193
|
+
<div data-slot="calendar" className={cn("w-[280px] p-3", className)}>
|
|
194
194
|
{/* Header */}
|
|
195
195
|
<div className="mb-2 flex items-center justify-between">
|
|
196
196
|
<button
|
|
197
197
|
type="button"
|
|
198
198
|
onClick={goToPreviousMonth}
|
|
199
|
-
className="
|
|
199
|
+
className="inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors hover:bg-accent"
|
|
200
200
|
aria-label="Previous month"
|
|
201
201
|
>
|
|
202
202
|
<ChevronLeft className="h-4 w-4" />
|
|
@@ -207,7 +207,7 @@ function Calendar({
|
|
|
207
207
|
<button
|
|
208
208
|
type="button"
|
|
209
209
|
onClick={goToNextMonth}
|
|
210
|
-
className="
|
|
210
|
+
className="inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors hover:bg-accent"
|
|
211
211
|
aria-label="Next month"
|
|
212
212
|
>
|
|
213
213
|
<ChevronRight className="h-4 w-4" />
|
|
@@ -219,7 +219,7 @@ function Calendar({
|
|
|
219
219
|
{WEEKDAYS.map((day) => (
|
|
220
220
|
<div
|
|
221
221
|
key={day}
|
|
222
|
-
className="
|
|
222
|
+
className="flex h-8 w-8 items-center justify-center text-center text-xs font-medium text-muted-foreground"
|
|
223
223
|
>
|
|
224
224
|
{day}
|
|
225
225
|
</div>
|
|
@@ -235,19 +235,19 @@ function Calendar({
|
|
|
235
235
|
disabled={day.isDisabled}
|
|
236
236
|
onClick={() => handleDayClick(day)}
|
|
237
237
|
className={cn(
|
|
238
|
-
|
|
238
|
+
"inline-flex h-8 w-8 items-center justify-center rounded-md text-sm transition-colors",
|
|
239
239
|
// Base states
|
|
240
|
-
!day.isCurrentMonth &&
|
|
241
|
-
day.isDisabled &&
|
|
242
|
-
!day.isDisabled && !day.isSelected &&
|
|
240
|
+
!day.isCurrentMonth && "text-muted-foreground/50",
|
|
241
|
+
day.isDisabled && "cursor-not-allowed opacity-30",
|
|
242
|
+
!day.isDisabled && !day.isSelected && "hover:bg-accent",
|
|
243
243
|
// Today
|
|
244
|
-
day.isToday && !day.isSelected &&
|
|
244
|
+
day.isToday && !day.isSelected && "border border-primary",
|
|
245
245
|
// Selected states
|
|
246
|
-
day.isSelected &&
|
|
247
|
-
day.isRangeStart &&
|
|
248
|
-
day.isRangeEnd &&
|
|
246
|
+
day.isSelected && "bg-primary text-primary-foreground",
|
|
247
|
+
day.isRangeStart && "rounded-r-none",
|
|
248
|
+
day.isRangeEnd && "rounded-l-none",
|
|
249
249
|
// In range
|
|
250
|
-
day.isInRange &&
|
|
250
|
+
day.isInRange && "rounded-none bg-primary/20",
|
|
251
251
|
)}
|
|
252
252
|
>
|
|
253
253
|
{day.date.getDate()}
|
|
@@ -255,8 +255,8 @@ function Calendar({
|
|
|
255
255
|
))}
|
|
256
256
|
</div>
|
|
257
257
|
</div>
|
|
258
|
-
)
|
|
258
|
+
);
|
|
259
259
|
}
|
|
260
|
-
Calendar.displayName =
|
|
260
|
+
Calendar.displayName = "Calendar";
|
|
261
261
|
|
|
262
|
-
export { Calendar }
|
|
262
|
+
export { Calendar };
|