1
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-present yiminghe
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
# rc-collapse
|
||||
|
||||
rc-collapse ui component for react
|
||||
|
||||
[![NPM version][npm-image]][npm-url] [![build status][github-actions-image]][github-actions-url] [![Test coverage][codecov-image]][codecov-url] [![npm download][download-image]][download-url]
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/rc-collapse.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/rc-collapse
|
||||
[github-actions-image]: https://github.com/react-component/collapse/workflows/CI/badge.svg
|
||||
[github-actions-url]: https://github.com/react-component/collapse/actions
|
||||
[codecov-image]: https://img.shields.io/codecov/c/github/react-component/collapse/master.svg?style=flat-square
|
||||
[codecov-url]: https://app.codecov.io/gh/react-component/collapse
|
||||
[download-image]: https://img.shields.io/npm/dm/rc-collapse.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/rc-collapse
|
||||
|
||||
## Live Demo
|
||||
|
||||
https://collapse-react-component.vercel.app
|
||||
|
||||
## Install
|
||||
|
||||
[](https://npmjs.org/package/rc-collapse)
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
var Collapse = require('rc-collapse');
|
||||
var Panel = Collapse.Panel;
|
||||
var React = require('react');
|
||||
var ReactDOM = require('react-dom');
|
||||
require('rc-collapse/assets/index.css');
|
||||
|
||||
var App = (
|
||||
<Collapse accordion={true}>
|
||||
<Panel header="hello" headerClass="my-header-class">
|
||||
this is panel content
|
||||
</Panel>
|
||||
<Panel header="title2">this is panel content2 or other</Panel>
|
||||
</Collapse>
|
||||
);
|
||||
ReactDOM.render(App, container);
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- support ie8,ie8+,chrome,firefox,safari
|
||||
|
||||
## API
|
||||
|
||||
### Collapse props
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 100px;">name</th>
|
||||
<th style="width: 50px;">type</th>
|
||||
<th>default</th>
|
||||
<th>description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>activeKey</td>
|
||||
<td>String|Array<String></td>
|
||||
<th>The first panel key</th>
|
||||
<td>current active Panel key</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>className</td>
|
||||
<td>String or object</td>
|
||||
<th></th>
|
||||
<td>custom className to apply</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>defaultActiveKey</td>
|
||||
<td>String|Array<String></td>
|
||||
<th>null</th>
|
||||
<td>default active key</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>destroyOnHidden</td>
|
||||
<td>Boolean</td>
|
||||
<th>false</th>
|
||||
<td>If destroy the panel which not active, default false. </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>accordion</td>
|
||||
<td>Boolean</td>
|
||||
<th>false</th>
|
||||
<td>accordion mode, default is null, is collapse mode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>onChange</td>
|
||||
<td>Function(key)</td>
|
||||
<th>noop</th>
|
||||
<td>called when collapse Panel is changed</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>expandIcon</td>
|
||||
<td>(props: PanelProps) => ReactNode</td>
|
||||
<th></th>
|
||||
<td>specific the custom expand icon.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>collapsible</td>
|
||||
<td>'header' | 'icon' | 'disabled'</td>
|
||||
<th>-</th>
|
||||
<td>specify whether the panel of children is collapsible or the area of collapsible.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>items</td>
|
||||
<td>
|
||||
<a href="./src/interface.ts#ItemType">interface.ts#ItemType</a>
|
||||
</td>
|
||||
<th>-</th>
|
||||
<td>collapse items content</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
If `accordion` is null or false, every panel can open. Opening another panel will not close any of the other panels. `activeKey` should be an string, if passing an array (the first item in the array will be used).
|
||||
|
||||
If `accordion` is true, only one panel can be open. Opening another panel will cause the previously opened panel to close. `activeKey` should be an string, if passing an array (the first item in the array will be used).
|
||||
|
||||
### Collapse.Panel props
|
||||
|
||||
> **deprecated** use `items` instead, will be removed in `v4.0.0`
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 100px;">name</th>
|
||||
<th style="width: 200px;">type</th>
|
||||
<th>default</th>
|
||||
<th>description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>header</td>
|
||||
<td>String or node</td>
|
||||
<th></th>
|
||||
<td>header content of Panel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>headerClass</td>
|
||||
<td>String</td>
|
||||
<th>' '</th>
|
||||
<td>custom className to apply to header</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>showArrow</td>
|
||||
<td>boolean</td>
|
||||
<th>true</th>
|
||||
<td>show arrow beside header</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>className</td>
|
||||
<td>String or object</td>
|
||||
<th></th>
|
||||
<td>custom className to apply</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>classNames</td>
|
||||
<td>{ header?: string, body?: string }</td>
|
||||
<th></th>
|
||||
<td>Semantic structure className</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>style</td>
|
||||
<td>object</td>
|
||||
<th></th>
|
||||
<td>custom style</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>styles</td>
|
||||
<td>{ header?: React.CSSProperties, body?: React.CSSProperties }</td>
|
||||
<th></th>
|
||||
<td>Semantic structure styles</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>openMotion</td>
|
||||
<td>object</td>
|
||||
<th></th>
|
||||
<td>set the animation of open behavior, [more](https://github.com/react-component/motion). Different with v2, closed pane use a `rc-collapse-content-hidden` class to set `display: none` for hidden.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>forceRender</td>
|
||||
<td>boolean</td>
|
||||
<th>false</th>
|
||||
<td>forced render of content in panel, not lazy render after clicking on header</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>extra</td>
|
||||
<td>String | ReactNode</td>
|
||||
<th></th>
|
||||
<td>Content to render in the right of the panel header</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>collapsible</td>
|
||||
<td>'header' | 'icon' | 'disabled'</td>
|
||||
<th>-</th>
|
||||
<td>specify whether the panel be collapsible or the area of collapsible.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
> `disabled` is removed since 3.0.0, please use `collapsible=disabled` replace it.
|
||||
|
||||
#### key
|
||||
|
||||
If `key` is not provided, the panel's index will be used instead.
|
||||
|
||||
#### KeyBoard Event
|
||||
|
||||
By default, Collapse will listen `onKeyDown`(<3.7.0 `onKeyPress`) event with `enter` key to toggle panel's active state when `collapsible` is not `disabled`. If you want to disable this behavior, you can prevent the event from bubbling like this:
|
||||
|
||||
```tsx | pure
|
||||
const App = () => {
|
||||
const items: CollapseProps['items'] = [
|
||||
{
|
||||
label: <input onKeyDown={(e) => e.stopPropagation()} />,
|
||||
children: 'content',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<div onKeyDown={(e) => e.stopPropagation()}>
|
||||
<CustomComponent />
|
||||
</div>
|
||||
),
|
||||
children: 'content',
|
||||
},
|
||||
{
|
||||
label: 'title 2',
|
||||
children: 'content 2',
|
||||
collapsible: 'disabled',
|
||||
},
|
||||
{
|
||||
label: 'title 3',
|
||||
children: 'content 3',
|
||||
onItemClick: console.log,
|
||||
},
|
||||
];
|
||||
|
||||
return <Collapse items={items} />;
|
||||
};
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
## Test Case
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
## Coverage
|
||||
|
||||
```bash
|
||||
npm test -- --coverage
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
rc-collapse is released under the MIT license.
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
.rc-collapse-motion {
|
||||
transition: height 0.3s, opacity 0.3s;
|
||||
}
|
||||
.rc-collapse-panel-hidden {
|
||||
display: none;
|
||||
}
|
||||
.rc-collapse {
|
||||
background-color: #f7f7f7;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #d9d9d9;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item {
|
||||
border-top: 1px solid #d9d9d9;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item > .rc-collapse-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 22px;
|
||||
padding: 10px 16px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item > .rc-collapse-header .arrow {
|
||||
display: inline-block;
|
||||
content: '\20';
|
||||
width: 0;
|
||||
height: 0;
|
||||
font-size: 0;
|
||||
line-height: 0;
|
||||
border-top: 3px solid transparent;
|
||||
border-bottom: 3px solid transparent;
|
||||
border-left: 4px solid #666;
|
||||
vertical-align: middle;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item > .rc-collapse-header .rc-collapse-extra {
|
||||
margin: 0 16px 0 auto;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item .rc-collapse-collapsible-header {
|
||||
cursor: default;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item .rc-collapse-collapsible-header .rc-collapse-title {
|
||||
cursor: pointer;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item .rc-collapse-collapsible-header .rc-collapse-expand-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item .rc-collapse-collapsible-icon {
|
||||
cursor: default;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item .rc-collapse-collapsible-icon .rc-collapse-expand-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item-disabled > .rc-collapse-header {
|
||||
cursor: not-allowed;
|
||||
color: #999;
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
.rc-collapse-panel {
|
||||
overflow: hidden;
|
||||
color: #666;
|
||||
padding: 0 16px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.rc-collapse-panel > .rc-collapse-panel-box {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.rc-collapse-item:last-child > .rc-collapse-panel {
|
||||
border-radius: 0 0 3px 3px;
|
||||
}
|
||||
.rc-collapse > .rc-collapse-item-active > .rc-collapse-header .arrow {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
border-left: 3px solid transparent;
|
||||
border-right: 3px solid transparent;
|
||||
border-top: 4px solid #666;
|
||||
margin-right: 6px;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import type { CollapseProps } from './interface';
|
||||
declare const _default: React.ForwardRefExoticComponent<CollapseProps & React.RefAttributes<HTMLDivElement>> & {
|
||||
/**
|
||||
* @deprecated use `items` instead, will be removed in `v4.0.0`
|
||||
*/
|
||||
Panel: React.ForwardRefExoticComponent<import("./interface").CollapsePanelProps & React.RefAttributes<HTMLDivElement>>;
|
||||
};
|
||||
export default _default;
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
import _extends from "@babel/runtime/helpers/esm/extends";
|
||||
import { clsx } from 'clsx';
|
||||
import { useControlledState, useEvent } from '@rc-component/util';
|
||||
import warning from "@rc-component/util/es/warning";
|
||||
import React from 'react';
|
||||
import useItems from "./hooks/useItems";
|
||||
import CollapsePanel from "./Panel";
|
||||
import pickAttrs from "@rc-component/util/es/pickAttrs";
|
||||
function getActiveKeysArray(activeKey) {
|
||||
let currentActiveKey = activeKey;
|
||||
if (!Array.isArray(currentActiveKey)) {
|
||||
const activeKeyType = typeof currentActiveKey;
|
||||
currentActiveKey = activeKeyType === 'number' || activeKeyType === 'string' ? [currentActiveKey] : [];
|
||||
}
|
||||
return currentActiveKey.map(key => String(key));
|
||||
}
|
||||
const Collapse = /*#__PURE__*/React.forwardRef((props, ref) => {
|
||||
const {
|
||||
prefixCls = 'rc-collapse',
|
||||
destroyOnHidden = false,
|
||||
style,
|
||||
accordion,
|
||||
className,
|
||||
children,
|
||||
collapsible,
|
||||
openMotion,
|
||||
expandIcon,
|
||||
activeKey: rawActiveKey,
|
||||
defaultActiveKey,
|
||||
onChange,
|
||||
items,
|
||||
classNames: customizeClassNames,
|
||||
styles
|
||||
} = props;
|
||||
const collapseClassName = clsx(prefixCls, className);
|
||||
const [internalActiveKey, setActiveKey] = useControlledState(defaultActiveKey, rawActiveKey);
|
||||
const activeKey = getActiveKeysArray(internalActiveKey);
|
||||
const triggerActiveKey = useEvent(next => {
|
||||
const nextKeys = getActiveKeysArray(next);
|
||||
setActiveKey(nextKeys);
|
||||
onChange?.(nextKeys);
|
||||
});
|
||||
const onItemClick = key => {
|
||||
if (accordion) {
|
||||
triggerActiveKey(activeKey[0] === key ? [] : [key]);
|
||||
} else {
|
||||
triggerActiveKey(activeKey.includes(key) ? activeKey.filter(item => item !== key) : [...activeKey, key]);
|
||||
}
|
||||
};
|
||||
|
||||
// ======================== Children ========================
|
||||
warning(!children, '[rc-collapse] `children` will be removed in next major version. Please use `items` instead.');
|
||||
const mergedChildren = useItems(items, children, {
|
||||
prefixCls,
|
||||
accordion,
|
||||
openMotion,
|
||||
expandIcon,
|
||||
collapsible,
|
||||
destroyOnHidden,
|
||||
onItemClick,
|
||||
activeKey,
|
||||
classNames: customizeClassNames,
|
||||
styles
|
||||
});
|
||||
|
||||
// ======================== Render ========================
|
||||
return /*#__PURE__*/React.createElement("div", _extends({
|
||||
ref: ref,
|
||||
className: collapseClassName,
|
||||
style: style,
|
||||
role: accordion ? 'tablist' : undefined
|
||||
}, pickAttrs(props, {
|
||||
aria: true,
|
||||
data: true
|
||||
})), mergedChildren);
|
||||
});
|
||||
export default Object.assign(Collapse, {
|
||||
/**
|
||||
* @deprecated use `items` instead, will be removed in `v4.0.0`
|
||||
*/
|
||||
Panel: CollapsePanel
|
||||
});
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import React from 'react';
|
||||
import type { CollapsePanelProps } from './interface';
|
||||
declare const CollapsePanel: React.ForwardRefExoticComponent<CollapsePanelProps & React.RefAttributes<HTMLDivElement>>;
|
||||
export default CollapsePanel;
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
import _extends from "@babel/runtime/helpers/esm/extends";
|
||||
import { clsx } from 'clsx';
|
||||
import CSSMotion from '@rc-component/motion';
|
||||
import KeyCode from "@rc-component/util/es/KeyCode";
|
||||
import React from 'react';
|
||||
import PanelContent from "./PanelContent";
|
||||
const CollapsePanel = /*#__PURE__*/React.forwardRef((props, ref) => {
|
||||
const {
|
||||
showArrow = true,
|
||||
headerClass,
|
||||
isActive,
|
||||
onItemClick,
|
||||
forceRender,
|
||||
className,
|
||||
classNames: customizeClassNames = {},
|
||||
styles = {},
|
||||
prefixCls,
|
||||
collapsible,
|
||||
accordion,
|
||||
panelKey,
|
||||
extra,
|
||||
header,
|
||||
expandIcon,
|
||||
openMotion,
|
||||
destroyOnHidden,
|
||||
children,
|
||||
...resetProps
|
||||
} = props;
|
||||
const disabled = collapsible === 'disabled';
|
||||
const ifExtraExist = extra !== null && extra !== undefined && typeof extra !== 'boolean';
|
||||
const collapsibleProps = {
|
||||
onClick: () => {
|
||||
onItemClick?.(panelKey);
|
||||
},
|
||||
onKeyDown: e => {
|
||||
if (e.key === 'Enter' || e.keyCode === KeyCode.ENTER || e.which === KeyCode.ENTER) {
|
||||
onItemClick?.(panelKey);
|
||||
}
|
||||
},
|
||||
role: accordion ? 'tab' : 'button',
|
||||
['aria-expanded']: isActive,
|
||||
['aria-disabled']: disabled,
|
||||
tabIndex: disabled ? -1 : 0
|
||||
};
|
||||
|
||||
// ======================== Icon ========================
|
||||
const iconNodeInner = typeof expandIcon === 'function' ? expandIcon(props) : /*#__PURE__*/React.createElement("i", {
|
||||
className: "arrow"
|
||||
});
|
||||
const iconNode = iconNodeInner && /*#__PURE__*/React.createElement("div", _extends({
|
||||
className: clsx(`${prefixCls}-expand-icon`, customizeClassNames?.icon),
|
||||
style: styles?.icon
|
||||
}, ['header', 'icon'].includes(collapsible) ? collapsibleProps : {}), iconNodeInner);
|
||||
const collapsePanelClassNames = clsx(`${prefixCls}-item`, {
|
||||
[`${prefixCls}-item-active`]: isActive,
|
||||
[`${prefixCls}-item-disabled`]: disabled
|
||||
}, className);
|
||||
const headerClassName = clsx(headerClass, `${prefixCls}-header`, {
|
||||
[`${prefixCls}-collapsible-${collapsible}`]: !!collapsible
|
||||
}, customizeClassNames?.header);
|
||||
|
||||
// ======================== HeaderProps ========================
|
||||
const headerProps = {
|
||||
className: headerClassName,
|
||||
style: styles?.header,
|
||||
...(['header', 'icon'].includes(collapsible) ? {} : collapsibleProps)
|
||||
};
|
||||
|
||||
// ======================== Render ========================
|
||||
return /*#__PURE__*/React.createElement("div", _extends({}, resetProps, {
|
||||
ref: ref,
|
||||
className: collapsePanelClassNames
|
||||
}), /*#__PURE__*/React.createElement("div", headerProps, showArrow && iconNode, /*#__PURE__*/React.createElement("span", _extends({
|
||||
className: clsx(`${prefixCls}-title`, customizeClassNames?.title),
|
||||
style: styles?.title
|
||||
}, collapsible === 'header' ? collapsibleProps : {}), header), ifExtraExist && /*#__PURE__*/React.createElement("div", {
|
||||
className: `${prefixCls}-extra`
|
||||
}, extra)), /*#__PURE__*/React.createElement(CSSMotion, _extends({
|
||||
visible: isActive,
|
||||
leavedClassName: `${prefixCls}-panel-hidden`
|
||||
}, openMotion, {
|
||||
forceRender: forceRender,
|
||||
removeOnLeave: destroyOnHidden
|
||||
}), ({
|
||||
className: motionClassName,
|
||||
style: motionStyle
|
||||
}, motionRef) => {
|
||||
return /*#__PURE__*/React.createElement(PanelContent, {
|
||||
ref: motionRef,
|
||||
prefixCls: prefixCls,
|
||||
className: motionClassName,
|
||||
classNames: customizeClassNames,
|
||||
style: motionStyle,
|
||||
styles: styles,
|
||||
isActive: isActive,
|
||||
forceRender: forceRender,
|
||||
role: accordion ? 'tabpanel' : undefined
|
||||
}, children);
|
||||
}));
|
||||
});
|
||||
export default CollapsePanel;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
import type { CollapsePanelProps } from './interface';
|
||||
declare const PanelContent: React.ForwardRefExoticComponent<Readonly<CollapsePanelProps> & {
|
||||
children?: React.ReactNode;
|
||||
} & React.RefAttributes<HTMLDivElement>>;
|
||||
export default PanelContent;
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import { clsx } from 'clsx';
|
||||
import React from 'react';
|
||||
const PanelContent = /*#__PURE__*/React.forwardRef((props, ref) => {
|
||||
const {
|
||||
prefixCls,
|
||||
forceRender,
|
||||
className,
|
||||
style,
|
||||
children,
|
||||
isActive,
|
||||
role,
|
||||
classNames: customizeClassNames,
|
||||
styles
|
||||
} = props;
|
||||
const [rendered, setRendered] = React.useState(isActive || forceRender);
|
||||
React.useEffect(() => {
|
||||
if (forceRender || isActive) {
|
||||
setRendered(true);
|
||||
}
|
||||
}, [forceRender, isActive]);
|
||||
if (!rendered) {
|
||||
return null;
|
||||
}
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
ref: ref,
|
||||
className: clsx(`${prefixCls}-panel`, {
|
||||
[`${prefixCls}-panel-active`]: isActive,
|
||||
[`${prefixCls}-panel-inactive`]: !isActive
|
||||
}, className),
|
||||
style: style,
|
||||
role: role
|
||||
}, /*#__PURE__*/React.createElement("div", {
|
||||
className: clsx(`${prefixCls}-body`, customizeClassNames?.body),
|
||||
style: styles?.body
|
||||
}, children));
|
||||
});
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
PanelContent.displayName = 'PanelContent';
|
||||
}
|
||||
export default PanelContent;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
import type { CollapsePanelProps, CollapseProps, ItemType } from '../interface';
|
||||
type Props = Pick<CollapsePanelProps, 'prefixCls' | 'onItemClick' | 'openMotion' | 'expandIcon' | 'classNames' | 'styles'> & Pick<CollapseProps, 'accordion' | 'collapsible' | 'destroyOnHidden'> & {
|
||||
activeKey: React.Key[];
|
||||
};
|
||||
declare function useItems(items?: ItemType[], rawChildren?: React.ReactNode, props?: Props): React.ReactElement<CollapsePanelProps>[];
|
||||
export default useItems;
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
import _extends from "@babel/runtime/helpers/esm/extends";
|
||||
import toArray from "@rc-component/util/es/Children/toArray";
|
||||
import React from 'react';
|
||||
import CollapsePanel from "../Panel";
|
||||
import clsx from 'clsx';
|
||||
function mergeSemantic(src, tgt, mergeFn) {
|
||||
if (!src || !tgt) {
|
||||
return src || tgt;
|
||||
}
|
||||
const keys = Array.from(new Set([...Object.keys(src), ...Object.keys(tgt)]));
|
||||
const result = {};
|
||||
keys.forEach(key => {
|
||||
result[key] = mergeFn(src[key], tgt[key]);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function mergeSemanticClassNames(src, tgt) {
|
||||
return mergeSemantic(src, tgt, (a, b) => clsx(a, b));
|
||||
}
|
||||
function mergeSemanticStyles(src, tgt) {
|
||||
return mergeSemantic(src, tgt, (a, b) => ({
|
||||
...a,
|
||||
...b
|
||||
}));
|
||||
}
|
||||
const convertItemsToNodes = (items, props) => {
|
||||
const {
|
||||
prefixCls,
|
||||
accordion,
|
||||
collapsible,
|
||||
destroyOnHidden,
|
||||
onItemClick,
|
||||
activeKey,
|
||||
openMotion,
|
||||
expandIcon,
|
||||
classNames: collapseClassNames,
|
||||
styles: collapseStyles
|
||||
} = props;
|
||||
return items.map((item, index) => {
|
||||
const {
|
||||
children,
|
||||
label,
|
||||
key: rawKey,
|
||||
collapsible: rawCollapsible,
|
||||
onItemClick: rawOnItemClick,
|
||||
destroyOnHidden: rawDestroyOnHidden,
|
||||
classNames,
|
||||
styles,
|
||||
...restProps
|
||||
} = item;
|
||||
|
||||
// You may be puzzled why you want to convert them all into strings, me too.
|
||||
// Maybe: https://github.com/react-component/collapse/blob/aac303a8b6ff30e35060b4f8fecde6f4556fcbe2/src/Collapse.tsx#L15
|
||||
const key = String(rawKey ?? index);
|
||||
const mergeCollapsible = rawCollapsible ?? collapsible;
|
||||
const mergedDestroyOnHidden = rawDestroyOnHidden ?? destroyOnHidden;
|
||||
const handleItemClick = value => {
|
||||
if (mergeCollapsible === 'disabled') {
|
||||
return;
|
||||
}
|
||||
onItemClick(value);
|
||||
rawOnItemClick?.(value);
|
||||
};
|
||||
let isActive = false;
|
||||
if (accordion) {
|
||||
isActive = activeKey[0] === key;
|
||||
} else {
|
||||
isActive = activeKey.indexOf(key) > -1;
|
||||
}
|
||||
return /*#__PURE__*/React.createElement(CollapsePanel, _extends({}, restProps, {
|
||||
classNames: mergeSemanticClassNames(collapseClassNames, classNames),
|
||||
styles: mergeSemanticStyles(collapseStyles, styles),
|
||||
prefixCls: prefixCls,
|
||||
key: key,
|
||||
panelKey: key,
|
||||
isActive: isActive,
|
||||
accordion: accordion,
|
||||
openMotion: openMotion,
|
||||
expandIcon: expandIcon,
|
||||
header: label,
|
||||
collapsible: mergeCollapsible,
|
||||
onItemClick: handleItemClick,
|
||||
destroyOnHidden: mergedDestroyOnHidden
|
||||
}), children);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated The next major version will be removed
|
||||
*/
|
||||
const getNewChild = (child, index, props) => {
|
||||
if (!child) {
|
||||
return null;
|
||||
}
|
||||
const {
|
||||
prefixCls,
|
||||
accordion,
|
||||
collapsible,
|
||||
destroyOnHidden,
|
||||
onItemClick,
|
||||
activeKey,
|
||||
openMotion,
|
||||
expandIcon,
|
||||
classNames: collapseClassNames,
|
||||
styles
|
||||
} = props;
|
||||
const key = child.key || String(index);
|
||||
const {
|
||||
header,
|
||||
headerClass,
|
||||
destroyOnHidden: childDestroyOnHidden,
|
||||
collapsible: childCollapsible,
|
||||
onItemClick: childOnItemClick
|
||||
} = child.props;
|
||||
let isActive = false;
|
||||
if (accordion) {
|
||||
isActive = activeKey[0] === key;
|
||||
} else {
|
||||
isActive = activeKey.indexOf(key) > -1;
|
||||
}
|
||||
const mergeCollapsible = childCollapsible ?? collapsible;
|
||||
const handleItemClick = value => {
|
||||
if (mergeCollapsible === 'disabled') {
|
||||
return;
|
||||
}
|
||||
onItemClick(value);
|
||||
childOnItemClick?.(value);
|
||||
};
|
||||
const childProps = {
|
||||
key,
|
||||
panelKey: key,
|
||||
header,
|
||||
headerClass,
|
||||
classNames: collapseClassNames,
|
||||
styles,
|
||||
isActive,
|
||||
prefixCls,
|
||||
destroyOnHidden: childDestroyOnHidden ?? destroyOnHidden,
|
||||
openMotion,
|
||||
accordion,
|
||||
children: child.props.children,
|
||||
onItemClick: handleItemClick,
|
||||
expandIcon,
|
||||
collapsible: mergeCollapsible
|
||||
};
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/20479
|
||||
if (typeof child.type === 'string') {
|
||||
return child;
|
||||
}
|
||||
Object.keys(childProps).forEach(propName => {
|
||||
if (typeof childProps[propName] === 'undefined') {
|
||||
delete childProps[propName];
|
||||
}
|
||||
});
|
||||
return /*#__PURE__*/React.cloneElement(child, childProps);
|
||||
};
|
||||
function useItems(items, rawChildren, props) {
|
||||
if (Array.isArray(items)) {
|
||||
return convertItemsToNodes(items, props);
|
||||
}
|
||||
return toArray(rawChildren).map((child, index) => getNewChild(child, index, props));
|
||||
}
|
||||
export default useItems;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/// <reference types="react" />
|
||||
import Collapse from './Collapse';
|
||||
export type { CollapsePanelProps, CollapseProps } from './interface';
|
||||
export default Collapse;
|
||||
/**
|
||||
* @deprecated use `items` instead, will be removed in `v4.0.0`
|
||||
*/
|
||||
export declare const Panel: import("react").ForwardRefExoticComponent<import("./interface").CollapsePanelProps & import("react").RefAttributes<HTMLDivElement>>;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import Collapse from "./Collapse";
|
||||
export default Collapse;
|
||||
|
||||
/**
|
||||
* @deprecated use `items` instead, will be removed in `v4.0.0`
|
||||
*/
|
||||
export const {
|
||||
Panel
|
||||
} = Collapse;
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import type { CSSMotionProps } from '@rc-component/motion';
|
||||
import type * as React from 'react';
|
||||
export type CollapsibleType = 'header' | 'icon' | 'disabled';
|
||||
export interface ItemType extends Omit<CollapsePanelProps, 'header' | 'prefixCls' | 'panelKey' | 'isActive' | 'accordion' | 'openMotion' | 'expandIcon'> {
|
||||
key?: CollapsePanelProps['panelKey'];
|
||||
label?: CollapsePanelProps['header'];
|
||||
ref?: React.RefObject<HTMLDivElement>;
|
||||
}
|
||||
export interface CollapseProps {
|
||||
prefixCls?: string;
|
||||
activeKey?: React.Key | React.Key[];
|
||||
defaultActiveKey?: React.Key | React.Key[];
|
||||
openMotion?: CSSMotionProps;
|
||||
onChange?: (key: React.Key[]) => void;
|
||||
accordion?: boolean;
|
||||
className?: string;
|
||||
style?: object;
|
||||
destroyOnHidden?: boolean;
|
||||
expandIcon?: (props: object) => React.ReactNode;
|
||||
collapsible?: CollapsibleType;
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* Collapse items content
|
||||
* @since 3.6.0
|
||||
*/
|
||||
items?: ItemType[];
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
}
|
||||
export type SemanticName = 'header' | 'title' | 'body' | 'icon';
|
||||
export interface CollapsePanelProps extends React.DOMAttributes<HTMLDivElement> {
|
||||
id?: string;
|
||||
header?: React.ReactNode;
|
||||
prefixCls?: string;
|
||||
headerClass?: string;
|
||||
showArrow?: boolean;
|
||||
className?: string;
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
style?: object;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
isActive?: boolean;
|
||||
openMotion?: CSSMotionProps;
|
||||
destroyOnHidden?: boolean;
|
||||
accordion?: boolean;
|
||||
forceRender?: boolean;
|
||||
extra?: React.ReactNode;
|
||||
onItemClick?: (panelKey: React.Key) => void;
|
||||
expandIcon?: (props: object) => React.ReactNode;
|
||||
panelKey?: React.Key;
|
||||
role?: string;
|
||||
collapsible?: CollapsibleType;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {};
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import type { CollapseProps } from './interface';
|
||||
declare const _default: React.ForwardRefExoticComponent<CollapseProps & React.RefAttributes<HTMLDivElement>> & {
|
||||
/**
|
||||
* @deprecated use `items` instead, will be removed in `v4.0.0`
|
||||
*/
|
||||
Panel: React.ForwardRefExoticComponent<import("./interface").CollapsePanelProps & React.RefAttributes<HTMLDivElement>>;
|
||||
};
|
||||
export default _default;
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
||||
var _clsx = require("clsx");
|
||||
var _util = require("@rc-component/util");
|
||||
var _warning = _interopRequireDefault(require("@rc-component/util/lib/warning"));
|
||||
var _react = _interopRequireDefault(require("react"));
|
||||
var _useItems = _interopRequireDefault(require("./hooks/useItems"));
|
||||
var _Panel = _interopRequireDefault(require("./Panel"));
|
||||
var _pickAttrs = _interopRequireDefault(require("@rc-component/util/lib/pickAttrs"));
|
||||
function getActiveKeysArray(activeKey) {
|
||||
let currentActiveKey = activeKey;
|
||||
if (!Array.isArray(currentActiveKey)) {
|
||||
const activeKeyType = typeof currentActiveKey;
|
||||
currentActiveKey = activeKeyType === 'number' || activeKeyType === 'string' ? [currentActiveKey] : [];
|
||||
}
|
||||
return currentActiveKey.map(key => String(key));
|
||||
}
|
||||
const Collapse = /*#__PURE__*/_react.default.forwardRef((props, ref) => {
|
||||
const {
|
||||
prefixCls = 'rc-collapse',
|
||||
destroyOnHidden = false,
|
||||
style,
|
||||
accordion,
|
||||
className,
|
||||
children,
|
||||
collapsible,
|
||||
openMotion,
|
||||
expandIcon,
|
||||
activeKey: rawActiveKey,
|
||||
defaultActiveKey,
|
||||
onChange,
|
||||
items,
|
||||
classNames: customizeClassNames,
|
||||
styles
|
||||
} = props;
|
||||
const collapseClassName = (0, _clsx.clsx)(prefixCls, className);
|
||||
const [internalActiveKey, setActiveKey] = (0, _util.useControlledState)(defaultActiveKey, rawActiveKey);
|
||||
const activeKey = getActiveKeysArray(internalActiveKey);
|
||||
const triggerActiveKey = (0, _util.useEvent)(next => {
|
||||
const nextKeys = getActiveKeysArray(next);
|
||||
setActiveKey(nextKeys);
|
||||
onChange?.(nextKeys);
|
||||
});
|
||||
const onItemClick = key => {
|
||||
if (accordion) {
|
||||
triggerActiveKey(activeKey[0] === key ? [] : [key]);
|
||||
} else {
|
||||
triggerActiveKey(activeKey.includes(key) ? activeKey.filter(item => item !== key) : [...activeKey, key]);
|
||||
}
|
||||
};
|
||||
|
||||
// ======================== Children ========================
|
||||
(0, _warning.default)(!children, '[rc-collapse] `children` will be removed in next major version. Please use `items` instead.');
|
||||
const mergedChildren = (0, _useItems.default)(items, children, {
|
||||
prefixCls,
|
||||
accordion,
|
||||
openMotion,
|
||||
expandIcon,
|
||||
collapsible,
|
||||
destroyOnHidden,
|
||||
onItemClick,
|
||||
activeKey,
|
||||
classNames: customizeClassNames,
|
||||
styles
|
||||
});
|
||||
|
||||
// ======================== Render ========================
|
||||
return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({
|
||||
ref: ref,
|
||||
className: collapseClassName,
|
||||
style: style,
|
||||
role: accordion ? 'tablist' : undefined
|
||||
}, (0, _pickAttrs.default)(props, {
|
||||
aria: true,
|
||||
data: true
|
||||
})), mergedChildren);
|
||||
});
|
||||
var _default = exports.default = Object.assign(Collapse, {
|
||||
/**
|
||||
* @deprecated use `items` instead, will be removed in `v4.0.0`
|
||||
*/
|
||||
Panel: _Panel.default
|
||||
});
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import React from 'react';
|
||||
import type { CollapsePanelProps } from './interface';
|
||||
declare const CollapsePanel: React.ForwardRefExoticComponent<CollapsePanelProps & React.RefAttributes<HTMLDivElement>>;
|
||||
export default CollapsePanel;
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
||||
var _clsx = require("clsx");
|
||||
var _motion = _interopRequireDefault(require("@rc-component/motion"));
|
||||
var _KeyCode = _interopRequireDefault(require("@rc-component/util/lib/KeyCode"));
|
||||
var _react = _interopRequireDefault(require("react"));
|
||||
var _PanelContent = _interopRequireDefault(require("./PanelContent"));
|
||||
const CollapsePanel = /*#__PURE__*/_react.default.forwardRef((props, ref) => {
|
||||
const {
|
||||
showArrow = true,
|
||||
headerClass,
|
||||
isActive,
|
||||
onItemClick,
|
||||
forceRender,
|
||||
className,
|
||||
classNames: customizeClassNames = {},
|
||||
styles = {},
|
||||
prefixCls,
|
||||
collapsible,
|
||||
accordion,
|
||||
panelKey,
|
||||
extra,
|
||||
header,
|
||||
expandIcon,
|
||||
openMotion,
|
||||
destroyOnHidden,
|
||||
children,
|
||||
...resetProps
|
||||
} = props;
|
||||
const disabled = collapsible === 'disabled';
|
||||
const ifExtraExist = extra !== null && extra !== undefined && typeof extra !== 'boolean';
|
||||
const collapsibleProps = {
|
||||
onClick: () => {
|
||||
onItemClick?.(panelKey);
|
||||
},
|
||||
onKeyDown: e => {
|
||||
if (e.key === 'Enter' || e.keyCode === _KeyCode.default.ENTER || e.which === _KeyCode.default.ENTER) {
|
||||
onItemClick?.(panelKey);
|
||||
}
|
||||
},
|
||||
role: accordion ? 'tab' : 'button',
|
||||
['aria-expanded']: isActive,
|
||||
['aria-disabled']: disabled,
|
||||
tabIndex: disabled ? -1 : 0
|
||||
};
|
||||
|
||||
// ======================== Icon ========================
|
||||
const iconNodeInner = typeof expandIcon === 'function' ? expandIcon(props) : /*#__PURE__*/_react.default.createElement("i", {
|
||||
className: "arrow"
|
||||
});
|
||||
const iconNode = iconNodeInner && /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-expand-icon`, customizeClassNames?.icon),
|
||||
style: styles?.icon
|
||||
}, ['header', 'icon'].includes(collapsible) ? collapsibleProps : {}), iconNodeInner);
|
||||
const collapsePanelClassNames = (0, _clsx.clsx)(`${prefixCls}-item`, {
|
||||
[`${prefixCls}-item-active`]: isActive,
|
||||
[`${prefixCls}-item-disabled`]: disabled
|
||||
}, className);
|
||||
const headerClassName = (0, _clsx.clsx)(headerClass, `${prefixCls}-header`, {
|
||||
[`${prefixCls}-collapsible-${collapsible}`]: !!collapsible
|
||||
}, customizeClassNames?.header);
|
||||
|
||||
// ======================== HeaderProps ========================
|
||||
const headerProps = {
|
||||
className: headerClassName,
|
||||
style: styles?.header,
|
||||
...(['header', 'icon'].includes(collapsible) ? {} : collapsibleProps)
|
||||
};
|
||||
|
||||
// ======================== Render ========================
|
||||
return /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, resetProps, {
|
||||
ref: ref,
|
||||
className: collapsePanelClassNames
|
||||
}), /*#__PURE__*/_react.default.createElement("div", headerProps, showArrow && iconNode, /*#__PURE__*/_react.default.createElement("span", (0, _extends2.default)({
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-title`, customizeClassNames?.title),
|
||||
style: styles?.title
|
||||
}, collapsible === 'header' ? collapsibleProps : {}), header), ifExtraExist && /*#__PURE__*/_react.default.createElement("div", {
|
||||
className: `${prefixCls}-extra`
|
||||
}, extra)), /*#__PURE__*/_react.default.createElement(_motion.default, (0, _extends2.default)({
|
||||
visible: isActive,
|
||||
leavedClassName: `${prefixCls}-panel-hidden`
|
||||
}, openMotion, {
|
||||
forceRender: forceRender,
|
||||
removeOnLeave: destroyOnHidden
|
||||
}), ({
|
||||
className: motionClassName,
|
||||
style: motionStyle
|
||||
}, motionRef) => {
|
||||
return /*#__PURE__*/_react.default.createElement(_PanelContent.default, {
|
||||
ref: motionRef,
|
||||
prefixCls: prefixCls,
|
||||
className: motionClassName,
|
||||
classNames: customizeClassNames,
|
||||
style: motionStyle,
|
||||
styles: styles,
|
||||
isActive: isActive,
|
||||
forceRender: forceRender,
|
||||
role: accordion ? 'tabpanel' : undefined
|
||||
}, children);
|
||||
}));
|
||||
});
|
||||
var _default = exports.default = CollapsePanel;
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import React from 'react';
|
||||
import type { CollapsePanelProps } from './interface';
|
||||
declare const PanelContent: React.ForwardRefExoticComponent<Readonly<CollapsePanelProps> & {
|
||||
children?: React.ReactNode;
|
||||
} & React.RefAttributes<HTMLDivElement>>;
|
||||
export default PanelContent;
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _clsx = require("clsx");
|
||||
var _react = _interopRequireDefault(require("react"));
|
||||
const PanelContent = /*#__PURE__*/_react.default.forwardRef((props, ref) => {
|
||||
const {
|
||||
prefixCls,
|
||||
forceRender,
|
||||
className,
|
||||
style,
|
||||
children,
|
||||
isActive,
|
||||
role,
|
||||
classNames: customizeClassNames,
|
||||
styles
|
||||
} = props;
|
||||
const [rendered, setRendered] = _react.default.useState(isActive || forceRender);
|
||||
_react.default.useEffect(() => {
|
||||
if (forceRender || isActive) {
|
||||
setRendered(true);
|
||||
}
|
||||
}, [forceRender, isActive]);
|
||||
if (!rendered) {
|
||||
return null;
|
||||
}
|
||||
return /*#__PURE__*/_react.default.createElement("div", {
|
||||
ref: ref,
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-panel`, {
|
||||
[`${prefixCls}-panel-active`]: isActive,
|
||||
[`${prefixCls}-panel-inactive`]: !isActive
|
||||
}, className),
|
||||
style: style,
|
||||
role: role
|
||||
}, /*#__PURE__*/_react.default.createElement("div", {
|
||||
className: (0, _clsx.clsx)(`${prefixCls}-body`, customizeClassNames?.body),
|
||||
style: styles?.body
|
||||
}, children));
|
||||
});
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
PanelContent.displayName = 'PanelContent';
|
||||
}
|
||||
var _default = exports.default = PanelContent;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
import type { CollapsePanelProps, CollapseProps, ItemType } from '../interface';
|
||||
type Props = Pick<CollapsePanelProps, 'prefixCls' | 'onItemClick' | 'openMotion' | 'expandIcon' | 'classNames' | 'styles'> & Pick<CollapseProps, 'accordion' | 'collapsible' | 'destroyOnHidden'> & {
|
||||
activeKey: React.Key[];
|
||||
};
|
||||
declare function useItems(items?: ItemType[], rawChildren?: React.ReactNode, props?: Props): React.ReactElement<CollapsePanelProps>[];
|
||||
export default useItems;
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
||||
var _toArray = _interopRequireDefault(require("@rc-component/util/lib/Children/toArray"));
|
||||
var _react = _interopRequireDefault(require("react"));
|
||||
var _Panel = _interopRequireDefault(require("../Panel"));
|
||||
var _clsx = _interopRequireDefault(require("clsx"));
|
||||
function mergeSemantic(src, tgt, mergeFn) {
|
||||
if (!src || !tgt) {
|
||||
return src || tgt;
|
||||
}
|
||||
const keys = Array.from(new Set([...Object.keys(src), ...Object.keys(tgt)]));
|
||||
const result = {};
|
||||
keys.forEach(key => {
|
||||
result[key] = mergeFn(src[key], tgt[key]);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function mergeSemanticClassNames(src, tgt) {
|
||||
return mergeSemantic(src, tgt, (a, b) => (0, _clsx.default)(a, b));
|
||||
}
|
||||
function mergeSemanticStyles(src, tgt) {
|
||||
return mergeSemantic(src, tgt, (a, b) => ({
|
||||
...a,
|
||||
...b
|
||||
}));
|
||||
}
|
||||
const convertItemsToNodes = (items, props) => {
|
||||
const {
|
||||
prefixCls,
|
||||
accordion,
|
||||
collapsible,
|
||||
destroyOnHidden,
|
||||
onItemClick,
|
||||
activeKey,
|
||||
openMotion,
|
||||
expandIcon,
|
||||
classNames: collapseClassNames,
|
||||
styles: collapseStyles
|
||||
} = props;
|
||||
return items.map((item, index) => {
|
||||
const {
|
||||
children,
|
||||
label,
|
||||
key: rawKey,
|
||||
collapsible: rawCollapsible,
|
||||
onItemClick: rawOnItemClick,
|
||||
destroyOnHidden: rawDestroyOnHidden,
|
||||
classNames,
|
||||
styles,
|
||||
...restProps
|
||||
} = item;
|
||||
|
||||
// You may be puzzled why you want to convert them all into strings, me too.
|
||||
// Maybe: https://github.com/react-component/collapse/blob/aac303a8b6ff30e35060b4f8fecde6f4556fcbe2/src/Collapse.tsx#L15
|
||||
const key = String(rawKey ?? index);
|
||||
const mergeCollapsible = rawCollapsible ?? collapsible;
|
||||
const mergedDestroyOnHidden = rawDestroyOnHidden ?? destroyOnHidden;
|
||||
const handleItemClick = value => {
|
||||
if (mergeCollapsible === 'disabled') {
|
||||
return;
|
||||
}
|
||||
onItemClick(value);
|
||||
rawOnItemClick?.(value);
|
||||
};
|
||||
let isActive = false;
|
||||
if (accordion) {
|
||||
isActive = activeKey[0] === key;
|
||||
} else {
|
||||
isActive = activeKey.indexOf(key) > -1;
|
||||
}
|
||||
return /*#__PURE__*/_react.default.createElement(_Panel.default, (0, _extends2.default)({}, restProps, {
|
||||
classNames: mergeSemanticClassNames(collapseClassNames, classNames),
|
||||
styles: mergeSemanticStyles(collapseStyles, styles),
|
||||
prefixCls: prefixCls,
|
||||
key: key,
|
||||
panelKey: key,
|
||||
isActive: isActive,
|
||||
accordion: accordion,
|
||||
openMotion: openMotion,
|
||||
expandIcon: expandIcon,
|
||||
header: label,
|
||||
collapsible: mergeCollapsible,
|
||||
onItemClick: handleItemClick,
|
||||
destroyOnHidden: mergedDestroyOnHidden
|
||||
}), children);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated The next major version will be removed
|
||||
*/
|
||||
const getNewChild = (child, index, props) => {
|
||||
if (!child) {
|
||||
return null;
|
||||
}
|
||||
const {
|
||||
prefixCls,
|
||||
accordion,
|
||||
collapsible,
|
||||
destroyOnHidden,
|
||||
onItemClick,
|
||||
activeKey,
|
||||
openMotion,
|
||||
expandIcon,
|
||||
classNames: collapseClassNames,
|
||||
styles
|
||||
} = props;
|
||||
const key = child.key || String(index);
|
||||
const {
|
||||
header,
|
||||
headerClass,
|
||||
destroyOnHidden: childDestroyOnHidden,
|
||||
collapsible: childCollapsible,
|
||||
onItemClick: childOnItemClick
|
||||
} = child.props;
|
||||
let isActive = false;
|
||||
if (accordion) {
|
||||
isActive = activeKey[0] === key;
|
||||
} else {
|
||||
isActive = activeKey.indexOf(key) > -1;
|
||||
}
|
||||
const mergeCollapsible = childCollapsible ?? collapsible;
|
||||
const handleItemClick = value => {
|
||||
if (mergeCollapsible === 'disabled') {
|
||||
return;
|
||||
}
|
||||
onItemClick(value);
|
||||
childOnItemClick?.(value);
|
||||
};
|
||||
const childProps = {
|
||||
key,
|
||||
panelKey: key,
|
||||
header,
|
||||
headerClass,
|
||||
classNames: collapseClassNames,
|
||||
styles,
|
||||
isActive,
|
||||
prefixCls,
|
||||
destroyOnHidden: childDestroyOnHidden ?? destroyOnHidden,
|
||||
openMotion,
|
||||
accordion,
|
||||
children: child.props.children,
|
||||
onItemClick: handleItemClick,
|
||||
expandIcon,
|
||||
collapsible: mergeCollapsible
|
||||
};
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/20479
|
||||
if (typeof child.type === 'string') {
|
||||
return child;
|
||||
}
|
||||
Object.keys(childProps).forEach(propName => {
|
||||
if (typeof childProps[propName] === 'undefined') {
|
||||
delete childProps[propName];
|
||||
}
|
||||
});
|
||||
return /*#__PURE__*/_react.default.cloneElement(child, childProps);
|
||||
};
|
||||
function useItems(items, rawChildren, props) {
|
||||
if (Array.isArray(items)) {
|
||||
return convertItemsToNodes(items, props);
|
||||
}
|
||||
return (0, _toArray.default)(rawChildren).map((child, index) => getNewChild(child, index, props));
|
||||
}
|
||||
var _default = exports.default = useItems;
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/// <reference types="react" />
|
||||
import Collapse from './Collapse';
|
||||
export type { CollapsePanelProps, CollapseProps } from './interface';
|
||||
export default Collapse;
|
||||
/**
|
||||
* @deprecated use `items` instead, will be removed in `v4.0.0`
|
||||
*/
|
||||
export declare const Panel: import("react").ForwardRefExoticComponent<import("./interface").CollapsePanelProps & import("react").RefAttributes<HTMLDivElement>>;
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = exports.Panel = void 0;
|
||||
var _Collapse = _interopRequireDefault(require("./Collapse"));
|
||||
var _default = exports.default = _Collapse.default;
|
||||
/**
|
||||
* @deprecated use `items` instead, will be removed in `v4.0.0`
|
||||
*/
|
||||
const {
|
||||
Panel
|
||||
} = _Collapse.default;
|
||||
exports.Panel = Panel;
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import type { CSSMotionProps } from '@rc-component/motion';
|
||||
import type * as React from 'react';
|
||||
export type CollapsibleType = 'header' | 'icon' | 'disabled';
|
||||
export interface ItemType extends Omit<CollapsePanelProps, 'header' | 'prefixCls' | 'panelKey' | 'isActive' | 'accordion' | 'openMotion' | 'expandIcon'> {
|
||||
key?: CollapsePanelProps['panelKey'];
|
||||
label?: CollapsePanelProps['header'];
|
||||
ref?: React.RefObject<HTMLDivElement>;
|
||||
}
|
||||
export interface CollapseProps {
|
||||
prefixCls?: string;
|
||||
activeKey?: React.Key | React.Key[];
|
||||
defaultActiveKey?: React.Key | React.Key[];
|
||||
openMotion?: CSSMotionProps;
|
||||
onChange?: (key: React.Key[]) => void;
|
||||
accordion?: boolean;
|
||||
className?: string;
|
||||
style?: object;
|
||||
destroyOnHidden?: boolean;
|
||||
expandIcon?: (props: object) => React.ReactNode;
|
||||
collapsible?: CollapsibleType;
|
||||
children?: React.ReactNode;
|
||||
/**
|
||||
* Collapse items content
|
||||
* @since 3.6.0
|
||||
*/
|
||||
items?: ItemType[];
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
}
|
||||
export type SemanticName = 'header' | 'title' | 'body' | 'icon';
|
||||
export interface CollapsePanelProps extends React.DOMAttributes<HTMLDivElement> {
|
||||
id?: string;
|
||||
header?: React.ReactNode;
|
||||
prefixCls?: string;
|
||||
headerClass?: string;
|
||||
showArrow?: boolean;
|
||||
className?: string;
|
||||
classNames?: Partial<Record<SemanticName, string>>;
|
||||
style?: object;
|
||||
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
|
||||
isActive?: boolean;
|
||||
openMotion?: CSSMotionProps;
|
||||
destroyOnHidden?: boolean;
|
||||
accordion?: boolean;
|
||||
forceRender?: boolean;
|
||||
extra?: React.ReactNode;
|
||||
onItemClick?: (panelKey: React.Key) => void;
|
||||
expandIcon?: (props: object) => React.ReactNode;
|
||||
panelKey?: React.Key;
|
||||
role?: string;
|
||||
collapsible?: CollapsibleType;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"name": "@rc-component/collapse",
|
||||
"version": "1.2.0",
|
||||
"description": "rc-collapse ui component for react",
|
||||
"keywords": [
|
||||
"react",
|
||||
"react-component",
|
||||
"react-rc-collapse",
|
||||
"rc-collapse",
|
||||
"collapse",
|
||||
"accordion"
|
||||
],
|
||||
"homepage": "http://github.com/react-component/collapse",
|
||||
"bugs": {
|
||||
"url": "http://github.com/react-component/collapse/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:react-component/collapse.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "./lib/index",
|
||||
"module": "./es/index",
|
||||
"typings": "es/index.d.ts",
|
||||
"files": [
|
||||
"lib",
|
||||
"es",
|
||||
"assets/*.css"
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "father build && lessc assets/index.less assets/index.css",
|
||||
"coverage": "rc-test --coverage",
|
||||
"docs:build": "dumi build",
|
||||
"docs:deploy": "npm run docs:build && gh-pages -d dist",
|
||||
"lint": "eslint src/ --ext .ts,.tsx,.jsx,.js,.md",
|
||||
"prepare": "husky",
|
||||
"now-build": "npm run docs:build",
|
||||
"prepublishOnly": "npm run compile && rc-np",
|
||||
"prettier": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
||||
"postpublish": "npm run docs:deploy",
|
||||
"start": "dumi dev",
|
||||
"test": "rc-test"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*.{ts,tsx,js,jsx,json,md}": "npm run prettier"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.10.1",
|
||||
"@rc-component/motion": "^1.1.4",
|
||||
"@rc-component/util": "^1.3.0",
|
||||
"clsx": "^2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rc-component/father-plugin": "^2.0.1",
|
||||
"@rc-component/np": "^1.0.4",
|
||||
"@testing-library/jest-dom": "^6.1.4",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/node": "^24.2.0",
|
||||
"@types/react": "^19.1.4",
|
||||
"@types/react-dom": "^19.1.5",
|
||||
"@umijs/fabric": "^4.0.0",
|
||||
"dumi": "^2.1.1",
|
||||
"eslint": "^8.55.0",
|
||||
"eslint-plugin-jest": "^29.0.1",
|
||||
"eslint-plugin-unicorn": "^49.0.0",
|
||||
"father": "^4.1.3",
|
||||
"gh-pages": "^6.2.0",
|
||||
"husky": "^9.0.0",
|
||||
"jest": "^30.0.3",
|
||||
"less": "^4.2.0",
|
||||
"lint-staged": "^16.0.0",
|
||||
"prettier": "^3.0.3",
|
||||
"rc-test": "^7.0.14",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.0.0",
|
||||
"react-dom": ">=18.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user