Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat calendar #153

Merged
merged 7 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 10 additions & 35 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,15 @@
<!--
Thanks for creating a Pull Request ❤️!
Follow the steps below to ensure that your PR is approved and error-free.
**Resolves issue:**
Issue link if existis

- 📝 Use a descriptive title for the PR.
- ✅ Make sure that tests have been added or modified to accommodate the new changes.
- 🔍 Make sure that documentation in the Storybook has been added or modified to reflect the new changes.
- 🙏 Review your own PR to make sure everything has been done correctly!
- 🎬 When making a visual change, provide screenshots of the proposed change.
**Description:**
A small summary of changes that can be understood by non-devs.

-->

## 📝 Description

_Describe the modification or addition being made._

## 🚀 Why is this change required and behavior changes

_Describe the behavior changes that occur as a result of this PR._

## 💣 Is this a breaking change:

_Could your change break any old components that are already being used?_
**Code changes:**
- feat|chore|fix XXXXXX

**Breaking change:**
- [ ] Yes
- [ ] No

_If yes, please describe how to upgrade from the old version to the new one below._

## 📝 Additional Information

_Some additional information._

## Checklist

_Don't forget to do everything here._
- [x] No

- [ ] I've created/modified some component
- [ ] I've created/modified the component's stories
- [ ] I've created/modified the component's tests
**Observation:**
Some additional information. (Optional)
77 changes: 77 additions & 0 deletions docs/src/stories/Calendar/Calendar.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Calendar, CalendarProps } from '@droz-js/visu'
import { useArgs } from '@storybook/preview-api'
import { Meta, StoryObj } from '@storybook/react'

const meta: Meta<CalendarProps> = {
title: 'Calendar/Calendar',
component: Calendar,
argTypes: {
children: {
control: 'none',
table: {
type: {
summary: 'React.ReactNode',
},
},
type: { name: 'other', required: false, value: 'React.ReactNode' },
},
mode: {
control: 'inline-radio',
description: 'Aplica o mode em Calendar',
options: [
'default',
'multiple',
'range',
'single',
] as CalendarProps['mode'][],
table: {
type: {
summary: ['default', 'multiple', 'range', 'single'].join('|'),
},
},
type: { name: 'string', required: true },
defaultValue: 'default' as CalendarProps['mode'],
},
selected: {
control: 'object',
description: 'Aplica o selected em CalendarCalendar',
table: {
type: { summary: 'object' },
},
type: { name: 'string', required: false },
},
onSelect: {
action: 'clicked',
description: 'Define o onSelect em CalendarCalendar',
table: { type: { summary: 'function' } },
},
},
args: {
children: '',
},
} as Meta<CalendarProps>

export default meta
type CalendarStory = StoryObj<CalendarProps>

export const Comum: CalendarStory = {
// @ts-expect-error dynamic component
render: ({ selected, onSelect, ...args }: CalendarProps) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [, updateArgs] = useArgs()

onSelect = (data: any) => {
updateArgs({ selected: data })
}

return (
// @ts-expect-error dynamic component
<Calendar
selected={selected}
onSelect={onSelect}
mode="range"
{...args}
/>
)
},
}
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-toggle-group": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.7",
"react-day-picker": "^8.10.0",
"tailwindcss": "^3.4.1"
},
"devDependencies": {
Expand Down Expand Up @@ -104,4 +105,4 @@
"access": "public",
"registry": "https://registry.npmjs.org/"
}
}
}
54 changes: 13 additions & 41 deletions package/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import LayoutDefault from './layout/Default'
import { Form, Input, Select } from './library'
import { Calendar, DateRange, Form, Popover } from './library'

import { zodResolver } from '@hookform/resolvers/zod'
import { Eraser, MagnifyingGlass } from '@phosphor-icons/react'
import { useMemo, useState } from 'react'
import { Eraser } from '@phosphor-icons/react'
import { useState } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'
import { z } from 'zod'

Expand All @@ -13,21 +13,8 @@ const formSchema = z.object({

type FormSchemaProps = z.infer<typeof formSchema>

const list = [
{ id: '1', value: 'first', label: 'First Item' },
{ id: '2', value: 'second', label: 'Second Item' },
{ id: '3', value: 'third', label: 'Third Item' },
{ id: '4', value: 'fourth', label: 'Fourth Item' },
{ id: '5', value: 'fifth', label: 'Fifth Item' },
{ id: '6', value: 'sixth', label: 'Sixth Item' },
{ id: '7', value: 'seventh', label: 'Seventh Item' },
{ id: '8', value: 'eighth', label: 'Eighth Item' },
{ id: '9', value: 'ninth', label: 'Ninth Item' },
{ id: '10', value: 'tenth', label: 'Tenth Item' },
]

function App() {
const [test, setTest] = useState('')
const [test, setTest] = useState<DateRange>()
const {
handleSubmit,
watch,
Expand All @@ -45,17 +32,9 @@ function App() {

const clearState = () => {
reset()
setTest('')
setTest(undefined)
}

const filteredList = useMemo(() => {
if (!test) return list
return list.filter((item) => {
const concat = `${item.value.toLowerCase()} - ${item.label.toLocaleLowerCase()}`
return concat.includes(test.toLocaleLowerCase())
})
}, [test])

return (
<LayoutDefault
asChild
Expand All @@ -64,21 +43,14 @@ function App() {
>
<Form.Root onSubmit={handleSubmit(onSubmit)}>
{/* ================================= TEST AREA ================================= */}
<Select.Root placeholder="Selecione uma opção">
<Input.Root className="mb-4">
<Input.Icon icon={<MagnifyingGlass />} />
<Input.Input
placeholder="Pesquise uma opção"
value={test}
onChange={(ev) => setTest(ev.target.value)}
/>
</Input.Root>
{filteredList.map((item) => (
<Select.Item key={item.id} value={item.id}>
{item.value} - {item.label}
</Select.Item>
))}
</Select.Root>
<Popover.Root>
<Popover.Trigger>
<span>Click me</span>
</Popover.Trigger>
<Popover.Content className="shadow">
<Calendar mode="range" selected={test} onSelect={setTest} />
</Popover.Content>
</Popover.Root>
{/* ================================= TEST AREA ================================= */}
</Form.Root>
</LayoutDefault>
Expand Down
19 changes: 19 additions & 0 deletions package/src/__tests__/Calendar/Calendar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Calendar } from '@library'

import { render, screen } from '@testing-library/react'
import { clsx } from 'clsx'

jest.mock('clsx', () => {
return {
clsx: jest.fn().mockImplementation(() => clsx),
}
})

describe('Calendar Root tests', () => {
it('Should render a calendar element', () => {
render(<Calendar data-testid="element" />)
const element = screen.getByTestId('element')

expect(element).toBeDefined()
})
})
68 changes: 68 additions & 0 deletions package/src/library/Calendar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use client'

import { cn } from '@/src/utils/class-merge.helper'

import { CaretLeft, CaretRight } from '@phosphor-icons/react'
import { ComponentProps } from 'react'
import { DayPicker } from 'react-day-picker'

export type DateRange = {
from: Date | undefined
to?: Date | undefined
}

export type CalendarProps = ComponentProps<typeof DayPicker>

const Calendar = ({
className,
classNames,
showOutsideDays = true,
...rest
}: CalendarProps) => {
return (
<DayPicker
showOutsideDays={showOutsideDays}
className={cn('rounded-md bg-gray-100 p-4', className)}
classNames={{
months: 'flex flex-col',
month: 'space-y-4',
caption: 'flex justify-center pt-1 relative items-center',
caption_label: 'text-sm font-medium',
nav: 'space-x-1 flex items-center',
nav_button:
'p-1 rounded-full bg-primary-100 text-primary hover:bg-primary-200 active:bg-primary-200',
nav_button_previous: 'absolute left-1',
nav_button_next: 'absolute right-1',
table: 'w-full border-collapse space-y-1',
head_row: 'flex',
head_cell: 'text-gray-500 rounded-md w-9 font-normal text-[0.8rem]',
row: 'flex w-full mt-2',
cell: 'h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-gray-100/50 [&:has([aria-selected])]:bg-gray-100 first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative',
day: 'w-full h-full rounded-md hover:border border-primary-200',
day_range_end: 'day-range-end rounded-l-none !bg-primary',
day_range_start: 'day-range-start rounded-r-none !bg-primary',
day_selected: 'bg-primary text-gray-100 rounded-md',
day_today: 'border !border-primary',
day_outside:
'day-outside text-gray-500 opacity-25 aria-selected:bg-gray-100/50 aria-selected:text-gray-500 aria-selected:opacity-30',
day_disabled: 'text-gray-500 opacity-25',
day_range_middle:
'aria-selected:bg-primary-200 aria-selected:text-gray-800 rounded-none',
day_hidden: 'opacity-0',
...classNames,
}}
components={{
IconLeft: ({ ...rest }) => (
<CaretLeft className="h-4 w-4 bg-error" {...rest} />
),
IconRight: ({ ...rest }) => (
<CaretRight className="h-4 w-4" {...rest} />
),
}}
{...rest}
/>
)
}
Calendar.displayName = 'Calendar'

export default Calendar
15 changes: 3 additions & 12 deletions package/src/library/Popover/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,14 @@ import { FC } from 'react'

export interface PopoverContentProps extends RadixPopover.PopoverContentProps {}

const PopoverContent: FC<PopoverContentProps> = ({
children,
className,
...rest
}) => {
const PopoverContent: FC<PopoverContentProps> = ({ className, ...rest }) => {
return (
<RadixPopover.Portal>
<RadixPopover.Content
className={cn(
'z-100 rounded-lg border-none bg-primary-200 p-3',
className,
)}
className={cn('z-100', className)}
sideOffset={5}
{...rest}
>
<div className="bg-background-200">{children}</div>
</RadixPopover.Content>
/>
</RadixPopover.Portal>
)
}
Expand Down
2 changes: 1 addition & 1 deletion package/src/library/Select/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const SelectRoot: FC<SelectRootProps> = ({
sideOffset={5}
collisionPadding={32}
avoidCollisions
className="z-100 flex max-h-[--radix-select-content-available-height] min-w-56 max-w-[--radix-select-content-available-width] flex-col gap-2 rounded-lg border border-gray bg-gray-100 shadow"
className="z-100 flex max-h-[--radix-select-content-height] w-[--radix-select-trigger-width] flex-col gap-2 rounded-lg border border-gray bg-gray-100 shadow"
>
<RadixSelect.ScrollUpButton className="flex items-center justify-center p-2">
<CaretUp />
Expand Down
Loading
Loading