basuicn 0.3.8 → 0.3.9
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/dist/ui-cli.cjs +1 -1
- package/package.json +1 -1
- package/registry.json +2 -2
- package/scripts/ui-cli.ts +1 -1
package/dist/ui-cli.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var import_fs = __toESM(require("fs"), 1);
|
|
|
27
27
|
var import_path = __toESM(require("path"), 1);
|
|
28
28
|
var import_child_process = require("child_process");
|
|
29
29
|
var import_readline = __toESM(require("readline"), 1);
|
|
30
|
-
var VERSION = "0.3.
|
|
30
|
+
var VERSION = "0.3.8";
|
|
31
31
|
var REGISTRY_LOCAL = "./registry.json";
|
|
32
32
|
var REGISTRY_REMOTE = "https://raw.githubusercontent.com/Basuicn/basuicn-core/main/registry.json";
|
|
33
33
|
var c = {
|
package/package.json
CHANGED
package/registry.json
CHANGED
|
@@ -339,7 +339,7 @@
|
|
|
339
339
|
"files": [
|
|
340
340
|
{
|
|
341
341
|
"path": "src/components/ui/drawer/Drawer.tsx",
|
|
342
|
-
"content": "import * as React from 'react';\r\nimport { tv, type VariantProps } from 'tailwind-variants';\r\nimport { Dialog as BaseDialog } from '@base-ui/react';\r\nimport { X } from 'lucide-react';\r\n\r\nconst drawerVariants = tv({\r\n slots: {\r\n overlay
|
|
342
|
+
"content": "import * as React from 'react';\r\nimport { tv, type VariantProps } from 'tailwind-variants';\r\nimport { Dialog as BaseDialog } from '@base-ui/react';\r\nimport { X } from 'lucide-react';\r\n\r\nconst drawerVariants = tv({\r\n slots: {\r\n overlay: [\r\n 'fixed inset-0 z-50 bg-black/40',\r\n 'transition-opacity duration-200 ease-out',\r\n 'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0',\r\n ],\r\n panel: [\r\n 'fixed z-50 bg-background shadow-2xl flex flex-col',\r\n 'outline-none overflow-hidden m-0 p-0 max-w-full max-h-full border-none',\r\n 'transition duration-300 ease-out',\r\n 'data-[starting-style]:opacity-0 data-[ending-style]:opacity-0',\r\n ],\r\n header:\r\n 'flex items-center justify-between px-6 py-4 border-b border-border/50 shrink-0',\r\n title: 'text-base font-semibold text-foreground',\r\n description: 'text-sm text-muted-foreground mt-0.5',\r\n body: 'flex-1 overflow-y-auto px-6 py-4',\r\n footer: 'px-6 py-4 border-t border-border/50 shrink-0',\r\n close:\r\n 'rounded-sm opacity-70 hover:opacity-100 transition-opacity ring-offset-background focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2',\r\n },\r\n variants: {\r\n direction: {\r\n left: {\r\n panel: [\r\n 'inset-y-0 left-0 h-full',\r\n 'data-[starting-style]:-translate-x-full data-[ending-style]:-translate-x-full',\r\n ],\r\n },\r\n right: {\r\n panel: [\r\n 'inset-y-0 right-0 h-full',\r\n 'data-[starting-style]:translate-x-full data-[ending-style]:translate-x-full',\r\n ],\r\n },\r\n top: {\r\n panel: [\r\n 'inset-x-0 top-0 w-full',\r\n 'data-[starting-style]:-translate-y-full data-[ending-style]:-translate-y-full',\r\n ],\r\n },\r\n bottom: {\r\n panel: [\r\n 'inset-x-0 bottom-0 w-full',\r\n 'data-[starting-style]:translate-y-full data-[ending-style]:translate-y-full',\r\n ],\r\n },\r\n },\r\n size: {\r\n sm: {},\r\n md: {},\r\n lg: {},\r\n full: {},\r\n },\r\n backdropBlur: {\r\n true: { overlay: 'backdrop-blur-sm' },\r\n false: { overlay: '' },\r\n },\r\n },\r\n compoundVariants: [\r\n { direction: 'left', size: 'sm', class: { panel: 'w-64' } },\r\n { direction: 'left', size: 'md', class: { panel: 'w-80' } },\r\n { direction: 'left', size: 'lg', class: { panel: 'w-[500px]' } },\r\n { direction: 'left', size: 'full', class: { panel: 'w-full' } },\r\n { direction: 'right', size: 'sm', class: { panel: 'w-64' } },\r\n { direction: 'right', size: 'md', class: { panel: 'w-80' } },\r\n { direction: 'right', size: 'lg', class: { panel: 'w-[500px]' } },\r\n { direction: 'right', size: 'full', class: { panel: 'w-full' } },\r\n { direction: 'top', size: 'sm', class: { panel: 'h-48' } },\r\n { direction: 'top', size: 'md', class: { panel: 'h-64' } },\r\n { direction: 'top', size: 'lg', class: { panel: 'h-[500px]' } },\r\n { direction: 'top', size: 'full', class: { panel: 'h-full' } },\r\n { direction: 'bottom', size: 'sm', class: { panel: 'h-48' } },\r\n { direction: 'bottom', size: 'md', class: { panel: 'h-64' } },\r\n { direction: 'bottom', size: 'lg', class: { panel: 'h-[500px]' } },\r\n { direction: 'bottom', size: 'full', class: { panel: 'h-full' } },\r\n ],\r\n defaultVariants: {\r\n direction: 'right',\r\n size: 'md',\r\n backdropBlur: true,\r\n },\r\n});\r\n\r\n/* ─── Root ─── */\r\nconst Drawer = BaseDialog.Root;\r\n\r\n/* ─── Trigger ─── */\r\nconst DrawerTrigger = BaseDialog.Trigger;\r\n\r\n/* ─── Close (re-export for custom close buttons) ─── */\r\nconst DrawerClose = BaseDialog.Close;\r\n\r\n/* ─── Content (Portal + Backdrop + Popup) ─── */\r\ninterface DrawerContentProps\r\n extends Omit<React.ComponentPropsWithoutRef<typeof BaseDialog.Popup>, 'className'>,\r\n VariantProps<typeof drawerVariants> {\r\n className?: string;\r\n}\r\n\r\nconst DrawerContent = React.forwardRef<HTMLDivElement, DrawerContentProps>(\r\n ({ className, children, direction, size, backdropBlur, ...props }, ref) => {\r\n const slots = drawerVariants({ direction, size, backdropBlur });\r\n return (\r\n <BaseDialog.Portal>\r\n <BaseDialog.Backdrop className={slots.overlay()} />\r\n <BaseDialog.Popup ref={ref} className={slots.panel({ className })} {...props}>\r\n {children}\r\n </BaseDialog.Popup>\r\n </BaseDialog.Portal>\r\n );\r\n },\r\n);\r\nDrawerContent.displayName = 'DrawerContent';\r\n\r\n/* ─── Header (includes close button by default) ─── */\r\ninterface DrawerHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\r\n hideClose?: boolean;\r\n}\r\n\r\nconst DrawerHeader = React.forwardRef<HTMLDivElement, DrawerHeaderProps>(\r\n ({ className, children, hideClose, ...props }, ref) => {\r\n const slots = drawerVariants();\r\n return (\r\n <div ref={ref} className={slots.header({ className })} {...props}>\r\n <div>{children}</div>\r\n {!hideClose && (\r\n <BaseDialog.Close className={slots.close()} aria-label=\"Close\">\r\n <X className=\"h-4 w-4\" />\r\n </BaseDialog.Close>\r\n )}\r\n </div>\r\n );\r\n },\r\n);\r\nDrawerHeader.displayName = 'DrawerHeader';\r\n\r\n/* ─── Title ─── */\r\nconst DrawerTitle = React.forwardRef<\r\n HTMLHeadingElement,\r\n Omit<React.ComponentPropsWithoutRef<typeof BaseDialog.Title>, 'className'> & {\r\n className?: string;\r\n }\r\n>(({ className, ...props }, ref) => {\r\n const slots = drawerVariants();\r\n return <BaseDialog.Title ref={ref} className={slots.title({ className })} {...props} />;\r\n});\r\nDrawerTitle.displayName = 'DrawerTitle';\r\n\r\n/* ─── Description ─── */\r\nconst DrawerDescription = React.forwardRef<\r\n HTMLParagraphElement,\r\n Omit<React.ComponentPropsWithoutRef<typeof BaseDialog.Description>, 'className'> & {\r\n className?: string;\r\n }\r\n>(({ className, ...props }, ref) => {\r\n const slots = drawerVariants();\r\n return (\r\n <BaseDialog.Description ref={ref} className={slots.description({ className })} {...props} />\r\n );\r\n});\r\nDrawerDescription.displayName = 'DrawerDescription';\r\n\r\n/* ─── Body (scrollable content area) ─── */\r\nconst DrawerBody = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\r\n ({ className, ...props }, ref) => {\r\n const slots = drawerVariants();\r\n return <div ref={ref} className={slots.body({ className })} {...props} />;\r\n },\r\n);\r\nDrawerBody.displayName = 'DrawerBody';\r\n\r\n/* ─── Footer ─── */\r\nconst DrawerFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\r\n ({ className, ...props }, ref) => {\r\n const slots = drawerVariants();\r\n return <div ref={ref} className={slots.footer({ className })} {...props} />;\r\n },\r\n);\r\nDrawerFooter.displayName = 'DrawerFooter';\r\n\r\nexport {\r\n Drawer,\r\n DrawerTrigger,\r\n DrawerContent,\r\n DrawerHeader,\r\n DrawerTitle,\r\n DrawerDescription,\r\n DrawerBody,\r\n DrawerFooter,\r\n DrawerClose,\r\n};\r\nexport type { DrawerContentProps, DrawerHeaderProps };\r\n"
|
|
343
343
|
}
|
|
344
344
|
]
|
|
345
345
|
},
|
|
@@ -1040,7 +1040,7 @@
|
|
|
1040
1040
|
"files": [
|
|
1041
1041
|
{
|
|
1042
1042
|
"path": "src/components/ui/textarea/Textarea.tsx",
|
|
1043
|
-
"content": "import * as React from 'react';\r\nimport { Field as BaseField } from '@base-ui/react';\r\nimport { tv, type VariantProps } from 'tailwind-variants';\r\nimport { cn } from '@/lib/utils/cn';\r\n\r\nconst textareaVariants = tv({\r\n base: 'flex min-h-[80px] w-full rounded-lg border border-border bg-background px-3 py-2 text-sm focus:border-primary focus:ring-0 placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 transition-shadow',\r\n variants: {\r\n variant: {\r\n default: '',\r\n filled: 'bg-accent border-transparent focus-visible:border-primary focus-visible:ring-0',\r\n }
|
|
1043
|
+
"content": "import * as React from 'react';\r\nimport { Field as BaseField } from '@base-ui/react';\r\nimport { tv, type VariantProps } from 'tailwind-variants';\r\nimport { cn } from '@/lib/utils/cn';\r\n\r\nconst textareaVariants = tv({\r\n base: 'flex min-h-[80px] w-full rounded-lg border border-border bg-background px-3 py-2 text-sm focus:border-primary focus:ring-0 placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 transition-shadow',\r\n variants: {\r\n variant: {\r\n default: '',\r\n filled: 'bg-accent border-transparent focus-visible:border-primary focus-visible:ring-0',\r\n },\r\n },\r\n defaultVariants: {\r\n variant: 'default',\r\n },\r\n});\r\n\r\n/** Props for the Textarea component */\r\nexport interface TextareaProps\r\n extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'maxLength' | 'minLength'>,\r\n VariantProps<typeof textareaVariants> {\r\n /** Label text displayed above the textarea */\r\n label?: string;\r\n /** Error message displayed below the textarea (replaces description) */\r\n error?: string;\r\n /** Helper text displayed below the textarea */\r\n description?: string;\r\n /** Show count of characters */\r\n showCount?: boolean;\r\n /** Max characters — enforced natively, displayed as count/max when showCount is true */\r\n maxLength?: number;\r\n /** Min characters — shows hint when current count is below min */\r\n minLength?: number;\r\n required?: boolean;\r\n}\r\n\r\nconst Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\r\n (\r\n {\r\n className,\r\n variant,\r\n label,\r\n error,\r\n description,\r\n showCount,\r\n maxLength,\r\n minLength,\r\n required,\r\n onChange,\r\n value,\r\n defaultValue,\r\n ...rest\r\n },\r\n ref,\r\n ) => {\r\n const isControlled = value !== undefined;\r\n\r\n const [charCount, setCharCount] = React.useState<number>(() => {\r\n if (isControlled) return String(value ?? '').length;\r\n if (defaultValue !== undefined) return String(defaultValue).length;\r\n return 0;\r\n });\r\n\r\n React.useEffect(() => {\r\n if (isControlled) setCharCount(String(value ?? '').length);\r\n }, [isControlled, value]);\r\n\r\n const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n setCharCount(event.target.value.length);\r\n onChange?.(event);\r\n };\r\n\r\n const isNearLimit = maxLength !== undefined && charCount >= Math.floor(maxLength * 0.9);\r\n const isAtLimit = maxLength !== undefined && charCount >= maxLength;\r\n const isBelowMin = minLength !== undefined && charCount > 0 && charCount < minLength;\r\n\r\n const hasFooter = error ?? description ?? isBelowMin;\r\n\r\n return (\r\n <BaseField.Root className=\"flex w-full flex-col gap-1.5\">\r\n {label && (\r\n <BaseField.Label className=\"text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70\">\r\n {label}\r\n {required && <span className=\"ml-0.5 text-danger\">*</span>}\r\n </BaseField.Label>\r\n )}\r\n\r\n <div className=\"relative\">\r\n <BaseField.Control\r\n render={\r\n <textarea\r\n ref={ref}\r\n className={cn(\r\n textareaVariants({ variant }),\r\n error && 'border-danger focus-visible:ring-danger',\r\n showCount && 'pb-6',\r\n className,\r\n )}\r\n value={value}\r\n defaultValue={!isControlled ? defaultValue : undefined}\r\n maxLength={maxLength}\r\n minLength={minLength}\r\n required={required}\r\n onChange={handleChange}\r\n {...rest}\r\n />\r\n }\r\n />\r\n\r\n {showCount && (\r\n <span\r\n className={cn(\r\n 'pointer-events-none absolute bottom-1 right-3 select-none text-[0.7rem] tabular-nums text-muted-foreground',\r\n isNearLimit && 'font-medium text-warning',\r\n isAtLimit && 'text-danger',\r\n )}\r\n >\r\n {charCount}\r\n {maxLength !== undefined && `/${maxLength}`}\r\n </span>\r\n )}\r\n </div>\r\n\r\n {hasFooter && (\r\n <div className=\"flex flex-col gap-0.5\">\r\n {error ? (\r\n <p className=\"text-[0.8rem] font-medium text-danger\">{error}</p>\r\n ) : (\r\n <>\r\n {description && (\r\n <BaseField.Description className=\"text-[0.8rem] text-muted-foreground\">\r\n {description}\r\n </BaseField.Description>\r\n )}\r\n {isBelowMin && (\r\n <p className=\"text-[0.8rem] text-warning\">Tối thiểu {minLength} ký tự</p>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </BaseField.Root>\r\n );\r\n },\r\n);\r\nTextarea.displayName = 'Textarea';\r\n\r\nexport { Textarea };\r\n"
|
|
1044
1044
|
}
|
|
1045
1045
|
]
|
|
1046
1046
|
},
|
package/scripts/ui-cli.ts
CHANGED
|
@@ -6,7 +6,7 @@ import readline from 'readline';
|
|
|
6
6
|
|
|
7
7
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
8
8
|
|
|
9
|
-
const VERSION = '0.3.
|
|
9
|
+
const VERSION = '0.3.9';
|
|
10
10
|
const REGISTRY_LOCAL = './registry.json';
|
|
11
11
|
const REGISTRY_REMOTE = 'https://raw.githubusercontent.com/Basuicn/basuicn-core/main/registry.json';
|
|
12
12
|
|