@egjs/flicking 4.3.1 → 4.4.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 (79) hide show
  1. package/README.md +1 -1
  2. package/declaration/Flicking.d.ts +20 -11
  3. package/declaration/camera/Camera.d.ts +3 -2
  4. package/declaration/camera/CircularCamera.d.ts +2 -1
  5. package/declaration/const/error.d.ts +3 -1
  6. package/declaration/const/external.d.ts +5 -0
  7. package/declaration/core/AutoResizer.d.ts +13 -0
  8. package/declaration/core/VirtualManager.d.ts +37 -0
  9. package/declaration/core/index.d.ts +2 -1
  10. package/declaration/core/panel/ExternalPanel.d.ts +9 -5
  11. package/declaration/core/panel/Panel.d.ts +13 -7
  12. package/declaration/core/panel/VirtualPanel.d.ts +19 -0
  13. package/declaration/core/panel/index.d.ts +4 -3
  14. package/declaration/core/panel/provider/ElementProvider.d.ts +7 -0
  15. package/declaration/core/panel/provider/ExternalElementProvider.d.ts +8 -0
  16. package/declaration/core/panel/provider/VanillaElementProvider.d.ts +10 -0
  17. package/declaration/core/panel/provider/VirtualElementProvider.d.ts +13 -0
  18. package/declaration/core/panel/provider/index.d.ts +6 -0
  19. package/declaration/index.d.ts +11 -1
  20. package/declaration/renderer/ExternalRenderer.d.ts +1 -0
  21. package/declaration/renderer/Renderer.d.ts +17 -12
  22. package/declaration/renderer/VanillaRenderer.d.ts +2 -7
  23. package/declaration/renderer/index.d.ts +1 -0
  24. package/declaration/renderer/strategy/NormalRenderingStrategy.d.ts +25 -0
  25. package/declaration/renderer/strategy/RenderingStrategy.d.ts +15 -0
  26. package/declaration/renderer/strategy/VirtualRenderingStrategy.d.ts +17 -0
  27. package/declaration/renderer/strategy/index.d.ts +5 -0
  28. package/declaration/utils.d.ts +7 -1
  29. package/dist/flicking.esm.js +4583 -3686
  30. package/dist/flicking.esm.js.map +1 -1
  31. package/dist/flicking.js +4596 -3674
  32. package/dist/flicking.js.map +1 -1
  33. package/dist/flicking.min.js +2 -2
  34. package/dist/flicking.min.js.map +1 -1
  35. package/dist/flicking.pkgd.js +10626 -9704
  36. package/dist/flicking.pkgd.js.map +1 -1
  37. package/dist/flicking.pkgd.min.js +2 -2
  38. package/dist/flicking.pkgd.min.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/Flicking.ts +130 -27
  41. package/src/camera/BoundCamera.ts +2 -2
  42. package/src/camera/Camera.ts +49 -26
  43. package/src/camera/CircularCamera.ts +23 -24
  44. package/src/camera/LinearCamera.ts +1 -1
  45. package/src/cfc/sync.ts +2 -2
  46. package/src/const/error.ts +6 -3
  47. package/src/const/external.ts +6 -0
  48. package/src/control/AxesController.ts +11 -6
  49. package/src/control/Control.ts +6 -6
  50. package/src/control/FreeControl.ts +2 -2
  51. package/src/control/SnapControl.ts +3 -3
  52. package/src/control/StrictControl.ts +2 -2
  53. package/src/core/AutoResizer.ts +81 -0
  54. package/src/core/VirtualManager.ts +188 -0
  55. package/src/core/index.ts +3 -1
  56. package/src/core/panel/ExternalPanel.ts +23 -15
  57. package/src/core/panel/Panel.ts +54 -34
  58. package/src/core/panel/VirtualPanel.ts +110 -0
  59. package/src/core/panel/index.ts +5 -4
  60. package/src/core/panel/provider/ElementProvider.ts +13 -0
  61. package/src/core/panel/provider/ExternalElementProvider.ts +15 -0
  62. package/src/core/panel/provider/VanillaElementProvider.ts +40 -0
  63. package/src/core/panel/provider/VirtualElementProvider.ts +45 -0
  64. package/src/core/panel/provider/index.ts +18 -0
  65. package/src/index.ts +12 -1
  66. package/src/index.umd.ts +2 -0
  67. package/src/renderer/ExternalRenderer.ts +36 -4
  68. package/src/renderer/Renderer.ts +106 -65
  69. package/src/renderer/VanillaRenderer.ts +28 -86
  70. package/src/renderer/index.ts +2 -0
  71. package/src/renderer/strategy/NormalRenderingStrategy.ts +109 -0
  72. package/src/renderer/strategy/RenderingStrategy.ts +21 -0
  73. package/src/renderer/strategy/VirtualRenderingStrategy.ts +110 -0
  74. package/src/renderer/strategy/index.ts +17 -0
  75. package/src/utils.ts +36 -2
  76. package/declaration/core/panel/ElementPanel.d.ts +0 -14
  77. package/declaration/exports.d.ts +0 -10
  78. package/src/core/panel/ElementPanel.ts +0 -52
  79. package/src/exports.ts +0 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@egjs/flicking",
3
- "version": "4.3.1",
3
+ "version": "4.4.0",
4
4
  "description": "Everyday 30 million people experience. It's reliable, flexible and extendable carousel.",
5
5
  "main": "dist/flicking.js",
6
6
  "module": "dist/flicking.esm.js",
package/src/Flicking.ts CHANGED
@@ -6,10 +6,13 @@ import Component, { ComponentEvent } from "@egjs/component";
6
6
 
7
7
  import FlickingError from "./core/FlickingError";
8
8
  import Viewport from "./core/Viewport";
9
+ import AutoResizer from "./core/AutoResizer";
9
10
  import { Panel } from "./core/panel";
11
+ import { VanillaElementProvider } from "./core/panel/provider";
12
+ import VirtualManager, { VirtualOptions } from "./core/VirtualManager";
10
13
  import { Control, SnapControl, SnapControlOptions, FreeControl, StrictControl, FreeControlOptions, StrictControlOptions } from "./control";
11
14
  import { BoundCamera, Camera, CircularCamera, LinearCamera } from "./camera";
12
- import { Renderer, VanillaRenderer, ExternalRenderer } from "./renderer";
15
+ import { Renderer, VanillaRenderer, ExternalRenderer, RendererOptions, NormalRenderingStrategy, VirtualRenderingStrategy } from "./renderer";
13
16
  import { EVENTS, ALIGN, MOVE_TYPE, DIRECTION } from "./const/external";
14
17
  import * as ERROR from "./const/error";
15
18
  import { findIndex, getElement, includes, parseElement } from "./utils";
@@ -72,12 +75,14 @@ export interface FlickingOptions {
72
75
  disableOnInit: boolean;
73
76
  // PERFORMANCE
74
77
  renderOnlyVisible: boolean;
78
+ virtual: VirtualOptions | null;
75
79
  // OTHERS
76
80
  autoInit: boolean;
77
81
  autoResize: boolean;
82
+ useResizeObserver: boolean;
78
83
  renderExternal: {
79
- renderer: typeof ExternalRenderer;
80
- rendererOptions: {[key: string]: any};
84
+ renderer: new (options: RendererOptions) => ExternalRenderer;
85
+ rendererOptions: RendererOptions;
81
86
  } | null;
82
87
  }
83
88
 
@@ -102,9 +107,11 @@ class Flicking extends Component<FlickingEvents> {
102
107
 
103
108
  // Core components
104
109
  private _viewport: Viewport;
110
+ private _autoResizer: AutoResizer;
105
111
  private _camera: Camera;
106
112
  private _control: Control;
107
113
  private _renderer: Renderer;
114
+ private _virtualManager: VirtualManager;
108
115
 
109
116
  // Options
110
117
  private _align: FlickingOptions["align"];
@@ -116,6 +123,7 @@ class Flicking extends Component<FlickingEvents> {
116
123
  private _panelsPerView: FlickingOptions["panelsPerView"];
117
124
  private _noPanelStyleOverride: FlickingOptions["noPanelStyleOverride"];
118
125
  private _resizeOnContentsReady: FlickingOptions["resizeOnContentsReady"];
126
+ private _virtual: FlickingOptions["virtual"];
119
127
 
120
128
  private _needPanelThreshold: FlickingOptions["needPanelThreshold"];
121
129
  private _preventEventsBeforeInit: FlickingOptions["preventEventsBeforeInit"];
@@ -135,8 +143,9 @@ class Flicking extends Component<FlickingEvents> {
135
143
 
136
144
  private _renderOnlyVisible: FlickingOptions["renderOnlyVisible"];
137
145
 
138
- private _autoResize: FlickingOptions["autoResize"];
139
146
  private _autoInit: FlickingOptions["autoInit"];
147
+ private _autoResize: FlickingOptions["autoResize"];
148
+ private _useResizeObserver: FlickingOptions["useResizeObserver"];
140
149
  private _renderExternal: FlickingOptions["renderExternal"];
141
150
 
142
151
  // Internal State
@@ -207,6 +216,16 @@ class Flicking extends Component<FlickingEvents> {
207
216
  * @readonly
208
217
  */
209
218
  public get circularEnabled() { return this._camera.controlParams.circular; }
219
+ /**
220
+ * Whether the `virtual` option is enabled.
221
+ * The {@link Flicking#virtual virtual} option can't be enabled when {@link Flicking#panelsPerView panelsPerView} is less or equal than zero.
222
+ * @ko {@link Flicking#virtual virtual} 옵션이 활성화되었는지 여부를 나타내는 멤버 변수.
223
+ * {@link Flicking#virtual virtual} 옵션은 {@link Flicking#panelsPerView panelsPerView} 옵션의 값이 0보다 같거나 작으면 비활성화됩니다.
224
+ * @type {boolean}
225
+ * @default false
226
+ * @readonly
227
+ */
228
+ public get virtualEnabled() { return this._panelsPerView > 0 && this._virtual != null; }
210
229
  /**
211
230
  * Index number of the {@link Flicking#currentPanel currentPanel}
212
231
  * @ko {@link Flicking#currentPanel currentPanel}의 인덱스 번호
@@ -515,12 +534,45 @@ class Flicking extends Component<FlickingEvents> {
515
534
  public get disableOnInit() { return this._disableOnInit; }
516
535
  // PERFORMANCE
517
536
  /**
518
- * Whether to render visible panels only. This can dramatically increase performance when there're many panels.
519
- * @ko 보이는 패널만 렌더링할지 여부를 설정합니다. 패널이 많을 경우에 퍼포먼스를 크게 향상시킬 수 있습니다.
537
+ * Whether to render visible panels only. This can dramatically increase performance when there're many panels
538
+ * @ko 보이는 패널만 렌더링할지 여부를 설정합니다. 패널이 많을 경우에 퍼포먼스를 크게 향상시킬 수 있습니다
520
539
  * @type {boolean}
521
540
  * @default false
522
541
  */
523
542
  public get renderOnlyVisible() { return this._renderOnlyVisible; }
543
+ /**
544
+ * By enabling this option, it will reduce memory consumption by restricting the number of DOM elements to `panelsPerView + 1`
545
+ * Must be used with `panelsPerview`.
546
+ * After Flicking's initialized, this property can be used to add/remove the panel count.
547
+ * @ko 이 옵션을 활성화할 경우 패널 엘리먼트의 개수를 `panelsPerView + 1` 개로 고정함으로써, 메모리 사용량을 줄일 수 있습니다.
548
+ * `panelsPerView` 옵션과 함께 사용되어야만 합니다.
549
+ * Flicking 초기화 이후에, 이 프로퍼티는 렌더링하는 패널의 개수를 추가/제거하기 위해 사용될 수 있습니다.
550
+ * @type {VirtualManager}
551
+ * @property {function} renderPanel A rendering function for the panel element's innerHTML<ko>패널 엘리먼트의 innerHTML을 렌더링하는 함수</ko>
552
+ * @property {number} initialPanelCount Initial panel count to render<ko>최초로 렌더링할 패널의 개수</ko>
553
+ * @property {boolean} [cache=false] Whether to cache rendered panel's innerHTML<ko>렌더링된 패널의 innerHTML 정보를 캐시할지 여부</ko>
554
+ * @property {string} [panelClass="flicking-panel"] The class name that will be applied to rendered panel elements<ko>렌더링되는 패널 엘리먼트에 적용될 클래스 이름</ko>
555
+ * @example
556
+ * ```ts
557
+ * import Flicking, { VirtualPanel } from "@egjs/flicking";
558
+ *
559
+ * const flicking = new Flicking("#some_el", {
560
+ * panelsPerView: 3,
561
+ * virtual: {
562
+ * renderPanel: (panel: VirtualPanel, index: number) => `Panel ${index}`,
563
+ * initialPanelCount: 100
564
+ * }
565
+ * });
566
+ *
567
+ * // Add 100 virtual panels (at the end)
568
+ * flicking.virtual.append(100);
569
+ *
570
+ * // Remove 100 virtual panels from 0 to 100
571
+ * flicking.virtual.remove(0, 100);
572
+ * ```
573
+ */
574
+ public get virtual() { return this._virtualManager; }
575
+
524
576
  // OTHERS
525
577
  /**
526
578
  * Call {@link Flicking#init init()} automatically when creating Flicking's instance
@@ -531,14 +583,19 @@ class Flicking extends Component<FlickingEvents> {
531
583
  */
532
584
  public get autoInit() { return this._autoInit; }
533
585
  /**
534
- * Attach Flicking's {@link Flicking#resize resize} method to window's resize event.
535
- * Flicking will automatically call {@link Flicking#resize resize} window size and orientation change.
536
- * @ko Flicking의 {@link Flicking#resize resize} 메소드를 window의 resize 이벤트 핸들러로 등록합니다.
537
- * 설정시 window 창 크기 및 orientation 변경에 의해 자동으로 {@link Flicking#resize resize}를 호출합니다.
586
+ * Whether to automatically call {@link Flicking#resize resize()} when the viewport element(.flicking-viewport)'s size is changed
587
+ * @ko 뷰포트 엘리먼트(.flicking-viewport)의 크기 변경시 {@link Flicking#resize resize()} 메소드를 자동으로 호출할지 여부를 설정합니다
538
588
  * @type {boolean}
539
589
  * @default true
540
590
  */
541
591
  public get autoResize() { return this._autoResize; }
592
+ /**
593
+ * Whether to listen {@link https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver ResizeObserver}'s event instead of Window's {@link https://developer.mozilla.org/ko/docs/Web/API/Window/resize_event resize} event when using the `autoResize` option
594
+ * @ko autoResize 옵션 사용시 {@link https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver ResizeObserver}의 이벤트를 Window객체의 {@link https://developer.mozilla.org/ko/docs/Web/API/Window/resize_event resize} 이벤트 대신 수신할지 여부를 설정합니다
595
+ * @type {boolean}
596
+ * @default true
597
+ */
598
+ public get useResizeObserver() { return this._useResizeObserver; }
542
599
  /**
543
600
  * This is an option for the frameworks(React, Vue, Angular, ...). Don't set it as it's automatically managed by Flicking.
544
601
  * @ko 프레임워크(React, Vue, Angular, ...)에서만 사용하는 옵션으로, 자동으로 설정되므로 따로 사용하실 필요 없습니다!
@@ -599,7 +656,23 @@ class Flicking extends Component<FlickingEvents> {
599
656
  // PERFORMANCE
600
657
  public set renderOnlyVisible(val: FlickingOptions["renderOnlyVisible"]) { this._renderOnlyVisible = val; }
601
658
  // OTHERS
602
- public set autoResize(val: FlickingOptions["autoResize"]) { this._autoResize = val; }
659
+ public set autoResize(val: FlickingOptions["autoResize"]) {
660
+ this._autoResize = val;
661
+
662
+ if (val) {
663
+ this._autoResizer.enable();
664
+ } else {
665
+ this._autoResizer.disable();
666
+ }
667
+ }
668
+
669
+ public set useResizeObserver(val: FlickingOptions["useResizeObserver"]) {
670
+ this._useResizeObserver = val;
671
+
672
+ if (this._autoResize) {
673
+ this._autoResizer.enable();
674
+ }
675
+ }
603
676
 
604
677
  /**
605
678
  * @param root A root HTMLElement to initialize Flicking on it. When it's a typeof `string`, it should be a css selector string
@@ -653,8 +726,10 @@ class Flicking extends Component<FlickingEvents> {
653
726
  preventClickOnDrag = true,
654
727
  disableOnInit = false,
655
728
  renderOnlyVisible = false,
729
+ virtual = null,
656
730
  autoInit = true,
657
731
  autoResize = true,
732
+ useResizeObserver = true,
658
733
  renderExternal = null
659
734
  }: Partial<FlickingOptions> = {}) {
660
735
  super();
@@ -673,6 +748,7 @@ class Flicking extends Component<FlickingEvents> {
673
748
  this._panelsPerView = panelsPerView;
674
749
  this._noPanelStyleOverride = noPanelStyleOverride;
675
750
  this._resizeOnContentsReady = resizeOnContentsReady;
751
+ this._virtual = virtual;
676
752
  this._needPanelThreshold = needPanelThreshold;
677
753
  this._preventEventsBeforeInit = preventEventsBeforeInit;
678
754
  this._deceleration = deceleration;
@@ -687,17 +763,18 @@ class Flicking extends Component<FlickingEvents> {
687
763
  this._preventClickOnDrag = preventClickOnDrag;
688
764
  this._disableOnInit = disableOnInit;
689
765
  this._renderOnlyVisible = renderOnlyVisible;
690
- this._autoResize = autoResize;
691
766
  this._autoInit = autoInit;
767
+ this._autoResize = autoResize;
768
+ this._useResizeObserver = useResizeObserver;
692
769
  this._renderExternal = renderExternal;
693
770
 
694
771
  // Create core components
695
772
  this._viewport = new Viewport(getElement(root));
773
+ this._autoResizer = new AutoResizer(this);
696
774
  this._renderer = this._createRenderer();
697
775
  this._camera = this._createCamera();
698
776
  this._control = this._createControl();
699
-
700
- this.resize = this.resize.bind(this);
777
+ this._virtualManager = new VirtualManager(this, virtual);
701
778
 
702
779
  if (this._autoInit) {
703
780
  void this.init();
@@ -718,10 +795,12 @@ class Flicking extends Component<FlickingEvents> {
718
795
  const camera = this._camera;
719
796
  const renderer = this._renderer;
720
797
  const control = this._control;
798
+ const virtualManager = this._virtualManager;
721
799
  const originalTrigger = this.trigger;
722
800
  const preventEventsBeforeInit = this._preventEventsBeforeInit;
723
801
 
724
802
  camera.init(this);
803
+ virtualManager.init();
725
804
  renderer.init(this);
726
805
  control.init(this);
727
806
 
@@ -735,7 +814,7 @@ class Flicking extends Component<FlickingEvents> {
735
814
  await this._moveToInitialPanel();
736
815
 
737
816
  if (this._autoResize) {
738
- window.addEventListener("resize", this.resize);
817
+ this._autoResizer.enable();
739
818
  }
740
819
  if (this._preventClickOnDrag) {
741
820
  control.controller.addPreventClickHandler();
@@ -764,8 +843,8 @@ class Flicking extends Component<FlickingEvents> {
764
843
  */
765
844
  public destroy(): void {
766
845
  this.off();
767
- window.removeEventListener("resize", this.resize);
768
846
 
847
+ this._autoResizer.disable();
769
848
  this._control.destroy();
770
849
  this._camera.destroy();
771
850
  this._renderer.destroy();
@@ -951,7 +1030,7 @@ class Flicking extends Component<FlickingEvents> {
951
1030
  * @param {boolean} [options.includePanelHTML=false] Include panel's `outerHTML` to the returning status<ko>패널의 `outerHTML`을 반환값에 포함시킵니다</ko>
952
1031
  * @param {boolean} [options.visiblePanelsOnly=false] Include only {@link Flicking#visiblePanel visiblePanel}'s HTML. This option is available only when the `includePanelHTML` is true
953
1032
  * <ko>현재 보이는 패널({@link Flicking#visiblePanel visiblePanel})의 HTML만 반환합니다. `includePanelHTML`이 `true`일 경우에만 동작합니다.</ko>
954
- * @return {Partial<Status>} An object with current status value information<ko>현재 상태값 정보를 가진 객체.</ko>
1033
+ * @return {Status} An object with current status value information<ko>현재 상태값 정보를 가진 객체.</ko>
955
1034
  */
956
1035
  public getStatus({
957
1036
  index = true,
@@ -1026,8 +1105,8 @@ class Flicking extends Component<FlickingEvents> {
1026
1105
 
1027
1106
  // Can't add/remove panels on external rendering
1028
1107
  if (panels[0]?.html && !this._renderExternal) {
1029
- renderer.batchRemove({ index: 0, deleteCount: this.panels.length });
1030
- renderer.batchInsert({ index: 0, elements: parseElement(panels.map(panel => panel.html!)) });
1108
+ renderer.batchRemove({ index: 0, deleteCount: this.panels.length, hasDOMInElements: true });
1109
+ renderer.batchInsert({ index: 0, elements: parseElement(panels.map(panel => panel.html!)), hasDOMInElements: true });
1031
1110
  }
1032
1111
 
1033
1112
  if (index) {
@@ -1219,7 +1298,7 @@ class Flicking extends Component<FlickingEvents> {
1219
1298
  throw new FlickingError(ERROR.MESSAGE.NOT_ALLOWED_IN_FRAMEWORK, ERROR.CODE.NOT_ALLOWED_IN_FRAMEWORK);
1220
1299
  }
1221
1300
 
1222
- return this._renderer.batchInsert({ index, elements: parseElement(element) });
1301
+ return this._renderer.batchInsert({ index, elements: parseElement(element), hasDOMInElements: true });
1223
1302
  }
1224
1303
 
1225
1304
  /**
@@ -1236,7 +1315,7 @@ class Flicking extends Component<FlickingEvents> {
1236
1315
  throw new FlickingError(ERROR.MESSAGE.NOT_ALLOWED_IN_FRAMEWORK, ERROR.CODE.NOT_ALLOWED_IN_FRAMEWORK);
1237
1316
  }
1238
1317
 
1239
- return this._renderer.batchRemove({ index, deleteCount });
1318
+ return this._renderer.batchRemove({ index, deleteCount, hasDOMInElements: true });
1240
1319
  }
1241
1320
 
1242
1321
  private _createControl(): Control {
@@ -1282,15 +1361,39 @@ class Flicking extends Component<FlickingEvents> {
1282
1361
  }
1283
1362
 
1284
1363
  private _createRenderer(): Renderer {
1285
- const rendererOptions = {
1286
- align: this._align
1287
- };
1288
-
1289
1364
  const renderExternal = this._renderExternal;
1290
1365
 
1366
+ if (this._virtual && this._panelsPerView <= 0) {
1367
+ // eslint-disable-next-line no-console
1368
+ console.warn("\"virtual\" and \"panelsPerView\" option should be used together, ignoring virtual.");
1369
+ }
1370
+
1291
1371
  return renderExternal
1292
- ? new (renderExternal.renderer as any)({ ...rendererOptions, ...renderExternal.rendererOptions })
1293
- : new VanillaRenderer(rendererOptions);
1372
+ ? this._createExternalRenderer()
1373
+ : this._createVanillaRenderer();
1374
+ }
1375
+
1376
+ private _createVanillaRenderer(): VanillaRenderer {
1377
+ const virtual = this.virtualEnabled;
1378
+
1379
+ return new VanillaRenderer({
1380
+ align: this._align,
1381
+ strategy: virtual
1382
+ ? new VirtualRenderingStrategy()
1383
+ : new NormalRenderingStrategy({
1384
+ providerCtor: VanillaElementProvider,
1385
+ panelCtor: Panel
1386
+ })
1387
+ });
1388
+ }
1389
+
1390
+ private _createExternalRenderer(): ExternalRenderer {
1391
+ const {
1392
+ renderer,
1393
+ rendererOptions
1394
+ } = this._renderExternal!;
1395
+
1396
+ return new (renderer)({ align: this._align, ...rendererOptions });
1294
1397
  }
1295
1398
 
1296
1399
  private async _moveToInitialPanel(): Promise<void> {
@@ -23,7 +23,7 @@ class BoundCamera extends Camera {
23
23
  * @return {this}
24
24
  */
25
25
  public updateRange() {
26
- const flicking = getFlickingAttached(this._flicking, "Camera");
26
+ const flicking = getFlickingAttached(this._flicking);
27
27
  const renderer = flicking.renderer;
28
28
  const alignPos = this._alignPos;
29
29
 
@@ -61,7 +61,7 @@ class BoundCamera extends Camera {
61
61
  }
62
62
 
63
63
  public updateAnchors(): this {
64
- const flicking = getFlickingAttached(this._flicking, "Camera");
64
+ const flicking = getFlickingAttached(this._flicking);
65
65
  const panels = flicking.renderer.panels;
66
66
 
67
67
  if (panels.length <= 0) {
@@ -10,7 +10,7 @@ import Panel from "../core/panel/Panel";
10
10
  import AnchorPoint from "../core/AnchorPoint";
11
11
  import * as ERROR from "../const/error";
12
12
  import { ALIGN, DIRECTION, EVENTS } from "../const/external";
13
- import { checkExistence, clamp, find, getFlickingAttached, getProgress, includes, parseAlign } from "../utils";
13
+ import { checkExistence, clamp, find, getFlickingAttached, getProgress, includes, parseAlign, toArray } from "../utils";
14
14
 
15
15
  export interface CameraOptions {
16
16
  align: FlickingOptions["align"];
@@ -38,12 +38,19 @@ abstract class Camera {
38
38
 
39
39
  // Internal states getter
40
40
  /**
41
- * The camera(`.flicking-camera`) element
42
- * @ko 카메라(`.flicking-camera`) 엘리먼트
41
+ * The camera element(`.flicking-camera`)
42
+ * @ko 카메라 엘리먼트(`.flicking-camera`)
43
43
  * @type {HTMLElement}
44
44
  * @readonly
45
45
  */
46
46
  public get element() { return this._el; }
47
+ /**
48
+ * An array of the child elements of the camera element(`.flicking-camera`)
49
+ * @ko 카메라 엘리먼트(`.flicking-camera`)의 자식 엘리먼트 배열
50
+ * @type {HTMLElement[]}
51
+ * @readonly
52
+ */
53
+ public get children() { return toArray(this._el.children) as HTMLElement[]; }
47
54
  /**
48
55
  * Current position of the camera
49
56
  * @ko Camera의 현재 좌표
@@ -278,7 +285,7 @@ abstract class Camera {
278
285
  this._refreshVisiblePanels();
279
286
  this._checkNeedPanel();
280
287
  this._checkReachEnd(prevPos, pos);
281
- this._applyTransform();
288
+ this.applyTransform();
282
289
  }
283
290
 
284
291
  /**
@@ -376,7 +383,7 @@ abstract class Camera {
376
383
  * @return {AnchorPoint | null}
377
384
  */
378
385
  public findActiveAnchor(): AnchorPoint | null {
379
- const flicking = getFlickingAttached(this._flicking, "Camera");
386
+ const flicking = getFlickingAttached(this._flicking);
380
387
  const activeIndex = flicking.control.activeIndex;
381
388
 
382
389
  return find(this._anchors, anchor => anchor.panel.index === activeIndex);
@@ -418,7 +425,7 @@ abstract class Camera {
418
425
  public canSee(panel: Panel): boolean {
419
426
  const visibleRange = this.visibleRange;
420
427
  // Should not include margin, as we don't declare what the margin is visible as what the panel is visible.
421
- return panel.includeRange(visibleRange.min, visibleRange.max, false);
428
+ return panel.isVisibleOnRange(visibleRange.min, visibleRange.max);
422
429
  }
423
430
 
424
431
  /**
@@ -449,7 +456,7 @@ abstract class Camera {
449
456
  * @return {this}
450
457
  */
451
458
  public updateAnchors(): this {
452
- const flicking = getFlickingAttached(this._flicking, "Camera");
459
+ const flicking = getFlickingAttached(this._flicking);
453
460
  const panels = flicking.renderer.panels;
454
461
 
455
462
  this._anchors = panels.map((panel, index) => new AnchorPoint({
@@ -471,7 +478,7 @@ abstract class Camera {
471
478
  * @return {this}
472
479
  */
473
480
  public updateAdaptiveHeight() {
474
- const flicking = getFlickingAttached(this._flicking, "Camera");
481
+ const flicking = getFlickingAttached(this._flicking);
475
482
  const activePanel = flicking.control.activePanel;
476
483
 
477
484
  if (!flicking.horizontal || !flicking.adaptive || !activePanel) return;
@@ -481,16 +488,24 @@ abstract class Camera {
481
488
  });
482
489
  }
483
490
 
484
- public updateOffset() {
485
- const flicking = getFlickingAttached(this._flicking, "Camera");
486
- const unRenderedPanels = flicking.panels.filter(panel => !panel.rendered);
491
+ /**
492
+ * Update current offset of the camera
493
+ * @ko 현재 카메라의 오프셋을 업데이트합니다
494
+ * @chainable
495
+ * @return {this}
496
+ */
497
+ public updateOffset(): this {
498
+ const flicking = getFlickingAttached(this._flicking);
487
499
  const position = this._position;
500
+ const unRenderedPanels = flicking.panels.filter(panel => !panel.rendered);
488
501
 
489
502
  this._offset = unRenderedPanels
490
503
  .filter(panel => panel.position + panel.offset < position)
491
504
  .reduce((offset, panel) => offset + panel.sizeIncludingMargin, 0);
492
505
 
493
- this._applyTransform();
506
+ this.applyTransform();
507
+
508
+ return this;
494
509
  }
495
510
 
496
511
  /**
@@ -504,6 +519,25 @@ abstract class Camera {
504
519
  return this;
505
520
  }
506
521
 
522
+ /**
523
+ * Apply "transform" style with the current position to camera element
524
+ * @ko 현재 위치를 기준으로한 transform 스타일을 카메라 엘리먼트에 적용합니다.
525
+ * @chainable
526
+ * @return {this}
527
+ */
528
+ public applyTransform(): this {
529
+ const el = this._el;
530
+ const flicking = getFlickingAttached(this._flicking);
531
+
532
+ const actualPosition = this._position - this._alignPos - this._offset;
533
+
534
+ el.style[this._transform] = flicking.horizontal
535
+ ? `translate(${-actualPosition}px)`
536
+ : `translate(0, ${-actualPosition}px)`;
537
+
538
+ return this;
539
+ }
540
+
507
541
  protected _resetInternalValues() {
508
542
  this._position = 0;
509
543
  this._alignPos = 0;
@@ -515,7 +549,7 @@ abstract class Camera {
515
549
  }
516
550
 
517
551
  protected _refreshVisiblePanels() {
518
- const flicking = getFlickingAttached(this._flicking, "Camera");
552
+ const flicking = getFlickingAttached(this._flicking);
519
553
  const panels = flicking.renderer.panels;
520
554
 
521
555
  const newVisiblePanels = panels.filter(panel => this.canSee(panel));
@@ -541,7 +575,7 @@ abstract class Camera {
541
575
 
542
576
  if (needPanelTriggered.prev && needPanelTriggered.next) return;
543
577
 
544
- const flicking = getFlickingAttached(this._flicking, "Camera");
578
+ const flicking = getFlickingAttached(this._flicking);
545
579
  const panels = flicking.renderer.panels;
546
580
 
547
581
  if (panels.length <= 0) {
@@ -588,7 +622,7 @@ abstract class Camera {
588
622
  }
589
623
 
590
624
  protected _checkReachEnd(prevPos: number, newPos: number): void {
591
- const flicking = getFlickingAttached(this._flicking, "Camera");
625
+ const flicking = getFlickingAttached(this._flicking);
592
626
  const range = this._range;
593
627
 
594
628
  const wasBetweenRange = prevPos > range.min && prevPos < range.max;
@@ -603,17 +637,6 @@ abstract class Camera {
603
637
  }));
604
638
  }
605
639
 
606
- protected _applyTransform(): void {
607
- const el = this._el;
608
- const flicking = getFlickingAttached(this._flicking, "Camera");
609
-
610
- const actualPosition = this._position - this._alignPos - this._offset;
611
-
612
- el.style[this._transform] = flicking.horizontal
613
- ? `translate(${-actualPosition}px)`
614
- : `translate(0, ${-actualPosition}px)`;
615
- }
616
-
617
640
  protected _checkTranslateSupport = () => {
618
641
  const transforms = ["webkitTransform", "msTransform", "MozTransform", "OTransform", "transform"];
619
642
 
@@ -150,9 +150,9 @@ class CircularCamera extends Camera {
150
150
 
151
151
  // Check looped visible area for circular case
152
152
  if (visibleRange.min < range.min) {
153
- return visibleInCurrentRange || panel.includeRange(visibleRange.min + rangeDiff, visibleRange.max + rangeDiff, false);
153
+ return visibleInCurrentRange || panel.isVisibleOnRange(visibleRange.min + rangeDiff, visibleRange.max + rangeDiff);
154
154
  } else if (visibleRange.max > range.max) {
155
- return visibleInCurrentRange || panel.includeRange(visibleRange.min - rangeDiff, visibleRange.max - rangeDiff, false);
155
+ return visibleInCurrentRange || panel.isVisibleOnRange(visibleRange.min - rangeDiff, visibleRange.max - rangeDiff);
156
156
  }
157
157
 
158
158
  return visibleInCurrentRange;
@@ -168,7 +168,7 @@ class CircularCamera extends Camera {
168
168
  * @return {this}
169
169
  */
170
170
  public updateRange() {
171
- const flicking = getFlickingAttached(this._flicking, "Camera");
171
+ const flicking = getFlickingAttached(this._flicking);
172
172
  const renderer = flicking.renderer;
173
173
 
174
174
  const panels = renderer.panels;
@@ -197,13 +197,19 @@ class CircularCamera extends Camera {
197
197
  this._range = { min: firstPanel.position, max: lastPanel.position };
198
198
  }
199
199
 
200
- this._updateCircularOffset();
200
+ this.updateOffset();
201
201
 
202
202
  return this;
203
203
  }
204
204
 
205
+ public updateOffset() {
206
+ this._updateCircularOffset();
207
+
208
+ return super.updateOffset();
209
+ }
210
+
205
211
  public lookAt(pos: number) {
206
- const flicking = getFlickingAttached(this._flicking, "Camera");
212
+ const flicking = getFlickingAttached(this._flicking);
207
213
  const prevPos = this._position;
208
214
 
209
215
  if (pos === prevPos) return super.lookAt(pos);
@@ -212,24 +218,26 @@ class CircularCamera extends Camera {
212
218
  const toggled = panels.map(panel => panel.toggle(prevPos, pos));
213
219
 
214
220
  this._position = pos;
221
+ super.lookAt(pos);
215
222
 
216
223
  if (toggled.some(isToggled => isToggled)) {
217
- this._updateCircularOffset();
218
- void flicking.renderer.render();
224
+ void flicking.renderer.render().then(() => {
225
+ this.updateOffset();
226
+ });
219
227
  }
220
-
221
- return super.lookAt(pos);
222
228
  }
223
229
 
224
- protected _applyTransform(): void {
230
+ public applyTransform(): this {
225
231
  const el = this._el;
226
- const flicking = getFlickingAttached(this._flicking, "Camera");
232
+ const flicking = getFlickingAttached(this._flicking);
227
233
 
228
234
  const actualPosition = this._position - this._alignPos - this._offset + this._circularOffset;
229
235
 
230
236
  el.style[this._transform] = flicking.horizontal
231
237
  ? `translate(${-actualPosition}px)`
232
238
  : `translate(0, ${-actualPosition}px)`;
239
+
240
+ return this;
233
241
  }
234
242
 
235
243
  protected _resetInternalValues() {
@@ -248,19 +256,10 @@ class CircularCamera extends Camera {
248
256
  return;
249
257
  }
250
258
 
251
- const flicking = getFlickingAttached(this._flicking, "Camera");
252
- const toggledPrev: Panel[] = [];
253
- const toggledNext: Panel[] = [];
254
-
255
- flicking.panels
256
- .filter(panel => panel.toggled)
257
- .forEach(panel => {
258
- if (panel.toggleDirection === DIRECTION.PREV) {
259
- toggledPrev.push(panel);
260
- } else {
261
- toggledNext.push(panel);
262
- }
263
- });
259
+ const flicking = getFlickingAttached(this._flicking);
260
+ const toggled = flicking.panels.filter(panel => panel.toggled);
261
+ const toggledPrev = toggled.filter(panel => panel.toggleDirection === DIRECTION.PREV);
262
+ const toggledNext = toggled.filter(panel => panel.toggleDirection === DIRECTION.NEXT);
264
263
 
265
264
  this._circularOffset = this._calcPanelAreaSum(toggledPrev) - this._calcPanelAreaSum(toggledNext);
266
265
  }
@@ -21,7 +21,7 @@ class LinearCamera extends Camera {
21
21
  * @return {this}
22
22
  */
23
23
  public updateRange() {
24
- const flicking = getFlickingAttached(this._flicking, "Camera");
24
+ const flicking = getFlickingAttached(this._flicking);
25
25
  const renderer = flicking.renderer;
26
26
 
27
27
  const firstPanel = renderer.getPanel(0);
package/src/cfc/sync.ts CHANGED
@@ -79,13 +79,13 @@ export default (flicking: Flicking, diffResult: DiffResult<any>, rendered: any[]
79
79
 
80
80
  const batchInsert = (renderer: Renderer, diffResult: DiffResult<any>, rendered: any[], startIdx: number, endIdx?: number) => {
81
81
  renderer.batchInsert(
82
- ...diffResult.added.slice(startIdx, endIdx).map((index, elIdx) => ({ index, elements: [rendered[elIdx + diffResult.prevList.length]] }))
82
+ ...diffResult.added.slice(startIdx, endIdx).map((index, elIdx) => ({ index, elements: [rendered[elIdx + diffResult.prevList.length]], hasDOMInElements: false }))
83
83
  );
84
84
  };
85
85
 
86
86
  const batchRemove = (renderer: Renderer, startIdx: number, endIdx?: number) => {
87
87
  const removed = renderer.panels.slice(startIdx, endIdx);
88
88
 
89
- renderer.batchRemove({ index: startIdx, deleteCount: removed.length });
89
+ renderer.batchRemove({ index: startIdx, deleteCount: removed.length, hasDOMInElements: false });
90
90
  };
91
91