@egjs/flicking 4.8.1 → 4.9.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@egjs/flicking",
3
- "version": "4.8.1",
3
+ "version": "4.9.2",
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",
@@ -23,7 +23,7 @@
23
23
  "test": "npm run test --prefix test/unit",
24
24
  "test:chrome": "npm run test:chrome --prefix test/unit",
25
25
  "test:cfc": "npm run test --prefix test/cfc",
26
- "lint": "eslint 'src/**/*.ts'",
26
+ "lint": "eslint src/**/*.ts",
27
27
  "lint:test": "eslint 'test/unit/**/*.ts'",
28
28
  "jsdoc": "jsdoc -c jsdoc.json",
29
29
  "jsdoc:watch": "npm-watch jsdoc",
@@ -136,7 +136,7 @@
136
136
  "typescript-transform-paths": "^2.2.3"
137
137
  },
138
138
  "dependencies": {
139
- "@egjs/axes": "^3.2.2",
139
+ "@egjs/axes": "^3.6.0",
140
140
  "@egjs/component": "^3.0.1",
141
141
  "@egjs/imready": "^1.1.3",
142
142
  "@egjs/list-differ": "^1.0.0"
package/src/Flicking.ts CHANGED
@@ -90,6 +90,7 @@ export interface FlickingOptions {
90
90
  useResizeObserver: boolean;
91
91
  resizeDebounce: number;
92
92
  maxResizeDebounce: number;
93
+ useFractionalSize: boolean;
93
94
  externalRenderer: ExternalRenderer | null;
94
95
 
95
96
  // @deprecated
@@ -164,6 +165,7 @@ class Flicking extends Component<FlickingEvents> {
164
165
  private _useResizeObserver: FlickingOptions["useResizeObserver"];
165
166
  private _resizeDebounce: FlickingOptions["resizeDebounce"];
166
167
  private _maxResizeDebounce: FlickingOptions["maxResizeDebounce"];
168
+ private _useFractionalSize: FlickingOptions["useFractionalSize"];
167
169
  private _externalRenderer: FlickingOptions["externalRenderer"];
168
170
  private _renderExternal: FlickingOptions["renderExternal"];
169
171
 
@@ -665,6 +667,17 @@ class Flicking extends Component<FlickingEvents> {
665
667
  * @default 100
666
668
  */
667
669
  public get maxResizeDebounce() { return this._maxResizeDebounce; }
670
+ /**
671
+ * By enabling this, Flicking will calculate all internal size with CSS width computed with getComputedStyle.
672
+ * This can prevent 1px offset issue in some cases where panel size has the fractional part.
673
+ * All sizes will have the original size before CSS {@link https://developer.mozilla.org/en-US/docs/Web/CSS/transform transform} is applied on the element.
674
+ * @ko 이 옵션을 활성화할 경우, Flicking은 내부의 모든 크기를 {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect getBoundingClientRect}를 이용하여 계산합니다.
675
+ * 이를 통해, 패널 크기에 소수점을 포함할 경우에 발생할 수 있는 일부 1px 오프셋 이슈를 해결 가능합니다.
676
+ * 모든 크기는 CSS {@link https://developer.mozilla.org/en-US/docs/Web/CSS/transform transform}이 엘리먼트에 적용되기 이전의 크기를 사용할 것입니다.
677
+ * @type {boolean}
678
+ * @default false
679
+ */
680
+ public get useFractionalSize() { return this._useFractionalSize; }
668
681
  /**
669
682
  * This is an option for the frameworks(React, Vue, Angular, ...). Don't set it as it's automatically managed by Flicking.
670
683
  * @ko 프레임워크(React, Vue, Angular, ...)에서만 사용하는 옵션으로, 자동으로 설정되므로 따로 사용하실 필요 없습니다!
@@ -814,6 +827,7 @@ class Flicking extends Component<FlickingEvents> {
814
827
  useResizeObserver = true,
815
828
  resizeDebounce = 0,
816
829
  maxResizeDebounce = 100,
830
+ useFractionalSize = false,
817
831
  externalRenderer = null,
818
832
  renderExternal = null
819
833
  }: Partial<FlickingOptions> = {}) {
@@ -856,11 +870,12 @@ class Flicking extends Component<FlickingEvents> {
856
870
  this._useResizeObserver = useResizeObserver;
857
871
  this._resizeDebounce = resizeDebounce;
858
872
  this._maxResizeDebounce = maxResizeDebounce;
873
+ this._useFractionalSize = useFractionalSize;
859
874
  this._externalRenderer = externalRenderer;
860
875
  this._renderExternal = renderExternal;
861
876
 
862
877
  // Create core components
863
- this._viewport = new Viewport(getElement(root));
878
+ this._viewport = new Viewport(this, getElement(root));
864
879
  this._autoResizer = new AutoResizer(this);
865
880
  this._renderer = this._createRenderer();
866
881
  this._camera = this._createCamera();
@@ -1069,6 +1084,10 @@ class Flicking extends Component<FlickingEvents> {
1069
1084
  return Promise.reject(new FlickingError(ERROR.MESSAGE.ANIMATION_ALREADY_PLAYING, ERROR.CODE.ANIMATION_ALREADY_PLAYING));
1070
1085
  }
1071
1086
 
1087
+ if (this._control.holding) {
1088
+ this._control.controller.release();
1089
+ }
1090
+
1072
1091
  return this._control.moveToPanel(panel, {
1073
1092
  duration,
1074
1093
  direction
@@ -1487,11 +1506,12 @@ class Flicking extends Component<FlickingEvents> {
1487
1506
  const renderer = this._renderer;
1488
1507
  const control = this._control;
1489
1508
  const camera = this._camera;
1490
- const initialPanel = renderer.getPanel(this._defaultIndex) || renderer.getPanel(0);
1509
+ const defaultPanel = renderer.getPanel(this._defaultIndex) || renderer.getPanel(0);
1491
1510
 
1492
- if (!initialPanel) return;
1511
+ if (!defaultPanel) return;
1493
1512
 
1494
- const nearestAnchor = camera.findNearestAnchor(initialPanel.position);
1513
+ const nearestAnchor = camera.findNearestAnchor(defaultPanel.position);
1514
+ const initialPanel = (nearestAnchor && defaultPanel.index !== nearestAnchor.panel.index) ? nearestAnchor.panel : defaultPanel;
1495
1515
  control.setActive(initialPanel, null, false);
1496
1516
 
1497
1517
  if (!nearestAnchor) {
@@ -202,6 +202,18 @@ class AxesController {
202
202
  return this;
203
203
  }
204
204
 
205
+ /**
206
+ * Releases ongoing user input (mouse/touch)
207
+ * @ko 사용자의 현재 입력(마우스/터치)를 중단시킵니다
208
+ * @chainable
209
+ * @return {this}
210
+ */
211
+ public release(): this {
212
+ this._panInput?.release();
213
+
214
+ return this;
215
+ }
216
+
205
217
  /**
206
218
  * Update {@link https://naver.github.io/egjs-axes/ @egjs/axes}'s state
207
219
  * @ko {@link https://naver.github.io/egjs-axes/ @egjs/axes}의 상태를 갱신합니다
@@ -161,6 +161,18 @@ abstract class Control {
161
161
  return this;
162
162
  }
163
163
 
164
+ /**
165
+ * Releases ongoing user input (mouse/touch)
166
+ * @ko 사용자의 현재 입력(마우스/터치)를 중단시킵니다
167
+ * @chainable
168
+ * @return {this}
169
+ */
170
+ public release(): this {
171
+ this._controller.release();
172
+
173
+ return this;
174
+ }
175
+
164
176
  /**
165
177
  * Update position after resizing
166
178
  * @ko resize 이후에 position을 업데이트합니다
@@ -2,13 +2,15 @@
2
2
  * Copyright (c) 2015 NAVER Corp.
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
- import { getStyle, isString } from "../utils";
5
+ import Flicking from "../Flicking";
6
+ import { getElementSize, getStyle, isString } from "../utils";
6
7
 
7
8
  /**
8
9
  * A component that manages viewport size
9
10
  * @ko 뷰포트 크기 정보를 담당하는 컴포넌트
10
11
  */
11
12
  class Viewport {
13
+ private _flicking: Flicking;
12
14
  private _el: HTMLElement;
13
15
  private _width: number;
14
16
  private _height: number;
@@ -57,7 +59,8 @@ class Viewport {
57
59
  /**
58
60
  * @param el A viewport element<ko>뷰포트 엘리먼트</ko>
59
61
  */
60
- public constructor(el: HTMLElement) {
62
+ public constructor(flicking: Flicking, el: HTMLElement) {
63
+ this._flicking = flicking;
61
64
  this._el = el;
62
65
  this._width = 0;
63
66
  this._height = 0;
@@ -120,9 +123,25 @@ class Viewport {
120
123
  public resize() {
121
124
  const el = this._el;
122
125
  const elStyle = getStyle(el);
126
+ const {
127
+ useFractionalSize
128
+ } = this._flicking;
129
+
130
+ this._width = getElementSize({
131
+ el,
132
+ horizontal: true,
133
+ useFractionalSize,
134
+ useOffset: false,
135
+ style: elStyle
136
+ });
137
+ this._height = getElementSize({
138
+ el,
139
+ horizontal: false,
140
+ useFractionalSize,
141
+ useOffset: false,
142
+ style: elStyle
143
+ });
123
144
 
124
- this._width = el.clientWidth;
125
- this._height = el.clientHeight;
126
145
  this._padding = {
127
146
  left: elStyle.paddingLeft ? parseFloat(elStyle.paddingLeft) : 0,
128
147
  right: elStyle.paddingRight ? parseFloat(elStyle.paddingRight) : 0,
@@ -3,7 +3,7 @@
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
5
  import Flicking from "../../Flicking";
6
- import { getProgress, getStyle, parseAlign, setSize } from "../../utils";
6
+ import { getElementSize, getProgress, getStyle, parseAlign, setSize } from "../../utils";
7
7
  import { ALIGN, DIRECTION } from "../../const/external";
8
8
  import { LiteralUnion, ValueOf } from "../../type/internal";
9
9
 
@@ -308,21 +308,37 @@ class Panel {
308
308
  */
309
309
  public resize(cached?: {
310
310
  size: number;
311
- height: number;
311
+ height?: number;
312
312
  margin: { prev: number; next: number };
313
313
  }): this {
314
314
  const el = this.element;
315
315
  const flicking = this._flicking;
316
- const horizontal = flicking.horizontal;
316
+ const {
317
+ horizontal,
318
+ useFractionalSize
319
+ } = flicking;
317
320
 
318
321
  if (cached) {
319
322
  this._size = cached.size;
320
323
  this._margin = { ...cached.margin };
321
- this._height = cached.height;
324
+ this._height = cached.height ?? getElementSize({
325
+ el,
326
+ horizontal: false,
327
+ useFractionalSize,
328
+ useOffset: true,
329
+ style: getStyle(el)
330
+ });
322
331
  } else {
323
332
  const elStyle = getStyle(el);
324
333
 
325
- this._size = horizontal ? el.offsetWidth : el.offsetHeight;
334
+ this._size = getElementSize({
335
+ el,
336
+ horizontal,
337
+ useFractionalSize,
338
+ useOffset: true,
339
+ style: elStyle
340
+ });
341
+
326
342
  this._margin = horizontal
327
343
  ? {
328
344
  prev: parseFloat(elStyle.marginLeft || "0"),
@@ -331,7 +347,16 @@ class Panel {
331
347
  prev: parseFloat(elStyle.marginTop || "0"),
332
348
  next: parseFloat(elStyle.marginBottom || "0")
333
349
  };
334
- this._height = horizontal ? el.offsetHeight : this._size;
350
+
351
+ this._height = horizontal
352
+ ? getElementSize({
353
+ el,
354
+ horizontal: false,
355
+ useFractionalSize,
356
+ useOffset: true,
357
+ style: elStyle
358
+ })
359
+ : this._size;
335
360
  }
336
361
 
337
362
  this.updatePosition();
@@ -496,8 +496,8 @@ abstract class Renderer {
496
496
  : { height: panelSize };
497
497
  const firstPanelSizeObj = {
498
498
  size: panelSize,
499
- height: referencePanel.height,
500
- margin: referencePanel.margin
499
+ margin: referencePanel.margin,
500
+ ...(!flicking.horizontal && { height: referencePanel.height})
501
501
  };
502
502
 
503
503
  if (!flicking.noPanelStyleOverride) {
package/src/utils.ts CHANGED
@@ -300,6 +300,48 @@ export const range = (end: number): number[] => {
300
300
  return arr;
301
301
  };
302
302
 
303
+ export const getElementSize = ({
304
+ el,
305
+ horizontal,
306
+ useFractionalSize,
307
+ useOffset,
308
+ style
309
+ }: {
310
+ el: HTMLElement;
311
+ horizontal: boolean;
312
+ useFractionalSize: boolean;
313
+ useOffset: boolean;
314
+ style: CSSStyleDeclaration;
315
+ }): number => {
316
+ if (useFractionalSize) {
317
+ const baseSize = parseFloat(horizontal ? style.width : style.height);
318
+ const isBorderBoxSizing = style.boxSizing === "border-box";
319
+ const border = horizontal
320
+ ? parseFloat(style.borderLeftWidth || "0") + parseFloat(style.borderRightWidth || "0")
321
+ : parseFloat(style.borderTopWidth || "0") + parseFloat(style.borderBottomWidth || "0");
322
+
323
+ if (isBorderBoxSizing) {
324
+ return useOffset
325
+ ? baseSize
326
+ : baseSize - border;
327
+ } else {
328
+ const padding = horizontal
329
+ ? parseFloat(style.paddingLeft || "0") + parseFloat(style.paddingRight || "0")
330
+ : parseFloat(style.paddingTop || "0") + parseFloat(style.paddingBottom || "0");
331
+
332
+ return useOffset
333
+ ? baseSize + padding + border
334
+ : baseSize + padding;
335
+ }
336
+ } else {
337
+ const sizeStr = horizontal ? "Width" : "Height";
338
+
339
+ return useOffset
340
+ ? el[`offset${sizeStr}`]
341
+ : el[`client${sizeStr}`];
342
+ }
343
+ };
344
+
303
345
  export const setPrototypeOf = Object.setPrototypeOf || ((obj, proto) => {
304
346
  obj.__proto__ = proto;
305
347
  return obj;