@egjs/flicking
Advanced tools
Comparing version 4.2.0 to 4.2.1
@@ -0,1 +1,2 @@ | ||
import AnchorPoint from "../core/AnchorPoint"; | ||
import Camera from "./Camera"; | ||
@@ -5,4 +6,5 @@ declare class BoundCamera extends Camera { | ||
updateAnchors(): this; | ||
findAnchorIncludePosition(position: number): AnchorPoint | null; | ||
private _findNearestPanel; | ||
} | ||
export default BoundCamera; |
@@ -63,2 +63,3 @@ import Flicking, { FlickingOptions } from "../Flicking"; | ||
findNearestAnchor(position: number): AnchorPoint | null; | ||
findActiveAnchor(): AnchorPoint | null; | ||
clampToReachablePosition(position: number): number; | ||
@@ -65,0 +66,0 @@ canReach(panel: Panel): boolean; |
@@ -29,4 +29,4 @@ import Axes, { OnRelease } from "@egjs/axes"; | ||
update(controlParams: ControlParams): this; | ||
addPreventClickHandler(): void; | ||
removePreventClickHandler(): void; | ||
addPreventClickHandler(): this; | ||
removePreventClickHandler(): this; | ||
animateTo(position: number, duration: number, axesEvent?: OnRelease): Promise<void>; | ||
@@ -33,0 +33,0 @@ private _resetInternalValues; |
import Control from "./Control"; | ||
import SnapControl from "./SnapControl"; | ||
import SnapControl, { SnapControlOptions } from "./SnapControl"; | ||
import FreeControl, { FreeControlOptions } from "./FreeControl"; | ||
@@ -14,2 +14,2 @@ import StrictControl, { StrictControlOptions } from "./StrictControl"; | ||
export { Control, SnapControl, FreeControl, StrictControl, AxesController, State, IdleState, HoldingState, DraggingState, AnimatingState, DisabledState, StateMachine }; | ||
export type { FreeControlOptions, StrictControlOptions }; | ||
export type { SnapControlOptions, FreeControlOptions, StrictControlOptions }; |
import { OnRelease } from "@egjs/axes"; | ||
import Control from "./Control"; | ||
export interface SnapControlOptions { | ||
count: number; | ||
} | ||
declare class SnapControl extends Control { | ||
private _count; | ||
get count(): SnapControlOptions["count"]; | ||
set count(val: SnapControlOptions["count"]); | ||
constructor({ count }?: Partial<SnapControlOptions>); | ||
moveToPosition(position: number, duration: number, axesEvent?: OnRelease): Promise<void>; | ||
private _findSnappedAnchor; | ||
private _findAdjacentAnchor; | ||
private _calcSnapThreshold; | ||
} | ||
export default SnapControl; |
@@ -5,2 +5,3 @@ import State from "./State"; | ||
readonly animating = false; | ||
onEnter(): void; | ||
onHold(ctx: Parameters<State["onHold"]>[0]): void; | ||
@@ -7,0 +8,0 @@ onChange(ctx: Parameters<State["onChange"]>[0]): void; |
@@ -13,2 +13,5 @@ import { OnAnimationEnd, OnChange, OnFinish, OnHold, OnRelease } from "@egjs/axes"; | ||
abstract readonly animating: boolean; | ||
protected _delta: number; | ||
get delta(): number; | ||
onEnter(prevState: State): void; | ||
onHold(ctx: { | ||
@@ -15,0 +18,0 @@ flicking: Flicking; |
import Flicking from "../Flicking"; | ||
import { FreeControlOptions, StrictControlOptions } from "../control"; | ||
import { SnapControlOptions, FreeControlOptions, StrictControlOptions } from "../control"; | ||
import { MOVE_TYPE } from "../const/external"; | ||
@@ -23,3 +23,3 @@ import { ValueOf } from "../type/internal"; | ||
} | ||
export declare type MoveTypeOptions<T extends ValueOf<typeof MOVE_TYPE>> = T extends typeof MOVE_TYPE.FREE_SCROLL ? [T] | [T, Partial<FreeControlOptions>] : T extends typeof MOVE_TYPE.STRICT ? [T] | [T, Partial<StrictControlOptions>] : [ | ||
export declare type MoveTypeOptions<T extends ValueOf<typeof MOVE_TYPE>> = T extends typeof MOVE_TYPE.SNAP ? [T] | [T, Partial<SnapControlOptions>] : T extends typeof MOVE_TYPE.FREE_SCROLL ? [T] | [T, Partial<FreeControlOptions>] : T extends typeof MOVE_TYPE.STRICT ? [T] | [T, Partial<StrictControlOptions>] : [ | ||
T | ||
@@ -26,0 +26,0 @@ ]; |
@@ -31,1 +31,2 @@ import Flicking, { FlickingOptions } from "./Flicking"; | ||
export declare const isBetween: (val: number, min: number, max: number) => boolean; | ||
export declare const circulateIndex: (index: number, max: number) => number; |
{ | ||
"name": "@egjs/flicking", | ||
"version": "4.2.0", | ||
"version": "4.2.1", | ||
"description": "Everyday 30 million people experience. It's reliable, flexible and extendable carousel.", | ||
@@ -40,5 +40,5 @@ "main": "dist/flicking.js", | ||
"packages": "npm run packages:update && npm run packages:build && npm run packages:publish", | ||
"packages:update": "pvu --update=react-flicking,ngx-flicking/projects/ngx-flicking,vue-flicking,vue3-flicking", | ||
"packages:build": "pvu --build=react-flicking,ngx-flicking,vue-flicking,vue3-flicking", | ||
"packages:publish": "pvu --publish=react-flicking,ngx-flicking/dist/ngx-flicking,vue-flicking,vue3-flicking", | ||
"packages:update": "pvu --update=react-flicking,ngx-flicking/projects/ngx-flicking,vue-flicking,vue3-flicking,svelte-flicking", | ||
"packages:build": "pvu --build=react-flicking,ngx-flicking,vue-flicking,vue3-flicking,svelte-flicking", | ||
"packages:publish": "pvu --publish=react-flicking,ngx-flicking/dist/ngx-flicking,vue-flicking,vue3-flicking,svelte-flicking", | ||
"storybook": "npm run storybook:all & npm run storybook:main", | ||
@@ -45,0 +45,0 @@ "storybook:main": "node_modules/@storybook/react/bin/index.js -p 6006", |
@@ -139,3 +139,3 @@ <h1 align="center" style="max-width: 100%;"> | ||
|:---:|:---:|:---:|:---:|:---:|:---:| | ||
|9+(With polyfill), 11+ for Angular|Latest|Latest|Latest|7+|4+| | ||
|9+(With polyfill), 11+ for Angular & Svelte|Latest|Latest|Latest|7+|4+| | ||
@@ -142,0 +142,0 @@ ## 📼 Demos |
@@ -124,2 +124,17 @@ /* | ||
public findAnchorIncludePosition(position: number): AnchorPoint | null { | ||
const range = this._range; | ||
const anchors = this._anchors; | ||
if (anchors.length <= 0) return null; | ||
if (position <= range.min) { | ||
return anchors[0]; | ||
} else if (position >= range.max) { | ||
return anchors[anchors.length - 1]; | ||
} else { | ||
return super.findAnchorIncludePosition(position); | ||
} | ||
} | ||
private _findNearestPanel(pos: number, panels: Panel[]): Panel { | ||
@@ -126,0 +141,0 @@ let prevDist = Infinity; |
@@ -13,3 +13,3 @@ /* | ||
import { ALIGN, DIRECTION, EVENTS } from "../const/external"; | ||
import { checkExistence, clamp, getFlickingAttached, getProgress, includes, parseAlign } from "../utils"; | ||
import { checkExistence, clamp, find, getFlickingAttached, getProgress, includes, parseAlign } from "../utils"; | ||
@@ -375,2 +375,14 @@ export interface CameraOptions { | ||
/** | ||
* Return {@link AnchorPoint} that matches {@link Flicking#currentPanel} | ||
* @ko 현재 {@link Flicking#currentPanel}에 해당하는 {@link AnchorPoint}를 반환합니다 | ||
* @return {AnchorPoint | null} | ||
*/ | ||
public findActiveAnchor(): AnchorPoint | null { | ||
const flicking = getFlickingAttached(this._flicking, "Camera"); | ||
const activeIndex = flicking.control.activeIndex; | ||
return find(this._anchors, anchor => anchor.panel.index === activeIndex); | ||
} | ||
/** | ||
* Clamp the given position between camera's range | ||
@@ -377,0 +389,0 @@ * @ko 주어진 좌표를 Camera가 도달 가능한 범위 사이의 값으로 만듭니다 |
@@ -11,3 +11,3 @@ /* | ||
import * as ERROR from "../const/error"; | ||
import { getFlickingAttached, parseBounce } from "../utils"; | ||
import { circulatePosition, getFlickingAttached, parseBounce } from "../utils"; | ||
import { ControlParams } from "../type/external"; | ||
@@ -223,3 +223,8 @@ | ||
public addPreventClickHandler() { | ||
/** | ||
* Attach a handler to the camera element to prevent click events during animation | ||
* @ko 카메라 엘리먼트에 애니메이션 도중에 클릭 이벤트를 방지하는 핸들러를 부착합니다 | ||
* @return {this} | ||
*/ | ||
public addPreventClickHandler(): this { | ||
const flicking = getFlickingAttached(this._flicking, "Control"); | ||
@@ -232,5 +237,12 @@ const axes = this._axes!; | ||
cameraEl.addEventListener("click", this._preventClickWhenDragged, true); | ||
return this; | ||
} | ||
public removePreventClickHandler() { | ||
/** | ||
* Detach a handler to the camera element to prevent click events during animation | ||
* @ko 카메라 엘리먼트에 애니메이션 도중에 클릭 이벤트를 방지하는 핸들러를 탈착합니다 | ||
* @return {this} | ||
*/ | ||
public removePreventClickHandler(): this { | ||
const flicking = getFlickingAttached(this._flicking, "Control"); | ||
@@ -243,2 +255,4 @@ const axes = this._axes!; | ||
cameraEl.removeEventListener("click", this._preventClickWhenDragged, true); | ||
return this; | ||
} | ||
@@ -303,5 +317,13 @@ | ||
if (duration === 0) { | ||
const flicking = getFlickingAttached(this._flicking, "Control"); | ||
const camera = flicking.camera; | ||
animate(); | ||
axes.axm.set({ [AXES.POSITION_KEY]: position }); | ||
const newPos = flicking.circularEnabled | ||
? circulatePosition(position, camera.range.min, camera.range.max) | ||
: position; | ||
axes.axm.set({ [AXES.POSITION_KEY]: newPos }); | ||
return Promise.resolve(); | ||
@@ -308,0 +330,0 @@ } else { |
@@ -6,3 +6,3 @@ /* | ||
import Control from "./Control"; | ||
import SnapControl from "./SnapControl"; | ||
import SnapControl, { SnapControlOptions } from "./SnapControl"; | ||
import FreeControl, { FreeControlOptions } from "./FreeControl"; | ||
@@ -35,4 +35,5 @@ import StrictControl, { StrictControlOptions } from "./StrictControl"; | ||
export type { | ||
SnapControlOptions, | ||
FreeControlOptions, | ||
StrictControlOptions | ||
}; |
@@ -7,5 +7,6 @@ /* | ||
import Panel from "../core/panel/Panel"; | ||
import FlickingError from "../core/FlickingError"; | ||
import { getFlickingAttached } from "../utils"; | ||
import AnchorPoint from "../core/AnchorPoint"; | ||
import { circulateIndex, clamp, getFlickingAttached } from "../utils"; | ||
import * as AXES from "../const/axes"; | ||
import * as ERROR from "../const/error"; | ||
@@ -16,2 +17,12 @@ | ||
/** | ||
* An options for the {@link SnapControl} | ||
* @ko {@link SnapControl} 생성시 사용되는 옵션 | ||
* @interface | ||
* @property {number} count Maximum number of panels can go after release<ko>입력 중단 이후 통과하여 이동할 수 있는 패널의 최대 갯수</ko> | ||
*/ | ||
export interface SnapControlOptions { | ||
count: number; | ||
} | ||
/** | ||
* A {@link Control} that uses a release momentum to choose destination panel | ||
@@ -21,3 +32,24 @@ * @ko 입력을 중단한 시점의 가속도에 영향받아 도달할 패널을 계산하는 이동 방식을 사용하는 {@link Control} | ||
class SnapControl extends Control { | ||
private _count: SnapControlOptions["count"]; | ||
/** | ||
* Maximum number of panels can go after release | ||
* @ko 입력 중단 이후 통과하여 이동할 수 있는 패널의 최대 갯수 | ||
* @type {number} | ||
* @default Infinity | ||
*/ | ||
public get count() { return this._count; } | ||
public set count(val: SnapControlOptions["count"]) { this._count = val; } | ||
/** */ | ||
public constructor({ | ||
count = Infinity | ||
}: Partial<SnapControlOptions> = {}) { | ||
super(); | ||
this._count = count; | ||
} | ||
/** | ||
* Move {@link Camera} to the given position | ||
@@ -61,46 +93,131 @@ * @ko {@link Camera}를 주어진 좌표로 이동합니다 | ||
const camera = flicking.camera; | ||
const activePanel = this._activePanel; | ||
const activeAnchor = camera.findActiveAnchor(); | ||
const anchorAtCamera = camera.findNearestAnchor(camera.position); | ||
const state = flicking.control.controller.state; | ||
const clampedPosition = camera.clampToReachablePosition(position); | ||
const anchorAtPosition = camera.findNearestAnchor(clampedPosition); | ||
if (!anchorAtPosition || !activePanel) { | ||
if (!activeAnchor || !anchorAtCamera) { | ||
return Promise.reject(new FlickingError(ERROR.MESSAGE.POSITION_NOT_REACHABLE(position), ERROR.CODE.POSITION_NOT_REACHABLE)); | ||
} | ||
const prevPos = activePanel.position; | ||
const snapThreshold = this._calcSnapThreshold(position, activeAnchor); | ||
const isOverThreshold = Math.abs(position - prevPos) >= flicking.threshold; | ||
const adjacentAnchor = (position > prevPos) | ||
? camera.getNextAnchor(anchorAtPosition) | ||
: camera.getPrevAnchor(anchorAtPosition); | ||
const posDelta = flicking.animating | ||
? state.delta | ||
: position - camera.position; | ||
const absPosDelta = Math.abs(posDelta); | ||
const snapDelta = axesEvent && axesEvent.delta[AXES.POSITION_KEY] !== 0 | ||
? Math.abs(axesEvent.delta[AXES.POSITION_KEY]) | ||
: absPosDelta; | ||
let targetAnchor: AnchorPoint; | ||
let targetPos: number; | ||
let targetPanel: Panel; | ||
if (isOverThreshold && anchorAtPosition.position !== activePanel.position) { | ||
if (snapDelta >= snapThreshold && snapDelta > 0) { | ||
// Move to anchor at position | ||
targetPanel = anchorAtPosition.panel; | ||
targetPos = anchorAtPosition.position; | ||
} else if (isOverThreshold && adjacentAnchor) { | ||
// Move to adjacent anchor | ||
targetPanel = adjacentAnchor.panel; | ||
targetPos = adjacentAnchor.position; | ||
targetAnchor = this._findSnappedAnchor(position, anchorAtCamera); | ||
} else if (absPosDelta >= flicking.threshold && absPosDelta > 0) { | ||
// Move to the adjacent panel | ||
targetAnchor = this._findAdjacentAnchor(posDelta, anchorAtCamera); | ||
} else { | ||
// Restore to active panel | ||
targetPos = camera.clampToReachablePosition(activePanel.position); | ||
targetPanel = activePanel; | ||
targetAnchor = anchorAtCamera; | ||
} | ||
this._triggerIndexChangeEvent(targetPanel, position, axesEvent); | ||
this._triggerIndexChangeEvent(targetAnchor.panel, position, axesEvent); | ||
return this._animateToPosition({ | ||
position: targetPos, | ||
position: camera.clampToReachablePosition(targetAnchor.position), | ||
duration, | ||
newActivePanel: targetPanel, | ||
newActivePanel: targetAnchor.panel, | ||
axesEvent | ||
}); | ||
} | ||
private _findSnappedAnchor(position: number, anchorAtCamera: AnchorPoint): AnchorPoint { | ||
const flicking = getFlickingAttached(this._flicking, "Control"); | ||
const camera = flicking.camera; | ||
const count = this._count; | ||
const currentPos = camera.position; | ||
const clampedPosition = camera.clampToReachablePosition(position); | ||
const anchorAtPosition = camera.findAnchorIncludePosition(clampedPosition); | ||
if (!anchorAtCamera || !anchorAtPosition) { | ||
throw new FlickingError(ERROR.MESSAGE.POSITION_NOT_REACHABLE(position), ERROR.CODE.POSITION_NOT_REACHABLE); | ||
} | ||
if (!isFinite(count)) { | ||
return anchorAtPosition; | ||
} | ||
const panelCount = flicking.panelCount; | ||
const anchors = camera.anchorPoints; | ||
let loopCount = Math.sign(position - currentPos) * Math.floor(Math.abs(position - currentPos) / camera.rangeDiff); | ||
if ((position > currentPos && anchorAtPosition.index < anchorAtCamera.index) | ||
|| (anchorAtPosition.position > anchorAtCamera.position && anchorAtPosition.index === anchorAtCamera.index)) { | ||
loopCount += 1; | ||
} else if ((position < currentPos && anchorAtPosition.index > anchorAtCamera.index) | ||
|| (anchorAtPosition.position < anchorAtCamera.position && anchorAtPosition.index === anchorAtCamera.index)) { | ||
loopCount -= 1; | ||
} | ||
const circularIndexOffset = loopCount * panelCount; | ||
const anchorAtPositionIndex = anchorAtPosition.index + circularIndexOffset; | ||
if (Math.abs(anchorAtPositionIndex - anchorAtCamera.index) <= count) { | ||
const anchor = anchors[anchorAtPosition.index]; | ||
return new AnchorPoint({ | ||
index: anchor.index, | ||
position: anchor.position + loopCount * camera.rangeDiff, | ||
panel: anchor.panel | ||
}); | ||
} | ||
if (flicking.circularEnabled) { | ||
const targetAnchor = anchors[circulateIndex(anchorAtCamera.index + Math.sign(position - currentPos) * count, panelCount)]; | ||
let loop = Math.floor(count / panelCount); | ||
if (position > currentPos && targetAnchor.index < anchorAtCamera.index) { | ||
loop += 1; | ||
} else if (position < currentPos && targetAnchor.index > anchorAtCamera.index) { | ||
loop -= 1; | ||
} | ||
return new AnchorPoint({ | ||
index: targetAnchor.index, | ||
position: targetAnchor.position + loop * camera.rangeDiff, | ||
panel: targetAnchor.panel | ||
}); | ||
} else { | ||
return anchors[clamp(anchorAtCamera.index + Math.sign(position - currentPos) * count, 0, anchors.length - 1)]; | ||
} | ||
} | ||
private _findAdjacentAnchor(posDelta: number, anchorAtCamera: AnchorPoint): AnchorPoint { | ||
const flicking = getFlickingAttached(this._flicking, "Control"); | ||
const camera = flicking.camera; | ||
const adjacentAnchor = (posDelta > 0 ? camera.getNextAnchor(anchorAtCamera) : camera.getPrevAnchor(anchorAtCamera)) ?? anchorAtCamera; | ||
return adjacentAnchor; | ||
} | ||
private _calcSnapThreshold(position: number, activeAnchor: AnchorPoint): number { | ||
const isNextDirection = position > activeAnchor.position; | ||
const panel = activeAnchor.panel; | ||
const panelSize = panel.size; | ||
const alignPos = panel.alignPosition; | ||
// Minimum distance needed to decide prev/next panel as nearest | ||
/* | ||
* | Prev | Next | | ||
* |<------>|<------------>| | ||
* [ |<-Anchor ] | ||
*/ | ||
return isNextDirection | ||
? panelSize - alignPos + panel.margin.next | ||
: alignPos + panel.margin.prev; | ||
} | ||
} | ||
export default SnapControl; |
@@ -76,2 +76,4 @@ /* | ||
nextState.onEnter(this._state); | ||
this._state = nextState; | ||
@@ -78,0 +80,0 @@ |
@@ -36,3 +36,5 @@ /* | ||
this._delta = 0; | ||
flicking.control.updateInput(); | ||
const holdStartEvent = new ComponentEvent(EVENTS.HOLD_START, { axesEvent }); | ||
@@ -39,0 +41,0 @@ flicking.trigger(holdStartEvent); |
@@ -33,2 +33,6 @@ /* | ||
public onEnter() { | ||
this._delta = 0; | ||
} | ||
public onHold(ctx: Parameters<State["onHold"]>[0]): void { | ||
@@ -35,0 +39,0 @@ // Shouldn't do any action until any panels on flicking area |
@@ -43,3 +43,23 @@ /* | ||
protected _delta: number = 0; | ||
/** | ||
* A sum of delta values of change events from the last hold event of Axes | ||
* @ko 이전 hold이벤트부터 change에 의해 발생한 이동 delta값의 합산 | ||
* @type {number} | ||
* @readonly | ||
*/ | ||
public get delta() { return this._delta; } | ||
/** | ||
* An callback which is called when state has changed to this state | ||
* @ko 현재 상태로 돌입했을때 호출되는 콜백 함수 | ||
* @param {State} prevState An previous state<ko>이전 상태값</ko> | ||
* @return {void} | ||
*/ | ||
public onEnter(prevState: State): void { | ||
this._delta = prevState._delta; | ||
} | ||
/** | ||
* An event handler for Axes's {@link https://naver.github.io/egjs-axes/release/latest/doc/eg.Axes.html#event:hold hold} event | ||
@@ -135,7 +155,10 @@ * @ko Axes의 {@link https://naver.github.io/egjs-axes/release/latest/doc/eg.Axes.html#event:hold hold} 이벤트 핸들러 | ||
const { flicking, axesEvent, transitTo } = ctx; | ||
const delta = axesEvent.delta[AXES.POSITION_KEY]; | ||
if (!axesEvent.delta[AXES.POSITION_KEY]) { | ||
if (!delta) { | ||
return; | ||
} | ||
this._delta += delta; | ||
const camera = flicking.camera; | ||
@@ -142,0 +165,0 @@ const prevPosition = camera.position; |
@@ -10,3 +10,3 @@ /* | ||
import { Panel } from "./core/panel"; | ||
import { Control, SnapControl, FreeControl, StrictControl, FreeControlOptions, StrictControlOptions } from "./control"; | ||
import { Control, SnapControl, SnapControlOptions, FreeControl, StrictControl, FreeControlOptions, StrictControlOptions } from "./control"; | ||
import { BoundCamera, Camera, CircularCamera, LinearCamera } from "./camera"; | ||
@@ -691,3 +691,3 @@ import { Renderer, VanillaRenderer, ExternalRenderer, RawRenderingStrategy, VisibleRenderingStrategy } from "./renderer"; | ||
// Look at initial panel | ||
this._moveToInitialPanel(); | ||
await this._moveToInitialPanel(); | ||
@@ -1218,3 +1218,3 @@ if (this._autoResize) { | ||
case MOVE_TYPE.SNAP: | ||
return new SnapControl(); | ||
return new SnapControl(moveTypeOptions as SnapControlOptions); | ||
case MOVE_TYPE.FREE_SCROLL: | ||
@@ -1260,3 +1260,3 @@ return new FreeControl(moveTypeOptions as FreeControlOptions); | ||
private _moveToInitialPanel(): void { | ||
private async _moveToInitialPanel(): Promise<void> { | ||
const renderer = this._renderer; | ||
@@ -1268,3 +1268,3 @@ const control = this._control; | ||
void control.moveToPanel(initialPanel, { | ||
return control.moveToPanel(initialPanel, { | ||
duration: 0 | ||
@@ -1271,0 +1271,0 @@ }); |
import Flicking from "../Flicking"; | ||
import { FreeControlOptions, StrictControlOptions } from "../control"; | ||
import { SnapControlOptions, FreeControlOptions, StrictControlOptions } from "../control"; | ||
import { MOVE_TYPE } from "../const/external"; | ||
@@ -56,2 +56,3 @@ import { ValueOf } from "../type/internal"; | ||
export type MoveTypeOptions<T extends ValueOf<typeof MOVE_TYPE>> = | ||
T extends typeof MOVE_TYPE.SNAP ? [T] | [T, Partial<SnapControlOptions>] : | ||
T extends typeof MOVE_TYPE.FREE_SCROLL ? [T] | [T, Partial<FreeControlOptions>] : | ||
@@ -58,0 +59,0 @@ T extends typeof MOVE_TYPE.STRICT ? [T] | [T, Partial<StrictControlOptions>] : |
@@ -258,1 +258,11 @@ /* | ||
export const isBetween = (val: number, min: number, max: number) => val >= min && val <= max; | ||
export const circulateIndex = (index: number, max: number): number => { | ||
if (index >= max) { | ||
return index % max; | ||
} else if (index < 0) { | ||
return getMinusCompensatedIndex((index + 1) % max - 1, max); | ||
} else { | ||
return index; | ||
} | ||
}; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
3192297
32363