anteriority-ui 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 (199) hide show
  1. package/.github/workflows/ci.yml +31 -0
  2. package/.github/workflows/publish.yml +45 -0
  3. package/.npmrc.bak +1 -0
  4. package/.storybook/main.js +15 -0
  5. package/.storybook/preview.jsx +26 -0
  6. package/AnteriorityUI.md +2400 -0
  7. package/CLAUDE.md +91 -0
  8. package/README.md +182 -0
  9. package/assets/anteriorityUI/AnteriorityUI.logo.jpeg +0 -0
  10. package/assets/favicon/anteriorityUI.ico +0 -0
  11. package/common/api/client.js +43 -0
  12. package/common/storage/LocalStorage.js +13 -0
  13. package/common/styles/typography.css +5 -0
  14. package/common/styles/variables.css +192 -0
  15. package/common/theme/muiTheme.js +9 -0
  16. package/features/password-reset/api.js +39 -0
  17. package/features/user-profile/api.js +5 -0
  18. package/hooks/useAdminPasswordReset.js +133 -0
  19. package/index.js +57 -0
  20. package/package.json +57 -0
  21. package/pnpm-workspace.yaml +3 -0
  22. package/screens/components/AlertModal/AlertModal.jsx +259 -0
  23. package/screens/components/AlertModal/AlertModal.module.css +185 -0
  24. package/screens/components/AlertModal/AlertModal.stories.jsx +87 -0
  25. package/screens/components/Avatar/index.jsx +0 -0
  26. package/screens/components/Avatar/index.module.css +0 -0
  27. package/screens/components/Avatar/utils.js +0 -0
  28. package/screens/components/Badge/index.jsx +33 -0
  29. package/screens/components/Badge/index.module.css +18 -0
  30. package/screens/components/Badge/index.stories.jsx +40 -0
  31. package/screens/components/Barnner/index.jsx +21 -0
  32. package/screens/components/Barnner/index.module.css +33 -0
  33. package/screens/components/Barnner/index.stories.jsx +39 -0
  34. package/screens/components/Barnner/utils.js +0 -0
  35. package/screens/components/BlueLink/index.jsx +27 -0
  36. package/screens/components/BlueLink/index.module.css +11 -0
  37. package/screens/components/BlueLink/index.stories.jsx +29 -0
  38. package/screens/components/Breadcrumbs/index.jsx +62 -0
  39. package/screens/components/Breadcrumbs/index.module.css +158 -0
  40. package/screens/components/Breadcrumbs/index.stories.jsx +37 -0
  41. package/screens/components/Button/index.jsx +169 -0
  42. package/screens/components/Button/index.module.css +168 -0
  43. package/screens/components/Button/index.stories.jsx +71 -0
  44. package/screens/components/Button/utils.js +28 -0
  45. package/screens/components/CalendarComponent/CustomDatePicker.jsx +248 -0
  46. package/screens/components/CalendarComponent/CustomDatePicker.module.css +323 -0
  47. package/screens/components/CalendarComponent/CustomDatePicker.stories.jsx +45 -0
  48. package/screens/components/CalendarPicker/Constants.js +12 -0
  49. package/screens/components/CalendarPicker/index.jsx +263 -0
  50. package/screens/components/CalendarPicker/index.module.css +147 -0
  51. package/screens/components/CalendarPicker/index.stories.jsx +45 -0
  52. package/screens/components/CalendarPicker/utils.js +42 -0
  53. package/screens/components/CardV1/index.jsx +165 -0
  54. package/screens/components/CardV1/index.module.css +232 -0
  55. package/screens/components/CardV1/index.stories.jsx +62 -0
  56. package/screens/components/CardV1/utils.js +49 -0
  57. package/screens/components/ChatWindow/index.jsx +251 -0
  58. package/screens/components/ChatWindow/index.module.css +311 -0
  59. package/screens/components/ChatWindow/index.stories.jsx +62 -0
  60. package/screens/components/Checks/index.jsx +31 -0
  61. package/screens/components/Checks/index.module.css +32 -0
  62. package/screens/components/Checks/index.stories.jsx +32 -0
  63. package/screens/components/Container/index.jsx +36 -0
  64. package/screens/components/Container/index.module.css +24 -0
  65. package/screens/components/Container/index.stories.jsx +32 -0
  66. package/screens/components/CopyText/index.jsx +42 -0
  67. package/screens/components/CopyText/index.module.css +52 -0
  68. package/screens/components/CopyText/index.stories.jsx +24 -0
  69. package/screens/components/CountdownBar/constants.js +3 -0
  70. package/screens/components/CountdownBar/index.jsx +81 -0
  71. package/screens/components/CountdownBar/index.module.css +45 -0
  72. package/screens/components/CountdownBar/index.stories.jsx +43 -0
  73. package/screens/components/CountdownBar/utils.js +119 -0
  74. package/screens/components/DateTag/index.jsx +33 -0
  75. package/screens/components/DateTag/index.module.css +12 -0
  76. package/screens/components/DateTag/index.stories.jsx +29 -0
  77. package/screens/components/DesplegablePanel/constants.js +0 -0
  78. package/screens/components/DesplegablePanel/index.jsx +61 -0
  79. package/screens/components/DesplegablePanel/index.module.css +120 -0
  80. package/screens/components/DesplegablePanel/index.stories.jsx +44 -0
  81. package/screens/components/DesplegablePanel/utils.js +0 -0
  82. package/screens/components/DrawPanel/index.jsx +217 -0
  83. package/screens/components/DrawPanel/index.module.css +252 -0
  84. package/screens/components/DrawPanel/index.stories.jsx +66 -0
  85. package/screens/components/DrawPanel/utils.js +0 -0
  86. package/screens/components/Filter/index.jsx +105 -0
  87. package/screens/components/Filter/index.module.css +91 -0
  88. package/screens/components/Filter/index.stories.jsx +46 -0
  89. package/screens/components/Filter/utils.js +0 -0
  90. package/screens/components/FormControls/FormControls.module.css +86 -0
  91. package/screens/components/FormControls/index.jsx +51 -0
  92. package/screens/components/FormControls/index.stories.jsx +36 -0
  93. package/screens/components/Frame/index.jsx +54 -0
  94. package/screens/components/Frame/index.module.css +102 -0
  95. package/screens/components/Frame/index.stories.jsx +37 -0
  96. package/screens/components/Frame/utils.js +0 -0
  97. package/screens/components/GreenHighlight/index.jsx +11 -0
  98. package/screens/components/GreenHighlight/index.module.css +7 -0
  99. package/screens/components/GreenHighlight/index.stories.jsx +26 -0
  100. package/screens/components/GreenHighlight/utils.jsx +45 -0
  101. package/screens/components/HoursPicker/Constants.js +26 -0
  102. package/screens/components/HoursPicker/index.jsx +350 -0
  103. package/screens/components/HoursPicker/index.module.css +99 -0
  104. package/screens/components/HoursPicker/index.stories.jsx +44 -0
  105. package/screens/components/HoursPicker/utils.js +48 -0
  106. package/screens/components/InfoTooltip/index.jsx +59 -0
  107. package/screens/components/InfoTooltip/index.module.css +98 -0
  108. package/screens/components/InfoTooltip/index.stories.jsx +35 -0
  109. package/screens/components/Input/index.jsx +36 -0
  110. package/screens/components/Input/index.module.css +49 -0
  111. package/screens/components/Input/index.stories.jsx +37 -0
  112. package/screens/components/Input/utils.js +0 -0
  113. package/screens/components/Loading/index.jsx +76 -0
  114. package/screens/components/Loading/index.module.css +193 -0
  115. package/screens/components/Loading/index.stories.jsx +38 -0
  116. package/screens/components/Loading/utils.js +0 -0
  117. package/screens/components/MarkdownContent/index.jsx +16 -0
  118. package/screens/components/MarkdownContent/index.module.css +149 -0
  119. package/screens/components/MarkdownContent/index.stories.jsx +30 -0
  120. package/screens/components/MarkdownEditor/index.jsx +430 -0
  121. package/screens/components/MarkdownEditor/index.module.css +192 -0
  122. package/screens/components/MarkdownEditor/index.stories.jsx +50 -0
  123. package/screens/components/Material-UI/Components/InputWithIcon/index.jsx +87 -0
  124. package/screens/components/Material-UI/Components/InputWithIcon/index.stories.jsx +49 -0
  125. package/screens/components/Material-UI/Components/MenuPopover/index.jsx +117 -0
  126. package/screens/components/Material-UI/Components/MenuPopover/index.stories.jsx +36 -0
  127. package/screens/components/Material-UI/Components/MultilinePlaceholder/index.jsx +44 -0
  128. package/screens/components/Material-UI/Components/MultilinePlaceholder/index.stories.jsx +45 -0
  129. package/screens/components/Material-UI/Components/Paginador/index.jsx +79 -0
  130. package/screens/components/Material-UI/Components/Paginador/index.stories.jsx +49 -0
  131. package/screens/components/Material-UI/Components/Search/index.jsx +81 -0
  132. package/screens/components/Material-UI/Components/Search/index.stories.jsx +68 -0
  133. package/screens/components/Material-UI/Components/Selector/index.jsx +100 -0
  134. package/screens/components/Material-UI/Components/Selector/index.module.css +0 -0
  135. package/screens/components/Material-UI/Components/Selector/index.stories.jsx +52 -0
  136. package/screens/components/Material-UI/Components/Selector/utils.js +0 -0
  137. package/screens/components/Material-UI/Components/TextField/index.jsx +61 -0
  138. package/screens/components/Material-UI/Components/TextField/index.stories.jsx +53 -0
  139. package/screens/components/ModalTooltip/ModalTooltip.jsx +122 -0
  140. package/screens/components/ModalTooltip/ModalTooltip.module.css +65 -0
  141. package/screens/components/ModalTooltip/ModalTooltip.stories.jsx +39 -0
  142. package/screens/components/Notification/Error/ErrorMessage.jsx +30 -0
  143. package/screens/components/Notification/Error/ErrorMessage.module.css +57 -0
  144. package/screens/components/Notification/Error/ErrorMessage.stories.jsx +37 -0
  145. package/screens/components/PasswordResetPanel/index.jsx +325 -0
  146. package/screens/components/PasswordResetPanel/index.stories.jsx +26 -0
  147. package/screens/components/PlaceholderButton/index.jsx +169 -0
  148. package/screens/components/PlaceholderButton/index.module.css +162 -0
  149. package/screens/components/PlaceholderButton/index.stories.jsx +69 -0
  150. package/screens/components/PlaceholderButton/utils.js +42 -0
  151. package/screens/components/Profile/Avatar/index.jsx +125 -0
  152. package/screens/components/Profile/Avatar/index.module.css +86 -0
  153. package/screens/components/Profile/Avatar/index.stories.jsx +48 -0
  154. package/screens/components/Profile/Avatar/utils.js +18 -0
  155. package/screens/components/Profile/index.jsx +58 -0
  156. package/screens/components/Profile/index.module.css +0 -0
  157. package/screens/components/Profile/index.stories.jsx +38 -0
  158. package/screens/components/Profile/utils.js +0 -0
  159. package/screens/components/ScrollBar/index.jsx +62 -0
  160. package/screens/components/ScrollBar/index.module.css +78 -0
  161. package/screens/components/ScrollBar/index.stories.jsx +64 -0
  162. package/screens/components/ScrollBar/utils.js +127 -0
  163. package/screens/components/Sidebar/constants.js +16 -0
  164. package/screens/components/Sidebar/index.jsx +399 -0
  165. package/screens/components/Sidebar/index.module.css +405 -0
  166. package/screens/components/Sidebar/index.stories.jsx +86 -0
  167. package/screens/components/Sidebar/utils.js +75 -0
  168. package/screens/components/Skeleton/index.jsx +11 -0
  169. package/screens/components/Skeleton/index.module.css +26 -0
  170. package/screens/components/Skeleton/index.stories.jsx +42 -0
  171. package/screens/components/SubSidebarLayout/index.jsx +44 -0
  172. package/screens/components/SubSidebarLayout/index.module.css +80 -0
  173. package/screens/components/SubSidebarLayout/index.stories.jsx +51 -0
  174. package/screens/components/SummaryCard/index.jsx +50 -0
  175. package/screens/components/SummaryCard/index.module.css +30 -0
  176. package/screens/components/SummaryCard/index.stories.jsx +29 -0
  177. package/screens/components/Swich/constants.js +4 -0
  178. package/screens/components/Swich/index.jsx +85 -0
  179. package/screens/components/Swich/index.module.css +68 -0
  180. package/screens/components/Swich/index.stories.jsx +44 -0
  181. package/screens/components/Swich/utils.js +0 -0
  182. package/screens/components/TableA/index.jsx +156 -0
  183. package/screens/components/TableA/index.module.css +105 -0
  184. package/screens/components/TableA/index.stories.jsx +116 -0
  185. package/screens/components/TableA/utils.js +11 -0
  186. package/screens/components/TableB/index.jsx +222 -0
  187. package/screens/components/TableB/index.module.css +295 -0
  188. package/screens/components/TableB/index.stories.jsx +110 -0
  189. package/screens/components/TableB/utils.js +11 -0
  190. package/screens/components/ToggleCard/index.jsx +64 -0
  191. package/screens/components/ToggleCard/index.module.css +111 -0
  192. package/screens/components/ToggleCard/index.stories.jsx +49 -0
  193. package/screens/components/UserEditPopover/index.jsx +102 -0
  194. package/screens/components/UserEditPopover/index.module.css +97 -0
  195. package/screens/components/UserEditPopover/index.stories.jsx +49 -0
  196. package/scripts/build.mjs +129 -0
  197. package/scripts/check-case.mjs +127 -0
  198. package/scripts/verify-dist.mjs +45 -0
  199. package/vitest.config.js +36 -0
@@ -0,0 +1,105 @@
1
+ .tableWrapper {
2
+ width: 100%;
3
+ overflow: hidden;
4
+ background: var(--tableA-surface, white);
5
+ border-radius: 12px;
6
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
7
+ border: 1px solid var(--tableA-border, #e2e8f0);
8
+ }
9
+
10
+ .table {
11
+ width: 100%;
12
+ border-collapse: collapse;
13
+ white-space: normal;
14
+ }
15
+
16
+ .table th {
17
+ background-color: var(--tableA-header, #f8fafc);
18
+ color: var(--tableA-heading-text, #475569);
19
+ font-weight: 600;
20
+ font-size: 0.75rem;
21
+ text-align: left;
22
+ padding: 0.5rem 0.75rem;
23
+ border-bottom: 1px solid var(--tableA-border, #e2e8f0);
24
+ text-transform: uppercase;
25
+ letter-spacing: 0.05em;
26
+ }
27
+
28
+ .headerFilterWrap {
29
+ display: flex;
30
+ align-items: center;
31
+ gap: 0.25rem;
32
+ }
33
+
34
+ .headerFilterBtn {
35
+ padding: 0 !important;
36
+ min-width: unset !important;
37
+ width: 20px !important;
38
+ height: 20px !important;
39
+ }
40
+
41
+ .row {
42
+ transition: background-color 0.2s ease;
43
+ }
44
+
45
+ .row:hover {
46
+ background-color: var(--tableA-hover, #f8fafc);
47
+ }
48
+
49
+ .row:not(:last-child) td {
50
+ border-bottom: 1px solid var(--tableA-row-border, #f1f5f9);
51
+ }
52
+
53
+ .table td {
54
+ padding: 0.5rem 0.75rem;
55
+ color: var(--tableA-text, #334155);
56
+ font-size: 0.9rem;
57
+ vertical-align: middle;
58
+ }
59
+
60
+ .emptyState {
61
+ display: flex;
62
+ flex-direction: column;
63
+ align-items: center;
64
+ justify-content: center;
65
+ padding: 3rem 1.5rem !important;
66
+ text-align: center;
67
+ color: var(--tableA-muted-text, #64748b);
68
+ background-color: var(--tableA-header, #f8fafc);
69
+ border-radius: 12px;
70
+ box-shadow: inset 0 2px 4px rgba(0,0,0,0.02);
71
+ border: 1px dashed var(--tableA-border, #cbd5e1);
72
+ }
73
+
74
+ .emptyIcon {
75
+ color: var(--tableA-muted-text, #94a3b8);
76
+ margin-bottom: 1rem;
77
+ }
78
+
79
+ .tableLoadingContainer {
80
+ display: flex;
81
+ align-items: center;
82
+ justify-content: center;
83
+ min-height: 200px;
84
+ background-color: var(--tableA-surface, #ffffff);
85
+ border-radius: 8px;
86
+ width: 100%;
87
+ }
88
+
89
+ .centerSection {
90
+ display: flex;
91
+ flex-direction: column;
92
+ align-items: center;
93
+ justify-content: center;
94
+ gap: 1rem;
95
+ padding: 3rem;
96
+ min-height: 200px;
97
+ }
98
+
99
+ .errorMessage {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: 0.75rem;
103
+ color: var(--SW-red);
104
+ font-weight: 500;
105
+ }
@@ -0,0 +1,116 @@
1
+ import React, { useState } from 'react';
2
+ import TableA from './index';
3
+ import { CheckCircle, XCircle } from 'lucide-react';
4
+
5
+ export default {
6
+ title: 'Components/TableA',
7
+ component: TableA,
8
+ };
9
+
10
+ const columns = [
11
+ { header: 'Nombre', accessor: 'name' },
12
+ { header: 'Email', accessor: 'email' },
13
+ {
14
+ header: 'Estado',
15
+ accessor: 'active',
16
+ align: 'center',
17
+ width: '120px',
18
+ render: (row) =>
19
+ row.active ? (
20
+ <CheckCircle size={18} color="var(--button-green, #16a34a)" />
21
+ ) : (
22
+ <XCircle size={18} color="var(--color-danger, #ef4444)" />
23
+ ),
24
+ },
25
+ ];
26
+
27
+ const data = [
28
+ { id: 1, name: 'Ana Gomez', email: 'ana@correo.com', active: true },
29
+ { id: 2, name: 'Luis Perez', email: 'luis@correo.com', active: false },
30
+ { id: 3, name: 'Marta Ruiz', email: 'marta@correo.com', active: true },
31
+ ];
32
+
33
+ export const Default = {
34
+ args: {
35
+ columns,
36
+ data,
37
+ keyExtractor: (row) => row.id,
38
+ },
39
+ };
40
+
41
+ export const Loading = {
42
+ args: {
43
+ columns,
44
+ data: [],
45
+ keyExtractor: (row) => row.id,
46
+ loading: true,
47
+ skeletonRows: 4,
48
+ },
49
+ };
50
+
51
+ export const ErrorState = {
52
+ args: {
53
+ columns,
54
+ data: [],
55
+ keyExtractor: (row) => row.id,
56
+ error: 'No se pudieron cargar los datos.',
57
+ onRetry: () => console.log('retry clicked'),
58
+ },
59
+ };
60
+
61
+ export const Empty = {
62
+ args: {
63
+ columns,
64
+ data: [],
65
+ keyExtractor: (row) => row.id,
66
+ emptyMessage: 'No hay usuarios registrados',
67
+ },
68
+ };
69
+
70
+ const STATUS_FILTER_OPTIONS = [
71
+ { value: '', label: 'Todos' },
72
+ { value: 'active', label: 'Activo' },
73
+ { value: 'inactive', label: 'Inactivo' },
74
+ ];
75
+
76
+ export const WithColumnFilter = {
77
+ render: () => {
78
+ const [statusFilter, setStatusFilter] = useState('');
79
+
80
+ const filterableColumns = [
81
+ { header: 'Nombre', accessor: 'name' },
82
+ { header: 'Email', accessor: 'email' },
83
+ {
84
+ header: 'Estado',
85
+ accessor: 'active',
86
+ align: 'center',
87
+ width: '150px',
88
+ filter: {
89
+ options: STATUS_FILTER_OPTIONS,
90
+ value: statusFilter,
91
+ onChange: setStatusFilter,
92
+ },
93
+ render: (row) =>
94
+ row.active ? (
95
+ <CheckCircle size={18} color="var(--button-green, #16a34a)" />
96
+ ) : (
97
+ <XCircle size={18} color="var(--color-danger, #ef4444)" />
98
+ ),
99
+ },
100
+ ];
101
+
102
+ const filteredData = data.filter((row) => {
103
+ if (statusFilter === 'active') return row.active;
104
+ if (statusFilter === 'inactive') return !row.active;
105
+ return true;
106
+ });
107
+
108
+ return (
109
+ <TableA
110
+ columns={filterableColumns}
111
+ data={filteredData}
112
+ keyExtractor={(row) => row.id}
113
+ />
114
+ );
115
+ },
116
+ };
@@ -0,0 +1,11 @@
1
+ export function getNextFilterValue(options, currentValue) {
2
+ if (!Array.isArray(options) || options.length === 0) return currentValue;
3
+ const currentIndex = options.findIndex((option) => option.value === currentValue);
4
+ const nextIndex = (currentIndex + 1) % options.length;
5
+ return options[nextIndex].value;
6
+ }
7
+
8
+ export function getFilterOptionLabel(options, value) {
9
+ if (!Array.isArray(options)) return undefined;
10
+ return options.find((option) => option.value === value)?.label;
11
+ }
@@ -0,0 +1,222 @@
1
+ import React, { useState } from 'react';
2
+ import styles from './index.module.css';
3
+ import { Inbox, ChevronDown, ChevronUp, Filter as FilterIcon } from 'lucide-react';
4
+ import Barnner from '../Barnner';
5
+ import Button from '../Button';
6
+ import Loading from '../Loading/index';
7
+ import Skeleton from '../Skeleton/index';
8
+ import ScrollBar from '../ScrollBar';
9
+ import { getNextFilterValue, getFilterOptionLabel } from './utils';
10
+
11
+ const TableB = (props) => {
12
+ const {
13
+ columns = [],
14
+ data = [],
15
+ loading = false,
16
+ skeletonRows = 6,
17
+ error = null,
18
+ emptyIcon: EmptyIcon = Inbox,
19
+ emptyMessage = "No hay datos disponibles.",
20
+ onRetry,
21
+ expandable,
22
+ rowKey = 'id',
23
+ rowClassName,
24
+ surfaceColor,
25
+ headerColor,
26
+ textColor,
27
+ headingColor,
28
+ mutedTextColor,
29
+ borderColor,
30
+ hoverColor,
31
+ rowBorderColor,
32
+ badgeColors,
33
+ filterIconColor,
34
+ filterActiveColor = '#10b981'
35
+ } = props;
36
+ const [expandedKeys, setExpandedKeys] = useState({});
37
+
38
+ const handleCycleFilter = (filter) => {
39
+ if (!filter || !Array.isArray(filter.options) || filter.options.length === 0) return;
40
+ filter.onChange?.(getNextFilterValue(filter.options, filter.value));
41
+ };
42
+
43
+ const toggleExpand = (key) => {
44
+ setExpandedKeys(prev => ({
45
+ ...prev,
46
+ [key]: !prev[key]
47
+ }));
48
+ };
49
+
50
+ const themeVars = {
51
+ '--tableB-surface': surfaceColor,
52
+ '--tableB-header': headerColor,
53
+ '--tableB-text': textColor,
54
+ '--tableB-heading-text': headingColor,
55
+ '--tableB-muted-text': mutedTextColor,
56
+ '--tableB-border': borderColor,
57
+ '--tableB-hover': hoverColor,
58
+ '--tableB-row-border': rowBorderColor,
59
+ '--tableB-badge-success-bg': badgeColors?.success?.bg,
60
+ '--tableB-badge-success-color': badgeColors?.success?.color,
61
+ '--tableB-badge-warning-bg': badgeColors?.warning?.bg,
62
+ '--tableB-badge-warning-color': badgeColors?.warning?.color,
63
+ '--tableB-badge-danger-bg': badgeColors?.danger?.bg,
64
+ '--tableB-badge-danger-color': badgeColors?.danger?.color,
65
+ };
66
+
67
+ const getBadgeOverrideClass = (badgeTypeValue) => {
68
+ if (badgeTypeValue === 'success') return styles.badgeSuccess;
69
+ if (badgeTypeValue === 'warning') return styles.badgeWarning;
70
+ if (badgeTypeValue === 'danger') return styles.badgeDanger;
71
+ return '';
72
+ };
73
+
74
+ return (
75
+ <ScrollBar horizontal vertical={false} className={styles.tableContainer} style={themeVars}>
76
+ <table className={styles.modernTable}>
77
+ <thead>
78
+ <tr>
79
+ {columns.map((col, idx) => (
80
+ <th
81
+ key={col.key || idx}
82
+ style={{ textAlign: col.align || 'left' }}
83
+ >
84
+ {col.filter ? (
85
+ <div
86
+ className={styles.headerFilterWrap}
87
+ style={{ justifyContent: col.align === 'right' ? 'flex-end' : col.align === 'center' ? 'center' : 'flex-start' }}
88
+ >
89
+ <span>{col.label}</span>
90
+ <Button
91
+ circle
92
+ size="small"
93
+ variant={Button.VARIANTS.GHOST}
94
+ icon={FilterIcon}
95
+ color={col.filter.value ? filterActiveColor : filterIconColor}
96
+ className={styles.headerFilterBtn}
97
+ ToolTip={col.filter.tooltip || getFilterOptionLabel(col.filter.options, col.filter.value)}
98
+ onClick={() => handleCycleFilter(col.filter)}
99
+ />
100
+ </div>
101
+ ) : col.label}
102
+ </th>
103
+ ))}
104
+ {expandable && <th className={styles.expandHeader}></th>}
105
+ </tr>
106
+ </thead>
107
+ <tbody>
108
+ {loading ? (
109
+ Array.from({ length: skeletonRows }).map((_, rowIdx) => (
110
+ <tr key={`skeleton-${rowIdx}`}>
111
+ {columns.map((col, colIdx) => (
112
+ <td key={col.key || colIdx} style={{ textAlign: col.align || 'left', width: col.width }}>
113
+ <Skeleton height="14px" width={col.align === 'right' || col.align === 'center' ? '60%' : '85%'} />
114
+ </td>
115
+ ))}
116
+ {expandable && <td className={styles.expandCell} />}
117
+ </tr>
118
+ ))
119
+ ) : error ? (
120
+ <tr>
121
+ <td colSpan={columns.length + (expandable ? 1 : 0)} style={{ padding: 0 }}>
122
+ <div className={styles.centerSection}>
123
+ <div style={{ marginBottom: '16px' }}>
124
+ <Loading size="large" phrases={[error, "Revisando conexión", "Por favor, intenta de nuevo"]} />
125
+ </div>
126
+ {/* {onRetry && (
127
+ <Button
128
+ type={"button"}
129
+ variant={Button.VARIANTS.PRIMARY}
130
+ size={Button.SIZES.LARGE}
131
+ color={Button.COLORS.GREEN}
132
+ onClick={onRetry}>Reintentar</Button>
133
+ )} */}
134
+ </div>
135
+ </td>
136
+ </tr>
137
+ ) : (!data || data.length === 0) ? (
138
+ <tr>
139
+ <td colSpan={columns.length + (expandable ? 1 : 0)} style={{ padding: '1.5rem' }}>
140
+ <div className={styles.emptyState}>
141
+ <EmptyIcon size={48} className={styles.emptyIcon} />
142
+ <p style={{ margin: 0 }}>{emptyMessage}</p>
143
+ </div>
144
+ </td>
145
+ </tr>
146
+ ) : (
147
+ data.map((row, rowIndex) => {
148
+ const key = row[rowKey] || rowIndex;
149
+ const isExpanded = !!expandedKeys[key];
150
+ const canExpand = expandable?.rowExpandable ? expandable.rowExpandable(row) : true;
151
+
152
+ return (
153
+ <React.Fragment key={key}>
154
+ <tr
155
+ className={`${styles.tableRow} ${isExpanded ? styles.rowExpanded : ''} ${rowClassName ? rowClassName(row, rowIndex) : ''}`}
156
+ onClick={() => canExpand && toggleExpand(key)}
157
+ style={{ cursor: canExpand ? 'pointer' : 'default' }}
158
+ >
159
+ {columns.map((col, colIndex) => (
160
+ <td
161
+ key={col.key || colIndex}
162
+ style={{ textAlign: col.align || 'left', width: col.width }}
163
+ >
164
+ {col.type === 'actions' && col.actions ? (
165
+ <div className={styles.actionButtons} style={{ justifyContent: col.align || 'flex-start' }}>
166
+ {col.actions.map((act, actIdx) => (
167
+ <Button
168
+ key={actIdx}
169
+ variant={Button.VARIANTS.PRIMARY}
170
+ size={Button.SIZES.LARGE}
171
+ color={Button.COLORS.GREEN}
172
+ onClick={(e) => { e.stopPropagation(); act.onClick(row); }}
173
+ disabled={act.disabled ? act.disabled(row) : false}
174
+ >
175
+ {act.label}
176
+ {act.icon && <img src={act.icon} alt={act.label} className={`${styles.actionIcon} ${act.invertIcon ? styles.actionIconInvert : ''}`} />}
177
+ </Button>
178
+ ))}
179
+ </div>
180
+ ) : col.type === 'badge' ? (
181
+ <Barnner
182
+ type={col.badgeType ? col.badgeType(row) : undefined}
183
+ className={`${getBadgeOverrideClass(col.badgeType ? col.badgeType(row) : undefined)} ${col.badgeClass ? col.badgeClass(row) : ''}`}
184
+ >
185
+ {col.render ? col.render(row, rowIndex) : row[col.key]}
186
+ </Barnner>
187
+ ) : col.render ? (
188
+ col.render(row, rowIndex)
189
+ ) : (
190
+ row[col.key]
191
+ )}
192
+ </td>
193
+ ))}
194
+ {expandable && (
195
+ <td className={styles.expandCell}>
196
+ {canExpand ? (
197
+ <div className={styles.expandIconWrapper}>
198
+ {isExpanded ? <ChevronUp size={18} /> : <ChevronDown size={18} />}
199
+ </div>
200
+ ) : null}
201
+ </td>
202
+ )}
203
+ </tr>
204
+ {expandable && isExpanded && (
205
+ <tr className={styles.expandedContentRow}>
206
+ <td colSpan={columns.length + 1} className={styles.expandedContentCell}>
207
+ <div className={styles.expandedWrapper}>
208
+ {expandable.expandedRowRender(row, rowIndex)}
209
+ </div>
210
+ </td>
211
+ </tr>
212
+ )}
213
+ </React.Fragment>
214
+ );
215
+ }))}
216
+ </tbody>
217
+ </table>
218
+ </ScrollBar>
219
+ );
220
+ };
221
+
222
+ export default TableB;