@toptal/picasso-collapse 1.0.1

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.
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { BaseProps, TransitionProps } from '@toptal/picasso-shared';
3
+ export interface Props extends TransitionProps, BaseProps {
4
+ children: React.ReactElement;
5
+ in?: boolean;
6
+ appear?: boolean;
7
+ unmountOnExit?: boolean;
8
+ onEnter?: (node: HTMLElement, isAppearing: boolean) => void;
9
+ }
10
+ export declare const Collapse: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLDivElement>>;
11
+ export default Collapse;
12
+ //# sourceMappingURL=Collapse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collapse.d.ts","sourceRoot":"","sources":["../../../src/Collapse/Collapse.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAA;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAIxE,MAAM,WAAW,KAAM,SAAQ,eAAe,EAAE,SAAS;IAEvD,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAA;IAE5B,EAAE,CAAC,EAAE,OAAO,CAAA;IAEZ,MAAM,CAAC,EAAE,OAAO,CAAA;IAEhB,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,KAAK,IAAI,CAAA;CAC5D;AAED,eAAO,MAAM,QAAQ,8EA+EpB,CAAA;AAED,eAAe,QAAQ,CAAA"}
@@ -0,0 +1,48 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React, { useRef, useState, forwardRef } from 'react';
13
+ import { Transition } from 'react-transition-group';
14
+ import { useMultipleForwardRefs } from '@toptal/picasso-utils';
15
+ import { twJoin } from 'tailwind-merge';
16
+ export const Collapse = forwardRef((_a, ref) => {
17
+ var { children, className, in: inProps = false, timeout = 350, unmountOnExit, style, appear, onExited: onExitedProp, 'data-testid': dataTestId } = _a, rest = __rest(_a, ["children", "className", "in", "timeout", "unmountOnExit", "style", "appear", "onExited", 'data-testid']);
18
+ const collapseRef = useRef(null);
19
+ const combinedRef = useMultipleForwardRefs([ref, collapseRef]);
20
+ const [height, setHeight] = useState();
21
+ const setToCurrentHeight = () => {
22
+ if (collapseRef.current) {
23
+ setHeight(collapseRef.current.scrollHeight);
24
+ }
25
+ };
26
+ const resetHeight = () => {
27
+ setHeight(0);
28
+ };
29
+ const onExited = (node) => {
30
+ resetHeight();
31
+ if (onExitedProp) {
32
+ onExitedProp(node);
33
+ }
34
+ };
35
+ return (React.createElement(Transition, Object.assign({ in: inProps, appear: appear, nodeRef: collapseRef, onEntering: setToCurrentHeight, unmountOnExit: unmountOnExit, onExit: setToCurrentHeight, onExiting: resetHeight, onExited: onExited, timeout: timeout }, rest), state => {
36
+ const currentHeight = height === 0 ? null : { maxHeight: height };
37
+ const isAnimating = state === 'entering' || state === 'exiting';
38
+ return (React.createElement("div", { className: twJoin([
39
+ isAnimating ? 'overflow-hidden max-h-0' : undefined,
40
+ state === 'exited' ? 'hidden' : undefined,
41
+ className,
42
+ ]), style: Object.assign(Object.assign(Object.assign({}, style), currentHeight), { transition: isAnimating
43
+ ? `max-height ${timeout}ms ease`
44
+ : undefined }), "data-testid": dataTestId, ref: combinedRef }, children));
45
+ }));
46
+ });
47
+ export default Collapse;
48
+ //# sourceMappingURL=Collapse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Collapse.js","sourceRoot":"","sources":["../../../src/Collapse/Collapse.tsx"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAEnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAevC,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAChC,CACE,EAWC,EACD,GAAG,EACH,EAAE;QAbF,EACE,QAAQ,EACR,SAAS,EACT,EAAE,EAAE,OAAO,GAAG,KAAK,EACnB,OAAO,GAAG,GAAG,EACb,aAAa,EACb,KAAK,EACL,MAAM,EACN,QAAQ,EAAE,YAAY,EACtB,aAAa,EAAE,UAAU,OAE1B,EADI,IAAI,cAVT,yGAWC,CADQ;IAIT,MAAM,WAAW,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAChD,MAAM,WAAW,GAAG,sBAAsB,CAAC,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAA;IAE9D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,EAAU,CAAA;IAE9C,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,IAAI,WAAW,CAAC,OAAO,EAAE;YACvB,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;SAC5C;IACH,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,SAAS,CAAC,CAAC,CAAC,CAAA;IACd,CAAC,CAAA;IAED,MAAM,QAAQ,GAAG,CAAC,IAAiB,EAAE,EAAE;QACrC,WAAW,EAAE,CAAA;QACb,IAAI,YAAY,EAAE;YAChB,YAAY,CAAC,IAAI,CAAC,CAAA;SACnB;IACH,CAAC,CAAA;IAED,OAAO,CACL,oBAAC,UAAU,kBACT,EAAE,EAAE,OAAO,EACX,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,kBAAkB,EAC9B,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,kBAAkB,EAC1B,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,IACZ,IAAI,GAEP,KAAK,CAAC,EAAE;QACP,MAAM,aAAa,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAA;QACjE,MAAM,WAAW,GAAG,KAAK,KAAK,UAAU,IAAI,KAAK,KAAK,SAAS,CAAA;QAE/D,OAAO,CACL,6BACE,SAAS,EAAE,MAAM,CAAC;gBAChB,WAAW,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,SAAS;gBACnD,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBACzC,SAAS;aACV,CAAC,EACF,KAAK,gDACA,KAAK,GACL,aAAa,KAChB,UAAU,EAAE,WAAW;oBACrB,CAAC,CAAC,cAAc,OAAO,SAAS;oBAChC,CAAC,CAAC,SAAS,oBAEF,UAAU,EACvB,GAAG,EAAE,WAAW,IAEf,QAAQ,CACL,CACP,CAAA;IACH,CAAC,CACU,CACd,CAAA;AACH,CAAC,CACF,CAAA;AAED,eAAe,QAAQ,CAAA"}
@@ -0,0 +1,5 @@
1
+ import type { OmitInternalProps } from '@toptal/picasso-shared';
2
+ import type { Props } from './Collapse';
3
+ export { default as Collapse } from './Collapse';
4
+ export declare type FadeProps = OmitInternalProps<Props>;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Collapse/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAE/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAA;AAChD,oBAAY,SAAS,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { default as Collapse } from './Collapse';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/Collapse/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './Collapse';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './Collapse';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA"}
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@toptal/picasso-collapse",
3
+ "version": "1.0.1",
4
+ "description": "Toptal UI components library - Collapse",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "main": "./dist-package/src/index.js",
9
+ "module": "./dist-package/src/index.js",
10
+ "scripts": {
11
+ "build:package": "tsc -b tsconfig.json",
12
+ "prepublishOnly": "yarn build:package"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/toptal/picasso.git"
17
+ },
18
+ "author": "Toptal",
19
+ "license": "MIT",
20
+ "bugs": {
21
+ "url": "https://github.com/toptal/picasso/issues"
22
+ },
23
+ "homepage": "https://github.com/toptal/picasso/tree/master/packages/picasso#readme",
24
+ "dependencies": {
25
+ "@toptal/picasso-utils": "1.0.2",
26
+ "tailwind-merge": "^2.2.2",
27
+ "react-transition-group": "^4.4.5"
28
+ },
29
+ "sideEffects": false,
30
+ "peerDependencies": {
31
+ "@toptal/picasso-tailwind": ">2.1.0",
32
+ "react": ">=16.12.0 < 19.0.0",
33
+ "tailwindcss": ">=3"
34
+ },
35
+ "exports": {
36
+ ".": "./dist-package/src/index.js"
37
+ },
38
+ "devDependencies": {
39
+ "@toptal/picasso-test-utils": "1.1.0"
40
+ },
41
+ "files": [
42
+ "dist-package/**",
43
+ "!dist-package/tsconfig.tsbuildinfo",
44
+ "src"
45
+ ]
46
+ }
@@ -0,0 +1,101 @@
1
+ import React, { useRef, useState, forwardRef } from 'react'
2
+ import { Transition } from 'react-transition-group'
3
+ import type { BaseProps, TransitionProps } from '@toptal/picasso-shared'
4
+ import { useMultipleForwardRefs } from '@toptal/picasso-utils'
5
+ import { twJoin } from 'tailwind-merge'
6
+
7
+ export interface Props extends TransitionProps, BaseProps {
8
+ /* Element that accepts ref */
9
+ children: React.ReactElement
10
+ /* Show the component; triggers the enter or exit states */
11
+ in?: boolean
12
+ /* Trigger the transition on the first mount, regardless of the `in` prop. */
13
+ appear?: boolean
14
+ /* Unmount the component on exit */
15
+ unmountOnExit?: boolean
16
+ /* Callback fired when the component has entered */
17
+ onEnter?: (node: HTMLElement, isAppearing: boolean) => void
18
+ }
19
+
20
+ export const Collapse = forwardRef<HTMLDivElement, Props>(
21
+ (
22
+ {
23
+ children,
24
+ className,
25
+ in: inProps = false,
26
+ timeout = 350,
27
+ unmountOnExit,
28
+ style,
29
+ appear,
30
+ onExited: onExitedProp,
31
+ 'data-testid': dataTestId,
32
+ ...rest
33
+ },
34
+ ref
35
+ ) => {
36
+ const collapseRef = useRef<HTMLDivElement>(null)
37
+ const combinedRef = useMultipleForwardRefs([ref, collapseRef])
38
+
39
+ const [height, setHeight] = useState<number>()
40
+
41
+ const setToCurrentHeight = () => {
42
+ if (collapseRef.current) {
43
+ setHeight(collapseRef.current.scrollHeight)
44
+ }
45
+ }
46
+
47
+ const resetHeight = () => {
48
+ setHeight(0)
49
+ }
50
+
51
+ const onExited = (node: HTMLElement) => {
52
+ resetHeight()
53
+ if (onExitedProp) {
54
+ onExitedProp(node)
55
+ }
56
+ }
57
+
58
+ return (
59
+ <Transition
60
+ in={inProps}
61
+ appear={appear}
62
+ nodeRef={collapseRef}
63
+ onEntering={setToCurrentHeight}
64
+ unmountOnExit={unmountOnExit}
65
+ onExit={setToCurrentHeight}
66
+ onExiting={resetHeight}
67
+ onExited={onExited}
68
+ timeout={timeout}
69
+ {...rest}
70
+ >
71
+ {state => {
72
+ const currentHeight = height === 0 ? null : { maxHeight: height }
73
+ const isAnimating = state === 'entering' || state === 'exiting'
74
+
75
+ return (
76
+ <div
77
+ className={twJoin([
78
+ isAnimating ? 'overflow-hidden max-h-0' : undefined,
79
+ state === 'exited' ? 'hidden' : undefined,
80
+ className,
81
+ ])}
82
+ style={{
83
+ ...style,
84
+ ...currentHeight,
85
+ transition: isAnimating
86
+ ? `max-height ${timeout}ms ease`
87
+ : undefined,
88
+ }}
89
+ data-testid={dataTestId}
90
+ ref={combinedRef}
91
+ >
92
+ {children}
93
+ </div>
94
+ )
95
+ }}
96
+ </Transition>
97
+ )
98
+ }
99
+ )
100
+
101
+ export default Collapse
@@ -0,0 +1,6 @@
1
+ import type { OmitInternalProps } from '@toptal/picasso-shared'
2
+
3
+ import type { Props } from './Collapse'
4
+
5
+ export { default as Collapse } from './Collapse'
6
+ export type FadeProps = OmitInternalProps<Props>
@@ -0,0 +1,22 @@
1
+ import { Container, Button } from '@toptal/picasso'
2
+ import { Collapse } from '@toptal/picasso-collapse'
3
+ import React, { useState } from 'react'
4
+
5
+ const Example = () => {
6
+ const [faded, setFaded] = useState(false)
7
+
8
+ const handleOnClick = () => setFaded(prevFaded => !prevFaded)
9
+
10
+ return (
11
+ <Container>
12
+ <Button onClick={handleOnClick} className='mb-4'>
13
+ Toggle Collapse
14
+ </Button>
15
+ <Collapse in={faded} timeout={400}>
16
+ <div className='bg-gray-100 p-4 rounded-md'>Collapse content</div>
17
+ </Collapse>
18
+ </Container>
19
+ )
20
+ }
21
+
22
+ export default Example
@@ -0,0 +1,18 @@
1
+ import { Collapse } from '../Collapse'
2
+ import PicassoBook from '~/.storybook/components/PicassoBook'
3
+
4
+ const page = PicassoBook.section('Transitions').createPage('Collapse')
5
+
6
+ page.createTabChapter('Props').addComponentDocs({
7
+ component: Collapse,
8
+ name: 'Collapse',
9
+ })
10
+
11
+ page.createChapter().addExample(
12
+ 'Collapse/story/Default.example.tsx',
13
+ {
14
+ title: 'Default',
15
+ takeScreenshot: false,
16
+ },
17
+ 'base/Collapse'
18
+ )
@@ -0,0 +1,53 @@
1
+ import React from 'react'
2
+ import { act, cleanup, render } from '@toptal/picasso-test-utils'
3
+
4
+ import Collapse from './Collapse'
5
+
6
+ const SomeChildComponent = React.forwardRef<HTMLDivElement>((props, ref) => (
7
+ <div ref={ref} data-testid='child-div' {...props}>
8
+ Hello, I'm child div!
9
+ </div>
10
+ ))
11
+
12
+ describe('Collapse', () => {
13
+ beforeEach(() => {
14
+ jest.useFakeTimers()
15
+ })
16
+
17
+ afterEach(() => {
18
+ cleanup()
19
+ jest.useRealTimers()
20
+ })
21
+
22
+ it('transitions based on the `in` prop', () => {
23
+ const { getByTestId, rerender } = render(
24
+ <Collapse in={false} data-testid='collapse'>
25
+ <SomeChildComponent />
26
+ </Collapse>
27
+ )
28
+
29
+ expect(getByTestId('collapse')).toHaveClass('hidden')
30
+
31
+ act(() => {
32
+ rerender(
33
+ <Collapse in={true} data-testid='collapse'>
34
+ <SomeChildComponent />
35
+ </Collapse>
36
+ )
37
+ jest.runAllTimers()
38
+ })
39
+
40
+ expect(getByTestId('collapse')).toHaveStyle('display: block')
41
+ })
42
+
43
+ it('forwards the ref', () => {
44
+ const ref = React.createRef<HTMLDivElement>()
45
+ const { getByTestId } = render(
46
+ <Collapse in={true} ref={ref} data-testid='collapse'>
47
+ <SomeChildComponent />
48
+ </Collapse>
49
+ )
50
+
51
+ expect(ref.current).toBe(getByTestId('collapse'))
52
+ })
53
+ })
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './Collapse'