@hh.ru/magritte-ui-scrollable-container 6.2.1 → 6.2.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.
@@ -1 +1 @@
1
- {"version":3,"file":"ObservableValue.js","sources":["../src/ObservableValue.ts"],"sourcesContent":["export interface ObservableValueInterface<T> {\n get(): T;\n set(value: T): void;\n on(event: 'change', callback: (value: T) => void): VoidFunction;\n}\n\nexport class ObservableValue<T> implements ObservableValueInterface<T> {\n private value: T;\n private listeners = new Set<(value: T) => void>();\n\n constructor(initial: T) {\n this.value = initial;\n }\n\n get(): T {\n return this.value;\n }\n\n set(value: T): void {\n if (this.value !== value || Array.isArray(this.value)) {\n this.value = value;\n this.listeners.forEach((listener) => listener(value));\n }\n }\n\n on(_event: 'change', callback: (value: T) => void): VoidFunction {\n this.listeners.add(callback);\n return () => this.listeners.delete(callback);\n }\n}\n"],"names":[],"mappings":"MAMa,eAAe,CAAA;AAChB,IAAA,KAAK,CAAI;AACT,IAAA,SAAS,GAAG,IAAI,GAAG,EAAsB,CAAC;AAElD,IAAA,WAAA,CAAY,OAAU,EAAA;AAClB,QAAA,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC;KACxB;IAED,GAAG,GAAA;QACC,OAAO,IAAI,CAAC,KAAK,CAAC;KACrB;AAED,IAAA,GAAG,CAAC,KAAQ,EAAA;AACR,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACnD,YAAA,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;AACnB,YAAA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;SACzD;KACJ;IAED,EAAE,CAAC,MAAgB,EAAE,QAA4B,EAAA;AAC7C,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;KAChD;AACJ;;;;"}
1
+ {"version":3,"file":"ObservableValue.js","sources":["src/ObservableValue.ts"],"sourcesContent":["export interface ObservableValueInterface<T> {\n get(): T;\n set(value: T): void;\n on(event: 'change', callback: (value: T) => void): VoidFunction;\n}\n\nexport class ObservableValue<T> implements ObservableValueInterface<T> {\n private value: T;\n private listeners = new Set<(value: T) => void>();\n\n constructor(initial: T) {\n this.value = initial;\n }\n\n get(): T {\n return this.value;\n }\n\n set(value: T): void {\n if (this.value !== value || Array.isArray(this.value)) {\n this.value = value;\n this.listeners.forEach((listener) => listener(value));\n }\n }\n\n on(_event: 'change', callback: (value: T) => void): VoidFunction {\n this.listeners.add(callback);\n return () => this.listeners.delete(callback);\n }\n}\n"],"names":[],"mappings":"MAMa,eAAe,CAAA;AAChB,IAAA,KAAK,CAAI;AACT,IAAA,SAAS,GAAG,IAAI,GAAG,EAAsB,CAAC;AAElD,IAAA,WAAA,CAAY,OAAU,EAAA;AAClB,QAAA,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC;KACxB;IAED,GAAG,GAAA;QACC,OAAO,IAAI,CAAC,KAAK,CAAC;KACrB;AAED,IAAA,GAAG,CAAC,KAAQ,EAAA;AACR,QAAA,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACnD,YAAA,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;AACnB,YAAA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;SACzD;KACJ;IAED,EAAE,CAAC,MAAgB,EAAE,QAA4B,EAAA;AAC7C,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;KAChD;AACJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollStateProvider.js","sources":["../src/ScrollStateProvider.tsx"],"sourcesContent":["import { type RefObject, createContext, useContext } from 'react';\nimport { MotionValue } from 'motion/react';\n\nimport { ObservableValue } from '@hh.ru/magritte-ui-scrollable-container/ObservableValue';\nimport { type ItemWithOffset, type ScrollSnapAlign } from '@hh.ru/magritte-ui-scrollable-container/types';\n\nexport interface ScrollState {\n /** ширина контента, которая складывается из ширины элементов галереи */\n contentWidth: ObservableValue<number>;\n /** ширина вьюпорта для просмотра галереи */\n viewportWidth: ObservableValue<number>;\n /** элементы галереи */\n items: ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>;\n /** текущая позиция */\n scrollPosition: MotionValue<number>;\n /** Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле */\n scrollSnapAlign: ScrollSnapAlign;\n /**\n * флаг коррекции \"по умолчанию\"\n * возникает при использовании \"стандартных\" (по спеке) кнопок в fade\n */\n defaultButtonsCorrection: ObservableValue<number>;\n /** значения коррекции */\n leftCorrection: ObservableValue<number>;\n rightCorrection: ObservableValue<number>;\n /** индекс элемента для отложенного скролла */\n indexForDeferScroll: number;\n}\n\nexport const createScrollState = (): ScrollState => ({\n contentWidth: new ObservableValue(0),\n viewportWidth: new ObservableValue(0),\n items: new ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>([]),\n scrollPosition: new MotionValue(0),\n defaultButtonsCorrection: new ObservableValue(0),\n leftCorrection: new ObservableValue(0),\n rightCorrection: new ObservableValue(0),\n indexForDeferScroll: -1,\n scrollSnapAlign: 'none',\n});\n\nexport const ScrollStateContext = createContext<ScrollState>(createScrollState());\n\nexport const useScrollState = (): ScrollState => useContext(ScrollStateContext);\n"],"names":[],"mappings":";;;;AA6Ba,MAAA,iBAAiB,GAAG,OAAoB;AACjD,IAAA,YAAY,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACpC,IAAA,aAAa,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACrC,IAAA,KAAK,EAAE,IAAI,eAAe,CAA4C,EAAE,CAAC;AACzE,IAAA,cAAc,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC;AAClC,IAAA,wBAAwB,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AAChD,IAAA,cAAc,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACtC,IAAA,eAAe,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;IACvC,mBAAmB,EAAE,CAAC,CAAC;AACvB,IAAA,eAAe,EAAE,MAAM;AAC1B,CAAA,EAAE;MAEU,kBAAkB,GAAG,aAAa,CAAc,iBAAiB,EAAE,EAAE;AAErE,MAAA,cAAc,GAAG,MAAmB,UAAU,CAAC,kBAAkB;;;;"}
1
+ {"version":3,"file":"ScrollStateProvider.js","sources":["src/ScrollStateProvider.tsx"],"sourcesContent":["import { type RefObject, createContext, useContext } from 'react';\nimport { MotionValue } from 'motion/react';\n\nimport { ObservableValue } from '@hh.ru/magritte-ui-scrollable-container/ObservableValue';\nimport { type ItemWithOffset, type ScrollSnapAlign } from '@hh.ru/magritte-ui-scrollable-container/types';\n\nexport interface ScrollState {\n /** ширина контента, которая складывается из ширины элементов галереи */\n contentWidth: ObservableValue<number>;\n /** ширина вьюпорта для просмотра галереи */\n viewportWidth: ObservableValue<number>;\n /** элементы галереи */\n items: ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>;\n /** текущая позиция */\n scrollPosition: MotionValue<number>;\n /** Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле */\n scrollSnapAlign: ScrollSnapAlign;\n /**\n * флаг коррекции \"по умолчанию\"\n * возникает при использовании \"стандартных\" (по спеке) кнопок в fade\n */\n defaultButtonsCorrection: ObservableValue<number>;\n /** значения коррекции */\n leftCorrection: ObservableValue<number>;\n rightCorrection: ObservableValue<number>;\n /** индекс элемента для отложенного скролла */\n indexForDeferScroll: number;\n}\n\nexport const createScrollState = (): ScrollState => ({\n contentWidth: new ObservableValue(0),\n viewportWidth: new ObservableValue(0),\n items: new ObservableValue<RefObject<HTMLElement & ItemWithOffset>[]>([]),\n scrollPosition: new MotionValue(0),\n defaultButtonsCorrection: new ObservableValue(0),\n leftCorrection: new ObservableValue(0),\n rightCorrection: new ObservableValue(0),\n indexForDeferScroll: -1,\n scrollSnapAlign: 'none',\n});\n\nexport const ScrollStateContext = createContext<ScrollState>(createScrollState());\n\nexport const useScrollState = (): ScrollState => useContext(ScrollStateContext);\n"],"names":[],"mappings":";;;;AA6Ba,MAAA,iBAAiB,GAAG,OAAoB;AACjD,IAAA,YAAY,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACpC,IAAA,aAAa,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACrC,IAAA,KAAK,EAAE,IAAI,eAAe,CAA4C,EAAE,CAAC;AACzE,IAAA,cAAc,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC;AAClC,IAAA,wBAAwB,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AAChD,IAAA,cAAc,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;AACtC,IAAA,eAAe,EAAE,IAAI,eAAe,CAAC,CAAC,CAAC;IACvC,mBAAmB,EAAE,CAAC,CAAC;AACvB,IAAA,eAAe,EAAE,MAAM;AAC1B,CAAA,EAAE;MAEU,kBAAkB,GAAG,aAAa,CAAc,iBAAiB,EAAE,EAAE;AAErE,MAAA,cAAc,GAAG,MAAmB,UAAU,CAAC,kBAAkB;;;;"}
@@ -11,7 +11,7 @@ import { ScrollableContainerGallery } from './ScrollableContainerGallery.js';
11
11
  import { ScrollableItem } from './ScrollableItem.js';
12
12
  import { useScrollableControlsWithState } from './useScrollableControls.js';
13
13
  import { getActualCorrection, useInitOnce } from './utils.js';
14
- import { s as styles } from './scrollableContainer-Dl-Nl71V.js';
14
+ import { s as styles } from './scrollableContainer-Co7tlvFk.js';
15
15
  import 'motion/react';
16
16
  import './ObservableValue.js';
17
17
  import '@hh.ru/magritte-common-use-translation';
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollableContainer.js","sources":["../src/ScrollableContainer.tsx"],"sourcesContent":["import { forwardRef, useImperativeHandle, useMemo, type CSSProperties } from 'react';\nimport classnames from 'classnames';\n\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { ScrollStateContext, createScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n ScrollableContainerLeft,\n ScrollableContainerRight,\n} from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerButton';\nimport { ScrollableContainerDefaultLayout } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerDefaultLayout';\nimport { ScrollableContainerDotPages } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerDotPages';\nimport { ScrollableContainerGallery } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';\nimport { ScrollableItem } from '@hh.ru/magritte-ui-scrollable-container/ScrollableItem';\nimport { ScrollableContainerProps, ScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControlsWithState } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nimport { getActualCorrection, useInitOnce } from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nimport styles from './scrollableContainer.less';\n\nexport interface ScrollableContainerComponents {\n Left: typeof ScrollableContainerLeft;\n Right: typeof ScrollableContainerRight;\n Item: typeof ScrollableItem;\n DefaultLayout: typeof ScrollableContainerDefaultLayout;\n Gallery: typeof ScrollableContainerGallery;\n DotPages: typeof ScrollableContainerDotPages;\n}\n\nconst ScrollableContainerComponent = forwardRef<ScrollableControls, ScrollableContainerProps>(\n (\n {\n children,\n scrollSnapAlign = 'none',\n correction = 0,\n correctionXS,\n correctionS,\n correctionM,\n correctionL,\n correctionXL,\n correctionXXL,\n correctionLeftXS,\n correctionLeftS,\n correctionLeftM,\n correctionLeftL,\n correctionLeftXL,\n correctionLeftXXL,\n correctionRightXS,\n correctionRightS,\n correctionRightM,\n correctionRightL,\n correctionRightXL,\n correctionRightXXL,\n style,\n ...props\n },\n controlsRef\n ) => {\n const breakpoint = useBreakpoint();\n const spacingCorrectionStyles = useMemo(() => {\n const correctionValue = getActualCorrection(\n {\n correction,\n correctionXS,\n correctionS,\n correctionM,\n correctionL,\n correctionXL,\n correctionXXL,\n correctionLeftXS,\n correctionLeftS,\n correctionLeftM,\n correctionLeftL,\n correctionLeftXL,\n correctionLeftXXL,\n correctionRightXS,\n correctionRightS,\n correctionRightM,\n correctionRightL,\n correctionRightXL,\n correctionRightXXL,\n },\n breakpoint.breakpoint\n );\n return {\n marginLeft: -correctionValue.leftCorrection,\n marginRight: -correctionValue.rightCorrection,\n paddingLeft: correctionValue.leftCorrection,\n paddingRight: correctionValue.rightCorrection,\n };\n }, [\n correction,\n correctionXS,\n correctionS,\n correctionM,\n correctionL,\n correctionXL,\n correctionXXL,\n correctionLeftXS,\n correctionLeftS,\n correctionLeftM,\n correctionLeftL,\n correctionLeftXL,\n correctionLeftXXL,\n correctionRightXS,\n correctionRightS,\n correctionRightM,\n correctionRightL,\n correctionRightXL,\n correctionRightXXL,\n breakpoint.breakpoint,\n ]);\n\n const scrollState = useInitOnce(createScrollState);\n scrollState.scrollSnapAlign = scrollSnapAlign;\n scrollState.leftCorrection.set(spacingCorrectionStyles.paddingLeft);\n scrollState.rightCorrection.set(spacingCorrectionStyles.paddingRight);\n\n const controls = useScrollableControlsWithState(scrollState);\n useImperativeHandle(controlsRef, () => controls, [controls]);\n\n return (\n <div\n role=\"region\"\n data-qa=\"scrollable-container__wrapper\"\n className={classnames(styles.scrollWrapper)}\n style={{\n ...({\n '--magritte-ui-scrollabe-container-ml': `${spacingCorrectionStyles.marginLeft}px`,\n '--magritte-ui-scrollabe-container-mr': `${spacingCorrectionStyles.marginRight}px`,\n '--magritte-ui-scrollabe-container-pl': `${spacingCorrectionStyles.paddingLeft}px`,\n '--magritte-ui-scrollabe-container-pr': `${spacingCorrectionStyles.paddingRight}px`,\n } as CSSProperties),\n ...(style || {}),\n }}\n {...props}\n >\n <ScrollStateContext.Provider value={scrollState}>{children}</ScrollStateContext.Provider>\n </div>\n );\n }\n);\n\nScrollableContainerComponent.displayName = 'ScrollableContainer';\n\nconst ScrollableContainer = ScrollableContainerComponent as typeof ScrollableContainerComponent &\n ScrollableContainerComponents;\n\nScrollableContainer.Left = ScrollableContainerLeft;\nScrollableContainer.Right = ScrollableContainerRight;\nScrollableContainer.Item = ScrollableItem;\nScrollableContainer.Gallery = ScrollableContainerGallery;\nScrollableContainer.DefaultLayout = ScrollableContainerDefaultLayout;\nScrollableContainer.DotPages = ScrollableContainerDotPages;\n\nexport { ScrollableContainer };\n"],"names":["_jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAM,4BAA4B,GAAG,UAAU,CAC3C,CACI,EACI,QAAQ,EACR,eAAe,GAAG,MAAM,EACxB,UAAU,GAAG,CAAC,EACd,YAAY,EACZ,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,EACL,GAAG,KAAK,EACX,EACD,WAAW,KACX;AACA,IAAA,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;AACnC,IAAA,MAAM,uBAAuB,GAAG,OAAO,CAAC,MAAK;QACzC,MAAM,eAAe,GAAG,mBAAmB,CACvC;YACI,UAAU;YACV,YAAY;YACZ,WAAW;YACX,WAAW;YACX,WAAW;YACX,YAAY;YACZ,aAAa;YACb,gBAAgB;YAChB,eAAe;YACf,eAAe;YACf,eAAe;YACf,gBAAgB;YAChB,iBAAiB;YACjB,iBAAiB;YACjB,gBAAgB;YAChB,gBAAgB;YAChB,gBAAgB;YAChB,iBAAiB;YACjB,kBAAkB;AACrB,SAAA,EACD,UAAU,CAAC,UAAU,CACxB,CAAC;QACF,OAAO;AACH,YAAA,UAAU,EAAE,CAAC,eAAe,CAAC,cAAc;AAC3C,YAAA,WAAW,EAAE,CAAC,eAAe,CAAC,eAAe;YAC7C,WAAW,EAAE,eAAe,CAAC,cAAc;YAC3C,YAAY,EAAE,eAAe,CAAC,eAAe;SAChD,CAAC;AACN,KAAC,EAAE;QACC,UAAU;QACV,YAAY;QACZ,WAAW;QACX,WAAW;QACX,WAAW;QACX,YAAY;QACZ,aAAa;QACb,gBAAgB;QAChB,eAAe;QACf,eAAe;QACf,eAAe;QACf,gBAAgB;QAChB,iBAAiB;QACjB,iBAAiB;QACjB,gBAAgB;QAChB,gBAAgB;QAChB,gBAAgB;QAChB,iBAAiB;QACjB,kBAAkB;AAClB,QAAA,UAAU,CAAC,UAAU;AACxB,KAAA,CAAC,CAAC;AAEH,IAAA,MAAM,WAAW,GAAG,WAAW,CAAC,iBAAiB,CAAC,CAAC;AACnD,IAAA,WAAW,CAAC,eAAe,GAAG,eAAe,CAAC;IAC9C,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,uBAAuB,CAAC,WAAW,CAAC,CAAC;IACpE,WAAW,CAAC,eAAe,CAAC,GAAG,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC;AAEtE,IAAA,MAAM,QAAQ,GAAG,8BAA8B,CAAC,WAAW,CAAC,CAAC;AAC7D,IAAA,mBAAmB,CAAC,WAAW,EAAE,MAAM,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE7D,IAAA,QACIA,GACI,CAAA,KAAA,EAAA,EAAA,IAAI,EAAC,QAAQ,EAAA,SAAA,EACL,+BAA+B,EACvC,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,EAC3C,KAAK,EAAE;YACH,GAAI;AACA,gBAAA,sCAAsC,EAAE,CAAA,EAAG,uBAAuB,CAAC,UAAU,CAAI,EAAA,CAAA;AACjF,gBAAA,sCAAsC,EAAE,CAAA,EAAG,uBAAuB,CAAC,WAAW,CAAI,EAAA,CAAA;AAClF,gBAAA,sCAAsC,EAAE,CAAA,EAAG,uBAAuB,CAAC,WAAW,CAAI,EAAA,CAAA;AAClF,gBAAA,sCAAsC,EAAE,CAAA,EAAG,uBAAuB,CAAC,YAAY,CAAI,EAAA,CAAA;AACpE,aAAA;AACnB,YAAA,IAAI,KAAK,IAAI,EAAE;AAClB,SAAA,EAAA,GACG,KAAK,EAAA,QAAA,EAETA,GAAC,CAAA,kBAAkB,CAAC,QAAQ,EAAA,EAAC,KAAK,EAAE,WAAW,EAAG,QAAA,EAAA,QAAQ,EAA+B,CAAA,EAAA,CACvF,EACR;AACN,CAAC,CACJ,CAAC;AAEF,4BAA4B,CAAC,WAAW,GAAG,qBAAqB,CAAC;AAE3D,MAAA,mBAAmB,GAAG,6BACM;AAElC,mBAAmB,CAAC,IAAI,GAAG,uBAAuB,CAAC;AACnD,mBAAmB,CAAC,KAAK,GAAG,wBAAwB,CAAC;AACrD,mBAAmB,CAAC,IAAI,GAAG,cAAc,CAAC;AAC1C,mBAAmB,CAAC,OAAO,GAAG,0BAA0B,CAAC;AACzD,mBAAmB,CAAC,aAAa,GAAG,gCAAgC,CAAC;AACrE,mBAAmB,CAAC,QAAQ,GAAG,2BAA2B;;;;"}
1
+ {"version":3,"file":"ScrollableContainer.js","sources":["src/ScrollableContainer.tsx"],"sourcesContent":["import { forwardRef, useImperativeHandle, useMemo, type CSSProperties } from 'react';\nimport classnames from 'classnames';\n\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { ScrollStateContext, createScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n ScrollableContainerLeft,\n ScrollableContainerRight,\n} from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerButton';\nimport { ScrollableContainerDefaultLayout } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerDefaultLayout';\nimport { ScrollableContainerDotPages } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerDotPages';\nimport { ScrollableContainerGallery } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';\nimport { ScrollableItem } from '@hh.ru/magritte-ui-scrollable-container/ScrollableItem';\nimport { ScrollableContainerProps, ScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControlsWithState } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nimport { getActualCorrection, useInitOnce } from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nimport styles from './scrollableContainer.less';\n\nexport interface ScrollableContainerComponents {\n Left: typeof ScrollableContainerLeft;\n Right: typeof ScrollableContainerRight;\n Item: typeof ScrollableItem;\n DefaultLayout: typeof ScrollableContainerDefaultLayout;\n Gallery: typeof ScrollableContainerGallery;\n DotPages: typeof ScrollableContainerDotPages;\n}\n\nconst ScrollableContainerComponent = forwardRef<ScrollableControls, ScrollableContainerProps>(\n (\n {\n children,\n scrollSnapAlign = 'none',\n correction = 0,\n correctionXS,\n correctionS,\n correctionM,\n correctionL,\n correctionXL,\n correctionXXL,\n correctionLeftXS,\n correctionLeftS,\n correctionLeftM,\n correctionLeftL,\n correctionLeftXL,\n correctionLeftXXL,\n correctionRightXS,\n correctionRightS,\n correctionRightM,\n correctionRightL,\n correctionRightXL,\n correctionRightXXL,\n style,\n ...props\n },\n controlsRef\n ) => {\n const breakpoint = useBreakpoint();\n const spacingCorrectionStyles = useMemo(() => {\n const correctionValue = getActualCorrection(\n {\n correction,\n correctionXS,\n correctionS,\n correctionM,\n correctionL,\n correctionXL,\n correctionXXL,\n correctionLeftXS,\n correctionLeftS,\n correctionLeftM,\n correctionLeftL,\n correctionLeftXL,\n correctionLeftXXL,\n correctionRightXS,\n correctionRightS,\n correctionRightM,\n correctionRightL,\n correctionRightXL,\n correctionRightXXL,\n },\n breakpoint.breakpoint\n );\n return {\n marginLeft: -correctionValue.leftCorrection,\n marginRight: -correctionValue.rightCorrection,\n paddingLeft: correctionValue.leftCorrection,\n paddingRight: correctionValue.rightCorrection,\n };\n }, [\n correction,\n correctionXS,\n correctionS,\n correctionM,\n correctionL,\n correctionXL,\n correctionXXL,\n correctionLeftXS,\n correctionLeftS,\n correctionLeftM,\n correctionLeftL,\n correctionLeftXL,\n correctionLeftXXL,\n correctionRightXS,\n correctionRightS,\n correctionRightM,\n correctionRightL,\n correctionRightXL,\n correctionRightXXL,\n breakpoint.breakpoint,\n ]);\n\n const scrollState = useInitOnce(createScrollState);\n scrollState.scrollSnapAlign = scrollSnapAlign;\n scrollState.leftCorrection.set(spacingCorrectionStyles.paddingLeft);\n scrollState.rightCorrection.set(spacingCorrectionStyles.paddingRight);\n\n const controls = useScrollableControlsWithState(scrollState);\n useImperativeHandle(controlsRef, () => controls, [controls]);\n\n return (\n <div\n role=\"region\"\n data-qa=\"scrollable-container__wrapper\"\n className={classnames(styles.scrollWrapper)}\n style={{\n ...({\n '--magritte-ui-scrollabe-container-ml': `${spacingCorrectionStyles.marginLeft}px`,\n '--magritte-ui-scrollabe-container-mr': `${spacingCorrectionStyles.marginRight}px`,\n '--magritte-ui-scrollabe-container-pl': `${spacingCorrectionStyles.paddingLeft}px`,\n '--magritte-ui-scrollabe-container-pr': `${spacingCorrectionStyles.paddingRight}px`,\n } as CSSProperties),\n ...(style || {}),\n }}\n {...props}\n >\n <ScrollStateContext.Provider value={scrollState}>{children}</ScrollStateContext.Provider>\n </div>\n );\n }\n);\n\nScrollableContainerComponent.displayName = 'ScrollableContainer';\n\nconst ScrollableContainer = ScrollableContainerComponent as typeof ScrollableContainerComponent &\n ScrollableContainerComponents;\n\nScrollableContainer.Left = ScrollableContainerLeft;\nScrollableContainer.Right = ScrollableContainerRight;\nScrollableContainer.Item = ScrollableItem;\nScrollableContainer.Gallery = ScrollableContainerGallery;\nScrollableContainer.DefaultLayout = ScrollableContainerDefaultLayout;\nScrollableContainer.DotPages = ScrollableContainerDotPages;\n\nexport { ScrollableContainer };\n"],"names":["_jsx"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollableContainerButton.js","sources":["../src/ScrollableContainerButton.tsx"],"sourcesContent":["import { cloneElement, isValidElement, type FC } from 'react';\n\nimport type { ControlWithClick, ScrollableContainerButtonProps } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\n\nconst ScrolllableContainerScrollButton: FC<ScrollableContainerButtonProps & { toRight?: boolean }> = ({\n children,\n toRight = false,\n}) => {\n const { scrollLeft, scrollRight } = useScrollableControls();\n if (!isValidElement<ControlWithClick>(children)) {\n return null;\n }\n const defaultDataQa = `scrollable-container__scroll-button-${toRight ? 'right' : 'left'}`;\n return cloneElement(children, {\n 'data-qa': children.props['data-qa'] || defaultDataQa,\n onClick: () => (toRight ? scrollRight() : scrollLeft()),\n });\n};\n\nexport const ScrollableContainerLeft: FC<ScrollableContainerButtonProps> = ({ children }) => (\n <ScrolllableContainerScrollButton>{children}</ScrolllableContainerScrollButton>\n);\n\nexport const ScrollableContainerRight: FC<ScrollableContainerButtonProps> = ({ children }) => (\n <ScrolllableContainerScrollButton toRight>{children}</ScrolllableContainerScrollButton>\n);\n"],"names":["_jsx"],"mappings":";;;;;;;;;;;AAKA,MAAM,gCAAgC,GAA+D,CAAC,EAClG,QAAQ,EACR,OAAO,GAAG,KAAK,GAClB,KAAI;IACD,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,qBAAqB,EAAE,CAAC;AAC5D,IAAA,IAAI,CAAC,cAAc,CAAmB,QAAQ,CAAC,EAAE;AAC7C,QAAA,OAAO,IAAI,CAAC;KACf;AACD,IAAA,MAAM,aAAa,GAAG,CAAuC,oCAAA,EAAA,OAAO,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC;IAC1F,OAAO,YAAY,CAAC,QAAQ,EAAE;QAC1B,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,aAAa;AACrD,QAAA,OAAO,EAAE,OAAO,OAAO,GAAG,WAAW,EAAE,GAAG,UAAU,EAAE,CAAC;AAC1D,KAAA,CAAC,CAAC;AACP,CAAC,CAAC;AAEW,MAAA,uBAAuB,GAAuC,CAAC,EAAE,QAAQ,EAAE,MACpFA,GAAC,CAAA,gCAAgC,cAAE,QAAQ,EAAA,CAAoC,EACjF;MAEW,wBAAwB,GAAuC,CAAC,EAAE,QAAQ,EAAE,MACrFA,GAAA,CAAC,gCAAgC,EAAC,EAAA,OAAO,kBAAE,QAAQ,EAAA,CAAoC;;;;"}
1
+ {"version":3,"file":"ScrollableContainerButton.js","sources":["src/ScrollableContainerButton.tsx"],"sourcesContent":["import { cloneElement, isValidElement, type FC } from 'react';\n\nimport type { ControlWithClick, ScrollableContainerButtonProps } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\n\nconst ScrolllableContainerScrollButton: FC<ScrollableContainerButtonProps & { toRight?: boolean }> = ({\n children,\n toRight = false,\n}) => {\n const { scrollLeft, scrollRight } = useScrollableControls();\n if (!isValidElement<ControlWithClick>(children)) {\n return null;\n }\n const defaultDataQa = `scrollable-container__scroll-button-${toRight ? 'right' : 'left'}`;\n return cloneElement(children, {\n 'data-qa': children.props['data-qa'] || defaultDataQa,\n onClick: () => (toRight ? scrollRight() : scrollLeft()),\n });\n};\n\nexport const ScrollableContainerLeft: FC<ScrollableContainerButtonProps> = ({ children }) => (\n <ScrolllableContainerScrollButton>{children}</ScrolllableContainerScrollButton>\n);\n\nexport const ScrollableContainerRight: FC<ScrollableContainerButtonProps> = ({ children }) => (\n <ScrolllableContainerScrollButton toRight>{children}</ScrolllableContainerScrollButton>\n);\n"],"names":["_jsx"],"mappings":";;;;;;;;;;;AAKA,MAAM,gCAAgC,GAA+D,CAAC,EAClG,QAAQ,EACR,OAAO,GAAG,KAAK,GAClB,KAAI;IACD,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,qBAAqB,EAAE,CAAC;AAC5D,IAAA,IAAI,CAAC,cAAc,CAAmB,QAAQ,CAAC,EAAE;AAC7C,QAAA,OAAO,IAAI,CAAC;KACf;AACD,IAAA,MAAM,aAAa,GAAG,CAAuC,oCAAA,EAAA,OAAO,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC;IAC1F,OAAO,YAAY,CAAC,QAAQ,EAAE;QAC1B,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,aAAa;AACrD,QAAA,OAAO,EAAE,OAAO,OAAO,GAAG,WAAW,EAAE,GAAG,UAAU,EAAE,CAAC;AAC1D,KAAA,CAAC,CAAC;AACP,CAAC,CAAC;AAEW,MAAA,uBAAuB,GAAuC,CAAC,EAAE,QAAQ,EAAE,MACpFA,GAAC,CAAA,gCAAgC,cAAE,QAAQ,EAAA,CAAoC,EACjF;MAEW,wBAAwB,GAAuC,CAAC,EAAE,QAAQ,EAAE,MACrFA,GAAA,CAAC,gCAAgC,EAAC,EAAA,OAAO,kBAAE,QAAQ,EAAA,CAAoC;;;;"}
@@ -9,7 +9,7 @@ import { ChevronLeftOutlinedSize24, ChevronRightOutlinedSize24 } from '@hh.ru/ma
9
9
  import { useScrollState } from './ScrollStateProvider.js';
10
10
  import { ScrollableContainerLeft, ScrollableContainerRight } from './ScrollableContainerButton.js';
11
11
  import { BREAKPOINTS_LIST, NO_BUTTONS_START_FROM_BREAKPOINT, useInitOnce } from './utils.js';
12
- import { s as styles } from './scrollableContainer-Dl-Nl71V.js';
12
+ import { s as styles } from './scrollableContainer-Co7tlvFk.js';
13
13
  import './ObservableValue.js';
14
14
  import './useScrollableControls.js';
15
15
  import '@hh.ru/magritte-internal-custom-scroll';
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollableContainerDefaultLayout.js","sources":["../src/ScrollableContainerDefaultLayout.tsx"],"sourcesContent":["import { type FC, useEffect } from 'react';\nimport classnames from 'classnames';\nimport { useMotionValue, motion } from 'motion/react';\n\nimport { useTranslation } from '@hh.ru/magritte-common-use-translation';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { ChevronRightOutlinedSize24, ChevronLeftOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n ScrollableContainerLeft,\n ScrollableContainerRight,\n} from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerButton';\nimport type { ScrollableContainerDefaultLayoutProps } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport {\n BREAKPOINTS_LIST,\n NO_BUTTONS_START_FROM_BREAKPOINT,\n useInitOnce,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nimport styles from './scrollableContainer.less';\n\nconst BUTTON_WIDTH = 44;\n\nexport const ScrollableContainerDefaultLayout: FC<ScrollableContainerDefaultLayoutProps> = ({\n children,\n leftButtonAriaLabel: _leftAriaLabel,\n rightButtonAriaLabel: _rightAriaLabel,\n leftAriaControls,\n rightAriaControls,\n}) => {\n const scrollState = useScrollState();\n const displayLeftButton = useMotionValue<'none' | 'block'>('none');\n const displayRightButton = useMotionValue<'none' | 'block'>('none');\n const mask = useMotionValue<string | number>('none');\n\n const breakpoint = useBreakpoint();\n const breakpointIndex = BREAKPOINTS_LIST.indexOf(breakpoint.breakpoint);\n const noButtonBreakpointIndex = BREAKPOINTS_LIST.indexOf(NO_BUTTONS_START_FROM_BREAKPOINT);\n const enableDefaultButtonsByBreakpoint = breakpointIndex > noButtonBreakpointIndex;\n\n const leftAriaLabelTrl = useTranslation('ScrollableContainer', 'left');\n const leftButtonAriaLabel = _leftAriaLabel ?? leftAriaLabelTrl;\n const rightAriaLabelTrl = useTranslation('ScrollableContainer', 'right');\n const rightButtonAriaLabel = _rightAriaLabel ?? rightAriaLabelTrl;\n\n const updateFadeAndButtons = useInitOnce(() => () => {\n const position = scrollState.scrollPosition.get();\n const contentWidth = scrollState.contentWidth.get();\n const viewportWidth = scrollState.viewportWidth.get();\n\n const showLeftButton = position < 0;\n const showRightButton = Math.abs(position) < Math.max(0, contentWidth - viewportWidth);\n\n displayLeftButton.set(showLeftButton ? 'block' : 'none');\n displayRightButton.set(showRightButton ? 'block' : 'none');\n\n if (showLeftButton && showRightButton) {\n mask.set('var(--both-sides-mask)');\n } else if (showLeftButton) {\n mask.set('var(--left-fade-mask)');\n } else if (showRightButton) {\n mask.set('var(--right-fade-mask)');\n } else {\n mask.set('none');\n }\n });\n\n useEffect(() => {\n updateFadeAndButtons();\n const unsubscribe = [\n scrollState.scrollPosition.on('change', updateFadeAndButtons),\n scrollState.contentWidth.on('change', updateFadeAndButtons),\n scrollState.viewportWidth.on('change', updateFadeAndButtons),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState, updateFadeAndButtons]);\n\n useEffect(() => {\n scrollState.defaultButtonsCorrection.set(enableDefaultButtonsByBreakpoint ? BUTTON_WIDTH : 0);\n return () => {\n scrollState.defaultButtonsCorrection.set(0);\n };\n }, [scrollState, enableDefaultButtonsByBreakpoint]);\n\n return (\n <div className={styles.scrollButtonsContainer}>\n <motion.div\n className={classnames(styles.scrollButton, styles.scrollButtonLeft)}\n style={{ display: enableDefaultButtonsByBreakpoint ? displayLeftButton : 'none' }}\n >\n <ScrollableContainerLeft>\n <ChevronLeftOutlinedSize24\n padding={8}\n borderRadius=\"halfHeight\"\n initialColor=\"secondary\"\n backgroundStyle=\"secondary\"\n aria-label={leftButtonAriaLabel}\n aria-controls={leftAriaControls}\n />\n </ScrollableContainerLeft>\n </motion.div>\n <motion.div\n className={styles.scrollButtons}\n style={{\n WebkitMask: enableDefaultButtonsByBreakpoint ? mask : 'none',\n mask: enableDefaultButtonsByBreakpoint ? mask : 'none',\n }}\n data-qa=\"scrollable-container__fade\"\n >\n {children}\n </motion.div>\n <motion.div\n className={classnames(styles.scrollButton, styles.scrollButtonRight)}\n style={{ display: enableDefaultButtonsByBreakpoint ? displayRightButton : 'none' }}\n >\n <ScrollableContainerRight>\n <ChevronRightOutlinedSize24\n padding={8}\n borderRadius=\"halfHeight\"\n initialColor=\"secondary\"\n backgroundStyle=\"secondary\"\n aria-label={rightButtonAriaLabel}\n aria-controls={rightAriaControls}\n />\n </ScrollableContainerRight>\n </motion.div>\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"ScrollableContainerDefaultLayout.js","sources":["src/ScrollableContainerDefaultLayout.tsx"],"sourcesContent":["import { type FC, useEffect } from 'react';\nimport classnames from 'classnames';\nimport { useMotionValue, motion } from 'motion/react';\n\nimport { useTranslation } from '@hh.ru/magritte-common-use-translation';\nimport { useBreakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { ChevronRightOutlinedSize24, ChevronLeftOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n ScrollableContainerLeft,\n ScrollableContainerRight,\n} from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerButton';\nimport type { ScrollableContainerDefaultLayoutProps } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport {\n BREAKPOINTS_LIST,\n NO_BUTTONS_START_FROM_BREAKPOINT,\n useInitOnce,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nimport styles from './scrollableContainer.less';\n\nconst BUTTON_WIDTH = 44;\n\nexport const ScrollableContainerDefaultLayout: FC<ScrollableContainerDefaultLayoutProps> = ({\n children,\n leftButtonAriaLabel: _leftAriaLabel,\n rightButtonAriaLabel: _rightAriaLabel,\n leftAriaControls,\n rightAriaControls,\n}) => {\n const scrollState = useScrollState();\n const displayLeftButton = useMotionValue<'none' | 'block'>('none');\n const displayRightButton = useMotionValue<'none' | 'block'>('none');\n const mask = useMotionValue<string | number>('none');\n\n const breakpoint = useBreakpoint();\n const breakpointIndex = BREAKPOINTS_LIST.indexOf(breakpoint.breakpoint);\n const noButtonBreakpointIndex = BREAKPOINTS_LIST.indexOf(NO_BUTTONS_START_FROM_BREAKPOINT);\n const enableDefaultButtonsByBreakpoint = breakpointIndex > noButtonBreakpointIndex;\n\n const leftAriaLabelTrl = useTranslation('ScrollableContainer', 'left');\n const leftButtonAriaLabel = _leftAriaLabel ?? leftAriaLabelTrl;\n const rightAriaLabelTrl = useTranslation('ScrollableContainer', 'right');\n const rightButtonAriaLabel = _rightAriaLabel ?? rightAriaLabelTrl;\n\n const updateFadeAndButtons = useInitOnce(() => () => {\n const position = scrollState.scrollPosition.get();\n const contentWidth = scrollState.contentWidth.get();\n const viewportWidth = scrollState.viewportWidth.get();\n\n const showLeftButton = position < 0;\n const showRightButton = Math.abs(position) < Math.max(0, contentWidth - viewportWidth);\n\n displayLeftButton.set(showLeftButton ? 'block' : 'none');\n displayRightButton.set(showRightButton ? 'block' : 'none');\n\n if (showLeftButton && showRightButton) {\n mask.set('var(--both-sides-mask)');\n } else if (showLeftButton) {\n mask.set('var(--left-fade-mask)');\n } else if (showRightButton) {\n mask.set('var(--right-fade-mask)');\n } else {\n mask.set('none');\n }\n });\n\n useEffect(() => {\n updateFadeAndButtons();\n const unsubscribe = [\n scrollState.scrollPosition.on('change', updateFadeAndButtons),\n scrollState.contentWidth.on('change', updateFadeAndButtons),\n scrollState.viewportWidth.on('change', updateFadeAndButtons),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState, updateFadeAndButtons]);\n\n useEffect(() => {\n scrollState.defaultButtonsCorrection.set(enableDefaultButtonsByBreakpoint ? BUTTON_WIDTH : 0);\n return () => {\n scrollState.defaultButtonsCorrection.set(0);\n };\n }, [scrollState, enableDefaultButtonsByBreakpoint]);\n\n return (\n <div className={styles.scrollButtonsContainer}>\n <motion.div\n className={classnames(styles.scrollButton, styles.scrollButtonLeft)}\n style={{ display: enableDefaultButtonsByBreakpoint ? displayLeftButton : 'none' }}\n >\n <ScrollableContainerLeft>\n <ChevronLeftOutlinedSize24\n padding={8}\n borderRadius=\"halfHeight\"\n initialColor=\"secondary\"\n backgroundStyle=\"secondary\"\n aria-label={leftButtonAriaLabel}\n aria-controls={leftAriaControls}\n />\n </ScrollableContainerLeft>\n </motion.div>\n <motion.div\n className={styles.scrollButtons}\n style={{\n WebkitMask: enableDefaultButtonsByBreakpoint ? mask : 'none',\n mask: enableDefaultButtonsByBreakpoint ? mask : 'none',\n }}\n data-qa=\"scrollable-container__fade\"\n >\n {children}\n </motion.div>\n <motion.div\n className={classnames(styles.scrollButton, styles.scrollButtonRight)}\n style={{ display: enableDefaultButtonsByBreakpoint ? displayRightButton : 'none' }}\n >\n <ScrollableContainerRight>\n <ChevronRightOutlinedSize24\n padding={8}\n borderRadius=\"halfHeight\"\n initialColor=\"secondary\"\n backgroundStyle=\"secondary\"\n aria-label={rightButtonAriaLabel}\n aria-controls={rightAriaControls}\n />\n </ScrollableContainerRight>\n </motion.div>\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -7,7 +7,7 @@ import { useScrollState } from './ScrollStateProvider.js';
7
7
  import { OFFSET_ATTR } from './types.js';
8
8
  import { useInitOnce, findIndexNearestToSnapPoint } from './utils.js';
9
9
  import { VSpacing } from '@hh.ru/magritte-ui-spacing';
10
- import { s as styles } from './scrollableContainer-Dl-Nl71V.js';
10
+ import { s as styles } from './scrollableContainer-Co7tlvFk.js';
11
11
  import 'motion/react';
12
12
  import './ObservableValue.js';
13
13
  import '@hh.ru/magritte-internal-custom-scroll';
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollableContainerDotPages.js","sources":["../src/ScrollableContainerDotPages.tsx"],"sourcesContent":["import { type FC, useState, useEffect, useRef } from 'react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';\nimport { DotPages } from '@hh.ru/magritte-ui-dot-pages';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport { OFFSET_ATTR, ScrollableContainerDotPagesProps } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useInitOnce, findIndexNearestToSnapPoint } from '@hh.ru/magritte-ui-scrollable-container/utils';\nimport { VSpacing } from '@hh.ru/magritte-ui-spacing';\n\nimport styles from './scrollableContainer.less';\n\nconst DEFAULT_DOT = 1;\n\nexport const ScrollableContainerDotPages: FC<ScrollableContainerDotPagesProps> = ({\n onChangeDot,\n dotPagesProps,\n offsetTop = 8,\n}) => {\n const scrollState = useScrollState();\n const [activeDot, setActiveDot] = useState(DEFAULT_DOT);\n const [itemsCount, setItemsCount] = useState(0);\n const activeDotRef = useRef(DEFAULT_DOT);\n const onChangeDotRef = useRef(onChangeDot);\n onChangeDotRef.current = onChangeDot;\n\n const setDotAndEmitOnChange = useInitOnce(() => (dot: number) => {\n if (dot === activeDotRef.current) {\n return;\n }\n setActiveDot(dot);\n onChangeDotRef.current?.(dot);\n activeDotRef.current = dot;\n });\n\n const updateActiveDot = useInitOnce(() => () => {\n const { viewportWidth, scrollPosition, items } = scrollState;\n const center = viewportWidth.get() / 2 + Math.abs(scrollPosition.get());\n const activeDotItem = items.get()[activeDotRef.current - 1]?.current;\n if (\n !activeDotItem ||\n !activeDotItem[OFFSET_ATTR] ||\n (activeDotItem[OFFSET_ATTR].left <= center && activeDotItem[OFFSET_ATTR].right >= center)\n ) {\n return;\n }\n setDotAndEmitOnChange(findIndexNearestToSnapPoint(scrollState) + 1);\n });\n\n useEffect(() => {\n const unsubscribe = [\n scrollState.scrollPosition.on('change', updateActiveDot),\n scrollState.items.on('change', (items) => {\n setItemsCount(items.length);\n // удалили последний элемент и он был активный\n if (activeDotRef.current > items.length && items.length !== 0) {\n setDotAndEmitOnChange(clamp(activeDotRef.current, 0, items.length - 1));\n return;\n }\n updateActiveDot();\n }),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState, updateActiveDot, setDotAndEmitOnChange]);\n\n if (itemsCount === 0) {\n return null;\n }\n\n return (\n <div>\n <VSpacing default={offsetTop} />\n <div className={styles.dotContainer}>\n <DotPages\n active={activeDot}\n count={itemsCount}\n data-qa={dotPagesProps?.['data-qa'] || 'scrollable-container__dot-pages'}\n {...dotPagesProps}\n />\n </div>\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"ScrollableContainerDotPages.js","sources":["src/ScrollableContainerDotPages.tsx"],"sourcesContent":["import { type FC, useState, useEffect, useRef } from 'react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';\nimport { DotPages } from '@hh.ru/magritte-ui-dot-pages';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport { OFFSET_ATTR, ScrollableContainerDotPagesProps } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useInitOnce, findIndexNearestToSnapPoint } from '@hh.ru/magritte-ui-scrollable-container/utils';\nimport { VSpacing } from '@hh.ru/magritte-ui-spacing';\n\nimport styles from './scrollableContainer.less';\n\nconst DEFAULT_DOT = 1;\n\nexport const ScrollableContainerDotPages: FC<ScrollableContainerDotPagesProps> = ({\n onChangeDot,\n dotPagesProps,\n offsetTop = 8,\n}) => {\n const scrollState = useScrollState();\n const [activeDot, setActiveDot] = useState(DEFAULT_DOT);\n const [itemsCount, setItemsCount] = useState(0);\n const activeDotRef = useRef(DEFAULT_DOT);\n const onChangeDotRef = useRef(onChangeDot);\n onChangeDotRef.current = onChangeDot;\n\n const setDotAndEmitOnChange = useInitOnce(() => (dot: number) => {\n if (dot === activeDotRef.current) {\n return;\n }\n setActiveDot(dot);\n onChangeDotRef.current?.(dot);\n activeDotRef.current = dot;\n });\n\n const updateActiveDot = useInitOnce(() => () => {\n const { viewportWidth, scrollPosition, items } = scrollState;\n const center = viewportWidth.get() / 2 + Math.abs(scrollPosition.get());\n const activeDotItem = items.get()[activeDotRef.current - 1]?.current;\n if (\n !activeDotItem ||\n !activeDotItem[OFFSET_ATTR] ||\n (activeDotItem[OFFSET_ATTR].left <= center && activeDotItem[OFFSET_ATTR].right >= center)\n ) {\n return;\n }\n setDotAndEmitOnChange(findIndexNearestToSnapPoint(scrollState) + 1);\n });\n\n useEffect(() => {\n const unsubscribe = [\n scrollState.scrollPosition.on('change', updateActiveDot),\n scrollState.items.on('change', (items) => {\n setItemsCount(items.length);\n // удалили последний элемент и он был активный\n if (activeDotRef.current > items.length && items.length !== 0) {\n setDotAndEmitOnChange(clamp(activeDotRef.current, 0, items.length - 1));\n return;\n }\n updateActiveDot();\n }),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState, updateActiveDot, setDotAndEmitOnChange]);\n\n if (itemsCount === 0) {\n return null;\n }\n\n return (\n <div>\n <VSpacing default={offsetTop} />\n <div className={styles.dotContainer}>\n <DotPages\n active={activeDot}\n count={itemsCount}\n data-qa={dotPagesProps?.['data-qa'] || 'scrollable-container__dot-pages'}\n {...dotPagesProps}\n />\n </div>\n </div>\n );\n};\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -6,7 +6,7 @@ import { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers
6
6
  import { useScrollState } from './ScrollStateProvider.js';
7
7
  import { useScrollContainer } from './useScrollContainer.js';
8
8
  import { getDisableState, findIndexNearestToSnapPoint, computeScrollSnapBehavior } from './utils.js';
9
- import { s as styles } from './scrollableContainer-Dl-Nl71V.js';
9
+ import { s as styles } from './scrollableContainer-Co7tlvFk.js';
10
10
  import './ObservableValue.js';
11
11
  import '@hh.ru/magritte-common-func-utils';
12
12
  import '@hh.ru/magritte-internal-custom-scroll';
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollableContainerGallery.js","sources":["../src/ScrollableContainerGallery.tsx"],"sourcesContent":["import { type FC, createContext, useContext, useEffect, useRef } from 'react';\nimport { animate, motion, useSpring } from 'motion/react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport type {\n ScrollableContainerGalleryProps,\n RegisterAndRemoveItem,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollContainer } from '@hh.ru/magritte-ui-scrollable-container/useScrollContainer';\nimport {\n getDisableState,\n findIndexNearestToSnapPoint,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nimport styles from './scrollableContainer.less';\n\nconst GalleryContext = createContext<RegisterAndRemoveItem>({\n registerItem: () => null,\n removeItem: () => null,\n});\n\nexport const useGalleryContext = (): RegisterAndRemoveItem => useContext(GalleryContext);\n\nexport const ScrollableContainerGallery: FC<ScrollableContainerGalleryProps> = ({\n children,\n onScroll,\n onReady,\n onChangeSize,\n ...props\n}) => {\n const scrollState = useScrollState();\n const onReadyRef = useRef(onReady);\n const onScrollRef = useRef(onScroll);\n const onChangeSizeRef = useRef(onChangeSize);\n onReadyRef.current = onReady;\n onScrollRef.current = onScroll;\n onChangeSizeRef.current = onChangeSize;\n\n const { registerItem, removeItem, initScrollHandlers, containerRef, positionContainerRef, isTouch } =\n useScrollContainer();\n\n useEffect(() => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n const updateScrollPositionByResize = () => {\n const index = findIndexNearestToSnapPoint(scrollState);\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n if (target === null) {\n return;\n }\n const position = clamp(target, viewportWidth.get() - contentWidth.get(), 0);\n onChangeSizeRef.current?.(getDisableState(scrollState));\n if (scrollPosition.get() === position) {\n return;\n }\n animate(scrollPosition, position, {\n velocity: Math.max(scrollPosition.getVelocity(), 1),\n });\n };\n const unsubscribe = [\n scrollPosition.on('change', () => {\n onScrollRef.current?.(getDisableState(scrollState));\n }),\n viewportWidth.on('change', updateScrollPositionByResize),\n contentWidth.on('change', updateScrollPositionByResize),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState]);\n\n useEffect(() => {\n onReadyRef.current?.(getDisableState(scrollState));\n return initScrollHandlers();\n }, [initScrollHandlers, scrollState]);\n\n const springScrollPosition = useSpring(scrollState.scrollPosition, {\n stiffness: 1800,\n damping: 75,\n mass: 0.5,\n });\n\n return (\n <GalleryContext.Provider\n value={{\n registerItem,\n removeItem,\n }}\n >\n <div\n ref={containerRef}\n role=\"list\"\n className={styles.scrollableContainer}\n data-qa=\"scrollable-container__overflow-container\"\n {...props}\n >\n <motion.div\n ref={positionContainerRef}\n data-qa=\"scrollable-container__position-container\"\n className={styles.positionContainer}\n style={{ x: isTouch ? scrollState.scrollPosition : springScrollPosition }}\n >\n {children}\n </motion.div>\n </div>\n </GalleryContext.Provider>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"ScrollableContainerGallery.js","sources":["src/ScrollableContainerGallery.tsx"],"sourcesContent":["import { type FC, createContext, useContext, useEffect, useRef } from 'react';\nimport { animate, motion, useSpring } from 'motion/react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport type {\n ScrollableContainerGalleryProps,\n RegisterAndRemoveItem,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollContainer } from '@hh.ru/magritte-ui-scrollable-container/useScrollContainer';\nimport {\n getDisableState,\n findIndexNearestToSnapPoint,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nimport styles from './scrollableContainer.less';\n\nconst GalleryContext = createContext<RegisterAndRemoveItem>({\n registerItem: () => null,\n removeItem: () => null,\n});\n\nexport const useGalleryContext = (): RegisterAndRemoveItem => useContext(GalleryContext);\n\nexport const ScrollableContainerGallery: FC<ScrollableContainerGalleryProps> = ({\n children,\n onScroll,\n onReady,\n onChangeSize,\n ...props\n}) => {\n const scrollState = useScrollState();\n const onReadyRef = useRef(onReady);\n const onScrollRef = useRef(onScroll);\n const onChangeSizeRef = useRef(onChangeSize);\n onReadyRef.current = onReady;\n onScrollRef.current = onScroll;\n onChangeSizeRef.current = onChangeSize;\n\n const { registerItem, removeItem, initScrollHandlers, containerRef, positionContainerRef, isTouch } =\n useScrollContainer();\n\n useEffect(() => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n const updateScrollPositionByResize = () => {\n const index = findIndexNearestToSnapPoint(scrollState);\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n if (target === null) {\n return;\n }\n const position = clamp(target, viewportWidth.get() - contentWidth.get(), 0);\n onChangeSizeRef.current?.(getDisableState(scrollState));\n if (scrollPosition.get() === position) {\n return;\n }\n animate(scrollPosition, position, {\n velocity: Math.max(scrollPosition.getVelocity(), 1),\n });\n };\n const unsubscribe = [\n scrollPosition.on('change', () => {\n onScrollRef.current?.(getDisableState(scrollState));\n }),\n viewportWidth.on('change', updateScrollPositionByResize),\n contentWidth.on('change', updateScrollPositionByResize),\n ];\n return () => {\n unsubscribe.forEach((fn) => fn());\n };\n }, [scrollState]);\n\n useEffect(() => {\n onReadyRef.current?.(getDisableState(scrollState));\n return initScrollHandlers();\n }, [initScrollHandlers, scrollState]);\n\n const springScrollPosition = useSpring(scrollState.scrollPosition, {\n stiffness: 1800,\n damping: 75,\n mass: 0.5,\n });\n\n return (\n <GalleryContext.Provider\n value={{\n registerItem,\n removeItem,\n }}\n >\n <div\n ref={containerRef}\n role=\"list\"\n className={styles.scrollableContainer}\n data-qa=\"scrollable-container__overflow-container\"\n {...props}\n >\n <motion.div\n ref={positionContainerRef}\n data-qa=\"scrollable-container__position-container\"\n className={styles.positionContainer}\n style={{ x: isTouch ? scrollState.scrollPosition : springScrollPosition }}\n >\n {children}\n </motion.div>\n </div>\n </GalleryContext.Provider>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
package/ScrollableItem.js CHANGED
@@ -13,7 +13,7 @@ import '@hh.ru/magritte-internal-custom-scroll';
13
13
  import './types.js';
14
14
  import './utils.js';
15
15
  import '@hh.ru/magritte-ui-breakpoint';
16
- import './scrollableContainer-Dl-Nl71V.js';
16
+ import './scrollableContainer-Co7tlvFk.js';
17
17
 
18
18
  const ScrollableItem = ({ children, scrollToItemOnFocus, ...props }) => {
19
19
  const ref = useRef(null);
@@ -1 +1 @@
1
- {"version":3,"file":"ScrollableItem.js","sources":["../src/ScrollableItem.tsx"],"sourcesContent":["import { useRef, useLayoutEffect, useCallback, type FC } from 'react';\n\nimport { useGalleryContext } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';\nimport type { ScrollableItemProps } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\n\nexport const ScrollableItem: FC<ScrollableItemProps> = ({ children, scrollToItemOnFocus, ...props }) => {\n const ref = useRef<HTMLDivElement>(null);\n const { registerItem, removeItem } = useGalleryContext();\n const { scrollToItem } = useScrollableControls();\n\n useLayoutEffect(() => {\n registerItem(ref);\n return () => {\n removeItem(ref);\n };\n }, [registerItem, removeItem]);\n\n const handleSelectItem = useCallback(() => scrollToItem(ref), [scrollToItem]);\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n {...props}\n onClick={handleSelectItem}\n onFocus={scrollToItemOnFocus ? handleSelectItem : undefined}\n >\n {children}\n </div>\n );\n};\n"],"names":["_jsx"],"mappings":";;;;;;;;;;;;;;;;AAMO,MAAM,cAAc,GAA4B,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,GAAG,KAAK,EAAE,KAAI;AACnG,IAAA,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IACzC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,iBAAiB,EAAE,CAAC;AACzD,IAAA,MAAM,EAAE,YAAY,EAAE,GAAG,qBAAqB,EAAE,CAAC;IAEjD,eAAe,CAAC,MAAK;QACjB,YAAY,CAAC,GAAG,CAAC,CAAC;AAClB,QAAA,OAAO,MAAK;YACR,UAAU,CAAC,GAAG,CAAC,CAAC;AACpB,SAAC,CAAC;AACN,KAAC,EAAE,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;AAE/B,IAAA,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAE9E,IAAA,QACIA,GAAA,CAAA,KAAA,EAAA,EACI,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,UAAU,EAAA,GACX,KAAK,EACT,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,SAAS,EAAA,QAAA,EAE1D,QAAQ,EAAA,CACP,EACR;AACN;;;;"}
1
+ {"version":3,"file":"ScrollableItem.js","sources":["src/ScrollableItem.tsx"],"sourcesContent":["import { useRef, useLayoutEffect, useCallback, type FC } from 'react';\n\nimport { useGalleryContext } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';\nimport type { ScrollableItemProps } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\n\nexport const ScrollableItem: FC<ScrollableItemProps> = ({ children, scrollToItemOnFocus, ...props }) => {\n const ref = useRef<HTMLDivElement>(null);\n const { registerItem, removeItem } = useGalleryContext();\n const { scrollToItem } = useScrollableControls();\n\n useLayoutEffect(() => {\n registerItem(ref);\n return () => {\n removeItem(ref);\n };\n }, [registerItem, removeItem]);\n\n const handleSelectItem = useCallback(() => scrollToItem(ref), [scrollToItem]);\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n {...props}\n onClick={handleSelectItem}\n onFocus={scrollToItemOnFocus ? handleSelectItem : undefined}\n >\n {children}\n </div>\n );\n};\n"],"names":["_jsx"],"mappings":";;;;;;;;;;;;;;;;AAMO,MAAM,cAAc,GAA4B,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,GAAG,KAAK,EAAE,KAAI;AACnG,IAAA,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IACzC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,iBAAiB,EAAE,CAAC;AACzD,IAAA,MAAM,EAAE,YAAY,EAAE,GAAG,qBAAqB,EAAE,CAAC;IAEjD,eAAe,CAAC,MAAK;QACjB,YAAY,CAAC,GAAG,CAAC,CAAC;AAClB,QAAA,OAAO,MAAK;YACR,UAAU,CAAC,GAAG,CAAC,CAAC;AACpB,SAAC,CAAC;AACN,KAAC,EAAE,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;AAE/B,IAAA,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAE9E,IAAA,QACIA,GAAA,CAAA,KAAA,EAAA,EACI,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,UAAU,EAAA,GACX,KAAK,EACT,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,SAAS,EAAA,QAAA,EAE1D,QAAQ,EAAA,CACP,EACR;AACN;;;;"}
package/index.css CHANGED
@@ -1,8 +1,8 @@
1
- .magritte-scroll-wrapper___vTdZl_6-2-1{
1
+ .magritte-scroll-wrapper___vTdZl_6-2-3{
2
2
  position:relative;
3
3
  touch-action:pan-y pinch-zoom;
4
4
  }
5
- .magritte-scrollable-container___AKIUp_6-2-1{
5
+ .magritte-scrollable-container___AKIUp_6-2-3{
6
6
  display:block;
7
7
  overflow-x:hidden;
8
8
  overflow-x:clip;
@@ -18,34 +18,34 @@
18
18
  margin-left:var(--magritte-ui-scrollabe-container-ml, -4px);
19
19
  margin-right:var(--magritte-ui-scrollabe-container-mr, -4px);
20
20
  }
21
- .magritte-scroll-buttons-container___ZeI5a_6-2-1{
21
+ .magritte-scroll-buttons-container___ZeI5a_6-2-3{
22
22
  position:relative;
23
23
  }
24
- .magritte-scroll-buttons___0SjoR_6-2-1{
24
+ .magritte-scroll-buttons___0SjoR_6-2-3{
25
25
  --right-fade-mask:linear-gradient(90deg, #000 0, #000 calc(100% - 100.50399999999999px), transparent calc(100% - 36px));
26
26
  --left-fade-mask:linear-gradient(90deg, transparent 0, transparent 36px, #000 100.504px);
27
27
  --both-sides-mask:linear-gradient(90deg, transparent 0, transparent 36px, #000 100.504px, #000 calc(100% - 100.50399999999999px), transparent calc(100% - 36px));
28
28
  -webkit-mask:'none';
29
29
  mask:'none';
30
30
  }
31
- .magritte-scroll-button___4GQu3_6-2-1{
31
+ .magritte-scroll-button___4GQu3_6-2-3{
32
32
  display:none;
33
33
  position:absolute;
34
34
  top:50%;
35
35
  transform:translateY(-50%);
36
36
  }
37
- .magritte-scroll-button-left___UueEY_6-2-1{
37
+ .magritte-scroll-button-left___UueEY_6-2-3{
38
38
  z-index:1;
39
39
  left:0;
40
40
  }
41
- .magritte-scroll-button-right___wZOn-_6-2-1{
41
+ .magritte-scroll-button-right___wZOn-_6-2-3{
42
42
  right:0;
43
43
  }
44
- .magritte-position-container___1A4Bv_6-2-1{
44
+ .magritte-position-container___1A4Bv_6-2-3{
45
45
  box-sizing:border-box;
46
46
  width:100%;
47
47
  }
48
- .magritte-dot-container___ahtlG_6-2-1{
48
+ .magritte-dot-container___ahtlG_6-2-3{
49
49
  display:flex;
50
50
  justify-content:center;
51
51
  }
package/index.js CHANGED
@@ -15,7 +15,7 @@ import '@hh.ru/magritte-ui-icon/icon';
15
15
  import './utils.js';
16
16
  import '@hh.ru/magritte-internal-custom-scroll';
17
17
  import './types.js';
18
- import './scrollableContainer-Dl-Nl71V.js';
18
+ import './scrollableContainer-Co7tlvFk.js';
19
19
  import './ScrollableContainerDotPages.js';
20
20
  import '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
21
21
  import '@hh.ru/magritte-ui-dot-pages';
package/index.mock.js CHANGED
@@ -13,7 +13,7 @@ import 'react/jsx-runtime';
13
13
  import '@hh.ru/magritte-internal-custom-scroll/initScrollHandlers';
14
14
  import './useScrollContainer.js';
15
15
  import '@hh.ru/magritte-common-func-utils';
16
- import './scrollableContainer-Dl-Nl71V.js';
16
+ import './scrollableContainer-Co7tlvFk.js';
17
17
  import './ObservableValue.js';
18
18
 
19
19
  const staticProps = {
package/index.mock.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mock.js","sources":["../src/index.mock.ts"],"sourcesContent":["import { mockComponent } from '@hh.ru/magritte-ui-mock-component';\n\nexport type {\n RegisterAndRemoveItem,\n ScrollableContainerProps,\n SpacingCorrectionProps,\n ScrollableControls,\n ScrollableItemProps,\n ScrollableContainerGalleryProps,\n ScrollableContainerDotPagesProps,\n ScrollDisableState,\n ScrollableContainerButtonProps,\n ScrollableContainerDefaultLayoutProps,\n ScrollSnapAlign,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\n\nconst staticProps = {\n Left: mockComponent('Left', undefined, {\n withChildren: true,\n }),\n Right: mockComponent('Right', undefined, {\n withChildren: true,\n }),\n Item: mockComponent('Item', undefined, {\n withChildren: true,\n }),\n Gallery: mockComponent('Gallery', undefined, {\n withChildren: true,\n }),\n DefaultLayout: mockComponent('DefaultLayout', undefined, {\n withChildren: true,\n }),\n DotPages: mockComponent('DotPages', undefined, {\n withChildren: true,\n }),\n};\n\nexport const ScrollableContainer = mockComponent('ScrollableContainer', staticProps, {\n withChildren: true,\n});\n\nexport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nexport { useGalleryContext } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';\nexport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAM,WAAW,GAAG;AAChB,IAAA,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE;AACnC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE;AACrC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE;AACnC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,OAAO,EAAE,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE;AACzC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,aAAa,EAAE,aAAa,CAAC,eAAe,EAAE,SAAS,EAAE;AACrD,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,QAAQ,EAAE,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE;AAC3C,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;CACL,CAAC;MAEW,mBAAmB,GAAG,aAAa,CAAC,qBAAqB,EAAE,WAAW,EAAE;AACjF,IAAA,YAAY,EAAE,IAAI;AACrB,CAAA;;;;"}
1
+ {"version":3,"file":"index.mock.js","sources":["src/index.mock.ts"],"sourcesContent":["import { mockComponent } from '@hh.ru/magritte-ui-mock-component';\n\nexport type {\n RegisterAndRemoveItem,\n ScrollableContainerProps,\n SpacingCorrectionProps,\n ScrollableControls,\n ScrollableItemProps,\n ScrollableContainerGalleryProps,\n ScrollableContainerDotPagesProps,\n ScrollDisableState,\n ScrollableContainerButtonProps,\n ScrollableContainerDefaultLayoutProps,\n ScrollSnapAlign,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\n\nconst staticProps = {\n Left: mockComponent('Left', undefined, {\n withChildren: true,\n }),\n Right: mockComponent('Right', undefined, {\n withChildren: true,\n }),\n Item: mockComponent('Item', undefined, {\n withChildren: true,\n }),\n Gallery: mockComponent('Gallery', undefined, {\n withChildren: true,\n }),\n DefaultLayout: mockComponent('DefaultLayout', undefined, {\n withChildren: true,\n }),\n DotPages: mockComponent('DotPages', undefined, {\n withChildren: true,\n }),\n};\n\nexport const ScrollableContainer = mockComponent('ScrollableContainer', staticProps, {\n withChildren: true,\n});\n\nexport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nexport { useGalleryContext } from '@hh.ru/magritte-ui-scrollable-container/ScrollableContainerGallery';\nexport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAM,WAAW,GAAG;AAChB,IAAA,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE;AACnC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE;AACrC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE;AACnC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,OAAO,EAAE,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE;AACzC,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,aAAa,EAAE,aAAa,CAAC,eAAe,EAAE,SAAS,EAAE;AACrD,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;AACF,IAAA,QAAQ,EAAE,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE;AAC3C,QAAA,YAAY,EAAE,IAAI;KACrB,CAAC;CACL,CAAC;MAEW,mBAAmB,GAAG,aAAa,CAAC,qBAAqB,EAAE,WAAW,EAAE;AACjF,IAAA,YAAY,EAAE,IAAI;AACrB,CAAA;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hh.ru/magritte-ui-scrollable-container",
3
- "version": "6.2.1",
3
+ "version": "6.2.3",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "sideEffects": [
@@ -19,15 +19,15 @@
19
19
  "watch": "yarn root:watch $(pwd)"
20
20
  },
21
21
  "dependencies": {
22
- "@hh.ru/magritte-common-func-utils": "1.3.14",
23
- "@hh.ru/magritte-common-use-translation": "3.0.0",
24
- "@hh.ru/magritte-design-tokens": "24.4.0",
25
- "@hh.ru/magritte-internal-custom-scroll": "2.1.0",
26
- "@hh.ru/magritte-ui-breakpoint": "6.0.6",
27
- "@hh.ru/magritte-ui-dot-pages": "4.0.17",
28
- "@hh.ru/magritte-ui-icon": "13.11.0",
29
- "@hh.ru/magritte-ui-mock-component": "1.1.6",
30
- "@hh.ru/magritte-ui-spacing": "2.1.10"
22
+ "@hh.ru/magritte-common-func-utils": "1.3.15",
23
+ "@hh.ru/magritte-common-use-translation": "3.0.1",
24
+ "@hh.ru/magritte-design-tokens": "24.4.1",
25
+ "@hh.ru/magritte-internal-custom-scroll": "2.1.1",
26
+ "@hh.ru/magritte-ui-breakpoint": "6.0.8",
27
+ "@hh.ru/magritte-ui-dot-pages": "4.0.18",
28
+ "@hh.ru/magritte-ui-icon": "13.11.2",
29
+ "@hh.ru/magritte-ui-mock-component": "1.1.7",
30
+ "@hh.ru/magritte-ui-spacing": "2.1.12"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "classnames": ">=2.3.2",
@@ -37,5 +37,5 @@
37
37
  "publishConfig": {
38
38
  "access": "public"
39
39
  },
40
- "gitHead": "7cea3ac4f7f947bba409d2fbc29284343113c4ba"
40
+ "gitHead": "9a088ded46caac9429f3e9fadaf055300b36990e"
41
41
  }
@@ -0,0 +1,5 @@
1
+ import './index.css';
2
+ var styles = {"scroll-wrapper":"magritte-scroll-wrapper___vTdZl_6-2-3","scrollWrapper":"magritte-scroll-wrapper___vTdZl_6-2-3","scrollable-container":"magritte-scrollable-container___AKIUp_6-2-3","scrollableContainer":"magritte-scrollable-container___AKIUp_6-2-3","scroll-buttons-container":"magritte-scroll-buttons-container___ZeI5a_6-2-3","scrollButtonsContainer":"magritte-scroll-buttons-container___ZeI5a_6-2-3","scroll-buttons":"magritte-scroll-buttons___0SjoR_6-2-3","scrollButtons":"magritte-scroll-buttons___0SjoR_6-2-3","scroll-button":"magritte-scroll-button___4GQu3_6-2-3","scrollButton":"magritte-scroll-button___4GQu3_6-2-3","scroll-button-left":"magritte-scroll-button-left___UueEY_6-2-3","scrollButtonLeft":"magritte-scroll-button-left___UueEY_6-2-3","scroll-button-right":"magritte-scroll-button-right___wZOn-_6-2-3","scrollButtonRight":"magritte-scroll-button-right___wZOn-_6-2-3","position-container":"magritte-position-container___1A4Bv_6-2-3","positionContainer":"magritte-position-container___1A4Bv_6-2-3","dot-container":"magritte-dot-container___ahtlG_6-2-3","dotContainer":"magritte-dot-container___ahtlG_6-2-3"};
3
+
4
+ export { styles as s };
5
+ //# sourceMappingURL=scrollableContainer-Co7tlvFk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollableContainer-Co7tlvFk.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
package/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sources":["../src/types.ts"],"sourcesContent":["import type { HTMLAttributes, RefObject, MouseEventHandler, ReactNode } from 'react';\n\nimport { TokenBaseStaticSpace } from '@hh.ru/magritte-design-tokens/types';\nimport type { DotPagesProps } from '@hh.ru/magritte-ui-dot-pages';\n\nexport const OFFSET_ATTR = Symbol('scroll-item-offset');\nexport interface ItemWithOffset {\n [OFFSET_ATTR]: { left: number; right: number };\n}\n\nexport interface ControlWithClick {\n onClick?: MouseEventHandler;\n 'data-qa'?: string;\n}\n\nexport interface RegisterAndRemoveItem {\n /** колбэк для регистрации элемента галерии */\n registerItem: (ref: RefObject<HTMLElement>) => void;\n /** колбэк для удаления элемента галерии */\n removeItem: (ref: RefObject<HTMLElement>) => void;\n}\n\nexport interface ScrollDisableState {\n /** заблокирован ли скролл влево */\n isScrollRightDisabled: boolean;\n /** заблокирован ли скролл вправо */\n isScrollLeftDisabled: boolean;\n}\n\nexport interface ScrollableControls {\n /** двигаем ScrollableContainer налево */\n scrollLeft: () => void;\n /** двигаем ScrollableContainer направо */\n scrollRight: () => void;\n /** двигаем ScrollableContainer к первому элементу */\n scrollToFirstItem: () => void;\n /** двигаем ScrollableContainer к последнему элементу */\n scrollToLastItem: () => void;\n /** скролл к элементу по индексу, элементы сортируются по расположению справа на лево */\n scrollToIndex: (index: number) => void;\n /**\n * скролл к элементу по ref, должен передаваться ref на элемент который был\n * зарегистрирован с помощью registerItem API\n **/\n scrollToItem: (ref: RefObject<HTMLElement>) => void;\n}\n\n/**\n * Пропы для настройки коррекции отступов в режиме без кнопок, когда надо чтобы край скролла соответствовал\n * краю родительского контейнера, у которого могут быть отступы. Задаются в виде положительного числа.\n * более специфичные пропсы переопределяют менее специфичные. При выборе значения коррекции для разрешения выбирается\n * ближайшее заданное значение для разрешений меньшего или равного размера. Т.е. если задано correction и correctionM,\n * то для разрешений S и XS будет использовано correction, а для остальных correctionM. Если задано\n * еще и correctionLeftM, то для разрешений начиная с M и больше для левого края будет использовано\n * correctionLeftM, а для правого correctionM.\n */\nexport interface SpacingCorrectionProps {\n /** Величина коррекции отступа, положительное число или 0 */\n correction?: number;\n /** Величина коррекции отступа для разрешения XS и больше, положительное число или 0 */\n correctionXS?: number;\n /** Величина коррекции отступа для разрешения S и больше, положительное число или 0 */\n correctionS?: number;\n /** Величина коррекции отступа для разрешения M и больше, положительное число или 0 */\n correctionM?: number;\n /** Величина коррекции отступа для разрешения L и больше, положительное число или 0 */\n correctionL?: number;\n /** Величина коррекции отступа для разрешения XL и больше, положительное число или 0 */\n correctionXL?: number;\n /** Величина коррекции отступа для разрешения XXL и больше, положительное число или 0 */\n correctionXXL?: number;\n /** Величина коррекции отступа слева для разрешения XS и больше, положительное число или 0 */\n correctionLeftXS?: number;\n /** Величина коррекции левого отступа для разрешения S и больше, положительное число или 0 */\n correctionLeftS?: number;\n /** Величина коррекции левого отступа для разрешения M и больше, положительное число или 0 */\n correctionLeftM?: number;\n /** Величина коррекции левого отступа для разрешения L и больше, положительное число или 0 */\n correctionLeftL?: number;\n /** Величина коррекции левого отступа для разрешения XL и больше, положительное число или 0 */\n correctionLeftXL?: number;\n /** Величина коррекции левого отступа для разрешения XXL и больше, положительное число или 0 */\n correctionLeftXXL?: number;\n /** Величина коррекции отступа справа для разрешения XS и больше, положительное число или 0 */\n correctionRightXS?: number;\n /** Величина коррекции отступа справа для разрешения S и больше, положительное число или 0 */\n correctionRightS?: number;\n /** Величина коррекции отступа справа для разрешения M и больше, положительное число или 0 */\n correctionRightM?: number;\n /** Величина коррекции отступа справа для разрешения L и больше, положительное число или 0 */\n correctionRightL?: number;\n /** Величина коррекции отступа справа для разрешения XL и больше, положительное число или 0 */\n correctionRightXL?: number;\n /** Величина коррекции отступа справа для разрешения XXL и больше, положительное число или 0 */\n correctionRightXXL?: number;\n}\n\nexport type ScrollSnapAlign = 'start' | 'end' | 'center' | 'none';\n\nexport type ScrollableContainerProps = SpacingCorrectionProps & {\n /** Контент ScrollableContainer */\n children: ReactNode;\n /**\n * Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле\n *\n * - `center` - ближайший элемент центрируется во вьюпорте\n * - `start` - ближайший элемент выравнивается по левой границе вьюпорта\n * - `end` - ближайший элемент выравнивается по правой границе вьюпорта\n */\n scrollSnapAlign?: ScrollSnapAlign;\n} & HTMLAttributes<HTMLDivElement>;\n\nexport interface ScrollableItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Элемент галереи */\n children: ReactNode;\n /** Нужно ли скролить к элементу при фокусе */\n scrollToItemOnFocus?: boolean;\n}\n\nexport interface ScrollableContainerGalleryProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onScroll'> {\n /** Колбэк при прокрутке контейнера */\n onScroll?: (scrollInfo: ScrollDisableState) => void;\n /** Колбэк при инициализации контейнера */\n onReady?: (scrollInfo: ScrollDisableState) => void;\n /** Колбэк при изменении размеров контейнера */\n onChangeSize?: (scrollInfo: ScrollDisableState) => void;\n /** Элементы галереи, которые отображаются внутри контейнера и прокручиваются по горизонтали */\n children: ReactNode;\n}\n\nexport interface ScrollableContainerDotPagesProps {\n /** Колбэк при изменении active dot в компоненте dot-pages*/\n onChangeDot?: (dot: number) => void;\n /** Свойства dot-pages*/\n dotPagesProps?: Omit<DotPagesProps, 'active' | 'count'>;\n /** Верхний отступ для DotPages */\n offsetTop?: TokenBaseStaticSpace;\n}\n\nexport interface ScrollableContainerButtonProps {\n /** Кнопка для скрола налево/направо */\n children: ReactNode;\n}\n\nexport interface ScrollableContainerDefaultLayoutProps {\n /** Контент ScrollableContainerGallery */\n children: ReactNode;\n /** aria-label кнопки налево */\n leftButtonAriaLabel?: string;\n /** aria-label кнопки направо */\n rightButtonAriaLabel?: string;\n /** aria-controls кнопки налево */\n leftAriaControls?: string;\n /** aria-controls кнопки направо */\n rightAriaControls?: string;\n}\n"],"names":[],"mappings":"MAKa,WAAW,GAAG,MAAM,CAAC,oBAAoB;;;;"}
1
+ {"version":3,"file":"types.js","sources":["src/types.ts"],"sourcesContent":["import type { HTMLAttributes, RefObject, MouseEventHandler, ReactNode } from 'react';\n\nimport { TokenBaseStaticSpace } from '@hh.ru/magritte-design-tokens/types';\nimport type { DotPagesProps } from '@hh.ru/magritte-ui-dot-pages';\n\nexport const OFFSET_ATTR = Symbol('scroll-item-offset');\nexport interface ItemWithOffset {\n [OFFSET_ATTR]: { left: number; right: number };\n}\n\nexport interface ControlWithClick {\n onClick?: MouseEventHandler;\n 'data-qa'?: string;\n}\n\nexport interface RegisterAndRemoveItem {\n /** колбэк для регистрации элемента галерии */\n registerItem: (ref: RefObject<HTMLElement>) => void;\n /** колбэк для удаления элемента галерии */\n removeItem: (ref: RefObject<HTMLElement>) => void;\n}\n\nexport interface ScrollDisableState {\n /** заблокирован ли скролл влево */\n isScrollRightDisabled: boolean;\n /** заблокирован ли скролл вправо */\n isScrollLeftDisabled: boolean;\n}\n\nexport interface ScrollableControls {\n /** двигаем ScrollableContainer налево */\n scrollLeft: () => void;\n /** двигаем ScrollableContainer направо */\n scrollRight: () => void;\n /** двигаем ScrollableContainer к первому элементу */\n scrollToFirstItem: () => void;\n /** двигаем ScrollableContainer к последнему элементу */\n scrollToLastItem: () => void;\n /** скролл к элементу по индексу, элементы сортируются по расположению справа на лево */\n scrollToIndex: (index: number) => void;\n /**\n * скролл к элементу по ref, должен передаваться ref на элемент который был\n * зарегистрирован с помощью registerItem API\n **/\n scrollToItem: (ref: RefObject<HTMLElement>) => void;\n}\n\n/**\n * Пропы для настройки коррекции отступов в режиме без кнопок, когда надо чтобы край скролла соответствовал\n * краю родительского контейнера, у которого могут быть отступы. Задаются в виде положительного числа.\n * более специфичные пропсы переопределяют менее специфичные. При выборе значения коррекции для разрешения выбирается\n * ближайшее заданное значение для разрешений меньшего или равного размера. Т.е. если задано correction и correctionM,\n * то для разрешений S и XS будет использовано correction, а для остальных correctionM. Если задано\n * еще и correctionLeftM, то для разрешений начиная с M и больше для левого края будет использовано\n * correctionLeftM, а для правого correctionM.\n */\nexport interface SpacingCorrectionProps {\n /** Величина коррекции отступа, положительное число или 0 */\n correction?: number;\n /** Величина коррекции отступа для разрешения XS и больше, положительное число или 0 */\n correctionXS?: number;\n /** Величина коррекции отступа для разрешения S и больше, положительное число или 0 */\n correctionS?: number;\n /** Величина коррекции отступа для разрешения M и больше, положительное число или 0 */\n correctionM?: number;\n /** Величина коррекции отступа для разрешения L и больше, положительное число или 0 */\n correctionL?: number;\n /** Величина коррекции отступа для разрешения XL и больше, положительное число или 0 */\n correctionXL?: number;\n /** Величина коррекции отступа для разрешения XXL и больше, положительное число или 0 */\n correctionXXL?: number;\n /** Величина коррекции отступа слева для разрешения XS и больше, положительное число или 0 */\n correctionLeftXS?: number;\n /** Величина коррекции левого отступа для разрешения S и больше, положительное число или 0 */\n correctionLeftS?: number;\n /** Величина коррекции левого отступа для разрешения M и больше, положительное число или 0 */\n correctionLeftM?: number;\n /** Величина коррекции левого отступа для разрешения L и больше, положительное число или 0 */\n correctionLeftL?: number;\n /** Величина коррекции левого отступа для разрешения XL и больше, положительное число или 0 */\n correctionLeftXL?: number;\n /** Величина коррекции левого отступа для разрешения XXL и больше, положительное число или 0 */\n correctionLeftXXL?: number;\n /** Величина коррекции отступа справа для разрешения XS и больше, положительное число или 0 */\n correctionRightXS?: number;\n /** Величина коррекции отступа справа для разрешения S и больше, положительное число или 0 */\n correctionRightS?: number;\n /** Величина коррекции отступа справа для разрешения M и больше, положительное число или 0 */\n correctionRightM?: number;\n /** Величина коррекции отступа справа для разрешения L и больше, положительное число или 0 */\n correctionRightL?: number;\n /** Величина коррекции отступа справа для разрешения XL и больше, положительное число или 0 */\n correctionRightXL?: number;\n /** Величина коррекции отступа справа для разрешения XXL и больше, положительное число или 0 */\n correctionRightXXL?: number;\n}\n\nexport type ScrollSnapAlign = 'start' | 'end' | 'center' | 'none';\n\nexport type ScrollableContainerProps = SpacingCorrectionProps & {\n /** Контент ScrollableContainer */\n children: ReactNode;\n /**\n * Определяет, как ближайший элемент будет размещён во вьюпорте при автоматическом скролле\n *\n * - `center` - ближайший элемент центрируется во вьюпорте\n * - `start` - ближайший элемент выравнивается по левой границе вьюпорта\n * - `end` - ближайший элемент выравнивается по правой границе вьюпорта\n */\n scrollSnapAlign?: ScrollSnapAlign;\n} & HTMLAttributes<HTMLDivElement>;\n\nexport interface ScrollableItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Элемент галереи */\n children: ReactNode;\n /** Нужно ли скролить к элементу при фокусе */\n scrollToItemOnFocus?: boolean;\n}\n\nexport interface ScrollableContainerGalleryProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onScroll'> {\n /** Колбэк при прокрутке контейнера */\n onScroll?: (scrollInfo: ScrollDisableState) => void;\n /** Колбэк при инициализации контейнера */\n onReady?: (scrollInfo: ScrollDisableState) => void;\n /** Колбэк при изменении размеров контейнера */\n onChangeSize?: (scrollInfo: ScrollDisableState) => void;\n /** Элементы галереи, которые отображаются внутри контейнера и прокручиваются по горизонтали */\n children: ReactNode;\n}\n\nexport interface ScrollableContainerDotPagesProps {\n /** Колбэк при изменении active dot в компоненте dot-pages*/\n onChangeDot?: (dot: number) => void;\n /** Свойства dot-pages*/\n dotPagesProps?: Omit<DotPagesProps, 'active' | 'count'>;\n /** Верхний отступ для DotPages */\n offsetTop?: TokenBaseStaticSpace;\n}\n\nexport interface ScrollableContainerButtonProps {\n /** Кнопка для скрола налево/направо */\n children: ReactNode;\n}\n\nexport interface ScrollableContainerDefaultLayoutProps {\n /** Контент ScrollableContainerGallery */\n children: ReactNode;\n /** aria-label кнопки налево */\n leftButtonAriaLabel?: string;\n /** aria-label кнопки направо */\n rightButtonAriaLabel?: string;\n /** aria-controls кнопки налево */\n leftAriaControls?: string;\n /** aria-controls кнопки направо */\n rightAriaControls?: string;\n}\n"],"names":[],"mappings":"MAKa,WAAW,GAAG,MAAM,CAAC,oBAAoB;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useScrollContainer.js","sources":["../src/useScrollContainer.ts"],"sourcesContent":["import { useRef, useEffect, type RefObject, useCallback, useState } from 'react';\n\nimport { requestAnimation, debounce } from '@hh.ru/magritte-common-func-utils';\nimport { clamp, type ScrollGestureEvent, initScrollHandlers } from '@hh.ru/magritte-internal-custom-scroll';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport { type ItemWithOffset, OFFSET_ATTR } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nimport {\n useInitOnce,\n findIndexNearestToSnapPoint,\n animateScrollToPosition,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nconst EPSILON = 0.5;\nconst MIN_DELTA_FOR_TOUCH = 5;\nconst MAX_OFFSET = { [OFFSET_ATTR]: { left: Number.MAX_SAFE_INTEGER } };\n\n/**\n * Переменные полностью описывающие состояние скролла, хранятся в одном объекте, чтобы не плодить\n * кучу ref'ов и передавать всё состояние в функции одним аргументом, а не длинным списком переменных\n */\nexport interface ScrollInternalState {\n /** контейнер, в котором лежит positionContainer (определяет видимую область) */\n containerRef: RefObject<HTMLDivElement>;\n /** контейнер, с помощью изменения положения которого обеспечивается скролл */\n positionContainerRef: RefObject<HTMLDivElement>;\n /** размер коррекции отступов */\n correction: { leftCorrection: number; rightCorrection: number };\n /* Было ли взаимодействие с компонентом - скролл или прокрутка к элементу */\n wasInteracted: boolean;\n}\n\ninterface UseScrollContainer {\n registerItem: (ref: RefObject<HTMLElement>) => void;\n removeItem: (ref: RefObject<HTMLElement>) => void;\n initScrollHandlers: () => VoidFunction;\n containerRef: RefObject<HTMLDivElement>;\n positionContainerRef: RefObject<HTMLDivElement>;\n isTouch: boolean;\n}\n\nexport const useScrollContainer = (): UseScrollContainer => {\n const scrollState = useScrollState();\n const { scrollToIndex } = useScrollableControls();\n const [isTouch, setIsTouch] = useState(false);\n const leftCorrection = scrollState.leftCorrection.get();\n const rightCorrection = scrollState.rightCorrection.get();\n const scrollStateRef = useRef<ScrollInternalState>({\n containerRef: useRef<HTMLDivElement>(null),\n positionContainerRef: useRef<HTMLDivElement>(null),\n correction: { leftCorrection, rightCorrection },\n wasInteracted: false,\n });\n scrollStateRef.current.correction = { leftCorrection, rightCorrection };\n const resizeOberverRef = useRef<ResizeObserver | null>(null);\n\n // recalc positions + report widths into store\n const recalculateItemPositions = useCallback(() => {\n const state = scrollStateRef.current;\n const { containerRef, correction, positionContainerRef } = state;\n const { leftCorrection, rightCorrection } = correction;\n const items = scrollState.items.get();\n if (!containerRef.current || !positionContainerRef.current) {\n return;\n }\n const offsetLeft = positionContainerRef.current?.getBoundingClientRect().left ?? 0;\n items.forEach((itemRef) => {\n if (!itemRef.current) {\n return;\n }\n const rect = itemRef.current.getBoundingClientRect();\n itemRef.current[OFFSET_ATTR] = { left: rect.left - offsetLeft, right: rect.right - offsetLeft };\n });\n items.sort((a, b) => (a.current || MAX_OFFSET)[OFFSET_ATTR].left - (b.current || MAX_OFFSET)[OFFSET_ATTR].left);\n const viewportWidth = containerRef.current.offsetWidth - leftCorrection - rightCorrection;\n const contentWidth = items.reduce(\n (pos, itemRef) => Math.max(pos, itemRef.current?.[OFFSET_ATTR]?.right || 0),\n 0\n );\n scrollState.viewportWidth.set(viewportWidth);\n scrollState.contentWidth.set(contentWidth);\n scrollState.items.set(items);\n if (scrollState.indexForDeferScroll !== -1) {\n scrollToIndex(scrollState.indexForDeferScroll);\n scrollState.indexForDeferScroll = -1;\n }\n }, [scrollState, scrollToIndex]);\n\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n const recalculateItemPositionsDebounced = useCallback(debounce(recalculateItemPositions, 10), [\n recalculateItemPositions,\n ]);\n\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n const scrollToItemDebounced = useInitOnce(() =>\n debounce(() => {\n if (scrollState.scrollSnapAlign === 'none') {\n return;\n }\n const targetItemIndex = findIndexNearestToSnapPoint(scrollState);\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, targetItemIndex);\n animateScrollToPosition(scrollState, target);\n }, 100)\n );\n\n useEffect(() => {\n const state = scrollStateRef.current;\n const observer = new ResizeObserver(\n requestAnimation(() => {\n recalculateItemPositions();\n })\n );\n\n scrollState.items.get().forEach((item) => item.current && observer.observe(item.current));\n state.containerRef.current && observer.observe(state.containerRef.current);\n resizeOberverRef.current = observer;\n return () => observer.disconnect();\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, []);\n\n // Слушатель нужен, чтобы не вызывать скролл в родительском контейнере (например в bs)\n useEffect(() => {\n const wrapperRef = scrollStateRef.current.containerRef.current;\n if (!wrapperRef) {\n return void 0;\n }\n const handleTouchStartHandler = (event: TouchEvent) => {\n event.stopPropagation();\n };\n wrapperRef.addEventListener('touchstart', handleTouchStartHandler);\n return () => {\n wrapperRef.removeEventListener('touchstart', handleTouchStartHandler);\n };\n }, []);\n\n // события тача\n const didContainerMove = useRef(false);\n const onTouchStart = useCallback(() => {\n setIsTouch(true);\n didContainerMove.current = false;\n scrollState.scrollPosition.stop();\n }, [scrollState]);\n\n const onTouchMove = useCallback(\n (event: ScrollGestureEvent) => {\n if (!didContainerMove.current) {\n // надо отличить тач от свайпа\n didContainerMove.current = Math.abs(event.delta) > MIN_DELTA_FOR_TOUCH;\n }\n scrollState.scrollPosition.set(\n clamp(\n scrollState.scrollPosition.get() + event.delta,\n scrollState.viewportWidth.get() - scrollState.contentWidth.get(),\n 0\n )\n );\n },\n [scrollState]\n );\n\n const onTouchEnd = useCallback(() => {\n if (didContainerMove.current) {\n scrollToItemDebounced();\n }\n }, [scrollToItemDebounced]);\n\n // события мыши\n const didContainerHovered = useRef(false);\n const onMouseEnter = useCallback(() => {\n didContainerHovered.current = true;\n }, []);\n\n const onWheelMove = useCallback(\n (event: ScrollGestureEvent) => {\n setIsTouch(false);\n if (!didContainerHovered.current) {\n return;\n }\n const currentPosition = scrollState.scrollPosition.get();\n const nextPosition = clamp(\n currentPosition + event.delta,\n scrollState.viewportWidth.get() - scrollState.contentWidth.get(),\n 0\n );\n if (Math.abs(nextPosition - currentPosition) > EPSILON) {\n scrollState.scrollPosition.set(nextPosition);\n scrollToItemDebounced();\n event.preventDefault();\n }\n },\n [scrollToItemDebounced, scrollState]\n );\n\n const onMouseLeave = useCallback(() => {\n didContainerHovered.current = false;\n }, []);\n\n const _initScrollHandlers = useCallback(\n () =>\n initScrollHandlers({\n axis: 'horizontal',\n wrapperRef: scrollStateRef.current.containerRef,\n onTouchStart,\n onTouchMove,\n onTouchEnd,\n onMouseEnter,\n onWheelMove,\n onMouseLeave,\n }),\n [onTouchMove, onTouchEnd, onWheelMove, onTouchStart, onMouseEnter, onMouseLeave]\n );\n\n const registerItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n if (!ref.current) {\n return;\n }\n scrollState.items.get().push(ref as unknown as RefObject<HTMLElement & ItemWithOffset>);\n scrollState.items.set(scrollState.items.get());\n resizeOberverRef.current?.observe(ref.current);\n recalculateItemPositions();\n },\n [recalculateItemPositions, scrollState]\n );\n\n const removeItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n if (!ref.current) {\n return;\n }\n scrollState.items.set(scrollState.items.get().filter((stored) => stored.current !== ref.current));\n resizeOberverRef.current?.unobserve(ref.current);\n recalculateItemPositionsDebounced();\n },\n [recalculateItemPositionsDebounced, scrollState]\n );\n\n return {\n registerItem,\n removeItem,\n initScrollHandlers: _initScrollHandlers,\n containerRef: scrollStateRef.current.containerRef,\n positionContainerRef: scrollStateRef.current.positionContainerRef,\n isTouch,\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useScrollContainer.js","sources":["src/useScrollContainer.ts"],"sourcesContent":["import { useRef, useEffect, type RefObject, useCallback, useState } from 'react';\n\nimport { requestAnimation, debounce } from '@hh.ru/magritte-common-func-utils';\nimport { clamp, type ScrollGestureEvent, initScrollHandlers } from '@hh.ru/magritte-internal-custom-scroll';\nimport { useScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport { type ItemWithOffset, OFFSET_ATTR } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport { useScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/useScrollableControls';\nimport {\n useInitOnce,\n findIndexNearestToSnapPoint,\n animateScrollToPosition,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nconst EPSILON = 0.5;\nconst MIN_DELTA_FOR_TOUCH = 5;\nconst MAX_OFFSET = { [OFFSET_ATTR]: { left: Number.MAX_SAFE_INTEGER } };\n\n/**\n * Переменные полностью описывающие состояние скролла, хранятся в одном объекте, чтобы не плодить\n * кучу ref'ов и передавать всё состояние в функции одним аргументом, а не длинным списком переменных\n */\nexport interface ScrollInternalState {\n /** контейнер, в котором лежит positionContainer (определяет видимую область) */\n containerRef: RefObject<HTMLDivElement>;\n /** контейнер, с помощью изменения положения которого обеспечивается скролл */\n positionContainerRef: RefObject<HTMLDivElement>;\n /** размер коррекции отступов */\n correction: { leftCorrection: number; rightCorrection: number };\n /* Было ли взаимодействие с компонентом - скролл или прокрутка к элементу */\n wasInteracted: boolean;\n}\n\ninterface UseScrollContainer {\n registerItem: (ref: RefObject<HTMLElement>) => void;\n removeItem: (ref: RefObject<HTMLElement>) => void;\n initScrollHandlers: () => VoidFunction;\n containerRef: RefObject<HTMLDivElement>;\n positionContainerRef: RefObject<HTMLDivElement>;\n isTouch: boolean;\n}\n\nexport const useScrollContainer = (): UseScrollContainer => {\n const scrollState = useScrollState();\n const { scrollToIndex } = useScrollableControls();\n const [isTouch, setIsTouch] = useState(false);\n const leftCorrection = scrollState.leftCorrection.get();\n const rightCorrection = scrollState.rightCorrection.get();\n const scrollStateRef = useRef<ScrollInternalState>({\n containerRef: useRef<HTMLDivElement>(null),\n positionContainerRef: useRef<HTMLDivElement>(null),\n correction: { leftCorrection, rightCorrection },\n wasInteracted: false,\n });\n scrollStateRef.current.correction = { leftCorrection, rightCorrection };\n const resizeOberverRef = useRef<ResizeObserver | null>(null);\n\n // recalc positions + report widths into store\n const recalculateItemPositions = useCallback(() => {\n const state = scrollStateRef.current;\n const { containerRef, correction, positionContainerRef } = state;\n const { leftCorrection, rightCorrection } = correction;\n const items = scrollState.items.get();\n if (!containerRef.current || !positionContainerRef.current) {\n return;\n }\n const offsetLeft = positionContainerRef.current?.getBoundingClientRect().left ?? 0;\n items.forEach((itemRef) => {\n if (!itemRef.current) {\n return;\n }\n const rect = itemRef.current.getBoundingClientRect();\n itemRef.current[OFFSET_ATTR] = { left: rect.left - offsetLeft, right: rect.right - offsetLeft };\n });\n items.sort((a, b) => (a.current || MAX_OFFSET)[OFFSET_ATTR].left - (b.current || MAX_OFFSET)[OFFSET_ATTR].left);\n const viewportWidth = containerRef.current.offsetWidth - leftCorrection - rightCorrection;\n const contentWidth = items.reduce(\n (pos, itemRef) => Math.max(pos, itemRef.current?.[OFFSET_ATTR]?.right || 0),\n 0\n );\n scrollState.viewportWidth.set(viewportWidth);\n scrollState.contentWidth.set(contentWidth);\n scrollState.items.set(items);\n if (scrollState.indexForDeferScroll !== -1) {\n scrollToIndex(scrollState.indexForDeferScroll);\n scrollState.indexForDeferScroll = -1;\n }\n }, [scrollState, scrollToIndex]);\n\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n const recalculateItemPositionsDebounced = useCallback(debounce(recalculateItemPositions, 10), [\n recalculateItemPositions,\n ]);\n\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n const scrollToItemDebounced = useInitOnce(() =>\n debounce(() => {\n if (scrollState.scrollSnapAlign === 'none') {\n return;\n }\n const targetItemIndex = findIndexNearestToSnapPoint(scrollState);\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, targetItemIndex);\n animateScrollToPosition(scrollState, target);\n }, 100)\n );\n\n useEffect(() => {\n const state = scrollStateRef.current;\n const observer = new ResizeObserver(\n requestAnimation(() => {\n recalculateItemPositions();\n })\n );\n\n scrollState.items.get().forEach((item) => item.current && observer.observe(item.current));\n state.containerRef.current && observer.observe(state.containerRef.current);\n resizeOberverRef.current = observer;\n return () => observer.disconnect();\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, []);\n\n // Слушатель нужен, чтобы не вызывать скролл в родительском контейнере (например в bs)\n useEffect(() => {\n const wrapperRef = scrollStateRef.current.containerRef.current;\n if (!wrapperRef) {\n return void 0;\n }\n const handleTouchStartHandler = (event: TouchEvent) => {\n event.stopPropagation();\n };\n wrapperRef.addEventListener('touchstart', handleTouchStartHandler);\n return () => {\n wrapperRef.removeEventListener('touchstart', handleTouchStartHandler);\n };\n }, []);\n\n // события тача\n const didContainerMove = useRef(false);\n const onTouchStart = useCallback(() => {\n setIsTouch(true);\n didContainerMove.current = false;\n scrollState.scrollPosition.stop();\n }, [scrollState]);\n\n const onTouchMove = useCallback(\n (event: ScrollGestureEvent) => {\n if (!didContainerMove.current) {\n // надо отличить тач от свайпа\n didContainerMove.current = Math.abs(event.delta) > MIN_DELTA_FOR_TOUCH;\n }\n scrollState.scrollPosition.set(\n clamp(\n scrollState.scrollPosition.get() + event.delta,\n scrollState.viewportWidth.get() - scrollState.contentWidth.get(),\n 0\n )\n );\n },\n [scrollState]\n );\n\n const onTouchEnd = useCallback(() => {\n if (didContainerMove.current) {\n scrollToItemDebounced();\n }\n }, [scrollToItemDebounced]);\n\n // события мыши\n const didContainerHovered = useRef(false);\n const onMouseEnter = useCallback(() => {\n didContainerHovered.current = true;\n }, []);\n\n const onWheelMove = useCallback(\n (event: ScrollGestureEvent) => {\n setIsTouch(false);\n if (!didContainerHovered.current) {\n return;\n }\n const currentPosition = scrollState.scrollPosition.get();\n const nextPosition = clamp(\n currentPosition + event.delta,\n scrollState.viewportWidth.get() - scrollState.contentWidth.get(),\n 0\n );\n if (Math.abs(nextPosition - currentPosition) > EPSILON) {\n scrollState.scrollPosition.set(nextPosition);\n scrollToItemDebounced();\n event.preventDefault();\n }\n },\n [scrollToItemDebounced, scrollState]\n );\n\n const onMouseLeave = useCallback(() => {\n didContainerHovered.current = false;\n }, []);\n\n const _initScrollHandlers = useCallback(\n () =>\n initScrollHandlers({\n axis: 'horizontal',\n wrapperRef: scrollStateRef.current.containerRef,\n onTouchStart,\n onTouchMove,\n onTouchEnd,\n onMouseEnter,\n onWheelMove,\n onMouseLeave,\n }),\n [onTouchMove, onTouchEnd, onWheelMove, onTouchStart, onMouseEnter, onMouseLeave]\n );\n\n const registerItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n if (!ref.current) {\n return;\n }\n scrollState.items.get().push(ref as unknown as RefObject<HTMLElement & ItemWithOffset>);\n scrollState.items.set(scrollState.items.get());\n resizeOberverRef.current?.observe(ref.current);\n recalculateItemPositions();\n },\n [recalculateItemPositions, scrollState]\n );\n\n const removeItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n if (!ref.current) {\n return;\n }\n scrollState.items.set(scrollState.items.get().filter((stored) => stored.current !== ref.current));\n resizeOberverRef.current?.unobserve(ref.current);\n recalculateItemPositionsDebounced();\n },\n [recalculateItemPositionsDebounced, scrollState]\n );\n\n return {\n registerItem,\n removeItem,\n initScrollHandlers: _initScrollHandlers,\n containerRef: scrollStateRef.current.containerRef,\n positionContainerRef: scrollStateRef.current.positionContainerRef,\n isTouch,\n };\n};\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useScrollableControls.js","sources":["../src/useScrollableControls.tsx"],"sourcesContent":["import { useCallback, type RefObject } from 'react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll';\nimport { useScrollState, type ScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport type { ScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport {\n findIndexNearestToSnapPoint,\n animateScrollToPosition,\n ensureItemReadyForScroll,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nexport const useScrollableControlsWithState: (scrollState: ScrollState) => ScrollableControls = (scrollState) => {\n const scrollSide = useCallback(\n (toRight: boolean = false) => {\n if (scrollState.scrollSnapAlign === 'none') {\n const delta = toRight ? -scrollState.viewportWidth.get() : scrollState.viewportWidth.get();\n const position = scrollState.scrollPosition.get() + delta;\n animateScrollToPosition(scrollState, position);\n return;\n }\n const index = findIndexNearestToSnapPoint(scrollState);\n const nextIndex = clamp(toRight ? index + 1 : index - 1, 0, scrollState.items.get().length - 1);\n if (!ensureItemReadyForScroll(scrollState, nextIndex)) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, nextIndex);\n animateScrollToPosition(scrollState, target);\n },\n [scrollState]\n );\n\n const scrollToIndex = useCallback(\n (index: number) => {\n if (!ensureItemReadyForScroll(scrollState, index)) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n animateScrollToPosition(scrollState, target);\n },\n [scrollState]\n );\n\n const scrollToFirstItem = useCallback(() => scrollToIndex(0), [scrollToIndex]);\n\n const scrollToLastItem = useCallback(\n () => scrollToIndex(scrollState.items.get().length - 1),\n [scrollState, scrollToIndex]\n );\n\n const scrollToItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n const index = scrollState.items.get().findIndex((item) => item.current && item.current === ref.current);\n index !== -1 && scrollToIndex(index);\n },\n [scrollState, scrollToIndex]\n );\n\n return {\n scrollLeft: () => scrollSide(),\n scrollRight: () => scrollSide(true),\n scrollToFirstItem,\n scrollToLastItem,\n scrollToIndex,\n scrollToItem,\n };\n};\n\nexport const useScrollableControls: () => ScrollableControls = () => {\n const scrollState = useScrollState();\n const controls = useScrollableControlsWithState(scrollState);\n return controls;\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useScrollableControls.js","sources":["src/useScrollableControls.tsx"],"sourcesContent":["import { useCallback, type RefObject } from 'react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll';\nimport { useScrollState, type ScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport type { ScrollableControls } from '@hh.ru/magritte-ui-scrollable-container/types';\nimport {\n findIndexNearestToSnapPoint,\n animateScrollToPosition,\n ensureItemReadyForScroll,\n computeScrollSnapBehavior,\n} from '@hh.ru/magritte-ui-scrollable-container/utils';\n\nexport const useScrollableControlsWithState: (scrollState: ScrollState) => ScrollableControls = (scrollState) => {\n const scrollSide = useCallback(\n (toRight: boolean = false) => {\n if (scrollState.scrollSnapAlign === 'none') {\n const delta = toRight ? -scrollState.viewportWidth.get() : scrollState.viewportWidth.get();\n const position = scrollState.scrollPosition.get() + delta;\n animateScrollToPosition(scrollState, position);\n return;\n }\n const index = findIndexNearestToSnapPoint(scrollState);\n const nextIndex = clamp(toRight ? index + 1 : index - 1, 0, scrollState.items.get().length - 1);\n if (!ensureItemReadyForScroll(scrollState, nextIndex)) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, nextIndex);\n animateScrollToPosition(scrollState, target);\n },\n [scrollState]\n );\n\n const scrollToIndex = useCallback(\n (index: number) => {\n if (!ensureItemReadyForScroll(scrollState, index)) {\n return;\n }\n const scrollSnapBehavior = computeScrollSnapBehavior(scrollState);\n const target = scrollSnapBehavior(scrollState, index);\n animateScrollToPosition(scrollState, target);\n },\n [scrollState]\n );\n\n const scrollToFirstItem = useCallback(() => scrollToIndex(0), [scrollToIndex]);\n\n const scrollToLastItem = useCallback(\n () => scrollToIndex(scrollState.items.get().length - 1),\n [scrollState, scrollToIndex]\n );\n\n const scrollToItem = useCallback(\n (ref: RefObject<HTMLElement>) => {\n const index = scrollState.items.get().findIndex((item) => item.current && item.current === ref.current);\n index !== -1 && scrollToIndex(index);\n },\n [scrollState, scrollToIndex]\n );\n\n return {\n scrollLeft: () => scrollSide(),\n scrollRight: () => scrollSide(true),\n scrollToFirstItem,\n scrollToLastItem,\n scrollToIndex,\n scrollToItem,\n };\n};\n\nexport const useScrollableControls: () => ScrollableControls = () => {\n const scrollState = useScrollState();\n const controls = useScrollableControlsWithState(scrollState);\n return controls;\n};\n"],"names":[],"mappings":"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"}
package/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../src/utils.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { animate } from 'motion/react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll';\nimport { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { type ScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n type SpacingCorrectionProps,\n type ScrollDisableState,\n type ScrollSnapAlign,\n OFFSET_ATTR,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\n\nexport const BREAKPOINTS_LIST = [\n Breakpoint.XS,\n Breakpoint.S,\n Breakpoint.M,\n Breakpoint.L,\n Breakpoint.XL,\n Breakpoint.XXL,\n];\nexport const NO_BUTTONS_START_FROM_BREAKPOINT = Breakpoint.S;\n\nexport function debounce<T extends unknown[]>(callback: (...args: T) => void, waitMs: number): typeof callback {\n let timeout = 0;\n return (...args: T) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => {\n callback(...args);\n }, waitMs) as unknown as number;\n };\n}\n\ninterface ActualCorrection {\n leftCorrection: number;\n rightCorrection: number;\n}\n\n/**\n * По переданным параметрам коррекции возвращает значения отступов для текущего брейкпоинта\n * @param props Параметры коррекции\n * @param breakpoint Текуший брейкпоинт\n * @returns Объект содержащий значения отступов\n */\nexport const getActualCorrection = (props: SpacingCorrectionProps, breakpoint: Breakpoint): ActualCorrection => {\n const breakpointIndex = BREAKPOINTS_LIST.indexOf(breakpoint);\n let leftCorrection: number | undefined;\n let rightCorrection: number | undefined;\n // Проходимся по всем брейкпоинтам, начиная с текущего в сторону меньших разрешений\n for (let i = breakpointIndex; i >= 0; i--) {\n const breakpointName = BREAKPOINTS_LIST[i].toUpperCase();\n // Ключи, которые могут быть в параметрах коррекции (SpacingCorrectionProps)\n const leftCorrectionKey = `correctionLeft${breakpointName}` as keyof SpacingCorrectionProps;\n const rightCorrectionKey = `correctionRight${breakpointName}` as keyof SpacingCorrectionProps;\n const commonCorrectionKey = `correction${breakpointName}` as keyof SpacingCorrectionProps;\n // Если для текущего брейкпоинта есть параметры коррекции для левой/правой стороны, то берем их\n props[leftCorrectionKey] !== undefined &&\n leftCorrection === undefined &&\n (leftCorrection = props[leftCorrectionKey]);\n props[rightCorrectionKey] !== undefined &&\n rightCorrection === undefined &&\n (rightCorrection = props[rightCorrectionKey]);\n\n // Если для левой или правой стороны не найден параметр коррекции, то пробуем взять параметр correction для\n // брейкпоинта который сейчас обрабатываем в цикле, например correctionM\n if (props[commonCorrectionKey] !== undefined) {\n leftCorrection === undefined && (leftCorrection = props[commonCorrectionKey]);\n rightCorrection === undefined && (rightCorrection = props[commonCorrectionKey]);\n }\n\n // Если нашли значения для обеих сторон - возращаем\n if (leftCorrection !== undefined && rightCorrection !== undefined) {\n return { leftCorrection, rightCorrection };\n }\n }\n // Если не нашли значение для какой то из сторон, то берем значение из correction, без уточнения брейкпоинта\n return {\n leftCorrection: leftCorrection === undefined ? props.correction || 0 : leftCorrection,\n rightCorrection: rightCorrection === undefined ? props.correction || 0 : rightCorrection,\n };\n};\n\nexport const useInitOnce = <T>(func: () => T): T => {\n const initializedRef = useRef<T | undefined>(undefined);\n if (initializedRef.current === undefined) {\n initializedRef.current = func();\n }\n return initializedRef.current;\n};\n\n/**\n * На основе стейта расчитывает флаги скрола\n * @param scrollState стейт скролла\n * @returns cостояние блокировки скролла\n */\nexport const getDisableState = (scrollState: ScrollState): ScrollDisableState => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n return {\n isScrollLeftDisabled: scrollPosition.get() >= 0,\n isScrollRightDisabled: Math.abs(scrollPosition.get()) + viewportWidth.get() >= contentWidth.get(),\n };\n};\n\n/**\n * Анимирует scrollPosition с учетом границ контенера\n * @param scrollState стейт скролла\n * @param position новая позиция\n * @returns void\n */\nexport const animateScrollToPosition = (scrollState: ScrollState, position: number | null): void => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n if (position === null || scrollPosition.get() === position) {\n return;\n }\n const clampedPosition = clamp(position, viewportWidth.get() - contentWidth.get(), 0);\n animate(scrollPosition, clampedPosition, {\n velocity: Math.max(scrollPosition.getVelocity(), 1),\n });\n};\n\n/**\n * scrollTo* может быть вызвана раньше чем появяться метрики элементов\n * например, scrollToIndex функция может вызвана в useEffect в tabs\n * запоминаем индекс и вызовем скролл, когда метрики будут посчитаны\n */\nexport const ensureItemReadyForScroll = (scrollState: ScrollState, index: number): boolean => {\n const { items } = scrollState;\n const item = items.get()[index]?.current;\n if (!item || !item[OFFSET_ATTR]) {\n scrollState.indexForDeferScroll = index;\n return false;\n }\n return true;\n};\n\n/**\n * Возвращает якорную точку отрезка в зависимости от scrollSnapAlign.\n *\n * start — левая граница элемента\n * center — центр элемента\n * end — правая граница элемента\n *\n * @param left левая граница элемента\n * @param right правая граница элемента\n * @param align режим выравнивания (scroll-snap-align)\n * @returns координата якорной точки элемента\n */\nconst getAnchorPoint = (left: number, right: number, align: ScrollSnapAlign): number => {\n let point = 0;\n switch (align) {\n case 'center':\n point = (left + right) / 2;\n break;\n case 'end':\n point = right;\n break;\n case 'start':\n default:\n point = left;\n }\n return point;\n};\n\n/**\n * Вычисляет целевую точку прокрутки в зависимости от режима scroll-snap выравнивания.\n *\n * В качестве базовой позиции используется текущее значение scrollLeft,\n * к которому добавляется смещение, зависящее от `scrollSnapAlign`:\n * - start — начало области просмотра\n * - center — центр области просмотра\n * - end — конец области просмотра\n *\n * @param state Текущее состояние скролл\n * @returns Координата целевой точки прокрутки\n */\nconst getTargetPoint = (state: ScrollState): number => {\n const scrollLeft = Math.abs(state.scrollPosition.get());\n let point = 0;\n switch (state.scrollSnapAlign) {\n case 'center':\n point = scrollLeft + state.viewportWidth.get() / 2;\n break;\n case 'end':\n point = scrollLeft + state.viewportWidth.get();\n break;\n case 'start':\n default:\n point = scrollLeft;\n }\n return point;\n};\n\n/**\n * На основе позиции, находит ближайший элемент к центру viewport\n * @param scrollState стейт скролла\n * @returns индекс найденого элемента\n */\nexport const findIndexNearestToSnapPoint = (state: ScrollState): number => {\n const items = state.items.get();\n if (items.length === 0) {\n return 0;\n }\n const targetPoint = getTargetPoint(state);\n let idx = 0;\n let minDist = Infinity;\n for (let key = 0; key < items.length; key++) {\n const element = items[key]?.current;\n if (element && element[OFFSET_ATTR]) {\n const { left, right } = element[OFFSET_ATTR];\n const anchor = getAnchorPoint(left, right, state.scrollSnapAlign);\n const dist = Math.abs(targetPoint - anchor);\n if (dist < minDist) {\n minDist = dist;\n idx = key;\n }\n }\n }\n return idx;\n};\n\ninterface ScrollBehavior {\n (scrollState: ScrollState, index: number): number | null;\n}\n\n/**\n * Определят позицию, при которой элемент будет находится на левой границе viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeStartPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, defaultButtonsCorrection } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n return -offset.left + defaultButtonsCorrection.get();\n};\n\n/**\n * Определят позицию, при которой элемент будет находится на правой границе viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeEndPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, defaultButtonsCorrection, viewportWidth } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n return -offset.right + viewportWidth.get() - defaultButtonsCorrection.get();\n};\n\n/**\n * Определят позицию, при которой элемент будет в центре viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeCenterPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, viewportWidth } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n const itemWidth = offset.right - offset.left;\n const itemCenter = offset.left + itemWidth / 2;\n const viewportCenter = viewportWidth.get() / 2;\n return viewportCenter - itemCenter;\n};\n\n/**\n * Определят позицию, при которой элемент будет находится во viewport (с учетом боковых кнопок в fade)\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computePositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, viewportWidth, scrollPosition, defaultButtonsCorrection } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n const viewportLeft = -scrollPosition.get() + defaultButtonsCorrection.get();\n const viewportRight = viewportLeft + viewportWidth.get() - defaultButtonsCorrection.get();\n if (offset.left >= viewportLeft && offset.right <= viewportRight) {\n return scrollPosition.get();\n }\n if (offset.left < viewportLeft) {\n return -(offset.left - defaultButtonsCorrection.get());\n }\n return viewportWidth.get() - offset.right - defaultButtonsCorrection.get();\n};\n\n/**\n * Определят поведение \"подскрола\" ближайшего элемента\n * @param scrollState стейт скролла\n * @returns StrategyPosition\n */\nexport const computeScrollSnapBehavior = (scrollState: ScrollState): ScrollBehavior => {\n switch (scrollState.scrollSnapAlign) {\n case 'center':\n return computeCenterPositionForIndex;\n case 'start':\n return computeStartPositionForIndex;\n case 'end':\n return computeEndPositionForIndex;\n case 'none':\n default:\n return computePositionForIndex;\n }\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["src/utils.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { animate } from 'motion/react';\n\nimport { clamp } from '@hh.ru/magritte-internal-custom-scroll';\nimport { Breakpoint } from '@hh.ru/magritte-ui-breakpoint';\nimport { type ScrollState } from '@hh.ru/magritte-ui-scrollable-container/ScrollStateProvider';\nimport {\n type SpacingCorrectionProps,\n type ScrollDisableState,\n type ScrollSnapAlign,\n OFFSET_ATTR,\n} from '@hh.ru/magritte-ui-scrollable-container/types';\n\nexport const BREAKPOINTS_LIST = [\n Breakpoint.XS,\n Breakpoint.S,\n Breakpoint.M,\n Breakpoint.L,\n Breakpoint.XL,\n Breakpoint.XXL,\n];\nexport const NO_BUTTONS_START_FROM_BREAKPOINT = Breakpoint.S;\n\nexport function debounce<T extends unknown[]>(callback: (...args: T) => void, waitMs: number): typeof callback {\n let timeout = 0;\n return (...args: T) => {\n clearTimeout(timeout);\n timeout = setTimeout(() => {\n callback(...args);\n }, waitMs) as unknown as number;\n };\n}\n\ninterface ActualCorrection {\n leftCorrection: number;\n rightCorrection: number;\n}\n\n/**\n * По переданным параметрам коррекции возвращает значения отступов для текущего брейкпоинта\n * @param props Параметры коррекции\n * @param breakpoint Текуший брейкпоинт\n * @returns Объект содержащий значения отступов\n */\nexport const getActualCorrection = (props: SpacingCorrectionProps, breakpoint: Breakpoint): ActualCorrection => {\n const breakpointIndex = BREAKPOINTS_LIST.indexOf(breakpoint);\n let leftCorrection: number | undefined;\n let rightCorrection: number | undefined;\n // Проходимся по всем брейкпоинтам, начиная с текущего в сторону меньших разрешений\n for (let i = breakpointIndex; i >= 0; i--) {\n const breakpointName = BREAKPOINTS_LIST[i].toUpperCase();\n // Ключи, которые могут быть в параметрах коррекции (SpacingCorrectionProps)\n const leftCorrectionKey = `correctionLeft${breakpointName}` as keyof SpacingCorrectionProps;\n const rightCorrectionKey = `correctionRight${breakpointName}` as keyof SpacingCorrectionProps;\n const commonCorrectionKey = `correction${breakpointName}` as keyof SpacingCorrectionProps;\n // Если для текущего брейкпоинта есть параметры коррекции для левой/правой стороны, то берем их\n props[leftCorrectionKey] !== undefined &&\n leftCorrection === undefined &&\n (leftCorrection = props[leftCorrectionKey]);\n props[rightCorrectionKey] !== undefined &&\n rightCorrection === undefined &&\n (rightCorrection = props[rightCorrectionKey]);\n\n // Если для левой или правой стороны не найден параметр коррекции, то пробуем взять параметр correction для\n // брейкпоинта который сейчас обрабатываем в цикле, например correctionM\n if (props[commonCorrectionKey] !== undefined) {\n leftCorrection === undefined && (leftCorrection = props[commonCorrectionKey]);\n rightCorrection === undefined && (rightCorrection = props[commonCorrectionKey]);\n }\n\n // Если нашли значения для обеих сторон - возращаем\n if (leftCorrection !== undefined && rightCorrection !== undefined) {\n return { leftCorrection, rightCorrection };\n }\n }\n // Если не нашли значение для какой то из сторон, то берем значение из correction, без уточнения брейкпоинта\n return {\n leftCorrection: leftCorrection === undefined ? props.correction || 0 : leftCorrection,\n rightCorrection: rightCorrection === undefined ? props.correction || 0 : rightCorrection,\n };\n};\n\nexport const useInitOnce = <T>(func: () => T): T => {\n const initializedRef = useRef<T | undefined>(undefined);\n if (initializedRef.current === undefined) {\n initializedRef.current = func();\n }\n return initializedRef.current;\n};\n\n/**\n * На основе стейта расчитывает флаги скрола\n * @param scrollState стейт скролла\n * @returns cостояние блокировки скролла\n */\nexport const getDisableState = (scrollState: ScrollState): ScrollDisableState => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n return {\n isScrollLeftDisabled: scrollPosition.get() >= 0,\n isScrollRightDisabled: Math.abs(scrollPosition.get()) + viewportWidth.get() >= contentWidth.get(),\n };\n};\n\n/**\n * Анимирует scrollPosition с учетом границ контенера\n * @param scrollState стейт скролла\n * @param position новая позиция\n * @returns void\n */\nexport const animateScrollToPosition = (scrollState: ScrollState, position: number | null): void => {\n const { scrollPosition, viewportWidth, contentWidth } = scrollState;\n if (position === null || scrollPosition.get() === position) {\n return;\n }\n const clampedPosition = clamp(position, viewportWidth.get() - contentWidth.get(), 0);\n animate(scrollPosition, clampedPosition, {\n velocity: Math.max(scrollPosition.getVelocity(), 1),\n });\n};\n\n/**\n * scrollTo* может быть вызвана раньше чем появяться метрики элементов\n * например, scrollToIndex функция может вызвана в useEffect в tabs\n * запоминаем индекс и вызовем скролл, когда метрики будут посчитаны\n */\nexport const ensureItemReadyForScroll = (scrollState: ScrollState, index: number): boolean => {\n const { items } = scrollState;\n const item = items.get()[index]?.current;\n if (!item || !item[OFFSET_ATTR]) {\n scrollState.indexForDeferScroll = index;\n return false;\n }\n return true;\n};\n\n/**\n * Возвращает якорную точку отрезка в зависимости от scrollSnapAlign.\n *\n * start — левая граница элемента\n * center — центр элемента\n * end — правая граница элемента\n *\n * @param left левая граница элемента\n * @param right правая граница элемента\n * @param align режим выравнивания (scroll-snap-align)\n * @returns координата якорной точки элемента\n */\nconst getAnchorPoint = (left: number, right: number, align: ScrollSnapAlign): number => {\n let point = 0;\n switch (align) {\n case 'center':\n point = (left + right) / 2;\n break;\n case 'end':\n point = right;\n break;\n case 'start':\n default:\n point = left;\n }\n return point;\n};\n\n/**\n * Вычисляет целевую точку прокрутки в зависимости от режима scroll-snap выравнивания.\n *\n * В качестве базовой позиции используется текущее значение scrollLeft,\n * к которому добавляется смещение, зависящее от `scrollSnapAlign`:\n * - start — начало области просмотра\n * - center — центр области просмотра\n * - end — конец области просмотра\n *\n * @param state Текущее состояние скролл\n * @returns Координата целевой точки прокрутки\n */\nconst getTargetPoint = (state: ScrollState): number => {\n const scrollLeft = Math.abs(state.scrollPosition.get());\n let point = 0;\n switch (state.scrollSnapAlign) {\n case 'center':\n point = scrollLeft + state.viewportWidth.get() / 2;\n break;\n case 'end':\n point = scrollLeft + state.viewportWidth.get();\n break;\n case 'start':\n default:\n point = scrollLeft;\n }\n return point;\n};\n\n/**\n * На основе позиции, находит ближайший элемент к центру viewport\n * @param scrollState стейт скролла\n * @returns индекс найденого элемента\n */\nexport const findIndexNearestToSnapPoint = (state: ScrollState): number => {\n const items = state.items.get();\n if (items.length === 0) {\n return 0;\n }\n const targetPoint = getTargetPoint(state);\n let idx = 0;\n let minDist = Infinity;\n for (let key = 0; key < items.length; key++) {\n const element = items[key]?.current;\n if (element && element[OFFSET_ATTR]) {\n const { left, right } = element[OFFSET_ATTR];\n const anchor = getAnchorPoint(left, right, state.scrollSnapAlign);\n const dist = Math.abs(targetPoint - anchor);\n if (dist < minDist) {\n minDist = dist;\n idx = key;\n }\n }\n }\n return idx;\n};\n\ninterface ScrollBehavior {\n (scrollState: ScrollState, index: number): number | null;\n}\n\n/**\n * Определят позицию, при которой элемент будет находится на левой границе viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeStartPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, defaultButtonsCorrection } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n return -offset.left + defaultButtonsCorrection.get();\n};\n\n/**\n * Определят позицию, при которой элемент будет находится на правой границе viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeEndPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, defaultButtonsCorrection, viewportWidth } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n return -offset.right + viewportWidth.get() - defaultButtonsCorrection.get();\n};\n\n/**\n * Определят позицию, при которой элемент будет в центре viewport\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computeCenterPositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, viewportWidth } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n const itemWidth = offset.right - offset.left;\n const itemCenter = offset.left + itemWidth / 2;\n const viewportCenter = viewportWidth.get() / 2;\n return viewportCenter - itemCenter;\n};\n\n/**\n * Определят позицию, при которой элемент будет находится во viewport (с учетом боковых кнопок в fade)\n * @param scrollState стейт скролла\n * @param index индекс элемента\n * @returns новая позиция\n */\nexport const computePositionForIndex: ScrollBehavior = (scrollState, index) => {\n const { items, viewportWidth, scrollPosition, defaultButtonsCorrection } = scrollState;\n const itemRef = items.get()[index];\n if (!itemRef?.current) {\n return null;\n }\n const offset = itemRef.current[OFFSET_ATTR];\n const viewportLeft = -scrollPosition.get() + defaultButtonsCorrection.get();\n const viewportRight = viewportLeft + viewportWidth.get() - defaultButtonsCorrection.get();\n if (offset.left >= viewportLeft && offset.right <= viewportRight) {\n return scrollPosition.get();\n }\n if (offset.left < viewportLeft) {\n return -(offset.left - defaultButtonsCorrection.get());\n }\n return viewportWidth.get() - offset.right - defaultButtonsCorrection.get();\n};\n\n/**\n * Определят поведение \"подскрола\" ближайшего элемента\n * @param scrollState стейт скролла\n * @returns StrategyPosition\n */\nexport const computeScrollSnapBehavior = (scrollState: ScrollState): ScrollBehavior => {\n switch (scrollState.scrollSnapAlign) {\n case 'center':\n return computeCenterPositionForIndex;\n case 'start':\n return computeStartPositionForIndex;\n case 'end':\n return computeEndPositionForIndex;\n case 'none':\n default:\n return computePositionForIndex;\n }\n};\n"],"names":[],"mappings":"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"}
@@ -1,5 +0,0 @@
1
- import './index.css';
2
- var styles = {"scroll-wrapper":"magritte-scroll-wrapper___vTdZl_6-2-1","scrollWrapper":"magritte-scroll-wrapper___vTdZl_6-2-1","scrollable-container":"magritte-scrollable-container___AKIUp_6-2-1","scrollableContainer":"magritte-scrollable-container___AKIUp_6-2-1","scroll-buttons-container":"magritte-scroll-buttons-container___ZeI5a_6-2-1","scrollButtonsContainer":"magritte-scroll-buttons-container___ZeI5a_6-2-1","scroll-buttons":"magritte-scroll-buttons___0SjoR_6-2-1","scrollButtons":"magritte-scroll-buttons___0SjoR_6-2-1","scroll-button":"magritte-scroll-button___4GQu3_6-2-1","scrollButton":"magritte-scroll-button___4GQu3_6-2-1","scroll-button-left":"magritte-scroll-button-left___UueEY_6-2-1","scrollButtonLeft":"magritte-scroll-button-left___UueEY_6-2-1","scroll-button-right":"magritte-scroll-button-right___wZOn-_6-2-1","scrollButtonRight":"magritte-scroll-button-right___wZOn-_6-2-1","position-container":"magritte-position-container___1A4Bv_6-2-1","positionContainer":"magritte-position-container___1A4Bv_6-2-1","dot-container":"magritte-dot-container___ahtlG_6-2-1","dotContainer":"magritte-dot-container___ahtlG_6-2-1"};
3
-
4
- export { styles as s };
5
- //# sourceMappingURL=scrollableContainer-Dl-Nl71V.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scrollableContainer-Dl-Nl71V.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}