@axzydev/axzy_ui_system 1.2.11 → 1.2.13
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 +21 -9
- package/dist/index.cjs +294 -257
- 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 +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +300 -263
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/avatar/avatar.tsx +1 -1
- package/src/components/calendar/calendar.tsx +1 -1
- package/src/components/card/card.tsx +11 -8
- package/src/components/data-table/dataTable.tsx +3 -3
- package/src/components/dialog/dialog.tsx +2 -2
- package/src/components/divider/divider.tsx +1 -1
- package/src/components/dropfile/dropfile.doc.mdx +15 -0
- package/src/components/dropfile/dropfile.props.ts +13 -0
- package/src/components/dropfile/dropfile.stories.tsx +21 -0
- package/src/components/dropfile/dropfile.tsx +90 -27
- package/src/components/form-builder/fieldRenderer.tsx +3 -3
- package/src/components/input/input.tsx +7 -7
- 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/search-select/search-select.tsx +8 -8
- 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 +2 -2
- package/src/components/sidebar/sidebar.tsx +15 -15
- package/src/components/slider/slider.tsx +3 -3
- package/src/components/stepper/stepper.tsx +5 -5
- package/src/components/table/table.tsx +3 -3
- package/src/components/tabs/tabs.tsx +4 -4
- package/src/components/textarea/textarea.tsx +3 -3
- package/src/components/theme-provider/themeProvider.tsx +32 -32
- package/src/components/time-picker/timePicker.tsx +5 -5
- package/src/components/topbar/topbar.tsx +6 -6
- package/src/index.css +23 -0
- package/src/theme/theme.ts +17 -17
- package/src/utils/styles.ts +5 -5
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ const sizeMap: Record<AvatarSize, { container: string; text: string }> = {
|
|
|
12
12
|
|
|
13
13
|
const DEFAULT_COLOR = "bg-primary-600";
|
|
14
14
|
const DEFAULT_BG = "var(--color-primary-600)";
|
|
15
|
-
const DEFAULT_SHADOW = "0
|
|
15
|
+
const DEFAULT_SHADOW = "0 6px 16px -2px rgba(37, 99, 235, 0.25)";
|
|
16
16
|
|
|
17
17
|
// Un valor tipo "#8b5cf6", "rgb(...)", "hsl(...)" o "var(--...)" se aplica
|
|
18
18
|
// como color inline; cualquier otra cosa se trata como clase de Tailwind
|
|
@@ -371,7 +371,7 @@ export const ITCalendar: React.FC<ITCalendarProps> = ({
|
|
|
371
371
|
{/* Weekday Headers */}
|
|
372
372
|
<div className="grid grid-cols-7 mb-2">
|
|
373
373
|
{['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'].map(day => (
|
|
374
|
-
<ITText key={day} as="div" className="text-center text-xs font-semibold text-
|
|
374
|
+
<ITText key={day} as="div" className="text-center text-xs font-semibold text-secondary-400 uppercase py-1">
|
|
375
375
|
{day}
|
|
376
376
|
</ITText>
|
|
377
377
|
))}
|
|
@@ -33,15 +33,18 @@ export default function ITCard({
|
|
|
33
33
|
|
|
34
34
|
const containerStyle: React.CSSProperties = {
|
|
35
35
|
backgroundColor: "var(--card-bg, #ffffff)",
|
|
36
|
-
borderColor: "var(--card-border,
|
|
36
|
+
borderColor: "var(--card-border, rgba(15, 23, 42, 0.06))",
|
|
37
37
|
borderWidth: "1px",
|
|
38
|
-
borderRadius: "var(--card-radius,
|
|
38
|
+
borderRadius: "var(--card-radius, var(--radius-2xl))",
|
|
39
|
+
// Soft depth: every card floats a little at rest; interactive cards
|
|
40
|
+
// gain visual weight on hover instead of appearing flat until clicked.
|
|
39
41
|
boxShadow: onClick
|
|
40
42
|
? isHovered
|
|
41
|
-
? "
|
|
42
|
-
: "
|
|
43
|
-
: "
|
|
44
|
-
transition: onClick ? "
|
|
43
|
+
? "var(--shadow-lg)"
|
|
44
|
+
: "var(--shadow-sm)"
|
|
45
|
+
: "var(--shadow-sm)",
|
|
46
|
+
transition: onClick ? "box-shadow 0.2s ease-in-out, transform 0.2s ease-in-out" : "none",
|
|
47
|
+
transform: onClick && isHovered ? "translateY(-2px)" : "translateY(0)",
|
|
45
48
|
cursor: onClick ? "pointer" : "default",
|
|
46
49
|
};
|
|
47
50
|
|
|
@@ -74,12 +77,12 @@ export default function ITCard({
|
|
|
74
77
|
{title}
|
|
75
78
|
</ITText>
|
|
76
79
|
)}
|
|
77
|
-
<ITText as="div" className="text-
|
|
80
|
+
<ITText as="div" className="text-secondary-600">{children}</ITText>
|
|
78
81
|
</div>
|
|
79
82
|
{actions && (
|
|
80
83
|
<div
|
|
81
84
|
className={clsx(
|
|
82
|
-
"p-4 border-t border-
|
|
85
|
+
"p-4 border-t border-secondary-100 mt-auto",
|
|
83
86
|
actionClassName,
|
|
84
87
|
)}
|
|
85
88
|
>
|
|
@@ -147,14 +147,14 @@ export default function ITDataTable<T extends Record<string, unknown>>({
|
|
|
147
147
|
title={`${getToggleLabel()} para ${col.label}`}
|
|
148
148
|
disabled={isLoading}
|
|
149
149
|
>
|
|
150
|
-
<div className="relative w-10 h-5 bg-
|
|
150
|
+
<div className="relative w-10 h-5 bg-secondary-300 rounded-full">
|
|
151
151
|
<div
|
|
152
152
|
className={clsx(
|
|
153
153
|
"absolute top-0.5 w-4 h-4 rounded-full transition-all duration-300 shadow-sm",
|
|
154
154
|
{
|
|
155
|
-
"left-0.5 bg-
|
|
155
|
+
"left-0.5 bg-secondary-400": currentValue === undefined,
|
|
156
156
|
"left-5 bg-slate-500": currentValue === true,
|
|
157
|
-
"left-0.5 bg-
|
|
157
|
+
"left-0.5 bg-secondary-500": currentValue === false,
|
|
158
158
|
}
|
|
159
159
|
)}
|
|
160
160
|
/>
|
|
@@ -70,7 +70,7 @@ export default function ITDialog({
|
|
|
70
70
|
data-it-dialog="true"
|
|
71
71
|
className={`fixed inset-0 flex ${
|
|
72
72
|
fullScreen ? "items-stretch" : "items-center justify-center"
|
|
73
|
-
} bg-
|
|
73
|
+
} bg-slate-900/50 z-[60]`}
|
|
74
74
|
>
|
|
75
75
|
<div
|
|
76
76
|
ref={modalRef}
|
|
@@ -98,7 +98,7 @@ export default function ITDialog({
|
|
|
98
98
|
) : (
|
|
99
99
|
<>
|
|
100
100
|
<button
|
|
101
|
-
className="absolute top-2 right-2 text-
|
|
101
|
+
className="absolute top-2 right-2 text-secondary-600 hover:text-secondary-900"
|
|
102
102
|
onClick={onClose}
|
|
103
103
|
>
|
|
104
104
|
<FaRegTimesCircle />
|
|
@@ -14,7 +14,7 @@ import { ITDividerProps } from "./divider.props";
|
|
|
14
14
|
*
|
|
15
15
|
* @example
|
|
16
16
|
* ```tsx
|
|
17
|
-
* <ITDivider orientation="vertical" color="bg-
|
|
17
|
+
* <ITDivider orientation="vertical" color="bg-danger-500" thickness="w-1" />
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
export default function ITDivider({
|
|
@@ -21,6 +21,9 @@ A drag-and-drop file upload zone with preview support for images. Tracks upload
|
|
|
21
21
|
| `uploadStatus` | `UploadStatus` | — | Externally controlled upload status. |
|
|
22
22
|
| `onStatusChange` | `(status: UploadStatus) => void` | — | Callback when upload status changes. |
|
|
23
23
|
| `initialPreviewUrl` | `string \| null` | — | Initial preview URL shown before any file is selected (e.g., editing an existing entry). |
|
|
24
|
+
| `view` | `"drop" \| "button"` | `"drop"` | `"drop"` renders the dropzone/preview inline. `"button"` renders a compact trigger button that opens the same UI inside an `ITDialog` modal. |
|
|
25
|
+
| `buttonLabel` | `string` | `"Subir archivo"` | Label for the trigger button when `view="button"` and no file is selected yet. |
|
|
26
|
+
| `modalTitle` | `string` | `buttonLabel` | Title of the modal opened when `view="button"`. |
|
|
24
27
|
|
|
25
28
|
### Enums
|
|
26
29
|
|
|
@@ -44,6 +47,18 @@ import { ITDropfile, UploadStatus, FileTypeEnum } from '@axzydev/axzy_ui_system'
|
|
|
44
47
|
/>
|
|
45
48
|
```
|
|
46
49
|
|
|
50
|
+
### `view="button"`
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
<ITDropfile
|
|
54
|
+
view="button"
|
|
55
|
+
buttonLabel="Subir archivos"
|
|
56
|
+
onFileSelect={(file) => setSelectedFile(file)}
|
|
57
|
+
/>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use this when you'd otherwise write your own button + modal wrapper around `ITDropfile` — it's built in. The button shows the picked file's name (and status badge, if `showStatusBadge`) once one is selected, and reopens the same dropzone/preview to change it. The modal auto-closes ~900ms after a successful confirm.
|
|
61
|
+
|
|
47
62
|
## Notes
|
|
48
63
|
|
|
49
64
|
- Displays image preview for image file types; shows a file icon for non-image types.
|
|
@@ -44,4 +44,17 @@ export interface ITDropfileProps {
|
|
|
44
44
|
onStatusChange?: (status: UploadStatus) => void;
|
|
45
45
|
/** An initial preview URL to display before any file is selected. */
|
|
46
46
|
initialPreviewUrl?: string | null;
|
|
47
|
+
/**
|
|
48
|
+
* Presentation mode. `"drop"` renders the dropzone/preview inline (default,
|
|
49
|
+
* current behavior). `"button"` renders a compact trigger button instead —
|
|
50
|
+
* clicking it opens the same dropzone/preview UI inside an `ITDialog`, so
|
|
51
|
+
* callers don't need to build their own "open a modal" button around
|
|
52
|
+
* `ITDropfile`.
|
|
53
|
+
* @default "drop"
|
|
54
|
+
*/
|
|
55
|
+
view?: "drop" | "button";
|
|
56
|
+
/** Label for the trigger button when `view="button"` and no file is selected yet. @default "Subir archivo" */
|
|
57
|
+
buttonLabel?: string;
|
|
58
|
+
/** Title of the modal opened when `view="button"`. Defaults to `buttonLabel`. */
|
|
59
|
+
modalTitle?: string;
|
|
47
60
|
}
|
|
@@ -18,6 +18,10 @@ const meta = {
|
|
|
18
18
|
control: 'select',
|
|
19
19
|
options: Object.values(UploadStatus),
|
|
20
20
|
},
|
|
21
|
+
view: {
|
|
22
|
+
control: 'radio',
|
|
23
|
+
options: ['drop', 'button'],
|
|
24
|
+
},
|
|
21
25
|
},
|
|
22
26
|
} satisfies Meta<typeof ITDropfile>;
|
|
23
27
|
|
|
@@ -64,6 +68,23 @@ export const Uploading: any = {
|
|
|
64
68
|
},
|
|
65
69
|
};
|
|
66
70
|
|
|
71
|
+
export const ButtonView: any = {
|
|
72
|
+
render: (args) => <DropfileWrapper {...args} />,
|
|
73
|
+
args: {
|
|
74
|
+
view: 'button',
|
|
75
|
+
buttonLabel: 'Subir archivos',
|
|
76
|
+
showStatusBadge: true,
|
|
77
|
+
},
|
|
78
|
+
parameters: {
|
|
79
|
+
docs: {
|
|
80
|
+
description: {
|
|
81
|
+
story:
|
|
82
|
+
'Compact trigger button that opens the dropzone/preview inside a modal (`ITDialog`) — use this instead of wrapping `ITDropfile` in your own "open a modal" button.',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
67
88
|
export const ErrorState: any = {
|
|
68
89
|
render: (args) => <DropfileWrapper {...args} />,
|
|
69
90
|
args: {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import React, { useState, useEffect
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
2
|
import { useDropzone } from "react-dropzone";
|
|
3
3
|
// import pdfjsLib from "@/hooks/pdf"; // Disabled as hook is missing
|
|
4
4
|
import clsx from "clsx";
|
|
5
5
|
import ITText from "@/components/text/text";
|
|
6
6
|
import ITButton from "@/components/button/button";
|
|
7
|
+
import ITDialog from "@/components/dialog/dialog";
|
|
7
8
|
import { ITDropfileProps, FileTypeEnum, UploadStatus } from "./dropfile.props";
|
|
8
9
|
export { FileTypeEnum, UploadStatus } from "./dropfile.props";
|
|
9
10
|
|
|
@@ -25,6 +26,17 @@ export { FileTypeEnum, UploadStatus } from "./dropfile.props";
|
|
|
25
26
|
* showStatusBadge
|
|
26
27
|
* />
|
|
27
28
|
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* Compact trigger button that opens the dropzone in a modal — no need to
|
|
32
|
+
* build your own "open a modal" button around `ITDropfile`:
|
|
33
|
+
* ```tsx
|
|
34
|
+
* <ITDropfile
|
|
35
|
+
* view="button"
|
|
36
|
+
* buttonLabel="Subir archivos"
|
|
37
|
+
* onFileSelect={(file) => setSelectedFile(file)}
|
|
38
|
+
* />
|
|
39
|
+
* ```
|
|
28
40
|
*/
|
|
29
41
|
const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
30
42
|
onFileSelect,
|
|
@@ -37,7 +49,11 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
37
49
|
uploadStatus: externalStatus,
|
|
38
50
|
onStatusChange,
|
|
39
51
|
initialPreviewUrl,
|
|
52
|
+
view = "drop",
|
|
53
|
+
buttonLabel = "Subir archivo",
|
|
54
|
+
modalTitle,
|
|
40
55
|
}) => {
|
|
56
|
+
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
41
57
|
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
|
42
58
|
const [fileType, setFileType] = useState<string | null>(null);
|
|
43
59
|
// Initialize preview with prop if available
|
|
@@ -47,8 +63,6 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
47
63
|
const [internalUploadStatus, setInternalUploadStatus] = useState<UploadStatus>(
|
|
48
64
|
initialPreviewUrl ? UploadStatus.UPLOADED : UploadStatus.PENDING
|
|
49
65
|
);
|
|
50
|
-
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
|
51
|
-
|
|
52
66
|
// Sync initialPreviewUrl if it changes
|
|
53
67
|
useEffect(() => {
|
|
54
68
|
if (initialPreviewUrl && !selectedFile) {
|
|
@@ -278,20 +292,30 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
278
292
|
handleCancel();
|
|
279
293
|
};
|
|
280
294
|
|
|
281
|
-
|
|
295
|
+
// In "button" view, close the modal a moment after a successful upload so
|
|
296
|
+
// the trigger collapses back to its compact state instead of leaving the
|
|
297
|
+
// modal open on a finished confirmation.
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
if (view === "button" && isConfirmed && uploadStatus === UploadStatus.UPLOADED) {
|
|
300
|
+
const timeout = setTimeout(() => setIsModalOpen(false), 900);
|
|
301
|
+
return () => clearTimeout(timeout);
|
|
302
|
+
}
|
|
303
|
+
}, [view, isConfirmed, uploadStatus]);
|
|
282
304
|
|
|
283
|
-
|
|
284
|
-
<div className=
|
|
285
|
-
<
|
|
286
|
-
<
|
|
287
|
-
|
|
288
|
-
</label>
|
|
289
|
-
|
|
290
|
-
{showStatusBadge && selectedFile && (
|
|
291
|
-
<StatusBadge status={uploadStatus} />
|
|
292
|
-
)}
|
|
293
|
-
</div>
|
|
305
|
+
const headerRow = (
|
|
306
|
+
<div className="flex items-center justify-between mb-2">
|
|
307
|
+
<label className="block text-sm font-semibold text-secondary-700">
|
|
308
|
+
<ITText as="span">Subir archivo </ITText><ITText as="span" className="text-secondary-400 font-normal text-xs">({getFileExtensions()})</ITText>
|
|
309
|
+
</label>
|
|
294
310
|
|
|
311
|
+
{showStatusBadge && selectedFile && (
|
|
312
|
+
<StatusBadge status={uploadStatus} />
|
|
313
|
+
)}
|
|
314
|
+
</div>
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const dropZoneOrPreview = (
|
|
318
|
+
<>
|
|
295
319
|
{!selectedFile && !imagePreview ? (
|
|
296
320
|
<div
|
|
297
321
|
{...getRootProps()}
|
|
@@ -301,15 +325,15 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
301
325
|
${
|
|
302
326
|
isDragActive
|
|
303
327
|
? "border-primary-500 bg-primary-50 scale-[1.01]"
|
|
304
|
-
: "border-
|
|
328
|
+
: "border-secondary-300 bg-white hover:border-primary-400 hover:bg-secondary-50"
|
|
305
329
|
}
|
|
306
330
|
`}
|
|
307
331
|
>
|
|
308
332
|
<input {...getInputProps()} />
|
|
309
333
|
|
|
310
|
-
<div className={`mb-3 p-3 rounded-full transition-colors duration-300 ${isDragActive ? 'bg-primary-100' : 'bg-
|
|
334
|
+
<div className={`mb-3 p-3 rounded-full transition-colors duration-300 ${isDragActive ? 'bg-primary-100' : 'bg-secondary-100 group-hover:bg-primary-50'}`}>
|
|
311
335
|
<svg
|
|
312
|
-
className={`w-6 h-6 transition-colors duration-300 ${isDragActive ? 'text-primary-600' : 'text-
|
|
336
|
+
className={`w-6 h-6 transition-colors duration-300 ${isDragActive ? 'text-primary-600' : 'text-secondary-400 group-hover:text-primary-500'}`}
|
|
313
337
|
fill="none" viewBox="0 0 24 24" stroke="currentColor"
|
|
314
338
|
>
|
|
315
339
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
|
|
@@ -317,14 +341,14 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
317
341
|
</div>
|
|
318
342
|
|
|
319
343
|
<div className="text-center space-y-1">
|
|
320
|
-
<ITText as="p" className={`text-sm font-medium transition-colors duration-300 ${isDragActive ? 'text-primary-700' : 'text-
|
|
344
|
+
<ITText as="p" className={`text-sm font-medium transition-colors duration-300 ${isDragActive ? 'text-primary-700' : 'text-secondary-700'}`}>
|
|
321
345
|
{isDragActive ? "¡Suelta aquí!" : "Haz clic o arrastra"}
|
|
322
346
|
</ITText>
|
|
323
347
|
</div>
|
|
324
348
|
</div>
|
|
325
349
|
) : (
|
|
326
|
-
<div className="w-full bg-white border border-
|
|
327
|
-
<div className="flex items-center justify-between p-3 bg-
|
|
350
|
+
<div className="w-full bg-white border border-secondary-200 rounded-xl shadow-sm overflow-hidden animate-fade-in">
|
|
351
|
+
<div className="flex items-center justify-between p-3 bg-secondary-50 border-b border-secondary-100">
|
|
328
352
|
<div className="flex items-center gap-3 overflow-hidden">
|
|
329
353
|
<div className="flex-shrink-0 w-8 h-8 rounded-lg bg-primary-100 flex items-center justify-center text-primary-600">
|
|
330
354
|
{(selectedFile && fileType?.startsWith('image/')) || (!selectedFile && imagePreview) ? (
|
|
@@ -338,17 +362,17 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
338
362
|
)}
|
|
339
363
|
</div>
|
|
340
364
|
<div className="min-w-0">
|
|
341
|
-
<ITText as="p" className="text-xs font-medium text-
|
|
365
|
+
<ITText as="p" className="text-xs font-medium text-secondary-900 truncate" title={selectedFile?.name || "Imagen cargada"}>
|
|
342
366
|
{selectedFile?.name || "Imagen cargada"}
|
|
343
367
|
</ITText>
|
|
344
|
-
<ITText as="p" className="text-[10px] text-
|
|
368
|
+
<ITText as="p" className="text-[10px] text-secondary-500">
|
|
345
369
|
{selectedFile ? (selectedFile.size / 1024 / 1024).toFixed(2) + " MB" : ""}
|
|
346
370
|
</ITText>
|
|
347
371
|
</div>
|
|
348
372
|
</div>
|
|
349
373
|
</div>
|
|
350
374
|
|
|
351
|
-
<div className={clsx("relative bg-
|
|
375
|
+
<div className={clsx("relative bg-secondary-100 flex items-center justify-center", !contentClassName ? "max-h-[200px] min-h-[100px] overflow-auto" : contentClassName)}>
|
|
352
376
|
{((selectedFile && fileType?.startsWith('image/')) || (!selectedFile && imagePreview)) ? (
|
|
353
377
|
<img
|
|
354
378
|
src={imagePreview}
|
|
@@ -356,7 +380,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
356
380
|
className="w-full h-full object-contain max-h-[200px]"
|
|
357
381
|
/>
|
|
358
382
|
) : (
|
|
359
|
-
<div className="py-8 flex flex-col items-center text-
|
|
383
|
+
<div className="py-8 flex flex-col items-center text-secondary-400">
|
|
360
384
|
<svg className="w-10 h-10 mb-2 opacity-50" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
361
385
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
|
|
362
386
|
</svg>
|
|
@@ -365,7 +389,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
365
389
|
)}
|
|
366
390
|
</div>
|
|
367
391
|
|
|
368
|
-
<div className="px-3 py-2 bg-white border-t border-
|
|
392
|
+
<div className="px-3 py-2 bg-white border-t border-secondary-100 flex justify-end gap-2">
|
|
369
393
|
{!isConfirmed ? (
|
|
370
394
|
<>
|
|
371
395
|
<ITButton
|
|
@@ -410,7 +434,7 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
410
434
|
|
|
411
435
|
{uploadStatus === UploadStatus.UPLOADING && (
|
|
412
436
|
<div className="px-4 pb-2">
|
|
413
|
-
<div className="w-full bg-
|
|
437
|
+
<div className="w-full bg-secondary-200 rounded-full h-1.5">
|
|
414
438
|
<div
|
|
415
439
|
className="bg-primary-600 h-1.5 rounded-full transition-all duration-1000 ease-out"
|
|
416
440
|
style={{
|
|
@@ -423,6 +447,45 @@ const ITDropfile: React.FC<ITDropfileProps> = ({
|
|
|
423
447
|
)}
|
|
424
448
|
</div>
|
|
425
449
|
)}
|
|
450
|
+
</>
|
|
451
|
+
);
|
|
452
|
+
|
|
453
|
+
if (view === "button") {
|
|
454
|
+
const hasFile = Boolean(selectedFile || imagePreview);
|
|
455
|
+
return (
|
|
456
|
+
<div className={clsx("inline-block", containerClassName)}>
|
|
457
|
+
<ITButton
|
|
458
|
+
type="button"
|
|
459
|
+
variant="outlined"
|
|
460
|
+
color={hasFile ? "primary" : "secondary"}
|
|
461
|
+
size="small"
|
|
462
|
+
onClick={() => setIsModalOpen(true)}
|
|
463
|
+
>
|
|
464
|
+
<div className="flex items-center gap-2 max-w-[220px]">
|
|
465
|
+
<svg className="w-4 h-4 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
466
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
|
|
467
|
+
</svg>
|
|
468
|
+
<ITText className="truncate">
|
|
469
|
+
{selectedFile?.name || (hasFile ? "Archivo cargado" : buttonLabel)}
|
|
470
|
+
</ITText>
|
|
471
|
+
{showStatusBadge && hasFile && <StatusBadge status={uploadStatus} />}
|
|
472
|
+
</div>
|
|
473
|
+
</ITButton>
|
|
474
|
+
|
|
475
|
+
<ITDialog isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} title={modalTitle ?? buttonLabel}>
|
|
476
|
+
<div className="w-full transition-all duration-300">
|
|
477
|
+
{headerRow}
|
|
478
|
+
{dropZoneOrPreview}
|
|
479
|
+
</div>
|
|
480
|
+
</ITDialog>
|
|
481
|
+
</div>
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
return (
|
|
486
|
+
<div className={clsx("w-full transition-all duration-300", containerClassName)}>
|
|
487
|
+
{headerRow}
|
|
488
|
+
{dropZoneOrPreview}
|
|
426
489
|
</div>
|
|
427
490
|
);
|
|
428
491
|
};
|
|
@@ -228,7 +228,7 @@ const ITFieldRenderer = ({
|
|
|
228
228
|
return (
|
|
229
229
|
<div className={clsx("w-full col-span-full", activeConfig.className)}>
|
|
230
230
|
{label && (
|
|
231
|
-
<ITText as="h4" className="text-lg font-semibold text-
|
|
231
|
+
<ITText as="h4" className="text-lg font-semibold text-secondary-800 mb-4">
|
|
232
232
|
{label}
|
|
233
233
|
</ITText>
|
|
234
234
|
)}
|
|
@@ -246,8 +246,8 @@ const ITFieldRenderer = ({
|
|
|
246
246
|
|
|
247
247
|
case "array":
|
|
248
248
|
return (
|
|
249
|
-
<div className="p-4 border-2 border-dashed border-
|
|
250
|
-
<ITText as="p" className="text-sm text-
|
|
249
|
+
<div className="p-4 border-2 border-dashed border-secondary-200 rounded-xl">
|
|
250
|
+
<ITText as="p" className="text-sm text-secondary-500 text-center">
|
|
251
251
|
Array Field: {label}
|
|
252
252
|
</ITText>
|
|
253
253
|
</div>
|
|
@@ -472,12 +472,12 @@ const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
|
472
472
|
type === "checkbox" && "form-checkbox rounded",
|
|
473
473
|
className,
|
|
474
474
|
{ [disabledOverlay]: disabled },
|
|
475
|
-
{ "border-
|
|
475
|
+
{ "border-danger-500": hasError }
|
|
476
476
|
)}
|
|
477
477
|
/>
|
|
478
478
|
{label && (
|
|
479
|
-
<label htmlFor={name} className="text-sm text-
|
|
480
|
-
{label} {required && <ITText as="span" className="text-
|
|
479
|
+
<label htmlFor={name} className="text-sm text-secondary-700 dark:text-slate-300 select-none">
|
|
480
|
+
{label} {required && <ITText as="span" className="text-danger-500">*</ITText>}
|
|
481
481
|
</label>
|
|
482
482
|
)}
|
|
483
483
|
</div>
|
|
@@ -493,7 +493,7 @@ const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
|
493
493
|
)}
|
|
494
494
|
>
|
|
495
495
|
{label}
|
|
496
|
-
{required && <ITText as="span" className="text-
|
|
496
|
+
{required && <ITText as="span" className="text-danger-500 ml-1">*</ITText>}
|
|
497
497
|
</label>
|
|
498
498
|
)}
|
|
499
499
|
|
|
@@ -594,7 +594,7 @@ const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
|
594
594
|
{type === "password" && (
|
|
595
595
|
<button
|
|
596
596
|
type="button"
|
|
597
|
-
className="absolute inset-y-0 right-0 flex items-center pr-3 z-10 text-
|
|
597
|
+
className="absolute inset-y-0 right-0 flex items-center pr-3 z-10 text-secondary-400 hover:text-secondary-600 focus:outline-none"
|
|
598
598
|
onClick={() => setShowPassword(!showPassword)}
|
|
599
599
|
tabIndex={-1} // Don't allow tabbing into the eye icon
|
|
600
600
|
>
|
|
@@ -627,7 +627,7 @@ const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
|
627
627
|
{/* Length hint below if needed */}
|
|
628
628
|
{showHintLength && (minLength || maxLength) && !isCheckboxOrRadio && (
|
|
629
629
|
<div className="mt-1 text-xs">
|
|
630
|
-
<ITText as="p" className="text-
|
|
630
|
+
<ITText as="p" className="text-secondary-500">
|
|
631
631
|
{currentLength}{maxLength && `/${maxLength}`}
|
|
632
632
|
</ITText>
|
|
633
633
|
</div>
|
|
@@ -636,7 +636,7 @@ const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
|
636
636
|
{/* Validation for checkbox/radio - keep below */}
|
|
637
637
|
{isCheckboxOrRadio && hasError && (
|
|
638
638
|
<div className="mt-1 text-xs">
|
|
639
|
-
<ITText as="p" className="text-
|
|
639
|
+
<ITText as="p" className="text-danger-500">{errorMessage}</ITText>
|
|
640
640
|
</div>
|
|
641
641
|
)}
|
|
642
642
|
</div>
|
|
@@ -94,7 +94,7 @@ export default function ITLoader({
|
|
|
94
94
|
: size === "lg"
|
|
95
95
|
? "h-2"
|
|
96
96
|
: "h-2.5"
|
|
97
|
-
} bg-
|
|
97
|
+
} bg-secondary-200 rounded-full overflow-hidden ${className}`}
|
|
98
98
|
>
|
|
99
99
|
<div
|
|
100
100
|
className={`h-full animate-progress ${colorClass}`}
|
|
@@ -80,12 +80,12 @@ export default function ITNavbar({
|
|
|
80
80
|
// Legacy behavior - original navbar implementation
|
|
81
81
|
return (
|
|
82
82
|
<div className="flex flex-col h-screen">
|
|
83
|
-
<nav className="bg-white border-b border-
|
|
83
|
+
<nav className="bg-white border-b border-secondary-200">
|
|
84
84
|
<div className="flex items-center justify-between mx-auto p-4">
|
|
85
85
|
<div className="flex items-center space-x-3 rtl:space-x-reverse">
|
|
86
86
|
{logo && <div className="h-8">{logo}</div>}
|
|
87
87
|
{logoText && (
|
|
88
|
-
<ITText as="span" className="self-center text-2xl font-semibold whitespace-nowrap text-
|
|
88
|
+
<ITText as="span" className="self-center text-2xl font-semibold whitespace-nowrap text-secondary-900">
|
|
89
89
|
{logoText}
|
|
90
90
|
</ITText>
|
|
91
91
|
)}
|
|
@@ -99,7 +99,7 @@ export default function ITNavbar({
|
|
|
99
99
|
<div className="relative">
|
|
100
100
|
<button
|
|
101
101
|
type="button"
|
|
102
|
-
className="flex text-sm bg-
|
|
102
|
+
className="flex text-sm bg-secondary-200 rounded-full md:me-0 focus:ring-4 focus:ring-secondary-300"
|
|
103
103
|
onClick={toggleUserMenu}
|
|
104
104
|
>
|
|
105
105
|
{userMenu.userImage ? (
|
|
@@ -109,20 +109,20 @@ export default function ITNavbar({
|
|
|
109
109
|
alt="user photo"
|
|
110
110
|
/>
|
|
111
111
|
) : (
|
|
112
|
-
<FaUserCircle className="w-8 h-8 text-
|
|
112
|
+
<FaUserCircle className="w-8 h-8 text-secondary-500" />
|
|
113
113
|
)}
|
|
114
114
|
</button>
|
|
115
115
|
|
|
116
116
|
{isUserMenuOpen && (
|
|
117
117
|
<div
|
|
118
118
|
ref={userMenuRef}
|
|
119
|
-
className="z-[70] absolute right-0 mt-2 text-base list-none bg-white divide-y divide-
|
|
119
|
+
className="z-[70] absolute right-0 mt-2 text-base list-none bg-white divide-y divide-secondary-100 rounded-lg shadow-sm"
|
|
120
120
|
>
|
|
121
121
|
<div className="px-4 py-3">
|
|
122
|
-
<ITText as="span" className="block text-sm text-
|
|
122
|
+
<ITText as="span" className="block text-sm text-secondary-900">
|
|
123
123
|
{userMenu.userName}
|
|
124
124
|
</ITText>
|
|
125
|
-
<ITText as="span" className="block text-sm text-
|
|
125
|
+
<ITText as="span" className="block text-sm text-secondary-500 truncate">
|
|
126
126
|
{userMenu.userEmail}
|
|
127
127
|
</ITText>
|
|
128
128
|
</div>
|
|
@@ -134,7 +134,7 @@ export default function ITNavbar({
|
|
|
134
134
|
item.onClick();
|
|
135
135
|
setIsUserMenuOpen(false);
|
|
136
136
|
}}
|
|
137
|
-
className="block px-4 py-2 text-sm text-
|
|
137
|
+
className="block px-4 py-2 text-sm text-secondary-700 hover:bg-secondary-100 w-full text-left"
|
|
138
138
|
>
|
|
139
139
|
<ITText as="span">{item.label}</ITText>
|
|
140
140
|
</button>
|
|
@@ -152,13 +152,13 @@ export default function ITNavbar({
|
|
|
152
152
|
|
|
153
153
|
<div className="flex-1 flex overflow-hidden relative">
|
|
154
154
|
{(showSidebar || showSidebarOnMobile) && (
|
|
155
|
-
<aside className="fixed inset-y-0 left-0 w-64 bg-
|
|
155
|
+
<aside className="fixed inset-y-0 left-0 w-64 bg-secondary-50 transform transition-transform duration-300 ease-in-out z-[40] shadow-lg md:static md:transform-none md:shadow-none md:border-r md:border-secondary-200">
|
|
156
156
|
<div className="h-full overflow-y-auto py-4 px-3">
|
|
157
157
|
<ul className="space-y-2 font-medium">{sidebarItems}</ul>
|
|
158
158
|
</div>
|
|
159
159
|
</aside>
|
|
160
160
|
)}
|
|
161
|
-
<main className="flex-1 bg-
|
|
161
|
+
<main className="flex-1 bg-secondary-100 overflow-y-auto">
|
|
162
162
|
{children}
|
|
163
163
|
</main>
|
|
164
164
|
</div>
|