@koaris/bloom-ui 1.1.1 → 1.1.2

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,67 @@
1
+ import { DetailedHTMLProps, HTMLAttributes, useState } from 'react'
2
+ import { twMerge } from 'tailwind-merge'
3
+ import { FiCheck } from 'react-icons/fi'
4
+
5
+ const options = [
6
+ { id: 1, value: 'option1', label: 'Opção 1' },
7
+ { id: 2, value: 'option2', label: 'Opção 2' },
8
+ ]
9
+
10
+ export interface RadioGroupProps
11
+ extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
12
+ disabled?: boolean
13
+ options: typeof options
14
+ required?: boolean
15
+ }
16
+
17
+ export const RadioGroup = ({
18
+ disabled,
19
+ options = [
20
+ { id: 1, value: 'option1', label: 'Opção 1' },
21
+ { id: 2, value: 'option2', label: 'Opção 2' },
22
+ ],
23
+ required = false,
24
+ className,
25
+ }: RadioGroupProps) => {
26
+ const [selectedOption, setSelectedOption] = useState('')
27
+
28
+ const handleOptionChange = (value: string) => {
29
+ setSelectedOption(value)
30
+ }
31
+
32
+ return (
33
+ <div className="flex flex-col ">
34
+ {options.map((option) => (
35
+ <div key={option.id} className="flex py-2 items-center">
36
+ <label
37
+ htmlFor={`radio${option.id}`}
38
+ className={twMerge(
39
+ 'relative rounded-full border-2 w-5 h-5 flex items-center justify-center hover:border-orange-500 hover:cursor-pointer',
40
+ selectedOption === option.value
41
+ ? 'bg-orange-500 border-orange-500'
42
+ : 'border-neutral-500 hover:shadow-md hover:shadow-orange-500',
43
+ disabled === true && 'opacity-50 cursor-not-allowed',
44
+ className,
45
+ )}
46
+ >
47
+ <input
48
+ type="radio"
49
+ id={`radio${option.id}`}
50
+ name="radioGroup"
51
+ value={option.value}
52
+ required={required}
53
+ className="hidden"
54
+ checked={selectedOption === option.value}
55
+ onChange={() => handleOptionChange(option.value)}
56
+ disabled={disabled}
57
+ />
58
+ {selectedOption === option.value && (
59
+ <FiCheck color="#FFFFFF" size={12} style={{ strokeWidth: 4 }} />
60
+ )}
61
+ </label>
62
+ <span className="px-2">{option.label}</span>
63
+ </div>
64
+ ))}
65
+ </div>
66
+ )
67
+ }
@@ -0,0 +1,60 @@
1
+ const masks = {
2
+ password: [/^(?=.*[!@#$%^&*])/, /(?=.*[0-9])/, /.{8,}$/],
3
+ date: [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/],
4
+ cpf: [
5
+ /\d/,
6
+ /\d/,
7
+ /\d/,
8
+ '.',
9
+ /\d/,
10
+ /\d/,
11
+ /\d/,
12
+ '.',
13
+ /\d/,
14
+ /\d/,
15
+ /\d/,
16
+ '-',
17
+ /\d/,
18
+ /\d/,
19
+ ],
20
+ cnpj: [
21
+ /\d/,
22
+ /\d/,
23
+ '.',
24
+ /\d/,
25
+ /\d/,
26
+ /\d/,
27
+ '.',
28
+ /\d/,
29
+ /\d/,
30
+ /\d/,
31
+ '/',
32
+ /\d/,
33
+ /\d/,
34
+ /\d/,
35
+ /\d/,
36
+ '-',
37
+ /\d/,
38
+ /\d/,
39
+ ],
40
+ cep: [/\d/, /\d/, /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/],
41
+ phone: [
42
+ '(',
43
+ /[1-9]/,
44
+ /[1-9]/,
45
+ ')',
46
+ ' ',
47
+ /\d/,
48
+ /\d/,
49
+ /\d/,
50
+ /\d/,
51
+ /\d/,
52
+ '-',
53
+ /\d/,
54
+ /\d/,
55
+ /\d/,
56
+ /\d/,
57
+ ],
58
+ }
59
+
60
+ export default masks
@@ -0,0 +1,62 @@
1
+ import { DetailedHTMLProps, HTMLAttributes, ReactNode } from 'react'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export interface TextProps
5
+ extends DetailedHTMLProps<
6
+ HTMLAttributes<HTMLLabelElement>,
7
+ HTMLLabelElement
8
+ > {
9
+ children: ReactNode
10
+ color?: string
11
+ size?:
12
+ | 'xxs'
13
+ | 'xs'
14
+ | 'sm'
15
+ | 'md'
16
+ | 'lg'
17
+ | 'xl'
18
+ | '2xl'
19
+ | '3xl'
20
+ | '4xl'
21
+ | '5xl'
22
+ | '6xl'
23
+ | '7xl'
24
+ | '8xl'
25
+ | '9xl'
26
+ tag?: 'p' | 'strong' | 'span' | 'label'
27
+ htmlFor?: string
28
+ }
29
+
30
+ export const Text = ({
31
+ children,
32
+ color = 'neutral-800',
33
+ size = 'md',
34
+ tag = 'p',
35
+ className,
36
+ ...rest
37
+ }: TextProps) => {
38
+ const fontSize = {
39
+ xxs: 'text-xxs',
40
+ xs: 'text-xs',
41
+ sm: 'text-sm',
42
+ md: 'text-md',
43
+ lg: 'text-lg',
44
+ xl: 'text-xl',
45
+ '2xl': 'text-2xl',
46
+ '3xl': 'text-3xl',
47
+ '4xl': 'text-4xl',
48
+ '5xl': 'text-5xl',
49
+ '6xl': 'text-6xl',
50
+ '7xl': 'text-7xl',
51
+ '8xl': 'text-8xl',
52
+ '9xl': 'text-9xl',
53
+ }[size]
54
+
55
+ const Tag = tag as React.ElementType
56
+
57
+ return (
58
+ <Tag {...rest} className={twMerge(`text-${color} ${fontSize}`, className)}>
59
+ {children}
60
+ </Tag>
61
+ )
62
+ }
@@ -0,0 +1,79 @@
1
+ import {
2
+ DetailedHTMLProps,
3
+ TextareaHTMLAttributes,
4
+ useEffect,
5
+ useState,
6
+ } from 'react'
7
+ import { twMerge } from 'tailwind-merge'
8
+
9
+ export interface TextAreaProps
10
+ extends DetailedHTMLProps<
11
+ TextareaHTMLAttributes<HTMLTextAreaElement>,
12
+ HTMLTextAreaElement
13
+ > {
14
+ disabled?: boolean
15
+ reference?: React.RefObject<HTMLTextAreaElement>
16
+ placeholder?: string
17
+ value?: string
18
+ validated?: boolean
19
+ error: boolean
20
+ required?: boolean
21
+ resize?: boolean
22
+ type: 'text' | 'password' | 'date' | 'cpf' | 'phone' | 'cnpj' | 'cep'
23
+ }
24
+
25
+ export const TextArea = ({
26
+ className,
27
+ disabled,
28
+ reference,
29
+ value,
30
+ error,
31
+ required,
32
+ placeholder,
33
+ resize,
34
+ onClick,
35
+ ...rest
36
+ }: TextAreaProps) => {
37
+ const [selected, setSelected] = useState(false)
38
+ const [inputValue, setInputValue] = useState(value)
39
+
40
+ const handleFocus = () => {
41
+ setSelected(!selected)
42
+ }
43
+
44
+ const handleBlur = () => {
45
+ setSelected(false)
46
+ }
47
+
48
+ const handleInput = (event: React.FocusEvent<HTMLTextAreaElement>) => {
49
+ setInputValue(event.currentTarget.value)
50
+ }
51
+
52
+ useEffect(() => {
53
+ setInputValue(value)
54
+ }, [value])
55
+
56
+ return (
57
+ <textarea
58
+ required={required}
59
+ ref={reference}
60
+ disabled={disabled}
61
+ className={twMerge(
62
+ 'rounded-sm w-full px-3 py-2 border-2 border-neutral text-md hover:shadow-md hover:shadow-neutral-500 focus:outline-none',
63
+ 'resize-y h-32',
64
+ className,
65
+ disabled === true && 'opacity-50 cursor-not-allowed',
66
+ selected === true && 'border-2 border-orange-500',
67
+ error === true && 'border-2 border-red-900',
68
+ resize === false && 'resize-none overflow-hidden',
69
+ )}
70
+ onClick={onClick}
71
+ onFocus={handleFocus}
72
+ onChange={handleInput}
73
+ onBlur={handleBlur}
74
+ placeholder={placeholder}
75
+ value={inputValue}
76
+ {...rest}
77
+ />
78
+ )
79
+ }
@@ -0,0 +1,102 @@
1
+ import {
2
+ DetailedHTMLProps,
3
+ InputHTMLAttributes,
4
+ useEffect,
5
+ useState,
6
+ forwardRef,
7
+ } from 'react'
8
+ import { twMerge } from 'tailwind-merge'
9
+
10
+ export interface TextInputProps
11
+ extends DetailedHTMLProps<
12
+ InputHTMLAttributes<HTMLInputElement>,
13
+ HTMLInputElement
14
+ > {
15
+ disabled?: boolean
16
+ placeholder?: string
17
+ prefix?: string
18
+ value?: string
19
+ variant?: 'primary' | 'secondary'
20
+ validated?: boolean
21
+ error: boolean
22
+ required?: boolean
23
+ type: 'text' | 'password' | 'date' | 'cpf' | 'phone' | 'cnpj' | 'cep'
24
+ }
25
+
26
+ const TextInput = forwardRef<HTMLInputElement, TextInputProps>(
27
+ (
28
+ {
29
+ className,
30
+ disabled,
31
+ value,
32
+ prefix,
33
+ placeholder,
34
+ error,
35
+ type = 'text',
36
+ variant = 'primary',
37
+ onClick,
38
+ ...rest
39
+ }: TextInputProps,
40
+ ref,
41
+ ) => {
42
+ const [selected, setSelected] = useState(false)
43
+ const [inputValue, setInputValue] = useState(value)
44
+
45
+ const handleFocus = () => {
46
+ setSelected(!selected)
47
+ }
48
+
49
+ const handleBlur = () => {
50
+ setSelected(false)
51
+ }
52
+
53
+ const handleInput = (event: React.FocusEvent<HTMLInputElement>) => {
54
+ setInputValue(event.currentTarget.value)
55
+ }
56
+
57
+ useEffect(() => {
58
+ setInputValue(value)
59
+ }, [value])
60
+
61
+ return (
62
+ <div
63
+ className={twMerge(
64
+ ' py-2 px-4 border-2 rounded-sm box-border flex items-baseline bg-neutral-200',
65
+ 'hover:shadow-md hover:shadow-neutral-500 focus:outline-none',
66
+ variant === 'secondary' && 'bg-neutral-800 border-neutral-800 ',
67
+ selected === true && 'border-2 border-orange-500',
68
+ disabled === true && 'opacity-50 cursor-not-allowed',
69
+ error === true && 'border-2 border-red-900',
70
+ )}
71
+ >
72
+ {!!prefix && (
73
+ <span className="text-neutral-500 sm:text-sm">{prefix}</span>
74
+ )}
75
+ <input
76
+ type={type}
77
+ required={rest.required}
78
+ onClick={onClick}
79
+ onFocus={handleFocus}
80
+ onChange={handleInput}
81
+ onBlur={handleBlur}
82
+ value={inputValue}
83
+ placeholder={placeholder}
84
+ disabled={disabled}
85
+ ref={ref}
86
+ className={twMerge(
87
+ 'flex items-center justify-center bg-neutral-200 rounded-sm w-full px-1 py-2 text-md',
88
+ 'focus:outline-none text-neutral-800',
89
+ disabled === true && 'cursor-not-allowed',
90
+ variant === 'secondary' && 'bg-neutral-800 text-neutral',
91
+ className,
92
+ )}
93
+ {...rest}
94
+ />
95
+ </div>
96
+ )
97
+ },
98
+ )
99
+
100
+ TextInput.displayName = 'TextInput'
101
+
102
+ export { TextInput }
package/src/index.tsx ADDED
@@ -0,0 +1,14 @@
1
+ export * from './components/Card'
2
+ export * from './components/Button'
3
+ export * from './components/Link'
4
+ export * from './components/RadioGroup'
5
+ export * from './components/Checkbox'
6
+ export * from './components/Input'
7
+ export * from './components/TextInput'
8
+ export * from './components/TextArea'
9
+ export * from './components/Text'
10
+ export * from './components/Heading'
11
+ export * from './components/Box'
12
+ export * from './components/Form'
13
+ export * from './components/Avatar'
14
+ export * from './components/MultiStep'
@@ -0,0 +1,7 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ html {
6
+ @apply font-default;
7
+ }
@@ -0,0 +1,19 @@
1
+ import { Config } from 'tailwindcss'
2
+ import { colors, fontSizes, fontWeights, fonts, lineHeights, raddi, space } from '@koaris/tokens';
3
+
4
+ /** @type {import('tailwindcss').Config} */
5
+ export default {
6
+ content: ['./src/**/*.{js,ts,jsx,tsx}'],
7
+ theme: {
8
+ extend: {
9
+ colors: colors,
10
+ fontSize: fontSizes,
11
+ fontWeight: fontWeights,
12
+ fontFamily: fonts,
13
+ lineHeight: lineHeights,
14
+ raddi,
15
+ space
16
+ },
17
+ },
18
+ plugins: [],
19
+ } satisfies Config
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "@koaris/ts-config/react.json",
3
+ "include": ["src"],
4
+ "splitting": true,
5
+ "external": ["react"],
6
+ "entryPoints": ["src/index.tsx"],
7
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.tsx", "src/tailwind-preset.ts"],
5
+ format: ["esm"],
6
+ tsconfig: "./tsconfig.json",
7
+ outExtension({ format }) {
8
+ return { js: ".mjs" };
9
+ },
10
+ dts: true,
11
+ external: ["react"],
12
+
13
+ clean: true,
14
+ });
package/dist/index.d.mts DELETED
@@ -1,145 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as react from 'react';
3
- import { DetailedHTMLProps, HTMLAttributes, ButtonHTMLAttributes, AnchorHTMLAttributes, InputHTMLAttributes, TextareaHTMLAttributes, ReactNode, FormHTMLAttributes } from 'react';
4
-
5
- /**
6
- * Primary UI component for user interaction
7
- */
8
- interface CardProps extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, // Change the type to HTMLDivElement
9
- HTMLDivElement> {
10
- selected?: boolean;
11
- disabled?: boolean;
12
- direction?: string;
13
- size?: string;
14
- imageSize: string;
15
- image?: string;
16
- onClick?: () => void;
17
- }
18
- declare const Card: ({ className, selected, direction, size, disabled, imageSize, onClick, ...rest }: CardProps) => react_jsx_runtime.JSX.Element;
19
-
20
- /**
21
- * Primary UI component for user interaction
22
- */
23
- interface ButtonProps extends DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
24
- size?: 'sm' | 'md';
25
- variant?: 'primary' | 'secondary';
26
- disabled?: boolean;
27
- children: string | JSX.Element;
28
- }
29
- declare const Button: ({ className, variant, size, disabled, onClick, ...rest }: ButtonProps) => react_jsx_runtime.JSX.Element;
30
-
31
- /**
32
- * Primary UI component for user interaction
33
- */
34
- interface LinkProps extends DetailedHTMLProps<AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement> {
35
- url: string;
36
- newPage: boolean;
37
- disabled?: boolean;
38
- children: string | JSX.Element;
39
- }
40
- declare const Link: ({ className, disabled, url, newPage, onClick, ...rest }: LinkProps) => react_jsx_runtime.JSX.Element;
41
-
42
- declare const options: {
43
- id: number;
44
- value: string;
45
- label: string;
46
- }[];
47
- interface RadioGroupProps extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
48
- disabled?: boolean;
49
- options: typeof options;
50
- required?: boolean;
51
- }
52
- declare const RadioGroup: ({ disabled, options, required, className, }: RadioGroupProps) => react_jsx_runtime.JSX.Element;
53
-
54
- interface CheckboxProps extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
55
- disabled?: boolean;
56
- required?: boolean;
57
- }
58
- declare const Checkbox: ({ className, required, disabled }: CheckboxProps) => react_jsx_runtime.JSX.Element;
59
-
60
- /**
61
- * Primary UI component for user interaction
62
- */
63
- interface InputProps extends DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> {
64
- disabled?: boolean;
65
- placeholder?: string;
66
- value?: string;
67
- validated?: boolean;
68
- error: boolean;
69
- required?: boolean;
70
- type: 'text' | 'password' | 'date' | 'cpf' | 'phone' | 'cnpj' | 'cep';
71
- }
72
- declare const Input: react.ForwardRefExoticComponent<Omit<InputProps, "ref"> & react.RefAttributes<HTMLInputElement>>;
73
-
74
- interface TextInputProps extends DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> {
75
- disabled?: boolean;
76
- placeholder?: string;
77
- prefix?: string;
78
- value?: string;
79
- variant?: 'primary' | 'secondary';
80
- validated?: boolean;
81
- error: boolean;
82
- required?: boolean;
83
- type: 'text' | 'password' | 'date' | 'cpf' | 'phone' | 'cnpj' | 'cep';
84
- }
85
- declare const TextInput: react.ForwardRefExoticComponent<Omit<TextInputProps, "ref"> & react.RefAttributes<HTMLInputElement>>;
86
-
87
- interface TextAreaProps extends DetailedHTMLProps<TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement> {
88
- disabled?: boolean;
89
- reference?: React.RefObject<HTMLTextAreaElement>;
90
- placeholder?: string;
91
- value?: string;
92
- validated?: boolean;
93
- error: boolean;
94
- required?: boolean;
95
- resize?: boolean;
96
- type: 'text' | 'password' | 'date' | 'cpf' | 'phone' | 'cnpj' | 'cep';
97
- }
98
- declare const TextArea: ({ className, disabled, reference, value, error, required, placeholder, resize, onClick, ...rest }: TextAreaProps) => react_jsx_runtime.JSX.Element;
99
-
100
- interface TextProps extends DetailedHTMLProps<HTMLAttributes<HTMLLabelElement>, HTMLLabelElement> {
101
- children: ReactNode;
102
- color?: string;
103
- size?: 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl' | '8xl' | '9xl';
104
- tag?: 'p' | 'strong' | 'span' | 'label';
105
- htmlFor?: string;
106
- }
107
- declare const Text: ({ children, color, size, tag, className, ...rest }: TextProps) => react_jsx_runtime.JSX.Element;
108
-
109
- interface HeadingProps extends DetailedHTMLProps<HTMLAttributes<HTMLHeadElement>, HTMLHeadElement> {
110
- children: React.ReactNode;
111
- color?: string;
112
- size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl' | '6xl' | '7xl' | '8xl' | '9xl';
113
- tag?: 'h1' | 'h2' | 'h3' | 'h4';
114
- }
115
- declare const Heading: ({ children, color, size, tag, className, }: HeadingProps) => react_jsx_runtime.JSX.Element;
116
-
117
- interface BoxProps extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
118
- children: React.ReactNode;
119
- tag?: 'div' | 'section' | 'article' | 'aside' | 'header' | 'footer';
120
- variant?: 'primary' | 'secondary';
121
- }
122
- declare const Box: ({ className, children, tag, variant, }: BoxProps) => react_jsx_runtime.JSX.Element;
123
-
124
- interface FormProps extends DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement> {
125
- children: React.ReactNode;
126
- variant?: 'primary' | 'secondary';
127
- orientation?: 'row' | 'col';
128
- handleSubmit?: (event: React.FormEvent<HTMLFormElement>) => void;
129
- }
130
- declare const Form: ({ className, children, variant, orientation, ...rest }: FormProps) => react_jsx_runtime.JSX.Element;
131
-
132
- interface AvatarProps {
133
- src?: string;
134
- alt?: string;
135
- className?: string;
136
- }
137
- declare const Avatar: ({ className, ...rest }: AvatarProps) => react_jsx_runtime.JSX.Element;
138
-
139
- interface MultiStepProps extends DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement> {
140
- size: number;
141
- currentStep?: number;
142
- }
143
- declare const MultiStep: ({ className, size, currentStep }: MultiStepProps) => react_jsx_runtime.JSX.Element;
144
-
145
- export { Avatar, type AvatarProps, Box, type BoxProps, Button, type ButtonProps, Card, type CardProps, Checkbox, type CheckboxProps, Form, type FormProps, Heading, type HeadingProps, Input, type InputProps, Link, type LinkProps, MultiStep, type MultiStepProps, RadioGroup, type RadioGroupProps, Text, TextArea, type TextAreaProps, TextInput, type TextInputProps, type TextProps };