diff --git a/libs/registry/registry/components/a/auto-complate.tsx b/libs/registry/registry/components/a/auto-complate.tsx new file mode 100644 index 0000000..4df152c --- /dev/null +++ b/libs/registry/registry/components/a/auto-complate.tsx @@ -0,0 +1,80 @@ +'use client'; + +import * as React from 'react'; +import { Check, ChevronsUpDown } from 'lucide-react'; + +import { cn } from '@/lib/utils'; +import { Button } from '@/components/a/button'; +import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/components/ui/command'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; + +type Option = { + value?: string; + label: string; +}; + +type AutoComplateProps = { + options: Option[]; + placeholder?: string; + value?: string; + onChange?: (value: string) => void; + width?: string; +}; +export function AutoComplate(props: AutoComplateProps) { + const [open, setOpen] = React.useState(false); + const [value, _setValue] = React.useState(''); + const setValue = (value: string) => { + props?.onChange?.(value); + _setValue(value); + }; + const showLabel = React.useMemo(() => { + const option = props.options.find((option) => option.value === value); + if (option) { + return option?.label; + } + if (props.value) return props.value; + if (value) return value; + return 'Select ...'; + }, [value, props.value]); + return ( + + + + + + + { + if (e.key === 'Enter') { + setOpen(false); + const value = e.target?.value || ''; + setValue(value.trim()); + } + }} + /> + + No options found. + + {props.options.map((framework) => ( + { + setValue(currentValue === value ? '' : currentValue); + setOpen(false); + }}> + + {framework.label} + + ))} + + + + + + ); +} diff --git a/libs/registry/registry/components/a/button.tsx b/libs/registry/registry/components/a/button.tsx new file mode 100644 index 0000000..92c6989 --- /dev/null +++ b/libs/registry/registry/components/a/button.tsx @@ -0,0 +1,18 @@ +import { Button as UiButton, ButtonProps } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; +export const IconButton: typeof UiButton = (props) => { + return ; +}; + +export const Button: typeof UiButton = (props) => { + return ; +}; + +export const ButtonTextIcon = (props: ButtonProps & { icon: React.ReactNode }) => { + return ( + + {props.icon} + {props.children} + + ); +}; diff --git a/libs/registry/registry/components/a/confirm.tsx b/libs/registry/registry/components/a/confirm.tsx new file mode 100644 index 0000000..fc418a7 --- /dev/null +++ b/libs/registry/registry/components/a/confirm.tsx @@ -0,0 +1,107 @@ +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from '@/components/ui/alert-dialog'; +import { useMemo, useRef, useState } from 'react'; + +type useConfirmOptions = { + tip?: React.ReactNode; + title?: string; + description?: string; + onOkText?: string; + onCancelText?: string; + onOk?: Fn; + onCancle?: Fn; + children?: React.ReactNode; +}; +type Fn = () => void; +export const useConfirm = (opts?: useConfirmOptions) => { + const [open, setOpen] = useState(false); + const onOkRef = useRef(null); + const onCancle = useRef(null); + type ConfirmOptions = { + onOk?: Fn; + onCancel?: Fn; + }; + const confirm = (opts: ConfirmOptions) => { + setOpen(true); + opts.onOk && (onOkRef.current = opts.onOk); + opts.onCancel && (onCancle.current = opts.onCancel); + }; + const module = useMemo(() => { + if (!open) return null; + return ( + + {opts?.tip ?? '提示'} + + + {opts?.title ?? '是否确认删除?'} + {opts?.description ?? '此操作无法撤销,是否继续。'} + + + { + setOpen(false); + onCancle.current && onCancle.current(); + e.stopPropagation(); + }}> + {opts?.onCancelText ?? '取消'} + + { + setOpen(false); + onOkRef.current && onOkRef.current(); + e.stopPropagation(); + }}> + {opts?.onOkText ?? '确定'} + + + + + ); + }, [open]); + return { + module, + open, + setOpen, + confirm, + }; +}; + +export const Confirm = (opts?: useConfirmOptions) => { + return ( + + {opts?.children && {opts?.children ?? opts?.tip ?? '提示'}} + {!opts?.children && {opts?.tip ?? '提示'}} + + + {opts?.title ?? '是否确认删除?'} + {opts?.description ?? '此操作无法撤销,是否继续。'} + + + { + opts?.onCancle?.(); + e.stopPropagation(); + }}> + {opts?.onCancelText ?? '取消'} + + { + opts?.onOk?.(); + e.stopPropagation(); + }}> + {opts?.onOkText ?? '确定'} + + + + + ); +}; diff --git a/libs/registry/registry/components/a/select.tsx b/libs/registry/registry/components/a/select.tsx new file mode 100644 index 0000000..6b968bd --- /dev/null +++ b/libs/registry/registry/components/a/select.tsx @@ -0,0 +1,31 @@ +import { Select as UISelect, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; + +type Option = { + value: string; + label?: string; +}; +type SelectProps = { + options?: Option[]; + value?: string; + placeholder?: string; + onChange?: (value: string) => any; +}; +export const Select = (props: SelectProps) => { + const options = props.options || []; + return ( + + + + + + {options.map((item, index) => { + return ( + + {item.label} + + ); + })} + + + ); +}; diff --git a/libs/registry/registry/components/a/tooltip.tsx b/libs/registry/registry/components/a/tooltip.tsx new file mode 100644 index 0000000..d07a4d9 --- /dev/null +++ b/libs/registry/registry/components/a/tooltip.tsx @@ -0,0 +1,14 @@ +import { Tooltip as UITooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; + +export const Tooltip = (props: { children?: React.ReactNode; title?: string }) => { + return ( + + + {props.children} + +

{props.title}

+
+
+
+ ); +}; diff --git a/libs/registry/registry/components/ui/alert-dialog.tsx b/libs/registry/registry/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..935eecf --- /dev/null +++ b/libs/registry/registry/components/ui/alert-dialog.tsx @@ -0,0 +1,155 @@ +import * as React from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +function AlertDialog({ + ...props +}: React.ComponentProps) { + return +} + +function AlertDialogTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogPortal({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogOverlay({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + + + + ) +} + +function AlertDialogHeader({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertDialogFooter({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function AlertDialogTitle({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogDescription({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogAction({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AlertDialogCancel({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel, +} diff --git a/libs/registry/registry/components/ui/breadcrumb.tsx b/libs/registry/registry/components/ui/breadcrumb.tsx new file mode 100644 index 0000000..eb88f32 --- /dev/null +++ b/libs/registry/registry/components/ui/breadcrumb.tsx @@ -0,0 +1,109 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { ChevronRight, MoreHorizontal } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { + return