@vkontakte/vkui 7.1.2 → 7.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Alert/Alert.js +5 -5
- package/dist/components/Alert/Alert.js.map +1 -1
- package/dist/components/CarouselBase/CarouselBase.d.ts.map +1 -1
- package/dist/components/CarouselBase/CarouselBase.js +1 -4
- package/dist/components/CarouselBase/CarouselBase.js.map +1 -1
- package/dist/components/FormItem/FormItem.d.ts.map +1 -1
- package/dist/components/FormItem/FormItem.js +1 -0
- package/dist/components/FormItem/FormItem.js.map +1 -1
- package/dist/components/HorizontalScroll/HorizontalScroll.d.ts +1 -1
- package/dist/components/HorizontalScroll/HorizontalScroll.d.ts.map +1 -1
- package/dist/components/HorizontalScroll/HorizontalScroll.js +17 -18
- package/dist/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
- package/dist/components/ModalCard/ModalCardInternal.d.ts +1 -1
- package/dist/components/ModalCard/ModalCardInternal.d.ts.map +1 -1
- package/dist/components/ModalCard/ModalCardInternal.js +4 -3
- package/dist/components/ModalCard/ModalCardInternal.js.map +1 -1
- package/dist/components/ModalCard/types.d.ts +7 -0
- package/dist/components/ModalCard/types.d.ts.map +1 -1
- package/dist/components/ModalCard/types.js.map +1 -1
- package/dist/components/ModalPage/ModalPageInternal.d.ts +1 -1
- package/dist/components/ModalPage/ModalPageInternal.d.ts.map +1 -1
- package/dist/components/ModalPage/ModalPageInternal.js +4 -3
- package/dist/components/ModalPage/ModalPageInternal.js.map +1 -1
- package/dist/components/ModalPage/types.d.ts +7 -0
- package/dist/components/ModalPage/types.d.ts.map +1 -1
- package/dist/components/ModalPage/types.js.map +1 -1
- package/dist/components/OnboardingTooltip/OnboardingTooltip.d.ts +7 -2
- package/dist/components/OnboardingTooltip/OnboardingTooltip.d.ts.map +1 -1
- package/dist/components/OnboardingTooltip/OnboardingTooltip.js +32 -13
- package/dist/components/OnboardingTooltip/OnboardingTooltip.js.map +1 -1
- package/dist/components/Pagination/Pagination.d.ts +6 -0
- package/dist/components/Pagination/Pagination.d.ts.map +1 -1
- package/dist/components/Pagination/Pagination.js +5 -3
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Pagination/PaginationPage/PaginationPageButton.d.ts.map +1 -1
- package/dist/components/Pagination/PaginationPage/PaginationPageButton.js +4 -4
- package/dist/components/Pagination/PaginationPage/PaginationPageButton.js.map +1 -1
- package/dist/components/Removable/Removable.d.ts +5 -1
- package/dist/components/Removable/Removable.d.ts.map +1 -1
- package/dist/components/Removable/Removable.js +4 -3
- package/dist/components/Removable/Removable.js.map +1 -1
- package/dist/components/TabbarItem/TabbarItem.d.ts +1 -1
- package/dist/components/TabbarItem/TabbarItem.d.ts.map +1 -1
- package/dist/components/TabbarItem/TabbarItem.js +16 -4
- package/dist/components/TabbarItem/TabbarItem.js.map +1 -1
- package/dist/components/TooltipBase/TooltipBase.d.ts +6 -1
- package/dist/components/TooltipBase/TooltipBase.d.ts.map +1 -1
- package/dist/components/TooltipBase/TooltipBase.js +3 -1
- package/dist/components/TooltipBase/TooltipBase.js.map +1 -1
- package/dist/components.css +1 -1
- package/dist/components.css.map +1 -1
- package/dist/cssm/components/Alert/Alert.js +5 -5
- package/dist/cssm/components/Alert/Alert.js.map +1 -1
- package/dist/cssm/components/CarouselBase/CarouselBase.js +1 -4
- package/dist/cssm/components/CarouselBase/CarouselBase.js.map +1 -1
- package/dist/cssm/components/FormItem/FormItem.js +1 -0
- package/dist/cssm/components/FormItem/FormItem.js.map +1 -1
- package/dist/cssm/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.module.css +1 -0
- package/dist/cssm/components/HorizontalScroll/HorizontalScroll.js +18 -14
- package/dist/cssm/components/HorizontalScroll/HorizontalScroll.js.map +1 -1
- package/dist/cssm/components/IconButton/IconButton.module.css +6 -0
- package/dist/cssm/components/ModalCard/ModalCardInternal.js +2 -2
- package/dist/cssm/components/ModalCard/ModalCardInternal.js.map +1 -1
- package/dist/cssm/components/ModalCard/types.js.map +1 -1
- package/dist/cssm/components/ModalPage/ModalPageInternal.js +2 -2
- package/dist/cssm/components/ModalPage/ModalPageInternal.js.map +1 -1
- package/dist/cssm/components/ModalPage/types.js.map +1 -1
- package/dist/cssm/components/OnboardingTooltip/OnboardingTooltip.js +21 -7
- package/dist/cssm/components/OnboardingTooltip/OnboardingTooltip.js.map +1 -1
- package/dist/cssm/components/OnboardingTooltip/OnboardingTooltip.module.css +15 -0
- package/dist/cssm/components/Pagination/Pagination.js +4 -2
- package/dist/cssm/components/Pagination/Pagination.js.map +1 -1
- package/dist/cssm/components/Pagination/PaginationPage/PaginationPageButton.js +4 -4
- package/dist/cssm/components/Pagination/PaginationPage/PaginationPageButton.js.map +1 -1
- package/dist/cssm/components/PanelHeaderButton/PanelHeaderButton.module.css +6 -0
- package/dist/cssm/components/Removable/Removable.js +2 -2
- package/dist/cssm/components/Removable/Removable.js.map +1 -1
- package/dist/cssm/components/Removable/Removable.module.css +3 -0
- package/dist/cssm/components/Search/Search.module.css +1 -0
- package/dist/cssm/components/SimpleCell/SimpleCell.module.css +2 -0
- package/dist/cssm/components/SubnavigationButton/SubnavigationButton.module.css +1 -0
- package/dist/cssm/components/TabbarItem/TabbarItem.js +13 -3
- package/dist/cssm/components/TabbarItem/TabbarItem.js.map +1 -1
- package/dist/cssm/components/TooltipBase/TooltipBase.js +2 -1
- package/dist/cssm/components/TooltipBase/TooltipBase.js.map +1 -1
- package/dist/cssm/components/TooltipBase/TooltipBase.module.css +1 -0
- package/dist/cssm/hooks/useFocusTrap.js +1 -1
- package/dist/cssm/hooks/useFocusTrap.js.map +1 -1
- package/dist/cssm/types.js.map +1 -1
- package/dist/hooks/useFocusTrap.js +1 -1
- package/dist/hooks/useFocusTrap.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/vkui.css +1 -1
- package/dist/vkui.css.map +1 -1
- package/package.json +1 -1
- package/src/components/Alert/Alert.tsx +5 -5
- package/src/components/CarouselBase/CarouselBase.tsx +1 -6
- package/src/components/FormItem/FormItem.tsx +1 -0
- package/src/components/HorizontalScroll/HorizontalCellShowMore/HorizontalCellShowMore.module.css +1 -0
- package/src/components/HorizontalScroll/HorizontalScroll.tsx +21 -15
- package/src/components/IconButton/IconButton.module.css +5 -0
- package/src/components/ModalCard/ModalCardInternal.tsx +5 -1
- package/src/components/ModalCard/types.ts +7 -0
- package/src/components/ModalPage/ModalPageInternal.tsx +2 -1
- package/src/components/ModalPage/types.ts +7 -0
- package/src/components/OnboardingTooltip/OnboardingTooltip.module.css +13 -0
- package/src/components/OnboardingTooltip/OnboardingTooltip.tsx +36 -8
- package/src/components/Pagination/Pagination.tsx +19 -5
- package/src/components/Pagination/PaginationPage/PaginationPageButton.tsx +3 -3
- package/src/components/PanelHeaderButton/PanelHeaderButton.module.css +5 -0
- package/src/components/Removable/Removable.module.css +3 -0
- package/src/components/Removable/Removable.tsx +12 -1
- package/src/components/Search/Search.module.css +1 -0
- package/src/components/SimpleCell/SimpleCell.module.css +2 -0
- package/src/components/SubnavigationButton/SubnavigationButton.module.css +1 -0
- package/src/components/TabbarItem/TabbarItem.tsx +18 -1
- package/src/components/TooltipBase/TooltipBase.module.css +1 -0
- package/src/components/TooltipBase/TooltipBase.tsx +7 -1
- package/src/hooks/useFocusTrap.ts +1 -1
- package/src/types.ts +2 -1
- package/dist/components/Pagination/utils.d.ts +0 -2
- package/dist/components/Pagination/utils.d.ts.map +0 -1
- package/dist/components/Pagination/utils.js +0 -5
- package/dist/components/Pagination/utils.js.map +0 -1
- package/dist/cssm/components/Pagination/utils.js +0 -5
- package/dist/cssm/components/Pagination/utils.js.map +0 -1
- package/src/components/Pagination/utils.ts +0 -3
|
@@ -29,7 +29,7 @@ const transitionStateClassNames = {
|
|
|
29
29
|
* В компоненте заложена вся логика модального окна.
|
|
30
30
|
*
|
|
31
31
|
* @private
|
|
32
|
-
*/ export const ModalPageInternal = ({ open, header, footer, size: desktopMaxWidth, height, children, className, style, snapPoint, onSnapPointChange, getModalContentRef, ModalOverlay = ModalOverlayDefault, modalOverlayTestId, modalContentTestId, modalDismissButtonTestId, noFocusToDialog, hideCloseButton, preventClose, disableContentPanningGesture, onOpen, onOpened, onClose = noop, onClosed, ...restProps })=>{
|
|
32
|
+
*/ export const ModalPageInternal = ({ open, header, footer, size: desktopMaxWidth, height, children, className, style, snapPoint, onSnapPointChange, getModalContentRef, ModalOverlay = ModalOverlayDefault, modalOverlayTestId, modalContentTestId, modalDismissButtonTestId, noFocusToDialog, hideCloseButton, preventClose, disableContentPanningGesture, onOpen, onOpened, onClose = noop, onClosed, disableFocusTrap, ...restProps })=>{
|
|
33
33
|
const { hasCustomPanelHeaderAfter } = useConfigProvider();
|
|
34
34
|
const [transitionState, { ref, onTransitionEnd }] = useCSSTransition(open, {
|
|
35
35
|
enableAppear: true,
|
|
@@ -101,7 +101,7 @@ const transitionStateClassNames = {
|
|
|
101
101
|
autoFocus: !noFocusToDialog,
|
|
102
102
|
role: "dialog",
|
|
103
103
|
"aria-modal": "true",
|
|
104
|
-
disabled: !opened || hidden,
|
|
104
|
+
disabled: !opened || hidden || disableFocusTrap,
|
|
105
105
|
className: classNames(className, styles.host, isDesktop ? styles.hostDesktop : styles.hostMobile, !isDesktop && (hasCustomPanelHeaderAfter ? styles.hostMobileSafeAreaInsetTopWithCustomOffset : styles.hostMobileSafeAreaInsetTop), desktopMaxWidthClassName, sizeX === 'regular' && 'vkuiInternalModalPage--sizeX-regular'),
|
|
106
106
|
style: mergeStyle(mergeStyle(desktopMaxWidthStyle, getHeightCSSVariable(height)), style),
|
|
107
107
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/ModalPage/ModalPageInternal.tsx"],"sourcesContent":["'use client';\n\nimport { type ComponentType, type KeyboardEvent, useCallback } from 'react';\nimport { classNames, hasReactNode, noop } from '@vkontakte/vkjs';\nimport { mergeStyle } from '../../helpers/mergeStyle';\nimport { useAdaptivityWithJSMediaQueries } from '../../hooks/useAdaptivityWithJSMediaQueries';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useVirtualKeyboardState } from '../../hooks/useVirtualKeyboardState';\nimport { Keys, pressedKey } from '../../lib/accessibility';\nimport { useCSSTransition, type UseCSSTransitionState } from '../../lib/animation';\nimport {\n BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE,\n type SnapPoint,\n type SnapPointChange,\n useBottomSheet,\n} from '../../lib/sheet';\nimport type { CSSCustomProperties } from '../../types';\nimport { useScrollLock } from '../AppRoot/ScrollContext';\nimport { useConfigProvider } from '../ConfigProvider/ConfigProviderContext';\nimport { FocusTrap } from '../FocusTrap/FocusTrap';\nimport { ModalDismissButton } from '../ModalDismissButton/ModalDismissButton';\nimport { ModalOutlet } from '../ModalOutlet/ModalOutlet';\nimport {\n ModalOverlay as ModalOverlayDefault,\n type ModalOverlayProps,\n} from '../ModalOverlay/ModalOverlay';\nimport { ModalPageContent } from '../ModalPageContent/ModalPageContent';\nimport type { ModalPageProps } from './types';\nimport styles from './ModalPage.module.css';\n\nconst transitionStateClassNames: Partial<Record<UseCSSTransitionState, string>> = {\n appear: styles['documentStateEnter'],\n appearing: styles['documentStateEntering'],\n\n enter: styles['documentStateEnter'],\n entering: styles['documentStateEntering'],\n\n exiting: styles['documentStateExiting'],\n exited: styles['documentStateExited'],\n};\n\nexport interface ModalPageInternalProps\n extends Omit<ModalPageProps, 'nav' | 'keepMounted' | 'settlingHeight' | 'dynamicContentHeight'> {\n snapPoint: SnapPoint;\n ModalOverlay?: ComponentType<ModalOverlayProps>;\n onSnapPointChange?: SnapPointChange;\n}\n\n/**\n * В компоненте заложена вся логика модального окна.\n *\n * @private\n */\nexport const ModalPageInternal = ({\n open,\n header,\n footer,\n size: desktopMaxWidth,\n height,\n children,\n className,\n style,\n snapPoint,\n onSnapPointChange,\n getModalContentRef,\n ModalOverlay = ModalOverlayDefault,\n modalOverlayTestId,\n modalContentTestId,\n modalDismissButtonTestId,\n noFocusToDialog,\n hideCloseButton,\n preventClose,\n disableContentPanningGesture,\n onOpen,\n onOpened,\n onClose = noop,\n onClosed,\n ...restProps\n}: ModalPageInternalProps) => {\n const { hasCustomPanelHeaderAfter } = useConfigProvider();\n const [transitionState, { ref, onTransitionEnd }] = useCSSTransition<HTMLDivElement>(open, {\n enableAppear: true,\n onEnter() {\n onOpen?.();\n },\n onEntered() {\n onOpened?.();\n },\n onExited() {\n onClosed?.();\n },\n });\n const opened = transitionState === 'appeared' || transitionState === 'entered';\n const hidden = transitionState === 'exited';\n const closable = !preventClose && opened;\n\n const { sizeX, isDesktop } = useAdaptivityWithJSMediaQueries();\n const bottomSheetEnabled = !isDesktop && !preventClose && transitionState !== 'exited';\n const { opened: keyboardOpened } = useVirtualKeyboardState(bottomSheetEnabled);\n\n const [{ initialStyle, setSheetEl, setSheetScrollEl, setBackdropEl }, bottomSheetEventHandlers] =\n useBottomSheet(bottomSheetEnabled, {\n blocked: keyboardOpened,\n snapPoint,\n sheetCSSProperty: '--vkui_internal_ModalPageDocument--snapPoint',\n backdropCSSProperty: '--vkui_internal--modal-overlay--opacity',\n onSnapPointChange,\n onDismiss() {\n onClose('swipe-down');\n },\n });\n const documentStyle = keyboardOpened\n ? {\n '--vkui_internal_ModalPageDocument--safeAreaInsetBottom': '0px',\n ...initialStyle,\n }\n : initialStyle;\n const handleSheetRef = useExternRef<HTMLDivElement>(setSheetEl, ref);\n const handleSheetScrollRef = useExternRef<HTMLDivElement>(setSheetScrollEl, getModalContentRef);\n\n const disableContentPanningGestureProp = disableContentPanningGesture\n ? BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE\n : undefined;\n const [desktopMaxWidthClassName, desktopMaxWidthStyle] = resolveDesktopMaxWidth(\n isDesktop ? desktopMaxWidth : 's',\n );\n\n const modalOverlay = (\n <ModalOverlay\n getRootRef={setBackdropEl}\n data-testid={modalOverlayTestId}\n visible={open}\n onClick={\n closable\n ? function handleBackdropClick(event) {\n onClose('click-overlay', event);\n }\n : undefined\n }\n />\n );\n const closeButton =\n hideCloseButton || !isDesktop ? null : (\n <ModalDismissButton\n data-testid={modalDismissButtonTestId}\n onClick={\n closable\n ? function handleDismissButtonClick(event) {\n onClose('click-close-button', event);\n }\n : undefined\n }\n />\n );\n const handleEscKeyDown = useCallback(\n (event: KeyboardEvent<HTMLElement>) => {\n if (closable && pressedKey(event) === Keys.ESCAPE) {\n onClose('escape-key');\n }\n },\n [closable, onClose],\n );\n\n useScrollLock(!hidden);\n\n return (\n <ModalOutlet hidden={hidden} isDesktop={isDesktop} onKeyDown={handleEscKeyDown}>\n {modalOverlay}\n <FocusTrap\n {...restProps}\n autoFocus={!noFocusToDialog}\n role=\"dialog\"\n aria-modal=\"true\"\n disabled={!opened || hidden}\n className={classNames(\n className,\n styles.host,\n isDesktop ? styles.hostDesktop : styles.hostMobile,\n !isDesktop &&\n (hasCustomPanelHeaderAfter\n ? styles.hostMobileSafeAreaInsetTopWithCustomOffset\n : styles.hostMobileSafeAreaInsetTop),\n desktopMaxWidthClassName,\n sizeX === 'regular' && 'vkuiInternalModalPage--sizeX-regular',\n )}\n style={mergeStyle(mergeStyle(desktopMaxWidthStyle, getHeightCSSVariable(height)), style)}\n >\n <div\n {...bottomSheetEventHandlers}\n ref={handleSheetRef}\n role=\"document\"\n style={documentStyle}\n className={classNames(\n styles.document,\n isDesktop ? styles.documentDesktop : styles.documentMobile,\n transitionStateClassNames[transitionState],\n )}\n onTransitionEnd={onTransitionEnd}\n >\n <div className={classNames(styles.children, isDesktop && styles.childrenDesktop)}>\n {hasReactNode(header) && header}\n <ModalPageContent\n getRootRef={handleSheetScrollRef}\n data-testid={modalContentTestId}\n {...disableContentPanningGestureProp}\n >\n {children}\n </ModalPageContent>\n {hasReactNode(footer) && footer}\n </div>\n {closeButton}\n </div>\n </FocusTrap>\n </ModalOutlet>\n );\n};\n\nconst desktopMaxWidthClassNames = {\n s: styles['hostDesktopMaxWidthS'],\n m: styles['hostDesktopMaxWidthM'],\n l: styles['hostDesktopMaxWidthL'],\n};\n\nfunction resolveDesktopMaxWidth(\n desktopMaxWidth: ModalPageInternalProps['size'] = 's',\n): [string | undefined, CSSCustomProperties | undefined] {\n if (typeof desktopMaxWidth === 'string') {\n return [desktopMaxWidthClassNames[desktopMaxWidth], undefined];\n }\n\n return [\n undefined,\n typeof desktopMaxWidth === 'number'\n ? { '--vkui_internal_ModalPage--desktopMaxWidth': `${desktopMaxWidth}px` }\n : undefined,\n ];\n}\n\nfunction getHeightCSSVariable(height?: number | string): CSSCustomProperties | undefined {\n return height !== undefined\n ? {\n '--vkui_internal_ModalPage--userHeight':\n typeof height === 'number' ? `${height}px` : height,\n }\n : undefined;\n}\n"],"names":["useCallback","classNames","hasReactNode","noop","mergeStyle","useAdaptivityWithJSMediaQueries","useExternRef","useVirtualKeyboardState","Keys","pressedKey","useCSSTransition","BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE","useBottomSheet","useScrollLock","useConfigProvider","FocusTrap","ModalDismissButton","ModalOutlet","ModalOverlay","ModalOverlayDefault","ModalPageContent","styles","transitionStateClassNames","appear","appearing","enter","entering","exiting","exited","ModalPageInternal","open","header","footer","size","desktopMaxWidth","height","children","className","style","snapPoint","onSnapPointChange","getModalContentRef","modalOverlayTestId","modalContentTestId","modalDismissButtonTestId","noFocusToDialog","hideCloseButton","preventClose","disableContentPanningGesture","onOpen","onOpened","onClose","onClosed","restProps","hasCustomPanelHeaderAfter","transitionState","ref","onTransitionEnd","enableAppear","onEnter","onEntered","onExited","opened","hidden","closable","sizeX","isDesktop","bottomSheetEnabled","keyboardOpened","initialStyle","setSheetEl","setSheetScrollEl","setBackdropEl","bottomSheetEventHandlers","blocked","sheetCSSProperty","backdropCSSProperty","onDismiss","documentStyle","handleSheetRef","handleSheetScrollRef","disableContentPanningGestureProp","undefined","desktopMaxWidthClassName","desktopMaxWidthStyle","resolveDesktopMaxWidth","modalOverlay","getRootRef","data-testid","visible","onClick","handleBackdropClick","event","closeButton","handleDismissButtonClick","handleEscKeyDown","ESCAPE","onKeyDown","autoFocus","role","aria-modal","disabled","host","hostDesktop","hostMobile","hostMobileSafeAreaInsetTopWithCustomOffset","hostMobileSafeAreaInsetTop","getHeightCSSVariable","div","document","documentDesktop","documentMobile","childrenDesktop","desktopMaxWidthClassNames","s","m","l"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ModalPage/ModalPageInternal.tsx"],"sourcesContent":["'use client';\n\nimport { type ComponentType, type KeyboardEvent, useCallback } from 'react';\nimport { classNames, hasReactNode, noop } from '@vkontakte/vkjs';\nimport { mergeStyle } from '../../helpers/mergeStyle';\nimport { useAdaptivityWithJSMediaQueries } from '../../hooks/useAdaptivityWithJSMediaQueries';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useVirtualKeyboardState } from '../../hooks/useVirtualKeyboardState';\nimport { Keys, pressedKey } from '../../lib/accessibility';\nimport { useCSSTransition, type UseCSSTransitionState } from '../../lib/animation';\nimport {\n BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE,\n type SnapPoint,\n type SnapPointChange,\n useBottomSheet,\n} from '../../lib/sheet';\nimport type { CSSCustomProperties } from '../../types';\nimport { useScrollLock } from '../AppRoot/ScrollContext';\nimport { useConfigProvider } from '../ConfigProvider/ConfigProviderContext';\nimport { FocusTrap } from '../FocusTrap/FocusTrap';\nimport { ModalDismissButton } from '../ModalDismissButton/ModalDismissButton';\nimport { ModalOutlet } from '../ModalOutlet/ModalOutlet';\nimport {\n ModalOverlay as ModalOverlayDefault,\n type ModalOverlayProps,\n} from '../ModalOverlay/ModalOverlay';\nimport { ModalPageContent } from '../ModalPageContent/ModalPageContent';\nimport type { ModalPageProps } from './types';\nimport styles from './ModalPage.module.css';\n\nconst transitionStateClassNames: Partial<Record<UseCSSTransitionState, string>> = {\n appear: styles['documentStateEnter'],\n appearing: styles['documentStateEntering'],\n\n enter: styles['documentStateEnter'],\n entering: styles['documentStateEntering'],\n\n exiting: styles['documentStateExiting'],\n exited: styles['documentStateExited'],\n};\n\nexport interface ModalPageInternalProps\n extends Omit<ModalPageProps, 'nav' | 'keepMounted' | 'settlingHeight' | 'dynamicContentHeight'> {\n snapPoint: SnapPoint;\n ModalOverlay?: ComponentType<ModalOverlayProps>;\n onSnapPointChange?: SnapPointChange;\n}\n\n/**\n * В компоненте заложена вся логика модального окна.\n *\n * @private\n */\nexport const ModalPageInternal = ({\n open,\n header,\n footer,\n size: desktopMaxWidth,\n height,\n children,\n className,\n style,\n snapPoint,\n onSnapPointChange,\n getModalContentRef,\n ModalOverlay = ModalOverlayDefault,\n modalOverlayTestId,\n modalContentTestId,\n modalDismissButtonTestId,\n noFocusToDialog,\n hideCloseButton,\n preventClose,\n disableContentPanningGesture,\n onOpen,\n onOpened,\n onClose = noop,\n onClosed,\n disableFocusTrap,\n ...restProps\n}: ModalPageInternalProps) => {\n const { hasCustomPanelHeaderAfter } = useConfigProvider();\n const [transitionState, { ref, onTransitionEnd }] = useCSSTransition<HTMLDivElement>(open, {\n enableAppear: true,\n onEnter() {\n onOpen?.();\n },\n onEntered() {\n onOpened?.();\n },\n onExited() {\n onClosed?.();\n },\n });\n const opened = transitionState === 'appeared' || transitionState === 'entered';\n const hidden = transitionState === 'exited';\n const closable = !preventClose && opened;\n\n const { sizeX, isDesktop } = useAdaptivityWithJSMediaQueries();\n const bottomSheetEnabled = !isDesktop && !preventClose && transitionState !== 'exited';\n const { opened: keyboardOpened } = useVirtualKeyboardState(bottomSheetEnabled);\n\n const [{ initialStyle, setSheetEl, setSheetScrollEl, setBackdropEl }, bottomSheetEventHandlers] =\n useBottomSheet(bottomSheetEnabled, {\n blocked: keyboardOpened,\n snapPoint,\n sheetCSSProperty: '--vkui_internal_ModalPageDocument--snapPoint',\n backdropCSSProperty: '--vkui_internal--modal-overlay--opacity',\n onSnapPointChange,\n onDismiss() {\n onClose('swipe-down');\n },\n });\n const documentStyle = keyboardOpened\n ? {\n '--vkui_internal_ModalPageDocument--safeAreaInsetBottom': '0px',\n ...initialStyle,\n }\n : initialStyle;\n const handleSheetRef = useExternRef<HTMLDivElement>(setSheetEl, ref);\n const handleSheetScrollRef = useExternRef<HTMLDivElement>(setSheetScrollEl, getModalContentRef);\n\n const disableContentPanningGestureProp = disableContentPanningGesture\n ? BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE\n : undefined;\n const [desktopMaxWidthClassName, desktopMaxWidthStyle] = resolveDesktopMaxWidth(\n isDesktop ? desktopMaxWidth : 's',\n );\n\n const modalOverlay = (\n <ModalOverlay\n getRootRef={setBackdropEl}\n data-testid={modalOverlayTestId}\n visible={open}\n onClick={\n closable\n ? function handleBackdropClick(event) {\n onClose('click-overlay', event);\n }\n : undefined\n }\n />\n );\n const closeButton =\n hideCloseButton || !isDesktop ? null : (\n <ModalDismissButton\n data-testid={modalDismissButtonTestId}\n onClick={\n closable\n ? function handleDismissButtonClick(event) {\n onClose('click-close-button', event);\n }\n : undefined\n }\n />\n );\n const handleEscKeyDown = useCallback(\n (event: KeyboardEvent<HTMLElement>) => {\n if (closable && pressedKey(event) === Keys.ESCAPE) {\n onClose('escape-key');\n }\n },\n [closable, onClose],\n );\n\n useScrollLock(!hidden);\n\n return (\n <ModalOutlet hidden={hidden} isDesktop={isDesktop} onKeyDown={handleEscKeyDown}>\n {modalOverlay}\n <FocusTrap\n {...restProps}\n autoFocus={!noFocusToDialog}\n role=\"dialog\"\n aria-modal=\"true\"\n disabled={!opened || hidden || disableFocusTrap}\n className={classNames(\n className,\n styles.host,\n isDesktop ? styles.hostDesktop : styles.hostMobile,\n !isDesktop &&\n (hasCustomPanelHeaderAfter\n ? styles.hostMobileSafeAreaInsetTopWithCustomOffset\n : styles.hostMobileSafeAreaInsetTop),\n desktopMaxWidthClassName,\n sizeX === 'regular' && 'vkuiInternalModalPage--sizeX-regular',\n )}\n style={mergeStyle(mergeStyle(desktopMaxWidthStyle, getHeightCSSVariable(height)), style)}\n >\n <div\n {...bottomSheetEventHandlers}\n ref={handleSheetRef}\n role=\"document\"\n style={documentStyle}\n className={classNames(\n styles.document,\n isDesktop ? styles.documentDesktop : styles.documentMobile,\n transitionStateClassNames[transitionState],\n )}\n onTransitionEnd={onTransitionEnd}\n >\n <div className={classNames(styles.children, isDesktop && styles.childrenDesktop)}>\n {hasReactNode(header) && header}\n <ModalPageContent\n getRootRef={handleSheetScrollRef}\n data-testid={modalContentTestId}\n {...disableContentPanningGestureProp}\n >\n {children}\n </ModalPageContent>\n {hasReactNode(footer) && footer}\n </div>\n {closeButton}\n </div>\n </FocusTrap>\n </ModalOutlet>\n );\n};\n\nconst desktopMaxWidthClassNames = {\n s: styles['hostDesktopMaxWidthS'],\n m: styles['hostDesktopMaxWidthM'],\n l: styles['hostDesktopMaxWidthL'],\n};\n\nfunction resolveDesktopMaxWidth(\n desktopMaxWidth: ModalPageInternalProps['size'] = 's',\n): [string | undefined, CSSCustomProperties | undefined] {\n if (typeof desktopMaxWidth === 'string') {\n return [desktopMaxWidthClassNames[desktopMaxWidth], undefined];\n }\n\n return [\n undefined,\n typeof desktopMaxWidth === 'number'\n ? { '--vkui_internal_ModalPage--desktopMaxWidth': `${desktopMaxWidth}px` }\n : undefined,\n ];\n}\n\nfunction getHeightCSSVariable(height?: number | string): CSSCustomProperties | undefined {\n return height !== undefined\n ? {\n '--vkui_internal_ModalPage--userHeight':\n typeof height === 'number' ? `${height}px` : height,\n }\n : undefined;\n}\n"],"names":["useCallback","classNames","hasReactNode","noop","mergeStyle","useAdaptivityWithJSMediaQueries","useExternRef","useVirtualKeyboardState","Keys","pressedKey","useCSSTransition","BLOCK_SHEET_BEHAVIOR_DATA_ATTRIBUTE","useBottomSheet","useScrollLock","useConfigProvider","FocusTrap","ModalDismissButton","ModalOutlet","ModalOverlay","ModalOverlayDefault","ModalPageContent","styles","transitionStateClassNames","appear","appearing","enter","entering","exiting","exited","ModalPageInternal","open","header","footer","size","desktopMaxWidth","height","children","className","style","snapPoint","onSnapPointChange","getModalContentRef","modalOverlayTestId","modalContentTestId","modalDismissButtonTestId","noFocusToDialog","hideCloseButton","preventClose","disableContentPanningGesture","onOpen","onOpened","onClose","onClosed","disableFocusTrap","restProps","hasCustomPanelHeaderAfter","transitionState","ref","onTransitionEnd","enableAppear","onEnter","onEntered","onExited","opened","hidden","closable","sizeX","isDesktop","bottomSheetEnabled","keyboardOpened","initialStyle","setSheetEl","setSheetScrollEl","setBackdropEl","bottomSheetEventHandlers","blocked","sheetCSSProperty","backdropCSSProperty","onDismiss","documentStyle","handleSheetRef","handleSheetScrollRef","disableContentPanningGestureProp","undefined","desktopMaxWidthClassName","desktopMaxWidthStyle","resolveDesktopMaxWidth","modalOverlay","getRootRef","data-testid","visible","onClick","handleBackdropClick","event","closeButton","handleDismissButtonClick","handleEscKeyDown","ESCAPE","onKeyDown","autoFocus","role","aria-modal","disabled","host","hostDesktop","hostMobile","hostMobileSafeAreaInsetTopWithCustomOffset","hostMobileSafeAreaInsetTop","getHeightCSSVariable","div","document","documentDesktop","documentMobile","childrenDesktop","desktopMaxWidthClassNames","s","m","l"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/ModalPage/types.ts"],"sourcesContent":["import type { CSSProperties, ReactNode, Ref, UIEvent } from 'react';\nimport type { NavIdProps } from '../../lib/getNavId';\nimport type { HTMLAttributesWithRootRef } from '../../types';\n\nexport type ModalPageCloseReason =\n | 'click-overlay'\n | 'click-close-button'\n | 'escape-key'\n | 'swipe-down';\n\ntype OmittedStyleAttribute = {\n style?: Omit<CSSProperties, 'height' | 'maxWidth' | 'maxHeight'>;\n};\n\nexport interface ModalPageProps\n extends NavIdProps,\n Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'id' | 'style'>,\n OmittedStyleAttribute {\n /**\n * Состояние видимости.\n *\n * @default false\n */\n open?: boolean;\n /**\n * Сохранять ли компонент в DOM при `open={false}`.\n *\n * @default false\n */\n keepMounted?: boolean;\n /**\n * Шапка модальной страницы, `<ModalPageHeader />`\n */\n header?: ReactNode;\n /**\n * Подвал модальной страницы, `<ModalPageFooter />`\n */\n footer?: ReactNode;\n /**\n * Задаёт контенту максимальную ширину на десктопе.\n */\n size?: 's' | 'm' | 'l' | number;\n /**\n * Задаёт модальному окну фиксированную высоту.\n * Можно передать числовое значение в пикселях, а можно строкой, в том числе и в процентах \"50%\".\n * В мобильной версии 'settlingHeight' будет считаться относительно заданного height.\n */\n height?: string | number;\n /**\n * Процент, на который изначально будет открыта модальная страница.\n *\n * > ⚠️ Следует использовать следующие значения: `25`, `50`, `75`, `100`.\n * > При передаче `< 25` значение приведётся к `25`, при передаче `> 75` значение приведётся к `75`.\n *\n * Игнорируется при включении `dynamicContentHeight`.\n */\n settlingHeight?: number;\n /**\n * Если высота контента в модальной странице может поменяться, нужно установить это свойство.\n */\n dynamicContentHeight?: boolean;\n /**\n * Отключает фокус на интерактивный элемент после открытия модалки.\n */\n noFocusToDialog?: boolean;\n /**\n * Скрывает кнопку закрытия (актуально для iOS, т.к. можно отрисовать кнопку закрытия внутри модалки)\n */\n hideCloseButton?: boolean;\n /**\n * `data-testid` для содержимого модального окна.\n */\n modalContentTestId?: string;\n /**\n * Возвращает DOM-элемент содержимого модального окна.\n */\n getModalContentRef?: Ref<HTMLDivElement>;\n /**\n * `data-testid` для оверлея.\n */\n modalOverlayTestId?: string;\n /**\n * `data-testid` для кнопки закрытия.\n */\n modalDismissButtonTestId?: string;\n /**\n * Позволяет отключить возможность закрытия модальной страницы (смахивание, клавиша `ESC`, клик по подложке)\n *\n * ⚠️ ВНИМАНИЕ: использование этой опции негативно сказывается на пользовательском опыте\n */\n preventClose?: boolean;\n /**\n * Отключает раскрытие и закрытие панели в мобильном виде.\n */\n disableContentPanningGesture?: boolean;\n /**\n * Будет вызвано при начале открытия модалки.\n */\n onOpen?: VoidFunction;\n /**\n * Будет вызвано при окончательном открытии модалки.\n */\n onOpened?: VoidFunction;\n /**\n * Будет вызвано при начале закрытия модалки.\n */\n onClose?: (reason: ModalPageCloseReason, event?: UIEvent<HTMLElement>) => void;\n /**\n * Будет вызвано при окончательном закрытии модалки.\n */\n onClosed?: VoidFunction;\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/ModalPage/types.ts"],"sourcesContent":["import type { CSSProperties, ReactNode, Ref, UIEvent } from 'react';\nimport { type UseFocusTrapProps } from '../../hooks/useFocusTrap';\nimport type { NavIdProps } from '../../lib/getNavId';\nimport type { HTMLAttributesWithRootRef } from '../../types';\n\nexport type ModalPageCloseReason =\n | 'click-overlay'\n | 'click-close-button'\n | 'escape-key'\n | 'swipe-down';\n\ntype OmittedStyleAttribute = {\n style?: Omit<CSSProperties, 'height' | 'maxWidth' | 'maxHeight'>;\n};\n\nexport interface ModalPageProps\n extends NavIdProps,\n Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'id' | 'style'>,\n OmittedStyleAttribute {\n /**\n * Состояние видимости.\n *\n * @default false\n */\n open?: boolean;\n /**\n * Сохранять ли компонент в DOM при `open={false}`.\n *\n * @default false\n */\n keepMounted?: boolean;\n /**\n * Шапка модальной страницы, `<ModalPageHeader />`\n */\n header?: ReactNode;\n /**\n * Подвал модальной страницы, `<ModalPageFooter />`\n */\n footer?: ReactNode;\n /**\n * Задаёт контенту максимальную ширину на десктопе.\n */\n size?: 's' | 'm' | 'l' | number;\n /**\n * Задаёт модальному окну фиксированную высоту.\n * Можно передать числовое значение в пикселях, а можно строкой, в том числе и в процентах \"50%\".\n * В мобильной версии 'settlingHeight' будет считаться относительно заданного height.\n */\n height?: string | number;\n /**\n * Процент, на который изначально будет открыта модальная страница.\n *\n * > ⚠️ Следует использовать следующие значения: `25`, `50`, `75`, `100`.\n * > При передаче `< 25` значение приведётся к `25`, при передаче `> 75` значение приведётся к `75`.\n *\n * Игнорируется при включении `dynamicContentHeight`.\n */\n settlingHeight?: number;\n /**\n * Если высота контента в модальной странице может поменяться, нужно установить это свойство.\n */\n dynamicContentHeight?: boolean;\n /**\n * Отключает фокус на интерактивный элемент после открытия модалки.\n */\n noFocusToDialog?: boolean;\n /**\n * Скрывает кнопку закрытия (актуально для iOS, т.к. можно отрисовать кнопку закрытия внутри модалки)\n */\n hideCloseButton?: boolean;\n /**\n * `data-testid` для содержимого модального окна.\n */\n modalContentTestId?: string;\n /**\n * Возвращает DOM-элемент содержимого модального окна.\n */\n getModalContentRef?: Ref<HTMLDivElement>;\n /**\n * `data-testid` для оверлея.\n */\n modalOverlayTestId?: string;\n /**\n * `data-testid` для кнопки закрытия.\n */\n modalDismissButtonTestId?: string;\n /**\n * Позволяет отключить возможность закрытия модальной страницы (смахивание, клавиша `ESC`, клик по подложке)\n *\n * ⚠️ ВНИМАНИЕ: использование этой опции негативно сказывается на пользовательском опыте\n */\n preventClose?: boolean;\n /**\n * Отключает раскрытие и закрытие панели в мобильном виде.\n */\n disableContentPanningGesture?: boolean;\n /**\n * Будет вызвано при начале открытия модалки.\n */\n onOpen?: VoidFunction;\n /**\n * Будет вызвано при окончательном открытии модалки.\n */\n onOpened?: VoidFunction;\n /**\n * Будет вызвано при начале закрытия модалки.\n */\n onClose?: (reason: ModalPageCloseReason, event?: UIEvent<HTMLElement>) => void;\n /**\n * Будет вызвано при окончательном закрытии модалки.\n */\n onClosed?: VoidFunction;\n /**\n * Позволяет отключить захват фокуса.\n *\n * Нужно использовать, когда поверх одной модалки открывается другая, чтобы два `FocusTrap` не конфликтовали\n */\n disableFocusTrap?: UseFocusTrapProps['disabled'];\n}\n"],"names":[],"mappings":"AAeA,WAuGC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { hasReactNode } from "@vkontakte/vkjs";
|
|
5
5
|
import { mergeStyle } from "../../helpers/mergeStyle.js";
|
|
@@ -10,6 +10,7 @@ import { autoUpdateFloatingElement, convertFloatingDataToReactCSSProperties, use
|
|
|
10
10
|
import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect.js";
|
|
11
11
|
import { warnOnce } from "../../lib/warnOnce.js";
|
|
12
12
|
import { DEFAULT_ARROW_HEIGHT, DEFAULT_ARROW_PADDING } from "../FloatingArrow/DefaultIcon.js";
|
|
13
|
+
import { FocusTrap } from "../FocusTrap/FocusTrap.js";
|
|
13
14
|
import { useNavTransition } from "../NavTransitionContext/NavTransitionContext.js";
|
|
14
15
|
import { TOOLTIP_MAX_WIDTH, TooltipBase } from "../TooltipBase/TooltipBase.js";
|
|
15
16
|
import { onboardingTooltipContainerAttr } from "./OnboardingTooltipContainer.js";
|
|
@@ -17,7 +18,7 @@ import styles from "./OnboardingTooltip.module.css";
|
|
|
17
18
|
const warn = warnOnce('OnboardingTooltip');
|
|
18
19
|
/**
|
|
19
20
|
* @see https://vkcom.github.io/VKUI/#/Tooltip
|
|
20
|
-
*/ export const OnboardingTooltip = ({ id: idProp, children, shown: shownProp = true, arrowPadding = DEFAULT_ARROW_PADDING, arrowHeight = DEFAULT_ARROW_HEIGHT, offsetByMainAxis = 0, offsetByCrossAxis = 0, arrowOffset = 0, isStaticArrowOffset = false, onClose, placement: placementProp = 'bottom-start', maxWidth = TOOLTIP_MAX_WIDTH, style: styleProp, getRootRef, disableArrow = false, onPlacementChange, disableFlipMiddleware = false, ...restProps })=>{
|
|
21
|
+
*/ export const OnboardingTooltip = ({ 'id': idProp, children, 'shown': shownProp = true, arrowPadding = DEFAULT_ARROW_PADDING, arrowHeight = DEFAULT_ARROW_HEIGHT, offsetByMainAxis = 0, offsetByCrossAxis = 0, arrowOffset = 0, isStaticArrowOffset = false, onClose, 'placement': placementProp = 'bottom-start', maxWidth = TOOLTIP_MAX_WIDTH, 'style': styleProp, getRootRef, disableArrow = false, onPlacementChange, disableFlipMiddleware = false, overlayLabel = 'Закрыть', title, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, restoreFocus, ...restProps })=>{
|
|
21
22
|
const generatedId = React.useId();
|
|
22
23
|
const tooltipId = idProp || generatedId;
|
|
23
24
|
const { entering } = useNavTransition();
|
|
@@ -46,14 +47,31 @@ const warn = warnOnce('OnboardingTooltip');
|
|
|
46
47
|
'aria-describedby': shown ? tooltipId : undefined
|
|
47
48
|
});
|
|
48
49
|
usePlacementChangeCallback(placementProp, resolvedPlacement, onPlacementChange);
|
|
50
|
+
const titleId = React.useId();
|
|
51
|
+
if (process.env.NODE_ENV === 'development' && !title && !ariaLabel && !ariaLabelledBy) {
|
|
52
|
+
warn('Если "title" не используется, то необходимо задать либо "aria-label", либо "aria-labelledby" (см. правило axe aria-dialog-name)');
|
|
53
|
+
}
|
|
49
54
|
let tooltip = null;
|
|
50
55
|
if (shown) {
|
|
51
56
|
const floatingStyle = convertFloatingDataToReactCSSProperties(positionStrategy, floatingDataX, floatingDataY);
|
|
52
|
-
tooltip = createPortal(/*#__PURE__*/ _jsxs(
|
|
57
|
+
tooltip = createPortal(/*#__PURE__*/ _jsxs(FocusTrap, {
|
|
58
|
+
role: "dialog",
|
|
59
|
+
"aria-modal": "true",
|
|
60
|
+
"aria-label": ariaLabel,
|
|
61
|
+
"aria-labelledby": title ? titleId : ariaLabel ? undefined : ariaLabelledBy,
|
|
62
|
+
onClose: onClose,
|
|
63
|
+
restoreFocus: restoreFocus,
|
|
53
64
|
children: [
|
|
65
|
+
/*#__PURE__*/ _jsx("button", {
|
|
66
|
+
"aria-label": overlayLabel,
|
|
67
|
+
className: styles.overlay,
|
|
68
|
+
onClickCapture: onClose
|
|
69
|
+
}),
|
|
54
70
|
/*#__PURE__*/ _jsx(TooltipBase, {
|
|
55
71
|
...restProps,
|
|
56
72
|
id: tooltipId,
|
|
73
|
+
title: title,
|
|
74
|
+
titleId: title ? titleId : undefined,
|
|
57
75
|
getRootRef: tooltipRef,
|
|
58
76
|
style: mergeStyle(floatingStyle, styleProp),
|
|
59
77
|
maxWidth: maxWidth,
|
|
@@ -64,10 +82,6 @@ const warn = warnOnce('OnboardingTooltip');
|
|
|
64
82
|
placement: resolvedPlacement,
|
|
65
83
|
getRootRef: setArrowRef
|
|
66
84
|
}
|
|
67
|
-
}),
|
|
68
|
-
/*#__PURE__*/ _jsx("div", {
|
|
69
|
-
className: styles.overlay,
|
|
70
|
-
onClickCapture: onClose
|
|
71
85
|
})
|
|
72
86
|
]
|
|
73
87
|
}), tooltipContainer);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/OnboardingTooltip/OnboardingTooltip.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { hasReactNode } from '@vkontakte/vkjs';\nimport { mergeStyle } from '../../helpers/mergeStyle';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { usePatchChildren } from '../../hooks/usePatchChildren';\nimport { createPortal } from '../../lib/createPortal';\nimport {\n autoUpdateFloatingElement,\n convertFloatingDataToReactCSSProperties,\n type FloatingComponentProps,\n useFloating,\n useFloatingMiddlewaresBootstrap,\n usePlacementChangeCallback,\n} from '../../lib/floating';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport { warnOnce } from '../../lib/warnOnce';\nimport { DEFAULT_ARROW_HEIGHT, DEFAULT_ARROW_PADDING } from '../FloatingArrow/DefaultIcon';\nimport type { FloatingArrowProps } from '../FloatingArrow/FloatingArrow';\nimport { useNavTransition } from '../NavTransitionContext/NavTransitionContext';\nimport { TOOLTIP_MAX_WIDTH, TooltipBase, type TooltipBaseProps } from '../TooltipBase/TooltipBase';\nimport { onboardingTooltipContainerAttr } from './OnboardingTooltipContainer';\nimport styles from './OnboardingTooltip.module.css';\n\nconst warn = warnOnce('OnboardingTooltip');\n\ntype AllowedFloatingComponentProps = Pick<\n FloatingComponentProps,\n | 'arrowHeight'\n | 'arrowPadding'\n | 'arrowRef'\n | 'placement'\n | 'offsetByMainAxis'\n | 'offsetByCrossAxis'\n | 'shown'\n | 'children'\n | 'onPlacementChange'\n | 'disableFlipMiddleware'\n>;\n\ntype AllowedTooltipBaseProps = Omit<\n TooltipBaseProps,\n 'arrowProps' | 'closeIconLabel' | 'onCloseIconClick'\n>;\n\ntype AllowedFloatingArrowProps = {\n /**\n * Сдвиг стрелки относительно текущих координат.\n */\n arrowOffset?: FloatingArrowProps['offset'];\n /**\n * Включает абсолютное смещение по `arrowOffset`.\n */\n isStaticArrowOffset?: FloatingArrowProps['isStaticOffset'];\n};\n\nexport interface OnboardingTooltipProps\n extends AllowedFloatingComponentProps,\n AllowedTooltipBaseProps,\n AllowedFloatingArrowProps {\n /**\n * Скрывает стрелку, указывающую на якорный элемент.\n */\n disableArrow?: boolean;\n /**\n * Callback, который вызывается при клике по любому месту в пределах экрана.\n */\n onClose?: (this: void) => void;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Tooltip\n */\nexport const OnboardingTooltip = ({\n id: idProp,\n children,\n shown: shownProp = true,\n arrowPadding = DEFAULT_ARROW_PADDING,\n arrowHeight = DEFAULT_ARROW_HEIGHT,\n offsetByMainAxis = 0,\n offsetByCrossAxis = 0,\n arrowOffset = 0,\n isStaticArrowOffset = false,\n onClose,\n placement: placementProp = 'bottom-start',\n maxWidth = TOOLTIP_MAX_WIDTH,\n style: styleProp,\n getRootRef,\n disableArrow = false,\n onPlacementChange,\n disableFlipMiddleware = false,\n ...restProps\n}: OnboardingTooltipProps): React.ReactNode => {\n const generatedId = React.useId();\n const tooltipId = idProp || generatedId;\n const { entering } = useNavTransition();\n\n const [arrowRef, setArrowRef] = React.useState<HTMLDivElement | null>(null);\n const [tooltipContainer, setTooltipContainer] = React.useState<HTMLElement | null>(null);\n const [positionStrategy, setPositionStrategy] = React.useState<'fixed' | 'absolute'>('absolute');\n const shown = shownProp && tooltipContainer && !entering;\n\n const { middlewares, strictPlacement } = useFloatingMiddlewaresBootstrap({\n placement: placementProp,\n offsetByMainAxis,\n offsetByCrossAxis,\n arrowRef,\n arrow: !disableArrow,\n arrowHeight,\n arrowPadding,\n disableFlipMiddleware,\n });\n const {\n x: floatingDataX,\n y: floatingDataY,\n refs,\n placement: resolvedPlacement,\n middlewareData: { arrow: arrowCoords },\n } = useFloating({\n strategy: positionStrategy,\n placement: strictPlacement,\n middleware: middlewares,\n whileElementsMounted: autoUpdateFloatingElement,\n });\n const tooltipRef = useExternRef<HTMLDivElement>(getRootRef, refs.setFloating);\n const [childRef, child] = usePatchChildren(children, {\n 'aria-describedby': shown ? tooltipId : undefined,\n });\n\n usePlacementChangeCallback(placementProp, resolvedPlacement, onPlacementChange);\n\n let tooltip: React.ReactPortal | null = null;\n if (shown) {\n const floatingStyle = convertFloatingDataToReactCSSProperties(\n positionStrategy,\n floatingDataX,\n floatingDataY,\n );\n\n tooltip = createPortal(\n <>\n <TooltipBase\n {...restProps}\n id={tooltipId}\n getRootRef={tooltipRef}\n style={mergeStyle(floatingStyle, styleProp)}\n maxWidth={maxWidth}\n arrowProps={\n disableArrow\n ? undefined\n : {\n offset: arrowOffset,\n isStaticOffset: isStaticArrowOffset,\n coords: arrowCoords,\n placement: resolvedPlacement,\n getRootRef: setArrowRef,\n }\n }\n />\n <div className={styles.overlay} onClickCapture={onClose} />\n </>,\n tooltipContainer,\n );\n }\n\n useIsomorphicLayoutEffect(\n function initialize() {\n const referenceEl = childRef.current;\n if (referenceEl) {\n setTooltipContainer(\n referenceEl.closest<HTMLDivElement>(`[${onboardingTooltipContainerAttr}]`), // eslint-disable-line no-restricted-properties\n );\n setPositionStrategy(referenceEl.style.position === 'fixed' ? 'fixed' : 'absolute');\n refs.setReference(referenceEl);\n }\n },\n [childRef],\n );\n\n if (process.env.NODE_ENV === 'development') {\n const multiChildren = React.Children.count(children) > 1;\n // Empty children is a noop\n const primitiveChild = hasReactNode(children) && typeof children !== 'object';\n (multiChildren || primitiveChild) &&\n warn(\n [\n 'children должен быть одним React элементом, получено',\n multiChildren && 'несколько',\n primitiveChild && JSON.stringify(children),\n ]\n .filter(Boolean)\n .join(' '),\n 'error',\n );\n\n if (refs.reference.current && !tooltipContainer) {\n throw new Error('Use TooltipContainer for Tooltip outside Panel (see docs)');\n }\n }\n\n return (\n <React.Fragment>\n {child}\n {tooltip}\n </React.Fragment>\n );\n};\n"],"names":["React","hasReactNode","mergeStyle","useExternRef","usePatchChildren","createPortal","autoUpdateFloatingElement","convertFloatingDataToReactCSSProperties","useFloating","useFloatingMiddlewaresBootstrap","usePlacementChangeCallback","useIsomorphicLayoutEffect","warnOnce","DEFAULT_ARROW_HEIGHT","DEFAULT_ARROW_PADDING","useNavTransition","TOOLTIP_MAX_WIDTH","TooltipBase","onboardingTooltipContainerAttr","styles","warn","OnboardingTooltip","id","idProp","children","shown","shownProp","arrowPadding","arrowHeight","offsetByMainAxis","offsetByCrossAxis","arrowOffset","isStaticArrowOffset","onClose","placement","placementProp","maxWidth","style","styleProp","getRootRef","disableArrow","onPlacementChange","disableFlipMiddleware","restProps","generatedId","useId","tooltipId","entering","arrowRef","setArrowRef","useState","tooltipContainer","setTooltipContainer","positionStrategy","setPositionStrategy","middlewares","strictPlacement","arrow","x","floatingDataX","y","floatingDataY","refs","resolvedPlacement","middlewareData","arrowCoords","strategy","middleware","whileElementsMounted","tooltipRef","setFloating","childRef","child","undefined","tooltip","floatingStyle","arrowProps","offset","isStaticOffset","coords","div","className","overlay","onClickCapture","initialize","referenceEl","current","closest","position","setReference","process","env","NODE_ENV","multiChildren","Children","count","primitiveChild","JSON","stringify","filter","Boolean","join","reference","Error","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/OnboardingTooltip/OnboardingTooltip.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { hasReactNode } from '@vkontakte/vkjs';\nimport { mergeStyle } from '../../helpers/mergeStyle';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { type UseFocusTrapProps } from '../../hooks/useFocusTrap';\nimport { usePatchChildren } from '../../hooks/usePatchChildren';\nimport { createPortal } from '../../lib/createPortal';\nimport {\n autoUpdateFloatingElement,\n convertFloatingDataToReactCSSProperties,\n type FloatingComponentProps,\n useFloating,\n useFloatingMiddlewaresBootstrap,\n usePlacementChangeCallback,\n} from '../../lib/floating';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport { warnOnce } from '../../lib/warnOnce';\nimport { DEFAULT_ARROW_HEIGHT, DEFAULT_ARROW_PADDING } from '../FloatingArrow/DefaultIcon';\nimport type { FloatingArrowProps } from '../FloatingArrow/FloatingArrow';\nimport { FocusTrap } from '../FocusTrap/FocusTrap';\nimport { useNavTransition } from '../NavTransitionContext/NavTransitionContext';\nimport { TOOLTIP_MAX_WIDTH, TooltipBase, type TooltipBaseProps } from '../TooltipBase/TooltipBase';\nimport { onboardingTooltipContainerAttr } from './OnboardingTooltipContainer';\nimport styles from './OnboardingTooltip.module.css';\n\nconst warn = warnOnce('OnboardingTooltip');\n\ntype AllowedFloatingComponentProps = Pick<\n FloatingComponentProps,\n | 'arrowHeight'\n | 'arrowPadding'\n | 'arrowRef'\n | 'placement'\n | 'offsetByMainAxis'\n | 'offsetByCrossAxis'\n | 'shown'\n | 'children'\n | 'onPlacementChange'\n | 'disableFlipMiddleware'\n>;\n\ntype AllowedTooltipBaseProps = Omit<\n TooltipBaseProps,\n 'arrowProps' | 'closeIconLabel' | 'onCloseIconClick'\n>;\n\ntype AllowedFloatingArrowProps = {\n /**\n * Сдвиг стрелки относительно текущих координат.\n */\n arrowOffset?: FloatingArrowProps['offset'];\n /**\n * Включает абсолютное смещение по `arrowOffset`.\n */\n isStaticArrowOffset?: FloatingArrowProps['isStaticOffset'];\n};\n\nexport interface OnboardingTooltipProps\n extends AllowedFloatingComponentProps,\n AllowedTooltipBaseProps,\n AllowedFloatingArrowProps,\n Pick<UseFocusTrapProps, 'restoreFocus'> {\n /**\n * Скрывает стрелку, указывающую на якорный элемент.\n */\n disableArrow?: boolean;\n /**\n * Callback, который вызывается при клике по любому месту в пределах экрана.\n */\n onClose?: (this: void) => void;\n /**\n * [a11y] Метка для подложки-кнопки, для описания того, что произойдёт при клике.\n */\n overlayLabel?: string;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Tooltip\n */\nexport const OnboardingTooltip = ({\n 'id': idProp,\n children,\n 'shown': shownProp = true,\n arrowPadding = DEFAULT_ARROW_PADDING,\n arrowHeight = DEFAULT_ARROW_HEIGHT,\n offsetByMainAxis = 0,\n offsetByCrossAxis = 0,\n arrowOffset = 0,\n isStaticArrowOffset = false,\n onClose,\n 'placement': placementProp = 'bottom-start',\n maxWidth = TOOLTIP_MAX_WIDTH,\n 'style': styleProp,\n getRootRef,\n disableArrow = false,\n onPlacementChange,\n disableFlipMiddleware = false,\n overlayLabel = 'Закрыть',\n title,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n restoreFocus,\n ...restProps\n}: OnboardingTooltipProps): React.ReactNode => {\n const generatedId = React.useId();\n const tooltipId = idProp || generatedId;\n const { entering } = useNavTransition();\n\n const [arrowRef, setArrowRef] = React.useState<HTMLDivElement | null>(null);\n const [tooltipContainer, setTooltipContainer] = React.useState<HTMLElement | null>(null);\n const [positionStrategy, setPositionStrategy] = React.useState<'fixed' | 'absolute'>('absolute');\n const shown = shownProp && tooltipContainer && !entering;\n\n const { middlewares, strictPlacement } = useFloatingMiddlewaresBootstrap({\n placement: placementProp,\n offsetByMainAxis,\n offsetByCrossAxis,\n arrowRef,\n arrow: !disableArrow,\n arrowHeight,\n arrowPadding,\n disableFlipMiddleware,\n });\n const {\n x: floatingDataX,\n y: floatingDataY,\n refs,\n placement: resolvedPlacement,\n middlewareData: { arrow: arrowCoords },\n } = useFloating({\n strategy: positionStrategy,\n placement: strictPlacement,\n middleware: middlewares,\n whileElementsMounted: autoUpdateFloatingElement,\n });\n const tooltipRef = useExternRef<HTMLDivElement>(getRootRef, refs.setFloating);\n const [childRef, child] = usePatchChildren(children, {\n 'aria-describedby': shown ? tooltipId : undefined,\n });\n\n usePlacementChangeCallback(placementProp, resolvedPlacement, onPlacementChange);\n\n const titleId = React.useId();\n if (process.env.NODE_ENV === 'development' && !title && !ariaLabel && !ariaLabelledBy) {\n warn(\n 'Если \"title\" не используется, то необходимо задать либо \"aria-label\", либо \"aria-labelledby\" (см. правило axe aria-dialog-name)',\n );\n }\n\n let tooltip: React.ReactPortal | null = null;\n if (shown) {\n const floatingStyle = convertFloatingDataToReactCSSProperties(\n positionStrategy,\n floatingDataX,\n floatingDataY,\n );\n\n tooltip = createPortal(\n <FocusTrap\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n aria-labelledby={title ? titleId : ariaLabel ? undefined : ariaLabelledBy}\n onClose={onClose}\n restoreFocus={restoreFocus}\n >\n <button aria-label={overlayLabel} className={styles.overlay} onClickCapture={onClose} />\n <TooltipBase\n {...restProps}\n id={tooltipId}\n title={title}\n titleId={title ? titleId : undefined}\n getRootRef={tooltipRef}\n style={mergeStyle(floatingStyle, styleProp)}\n maxWidth={maxWidth}\n arrowProps={\n disableArrow\n ? undefined\n : {\n offset: arrowOffset,\n isStaticOffset: isStaticArrowOffset,\n coords: arrowCoords,\n placement: resolvedPlacement,\n getRootRef: setArrowRef,\n }\n }\n />\n </FocusTrap>,\n tooltipContainer,\n );\n }\n\n useIsomorphicLayoutEffect(\n function initialize() {\n const referenceEl = childRef.current;\n if (referenceEl) {\n setTooltipContainer(\n referenceEl.closest<HTMLDivElement>(`[${onboardingTooltipContainerAttr}]`), // eslint-disable-line no-restricted-properties\n );\n setPositionStrategy(referenceEl.style.position === 'fixed' ? 'fixed' : 'absolute');\n refs.setReference(referenceEl);\n }\n },\n [childRef],\n );\n\n if (process.env.NODE_ENV === 'development') {\n const multiChildren = React.Children.count(children) > 1;\n // Empty children is a noop\n const primitiveChild = hasReactNode(children) && typeof children !== 'object';\n (multiChildren || primitiveChild) &&\n warn(\n [\n 'children должен быть одним React элементом, получено',\n multiChildren && 'несколько',\n primitiveChild && JSON.stringify(children),\n ]\n .filter(Boolean)\n .join(' '),\n 'error',\n );\n\n if (refs.reference.current && !tooltipContainer) {\n throw new Error('Use TooltipContainer for Tooltip outside Panel (see docs)');\n }\n }\n\n return (\n <React.Fragment>\n {child}\n {tooltip}\n </React.Fragment>\n );\n};\n"],"names":["React","hasReactNode","mergeStyle","useExternRef","usePatchChildren","createPortal","autoUpdateFloatingElement","convertFloatingDataToReactCSSProperties","useFloating","useFloatingMiddlewaresBootstrap","usePlacementChangeCallback","useIsomorphicLayoutEffect","warnOnce","DEFAULT_ARROW_HEIGHT","DEFAULT_ARROW_PADDING","FocusTrap","useNavTransition","TOOLTIP_MAX_WIDTH","TooltipBase","onboardingTooltipContainerAttr","styles","warn","OnboardingTooltip","idProp","children","shownProp","arrowPadding","arrowHeight","offsetByMainAxis","offsetByCrossAxis","arrowOffset","isStaticArrowOffset","onClose","placementProp","maxWidth","styleProp","getRootRef","disableArrow","onPlacementChange","disableFlipMiddleware","overlayLabel","title","ariaLabel","ariaLabelledBy","restoreFocus","restProps","generatedId","useId","tooltipId","entering","arrowRef","setArrowRef","useState","tooltipContainer","setTooltipContainer","positionStrategy","setPositionStrategy","shown","middlewares","strictPlacement","placement","arrow","x","floatingDataX","y","floatingDataY","refs","resolvedPlacement","middlewareData","arrowCoords","strategy","middleware","whileElementsMounted","tooltipRef","setFloating","childRef","child","undefined","titleId","process","env","NODE_ENV","tooltip","floatingStyle","role","aria-modal","aria-label","aria-labelledby","button","className","overlay","onClickCapture","id","style","arrowProps","offset","isStaticOffset","coords","initialize","referenceEl","current","closest","position","setReference","multiChildren","Children","count","primitiveChild","JSON","stringify","filter","Boolean","join","reference","Error","Fragment"],"mappings":"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"}
|
|
@@ -4,4 +4,19 @@
|
|
|
4
4
|
inset-block-start: 0;
|
|
5
5
|
inline-size: 100%;
|
|
6
6
|
block-size: 100%;
|
|
7
|
+
padding: 0;
|
|
8
|
+
margin: 0;
|
|
9
|
+
-webkit-appearance: none;
|
|
10
|
+
-moz-appearance: none;
|
|
11
|
+
appearance: none;
|
|
12
|
+
-webkit-touch-callout: none;
|
|
13
|
+
-webkit-user-drag: none;
|
|
14
|
+
cursor: default;
|
|
15
|
+
background: transparent;
|
|
16
|
+
border: 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.overlay:focus,
|
|
20
|
+
.overlay:focus-visible {
|
|
21
|
+
outline: none;
|
|
7
22
|
}
|
|
@@ -9,11 +9,10 @@ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
|
|
|
9
9
|
import { PaginationNavigationButton } from "./PaginationNavigationButton/PaginationNavigationButton.js";
|
|
10
10
|
import { PaginationPageButton } from "./PaginationPage/PaginationPageButton.js";
|
|
11
11
|
import { PaginationPageEllipsis } from "./PaginationPage/PaginationPageEllipsis.js";
|
|
12
|
-
import { getPageLabelDefault } from "./utils.js";
|
|
13
12
|
import styles from "./Pagination.module.css";
|
|
14
13
|
/**
|
|
15
14
|
* @see https://vkcom.github.io/VKUI/#/Pagination
|
|
16
|
-
*/ export const Pagination = ({ currentPage = 1, siblingCount = 1, boundaryCount = 1, totalPages = 1, disabled, prevButtonCaption = 'Назад', nextButtonCaption = 'Вперёд', navigationButtonsStyle = 'icon', getPageLabel
|
|
15
|
+
*/ export const Pagination = ({ currentPage = 1, siblingCount = 1, boundaryCount = 1, totalPages = 1, disabled, prevButtonCaption = 'Назад', nextButtonCaption = 'Вперёд', navigationButtonsStyle = 'icon', getPageLabel, navigationLabel = 'Страницы', navigationLabelComponent = 'h2', prevButtonLabel = 'Перейти на предыдущую страницу', nextButtonLabel = 'Перейти на следующую страницу', onChange, renderPageButton, pageButtonTestId, prevButtonTestId, nextButtonTestId, renderNavigationButton, ...resetProps })=>{
|
|
17
16
|
const pages = usePagination({
|
|
18
17
|
currentPage,
|
|
19
18
|
totalPages,
|
|
@@ -84,12 +83,15 @@ import styles from "./Pagination.module.css";
|
|
|
84
83
|
sizeY,
|
|
85
84
|
pageButtonTestId
|
|
86
85
|
]);
|
|
86
|
+
const navigationLabelId = React.useId();
|
|
87
87
|
return /*#__PURE__*/ _jsxs(RootComponent, {
|
|
88
88
|
Component: "nav",
|
|
89
89
|
role: "navigation",
|
|
90
|
+
"aria-labelledby": navigationLabelId,
|
|
90
91
|
...resetProps,
|
|
91
92
|
children: [
|
|
92
93
|
/*#__PURE__*/ _jsx(VisuallyHidden, {
|
|
94
|
+
id: navigationLabelId,
|
|
93
95
|
Component: navigationLabelComponent,
|
|
94
96
|
children: navigationLabel
|
|
95
97
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Icon24ChevronCompactLeft, Icon24ChevronCompactRight } from '@vkontakte/icons';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { type PaginationPageType, usePagination } from '../../hooks/usePagination';\nimport type { HasComponent, HTMLAttributesWithRootRef } from '../../types';\nimport { RootComponent } from '../RootComponent/RootComponent';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport {\n type CustomPaginationNavigationButton,\n PaginationNavigationButton,\n type PaginationNavigationButtonProps,\n} from './PaginationNavigationButton/PaginationNavigationButton';\nimport {\n type CustomPaginationPageButtonProps,\n PaginationPageButton,\n} from './PaginationPage/PaginationPageButton';\nimport { PaginationPageEllipsis } from './PaginationPage/PaginationPageEllipsis';\nimport { getPageLabelDefault } from './utils';\nimport styles from './Pagination.module.css';\n\nexport interface PaginationProps extends Omit<HTMLAttributesWithRootRef<HTMLElement>, 'onChange'> {\n /**\n * Текущая страница.\n */\n currentPage?: number;\n /**\n * Кол-во всегда видимых страниц по краям текущей страницы.\n */\n siblingCount?: number;\n /**\n * Кол-во всегда видимых страниц в начале и в конце.\n */\n boundaryCount?: number;\n /**\n * Общее кол-во страниц.\n */\n totalPages?: number;\n /**\n * Блокировка всех кнопок.\n */\n disabled?: boolean;\n /**\n * Декоративный текст для кнопки навигации назад.\n *\n * > Note: Экранные дикторы будут использовать `prevButtonLabel`.\n */\n prevButtonCaption?: string;\n /**\n * Декоративный текст для кнопки навигации вперёд.\n *\n * > Note: Экранные дикторы будут использовать `nextButtonLabel`.\n */\n nextButtonCaption?: string;\n /**\n * Задаёт стиль отображения кнопок навигации.\n *\n * - `icon` – показывать только иконку;\n * - `caption` – показывать только подпись;\n * - `both` – показывать и иконку, и подпись.\n */\n navigationButtonsStyle?: PaginationNavigationButtonProps['style'];\n /**\n * [a11y] Метка для обозначения блока навигации.\n */\n navigationLabel?: string;\n navigationLabelComponent?: HasComponent['Component'];\n /**\n * [a11y] Метка для кнопки навигации назад.\n */\n prevButtonLabel?: string;\n /**\n * [a11y] Метка для кнопки навигации вперёд.\n */\n nextButtonLabel?: string;\n /**\n * [a11y] Функция для переопределения и/или локализации метки кнопки страницы.\n */\n getPageLabel?: (isCurrent: boolean) => string;\n onChange?: (page: number, event: React.MouseEvent<HTMLElement>) => void;\n /**\n * Функция для кастомного рендера кнопок страниц.\n *\n * > Note: `CustomPaginationPageButtonProps` наследует API [Tappable](https://vkcom.github.io/VKUI/#/Tappable).\n */\n renderPageButton?: (props: CustomPaginationPageButtonProps) => React.ReactNode;\n /**\n Функция для кастомного рендера кнопок навигации `prev` и `next`.\n *\n * > Note: `CustomPaginationNavigationButton` наследует API [Button](https://vkcom.github.io/VKUI/#/Button).\n */\n renderNavigationButton?: (props: CustomPaginationNavigationButton) => React.ReactNode;\n /**\n * Передает атрибут `data-testid` для кнопок страниц\n */\n pageButtonTestId?: (day: PaginationPageType, active: boolean) => string;\n /**\n * Передает атрибут `data-testid` для кнопки `prev`\n */\n prevButtonTestId?: string;\n /**\n * Передает атрибут `data-testid` для кнопки `next`\n */\n nextButtonTestId?: string;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Pagination\n */\nexport const Pagination = ({\n currentPage = 1,\n siblingCount = 1,\n boundaryCount = 1,\n totalPages = 1,\n disabled,\n prevButtonCaption = 'Назад',\n nextButtonCaption = 'Вперёд',\n navigationButtonsStyle = 'icon',\n getPageLabel = getPageLabelDefault,\n navigationLabel = 'Навигация по страницам',\n navigationLabelComponent = 'h2',\n prevButtonLabel = 'Перейти на предыдущую страницу',\n nextButtonLabel = 'Перейти на следующую страницу',\n onChange,\n renderPageButton,\n pageButtonTestId,\n prevButtonTestId,\n nextButtonTestId,\n renderNavigationButton,\n ...resetProps\n}: PaginationProps): React.ReactNode => {\n const pages = usePagination({\n currentPage,\n totalPages,\n siblingCount,\n boundaryCount,\n });\n const isFirstPage = currentPage === 1;\n const isLastPage = currentPage === totalPages;\n const prevPage = isFirstPage ? undefined : currentPage - 1;\n const nextPage = isLastPage ? undefined : currentPage + 1;\n\n const handlePrevClick = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n if (onChange && prevPage !== undefined) {\n onChange(prevPage, event);\n }\n },\n [prevPage, onChange],\n );\n\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n const page: string = event.currentTarget.dataset.page || '1';\n onChange?.(Number(page), event);\n },\n [onChange],\n );\n\n const handleNextClick = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n if (onChange && nextPage !== undefined) {\n onChange(nextPage, event);\n }\n },\n [nextPage, onChange],\n );\n\n const { sizeY } = useAdaptivity();\n\n const renderPages = React.useCallback(\n (page: PaginationPageType) => {\n const isCurrent = page === currentPage;\n const dataTestId = pageButtonTestId?.(page, isCurrent);\n\n switch (page) {\n case 'start-ellipsis':\n case 'end-ellipsis':\n return (\n <li key={page}>\n <PaginationPageEllipsis disabled={disabled} data-testid={dataTestId} />\n </li>\n );\n default: {\n return (\n <li key={page}>\n <PaginationPageButton\n getPageLabel={getPageLabel}\n isCurrent={isCurrent}\n onClick={handleClick}\n disabled={disabled}\n sizeY={sizeY}\n renderPageButton={renderPageButton}\n data-testid={dataTestId}\n >\n {page}\n </PaginationPageButton>\n </li>\n );\n }\n }\n },\n [currentPage, disabled, getPageLabel, handleClick, renderPageButton, sizeY, pageButtonTestId],\n );\n\n return (\n <RootComponent Component=\"nav\" role=\"navigation\" {...resetProps}>\n <VisuallyHidden Component={navigationLabelComponent}>{navigationLabel}</VisuallyHidden>\n <ul className={styles.list}>\n <li className={styles.prevButtonContainer}>\n <PaginationNavigationButton\n type=\"prev\"\n style={navigationButtonsStyle}\n caption={prevButtonCaption}\n Icon={Icon24ChevronCompactLeft}\n a11yLabel={prevButtonLabel}\n disabled={isFirstPage || disabled}\n onClick={handlePrevClick}\n data-page={prevPage}\n data-testid={prevButtonTestId}\n renderNavigationButton={renderNavigationButton}\n />\n </li>\n {pages.map(renderPages)}\n <li className={styles.nextButtonContainer}>\n <PaginationNavigationButton\n type=\"next\"\n style={navigationButtonsStyle}\n caption={nextButtonCaption}\n Icon={Icon24ChevronCompactRight}\n a11yLabel={nextButtonLabel}\n disabled={isLastPage || disabled}\n onClick={handleNextClick}\n data-page={nextPage}\n data-testid={nextButtonTestId}\n renderNavigationButton={renderNavigationButton}\n />\n </li>\n </ul>\n </RootComponent>\n );\n};\n"],"names":["React","Icon24ChevronCompactLeft","Icon24ChevronCompactRight","useAdaptivity","usePagination","RootComponent","VisuallyHidden","PaginationNavigationButton","PaginationPageButton","PaginationPageEllipsis","getPageLabelDefault","styles","Pagination","currentPage","siblingCount","boundaryCount","totalPages","disabled","prevButtonCaption","nextButtonCaption","navigationButtonsStyle","getPageLabel","navigationLabel","navigationLabelComponent","prevButtonLabel","nextButtonLabel","onChange","renderPageButton","pageButtonTestId","prevButtonTestId","nextButtonTestId","renderNavigationButton","resetProps","pages","isFirstPage","isLastPage","prevPage","undefined","nextPage","handlePrevClick","useCallback","event","handleClick","page","currentTarget","dataset","Number","handleNextClick","sizeY","renderPages","isCurrent","dataTestId","li","data-testid","onClick","Component","role","ul","className","list","prevButtonContainer","type","style","caption","Icon","a11yLabel","data-page","map","nextButtonContainer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Icon24ChevronCompactLeft, Icon24ChevronCompactRight } from '@vkontakte/icons';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { type PaginationPageType, usePagination } from '../../hooks/usePagination';\nimport type { HasComponent, HTMLAttributesWithRootRef } from '../../types';\nimport { RootComponent } from '../RootComponent/RootComponent';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport {\n type CustomPaginationNavigationButton,\n PaginationNavigationButton,\n type PaginationNavigationButtonProps,\n} from './PaginationNavigationButton/PaginationNavigationButton';\nimport {\n type CustomPaginationPageButtonProps,\n PaginationPageButton,\n} from './PaginationPage/PaginationPageButton';\nimport { PaginationPageEllipsis } from './PaginationPage/PaginationPageEllipsis';\nimport styles from './Pagination.module.css';\n\nexport interface PaginationProps extends Omit<HTMLAttributesWithRootRef<HTMLElement>, 'onChange'> {\n /**\n * Текущая страница.\n */\n currentPage?: number;\n /**\n * Кол-во всегда видимых страниц по краям текущей страницы.\n */\n siblingCount?: number;\n /**\n * Кол-во всегда видимых страниц в начале и в конце.\n */\n boundaryCount?: number;\n /**\n * Общее кол-во страниц.\n */\n totalPages?: number;\n /**\n * Блокировка всех кнопок.\n */\n disabled?: boolean;\n /**\n * Декоративный текст для кнопки навигации назад.\n *\n * > Note: Экранные дикторы будут использовать `prevButtonLabel`.\n */\n prevButtonCaption?: string;\n /**\n * Декоративный текст для кнопки навигации вперёд.\n *\n * > Note: Экранные дикторы будут использовать `nextButtonLabel`.\n */\n nextButtonCaption?: string;\n /**\n * Задаёт стиль отображения кнопок навигации.\n *\n * - `icon` – показывать только иконку;\n * - `caption` – показывать только подпись;\n * - `both` – показывать и иконку, и подпись.\n */\n navigationButtonsStyle?: PaginationNavigationButtonProps['style'];\n /**\n * [a11y] Метка для обозначения блока навигации.\n */\n navigationLabel?: string;\n navigationLabelComponent?: HasComponent['Component'];\n /**\n * [a11y] Метка для кнопки навигации назад.\n */\n prevButtonLabel?: string;\n /**\n * [a11y] Метка для кнопки навигации вперёд.\n */\n nextButtonLabel?: string;\n /**\n * [a11y] Функция для переопределения и/или локализации метки кнопки страницы.\n *\n * > Note: По возможности лучше не использовать,\n * так как компонент и так проставляет номер страницы в разметку,\n * что достаточно для пользователей скринридеров.\n * Дополнительная информация скорее будет избыточна,\n * так как будет зачитываться для каждой кнопки при перемещении по списку.\n */\n getPageLabel?: (isCurrent: boolean) => string;\n onChange?: (page: number, event: React.MouseEvent<HTMLElement>) => void;\n /**\n * Функция для кастомного рендера кнопок страниц.\n *\n * > Note: `CustomPaginationPageButtonProps` наследует API [Tappable](https://vkcom.github.io/VKUI/#/Tappable).\n */\n renderPageButton?: (props: CustomPaginationPageButtonProps) => React.ReactNode;\n /**\n Функция для кастомного рендера кнопок навигации `prev` и `next`.\n *\n * > Note: `CustomPaginationNavigationButton` наследует API [Button](https://vkcom.github.io/VKUI/#/Button).\n */\n renderNavigationButton?: (props: CustomPaginationNavigationButton) => React.ReactNode;\n /**\n * Передает атрибут `data-testid` для кнопок страниц\n */\n pageButtonTestId?: (day: PaginationPageType, active: boolean) => string;\n /**\n * Передает атрибут `data-testid` для кнопки `prev`\n */\n prevButtonTestId?: string;\n /**\n * Передает атрибут `data-testid` для кнопки `next`\n */\n nextButtonTestId?: string;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Pagination\n */\nexport const Pagination = ({\n currentPage = 1,\n siblingCount = 1,\n boundaryCount = 1,\n totalPages = 1,\n disabled,\n prevButtonCaption = 'Назад',\n nextButtonCaption = 'Вперёд',\n navigationButtonsStyle = 'icon',\n getPageLabel,\n navigationLabel = 'Страницы',\n navigationLabelComponent = 'h2',\n prevButtonLabel = 'Перейти на предыдущую страницу',\n nextButtonLabel = 'Перейти на следующую страницу',\n onChange,\n renderPageButton,\n pageButtonTestId,\n prevButtonTestId,\n nextButtonTestId,\n renderNavigationButton,\n ...resetProps\n}: PaginationProps): React.ReactNode => {\n const pages = usePagination({\n currentPage,\n totalPages,\n siblingCount,\n boundaryCount,\n });\n const isFirstPage = currentPage === 1;\n const isLastPage = currentPage === totalPages;\n const prevPage = isFirstPage ? undefined : currentPage - 1;\n const nextPage = isLastPage ? undefined : currentPage + 1;\n\n const handlePrevClick = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n if (onChange && prevPage !== undefined) {\n onChange(prevPage, event);\n }\n },\n [prevPage, onChange],\n );\n\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n const page: string = event.currentTarget.dataset.page || '1';\n onChange?.(Number(page), event);\n },\n [onChange],\n );\n\n const handleNextClick = React.useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n if (onChange && nextPage !== undefined) {\n onChange(nextPage, event);\n }\n },\n [nextPage, onChange],\n );\n\n const { sizeY } = useAdaptivity();\n\n const renderPages = React.useCallback(\n (page: PaginationPageType) => {\n const isCurrent = page === currentPage;\n const dataTestId = pageButtonTestId?.(page, isCurrent);\n\n switch (page) {\n case 'start-ellipsis':\n case 'end-ellipsis':\n return (\n <li key={page}>\n <PaginationPageEllipsis disabled={disabled} data-testid={dataTestId} />\n </li>\n );\n default: {\n return (\n <li key={page}>\n <PaginationPageButton\n getPageLabel={getPageLabel}\n isCurrent={isCurrent}\n onClick={handleClick}\n disabled={disabled}\n sizeY={sizeY}\n renderPageButton={renderPageButton}\n data-testid={dataTestId}\n >\n {page}\n </PaginationPageButton>\n </li>\n );\n }\n }\n },\n [currentPage, disabled, getPageLabel, handleClick, renderPageButton, sizeY, pageButtonTestId],\n );\n\n const navigationLabelId = React.useId();\n\n return (\n <RootComponent\n Component=\"nav\"\n role=\"navigation\"\n aria-labelledby={navigationLabelId}\n {...resetProps}\n >\n <VisuallyHidden id={navigationLabelId} Component={navigationLabelComponent}>\n {navigationLabel}\n </VisuallyHidden>\n <ul className={styles.list}>\n <li className={styles.prevButtonContainer}>\n <PaginationNavigationButton\n type=\"prev\"\n style={navigationButtonsStyle}\n caption={prevButtonCaption}\n Icon={Icon24ChevronCompactLeft}\n a11yLabel={prevButtonLabel}\n disabled={isFirstPage || disabled}\n onClick={handlePrevClick}\n data-page={prevPage}\n data-testid={prevButtonTestId}\n renderNavigationButton={renderNavigationButton}\n />\n </li>\n {pages.map(renderPages)}\n <li className={styles.nextButtonContainer}>\n <PaginationNavigationButton\n type=\"next\"\n style={navigationButtonsStyle}\n caption={nextButtonCaption}\n Icon={Icon24ChevronCompactRight}\n a11yLabel={nextButtonLabel}\n disabled={isLastPage || disabled}\n onClick={handleNextClick}\n data-page={nextPage}\n data-testid={nextButtonTestId}\n renderNavigationButton={renderNavigationButton}\n />\n </li>\n </ul>\n </RootComponent>\n );\n};\n"],"names":["React","Icon24ChevronCompactLeft","Icon24ChevronCompactRight","useAdaptivity","usePagination","RootComponent","VisuallyHidden","PaginationNavigationButton","PaginationPageButton","PaginationPageEllipsis","styles","Pagination","currentPage","siblingCount","boundaryCount","totalPages","disabled","prevButtonCaption","nextButtonCaption","navigationButtonsStyle","getPageLabel","navigationLabel","navigationLabelComponent","prevButtonLabel","nextButtonLabel","onChange","renderPageButton","pageButtonTestId","prevButtonTestId","nextButtonTestId","renderNavigationButton","resetProps","pages","isFirstPage","isLastPage","prevPage","undefined","nextPage","handlePrevClick","useCallback","event","handleClick","page","currentTarget","dataset","Number","handleNextClick","sizeY","renderPages","isCurrent","dataTestId","li","data-testid","onClick","navigationLabelId","useId","Component","role","aria-labelledby","id","ul","className","list","prevButtonContainer","type","style","caption","Icon","a11yLabel","data-page","map","nextButtonContainer"],"mappings":"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"}
|
|
@@ -4,16 +4,16 @@ import { classNames } from "@vkontakte/vkjs";
|
|
|
4
4
|
import { Tappable } from "../../Tappable/Tappable.js";
|
|
5
5
|
import { Text } from "../../Typography/Text/Text.js";
|
|
6
6
|
import { VisuallyHidden } from "../../VisuallyHidden/VisuallyHidden.js";
|
|
7
|
-
import { getPageLabelDefault } from "../utils.js";
|
|
8
7
|
import { getPaginationPageClassNames } from "./usePaginationPageClasses.js";
|
|
9
8
|
import styles from "./PaginationPage.module.css";
|
|
10
9
|
const getTappablePropsFromPaginationPage = (opts)=>{
|
|
11
|
-
const { isCurrent = false, getPageLabel
|
|
10
|
+
const { isCurrent = false, getPageLabel, children, className, disabled, sizeY, ...restProps } = opts;
|
|
12
11
|
const pageClassNames = getPaginationPageClassNames({
|
|
13
12
|
isCurrent,
|
|
14
13
|
disabled,
|
|
15
14
|
sizeY
|
|
16
15
|
});
|
|
16
|
+
const pageLabel = getPageLabel?.(isCurrent);
|
|
17
17
|
return {
|
|
18
18
|
'className': classNames(pageClassNames, className),
|
|
19
19
|
'activeMode': styles.stateActive,
|
|
@@ -24,9 +24,9 @@ const getTappablePropsFromPaginationPage = (opts)=>{
|
|
|
24
24
|
'children': /*#__PURE__*/ _jsxs(Text, {
|
|
25
25
|
normalize: false,
|
|
26
26
|
children: [
|
|
27
|
-
/*#__PURE__*/ _jsxs(VisuallyHidden, {
|
|
27
|
+
pageLabel && /*#__PURE__*/ _jsxs(VisuallyHidden, {
|
|
28
28
|
children: [
|
|
29
|
-
|
|
29
|
+
pageLabel,
|
|
30
30
|
" "
|
|
31
31
|
]
|
|
32
32
|
}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/components/Pagination/PaginationPage/PaginationPageButton.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { type SizeTypeValues } from '../../../lib/adaptivity';\nimport { Tappable, type TappableProps } from '../../Tappable/Tappable';\nimport { Text } from '../../Typography/Text/Text';\nimport { VisuallyHidden } from '../../VisuallyHidden/VisuallyHidden';\nimport type { PaginationProps } from '../Pagination';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/components/Pagination/PaginationPage/PaginationPageButton.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { type SizeTypeValues } from '../../../lib/adaptivity';\nimport { Tappable, type TappableProps } from '../../Tappable/Tappable';\nimport { Text } from '../../Typography/Text/Text';\nimport { VisuallyHidden } from '../../VisuallyHidden/VisuallyHidden';\nimport type { PaginationProps } from '../Pagination';\nimport { getPaginationPageClassNames } from './usePaginationPageClasses';\nimport styles from './PaginationPage.module.css';\n\nexport interface PaginationPageButtonOpts\n extends Pick<React.ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'disabled' | 'className'>,\n Pick<PaginationProps, 'getPageLabel'> {\n isCurrent?: boolean;\n sizeY?: SizeTypeValues;\n children: number;\n}\n\nexport interface PaginationPageButtonProps extends PaginationPageButtonOpts {\n renderPageButton?: (props: CustomPaginationPageButtonProps) => React.ReactNode;\n}\n\nconst getTappablePropsFromPaginationPage = (\n opts: PaginationPageButtonOpts,\n): TappableProps & { 'data-page': number } => {\n const {\n isCurrent = false,\n getPageLabel,\n children,\n className,\n disabled,\n sizeY,\n ...restProps\n } = opts;\n\n const pageClassNames = getPaginationPageClassNames({\n isCurrent,\n disabled,\n sizeY,\n });\n\n const pageLabel = getPageLabel?.(isCurrent);\n return {\n 'className': classNames(pageClassNames, className),\n 'activeMode': styles.stateActive,\n 'hoverMode': styles.stateHover,\n 'focusVisibleMode': 'outside',\n 'aria-current': isCurrent ? true : undefined,\n 'disabled': disabled,\n 'children': (\n <Text normalize={false}>\n {pageLabel && <VisuallyHidden>{pageLabel} </VisuallyHidden>}\n {children}\n </Text>\n ),\n 'data-page': children,\n ...restProps,\n };\n};\n\nexport type CustomPaginationPageButtonProps = ReturnType<typeof getTappablePropsFromPaginationPage>;\n\nexport const PaginationPageButton = ({\n renderPageButton,\n ...restProps\n}: PaginationPageButtonProps): React.ReactNode => {\n const tappableProps = getTappablePropsFromPaginationPage(restProps);\n\n if (typeof renderPageButton === 'function') {\n return renderPageButton(tappableProps);\n }\n\n return <Tappable {...tappableProps} />;\n};\n"],"names":["React","classNames","Tappable","Text","VisuallyHidden","getPaginationPageClassNames","styles","getTappablePropsFromPaginationPage","opts","isCurrent","getPageLabel","children","className","disabled","sizeY","restProps","pageClassNames","pageLabel","stateActive","stateHover","undefined","normalize","PaginationPageButton","renderPageButton","tappableProps"],"mappings":";AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,UAAU,QAAQ,kBAAkB;AAE7C,SAASC,QAAQ,QAA4B,6BAA0B;AACvE,SAASC,IAAI,QAAQ,gCAA6B;AAClD,SAASC,cAAc,QAAQ,yCAAsC;AAErE,SAASC,2BAA2B,QAAQ,gCAA6B;AACzE,OAAOC,YAAY,8BAA8B;AAcjD,MAAMC,qCAAqC,CACzCC;IAEA,MAAM,EACJC,YAAY,KAAK,EACjBC,YAAY,EACZC,QAAQ,EACRC,SAAS,EACTC,QAAQ,EACRC,KAAK,EACL,GAAGC,WACJ,GAAGP;IAEJ,MAAMQ,iBAAiBX,4BAA4B;QACjDI;QACAI;QACAC;IACF;IAEA,MAAMG,YAAYP,eAAeD;IACjC,OAAO;QACL,aAAaR,WAAWe,gBAAgBJ;QACxC,cAAcN,OAAOY,WAAW;QAChC,aAAaZ,OAAOa,UAAU;QAC9B,oBAAoB;QACpB,gBAAgBV,YAAY,OAAOW;QACnC,YAAYP;QACZ,0BACE,MAACV;YAAKkB,WAAW;;gBACdJ,2BAAa,MAACb;;wBAAgBa;wBAAU;;;gBACxCN;;;QAGL,aAAaA;QACb,GAAGI,SAAS;IACd;AACF;AAIA,OAAO,MAAMO,uBAAuB,CAAC,EACnCC,gBAAgB,EAChB,GAAGR,WACuB;IAC1B,MAAMS,gBAAgBjB,mCAAmCQ;IAEzD,IAAI,OAAOQ,qBAAqB,YAAY;QAC1C,OAAOA,iBAAiBC;IAC1B;IAEA,qBAAO,KAACtB;QAAU,GAAGsB,aAAa;;AACpC,EAAE"}
|
|
@@ -92,7 +92,7 @@ import styles from "./Removable.module.css";
|
|
|
92
92
|
};
|
|
93
93
|
/**
|
|
94
94
|
* @see https://vkcom.github.io/VKUI/#/Removable
|
|
95
|
-
*/ export const Removable = ({ children, onRemove, removePlaceholder = 'Удалить', align = 'center', indent = false, toggleButtonTestId, removeButtonTestId, disabled, ...restProps })=>{
|
|
95
|
+
*/ export const Removable = ({ children, onRemove, removePlaceholder = 'Удалить', align = 'center', indent = false, toggleButtonTestId, removeButtonTestId, disabled, noPadding, ...restProps })=>{
|
|
96
96
|
const platform = usePlatform();
|
|
97
97
|
const onRemoveClick = (e)=>{
|
|
98
98
|
e.preventDefault();
|
|
@@ -104,7 +104,7 @@ import styles from "./Removable.module.css";
|
|
|
104
104
|
baseClassName: classNames(platform === 'ios' && styles.ios, align === 'start' && styles.alignStart, indent && styles.indent),
|
|
105
105
|
children: [
|
|
106
106
|
platform !== 'ios' && /*#__PURE__*/ _jsxs("div", {
|
|
107
|
-
className: classNames(styles.content, 'vkuiInternalRemovable__content'),
|
|
107
|
+
className: classNames(styles.content, !noPadding && styles.withPadding, 'vkuiInternalRemovable__content'),
|
|
108
108
|
children: [
|
|
109
109
|
typeof children === 'function' ? children({
|
|
110
110
|
isRemoving: false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Removable/Removable.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Icon24Cancel } from '@vkontakte/icons';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useGlobalEventListener } from '../../hooks/useGlobalEventListener';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { getTextFromChildren } from '../../lib/children';\nimport { useDOM } from '../../lib/dom';\nimport type { HTMLAttributesWithRootRef } from '../../types';\nimport { IconButton } from '../IconButton/IconButton';\nimport { RootComponent } from '../RootComponent/RootComponent';\nimport { Tappable } from '../Tappable/Tappable';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport styles from './Removable.module.css';\n\nexport interface RemovableProps {\n /**\n * Текст кнопки удаления ячейки. Визуально скрыт везде, кроме iOS. На iOS появляется в выезжающей кнопке для удаления ячейки.\n */\n removePlaceholder?: React.ReactNode;\n /**\n * Коллбэк срабатывает при клике на контрол удаления.\n */\n onRemove?: (e: React.MouseEvent, rootEl?: HTMLElement | null) => void;\n /**\n * Передает атрибут `data-testid` для кнопки, которая активирует кнопку удаления (iOS only)\n */\n toggleButtonTestId?: string;\n /**\n * Передает атрибут `data-testid` для кнопки удаления\n */\n removeButtonTestId?: string;\n /**\n * Ячейка превращается в неактивную\n */\n disabled?: boolean;\n}\n\ninterface RemovableIosOwnProps extends RemovableProps {\n removePlaceholderString?: string;\n children?: React.ReactNode | ((renderProps: RemovableIosRenderProps) => React.ReactNode);\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/RemovableIos\n */\nconst RemovableIos = ({\n onRemove,\n removePlaceholder,\n removePlaceholderString,\n children: childrenProp,\n toggleButtonTestId,\n removeButtonTestId,\n disabled,\n}: RemovableIosOwnProps) => {\n const { window } = useDOM();\n\n const removeButtonRef = React.useRef<HTMLElement>(null);\n const disabledRef = React.useRef(true);\n const [removeOffset, updateRemoveOffset] = React.useState(0);\n\n useGlobalEventListener(\n window,\n 'click',\n () => {\n if (removeOffset > 0) {\n updateRemoveOffset(0);\n }\n },\n { capture: true },\n );\n\n const onRemoveTransitionEnd = () => {\n if (removeOffset > 0) {\n removeButtonRef?.current?.focus();\n } else {\n disabledRef.current = true;\n }\n };\n\n const onRemoveActivateClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!removeButtonRef.current) {\n return;\n }\n const { offsetWidth } = removeButtonRef.current;\n disabledRef.current = false;\n updateRemoveOffset(offsetWidth);\n };\n\n return (\n <div\n className={classNames(styles.content, 'vkuiInternalRemovable__content')}\n style={{ transform: `translateX(-${removeOffset ?? 0}px)` }}\n onTransitionEnd={onRemoveTransitionEnd}\n >\n <IconButton\n hasActive={false}\n hasHover={false}\n className={classNames(styles.action, styles.toggle, 'vkuiInternalRemovable__action')}\n onClick={onRemoveActivateClick}\n disabled={removeOffset > 0 || disabled}\n data-testid={toggleButtonTestId}\n >\n <VisuallyHidden>{removePlaceholderString}</VisuallyHidden>\n <i className={styles.toggleIn} role=\"presentation\" />\n </IconButton>\n {typeof childrenProp === 'function'\n ? childrenProp({ isRemoving: removeOffset > 0 })\n : childrenProp}\n\n <span className={styles.offset} aria-hidden />\n\n <Tappable\n Component=\"button\"\n hasActive={false}\n hasHover={false}\n disabled={disabledRef.current}\n getRootRef={removeButtonRef}\n className={styles.remove}\n onClick={onRemove}\n data-testid={removeButtonTestId}\n >\n <span className={styles.removeIn}>{removePlaceholder}</span>\n </Tappable>\n </div>\n );\n};\n\ninterface RemovableIosRenderProps {\n /**\n * Показывает состояние Removable на платформе iOS при клике на иконку удаления.\n * Для имитации поведения на iOS при клике на иконку удаления самого удаление не происходит,\n * контент сдвигается влево и справа выезжает настоящая кнопка \"Удалить\".\n * Когда контент сдвинут `isRemoving = true`.\n */\n isRemoving: boolean;\n}\n\ninterface RemovableOwnProps\n extends Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'children'>,\n RemovableProps {\n /**\n * Расположение кнопки удаления.\n */\n align?: 'start' | 'center';\n /**\n * Скрывает кнопку, но оставляет отступ.\n * @since 5.4.0\n */\n indent?: boolean;\n children?: React.ReactNode | ((renderProps: RemovableIosRenderProps) => React.ReactNode);\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Removable\n */\nexport const Removable = ({\n children,\n onRemove,\n removePlaceholder = 'Удалить',\n align = 'center',\n indent = false,\n toggleButtonTestId,\n removeButtonTestId,\n disabled,\n ...restProps\n}: RemovableOwnProps): React.ReactNode => {\n const platform = usePlatform();\n\n const onRemoveClick = (e: React.MouseEvent) => {\n e.preventDefault();\n onRemove?.(e);\n };\n\n const removePlaceholderString: string = getTextFromChildren(removePlaceholder);\n\n return (\n <RootComponent\n {...restProps}\n baseClassName={classNames(\n platform === 'ios' && styles.ios,\n align === 'start' && styles.alignStart,\n indent && styles.indent,\n )}\n >\n {platform !== 'ios' && (\n <div className={classNames(styles.content, 'vkuiInternalRemovable__content')}>\n {typeof children === 'function' ? children({ isRemoving: false }) : children}\n\n <IconButton\n activeMode=\"opacity\"\n hoverMode=\"opacity\"\n className={classNames(styles.action, 'vkuiInternalRemovable__action')}\n onClick={onRemoveClick}\n label={removePlaceholderString}\n data-testid={removeButtonTestId}\n disabled={disabled}\n >\n <Icon24Cancel role=\"presentation\" />\n </IconButton>\n\n <span className={styles.offset} aria-hidden />\n </div>\n )}\n\n {platform === 'ios' && (\n <RemovableIos\n onRemove={onRemoveClick}\n removePlaceholder={removePlaceholder}\n removePlaceholderString={removePlaceholderString}\n toggleButtonTestId={toggleButtonTestId}\n removeButtonTestId={removeButtonTestId}\n disabled={disabled}\n >\n {children}\n </RemovableIos>\n )}\n </RootComponent>\n );\n};\n"],"names":["React","Icon24Cancel","classNames","useGlobalEventListener","usePlatform","getTextFromChildren","useDOM","IconButton","RootComponent","Tappable","VisuallyHidden","styles","RemovableIos","onRemove","removePlaceholder","removePlaceholderString","children","childrenProp","toggleButtonTestId","removeButtonTestId","disabled","window","removeButtonRef","useRef","disabledRef","removeOffset","updateRemoveOffset","useState","capture","onRemoveTransitionEnd","current","focus","onRemoveActivateClick","e","stopPropagation","offsetWidth","div","className","content","style","transform","onTransitionEnd","hasActive","hasHover","action","toggle","onClick","data-testid","i","toggleIn","role","isRemoving","span","offset","aria-hidden","Component","getRootRef","remove","removeIn","Removable","align","indent","restProps","platform","onRemoveClick","preventDefault","baseClassName","ios","alignStart","activeMode","hoverMode","label"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Removable/Removable.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Icon24Cancel } from '@vkontakte/icons';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useGlobalEventListener } from '../../hooks/useGlobalEventListener';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { getTextFromChildren } from '../../lib/children';\nimport { useDOM } from '../../lib/dom';\nimport type { HTMLAttributesWithRootRef } from '../../types';\nimport { IconButton } from '../IconButton/IconButton';\nimport { RootComponent } from '../RootComponent/RootComponent';\nimport { Tappable } from '../Tappable/Tappable';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport styles from './Removable.module.css';\n\nexport interface RemovableProps {\n /**\n * Текст кнопки удаления ячейки. Визуально скрыт везде, кроме iOS. На iOS появляется в выезжающей кнопке для удаления ячейки.\n */\n removePlaceholder?: React.ReactNode;\n /**\n * Коллбэк срабатывает при клике на контрол удаления.\n */\n onRemove?: (e: React.MouseEvent, rootEl?: HTMLElement | null) => void;\n /**\n * Передает атрибут `data-testid` для кнопки, которая активирует кнопку удаления (iOS only)\n */\n toggleButtonTestId?: string;\n /**\n * Передает атрибут `data-testid` для кнопки удаления\n */\n removeButtonTestId?: string;\n /**\n * Ячейка превращается в неактивную\n */\n disabled?: boolean;\n}\n\ninterface RemovableIosOwnProps extends RemovableProps {\n removePlaceholderString?: string;\n children?: React.ReactNode | ((renderProps: RemovableIosRenderProps) => React.ReactNode);\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/RemovableIos\n */\nconst RemovableIos = ({\n onRemove,\n removePlaceholder,\n removePlaceholderString,\n children: childrenProp,\n toggleButtonTestId,\n removeButtonTestId,\n disabled,\n}: RemovableIosOwnProps) => {\n const { window } = useDOM();\n\n const removeButtonRef = React.useRef<HTMLElement>(null);\n const disabledRef = React.useRef(true);\n const [removeOffset, updateRemoveOffset] = React.useState(0);\n\n useGlobalEventListener(\n window,\n 'click',\n () => {\n if (removeOffset > 0) {\n updateRemoveOffset(0);\n }\n },\n { capture: true },\n );\n\n const onRemoveTransitionEnd = () => {\n if (removeOffset > 0) {\n removeButtonRef?.current?.focus();\n } else {\n disabledRef.current = true;\n }\n };\n\n const onRemoveActivateClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n if (!removeButtonRef.current) {\n return;\n }\n const { offsetWidth } = removeButtonRef.current;\n disabledRef.current = false;\n updateRemoveOffset(offsetWidth);\n };\n\n return (\n <div\n className={classNames(styles.content, 'vkuiInternalRemovable__content')}\n style={{ transform: `translateX(-${removeOffset ?? 0}px)` }}\n onTransitionEnd={onRemoveTransitionEnd}\n >\n <IconButton\n hasActive={false}\n hasHover={false}\n className={classNames(styles.action, styles.toggle, 'vkuiInternalRemovable__action')}\n onClick={onRemoveActivateClick}\n disabled={removeOffset > 0 || disabled}\n data-testid={toggleButtonTestId}\n >\n <VisuallyHidden>{removePlaceholderString}</VisuallyHidden>\n <i className={styles.toggleIn} role=\"presentation\" />\n </IconButton>\n {typeof childrenProp === 'function'\n ? childrenProp({ isRemoving: removeOffset > 0 })\n : childrenProp}\n\n <span className={styles.offset} aria-hidden />\n\n <Tappable\n Component=\"button\"\n hasActive={false}\n hasHover={false}\n disabled={disabledRef.current}\n getRootRef={removeButtonRef}\n className={styles.remove}\n onClick={onRemove}\n data-testid={removeButtonTestId}\n >\n <span className={styles.removeIn}>{removePlaceholder}</span>\n </Tappable>\n </div>\n );\n};\n\ninterface RemovableIosRenderProps {\n /**\n * Показывает состояние Removable на платформе iOS при клике на иконку удаления.\n * Для имитации поведения на iOS при клике на иконку удаления самого удаление не происходит,\n * контент сдвигается влево и справа выезжает настоящая кнопка \"Удалить\".\n * Когда контент сдвинут `isRemoving = true`.\n */\n isRemoving: boolean;\n}\n\ninterface RemovableOwnProps\n extends Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'children'>,\n RemovableProps {\n /**\n * Расположение кнопки удаления.\n */\n align?: 'start' | 'center';\n /**\n * Скрывает кнопку, но оставляет отступ.\n * @since 5.4.0\n */\n indent?: boolean;\n /**\n * Убирает базовые отступы для базовой платформы\n */\n noPadding?: boolean;\n children?: React.ReactNode | ((renderProps: RemovableIosRenderProps) => React.ReactNode);\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Removable\n */\nexport const Removable = ({\n children,\n onRemove,\n removePlaceholder = 'Удалить',\n align = 'center',\n indent = false,\n toggleButtonTestId,\n removeButtonTestId,\n disabled,\n noPadding,\n ...restProps\n}: RemovableOwnProps): React.ReactNode => {\n const platform = usePlatform();\n\n const onRemoveClick = (e: React.MouseEvent) => {\n e.preventDefault();\n onRemove?.(e);\n };\n\n const removePlaceholderString: string = getTextFromChildren(removePlaceholder);\n\n return (\n <RootComponent\n {...restProps}\n baseClassName={classNames(\n platform === 'ios' && styles.ios,\n align === 'start' && styles.alignStart,\n indent && styles.indent,\n )}\n >\n {platform !== 'ios' && (\n <div\n className={classNames(\n styles.content,\n !noPadding && styles.withPadding,\n 'vkuiInternalRemovable__content',\n )}\n >\n {typeof children === 'function' ? children({ isRemoving: false }) : children}\n\n <IconButton\n activeMode=\"opacity\"\n hoverMode=\"opacity\"\n className={classNames(styles.action, 'vkuiInternalRemovable__action')}\n onClick={onRemoveClick}\n label={removePlaceholderString}\n data-testid={removeButtonTestId}\n disabled={disabled}\n >\n <Icon24Cancel role=\"presentation\" />\n </IconButton>\n\n <span className={styles.offset} aria-hidden />\n </div>\n )}\n\n {platform === 'ios' && (\n <RemovableIos\n onRemove={onRemoveClick}\n removePlaceholder={removePlaceholder}\n removePlaceholderString={removePlaceholderString}\n toggleButtonTestId={toggleButtonTestId}\n removeButtonTestId={removeButtonTestId}\n disabled={disabled}\n >\n {children}\n </RemovableIos>\n )}\n </RootComponent>\n );\n};\n"],"names":["React","Icon24Cancel","classNames","useGlobalEventListener","usePlatform","getTextFromChildren","useDOM","IconButton","RootComponent","Tappable","VisuallyHidden","styles","RemovableIos","onRemove","removePlaceholder","removePlaceholderString","children","childrenProp","toggleButtonTestId","removeButtonTestId","disabled","window","removeButtonRef","useRef","disabledRef","removeOffset","updateRemoveOffset","useState","capture","onRemoveTransitionEnd","current","focus","onRemoveActivateClick","e","stopPropagation","offsetWidth","div","className","content","style","transform","onTransitionEnd","hasActive","hasHover","action","toggle","onClick","data-testid","i","toggleIn","role","isRemoving","span","offset","aria-hidden","Component","getRootRef","remove","removeIn","Removable","align","indent","noPadding","restProps","platform","onRemoveClick","preventDefault","baseClassName","ios","alignStart","withPadding","activeMode","hoverMode","label"],"mappings":"AAAA;;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,YAAY,QAAQ,mBAAmB;AAChD,SAASC,UAAU,QAAQ,kBAAkB;AAC7C,SAASC,sBAAsB,QAAQ,wCAAqC;AAC5E,SAASC,WAAW,QAAQ,6BAA0B;AACtD,SAASC,mBAAmB,QAAQ,wBAAqB;AACzD,SAASC,MAAM,QAAQ,mBAAgB;AAEvC,SAASC,UAAU,QAAQ,8BAA2B;AACtD,SAASC,aAAa,QAAQ,oCAAiC;AAC/D,SAASC,QAAQ,QAAQ,0BAAuB;AAChD,SAASC,cAAc,QAAQ,sCAAmC;AAClE,OAAOC,YAAY,yBAAyB;AA8B5C;;CAEC,GACD,MAAMC,eAAe,CAAC,EACpBC,QAAQ,EACRC,iBAAiB,EACjBC,uBAAuB,EACvBC,UAAUC,YAAY,EACtBC,kBAAkB,EAClBC,kBAAkB,EAClBC,QAAQ,EACa;IACrB,MAAM,EAAEC,MAAM,EAAE,GAAGf;IAEnB,MAAMgB,kBAAkBtB,MAAMuB,MAAM,CAAc;IAClD,MAAMC,cAAcxB,MAAMuB,MAAM,CAAC;IACjC,MAAM,CAACE,cAAcC,mBAAmB,GAAG1B,MAAM2B,QAAQ,CAAC;IAE1DxB,uBACEkB,QACA,SACA;QACE,IAAII,eAAe,GAAG;YACpBC,mBAAmB;QACrB;IACF,GACA;QAAEE,SAAS;IAAK;IAGlB,MAAMC,wBAAwB;QAC5B,IAAIJ,eAAe,GAAG;YACpBH,iBAAiBQ,SAASC;QAC5B,OAAO;YACLP,YAAYM,OAAO,GAAG;QACxB;IACF;IAEA,MAAME,wBAAwB,CAACC;QAC7BA,EAAEC,eAAe;QACjB,IAAI,CAACZ,gBAAgBQ,OAAO,EAAE;YAC5B;QACF;QACA,MAAM,EAAEK,WAAW,EAAE,GAAGb,gBAAgBQ,OAAO;QAC/CN,YAAYM,OAAO,GAAG;QACtBJ,mBAAmBS;IACrB;IAEA,qBACE,MAACC;QACCC,WAAWnC,WAAWS,OAAO2B,OAAO,EAAE;QACtCC,OAAO;YAAEC,WAAW,CAAC,YAAY,EAAEf,gBAAgB,EAAE,GAAG,CAAC;QAAC;QAC1DgB,iBAAiBZ;;0BAEjB,MAACtB;gBACCmC,WAAW;gBACXC,UAAU;gBACVN,WAAWnC,WAAWS,OAAOiC,MAAM,EAAEjC,OAAOkC,MAAM,EAAE;gBACpDC,SAASd;gBACTZ,UAAUK,eAAe,KAAKL;gBAC9B2B,eAAa7B;;kCAEb,KAACR;kCAAgBK;;kCACjB,KAACiC;wBAAEX,WAAW1B,OAAOsC,QAAQ;wBAAEC,MAAK;;;;YAErC,OAAOjC,iBAAiB,aACrBA,aAAa;gBAAEkC,YAAY1B,eAAe;YAAE,KAC5CR;0BAEJ,KAACmC;gBAAKf,WAAW1B,OAAO0C,MAAM;gBAAEC,aAAW;;0BAE3C,KAAC7C;gBACC8C,WAAU;gBACVb,WAAW;gBACXC,UAAU;gBACVvB,UAAUI,YAAYM,OAAO;gBAC7B0B,YAAYlC;gBACZe,WAAW1B,OAAO8C,MAAM;gBACxBX,SAASjC;gBACTkC,eAAa5B;0BAEb,cAAA,KAACiC;oBAAKf,WAAW1B,OAAO+C,QAAQ;8BAAG5C;;;;;AAI3C;AA+BA;;CAEC,GACD,OAAO,MAAM6C,YAAY,CAAC,EACxB3C,QAAQ,EACRH,QAAQ,EACRC,oBAAoB,SAAS,EAC7B8C,QAAQ,QAAQ,EAChBC,SAAS,KAAK,EACd3C,kBAAkB,EAClBC,kBAAkB,EAClBC,QAAQ,EACR0C,SAAS,EACT,GAAGC,WACe;IAClB,MAAMC,WAAW5D;IAEjB,MAAM6D,gBAAgB,CAAChC;QACrBA,EAAEiC,cAAc;QAChBrD,WAAWoB;IACb;IAEA,MAAMlB,0BAAkCV,oBAAoBS;IAE5D,qBACE,MAACN;QACE,GAAGuD,SAAS;QACbI,eAAejE,WACb8D,aAAa,SAASrD,OAAOyD,GAAG,EAChCR,UAAU,WAAWjD,OAAO0D,UAAU,EACtCR,UAAUlD,OAAOkD,MAAM;;YAGxBG,aAAa,uBACZ,MAAC5B;gBACCC,WAAWnC,WACTS,OAAO2B,OAAO,EACd,CAACwB,aAAanD,OAAO2D,WAAW,EAChC;;oBAGD,OAAOtD,aAAa,aAAaA,SAAS;wBAAEmC,YAAY;oBAAM,KAAKnC;kCAEpE,KAACT;wBACCgE,YAAW;wBACXC,WAAU;wBACVnC,WAAWnC,WAAWS,OAAOiC,MAAM,EAAE;wBACrCE,SAASmB;wBACTQ,OAAO1D;wBACPgC,eAAa5B;wBACbC,UAAUA;kCAEV,cAAA,KAACnB;4BAAaiD,MAAK;;;kCAGrB,KAACE;wBAAKf,WAAW1B,OAAO0C,MAAM;wBAAEC,aAAW;;;;YAI9CU,aAAa,uBACZ,KAACpD;gBACCC,UAAUoD;gBACVnD,mBAAmBA;gBACnBC,yBAAyBA;gBACzBG,oBAAoBA;gBACpBC,oBAAoBA;gBACpBC,UAAUA;0BAETJ;;;;AAKX,EAAE"}
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
/* stylelint-disable-next-line selector-pseudo-class-disallowed-list */
|
|
35
35
|
|
|
36
36
|
.before > :global(.vkuiIcon) {
|
|
37
|
+
box-sizing: content-box;
|
|
37
38
|
-webkit-padding-end: var(--vkui--spacing_size_xs);
|
|
38
39
|
padding-inline-end: var(--vkui--spacing_size_xs);
|
|
39
40
|
}
|
|
@@ -136,6 +137,7 @@
|
|
|
136
137
|
/* stylelint-disable-next-line selector-pseudo-class-disallowed-list */
|
|
137
138
|
|
|
138
139
|
.after > :global(.vkuiIcon) {
|
|
140
|
+
box-sizing: content-box;
|
|
139
141
|
-webkit-padding-start: var(--vkui--spacing_size_m);
|
|
140
142
|
padding-inline-start: var(--vkui--spacing_size_m);
|
|
141
143
|
}
|