Skip to content

Commit

Permalink
Implement custom createContext util function (#1442)
Browse files Browse the repository at this point in the history
* refactor(utils): create createContext util function

* refactor(tooltip): apply createContext util

* refactor(segmented-control): apply create context util

* feat(utils): change the createContext function to distinguish between null and undefined

* refactor(form-control): apply createContext util

* refactor(modal): apply createContext util

fix ModalContentContextValue type declaration

* style: remove unnecessary empty line

* refactor(outline-item): apply createContext util

* refactor(tab-list): apply createContext util

* refactor(toast): apply createContext util

* feat(feature-provider): apply createContext util

* refactor(outline-item-context): fix type error (dead-code)
  • Loading branch information
sungik-choi authored Jul 4, 2023
1 parent 80c5b5a commit ded3f4e
Show file tree
Hide file tree
Showing 30 changed files with 128 additions and 155 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
type HelperTextPropsGetter,
type LabelPropsGetter,
} from './FormControl.types'
import { FormControlContext } from './FormControlContext'
import { FormControlContextProvider } from './FormControlContext'

import * as Styled from './FormControl.styled'

Expand Down Expand Up @@ -203,7 +203,7 @@ export const FormControl = forwardRef<HTMLElement, FormControlProps>(function Fo
if (!children) { return null }

return (
<FormControlContext.Provider value={contextValue}>
<FormControlContextProvider value={contextValue}>
<Container
{...bezierProps}
ref={forwardedRef}
Expand All @@ -213,6 +213,6 @@ export const FormControl = forwardRef<HTMLElement, FormControlProps>(function Fo
>
{ children }
</Container>
</FormControlContext.Provider>
</FormControlContextProvider>
)
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { createContext } from 'react'
import { createContext } from '~/src/utils/reactUtils'

import { type FormControlContextValue } from '~/src/components/Forms/FormControl'

export const FormControlContext = createContext<FormControlContextValue | undefined>(undefined)
export const [
FormControlContextProvider,
useFormControlContext,
] = createContext<FormControlContextValue | undefined>(undefined)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { FormControl } from './FormControl'

export { FormControlContext } from './FormControlContext'
export { useFormControlContext } from './FormControlContext'

export type {
FormControlProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React, { forwardRef } from 'react'
import useMergeRefs from '~/src/hooks/useMergeRefs'
import { noop } from '~/src/utils/functionUtils'

import useFormControlContext from '~/src/components/Forms/useFormControlContext'
import { useFormControlContext } from '~/src/components/Forms/FormControl'

import type FormGroupProps from './FormGroup.types'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import useMergeRefs from '~/src/hooks/useMergeRefs'
import { noop } from '~/src/utils/functionUtils'
import { isEmpty } from '~/src/utils/typeUtils'

import useFormControlContext from '~/src/components/Forms/useFormControlContext'
import { useFormControlContext } from '~/src/components/Forms/FormControl'

import type {
BaseHelperTextProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Typography } from '~/src/foundation'

import { isEmpty } from '~/src/utils/typeUtils'

import useFormControlContext from '~/src/components/Forms/useFormControlContext'
import { useFormControlContext } from '~/src/components/Forms/FormControl'
import { Help } from '~/src/components/Help'
import { HELP_DISPLAY_NAME } from '~/src/components/Help/Help'
import {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
import React from 'react'
import { createContext } from '~/src/utils/reactUtils'

import {
type SegmentedControlProps,
type SegmentedControlType,
} from './SegmentedControl.types'

// TODO: (@ed) Evolve it into a commonly reusable function
function createContext<ContextValue>(
providerName: string,
defaultValue: ContextValue,
) {
const Context = React.createContext<ContextValue>(defaultValue)

function useContext(consumerName: string) {
const contextValue = React.useContext(Context)

if (!contextValue) {
throw new Error(`'${consumerName}' must be used within '${providerName}'`)
}

return contextValue
}

return [
Context.Provider,
useContext,
] as const
}

type SegmentedControlContextValue = Required<Pick<SegmentedControlProps<SegmentedControlType, string>, 'type' | 'size' | 'width'>>

export const [
SegmentedControlContextProvider,
useSegmentedControlContext,
] = createContext<SegmentedControlContextValue | null>('SegmentedControl', null)
] = createContext<SegmentedControlContextValue | null>(null, 'SegmentedControl')

interface SegmentedControlItemListContextValue {
setSelectedElement: (node: HTMLButtonElement | null) => void
Expand All @@ -42,4 +19,4 @@ interface SegmentedControlItemListContextValue {
export const [
SegmentedControlItemListContextProvider,
useSegmentedControlItemListContext,
] = createContext<SegmentedControlItemListContextValue | null>('SegmentedControlItemList', null)
] = createContext<SegmentedControlItemListContextValue | null>(null, 'SegmentedControlItemList')
2 changes: 0 additions & 2 deletions packages/bezier-react/src/components/Forms/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import type { FormComponentProps } from './Form.types'
import FormFieldSize from './FormFieldSize'
import useFormControlContext from './useFormControlContext'
import useFormFieldProps from './useFormFieldProps'
import useKeyboardActionLockerWhileComposing from './useKeyboardActionLockerWhileComposing'

export type { FormComponentProps }
export * from './Inputs/constants/CommonImeControlKeys'
export {
FormFieldSize,
useFormControlContext,
useFormFieldProps,
useKeyboardActionLockerWhileComposing,
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { useMemo } from 'react'
import { ariaAttr } from '~/src/utils/domUtils'

import type { FormComponentProps } from '~/src/components/Forms/Form.types'

import useFormControlContext from './useFormControlContext'
import { useFormControlContext } from '~/src/components/Forms/FormControl'

// TODO: 테스트 추가
function useFormFieldProps<Props extends FormComponentProps>(props?: Props) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function ModalComposition({

<ModalBody>
<FormControl labelPosition="left">
<FormLabel>Name</FormLabel>
<FormLabel help="Lorem Ipsum">Name</FormLabel>
<Select text="Lorem Ipsum">
{ Array.from({ length: 20 }).map((_, index) => (
<ListItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,3 @@ export function Modal({
</DialogPrimitive.Root>
)
}

Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,4 @@ export interface ModalCloseProps extends
ChildrenProps<React.ReactElement> {}

export interface ModalContentContextValue extends
NonNullable<Pick<ModalContentOptions, 'showCloseIcon'>> {}
Required<Pick<ModalContentOptions, 'showCloseIcon'>> {}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
type ModalContentContextValue,
type ModalContentProps,
} from './Modal.types'
import ModalContentContext from './ModalContentContext'
import { ModalContentContextProvider } from './ModalContentContext'
import { ModalClose } from './ModalHelpers'

import * as Styled from './Modal.styled'
Expand Down Expand Up @@ -67,9 +67,9 @@ export const ModalContent = forwardRef(function ModalContent({
{...rest}
>
<Styled.Section>
<ModalContentContext.Provider value={contextValue}>
<ModalContentContextProvider value={contextValue}>
{ children }
</ModalContentContext.Provider>
</ModalContentContextProvider>

{ /* NOTE: To prevent focusing first on the close button when opening the modal, place the close button behind. */ }
{ showCloseIcon && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react'
import { createContext } from '~/src/utils/reactUtils'

import { type ModalContentContextValue } from './Modal.types'

const ModalContentContext = React.createContext<ModalContentContextValue>({
export const [
ModalContentContextProvider,
useModalContentContext,
] = createContext<ModalContentContextValue>({
showCloseIcon: false,
})

export default ModalContentContext
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import React, {
forwardRef,
useContext,
} from 'react'
import React, { forwardRef } from 'react'

import * as DialogPrimitive from '@radix-ui/react-dialog'

Expand All @@ -14,7 +11,7 @@ import {
type ModalHeaderProps,
ModalTitleSize,
} from './Modal.types'
import ModalContentContext from './ModalContentContext'
import { useModalContentContext } from './ModalContentContext'

import * as Styled from './Modal.styled'

Expand Down Expand Up @@ -82,7 +79,7 @@ export const ModalHeader = forwardRef(function ModalHeader({
hidden = false,
...rest
}: ModalHeaderProps, forwardedRef: React.Ref<HTMLElement>) {
const { showCloseIcon } = useContext(ModalContentContext)
const { showCloseIcon } = useModalContentContext()
const hasTitleArea = title || showCloseIcon
const Hidden = hidden ? VisuallyHidden : React.Fragment

Expand Down
10 changes: 6 additions & 4 deletions packages/bezier-react/src/components/OutlineItem/OutlineItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import { isNil } from '~/src/utils/typeUtils'
import { IconSize } from '~/src/components/Icon'

import type OutlineItemProps from './OutlineItem.types'
import { OutlineItemContext } from './OutlineItemContext'
import useOutlineItemContext from './useOutlineItemContext'
import {
OutlineItemContextProvider,
useOutlineItemContext,
} from './OutlineItemContext'

import {
ChevronWrapper,
Expand Down Expand Up @@ -250,9 +252,9 @@ function OutlineItem(
}

return (
<OutlineItemContext.Provider value={passedContext}>
<OutlineItemContextProvider value={passedContext}>
{ element }
</OutlineItemContext.Provider>
</OutlineItemContextProvider>
)
})
), [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import type React from 'react'
import { createContext } from 'react'

import { noop } from '~/src/utils/functionUtils'
import { createContext } from '~/src/utils/reactUtils'

export interface OutlineItemContextProps {
interface OutlineItemContextProps {
depth: number
paddingLeft: number
active: boolean
onClick: (event?: React.MouseEvent<Element>, name?: string) => void
}

export const defaultOutlineItemContext = {
const defaultOutlineItemContext = {
depth: 0,
paddingLeft: 0,
active: false,
onClick: noop,
}

export function mergeOutlineItemContexts(
function mergeOutlineItemContexts(
inherited: OutlineItemContextProps,
props: Partial<Omit<OutlineItemContextProps, 'depth'>>,
indent: number,
Expand All @@ -33,4 +33,15 @@ export function mergeOutlineItemContexts(
}
}

export const OutlineItemContext = createContext<OutlineItemContextProps>(defaultOutlineItemContext)
const [
OutlineItemContextProvider,
useOutlineItemContextBase,
] = createContext<OutlineItemContextProps>(defaultOutlineItemContext)

export { OutlineItemContextProvider }

export const useOutlineItemContext = (props: Partial<Omit<OutlineItemContextProps, 'depth'>>, indent: number) => {
const inheritedContext = useOutlineItemContextBase() ?? defaultOutlineItemContext
const context = mergeOutlineItemContexts(inheritedContext, props, indent)
return context
}

This file was deleted.

9 changes: 3 additions & 6 deletions packages/bezier-react/src/components/Tabs/TabAction.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import React, {
forwardRef,
useContext,
} from 'react'
import React, { forwardRef } from 'react'

import { OpenInNewIcon } from '@channel.io/bezier-icons'

Expand All @@ -12,7 +9,7 @@ import { isNil } from '~/src/utils/typeUtils'
import { IconSize } from '~/src/components/Icon'
import { Text } from '~/src/components/Text'

import TabListContext from './TabListContext'
import { useTabListContext } from './TabListContext'
import {
type TabActionElement,
type TabActionProps,
Expand Down Expand Up @@ -52,7 +49,7 @@ export const TabAction = forwardRef(function TabAction<Link extends string | und
...rest
}: TabActionProps<Link>, forwardedRef: React.Ref<TabActionElement<Link>>,
) {
const { size } = useContext(TabListContext)
const { size } = useTabListContext()

return (
isNil(href) ? (
Expand Down
9 changes: 3 additions & 6 deletions packages/bezier-react/src/components/Tabs/TabItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import React, {
forwardRef,
useContext,
} from 'react'
import React, { forwardRef } from 'react'

import * as Tabs from '@radix-ui/react-tabs'

Expand All @@ -11,7 +8,7 @@ import {
ButtonStyleVariant,
} from '~/src/components/Button'

import TabListContext from './TabListContext'
import { useTabListContext } from './TabListContext'
import {
type TabItemProps,
TabSize,
Expand Down Expand Up @@ -40,7 +37,7 @@ export const TabItem = forwardRef(function TabItem({
children,
...rest
}: TabItemProps, forwardedRef: React.Ref<HTMLButtonElement>) {
const { size } = useContext(TabListContext)
const { size } = useTabListContext()

if (typeof children !== 'string') {
return null
Expand Down
Loading

0 comments on commit ded3f4e

Please sign in to comment.