@liguelead/design-system 0.0.16 → 0.0.18

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.
@@ -0,0 +1,23 @@
1
+ import styled from 'styled-components';
2
+ import { parseColor } from 'package/utils';
3
+ import {spacing, radius} from '@liguelead/foundation'
4
+
5
+ export const AlertContainer = styled.div<{ $variant: string }>`
6
+ padding: ${spacing.spacing8}px;
7
+ border: 1px solid ${({theme}) => parseColor(theme.colors.neutral200)};
8
+ background-color: ${({theme}) => parseColor(theme.colors.background)};
9
+ color: ${({theme}) => parseColor(theme.colors.text)};
10
+ border-radius: ${radius.radius4}px;
11
+
12
+ ${({ $variant }) => $variant}
13
+ `;
14
+
15
+ export const AlertContent = styled.div`
16
+ display: flex;
17
+ gap: 8px;
18
+ `;
19
+
20
+ export const AlertButtonContainer = styled.div`
21
+ display: flex;
22
+ justify-content: flex-end;
23
+ `;
@@ -0,0 +1,55 @@
1
+ import Text from '../Text'
2
+ import LinkButton from '../LinkButton'
3
+
4
+ import {
5
+ AlertButtonContainer,
6
+ AlertContainer,
7
+ AlertContent
8
+ } from './Alert.style'
9
+ import { AlertVariant } from './Alert.variants'
10
+ import { TAlertProps } from './Alert.types'
11
+ import { iconsByVariant } from './IconVariant'
12
+
13
+ const Alert = ({
14
+ variant = 'default',
15
+ buttonLabel,
16
+ className,
17
+ description,
18
+ href,
19
+ children,
20
+ title,
21
+ hasButton
22
+ }: TAlertProps) => {
23
+ const alertVariant = AlertVariant(variant)
24
+
25
+ return (
26
+ <AlertContainer $variant={alertVariant} className={className}>
27
+ <AlertContent>
28
+ {iconsByVariant(variant)}
29
+ <div>
30
+ <Text
31
+ size="body03"
32
+ color="textDark"
33
+ weight="fontWeight600"
34
+ className="mb-4">
35
+ {title}
36
+ </Text>
37
+ {description ? (
38
+ <Text size="body02" color="textMedium">
39
+ {description}
40
+ </Text>
41
+ ) : (
42
+ children
43
+ )}
44
+ </div>
45
+ </AlertContent>
46
+ {hasButton && (
47
+ <AlertButtonContainer>
48
+ <LinkButton href={href || ''}>{buttonLabel}</LinkButton>
49
+ </AlertButtonContainer>
50
+ )}
51
+ </AlertContainer>
52
+ )
53
+ }
54
+
55
+ export default Alert
@@ -0,0 +1,10 @@
1
+ export type TAlertProps = {
2
+ buttonLabel?: string
3
+ href?: string
4
+ children?: React.ReactNode
5
+ hasButton?: boolean
6
+ className?: string
7
+ description?: string
8
+ variant?: 'default' | 'danger' | 'warning' | 'info' | 'success'
9
+ title: string
10
+ }
@@ -0,0 +1,68 @@
1
+ import { parseColor } from 'package/utils'
2
+ import { useTheme } from 'styled-components'
3
+
4
+ type TVariant = 'success' | 'danger' | 'warning' | 'info' | 'default'
5
+
6
+ export const AlertVariant = (variant: TVariant) => {
7
+ const theme = useTheme()
8
+
9
+ const variants = {
10
+ success: `
11
+ border-left: 8px solid ${parseColor(theme.colors.success100)};
12
+ & svg {
13
+ fill: ${parseColor(theme.colors.success100)};
14
+ width: 24px;
15
+ height: 24px;
16
+ }
17
+
18
+ & a {
19
+ color: ${parseColor(theme.colors.success100)};
20
+ }
21
+ `,
22
+ danger: `
23
+ border-left: 8px solid ${parseColor(theme.colors.danger200)};
24
+ & svg {
25
+ fill: ${parseColor(theme.colors.danger200)};
26
+ width: 24px;
27
+ height: 24px;
28
+ }
29
+
30
+ & a {
31
+ color: ${parseColor(theme.colors.danger200)};
32
+ }
33
+ `,
34
+ warning: `
35
+ border-left: 8px solid ${parseColor(theme.colors.warning100)};
36
+ & svg {
37
+ fill: ${parseColor(theme.colors.warning100)};
38
+ width: 24px;
39
+ height: 24px;
40
+ }
41
+
42
+ & a {
43
+ color: ${parseColor(theme.colors.warning100)};
44
+ }
45
+ `,
46
+ info: `
47
+ border-left: 8px solid ${parseColor(theme.colors.info100)};
48
+ & svg {
49
+ fill: ${parseColor(theme.colors.info100)};
50
+ width: 24px;
51
+ height: 24px;
52
+ }
53
+
54
+ & a {
55
+ color: ${parseColor(theme.colors.info100)};
56
+ }
57
+ `,
58
+ default: `
59
+ border-left: 8px solid ${parseColor(theme.colors.primary)};
60
+
61
+ & a {
62
+ color: ${parseColor(theme.colors.primary)};
63
+ }
64
+ `
65
+ }
66
+
67
+ return variants[variant]
68
+ }
@@ -0,0 +1,22 @@
1
+ import { TAlertProps } from "./Alert.types"
2
+ import {
3
+ CheckCircleIcon,
4
+ WarningCircleIcon,
5
+ WarningIcon,
6
+ InfoIcon
7
+ } from '@phosphor-icons/react'
8
+
9
+ export const iconsByVariant = (variant: TAlertProps['variant']) => {
10
+ switch (variant) {
11
+ case 'success':
12
+ return <CheckCircleIcon />
13
+ case 'danger':
14
+ return <WarningCircleIcon />
15
+ case 'warning':
16
+ return <WarningIcon />
17
+ case 'info':
18
+ return <InfoIcon />
19
+ default:
20
+ return <></>
21
+ }
22
+ }
@@ -0,0 +1 @@
1
+ export { default } from "./Alert"
@@ -1,6 +1,6 @@
1
1
  import { ButtonVariantTypes} from './Button.types'
2
- import {colorType} from 'types'
3
- import {useTheme} from 'styled-components'
2
+ import { colorType } from '../../../types'
3
+ import { useTheme } from 'styled-components'
4
4
  import {darkenOrLighten, getTextColor, parseColor} from '../../utils'
5
5
 
6
6
  export const ButtonVariant = (
@@ -1,4 +1,4 @@
1
- import { colorType } from 'types'
1
+ import { colorType } from '../../../types'
2
2
 
3
3
  export type ButtonSizeTypes = 'sm' | 'md' | 'lg'
4
4
  export type ButtonVariantTypes = 'solid' | 'outline' | 'ghost'
@@ -7,7 +7,6 @@ import {
7
7
  } from '@liguelead/foundation'
8
8
  import { parseColor } from '../../utils'
9
9
  import styled, { css } from 'styled-components'
10
- import Text from '../Text'
11
10
 
12
11
  export const CheckboxWrapper = styled.label`
13
12
  display: flex;
@@ -33,9 +32,9 @@ export const CheckboxWrapper = styled.label`
33
32
  export const CustomCheckbox = styled.span<{
34
33
  checked: boolean
35
34
  disabled?: boolean
36
- error?: boolean
35
+ $hasError?: boolean
37
36
  }>`
38
- ${({ checked, theme, disabled, error }) => css`
37
+ ${({ checked, theme, disabled, $hasError }) => css`
39
38
  width: ${spacing.spacing16}px;
40
39
  height: ${spacing.spacing16}px;
41
40
  border: 1px solid ${checked
@@ -60,7 +59,7 @@ export const CustomCheckbox = styled.span<{
60
59
  cursor: not-allowed;
61
60
  `}
62
61
 
63
- ${error &&
62
+ ${$hasError &&
64
63
  css`
65
64
  border-color: ${parseColor(theme.colors.danger200)};
66
65
  box-shadow: ${shadow.errorShadow};
@@ -100,7 +99,7 @@ export const RippleContainer = styled.span`
100
99
  }
101
100
  `
102
101
 
103
- export const Label = styled.span<{ disabled?: boolean }>`
102
+ export const Label = styled.label<{ disabled?: boolean }>`
104
103
  font-size: ${fontSize.fontSize14}px;
105
104
  font-weight: ${fontWeight.fontWeight500};
106
105
 
@@ -110,15 +109,15 @@ export const Label = styled.span<{ disabled?: boolean }>`
110
109
  : parseColor(theme.colors.textDark)};
111
110
  `
112
111
 
113
- export const CustomLabel = styled(Text)<{ disabled?: boolean; error?: boolean }>`
112
+ export const CustomLabel = styled.p<{ disabled?: boolean; $hasError?: boolean }>`
114
113
  font-size: ${fontSize.fontSize12}px;
115
114
  font-weight: ${fontWeight.fontWeight400};
116
115
  line-height: 8px;
117
116
 
118
- color: ${({ theme, disabled, error }) =>
117
+ color: ${({ theme, disabled, $hasError }) =>
119
118
  disabled
120
119
  ? `${parseColor(theme.colors.textMedium)}70`
121
- : error
120
+ : $hasError
122
121
  ? parseColor(theme.colors.danger200)
123
122
  : parseColor(theme.colors.textMedium)};
124
123
  `
@@ -21,9 +21,9 @@ const Checkbox: React.FC<CheckboxProps> = ({
21
21
  disabled = false,
22
22
  register,
23
23
  className,
24
- error,
25
24
  children,
26
25
  description,
26
+ $hasError,
27
27
  ...rest
28
28
  }) => {
29
29
  const [internalChecked, setInternalChecked] = useState<boolean>(
@@ -66,7 +66,7 @@ const Checkbox: React.FC<CheckboxProps> = ({
66
66
  <CustomCheckbox
67
67
  checked={internalChecked}
68
68
  disabled={disabled}
69
- error={!!error}
69
+ $hasError={$hasError}
70
70
  onClick={handleRipple}>
71
71
  {ripples.map(ripple => (
72
72
  <RippleContainer
@@ -85,9 +85,9 @@ const Checkbox: React.FC<CheckboxProps> = ({
85
85
  </CustomCheckbox>
86
86
  <div>
87
87
  {label ? <Label disabled={disabled}>{label}</Label> : children}
88
- {(description || error) && (
89
- <CustomLabel disabled={disabled} weight="fontWeight400">
90
- {error?.message || description}
88
+ {(description || $hasError) && (
89
+ <CustomLabel disabled={disabled} $hasError={$hasError}>
90
+ {description}
91
91
  </CustomLabel>
92
92
  )}
93
93
  </div>
@@ -1,9 +1,9 @@
1
- import { FieldValues, UseFormRegisterReturn } from 'react-hook-form'
1
+ import { UseFormRegisterReturn } from 'react-hook-form'
2
2
 
3
- export interface CheckboxProps<TFieldValues extends FieldValues = FieldValues> {
3
+ export interface CheckboxProps {
4
4
  label?: string
5
5
  checked?: boolean
6
- error?: TFieldValues
6
+ $hasError?: boolean
7
7
  description?: string
8
8
  children?: React.ReactNode
9
9
  onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void
@@ -70,7 +70,7 @@ const DatePickerCustom = forwardRef<HTMLInputElement, DatePickerProps>(
70
70
  </ButtonDatePicker>
71
71
  </DropdownMenu.Trigger>
72
72
  <DropdownContent>
73
- {years.map(option => (
73
+ {years.map((option: number) => (
74
74
  <DropdownItem
75
75
  key={option}
76
76
  onSelect={() => {
@@ -0,0 +1,62 @@
1
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
2
+ import styled from 'styled-components';
3
+ import { spacing, shadow } from '@liguelead/foundation';
4
+ import { parseColor } from '../../utils';
5
+
6
+ export const Overlay = styled(DialogPrimitive.Overlay)`
7
+ background: rgba(0, 0, 0, 0.3);
8
+ position: fixed;
9
+ inset: 0;
10
+ `
11
+
12
+ export const Content = styled(DialogPrimitive.Content)<{$centerContent?: boolean}>`
13
+ background: #fff;
14
+ border: 1px solid ${({ theme }) => parseColor(theme.colors.neutral300)};
15
+ box-shadow: 0 4px 15px -3px rgba(0, 0, 0, 0.1);
16
+ border-radius: 8px;
17
+ padding: ${spacing.spacing24}px;
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: ${({ $centerContent }) => ($centerContent ? 'center' : 'flex-start')};
21
+
22
+ min-width: 425px;
23
+ max-width: 90vw;
24
+ position: fixed;
25
+ top: 50%;
26
+ left: 50%;
27
+ transform: translate(-50%, -50%);
28
+ `
29
+ export const CloseDialogIconButton = styled.button`
30
+ position: absolute;
31
+ top: 10px;
32
+ right: 10px;
33
+ background: none;
34
+ border: none;
35
+ border-radius: 8px;
36
+ padding: 0px 2px;
37
+
38
+ & svg {
39
+ color: ${({ theme }) => parseColor(theme.colors.neutral700)};
40
+ }
41
+
42
+ &:hover svg {
43
+ color: ${({ theme }) => parseColor(theme.colors.neutral900)};
44
+ }
45
+
46
+ &:focus {
47
+ box-shadow: ${shadow.focusShadow};
48
+ }
49
+ `
50
+ export const ChildrenContainer = styled.div`
51
+ margin-top: ${spacing.spacing24}px;
52
+ width: 100%;
53
+ `
54
+
55
+ export const ButtonContainer = styled.div<{$centerContent?: boolean}>`
56
+ width: 100%;
57
+ display: flex;
58
+ justify-content: ${({ $centerContent }) => ($centerContent ? 'center' : 'flex-end')};
59
+ flex-direction: ${({ $centerContent }) => ($centerContent ? 'column-reverse' : 'row')};
60
+ gap: ${spacing.spacing12}px;
61
+ margin-top: ${spacing.spacing24}px;
62
+ `;
@@ -0,0 +1,113 @@
1
+ import * as DialogPrimitive from "@radix-ui/react-dialog"
2
+ import { XIcon } from "@phosphor-icons/react"
3
+
4
+ import {
5
+ ButtonContainer,
6
+ ChildrenContainer,
7
+ CloseDialogIconButton,
8
+ Content,
9
+ Overlay
10
+ } from "./Dialog.style"
11
+ import { TDialogProps } from "./Dialog.types"
12
+
13
+ import Button from "../Button"
14
+ import Text from "../Text"
15
+
16
+ export const Dialog: React.FC<TDialogProps> = ({
17
+ open,
18
+ onOpenChange,
19
+ title,
20
+ description,
21
+ trigger,
22
+ children,
23
+ onConfirm,
24
+ variant = 'default',
25
+ className,
26
+ confirmLabel = 'Confirmar',
27
+ cancelLabel = 'Cancelar',
28
+ centerContent = false,
29
+ }: TDialogProps) => {
30
+ return (
31
+ <DialogPrimitive.Root
32
+ open={open}
33
+ onOpenChange={onOpenChange}
34
+ >
35
+ {trigger
36
+ && <DialogPrimitive.Trigger asChild className={className}>
37
+ {trigger}
38
+ </DialogPrimitive.Trigger>
39
+ }
40
+
41
+ <DialogPrimitive.Portal>
42
+ <Overlay />
43
+
44
+ <Content
45
+ className={className}
46
+ $centerContent={centerContent}
47
+ onInteractOutside={(event) => {
48
+ if (variant === 'danger') event.preventDefault()
49
+ }}
50
+ onEscapeKeyDown={(event) => {
51
+ if (variant === 'danger') event.preventDefault()
52
+ }}
53
+ >
54
+ {title && (
55
+ <DialogPrimitive.Title>
56
+ <Text
57
+ isTitle
58
+ tag='h1'
59
+ size="heading01"
60
+ weight="fontWeight500"
61
+ color='textDark'
62
+ >
63
+ {title}
64
+ </Text>
65
+ </DialogPrimitive.Title>
66
+ )}
67
+
68
+ {description && (
69
+ <DialogPrimitive.Description>
70
+ <Text
71
+ tag='p'
72
+ size="body02"
73
+ weight="fontWeight400"
74
+ color='textMedium'
75
+ >
76
+ {description}
77
+ </Text>
78
+ </DialogPrimitive.Description>
79
+ )}
80
+
81
+ <ChildrenContainer>
82
+ {children}
83
+ </ChildrenContainer>
84
+
85
+ <ButtonContainer $centerContent={centerContent}>
86
+ <DialogPrimitive.Close asChild>
87
+ <Button
88
+ variant="outline"
89
+ >
90
+ {cancelLabel}
91
+ </Button>
92
+ </DialogPrimitive.Close>
93
+
94
+ <Button
95
+ onClick={onConfirm}
96
+ >
97
+ {confirmLabel}
98
+ </Button>
99
+ </ButtonContainer>
100
+ {variant === 'danger' ? null : (
101
+ <DialogPrimitive.Close asChild>
102
+ <CloseDialogIconButton aria-label="Fechar">
103
+ <XIcon size={16} />
104
+ </CloseDialogIconButton>
105
+ </DialogPrimitive.Close>
106
+ )}
107
+ </Content>
108
+ </DialogPrimitive.Portal>
109
+ </DialogPrimitive.Root>
110
+ )
111
+ };
112
+
113
+ export default Dialog;
@@ -0,0 +1,17 @@
1
+ import { ReactNode } from "react"
2
+
3
+ export type TDialogProps = {
4
+ open?: boolean
5
+ onOpenChange?: (open: boolean) => void
6
+ title: string
7
+ description?: string
8
+ className?: string
9
+ trigger?: ReactNode
10
+ children: ReactNode
11
+ onConfirm?: () => void
12
+ confirmLabel?: string
13
+ cancelLabel?: string
14
+ disableClose?: boolean
15
+ centerContent?: boolean
16
+ variant?: 'default' | 'danger'
17
+ }
@@ -0,0 +1 @@
1
+ export { default } from "./Dialog";
@@ -9,7 +9,7 @@ interface OptBoxProps {
9
9
 
10
10
  export const OptWrapper = styled.div`
11
11
  display: flex;
12
- gap: ${spacing.spacing8}px;
12
+ justify-content: space-between;
13
13
  `
14
14
 
15
15
  export const OptContainer = styled.div`
@@ -131,7 +131,9 @@ const InputOpt: React.FC<InputOptProps> = ({
131
131
  {Array.from({ length }).map((_, i) => (
132
132
  <React.Fragment key={i}>
133
133
  <OptBox
134
- ref={el => (refs.current[i] = el)}
134
+ ref={(el) => {
135
+ refs.current[i] = el
136
+ }}
135
137
  $disabled={disabled}
136
138
  $error={!!error}
137
139
  value={internal[i] || ''}
@@ -1,6 +1,6 @@
1
1
  import {parseColor} from '../../utils'
2
2
  import styled from 'styled-components'
3
- import {colorType} from 'types'
3
+ import {colorType} from '../../../types'
4
4
  import {spacing, SpacingInterface} from '@liguelead/foundation'
5
5
 
6
6
  type SpacingType = keyof SpacingInterface
@@ -1,4 +1,4 @@
1
- import { colorType } from 'types'
1
+ import { colorType } from '../../../types'
2
2
  type SegmentedButtonType = {
3
3
  label: string
4
4
  action?: () => void
@@ -1,4 +1,4 @@
1
- import { colorType } from 'types'
1
+ import { colorType } from '../../../types'
2
2
  import { ReactNode } from 'react'
3
3
 
4
4
  type AlignType = 'left' | 'center' | 'right' | 'justify'
@@ -7,6 +7,7 @@ type SizeType =
7
7
  | 'span01'
8
8
  | 'body01'
9
9
  | 'body02'
10
+ | 'body03'
10
11
  | 'heading01'
11
12
  | 'heading02'
12
13
  | 'heading03'
@@ -1,10 +1,23 @@
1
1
  import styled, { css } from 'styled-components'
2
2
  import { parseColor } from '../../utils'
3
3
  import { ToastContainer } from 'react-toastify'
4
+ import { spacing, fontSize, radius, fontWeight } from "@liguelead/foundation"
4
5
 
5
6
  export const ToasterStyledContainer = styled(ToastContainer)`
6
7
  ${({ theme }) => css`
7
8
 
9
+ .Toastify__toast {
10
+ border-radius: ${radius.radius4}px;
11
+ font-size: ${fontSize.fontSize14}px;
12
+ white-space: pre-line;
13
+ color: ${parseColor(theme.colors?.textDark)};
14
+ font-weight: ${fontWeight.fontWeight500};
15
+ }
16
+
17
+ .Toastify__toast-icon {
18
+ width: ${spacing.spacing20}px;
19
+ }
20
+
8
21
  /* Colored Theme */
9
22
 
10
23
  .Toastify__toast-theme--colored.Toastify__toast--success {
@@ -1,3 +1,4 @@
1
+ export { default as Alert } from './Alert'
1
2
  export { default as Button } from './Button'
2
3
  export { default as Checkbox } from './Checkbox'
3
4
  export { default as DatePicker } from './DatePicker'
@@ -13,3 +14,4 @@ export { default as SegmentedButton } from './SegmentedButton'
13
14
  export { default as LinkButton } from './LinkButton'
14
15
  export { default as RadioButton } from './RadioButton'
15
16
  export { ToastProvider, Toaster } from './Toaster'
17
+ export { default as Dialog } from './Dialog'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liguelead/design-system",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "type": "module",
5
5
  "main": "components/index.ts",
6
6
  "publishConfig": {