@gunjo/ui 0.0.1-alpha.1 → 0.0.1-alpha.2
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/LICENSE +21 -0
- package/README.ja.md +90 -0
- package/README.md +52 -91
- package/package.json +47 -6
- package/src/components/display/Accordion.tsx +185 -0
- package/src/components/display/AccordionGroup.tsx +155 -0
- package/src/components/display/ActionDataTable.tsx +413 -0
- package/src/components/display/ActivityTimelineCard.tsx +483 -0
- package/src/components/display/AnalyticsCard.tsx +167 -0
- package/src/components/display/AssetCard.tsx +242 -0
- package/src/components/display/AssetGrid.tsx +164 -0
- package/src/components/display/Avatar.tsx +127 -0
- package/src/components/display/AvatarGroup.tsx +131 -0
- package/src/components/{atoms → display}/Badge.tsx +3 -3
- package/src/components/display/BarChart.tsx +247 -0
- package/src/components/{molecules → display}/Card.tsx +1 -1
- package/src/components/display/Carousel.tsx +593 -0
- package/src/components/display/ChartLegend.tsx +124 -0
- package/src/components/display/ChatMessage.tsx +382 -0
- package/src/components/display/ChoroplethMap.tsx +613 -0
- package/src/components/display/Code.tsx +42 -0
- package/src/components/display/CodeBlock.tsx +338 -0
- package/src/components/display/ColorSwatch.tsx +71 -0
- package/src/components/display/ConcentricProgressCard.tsx +545 -0
- package/src/components/display/DataTable.tsx +522 -0
- package/src/components/display/DistributionBar.tsx +102 -0
- package/src/components/display/DocNote.tsx +36 -0
- package/src/components/display/DonutChart.tsx +257 -0
- package/src/components/display/EmptyState.tsx +44 -0
- package/src/components/display/FileTree.tsx +180 -0
- package/src/components/display/GaugeChart.tsx +219 -0
- package/src/components/display/HeatmapChart.tsx +266 -0
- package/src/components/display/Icon.tsx +66 -0
- package/src/components/display/ImagePreview.tsx +140 -0
- package/src/components/{atoms → display}/Img.tsx +46 -12
- package/src/components/display/LabeledDonutCard.tsx +475 -0
- package/src/components/display/LineChart.tsx +464 -0
- package/src/components/{molecules → display}/List.tsx +20 -13
- package/src/components/display/MarkdownRenderer.tsx +157 -0
- package/src/components/display/MetadataList.tsx +81 -0
- package/src/components/display/MiniDistributionBarCard.tsx +314 -0
- package/src/components/display/PieChart.tsx +234 -0
- package/src/components/display/QuadrantMatrix.tsx +330 -0
- package/src/components/display/RadarChart.tsx +335 -0
- package/src/components/display/RadialBarChart.tsx +264 -0
- package/src/components/display/RetentionCohortCard.tsx +350 -0
- package/src/components/display/RibbonChart.tsx +618 -0
- package/src/components/display/SearchableAccordion.tsx +270 -0
- package/src/components/display/SegmentTimelineCard.tsx +452 -0
- package/src/components/display/SegmentedGaugeCard.tsx +607 -0
- package/src/components/display/Spacer.tsx +51 -0
- package/src/components/display/SparklineChart.tsx +394 -0
- package/src/components/display/StackedBarChart.tsx +393 -0
- package/src/components/display/Statistic.tsx +70 -0
- package/src/components/{molecules → display}/Table.tsx +22 -7
- package/src/components/display/Tag.tsx +80 -0
- package/src/components/display/TagEditor.tsx +141 -0
- package/src/components/display/Timeline.tsx +121 -0
- package/src/components/{atoms → display}/ToolPill.tsx +42 -18
- package/src/components/display/TreeView.tsx +226 -0
- package/src/components/display/chart-tooltip.tsx +423 -0
- package/src/components/display/chart-utils.ts +71 -0
- package/src/components/display/circular-chart-utils.ts +147 -0
- package/src/components/display/generated/default-variant-keys.ts +90 -0
- package/src/components/display/generated/variant-keys.ts +169 -0
- package/src/components/{atoms → feedback}/Alert.tsx +12 -5
- package/src/components/feedback/Banner.tsx +90 -0
- package/src/components/{molecules → feedback}/NotificationCenter.tsx +64 -31
- package/src/components/feedback/ProgressWidget.tsx +44 -0
- package/src/components/{atoms → feedback}/Spinner.tsx +2 -2
- package/src/components/{molecules → feedback}/StatusBar.tsx +4 -4
- package/src/components/feedback/StatusScreen.tsx +148 -0
- package/src/components/{molecules → feedback}/Stepper.tsx +10 -5
- package/src/components/feedback/Toast.tsx +108 -0
- package/src/components/feedback/ToastProvider.tsx +78 -0
- package/src/components/feedback/generated/default-variant-keys.ts +16 -0
- package/src/components/feedback/generated/variant-keys.ts +21 -0
- package/src/components/generated/component-manifest.ts +1568 -454
- package/src/components/generated/component-style-hints.ts +1958 -718
- package/src/components/{atoms → inputs}/ButtonVariants.ts +13 -3
- package/src/components/inputs/Calendar.tsx +212 -0
- package/src/components/inputs/ChatComposer.tsx +75 -0
- package/src/components/inputs/ChatInput.tsx +528 -0
- package/src/components/{atoms → inputs}/Checkbox.tsx +2 -2
- package/src/components/inputs/Combobox.tsx +175 -0
- package/src/components/inputs/CopyButton.tsx +187 -0
- package/src/components/inputs/DatePicker.tsx +519 -0
- package/src/components/inputs/DateRangePicker.tsx +878 -0
- package/src/components/inputs/EditableField.tsx +182 -0
- package/src/components/{organisms → inputs}/FileUploader.tsx +24 -9
- package/src/components/inputs/FilterButton.tsx +163 -0
- package/src/components/{molecules → inputs}/Form.tsx +20 -3
- package/src/components/{atoms → inputs}/Input.tsx +2 -0
- package/src/components/inputs/InputOTP.tsx +75 -0
- package/src/components/inputs/Mention.tsx +279 -0
- package/src/components/inputs/NumberInput.tsx +109 -0
- package/src/components/inputs/PasswordGroup.tsx +138 -0
- package/src/components/inputs/PasswordInput.tsx +74 -0
- package/src/components/inputs/PasswordRequirementList.tsx +96 -0
- package/src/components/inputs/PasswordStrengthMeter.tsx +93 -0
- package/src/components/inputs/PhoneInput.tsx +99 -0
- package/src/components/inputs/PostalCodeInput.tsx +98 -0
- package/src/components/inputs/RangeSlider.tsx +129 -0
- package/src/components/inputs/SearchInput.tsx +76 -0
- package/src/components/inputs/Select.tsx +39 -0
- package/src/components/{atoms → inputs}/Slider.tsx +18 -5
- package/src/components/{molecules → inputs}/SortButton.tsx +5 -2
- package/src/components/{atoms → inputs}/Switch.tsx +15 -4
- package/src/components/inputs/TagInput.tsx +114 -0
- package/src/components/{atoms → inputs}/Textarea.tsx +1 -0
- package/src/components/inputs/TimePicker.tsx +150 -0
- package/src/components/inputs/Toggle.tsx +48 -0
- package/src/components/{atoms → inputs}/ToggleGroup.tsx +2 -2
- package/src/components/inputs/TooltipButton.tsx +148 -0
- package/src/components/inputs/VoiceInputButton.tsx +317 -0
- package/src/components/inputs/calendar-holidays.ts +56 -0
- package/src/components/inputs/generated/default-variant-keys.ts +32 -0
- package/src/components/{atoms → inputs}/generated/variant-keys.ts +19 -27
- package/src/components/layout/AspectRatio.tsx +12 -0
- package/src/components/layout/AssetInspectorPanel.tsx +416 -0
- package/src/components/layout/Cluster.tsx +56 -0
- package/src/components/layout/CollapsiblePanelToggle.tsx +94 -0
- package/src/components/layout/Container.tsx +43 -0
- package/src/components/layout/DeviceFrame.tsx +227 -0
- package/src/components/layout/Grid.tsx +65 -0
- package/src/components/layout/HStack.tsx +73 -0
- package/src/components/{organisms → layout}/InspectorPanel.tsx +6 -5
- package/src/components/layout/MarqueeFrame.tsx +158 -0
- package/src/components/layout/Resizable.tsx +94 -0
- package/src/components/layout/ScrollArea.tsx +71 -0
- package/src/components/{organisms → layout}/SpatialCanvas.tsx +12 -7
- package/src/components/layout/VStack.tsx +69 -0
- package/src/components/layout/generated/default-variant-keys.ts +16 -0
- package/src/components/layout/generated/variant-keys.ts +21 -0
- package/src/components/{molecules → navigation}/Breadcrumb.tsx +5 -4
- package/src/components/navigation/Command.tsx +266 -0
- package/src/components/navigation/CommandPalette.tsx +83 -0
- package/src/components/navigation/DocumentPager.tsx +171 -0
- package/src/components/navigation/Footer.tsx +88 -0
- package/src/components/navigation/Header.tsx +80 -0
- package/src/components/{molecules → navigation}/Menubar.tsx +45 -12
- package/src/components/navigation/NavigationMenu.tsx +128 -0
- package/src/components/navigation/PageAside.tsx +84 -0
- package/src/components/{molecules → navigation}/Pagination.tsx +60 -7
- package/src/components/{organisms → navigation}/RightRail.tsx +1 -1
- package/src/components/navigation/Sidebar.tsx +223 -0
- package/src/components/navigation/SidebarItem.tsx +160 -0
- package/src/components/{molecules → navigation}/Tabs.tsx +2 -2
- package/src/components/navigation/TextLink.tsx +71 -0
- package/src/components/navigation/generated/default-variant-keys.ts +12 -0
- package/src/components/navigation/generated/variant-keys.ts +13 -0
- package/src/components/overlay/AIChatInput.tsx +5 -0
- package/src/components/overlay/AIChatMessage.tsx +6 -0
- package/src/components/overlay/AlertDialog.tsx +145 -0
- package/src/components/overlay/ChatPanel.tsx +180 -0
- package/src/components/{molecules → overlay}/ContextMenu.tsx +65 -29
- package/src/components/{molecules → overlay}/Dialog.tsx +21 -13
- package/src/components/overlay/Drawer.tsx +131 -0
- package/src/components/{molecules → overlay}/DropdownMenu.tsx +52 -17
- package/src/components/overlay/FloatingPanel.tsx +90 -0
- package/src/components/overlay/HoverCard.tsx +36 -0
- package/src/components/overlay/MediaLightbox.tsx +403 -0
- package/src/components/overlay/MediaPickerDialog.tsx +198 -0
- package/src/components/overlay/Modal.tsx +103 -0
- package/src/components/overlay/OnboardingFlow.tsx +172 -0
- package/src/components/overlay/Popover.tsx +36 -0
- package/src/components/overlay/ShareModal.tsx +324 -0
- package/src/components/{molecules → overlay}/Sheet.tsx +76 -19
- package/src/components/overlay/Tooltip.tsx +130 -0
- package/src/components/overlay/generated/default-variant-keys.ts +14 -0
- package/src/components/overlay/generated/variant-keys.ts +17 -0
- package/src/components/patterns/BlogTemplate.tsx +46 -0
- package/src/components/{templates → patterns}/DashboardTemplate.tsx +2 -2
- package/src/components/patterns/DocsTemplate.tsx +41 -0
- package/src/components/{templates → patterns}/MediaLibraryTemplate.tsx +1 -1
- package/src/components/patterns/OnboardingTemplate.tsx +32 -0
- package/src/components/patterns/PricingTemplate.tsx +106 -0
- package/src/globals.css +173 -22
- package/src/index.ts +177 -76
- package/tailwind-theme-extend.cjs +48 -3
- package/design/atoms-metadata.json +0 -82
- package/design/molecules-metadata.json +0 -130
- package/design/organisms-metadata.json +0 -38
- package/design/templates-metadata.json +0 -38
- package/src/components/atoms/Avatar.tsx +0 -57
- package/src/components/atoms/Select.tsx +0 -28
- package/src/components/atoms/generated/default-variant-keys.ts +0 -36
- package/src/components/molecules/AIChatInput.tsx +0 -140
- package/src/components/molecules/AIChatMessage.tsx +0 -109
- package/src/components/molecules/Accordion.tsx +0 -99
- package/src/components/molecules/Calendar.tsx +0 -60
- package/src/components/molecules/Carousel.tsx +0 -261
- package/src/components/molecules/Command.tsx +0 -152
- package/src/components/molecules/FilterButton.tsx +0 -133
- package/src/components/molecules/HoverCard.tsx +0 -29
- package/src/components/molecules/Modal.tsx +0 -66
- package/src/components/molecules/Popover.tsx +0 -31
- package/src/components/molecules/ProgressWidget.tsx +0 -40
- package/src/components/molecules/Resizable.tsx +0 -47
- package/src/components/molecules/ScrollArea.tsx +0 -48
- package/src/components/molecules/SidebarItem.tsx +0 -134
- package/src/components/molecules/Toast.tsx +0 -57
- package/src/components/molecules/Tooltip.tsx +0 -30
- package/src/components/molecules/generated/default-variant-keys.ts +0 -22
- package/src/components/molecules/generated/variant-keys.ts +0 -33
- package/src/components/organisms/CommandPalette.tsx +0 -58
- package/src/components/organisms/FloatingPanel.tsx +0 -46
- package/src/components/organisms/ShareModal.tsx +0 -182
- package/src/components/organisms/ToastProvider.tsx +0 -49
- /package/src/components/{atoms → display}/Kbd.tsx +0 -0
- /package/src/components/{atoms → display}/Separator.tsx +0 -0
- /package/src/components/{atoms → display}/Skeleton.tsx +0 -0
- /package/src/components/{atoms → feedback}/Progress.tsx +0 -0
- /package/src/components/{atoms → inputs}/Button.tsx +0 -0
- /package/src/components/{atoms → inputs}/Label.tsx +0 -0
- /package/src/components/{atoms → inputs}/RadioGroup.tsx +0 -0
- /package/src/components/{organisms → navigation}/AppRail.tsx +0 -0
- /package/src/components/{templates → patterns}/AuthTemplate.tsx +0 -0
- /package/src/components/{templates → patterns}/BannalyzeTemplate.tsx +0 -0
- /package/src/components/{templates → patterns}/ChatTemplate.tsx +0 -0
- /package/src/components/{templates → patterns}/EditorTemplate.tsx +0 -0
- /package/src/components/{templates → patterns}/KanbanTemplate.tsx +0 -0
- /package/src/components/{templates → patterns}/LandingTemplate.tsx +0 -0
- /package/src/components/{templates → patterns}/SettingsTemplate.tsx +0 -0
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import * as AvatarPrimitive from "@radix-ui/react-avatar"
|
|
5
|
-
|
|
6
|
-
import { cn } from "../../lib/utils"
|
|
7
|
-
import type { AvatarVariantKey } from "./generated/variant-keys"
|
|
8
|
-
import { avatarDefaultVariantKey } from "./generated/default-variant-keys"
|
|
9
|
-
|
|
10
|
-
const avatarSlotClasses: Record<AvatarVariantKey, string> = {
|
|
11
|
-
fallback: "flex h-full w-full items-center justify-center rounded-full bg-secondary text-sm font-medium text-muted-foreground",
|
|
12
|
-
image: "aspect-square h-full w-full",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const Avatar = React.forwardRef<
|
|
16
|
-
React.ElementRef<typeof AvatarPrimitive.Root>,
|
|
17
|
-
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
|
|
18
|
-
>(({ className, ...props }, ref) => (
|
|
19
|
-
<AvatarPrimitive.Root
|
|
20
|
-
ref={ref}
|
|
21
|
-
className={cn(
|
|
22
|
-
"relative inline-flex h-10 w-10 shrink-0 items-center overflow-hidden rounded-full",
|
|
23
|
-
className
|
|
24
|
-
)}
|
|
25
|
-
{...props}
|
|
26
|
-
/>
|
|
27
|
-
))
|
|
28
|
-
Avatar.displayName = AvatarPrimitive.Root.displayName
|
|
29
|
-
|
|
30
|
-
const AvatarImage = React.forwardRef<
|
|
31
|
-
React.ElementRef<typeof AvatarPrimitive.Image>,
|
|
32
|
-
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
|
33
|
-
>(({ className, ...props }, ref) => (
|
|
34
|
-
<AvatarPrimitive.Image
|
|
35
|
-
ref={ref}
|
|
36
|
-
className={cn(avatarSlotClasses.image, className)}
|
|
37
|
-
{...props}
|
|
38
|
-
/>
|
|
39
|
-
))
|
|
40
|
-
AvatarImage.displayName = AvatarPrimitive.Image.displayName
|
|
41
|
-
|
|
42
|
-
const AvatarFallback = React.forwardRef<
|
|
43
|
-
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
|
44
|
-
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
|
45
|
-
>(({ className, ...props }, ref) => (
|
|
46
|
-
<AvatarPrimitive.Fallback
|
|
47
|
-
ref={ref}
|
|
48
|
-
className={cn(
|
|
49
|
-
avatarSlotClasses[avatarDefaultVariantKey],
|
|
50
|
-
className
|
|
51
|
-
)}
|
|
52
|
-
{...props}
|
|
53
|
-
/>
|
|
54
|
-
))
|
|
55
|
-
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
|
|
56
|
-
|
|
57
|
-
export { Avatar, AvatarImage, AvatarFallback }
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
import { cn } from "../../lib/utils"
|
|
3
|
-
import { ChevronDown } from "lucide-react"
|
|
4
|
-
|
|
5
|
-
export interface SelectProps extends React.SelectHTMLAttributes<HTMLSelectElement> { }
|
|
6
|
-
|
|
7
|
-
const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
|
|
8
|
-
({ className, children, ...props }, ref) => {
|
|
9
|
-
return (
|
|
10
|
-
<div className="relative">
|
|
11
|
-
<select
|
|
12
|
-
className={cn(
|
|
13
|
-
"inline-flex h-10 w-[200px] appearance-none items-center justify-between rounded-lg border border-input bg-transparent px-3 py-2 text-sm font-normal text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:bg-muted disabled:text-muted-foreground disabled:opacity-50",
|
|
14
|
-
className
|
|
15
|
-
)}
|
|
16
|
-
ref={ref}
|
|
17
|
-
{...props}
|
|
18
|
-
>
|
|
19
|
-
{children}
|
|
20
|
-
</select>
|
|
21
|
-
<ChevronDown className="pointer-events-none absolute right-3 top-3 h-4 w-4 text-muted-foreground" />
|
|
22
|
-
</div>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
)
|
|
26
|
-
Select.displayName = "Select"
|
|
27
|
-
|
|
28
|
-
export { Select }
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
// Generated by `npm run design:sync:components`. Do not edit manually.
|
|
3
|
-
|
|
4
|
-
import type { AlertVariantKey, AvatarVariantKey, BadgeVariantKey, ButtonVariantKey, CheckboxVariantKey, ImgVariantKey, InputVariantKey, RadioGroupVariantKey, SeparatorVariantKey, SpinnerVariantKey, SwitchVariantKey, TextareaVariantKey, ToggleGroupVariantKey, ToolPillVariantKey } from "./variant-keys";
|
|
5
|
-
|
|
6
|
-
export const alertDefaultVariantKey: AlertVariantKey = "default";
|
|
7
|
-
export const avatarDefaultVariantKey: AvatarVariantKey = "fallback";
|
|
8
|
-
export const badgeDefaultVariantKey: BadgeVariantKey = "default";
|
|
9
|
-
export const buttonDefaultVariantKey: ButtonVariantKey = "default";
|
|
10
|
-
export const checkboxDefaultVariantKey: CheckboxVariantKey = "unchecked";
|
|
11
|
-
export const imgDefaultVariantKey: ImgVariantKey = "loading";
|
|
12
|
-
export const inputDefaultVariantKey: InputVariantKey = "default";
|
|
13
|
-
export const radioGroupDefaultVariantKey: RadioGroupVariantKey = "unchecked";
|
|
14
|
-
export const separatorDefaultVariantKey: SeparatorVariantKey = "horizontal";
|
|
15
|
-
export const spinnerDefaultVariantKey: SpinnerVariantKey = "default";
|
|
16
|
-
export const switchDefaultVariantKey: SwitchVariantKey = "unchecked";
|
|
17
|
-
export const textareaDefaultVariantKey: TextareaVariantKey = "default";
|
|
18
|
-
export const toggleGroupDefaultVariantKey: ToggleGroupVariantKey = "default";
|
|
19
|
-
export const toolPillDefaultVariantKey: ToolPillVariantKey = "primary";
|
|
20
|
-
|
|
21
|
-
export const atomDefaultVariantKeys = {
|
|
22
|
-
alert: alertDefaultVariantKey,
|
|
23
|
-
avatar: avatarDefaultVariantKey,
|
|
24
|
-
badge: badgeDefaultVariantKey,
|
|
25
|
-
button: buttonDefaultVariantKey,
|
|
26
|
-
checkbox: checkboxDefaultVariantKey,
|
|
27
|
-
img: imgDefaultVariantKey,
|
|
28
|
-
input: inputDefaultVariantKey,
|
|
29
|
-
radioGroup: radioGroupDefaultVariantKey,
|
|
30
|
-
separator: separatorDefaultVariantKey,
|
|
31
|
-
spinner: spinnerDefaultVariantKey,
|
|
32
|
-
switch: switchDefaultVariantKey,
|
|
33
|
-
textarea: textareaDefaultVariantKey,
|
|
34
|
-
toggleGroup: toggleGroupDefaultVariantKey,
|
|
35
|
-
toolPill: toolPillDefaultVariantKey,
|
|
36
|
-
} as const;
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { Send, Paperclip, Loader2, Square } from "lucide-react";
|
|
5
|
-
import { Button } from "../atoms/Button";
|
|
6
|
-
import { Textarea } from "../atoms/Textarea";
|
|
7
|
-
import { cn } from "../../lib/utils";
|
|
8
|
-
import { buttonDefaultVariantKey } from "../atoms/generated/default-variant-keys";
|
|
9
|
-
|
|
10
|
-
export interface AIChatInputProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
11
|
-
onSend: (message: string, files?: File[]) => void;
|
|
12
|
-
onStop?: () => void;
|
|
13
|
-
isProcessing?: boolean;
|
|
14
|
-
placeholder?: string;
|
|
15
|
-
enableAttachments?: boolean;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function AIChatInput({
|
|
19
|
-
onSend,
|
|
20
|
-
onStop,
|
|
21
|
-
isProcessing = false,
|
|
22
|
-
placeholder = "メッセージを入力...",
|
|
23
|
-
enableAttachments = true,
|
|
24
|
-
className,
|
|
25
|
-
disabled,
|
|
26
|
-
...props
|
|
27
|
-
}: AIChatInputProps) {
|
|
28
|
-
const [message, setMessage] = React.useState("");
|
|
29
|
-
const textareaRef = React.useRef<HTMLTextAreaElement>(null);
|
|
30
|
-
const fileInputRef = React.useRef<HTMLInputElement>(null);
|
|
31
|
-
|
|
32
|
-
const handleInput = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
33
|
-
setMessage(e.target.value);
|
|
34
|
-
adjustHeight();
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const adjustHeight = () => {
|
|
38
|
-
const textarea = textareaRef.current;
|
|
39
|
-
if (textarea) {
|
|
40
|
-
textarea.style.height = "auto";
|
|
41
|
-
textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
46
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
47
|
-
e.preventDefault();
|
|
48
|
-
handleSend();
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const handleSend = () => {
|
|
53
|
-
if (!message.trim() || isProcessing) return;
|
|
54
|
-
onSend(message);
|
|
55
|
-
setMessage("");
|
|
56
|
-
if (textareaRef.current) {
|
|
57
|
-
textareaRef.current.style.height = "auto";
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const handleUploadClick = () => {
|
|
62
|
-
fileInputRef.current?.click();
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
66
|
-
if (e.target.files && e.target.files.length > 0) {
|
|
67
|
-
// For now, we just pass the files to onSend alongside an empty message or handle it differently
|
|
68
|
-
// In a real app, we might stage files. Here we'll just expose the capability.
|
|
69
|
-
onSend(message, Array.from(e.target.files));
|
|
70
|
-
setMessage(""); // Clear message if sent with file
|
|
71
|
-
|
|
72
|
-
if (textareaRef.current) {
|
|
73
|
-
textareaRef.current.value = ""; // Reset input
|
|
74
|
-
textareaRef.current.style.height = "auto";
|
|
75
|
-
}
|
|
76
|
-
if (fileInputRef.current) {
|
|
77
|
-
fileInputRef.current.value = ""; // Reset file input
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
return (
|
|
83
|
-
<div className={cn("relative flex flex-col flex-row items-center items-end w-[640px] max-w-full gap-2 p-4 bg-background border border-t border-border", className)}>
|
|
84
|
-
{enableAttachments && (
|
|
85
|
-
<>
|
|
86
|
-
<input
|
|
87
|
-
type="file"
|
|
88
|
-
multiple
|
|
89
|
-
className="hidden"
|
|
90
|
-
ref={fileInputRef}
|
|
91
|
-
onChange={handleFileChange}
|
|
92
|
-
/>
|
|
93
|
-
<Button
|
|
94
|
-
variant="ghost"
|
|
95
|
-
size="icon"
|
|
96
|
-
className="flex-shrink-0 text-muted-foreground hover:text-foreground mb-0.5"
|
|
97
|
-
onClick={handleUploadClick}
|
|
98
|
-
disabled={disabled || isProcessing}
|
|
99
|
-
>
|
|
100
|
-
<Paperclip className="h-5 w-5" />
|
|
101
|
-
</Button>
|
|
102
|
-
</>
|
|
103
|
-
)}
|
|
104
|
-
|
|
105
|
-
<div className="flex-1 relative">
|
|
106
|
-
<Textarea
|
|
107
|
-
ref={textareaRef}
|
|
108
|
-
value={message}
|
|
109
|
-
onChange={handleInput}
|
|
110
|
-
onKeyDown={handleKeyDown}
|
|
111
|
-
placeholder={placeholder}
|
|
112
|
-
disabled={disabled || isProcessing}
|
|
113
|
-
className="min-h-[44px] max-h-[200px] py-3 pr-4 resize-none rounded-xl border-border focus:ring-ring bg-muted"
|
|
114
|
-
rows={1}
|
|
115
|
-
/>
|
|
116
|
-
</div>
|
|
117
|
-
|
|
118
|
-
{isProcessing ? (
|
|
119
|
-
<Button
|
|
120
|
-
variant="destructive"
|
|
121
|
-
size="icon"
|
|
122
|
-
className="flex-shrink-0 rounded-xl mb-0.5"
|
|
123
|
-
onClick={onStop}
|
|
124
|
-
>
|
|
125
|
-
<Square className="h-4 w-4 fill-current" />
|
|
126
|
-
</Button>
|
|
127
|
-
) : (
|
|
128
|
-
<Button
|
|
129
|
-
variant={buttonDefaultVariantKey}
|
|
130
|
-
size="icon"
|
|
131
|
-
className="mb-0.5 flex-shrink-0 rounded-xl bg-primary text-primary-foreground hover:bg-primary/90"
|
|
132
|
-
onClick={handleSend}
|
|
133
|
-
disabled={!message.trim() || disabled}
|
|
134
|
-
>
|
|
135
|
-
<Send className="h-4 w-4" />
|
|
136
|
-
</Button>
|
|
137
|
-
)}
|
|
138
|
-
</div>
|
|
139
|
-
);
|
|
140
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { User, Sparkles, Copy, ThumbsUp, ThumbsDown } from "lucide-react";
|
|
5
|
-
import { Avatar, AvatarFallback, AvatarImage } from "../atoms/Avatar";
|
|
6
|
-
import { Button } from "../atoms/Button";
|
|
7
|
-
import { cn } from "../../lib/utils";
|
|
8
|
-
import type { AiChatMessageVariantKey } from "./generated/variant-keys";
|
|
9
|
-
import { aiChatMessageDefaultVariantKey } from "./generated/default-variant-keys";
|
|
10
|
-
|
|
11
|
-
type AIChatMessageRole = AiChatMessageVariantKey | "system";
|
|
12
|
-
|
|
13
|
-
export interface AIChatMessageProps {
|
|
14
|
-
role: AIChatMessageRole;
|
|
15
|
-
content: string;
|
|
16
|
-
avatarSrc?: string;
|
|
17
|
-
userName?: string;
|
|
18
|
-
timestamp?: string;
|
|
19
|
-
isTyping?: boolean;
|
|
20
|
-
className?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function AIChatMessage({
|
|
24
|
-
role,
|
|
25
|
-
content,
|
|
26
|
-
avatarSrc,
|
|
27
|
-
userName = role === "user" ? "You" : "AI Assistant",
|
|
28
|
-
timestamp,
|
|
29
|
-
isTyping = false,
|
|
30
|
-
className
|
|
31
|
-
}: AIChatMessageProps) {
|
|
32
|
-
if (role === "system") {
|
|
33
|
-
return (
|
|
34
|
-
<div className={cn("flex justify-center my-4", className)}>
|
|
35
|
-
<span className="text-xs text-muted-foreground bg-muted px-3 py-1 rounded-full">
|
|
36
|
-
{content}
|
|
37
|
-
</span>
|
|
38
|
-
</div>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const messageRole: AiChatMessageVariantKey =
|
|
43
|
-
role === "user" ? "user" : aiChatMessageDefaultVariantKey;
|
|
44
|
-
const isUser = messageRole === "user";
|
|
45
|
-
|
|
46
|
-
const rowDirectionClasses: Record<AiChatMessageVariantKey, string> = {
|
|
47
|
-
assistant: "flex-row",
|
|
48
|
-
user: "flex-row-reverse",
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const bubbleClasses: Record<AiChatMessageVariantKey, string> = {
|
|
52
|
-
assistant: "bg-background border border-border text-foreground rounded-tl-none",
|
|
53
|
-
user: "bg-primary text-primary-foreground rounded-tr-none",
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<div className={cn(
|
|
58
|
-
"flex gap-4 p-4 w-[720px] max-w-full transition-colors hover:bg-muted/50 group",
|
|
59
|
-
rowDirectionClasses[messageRole],
|
|
60
|
-
className
|
|
61
|
-
)}>
|
|
62
|
-
{/* Avatar */}
|
|
63
|
-
<div className="flex-shrink-0 mt-1">
|
|
64
|
-
<Avatar className={cn("h-8 w-8", isUser ? "ring-2 ring-primary/20" : "bg-primary text-primary-foreground")}>
|
|
65
|
-
{avatarSrc ? (
|
|
66
|
-
<AvatarImage src={avatarSrc} alt={userName} />
|
|
67
|
-
) : (
|
|
68
|
-
<AvatarFallback className={cn(isUser ? "bg-background text-muted-foreground" : "bg-transparent text-primary-foreground")}>
|
|
69
|
-
{isUser ? <User className="h-4 w-4" /> : <Sparkles className="h-4 w-4" />}
|
|
70
|
-
</AvatarFallback>
|
|
71
|
-
)}
|
|
72
|
-
</Avatar>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
{/* Content Body */}
|
|
76
|
-
<div className={cn("flex flex-col max-w-[80%]", isUser ? "items-end" : "items-start")}>
|
|
77
|
-
<div className="flex items-center gap-2 mb-1">
|
|
78
|
-
<span className="text-sm font-semibold text-foreground">{userName}</span>
|
|
79
|
-
{timestamp && <span className="text-xs text-muted-foreground">{timestamp}</span>}
|
|
80
|
-
</div>
|
|
81
|
-
|
|
82
|
-
<div className={cn(
|
|
83
|
-
"text-sm leading-relaxed rounded-2xl px-4 py-3 shadow-sm whitespace-pre-wrap",
|
|
84
|
-
bubbleClasses[messageRole]
|
|
85
|
-
)}>
|
|
86
|
-
{content}
|
|
87
|
-
{isTyping && (
|
|
88
|
-
<span className="inline-block w-1.5 h-4 ml-1 align-middle bg-current animate-pulse" />
|
|
89
|
-
)}
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
{/* Actions (Only for assistant messages usually, but logic allows both) */}
|
|
93
|
-
{!isUser && !isTyping && (
|
|
94
|
-
<div className="flex items-center gap-1 mt-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
95
|
-
<Button variant="ghost" size="icon" className="h-6 w-6 text-muted-foreground hover:text-foreground">
|
|
96
|
-
<Copy className="h-3 w-3" />
|
|
97
|
-
</Button>
|
|
98
|
-
<Button variant="ghost" size="icon" className="h-6 w-6 text-muted-foreground hover:text-foreground">
|
|
99
|
-
<ThumbsUp className="h-3 w-3" />
|
|
100
|
-
</Button>
|
|
101
|
-
<Button variant="ghost" size="icon" className="h-6 w-6 text-muted-foreground hover:text-foreground">
|
|
102
|
-
<ThumbsDown className="h-3 w-3" />
|
|
103
|
-
</Button>
|
|
104
|
-
</div>
|
|
105
|
-
)}
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
);
|
|
109
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import * as AccordionPrimitive from "@radix-ui/react-accordion"
|
|
5
|
-
import { ChevronDown } from "lucide-react"
|
|
6
|
-
|
|
7
|
-
import { cn } from "../../lib/utils"
|
|
8
|
-
import type { AccordionVariantKey } from "./generated/variant-keys"
|
|
9
|
-
import { accordionDefaultVariantKey } from "./generated/default-variant-keys"
|
|
10
|
-
|
|
11
|
-
function buildVariantStateMap(
|
|
12
|
-
defaultVariantKey: AccordionVariantKey,
|
|
13
|
-
defaultStateClass: string,
|
|
14
|
-
alternateStateClass: string
|
|
15
|
-
): Record<AccordionVariantKey, string> {
|
|
16
|
-
return defaultVariantKey === "collapsed"
|
|
17
|
-
? { collapsed: defaultStateClass, expanded: alternateStateClass }
|
|
18
|
-
: { collapsed: alternateStateClass, expanded: defaultStateClass }
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const expandedAccordionVariantKey: AccordionVariantKey =
|
|
22
|
-
accordionDefaultVariantKey === "collapsed" ? "expanded" : "collapsed"
|
|
23
|
-
|
|
24
|
-
const triggerStateClasses = buildVariantStateMap(
|
|
25
|
-
accordionDefaultVariantKey,
|
|
26
|
-
"",
|
|
27
|
-
"[&[data-state=open]>svg]:rotate-180"
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
const contentStateClasses = buildVariantStateMap(
|
|
31
|
-
accordionDefaultVariantKey,
|
|
32
|
-
"data-[state=closed]:animate-accordion-up",
|
|
33
|
-
"data-[state=open]:animate-accordion-down"
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
const Accordion = React.forwardRef<
|
|
37
|
-
React.ElementRef<typeof AccordionPrimitive.Root>,
|
|
38
|
-
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Root>
|
|
39
|
-
>(({ className, ...props }, ref) => (
|
|
40
|
-
<AccordionPrimitive.Root
|
|
41
|
-
ref={ref}
|
|
42
|
-
className={cn("flex flex-col w-[400px] border", className)}
|
|
43
|
-
{...props}
|
|
44
|
-
/>
|
|
45
|
-
))
|
|
46
|
-
Accordion.displayName = AccordionPrimitive.Root.displayName
|
|
47
|
-
|
|
48
|
-
const AccordionItem = React.forwardRef<
|
|
49
|
-
React.ElementRef<typeof AccordionPrimitive.Item>,
|
|
50
|
-
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
|
51
|
-
>(({ className, ...props }, ref) => (
|
|
52
|
-
<AccordionPrimitive.Item
|
|
53
|
-
ref={ref}
|
|
54
|
-
className={cn("border-b", className)}
|
|
55
|
-
{...props}
|
|
56
|
-
/>
|
|
57
|
-
))
|
|
58
|
-
AccordionItem.displayName = "AccordionItem"
|
|
59
|
-
|
|
60
|
-
const AccordionTrigger = React.forwardRef<
|
|
61
|
-
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
|
62
|
-
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
|
63
|
-
>(({ className, children, ...props }, ref) => (
|
|
64
|
-
<AccordionPrimitive.Header className="flex">
|
|
65
|
-
<AccordionPrimitive.Trigger
|
|
66
|
-
ref={ref}
|
|
67
|
-
className={cn(
|
|
68
|
-
"flex flex-1 items-center justify-between px-4 py-4 text-sm font-medium transition-all hover:underline",
|
|
69
|
-
triggerStateClasses[expandedAccordionVariantKey],
|
|
70
|
-
className
|
|
71
|
-
)}
|
|
72
|
-
{...props}
|
|
73
|
-
>
|
|
74
|
-
{children}
|
|
75
|
-
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
|
|
76
|
-
</AccordionPrimitive.Trigger>
|
|
77
|
-
</AccordionPrimitive.Header>
|
|
78
|
-
))
|
|
79
|
-
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
|
|
80
|
-
|
|
81
|
-
const AccordionContent = React.forwardRef<
|
|
82
|
-
React.ElementRef<typeof AccordionPrimitive.Content>,
|
|
83
|
-
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
|
84
|
-
>(({ className, children, ...props }, ref) => (
|
|
85
|
-
<AccordionPrimitive.Content
|
|
86
|
-
ref={ref}
|
|
87
|
-
className={cn(
|
|
88
|
-
"overflow-hidden text-sm text-muted-foreground transition-all",
|
|
89
|
-
contentStateClasses[accordionDefaultVariantKey],
|
|
90
|
-
contentStateClasses[expandedAccordionVariantKey]
|
|
91
|
-
)}
|
|
92
|
-
{...props}
|
|
93
|
-
>
|
|
94
|
-
<div className={cn("px-4 pb-4 pt-0", className)}>{children}</div>
|
|
95
|
-
</AccordionPrimitive.Content>
|
|
96
|
-
))
|
|
97
|
-
AccordionContent.displayName = AccordionPrimitive.Content.displayName
|
|
98
|
-
|
|
99
|
-
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
|
|
3
|
-
import * as React from "react"
|
|
4
|
-
import { DayPicker } from "react-day-picker"
|
|
5
|
-
|
|
6
|
-
import { cn } from "../../lib/utils"
|
|
7
|
-
|
|
8
|
-
export type CalendarProps = React.ComponentProps<typeof DayPicker>
|
|
9
|
-
|
|
10
|
-
function Calendar({
|
|
11
|
-
className,
|
|
12
|
-
classNames,
|
|
13
|
-
showOutsideDays = true,
|
|
14
|
-
...props
|
|
15
|
-
}: CalendarProps) {
|
|
16
|
-
return (
|
|
17
|
-
<DayPicker
|
|
18
|
-
showOutsideDays={showOutsideDays}
|
|
19
|
-
className={cn("flex flex-col w-[320px] rounded-md rounded-lg border bg-card p-4", className)}
|
|
20
|
-
classNames={{
|
|
21
|
-
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0 relative",
|
|
22
|
-
month: "space-y-4",
|
|
23
|
-
caption: "flex justify-center pt-1 relative items-center w-full",
|
|
24
|
-
month_caption: "flex justify-center pt-1 relative items-center w-full",
|
|
25
|
-
caption_label: "text-sm font-semibold",
|
|
26
|
-
nav: "absolute left-0 top-0 right-0 flex items-center justify-between px-1 pointer-events-none",
|
|
27
|
-
nav_button: cn(
|
|
28
|
-
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 text-foreground pointer-events-auto hover:bg-accent rounded-md flex items-center justify-center transition-colors"
|
|
29
|
-
),
|
|
30
|
-
nav_button_previous: "absolute left-1 top-1",
|
|
31
|
-
nav_button_next: "absolute right-1 top-1",
|
|
32
|
-
table: "w-full border-collapse space-y-1",
|
|
33
|
-
head_row: "",
|
|
34
|
-
head_cell:
|
|
35
|
-
"text-muted-foreground rounded-md w-9 font-normal text-xs",
|
|
36
|
-
row: "w-full mt-2",
|
|
37
|
-
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",
|
|
38
|
-
day: "h-9 w-9 p-0 font-normal aria-selected:opacity-100",
|
|
39
|
-
day_button: cn(
|
|
40
|
-
"h-9 w-9 p-0 font-normal aria-selected:opacity-100 hover:bg-accent/50 rounded-md flex items-center justify-center transition-colors"
|
|
41
|
-
),
|
|
42
|
-
day_range_end: "day-range-end",
|
|
43
|
-
day_selected:
|
|
44
|
-
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
|
|
45
|
-
day_today: "bg-accent text-accent-foreground",
|
|
46
|
-
day_outside:
|
|
47
|
-
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
|
|
48
|
-
day_disabled: "text-muted-foreground opacity-50",
|
|
49
|
-
day_range_middle:
|
|
50
|
-
"aria-selected:bg-accent aria-selected:text-accent-foreground",
|
|
51
|
-
day_hidden: "invisible",
|
|
52
|
-
...classNames,
|
|
53
|
-
}}
|
|
54
|
-
{...props}
|
|
55
|
-
/>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
Calendar.displayName = "Calendar"
|
|
59
|
-
|
|
60
|
-
export { Calendar }
|