@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
@@ -25,6 +25,7 @@
25
25
  * <ko>프레임워크(React, Angular, Vue ...)에서 사용 불가능한 메소드를 호출했을 경우</ko>
26
26
  * @property {number} NOT_INITIALIZED When the {@link Flicking#init} is not called before but is needed<ko>{@link Flicking#init}의 호출이 필요하나, 아직 호출되지 않았을 경우</ko>
27
27
  * @property {number} NO_ACTIVE When there're no active panel that flicking has selected. This may be due to the absence of any panels<ko>현재 Flicking이 선택한 패널이 없을 경우. 일반적으로 패널이 하나도 없는 경우에 발생할 수 있습니다</ko>
28
+ * @property {number} NOT_ALLOWED_IN_VIRTUAL When the non-allowed method is called while the virtual option is enabled<ko>virtual 옵션이 활성화된 상태에서 사용 불가능한 메소드가 호출되었을 경우</ko>
28
29
  */
29
30
  export const CODE = {
30
31
  WRONG_TYPE: 0,
@@ -40,14 +41,15 @@ export const CODE = {
40
41
  ANIMATION_ALREADY_PLAYING: 10,
41
42
  NOT_ALLOWED_IN_FRAMEWORK: 11,
42
43
  NOT_INITIALIZED: 12,
43
- NO_ACTIVE: 13
44
+ NO_ACTIVE: 13,
45
+ NOT_ALLOWED_IN_VIRTUAL: 14
44
46
  } as const;
45
47
 
46
48
  export const MESSAGE = {
47
49
  WRONG_TYPE: (wrongVal: any, correctTypes: string[]) => `${wrongVal}(${typeof wrongVal}) is not a ${correctTypes.map(type => `"${type}"`).join(" or ")}.`,
48
50
  ELEMENT_NOT_FOUND: (selector: string) => `Element with selector "${selector}" not found.`,
49
51
  VAL_MUST_NOT_NULL: (val: any, name: string) => `${name} should be provided. Given: ${val}`,
50
- NOT_ATTACHED_TO_FLICKING: (name: string) => `${name} is not attached to the Flicking instance. "init()" should be called first.`,
52
+ NOT_ATTACHED_TO_FLICKING: "This module is not attached to the Flicking instance. \"init()\" should be called first.",
51
53
  WRONG_OPTION: (optionName: string, val: any) => `Option "${optionName}" is not in correct format, given: ${val}`,
52
54
  INDEX_OUT_OF_RANGE: (val: number, min: number, max: number) => `Index "${val}" is out of range: should be between ${min} and ${max}.`,
53
55
  POSITION_NOT_REACHABLE: (position: number) => `Position "${position}" is not reachable.`,
@@ -57,5 +59,6 @@ export const MESSAGE = {
57
59
  ANIMATION_ALREADY_PLAYING: "Animation is already playing.",
58
60
  NOT_ALLOWED_IN_FRAMEWORK: "This behavior is not allowed in the frameworks like React, Vue, or Angular.",
59
61
  NOT_INITIALIZED: "Flicking is not initialized yet, call init() first.",
60
- NO_ACTIVE: "There's no active panel that Flicking has selected. This may be due to the absence of any panels."
62
+ NO_ACTIVE: "There's no active panel that Flicking has selected. This may be due to the absence of any panels.",
63
+ NOT_ALLOWED_IN_VIRTUAL: "This behavior is not allowed when the virtual option is enabled"
61
64
  } as const;
@@ -92,3 +92,9 @@ export const MOVE_TYPE = {
92
92
  FREE_SCROLL: "freeScroll",
93
93
  STRICT: "strict"
94
94
  } as const;
95
+
96
+ export const CLASS = {
97
+ VERTICAL: "vertical",
98
+ HIDDEN: "flicking-hidden",
99
+ DEFAULT_VIRTUAL: "flicking-panel"
100
+ };
@@ -211,7 +211,7 @@ class AxesController {
211
211
  * @return {this}
212
212
  */
213
213
  public update(controlParams: ControlParams): this {
214
- const flicking = getFlickingAttached(this._flicking, "Control");
214
+ const flicking = getFlickingAttached(this._flicking);
215
215
  const camera = flicking.camera;
216
216
  const axes = this._axes!;
217
217
  const axis = axes.axis[AXES.POSITION_KEY];
@@ -231,7 +231,7 @@ class AxesController {
231
231
  * @return {this}
232
232
  */
233
233
  public addPreventClickHandler(): this {
234
- const flicking = getFlickingAttached(this._flicking, "Control");
234
+ const flicking = getFlickingAttached(this._flicking);
235
235
  const axes = this._axes!;
236
236
  const cameraEl = flicking.camera.element;
237
237
 
@@ -248,7 +248,7 @@ class AxesController {
248
248
  * @return {this}
249
249
  */
250
250
  public removePreventClickHandler(): this {
251
- const flicking = getFlickingAttached(this._flicking, "Control");
251
+ const flicking = getFlickingAttached(this._flicking);
252
252
  const axes = this._axes!;
253
253
  const cameraEl = flicking.camera.element;
254
254
 
@@ -282,17 +282,22 @@ class AxesController {
282
282
  */
283
283
  public animateTo(position: number, duration: number, axesEvent?: OnRelease): Promise<void> {
284
284
  const axes = this._axes;
285
+ const state = this._stateMachine.state;
285
286
 
286
287
  if (!axes) {
287
- return Promise.reject(new FlickingError(ERROR.MESSAGE.NOT_ATTACHED_TO_FLICKING("Control"), ERROR.CODE.NOT_ATTACHED_TO_FLICKING));
288
+ return Promise.reject(new FlickingError(ERROR.MESSAGE.NOT_ATTACHED_TO_FLICKING, ERROR.CODE.NOT_ATTACHED_TO_FLICKING));
288
289
  }
289
290
 
290
291
  const startPos = axes.get([AXES.POSITION_KEY])[AXES.POSITION_KEY];
291
292
 
292
293
  if (startPos === position) {
293
- const flicking = getFlickingAttached(this._flicking, "Control");
294
+ const flicking = getFlickingAttached(this._flicking);
294
295
 
295
296
  flicking.camera.lookAt(position);
297
+
298
+ if (state.targetPanel) {
299
+ flicking.control.setActive(state.targetPanel, flicking.control.activePanel, axesEvent?.isTrusted ?? false);
300
+ }
296
301
  return Promise.resolve();
297
302
  }
298
303
 
@@ -317,7 +322,7 @@ class AxesController {
317
322
  };
318
323
 
319
324
  if (duration === 0) {
320
- const flicking = getFlickingAttached(this._flicking, "Control");
325
+ const flicking = getFlickingAttached(this._flicking);
321
326
  const camera = flicking.camera;
322
327
 
323
328
  animate();
@@ -172,7 +172,7 @@ abstract class Control {
172
172
  * @return {Promise<void>}
173
173
  */
174
174
  public updatePosition(_progressInPanel: number): void { // eslint-disable-line @typescript-eslint/no-unused-vars
175
- const flicking = getFlickingAttached(this._flicking, "Control");
175
+ const flicking = getFlickingAttached(this._flicking);
176
176
  const camera = flicking.camera;
177
177
  const activePanel = this._activePanel;
178
178
 
@@ -188,7 +188,7 @@ abstract class Control {
188
188
  * @return {this}
189
189
  */
190
190
  public updateInput(): this {
191
- const flicking = getFlickingAttached(this._flicking, "Control");
191
+ const flicking = getFlickingAttached(this._flicking);
192
192
  const camera = flicking.camera;
193
193
 
194
194
  this._controller.update(camera.controlParams);
@@ -255,7 +255,7 @@ abstract class Control {
255
255
  direction?: ValueOf<typeof DIRECTION>;
256
256
  axesEvent?: OnRelease;
257
257
  }) {
258
- const flicking = getFlickingAttached(this._flicking, "Control");
258
+ const flicking = getFlickingAttached(this._flicking);
259
259
  const camera = flicking.camera;
260
260
 
261
261
  let position = panel.position;
@@ -299,7 +299,7 @@ abstract class Control {
299
299
  * @internal
300
300
  */
301
301
  public setActive(newActivePanel: Panel, prevActivePanel: Panel | null, isTrusted: boolean) {
302
- const flicking = getFlickingAttached(this._flicking, "Control");
302
+ const flicking = getFlickingAttached(this._flicking);
303
303
 
304
304
  this._activePanel = newActivePanel;
305
305
 
@@ -322,7 +322,7 @@ abstract class Control {
322
322
  }
323
323
 
324
324
  protected _triggerIndexChangeEvent(panel: Panel, position: number, axesEvent?: OnRelease): void {
325
- const flicking = getFlickingAttached(this._flicking, "Control");
325
+ const flicking = getFlickingAttached(this._flicking);
326
326
  const triggeringEvent = panel !== this._activePanel ? EVENTS.WILL_CHANGE : EVENTS.WILL_RESTORE;
327
327
  const camera = flicking.camera;
328
328
  const activePanel = this._activePanel;
@@ -351,7 +351,7 @@ abstract class Control {
351
351
  newActivePanel: Panel;
352
352
  axesEvent?: OnRelease;
353
353
  }) {
354
- const flicking = getFlickingAttached(this._flicking, "Control");
354
+ const flicking = getFlickingAttached(this._flicking);
355
355
  const animate = () => this._controller.animateTo(position, duration, axesEvent);
356
356
  const state = this._controller.state;
357
357
 
@@ -58,7 +58,7 @@ class FreeControl extends Control {
58
58
  * @return {Promise<void>}
59
59
  */
60
60
  public updatePosition(progressInPanel: number): void {
61
- const flicking = getFlickingAttached(this._flicking, "Control");
61
+ const flicking = getFlickingAttached(this._flicking);
62
62
  const camera = flicking.camera;
63
63
  const activePanel = this._activePanel;
64
64
 
@@ -107,7 +107,7 @@ class FreeControl extends Control {
107
107
  * @return {Promise<void>} A Promise which will be resolved after reaching the target position<ko>해당 좌표 도달시에 resolve되는 Promise</ko>
108
108
  */
109
109
  public async moveToPosition(position: number, duration: number, axesEvent?: OnRelease) {
110
- const flicking = getFlickingAttached(this._flicking, "Control");
110
+ const flicking = getFlickingAttached(this._flicking);
111
111
 
112
112
  const camera = flicking.camera;
113
113
  const targetPos = camera.clampToReachablePosition(position);
@@ -85,7 +85,7 @@ class SnapControl extends Control {
85
85
  * @return {Promise<void>} A Promise which will be resolved after reaching the target position<ko>해당 좌표 도달시에 resolve되는 Promise</ko>
86
86
  */
87
87
  public async moveToPosition(position: number, duration: number, axesEvent?: OnRelease) {
88
- const flicking = getFlickingAttached(this._flicking, "Control");
88
+ const flicking = getFlickingAttached(this._flicking);
89
89
  const camera = flicking.camera;
90
90
  const activeAnchor = camera.findActiveAnchor();
91
91
  const anchorAtCamera = camera.findNearestAnchor(camera.position);
@@ -128,7 +128,7 @@ class SnapControl extends Control {
128
128
  }
129
129
 
130
130
  private _findSnappedAnchor(position: number, anchorAtCamera: AnchorPoint): AnchorPoint {
131
- const flicking = getFlickingAttached(this._flicking, "Control");
131
+ const flicking = getFlickingAttached(this._flicking);
132
132
  const camera = flicking.camera;
133
133
  const count = this._count;
134
134
 
@@ -191,7 +191,7 @@ class SnapControl extends Control {
191
191
  }
192
192
 
193
193
  private _findAdjacentAnchor(posDelta: number, anchorAtCamera: AnchorPoint): AnchorPoint {
194
- const flicking = getFlickingAttached(this._flicking, "Control");
194
+ const flicking = getFlickingAttached(this._flicking);
195
195
  const camera = flicking.camera;
196
196
  const adjacentAnchor = (posDelta > 0 ? camera.getNextAnchor(anchorAtCamera) : camera.getPrevAnchor(anchorAtCamera)) ?? anchorAtCamera;
197
197
 
@@ -66,7 +66,7 @@ class StrictControl extends Control {
66
66
  * @return {this}
67
67
  */
68
68
  public updateInput(): this {
69
- const flicking = getFlickingAttached(this._flicking, "Control");
69
+ const flicking = getFlickingAttached(this._flicking);
70
70
  const camera = flicking.camera;
71
71
  const renderer = flicking.renderer;
72
72
  const controller = this._controller;
@@ -178,7 +178,7 @@ class StrictControl extends Control {
178
178
  * @return {Promise<void>} A Promise which will be resolved after reaching the target position<ko>해당 좌표 도달시에 resolve되는 Promise</ko>
179
179
  */
180
180
  public async moveToPosition(position: number, duration: number, axesEvent?: OnRelease) {
181
- const flicking = getFlickingAttached(this._flicking, "Control");
181
+ const flicking = getFlickingAttached(this._flicking);
182
182
  const camera = flicking.camera;
183
183
  const activePanel = this._activePanel;
184
184
  const axesRange = this._controller.range;
@@ -0,0 +1,81 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+ import Flicking from "../Flicking";
6
+
7
+ class AutoResizer {
8
+ private _flicking: Flicking;
9
+ private _enabled: boolean;
10
+ private _resizeObserver: ResizeObserver | null;
11
+
12
+ public get enabled() { return this._enabled; }
13
+
14
+ public constructor(flicking: Flicking) {
15
+ this._flicking = flicking;
16
+ this._enabled = false;
17
+ this._resizeObserver = null;
18
+ }
19
+
20
+ public enable(): this {
21
+ const flicking = this._flicking;
22
+ const viewport = flicking.viewport;
23
+
24
+ if (this._enabled) {
25
+ this.disable();
26
+ }
27
+
28
+ if (flicking.useResizeObserver && !!window.ResizeObserver) {
29
+ const viewportSizeNot0 = viewport.width !== 0 || viewport.height !== 0;
30
+
31
+ const resizeObserver = viewportSizeNot0
32
+ ? new ResizeObserver(this._skipFirstResize)
33
+ : new ResizeObserver(this._onResize);
34
+
35
+ resizeObserver.observe(flicking.viewport.element);
36
+
37
+ this._resizeObserver = resizeObserver;
38
+ } else {
39
+ window.addEventListener("resize", this._onResize);
40
+ }
41
+
42
+ this._enabled = true;
43
+
44
+ return this;
45
+ }
46
+
47
+ public disable(): this {
48
+ if (!this._enabled) return this;
49
+
50
+ const resizeObserver = this._resizeObserver;
51
+ if (resizeObserver) {
52
+ resizeObserver.disconnect();
53
+ this._resizeObserver = null;
54
+ } else {
55
+ window.removeEventListener("resize", this._onResize);
56
+ }
57
+
58
+ this._enabled = false;
59
+
60
+ return this;
61
+ }
62
+
63
+ private _onResize = () => {
64
+ void this._flicking.resize();
65
+ };
66
+
67
+ // eslint-disable-next-line @typescript-eslint/member-ordering
68
+ private _skipFirstResize = (() => {
69
+ let isFirstResize = true;
70
+
71
+ return (() => {
72
+ if (isFirstResize) {
73
+ isFirstResize = false;
74
+ return;
75
+ }
76
+ this._onResize();
77
+ });
78
+ })();
79
+ }
80
+
81
+ export default AutoResizer;
@@ -0,0 +1,188 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+ import Flicking from "../Flicking";
6
+ import { range } from "../utils";
7
+ import { CLASS } from "../const/external";
8
+
9
+ import VirtualPanel from "./panel/VirtualPanel";
10
+
11
+ export interface VirtualOptions {
12
+ renderPanel: (panel: VirtualPanel, index: number) => string;
13
+ initialPanelCount: number;
14
+ cache?: boolean;
15
+ panelClass?: string;
16
+ }
17
+
18
+ /**
19
+ * A manager class to add / remove virtual panels
20
+ */
21
+ class VirtualManager {
22
+ private _flicking: Flicking;
23
+
24
+ private _renderPanel: (panel: VirtualPanel, index: number) => string;
25
+ private _initialPanelCount: number;
26
+ private _cache: boolean;
27
+ private _panelClass: string;
28
+
29
+ private _elements: Array<{ nativeElement: HTMLElement; visible: boolean }>;
30
+
31
+ public get elements() { return this._elements; }
32
+
33
+ // Options
34
+ /**
35
+ * A rendering function for the panel element's innerHTML
36
+ * @ko 패널 엘리먼트의 innerHTML을 렌더링하는 함수
37
+ * @type {function}
38
+ * @param {VirtualPanel} panel Instance of the panel<ko>패널 인스턴스</ko>
39
+ * @param {number} index Index of the panel<ko>패널 인덱스</ko>
40
+ * @default "() => {}"
41
+ */
42
+ public get renderPanel() { return this._renderPanel; }
43
+ /**
44
+ * Initial panel count to render
45
+ * @ko 최초로 렌더링할 패널의 개수
46
+ * @readonly
47
+ * @type {number}
48
+ * @default -1
49
+ */
50
+ public get initialPanelCount() { return this._initialPanelCount; }
51
+ /**
52
+ * Whether to cache rendered panel's innerHTML
53
+ * @ko 렌더링된 패널의 innerHTML 정보를 캐시할지 여부
54
+ * @type {boolean}
55
+ * @default false
56
+ */
57
+ public get cache() { return this._cache; }
58
+ /**
59
+ * The class name that will be applied to rendered panel elements
60
+ * @ko 렌더링되는 패널 엘리먼트에 적용될 클래스 이름
61
+ * @type {string}
62
+ * @default "flicking-panel"
63
+ */
64
+ public get panelClass() { return this._panelClass; }
65
+
66
+ public set renderPanel(val: VirtualOptions["renderPanel"]) {
67
+ this._renderPanel = val;
68
+ this._flicking.renderer.panels.forEach((panel: VirtualPanel) => panel.uncacheRenderResult());
69
+ }
70
+
71
+ public set cache(val: NonNullable<VirtualOptions["cache"]>) { this._cache = val; }
72
+ public set panelClass(val: NonNullable<VirtualOptions["panelClass"]>) { this._panelClass = val; }
73
+
74
+ public constructor(flicking: Flicking, options: VirtualOptions | null) {
75
+ this._flicking = flicking;
76
+
77
+ this._renderPanel = options?.renderPanel ?? (() => "");
78
+ this._initialPanelCount = options?.initialPanelCount ?? -1;
79
+ this._cache = options?.cache ?? false;
80
+ this._panelClass = options?.panelClass ?? CLASS.DEFAULT_VIRTUAL;
81
+
82
+ this._elements = [];
83
+ }
84
+
85
+ public init() {
86
+ const flicking = this._flicking;
87
+
88
+ if (!flicking.virtualEnabled) return;
89
+
90
+ if (!flicking.renderExternal) {
91
+ this._initVirtualElements();
92
+ }
93
+
94
+ const virtualElements = flicking.camera.children;
95
+ this._elements = virtualElements.map(el => ({ nativeElement: el, visible: true }));
96
+ }
97
+
98
+ public show(index: number) {
99
+ const el = this._elements[index];
100
+ const nativeEl = el.nativeElement;
101
+
102
+ el.visible = true;
103
+
104
+ if (nativeEl.style.display) {
105
+ nativeEl.style.display = "";
106
+ }
107
+ }
108
+
109
+ public hide(index: number) {
110
+ const el = this._elements[index];
111
+ const nativeEl = el.nativeElement;
112
+
113
+ el.visible = false;
114
+ nativeEl.style.display = "none";
115
+ }
116
+
117
+ /**
118
+ * Add new virtual panels at the end of the list
119
+ * @ko 새로운 가상 패널들을 리스트의 끝에 추가합니다
120
+ * @param {number} count The number of panels to add<ko>추가할 패널의 개수</ko>
121
+ * @returns {Array<VirtualPanel>} The new panels added<ko>새롭게 추가된 패널들</ko>
122
+ */
123
+ public append(count: number = 1): VirtualPanel[] {
124
+ const flicking = this._flicking;
125
+
126
+ return this.insert(flicking.panels.length, count);
127
+ }
128
+
129
+ /**
130
+ * Add new virtual panels at the start of the list
131
+ * @ko 새로운 가상 패널들을 리스트의 시작에 추가합니다
132
+ * @param {number} count The number of panels to add<ko>추가할 패널의 개수</ko>
133
+ * @returns {Array<VirtualPanel>} The new panels added<ko>새롭게 추가된 패널들</ko>
134
+ */
135
+ public prepend(count: number = 1): VirtualPanel[] {
136
+ return this.insert(0, count);
137
+ }
138
+
139
+ /**
140
+ * Add new virtual panels at the given index
141
+ * @ko 새로운 가상 패널들을 주어진 인덱스에 추가합니다
142
+ * @param {number} count The number of panels to add<ko>추가할 패널의 개수</ko>
143
+ * @returns {Array<VirtualPanel>} The new panels added<ko>새롭게 추가된 패널들</ko>
144
+ */
145
+ public insert(index: number, count: number = 1): VirtualPanel[] {
146
+ if (count <= 0) return [];
147
+
148
+ const flicking = this._flicking;
149
+
150
+ return flicking.renderer.batchInsert({ index, elements: range(count), hasDOMInElements: false }) as VirtualPanel[];
151
+ }
152
+
153
+ /**
154
+ * Remove panels at the given index
155
+ * @ko 주어진 인덱스에서 패널들을 삭제합니다
156
+ * @param {number} count The number of panels to remove<ko>삭제할 패널의 개수</ko>
157
+ * @returns {Array<VirtualPanel>} The panels removed<ko>삭제된 패널들</ko>
158
+ */
159
+ public remove(index: number, count: number): VirtualPanel[] {
160
+ if (count <= 0) return [];
161
+
162
+ const flicking = this._flicking;
163
+
164
+ return flicking.renderer.batchRemove({ index, deleteCount: count, hasDOMInElements: false }) as VirtualPanel[];
165
+ }
166
+
167
+ private _initVirtualElements() {
168
+ const flicking = this._flicking;
169
+ const cameraElement = flicking.camera.element;
170
+ const panelsPerView = flicking.panelsPerView;
171
+ const fragment = document.createDocumentFragment();
172
+
173
+ const newElements = range(panelsPerView + 1).map(idx => {
174
+ const panelEl = document.createElement("div");
175
+ panelEl.className = this._panelClass;
176
+ panelEl.dataset.elementIndex = idx.toString();
177
+ return panelEl;
178
+ });
179
+
180
+ newElements.forEach(el => {
181
+ fragment.appendChild(el);
182
+ });
183
+
184
+ cameraElement.appendChild(fragment);
185
+ }
186
+ }
187
+
188
+ export default VirtualManager;
package/src/core/index.ts CHANGED
@@ -5,11 +5,13 @@
5
5
  import Viewport from "./Viewport";
6
6
  import FlickingError from "./FlickingError";
7
7
  import AnchorPoint from "./AnchorPoint";
8
+ import VirtualManager from "./VirtualManager";
8
9
 
9
10
  export {
10
11
  Viewport,
11
12
  FlickingError,
12
- AnchorPoint
13
+ AnchorPoint,
14
+ VirtualManager
13
15
  };
14
16
 
15
17
  export * from "./panel";
@@ -3,29 +3,37 @@
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
5
  import Panel, { PanelOptions } from "./Panel";
6
+ import ExternalElementProvider from "./provider/ExternalElementProvider";
6
7
 
7
- export interface ExternalPanelOptions<T> extends PanelOptions {
8
- externalComponent: T;
8
+ export interface ExternalPanelOptions extends PanelOptions {
9
+ elementProvider: ExternalElementProvider;
9
10
  }
10
11
 
11
12
  /**
12
- * An slide data component that holds information of a single HTMLElement
13
+ * A slide data component that holds information of a single HTMLElement
13
14
  * @ko 슬라이드 데이터 컴포넌트로, 단일 HTMLElement의 정보를 갖고 있습니다
14
15
  */
15
- abstract class ExternalPanel<T = any> extends Panel {
16
- protected _externalComponent: T;
17
-
18
- /**
19
- * @param {object} options An options object<ko>옵션 오브젝트</ko>
20
- * @param {HTMLElement} [options.el] A `HTMLElement` panel's referencing<ko>패널이 참조하는 `HTMLElement`</ko>
21
- * @param {number} [options.index] An initial index of the panel<ko>패널의 초기 인덱스</ko>
22
- * @param {Constants.ALIGN | string | number} [options.align] An initial {@link Flicking#align align} value of the panel<ko>패널의 초기 {@link Flicking#align align}값</ko>
23
- * @param {Flicking} [options.flicking] A Flicking instance panel's referencing<ko>패널이 참조하는 {@link Flicking} 인스턴스</ko>
24
- */
25
- public constructor(options: ExternalPanelOptions<T>) {
16
+ class ExternalPanel extends Panel {
17
+ protected _elProvider: ExternalElementProvider;
18
+
19
+ public get rendered() { return this._elProvider.rendered; }
20
+
21
+ public constructor(options: ExternalPanelOptions) {
26
22
  super(options);
27
23
 
28
- this._externalComponent = options.externalComponent;
24
+ this._elProvider = options.elementProvider;
25
+ }
26
+
27
+ public markForShow() {
28
+ this._elProvider.show(this._flicking);
29
+
30
+ return super.markForShow();
31
+ }
32
+
33
+ public markForHide() {
34
+ this._elProvider.hide(this._flicking);
35
+
36
+ return super.markForHide();
29
37
  }
30
38
  }
31
39