Skip to content

Commit

Permalink
Merge branch 'release/0.18.7'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ishdeep Singh authored and Ishdeep Singh committed Nov 4, 2024
2 parents 3d61826 + 4220d49 commit 5c98cc4
Show file tree
Hide file tree
Showing 13 changed files with 442 additions and 73 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ Prefix the change with one of these keywords:

## [Unreleased]

## [0.18.7]

### Added

- Input Addon Component for before and after element in Input Form Field
- Loader for Pagination , Events and calendar

## [0.18.6]

### Changed
Expand Down
65 changes: 62 additions & 3 deletions lib/components/Form/Form.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import { Button } from '../Button/Button'
import { AutoSuggestData } from './../../data/AutoSuggestData'
import { LoadScript } from '@react-google-maps/api'
import { SingleMarkerInterface } from './PlacesAutoComplete/PlacesAutoComplete'
import FormError from './FormError/FormError'

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))
import InputAddon from './InputAddon/InputAddon'

const meta: Meta<typeof Form> = {
title: 'Components/Form',
Expand Down Expand Up @@ -79,6 +77,67 @@ export const Input: Story = () => {
)
}

export const InputAddonStory: Story = () => {
type IInput = {
inputText: string
}

const InputInitialValues = {
inputText: '',
}

const InputValidationSchema = Yup.object().shape({
inputText: Yup.string().required('The field is required'),
})

const onSubmit = async (values: IInput, actions: FormikHelpers<IInput>) => {
actions.setSubmitting(true)
alert(JSON.stringify(values, null, 2))
await sleep(1000)
actions.setSubmitting(false)
}

const onReset: MouseEventHandler<HTMLButtonElement> = () => {
formikProps.resetForm()
}

const formikProps = useFormik({
initialValues: InputInitialValues,
validationSchema: InputValidationSchema,
onSubmit,
})

return (
<Form formikProps={formikProps}>
<Form.FieldGroup>
<Form.FieldControl
control="text"
label="Label"
name="inputText"
required
helper="Helper Text"
hasPrefix={
<InputAddon border="right" isGrey>
$
</InputAddon>
}
hasSuffix={
<InputAddon border="left" isGrey>
USD
</InputAddon>
}
helperpostop
disabled={formikProps.isSubmitting}
/>
</Form.FieldGroup>
<ButtonGroup>
<Button title="Submit" type="submit" />
<Button title="Reset" type="reset" color="grey" onClick={onReset} />
</ButtonGroup>
</Form>
)
}

export const TextArea: Story = () => {
type ITextArea = {
textareainput: string
Expand Down
21 changes: 12 additions & 9 deletions lib/components/Form/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ import { fieldStyles } from '../form.Styles'
import { FieldComponentProps } from '../FormField/FormField'
import useErrorClass from '../UseError'

export const Input = ({ ...props }: FieldComponentProps) => {
const { name, ...rest } = props
export interface InputProps extends FieldComponentProps {
hasPrefix?: React.ReactNode
hasSuffix?: React.ReactNode
}

export const Input = ({ ...props }: InputProps) => {
const { name, hasPrefix, hasSuffix, ...rest } = props

const errorClass = useErrorClass(name)

return (
<Field
type="text"
id={name}
name={name}
className={`${fieldStyles.input} ${fieldStyles.disabled} ${errorClass}`}
{...rest}
/>
<div className={`${fieldStyles.input} ${fieldStyles.disabled} flex items-stretch`}>
{hasPrefix && hasPrefix}
<Field type="text" id={name} name={name} className={`border-none rounded-md w-full ${errorClass}`} {...rest} />
{hasSuffix && hasSuffix}
</div>
)
}
32 changes: 32 additions & 0 deletions lib/components/Form/InputAddon/InputAddon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export interface InputAddonProps {
children: React.ReactNode
border?: 'none' | 'left' | 'right'
isGrey?: boolean
}

export const InputAddon = ({ children, ...props }: InputAddonProps) => {
const { border, isGrey } = props

let greyBg = ''
let hasBorder = ''

switch (border) {
case 'left':
greyBg = isGrey ? 'rounded-r-md bg-cu-black-50' : ''
hasBorder = `border-l border-cu-black-200 ${greyBg}`
break
case 'right':
greyBg = isGrey ? 'rounded-l-md bg-cu-black-50' : ''
hasBorder = `border-r border-cu-black-200 ${greyBg}`
break

default:
greyBg = ''
hasBorder = ''
break
}

return <span className={`px-4 flex items-center ${hasBorder}`}>{children}</span>
}

export default InputAddon
31 changes: 31 additions & 0 deletions lib/components/Loaders/CalendarLoader/CalendarLoader.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Meta, StoryObj } from '@storybook/react'
import { CalendarLoader } from './CalendarLoader'
import { Section } from '../../../layouts/Section/Section'
import React from 'react'

const meta: Meta<typeof CalendarLoader> = {
title: 'Components/Load Screens/Calendar Loader',
component: CalendarLoader,
tags: ['autodocs'],
parameters: {
controls: {
sort: 'requiredFirst',
},
},
}

export default meta
type Story = StoryObj<typeof CalendarLoader>

export const Primary: Story = {
args: {
showClearButton: true,
},
render: (args) => {
return (
<Section>
<CalendarLoader {...args} />
</Section>
)
},
}
84 changes: 84 additions & 0 deletions lib/components/Loaders/CalendarLoader/CalendarLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { format, getDay, isBefore, startOfToday, eachDayOfInterval, endOfMonth, parse } from 'date-fns'
import { ButtonLoader } from '../ButtonLoader/ButtonLoader'
import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/24/outline'
import { useState } from 'react'

const styles = {
prevNextArrows: `flex items-center justify-center flex-none p-2 text-cu-black-800 hover:text-cu-red`,
calendarGrid: `grid grid-cols-7 gap-px mt-4 text-center`,
element: `w-8 h-8 bg-cu-black-200 rounded-full `,
}

const classNames = (...classes: (string | boolean)[]) => {
return classes.filter(Boolean).join(' ')
}

export interface CalendarLoaderProps {
showClearButton?: boolean
}

export const CalendarLoader = ({ showClearButton }: CalendarLoaderProps) => {
const today = startOfToday()
const [currentMonth] = useState(format(today, 'MMM-yyyy'))
const firstDayCurrentMonth = parse(currentMonth, 'MMM-yyyy', new Date())
const colStartClasses = ['', 'col-start-2', 'col-start-3', 'col-start-4', 'col-start-5', 'col-start-6', 'col-start-7']
const days = eachDayOfInterval({
start: firstDayCurrentMonth,
end: endOfMonth(firstDayCurrentMonth),
})

return (
<>
<div className="animate-pulse">
<div className="cu-calendar cu-component not-prose">
<div className="flex items-center py-2 mb-6 bg-white border rounded-lg border-cu-black-100">
<button type="button" className={`${styles.prevNextArrows}`}>
<span className="text-base sr-only">Previous month</span>
<ChevronLeftIcon className="w-5 h-5" aria-hidden="true" />
</button>
<div className="flex items-center justify-center mx-auto">
{/* {format(firstDayCurrentMonth, 'MMMM yyyy')} */}
<span className="block h-6 w-48 rounded-md bg-cu-black-200"></span>
</div>
<button type="button" className={`${styles.prevNextArrows}`}>
<span className="text-base sr-only">Next month</span>
<ChevronRightIcon className="w-5 h-5" aria-hidden="true" />
</button>
</div>

<div className={`${styles.calendarGrid} text-xs text-cu-black-600`}>
<div>S</div>
<div>M</div>
<div>T</div>
<div>W</div>
<div>T</div>
<div>F</div>
<div>S</div>
</div>

<div
className={`${styles.calendarGrid} isolate overflow-hidden rounded-lg border border-cu-black-100 bg-cu-black-50 text-sm`}
>
{days.map((day, dayIdx) => (
<div
key={day.toString()}
className={classNames(dayIdx === 0 && colStartClasses[getDay(day)], 'bg-white py-2')}
>
<button type="button" disabled={isBefore(day, today)}>
<div className={styles.element}></div>
</button>

<div className="w-1 h-1 mx-auto mt-1"></div>
</div>
))}
</div>
{showClearButton && (
<div className="mt-4 flex justify-center items-center">
<ButtonLoader number={1} isSmall={true} />
</div>
)}
</div>
</div>
</>
)
}
19 changes: 19 additions & 0 deletions lib/components/Loaders/EventLoader/EventLoader.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react'
import { EventLoader } from './EventLoader'

const meta: Meta<typeof EventLoader> = {
title: 'Components/Load Screens/Event Loader',
component: EventLoader,
tags: ['autodocs'],
parameters: {
controls: {
sort: 'requiredFirst',
},
},
}

export default meta
type Story = StoryObj<typeof EventLoader>

export const Default: Story = {}
Default.args = {}
33 changes: 33 additions & 0 deletions lib/components/Loaders/EventLoader/EventLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Column, StackedList, Aside } from '../../../main'
import { ListingNewsLoader } from '../ListingLoader/ListingNewsLoader'
import { PaginationLoader } from '../PaginationLoader/PaginationLoader'
import { CalendarLoader } from '../CalendarLoader/CalendarLoader'

export interface EventLoaderProps {
pageCount?: number
showClearButton?: boolean
}

export const EventLoader = ({ pageCount = 5, showClearButton = false }: EventLoaderProps) => {
return (
<>
<Column cols="2/3" maxWidth="7xl">
<Column.Content>
<StackedList cols="2">
<ListingNewsLoader />
<ListingNewsLoader />
<ListingNewsLoader />
<ListingNewsLoader />
<ListingNewsLoader />
<ListingNewsLoader />
</StackedList>
<PaginationLoader pageCount={pageCount} />
</Column.Content>

<Aside isSticky topSpace={105}>
<CalendarLoader showClearButton={showClearButton} />
</Aside>
</Column>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { Meta, StoryObj } from '@storybook/react'
import { PaginationLoader } from './PaginationLoader'
import { Section } from '../../../layouts/Section/Section'
import React from 'react'

const meta: Meta<typeof PaginationLoader> = {
title: 'Components/Load Screens/Pagination Loader',
component: PaginationLoader,
tags: ['autodocs'],
parameters: {
controls: {
sort: 'requiredFirst',
},
},
}

export default meta
type Story = StoryObj<typeof PaginationLoader>

export const Primary: Story = {
args: {
hasBorder: true,
pageCount: 5,
},
render: (args) => {
return (
<Section>
<PaginationLoader {...args} />
</Section>
)
},
}
Loading

0 comments on commit 5c98cc4

Please sign in to comment.