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.
- package/README.md +101 -0
- package/dist/content/Alert/index.d.ts +878 -0
- package/dist/content/Avatar/index.d.ts +886 -0
- package/dist/content/Badge/index.d.ts +887 -0
- package/dist/content/Image/index.d.ts +893 -0
- package/dist/content/Label/index.d.ts +879 -0
- package/dist/content/Progress/index.d.ts +898 -0
- package/dist/content/Skeleton/index.d.ts +879 -0
- package/dist/content/Spinner/index.d.ts +880 -0
- package/dist/content/Text/index.d.ts +878 -0
- package/dist/content/index.d.ts +9 -0
- package/dist/core/StateWrapper.d.ts +28 -0
- package/dist/core/builder.d.ts +50 -0
- package/dist/core/component.d.ts +7 -0
- package/dist/core/effects.d.ts +3 -0
- package/dist/core/icons.d.ts +11 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/state.d.ts +37 -0
- package/dist/core/types.d.ts +51 -0
- package/dist/demo.d.ts +7 -0
- package/dist/effects-Co9C_Dyx.mjs +9 -0
- package/dist/examples/ScaffoldExamples.d.ts +3 -0
- package/dist/examples/StateExamples.d.ts +5 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.esm.js +4622 -0
- package/dist/index.umd.js +251 -0
- package/dist/interactive/Button/index.d.ts +897 -0
- package/dist/interactive/Checkbox/index.d.ts +884 -0
- package/dist/interactive/Combobox/index.d.ts +898 -0
- package/dist/interactive/RadioGroup/index.d.ts +888 -0
- package/dist/interactive/Select/index.d.ts +895 -0
- package/dist/interactive/Switch/index.d.ts +881 -0
- package/dist/interactive/TextField/index.d.ts +892 -0
- package/dist/interactive/Textarea/index.d.ts +890 -0
- package/dist/interactive/index.d.ts +8 -0
- package/dist/layout/Center/index.d.ts +869 -0
- package/dist/layout/Column/index.d.ts +881 -0
- package/dist/layout/Container/index.d.ts +870 -0
- package/dist/layout/DashboardLayout/index.d.ts +870 -0
- package/dist/layout/Header/index.d.ts +870 -0
- package/dist/layout/Line/index.d.ts +872 -0
- package/dist/layout/Row/index.d.ts +879 -0
- package/dist/layout/Scaffold/index.d.ts +878 -0
- package/dist/layout/ScrollView/index.d.ts +879 -0
- package/dist/layout/Sidebar/index.d.ts +870 -0
- package/dist/layout/Spacer/index.d.ts +875 -0
- package/dist/layout/StakentComponents.d.ts +4 -0
- package/dist/layout/index.d.ts +11 -0
- package/dist/structure/Banner/index.d.ts +879 -0
- package/dist/structure/Box/index.d.ts +869 -0
- package/dist/structure/Card/index.d.ts +881 -0
- package/dist/structure/Collapse/index.d.ts +884 -0
- package/dist/structure/Grid/index.d.ts +1757 -0
- package/dist/structure/List/index.d.ts +888 -0
- package/dist/structure/Table/index.d.ts +895 -0
- package/dist/structure/Tags/index.d.ts +876 -0
- package/dist/structure/cards/AssetCard/index.d.ts +884 -0
- package/dist/structure/cards/CollectionCard/index.d.ts +880 -0
- package/dist/structure/cards/ContentCard/index.d.ts +884 -0
- package/dist/structure/cards/ProfileCard/index.d.ts +892 -0
- package/dist/structure/cards/index.d.ts +5 -0
- package/dist/structure/cards/variants/index.d.ts +3490 -0
- package/dist/structure/index.d.ts +9 -0
- package/dist/style.css +1 -0
- package/dist/theme/cupertino.d.ts +3 -0
- package/dist/theme/index.d.ts +5 -0
- package/dist/theme/material.d.ts +3 -0
- package/dist/theme/provider.d.ts +16 -0
- package/dist/theme/types.d.ts +57 -0
- package/dist/theme/web.d.ts +3 -0
- package/package.json +54 -0
- package/src/content/Alert/index.ts +110 -0
- package/src/content/Avatar/index.ts +116 -0
- package/src/content/Badge/index.ts +162 -0
- package/src/content/Image/index.ts +137 -0
- package/src/content/Label/index.ts +66 -0
- package/src/content/Progress/index.ts +378 -0
- package/src/content/Skeleton/index.ts +71 -0
- package/src/content/Spinner/index.ts +139 -0
- package/src/content/Text/index.ts +74 -0
- package/src/content/index.ts +9 -0
- package/src/core/StateWrapper.tsx +105 -0
- package/src/core/builder.ts +259 -0
- package/src/core/component.ts +49 -0
- package/src/core/effects.ts +27 -0
- package/src/core/icons.tsx +57 -0
- package/src/core/index.ts +5 -0
- package/src/core/state.ts +233 -0
- package/src/core/types.ts +62 -0
- package/src/demo.tsx +1045 -0
- package/src/examples/ScaffoldExamples.tsx +299 -0
- package/src/examples/StateExamples.tsx +149 -0
- package/src/index.ts +8 -0
- package/src/interactive/Button/index.ts +218 -0
- package/src/interactive/Checkbox/index.ts +145 -0
- package/src/interactive/Combobox/index.ts +278 -0
- package/src/interactive/RadioGroup/index.ts +124 -0
- package/src/interactive/Select/index.ts +227 -0
- package/src/interactive/Switch/index.ts +123 -0
- package/src/interactive/TextField/index.ts +200 -0
- package/src/interactive/Textarea/index.ts +129 -0
- package/src/interactive/index.ts +8 -0
- package/src/layout/Center/index.ts +34 -0
- package/src/layout/Column/index.ts +101 -0
- package/src/layout/Container/index.ts +28 -0
- package/src/layout/DashboardLayout/index.ts +106 -0
- package/src/layout/Header/index.ts +50 -0
- package/src/layout/Line/index.ts +41 -0
- package/src/layout/Row/index.ts +93 -0
- package/src/layout/Scaffold/index.ts +133 -0
- package/src/layout/ScrollView/index.ts +67 -0
- package/src/layout/Sidebar/index.ts +56 -0
- package/src/layout/Spacer/index.ts +46 -0
- package/src/layout/StakentComponents.tsx +57 -0
- package/src/layout/index.ts +11 -0
- package/src/structure/Banner/index.ts +92 -0
- package/src/structure/Box/index.ts +45 -0
- package/src/structure/Card/index.ts +113 -0
- package/src/structure/Collapse/index.ts +122 -0
- package/src/structure/Grid/index.ts +197 -0
- package/src/structure/List/index.ts +185 -0
- package/src/structure/Table/index.ts +165 -0
- package/src/structure/Tags/index.ts +69 -0
- package/src/structure/cards/AssetCard/index.ts +158 -0
- package/src/structure/cards/CollectionCard/index.ts +95 -0
- package/src/structure/cards/ContentCard/index.ts +127 -0
- package/src/structure/cards/ProfileCard/index.ts +152 -0
- package/src/structure/cards/index.ts +5 -0
- package/src/structure/cards/variants/index.ts +301 -0
- package/src/structure/index.ts +10 -0
- package/src/styles/base.css +186 -0
- package/src/styles/core.css +52 -0
- package/src/styles/themes/cupertino.css +197 -0
- package/src/styles/themes/material.css +322 -0
- package/src/styles/themes/web.css +196 -0
- package/src/theme/cupertino.ts +85 -0
- package/src/theme/index.ts +5 -0
- package/src/theme/material.ts +86 -0
- package/src/theme/provider.tsx +76 -0
- package/src/theme/types.ts +62 -0
- package/src/theme/web.ts +82 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import React, { ReactElement } from 'react';
|
|
2
|
+
import { FiboBuilder, createBuilder } from '../../core/builder';
|
|
3
|
+
import { BaseProps } from '../../core/types';
|
|
4
|
+
|
|
5
|
+
type ProgressVariant = 'default' | 'striped' | 'labeled' | 'circular' | 'segments' | 'knob' | 'steps' | 'chevron' | 'floating' | 'pagination' | 'timeline';
|
|
6
|
+
|
|
7
|
+
interface ProgressItem {
|
|
8
|
+
title?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
date?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const ProgressInner = React.memo((props: any) => {
|
|
14
|
+
const {
|
|
15
|
+
value, max, color, height, variant = 'default',
|
|
16
|
+
label, subLabel, items = [],
|
|
17
|
+
className, style, ...rest
|
|
18
|
+
} = props;
|
|
19
|
+
|
|
20
|
+
const percentage = Math.min(100, Math.max(0, (value / max) * 100));
|
|
21
|
+
const mainColor = color || '#3B82F6';
|
|
22
|
+
|
|
23
|
+
if (variant === 'circular') {
|
|
24
|
+
const size = typeof height === 'number' ? height : 64;
|
|
25
|
+
const strokeWidth = 8;
|
|
26
|
+
const radius = (size - strokeWidth) / 2;
|
|
27
|
+
const circumference = radius * 2 * Math.PI;
|
|
28
|
+
const offset = circumference - (percentage / 100) * circumference;
|
|
29
|
+
|
|
30
|
+
return React.createElement('div', {
|
|
31
|
+
className: `relative inline-flex items-center justify-center ${className}`,
|
|
32
|
+
style: { width: size, height: size, ...style },
|
|
33
|
+
...rest
|
|
34
|
+
}, [
|
|
35
|
+
React.createElement('svg', {
|
|
36
|
+
key: 'svg',
|
|
37
|
+
className: 'transform -rotate-90',
|
|
38
|
+
width: size,
|
|
39
|
+
height: size
|
|
40
|
+
}, [
|
|
41
|
+
React.createElement('circle', {
|
|
42
|
+
key: 'track',
|
|
43
|
+
className: 'text-gray-100',
|
|
44
|
+
stroke: 'currentColor',
|
|
45
|
+
strokeWidth: strokeWidth,
|
|
46
|
+
fill: 'transparent',
|
|
47
|
+
r: radius,
|
|
48
|
+
cx: size / 2,
|
|
49
|
+
cy: size / 2
|
|
50
|
+
}),
|
|
51
|
+
React.createElement('circle', {
|
|
52
|
+
key: 'prog',
|
|
53
|
+
stroke: mainColor,
|
|
54
|
+
strokeWidth: strokeWidth,
|
|
55
|
+
strokeDasharray: circumference,
|
|
56
|
+
strokeDashoffset: offset,
|
|
57
|
+
strokeLinecap: 'round',
|
|
58
|
+
fill: 'transparent',
|
|
59
|
+
r: radius,
|
|
60
|
+
cx: size / 2,
|
|
61
|
+
cy: size / 2,
|
|
62
|
+
className: 'transition-all duration-1000 ease-out'
|
|
63
|
+
})
|
|
64
|
+
]),
|
|
65
|
+
React.createElement('span', {
|
|
66
|
+
key: 'label',
|
|
67
|
+
className: 'absolute text-sm font-bold text-gray-700'
|
|
68
|
+
}, label || `${Math.round(percentage)}%`)
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (variant === 'pagination') {
|
|
73
|
+
const count = 5;
|
|
74
|
+
const activeIndex = Math.floor((percentage / 100) * count);
|
|
75
|
+
|
|
76
|
+
return React.createElement('div', {
|
|
77
|
+
className: `flex items-center gap-2 ${className}`,
|
|
78
|
+
style,
|
|
79
|
+
...rest
|
|
80
|
+
}, Array.from({ length: count }).map((_, i) => {
|
|
81
|
+
const isActive = i === activeIndex;
|
|
82
|
+
return React.createElement('div', {
|
|
83
|
+
key: i,
|
|
84
|
+
className: `h-3 rounded-full transition-all duration-300 ${isActive ? 'w-8' : 'w-3'}`,
|
|
85
|
+
style: { backgroundColor: i <= activeIndex ? mainColor : '#E5E7EB' }
|
|
86
|
+
});
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (variant === 'timeline') {
|
|
91
|
+
const timelineItems = items.length ? items : [
|
|
92
|
+
{ title: 'Order components', date: 'Done' },
|
|
93
|
+
{ title: 'Draft implementation', date: 'In Progress' },
|
|
94
|
+
{ title: 'Verify functionality', date: 'Pending' }
|
|
95
|
+
];
|
|
96
|
+
const activeIndex = Math.floor((percentage / 100) * timelineItems.length);
|
|
97
|
+
|
|
98
|
+
return React.createElement('div', {
|
|
99
|
+
className: `flex flex-col relative ${className}`,
|
|
100
|
+
style,
|
|
101
|
+
...rest
|
|
102
|
+
}, timelineItems.map((item: ProgressItem, i: number) => {
|
|
103
|
+
const isCompleted = i < activeIndex;
|
|
104
|
+
const isCurrent = i === activeIndex;
|
|
105
|
+
const isLast = i === timelineItems.length - 1;
|
|
106
|
+
|
|
107
|
+
const statusColor = isCompleted || isCurrent ? mainColor : '#E5E7EB';
|
|
108
|
+
const iconContent = isCompleted ? React.createElement('span', {}, '✓') : (i + 1);
|
|
109
|
+
|
|
110
|
+
return React.createElement('div', {
|
|
111
|
+
key: i,
|
|
112
|
+
className: `relative flex items-start gap-4 pb-8 last:pb-0`
|
|
113
|
+
}, [
|
|
114
|
+
!isLast && React.createElement('div', {
|
|
115
|
+
key: 'tail',
|
|
116
|
+
className: 'absolute left-[19px] top-10 bottom-0 w-0.5 transition-colors duration-500',
|
|
117
|
+
style: { backgroundColor: isCompleted ? mainColor : '#E5E7EB' }
|
|
118
|
+
}),
|
|
119
|
+
|
|
120
|
+
React.createElement('div', {
|
|
121
|
+
key: 'dot',
|
|
122
|
+
className: `relative z-10 w-10 h-10 rounded-full flex items-center justify-center border-2 bg-white transition-all duration-300 shrink-0 text-sm font-bold shadow-sm`,
|
|
123
|
+
style: {
|
|
124
|
+
borderColor: statusColor,
|
|
125
|
+
color: isCompleted ? '#fff' : (isCurrent ? statusColor : '#9CA3AF'),
|
|
126
|
+
backgroundColor: isCompleted ? statusColor : '#fff'
|
|
127
|
+
}
|
|
128
|
+
}, iconContent),
|
|
129
|
+
|
|
130
|
+
React.createElement('div', { key: 'content', className: 'pt-2' }, [
|
|
131
|
+
React.createElement('div', { className: 'text-sm font-bold text-gray-900 leading-none' }, item.title),
|
|
132
|
+
item.description && React.createElement('div', { className: 'text-xs text-gray-500 mt-1.5' }, item.description),
|
|
133
|
+
item.date && React.createElement('div', { className: 'text-xs font-mono text-gray-400 mt-1' }, item.date)
|
|
134
|
+
])
|
|
135
|
+
]);
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (variant === 'floating') {
|
|
140
|
+
return React.createElement('div', {
|
|
141
|
+
className: `w-full bg-white rounded-xl shadow-sm border border-gray-100 p-4 relative overflow-hidden ${className}`,
|
|
142
|
+
style,
|
|
143
|
+
...rest
|
|
144
|
+
}, [
|
|
145
|
+
React.createElement('div', { key: 'info', className: 'flex justify-between items-center mb-3 px-1' }, [
|
|
146
|
+
React.createElement('span', { key: 'l', className: 'text-sm font-semibold text-gray-700' },
|
|
147
|
+
label ? React.createElement('span', { className: 'text-blue-600 mr-2' }, `${Math.round(percentage)}%`) : null,
|
|
148
|
+
label || 'Update in progress...'
|
|
149
|
+
),
|
|
150
|
+
subLabel && React.createElement('span', { key: 'r', className: 'text-xs font-medium text-gray-400' }, subLabel)
|
|
151
|
+
]),
|
|
152
|
+
React.createElement('div', {
|
|
153
|
+
key: 'track',
|
|
154
|
+
className: 'w-full bg-blue-50 h-1.5 rounded-full overflow-hidden'
|
|
155
|
+
}, React.createElement('div', {
|
|
156
|
+
className: 'h-full rounded-full transition-all duration-1000 ease-out',
|
|
157
|
+
style: { width: `${percentage}%`, backgroundColor: mainColor }
|
|
158
|
+
}))
|
|
159
|
+
]);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (variant === 'chevron') {
|
|
163
|
+
const steps = 3;
|
|
164
|
+
const activeIndex = Math.floor((percentage / 100) * steps);
|
|
165
|
+
|
|
166
|
+
return React.createElement('div', {
|
|
167
|
+
className: `flex w-full rounded-lg overflow-hidden ${className}`,
|
|
168
|
+
style,
|
|
169
|
+
...rest
|
|
170
|
+
}, Array.from({ length: steps }).map((_, i) => {
|
|
171
|
+
const isActive = i <= activeIndex;
|
|
172
|
+
|
|
173
|
+
return React.createElement('div', {
|
|
174
|
+
key: i,
|
|
175
|
+
className: `flex-1 h-10 flex items-center justify-center text-sm font-bold text-white transition-colors duration-300`,
|
|
176
|
+
style: {
|
|
177
|
+
backgroundColor: isActive ? (i === activeIndex ? mainColor : '#60A5FA') : '#E5E7EB',
|
|
178
|
+
clipPath: i === 0
|
|
179
|
+
? 'polygon(0% 0%, 85% 0%, 100% 50%, 85% 100%, 0% 100%)'
|
|
180
|
+
: i === steps - 1
|
|
181
|
+
? 'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 15% 50%)'
|
|
182
|
+
: 'polygon(0% 0%, 85% 0%, 100% 50%, 85% 100%, 0% 100%, 15% 50%)',
|
|
183
|
+
marginLeft: i === 0 ? 0 : '-10px',
|
|
184
|
+
paddingLeft: i === 0 ? 0 : '10px',
|
|
185
|
+
zIndex: steps - i
|
|
186
|
+
}
|
|
187
|
+
}, `Step ${i + 1}`);
|
|
188
|
+
}));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (variant === 'steps') {
|
|
192
|
+
const steps = 3;
|
|
193
|
+
const activeStep = Math.ceil((percentage / 100) * steps);
|
|
194
|
+
|
|
195
|
+
return React.createElement('div', {
|
|
196
|
+
className: `w-full flex items-center justify-between relative ${className}`,
|
|
197
|
+
style: {
|
|
198
|
+
marginTop: '1rem',
|
|
199
|
+
...style
|
|
200
|
+
},
|
|
201
|
+
...rest
|
|
202
|
+
}, [
|
|
203
|
+
React.createElement('div', {
|
|
204
|
+
key: 'line-bg',
|
|
205
|
+
className: 'absolute top-1/2 left-0 w-full h-1.5 bg-gray-200 z-0 transform -translate-y-1/2 rounded-full'
|
|
206
|
+
}),
|
|
207
|
+
React.createElement('div', {
|
|
208
|
+
key: 'line-active',
|
|
209
|
+
className: 'absolute top-1/2 left-0 h-1.5 z-0 transform -translate-y-1/2 transition-all duration-500 rounded-full',
|
|
210
|
+
style: { width: `${percentage}%`, backgroundColor: mainColor }
|
|
211
|
+
}),
|
|
212
|
+
...Array.from({ length: steps }).map((_, i) => {
|
|
213
|
+
const stepNum = i + 1;
|
|
214
|
+
const isActive = stepNum <= activeStep;
|
|
215
|
+
const isCompleted = stepNum < activeStep;
|
|
216
|
+
|
|
217
|
+
return React.createElement('div', {
|
|
218
|
+
key: i,
|
|
219
|
+
className: `relative z-10 w-10 h-10 rounded-full flex items-center justify-center text-sm font-bold transition-all duration-300 border-4 ${isActive ? 'text-white border-white shadow-md' : 'bg-gray-100 text-gray-400 border-gray-50'}`,
|
|
220
|
+
style: { backgroundColor: isActive ? mainColor : undefined }
|
|
221
|
+
}, isCompleted ? React.createElement('span', {}, '✔') : stepNum);
|
|
222
|
+
})
|
|
223
|
+
]);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const heightVal = height || ((variant === 'labeled' || variant === 'knob') ? 12 : 12);
|
|
227
|
+
|
|
228
|
+
if (variant === 'segments') {
|
|
229
|
+
const segCount = 10;
|
|
230
|
+
const activeSegs = Math.round((percentage / 100) * segCount);
|
|
231
|
+
|
|
232
|
+
return React.createElement('div', {
|
|
233
|
+
className: `flex gap-1.5 w-full ${className}`,
|
|
234
|
+
style,
|
|
235
|
+
...rest
|
|
236
|
+
},
|
|
237
|
+
Array.from({ length: segCount }).map((_, i) => React.createElement('div', {
|
|
238
|
+
key: i,
|
|
239
|
+
className: `h-3 flex-1 rounded-sm transition-all duration-300 first:rounded-l-full last:rounded-r-full`,
|
|
240
|
+
style: {
|
|
241
|
+
height: height || 12,
|
|
242
|
+
backgroundColor: i < activeSegs ? mainColor : '#E5E7EB'
|
|
243
|
+
}
|
|
244
|
+
}))
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
let innerContent: ReactElement | null = null;
|
|
249
|
+
|
|
250
|
+
if (variant === 'striped') {
|
|
251
|
+
innerContent = React.createElement('div', {
|
|
252
|
+
className: 'w-full h-full opacity-30 animate-[stripes_1s_linear_infinite]',
|
|
253
|
+
style: {
|
|
254
|
+
backgroundImage: 'linear-gradient(45deg,rgba(255,255,255,.25) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.25) 50%,rgba(255,255,255,.25) 75%,transparent 75%,transparent)',
|
|
255
|
+
backgroundSize: '20px 20px'
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const labelElement = variant === 'labeled' ? React.createElement('div', {
|
|
261
|
+
className: 'absolute -top-12 transform -translate-x-1/2 bg-slate-800 text-white text-xs font-bold py-1.5 px-3 rounded-lg shadow-xl whitespace-nowrap',
|
|
262
|
+
style: { left: `${percentage}%` }
|
|
263
|
+
}, [
|
|
264
|
+
label || `${Math.round(percentage)}%`,
|
|
265
|
+
React.createElement('div', { key: 'arrow', className: 'absolute -bottom-1 left-1/2 transform -translate-x-1/2 w-2 h-2 bg-slate-800 rotate-45' })
|
|
266
|
+
]) : null;
|
|
267
|
+
|
|
268
|
+
const knobElement = variant === 'knob' ? React.createElement('div', {
|
|
269
|
+
className: 'absolute top-1/2 right-0 w-7 h-7 bg-white rounded-full shadow-lg border-4 transform translate-x-1/2 -translate-y-1/2 flex items-center justify-center',
|
|
270
|
+
style: { borderColor: mainColor }
|
|
271
|
+
}, React.createElement('div', { className: 'w-1.5 h-1.5 rounded-full', style: { backgroundColor: mainColor } })) : null;
|
|
272
|
+
|
|
273
|
+
return React.createElement('div', {
|
|
274
|
+
className: `relative w-full ${variant === 'labeled' ? 'mt-8' : ''}`,
|
|
275
|
+
...rest
|
|
276
|
+
}, [
|
|
277
|
+
labelElement,
|
|
278
|
+
React.createElement('div', {
|
|
279
|
+
key: 'track',
|
|
280
|
+
className: `w-full bg-slate-100 rounded-full ${className}`,
|
|
281
|
+
style: {
|
|
282
|
+
width: '100%',
|
|
283
|
+
height: heightVal,
|
|
284
|
+
...style
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
React.createElement('div', {
|
|
288
|
+
className: `h-full transition-all duration-1000 ease-out rounded-full flex items-center justify-center relative`,
|
|
289
|
+
style: {
|
|
290
|
+
width: `${percentage}%`,
|
|
291
|
+
backgroundColor: mainColor
|
|
292
|
+
}
|
|
293
|
+
}, [innerContent, knobElement])
|
|
294
|
+
)
|
|
295
|
+
]);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
class ProgressBuilder extends FiboBuilder {
|
|
299
|
+
private _value: number = 0;
|
|
300
|
+
private _max: number = 100;
|
|
301
|
+
private _color?: string;
|
|
302
|
+
private _height?: number | string;
|
|
303
|
+
private _variant: ProgressVariant = 'default';
|
|
304
|
+
private _label?: string;
|
|
305
|
+
private _subLabel?: string;
|
|
306
|
+
private _items?: ProgressItem[];
|
|
307
|
+
|
|
308
|
+
value(current: number): this {
|
|
309
|
+
this._value = current;
|
|
310
|
+
return this;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
max(total: number): this {
|
|
314
|
+
this._max = total;
|
|
315
|
+
return this;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
color(hex: string): this {
|
|
319
|
+
this._color = hex;
|
|
320
|
+
return this;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
height(val: number | string): this {
|
|
324
|
+
this._height = val;
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
variant(val: ProgressVariant): this {
|
|
329
|
+
this._variant = val;
|
|
330
|
+
return this;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
label(text: string): this {
|
|
334
|
+
this._label = text;
|
|
335
|
+
return this;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
subLabel(text: string): this {
|
|
339
|
+
this._subLabel = text;
|
|
340
|
+
return this;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
items(list: ProgressItem[]): this {
|
|
344
|
+
this._items = list;
|
|
345
|
+
return this;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
build(): ReactElement {
|
|
349
|
+
const props = {
|
|
350
|
+
value: this._value,
|
|
351
|
+
max: this._max,
|
|
352
|
+
color: this._color,
|
|
353
|
+
height: this._height,
|
|
354
|
+
variant: this._variant,
|
|
355
|
+
label: this._label,
|
|
356
|
+
subLabel: this._subLabel,
|
|
357
|
+
items: this._items,
|
|
358
|
+
className: this.getClassName(),
|
|
359
|
+
style: this.getStyle(),
|
|
360
|
+
...this._props
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
return React.createElement(ProgressInner, props);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
export const Progress = createBuilder(ProgressBuilder);
|
|
369
|
+
|
|
370
|
+
export interface ProgressProps extends BaseProps {
|
|
371
|
+
value: number;
|
|
372
|
+
max?: number;
|
|
373
|
+
color?: string;
|
|
374
|
+
variant?: ProgressVariant;
|
|
375
|
+
label?: string;
|
|
376
|
+
subLabel?: string;
|
|
377
|
+
items?: ProgressItem[];
|
|
378
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React, { ReactElement } from 'react';
|
|
2
|
+
import { FiboBuilder, createBuilder } from '../../core/builder';
|
|
3
|
+
import { BaseProps } from '../../core/types';
|
|
4
|
+
|
|
5
|
+
const SkeletonInner = React.memo((props: any) => {
|
|
6
|
+
const { width, height, shape, className, style, ...rest } = props;
|
|
7
|
+
|
|
8
|
+
const baseClasses = ['animate-pulse', 'bg-gray-200', 'loading-skeleton'];
|
|
9
|
+
|
|
10
|
+
if (shape === 'circle') baseClasses.push('rounded-full');
|
|
11
|
+
else if (shape === 'rounded-sm') baseClasses.push('rounded-sm');
|
|
12
|
+
else if (shape === 'rounded-md') baseClasses.push('rounded-md');
|
|
13
|
+
else if (shape === 'rounded-lg') baseClasses.push('rounded-lg');
|
|
14
|
+
else if (shape === 'square') baseClasses.push('rounded-none');
|
|
15
|
+
else baseClasses.push('rounded');
|
|
16
|
+
|
|
17
|
+
return React.createElement('div', {
|
|
18
|
+
className: [...baseClasses, className].filter(Boolean).join(' '),
|
|
19
|
+
style: {
|
|
20
|
+
width: width,
|
|
21
|
+
height: height,
|
|
22
|
+
...style
|
|
23
|
+
},
|
|
24
|
+
...rest
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
type SkeletonShape = 'circle' | 'square' | 'rounded' | 'rounded-sm' | 'rounded-md' | 'rounded-lg';
|
|
29
|
+
|
|
30
|
+
class SkeletonBuilder extends FiboBuilder {
|
|
31
|
+
private _width: string | number = '100%';
|
|
32
|
+
private _height: string | number = '20px';
|
|
33
|
+
private _shape: SkeletonShape = 'rounded';
|
|
34
|
+
|
|
35
|
+
width(value: string | number): this {
|
|
36
|
+
this._width = value;
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
height(value: string | number): this {
|
|
41
|
+
this._height = value;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
shape(value: SkeletonShape): this {
|
|
46
|
+
this._shape = value;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
build(): ReactElement {
|
|
51
|
+
const props = {
|
|
52
|
+
width: this._width,
|
|
53
|
+
height: this._height,
|
|
54
|
+
shape: this._shape,
|
|
55
|
+
className: this.getClassName(),
|
|
56
|
+
style: this.getStyle(),
|
|
57
|
+
...this._props
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
return React.createElement(SkeletonInner, props);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
export const Skeleton = createBuilder(SkeletonBuilder);
|
|
66
|
+
|
|
67
|
+
export interface SkeletonProps extends BaseProps {
|
|
68
|
+
width?: string | number;
|
|
69
|
+
height?: string | number;
|
|
70
|
+
shape?: SkeletonShape;
|
|
71
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React, { ReactElement } from 'react';
|
|
2
|
+
import { FiboBuilder, createBuilder } from '../../core/builder';
|
|
3
|
+
import { BaseProps } from '../../core/types';
|
|
4
|
+
|
|
5
|
+
type SpinnerVariant = 'circle' | 'dots' | 'pulse' | 'blocks';
|
|
6
|
+
type SpinnerSize = 'sm' | 'md' | 'lg' | 'xl' | number;
|
|
7
|
+
|
|
8
|
+
const SpinnerInner = React.memo((props: any) => {
|
|
9
|
+
const { size, color, variant = 'circle', className, style, ...rest } = props;
|
|
10
|
+
|
|
11
|
+
const sizeMap: Record<string, number> = {
|
|
12
|
+
sm: 16,
|
|
13
|
+
md: 24,
|
|
14
|
+
lg: 32,
|
|
15
|
+
xl: 48
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const pixelSize = typeof size === 'number' ? size : (sizeMap[size] || 24);
|
|
19
|
+
const mainColor = color || "currentColor";
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const containerProps = {
|
|
23
|
+
className: `fibo-spinner ${className}`,
|
|
24
|
+
style: { width: pixelSize, height: pixelSize, ...style },
|
|
25
|
+
...rest
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
if (variant === 'dots') {
|
|
29
|
+
return React.createElement('div', { ...containerProps, className: `${containerProps.className} flex items-center justify-between` },
|
|
30
|
+
[0, 1, 2].map(i => React.createElement('div', {
|
|
31
|
+
key: i,
|
|
32
|
+
className: 'w-[25%] h-[25%] rounded-full animate-bounce',
|
|
33
|
+
style: {
|
|
34
|
+
backgroundColor: mainColor,
|
|
35
|
+
animationDelay: `${i * 0.1}s`
|
|
36
|
+
}
|
|
37
|
+
}))
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (variant === 'pulse') {
|
|
42
|
+
return React.createElement('div', { ...containerProps, className: `${containerProps.className} relative flex items-center justify-center` },
|
|
43
|
+
[
|
|
44
|
+
React.createElement('div', {
|
|
45
|
+
key: 'ring',
|
|
46
|
+
className: 'absolute inset-0 rounded-full opacity-75 animate-ping',
|
|
47
|
+
style: { backgroundColor: mainColor }
|
|
48
|
+
}),
|
|
49
|
+
React.createElement('div', {
|
|
50
|
+
key: 'dot',
|
|
51
|
+
className: 'relative rounded-full h-[75%] w-[75%]',
|
|
52
|
+
style: { backgroundColor: mainColor }
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (variant === 'blocks') {
|
|
59
|
+
return React.createElement('div', { ...containerProps, className: `${containerProps.className} grid grid-cols-2 gap-[10%] p-[10%]` },
|
|
60
|
+
[0, 1, 2, 3].map(i => React.createElement('div', {
|
|
61
|
+
key: i,
|
|
62
|
+
className: 'w-full h-full bg-current animate-pulse',
|
|
63
|
+
style: {
|
|
64
|
+
backgroundColor: mainColor,
|
|
65
|
+
animationDelay: `${i * 0.15}s`,
|
|
66
|
+
opacity: 0.6
|
|
67
|
+
}
|
|
68
|
+
}))
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
return React.createElement(
|
|
74
|
+
'div',
|
|
75
|
+
{ ...containerProps, className: `${containerProps.className} animate-spin` },
|
|
76
|
+
React.createElement("svg", {
|
|
77
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
78
|
+
fill: "none",
|
|
79
|
+
viewBox: "0 0 24 24",
|
|
80
|
+
style: { width: '100%', height: '100%' }
|
|
81
|
+
},
|
|
82
|
+
React.createElement("circle", {
|
|
83
|
+
className: "opacity-20",
|
|
84
|
+
cx: "12",
|
|
85
|
+
cy: "12",
|
|
86
|
+
r: "10",
|
|
87
|
+
stroke: mainColor,
|
|
88
|
+
strokeWidth: "4"
|
|
89
|
+
}),
|
|
90
|
+
React.createElement("path", {
|
|
91
|
+
className: "",
|
|
92
|
+
fill: mainColor,
|
|
93
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
94
|
+
}))
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
class SpinnerBuilder extends FiboBuilder {
|
|
99
|
+
private _size: SpinnerSize = 'md';
|
|
100
|
+
private _color?: string;
|
|
101
|
+
private _variant: SpinnerVariant = 'circle';
|
|
102
|
+
|
|
103
|
+
size(value: SpinnerSize): this {
|
|
104
|
+
this._size = value;
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
color(value: string): this {
|
|
109
|
+
this._color = value;
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
variant(value: SpinnerVariant): this {
|
|
114
|
+
this._variant = value;
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
build(): ReactElement {
|
|
119
|
+
const props = {
|
|
120
|
+
size: this._size,
|
|
121
|
+
color: this._color,
|
|
122
|
+
variant: this._variant,
|
|
123
|
+
className: this.getClassName(),
|
|
124
|
+
style: this.getStyle(),
|
|
125
|
+
...this._props
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return React.createElement(SpinnerInner, props);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
export const Spinner = createBuilder(SpinnerBuilder);
|
|
134
|
+
|
|
135
|
+
export interface SpinnerProps extends BaseProps {
|
|
136
|
+
size?: SpinnerSize;
|
|
137
|
+
color?: string;
|
|
138
|
+
variant?: SpinnerVariant;
|
|
139
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { ReactElement } from 'react';
|
|
2
|
+
import { FiboBuilder, createBuilder } from '../../core/builder';
|
|
3
|
+
import { BaseProps, TextType } from '../../core/types';
|
|
4
|
+
|
|
5
|
+
const TextInner = React.memo((props: any) => {
|
|
6
|
+
const { text, type, className, style, ...rest } = props;
|
|
7
|
+
|
|
8
|
+
const elementMap: Record<TextType, string> = {
|
|
9
|
+
h1: 'h1',
|
|
10
|
+
h2: 'h2',
|
|
11
|
+
h3: 'h3',
|
|
12
|
+
h4: 'h4',
|
|
13
|
+
h5: 'h5',
|
|
14
|
+
h6: 'h6',
|
|
15
|
+
body: 'p',
|
|
16
|
+
caption: 'span',
|
|
17
|
+
label: 'label',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return React.createElement(
|
|
21
|
+
elementMap[type as TextType],
|
|
22
|
+
{
|
|
23
|
+
className: `fibo-text fibo-text-${type} ${className}`,
|
|
24
|
+
style,
|
|
25
|
+
...rest,
|
|
26
|
+
},
|
|
27
|
+
text
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
class TextBuilder extends FiboBuilder {
|
|
32
|
+
private _text: string = '';
|
|
33
|
+
private _type: TextType = 'body';
|
|
34
|
+
|
|
35
|
+
constructor(text: string = '') {
|
|
36
|
+
super();
|
|
37
|
+
this._text = text;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
text(value: string): this {
|
|
41
|
+
this._text = value;
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type(type: TextType): this {
|
|
46
|
+
this._type = type;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
variant(variant: TextType): this {
|
|
51
|
+
this._type = variant;
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
build(): ReactElement {
|
|
56
|
+
const props = {
|
|
57
|
+
text: this._text,
|
|
58
|
+
type: this._type,
|
|
59
|
+
className: this.getClassName(),
|
|
60
|
+
style: this.getStyle(),
|
|
61
|
+
...this._props
|
|
62
|
+
};
|
|
63
|
+
return React.createElement(TextInner, props);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
export const Text = createBuilder(TextBuilder);
|
|
69
|
+
|
|
70
|
+
export interface TextProps extends BaseProps {
|
|
71
|
+
text: string;
|
|
72
|
+
type?: TextType;
|
|
73
|
+
variant?: TextType;
|
|
74
|
+
}
|