packages/antd/src/form-button-group/index.tsx (122 lines of code) (raw):
/**
* 1. FormItem网格布局
* 2. 居中,居右,居左布局
* 3. 行内布局
* 4. 吸底布局
*/
import React, { useRef, useLayoutEffect, useState } from 'react'
import { ReactFC } from '@formily/react'
import { Space } from 'antd'
import { SpaceProps } from 'antd/lib/space'
import { BaseItem, IFormItemProps } from '../form-item'
import { usePrefixCls } from '../__builtins__'
import StickyBox from 'react-sticky-box'
import cls from 'classnames'
interface IStickyProps extends React.ComponentProps<typeof StickyBox> {
align?: React.CSSProperties['textAlign']
}
type IFormButtonGroupProps = Omit<SpaceProps, 'align' | 'size'> & {
align?: React.CSSProperties['textAlign']
gutter?: number
}
type ComposedButtonGroup = ReactFC<IFormButtonGroupProps> & {
Sticky: ReactFC<React.PropsWithChildren<IStickyProps>>
FormItem: ReactFC<
IFormItemProps & {
gutter?: number
}
>
}
function getInheritedBackgroundColor(el: HTMLElement) {
// get default style for current browser
const defaultStyle = getDefaultBackground() // typically "rgba(0, 0, 0, 0)"
// get computed color for el
const backgroundColor = window.getComputedStyle(el).backgroundColor
// if we got a real value, return it
if (backgroundColor != defaultStyle) return backgroundColor
// if we've reached the top parent el without getting an explicit color, return default
if (!el.parentElement) return defaultStyle
// otherwise, recurse and try again on parent element
return getInheritedBackgroundColor(el.parentElement)
}
function getDefaultBackground() {
// have to add to the document in order to use getComputedStyle
let div = document.createElement('div')
document.head.appendChild(div)
let bg = window.getComputedStyle(div).backgroundColor
document.head.removeChild(div)
return bg
}
export const FormButtonGroup: ComposedButtonGroup = ({
align = 'left',
gutter,
...props
}) => {
const prefixCls = usePrefixCls('formily-button-group')
return (
<Space
{...props}
size={gutter}
className={cls(prefixCls, props.className)}
style={{
...props.style,
justifyContent:
align === 'left'
? 'flex-start'
: align === 'right'
? 'flex-end'
: 'center',
display: 'flex',
}}
>
{props.children}
</Space>
)
}
FormButtonGroup.FormItem = ({ gutter, ...props }) => {
return (
<BaseItem
{...props}
label=" "
style={{
margin: 0,
padding: 0,
...props.style,
width: '100%',
}}
colon={false}
>
{props.children?.['length'] ? (
<Space size={gutter}>{props.children}</Space>
) : (
props.children
)}
</BaseItem>
)
}
FormButtonGroup.Sticky = ({ align = 'left', ...props }) => {
const ref = useRef()
const [color, setColor] = useState('transparent')
const prefixCls = usePrefixCls('formily-button-group')
useLayoutEffect(() => {
if (ref.current) {
const computed = getInheritedBackgroundColor(ref.current)
if (computed !== color) {
setColor(computed)
}
}
})
return (
<StickyBox
{...props}
className={cls(`${prefixCls}-sticky`, props.className)}
style={{
backgroundColor: color,
...props.style,
}}
bottom
>
<div
ref={ref}
className={`${prefixCls}-sticky-inner`}
style={{
...props.style,
justifyContent:
align === 'left'
? 'flex-start'
: align === 'right'
? 'flex-end'
: 'center',
}}
>
{props.children}
</div>
</StickyBox>
)
}
export default FormButtonGroup