@startupjs-ui/collapse 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/CollapseContent/index.cssx.styl +7 -0
- package/CollapseContent/index.tsx +57 -0
- package/CollapseHeader/index.cssx.styl +13 -0
- package/CollapseHeader/index.tsx +90 -0
- package/README.mdx +148 -0
- package/index.cssx.styl +5 -0
- package/index.d.ts +45 -0
- package/index.tsx +130 -0
- package/package.json +23 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
## [0.1.3](https://github.com/startupjs/startupjs-ui/compare/v0.1.2...v0.1.3) (2025-12-29)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @startupjs-ui/collapse
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [0.1.2](https://github.com/startupjs/startupjs-ui/compare/v0.1.1...v0.1.2) (2025-12-29)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* **collapse:** remove re-exports of subcomponents ([fd521e6](https://github.com/startupjs/startupjs-ui/commit/fd521e6c3509553c8ad231de09933a987b0c74f9))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* add mdx and docs packages. Refactor docs to get rid of any @startupjs/ui usage and use startupjs-ui instead ([703c926](https://github.com/startupjs/startupjs-ui/commit/703c92636efb0421ffd11783f692fc892b74018f))
|
|
25
|
+
* **collapse:** refactor Collapse component ([f43d6e5](https://github.com/startupjs/startupjs-ui/commit/f43d6e55cba1dd9d970125016a1069671a4e581b))
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React, { type ReactNode } from 'react'
|
|
2
|
+
import Collapsible from 'react-native-collapsible'
|
|
3
|
+
import { pug, observer } from 'startupjs'
|
|
4
|
+
import { themed } from '@startupjs-ui/core'
|
|
5
|
+
import Span from '@startupjs-ui/span'
|
|
6
|
+
import './index.cssx.styl'
|
|
7
|
+
|
|
8
|
+
export const _PropsJsonSchema = {/* CollapseContentProps */}
|
|
9
|
+
|
|
10
|
+
export interface CollapseContentProps {
|
|
11
|
+
/** Custom styles applied to the collapsible container */
|
|
12
|
+
style?: any
|
|
13
|
+
/** Content rendered inside the collapsible area */
|
|
14
|
+
children?: ReactNode
|
|
15
|
+
/** Whether the collapse is open (provided internally) */
|
|
16
|
+
open?: boolean
|
|
17
|
+
/** Collapse variant controlling paddings */
|
|
18
|
+
variant?: 'full' | 'pure'
|
|
19
|
+
/** Alignment of collapsed content */
|
|
20
|
+
align?: 'top' | 'center' | 'bottom'
|
|
21
|
+
/** Height when collapsed */
|
|
22
|
+
collapsedHeight?: number
|
|
23
|
+
/** Enable pointer events while collapsed */
|
|
24
|
+
enablePointerEvents?: boolean
|
|
25
|
+
/** Animation duration in ms */
|
|
26
|
+
duration?: number
|
|
27
|
+
/** Easing function or preset name */
|
|
28
|
+
easing?: ((value: number) => number) | string
|
|
29
|
+
/** Render children even when collapsed */
|
|
30
|
+
renderChildrenCollapsed?: boolean
|
|
31
|
+
/** Callback fired after collapse animation ends */
|
|
32
|
+
onAnimationEnd?: () => void
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function CollapseContent ({
|
|
36
|
+
style,
|
|
37
|
+
children,
|
|
38
|
+
open,
|
|
39
|
+
variant,
|
|
40
|
+
...props
|
|
41
|
+
}: CollapseContentProps): ReactNode {
|
|
42
|
+
const content = React.Children.map(children as any, (child: any, index: number): ReactNode => {
|
|
43
|
+
if (typeof child === 'string') {
|
|
44
|
+
return pug`
|
|
45
|
+
Span(key=index)= child
|
|
46
|
+
`
|
|
47
|
+
}
|
|
48
|
+
return child
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
return pug`
|
|
52
|
+
Collapsible.root(style=style styleName=[variant] collapsed=!open ...props)
|
|
53
|
+
= content
|
|
54
|
+
`
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default observer(themed('CollapseContent', CollapseContent))
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { useRef, type ReactNode } from 'react'
|
|
2
|
+
import { Animated, type StyleProp, type ViewStyle } from 'react-native'
|
|
3
|
+
import { pug, observer, useDidUpdate } from 'startupjs'
|
|
4
|
+
import { themed } from '@startupjs-ui/core'
|
|
5
|
+
import Div from '@startupjs-ui/div'
|
|
6
|
+
import Icon, { type IconProps } from '@startupjs-ui/icon'
|
|
7
|
+
import Span from '@startupjs-ui/span'
|
|
8
|
+
import { faCaretRight } from '@fortawesome/free-solid-svg-icons/faCaretRight'
|
|
9
|
+
import './index.cssx.styl'
|
|
10
|
+
|
|
11
|
+
export const _PropsJsonSchema = {/* CollapseHeaderProps */}
|
|
12
|
+
|
|
13
|
+
export interface CollapseHeaderProps {
|
|
14
|
+
/** Custom styles applied to the root view */
|
|
15
|
+
style?: StyleProp<ViewStyle>
|
|
16
|
+
/** Custom styles applied to the icon */
|
|
17
|
+
iconStyle?: IconProps['style']
|
|
18
|
+
/** Custom styles applied to the content container */
|
|
19
|
+
containerStyle?: StyleProp<ViewStyle>
|
|
20
|
+
/** Header content */
|
|
21
|
+
children?: ReactNode
|
|
22
|
+
/** Collapse variant controlling paddings */
|
|
23
|
+
variant?: 'full' | 'pure'
|
|
24
|
+
/** Icon position relative to the title @default 'left' */
|
|
25
|
+
iconPosition?: 'left' | 'right'
|
|
26
|
+
/** Icon displayed in header; true uses default caret @default true */
|
|
27
|
+
icon?: IconProps['icon'] | boolean
|
|
28
|
+
/** Whether the collapse is open (provided internally) */
|
|
29
|
+
open?: boolean
|
|
30
|
+
/** Press handler provided by Collapse */
|
|
31
|
+
onPress?: () => void
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function CollapseHeader ({
|
|
35
|
+
style,
|
|
36
|
+
iconStyle,
|
|
37
|
+
containerStyle,
|
|
38
|
+
children,
|
|
39
|
+
variant,
|
|
40
|
+
iconPosition = 'left',
|
|
41
|
+
icon = true,
|
|
42
|
+
open,
|
|
43
|
+
onPress,
|
|
44
|
+
...props
|
|
45
|
+
}: CollapseHeaderProps): ReactNode {
|
|
46
|
+
if (icon === true) icon = faCaretRight
|
|
47
|
+
const reverse = iconPosition === 'right'
|
|
48
|
+
const animation = useRef(new Animated.Value(open ? 1 : 0)).current
|
|
49
|
+
|
|
50
|
+
useDidUpdate(() => {
|
|
51
|
+
Animated.timing(
|
|
52
|
+
animation,
|
|
53
|
+
{
|
|
54
|
+
toValue: open ? 1 : 0,
|
|
55
|
+
duration: 250,
|
|
56
|
+
useNativeDriver: true
|
|
57
|
+
}
|
|
58
|
+
).start()
|
|
59
|
+
}, [open])
|
|
60
|
+
|
|
61
|
+
return pug`
|
|
62
|
+
Div.root(
|
|
63
|
+
row
|
|
64
|
+
style=style
|
|
65
|
+
styleName=[variant]
|
|
66
|
+
onPress=onPress
|
|
67
|
+
reverse=reverse
|
|
68
|
+
...props
|
|
69
|
+
)
|
|
70
|
+
if icon
|
|
71
|
+
Animated.View(
|
|
72
|
+
style={
|
|
73
|
+
transform: [{
|
|
74
|
+
rotate: animation.interpolate({
|
|
75
|
+
inputRange: [0, 1],
|
|
76
|
+
outputRange: [reverse ? '180deg' : '0deg', '90deg']
|
|
77
|
+
})
|
|
78
|
+
}]
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
Icon(icon=icon style=iconStyle)
|
|
82
|
+
Div.container(style=containerStyle styleName={reverse})
|
|
83
|
+
if typeof children === 'string'
|
|
84
|
+
Span= children
|
|
85
|
+
else
|
|
86
|
+
= children
|
|
87
|
+
`
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export default observer(themed('CollapseHeader', CollapseHeader))
|
package/README.mdx
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { $ } from 'startupjs'
|
|
2
|
+
import { useState } from 'react'
|
|
3
|
+
import { Sandbox } from '@startupjs-ui/docs'
|
|
4
|
+
import { faAngleRight } from '@fortawesome/free-solid-svg-icons'
|
|
5
|
+
import Collapse, { _PropsJsonSchema as CollapsePropsJsonSchema } from './index'
|
|
6
|
+
import { _PropsJsonSchema as CollapseHeaderPropsJsonSchema } from './CollapseHeader'
|
|
7
|
+
import { _PropsJsonSchema as CollapseContentPropsJsonSchema } from './CollapseContent'
|
|
8
|
+
import Div from '@startupjs-ui/div'
|
|
9
|
+
|
|
10
|
+
# Collapse
|
|
11
|
+
|
|
12
|
+
Inherits [react-native-collapsible](https://github.com/oblador/react-native-collapsible).
|
|
13
|
+
|
|
14
|
+
Collapse allows to toggle the visibility of content.
|
|
15
|
+
|
|
16
|
+
```jsx
|
|
17
|
+
import { Collapse } from 'startupjs-ui'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Simple example
|
|
21
|
+
|
|
22
|
+
```jsx example noscroll
|
|
23
|
+
const [open, setOpen] = useState(false)
|
|
24
|
+
return (
|
|
25
|
+
<Collapse title='Simple collapse' open={open} onChange={() => setOpen(!open)}>
|
|
26
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
|
27
|
+
</Collapse>
|
|
28
|
+
)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Pure collapse
|
|
32
|
+
|
|
33
|
+
Pure collapse does not contain any styles (background, paddings, etc.). It is useful when `Collapse` is used as a children of other components like `Card`. To make it pure, pass the string `pure` to the `variant` property.
|
|
34
|
+
|
|
35
|
+
```jsx example noscroll
|
|
36
|
+
const [open, setOpen] = useState(false)
|
|
37
|
+
return (
|
|
38
|
+
<Collapse
|
|
39
|
+
variant='pure'
|
|
40
|
+
open={open}
|
|
41
|
+
onChange={() => setOpen(!open)}
|
|
42
|
+
title='Pure collapse'
|
|
43
|
+
>
|
|
44
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
|
45
|
+
</Collapse>
|
|
46
|
+
)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Advanced usage
|
|
50
|
+
|
|
51
|
+
Collapse consists of two parts - `Header` and `Content`. These parts can be used to add custom markup, the `Header` is used instead of title and the `Content` is used instad of children. They can be used separately. Each part take value of `variant` prop from parent `Collapse` which can be overridden by passing `variant` to itself.
|
|
52
|
+
|
|
53
|
+
```jsx example noscroll
|
|
54
|
+
const [open, setOpen] = useState(false)
|
|
55
|
+
return (
|
|
56
|
+
<Collapse open={open} onChange={() => setOpen(!open)}>
|
|
57
|
+
<Collapse.Header iconPosition='right'>Advanced collapse</Collapse.Header>
|
|
58
|
+
<Collapse.Content>
|
|
59
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
|
60
|
+
</Collapse.Content>
|
|
61
|
+
</Collapse>
|
|
62
|
+
)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Icon configuration
|
|
66
|
+
|
|
67
|
+
You can provide a custom icon by specifying the `icon` option. It must be an arrow-like icon pointing right.
|
|
68
|
+
|
|
69
|
+
```jsx example
|
|
70
|
+
const [open, setOpen] = useState(false)
|
|
71
|
+
return (
|
|
72
|
+
<Collapse open={open} onChange={() => setOpen(!open)}>
|
|
73
|
+
<Collapse.Header icon={faAngleRight}>
|
|
74
|
+
Collapse with custom icon
|
|
75
|
+
</Collapse.Header>
|
|
76
|
+
<Collapse.Content>
|
|
77
|
+
Collapse content
|
|
78
|
+
</Collapse.Content>
|
|
79
|
+
</Collapse>
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### No Icon
|
|
84
|
+
|
|
85
|
+
You can remove an icon completely by specifying `icon={false}`
|
|
86
|
+
|
|
87
|
+
## Accordion
|
|
88
|
+
|
|
89
|
+
Using the `Collapse` component, you can create behavior like an accordion.
|
|
90
|
+
|
|
91
|
+
```jsx example noscroll
|
|
92
|
+
const [expand, setExpand] = useState()
|
|
93
|
+
const handleChange = (panel) => (shouldExpand) => {
|
|
94
|
+
setExpand(shouldExpand ? panel : null)
|
|
95
|
+
}
|
|
96
|
+
const collapseStyle = {
|
|
97
|
+
borderTopWidth: 1,
|
|
98
|
+
borderStyle: 'solid',
|
|
99
|
+
borderColor: '#ddd'
|
|
100
|
+
}
|
|
101
|
+
return (
|
|
102
|
+
<Div>
|
|
103
|
+
<Collapse
|
|
104
|
+
open={expand === 'open1'}
|
|
105
|
+
title='Accordion Header - 1'
|
|
106
|
+
onChange={handleChange('open1')}
|
|
107
|
+
>
|
|
108
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.
|
|
109
|
+
</Collapse>
|
|
110
|
+
<Collapse
|
|
111
|
+
style={collapseStyle}
|
|
112
|
+
open={expand === 'open2'}
|
|
113
|
+
title='Accordion Header - 2'
|
|
114
|
+
onChange={handleChange('open2')}
|
|
115
|
+
>
|
|
116
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.
|
|
117
|
+
</Collapse>
|
|
118
|
+
<Collapse
|
|
119
|
+
style={collapseStyle}
|
|
120
|
+
open={expand === 'open3'}
|
|
121
|
+
title='Accordion Header - 3'
|
|
122
|
+
onChange={handleChange('open3')}
|
|
123
|
+
>
|
|
124
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco.
|
|
125
|
+
</Collapse>
|
|
126
|
+
</Div>
|
|
127
|
+
)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Sandbox
|
|
131
|
+
|
|
132
|
+
### Collapse
|
|
133
|
+
|
|
134
|
+
<Sandbox
|
|
135
|
+
Component={Collapse}
|
|
136
|
+
props={{ $open: $.session.Props.Collapse.open }}
|
|
137
|
+
$props={$.session.Props.Collapse}
|
|
138
|
+
propsJsonSchema={CollapsePropsJsonSchema}
|
|
139
|
+
{...{ _comment: "HACK to make alive sandbox when user click on 'open' checkbox" }}
|
|
140
|
+
/>
|
|
141
|
+
|
|
142
|
+
### Collapse.Header
|
|
143
|
+
|
|
144
|
+
<Sandbox Component={Collapse.Header} propsJsonSchema={CollapseHeaderPropsJsonSchema} />
|
|
145
|
+
|
|
146
|
+
### Collapse.Content
|
|
147
|
+
|
|
148
|
+
<Sandbox Component={Collapse.Content} propsJsonSchema={CollapseContentPropsJsonSchema} />
|
package/index.cssx.styl
ADDED
package/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// DO NOT MODIFY THIS FILE - IT IS AUTOMATICALLY GENERATED ON COMMITS.
|
|
3
|
+
|
|
4
|
+
import { type ReactNode } from 'react';
|
|
5
|
+
import { type StyleProp, type ViewStyle } from 'react-native';
|
|
6
|
+
import { type DivProps } from '@startupjs-ui/div';
|
|
7
|
+
import { type CollapseHeaderProps } from './CollapseHeader';
|
|
8
|
+
import './index.cssx.styl';
|
|
9
|
+
export declare const _PropsJsonSchema: {};
|
|
10
|
+
export interface CollapseProps extends Omit<DivProps, 'style' | 'children' | 'variant' | 'align'> {
|
|
11
|
+
/** Custom styles applied to the root view */
|
|
12
|
+
style?: StyleProp<ViewStyle>;
|
|
13
|
+
/** Content rendered inside Collapse or via Collapse.Content */
|
|
14
|
+
children?: ReactNode;
|
|
15
|
+
/** Header title when no custom Collapse.Header is provided */
|
|
16
|
+
title?: ReactNode;
|
|
17
|
+
/** Controlled open state @default false */
|
|
18
|
+
open?: boolean;
|
|
19
|
+
/** Scoped model for open state */
|
|
20
|
+
$open?: any;
|
|
21
|
+
/** Visual appearance variant @default 'full' */
|
|
22
|
+
variant?: 'full' | 'pure';
|
|
23
|
+
/** Icon displayed in header; true uses default caret @default true */
|
|
24
|
+
icon?: CollapseHeaderProps['icon'];
|
|
25
|
+
/** Called when open state changes */
|
|
26
|
+
onChange?: (open: boolean) => void;
|
|
27
|
+
/** Custom styles applied to the collapsible container */
|
|
28
|
+
collapsibleContainerStyle?: StyleProp<ViewStyle>;
|
|
29
|
+
/** Alignment of collapsed content */
|
|
30
|
+
align?: 'top' | 'center' | 'bottom';
|
|
31
|
+
/** Height when collapsed */
|
|
32
|
+
collapsedHeight?: number;
|
|
33
|
+
/** Enable pointer events while collapsed */
|
|
34
|
+
enablePointerEvents?: boolean;
|
|
35
|
+
/** Animation duration in ms */
|
|
36
|
+
duration?: number;
|
|
37
|
+
/** Easing function or preset name */
|
|
38
|
+
easing?: ((value: number) => number) | string;
|
|
39
|
+
/** Render children even when collapsed */
|
|
40
|
+
renderChildrenCollapsed?: boolean;
|
|
41
|
+
/** Callback fired after collapse animation ends */
|
|
42
|
+
onAnimationEnd?: () => void;
|
|
43
|
+
}
|
|
44
|
+
declare const ObservedCollapse: any;
|
|
45
|
+
export default ObservedCollapse;
|
package/index.tsx
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { type ReactNode } from 'react'
|
|
2
|
+
import { type StyleProp, type ViewStyle } from 'react-native'
|
|
3
|
+
import { pug, observer, useBind } from 'startupjs'
|
|
4
|
+
import { themed } from '@startupjs-ui/core'
|
|
5
|
+
import Div, { type DivProps } from '@startupjs-ui/div'
|
|
6
|
+
import CollapseHeader, { type CollapseHeaderProps } from './CollapseHeader'
|
|
7
|
+
import CollapseContent from './CollapseContent'
|
|
8
|
+
import './index.cssx.styl'
|
|
9
|
+
|
|
10
|
+
export const _PropsJsonSchema = {/* CollapseProps */}
|
|
11
|
+
|
|
12
|
+
export interface CollapseProps extends Omit<DivProps, 'style' | 'children' | 'variant' | 'align'> {
|
|
13
|
+
/** Custom styles applied to the root view */
|
|
14
|
+
style?: StyleProp<ViewStyle>
|
|
15
|
+
/** Content rendered inside Collapse or via Collapse.Content */
|
|
16
|
+
children?: ReactNode
|
|
17
|
+
/** Header title when no custom Collapse.Header is provided */
|
|
18
|
+
title?: ReactNode
|
|
19
|
+
/** Controlled open state @default false */
|
|
20
|
+
open?: boolean
|
|
21
|
+
/** Scoped model for open state */
|
|
22
|
+
$open?: any
|
|
23
|
+
/** Visual appearance variant @default 'full' */
|
|
24
|
+
variant?: 'full' | 'pure'
|
|
25
|
+
/** Icon displayed in header; true uses default caret @default true */
|
|
26
|
+
icon?: CollapseHeaderProps['icon']
|
|
27
|
+
/** Called when open state changes */
|
|
28
|
+
onChange?: (open: boolean) => void
|
|
29
|
+
/** Custom styles applied to the collapsible container */
|
|
30
|
+
collapsibleContainerStyle?: StyleProp<ViewStyle>
|
|
31
|
+
/** Alignment of collapsed content */
|
|
32
|
+
align?: 'top' | 'center' | 'bottom'
|
|
33
|
+
/** Height when collapsed */
|
|
34
|
+
collapsedHeight?: number
|
|
35
|
+
/** Enable pointer events while collapsed */
|
|
36
|
+
enablePointerEvents?: boolean
|
|
37
|
+
/** Animation duration in ms */
|
|
38
|
+
duration?: number
|
|
39
|
+
/** Easing function or preset name */
|
|
40
|
+
easing?: ((value: number) => number) | string
|
|
41
|
+
/** Render children even when collapsed */
|
|
42
|
+
renderChildrenCollapsed?: boolean
|
|
43
|
+
/** Callback fired after collapse animation ends */
|
|
44
|
+
onAnimationEnd?: () => void
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function Collapse ({
|
|
48
|
+
style,
|
|
49
|
+
children,
|
|
50
|
+
title,
|
|
51
|
+
open = false,
|
|
52
|
+
$open,
|
|
53
|
+
variant = 'full',
|
|
54
|
+
icon = true,
|
|
55
|
+
onChange,
|
|
56
|
+
collapsibleContainerStyle,
|
|
57
|
+
align,
|
|
58
|
+
collapsedHeight,
|
|
59
|
+
enablePointerEvents,
|
|
60
|
+
duration,
|
|
61
|
+
easing,
|
|
62
|
+
renderChildrenCollapsed,
|
|
63
|
+
onAnimationEnd,
|
|
64
|
+
...props
|
|
65
|
+
}: CollapseProps): ReactNode {
|
|
66
|
+
;({ open, onChange } = useBind({ $open, open, onChange }) as any)
|
|
67
|
+
|
|
68
|
+
let header: ReactNode | undefined
|
|
69
|
+
let content: ReactNode | undefined
|
|
70
|
+
const contentChildren: ReactNode[] = []
|
|
71
|
+
|
|
72
|
+
React.Children.forEach(children as any, (child: any) => {
|
|
73
|
+
if (!child) return
|
|
74
|
+
|
|
75
|
+
switch (child.type) {
|
|
76
|
+
case CollapseHeader:
|
|
77
|
+
if (header) throw Error('[ui -> Collapse] You must specify a single <Collapse.Header>')
|
|
78
|
+
header = child
|
|
79
|
+
break
|
|
80
|
+
case CollapseContent:
|
|
81
|
+
if (content) throw Error('[ui -> Collapse] You must specify a single <Collapse.Content>')
|
|
82
|
+
content = child
|
|
83
|
+
break
|
|
84
|
+
default:
|
|
85
|
+
contentChildren.push(child as ReactNode)
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
if (content && contentChildren.length > 0) {
|
|
90
|
+
throw Error('[ui -> Collapse] React elements found directly within <Collapse>. ' +
|
|
91
|
+
'If <Collapse.Content> is specified, you have to put all your content inside it')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const contentProps = {
|
|
95
|
+
open,
|
|
96
|
+
variant,
|
|
97
|
+
style: collapsibleContainerStyle,
|
|
98
|
+
align,
|
|
99
|
+
collapsedHeight,
|
|
100
|
+
enablePointerEvents,
|
|
101
|
+
duration,
|
|
102
|
+
easing,
|
|
103
|
+
renderChildrenCollapsed,
|
|
104
|
+
onAnimationEnd
|
|
105
|
+
}
|
|
106
|
+
content = content
|
|
107
|
+
? React.cloneElement(content as any, { ...contentProps, ...(content as any).props })
|
|
108
|
+
: React.createElement(CollapseContent, contentProps, contentChildren)
|
|
109
|
+
|
|
110
|
+
const headerProps = { open, variant, icon, onPress }
|
|
111
|
+
header = header
|
|
112
|
+
? React.cloneElement(header as any, { ...headerProps, ...(header as any).props })
|
|
113
|
+
: React.createElement(CollapseHeader, headerProps, title ?? '')
|
|
114
|
+
|
|
115
|
+
function onPress () {
|
|
116
|
+
onChange?.(!open)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return pug`
|
|
120
|
+
Div.root(style=style ...props)
|
|
121
|
+
= header
|
|
122
|
+
= content
|
|
123
|
+
`
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const ObservedCollapse: any = observer(themed('Collapse', Collapse))
|
|
127
|
+
ObservedCollapse.Header = CollapseHeader
|
|
128
|
+
ObservedCollapse.Content = CollapseContent
|
|
129
|
+
|
|
130
|
+
export default ObservedCollapse
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@startupjs-ui/collapse",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"main": "index.tsx",
|
|
8
|
+
"types": "index.d.ts",
|
|
9
|
+
"type": "module",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@startupjs-ui/core": "^0.1.3",
|
|
12
|
+
"@startupjs-ui/div": "^0.1.3",
|
|
13
|
+
"@startupjs-ui/icon": "^0.1.3",
|
|
14
|
+
"@startupjs-ui/span": "^0.1.3",
|
|
15
|
+
"react-native-collapsible": "^1.6.2"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"react": "*",
|
|
19
|
+
"react-native": "*",
|
|
20
|
+
"startupjs": "*"
|
|
21
|
+
},
|
|
22
|
+
"gitHead": "fd964ebc3892d3dd0a6c85438c0af619cc50c3f0"
|
|
23
|
+
}
|