@lp-labs/ui-components 0.0.0-stage → 1.0.0

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 (244) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +21 -0
  3. package/README.md +256 -2
  4. package/dist/cjs/components/Accordion.d.ts +78 -0
  5. package/dist/cjs/components/Accordion.js +78 -0
  6. package/dist/cjs/components/AdvancedComponents.d.ts +353 -0
  7. package/dist/cjs/components/AdvancedComponents.js +353 -0
  8. package/dist/cjs/components/Alert.d.ts +102 -0
  9. package/dist/cjs/components/Alert.js +102 -0
  10. package/dist/cjs/components/Avatar.d.ts +89 -0
  11. package/dist/cjs/components/Avatar.js +89 -0
  12. package/dist/cjs/components/Badge.d.ts +57 -0
  13. package/dist/cjs/components/Badge.js +57 -0
  14. package/dist/cjs/components/Breadcrumb.d.ts +50 -0
  15. package/dist/cjs/components/Breadcrumb.js +50 -0
  16. package/dist/cjs/components/Button.d.ts +77 -0
  17. package/dist/cjs/components/Button.js +77 -0
  18. package/dist/cjs/components/ButtonVariants.d.ts +261 -0
  19. package/dist/cjs/components/ButtonVariants.js +261 -0
  20. package/dist/cjs/components/Card.d.ts +56 -0
  21. package/dist/cjs/components/Card.js +56 -0
  22. package/dist/cjs/components/CardVariants.d.ts +267 -0
  23. package/dist/cjs/components/CardVariants.js +267 -0
  24. package/dist/cjs/components/Checkbox.d.ts +50 -0
  25. package/dist/cjs/components/Checkbox.js +50 -0
  26. package/dist/cjs/components/Chip.d.ts +104 -0
  27. package/dist/cjs/components/Chip.js +104 -0
  28. package/dist/cjs/components/DataDisplayComponents.d.ts +275 -0
  29. package/dist/cjs/components/DataDisplayComponents.js +275 -0
  30. package/dist/cjs/components/Divider.d.ts +77 -0
  31. package/dist/cjs/components/Divider.js +77 -0
  32. package/dist/cjs/components/Drawer.d.ts +142 -0
  33. package/dist/cjs/components/Drawer.js +142 -0
  34. package/dist/cjs/components/Dropdown.d.ts +139 -0
  35. package/dist/cjs/components/Dropdown.js +139 -0
  36. package/dist/cjs/components/Form.d.ts +41 -0
  37. package/dist/cjs/components/Form.js +41 -0
  38. package/dist/cjs/components/FormGroup.d.ts +58 -0
  39. package/dist/cjs/components/FormGroup.js +58 -0
  40. package/dist/cjs/components/FormInputVariants.d.ts +298 -0
  41. package/dist/cjs/components/FormInputVariants.js +298 -0
  42. package/dist/cjs/components/Image.d.ts +106 -0
  43. package/dist/cjs/components/Image.js +106 -0
  44. package/dist/cjs/components/Input.d.ts +65 -0
  45. package/dist/cjs/components/Input.js +65 -0
  46. package/dist/cjs/components/LayoutComponents.d.ts +258 -0
  47. package/dist/cjs/components/LayoutComponents.js +258 -0
  48. package/dist/cjs/components/Link.d.ts +71 -0
  49. package/dist/cjs/components/Link.js +71 -0
  50. package/dist/cjs/components/LoadingFeedbackComponents.d.ts +230 -0
  51. package/dist/cjs/components/LoadingFeedbackComponents.js +230 -0
  52. package/dist/cjs/components/Menu.d.ts +167 -0
  53. package/dist/cjs/components/Menu.js +167 -0
  54. package/dist/cjs/components/Modal.d.ts +145 -0
  55. package/dist/cjs/components/Modal.js +145 -0
  56. package/dist/cjs/components/ModalTypes.d.ts +288 -0
  57. package/dist/cjs/components/ModalTypes.js +288 -0
  58. package/dist/cjs/components/Navbar.d.ts +181 -0
  59. package/dist/cjs/components/Navbar.js +181 -0
  60. package/dist/cjs/components/NavigationComponents.d.ts +276 -0
  61. package/dist/cjs/components/NavigationComponents.js +276 -0
  62. package/dist/cjs/components/Pagination.d.ts +94 -0
  63. package/dist/cjs/components/Pagination.js +94 -0
  64. package/dist/cjs/components/Popover.d.ts +108 -0
  65. package/dist/cjs/components/Popover.js +108 -0
  66. package/dist/cjs/components/Progress.d.ts +68 -0
  67. package/dist/cjs/components/Progress.js +68 -0
  68. package/dist/cjs/components/Radio.d.ts +93 -0
  69. package/dist/cjs/components/Radio.js +93 -0
  70. package/dist/cjs/components/Rating.d.ts +82 -0
  71. package/dist/cjs/components/Rating.js +82 -0
  72. package/dist/cjs/components/Select.d.ts +74 -0
  73. package/dist/cjs/components/Select.js +74 -0
  74. package/dist/cjs/components/Sidebar.d.ts +174 -0
  75. package/dist/cjs/components/Sidebar.js +174 -0
  76. package/dist/cjs/components/Skeleton.d.ts +57 -0
  77. package/dist/cjs/components/Skeleton.js +57 -0
  78. package/dist/cjs/components/Slider.d.ts +64 -0
  79. package/dist/cjs/components/Slider.js +64 -0
  80. package/dist/cjs/components/Spinner.d.ts +70 -0
  81. package/dist/cjs/components/Spinner.js +70 -0
  82. package/dist/cjs/components/Stack.d.ts +75 -0
  83. package/dist/cjs/components/Stack.js +75 -0
  84. package/dist/cjs/components/Stepper.d.ts +150 -0
  85. package/dist/cjs/components/Stepper.js +150 -0
  86. package/dist/cjs/components/Table.d.ts +173 -0
  87. package/dist/cjs/components/Table.js +173 -0
  88. package/dist/cjs/components/Tabs.d.ts +104 -0
  89. package/dist/cjs/components/Tabs.js +104 -0
  90. package/dist/cjs/components/Tag.d.ts +74 -0
  91. package/dist/cjs/components/Tag.js +74 -0
  92. package/dist/cjs/components/Textarea.d.ts +75 -0
  93. package/dist/cjs/components/Textarea.js +75 -0
  94. package/dist/cjs/components/Timeline.d.ts +124 -0
  95. package/dist/cjs/components/Timeline.js +124 -0
  96. package/dist/cjs/components/Toast.d.ts +155 -0
  97. package/dist/cjs/components/Toast.js +155 -0
  98. package/dist/cjs/components/Toggle.d.ts +75 -0
  99. package/dist/cjs/components/Toggle.js +75 -0
  100. package/dist/cjs/components/Tooltip.d.ts +80 -0
  101. package/dist/cjs/components/Tooltip.js +80 -0
  102. package/dist/cjs/components/TypographyComponents.d.ts +265 -0
  103. package/dist/cjs/components/TypographyComponents.js +265 -0
  104. package/dist/cjs/components/UtilityComponents.d.ts +345 -0
  105. package/dist/cjs/components/UtilityComponents.js +345 -0
  106. package/dist/cjs/components/Video.d.ts +82 -0
  107. package/dist/cjs/components/Video.js +82 -0
  108. package/dist/cjs/components/index.d.ts +311 -0
  109. package/dist/cjs/components/index.js +311 -0
  110. package/dist/cjs/index.d.ts +5 -0
  111. package/dist/cjs/index.js +5 -0
  112. package/dist/cjs/styles/main.css +493 -0
  113. package/dist/cjs/theme/ThemeProvider.d.ts +185 -0
  114. package/dist/cjs/theme/ThemeProvider.js +185 -0
  115. package/dist/cjs/theme/index.d.ts +2 -0
  116. package/dist/cjs/theme/index.js +2 -0
  117. package/dist/cjs/utilities/classNames.d.ts +200 -0
  118. package/dist/cjs/utilities/classNames.js +200 -0
  119. package/dist/cjs/utilities/index.d.ts +3 -0
  120. package/dist/cjs/utilities/index.js +3 -0
  121. package/dist/cjs/utilities/styles.d.ts +94 -0
  122. package/dist/cjs/utilities/styles.js +94 -0
  123. package/dist/esm/components/Accordion.d.ts +78 -0
  124. package/dist/esm/components/Accordion.js +78 -0
  125. package/dist/esm/components/AdvancedComponents.d.ts +353 -0
  126. package/dist/esm/components/AdvancedComponents.js +353 -0
  127. package/dist/esm/components/Alert.d.ts +102 -0
  128. package/dist/esm/components/Alert.js +102 -0
  129. package/dist/esm/components/Avatar.d.ts +89 -0
  130. package/dist/esm/components/Avatar.js +89 -0
  131. package/dist/esm/components/Badge.d.ts +57 -0
  132. package/dist/esm/components/Badge.js +57 -0
  133. package/dist/esm/components/Breadcrumb.d.ts +50 -0
  134. package/dist/esm/components/Breadcrumb.js +50 -0
  135. package/dist/esm/components/Button.d.ts +77 -0
  136. package/dist/esm/components/Button.js +77 -0
  137. package/dist/esm/components/ButtonVariants.d.ts +261 -0
  138. package/dist/esm/components/ButtonVariants.js +261 -0
  139. package/dist/esm/components/Card.d.ts +56 -0
  140. package/dist/esm/components/Card.js +56 -0
  141. package/dist/esm/components/CardVariants.d.ts +267 -0
  142. package/dist/esm/components/CardVariants.js +267 -0
  143. package/dist/esm/components/Checkbox.d.ts +50 -0
  144. package/dist/esm/components/Checkbox.js +50 -0
  145. package/dist/esm/components/Chip.d.ts +104 -0
  146. package/dist/esm/components/Chip.js +104 -0
  147. package/dist/esm/components/DataDisplayComponents.d.ts +275 -0
  148. package/dist/esm/components/DataDisplayComponents.js +275 -0
  149. package/dist/esm/components/Divider.d.ts +77 -0
  150. package/dist/esm/components/Divider.js +77 -0
  151. package/dist/esm/components/Drawer.d.ts +142 -0
  152. package/dist/esm/components/Drawer.js +142 -0
  153. package/dist/esm/components/Dropdown.d.ts +139 -0
  154. package/dist/esm/components/Dropdown.js +139 -0
  155. package/dist/esm/components/Form.d.ts +41 -0
  156. package/dist/esm/components/Form.js +41 -0
  157. package/dist/esm/components/FormGroup.d.ts +58 -0
  158. package/dist/esm/components/FormGroup.js +58 -0
  159. package/dist/esm/components/FormInputVariants.d.ts +298 -0
  160. package/dist/esm/components/FormInputVariants.js +298 -0
  161. package/dist/esm/components/Image.d.ts +106 -0
  162. package/dist/esm/components/Image.js +106 -0
  163. package/dist/esm/components/Input.d.ts +65 -0
  164. package/dist/esm/components/Input.js +65 -0
  165. package/dist/esm/components/LayoutComponents.d.ts +258 -0
  166. package/dist/esm/components/LayoutComponents.js +258 -0
  167. package/dist/esm/components/Link.d.ts +71 -0
  168. package/dist/esm/components/Link.js +71 -0
  169. package/dist/esm/components/LoadingFeedbackComponents.d.ts +230 -0
  170. package/dist/esm/components/LoadingFeedbackComponents.js +230 -0
  171. package/dist/esm/components/Menu.d.ts +167 -0
  172. package/dist/esm/components/Menu.js +167 -0
  173. package/dist/esm/components/Modal.d.ts +145 -0
  174. package/dist/esm/components/Modal.js +145 -0
  175. package/dist/esm/components/ModalTypes.d.ts +288 -0
  176. package/dist/esm/components/ModalTypes.js +288 -0
  177. package/dist/esm/components/Navbar.d.ts +181 -0
  178. package/dist/esm/components/Navbar.js +181 -0
  179. package/dist/esm/components/NavigationComponents.d.ts +276 -0
  180. package/dist/esm/components/NavigationComponents.js +276 -0
  181. package/dist/esm/components/Pagination.d.ts +94 -0
  182. package/dist/esm/components/Pagination.js +94 -0
  183. package/dist/esm/components/Popover.d.ts +108 -0
  184. package/dist/esm/components/Popover.js +108 -0
  185. package/dist/esm/components/Progress.d.ts +68 -0
  186. package/dist/esm/components/Progress.js +68 -0
  187. package/dist/esm/components/Radio.d.ts +93 -0
  188. package/dist/esm/components/Radio.js +93 -0
  189. package/dist/esm/components/Rating.d.ts +82 -0
  190. package/dist/esm/components/Rating.js +82 -0
  191. package/dist/esm/components/Select.d.ts +74 -0
  192. package/dist/esm/components/Select.js +74 -0
  193. package/dist/esm/components/Sidebar.d.ts +174 -0
  194. package/dist/esm/components/Sidebar.js +174 -0
  195. package/dist/esm/components/Skeleton.d.ts +57 -0
  196. package/dist/esm/components/Skeleton.js +57 -0
  197. package/dist/esm/components/Slider.d.ts +64 -0
  198. package/dist/esm/components/Slider.js +64 -0
  199. package/dist/esm/components/Spinner.d.ts +70 -0
  200. package/dist/esm/components/Spinner.js +70 -0
  201. package/dist/esm/components/Stack.d.ts +75 -0
  202. package/dist/esm/components/Stack.js +75 -0
  203. package/dist/esm/components/Stepper.d.ts +150 -0
  204. package/dist/esm/components/Stepper.js +150 -0
  205. package/dist/esm/components/Table.d.ts +173 -0
  206. package/dist/esm/components/Table.js +173 -0
  207. package/dist/esm/components/Tabs.d.ts +104 -0
  208. package/dist/esm/components/Tabs.js +104 -0
  209. package/dist/esm/components/Tag.d.ts +74 -0
  210. package/dist/esm/components/Tag.js +74 -0
  211. package/dist/esm/components/Textarea.d.ts +75 -0
  212. package/dist/esm/components/Textarea.js +75 -0
  213. package/dist/esm/components/Timeline.d.ts +124 -0
  214. package/dist/esm/components/Timeline.js +124 -0
  215. package/dist/esm/components/Toast.d.ts +155 -0
  216. package/dist/esm/components/Toast.js +155 -0
  217. package/dist/esm/components/Toggle.d.ts +75 -0
  218. package/dist/esm/components/Toggle.js +75 -0
  219. package/dist/esm/components/Tooltip.d.ts +80 -0
  220. package/dist/esm/components/Tooltip.js +80 -0
  221. package/dist/esm/components/TypographyComponents.d.ts +265 -0
  222. package/dist/esm/components/TypographyComponents.js +265 -0
  223. package/dist/esm/components/UtilityComponents.d.ts +345 -0
  224. package/dist/esm/components/UtilityComponents.js +345 -0
  225. package/dist/esm/components/Video.d.ts +82 -0
  226. package/dist/esm/components/Video.js +82 -0
  227. package/dist/esm/components/index.d.ts +311 -0
  228. package/dist/esm/components/index.js +311 -0
  229. package/dist/esm/index.d.ts +5 -0
  230. package/dist/esm/index.js +5 -0
  231. package/dist/esm/styles/main.css +493 -0
  232. package/dist/esm/theme/ThemeProvider.d.ts +185 -0
  233. package/dist/esm/theme/ThemeProvider.js +185 -0
  234. package/dist/esm/theme/index.d.ts +2 -0
  235. package/dist/esm/theme/index.js +2 -0
  236. package/dist/esm/utilities/classNames.d.ts +200 -0
  237. package/dist/esm/utilities/classNames.js +200 -0
  238. package/dist/esm/utilities/index.d.ts +3 -0
  239. package/dist/esm/utilities/index.js +3 -0
  240. package/dist/esm/utilities/styles.d.ts +94 -0
  241. package/dist/esm/utilities/styles.js +94 -0
  242. package/dist/styles/main.css +493 -0
  243. package/package.json +124 -6
  244. package/src/styles/main.css +493 -0
@@ -0,0 +1,258 @@
1
+ import React from 'react';
2
+
3
+ export interface GridProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ children?: React.ReactNode;
5
+ gap?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
6
+ autoFit?: boolean;
7
+ minWidth?: string;
8
+ }
9
+
10
+ const gapClass = {
11
+ xs: 'gap-2',
12
+ sm: 'gap-4',
13
+ md: 'gap-6',
14
+ lg: 'gap-8',
15
+ xl: 'gap-12',
16
+ };
17
+
18
+ export const GridAuto: React.FC<GridProps> = ({
19
+ gap = 'md',
20
+ autoFit = true,
21
+ minWidth = '250px',
22
+ className = '',
23
+ children,
24
+ ...props
25
+ }) => {
26
+ return (
27
+ <div
28
+ className={`grid ${gapClass[gap]} ${className}`}
29
+ style={{
30
+ gridTemplateColumns: autoFit ? `repeat(auto-fit, minmax(${minWidth}, 1fr))` : undefined,
31
+ }}
32
+ {...props}
33
+ >
34
+ {children}
35
+ </div>
36
+ );
37
+ };
38
+
39
+ export const GridResponsive: React.FC<
40
+ GridProps & {
41
+ cols?: { sm?: number; md?: number; lg?: number; xl?: number };
42
+ }
43
+ > = ({
44
+ gap = 'md',
45
+ cols = { sm: 1, md: 2, lg: 3, xl: 4 },
46
+ className = '',
47
+ children,
48
+ ...props
49
+ }) => {
50
+ const colClass = `grid-cols-${cols.sm || 1} sm:grid-cols-${cols.md || 2} lg:grid-cols-${cols.lg || 3} xl:grid-cols-${cols.xl || 4}`;
51
+
52
+ return (
53
+ <div className={`grid ${gapClass[gap]} ${colClass} ${className}`} {...props}>
54
+ {children}
55
+ </div>
56
+ );
57
+ };
58
+
59
+ export const GridMasonry: React.FC<GridProps> = ({ gap = 'md', className = '', children, ...props }) => {
60
+ return (
61
+ <div
62
+ className={`grid ${gapClass[gap]} ${className}`}
63
+ style={{ columnCount: 'auto', columnFill: 'balance' }}
64
+ {...props}
65
+ >
66
+ {React.Children.map(children, (child) => (
67
+ <div style={{ breakInside: 'avoid' }}>{child}</div>
68
+ ))}
69
+ </div>
70
+ );
71
+ };
72
+
73
+ export const GridFixedCol: React.FC<
74
+ GridProps & {
75
+ columns: number;
76
+ }
77
+ > = ({ gap = 'md', columns = 3, className = '', children, ...props }) => {
78
+ return (
79
+ <div className={`grid grid-cols-${columns} ${gapClass[gap]} ${className}`} {...props}>
80
+ {children}
81
+ </div>
82
+ );
83
+ };
84
+
85
+ export const GridDynamic: React.FC<
86
+ GridProps & {
87
+ minColWidth?: string;
88
+ }
89
+ > = ({
90
+ gap = 'md',
91
+ minColWidth = '200px',
92
+ className = '',
93
+ children,
94
+ ...props
95
+ }) => {
96
+ return (
97
+ <div
98
+ className={`grid ${gapClass[gap]} ${className}`}
99
+ style={{
100
+ gridTemplateColumns: `repeat(auto-fill, minmax(${minColWidth}, 1fr))`,
101
+ }}
102
+ {...props}
103
+ >
104
+ {children}
105
+ </div>
106
+ );
107
+ };
108
+
109
+ export const GridNested: React.FC<GridProps> = ({
110
+ gap = 'md',
111
+ className = '',
112
+ children,
113
+ ...props
114
+ }) => {
115
+ return (
116
+ <div className={`grid ${gapClass[gap]} ${className}`} {...props}>
117
+ {children}
118
+ </div>
119
+ );
120
+ };
121
+
122
+ export const GridAligned: React.FC<
123
+ GridProps & {
124
+ align?: 'start' | 'center' | 'end' | 'stretch';
125
+ justify?: 'start' | 'center' | 'end' | 'between';
126
+ }
127
+ > = ({
128
+ gap = 'md',
129
+ align = 'stretch',
130
+ justify = 'start',
131
+ className = '',
132
+ children,
133
+ ...props
134
+ }) => {
135
+ const alignClass = {
136
+ start: 'items-start',
137
+ center: 'items-center',
138
+ end: 'items-end',
139
+ stretch: 'items-stretch',
140
+ }[align];
141
+
142
+ const justifyClass = {
143
+ start: 'justify-start',
144
+ center: 'justify-center',
145
+ end: 'justify-end',
146
+ between: 'justify-between',
147
+ }[justify];
148
+
149
+ return (
150
+ <div className={`grid ${gapClass[gap]} ${alignClass} ${justifyClass} ${className}`} {...props}>
151
+ {children}
152
+ </div>
153
+ );
154
+ };
155
+
156
+ export const Container: React.FC<GridProps & { maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' }> = ({
157
+ maxWidth = 'lg',
158
+ className = '',
159
+ children,
160
+ ...props
161
+ }) => {
162
+ const maxWidthClass = {
163
+ sm: 'max-w-sm',
164
+ md: 'max-w-md',
165
+ lg: 'max-w-lg',
166
+ xl: 'max-w-xl',
167
+ '2xl': 'max-w-2xl',
168
+ }[maxWidth];
169
+
170
+ return (
171
+ <div className={`mx-auto px-4 ${maxWidthClass} ${className}`} {...props}>
172
+ {children}
173
+ </div>
174
+ );
175
+ };
176
+
177
+ export const Flex: React.FC<
178
+ GridProps & {
179
+ direction?: 'row' | 'col';
180
+ wrap?: boolean;
181
+ align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline';
182
+ justify?: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
183
+ }
184
+ > = ({
185
+ direction = 'row',
186
+ wrap = false,
187
+ gap = 'md',
188
+ align = 'stretch',
189
+ justify = 'start',
190
+ className = '',
191
+ children,
192
+ ...props
193
+ }) => {
194
+ const directionClass = direction === 'col' ? 'flex-col' : 'flex-row';
195
+ const wrapClass = wrap ? 'flex-wrap' : 'flex-nowrap';
196
+ const alignClass = {
197
+ start: 'items-start',
198
+ center: 'items-center',
199
+ end: 'items-end',
200
+ stretch: 'items-stretch',
201
+ baseline: 'items-baseline',
202
+ }[align];
203
+
204
+ const justifyClass = {
205
+ start: 'justify-start',
206
+ center: 'justify-center',
207
+ end: 'justify-end',
208
+ between: 'justify-between',
209
+ around: 'justify-around',
210
+ evenly: 'justify-evenly',
211
+ }[justify];
212
+
213
+ return (
214
+ <div className={`flex ${directionClass} ${wrapClass} ${gapClass[gap]} ${alignClass} ${justifyClass} ${className}`} {...props}>
215
+ {children}
216
+ </div>
217
+ );
218
+ };
219
+
220
+ export const Stack: React.FC<GridProps & { direction?: 'vertical' | 'horizontal' }> = ({
221
+ direction = 'vertical',
222
+ gap = 'md',
223
+ className = '',
224
+ children,
225
+ ...props
226
+ }) => {
227
+ const directionClass = direction === 'vertical' ? 'flex-col' : 'flex-row';
228
+
229
+ return (
230
+ <div className={`flex ${directionClass} ${gapClass[gap]} ${className}`} {...props}>
231
+ {children}
232
+ </div>
233
+ );
234
+ };
235
+
236
+ export const AspectRatio: React.FC<
237
+ GridProps & {
238
+ ratio?: 'square' | '16/9' | '4/3' | '21/9';
239
+ }
240
+ > = ({
241
+ ratio = 'square',
242
+ className = '',
243
+ children,
244
+ ...props
245
+ }) => {
246
+ const ratioClass = {
247
+ square: 'aspect-square',
248
+ '16/9': 'aspect-video',
249
+ '4/3': 'aspect-video', // fallback
250
+ '21/9': 'aspect-auto',
251
+ }[ratio];
252
+
253
+ return (
254
+ <div className={`${ratioClass} overflow-hidden ${className}`} {...props}>
255
+ {children}
256
+ </div>
257
+ );
258
+ };
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { cn } from '../utilities/classNames';
3
+
4
+ export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
5
+ href: string;
6
+ children: React.ReactNode;
7
+ variant?: 'primary' | 'secondary' | 'danger' | 'success';
8
+ underline?: 'always' | 'hover' | 'none';
9
+ external?: boolean;
10
+ disabled?: boolean;
11
+ className?: string;
12
+ }
13
+
14
+ export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
15
+ (
16
+ {
17
+ href,
18
+ children,
19
+ variant = 'primary',
20
+ underline = 'hover',
21
+ external = false,
22
+ disabled = false,
23
+ className,
24
+ ...props
25
+ },
26
+ ref
27
+ ) => {
28
+ const variantClasses = {
29
+ primary: 'text-blue-600 hover:text-blue-800',
30
+ secondary: 'text-gray-600 hover:text-gray-800',
31
+ danger: 'text-red-600 hover:text-red-800',
32
+ success: 'text-green-600 hover:text-green-800',
33
+ };
34
+
35
+ const underlineClasses = {
36
+ always: 'underline',
37
+ hover: 'hover:underline',
38
+ none: 'no-underline',
39
+ };
40
+
41
+ return (
42
+ <a
43
+ ref={ref}
44
+ href={disabled ? undefined : href}
45
+ target={external ? '_blank' : undefined}
46
+ rel={external ? 'noopener noreferrer' : undefined}
47
+ className={cn(
48
+ 'transition-colors font-medium',
49
+ variantClasses[variant],
50
+ underlineClasses[underline],
51
+ {
52
+ 'opacity-50 cursor-not-allowed': disabled,
53
+ 'cursor-pointer': !disabled,
54
+ },
55
+ className
56
+ )}
57
+ onClick={(e) => {
58
+ if (disabled) {
59
+ e.preventDefault();
60
+ }
61
+ }}
62
+ {...props}
63
+ >
64
+ {children}
65
+ {external && <span className="ml-1">↗</span>}
66
+ </a>
67
+ );
68
+ }
69
+ );
70
+
71
+ Link.displayName = 'Link';
@@ -0,0 +1,71 @@
1
+ import React from 'react';
2
+ import { cn } from '../utilities/classNames';
3
+
4
+ export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
5
+ href: string;
6
+ children: React.ReactNode;
7
+ variant?: 'primary' | 'secondary' | 'danger' | 'success';
8
+ underline?: 'always' | 'hover' | 'none';
9
+ external?: boolean;
10
+ disabled?: boolean;
11
+ className?: string;
12
+ }
13
+
14
+ export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
15
+ (
16
+ {
17
+ href,
18
+ children,
19
+ variant = 'primary',
20
+ underline = 'hover',
21
+ external = false,
22
+ disabled = false,
23
+ className,
24
+ ...props
25
+ },
26
+ ref
27
+ ) => {
28
+ const variantClasses = {
29
+ primary: 'text-blue-600 hover:text-blue-800',
30
+ secondary: 'text-gray-600 hover:text-gray-800',
31
+ danger: 'text-red-600 hover:text-red-800',
32
+ success: 'text-green-600 hover:text-green-800',
33
+ };
34
+
35
+ const underlineClasses = {
36
+ always: 'underline',
37
+ hover: 'hover:underline',
38
+ none: 'no-underline',
39
+ };
40
+
41
+ return (
42
+ <a
43
+ ref={ref}
44
+ href={disabled ? undefined : href}
45
+ target={external ? '_blank' : undefined}
46
+ rel={external ? 'noopener noreferrer' : undefined}
47
+ className={cn(
48
+ 'transition-colors font-medium',
49
+ variantClasses[variant],
50
+ underlineClasses[underline],
51
+ {
52
+ 'opacity-50 cursor-not-allowed': disabled,
53
+ 'cursor-pointer': !disabled,
54
+ },
55
+ className
56
+ )}
57
+ onClick={(e) => {
58
+ if (disabled) {
59
+ e.preventDefault();
60
+ }
61
+ }}
62
+ {...props}
63
+ >
64
+ {children}
65
+ {external && <span className="ml-1">↗</span>}
66
+ </a>
67
+ );
68
+ }
69
+ );
70
+
71
+ Link.displayName = 'Link';
@@ -0,0 +1,230 @@
1
+ import React from 'react';
2
+
3
+ export interface LoadingProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ size?: 'sm' | 'md' | 'lg';
5
+ color?: string;
6
+ children?: React.ReactNode;
7
+ }
8
+
9
+ export const SpinnerDots: React.FC<LoadingProps> = ({ size = 'md', color = 'blue', className = '', ...props }) => {
10
+ const sizeClass = { sm: 'w-6 h-6', md: 'w-8 h-8', lg: 'w-12 h-12' }[size];
11
+
12
+ return (
13
+ <div className={`flex gap-1 items-center justify-center ${className}`} {...props}>
14
+ {[0, 1, 2].map((i) => (
15
+ <div
16
+ key={i}
17
+ className={`${sizeClass} bg-${color}-600 rounded-full animate-bounce`}
18
+ style={{ animationDelay: `${i * 0.1}s` }}
19
+ ></div>
20
+ ))}
21
+ </div>
22
+ );
23
+ };
24
+
25
+ export const SpinnerRing: React.FC<LoadingProps> = ({ size = 'md', color = 'blue', className = '', ...props }) => {
26
+ const sizeClass = { sm: 'w-6 h-6', md: 'w-8 h-8', lg: 'w-12 h-12' }[size];
27
+
28
+ return (
29
+ <div className={`${sizeClass} border-4 border-gray-200 border-t-${color}-600 rounded-full animate-spin ${className}`} {...props}></div>
30
+ );
31
+ };
32
+
33
+ export const SpinnerBar: React.FC<LoadingProps> = ({ size = 'md', color = 'blue', className = '', ...props }) => {
34
+ const heightClass = { sm: 'h-1', md: 'h-2', lg: 'h-3' }[size];
35
+
36
+ return (
37
+ <div className={`w-full ${heightClass} bg-gray-200 rounded-full overflow-hidden ${className}`} {...props}>
38
+ <div
39
+ className={`h-full w-1/3 bg-${color}-600 animate-pulse`}
40
+ style={{
41
+ animation: 'slide 1.5s ease-in-out infinite',
42
+ }}
43
+ ></div>
44
+ </div>
45
+ );
46
+ };
47
+
48
+ export const SpinnerBounce: React.FC<LoadingProps> = ({ size = 'md', color = 'blue', className = '', ...props }) => {
49
+ const sizeClass = { sm: 'w-6 h-6', md: 'w-8 h-8', lg: 'w-12 h-12' }[size];
50
+
51
+ return (
52
+ <div className={`flex gap-2 items-end justify-center ${className}`} {...props}>
53
+ {[0, 1, 2].map((i) => (
54
+ <div
55
+ key={i}
56
+ className={`${sizeClass} bg-${color}-600 rounded-full`}
57
+ style={{
58
+ animation: 'bounce 1.4s ease-in-out infinite',
59
+ animationDelay: `${i * 0.16}s`,
60
+ }}
61
+ ></div>
62
+ ))}
63
+ </div>
64
+ );
65
+ };
66
+
67
+ export const SpinnerPulse: React.FC<LoadingProps> = ({ size = 'md', color = 'blue', className = '', ...props }) => {
68
+ const sizeClass = { sm: 'w-6 h-6', md: 'w-8 h-8', lg: 'w-12 h-12' }[size];
69
+
70
+ return (
71
+ <div
72
+ className={`${sizeClass} bg-${color}-600 rounded-full animate-pulse ${className}`}
73
+ {...props}
74
+ ></div>
75
+ );
76
+ };
77
+
78
+ export const SkeletonText: React.FC<LoadingProps & { lines?: number }> = ({
79
+ lines = 3,
80
+ className = '',
81
+ ...props
82
+ }) => {
83
+ return (
84
+ <div className={`space-y-2 ${className}`} {...props}>
85
+ {Array.from({ length: lines }).map((_, i) => (
86
+ <div key={i} className="h-4 bg-gray-200 rounded animate-pulse"></div>
87
+ ))}
88
+ </div>
89
+ );
90
+ };
91
+
92
+ export const SkeletonCard: React.FC<LoadingProps> = ({ className = '', ...props }) => {
93
+ return (
94
+ <div className={`bg-white rounded-lg shadow-md p-6 space-y-4 ${className}`} {...props}>
95
+ <div className="h-8 bg-gray-200 rounded animate-pulse w-1/3"></div>
96
+ <div className="h-4 bg-gray-200 rounded animate-pulse"></div>
97
+ <div className="h-4 bg-gray-200 rounded animate-pulse w-5/6"></div>
98
+ <div className="h-32 bg-gray-200 rounded animate-pulse"></div>
99
+ </div>
100
+ );
101
+ };
102
+
103
+ export const SkeletonImage: React.FC<LoadingProps> = ({
104
+ size = 'md',
105
+ className = '',
106
+ ...props
107
+ }) => {
108
+ const sizeClass = {
109
+ sm: 'w-24 h-24',
110
+ md: 'w-48 h-48',
111
+ lg: 'w-96 h-96',
112
+ }[size];
113
+
114
+ return <div className={`${sizeClass} bg-gray-200 rounded animate-pulse ${className}`} {...props}></div>;
115
+ };
116
+
117
+ export const SkeletonTable: React.FC<LoadingProps & { rows?: number; cols?: number }> = ({
118
+ rows = 5,
119
+ cols = 4,
120
+ className = '',
121
+ ...props
122
+ }) => {
123
+ return (
124
+ <div className={`space-y-2 ${className}`} {...props}>
125
+ {Array.from({ length: rows }).map((_, i) => (
126
+ <div key={i} className="flex gap-2">
127
+ {Array.from({ length: cols }).map((_, j) => (
128
+ <div key={j} className="flex-1 h-6 bg-gray-200 rounded animate-pulse"></div>
129
+ ))}
130
+ </div>
131
+ ))}
132
+ </div>
133
+ );
134
+ };
135
+
136
+ export const ProgressLinear: React.FC<
137
+ LoadingProps & {
138
+ value: number;
139
+ max?: number;
140
+ showLabel?: boolean;
141
+ color?: 'blue' | 'green' | 'red' | 'yellow';
142
+ }
143
+ > = ({ value, max = 100, showLabel = false, color = 'blue', className = '', ...props }) => {
144
+ const percentage = (value / max) * 100;
145
+
146
+ return (
147
+ <div className={`w-full ${className}`} {...props}>
148
+ <div className="h-2 bg-gray-200 rounded-full overflow-hidden">
149
+ <div
150
+ className={`h-full bg-${color}-600 transition-all duration-300`}
151
+ style={{ width: `${Math.min(percentage, 100)}%` }}
152
+ ></div>
153
+ </div>
154
+ {showLabel && <p className="text-sm text-gray-600 mt-1">{Math.round(percentage)}%</p>}
155
+ </div>
156
+ );
157
+ };
158
+
159
+ export const ProgressCircular: React.FC<
160
+ LoadingProps & {
161
+ value: number;
162
+ max?: number;
163
+ showLabel?: boolean;
164
+ color?: 'blue' | 'green' | 'red' | 'yellow';
165
+ }
166
+ > = ({ value, max = 100, showLabel = false, size = 'md', color = 'blue', className = '', ...props }) => {
167
+ const percentage = (value / max) * 100;
168
+ const sizeClass = { sm: 'w-16 h-16', md: 'w-24 h-24', lg: 'w-32 h-32' }[size];
169
+ const circumference = 2 * Math.PI * 45;
170
+
171
+ return (
172
+ <div className={`flex flex-col items-center ${className}`} {...props}>
173
+ <div className={`${sizeClass} relative`}>
174
+ <svg className="transform -rotate-90 w-full h-full">
175
+ <circle cx="50%" cy="50%" r="45" fill="none" stroke="#e5e7eb" strokeWidth="4"></circle>
176
+ <circle
177
+ cx="50%"
178
+ cy="50%"
179
+ r="45"
180
+ fill="none"
181
+ stroke={`currentColor`}
182
+ strokeWidth="4"
183
+ strokeDasharray={circumference}
184
+ strokeDashoffset={circumference - (percentage / 100) * circumference}
185
+ className={`text-${color}-600 transition-all duration-300`}
186
+ ></circle>
187
+ </svg>
188
+ {showLabel && (
189
+ <div className="absolute inset-0 flex items-center justify-center">
190
+ <span className="text-sm font-semibold">{Math.round(percentage)}%</span>
191
+ </div>
192
+ )}
193
+ </div>
194
+ </div>
195
+ );
196
+ };
197
+
198
+ export const ProgressStepped: React.FC<
199
+ LoadingProps & {
200
+ current: number;
201
+ total: number;
202
+ color?: 'blue' | 'green' | 'red' | 'yellow';
203
+ }
204
+ > = ({ current, total, color = 'blue', className = '', ...props }) => {
205
+ return (
206
+ <div className={`flex gap-2 ${className}`} {...props}>
207
+ {Array.from({ length: total }).map((_, i) => (
208
+ <div
209
+ key={i}
210
+ className={`flex-1 h-2 rounded-full ${i < current ? `bg-${color}-600` : 'bg-gray-200'} transition-colors`}
211
+ ></div>
212
+ ))}
213
+ </div>
214
+ );
215
+ };
216
+
217
+ export const Overlay: React.FC<LoadingProps & { isVisible?: boolean }> = ({
218
+ isVisible = true,
219
+ className = '',
220
+ children,
221
+ ...props
222
+ }) => {
223
+ if (!isVisible) return null;
224
+
225
+ return (
226
+ <div className={`absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center ${className}`} {...props}>
227
+ {children}
228
+ </div>
229
+ );
230
+ };