@vkontakte/vkui 6.2.1 → 6.2.2
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/cjs/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/cjs/components/Checkbox/Checkbox.js +10 -8
- package/dist/cjs/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/cjs/components/ChipsInputBase/ChipsInputBase.d.ts.map +1 -1
- package/dist/cjs/components/ChipsInputBase/ChipsInputBase.js +1 -3
- package/dist/cjs/components/ChipsInputBase/ChipsInputBase.js.map +1 -1
- package/dist/cjs/components/FocusTrap/FocusTrap.d.ts.map +1 -1
- package/dist/cjs/components/FocusTrap/FocusTrap.js +10 -1
- package/dist/cjs/components/FocusTrap/FocusTrap.js.map +1 -1
- package/dist/cjs/components/PanelHeaderContext/PanelHeaderContext.d.ts.map +1 -1
- package/dist/cjs/components/PanelHeaderContext/PanelHeaderContext.js +1 -1
- package/dist/cjs/components/PanelHeaderContext/PanelHeaderContext.js.map +1 -1
- package/dist/cjs/components/Snackbar/Snackbar.d.ts +6 -0
- package/dist/cjs/components/Snackbar/Snackbar.d.ts.map +1 -1
- package/dist/cjs/components/Snackbar/Snackbar.js +3 -1
- package/dist/cjs/components/Snackbar/Snackbar.js.map +1 -1
- package/dist/cjs/components/Snackbar/types.d.ts +1 -0
- package/dist/cjs/components/Snackbar/types.d.ts.map +1 -1
- package/dist/cjs/components/Snackbar/utils.d.ts +4 -8
- package/dist/cjs/components/Snackbar/utils.d.ts.map +1 -1
- package/dist/cjs/components/Snackbar/utils.js +31 -41
- package/dist/cjs/components/Snackbar/utils.js.map +1 -1
- package/dist/cjs/helpers/array.d.ts +5 -0
- package/dist/cjs/helpers/array.d.ts.map +1 -0
- package/dist/cjs/helpers/array.js +20 -0
- package/dist/cjs/helpers/array.js.map +1 -0
- package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
- package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +9 -5
- package/dist/cjs/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +10 -8
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/ChipsInputBase/ChipsInputBase.d.ts.map +1 -1
- package/dist/components/ChipsInputBase/ChipsInputBase.js +1 -3
- package/dist/components/ChipsInputBase/ChipsInputBase.js.map +1 -1
- package/dist/components/FocusTrap/FocusTrap.d.ts.map +1 -1
- package/dist/components/FocusTrap/FocusTrap.js +10 -1
- package/dist/components/FocusTrap/FocusTrap.js.map +1 -1
- package/dist/components/PanelHeaderContext/PanelHeaderContext.d.ts.map +1 -1
- package/dist/components/PanelHeaderContext/PanelHeaderContext.js +1 -1
- package/dist/components/PanelHeaderContext/PanelHeaderContext.js.map +1 -1
- package/dist/components/Snackbar/Snackbar.d.ts +6 -0
- package/dist/components/Snackbar/Snackbar.d.ts.map +1 -1
- package/dist/components/Snackbar/Snackbar.js +3 -1
- package/dist/components/Snackbar/Snackbar.js.map +1 -1
- package/dist/components/Snackbar/types.d.ts +1 -0
- package/dist/components/Snackbar/types.d.ts.map +1 -1
- package/dist/components/Snackbar/types.js.map +1 -1
- package/dist/components/Snackbar/utils.d.ts +4 -8
- package/dist/components/Snackbar/utils.d.ts.map +1 -1
- package/dist/components/Snackbar/utils.js +30 -41
- package/dist/components/Snackbar/utils.js.map +1 -1
- package/dist/components.css +2 -2
- package/dist/components.css.map +1 -1
- package/dist/components.js.tmp +101 -75
- package/dist/cssm/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/cssm/components/Checkbox/Checkbox.js +10 -8
- package/dist/cssm/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/cssm/components/ChipsInputBase/ChipsInputBase.d.ts.map +1 -1
- package/dist/cssm/components/ChipsInputBase/ChipsInputBase.js +1 -3
- package/dist/cssm/components/ChipsInputBase/ChipsInputBase.js.map +1 -1
- package/dist/cssm/components/FocusTrap/FocusTrap.d.ts.map +1 -1
- package/dist/cssm/components/FocusTrap/FocusTrap.js +10 -1
- package/dist/cssm/components/FocusTrap/FocusTrap.js.map +1 -1
- package/dist/cssm/components/PanelHeaderContext/PanelHeaderContext.d.ts.map +1 -1
- package/dist/cssm/components/PanelHeaderContext/PanelHeaderContext.js +1 -1
- package/dist/cssm/components/PanelHeaderContext/PanelHeaderContext.js.map +1 -1
- package/dist/cssm/components/Search/Search.module.css +4 -5
- package/dist/cssm/components/Snackbar/Snackbar.d.ts +6 -0
- package/dist/cssm/components/Snackbar/Snackbar.d.ts.map +1 -1
- package/dist/cssm/components/Snackbar/Snackbar.js +3 -1
- package/dist/cssm/components/Snackbar/Snackbar.js.map +1 -1
- package/dist/cssm/components/Snackbar/Snackbar.module.css +47 -33
- package/dist/cssm/components/Snackbar/types.d.ts +1 -0
- package/dist/cssm/components/Snackbar/types.d.ts.map +1 -1
- package/dist/cssm/components/Snackbar/types.js.map +1 -1
- package/dist/cssm/components/Snackbar/utils.d.ts +4 -8
- package/dist/cssm/components/Snackbar/utils.d.ts.map +1 -1
- package/dist/cssm/components/Snackbar/utils.js +30 -41
- package/dist/cssm/components/Snackbar/utils.js.map +1 -1
- package/dist/cssm/helpers/array.d.ts +5 -0
- package/dist/cssm/helpers/array.d.ts.map +1 -0
- package/dist/cssm/helpers/array.js +10 -0
- package/dist/cssm/helpers/array.js.map +1 -0
- package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
- package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +9 -5
- package/dist/cssm/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
- package/dist/helpers/array.d.ts +5 -0
- package/dist/helpers/array.d.ts.map +1 -0
- package/dist/helpers/array.js +10 -0
- package/dist/helpers/array.js.map +1 -0
- package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.d.ts.map +1 -1
- package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js +9 -5
- package/dist/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.js.map +1 -1
- package/dist/vkui.css +2 -2
- package/dist/vkui.css.map +1 -1
- package/dist/vkui.js.tmp +101 -75
- package/package.json +1 -1
- package/src/components/Checkbox/Checkbox.tsx +11 -8
- package/src/components/ChipsInputBase/ChipsInputBase.tsx +1 -3
- package/src/components/FocusTrap/FocusTrap.tsx +10 -1
- package/src/components/PanelHeaderContext/PanelHeaderContext.tsx +2 -0
- package/src/components/Search/Search.module.css +4 -5
- package/src/components/Snackbar/Snackbar.module.css +47 -33
- package/src/components/Snackbar/Snackbar.tsx +9 -0
- package/src/components/Snackbar/types.ts +8 -1
- package/src/components/Snackbar/utils.ts +46 -42
- package/src/helpers/array.ts +9 -0
- package/src/lib/floating/useFloatingWithInteractions/useFloatingWithInteractions.ts +18 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/FocusTrap/FocusTrap.tsx"],"sourcesContent":["import { AllHTMLAttributes, useCallback, useRef, useState } from 'react';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { FOCUSABLE_ELEMENTS_LIST, Keys, pressedKey } from '../../lib/accessibility';\nimport {\n contains,\n getActiveElementByAnotherElement,\n getWindow,\n isHTMLElement,\n useDOM,\n} from '../../lib/dom';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport { HasComponent, HasRootRef } from '../../types';\n\nconst FOCUSABLE_ELEMENTS: string = FOCUSABLE_ELEMENTS_LIST.join();\nexport interface FocusTrapProps<T extends HTMLElement = HTMLElement>\n extends AllHTMLAttributes<T>,\n HasRootRef<T>,\n HasComponent {\n autoFocus?: boolean;\n restoreFocus?: boolean | (() => boolean);\n mount?: boolean;\n timeout?: number;\n onClose?: () => void;\n /**\n * Форсированное отключение захвата фокуса\n */\n disabled?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/FocusTrap\n */\nexport const FocusTrap = <T extends HTMLElement = HTMLElement>({\n Component = 'div',\n onClose,\n autoFocus = true,\n restoreFocus = true,\n disabled = false,\n mount = true,\n timeout = 0,\n getRootRef,\n children,\n ...restProps\n}: FocusTrapProps<T>) => {\n const ref = useExternRef<T>(getRootRef);\n const { document } = useDOM();\n\n const focusableNodesRef = useRef<HTMLElement[]>([]);\n\n const [restoreFocusTo, setRestoreFocusTo] = useState<Element | null>(null);\n\n const focusNodeByIndex = (nodeIndex: number) => {\n const element = focusableNodesRef.current[nodeIndex];\n\n if (element) {\n element.focus();\n }\n };\n\n const recalculateFocusableNodesRef = (parentNode: HTMLElement) => {\n // eslint-disable-next-line no-restricted-properties\n const newFocusableElements = parentNode.querySelectorAll<HTMLElement>(FOCUSABLE_ELEMENTS);\n\n const nodes: HTMLElement[] = [];\n newFocusableElements.forEach((focusableEl) => {\n const { display, visibility } = getComputedStyle(focusableEl);\n if (display !== 'none' && visibility !== 'hidden') {\n nodes.push(focusableEl);\n }\n });\n\n if (nodes.length === 0) {\n // Чтобы фокус был хотя бы на родителе\n nodes.push(parentNode);\n }\n focusableNodesRef.current = nodes;\n };\n\n const onMutateParentHandler = (parentNode: HTMLElement) => {\n recalculateFocusableNodesRef(parentNode);\n\n if (document) {\n const activeElement = document.activeElement as HTMLElement;\n const currentElementIndex = Math.max(\n document.activeElement ? focusableNodesRef.current.indexOf(activeElement) : -1,\n 0,\n );\n focusNodeByIndex(currentElementIndex);\n }\n };\n\n useIsomorphicLayoutEffect(\n function collectFocusableNodesRef() {\n if (!ref.current) {\n return;\n }\n const parentNode = ref.current;\n const observer = new MutationObserver(() => onMutateParentHandler(parentNode));\n observer.observe(ref.current, {\n subtree: true,\n childList: true,\n });\n recalculateFocusableNodesRef(parentNode);\n return () => observer.disconnect();\n },\n [ref],\n );\n\n useIsomorphicLayoutEffect(\n function tryToAutoFocusToFirstNode() {\n if (!ref.current || !autoFocus || disabled) {\n return;\n }\n\n const autoFocusToFirstNode = () => {\n if (!ref.current || !focusableNodesRef.current.length) {\n return;\n }\n const activeElement = getActiveElementByAnotherElement(ref.current);\n if (!contains(ref.current, activeElement)) {\n focusableNodesRef.current[0].focus();\n }\n };\n const timeoutId = setTimeout(autoFocusToFirstNode, timeout);\n return () => {\n clearTimeout(timeoutId);\n };\n },\n [autoFocus, timeout, disabled],\n );\n\n const restoreFocusImpl = useCallback(() => {\n const shouldRestoreFocus = typeof restoreFocus === 'function' ? restoreFocus() : restoreFocus;\n\n if (!restoreFocusTo || !isHTMLElement(restoreFocusTo) || !shouldRestoreFocus) {\n return;\n }\n\n setTimeout(() => {\n if (restoreFocusTo) {\n restoreFocusTo.focus();\n setRestoreFocusTo(null);\n }\n }, timeout);\n }, [restoreFocus, restoreFocusTo, timeout]);\n\n useIsomorphicLayoutEffect(\n function calculateRestoreFocusTo() {\n if (!ref.current || !restoreFocus || !mount) {\n setRestoreFocusTo(null);\n return;\n }\n setRestoreFocusTo(getActiveElementByAnotherElement(ref.current));\n },\n [ref, mount, restoreFocus],\n );\n\n useIsomorphicLayoutEffect(\n function tryToRestoreFocusOnUnmount() {\n return () => restoreFocusImpl();\n },\n [restoreFocusImpl],\n );\n\n useIsomorphicLayoutEffect(\n function tryToRestoreFocusWhenFakeUnmount() {\n if (!mount) {\n restoreFocusImpl();\n }\n },\n [mount, restoreFocusImpl],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (!ref.current) {\n return;\n }\n\n const onDocumentKeydown = (event: KeyboardEvent) => {\n if (disabled) {\n return;\n }\n\n const pressedKeyResult = pressedKey(event);\n\n switch (pressedKeyResult) {\n case Keys.TAB: {\n if (!focusableNodesRef.current.length) {\n return false;\n }\n\n const lastIdx = focusableNodesRef.current.length - 1;\n const targetIdx = focusableNodesRef.current.findIndex((node) => node === event.target);\n\n const shouldFocusFirstNode =\n targetIdx === -1 || (targetIdx === lastIdx && !event.shiftKey);\n\n if (shouldFocusFirstNode || (targetIdx === 0 && event.shiftKey)) {\n event.preventDefault();\n\n const node = focusableNodesRef.current[shouldFocusFirstNode ? 0 : lastIdx];\n\n if (node !== getActiveElementByAnotherElement(node)) {\n node.focus();\n }\n\n return false;\n }\n\n break;\n }\n case Keys.ESCAPE: {\n if (onClose) {\n event.preventDefault();\n onClose();\n }\n }\n }\n\n return true;\n };\n\n const doc = getWindow(ref.current).document;\n doc.addEventListener('keydown', onDocumentKeydown, {\n capture: true,\n });\n return () => {\n doc.removeEventListener('keydown', onDocumentKeydown, true);\n };\n }, [onClose, ref, disabled]);\n\n return (\n <Component tabIndex={-1} ref={ref} {...restProps}>\n {children}\n </Component>\n );\n};\n"],"names":["useCallback","useRef","useState","useExternRef","FOCUSABLE_ELEMENTS_LIST","Keys","pressedKey","contains","getActiveElementByAnotherElement","getWindow","isHTMLElement","useDOM","useIsomorphicLayoutEffect","FOCUSABLE_ELEMENTS","join","FocusTrap","Component","onClose","autoFocus","restoreFocus","disabled","mount","timeout","getRootRef","children","restProps","ref","document","focusableNodesRef","restoreFocusTo","setRestoreFocusTo","focusNodeByIndex","nodeIndex","element","current","focus","recalculateFocusableNodesRef","parentNode","newFocusableElements","querySelectorAll","nodes","forEach","focusableEl","display","visibility","getComputedStyle","push","length","onMutateParentHandler","activeElement","currentElementIndex","Math","max","indexOf","collectFocusableNodesRef","observer","MutationObserver","observe","subtree","childList","disconnect","tryToAutoFocusToFirstNode","autoFocusToFirstNode","timeoutId","setTimeout","clearTimeout","restoreFocusImpl","shouldRestoreFocus","calculateRestoreFocusTo","tryToRestoreFocusOnUnmount","tryToRestoreFocusWhenFakeUnmount","onDocumentKeydown","event","pressedKeyResult","TAB","lastIdx","targetIdx","findIndex","node","target","shouldFocusFirstNode","shiftKey","preventDefault","ESCAPE","doc","addEventListener","capture","removeEventListener","tabIndex"],"mappings":";;;;AAAA,SAA4BA,WAAW,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAQ;AACzE,SAASC,YAAY,QAAQ,2BAA2B;AACxD,SAASC,uBAAuB,EAAEC,IAAI,EAAEC,UAAU,QAAQ,0BAA0B;AACpF,SACEC,QAAQ,EACRC,gCAAgC,EAChCC,SAAS,EACTC,aAAa,EACbC,MAAM,QACD,gBAAgB;AACvB,SAASC,yBAAyB,QAAQ,sCAAsC;AAGhF,MAAMC,qBAA6BT,wBAAwBU,IAAI;AAgB/D;;CAEC,GACD,OAAO,MAAMC,YAAY;QAAsC,EAC7DC,YAAY,KAAK,EACjBC,OAAO,EACPC,YAAY,IAAI,EAChBC,eAAe,IAAI,EACnBC,WAAW,KAAK,EAChBC,QAAQ,IAAI,EACZC,UAAU,CAAC,EACXC,UAAU,EACVC,QAAQ,EAEU,WADfC;QATHT;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;;IAGA,MAAME,MAAMvB,aAAgBoB;IAC5B,MAAM,EAAEI,QAAQ,EAAE,GAAGhB;IAErB,MAAMiB,oBAAoB3B,OAAsB,EAAE;IAElD,MAAM,CAAC4B,gBAAgBC,kBAAkB,GAAG5B,SAAyB;IAErE,MAAM6B,mBAAmB,CAACC;QACxB,MAAMC,UAAUL,kBAAkBM,OAAO,CAACF,UAAU;QAEpD,IAAIC,SAAS;YACXA,QAAQE,KAAK;QACf;IACF;IAEA,MAAMC,+BAA+B,CAACC;QACpC,oDAAoD;QACpD,MAAMC,uBAAuBD,WAAWE,gBAAgB,CAAc1B;QAEtE,MAAM2B,QAAuB,EAAE;QAC/BF,qBAAqBG,OAAO,CAAC,CAACC;YAC5B,MAAM,EAAEC,OAAO,EAAEC,UAAU,EAAE,GAAGC,iBAAiBH;YACjD,IAAIC,YAAY,UAAUC,eAAe,UAAU;gBACjDJ,MAAMM,IAAI,CAACJ;YACb;QACF;QAEA,IAAIF,MAAMO,MAAM,KAAK,GAAG;YACtB,sCAAsC;YACtCP,MAAMM,IAAI,CAACT;QACb;QACAT,kBAAkBM,OAAO,GAAGM;IAC9B;IAEA,MAAMQ,wBAAwB,CAACX;QAC7BD,6BAA6BC;QAE7B,IAAIV,UAAU;YACZ,MAAMsB,gBAAgBtB,SAASsB,aAAa;YAC5C,MAAMC,sBAAsBC,KAAKC,GAAG,CAClCzB,SAASsB,aAAa,GAAGrB,kBAAkBM,OAAO,CAACmB,OAAO,CAACJ,iBAAiB,CAAC,GAC7E;YAEFlB,iBAAiBmB;QACnB;IACF;IAEAtC,0BACE,SAAS0C;QACP,IAAI,CAAC5B,IAAIQ,OAAO,EAAE;YAChB;QACF;QACA,MAAMG,aAAaX,IAAIQ,OAAO;QAC9B,MAAMqB,WAAW,IAAIC,iBAAiB,IAAMR,sBAAsBX;QAClEkB,SAASE,OAAO,CAAC/B,IAAIQ,OAAO,EAAE;YAC5BwB,SAAS;YACTC,WAAW;QACb;QACAvB,6BAA6BC;QAC7B,OAAO,IAAMkB,SAASK,UAAU;IAClC,GACA;QAAClC;KAAI;IAGPd,0BACE,SAASiD;QACP,IAAI,CAACnC,IAAIQ,OAAO,IAAI,CAAChB,aAAaE,UAAU;YAC1C;QACF;QAEA,MAAM0C,uBAAuB;YAC3B,IAAI,CAACpC,IAAIQ,OAAO,IAAI,CAACN,kBAAkBM,OAAO,CAACa,MAAM,EAAE;gBACrD;YACF;YACA,MAAME,gBAAgBzC,iCAAiCkB,IAAIQ,OAAO;YAClE,IAAI,CAAC3B,SAASmB,IAAIQ,OAAO,EAAEe,gBAAgB;gBACzCrB,kBAAkBM,OAAO,CAAC,EAAE,CAACC,KAAK;YACpC;QACF;QACA,MAAM4B,YAAYC,WAAWF,sBAAsBxC;QACnD,OAAO;YACL2C,aAAaF;QACf;IACF,GACA;QAAC7C;QAAWI;QAASF;KAAS;IAGhC,MAAM8C,mBAAmBlE,YAAY;QACnC,MAAMmE,qBAAqB,OAAOhD,iBAAiB,aAAaA,iBAAiBA;QAEjF,IAAI,CAACU,kBAAkB,CAACnB,cAAcmB,mBAAmB,CAACsC,oBAAoB;YAC5E;QACF;QAEAH,WAAW;YACT,IAAInC,gBAAgB;gBAClBA,eAAeM,KAAK;gBACpBL,kBAAkB;YACpB;QACF,GAAGR;IACL,GAAG;QAACH;QAAcU;QAAgBP;KAAQ;IAE1CV,0BACE,SAASwD;QACP,IAAI,CAAC1C,IAAIQ,OAAO,IAAI,CAACf,gBAAgB,CAACE,OAAO;YAC3CS,kBAAkB;YAClB;QACF;QACAA,kBAAkBtB,iCAAiCkB,IAAIQ,OAAO;IAChE,GACA;QAACR;QAAKL;QAAOF;KAAa;IAG5BP,0BACE,SAASyD;QACP,OAAO,IAAMH;IACf,GACA;QAACA;KAAiB;IAGpBtD,0BACE,SAAS0D;QACP,IAAI,CAACjD,OAAO;YACV6C;QACF;IACF,GACA;QAAC7C;QAAO6C;KAAiB;IAG3BtD,0BAA0B;QACxB,IAAI,CAACc,IAAIQ,OAAO,EAAE;YAChB;QACF;QAEA,MAAMqC,oBAAoB,CAACC;YACzB,IAAIpD,UAAU;gBACZ;YACF;YAEA,MAAMqD,mBAAmBnE,WAAWkE;YAEpC,OAAQC;gBACN,KAAKpE,KAAKqE,GAAG;oBAAE;wBACb,IAAI,CAAC9C,kBAAkBM,OAAO,CAACa,MAAM,EAAE;4BACrC,OAAO;wBACT;wBAEA,MAAM4B,UAAU/C,kBAAkBM,OAAO,CAACa,MAAM,GAAG;wBACnD,MAAM6B,YAAYhD,kBAAkBM,OAAO,CAAC2C,SAAS,CAAC,CAACC,OAASA,SAASN,MAAMO,MAAM;wBAErF,MAAMC,uBACJJ,cAAc,CAAC,KAAMA,cAAcD,WAAW,CAACH,MAAMS,QAAQ;wBAE/D,IAAID,wBAAyBJ,cAAc,KAAKJ,MAAMS,QAAQ,EAAG;4BAC/DT,MAAMU,cAAc;4BAEpB,MAAMJ,OAAOlD,kBAAkBM,OAAO,CAAC8C,uBAAuB,IAAIL,QAAQ;4BAE1E,IAAIG,SAAStE,iCAAiCsE,OAAO;gCACnDA,KAAK3C,KAAK;4BACZ;4BAEA,OAAO;wBACT;wBAEA;oBACF;gBACA,KAAK9B,KAAK8E,MAAM;oBAAE;wBAChB,IAAIlE,SAAS;4BACXuD,MAAMU,cAAc;4BACpBjE;wBACF;oBACF;YACF;YAEA,OAAO;QACT;QAEA,MAAMmE,MAAM3E,UAAUiB,IAAIQ,OAAO,EAAEP,QAAQ;QAC3CyD,IAAIC,gBAAgB,CAAC,WAAWd,mBAAmB;YACjDe,SAAS;QACX;QACA,OAAO;YACLF,IAAIG,mBAAmB,CAAC,WAAWhB,mBAAmB;QACxD;IACF,GAAG;QAACtD;QAASS;QAAKN;KAAS;IAE3B,qBACE,KAACJ;QAAUwE,UAAU,CAAC;QAAG9D,KAAKA;OAASD;kBACpCD;;AAGP,EAAE"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/FocusTrap/FocusTrap.tsx"],"sourcesContent":["import { AllHTMLAttributes, useCallback, useRef, useState } from 'react';\nimport { arraysEquals } from '../../helpers/array';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { FOCUSABLE_ELEMENTS_LIST, Keys, pressedKey } from '../../lib/accessibility';\nimport {\n contains,\n getActiveElementByAnotherElement,\n getWindow,\n isHTMLElement,\n useDOM,\n} from '../../lib/dom';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport { HasComponent, HasRootRef } from '../../types';\n\nconst FOCUSABLE_ELEMENTS: string = FOCUSABLE_ELEMENTS_LIST.join();\nexport interface FocusTrapProps<T extends HTMLElement = HTMLElement>\n extends AllHTMLAttributes<T>,\n HasRootRef<T>,\n HasComponent {\n autoFocus?: boolean;\n restoreFocus?: boolean | (() => boolean);\n mount?: boolean;\n timeout?: number;\n onClose?: () => void;\n /**\n * Форсированное отключение захвата фокуса\n */\n disabled?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/FocusTrap\n */\nexport const FocusTrap = <T extends HTMLElement = HTMLElement>({\n Component = 'div',\n onClose,\n autoFocus = true,\n restoreFocus = true,\n disabled = false,\n mount = true,\n timeout = 0,\n getRootRef,\n children,\n ...restProps\n}: FocusTrapProps<T>) => {\n const ref = useExternRef<T>(getRootRef);\n const { document } = useDOM();\n\n const focusableNodesRef = useRef<HTMLElement[]>([]);\n\n const [restoreFocusTo, setRestoreFocusTo] = useState<Element | null>(null);\n\n const focusNodeByIndex = (nodeIndex: number) => {\n const element = focusableNodesRef.current[nodeIndex];\n\n if (element) {\n element.focus({\n preventScroll: true,\n });\n }\n };\n\n const recalculateFocusableNodesRef = (parentNode: HTMLElement) => {\n // eslint-disable-next-line no-restricted-properties\n const newFocusableElements = parentNode.querySelectorAll<HTMLElement>(FOCUSABLE_ELEMENTS);\n\n const nodes: HTMLElement[] = [];\n newFocusableElements.forEach((focusableEl) => {\n const { display, visibility } = getComputedStyle(focusableEl);\n if (display !== 'none' && visibility !== 'hidden') {\n nodes.push(focusableEl);\n }\n });\n\n if (nodes.length === 0) {\n // Чтобы фокус был хотя бы на родителе\n nodes.push(parentNode);\n }\n focusableNodesRef.current = nodes;\n };\n\n const onMutateParentHandler = (parentNode: HTMLElement) => {\n const oldFocusableNodes = [...focusableNodesRef.current];\n\n recalculateFocusableNodesRef(parentNode);\n\n if (arraysEquals(oldFocusableNodes, focusableNodesRef.current)) {\n return;\n }\n\n if (document) {\n const activeElement = document.activeElement as HTMLElement;\n const currentElementIndex = Math.max(\n document.activeElement ? focusableNodesRef.current.indexOf(activeElement) : -1,\n 0,\n );\n focusNodeByIndex(currentElementIndex);\n }\n };\n\n useIsomorphicLayoutEffect(\n function collectFocusableNodesRef() {\n if (!ref.current) {\n return;\n }\n const parentNode = ref.current;\n const observer = new MutationObserver(() => onMutateParentHandler(parentNode));\n observer.observe(ref.current, {\n subtree: true,\n childList: true,\n });\n recalculateFocusableNodesRef(parentNode);\n return () => observer.disconnect();\n },\n [ref],\n );\n\n useIsomorphicLayoutEffect(\n function tryToAutoFocusToFirstNode() {\n if (!ref.current || !autoFocus || disabled) {\n return;\n }\n\n const autoFocusToFirstNode = () => {\n if (!ref.current || !focusableNodesRef.current.length) {\n return;\n }\n const activeElement = getActiveElementByAnotherElement(ref.current);\n if (!contains(ref.current, activeElement)) {\n focusableNodesRef.current[0].focus();\n }\n };\n const timeoutId = setTimeout(autoFocusToFirstNode, timeout);\n return () => {\n clearTimeout(timeoutId);\n };\n },\n [autoFocus, timeout, disabled],\n );\n\n const restoreFocusImpl = useCallback(() => {\n const shouldRestoreFocus = typeof restoreFocus === 'function' ? restoreFocus() : restoreFocus;\n\n if (!restoreFocusTo || !isHTMLElement(restoreFocusTo) || !shouldRestoreFocus) {\n return;\n }\n\n setTimeout(() => {\n if (restoreFocusTo) {\n restoreFocusTo.focus();\n setRestoreFocusTo(null);\n }\n }, timeout);\n }, [restoreFocus, restoreFocusTo, timeout]);\n\n useIsomorphicLayoutEffect(\n function calculateRestoreFocusTo() {\n if (!ref.current || !restoreFocus || !mount) {\n setRestoreFocusTo(null);\n return;\n }\n setRestoreFocusTo(getActiveElementByAnotherElement(ref.current));\n },\n [ref, mount, restoreFocus],\n );\n\n useIsomorphicLayoutEffect(\n function tryToRestoreFocusOnUnmount() {\n return () => restoreFocusImpl();\n },\n [restoreFocusImpl],\n );\n\n useIsomorphicLayoutEffect(\n function tryToRestoreFocusWhenFakeUnmount() {\n if (!mount) {\n restoreFocusImpl();\n }\n },\n [mount, restoreFocusImpl],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (!ref.current) {\n return;\n }\n\n const onDocumentKeydown = (event: KeyboardEvent) => {\n if (disabled) {\n return;\n }\n\n const pressedKeyResult = pressedKey(event);\n\n switch (pressedKeyResult) {\n case Keys.TAB: {\n if (!focusableNodesRef.current.length) {\n return false;\n }\n\n const lastIdx = focusableNodesRef.current.length - 1;\n const targetIdx = focusableNodesRef.current.findIndex((node) => node === event.target);\n\n const shouldFocusFirstNode =\n targetIdx === -1 || (targetIdx === lastIdx && !event.shiftKey);\n\n if (shouldFocusFirstNode || (targetIdx === 0 && event.shiftKey)) {\n event.preventDefault();\n\n const node = focusableNodesRef.current[shouldFocusFirstNode ? 0 : lastIdx];\n\n if (node !== getActiveElementByAnotherElement(node)) {\n node.focus();\n }\n\n return false;\n }\n\n break;\n }\n case Keys.ESCAPE: {\n if (onClose) {\n event.preventDefault();\n onClose();\n }\n }\n }\n\n return true;\n };\n\n const doc = getWindow(ref.current).document;\n doc.addEventListener('keydown', onDocumentKeydown, {\n capture: true,\n });\n return () => {\n doc.removeEventListener('keydown', onDocumentKeydown, true);\n };\n }, [onClose, ref, disabled]);\n\n return (\n <Component tabIndex={-1} ref={ref} {...restProps}>\n {children}\n </Component>\n );\n};\n"],"names":["useCallback","useRef","useState","arraysEquals","useExternRef","FOCUSABLE_ELEMENTS_LIST","Keys","pressedKey","contains","getActiveElementByAnotherElement","getWindow","isHTMLElement","useDOM","useIsomorphicLayoutEffect","FOCUSABLE_ELEMENTS","join","FocusTrap","Component","onClose","autoFocus","restoreFocus","disabled","mount","timeout","getRootRef","children","restProps","ref","document","focusableNodesRef","restoreFocusTo","setRestoreFocusTo","focusNodeByIndex","nodeIndex","element","current","focus","preventScroll","recalculateFocusableNodesRef","parentNode","newFocusableElements","querySelectorAll","nodes","forEach","focusableEl","display","visibility","getComputedStyle","push","length","onMutateParentHandler","oldFocusableNodes","activeElement","currentElementIndex","Math","max","indexOf","collectFocusableNodesRef","observer","MutationObserver","observe","subtree","childList","disconnect","tryToAutoFocusToFirstNode","autoFocusToFirstNode","timeoutId","setTimeout","clearTimeout","restoreFocusImpl","shouldRestoreFocus","calculateRestoreFocusTo","tryToRestoreFocusOnUnmount","tryToRestoreFocusWhenFakeUnmount","onDocumentKeydown","event","pressedKeyResult","TAB","lastIdx","targetIdx","findIndex","node","target","shouldFocusFirstNode","shiftKey","preventDefault","ESCAPE","doc","addEventListener","capture","removeEventListener","tabIndex"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PanelHeaderContext.d.ts","sourceRoot":"","sources":["../../../src/components/PanelHeaderContext/PanelHeaderContext.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAW7D,MAAM,WAAW,uBAAwB,SAAQ,yBAAyB,CAAC,cAAc,CAAC;IACxF,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,2DAM5B,uBAAuB,
|
|
1
|
+
{"version":3,"file":"PanelHeaderContext.d.ts","sourceRoot":"","sources":["../../../src/components/PanelHeaderContext/PanelHeaderContext.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAW7D,MAAM,WAAW,uBAAwB,SAAQ,yBAAyB,CAAC,cAAc,CAAC;IACxF,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,2DAM5B,uBAAuB,mDA0DzB,CAAC"}
|
|
@@ -27,7 +27,7 @@ const sizeXClassNames = {
|
|
|
27
27
|
const platform = usePlatform();
|
|
28
28
|
const { sizeX = 'none' } = useAdaptivity();
|
|
29
29
|
const elementRef = React.useRef(null);
|
|
30
|
-
const [animationState, animationHandlers] = useCSSKeyframesAnimationController(opened ? 'enter' : 'exit');
|
|
30
|
+
const [animationState, animationHandlers] = useCSSKeyframesAnimationController(opened ? 'enter' : 'exit', undefined, true);
|
|
31
31
|
const visible = animationState !== 'exited';
|
|
32
32
|
useScrollLock(platform !== 'vkcom' && visible);
|
|
33
33
|
const handleGlobalOnClickOutside = React.useCallback((event)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/PanelHeaderContext/PanelHeaderContext.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useGlobalOnClickOutside } from '../../hooks/useGlobalOnClickOutside';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { useCSSKeyframesAnimationController } from '../../lib/animation';\nimport type { HTMLAttributesWithRootRef } from '../../types';\nimport { useScrollLock } from '../AppRoot/ScrollContext';\nimport { FixedLayout } from '../FixedLayout/FixedLayout';\nimport styles from './PanelHeaderContext.module.css';\n\nconst sizeXClassNames = {\n none: styles['PanelHeaderContext--sizeX-none'],\n compact: styles['PanelHeaderContext--sizeX-compact'],\n regular: styles['PanelHeaderContext--sizeX-regular'],\n};\n\nexport interface PanelHeaderContextProps extends HTMLAttributesWithRootRef<HTMLDivElement> {\n opened: boolean;\n onClose: VoidFunction;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/PanelHeaderContext\n */\nexport const PanelHeaderContext = ({\n children,\n opened = false,\n className,\n onClose,\n ...restProps\n}: PanelHeaderContextProps) => {\n const platform = usePlatform();\n const { sizeX = 'none' } = useAdaptivity();\n const elementRef = React.useRef<HTMLDivElement>(null);\n const [animationState, animationHandlers] = useCSSKeyframesAnimationController(\n opened ? 'enter' : 'exit',\n );\n const visible = animationState !== 'exited';\n\n useScrollLock(platform !== 'vkcom' && visible);\n\n const handleGlobalOnClickOutside = React.useCallback(\n (event: MouseEvent) => {\n if (opened) {\n event.stopPropagation();\n onClose();\n }\n },\n [opened, onClose],\n );\n\n useGlobalOnClickOutside(handleGlobalOnClickOutside, visible ? elementRef : null);\n\n if (!visible) {\n return null;\n }\n\n return (\n <FixedLayout\n {...restProps}\n className={classNames(\n styles['PanelHeaderContext'],\n platform === 'ios' && styles['PanelHeaderContext--ios'],\n opened ? styles['PanelHeaderContext--opened'] : styles['PanelHeaderContext--closing'],\n sizeXClassNames[sizeX],\n className,\n )}\n vertical=\"top\"\n >\n <div\n onClick={(event) => {\n event.stopPropagation();\n onClose();\n }}\n className={styles['PanelHeaderContext__fade']}\n />\n <div\n data-testid={process.env.NODE_ENV === 'test' ? 'content' : undefined}\n className={styles['PanelHeaderContext__in']}\n ref={elementRef}\n {...animationHandlers}\n >\n <div className={styles['PanelHeaderContext__content']}>{children}</div>\n </div>\n </FixedLayout>\n );\n};\n"],"names":["React","classNames","useAdaptivity","useGlobalOnClickOutside","usePlatform","useCSSKeyframesAnimationController","useScrollLock","FixedLayout","sizeXClassNames","none","compact","regular","PanelHeaderContext","children","opened","className","onClose","restProps","platform","sizeX","elementRef","useRef","animationState","animationHandlers","visible","handleGlobalOnClickOutside","useCallback","event","stopPropagation","vertical","div","onClick","data-testid","process","env","NODE_ENV","
|
|
1
|
+
{"version":3,"sources":["../../../src/components/PanelHeaderContext/PanelHeaderContext.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useGlobalOnClickOutside } from '../../hooks/useGlobalOnClickOutside';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { useCSSKeyframesAnimationController } from '../../lib/animation';\nimport type { HTMLAttributesWithRootRef } from '../../types';\nimport { useScrollLock } from '../AppRoot/ScrollContext';\nimport { FixedLayout } from '../FixedLayout/FixedLayout';\nimport styles from './PanelHeaderContext.module.css';\n\nconst sizeXClassNames = {\n none: styles['PanelHeaderContext--sizeX-none'],\n compact: styles['PanelHeaderContext--sizeX-compact'],\n regular: styles['PanelHeaderContext--sizeX-regular'],\n};\n\nexport interface PanelHeaderContextProps extends HTMLAttributesWithRootRef<HTMLDivElement> {\n opened: boolean;\n onClose: VoidFunction;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/PanelHeaderContext\n */\nexport const PanelHeaderContext = ({\n children,\n opened = false,\n className,\n onClose,\n ...restProps\n}: PanelHeaderContextProps) => {\n const platform = usePlatform();\n const { sizeX = 'none' } = useAdaptivity();\n const elementRef = React.useRef<HTMLDivElement>(null);\n const [animationState, animationHandlers] = useCSSKeyframesAnimationController(\n opened ? 'enter' : 'exit',\n undefined,\n true,\n );\n const visible = animationState !== 'exited';\n\n useScrollLock(platform !== 'vkcom' && visible);\n\n const handleGlobalOnClickOutside = React.useCallback(\n (event: MouseEvent) => {\n if (opened) {\n event.stopPropagation();\n onClose();\n }\n },\n [opened, onClose],\n );\n\n useGlobalOnClickOutside(handleGlobalOnClickOutside, visible ? elementRef : null);\n\n if (!visible) {\n return null;\n }\n\n return (\n <FixedLayout\n {...restProps}\n className={classNames(\n styles['PanelHeaderContext'],\n platform === 'ios' && styles['PanelHeaderContext--ios'],\n opened ? styles['PanelHeaderContext--opened'] : styles['PanelHeaderContext--closing'],\n sizeXClassNames[sizeX],\n className,\n )}\n vertical=\"top\"\n >\n <div\n onClick={(event) => {\n event.stopPropagation();\n onClose();\n }}\n className={styles['PanelHeaderContext__fade']}\n />\n <div\n data-testid={process.env.NODE_ENV === 'test' ? 'content' : undefined}\n className={styles['PanelHeaderContext__in']}\n ref={elementRef}\n {...animationHandlers}\n >\n <div className={styles['PanelHeaderContext__content']}>{children}</div>\n </div>\n </FixedLayout>\n );\n};\n"],"names":["React","classNames","useAdaptivity","useGlobalOnClickOutside","usePlatform","useCSSKeyframesAnimationController","useScrollLock","FixedLayout","sizeXClassNames","none","compact","regular","PanelHeaderContext","children","opened","className","onClose","restProps","platform","sizeX","elementRef","useRef","animationState","animationHandlers","undefined","visible","handleGlobalOnClickOutside","useCallback","event","stopPropagation","vertical","div","onClick","data-testid","process","env","NODE_ENV","ref"],"mappings":";;;;AAAA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,UAAU,QAAQ,kBAAkB;AAC7C,SAASC,aAAa,QAAQ,4BAA4B;AAC1D,SAASC,uBAAuB,QAAQ,sCAAsC;AAC9E,SAASC,WAAW,QAAQ,0BAA0B;AACtD,SAASC,kCAAkC,QAAQ,sBAAsB;AAEzE,SAASC,aAAa,QAAQ,2BAA2B;AACzD,SAASC,WAAW,QAAQ,6BAA6B;AAGzD,MAAMC,kBAAkB;IACtBC,IAAI;IACJC,OAAO;IACPC,OAAO;AACT;AAOA;;CAEC,GACD,OAAO,MAAMC,qBAAqB;QAAC,EACjCC,QAAQ,EACRC,SAAS,KAAK,EACdC,SAAS,EACTC,OAAO,EAEiB,WADrBC;QAJHJ;QACAC;QACAC;QACAC;;IAGA,MAAME,WAAWd;IACjB,MAAM,EAAEe,QAAQ,MAAM,EAAE,GAAGjB;IAC3B,MAAMkB,aAAapB,MAAMqB,MAAM,CAAiB;IAChD,MAAM,CAACC,gBAAgBC,kBAAkB,GAAGlB,mCAC1CS,SAAS,UAAU,QACnBU,WACA;IAEF,MAAMC,UAAUH,mBAAmB;IAEnChB,cAAcY,aAAa,WAAWO;IAEtC,MAAMC,6BAA6B1B,MAAM2B,WAAW,CAClD,CAACC;QACC,IAAId,QAAQ;YACVc,MAAMC,eAAe;YACrBb;QACF;IACF,GACA;QAACF;QAAQE;KAAQ;IAGnBb,wBAAwBuB,4BAA4BD,UAAUL,aAAa;IAE3E,IAAI,CAACK,SAAS;QACZ,OAAO;IACT;IAEA,qBACE,MAAClB,qDACKU;QACJF,WAAWd,qCAETiB,aAAa,wCACbJ,+EACAN,eAAe,CAACW,MAAM,EACtBJ;QAEFe,UAAS;;0BAET,KAACC;gBACCC,SAAS,CAACJ;oBACRA,MAAMC,eAAe;oBACrBb;gBACF;gBACAD,SAAS;;0BAEX,KAACgB;gBACCE,eAAaC,QAAQC,GAAG,CAACC,QAAQ,KAAK,SAAS,YAAYZ;gBAC3DT,SAAS;gBACTsB,KAAKjB;eACDG;0BAEJ,cAAA,KAACQ;oBAAIhB,SAAS;8BAA0CF;;;;;AAIhE,EAAE"}
|
|
@@ -5,6 +5,12 @@ import type { SnackbarPlacement } from './types';
|
|
|
5
5
|
export interface SnackbarProps extends Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'role'>, BasicProps {
|
|
6
6
|
/**
|
|
7
7
|
* Задаёт расположение компонента.
|
|
8
|
+
*
|
|
9
|
+
* > Note: в мобильном режиме:
|
|
10
|
+
* > - `"top-start"`/`"top-end"` перебивается на `"top"`, чтобы поведение было схожим с нативными
|
|
11
|
+
* > уведомлениями;
|
|
12
|
+
* > - `"bottom"`/`"bottom-end"` перебивается на "bottom-start", чтобы избежать вызова системных
|
|
13
|
+
* > функций, таких как **Pull To Refresh** и **Режим управления одной рукой**.
|
|
8
14
|
*/
|
|
9
15
|
placement?: SnackbarPlacement;
|
|
10
16
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Snackbar.d.ts","sourceRoot":"","sources":["../../../src/components/Snackbar/Snackbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Snackbar.d.ts","sourceRoot":"","sources":["../../../src/components/Snackbar/Snackbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAW/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAGxD,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAa,iBAAiB,EAAE,MAAM,SAAS,CAAC;AA2B5D,MAAM,WAAW,aACf,SAAQ,IAAI,CAAC,yBAAyB,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC,EAC7D,UAAU;IACZ;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B;;;OAGG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAClD;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;OAEG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;CACzC;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ;yJAgBlB,aAAa;;CAqMf,CAAC"}
|
|
@@ -7,6 +7,7 @@ import { classNames, noop } from '@vkontakte/vkjs';
|
|
|
7
7
|
import { useExternRef } from '../../hooks/useExternRef';
|
|
8
8
|
import { useFocusWithin } from '../../hooks/useFocusWithin';
|
|
9
9
|
import { useGlobalEscKeyDown } from '../../hooks/useGlobalEscKeyDown';
|
|
10
|
+
import { useMediaQueries } from '../../hooks/useMediaQueries';
|
|
10
11
|
import { usePlatform } from '../../hooks/usePlatform';
|
|
11
12
|
import { useCSSKeyframesAnimationController } from '../../lib/animation';
|
|
12
13
|
import { getRelativeBoundingClientRect } from '../../lib/dom';
|
|
@@ -61,6 +62,7 @@ const animationStateClassNames = {
|
|
|
61
62
|
const shiftDataRef = React.useRef(null);
|
|
62
63
|
const rafRef = React.useRef(null);
|
|
63
64
|
const closeTimeoutIdRef = React.useRef();
|
|
65
|
+
const mediaQueries = useMediaQueries();
|
|
64
66
|
const [animationState, animationHandlers] = useCSSKeyframesAnimationController(open ? 'enter' : 'exit', {
|
|
65
67
|
onExited: onClose
|
|
66
68
|
});
|
|
@@ -92,7 +94,7 @@ const animationStateClassNames = {
|
|
|
92
94
|
const handleTouchStart = (event)=>{
|
|
93
95
|
panGestureRecognizer.current = new UIPanGestureRecognizer();
|
|
94
96
|
panGestureRecognizer.current.setStartCoords(event.nativeEvent);
|
|
95
|
-
shiftDataRef.current = getInitialShiftData(rootRef.current.offsetWidth, rootRef.current.offsetHeight);
|
|
97
|
+
shiftDataRef.current = getInitialShiftData(rootRef.current.offsetWidth, rootRef.current.offsetHeight, mediaQueries);
|
|
96
98
|
setTouched(true);
|
|
97
99
|
};
|
|
98
100
|
const handleTouchMove = (event)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Snackbar/Snackbar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames, noop } from '@vkontakte/vkjs';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useFocusWithin } from '../../hooks/useFocusWithin';\nimport { useGlobalEscKeyDown } from '../../hooks/useGlobalEscKeyDown';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { useCSSKeyframesAnimationController } from '../../lib/animation';\nimport { getRelativeBoundingClientRect } from '../../lib/dom';\nimport { UIPanGestureRecognizer } from '../../lib/touch';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport { HTMLAttributesWithRootRef } from '../../types';\nimport { Button } from '../Button/Button';\nimport { RootComponent } from '../RootComponent/RootComponent';\nimport { Basic, BasicProps } from './subcomponents/Basic/Basic';\nimport type { ShiftData, SnackbarPlacement } from './types';\nimport {\n getInitialShiftData,\n getMovedShiftData,\n resolveOffsetYCssStyle,\n shouldBeClosedByShiftData,\n} from './utils';\nimport styles from './Snackbar.module.css';\n\nconst placementClassNames = {\n 'top-start': styles['Snackbar--placement-top-start'],\n 'top': styles['Snackbar--placement-top'],\n 'top-end': styles['Snackbar--placement-top-end'],\n 'bottom-start': styles['Snackbar--placement-bottom-start'],\n 'bottom': styles['Snackbar--placement-bottom'],\n 'bottom-end': styles['Snackbar--placement-bottom-end'],\n};\n\nconst animationStateClassNames = {\n enter: styles['Snackbar--state-enter'],\n entering: styles['Snackbar--state-entering'],\n entered: styles['Snackbar--state-entered'],\n exit: styles['Snackbar--state-exit'],\n exiting: styles['Snackbar--state-exiting'],\n exited: undefined,\n};\n\nexport interface SnackbarProps\n extends Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'role'>,\n BasicProps {\n /**\n * Задаёт расположение компонента.\n */\n placement?: SnackbarPlacement;\n /**\n * Название кнопки действия в уведомлении\n * Не может использоваться одновременно с `subtitle`\n */\n action?: React.ReactNode;\n /**\n * Будет вызвано при клике на кнопку действия\n */\n onActionClick?: (event: React.MouseEvent) => void;\n /**\n * Время в миллисекундах, через которое плашка скроется\n */\n duration?: number;\n /**\n * Обработчик закрытия уведомления\n */\n onClose: () => void;\n /**\n * Величина отступа снизу. Используется для позиционирования элемента в случае, когда нежелательно, чтобы Snackbar при появлении перекрывал важные элементы интерфейса.\n */\n offsetY?: React.CSSProperties['bottom'];\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Snackbar\n */\nexport const Snackbar = ({\n placement = 'bottom-start',\n children,\n layout,\n action,\n before,\n after,\n duration = 4000,\n onActionClick = noop,\n onClose,\n mode = 'default',\n subtitle,\n offsetY,\n style,\n getRootRef,\n ...restProps\n}: SnackbarProps) => {\n const platform = usePlatform();\n\n const [open, setOpen] = React.useState(true);\n const [touched, setTouched] = React.useState(false);\n\n const rootRef = useExternRef(getRootRef);\n const focused = useFocusWithin(rootRef);\n const inRef = React.useRef<HTMLDivElement>(null);\n const panGestureRecognizer = React.useRef<UIPanGestureRecognizer | null>(null);\n\n const shiftDataRef = React.useRef<ShiftData | null>(null);\n\n const rafRef = React.useRef<ReturnType<typeof requestAnimationFrame> | null>(null);\n const closeTimeoutIdRef = React.useRef<ReturnType<typeof setTimeout>>();\n const [animationState, animationHandlers] = useCSSKeyframesAnimationController(\n open ? 'enter' : 'exit',\n {\n onExited: onClose,\n },\n );\n\n const clearRAF = React.useCallback(() => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n }, []);\n\n const updateShiftAxisCSSProperties = React.useCallback(\n (x: number | null, y: number | null) => {\n rafRef.current = requestAnimationFrame(() => {\n if (rootRef.current) {\n x === null\n ? rootRef.current.style.removeProperty('--vkui_internal--snackbar_shift_x')\n : rootRef.current.style.setProperty('--vkui_internal--snackbar_shift_x', `${x}px`);\n y === null\n ? rootRef.current.style.removeProperty('--vkui_internal--snackbar_shift_y')\n : rootRef.current.style.setProperty('--vkui_internal--snackbar_shift_y', `${y}px`);\n }\n });\n },\n [rootRef],\n );\n\n const close = React.useCallback(() => {\n setOpen(false);\n }, []);\n\n const handleActionClick = (event: React.MouseEvent) => {\n close();\n if (action) {\n onActionClick(event);\n }\n };\n\n const handleTouchStart = (event: React.UIEvent<HTMLDivElement>) => {\n panGestureRecognizer.current = new UIPanGestureRecognizer();\n panGestureRecognizer.current.setStartCoords(event.nativeEvent);\n shiftDataRef.current = getInitialShiftData(\n rootRef.current!.offsetWidth,\n rootRef.current!.offsetHeight,\n );\n setTouched(true);\n };\n\n const handleTouchMove = (event: React.UIEvent<HTMLDivElement>) => {\n if (shiftDataRef.current && panGestureRecognizer.current) {\n panGestureRecognizer.current.setInitialTimeOnce();\n panGestureRecognizer.current.setEndCoords(event.nativeEvent);\n shiftDataRef.current = getMovedShiftData(\n placement,\n shiftDataRef.current,\n panGestureRecognizer.current.delta(),\n );\n\n if (shiftDataRef.current.shifted) {\n updateShiftAxisCSSProperties(shiftDataRef.current.x, shiftDataRef.current.y);\n }\n }\n };\n\n const handleTouchEnd = () => {\n if (\n touched &&\n shiftDataRef.current &&\n panGestureRecognizer.current &&\n shouldBeClosedByShiftData(\n placement,\n shiftDataRef.current,\n getRelativeBoundingClientRect(rootRef.current!, inRef.current!),\n panGestureRecognizer.current.velocity(),\n )\n ) {\n close();\n }\n\n setTouched(false);\n };\n\n useIsomorphicLayoutEffect(\n function closeAfterDelay() {\n if (!open || focused || touched || animationState !== 'entered') {\n return;\n }\n closeTimeoutIdRef.current = setTimeout(close, duration);\n return function preventCloseAfterDelayOnUnmount() {\n clearTimeout(closeTimeoutIdRef.current);\n };\n },\n [open, focused, touched, animationState, close, duration],\n );\n\n useIsomorphicLayoutEffect(\n function clearUserInteractionDataAfterTouchEnd() {\n if (!touched) {\n clearRAF();\n shiftDataRef.current = null;\n panGestureRecognizer.current = null;\n\n if (open) {\n updateShiftAxisCSSProperties(null, null);\n }\n }\n },\n [touched, open, updateShiftAxisCSSProperties, clearRAF],\n );\n\n React.useEffect(() => clearRAF, [clearRAF]);\n\n useGlobalEscKeyDown(open, close);\n\n if (animationState === 'exited') {\n return null;\n }\n\n return (\n <RootComponent\n {...restProps}\n role=\"presentation\"\n baseClassName={classNames(\n styles['Snackbar'],\n platform === 'ios' && styles['Snackbar--ios'],\n touched && styles['Snackbar--touched'],\n placementClassNames[placement],\n animationStateClassNames[animationState],\n )}\n style={resolveOffsetYCssStyle(placement, style, offsetY)}\n getRootRef={rootRef}\n >\n <div\n role=\"alert\"\n className={styles['Snackbar__in']}\n ref={inRef}\n // mobile\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n // desktop\n onMouseDown={handleTouchStart}\n onMouseMove={handleTouchMove}\n onMouseUp={handleTouchEnd}\n onMouseLeave={handleTouchEnd}\n {...animationHandlers}\n >\n <Basic\n mode={mode}\n layout={layout}\n before={before}\n after={after}\n subtitle={subtitle}\n action={\n action && (\n <Button\n align=\"left\"\n mode=\"link\"\n appearance={\n mode === 'dark'\n ? /* istanbul ignore next: проверяется в e2e */\n 'overlay'\n : 'accent'\n }\n size=\"s\"\n onClick={handleActionClick}\n >\n {action}\n </Button>\n )\n }\n >\n {children}\n </Basic>\n </div>\n </RootComponent>\n );\n};\n\nSnackbar.Basic = Basic;\n"],"names":["React","classNames","noop","useExternRef","useFocusWithin","useGlobalEscKeyDown","usePlatform","useCSSKeyframesAnimationController","getRelativeBoundingClientRect","UIPanGestureRecognizer","useIsomorphicLayoutEffect","Button","RootComponent","Basic","getInitialShiftData","getMovedShiftData","resolveOffsetYCssStyle","shouldBeClosedByShiftData","placementClassNames","animationStateClassNames","enter","entering","entered","exit","exiting","exited","undefined","Snackbar","placement","children","layout","action","before","after","duration","onActionClick","onClose","mode","subtitle","offsetY","style","getRootRef","restProps","platform","open","setOpen","useState","touched","setTouched","rootRef","focused","inRef","useRef","panGestureRecognizer","shiftDataRef","rafRef","closeTimeoutIdRef","animationState","animationHandlers","onExited","clearRAF","useCallback","current","cancelAnimationFrame","updateShiftAxisCSSProperties","x","y","requestAnimationFrame","removeProperty","setProperty","close","handleActionClick","event","handleTouchStart","setStartCoords","nativeEvent","offsetWidth","offsetHeight","handleTouchMove","setInitialTimeOnce","setEndCoords","delta","shifted","handleTouchEnd","velocity","closeAfterDelay","setTimeout","preventCloseAfterDelayOnUnmount","clearTimeout","clearUserInteractionDataAfterTouchEnd","useEffect","role","baseClassName","div","className","ref","onTouchStart","onTouchMove","onTouchEnd","onMouseDown","onMouseMove","onMouseUp","onMouseLeave","align","appearance","size","onClick"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Snackbar/Snackbar.tsx"],"sourcesContent":["import * as React from 'react';\nimport { classNames, noop } from '@vkontakte/vkjs';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useFocusWithin } from '../../hooks/useFocusWithin';\nimport { useGlobalEscKeyDown } from '../../hooks/useGlobalEscKeyDown';\nimport { useMediaQueries } from '../../hooks/useMediaQueries';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { useCSSKeyframesAnimationController } from '../../lib/animation';\nimport { getRelativeBoundingClientRect } from '../../lib/dom';\nimport { UIPanGestureRecognizer } from '../../lib/touch';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport { HTMLAttributesWithRootRef } from '../../types';\nimport { Button } from '../Button/Button';\nimport { RootComponent } from '../RootComponent/RootComponent';\nimport { Basic, BasicProps } from './subcomponents/Basic/Basic';\nimport type { ShiftData, SnackbarPlacement } from './types';\nimport {\n getInitialShiftData,\n getMovedShiftData,\n resolveOffsetYCssStyle,\n shouldBeClosedByShiftData,\n} from './utils';\nimport styles from './Snackbar.module.css';\n\nconst placementClassNames = {\n 'top-start': styles['Snackbar--placement-top-start'],\n 'top': styles['Snackbar--placement-top'],\n 'top-end': styles['Snackbar--placement-top-end'],\n 'bottom-start': styles['Snackbar--placement-bottom-start'],\n 'bottom': styles['Snackbar--placement-bottom'],\n 'bottom-end': styles['Snackbar--placement-bottom-end'],\n};\n\nconst animationStateClassNames = {\n enter: styles['Snackbar--state-enter'],\n entering: styles['Snackbar--state-entering'],\n entered: styles['Snackbar--state-entered'],\n exit: styles['Snackbar--state-exit'],\n exiting: styles['Snackbar--state-exiting'],\n exited: undefined,\n};\n\nexport interface SnackbarProps\n extends Omit<HTMLAttributesWithRootRef<HTMLDivElement>, 'role'>,\n BasicProps {\n /**\n * Задаёт расположение компонента.\n *\n * > Note: в мобильном режиме:\n * > - `\"top-start\"`/`\"top-end\"` перебивается на `\"top\"`, чтобы поведение было схожим с нативными\n * > уведомлениями;\n * > - `\"bottom\"`/`\"bottom-end\"` перебивается на \"bottom-start\", чтобы избежать вызова системных\n * > функций, таких как **Pull To Refresh** и **Режим управления одной рукой**.\n */\n placement?: SnackbarPlacement;\n /**\n * Название кнопки действия в уведомлении\n * Не может использоваться одновременно с `subtitle`\n */\n action?: React.ReactNode;\n /**\n * Будет вызвано при клике на кнопку действия\n */\n onActionClick?: (event: React.MouseEvent) => void;\n /**\n * Время в миллисекундах, через которое плашка скроется\n */\n duration?: number;\n /**\n * Обработчик закрытия уведомления\n */\n onClose: () => void;\n /**\n * Величина отступа снизу. Используется для позиционирования элемента в случае, когда нежелательно, чтобы Snackbar при появлении перекрывал важные элементы интерфейса.\n */\n offsetY?: React.CSSProperties['bottom'];\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Snackbar\n */\nexport const Snackbar = ({\n placement = 'bottom-start',\n children,\n layout,\n action,\n before,\n after,\n duration = 4000,\n onActionClick = noop,\n onClose,\n mode = 'default',\n subtitle,\n offsetY,\n style,\n getRootRef,\n ...restProps\n}: SnackbarProps) => {\n const platform = usePlatform();\n\n const [open, setOpen] = React.useState(true);\n const [touched, setTouched] = React.useState(false);\n\n const rootRef = useExternRef(getRootRef);\n const focused = useFocusWithin(rootRef);\n const inRef = React.useRef<HTMLDivElement>(null);\n const panGestureRecognizer = React.useRef<UIPanGestureRecognizer | null>(null);\n\n const shiftDataRef = React.useRef<ShiftData | null>(null);\n\n const rafRef = React.useRef<ReturnType<typeof requestAnimationFrame> | null>(null);\n const closeTimeoutIdRef = React.useRef<ReturnType<typeof setTimeout>>();\n const mediaQueries = useMediaQueries();\n const [animationState, animationHandlers] = useCSSKeyframesAnimationController(\n open ? 'enter' : 'exit',\n {\n onExited: onClose,\n },\n );\n\n const clearRAF = React.useCallback(() => {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = null;\n }\n }, []);\n\n const updateShiftAxisCSSProperties = React.useCallback(\n (x: number | null, y: number | null) => {\n rafRef.current = requestAnimationFrame(() => {\n if (rootRef.current) {\n x === null\n ? rootRef.current.style.removeProperty('--vkui_internal--snackbar_shift_x')\n : rootRef.current.style.setProperty('--vkui_internal--snackbar_shift_x', `${x}px`);\n y === null\n ? rootRef.current.style.removeProperty('--vkui_internal--snackbar_shift_y')\n : rootRef.current.style.setProperty('--vkui_internal--snackbar_shift_y', `${y}px`);\n }\n });\n },\n [rootRef],\n );\n\n const close = React.useCallback(() => {\n setOpen(false);\n }, []);\n\n const handleActionClick = (event: React.MouseEvent) => {\n close();\n if (action) {\n onActionClick(event);\n }\n };\n\n const handleTouchStart = (event: React.UIEvent<HTMLDivElement>) => {\n panGestureRecognizer.current = new UIPanGestureRecognizer();\n panGestureRecognizer.current.setStartCoords(event.nativeEvent);\n shiftDataRef.current = getInitialShiftData(\n rootRef.current!.offsetWidth,\n rootRef.current!.offsetHeight,\n mediaQueries,\n );\n setTouched(true);\n };\n\n const handleTouchMove = (event: React.UIEvent<HTMLDivElement>) => {\n if (shiftDataRef.current && panGestureRecognizer.current) {\n panGestureRecognizer.current.setInitialTimeOnce();\n panGestureRecognizer.current.setEndCoords(event.nativeEvent);\n shiftDataRef.current = getMovedShiftData(\n placement,\n shiftDataRef.current,\n panGestureRecognizer.current.delta(),\n );\n\n if (shiftDataRef.current.shifted) {\n updateShiftAxisCSSProperties(shiftDataRef.current.x, shiftDataRef.current.y);\n }\n }\n };\n\n const handleTouchEnd = () => {\n if (\n touched &&\n shiftDataRef.current &&\n panGestureRecognizer.current &&\n shouldBeClosedByShiftData(\n placement,\n shiftDataRef.current,\n getRelativeBoundingClientRect(rootRef.current!, inRef.current!),\n panGestureRecognizer.current.velocity(),\n )\n ) {\n close();\n }\n\n setTouched(false);\n };\n\n useIsomorphicLayoutEffect(\n function closeAfterDelay() {\n if (!open || focused || touched || animationState !== 'entered') {\n return;\n }\n closeTimeoutIdRef.current = setTimeout(close, duration);\n return function preventCloseAfterDelayOnUnmount() {\n clearTimeout(closeTimeoutIdRef.current);\n };\n },\n [open, focused, touched, animationState, close, duration],\n );\n\n useIsomorphicLayoutEffect(\n function clearUserInteractionDataAfterTouchEnd() {\n if (!touched) {\n clearRAF();\n shiftDataRef.current = null;\n panGestureRecognizer.current = null;\n\n if (open) {\n updateShiftAxisCSSProperties(null, null);\n }\n }\n },\n [touched, open, updateShiftAxisCSSProperties, clearRAF],\n );\n\n React.useEffect(() => clearRAF, [clearRAF]);\n\n useGlobalEscKeyDown(open, close);\n\n if (animationState === 'exited') {\n return null;\n }\n\n return (\n <RootComponent\n {...restProps}\n role=\"presentation\"\n baseClassName={classNames(\n styles['Snackbar'],\n platform === 'ios' && styles['Snackbar--ios'],\n touched && styles['Snackbar--touched'],\n placementClassNames[placement],\n animationStateClassNames[animationState],\n )}\n style={resolveOffsetYCssStyle(placement, style, offsetY)}\n getRootRef={rootRef}\n >\n <div\n role=\"alert\"\n className={styles['Snackbar__in']}\n ref={inRef}\n // mobile\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n // desktop\n onMouseDown={handleTouchStart}\n onMouseMove={handleTouchMove}\n onMouseUp={handleTouchEnd}\n onMouseLeave={handleTouchEnd}\n {...animationHandlers}\n >\n <Basic\n mode={mode}\n layout={layout}\n before={before}\n after={after}\n subtitle={subtitle}\n action={\n action && (\n <Button\n align=\"left\"\n mode=\"link\"\n appearance={\n mode === 'dark'\n ? /* istanbul ignore next: проверяется в e2e */\n 'overlay'\n : 'accent'\n }\n size=\"s\"\n onClick={handleActionClick}\n >\n {action}\n </Button>\n )\n }\n >\n {children}\n </Basic>\n </div>\n </RootComponent>\n );\n};\n\nSnackbar.Basic = Basic;\n"],"names":["React","classNames","noop","useExternRef","useFocusWithin","useGlobalEscKeyDown","useMediaQueries","usePlatform","useCSSKeyframesAnimationController","getRelativeBoundingClientRect","UIPanGestureRecognizer","useIsomorphicLayoutEffect","Button","RootComponent","Basic","getInitialShiftData","getMovedShiftData","resolveOffsetYCssStyle","shouldBeClosedByShiftData","placementClassNames","animationStateClassNames","enter","entering","entered","exit","exiting","exited","undefined","Snackbar","placement","children","layout","action","before","after","duration","onActionClick","onClose","mode","subtitle","offsetY","style","getRootRef","restProps","platform","open","setOpen","useState","touched","setTouched","rootRef","focused","inRef","useRef","panGestureRecognizer","shiftDataRef","rafRef","closeTimeoutIdRef","mediaQueries","animationState","animationHandlers","onExited","clearRAF","useCallback","current","cancelAnimationFrame","updateShiftAxisCSSProperties","x","y","requestAnimationFrame","removeProperty","setProperty","close","handleActionClick","event","handleTouchStart","setStartCoords","nativeEvent","offsetWidth","offsetHeight","handleTouchMove","setInitialTimeOnce","setEndCoords","delta","shifted","handleTouchEnd","velocity","closeAfterDelay","setTimeout","preventCloseAfterDelayOnUnmount","clearTimeout","clearUserInteractionDataAfterTouchEnd","useEffect","role","baseClassName","div","className","ref","onTouchStart","onTouchMove","onTouchEnd","onMouseDown","onMouseMove","onMouseUp","onMouseLeave","align","appearance","size","onClick"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/Snackbar/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,KAAK,GACL,SAAS,GACT,cAAc,GACd,QAAQ,GACR,YAAY,CAAC;AAEjB,MAAM,MAAM,SAAS,GAAG;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/Snackbar/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GACzB,WAAW,GACX,KAAK,GACL,SAAS,GACT,cAAc,GACd,QAAQ,GACR,YAAY,CAAC;AAEjB,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Snackbar/types.ts"],"sourcesContent":["export type SnackbarPlacement =\n | 'top-start'\n | 'top'\n | 'top-end'\n | 'bottom-start'\n | 'bottom'\n | 'bottom-end';\n\nexport type ShiftData = {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Snackbar/types.ts"],"sourcesContent":["export type SnackbarPlacement =\n | 'top-start'\n | 'top'\n | 'top-end'\n | 'bottom-start'\n | 'bottom'\n | 'bottom-end';\n\nexport type ShiftData = {\n x: number;\n y: number;\n width: number;\n height: number;\n shifted: boolean;\n isDesktop: boolean;\n};\n"],"names":[],"mappings":"AAQA,WAOE"}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { MediaQueries } from '../../lib/adaptivity';
|
|
1
3
|
import type { ShiftData, SnackbarPlacement } from './types';
|
|
2
|
-
export declare function resolveOffsetYCssStyle(placement: SnackbarPlacement, style?: React.CSSProperties, offsetY?: React.CSSProperties['inset']):
|
|
3
|
-
export declare function getInitialShiftData(width: number, height: number):
|
|
4
|
-
shifted: boolean;
|
|
5
|
-
x: number;
|
|
6
|
-
y: number;
|
|
7
|
-
width: number;
|
|
8
|
-
height: number;
|
|
9
|
-
};
|
|
4
|
+
export declare function resolveOffsetYCssStyle(placement: SnackbarPlacement, style?: React.CSSProperties, offsetY?: React.CSSProperties['inset']): React.CSSProperties | undefined;
|
|
5
|
+
export declare function getInitialShiftData(width: number, height: number, mediaQueries: MediaQueries): ShiftData;
|
|
10
6
|
export declare function getMovedShiftData(placement: SnackbarPlacement, shiftData: ShiftData, nextShift: {
|
|
11
7
|
x: number;
|
|
12
8
|
y: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/Snackbar/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/Snackbar/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5D,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,iBAAiB,EAC5B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,EAC3B,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,mCAevC;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GACzB,SAAS,CASX;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,iBAAiB,EAC5B,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAClC,SAAS,CAuBX;AAID,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,iBAAiB,EAC5B,SAAS,EAAE,SAAS,EACpB,kBAAkB,EAAE,OAAO,EAC3B,QAAQ,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,WA6CnC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
|
|
2
2
|
import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props";
|
|
3
|
+
import * as React from 'react';
|
|
3
4
|
import { rubberbandIfOutOfBounds } from '../../lib/animation';
|
|
4
5
|
export function resolveOffsetYCssStyle(placement, style, offsetY) {
|
|
5
6
|
if (offsetY === undefined) {
|
|
@@ -20,9 +21,10 @@ export function resolveOffsetYCssStyle(placement, style, offsetY) {
|
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
|
-
export function getInitialShiftData(width, height) {
|
|
24
|
+
export function getInitialShiftData(width, height, mediaQueries) {
|
|
24
25
|
return {
|
|
25
26
|
shifted: false,
|
|
27
|
+
isDesktop: mediaQueries.smallTabletPlus.matches,
|
|
26
28
|
x: 0,
|
|
27
29
|
y: 0,
|
|
28
30
|
width,
|
|
@@ -30,27 +32,20 @@ export function getInitialShiftData(width, height) {
|
|
|
30
32
|
};
|
|
31
33
|
}
|
|
32
34
|
export function getMovedShiftData(placement, shiftData, nextShift) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
case 'bottom-start':
|
|
35
|
+
/* istanbul ignore else: TODO чтобы протестировать кейс в блоке else, нужно мокать useMediaQueries(), чтобы перебивать mediaQueries.smallTabletPlus.matches */ if (shiftData.isDesktop) {
|
|
36
|
+
if (placement.endsWith('start')) {
|
|
36
37
|
shiftData.x = rubberbandIfOutOfBounds(nextShift.x, -shiftData.width, 0);
|
|
37
|
-
|
|
38
|
-
case 'top-end':
|
|
39
|
-
case 'bottom-end':
|
|
38
|
+
} else if (placement.endsWith('end')) {
|
|
40
39
|
shiftData.x = rubberbandIfOutOfBounds(nextShift.x, 0, shiftData.width);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
switch(placement){
|
|
44
|
-
case 'top-start':
|
|
45
|
-
case 'top':
|
|
46
|
-
case 'top-end':
|
|
47
|
-
shiftData.y = rubberbandIfOutOfBounds(nextShift.y, -shiftData.height, 0);
|
|
48
|
-
break;
|
|
49
|
-
case 'bottom-start':
|
|
50
|
-
case 'bottom':
|
|
51
|
-
case 'bottom-end':
|
|
40
|
+
}
|
|
41
|
+
if (placement.startsWith('bottom')) {
|
|
52
42
|
shiftData.y = rubberbandIfOutOfBounds(nextShift.y, 0, shiftData.height);
|
|
53
|
-
|
|
43
|
+
}
|
|
44
|
+
} else if (placement.startsWith('bottom')) {
|
|
45
|
+
shiftData.x = rubberbandIfOutOfBounds(nextShift.x, -shiftData.width, 0);
|
|
46
|
+
}
|
|
47
|
+
if (placement.startsWith('top')) {
|
|
48
|
+
shiftData.y = rubberbandIfOutOfBounds(nextShift.y, -shiftData.height, 0);
|
|
54
49
|
}
|
|
55
50
|
shiftData.shifted = true;
|
|
56
51
|
return shiftData;
|
|
@@ -68,31 +63,25 @@ export function shouldBeClosedByShiftData(placement, shiftData, relativeClientRe
|
|
|
68
63
|
x: false,
|
|
69
64
|
y: false
|
|
70
65
|
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
case 'bottom-start':
|
|
66
|
+
/* istanbul ignore else: TODO чтобы протестировать кейс в блоке else, нужно мокать useMediaQueries(), чтобы перебивать mediaQueries.smallTabletPlus.matches */ if (shiftData.isDesktop) {
|
|
67
|
+
if (placement.endsWith('start')) {
|
|
74
68
|
shouldBeClosedThreshold.x = relativeClientRect.x < -relativeClientRect.width / 2;
|
|
75
|
-
shouldBeClosedByVelocity.x = velocity.x < -MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE;
|
|
76
|
-
|
|
77
|
-
case 'top-end':
|
|
78
|
-
case 'bottom-end':
|
|
69
|
+
shouldBeClosedByVelocity.x = relativeClientRect.x < 0 ? velocity.x < -MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;
|
|
70
|
+
} else if (placement.endsWith('end')) {
|
|
79
71
|
shouldBeClosedThreshold.x = relativeClientRect.x > relativeClientRect.width / 2;
|
|
80
|
-
shouldBeClosedByVelocity.x = velocity.x > MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
switch(placement){
|
|
84
|
-
case 'top-start':
|
|
85
|
-
case 'top':
|
|
86
|
-
case 'top-end':
|
|
87
|
-
shouldBeClosedThreshold.y = relativeClientRect.y < -relativeClientRect.height / 2;
|
|
88
|
-
shouldBeClosedByVelocity.y = velocity.y < -MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE;
|
|
89
|
-
break;
|
|
90
|
-
case 'bottom-start':
|
|
91
|
-
case 'bottom':
|
|
92
|
-
case 'bottom-end':
|
|
72
|
+
shouldBeClosedByVelocity.x = relativeClientRect.x > 0 ? velocity.x > MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;
|
|
73
|
+
}
|
|
74
|
+
if (placement.startsWith('bottom')) {
|
|
93
75
|
shouldBeClosedThreshold.y = relativeClientRect.y > relativeClientRect.height / 2;
|
|
94
|
-
shouldBeClosedByVelocity.y = velocity.y > MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE;
|
|
95
|
-
|
|
76
|
+
shouldBeClosedByVelocity.y = relativeClientRect.y > 0 ? velocity.y > MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;
|
|
77
|
+
}
|
|
78
|
+
} else if (placement.startsWith('bottom')) {
|
|
79
|
+
shouldBeClosedThreshold.x = relativeClientRect.x < -relativeClientRect.width / 2;
|
|
80
|
+
shouldBeClosedByVelocity.x = relativeClientRect.x < 0 ? velocity.x < -MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;
|
|
81
|
+
}
|
|
82
|
+
if (placement.startsWith('top')) {
|
|
83
|
+
shouldBeClosedThreshold.y = relativeClientRect.y < -relativeClientRect.height / 2;
|
|
84
|
+
shouldBeClosedByVelocity.y = relativeClientRect.y < 0 ? velocity.y < -MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;
|
|
96
85
|
}
|
|
97
86
|
return shouldBeClosedThreshold.x || shouldBeClosedByVelocity.x || shouldBeClosedThreshold.y || /* istanbul ignore next: подсвечивает жёлтым и пишет "branch not covered" */ shouldBeClosedByVelocity.y;
|
|
98
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/Snackbar/utils.ts"],"sourcesContent":["import { rubberbandIfOutOfBounds } from '../../lib/animation';\nimport type { ShiftData, SnackbarPlacement } from './types';\n\nexport function resolveOffsetYCssStyle(\n placement: SnackbarPlacement,\n style?: React.CSSProperties,\n offsetY?: React.CSSProperties['inset'],\n) {\n if (offsetY === undefined) {\n return style;\n }\n switch (placement) {\n case 'top-start':\n case 'top':\n case 'top-end':\n return { ...style, top: offsetY };\n case 'bottom-start':\n case 'bottom':\n case 'bottom-end':\n return { ...style, bottom: offsetY };\n }\n}\n\nexport function getInitialShiftData(width: number
|
|
1
|
+
{"version":3,"sources":["../../../src/components/Snackbar/utils.ts"],"sourcesContent":["import * as React from 'react';\nimport type { MediaQueries } from '../../lib/adaptivity';\nimport { rubberbandIfOutOfBounds } from '../../lib/animation';\nimport type { ShiftData, SnackbarPlacement } from './types';\n\nexport function resolveOffsetYCssStyle(\n placement: SnackbarPlacement,\n style?: React.CSSProperties,\n offsetY?: React.CSSProperties['inset'],\n) {\n if (offsetY === undefined) {\n return style;\n }\n switch (placement) {\n case 'top-start':\n case 'top':\n case 'top-end':\n return { ...style, top: offsetY };\n case 'bottom-start':\n case 'bottom':\n case 'bottom-end':\n return { ...style, bottom: offsetY };\n }\n}\n\nexport function getInitialShiftData(\n width: number,\n height: number,\n mediaQueries: MediaQueries,\n): ShiftData {\n return {\n shifted: false,\n isDesktop: mediaQueries.smallTabletPlus.matches, // eslint-disable-line no-restricted-properties\n x: 0,\n y: 0,\n width,\n height,\n };\n}\n\nexport function getMovedShiftData(\n placement: SnackbarPlacement,\n shiftData: ShiftData,\n nextShift: { x: number; y: number },\n): ShiftData {\n /* istanbul ignore else: TODO чтобы протестировать кейс в блоке else, нужно мокать useMediaQueries(), чтобы перебивать mediaQueries.smallTabletPlus.matches */\n if (shiftData.isDesktop) {\n if (placement.endsWith('start')) {\n shiftData.x = rubberbandIfOutOfBounds(nextShift.x, -shiftData.width, 0);\n } else if (placement.endsWith('end')) {\n shiftData.x = rubberbandIfOutOfBounds(nextShift.x, 0, shiftData.width);\n }\n\n if (placement.startsWith('bottom')) {\n shiftData.y = rubberbandIfOutOfBounds(nextShift.y, 0, shiftData.height);\n }\n } else if (placement.startsWith('bottom')) {\n shiftData.x = rubberbandIfOutOfBounds(nextShift.x, -shiftData.width, 0);\n }\n\n if (placement.startsWith('top')) {\n shiftData.y = rubberbandIfOutOfBounds(nextShift.y, -shiftData.height, 0);\n }\n\n shiftData.shifted = true;\n\n return shiftData;\n}\n\nconst MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE = 200;\n\nexport function shouldBeClosedByShiftData(\n placement: SnackbarPlacement,\n shiftData: ShiftData,\n relativeClientRect: DOMRect,\n velocity: { x: number; y: number },\n) {\n if (!shiftData.shifted) {\n return false;\n }\n\n const shouldBeClosedThreshold = { x: false, y: false };\n const shouldBeClosedByVelocity = { x: false, y: false };\n\n /* istanbul ignore else: TODO чтобы протестировать кейс в блоке else, нужно мокать useMediaQueries(), чтобы перебивать mediaQueries.smallTabletPlus.matches */\n if (shiftData.isDesktop) {\n if (placement.endsWith('start')) {\n shouldBeClosedThreshold.x = relativeClientRect.x < -relativeClientRect.width / 2;\n shouldBeClosedByVelocity.x =\n relativeClientRect.x < 0 ? velocity.x < -MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;\n } else if (placement.endsWith('end')) {\n shouldBeClosedThreshold.x = relativeClientRect.x > relativeClientRect.width / 2;\n shouldBeClosedByVelocity.x =\n relativeClientRect.x > 0 ? velocity.x > MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;\n }\n\n if (placement.startsWith('bottom')) {\n shouldBeClosedThreshold.y = relativeClientRect.y > relativeClientRect.height / 2;\n shouldBeClosedByVelocity.y =\n relativeClientRect.y > 0 ? velocity.y > MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;\n }\n } else if (placement.startsWith('bottom')) {\n shouldBeClosedThreshold.x = relativeClientRect.x < -relativeClientRect.width / 2;\n shouldBeClosedByVelocity.x =\n relativeClientRect.x < 0 ? velocity.x < -MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;\n }\n\n if (placement.startsWith('top')) {\n shouldBeClosedThreshold.y = relativeClientRect.y < -relativeClientRect.height / 2;\n shouldBeClosedByVelocity.y =\n relativeClientRect.y < 0 ? velocity.y < -MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE : false;\n }\n\n return (\n shouldBeClosedThreshold.x ||\n shouldBeClosedByVelocity.x ||\n shouldBeClosedThreshold.y ||\n /* istanbul ignore next: подсвечивает жёлтым и пишет \"branch not covered\" */\n shouldBeClosedByVelocity.y\n );\n}\n"],"names":["React","rubberbandIfOutOfBounds","resolveOffsetYCssStyle","placement","style","offsetY","undefined","top","bottom","getInitialShiftData","width","height","mediaQueries","shifted","isDesktop","smallTabletPlus","matches","x","y","getMovedShiftData","shiftData","nextShift","endsWith","startsWith","MINIMUM_PAN_GESTURE_FOR_TRIGGER_CLOSE","shouldBeClosedByShiftData","relativeClientRect","velocity","shouldBeClosedThreshold","shouldBeClosedByVelocity"],"mappings":"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"}
|