diff --git a/frontend/app/shadcn/chart.tsx b/frontend/app/shadcn/chart.tsx index 345e4c69dc..38b6ecc7f9 100644 --- a/frontend/app/shadcn/chart.tsx +++ b/frontend/app/shadcn/chart.tsx @@ -1,9 +1,16 @@ +// Copyright 2025, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 +// +// This file is based on components from shadcn/ui, which is licensed under the MIT License. +// Original source: https://github.com/shadcn/ui +// Modifications made by Command Line Inc. + "use client"; import * as React from "react"; import * as RechartsPrimitive from "recharts"; -import cn from "clsx"; +import { cn } from "@/shadcn/lib/utils"; // Format: { THEME_NAME: CSS_SELECTOR } const THEMES = { light: "", dark: ".dark" } as const; diff --git a/frontend/app/shadcn/form.tsx b/frontend/app/shadcn/form.tsx new file mode 100644 index 0000000000..621dd5b49b --- /dev/null +++ b/frontend/app/shadcn/form.tsx @@ -0,0 +1,151 @@ +// Copyright 2025, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 +// +// This file is based on components from shadcn/ui, which is licensed under the MIT License. +// Original source: https://github.com/shadcn/ui +// Modifications made by Command Line Inc. + +"use client"; + +import * as LabelPrimitive from "@radix-ui/react-label"; +import { Slot } from "@radix-ui/react-slot"; +import { Controller, ControllerProps, FieldPath, FieldValues, FormProvider, useFormContext } from "react-hook-form"; + +import { Label } from "@/shadcn/label"; +import * as React from "react"; + +import { cn } from "@/shadcn/lib/utils"; + +const Form = FormProvider; + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath, +> = { + name: TName; +}; + +const FormFieldContext = React.createContext({} as FormFieldContextValue); + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath, +>({ + ...props +}: ControllerProps) => { + return ( + + + + ); +}; + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext); + const itemContext = React.useContext(FormItemContext); + const { getFieldState, formState } = useFormContext(); + + const fieldState = getFieldState(fieldContext.name, formState); + + if (!fieldContext) { + throw new Error("useFormField should be used within "); + } + + const { id } = itemContext; + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + }; +}; + +type FormItemContextValue = { + id: string; +}; + +const FormItemContext = React.createContext({} as FormItemContextValue); + +const FormItem = React.forwardRef>( + ({ className, ...props }, ref) => { + const id = React.useId(); + + return ( + +
+ + ); + } +); +FormItem.displayName = "FormItem"; + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField(); + + return