@egjs/flicking 4.4.2 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/declaration/Flicking.d.ts +8 -2
  2. package/declaration/camera/Camera.d.ts +26 -24
  3. package/declaration/camera/index.d.ts +2 -4
  4. package/declaration/camera/mode/BoundCameraMode.d.ts +13 -0
  5. package/declaration/camera/mode/CameraMode.d.ts +19 -0
  6. package/declaration/camera/mode/CircularCameraMode.d.ts +18 -0
  7. package/declaration/camera/mode/LinearCameraMode.d.ts +9 -0
  8. package/declaration/camera/mode/index.d.ts +6 -0
  9. package/declaration/const/external.d.ts +4 -0
  10. package/declaration/type/external.d.ts +1 -3
  11. package/dist/flicking.esm.js +1181 -1090
  12. package/dist/flicking.esm.js.map +1 -1
  13. package/dist/flicking.js +1184 -1092
  14. package/dist/flicking.js.map +1 -1
  15. package/dist/flicking.min.js +2 -2
  16. package/dist/flicking.min.js.map +1 -1
  17. package/dist/flicking.pkgd.js +1183 -1091
  18. package/dist/flicking.pkgd.js.map +1 -1
  19. package/dist/flicking.pkgd.min.js +2 -2
  20. package/dist/flicking.pkgd.min.js.map +1 -1
  21. package/package.json +4 -3
  22. package/src/Flicking.ts +26 -15
  23. package/src/camera/Camera.ts +155 -70
  24. package/src/camera/index.ts +3 -7
  25. package/src/camera/{BoundCamera.ts → mode/BoundCameraMode.ts} +46 -43
  26. package/src/camera/mode/CameraMode.ts +77 -0
  27. package/src/camera/mode/CircularCameraMode.ts +171 -0
  28. package/src/camera/mode/LinearCameraMode.ts +23 -0
  29. package/src/camera/mode/index.ts +14 -0
  30. package/src/const/external.ts +12 -0
  31. package/declaration/camera/BoundCamera.d.ts +0 -9
  32. package/declaration/camera/CircularCamera.d.ts +0 -37
  33. package/declaration/camera/LinearCamera.d.ts +0 -5
  34. package/src/camera/CircularCamera.ts +0 -268
  35. package/src/camera/LinearCamera.ts +0 -35
package/dist/flicking.js CHANGED
@@ -4,7 +4,7 @@ name: @egjs/flicking
4
4
  license: MIT
5
5
  author: NAVER Corp.
6
6
  repository: https://github.com/naver/egjs-flicking
7
- version: 4.4.2
7
+ version: 4.5.0
8
8
  */
9
9
  (function (global, factory) {
10
10
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@egjs/component'), require('@egjs/axes'), require('@egjs/imready')) :
@@ -242,10 +242,12 @@ version: 4.4.2
242
242
 
243
243
  return ar;
244
244
  }
245
- function __spreadArray(to, from) {
246
- for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i];
245
+ /** @deprecated */
247
246
 
248
- return to;
247
+ function __spread() {
248
+ for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
249
+
250
+ return ar;
249
251
  }
250
252
 
251
253
  /*
@@ -425,6 +427,18 @@ version: 4.4.2
425
427
  HIDDEN: "flicking-hidden",
426
428
  DEFAULT_VIRTUAL: "flicking-panel"
427
429
  };
430
+ /**
431
+ * An object with all possible {@link Flicking#circularFallback circularFallback}s
432
+ * @ko Flicking의 {@link Flicking#circularFallback circularFallback}에 설정 가능한 값들을 담고 있는 객체
433
+ * @type {object}
434
+ * @property {string} LINEAR "linear"
435
+ * @property {string} BOUND "bound"
436
+ */
437
+
438
+ var CIRCULAR_FALLBACK = {
439
+ LINEAR: "linear",
440
+ BOUND: "bound"
441
+ };
428
442
 
429
443
  var Constants = {
430
444
  __proto__: null,
@@ -433,6 +447,7 @@ version: 4.4.2
433
447
  DIRECTION: DIRECTION,
434
448
  MOVE_TYPE: MOVE_TYPE,
435
449
  CLASS: CLASS,
450
+ CIRCULAR_FALLBACK: CIRCULAR_FALLBACK,
436
451
  ERROR_CODE: CODE
437
452
  };
438
453
 
@@ -618,7 +633,7 @@ version: 4.4.2
618
633
  if (isString(el)) {
619
634
  var tempDiv = document.createElement("div");
620
635
  tempDiv.innerHTML = el;
621
- elements.push.apply(elements, __spreadArray([], __read(toArray(tempDiv.children))));
636
+ elements.push.apply(elements, __spread(toArray(tempDiv.children)));
622
637
 
623
638
  while (tempDiv.firstChild) {
624
639
  tempDiv.removeChild(tempDiv.firstChild);
@@ -3031,9 +3046,8 @@ version: 4.4.2
3031
3046
 
3032
3047
 
3033
3048
  function SnapControl(_a) {
3034
- var _b = _a === void 0 ? {} : _a,
3035
- _c = _b.count,
3036
- count = _c === void 0 ? Infinity : _c;
3049
+ var _b = (_a === void 0 ? {} : _a).count,
3050
+ count = _b === void 0 ? Infinity : _b;
3037
3051
 
3038
3052
  var _this = _super.call(this) || this;
3039
3053
 
@@ -3239,9 +3253,8 @@ version: 4.4.2
3239
3253
 
3240
3254
 
3241
3255
  function FreeControl(_a) {
3242
- var _b = _a === void 0 ? {} : _a,
3243
- _c = _b.stopAtEdge,
3244
- stopAtEdge = _c === void 0 ? true : _c;
3256
+ var _b = (_a === void 0 ? {} : _a).stopAtEdge,
3257
+ stopAtEdge = _b === void 0 ? true : _b;
3245
3258
 
3246
3259
  var _this = _super.call(this) || this;
3247
3260
 
@@ -3375,9 +3388,8 @@ version: 4.4.2
3375
3388
 
3376
3389
 
3377
3390
  function StrictControl(_a) {
3378
- var _b = _a === void 0 ? {} : _a,
3379
- _c = _b.count,
3380
- count = _c === void 0 ? 1 : _c;
3391
+ var _b = (_a === void 0 ? {} : _a).count,
3392
+ count = _b === void 0 ? 1 : _b;
3381
3393
 
3382
3394
  var _this = _super.call(this) || this;
3383
3395
 
@@ -3630,761 +3642,826 @@ version: 4.4.2
3630
3642
  };
3631
3643
 
3632
3644
  /**
3633
- * A component that manages actual movement inside the viewport
3634
- * @ko 뷰포트 내에서의 실제 움직임을 담당하는 컴포넌트
3645
+ * A mode of camera
3635
3646
  */
3636
3647
 
3637
- var Camera$1 =
3648
+ var CameraMode =
3638
3649
  /*#__PURE__*/
3639
3650
  function () {
3640
3651
  /** */
3641
- function Camera(_a) {
3642
- var _this = this;
3652
+ function CameraMode(flicking) {
3653
+ this._flicking = flicking;
3654
+ }
3643
3655
 
3644
- var _b = _a === void 0 ? {} : _a,
3645
- _c = _b.align,
3646
- align = _c === void 0 ? ALIGN.CENTER : _c;
3656
+ var __proto = CameraMode.prototype;
3647
3657
 
3648
- this._checkTranslateSupport = function () {
3649
- var e_1, _a;
3658
+ __proto.getAnchors = function () {
3659
+ var panels = this._flicking.renderer.panels;
3660
+ return panels.map(function (panel, index) {
3661
+ return new AnchorPoint({
3662
+ index: index,
3663
+ position: panel.position,
3664
+ panel: panel
3665
+ });
3666
+ });
3667
+ };
3650
3668
 
3651
- var transforms = ["webkitTransform", "msTransform", "MozTransform", "OTransform", "transform"];
3652
- var supportedStyle = document.documentElement.style;
3653
- var transformName = "";
3669
+ __proto.findAnchorIncludePosition = function (position) {
3670
+ var anchors = this._flicking.camera.anchorPoints;
3671
+ var anchorsIncludingPosition = anchors.filter(function (anchor) {
3672
+ return anchor.panel.includePosition(position, true);
3673
+ });
3674
+ return anchorsIncludingPosition.reduce(function (nearest, anchor) {
3675
+ if (!nearest) return anchor;
3676
+ return Math.abs(nearest.position - position) < Math.abs(anchor.position - position) ? nearest : anchor;
3677
+ }, null);
3678
+ };
3654
3679
 
3655
- try {
3656
- for (var transforms_1 = __values(transforms), transforms_1_1 = transforms_1.next(); !transforms_1_1.done; transforms_1_1 = transforms_1.next()) {
3657
- var prefixedTransform = transforms_1_1.value;
3680
+ __proto.clampToReachablePosition = function (position) {
3681
+ var camera = this._flicking.camera;
3682
+ var range = camera.range;
3683
+ return clamp(position, range.min, range.max);
3684
+ };
3658
3685
 
3659
- if (prefixedTransform in supportedStyle) {
3660
- transformName = prefixedTransform;
3661
- }
3662
- }
3663
- } catch (e_1_1) {
3664
- e_1 = {
3665
- error: e_1_1
3666
- };
3667
- } finally {
3668
- try {
3669
- if (transforms_1_1 && !transforms_1_1.done && (_a = transforms_1.return)) _a.call(transforms_1);
3670
- } finally {
3671
- if (e_1) throw e_1.error;
3672
- }
3673
- }
3686
+ __proto.getCircularOffset = function () {
3687
+ return 0;
3688
+ };
3674
3689
 
3675
- if (!transformName) {
3676
- throw new FlickingError(MESSAGE.TRANSFORM_NOT_SUPPORTED, CODE.TRANSFORM_NOT_SUPPORTED);
3677
- }
3690
+ __proto.canReach = function (panel) {
3691
+ var camera = this._flicking.camera;
3692
+ var range = camera.range;
3693
+ if (panel.removed) return false;
3694
+ var panelPos = panel.position;
3695
+ return panelPos >= range.min && panelPos <= range.max;
3696
+ };
3678
3697
 
3679
- _this._transform = transformName;
3698
+ __proto.canSee = function (panel) {
3699
+ var camera = this._flicking.camera;
3700
+ var visibleRange = camera.visibleRange; // Should not include margin, as we don't declare what the margin is visible as what the panel is visible.
3701
+
3702
+ return panel.isVisibleOnRange(visibleRange.min, visibleRange.max);
3703
+ };
3704
+
3705
+ return CameraMode;
3706
+ }();
3707
+
3708
+ var LinearCameraMode =
3709
+ /*#__PURE__*/
3710
+ function (_super) {
3711
+ __extends(LinearCameraMode, _super);
3712
+
3713
+ function LinearCameraMode() {
3714
+ return _super !== null && _super.apply(this, arguments) || this;
3715
+ }
3716
+
3717
+ var __proto = LinearCameraMode.prototype;
3718
+
3719
+ __proto.checkAvailability = function () {
3720
+ // It's always available
3721
+ return true;
3722
+ };
3723
+
3724
+ __proto.getRange = function () {
3725
+ var _a, _b;
3726
+
3727
+ var renderer = this._flicking.renderer;
3728
+ var firstPanel = renderer.getPanel(0);
3729
+ var lastPanel = renderer.getPanel(renderer.panelCount - 1);
3730
+ return {
3731
+ min: (_a = firstPanel === null || firstPanel === void 0 ? void 0 : firstPanel.position) !== null && _a !== void 0 ? _a : 0,
3732
+ max: (_b = lastPanel === null || lastPanel === void 0 ? void 0 : lastPanel.position) !== null && _b !== void 0 ? _b : 0
3680
3733
  };
3734
+ };
3681
3735
 
3682
- this._flicking = null;
3736
+ return LinearCameraMode;
3737
+ }(CameraMode);
3683
3738
 
3684
- this._resetInternalValues(); // Options
3739
+ /**
3740
+ * A {@link Camera} mode that connects the last panel and the first panel, enabling continuous loop
3741
+ * @ko 첫번째 패널과 마지막 패널이 이어진 상태로, 무한히 회전할 수 있는 종류의 {@link Camera} 모드
3742
+ */
3685
3743
 
3744
+ var CircularCameraMode =
3745
+ /*#__PURE__*/
3746
+ function (_super) {
3747
+ __extends(CircularCameraMode, _super);
3686
3748
 
3687
- this._align = align;
3749
+ function CircularCameraMode() {
3750
+ return _super !== null && _super.apply(this, arguments) || this;
3688
3751
  }
3689
3752
 
3690
- var __proto = Camera.prototype;
3691
- Object.defineProperty(__proto, "element", {
3692
- // Internal states getter
3753
+ var __proto = CircularCameraMode.prototype;
3693
3754
 
3694
- /**
3695
- * The camera element(`.flicking-camera`)
3696
- * @ko 카메라 엘리먼트(`.flicking-camera`)
3697
- * @type {HTMLElement}
3698
- * @readonly
3699
- */
3700
- get: function () {
3701
- return this._el;
3702
- },
3703
- enumerable: false,
3704
- configurable: true
3705
- });
3706
- Object.defineProperty(__proto, "children", {
3707
- /**
3708
- * An array of the child elements of the camera element(`.flicking-camera`)
3709
- * @ko 카메라 엘리먼트(`.flicking-camera`) 자식 엘리먼트 배열
3710
- * @type {HTMLElement[]}
3711
- * @readonly
3712
- */
3713
- get: function () {
3714
- return toArray(this._el.children);
3715
- },
3716
- enumerable: false,
3717
- configurable: true
3718
- });
3719
- Object.defineProperty(__proto, "position", {
3720
- /**
3721
- * Current position of the camera
3722
- * @ko Camera의 현재 좌표
3723
- * @type {number}
3724
- * @readonly
3725
- */
3726
- get: function () {
3727
- return this._position;
3728
- },
3729
- enumerable: false,
3730
- configurable: true
3731
- });
3732
- Object.defineProperty(__proto, "alignPosition", {
3733
- /**
3734
- * Align position inside the viewport where {@link Panel}'s {@link Panel#alignPosition alignPosition} should be located at
3735
- * @ko 패널의 정렬 기준 위치. 뷰포트 내에서 {@link Panel}의 {@link Panel#alignPosition alignPosition}이 위치해야 하는 곳입니다
3736
- * @type {number}
3737
- * @readonly
3738
- */
3739
- get: function () {
3740
- return this._alignPos;
3741
- },
3742
- enumerable: false,
3743
- configurable: true
3744
- });
3745
- Object.defineProperty(__proto, "offset", {
3746
- /**
3747
- * Position offset, used for the {@link Flicking#renderOnlyVisible renderOnlyVisible} option
3748
- * @ko Camera의 좌표 오프셋. {@link Flicking#renderOnlyVisible renderOnlyVisible} 옵션을 위해 사용됩니다.
3749
- * @type {number}
3750
- * @default 0
3751
- * @readonly
3752
- */
3753
- get: function () {
3754
- return this._offset;
3755
- },
3756
- enumerable: false,
3757
- configurable: true
3758
- });
3759
- Object.defineProperty(__proto, "range", {
3760
- /**
3761
- * A range that Camera's {@link Camera#position position} can reach
3762
- * @ko Camera의 {@link Camera#position position}이 도달 가능한 범위
3763
- * @type {object}
3764
- * @property {number} min A minimum position<ko>최소 위치</ko>
3765
- * @property {number} max A maximum position<ko>최대 위치</ko>
3766
- * @readonly
3767
- */
3768
- get: function () {
3769
- return this._range;
3770
- },
3771
- enumerable: false,
3772
- configurable: true
3773
- });
3774
- Object.defineProperty(__proto, "rangeDiff", {
3775
- /**
3776
- * A difference between Camera's minimum and maximum position that can reach
3777
- * @ko Camera가 도달 가능한 최소/최대 좌표의 차이
3778
- * @type {number}
3779
- * @readonly
3780
- */
3781
- get: function () {
3782
- return this._range.max - this._range.min;
3783
- },
3784
- enumerable: false,
3785
- configurable: true
3786
- });
3787
- Object.defineProperty(__proto, "visiblePanels", {
3788
- /**
3789
- * An array of visible panels from the current position
3790
- * @ko 현재 보이는 패널들의 배열
3791
- * @type {Panel[]}
3792
- * @readonly
3793
- */
3794
- get: function () {
3795
- return this._visiblePanels;
3796
- },
3797
- enumerable: false,
3798
- configurable: true
3799
- });
3800
- Object.defineProperty(__proto, "visibleRange", {
3801
- /**
3802
- * A range of the visible area from the current position
3803
- * @ko 현재 위치에서 보이는 범위
3804
- * @type {object}
3805
- * @property {number} min A minimum position<ko>최소 위치</ko>
3806
- * @property {number} min A maximum position<ko>최대 위치</ko>
3807
- * @readonly
3808
- */
3809
- get: function () {
3755
+ __proto.checkAvailability = function () {
3756
+ var flicking = this._flicking;
3757
+ var renderer = flicking.renderer;
3758
+ var panels = renderer.panels;
3759
+
3760
+ if (panels.length <= 0) {
3761
+ return false;
3762
+ }
3763
+
3764
+ var firstPanel = panels[0];
3765
+ var lastPanel = panels[panels.length - 1];
3766
+ var firstPanelPrev = firstPanel.range.min - firstPanel.margin.prev;
3767
+ var lastPanelNext = lastPanel.range.max + lastPanel.margin.next;
3768
+ var visibleSize = flicking.camera.size;
3769
+ var panelSizeSum = lastPanelNext - firstPanelPrev;
3770
+ var canSetCircularMode = panels.every(function (panel) {
3771
+ return panelSizeSum - panel.size >= visibleSize;
3772
+ });
3773
+ return canSetCircularMode;
3774
+ };
3775
+
3776
+ __proto.getRange = function () {
3777
+ var flicking = this._flicking;
3778
+ var panels = flicking.renderer.panels;
3779
+
3780
+ if (panels.length <= 0) {
3810
3781
  return {
3811
- min: this._position - this._alignPos,
3812
- max: this._position - this._alignPos + this.size
3782
+ min: 0,
3783
+ max: 0
3813
3784
  };
3814
- },
3815
- enumerable: false,
3816
- configurable: true
3817
- });
3818
- Object.defineProperty(__proto, "anchorPoints", {
3819
- /**
3820
- * An array of {@link AnchorPoint}s that Camera can be stopped at
3821
- * @ko 카메라가 도달 가능한 {@link AnchorPoint}의 목록
3822
- * @type {AnchorPoint[]}
3823
- * @readonly
3824
- */
3825
- get: function () {
3826
- return this._anchors;
3827
- },
3828
- enumerable: false,
3829
- configurable: true
3830
- });
3831
- Object.defineProperty(__proto, "controlParams", {
3832
- /**
3833
- * A current parameters of the Camera for updating {@link AxesController}
3834
- * @ko {@link AxesController}를 업데이트하기 위한 현재 Camera 패러미터들
3835
- * @type {ControlParams}
3836
- * @readonly
3837
- */
3838
- get: function () {
3839
- return {
3840
- range: this._range,
3841
- position: this._position,
3842
- circular: false
3843
- };
3844
- },
3845
- enumerable: false,
3846
- configurable: true
3847
- });
3848
- Object.defineProperty(__proto, "atEdge", {
3849
- /**
3850
- * A Boolean value indicating whether Camera's over the minimum or maximum position reachable
3851
- * @ko 현재 카메라가 도달 가능한 범위의 최소 혹은 최대점을 넘어섰는지를 나타냅니다
3852
- * @type {boolean}
3853
- * @readonly
3854
- */
3855
- get: function () {
3856
- return this._position <= this._range.min || this._position >= this._range.max;
3857
- },
3858
- enumerable: false,
3859
- configurable: true
3860
- });
3861
- Object.defineProperty(__proto, "size", {
3862
- /**
3863
- * Return the size of the viewport
3864
- * @ko 뷰포트 크기를 반환합니다
3865
- * @type {number}
3866
- * @readonly
3867
- */
3868
- get: function () {
3869
- var flicking = this._flicking;
3870
- return flicking ? flicking.horizontal ? flicking.viewport.width : flicking.viewport.height : 0;
3871
- },
3872
- enumerable: false,
3873
- configurable: true
3874
- });
3875
- Object.defineProperty(__proto, "progress", {
3876
- /**
3877
- * Return the camera's position progress from the first panel to last panel
3878
- * Range is from 0 to last panel's index
3879
- * @ko 첫번째 패널로부터 마지막 패널까지의 카메라 위치의 진행도를 반환합니다
3880
- * 범위는 0부터 마지막 패널의 인덱스까지입니다
3881
- * @type {number}
3882
- * @readonly
3883
- */
3884
- get: function () {
3885
- var flicking = this._flicking;
3886
- var position = this._position + this._offset;
3887
- var nearestAnchor = this.findNearestAnchor(this._position);
3785
+ }
3888
3786
 
3889
- if (!flicking || !nearestAnchor) {
3890
- return NaN;
3891
- }
3787
+ var firstPanel = panels[0];
3788
+ var lastPanel = panels[panels.length - 1];
3789
+ var firstPanelPrev = firstPanel.range.min - firstPanel.margin.prev;
3790
+ var lastPanelNext = lastPanel.range.max + lastPanel.margin.next;
3791
+ return {
3792
+ min: firstPanelPrev,
3793
+ max: lastPanelNext
3794
+ };
3795
+ };
3892
3796
 
3893
- var nearestPanel = nearestAnchor.panel;
3894
- var panelPos = nearestPanel.position + nearestPanel.offset;
3895
- var bounceSize = flicking.control.controller.bounce;
3896
- var _a = this.range,
3897
- prevRange = _a.min,
3898
- nextRange = _a.max;
3899
- var rangeDiff = this.rangeDiff;
3797
+ __proto.getAnchors = function () {
3798
+ var flicking = this._flicking;
3799
+ var panels = flicking.renderer.panels;
3800
+ return panels.map(function (panel, index) {
3801
+ return new AnchorPoint({
3802
+ index: index,
3803
+ position: panel.position,
3804
+ panel: panel
3805
+ });
3806
+ });
3807
+ };
3900
3808
 
3901
- if (position === panelPos) {
3902
- return nearestPanel.index;
3903
- }
3809
+ __proto.findAnchorIncludePosition = function (position) {
3810
+ var camera = this._flicking.camera;
3811
+ var range = camera.range;
3812
+ var anchors = camera.anchorPoints;
3813
+ var rangeDiff = camera.rangeDiff;
3814
+ var anchorCount = anchors.length;
3815
+ var positionInRange = circulatePosition(position, range.min, range.max);
3904
3816
 
3905
- if (position < panelPos) {
3906
- var prevPanel = nearestPanel.prev();
3907
- var prevPosition = prevPanel ? prevPanel.position + prevPanel.offset : prevRange - bounceSize[0]; // Looped
3817
+ var anchorInRange = _super.prototype.findAnchorIncludePosition.call(this, positionInRange);
3908
3818
 
3909
- if (prevPosition > panelPos) {
3910
- prevPosition -= rangeDiff;
3911
- }
3819
+ if (anchorCount > 0 && (position === range.min || position === range.max)) {
3820
+ var possibleAnchors = [anchorInRange, new AnchorPoint({
3821
+ index: 0,
3822
+ position: anchors[0].position + rangeDiff,
3823
+ panel: anchors[0].panel
3824
+ }), new AnchorPoint({
3825
+ index: anchorCount - 1,
3826
+ position: anchors[anchorCount - 1].position - rangeDiff,
3827
+ panel: anchors[anchorCount - 1].panel
3828
+ })].filter(function (anchor) {
3829
+ return !!anchor;
3830
+ });
3831
+ anchorInRange = possibleAnchors.reduce(function (nearest, anchor) {
3832
+ if (!nearest) return anchor;
3833
+ return Math.abs(nearest.position - position) < Math.abs(anchor.position - position) ? nearest : anchor;
3834
+ }, null);
3835
+ }
3912
3836
 
3913
- return nearestPanel.index - 1 + getProgress(position, prevPosition, panelPos);
3914
- } else {
3915
- var nextPanel = nearestPanel.next();
3916
- var nextPosition = nextPanel ? nextPanel.position + nextPanel.offset : nextRange + bounceSize[1]; // Looped
3837
+ if (!anchorInRange) return null;
3917
3838
 
3918
- if (nextPosition < panelPos) {
3919
- nextPosition += rangeDiff;
3920
- }
3839
+ if (position < range.min) {
3840
+ var loopCount = -Math.floor((range.min - position) / rangeDiff) - 1;
3841
+ return new AnchorPoint({
3842
+ index: anchorInRange.index,
3843
+ position: anchorInRange.position + rangeDiff * loopCount,
3844
+ panel: anchorInRange.panel
3845
+ });
3846
+ } else if (position > range.max) {
3847
+ var loopCount = Math.floor((position - range.max) / rangeDiff) + 1;
3848
+ return new AnchorPoint({
3849
+ index: anchorInRange.index,
3850
+ position: anchorInRange.position + rangeDiff * loopCount,
3851
+ panel: anchorInRange.panel
3852
+ });
3853
+ }
3921
3854
 
3922
- return nearestPanel.index + getProgress(position, panelPos, nextPosition);
3923
- }
3924
- },
3925
- enumerable: false,
3926
- configurable: true
3927
- });
3928
- Object.defineProperty(__proto, "align", {
3929
- // Options Getter
3855
+ return anchorInRange;
3856
+ };
3930
3857
 
3931
- /**
3932
- * A value indicating where the {@link Camera#alignPosition alignPosition} should be located at inside the viewport element
3933
- * @ko {@link Camera#alignPosition alignPosition}이 뷰포트 엘리먼트 내의 어디에 위치해야 하는지를 나타내는 값
3934
- * @type {ALIGN | string | number}
3935
- */
3936
- get: function () {
3937
- return this._align;
3938
- },
3939
- // Options Setter
3940
- set: function (val) {
3941
- this._align = val;
3942
- },
3943
- enumerable: false,
3944
- configurable: true
3945
- });
3946
- /**
3947
- * Initialize Camera
3948
- * @ko Camera를 초기화합니다
3949
- * @param {Flicking} flicking An instance of {@link Flicking}<ko>Flicking의 인스턴스</ko>
3950
- * @chainable
3951
- * @throws {FlickingError}
3952
- * {@link ERROR_CODE VAL_MUST_NOT_NULL} If the camera element(`.flicking-camera`) does not exist inside viewport element
3953
- * <ko>{@link ERROR_CODE VAL_MUST_NOT_NULL} 뷰포트 엘리먼트 내부에 카메라 엘리먼트(`.flicking-camera`)가 존재하지 않을 경우</ko>
3954
- * @return {this}
3955
- */
3858
+ __proto.getCircularOffset = function () {
3859
+ var flicking = this._flicking;
3860
+ var camera = flicking.camera;
3861
+ if (!camera.circularEnabled) return 0;
3862
+ var toggled = flicking.panels.filter(function (panel) {
3863
+ return panel.toggled;
3864
+ });
3865
+ var toggledPrev = toggled.filter(function (panel) {
3866
+ return panel.toggleDirection === DIRECTION.PREV;
3867
+ });
3868
+ var toggledNext = toggled.filter(function (panel) {
3869
+ return panel.toggleDirection === DIRECTION.NEXT;
3870
+ });
3871
+ return this._calcPanelAreaSum(toggledPrev) - this._calcPanelAreaSum(toggledNext);
3872
+ };
3956
3873
 
3957
- __proto.init = function (flicking) {
3958
- this._flicking = flicking;
3959
- var viewportEl = flicking.viewport.element;
3960
- checkExistence(viewportEl.firstElementChild, "First element child of the viewport element");
3961
- this._el = viewportEl.firstElementChild;
3874
+ __proto.clampToReachablePosition = function (position) {
3875
+ // Basically all position is reachable for circular camera
3876
+ return position;
3877
+ };
3962
3878
 
3963
- this._checkTranslateSupport();
3879
+ __proto.canReach = function (panel) {
3880
+ if (panel.removed) return false; // Always reachable on circular mode
3964
3881
 
3965
- return this;
3882
+ return true;
3966
3883
  };
3967
- /**
3968
- * Destroy Camera and return to initial state
3969
- * @ko Camera를 초기 상태로 되돌립니다
3970
- * @return {void}
3971
- */
3972
-
3973
3884
 
3974
- __proto.destroy = function () {
3975
- this._flicking = null;
3885
+ __proto.canSee = function (panel) {
3886
+ var camera = this._flicking.camera;
3887
+ var range = camera.range;
3888
+ var rangeDiff = camera.rangeDiff;
3889
+ var visibleRange = camera.visibleRange;
3976
3890
 
3977
- this._resetInternalValues();
3891
+ var visibleInCurrentRange = _super.prototype.canSee.call(this, panel); // Check looped visible area for circular case
3978
3892
 
3979
- return this;
3980
- };
3981
- /**
3982
- * Move to the given position and apply CSS transform
3983
- * @ko 해당 좌표로 이동하고, CSS transform을 적용합니다
3984
- * @param {number} pos A new position<ko>움직일 위치</ko>
3985
- * @throws {FlickingError}
3986
- * {@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} When {@link Camera#init init} is not called before
3987
- * <ko>{@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} {@link Camera#init init}이 이전에 호출되지 않은 경우</ko>
3988
- * @return {this}
3989
- */
3990
3893
 
3894
+ if (visibleRange.min < range.min) {
3895
+ return visibleInCurrentRange || panel.isVisibleOnRange(visibleRange.min + rangeDiff, visibleRange.max + rangeDiff);
3896
+ } else if (visibleRange.max > range.max) {
3897
+ return visibleInCurrentRange || panel.isVisibleOnRange(visibleRange.min - rangeDiff, visibleRange.max - rangeDiff);
3898
+ }
3991
3899
 
3992
- __proto.lookAt = function (pos) {
3993
- var prevPos = this._position;
3994
- this._position = pos;
3900
+ return visibleInCurrentRange;
3901
+ };
3995
3902
 
3996
- this._refreshVisiblePanels();
3903
+ __proto._calcPanelAreaSum = function (panels) {
3904
+ return panels.reduce(function (sum, panel) {
3905
+ return sum + panel.sizeIncludingMargin;
3906
+ }, 0);
3907
+ };
3997
3908
 
3998
- this._checkNeedPanel();
3909
+ return CircularCameraMode;
3910
+ }(CameraMode);
3999
3911
 
4000
- this._checkReachEnd(prevPos, pos);
3912
+ var BoundCameraMode =
3913
+ /*#__PURE__*/
3914
+ function (_super) {
3915
+ __extends(BoundCameraMode, _super);
4001
3916
 
4002
- this.applyTransform();
4003
- };
4004
- /**
4005
- * Return a previous {@link AnchorPoint} of given {@link AnchorPoint}
4006
- * If it does not exist, return `null` instead
4007
- * @ko 주어진 {@link AnchorPoint}의 이전 {@link AnchorPoint}를 반환합니다
4008
- * 존재하지 않을 경우 `null`을 반환합니다
4009
- * @param {AnchorPoint} anchor A reference {@link AnchorPoint}<ko>기준 {@link AnchorPoint}</ko>
4010
- * @return {AnchorPoint | null} The previous {@link AnchorPoint}<ko>이전 {@link AnchorPoint}</ko>
4011
- */
3917
+ function BoundCameraMode() {
3918
+ return _super !== null && _super.apply(this, arguments) || this;
3919
+ }
4012
3920
 
3921
+ var __proto = BoundCameraMode.prototype;
4013
3922
 
4014
- __proto.getPrevAnchor = function (anchor) {
4015
- return this._anchors[anchor.index - 1] || null;
4016
- };
4017
- /**
4018
- * Return a next {@link AnchorPoint} of given {@link AnchorPoint}
4019
- * If it does not exist, return `null` instead
4020
- * @ko 주어진 {@link AnchorPoint}의 다음 {@link AnchorPoint}를 반환합니다
4021
- * 존재하지 않을 경우 `null`을 반환합니다
4022
- * @param {AnchorPoint} anchor A reference {@link AnchorPoint}<ko>기준 {@link AnchorPoint}</ko>
4023
- * @return {AnchorPoint | null} The next {@link AnchorPoint}<ko>다음 {@link AnchorPoint}</ko>
4024
- */
3923
+ __proto.checkAvailability = function () {
3924
+ var flicking = this._flicking;
3925
+ var renderer = flicking.renderer;
3926
+ var firstPanel = renderer.getPanel(0);
3927
+ var lastPanel = renderer.getPanel(renderer.panelCount - 1);
4025
3928
 
3929
+ if (!firstPanel || !lastPanel) {
3930
+ return false;
3931
+ }
4026
3932
 
4027
- __proto.getNextAnchor = function (anchor) {
4028
- return this._anchors[anchor.index + 1] || null;
3933
+ var viewportSize = flicking.camera.size;
3934
+ var firstPanelPrev = firstPanel.range.min;
3935
+ var lastPanelNext = lastPanel.range.max;
3936
+ var panelAreaSize = lastPanelNext - firstPanelPrev;
3937
+ var isBiggerThanViewport = viewportSize < panelAreaSize;
3938
+ return isBiggerThanViewport;
4029
3939
  };
4030
- /**
4031
- * Return the camera's position progress in the panel below
4032
- * Value is from 0 to 1 when the camera's inside panel
4033
- * Value can be lower than 0 or bigger than 1 when it's in the margin area
4034
- * @ko 현재 카메라 아래 패널에서의 위치 진행도를 반환합니다
4035
- * 반환값은 카메라가 패널 내부에 있을 경우 0부터 1까지의 값을 갖습니다
4036
- * 패널의 margin 영역에 있을 경우 0보다 작거나 1보다 큰 값을 반환할 수 있습니다
4037
- */
4038
3940
 
3941
+ __proto.getRange = function () {
3942
+ var flicking = this._flicking;
3943
+ var renderer = flicking.renderer;
3944
+ var alignPos = flicking.camera.alignPosition;
3945
+ var firstPanel = renderer.getPanel(0);
3946
+ var lastPanel = renderer.getPanel(renderer.panelCount - 1);
3947
+
3948
+ if (!firstPanel || !lastPanel) {
3949
+ return {
3950
+ min: 0,
3951
+ max: 0
3952
+ };
3953
+ }
4039
3954
 
4040
- __proto.getProgressInPanel = function (panel) {
4041
- var panelRange = panel.range;
4042
- return (this._position - panelRange.min) / (panelRange.max - panelRange.min);
3955
+ var viewportSize = flicking.camera.size;
3956
+ var firstPanelPrev = firstPanel.range.min;
3957
+ var lastPanelNext = lastPanel.range.max;
3958
+ var panelAreaSize = lastPanelNext - firstPanelPrev;
3959
+ var isBiggerThanViewport = viewportSize < panelAreaSize;
3960
+ var firstPos = firstPanelPrev + alignPos;
3961
+ var lastPos = lastPanelNext - viewportSize + alignPos;
3962
+
3963
+ if (isBiggerThanViewport) {
3964
+ return {
3965
+ min: firstPos,
3966
+ max: lastPos
3967
+ };
3968
+ } else {
3969
+ var align = flicking.camera.align;
3970
+ var alignVal = typeof align === "object" ? align.camera : align;
3971
+ var pos = firstPos + parseAlign$1(alignVal, lastPos - firstPos);
3972
+ return {
3973
+ min: pos,
3974
+ max: pos
3975
+ };
3976
+ }
4043
3977
  };
4044
- /**
4045
- * Return {@link AnchorPoint} that includes given position
4046
- * If there's no {@link AnchorPoint} that includes the given position, return `null` instead
4047
- * @ko 주어진 좌표를 포함하는 {@link AnchorPoint}를 반환합니다
4048
- * 주어진 좌표를 포함하는 {@link AnchorPoint}가 없을 경우 `null`을 반환합니다
4049
- * @param {number} position A position to check<ko>확인할 좌표</ko>
4050
- * @return {AnchorPoint | null} The {@link AnchorPoint} that includes the given position<ko>해당 좌표를 포함하는 {@link AnchorPoint}</ko>
4051
- */
4052
3978
 
3979
+ __proto.getAnchors = function () {
3980
+ var flicking = this._flicking;
3981
+ var camera = flicking.camera;
3982
+ var panels = flicking.renderer.panels;
4053
3983
 
4054
- __proto.findAnchorIncludePosition = function (position) {
4055
- var anchors = this._anchors;
4056
- var anchorsIncludingPosition = anchors.filter(function (anchor) {
4057
- return anchor.panel.includePosition(position, true);
3984
+ if (panels.length <= 0) {
3985
+ return [];
3986
+ }
3987
+
3988
+ var range = flicking.camera.range;
3989
+ var reachablePanels = panels.filter(function (panel) {
3990
+ return camera.canReach(panel);
4058
3991
  });
4059
- return anchorsIncludingPosition.reduce(function (nearest, anchor) {
4060
- if (!nearest) return anchor;
4061
- return Math.abs(nearest.position - position) < Math.abs(anchor.position - position) ? nearest : anchor;
4062
- }, null);
4063
- };
4064
- /**
4065
- * Return {@link AnchorPoint} nearest to given position
4066
- * If there're no {@link AnchorPoint}s, return `null` instead
4067
- * @ko 해당 좌표에서 가장 가까운 {@link AnchorPoint}를 반환합니다
4068
- * {@link AnchorPoint}가 하나도 없을 경우 `null`을 반환합니다
4069
- * @param {number} position A position to check<ko>확인할 좌표</ko>
4070
- * @return {AnchorPoint | null} The {@link AnchorPoint} nearest to the given position<ko>해당 좌표에 가장 인접한 {@link AnchorPoint}</ko>
4071
- */
4072
3992
 
3993
+ if (reachablePanels.length > 0) {
3994
+ var shouldPrependBoundAnchor = reachablePanels[0].position !== range.min;
3995
+ var shouldAppendBoundAnchor = reachablePanels[reachablePanels.length - 1].position !== range.max;
3996
+ var indexOffset_1 = shouldPrependBoundAnchor ? 1 : 0;
3997
+ var newAnchors = reachablePanels.map(function (panel, idx) {
3998
+ return new AnchorPoint({
3999
+ index: idx + indexOffset_1,
4000
+ position: panel.position,
4001
+ panel: panel
4002
+ });
4003
+ });
4073
4004
 
4074
- __proto.findNearestAnchor = function (position) {
4075
- var anchors = this._anchors;
4005
+ if (shouldPrependBoundAnchor) {
4006
+ newAnchors.splice(0, 0, new AnchorPoint({
4007
+ index: 0,
4008
+ position: range.min,
4009
+ panel: panels[reachablePanels[0].index - 1]
4010
+ }));
4011
+ }
4012
+
4013
+ if (shouldAppendBoundAnchor) {
4014
+ newAnchors.push(new AnchorPoint({
4015
+ index: newAnchors.length,
4016
+ position: range.max,
4017
+ panel: panels[reachablePanels[reachablePanels.length - 1].index + 1]
4018
+ }));
4019
+ }
4020
+
4021
+ return newAnchors;
4022
+ } else if (range.min !== range.max) {
4023
+ // There're more than 2 panels
4024
+ var nearestPanelAtMin = this._findNearestPanel(range.min, panels);
4025
+
4026
+ var panelAtMin = nearestPanelAtMin.index === panels.length - 1 ? nearestPanelAtMin.prev() : nearestPanelAtMin;
4027
+ var panelAtMax = panelAtMin.next();
4028
+ return [new AnchorPoint({
4029
+ index: 0,
4030
+ position: range.min,
4031
+ panel: panelAtMin
4032
+ }), new AnchorPoint({
4033
+ index: 1,
4034
+ position: range.max,
4035
+ panel: panelAtMax
4036
+ })];
4037
+ } else {
4038
+ return [new AnchorPoint({
4039
+ index: 0,
4040
+ position: range.min,
4041
+ panel: this._findNearestPanel(range.min, panels)
4042
+ })];
4043
+ }
4044
+ };
4045
+
4046
+ __proto.findAnchorIncludePosition = function (position) {
4047
+ var camera = this._flicking.camera;
4048
+ var range = camera.range;
4049
+ var anchors = camera.anchorPoints;
4076
4050
  if (anchors.length <= 0) return null;
4051
+
4052
+ if (position <= range.min) {
4053
+ return anchors[0];
4054
+ } else if (position >= range.max) {
4055
+ return anchors[anchors.length - 1];
4056
+ } else {
4057
+ return _super.prototype.findAnchorIncludePosition.call(this, position);
4058
+ }
4059
+ };
4060
+
4061
+ __proto._findNearestPanel = function (pos, panels) {
4077
4062
  var prevDist = Infinity;
4078
4063
 
4079
- for (var anchorIdx = 0; anchorIdx < anchors.length; anchorIdx++) {
4080
- var anchor = anchors[anchorIdx];
4081
- var dist = Math.abs(anchor.position - position);
4064
+ for (var panelIdx = 0; panelIdx < panels.length; panelIdx++) {
4065
+ var panel = panels[panelIdx];
4066
+ var dist = Math.abs(panel.position - pos);
4082
4067
 
4083
4068
  if (dist > prevDist) {
4084
4069
  // Return previous anchor
4085
- return anchors[anchorIdx - 1];
4070
+ return panels[panelIdx - 1];
4086
4071
  }
4087
4072
 
4088
4073
  prevDist = dist;
4089
4074
  } // Return last anchor
4090
4075
 
4091
4076
 
4092
- return anchors[anchors.length - 1];
4077
+ return panels[panels.length - 1];
4093
4078
  };
4094
- /**
4095
- * Return {@link AnchorPoint} that matches {@link Flicking#currentPanel}
4096
- * @ko 현재 {@link Flicking#currentPanel}에 해당하는 {@link AnchorPoint}를 반환합니다
4097
- * @return {AnchorPoint | null}
4098
- */
4099
-
4100
4079
 
4101
- __proto.findActiveAnchor = function () {
4102
- var flicking = getFlickingAttached(this._flicking);
4103
- var activeIndex = flicking.control.activeIndex;
4104
- return find(this._anchors, function (anchor) {
4105
- return anchor.panel.index === activeIndex;
4106
- });
4107
- };
4108
- /**
4109
- * Clamp the given position between camera's range
4110
- * @ko 주어진 좌표를 Camera가 도달 가능한 범위 사이의 값으로 만듭니다
4111
- * @param {number} position A position to clamp<ko>범위를 제한할 좌표</ko>
4112
- * @return {number} A clamped position<ko>범위 제한된 좌표</ko>
4113
- */
4080
+ return BoundCameraMode;
4081
+ }(CameraMode);
4114
4082
 
4083
+ /**
4084
+ * A component that manages actual movement inside the viewport
4085
+ * @ko 뷰포트 내에서의 실제 움직임을 담당하는 컴포넌트
4086
+ */
4115
4087
 
4116
- __proto.clampToReachablePosition = function (position) {
4117
- var range = this._range;
4118
- return clamp(position, range.min, range.max);
4119
- };
4120
- /**
4121
- * Check whether the given panel is inside of the Camera's range
4122
- * @ko 해당 {@link Panel}이 Camera가 도달 가능한 범위 내에 있는지를 반환합니다
4123
- * @param panel An instance of {@link Panel} to check<ko>확인할 {@link Panel}의 인스턴스</ko>
4124
- * @return {boolean} Whether the panel's inside Camera's range<ko>도달 가능한 범위 내에 해당 패널이 존재하는지 여부</ko>
4125
- */
4088
+ var Camera$1 =
4089
+ /*#__PURE__*/
4090
+ function () {
4091
+ /** */
4092
+ function Camera(_a) {
4093
+ var _this = this;
4126
4094
 
4095
+ var _b = (_a === void 0 ? {} : _a).align,
4096
+ align = _b === void 0 ? ALIGN.CENTER : _b;
4127
4097
 
4128
- __proto.canReach = function (panel) {
4129
- var range = this._range;
4130
- if (panel.removed) return false;
4131
- var panelPos = panel.position;
4132
- return panelPos >= range.min && panelPos <= range.max;
4133
- };
4134
- /**
4135
- * Check whether the given panel element is visible at the current position
4136
- * @ko 현재 좌표에서 해당 패널 엘리먼트를 볼 수 있는지 여부를 반환합니다
4137
- * @param panel An instance of {@link Panel} to check<ko>확인할 {@link Panel}의 인스턴스</ko>
4138
- * @return Whether the panel element is visible at the current position<ko>현재 위치에서 해당 패널 엘리먼트가 보이는지 여부</ko>
4139
- */
4098
+ this._checkTranslateSupport = function () {
4099
+ var e_1, _a;
4140
4100
 
4101
+ var transforms = ["webkitTransform", "msTransform", "MozTransform", "OTransform", "transform"];
4102
+ var supportedStyle = document.documentElement.style;
4103
+ var transformName = "";
4141
4104
 
4142
- __proto.canSee = function (panel) {
4143
- var visibleRange = this.visibleRange; // Should not include margin, as we don't declare what the margin is visible as what the panel is visible.
4105
+ try {
4106
+ for (var transforms_1 = __values(transforms), transforms_1_1 = transforms_1.next(); !transforms_1_1.done; transforms_1_1 = transforms_1.next()) {
4107
+ var prefixedTransform = transforms_1_1.value;
4144
4108
 
4145
- return panel.isVisibleOnRange(visibleRange.min, visibleRange.max);
4146
- };
4147
- /**
4148
- * Update Camera's {@link Camera#alignPosition alignPosition}
4149
- * @ko Camera의 {@link Camera#alignPosition alignPosition}을 업데이트합니다
4150
- * @chainable
4151
- * @return {this}
4152
- */
4109
+ if (prefixedTransform in supportedStyle) {
4110
+ transformName = prefixedTransform;
4111
+ }
4112
+ }
4113
+ } catch (e_1_1) {
4114
+ e_1 = {
4115
+ error: e_1_1
4116
+ };
4117
+ } finally {
4118
+ try {
4119
+ if (transforms_1_1 && !transforms_1_1.done && (_a = transforms_1.return)) _a.call(transforms_1);
4120
+ } finally {
4121
+ if (e_1) throw e_1.error;
4122
+ }
4123
+ }
4153
4124
 
4125
+ if (!transformName) {
4126
+ throw new FlickingError(MESSAGE.TRANSFORM_NOT_SUPPORTED, CODE.TRANSFORM_NOT_SUPPORTED);
4127
+ }
4154
4128
 
4155
- __proto.updateAlignPos = function () {
4156
- var align = this._align;
4157
- var alignVal = typeof align === "object" ? align.camera : align;
4158
- this._alignPos = parseAlign$1(alignVal, this.size);
4159
- return this;
4160
- };
4161
- /**
4162
- * Update Camera's {@link Camera#anchorPoints anchorPoints}
4163
- * @ko Camera의 {@link Camera#anchorPoints anchorPoints}를 업데이트합니다
4164
- * @throws {FlickingError}
4165
- * {@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} When {@link Camera#init init} is not called before
4166
- * <ko>{@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} {@link Camera#init init}이 이전에 호출되지 않은 경우</ko>
4167
- * @chainable
4168
- * @return {this}
4169
- */
4170
-
4171
-
4172
- __proto.updateAnchors = function () {
4173
- var flicking = getFlickingAttached(this._flicking);
4174
- var panels = flicking.renderer.panels;
4175
- this._anchors = panels.map(function (panel, index) {
4176
- return new AnchorPoint({
4177
- index: index,
4178
- position: panel.position,
4179
- panel: panel
4180
- });
4181
- });
4182
- return this;
4183
- };
4184
- /**
4185
- * Update Viewport's height to active panel's height
4186
- * @ko 현재 선택된 패널의 높이와 동일하도록 뷰포트의 높이를 업데이트합니다
4187
- * @throws {FlickingError}
4188
- * {@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} When {@link Camera#init init} is not called before
4189
- * <ko>{@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} {@link Camera#init init}이 이전에 호출되지 않은 경우</ko>
4190
- * @chainable
4191
- * @return {this}
4192
- */
4193
-
4194
-
4195
- __proto.updateAdaptiveHeight = function () {
4196
- var flicking = getFlickingAttached(this._flicking);
4197
- var activePanel = flicking.control.activePanel;
4198
- if (!flicking.horizontal || !flicking.adaptive || !activePanel) return;
4199
- flicking.viewport.setSize({
4200
- height: activePanel.height
4201
- });
4202
- };
4203
- /**
4204
- * Update current offset of the camera
4205
- * @ko 현재 카메라의 오프셋을 업데이트합니다
4206
- * @chainable
4207
- * @return {this}
4208
- */
4209
-
4210
-
4211
- __proto.updateOffset = function () {
4212
- var flicking = getFlickingAttached(this._flicking);
4213
- var position = this._position;
4214
- var unRenderedPanels = flicking.panels.filter(function (panel) {
4215
- return !panel.rendered;
4216
- });
4217
- this._offset = unRenderedPanels.filter(function (panel) {
4218
- return panel.position + panel.offset < position;
4219
- }).reduce(function (offset, panel) {
4220
- return offset + panel.sizeIncludingMargin;
4221
- }, 0);
4222
- this.applyTransform();
4223
- return this;
4224
- };
4225
- /**
4226
- * Reset the history of {@link Flicking#event:needPanel needPanel} events so it can be triggered again
4227
- * @ko 발생한 {@link Flicking#event:needPanel needPanel} 이벤트들을 초기화하여 다시 발생할 수 있도록 합니다
4228
- * @chainable
4229
- * @return {this}
4230
- */
4231
-
4232
-
4233
- __proto.resetNeedPanelHistory = function () {
4234
- this._needPanelTriggered = {
4235
- prev: false,
4236
- next: false
4129
+ _this._transform = transformName;
4237
4130
  };
4238
- return this;
4239
- };
4240
- /**
4241
- * Apply "transform" style with the current position to camera element
4242
- * @ko 현재 위치를 기준으로한 transform 스타일을 카메라 엘리먼트에 적용합니다.
4243
- * @chainable
4244
- * @return {this}
4245
- */
4246
4131
 
4132
+ this._flicking = null;
4247
4133
 
4248
- __proto.applyTransform = function () {
4249
- var el = this._el;
4250
- var flicking = getFlickingAttached(this._flicking);
4251
- var actualPosition = this._position - this._alignPos - this._offset;
4252
- el.style[this._transform] = flicking.horizontal ? "translate(" + -actualPosition + "px)" : "translate(0, " + -actualPosition + "px)";
4253
- return this;
4254
- };
4134
+ this._resetInternalValues(); // Options
4255
4135
 
4256
- __proto._resetInternalValues = function () {
4257
- this._position = 0;
4258
- this._alignPos = 0;
4259
- this._offset = 0;
4260
- this._range = {
4261
- min: 0,
4262
- max: 0
4263
- };
4264
- this._visiblePanels = [];
4265
- this._anchors = [];
4266
- this._needPanelTriggered = {
4267
- prev: false,
4268
- next: false
4269
- };
4270
- };
4271
4136
 
4272
- __proto._refreshVisiblePanels = function () {
4273
- var _this = this;
4137
+ this._align = align;
4138
+ }
4274
4139
 
4275
- var flicking = getFlickingAttached(this._flicking);
4276
- var panels = flicking.renderer.panels;
4277
- var newVisiblePanels = panels.filter(function (panel) {
4278
- return _this.canSee(panel);
4279
- });
4280
- var prevVisiblePanels = this._visiblePanels;
4281
- this._visiblePanels = newVisiblePanels;
4282
- var added = newVisiblePanels.filter(function (panel) {
4283
- return !includes(prevVisiblePanels, panel);
4284
- });
4285
- var removed = prevVisiblePanels.filter(function (panel) {
4286
- return !includes(newVisiblePanels, panel);
4287
- });
4140
+ var __proto = Camera.prototype;
4141
+ Object.defineProperty(__proto, "element", {
4142
+ // Internal states getter
4143
+
4144
+ /**
4145
+ * The camera element(`.flicking-camera`)
4146
+ * @ko 카메라 엘리먼트(`.flicking-camera`)
4147
+ * @type {HTMLElement}
4148
+ * @readonly
4149
+ */
4150
+ get: function () {
4151
+ return this._el;
4152
+ },
4153
+ enumerable: false,
4154
+ configurable: true
4155
+ });
4156
+ Object.defineProperty(__proto, "children", {
4157
+ /**
4158
+ * An array of the child elements of the camera element(`.flicking-camera`)
4159
+ * @ko 카메라 엘리먼트(`.flicking-camera`)의 자식 엘리먼트 배열
4160
+ * @type {HTMLElement[]}
4161
+ * @readonly
4162
+ */
4163
+ get: function () {
4164
+ return toArray(this._el.children);
4165
+ },
4166
+ enumerable: false,
4167
+ configurable: true
4168
+ });
4169
+ Object.defineProperty(__proto, "position", {
4170
+ /**
4171
+ * Current position of the camera
4172
+ * @ko Camera의 현재 좌표
4173
+ * @type {number}
4174
+ * @readonly
4175
+ */
4176
+ get: function () {
4177
+ return this._position;
4178
+ },
4179
+ enumerable: false,
4180
+ configurable: true
4181
+ });
4182
+ Object.defineProperty(__proto, "alignPosition", {
4183
+ /**
4184
+ * Align position inside the viewport where {@link Panel}'s {@link Panel#alignPosition alignPosition} should be located at
4185
+ * @ko 패널의 정렬 기준 위치. 뷰포트 내에서 {@link Panel}의 {@link Panel#alignPosition alignPosition}이 위치해야 하는 곳입니다
4186
+ * @type {number}
4187
+ * @readonly
4188
+ */
4189
+ get: function () {
4190
+ return this._alignPos;
4191
+ },
4192
+ enumerable: false,
4193
+ configurable: true
4194
+ });
4195
+ Object.defineProperty(__proto, "offset", {
4196
+ /**
4197
+ * Position offset, used for the {@link Flicking#renderOnlyVisible renderOnlyVisible} option
4198
+ * @ko Camera의 좌표 오프셋. {@link Flicking#renderOnlyVisible renderOnlyVisible} 옵션을 위해 사용됩니다.
4199
+ * @type {number}
4200
+ * @default 0
4201
+ * @readonly
4202
+ */
4203
+ get: function () {
4204
+ return this._offset - this._circularOffset;
4205
+ },
4206
+ enumerable: false,
4207
+ configurable: true
4208
+ });
4209
+ Object.defineProperty(__proto, "circularEnabled", {
4210
+ /**
4211
+ * Whether the `circular` option is enabled.
4212
+ * The {@link Flicking#circular circular} option can't be enabled when sum of the panel sizes are too small.
4213
+ * @ko {@link Flicking#circular circular} 옵션이 활성화되었는지 여부를 나타내는 멤버 변수.
4214
+ * {@link Flicking#circular circular} 옵션은 패널의 크기의 합이 충분하지 않을 경우 비활성화됩니다.
4215
+ * @type {boolean}
4216
+ * @default false
4217
+ * @readonly
4218
+ */
4219
+ get: function () {
4220
+ return this._circularEnabled;
4221
+ },
4222
+ enumerable: false,
4223
+ configurable: true
4224
+ });
4225
+ Object.defineProperty(__proto, "mode", {
4226
+ /**
4227
+ * A current camera mode
4228
+ * @type {CameraMode}
4229
+ * @readonly
4230
+ */
4231
+ get: function () {
4232
+ return this._mode;
4233
+ },
4234
+ enumerable: false,
4235
+ configurable: true
4236
+ });
4237
+ Object.defineProperty(__proto, "range", {
4238
+ /**
4239
+ * A range that Camera's {@link Camera#position position} can reach
4240
+ * @ko Camera의 {@link Camera#position position}이 도달 가능한 범위
4241
+ * @type {object}
4242
+ * @property {number} min A minimum position<ko>최소 위치</ko>
4243
+ * @property {number} max A maximum position<ko>최대 위치</ko>
4244
+ * @readonly
4245
+ */
4246
+ get: function () {
4247
+ return this._range;
4248
+ },
4249
+ enumerable: false,
4250
+ configurable: true
4251
+ });
4252
+ Object.defineProperty(__proto, "rangeDiff", {
4253
+ /**
4254
+ * A difference between Camera's minimum and maximum position that can reach
4255
+ * @ko Camera가 도달 가능한 최소/최대 좌표의 차이
4256
+ * @type {number}
4257
+ * @readonly
4258
+ */
4259
+ get: function () {
4260
+ return this._range.max - this._range.min;
4261
+ },
4262
+ enumerable: false,
4263
+ configurable: true
4264
+ });
4265
+ Object.defineProperty(__proto, "visiblePanels", {
4266
+ /**
4267
+ * An array of visible panels from the current position
4268
+ * @ko 현재 보이는 패널들의 배열
4269
+ * @type {Panel[]}
4270
+ * @readonly
4271
+ */
4272
+ get: function () {
4273
+ return this._visiblePanels;
4274
+ },
4275
+ enumerable: false,
4276
+ configurable: true
4277
+ });
4278
+ Object.defineProperty(__proto, "visibleRange", {
4279
+ /**
4280
+ * A range of the visible area from the current position
4281
+ * @ko 현재 위치에서 보이는 범위
4282
+ * @type {object}
4283
+ * @property {number} min A minimum position<ko>최소 위치</ko>
4284
+ * @property {number} min A maximum position<ko>최대 위치</ko>
4285
+ * @readonly
4286
+ */
4287
+ get: function () {
4288
+ return {
4289
+ min: this._position - this._alignPos,
4290
+ max: this._position - this._alignPos + this.size
4291
+ };
4292
+ },
4293
+ enumerable: false,
4294
+ configurable: true
4295
+ });
4296
+ Object.defineProperty(__proto, "anchorPoints", {
4297
+ /**
4298
+ * An array of {@link AnchorPoint}s that Camera can be stopped at
4299
+ * @ko 카메라가 도달 가능한 {@link AnchorPoint}의 목록
4300
+ * @type {AnchorPoint[]}
4301
+ * @readonly
4302
+ */
4303
+ get: function () {
4304
+ return this._anchors;
4305
+ },
4306
+ enumerable: false,
4307
+ configurable: true
4308
+ });
4309
+ Object.defineProperty(__proto, "controlParams", {
4310
+ /**
4311
+ * A current parameters of the Camera for updating {@link AxesController}
4312
+ * @ko {@link AxesController}를 업데이트하기 위한 현재 Camera 패러미터들
4313
+ * @type {ControlParams}
4314
+ * @readonly
4315
+ */
4316
+ get: function () {
4317
+ return {
4318
+ range: this._range,
4319
+ position: this._position,
4320
+ circular: this._circularEnabled
4321
+ };
4322
+ },
4323
+ enumerable: false,
4324
+ configurable: true
4325
+ });
4326
+ Object.defineProperty(__proto, "atEdge", {
4327
+ /**
4328
+ * A Boolean value indicating whether Camera's over the minimum or maximum position reachable
4329
+ * @ko 현재 카메라가 도달 가능한 범위의 최소 혹은 최대점을 넘어섰는지를 나타냅니다
4330
+ * @type {boolean}
4331
+ * @readonly
4332
+ */
4333
+ get: function () {
4334
+ return this._position <= this._range.min || this._position >= this._range.max;
4335
+ },
4336
+ enumerable: false,
4337
+ configurable: true
4338
+ });
4339
+ Object.defineProperty(__proto, "size", {
4340
+ /**
4341
+ * Return the size of the viewport
4342
+ * @ko 뷰포트 크기를 반환합니다
4343
+ * @type {number}
4344
+ * @readonly
4345
+ */
4346
+ get: function () {
4347
+ var flicking = this._flicking;
4348
+ return flicking ? flicking.horizontal ? flicking.viewport.width : flicking.viewport.height : 0;
4349
+ },
4350
+ enumerable: false,
4351
+ configurable: true
4352
+ });
4353
+ Object.defineProperty(__proto, "progress", {
4354
+ /**
4355
+ * Return the camera's position progress from the first panel to last panel
4356
+ * Range is from 0 to last panel's index
4357
+ * @ko 첫번째 패널로부터 마지막 패널까지의 카메라 위치의 진행도를 반환합니다
4358
+ * 범위는 0부터 마지막 패널의 인덱스까지입니다
4359
+ * @type {number}
4360
+ * @readonly
4361
+ */
4362
+ get: function () {
4363
+ var flicking = this._flicking;
4364
+ var position = this._position + this._offset;
4365
+ var nearestAnchor = this.findNearestAnchor(this._position);
4288
4366
 
4289
- if (added.length > 0 || removed.length > 0) {
4290
- void flicking.renderer.render().then(function () {
4291
- flicking.trigger(new Component.ComponentEvent(EVENTS.VISIBLE_CHANGE, {
4292
- added: added,
4293
- removed: removed,
4294
- visiblePanels: newVisiblePanels
4295
- }));
4296
- });
4297
- }
4298
- };
4367
+ if (!flicking || !nearestAnchor) {
4368
+ return NaN;
4369
+ }
4299
4370
 
4300
- __proto._checkNeedPanel = function () {
4301
- var needPanelTriggered = this._needPanelTriggered;
4302
- if (needPanelTriggered.prev && needPanelTriggered.next) return;
4303
- var flicking = getFlickingAttached(this._flicking);
4304
- var panels = flicking.renderer.panels;
4371
+ var nearestPanel = nearestAnchor.panel;
4372
+ var panelPos = nearestPanel.position + nearestPanel.offset;
4373
+ var bounceSize = flicking.control.controller.bounce;
4374
+ var _a = this.range,
4375
+ prevRange = _a.min,
4376
+ nextRange = _a.max;
4377
+ var rangeDiff = this.rangeDiff;
4305
4378
 
4306
- if (panels.length <= 0) {
4307
- if (!needPanelTriggered.prev) {
4308
- flicking.trigger(new Component.ComponentEvent(EVENTS.NEED_PANEL, {
4309
- direction: DIRECTION.PREV
4310
- }));
4311
- needPanelTriggered.prev = true;
4379
+ if (position === panelPos) {
4380
+ return nearestPanel.index;
4312
4381
  }
4313
4382
 
4314
- if (!needPanelTriggered.next) {
4315
- flicking.trigger(new Component.ComponentEvent(EVENTS.NEED_PANEL, {
4316
- direction: DIRECTION.NEXT
4317
- }));
4318
- needPanelTriggered.next = true;
4319
- }
4383
+ if (position < panelPos) {
4384
+ var prevPanel = nearestPanel.prev();
4385
+ var prevPosition = prevPanel ? prevPanel.position + prevPanel.offset : prevRange - bounceSize[0]; // Looped
4320
4386
 
4321
- return;
4322
- }
4387
+ if (prevPosition > panelPos) {
4388
+ prevPosition -= rangeDiff;
4389
+ }
4323
4390
 
4324
- var cameraPosition = this._position;
4325
- var cameraSize = this.size;
4326
- var cameraRange = this._range;
4327
- var needPanelThreshold = flicking.needPanelThreshold;
4328
- var cameraPrev = cameraPosition - this._alignPos;
4329
- var cameraNext = cameraPrev + cameraSize;
4330
- var firstPanel = panels[0];
4331
- var lastPanel = panels[panels.length - 1];
4391
+ return nearestPanel.index - 1 + getProgress(position, prevPosition, panelPos);
4392
+ } else {
4393
+ var nextPanel = nearestPanel.next();
4394
+ var nextPosition = nextPanel ? nextPanel.position + nextPanel.offset : nextRange + bounceSize[1]; // Looped
4332
4395
 
4333
- if (!needPanelTriggered.prev) {
4334
- var firstPanelPrev = firstPanel.range.min;
4396
+ if (nextPosition < panelPos) {
4397
+ nextPosition += rangeDiff;
4398
+ }
4335
4399
 
4336
- if (cameraPrev <= firstPanelPrev + needPanelThreshold || cameraPosition <= cameraRange.min + needPanelThreshold) {
4337
- flicking.trigger(new Component.ComponentEvent(EVENTS.NEED_PANEL, {
4338
- direction: DIRECTION.PREV
4339
- }));
4340
- needPanelTriggered.prev = true;
4400
+ return nearestPanel.index + getProgress(position, panelPos, nextPosition);
4341
4401
  }
4342
- }
4402
+ },
4403
+ enumerable: false,
4404
+ configurable: true
4405
+ });
4406
+ Object.defineProperty(__proto, "align", {
4407
+ // Options Getter
4343
4408
 
4344
- if (!needPanelTriggered.next) {
4345
- var lastPanelNext = lastPanel.range.max;
4409
+ /**
4410
+ * A value indicating where the {@link Camera#alignPosition alignPosition} should be located at inside the viewport element
4411
+ * @ko {@link Camera#alignPosition alignPosition}이 뷰포트 엘리먼트 내의 어디에 위치해야 하는지를 나타내는 값
4412
+ * @type {ALIGN | string | number}
4413
+ */
4414
+ get: function () {
4415
+ return this._align;
4416
+ },
4417
+ // Options Setter
4418
+ set: function (val) {
4419
+ this._align = val;
4420
+ },
4421
+ enumerable: false,
4422
+ configurable: true
4423
+ });
4424
+ /**
4425
+ * Initialize Camera
4426
+ * @ko Camera를 초기화합니다
4427
+ * @param {Flicking} flicking An instance of {@link Flicking}<ko>Flicking의 인스턴스</ko>
4428
+ * @chainable
4429
+ * @throws {FlickingError}
4430
+ * {@link ERROR_CODE VAL_MUST_NOT_NULL} If the camera element(`.flicking-camera`) does not exist inside viewport element
4431
+ * <ko>{@link ERROR_CODE VAL_MUST_NOT_NULL} 뷰포트 엘리먼트 내부에 카메라 엘리먼트(`.flicking-camera`)가 존재하지 않을 경우</ko>
4432
+ * @return {this}
4433
+ */
4346
4434
 
4347
- if (cameraNext >= lastPanelNext - needPanelThreshold || cameraPosition >= cameraRange.max - needPanelThreshold) {
4348
- flicking.trigger(new Component.ComponentEvent(EVENTS.NEED_PANEL, {
4349
- direction: DIRECTION.NEXT
4350
- }));
4351
- needPanelTriggered.next = true;
4352
- }
4353
- }
4354
- };
4435
+ __proto.init = function (flicking) {
4436
+ this._flicking = flicking;
4437
+ var viewportEl = flicking.viewport.element;
4438
+ checkExistence(viewportEl.firstElementChild, "First element child of the viewport element");
4439
+ this._el = viewportEl.firstElementChild;
4355
4440
 
4356
- __proto._checkReachEnd = function (prevPos, newPos) {
4357
- var flicking = getFlickingAttached(this._flicking);
4358
- var range = this._range;
4359
- var wasBetweenRange = prevPos > range.min && prevPos < range.max;
4360
- var isBetweenRange = newPos > range.min && newPos < range.max;
4361
- if (!wasBetweenRange || isBetweenRange) return;
4362
- var direction = newPos <= range.min ? DIRECTION.PREV : DIRECTION.NEXT;
4363
- flicking.trigger(new Component.ComponentEvent(EVENTS.REACH_EDGE, {
4364
- direction: direction
4365
- }));
4441
+ this._checkTranslateSupport();
4442
+
4443
+ this._updateMode();
4444
+
4445
+ return this;
4366
4446
  };
4447
+ /**
4448
+ * Destroy Camera and return to initial state
4449
+ * @ko Camera를 초기 상태로 되돌립니다
4450
+ * @return {void}
4451
+ */
4367
4452
 
4368
- return Camera;
4369
- }();
4370
4453
 
4371
- /**
4372
- * A {@link Camera} that can move from the position of the first panel to the position of the last panel
4373
- * @ko 첫번째 패널의 좌표로부터 마지막 패널의 좌표로까지 이동할 수 있는 종류의 {@link Camera}
4374
- */
4454
+ __proto.destroy = function () {
4455
+ this._flicking = null;
4375
4456
 
4376
- var LinearCamera =
4377
- /*#__PURE__*/
4378
- function (_super) {
4379
- __extends(LinearCamera, _super);
4457
+ this._resetInternalValues();
4380
4458
 
4381
- function LinearCamera() {
4382
- return _super !== null && _super.apply(this, arguments) || this;
4383
- }
4459
+ return this;
4460
+ };
4384
4461
  /**
4385
- * Update {@link Camera#range range} of Camera
4386
- * @ko Camera의 {@link Camera#range range}를 업데이트합니다
4387
- * @chainable
4462
+ * Move to the given position and apply CSS transform
4463
+ * @ko 해당 좌표로 이동하고, CSS transform을 적용합니다
4464
+ * @param {number} pos A new position<ko>움직일 위치</ko>
4388
4465
  * @throws {FlickingError}
4389
4466
  * {@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} When {@link Camera#init init} is not called before
4390
4467
  * <ko>{@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} {@link Camera#init init}이 이전에 호출되지 않은 경우</ko>
@@ -4392,170 +4469,190 @@ version: 4.4.2
4392
4469
  */
4393
4470
 
4394
4471
 
4395
- var __proto = LinearCamera.prototype;
4396
-
4397
- __proto.updateRange = function () {
4398
- var _a, _b;
4472
+ __proto.lookAt = function (pos) {
4473
+ var _this = this;
4399
4474
 
4400
4475
  var flicking = getFlickingAttached(this._flicking);
4401
- var renderer = flicking.renderer;
4402
- var firstPanel = renderer.getPanel(0);
4403
- var lastPanel = renderer.getPanel(renderer.panelCount - 1);
4404
- this._range = {
4405
- min: (_a = firstPanel === null || firstPanel === void 0 ? void 0 : firstPanel.position) !== null && _a !== void 0 ? _a : 0,
4406
- max: (_b = lastPanel === null || lastPanel === void 0 ? void 0 : lastPanel.position) !== null && _b !== void 0 ? _b : 0
4407
- };
4408
- return this;
4409
- };
4476
+ var prevPos = this._position;
4477
+ this._position = pos;
4410
4478
 
4411
- return LinearCamera;
4412
- }(Camera$1);
4479
+ var toggled = this._togglePanels(prevPos, pos);
4413
4480
 
4414
- /**
4415
- * A {@link Camera} that connects the last panel and the first panel, enabling continuous loop
4416
- * @ko 첫번째 패널과 마지막 패널이 이어진 상태로, 무한히 회전할 수 있는 종류의 {@link Camera}
4417
- */
4481
+ this._refreshVisiblePanels();
4418
4482
 
4419
- var CircularCamera =
4420
- /*#__PURE__*/
4421
- function (_super) {
4422
- __extends(CircularCamera, _super);
4483
+ this._checkNeedPanel();
4423
4484
 
4424
- function CircularCamera() {
4425
- var _this = _super !== null && _super.apply(this, arguments) || this;
4485
+ this._checkReachEnd(prevPos, pos);
4426
4486
 
4427
- _this._circularOffset = 0;
4428
- _this._circularEnabled = false;
4429
- return _this;
4430
- }
4487
+ this.applyTransform();
4488
+
4489
+ if (toggled) {
4490
+ void flicking.renderer.render().then(function () {
4491
+ _this.updateOffset();
4492
+ });
4493
+ }
4494
+ };
4495
+ /**
4496
+ * Return a previous {@link AnchorPoint} of given {@link AnchorPoint}
4497
+ * If it does not exist, return `null` instead
4498
+ * @ko 주어진 {@link AnchorPoint}의 이전 {@link AnchorPoint}를 반환합니다
4499
+ * 존재하지 않을 경우 `null`을 반환합니다
4500
+ * @param {AnchorPoint} anchor A reference {@link AnchorPoint}<ko>기준 {@link AnchorPoint}</ko>
4501
+ * @return {AnchorPoint | null} The previous {@link AnchorPoint}<ko>이전 {@link AnchorPoint}</ko>
4502
+ */
4431
4503
 
4432
- var __proto = CircularCamera.prototype;
4433
- Object.defineProperty(__proto, "offset", {
4434
- get: function () {
4435
- return this._offset - this._circularOffset;
4436
- },
4437
- enumerable: false,
4438
- configurable: true
4439
- });
4440
- Object.defineProperty(__proto, "controlParams", {
4441
- get: function () {
4442
- return {
4443
- range: this._range,
4444
- position: this._position,
4445
- circular: this._circularEnabled
4446
- };
4447
- },
4448
- enumerable: false,
4449
- configurable: true
4450
- });
4451
4504
 
4452
4505
  __proto.getPrevAnchor = function (anchor) {
4453
- if (!this._circularEnabled || anchor.index !== 0) return _super.prototype.getPrevAnchor.call(this, anchor);
4454
- var anchors = this._anchors;
4455
- var rangeDiff = this.rangeDiff;
4456
- var lastAnchor = anchors[anchors.length - 1];
4457
- return new AnchorPoint({
4458
- index: lastAnchor.index,
4459
- position: lastAnchor.position - rangeDiff,
4460
- panel: lastAnchor.panel
4461
- });
4506
+ if (!this._circularEnabled || anchor.index !== 0) {
4507
+ return this._anchors[anchor.index - 1] || null;
4508
+ } else {
4509
+ var anchors = this._anchors;
4510
+ var rangeDiff = this.rangeDiff;
4511
+ var lastAnchor = anchors[anchors.length - 1];
4512
+ return new AnchorPoint({
4513
+ index: lastAnchor.index,
4514
+ position: lastAnchor.position - rangeDiff,
4515
+ panel: lastAnchor.panel
4516
+ });
4517
+ }
4462
4518
  };
4519
+ /**
4520
+ * Return a next {@link AnchorPoint} of given {@link AnchorPoint}
4521
+ * If it does not exist, return `null` instead
4522
+ * @ko 주어진 {@link AnchorPoint}의 다음 {@link AnchorPoint}를 반환합니다
4523
+ * 존재하지 않을 경우 `null`을 반환합니다
4524
+ * @param {AnchorPoint} anchor A reference {@link AnchorPoint}<ko>기준 {@link AnchorPoint}</ko>
4525
+ * @return {AnchorPoint | null} The next {@link AnchorPoint}<ko>다음 {@link AnchorPoint}</ko>
4526
+ */
4527
+
4463
4528
 
4464
4529
  __proto.getNextAnchor = function (anchor) {
4465
4530
  var anchors = this._anchors;
4466
- if (!this._circularEnabled || anchor.index !== anchors.length - 1) return _super.prototype.getNextAnchor.call(this, anchor);
4467
- var rangeDiff = this.rangeDiff;
4468
- var firstAnchor = anchors[0];
4469
- return new AnchorPoint({
4470
- index: firstAnchor.index,
4471
- position: firstAnchor.position + rangeDiff,
4472
- panel: firstAnchor.panel
4473
- });
4531
+
4532
+ if (!this._circularEnabled || anchor.index !== anchors.length - 1) {
4533
+ return anchors[anchor.index + 1] || null;
4534
+ } else {
4535
+ var rangeDiff = this.rangeDiff;
4536
+ var firstAnchor = anchors[0];
4537
+ return new AnchorPoint({
4538
+ index: firstAnchor.index,
4539
+ position: firstAnchor.position + rangeDiff,
4540
+ panel: firstAnchor.panel
4541
+ });
4542
+ }
4543
+ };
4544
+ /**
4545
+ * Return the camera's position progress in the panel below
4546
+ * Value is from 0 to 1 when the camera's inside panel
4547
+ * Value can be lower than 0 or bigger than 1 when it's in the margin area
4548
+ * @ko 현재 카메라 아래 패널에서의 위치 진행도를 반환합니다
4549
+ * 반환값은 카메라가 패널 내부에 있을 경우 0부터 1까지의 값을 갖습니다
4550
+ * 패널의 margin 영역에 있을 경우 0보다 작거나 1보다 큰 값을 반환할 수 있습니다
4551
+ */
4552
+
4553
+
4554
+ __proto.getProgressInPanel = function (panel) {
4555
+ var panelRange = panel.range;
4556
+ return (this._position - panelRange.min) / (panelRange.max - panelRange.min);
4474
4557
  };
4558
+ /**
4559
+ * Return {@link AnchorPoint} that includes given position
4560
+ * If there's no {@link AnchorPoint} that includes the given position, return `null` instead
4561
+ * @ko 주어진 좌표를 포함하는 {@link AnchorPoint}를 반환합니다
4562
+ * 주어진 좌표를 포함하는 {@link AnchorPoint}가 없을 경우 `null`을 반환합니다
4563
+ * @param {number} position A position to check<ko>확인할 좌표</ko>
4564
+ * @return {AnchorPoint | null} The {@link AnchorPoint} that includes the given position<ko>해당 좌표를 포함하는 {@link AnchorPoint}</ko>
4565
+ */
4566
+
4475
4567
 
4476
4568
  __proto.findAnchorIncludePosition = function (position) {
4477
- if (!this._circularEnabled) return _super.prototype.findAnchorIncludePosition.call(this, position);
4478
- var range = this._range;
4569
+ return this._mode.findAnchorIncludePosition(position);
4570
+ };
4571
+ /**
4572
+ * Return {@link AnchorPoint} nearest to given position
4573
+ * If there're no {@link AnchorPoint}s, return `null` instead
4574
+ * @ko 해당 좌표에서 가장 가까운 {@link AnchorPoint}를 반환합니다
4575
+ * {@link AnchorPoint}가 하나도 없을 경우 `null`을 반환합니다
4576
+ * @param {number} position A position to check<ko>확인할 좌표</ko>
4577
+ * @return {AnchorPoint | null} The {@link AnchorPoint} nearest to the given position<ko>해당 좌표에 가장 인접한 {@link AnchorPoint}</ko>
4578
+ */
4579
+
4580
+
4581
+ __proto.findNearestAnchor = function (position) {
4479
4582
  var anchors = this._anchors;
4480
- var rangeDiff = this.rangeDiff;
4481
- var anchorCount = anchors.length;
4482
- var positionInRange = circulatePosition(position, range.min, range.max);
4583
+ if (anchors.length <= 0) return null;
4584
+ var prevDist = Infinity;
4483
4585
 
4484
- var anchorInRange = _super.prototype.findAnchorIncludePosition.call(this, positionInRange);
4586
+ for (var anchorIdx = 0; anchorIdx < anchors.length; anchorIdx++) {
4587
+ var anchor = anchors[anchorIdx];
4588
+ var dist = Math.abs(anchor.position - position);
4485
4589
 
4486
- if (anchorCount > 0 && (position === range.min || position === range.max)) {
4487
- var possibleAnchors = [anchorInRange, new AnchorPoint({
4488
- index: 0,
4489
- position: anchors[0].position + rangeDiff,
4490
- panel: anchors[0].panel
4491
- }), new AnchorPoint({
4492
- index: anchorCount - 1,
4493
- position: anchors[anchorCount - 1].position - rangeDiff,
4494
- panel: anchors[anchorCount - 1].panel
4495
- })].filter(function (anchor) {
4496
- return !!anchor;
4497
- });
4498
- anchorInRange = possibleAnchors.reduce(function (nearest, anchor) {
4499
- if (!nearest) return anchor;
4500
- return Math.abs(nearest.position - position) < Math.abs(anchor.position - position) ? nearest : anchor;
4501
- }, null);
4502
- }
4590
+ if (dist > prevDist) {
4591
+ // Return previous anchor
4592
+ return anchors[anchorIdx - 1];
4593
+ }
4503
4594
 
4504
- if (!anchorInRange) return null;
4595
+ prevDist = dist;
4596
+ } // Return last anchor
4505
4597
 
4506
- if (position < range.min) {
4507
- var loopCount = -Math.floor((range.min - position) / rangeDiff) - 1;
4508
- return new AnchorPoint({
4509
- index: anchorInRange.index,
4510
- position: anchorInRange.position + rangeDiff * loopCount,
4511
- panel: anchorInRange.panel
4512
- });
4513
- } else if (position > range.max) {
4514
- var loopCount = Math.floor((position - range.max) / rangeDiff) + 1;
4515
- return new AnchorPoint({
4516
- index: anchorInRange.index,
4517
- position: anchorInRange.position + rangeDiff * loopCount,
4518
- panel: anchorInRange.panel
4519
- });
4520
- }
4521
4598
 
4522
- return anchorInRange;
4599
+ return anchors[anchors.length - 1];
4523
4600
  };
4601
+ /**
4602
+ * Return {@link AnchorPoint} that matches {@link Flicking#currentPanel}
4603
+ * @ko 현재 {@link Flicking#currentPanel}에 해당하는 {@link AnchorPoint}를 반환합니다
4604
+ * @return {AnchorPoint | null}
4605
+ */
4524
4606
 
4525
- __proto.clampToReachablePosition = function (position) {
4526
- // Basically all position is reachable for circular camera
4527
- return this._circularEnabled ? position : _super.prototype.clampToReachablePosition.call(this, position);
4528
- };
4529
4607
 
4530
- __proto.canReach = function (panel) {
4531
- if (panel.removed) return false;
4532
- return this._circularEnabled // Always reachable on circular mode
4533
- ? true : _super.prototype.canReach.call(this, panel);
4608
+ __proto.findActiveAnchor = function () {
4609
+ var flicking = getFlickingAttached(this._flicking);
4610
+ var activeIndex = flicking.control.activeIndex;
4611
+ return find(this._anchors, function (anchor) {
4612
+ return anchor.panel.index === activeIndex;
4613
+ });
4534
4614
  };
4615
+ /**
4616
+ * Clamp the given position between camera's range
4617
+ * @ko 주어진 좌표를 Camera가 도달 가능한 범위 사이의 값으로 만듭니다
4618
+ * @param {number} position A position to clamp<ko>범위를 제한할 좌표</ko>
4619
+ * @return {number} A clamped position<ko>범위 제한된 좌표</ko>
4620
+ */
4535
4621
 
4536
- __proto.canSee = function (panel) {
4537
- var range = this._range;
4538
- var rangeDiff = this.rangeDiff;
4539
- var visibleRange = this.visibleRange;
4540
4622
 
4541
- var visibleInCurrentRange = _super.prototype.canSee.call(this, panel);
4623
+ __proto.clampToReachablePosition = function (position) {
4624
+ return this._mode.clampToReachablePosition(position);
4625
+ };
4626
+ /**
4627
+ * Check whether the given panel is inside of the Camera's range
4628
+ * @ko 해당 {@link Panel}이 Camera가 도달 가능한 범위 내에 있는지를 반환합니다
4629
+ * @param panel An instance of {@link Panel} to check<ko>확인할 {@link Panel}의 인스턴스</ko>
4630
+ * @return {boolean} Whether the panel's inside Camera's range<ko>도달 가능한 범위 내에 해당 패널이 존재하는지 여부</ko>
4631
+ */
4542
4632
 
4543
- if (!this._circularEnabled) {
4544
- return visibleInCurrentRange;
4545
- } // Check looped visible area for circular case
4546
4633
 
4634
+ __proto.canReach = function (panel) {
4635
+ return this._mode.canReach(panel);
4636
+ };
4637
+ /**
4638
+ * Check whether the given panel element is visible at the current position
4639
+ * @ko 현재 좌표에서 해당 패널 엘리먼트를 볼 수 있는지 여부를 반환합니다
4640
+ * @param panel An instance of {@link Panel} to check<ko>확인할 {@link Panel}의 인스턴스</ko>
4641
+ * @return Whether the panel element is visible at the current position<ko>현재 위치에서 해당 패널 엘리먼트가 보이는지 여부</ko>
4642
+ */
4547
4643
 
4548
- if (visibleRange.min < range.min) {
4549
- return visibleInCurrentRange || panel.isVisibleOnRange(visibleRange.min + rangeDiff, visibleRange.max + rangeDiff);
4550
- } else if (visibleRange.max > range.max) {
4551
- return visibleInCurrentRange || panel.isVisibleOnRange(visibleRange.min - rangeDiff, visibleRange.max - rangeDiff);
4552
- }
4553
4644
 
4554
- return visibleInCurrentRange;
4645
+ __proto.canSee = function (panel) {
4646
+ return this._mode.canSee(panel);
4555
4647
  };
4556
4648
  /**
4557
4649
  * Update {@link Camera#range range} of Camera
4558
4650
  * @ko Camera의 {@link Camera#range range}를 업데이트합니다
4651
+ * @method
4652
+ * @abstract
4653
+ * @memberof Camera
4654
+ * @instance
4655
+ * @name updateRange
4559
4656
  * @chainable
4560
4657
  * @throws {FlickingError}
4561
4658
  * {@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} When {@link Camera#init init} is not called before
@@ -4569,287 +4666,269 @@ version: 4.4.2
4569
4666
  var renderer = flicking.renderer;
4570
4667
  var panels = renderer.panels;
4571
4668
 
4572
- if (panels.length <= 0) {
4573
- this._resetInternalValues();
4574
-
4575
- return this;
4576
- }
4669
+ this._updateMode();
4577
4670
 
4578
- var firstPanel = panels[0];
4579
- var lastPanel = panels[panels.length - 1];
4580
- var firstPanelPrev = firstPanel.range.min - firstPanel.margin.prev;
4581
- var lastPanelNext = lastPanel.range.max + lastPanel.margin.next;
4582
- var visibleSize = this.size;
4583
- var panelSizeSum = lastPanelNext - firstPanelPrev;
4584
- var canSetCircularMode = panels.every(function (panel) {
4585
- return panelSizeSum - panel.size >= visibleSize;
4586
- });
4587
- this._circularEnabled = canSetCircularMode;
4671
+ this._range = this._mode.getRange();
4588
4672
 
4589
- if (canSetCircularMode) {
4590
- this._range = {
4591
- min: firstPanelPrev,
4592
- max: lastPanelNext
4593
- };
4673
+ if (this._circularEnabled) {
4594
4674
  panels.forEach(function (panel) {
4595
4675
  return panel.updateCircularToggleDirection();
4596
4676
  });
4597
- } else {
4598
- this._range = {
4599
- min: firstPanel.position,
4600
- max: lastPanel.position
4601
- };
4602
4677
  }
4603
4678
 
4604
4679
  this.updateOffset();
4605
4680
  return this;
4606
4681
  };
4682
+ /**
4683
+ * Update Camera's {@link Camera#alignPosition alignPosition}
4684
+ * @ko Camera의 {@link Camera#alignPosition alignPosition}을 업데이트합니다
4685
+ * @chainable
4686
+ * @return {this}
4687
+ */
4607
4688
 
4608
- __proto.updateOffset = function () {
4609
- this._updateCircularOffset();
4610
4689
 
4611
- return _super.prototype.updateOffset.call(this);
4690
+ __proto.updateAlignPos = function () {
4691
+ var align = this._align;
4692
+ var alignVal = typeof align === "object" ? align.camera : align;
4693
+ this._alignPos = parseAlign$1(alignVal, this.size);
4694
+ return this;
4612
4695
  };
4696
+ /**
4697
+ * Update Camera's {@link Camera#anchorPoints anchorPoints}
4698
+ * @ko Camera의 {@link Camera#anchorPoints anchorPoints}를 업데이트합니다
4699
+ * @throws {FlickingError}
4700
+ * {@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} When {@link Camera#init init} is not called before
4701
+ * <ko>{@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} {@link Camera#init init}이 이전에 호출되지 않은 경우</ko>
4702
+ * @chainable
4703
+ * @return {this}
4704
+ */
4613
4705
 
4614
- __proto.lookAt = function (pos) {
4615
- var _this = this;
4616
-
4617
- var flicking = getFlickingAttached(this._flicking);
4618
- var prevPos = this._position;
4619
- if (pos === prevPos) return _super.prototype.lookAt.call(this, pos);
4620
- var panels = flicking.renderer.panels;
4621
- var toggled = panels.map(function (panel) {
4622
- return panel.toggle(prevPos, pos);
4623
- });
4624
- this._position = pos;
4625
-
4626
- _super.prototype.lookAt.call(this, pos);
4627
-
4628
- if (toggled.some(function (isToggled) {
4629
- return isToggled;
4630
- })) {
4631
- void flicking.renderer.render().then(function () {
4632
- _this.updateOffset();
4633
- });
4634
- }
4635
- };
4636
4706
 
4637
- __proto.applyTransform = function () {
4638
- var el = this._el;
4639
- var flicking = getFlickingAttached(this._flicking);
4640
- var actualPosition = this._position - this._alignPos - this._offset + this._circularOffset;
4641
- el.style[this._transform] = flicking.horizontal ? "translate(" + -actualPosition + "px)" : "translate(0, " + -actualPosition + "px)";
4707
+ __proto.updateAnchors = function () {
4708
+ this._anchors = this._mode.getAnchors();
4642
4709
  return this;
4643
4710
  };
4711
+ /**
4712
+ * Update Viewport's height to active panel's height
4713
+ * @ko 현재 선택된 패널의 높이와 동일하도록 뷰포트의 높이를 업데이트합니다
4714
+ * @throws {FlickingError}
4715
+ * {@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} When {@link Camera#init init} is not called before
4716
+ * <ko>{@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} {@link Camera#init init}이 이전에 호출되지 않은 경우</ko>
4717
+ * @chainable
4718
+ * @return {this}
4719
+ */
4644
4720
 
4645
- __proto._resetInternalValues = function () {
4646
- _super.prototype._resetInternalValues.call(this);
4647
-
4648
- this._circularOffset = 0;
4649
- this._circularEnabled = false;
4650
- };
4651
4721
 
4652
- __proto._calcPanelAreaSum = function (panels) {
4653
- return panels.reduce(function (sum, panel) {
4654
- return sum + panel.sizeIncludingMargin;
4655
- }, 0);
4722
+ __proto.updateAdaptiveHeight = function () {
4723
+ var flicking = getFlickingAttached(this._flicking);
4724
+ var activePanel = flicking.control.activePanel;
4725
+ if (!flicking.horizontal || !flicking.adaptive || !activePanel) return;
4726
+ flicking.viewport.setSize({
4727
+ height: activePanel.height
4728
+ });
4656
4729
  };
4730
+ /**
4731
+ * Update current offset of the camera
4732
+ * @ko 현재 카메라의 오프셋을 업데이트합니다
4733
+ * @chainable
4734
+ * @return {this}
4735
+ */
4657
4736
 
4658
- __proto._updateCircularOffset = function () {
4659
- if (!this._circularEnabled) {
4660
- this._circularOffset = 0;
4661
- return;
4662
- }
4663
4737
 
4738
+ __proto.updateOffset = function () {
4664
4739
  var flicking = getFlickingAttached(this._flicking);
4665
- var toggled = flicking.panels.filter(function (panel) {
4666
- return panel.toggled;
4667
- });
4668
- var toggledPrev = toggled.filter(function (panel) {
4669
- return panel.toggleDirection === DIRECTION.PREV;
4670
- });
4671
- var toggledNext = toggled.filter(function (panel) {
4672
- return panel.toggleDirection === DIRECTION.NEXT;
4740
+ var position = this._position;
4741
+ var unRenderedPanels = flicking.panels.filter(function (panel) {
4742
+ return !panel.rendered;
4673
4743
  });
4674
- this._circularOffset = this._calcPanelAreaSum(toggledPrev) - this._calcPanelAreaSum(toggledNext);
4744
+ this._offset = unRenderedPanels.filter(function (panel) {
4745
+ return panel.position + panel.offset < position;
4746
+ }).reduce(function (offset, panel) {
4747
+ return offset + panel.sizeIncludingMargin;
4748
+ }, 0);
4749
+ this._circularOffset = this._mode.getCircularOffset();
4750
+ this.applyTransform();
4751
+ return this;
4675
4752
  };
4753
+ /**
4754
+ * Reset the history of {@link Flicking#event:needPanel needPanel} events so it can be triggered again
4755
+ * @ko 발생한 {@link Flicking#event:needPanel needPanel} 이벤트들을 초기화하여 다시 발생할 수 있도록 합니다
4756
+ * @chainable
4757
+ * @return {this}
4758
+ */
4676
4759
 
4677
- return CircularCamera;
4678
- }(Camera$1);
4679
-
4680
- /**
4681
- * A {@link Camera} that set range not to go out of the first/last panel, so it won't show empty spaces before/after the first/last panel
4682
- * @ko 첫번째와 마지막 패널 밖으로 넘어가지 못하도록 범위를 설정하여, 첫번째/마지막 패널 전/후의 빈 공간을 보이지 않도록 하는 종류의 {@link Camera}
4683
- */
4684
-
4685
- var BoundCamera =
4686
- /*#__PURE__*/
4687
- function (_super) {
4688
- __extends(BoundCamera, _super);
4689
4760
 
4690
- function BoundCamera() {
4691
- return _super !== null && _super.apply(this, arguments) || this;
4692
- }
4761
+ __proto.resetNeedPanelHistory = function () {
4762
+ this._needPanelTriggered = {
4763
+ prev: false,
4764
+ next: false
4765
+ };
4766
+ return this;
4767
+ };
4693
4768
  /**
4694
- * Update {@link Camera#range range} of Camera
4695
- * @ko Camera의 {@link Camera#range range}를 업데이트합니다
4769
+ * Apply "transform" style with the current position to camera element
4770
+ * @ko 현재 위치를 기준으로한 transform 스타일을 카메라 엘리먼트에 적용합니다.
4696
4771
  * @chainable
4697
- * @throws {FlickingError}
4698
- * {@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} When {@link Camera#init init} is not called before
4699
- * <ko>{@link ERROR_CODE NOT_ATTACHED_TO_FLICKING} {@link Camera#init init}이 이전에 호출되지 않은 경우</ko>
4700
4772
  * @return {this}
4701
4773
  */
4702
4774
 
4703
4775
 
4704
- var __proto = BoundCamera.prototype;
4705
-
4706
- __proto.updateRange = function () {
4776
+ __proto.applyTransform = function () {
4777
+ var el = this._el;
4707
4778
  var flicking = getFlickingAttached(this._flicking);
4708
- var renderer = flicking.renderer;
4709
- var alignPos = this._alignPos;
4710
- var firstPanel = renderer.getPanel(0);
4711
- var lastPanel = renderer.getPanel(renderer.panelCount - 1);
4712
-
4713
- if (!firstPanel || !lastPanel) {
4714
- this._range = {
4715
- min: 0,
4716
- max: 0
4717
- };
4718
- return this;
4719
- }
4720
-
4721
- var viewportSize = this.size;
4722
- var firstPanelPrev = firstPanel.range.min;
4723
- var lastPanelNext = lastPanel.range.max;
4724
- var panelAreaSize = lastPanelNext - firstPanelPrev;
4725
- var isBiggerThanViewport = viewportSize < panelAreaSize;
4726
- var firstPos = firstPanelPrev + alignPos;
4727
- var lastPos = lastPanelNext - viewportSize + alignPos;
4728
-
4729
- if (isBiggerThanViewport) {
4730
- this._range = {
4731
- min: firstPos,
4732
- max: lastPos
4733
- };
4734
- } else {
4735
- var align = this._align;
4736
- var alignVal = typeof align === "object" ? align.camera : align;
4737
- var pos = firstPos + parseAlign$1(alignVal, lastPos - firstPos);
4738
- this._range = {
4739
- min: pos,
4740
- max: pos
4741
- };
4742
- }
4743
-
4779
+ var actualPosition = this._position - this._alignPos - this._offset + this._circularOffset;
4780
+ el.style[this._transform] = flicking.horizontal ? "translate(" + -actualPosition + "px)" : "translate(0, " + -actualPosition + "px)";
4744
4781
  return this;
4745
4782
  };
4746
4783
 
4747
- __proto.updateAnchors = function () {
4784
+ __proto._resetInternalValues = function () {
4785
+ this._position = 0;
4786
+ this._alignPos = 0;
4787
+ this._offset = 0;
4788
+ this._circularOffset = 0;
4789
+ this._circularEnabled = false;
4790
+ this._range = {
4791
+ min: 0,
4792
+ max: 0
4793
+ };
4794
+ this._visiblePanels = [];
4795
+ this._anchors = [];
4796
+ this._needPanelTriggered = {
4797
+ prev: false,
4798
+ next: false
4799
+ };
4800
+ };
4801
+
4802
+ __proto._refreshVisiblePanels = function () {
4748
4803
  var _this = this;
4749
4804
 
4750
4805
  var flicking = getFlickingAttached(this._flicking);
4751
4806
  var panels = flicking.renderer.panels;
4752
-
4753
- if (panels.length <= 0) {
4754
- this._anchors = [];
4755
- return this;
4756
- }
4757
-
4758
- var range = this._range;
4759
- var reachablePanels = panels.filter(function (panel) {
4760
- return _this.canReach(panel);
4807
+ var newVisiblePanels = panels.filter(function (panel) {
4808
+ return _this.canSee(panel);
4809
+ });
4810
+ var prevVisiblePanels = this._visiblePanels;
4811
+ this._visiblePanels = newVisiblePanels;
4812
+ var added = newVisiblePanels.filter(function (panel) {
4813
+ return !includes(prevVisiblePanels, panel);
4814
+ });
4815
+ var removed = prevVisiblePanels.filter(function (panel) {
4816
+ return !includes(newVisiblePanels, panel);
4761
4817
  });
4762
4818
 
4763
- if (reachablePanels.length > 0) {
4764
- var shouldPrependBoundAnchor = reachablePanels[0].position !== range.min;
4765
- var shouldAppendBoundAnchor = reachablePanels[reachablePanels.length - 1].position !== range.max;
4766
- var indexOffset_1 = shouldPrependBoundAnchor ? 1 : 0;
4767
- var newAnchors = reachablePanels.map(function (panel, idx) {
4768
- return new AnchorPoint({
4769
- index: idx + indexOffset_1,
4770
- position: panel.position,
4771
- panel: panel
4772
- });
4819
+ if (added.length > 0 || removed.length > 0) {
4820
+ void flicking.renderer.render().then(function () {
4821
+ flicking.trigger(new Component.ComponentEvent(EVENTS.VISIBLE_CHANGE, {
4822
+ added: added,
4823
+ removed: removed,
4824
+ visiblePanels: newVisiblePanels
4825
+ }));
4773
4826
  });
4827
+ }
4828
+ };
4774
4829
 
4775
- if (shouldPrependBoundAnchor) {
4776
- newAnchors.splice(0, 0, new AnchorPoint({
4777
- index: 0,
4778
- position: range.min,
4779
- panel: panels[reachablePanels[0].index - 1]
4830
+ __proto._checkNeedPanel = function () {
4831
+ var needPanelTriggered = this._needPanelTriggered;
4832
+ if (needPanelTriggered.prev && needPanelTriggered.next) return;
4833
+ var flicking = getFlickingAttached(this._flicking);
4834
+ var panels = flicking.renderer.panels;
4835
+
4836
+ if (panels.length <= 0) {
4837
+ if (!needPanelTriggered.prev) {
4838
+ flicking.trigger(new Component.ComponentEvent(EVENTS.NEED_PANEL, {
4839
+ direction: DIRECTION.PREV
4780
4840
  }));
4841
+ needPanelTriggered.prev = true;
4781
4842
  }
4782
4843
 
4783
- if (shouldAppendBoundAnchor) {
4784
- newAnchors.push(new AnchorPoint({
4785
- index: newAnchors.length,
4786
- position: range.max,
4787
- panel: panels[reachablePanels[reachablePanels.length - 1].index + 1]
4844
+ if (!needPanelTriggered.next) {
4845
+ flicking.trigger(new Component.ComponentEvent(EVENTS.NEED_PANEL, {
4846
+ direction: DIRECTION.NEXT
4788
4847
  }));
4848
+ needPanelTriggered.next = true;
4789
4849
  }
4790
4850
 
4791
- this._anchors = newAnchors;
4792
- } else if (range.min !== range.max) {
4793
- // There're more than 2 panels
4794
- var nearestPanelAtMin = this._findNearestPanel(range.min, panels);
4851
+ return;
4852
+ }
4795
4853
 
4796
- var panelAtMin = nearestPanelAtMin.index === panels.length - 1 ? nearestPanelAtMin.prev() : nearestPanelAtMin;
4797
- var panelAtMax = panelAtMin.next();
4798
- this._anchors = [new AnchorPoint({
4799
- index: 0,
4800
- position: range.min,
4801
- panel: panelAtMin
4802
- }), new AnchorPoint({
4803
- index: 1,
4804
- position: range.max,
4805
- panel: panelAtMax
4806
- })];
4807
- } else {
4808
- this._anchors = [new AnchorPoint({
4809
- index: 0,
4810
- position: range.min,
4811
- panel: this._findNearestPanel(range.min, panels)
4812
- })];
4854
+ var cameraPosition = this._position;
4855
+ var cameraSize = this.size;
4856
+ var cameraRange = this._range;
4857
+ var needPanelThreshold = flicking.needPanelThreshold;
4858
+ var cameraPrev = cameraPosition - this._alignPos;
4859
+ var cameraNext = cameraPrev + cameraSize;
4860
+ var firstPanel = panels[0];
4861
+ var lastPanel = panels[panels.length - 1];
4862
+
4863
+ if (!needPanelTriggered.prev) {
4864
+ var firstPanelPrev = firstPanel.range.min;
4865
+
4866
+ if (cameraPrev <= firstPanelPrev + needPanelThreshold || cameraPosition <= cameraRange.min + needPanelThreshold) {
4867
+ flicking.trigger(new Component.ComponentEvent(EVENTS.NEED_PANEL, {
4868
+ direction: DIRECTION.PREV
4869
+ }));
4870
+ needPanelTriggered.prev = true;
4871
+ }
4813
4872
  }
4814
4873
 
4815
- return this;
4874
+ if (!needPanelTriggered.next) {
4875
+ var lastPanelNext = lastPanel.range.max;
4876
+
4877
+ if (cameraNext >= lastPanelNext - needPanelThreshold || cameraPosition >= cameraRange.max - needPanelThreshold) {
4878
+ flicking.trigger(new Component.ComponentEvent(EVENTS.NEED_PANEL, {
4879
+ direction: DIRECTION.NEXT
4880
+ }));
4881
+ needPanelTriggered.next = true;
4882
+ }
4883
+ }
4816
4884
  };
4817
4885
 
4818
- __proto.findAnchorIncludePosition = function (position) {
4886
+ __proto._checkReachEnd = function (prevPos, newPos) {
4887
+ var flicking = getFlickingAttached(this._flicking);
4819
4888
  var range = this._range;
4820
- var anchors = this._anchors;
4821
- if (anchors.length <= 0) return null;
4822
-
4823
- if (position <= range.min) {
4824
- return anchors[0];
4825
- } else if (position >= range.max) {
4826
- return anchors[anchors.length - 1];
4827
- } else {
4828
- return _super.prototype.findAnchorIncludePosition.call(this, position);
4829
- }
4889
+ var wasBetweenRange = prevPos > range.min && prevPos < range.max;
4890
+ var isBetweenRange = newPos > range.min && newPos < range.max;
4891
+ if (!wasBetweenRange || isBetweenRange) return;
4892
+ var direction = newPos <= range.min ? DIRECTION.PREV : DIRECTION.NEXT;
4893
+ flicking.trigger(new Component.ComponentEvent(EVENTS.REACH_EDGE, {
4894
+ direction: direction
4895
+ }));
4830
4896
  };
4831
4897
 
4832
- __proto._findNearestPanel = function (pos, panels) {
4833
- var prevDist = Infinity;
4898
+ __proto._updateMode = function () {
4899
+ var flicking = getFlickingAttached(this._flicking);
4834
4900
 
4835
- for (var panelIdx = 0; panelIdx < panels.length; panelIdx++) {
4836
- var panel = panels[panelIdx];
4837
- var dist = Math.abs(panel.position - pos);
4901
+ if (flicking.circular) {
4902
+ var circularMode = new CircularCameraMode(flicking);
4903
+ var canSetCircularMode = circularMode.checkAvailability();
4838
4904
 
4839
- if (dist > prevDist) {
4840
- // Return previous anchor
4841
- return panels[panelIdx - 1];
4905
+ if (canSetCircularMode) {
4906
+ this._mode = circularMode;
4907
+ } else {
4908
+ var fallbackMode = flicking.circularFallback;
4909
+ this._mode = fallbackMode === CIRCULAR_FALLBACK.BOUND ? new BoundCameraMode(flicking) : new LinearCameraMode(flicking);
4842
4910
  }
4843
4911
 
4844
- prevDist = dist;
4845
- } // Return last anchor
4846
-
4912
+ this._circularEnabled = canSetCircularMode;
4913
+ } else {
4914
+ this._mode = flicking.bound ? new BoundCameraMode(flicking) : new LinearCameraMode(flicking);
4915
+ }
4916
+ };
4847
4917
 
4848
- return panels[panels.length - 1];
4918
+ __proto._togglePanels = function (prevPos, pos) {
4919
+ if (pos === prevPos) return false;
4920
+ var flicking = getFlickingAttached(this._flicking);
4921
+ var panels = flicking.renderer.panels;
4922
+ var toggled = panels.map(function (panel) {
4923
+ return panel.toggle(prevPos, pos);
4924
+ });
4925
+ return toggled.some(function (isToggled) {
4926
+ return isToggled;
4927
+ });
4849
4928
  };
4850
4929
 
4851
- return BoundCamera;
4852
- }(Camera$1);
4930
+ return Camera;
4931
+ }();
4853
4932
 
4854
4933
  /*
4855
4934
  * Copyright (c) 2015 NAVER Corp.
@@ -4859,9 +4938,9 @@ version: 4.4.2
4859
4938
  var Camera = {
4860
4939
  __proto__: null,
4861
4940
  Camera: Camera$1,
4862
- LinearCamera: LinearCamera,
4863
- CircularCamera: CircularCamera,
4864
- BoundCamera: BoundCamera
4941
+ LinearCameraMode: LinearCameraMode,
4942
+ CircularCameraMode: CircularCameraMode,
4943
+ BoundCameraMode: BoundCameraMode
4865
4944
  };
4866
4945
 
4867
4946
  /**
@@ -5061,7 +5140,7 @@ version: 4.4.2
5061
5140
  flicking: flicking
5062
5141
  });
5063
5142
  });
5064
- panels.splice.apply(panels, __spreadArray([insertingIdx, 0], __read(panelsInserted)));
5143
+ panels.splice.apply(panels, __spread([insertingIdx, 0], panelsInserted));
5065
5144
 
5066
5145
  if (item.hasDOMInElements) {
5067
5146
  // Insert the actual elements as camera element's children
@@ -5084,7 +5163,7 @@ version: 4.4.2
5084
5163
  panel.increaseIndex(panelsInserted.length);
5085
5164
  panel.updatePosition();
5086
5165
  });
5087
- return __spreadArray(__spreadArray([], __read(addedPanels), false), __read(panelsInserted));
5166
+ return __spread(addedPanels, panelsInserted);
5088
5167
  }, []);
5089
5168
  if (allPanelsInserted.length <= 0) return []; // Update camera & control
5090
5169
 
@@ -5163,7 +5242,7 @@ version: 4.4.2
5163
5242
  control.resetActive();
5164
5243
  }
5165
5244
 
5166
- return __spreadArray(__spreadArray([], __read(removed), false), __read(panelsRemoved));
5245
+ return __spread(removed, panelsRemoved);
5167
5246
  }, []); // Update camera & control
5168
5247
 
5169
5248
  this._updateCameraAndControl();
@@ -6162,7 +6241,7 @@ version: 4.4.2
6162
6241
  var notToggled = renderedPanels.filter(function (panel) {
6163
6242
  return !panel.toggled;
6164
6243
  });
6165
- return __spreadArray(__spreadArray(__spreadArray([], __read(toggledPrev), false), __read(notToggled), false), __read(toggledNext)).map(function (panel) {
6244
+ return __spread(toggledPrev, notToggled, toggledNext).map(function (panel) {
6166
6245
  return panel.index;
6167
6246
  });
6168
6247
  };
@@ -6372,7 +6451,7 @@ version: 4.4.2
6372
6451
  __proto.getRenderingIndexesByOrder = function (flicking) {
6373
6452
  var virtualManager = flicking.virtual;
6374
6453
 
6375
- var visiblePanels = __spreadArray([], __read(flicking.visiblePanels)).filter(function (panel) {
6454
+ var visiblePanels = __spread(flicking.visiblePanels).filter(function (panel) {
6376
6455
  return panel.rendered;
6377
6456
  }).sort(function (panel1, panel2) {
6378
6457
  return panel1.position + panel1.offset - (panel2.position + panel2.offset);
@@ -6393,7 +6472,7 @@ version: 4.4.2
6393
6472
  }).map(function (el) {
6394
6473
  return el.idx;
6395
6474
  });
6396
- return __spreadArray(__spreadArray([], __read(visibleIndexes), false), __read(invisibleIndexes));
6475
+ return __spread(visibleIndexes, invisibleIndexes);
6397
6476
  };
6398
6477
 
6399
6478
  __proto.getRenderingElementsByOrder = function (flicking) {
@@ -6516,58 +6595,60 @@ version: 4.4.2
6516
6595
  horizontal = _e === void 0 ? true : _e,
6517
6596
  _f = _b.circular,
6518
6597
  circular = _f === void 0 ? false : _f,
6519
- _g = _b.bound,
6520
- bound = _g === void 0 ? false : _g,
6521
- _h = _b.adaptive,
6522
- adaptive = _h === void 0 ? false : _h,
6523
- _j = _b.panelsPerView,
6524
- panelsPerView = _j === void 0 ? -1 : _j,
6525
- _k = _b.noPanelStyleOverride,
6526
- noPanelStyleOverride = _k === void 0 ? false : _k,
6527
- _l = _b.resizeOnContentsReady,
6528
- resizeOnContentsReady = _l === void 0 ? false : _l,
6529
- _m = _b.needPanelThreshold,
6530
- needPanelThreshold = _m === void 0 ? 0 : _m,
6531
- _o = _b.preventEventsBeforeInit,
6532
- preventEventsBeforeInit = _o === void 0 ? true : _o,
6533
- _p = _b.deceleration,
6534
- deceleration = _p === void 0 ? 0.0075 : _p,
6535
- _q = _b.duration,
6536
- duration = _q === void 0 ? 500 : _q,
6537
- _r = _b.easing,
6538
- easing = _r === void 0 ? function (x) {
6598
+ _g = _b.circularFallback,
6599
+ circularFallback = _g === void 0 ? CIRCULAR_FALLBACK.LINEAR : _g,
6600
+ _h = _b.bound,
6601
+ bound = _h === void 0 ? false : _h,
6602
+ _j = _b.adaptive,
6603
+ adaptive = _j === void 0 ? false : _j,
6604
+ _k = _b.panelsPerView,
6605
+ panelsPerView = _k === void 0 ? -1 : _k,
6606
+ _l = _b.noPanelStyleOverride,
6607
+ noPanelStyleOverride = _l === void 0 ? false : _l,
6608
+ _m = _b.resizeOnContentsReady,
6609
+ resizeOnContentsReady = _m === void 0 ? false : _m,
6610
+ _o = _b.needPanelThreshold,
6611
+ needPanelThreshold = _o === void 0 ? 0 : _o,
6612
+ _p = _b.preventEventsBeforeInit,
6613
+ preventEventsBeforeInit = _p === void 0 ? true : _p,
6614
+ _q = _b.deceleration,
6615
+ deceleration = _q === void 0 ? 0.0075 : _q,
6616
+ _r = _b.duration,
6617
+ duration = _r === void 0 ? 500 : _r,
6618
+ _s = _b.easing,
6619
+ easing = _s === void 0 ? function (x) {
6539
6620
  return 1 - Math.pow(1 - x, 3);
6540
- } : _r,
6541
- _s = _b.inputType,
6542
- inputType = _s === void 0 ? ["mouse", "touch"] : _s,
6543
- _t = _b.moveType,
6544
- moveType = _t === void 0 ? "snap" : _t,
6545
- _u = _b.threshold,
6546
- threshold = _u === void 0 ? 40 : _u,
6547
- _v = _b.interruptable,
6548
- interruptable = _v === void 0 ? true : _v,
6549
- _w = _b.bounce,
6550
- bounce = _w === void 0 ? "20%" : _w,
6551
- _x = _b.iOSEdgeSwipeThreshold,
6552
- iOSEdgeSwipeThreshold = _x === void 0 ? 30 : _x,
6553
- _y = _b.preventClickOnDrag,
6554
- preventClickOnDrag = _y === void 0 ? true : _y,
6555
- _z = _b.disableOnInit,
6556
- disableOnInit = _z === void 0 ? false : _z,
6557
- _0 = _b.renderOnlyVisible,
6558
- renderOnlyVisible = _0 === void 0 ? false : _0,
6559
- _1 = _b.virtual,
6560
- virtual = _1 === void 0 ? null : _1,
6561
- _2 = _b.autoInit,
6562
- autoInit = _2 === void 0 ? true : _2,
6563
- _3 = _b.autoResize,
6564
- autoResize = _3 === void 0 ? true : _3,
6565
- _4 = _b.useResizeObserver,
6566
- useResizeObserver = _4 === void 0 ? true : _4,
6567
- _5 = _b.externalRenderer,
6568
- externalRenderer = _5 === void 0 ? null : _5,
6569
- _6 = _b.renderExternal,
6570
- renderExternal = _6 === void 0 ? null : _6;
6621
+ } : _s,
6622
+ _t = _b.inputType,
6623
+ inputType = _t === void 0 ? ["mouse", "touch"] : _t,
6624
+ _u = _b.moveType,
6625
+ moveType = _u === void 0 ? "snap" : _u,
6626
+ _v = _b.threshold,
6627
+ threshold = _v === void 0 ? 40 : _v,
6628
+ _w = _b.interruptable,
6629
+ interruptable = _w === void 0 ? true : _w,
6630
+ _x = _b.bounce,
6631
+ bounce = _x === void 0 ? "20%" : _x,
6632
+ _y = _b.iOSEdgeSwipeThreshold,
6633
+ iOSEdgeSwipeThreshold = _y === void 0 ? 30 : _y,
6634
+ _z = _b.preventClickOnDrag,
6635
+ preventClickOnDrag = _z === void 0 ? true : _z,
6636
+ _0 = _b.disableOnInit,
6637
+ disableOnInit = _0 === void 0 ? false : _0,
6638
+ _1 = _b.renderOnlyVisible,
6639
+ renderOnlyVisible = _1 === void 0 ? false : _1,
6640
+ _2 = _b.virtual,
6641
+ virtual = _2 === void 0 ? null : _2,
6642
+ _3 = _b.autoInit,
6643
+ autoInit = _3 === void 0 ? true : _3,
6644
+ _4 = _b.autoResize,
6645
+ autoResize = _4 === void 0 ? true : _4,
6646
+ _5 = _b.useResizeObserver,
6647
+ useResizeObserver = _5 === void 0 ? true : _5,
6648
+ _6 = _b.externalRenderer,
6649
+ externalRenderer = _6 === void 0 ? null : _6,
6650
+ _7 = _b.renderExternal,
6651
+ renderExternal = _7 === void 0 ? null : _7;
6571
6652
 
6572
6653
  var _this = _super.call(this) || this; // Internal states
6573
6654
 
@@ -6579,6 +6660,7 @@ version: 4.4.2
6579
6660
  _this._defaultIndex = defaultIndex;
6580
6661
  _this._horizontal = horizontal;
6581
6662
  _this._circular = circular;
6663
+ _this._circularFallback = circularFallback;
6582
6664
  _this._bound = bound;
6583
6665
  _this._adaptive = adaptive;
6584
6666
  _this._panelsPerView = panelsPerView;
@@ -6717,7 +6799,7 @@ version: 4.4.2
6717
6799
  * @readonly
6718
6800
  */
6719
6801
  get: function () {
6720
- return this._camera.controlParams.circular;
6802
+ return this._camera.circularEnabled;
6721
6803
  },
6722
6804
  enumerable: false,
6723
6805
  configurable: true
@@ -6951,6 +7033,24 @@ version: 4.4.2
6951
7033
  enumerable: false,
6952
7034
  configurable: true
6953
7035
  });
7036
+ Object.defineProperty(__proto, "circularFallback", {
7037
+ /**
7038
+ * Set panel control mode for the case when circular cannot be enabled.
7039
+ * "linear" will set the view's range from the top of the first panel to the top of the last panel.
7040
+ * "bound" will prevent the view from going out of the first/last panel, so it won't show empty spaces before/after the first/last panel.
7041
+ * @ko 순환 모드 사용 불가능시 사용할 패널 조작 범위 설정 방식을 변경합니다.
7042
+ * "linear" 사용시 시점이 첫번째 엘리먼트 위에서부터 마지막 엘리먼트 위까지 움직일 수 있도록 설정합니다.
7043
+ * "bound" 사용시 시점이 첫번째 엘리먼트와 마지막 엘리먼트의 끝과 끝 사이에서 움직일 수 있도록 설정합니다.
7044
+ * @see CIRCULAR_FALLBACK
7045
+ * @type {string}
7046
+ * @default "linear"
7047
+ */
7048
+ get: function () {
7049
+ return this._circularFallback;
7050
+ },
7051
+ enumerable: false,
7052
+ configurable: true
7053
+ });
6954
7054
  Object.defineProperty(__proto, "bound", {
6955
7055
  /**
6956
7056
  * Prevent the view(camera element) from going out of the first/last panel, so it won't show empty spaces before/after the first/last panel
@@ -7911,7 +8011,7 @@ version: 4.4.2
7911
8011
  });
7912
8012
  }
7913
8013
 
7914
- (_a = this._plugins).push.apply(_a, __spreadArray([], __read(plugins)));
8014
+ (_a = this._plugins).push.apply(_a, __spread(plugins));
7915
8015
 
7916
8016
  return this;
7917
8017
  };
@@ -8158,22 +8258,14 @@ version: 4.4.2
8158
8258
  };
8159
8259
 
8160
8260
  __proto._createCamera = function () {
8161
- var cameraOption = {
8162
- align: this._align
8163
- };
8164
-
8165
- if (this._circular) {
8166
- if (this._bound) {
8167
- // eslint-disable-next-line no-console
8168
- console.warn("\"circular\" and \"bound\" option cannot be used together, ignoring bound.");
8169
- }
8170
-
8171
- return new CircularCamera(cameraOption);
8172
- } else if (this._bound) {
8173
- return new BoundCamera(cameraOption);
8174
- } else {
8175
- return new LinearCamera(cameraOption);
8261
+ if (this._circular && this._bound) {
8262
+ // eslint-disable-next-line no-console
8263
+ console.warn("\"circular\" and \"bound\" option cannot be used together, ignoring bound.");
8176
8264
  }
8265
+
8266
+ return new Camera$1({
8267
+ align: this._align
8268
+ });
8177
8269
  };
8178
8270
 
8179
8271
  __proto._createRenderer = function () {
@@ -8237,7 +8329,7 @@ version: 4.4.2
8237
8329
  */
8238
8330
 
8239
8331
 
8240
- Flicking.VERSION = "4.4.2";
8332
+ Flicking.VERSION = "4.5.0";
8241
8333
  return Flicking;
8242
8334
  }(Component);
8243
8335
 
@@ -8293,7 +8385,7 @@ version: 4.4.2
8293
8385
  args[_i] = arguments[_i];
8294
8386
  }
8295
8387
 
8296
- return (_a = descriptor.value).call.apply(_a, __spreadArray([this[flickingName]], __read(args)));
8388
+ return (_a = descriptor.value).call.apply(_a, __spread([this[flickingName]], args));
8297
8389
  }
8298
8390
  });
8299
8391
  } else {
@@ -8317,7 +8409,7 @@ version: 4.4.2
8317
8409
  args[_i] = arguments[_i];
8318
8410
  }
8319
8411
 
8320
- return (_a = descriptor.set) === null || _a === void 0 ? void 0 : _a.call.apply(_a, __spreadArray([this[flickingName]], __read(args)));
8412
+ return (_a = descriptor.set) === null || _a === void 0 ? void 0 : _a.call.apply(_a, __spread([this[flickingName]], args));
8321
8413
  };
8322
8414
  }
8323
8415
 
@@ -8331,7 +8423,7 @@ version: 4.4.2
8331
8423
  var renderer = flicking.renderer;
8332
8424
  var panels = renderer.panels;
8333
8425
 
8334
- var prevList = __spreadArray([], __read(diffResult.prevList));
8426
+ var prevList = __spread(diffResult.prevList);
8335
8427
 
8336
8428
  if (diffResult.removed.length > 0) {
8337
8429
  var endIdx_1 = -1;
@@ -8411,13 +8503,13 @@ version: 4.4.2
8411
8503
  });
8412
8504
 
8413
8505
  var batchInsert = function (renderer, diffResult, addedElements, startIdx, endIdx) {
8414
- renderer.batchInsert.apply(renderer, __spreadArray([], __read(diffResult.added.slice(startIdx, endIdx).map(function (index, elIdx) {
8506
+ renderer.batchInsert.apply(renderer, __spread(diffResult.added.slice(startIdx, endIdx).map(function (index, elIdx) {
8415
8507
  return {
8416
8508
  index: index,
8417
8509
  elements: [addedElements[elIdx]],
8418
8510
  hasDOMInElements: false
8419
8511
  };
8420
- }))));
8512
+ })));
8421
8513
  };
8422
8514
 
8423
8515
  var batchRemove = function (renderer, startIdx, endIdx) {
@@ -8442,16 +8534,16 @@ version: 4.4.2
8442
8534
  map[prev] = current;
8443
8535
  return map;
8444
8536
  }, {});
8445
- return __spreadArray(__spreadArray([], __read(flicking.panels.filter(function (panel) {
8537
+ return __spread(flicking.panels.filter(function (panel) {
8446
8538
  return !removedPanels[panel.index];
8447
8539
  }) // Sort panels by position
8448
8540
  .sort(function (panel1, panel2) {
8449
8541
  return panel1.position + panel1.offset - (panel2.position + panel2.offset);
8450
8542
  }).map(function (panel) {
8451
8543
  return diffResult.list[maintainedMap[panel.index]];
8452
- })), false), __read(diffResult.added.map(function (idx) {
8544
+ }), diffResult.added.map(function (idx) {
8453
8545
  return diffResult.list[idx];
8454
- })));
8546
+ }));
8455
8547
  });
8456
8548
 
8457
8549
  var getDefaultCameraTransform = (function (align, horizontal, firstPanelSize) {