@xsolla/xui-b2b-drawer 0.147.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
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"]}
@@ -0,0 +1,552 @@
1
+ // src/Drawer.tsx
2
+ import { forwardRef, useCallback, useEffect, useRef, useState } from "react";
3
+
4
+ // ../../foundation/primitives-native/src/Box.tsx
5
+ import {
6
+ View,
7
+ Pressable,
8
+ Image
9
+ } from "react-native";
10
+ import { jsx } from "react/jsx-runtime";
11
+ var Box = ({
12
+ children,
13
+ onPress,
14
+ onLayout,
15
+ onMoveShouldSetResponder,
16
+ onResponderGrant,
17
+ onResponderMove,
18
+ onResponderRelease,
19
+ onResponderTerminate,
20
+ backgroundColor,
21
+ borderColor,
22
+ borderWidth,
23
+ borderBottomWidth,
24
+ borderBottomColor,
25
+ borderTopWidth,
26
+ borderTopColor,
27
+ borderLeftWidth,
28
+ borderLeftColor,
29
+ borderRightWidth,
30
+ borderRightColor,
31
+ borderRadius,
32
+ borderStyle,
33
+ height,
34
+ padding,
35
+ paddingHorizontal,
36
+ paddingVertical,
37
+ margin,
38
+ marginTop,
39
+ marginBottom,
40
+ marginLeft,
41
+ marginRight,
42
+ flexDirection,
43
+ alignItems,
44
+ justifyContent,
45
+ position,
46
+ top,
47
+ bottom,
48
+ left,
49
+ right,
50
+ width,
51
+ minWidth,
52
+ minHeight,
53
+ maxWidth,
54
+ maxHeight,
55
+ flex,
56
+ overflow,
57
+ zIndex,
58
+ hoverStyle,
59
+ pressStyle,
60
+ style,
61
+ "data-testid": dataTestId,
62
+ testID,
63
+ as,
64
+ src,
65
+ alt,
66
+ ...rest
67
+ }) => {
68
+ const getContainerStyle = (pressed) => ({
69
+ backgroundColor: pressed && pressStyle?.backgroundColor ? pressStyle.backgroundColor : backgroundColor,
70
+ borderColor,
71
+ borderWidth,
72
+ borderBottomWidth,
73
+ borderBottomColor,
74
+ borderTopWidth,
75
+ borderTopColor,
76
+ borderLeftWidth,
77
+ borderLeftColor,
78
+ borderRightWidth,
79
+ borderRightColor,
80
+ borderRadius,
81
+ borderStyle,
82
+ overflow,
83
+ zIndex,
84
+ height,
85
+ width,
86
+ minWidth,
87
+ minHeight,
88
+ maxWidth,
89
+ maxHeight,
90
+ padding,
91
+ paddingHorizontal,
92
+ paddingVertical,
93
+ margin,
94
+ marginTop,
95
+ marginBottom,
96
+ marginLeft,
97
+ marginRight,
98
+ flexDirection,
99
+ alignItems,
100
+ justifyContent,
101
+ position,
102
+ top,
103
+ bottom,
104
+ left,
105
+ right,
106
+ flex,
107
+ ...style
108
+ });
109
+ const finalTestID = dataTestId || testID;
110
+ const {
111
+ role,
112
+ tabIndex,
113
+ onKeyDown,
114
+ onKeyUp,
115
+ "aria-label": _ariaLabel,
116
+ "aria-labelledby": _ariaLabelledBy,
117
+ "aria-current": _ariaCurrent,
118
+ "aria-disabled": _ariaDisabled,
119
+ "aria-live": _ariaLive,
120
+ className,
121
+ "data-testid": _dataTestId,
122
+ ...nativeRest
123
+ } = rest;
124
+ if (as === "img" && src) {
125
+ const imageStyle = {
126
+ width,
127
+ height,
128
+ borderRadius,
129
+ position,
130
+ top,
131
+ bottom,
132
+ left,
133
+ right,
134
+ ...style
135
+ };
136
+ return /* @__PURE__ */ jsx(
137
+ Image,
138
+ {
139
+ source: { uri: src },
140
+ style: imageStyle,
141
+ testID: finalTestID,
142
+ resizeMode: "cover",
143
+ ...nativeRest
144
+ }
145
+ );
146
+ }
147
+ if (onPress) {
148
+ return /* @__PURE__ */ jsx(
149
+ Pressable,
150
+ {
151
+ onPress,
152
+ onLayout,
153
+ onMoveShouldSetResponder,
154
+ onResponderGrant,
155
+ onResponderMove,
156
+ onResponderRelease,
157
+ onResponderTerminate,
158
+ style: ({ pressed }) => getContainerStyle(pressed),
159
+ testID: finalTestID,
160
+ ...nativeRest,
161
+ children
162
+ }
163
+ );
164
+ }
165
+ return /* @__PURE__ */ jsx(
166
+ View,
167
+ {
168
+ style: getContainerStyle(),
169
+ testID: finalTestID,
170
+ onLayout,
171
+ onMoveShouldSetResponder,
172
+ onResponderGrant,
173
+ onResponderMove,
174
+ onResponderRelease,
175
+ onResponderTerminate,
176
+ ...nativeRest,
177
+ children
178
+ }
179
+ );
180
+ };
181
+
182
+ // src/Drawer.tsx
183
+ import { useResolvedTheme } from "@xsolla/xui-core";
184
+
185
+ // src/DrawerRoot.native.tsx
186
+ import { memo } from "react";
187
+ var DrawerRoot = memo((_props) => {
188
+ return null;
189
+ });
190
+ DrawerRoot.displayName = "DrawerRoot";
191
+
192
+ // src/DrawerHeader.tsx
193
+ import { memo as memo2 } from "react";
194
+ import { IconButton } from "@xsolla/xui-button";
195
+ import { ArrowLeft, Remove } from "@xsolla/xui-icons-base";
196
+ import { Typography } from "@xsolla/xui-typography";
197
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
198
+ var DrawerHeader = memo2(
199
+ ({
200
+ title,
201
+ onBack,
202
+ onClose,
203
+ headerAction,
204
+ paddingX,
205
+ paddingY,
206
+ gap
207
+ }) => {
208
+ return /* @__PURE__ */ jsxs(
209
+ "div",
210
+ {
211
+ style: {
212
+ flexShrink: 0,
213
+ height: 80,
214
+ width: "100%",
215
+ display: "flex",
216
+ flexDirection: "row",
217
+ alignItems: "center",
218
+ paddingLeft: paddingX,
219
+ paddingRight: paddingX,
220
+ paddingTop: paddingY,
221
+ paddingBottom: paddingY,
222
+ gap,
223
+ boxSizing: "border-box"
224
+ },
225
+ children: [
226
+ /* @__PURE__ */ jsxs(
227
+ "div",
228
+ {
229
+ style: {
230
+ flex: 1,
231
+ minWidth: 0,
232
+ display: "flex",
233
+ flexDirection: "row",
234
+ alignItems: "center",
235
+ gap: 16
236
+ },
237
+ children: [
238
+ onBack && /* @__PURE__ */ jsx2(
239
+ IconButton,
240
+ {
241
+ variant: "secondary",
242
+ tone: "mono",
243
+ size: "xs",
244
+ icon: /* @__PURE__ */ jsx2(ArrowLeft, {}),
245
+ onPress: onBack,
246
+ "aria-label": "Go back"
247
+ }
248
+ ),
249
+ title && /* @__PURE__ */ jsx2("div", { style: { flex: 1, minWidth: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx2(Typography, { variant: "bodyLgAccent", noWrap: true, children: title }) })
250
+ ]
251
+ }
252
+ ),
253
+ headerAction && /* @__PURE__ */ jsx2("div", { style: { flexShrink: 0 }, children: headerAction }),
254
+ onClose && /* @__PURE__ */ jsx2(
255
+ IconButton,
256
+ {
257
+ variant: "secondary",
258
+ tone: "mono",
259
+ size: "xs",
260
+ icon: /* @__PURE__ */ jsx2(Remove, {}),
261
+ onPress: onClose,
262
+ "aria-label": "Close drawer"
263
+ }
264
+ )
265
+ ]
266
+ }
267
+ );
268
+ }
269
+ );
270
+ DrawerHeader.displayName = "DrawerHeader";
271
+
272
+ // src/DrawerFooter.tsx
273
+ import React, { memo as memo3 } from "react";
274
+ import { jsx as jsx3 } from "react/jsx-runtime";
275
+ var flattenChildren = (children) => {
276
+ const result = [];
277
+ React.Children.forEach(children, (child) => {
278
+ if (React.isValidElement(child) && child.type === React.Fragment) {
279
+ result.push(
280
+ ...flattenChildren(
281
+ child.props.children
282
+ )
283
+ );
284
+ } else if (child !== null && child !== void 0) {
285
+ result.push(child);
286
+ }
287
+ });
288
+ return result;
289
+ };
290
+ var DrawerFooter = memo3(
291
+ ({ children, align, shadow, fullWidth }) => {
292
+ const justifyContent = align === "center" ? "center" : "flex-end";
293
+ const renderedChildren = fullWidth ? flattenChildren(children).map(
294
+ (child, i) => React.isValidElement(child) ? React.cloneElement(
295
+ child,
296
+ {
297
+ key: child.key ?? i,
298
+ fullWidth: true
299
+ }
300
+ ) : child
301
+ ) : children;
302
+ return /* @__PURE__ */ jsx3(
303
+ "div",
304
+ {
305
+ style: {
306
+ flexShrink: 0,
307
+ width: "100%",
308
+ boxShadow: shadow ? "0px 2px 25px 0px rgba(7, 7, 8, 0.15)" : "none"
309
+ },
310
+ children: /* @__PURE__ */ jsx3(
311
+ "div",
312
+ {
313
+ style: {
314
+ display: "flex",
315
+ flexDirection: "row",
316
+ justifyContent: fullWidth ? "stretch" : justifyContent,
317
+ padding: 16,
318
+ gap: 8
319
+ },
320
+ children: renderedChildren
321
+ }
322
+ )
323
+ }
324
+ );
325
+ }
326
+ );
327
+ DrawerFooter.displayName = "DrawerFooter";
328
+
329
+ // src/Drawer.tsx
330
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
331
+ var FOCUSABLE_SELECTORS = 'button:not([disabled]), [href], input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
332
+ var isElementVisible = (el) => {
333
+ if (el.offsetParent === null && getComputedStyle(el).position !== "fixed")
334
+ return false;
335
+ const style = getComputedStyle(el);
336
+ return style.visibility !== "hidden" && style.display !== "none";
337
+ };
338
+ var getFocusableElements = (container) => Array.from(
339
+ container.querySelectorAll(FOCUSABLE_SELECTORS)
340
+ ).filter(isElementVisible);
341
+ var DRAWER_WIDTHS = {
342
+ sm: 480,
343
+ md: 620,
344
+ lg: 1056
345
+ };
346
+ var Drawer = forwardRef(
347
+ ({
348
+ open: openProp,
349
+ isOpen,
350
+ onClose,
351
+ size = "md",
352
+ title: titleProp,
353
+ header: headerProp,
354
+ onBack: onBackProp,
355
+ headerAction,
356
+ closeOnOverlayClick = true,
357
+ closeOnEscape = true,
358
+ footer: footerProp,
359
+ bottom,
360
+ footerAlign = "right",
361
+ footerShadow = false,
362
+ footerFullWidth = true,
363
+ stepper,
364
+ children,
365
+ initialFocusRef,
366
+ themeMode,
367
+ themeProductContext
368
+ }, ref) => {
369
+ const open = openProp ?? isOpen ?? false;
370
+ const title = titleProp ?? headerProp?.title;
371
+ const onBack = onBackProp ?? headerProp?.onBack;
372
+ const footer = footerProp ?? bottom;
373
+ const { theme } = useResolvedTheme({ themeMode, themeProductContext });
374
+ const sizing = theme.sizing.drawer();
375
+ const [mounted, setMounted] = useState(open);
376
+ useEffect(() => {
377
+ if (open) setMounted(true);
378
+ }, [open]);
379
+ const drawerRef = useRef(null);
380
+ const closeButtonRef = useRef(null);
381
+ const previousActiveElement = useRef(null);
382
+ useEffect(() => {
383
+ if (!open) return;
384
+ if (typeof document === "undefined") return;
385
+ previousActiveElement.current = document.activeElement;
386
+ const focusTarget = initialFocusRef?.current || closeButtonRef.current || drawerRef.current && getFocusableElements(drawerRef.current)[0];
387
+ if (focusTarget) {
388
+ focusTarget.focus();
389
+ } else {
390
+ drawerRef.current?.focus();
391
+ }
392
+ }, [open, initialFocusRef]);
393
+ useEffect(() => {
394
+ if (!open || !closeOnEscape || !onClose) return;
395
+ if (typeof document === "undefined") return;
396
+ const handleKeyDown2 = (event) => {
397
+ if (event.key === "Escape") onClose();
398
+ };
399
+ document.addEventListener("keydown", handleKeyDown2);
400
+ return () => document.removeEventListener("keydown", handleKeyDown2);
401
+ }, [open, closeOnEscape, onClose]);
402
+ const handleKeyDown = useCallback((event) => {
403
+ if (event.key !== "Tab" || !drawerRef.current) return;
404
+ if (typeof document === "undefined") return;
405
+ const focusableElements = getFocusableElements(drawerRef.current);
406
+ const firstElement = focusableElements[0];
407
+ const lastElement = focusableElements[focusableElements.length - 1];
408
+ if (!firstElement) {
409
+ event.preventDefault();
410
+ return;
411
+ }
412
+ if (event.shiftKey && document.activeElement === firstElement) {
413
+ event.preventDefault();
414
+ lastElement.focus();
415
+ } else if (!event.shiftKey && document.activeElement === lastElement) {
416
+ event.preventDefault();
417
+ firstElement.focus();
418
+ }
419
+ }, []);
420
+ if (!mounted) return null;
421
+ const contentWidth = DRAWER_WIDTHS[size];
422
+ return /* @__PURE__ */ jsx4(
423
+ DrawerRoot,
424
+ {
425
+ open,
426
+ onExited: () => {
427
+ setMounted(false);
428
+ previousActiveElement.current?.focus();
429
+ },
430
+ onBackdropClick: closeOnOverlayClick ? onClose : void 0,
431
+ scrimColor: sizing.scrimColor,
432
+ outerPadding: sizing.outerPadding,
433
+ animationDuration: sizing.animationDuration,
434
+ zIndex: sizing.zIndex,
435
+ children: /* @__PURE__ */ jsxs2(
436
+ "div",
437
+ {
438
+ style: {
439
+ height: "100%",
440
+ display: "flex",
441
+ flexDirection: "row",
442
+ alignItems: "stretch",
443
+ backgroundColor: theme.colors.background.primary,
444
+ borderRadius: sizing.containerRadius,
445
+ overflow: "hidden",
446
+ gap: stepper ? sizing.stepperContentGap : 0
447
+ },
448
+ children: [
449
+ stepper && /* @__PURE__ */ jsx4(
450
+ "div",
451
+ {
452
+ style: {
453
+ flexShrink: 0,
454
+ alignSelf: "stretch",
455
+ backgroundColor: theme.colors.background.secondary,
456
+ borderRadius: sizing.contentRadius,
457
+ padding: sizing.stepperPadding,
458
+ display: "flex",
459
+ flexDirection: "column"
460
+ },
461
+ children: stepper
462
+ }
463
+ ),
464
+ /* @__PURE__ */ jsxs2(
465
+ Box,
466
+ {
467
+ ref: (node) => {
468
+ drawerRef.current = node;
469
+ if (typeof ref === "function") ref(node);
470
+ else if (ref)
471
+ ref.current = node;
472
+ },
473
+ role: "dialog",
474
+ "aria-modal": "true",
475
+ "aria-label": typeof title === "string" ? title : void 0,
476
+ tabIndex: -1,
477
+ onKeyDown: handleKeyDown,
478
+ style: {
479
+ width: contentWidth,
480
+ height: "100%",
481
+ flexShrink: 0,
482
+ display: "flex",
483
+ flexDirection: "column",
484
+ outline: "none",
485
+ color: theme.colors.content.primary
486
+ },
487
+ children: [
488
+ /* @__PURE__ */ jsx4(
489
+ DrawerHeader,
490
+ {
491
+ title,
492
+ onBack,
493
+ onClose,
494
+ headerAction,
495
+ paddingX: sizing.headerPaddingX,
496
+ paddingY: sizing.headerPaddingY,
497
+ gap: sizing.headerGap
498
+ }
499
+ ),
500
+ /* @__PURE__ */ jsx4(
501
+ Box,
502
+ {
503
+ style: {
504
+ flex: 1,
505
+ minHeight: 0,
506
+ overflowY: "auto",
507
+ paddingLeft: sizing.contentPaddingX,
508
+ paddingRight: sizing.contentPaddingX
509
+ },
510
+ children
511
+ }
512
+ ),
513
+ footer ? /* @__PURE__ */ jsx4(
514
+ DrawerFooter,
515
+ {
516
+ align: footerAlign,
517
+ shadow: footerShadow,
518
+ fullWidth: footerFullWidth,
519
+ children: footer
520
+ }
521
+ ) : /* @__PURE__ */ jsx4("div", { style: { flexShrink: 0, height: 32 } })
522
+ ]
523
+ }
524
+ )
525
+ ]
526
+ }
527
+ )
528
+ }
529
+ );
530
+ }
531
+ );
532
+ Drawer.displayName = "Drawer";
533
+
534
+ // src/useDrawer.ts
535
+ import { useCallback as useCallback2, useState as useState2 } from "react";
536
+ function useDrawer(options) {
537
+ const [isOpen, setIsOpen] = useState2(false);
538
+ const open = useCallback2(() => {
539
+ setIsOpen(true);
540
+ options?.onOpen?.();
541
+ }, [options]);
542
+ const close = useCallback2(() => {
543
+ setIsOpen(false);
544
+ options?.onClose?.();
545
+ }, [options]);
546
+ return { isOpen, open, close };
547
+ }
548
+ export {
549
+ Drawer,
550
+ useDrawer
551
+ };
552
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Drawer.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../src/DrawerRoot.native.tsx","../../src/DrawerHeader.tsx","../../src/DrawerFooter.tsx","../../src/useDrawer.ts"],"sourcesContent":["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":["memo","jsx","memo","jsx","jsx","jsxs","handleKeyDown","useCallback","useState"]}