40 | Interrupt type: {type} 41 |
42 | 43 | 65 |28 | The page you're looking for doesn't exist or has been moved. 29 |
30 | 31 |38 | A critical application error has occurred. This is likely a 39 | problem with the application itself. 40 |
41 | 42 | {error.digest && ( 43 |Error ID: {error.digest}
45 |
61 | {children}
62 |
63 | );
64 | },
65 | }}
66 | >
67 | {parsedContent}
68 | 41 | Something went wrong while loading this page. 42 |
43 | 44 | {error.digest && ( 45 |Error ID: {error.digest}
47 |
43 | Initializing your travel experience
44 |
45 | Please stand by...
46 |
No content to display
144 |24 | Open-source implementation of Canvas with human-in-the-loop 25 |
26 |31 | Canvas Callback demonstrates how to transform AI chat interfaces 32 | into interactive visual workspaces using LangGraph interrupts for 33 | joint problem-solving between users and AI agents. 34 |
35 |42 | Learn architecture and implementation patterns for interactive 43 | canvas interfaces. 44 |
45 | 58 |63 | Try canvas interactions firsthand with an interactive travel 64 | planning AI Agent. 65 |
66 | 79 |88 | Visual workspace alongside chat interface 89 |
90 |96 | LangGraph interrupts for collecting user input 97 |
98 |102 | Patterns to adapt to your applications 103 |
104 |
222 | );
223 | },
224 | CodeHeader,
225 | });
226 |
--------------------------------------------------------------------------------
/web/components/ui/date-range-picker.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { addDays, format, isSameDay, isToday, startOfMonth } from "date-fns";
4 | import { Calendar as CalendarIcon } from "lucide-react";
5 | import * as React from "react";
6 | import { DateRange } from "react-day-picker";
7 |
8 | import { Button } from "@/components/ui/button";
9 | import { Calendar } from "@/components/ui/calendar";
10 | import {
11 | Popover,
12 | PopoverContent,
13 | PopoverTrigger,
14 | } from "@/components/ui/popover";
15 | import { cn } from "@/lib/utils";
16 |
17 | export interface DateRangePickerProps {
18 | dateRange: DateRange | undefined;
19 | onDateRangeChange: (range: DateRange | undefined) => void;
20 | showCompactCalendar?: boolean;
21 | className?: string;
22 | align?: "center" | "start" | "end";
23 | numberOfMonths?: number;
24 | }
25 |
26 | export function DateRangePicker({
27 | dateRange,
28 | onDateRangeChange,
29 | showCompactCalendar = false,
30 | className,
31 | align = "start",
32 | numberOfMonths = 2,
33 | }: DateRangePickerProps) {
34 | const [isCalendarOpen, setIsCalendarOpen] = React.useState(false);
35 |
36 | // Predefined ranges
37 | const predefinedRanges = [
38 | {
39 | name: "Today",
40 | range: {
41 | from: new Date(),
42 | to: new Date(),
43 | },
44 | },
45 | {
46 | name: "Next weekend",
47 | range: {
48 | from: (() => {
49 | const today = new Date();
50 | const day = today.getDay(); // 0 is Sunday, 6 is Saturday
51 | const daysUntilFriday = day <= 5 ? 5 - day : 5 - day + 7;
52 | return addDays(today, daysUntilFriday);
53 | })(),
54 | to: (() => {
55 | const today = new Date();
56 | const day = today.getDay(); // 0 is Sunday, 6 is Saturday
57 | const daysUntilSunday = day <= 6 ? 7 - day : 7 - day + 7;
58 | return addDays(today, daysUntilSunday);
59 | })(),
60 | },
61 | },
62 | {
63 | name: "Next week",
64 | range: {
65 | from: addDays(new Date(), 7),
66 | to: addDays(new Date(), 13),
67 | },
68 | },
69 | {
70 | name: "Next month",
71 | range: {
72 | from: startOfMonth(addDays(new Date(), 30)),
73 | to: (() => {
74 | const nextMonth = addDays(new Date(), 30);
75 | const startOfNextMonth = startOfMonth(nextMonth);
76 | return addDays(startOfNextMonth, 6);
77 | })(),
78 | },
79 | },
80 | ];
81 |
82 | // Format the selected date range for display
83 | const formatDateRange = () => {
84 | if (!dateRange?.from) {
85 | return "Select dates";
86 | }
87 |
88 | if (dateRange.to) {
89 | if (isSameDay(dateRange.from, dateRange.to)) {
90 | return format(dateRange.from, "MMM d, yyyy");
91 | }
92 | return `${format(dateRange.from, "MMM d, yyyy")} - ${format(
93 | dateRange.to,
94 | "MMM d, yyyy"
95 | )}`;
96 | }
97 |
98 | return format(dateRange.from, "MMM d, yyyy");
99 | };
100 |
101 | // If we're showing the compact calendar, render it directly without popover
102 | if (!showCompactCalendar) {
103 | return (
104 | 195 | {formatDateRange()} 196 |
197 |83 | We're working on your request. This might take a moment... 84 |
85 |{description}
212 | )} 213 | {children} 214 |92 | Build interactive AI experiences with dedicated workspaces 93 | alongside your chat interface. 94 |
95 |"{message}"
289 |