@xsolla/xui-b2b-drawer 0.158.0 → 0.159.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/README.md +98 -58
- package/native/index.d.mts +2 -0
- package/native/index.d.ts +2 -0
- package/native/index.js +13 -2
- package/native/index.js.map +1 -1
- package/native/index.mjs +13 -2
- package/native/index.mjs.map +1 -1
- package/package.json +7 -7
- package/web/index.d.mts +2 -0
- package/web/index.d.ts +2 -0
- package/web/index.js +13 -2
- package/web/index.js.map +1 -1
- package/web/index.mjs +13 -2
- package/web/index.mjs.map +1 -1
package/README.md
CHANGED
|
@@ -19,23 +19,28 @@ import {
|
|
|
19
19
|
type DrawerFooterAlign,
|
|
20
20
|
type UseDrawerOptions,
|
|
21
21
|
type UseDrawerReturn,
|
|
22
|
-
} from
|
|
22
|
+
} from "@xsolla/xui-b2b-drawer";
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
## Quick start
|
|
26
26
|
|
|
27
27
|
```tsx
|
|
28
|
-
import { useState } from
|
|
29
|
-
import { Drawer } from
|
|
30
|
-
import { Button } from
|
|
31
|
-
import { Typography } from
|
|
28
|
+
import { useState } from "react";
|
|
29
|
+
import { Drawer } from "@xsolla/xui-b2b-drawer";
|
|
30
|
+
import { Button } from "@xsolla/xui-button";
|
|
31
|
+
import { Typography } from "@xsolla/xui-typography";
|
|
32
32
|
|
|
33
33
|
function BasicDrawer() {
|
|
34
34
|
const [open, setOpen] = useState(false);
|
|
35
35
|
|
|
36
36
|
return (
|
|
37
37
|
<>
|
|
38
|
-
<Button
|
|
38
|
+
<Button
|
|
39
|
+
variant="primary"
|
|
40
|
+
tone="brand"
|
|
41
|
+
size="sm"
|
|
42
|
+
onPress={() => setOpen(true)}
|
|
43
|
+
>
|
|
39
44
|
Open drawer
|
|
40
45
|
</Button>
|
|
41
46
|
<Drawer
|
|
@@ -44,10 +49,20 @@ function BasicDrawer() {
|
|
|
44
49
|
title="Settings"
|
|
45
50
|
footer={
|
|
46
51
|
<>
|
|
47
|
-
<Button
|
|
52
|
+
<Button
|
|
53
|
+
variant="secondary"
|
|
54
|
+
tone="mono"
|
|
55
|
+
size="sm"
|
|
56
|
+
onPress={() => setOpen(false)}
|
|
57
|
+
>
|
|
48
58
|
Cancel
|
|
49
59
|
</Button>
|
|
50
|
-
<Button
|
|
60
|
+
<Button
|
|
61
|
+
variant="primary"
|
|
62
|
+
tone="brand"
|
|
63
|
+
size="sm"
|
|
64
|
+
onPress={() => setOpen(false)}
|
|
65
|
+
>
|
|
51
66
|
Save
|
|
52
67
|
</Button>
|
|
53
68
|
</>
|
|
@@ -64,33 +79,34 @@ function BasicDrawer() {
|
|
|
64
79
|
|
|
65
80
|
### `<Drawer>`
|
|
66
81
|
|
|
67
|
-
| Prop
|
|
68
|
-
|
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
82
|
+
| Prop | Type | Default | Description |
|
|
83
|
+
| --------------------- | ------------------------ | --------- | ------------------------------------------------------------------------------------------------------------- |
|
|
84
|
+
| `testID` | `string` | — | Test ID for testing frameworks. On web this renders as `data-testid`; on React Native it renders as `testID`. |
|
|
85
|
+
| `open` | `boolean` | `false` | Whether the drawer is visible. |
|
|
86
|
+
| `onClose` | `() => void` | — | Called when the drawer should close (Escape, overlay click, close button). |
|
|
87
|
+
| `size` | `DrawerSize` | `"md"` | Width preset: `sm` 480px, `md` 620px, `lg` 1056px. |
|
|
88
|
+
| `title` | `ReactNode` | — | Title displayed in the header. |
|
|
89
|
+
| `onBack` | `() => void` | — | When provided, renders a back arrow button in the header. |
|
|
90
|
+
| `headerAction` | `ReactNode` | — | Element rendered between the title and the close button. |
|
|
91
|
+
| `closeOnOverlayClick` | `boolean` | `true` | Whether clicking the backdrop closes the drawer. |
|
|
92
|
+
| `closeOnEscape` | `boolean` | `true` | Whether pressing Escape closes the drawer. |
|
|
93
|
+
| `footer` | `ReactNode` | — | Footer content (typically action buttons). |
|
|
94
|
+
| `footerAlign` | `DrawerFooterAlign` | `"right"` | Alignment of footer content. |
|
|
95
|
+
| `footerShadow` | `boolean` | `false` | Show a drop shadow above the footer (useful with scrollable content). |
|
|
96
|
+
| `footerFullWidth` | `boolean` | `true` | Whether footer buttons stretch to full width. |
|
|
97
|
+
| `stepper` | `ReactNode` | — | Stepper sidebar rendered to the left of the content panel. |
|
|
98
|
+
| `children` | `ReactNode` | — | **Required.** Main scrollable body content. |
|
|
99
|
+
| `initialFocusRef` | `RefObject<HTMLElement>` | — | Ref to the element that should receive focus when the drawer opens. |
|
|
84
100
|
|
|
85
101
|
Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).
|
|
86
102
|
|
|
87
103
|
#### Deprecated props
|
|
88
104
|
|
|
89
|
-
| Prop
|
|
90
|
-
|
|
|
91
|
-
| `isOpen`
|
|
105
|
+
| Prop | Replacement |
|
|
106
|
+
| ------------------------------ | ------------------ |
|
|
107
|
+
| `isOpen` | `open` |
|
|
92
108
|
| `header` (`{ title, onBack }`) | `title` + `onBack` |
|
|
93
|
-
| `bottom`
|
|
109
|
+
| `bottom` | `footer` |
|
|
94
110
|
|
|
95
111
|
### `useDrawer(options?)`
|
|
96
112
|
|
|
@@ -116,8 +132,8 @@ interface UseDrawerReturn {
|
|
|
116
132
|
### Type exports
|
|
117
133
|
|
|
118
134
|
```ts
|
|
119
|
-
type DrawerSize =
|
|
120
|
-
type DrawerFooterAlign =
|
|
135
|
+
type DrawerSize = "sm" | "md" | "lg";
|
|
136
|
+
type DrawerFooterAlign = "center" | "right";
|
|
121
137
|
```
|
|
122
138
|
|
|
123
139
|
## Examples
|
|
@@ -138,7 +154,7 @@ import { Drawer } from '@xsolla/xui-b2b-drawer';
|
|
|
138
154
|
### With back button
|
|
139
155
|
|
|
140
156
|
```tsx
|
|
141
|
-
import { Drawer } from
|
|
157
|
+
import { Drawer } from "@xsolla/xui-b2b-drawer";
|
|
142
158
|
|
|
143
159
|
<Drawer
|
|
144
160
|
open={open}
|
|
@@ -153,8 +169,8 @@ import { Drawer } from '@xsolla/xui-b2b-drawer';
|
|
|
153
169
|
### With header action
|
|
154
170
|
|
|
155
171
|
```tsx
|
|
156
|
-
import { Drawer } from
|
|
157
|
-
import { Button } from
|
|
172
|
+
import { Drawer } from "@xsolla/xui-b2b-drawer";
|
|
173
|
+
import { Button } from "@xsolla/xui-button";
|
|
158
174
|
|
|
159
175
|
<Drawer
|
|
160
176
|
open={open}
|
|
@@ -173,12 +189,12 @@ import { Button } from '@xsolla/xui-button';
|
|
|
173
189
|
### `useDrawer` hook
|
|
174
190
|
|
|
175
191
|
```tsx
|
|
176
|
-
import { Drawer, useDrawer } from
|
|
177
|
-
import { Button } from
|
|
178
|
-
import { Typography } from
|
|
192
|
+
import { Drawer, useDrawer } from "@xsolla/xui-b2b-drawer";
|
|
193
|
+
import { Button } from "@xsolla/xui-button";
|
|
194
|
+
import { Typography } from "@xsolla/xui-typography";
|
|
179
195
|
|
|
180
196
|
function HookExample() {
|
|
181
|
-
const drawer = useDrawer({ onOpen: () => console.log(
|
|
197
|
+
const drawer = useDrawer({ onOpen: () => console.log("opened") });
|
|
182
198
|
return (
|
|
183
199
|
<>
|
|
184
200
|
<Button variant="primary" tone="brand" size="sm" onPress={drawer.open}>
|
|
@@ -195,16 +211,16 @@ function HookExample() {
|
|
|
195
211
|
### With stepper sidebar
|
|
196
212
|
|
|
197
213
|
```tsx
|
|
198
|
-
import { useState } from
|
|
199
|
-
import { Drawer } from
|
|
200
|
-
import { Stepper } from
|
|
201
|
-
import { Button } from
|
|
202
|
-
import { Typography } from
|
|
214
|
+
import { useState } from "react";
|
|
215
|
+
import { Drawer } from "@xsolla/xui-b2b-drawer";
|
|
216
|
+
import { Stepper } from "@xsolla/xui-b2b-stepper";
|
|
217
|
+
import { Button } from "@xsolla/xui-button";
|
|
218
|
+
import { Typography } from "@xsolla/xui-typography";
|
|
203
219
|
|
|
204
220
|
const STEPS = [
|
|
205
|
-
{ title:
|
|
206
|
-
{ title:
|
|
207
|
-
{ title:
|
|
221
|
+
{ title: "Account", description: "Name and email" },
|
|
222
|
+
{ title: "Billing", description: "Payment method" },
|
|
223
|
+
{ title: "Confirm", description: "Review and submit" },
|
|
208
224
|
];
|
|
209
225
|
|
|
210
226
|
function StepperDrawer() {
|
|
@@ -214,15 +230,26 @@ function StepperDrawer() {
|
|
|
214
230
|
const steps = STEPS.map((s, i) => ({
|
|
215
231
|
...s,
|
|
216
232
|
state:
|
|
217
|
-
i < active
|
|
218
|
-
|
|
233
|
+
i < active
|
|
234
|
+
? ("complete" as const)
|
|
235
|
+
: i === active
|
|
236
|
+
? ("current" as const)
|
|
237
|
+
: ("incomplete" as const),
|
|
219
238
|
}));
|
|
220
239
|
|
|
221
240
|
const isLast = active === steps.length - 1;
|
|
222
241
|
|
|
223
242
|
return (
|
|
224
243
|
<>
|
|
225
|
-
<Button
|
|
244
|
+
<Button
|
|
245
|
+
variant="primary"
|
|
246
|
+
tone="brand"
|
|
247
|
+
size="sm"
|
|
248
|
+
onPress={() => {
|
|
249
|
+
setActive(0);
|
|
250
|
+
setOpen(true);
|
|
251
|
+
}}
|
|
252
|
+
>
|
|
226
253
|
Open wizard
|
|
227
254
|
</Button>
|
|
228
255
|
<Drawer
|
|
@@ -240,16 +267,23 @@ function StepperDrawer() {
|
|
|
240
267
|
}
|
|
241
268
|
footer={
|
|
242
269
|
<>
|
|
243
|
-
<Button
|
|
270
|
+
<Button
|
|
271
|
+
variant="secondary"
|
|
272
|
+
tone="mono"
|
|
273
|
+
size="sm"
|
|
274
|
+
onPress={() => setOpen(false)}
|
|
275
|
+
>
|
|
244
276
|
Cancel
|
|
245
277
|
</Button>
|
|
246
278
|
<Button
|
|
247
279
|
variant="primary"
|
|
248
280
|
tone="brand"
|
|
249
281
|
size="sm"
|
|
250
|
-
onPress={() =>
|
|
282
|
+
onPress={() =>
|
|
283
|
+
isLast ? setOpen(false) : setActive((a) => a + 1)
|
|
284
|
+
}
|
|
251
285
|
>
|
|
252
|
-
{isLast ?
|
|
286
|
+
{isLast ? "Submit" : "Next"}
|
|
253
287
|
</Button>
|
|
254
288
|
</>
|
|
255
289
|
}
|
|
@@ -264,20 +298,26 @@ function StepperDrawer() {
|
|
|
264
298
|
### Scrollable content with footer shadow
|
|
265
299
|
|
|
266
300
|
```tsx
|
|
267
|
-
import { Drawer } from
|
|
268
|
-
import { Button } from
|
|
269
|
-
import { Typography } from
|
|
301
|
+
import { Drawer } from "@xsolla/xui-b2b-drawer";
|
|
302
|
+
import { Button } from "@xsolla/xui-button";
|
|
303
|
+
import { Typography } from "@xsolla/xui-typography";
|
|
270
304
|
|
|
271
305
|
<Drawer
|
|
272
306
|
open={open}
|
|
273
307
|
onClose={onClose}
|
|
274
308
|
title="Long content"
|
|
275
309
|
footerShadow
|
|
276
|
-
footer={
|
|
310
|
+
footer={
|
|
311
|
+
<Button variant="primary" tone="brand" size="sm">
|
|
312
|
+
Done
|
|
313
|
+
</Button>
|
|
314
|
+
}
|
|
277
315
|
>
|
|
278
|
-
<div style={{ display:
|
|
316
|
+
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
|
|
279
317
|
{Array.from({ length: 40 }, (_, i) => (
|
|
280
|
-
<Typography key={i} variant="bodyMd">
|
|
318
|
+
<Typography key={i} variant="bodyMd">
|
|
319
|
+
Item {i + 1}
|
|
320
|
+
</Typography>
|
|
281
321
|
))}
|
|
282
322
|
</div>
|
|
283
323
|
</Drawer>;
|
package/native/index.d.mts
CHANGED
|
@@ -46,6 +46,8 @@ interface DrawerProps extends ThemeOverrideProps {
|
|
|
46
46
|
children: ReactNode;
|
|
47
47
|
/** Ref to element that should receive focus when the drawer opens */
|
|
48
48
|
initialFocusRef?: RefObject<HTMLElement>;
|
|
49
|
+
/** Test ID for testing frameworks */
|
|
50
|
+
testID?: string;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
declare const Drawer: react.ForwardRefExoticComponent<DrawerProps & react.RefAttributes<HTMLDivElement>>;
|
package/native/index.d.ts
CHANGED
|
@@ -46,6 +46,8 @@ interface DrawerProps extends ThemeOverrideProps {
|
|
|
46
46
|
children: ReactNode;
|
|
47
47
|
/** Ref to element that should receive focus when the drawer opens */
|
|
48
48
|
initialFocusRef?: RefObject<HTMLElement>;
|
|
49
|
+
/** Test ID for testing frameworks */
|
|
50
|
+
testID?: string;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
declare const Drawer: react.ForwardRefExoticComponent<DrawerProps & react.RefAttributes<HTMLDivElement>>;
|
package/native/index.js
CHANGED
|
@@ -321,7 +321,14 @@ var flattenChildren = (children) => {
|
|
|
321
321
|
return result;
|
|
322
322
|
};
|
|
323
323
|
var DrawerFooter = (0, import_react3.memo)(
|
|
324
|
-
({
|
|
324
|
+
({
|
|
325
|
+
children,
|
|
326
|
+
align,
|
|
327
|
+
shadow,
|
|
328
|
+
fullWidth,
|
|
329
|
+
paddingX,
|
|
330
|
+
paddingY
|
|
331
|
+
}) => {
|
|
325
332
|
const justifyContent = align === "center" ? "center" : "flex-end";
|
|
326
333
|
const renderedChildren = fullWidth ? flattenChildren(children).map(
|
|
327
334
|
(child, i) => import_react3.default.isValidElement(child) ? import_react3.default.cloneElement(
|
|
@@ -347,7 +354,7 @@ var DrawerFooter = (0, import_react3.memo)(
|
|
|
347
354
|
display: "flex",
|
|
348
355
|
flexDirection: "row",
|
|
349
356
|
justifyContent: fullWidth ? "stretch" : justifyContent,
|
|
350
|
-
padding:
|
|
357
|
+
padding: `${paddingY}px ${paddingX}px`,
|
|
351
358
|
gap: 8
|
|
352
359
|
},
|
|
353
360
|
children: renderedChildren
|
|
@@ -396,6 +403,7 @@ var Drawer = (0, import_react4.forwardRef)(
|
|
|
396
403
|
stepper,
|
|
397
404
|
children,
|
|
398
405
|
initialFocusRef,
|
|
406
|
+
testID,
|
|
399
407
|
themeMode,
|
|
400
408
|
themeProductContext
|
|
401
409
|
}, ref) => {
|
|
@@ -497,6 +505,7 @@ var Drawer = (0, import_react4.forwardRef)(
|
|
|
497
505
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
498
506
|
Box,
|
|
499
507
|
{
|
|
508
|
+
testID,
|
|
500
509
|
ref: (node) => {
|
|
501
510
|
drawerRef.current = node;
|
|
502
511
|
if (typeof ref === "function") ref(node);
|
|
@@ -549,6 +558,8 @@ var Drawer = (0, import_react4.forwardRef)(
|
|
|
549
558
|
align: footerAlign,
|
|
550
559
|
shadow: footerShadow,
|
|
551
560
|
fullWidth: footerFullWidth,
|
|
561
|
+
paddingX: sizing.contentPaddingX,
|
|
562
|
+
paddingY: sizing.footerPadding,
|
|
552
563
|
children: footer
|
|
553
564
|
}
|
|
554
565
|
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { flexShrink: 0, height: 32 } })
|
package/native/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.tsx","../../src/Drawer.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../src/DrawerRoot.native.tsx","../../src/DrawerHeader.tsx","../../src/DrawerFooter.tsx","../../src/useDrawer.ts"],"sourcesContent":["export { Drawer } from \"./Drawer\";\nexport { useDrawer } from \"./useDrawer\";\nexport type {\n DrawerProps,\n DrawerSize,\n DrawerFooterAlign,\n LegacyDrawerHeader,\n} from \"./types\";\nexport type { UseDrawerOptions, UseDrawerReturn } from \"./useDrawer\";\n","import { forwardRef, useCallback, useEffect, useRef, useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme } from \"@xsolla/xui-core\";\nimport type { DrawerProps } from \"./types\";\nimport { DrawerRoot } from \"./DrawerRoot\";\nimport { DrawerHeader } from \"./DrawerHeader\";\nimport { DrawerFooter } from \"./DrawerFooter\";\n\nconst FOCUSABLE_SELECTORS =\n 'button:not([disabled]), [href], input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nconst isElementVisible = (el: HTMLElement): boolean => {\n if (el.offsetParent === null && getComputedStyle(el).position !== \"fixed\")\n return false;\n const style = getComputedStyle(el);\n return style.visibility !== \"hidden\" && style.display !== \"none\";\n};\n\nconst getFocusableElements = (container: HTMLElement): HTMLElement[] =>\n Array.from(\n container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTORS)\n ).filter(isElementVisible);\n\nconst DRAWER_WIDTHS: Record<string, number> = {\n sm: 480,\n md: 620,\n lg: 1056,\n};\n\nexport const Drawer = forwardRef<HTMLDivElement, DrawerProps>(\n (\n {\n open: openProp,\n isOpen,\n onClose,\n size = \"md\",\n title: titleProp,\n header: headerProp,\n onBack: onBackProp,\n headerAction,\n closeOnOverlayClick = true,\n closeOnEscape = true,\n footer: footerProp,\n bottom,\n footerAlign = \"right\",\n footerShadow = false,\n footerFullWidth = true,\n stepper,\n children,\n initialFocusRef,\n themeMode,\n themeProductContext,\n },\n ref\n ) => {\n // Resolve legacy aliases — new props take precedence\n const open = openProp ?? isOpen ?? false;\n const title = titleProp ?? headerProp?.title;\n const onBack = onBackProp ?? headerProp?.onBack;\n const footer = footerProp ?? bottom;\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.drawer();\n\n const [mounted, setMounted] = useState(open);\n\n useEffect(() => {\n if (open) setMounted(true);\n }, [open]);\n\n const drawerRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLDivElement>(null);\n const previousActiveElement = useRef<HTMLElement | null>(null);\n\n // Focus management on open/close\n useEffect(() => {\n if (!open) return;\n if (typeof document === \"undefined\") return;\n\n previousActiveElement.current = document.activeElement as HTMLElement;\n\n const focusTarget =\n initialFocusRef?.current ||\n closeButtonRef.current ||\n (drawerRef.current && getFocusableElements(drawerRef.current)[0]);\n\n if (focusTarget) {\n (focusTarget as HTMLElement).focus();\n } else {\n drawerRef.current?.focus();\n }\n\n // Focus is restored inside onExited (after the exit animation) so that\n // keyboard focus does not escape back to the page while the drawer is\n // still visible on screen.\n }, [open, initialFocusRef]);\n\n // Escape key handler\n useEffect(() => {\n if (!open || !closeOnEscape || !onClose) return;\n if (typeof document === \"undefined\") return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, closeOnEscape, onClose]);\n\n // Focus trap\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (event.key !== \"Tab\" || !drawerRef.current) return;\n if (typeof document === \"undefined\") return;\n\n const focusableElements = getFocusableElements(drawerRef.current);\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n if (!firstElement) {\n event.preventDefault();\n return;\n }\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n }, []);\n\n if (!mounted) return null;\n\n const contentWidth = DRAWER_WIDTHS[size];\n\n return (\n <DrawerRoot\n open={open}\n onExited={() => {\n setMounted(false);\n previousActiveElement.current?.focus();\n }}\n onBackdropClick={closeOnOverlayClick ? onClose : undefined}\n scrimColor={sizing.scrimColor}\n outerPadding={sizing.outerPadding}\n animationDuration={sizing.animationDuration}\n zIndex={sizing.zIndex}\n >\n {/* Outer panel — white background + container radius clips the inner content corners */}\n <div\n style={{\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"stretch\",\n backgroundColor: theme.colors.background.primary,\n borderRadius: sizing.containerRadius,\n overflow: \"hidden\",\n gap: stepper ? sizing.stepperContentGap : 0,\n }}\n >\n {/* Optional stepper sidebar */}\n {stepper && (\n <div\n style={{\n flexShrink: 0,\n alignSelf: \"stretch\",\n backgroundColor: theme.colors.background.secondary,\n borderRadius: sizing.contentRadius,\n padding: sizing.stepperPadding,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {stepper}\n </div>\n )}\n\n {/* Content panel */}\n <Box\n ref={(node: HTMLDivElement | null) => {\n (\n drawerRef as React.MutableRefObject<HTMLDivElement | null>\n ).current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref)\n (ref as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n }}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={typeof title === \"string\" ? title : undefined}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n style={{\n width: contentWidth,\n height: \"100%\",\n flexShrink: 0,\n display: \"flex\",\n flexDirection: \"column\",\n outline: \"none\",\n color: theme.colors.content.primary,\n }}\n >\n {/* Header */}\n <DrawerHeader\n title={title}\n onBack={onBack}\n onClose={onClose}\n headerAction={headerAction}\n paddingX={sizing.headerPaddingX}\n paddingY={sizing.headerPaddingY}\n gap={sizing.headerGap}\n />\n\n {/* Body */}\n <Box\n style={{\n flex: 1,\n minHeight: 0,\n overflowY: \"auto\",\n paddingLeft: sizing.contentPaddingX,\n paddingRight: sizing.contentPaddingX,\n }}\n >\n {children}\n </Box>\n\n {/* Footer */}\n {footer ? (\n <DrawerFooter\n align={footerAlign}\n shadow={footerShadow}\n fullWidth={footerFullWidth}\n >\n {footer}\n </DrawerFooter>\n ) : (\n <div style={{ flexShrink: 0, height: 32 }} />\n )}\n </Box>\n </div>\n </DrawerRoot>\n );\n }\n);\n\nDrawer.displayName = \"Drawer\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n minWidth,\n minHeight,\n maxWidth,\n maxHeight,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n minWidth: minWidth as DimensionValue,\n minHeight: minHeight as DimensionValue,\n maxWidth: maxWidth as DimensionValue,\n maxHeight: maxHeight as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import { memo } from \"react\";\nimport type { DrawerRootProps } from \"./types\";\n\n// Web portal not available on React Native.\n// Native drawer implementation would use RN-specific approach (e.g. Animated.View).\nexport const DrawerRoot = memo((_props: DrawerRootProps) => {\n return null;\n});\n\nDrawerRoot.displayName = \"DrawerRoot\";\n","import { memo } from \"react\";\nimport { IconButton } from \"@xsolla/xui-button\";\nimport { ArrowLeft, Remove } from \"@xsolla/xui-icons-base\";\nimport { Typography } from \"@xsolla/xui-typography\";\nimport type { DrawerHeaderProps } from \"./types\";\n\nexport const DrawerHeader = memo(\n ({\n title,\n onBack,\n onClose,\n headerAction,\n paddingX,\n paddingY,\n gap,\n }: DrawerHeaderProps) => {\n return (\n <div\n style={{\n flexShrink: 0,\n height: 80,\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n paddingLeft: paddingX,\n paddingRight: paddingX,\n paddingTop: paddingY,\n paddingBottom: paddingY,\n gap,\n boxSizing: \"border-box\",\n }}\n >\n {/* Left content: back button + title */}\n <div\n style={{\n flex: 1,\n minWidth: 0,\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 16,\n }}\n >\n {/* Back button */}\n {onBack && (\n <IconButton\n variant=\"secondary\"\n tone=\"mono\"\n size=\"xs\"\n icon={<ArrowLeft />}\n onPress={onBack}\n aria-label=\"Go back\"\n />\n )}\n\n {/* Title */}\n {title && (\n <div style={{ flex: 1, minWidth: 0, overflow: \"hidden\" }}>\n <Typography variant=\"bodyLgAccent\" noWrap>\n {title}\n </Typography>\n </div>\n )}\n </div>\n\n {/* Optional header action */}\n {headerAction && <div style={{ flexShrink: 0 }}>{headerAction}</div>}\n\n {/* Close button */}\n {onClose && (\n <IconButton\n variant=\"secondary\"\n tone=\"mono\"\n size=\"xs\"\n icon={<Remove />}\n onPress={onClose}\n aria-label=\"Close drawer\"\n />\n )}\n </div>\n );\n }\n);\n\nDrawerHeader.displayName = \"DrawerHeader\";\n","import React, { memo } from \"react\";\nimport type { DrawerFooterProps } from \"./types\";\n\nconst flattenChildren = (children: React.ReactNode): React.ReactNode[] => {\n const result: React.ReactNode[] = [];\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child) && child.type === React.Fragment) {\n result.push(\n ...flattenChildren(\n (child.props as { children: React.ReactNode }).children\n )\n );\n } else if (child !== null && child !== undefined) {\n result.push(child);\n }\n });\n return result;\n};\n\nexport const DrawerFooter = memo(\n ({ children, align, shadow, fullWidth }: DrawerFooterProps) => {\n const justifyContent = align === \"center\" ? \"center\" : \"flex-end\";\n\n const renderedChildren = fullWidth\n ? flattenChildren(children).map((child, i) =>\n React.isValidElement(child)\n ? React.cloneElement(\n child as React.ReactElement<Record<string, unknown>>,\n {\n key: (child as React.ReactElement).key ?? i,\n fullWidth: true,\n }\n )\n : child\n )\n : children;\n\n return (\n <div\n style={{\n flexShrink: 0,\n width: \"100%\",\n boxShadow: shadow ? \"0px 2px 25px 0px rgba(7, 7, 8, 0.15)\" : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n justifyContent: fullWidth ? \"stretch\" : justifyContent,\n padding: 16,\n gap: 8,\n }}\n >\n {renderedChildren}\n </div>\n </div>\n );\n }\n);\n\nDrawerFooter.displayName = \"DrawerFooter\";\n","import { useCallback, useState } from \"react\";\n\nexport interface UseDrawerOptions {\n onOpen?: () => void;\n onClose?: () => void;\n}\n\nexport interface UseDrawerReturn {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n}\n\nexport function useDrawer(options?: UseDrawerOptions): UseDrawerReturn {\n const [isOpen, setIsOpen] = useState(false);\n\n const open = useCallback(() => {\n setIsOpen(true);\n options?.onOpen?.();\n }, [options]);\n\n const close = useCallback(() => {\n setIsOpen(false);\n options?.onClose?.();\n }, [options]);\n\n return { isOpen, open, close };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","React","import_jsx_runtime","handleKeyDown","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.tsx","../../src/Drawer.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../src/DrawerRoot.native.tsx","../../src/DrawerHeader.tsx","../../src/DrawerFooter.tsx","../../src/useDrawer.ts"],"sourcesContent":["export { Drawer } from \"./Drawer\";\nexport { useDrawer } from \"./useDrawer\";\nexport type {\n DrawerProps,\n DrawerSize,\n DrawerFooterAlign,\n LegacyDrawerHeader,\n} from \"./types\";\nexport type { UseDrawerOptions, UseDrawerReturn } from \"./useDrawer\";\n","import { forwardRef, useCallback, useEffect, useRef, useState } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme } from \"@xsolla/xui-core\";\nimport type { DrawerProps } from \"./types\";\nimport { DrawerRoot } from \"./DrawerRoot\";\nimport { DrawerHeader } from \"./DrawerHeader\";\nimport { DrawerFooter } from \"./DrawerFooter\";\n\nconst FOCUSABLE_SELECTORS =\n 'button:not([disabled]), [href], input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nconst isElementVisible = (el: HTMLElement): boolean => {\n if (el.offsetParent === null && getComputedStyle(el).position !== \"fixed\")\n return false;\n const style = getComputedStyle(el);\n return style.visibility !== \"hidden\" && style.display !== \"none\";\n};\n\nconst getFocusableElements = (container: HTMLElement): HTMLElement[] =>\n Array.from(\n container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTORS)\n ).filter(isElementVisible);\n\nconst DRAWER_WIDTHS: Record<string, number> = {\n sm: 480,\n md: 620,\n lg: 1056,\n};\n\nexport const Drawer = forwardRef<HTMLDivElement, DrawerProps>(\n (\n {\n open: openProp,\n isOpen,\n onClose,\n size = \"md\",\n title: titleProp,\n header: headerProp,\n onBack: onBackProp,\n headerAction,\n closeOnOverlayClick = true,\n closeOnEscape = true,\n footer: footerProp,\n bottom,\n footerAlign = \"right\",\n footerShadow = false,\n footerFullWidth = true,\n stepper,\n children,\n initialFocusRef,\n testID,\n themeMode,\n themeProductContext,\n },\n ref\n ) => {\n // Resolve legacy aliases — new props take precedence\n const open = openProp ?? isOpen ?? false;\n const title = titleProp ?? headerProp?.title;\n const onBack = onBackProp ?? headerProp?.onBack;\n const footer = footerProp ?? bottom;\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.drawer();\n\n const [mounted, setMounted] = useState(open);\n\n useEffect(() => {\n if (open) setMounted(true);\n }, [open]);\n\n const drawerRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLDivElement>(null);\n const previousActiveElement = useRef<HTMLElement | null>(null);\n\n // Focus management on open/close\n useEffect(() => {\n if (!open) return;\n if (typeof document === \"undefined\") return;\n\n previousActiveElement.current = document.activeElement as HTMLElement;\n\n const focusTarget =\n initialFocusRef?.current ||\n closeButtonRef.current ||\n (drawerRef.current && getFocusableElements(drawerRef.current)[0]);\n\n if (focusTarget) {\n (focusTarget as HTMLElement).focus();\n } else {\n drawerRef.current?.focus();\n }\n\n // Focus is restored inside onExited (after the exit animation) so that\n // keyboard focus does not escape back to the page while the drawer is\n // still visible on screen.\n }, [open, initialFocusRef]);\n\n // Escape key handler\n useEffect(() => {\n if (!open || !closeOnEscape || !onClose) return;\n if (typeof document === \"undefined\") return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onClose();\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, closeOnEscape, onClose]);\n\n // Focus trap\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (event.key !== \"Tab\" || !drawerRef.current) return;\n if (typeof document === \"undefined\") return;\n\n const focusableElements = getFocusableElements(drawerRef.current);\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n if (!firstElement) {\n event.preventDefault();\n return;\n }\n\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n } else if (!event.shiftKey && document.activeElement === lastElement) {\n event.preventDefault();\n firstElement.focus();\n }\n }, []);\n\n if (!mounted) return null;\n\n const contentWidth = DRAWER_WIDTHS[size];\n\n return (\n <DrawerRoot\n open={open}\n onExited={() => {\n setMounted(false);\n previousActiveElement.current?.focus();\n }}\n onBackdropClick={closeOnOverlayClick ? onClose : undefined}\n scrimColor={sizing.scrimColor}\n outerPadding={sizing.outerPadding}\n animationDuration={sizing.animationDuration}\n zIndex={sizing.zIndex}\n >\n {/* Outer panel — white background + container radius clips the inner content corners */}\n <div\n style={{\n height: \"100%\",\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"stretch\",\n backgroundColor: theme.colors.background.primary,\n borderRadius: sizing.containerRadius,\n overflow: \"hidden\",\n gap: stepper ? sizing.stepperContentGap : 0,\n }}\n >\n {/* Optional stepper sidebar */}\n {stepper && (\n <div\n style={{\n flexShrink: 0,\n alignSelf: \"stretch\",\n backgroundColor: theme.colors.background.secondary,\n borderRadius: sizing.contentRadius,\n padding: sizing.stepperPadding,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n {stepper}\n </div>\n )}\n\n {/* Content panel */}\n <Box\n testID={testID}\n ref={(node: HTMLDivElement | null) => {\n (\n drawerRef as React.MutableRefObject<HTMLDivElement | null>\n ).current = node;\n if (typeof ref === \"function\") ref(node);\n else if (ref)\n (ref as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n }}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={typeof title === \"string\" ? title : undefined}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n style={{\n width: contentWidth,\n height: \"100%\",\n flexShrink: 0,\n display: \"flex\",\n flexDirection: \"column\",\n outline: \"none\",\n color: theme.colors.content.primary,\n }}\n >\n {/* Header */}\n <DrawerHeader\n title={title}\n onBack={onBack}\n onClose={onClose}\n headerAction={headerAction}\n paddingX={sizing.headerPaddingX}\n paddingY={sizing.headerPaddingY}\n gap={sizing.headerGap}\n />\n\n {/* Body */}\n <Box\n style={{\n flex: 1,\n minHeight: 0,\n overflowY: \"auto\",\n paddingLeft: sizing.contentPaddingX,\n paddingRight: sizing.contentPaddingX,\n }}\n >\n {children}\n </Box>\n\n {/* Footer */}\n {footer ? (\n <DrawerFooter\n align={footerAlign}\n shadow={footerShadow}\n fullWidth={footerFullWidth}\n paddingX={sizing.contentPaddingX}\n paddingY={sizing.footerPadding}\n >\n {footer}\n </DrawerFooter>\n ) : (\n <div style={{ flexShrink: 0, height: 32 }} />\n )}\n </Box>\n </div>\n </DrawerRoot>\n );\n }\n);\n\nDrawer.displayName = \"Drawer\";\n","import React from \"react\";\nimport {\n View,\n Pressable,\n Image,\n ViewStyle,\n ImageStyle,\n DimensionValue,\n AnimatableNumericValue,\n} from \"react-native\";\nimport { BoxProps } from \"@xsolla/xui-primitives-core\";\n\nexport const Box: React.FC<BoxProps> = ({\n children,\n onPress,\n onLayout,\n onMoveShouldSetResponder,\n onResponderGrant,\n onResponderMove,\n onResponderRelease,\n onResponderTerminate,\n backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius,\n borderStyle,\n height,\n padding,\n paddingHorizontal,\n paddingVertical,\n margin,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n flexDirection,\n alignItems,\n justifyContent,\n position,\n top,\n bottom,\n left,\n right,\n width,\n minWidth,\n minHeight,\n maxWidth,\n maxHeight,\n flex,\n overflow,\n zIndex,\n hoverStyle,\n pressStyle,\n style,\n \"data-testid\": dataTestId,\n testID,\n as,\n src,\n alt,\n ...rest\n}) => {\n const getContainerStyle = (pressed?: boolean): ViewStyle => ({\n backgroundColor:\n pressed && pressStyle?.backgroundColor\n ? pressStyle.backgroundColor\n : backgroundColor,\n borderColor,\n borderWidth,\n borderBottomWidth,\n borderBottomColor,\n borderTopWidth,\n borderTopColor,\n borderLeftWidth,\n borderLeftColor,\n borderRightWidth,\n borderRightColor,\n borderRadius: borderRadius as AnimatableNumericValue,\n borderStyle: borderStyle as ViewStyle[\"borderStyle\"],\n overflow,\n zIndex,\n height: height as DimensionValue,\n width: width as DimensionValue,\n minWidth: minWidth as DimensionValue,\n minHeight: minHeight as DimensionValue,\n maxWidth: maxWidth as DimensionValue,\n maxHeight: maxHeight as DimensionValue,\n padding: padding as DimensionValue,\n paddingHorizontal: paddingHorizontal as DimensionValue,\n paddingVertical: paddingVertical as DimensionValue,\n margin: margin as DimensionValue,\n marginTop: marginTop as DimensionValue,\n marginBottom: marginBottom as DimensionValue,\n marginLeft: marginLeft as DimensionValue,\n marginRight: marginRight as DimensionValue,\n flexDirection,\n alignItems,\n justifyContent,\n position: position as ViewStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n flex,\n ...(style as ViewStyle),\n });\n\n const finalTestID = dataTestId || testID;\n\n // Destructure and drop web-only props from rest before passing to RN components\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const {\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n \"aria-label\": _ariaLabel,\n \"aria-labelledby\": _ariaLabelledBy,\n \"aria-current\": _ariaCurrent,\n \"aria-disabled\": _ariaDisabled,\n \"aria-live\": _ariaLive,\n className,\n \"data-testid\": _dataTestId,\n ...nativeRest\n } = rest as Record<string, unknown>;\n\n // Handle as=\"img\" for React Native\n if (as === \"img\" && src) {\n const imageStyle: ImageStyle = {\n width: width as DimensionValue,\n height: height as DimensionValue,\n borderRadius: borderRadius as number,\n position: position as ImageStyle[\"position\"],\n top: top as DimensionValue,\n bottom: bottom as DimensionValue,\n left: left as DimensionValue,\n right: right as DimensionValue,\n ...(style as ImageStyle),\n };\n\n return (\n <Image\n source={{ uri: src }}\n style={imageStyle}\n testID={finalTestID}\n resizeMode=\"cover\"\n {...nativeRest}\n />\n );\n }\n\n if (onPress) {\n return (\n <Pressable\n onPress={onPress}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n style={({ pressed }) => getContainerStyle(pressed)}\n testID={finalTestID}\n {...nativeRest}\n >\n {children}\n </Pressable>\n );\n }\n\n return (\n <View\n style={getContainerStyle()}\n testID={finalTestID}\n onLayout={onLayout}\n onMoveShouldSetResponder={onMoveShouldSetResponder}\n onResponderGrant={onResponderGrant}\n onResponderMove={onResponderMove}\n onResponderRelease={onResponderRelease}\n onResponderTerminate={onResponderTerminate}\n {...nativeRest}\n >\n {children}\n </View>\n );\n};\n","import { memo } from \"react\";\nimport type { DrawerRootProps } from \"./types\";\n\n// Web portal not available on React Native.\n// Native drawer implementation would use RN-specific approach (e.g. Animated.View).\nexport const DrawerRoot = memo((_props: DrawerRootProps) => {\n return null;\n});\n\nDrawerRoot.displayName = \"DrawerRoot\";\n","import { memo } from \"react\";\nimport { IconButton } from \"@xsolla/xui-button\";\nimport { ArrowLeft, Remove } from \"@xsolla/xui-icons-base\";\nimport { Typography } from \"@xsolla/xui-typography\";\nimport type { DrawerHeaderProps } from \"./types\";\n\nexport const DrawerHeader = memo(\n ({\n title,\n onBack,\n onClose,\n headerAction,\n paddingX,\n paddingY,\n gap,\n }: DrawerHeaderProps) => {\n return (\n <div\n style={{\n flexShrink: 0,\n height: 80,\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n paddingLeft: paddingX,\n paddingRight: paddingX,\n paddingTop: paddingY,\n paddingBottom: paddingY,\n gap,\n boxSizing: \"border-box\",\n }}\n >\n {/* Left content: back button + title */}\n <div\n style={{\n flex: 1,\n minWidth: 0,\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: 16,\n }}\n >\n {/* Back button */}\n {onBack && (\n <IconButton\n variant=\"secondary\"\n tone=\"mono\"\n size=\"xs\"\n icon={<ArrowLeft />}\n onPress={onBack}\n aria-label=\"Go back\"\n />\n )}\n\n {/* Title */}\n {title && (\n <div style={{ flex: 1, minWidth: 0, overflow: \"hidden\" }}>\n <Typography variant=\"bodyLgAccent\" noWrap>\n {title}\n </Typography>\n </div>\n )}\n </div>\n\n {/* Optional header action */}\n {headerAction && <div style={{ flexShrink: 0 }}>{headerAction}</div>}\n\n {/* Close button */}\n {onClose && (\n <IconButton\n variant=\"secondary\"\n tone=\"mono\"\n size=\"xs\"\n icon={<Remove />}\n onPress={onClose}\n aria-label=\"Close drawer\"\n />\n )}\n </div>\n );\n }\n);\n\nDrawerHeader.displayName = \"DrawerHeader\";\n","import React, { memo } from \"react\";\nimport type { DrawerFooterProps } from \"./types\";\n\nconst flattenChildren = (children: React.ReactNode): React.ReactNode[] => {\n const result: React.ReactNode[] = [];\n React.Children.forEach(children, (child) => {\n if (React.isValidElement(child) && child.type === React.Fragment) {\n result.push(\n ...flattenChildren(\n (child.props as { children: React.ReactNode }).children\n )\n );\n } else if (child !== null && child !== undefined) {\n result.push(child);\n }\n });\n return result;\n};\n\nexport const DrawerFooter = memo(\n ({\n children,\n align,\n shadow,\n fullWidth,\n paddingX,\n paddingY,\n }: DrawerFooterProps) => {\n const justifyContent = align === \"center\" ? \"center\" : \"flex-end\";\n\n const renderedChildren = fullWidth\n ? flattenChildren(children).map((child, i) =>\n React.isValidElement(child)\n ? React.cloneElement(\n child as React.ReactElement<Record<string, unknown>>,\n {\n key: (child as React.ReactElement).key ?? i,\n fullWidth: true,\n }\n )\n : child\n )\n : children;\n\n return (\n <div\n style={{\n flexShrink: 0,\n width: \"100%\",\n boxShadow: shadow ? \"0px 2px 25px 0px rgba(7, 7, 8, 0.15)\" : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n justifyContent: fullWidth ? \"stretch\" : justifyContent,\n padding: `${paddingY}px ${paddingX}px`,\n gap: 8,\n }}\n >\n {renderedChildren}\n </div>\n </div>\n );\n }\n);\n\nDrawerFooter.displayName = \"DrawerFooter\";\n","import { useCallback, useState } from \"react\";\n\nexport interface UseDrawerOptions {\n onOpen?: () => void;\n onClose?: () => void;\n}\n\nexport interface UseDrawerReturn {\n isOpen: boolean;\n open: () => void;\n close: () => void;\n}\n\nexport function useDrawer(options?: UseDrawerOptions): UseDrawerReturn {\n const [isOpen, setIsOpen] = useState(false);\n\n const open = useCallback(() => {\n setIsOpen(true);\n options?.onOpen?.();\n }, [options]);\n\n const close = useCallback(() => {\n setIsOpen(false);\n options?.onClose?.();\n }, [options]);\n\n return { isOpen, open, close };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_react","import_jsx_runtime","React","import_jsx_runtime","handleKeyDown","import_react"]}
|
package/native/index.mjs
CHANGED
|
@@ -288,7 +288,14 @@ var flattenChildren = (children) => {
|
|
|
288
288
|
return result;
|
|
289
289
|
};
|
|
290
290
|
var DrawerFooter = memo3(
|
|
291
|
-
({
|
|
291
|
+
({
|
|
292
|
+
children,
|
|
293
|
+
align,
|
|
294
|
+
shadow,
|
|
295
|
+
fullWidth,
|
|
296
|
+
paddingX,
|
|
297
|
+
paddingY
|
|
298
|
+
}) => {
|
|
292
299
|
const justifyContent = align === "center" ? "center" : "flex-end";
|
|
293
300
|
const renderedChildren = fullWidth ? flattenChildren(children).map(
|
|
294
301
|
(child, i) => React.isValidElement(child) ? React.cloneElement(
|
|
@@ -314,7 +321,7 @@ var DrawerFooter = memo3(
|
|
|
314
321
|
display: "flex",
|
|
315
322
|
flexDirection: "row",
|
|
316
323
|
justifyContent: fullWidth ? "stretch" : justifyContent,
|
|
317
|
-
padding:
|
|
324
|
+
padding: `${paddingY}px ${paddingX}px`,
|
|
318
325
|
gap: 8
|
|
319
326
|
},
|
|
320
327
|
children: renderedChildren
|
|
@@ -363,6 +370,7 @@ var Drawer = forwardRef(
|
|
|
363
370
|
stepper,
|
|
364
371
|
children,
|
|
365
372
|
initialFocusRef,
|
|
373
|
+
testID,
|
|
366
374
|
themeMode,
|
|
367
375
|
themeProductContext
|
|
368
376
|
}, ref) => {
|
|
@@ -464,6 +472,7 @@ var Drawer = forwardRef(
|
|
|
464
472
|
/* @__PURE__ */ jsxs2(
|
|
465
473
|
Box,
|
|
466
474
|
{
|
|
475
|
+
testID,
|
|
467
476
|
ref: (node) => {
|
|
468
477
|
drawerRef.current = node;
|
|
469
478
|
if (typeof ref === "function") ref(node);
|
|
@@ -516,6 +525,8 @@ var Drawer = forwardRef(
|
|
|
516
525
|
align: footerAlign,
|
|
517
526
|
shadow: footerShadow,
|
|
518
527
|
fullWidth: footerFullWidth,
|
|
528
|
+
paddingX: sizing.contentPaddingX,
|
|
529
|
+
paddingY: sizing.footerPadding,
|
|
519
530
|
children: footer
|
|
520
531
|
}
|
|
521
532
|
) : /* @__PURE__ */ jsx4("div", { style: { flexShrink: 0, height: 32 } })
|