@dsbtek/component-library 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,1400 @@
1
+ # @smartflowssbu/component-pack
2
+
3
+ A collection of advanced React components built with TypeScript, Tailwind CSS, and shadcn/ui.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Installation](#installation)
8
+ - [Components](#components)
9
+ - [AppSidebar](#appsidebar)
10
+ - [Breadcrumbs](#breadcrumbs)
11
+ - [ColorPicker](#colorpicker)
12
+ - [DataTable](#datatable)
13
+ - [DateTimePicker](#datetimepicker)
14
+ - [FileInput](#fileinput)
15
+ - [MultiSelect](#multiselect)
16
+ - [MultiStepper](#multistepper)
17
+ - [PasswordInput](#passwordinput)
18
+ - [PhoneInput](#phoneinput)
19
+ - [ResponsiveAlertDialog](#responsivealertdialog)
20
+ - [ResponsiveDialog](#responsivedialog)
21
+ - [TagInput](#taginput)
22
+ - [Styling](#styling)
23
+ - [Contributing](#contributing)
24
+ - [License](#license)
25
+
26
+ ## Installation
27
+
28
+ 1. Install the package:
29
+
30
+ ```bash
31
+ npm install @smartflowssbu/component-pack
32
+ ````
33
+
34
+ 2. Install peer dependencies:
35
+
36
+
37
+ ```bash
38
+ npm install react@^18 react-dom@^18
39
+ ```
40
+
41
+ 3. Set up Tailwind CSS:
42
+
43
+
44
+ ```bash
45
+ npm install -D tailwindcss postcss autoprefixer
46
+ npx tailwindcss init -p
47
+ ```
48
+
49
+ 4. Update your `tailwind.config.js`:
50
+
51
+
52
+ ```javascript
53
+ /** @type {import('tailwindcss').Config} */
54
+ module.exports = {
55
+ darkMode: ['class'],
56
+ content: [
57
+ './src/**/*.{js,ts,jsx,tsx}',
58
+ './node_modules/@smartflowssbu/component-pack/**/*.{js,ts,jsx,tsx}',
59
+ ],
60
+ theme: {
61
+ extend: {
62
+ colors: {
63
+ border: 'hsl(var(--border))',
64
+ input: 'hsl(var(--input))',
65
+ ring: 'hsl(var(--ring))',
66
+ background: 'hsl(var(--background))',
67
+ foreground: 'hsl(var(--foreground))',
68
+ primary: {
69
+ DEFAULT: 'hsl(var(--primary))',
70
+ foreground: 'hsl(var(--primary-foreground))',
71
+ },
72
+ secondary: {
73
+ DEFAULT: 'hsl(var(--secondary))',
74
+ foreground: 'hsl(var(--secondary-foreground))',
75
+ },
76
+ destructive: {
77
+ DEFAULT: 'hsl(var(--destructive))',
78
+ foreground: 'hsl(var(--destructive-foreground))',
79
+ },
80
+ muted: {
81
+ DEFAULT: 'hsl(var(--muted))',
82
+ foreground: 'hsl(var(--muted-foreground))',
83
+ },
84
+ accent: {
85
+ DEFAULT: 'hsl(var(--accent))',
86
+ foreground: 'hsl(var(--accent-foreground))',
87
+ },
88
+ popover: {
89
+ DEFAULT: 'hsl(var(--popover))',
90
+ foreground: 'hsl(var(--popover-foreground))',
91
+ },
92
+ card: {
93
+ DEFAULT: 'hsl(var(--card))',
94
+ foreground: 'hsl(var(--card-foreground))',
95
+ },
96
+ },
97
+ borderRadius: {
98
+ lg: 'var(--radius)',
99
+ md: 'calc(var(--radius) - 2px)',
100
+ sm: 'calc(var(--radius) - 4px)',
101
+ },
102
+ },
103
+ },
104
+ plugins: [require('tailwindcss-animate')],
105
+ };
106
+ ```
107
+
108
+ 5. Add these CSS variables to your global CSS:
109
+
110
+
111
+ ```css
112
+ @tailwind base;
113
+ @tailwind components;
114
+ @tailwind utilities;
115
+
116
+ @layer base {
117
+ :root {
118
+ --background: 0 0% 100%;
119
+ --foreground: 222.2 84% 4.9%;
120
+ --card: 0 0% 100%;
121
+ --card-foreground: 222.2 84% 4.9%;
122
+ --popover: 0 0% 100%;
123
+ --popover-foreground: 222.2 84% 4.9%;
124
+ --primary: 222.2 47.4% 11.2%;
125
+ --primary-foreground: 210 40% 98%;
126
+ --secondary: 210 40% 96.1%;
127
+ --secondary-foreground: 222.2 47.4% 11.2%;
128
+ --muted: 210 40% 96.1%;
129
+ --muted-foreground: 215.4 16.3% 46.9%;
130
+ --accent: 210 40% 96.1%;
131
+ --accent-foreground: 222.2 47.4% 11.2%;
132
+ --destructive: 0 84.2% 60.2%;
133
+ --destructive-foreground: 210 40% 98%;
134
+ --border: 214.3 31.8% 91.4%;
135
+ --input: 214.3 31.8% 91.4%;
136
+ --ring: 222.2 84% 4.9%;
137
+ --radius: 0.5rem;
138
+
139
+ /* Sidebar Variables */
140
+ --sidebar-background: 0 0% 98%;
141
+ --sidebar-foreground: 240 5.3% 26.1%;
142
+ --sidebar-primary: 240 5.9% 10%;
143
+ --sidebar-primary-foreground: 0 0% 98%;
144
+ --sidebar-accent: 240 4.8% 95.9%;
145
+ --sidebar-accent-foreground: 240 5.9% 10%;
146
+ --sidebar-border: 220 13% 91%;
147
+ --sidebar-ring: 217.2 91.2% 59.8%;
148
+ }
149
+
150
+ .dark {
151
+ --background: 222.2 84% 4.9%;
152
+ --foreground: 210 40% 98%;
153
+ --card: 222.2 84% 4.9%;
154
+ --card-foreground: 210 40% 98%;
155
+ --popover: 222.2 84% 4.9%;
156
+ --popover-foreground: 210 40% 98%;
157
+ --primary: 210 40% 98%;
158
+ --primary-foreground: 222.2 47.4% 11.2%;
159
+ --secondary: 217.2 32.6% 17.5%;
160
+ --secondary-foreground: 210 40% 98%;
161
+ --muted: 217.2 32.6% 17.5%;
162
+ --muted-foreground: 215 20.2% 65.1%;
163
+ --accent: 217.2 32.6% 17.5%;
164
+ --accent-foreground: 210 40% 98%;
165
+ --destructive: 0 62.8% 30.6%;
166
+ --destructive-foreground: 210 40% 98%;
167
+ --border: 217.2 32.6% 17.5%;
168
+ --input: 217.2 32.6% 17.5%;
169
+ --ring: 212.7 26.8% 83.9%;
170
+
171
+ /* Sidebar Variables - Dark Mode */
172
+ --sidebar-background: 240 5.9% 10%;
173
+ --sidebar-foreground: 240 4.8% 95.9%;
174
+ --sidebar-primary: 0 0% 98%;
175
+ --sidebar-primary-foreground: 240 5.9% 10%;
176
+ --sidebar-accent: 240 3.7% 15.9%;
177
+ --sidebar-accent-foreground: 240 4.8% 95.9%;
178
+ --sidebar-border: 240 3.7% 15.9%;
179
+ --sidebar-ring: 217.2 91.2% 59.8%;
180
+ }
181
+ }
182
+ ```
183
+
184
+ ## Components
185
+
186
+ ### AppSidebar
187
+
188
+ A flexible, customizable sidebar component with navigation, search, team switching, and user profile features. Built on top of the shadcn/ui Sidebar primitives.
189
+
190
+ #### Props
191
+
192
+ | Prop | Type | Default | Description
193
+ |-----|-----|-----|-----
194
+ | teams | `Team[]` | `[]` | Array of teams for the team switcher
195
+ | defaultTeam | `Team` | - | Default selected team
196
+ | onTeamChange | `(team: Team) => void` | - | Callback when team selection changes
197
+ | onSearch | `(query: string) => void` | - | Callback when search query changes
198
+ | searchPlaceholder | `string` | `"Search..."` | Placeholder text for search input
199
+ | navItems | `NavItem[]` | Required | Array of navigation items
200
+ | navGroupLabel | `string` | `"Navigation"` | Label for the main navigation group
201
+ | navSecondary | `{ title: string; url: string; icon: LucideIcon; onClick?: () => void }[]` | `[]` | Array of secondary navigation items
202
+ | navSecondaryLabel | `string` | - | Label for the secondary navigation group
203
+ | user | `User` | - | User data for the profile section
204
+ | onLogout | `() => void` | - | Callback when logout is clicked
205
+ | userMenuItems | `{ group: string; items: { label: string; icon: React.ComponentType<{ className?: string }>; onClick?: () => void }[] }[]` | - | Custom menu items for user dropdown
206
+ | isLoading | `boolean` | `false` | Loading state for all sidebar components
207
+ | variant | `"sidebar" | "floating" | "inset"` | `"sidebar"` | The variant of the sidebar
208
+ | collapsible | `"offcanvas" | "icon" | "none"` | `"icon"` | Collapsible state of the sidebar
209
+ | side | `"left" | "right"` | `"left"` | The side of the sidebar
210
+ | defaultOpen | `boolean` | `true` | Default open state of the sidebar
211
+ | open | `boolean` | - | Controlled open state
212
+ | onOpenChange | `(open: boolean) => void` | - | Callback when open state changes
213
+ | ...props | `React.ComponentProps<typeof Sidebar>` | - | All props from shadcn Sidebar component
214
+
215
+
216
+ #### SidebarProvider
217
+
218
+ 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.
219
+
220
+ ##### Props
221
+
222
+ | Prop | Type | Default | Description
223
+ |-----|-----|-----|-----
224
+ | children | `React.ReactNode` | Required | Child components
225
+ | defaultOpen | `boolean` | `true` | Default open state of the sidebar
226
+ | open | `boolean` | - | Controlled open state
227
+ | onOpenChange | `(open: boolean) => void` | - | Callback when open state changes
228
+
229
+
230
+ ##### useSidebar Hook
231
+
232
+ The `useSidebar` hook provides access to the sidebar context. It returns an object with the following properties:
233
+
234
+ | Property | Type | Description
235
+ |-----|-----|-----|-----
236
+ | state | `"expanded" | "collapsed"` | Current state of the sidebar
237
+ | open | `boolean` | Whether the sidebar is open
238
+ | setOpen | `(open: boolean) => void` | Function to set the open state
239
+ | openMobile | `boolean` | Whether the mobile sidebar is open
240
+ | setOpenMobile | `(open: boolean) => void` | Function to set the mobile open state
241
+ | isMobile | `boolean` | Whether the current device is mobile
242
+ | toggleSidebar | `() => void` | Function to toggle the sidebar open/closed
243
+
244
+
245
+ #### Example Usage
246
+
247
+ ```tsx
248
+ import { AppSidebar } from '@smartflowssbu/component-pack';
249
+ import { Home, Settings, Users, HelpCircle, LogOut } from 'lucide-react';
250
+
251
+ function SidebarExample() {
252
+ const navItems = [
253
+ {
254
+ title: "Dashboard",
255
+ url: "/dashboard",
256
+ icon: Home,
257
+ isActive: true
258
+ },
259
+ {
260
+ title: "Settings",
261
+ url: "/settings",
262
+ icon: Settings,
263
+ items: [
264
+ { title: "Profile", url: "/settings/profile" },
265
+ { title: "Account", url: "/settings/account" },
266
+ { title: "Preferences", url: "/settings/preferences" }
267
+ ]
268
+ },
269
+ {
270
+ title: "Users",
271
+ url: "/users",
272
+ icon: Users
273
+ }
274
+ ];
275
+
276
+ const teams = [
277
+ { name: "Acme Inc", logo: Users, plan: "Pro" },
278
+ { name: "Personal", logo: Home, plan: "Free" }
279
+ ];
280
+
281
+ const secondaryNav = [
282
+ { title: "Help", url: "/help", icon: HelpCircle }
283
+ ];
284
+
285
+ const user = {
286
+ name: "John Doe",
287
+ email: "john@example.com",
288
+ image: "/avatar.jpg"
289
+ };
290
+
291
+ return (
292
+ <div className="flex h-screen">
293
+ <AppSidebar
294
+ teams={teams}
295
+ defaultTeam={teams[0]}
296
+ onTeamChange={(team) => console.log("Team changed:", team)}
297
+ onSearch={(query) => console.log("Search:", query)}
298
+ searchPlaceholder="Search..."
299
+ navItems={navItems}
300
+ navGroupLabel="Main Navigation"
301
+ navSecondary={secondaryNav}
302
+ navSecondaryLabel="Support"
303
+ user={user}
304
+ onLogout={() => console.log("Logout clicked")}
305
+ userMenuItems={[
306
+ {
307
+ group: "Account",
308
+ items: [
309
+ {
310
+ label: "Settings",
311
+ icon: Settings,
312
+ onClick: () => console.log("Settings clicked")
313
+ },
314
+ {
315
+ label: "Logout",
316
+ icon: LogOut,
317
+ onClick: () => console.log("Logout clicked")
318
+ }
319
+ ]
320
+ }
321
+ ]}
322
+ defaultOpen={true}
323
+ collapsible="icon"
324
+ variant="sidebar"
325
+ />
326
+ <main className="flex-1 p-6">
327
+ <h1 className="text-2xl font-bold">Dashboard</h1>
328
+ {/* Your page content */}
329
+ </main>
330
+ </div>
331
+ );
332
+ }
333
+ ```
334
+
335
+ #### Using SidebarProvider Separately
336
+
337
+ For more advanced use cases, you can use the `SidebarProvider` and sidebar components separately:
338
+
339
+ ```tsx
340
+ import {
341
+ SidebarProvider,
342
+ useSidebar,
343
+ NavProjects,
344
+ NavMain,
345
+ NavUser
346
+ } from '@smartflowssbu/component-pack';
347
+ import { Home, Settings, Users } from 'lucide-react';
348
+
349
+ function CustomSidebar() {
350
+ const navItems = [
351
+ { title: "Dashboard", url: "/dashboard", icon: Home },
352
+ { title: "Settings", url: "/settings", icon: Settings },
353
+ { title: "Users", url: "/users", icon: Users }
354
+ ];
355
+
356
+ const projects = [
357
+ { name: "Project A", url: "/projects/a", icon: Home },
358
+ { name: "Project B", url: "/projects/b", icon: Settings }
359
+ ];
360
+
361
+ const user = {
362
+ name: "John Doe",
363
+ email: "john@example.com"
364
+ };
365
+
366
+ return (
367
+ <SidebarProvider defaultOpen={true}>
368
+ <div className="flex h-screen">
369
+ <div className="w-64 bg-sidebar text-sidebar-foreground">
370
+ <NavMain items={navItems} groupLabel="Navigation" />
371
+ <NavProjects projects={projects} groupLabel="Projects" />
372
+ <NavUser user={user} onLogout={() => console.log("Logout")} />
373
+ </div>
374
+ <main className="flex-1 p-6">
375
+ <SidebarToggleButton />
376
+ <h1 className="text-2xl font-bold">Dashboard</h1>
377
+ {/* Your page content */}
378
+ </main>
379
+ </div>
380
+ </SidebarProvider>
381
+ );
382
+ }
383
+
384
+ // Custom toggle button using the useSidebar hook
385
+ function SidebarToggleButton() {
386
+ const { toggleSidebar, state } = useSidebar();
387
+
388
+ return (
389
+ <button
390
+ onClick={toggleSidebar}
391
+ className="p-2 rounded-md bg-primary text-primary-foreground"
392
+ >
393
+ {state === "expanded" ? "Collapse" : "Expand"} Sidebar
394
+ </button>
395
+ );
396
+ }
397
+ ```
398
+
399
+ ### Breadcrumbs
400
+
401
+ A navigation component that helps users understand their current location within a website's hierarchy.
402
+
403
+ #### Props
404
+
405
+ | Prop | Type | Default | Description
406
+ |-----|-----|-----|-----
407
+ | segments | `Array<{ label: string; href?: string }>` | Required | Array of breadcrumb segments
408
+ | separator | `React.ReactNode` | `<ChevronRight className="h-4 w-4" />` | Custom separator between breadcrumb items
409
+ | className | `string` | - | Additional CSS classes
410
+ | onNavigate | `(href: string) => void` | - | Callback function when a breadcrumb is clicked
411
+
412
+
413
+ #### Example Usage
414
+
415
+ ```tsx
416
+ import { Breadcrumbs } from '@smartflowssbu/component-pack';
417
+
418
+ function BreadcrumbsExample() {
419
+ return (
420
+ <Breadcrumbs
421
+ segments={[
422
+ { label: 'Home', href: '/' },
423
+ { label: 'Products', href: '/products' },
424
+ { label: 'Electronics', href: '/products/electronics' },
425
+ { label: 'Smartphones' },
426
+ ]}
427
+ onNavigate={(href) => console.log(`Navigating to: ${href}`)}
428
+ />
429
+ );
430
+ }
431
+ ```
432
+
433
+ ### ColorPicker
434
+
435
+ A comprehensive color selection component with RGB, HSL support, color schemes, and history.
436
+
437
+ #### Props
438
+
439
+ | Prop | Type | Default | Description
440
+ |-----|-----|-----|-----
441
+ | color | `string` | `#000000` | Current color value in hex format
442
+ | onChange | `(value: string) => void` | - | Callback function when color changes
443
+ | className | `string` | - | Additional CSS classes
444
+
445
+
446
+ #### Example Usage
447
+
448
+ ```tsx
449
+ import { ColorPicker } from '@smartflowssbu/component-pack';
450
+ import { useState } from 'react';
451
+
452
+ function ColorPickerExample() {
453
+ const [color, setColor] = useState('#3B82F6');
454
+
455
+ return (
456
+ <ColorPicker
457
+ color={color}
458
+ onChange={setColor}
459
+ />
460
+ );
461
+ }
462
+ ```
463
+
464
+ ### DataTable
465
+
466
+ A feature-rich table component with sorting, filtering, pagination, and more.
467
+
468
+ #### Props
469
+
470
+ | Prop | Type | Default | Description
471
+ |-----|-----|-----|-----
472
+ | data | `T[]` | Required | Array of data items
473
+ | columns | `ColumnDef<T>[]` | Required | Array of column definitions
474
+ | meta | `{ current_page: number; last_page: number; per_page: number; total: number }` | - | Pagination metadata
475
+ | loading | `boolean` | `false` | Loading state of the table
476
+ | onPageChange | `(page: number) => void` | - | Callback when page changes
477
+ | onPerPageChange | `(perPage: number) => void` | - | Callback when items per page changes
478
+ | onSort | `(column: string, direction: 'asc' | 'desc' | null) => void` | - | Callback when sorting changes
479
+ | onSearch | `(value: string) => void` | - | Callback when search value changes
480
+ | onFilter | `(filters: AdvancedFilter[]) => void` | - | Callback when filters change
481
+ | pageSizeOptions | `number[]` | `[10,20,50]` | Available options for items per page
482
+ | renderItemActions | `(row: T) => React.ReactNode` | - | Function to render action buttons for each row
483
+ | features | `Partial<DataTableFeatures>` | - | Object to enable/disable various table features
484
+
485
+
486
+ #### Example Usage
487
+
488
+ ```tsx
489
+ import { DataTable } from '@smartflowssbu/component-pack';
490
+
491
+ function DataTableExample() {
492
+ const columns = [
493
+ { accessorKey: 'name', header: 'Name' },
494
+ { accessorKey: 'email', header: 'Email' },
495
+ { accessorKey: 'role', header: 'Role' },
496
+ ];
497
+
498
+ const data = [
499
+ { id: '1', name: 'John Doe', email: 'john@example.com', role: 'Admin' },
500
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
501
+ // ... more data
502
+ ];
503
+
504
+ return (
505
+ <DataTable
506
+ data={data}
507
+ columns={columns}
508
+ features={{
509
+ sorting: true,
510
+ pagination: true,
511
+ search: true,
512
+ }}
513
+ onPageChange={(page) => console.log(`Page changed to ${page}`)}
514
+ onSort={(column, direction) => console.log(`Sorting ${column} ${direction}`)}
515
+ />
516
+ );
517
+ }
518
+ ```
519
+
520
+ ### DateTimePicker
521
+
522
+ A versatile date and time selection component with support for ranges, time-only, and date-only modes.
523
+
524
+ #### Props
525
+
526
+ | Prop | Type | Default | Description
527
+ |-----|-----|-----|-----
528
+ | date | `DateValue | DateRange | undefined | null` | - | Selected date(s)
529
+ | setDate | `(date: DateValue | DateRange | undefined) => void` | Required | Callback function when date changes
530
+ | isRange | `boolean` | `false` | Enable date range selection
531
+ | includeTime | `boolean` | `true` | Include time selection
532
+ | dateOnly | `boolean` | `false` | Show date picker only
533
+ | timeOnly | `boolean` | `false` | Show time picker only
534
+ | minDate | `Date` | - | Minimum selectable date
535
+ | maxDate | `Date` | - | Maximum selectable date
536
+ | disabledDates | `Date[]` | - | Array of disabled dates
537
+ | clearable | `boolean` | `true` | Allow clearing the selection
538
+ | disabled | `boolean` | `false` | Disable the input
539
+
540
+
541
+ #### Example Usage
542
+
543
+ ```tsx
544
+ import { DateTimePicker } from '@smartflowssbu/component-pack';
545
+ import { useState } from 'react';
546
+
547
+ function DateTimePickerExample() {
548
+ const [date, setDate] = useState<Date | undefined>(new Date());
549
+
550
+ return (
551
+ <DateTimePicker
552
+ date={date}
553
+ setDate={setDate}
554
+ includeTime={true}
555
+ />
556
+ );
557
+ }
558
+ ```
559
+
560
+ ### FileInput
561
+
562
+ A file upload component with drag and drop support, previews, and progress indication.
563
+
564
+ #### Props
565
+
566
+ | Prop | Type | Default | Description
567
+ |-----|-----|-----|-----
568
+ | value | `FileWithPreview[]` | - | Array of selected files
569
+ | onChange | `(files: FileWithPreview[]) => void` | Required | Callback when files change
570
+ | multiple | `boolean` | `false` | Allow multiple file selection
571
+ | accept | `Record<string, string[]>` | `{ "image/*": [".png", ".jpg", ".jpeg", ".gif"], "application/pdf": [".pdf"] }` | Accepted file types
572
+ | maxSize | `number` | 2MB | Maximum file size in bytes
573
+ | maxFiles | `number` | 5 | Maximum number of files
574
+ | disabled | `boolean` | `false` | Disable the input
575
+ | loading | `boolean` | `false` | Show loading state
576
+ | progress | `number | number[]` | - | Upload progress percentage
577
+ | onRemove | `(file: FileWithPreview) => void` | - | Callback when a file is removed
578
+
579
+
580
+ #### Example Usage
581
+
582
+ ```tsx
583
+ import { FileInput } from '@smartflowssbu/component-pack';
584
+ import { useState } from 'react';
585
+
586
+ function FileInputExample() {
587
+ const [files, setFiles] = useState([]);
588
+
589
+ return (
590
+ <FileInput
591
+ value={files}
592
+ onChange={setFiles}
593
+ multiple={true}
594
+ maxSize={5 * 1024 * 1024} // 5MB
595
+ />
596
+ );
597
+ }
598
+ ```
599
+
600
+ ### MultiSelect
601
+
602
+ A flexible select component that supports single or multiple selection with grouping, search, and responsive behavior.
603
+
604
+ #### Props
605
+
606
+ | Prop | Type | Default | Description
607
+ |-----|-----|-----|-----
608
+ | options | `OptionType[]` | Required | Array of selectable options with format `{label: string, value: string, group?: string}`
609
+ | selected | `string[]` | Required | Array of selected option values
610
+ | onChange | `(value: string[]) => void` | Required | Callback when selection changes
611
+ | placeholder | `string` | `"Select..."` | Placeholder text
612
+ | className | `string` | - | Additional CSS classes for the main component
613
+ | multiple | `boolean` | `false` | Allow multiple selection
614
+ | onLoadMore | `() => void` | - | Callback for infinite loading
615
+ | hasMore | `boolean` | `false` | Indicates if more options can be loaded
616
+ | isDialog | `boolean` | `false` | Use dialog instead of drawer on mobile
617
+ | triggerClassName | `string` | - | Custom class for the trigger button
618
+ | contentClassName | `string` | - | Custom class for the dropdown content
619
+ | badgeClassName | `string` | - | Custom class for the selected item badges
620
+ | commandClassName | `string` | - | Custom class for the command component
621
+ | commandInputClassName | `string` | - | Custom class for the search input
622
+ | commandListClassName | `string` | - | Custom class for the options list
623
+ | commandItemClassName | `string` | - | Custom class for individual option items
624
+ | commandEmptyClassName | `string` | - | Custom class for the empty state
625
+ | commandGroupClassName | `string` | - | Custom class for option groups
626
+ | commandSeparatorClassName | `string` | - | Custom class for group separators
627
+ | align | `"start" \| "center" \| "end"` | `"start"` | Alignment of the dropdown relative to the trigger
628
+ | sideOffset | `number` | `5` | Offset from the trigger
629
+ | width | `"auto" \| "trigger" \| string` | `"trigger"` | Width of the dropdown content
630
+
631
+ #### Example Usage
632
+
633
+ ```tsx
634
+ import { MultiSelect } from '@smartflowssbu/component-pack';
635
+ import { useState } from 'react';
636
+
637
+ function MultiSelectExample() {
638
+ const [selected, setSelected] = useState(['react']);
639
+
640
+ const options = [
641
+ { label: 'React', value: 'react', group: 'Frontend' },
642
+ { label: 'Vue', value: 'vue', group: 'Frontend' },
643
+ { label: 'Angular', value: 'angular', group: 'Frontend' },
644
+ { label: 'Node.js', value: 'nodejs', group: 'Backend' },
645
+ { label: 'Express', value: 'express', group: 'Backend' },
646
+ ];
647
+
648
+ return (
649
+ <MultiSelect
650
+ options={options}
651
+ selected={selected}
652
+ onChange={setSelected}
653
+ placeholder="Select technologies..."
654
+ multiple={true}
655
+ className="w-[350px]"
656
+ badgeClassName="bg-blue-100 text-blue-800"
657
+ />
658
+ );
659
+ }
660
+ ````
661
+
662
+ ### MultiStepper
663
+
664
+ A comprehensive multi-step form component with navigation, validation, and customizable steps.
665
+
666
+ #### Props
667
+
668
+ | Prop | Type | Default | Description
669
+ |-----|-----|-----|-----
670
+ | context | `React.Context<UseMultiStepFormTypeOptions<T>>` | Required | Context created with buildMultiStepForm
671
+ | previousLabel | `string` | `"Previous"` | Label for the previous button
672
+ | nextLabel | `string` | `"Next"` | Label for the next button
673
+ | endStepLabel | `string` | `"Submit"` | Label for the submit button
674
+ | showNavbar | `boolean` | `true` | Show the step navigation bar
675
+ | showButtons | `boolean` | `true` | Show the navigation buttons
676
+ | isLoading | `boolean` | `false` | Loading state for the submit button
677
+ | className | `string` | `""` | Additional CSS classes
678
+ | debug | `boolean` | `false` | Show debug information
679
+
680
+ #### Utility Functions
681
+
682
+ | Function | Description
683
+ |-----|-----
684
+ | buildMultiStepForm | Creates a context and provider for a multi-step form
685
+ | useMultiStepForm | Hook for accessing multi-step form functionality
686
+
687
+ #### Example Usage
688
+
689
+ ```tsx
690
+ import {
691
+ buildMultiStepForm,
692
+ useMultiStepForm,
693
+ Form
694
+ } from '@smartflowssbu/component-pack';
695
+ import { z } from 'zod';
696
+ import { useForm, FormProvider, useFormContext } from 'react-hook-form';
697
+ import {
698
+ FormField,
699
+ FormItem,
700
+ FormLabel,
701
+ FormControl,
702
+ FormMessage
703
+ } from '@/components/ui/form';
704
+ import { Input } from '@/components/ui/input';
705
+ import { PasswordInput } from '@smartflowssbu/component-pack';
706
+ import { MultiSelect } from '@smartflowssbu/component-pack';
707
+ import { FileInput } from '@smartflowssbu/component-pack';
708
+
709
+ // Define your form schema
710
+ export const signupSchema = z.object({
711
+ name: z.string().min(2, "Name must be at least 2 characters"),
712
+ email: z.string().email("Please enter a valid email"),
713
+ phone: z.string().min(10, "Please enter a valid phone number"),
714
+ password: z.string().min(8, "Password must be at least 8 characters"),
715
+ password_confirmation: z.string(),
716
+ roles: z.array(z.string()),
717
+ permissions: z.array(z.string()),
718
+ image: z.any().optional(),
719
+ }).refine((data) => data.password === data.password_confirmation, {
720
+ message: "Passwords do not match",
721
+ path: ["password_confirmation"],
722
+ });
723
+
724
+ // Step 1: Basic Information
725
+ export function Step1() {
726
+ const { control } = useFormContext();
727
+
728
+ return (
729
+ <>
730
+ <FormField
731
+ control={control}
732
+ name="name"
733
+ render={({ field }) => (
734
+ <FormItem>
735
+ <FormLabel>Name</FormLabel>
736
+ <FormControl>
737
+ <Input placeholder="Enter your name" {...field} />
738
+ </FormControl>
739
+ <FormMessage />
740
+ </FormItem>
741
+ )}
742
+ />
743
+ <FormField
744
+ control={control}
745
+ name="email"
746
+ render={({ field }) => (
747
+ <FormItem>
748
+ <FormLabel>Email</FormLabel>
749
+ <FormControl>
750
+ <Input placeholder="Enter your email" {...field} />
751
+ </FormControl>
752
+ <FormMessage />
753
+ </FormItem>
754
+ )}
755
+ />
756
+ <FormField
757
+ control={control}
758
+ name="phone"
759
+ render={({ field }) => (
760
+ <FormItem>
761
+ <FormLabel>Phone</FormLabel>
762
+ <FormControl>
763
+ <Input placeholder="Enter your phone number" {...field} />
764
+ </FormControl>
765
+ <FormMessage />
766
+ </FormItem>
767
+ )}
768
+ />
769
+ </>
770
+ );
771
+ }
772
+
773
+ // Step 2: Security
774
+ export function Step2() {
775
+ const { control } = useFormContext();
776
+
777
+ return (
778
+ <>
779
+ <FormField
780
+ control={control}
781
+ name="password"
782
+ render={({ field }) => (
783
+ <FormItem>
784
+ <FormLabel>Password</FormLabel>
785
+ <FormControl>
786
+ <PasswordInput placeholder="Enter your password" {...field} />
787
+ </FormControl>
788
+ <FormMessage />
789
+ </FormItem>
790
+ )}
791
+ />
792
+ <FormField
793
+ control={control}
794
+ name="password_confirmation"
795
+ render={({ field }) => (
796
+ <FormItem>
797
+ <FormLabel>Confirm Password</FormLabel>
798
+ <FormControl>
799
+ <PasswordInput placeholder="Confirm your password" {...field} />
800
+ </FormControl>
801
+ <FormMessage />
802
+ </FormItem>
803
+ )}
804
+ />
805
+ </>
806
+ );
807
+ }
808
+
809
+ // Step 3: Roles & Permissions
810
+ export function Step3() {
811
+ const { control } = useFormContext();
812
+
813
+ const roleOptions = [
814
+ { label: 'Admin', value: 'admin' },
815
+ { label: 'User', value: 'user' },
816
+ { label: 'Editor', value: 'editor' },
817
+ ];
818
+
819
+ const permissionOptions = [
820
+ { label: 'Create', value: 'create', group: 'Content' },
821
+ { label: 'Edit', value: 'edit', group: 'Content' },
822
+ { label: 'Delete', value: 'delete', group: 'Content' },
823
+ { label: 'View Users', value: 'view_users', group: 'Users' },
824
+ { label: 'Manage Users', value: 'manage_users', group: 'Users' },
825
+ ];
826
+
827
+ return (
828
+ <>
829
+ <FormField
830
+ control={control}
831
+ name="roles"
832
+ render={({ field }) => (
833
+ <FormItem>
834
+ <FormLabel>Roles</FormLabel>
835
+ <FormControl>
836
+ <MultiSelect
837
+ options={roleOptions}
838
+ selected={field.value || []}
839
+ onChange={field.onChange}
840
+ placeholder="Select roles"
841
+ multiple={true}
842
+ />
843
+ </FormControl>
844
+ <FormMessage />
845
+ </FormItem>
846
+ )}
847
+ />
848
+ <FormField
849
+ control={control}
850
+ name="permissions"
851
+ render={({ field }) => (
852
+ <FormItem>
853
+ <FormLabel>Permissions</FormLabel>
854
+ <FormControl>
855
+ <MultiSelect
856
+ options={permissionOptions}
857
+ selected={field.value || []}
858
+ onChange={field.onChange}
859
+ placeholder="Select permissions"
860
+ multiple={true}
861
+ />
862
+ </FormControl>
863
+ <FormMessage />
864
+ </FormItem>
865
+ )}
866
+ />
867
+ </>
868
+ );
869
+ }
870
+
871
+ // Step 4: Profile Picture
872
+ export function Step4() {
873
+ const { control } = useFormContext();
874
+
875
+ return (
876
+ <FormField
877
+ control={control}
878
+ name="image"
879
+ render={({ field }) => (
880
+ <FormItem>
881
+ <FormLabel>Profile Picture</FormLabel>
882
+ <FormControl>
883
+ <FileInput
884
+ value={field.value || []}
885
+ onChange={field.onChange}
886
+ accept={{ "image/*": [".png", ".jpg", ".jpeg"] }}
887
+ maxSize={2 * 1024 * 1024} // 2MB
888
+ />
889
+ </FormControl>
890
+ <FormMessage />
891
+ </FormItem>
892
+ )}
893
+ />
894
+ );
895
+ }
896
+ ```
897
+
898
+ ```tsx
899
+ //Sign Up Step Config
900
+ import React from 'react'
901
+ import {
902
+ Card,
903
+ CardContent,
904
+ CardDescription,
905
+ CardFooter,
906
+ CardHeader,
907
+ CardTitle
908
+ } from '@/components/ui/card'
909
+ import { Social } from '@/components/auth/social'
910
+ import { BackButton } from '@/components/auth/back-button'
911
+ import { cn } from "@/lib/utils"
912
+
913
+ interface AuthWrapperProps {
914
+ children: React.ReactNode
915
+ headerTitle: string
916
+ headerDescription: string
917
+ backButtonLabel: string
918
+ backLinkLabel: string
919
+ backButtonHref: string
920
+ enableSocial: boolean
921
+ onSocialLogin: (provider: string) => void
922
+ showGoogle?: boolean
923
+ showFacebook?: boolean
924
+ showApple?: boolean
925
+ showGithub?: boolean
926
+ showSlack?: boolean
927
+ showX?: boolean
928
+ showLinkedin?: boolean
929
+ showMicrosoft?: boolean
930
+ className?: string
931
+ contentClassName?: string
932
+ width?: string;
933
+ }
934
+
935
+ export function AuthWrapper({
936
+ children,
937
+ headerTitle,
938
+ headerDescription,
939
+ backButtonLabel,
940
+ backLinkLabel,
941
+ backButtonHref,
942
+ enableSocial,
943
+ onSocialLogin,
944
+ className,
945
+ contentClassName,
946
+ width = "w-[350px]",
947
+ ...socialProps
948
+ }: AuthWrapperProps) {
949
+ return (
950
+ <Card className={cn(width, className)}>
951
+ <CardHeader className="space-y-1">
952
+ <CardTitle>{headerTitle}</CardTitle>
953
+ <CardDescription>{headerDescription}</CardDescription>
954
+ </CardHeader>
955
+ <CardContent className={cn(contentClassName)}>{children}</CardContent>
956
+ <CardFooter className="flex flex-col items-center gap-4">
957
+ {enableSocial && (
958
+ <Social onSocialLogin={onSocialLogin} {...socialProps} />
959
+ )}
960
+ <BackButton
961
+ backLinkLabel={backLinkLabel}
962
+ label={backButtonLabel}
963
+ href={backButtonHref}
964
+ />
965
+ </CardFooter>
966
+ </Card>
967
+ )
968
+ }
969
+ ```
970
+
971
+ ```tsx
972
+ // Use the Sign Up Dorm
973
+ "use client";
974
+ import {containerSignUpForm as container} from "@/constants/framer-motion";
975
+ import {useMultiStepForm, MultiStepNavbar, MultiStepNavButtons} from "@smartflowssbu/component-pack";
976
+ import {motion} from "framer-motion";
977
+ import MultiStepForm from "@/app/(auth)/signup/_components/multi-step-form";
978
+ import {SignUpFormContext} from "@/app/(auth)/signup/_components/signup-step-config";
979
+
980
+ export default function SignUpForm() {
981
+ const {CurrentForm} = useMultiStepForm(SignUpFormContext);
982
+
983
+ return (
984
+ <MultiStepForm title="Sign up" description="Create an account to get started">
985
+ <MultiStepNavbar context={SignUpFormContext}/>
986
+ <div className="flex-1">
987
+ <motion.div variants={container} className="space-y-6" initial="hidden" animate="visible" exit="exit">
988
+ <CurrentForm/>
989
+ </motion.div>
990
+ <MultiStepNavButtons
991
+ context={SignUpFormContext}
992
+ previousLabel="Previous"
993
+ nextLabel="Next"
994
+ endStepLabel="Submit"
995
+ />
996
+ </div>
997
+ </MultiStepForm>
998
+ );
999
+ };
1000
+ ```
1001
+
1002
+ ```tsx
1003
+ //Use the Multi Step Form
1004
+ "use client";
1005
+ import {containerMultiStepForm as container} from "@/constants/framer-motion";
1006
+ import {useMultiStepForm} from "@/hooks/multi-step-form";
1007
+ import {motion} from "framer-motion";
1008
+ import {Form} from "@/components/ui/form";
1009
+ import React, {PropsWithChildren} from "react";
1010
+ import {SignUpFormContext} from "@/app/(auth)/signup/_components/signup-step-config";
1011
+ import {AuthWrapper} from "@/components/auth/auth-wrapper";
1012
+
1013
+ interface Props extends PropsWithChildren {
1014
+ title: string;
1015
+ description: string;
1016
+ }
1017
+
1018
+ const MultiStepForm = ({title, description, children}: Props) => {
1019
+ const {form, onSubmit, onErrors} = useMultiStepForm(SignUpFormContext);
1020
+
1021
+ function handleSocialLogin(provider: string) {
1022
+ // Implement social signin logic here
1023
+ console.log(Social login with ${provider})
1024
+ }
1025
+
1026
+ return (
1027
+ <Form {...form}>
1028
+ <form onSubmit={form?.handleSubmit(onSubmit, onErrors)}>
1029
+ <motion.div
1030
+ variants={container}
1031
+ className="flex flex-col gap-2"
1032
+ initial="hidden"
1033
+ animate="visible"
1034
+ exit="exit"
1035
+ >
1036
+ <AuthWrapper
1037
+ headerTitle={title}
1038
+ headerDescription={description}
1039
+ backButtonLabel='Already have an account?'
1040
+ backLinkLabel='Sign in'
1041
+ backButtonHref='/signin'
1042
+ enableSocial={false}
1043
+ onSocialLogin={handleSocialLogin}
1044
+ width='w-[500px]'
1045
+ contentClassName='flex flex-col sm:flex-row gap-2 p-2 m-2'>
1046
+ {children}
1047
+ </AuthWrapper>
1048
+ </motion.div>
1049
+ </form>
1050
+ </Form>
1051
+ );
1052
+ };
1053
+
1054
+ export default MultiStepForm;
1055
+ ```
1056
+
1057
+ ```tsx
1058
+ //Use Auth Wrapper
1059
+ import React from 'react'
1060
+ import {
1061
+ Card,
1062
+ CardContent,
1063
+ CardDescription,
1064
+ CardFooter,
1065
+ CardHeader,
1066
+ CardTitle
1067
+ } from '@/components/ui/card'
1068
+ import { Social } from '@/components/auth/social'
1069
+ import { BackButton } from '@/components/auth/back-button'
1070
+ import { cn } from "@/lib/utils"
1071
+
1072
+ interface AuthWrapperProps {
1073
+ children: React.ReactNode
1074
+ headerTitle: string
1075
+ headerDescription: string
1076
+ backButtonLabel: string
1077
+ backLinkLabel: string
1078
+ backButtonHref: string
1079
+ enableSocial: boolean
1080
+ onSocialLogin: (provider: string) => void
1081
+ showGoogle?: boolean
1082
+ showFacebook?: boolean
1083
+ showApple?: boolean
1084
+ showGithub?: boolean
1085
+ showSlack?: boolean
1086
+ showX?: boolean
1087
+ showLinkedin?: boolean
1088
+ showMicrosoft?: boolean
1089
+ className?: string
1090
+ contentClassName?: string
1091
+ width?: string;
1092
+ }
1093
+
1094
+ export function AuthWrapper({
1095
+ children,
1096
+ headerTitle,
1097
+ headerDescription,
1098
+ backButtonLabel,
1099
+ backLinkLabel,
1100
+ backButtonHref,
1101
+ enableSocial,
1102
+ onSocialLogin,
1103
+ className,
1104
+ contentClassName,
1105
+ width = "w-[350px]",
1106
+ ...socialProps
1107
+ }: AuthWrapperProps) {
1108
+ return (
1109
+ <Card className={cn(width, className)}>
1110
+ <CardHeader className="space-y-1">
1111
+ <CardTitle>{headerTitle}</CardTitle>
1112
+ <CardDescription>{headerDescription}</CardDescription>
1113
+ </CardHeader>
1114
+ <CardContent className={cn(contentClassName)}>{children}</CardContent>
1115
+ <CardFooter className="flex flex-col items-center gap-4">
1116
+ {enableSocial && (
1117
+ <Social onSocialLogin={onSocialLogin} {...socialProps} />
1118
+ )}
1119
+ <BackButton
1120
+ backLinkLabel={backLinkLabel}
1121
+ label={backButtonLabel}
1122
+ href={backButtonHref}
1123
+ />
1124
+ </CardFooter>
1125
+ </Card>
1126
+ )
1127
+ }
1128
+ ```
1129
+
1130
+ ```tsx
1131
+ //Multi Ster SignUp Form
1132
+ "use client";
1133
+
1134
+ import {SignUpProvider} from "@/app/(auth)/signup/_components/signup-step-config";
1135
+ import SignUpForm from "@/app/(auth)/signup/_components/form/signup-form";
1136
+
1137
+ export default function MultiStepSignUp () {
1138
+ return (
1139
+ <SignUpProvider>
1140
+ <SignUpForm />
1141
+ </SignUpProvider>
1142
+ );
1143
+ };
1144
+ ```
1145
+
1146
+
1147
+ ```tsx
1148
+ //back button
1149
+ import Link from 'next/link'
1150
+
1151
+ interface BackButtonProps {
1152
+ label: string
1153
+ href: string
1154
+ backLinkLabel: string
1155
+ }
1156
+
1157
+ export function BackButton({ backLinkLabel, label, href }: BackButtonProps) {
1158
+ return (
1159
+ <div className="text-sm text-muted-foreground text-center w-full">
1160
+ {label}{' '}
1161
+ <Link href={href} className="text-primary underline-offset-4 hover:underline">
1162
+ {backLinkLabel}
1163
+ </Link>
1164
+ </div>
1165
+ )
1166
+ }
1167
+ ```
1168
+
1169
+ ### PasswordInput
1170
+
1171
+ A password input component with show/hide functionality.
1172
+
1173
+ #### Props
1174
+
1175
+ | Prop | Type | Default | Description
1176
+ |-----|-----|-----|-----
1177
+ | className | `string` | - | Additional CSS classes
1178
+ | showPasswordLabel | `string` | `"Show password"` | Screen reader label for show password button
1179
+ | hidePasswordLabel | `string` | `"Hide password"` | Screen reader label for hide password button
1180
+ | ...props | `React.InputHTMLAttributes<HTMLInputElement>` | - | All standard input props
1181
+
1182
+
1183
+ #### Example Usage
1184
+
1185
+ ```tsx
1186
+ import { PasswordInput } from '@smartflowssbu/component-pack';
1187
+ import { useState } from 'react';
1188
+
1189
+ function PasswordInputExample() {
1190
+ const [password, setPassword] = useState('');
1191
+
1192
+ return (
1193
+ <PasswordInput
1194
+ value={password}
1195
+ onChange={(e) => setPassword(e.target.value)}
1196
+ placeholder="Enter your password"
1197
+ />
1198
+ );
1199
+ }
1200
+ ```
1201
+
1202
+ ### PhoneInput
1203
+
1204
+ An international phone number input with country selection and validation.
1205
+
1206
+ #### Props
1207
+
1208
+ | Prop | Type | Default | Description
1209
+ |-----|-----|-----|-----
1210
+ | value | `string` | - | Phone number value
1211
+ | defaultCountry | `CountryCode` | `"US"` | Default country code
1212
+ | ...props | `React.ComponentPropsWithoutRef<'input'>` | - | All standard input props
1213
+
1214
+
1215
+ #### Example Usage
1216
+
1217
+ ```tsx
1218
+ import { PhoneInput, getPhoneData } from '@smartflowssbu/component-pack';
1219
+ import { useState, useEffect } from 'react';
1220
+
1221
+ function PhoneInputExample() {
1222
+ const [phone, setPhone] = useState('+1');
1223
+ const [phoneData, setPhoneData] = useState(getPhoneData(phone));
1224
+
1225
+ useEffect(() => {
1226
+ setPhoneData(getPhoneData(phone));
1227
+ }, [phone]);
1228
+
1229
+ return (
1230
+ <PhoneInput
1231
+ value={phone}
1232
+ onChange={(e) => setPhone(e.target.value)}
1233
+ defaultCountry="US"
1234
+ />
1235
+ );
1236
+ }
1237
+ ```
1238
+
1239
+ ### ResponsiveAlertDialog
1240
+
1241
+ An alert dialog component that adapts to desktop (modal) and mobile (drawer) views.
1242
+
1243
+ #### Props
1244
+
1245
+ | Prop | Type | Default | Description
1246
+ |-----|-----|-----|-----
1247
+ | trigger | `React.ReactNode` | Required | Element that triggers the dialog
1248
+ | title | `string` | Required | Dialog title
1249
+ | description | `string` | Required | Dialog description
1250
+ | cancelText | `string` | `"Cancel"` | Text for the cancel button
1251
+ | confirmText | `string` | `"Continue"` | Text for the confirm button
1252
+ | onConfirm | `() => void` | Required | Callback when confirm button is clicked
1253
+
1254
+
1255
+ #### Example Usage
1256
+
1257
+ ```tsx
1258
+ import { ResponsiveAlertDialog } from '@smartflowssbu/component-pack';
1259
+ import { Button } from '@smartflowssbu/component-pack';
1260
+
1261
+ function AlertDialogExample() {
1262
+ const handleDelete = () => {
1263
+ console.log('Item deleted');
1264
+ };
1265
+
1266
+ return (
1267
+ <ResponsiveAlertDialog
1268
+ trigger={<Button variant="destructive">Delete Item</Button>}
1269
+ title="Are you sure?"
1270
+ description="This action cannot be undone. This will permanently delete the item."
1271
+ cancelText="Cancel"
1272
+ confirmText="Delete"
1273
+ onConfirm={handleDelete}
1274
+ />
1275
+ );
1276
+ }
1277
+ ```
1278
+
1279
+ ### ResponsiveDialog
1280
+
1281
+ A dialog component that adapts to desktop (modal) and mobile (drawer) views.
1282
+
1283
+ #### Props
1284
+
1285
+ | Prop | Type | Default | Description
1286
+ |-----|-----|-----|-----
1287
+ | trigger | `React.ReactNode` | Required | Element that triggers the dialog
1288
+ | title | `string` | Required | Dialog title
1289
+ | description | `string` | Required | Dialog description
1290
+ | children | `React.ReactNode` | Required | Dialog content
1291
+
1292
+
1293
+ #### Example Usage
1294
+
1295
+ ```tsx
1296
+ import { ResponsiveDialog } from '@smartflowssbu/component-pack';
1297
+ import { Button } from '@smartflowssbu/component-pack';
1298
+
1299
+ function DialogExample() {
1300
+ return (
1301
+ <ResponsiveDialog
1302
+ trigger={<Button>Open Dialog</Button>}
1303
+ title="Edit Profile"
1304
+ description="Make changes to your profile here."
1305
+ >
1306
+ <form className="space-y-4 pt-4">
1307
+ <div className="space-y-2">
1308
+ <label htmlFor="name">Name</label>
1309
+ <input id="name" className="w-full p-2 border rounded" />
1310
+ </div>
1311
+ <div className="space-y-2">
1312
+ <label htmlFor="email">Email</label>
1313
+ <input id="email" type="email" className="w-full p-2 border rounded" />
1314
+ </div>
1315
+ <div className="flex justify-end space-x-2">
1316
+ <Button type="button" variant="outline">Cancel</Button>
1317
+ <Button type="submit">Save</Button>
1318
+ </div>
1319
+ </form>
1320
+ </ResponsiveDialog>
1321
+ );
1322
+ }
1323
+ ```
1324
+
1325
+ ### TagInput
1326
+
1327
+ A component for adding and managing tags with suggestions and validation.
1328
+
1329
+ #### Props
1330
+
1331
+ | Prop | Type | Default | Description
1332
+ |-----|-----|-----|-----
1333
+ | placeholder | `string` | `"Add tag..."` | Placeholder text
1334
+ | tags | `string[]` | Required | Array of current tags
1335
+ | setTags | `(tags: string[]) => void` | Required | Callback when tags change
1336
+ | suggestions | `string[]` | `[]` | Array of tag suggestions
1337
+ | maxTags | `number` | - | Maximum number of tags allowed
1338
+ | disabled | `boolean` | `false` | Disable the input
1339
+ | error | `string` | - | Error message to display
1340
+
1341
+
1342
+ #### Example Usage
1343
+
1344
+ ```tsx
1345
+ import { TagInput } from '@smartflowssbu/component-pack';
1346
+ import { useState } from 'react';
1347
+
1348
+ function TagInputExample() {
1349
+ const [tags, setTags] = useState(['react', 'typescript']);
1350
+
1351
+ const suggestions = [
1352
+ 'react', 'vue', 'angular', 'svelte', 'javascript',
1353
+ 'typescript', 'node', 'express', 'mongodb'
1354
+ ];
1355
+
1356
+ return (
1357
+ <TagInput
1358
+ tags={tags}
1359
+ setTags={setTags}
1360
+ suggestions={suggestions}
1361
+ placeholder="Add technologies..."
1362
+ />
1363
+ );
1364
+ }
1365
+ ```
1366
+
1367
+ ## Styling
1368
+
1369
+ 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.
1370
+
1371
+ ### Custom Styling Example
1372
+
1373
+ ```tsx
1374
+ <Breadcrumbs
1375
+ className="text-blue-600 dark:text-blue-400"
1376
+ segments={[
1377
+ { label: 'Home', href: '/' },
1378
+ { label: 'Products', href: '/products' },
1379
+ { label: 'Current Page' },
1380
+ ]}
1381
+ />
1382
+
1383
+ <ColorPicker
1384
+ className="w-[300px] rounded-lg"
1385
+ color="#3B82F6"
1386
+ onChange={setColor}
1387
+ />
1388
+ ```
1389
+
1390
+ ## TypeScript Support
1391
+
1392
+ All components include full TypeScript support out of the box. Type definitions are automatically available when you import components.
1393
+
1394
+ ## Contributing
1395
+
1396
+ Please read our [Contributing Guide](CONTRIBUTING.md) before submitting a Pull Request.
1397
+
1398
+ ## License
1399
+
1400
+ MIT © [Smartflowtech Team](https://smartflowtech.com)