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,197 @@
1
+ import React, { ReactElement, ReactNode } from 'react';
2
+ import { FiboBuilder, createBuilder } from '../../core/builder';
3
+ import { BaseProps } from '../../core/types';
4
+
5
+ type GridVariant = 'standard' | 'masonry' | 'bento';
6
+ type GridGap = 'none' | 'sm' | 'md' | 'lg' | 'xl' | number;
7
+ type GridCols = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
8
+
9
+ interface ResponsiveCols {
10
+ sm?: GridCols;
11
+ md?: GridCols;
12
+ lg?: GridCols;
13
+ xl?: GridCols;
14
+ }
15
+
16
+ const GridInner = React.memo((props: any) => {
17
+ const {
18
+ children,
19
+ variant = 'standard',
20
+ columns = 1,
21
+ gap = 'md',
22
+ className,
23
+ style,
24
+ ...rest
25
+ } = props;
26
+
27
+
28
+ const getGapClass = (g: GridGap) => {
29
+ if (typeof g === 'number') return '';
30
+ const gaps: Record<string, string> = {
31
+ none: 'gap-0',
32
+ sm: 'gap-2',
33
+ md: 'gap-4',
34
+ lg: 'gap-6',
35
+ xl: 'gap-8'
36
+ };
37
+ return gaps[g] || 'gap-4';
38
+ };
39
+
40
+ const getGapStyle = (g: GridGap) => {
41
+ if (typeof g === 'number') return g + 'px';
42
+ return undefined;
43
+ };
44
+
45
+
46
+ const getColsClass = (cols: GridCols | ResponsiveCols) => {
47
+ if (typeof cols === 'number') return `grid-cols-${cols}`;
48
+
49
+
50
+ let classes = [];
51
+ if (cols.sm) classes.push(`sm:grid-cols-${cols.sm}`);
52
+ if (cols.md) classes.push(`md:grid-cols-${cols.md}`);
53
+ if (cols.lg) classes.push(`lg:grid-cols-${cols.lg}`);
54
+ if (cols.xl) classes.push(`xl:grid-cols-${cols.xl}`);
55
+
56
+
57
+ return classes.join(' ') || 'grid-cols-1';
58
+ };
59
+
60
+
61
+ if (variant === 'masonry') {
62
+ const getMasonryColsClass = (cols: GridCols | ResponsiveCols) => {
63
+ if (typeof cols === 'number') return `columns-${cols}`;
64
+ let classes = [];
65
+ if (cols.sm) classes.push(`sm:columns-${cols.sm}`);
66
+ if (cols.md) classes.push(`md:columns-${cols.md}`);
67
+ if (cols.lg) classes.push(`lg:columns-${cols.lg}`);
68
+ if (cols.xl) classes.push(`xl:columns-${cols.xl}`);
69
+ return classes.join(' ') || 'columns-1';
70
+ };
71
+
72
+ return React.createElement('div', {
73
+ className: `${getMasonryColsClass(columns)} ${getGapClass(gap)} space-y-4 ${className}`,
74
+ style: {
75
+ columnGap: getGapStyle(gap),
76
+ ...style
77
+ },
78
+ ...rest
79
+ }, React.Children.map(children, child =>
80
+ React.createElement('div', { className: 'break-inside-avoid mb-4' }, child)
81
+ ));
82
+ }
83
+
84
+
85
+ return React.createElement('div', {
86
+ className: `grid ${getColsClass(columns)} ${getGapClass(gap)} ${className}`,
87
+ style: {
88
+ gap: getGapStyle(gap),
89
+ ...style
90
+ },
91
+ ...rest
92
+ }, children);
93
+ });
94
+
95
+
96
+ const GridItemInner = React.memo((props: any) => {
97
+ const { children, colSpan, rowSpan, className, style, ...rest } = props;
98
+
99
+ const getSpanClass = () => {
100
+ let classes = [];
101
+ if (colSpan) classes.push(`col-span-${colSpan}`);
102
+ if (rowSpan) classes.push(`row-span-${rowSpan}`);
103
+ return classes.join(' ');
104
+ };
105
+
106
+ return React.createElement('div', {
107
+ className: `${getSpanClass()} ${className}`,
108
+ style,
109
+ ...rest
110
+ }, children);
111
+ });
112
+
113
+
114
+ class GridBuilder extends FiboBuilder {
115
+ private _variant: GridVariant = 'standard';
116
+ private _columns: GridCols | ResponsiveCols = 1;
117
+ private _gap: GridGap = 'md';
118
+ protected _children: ReactNode[] = [];
119
+
120
+ variant(v: GridVariant): this {
121
+ this._variant = v;
122
+ return this;
123
+ }
124
+
125
+ columns(cols: GridCols | ResponsiveCols): this {
126
+ this._columns = cols;
127
+ return this;
128
+ }
129
+
130
+ gap(g: GridGap): this {
131
+ this._gap = g;
132
+ return this;
133
+ }
134
+
135
+ children(nodes: ReactNode[]): this {
136
+ this._children = nodes;
137
+ return this;
138
+ }
139
+
140
+ build(): ReactElement {
141
+ const props = {
142
+ variant: this._variant,
143
+ columns: this._columns,
144
+ gap: this._gap,
145
+ children: this._children,
146
+ className: this.getClassName(),
147
+ style: this.getStyle(),
148
+ ...this._props
149
+ };
150
+
151
+ return React.createElement(GridInner, props);
152
+ }
153
+ }
154
+
155
+ class GridItemBuilder extends FiboBuilder {
156
+ private _colSpan?: number;
157
+ private _rowSpan?: number;
158
+ protected _children: ReactNode[] = [];
159
+
160
+ colSpan(span: number): this {
161
+ this._colSpan = span;
162
+ return this;
163
+ }
164
+
165
+ rowSpan(span: number): this {
166
+ this._rowSpan = span;
167
+ return this;
168
+ }
169
+
170
+ children(nodes: ReactNode[]): this {
171
+ this._children = nodes;
172
+ return this;
173
+ }
174
+
175
+ build(): ReactElement {
176
+ const props = {
177
+ colSpan: this._colSpan,
178
+ rowSpan: this._rowSpan,
179
+ children: this._children,
180
+ className: this.getClassName(),
181
+ style: this.getStyle(),
182
+ ...this._props
183
+ };
184
+ return React.createElement(GridItemInner, props);
185
+ }
186
+ }
187
+
188
+
189
+ export const Grid = createBuilder(GridBuilder);
190
+
191
+ export const GridItem = createBuilder(GridItemBuilder);
192
+
193
+ export interface GridProps extends BaseProps {
194
+ variant?: GridVariant;
195
+ columns?: GridCols | ResponsiveCols;
196
+ gap?: GridGap;
197
+ }
@@ -0,0 +1,185 @@
1
+ import React, { ReactElement, ReactNode } from 'react';
2
+ import { FiboBuilder, createBuilder } from '../../core/builder';
3
+ import { BaseProps } from '../../core/types';
4
+ import { Box } from '../Box';
5
+
6
+ type ListVariant = 'default' | 'card' | 'floating';
7
+
8
+ const ListInner = React.memo((props: any) => {
9
+ const {
10
+ items,
11
+ renderItem,
12
+ variant,
13
+ separator,
14
+ loading,
15
+ threshold,
16
+ onEndReached,
17
+ className,
18
+ style
19
+ } = props;
20
+
21
+ const observerRef = React.useRef<HTMLDivElement>(null);
22
+
23
+ React.useEffect(() => {
24
+ if (!onEndReached || loading) return;
25
+
26
+ const observer = new IntersectionObserver(
27
+ (entries) => {
28
+ if (entries[0].isIntersecting) {
29
+ onEndReached?.();
30
+ }
31
+ },
32
+ { threshold: threshold }
33
+ );
34
+
35
+ if (observerRef.current) {
36
+ observer.observe(observerRef.current);
37
+ }
38
+
39
+ return () => observer.disconnect();
40
+ }, [loading, items.length, onEndReached, threshold]);
41
+
42
+ const variantStyles: Record<ListVariant, any> = {
43
+ default: { gap: '0px' },
44
+ card: { gap: '12px' },
45
+ floating: { gap: '8px' }
46
+ };
47
+
48
+ const itemContainerStyles: Record<ListVariant, any> = {
49
+ default: {
50
+ padding: '12px 16px',
51
+ borderBottom: separator ? '1px solid #F3F4F6' : 'none',
52
+ backgroundColor: 'transparent',
53
+ transition: 'background-color 0.2s'
54
+ },
55
+ card: {
56
+ padding: '16px',
57
+ backgroundColor: '#fff',
58
+ borderRadius: '16px',
59
+ boxShadow: '0 2px 8px -2px rgba(0,0,0,0.05)',
60
+ border: '1px solid #F3F4F6',
61
+ transition: 'transform 0.2s, box-shadow 0.2s'
62
+ },
63
+ floating: {
64
+ padding: '8px 12px',
65
+ borderRadius: '12px',
66
+ backgroundColor: 'transparent',
67
+ transition: 'background-color 0.2s'
68
+ }
69
+ };
70
+
71
+ const variantClasses: Record<ListVariant, string[]> = {
72
+ default: ['hover:bg-gray-50', 'first:rounded-t-xl', 'last:rounded-b-xl'],
73
+ card: ['hover:-translate-y-0.5', 'hover:shadow-md'],
74
+ floating: ['hover:bg-white', 'hover:shadow-sm']
75
+ };
76
+
77
+ return Box()
78
+ .className(className)
79
+ .classNames(['flex', 'flex-col', 'w-full'])
80
+ .style({
81
+ ...variantStyles[variant as ListVariant],
82
+ ...style
83
+ })
84
+ .children(
85
+ React.createElement(React.Fragment, {}, [
86
+ ...items.map((item: any, index: number) =>
87
+ React.cloneElement(
88
+ Box()
89
+ .style(itemContainerStyles[variant as ListVariant])
90
+ .classNames(variantClasses[variant as ListVariant])
91
+ .children(
92
+ renderItem ? renderItem(item, index) : null
93
+ )
94
+ .build(),
95
+ { key: `item-${index}` }
96
+ )
97
+ ),
98
+
99
+ onEndReached && (
100
+ React.createElement('div', {
101
+ ref: observerRef,
102
+ className: 'py-4 flex justify-center w-full'
103
+ }, loading ? (
104
+
105
+ React.createElement('div', { className: 'animate-spin rounded-full h-5 w-5 border-2 border-gray-300 border-b-blue-600' })
106
+ ) : (
107
+
108
+ React.createElement('div', { style: { height: '20px' } })
109
+ ))
110
+ )
111
+ ])
112
+ )
113
+ .build();
114
+ });
115
+
116
+ class ListBuilder<T = any> extends FiboBuilder {
117
+ private _items: T[] = [];
118
+ private _renderItem?: (item: T, index: number) => ReactNode;
119
+ private _variant: ListVariant = 'default';
120
+ private _separator: boolean = false;
121
+
122
+ items(items: T[]): this {
123
+ this._items = items;
124
+ return this;
125
+ }
126
+
127
+ renderItem(fn: (item: T, index: number) => ReactNode): this {
128
+ this._renderItem = fn;
129
+ return this;
130
+ }
131
+
132
+ variant(variant: ListVariant): this {
133
+ this._variant = variant;
134
+ return this;
135
+ }
136
+
137
+ separator(show: boolean = true): this {
138
+ this._separator = show;
139
+ return this;
140
+ }
141
+
142
+ private _onEndReached?: () => void;
143
+ private _loading: boolean = false;
144
+ private _threshold: number = 0.5;
145
+
146
+ onEndReached(handler: () => void): this {
147
+ this._onEndReached = handler;
148
+ return this;
149
+ }
150
+
151
+ loading(isLoading: boolean): this {
152
+ this._loading = isLoading;
153
+ return this;
154
+ }
155
+
156
+ threshold(value: number): this {
157
+ this._threshold = value;
158
+ return this;
159
+ }
160
+
161
+ build(): ReactElement {
162
+ const props = {
163
+ items: this._items,
164
+ renderItem: this._renderItem,
165
+ variant: this._variant,
166
+ separator: this._separator,
167
+ loading: this._loading,
168
+ threshold: this._threshold,
169
+ onEndReached: this._onEndReached,
170
+ className: this.getClassName(),
171
+ style: this.getStyle()
172
+ };
173
+ return React.createElement(ListInner, props);
174
+ }
175
+ }
176
+
177
+
178
+ export const List = createBuilder(ListBuilder);
179
+
180
+ export interface ListProps<T = any> extends BaseProps {
181
+ items: T[];
182
+ renderItem?: (item: T, index: number) => ReactNode;
183
+ variant?: ListVariant;
184
+ separator?: boolean;
185
+ }
@@ -0,0 +1,165 @@
1
+ import React, { ReactElement, ReactNode } from 'react';
2
+ import { FiboBuilder, createBuilder } from '../../core/builder';
3
+ import { BaseProps } from '../../core/types';
4
+ import { Box } from '../Box';
5
+
6
+ type TableVariant = 'default' | 'clean';
7
+ type TableDensity = 'compact' | 'standard' | 'relaxed';
8
+
9
+ export interface TableColumn<T = any> {
10
+ header: string;
11
+ accessor?: keyof T;
12
+ render?: (item: T) => ReactNode;
13
+ width?: string;
14
+ align?: 'left' | 'center' | 'right';
15
+ }
16
+
17
+ const TableInner = React.memo((props: any) => {
18
+ const {
19
+ data,
20
+ columns,
21
+ variant,
22
+ density,
23
+ striped,
24
+ width,
25
+ className,
26
+ style
27
+ } = props;
28
+
29
+ const tableStyles: React.CSSProperties = {
30
+ width: '100%',
31
+ borderCollapse: 'separate',
32
+ borderSpacing: '0',
33
+ ...style
34
+ };
35
+
36
+ if (width) {
37
+ tableStyles.width = typeof width === 'number' ? `${width}px` : width;
38
+ }
39
+
40
+ const containerClass = variant === 'clean'
41
+ ? ['bg-white', 'rounded-2xl', 'border', 'border-gray-100', 'overflow-hidden', 'shadow-sm']
42
+ : [];
43
+
44
+
45
+ const cellPadding: Record<TableDensity, string> = {
46
+ compact: '10px 16px',
47
+ standard: '16px 24px',
48
+ relaxed: '24px 32px'
49
+ };
50
+ const padding = cellPadding[density as TableDensity];
51
+
52
+ return Box()
53
+ .className(className)
54
+ .classNames(containerClass)
55
+ .children(
56
+ React.createElement('table', { style: tableStyles }, [
57
+
58
+ React.createElement('thead', { key: 'thead', className: 'bg-gray-50/50' },
59
+ React.createElement('tr', {},
60
+ columns.map((col: any, i: number) =>
61
+ React.createElement('th', {
62
+ key: i,
63
+ style: {
64
+ textAlign: col.align || 'left',
65
+ padding: padding,
66
+ width: col.width
67
+ },
68
+ className: 'text-xs font-bold text-gray-400 uppercase tracking-widest'
69
+ }, col.header)
70
+ )
71
+ )
72
+ ),
73
+
74
+ React.createElement('tbody', { key: 'tbody' },
75
+ data.map((row: any, i: number) =>
76
+ React.createElement('tr', {
77
+ key: i,
78
+
79
+ className: `group transition-all duration-200 border-b border-gray-50 last:border-b-0 ${
80
+ striped && i % 2 !== 0 ? 'bg-gray-50/30' : 'bg-transparent'
81
+ } ${variant === 'clean' ? 'hover:bg-white hover:shadow-md hover:scale-[1.002] hover:z-10 relative' : 'hover:bg-gray-50/50'}`
82
+ },
83
+ columns.map((col: any, j: number) =>
84
+ React.createElement('td', {
85
+ key: j,
86
+ style: {
87
+ textAlign: col.align || 'left',
88
+ padding: padding,
89
+ borderTop: variant === 'default' ? '1px solid #F3F4F6' : 'none'
90
+ },
91
+ className: 'text-sm text-gray-900 font-medium'
92
+ },
93
+ col.render ? col.render(row) : (col.accessor ? row[col.accessor] as ReactNode : null)
94
+ )
95
+ )
96
+ )
97
+ )
98
+ )
99
+ ])
100
+ ).build();
101
+ });
102
+
103
+ class TableBuilder<T = any> extends FiboBuilder {
104
+ private _data: T[] = [];
105
+ private _columns: TableColumn<T>[] = [];
106
+ private _variant: TableVariant = 'clean';
107
+ private _density: TableDensity = 'standard';
108
+ private _striped: boolean = false;
109
+ private _width: string | number | undefined;
110
+
111
+ data(items: T[]): this {
112
+ this._data = items;
113
+ return this;
114
+ }
115
+
116
+ columns(cols: TableColumn<T>[]): this {
117
+ this._columns = cols;
118
+ return this;
119
+ }
120
+
121
+ variant(variant: TableVariant): this {
122
+ this._variant = variant;
123
+ return this;
124
+ }
125
+
126
+ density(density: TableDensity): this {
127
+ this._density = density;
128
+ return this;
129
+ }
130
+
131
+ striped(enable: boolean = true): this {
132
+ this._striped = enable;
133
+ return this;
134
+ }
135
+
136
+ width(value: string | number): this {
137
+ this._width = value;
138
+ return this;
139
+ }
140
+
141
+ build(): ReactElement {
142
+ const props = {
143
+ data: this._data,
144
+ columns: this._columns,
145
+ variant: this._variant,
146
+ density: this._density,
147
+ striped: this._striped,
148
+ width: this._width,
149
+ className: this.getClassName(),
150
+ style: this.getStyle()
151
+ };
152
+ return React.createElement(TableInner, props);
153
+ }
154
+ }
155
+
156
+
157
+ export const Table = createBuilder(TableBuilder);
158
+
159
+ export interface TableProps<T = any> extends BaseProps {
160
+ data: T[];
161
+ columns: TableColumn<T>[];
162
+ variant?: TableVariant;
163
+ density?: TableDensity;
164
+ striped?: boolean;
165
+ }
@@ -0,0 +1,69 @@
1
+ import React, { ReactElement } from 'react';
2
+ import { FiboBuilder, createBuilder } from '../../core/builder';
3
+ import { BaseProps } from '../../core/types';
4
+
5
+ interface TagItem {
6
+ title: string;
7
+ }
8
+
9
+ const TagsInner = React.memo((props: any) => {
10
+ const { items, className, style, ...rest } = props;
11
+
12
+ const tags = items.map((item: TagItem, index: number) =>
13
+ React.createElement(
14
+ 'span',
15
+ {
16
+ key: index,
17
+ className: 'fibo-tag',
18
+ },
19
+ item.title
20
+ )
21
+ );
22
+
23
+ return React.createElement(
24
+ 'div',
25
+ {
26
+ className,
27
+ style,
28
+ ...rest,
29
+ },
30
+ ...tags
31
+ );
32
+ });
33
+
34
+ class TagsBuilder extends FiboBuilder {
35
+ private _items: TagItem[] = [];
36
+
37
+ constructor(items: TagItem[] = []) {
38
+ super();
39
+ this._items = items;
40
+ }
41
+
42
+ items(items: TagItem[]): this {
43
+ this._items = items;
44
+ return this;
45
+ }
46
+
47
+ build(): ReactElement {
48
+ const className = ['fibo-tags', 'flex', 'gap-2', 'flex-wrap', ...this._classNames]
49
+ .filter(Boolean)
50
+ .join(' ');
51
+
52
+ const props = {
53
+ items: this._items,
54
+ className: className,
55
+ style: this.getStyle(),
56
+ ...this._props
57
+ };
58
+ return React.createElement(TagsInner, props);
59
+ }
60
+ }
61
+
62
+
63
+ export const Tags = createBuilder(TagsBuilder);
64
+
65
+ export interface TagsProps extends BaseProps {
66
+ items: TagItem[];
67
+ }
68
+
69
+ export type { TagItem };