@axzydev/axzy_ui_system 1.2.9 → 1.2.12
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 +6 -0
- package/dist/index.cjs +313 -242
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +142 -6
- package/dist/index.d.ts +142 -6
- package/dist/index.js +313 -242
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/snippets/axzy-ui-system.code-snippets +547 -0
- package/src/App.tsx +37 -34
- package/src/components/avatar/avatar.props.ts +12 -1
- package/src/components/avatar/avatar.stories.tsx +19 -0
- package/src/components/avatar/avatar.tsx +27 -4
- package/src/components/calendar/calendar.tsx +1 -1
- package/src/components/card/card.tsx +11 -8
- package/src/components/confirm-dialog/confirm-dialog.tsx +1 -1
- package/src/components/data-table/dataTable.props.ts +10 -0
- package/src/components/data-table/dataTable.tsx +27 -16
- package/src/components/date-picker/datePicker.tsx +1 -1
- package/src/components/dialog/dialog.tsx +3 -2
- package/src/components/divider/divider.tsx +1 -1
- package/src/components/drawer/drawer.tsx +1 -1
- package/src/components/dropfile/dropfile.props.ts +6 -0
- package/src/components/dropfile/dropfile.tsx +65 -30
- package/src/components/form-builder/fieldRenderer.tsx +3 -3
- package/src/components/input/input.tsx +7 -7
- package/src/components/layout/layout.tsx +1 -1
- package/src/components/loader/loader.tsx +1 -1
- package/src/components/navbar/navbar.tsx +10 -10
- package/src/components/pagination/pagination.tsx +11 -11
- package/src/components/popover/popover.tsx +1 -1
- package/src/components/search-select/search-select.tsx +11 -11
- package/src/components/searchTable/components/EditableCell.tsx +1 -1
- package/src/components/searchTable/components/PaginationControls.tsx +2 -2
- package/src/components/searchTable/components/PaginationInfo.tsx +1 -1
- package/src/components/searchTable/components/SearchAndSortBar.tsx +1 -1
- package/src/components/searchTable/components/SearchInput.tsx +1 -1
- package/src/components/searchTable/components/SortButton.tsx +3 -3
- package/src/components/searchTable/components/TableHeader.tsx +1 -1
- package/src/components/searchTable/components/TableRow.tsx +4 -4
- package/src/components/searchTable/searchTable.tsx +2 -2
- package/src/components/select/select.tsx +8 -10
- package/src/components/sidebar/sidebar.tsx +29 -29
- package/src/components/slider/slider.tsx +3 -3
- package/src/components/stepper/stepper.props.ts +4 -0
- package/src/components/stepper/stepper.tsx +5 -5
- package/src/components/table/table.props.ts +21 -3
- package/src/components/table/table.tsx +27 -16
- package/src/components/tabs/tabs.tsx +4 -4
- package/src/components/textarea/textarea.tsx +3 -3
- package/src/components/theme-provider/themeProvider.props.ts +21 -3
- package/src/components/theme-provider/themeProvider.tsx +32 -32
- package/src/components/time-picker/timePicker.tsx +5 -5
- package/src/components/toast/toast.tsx +1 -1
- package/src/components/tooltip/tooltip.tsx +1 -1
- package/src/components/topbar/topbar.tsx +7 -7
- package/src/dev.css +1 -1
- package/src/hooks/useClickOutside.ts +8 -0
- package/src/hooks/useTableState.ts +5 -2
- package/src/index.css +24 -1
- package/src/showcases/HomeShowcase.tsx +95 -3
- package/src/theme/theme.ts +38 -17
- package/src/types/field.types.ts +70 -7
- package/src/utils/styles.ts +5 -5
|
@@ -66,7 +66,7 @@ export default function TableRow<T>({
|
|
|
66
66
|
title="Verdadero"
|
|
67
67
|
/>
|
|
68
68
|
) : (
|
|
69
|
-
<FaTimes className="text-
|
|
69
|
+
<FaTimes className="text-danger-500" aria-label="Falso" title="Falso" />
|
|
70
70
|
);
|
|
71
71
|
|
|
72
72
|
case "actions":
|
|
@@ -99,13 +99,13 @@ export default function TableRow<T>({
|
|
|
99
99
|
<tr
|
|
100
100
|
onMouseEnter={() => setIsHovered(true)}
|
|
101
101
|
onMouseLeave={() => setIsHovered(false)}
|
|
102
|
-
className={`border-b border-
|
|
102
|
+
className={`border-b border-secondary-200 transition-colors duration-150 ${
|
|
103
103
|
isEditing
|
|
104
104
|
? "bg-slate-50"
|
|
105
105
|
: rowIndex % 2 === 0
|
|
106
106
|
? "bg-white"
|
|
107
|
-
: "bg-
|
|
108
|
-
} ${isHovered && !isEditing ? "bg-
|
|
107
|
+
: "bg-secondary-50"
|
|
108
|
+
} ${isHovered && !isEditing ? "bg-secondary-100" : ""}`}
|
|
109
109
|
>
|
|
110
110
|
{columns.map((col) => (
|
|
111
111
|
<td
|
|
@@ -139,7 +139,7 @@ return (
|
|
|
139
139
|
{/* Contenido con scroll */}
|
|
140
140
|
<div className="bg-white">
|
|
141
141
|
{/* Barra de búsqueda y ordenamiento */}
|
|
142
|
-
<div className="p-4 border-b border-
|
|
142
|
+
<div className="p-4 border-b border-secondary-200">
|
|
143
143
|
<SearchAndSortBar
|
|
144
144
|
searchTerm={searchTerm}
|
|
145
145
|
onSearchChange={handleSearchChange}
|
|
@@ -154,7 +154,7 @@ return (
|
|
|
154
154
|
<div className="overflow-x-auto">
|
|
155
155
|
<table
|
|
156
156
|
className={clsx(
|
|
157
|
-
"min-w-full text-sm text-left bg-white text-
|
|
157
|
+
"min-w-full text-sm text-left bg-white text-secondary-900 table-auto",
|
|
158
158
|
variantStyles[variant],
|
|
159
159
|
sizeStyles[size]
|
|
160
160
|
)}
|
|
@@ -4,6 +4,7 @@ import { useState } from "react";
|
|
|
4
4
|
import { FaAngleDown } from "react-icons/fa";
|
|
5
5
|
import { ITSelectProps } from "./select.props";
|
|
6
6
|
import ITText from "@/components/text/text";
|
|
7
|
+
import { inputError, inputLabel } from "@/utils/styles";
|
|
7
8
|
|
|
8
9
|
export default function ITSelect({
|
|
9
10
|
name,
|
|
@@ -80,13 +81,10 @@ export default function ITSelect({
|
|
|
80
81
|
<ITText
|
|
81
82
|
as="label"
|
|
82
83
|
htmlFor={name}
|
|
83
|
-
className={
|
|
84
|
-
"text-sm font-medium text-gray-700 dark:text-slate-300 pt-0",
|
|
85
|
-
{ "text-red-500": hasError }
|
|
86
|
-
)}
|
|
84
|
+
className={inputLabel(hasError)}
|
|
87
85
|
>
|
|
88
86
|
<ITText as="span">{label}</ITText>
|
|
89
|
-
{required && <ITText as="span" className="text-
|
|
87
|
+
{required && <ITText as="span" className="text-danger-500 ml-1">*</ITText>}
|
|
90
88
|
</ITText>
|
|
91
89
|
)}
|
|
92
90
|
<div className="flex flex-col w-full">
|
|
@@ -110,11 +108,11 @@ export default function ITSelect({
|
|
|
110
108
|
)}
|
|
111
109
|
style={getStyle()}
|
|
112
110
|
>
|
|
113
|
-
<option value=""
|
|
111
|
+
<option value="">{placeholder || "Selecciona una opción"}</option>
|
|
114
112
|
{
|
|
115
113
|
readOnly ? (
|
|
116
114
|
<option value={value} disabled>
|
|
117
|
-
|
|
115
|
+
{options.find((option) => option[valueField] === value)?.[labelField]}
|
|
118
116
|
</option>
|
|
119
117
|
) : (
|
|
120
118
|
options.map((option) => (
|
|
@@ -123,20 +121,20 @@ export default function ITSelect({
|
|
|
123
121
|
value={option[valueField]}
|
|
124
122
|
title={option[labelField]}
|
|
125
123
|
>
|
|
126
|
-
|
|
124
|
+
{option[labelField]}
|
|
127
125
|
</option>
|
|
128
126
|
))
|
|
129
127
|
)
|
|
130
128
|
}
|
|
131
129
|
</select>
|
|
132
|
-
<div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none text-
|
|
130
|
+
<div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none text-secondary-500">
|
|
133
131
|
<FaAngleDown />
|
|
134
132
|
</div>
|
|
135
133
|
</div>
|
|
136
134
|
{/* Validation message aligned with select */}
|
|
137
135
|
{hasError && (
|
|
138
136
|
<div className="flex-shrink-0 min-w-[140px] flex items-center pt-3">
|
|
139
|
-
<ITText as="p" className=
|
|
137
|
+
<ITText as="p" className={inputError}>{errorMessage}</ITText>
|
|
140
138
|
</div>
|
|
141
139
|
)}
|
|
142
140
|
</div>
|
|
@@ -121,12 +121,12 @@ export default function ITSidebar({
|
|
|
121
121
|
${sidebarWidth}
|
|
122
122
|
${className}
|
|
123
123
|
${!visibleOnMobile ? "hidden lg:flex" : "flex"}
|
|
124
|
-
shadow-[
|
|
124
|
+
shadow-[4px_0_32px_rgba(15,23,42,0.04)]
|
|
125
125
|
`}
|
|
126
126
|
style={{
|
|
127
127
|
zIndex: 50,
|
|
128
128
|
backgroundColor: "var(--sidebar-bg, rgba(255, 255, 255, 0.90))",
|
|
129
|
-
borderRight: "1px solid var(--sidebar-border,
|
|
129
|
+
borderRight: "1px solid var(--sidebar-border, var(--color-secondary-200))",
|
|
130
130
|
WebkitBackdropFilter: 'blur(12px)',
|
|
131
131
|
backdropFilter: 'blur(12px)',
|
|
132
132
|
}}
|
|
@@ -143,12 +143,12 @@ export default function ITSidebar({
|
|
|
143
143
|
${isSidebarCollapsed ? "justify-center p-2.5 mb-2" : "justify-between px-3.5 py-3 mb-1"}
|
|
144
144
|
`}
|
|
145
145
|
style={{
|
|
146
|
-
backgroundColor: item.isActive ? "var(--sidebar-active-bg,
|
|
147
|
-
boxShadow: item.isActive ? '
|
|
148
|
-
border: item.isActive ? "1px solid var(--sidebar-border,
|
|
146
|
+
backgroundColor: item.isActive ? "var(--sidebar-active-bg, var(--color-secondary-50))" : 'transparent',
|
|
147
|
+
boxShadow: item.isActive ? 'var(--shadow-xs)' : 'none',
|
|
148
|
+
border: item.isActive ? "1px solid var(--sidebar-border, var(--color-secondary-200))" : '1px solid transparent'
|
|
149
149
|
}}
|
|
150
150
|
onMouseEnter={(e) => {
|
|
151
|
-
if (!item.isActive) e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg,
|
|
151
|
+
if (!item.isActive) e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, var(--color-secondary-100))";
|
|
152
152
|
}}
|
|
153
153
|
onMouseLeave={(e) => {
|
|
154
154
|
if (!item.isActive) e.currentTarget.style.backgroundColor = 'transparent';
|
|
@@ -158,7 +158,7 @@ export default function ITSidebar({
|
|
|
158
158
|
{item.isActive && !isSidebarCollapsed && (
|
|
159
159
|
<div
|
|
160
160
|
className="absolute left-0 top-1/4 bottom-1/4 w-[3px] rounded-r-full transition-all"
|
|
161
|
-
style={{ backgroundColor: "var(--sidebar-active-icon,
|
|
161
|
+
style={{ backgroundColor: "var(--sidebar-active-icon, var(--color-primary-500))", boxShadow: "0 0 10px var(--sidebar-active-icon, var(--color-primary-500))" }}
|
|
162
162
|
/>
|
|
163
163
|
)}
|
|
164
164
|
|
|
@@ -167,7 +167,7 @@ export default function ITSidebar({
|
|
|
167
167
|
<div
|
|
168
168
|
className={`transition-all duration-300 flex-shrink-0 flex items-center justify-center`}
|
|
169
169
|
style={{
|
|
170
|
-
color: item.isActive ? "var(--sidebar-active-icon,
|
|
170
|
+
color: item.isActive ? "var(--sidebar-active-icon, var(--color-primary-500))" : "var(--sidebar-icon-color, #9ca3af)",
|
|
171
171
|
opacity: item.isActive ? 1 : 0.8,
|
|
172
172
|
fontSize: item.isActive ? '1.35rem' : '1.25rem',
|
|
173
173
|
filter: item.isActive ? 'drop-shadow(0 0 8px rgba(255,255,255,0.2))' : 'none'
|
|
@@ -181,7 +181,7 @@ export default function ITSidebar({
|
|
|
181
181
|
<ITText as="span"
|
|
182
182
|
className={`transition-all duration-300 truncate tracking-wide`}
|
|
183
183
|
style={{
|
|
184
|
-
color: item.isActive ? "var(--sidebar-active-color, #ffffff)" : "var(--sidebar-label-color,
|
|
184
|
+
color: item.isActive ? "var(--sidebar-active-color, #ffffff)" : "var(--sidebar-label-color, var(--color-secondary-300))",
|
|
185
185
|
fontSize: '0.9rem',
|
|
186
186
|
fontWeight: item.isActive ? '600' : '500'
|
|
187
187
|
}}
|
|
@@ -193,7 +193,7 @@ export default function ITSidebar({
|
|
|
193
193
|
|
|
194
194
|
{!isSidebarCollapsed && item.subitems && item.subitems.length > 0 && (
|
|
195
195
|
<div className={`flex-shrink-0 transition-transform duration-300 ease-[cubic-bezier(0.2,0,0,1)] ${expandedItems.has(item.id) ? "rotate-180" : ""}`}
|
|
196
|
-
style={{ color: item.isActive ? "var(--sidebar-active-color,
|
|
196
|
+
style={{ color: item.isActive ? "var(--sidebar-active-color, var(--color-secondary-900))" : "var(--sidebar-icon-color, var(--color-secondary-500))", opacity: 0.7 }}>
|
|
197
197
|
<FaChevronDown className="w-3 h-3" />
|
|
198
198
|
</div>
|
|
199
199
|
)}
|
|
@@ -207,9 +207,9 @@ export default function ITSidebar({
|
|
|
207
207
|
: "right-3 top-1/2 transform -translate-y-1/2 px-2 py-0.5 text-[10px] rounded-full backdrop-blur-sm"}
|
|
208
208
|
`}
|
|
209
209
|
style={{
|
|
210
|
-
backgroundColor: "var(--sidebar-badge-bg,
|
|
210
|
+
backgroundColor: "var(--sidebar-badge-bg, var(--color-primary-500))",
|
|
211
211
|
color: "var(--sidebar-badge-color, #ffffff)",
|
|
212
|
-
boxShadow: isSidebarCollapsed ? "0 0 0 2px var(--sidebar-bg,
|
|
212
|
+
boxShadow: isSidebarCollapsed ? "0 0 0 2px var(--sidebar-bg, var(--color-secondary-900))" : 'none'
|
|
213
213
|
}}
|
|
214
214
|
>
|
|
215
215
|
{isSidebarCollapsed ? "" : item.badge}
|
|
@@ -220,16 +220,16 @@ export default function ITSidebar({
|
|
|
220
220
|
{/* Glassmorphism Collapsed Tooltip / Submenu */}
|
|
221
221
|
{isSidebarCollapsed && (
|
|
222
222
|
<div
|
|
223
|
-
className="absolute left-full top-0 ml-4 rounded-2xl opacity-0 invisible group-hover/navitem:opacity-100 group-hover/navitem:visible transition-all duration-300 pointer-events-none z-
|
|
223
|
+
className="absolute left-full top-0 ml-4 rounded-2xl opacity-0 invisible group-hover/navitem:opacity-100 group-hover/navitem:visible transition-all duration-300 pointer-events-none z-[70] min-w-[220px] overflow-hidden -translate-x-2 group-hover/navitem:translate-x-0 shadow-[0_10px_40px_-10px_rgba(0,0,0,0.15)]"
|
|
224
224
|
style={{
|
|
225
225
|
backgroundColor: "var(--sidebar-bg, #ffffff)",
|
|
226
|
-
border: "1px solid var(--sidebar-border,
|
|
226
|
+
border: "1px solid var(--sidebar-border, var(--color-secondary-200))",
|
|
227
227
|
WebkitBackdropFilter: 'blur(16px)',
|
|
228
228
|
backdropFilter: 'blur(16px)',
|
|
229
229
|
}}
|
|
230
230
|
>
|
|
231
|
-
<div className="px-5 py-4 flex items-center gap-3 font-semibold border-b" style={{ borderColor: "var(--sidebar-border,
|
|
232
|
-
{item.icon && <span style={{ color: "var(--sidebar-active-icon,
|
|
231
|
+
<div className="px-5 py-4 flex items-center gap-3 font-semibold border-b" style={{ borderColor: "var(--sidebar-border, var(--color-secondary-200))", color: "var(--sidebar-active-color, var(--color-secondary-900))" }}>
|
|
232
|
+
{item.icon && <span style={{ color: "var(--sidebar-active-icon, var(--color-primary-500))" }} className="text-xl drop-shadow-sm">{item.icon}</span>}
|
|
233
233
|
<ITText as="span" className="tracking-wide text-[15px]">{item.label}</ITText>
|
|
234
234
|
</div>
|
|
235
235
|
|
|
@@ -244,18 +244,18 @@ export default function ITSidebar({
|
|
|
244
244
|
<div
|
|
245
245
|
className="absolute left-0 top-1/3 bottom-1/3 w-[2.5px] rounded-r-full"
|
|
246
246
|
style={{
|
|
247
|
-
backgroundColor: "var(--sidebar-active-icon,
|
|
248
|
-
boxShadow: "0 0 6px color-mix(in srgb, var(--sidebar-active-icon,
|
|
247
|
+
backgroundColor: "var(--sidebar-active-icon, var(--color-primary-500))",
|
|
248
|
+
boxShadow: "0 0 6px color-mix(in srgb, var(--sidebar-active-icon, var(--color-primary-500)) 25%, transparent)",
|
|
249
249
|
}}
|
|
250
250
|
/>
|
|
251
251
|
)}
|
|
252
|
-
<span className={`w-1.5 h-1.5 rounded-full transition-all ${subitem.isActive ? "scale-125" : ""}`} style={{ backgroundColor: subitem.isActive ? "var(--sidebar-active-icon,
|
|
253
|
-
<ITText as="span" style={{ color: subitem.isActive ? "var(--sidebar-active-color,
|
|
252
|
+
<span className={`w-1.5 h-1.5 rounded-full transition-all ${subitem.isActive ? "scale-125" : ""}`} style={{ backgroundColor: subitem.isActive ? "var(--sidebar-active-icon, var(--color-primary-500))" : "var(--sidebar-icon-color, var(--color-secondary-400))" }} />
|
|
253
|
+
<ITText as="span" style={{ color: subitem.isActive ? "var(--sidebar-active-color, var(--color-secondary-900))" : "var(--sidebar-label-color, var(--color-secondary-600))", fontWeight: subitem.isActive ? 600 : 500 }}>{subitem.label}</ITText>
|
|
254
254
|
</div>
|
|
255
255
|
))}
|
|
256
256
|
</div>
|
|
257
257
|
) : (
|
|
258
|
-
<ITText as="div" className="px-5 py-3 text-sm italic" style={{ color: "var(--sidebar-label-color,
|
|
258
|
+
<ITText as="div" className="px-5 py-3 text-sm italic" style={{ color: "var(--sidebar-label-color, var(--color-secondary-400))" }}>No hay submenú</ITText>
|
|
259
259
|
)}
|
|
260
260
|
</div>
|
|
261
261
|
)}
|
|
@@ -267,7 +267,7 @@ export default function ITSidebar({
|
|
|
267
267
|
className="ml-5 flex flex-col gap-0.5 py-1"
|
|
268
268
|
style={{
|
|
269
269
|
borderLeft: subitemConnector === '|'
|
|
270
|
-
? "1px solid var(--sidebar-border,
|
|
270
|
+
? "1px solid var(--sidebar-border, var(--color-secondary-200))"
|
|
271
271
|
: 'none'
|
|
272
272
|
}}
|
|
273
273
|
>
|
|
@@ -280,8 +280,8 @@ export default function ITSidebar({
|
|
|
280
280
|
}}
|
|
281
281
|
className={`flex items-center gap-2.5 w-full text-left px-3 py-2 rounded-xl transition-all duration-300`}
|
|
282
282
|
style={{
|
|
283
|
-
color: subitem.isActive ? "var(--sidebar-active-color,
|
|
284
|
-
backgroundColor: subitem.isActive ? "var(--sidebar-active-bg,
|
|
283
|
+
color: subitem.isActive ? "var(--sidebar-active-color, var(--color-secondary-900))" : "var(--sidebar-label-color, var(--color-secondary-600))",
|
|
284
|
+
backgroundColor: subitem.isActive ? "var(--sidebar-active-bg, var(--color-secondary-50))" : 'transparent',
|
|
285
285
|
fontSize: '0.85rem',
|
|
286
286
|
fontWeight: subitem.isActive ? 600 : 500,
|
|
287
287
|
letterSpacing: '0.01em',
|
|
@@ -289,7 +289,7 @@ export default function ITSidebar({
|
|
|
289
289
|
}}
|
|
290
290
|
onMouseEnter={(e) => {
|
|
291
291
|
if (!subitem.isActive) {
|
|
292
|
-
e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg,
|
|
292
|
+
e.currentTarget.style.backgroundColor = "var(--sidebar-hover-bg, var(--color-secondary-100))";
|
|
293
293
|
e.currentTarget.style.transform = 'translateX(3px)';
|
|
294
294
|
}
|
|
295
295
|
}}
|
|
@@ -304,8 +304,8 @@ export default function ITSidebar({
|
|
|
304
304
|
<div
|
|
305
305
|
className="absolute left-0 top-1/3 bottom-1/3 w-[2.5px] rounded-r-full transition-all"
|
|
306
306
|
style={{
|
|
307
|
-
backgroundColor: "var(--sidebar-active-icon,
|
|
308
|
-
boxShadow: "0 0 6px color-mix(in srgb, var(--sidebar-active-icon,
|
|
307
|
+
backgroundColor: "var(--sidebar-active-icon, var(--color-primary-500))",
|
|
308
|
+
boxShadow: "0 0 6px color-mix(in srgb, var(--sidebar-active-icon, var(--color-primary-500)) 25%, transparent)",
|
|
309
309
|
}}
|
|
310
310
|
/>
|
|
311
311
|
)}
|
|
@@ -314,8 +314,8 @@ export default function ITSidebar({
|
|
|
314
314
|
className={`w-1.5 h-1.5 rounded-full flex-shrink-0 transition-all duration-300 ${subitem.isActive ? 'scale-125' : ''}`}
|
|
315
315
|
style={{
|
|
316
316
|
backgroundColor: subitem.isActive
|
|
317
|
-
? "var(--sidebar-active-icon,
|
|
318
|
-
: "var(--sidebar-icon-color,
|
|
317
|
+
? "var(--sidebar-active-icon, var(--color-primary-500))"
|
|
318
|
+
: "var(--sidebar-icon-color, var(--color-secondary-400))"
|
|
319
319
|
}}
|
|
320
320
|
/>
|
|
321
321
|
)}
|
|
@@ -30,7 +30,7 @@ export default function ITSlider({
|
|
|
30
30
|
return (
|
|
31
31
|
<div className={clsx("flex flex-col gap-1.5", className)}>
|
|
32
32
|
{label && (
|
|
33
|
-
<ITText as="label" className="text-xs font-semibold text-
|
|
33
|
+
<ITText as="label" className="text-xs font-semibold text-secondary-600 dark:text-secondary-400">
|
|
34
34
|
{label}: {value}
|
|
35
35
|
</ITText>
|
|
36
36
|
)}
|
|
@@ -45,7 +45,7 @@ export default function ITSlider({
|
|
|
45
45
|
disabled={disabled}
|
|
46
46
|
className={clsx(
|
|
47
47
|
"w-full h-1.5 appearance-none rounded-full outline-none cursor-pointer",
|
|
48
|
-
"bg-
|
|
48
|
+
"bg-secondary-200 dark:bg-secondary-700",
|
|
49
49
|
"accent-primary-500",
|
|
50
50
|
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
51
51
|
"[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4",
|
|
@@ -54,7 +54,7 @@ export default function ITSlider({
|
|
|
54
54
|
"[&::-webkit-slider-thumb]:hover:bg-primary-600 [&::-webkit-slider-thumb]:transition-colors",
|
|
55
55
|
"[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:rounded-full",
|
|
56
56
|
"[&::-moz-range-thumb]:bg-primary-500 [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-white",
|
|
57
|
-
"[&::-moz-range-track]:bg-
|
|
57
|
+
"[&::-moz-range-track]:bg-secondary-200 dark:[&::-moz-range-track]:bg-secondary-700",
|
|
58
58
|
"[&::-moz-range-track]:rounded-full [&::-moz-range-track]:h-1.5"
|
|
59
59
|
)}
|
|
60
60
|
/>
|
|
@@ -2,9 +2,13 @@ import React from "react";
|
|
|
2
2
|
|
|
3
3
|
export type IconType = React.ReactNode;
|
|
4
4
|
|
|
5
|
+
/** A single step in an `ITStepper` flow. */
|
|
5
6
|
export interface Step {
|
|
7
|
+
/** Label shown next to the step indicator. */
|
|
6
8
|
label: string;
|
|
9
|
+
/** Content rendered in the panel while this step is active. */
|
|
7
10
|
content: React.ReactNode;
|
|
11
|
+
/** Custom icon shown in the step indicator when the stepper's `useIcons` is true. */
|
|
8
12
|
icon?: IconType;
|
|
9
13
|
}
|
|
10
14
|
|
|
@@ -128,7 +128,7 @@ export default function ITStepper({
|
|
|
128
128
|
<div className={clsx("w-full max-w-5xl mx-auto px-4", containerClassName)}>
|
|
129
129
|
<div className="relative mb-8">
|
|
130
130
|
<div
|
|
131
|
-
className="absolute left-6 right-6 top-5 h-1 bg-
|
|
131
|
+
className="absolute left-6 right-6 top-5 h-1 bg-secondary-200 rounded-full z-0"
|
|
132
132
|
aria-hidden
|
|
133
133
|
/>
|
|
134
134
|
<div
|
|
@@ -161,7 +161,7 @@ export default function ITStepper({
|
|
|
161
161
|
hasIcon && "p-2",
|
|
162
162
|
isCompleted && "bg-slate-400 border-slate-400 text-white scale-100 shadow",
|
|
163
163
|
isActive && "text-white scale-110 shadow-lg",
|
|
164
|
-
!isActive && !isCompleted && "bg-white border-
|
|
164
|
+
!isActive && !isCompleted && "bg-white border-secondary-300 text-secondary-400"
|
|
165
165
|
)}
|
|
166
166
|
style={isActive ? { backgroundColor: resolvedColor, borderColor: resolvedColor } : undefined}
|
|
167
167
|
>
|
|
@@ -172,7 +172,7 @@ export default function ITStepper({
|
|
|
172
172
|
as="span"
|
|
173
173
|
className={clsx(
|
|
174
174
|
"mt-2 text-xs sm:text-sm font-medium transition-colors text-center",
|
|
175
|
-
isCompleted ? "text-slate-400" : !isActive && "text-
|
|
175
|
+
isCompleted ? "text-slate-400" : !isActive && "text-secondary-400"
|
|
176
176
|
)}
|
|
177
177
|
style={isActive ? { color: resolvedColor } : undefined}
|
|
178
178
|
>
|
|
@@ -193,7 +193,7 @@ export default function ITStepper({
|
|
|
193
193
|
aria-labelledby={`step-${currentStep}`}
|
|
194
194
|
className={clsx(
|
|
195
195
|
stepClassName,
|
|
196
|
-
"bg-white border border-
|
|
196
|
+
"bg-white border border-secondary-100 rounded-2xl shadow-lg min-h-[280px] transition-transform duration-400 no-scrollbar p-6",
|
|
197
197
|
scrollableContent && "overflow-y-auto hide-scrollbar"
|
|
198
198
|
)}
|
|
199
199
|
style={
|
|
@@ -220,7 +220,7 @@ export default function ITStepper({
|
|
|
220
220
|
</ITButton>
|
|
221
221
|
|
|
222
222
|
<div className="flex items-center gap-3">
|
|
223
|
-
<ITText as="div" className="text-sm text-
|
|
223
|
+
<ITText as="div" className="text-sm text-secondary-500 mr-2 hidden sm:block">
|
|
224
224
|
Paso {currentStep + 1} de {steps.length}
|
|
225
225
|
</ITText>
|
|
226
226
|
|
|
@@ -1,31 +1,49 @@
|
|
|
1
1
|
import { TableSize, TableVariants } from "@/types/table.types";
|
|
2
2
|
|
|
3
|
+
/** Data type of a table column, controls default rendering, filter UI, and sort comparison. */
|
|
3
4
|
export type ColumnType = "string" | "date" | "number" | "boolean" | "actions" | "catalog";
|
|
4
5
|
|
|
6
|
+
/** A single selectable entry for a `"catalog"`-type column's filter/value lookup. */
|
|
5
7
|
export interface CatalogOption {
|
|
8
|
+
/** Unique identifier matched against the row's field value. */
|
|
6
9
|
id: string | number;
|
|
10
|
+
/** Human-readable label shown in the filter dropdown and resolved cell display. */
|
|
7
11
|
name: string;
|
|
8
12
|
}
|
|
9
13
|
|
|
14
|
+
/** Definition of a single column for ITTable. */
|
|
10
15
|
export interface Column<T = any> {
|
|
16
|
+
/** Field key on the row object this column reads from (supports dot-notation for nested values, e.g. `"address.city"`). */
|
|
11
17
|
key: string;
|
|
18
|
+
/** Column header text. */
|
|
12
19
|
label: string;
|
|
20
|
+
/** Additional CSS classes applied to both the header (`<th>`) and body (`<td>`) cells of this column. */
|
|
13
21
|
className?: string;
|
|
14
|
-
|
|
22
|
+
/** Formats numeric values as Mexican pesos (MXN) via `Intl`-based currency formatting. Only applies when `type` is `"number"`. @default false */
|
|
23
|
+
currencyMX?: boolean;
|
|
24
|
+
/** Custom action buttons/content rendered for a `"actions"`-type column. Receives the full row object. */
|
|
15
25
|
actions?: (row: T) => React.ReactNode;
|
|
26
|
+
/** Enables per-column filtering. Pass `true` for a text/number/boolean filter matching `type`, or `"catalog"` to filter against `catalogOptions`. @default false */
|
|
16
27
|
filter?: boolean | "catalog";
|
|
28
|
+
/** Column data type. Drives default cell rendering, filter UI, and sort comparison. */
|
|
17
29
|
type: ColumnType;
|
|
30
|
+
/** Whether clicking the header sorts by this column. Ignored for `type: "actions"`. @default false */
|
|
18
31
|
sortable?: boolean;
|
|
32
|
+
/** Custom cell renderer, takes precedence over the default type-based rendering. Receives the full row object. */
|
|
19
33
|
render?: (row: T) => React.ReactNode;
|
|
34
|
+
/** Custom inline-edit input renderer (used by table variants that support inline editing). */
|
|
20
35
|
editComponent?: (props: {
|
|
21
36
|
value: any;
|
|
22
37
|
onChange: (value: any) => void;
|
|
23
38
|
rowData: T;
|
|
24
39
|
}) => React.ReactNode;
|
|
25
|
-
|
|
40
|
+
/** Configuration for `type: "catalog"` columns: the lookup options plus loading/error state for async catalogs. */
|
|
26
41
|
catalogOptions?: {
|
|
42
|
+
/** Available catalog entries used to resolve/filter the raw id stored on the row. */
|
|
27
43
|
data: CatalogOption[];
|
|
44
|
+
/** Shows a loading spinner in the filter UI while the catalog is being fetched. @default false */
|
|
28
45
|
loading?: boolean;
|
|
46
|
+
/** Shows an error state in the filter UI when the catalog failed to load. @default false */
|
|
29
47
|
error?: boolean;
|
|
30
48
|
};
|
|
31
49
|
}
|
|
@@ -57,4 +75,4 @@ export interface ITTableProps<T> {
|
|
|
57
75
|
showVerticalBorder?: boolean;
|
|
58
76
|
/** Custom class for vertical borders (overrides the default subtle gray). */
|
|
59
77
|
verticalBorderClassname?: string;
|
|
60
|
-
}
|
|
78
|
+
}
|
|
@@ -15,6 +15,17 @@ import ITPagination from "../pagination/pagination";
|
|
|
15
15
|
import ITSelect from "../select/select";
|
|
16
16
|
import { Column, ITTableProps } from "./table.props";
|
|
17
17
|
import ITText from "@/components/text/text";
|
|
18
|
+
import {
|
|
19
|
+
tableActionsCell,
|
|
20
|
+
tableBody,
|
|
21
|
+
tableCell,
|
|
22
|
+
tableCellText,
|
|
23
|
+
tableContainer,
|
|
24
|
+
tableEmptyContent,
|
|
25
|
+
tableHeaderCell,
|
|
26
|
+
tableHeaderRow,
|
|
27
|
+
tableRow,
|
|
28
|
+
} from "@/utils/styles";
|
|
18
29
|
|
|
19
30
|
const getNestedValue = (obj: unknown, path: string) => {
|
|
20
31
|
return path.split(".").reduce((acc, part) => acc && acc[part], obj);
|
|
@@ -183,14 +194,14 @@ export default function ITTable<T extends Record<string, unknown>>({
|
|
|
183
194
|
aria-label={`${getToggleLabel()} para ${col.label}`}
|
|
184
195
|
title={`${getToggleLabel()} para ${col.label}`}
|
|
185
196
|
>
|
|
186
|
-
<div className="relative w-10 h-5 bg-
|
|
197
|
+
<div className="relative w-10 h-5 bg-secondary-300 rounded-full">
|
|
187
198
|
<div
|
|
188
199
|
className={clsx(
|
|
189
200
|
"absolute top-0.5 w-4 h-4 rounded-full transition-all duration-300 shadow-sm",
|
|
190
201
|
{
|
|
191
|
-
"left-0.5 bg-
|
|
202
|
+
"left-0.5 bg-secondary-400": currentValue === undefined,
|
|
192
203
|
"left-5 bg-slate-500": currentValue === true,
|
|
193
|
-
"left-0.5 bg-
|
|
204
|
+
"left-0.5 bg-secondary-500": currentValue === false,
|
|
194
205
|
}
|
|
195
206
|
)}
|
|
196
207
|
/>
|
|
@@ -211,7 +222,7 @@ export default function ITTable<T extends Record<string, unknown>>({
|
|
|
211
222
|
}
|
|
212
223
|
|
|
213
224
|
if (col.catalogOptions.error) {
|
|
214
|
-
return <ITText as="span" className="text-
|
|
225
|
+
return <ITText as="span" className="text-danger-500 text-xs">Error cargando</ITText>;
|
|
215
226
|
}
|
|
216
227
|
|
|
217
228
|
return (
|
|
@@ -260,13 +271,13 @@ export default function ITTable<T extends Record<string, unknown>>({
|
|
|
260
271
|
case "boolean":
|
|
261
272
|
return value ? (
|
|
262
273
|
<FaCheck
|
|
263
|
-
className="text-
|
|
274
|
+
className="text-success-500"
|
|
264
275
|
aria-label="Verdadero"
|
|
265
276
|
title="Verdadero"
|
|
266
277
|
/>
|
|
267
278
|
) : (
|
|
268
279
|
<FaTimes
|
|
269
|
-
className="text-
|
|
280
|
+
className="text-danger-500"
|
|
270
281
|
aria-label="Falso"
|
|
271
282
|
title="Falso"
|
|
272
283
|
/>
|
|
@@ -312,7 +323,7 @@ export default function ITTable<T extends Record<string, unknown>>({
|
|
|
312
323
|
|
|
313
324
|
return (
|
|
314
325
|
<div className={clsx("space-y-4 w-full", containerClassName)}>
|
|
315
|
-
<div className=
|
|
326
|
+
<div className={tableContainer} style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
|
|
316
327
|
{/* Header outside overflow */}
|
|
317
328
|
{title && (
|
|
318
329
|
<div className="px-6 py-5 flex items-center justify-between" style={{ backgroundColor: 'var(--color-table-rowBg, #ffffff)' }}>
|
|
@@ -382,7 +393,7 @@ export default function ITTable<T extends Record<string, unknown>>({
|
|
|
382
393
|
</div>
|
|
383
394
|
))
|
|
384
395
|
) : (
|
|
385
|
-
<div className="
|
|
396
|
+
<div className={clsx(tableEmptyContent, "py-12")}>
|
|
386
397
|
<ITText as="span" className="text-lg">No se encontraron resultados</ITText>
|
|
387
398
|
<ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
|
|
388
399
|
</div>
|
|
@@ -400,12 +411,12 @@ export default function ITTable<T extends Record<string, unknown>>({
|
|
|
400
411
|
)}
|
|
401
412
|
>
|
|
402
413
|
<thead>
|
|
403
|
-
<tr className="
|
|
414
|
+
<tr className={clsx(tableHeaderRow, "dark:text-slate-200")}>
|
|
404
415
|
{columns.map((col) => (
|
|
405
416
|
<th
|
|
406
417
|
key={col.key}
|
|
407
418
|
scope="col"
|
|
408
|
-
className={
|
|
419
|
+
className={tableHeaderCell(col.className)}
|
|
409
420
|
>
|
|
410
421
|
<div className="flex flex-col gap-3 min-w-[150px]">
|
|
411
422
|
<div className="flex items-center justify-between gap-2">
|
|
@@ -431,24 +442,24 @@ export default function ITTable<T extends Record<string, unknown>>({
|
|
|
431
442
|
))}
|
|
432
443
|
</tr>
|
|
433
444
|
</thead>
|
|
434
|
-
<tbody className="
|
|
445
|
+
<tbody className={clsx(tableBody, "dark:divide-slate-700/30")}>
|
|
435
446
|
{currentData.length > 0 ? (
|
|
436
447
|
currentData.map((row, rowIndex) => (
|
|
437
448
|
<tr
|
|
438
449
|
key={rowIndex}
|
|
439
|
-
className={clsx(
|
|
450
|
+
className={clsx(tableRow, variant === "striped" && "odd:bg-secondary-50/40 dark:odd:bg-slate-800/20")}
|
|
440
451
|
>
|
|
441
452
|
{columns.map((col) => (
|
|
442
453
|
<td
|
|
443
454
|
key={`${rowIndex}-${col.key}`}
|
|
444
|
-
className={
|
|
455
|
+
className={tableCell(col.className)}
|
|
445
456
|
>
|
|
446
457
|
{col.type === "actions" ? (
|
|
447
|
-
<div className=
|
|
458
|
+
<div className={tableActionsCell}>
|
|
448
459
|
{renderCellContent(col, row) as React.ReactNode}
|
|
449
460
|
</div>
|
|
450
461
|
) : (
|
|
451
|
-
<div className=
|
|
462
|
+
<div className={tableCellText}>
|
|
452
463
|
{renderCellContent(col, row) as React.ReactNode}
|
|
453
464
|
</div>
|
|
454
465
|
)}
|
|
@@ -459,7 +470,7 @@ export default function ITTable<T extends Record<string, unknown>>({
|
|
|
459
470
|
) : (
|
|
460
471
|
<tr>
|
|
461
472
|
<td colSpan={columns.length} className="px-6 py-12 text-center">
|
|
462
|
-
<div className=
|
|
473
|
+
<div className={tableEmptyContent}>
|
|
463
474
|
<ITText as="span" className="text-lg">No se encontraron resultados</ITText>
|
|
464
475
|
<ITText as="span" className="text-sm mt-1">Intenta ajustar los filtros</ITText>
|
|
465
476
|
</div>
|
|
@@ -39,8 +39,8 @@ const ITTabs: React.FC<ITTabsProps> = ({
|
|
|
39
39
|
<div className={clsx("w-full", containerClassName)}>
|
|
40
40
|
{/* HEADER */}
|
|
41
41
|
<div className={clsx(
|
|
42
|
-
"flex border-
|
|
43
|
-
variant === 'line' ? "border-b" : "gap-2 p-1 bg-
|
|
42
|
+
"flex border-secondary-200 mb-4",
|
|
43
|
+
variant === 'line' ? "border-b" : "gap-2 p-1 bg-secondary-100 rounded-lg w-fit",
|
|
44
44
|
className
|
|
45
45
|
)}>
|
|
46
46
|
{items.map((item) => {
|
|
@@ -58,14 +58,14 @@ const ITTabs: React.FC<ITTabsProps> = ({
|
|
|
58
58
|
"border-b-2 -mb-[2px]",
|
|
59
59
|
isActive
|
|
60
60
|
? "border-primary-500 text-primary-600"
|
|
61
|
-
: "border-transparent text-
|
|
61
|
+
: "border-transparent text-secondary-500 hover:text-secondary-700 hover:border-secondary-300",
|
|
62
62
|
],
|
|
63
63
|
// PILL VARIANT
|
|
64
64
|
variant === 'pill' && [
|
|
65
65
|
"rounded-md",
|
|
66
66
|
isActive
|
|
67
67
|
? "bg-white text-primary-600 shadow-sm"
|
|
68
|
-
: "text-
|
|
68
|
+
: "text-secondary-500 hover:text-secondary-700",
|
|
69
69
|
],
|
|
70
70
|
item.disabled && "opacity-50 cursor-not-allowed"
|
|
71
71
|
)}
|
|
@@ -60,9 +60,9 @@ export default function ITTextarea({
|
|
|
60
60
|
"focus:ring-2",
|
|
61
61
|
resizeMap[resize],
|
|
62
62
|
error
|
|
63
|
-
? "border-
|
|
64
|
-
: "border-
|
|
65
|
-
disabled && "opacity-50 cursor-not-allowed bg-
|
|
63
|
+
? "border-danger-500 ring-danger-100 focus:border-danger-500 focus:ring-danger-100"
|
|
64
|
+
: "border-secondary-300 focus:border-primary-500 focus:ring-primary-100",
|
|
65
|
+
disabled && "opacity-50 cursor-not-allowed bg-secondary-100 dark:bg-slate-800"
|
|
66
66
|
)}
|
|
67
67
|
/>
|
|
68
68
|
{error && <ITText as="span" className={inputError}>{error}</ITText>}
|