🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

zedblock

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zedblock - npm Package Compare versions

Package was removed
Sorry, it seems this package was removed from the registry
Comparing version
0.0.9
to
0.0.11
+10
-26
dist/commands/add.js

@@ -7,31 +7,15 @@ import chalk from "chalk";

const __dirname = path.dirname(__filename);
function toPascalCase(str) {
return str.replace(/(^\w|-\w)/g, (m) => m.replace("-", "").toUpperCase());
}
function toKebabCase(str) {
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
}
const pascalCase = (str) => str.replace(/(^\w|-\w)/g, (match) => match.replace("-", "").toUpperCase());
export async function addComponent(name) {
// Support both kebab-case and PascalCase input
const kebabName = toKebabCase(name); // e.g. animated-tabs
const pascalName = toPascalCase(kebabName); // e.g. AnimatedTabs
const fileName = `${pascalName}.tsx`; // e.g. AnimatedTabs.tsx
// Look for the component in the CLI's components directory
const sourceFile = path.resolve(__dirname, "../../components/ui", pascalName, fileName);
const targetDir = path.resolve(process.cwd(), "components/ui", pascalName);
const targetFile = path.join(targetDir, fileName);
const exists = await fs.pathExists(sourceFile);
if (!exists) {
console.log(chalk.red(`❌ Component '${name}' not found.\nExpected at: ${sourceFile}\nMake sure the component exists in the CLI package.`));
const componentName = pascalCase(name); // animated-tabs -> AnimatedTabs
const source = path.resolve(__dirname, "../../src/components", componentName);
const target = path.resolve(process.cwd(), "components/ui", componentName);
if (!(await fs.pathExists(source))) {
console.log(chalk.red(`❌ Component "${componentName}" not found.`));
return;
}
try {
await fs.ensureDir(targetDir);
await fs.copyFile(sourceFile, targetFile);
console.log(chalk.green(`✅ ${fileName} copied to components/ui/${pascalName}/`));
console.log(chalk.yellow(`👉 Import using: import { ${pascalName} } from "@/components/ui/${pascalName}/${pascalName}";`));
}
catch (error) {
console.error(chalk.red("❌ Error copying component:"), error);
}
await fs.ensureDir(path.dirname(target));
await fs.copy(source, target);
console.log(chalk.green(`✅ Copied ${componentName} to components/ui/${componentName}`));
console.log(chalk.yellow(`👉 Make sure Tailwind is configured if this component uses classes or animations.`));
}
#!/usr/bin/env node
import { Command } from "commander";
import { addComponent } from "./commands/add.js";
import { initProject } from "./commands/init.js";
const program = new Command();
program.name("zedblock").description("ZedBlock UI CLI").version("0.0.1");
program
.name("zedblock")
.description("ZedBlock UI CLI - Add beautiful UI components to your project")
.version("0.0.8");
program
.command("add")
.description("Add a component to your project")
.argument("<component>", "Component name (e.g., animated-tabs)")
.argument("<component>", "Component name")
.action(async (component) => {
await addComponent(component);
});
program
.command("init")
.description("Initialize ZedBlock UI in your project")
.action(async () => {
await initProject();
});
program.parse();
program.parse(process.argv);
{
"name": "zedblock",
"version": "0.0.9",
"version": "0.0.11",
"type": "module",

@@ -9,9 +9,6 @@ "bin": {

"scripts": {
"build": "node build.js && tsc",
"dev": "tsc --watch",
"prepublishOnly": "npm run build"
"build": "tsc"
},
"files": [
"dist",
"components"
"dist"
],

@@ -25,21 +22,4 @@ "dependencies": {

"@types/fs-extra": "^11.0.4",
"@types/node": "^20.0.0",
"typescript": "^5.2.2"
},
"engines": {
"node": ">=18.0.0"
},
"keywords": [
"ui",
"components",
"react",
"tailwind",
"cli"
],
"repository": {
"type": "git",
"url": "your-repo-url"
},
"author": "Your Name",
"license": "MIT"
}
}
import type { Meta, StoryObj } from "@storybook/react";
import { Button } from ".";
const meta: Meta<typeof Button> = {
title: "Components/Button",
component: Button,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Solid: Story = {
args: {
variant: "solid",
children: "Button",
},
};
export const Outline: Story = {
args: {
variant: "outline",
children: "Button",
},
};
export const Ghost: Story = {
args: {
variant: "ghost",
children: "Button",
},
};
import { cn } from "@/utils";
import { cva, VariantProps } from "class-variance-authority";
import { ComponentProps, forwardRef } from "react";
const buttonStyles = cva(
[
"w-full",
"rounded-md",
"font-semibold",
"focus:outline-none",
"disabled:cursor-not-allowed",
],
{
variants: {
variant: {
solid: "",
outline: "border-2",
ghost: "transition-colors duration-300",
},
size: {
sm: "px-4 py-2 text-sm",
md: "px-4 py-2 text-base",
lg: "px-6 py-3 text-lg",
},
colorscheme: {
primary: "text-white",
},
},
compoundVariants: [
{
variant: "solid",
colorscheme: "primary",
className: "bg-primary-500 hover:bg-primary-600",
},
{
variant: "outline",
colorscheme: "primary",
className:
"text-primary-600 border-primary-500 bg-transparent hover:bg-primary-100",
},
{
variant: "ghost",
colorscheme: "primary",
className: "text-primary-600 bg-transparent hover:bg-primary-100",
},
],
defaultVariants: {
variant: "solid",
size: "md",
colorscheme: "primary",
},
}
);
type ButtonProps = ComponentProps<"button"> & VariantProps<typeof buttonStyles>;
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ variant, size, colorscheme, className, ...props }, ref) => {
return (
<button
ref={ref}
className={cn(buttonStyles({ variant, size, colorscheme, className }))}
{...props}
/>
);
}
);
export { Animatedtabs } from "./ui/Animatedtabs/animatedtabs";
import type { Meta, StoryObj } from "@storybook/react";
import { Input } from ".";
const meta: Meta<typeof Input> = {
title: "Components/Input",
component: Input,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Text: Story = {
args: {
type: "text",
placeholder: "Insert text here",
},
};
export const Password: Story = {
args: {
type: "password",
placeholder: "Password",
},
};
export const Number: Story = {
args: {
type: "number",
placeholder: "Number",
},
};
export const Date: Story = {
args: {
type: "date",
placeholder: "Date",
},
};
import { cn } from "@/utils";
import { cva, VariantProps } from "class-variance-authority";
import { ComponentProps, forwardRef } from "react";
const inputStyles = cva([
"w-full",
"border",
"border-gray-200",
"p-2",
"rounded-lg",
"transition-all",
"duration-100",
"outline-none",
"focus:outline-primary-500 ",
"focus:border-transparent",
"placeholder:text-gray-400",
"placeholder:text-sm",
]);
type InputProps = ComponentProps<"input"> & VariantProps<typeof inputStyles>;
export const Input = forwardRef<HTMLInputElement, InputProps>(
({ className, ...props }, ref) => {
return (
<input
ref={ref}
type="text"
autoComplete="off"
className={cn(inputStyles({ className }))}
{...props}
/>
);
}
);
import { ComponentPropsWithRef, forwardRef } from "react";
export type BoxProps = ComponentPropsWithRef<"div">;
export const Box = forwardRef<HTMLDivElement, BoxProps>(({ ...props }, ref) => {
return <div ref={ref} {...props} />;
});
export * from "./Box";
export * from "./Stack";
import type { Meta, StoryObj } from "@storybook/react";
import { Stack } from ".";
import { Box } from "..";
const meta: Meta<typeof Stack> = {
title: "Layout/Stack",
component: Stack,
parameters: {
layout: "centered",
},
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
render: (args) => (
<Stack className="gap-4 p-4 bg-gray-300" {...args}>
<Box className="w-[100px] h-[100px] bg-blue-500" />
<Box className="w-[100px] h-[100px] bg-red-500" />
<Box className="w-[100px] h-[100px] bg-green-500" />
</Stack>
),
};
import { Box, BoxProps } from "@/components";
import { cn } from "@/utils";
type StackProps = BoxProps;
export const Stack = ({ className, ...props }: StackProps) => {
return (
<Box className={cn("flex flex-col items-start", className)} {...props} />
);
};
import type { Meta, StoryObj } from "@storybook/react";
import { Text } from ".";
const meta: Meta<typeof Text> = {
title: "Components/Text",
component: Text,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: {
as: "h1",
children:
"be parts correct potatoes sides donkey extra climate happily freedom relationship tape unit tall hung call cat window steady world front graph particular pick",
},
};
import { cn } from "@/utils";
import {
PolymorphicComponentPropsWithRef,
PolymorphicRef,
} from "@/utils/types";
import { VariantProps, cva } from "class-variance-authority";
import { forwardRef } from "react";
const textStyles = cva("w-full", {
variants: {
emphasis: {
low: "text-gray-600 font-light",
},
size: {
sm: "text-sm",
base: "text-base",
lg: "text-lg",
xl: "text-xl",
"2xl": "text-2xl",
"3xl": "text-3xl",
},
weight: {
thin: "font-thin",
normal: "font-normal",
medium: "font-medium",
semibold: "font-semibold",
bold: "font-bold",
black: "font-black",
},
align: {
left: "text-left",
center: "text-center",
right: "text-right",
},
italic: {
true: "italic",
},
underline: {
true: "underline underline-offset-2",
},
},
defaultVariants: {
size: "base",
align: "left",
},
});
type TextProps<C extends React.ElementType> = PolymorphicComponentPropsWithRef<
C,
VariantProps<typeof textStyles>
>;
type TextComponent = <C extends React.ElementType = "span">(
props: TextProps<C>
) => React.ReactElement | null;
// @ts-expect-error - unexpected typing errors
export const Text: TextComponent = forwardRef(
<C extends React.ElementType = "span">(
{
as,
align,
size,
emphasis,
italic,
underline,
weight,
className,
...props
}: TextProps<C>,
ref?: PolymorphicRef<C>
) => {
const Component = as || "span";
return (
<Component
ref={ref}
className={cn(
textStyles({
size,
weight,
emphasis,
italic,
underline,
align,
className,
})
)}
{...props}
/>
);
}
);
import type { Meta, StoryObj } from "@storybook/react";
import { Animatedtabs, type Tab } from "./animatedtabs";
const meta: Meta<typeof Animatedtabs> = {
title: "Components/AnimatedTabs",
component: Animatedtabs,
parameters: {
layout: "padded",
docs: {
description: {
component:
"A reusable animated tab component with multiple variants and sizes. Built with Framer Motion for smooth animations.",
},
},
},
argTypes: {
variant: {
control: "select",
options: ["default", "pills", "underline", "cards"],
description: "Visual style variant of the tabs",
},
size: {
control: "select",
options: ["sm", "md", "lg"],
description: "Size of the tabs",
},
orientation: {
control: "select",
options: ["horizontal", "vertical"],
description: "Orientation of the tab layout",
},
animated: {
control: "boolean",
description: "Enable/disable animations",
},
onTabChange: {
action: "tab-changed",
description: "Callback fired when tab changes",
},
},
tags: ["autodocs"],
};
export default meta;
type Story = StoryObj<typeof Animatedtabs>;
const sampleTabs: Tab[] = [
{
id: "research",
label: "Research",
content: (
<div className="p-4 rounded-lg bg-muted/50">
<h3 className="mb-2 text-lg font-semibold">Research Phase</h3>
<p className="text-muted-foreground">
Gather information, analyze market trends, and understand user needs.
This phase is crucial for making informed decisions.
</p>
</div>
),
},
{
id: "outline",
label: "Outline",
content: (
<div className="p-4 rounded-lg bg-muted/50">
<h3 className="mb-2 text-lg font-semibold">Project Outline</h3>
<ul className="space-y-1 list-disc list-inside text-muted-foreground">
<li>Define project scope and objectives</li>
<li>Create timeline and milestones</li>
<li>Identify resources and constraints</li>
<li>Plan deliverables and success metrics</li>
</ul>
</div>
),
},
{
id: "script",
label: "Script",
content: (
<div className="p-4 rounded-lg bg-muted/50">
<h3 className="mb-2 text-lg font-semibold">Script Development</h3>
<p className="text-muted-foreground">
Write detailed scripts, create user flows, and document technical
specifications. This ensures smooth execution.
</p>
</div>
),
},
];
const longTabList: Tab[] = [
{
id: "overview",
label: "Overview",
content: <div className="p-4">Overview content</div>,
},
{
id: "features",
label: "Features",
content: <div className="p-4">Features content</div>,
},
{
id: "pricing",
label: "Pricing",
content: <div className="p-4">Pricing content</div>,
},
{
id: "documentation",
label: "Documentation",
content: <div className="p-4">Documentation content</div>,
},
{
id: "support",
label: "Support",
content: <div className="p-4">Support content</div>,
},
{
id: "changelog",
label: "Changelog",
content: <div className="p-4">Changelog content</div>,
},
];
const tabsWithDisabled: Tab[] = [
{
id: "active1",
label: "Active Tab",
content: <div className="p-4">This tab is active</div>,
},
{
id: "active2",
label: "Another Active",
content: <div className="p-4">This tab is also active</div>,
},
{
id: "disabled",
label: "Disabled Tab",
content: <div className="p-4">This content won't show</div>,
disabled: true,
},
{
id: "active3",
label: "Last Active",
content: <div className="p-4">This is the last active tab</div>,
},
];
// Default story
export const Default: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "default",
size: "md",
orientation: "horizontal",
animated: true,
},
};
// Variant stories
export const Pills: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "pills",
size: "md",
orientation: "horizontal",
animated: true,
},
};
export const Underline: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "underline",
size: "md",
orientation: "horizontal",
animated: true,
},
};
export const Cards: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "cards",
size: "md",
orientation: "horizontal",
animated: true,
},
};
// Size stories
export const Small: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "pills",
size: "sm",
orientation: "horizontal",
animated: true,
},
};
export const Large: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "pills",
size: "lg",
orientation: "horizontal",
animated: true,
},
};
// Orientation stories
export const Vertical: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "default",
size: "md",
orientation: "vertical",
animated: true,
},
parameters: {
docs: {
description: {
story:
"Vertical orientation places tabs in a column layout, useful for sidebar navigation.",
},
},
},
};
export const VerticalPills: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "pills",
size: "md",
orientation: "vertical",
animated: true,
},
};
// Special cases
export const WithoutAnimation: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "default",
size: "md",
orientation: "horizontal",
animated: false,
},
parameters: {
docs: {
description: {
story:
"Tabs without animation for better performance or accessibility needs.",
},
},
},
};
export const ManyTabs: Story = {
args: {
tabs: longTabList,
defaultTab: "overview",
variant: "underline",
size: "sm",
orientation: "horizontal",
animated: true,
},
parameters: {
docs: {
description: {
story: "Example with many tabs to test overflow behavior.",
},
},
},
};
export const WithDisabledTabs: Story = {
args: {
tabs: tabsWithDisabled,
defaultTab: "active1",
variant: "pills",
size: "md",
orientation: "horizontal",
animated: true,
},
parameters: {
docs: {
description: {
story: "Tabs with some disabled options that cannot be selected.",
},
},
},
};
export const TabsOnly: Story = {
args: {
tabs: [
{ id: "tab1", label: "Tab 1" },
{ id: "tab2", label: "Tab 2" },
{ id: "tab3", label: "Tab 3" },
],
defaultTab: "tab1",
variant: "underline",
size: "md",
orientation: "horizontal",
animated: true,
},
parameters: {
docs: {
description: {
story:
"Tabs without content panels, useful for navigation-only scenarios.",
},
},
},
};
// Custom styling story
export const CustomStyling: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "pills",
size: "md",
orientation: "horizontal",
animated: true,
className: "bg-slate-100 p-4 rounded-xl",
tabClassName: "font-bold",
contentClassName: "mt-6 p-6 bg-white rounded-lg shadow-sm",
},
parameters: {
docs: {
description: {
story: "Example with custom styling applied via className props.",
},
},
},
};
// Interactive playground
export const Playground: Story = {
args: {
tabs: sampleTabs,
defaultTab: "research",
variant: "default",
size: "md",
orientation: "horizontal",
animated: true,
},
parameters: {
docs: {
description: {
story:
"Interactive playground to test different combinations of props.",
},
},
},
};
"use client";
import { cn } from "@/lib/utils";
import { motion } from "framer-motion";
import * as React from "react";
export interface Tab {
id: string;
label: string;
content?: React.ReactNode;
disabled?: boolean;
}
export interface AnimatedTabsProps {
tabs: Tab[];
defaultTab?: string;
onTabChange?: (tabId: string) => void;
variant?: "default" | "pills" | "underline" | "cards";
size?: "sm" | "md" | "lg";
orientation?: "horizontal" | "vertical";
className?: string;
tabClassName?: string;
contentClassName?: string;
animated?: boolean;
}
const AnimatedTabs = React.forwardRef<HTMLDivElement, AnimatedTabsProps>(
(
{
tabs,
defaultTab,
onTabChange,
variant = "default",
size = "md",
orientation = "horizontal",
className,
tabClassName,
contentClassName,
animated = true,
...props
},
ref
) => {
const [activeTab, setActiveTab] = React.useState(defaultTab || tabs[0]?.id);
const handleTabChange = (tabId: string) => {
const tab = tabs.find((t) => t.id === tabId);
if (tab && !tab.disabled) {
setActiveTab(tabId);
onTabChange?.(tabId);
}
};
const activeTabContent = tabs.find((tab) => tab.id === activeTab)?.content;
const tabListVariants = {
default: "border-b border-muted",
pills: "bg-muted p-1 rounded-lg",
underline: "border-b border-border",
cards: "gap-2",
};
const tabVariants = {
default: {
base: "relative px-4 py-2 text-sm font-medium transition-colors hover:text-foreground disabled:pointer-events-none disabled:opacity-50",
active: "text-foreground",
inactive: "text-muted-foreground",
},
pills: {
base: "relative px-3 py-1.5 text-sm font-medium transition-colors hover:text-foreground disabled:pointer-events-none disabled:opacity-50 rounded-md",
active: "text-foreground",
inactive: "text-muted-foreground",
},
underline: {
base: "relative px-4 py-2 text-sm font-medium transition-colors hover:text-foreground disabled:pointer-events-none disabled:opacity-50",
active: "text-foreground",
inactive: "text-muted-foreground",
},
cards: {
base: "relative px-4 py-2 text-sm font-medium transition-colors hover:text-foreground disabled:pointer-events-none disabled:opacity-50 rounded-lg border",
active: "text-foreground bg-background border-border shadow-sm",
inactive:
"text-muted-foreground border-transparent hover:border-border",
},
};
const sizeVariants = {
sm: "text-xs px-2 py-1",
md: "text-sm px-4 py-2",
lg: "text-base px-6 py-3",
};
const getIndicatorProps = () => {
switch (variant) {
case "pills":
return {
className: "absolute inset-0 bg-background rounded-md shadow-sm",
layoutId: "pill-indicator",
};
case "underline":
return {
className: "absolute bottom-0 left-0 right-0 h-0.5 bg-primary",
layoutId: "underline-indicator",
};
default:
return {
className: "absolute bottom-0 left-0 right-0 h-0.5 bg-primary",
layoutId: "default-indicator",
};
}
};
return (
<div
ref={ref}
className={cn(
"w-full",
orientation === "vertical" && "flex gap-4",
className
)}
{...props}
>
<div
className={cn(
"flex",
orientation === "horizontal" ? "flex-row" : "flex-col",
orientation === "vertical" && "min-w-[200px]",
tabListVariants[variant]
)}
role="tablist"
>
{tabs.map((tab) => (
<button
key={tab.id}
role="tab"
aria-selected={activeTab === tab.id}
aria-controls={`panel-${tab.id}`}
disabled={tab.disabled}
className={cn(
tabVariants[variant].base,
sizeVariants[size],
activeTab === tab.id
? tabVariants[variant].active
: tabVariants[variant].inactive,
tabClassName
)}
onClick={() => handleTabChange(tab.id)}
>
{animated && activeTab === tab.id && variant !== "cards" && (
<motion.div
{...getIndicatorProps()}
transition={{ type: "spring", bounce: 0.2, duration: 0.6 }}
/>
)}
<span className="relative z-10">{tab.label}</span>
</button>
))}
</div>
{activeTabContent && (
<div
className={cn(
"mt-4",
orientation === "vertical" && "mt-0 flex-1",
contentClassName
)}
>
{animated ? (
<motion.div
key={activeTab}
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -10 }}
transition={{ duration: 0.2 }}
role="tabpanel"
id={`panel-${activeTab}`}
>
{activeTabContent}
</motion.div>
) : (
<div role="tabpanel" id={`panel-${activeTab}`}>
{activeTabContent}
</div>
)}
</div>
)}
</div>
);
}
);
AnimatedTabs.displayName = "AnimatedTabs";
export { AnimatedTabs };
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline:
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }
export declare function addComponent(name: string): Promise<void>;
export declare function initProject(): Promise<void>;
#!/usr/bin/env node
export {};