@sproutsocial/seeds-react-drawer 1.2.10 → 2.2.7
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/dist/drawer.css +248 -0
- package/dist/esm/index.js +599 -189
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +109 -19
- package/dist/index.d.ts +109 -19
- package/dist/index.js +607 -191
- package/dist/index.js.map +1 -1
- package/package.json +24 -12
- package/.eslintignore +0 -6
- package/.eslintrc.js +0 -4
- package/.turbo/turbo-build.log +0 -21
- package/CHANGELOG.md +0 -343
- package/jest.config.js +0 -9
- package/src/Drawer.stories.tsx +0 -474
- package/src/Drawer.tsx +0 -291
- package/src/DrawerTypes.ts +0 -88
- package/src/__tests__/Drawer.test.tsx +0 -339
- package/src/__tests__/Drawer.typetest.tsx +0 -39
- package/src/index.ts +0 -5
- package/src/styles.ts +0 -35
- package/tsconfig.json +0 -15
- package/tsup.config.ts +0 -12
package/dist/esm/index.js
CHANGED
|
@@ -1,65 +1,316 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import { MOTION_DURATION_MEDIUM } from "@sproutsocial/seeds-motion/unitless";
|
|
7
|
-
import Box2 from "@sproutsocial/seeds-react-box";
|
|
8
|
-
import Button from "@sproutsocial/seeds-react-button";
|
|
9
|
-
import Icon from "@sproutsocial/seeds-react-icon";
|
|
10
|
-
import Text from "@sproutsocial/seeds-react-text";
|
|
11
|
-
import Portal from "@sproutsocial/seeds-react-portal";
|
|
1
|
+
// src/DrawerHybrid.tsx
|
|
2
|
+
import { hasStyledProps } from "@sproutsocial/seeds-react-system-props";
|
|
3
|
+
|
|
4
|
+
// src/DrawerStyled.tsx
|
|
5
|
+
import { Drawer as BaseDrawer2 } from "@base-ui/react/drawer";
|
|
12
6
|
|
|
13
7
|
// src/styles.ts
|
|
14
|
-
import
|
|
8
|
+
import { Drawer } from "@base-ui/react/drawer";
|
|
9
|
+
import styled3 from "styled-components";
|
|
15
10
|
import { COMMON } from "@sproutsocial/seeds-react-system-props";
|
|
11
|
+
import { MOTION_DURATION_MEDIUM } from "@sproutsocial/seeds-motion/unitless";
|
|
16
12
|
import Box from "@sproutsocial/seeds-react-box";
|
|
17
|
-
|
|
13
|
+
|
|
14
|
+
// src/ActionRail/ActionRail.tsx
|
|
15
|
+
import "react";
|
|
16
|
+
import styled, { css } from "styled-components";
|
|
17
|
+
import { jsx } from "react/jsx-runtime";
|
|
18
|
+
var RAIL_BUTTON_SIZE = 44;
|
|
19
|
+
var RAIL_BUTTON_HEIGHT = 32;
|
|
20
|
+
var RAIL_OFFSET = 12;
|
|
21
|
+
var RAIL_GAP = 12;
|
|
22
|
+
var mobileLayout = css`
|
|
23
|
+
top: auto;
|
|
24
|
+
bottom: calc(100% + ${RAIL_OFFSET}px);
|
|
25
|
+
right: ${RAIL_OFFSET}px;
|
|
26
|
+
left: auto;
|
|
27
|
+
flex-direction: row-reverse;
|
|
28
|
+
`;
|
|
29
|
+
var desktopLayout = css`
|
|
30
|
+
top: ${RAIL_OFFSET}px;
|
|
31
|
+
right: calc(-1 * (${RAIL_BUTTON_SIZE}px + ${RAIL_OFFSET}px));
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
`;
|
|
34
|
+
var Rail = styled.div`
|
|
35
|
+
position: absolute;
|
|
36
|
+
display: flex;
|
|
37
|
+
gap: ${RAIL_GAP}px;
|
|
38
|
+
z-index: 1;
|
|
39
|
+
${(props) => props.$isMobile ? mobileLayout : desktopLayout}
|
|
40
|
+
`;
|
|
41
|
+
var ActionRail = ({
|
|
42
|
+
children,
|
|
43
|
+
isMobile,
|
|
44
|
+
"aria-label": ariaLabel = "Quick actions"
|
|
45
|
+
}) => {
|
|
46
|
+
return /* @__PURE__ */ jsx(
|
|
47
|
+
Rail,
|
|
48
|
+
{
|
|
49
|
+
$isMobile: isMobile,
|
|
50
|
+
"data-slot": "action-rail",
|
|
51
|
+
"data-qa-action-rail": true,
|
|
52
|
+
"aria-label": ariaLabel,
|
|
53
|
+
role: "group",
|
|
54
|
+
children
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
ActionRail.displayName = "ActionRail";
|
|
59
|
+
|
|
60
|
+
// src/ActionRail/ActionRailButton.tsx
|
|
61
|
+
import * as React2 from "react";
|
|
62
|
+
import styled2 from "styled-components";
|
|
63
|
+
import { focusRing } from "@sproutsocial/seeds-react-mixins";
|
|
64
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
65
|
+
var StyledButton = styled2.button`
|
|
66
|
+
width: ${RAIL_BUTTON_SIZE}px;
|
|
67
|
+
height: ${RAIL_BUTTON_HEIGHT}px;
|
|
68
|
+
display: inline-grid;
|
|
69
|
+
place-items: center;
|
|
70
|
+
border-radius: ${(props) => props.theme.radii.outer};
|
|
71
|
+
border: none;
|
|
72
|
+
background: ${(props) => props.theme.colors.button.overlay.background.base};
|
|
73
|
+
color: ${(props) => props.theme.colors.button.overlay.text.base};
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
outline: none;
|
|
76
|
+
transition: all ${(props) => props.theme.duration.fast}
|
|
77
|
+
${(props) => props.theme.easing.ease_inout};
|
|
78
|
+
|
|
79
|
+
&:hover {
|
|
80
|
+
background: ${(props) => props.theme.colors.button.overlay.background.hover};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
&:hover,
|
|
84
|
+
&:active {
|
|
85
|
+
transform: none;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&:focus-visible {
|
|
89
|
+
${focusRing}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
&:disabled {
|
|
93
|
+
opacity: 0.5;
|
|
94
|
+
cursor: not-allowed;
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
var ActionRailButton = React2.forwardRef(({ children, ...rest }, ref) => /* @__PURE__ */ jsx2(
|
|
98
|
+
StyledButton,
|
|
99
|
+
{
|
|
100
|
+
ref,
|
|
101
|
+
type: "button",
|
|
102
|
+
"data-slot": "action-rail-button",
|
|
103
|
+
...rest,
|
|
104
|
+
children
|
|
105
|
+
}
|
|
106
|
+
));
|
|
107
|
+
ActionRailButton.displayName = "ActionRailButton";
|
|
108
|
+
|
|
109
|
+
// src/styles.ts
|
|
110
|
+
var ACTION_RAIL_OUTSET = RAIL_BUTTON_HEIGHT + RAIL_OFFSET;
|
|
111
|
+
var Content = styled3(Box)`
|
|
18
112
|
overflow-y: auto;
|
|
19
113
|
`;
|
|
20
|
-
var
|
|
114
|
+
var StyledViewport = styled3(Drawer.Viewport)`
|
|
115
|
+
${(props) => props.$hasSnapPoints ? `
|
|
116
|
+
position: fixed;
|
|
117
|
+
inset: 0;
|
|
118
|
+
display: flex;
|
|
119
|
+
align-items: flex-end;
|
|
120
|
+
justify-content: center;
|
|
121
|
+
touch-action: none;
|
|
122
|
+
/* The viewport spans the whole screen but the popup only fills part of
|
|
123
|
+
it. Letting clicks fall through the empty area means a nested
|
|
124
|
+
snap-point drawer doesn't block selection/interaction with the
|
|
125
|
+
parent drawer visible underneath. The popup re-enables events. */
|
|
126
|
+
pointer-events: none;
|
|
127
|
+
` : ""}
|
|
128
|
+
`;
|
|
129
|
+
var StyledPopup = styled3(Drawer.Popup)`
|
|
21
130
|
display: flex;
|
|
22
131
|
flex-direction: column;
|
|
23
132
|
position: fixed;
|
|
24
|
-
top: 0;
|
|
25
|
-
height: 100%;
|
|
26
|
-
width: ${(props) => props.width}px;
|
|
27
133
|
background-color: ${(props) => props.theme.colors.container.background.base};
|
|
28
|
-
|
|
134
|
+
z-index: ${(props) => props.$zIndex};
|
|
29
135
|
filter: blur(0);
|
|
136
|
+
transition: transform ${MOTION_DURATION_MEDIUM}s ease,
|
|
137
|
+
border-radius ${MOTION_DURATION_MEDIUM}s ease,
|
|
138
|
+
height ${MOTION_DURATION_MEDIUM}s ease;
|
|
139
|
+
|
|
140
|
+
/* Always-on opacity transition so content fades smoothly both into and out of stacked state */
|
|
141
|
+
> * {
|
|
142
|
+
transition: opacity ${MOTION_DURATION_MEDIUM}s ease;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
${(props) => {
|
|
146
|
+
if (props.$direction === "bottom") {
|
|
147
|
+
if (props.$hasSnapPoints) {
|
|
148
|
+
return `
|
|
149
|
+
box-sizing: border-box;
|
|
150
|
+
position: relative;
|
|
151
|
+
width: 100%;
|
|
152
|
+
height: calc(100dvh - 1rem);
|
|
153
|
+
padding-bottom: max(0px, calc(var(--drawer-snap-point-offset, 0px) + var(--drawer-swipe-movement-y, 0px)));
|
|
154
|
+
overflow: visible;
|
|
155
|
+
touch-action: none;
|
|
156
|
+
/* Counterpart to the viewport's pointer-events: none \u2014 the popup
|
|
157
|
+
itself stays interactive. */
|
|
158
|
+
pointer-events: auto;
|
|
159
|
+
border-radius: ${props.theme.radii[800]} ${props.theme.radii[800]} 0 0;
|
|
160
|
+
box-shadow: 0px -8px 16px rgba(39,51,51,.25);
|
|
161
|
+
transform: translateY(calc(var(--drawer-snap-point-offset, 0px) + var(--drawer-swipe-movement-y, 0px)));
|
|
162
|
+
will-change: transform;
|
|
163
|
+
transition:
|
|
164
|
+
transform ${MOTION_DURATION_MEDIUM}s cubic-bezier(0.32, 0.72, 0, 1),
|
|
165
|
+
box-shadow ${MOTION_DURATION_MEDIUM}s cubic-bezier(0.32, 0.72, 0, 1);
|
|
166
|
+
`;
|
|
167
|
+
}
|
|
168
|
+
return `
|
|
169
|
+
--bleed: 3rem;
|
|
170
|
+
--stack-scale: 1;
|
|
171
|
+
--translate-y: 0px;
|
|
172
|
+
bottom: 0;
|
|
173
|
+
left: 0;
|
|
174
|
+
right: 0;
|
|
175
|
+
width: 100%;
|
|
176
|
+
height: calc(90vh + var(--bleed));
|
|
177
|
+
margin-bottom: calc(-1 * var(--bleed));
|
|
178
|
+
border-radius: ${props.theme.radii[800]} ${props.theme.radii[800]} 0 0;
|
|
179
|
+
transform: translateY(var(--translate-y)) scale(var(--stack-scale));
|
|
180
|
+
transform-origin: 50% calc(100% - var(--bleed));
|
|
181
|
+
box-shadow: 0px -8px 16px rgba(39,51,51,.25);
|
|
182
|
+
`;
|
|
183
|
+
}
|
|
184
|
+
return `
|
|
185
|
+
top: 0;
|
|
186
|
+
height: 100%;
|
|
187
|
+
width: ${props.$width}px;
|
|
188
|
+
${props.$direction === "right" ? `right: ${props.$offset}px;` : `left: ${props.$offset}px;`}
|
|
189
|
+
box-shadow: ${props.theme.shadows.medium};
|
|
190
|
+
`;
|
|
191
|
+
}}
|
|
30
192
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
193
|
+
&[data-starting-style],
|
|
194
|
+
&[data-ending-style] {
|
|
195
|
+
${(props) => {
|
|
196
|
+
if (props.$direction !== "bottom") {
|
|
197
|
+
return `transform: translateX(${props.$direction === "right" ? "100%" : "-100%"});`;
|
|
198
|
+
}
|
|
199
|
+
const railOffset = props.$hasActionRail ? ` + ${ACTION_RAIL_OUTSET}px` : "";
|
|
200
|
+
if (props.$hasSnapPoints) {
|
|
201
|
+
return `
|
|
202
|
+
transform: translateY(calc(100% + 2px${railOffset}));
|
|
203
|
+
padding-bottom: 0;
|
|
204
|
+
`;
|
|
205
|
+
}
|
|
206
|
+
return `transform: translateY(calc(100% - var(--bleed) + 2px${railOffset}));`;
|
|
207
|
+
}}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
&[data-swiping],
|
|
211
|
+
&[data-nested-drawer-swiping] {
|
|
212
|
+
transition-duration: 0ms;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
&[data-nested-drawer-open] {
|
|
216
|
+
border-radius: ${(props) => props.theme.radii[800]};
|
|
217
|
+
|
|
218
|
+
${(props) => {
|
|
219
|
+
if (props.$direction === "bottom") {
|
|
220
|
+
if (props.$hasSnapPoints) return "";
|
|
221
|
+
return `
|
|
222
|
+
--stack-step: 0.05;
|
|
223
|
+
--stack-progress: clamp(0, var(--drawer-swipe-progress), 1);
|
|
224
|
+
/* Override default vars; base transform rule picks them up automatically */
|
|
225
|
+
--stack-scale: max(0, calc(
|
|
226
|
+
1 - (var(--nested-drawers) * var(--stack-step))
|
|
227
|
+
+ (var(--stack-step) * var(--stack-progress))
|
|
228
|
+
));
|
|
229
|
+
--stack-shrink: calc(1 - var(--stack-scale));
|
|
230
|
+
--stack-height: max(0px, calc(
|
|
231
|
+
var(--drawer-frontmost-height, var(--drawer-height)) - var(--bleed)
|
|
232
|
+
));
|
|
233
|
+
--stack-peek-offset: max(0px, calc(
|
|
234
|
+
(var(--nested-drawers) - var(--stack-progress)) * 1rem
|
|
235
|
+
));
|
|
236
|
+
--translate-y: calc(
|
|
237
|
+
var(--drawer-swipe-movement-y)
|
|
238
|
+
- var(--stack-peek-offset)
|
|
239
|
+
- (var(--stack-shrink) * var(--stack-height))
|
|
240
|
+
);
|
|
241
|
+
height: calc(var(--stack-height) + var(--bleed));
|
|
242
|
+
overflow: hidden;
|
|
243
|
+
`;
|
|
244
|
+
}
|
|
245
|
+
return `
|
|
246
|
+
transform: translateY(calc(var(--nested-drawers) * -20px))
|
|
247
|
+
scale(calc(1 - var(--nested-drawers) * 0.08));
|
|
248
|
+
transform-origin: top center;
|
|
249
|
+
`;
|
|
250
|
+
}}
|
|
251
|
+
|
|
252
|
+
${(props) => props.$hasSnapPoints ? "" : `
|
|
253
|
+
> * {
|
|
254
|
+
opacity: 0;
|
|
255
|
+
}
|
|
256
|
+
`}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
&[data-nested-drawer-open][data-nested-drawer-swiping] {
|
|
260
|
+
> * {
|
|
261
|
+
opacity: 1;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
34
264
|
|
|
35
265
|
${COMMON}
|
|
36
266
|
`;
|
|
37
|
-
var
|
|
267
|
+
var DragHandle = styled3.div`
|
|
268
|
+
position: absolute;
|
|
269
|
+
top: 8px;
|
|
270
|
+
left: 50%;
|
|
271
|
+
transform: translateX(-50%);
|
|
272
|
+
width: 36px;
|
|
273
|
+
height: 4px;
|
|
274
|
+
border-radius: 2px;
|
|
275
|
+
background-color: ${(props) => props.theme.colors.container.border.base};
|
|
276
|
+
`;
|
|
277
|
+
var StyledBackdrop = styled3(Drawer.Backdrop)`
|
|
278
|
+
position: fixed;
|
|
279
|
+
inset: 0;
|
|
280
|
+
background: transparent;
|
|
281
|
+
pointer-events: none;
|
|
282
|
+
`;
|
|
38
283
|
|
|
39
|
-
// src/
|
|
40
|
-
import
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
284
|
+
// src/DrawerShared.tsx
|
|
285
|
+
import * as React3 from "react";
|
|
286
|
+
import { useContext } from "react";
|
|
287
|
+
import "@base-ui/react/drawer";
|
|
288
|
+
import Box2 from "@sproutsocial/seeds-react-box";
|
|
289
|
+
import Button from "@sproutsocial/seeds-react-button";
|
|
290
|
+
import Icon from "@sproutsocial/seeds-react-icon";
|
|
291
|
+
import Text from "@sproutsocial/seeds-react-text";
|
|
292
|
+
import { useIsMobile } from "@sproutsocial/seeds-react-hooks";
|
|
293
|
+
import { DisablePortalToBodyContext } from "@sproutsocial/seeds-react-portal";
|
|
294
|
+
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
295
|
+
var DrawerContext = React3.createContext({
|
|
46
296
|
isLocked: false,
|
|
47
297
|
setIsLocked: () => {
|
|
48
|
-
}
|
|
298
|
+
},
|
|
299
|
+
hasActionRail: false
|
|
49
300
|
});
|
|
50
301
|
var DrawerCloseButton = (props) => {
|
|
51
302
|
const drawerContext = useContext(DrawerContext);
|
|
52
303
|
if (props.render) {
|
|
53
304
|
return props.render(drawerContext) ?? null;
|
|
54
305
|
}
|
|
55
|
-
return /* @__PURE__ */
|
|
306
|
+
return /* @__PURE__ */ jsx3(
|
|
56
307
|
Button,
|
|
57
308
|
{
|
|
58
309
|
appearance: "pill",
|
|
59
310
|
"aria-label": drawerContext.closeButtonLabel,
|
|
60
311
|
onClick: drawerContext.onClose,
|
|
61
312
|
...props,
|
|
62
|
-
children: props.children || /* @__PURE__ */
|
|
313
|
+
children: props.children || /* @__PURE__ */ jsx3(Icon, { "aria-hidden": true, name: "x-outline" })
|
|
63
314
|
}
|
|
64
315
|
);
|
|
65
316
|
};
|
|
@@ -74,7 +325,7 @@ var DrawerHeader = ({
|
|
|
74
325
|
if (render) {
|
|
75
326
|
return render(drawerContext);
|
|
76
327
|
}
|
|
77
|
-
return /* @__PURE__ */
|
|
328
|
+
return /* @__PURE__ */ jsx3(
|
|
78
329
|
Box2,
|
|
79
330
|
{
|
|
80
331
|
display: "flex",
|
|
@@ -84,8 +335,8 @@ var DrawerHeader = ({
|
|
|
84
335
|
pt: 400,
|
|
85
336
|
px: 450,
|
|
86
337
|
...rest,
|
|
87
|
-
children: children || /* @__PURE__ */ jsxs(
|
|
88
|
-
/* @__PURE__ */
|
|
338
|
+
children: children || /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
339
|
+
/* @__PURE__ */ jsx3(
|
|
89
340
|
Text,
|
|
90
341
|
{
|
|
91
342
|
as: "h2",
|
|
@@ -96,177 +347,330 @@ var DrawerHeader = ({
|
|
|
96
347
|
children: title
|
|
97
348
|
}
|
|
98
349
|
),
|
|
99
|
-
/* @__PURE__ */
|
|
350
|
+
!drawerContext.hasActionRail && /* @__PURE__ */ jsx3(DrawerCloseButton, {})
|
|
100
351
|
] })
|
|
101
352
|
}
|
|
102
353
|
);
|
|
103
354
|
};
|
|
104
|
-
var DrawerContent = ({ children, ...rest }) => /* @__PURE__ */
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
355
|
+
var DrawerContent = ({ children, ...rest }) => /* @__PURE__ */ jsx3(
|
|
356
|
+
Content,
|
|
357
|
+
{
|
|
358
|
+
height: "100%",
|
|
359
|
+
p: 450,
|
|
360
|
+
color: "text.body",
|
|
361
|
+
"data-drawer-content": "",
|
|
362
|
+
...rest,
|
|
363
|
+
children
|
|
364
|
+
}
|
|
365
|
+
);
|
|
366
|
+
DrawerHeader.displayName = "Drawer.Header";
|
|
367
|
+
DrawerContent.displayName = "Drawer.Content";
|
|
368
|
+
DrawerCloseButton.displayName = "Drawer.CloseButton";
|
|
369
|
+
var useDrawerShell = (props) => {
|
|
370
|
+
const {
|
|
371
|
+
children,
|
|
372
|
+
closeButtonLabel,
|
|
373
|
+
direction = "right",
|
|
374
|
+
disableCloseOnClickOutside = false,
|
|
375
|
+
id,
|
|
376
|
+
modal = false,
|
|
377
|
+
open,
|
|
378
|
+
offset = 0,
|
|
379
|
+
onClose,
|
|
380
|
+
zIndex = 7,
|
|
381
|
+
width = 600,
|
|
382
|
+
snapPoints,
|
|
383
|
+
defaultSnapPoint,
|
|
384
|
+
snapPoint,
|
|
385
|
+
onSnapPointChange,
|
|
386
|
+
snapToSequentialPoints,
|
|
387
|
+
actions,
|
|
388
|
+
actionsInHeader = false,
|
|
389
|
+
...rest
|
|
390
|
+
} = props;
|
|
391
|
+
const isMobile = useIsMobile();
|
|
392
|
+
const effectiveDirection = isMobile ? "bottom" : direction;
|
|
393
|
+
const effectiveSnapPoints = effectiveDirection === "bottom" ? snapPoints : void 0;
|
|
394
|
+
const hasSnapPoints = !!effectiveSnapPoints && effectiveSnapPoints.length > 0;
|
|
395
|
+
const hasActionRail = isMobile && !actionsInHeader && !!actions && actions.length > 0;
|
|
396
|
+
const [isLocked, setIsLocked] = React3.useState(false);
|
|
397
|
+
const ariaLabelledBy = rest["aria-labelledby"];
|
|
398
|
+
const ariaLabel = rest["aria-label"];
|
|
399
|
+
React3.useEffect(() => {
|
|
400
|
+
if (process.env.NODE_ENV !== "production") {
|
|
401
|
+
if (!ariaLabelledBy && !ariaLabel) {
|
|
402
|
+
console.warn(
|
|
403
|
+
"[Drawer] Missing accessible name. Add aria-labelledby pointing to your Drawer.Header id, or aria-label, so screen readers can identify the dialog."
|
|
404
|
+
);
|
|
129
405
|
}
|
|
130
|
-
};
|
|
131
|
-
documentBody?.addEventListener("keydown", onEsc, { capture: true });
|
|
132
|
-
if (closeTargets) {
|
|
133
|
-
closeTargets.forEach(
|
|
134
|
-
(targetElement) => targetElement?.addEventListener("click", bodyClick, { capture: true })
|
|
135
|
-
);
|
|
136
|
-
} else {
|
|
137
|
-
documentBody.firstElementChild?.addEventListener("click", bodyClick, {
|
|
138
|
-
capture: true
|
|
139
|
-
});
|
|
140
406
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
407
|
+
}, [ariaLabelledBy, ariaLabel]);
|
|
408
|
+
const isLockedRef = React3.useRef(isLocked);
|
|
409
|
+
isLockedRef.current = isLocked;
|
|
410
|
+
const prevChildrenRef = React3.useRef(null);
|
|
411
|
+
if (open) {
|
|
412
|
+
prevChildrenRef.current = children;
|
|
413
|
+
}
|
|
414
|
+
const renderedChildren = open ? children : prevChildrenRef.current;
|
|
415
|
+
const rootProps = {
|
|
416
|
+
open,
|
|
417
|
+
onOpenChange: (isOpen, eventDetails) => {
|
|
418
|
+
if (!isOpen) {
|
|
419
|
+
if (isLockedRef.current && eventDetails.reason === "escape-key") {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
onClose();
|
|
155
423
|
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
424
|
+
},
|
|
425
|
+
disablePointerDismissal: disableCloseOnClickOutside,
|
|
426
|
+
swipeDirection: effectiveDirection === "bottom" ? "down" : effectiveDirection,
|
|
427
|
+
modal,
|
|
428
|
+
snapPoints: effectiveSnapPoints,
|
|
429
|
+
defaultSnapPoint,
|
|
430
|
+
snapPoint,
|
|
431
|
+
onSnapPointChange: onSnapPointChange ? (sp) => onSnapPointChange(sp) : void 0,
|
|
432
|
+
snapToSequentialPoints
|
|
433
|
+
};
|
|
434
|
+
return {
|
|
435
|
+
effectiveDirection,
|
|
436
|
+
hasSnapPoints,
|
|
437
|
+
hasActionRail,
|
|
162
438
|
isLocked,
|
|
163
|
-
|
|
164
|
-
|
|
439
|
+
setIsLocked,
|
|
440
|
+
renderedChildren,
|
|
441
|
+
rootProps,
|
|
442
|
+
rest,
|
|
443
|
+
width,
|
|
444
|
+
offset,
|
|
445
|
+
zIndex,
|
|
446
|
+
id,
|
|
447
|
+
open,
|
|
448
|
+
closeButtonLabel,
|
|
449
|
+
onClose,
|
|
450
|
+
actions
|
|
451
|
+
};
|
|
165
452
|
};
|
|
166
|
-
var
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
children,
|
|
171
|
-
disableCloseOnClickOutside,
|
|
172
|
-
onClose,
|
|
173
|
-
zIndex,
|
|
174
|
-
closeTargets,
|
|
175
|
-
width,
|
|
176
|
-
focusLockExemptCheck,
|
|
177
|
-
isOpen,
|
|
178
|
-
...rest
|
|
179
|
-
}) => {
|
|
180
|
-
const ref = useRef(null);
|
|
181
|
-
useCloseOnBodyClick({
|
|
182
|
-
ref,
|
|
183
|
-
disableCloseOnClickOutside,
|
|
453
|
+
var DrawerPopupContents = ({ shell }) => {
|
|
454
|
+
const {
|
|
455
|
+
hasActionRail,
|
|
456
|
+
closeButtonLabel,
|
|
184
457
|
onClose,
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
{
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
returnFocus: true,
|
|
195
|
-
whiteList: focusLockExemptCheck ? (e) => !focusLockExemptCheck(e) : void 0,
|
|
196
|
-
children: /* @__PURE__ */ jsx(AnimatePresence, { children: isOpen && /* @__PURE__ */ jsx(
|
|
197
|
-
MotionContainer,
|
|
458
|
+
actions,
|
|
459
|
+
isLocked,
|
|
460
|
+
setIsLocked,
|
|
461
|
+
renderedChildren
|
|
462
|
+
} = shell;
|
|
463
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
464
|
+
hasActionRail && actions && /* @__PURE__ */ jsxs(ActionRail, { isMobile: true, "aria-label": "Drawer quick actions", children: [
|
|
465
|
+
/* @__PURE__ */ jsx3(
|
|
466
|
+
ActionRailButton,
|
|
198
467
|
{
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
direction,
|
|
204
|
-
"data-qa-drawer": id,
|
|
205
|
-
role: "dialog",
|
|
206
|
-
initial: { opacity: 0, x: offset_x },
|
|
207
|
-
animate: { opacity: 1, x: 0 },
|
|
208
|
-
exit: { opacity: 0, x: offset_x },
|
|
209
|
-
transition: { duration: MOTION_DURATION_MEDIUM },
|
|
210
|
-
...rest,
|
|
211
|
-
children
|
|
468
|
+
"aria-label": closeButtonLabel,
|
|
469
|
+
onClick: onClose,
|
|
470
|
+
"data-qa-drawer-rail-close": true,
|
|
471
|
+
children: /* @__PURE__ */ jsx3(Icon, { "aria-hidden": true, name: "x-outline" })
|
|
212
472
|
}
|
|
213
|
-
)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
);
|
|
217
|
-
};
|
|
218
|
-
var DrawerContainer = ({
|
|
219
|
-
children,
|
|
220
|
-
closeButtonLabel,
|
|
221
|
-
direction = "right",
|
|
222
|
-
disableCloseOnClickOutside = false,
|
|
223
|
-
id,
|
|
224
|
-
isOpen,
|
|
225
|
-
offset = 0,
|
|
226
|
-
onClose,
|
|
227
|
-
zIndex = 7,
|
|
228
|
-
closeTargets = [],
|
|
229
|
-
width = 600,
|
|
230
|
-
...rest
|
|
231
|
-
}) => {
|
|
232
|
-
const [isLocked, setIsLocked] = React.useState(false);
|
|
233
|
-
return /* @__PURE__ */ jsx(Portal, { id, children: /* @__PURE__ */ jsx(
|
|
234
|
-
DrawerContext.Provider,
|
|
235
|
-
{
|
|
236
|
-
value: {
|
|
237
|
-
onClose,
|
|
238
|
-
closeButtonLabel,
|
|
239
|
-
isLocked,
|
|
240
|
-
setIsLocked
|
|
241
|
-
},
|
|
242
|
-
children: /* @__PURE__ */ jsx(
|
|
243
|
-
Drawer,
|
|
473
|
+
),
|
|
474
|
+
actions.map((action, i) => /* @__PURE__ */ jsx3(
|
|
475
|
+
ActionRailButton,
|
|
244
476
|
{
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
477
|
+
"aria-label": action["aria-label"],
|
|
478
|
+
onClick: action.onClick,
|
|
479
|
+
disabled: action.disabled,
|
|
480
|
+
children: action.iconName && /* @__PURE__ */ jsx3(Icon, { "aria-hidden": true, name: action.iconName })
|
|
481
|
+
},
|
|
482
|
+
i
|
|
483
|
+
))
|
|
484
|
+
] }),
|
|
485
|
+
/* @__PURE__ */ jsx3(DisablePortalToBodyContext.Provider, { value: true, children: /* @__PURE__ */ jsx3(
|
|
486
|
+
DrawerContext.Provider,
|
|
487
|
+
{
|
|
488
|
+
value: {
|
|
250
489
|
onClose,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
490
|
+
closeButtonLabel,
|
|
491
|
+
isLocked,
|
|
492
|
+
setIsLocked,
|
|
493
|
+
hasActionRail
|
|
494
|
+
},
|
|
495
|
+
children: renderedChildren
|
|
496
|
+
}
|
|
497
|
+
) })
|
|
498
|
+
] });
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
// src/DrawerStyled.tsx
|
|
502
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
503
|
+
var DrawerStyled = (props) => {
|
|
504
|
+
const shell = useDrawerShell(props);
|
|
505
|
+
const {
|
|
506
|
+
effectiveDirection,
|
|
507
|
+
hasSnapPoints,
|
|
508
|
+
hasActionRail,
|
|
509
|
+
rootProps,
|
|
510
|
+
rest,
|
|
511
|
+
width,
|
|
512
|
+
offset,
|
|
513
|
+
zIndex,
|
|
514
|
+
id,
|
|
515
|
+
open
|
|
516
|
+
} = shell;
|
|
517
|
+
return /* @__PURE__ */ jsx4(BaseDrawer2.Root, { ...rootProps, children: /* @__PURE__ */ jsxs2(BaseDrawer2.Portal, { children: [
|
|
518
|
+
/* @__PURE__ */ jsx4(StyledBackdrop, { "data-testid": "drawer-backdrop" }),
|
|
519
|
+
/* @__PURE__ */ jsx4(StyledViewport, { $hasSnapPoints: hasSnapPoints, children: /* @__PURE__ */ jsxs2(
|
|
520
|
+
StyledPopup,
|
|
521
|
+
{
|
|
522
|
+
initialFocus: true,
|
|
523
|
+
$width: width,
|
|
524
|
+
$offset: offset,
|
|
525
|
+
$direction: effectiveDirection,
|
|
526
|
+
$zIndex: zIndex,
|
|
527
|
+
$hasSnapPoints: hasSnapPoints,
|
|
528
|
+
$hasActionRail: hasActionRail,
|
|
529
|
+
"data-qa-drawer": id,
|
|
530
|
+
"data-qa-drawer-isopen": open,
|
|
531
|
+
...rest,
|
|
532
|
+
children: [
|
|
533
|
+
effectiveDirection === "bottom" && /* @__PURE__ */ jsx4(DragHandle, { "aria-hidden": true }),
|
|
534
|
+
/* @__PURE__ */ jsx4(DrawerPopupContents, { shell })
|
|
535
|
+
]
|
|
536
|
+
}
|
|
537
|
+
) })
|
|
538
|
+
] }) });
|
|
539
|
+
};
|
|
540
|
+
var DrawerStyled_default = DrawerStyled;
|
|
541
|
+
|
|
542
|
+
// src/DrawerTailwind.tsx
|
|
543
|
+
import { Drawer as BaseDrawer3 } from "@base-ui/react/drawer";
|
|
544
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
545
|
+
function cn(...inputs) {
|
|
546
|
+
const classes = [];
|
|
547
|
+
for (const input of inputs) {
|
|
548
|
+
if (!input) continue;
|
|
549
|
+
if (typeof input === "string") {
|
|
550
|
+
classes.push(input);
|
|
551
|
+
} else if (typeof input === "object") {
|
|
552
|
+
for (const [key, value] of Object.entries(input)) {
|
|
553
|
+
if (value) {
|
|
554
|
+
classes.push(key);
|
|
258
555
|
}
|
|
259
|
-
|
|
556
|
+
}
|
|
260
557
|
}
|
|
261
|
-
|
|
558
|
+
}
|
|
559
|
+
return classes.join(" ");
|
|
560
|
+
}
|
|
561
|
+
var DrawerTailwind = (props) => {
|
|
562
|
+
const shell = useDrawerShell(props);
|
|
563
|
+
const {
|
|
564
|
+
effectiveDirection,
|
|
565
|
+
hasSnapPoints,
|
|
566
|
+
hasActionRail,
|
|
567
|
+
rootProps,
|
|
568
|
+
rest,
|
|
569
|
+
width,
|
|
570
|
+
offset,
|
|
571
|
+
zIndex,
|
|
572
|
+
id,
|
|
573
|
+
open
|
|
574
|
+
} = shell;
|
|
575
|
+
const { className, style, ...domRest } = rest;
|
|
576
|
+
return /* @__PURE__ */ jsx5(BaseDrawer3.Root, { ...rootProps, children: /* @__PURE__ */ jsxs3(BaseDrawer3.Portal, { children: [
|
|
577
|
+
/* @__PURE__ */ jsx5(
|
|
578
|
+
BaseDrawer3.Backdrop,
|
|
579
|
+
{
|
|
580
|
+
"data-testid": "drawer-backdrop",
|
|
581
|
+
className: "seeds-drawer-backdrop"
|
|
582
|
+
}
|
|
583
|
+
),
|
|
584
|
+
/* @__PURE__ */ jsx5(
|
|
585
|
+
BaseDrawer3.Viewport,
|
|
586
|
+
{
|
|
587
|
+
className: cn("seeds-drawer-viewport", {
|
|
588
|
+
"seeds-drawer-viewport--snap": hasSnapPoints
|
|
589
|
+
}),
|
|
590
|
+
children: /* @__PURE__ */ jsxs3(
|
|
591
|
+
BaseDrawer3.Popup,
|
|
592
|
+
{
|
|
593
|
+
initialFocus: true,
|
|
594
|
+
"data-qa-drawer": id,
|
|
595
|
+
"data-qa-drawer-isopen": open,
|
|
596
|
+
...domRest,
|
|
597
|
+
className: cn(
|
|
598
|
+
"seeds-drawer-popup",
|
|
599
|
+
effectiveDirection === "bottom" ? "seeds-drawer-popup--bottom" : "seeds-drawer-popup--side",
|
|
600
|
+
effectiveDirection === "right" && "seeds-drawer-popup--right",
|
|
601
|
+
effectiveDirection === "left" && "seeds-drawer-popup--left",
|
|
602
|
+
{
|
|
603
|
+
"seeds-drawer-popup--snap": hasSnapPoints,
|
|
604
|
+
"seeds-drawer-popup--action-rail": hasActionRail
|
|
605
|
+
},
|
|
606
|
+
// Consumer className folded in last so it appends to (not
|
|
607
|
+
// replaces) the component classes.
|
|
608
|
+
className
|
|
609
|
+
),
|
|
610
|
+
style: {
|
|
611
|
+
// z-index is always inline (runtime numeric, mirrors styles.ts).
|
|
612
|
+
zIndex,
|
|
613
|
+
// Side drawers carry their width/offset as direct inline styles —
|
|
614
|
+
// runtime numerics, and required for the jsdom `toHaveStyle`
|
|
615
|
+
// assertions. Bottom drawers derive width/position from the class.
|
|
616
|
+
...effectiveDirection === "right" ? { width: `${width}px`, right: `${offset}px` } : effectiveDirection === "left" ? { width: `${width}px`, left: `${offset}px` } : {},
|
|
617
|
+
// Consumer style folded in last so it wins over the computed
|
|
618
|
+
// geometry, matching the styled-components inline-style semantics.
|
|
619
|
+
...style
|
|
620
|
+
},
|
|
621
|
+
children: [
|
|
622
|
+
effectiveDirection === "bottom" && /* @__PURE__ */ jsx5("div", { "aria-hidden": true, className: "seeds-drawer-drag-handle" }),
|
|
623
|
+
/* @__PURE__ */ jsx5(DrawerPopupContents, { shell })
|
|
624
|
+
]
|
|
625
|
+
}
|
|
626
|
+
)
|
|
627
|
+
}
|
|
628
|
+
)
|
|
629
|
+
] }) });
|
|
262
630
|
};
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
631
|
+
var DrawerTailwind_default = DrawerTailwind;
|
|
632
|
+
|
|
633
|
+
// src/DrawerHybrid.tsx
|
|
634
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
635
|
+
var DRAWER_OWN_PROPS = [
|
|
636
|
+
"children",
|
|
637
|
+
"closeButtonLabel",
|
|
638
|
+
"direction",
|
|
639
|
+
"disableCloseOnClickOutside",
|
|
640
|
+
"id",
|
|
641
|
+
"modal",
|
|
642
|
+
"open",
|
|
643
|
+
"offset",
|
|
644
|
+
"onClose",
|
|
645
|
+
"zIndex",
|
|
646
|
+
"width",
|
|
647
|
+
"snapPoints",
|
|
648
|
+
"defaultSnapPoint",
|
|
649
|
+
"snapPoint",
|
|
650
|
+
"onSnapPointChange",
|
|
651
|
+
"snapToSequentialPoints",
|
|
652
|
+
"actions",
|
|
653
|
+
"actionsInHeader"
|
|
654
|
+
];
|
|
655
|
+
var DrawerHybrid = (props) => {
|
|
656
|
+
const rest = {};
|
|
657
|
+
for (const key of Object.keys(props)) {
|
|
658
|
+
if (!DRAWER_OWN_PROPS.includes(key)) {
|
|
659
|
+
rest[key] = props[key];
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (hasStyledProps(rest)) {
|
|
663
|
+
return /* @__PURE__ */ jsx6(DrawerStyled_default, { ...props });
|
|
664
|
+
}
|
|
665
|
+
return /* @__PURE__ */ jsx6(DrawerTailwind_default, { ...props });
|
|
666
|
+
};
|
|
667
|
+
DrawerHybrid.Header = DrawerHeader;
|
|
668
|
+
DrawerHybrid.Content = DrawerContent;
|
|
669
|
+
DrawerHybrid.CloseButton = DrawerCloseButton;
|
|
670
|
+
var DrawerHybrid_default = DrawerHybrid;
|
|
671
|
+
|
|
672
|
+
// src/Drawer.tsx
|
|
673
|
+
var Drawer_default = DrawerHybrid_default;
|
|
270
674
|
|
|
271
675
|
// src/DrawerTypes.ts
|
|
272
676
|
import "react";
|
|
@@ -274,8 +678,14 @@ import "react";
|
|
|
274
678
|
// src/index.ts
|
|
275
679
|
var index_default = Drawer_default;
|
|
276
680
|
export {
|
|
681
|
+
ActionRail,
|
|
682
|
+
ActionRailButton,
|
|
277
683
|
Drawer_default as Drawer,
|
|
278
684
|
DrawerContext,
|
|
685
|
+
RAIL_BUTTON_HEIGHT,
|
|
686
|
+
RAIL_BUTTON_SIZE,
|
|
687
|
+
RAIL_GAP,
|
|
688
|
+
RAIL_OFFSET,
|
|
279
689
|
index_default as default
|
|
280
690
|
};
|
|
281
691
|
//# sourceMappingURL=index.js.map
|