Skip to content

Commit

Permalink
fix(antd/next): fix Editable component can not set default editable
Browse files Browse the repository at this point in the history
  • Loading branch information
janryWang committed Dec 29, 2021
1 parent 475d10e commit 88915bc
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 31 deletions.
38 changes: 24 additions & 14 deletions packages/antd/src/editable/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { useLayoutEffect, useRef, useState } from 'react'
import React, {
useEffect,
useMemo,
useLayoutEffect,
useRef,
useState,
} from 'react'
import { isVoidField, Field } from '@formily/core'
import { useField, observer } from '@formily/react'
import { Popover } from 'antd'
Expand All @@ -17,13 +23,13 @@ type ComposedEditable = React.FC<IFormItemProps> & {
Popover?: React.FC<IPopoverProps & { title?: React.ReactNode }>
}

const useParentPattern = () => {
const useInitialPattern = () => {
const field = useField<Field>()
return field?.parent?.pattern || field?.form?.pattern
return useMemo(() => field?.pattern, [])
}

const useEditable = (): [boolean, (payload: boolean) => void] => {
const pattern = useParentPattern()
const useEditable = (): [boolean, (editable: boolean) => void, () => void] => {
const pattern = useInitialPattern()
const field = useField<Field>()
useLayoutEffect(() => {
if (pattern === 'editable') {
Expand All @@ -36,6 +42,9 @@ const useEditable = (): [boolean, (payload: boolean) => void] => {
if (pattern !== 'editable') return
field.setPattern(payload ? 'editable' : 'readPretty')
},
() => {
field.setPattern(pattern)
},
]
}

Expand All @@ -58,15 +67,15 @@ const useFormItemProps = (): IFormItemProps => {
}

export const Editable: ComposedEditable = observer((props) => {
const [editable, setEditable] = useEditable()
const pattern = useParentPattern()
const [editable, setEditable, resetEditable] = useEditable()
const pattern = useInitialPattern()
const itemProps = useFormItemProps()
const field = useField<Field>()
const basePrefixCls = usePrefixCls()
const prefixCls = usePrefixCls('formily-editable')
const ref = useRef<boolean>()
const innerRef = useRef<HTMLDivElement>()
const recover = () => {
const closeEditable = () => {
if (ref.current && !field?.errors?.length) {
setEditable(false)
}
Expand All @@ -78,9 +87,6 @@ export const Editable: ComposedEditable = observer((props) => {
{pattern === 'editable' && (
<EditOutlined className={`${prefixCls}-edit-btn`} />
)}
{pattern !== 'editable' && (
<MessageOutlined className={`${prefixCls}-edit-btn`} />
)}
</BaseItem>
)
}
Expand All @@ -99,14 +105,14 @@ export const Editable: ComposedEditable = observer((props) => {
if (target?.closest(`.${basePrefixCls}-select-dropdown`)) return
if (target?.closest(`.${basePrefixCls}-picker-dropdown`)) return
if (target?.closest(`.${basePrefixCls}-cascader-menus`)) return
recover()
closeEditable()
}, innerRef)

const onClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const target = e.target as HTMLElement
const close = innerRef.current.querySelector(`.${prefixCls}-close-btn`)
if (target?.contains(close) || close?.contains(target)) {
recover()
closeEditable()
} else if (!ref.current) {
setTimeout(() => {
setEditable(true)
Expand All @@ -119,6 +125,10 @@ export const Editable: ComposedEditable = observer((props) => {

ref.current = editable

useEffect(() => {
return resetEditable
}, [])

return (
<div className={prefixCls} ref={innerRef} onClick={onClick}>
<div className={`${prefixCls}-content`}>
Expand All @@ -134,7 +144,7 @@ export const Editable: ComposedEditable = observer((props) => {

Editable.Popover = observer((props) => {
const field = useField<Field>()
const pattern = useParentPattern()
const pattern = useInitialPattern()
const [visible, setVisible] = useState(false)
const prefixCls = usePrefixCls('formily-editable')
const closePopover = async () => {
Expand Down
44 changes: 27 additions & 17 deletions packages/next/src/editable/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { useLayoutEffect, useRef, useState } from 'react'
import React, {
useLayoutEffect,
useMemo,
useEffect,
useRef,
useState,
} from 'react'
import { isVoidField, Field } from '@formily/core'
import { useField, observer } from '@formily/react'
import { Balloon } from '@alifd/next'
Expand All @@ -21,24 +27,27 @@ type ComposedEditable = React.FC<IFormItemProps> & {
Popover?: React.FC<IPopoverProps & { title?: React.ReactNode }>
}

const useParentPattern = () => {
const useInitialPattern = () => {
const field = useField<Field>()
return field?.parent?.pattern || field?.form?.pattern
return useMemo(() => field?.pattern, [])
}

const useEditable = (): [boolean, (payload: boolean) => void] => {
const pattern = useParentPattern()
const useEditable = (): [boolean, (editable: boolean) => void, () => void] => {
const pattern = useInitialPattern()
const field = useField<Field>()
useLayoutEffect(() => {
if (pattern === 'editable') {
field.setPattern('readPretty')
return field.setPattern('readPretty')
}
}, [pattern])
return [
field.pattern === 'editable',
(pyaload: boolean) => {
(payload: boolean) => {
if (pattern !== 'editable') return
field.setPattern(pyaload ? 'editable' : 'readPretty')
field.setPattern(payload ? 'editable' : 'readPretty')
},
() => {
field.setPattern(pattern)
},
]
}
Expand All @@ -62,15 +71,15 @@ const useFormItemProps = (): IFormItemProps => {
}

export const Editable: ComposedEditable = observer((props) => {
const [editable, setEditable] = useEditable()
const pattern = useParentPattern()
const [editable, setEditable, resetEditable] = useEditable()
const pattern = useInitialPattern()
const itemProps = useFormItemProps()
const field = useField<Field>()
const basePrefixCls = usePrefixCls()
const prefixCls = usePrefixCls('formily-editable')
const ref = useRef<boolean>()
const innerRef = useRef<HTMLDivElement>()
const recover = () => {
const closeEditable = () => {
if (ref.current && !field?.errors?.length) {
setEditable(false)
}
Expand All @@ -82,9 +91,6 @@ export const Editable: ComposedEditable = observer((props) => {
{pattern === 'editable' && (
<EditOutlinedIcon className={`${prefixCls}-edit-btn`} />
)}
{pattern !== 'editable' && (
<MessageOutlinedIcon className={`${prefixCls}-edit-btn`} />
)}
</BaseItem>
)
}
Expand All @@ -101,14 +107,14 @@ export const Editable: ComposedEditable = observer((props) => {
useClickAway((e) => {
const target = e.target as HTMLElement
if (target?.closest(`.${basePrefixCls}-overlay-wrapper`)) return
recover()
closeEditable()
}, innerRef)

const onClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const target = e.target as HTMLElement
const close = innerRef.current.querySelector(`.${prefixCls}-close-btn`)
if (target?.contains(close) || close?.contains(target)) {
recover()
closeEditable()
} else if (!ref.current) {
setTimeout(() => {
setEditable(true)
Expand All @@ -119,6 +125,10 @@ export const Editable: ComposedEditable = observer((props) => {
}
}

useEffect(() => {
return resetEditable
}, [])

ref.current = editable

return (
Expand All @@ -136,7 +146,7 @@ export const Editable: ComposedEditable = observer((props) => {

Editable.Popover = observer(({ ...props }) => {
const field = useField<Field>()
const pattern = useParentPattern()
const pattern = useInitialPattern()
const [visible, setVisible] = useState(false)
const prefixCls = usePrefixCls('formily-editable')
const closePopover = async () => {
Expand Down

0 comments on commit 88915bc

Please sign in to comment.