fiboui 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 (141) hide show
  1. package/README.md +101 -0
  2. package/dist/content/Alert/index.d.ts +878 -0
  3. package/dist/content/Avatar/index.d.ts +886 -0
  4. package/dist/content/Badge/index.d.ts +887 -0
  5. package/dist/content/Image/index.d.ts +893 -0
  6. package/dist/content/Label/index.d.ts +879 -0
  7. package/dist/content/Progress/index.d.ts +898 -0
  8. package/dist/content/Skeleton/index.d.ts +879 -0
  9. package/dist/content/Spinner/index.d.ts +880 -0
  10. package/dist/content/Text/index.d.ts +878 -0
  11. package/dist/content/index.d.ts +9 -0
  12. package/dist/core/StateWrapper.d.ts +28 -0
  13. package/dist/core/builder.d.ts +50 -0
  14. package/dist/core/component.d.ts +7 -0
  15. package/dist/core/effects.d.ts +3 -0
  16. package/dist/core/icons.d.ts +11 -0
  17. package/dist/core/index.d.ts +5 -0
  18. package/dist/core/state.d.ts +37 -0
  19. package/dist/core/types.d.ts +51 -0
  20. package/dist/demo.d.ts +7 -0
  21. package/dist/effects-Co9C_Dyx.mjs +9 -0
  22. package/dist/examples/ScaffoldExamples.d.ts +3 -0
  23. package/dist/examples/StateExamples.d.ts +5 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.esm.js +4622 -0
  26. package/dist/index.umd.js +251 -0
  27. package/dist/interactive/Button/index.d.ts +897 -0
  28. package/dist/interactive/Checkbox/index.d.ts +884 -0
  29. package/dist/interactive/Combobox/index.d.ts +898 -0
  30. package/dist/interactive/RadioGroup/index.d.ts +888 -0
  31. package/dist/interactive/Select/index.d.ts +895 -0
  32. package/dist/interactive/Switch/index.d.ts +881 -0
  33. package/dist/interactive/TextField/index.d.ts +892 -0
  34. package/dist/interactive/Textarea/index.d.ts +890 -0
  35. package/dist/interactive/index.d.ts +8 -0
  36. package/dist/layout/Center/index.d.ts +869 -0
  37. package/dist/layout/Column/index.d.ts +881 -0
  38. package/dist/layout/Container/index.d.ts +870 -0
  39. package/dist/layout/DashboardLayout/index.d.ts +870 -0
  40. package/dist/layout/Header/index.d.ts +870 -0
  41. package/dist/layout/Line/index.d.ts +872 -0
  42. package/dist/layout/Row/index.d.ts +879 -0
  43. package/dist/layout/Scaffold/index.d.ts +878 -0
  44. package/dist/layout/ScrollView/index.d.ts +879 -0
  45. package/dist/layout/Sidebar/index.d.ts +870 -0
  46. package/dist/layout/Spacer/index.d.ts +875 -0
  47. package/dist/layout/StakentComponents.d.ts +4 -0
  48. package/dist/layout/index.d.ts +11 -0
  49. package/dist/structure/Banner/index.d.ts +879 -0
  50. package/dist/structure/Box/index.d.ts +869 -0
  51. package/dist/structure/Card/index.d.ts +881 -0
  52. package/dist/structure/Collapse/index.d.ts +884 -0
  53. package/dist/structure/Grid/index.d.ts +1757 -0
  54. package/dist/structure/List/index.d.ts +888 -0
  55. package/dist/structure/Table/index.d.ts +895 -0
  56. package/dist/structure/Tags/index.d.ts +876 -0
  57. package/dist/structure/cards/AssetCard/index.d.ts +884 -0
  58. package/dist/structure/cards/CollectionCard/index.d.ts +880 -0
  59. package/dist/structure/cards/ContentCard/index.d.ts +884 -0
  60. package/dist/structure/cards/ProfileCard/index.d.ts +892 -0
  61. package/dist/structure/cards/index.d.ts +5 -0
  62. package/dist/structure/cards/variants/index.d.ts +3490 -0
  63. package/dist/structure/index.d.ts +9 -0
  64. package/dist/style.css +1 -0
  65. package/dist/theme/cupertino.d.ts +3 -0
  66. package/dist/theme/index.d.ts +5 -0
  67. package/dist/theme/material.d.ts +3 -0
  68. package/dist/theme/provider.d.ts +16 -0
  69. package/dist/theme/types.d.ts +57 -0
  70. package/dist/theme/web.d.ts +3 -0
  71. package/package.json +54 -0
  72. package/src/content/Alert/index.ts +110 -0
  73. package/src/content/Avatar/index.ts +116 -0
  74. package/src/content/Badge/index.ts +162 -0
  75. package/src/content/Image/index.ts +137 -0
  76. package/src/content/Label/index.ts +66 -0
  77. package/src/content/Progress/index.ts +378 -0
  78. package/src/content/Skeleton/index.ts +71 -0
  79. package/src/content/Spinner/index.ts +139 -0
  80. package/src/content/Text/index.ts +74 -0
  81. package/src/content/index.ts +9 -0
  82. package/src/core/StateWrapper.tsx +105 -0
  83. package/src/core/builder.ts +259 -0
  84. package/src/core/component.ts +49 -0
  85. package/src/core/effects.ts +27 -0
  86. package/src/core/icons.tsx +57 -0
  87. package/src/core/index.ts +5 -0
  88. package/src/core/state.ts +233 -0
  89. package/src/core/types.ts +62 -0
  90. package/src/demo.tsx +1045 -0
  91. package/src/examples/ScaffoldExamples.tsx +299 -0
  92. package/src/examples/StateExamples.tsx +149 -0
  93. package/src/index.ts +8 -0
  94. package/src/interactive/Button/index.ts +218 -0
  95. package/src/interactive/Checkbox/index.ts +145 -0
  96. package/src/interactive/Combobox/index.ts +278 -0
  97. package/src/interactive/RadioGroup/index.ts +124 -0
  98. package/src/interactive/Select/index.ts +227 -0
  99. package/src/interactive/Switch/index.ts +123 -0
  100. package/src/interactive/TextField/index.ts +200 -0
  101. package/src/interactive/Textarea/index.ts +129 -0
  102. package/src/interactive/index.ts +8 -0
  103. package/src/layout/Center/index.ts +34 -0
  104. package/src/layout/Column/index.ts +101 -0
  105. package/src/layout/Container/index.ts +28 -0
  106. package/src/layout/DashboardLayout/index.ts +106 -0
  107. package/src/layout/Header/index.ts +50 -0
  108. package/src/layout/Line/index.ts +41 -0
  109. package/src/layout/Row/index.ts +93 -0
  110. package/src/layout/Scaffold/index.ts +133 -0
  111. package/src/layout/ScrollView/index.ts +67 -0
  112. package/src/layout/Sidebar/index.ts +56 -0
  113. package/src/layout/Spacer/index.ts +46 -0
  114. package/src/layout/StakentComponents.tsx +57 -0
  115. package/src/layout/index.ts +11 -0
  116. package/src/structure/Banner/index.ts +92 -0
  117. package/src/structure/Box/index.ts +45 -0
  118. package/src/structure/Card/index.ts +113 -0
  119. package/src/structure/Collapse/index.ts +122 -0
  120. package/src/structure/Grid/index.ts +197 -0
  121. package/src/structure/List/index.ts +185 -0
  122. package/src/structure/Table/index.ts +165 -0
  123. package/src/structure/Tags/index.ts +69 -0
  124. package/src/structure/cards/AssetCard/index.ts +158 -0
  125. package/src/structure/cards/CollectionCard/index.ts +95 -0
  126. package/src/structure/cards/ContentCard/index.ts +127 -0
  127. package/src/structure/cards/ProfileCard/index.ts +152 -0
  128. package/src/structure/cards/index.ts +5 -0
  129. package/src/structure/cards/variants/index.ts +301 -0
  130. package/src/structure/index.ts +10 -0
  131. package/src/styles/base.css +186 -0
  132. package/src/styles/core.css +52 -0
  133. package/src/styles/themes/cupertino.css +197 -0
  134. package/src/styles/themes/material.css +322 -0
  135. package/src/styles/themes/web.css +196 -0
  136. package/src/theme/cupertino.ts +85 -0
  137. package/src/theme/index.ts +5 -0
  138. package/src/theme/material.ts +86 -0
  139. package/src/theme/provider.tsx +76 -0
  140. package/src/theme/types.ts +62 -0
  141. package/src/theme/web.ts +82 -0
@@ -0,0 +1,299 @@
1
+
2
+
3
+ import { Scaffold } from '../layout/Scaffold';
4
+ import { Box } from '../structure/Box';
5
+ import { Text } from '../content/Text';
6
+ import { Button } from '../interactive/Button';
7
+ import { Header } from '../layout/Header';
8
+ import { Row } from '../layout/Row';
9
+ import { Column } from '../layout/Column';
10
+ import { signal, createStore } from '../core/state';
11
+
12
+
13
+
14
+
15
+
16
+
17
+ const lightTheme = {
18
+ primary: '#3B82F6',
19
+ secondary: '#10B981',
20
+ background: '#FFFFFF',
21
+ text: '#1F2937',
22
+ mode: 'light' as const,
23
+ };
24
+
25
+ const darkTheme = {
26
+ primary: '#60A5FA',
27
+ secondary: '#34D399',
28
+ background: '#1F2937',
29
+ text: '#F9FAFB',
30
+ mode: 'dark' as const,
31
+ };
32
+
33
+
34
+ const currentTheme = signal<typeof lightTheme | typeof darkTheme>(lightTheme);
35
+
36
+
37
+ const appStore = createStore({
38
+ user: {
39
+ name: 'Guest',
40
+ email: '',
41
+ isLoggedIn: false,
42
+ },
43
+ notifications: [],
44
+ settings: {
45
+ language: 'pt-BR',
46
+ timezone: 'America/Sao_Paulo',
47
+ },
48
+ });
49
+
50
+
51
+
52
+
53
+
54
+ function AppHeader() {
55
+ const theme = currentTheme.value;
56
+ const user = appStore.getState().user;
57
+
58
+ return Header()
59
+ .height(64)
60
+ .children(
61
+ Row()
62
+ .mainAxisAlignment('spaceBetween')
63
+ .crossAxisAlignment('center')
64
+ .padding('0 24px')
65
+ .children([
66
+ Text('🏗️ My App').variant('h2').color(theme.primary).build(),
67
+
68
+ Row()
69
+ .spacing(16)
70
+ .children([
71
+ Text(user.name).variant('body').build(),
72
+ Button()
73
+ .text(theme.mode === 'light' ? '🌙' : '☀️')
74
+ .variant('outline')
75
+ .onPress(() => {
76
+ currentTheme.value =
77
+ theme.mode === 'light' ? darkTheme : lightTheme;
78
+ })
79
+ .build(),
80
+ ])
81
+ .build(),
82
+ ])
83
+ .build()
84
+ )
85
+ .build();
86
+ }
87
+
88
+ function AppContent() {
89
+ const theme = currentTheme.value;
90
+
91
+ return Box()
92
+ .flex('1')
93
+ .padding('24px')
94
+ .backgroundColor(theme.background)
95
+ .children(
96
+ Column()
97
+ .spacing(24)
98
+ .children([
99
+ Text('Welcome to FiboUI!').variant('h1').color(theme.text).build(),
100
+ Text('This app uses Scaffold for global configuration.')
101
+ .variant('body')
102
+ .color(theme.text)
103
+ .build(),
104
+
105
+ Box()
106
+ .padding('24px')
107
+ .backgroundColor(theme.primary)
108
+ .borderRadius('12px')
109
+ .children(
110
+ Text('Themed Box')
111
+ .variant('h3')
112
+ .color('#FFFFFF')
113
+ .build()
114
+ )
115
+ .build(),
116
+ ])
117
+ .build()
118
+ )
119
+ .build();
120
+ }
121
+
122
+ function AppFooter() {
123
+ const theme = currentTheme.value;
124
+
125
+ return Box()
126
+ .padding('16px 24px')
127
+ .borderTop(`1px solid ${theme.primary}`)
128
+ .backgroundColor(theme.background)
129
+ .children(
130
+ Text('© 2024 My App - Built with FiboUI')
131
+ .variant('caption')
132
+ .color(theme.text)
133
+ .textAlign('center')
134
+ .build()
135
+ )
136
+ .build();
137
+ }
138
+
139
+
140
+
141
+
142
+
143
+ export function App() {
144
+ return (
145
+ Scaffold()
146
+
147
+ .theme(currentTheme.value)
148
+
149
+
150
+ .locale('pt-BR')
151
+
152
+
153
+ .providers({
154
+ store: appStore,
155
+ theme: currentTheme,
156
+ })
157
+
158
+
159
+ .bindSignal(currentTheme)
160
+
161
+
162
+ .children([
163
+ AppHeader(),
164
+ AppContent(),
165
+ AppFooter(),
166
+ ])
167
+ .build()
168
+ );
169
+ }
170
+
171
+
172
+
173
+
174
+
175
+ const ecommerceTheme = {
176
+ primary: '#FF6B6B',
177
+ secondary: '#4ECDC4',
178
+ background: '#F7F7F7',
179
+ text: '#2C3E50',
180
+ };
181
+
182
+ const ecommerceStore = createStore({
183
+ cart: [],
184
+ products: [],
185
+ user: null,
186
+ });
187
+
188
+ export function EcommerceApp() {
189
+ return (
190
+ Scaffold()
191
+ .theme(ecommerceTheme)
192
+ .locale('pt-BR')
193
+ .provider('cart', ecommerceStore)
194
+ .provider('analytics', { track: () => {} })
195
+ .backgroundColor(ecommerceTheme.background)
196
+ .children([
197
+
198
+ Header()
199
+ .height(80)
200
+ .children(
201
+ Row()
202
+ .mainAxisAlignment('spaceBetween')
203
+ .padding('0 48px')
204
+ .children([
205
+ Text('🛒 Shop').variant('h2').build(),
206
+ Text('Cart (0)').variant('body').build(),
207
+ ])
208
+ .build()
209
+ )
210
+ .build(),
211
+
212
+
213
+ Box()
214
+ .flex('1')
215
+ .padding('48px')
216
+ .children(
217
+ Text('Products will go here')
218
+ .variant('h3')
219
+ .build()
220
+ )
221
+ .build(),
222
+ ])
223
+ .build()
224
+ );
225
+ }
226
+
227
+
228
+
229
+
230
+
231
+ export function DashboardApp() {
232
+ return (
233
+ Scaffold()
234
+ .theme(darkTheme)
235
+ .locale('en-US')
236
+ .providers({
237
+ auth: createStore({ user: null, token: null }),
238
+ notifications: createStore({ items: [] }),
239
+ settings: createStore({ theme: 'dark', sidebar: 'expanded' }),
240
+ })
241
+ .children([
242
+
243
+ Box()
244
+ .display('flex')
245
+ .height('100vh')
246
+ .children([
247
+
248
+ Box()
249
+ .width('260px')
250
+ .backgroundColor('#1E293B')
251
+ .children(
252
+ Text('Sidebar').color('#FFF').padding('24px').build()
253
+ )
254
+ .build(),
255
+
256
+
257
+ Box()
258
+ .flex('1')
259
+ .display('flex')
260
+ .flexDirection('column')
261
+ .children([
262
+
263
+ Box()
264
+ .height('64px')
265
+ .backgroundColor('#0F172A')
266
+ .children(
267
+ Text('Dashboard')
268
+ .color('#FFF')
269
+ .padding('0 24px')
270
+ .lineHeight('64px')
271
+ .build()
272
+ )
273
+ .build(),
274
+
275
+
276
+ Box()
277
+ .flex('1')
278
+ .padding('24px')
279
+ .backgroundColor('#0F172A')
280
+ .children(
281
+ Text('Dashboard content')
282
+ .color('#FFF')
283
+ .build()
284
+ )
285
+ .build(),
286
+ ])
287
+ .build(),
288
+ ])
289
+ .build(),
290
+ ])
291
+ .build()
292
+ );
293
+ }
294
+
295
+
296
+
297
+
298
+
299
+
@@ -0,0 +1,149 @@
1
+ import { Box } from '../structure/Box';
2
+ import { Text } from '../content/Text';
3
+ import { Button } from '../interactive/Button';
4
+ import { signal, computed, observable, createStore } from '../core/state';
5
+
6
+
7
+
8
+
9
+
10
+ export function SignalCounterExample() {
11
+ const count = signal(0);
12
+ const doubled = computed(() => count.value * 2);
13
+
14
+ return Box()
15
+ .display('flex')
16
+ .flexDirection('column')
17
+ .gap('16px')
18
+ .padding('24px')
19
+ .border('1px solid #E5E7EB')
20
+ .borderRadius('8px')
21
+ .children([
22
+ Text(`Count: ${count.value}`).variant('h3').build(),
23
+ Text(`Doubled: ${doubled.value}`).variant('body').build(),
24
+ Box()
25
+ .display('flex')
26
+ .gap('8px')
27
+ .children([
28
+ Button()
29
+ .text('Increment')
30
+ .onPress(() => count.value++)
31
+ .build(),
32
+ Button()
33
+ .text('Decrement')
34
+ .onPress(() => count.value--)
35
+ .build(),
36
+ ])
37
+ .build(),
38
+ ])
39
+ .bindSignal(count)
40
+ .bindSignal(doubled)
41
+ .build();
42
+ }
43
+
44
+
45
+
46
+
47
+
48
+ export function ObservableExample() {
49
+ const state = observable({ name: 'John', age: 25 });
50
+
51
+ return Box()
52
+ .display('flex')
53
+ .flexDirection('column')
54
+ .gap('16px')
55
+ .padding('24px')
56
+ .border('1px solid #E5E7EB')
57
+ .borderRadius('8px')
58
+ .children([
59
+ Text(`Name: ${state.get().name}`).variant('body').build(),
60
+ Text(`Age: ${state.get().age}`).variant('body').build(),
61
+ Button()
62
+ .text('Update')
63
+ .onPress(() => state.set({ name: 'Jane', age: 30 }))
64
+ .build(),
65
+ ])
66
+ .observe(state)
67
+ .build();
68
+ }
69
+
70
+
71
+
72
+
73
+
74
+ const appStore = createStore({
75
+ user: { name: 'Guest', loggedIn: false },
76
+ theme: 'light',
77
+ });
78
+
79
+ export function StoreExample() {
80
+ const state = appStore.getState();
81
+
82
+ return Box()
83
+ .display('flex')
84
+ .flexDirection('column')
85
+ .gap('16px')
86
+ .padding('24px')
87
+ .border('1px solid #E5E7EB')
88
+ .borderRadius('8px')
89
+ .children([
90
+ Text(`User: ${state.user.name}`).variant('body').build(),
91
+ Text(`Theme: ${state.theme}`).variant('body').build(),
92
+ Button()
93
+ .text('Login')
94
+ .onPress(() =>
95
+ appStore.setState({ user: { name: 'John Doe', loggedIn: true } })
96
+ )
97
+ .build(),
98
+ ])
99
+ .observer()
100
+ .build();
101
+ }
102
+
103
+
104
+
105
+
106
+
107
+ export function ProviderExample() {
108
+ const theme = { primary: '#3B82F6', secondary: '#10B981' };
109
+
110
+ return Box()
111
+ .provide('theme', theme)
112
+ .padding('24px')
113
+ .children([
114
+ Box()
115
+ .padding('16px')
116
+ .backgroundColor('#3B82F6')
117
+ .borderRadius('8px')
118
+ .children(
119
+ Text('Themed Box').color('#FFF').variant('h3').build()
120
+ )
121
+ .build(),
122
+ ])
123
+ .build();
124
+ }
125
+
126
+
127
+
128
+
129
+
130
+ export function LocalStateExample() {
131
+ return Box()
132
+ .state('count', 0)
133
+ .state('name', 'Guest')
134
+ .display('flex')
135
+ .flexDirection('column')
136
+ .gap('16px')
137
+ .padding('24px')
138
+ .border('1px solid #E5E7EB')
139
+ .borderRadius('8px')
140
+ .children([
141
+ Text('Local State Example').variant('h3').build(),
142
+ Text('Count: 0').variant('body').build(),
143
+ Text('Name: Guest').variant('body').build(),
144
+ Button()
145
+ .text('Increment')
146
+ .build(),
147
+ ])
148
+ .build();
149
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './core';
2
+ export * from './theme';
3
+ export * from './layout';
4
+ export * from './content';
5
+ export * from './interactive';
6
+ export * from './structure';
7
+
8
+ import './styles/base.css';
@@ -0,0 +1,218 @@
1
+ import React, { ReactElement, ReactNode } from 'react';
2
+ import { FiboBuilder, createBuilder } from '../../core/builder';
3
+ import { BaseProps, ButtonVariant } from '../../core/types';
4
+
5
+
6
+ type ExtendedButtonVariant = ButtonVariant | 'ghost' | 'soft' | 'outline' | 'text';
7
+ type ButtonSize = 'sm' | 'md' | 'lg';
8
+ type ButtonShape = 'default' | 'pill' | 'square';
9
+
10
+ const ButtonInner = React.memo((props: any) => {
11
+ const {
12
+ text,
13
+ variant,
14
+ size,
15
+ onPress,
16
+ disabled,
17
+ icon,
18
+ shape,
19
+ shadow,
20
+ className,
21
+ style,
22
+ ...rest
23
+ } = props;
24
+
25
+
26
+ const finalStyle = { ...style };
27
+
28
+
29
+ const sizeStyles: Record<ButtonSize, any> = {
30
+ sm: { padding: '6px 14px', fontSize: '13px', gap: '6px', height: '32px' },
31
+ md: { padding: '10px 22px', fontSize: '15px', gap: '8px', height: '44px' },
32
+ lg: { padding: '16px 32px', fontSize: '17px', gap: '10px', height: '56px' }
33
+ };
34
+ Object.assign(finalStyle, sizeStyles[size as ButtonSize]);
35
+
36
+
37
+ if (shape === 'pill') {
38
+ finalStyle.borderRadius = '9999px';
39
+ } else if (shape === 'square') {
40
+ finalStyle.borderRadius = '12px';
41
+ } else {
42
+ finalStyle.borderRadius = '14px';
43
+ }
44
+
45
+
46
+ if (shadow === 'soft') {
47
+
48
+ finalStyle.boxShadow = '0 8px 20px -6px rgba(59, 130, 246, 0.4)';
49
+ }
50
+
51
+
52
+ if (variant === 'ghost') {
53
+ finalStyle.backgroundColor = 'transparent';
54
+ finalStyle.color = '#4B5563';
55
+ finalStyle.boxShadow = 'none';
56
+ finalStyle.border = '1px solid transparent';
57
+ }
58
+ else if (variant === 'text') {
59
+ finalStyle.backgroundColor = 'transparent';
60
+ finalStyle.color = '#4B5563';
61
+ finalStyle.boxShadow = 'none';
62
+ finalStyle.border = 'none';
63
+ finalStyle.paddingLeft = '8px';
64
+ finalStyle.paddingRight = '8px';
65
+ }
66
+ else if (variant === 'soft') {
67
+
68
+ finalStyle.backgroundColor = '#EEF2FF';
69
+ finalStyle.color = '#4F46E5';
70
+ finalStyle.boxShadow = 'none';
71
+ finalStyle.border = 'none';
72
+ } else if (variant === 'outline') {
73
+ finalStyle.backgroundColor = 'transparent';
74
+ finalStyle.border = '1.5px solid #E5E7EB';
75
+ finalStyle.color = '#374151';
76
+ finalStyle.boxShadow = 'none';
77
+ }
78
+
79
+ const children = [];
80
+ if (icon) {
81
+ children.push(icon);
82
+ }
83
+ if (text) {
84
+ children.push(text);
85
+ }
86
+
87
+ return React.createElement(
88
+ 'button',
89
+ {
90
+ className,
91
+ style: {
92
+ display: 'inline-flex',
93
+ alignItems: 'center',
94
+ justifyContent: 'center',
95
+ cursor: disabled ? 'not-allowed' : 'pointer',
96
+ opacity: disabled ? 0.6 : 1,
97
+ fontWeight: 600,
98
+ whiteSpace: 'nowrap',
99
+ ...finalStyle
100
+ },
101
+ onClick: (e: React.MouseEvent<HTMLButtonElement>) => {
102
+ if (!disabled) {
103
+
104
+ if (document.documentElement.classList.contains('fibo-theme-material')) {
105
+ import('../../core/effects').then(({ createRipple }) => {
106
+ createRipple(e);
107
+ });
108
+ }
109
+ onPress?.();
110
+ }
111
+ },
112
+ disabled: disabled,
113
+ ...rest,
114
+ },
115
+ ...children
116
+ );
117
+ });
118
+
119
+ class ButtonBuilder extends FiboBuilder {
120
+ private _text: string = '';
121
+ private _variant: ExtendedButtonVariant = 'elevated';
122
+ private _size: ButtonSize = 'md';
123
+ private _onPress?: () => void;
124
+ private _disabled: boolean = false;
125
+ private _icon?: ReactNode;
126
+ private _shape: ButtonShape = 'default';
127
+ private _shadow: 'none' | 'soft' = 'none';
128
+
129
+ constructor(text: string = '') {
130
+ super();
131
+ this._text = text;
132
+ }
133
+
134
+ text(value: string): this {
135
+ this._text = value;
136
+ return this;
137
+ }
138
+
139
+ variant(variant: ExtendedButtonVariant): this {
140
+ this._variant = variant;
141
+ return this;
142
+ }
143
+
144
+ size(size: ButtonSize): this {
145
+ this._size = size;
146
+ return this;
147
+ }
148
+
149
+ onPress(handler: () => void): this {
150
+ this._onPress = handler;
151
+ return this;
152
+ }
153
+
154
+ disabled(value: boolean = true): this {
155
+ this._disabled = value;
156
+ return this;
157
+ }
158
+
159
+ icon(icon: ReactNode): this {
160
+ this._icon = icon;
161
+ return this;
162
+ }
163
+
164
+ shape(value: ButtonShape): this {
165
+ this._shape = value;
166
+ return this;
167
+ }
168
+
169
+ shadow(value: 'none' | 'soft'): this {
170
+ this._shadow = value;
171
+ return this;
172
+ }
173
+
174
+ build(): ReactElement {
175
+ const className = [
176
+ 'fibo-button',
177
+ `fibo-button-${this._variant}`,
178
+ 'active:scale-[0.96]',
179
+ 'transform',
180
+ 'transition-all',
181
+ 'duration-200',
182
+ 'ease-out',
183
+ ...this._classNames,
184
+ ]
185
+ .filter(Boolean)
186
+ .join(' ');
187
+
188
+ const props = {
189
+ text: this._text,
190
+ variant: this._variant,
191
+ size: this._size,
192
+ onPress: this._onPress,
193
+ disabled: this._disabled,
194
+ icon: this._icon,
195
+ shape: this._shape,
196
+ shadow: this._shadow,
197
+ className: className,
198
+ style: this.getStyle(),
199
+ ...this._props
200
+ };
201
+
202
+ return React.createElement(ButtonInner, props);
203
+ }
204
+ }
205
+
206
+
207
+ export const Button = createBuilder(ButtonBuilder);
208
+
209
+ export interface ButtonProps extends BaseProps {
210
+ text: string;
211
+ variant?: ExtendedButtonVariant;
212
+ size?: ButtonSize;
213
+ onPress?: () => void;
214
+ disabled?: boolean;
215
+ icon?: ReactNode;
216
+ shape?: ButtonShape;
217
+ shadow?: 'none' | 'soft';
218
+ }