@egjs/flicking 4.2.4 → 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 (86) hide show
  1. package/README.md +1 -1
  2. package/declaration/Flicking.d.ts +24 -11
  3. package/declaration/camera/Camera.d.ts +5 -4
  4. package/declaration/camera/CircularCamera.d.ts +3 -2
  5. package/declaration/const/error.d.ts +3 -1
  6. package/declaration/const/external.d.ts +5 -0
  7. package/declaration/control/Control.d.ts +2 -2
  8. package/declaration/control/FreeControl.d.ts +1 -1
  9. package/declaration/control/StrictControl.d.ts +1 -1
  10. package/declaration/control/states/State.d.ts +2 -1
  11. package/declaration/core/AutoResizer.d.ts +13 -0
  12. package/declaration/core/VirtualManager.d.ts +37 -0
  13. package/declaration/core/index.d.ts +2 -1
  14. package/declaration/core/panel/ExternalPanel.d.ts +9 -5
  15. package/declaration/core/panel/Panel.d.ts +17 -10
  16. package/declaration/core/panel/VirtualPanel.d.ts +19 -0
  17. package/declaration/core/panel/index.d.ts +4 -3
  18. package/declaration/core/panel/provider/ElementProvider.d.ts +7 -0
  19. package/declaration/core/panel/provider/ExternalElementProvider.d.ts +8 -0
  20. package/declaration/core/panel/provider/VanillaElementProvider.d.ts +10 -0
  21. package/declaration/core/panel/provider/VirtualElementProvider.d.ts +13 -0
  22. package/declaration/core/panel/provider/index.d.ts +6 -0
  23. package/declaration/index.d.ts +11 -1
  24. package/declaration/renderer/ExternalRenderer.d.ts +1 -0
  25. package/declaration/renderer/Renderer.d.ts +18 -13
  26. package/declaration/renderer/VanillaRenderer.d.ts +2 -7
  27. package/declaration/renderer/index.d.ts +1 -0
  28. package/declaration/renderer/strategy/NormalRenderingStrategy.d.ts +25 -0
  29. package/declaration/renderer/strategy/RenderingStrategy.d.ts +15 -0
  30. package/declaration/renderer/strategy/VirtualRenderingStrategy.d.ts +17 -0
  31. package/declaration/renderer/strategy/index.d.ts +5 -0
  32. package/declaration/utils.d.ts +7 -1
  33. package/dist/flicking.esm.js +4649 -3767
  34. package/dist/flicking.esm.js.map +1 -1
  35. package/dist/flicking.js +4689 -3783
  36. package/dist/flicking.js.map +1 -1
  37. package/dist/flicking.min.js +2 -2
  38. package/dist/flicking.min.js.map +1 -1
  39. package/dist/flicking.pkgd.js +4359 -2062
  40. package/dist/flicking.pkgd.js.map +1 -1
  41. package/dist/flicking.pkgd.min.js +2 -2
  42. package/dist/flicking.pkgd.min.js.map +1 -1
  43. package/package.json +2 -1
  44. package/src/Flicking.ts +148 -30
  45. package/src/camera/BoundCamera.ts +2 -2
  46. package/src/camera/Camera.ts +59 -36
  47. package/src/camera/CircularCamera.ts +54 -29
  48. package/src/camera/LinearCamera.ts +1 -1
  49. package/src/cfc/getRenderingPanels.ts +6 -1
  50. package/src/cfc/sync.ts +2 -2
  51. package/src/const/error.ts +6 -3
  52. package/src/const/external.ts +6 -0
  53. package/src/control/AxesController.ts +17 -9
  54. package/src/control/Control.ts +37 -39
  55. package/src/control/FreeControl.ts +4 -4
  56. package/src/control/SnapControl.ts +3 -3
  57. package/src/control/StrictControl.ts +4 -4
  58. package/src/control/states/AnimatingState.ts +6 -3
  59. package/src/control/states/State.ts +4 -2
  60. package/src/core/AutoResizer.ts +81 -0
  61. package/src/core/VirtualManager.ts +188 -0
  62. package/src/core/index.ts +3 -1
  63. package/src/core/panel/ExternalPanel.ts +23 -15
  64. package/src/core/panel/Panel.ts +68 -60
  65. package/src/core/panel/VirtualPanel.ts +110 -0
  66. package/src/core/panel/index.ts +5 -4
  67. package/src/core/panel/provider/ElementProvider.ts +13 -0
  68. package/src/core/panel/provider/ExternalElementProvider.ts +15 -0
  69. package/src/core/panel/provider/VanillaElementProvider.ts +40 -0
  70. package/src/core/panel/provider/VirtualElementProvider.ts +45 -0
  71. package/src/core/panel/provider/index.ts +18 -0
  72. package/src/index.ts +12 -1
  73. package/src/index.umd.ts +2 -0
  74. package/src/renderer/ExternalRenderer.ts +36 -4
  75. package/src/renderer/Renderer.ts +174 -69
  76. package/src/renderer/VanillaRenderer.ts +28 -86
  77. package/src/renderer/index.ts +2 -0
  78. package/src/renderer/strategy/NormalRenderingStrategy.ts +109 -0
  79. package/src/renderer/strategy/RenderingStrategy.ts +21 -0
  80. package/src/renderer/strategy/VirtualRenderingStrategy.ts +110 -0
  81. package/src/renderer/strategy/index.ts +17 -0
  82. package/src/utils.ts +36 -2
  83. package/declaration/core/panel/ElementPanel.d.ts +0 -14
  84. package/declaration/exports.d.ts +0 -10
  85. package/src/core/panel/ElementPanel.ts +0 -52
  86. package/src/exports.ts +0 -16
@@ -0,0 +1,40 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+ import Flicking from "../../../Flicking";
6
+
7
+ import ElementProvider from "./ElementProvider";
8
+
9
+ /**
10
+ * @internal
11
+ */
12
+ class VanillaElementProvider implements ElementProvider {
13
+ private _element: HTMLElement;
14
+
15
+ public get element() { return this._element; }
16
+
17
+ public constructor(element: HTMLElement) {
18
+ this._element = element;
19
+ }
20
+
21
+ public show(flicking: Flicking): void {
22
+ const el = this.element;
23
+ const cameraEl = flicking.camera.element;
24
+
25
+ if (el.parentElement !== cameraEl) {
26
+ cameraEl.appendChild(el);
27
+ }
28
+ }
29
+
30
+ public hide(flicking: Flicking): void {
31
+ const el = this.element;
32
+ const cameraEl = flicking.camera.element;
33
+
34
+ if (el.parentElement === cameraEl) {
35
+ cameraEl.removeChild(el);
36
+ }
37
+ }
38
+ }
39
+
40
+ export default VanillaElementProvider;
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+
6
+ import Flicking from "../../../Flicking";
7
+ import VirtualPanel from "../VirtualPanel";
8
+
9
+ import ElementProvider from "./ElementProvider";
10
+
11
+ /**
12
+ * @internal
13
+ */
14
+ class VirtualElementProvider implements ElementProvider {
15
+ private _flicking: Flicking;
16
+ private _panel: VirtualPanel;
17
+
18
+ public get element() {
19
+ const flicking = this._flicking;
20
+ const elIndex = this._panel.elementIndex;
21
+ const virtualElements = flicking.virtual.elements;
22
+
23
+ return virtualElements[elIndex].nativeElement;
24
+ }
25
+
26
+ public constructor(flicking: Flicking) {
27
+ this._flicking = flicking;
28
+ }
29
+
30
+ public init(panel: VirtualPanel) {
31
+ this._panel = panel;
32
+ }
33
+
34
+ public show(): void {
35
+ // DO_NOTHING
36
+ // Actual element visibility is controlled by VirtualManager
37
+ }
38
+
39
+ public hide(): void {
40
+ // DO_NOTHING
41
+ // Actual element visibility is controlled by VirtualManager
42
+ }
43
+ }
44
+
45
+ export default VirtualElementProvider;
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+ import ElementProvider from "./ElementProvider";
6
+ import ExternalElementProvider from "./ExternalElementProvider";
7
+ import VanillaElementProvider from "./VanillaElementProvider";
8
+ import VirtualElementProvider from "./VirtualElementProvider";
9
+
10
+ export {
11
+ VanillaElementProvider,
12
+ VirtualElementProvider
13
+ };
14
+
15
+ export type {
16
+ ElementProvider,
17
+ ExternalElementProvider
18
+ };
package/src/index.ts CHANGED
@@ -3,7 +3,18 @@
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
5
  import Flicking from "./Flicking";
6
+ import type { FlickingOptions, FlickingEvents } from "./Flicking";
6
7
 
7
- export * from "./exports";
8
+ export * from "./core";
9
+ export * from "./camera";
10
+ export * from "./control";
11
+ export * from "./renderer";
12
+ export * from "./const/external";
13
+ export * from "./cfc";
14
+ export * from "./utils";
15
+
16
+ export * from "./type/event";
17
+ export * from "./type/external";
18
+ export type { FlickingOptions, FlickingEvents };
8
19
 
9
20
  export default Flicking;
package/src/index.umd.ts CHANGED
@@ -9,6 +9,7 @@ import * as Control from "./control";
9
9
  import * as Renderer from "./renderer";
10
10
  import * as Constants from "./const/external";
11
11
  import * as CFC from "./cfc";
12
+ import * as Utils from "./utils";
12
13
  import { merge } from "./utils";
13
14
 
14
15
  merge(Flicking, Core);
@@ -17,5 +18,6 @@ merge(Flicking, Control);
17
18
  merge(Flicking, Renderer);
18
19
  merge(Flicking, Constants);
19
20
  merge(Flicking, CFC);
21
+ merge(Flicking, Utils);
20
22
 
21
23
  export default Flicking;
@@ -10,15 +10,47 @@ import Renderer from "./Renderer";
10
10
  *
11
11
  */
12
12
  abstract class ExternalRenderer extends Renderer {
13
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
+ /* eslint-disable @typescript-eslint/no-unused-vars */
14
14
  protected _insertPanelElements(panels: Panel[], nextSibling: Panel | null): void {
15
- // DO NOTHING
15
+ // DO NOTHING, overrided to prevent an unexpected error
16
16
  }
17
17
 
18
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
19
18
  protected _removePanelElements(panels: Panel[]): void {
20
- // DO NOTHING
19
+ // DO NOTHING, overrided to prevent an unexpected error
21
20
  }
21
+
22
+ protected _removeAllChildsFromCamera(): void {
23
+ // DO NOTHING, overrided to prevent an unexpected error
24
+ }
25
+ /* eslint-enable @typescript-eslint/no-unused-vars */
26
+
27
+ // protected _renderVirtualPanels() {
28
+ // const flicking = getFlickingAttached(this._flicking);
29
+ // const virtualManager = this._virtualManager;
30
+
31
+ // if (!virtualManager) return;
32
+
33
+ // const elements = virtualManager.elements;
34
+ // const visiblePanels = flicking.visiblePanels as VirtualPanel[];
35
+ // const invisibles = elements.map((_, idx) => idx);
36
+
37
+ // visiblePanels.forEach(panel => {
38
+ // const virtualEl = panel.virtualElement;
39
+
40
+ // invisibles[virtualEl.index] = -1;
41
+ // virtualEl.renderingPanel = panel;
42
+ // virtualEl.show();
43
+ // panel.markForShow();
44
+ // });
45
+
46
+ // invisibles.filter(val => val >= 0)
47
+ // .forEach(idx => {
48
+ // const virtualEl = elements[idx];
49
+ // virtualEl.hide();
50
+ // virtualEl.renderingPanel?.markForHide();
51
+ // virtualEl.renderingPanel = null;
52
+ // });
53
+ // }
22
54
  }
23
55
 
24
56
  export default ExternalRenderer;
@@ -3,16 +3,20 @@
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
5
  import { ComponentEvent } from "@egjs/component";
6
+ import ImReady from "@egjs/imready";
6
7
 
7
8
  import Flicking, { FlickingOptions } from "../Flicking";
8
9
  import Panel, { PanelOptions } from "../core/panel/Panel";
9
10
  import FlickingError from "../core/FlickingError";
10
11
  import { ALIGN, EVENTS } from "../const/external";
11
12
  import * as ERROR from "../const/error";
12
- import { getFlickingAttached, getMinusCompensatedIndex, includes } from "../utils";
13
+ import { getFlickingAttached, getMinusCompensatedIndex, includes, parsePanelAlign } from "../utils";
14
+
15
+ import RenderingStrategy from "./strategy/RenderingStrategy";
13
16
 
14
17
  export interface RendererOptions {
15
- align: FlickingOptions["align"];
18
+ align?: FlickingOptions["align"];
19
+ strategy: RenderingStrategy;
16
20
  }
17
21
 
18
22
  /**
@@ -25,7 +29,8 @@ abstract class Renderer {
25
29
  protected _panels: Panel[];
26
30
 
27
31
  // Options
28
- protected _align: RendererOptions["align"];
32
+ protected _align: NonNullable<RendererOptions["align"]>;
33
+ protected _strategy: RendererOptions["strategy"];
29
34
 
30
35
  // Internal states Getter
31
36
  /**
@@ -43,6 +48,10 @@ abstract class Renderer {
43
48
  * @readonly
44
49
  */
45
50
  public get panelCount() { return this._panels.length; }
51
+ /**
52
+ * @internal
53
+ */
54
+ public get strategy() { return this._strategy; }
46
55
 
47
56
  // Options Getter
48
57
  /**
@@ -53,25 +62,28 @@ abstract class Renderer {
53
62
  public get align() { return this._align; }
54
63
 
55
64
  // Options Setter
56
- public set align(val: RendererOptions["align"]) {
65
+ public set align(val: NonNullable<RendererOptions["align"]>) {
57
66
  this._align = val;
58
67
 
59
- const panelAlign = this._getPanelAlign();
68
+ const panelAlign = parsePanelAlign(val);
60
69
  this._panels.forEach(panel => { panel.align = panelAlign; });
61
70
  }
62
71
 
63
72
  /**
64
73
  * @param {object} options An options object<ko>옵션 오브젝트</ko>
65
- * @param {Constants.ALIGN | string | number} [options.align] An {@link Flicking#align align} value that will be applied to all panels<ko>전체 패널에 적용될 {@link Flicking#align align} 값</ko>
74
+ * @param {Constants.ALIGN | string | number} [options.align="center"] An {@link Flicking#align align} value that will be applied to all panels<ko>전체 패널에 적용될 {@link Flicking#align align} 값</ko>
75
+ * @param {object} [options.strategy] An instance of RenderingStrategy(internal module)<ko>RenderingStrategy의 인스턴스(내부 모듈)</ko>
66
76
  */
67
77
  public constructor({
68
- align = ALIGN.CENTER
69
- }: Partial<RendererOptions> = {}) {
78
+ align = ALIGN.CENTER,
79
+ strategy
80
+ }: RendererOptions) {
70
81
  this._flicking = null;
71
82
  this._panels = [];
72
83
 
73
84
  // Bind options
74
85
  this._align = align;
86
+ this._strategy = strategy;
75
87
  }
76
88
 
77
89
  /**
@@ -86,12 +98,9 @@ abstract class Renderer {
86
98
  * @return {this}
87
99
  */
88
100
  public abstract render(): Promise<void>;
89
- public abstract forceRenderAllPanels(): Promise<void>;
90
101
 
91
102
  protected abstract _collectPanels(): void;
92
- protected abstract _createPanel(el: any, options: PanelOptions): Panel;
93
- protected abstract _insertPanelElements(panels: Panel[], nextSibling: Panel | null): void;
94
- protected abstract _removePanelElements(panels: Panel[]): void;
103
+ protected abstract _createPanel(el: any, options: Omit<PanelOptions, "elementProvider">): Panel;
95
104
 
96
105
  /**
97
106
  * Initialize Renderer
@@ -127,6 +136,12 @@ abstract class Renderer {
127
136
  return this._panels[index] || null;
128
137
  }
129
138
 
139
+ public forceRenderAllPanels(): Promise<void> {
140
+ this._panels.forEach(panel => panel.markForShow());
141
+
142
+ return Promise.resolve();
143
+ }
144
+
130
145
  /**
131
146
  * Update all panel sizes
132
147
  * @ko 모든 패널의 크기를 업데이트합니다
@@ -134,10 +149,16 @@ abstract class Renderer {
134
149
  * @return {this}
135
150
  */
136
151
  public updatePanelSize(): this {
137
- const flicking = getFlickingAttached(this._flicking, "Renderer");
152
+ const flicking = getFlickingAttached(this._flicking);
153
+ const panels = this._panels;
154
+
155
+ if (panels.length <= 0) return this;
138
156
 
139
157
  if (flicking.panelsPerView > 0) {
140
- this._updatePanelSizeByGrid(flicking);
158
+ const firstPanel = panels[0];
159
+ firstPanel.resize();
160
+
161
+ this._updatePanelSizeByGrid(firstPanel, panels);
141
162
  } else {
142
163
  flicking.panels.forEach(panel => panel.resize());
143
164
  }
@@ -150,19 +171,23 @@ abstract class Renderer {
150
171
  * This will increase index of panels after by the number of panels added
151
172
  * @ko 주어진 인덱스에 새로운 패널들을 추가합니다
152
173
  * 해당 인덱스보다 같거나 큰 인덱스를 가진 기존 패널들은 추가한 패널의 개수만큼 인덱스가 증가합니다.
153
- * @param {number} index Index to insert new panels at<ko>새로 패널들을 추가할 인덱스</ko>
154
- * @param {any[]} elements An array of element or framework component with element in it<ko>엘리먼트의 배열 혹은 프레임워크에서 엘리먼트를 포함한 컴포넌트들의 배열</ko>
174
+ * @param {Array<object>} items An array of items to insert<ko>추가할 아이템들의 배열</ko>
175
+ * @param {number} [items.index] Index to insert new panels at<ko>새로 패널들을 추가할 인덱스</ko>
176
+ * @param {any[]} [items.elements] An array of element or framework component with element in it<ko>엘리먼트의 배열 혹은 프레임워크에서 엘리먼트를 포함한 컴포넌트들의 배열</ko>
177
+ * @param {boolean} [items.hasDOMInElements] Whether it contains actual DOM elements. If set to true, renderer will add them to the camera element<ko>내부에 실제 DOM 엘리먼트들을 포함하고 있는지 여부. true로 설정할 경우, 렌더러는 해당 엘리먼트들을 카메라 엘리먼트 내부에 추가합니다</ko>
155
178
  * @return {Panel[]} An array of prepended panels<ko>추가된 패널들의 배열</ko>
156
179
  */
157
180
  public batchInsert(...items: Array<{
158
181
  index: number;
159
182
  elements: any[];
183
+ hasDOMInElements: boolean;
160
184
  }>): Panel[] {
161
185
  const panels = this._panels;
162
- const flicking = getFlickingAttached(this._flicking, "Renderer");
186
+ const flicking = getFlickingAttached(this._flicking);
163
187
 
164
188
  const { control } = flicking;
165
- const align = this._getPanelAlign();
189
+ const prevFirstPanel = panels[0];
190
+ const align = parsePanelAlign(this._align);
166
191
 
167
192
  const allPanelsInserted = items.reduce((addedPanels, item) => {
168
193
  const insertingIdx = getMinusCompensatedIndex(item.index, panels.length);
@@ -171,18 +196,24 @@ abstract class Renderer {
171
196
 
172
197
  panels.splice(insertingIdx, 0, ...panelsInserted);
173
198
 
174
- // Insert the actual elements as camera element's children
175
- this._insertPanelElements(panelsInserted, panelsPushed[0] ?? null);
199
+ if (item.hasDOMInElements) {
200
+ // Insert the actual elements as camera element's children
201
+ this._insertPanelElements(panelsInserted, panelsPushed[0] ?? null);
202
+ }
176
203
 
177
204
  // Resize the newly added panels
178
- panelsInserted.forEach(panel => panel.resize());
205
+ if (flicking.panelsPerView > 0) {
206
+ const firstPanel = prevFirstPanel || panelsInserted[0].resize();
179
207
 
180
- const insertedSize = this._getPanelSizeSum(panelsInserted);
208
+ this._updatePanelSizeByGrid(firstPanel, panelsInserted);
209
+ } else {
210
+ panelsInserted.forEach(panel => panel.resize());
211
+ }
181
212
 
182
213
  // Update panel indexes & positions
183
214
  panelsPushed.forEach(panel => {
184
215
  panel.increaseIndex(panelsInserted.length);
185
- panel.increasePosition(insertedSize);
216
+ panel.updatePosition();
186
217
  });
187
218
 
188
219
  return [...addedPanels, ...panelsInserted];
@@ -210,6 +241,8 @@ abstract class Renderer {
210
241
  removed: []
211
242
  }));
212
243
 
244
+ this.checkPanelContentsReady(allPanelsInserted);
245
+
213
246
  return allPanelsInserted;
214
247
  }
215
248
 
@@ -218,13 +251,15 @@ abstract class Renderer {
218
251
  * This will decrease index of panels after by the number of panels removed
219
252
  * @ko 주어진 인덱스의 패널을 제거합니다
220
253
  * 해당 인덱스보다 큰 인덱스를 가진 기존 패널들은 제거한 패널의 개수만큼 인덱스가 감소합니다
221
- * @param {number} index Index of panel to remove<ko>제거할 패널의 인덱스</ko>
222
- * @param {number} [deleteCount=1] Number of panels to remove from index<ko>`index` 이후로 제거할 패널의 개수</ko>
254
+ * @param {Array<object>} items An array of items to remove<ko>제거할 아이템들의 배열</ko>
255
+ * @param {number} [items.index] Index of panel to remove<ko>제거할 패널의 인덱스</ko>
256
+ * @param {number} [items.deleteCount=1] Number of panels to remove from index<ko>`index` 이후로 제거할 패널의 개수</ko>
257
+ * @param {boolean} [items.hasDOMInElements=1] Whether it contains actual DOM elements. If set to true, renderer will remove them from the camera element<ko>내부에 실제 DOM 엘리먼트들을 포함하고 있는지 여부. true로 설정할 경우, 렌더러는 해당 엘리먼트들을 카메라 엘리먼트 내부에서 제거합니다</ko>
223
258
  * @return An array of removed panels<ko>제거된 패널들의 배열</ko>
224
259
  */
225
- public batchRemove(...items: Array<{ index: number; deleteCount: number }>): Panel[] {
260
+ public batchRemove(...items: Array<{ index: number; deleteCount: number; hasDOMInElements: boolean }>): Panel[] {
226
261
  const panels = this._panels;
227
- const flicking = getFlickingAttached(this._flicking, "Renderer");
262
+ const flicking = getFlickingAttached(this._flicking);
228
263
 
229
264
  const { camera, control } = flicking;
230
265
  const activePanel = control.activePanel;
@@ -240,20 +275,18 @@ abstract class Renderer {
240
275
  if (panelsRemoved.length <= 0) return [];
241
276
 
242
277
  // Update panel indexes & positions
243
- const removedSize = this._getPanelSizeSum(panelsRemoved);
244
278
  panelsPulled.forEach(panel => {
245
279
  panel.decreaseIndex(panelsRemoved.length);
246
- panel.decreasePosition(removedSize);
280
+ panel.updatePosition();
247
281
  });
248
282
 
249
- this._removePanelElements(panelsRemoved);
283
+ if (item.hasDOMInElements) {
284
+ this._removePanelElements(panelsRemoved);
285
+ }
250
286
 
251
287
  // Remove panel elements
252
288
  panelsRemoved.forEach(panel => panel.destroy());
253
289
 
254
- // Update camera & control
255
- this._updateCameraAndControl();
256
-
257
290
  if (includes(panelsRemoved, activePanel)) {
258
291
  control.resetActive();
259
292
  }
@@ -261,6 +294,9 @@ abstract class Renderer {
261
294
  return [...removed, ...panelsRemoved];
262
295
  }, []);
263
296
 
297
+ // Update camera & control
298
+ this._updateCameraAndControl();
299
+
264
300
  void this.render();
265
301
 
266
302
  // FIXME: fix for animating case
@@ -275,7 +311,7 @@ abstract class Renderer {
275
311
  }).catch(() => void 0);
276
312
  } else {
277
313
  // All panels removed
278
- void camera.lookAt(0);
314
+ camera.lookAt(0);
279
315
  }
280
316
  }
281
317
 
@@ -289,25 +325,80 @@ abstract class Renderer {
289
325
  return allPanelsRemoved;
290
326
  }
291
327
 
292
- protected _getPanelAlign() {
293
- const align = this._align;
328
+ /**
329
+ * @internal
330
+ */
331
+ public checkPanelContentsReady(checkingPanels: Panel[]) {
332
+ const flicking = getFlickingAttached(this._flicking);
333
+ const resizeOnContentsReady = flicking.resizeOnContentsReady;
334
+ const panels = this._panels;
335
+
336
+ if (!resizeOnContentsReady || flicking.virtualEnabled) return;
294
337
 
295
- return typeof align === "object"
296
- ? (align as { panel: string | number }).panel
297
- : align;
298
- }
338
+ const hasContents = (panel: Panel) => !!panel.element.querySelector("img, video");
339
+ checkingPanels = checkingPanels.filter(panel => hasContents(panel));
340
+
341
+ if (checkingPanels.length <= 0) return;
299
342
 
300
- protected _getPanelSizeSum(panels: Panel[]): number {
301
- const firstPanel = panels[0];
302
- const lastPanel = panels[panels.length - 1];
343
+ const contentsReadyChecker = new ImReady();
303
344
 
304
- const marginDiff = lastPanel.margin.next - firstPanel.margin.prev;
345
+ checkingPanels.forEach(panel => {
346
+ panel.loading = true;
347
+ });
348
+
349
+ contentsReadyChecker.on("readyElement", e => {
350
+ if (!this._flicking) {
351
+ // Renderer's destroy() is called before
352
+ contentsReadyChecker.destroy();
353
+ return;
354
+ }
355
+
356
+ const panel = checkingPanels[e.index];
357
+ const camera = flicking.camera;
358
+ const control = flicking.control;
359
+ const prevProgressInPanel = control.activePanel
360
+ ? camera.getProgressInPanel(control.activePanel)
361
+ : 0;
305
362
 
306
- return (lastPanel.range.max - firstPanel.range.min) + marginDiff;
363
+ panel.loading = false;
364
+ panel.resize();
365
+ panels.slice(panel.index + 1).forEach(panelBehind => panelBehind.updatePosition());
366
+
367
+ if (!flicking.initialized) return;
368
+
369
+ camera.updateRange();
370
+ camera.updateAnchors();
371
+
372
+ if (control.animating) {
373
+ // TODO: Need Axes update
374
+ } else {
375
+ control.updatePosition(prevProgressInPanel);
376
+ control.updateInput();
377
+ }
378
+ });
379
+
380
+ contentsReadyChecker.on("preReady", e => {
381
+ if (this._flicking) {
382
+ void this.render();
383
+ }
384
+
385
+ if (e.readyCount === e.totalCount) {
386
+ contentsReadyChecker.destroy();
387
+ }
388
+ });
389
+
390
+ contentsReadyChecker.on("ready", () => {
391
+ if (this._flicking) {
392
+ void this.render();
393
+ }
394
+ contentsReadyChecker.destroy();
395
+ });
396
+
397
+ contentsReadyChecker.check(checkingPanels.map(panel => panel.element));
307
398
  }
308
399
 
309
400
  protected _updateCameraAndControl() {
310
- const flicking = getFlickingAttached(this._flicking, "Renderer");
401
+ const flicking = getFlickingAttached(this._flicking);
311
402
  const { camera, control } = flicking;
312
403
 
313
404
  camera.updateRange();
@@ -316,16 +407,6 @@ abstract class Renderer {
316
407
  control.updateInput();
317
408
  }
318
409
 
319
- protected _updateRenderingPanels(): void {
320
- const flicking = getFlickingAttached(this._flicking, "Renderer");
321
-
322
- if (flicking.renderOnlyVisible) {
323
- this._showOnlyVisiblePanels(flicking);
324
- } else {
325
- flicking.panels.forEach(panel => panel.markForShow());
326
- }
327
- }
328
-
329
410
  protected _showOnlyVisiblePanels(flicking: Flicking) {
330
411
  const panels = flicking.renderer.panels;
331
412
  const camera = flicking.camera;
@@ -336,7 +417,7 @@ abstract class Renderer {
336
417
  }, {});
337
418
 
338
419
  panels.forEach(panel => {
339
- if (panel.index in visibleIndexes) {
420
+ if (panel.index in visibleIndexes || panel.loading) {
340
421
  panel.markForShow();
341
422
  } else if (!flicking.holding) {
342
423
  // During the input sequence,
@@ -344,12 +425,10 @@ abstract class Renderer {
344
425
  panel.markForHide();
345
426
  }
346
427
  });
347
-
348
- camera.updateOffset();
349
428
  }
350
429
 
351
- protected _updatePanelSizeByGrid(flicking: Flicking) {
352
- const panels = flicking.panels;
430
+ protected _updatePanelSizeByGrid(referencePanel: Panel, panels: Panel[]) {
431
+ const flicking = getFlickingAttached(this._flicking);
353
432
  const panelsPerView = flicking.panelsPerView;
354
433
 
355
434
  if (panelsPerView <= 0) {
@@ -357,12 +436,8 @@ abstract class Renderer {
357
436
  }
358
437
  if (panels.length <= 0) return;
359
438
 
360
- // resize only the first panel
361
- const firstPanel = panels[0];
362
- firstPanel.resize();
363
-
364
439
  const viewportSize = flicking.camera.size;
365
- const gap = firstPanel.margin.prev + firstPanel.margin.next;
440
+ const gap = referencePanel.margin.prev + referencePanel.margin.next;
366
441
 
367
442
  const panelSize = (viewportSize - gap * (panelsPerView - 1)) / panelsPerView;
368
443
  const panelSizeObj = flicking.horizontal
@@ -370,16 +445,46 @@ abstract class Renderer {
370
445
  : { height: panelSize };
371
446
  const firstPanelSizeObj = {
372
447
  size: panelSize,
373
- height: firstPanel.height,
374
- margin: firstPanel.margin
448
+ height: referencePanel.height,
449
+ margin: referencePanel.margin
375
450
  };
376
451
 
377
452
  if (!flicking.noPanelStyleOverride) {
378
- flicking.panels.forEach(panel => panel.setSize(panelSizeObj));
453
+ this._strategy.updatePanelSizes(flicking, panelSizeObj);
379
454
  }
380
455
 
381
456
  flicking.panels.forEach(panel => panel.resize(firstPanelSizeObj));
382
457
  }
458
+
459
+ protected _removeAllChildsFromCamera() {
460
+ const flicking = getFlickingAttached(this._flicking);
461
+ const cameraElement = flicking.camera.element;
462
+
463
+ // Remove other elements
464
+ while (cameraElement.firstChild) {
465
+ cameraElement.removeChild(cameraElement.firstChild);
466
+ }
467
+ }
468
+
469
+ protected _insertPanelElements(panels: Panel[], nextSibling: Panel | null = null) {
470
+ const flicking = getFlickingAttached(this._flicking);
471
+ const camera = flicking.camera;
472
+ const cameraElement = camera.element;
473
+ const nextSiblingElement = nextSibling?.element || null;
474
+ const fragment = document.createDocumentFragment();
475
+
476
+ panels.forEach(panel => fragment.appendChild(panel.element));
477
+ cameraElement.insertBefore(fragment, nextSiblingElement);
478
+ }
479
+
480
+ protected _removePanelElements(panels: Panel[]) {
481
+ const flicking = getFlickingAttached(this._flicking);
482
+ const cameraElement = flicking.camera.element;
483
+
484
+ panels.forEach(panel => {
485
+ cameraElement.removeChild(panel.element);
486
+ });
487
+ }
383
488
  }
384
489
 
385
490
  export default Renderer;