diff --git a/src/components/sq-modal/__docs__/sq-modal.component.example.tsx b/src/components/sq-modal/__docs__/sq-modal.component.example.tsx
index 8d117dd..76b819d 100644
--- a/src/components/sq-modal/__docs__/sq-modal.component.example.tsx
+++ b/src/components/sq-modal/__docs__/sq-modal.component.example.tsx
@@ -1,20 +1,15 @@
import React, { useState } from 'react'
import ModalExample, { Props } from '../sq-modal.component'
-import SqButtonComponent from '../../sq-button/sq-button.component'
+import SqButtonComponent from '../../buttons/sq-button/sq-button.component'
-const Modal = ({ ...props }: Props) => {
+const Modal = ({ children, header, ...props }: Props) => {
const [open, setOpen] = useState(false)
- const header = (
-
- )
-
const footer = (
{
setOpen(false)
}}
@@ -22,7 +17,6 @@ const Modal = ({ ...props }: Props) => {
Cancel
{
setOpen(false)
}}
@@ -32,7 +26,7 @@ const Modal = ({ ...props }: Props) => {
)
- const body =
Content Modal
+ const body =
{children}
return (
{
minHeight: '300px',
}}
>
- setOpen(true)} color="var(--pink)" borderColor="transparent">
- Open Modal
-
- setOpen(false)}>
+ setOpen(true)}>Open Modal
+ setOpen(!open)}
+ onOpenChange={(open) => setOpen(open)}
+ >
{body}
diff --git a/src/components/sq-modal/__docs__/sq-modal.component.stories.tsx b/src/components/sq-modal/__docs__/sq-modal.component.stories.tsx
index 63008dd..02a18fb 100644
--- a/src/components/sq-modal/__docs__/sq-modal.component.stories.tsx
+++ b/src/components/sq-modal/__docs__/sq-modal.component.stories.tsx
@@ -1,5 +1,7 @@
+import React from 'react'
import { Meta, StoryObj } from '@storybook/react'
import SqModalExample from './sq-modal.component.example'
+import { fn } from '@storybook/test'
const meta: Meta
= {
title: 'Components/SqModal',
@@ -10,4 +12,10 @@ const meta: Meta = {
export default meta
type Story = StoryObj
-export const Default: Story = {}
+export const Default: Story = {
+ args: {
+ children: 'Content',
+ header: 'Title',
+ onOpenChange: fn(),
+ },
+}
diff --git a/src/components/sq-overlay/__docs__/sq-overlay.component.example.tsx b/src/components/sq-overlay/__docs__/sq-overlay.component.example.tsx
new file mode 100644
index 0000000..82f63d0
--- /dev/null
+++ b/src/components/sq-overlay/__docs__/sq-overlay.component.example.tsx
@@ -0,0 +1,33 @@
+import React from 'react'
+import SqOverlay, { Props } from '../sq-overlay.component'
+import SqButton from '../../buttons/sq-button/__docs__/sq-button.component.example'
+
+const SqOverlayExample = ({ children, ...props }: Props) => {
+ const [open, setOpen] = React.useState(false)
+ return (
+
+
setOpen(true)}>Open Overlay
+
setOpen(open)} onCloseChange={() => setOpen(false)}>
+
+ {children}
+
+
+
+ )
+}
+
+export default SqOverlayExample
diff --git a/src/components/sq-overlay/__docs__/sq-overlay.component.stories.tsx b/src/components/sq-overlay/__docs__/sq-overlay.component.stories.tsx
new file mode 100644
index 0000000..e6b9dd5
--- /dev/null
+++ b/src/components/sq-overlay/__docs__/sq-overlay.component.stories.tsx
@@ -0,0 +1,26 @@
+import { Meta, StoryObj } from '@storybook/react'
+import SqOverlayExample from './sq-overlay.component.example'
+
+const meta: Meta = {
+ title: 'Components/SqOverlay',
+ parameters: {
+ docs: {
+ description: {
+ component: 'A simple Overlay component',
+ },
+ },
+ },
+ component: SqOverlayExample,
+ tags: ['autodocs'],
+}
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {
+ header: 'Overlay header',
+ children: 'Overlay content',
+ footer: 'Overlay footer',
+ },
+}
diff --git a/src/components/sq-overlay/index.ts b/src/components/sq-overlay/index.ts
new file mode 100644
index 0000000..d6c6e21
--- /dev/null
+++ b/src/components/sq-overlay/index.ts
@@ -0,0 +1 @@
+export { default as SqOverlay } from './sq-overlay.component'
diff --git a/src/components/sq-overlay/sq-overlay.component.md b/src/components/sq-overlay/sq-overlay.component.md
new file mode 100644
index 0000000..6970bdf
--- /dev/null
+++ b/src/components/sq-overlay/sq-overlay.component.md
@@ -0,0 +1,106 @@
+# Overlay
+
+## Props
+
+### 1. overlayClass
+
+- description: Add class to Overlay window
+- type: `string`
+
+### 4. buttonClose
+
+- description: Show or hidden button close
+- type: `boolean`
+
+### 5. backdrop
+
+- description: enable click on backdrop to close Overlay
+- type: `'static' | 'cliclable'`
+
+### 6. open
+
+- description: Open Overlay
+- type: `boolean`
+
+### 7. header
+
+- description: HTML or JSX to header render
+- type: `any`
+
+### 8. footer
+
+- description: HTML or JSX to footer render
+- type: `any`
+
+### 9. onCloseChange
+
+- description: Functon when Overlay is close
+- type: `() => any | void`
+
+### 10. onOpenChange
+
+- description: Function to toggle Open variable
+- type: `open: boolean) => any | void`
+
+### 11. onLeftPress
+
+- description: Function on left keyboard press
+- type: `() => any | void`
+
+### 12. onRightPress
+
+- description: Function on right keyboard press
+- type: `() => any | void`
+
+### 13. width
+
+- description: Overlay width rule
+- type: `string`
+
+### 14. maxWidth
+
+- description: Overlay maxWidth rule
+- type: `string`
+
+### 15. headerColor
+
+- description: Change header color
+- type: `string`
+
+### 16. footerColor
+
+- description: Change footer color
+- type: `string`
+
+### 17. bodyColor
+
+- description: Change body color
+- type: `string`
+
+### 18. backdropColor
+
+- description: Change backdrop color
+- type: `string`
+
+### 19. borderless
+
+- description: Remove border from footer and header
+- type: `boolean`
+
+### 20. overlayDirection
+
+- description: Direction to open overlay
+- type: type: `'right' | 'left'`
+
+### 21. headerHeight
+
+- description: Header height rule
+- type: type: `string`
+
+## Exemple
+
+```jsx
+ setOpen(open)}>
+ Body
+
+```
diff --git a/src/components/sq-overlay/sq-overlay.component.scoped.scss b/src/components/sq-overlay/sq-overlay.component.scoped.scss
new file mode 100644
index 0000000..d5f9db8
--- /dev/null
+++ b/src/components/sq-overlay/sq-overlay.component.scoped.scss
@@ -0,0 +1,16 @@
+.without-header {
+ padding: 0 1rem;
+ border: none;
+ justify-content: flex-end;
+ .modal-exit {
+ margin: 0;
+ padding: 0;
+ }
+}
+.modal-exit {
+ line-height: 20px;
+ transition: all 0.3s ease;
+}
+.modal-over {
+ padding: 0;
+}
diff --git a/src/components/sq-overlay/sq-overlay.component.scss b/src/components/sq-overlay/sq-overlay.component.scss
new file mode 100644
index 0000000..665ec3f
--- /dev/null
+++ b/src/components/sq-overlay/sq-overlay.component.scss
@@ -0,0 +1,81 @@
+.modal.overlay {
+ padding: 0;
+ justify-content: initial;
+ .button-close {
+ top: 1rem;
+ right: 2rem;
+ }
+}
+.overlay {
+ &.left {
+ justify-content: flex-start;
+ }
+ &.right {
+ justify-content: flex-end;
+ }
+ .modal-header {
+ height: 52px;
+ border-radius: 0;
+ overflow: hidden;
+ padding: 1rem 4rem 1rem 2rem;
+ border-bottom: 1px solid var(--border_color);
+ align-items: center;
+ display: flex;
+ margin: 0 auto;
+ }
+ .modal-footer {
+ border-radius: 0;
+ overflow: hidden;
+ padding: 1rem 2rem;
+ border-top: 1px solid var(--border_color);
+ margin: 0 auto;
+ }
+ .borderless {
+ border-color: transparent;
+ }
+ .modal-body {
+ height: calc(100vh - 112px + 1rem - var(--safe-area-inset-bottom));
+ overflow: auto;
+ padding: 2rem !important;
+ }
+ .modal-dialog {
+ transition: opacity 0.3s linear, left 0.3s ease-out, right 0.3s ease-out, width 0.3s ease-out, height 0.3s ease-out !important;
+ transform: translate3d(0%, 0, 0) !important;
+ position: fixed;
+ margin: auto;
+ width: 0;
+ max-width: 100vw;
+ height: 100%;
+ }
+ .modal-content {
+ height: 100%;
+ border-radius: 0;
+ overflow-y: auto;
+ border: none;
+ padding: 0;
+ background-color: transparent;
+
+ .mobile-footer-flex-column {
+ @media (max-width: 767px) {
+ display: flex;
+ flex-direction: column;
+ }
+ }
+ }
+ .modal-footer > * {
+ margin: 0;
+ }
+ &.modal-static {
+ .modal-dialog {
+ transform: scale(1.02) !important;
+ transition: opacity 0.3s linear, left 0.3s ease-out, right 0.3s ease-out, width 0.3s ease-out, height 0.3s ease-out,
+ transform 0.3s ease-out !important;
+ }
+ }
+ &.open {
+ .modal-dialog.opened {
+ width: 320px;
+ margin: 0;
+ }
+ }
+}
diff --git a/src/components/sq-overlay/sq-overlay.component.tsx b/src/components/sq-overlay/sq-overlay.component.tsx
new file mode 100644
index 0000000..229834b
--- /dev/null
+++ b/src/components/sq-overlay/sq-overlay.component.tsx
@@ -0,0 +1,253 @@
+import React, { PropsWithChildren, useEffect, useRef, useState } from 'react'
+
+import './sq-overlay.component.scoped.scss'
+import './sq-overlay.component.scss'
+
+export interface Props extends PropsWithChildren> {
+ open?: boolean
+ overlayClass?: string
+ backdrop?: 'static' | 'cliclable'
+ buttonClose?: boolean
+ header?: any
+ footer?: any
+ onCloseChange?: () => any | void
+ onOpenChange?: (open: boolean) => any | void
+ onLeftPress?: () => any | void
+ onRightPress?: () => any | void
+ width?: string
+ maxWidth?: string
+ headerColor?: string
+ footerColor?: string
+ bodyColor?: string
+ backdropColor?: string
+ borderless?: boolean
+ overlayDirection?: 'right' | 'left'
+ headerHeight?: string
+}
+
+export default ({
+ overlayClass = '',
+ className = '',
+ buttonClose = true,
+ backdrop = 'static',
+ children,
+ open = false,
+ header = null,
+ footer = null,
+ id = '',
+ onCloseChange,
+ onOpenChange,
+ onLeftPress,
+ onRightPress,
+ width = '475px',
+ maxWidth = '100vw',
+ headerColor = 'var(--background_secondary)',
+ footerColor = 'var(--background_secondary)',
+ bodyColor = 'var(--background_secondary)',
+ backdropColor = 'var(--background_secondary)',
+ borderless = false,
+ overlayDirection = 'right',
+ headerHeight = '52px',
+}: Props) => {
+ const modalRef = useRef(null)
+ const modals = useRef>(null)
+ const [enableBackdropClick, setEnableBackdropClick] = useState(false)
+ const [count, setCount] = useState(0)
+ const [finishOpening, setFinishOpening] = useState(false)
+
+ useEffect(() => {
+ return () => {
+ if (document.getElementById('modal-backdrop') && count === 0) {
+ document.getElementById('modal-backdrop')?.remove()
+ document.body.classList.remove('block')
+ }
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [])
+
+ useEffect(() => {
+ if (backdrop !== 'static' && modalRef.current && open && enableBackdropClick) {
+ document.addEventListener('click', backdropClick)
+ return () => {
+ window.removeEventListener('keydown', onKeydown)
+ document.removeEventListener('click', backdropClick)
+ }
+ }
+ //eslint-disable-next-line
+ }, [enableBackdropClick, open, backdrop])
+
+ useEffect(() => {
+ const css = `
+ .overlay.open .modal-dialog.opened {
+ width: ${width};
+ max-width: ${maxWidth};
+ }
+ `
+ const head = document.getElementsByTagName('head')[0]
+ const styleId = `${id || `random-id-${count}`}-style`
+ let style = document.getElementById(styleId)
+ if (!style) {
+ style = document.createElement('style')
+ style.setAttribute('id', styleId)
+ style.appendChild(document.createTextNode(css))
+ head.appendChild(style)
+ } else {
+ style.innerHTML = ''
+ style.appendChild(document.createTextNode(css))
+ }
+ return () => {
+ style.remove()
+ }
+ }, [width, maxWidth, count, id])
+
+ useEffect(() => {
+ const body = document.getElementsByTagName('body')[0]
+ const backdrop = document.getElementById('modal-backdrop') || document.createElement('div')
+ if (open && modalRef.current) {
+ body.classList.add('block')
+ // @ts-ignore
+ modals.current = document.getElementsByClassName('modal open')
+ setCount(modals.current?.length)
+ if (!document.getElementById('modal-backdrop')) {
+ modalRef.current.classList.remove('modal-over')
+ backdrop.setAttribute('id', 'modal-backdrop')
+ backdrop.setAttribute('class', 'modal-backdrop show')
+ body.appendChild(backdrop)
+ }
+ modalRef.current.style.display = 'flex'
+ setTimeout(() => {
+ setFinishOpening(true)
+ }, 100)
+ setEnableBackdropClick(true)
+ window.addEventListener('keydown', onKeydown)
+ } else if (modalRef.current) {
+ toCloseModal(body, backdrop)
+ }
+ return () => {
+ window.removeEventListener('keydown', onKeydown)
+ }
+ //eslint-disable-next-line
+ }, [open])
+
+ function toCloseModal(body: HTMLBodyElement, backdrop: HTMLElement) {
+ callOpenChange(false)
+ callCloseChange()
+ setFinishOpening(false)
+ setTimeout(() => {
+ if (modalRef?.current?.style?.display) {
+ modalRef.current.style.display = 'none'
+ }
+ }, 300)
+ if (backdrop.parentNode && modalRef.current?.tabIndex === 1) {
+ backdrop.parentNode.removeChild(backdrop)
+ body.classList.remove('block')
+ }
+ setEnableBackdropClick(false)
+ window.removeEventListener('keydown', onKeydown)
+ }
+
+ function backdropClick(event: any) {
+ if (backdrop === 'static' || !modalRef.current || !open || !enableBackdropClick) {
+ return
+ }
+ const modalDialog = modalRef.current.firstElementChild
+ if (!modalDialog?.contains(event.target)) {
+ const body = document.getElementsByTagName('body')[0]
+ const backdrop = document.getElementById('modal-backdrop') || document.createElement('div')
+ toCloseModal(body, backdrop)
+ }
+ }
+
+ function onKeydown(event: any) {
+ if (open) {
+ const contextModals = document.getElementsByClassName('modal open')
+ if (modalRef.current?.tabIndex === contextModals?.length) {
+ events(event.keyCode)
+ }
+ }
+ }
+
+ function callOpenChange(open: boolean) {
+ if (onOpenChange && typeof onOpenChange === 'function') {
+ onOpenChange(open)
+ }
+ }
+
+ function callCloseChange() {
+ if (onCloseChange && typeof onCloseChange === 'function') {
+ onCloseChange()
+ }
+ }
+
+ function callLeftPress() {
+ if (onLeftPress && typeof onLeftPress === 'function') {
+ onLeftPress()
+ }
+ }
+
+ function callRightPress() {
+ if (onRightPress && typeof onRightPress === 'function') {
+ onRightPress()
+ }
+ }
+
+ function events(key: number) {
+ switch (key) {
+ case 27:
+ callOpenChange(false)
+ callCloseChange()
+ break
+ case 37:
+ callLeftPress()
+ break
+ case 39:
+ callRightPress()
+ break
+ }
+ }
+
+ return (
+
+
+
+
+ {header}
+ {buttonClose ? (
+ callCloseChange()} className="button-close modal-exit">
+
+
+ ) : null}
+
+
+ {children}
+
+ {footer ? (
+
+ {footer}
+
+ ) : null}
+
+
+
+ )
+}
diff --git a/src/components/sq-timeline/__docs__/sq-timeline.component.example.tsx b/src/components/sq-timeline/__docs__/sq-timeline.component.example.tsx
new file mode 100644
index 0000000..005ce4c
--- /dev/null
+++ b/src/components/sq-timeline/__docs__/sq-timeline.component.example.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import SqTimeline, { Props } from '../sq-timeline.component'
+
+const SqTimelineExample = ({ children, ...props }: Props) => {
+ return (
+
+ {children}
+
+ )
+}
+
+export default SqTimelineExample
diff --git a/src/components/sq-timeline/__docs__/sq-timeline.component.stories.tsx b/src/components/sq-timeline/__docs__/sq-timeline.component.stories.tsx
new file mode 100644
index 0000000..ba475aa
--- /dev/null
+++ b/src/components/sq-timeline/__docs__/sq-timeline.component.stories.tsx
@@ -0,0 +1,36 @@
+import React from 'react'
+import { Meta, StoryObj } from '@storybook/react'
+import SqTimelineExample from './sq-timeline.component.example'
+import Timeline from '../sq-timeline.component'
+
+const meta: Meta = {
+ title: 'Components/SqTimeline',
+ parameters: {
+ docs: {
+ description: {
+ component: 'A simple Timeline component',
+ },
+ },
+ },
+ component: SqTimelineExample,
+ tags: ['autodocs'],
+}
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {
+ children: [
+
+ 2015-09-01
+ ,
+
+ 2015-09-01
+ ,
+
+ 2015-09-01
+ ,
+ ],
+ },
+}
diff --git a/src/components/sq-timeline/index.ts b/src/components/sq-timeline/index.ts
new file mode 100644
index 0000000..68d3aa1
--- /dev/null
+++ b/src/components/sq-timeline/index.ts
@@ -0,0 +1 @@
+export { default as SqTimeline } from './sq-timeline.component'
diff --git a/src/components/sq-timeline/sq-timeline.component.scoped.scss b/src/components/sq-timeline/sq-timeline.component.scoped.scss
new file mode 100644
index 0000000..dc96516
--- /dev/null
+++ b/src/components/sq-timeline/sq-timeline.component.scoped.scss
@@ -0,0 +1,42 @@
+.timeline {
+ padding-left: 1rem;
+ border-left: 1px solid var(--gray);
+ margin-left: 0.5rem;
+ min-height: -webkit-fill-available;
+
+ .item {
+ list-style: none;
+
+ position: relative;
+ left: -8px;
+ padding-left: 1rem;
+ top: -1rem;
+ margin-bottom: 1rem;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ .container-item {
+ position: relative;
+
+ .content-item {
+ * {
+ width: 100%;
+ }
+
+ position: relative;
+ }
+ }
+
+ .marker {
+ width: 10px;
+ height: 10px;
+ background-color: var(--gray);
+ position: absolute;
+ border-radius: 50%;
+ left: -11px;
+ top: 7px;
+ }
+ }
+}
diff --git a/src/components/sq-timeline/sq-timeline.component.tsx b/src/components/sq-timeline/sq-timeline.component.tsx
new file mode 100644
index 0000000..07810df
--- /dev/null
+++ b/src/components/sq-timeline/sq-timeline.component.tsx
@@ -0,0 +1,37 @@
+import { PropsWithChildren } from 'react'
+
+import './sq-timeline.component.scoped.scss'
+
+export interface Props extends React.HTMLAttributes, PropsWithChildren {
+ items?: Array
+ children?: React.ReactNode
+}
+
+const Timeline = ({ items, children, ...rest }: Props) => {
+ return (
+
+ {items?.length ? items?.map((item, index) => - {item}
) : children}
+
+ )
+}
+
+interface ItemProps extends React.HTMLAttributes {
+ children: React.ReactNode
+}
+
+const Item = ({ children, ...props }: ItemProps) => {
+ return (
+
+
+
+
+ )
+}
+
+Timeline.Item = Item
+
+export default Timeline
diff --git a/src/components/sq-tiny-calendar/__docs__/sq-tiny-calendar.component.example.tsx b/src/components/sq-tiny-calendar/__docs__/sq-tiny-calendar.component.example.tsx
new file mode 100644
index 0000000..cc0b4ec
--- /dev/null
+++ b/src/components/sq-tiny-calendar/__docs__/sq-tiny-calendar.component.example.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import SqTinyCalendar, { Props } from '../sq-tiny-calendar.component'
+
+const SqTinyCalendarExample = (props: Props) => {
+ return (
+
+
+
+ )
+}
+
+export default SqTinyCalendarExample
diff --git a/src/components/sq-tiny-calendar/__docs__/sq-tiny-calendar.component.stories.tsx b/src/components/sq-tiny-calendar/__docs__/sq-tiny-calendar.component.stories.tsx
new file mode 100644
index 0000000..b4f6cca
--- /dev/null
+++ b/src/components/sq-tiny-calendar/__docs__/sq-tiny-calendar.component.stories.tsx
@@ -0,0 +1,33 @@
+import React from 'react'
+import { Meta, StoryObj } from '@storybook/react'
+import SqTinyCalendarExample from './sq-tiny-calendar.component.example'
+import SqTinyCalendar from '../sq-tiny-calendar.component'
+
+const meta: Meta = {
+ title: 'Components/SqTinyCalendar',
+ parameters: {
+ docs: {
+ description: {
+ component: 'A simple TinyCalendar component',
+ },
+ },
+ },
+ component: SqTinyCalendarExample,
+ tags: ['autodocs'],
+}
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {
+ dateString: new Date().toISOString(),
+ children: (
+
+
+
+
+
+ ),
+ },
+}
diff --git a/src/components/sq-tiny-calendar/index.ts b/src/components/sq-tiny-calendar/index.ts
new file mode 100644
index 0000000..aea4367
--- /dev/null
+++ b/src/components/sq-tiny-calendar/index.ts
@@ -0,0 +1 @@
+export { default as SqTinyCalendar } from './sq-tiny-calendar.component'
diff --git a/src/components/sq-tiny-calendar/sq-tiny-calendar.component.md b/src/components/sq-tiny-calendar/sq-tiny-calendar.component.md
new file mode 100644
index 0000000..d842f1f
--- /dev/null
+++ b/src/components/sq-tiny-calendar/sq-tiny-calendar.component.md
@@ -0,0 +1,18 @@
+# TinyCalendar Component
+
+## Props
+
+### 1. dateString
+
+- description: date in string format
+- type: `string`
+
+## Example
+
+```jsx
+
+
+
+
+
+```
diff --git a/src/components/sq-tiny-calendar/sq-tiny-calendar.component.scoped.scss b/src/components/sq-tiny-calendar/sq-tiny-calendar.component.scoped.scss
new file mode 100644
index 0000000..78bc83b
--- /dev/null
+++ b/src/components/sq-tiny-calendar/sq-tiny-calendar.component.scoped.scss
@@ -0,0 +1,32 @@
+.tiny-calendar {
+ flex-shrink: 0;
+
+ .card-tiny-calendar {
+ max-width: 38px;
+ width: 100%;
+ border: 1px solid var(--border_color);
+ text-align: center;
+ min-width: 80px;
+ align-items: center;
+ text-align: center;
+ box-shadow: var(--box_shadow);
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ color: var(--gray);
+
+ span {
+ font-size: 0.86rem;
+ text-transform: uppercase;
+ }
+
+ .text-big {
+ font-size: 1.7rem;
+ font-weight: bold;
+ letter-spacing: 0.1rem;
+ margin: -6px 0;
+ color: var(--text_color);
+ }
+ }
+}
diff --git a/src/components/sq-tiny-calendar/sq-tiny-calendar.component.tsx b/src/components/sq-tiny-calendar/sq-tiny-calendar.component.tsx
new file mode 100644
index 0000000..5219a9d
--- /dev/null
+++ b/src/components/sq-tiny-calendar/sq-tiny-calendar.component.tsx
@@ -0,0 +1,63 @@
+import { HTMLAttributes, createContext, useEffect, useRef, useState } from 'react'
+import { Subscription } from 'rxjs'
+
+import './sq-tiny-calendar.component.scoped.scss'
+import { onLangChange } from '@/src/observables'
+import i18n from '@/src/i18n'
+
+export interface Props extends React.PropsWithChildren> {
+ dateString: string
+}
+
+const TinyCalendarContext = createContext({})
+
+const TinyCalendar = ({ children, className = '', id = '', dateString, ...props }: Props) => {
+ const [dayWeek, setDayWeek] = useState('')
+ const [day, setDay] = useState(0)
+ const [month, setMonth] = useState('')
+ const [year, setYear] = useState(0)
+
+ useEffect(() => {
+ const dateInUTC = new Date(dateString).toLocaleDateString('en', { timeZone: 'UTC' })
+ const dateObj = new Date(dateInUTC)
+
+ const month = dateObj.toLocaleString(i18n?.language, { month: 'short' })
+ const weekday = dateObj.toLocaleString(i18n?.language, { weekday: 'short' })
+ setDay(dateObj.getDate())
+ setMonth(month.replace('.', ''))
+ setDayWeek(weekday.replace('.', ''))
+ setYear(dateObj.getFullYear())
+ }, [dateString])
+
+ return (
+
+
+
+ )
+}
+
+type ChildProps = HTMLAttributes
+
+const Day = ({ ...props }: ChildProps) => (
+ {({ day }) => {day}
}
+)
+const DayWeek = ({ ...props }: ChildProps) => (
+ {({ dayWeek }) => {dayWeek}
}
+)
+const Month = ({ ...props }: ChildProps) => (
+ {({ month }) => {month}
}
+)
+const Year = ({ ...props }: ChildProps) => (
+ {({ year }) => {year}
}
+)
+
+TinyCalendar.Day = Day
+TinyCalendar.DayWeek = DayWeek
+TinyCalendar.Month = Month
+TinyCalendar.Year = Year
+
+export default TinyCalendar
diff --git a/src/components/sq-tip/__docs__/sq-tip.component.example.tsx b/src/components/sq-tip/__docs__/sq-tip.component.example.tsx
new file mode 100644
index 0000000..57177aa
--- /dev/null
+++ b/src/components/sq-tip/__docs__/sq-tip.component.example.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import SqTip, { Props } from '../sq-tip.component'
+
+const SqTipExample = (props: Props) => {
+ return (
+
+
+
+ )
+}
+
+export default SqTipExample
diff --git a/src/components/sq-tip/__docs__/sq-tip.component.stories.tsx b/src/components/sq-tip/__docs__/sq-tip.component.stories.tsx
new file mode 100644
index 0000000..d20fb04
--- /dev/null
+++ b/src/components/sq-tip/__docs__/sq-tip.component.stories.tsx
@@ -0,0 +1,24 @@
+import { Meta, StoryObj } from '@storybook/react'
+import SqTipExample from './sq-tip.component.example'
+
+const meta: Meta = {
+ title: 'Components/SqTip',
+ parameters: {
+ docs: {
+ description: {
+ component: 'A simple Tip component',
+ },
+ },
+ },
+ component: SqTipExample,
+ tags: ['autodocs'],
+}
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {
+ message: 'This is a tip',
+ },
+}
diff --git a/src/components/sq-tip/index.ts b/src/components/sq-tip/index.ts
new file mode 100644
index 0000000..d5aeb5f
--- /dev/null
+++ b/src/components/sq-tip/index.ts
@@ -0,0 +1 @@
+export { default as SqTip } from './sq-tip.component'
diff --git a/src/components/sq-tip/sq-tip.component.md b/src/components/sq-tip/sq-tip.component.md
new file mode 100644
index 0000000..474c5a2
--- /dev/null
+++ b/src/components/sq-tip/sq-tip.component.md
@@ -0,0 +1,46 @@
+# Tip
+
+We use to do this tooltip
+
+## Props
+
+### 1. message
+
+- description: Tip message
+- type: `string`
+
+### 2. place
+
+- description: Tooltip position
+- type: `'top' | 'right' | 'left' | 'bottom'`
+
+### 3. theme
+
+- description: Tooltip theme
+- type: `light' | 'dark'`
+
+### 4. trigger
+
+- description: Tooltip trigger
+- type: `'hover' | 'click'`
+
+### 5. icon
+
+- description: FontAwesome Icon
+- type: `IconName`
+
+### 6. id
+
+- description: Tooltip ID
+- type: `string`
+
+### 7. fontSize
+
+- description: Icon fontSize
+- type: `string`
+
+## Exemple
+
+```html
+
+```
diff --git a/src/components/sq-tip/sq-tip.component.scoped.scss b/src/components/sq-tip/sq-tip.component.scoped.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/sq-tip/sq-tip.component.scss b/src/components/sq-tip/sq-tip.component.scss
new file mode 100644
index 0000000..50383ad
--- /dev/null
+++ b/src/components/sq-tip/sq-tip.component.scss
@@ -0,0 +1,8 @@
+.tip-class {
+ max-width: 500px;
+ opacity: 1 !important;
+
+ @media (max-width: 500px) {
+ max-width: 300px;
+ }
+}
diff --git a/src/components/sq-tip/sq-tip.component.test.tsx b/src/components/sq-tip/sq-tip.component.test.tsx
new file mode 100644
index 0000000..40b9b72
--- /dev/null
+++ b/src/components/sq-tip/sq-tip.component.test.tsx
@@ -0,0 +1,24 @@
+import SqTip from '@/src/components/sq-tip/sq-tip.component'
+import { render, waitFor, screen } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import { describe, expect, it } from 'vitest'
+
+describe('Tip Component', () => {
+ const tipComponent =
+ it('should render without errors', () => {
+ const { container } = render(tipComponent)
+ const tip = container.querySelector('i')
+ expect(tip).toHaveClass('fa-circle-info')
+ })
+
+ it('should render the message', async () => {
+ const { container } = render(tipComponent)
+ const tip: any = container.querySelector('i')
+ await userEvent.hover(tip)
+ const tipMessage = screen.getByText(/hello/)
+ await waitFor(() => {
+ expect(tipMessage).toBeInTheDocument()
+ expect(tipMessage).toHaveTextContent('hello')
+ })
+ })
+})
diff --git a/src/components/sq-tip/sq-tip.component.tsx b/src/components/sq-tip/sq-tip.component.tsx
new file mode 100644
index 0000000..123b51e
--- /dev/null
+++ b/src/components/sq-tip/sq-tip.component.tsx
@@ -0,0 +1,65 @@
+import React from 'react'
+import { Tooltip } from 'react-tooltip'
+import './sq-tip.component.scoped.scss'
+import './sq-tip.component.scss'
+
+export interface Props extends React.HTMLAttributes {
+ message?: string
+ place?: 'top' | 'right' | 'left' | 'bottom'
+ theme?: 'light' | 'dark'
+ trigger?: 'hover' | 'click'
+ icon?: string
+ fontSize?: string
+ id?: string
+}
+
+export default ({
+ className = '',
+ message = '',
+ place = 'top',
+ trigger = 'hover',
+ icon = 'fa-solid fa-circle-info',
+ id,
+ fontSize = '16px',
+}: Props) => {
+ const timestamp = `random-id-${(1 + Date.now() + Math.random()).toString().replace('.', '')}`
+ const watcher = React.useRef(null)
+ const [theme, setTheme] = React.useState<'light' | 'dark'>('light')
+
+ React.useEffect(() => {
+ watcher.current = new MutationObserver((mutations) => {
+ mutations.forEach((mu) => {
+ if (mu.type !== 'attributes' && mu.attributeName !== 'class') return
+ applyTheme()
+ })
+ })
+ const html = document.getElementsByTagName('html')[0]
+ watcher.current.observe(html, { attributes: true })
+
+ applyTheme()
+ })
+
+ const applyTheme = () => {
+ const html = document.getElementsByTagName('html')[0]
+ if (html?.classList.contains('dark')) {
+ setTheme('light')
+ } else {
+ setTheme('dark')
+ }
+ }
+
+ return (
+
+
+
+
+
+ )
+}
diff --git a/src/helpers/index.ts b/src/helpers/index.ts
index 9b06fba..1b00755 100644
--- a/src/helpers/index.ts
+++ b/src/helpers/index.ts
@@ -5,3 +5,6 @@ export * from './sq-strings/sq-strings.helper'
export * from './sq-validator/sq-validator.helper'
export * from './sq-toast/sq-toast.helper'
export * from './sq-jwt/sq-jwt.helper'
+export * from './sq-color-icon/sq-color-icon.helper'
+export * from './sq-data/sq-data.helper'
+export * from './sq-event-emitter/sq-event-emitter.helper'
diff --git a/src/helpers/sq-color-icon/sq-color-icon.helper.md b/src/helpers/sq-color-icon/sq-color-icon.helper.md
new file mode 100644
index 0000000..0b10052
--- /dev/null
+++ b/src/helpers/sq-color-icon/sq-color-icon.helper.md
@@ -0,0 +1,41 @@
+# ColorIconHelper
+
+A utility class for handling color and icon settings.
+
+## Description
+
+`ColorIconHelper` is a utility class that provides methods for setting icons and colors.
+
+## Methods
+
+### `setIcon(icon?: string): string`
+
+Sets the icon based on a provided string.
+
+- `icon` (optional): The name of the icon.
+- Returns: The set icon or the provided string.
+
+### `setColor(color?: string): string`
+
+Sets the color based on a provided string.
+
+- `color` (optional): The color to be set.
+- Returns: The set color or the provided string.
+
+## Example Usage
+
+```typescript
+import ColorIconHelper from './ColorIconHelper'; // Assuming the class is in a file named ColorIconHelper.js
+
+// Create an instance of ColorIconHelper
+const colorIconHelper = new ColorIconHelper();
+
+// Set the icon for Twitter
+const twitterIcon = colorIconHelper.setIcon('twitter');
+
+// Set the color for Twitter
+const twitterColor = colorIconHelper.setColor('twitter');
+
+console.log('Twitter Icon:', twitterIcon); // Output: 'x'
+console.log('Twitter Color:', twitterColor); // Output: 'x'
+```
diff --git a/src/helpers/sq-color-icon/sq-color-icon.helper.mdx b/src/helpers/sq-color-icon/sq-color-icon.helper.mdx
new file mode 100644
index 0000000..a26b799
--- /dev/null
+++ b/src/helpers/sq-color-icon/sq-color-icon.helper.mdx
@@ -0,0 +1,8 @@
+import { Markdown, Meta } from '@storybook/blocks'
+import SqColorIconDoc from './sq-color-icon.helper.md?raw'
+
+
+
+
+ {SqColorIconDoc}
+
diff --git a/src/helpers/sq-color-icon/sq-color-icon.helper.ts b/src/helpers/sq-color-icon/sq-color-icon.helper.ts
new file mode 100644
index 0000000..f93fce1
--- /dev/null
+++ b/src/helpers/sq-color-icon/sq-color-icon.helper.ts
@@ -0,0 +1,15 @@
+export default class SqColorIconHelper {
+ setIcon(icon?: string) {
+ if (icon === 'twitter') {
+ return 'x'
+ }
+ return icon
+ }
+
+ setColor(color?: string) {
+ if (color === 'twitter') {
+ return 'x'
+ }
+ return color
+ }
+}
diff --git a/src/helpers/sq-colors/sq-colors.helper.stories.mdx b/src/helpers/sq-colors/sq-colors.helper.mdx
similarity index 79%
rename from src/helpers/sq-colors/sq-colors.helper.stories.mdx
rename to src/helpers/sq-colors/sq-colors.helper.mdx
index 8c43b6f..f5a3d62 100644
--- a/src/helpers/sq-colors/sq-colors.helper.stories.mdx
+++ b/src/helpers/sq-colors/sq-colors.helper.mdx
@@ -3,5 +3,6 @@ import SqColorDoc from './sq-colors.helper.md?raw'
-{SqColorDoc}
-
+
+ {SqColorDoc}
+
diff --git a/src/helpers/sq-data/sq-data.helper.md b/src/helpers/sq-data/sq-data.helper.md
new file mode 100644
index 0000000..874637f
--- /dev/null
+++ b/src/helpers/sq-data/sq-data.helper.md
@@ -0,0 +1,86 @@
+# DataHelper
+
+A utility class for handling date, phone number, and time-related operations.
+
+## Description
+
+`DataHelper` is a utility class that provides methods for formatting dates, phone numbers, calculating age, and formatting time-related texts.
+
+## Methods
+
+### `formatDate(date: string): string`
+
+Formats a date string into the "dd-MM-yyyy" format.
+
+- `date`: The date string to format.
+- Returns: The formatted date string.
+
+### `formatPhoneNumber(phoneNumber: string): string`
+
+Formats a phone number into a Brazilian phone number format.
+
+- `phoneNumber`: The phone number string to format.
+- Returns: The formatted phone number string.
+
+### `calcAge(year: number, month: number, day: number): number`
+
+Calculates the age based on the provided birth year, month, and day.
+
+- `year`: The birth year.
+- `month`: The birth month (1-based index).
+- `day`: The birth day of the month.
+- Returns: The calculated age as a number.
+
+### `formatTimeText(seconds: number, periodSeconds: number, period: string): string`
+
+Formats a time-related text based on the provided seconds, period seconds, and period name.
+
+- `seconds`: The total seconds.
+- `periodSeconds`: The duration of the period in seconds.
+- `period`: The name of the period (e.g., "year", "month", "day", "hour").
+- Returns: The formatted time-related text string.
+
+### `formatTimeFormatAgo(date: string): string`
+
+Formats a date string into a relative time format (e.g., "today", "1 year ago", "3 months ago").
+
+- `date`: The date string to format.
+- Returns: The formatted relative time string.
+
+## Example Usage
+
+```typescript
+import DataHelper from './DataHelper'; // Assuming the class is in a file named DataHelper.js
+
+// Create an instance of DataHelper
+const dataHelper = new DataHelper();
+
+// Format a date
+const dateString = '2024-05-08';
+const formattedDate = dataHelper.formatDate(dateString);
+console.log('Formatted Date:', formattedDate);
+
+// Format a phone number
+const phoneNumber = '+551234567890';
+const formattedPhoneNumber = dataHelper.formatPhoneNumber(phoneNumber);
+console.log('Formatted Phone Number:', formattedPhoneNumber);
+
+// Calculate age
+const birthYear = 1990;
+const birthMonth = 1; // January
+const birthDay = 1;
+const age = dataHelper.calcAge(birthYear, birthMonth, birthDay);
+console.log('Age:', age);
+
+// Format time text
+const seconds = 3600;
+const periodSeconds = 3600;
+const period = 'hour';
+const formattedTimeText = dataHelper.formatTimeText(seconds, periodSeconds, period);
+console.log('Formatted Time Text:', formattedTimeText);
+
+// Format time format ago
+const dateAgoString = '2024-05-07T12:00:00Z';
+const formattedTimeAgo = dataHelper.formatTimeFormatAgo(dateAgoString);
+console.log('Formatted Time Ago:', formattedTimeAgo);
+```
diff --git a/src/helpers/sq-data/sq-data.helper.mdx b/src/helpers/sq-data/sq-data.helper.mdx
new file mode 100644
index 0000000..854a7f7
--- /dev/null
+++ b/src/helpers/sq-data/sq-data.helper.mdx
@@ -0,0 +1,8 @@
+import { Markdown, Meta, Canvas } from '@storybook/blocks'
+import SqDataDoc from './sq-data.helper.md?raw'
+
+
+
+
+ {SqDataDoc}
+
diff --git a/src/helpers/sq-data/sq-data.helper.ts b/src/helpers/sq-data/sq-data.helper.ts
new file mode 100644
index 0000000..47962be
--- /dev/null
+++ b/src/helpers/sq-data/sq-data.helper.ts
@@ -0,0 +1,97 @@
+import i18next from 'i18next'
+
+export default class DataHelper {
+ formatDate(date: string) {
+ try {
+ return new Date(date).toLocaleDateString('pt-br').split('/').reverse().join('-')
+ } catch (e) {
+ return ''
+ }
+ }
+
+ formatPhoneNumber(phoneNumber: string): string | undefined {
+ if (phoneNumber) {
+ const brazilDDI = '+55'
+ const ninePrefix = '9'
+ const hasBrazilDDI = `+${phoneNumber}`.slice(0, 3) === brazilDDI
+ const hasNineDigits = phoneNumber.slice(4).length === 9
+ const hasNinePrefix = phoneNumber.slice(4, 5) === ninePrefix
+
+ if (hasBrazilDDI) {
+ if (hasNinePrefix && hasNineDigits) {
+ return `${brazilDDI} (${phoneNumber.slice(2, 4)}) ${phoneNumber.slice(4, 9)}-${phoneNumber.slice(9, 14)}`
+ } else {
+ return `${brazilDDI} (${phoneNumber.slice(2, 4)}) ${phoneNumber.slice(4, 8)}-${phoneNumber.slice(8, 13)}`
+ }
+ } else {
+ return phoneNumber
+ }
+ }
+ }
+
+ calcAge(year: number, month: number, day: number) {
+ const date = new Date()
+
+ const thisYear = date.getFullYear()
+ const thisMont = date.getMonth() + 1
+ const thisDay = date.getDate()
+
+ year = +year
+ month = +month
+ day = +day
+
+ let age = thisYear - year
+
+ if (thisMont < month || (thisMont == month && thisDay < day)) {
+ age--
+ }
+
+ return age < 0 ? 0 : age
+ }
+
+ formatTimeText(seconds: number, periodSeconds: number, period: string) {
+ const interval = seconds / periodSeconds
+ if (interval > 1) {
+ const intervalRound = Math.floor(interval)
+ return i18next.t(`globals:${period}`, { value: intervalRound, count: intervalRound })
+ }
+ return ''
+ }
+
+ formatTimeFormatAgo(date: string) {
+ const today = new Date()
+ const newDate = new Date(date)
+ const seconds = (today.getTime() - newDate.getTime()) / 1000
+
+ const periods = [
+ {
+ period: 'year',
+ value: 31536000,
+ },
+ {
+ period: 'month',
+ value: 2592000,
+ },
+ {
+ period: 'day',
+ value: 86400,
+ },
+ {
+ period: 'hour',
+ value: 3600,
+ },
+ ]
+
+ if (today.getDate() === newDate.getDate()) {
+ return i18next.t('globals:today')
+ }
+
+ let timeText = ''
+ periods.forEach((element) => {
+ if (!timeText) {
+ timeText = this.formatTimeText(seconds, element.value, element.period)
+ }
+ })
+ return timeText
+ }
+}
diff --git a/src/helpers/sq-event-emitter/sq-event-emitter.helper.md b/src/helpers/sq-event-emitter/sq-event-emitter.helper.md
new file mode 100644
index 0000000..2c96e75
--- /dev/null
+++ b/src/helpers/sq-event-emitter/sq-event-emitter.helper.md
@@ -0,0 +1,68 @@
+# SqEventEmitter
+
+A utility class for event handling using EventEmitter pattern.
+
+## Description
+
+`Emitter` provides methods for registering event listeners, emitting events, and removing event listeners.
+
+## Methods
+
+### `on(event: any, fn: any): void`
+
+Registers an event listener for the specified event.
+
+- `event`: The event to listen for.
+- `fn`: The callback function to be invoked when the event is emitted.
+
+### `once(event: any, fn: any): void`
+
+Registers an event listener that will be called at most once for a particular event.
+
+- `event`: The event to listen for.
+- `fn`: The callback function to be invoked when the event is emitted.
+
+### `off(event: any, fn?: any): void`
+
+Removes the specified event listener or all listeners for the specified event.
+
+- `event`: The event to remove listeners from.
+- `fn`: (Optional) The specific listener function to remove. If not provided, removes all listeners for the event.
+
+### `emit(event: any, payload: any): void`
+
+Emits the specified event with an optional payload.
+
+- `event`: The event to emit.
+- `payload`: (Optional) The data to pass to event listeners.
+
+## Example Usage
+
+```javascript
+import Emitter from './Emitter'; // Assuming the class is in a file named Emitter.js
+
+// Emit event inside a component:
+Emitter.emit('hover', hover);
+
+// To listen on every change:
+componentDidMount() {
+ Emitter.on('hover', (hover) => {
+ // Your code here
+ });
+}
+
+componentWillUnmount() {
+ Emitter.off('hover');
+}
+
+// To listen once:
+componentDidMount() {
+ Emitter.once('hover', (hover) => {
+ // Your code here
+ });
+}
+
+componentWillUnmount() {
+ Emitter.off('hover');
+}
+```
\ No newline at end of file
diff --git a/src/helpers/sq-event-emitter/sq-event-emitter.helper.mdx b/src/helpers/sq-event-emitter/sq-event-emitter.helper.mdx
new file mode 100644
index 0000000..9ae53d5
--- /dev/null
+++ b/src/helpers/sq-event-emitter/sq-event-emitter.helper.mdx
@@ -0,0 +1,8 @@
+import { Markdown, Meta, Canvas } from '@storybook/blocks'
+import SqEventEmitterDoc from './sq-event-emitter.helper.md?raw'
+
+
+
+
+ {SqEventEmitterDoc}
+
diff --git a/src/helpers/sq-event-emitter/sq-event-emitter.helper.ts b/src/helpers/sq-event-emitter/sq-event-emitter.helper.ts
new file mode 100644
index 0000000..d34ab6c
--- /dev/null
+++ b/src/helpers/sq-event-emitter/sq-event-emitter.helper.ts
@@ -0,0 +1,38 @@
+import EventEmitter from 'eventemitter3'
+
+const eventEmitter = new EventEmitter()
+
+const Emitter = {
+ on: (event: any, fn: any) => eventEmitter.on(event, fn),
+ once: (event: any, fn: any) => eventEmitter.once(event, fn),
+ off: (event: any, fn: any) => eventEmitter.off(event, fn),
+ emit: (event: any, payload: any) => eventEmitter.emit(event, payload),
+}
+
+Object.freeze(Emitter)
+
+export default Emitter
+
+/*
+ Usage on a component:
+ - Emit event insite the component:
+ Emitter.emit('hover', hover)
+
+ - To listen on every change
+ componentDidMount() {
+ Emitter.on('hover', (hover) => // your code here)
+ }
+
+ componentWillUnmount() {
+ Emitter.off('hover')
+ }
+
+ - To listen once:
+ componentDidMount() {
+ Emitter.once('hover', (hover) => // your code here)
+ }
+
+ componentWillUnmount() {
+ Emitter.off('hover')
+ }
+*/
diff --git a/src/helpers/sq-jwt/sq-jwt.helper.stories.mdx b/src/helpers/sq-jwt/sq-jwt.helper.mdx
similarity index 78%
rename from src/helpers/sq-jwt/sq-jwt.helper.stories.mdx
rename to src/helpers/sq-jwt/sq-jwt.helper.mdx
index 05c5569..06f0b60 100644
--- a/src/helpers/sq-jwt/sq-jwt.helper.stories.mdx
+++ b/src/helpers/sq-jwt/sq-jwt.helper.mdx
@@ -3,4 +3,6 @@ import SqJWTDoc from './sq-jwt.helper.md?raw'
-{SqJWTDoc}
+
+ {SqJWTDoc}
+
diff --git a/src/helpers/sq-numbers/sq-number.helper.stories.mdx b/src/helpers/sq-numbers/sq-number.helper.mdx
similarity index 76%
rename from src/helpers/sq-numbers/sq-number.helper.stories.mdx
rename to src/helpers/sq-numbers/sq-number.helper.mdx
index 996095f..b172f2b 100644
--- a/src/helpers/sq-numbers/sq-number.helper.stories.mdx
+++ b/src/helpers/sq-numbers/sq-number.helper.mdx
@@ -3,4 +3,6 @@ import SqNumbersHelperDoc from './sq-numbers.helper.md?raw'
-{SqNumbersHelperDoc}
+
+ {SqNumbersHelperDoc}
+
diff --git a/src/helpers/sq-object/sq-object.helper.stories.mdx b/src/helpers/sq-object/sq-object.helper.mdx
similarity index 76%
rename from src/helpers/sq-object/sq-object.helper.stories.mdx
rename to src/helpers/sq-object/sq-object.helper.mdx
index 5701753..ef55fe7 100644
--- a/src/helpers/sq-object/sq-object.helper.stories.mdx
+++ b/src/helpers/sq-object/sq-object.helper.mdx
@@ -3,4 +3,6 @@ import SqObjectHelperDoc from './sq-object.helper.md?raw'
-{SqObjectHelperDoc}
+
+ {SqObjectHelperDoc}
+
diff --git a/src/helpers/sq-strings/sq-strings.helper.stories.mdx b/src/helpers/sq-strings/sq-strings.helper.mdx
similarity index 76%
rename from src/helpers/sq-strings/sq-strings.helper.stories.mdx
rename to src/helpers/sq-strings/sq-strings.helper.mdx
index 7b0a269..b82c729 100644
--- a/src/helpers/sq-strings/sq-strings.helper.stories.mdx
+++ b/src/helpers/sq-strings/sq-strings.helper.mdx
@@ -3,4 +3,6 @@ import SqStringsHelperDoc from './sq-strings.helper.md?raw'
-{SqStringsHelperDoc}
+
+ {SqStringsHelperDoc}
+
diff --git a/src/helpers/sq-toast/sq-toast.helmper.stories.mdx b/src/helpers/sq-toast/sq-toast.helmper.mdx
similarity index 76%
rename from src/helpers/sq-toast/sq-toast.helmper.stories.mdx
rename to src/helpers/sq-toast/sq-toast.helmper.mdx
index 782d80b..4da43b8 100644
--- a/src/helpers/sq-toast/sq-toast.helmper.stories.mdx
+++ b/src/helpers/sq-toast/sq-toast.helmper.mdx
@@ -3,4 +3,6 @@ import SqToastHelperDoc from './sq-toast.helper.md?raw'
-{SqToastHelperDoc}
+
+ {SqToastHelperDoc}
+
diff --git a/src/helpers/sq-validator/sq-validator.helper.stories.mdx b/src/helpers/sq-validator/sq-validator.helper.mdx
similarity index 77%
rename from src/helpers/sq-validator/sq-validator.helper.stories.mdx
rename to src/helpers/sq-validator/sq-validator.helper.mdx
index c228132..931c460 100644
--- a/src/helpers/sq-validator/sq-validator.helper.stories.mdx
+++ b/src/helpers/sq-validator/sq-validator.helper.mdx
@@ -3,4 +3,6 @@ import SqValidatorDoc from './sq-validator.helper.md?raw'
-{SqValidatorDoc}
+
+ {SqValidatorDoc}
+
diff --git a/src/hooks/use-sq-image-loader/index.ts b/src/hooks/use-sq-image-loader/index.ts
deleted file mode 100644
index 2721a80..0000000
--- a/src/hooks/use-sq-image-loader/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { default as useSqImageLoader } from './use-sq-image-loader.hook'
diff --git a/src/hooks/use-sq-image-loader/use-image-loader.stories.tsx b/src/hooks/use-sq-image-loader/use-image-loader.stories.tsx
deleted file mode 100644
index e3f600f..0000000
--- a/src/hooks/use-sq-image-loader/use-image-loader.stories.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import useImageLoader from './use-sq-image-loader.hook'
-import SqLoader from '../../components/sq-loader/sq-loader.component'
-
-export const Overview = () => {
- const [ref, loading, onLoad] = useImageLoader()
-
- if (loading) {
- return
- }
-
- return
-}
-
-export default { title: 'Hooks/useSqImageLoader', tags: ['autodocs'] }
diff --git a/src/hooks/use-sq-image-loader/use-sq-image-loader.hook.tsx b/src/hooks/use-sq-image-loader/use-sq-image-loader.hook.tsx
deleted file mode 100644
index ce4cab5..0000000
--- a/src/hooks/use-sq-image-loader/use-sq-image-loader.hook.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { useRef, useState } from 'react'
-
-export default () => {
- const [loading, setLoading] = useState(true)
- const ref = useRef(null) as any
-
- const onLoad = () => {
- if (ref.current?.complete) {
- setLoading(false)
- }
- }
-
- return [ref, loading, onLoad]
-}
diff --git a/src/hooks/use-sq-metric-chart/use-sq-metric-chart.hook.stories.tsx b/src/hooks/use-sq-metric-chart/use-sq-metric-chart.hook.stories.tsx
new file mode 100644
index 0000000..f69b684
--- /dev/null
+++ b/src/hooks/use-sq-metric-chart/use-sq-metric-chart.hook.stories.tsx
@@ -0,0 +1,44 @@
+import useSqMetricChart, { MetricChartProps } from './use-sq-metric-chart.hook'
+import { Meta, StoryObj } from '@storybook/react'
+import { useEffect } from 'react'
+
+const Overview = (props: MetricChartProps) => {
+ const { state, setState } = useSqMetricChart(props)
+
+ useEffect(() => {
+ setState(props)
+ }, [props, setState])
+
+ return (
+
+
metric: {JSON.stringify(state.metric, null, 2)}
+
percentage: {JSON.stringify(state.percentage, null, 2)}
+
+ )
+}
+
+const meta: Meta = {
+ title: 'Hooks/useSqMetricChart',
+ component: Overview,
+ parameters: {
+ controls: { expanded: true },
+ },
+}
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {
+ metric: {
+ user: 50,
+ first: 100,
+ influencersAverage: 30,
+ position: {
+ ranking: 50,
+ total: 100,
+ },
+ },
+ percentage: true,
+ },
+}
diff --git a/src/hooks/use-sq-metric-chart/use-sq-metric-chart.hook.tsx b/src/hooks/use-sq-metric-chart/use-sq-metric-chart.hook.tsx
index 8e1cb31..61afbc0 100644
--- a/src/hooks/use-sq-metric-chart/use-sq-metric-chart.hook.tsx
+++ b/src/hooks/use-sq-metric-chart/use-sq-metric-chart.hook.tsx
@@ -1,8 +1,8 @@
import { useState } from 'react'
-import SqMetricsDetails from '@interfaces/sq-metrics.interface'
+import { MetricsDetails } from '@interfaces/sq-metrics.interface'
export interface MetricChartProps {
- metric: SqMetricsDetails
+ metric: MetricsDetails
percentage?: boolean
}
diff --git a/src/hooks/use-sq-rect/use-sq-rect.hook.stories.tsx b/src/hooks/use-sq-rect/use-sq-rect.hook.stories.tsx
index bc7e44d..4d45f7a 100644
--- a/src/hooks/use-sq-rect/use-sq-rect.hook.stories.tsx
+++ b/src/hooks/use-sq-rect/use-sq-rect.hook.stories.tsx
@@ -1,9 +1,14 @@
import { useRef } from 'react'
import useRect from './use-sq-rect.hook'
+import { Meta, StoryObj } from '@storybook/react'
-export const Overview = () => {
+interface Props {
+ refContainer: React.RefObject
+}
+
+const Overview = ({ refContainer }: Props) => {
const containerRef = useRef(null)
- const dimensions = useRect(containerRef)
+ const dimensions = useRect(refContainer)
return (
@@ -12,4 +17,19 @@ export const Overview = () => {
)
}
-export default { title: 'Hooks/useSqRect', tags: ['autodocs'] }
+const meta: Meta = {
+ title: 'Hooks/useSqRect',
+ component: Overview,
+ parameters: {
+ controls: { expanded: true },
+ },
+}
+
+export default meta
+type Story = StoryObj
+
+export const Default: Story = {
+ args: {
+ refContainer: { current: null },
+ },
+}
diff --git a/src/hooks/use-sq-throttle/use-sq-throttle.hook.stories.tsx b/src/hooks/use-sq-throttle/use-sq-throttle.hook.stories.tsx
index 26cce8d..eda71b2 100644
--- a/src/hooks/use-sq-throttle/use-sq-throttle.hook.stories.tsx
+++ b/src/hooks/use-sq-throttle/use-sq-throttle.hook.stories.tsx
@@ -1,6 +1,6 @@
import { useState } from 'react'
import useThrottle from './use-sq-throttle.hook'
-import { SqButton } from '@components/sq-button'
+import { SqButton } from '@/src/components/buttons/sq-button'
export const Overview = () => {
const [count, setCount] = useState(0)
diff --git a/src/i18n.ts b/src/i18n.ts
index 5f44564..c939c53 100644
--- a/src/i18n.ts
+++ b/src/i18n.ts
@@ -25,6 +25,30 @@ import esGlobals from '@assets/locales/es.json'
import ptSqMetricChart from '@components/sq-metric-chart/locales/pt.json'
import enSqMetricChart from '@components/sq-metric-chart/locales/en.json'
import esSqMetricChart from '@components/sq-metric-chart/locales/es.json'
+import ptSqButtonCopyText from '@components/buttons/sq-button-copy-text/locales/pt.json'
+import enSqButtonCopyText from '@components/buttons/sq-button-copy-text/locales/en.json'
+import esSqButtonCopyText from '@components/buttons/sq-button-copy-text/locales/es.json'
+import ptSqInputBirthday from '@components/inputs/sq-input-birthday/locales/pt.json'
+import enSqInputBirthday from '@components/inputs/sq-input-birthday/locales/en.json'
+import esSqInputBirthday from '@components/inputs/sq-input-birthday/locales/es.json'
+import ptSqInputDigits from '@components/inputs/sq-input-digits/locales/pt.json'
+import enSqInputDigits from '@components/inputs/sq-input-digits/locales/en.json'
+import esSqInputDigits from '@components/inputs/sq-input-digits/locales/es.json'
+import ptSqInputDocumentCnpj from '@components/inputs/sq-input-document-cnpj/locales/pt.json'
+import enSqInputDocumentCnpj from '@components/inputs/sq-input-document-cnpj/locales/en.json'
+import esSqInputDocumentCnpj from '@components/inputs/sq-input-document-cnpj/locales/es.json'
+import ptSqInputDocumentCpf from '@components/inputs/sq-input-document-cpf/locales/pt.json'
+import enSqInputDocumentCpf from '@components/inputs/sq-input-document-cpf/locales/en.json'
+import esSqInputDocumentCpf from '@components/inputs/sq-input-document-cpf/locales/es.json'
+import ptSqInputDocumentInternational from '@components/inputs/sq-input-document-international/locales/pt.json'
+import enSqInputDocumentInternational from '@components/inputs/sq-input-document-international/locales/en.json'
+import esSqInputDocumentInternational from '@components/inputs/sq-input-document-international/locales/es.json'
+import ptSqInputDocumentRut from '@components/inputs/sq-input-document-rut/locales/pt.json'
+import enSqInputDocumentRut from '@components/inputs/sq-input-document-rut/locales/en.json'
+import esSqInputDocumentRut from '@components/inputs/sq-input-document-rut/locales/es.json'
+import ptSqInputName from '@components/inputs/sq-input-name/locales/pt.json'
+import enSqInputName from '@components/inputs/sq-input-name/locales/en.json'
+import esSqInputName from '@components/inputs/sq-input-name/locales/es.json'
const componentsThatUseGlobals = ['sqInput']
@@ -32,14 +56,38 @@ const getResources = () => ({
en: {
globals: enGlobals,
sqMetricChart: enSqMetricChart,
+ sqButtonCopyText: enSqButtonCopyText,
+ sqInputBirthday: enSqInputBirthday,
+ sqInputDigits: enSqInputDigits,
+ sqInputDocumentCnpj: enSqInputDocumentCnpj,
+ sqInputDocumentCpf: enSqInputDocumentCpf,
+ sqInputDocumentInternational: enSqInputDocumentInternational,
+ sqInputDocumentRut: enSqInputDocumentRut,
+ sqInputName: enSqInputName,
},
pt: {
globals: ptGlobals,
sqMetricChart: ptSqMetricChart,
+ sqButtonCopyText: ptSqButtonCopyText,
+ sqInputBirthday: ptSqInputBirthday,
+ sqInputDigits: ptSqInputDigits,
+ sqInputDocumentCnpj: ptSqInputDocumentCnpj,
+ sqInputDocumentCpf: ptSqInputDocumentCpf,
+ sqInputDocumentInternational: ptSqInputDocumentInternational,
+ sqInputDocumentRut: ptSqInputDocumentRut,
+ sqInputName: ptSqInputName,
},
es: {
globals: esGlobals,
sqMetricChart: esSqMetricChart,
+ sqButtonCopyText: esSqButtonCopyText,
+ sqInputBirthday: esSqInputBirthday,
+ sqInputDigits: esSqInputDigits,
+ sqInputDocumentCnpj: esSqInputDocumentCnpj,
+ sqInputDocumentCpf: esSqInputDocumentCpf,
+ sqInputDocumentInternational: esSqInputDocumentInternational,
+ sqInputDocumentRut: esSqInputDocumentRut,
+ sqInputName: esSqInputName,
},
})
@@ -76,10 +124,22 @@ i18n
.use(initReactI18next)
.init({
defaultNS,
- ns: ['globals', 'sqMetricChart'],
+ ns: [
+ 'globals',
+ 'sqMetricChart',
+ 'sqButtonCopyText',
+ 'sqInputBirthday',
+ 'sqInputDigits',
+ 'sqInputDocumentCnpj',
+ 'sqInputDocumentCpf',
+ 'sqInputDocumentInternational',
+ 'sqInputDocumentRut',
+ 'sqInputName',
+ ],
load: 'all',
supportedLngs: ['en', 'pt', 'es'],
debug: false,
+ lng: navigator.language?.split('-')[0] || 'en',
cache: { enable: false },
interpolation: { escapeValue: false },
fallbackLng: 'en',
diff --git a/src/index.mdx b/src/index.mdx
new file mode 100644
index 0000000..90b1dc8
--- /dev/null
+++ b/src/index.mdx
@@ -0,0 +1,77 @@
+import { Meta } from '@storybook/blocks'
+
+
+
+
+
+
+
@squidit/react-css
+ This repository contains a React component library developed to facilitate the creation of consistent and elegant interfaces, following a custom style guide. The included components are highly customizable and designed to be reusable across a variety of React projects.
+
+
+## Table of contents
+
+* [Welcome to Squid Design System](#welcome-to-squid-design-system)
+* [Style](#style)
+* [Components](#components)
+* [Installation](#installation)
+* [How to Use](#how-to-use)
+* [Customization](#customization)
+* [License](#license)
+
+## Welcome to Squid Design System
+
+⚡ Get the experience by browsing one of [our platforms](https://app.squidit.com.br)!
+
+This framework provides low level utilities and UI components for building
+custom experiences.
+
+
+
+## Style
+
+Our Design System can be seen [here](https://css.squidit.com.br/styleguide)
+
+## Components
+
+UI Components are currently offered as React (Web) components.
+
+## Installation
+
+1. Node version >= 18
+2. To use this library in your React project, you can install it via npm or yarn:
+
+```bash
+npm install @squidit/css @squidit/react-css
+# or
+yarn add @squidit/css @squidit/react-css
+```
+
+3. Configure css in your project according to the @squidit/css documentation described in the project's [README](https://github.com/squidit/css/blob/master/README.md)
+
+## How to Use
+
+After installation, you can import and use the components as needed in your React components:
+
+```jsx
+import React from 'react';
+import { SqButton } from '@squidit/react-css';
+
+const MyComponent = () => {
+ return (
+
+ Click Here
+
+ );
+};
+
+export default MyComponent;
+```
+
+## Customization
+
+This library allows high flexibility and customization of the components. You can modify the default styles of the components using specific props or by overriding the styles via CSS.
+
+## License
+
+This project is licensed under the [MIT License](LICENSE).
diff --git a/src/index.stories.mdx b/src/index.stories.mdx
deleted file mode 100644
index c57bd7a..0000000
--- a/src/index.stories.mdx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Meta } from '@storybook/addon-docs'
-
-
-
-# Welcome to Squid Design System
-
-⚡ Get the experience by browsing one of [our platforms](https://app.squidit.com.br)!
-
-This framework provides low level utilities and UI components for building
-custom experiences.
-
-
-
-## Style
-
-Our Design System can be seen [here](https://css.squidit.com.br/styleguide)
-
-## Components
-
-UI Components are currently offered as React (Web) components.
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 6828418..2eda90a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -6,6 +6,7 @@ export * from './helpers'
export * from './hooks'
export * from './interfaces'
export * from './observables'
+
export { setComponentTranslations, setAllComponentsTranslations } from './i18n'
onLangChange.subscribe((lang) => {
diff --git a/src/styles.scss b/src/styles.scss
index 757339c..b0a97fa 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -4,5 +4,5 @@ $fontsFolderPath: '@squidit/css/dist/fonts';
@import '@squidit/css/src/scss/squid.scss';
:root {
- --primary_color: var(--pink);
+ --primary_color: var(--purple);
}