@festo-ui/react 7.0.0-dev.395 → 7.0.0
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/lib/components/bottom-sheet/BottomSheet.d.ts +12 -0
- package/lib/components/bottom-sheet/BottomSheet.js +95 -0
- package/lib/components/bottom-sheet/BottomSheet.stories.d.ts +9 -0
- package/lib/components/bottom-sheet/BottomSheet.stories.js +51 -0
- package/node/lib/components/bottom-sheet/BottomSheet.js +101 -0
- package/node/lib/components/bottom-sheet/BottomSheet.stories.js +56 -0
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
interface BottomSheetProps {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
defaultExpanded?: boolean;
|
|
5
|
+
open?: boolean;
|
|
6
|
+
expandFrom?: 'center' | 'bottom';
|
|
7
|
+
hasBackdrop?: boolean;
|
|
8
|
+
hideCloseIcon?: boolean;
|
|
9
|
+
onOpenChange?: (value: boolean) => void;
|
|
10
|
+
}
|
|
11
|
+
export default function BottomSheet({ children, open, defaultExpanded, expandFrom, hasBackdrop, hideCloseIcon, onOpenChange, }: BottomSheetProps): JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
2
|
+
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
3
|
+
import cn from 'classnames';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
8
|
+
export default function BottomSheet(_ref) {
|
|
9
|
+
let {
|
|
10
|
+
children,
|
|
11
|
+
open,
|
|
12
|
+
defaultExpanded,
|
|
13
|
+
expandFrom = 'center',
|
|
14
|
+
hasBackdrop = true,
|
|
15
|
+
hideCloseIcon,
|
|
16
|
+
onOpenChange
|
|
17
|
+
} = _ref;
|
|
18
|
+
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
19
|
+
const [isClosing, setClosing] = useState(false);
|
|
20
|
+
const [startY, setStartY] = useState(0);
|
|
21
|
+
const [swiping, setSwiping] = useState(false);
|
|
22
|
+
function toggleExpand() {
|
|
23
|
+
const newExpanded = !expanded;
|
|
24
|
+
setExpanded(newExpanded);
|
|
25
|
+
}
|
|
26
|
+
function closeBottomSheet() {
|
|
27
|
+
setClosing(true);
|
|
28
|
+
setExpanded(defaultExpanded);
|
|
29
|
+
setTimeout(() => {
|
|
30
|
+
setClosing(false);
|
|
31
|
+
onOpenChange?.(false);
|
|
32
|
+
}, 300);
|
|
33
|
+
}
|
|
34
|
+
const handleTouchStart = event => {
|
|
35
|
+
setStartY(event.touches[0].clientY);
|
|
36
|
+
setSwiping(true);
|
|
37
|
+
};
|
|
38
|
+
const handleTouchMove = event => {
|
|
39
|
+
if (!swiping) return;
|
|
40
|
+
const currentY = event.touches[0].clientY;
|
|
41
|
+
const deltaY = currentY - startY;
|
|
42
|
+
if (deltaY < -50 && !expanded) {
|
|
43
|
+
// swipe up to expand
|
|
44
|
+
setExpanded(true);
|
|
45
|
+
setSwiping(false);
|
|
46
|
+
} else if (deltaY > 50 && expanded) {
|
|
47
|
+
// swipe down to collapse
|
|
48
|
+
setExpanded(false);
|
|
49
|
+
setSwiping(false);
|
|
50
|
+
} else if (deltaY > 100 && !expanded) {
|
|
51
|
+
// swipe down to close
|
|
52
|
+
closeBottomSheet();
|
|
53
|
+
setSwiping(false);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
57
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
58
|
+
className: cn('fwe-bottom-sheet-backdrop', {
|
|
59
|
+
'fwe-bottom-sheet-backdrop--visible': hasBackdrop && open && !isClosing
|
|
60
|
+
}),
|
|
61
|
+
onClick: closeBottomSheet
|
|
62
|
+
}), /*#__PURE__*/_jsxs("div", {
|
|
63
|
+
className: cn('fwe-bottom-sheet-container', {
|
|
64
|
+
'fwe-bottom-sheet-container--open': open,
|
|
65
|
+
'fwe-bottom-sheet-container--expanded': expanded,
|
|
66
|
+
'fwe-bottom-sheet-container--expand-from-center': expandFrom === 'center',
|
|
67
|
+
'fwe-bottom-sheet-container--with-backdrop': hasBackdrop,
|
|
68
|
+
'fwe-bottom-sheet-container--closing': isClosing
|
|
69
|
+
}),
|
|
70
|
+
onTouchStart: handleTouchStart,
|
|
71
|
+
onTouchMove: handleTouchMove,
|
|
72
|
+
children: [/*#__PURE__*/_jsxs("div", {
|
|
73
|
+
className: "fwe-bottom-sheet-header",
|
|
74
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
75
|
+
className: "fwe-bottom-sheet-drag-handle-container",
|
|
76
|
+
onClick: toggleExpand,
|
|
77
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
78
|
+
className: "fwe-bottom-sheet-drag-handle"
|
|
79
|
+
})
|
|
80
|
+
}), !hideCloseIcon && /*#__PURE__*/_jsx("button", {
|
|
81
|
+
type: "button",
|
|
82
|
+
className: "fwe-bottom-sheet-close-btn",
|
|
83
|
+
onClick: closeBottomSheet,
|
|
84
|
+
children: /*#__PURE__*/_jsx("span", {
|
|
85
|
+
className: "fwe-sr-only",
|
|
86
|
+
children: "Close"
|
|
87
|
+
})
|
|
88
|
+
})]
|
|
89
|
+
}), /*#__PURE__*/_jsx("div", {
|
|
90
|
+
className: "fwe-bottom-sheet-content",
|
|
91
|
+
children: children
|
|
92
|
+
})]
|
|
93
|
+
})]
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import BottomSheet from './BottomSheet';
|
|
3
|
+
declare const meta: Meta<typeof BottomSheet>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof BottomSheet>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const WithoutBackdrop: Story;
|
|
8
|
+
export declare const ExpandFromBottom: Story;
|
|
9
|
+
export declare const WithoutCloseIcon: Story;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import BottomSheet from './BottomSheet';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
5
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
+
const meta = {
|
|
7
|
+
component: BottomSheet,
|
|
8
|
+
title: 'Components/Bottom Sheet',
|
|
9
|
+
decorators: [Story => /*#__PURE__*/_jsx("div", {
|
|
10
|
+
style: {
|
|
11
|
+
minHeight: 600
|
|
12
|
+
},
|
|
13
|
+
children: /*#__PURE__*/_jsx(Story, {})
|
|
14
|
+
})]
|
|
15
|
+
};
|
|
16
|
+
export default meta;
|
|
17
|
+
export const Default = {
|
|
18
|
+
render: args => {
|
|
19
|
+
const [open, setOpen] = useState(false);
|
|
20
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
21
|
+
children: [/*#__PURE__*/_jsx("button", {
|
|
22
|
+
type: "button",
|
|
23
|
+
className: "fwe-btn",
|
|
24
|
+
onClick: () => setOpen(true),
|
|
25
|
+
children: "Open"
|
|
26
|
+
}), /*#__PURE__*/_jsx(BottomSheet, {
|
|
27
|
+
...args,
|
|
28
|
+
open: open,
|
|
29
|
+
onOpenChange: setOpen
|
|
30
|
+
})]
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export const WithoutBackdrop = {
|
|
35
|
+
args: {
|
|
36
|
+
hasBackdrop: false
|
|
37
|
+
},
|
|
38
|
+
render: Default.render
|
|
39
|
+
};
|
|
40
|
+
export const ExpandFromBottom = {
|
|
41
|
+
args: {
|
|
42
|
+
expandFrom: 'bottom'
|
|
43
|
+
},
|
|
44
|
+
render: Default.render
|
|
45
|
+
};
|
|
46
|
+
export const WithoutCloseIcon = {
|
|
47
|
+
args: {
|
|
48
|
+
hideCloseIcon: true
|
|
49
|
+
},
|
|
50
|
+
render: Default.render
|
|
51
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = BottomSheet;
|
|
7
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
12
|
+
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
13
|
+
|
|
14
|
+
function BottomSheet(_ref) {
|
|
15
|
+
let {
|
|
16
|
+
children,
|
|
17
|
+
open,
|
|
18
|
+
defaultExpanded,
|
|
19
|
+
expandFrom = 'center',
|
|
20
|
+
hasBackdrop = true,
|
|
21
|
+
hideCloseIcon,
|
|
22
|
+
onOpenChange
|
|
23
|
+
} = _ref;
|
|
24
|
+
const [expanded, setExpanded] = (0, _react.useState)(defaultExpanded);
|
|
25
|
+
const [isClosing, setClosing] = (0, _react.useState)(false);
|
|
26
|
+
const [startY, setStartY] = (0, _react.useState)(0);
|
|
27
|
+
const [swiping, setSwiping] = (0, _react.useState)(false);
|
|
28
|
+
function toggleExpand() {
|
|
29
|
+
const newExpanded = !expanded;
|
|
30
|
+
setExpanded(newExpanded);
|
|
31
|
+
}
|
|
32
|
+
function closeBottomSheet() {
|
|
33
|
+
setClosing(true);
|
|
34
|
+
setExpanded(defaultExpanded);
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
setClosing(false);
|
|
37
|
+
onOpenChange?.(false);
|
|
38
|
+
}, 300);
|
|
39
|
+
}
|
|
40
|
+
const handleTouchStart = event => {
|
|
41
|
+
setStartY(event.touches[0].clientY);
|
|
42
|
+
setSwiping(true);
|
|
43
|
+
};
|
|
44
|
+
const handleTouchMove = event => {
|
|
45
|
+
if (!swiping) return;
|
|
46
|
+
const currentY = event.touches[0].clientY;
|
|
47
|
+
const deltaY = currentY - startY;
|
|
48
|
+
if (deltaY < -50 && !expanded) {
|
|
49
|
+
// swipe up to expand
|
|
50
|
+
setExpanded(true);
|
|
51
|
+
setSwiping(false);
|
|
52
|
+
} else if (deltaY > 50 && expanded) {
|
|
53
|
+
// swipe down to collapse
|
|
54
|
+
setExpanded(false);
|
|
55
|
+
setSwiping(false);
|
|
56
|
+
} else if (deltaY > 100 && !expanded) {
|
|
57
|
+
// swipe down to close
|
|
58
|
+
closeBottomSheet();
|
|
59
|
+
setSwiping(false);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
63
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
64
|
+
className: (0, _classnames.default)('fwe-bottom-sheet-backdrop', {
|
|
65
|
+
'fwe-bottom-sheet-backdrop--visible': hasBackdrop && open && !isClosing
|
|
66
|
+
}),
|
|
67
|
+
onClick: closeBottomSheet
|
|
68
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
69
|
+
className: (0, _classnames.default)('fwe-bottom-sheet-container', {
|
|
70
|
+
'fwe-bottom-sheet-container--open': open,
|
|
71
|
+
'fwe-bottom-sheet-container--expanded': expanded,
|
|
72
|
+
'fwe-bottom-sheet-container--expand-from-center': expandFrom === 'center',
|
|
73
|
+
'fwe-bottom-sheet-container--with-backdrop': hasBackdrop,
|
|
74
|
+
'fwe-bottom-sheet-container--closing': isClosing
|
|
75
|
+
}),
|
|
76
|
+
onTouchStart: handleTouchStart,
|
|
77
|
+
onTouchMove: handleTouchMove,
|
|
78
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
79
|
+
className: "fwe-bottom-sheet-header",
|
|
80
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
81
|
+
className: "fwe-bottom-sheet-drag-handle-container",
|
|
82
|
+
onClick: toggleExpand,
|
|
83
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
84
|
+
className: "fwe-bottom-sheet-drag-handle"
|
|
85
|
+
})
|
|
86
|
+
}), !hideCloseIcon && /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
|
|
87
|
+
type: "button",
|
|
88
|
+
className: "fwe-bottom-sheet-close-btn",
|
|
89
|
+
onClick: closeBottomSheet,
|
|
90
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
91
|
+
className: "fwe-sr-only",
|
|
92
|
+
children: "Close"
|
|
93
|
+
})
|
|
94
|
+
})]
|
|
95
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
96
|
+
className: "fwe-bottom-sheet-content",
|
|
97
|
+
children: children
|
|
98
|
+
})]
|
|
99
|
+
})]
|
|
100
|
+
});
|
|
101
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.WithoutCloseIcon = exports.WithoutBackdrop = exports.ExpandFromBottom = exports.Default = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _BottomSheet = _interopRequireDefault(require("./BottomSheet"));
|
|
9
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
const meta = {
|
|
12
|
+
component: _BottomSheet.default,
|
|
13
|
+
title: 'Components/Bottom Sheet',
|
|
14
|
+
decorators: [Story => /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
15
|
+
style: {
|
|
16
|
+
minHeight: 600
|
|
17
|
+
},
|
|
18
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Story, {})
|
|
19
|
+
})]
|
|
20
|
+
};
|
|
21
|
+
var _default = exports.default = meta;
|
|
22
|
+
const Default = exports.Default = {
|
|
23
|
+
render: args => {
|
|
24
|
+
const [open, setOpen] = (0, _react.useState)(false);
|
|
25
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
26
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
|
|
27
|
+
type: "button",
|
|
28
|
+
className: "fwe-btn",
|
|
29
|
+
onClick: () => setOpen(true),
|
|
30
|
+
children: "Open"
|
|
31
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_BottomSheet.default, {
|
|
32
|
+
...args,
|
|
33
|
+
open: open,
|
|
34
|
+
onOpenChange: setOpen
|
|
35
|
+
})]
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const WithoutBackdrop = exports.WithoutBackdrop = {
|
|
40
|
+
args: {
|
|
41
|
+
hasBackdrop: false
|
|
42
|
+
},
|
|
43
|
+
render: Default.render
|
|
44
|
+
};
|
|
45
|
+
const ExpandFromBottom = exports.ExpandFromBottom = {
|
|
46
|
+
args: {
|
|
47
|
+
expandFrom: 'bottom'
|
|
48
|
+
},
|
|
49
|
+
render: Default.render
|
|
50
|
+
};
|
|
51
|
+
const WithoutCloseIcon = exports.WithoutCloseIcon = {
|
|
52
|
+
args: {
|
|
53
|
+
hideCloseIcon: true
|
|
54
|
+
},
|
|
55
|
+
render: Default.render
|
|
56
|
+
};
|