@sproutsocial/seeds-react-drawer 1.2.11 → 2.2.8
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 +602 -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 +610 -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 -350
- 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
|
+
}}
|
|
192
|
+
|
|
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
|
+
}
|
|
30
209
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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,333 @@ 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 = ({
|
|
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 = ({
|
|
356
|
+
children,
|
|
357
|
+
...rest
|
|
358
|
+
}) => /* @__PURE__ */ jsx3(
|
|
359
|
+
Content,
|
|
360
|
+
{
|
|
361
|
+
height: "100%",
|
|
362
|
+
p: 450,
|
|
363
|
+
color: "text.body",
|
|
364
|
+
"data-drawer-content": "",
|
|
365
|
+
...rest,
|
|
366
|
+
children
|
|
367
|
+
}
|
|
368
|
+
);
|
|
369
|
+
DrawerHeader.displayName = "Drawer.Header";
|
|
370
|
+
DrawerContent.displayName = "Drawer.Content";
|
|
371
|
+
DrawerCloseButton.displayName = "Drawer.CloseButton";
|
|
372
|
+
var useDrawerShell = (props) => {
|
|
373
|
+
const {
|
|
374
|
+
children,
|
|
375
|
+
closeButtonLabel,
|
|
376
|
+
direction = "right",
|
|
377
|
+
disableCloseOnClickOutside = false,
|
|
378
|
+
id,
|
|
379
|
+
modal = false,
|
|
380
|
+
open,
|
|
381
|
+
offset = 0,
|
|
382
|
+
onClose,
|
|
383
|
+
zIndex = 7,
|
|
384
|
+
width = 600,
|
|
385
|
+
snapPoints,
|
|
386
|
+
defaultSnapPoint,
|
|
387
|
+
snapPoint,
|
|
388
|
+
onSnapPointChange,
|
|
389
|
+
snapToSequentialPoints,
|
|
390
|
+
actions,
|
|
391
|
+
actionsInHeader = false,
|
|
392
|
+
...rest
|
|
393
|
+
} = props;
|
|
394
|
+
const isMobile = useIsMobile();
|
|
395
|
+
const effectiveDirection = isMobile ? "bottom" : direction;
|
|
396
|
+
const effectiveSnapPoints = effectiveDirection === "bottom" ? snapPoints : void 0;
|
|
397
|
+
const hasSnapPoints = !!effectiveSnapPoints && effectiveSnapPoints.length > 0;
|
|
398
|
+
const hasActionRail = isMobile && !actionsInHeader && !!actions && actions.length > 0;
|
|
399
|
+
const [isLocked, setIsLocked] = React3.useState(false);
|
|
400
|
+
const ariaLabelledBy = rest["aria-labelledby"];
|
|
401
|
+
const ariaLabel = rest["aria-label"];
|
|
402
|
+
React3.useEffect(() => {
|
|
403
|
+
if (process.env.NODE_ENV !== "production") {
|
|
404
|
+
if (!ariaLabelledBy && !ariaLabel) {
|
|
405
|
+
console.warn(
|
|
406
|
+
"[Drawer] Missing accessible name. Add aria-labelledby pointing to your Drawer.Header id, or aria-label, so screen readers can identify the dialog."
|
|
407
|
+
);
|
|
129
408
|
}
|
|
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
409
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
410
|
+
}, [ariaLabelledBy, ariaLabel]);
|
|
411
|
+
const isLockedRef = React3.useRef(isLocked);
|
|
412
|
+
isLockedRef.current = isLocked;
|
|
413
|
+
const prevChildrenRef = React3.useRef(null);
|
|
414
|
+
if (open) {
|
|
415
|
+
prevChildrenRef.current = children;
|
|
416
|
+
}
|
|
417
|
+
const renderedChildren = open ? children : prevChildrenRef.current;
|
|
418
|
+
const rootProps = {
|
|
419
|
+
open,
|
|
420
|
+
onOpenChange: (isOpen, eventDetails) => {
|
|
421
|
+
if (!isOpen) {
|
|
422
|
+
if (isLockedRef.current && eventDetails.reason === "escape-key") {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
onClose();
|
|
155
426
|
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
427
|
+
},
|
|
428
|
+
disablePointerDismissal: disableCloseOnClickOutside,
|
|
429
|
+
swipeDirection: effectiveDirection === "bottom" ? "down" : effectiveDirection,
|
|
430
|
+
modal,
|
|
431
|
+
snapPoints: effectiveSnapPoints,
|
|
432
|
+
defaultSnapPoint,
|
|
433
|
+
snapPoint,
|
|
434
|
+
onSnapPointChange: onSnapPointChange ? (sp) => onSnapPointChange(sp) : void 0,
|
|
435
|
+
snapToSequentialPoints
|
|
436
|
+
};
|
|
437
|
+
return {
|
|
438
|
+
effectiveDirection,
|
|
439
|
+
hasSnapPoints,
|
|
440
|
+
hasActionRail,
|
|
162
441
|
isLocked,
|
|
163
|
-
|
|
164
|
-
|
|
442
|
+
setIsLocked,
|
|
443
|
+
renderedChildren,
|
|
444
|
+
rootProps,
|
|
445
|
+
rest,
|
|
446
|
+
width,
|
|
447
|
+
offset,
|
|
448
|
+
zIndex,
|
|
449
|
+
id,
|
|
450
|
+
open,
|
|
451
|
+
closeButtonLabel,
|
|
452
|
+
onClose,
|
|
453
|
+
actions
|
|
454
|
+
};
|
|
165
455
|
};
|
|
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,
|
|
456
|
+
var DrawerPopupContents = ({ shell }) => {
|
|
457
|
+
const {
|
|
458
|
+
hasActionRail,
|
|
459
|
+
closeButtonLabel,
|
|
184
460
|
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,
|
|
461
|
+
actions,
|
|
462
|
+
isLocked,
|
|
463
|
+
setIsLocked,
|
|
464
|
+
renderedChildren
|
|
465
|
+
} = shell;
|
|
466
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
467
|
+
hasActionRail && actions && /* @__PURE__ */ jsxs(ActionRail, { isMobile: true, "aria-label": "Drawer quick actions", children: [
|
|
468
|
+
/* @__PURE__ */ jsx3(
|
|
469
|
+
ActionRailButton,
|
|
198
470
|
{
|
|
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
|
|
471
|
+
"aria-label": closeButtonLabel,
|
|
472
|
+
onClick: onClose,
|
|
473
|
+
"data-qa-drawer-rail-close": true,
|
|
474
|
+
children: /* @__PURE__ */ jsx3(Icon, { "aria-hidden": true, name: "x-outline" })
|
|
212
475
|
}
|
|
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,
|
|
476
|
+
),
|
|
477
|
+
actions.map((action, i) => /* @__PURE__ */ jsx3(
|
|
478
|
+
ActionRailButton,
|
|
244
479
|
{
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
480
|
+
"aria-label": action["aria-label"],
|
|
481
|
+
onClick: action.onClick,
|
|
482
|
+
disabled: action.disabled,
|
|
483
|
+
children: action.iconName && /* @__PURE__ */ jsx3(Icon, { "aria-hidden": true, name: action.iconName })
|
|
484
|
+
},
|
|
485
|
+
i
|
|
486
|
+
))
|
|
487
|
+
] }),
|
|
488
|
+
/* @__PURE__ */ jsx3(DisablePortalToBodyContext.Provider, { value: true, children: /* @__PURE__ */ jsx3(
|
|
489
|
+
DrawerContext.Provider,
|
|
490
|
+
{
|
|
491
|
+
value: {
|
|
250
492
|
onClose,
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
493
|
+
closeButtonLabel,
|
|
494
|
+
isLocked,
|
|
495
|
+
setIsLocked,
|
|
496
|
+
hasActionRail
|
|
497
|
+
},
|
|
498
|
+
children: renderedChildren
|
|
499
|
+
}
|
|
500
|
+
) })
|
|
501
|
+
] });
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
// src/DrawerStyled.tsx
|
|
505
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
506
|
+
var DrawerStyled = (props) => {
|
|
507
|
+
const shell = useDrawerShell(props);
|
|
508
|
+
const {
|
|
509
|
+
effectiveDirection,
|
|
510
|
+
hasSnapPoints,
|
|
511
|
+
hasActionRail,
|
|
512
|
+
rootProps,
|
|
513
|
+
rest,
|
|
514
|
+
width,
|
|
515
|
+
offset,
|
|
516
|
+
zIndex,
|
|
517
|
+
id,
|
|
518
|
+
open
|
|
519
|
+
} = shell;
|
|
520
|
+
return /* @__PURE__ */ jsx4(BaseDrawer2.Root, { ...rootProps, children: /* @__PURE__ */ jsxs2(BaseDrawer2.Portal, { children: [
|
|
521
|
+
/* @__PURE__ */ jsx4(StyledBackdrop, { "data-testid": "drawer-backdrop" }),
|
|
522
|
+
/* @__PURE__ */ jsx4(StyledViewport, { $hasSnapPoints: hasSnapPoints, children: /* @__PURE__ */ jsxs2(
|
|
523
|
+
StyledPopup,
|
|
524
|
+
{
|
|
525
|
+
initialFocus: true,
|
|
526
|
+
$width: width,
|
|
527
|
+
$offset: offset,
|
|
528
|
+
$direction: effectiveDirection,
|
|
529
|
+
$zIndex: zIndex,
|
|
530
|
+
$hasSnapPoints: hasSnapPoints,
|
|
531
|
+
$hasActionRail: hasActionRail,
|
|
532
|
+
"data-qa-drawer": id,
|
|
533
|
+
"data-qa-drawer-isopen": open,
|
|
534
|
+
...rest,
|
|
535
|
+
children: [
|
|
536
|
+
effectiveDirection === "bottom" && /* @__PURE__ */ jsx4(DragHandle, { "aria-hidden": true }),
|
|
537
|
+
/* @__PURE__ */ jsx4(DrawerPopupContents, { shell })
|
|
538
|
+
]
|
|
539
|
+
}
|
|
540
|
+
) })
|
|
541
|
+
] }) });
|
|
542
|
+
};
|
|
543
|
+
var DrawerStyled_default = DrawerStyled;
|
|
544
|
+
|
|
545
|
+
// src/DrawerTailwind.tsx
|
|
546
|
+
import { Drawer as BaseDrawer3 } from "@base-ui/react/drawer";
|
|
547
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
548
|
+
function cn(...inputs) {
|
|
549
|
+
const classes = [];
|
|
550
|
+
for (const input of inputs) {
|
|
551
|
+
if (!input) continue;
|
|
552
|
+
if (typeof input === "string") {
|
|
553
|
+
classes.push(input);
|
|
554
|
+
} else if (typeof input === "object") {
|
|
555
|
+
for (const [key, value] of Object.entries(input)) {
|
|
556
|
+
if (value) {
|
|
557
|
+
classes.push(key);
|
|
258
558
|
}
|
|
259
|
-
|
|
559
|
+
}
|
|
260
560
|
}
|
|
261
|
-
|
|
561
|
+
}
|
|
562
|
+
return classes.join(" ");
|
|
563
|
+
}
|
|
564
|
+
var DrawerTailwind = (props) => {
|
|
565
|
+
const shell = useDrawerShell(props);
|
|
566
|
+
const {
|
|
567
|
+
effectiveDirection,
|
|
568
|
+
hasSnapPoints,
|
|
569
|
+
hasActionRail,
|
|
570
|
+
rootProps,
|
|
571
|
+
rest,
|
|
572
|
+
width,
|
|
573
|
+
offset,
|
|
574
|
+
zIndex,
|
|
575
|
+
id,
|
|
576
|
+
open
|
|
577
|
+
} = shell;
|
|
578
|
+
const { className, style, ...domRest } = rest;
|
|
579
|
+
return /* @__PURE__ */ jsx5(BaseDrawer3.Root, { ...rootProps, children: /* @__PURE__ */ jsxs3(BaseDrawer3.Portal, { children: [
|
|
580
|
+
/* @__PURE__ */ jsx5(
|
|
581
|
+
BaseDrawer3.Backdrop,
|
|
582
|
+
{
|
|
583
|
+
"data-testid": "drawer-backdrop",
|
|
584
|
+
className: "seeds-drawer-backdrop"
|
|
585
|
+
}
|
|
586
|
+
),
|
|
587
|
+
/* @__PURE__ */ jsx5(
|
|
588
|
+
BaseDrawer3.Viewport,
|
|
589
|
+
{
|
|
590
|
+
className: cn("seeds-drawer-viewport", {
|
|
591
|
+
"seeds-drawer-viewport--snap": hasSnapPoints
|
|
592
|
+
}),
|
|
593
|
+
children: /* @__PURE__ */ jsxs3(
|
|
594
|
+
BaseDrawer3.Popup,
|
|
595
|
+
{
|
|
596
|
+
initialFocus: true,
|
|
597
|
+
"data-qa-drawer": id,
|
|
598
|
+
"data-qa-drawer-isopen": open,
|
|
599
|
+
...domRest,
|
|
600
|
+
className: cn(
|
|
601
|
+
"seeds-drawer-popup",
|
|
602
|
+
effectiveDirection === "bottom" ? "seeds-drawer-popup--bottom" : "seeds-drawer-popup--side",
|
|
603
|
+
effectiveDirection === "right" && "seeds-drawer-popup--right",
|
|
604
|
+
effectiveDirection === "left" && "seeds-drawer-popup--left",
|
|
605
|
+
{
|
|
606
|
+
"seeds-drawer-popup--snap": hasSnapPoints,
|
|
607
|
+
"seeds-drawer-popup--action-rail": hasActionRail
|
|
608
|
+
},
|
|
609
|
+
// Consumer className folded in last so it appends to (not
|
|
610
|
+
// replaces) the component classes.
|
|
611
|
+
className
|
|
612
|
+
),
|
|
613
|
+
style: {
|
|
614
|
+
// z-index is always inline (runtime numeric, mirrors styles.ts).
|
|
615
|
+
zIndex,
|
|
616
|
+
// Side drawers carry their width/offset as direct inline styles —
|
|
617
|
+
// runtime numerics, and required for the jsdom `toHaveStyle`
|
|
618
|
+
// assertions. Bottom drawers derive width/position from the class.
|
|
619
|
+
...effectiveDirection === "right" ? { width: `${width}px`, right: `${offset}px` } : effectiveDirection === "left" ? { width: `${width}px`, left: `${offset}px` } : {},
|
|
620
|
+
// Consumer style folded in last so it wins over the computed
|
|
621
|
+
// geometry, matching the styled-components inline-style semantics.
|
|
622
|
+
...style
|
|
623
|
+
},
|
|
624
|
+
children: [
|
|
625
|
+
effectiveDirection === "bottom" && /* @__PURE__ */ jsx5("div", { "aria-hidden": true, className: "seeds-drawer-drag-handle" }),
|
|
626
|
+
/* @__PURE__ */ jsx5(DrawerPopupContents, { shell })
|
|
627
|
+
]
|
|
628
|
+
}
|
|
629
|
+
)
|
|
630
|
+
}
|
|
631
|
+
)
|
|
632
|
+
] }) });
|
|
262
633
|
};
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
634
|
+
var DrawerTailwind_default = DrawerTailwind;
|
|
635
|
+
|
|
636
|
+
// src/DrawerHybrid.tsx
|
|
637
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
638
|
+
var DRAWER_OWN_PROPS = [
|
|
639
|
+
"children",
|
|
640
|
+
"closeButtonLabel",
|
|
641
|
+
"direction",
|
|
642
|
+
"disableCloseOnClickOutside",
|
|
643
|
+
"id",
|
|
644
|
+
"modal",
|
|
645
|
+
"open",
|
|
646
|
+
"offset",
|
|
647
|
+
"onClose",
|
|
648
|
+
"zIndex",
|
|
649
|
+
"width",
|
|
650
|
+
"snapPoints",
|
|
651
|
+
"defaultSnapPoint",
|
|
652
|
+
"snapPoint",
|
|
653
|
+
"onSnapPointChange",
|
|
654
|
+
"snapToSequentialPoints",
|
|
655
|
+
"actions",
|
|
656
|
+
"actionsInHeader"
|
|
657
|
+
];
|
|
658
|
+
var DrawerHybrid = (props) => {
|
|
659
|
+
const rest = {};
|
|
660
|
+
for (const key of Object.keys(props)) {
|
|
661
|
+
if (!DRAWER_OWN_PROPS.includes(key)) {
|
|
662
|
+
rest[key] = props[key];
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (hasStyledProps(rest)) {
|
|
666
|
+
return /* @__PURE__ */ jsx6(DrawerStyled_default, { ...props });
|
|
667
|
+
}
|
|
668
|
+
return /* @__PURE__ */ jsx6(DrawerTailwind_default, { ...props });
|
|
669
|
+
};
|
|
670
|
+
DrawerHybrid.Header = DrawerHeader;
|
|
671
|
+
DrawerHybrid.Content = DrawerContent;
|
|
672
|
+
DrawerHybrid.CloseButton = DrawerCloseButton;
|
|
673
|
+
var DrawerHybrid_default = DrawerHybrid;
|
|
674
|
+
|
|
675
|
+
// src/Drawer.tsx
|
|
676
|
+
var Drawer_default = DrawerHybrid_default;
|
|
270
677
|
|
|
271
678
|
// src/DrawerTypes.ts
|
|
272
679
|
import "react";
|
|
@@ -274,8 +681,14 @@ import "react";
|
|
|
274
681
|
// src/index.ts
|
|
275
682
|
var index_default = Drawer_default;
|
|
276
683
|
export {
|
|
684
|
+
ActionRail,
|
|
685
|
+
ActionRailButton,
|
|
277
686
|
Drawer_default as Drawer,
|
|
278
687
|
DrawerContext,
|
|
688
|
+
RAIL_BUTTON_HEIGHT,
|
|
689
|
+
RAIL_BUTTON_SIZE,
|
|
690
|
+
RAIL_GAP,
|
|
691
|
+
RAIL_OFFSET,
|
|
279
692
|
index_default as default
|
|
280
693
|
};
|
|
281
694
|
//# sourceMappingURL=index.js.map
|