New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@dsbtek/component-library

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@dsbtek/component-library

Advanced components built with shadcn/ui

latest
Source
npmnpm
Version
0.1.6
Version published
Maintainers
1
Created
Source

@dsbtek/component-library

A collection of advanced React components built with TypeScript, Tailwind CSS, and shadcn/ui.

Table of Contents

  • Installation
  • Components
  • Styling
  • Contributing
  • License

Installation

  • Install the package:
npm install @dsbtek/component-library
  • Install peer dependencies:
npm install react@^18 react-dom@^18
  • Set up Tailwind CSS:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
  • Update your tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: ['class'],
  content: [
    './src/**/*.{js,ts,jsx,tsx}',
    './node_modules/@dsbtek/component-library/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      colors: {
        border: 'hsl(var(--border))',
        input: 'hsl(var(--input))',
        ring: 'hsl(var(--ring))',
        background: 'hsl(var(--background))',
        foreground: 'hsl(var(--foreground))',
        primary: {
          DEFAULT: 'hsl(var(--primary))',
          foreground: 'hsl(var(--primary-foreground))',
        },
        secondary: {
          DEFAULT: 'hsl(var(--secondary))',
          foreground: 'hsl(var(--secondary-foreground))',
        },
        destructive: {
          DEFAULT: 'hsl(var(--destructive))',
          foreground: 'hsl(var(--destructive-foreground))',
        },
        muted: {
          DEFAULT: 'hsl(var(--muted))',
          foreground: 'hsl(var(--muted-foreground))',
        },
        accent: {
          DEFAULT: 'hsl(var(--accent))',
          foreground: 'hsl(var(--accent-foreground))',
        },
        popover: {
          DEFAULT: 'hsl(var(--popover))',
          foreground: 'hsl(var(--popover-foreground))',
        },
        card: {
          DEFAULT: 'hsl(var(--card))',
          foreground: 'hsl(var(--card-foreground))',
        },
      },
      borderRadius: {
        lg: 'var(--radius)',
        md: 'calc(var(--radius) - 2px)',
        sm: 'calc(var(--radius) - 4px)',
      },
    },
  },
  plugins: [require('tailwindcss-animate')],
};
  • Add these CSS variables to your global CSS:
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;
    --card: 0 0% 100%;
    --card-foreground: 222.2 84% 4.9%;
    --popover: 0 0% 100%;
    --popover-foreground: 222.2 84% 4.9%;
    --primary: 222.2 47.4% 11.2%;
    --primary-foreground: 210 40% 98%;
    --secondary: 210 40% 96.1%;
    --secondary-foreground: 222.2 47.4% 11.2%;
    --muted: 210 40% 96.1%;
    --muted-foreground: 215.4 16.3% 46.9%;
    --accent: 210 40% 96.1%;
    --accent-foreground: 222.2 47.4% 11.2%;
    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 210 40% 98%;
    --border: 214.3 31.8% 91.4%;
    --input: 214.3 31.8% 91.4%;
    --ring: 222.2 84% 4.9%;
    --radius: 0.5rem;

    /* Sidebar Variables */
    --sidebar-background: 0 0% 98%;
    --sidebar-foreground: 240 5.3% 26.1%;
    --sidebar-primary: 240 5.9% 10%;
    --sidebar-primary-foreground: 0 0% 98%;
    --sidebar-accent: 240 4.8% 95.9%;
    --sidebar-accent-foreground: 240 5.9% 10%;
    --sidebar-border: 220 13% 91%;
    --sidebar-ring: 217.2 91.2% 59.8%;
  }

  .dark {
    --background: 222.2 84% 4.9%;
    --foreground: 210 40% 98%;
    --card: 222.2 84% 4.9%;
    --card-foreground: 210 40% 98%;
    --popover: 222.2 84% 4.9%;
    --popover-foreground: 210 40% 98%;
    --primary: 210 40% 98%;
    --primary-foreground: 222.2 47.4% 11.2%;
    --secondary: 217.2 32.6% 17.5%;
    --secondary-foreground: 210 40% 98%;
    --muted: 217.2 32.6% 17.5%;
    --muted-foreground: 215 20.2% 65.1%;
    --accent: 217.2 32.6% 17.5%;
    --accent-foreground: 210 40% 98%;
    --destructive: 0 62.8% 30.6%;
    --destructive-foreground: 210 40% 98%;
    --border: 217.2 32.6% 17.5%;
    --input: 217.2 32.6% 17.5%;
    --ring: 212.7 26.8% 83.9%;

    /* Sidebar Variables - Dark Mode */
    --sidebar-background: 240 5.9% 10%;
    --sidebar-foreground: 240 4.8% 95.9%;
    --sidebar-primary: 0 0% 98%;
    --sidebar-primary-foreground: 240 5.9% 10%;
    --sidebar-accent: 240 3.7% 15.9%;
    --sidebar-accent-foreground: 240 4.8% 95.9%;
    --sidebar-border: 240 3.7% 15.9%;
    --sidebar-ring: 217.2 91.2% 59.8%;
  }
}

Components

AppSidebar

A flexible, customizable sidebar component with navigation, search, team switching, and user profile features. Built on top of the shadcn/ui Sidebar primitives.

Props

PropTypeDefaultDescription
teamsTeam[][]Array of teams for the team switcher
defaultTeamTeam-Default selected team
onTeamChange(team: Team) => void-Callback when team selection changes
onSearch(query: string) => void-Callback when search query changes
searchPlaceholderstring"Search..."Placeholder text for search input
navItemsNavItem[]RequiredArray of navigation items
navGroupLabelstring"Navigation"Label for the main navigation group
navSecondary{ title: string; url: string; icon: LucideIcon; onClick?: () => void }[][]Array of secondary navigation items
navSecondaryLabelstring-Label for the secondary navigation group
userUser-User data for the profile section
onLogout() => void-Callback when logout is clicked
userMenuItems{ group: string; items: { label: string; icon: React.ComponentType<{ className?: string }>; onClick?: () => void }[] }[]-Custom menu items for user dropdown
isLoadingbooleanfalseLoading state for all sidebar components
variant`"sidebar""floating""inset"`
collapsible`"offcanvas""icon""none"`
side`"left""right"`"left"
defaultOpenbooleantrueDefault open state of the sidebar
openboolean-Controlled open state
onOpenChange(open: boolean) => void-Callback when open state changes
...propsReact.ComponentProps<typeof Sidebar>-All props from shadcn Sidebar component

SidebarProvider

The SidebarProvider is a context provider that manages the state of the sidebar. It's automatically included in the AppSidebar component, but can also be used separately for more advanced use cases.

Props
PropTypeDefaultDescription
childrenReact.ReactNodeRequiredChild components
defaultOpenbooleantrueDefault open state of the sidebar
openboolean-Controlled open state
onOpenChange(open: boolean) => void-Callback when open state changes
useSidebar Hook

The useSidebar hook provides access to the sidebar context. It returns an object with the following properties:

| Property | Type | Description |-----|-----|-----|----- | state | "expanded" | "collapsed" | Current state of the sidebar | open | boolean | Whether the sidebar is open | setOpen | (open: boolean) => void | Function to set the open state | openMobile | boolean | Whether the mobile sidebar is open | setOpenMobile | (open: boolean) => void | Function to set the mobile open state | isMobile | boolean | Whether the current device is mobile | toggleSidebar | () => void | Function to toggle the sidebar open/closed

Example Usage

import { AppSidebar } from '@dsbtek/component-library';
import { Home, Settings, Users, HelpCircle, LogOut } from 'lucide-react';

function SidebarExample() {
  const navItems = [
    {
      title: "Dashboard",
      url: "/dashboard",
      icon: Home,
      isActive: true
    },
    {
      title: "Settings",
      url: "/settings",
      icon: Settings,
      items: [
        { title: "Profile", url: "/settings/profile" },
        { title: "Account", url: "/settings/account" },
        { title: "Preferences", url: "/settings/preferences" }
      ]
    },
    {
      title: "Users",
      url: "/users",
      icon: Users
    }
  ];
  
  const teams = [
    { name: "Acme Inc", logo: Users, plan: "Pro" },
    { name: "Personal", logo: Home, plan: "Free" }
  ];
  
  const secondaryNav = [
    { title: "Help", url: "/help", icon: HelpCircle }
  ];
  
  const user = {
    name: "John Doe",
    email: "john@example.com",
    image: "/avatar.jpg"
  };
  
  return (
    <div className="flex h-screen">
      <AppSidebar
        teams={teams}
        defaultTeam={teams[0]}
        onTeamChange={(team) => console.log("Team changed:", team)}
        onSearch={(query) => console.log("Search:", query)}
        searchPlaceholder="Search..."
        navItems={navItems}
        navGroupLabel="Main Navigation"
        navSecondary={secondaryNav}
        navSecondaryLabel="Support"
        user={user}
        onLogout={() => console.log("Logout clicked")}
        userMenuItems={[
          {
            group: "Account",
            items: [
              {
                label: "Settings",
                icon: Settings,
                onClick: () => console.log("Settings clicked")
              },
              {
                label: "Logout",
                icon: LogOut,
                onClick: () => console.log("Logout clicked")
              }
            ]
          }
        ]}
        defaultOpen={true}
        collapsible="icon"
        variant="sidebar"
      />
      <main className="flex-1 p-6">
        <h1 className="text-2xl font-bold">Dashboard</h1>
        {/* Your page content */}
      </main>
    </div>
  );
}

Using SidebarProvider Separately

For more advanced use cases, you can use the SidebarProvider and sidebar components separately:

import { 
  SidebarProvider, 
  useSidebar,
  NavProjects, 
  NavMain, 
  NavUser 
} from '@dsbtek/component-library';
import { Home, Settings, Users } from 'lucide-react';

function CustomSidebar() {
  const navItems = [
    { title: "Dashboard", url: "/dashboard", icon: Home },
    { title: "Settings", url: "/settings", icon: Settings },
    { title: "Users", url: "/users", icon: Users }
  ];
  
  const projects = [
    { name: "Project A", url: "/projects/a", icon: Home },
    { name: "Project B", url: "/projects/b", icon: Settings }
  ];
  
  const user = {
    name: "John Doe",
    email: "john@example.com"
  };
  
  return (
    <SidebarProvider defaultOpen={true}>
      <div className="flex h-screen">
        <div className="w-64 bg-sidebar text-sidebar-foreground">
          <NavMain items={navItems} groupLabel="Navigation" />
          <NavProjects projects={projects} groupLabel="Projects" />
          <NavUser user={user} onLogout={() => console.log("Logout")} />
        </div>
        <main className="flex-1 p-6">
          <SidebarToggleButton />
          <h1 className="text-2xl font-bold">Dashboard</h1>
          {/* Your page content */}
        </main>
      </div>
    </SidebarProvider>
  );
}

// Custom toggle button using the useSidebar hook
function SidebarToggleButton() {
  const { toggleSidebar, state } = useSidebar();
  
  return (
    <button 
      onClick={toggleSidebar}
      className="p-2 rounded-md bg-primary text-primary-foreground"
    >
      {state === "expanded" ? "Collapse" : "Expand"} Sidebar
    </button>
  );
}

Breadcrumbs

A navigation component that helps users understand their current location within a website's hierarchy.

Props

PropTypeDefaultDescription
segmentsArray<{ label: string; href?: string }>RequiredArray of breadcrumb segments
separatorReact.ReactNode<ChevronRight className="h-4 w-4" />Custom separator between breadcrumb items
classNamestring-Additional CSS classes
onNavigate(href: string) => void-Callback function when a breadcrumb is clicked

Example Usage

import { Breadcrumbs } from '@dsbtek/component-library';

function BreadcrumbsExample() {
  return (
    <Breadcrumbs
      segments={[
        { label: 'Home', href: '/' },
        { label: 'Products', href: '/products' },
        { label: 'Electronics', href: '/products/electronics' },
        { label: 'Smartphones' },
      ]}
      onNavigate={(href) => console.log(`Navigating to: ${href}`)}
    />
  );
}

ColorPicker

A comprehensive color selection component with RGB, HSL support, color schemes, and history.

Props

PropTypeDefaultDescription
colorstring#000000Current color value in hex format
onChange(value: string) => void-Callback function when color changes
classNamestring-Additional CSS classes

Example Usage

import { ColorPicker } from '@dsbtek/component-library';
import { useState } from 'react';

function ColorPickerExample() {
  const [color, setColor] = useState('#3B82F6');
  
  return (
    <ColorPicker 
      color={color} 
      onChange={setColor} 
    />
  );
}

DataTable

A feature-rich table component with sorting, filtering, pagination, and more.

Props

PropTypeDefaultDescription
dataT[]RequiredArray of data items
columnsColumnDef<T>[]RequiredArray of column definitions
meta{ current_page: number; last_page: number; per_page: number; total: number }-Pagination metadata
loadingbooleanfalseLoading state of the table
onPageChange(page: number) => void-Callback when page changes
onPerPageChange(perPage: number) => void-Callback when items per page changes
onSort`(column: string, direction: 'asc''desc'null) => void`
onSearch(value: string) => void-Callback when search value changes
onFilter(filters: AdvancedFilter[]) => void-Callback when filters change
pageSizeOptionsnumber[][10,20,50]Available options for items per page
renderItemActions(row: T) => React.ReactNode-Function to render action buttons for each row
featuresPartial<DataTableFeatures>-Object to enable/disable various table features

Example Usage

import { DataTable } from '@dsbtek/component-library';

function DataTableExample() {
  const columns = [
    { accessorKey: 'name', header: 'Name' },
    { accessorKey: 'email', header: 'Email' },
    { accessorKey: 'role', header: 'Role' },
  ];

  const data = [
    { id: '1', name: 'John Doe', email: 'john@example.com', role: 'Admin' },
    { id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
    // ... more data
  ];

  return (
    <DataTable
      data={data}
      columns={columns}
      features={{
        sorting: true,
        pagination: true,
        search: true,
      }}
      onPageChange={(page) => console.log(`Page changed to ${page}`)}
      onSort={(column, direction) => console.log(`Sorting ${column} ${direction}`)}
    />
  );
}

DateTimePicker

A versatile date and time selection component with support for ranges, time-only, and date-only modes.

Props

PropTypeDefaultDescription
date`DateValueDateRangeundefined
setDate`(date: DateValueDateRangeundefined) => void`
isRangebooleanfalseEnable date range selection
includeTimebooleantrueInclude time selection
dateOnlybooleanfalseShow date picker only
timeOnlybooleanfalseShow time picker only
minDateDate-Minimum selectable date
maxDateDate-Maximum selectable date
disabledDatesDate[]-Array of disabled dates
clearablebooleantrueAllow clearing the selection
disabledbooleanfalseDisable the input

Example Usage

import { DateTimePicker } from '@dsbtek/component-library';
import { useState } from 'react';

function DateTimePickerExample() {
  const [date, setDate] = useState<Date | undefined>(new Date());
  
  return (
    <DateTimePicker 
      date={date} 
      setDate={setDate} 
      includeTime={true}
    />
  );
}

FileInput

A file upload component with drag and drop support, previews, and progress indication.

Props

PropTypeDefaultDescription
valueFileWithPreview[]-Array of selected files
onChange(files: FileWithPreview[]) => voidRequiredCallback when files change
multiplebooleanfalseAllow multiple file selection
acceptRecord<string, string[]>{ "image/*": [".png", ".jpg", ".jpeg", ".gif"], "application/pdf": [".pdf"] }Accepted file types
maxSizenumber2MBMaximum file size in bytes
maxFilesnumber5Maximum number of files
disabledbooleanfalseDisable the input
loadingbooleanfalseShow loading state
progress`numbernumber[]`-
onRemove(file: FileWithPreview) => void-Callback when a file is removed

Example Usage

import { FileInput } from '@dsbtek/component-library';
import { useState } from 'react';

function FileInputExample() {
  const [files, setFiles] = useState([]);
  
  return (
    <FileInput
      value={files}
      onChange={setFiles}
      multiple={true}
      maxSize={5 * 1024 * 1024} // 5MB
    />
  );
}

MultiSelect

A flexible select component that supports single or multiple selection with grouping, search, and responsive behavior.

Props

PropTypeDefaultDescription
optionsOptionType[]RequiredArray of selectable options with format {label: string, value: string, group?: string}
selectedstring[]RequiredArray of selected option values
onChange(value: string[]) => voidRequiredCallback when selection changes
placeholderstring"Select..."Placeholder text
classNamestring-Additional CSS classes for the main component
multiplebooleanfalseAllow multiple selection
onLoadMore() => void-Callback for infinite loading
hasMorebooleanfalseIndicates if more options can be loaded
isDialogbooleanfalseUse dialog instead of drawer on mobile
triggerClassNamestring-Custom class for the trigger button
contentClassNamestring-Custom class for the dropdown content
badgeClassNamestring-Custom class for the selected item badges
commandClassNamestring-Custom class for the command component
commandInputClassNamestring-Custom class for the search input
commandListClassNamestring-Custom class for the options list
commandItemClassNamestring-Custom class for individual option items
commandEmptyClassNamestring-Custom class for the empty state
commandGroupClassNamestring-Custom class for option groups
commandSeparatorClassNamestring-Custom class for group separators
align"start" | "center" | "end""start"Alignment of the dropdown relative to the trigger
sideOffsetnumber5Offset from the trigger
width"auto" | "trigger" | string"trigger"Width of the dropdown content

Example Usage

import { MultiSelect } from '@dsbtek/component-library';
import { useState } from 'react';

function MultiSelectExample() {
  const [selected, setSelected] = useState(['react']);

  const options = [
    { label: 'React', value: 'react', group: 'Frontend' },
    { label: 'Vue', value: 'vue', group: 'Frontend' },
    { label: 'Angular', value: 'angular', group: 'Frontend' },
    { label: 'Node.js', value: 'nodejs', group: 'Backend' },
    { label: 'Express', value: 'express', group: 'Backend' },
  ];

  return (
          <MultiSelect
                  options={options}
                  selected={selected}
                  onChange={setSelected}
                  placeholder="Select technologies..."
                  multiple={true}
                  className="w-[350px]"
                  badgeClassName="bg-blue-100 text-blue-800"
          />
  );
}

MultiStepper

A comprehensive multi-step form component with navigation, validation, and customizable steps.

Props

PropTypeDefaultDescription
contextReact.Context<UseMultiStepFormTypeOptions<T>>RequiredContext created with buildMultiStepForm
previousLabelstring"Previous"Label for the previous button
nextLabelstring"Next"Label for the next button
endStepLabelstring"Submit"Label for the submit button
showNavbarbooleantrueShow the step navigation bar
showButtonsbooleantrueShow the navigation buttons
isLoadingbooleanfalseLoading state for the submit button
classNamestring""Additional CSS classes
debugbooleanfalseShow debug information

Utility Functions

FunctionDescription
buildMultiStepFormCreates a context and provider for a multi-step form
useMultiStepFormHook for accessing multi-step form functionality

Example Usage

import {
  buildMultiStepForm,
  useMultiStepForm,
  Form
} from '@dsbtek/component-library';
import { z } from 'zod';
import { useForm, FormProvider, useFormContext } from 'react-hook-form';
import {
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormMessage
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { PasswordInput } from '@dsbtek/component-library';
import { MultiSelect } from '@dsbtek/component-library';
import { FileInput } from '@dsbtek/component-library';

// Define your form schema
export const signupSchema = z.object({
  name: z.string().min(2, "Name must be at least 2 characters"),
  email: z.string().email("Please enter a valid email"),
  phone: z.string().min(10, "Please enter a valid phone number"),
  password: z.string().min(8, "Password must be at least 8 characters"),
  password_confirmation: z.string(),
  roles: z.array(z.string()),
  permissions: z.array(z.string()),
  image: z.any().optional(),
}).refine((data) => data.password === data.password_confirmation, {
  message: "Passwords do not match",
  path: ["password_confirmation"],
});

// Step 1: Basic Information
export function Step1() {
  const { control } = useFormContext();

  return (
          <>
            <FormField
                    control={control}
                    name="name"
                    render={({ field }) => (
                            <FormItem>
                              <FormLabel>Name</FormLabel>
                              <FormControl>
                                <Input placeholder="Enter your name" {...field} />
                              </FormControl>
                              <FormMessage />
                            </FormItem>
                    )}
            />
            <FormField
                    control={control}
                    name="email"
                    render={({ field }) => (
                            <FormItem>
                              <FormLabel>Email</FormLabel>
                              <FormControl>
                                <Input placeholder="Enter your email" {...field} />
                              </FormControl>
                              <FormMessage />
                            </FormItem>
                    )}
            />
            <FormField
                    control={control}
                    name="phone"
                    render={({ field }) => (
                            <FormItem>
                              <FormLabel>Phone</FormLabel>
                              <FormControl>
                                <Input placeholder="Enter your phone number" {...field} />
                              </FormControl>
                              <FormMessage />
                            </FormItem>
                    )}
            />
          </>
  );
}

// Step 2: Security
export function Step2() {
  const { control } = useFormContext();

  return (
          <>
            <FormField
                    control={control}
                    name="password"
                    render={({ field }) => (
                            <FormItem>
                              <FormLabel>Password</FormLabel>
                              <FormControl>
                                <PasswordInput placeholder="Enter your password" {...field} />
                              </FormControl>
                              <FormMessage />
                            </FormItem>
                    )}
            />
            <FormField
                    control={control}
                    name="password_confirmation"
                    render={({ field }) => (
                            <FormItem>
                              <FormLabel>Confirm Password</FormLabel>
                              <FormControl>
                                <PasswordInput placeholder="Confirm your password" {...field} />
                              </FormControl>
                              <FormMessage />
                            </FormItem>
                    )}
            />
          </>
  );
}

// Step 3: Roles & Permissions
export function Step3() {
  const { control } = useFormContext();

  const roleOptions = [
    { label: 'Admin', value: 'admin' },
    { label: 'User', value: 'user' },
    { label: 'Editor', value: 'editor' },
  ];

  const permissionOptions = [
    { label: 'Create', value: 'create', group: 'Content' },
    { label: 'Edit', value: 'edit', group: 'Content' },
    { label: 'Delete', value: 'delete', group: 'Content' },
    { label: 'View Users', value: 'view_users', group: 'Users' },
    { label: 'Manage Users', value: 'manage_users', group: 'Users' },
  ];

  return (
          <>
            <FormField
                    control={control}
                    name="roles"
                    render={({ field }) => (
                            <FormItem>
                              <FormLabel>Roles</FormLabel>
                              <FormControl>
                                <MultiSelect
                                        options={roleOptions}
                                        selected={field.value || []}
                                        onChange={field.onChange}
                                        placeholder="Select roles"
                                        multiple={true}
                                />
                              </FormControl>
                              <FormMessage />
                            </FormItem>
                    )}
            />
            <FormField
                    control={control}
                    name="permissions"
                    render={({ field }) => (
                            <FormItem>
                              <FormLabel>Permissions</FormLabel>
                              <FormControl>
                                <MultiSelect
                                        options={permissionOptions}
                                        selected={field.value || []}
                                        onChange={field.onChange}
                                        placeholder="Select permissions"
                                        multiple={true}
                                />
                              </FormControl>
                              <FormMessage />
                            </FormItem>
                    )}
            />
          </>
  );
}

// Step 4: Profile Picture
export function Step4() {
  const { control } = useFormContext();

  return (
          <FormField
                  control={control}
                  name="image"
                  render={({ field }) => (
                          <FormItem>
                            <FormLabel>Profile Picture</FormLabel>
                            <FormControl>
                              <FileInput
                                      value={field.value || []}
                                      onChange={field.onChange}
                                      accept={{ "image/*": [".png", ".jpg", ".jpeg"] }}
                                      maxSize={2 * 1024 * 1024} // 2MB
                              />
                            </FormControl>
                            <FormMessage />
                          </FormItem>
                  )}
          />
  );
}
//Sign Up Step Config
import React from 'react'
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle
} from '@/components/ui/card'
import { Social } from '@/components/auth/social'
import { BackButton } from '@/components/auth/back-button'
import { cn } from "@/lib/utils"

interface AuthWrapperProps {
  children: React.ReactNode
  headerTitle: string
  headerDescription: string
  backButtonLabel: string
  backLinkLabel: string
  backButtonHref: string
  enableSocial: boolean
  onSocialLogin: (provider: string) => void
  showGoogle?: boolean
  showFacebook?: boolean
  showApple?: boolean
  showGithub?: boolean
  showSlack?: boolean
  showX?: boolean
  showLinkedin?: boolean
  showMicrosoft?: boolean
  className?: string
  contentClassName?: string
  width?: string;
}

export function AuthWrapper({
                              children,
                              headerTitle,
                              headerDescription,
                              backButtonLabel,
                              backLinkLabel,
                              backButtonHref,
                              enableSocial,
                              onSocialLogin,
                              className,
                              contentClassName,
                              width = "w-[350px]",
                              ...socialProps
                            }: AuthWrapperProps) {
  return (
          <Card className={cn(width, className)}>
            <CardHeader className="space-y-1">
              <CardTitle>{headerTitle}</CardTitle>
              <CardDescription>{headerDescription}</CardDescription>
            </CardHeader>
            <CardContent className={cn(contentClassName)}>{children}</CardContent>
            <CardFooter className="flex flex-col items-center gap-4">
              {enableSocial && (
                      <Social onSocialLogin={onSocialLogin} {...socialProps} />
              )}
              <BackButton
                      backLinkLabel={backLinkLabel}
                      label={backButtonLabel}
                      href={backButtonHref}
              />
            </CardFooter>
          </Card>
  )
}
// Use the Sign Up Dorm
"use client";
import {containerSignUpForm as container} from "@/constants/framer-motion";
import {useMultiStepForm, MultiStepNavbar, MultiStepNavButtons} from "@smartflowssbu/component-pack";
import {motion} from "framer-motion";
import MultiStepForm from "@/app/(auth)/signup/_components/multi-step-form";
import {SignUpFormContext} from "@/app/(auth)/signup/_components/signup-step-config";

export default function SignUpForm() {
  const {CurrentForm} = useMultiStepForm(SignUpFormContext);

  return (
          <MultiStepForm title="Sign up" description="Create an account to get started">
            <MultiStepNavbar context={SignUpFormContext}/>
            <div className="flex-1">
              <motion.div variants={container} className="space-y-6" initial="hidden" animate="visible" exit="exit">
                <CurrentForm/>
              </motion.div>
              <MultiStepNavButtons
                      context={SignUpFormContext}
                      previousLabel="Previous"
                      nextLabel="Next"
                      endStepLabel="Submit"
              />
            </div>
          </MultiStepForm>
  );
};
//Use the Multi Step Form
"use client";
import {containerMultiStepForm as container} from "@/constants/framer-motion";
import {useMultiStepForm} from "@/hooks/multi-step-form";
import {motion} from "framer-motion";
import {Form} from "@/components/ui/form";
import React, {PropsWithChildren} from "react";
import {SignUpFormContext} from "@/app/(auth)/signup/_components/signup-step-config";
import {AuthWrapper} from "@/components/auth/auth-wrapper";

interface Props extends PropsWithChildren {
  title: string;
  description: string;
}

const MultiStepForm = ({title, description, children}: Props) => {
  const {form, onSubmit, onErrors} = useMultiStepForm(SignUpFormContext);

  function handleSocialLogin(provider: string) {
    // Implement social signin logic here
    console.log(Social login with ${provider})
  }

  return (
          <Form {...form}>
            <form onSubmit={form?.handleSubmit(onSubmit, onErrors)}>
              <motion.div
                      variants={container}
                      className="flex flex-col gap-2"
                      initial="hidden"
                      animate="visible"
                      exit="exit"
              >
                <AuthWrapper
                        headerTitle={title}
                        headerDescription={description}
                        backButtonLabel='Already have an account?'
                        backLinkLabel='Sign in'
                        backButtonHref='/signin'
                        enableSocial={false}
                        onSocialLogin={handleSocialLogin}
                        width='w-[500px]'
                        contentClassName='flex flex-col sm:flex-row gap-2 p-2 m-2'>
                  {children}
                </AuthWrapper>
              </motion.div>
            </form>
          </Form>
  );
};

export default MultiStepForm;
//Use Auth Wrapper
import React from 'react'
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle
} from '@/components/ui/card'
import { Social } from '@/components/auth/social'
import { BackButton } from '@/components/auth/back-button'
import { cn } from "@/lib/utils"

interface AuthWrapperProps {
  children: React.ReactNode
  headerTitle: string
  headerDescription: string
  backButtonLabel: string
  backLinkLabel: string
  backButtonHref: string
  enableSocial: boolean
  onSocialLogin: (provider: string) => void
  showGoogle?: boolean
  showFacebook?: boolean
  showApple?: boolean
  showGithub?: boolean
  showSlack?: boolean
  showX?: boolean
  showLinkedin?: boolean
  showMicrosoft?: boolean
  className?: string
  contentClassName?: string
  width?: string;
}

export function AuthWrapper({
                              children,
                              headerTitle,
                              headerDescription,
                              backButtonLabel,
                              backLinkLabel,
                              backButtonHref,
                              enableSocial,
                              onSocialLogin,
                              className,
                              contentClassName,
                              width = "w-[350px]",
                              ...socialProps
                            }: AuthWrapperProps) {
  return (
          <Card className={cn(width, className)}>
            <CardHeader className="space-y-1">
              <CardTitle>{headerTitle}</CardTitle>
              <CardDescription>{headerDescription}</CardDescription>
            </CardHeader>
            <CardContent className={cn(contentClassName)}>{children}</CardContent>
            <CardFooter className="flex flex-col items-center gap-4">
              {enableSocial && (
                      <Social onSocialLogin={onSocialLogin} {...socialProps} />
              )}
              <BackButton
                      backLinkLabel={backLinkLabel}
                      label={backButtonLabel}
                      href={backButtonHref}
              />
            </CardFooter>
          </Card>
  )
}
//Multi Ster SignUp Form
"use client";

import {SignUpProvider} from "@/app/(auth)/signup/_components/signup-step-config";
import SignUpForm from "@/app/(auth)/signup/_components/form/signup-form";

export default function MultiStepSignUp () {
  return (
          <SignUpProvider>
            <SignUpForm />
          </SignUpProvider>
  );
};
//back button
import Link from 'next/link'

interface BackButtonProps {
  label: string
  href: string
  backLinkLabel: string
}

export function BackButton({ backLinkLabel, label, href }: BackButtonProps) {
  return (
          <div className="text-sm text-muted-foreground text-center w-full">
            {label}{' '}
            <Link href={href} className="text-primary underline-offset-4 hover:underline">
              {backLinkLabel}
            </Link>
          </div>
  )
}

PasswordInput

A password input component with show/hide functionality.

Props

PropTypeDefaultDescription
classNamestring-Additional CSS classes
showPasswordLabelstring"Show password"Screen reader label for show password button
hidePasswordLabelstring"Hide password"Screen reader label for hide password button
...propsReact.InputHTMLAttributes<HTMLInputElement>-All standard input props

Example Usage

import { PasswordInput } from '@smartflowssbu/component-pack';
import { useState } from 'react';

function PasswordInputExample() {
  const [password, setPassword] = useState('');
  
  return (
    <PasswordInput
      value={password}
      onChange={(e) => setPassword(e.target.value)}
      placeholder="Enter your password"
    />
  );
}

PhoneInput

An international phone number input with country selection and validation.

Props

PropTypeDefaultDescription
valuestring-Phone number value
defaultCountryCountryCode"US"Default country code
...propsReact.ComponentPropsWithoutRef<'input'>-All standard input props

Example Usage

import { PhoneInput, getPhoneData } from '@smartflowssbu/component-pack';
import { useState, useEffect } from 'react';

function PhoneInputExample() {
  const [phone, setPhone] = useState('+1');
  const [phoneData, setPhoneData] = useState(getPhoneData(phone));
  
  useEffect(() => {
    setPhoneData(getPhoneData(phone));
  }, [phone]);
  
  return (
    <PhoneInput
      value={phone}
      onChange={(e) => setPhone(e.target.value)}
      defaultCountry="US"
    />
  );
}

ResponsiveAlertDialog

An alert dialog component that adapts to desktop (modal) and mobile (drawer) views.

Props

PropTypeDefaultDescription
triggerReact.ReactNodeRequiredElement that triggers the dialog
titlestringRequiredDialog title
descriptionstringRequiredDialog description
cancelTextstring"Cancel"Text for the cancel button
confirmTextstring"Continue"Text for the confirm button
onConfirm() => voidRequiredCallback when confirm button is clicked

Example Usage

import { ResponsiveAlertDialog } from '@smartflowssbu/component-pack';
import { Button } from '@smartflowssbu/component-pack';

function AlertDialogExample() {
  const handleDelete = () => {
    console.log('Item deleted');
  };
  
  return (
    <ResponsiveAlertDialog
      trigger={<Button variant="destructive">Delete Item</Button>}
      title="Are you sure?"
      description="This action cannot be undone. This will permanently delete the item."
      cancelText="Cancel"
      confirmText="Delete"
      onConfirm={handleDelete}
    />
  );
}

ResponsiveDialog

A dialog component that adapts to desktop (modal) and mobile (drawer) views.

Props

PropTypeDefaultDescription
triggerReact.ReactNodeRequiredElement that triggers the dialog
titlestringRequiredDialog title
descriptionstringRequiredDialog description
childrenReact.ReactNodeRequiredDialog content

Example Usage

import { ResponsiveDialog } from '@smartflowssbu/component-pack';
import { Button } from '@smartflowssbu/component-pack';

function DialogExample() {
  return (
    <ResponsiveDialog
      trigger={<Button>Open Dialog</Button>}
      title="Edit Profile"
      description="Make changes to your profile here."
    >
      <form className="space-y-4 pt-4">
        <div className="space-y-2">
          <label htmlFor="name">Name</label>
          <input id="name" className="w-full p-2 border rounded" />
        </div>
        <div className="space-y-2">
          <label htmlFor="email">Email</label>
          <input id="email" type="email" className="w-full p-2 border rounded" />
        </div>
        <div className="flex justify-end space-x-2">
          <Button type="button" variant="outline">Cancel</Button>
          <Button type="submit">Save</Button>
        </div>
      </form>
    </ResponsiveDialog>
  );
}

TagInput

A component for adding and managing tags with suggestions and validation.

Props

PropTypeDefaultDescription
placeholderstring"Add tag..."Placeholder text
tagsstring[]RequiredArray of current tags
setTags(tags: string[]) => voidRequiredCallback when tags change
suggestionsstring[][]Array of tag suggestions
maxTagsnumber-Maximum number of tags allowed
disabledbooleanfalseDisable the input
errorstring-Error message to display

Example Usage

import { TagInput } from '@smartflowssbu/component-pack';
import { useState } from 'react';

function TagInputExample() {
  const [tags, setTags] = useState(['react', 'typescript']);
  
  const suggestions = [
    'react', 'vue', 'angular', 'svelte', 'javascript', 
    'typescript', 'node', 'express', 'mongodb'
  ];
  
  return (
    <TagInput
      tags={tags}
      setTags={setTags}
      suggestions={suggestions}
      placeholder="Add technologies..."
    />
  );
}

Styling

All components use Tailwind CSS for styling and can be customized using Tailwind classes. The components also respect the theme variables defined in your CSS.

Custom Styling Example

<Breadcrumbs
  className="text-blue-600 dark:text-blue-400"
  segments={[
    { label: 'Home', href: '/' },
    { label: 'Products', href: '/products' },
    { label: 'Current Page' },
  ]}
/>

<ColorPicker
  className="w-[300px] rounded-lg"
  color="#3B82F6"
  onChange={setColor}
/>

TypeScript Support

All components include full TypeScript support out of the box. Type definitions are automatically available when you import components.

Contributing

Please read our Contributing Guide before submitting a Pull Request.

License

MIT © Smartflowtech Team

FAQs

Package last updated on 15 Feb 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts