@umituz/web-design-system 1.0.2 → 1.0.3

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.
Files changed (30) hide show
  1. package/package.json +1 -1
  2. package/src/domain/tokens/animation.tokens.ts +87 -0
  3. package/src/domain/tokens/index.ts +11 -0
  4. package/src/presentation/atoms/Checkbox.tsx +50 -0
  5. package/src/presentation/atoms/Divider.tsx +34 -0
  6. package/src/presentation/atoms/Link.tsx +45 -0
  7. package/src/presentation/atoms/Progress.tsx +48 -0
  8. package/src/presentation/atoms/Radio.tsx +42 -0
  9. package/src/presentation/atoms/Skeleton.tsx +38 -0
  10. package/src/presentation/atoms/Slider.tsx +49 -0
  11. package/src/presentation/atoms/Tooltip.tsx +76 -0
  12. package/src/presentation/atoms/index.ts +24 -0
  13. package/src/presentation/hooks/index.ts +13 -0
  14. package/src/presentation/hooks/useClickOutside.ts +33 -0
  15. package/src/presentation/hooks/useClipboard.ts +38 -0
  16. package/src/presentation/hooks/useDebounce.ts +22 -0
  17. package/src/presentation/hooks/useKeyboard.ts +89 -0
  18. package/src/presentation/hooks/useScrollLock.ts +26 -0
  19. package/src/presentation/hooks/useToggle.ts +16 -0
  20. package/src/presentation/molecules/CheckboxGroup.tsx +68 -0
  21. package/src/presentation/molecules/InputGroup.tsx +65 -0
  22. package/src/presentation/molecules/RadioGroup.tsx +63 -0
  23. package/src/presentation/molecules/Select.tsx +41 -0
  24. package/src/presentation/molecules/Textarea.tsx +43 -0
  25. package/src/presentation/molecules/index.ts +15 -0
  26. package/src/presentation/organisms/Accordion.tsx +117 -0
  27. package/src/presentation/organisms/Breadcrumb.tsx +83 -0
  28. package/src/presentation/organisms/Table.tsx +120 -0
  29. package/src/presentation/organisms/Tabs.tsx +99 -0
  30. package/src/presentation/organisms/index.ts +21 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Table Component (Organism)
3
+ * @description Data table component
4
+ */
5
+
6
+ import { forwardRef, type HTMLAttributes } from 'react';
7
+ import { cn } from '../../infrastructure/utils';
8
+ import type { BaseProps, ChildrenProps } from '../../domain/types';
9
+
10
+ export interface TableProps extends HTMLAttributes<HTMLTableElement>, BaseProps, ChildrenProps {}
11
+
12
+ export const Table = forwardRef<HTMLTableElement, TableProps>(
13
+ ({ className, children, ...props }, ref) => {
14
+ return (
15
+ <div className="relative w-full overflow-auto">
16
+ <table
17
+ ref={ref}
18
+ className={cn('w-full caption-bottom text-sm', className)}
19
+ {...props}
20
+ >
21
+ {children}
22
+ </table>
23
+ </div>
24
+ );
25
+ }
26
+ );
27
+
28
+ Table.displayName = 'Table';
29
+
30
+ export const TableHeader = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(
31
+ ({ className, ...props }, ref) => (
32
+ <thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />
33
+ )
34
+ );
35
+
36
+ TableHeader.displayName = 'TableHeader';
37
+
38
+ export const TableBody = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(
39
+ ({ className, ...props }, ref) => (
40
+ <tbody
41
+ ref={ref}
42
+ className={cn('[&_tr:last-child]:border-0', className)}
43
+ {...props}
44
+ />
45
+ )
46
+ );
47
+
48
+ TableBody.displayName = 'TableBody';
49
+
50
+ export const TableFooter = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(
51
+ ({ className, ...props }, ref) => (
52
+ <tfoot
53
+ ref={ref}
54
+ className={cn(
55
+ 'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',
56
+ className
57
+ )}
58
+ {...props}
59
+ />
60
+ )
61
+ );
62
+
63
+ TableFooter.displayName = 'TableFooter';
64
+
65
+ export const TableRow = forwardRef<HTMLTableRowElement, HTMLAttributes<HTMLTableRowElement>>(
66
+ ({ className, ...props }, ref) => (
67
+ <tr
68
+ ref={ref}
69
+ className={cn(
70
+ 'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
71
+ className
72
+ )}
73
+ {...props}
74
+ />
75
+ )
76
+ );
77
+
78
+ TableRow.displayName = 'TableRow';
79
+
80
+ export const TableHead = forwardRef<HTMLTableCellElement, HTMLAttributes<HTMLTableCellElement>>(
81
+ ({ className, ...props }, ref) => (
82
+ <th
83
+ ref={ref}
84
+ className={cn(
85
+ 'h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
86
+ className
87
+ )}
88
+ {...props}
89
+ />
90
+ )
91
+ );
92
+
93
+ TableHead.displayName = 'TableHead';
94
+
95
+ export const TableCell = forwardRef<HTMLTableCellElement, HTMLAttributes<HTMLTableCellElement>>(
96
+ ({ className, ...props }, ref) => (
97
+ <td
98
+ ref={ref}
99
+ className={cn(
100
+ 'p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
101
+ className
102
+ )}
103
+ {...props}
104
+ />
105
+ )
106
+ );
107
+
108
+ TableCell.displayName = 'TableCell';
109
+
110
+ export const TableCaption = forwardRef<HTMLTableCaptionElement, HTMLAttributes<HTMLTableCaptionElement>>(
111
+ ({ className, ...props }, ref) => (
112
+ <caption
113
+ ref={ref}
114
+ className={cn('mt-4 text-sm text-muted-foreground', className)}
115
+ {...props}
116
+ />
117
+ )
118
+ );
119
+
120
+ TableCaption.displayName = 'TableCaption';
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Tabs Component (Organism)
3
+ * @description Tabbed interface
4
+ */
5
+
6
+ import { useState, useCallback, type ReactNode, type HTMLAttributes } from 'react';
7
+ import { cn } from '../../infrastructure/utils';
8
+ import type { BaseProps, ChildrenProps } from '../../domain/types';
9
+
10
+ export interface Tab {
11
+ value: string;
12
+ label: string;
13
+ content?: ReactNode;
14
+ disabled?: boolean;
15
+ }
16
+
17
+ export interface TabsProps extends HTMLAttributes<HTMLDivElement>, BaseProps {
18
+ tabs: Tab[];
19
+ defaultValue?: string;
20
+ variant?: 'default' | 'pills' | 'underline';
21
+ }
22
+
23
+ const variantStyles: Record<'default' | 'pills' | 'underline', string> = {
24
+ default: 'bg-muted p-1 rounded-lg gap-1',
25
+ pills: 'bg-transparent gap-2',
26
+ underline: 'bg-transparent border-b gap-6',
27
+ };
28
+
29
+ const tabVariantStyles: Record<'default' | 'pills' | 'underline', { base: string; active: string }> = {
30
+ default: {
31
+ base: 'px-3 py-1.5 rounded-md text-sm font-medium transition-all',
32
+ active: 'bg-background text-foreground shadow-sm',
33
+ },
34
+ pills: {
35
+ base: 'px-4 py-2 rounded-full text-sm font-medium transition-all',
36
+ active: 'bg-primary text-primary-foreground',
37
+ },
38
+ underline: {
39
+ base: 'px-1 pb-3 text-sm font-medium transition-all border-b-2 border-transparent',
40
+ active: 'text-foreground border-primary',
41
+ },
42
+ };
43
+
44
+ export function Tabs({ tabs, defaultValue, variant = 'default', className, ...props }: TabsProps) {
45
+ const [activeTab, setActiveTab] = useState(defaultValue || tabs[0]?.value);
46
+
47
+ const handleTabChange = useCallback((value: string) => {
48
+ const tab = tabs.find((t) => t.value === value);
49
+ if (tab && !tab.disabled) {
50
+ setActiveTab(value);
51
+ }
52
+ }, [tabs]);
53
+
54
+ const currentTab = tabs.find((t) => t.value === activeTab);
55
+
56
+ return (
57
+ <div className={cn('w-full', className)} {...props}>
58
+ {/* Tab List */}
59
+ <div
60
+ role="tablist"
61
+ className={cn('inline-flex w-full', variantStyles[variant])}
62
+ >
63
+ {tabs.map((tab) => {
64
+ const isActive = activeTab === tab.value;
65
+ const styles = tabVariantStyles[variant];
66
+
67
+ return (
68
+ <button
69
+ key={tab.value}
70
+ role="tab"
71
+ aria-selected={isActive}
72
+ disabled={tab.disabled}
73
+ onClick={() => handleTabChange(tab.value)}
74
+ className={cn(
75
+ styles.base,
76
+ isActive
77
+ ? styles.active
78
+ : 'text-muted-foreground hover:text-foreground',
79
+ tab.disabled && 'opacity-50 cursor-not-allowed'
80
+ )}
81
+ >
82
+ {tab.label}
83
+ </button>
84
+ );
85
+ })}
86
+ </div>
87
+
88
+ {/* Tab Content */}
89
+ <div
90
+ role="tabpanel"
91
+ className="mt-4"
92
+ >
93
+ {currentTab?.content}
94
+ </div>
95
+ </div>
96
+ );
97
+ }
98
+
99
+ Tabs.displayName = 'Tabs';
@@ -15,3 +15,24 @@ export type { ModalProps } from './Modal';
15
15
 
16
16
  export { Navbar, NavbarBrand, NavbarLinks, NavbarActions } from './Navbar';
17
17
  export type { NavbarProps } from './Navbar';
18
+
19
+ export {
20
+ Table,
21
+ TableHeader,
22
+ TableBody,
23
+ TableFooter,
24
+ TableRow,
25
+ TableHead,
26
+ TableCell,
27
+ TableCaption
28
+ } from './Table';
29
+ export type { TableProps } from './Table';
30
+
31
+ export { Tabs } from './Tabs';
32
+ export type { TabsProps, Tab } from './Tabs';
33
+
34
+ export { Accordion } from './Accordion';
35
+ export type { AccordionProps, AccordionItem } from './Accordion';
36
+
37
+ export { Breadcrumbs } from './Breadcrumb';
38
+ export type { BreadcrumbsProps, BreadcrumbItem } from './Breadcrumb';