diff --git a/exec/cli.js b/exec/cli.js index 95d3b40..92ed266 100755 --- a/exec/cli.js +++ b/exec/cli.js @@ -1,5 +1,5 @@ #!/usr/bin/env node -import{Command as Re}from"commander";import h from"fs-extra";import u from"path";import f from"chalk";import ee from"ora";import{fileURLToPath as Ae}from"url";import{execSync as $e}from"child_process";import Ie from"enquirer";var w={accordion:{name:"Accordion",files:["src/dashkit/Accordion/Accordion.tsx","src/dashkit/Accordion/AccordionItem.tsx","src/dashkit/Accordion/AccordionTrigger.tsx","src/dashkit/Accordion/AccordionContent.tsx","src/dashkit/Accordion/AccordionContext.ts","src/dashkit/Accordion/Accordion.test.tsx","src/dashkit/Accordion/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},avatar:{name:"Avatar",files:["src/dashkit/Avatar/Avatar.tsx","src/dashkit/Avatar/AvatarGroup.tsx","src/dashkit/Avatar/Avatar.test.tsx","src/dashkit/Avatar/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},badge:{name:"Badge",files:["src/dashkit/Badge/Badge.tsx","src/dashkit/Badge/FloatBadge.tsx","src/dashkit/Badge/Badge.test.tsx","src/dashkit/Badge/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},floatbadge:{name:"FloatBadge",files:["src/dashkit/Badge/FloatBadge.tsx"],dependencies:["clsx","tailwind-merge"],registryDependencies:["badge"]},button:{name:"Button",files:["src/dashkit/Button/Button.tsx","src/dashkit/Button/Button.test.tsx","src/dashkit/Button/index.ts"],registryDependencies:["spinner"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},card:{name:"Card",files:["src/dashkit/Card/Card.tsx","src/dashkit/Card/CardHeader.tsx","src/dashkit/Card/CardContent.tsx","src/dashkit/Card/CardFooter.tsx","src/dashkit/Card/Card.test.tsx","src/dashkit/Card/index.ts"],registryDependencies:["badge","button"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},chip:{name:"Chip",files:["src/dashkit/Chip/Chip.tsx","src/dashkit/Chip/Chip.test.tsx","src/dashkit/Chip/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority","react-icons"]},checkbox:{name:"Checkbox",files:["src/dashkit/Checkbox/Checkbox.tsx","src/dashkit/Checkbox/Checkbox.test.tsx","src/dashkit/Checkbox/index.ts"],dependencies:["clsx","tailwind-merge"]},drawer:{name:"Drawer",files:["src/dashkit/Drawer/Drawer.tsx","src/dashkit/Drawer/useDrawer.ts","src/dashkit/Drawer/Drawer.test.tsx","src/dashkit/Drawer/index.ts"],registryDependencies:["backdrop"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority","react-icons"]},dropdown:{name:"Dropdown",files:["src/dashkit/Dropdown/Dropdown.tsx","src/dashkit/Dropdown/DropdownContent.tsx","src/dashkit/Dropdown/DropdownItem.tsx","src/dashkit/Dropdown/DropdownLabel.tsx","src/dashkit/Dropdown/DropdownSeparator.tsx","src/dashkit/Dropdown/DropdownTrigger.tsx","src/dashkit/Dropdown/useDropdown.ts","src/dashkit/Dropdown/Dropdown.test.tsx","src/dashkit/Dropdown/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"]},imageexpander:{name:"ImageExpander",files:["src/dashkit/ImageExpander/ImageExpander.tsx","src/dashkit/ImageExpander/useImageExpander.ts","src/dashkit/ImageExpander/ImageExpander.test.tsx","src/dashkit/ImageExpander/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},input:{name:"Input",files:["src/dashkit/Input/Input.tsx","src/dashkit/Input/Input.test.tsx","src/dashkit/Input/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},modal:{name:"Modal",files:["src/dashkit/Modal/Modal.tsx","src/dashkit/Modal/ModalContent.tsx","src/dashkit/Modal/ModalFooter.tsx","src/dashkit/Modal/ModalHeader.tsx","src/dashkit/Modal/useModal.ts","src/dashkit/Modal/Modal.test.tsx","src/dashkit/Modal/index.ts"],registryDependencies:["backdrop","iconbutton"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority","react-icons"]},otpinput:{name:"OtpInput",files:["src/dashkit/OtpInput/OtpInput.tsx","src/dashkit/OtpInput/useOtpInput.ts","src/dashkit/OtpInput/OtpInput.test.tsx","src/dashkit/OtpInput/index.ts"],dependencies:["clsx","tailwind-merge"]},radio:{name:"Radio",files:["src/dashkit/Radio/Radio.tsx","src/dashkit/Radio/useRadio.ts","src/dashkit/Radio/Radio.test.tsx","src/dashkit/Radio/index.ts"],dependencies:["clsx","tailwind-merge"]},select:{name:"Select",files:["src/dashkit/Select/Select.tsx","src/dashkit/Select/useSelect.ts","src/dashkit/Select/Select.test.tsx","src/dashkit/Select/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority","react-icons"]},switch:{name:"Switch",files:["src/dashkit/Switch/Switch.tsx","src/dashkit/Switch/useSwitch.ts","src/dashkit/Switch/Switch.test.tsx","src/dashkit/Switch/index.ts"],dependencies:["clsx","tailwind-merge"]},slider:{name:"Slider",files:["src/dashkit/Slider/Slider.tsx","src/dashkit/Slider/useSlider.ts","src/dashkit/Slider/Slider.test.tsx","src/dashkit/Slider/index.ts"],dependencies:["clsx","tailwind-merge"]},surface:{name:"Surface",files:["src/dashkit/Surface/Surface.tsx","src/dashkit/Surface/Surface.test.tsx","src/dashkit/Surface/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},tabs:{name:"Tabs",files:["src/dashkit/Tabs/Tabs.tsx","src/dashkit/Tabs/Tabs.test.tsx","src/dashkit/Tabs/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},toast:{name:"Toast",files:["src/dashkit/Toast/Toast.tsx","src/dashkit/Toast/useToast.ts","src/dashkit/Toast/Toast.test.tsx","src/dashkit/Toast/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},stepper:{name:"Stepper",files:["src/dashkit/Stepper/Stepper.tsx","src/dashkit/Stepper/Stepper.test.tsx","src/dashkit/Stepper/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},pagination:{name:"Pagination",files:["src/dashkit/Pagination/Pagination.tsx","src/dashkit/Pagination/Pagination.test.tsx","src/dashkit/Pagination/index.ts"],dependencies:["clsx","tailwind-merge","react-icons","framer-motion"]},spinner:{name:"Spinner",files:["src/dashkit/Spinner/Spinner.tsx","src/dashkit/Spinner/Spinner.test.tsx","src/dashkit/Spinner/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},navbar:{name:"Navbar",files:["src/dashkit/Navbar/Navbar.tsx","src/dashkit/Navbar/NavbarActions.tsx","src/dashkit/Navbar/NavbarBrand.tsx","src/dashkit/Navbar/NavbarLinks.tsx","src/dashkit/Navbar/Navbar.test.tsx","src/dashkit/Navbar/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},skeleton:{name:"Skeleton",files:["src/dashkit/Skeleton/Skeleton.tsx","src/dashkit/Skeleton/Skeleton.test.tsx","src/dashkit/Skeleton/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},breadcrumb:{name:"Breadcrumb",files:["src/dashkit/Breadcrumb/Breadcrumb.tsx","src/dashkit/Breadcrumb/BreadcrumbList.tsx","src/dashkit/Breadcrumb/BreadcrumbItem.tsx","src/dashkit/Breadcrumb/BreadcrumbSeparator.tsx","src/dashkit/Breadcrumb/BreadcrumbEllipsis.tsx","src/dashkit/Breadcrumb/Breadcrumb.test.tsx","src/dashkit/Breadcrumb/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"]},iconbutton:{name:"IconButton",files:["src/dashkit/IconButton/IconButton.tsx","src/dashkit/IconButton/IconButton.test.tsx","src/dashkit/IconButton/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},areachart:{name:"AreaChart",files:["src/dashkit/AreaChart/AreaChart.tsx","src/dashkit/AreaChart/useAreaChart.ts","src/dashkit/AreaChart/AreaChart.test.tsx","src/dashkit/AreaChart/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},barchart:{name:"BarChart",files:["src/dashkit/BarChart/BarChart.tsx","src/dashkit/BarChart/useBarChart.ts","src/dashkit/BarChart/BarChart.test.tsx","src/dashkit/BarChart/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},linechart:{name:"LineChart",files:["src/dashkit/LineChart/LineChart.tsx","src/dashkit/LineChart/useLineChart.ts","src/dashkit/LineChart/LineChart.test.tsx","src/dashkit/LineChart/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},piechart:{name:"PieChart",files:["src/dashkit/PieChart/PieChart.tsx","src/dashkit/PieChart/usePieChart.ts","src/dashkit/PieChart/PieChart.test.tsx","src/dashkit/PieChart/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},progressbar:{name:"ProgressBar",files:["src/dashkit/ProgressBar/ProgressBar.tsx","src/dashkit/ProgressBar/useProgressBar.ts","src/dashkit/ProgressBar/ProgressBar.test.tsx","src/dashkit/ProgressBar/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},buttongroup:{name:"ButtonGroup",files:["src/dashkit/ButtonGroup/ButtonGroup.tsx","src/dashkit/ButtonGroup/ButtonGroup.test.tsx","src/dashkit/ButtonGroup/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},combobox:{name:"Combobox",files:["src/dashkit/Combobox/Combobox.tsx","src/dashkit/Combobox/useCombobox.ts","src/dashkit/Combobox/Combobox.test.tsx","src/dashkit/Combobox/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"],registryDependencies:["chip"]},divider:{name:"Divider",files:["src/dashkit/Divider/Divider.tsx","src/dashkit/Divider/Divider.test.tsx","src/dashkit/Divider/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},sidebar:{name:"Sidebar",files:["src/dashkit/Sidebar/Sidebar.tsx","src/dashkit/Sidebar/useSidebar.ts","src/dashkit/Sidebar/SidebarContext.tsx","src/dashkit/Sidebar/Sidebar.test.tsx","src/dashkit/Sidebar/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"],registryDependencies:["iconbutton","tooltip","backdrop"]},"float-action-menu":{name:"FloatActionMenu",files:["src/dashkit/FloatActionMenu/FloatActionMenu.tsx","src/dashkit/FloatActionMenu/useFloatActionMenu.ts","src/dashkit/FloatActionMenu/FloatActionMenu.test.tsx","src/dashkit/FloatActionMenu/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"],registryDependencies:["iconbutton"]},textarea:{name:"Textarea",files:["src/dashkit/Textarea/Textarea.tsx","src/dashkit/Textarea/useTextarea.ts","src/dashkit/Textarea/Textarea.test.tsx","src/dashkit/Textarea/index.ts"],dependencies:["clsx","tailwind-merge"]},datepicker:{name:"DatePicker",files:["src/dashkit/DatePicker/DatePicker.tsx","src/dashkit/DatePicker/useDatePicker.ts","src/dashkit/DatePicker/DatePicker.test.tsx","src/dashkit/DatePicker/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"]},table:{name:"Table",files:["src/dashkit/Table/Table.tsx","src/dashkit/Table/Table.test.tsx","src/dashkit/Table/index.ts"],dependencies:["clsx","tailwind-merge"]},animatenumber:{name:"AnimateNumber",files:["src/dashkit/AnimateNumber/AnimateNumber.tsx","src/dashkit/AnimateNumber/Digit.tsx","src/dashkit/AnimateNumber/AnimateNumber.test.tsx","src/dashkit/AnimateNumber/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},circularprogress:{name:"CircularProgress",files:["src/dashkit/CircularProgress/CircularProgress.tsx","src/dashkit/CircularProgress/CircularProgress.test.tsx","src/dashkit/CircularProgress/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},dock:{name:"Dock",files:["src/dashkit/Dock/Dock.tsx","src/dashkit/Dock/DockItem.tsx","src/dashkit/Dock/Dock.test.tsx","src/dashkit/Dock/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},popover:{name:"Popover",files:["src/dashkit/Popover/Popover.tsx","src/dashkit/Popover/PopoverContent.tsx","src/dashkit/Popover/PopoverTrigger.tsx","src/dashkit/Popover/usePopover.ts","src/dashkit/Popover/Popover.test.tsx","src/dashkit/Popover/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},tooltip:{name:"Tooltip",files:["src/dashkit/Tooltip/Tooltip.tsx","src/dashkit/Tooltip/Tooltip.test.tsx","src/dashkit/Tooltip/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},systemlogs:{name:"SystemLogs",files:["src/dashkit/SystemLogs/SystemLogs.tsx","src/dashkit/SystemLogs/SystemLogs.test.tsx","src/dashkit/SystemLogs/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"],registryDependencies:["badge"]},datefield:{name:"DateField",files:["src/dashkit/DateField/DateField.tsx","src/dashkit/DateField/useDateField.ts","src/dashkit/DateField/DateField.test.tsx","src/dashkit/DateField/index.ts"],dependencies:["clsx","tailwind-merge"]},"navigation-menu":{name:"NavigationMenu",files:["src/dashkit/NavigationMenu/NavigationMenu.tsx","src/dashkit/NavigationMenu/NavigationMenuContent.tsx","src/dashkit/NavigationMenu/NavigationMenuContext.tsx","src/dashkit/NavigationMenu/NavigationMenuItem.tsx","src/dashkit/NavigationMenu/NavigationMenuLink.tsx","src/dashkit/NavigationMenu/NavigationMenuList.tsx","src/dashkit/NavigationMenu/NavigationMenuTrigger.tsx","src/dashkit/NavigationMenu/NavigationMenuViewport.tsx","src/dashkit/NavigationMenu/useNavigationMenu.ts","src/dashkit/NavigationMenu/useNavigationMenuViewport.ts","src/dashkit/NavigationMenu/NavigationMenu.test.tsx","src/dashkit/NavigationMenu/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},backdrop:{name:"Backdrop",files:["src/dashkit/Backdrop/Backdrop.tsx","src/dashkit/Backdrop/Backdrop.test.tsx","src/dashkit/Backdrop/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},scrollarea:{name:"ScrollArea",files:["src/dashkit/ScrollArea/ScrollArea.tsx","src/dashkit/ScrollArea/ScrollArea.test.tsx","src/dashkit/ScrollArea/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},statscard:{name:"StatsCard",files:["src/dashkit/StatsCard/StatsCard.tsx","src/dashkit/StatsCard/StatsCard.test.tsx","src/dashkit/StatsCard/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"],registryDependencies:["card","animatenumber","divider"]},colorpicker:{name:"ColorPicker",files:["src/dashkit/ColorPicker/ColorPicker.tsx","src/dashkit/ColorPicker/ColorPicker.test.tsx","src/dashkit/ColorPicker/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"],registryDependencies:["popover","input"]},copyfield:{name:"CopyField",files:["src/dashkit/CopyField/CopyField.tsx","src/dashkit/CopyField/CopyField.test.tsx","src/dashkit/CopyField/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"],registryDependencies:["input","iconbutton","toast"]},listtile:{name:"ListTile",files:["src/dashkit/ListTile/ListTile.tsx","src/dashkit/ListTile/ListTile.test.tsx","src/dashkit/ListTile/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]}};import F from"fs-extra";import B from"path";import Z from"chalk";import Q from"ora";import v from"fs-extra";import M from"path";var ne="dashkit.json";function S(e){let t=e.trim().replace(/\\/g,"/").replace(/^\.\/+/,"").replace(/\/+$/,"");return t==="."?"":t}function U(e,t="dashkit"){let s=S(e)||S(t)||"dashkit";return(s.split("/").pop()??"").toLowerCase().includes("dashkit")?s:`${s}/dashkit`}async function re(e){let t={componentsDir:S(e.componentsDir),cssDir:S(e.cssDir)};await v.writeJson(M.resolve(process.cwd(),ne),t,{spaces:2})}async function $(){let e=M.resolve(process.cwd(),ne);if(await v.pathExists(e))try{return await v.readJson(e)}catch{return null}return null}async function I(){let e=process.cwd(),t=await v.pathExists(M.resolve(e,"src")),s=await v.pathExists(M.resolve(e,"app"))||await v.pathExists(M.resolve(e,"src","app"));return{hasSrc:t,hasApp:s}}function T(e){let t=e.hasSrc?"src/dashkit":"dashkit";return{components:t,css:t}}async function Y(e=process.cwd()){let t=["src/index.css","src/main.css","src/app.css","src/globals.css","src/app/globals.css","app/globals.css","styles/globals.css","index.css"];for(let s of t){let i=M.resolve(e,s);if(await v.pathExists(i))return i}return null}function X(e,t){let s=M.relative(M.dirname(e),t).replace(/\\/g,"/");return s.startsWith(".")||(s=`./${s}`),s}async function ae(e,t){if(!await v.pathExists(e))return{updated:!1,reason:"main_css_not_found"};let s=await v.readFile(e,"utf8");if(s.includes("dashkit.css"))return{updated:!1,reason:"already_imported"};let i=X(e,t),r=`@import "${i}";`,p=/(@import\s+['"]tailwindcss['"];?)(?:\r?\n|$)/,o;return p.test(s)?o=s.replace(p,`$1 +import{Command as Re}from"commander";import h from"fs-extra";import u from"path";import f from"chalk";import ee from"ora";import{fileURLToPath as Ae}from"url";import{execSync as $e}from"child_process";import Ie from"enquirer";var w={accordion:{name:"Accordion",files:["src/dashkit/Accordion/Accordion.tsx","src/dashkit/Accordion/AccordionItem.tsx","src/dashkit/Accordion/AccordionTrigger.tsx","src/dashkit/Accordion/AccordionContent.tsx","src/dashkit/Accordion/AccordionContext.ts","src/dashkit/Accordion/Accordion.test.tsx","src/dashkit/Accordion/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},avatar:{name:"Avatar",files:["src/dashkit/Avatar/Avatar.tsx","src/dashkit/Avatar/AvatarGroup.tsx","src/dashkit/Avatar/Avatar.test.tsx","src/dashkit/Avatar/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},badge:{name:"Badge",files:["src/dashkit/Badge/Badge.tsx","src/dashkit/Badge/FloatBadge.tsx","src/dashkit/Badge/Badge.test.tsx","src/dashkit/Badge/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},floatbadge:{name:"FloatBadge",files:["src/dashkit/Badge/FloatBadge.tsx"],dependencies:["clsx","tailwind-merge"],registryDependencies:["badge"]},"bento-grid":{name:"BentoGrid",files:["src/dashkit/BentoGrid/BentoGrid.tsx","src/dashkit/BentoGrid/BentoGrid.test.tsx","src/dashkit/BentoGrid/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},button:{name:"Button",files:["src/dashkit/Button/Button.tsx","src/dashkit/Button/Button.test.tsx","src/dashkit/Button/index.ts"],registryDependencies:["spinner"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},card:{name:"Card",files:["src/dashkit/Card/Card.tsx","src/dashkit/Card/CardHeader.tsx","src/dashkit/Card/CardContent.tsx","src/dashkit/Card/CardFooter.tsx","src/dashkit/Card/Card.test.tsx","src/dashkit/Card/index.ts"],registryDependencies:["badge","button"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},chip:{name:"Chip",files:["src/dashkit/Chip/Chip.tsx","src/dashkit/Chip/Chip.test.tsx","src/dashkit/Chip/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority","react-icons"]},checkbox:{name:"Checkbox",files:["src/dashkit/Checkbox/Checkbox.tsx","src/dashkit/Checkbox/Checkbox.test.tsx","src/dashkit/Checkbox/index.ts"],dependencies:["clsx","tailwind-merge"]},drawer:{name:"Drawer",files:["src/dashkit/Drawer/Drawer.tsx","src/dashkit/Drawer/useDrawer.ts","src/dashkit/Drawer/Drawer.test.tsx","src/dashkit/Drawer/index.ts"],registryDependencies:["backdrop"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority","react-icons"]},dropdown:{name:"Dropdown",files:["src/dashkit/Dropdown/Dropdown.tsx","src/dashkit/Dropdown/DropdownContent.tsx","src/dashkit/Dropdown/DropdownItem.tsx","src/dashkit/Dropdown/DropdownLabel.tsx","src/dashkit/Dropdown/DropdownSeparator.tsx","src/dashkit/Dropdown/DropdownTrigger.tsx","src/dashkit/Dropdown/useDropdown.ts","src/dashkit/Dropdown/Dropdown.test.tsx","src/dashkit/Dropdown/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"]},imageexpander:{name:"ImageExpander",files:["src/dashkit/ImageExpander/ImageExpander.tsx","src/dashkit/ImageExpander/useImageExpander.ts","src/dashkit/ImageExpander/ImageExpander.test.tsx","src/dashkit/ImageExpander/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},input:{name:"Input",files:["src/dashkit/Input/Input.tsx","src/dashkit/Input/Input.test.tsx","src/dashkit/Input/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},modal:{name:"Modal",files:["src/dashkit/Modal/Modal.tsx","src/dashkit/Modal/ModalContent.tsx","src/dashkit/Modal/ModalFooter.tsx","src/dashkit/Modal/ModalHeader.tsx","src/dashkit/Modal/useModal.ts","src/dashkit/Modal/Modal.test.tsx","src/dashkit/Modal/index.ts"],registryDependencies:["backdrop","iconbutton"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority","react-icons"]},otpinput:{name:"OtpInput",files:["src/dashkit/OtpInput/OtpInput.tsx","src/dashkit/OtpInput/useOtpInput.ts","src/dashkit/OtpInput/OtpInput.test.tsx","src/dashkit/OtpInput/index.ts"],dependencies:["clsx","tailwind-merge"]},radio:{name:"Radio",files:["src/dashkit/Radio/Radio.tsx","src/dashkit/Radio/useRadio.ts","src/dashkit/Radio/Radio.test.tsx","src/dashkit/Radio/index.ts"],dependencies:["clsx","tailwind-merge"]},select:{name:"Select",files:["src/dashkit/Select/Select.tsx","src/dashkit/Select/useSelect.ts","src/dashkit/Select/Select.test.tsx","src/dashkit/Select/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority","react-icons"]},switch:{name:"Switch",files:["src/dashkit/Switch/Switch.tsx","src/dashkit/Switch/useSwitch.ts","src/dashkit/Switch/Switch.test.tsx","src/dashkit/Switch/index.ts"],dependencies:["clsx","tailwind-merge"]},slider:{name:"Slider",files:["src/dashkit/Slider/Slider.tsx","src/dashkit/Slider/useSlider.ts","src/dashkit/Slider/Slider.test.tsx","src/dashkit/Slider/index.ts"],dependencies:["clsx","tailwind-merge"]},surface:{name:"Surface",files:["src/dashkit/Surface/Surface.tsx","src/dashkit/Surface/Surface.test.tsx","src/dashkit/Surface/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},tabs:{name:"Tabs",files:["src/dashkit/Tabs/Tabs.tsx","src/dashkit/Tabs/Tabs.test.tsx","src/dashkit/Tabs/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},toast:{name:"Toast",files:["src/dashkit/Toast/Toast.tsx","src/dashkit/Toast/useToast.ts","src/dashkit/Toast/Toast.test.tsx","src/dashkit/Toast/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},stepper:{name:"Stepper",files:["src/dashkit/Stepper/Stepper.tsx","src/dashkit/Stepper/Stepper.test.tsx","src/dashkit/Stepper/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},pagination:{name:"Pagination",files:["src/dashkit/Pagination/Pagination.tsx","src/dashkit/Pagination/Pagination.test.tsx","src/dashkit/Pagination/index.ts"],dependencies:["clsx","tailwind-merge","react-icons","framer-motion"]},spinner:{name:"Spinner",files:["src/dashkit/Spinner/Spinner.tsx","src/dashkit/Spinner/Spinner.test.tsx","src/dashkit/Spinner/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},navbar:{name:"Navbar",files:["src/dashkit/Navbar/Navbar.tsx","src/dashkit/Navbar/NavbarActions.tsx","src/dashkit/Navbar/NavbarBrand.tsx","src/dashkit/Navbar/NavbarLinks.tsx","src/dashkit/Navbar/Navbar.test.tsx","src/dashkit/Navbar/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},skeleton:{name:"Skeleton",files:["src/dashkit/Skeleton/Skeleton.tsx","src/dashkit/Skeleton/Skeleton.test.tsx","src/dashkit/Skeleton/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},breadcrumb:{name:"Breadcrumb",files:["src/dashkit/Breadcrumb/Breadcrumb.tsx","src/dashkit/Breadcrumb/BreadcrumbList.tsx","src/dashkit/Breadcrumb/BreadcrumbItem.tsx","src/dashkit/Breadcrumb/BreadcrumbSeparator.tsx","src/dashkit/Breadcrumb/BreadcrumbEllipsis.tsx","src/dashkit/Breadcrumb/Breadcrumb.test.tsx","src/dashkit/Breadcrumb/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"]},iconbutton:{name:"IconButton",files:["src/dashkit/IconButton/IconButton.tsx","src/dashkit/IconButton/IconButton.test.tsx","src/dashkit/IconButton/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},areachart:{name:"AreaChart",files:["src/dashkit/AreaChart/AreaChart.tsx","src/dashkit/AreaChart/useAreaChart.ts","src/dashkit/AreaChart/AreaChart.test.tsx","src/dashkit/AreaChart/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},barchart:{name:"BarChart",files:["src/dashkit/BarChart/BarChart.tsx","src/dashkit/BarChart/useBarChart.ts","src/dashkit/BarChart/BarChart.test.tsx","src/dashkit/BarChart/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},linechart:{name:"LineChart",files:["src/dashkit/LineChart/LineChart.tsx","src/dashkit/LineChart/useLineChart.ts","src/dashkit/LineChart/LineChart.test.tsx","src/dashkit/LineChart/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},piechart:{name:"PieChart",files:["src/dashkit/PieChart/PieChart.tsx","src/dashkit/PieChart/usePieChart.ts","src/dashkit/PieChart/PieChart.test.tsx","src/dashkit/PieChart/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},progressbar:{name:"ProgressBar",files:["src/dashkit/ProgressBar/ProgressBar.tsx","src/dashkit/ProgressBar/useProgressBar.ts","src/dashkit/ProgressBar/ProgressBar.test.tsx","src/dashkit/ProgressBar/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","class-variance-authority"]},buttongroup:{name:"ButtonGroup",files:["src/dashkit/ButtonGroup/ButtonGroup.tsx","src/dashkit/ButtonGroup/ButtonGroup.test.tsx","src/dashkit/ButtonGroup/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},combobox:{name:"Combobox",files:["src/dashkit/Combobox/Combobox.tsx","src/dashkit/Combobox/useCombobox.ts","src/dashkit/Combobox/Combobox.test.tsx","src/dashkit/Combobox/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"],registryDependencies:["chip"]},divider:{name:"Divider",files:["src/dashkit/Divider/Divider.tsx","src/dashkit/Divider/Divider.test.tsx","src/dashkit/Divider/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},sidebar:{name:"Sidebar",files:["src/dashkit/Sidebar/Sidebar.tsx","src/dashkit/Sidebar/useSidebar.ts","src/dashkit/Sidebar/SidebarContext.tsx","src/dashkit/Sidebar/Sidebar.test.tsx","src/dashkit/Sidebar/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"],registryDependencies:["iconbutton","tooltip","backdrop"]},"float-action-menu":{name:"FloatActionMenu",files:["src/dashkit/FloatActionMenu/FloatActionMenu.tsx","src/dashkit/FloatActionMenu/useFloatActionMenu.ts","src/dashkit/FloatActionMenu/FloatActionMenu.test.tsx","src/dashkit/FloatActionMenu/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"],registryDependencies:["iconbutton"]},textarea:{name:"Textarea",files:["src/dashkit/Textarea/Textarea.tsx","src/dashkit/Textarea/useTextarea.ts","src/dashkit/Textarea/Textarea.test.tsx","src/dashkit/Textarea/index.ts"],dependencies:["clsx","tailwind-merge"]},datepicker:{name:"DatePicker",files:["src/dashkit/DatePicker/DatePicker.tsx","src/dashkit/DatePicker/useDatePicker.ts","src/dashkit/DatePicker/DatePicker.test.tsx","src/dashkit/DatePicker/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"]},table:{name:"Table",files:["src/dashkit/Table/Table.tsx","src/dashkit/Table/Table.test.tsx","src/dashkit/Table/index.ts"],dependencies:["clsx","tailwind-merge"]},animatenumber:{name:"AnimateNumber",files:["src/dashkit/AnimateNumber/AnimateNumber.tsx","src/dashkit/AnimateNumber/Digit.tsx","src/dashkit/AnimateNumber/AnimateNumber.test.tsx","src/dashkit/AnimateNumber/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},circularprogress:{name:"CircularProgress",files:["src/dashkit/CircularProgress/CircularProgress.tsx","src/dashkit/CircularProgress/CircularProgress.test.tsx","src/dashkit/CircularProgress/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},dock:{name:"Dock",files:["src/dashkit/Dock/Dock.tsx","src/dashkit/Dock/DockItem.tsx","src/dashkit/Dock/Dock.test.tsx","src/dashkit/Dock/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},popover:{name:"Popover",files:["src/dashkit/Popover/Popover.tsx","src/dashkit/Popover/PopoverContent.tsx","src/dashkit/Popover/PopoverTrigger.tsx","src/dashkit/Popover/usePopover.ts","src/dashkit/Popover/Popover.test.tsx","src/dashkit/Popover/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},tooltip:{name:"Tooltip",files:["src/dashkit/Tooltip/Tooltip.tsx","src/dashkit/Tooltip/Tooltip.test.tsx","src/dashkit/Tooltip/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},systemlogs:{name:"SystemLogs",files:["src/dashkit/SystemLogs/SystemLogs.tsx","src/dashkit/SystemLogs/SystemLogs.test.tsx","src/dashkit/SystemLogs/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"],registryDependencies:["badge"]},datefield:{name:"DateField",files:["src/dashkit/DateField/DateField.tsx","src/dashkit/DateField/useDateField.ts","src/dashkit/DateField/DateField.test.tsx","src/dashkit/DateField/index.ts"],dependencies:["clsx","tailwind-merge"]},"navigation-menu":{name:"NavigationMenu",files:["src/dashkit/NavigationMenu/NavigationMenu.tsx","src/dashkit/NavigationMenu/NavigationMenuContent.tsx","src/dashkit/NavigationMenu/NavigationMenuContext.tsx","src/dashkit/NavigationMenu/NavigationMenuItem.tsx","src/dashkit/NavigationMenu/NavigationMenuLink.tsx","src/dashkit/NavigationMenu/NavigationMenuList.tsx","src/dashkit/NavigationMenu/NavigationMenuTrigger.tsx","src/dashkit/NavigationMenu/NavigationMenuViewport.tsx","src/dashkit/NavigationMenu/useNavigationMenu.ts","src/dashkit/NavigationMenu/useNavigationMenuViewport.ts","src/dashkit/NavigationMenu/NavigationMenu.test.tsx","src/dashkit/NavigationMenu/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"]},backdrop:{name:"Backdrop",files:["src/dashkit/Backdrop/Backdrop.tsx","src/dashkit/Backdrop/Backdrop.test.tsx","src/dashkit/Backdrop/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]},scrollarea:{name:"ScrollArea",files:["src/dashkit/ScrollArea/ScrollArea.tsx","src/dashkit/ScrollArea/ScrollArea.test.tsx","src/dashkit/ScrollArea/index.ts"],dependencies:["clsx","tailwind-merge","class-variance-authority"]},statscard:{name:"StatsCard",files:["src/dashkit/StatsCard/StatsCard.tsx","src/dashkit/StatsCard/StatsCard.test.tsx","src/dashkit/StatsCard/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge","react-icons"],registryDependencies:["card","animatenumber","divider"]},colorpicker:{name:"ColorPicker",files:["src/dashkit/ColorPicker/ColorPicker.tsx","src/dashkit/ColorPicker/ColorPicker.test.tsx","src/dashkit/ColorPicker/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"],registryDependencies:["popover","input"]},copyfield:{name:"CopyField",files:["src/dashkit/CopyField/CopyField.tsx","src/dashkit/CopyField/CopyField.test.tsx","src/dashkit/CopyField/index.ts"],dependencies:["clsx","tailwind-merge","react-icons"],registryDependencies:["input","iconbutton","toast"]},listtile:{name:"ListTile",files:["src/dashkit/ListTile/ListTile.tsx","src/dashkit/ListTile/ListTile.test.tsx","src/dashkit/ListTile/index.ts"],dependencies:["framer-motion","clsx","tailwind-merge"]}};import F from"fs-extra";import B from"path";import Z from"chalk";import Q from"ora";import v from"fs-extra";import M from"path";var ne="dashkit.json";function S(e){let t=e.trim().replace(/\\/g,"/").replace(/^\.\/+/,"").replace(/\/+$/,"");return t==="."?"":t}function U(e,t="dashkit"){let s=S(e)||S(t)||"dashkit";return(s.split("/").pop()??"").toLowerCase().includes("dashkit")?s:`${s}/dashkit`}async function re(e){let t={componentsDir:S(e.componentsDir),cssDir:S(e.cssDir)};await v.writeJson(M.resolve(process.cwd(),ne),t,{spaces:2})}async function $(){let e=M.resolve(process.cwd(),ne);if(await v.pathExists(e))try{return await v.readJson(e)}catch{return null}return null}async function I(){let e=process.cwd(),t=await v.pathExists(M.resolve(e,"src")),s=await v.pathExists(M.resolve(e,"app"))||await v.pathExists(M.resolve(e,"src","app"));return{hasSrc:t,hasApp:s}}function T(e){let t=e.hasSrc?"src/dashkit":"dashkit";return{components:t,css:t}}async function Y(e=process.cwd()){let t=["src/index.css","src/main.css","src/app.css","src/globals.css","src/app/globals.css","app/globals.css","styles/globals.css","index.css"];for(let s of t){let i=M.resolve(e,s);if(await v.pathExists(i))return i}return null}function X(e,t){let s=M.relative(M.dirname(e),t).replace(/\\/g,"/");return s.startsWith(".")||(s=`./${s}`),s}async function ae(e,t){if(!await v.pathExists(e))return{updated:!1,reason:"main_css_not_found"};let s=await v.readFile(e,"utf8");if(s.includes("dashkit.css"))return{updated:!1,reason:"already_imported"};let i=X(e,t),r=`@import "${i}";`,p=/(@import\s+['"]tailwindcss['"];?)(?:\r?\n|$)/,o;return p.test(s)?o=s.replace(p,`$1 ${r} `):o=`${r} ${s}`,await v.writeFile(e,o,"utf8"),{updated:!0,importPath:i}}import L from"chalk";var Se={success:"[SUCCESS]",warning:"[WARNING]",error:"[ERROR]",info:"[INFO]"},Pe={success:L.green,warning:L.yellow,error:L.red,info:L.blue};function V(e,t="info"){let s=Se[t],i=Pe[t];(t==="error"?console.error:console.log)(i(`${s} ${e}`))}var a={success:e=>V(e,"success"),warning:e=>V(e,"warning"),error:e=>V(e,"error"),info:e=>V(e,"info"),bold:e=>console.log(L.bold(e))};function G(){let e=process.cwd();return F.existsSync(B.resolve(e,"bun.lock"))||F.existsSync(B.resolve(e,"bun.lockb"))?"bun":F.existsSync(B.resolve(e,"pnpm-lock.yaml"))?"pnpm":F.existsSync(B.resolve(e,"yarn.lock"))?"yarn":F.existsSync(B.resolve(e,"package-lock.json"))?"npm":"bun"}async function R(e){let t=B.resolve(process.cwd(),"package.json");if(!await F.pathExists(t))return e;try{let s=await F.readJson(t),i={...s.dependencies,...s.devDependencies};return e.filter(r=>!i[r])}catch{return e}}async function oe(){a.bold(` diff --git a/public/llms-full.txt b/public/llms-full.txt index de5d7ac..ee1b069 100644 --- a/public/llms-full.txt +++ b/public/llms-full.txt @@ -175,6 +175,186 @@ Use the `type="multiple"` prop to allow more than one item to be expanded at the | `className` | `string` | - | Custom styles for the container. | +## BentoGrid + +- Category: Layout & Containers +- Slug: `bento-grid` +- Installation: `bunx carllosnc/dashkit add bento-grid` +- NPM Dependencies: `clsx`, `tailwind-merge`, `class-variance-authority` + +A modular grid layout system for building regular and irregular Bento or Hairline grids while maintaining seamless `1px` shared border coherence across arbitrary column/row spans and responsive breakpoints. + +### Installation + +Add the BentoGrid component to your project using the Dashkit CLI: + +```bash +bunx carllosnc/dashkit add bento-grid +``` + +### Import + +```tsx +import { BentoGrid, BentoGridItem } from '@/dashkit/BentoGrid'; +``` + +### Irregular Hairline Grid + +By default, `BentoGrid` uses `gap="none"` to render a continuous `1px` hairline divider between cells without double borders—even when combining multi-row vertical spans (`rowSpan={2}`) and full-width spans (`colSpan="full"`). + + + + 01 / Ingestion + + Edge Collector + Low-latency telemetry pipelines across 38 regions. + + + + + 02 / Cache + + 99.98% Hit Rate + In-memory distributed read replicas. + + + + + + 03 / Architecture + + + + 1.42M req/s + + Tall vertical cell spanning two rows alongside the 2x2 grid on the left, sharing a single 1px border on all sides. + + + cluster-us-east-primary + + + + 04 / Storage + + Zero-Copy Snapshots + Instant branching for isolated preview environments. + + + + + 05 / Security + + mTLS Enforced + Automated certificate rotation every 24h. + + + + + + 06 / Full-Width Footer + Global Consensus Layer + Spans all 12 columns across the bottom while preserving a crisp 1px top divider. + + + + + +```tsx + + Cell 1 + Cell 2 + + Cell 3 (Tall 2-Row Span) + + Cell 4 + Cell 5 + Cell 6 (Full Width) + +``` + +### Sharp Architectural Wireframe (`rounded="none"`) + +Set `rounded="none"` for a sharp editorial or architectural blueprint layout where every outer corner and inner intersection meets at 90 degrees. + + + + col-span-4 + + + col-span-3 + + + col-span-5 / row-span-2 + + + col-span-4 + + + col-span-3 + + + col-span-full + + + +```tsx + + col-span-4 + col-span-3 + + col-span-5 / row-span-2 + + col-span-4 + col-span-3 + col-span-full + +``` + +### Spaced Bento Cards + +Pass `gap="sm" | "md" | "lg"` when you want detached Bento cards instead of shared hairline borders. + + + + Detached Bento Card (2 cols) + Automatically switches to individual card borders when gap is enabled. + + + Side Card (1 col) + Muted surface variant. + + + +```tsx + + Detached Bento Card + Side Card + +``` + +### BentoGrid Props + +| Property | Type | Default | Description | +| :--- | :--- | :--- | :--- | +| `cols` | `BentoResponsiveValue` | `3` | Number of grid columns. Accepts a direct number (stacks on mobile, applies at md+) or a responsive breakpoint object ({ base, sm, md, lg, xl }). | +| `gap` | `'none' \| 'sm' \| 'md' \| 'lg'` | `'none'` | 'none' enables the seamless 1px hairline border mode. Other values separate items into individual bordered cards. | +| `bordered` | `boolean` | `true` | Whether to render the outer 1px perimeter border in hairline mode. | +| `rounded` | `'none' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'xl'` | Controls the outer corner radius of the grid container. | +| `autoRows` | `string` | - | Sets the CSS grid-auto-rows property (e.g., 'minmax(140px, auto)'). | + +### BentoGridItem Props + +| Property | Type | Default | Description | +| :--- | :--- | :--- | :--- | +| `colSpan` | `BentoResponsiveValue<1..12 \| 'full'>` | `1` | Number of columns the cell spans. Accepts a direct value or a responsive breakpoint object. | +| `rowSpan` | `BentoResponsiveValue` | `1` | Number of rows the cell spans. Accepts a direct value or a responsive breakpoint object. | +| `surface` | `'card' \| 'background' \| 'muted' \| 'transparent'` | `'card'` | Semantic background surface color of the cell. | +| `padding` | `'none' \| 'sm' \| 'md' \| 'lg'` | `'md'` | Internal cell padding ('none' for full-bleed visuals, 'sm' = p-4, 'md' = p-6, 'lg' = p-8). | + + ## Card - Category: Layout & Containers diff --git a/public/llms.txt b/public/llms.txt index 42cf8fb..d3cc0d8 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -87,6 +87,7 @@ Complete list of 55 production-ready components. For full API signatures, props ### Layout & Containers - [Accordion](llms-full.txt#accordion): A vertically stacked list of headers that reveal associated content areas when clicked. +- [BentoGrid](llms-full.txt#bentogrid): A modular grid layout system for building regular and irregular Bento or Hairline grids while maintaining seamless `1px` shared border coherence across arbitrary column/row spans and responsive breakpoints. - [Card](llms-full.txt#card): Dashkit's Card is designed as a **composed wrapper**, providing total layout control through granular sub-components. - [Surface](llms-full.txt#surface): A lightweight, foundational component for creating containers with consistent background variants based on design system states. It provides a clean, borderless surface with no internal padding or margin, serving as a pure visual block. - [Divider](llms-full.txt#divider): A versatile component used to separate sections of content with horizontal or vertical lines. diff --git a/public/registry.json b/public/registry.json index f0037f1..cf24298 100644 --- a/public/registry.json +++ b/public/registry.json @@ -1,6 +1,6 @@ { "name": "Dashkit UI Registry", - "totalComponents": 55, + "totalComponents": 56, "components": { "accordion": { "slug": "accordion", @@ -188,6 +188,31 @@ "export interface BarChartProps {\r\n data: Record[];\r\n series: BarChartSeries[];\r\n height?: number | string;\r\n className?: string;\r\n showGrid?: boolean;\r\n showLabels?: boolean;\r\n showTooltip?: boolean;\r\n animate?: boolean;\r\n barGap?: number;\r\n maxBarWidth?: number;\r\n rounded?: boolean;\r\n texture?: BarChartTexture;\r\n showTrack?: boolean;\r\n}" ] }, + "bento-grid": { + "slug": "bento-grid", + "name": "BentoGrid", + "category": "Layout & Containers", + "description": "A modular grid layout system for building regular and irregular Bento or Hairline grids while maintaining seamless `1px` shared border coherence across arbitrary column/row spans and responsive breakpoints.", + "installCommand": "bunx carllosnc/dashkit add bento-grid", + "files": [ + "src/dashkit/BentoGrid/BentoGrid.tsx", + "src/dashkit/BentoGrid/index.ts" + ], + "dependencies": [ + "clsx", + "tailwind-merge", + "class-variance-authority" + ], + "registryDependencies": [], + "exports": [ + "BentoGrid", + "BentoGridItem" + ], + "propsDefinitions": [ + "export interface BentoGridProps\n extends React.HTMLAttributes,\n VariantProps {\n cols?: BentoResponsiveValue;\n autoRows?: string;\n}", + "export interface BentoGridItemProps\n extends React.HTMLAttributes,\n Omit, 'divided'> {\n colSpan?: BentoResponsiveValue;\n rowSpan?: BentoResponsiveValue;\n}" + ] + }, "breadcrumb": { "slug": "breadcrumb", "name": "Breadcrumb", diff --git a/scripts/generate-llms.ts b/scripts/generate-llms.ts index ddd1853..ac959ed 100644 --- a/scripts/generate-llms.ts +++ b/scripts/generate-llms.ts @@ -20,6 +20,7 @@ export const CATEGORIES: ComponentCategory[] = [ name: 'Layout & Containers', components: [ { name: 'Accordion', slug: 'accordion', mdxFile: 'accordion.mdx' }, + { name: 'BentoGrid', slug: 'bento-grid', mdxFile: 'bento-grid.mdx' }, { name: 'Card', slug: 'card', mdxFile: 'card.mdx' }, { name: 'Surface', slug: 'surface', mdxFile: 'surface.mdx' }, { name: 'Divider', slug: 'divider', mdxFile: 'divider.mdx' }, diff --git a/scripts/registry.ts b/scripts/registry.ts index 98ab12b..8fe47f7 100644 --- a/scripts/registry.ts +++ b/scripts/registry.ts @@ -45,6 +45,15 @@ export const registry: Record = { dependencies: ['clsx', 'tailwind-merge'], registryDependencies: ['badge'], }, + 'bento-grid': { + name: 'BentoGrid', + files: [ + 'src/dashkit/BentoGrid/BentoGrid.tsx', + 'src/dashkit/BentoGrid/BentoGrid.test.tsx', + 'src/dashkit/BentoGrid/index.ts' + ], + dependencies: ['clsx', 'tailwind-merge', 'class-variance-authority'], + }, button: { name: 'Button', files: [ diff --git a/scripts/tests/llms.test.ts b/scripts/tests/llms.test.ts index db314f8..76af71a 100644 --- a/scripts/tests/llms.test.ts +++ b/scripts/tests/llms.test.ts @@ -22,7 +22,7 @@ describe('LLMs Documentation Generator', () => { expect(llmsContent.length).toBeGreaterThan(1000); expect(llmsFullContent.length).toBeGreaterThan(10000); - expect(registryJson.totalComponents).toBeGreaterThanOrEqual(55); + expect(registryJson.totalComponents).toBeGreaterThanOrEqual(56); expect(registryJson.components.button.name).toBe('Button'); expect(Array.isArray(registryJson.components.button.exports)).toBe(true); }); @@ -57,7 +57,7 @@ describe('LLMs Documentation Generator', () => { } } - expect(totalCatalogComponents).toBe(55); + expect(totalCatalogComponents).toBe(56); }); it('should resolve every catalog link anchor in llms.txt to an existing heading in llms-full.txt', () => { @@ -70,7 +70,7 @@ describe('LLMs Documentation Generator', () => { } const linkAnchors = [...llmsContent.matchAll(/\(llms-full\.txt#([^)]+)\)/g)].map((m) => m[1]); - expect(linkAnchors.length).toBe(55); + expect(linkAnchors.length).toBe(56); for (const anchor of linkAnchors) { expect(fullHeadingAnchors.has(anchor), `Broken anchor link: #${anchor}`).toBe(true); diff --git a/src/dashkit/BentoGrid/BentoGrid.test.tsx b/src/dashkit/BentoGrid/BentoGrid.test.tsx new file mode 100644 index 0000000..5a01504 --- /dev/null +++ b/src/dashkit/BentoGrid/BentoGrid.test.tsx @@ -0,0 +1,109 @@ +import * as React from 'react'; +import { render, screen } from '@testing-library/react'; +import { describe, it, expect } from 'vitest'; +import { BentoGrid, BentoGridItem } from './index'; + +describe('BentoGrid', () => { + it('renders grid and items with default hairline border coherence classes', () => { + render( + + Cell 1 + Cell 2 + + ); + + const grid = screen.getByTestId('grid'); + const cell1 = screen.getByText('Cell 1'); + + expect(grid).toHaveAttribute('data-slot', 'bento-grid'); + expect(grid).toHaveClass('grid', 'gap-px', 'bg-border', 'border', 'border-border', 'rounded-xl'); + expect(grid).toHaveClass('grid-cols-1', 'md:grid-cols-3'); + + expect(cell1).toHaveAttribute('data-slot', 'bento-grid-item'); + expect(cell1).toHaveClass('bg-card', 'p-6', 'ring-1', 'ring-border', 'col-span-1', 'row-span-1'); + }); + + it('supports numeric cols, colSpan, and rowSpan with mobile-first responsive defaults', () => { + render( + + + Irregular Cell + + + Footer Cell + + + ); + + const grid = screen.getByTestId('grid'); + const irregular = screen.getByText('Irregular Cell'); + const footer = screen.getByText('Footer Cell'); + + expect(grid).toHaveClass('grid-cols-1', 'md:grid-cols-12'); + expect(irregular).toHaveClass('col-span-full', 'md:col-span-4', 'row-span-1', 'md:row-span-2'); + expect(footer).toHaveClass('col-span-full'); + }); + + it('supports responsive breakpoint objects for cols, colSpan, and rowSpan', () => { + render( + + + Responsive Cell + + + ); + + const grid = screen.getByTestId('grid'); + const cell = screen.getByText('Responsive Cell'); + + expect(grid).toHaveClass('grid-cols-1', 'sm:grid-cols-2', 'md:grid-cols-4', 'lg:grid-cols-12'); + expect(cell).toHaveClass( + 'col-span-1', + 'sm:col-span-2', + 'md:col-span-2', + 'lg:col-span-5', + 'row-span-1', + 'lg:row-span-2' + ); + }); + + it('applies rounded, bordered, gap, and autoRows props correctly', () => { + render( + + + Spaced Cell + + + ); + + const grid = screen.getByTestId('grid'); + const cell = screen.getByText('Spaced Cell'); + + expect(grid).toHaveClass('rounded-none', 'border-0', 'gap-4'); + expect(grid).toHaveStyle({ gridAutoRows: 'minmax(180px, auto)' }); + expect(cell).toHaveClass('bg-muted/60', 'p-4', 'border', 'border-border', 'rounded-xl'); + }); + + it('forwards refs to BentoGrid and BentoGridItem', () => { + const gridRef = React.createRef(); + const itemRef = React.createRef(); + + render( + + Ref Cell + + ); + + expect(gridRef.current).toBeInstanceOf(HTMLDivElement); + expect(itemRef.current).toBeInstanceOf(HTMLDivElement); + }); +}); diff --git a/src/dashkit/BentoGrid/BentoGrid.tsx b/src/dashkit/BentoGrid/BentoGrid.tsx new file mode 100644 index 0000000..106846c --- /dev/null +++ b/src/dashkit/BentoGrid/BentoGrid.tsx @@ -0,0 +1,388 @@ +import * as React from 'react'; +import { cva, type VariantProps } from 'class-variance-authority'; +import { cn } from '../utils/cn'; + +export type BentoBreakpoint = 'base' | 'sm' | 'md' | 'lg' | 'xl'; +export type BentoResponsiveValue = T | Partial>; + +export type BentoCols = 1 | 2 | 3 | 4 | 5 | 6 | 12; +export type BentoColSpan = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'full'; +export type BentoRowSpan = 1 | 2 | 3 | 4 | 5 | 6; +export type BentoGap = 'none' | 'sm' | 'md' | 'lg'; +export type BentoRounded = 'none' | 'sm' | 'md' | 'lg' | 'xl'; +export type BentoSurface = 'card' | 'background' | 'muted' | 'transparent'; +export type BentoPadding = 'none' | 'sm' | 'md' | 'lg'; + +const COLS_MAP: Record> = { + base: { + 1: 'grid-cols-1', + 2: 'grid-cols-2', + 3: 'grid-cols-3', + 4: 'grid-cols-4', + 5: 'grid-cols-5', + 6: 'grid-cols-6', + 12: 'grid-cols-12', + }, + sm: { + 1: 'sm:grid-cols-1', + 2: 'sm:grid-cols-2', + 3: 'sm:grid-cols-3', + 4: 'sm:grid-cols-4', + 5: 'sm:grid-cols-5', + 6: 'sm:grid-cols-6', + 12: 'sm:grid-cols-12', + }, + md: { + 1: 'md:grid-cols-1', + 2: 'md:grid-cols-2', + 3: 'md:grid-cols-3', + 4: 'md:grid-cols-4', + 5: 'md:grid-cols-5', + 6: 'md:grid-cols-6', + 12: 'md:grid-cols-12', + }, + lg: { + 1: 'lg:grid-cols-1', + 2: 'lg:grid-cols-2', + 3: 'lg:grid-cols-3', + 4: 'lg:grid-cols-4', + 5: 'lg:grid-cols-5', + 6: 'lg:grid-cols-6', + 12: 'lg:grid-cols-12', + }, + xl: { + 1: 'xl:grid-cols-1', + 2: 'xl:grid-cols-2', + 3: 'xl:grid-cols-3', + 4: 'xl:grid-cols-4', + 5: 'xl:grid-cols-5', + 6: 'xl:grid-cols-6', + 12: 'xl:grid-cols-12', + }, +}; + +const COL_SPAN_MAP: Record> = { + base: { + 1: 'col-span-1', + 2: 'col-span-2', + 3: 'col-span-3', + 4: 'col-span-4', + 5: 'col-span-5', + 6: 'col-span-6', + 7: 'col-span-7', + 8: 'col-span-8', + 9: 'col-span-9', + 10: 'col-span-10', + 11: 'col-span-11', + 12: 'col-span-12', + full: 'col-span-full', + }, + sm: { + 1: 'sm:col-span-1', + 2: 'sm:col-span-2', + 3: 'sm:col-span-3', + 4: 'sm:col-span-4', + 5: 'sm:col-span-5', + 6: 'sm:col-span-6', + 7: 'sm:col-span-7', + 8: 'sm:col-span-8', + 9: 'sm:col-span-9', + 10: 'sm:col-span-10', + 11: 'sm:col-span-11', + 12: 'sm:col-span-12', + full: 'sm:col-span-full', + }, + md: { + 1: 'md:col-span-1', + 2: 'md:col-span-2', + 3: 'md:col-span-3', + 4: 'md:col-span-4', + 5: 'md:col-span-5', + 6: 'md:col-span-6', + 7: 'md:col-span-7', + 8: 'md:col-span-8', + 9: 'md:col-span-9', + 10: 'md:col-span-10', + 11: 'md:col-span-11', + 12: 'md:col-span-12', + full: 'md:col-span-full', + }, + lg: { + 1: 'lg:col-span-1', + 2: 'lg:col-span-2', + 3: 'lg:col-span-3', + 4: 'lg:col-span-4', + 5: 'lg:col-span-5', + 6: 'lg:col-span-6', + 7: 'lg:col-span-7', + 8: 'lg:col-span-8', + 9: 'lg:col-span-9', + 10: 'lg:col-span-10', + 11: 'lg:col-span-11', + 12: 'lg:col-span-12', + full: 'lg:col-span-full', + }, + xl: { + 1: 'xl:col-span-1', + 2: 'xl:col-span-2', + 3: 'xl:col-span-3', + 4: 'xl:col-span-4', + 5: 'xl:col-span-5', + 6: 'xl:col-span-6', + 7: 'xl:col-span-7', + 8: 'xl:col-span-8', + 9: 'xl:col-span-9', + 10: 'xl:col-span-10', + 11: 'xl:col-span-11', + 12: 'xl:col-span-12', + full: 'xl:col-span-full', + }, +}; + +const ROW_SPAN_MAP: Record> = { + base: { + 1: 'row-span-1', + 2: 'row-span-2', + 3: 'row-span-3', + 4: 'row-span-4', + 5: 'row-span-5', + 6: 'row-span-6', + }, + sm: { + 1: 'sm:row-span-1', + 2: 'sm:row-span-2', + 3: 'sm:row-span-3', + 4: 'sm:row-span-4', + 5: 'sm:row-span-5', + 6: 'sm:row-span-6', + }, + md: { + 1: 'md:row-span-1', + 2: 'md:row-span-2', + 3: 'md:row-span-3', + 4: 'md:row-span-4', + 5: 'md:row-span-5', + 6: 'md:row-span-6', + }, + lg: { + 1: 'lg:row-span-1', + 2: 'lg:row-span-2', + 3: 'lg:row-span-3', + 4: 'lg:row-span-4', + 5: 'lg:row-span-5', + 6: 'lg:row-span-6', + }, + xl: { + 1: 'xl:row-span-1', + 2: 'xl:row-span-2', + 3: 'xl:row-span-3', + 4: 'xl:row-span-4', + 5: 'xl:row-span-5', + 6: 'xl:row-span-6', + }, +}; + +const BREAKPOINT_ORDER: BentoBreakpoint[] = ['base', 'sm', 'md', 'lg', 'xl']; + +function resolveColsClasses(cols: BentoResponsiveValue): string { + if (typeof cols === 'number') { + if (cols === 1) return COLS_MAP.base[1]; + return `${COLS_MAP.base[1]} ${COLS_MAP.md[cols]}`; + } + + return BREAKPOINT_ORDER.map((bp) => { + const val = cols[bp]; + return val !== undefined ? COLS_MAP[bp][val] : ''; + }) + .filter(Boolean) + .join(' '); +} + +function resolveColSpanClasses(colSpan: BentoResponsiveValue): string { + if (typeof colSpan === 'number' || colSpan === 'full') { + if (colSpan === 1) return COL_SPAN_MAP.base[1]; + if (colSpan === 'full') return COL_SPAN_MAP.base.full; + return `${COL_SPAN_MAP.base.full} ${COL_SPAN_MAP.md[colSpan]}`; + } + + return BREAKPOINT_ORDER.map((bp) => { + const val = colSpan[bp]; + return val !== undefined ? COL_SPAN_MAP[bp][val] : ''; + }) + .filter(Boolean) + .join(' '); +} + +function resolveRowSpanClasses(rowSpan: BentoResponsiveValue): string { + if (typeof rowSpan === 'number') { + if (rowSpan === 1) return ROW_SPAN_MAP.base[1]; + return `${ROW_SPAN_MAP.base[1]} ${ROW_SPAN_MAP.md[rowSpan]}`; + } + + return BREAKPOINT_ORDER.map((bp) => { + const val = rowSpan[bp]; + return val !== undefined ? ROW_SPAN_MAP[bp][val] : ''; + }) + .filter(Boolean) + .join(' '); +} + +const bentoGridVariants = cva('grid w-full font-sans', { + variants: { + gap: { + none: 'gap-px bg-border overflow-hidden', + sm: 'gap-2', + md: 'gap-4', + lg: 'gap-6', + }, + bordered: { + true: '', + false: 'border-0', + }, + rounded: { + none: 'rounded-none', + sm: 'rounded-sm', + md: 'rounded-md', + lg: 'rounded-lg', + xl: 'rounded-xl', + }, + }, + compoundVariants: [ + { + gap: 'none', + bordered: true, + className: 'border border-border', + }, + ], + defaultVariants: { + gap: 'none', + bordered: true, + rounded: 'xl', + }, +}); + +const bentoGridItemVariants = cva( + 'relative flex flex-col min-w-0 text-card-foreground transition-colors', + { + variants: { + surface: { + card: 'bg-card text-card-foreground', + background: 'bg-background text-foreground', + muted: 'bg-muted/60 dark:bg-muted/40 text-foreground', + transparent: 'bg-transparent text-foreground', + }, + padding: { + none: 'p-0', + sm: 'p-4', + md: 'p-6', + lg: 'p-8', + }, + divided: { + true: 'ring-1 ring-border', + false: 'border border-border rounded-xl', + }, + }, + defaultVariants: { + surface: 'card', + padding: 'md', + divided: true, + }, + } +); + +interface BentoGridContextValue { + divided: boolean; +} + +const BentoGridContext = React.createContext({ + divided: true, +}); + +export interface BentoGridProps + extends React.HTMLAttributes, + VariantProps { + cols?: BentoResponsiveValue; + autoRows?: string; +} + +export const BentoGrid = React.forwardRef( + function BentoGrid( + { + cols = 3, + gap = 'none', + bordered = true, + rounded = 'xl', + autoRows, + style, + className, + children, + ...props + }, + ref + ) { + const divided = (gap ?? 'none') === 'none'; + const mergedStyle = autoRows ? { gridAutoRows: autoRows, ...style } : style; + + return ( + +
+ {children} +
+
+ ); + } +); + +BentoGrid.displayName = 'BentoGrid'; + +export interface BentoGridItemProps + extends React.HTMLAttributes, + Omit, 'divided'> { + colSpan?: BentoResponsiveValue; + rowSpan?: BentoResponsiveValue; +} + +export const BentoGridItem = React.forwardRef( + function BentoGridItem( + { + colSpan = 1, + rowSpan = 1, + surface = 'card', + padding = 'md', + className, + children, + ...props + }, + ref + ) { + const { divided } = React.useContext(BentoGridContext); + + return ( +
+ {children} +
+ ); + } +); + +BentoGridItem.displayName = 'BentoGridItem'; diff --git a/src/dashkit/BentoGrid/index.ts b/src/dashkit/BentoGrid/index.ts new file mode 100644 index 0000000..cb5f621 --- /dev/null +++ b/src/dashkit/BentoGrid/index.ts @@ -0,0 +1 @@ +export * from './BentoGrid'; diff --git a/src/dashkit/index.ts b/src/dashkit/index.ts index 9fb647f..f78f98a 100644 --- a/src/dashkit/index.ts +++ b/src/dashkit/index.ts @@ -5,6 +5,7 @@ export * from './Avatar'; export * from './Backdrop'; export * from './Badge'; export * from './BarChart'; +export * from './BentoGrid'; export * from './Breadcrumb'; export * from './Button'; export * from './ButtonGroup'; diff --git a/src/layouts/DocsLayout.tsx b/src/layouts/DocsLayout.tsx index 724a283..1b69967 100644 --- a/src/layouts/DocsLayout.tsx +++ b/src/layouts/DocsLayout.tsx @@ -35,6 +35,7 @@ const navItems: SidebarSection[] = [ { to: '/docs/avatar', label: 'Avatar', icon: }, { to: '/docs/backdrop', label: 'Backdrop', icon: }, { to: '/docs/badge', label: 'Badge', icon: }, + { to: '/docs/bento-grid', label: 'Bento Grid', icon: }, { to: '/docs/breadcrumb', label: 'Breadcrumb', icon: }, { to: '/docs/button', label: 'Button', icon: }, { to: '/docs/button-group', label: 'Button Group', icon: }, diff --git a/src/layouts/MdxWrapper.tsx b/src/layouts/MdxWrapper.tsx index c1bb1d1..a5d28c2 100644 --- a/src/layouts/MdxWrapper.tsx +++ b/src/layouts/MdxWrapper.tsx @@ -30,6 +30,7 @@ import { Sidebar, SidebarHeader, SidebarFooter, SidebarSection, SidebarItem } fr import { ImageExpander } from '../dashkit/ImageExpander/ImageExpander'; import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '../dashkit/Accordion'; import { Badge, FloatBadge } from '../dashkit/Badge'; +import { BentoGrid, BentoGridItem } from '../dashkit/BentoGrid'; import { Skeleton } from '../dashkit/Skeleton/Skeleton'; import { Spinner } from '../dashkit/Spinner/Spinner'; import { Navbar } from '../dashkit/Navbar'; @@ -238,6 +239,8 @@ const components: Record = { NavigationMenuLink, NavigationMenuViewport, StatsCard, + BentoGrid, + BentoGridItem, HiOutlineChartBarSquare, HiOutlineTicket, Preview: ({ children }: { children: ReactNode }) => ( diff --git a/src/main.tsx b/src/main.tsx index 5780494..2923afb 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -22,6 +22,7 @@ import { BackdropDocs, BadgeDocs, BarChartDocs, + BentoGridDocs, BreadcrumbDocs, ButtonDocs, ButtonGroupDocs, @@ -113,6 +114,7 @@ createRoot(document.getElementById('root')!).render( } /> } /> } /> + } /> } /> } /> } /> diff --git a/src/pages/bento-grid.mdx b/src/pages/bento-grid.mdx new file mode 100644 index 0000000..57eabd1 --- /dev/null +++ b/src/pages/bento-grid.mdx @@ -0,0 +1,239 @@ +import { BentoGrid, BentoGridItem } from '../dashkit/BentoGrid'; +import { Badge } from '../dashkit/Badge'; + +# Bento Grid + +A modular grid layout system for building regular and irregular Bento or Hairline grids while maintaining seamless `1px` shared border coherence across arbitrary column/row spans and responsive breakpoints. + +## Installation + +Add the BentoGrid component to your project using the Dashkit CLI: + +```bash +bunx carllosnc/dashkit add bento-grid +``` + +## Import + +```tsx +import { BentoGrid, BentoGridItem } from '@/dashkit/BentoGrid'; +``` + +## Irregular Hairline Grid + +By default, `BentoGrid` uses `gap="none"` to render a continuous `1px` hairline divider between cells without double borders—even when combining multi-row vertical spans (`rowSpan={2}`) and full-width spans (`colSpan="full"`). + +
+ + + 01 / Ingestion +
+

Edge Collector

+

Low-latency telemetry pipelines across 38 regions.

+
+
+ + + 02 / Cache +
+

99.98% Hit Rate

+

In-memory distributed read replicas.

+
+
+ + +
+ 03 / Architecture + +
+
+
1.42M req/s
+

+ Tall vertical cell spanning two rows alongside the 2x2 grid on the left, sharing a single 1px border on all sides. +

+
+ cluster-us-east-primary +
+ + + 04 / Storage +
+

Zero-Copy Snapshots

+

Instant branching for isolated preview environments.

+
+
+ + + 05 / Security +
+

mTLS Enforced

+

Automated certificate rotation every 24h.

+
+
+ + +
+ 06 / Full-Width Footer +

Global Consensus Layer

+

Spans all 12 columns across the bottom while preserving a crisp 1px top divider.

+
+ +
+
+
+ +```tsx + + Cell 1 + Cell 2 + + Cell 3 (Tall 2-Row Span) + + Cell 4 + Cell 5 + Cell 6 (Full Width) + +``` + +## Sharp Architectural Wireframe (`rounded="none"`) + +Set `rounded="none"` for a sharp editorial or architectural blueprint layout where every outer corner and inner intersection meets at 90 degrees. + +
+ + + col-span-4 + + + col-span-3 + + + col-span-5 / row-span-2 + + + col-span-4 + + + col-span-3 + + + col-span-full + + +
+ +```tsx + + col-span-4 + col-span-3 + + col-span-5 / row-span-2 + + col-span-4 + col-span-3 + col-span-full + +``` + +## Spaced Bento Cards + +Pass `gap="sm" | "md" | "lg"` when you want detached Bento cards instead of shared hairline borders. + +
+ + +

Detached Bento Card (2 cols)

+

Automatically switches to individual card borders when gap is enabled.

+
+ +

Side Card (1 col)

+

Muted surface variant.

+
+
+
+ +```tsx + + Detached Bento Card + Side Card + +``` + +## BentoGrid Props + +", + defaultValue: "3", + description: "Number of grid columns. Accepts a direct number (stacks on mobile, applies at md+) or a responsive breakpoint object ({ base, sm, md, lg, xl })." + }, + { + prop: "gap", + type: "'none' | 'sm' | 'md' | 'lg'", + defaultValue: "'none'", + description: "'none' enables the seamless 1px hairline border mode. Other values separate items into individual bordered cards." + }, + { + prop: "bordered", + type: "boolean", + defaultValue: "true", + description: "Whether to render the outer 1px perimeter border in hairline mode." + }, + { + prop: "rounded", + type: "'none' | 'sm' | 'md' | 'lg' | 'xl'", + defaultValue: "'xl'", + description: "Controls the outer corner radius of the grid container." + }, + { + prop: "autoRows", + type: "string", + defaultValue: "—", + description: "Sets the CSS grid-auto-rows property (e.g., 'minmax(140px, auto)')." + } + ]} +/> + +## BentoGridItem Props + +", + defaultValue: "1", + description: "Number of columns the cell spans. Accepts a direct value or a responsive breakpoint object." + }, + { + prop: "rowSpan", + type: "BentoResponsiveValue<1 | 2 | 3 | 4 | 5 | 6>", + defaultValue: "1", + description: "Number of rows the cell spans. Accepts a direct value or a responsive breakpoint object." + }, + { + prop: "surface", + type: "'card' | 'background' | 'muted' | 'transparent'", + defaultValue: "'card'", + description: "Semantic background surface color of the cell." + }, + { + prop: "padding", + type: "'none' | 'sm' | 'md' | 'lg'", + defaultValue: "'md'", + description: "Internal cell padding ('none' for full-bleed visuals, 'sm' = p-4, 'md' = p-6, 'lg' = p-8)." + } + ]} +/> diff --git a/src/pages/examples/AllComponentsExample.tsx b/src/pages/examples/AllComponentsExample.tsx index e5338f1..be5e825 100644 --- a/src/pages/examples/AllComponentsExample.tsx +++ b/src/pages/examples/AllComponentsExample.tsx @@ -8,6 +8,7 @@ import { IconButton } from '../../dashkit/IconButton/IconButton'; import { Chip } from '../../dashkit/Chip/Chip'; import { Divider } from '../../dashkit/Divider/Divider'; import { Badge, FloatBadge } from '../../dashkit/Badge'; +import { BentoGrid, BentoGridItem } from '../../dashkit/BentoGrid'; import { AnimateNumber } from '../../dashkit/AnimateNumber'; import { CircularProgress } from '../../dashkit/CircularProgress/CircularProgress'; import { Avatar, AvatarGroup } from '../../dashkit/Avatar'; @@ -1644,6 +1645,50 @@ export const AllComponentsExample = () => { + + {/* BENTO GRID */} + + + Bento Grid + Regular and irregular hairline-bordered grids with responsive column and row spans. + + + + + 01 + Ingestion + + + 02 + Cache Layer + + + 03 / Tall Span +
+
99.99%
+

Spans 2 vertical rows with 1px border coherence.

+
+
+ + 04 + Zero-Copy Storage + + + 05 + mTLS Security + + + Global Consensus Footer (Full Span) + + +
+
+