Skip to content

Commit

Permalink
feat(next): add ArrayCollapse (#1513)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lind-pro authored May 27, 2021
1 parent e729e00 commit ebddc01
Show file tree
Hide file tree
Showing 8 changed files with 1,015 additions and 0 deletions.
631 changes: 631 additions & 0 deletions packages/next/docs/components/ArrayCollapse.md

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions packages/next/src/__builtins__/empty.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react'

export const Empty = () => {
return (
<div className="next-empty">
<div className="next-empty-image">
<svg
className="ant-empty-img-default"
width="184"
height="120"
viewBox="0 0 184 152"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="none" fillRule="evenodd">
<g transform="translate(24 31.67)">
<ellipse
className="ant-empty-img-default-ellipse"
cx="67.797"
cy="106.89"
rx="67.797"
ry="12.668"
></ellipse>
<path
className="ant-empty-img-default-path-1"
d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
></path>
<path
className="ant-empty-img-default-path-2"
d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
transform="translate(13.56)"
></path>
<path
className="ant-empty-img-default-path-3"
d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
></path>
<path
className="ant-empty-img-default-path-4"
d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
></path>
</g>
<path
className="ant-empty-img-default-path-5"
d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
></path>
<g
className="ant-empty-img-default-g"
transform="translate(149.65 15.383)"
>
<ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"></ellipse>
<path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"></path>
</g>
</g>
</svg>
</div>
</div>
)
}
1 change: 1 addition & 0 deletions packages/next/src/__builtins__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './hooks'
export * from './toArray'
export * from './mapStatus'
export * from './mapSize'
export * from './empty'
218 changes: 218 additions & 0 deletions packages/next/src/array-collapse/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import React, { Fragment, useState, useEffect } from 'react'
import { Badge, Card, Collapse } from '@alifd/next'
import {
RecursionField,
useField,
useFieldSchema,
observer,
ISchema,
} from '@formily/react'
import cls from 'classnames'
import ArrayBase, { ArrayBaseMixins } from '../array-base'
import { usePrefixCls, Empty } from '../__builtins__'
import { CollapseProps, PanelProps } from '@alifd/next/lib/collapse'

export interface IArrayCollapseProps extends CollapseProps {
defaultOpenPanelCount?: number
}
type ComposedArrayCollapse = React.FC<IArrayCollapseProps> &
ArrayBaseMixins & {
CollapsePanel?: React.FC<PanelProps>
}

const isAdditionComponent = (schema: ISchema) => {
return schema['x-component']?.indexOf('Addition') > -1
}

const isIndexComponent = (schema: ISchema) => {
return schema['x-component']?.indexOf('Index') > -1
}

const isRemoveComponent = (schema: ISchema) => {
return schema['x-component']?.indexOf('Remove') > -1
}

const isMoveUpComponent = (schema: ISchema) => {
return schema['x-component']?.indexOf('MoveUp') > -1
}

const isMoveDownComponent = (schema: ISchema) => {
return schema['x-component']?.indexOf('MoveDown') > -1
}

const isOperationComponent = (schema: ISchema) => {
return (
isAdditionComponent(schema) ||
isRemoveComponent(schema) ||
isMoveDownComponent(schema) ||
isMoveUpComponent(schema)
)
}

const range = (count: number) => Array.from({ length: count }).map((_, i) => i)

const takeDefaultExpandedKeys = (
dataSourceLength: number,
defaultOpenPanelCount: number
) => {
if (dataSourceLength < defaultOpenPanelCount) return range(dataSourceLength)
return range(defaultOpenPanelCount)
}

const insertExpandedKeys = (expandedKeys: number[], index: number) => {
if (expandedKeys.length <= index) return expandedKeys.concat(index)
return expandedKeys.reduce((buf, key) => {
if (key < index) return buf.concat(key)
if (key === index) return buf.concat([key, key + 1])
return buf.concat(key + 1)
}, [])
}

export const ArrayCollapse: ComposedArrayCollapse = observer(
({ defaultOpenPanelCount, ...props }: IArrayCollapseProps) => {
const field = useField<Formily.Core.Models.ArrayField>()
const dataSource = Array.isArray(field.value) ? field.value : []

const [expandKeys, setExpandKeys] = useState<number[]>(
takeDefaultExpandedKeys(dataSource.length, defaultOpenPanelCount)
)
const schema = useFieldSchema()
const prefixCls = usePrefixCls('formily-array-collapse', props)
useEffect(() => {
if (!field.modified && dataSource.length) {
setExpandKeys(
takeDefaultExpandedKeys(dataSource.length, defaultOpenPanelCount)
)
}
}, [dataSource.length, field])
if (!schema) throw new Error('can not found schema object')

const renderAddition = () => {
return schema.reduceProperties((addition, schema) => {
if (isAdditionComponent(schema)) {
return <RecursionField schema={schema} name="addition" />
}
return addition
}, null)
}
const renderEmpty = () => {
if (dataSource.length) return
return (
<Card className={cls(`${prefixCls}-item`, props.className)}>
<Empty />
</Card>
)
}

const renderItems = () => {
return (
<Collapse
{...props}
expandedKeys={expandKeys.map(String)}
onExpand={(keys: string[]) => setExpandKeys(keys.map(Number))}
className={cls(`${prefixCls}-item`, props.className)}
>
{dataSource.map((item, index) => {
const items = Array.isArray(schema.items)
? schema.items[index] || schema.items[0]
: schema.items

const props: PanelProps = items['x-component-props']

const title = () => {
const title = `${props?.title || field.title}`
const path = field.address.concat(index)
const errors = field.form.queryFeedbacks({
type: 'error',
address: `*(${path},${path}.*)`,
})
return (
<ArrayBase.Item index={index}>
<div
className={cls(`${prefixCls}-item-title`, props.className)}
>
<div>
<RecursionField
schema={items}
name={index}
filterProperties={(schema) => {
if (!isIndexComponent(schema)) return false
return true
}}
onlyRenderProperties
/>
{errors.length ? (
<Badge className="errors-badge" count={errors.length}>
{title}
</Badge>
) : (
title
)}
</div>
<div>
<RecursionField
schema={items}
name={index}
filterProperties={(schema) => {
if (!isOperationComponent(schema)) return false
return true
}}
onlyRenderProperties
/>
</div>
</div>
</ArrayBase.Item>
)
}

const content = (
<RecursionField
schema={items}
name={index}
filterProperties={(schema) => {
if (isIndexComponent(schema)) return false
if (isOperationComponent(schema)) return false
return true
}}
/>
)
return (
<Collapse.Panel {...props} key={index} title={title()}>
<ArrayBase.Item index={index} key={index}>
{content}
</ArrayBase.Item>
</Collapse.Panel>
)
})}
</Collapse>
)
}
return (
<ArrayBase
onAdd={(index) => {
setExpandKeys(insertExpandedKeys(expandKeys, index))
}}
>
{renderEmpty()}
{renderItems()}
{renderAddition()}
</ArrayBase>
)
}
)

const CollapsePanel: React.FC<PanelProps> = ({ children }) => {
return <Fragment>{children}</Fragment>
}

CollapsePanel.displayName = 'CollapsePanel'

ArrayCollapse.defaultProps = {
defaultOpenPanelCount: 5,
}
ArrayCollapse.displayName = 'ArrayCollapse'
ArrayCollapse.CollapsePanel = CollapsePanel

ArrayBase.mixin(ArrayCollapse)

export default ArrayCollapse
103 changes: 103 additions & 0 deletions packages/next/src/array-collapse/main.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
@import '~@alifd/next/lib/core/index-noreset.scss';

$array-collapse-prefix-cls: '#{$css-prefix}formily-array-collapse';

.#{$css-prefix}empty {
display: flex;
justify-content: center;
align-items: center;

&-image {
display: flex;
justify-content: center;
align-items: center;
transform: scale(0.8);

.ant-empty-img-default-ellipse {
fill-opacity: 0.8;
fill: #f5f5f5;
}

.ant-empty-img-default-path-1 {
fill: #aeb8c2;
}

.ant-empty-img-default-path-2 {
fill: url(#linearGradient-1);
}

.ant-empty-img-default-path-3 {
fill: #f5f5f7;
}

.ant-empty-img-default-path-4,
.ant-empty-img-default-path-5 {
fill: #dce0e6;
}

.ant-empty-img-default-g {
fill: #fff;
}

.ant-empty-img-simple-ellipse {
fill: #f5f5f5;
}

.ant-empty-img-simple-g {
stroke: #d9d9d9;
}

.ant-empty-img-simple-path {
fill: #fafafa;
}

.ant-empty-rtl {
direction: rtl;
}
}
}

.#{$array-collapse-prefix-cls}-remove {
transition: all 0.25s ease-in-out;
color: $color-text1-3;
font-size: 16px;
margin-left: 6px;

&:hover {
color: $color-text1-1;
}
}

.#{$array-collapse-prefix-cls}-addition {
transition: all 0.25s ease-in-out;
}

.#{$array-collapse-prefix-cls}-move-down {
transition: all 0.25s ease-in-out;
color: $color-text1-3;
font-size: 16px;
margin-left: 6px;

&:hover {
color: $color-text1-1;
}
}

.#{$array-collapse-prefix-cls}-move-up {
transition: all 0.25s ease-in-out;
color: $color-text1-3;
font-size: 16px;
margin-left: 6px;

&:hover {
color: $color-text1-1;
}
}

.#{$array-collapse-prefix-cls}-item {
margin-bottom: 10px !important;
.#{$array-collapse-prefix-cls}-item-title {
display: flex;
justify-content: space-between;
}
}
3 changes: 3 additions & 0 deletions packages/next/src/array-collapse/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import '@alifd/next/lib/collapse/style'
import '@alifd/next/lib/card/style'
import './main.scss'
1 change: 1 addition & 0 deletions packages/next/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import './style'
export * from './array-base'
export * from './array-table'
export * from './array-cards'
export * from './array-collapse'
export * from './array-items'
export * from './form-dialog'
export * from './form-drawer'
Expand Down
Loading

0 comments on commit ebddc01

Please sign in to comment.