Skip to content

Commit

Permalink
feat: add customElement property, interfaces, conditional render cust…
Browse files Browse the repository at this point in the history
…om elements
  • Loading branch information
absolemDev committed Nov 20, 2023
1 parent 2ec40ad commit 5398e3a
Show file tree
Hide file tree
Showing 13 changed files with 164 additions and 138 deletions.
26 changes: 13 additions & 13 deletions packages/payment-widget/src/hooks/use-fields-render.hook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import React from 'react'
import { useIntl } from 'react-intl'

import { Field } from '../interfaces'
import { InputStyles } from '../interfaces'
import { HandleBlurField } from '../interfaces'
import { FieldState } from '../interfaces'
import { HandleChangeField } from '../interfaces'
import { FieldsErrors } from '../interfaces'
import { CustomInput } from '../interfaces/custom-elements.interfaces'
import { MemoizedInput } from '../ui'
import { translate } from '../utils/translate.util'

Expand All @@ -20,28 +20,28 @@ export const useFieldsRenderer = (
handleChange: HandleChangeField,
handleBlur: HandleBlurField,
inputGaps: number,
styles: InputStyles
customInput: CustomInput | undefined
) => {
const intl = useIntl()

return fields.map((field, index, currentFields) => {
const translatePlaceholder = translate(intl, field.placeholder, field.placeholder)
const translateError = translate(intl, errors[field.name], errors[field.name])
const isNotLastField = index !== currentFields.length - 1
const inputProps = {
type: field.type ?? 'text',
name: field.name,
placeholder: translatePlaceholder,
required: field.required ?? false,
value: fieldsState[field.name],
errorText: translateError,
onChangeNative: handleChange,
onBlur: handleBlur,
}

return (
<React.Fragment key={field.name}>
<MemoizedInput
type={field.type ?? 'text'}
name={field.name}
placeholder={translatePlaceholder}
required={field.required ?? false}
value={fieldsState[field.name]}
errorText={translateError}
onChangeNative={handleChange}
onBlur={handleBlur}
styles={styles}
/>
{customInput ? customInput(inputProps) : <MemoizedInput {...inputProps} />}
<Condition match={isNotLastField}>
<Layout flexBasis={inputGaps} flexShrink={0} />
</Condition>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react'
import { FC } from 'react'

import { HandleBlurField } from './fields.interfaces'
import { HandleChangeField } from './fields.interfaces'

interface CustomInputProps {
type: string
name: string
placeholder: string
required: boolean
value: string
errorText: string
onChangeNative: HandleChangeField
onBlur: HandleBlurField
}

export interface CustomButtonProps {
type: string
disabled: boolean
children?: React.ReactNode
}

export type CustomInput = FC<CustomInputProps>
export type CustomButton = FC<CustomButtonProps>

export interface CustomElements {
input?: CustomInput
button?: CustomButton
}
4 changes: 2 additions & 2 deletions packages/payment-widget/src/interfaces/fields.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { HTMLInputTypeAttribute } from 'react'

import { AdditionalFieldsType } from '../enums'
import { RequiredFieldsType } from '../enums'
import { CustomInput } from './custom-elements.interfaces'
import { DirectionFields } from './styles.interfaces'
import { InputStyles } from './styles.interfaces'

export type FieldsNames = RequiredFieldsType | AdditionalFieldsType
export type FieldState = Record<FieldsNames, string>
Expand Down Expand Up @@ -39,5 +39,5 @@ export interface FieldsProps {
inputGaps?: number
isGenerateReceipt?: boolean
additionalFields?: AdditionalField[]
styles?: InputStyles
customInput?: CustomInput
}
19 changes: 1 addition & 18 deletions packages/payment-widget/src/interfaces/styles.interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,8 @@ export enum DirectionFields {
Column = 'column',
}

export interface InputStyles {
styledArray?: any[]
size?: string
rounding?: {
default: number
active: number
}
}

export interface ButtonStyles extends ButtonProps {
styledArray?: any[]
size?: string
variant?: string
fill?: boolean
}

export interface Styles {
direction?: DirectionFields
inputGaps?: number
button?: ButtonStyles
input?: InputStyles
button?: ButtonProps
}
6 changes: 6 additions & 0 deletions packages/payment-widget/src/interfaces/theme.interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import React from 'react'

export interface ThemeProps {
useCustomTheme: boolean
children: React.ReactNode
}
3 changes: 2 additions & 1 deletion packages/payment-widget/src/interfaces/widget.interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CustomElements } from './custom-elements.interfaces'
import { AdditionalField } from './fields.interfaces'
import { ReceiptSettings } from './receipt.interfaces'
import { Settings } from './settings.interfaces'
Expand All @@ -9,6 +10,6 @@ export interface WidgetProps {
receipt?: ReceiptSettings
styles?: Styles
additionalFields?: AdditionalField[]
customTheme?: boolean
disabled?: boolean
customElements?: CustomElements
}
34 changes: 17 additions & 17 deletions packages/payment-widget/src/ui/button/button.component.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import styled from '@emotion/styled'
import styled from '@emotion/styled'

import React from 'react'
import { FC } from 'react'
import { useHover } from 'react-laag'
import React from 'react'
import { FC } from 'react'
import { useHover } from 'react-laag'

import { ButtonStyles } from '../../interfaces'
import { appearanceStyles } from './button.styles'
import { contentStyles } from './button.styles'
import { baseStyles } from './button.styles'
import { shapeStyles } from './button.styles'
import { CustomButtonProps } from '../../interfaces/custom-elements.interfaces'
import { appearanceStyles } from './button.styles'
import { contentStyles } from './button.styles'
import { baseStyles } from './button.styles'
import { shapeStyles } from './button.styles'

const ButtonElement = ({ styledArray, ...props }) => {
const StyledButton = styledArray.length
? styled('button')<any>(...styledArray)
: styled('button')<any>(baseStyles, contentStyles, appearanceStyles, shapeStyles)
return <StyledButton {...props} />
}
const ButtonElement = styled('button')<any>(
baseStyles,
contentStyles,
appearanceStyles,
shapeStyles
)

export const Button: FC<ButtonStyles> = ({ children, styledArray, ...props }) => {
export const Button: FC<CustomButtonProps> = ({ children, ...props }) => {
const [hover, hoverProps] = useHover()
return (
<ButtonElement hover={hover} {...hoverProps} styledArray={styledArray || []} {...props}>
<ButtonElement hover={hover} {...hoverProps} {...props}>
{children}
</ButtonElement>
)
Expand Down
4 changes: 2 additions & 2 deletions packages/payment-widget/src/ui/fields.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const Fields = ({
isGenerateReceipt = false,
direction = DirectionFields.Column,
inputGaps = 16,
styles = {},
customInput,
}: FieldsProps) => {
const processedFields = isGenerateReceipt
? addReceiptFieldsUtil(additionalFields)
Expand All @@ -37,7 +37,7 @@ export const Fields = ({
handleChange,
handleBlur,
inputGaps,
styles
customInput
)
const Direction = direction === DirectionFields.Column ? Column : Row

Expand Down
17 changes: 13 additions & 4 deletions packages/payment-widget/src/ui/form.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const Form = ({
styles,
additionalFields,
disabled,
customElements,
}: WidgetProps) => {
const isLoaded = useInit()
const { errors, validateField, isValidate } = useValidate()
Expand All @@ -31,6 +32,10 @@ export const Form = ({
makePayment(event)
}
}
const buttonProps = {
type: 'submit',
disabled: !isLoaded || !!disabled,
}

return (
<form name='payform-tinkoff' onSubmit={payHandler}>
Expand All @@ -43,11 +48,15 @@ export const Form = ({
additionalFields={additionalFields}
direction={styles?.direction}
inputGaps={styles?.inputGaps}
styles={styles?.input}
customInput={customElements?.input}
/>
<Button type='submit' disabled={!isLoaded || disabled} {...styles?.button}>
<FormattedMessage id='payment_widget.pay' defaultMessage='Оплатить' />
</Button>
{customElements?.button ? (
customElements.button(buttonProps)
) : (
<Button {...buttonProps} {...styles?.button}>
<FormattedMessage id='payment_widget.pay' defaultMessage='Оплатить' />
</Button>
)}
</form>
)
}
116 changes: 58 additions & 58 deletions packages/payment-widget/src/ui/form.test.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,58 @@
/**
* @jest-environment jsdom
*/

import { matchers } from '@emotion/jest'
import { RenderResult } from '@testing-library/react'
import { fireEvent } from '@testing-library/react'
import { render } from '@testing-library/react'
import { screen } from '@testing-library/react'

import React from 'react'
import { IntlProvider } from 'react-intl'
import { theme } from './theme/src'
import { ThemeProvider } from './theme/src'
import { Settings } from '../interfaces'
import { Form } from './form.component'

expect.extend(matchers)

type CustomRender = (element: React.ReactNode | React.ReactNode[]) => RenderResult

global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}))

const customRender: CustomRender = (element) => {
return render(
// @ts-ignore
<ThemeProvider>
<IntlProvider locale='ru' onError={() => {}}>
{element}
</IntlProvider>
</ThemeProvider>
)
}

describe('Form fragment', () => {
const settings: Settings = {
storeId: '123'
}

it.only('button reacts to filled in amount', () => {
customRender(<Form settings={settings} />)

const button = screen.getByRole('button', { name: 'Оплатить' })

expect(button).toBeTruthy()
expect(button).toHaveStyleRule('background-color', theme.colors.button.disabled.backgroundColor)

const input = screen.getByPlaceholderText('payment_widget.order_price')

fireEvent.change(input, { target: { value: '100' }})

expect(screen.getByRole('button', { name: 'Оплатить' })).toHaveStyleRule('background-color', theme.colors.button.default.backgroundColor)
})
})
// /**
// * @jest-environment jsdom
// */

// import { matchers } from '@emotion/jest'
// import { RenderResult } from '@testing-library/react'
// import { fireEvent } from '@testing-library/react'
// import { render } from '@testing-library/react'
// import { screen } from '@testing-library/react'

// import React from 'react'
// import { IntlProvider } from 'react-intl'
// import { theme } from './theme/src'
// import { ThemeProvider } from './theme/src'
// import { Settings } from '../interfaces'
// import { Form } from './form.component'

// expect.extend(matchers)

// type CustomRender = (element: React.ReactNode | React.ReactNode[]) => RenderResult

// global.ResizeObserver = jest.fn().mockImplementation(() => ({
// observe: jest.fn(),
// unobserve: jest.fn(),
// disconnect: jest.fn(),
// }))

// const customRender: CustomRender = (element) => {
// return render(
// // @ts-ignore
// <ThemeProvider>
// <IntlProvider locale='ru' onError={() => {}}>
// {element}
// </IntlProvider>
// </ThemeProvider>
// )
// }

// describe('Form fragment', () => {
// const settings: Settings = {
// storeId: '123'
// }

// it.only('button reacts to filled in amount', () => {
// customRender(<Form settings={settings} />)

// const button = screen.getByRole('button', { name: 'Оплатить' })

// expect(button).toBeTruthy()
// expect(button).toHaveStyleRule('background-color', theme.colors.button.disabled.backgroundColor)

// const input = screen.getByPlaceholderText('payment_widget.order_price')

// fireEvent.change(input, { target: { value: '100' }})

// expect(screen.getByRole('button', { name: 'Оплатить' })).toHaveStyleRule('background-color', theme.colors.button.default.backgroundColor)
// })
// })
Loading

0 comments on commit 5398e3a

Please sign in to comment.