@adamosuiteservices/ui 2.14.1 → 2.15.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 (41) hide show
  1. package/dist/combobox-DGuQtXjP.js +608 -0
  2. package/dist/combobox-hTCtPMUL.cjs +40 -0
  3. package/dist/combobox.cjs +1 -1
  4. package/dist/combobox.js +1 -1
  5. package/dist/components/ui/combobox/combobox.d.ts +7 -1
  6. package/dist/components/ui/date-picker-selector/date-picker-selector.d.ts +75 -1
  7. package/dist/components/ui/file-upload/file-upload.d.ts +3 -1
  8. package/dist/components/ui/slider/slider.d.ts +1 -1
  9. package/dist/components/ui/switch/switch.d.ts +1 -1
  10. package/dist/date-picker-selector.cjs +1 -1
  11. package/dist/date-picker-selector.js +81 -78
  12. package/dist/field.cjs +2 -2
  13. package/dist/field.js +2 -2
  14. package/dist/file-upload.cjs +5 -3
  15. package/dist/file-upload.js +178 -149
  16. package/dist/slider.cjs +5 -5
  17. package/dist/slider.js +196 -177
  18. package/dist/styles.css +1 -1
  19. package/dist/switch.cjs +3 -3
  20. package/dist/switch.js +105 -85
  21. package/docs/components/ui/accordion-rounded.md +2 -6
  22. package/docs/components/ui/avatar.md +3 -1
  23. package/docs/components/ui/button.md +22 -16
  24. package/docs/components/ui/card.md +49 -31
  25. package/docs/components/ui/checkbox.md +44 -8
  26. package/docs/components/ui/combobox.md +100 -0
  27. package/docs/components/ui/date-picker-selector.md +147 -28
  28. package/docs/components/ui/file-upload.md +241 -94
  29. package/docs/components/ui/icon.md +1 -1
  30. package/docs/components/ui/input.md +4 -1
  31. package/docs/components/ui/radio-group.md +1 -1
  32. package/docs/components/ui/select.md +51 -34
  33. package/docs/components/ui/sheet.md +3 -9
  34. package/docs/components/ui/slider.md +120 -99
  35. package/docs/components/ui/switch.md +408 -408
  36. package/docs/components/ui/textarea.md +37 -22
  37. package/docs/components/ui/tooltip.md +5 -2
  38. package/docs/components/ui/typography.md +63 -39
  39. package/package.json +1 -1
  40. package/dist/combobox-B8HMlZy6.js +0 -601
  41. package/dist/combobox-Btj-hiBy.cjs +0 -40
@@ -17,6 +17,9 @@ Componente de carga de archivos con funcionalidad **drag & drop**, validación d
17
17
  - ✅ Límite de cantidad de archivos en modo múltiple
18
18
  - ✅ Etiquetas personalizables (i18n)
19
19
  - ✅ Estado de arrastre visual (borde y fondo cambian)
20
+ - ✅ Estados de validación con `aria-invalid`
21
+ - ✅ Estados deshabilitados con `disabled`
22
+ - ✅ Detección automática de fieldset disabled
20
23
  - ✅ Integración con formularios React
21
24
  - ✅ TypeScript completo con tipos exportados
22
25
 
@@ -24,7 +27,10 @@ Componente de carga de archivos con funcionalidad **drag & drop**, validación d
24
27
 
25
28
  ```typescript
26
29
  import { FileUpload } from "@adamosuiteservices/ui/file-upload";
27
- import type { FileUploadProps, FileUploadLabels } from "@adamosuiteservices/ui/file-upload";
30
+ import type {
31
+ FileUploadProps,
32
+ FileUploadLabels,
33
+ } from "@adamosuiteservices/ui/file-upload";
28
34
  ```
29
35
 
30
36
  ## Uso Básico
@@ -38,12 +44,7 @@ import { FileUpload } from "@adamosuiteservices/ui/file-upload";
38
44
  function MyForm() {
39
45
  const [file, setFile] = useState<File | null>(null);
40
46
 
41
- return (
42
- <FileUpload
43
- selectedFile={file}
44
- onFileSelect={setFile}
45
- />
46
- );
47
+ return <FileUpload selectedFile={file} onFileSelect={setFile} />;
47
48
  }
48
49
  ```
49
50
 
@@ -56,17 +57,12 @@ import { FileUpload } from "@adamosuiteservices/ui/file-upload";
56
57
  function MyForm() {
57
58
  const [files, setFiles] = useState<File[]>([]);
58
59
 
59
- return (
60
- <FileUpload
61
- selectedFiles={files}
62
- onFilesSelect={setFiles}
63
- multiple
64
- />
65
- );
60
+ return <FileUpload selectedFiles={files} onFilesSelect={setFiles} multiple />;
66
61
  }
67
62
  ```
68
63
 
69
64
  **Configuración por defecto**:
65
+
70
66
  - Extensiones aceptadas: `.xls`, `.xlsx`, `.numbers`
71
67
  - Tamaño máximo: 50 MB
72
68
  - Máximo de archivos (modo múltiple): 10
@@ -101,7 +97,8 @@ acceptedExtensions?: string[]
101
97
  Array de extensiones de archivo permitidas. Por defecto: `[".xls", ".xlsx", ".numbers"]`
102
98
 
103
99
  **Ejemplo**:
104
- ```tsx
100
+
101
+ ````tsx
105
102
  <FileUpload
106
103
  selectedFile={file}
107
104
  onFileSelect={setFile}
@@ -111,17 +108,14 @@ Array de extensiones de archivo permitidas. Por defecto: `[".xls", ".xlsx", ".nu
111
108
 
112
109
  ```tsx
113
110
  maxSizeInMB?: number
114
- ```
111
+ ````
115
112
 
116
113
  Tamaño máximo del archivo en megabytes. Por defecto: `50`
117
114
 
118
115
  **Ejemplo**:
116
+
119
117
  ```tsx
120
- <FileUpload
121
- selectedFile={file}
122
- onFileSelect={setFile}
123
- maxSizeInMB={10}
124
- />
118
+ <FileUpload selectedFile={file} onFileSelect={setFile} maxSizeInMB={10} />
125
119
  ```
126
120
 
127
121
  #### labels
@@ -140,6 +134,7 @@ type FileUploadLabels = {
140
134
  Etiquetas personalizables para internacionalización o textos específicos.
141
135
 
142
136
  **Ejemplo**:
137
+
143
138
  ```tsx
144
139
  <FileUpload
145
140
  selectedFile={file}
@@ -147,20 +142,39 @@ Etiquetas personalizables para internacionalización o textos específicos.
147
142
  labels={{
148
143
  dragDrop: "Arrastra y suelta tu archivo aquí o",
149
144
  selectFile: "Selecciona el archivo",
150
- fileRequirements: "Archivos permitidos: .xls, .xlsx. Tamaño máximo 50 MB."
145
+ fileRequirements: "Archivos permitidos: .xls, .xlsx. Tamaño máximo 50 MB.",
151
146
  }}
152
147
  />
153
148
  ```
154
149
 
150
+ #### aria-invalid
151
+
152
+ ```tsx
153
+ "aria-invalid"?: boolean
154
+ ```
155
+
156
+ Marca el componente como inválido, aplicando estilos destructivos. Útil para validación de formularios. Por defecto: `false`
157
+
158
+ **Ejemplo**:
159
+
160
+ ```tsx
161
+ <FileUpload
162
+ selectedFile={file}
163
+ onFileSelect={setFile}
164
+ aria-invalid={!!errorMessage}
165
+ />
166
+ ```
167
+
155
168
  #### invalid
156
169
 
157
170
  ```tsx
158
171
  invalid?: boolean
159
172
  ```
160
173
 
161
- Marca el componente como inválido, aplicando estilos destructivos. Por defecto: `false`
174
+ Alternativa a `aria-invalid` para marcar el componente como inválido. Por defecto: `false`
162
175
 
163
176
  **Ejemplo**:
177
+
164
178
  ```tsx
165
179
  <FileUpload
166
180
  selectedFile={file}
@@ -169,6 +183,22 @@ Marca el componente como inválido, aplicando estilos destructivos. Por defecto:
169
183
  />
170
184
  ```
171
185
 
186
+ #### disabled
187
+
188
+ ```tsx
189
+ disabled?: boolean
190
+ ```
191
+
192
+ Deshabilita el componente, impidiendo toda interacción del usuario. Por defecto: `false`
193
+
194
+ **Ejemplo**:
195
+
196
+ ```tsx
197
+ <FileUpload selectedFile={file} onFileSelect={setFile} disabled />
198
+ ```
199
+
200
+ **Nota**: El componente también detecta automáticamente si está dentro de un `<fieldset disabled>` y se deshabilitará automáticamente.
201
+
172
202
  #### onInvalidFile
173
203
 
174
204
  ```tsx
@@ -178,6 +208,7 @@ onInvalidFile?: (file: File, reason: "extension" | "size") => void
178
208
  Callback invocado cuando un archivo no pasa la validación. Recibe el archivo y el motivo del rechazo.
179
209
 
180
210
  **Ejemplo**:
211
+
181
212
  ```tsx
182
213
  const handleInvalidFile = (file: File, reason: "extension" | "size") => {
183
214
  if (reason === "extension") {
@@ -192,7 +223,7 @@ const handleInvalidFile = (file: File, reason: "extension" | "size") => {
192
223
  onFileSelect={setFile}
193
224
  onInvalidFile={handleInvalidFile}
194
225
  invalid={!!error}
195
- />
226
+ />;
196
227
  ```
197
228
 
198
229
  ### Modo Múltiple
@@ -236,10 +267,12 @@ filesPosition?: "above" | "below"
236
267
  ```
237
268
 
238
269
  Posición donde aparecen los archivos seleccionados en modo múltiple:
270
+
239
271
  - `"above"` - Archivos arriba del área de drag & drop
240
272
  - `"below"` - Archivos debajo del área de drag & drop (por defecto)
241
273
 
242
274
  **Ejemplo**:
275
+
243
276
  ```tsx
244
277
  <FileUpload
245
278
  selectedFiles={files}
@@ -265,7 +298,8 @@ type FileUploadLabels = {
265
298
  Etiquetas personalizables para internacionalización o textos específicos.
266
299
 
267
300
  **Ejemplo**:
268
- ```tsx
301
+
302
+ ````tsx
269
303
  <FileUpload
270
304
  selectedFile={file}
271
305
  onFileSelect={setFile}
@@ -291,11 +325,12 @@ Etiquetas personalizables para internacionalización o textos específicos.
291
325
 
292
326
  ```tsx
293
327
  acceptedExtensions?: string[]
294
- ```
328
+ ````
295
329
 
296
330
  Array de extensiones de archivo permitidas. Por defecto: `[".xls", ".xlsx", ".numbers"]`
297
331
 
298
332
  **Ejemplo**:
333
+
299
334
  ```tsx
300
335
  <FileUpload
301
336
  selectedFile={file}
@@ -313,12 +348,9 @@ maxSizeInMB?: number
313
348
  Tamaño máximo del archivo en megabytes. Por defecto: `50`
314
349
 
315
350
  **Ejemplo**:
351
+
316
352
  ```tsx
317
- <FileUpload
318
- selectedFile={file}
319
- onFileSelect={setFile}
320
- maxSizeInMB={10}
321
- />
353
+ <FileUpload selectedFile={file} onFileSelect={setFile} maxSizeInMB={10} />
322
354
  ```
323
355
 
324
356
  ### labels
@@ -336,6 +368,7 @@ type FileUploadLabels = {
336
368
  Etiquetas personalizables para internacionalización o textos específicos.
337
369
 
338
370
  **Ejemplo**:
371
+
339
372
  ```tsx
340
373
  <FileUpload
341
374
  selectedFile={file}
@@ -343,16 +376,127 @@ Etiquetas personalizables para internacionalización o textos específicos.
343
376
  labels={{
344
377
  dragDrop: "Arrastra y suelta tu archivo aquí o",
345
378
  selectFile: "Selecciona el archivo",
346
- fileRequirements: "Archivos permitidos: .xls, .xlsx. Tamaño máximo 50 MB."
379
+ fileRequirements: "Archivos permitidos: .xls, .xlsx. Tamaño máximo 50 MB.",
347
380
  }}
348
381
  />
349
382
  ```
350
383
 
351
384
  ## Ejemplos
352
385
 
353
- ### Archivos de Excel (Por Defecto)
386
+ ### Con Componentes Field
387
+
388
+ ```tsx
389
+ import {
390
+ Field,
391
+ FieldLabel,
392
+ FieldDescription,
393
+ FieldError,
394
+ FieldGroup,
395
+ } from "@adamosuiteservices/ui/field";
396
+ import { FileUpload } from "@adamosuiteservices/ui/file-upload";
397
+
398
+ function FileUploadForm() {
399
+ const [file, setFile] = useState<File | null>(null);
400
+ const [error, setError] = useState<string>("");
401
+
402
+ const handleInvalidFile = (file: File, reason: "extension" | "size") => {
403
+ if (reason === "extension") {
404
+ setError(`File "${file.name}" has an invalid extension.`);
405
+ } else if (reason === "size") {
406
+ setError(`File "${file.name}" exceeds the maximum size limit.`);
407
+ }
408
+ };
409
+
410
+ return (
411
+ <FieldGroup className="adm:max-w-xl">
412
+ <Field>
413
+ <FieldLabel>Upload document (PDF or DOCX only, max 2MB)</FieldLabel>
414
+ <FileUpload
415
+ selectedFile={file}
416
+ onFileSelect={(newFile) => {
417
+ setFile(newFile);
418
+ if (newFile) setError("");
419
+ }}
420
+ onInvalidFile={handleInvalidFile}
421
+ aria-invalid={!!error}
422
+ acceptedExtensions={[".pdf", ".docx"]}
423
+ maxSizeInMB={2}
424
+ />
425
+ {error ? (
426
+ <FieldError>{error}</FieldError>
427
+ ) : (
428
+ <FieldDescription>
429
+ Supported formats: PDF, DOCX. Maximum 2MB.
430
+ </FieldDescription>
431
+ )}
432
+ </Field>
433
+ </FieldGroup>
434
+ );
435
+ }
436
+ ```
437
+
438
+ ### Estado Deshabilitado
439
+
440
+ ```tsx
441
+ import {
442
+ Field,
443
+ FieldLabel,
444
+ FieldDescription,
445
+ FieldGroup,
446
+ } from "@adamosuiteservices/ui/field";
447
+
448
+ function DisabledExample() {
449
+ const [file, setFile] = useState<File | null>(null);
450
+
451
+ return (
452
+ <FieldGroup className="adm:max-w-xl">
453
+ <Field>
454
+ <FieldLabel>Upload document (Disabled)</FieldLabel>
455
+ <FileUpload selectedFile={file} onFileSelect={setFile} disabled />
456
+ <FieldDescription>This file upload is disabled</FieldDescription>
457
+ </Field>
458
+ </FieldGroup>
459
+ );
460
+ }
461
+ ```
462
+
463
+ ### Dentro de Fieldset Disabled
354
464
 
355
465
  ```tsx
466
+ import {
467
+ FieldSet,
468
+ FieldLegend,
469
+ FieldGroup,
470
+ Field,
471
+ FieldLabel,
472
+ } from "@adamosuiteservices/ui/field";
473
+
474
+ function FieldsetExample() {
475
+ const [file, setFile] = useState<File | null>(null);
476
+
477
+ return (
478
+ <FieldSet disabled>
479
+ <FieldLegend>Document upload (Fieldset disabled)</FieldLegend>
480
+ <FieldGroup>
481
+ <Field>
482
+ <FieldLabel>Upload document</FieldLabel>
483
+ <FileUpload
484
+ selectedFile={file}
485
+ onFileSelect={setFile}
486
+ className="adm:max-w-xl"
487
+ />
488
+ </Field>
489
+ </FieldGroup>
490
+ </FieldSet>
491
+ );
492
+ }
493
+ ```
494
+
495
+ **Nota**: El componente detecta automáticamente cuando está dentro de un `<fieldset disabled>` o `<FieldSet disabled>` y se deshabilita automáticamente.
496
+
497
+ ### Archivos de Excel (Por Defecto)
498
+
499
+ ````tsx
356
500
  const [file, setFile] = useState<File | null>(null);
357
501
 
358
502
  <FileUpload
@@ -372,7 +516,7 @@ const [files, setFiles] = useState<File[]>([]);
372
516
  selectFile: "Select files"
373
517
  }}
374
518
  />
375
- ```
519
+ ````
376
520
 
377
521
  ### Múltiples Imágenes
378
522
 
@@ -389,10 +533,12 @@ const [images, setImages] = useState<File[]>([]);
389
533
  labels={{
390
534
  dragDrop: "Drag and drop your images here or",
391
535
  selectFile: "Select images",
392
- fileRequirements: "Supported formats: JPG, PNG, GIF, WebP. Max 5MB each. Up to 10 images.",
393
- filesSelected: (count) => `${count} image${count !== 1 ? "s" : ""} selected`
536
+ fileRequirements:
537
+ "Supported formats: JPG, PNG, GIF, WebP. Max 5MB each. Up to 10 images.",
538
+ filesSelected: (count) =>
539
+ `${count} image${count !== 1 ? "s" : ""} selected`,
394
540
  }}
395
- />
541
+ />;
396
542
  ```
397
543
 
398
544
  ### Archivos Arriba del Área de Drop
@@ -407,14 +553,14 @@ const [files, setFiles] = useState<File[]>([]);
407
553
  filesPosition="above"
408
554
  acceptedExtensions={[".pdf"]}
409
555
  maxSizeInMB={10}
410
- />
556
+ />;
411
557
  ```
558
+
412
559
  />
413
- ```
414
560
 
415
561
  ### Imágenes
416
562
 
417
- ```tsx
563
+ ````tsx
418
564
  const [image, setImage] = useState<File | null>(null);
419
565
 
420
566
  ## Estados Visuales
@@ -460,16 +606,6 @@ Cuando `invalid={true}`:
460
606
  - Contador de archivos: `text-destructive`
461
607
  - Tarjetas de archivos: borde y fondo con colores destructivos
462
608
 
463
- ## Validacióne={document}
464
- onFileSelect={setDocument}
465
- acceptedExtensions={[".pdf"]}
466
- maxSizeInMB={20}
467
- labels={{
468
- dragDrop: "Drag and drop your PDF here or",
469
- selectFile: "Select PDF",
470
- fileRequirements: "Only PDF files. Maximum 20 MB."
471
- }}
472
- />
473
609
  ## Validación
474
610
 
475
611
  El componente valida automáticamente:
@@ -518,7 +654,7 @@ const handleInvalidFile = (file: File, reason: "extension" | "size") => {
518
654
  </Typography>
519
655
  </div>
520
656
  )}
521
- ```
657
+ ````
522
658
 
523
659
  ## Comportamiento por Modo
524
660
 
@@ -558,9 +694,9 @@ const [archive, setArchive] = useState<File | null>(null);
558
694
  maxSizeInMB={500}
559
695
  labels={{
560
696
  dragDrop: "Drag and drop your archive here or",
561
- selectFile: "Select the archive"
697
+ selectFile: "Select the archive",
562
698
  }}
563
- />
699
+ />;
564
700
  ```
565
701
 
566
702
  ### Con Integración en Formulario
@@ -571,7 +707,7 @@ function UploadForm() {
571
707
 
572
708
  const handleSubmit = async (e: React.FormEvent) => {
573
709
  e.preventDefault();
574
-
710
+
575
711
  if (!file) return;
576
712
 
577
713
  const formData = new FormData();
@@ -582,7 +718,7 @@ function UploadForm() {
582
718
  method: "POST",
583
719
  body: formData
584
720
  });
585
-
721
+
586
722
  ### Botón de Remover
587
723
 
588
724
  - Variante: `destructive-medium`
@@ -617,6 +753,7 @@ function UploadForm() {
617
753
  ### Sin Archivo Seleccionado
618
754
 
619
755
  El componente muestra:
756
+
620
757
  - Área de drag & drop con borde punteado
621
758
  - Icono de documento en fondo azul claro
622
759
  - Texto instructivo y link para seleccionar archivo
@@ -625,6 +762,7 @@ El componente muestra:
625
762
  ### Durante Drag Over
626
763
 
627
764
  Cuando el usuario arrastra un archivo sobre el área:
765
+
628
766
  - Borde cambia a `border-primary-500`
629
767
  - Fondo cambia a `bg-primary-50`
630
768
  - Transición suave con `transition-colors`
@@ -632,6 +770,7 @@ Cuando el usuario arrastra un archivo sobre el área:
632
770
  ### Con Archivo Seleccionado
633
771
 
634
772
  El componente muestra:
773
+
635
774
  - Tarjeta con fondo `bg-neutral-100`
636
775
  - Icono de documento en fondo blanco
637
776
  - Nombre del archivo (con truncate si es largo)
@@ -687,9 +826,10 @@ border-primary-500 bg-primary-50
687
826
  - Label asociado correctamente con `htmlFor="file-upload"`
688
827
  - Botón de link usa `asChild` para comportamiento semántico
689
828
  - Typography con color `muted` para textos secundarios
829
+
690
830
  ## Tipos TypeScript
691
831
 
692
- ```typescript
832
+ ````typescript
693
833
  export type FileUploadLabels = {
694
834
  dragDrop?: string
695
835
  selectFile?: string
@@ -701,22 +841,27 @@ export type FileUploadProps = ComponentProps<"div"> & Readonly<{
701
841
  // Modo simple
702
842
  selectedFile?: File | null
703
843
  onFileSelect?: (file: File | null) => void
704
-
844
+
705
845
  // Modo múltiple
706
846
  selectedFiles?: File[]
707
847
  onFilesSelect?: (files: File[]) => void
708
848
  multiple?: boolean
709
849
  maxFiles?: number
710
850
  filesPosition?: "above" | "below"
711
-
851
+
712
852
  // Validación
713
853
  onInvalidFile?: (file: File, reason: "extension" | "size") => void
714
854
  invalid?: boolean
715
-
855
+ "aria-invalid"?: boolean
856
+
857
+ // Estados
858
+ disabled?: boolean
859
+
716
860
  // Común
717
861
  acceptedExtensions?: string[]
718
862
  maxSizeInMB?: number
719
863
  labels?: FileUploadLabels
864
+ }>
720
865
  ### FormData para Upload
721
866
 
722
867
  ```tsx
@@ -750,7 +895,8 @@ const uploadFiles = async (files: File[]) => {
750
895
 
751
896
  return response.json();
752
897
  };
753
- ```
898
+ ````
899
+
754
900
  ```tsx
755
901
  // No validar el archivo antes de hacer upload
756
902
  // Siempre verificar que file no sea null
@@ -769,18 +915,19 @@ labels={{ selectFile: "Select file" }} // Poco descriptivo
769
915
 
770
916
  ```typescript
771
917
  export type FileUploadLabels = {
772
- dragDrop?: string
773
- selectFile?: string
774
- fileRequirements?: string
918
+ dragDrop?: string;
919
+ selectFile?: string;
920
+ fileRequirements?: string;
775
921
  };
776
922
 
777
- export type FileUploadProps = ComponentProps<"div"> & Readonly<{
778
- selectedFile: File | null
779
- onFileSelect: (file: File | null) => void
780
- acceptedExtensions?: string[]
781
- maxSizeInMB?: number
782
- labels?: FileUploadLabels
783
- }>;
923
+ export type FileUploadProps = ComponentProps<"div"> &
924
+ Readonly<{
925
+ selectedFile: File | null;
926
+ onFileSelect: (file: File | null) => void;
927
+ acceptedExtensions?: string[];
928
+ maxSizeInMB?: number;
929
+ labels?: FileUploadLabels;
930
+ }>;
784
931
  ```
785
932
 
786
933
  ## Integración con Backend
@@ -791,13 +938,16 @@ export type FileUploadProps = ComponentProps<"div"> & Readonly<{
791
938
  const uploadFile = async (file: File) => {
792
939
  const formData = new FormData();
793
940
  formData.append("file", file);
794
- formData.append("metadata", JSON.stringify({
795
- uploadedAt: new Date().toISOString()
796
- }));
941
+ formData.append(
942
+ "metadata",
943
+ JSON.stringify({
944
+ uploadedAt: new Date().toISOString(),
945
+ })
946
+ );
797
947
 
798
948
  const response = await fetch("/api/upload", {
799
949
  method: "POST",
800
- body: formData
950
+ body: formData,
801
951
  });
802
952
 
803
953
  return response.json();
@@ -806,7 +956,7 @@ const uploadFile = async (file: File) => {
806
956
 
807
957
  ### Con Progress Tracking
808
958
 
809
- ```tsx
959
+ ````tsx
810
960
  const [progress, setProgress] = useState(0);
811
961
 
812
962
  const uploadWithProgress = async (file: File) => {
@@ -826,6 +976,8 @@ const uploadWithProgress = async (file: File) => {
826
976
  | Posición de preview | ❌ No configurable | ✅ Arriba o abajo |
827
977
  | UX consistente | ❌ Varía por browser | ✅ Consistente |
828
978
  | Labels customizables | ❌ No | ✅ Sí (i18n friendly) |
979
+ | aria-invalid | ⚠️ Manual | ✅ Integrado |
980
+ | Fieldset disabled | ⚠️ Nativo pero sin estilos | ✅ Detectado automáticamente |
829
981
 
830
982
  ## Notas
831
983
 
@@ -836,42 +988,37 @@ const uploadWithProgress = async (file: File) => {
836
988
  - Los archivos no se almacenan automáticamente - manejar el upload con los callbacks
837
989
  - El componente es completamente controlado - el padre maneja el estado de los archivos
838
990
  - El input file es reutilizable: después de seleccionar, se resetea para permitir seleccionar el mismo archivo de nuevo
991
+ - **Detección automática de fieldset**: El componente detecta cuando está dentro de un `<fieldset disabled>` usando MutationObserver y se deshabilita automáticamente
992
+ - Usar con los componentes Field (`Field`, `FieldLabel`, `FieldError`, etc.) para una mejor experiencia de formulario
839
993
  ```tsx
840
994
  <FileUpload
841
995
  selectedFile={file}
842
996
  onFileSelect={setFile}
843
997
  className="adm:max-w-2xl adm:mx-auto"
844
998
  />
845
- ```
999
+ ````
846
1000
 
847
1001
  ### Con Wrapper Adicional
848
1002
 
849
1003
  ```tsx
850
1004
  <div className="adm:space-y-4">
851
1005
  <Label>Upload your document</Label>
852
- <FileUpload
853
- selectedFile={file}
854
- onFileSelect={setFile}
855
- />
856
- {file && (
857
- <Typography color="success">
858
- ✓ File ready to upload
859
- </Typography>
860
- )}
1006
+ <FileUpload selectedFile={file} onFileSelect={setFile} />
1007
+ {file && <Typography color="success">✓ File ready to upload</Typography>}
861
1008
  </div>
862
1009
  ```
863
1010
 
864
1011
  ## Comparación con Input type="file"
865
1012
 
866
- | Característica | Input file nativo | FileUpload |
867
- |----------------|-------------------|------------|
868
- | Drag & Drop | ❌ No | ✅ Sí |
869
- | Validación visual | ❌ No | ✅ Sí |
870
- | Preview del archivo | ❌ No | ✅ Sí con nombre y tamaño |
871
- | Extensiones validadas | ⚠️ Solo accept attribute | ✅ Con feedback visual |
872
- | Tamaño validado | ❌ Solo en backend | ✅ Cliente y servidor |
873
- | UX consistente | ❌ Varía por browser | ✅ Consistente |
874
- | Labels customizables | ❌ No | ✅ Sí (i18n friendly) |
1013
+ | Característica | Input file nativo | FileUpload |
1014
+ | --------------------- | ------------------------ | ------------------------- |
1015
+ | Drag & Drop | ❌ No | ✅ Sí |
1016
+ | Validación visual | ❌ No | ✅ Sí |
1017
+ | Preview del archivo | ❌ No | ✅ Sí con nombre y tamaño |
1018
+ | Extensiones validadas | ⚠️ Solo accept attribute | ✅ Con feedback visual |
1019
+ | Tamaño validado | ❌ Solo en backend | ✅ Cliente y servidor |
1020
+ | UX consistente | ❌ Varía por browser | ✅ Consistente |
1021
+ | Labels customizables | ❌ No | ✅ Sí (i18n friendly) |
875
1022
 
876
1023
  ## Notas
877
1024
 
@@ -510,7 +510,7 @@ El componente renderiza un `<span>` con las siguientes características:
510
510
  <span
511
511
  data-slot="icon"
512
512
  className="material-symbols-outlined adm:inline-block adm:text-2xl"
513
- style={{ fontVariationSettings: '...' }}
513
+ style={{ fontVariationSettings: "..." }}
514
514
  >
515
515
  {symbol}
516
516
  </span>
@@ -135,7 +135,10 @@ import { Input } from "@adamosuiteservices/ui/input";
135
135
  {
136
136
  /* Por defecto */
137
137
  }
138
- <Input type="text" placeholder="Default input" />; {/* h-10 por defecto */}
138
+ <Input type="text" placeholder="Default input" />;
139
+ {
140
+ /* h-10 por defecto */
141
+ }
139
142
 
140
143
  {
141
144
  /* Grande */
@@ -283,7 +283,7 @@ function App() {
283
283
  ## Accesibilidad
284
284
 
285
285
  - ✅ **Role**: `role="radio"` y `role="radiogroup"`
286
- - ✅ **ARIA**: `aria-checked`, `aria-disabled`, `aria-invalid`
286
+ - ✅ **ARIA**: `aria-checked`, `aria-invalid`
287
287
  - ✅ **Keyboard**: Arrow keys para navegar, Space para seleccionar
288
288
  - ✅ **Label**: Asociar con `htmlFor` e `id`
289
289
  - ✅ **Focus**: Focus ring visible en navegación por teclado