rharuow-ds 1.9.0 → 1.10.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.
- package/README.md +372 -2
- package/dist/rharuow-ds.cjs.js +1 -1
- package/dist/rharuow-ds.es.js +1298 -963
- package/dist/styles.css +1 -1
- package/dist/types/src/components/Modal.d.ts +16 -0
- package/dist/types/src/components/Toaster.d.ts +31 -0
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/stories/Modal.stories.d.ts +13 -0
- package/dist/types/src/stories/Toaster.stories.d.ts +13 -0
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ Um Design System moderno em React com integração completa ao React Hook Form,
|
|
|
44
44
|
## 🌟 Características
|
|
45
45
|
|
|
46
46
|
- ⚛️ **React 18+** com TypeScript
|
|
47
|
-
- 🧩 **
|
|
47
|
+
- 🧩 **17 componentes** prontos para uso (Input, Textarea, Select, AsyncSelect, MultiSelect, MultiAsyncSelect, RadioGroup, Button, Card, Table, Tooltip, Accordion, AsideSheet, Modal, Toaster, ImageInput)
|
|
48
48
|
- 💡 **Filtro digitável** em componentes Select - Digite para encontrar opções rapidamente
|
|
49
49
|
- 🔗 **Integração nativa** com React Hook Form
|
|
50
50
|
- 🎨 **Customização via CSS Variables** - Mude o tema facilmente
|
|
@@ -112,6 +112,8 @@ npm install react-hook-form
|
|
|
112
112
|
Tooltip,
|
|
113
113
|
Accordion,
|
|
114
114
|
AsideSheet,
|
|
115
|
+
Modal,
|
|
116
|
+
Toaster,
|
|
115
117
|
ImageInput,
|
|
116
118
|
} from "rharuow-ds";
|
|
117
119
|
|
|
@@ -199,6 +201,8 @@ npm install react-hook-form
|
|
|
199
201
|
Tooltip,
|
|
200
202
|
Accordion,
|
|
201
203
|
AsideSheet,
|
|
204
|
+
Modal,
|
|
205
|
+
Toaster,
|
|
202
206
|
ImageInput,
|
|
203
207
|
} from "rharuow-ds";
|
|
204
208
|
|
|
@@ -582,7 +586,373 @@ Veja a story do componente no Storybook para demonstrações e variações (left
|
|
|
582
586
|
|
|
583
587
|
[Storybook — AsideSheet](https://rharuow.github.io/rharuow-ds-docs/?path=/story/asidesheet--default)
|
|
584
588
|
|
|
585
|
-
###
|
|
589
|
+
### 🎭 **Modal**
|
|
590
|
+
|
|
591
|
+
Componente de diálogo modal para exibir conteúdo sobreposto à página principal.
|
|
592
|
+
|
|
593
|
+
- ✅ Overlay com transparência configurável
|
|
594
|
+
- ✅ Múltiplos tamanhos: sm, md, lg, xl, full
|
|
595
|
+
- ✅ Controle de fechamento via overlay, ESC ou botão X
|
|
596
|
+
- ✅ Prevenção de scroll do body quando aberto
|
|
597
|
+
- ✅ Animações suaves de entrada/saída
|
|
598
|
+
- ✅ Sub-componentes para estruturação: Header, Body, Footer
|
|
599
|
+
- ✅ Renderização via Portal (React Portal)
|
|
600
|
+
- ✅ Acessível: role="dialog", aria-modal
|
|
601
|
+
|
|
602
|
+
Props principais:
|
|
603
|
+
|
|
604
|
+
- `open: boolean` — controla visibilidade do modal
|
|
605
|
+
- `onClose: () => void` — callback chamado ao fechar
|
|
606
|
+
- `size?: 'sm' | 'md' | 'lg' | 'xl' | 'full'` — tamanho do modal (padrão: 'md')
|
|
607
|
+
- `closeOnOverlayClick?: boolean` — fecha ao clicar fora (padrão: true)
|
|
608
|
+
- `closeOnEscape?: boolean` — fecha ao pressionar ESC (padrão: true)
|
|
609
|
+
- `showCloseButton?: boolean` — exibe botão X de fechar (padrão: true)
|
|
610
|
+
- `className?: string` — classes adicionais para o container do modal
|
|
611
|
+
|
|
612
|
+
Exemplo de uso básico:
|
|
613
|
+
|
|
614
|
+
```tsx
|
|
615
|
+
import React from 'react';
|
|
616
|
+
import { Modal, Button } from 'rharuow-ds';
|
|
617
|
+
|
|
618
|
+
function Example() {
|
|
619
|
+
const [open, setOpen] = React.useState(false);
|
|
620
|
+
|
|
621
|
+
return (
|
|
622
|
+
<div>
|
|
623
|
+
<Button onClick={() => setOpen(true)}>Abrir Modal</Button>
|
|
624
|
+
|
|
625
|
+
<Modal open={open} onClose={() => setOpen(false)}>
|
|
626
|
+
<h2>Título do Modal</h2>
|
|
627
|
+
<p>Conteúdo do modal aqui.</p>
|
|
628
|
+
</Modal>
|
|
629
|
+
</div>
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
Exemplo com estrutura completa:
|
|
635
|
+
|
|
636
|
+
```tsx
|
|
637
|
+
import React from 'react';
|
|
638
|
+
import { Modal, Button } from 'rharuow-ds';
|
|
639
|
+
|
|
640
|
+
function Example() {
|
|
641
|
+
const [open, setOpen] = React.useState(false);
|
|
642
|
+
|
|
643
|
+
return (
|
|
644
|
+
<div>
|
|
645
|
+
<Button onClick={() => setOpen(true)}>Confirmar Ação</Button>
|
|
646
|
+
|
|
647
|
+
<Modal
|
|
648
|
+
open={open}
|
|
649
|
+
onClose={() => setOpen(false)}
|
|
650
|
+
size="md"
|
|
651
|
+
>
|
|
652
|
+
<Modal.Header>
|
|
653
|
+
<h2 className="text-2xl font-bold">Confirmar Exclusão</h2>
|
|
654
|
+
<p className="text-sm text-gray-500">Esta ação não pode ser desfeita</p>
|
|
655
|
+
</Modal.Header>
|
|
656
|
+
|
|
657
|
+
<Modal.Body>
|
|
658
|
+
<p className="text-gray-700">
|
|
659
|
+
Você tem certeza que deseja excluir este item?
|
|
660
|
+
Todos os dados associados serão removidos permanentemente.
|
|
661
|
+
</p>
|
|
662
|
+
</Modal.Body>
|
|
663
|
+
|
|
664
|
+
<Modal.Footer>
|
|
665
|
+
<Button variant="outline" onClick={() => setOpen(false)}>
|
|
666
|
+
Cancelar
|
|
667
|
+
</Button>
|
|
668
|
+
<Button onClick={() => {
|
|
669
|
+
// Executar ação
|
|
670
|
+
setOpen(false);
|
|
671
|
+
}}>
|
|
672
|
+
Confirmar
|
|
673
|
+
</Button>
|
|
674
|
+
</Modal.Footer>
|
|
675
|
+
</Modal>
|
|
676
|
+
</div>
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
Exemplo com formulário integrado:
|
|
682
|
+
|
|
683
|
+
```tsx
|
|
684
|
+
import React from 'react';
|
|
685
|
+
import { Modal, Button, Input } from 'rharuow-ds';
|
|
686
|
+
import { FormProvider, useForm } from 'react-hook-form';
|
|
687
|
+
|
|
688
|
+
function FormModal() {
|
|
689
|
+
const [open, setOpen] = React.useState(false);
|
|
690
|
+
const methods = useForm();
|
|
691
|
+
|
|
692
|
+
const onSubmit = (data: any) => {
|
|
693
|
+
console.log('Form data:', data);
|
|
694
|
+
setOpen(false);
|
|
695
|
+
methods.reset();
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
return (
|
|
699
|
+
<div>
|
|
700
|
+
<Button onClick={() => setOpen(true)}>Novo Cadastro</Button>
|
|
701
|
+
|
|
702
|
+
<Modal
|
|
703
|
+
open={open}
|
|
704
|
+
onClose={() => setOpen(false)}
|
|
705
|
+
size="lg"
|
|
706
|
+
closeOnOverlayClick={false}
|
|
707
|
+
>
|
|
708
|
+
<FormProvider {...methods}>
|
|
709
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
710
|
+
<Modal.Header>
|
|
711
|
+
<h2 className="text-2xl font-bold">Cadastrar Usuário</h2>
|
|
712
|
+
</Modal.Header>
|
|
713
|
+
|
|
714
|
+
<Modal.Body>
|
|
715
|
+
<div className="space-y-4">
|
|
716
|
+
<Input label="Nome completo" name="name" required />
|
|
717
|
+
<Input label="E-mail" name="email" type="email" required />
|
|
718
|
+
<Input label="Telefone" name="phone" />
|
|
719
|
+
</div>
|
|
720
|
+
</Modal.Body>
|
|
721
|
+
|
|
722
|
+
<Modal.Footer>
|
|
723
|
+
<Button
|
|
724
|
+
type="button"
|
|
725
|
+
variant="outline"
|
|
726
|
+
onClick={() => setOpen(false)}
|
|
727
|
+
>
|
|
728
|
+
Cancelar
|
|
729
|
+
</Button>
|
|
730
|
+
<Button type="submit">Salvar</Button>
|
|
731
|
+
</Modal.Footer>
|
|
732
|
+
</form>
|
|
733
|
+
</FormProvider>
|
|
734
|
+
</Modal>
|
|
735
|
+
</div>
|
|
736
|
+
);
|
|
737
|
+
}
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
Veja a story do componente no Storybook para mais exemplos e variações:
|
|
741
|
+
|
|
742
|
+
[Storybook — Modal](https://rharuow.github.io/rharuow-ds-docs/?path=/story/components-modal--basic)
|
|
743
|
+
|
|
744
|
+
### � **Toaster**
|
|
745
|
+
|
|
746
|
+
Sistema completo de notificações toast para feedback ao usuário com múltiplas variantes e posicionamento flexível.
|
|
747
|
+
|
|
748
|
+
- ✅ 5 variantes de toast: success, error, warning, info, default
|
|
749
|
+
- ✅ 6 posições configuráveis na tela
|
|
750
|
+
- ✅ Auto-dismiss com duração customizável
|
|
751
|
+
- ✅ Toast permanente (duration: 0)
|
|
752
|
+
- ✅ Ícones automáticos por variante
|
|
753
|
+
- ✅ Animações suaves de entrada e saída
|
|
754
|
+
- ✅ Limite de toasts simultâneos (padrão: 5)
|
|
755
|
+
- ✅ Callbacks ao fechar
|
|
756
|
+
- ✅ Hook `useToast` para uso simplificado
|
|
757
|
+
- ✅ Gerenciamento via Context API
|
|
758
|
+
|
|
759
|
+
**Configuração inicial:**
|
|
760
|
+
|
|
761
|
+
O Toaster precisa ser configurado uma única vez no nível superior da aplicação:
|
|
762
|
+
|
|
763
|
+
```tsx
|
|
764
|
+
import React from 'react';
|
|
765
|
+
import { ToasterProvider } from 'rharuow-ds';
|
|
766
|
+
|
|
767
|
+
function App() {
|
|
768
|
+
return (
|
|
769
|
+
<ToasterProvider position="top-right" maxToasts={5}>
|
|
770
|
+
{/* Sua aplicação aqui */}
|
|
771
|
+
<YourApp />
|
|
772
|
+
</ToasterProvider>
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
Props do `ToasterProvider`:
|
|
778
|
+
|
|
779
|
+
- `position?: ToastPosition` - Posição dos toasts na tela (padrão: 'top-right')
|
|
780
|
+
- Opções: 'top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'
|
|
781
|
+
- `maxToasts?: number` - Número máximo de toasts simultâneos (padrão: 5)
|
|
782
|
+
|
|
783
|
+
**Uso básico com hook `useToast`:**
|
|
784
|
+
|
|
785
|
+
```tsx
|
|
786
|
+
import React from 'react';
|
|
787
|
+
import { useToast, Button } from 'rharuow-ds';
|
|
788
|
+
|
|
789
|
+
function MyComponent() {
|
|
790
|
+
const toast = useToast();
|
|
791
|
+
|
|
792
|
+
return (
|
|
793
|
+
<div>
|
|
794
|
+
<Button onClick={() => toast.success('Operação realizada com sucesso!')}>
|
|
795
|
+
Success
|
|
796
|
+
</Button>
|
|
797
|
+
|
|
798
|
+
<Button onClick={() => toast.error('Erro ao processar requisição')}>
|
|
799
|
+
Error
|
|
800
|
+
</Button>
|
|
801
|
+
|
|
802
|
+
<Button onClick={() => toast.warning('Atenção: verifique os dados')}>
|
|
803
|
+
Warning
|
|
804
|
+
</Button>
|
|
805
|
+
|
|
806
|
+
<Button onClick={() => toast.info('Você tem 3 novas mensagens')}>
|
|
807
|
+
Info
|
|
808
|
+
</Button>
|
|
809
|
+
</div>
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
**Toasts com duração customizada:**
|
|
815
|
+
|
|
816
|
+
```tsx
|
|
817
|
+
import React from 'react';
|
|
818
|
+
import { useToast, Button } from 'rharuow-ds';
|
|
819
|
+
|
|
820
|
+
function CustomDuration() {
|
|
821
|
+
const toast = useToast();
|
|
822
|
+
|
|
823
|
+
return (
|
|
824
|
+
<div>
|
|
825
|
+
{/* Toast rápido - 2 segundos */}
|
|
826
|
+
<Button onClick={() => toast.success('Toast rápido', 2000)}>
|
|
827
|
+
2 Segundos
|
|
828
|
+
</Button>
|
|
829
|
+
|
|
830
|
+
{/* Toast longo - 10 segundos */}
|
|
831
|
+
<Button onClick={() => toast.info('Toast longo', 10000)}>
|
|
832
|
+
10 Segundos
|
|
833
|
+
</Button>
|
|
834
|
+
|
|
835
|
+
{/* Toast permanente - não fecha automaticamente */}
|
|
836
|
+
<Button
|
|
837
|
+
onClick={() => toast.toast('Toast permanente', { duration: 0 })}
|
|
838
|
+
>
|
|
839
|
+
Permanente
|
|
840
|
+
</Button>
|
|
841
|
+
</div>
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
**Toast com callback ao fechar:**
|
|
847
|
+
|
|
848
|
+
```tsx
|
|
849
|
+
import React from 'react';
|
|
850
|
+
import { useToaster, Button } from 'rharuow-ds';
|
|
851
|
+
|
|
852
|
+
function WithCallback() {
|
|
853
|
+
const { addToast } = useToaster();
|
|
854
|
+
|
|
855
|
+
const handleAction = () => {
|
|
856
|
+
addToast({
|
|
857
|
+
message: 'Processando dados...',
|
|
858
|
+
variant: 'info',
|
|
859
|
+
duration: 3000,
|
|
860
|
+
onClose: () => {
|
|
861
|
+
console.log('Toast fechado!');
|
|
862
|
+
// Executar ação após fechamento
|
|
863
|
+
performNextAction();
|
|
864
|
+
},
|
|
865
|
+
});
|
|
866
|
+
};
|
|
867
|
+
|
|
868
|
+
return <Button onClick={handleAction}>Iniciar Processo</Button>;
|
|
869
|
+
}
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
**Exemplo completo em um formulário:**
|
|
873
|
+
|
|
874
|
+
```tsx
|
|
875
|
+
import React from 'react';
|
|
876
|
+
import { useForm, FormProvider } from 'react-hook-form';
|
|
877
|
+
import { Input, Button, useToast } from 'rharuow-ds';
|
|
878
|
+
|
|
879
|
+
function FormWithToast() {
|
|
880
|
+
const methods = useForm();
|
|
881
|
+
const toast = useToast();
|
|
882
|
+
|
|
883
|
+
const onSubmit = async (data: any) => {
|
|
884
|
+
try {
|
|
885
|
+
// Simular chamada à API
|
|
886
|
+
await saveData(data);
|
|
887
|
+
|
|
888
|
+
toast.success('Dados salvos com sucesso!');
|
|
889
|
+
methods.reset();
|
|
890
|
+
} catch (error) {
|
|
891
|
+
toast.error('Erro ao salvar dados. Tente novamente.');
|
|
892
|
+
console.error(error);
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
|
|
896
|
+
return (
|
|
897
|
+
<FormProvider {...methods}>
|
|
898
|
+
<form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
899
|
+
<Input label="Nome" name="name" required />
|
|
900
|
+
<Input label="E-mail" name="email" type="email" required />
|
|
901
|
+
|
|
902
|
+
<Button type="submit">Salvar</Button>
|
|
903
|
+
</form>
|
|
904
|
+
</FormProvider>
|
|
905
|
+
);
|
|
906
|
+
}
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
**API do hook `useToast`:**
|
|
910
|
+
|
|
911
|
+
```typescript
|
|
912
|
+
const toast = useToast();
|
|
913
|
+
|
|
914
|
+
// Métodos disponíveis:
|
|
915
|
+
toast.success(message: string, duration?: number)
|
|
916
|
+
toast.error(message: string, duration?: number)
|
|
917
|
+
toast.warning(message: string, duration?: number)
|
|
918
|
+
toast.info(message: string, duration?: number)
|
|
919
|
+
toast.toast(message: string, options?: ToastOptions)
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
**API avançada com `useToaster`:**
|
|
923
|
+
|
|
924
|
+
```typescript
|
|
925
|
+
const { addToast, removeToast, clearAll, toasts } = useToaster();
|
|
926
|
+
|
|
927
|
+
// Adicionar toast com controle total
|
|
928
|
+
const id = addToast({
|
|
929
|
+
message: 'Mensagem personalizada',
|
|
930
|
+
variant: 'success',
|
|
931
|
+
duration: 5000,
|
|
932
|
+
onClose: () => console.log('Fechado'),
|
|
933
|
+
});
|
|
934
|
+
|
|
935
|
+
// Remover toast específico
|
|
936
|
+
removeToast(id);
|
|
937
|
+
|
|
938
|
+
// Limpar todos os toasts
|
|
939
|
+
clearAll();
|
|
940
|
+
```
|
|
941
|
+
|
|
942
|
+
**Dicas de uso:**
|
|
943
|
+
|
|
944
|
+
- Use `success` para operações bem-sucedidas (save, delete, update)
|
|
945
|
+
- Use `error` para falhas e erros
|
|
946
|
+
- Use `warning` para avisos que requerem atenção
|
|
947
|
+
- Use `info` para informações gerais
|
|
948
|
+
- Configure `duration: 0` para toasts que precisam de ação manual do usuário
|
|
949
|
+
- Posicione toasts conforme o contexto: top para notificações gerais, bottom para ações específicas
|
|
950
|
+
|
|
951
|
+
Veja a story do componente no Storybook para demonstrações interativas:
|
|
952
|
+
|
|
953
|
+
[Storybook — Toaster](https://rharuow.github.io/rharuow-ds-docs/?path=/story/components-toaster--top-right)
|
|
954
|
+
|
|
955
|
+
### �📷 **ImageInput**
|
|
586
956
|
|
|
587
957
|
Componente para seleção e upload de imagens com preview e ações de confirmação/remoção:
|
|
588
958
|
|