@xsolla/xui-modal 0.158.0 → 0.160.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 +108 -81
- package/native/index.d.mts +9 -1
- package/native/index.d.ts +9 -1
- package/native/index.js +22 -14
- package/native/index.js.map +1 -1
- package/native/index.mjs +23 -15
- package/native/index.mjs.map +1 -1
- package/package.json +5 -5
- package/web/index.d.mts +9 -1
- package/web/index.d.ts +9 -1
- package/web/index.js +19 -12
- package/web/index.js.map +1 -1
- package/web/index.mjs +20 -13
- package/web/index.mjs.map +1 -1
package/native/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.tsx","../../src/Modal.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../src/WorkArea.tsx","../../src/ModalProvider.tsx","../../src/ModalContext.ts","../../src/ModalRoot.native.tsx","../../src/useModal.ts"],"sourcesContent":["export * from \"./Modal\";\nexport * from \"./ModalProvider\";\nexport * from \"./useModal\";\nexport * from \"./types\";\nexport * from \"./WorkArea\";\nexport { useModalId } from \"@xsolla/xui-core\";\n","import { forwardRef, useEffect, useRef, useCallback } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, useId, ModalIdContext } from \"@xsolla/xui-core\";\nimport { FlexButton } from \"@xsolla/xui-button\";\nimport { ChevronLeft, Remove } from \"@xsolla/xui-icons-base\";\nimport type { ModalProps } from \"./types\";\nimport { WorkArea } from \"./WorkArea\";\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\nexport const Modal = forwardRef<any, ModalProps>(\n (\n {\n children,\n type = \"popup\",\n openContent = false,\n closeOutside = true,\n onClose,\n onBack,\n align,\n header,\n footer,\n styled: styledProps,\n maxWidth,\n minHeight,\n title,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n initialFocusRef,\n themeMode,\n themeProductContext,\n ...rest\n },\n ref\n ) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.modal();\n const modalRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLDivElement>(null);\n const previousActiveElement = useRef<HTMLElement | null>(null);\n const titleId = useId();\n\n useEffect(() => {\n previousActiveElement.current = document.activeElement as HTMLElement;\n\n const focusTarget =\n initialFocusRef?.current ||\n closeButtonRef.current ||\n (modalRef.current && getFocusableElements(modalRef.current)[0]);\n\n if (focusTarget) {\n focusTarget.focus();\n } else {\n modalRef.current?.focus();\n }\n\n return () => {\n previousActiveElement.current?.focus();\n };\n }, [initialFocusRef]);\n\n useEffect(() => {\n if (!onClose) 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 }, [onClose]);\n\n useEffect(() => {\n if (!closeOutside || !onClose) return;\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target;\n if (!target || !(target instanceof Node)) return;\n if (modalRef.current && !modalRef.current.contains(target)) {\n const portalContent = (target as Element).closest?.(\n `[data-modal-id=\"${titleId}\"]`\n );\n if (!portalContent) {\n onClose();\n }\n }\n };\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }, [closeOutside, onClose, titleId]);\n\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (event.key !== \"Tab\" || !modalRef.current) return;\n\n const focusableElements = getFocusableElements(modalRef.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 const maxWidthValue =\n type === \"full-screen\" || type === \"bottom-sheet\"\n ? \"100%\"\n : (maxWidth ?? sizing.maxWidth);\n const hasDefaultHeader = !header && (onBack || onClose);\n const hasHeader = !!header || hasDefaultHeader;\n\n const typeStyles: React.CSSProperties =\n type === \"full-screen\"\n ? {\n position: \"fixed\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 1,\n maxWidth: \"100%\",\n }\n : type === \"bottom-sheet\"\n ? {\n position: \"fixed\",\n bottom: 0,\n left: 0,\n right: 0,\n zIndex: 1,\n maxWidth: \"100%\",\n }\n : {};\n\n return (\n <Box\n ref={modalRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n aria-label={!title ? ariaLabel : undefined}\n aria-describedby={ariaDescribedBy}\n data-modal-id={titleId}\n data-modal-type={type}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n flexGrow={1}\n position=\"relative\"\n width=\"100%\"\n style={{\n maxWidth:\n typeof maxWidthValue === \"number\"\n ? `${maxWidthValue}px`\n : maxWidthValue,\n minHeight:\n typeof minHeight === \"number\" ? `${minHeight}px` : minHeight,\n outline: \"none\",\n ...typeStyles,\n ...styledProps,\n }}\n {...rest}\n >\n {title && (\n <Box\n id={titleId}\n position=\"absolute\"\n style={{\n clip: \"rect(0 0 0 0)\",\n clipPath: \"inset(50%)\",\n height: 1,\n width: 1,\n overflow: \"hidden\",\n whiteSpace: \"nowrap\",\n }}\n >\n {title}\n </Box>\n )}\n <ModalIdContext.Provider value={titleId}>\n <WorkArea\n ref={ref}\n stretched\n openContent={openContent}\n type={type}\n align={align}\n >\n {hasHeader && (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n width=\"100%\"\n padding={sizing.headerPadding}\n style={{ flexShrink: 0 }}\n >\n {header ?? (\n <>\n <Box style={{ minWidth: 36 }}>\n {onBack && (\n <FlexButton\n variant=\"secondary\"\n size={sizing.headerButtonSize}\n background\n onPress={onBack}\n aria-label=\"Go back\"\n >\n <ChevronLeft />\n </FlexButton>\n )}\n </Box>\n <Box\n ref={closeButtonRef}\n style={{ minWidth: 36 }}\n alignItems=\"flex-end\"\n >\n {onClose && (\n <FlexButton\n variant=\"secondary\"\n size={sizing.headerButtonSize}\n background\n onPress={onClose}\n aria-label=\"Close modal\"\n >\n <Remove />\n </FlexButton>\n )}\n </Box>\n </>\n )}\n </Box>\n )}\n <Box\n flexGrow={1}\n width=\"100%\"\n padding={openContent ? 0 : sizing.contentPadding}\n style={{ paddingTop: hasHeader ? 0 : undefined }}\n >\n {children}\n </Box>\n {footer && (\n <Box\n width=\"100%\"\n padding={openContent ? 0 : sizing.contentPadding}\n style={{ paddingTop: 0, flexShrink: 0 }}\n >\n {footer}\n </Box>\n )}\n </WorkArea>\n </ModalIdContext.Provider>\n </Box>\n );\n }\n);\n\nModal.displayName = \"Modal\";\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 { forwardRef } 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 { WorkAreaProps } from \"./types\";\n\nconst getBorderRadius = (\n type: WorkAreaProps[\"type\"],\n baseRadius: number\n): string | number => {\n switch (type) {\n case \"full-screen\":\n return 0;\n case \"bottom-sheet\":\n return `${baseRadius}px ${baseRadius}px 0 0`;\n default:\n return baseRadius;\n }\n};\n\nexport const WorkArea = forwardRef<any, WorkAreaProps>(\n (\n {\n children,\n openContent = false,\n stretched = false,\n fetching = false,\n type = \"popup\",\n align,\n themeMode,\n themeProductContext,\n },\n ref\n ) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.modal();\n const showShadow = type !== \"full-screen\";\n\n return (\n <Box\n ref={ref}\n backgroundColor={theme.colors.background.primary}\n width=\"100%\"\n height={stretched ? \"100%\" : \"auto\"}\n flexDirection=\"column\"\n alignItems={align === \"center\" ? \"center\" : \"stretch\"}\n style={{\n borderRadius: getBorderRadius(type, sizing.borderRadius),\n boxShadow: showShadow ? sizing.shadow : \"none\",\n overflow: \"hidden\",\n color: theme.colors.content.primary,\n }}\n >\n <Box\n width=\"100%\"\n height=\"100%\"\n flexDirection=\"column\"\n alignItems={align === \"center\" ? \"center\" : \"stretch\"}\n style={{ textAlign: align === \"center\" ? \"center\" : \"left\" }}\n >\n {fetching ? (\n <Box\n alignItems=\"center\"\n justifyContent=\"center\"\n width=\"100%\"\n height=\"100%\"\n >\n <div>Loading...</div>\n </Box>\n ) : (\n children\n )}\n </Box>\n </Box>\n );\n }\n);\n\nWorkArea.displayName = \"WorkArea\";\n","import { useCallback, useMemo, useState } from \"react\";\nimport { ModalContext } from \"./ModalContext\";\nimport { ModalRoot } from \"./ModalRoot\";\nimport type { ModalProviderProps, ModalType } from \"./types\";\n\nexport const ModalProvider = ({ children }: ModalProviderProps) => {\n const [modals, setModals] = useState<Record<string, ModalType>>({});\n\n const onOpenModal = useCallback(\n (key: string, modal: ModalType) =>\n setModals((m) => ({ ...m, [key]: modal })),\n []\n );\n\n const onCloseModal = useCallback(\n (key: string) =>\n setModals((m) => {\n if (!m[key]) return m;\n const newModals = { ...m };\n delete newModals[key];\n return newModals;\n }),\n []\n );\n\n const contextValue = useMemo(\n () => ({ onOpenModal, onCloseModal }),\n [onOpenModal, onCloseModal]\n );\n\n return (\n <ModalContext.Provider value={contextValue}>\n {children}\n <ModalRoot modals={modals} />\n </ModalContext.Provider>\n );\n};\n","import { createContext } from \"react\";\nimport type { ModalContextType } from \"./types\";\n\nconst invariantViolation = () => {\n throw new Error(\n \"Attempted to call useModal outside of modal context. Make sure your app is rendered inside ModalProvider.\"\n );\n};\n\nexport const ModalContext = createContext<ModalContextType>({\n onOpenModal: invariantViolation,\n onCloseModal: invariantViolation,\n});\n","import React, { memo } from \"react\";\nimport type { ModalRootProps } from \"./types\";\n\n// Web portal not available on React Native\n// Native modal implementation would use RN-specific approach\nexport const ModalRoot = memo(({ modals }: ModalRootProps) => {\n return null;\n});\n\nModalRoot.displayName = \"ModalRoot\";\n","import { useContext, useEffect, useMemo, useRef, useCallback } from \"react\";\nimport { ModalContext } from \"./ModalContext\";\nimport { ModalType } from \"./types\";\n\nexport const useModal = (modal: ModalType): [() => void, () => void] => {\n const { onOpenModal, onCloseModal } = useContext(ModalContext);\n const key = useMemo(() => Math.random().toString(36).substr(2, 9), []);\n const modalRef = useRef(modal);\n\n useEffect(() => {\n modalRef.current = modal;\n }, [modal]);\n\n const open = useCallback(() => {\n onOpenModal(key, modalRef.current);\n }, [key, onOpenModal]);\n\n const close = useCallback(() => {\n onCloseModal(key);\n }, [key, onCloseModal]);\n\n return [open, close];\n};\n"],"mappings":"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","names":["import_react","import_xui_core","import_jsx_runtime","import_jsx_runtime","handleKeyDown","import_react","import_react","import_react","import_jsx_runtime","import_react","import_xui_core"]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.tsx","../../src/Modal.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../src/WorkArea.tsx","../../src/ModalProvider.tsx","../../src/ModalContext.ts","../../src/ModalRoot.native.tsx","../../src/useModal.ts"],"sourcesContent":["export * from \"./Modal\";\nexport * from \"./ModalProvider\";\nexport * from \"./useModal\";\nexport * from \"./types\";\nexport * from \"./WorkArea\";\nexport { useModalId } from \"@xsolla/xui-core\";\n","import { forwardRef, useEffect, useRef, useCallback } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, useId, ModalIdContext } from \"@xsolla/xui-core\";\nimport { IconButton } from \"@xsolla/xui-button\";\nimport { ChevronLeft, Remove } from \"@xsolla/xui-icons-base\";\nimport type { ModalProps } from \"./types\";\nimport { WorkArea } from \"./WorkArea\";\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\nexport const Modal = forwardRef<any, ModalProps>(\n (\n {\n children,\n type = \"popup\",\n openContent = false,\n closeOutside = true,\n onClose,\n onBack,\n align,\n header,\n footer,\n styled: styledProps,\n maxWidth,\n minHeight,\n title,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n initialFocusRef,\n testID,\n themeMode,\n themeProductContext,\n ...rest\n },\n ref\n ) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.modal();\n const modalRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLDivElement>(null);\n const previousActiveElement = useRef<HTMLElement | null>(null);\n const titleId = useId();\n\n useEffect(() => {\n previousActiveElement.current = document.activeElement as HTMLElement;\n\n const focusTarget =\n initialFocusRef?.current ||\n closeButtonRef.current ||\n (modalRef.current && getFocusableElements(modalRef.current)[0]);\n\n if (focusTarget) {\n focusTarget.focus();\n } else {\n modalRef.current?.focus();\n }\n\n return () => {\n previousActiveElement.current?.focus();\n };\n }, [initialFocusRef]);\n\n useEffect(() => {\n if (!onClose) 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 }, [onClose]);\n\n useEffect(() => {\n if (!closeOutside || !onClose) return;\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target;\n if (!target || !(target instanceof Node)) return;\n if (modalRef.current && !modalRef.current.contains(target)) {\n const portalContent = (target as Element).closest?.(\n `[data-modal-id=\"${titleId}\"]`\n );\n if (!portalContent) {\n onClose();\n }\n }\n };\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }, [closeOutside, onClose, titleId]);\n\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (event.key !== \"Tab\" || !modalRef.current) return;\n\n const focusableElements = getFocusableElements(modalRef.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 const maxWidthValue =\n type === \"full-screen\" || type === \"bottom-sheet\"\n ? \"100%\"\n : (maxWidth ?? sizing.maxWidth);\n const hasDefaultHeader = !header && (onBack || onClose);\n const hasHeader = !!header || hasDefaultHeader;\n\n const typeStyles: React.CSSProperties =\n type === \"full-screen\"\n ? {\n position: \"fixed\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 1,\n maxWidth: \"100%\",\n }\n : type === \"bottom-sheet\"\n ? {\n position: \"fixed\",\n bottom: 0,\n left: 0,\n right: 0,\n zIndex: 1,\n maxWidth: \"100%\",\n }\n : {};\n\n return (\n <Box\n testID={testID}\n ref={modalRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n aria-label={!title ? ariaLabel : undefined}\n aria-describedby={ariaDescribedBy}\n data-modal-id={titleId}\n data-modal-type={type}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n flexGrow={1}\n position=\"relative\"\n width=\"100%\"\n style={{\n maxWidth:\n typeof maxWidthValue === \"number\"\n ? `${maxWidthValue}px`\n : maxWidthValue,\n minHeight:\n typeof minHeight === \"number\" ? `${minHeight}px` : minHeight,\n outline: \"none\",\n ...typeStyles,\n ...styledProps,\n }}\n {...rest}\n >\n {title && (\n <Box\n id={titleId}\n position=\"absolute\"\n style={{\n clip: \"rect(0 0 0 0)\",\n clipPath: \"inset(50%)\",\n height: 1,\n width: 1,\n overflow: \"hidden\",\n whiteSpace: \"nowrap\",\n }}\n >\n {title}\n </Box>\n )}\n <ModalIdContext.Provider value={titleId}>\n <WorkArea\n ref={ref}\n stretched\n openContent={openContent}\n type={type}\n align={align}\n >\n {hasHeader && (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n width=\"100%\"\n padding={sizing.headerPadding}\n style={{ flexShrink: 0 }}\n >\n {header ?? (\n <>\n <Box style={{ minWidth: 36 }}>\n {onBack && (\n <IconButton\n variant=\"secondary\"\n tone=\"mono\"\n size={sizing.headerButtonSize}\n icon={<ChevronLeft />}\n onPress={onBack}\n aria-label=\"Go back\"\n />\n )}\n </Box>\n <Box\n ref={closeButtonRef}\n style={{ minWidth: 36 }}\n alignItems=\"flex-end\"\n >\n {onClose && (\n <IconButton\n variant=\"secondary\"\n tone=\"mono\"\n size={sizing.headerButtonSize}\n icon={<Remove />}\n onPress={onClose}\n aria-label=\"Close modal\"\n />\n )}\n </Box>\n </>\n )}\n </Box>\n )}\n <Box\n flexGrow={1}\n width=\"100%\"\n padding={openContent ? 0 : sizing.contentPadding}\n style={{\n paddingTop:\n hasHeader && !openContent ? sizing.headerGap : undefined,\n }}\n >\n {children}\n </Box>\n {footer && (\n <Box\n width=\"100%\"\n padding={openContent ? 0 : sizing.contentPadding}\n style={{ paddingTop: 0, flexShrink: 0 }}\n >\n {footer}\n </Box>\n )}\n </WorkArea>\n </ModalIdContext.Provider>\n </Box>\n );\n }\n);\n\nModal.displayName = \"Modal\";\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 { forwardRef } 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 { WorkAreaProps } from \"./types\";\n\nconst getBorderRadius = (\n type: WorkAreaProps[\"type\"],\n baseRadius: number\n): string | number => {\n switch (type) {\n case \"full-screen\":\n return 0;\n case \"bottom-sheet\":\n return `${baseRadius}px ${baseRadius}px 0 0`;\n default:\n return baseRadius;\n }\n};\n\nexport const WorkArea = forwardRef<any, WorkAreaProps>(\n (\n {\n children,\n openContent = false,\n stretched = false,\n fetching = false,\n type = \"popup\",\n align,\n testID,\n themeMode,\n themeProductContext,\n },\n ref\n ) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.modal();\n const showShadow = type !== \"full-screen\";\n\n return (\n <Box\n testID={testID}\n ref={ref}\n backgroundColor={theme.colors.background.primary}\n width=\"100%\"\n height={stretched ? \"100%\" : \"auto\"}\n flexDirection=\"column\"\n alignItems={align === \"center\" ? \"center\" : \"stretch\"}\n style={{\n borderRadius: getBorderRadius(type, sizing.borderRadius),\n boxShadow: showShadow ? sizing.shadow : \"none\",\n overflow: \"hidden\",\n color: theme.colors.content.primary,\n }}\n >\n <Box\n width=\"100%\"\n height=\"100%\"\n flexDirection=\"column\"\n alignItems={align === \"center\" ? \"center\" : \"stretch\"}\n style={{ textAlign: align === \"center\" ? \"center\" : \"left\" }}\n >\n {fetching ? (\n <Box\n alignItems=\"center\"\n justifyContent=\"center\"\n width=\"100%\"\n height=\"100%\"\n >\n <div>Loading...</div>\n </Box>\n ) : (\n children\n )}\n </Box>\n </Box>\n );\n }\n);\n\nWorkArea.displayName = \"WorkArea\";\n","import { useCallback, useMemo, useState } from \"react\";\nimport { ModalContext } from \"./ModalContext\";\nimport { ModalRoot } from \"./ModalRoot\";\nimport type { ModalProviderProps, ModalType } from \"./types\";\n\nexport const ModalProvider = ({ children, testID }: ModalProviderProps) => {\n const [modals, setModals] = useState<Record<string, ModalType>>({});\n\n const onOpenModal = useCallback(\n (key: string, modal: ModalType) =>\n setModals((m) => ({ ...m, [key]: modal })),\n []\n );\n\n const onCloseModal = useCallback(\n (key: string) =>\n setModals((m) => {\n if (!m[key]) return m;\n const newModals = { ...m };\n delete newModals[key];\n return newModals;\n }),\n []\n );\n\n const contextValue = useMemo(\n () => ({ onOpenModal, onCloseModal }),\n [onOpenModal, onCloseModal]\n );\n\n return (\n <ModalContext.Provider value={contextValue}>\n {children}\n <ModalRoot modals={modals} testID={testID} />\n </ModalContext.Provider>\n );\n};\n","import { createContext } from \"react\";\nimport type { ModalContextType } from \"./types\";\n\nconst invariantViolation = () => {\n throw new Error(\n \"Attempted to call useModal outside of modal context. Make sure your app is rendered inside ModalProvider.\"\n );\n};\n\nexport const ModalContext = createContext<ModalContextType>({\n onOpenModal: invariantViolation,\n onCloseModal: invariantViolation,\n});\n","import React, { memo } from \"react\";\nimport type { ModalRootProps } from \"./types\";\n\n// Web portal not available on React Native\n// Native modal implementation would use RN-specific approach\nexport const ModalRoot = memo(\n ({ modals: _modals, testID: _testID }: ModalRootProps) => {\n return null;\n }\n);\n\nModalRoot.displayName = \"ModalRoot\";\n","import { useContext, useEffect, useMemo, useRef, useCallback } from \"react\";\nimport { ModalContext } from \"./ModalContext\";\nimport { ModalType } from \"./types\";\n\nexport const useModal = (modal: ModalType): [() => void, () => void] => {\n const { onOpenModal, onCloseModal } = useContext(ModalContext);\n const key = useMemo(() => Math.random().toString(36).substr(2, 9), []);\n const modalRef = useRef(modal);\n\n useEffect(() => {\n modalRef.current = modal;\n }, [modal]);\n\n const open = useCallback(() => {\n onOpenModal(key, modalRef.current);\n }, [key, onOpenModal]);\n\n const close = useCallback(() => {\n onCloseModal(key);\n }, [key, onCloseModal]);\n\n return [open, close];\n};\n"],"mappings":"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","names":["import_react","import_xui_core","import_jsx_runtime","import_jsx_runtime","handleKeyDown","import_react","import_react","import_react","import_jsx_runtime","import_react","import_xui_core"]}
|
package/native/index.mjs
CHANGED
|
@@ -181,7 +181,7 @@ var Box = ({
|
|
|
181
181
|
|
|
182
182
|
// src/Modal.tsx
|
|
183
183
|
import { useResolvedTheme as useResolvedTheme2, useId, ModalIdContext } from "@xsolla/xui-core";
|
|
184
|
-
import {
|
|
184
|
+
import { IconButton } from "@xsolla/xui-button";
|
|
185
185
|
import { ChevronLeft, Remove } from "@xsolla/xui-icons-base";
|
|
186
186
|
|
|
187
187
|
// src/WorkArea.tsx
|
|
@@ -206,6 +206,7 @@ var WorkArea = forwardRef(
|
|
|
206
206
|
fetching = false,
|
|
207
207
|
type = "popup",
|
|
208
208
|
align,
|
|
209
|
+
testID,
|
|
209
210
|
themeMode,
|
|
210
211
|
themeProductContext
|
|
211
212
|
}, ref) => {
|
|
@@ -215,6 +216,7 @@ var WorkArea = forwardRef(
|
|
|
215
216
|
return /* @__PURE__ */ jsx2(
|
|
216
217
|
Box,
|
|
217
218
|
{
|
|
219
|
+
testID,
|
|
218
220
|
ref,
|
|
219
221
|
backgroundColor: theme.colors.background.primary,
|
|
220
222
|
width: "100%",
|
|
@@ -283,6 +285,7 @@ var Modal = forwardRef2(
|
|
|
283
285
|
"aria-label": ariaLabel,
|
|
284
286
|
"aria-describedby": ariaDescribedBy,
|
|
285
287
|
initialFocusRef,
|
|
288
|
+
testID,
|
|
286
289
|
themeMode,
|
|
287
290
|
themeProductContext,
|
|
288
291
|
...rest
|
|
@@ -369,6 +372,7 @@ var Modal = forwardRef2(
|
|
|
369
372
|
return /* @__PURE__ */ jsxs(
|
|
370
373
|
Box,
|
|
371
374
|
{
|
|
375
|
+
testID,
|
|
372
376
|
ref: modalRef,
|
|
373
377
|
role: "dialog",
|
|
374
378
|
"aria-modal": "true",
|
|
@@ -427,14 +431,14 @@ var Modal = forwardRef2(
|
|
|
427
431
|
style: { flexShrink: 0 },
|
|
428
432
|
children: header ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
429
433
|
/* @__PURE__ */ jsx3(Box, { style: { minWidth: 36 }, children: onBack && /* @__PURE__ */ jsx3(
|
|
430
|
-
|
|
434
|
+
IconButton,
|
|
431
435
|
{
|
|
432
436
|
variant: "secondary",
|
|
437
|
+
tone: "mono",
|
|
433
438
|
size: sizing.headerButtonSize,
|
|
434
|
-
|
|
439
|
+
icon: /* @__PURE__ */ jsx3(ChevronLeft, {}),
|
|
435
440
|
onPress: onBack,
|
|
436
|
-
"aria-label": "Go back"
|
|
437
|
-
children: /* @__PURE__ */ jsx3(ChevronLeft, {})
|
|
441
|
+
"aria-label": "Go back"
|
|
438
442
|
}
|
|
439
443
|
) }),
|
|
440
444
|
/* @__PURE__ */ jsx3(
|
|
@@ -444,14 +448,14 @@ var Modal = forwardRef2(
|
|
|
444
448
|
style: { minWidth: 36 },
|
|
445
449
|
alignItems: "flex-end",
|
|
446
450
|
children: onClose && /* @__PURE__ */ jsx3(
|
|
447
|
-
|
|
451
|
+
IconButton,
|
|
448
452
|
{
|
|
449
453
|
variant: "secondary",
|
|
454
|
+
tone: "mono",
|
|
450
455
|
size: sizing.headerButtonSize,
|
|
451
|
-
|
|
456
|
+
icon: /* @__PURE__ */ jsx3(Remove, {}),
|
|
452
457
|
onPress: onClose,
|
|
453
|
-
"aria-label": "Close modal"
|
|
454
|
-
children: /* @__PURE__ */ jsx3(Remove, {})
|
|
458
|
+
"aria-label": "Close modal"
|
|
455
459
|
}
|
|
456
460
|
)
|
|
457
461
|
}
|
|
@@ -465,7 +469,9 @@ var Modal = forwardRef2(
|
|
|
465
469
|
flexGrow: 1,
|
|
466
470
|
width: "100%",
|
|
467
471
|
padding: openContent ? 0 : sizing.contentPadding,
|
|
468
|
-
style: {
|
|
472
|
+
style: {
|
|
473
|
+
paddingTop: hasHeader && !openContent ? sizing.headerGap : void 0
|
|
474
|
+
},
|
|
469
475
|
children
|
|
470
476
|
}
|
|
471
477
|
),
|
|
@@ -505,14 +511,16 @@ var ModalContext = createContext({
|
|
|
505
511
|
|
|
506
512
|
// src/ModalRoot.native.tsx
|
|
507
513
|
import { memo } from "react";
|
|
508
|
-
var ModalRoot = memo(
|
|
509
|
-
|
|
510
|
-
|
|
514
|
+
var ModalRoot = memo(
|
|
515
|
+
({ modals: _modals, testID: _testID }) => {
|
|
516
|
+
return null;
|
|
517
|
+
}
|
|
518
|
+
);
|
|
511
519
|
ModalRoot.displayName = "ModalRoot";
|
|
512
520
|
|
|
513
521
|
// src/ModalProvider.tsx
|
|
514
522
|
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
515
|
-
var ModalProvider = ({ children }) => {
|
|
523
|
+
var ModalProvider = ({ children, testID }) => {
|
|
516
524
|
const [modals, setModals] = useState({});
|
|
517
525
|
const onOpenModal = useCallback2(
|
|
518
526
|
(key, modal) => setModals((m) => ({ ...m, [key]: modal })),
|
|
@@ -533,7 +541,7 @@ var ModalProvider = ({ children }) => {
|
|
|
533
541
|
);
|
|
534
542
|
return /* @__PURE__ */ jsxs2(ModalContext.Provider, { value: contextValue, children: [
|
|
535
543
|
children,
|
|
536
|
-
/* @__PURE__ */ jsx4(ModalRoot, { modals })
|
|
544
|
+
/* @__PURE__ */ jsx4(ModalRoot, { modals, testID })
|
|
537
545
|
] });
|
|
538
546
|
};
|
|
539
547
|
|
package/native/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Modal.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../src/WorkArea.tsx","../../src/ModalProvider.tsx","../../src/ModalContext.ts","../../src/ModalRoot.native.tsx","../../src/useModal.ts","../../src/index.tsx"],"sourcesContent":["import { forwardRef, useEffect, useRef, useCallback } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, useId, ModalIdContext } from \"@xsolla/xui-core\";\nimport { FlexButton } from \"@xsolla/xui-button\";\nimport { ChevronLeft, Remove } from \"@xsolla/xui-icons-base\";\nimport type { ModalProps } from \"./types\";\nimport { WorkArea } from \"./WorkArea\";\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\nexport const Modal = forwardRef<any, ModalProps>(\n (\n {\n children,\n type = \"popup\",\n openContent = false,\n closeOutside = true,\n onClose,\n onBack,\n align,\n header,\n footer,\n styled: styledProps,\n maxWidth,\n minHeight,\n title,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n initialFocusRef,\n themeMode,\n themeProductContext,\n ...rest\n },\n ref\n ) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.modal();\n const modalRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLDivElement>(null);\n const previousActiveElement = useRef<HTMLElement | null>(null);\n const titleId = useId();\n\n useEffect(() => {\n previousActiveElement.current = document.activeElement as HTMLElement;\n\n const focusTarget =\n initialFocusRef?.current ||\n closeButtonRef.current ||\n (modalRef.current && getFocusableElements(modalRef.current)[0]);\n\n if (focusTarget) {\n focusTarget.focus();\n } else {\n modalRef.current?.focus();\n }\n\n return () => {\n previousActiveElement.current?.focus();\n };\n }, [initialFocusRef]);\n\n useEffect(() => {\n if (!onClose) 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 }, [onClose]);\n\n useEffect(() => {\n if (!closeOutside || !onClose) return;\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target;\n if (!target || !(target instanceof Node)) return;\n if (modalRef.current && !modalRef.current.contains(target)) {\n const portalContent = (target as Element).closest?.(\n `[data-modal-id=\"${titleId}\"]`\n );\n if (!portalContent) {\n onClose();\n }\n }\n };\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }, [closeOutside, onClose, titleId]);\n\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (event.key !== \"Tab\" || !modalRef.current) return;\n\n const focusableElements = getFocusableElements(modalRef.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 const maxWidthValue =\n type === \"full-screen\" || type === \"bottom-sheet\"\n ? \"100%\"\n : (maxWidth ?? sizing.maxWidth);\n const hasDefaultHeader = !header && (onBack || onClose);\n const hasHeader = !!header || hasDefaultHeader;\n\n const typeStyles: React.CSSProperties =\n type === \"full-screen\"\n ? {\n position: \"fixed\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 1,\n maxWidth: \"100%\",\n }\n : type === \"bottom-sheet\"\n ? {\n position: \"fixed\",\n bottom: 0,\n left: 0,\n right: 0,\n zIndex: 1,\n maxWidth: \"100%\",\n }\n : {};\n\n return (\n <Box\n ref={modalRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n aria-label={!title ? ariaLabel : undefined}\n aria-describedby={ariaDescribedBy}\n data-modal-id={titleId}\n data-modal-type={type}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n flexGrow={1}\n position=\"relative\"\n width=\"100%\"\n style={{\n maxWidth:\n typeof maxWidthValue === \"number\"\n ? `${maxWidthValue}px`\n : maxWidthValue,\n minHeight:\n typeof minHeight === \"number\" ? `${minHeight}px` : minHeight,\n outline: \"none\",\n ...typeStyles,\n ...styledProps,\n }}\n {...rest}\n >\n {title && (\n <Box\n id={titleId}\n position=\"absolute\"\n style={{\n clip: \"rect(0 0 0 0)\",\n clipPath: \"inset(50%)\",\n height: 1,\n width: 1,\n overflow: \"hidden\",\n whiteSpace: \"nowrap\",\n }}\n >\n {title}\n </Box>\n )}\n <ModalIdContext.Provider value={titleId}>\n <WorkArea\n ref={ref}\n stretched\n openContent={openContent}\n type={type}\n align={align}\n >\n {hasHeader && (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n width=\"100%\"\n padding={sizing.headerPadding}\n style={{ flexShrink: 0 }}\n >\n {header ?? (\n <>\n <Box style={{ minWidth: 36 }}>\n {onBack && (\n <FlexButton\n variant=\"secondary\"\n size={sizing.headerButtonSize}\n background\n onPress={onBack}\n aria-label=\"Go back\"\n >\n <ChevronLeft />\n </FlexButton>\n )}\n </Box>\n <Box\n ref={closeButtonRef}\n style={{ minWidth: 36 }}\n alignItems=\"flex-end\"\n >\n {onClose && (\n <FlexButton\n variant=\"secondary\"\n size={sizing.headerButtonSize}\n background\n onPress={onClose}\n aria-label=\"Close modal\"\n >\n <Remove />\n </FlexButton>\n )}\n </Box>\n </>\n )}\n </Box>\n )}\n <Box\n flexGrow={1}\n width=\"100%\"\n padding={openContent ? 0 : sizing.contentPadding}\n style={{ paddingTop: hasHeader ? 0 : undefined }}\n >\n {children}\n </Box>\n {footer && (\n <Box\n width=\"100%\"\n padding={openContent ? 0 : sizing.contentPadding}\n style={{ paddingTop: 0, flexShrink: 0 }}\n >\n {footer}\n </Box>\n )}\n </WorkArea>\n </ModalIdContext.Provider>\n </Box>\n );\n }\n);\n\nModal.displayName = \"Modal\";\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 { forwardRef } 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 { WorkAreaProps } from \"./types\";\n\nconst getBorderRadius = (\n type: WorkAreaProps[\"type\"],\n baseRadius: number\n): string | number => {\n switch (type) {\n case \"full-screen\":\n return 0;\n case \"bottom-sheet\":\n return `${baseRadius}px ${baseRadius}px 0 0`;\n default:\n return baseRadius;\n }\n};\n\nexport const WorkArea = forwardRef<any, WorkAreaProps>(\n (\n {\n children,\n openContent = false,\n stretched = false,\n fetching = false,\n type = \"popup\",\n align,\n themeMode,\n themeProductContext,\n },\n ref\n ) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.modal();\n const showShadow = type !== \"full-screen\";\n\n return (\n <Box\n ref={ref}\n backgroundColor={theme.colors.background.primary}\n width=\"100%\"\n height={stretched ? \"100%\" : \"auto\"}\n flexDirection=\"column\"\n alignItems={align === \"center\" ? \"center\" : \"stretch\"}\n style={{\n borderRadius: getBorderRadius(type, sizing.borderRadius),\n boxShadow: showShadow ? sizing.shadow : \"none\",\n overflow: \"hidden\",\n color: theme.colors.content.primary,\n }}\n >\n <Box\n width=\"100%\"\n height=\"100%\"\n flexDirection=\"column\"\n alignItems={align === \"center\" ? \"center\" : \"stretch\"}\n style={{ textAlign: align === \"center\" ? \"center\" : \"left\" }}\n >\n {fetching ? (\n <Box\n alignItems=\"center\"\n justifyContent=\"center\"\n width=\"100%\"\n height=\"100%\"\n >\n <div>Loading...</div>\n </Box>\n ) : (\n children\n )}\n </Box>\n </Box>\n );\n }\n);\n\nWorkArea.displayName = \"WorkArea\";\n","import { useCallback, useMemo, useState } from \"react\";\nimport { ModalContext } from \"./ModalContext\";\nimport { ModalRoot } from \"./ModalRoot\";\nimport type { ModalProviderProps, ModalType } from \"./types\";\n\nexport const ModalProvider = ({ children }: ModalProviderProps) => {\n const [modals, setModals] = useState<Record<string, ModalType>>({});\n\n const onOpenModal = useCallback(\n (key: string, modal: ModalType) =>\n setModals((m) => ({ ...m, [key]: modal })),\n []\n );\n\n const onCloseModal = useCallback(\n (key: string) =>\n setModals((m) => {\n if (!m[key]) return m;\n const newModals = { ...m };\n delete newModals[key];\n return newModals;\n }),\n []\n );\n\n const contextValue = useMemo(\n () => ({ onOpenModal, onCloseModal }),\n [onOpenModal, onCloseModal]\n );\n\n return (\n <ModalContext.Provider value={contextValue}>\n {children}\n <ModalRoot modals={modals} />\n </ModalContext.Provider>\n );\n};\n","import { createContext } from \"react\";\nimport type { ModalContextType } from \"./types\";\n\nconst invariantViolation = () => {\n throw new Error(\n \"Attempted to call useModal outside of modal context. Make sure your app is rendered inside ModalProvider.\"\n );\n};\n\nexport const ModalContext = createContext<ModalContextType>({\n onOpenModal: invariantViolation,\n onCloseModal: invariantViolation,\n});\n","import React, { memo } from \"react\";\nimport type { ModalRootProps } from \"./types\";\n\n// Web portal not available on React Native\n// Native modal implementation would use RN-specific approach\nexport const ModalRoot = memo(({ modals }: ModalRootProps) => {\n return null;\n});\n\nModalRoot.displayName = \"ModalRoot\";\n","import { useContext, useEffect, useMemo, useRef, useCallback } from \"react\";\nimport { ModalContext } from \"./ModalContext\";\nimport { ModalType } from \"./types\";\n\nexport const useModal = (modal: ModalType): [() => void, () => void] => {\n const { onOpenModal, onCloseModal } = useContext(ModalContext);\n const key = useMemo(() => Math.random().toString(36).substr(2, 9), []);\n const modalRef = useRef(modal);\n\n useEffect(() => {\n modalRef.current = modal;\n }, [modal]);\n\n const open = useCallback(() => {\n onOpenModal(key, modalRef.current);\n }, [key, onOpenModal]);\n\n const close = useCallback(() => {\n onCloseModal(key);\n }, [key, onCloseModal]);\n\n return [open, close];\n};\n","export * from \"./Modal\";\nexport * from \"./ModalProvider\";\nexport * from \"./useModal\";\nexport * from \"./types\";\nexport * from \"./WorkArea\";\nexport { useModalId } from \"@xsolla/xui-core\";\n"],"mappings":"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","names":["forwardRef","useResolvedTheme","jsx","jsx","forwardRef","useResolvedTheme","handleKeyDown","useCallback","jsx","jsxs","useCallback","useEffect","useMemo","useRef","useCallback","useMemo","useRef","useEffect","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Modal.tsx","../../../../foundation/primitives-native/src/Box.tsx","../../src/WorkArea.tsx","../../src/ModalProvider.tsx","../../src/ModalContext.ts","../../src/ModalRoot.native.tsx","../../src/useModal.ts","../../src/index.tsx"],"sourcesContent":["import { forwardRef, useEffect, useRef, useCallback } from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Box } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, useId, ModalIdContext } from \"@xsolla/xui-core\";\nimport { IconButton } from \"@xsolla/xui-button\";\nimport { ChevronLeft, Remove } from \"@xsolla/xui-icons-base\";\nimport type { ModalProps } from \"./types\";\nimport { WorkArea } from \"./WorkArea\";\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\nexport const Modal = forwardRef<any, ModalProps>(\n (\n {\n children,\n type = \"popup\",\n openContent = false,\n closeOutside = true,\n onClose,\n onBack,\n align,\n header,\n footer,\n styled: styledProps,\n maxWidth,\n minHeight,\n title,\n \"aria-label\": ariaLabel,\n \"aria-describedby\": ariaDescribedBy,\n initialFocusRef,\n testID,\n themeMode,\n themeProductContext,\n ...rest\n },\n ref\n ) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.modal();\n const modalRef = useRef<HTMLDivElement>(null);\n const closeButtonRef = useRef<HTMLDivElement>(null);\n const previousActiveElement = useRef<HTMLElement | null>(null);\n const titleId = useId();\n\n useEffect(() => {\n previousActiveElement.current = document.activeElement as HTMLElement;\n\n const focusTarget =\n initialFocusRef?.current ||\n closeButtonRef.current ||\n (modalRef.current && getFocusableElements(modalRef.current)[0]);\n\n if (focusTarget) {\n focusTarget.focus();\n } else {\n modalRef.current?.focus();\n }\n\n return () => {\n previousActiveElement.current?.focus();\n };\n }, [initialFocusRef]);\n\n useEffect(() => {\n if (!onClose) 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 }, [onClose]);\n\n useEffect(() => {\n if (!closeOutside || !onClose) return;\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target;\n if (!target || !(target instanceof Node)) return;\n if (modalRef.current && !modalRef.current.contains(target)) {\n const portalContent = (target as Element).closest?.(\n `[data-modal-id=\"${titleId}\"]`\n );\n if (!portalContent) {\n onClose();\n }\n }\n };\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () =>\n document.removeEventListener(\"mousedown\", handleClickOutside);\n }, [closeOutside, onClose, titleId]);\n\n const handleKeyDown = useCallback((event: React.KeyboardEvent) => {\n if (event.key !== \"Tab\" || !modalRef.current) return;\n\n const focusableElements = getFocusableElements(modalRef.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 const maxWidthValue =\n type === \"full-screen\" || type === \"bottom-sheet\"\n ? \"100%\"\n : (maxWidth ?? sizing.maxWidth);\n const hasDefaultHeader = !header && (onBack || onClose);\n const hasHeader = !!header || hasDefaultHeader;\n\n const typeStyles: React.CSSProperties =\n type === \"full-screen\"\n ? {\n position: \"fixed\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 1,\n maxWidth: \"100%\",\n }\n : type === \"bottom-sheet\"\n ? {\n position: \"fixed\",\n bottom: 0,\n left: 0,\n right: 0,\n zIndex: 1,\n maxWidth: \"100%\",\n }\n : {};\n\n return (\n <Box\n testID={testID}\n ref={modalRef}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={title ? titleId : undefined}\n aria-label={!title ? ariaLabel : undefined}\n aria-describedby={ariaDescribedBy}\n data-modal-id={titleId}\n data-modal-type={type}\n tabIndex={-1}\n onKeyDown={handleKeyDown}\n flexGrow={1}\n position=\"relative\"\n width=\"100%\"\n style={{\n maxWidth:\n typeof maxWidthValue === \"number\"\n ? `${maxWidthValue}px`\n : maxWidthValue,\n minHeight:\n typeof minHeight === \"number\" ? `${minHeight}px` : minHeight,\n outline: \"none\",\n ...typeStyles,\n ...styledProps,\n }}\n {...rest}\n >\n {title && (\n <Box\n id={titleId}\n position=\"absolute\"\n style={{\n clip: \"rect(0 0 0 0)\",\n clipPath: \"inset(50%)\",\n height: 1,\n width: 1,\n overflow: \"hidden\",\n whiteSpace: \"nowrap\",\n }}\n >\n {title}\n </Box>\n )}\n <ModalIdContext.Provider value={titleId}>\n <WorkArea\n ref={ref}\n stretched\n openContent={openContent}\n type={type}\n align={align}\n >\n {hasHeader && (\n <Box\n flexDirection=\"row\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n width=\"100%\"\n padding={sizing.headerPadding}\n style={{ flexShrink: 0 }}\n >\n {header ?? (\n <>\n <Box style={{ minWidth: 36 }}>\n {onBack && (\n <IconButton\n variant=\"secondary\"\n tone=\"mono\"\n size={sizing.headerButtonSize}\n icon={<ChevronLeft />}\n onPress={onBack}\n aria-label=\"Go back\"\n />\n )}\n </Box>\n <Box\n ref={closeButtonRef}\n style={{ minWidth: 36 }}\n alignItems=\"flex-end\"\n >\n {onClose && (\n <IconButton\n variant=\"secondary\"\n tone=\"mono\"\n size={sizing.headerButtonSize}\n icon={<Remove />}\n onPress={onClose}\n aria-label=\"Close modal\"\n />\n )}\n </Box>\n </>\n )}\n </Box>\n )}\n <Box\n flexGrow={1}\n width=\"100%\"\n padding={openContent ? 0 : sizing.contentPadding}\n style={{\n paddingTop:\n hasHeader && !openContent ? sizing.headerGap : undefined,\n }}\n >\n {children}\n </Box>\n {footer && (\n <Box\n width=\"100%\"\n padding={openContent ? 0 : sizing.contentPadding}\n style={{ paddingTop: 0, flexShrink: 0 }}\n >\n {footer}\n </Box>\n )}\n </WorkArea>\n </ModalIdContext.Provider>\n </Box>\n );\n }\n);\n\nModal.displayName = \"Modal\";\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 { forwardRef } 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 { WorkAreaProps } from \"./types\";\n\nconst getBorderRadius = (\n type: WorkAreaProps[\"type\"],\n baseRadius: number\n): string | number => {\n switch (type) {\n case \"full-screen\":\n return 0;\n case \"bottom-sheet\":\n return `${baseRadius}px ${baseRadius}px 0 0`;\n default:\n return baseRadius;\n }\n};\n\nexport const WorkArea = forwardRef<any, WorkAreaProps>(\n (\n {\n children,\n openContent = false,\n stretched = false,\n fetching = false,\n type = \"popup\",\n align,\n testID,\n themeMode,\n themeProductContext,\n },\n ref\n ) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n const sizing = theme.sizing.modal();\n const showShadow = type !== \"full-screen\";\n\n return (\n <Box\n testID={testID}\n ref={ref}\n backgroundColor={theme.colors.background.primary}\n width=\"100%\"\n height={stretched ? \"100%\" : \"auto\"}\n flexDirection=\"column\"\n alignItems={align === \"center\" ? \"center\" : \"stretch\"}\n style={{\n borderRadius: getBorderRadius(type, sizing.borderRadius),\n boxShadow: showShadow ? sizing.shadow : \"none\",\n overflow: \"hidden\",\n color: theme.colors.content.primary,\n }}\n >\n <Box\n width=\"100%\"\n height=\"100%\"\n flexDirection=\"column\"\n alignItems={align === \"center\" ? \"center\" : \"stretch\"}\n style={{ textAlign: align === \"center\" ? \"center\" : \"left\" }}\n >\n {fetching ? (\n <Box\n alignItems=\"center\"\n justifyContent=\"center\"\n width=\"100%\"\n height=\"100%\"\n >\n <div>Loading...</div>\n </Box>\n ) : (\n children\n )}\n </Box>\n </Box>\n );\n }\n);\n\nWorkArea.displayName = \"WorkArea\";\n","import { useCallback, useMemo, useState } from \"react\";\nimport { ModalContext } from \"./ModalContext\";\nimport { ModalRoot } from \"./ModalRoot\";\nimport type { ModalProviderProps, ModalType } from \"./types\";\n\nexport const ModalProvider = ({ children, testID }: ModalProviderProps) => {\n const [modals, setModals] = useState<Record<string, ModalType>>({});\n\n const onOpenModal = useCallback(\n (key: string, modal: ModalType) =>\n setModals((m) => ({ ...m, [key]: modal })),\n []\n );\n\n const onCloseModal = useCallback(\n (key: string) =>\n setModals((m) => {\n if (!m[key]) return m;\n const newModals = { ...m };\n delete newModals[key];\n return newModals;\n }),\n []\n );\n\n const contextValue = useMemo(\n () => ({ onOpenModal, onCloseModal }),\n [onOpenModal, onCloseModal]\n );\n\n return (\n <ModalContext.Provider value={contextValue}>\n {children}\n <ModalRoot modals={modals} testID={testID} />\n </ModalContext.Provider>\n );\n};\n","import { createContext } from \"react\";\nimport type { ModalContextType } from \"./types\";\n\nconst invariantViolation = () => {\n throw new Error(\n \"Attempted to call useModal outside of modal context. Make sure your app is rendered inside ModalProvider.\"\n );\n};\n\nexport const ModalContext = createContext<ModalContextType>({\n onOpenModal: invariantViolation,\n onCloseModal: invariantViolation,\n});\n","import React, { memo } from \"react\";\nimport type { ModalRootProps } from \"./types\";\n\n// Web portal not available on React Native\n// Native modal implementation would use RN-specific approach\nexport const ModalRoot = memo(\n ({ modals: _modals, testID: _testID }: ModalRootProps) => {\n return null;\n }\n);\n\nModalRoot.displayName = \"ModalRoot\";\n","import { useContext, useEffect, useMemo, useRef, useCallback } from \"react\";\nimport { ModalContext } from \"./ModalContext\";\nimport { ModalType } from \"./types\";\n\nexport const useModal = (modal: ModalType): [() => void, () => void] => {\n const { onOpenModal, onCloseModal } = useContext(ModalContext);\n const key = useMemo(() => Math.random().toString(36).substr(2, 9), []);\n const modalRef = useRef(modal);\n\n useEffect(() => {\n modalRef.current = modal;\n }, [modal]);\n\n const open = useCallback(() => {\n onOpenModal(key, modalRef.current);\n }, [key, onOpenModal]);\n\n const close = useCallback(() => {\n onCloseModal(key);\n }, [key, onCloseModal]);\n\n return [open, close];\n};\n","export * from \"./Modal\";\nexport * from \"./ModalProvider\";\nexport * from \"./useModal\";\nexport * from \"./types\";\nexport * from \"./WorkArea\";\nexport { useModalId } from \"@xsolla/xui-core\";\n"],"mappings":"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","names":["forwardRef","useResolvedTheme","jsx","jsx","forwardRef","useResolvedTheme","handleKeyDown","useCallback","jsx","jsxs","useCallback","useEffect","useMemo","useRef","useCallback","useMemo","useRef","useEffect","useCallback"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-modal",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.160.0",
|
|
4
4
|
"main": "./web/index.js",
|
|
5
5
|
"module": "./web/index.mjs",
|
|
6
6
|
"types": "./web/index.d.ts",
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"test:coverage": "vitest run --coverage"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@xsolla/xui-button": "0.
|
|
17
|
-
"@xsolla/xui-core": "0.
|
|
18
|
-
"@xsolla/xui-icons-base": "0.
|
|
19
|
-
"@xsolla/xui-primitives-core": "0.
|
|
16
|
+
"@xsolla/xui-button": "0.160.0",
|
|
17
|
+
"@xsolla/xui-core": "0.160.0",
|
|
18
|
+
"@xsolla/xui-icons-base": "0.160.0",
|
|
19
|
+
"@xsolla/xui-primitives-core": "0.160.0"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"react": ">=16.8.0",
|
package/web/index.d.mts
CHANGED
|
@@ -33,6 +33,8 @@ interface ModalProps extends ThemeOverrideProps {
|
|
|
33
33
|
"aria-describedby"?: string;
|
|
34
34
|
/** Ref to element that should receive focus when modal opens */
|
|
35
35
|
initialFocusRef?: RefObject<HTMLElement>;
|
|
36
|
+
/** Test ID for testing frameworks */
|
|
37
|
+
testID?: string;
|
|
36
38
|
}
|
|
37
39
|
type ModalType = (props: any) => ReactNode;
|
|
38
40
|
interface ModalContextType {
|
|
@@ -41,9 +43,13 @@ interface ModalContextType {
|
|
|
41
43
|
}
|
|
42
44
|
interface ModalProviderProps {
|
|
43
45
|
children: ReactNode;
|
|
46
|
+
/** Test ID for testing frameworks */
|
|
47
|
+
testID?: string;
|
|
44
48
|
}
|
|
45
49
|
interface ModalRootProps {
|
|
46
50
|
modals: Record<string, ModalType>;
|
|
51
|
+
/** Test ID for testing frameworks */
|
|
52
|
+
testID?: string;
|
|
47
53
|
}
|
|
48
54
|
type WorkAreaSize = "sm" | "md" | "lg";
|
|
49
55
|
interface WorkAreaProps extends ThemeOverrideProps {
|
|
@@ -56,11 +62,13 @@ interface WorkAreaProps extends ThemeOverrideProps {
|
|
|
56
62
|
type?: ModalVariant;
|
|
57
63
|
/** Content alignment */
|
|
58
64
|
align?: "left" | "center";
|
|
65
|
+
/** Test ID for testing frameworks */
|
|
66
|
+
testID?: string;
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
declare const Modal: react.ForwardRefExoticComponent<ModalProps & react.RefAttributes<any>>;
|
|
62
70
|
|
|
63
|
-
declare const ModalProvider: ({ children }: ModalProviderProps) => react_jsx_runtime.JSX.Element;
|
|
71
|
+
declare const ModalProvider: ({ children, testID }: ModalProviderProps) => react_jsx_runtime.JSX.Element;
|
|
64
72
|
|
|
65
73
|
declare const useModal: (modal: ModalType) => [() => void, () => void];
|
|
66
74
|
|
package/web/index.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ interface ModalProps extends ThemeOverrideProps {
|
|
|
33
33
|
"aria-describedby"?: string;
|
|
34
34
|
/** Ref to element that should receive focus when modal opens */
|
|
35
35
|
initialFocusRef?: RefObject<HTMLElement>;
|
|
36
|
+
/** Test ID for testing frameworks */
|
|
37
|
+
testID?: string;
|
|
36
38
|
}
|
|
37
39
|
type ModalType = (props: any) => ReactNode;
|
|
38
40
|
interface ModalContextType {
|
|
@@ -41,9 +43,13 @@ interface ModalContextType {
|
|
|
41
43
|
}
|
|
42
44
|
interface ModalProviderProps {
|
|
43
45
|
children: ReactNode;
|
|
46
|
+
/** Test ID for testing frameworks */
|
|
47
|
+
testID?: string;
|
|
44
48
|
}
|
|
45
49
|
interface ModalRootProps {
|
|
46
50
|
modals: Record<string, ModalType>;
|
|
51
|
+
/** Test ID for testing frameworks */
|
|
52
|
+
testID?: string;
|
|
47
53
|
}
|
|
48
54
|
type WorkAreaSize = "sm" | "md" | "lg";
|
|
49
55
|
interface WorkAreaProps extends ThemeOverrideProps {
|
|
@@ -56,11 +62,13 @@ interface WorkAreaProps extends ThemeOverrideProps {
|
|
|
56
62
|
type?: ModalVariant;
|
|
57
63
|
/** Content alignment */
|
|
58
64
|
align?: "left" | "center";
|
|
65
|
+
/** Test ID for testing frameworks */
|
|
66
|
+
testID?: string;
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
declare const Modal: react.ForwardRefExoticComponent<ModalProps & react.RefAttributes<any>>;
|
|
62
70
|
|
|
63
|
-
declare const ModalProvider: ({ children }: ModalProviderProps) => react_jsx_runtime.JSX.Element;
|
|
71
|
+
declare const ModalProvider: ({ children, testID }: ModalProviderProps) => react_jsx_runtime.JSX.Element;
|
|
64
72
|
|
|
65
73
|
declare const useModal: (modal: ModalType) => [() => void, () => void];
|
|
66
74
|
|
package/web/index.js
CHANGED
|
@@ -319,6 +319,7 @@ var WorkArea = (0, import_react3.forwardRef)(
|
|
|
319
319
|
fetching = false,
|
|
320
320
|
type = "popup",
|
|
321
321
|
align,
|
|
322
|
+
testID,
|
|
322
323
|
themeMode,
|
|
323
324
|
themeProductContext
|
|
324
325
|
}, ref) => {
|
|
@@ -328,6 +329,7 @@ var WorkArea = (0, import_react3.forwardRef)(
|
|
|
328
329
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
329
330
|
Box,
|
|
330
331
|
{
|
|
332
|
+
testID,
|
|
331
333
|
ref,
|
|
332
334
|
backgroundColor: theme.colors.background.primary,
|
|
333
335
|
width: "100%",
|
|
@@ -396,6 +398,7 @@ var Modal = (0, import_react4.forwardRef)(
|
|
|
396
398
|
"aria-label": ariaLabel,
|
|
397
399
|
"aria-describedby": ariaDescribedBy,
|
|
398
400
|
initialFocusRef,
|
|
401
|
+
testID,
|
|
399
402
|
themeMode,
|
|
400
403
|
themeProductContext,
|
|
401
404
|
...rest
|
|
@@ -482,6 +485,7 @@ var Modal = (0, import_react4.forwardRef)(
|
|
|
482
485
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
483
486
|
Box,
|
|
484
487
|
{
|
|
488
|
+
testID,
|
|
485
489
|
ref: modalRef,
|
|
486
490
|
role: "dialog",
|
|
487
491
|
"aria-modal": "true",
|
|
@@ -540,14 +544,14 @@ var Modal = (0, import_react4.forwardRef)(
|
|
|
540
544
|
style: { flexShrink: 0 },
|
|
541
545
|
children: header ?? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
542
546
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box, { style: { minWidth: 36 }, children: onBack && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
543
|
-
import_xui_button.
|
|
547
|
+
import_xui_button.IconButton,
|
|
544
548
|
{
|
|
545
549
|
variant: "secondary",
|
|
550
|
+
tone: "mono",
|
|
546
551
|
size: sizing.headerButtonSize,
|
|
547
|
-
|
|
552
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_xui_icons_base.ChevronLeft, {}),
|
|
548
553
|
onPress: onBack,
|
|
549
|
-
"aria-label": "Go back"
|
|
550
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_xui_icons_base.ChevronLeft, {})
|
|
554
|
+
"aria-label": "Go back"
|
|
551
555
|
}
|
|
552
556
|
) }),
|
|
553
557
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -557,14 +561,14 @@ var Modal = (0, import_react4.forwardRef)(
|
|
|
557
561
|
style: { minWidth: 36 },
|
|
558
562
|
alignItems: "flex-end",
|
|
559
563
|
children: onClose && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
560
|
-
import_xui_button.
|
|
564
|
+
import_xui_button.IconButton,
|
|
561
565
|
{
|
|
562
566
|
variant: "secondary",
|
|
567
|
+
tone: "mono",
|
|
563
568
|
size: sizing.headerButtonSize,
|
|
564
|
-
|
|
569
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_xui_icons_base.Remove, {}),
|
|
565
570
|
onPress: onClose,
|
|
566
|
-
"aria-label": "Close modal"
|
|
567
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_xui_icons_base.Remove, {})
|
|
571
|
+
"aria-label": "Close modal"
|
|
568
572
|
}
|
|
569
573
|
)
|
|
570
574
|
}
|
|
@@ -578,7 +582,9 @@ var Modal = (0, import_react4.forwardRef)(
|
|
|
578
582
|
flexGrow: 1,
|
|
579
583
|
width: "100%",
|
|
580
584
|
padding: openContent ? 0 : sizing.contentPadding,
|
|
581
|
-
style: {
|
|
585
|
+
style: {
|
|
586
|
+
paddingTop: hasHeader && !openContent ? sizing.headerGap : void 0
|
|
587
|
+
},
|
|
582
588
|
children
|
|
583
589
|
}
|
|
584
590
|
),
|
|
@@ -620,7 +626,7 @@ var ModalContext = (0, import_react5.createContext)({
|
|
|
620
626
|
var import_react6 = __toESM(require("react"));
|
|
621
627
|
var import_react_dom = __toESM(require("react-dom"));
|
|
622
628
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
623
|
-
var ModalRoot = (0, import_react6.memo)(({ modals }) => {
|
|
629
|
+
var ModalRoot = (0, import_react6.memo)(({ modals, testID }) => {
|
|
624
630
|
const visibleModalKey = (0, import_react6.useMemo)(
|
|
625
631
|
() => Object.keys(modals)[Object.keys(modals).length - 1],
|
|
626
632
|
[modals]
|
|
@@ -630,6 +636,7 @@ var ModalRoot = (0, import_react6.memo)(({ modals }) => {
|
|
|
630
636
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
631
637
|
Box,
|
|
632
638
|
{
|
|
639
|
+
testID,
|
|
633
640
|
position: "fixed",
|
|
634
641
|
zIndex: 1e3,
|
|
635
642
|
top: 0,
|
|
@@ -679,7 +686,7 @@ ModalRoot.displayName = "ModalRoot";
|
|
|
679
686
|
|
|
680
687
|
// src/ModalProvider.tsx
|
|
681
688
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
682
|
-
var ModalProvider = ({ children }) => {
|
|
689
|
+
var ModalProvider = ({ children, testID }) => {
|
|
683
690
|
const [modals, setModals] = (0, import_react7.useState)({});
|
|
684
691
|
const onOpenModal = (0, import_react7.useCallback)(
|
|
685
692
|
(key, modal) => setModals((m) => ({ ...m, [key]: modal })),
|
|
@@ -700,7 +707,7 @@ var ModalProvider = ({ children }) => {
|
|
|
700
707
|
);
|
|
701
708
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(ModalContext.Provider, { value: contextValue, children: [
|
|
702
709
|
children,
|
|
703
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ModalRoot, { modals })
|
|
710
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ModalRoot, { modals, testID })
|
|
704
711
|
] });
|
|
705
712
|
};
|
|
706
713
|
|