UNPKG

98.5 kBJavaScriptView Raw
1/*
2Copyright (c) 2021-present NAVER Corp.
3name: @egjs/grid
4license: MIT
5author: NAVER Corp.
6repository: https://github.com/naver/egjs-grid
7version: 1.6.0
8*/
9'use strict';
10
11var Component = require('@egjs/component');
12var ImReady = require('@egjs/imready');
13var childrenDiffer = require('@egjs/children-differ');
14
15/*! *****************************************************************************
16Copyright (c) Microsoft Corporation.
17
18Permission to use, copy, modify, and/or distribute this software for any
19purpose with or without fee is hereby granted.
20
21THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
23AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
24INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27PERFORMANCE OF THIS SOFTWARE.
28***************************************************************************** */
29
30/* global Reflect, Promise */
31var extendStatics = function (d, b) {
32 extendStatics = Object.setPrototypeOf || {
33 __proto__: []
34 } instanceof Array && function (d, b) {
35 d.__proto__ = b;
36 } || function (d, b) {
37 for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
38 };
39
40 return extendStatics(d, b);
41};
42
43function __extends(d, b) {
44 if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
45 extendStatics(d, b);
46
47 function __() {
48 this.constructor = d;
49 }
50
51 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
52}
53var __assign = function () {
54 __assign = Object.assign || function __assign(t) {
55 for (var s, i = 1, n = arguments.length; i < n; i++) {
56 s = arguments[i];
57
58 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
59 }
60
61 return t;
62 };
63
64 return __assign.apply(this, arguments);
65};
66function __decorate(decorators, target, key, desc) {
67 var c = arguments.length,
68 r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
69 d;
70 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
71 return c > 3 && r && Object.defineProperty(target, key, r), r;
72}
73/** @deprecated */
74
75function __spreadArrays() {
76 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
77
78 for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j];
79
80 return r;
81}
82
83var DEFAULT_GRID_OPTIONS = {
84 horizontal: false,
85 useTransform: false,
86 percentage: false,
87 isEqualSize: false,
88 isConstantSize: false,
89 gap: 0,
90 attributePrefix: "data-grid-",
91 resizeDebounce: 100,
92 maxResizeDebounce: 0,
93 autoResize: true,
94 preserveUIOnDestroy: false,
95 defaultDirection: "end",
96 externalContainerManager: null,
97 externalItemRenderer: null,
98 renderOnPropertyChange: true,
99 useFit: true
100};
101var PROPERTY_TYPE;
102
103(function (PROPERTY_TYPE) {
104 PROPERTY_TYPE[PROPERTY_TYPE["PROPERTY"] = 1] = "PROPERTY";
105 PROPERTY_TYPE[PROPERTY_TYPE["RENDER_PROPERTY"] = 2] = "RENDER_PROPERTY";
106})(PROPERTY_TYPE || (PROPERTY_TYPE = {}));
107
108var MOUNT_STATE;
109
110(function (MOUNT_STATE) {
111 MOUNT_STATE[MOUNT_STATE["UNCHECKED"] = 1] = "UNCHECKED";
112 MOUNT_STATE[MOUNT_STATE["UNMOUNTED"] = 2] = "UNMOUNTED";
113 MOUNT_STATE[MOUNT_STATE["MOUNTED"] = 3] = "MOUNTED";
114})(MOUNT_STATE || (MOUNT_STATE = {}));
115
116var UPDATE_STATE;
117
118(function (UPDATE_STATE) {
119 UPDATE_STATE[UPDATE_STATE["NEED_UPDATE"] = 1] = "NEED_UPDATE";
120 UPDATE_STATE[UPDATE_STATE["WAIT_LOADING"] = 2] = "WAIT_LOADING";
121 UPDATE_STATE[UPDATE_STATE["UPDATED"] = 3] = "UPDATED";
122})(UPDATE_STATE || (UPDATE_STATE = {}));
123
124var GRID_PROPERTY_TYPES = {
125 gap: PROPERTY_TYPE.RENDER_PROPERTY,
126 defaultDirection: PROPERTY_TYPE.PROPERTY,
127 renderOnPropertyChange: PROPERTY_TYPE.PROPERTY,
128 preserveUIOnDestroy: PROPERTY_TYPE.PROPERTY,
129 useFit: PROPERTY_TYPE.PROPERTY
130};
131var GRID_METHODS = ["syncElements", "updateItems", "getItems", "setItems", "renderItems", "getContainerInlineSize", "getContainerElement"];
132var GRID_EVENTS = ["renderComplete", "contentError"];
133var RECT_NAMES = {
134 horizontal: {
135 inlinePos: "top",
136 contentPos: "left",
137 inlineSize: "height",
138 contentSize: "width"
139 },
140 vertical: {
141 inlinePos: "left",
142 contentPos: "top",
143 inlineSize: "width",
144 contentSize: "height"
145 }
146};
147
148var ContainerManager =
149/*#__PURE__*/
150function (_super) {
151 __extends(ContainerManager, _super);
152
153 function ContainerManager(container, options) {
154 var _this = _super.call(this) || this;
155
156 _this.container = container;
157 _this._resizeTimer = 0;
158 _this._maxResizeDebounceTimer = 0;
159
160 _this._onResize = function () {
161 clearTimeout(_this._resizeTimer);
162 clearTimeout(_this._maxResizeDebounceTimer);
163 _this._maxResizeDebounceTimer = 0;
164 _this._resizeTimer = 0;
165
166 _this.trigger("resize");
167 };
168
169 _this._scheduleResize = function () {
170 var _a = _this.options,
171 resizeDebounce = _a.resizeDebounce,
172 maxResizeDebounce = _a.maxResizeDebounce;
173
174 if (!_this._maxResizeDebounceTimer && maxResizeDebounce >= resizeDebounce) {
175 _this._maxResizeDebounceTimer = window.setTimeout(_this._onResize, maxResizeDebounce);
176 }
177
178 if (_this._resizeTimer) {
179 clearTimeout(_this._resizeTimer);
180 _this._resizeTimer = 0;
181 }
182
183 _this._resizeTimer = window.setTimeout(_this._onResize, resizeDebounce);
184 };
185
186 _this.options = __assign({
187 horizontal: DEFAULT_GRID_OPTIONS.horizontal,
188 autoResize: DEFAULT_GRID_OPTIONS.autoResize,
189 resizeDebounce: DEFAULT_GRID_OPTIONS.resizeDebounce,
190 maxResizeDebounce: DEFAULT_GRID_OPTIONS.maxResizeDebounce
191 }, options);
192
193 _this._init();
194
195 return _this;
196 }
197
198 var __proto = ContainerManager.prototype;
199
200 __proto.resize = function () {
201 var container = this.container;
202 this.setRect({
203 width: container.clientWidth,
204 height: container.clientHeight
205 });
206 };
207
208 __proto.getRect = function () {
209 return this.rect;
210 };
211
212 __proto.setRect = function (rect) {
213 this.rect = __assign({}, rect);
214 };
215
216 __proto.getInlineSize = function () {
217 return this.rect[this.options.horizontal ? "height" : "width"];
218 };
219
220 __proto.getContentSize = function () {
221 return this.rect[this.options.horizontal ? "width" : "height"];
222 };
223
224 __proto.getStatus = function () {
225 return {
226 rect: __assign({}, this.rect)
227 };
228 };
229
230 __proto.setStatus = function (status) {
231 this.rect = __assign({}, status.rect);
232 this.setContentSize(this.getContentSize());
233 };
234
235 __proto.setContentSize = function (size) {
236 var sizeName = this.options.horizontal ? "width" : "height";
237 this.rect[sizeName] = size;
238 this.container.style[sizeName] = size + "px";
239 };
240
241 __proto.destroy = function (options) {
242 if (options === void 0) {
243 options = {};
244 }
245
246 window.removeEventListener("resize", this._scheduleResize);
247
248 if (!options.preserveUI) {
249 this.container.style.cssText = this.orgCSSText;
250 }
251 };
252
253 __proto._init = function () {
254 var container = this.container;
255 var style = window.getComputedStyle(container);
256 this.orgCSSText = container.style.cssText;
257
258 if (style.position === "static") {
259 container.style.position = "relative";
260 }
261
262 if (this.options.autoResize) {
263 window.addEventListener("resize", this._scheduleResize);
264 }
265 };
266
267 return ContainerManager;
268}(Component);
269
270function getKeys(obj) {
271 return Object.keys(obj);
272}
273function isString(val) {
274 return typeof val === "string";
275}
276function isObject(val) {
277 return typeof val === "object";
278}
279function isNumber(val) {
280 return typeof val === "number";
281}
282function camelize(str) {
283 return str.replace(/[\s-_]([a-z])/g, function (all, letter) {
284 return letter.toUpperCase();
285 });
286}
287function getDataAttributes(element, attributePrefix) {
288 var dataAttributes = {};
289 var attributes = element.attributes;
290 var length = attributes.length;
291
292 for (var i = 0; i < length; ++i) {
293 var attribute = attributes[i];
294 var name = attribute.name,
295 value = attribute.value;
296
297 if (name.indexOf(attributePrefix) === -1) {
298 continue;
299 }
300
301 dataAttributes[camelize(name.replace(attributePrefix, ""))] = value;
302 }
303
304 return dataAttributes;
305}
306/* Class Decorator */
307
308function GetterSetter(component) {
309 var prototype = component.prototype,
310 propertyTypes = component.propertyTypes;
311
312 var _loop_1 = function (name) {
313 var shouldRender = propertyTypes[name] === PROPERTY_TYPE.RENDER_PROPERTY;
314 var descriptor = Object.getOwnPropertyDescriptor(prototype, name) || {};
315
316 var getter = descriptor.get || function get() {
317 return this.options[name];
318 };
319
320 var setter = descriptor.set || function set(value) {
321 var options = this.options;
322 var prevValue = options[name];
323
324 if (prevValue === value) {
325 return;
326 }
327
328 options[name] = value;
329
330 if (shouldRender && options.renderOnPropertyChange) {
331 this.scheduleRender();
332 }
333 };
334
335 var attributes = {
336 enumerable: true,
337 configurable: true,
338 get: getter,
339 set: setter
340 };
341 Object.defineProperty(prototype, name, attributes);
342 };
343
344 for (var name in propertyTypes) {
345 _loop_1(name);
346 }
347}
348function withMethods(methods) {
349 return function (prototype, memberName) {
350 methods.forEach(function (name) {
351 if (name in prototype) {
352 return;
353 }
354
355 prototype[name] = function () {
356 var _a;
357
358 var args = [];
359
360 for (var _i = 0; _i < arguments.length; _i++) {
361 args[_i] = arguments[_i];
362 }
363
364 var result = (_a = this[memberName])[name].apply(_a, args); // fix `this` type to return your own `class` instance to the instance using the decorator.
365
366
367 if (result === this[memberName]) {
368 return this;
369 } else {
370 return result;
371 }
372 };
373 });
374 };
375}
376function range(length) {
377 var arr = [];
378
379 for (var i = 0; i < length; ++i) {
380 arr.push(i);
381 }
382
383 return arr;
384}
385function getRangeCost(value, valueRange) {
386 return Math.max(value - valueRange[1], valueRange[0] - value, 0) + 1;
387}
388/**
389 * Decorator that makes the method of grid available in the framework.
390 * @ko 프레임워크에서 그리드의 메소드를 사용할 수 있게 하는 데코레이터.
391 * @memberof eg.Grid
392 * @private
393 * @example
394 * ```js
395 * import { withGridMethods } from "@egjs/grid";
396 *
397 * class Grid extends React.Component<Partial<GridProps & GridOptions>> {
398 * &#64;withGridMethods
399 * private grid: NativeGrid;
400 * }
401 * ```
402 */
403
404var withGridMethods = withMethods(GRID_METHODS);
405
406var ItemRenderer =
407/*#__PURE__*/
408function () {
409 function ItemRenderer(options) {
410 this.initialRect = null;
411 this.sizePercetage = false;
412 this.posPercetage = false;
413 this.options = __assign({
414 attributePrefix: DEFAULT_GRID_OPTIONS.attributePrefix,
415 useTransform: DEFAULT_GRID_OPTIONS.useTransform,
416 horizontal: DEFAULT_GRID_OPTIONS.horizontal,
417 percentage: DEFAULT_GRID_OPTIONS.percentage,
418 isEqualSize: DEFAULT_GRID_OPTIONS.isEqualSize,
419 isConstantSize: DEFAULT_GRID_OPTIONS.isConstantSize
420 }, options);
421
422 this._init();
423 }
424
425 var __proto = ItemRenderer.prototype;
426
427 __proto.resize = function () {
428 this.initialRect = null;
429 };
430
431 __proto.renderItems = function (items) {
432 var _this = this;
433
434 items.forEach(function (item) {
435 _this._renderItem(item);
436 });
437 };
438
439 __proto.getInlineSize = function () {
440 return this.containerRect[this.options.horizontal ? "height" : "width"];
441 };
442
443 __proto.setContainerRect = function (rect) {
444 this.containerRect = rect;
445 };
446
447 __proto.updateItems = function (items) {
448 var _this = this;
449
450 items.forEach(function (item) {
451 _this._updateItem(item);
452 });
453 };
454
455 __proto.getStatus = function () {
456 return {
457 initialRect: this.initialRect
458 };
459 };
460
461 __proto.setStatus = function (status) {
462 this.initialRect = status.initialRect;
463 };
464
465 __proto._init = function () {
466 var percentage = this.options.percentage;
467 var sizePercentage = false;
468 var posPercentage = false;
469
470 if (percentage === true) {
471 sizePercentage = true;
472 posPercentage = true;
473 } else if (percentage) {
474 if (percentage.indexOf("position") > -1) {
475 posPercentage = true;
476 }
477
478 if (percentage.indexOf("size") > -1) {
479 sizePercentage = true;
480 }
481 }
482
483 this.posPercetage = posPercentage;
484 this.sizePercetage = sizePercentage;
485 };
486
487 __proto._updateItem = function (item) {
488 var _a = this.options,
489 isEqualSize = _a.isEqualSize,
490 isConstantSize = _a.isConstantSize;
491 var initialRect = this.initialRect;
492 var orgRect = item.orgRect,
493 element = item.element;
494 var isLoading = item.updateState === UPDATE_STATE.WAIT_LOADING;
495 var hasOrgSize = orgRect && orgRect.width && orgRect.height;
496 var rect;
497
498 if (isEqualSize && initialRect) {
499 rect = initialRect;
500 } else if (isConstantSize && hasOrgSize && !isLoading) {
501 rect = orgRect;
502 } else if (!element) {
503 return;
504 } else {
505 rect = {
506 left: element.offsetLeft,
507 top: element.offsetTop,
508 width: element.offsetWidth,
509 height: element.offsetHeight
510 };
511 }
512
513 if (!item.isFirstUpdate) {
514 item.orgRect = __assign({}, rect);
515 }
516
517 item.rect = __assign({}, rect);
518
519 if (item.element) {
520 item.mountState = MOUNT_STATE.MOUNTED;
521 }
522
523 if (item.updateState === UPDATE_STATE.NEED_UPDATE) {
524 item.updateState = UPDATE_STATE.UPDATED;
525 item.isFirstUpdate = true;
526 }
527
528 item.attributes = element ? getDataAttributes(element, this.options.attributePrefix) : {};
529
530 if (!isLoading) {
531 this.initialRect = __assign({}, rect);
532 }
533
534 return rect;
535 };
536
537 __proto._renderItem = function (item) {
538 var element = item.element;
539 var cssRect = item.cssRect;
540
541 if (!element || !cssRect) {
542 return;
543 }
544
545 var _a = this.options,
546 horizontal = _a.horizontal,
547 useTransform = _a.useTransform;
548 var posPercentage = this.posPercetage;
549 var sizePercentage = this.sizePercetage;
550 var cssTexts = ["position: absolute;"];
551 var _b = RECT_NAMES[horizontal ? "horizontal" : "vertical"],
552 sizeName = _b.inlineSize,
553 posName = _b.inlinePos;
554 var inlineSize = this.getInlineSize();
555 var keys = getKeys(cssRect);
556
557 if (useTransform) {
558 keys = keys.filter(function (key) {
559 return key !== "top" && key !== "left";
560 });
561 cssTexts.push("transform: " + ("translate(" + (cssRect.left || 0) + "px, " + (cssRect.top || 0) + "px);"));
562 }
563
564 cssTexts.push.apply(cssTexts, keys.map(function (name) {
565 var value = cssRect[name];
566
567 if (name === sizeName && sizePercentage || name === posName && posPercentage) {
568 return name + ": " + value / inlineSize * 100 + "%;";
569 }
570
571 return name + ": " + value + "px;";
572 }));
573 element.style.cssText += cssTexts.join("");
574 };
575
576 return ItemRenderer;
577}();
578
579/**
580 * @memberof Grid
581 * @implements Grid.GridItem.GridItemStatus
582 */
583
584var GridItem =
585/*#__PURE__*/
586function () {
587 /**
588 * @constructor
589 * @param horizontal - Direction of the scroll movement. (true: horizontal, false: vertical) <ko>스크롤 이동 방향. (true: 가로방향, false: 세로방향)</ko>
590 * @param itemStatus - Default status object of GridItem module. <ko>GridItem 모듈의 기본 status 객체.</ko>
591 */
592 function GridItem(horizontal, itemStatus) {
593 if (itemStatus === void 0) {
594 itemStatus = {};
595 }
596
597 var _a;
598
599 this.horizontal = horizontal;
600 this.isUpdate = false;
601 this.hasTransition = false;
602 this.transitionDuration = "";
603 var element = itemStatus.element;
604
605 var status = __assign({
606 key: "",
607 orgRect: {
608 left: 0,
609 top: 0,
610 width: 0,
611 height: 0
612 },
613 rect: {
614 left: 0,
615 top: 0,
616 width: 0,
617 height: 0
618 },
619 cssRect: {},
620 attributes: {},
621 data: {},
622 isFirstUpdate: false,
623 mountState: MOUNT_STATE.UNCHECKED,
624 updateState: UPDATE_STATE.NEED_UPDATE,
625 element: element || null,
626 orgCSSText: (_a = element === null || element === void 0 ? void 0 : element.style.cssText) !== null && _a !== void 0 ? _a : "",
627 gridData: {}
628 }, itemStatus);
629
630 for (var name in status) {
631 this[name] = status[name];
632 }
633 }
634
635 var __proto = GridItem.prototype;
636 Object.defineProperty(__proto, "orgInlineSize", {
637 /**
638 * The size in inline direction before first rendering. "width" if horizontal is false, "height" otherwise.
639 * @ko 첫 렌더링 되기 전의 inline 방향의 사이즈. horizontal이 false면 "width", 아니면 "height".
640 * @member Grid.GridItem#orgInlineSize
641 */
642 get: function () {
643 var orgRect = this.orgRect || this.rect;
644 return this.horizontal ? orgRect.height : orgRect.width;
645 },
646 enumerable: false,
647 configurable: true
648 });
649 Object.defineProperty(__proto, "orgContentSize", {
650 /**
651 * The size in content direction before first rendering. "height" if horizontal is false, "width" otherwise.
652 * @ko 첫 렌더링 되기 전의 content 방향의 사이즈. horizontal이 false면 "height", 아니면 "width".
653 * @member Grid.GridItem#orgContentSize
654 */
655 get: function () {
656 var orgRect = this.orgRect || this.rect;
657 return this.horizontal ? orgRect.width : orgRect.height;
658 },
659 enumerable: false,
660 configurable: true
661 });
662 Object.defineProperty(__proto, "inlineSize", {
663 /**
664 * The size in inline direction. "width" if horizontal is false, "height" otherwise.
665 * @ko inline 방향의 사이즈. horizontal이 false면 "width", 아니면 "height".
666 * @member Grid.GridItem#inlineSize
667 */
668 get: function () {
669 var rect = this.rect;
670 return this.horizontal ? rect.height : rect.width;
671 },
672 enumerable: false,
673 configurable: true
674 });
675 Object.defineProperty(__proto, "contentSize", {
676 /**
677 * The size in content direction. "height" if horizontal is false, "width" otherwise.
678 * @ko content 방향의 사이즈. horizontal이 false면 "height", 아니면 "width".
679 * @member Grid.GridItem#contentSize
680 */
681 get: function () {
682 var rect = this.rect;
683 return this.horizontal ? rect.width : rect.height;
684 },
685 enumerable: false,
686 configurable: true
687 });
688 Object.defineProperty(__proto, "cssInlineSize", {
689 /**
690 * The CSS size in inline direction applied to the Grid. "width" if horizontal is false, "height" otherwise.
691 * @ko Grid에 적용된 inline 방향의 CSS 사이즈. horizontal이 false면 "width", 아니면 "height".
692 * @member Grid.GridItem#cssInlineSize
693 */
694 get: function () {
695 var cssRect = this.cssRect;
696 return this.horizontal ? cssRect.height : cssRect.width;
697 },
698 set: function (inlineSize) {
699 var cssRect = this.cssRect;
700 cssRect[this.horizontal ? "height" : "width"] = inlineSize;
701 },
702 enumerable: false,
703 configurable: true
704 });
705 Object.defineProperty(__proto, "cssContentSize", {
706 /**
707 * The CSS size in content direction applied to the Grid. "height" if horizontal is false, "width" otherwise.
708 * @ko Grid에 적용된 content 방향의 CSS 사이즈. horizontal이 false면 "height", 아니면 "width".
709 * @member Grid.GridItem#cssContentSize
710 */
711 get: function () {
712 var cssRect = this.cssRect;
713 return this.horizontal ? cssRect.width : cssRect.height;
714 },
715 set: function (contentSize) {
716 var cssRect = this.cssRect;
717 cssRect[this.horizontal ? "width" : "height"] = contentSize;
718 },
719 enumerable: false,
720 configurable: true
721 });
722 Object.defineProperty(__proto, "cssInlinePos", {
723 /**
724 * The CSS pos in inline direction applied to the Grid. "left" if horizontal is false, "top" otherwise.
725 * @ko Grid에 적용된 inline 방향의 CSS 포지션. horizontal이 false면 "left", 아니면 "top".
726 * @member Grid.GridItem#cssInlinePos
727 */
728 get: function () {
729 var cssRect = this.cssRect;
730 return this.horizontal ? cssRect.top : cssRect.left;
731 },
732 set: function (inlinePos) {
733 var cssRect = this.cssRect;
734 cssRect[this.horizontal ? "top" : "left"] = inlinePos;
735 },
736 enumerable: false,
737 configurable: true
738 });
739 Object.defineProperty(__proto, "cssContentPos", {
740 /**
741 * The CSS pos in content direction applied to the Grid. "top" if horizontal is false, "left" otherwise.
742 * @ko Grid에 적용된 content 방향의 CSS 포지션. horizontal이 false면 "top", 아니면 "left".
743 * @member Grid.GridItem#cssContentPos
744 */
745 get: function () {
746 var cssRect = this.cssRect;
747 return this.horizontal ? cssRect.left : cssRect.top;
748 },
749 set: function (contentPos) {
750 var cssRect = this.cssRect;
751 cssRect[this.horizontal ? "left" : "top"] = contentPos;
752 },
753 enumerable: false,
754 configurable: true
755 });
756 /**
757 * Set CSS Rect through GridRect.
758 * @ko GridRect을 통해 CSS Rect를 설정한다.
759 * @param - The style for setting CSS rect. <ko>CSS rect를 설정하기 위한 스타일.</ko>
760 */
761
762 __proto.setCSSGridRect = function (gridRect) {
763 var names = RECT_NAMES[this.horizontal ? "horizontal" : "vertical"];
764 var rect = {};
765
766 for (var name in gridRect) {
767 rect[names[name]] = gridRect[name];
768 }
769
770 this.cssRect = rect;
771 };
772 /**
773 * Returns the status of the item.
774 * @ko 아이템의 상태를 반환한다.
775 */
776
777
778 __proto.getStatus = function () {
779 return {
780 mountState: this.mountState,
781 updateState: this.updateState,
782 attributes: this.attributes,
783 orgCSSText: this.orgCSSText,
784 isFirstUpdate: this.isFirstUpdate,
785 element: null,
786 key: this.key,
787 orgRect: this.orgRect,
788 rect: this.rect,
789 cssRect: this.cssRect,
790 gridData: this.gridData,
791 data: this.data
792 };
793 };
794 /**
795 * Returns minimized status of the item.
796 * @ko 아이템의 간소화된 상태를 반환한다.
797 */
798
799
800 __proto.getMinimizedStatus = function () {
801 var status = {
802 orgRect: this.orgRect,
803 rect: this.rect,
804 cssRect: this.cssRect,
805 attributes: this.attributes,
806 gridData: this.gridData
807 };
808
809 if (typeof this.key !== "undefined") {
810 status.key = this.key;
811 }
812
813 if (this.mountState !== MOUNT_STATE.UNCHECKED) {
814 status.mountState = this.mountState;
815 }
816
817 if (this.updateState !== UPDATE_STATE.NEED_UPDATE) {
818 status.updateState = this.updateState;
819 }
820
821 if (this.isFirstUpdate) {
822 status.isFirstUpdate = true;
823 }
824
825 if (this.orgCSSText) {
826 status.orgCSSText = this.orgCSSText;
827 }
828
829 return status;
830 };
831
832 return GridItem;
833}();
834
835/**
836 * @extends eg.Component
837 */
838
839var Grid =
840/*#__PURE__*/
841function (_super) {
842 __extends(Grid, _super);
843 /**
844 * @param - A base element for a module <ko>모듈을 적용할 기준 엘리먼트</ko>
845 * @param - The option object of the Grid module <ko>Grid 모듈의 옵션 객체</ko>
846 */
847
848
849 function Grid(containerElement, options) {
850 if (options === void 0) {
851 options = {};
852 }
853
854 var _this = _super.call(this) || this;
855
856 _this.items = [];
857 _this.outlines = {
858 start: [],
859 end: []
860 };
861 _this._renderTimer = 0;
862
863 _this._onResize = function () {
864 _this.renderItems({
865 useResize: true
866 });
867 };
868
869 _this.options = __assign(__assign({}, _this.constructor.defaultOptions), options);
870 _this.containerElement = isString(containerElement) ? document.querySelector(containerElement) : containerElement;
871 var _a = _this.options,
872 isEqualSize = _a.isEqualSize,
873 isConstantSize = _a.isConstantSize,
874 useTransform = _a.useTransform,
875 horizontal = _a.horizontal,
876 percentage = _a.percentage,
877 externalContainerManager = _a.externalContainerManager,
878 externalItemRenderer = _a.externalItemRenderer,
879 resizeDebounce = _a.resizeDebounce,
880 maxResizeDebounce = _a.maxResizeDebounce,
881 autoResize = _a.autoResize; // TODO: 테스트용 설정
882
883 _this.containerManager = externalContainerManager || new ContainerManager(_this.containerElement, {
884 horizontal: horizontal,
885 resizeDebounce: resizeDebounce,
886 maxResizeDebounce: maxResizeDebounce,
887 autoResize: autoResize
888 }).on("resize", _this._onResize);
889 _this.itemRenderer = externalItemRenderer || new ItemRenderer({
890 useTransform: useTransform,
891 isEqualSize: isEqualSize,
892 isConstantSize: isConstantSize,
893 percentage: percentage
894 });
895
896 _this._init();
897
898 return _this;
899 }
900
901 var __proto = Grid.prototype;
902 Grid_1 = Grid;
903 /**
904 * Return Container Element.
905 * @ko 컨테이너 엘리먼트를 반환한다.
906 */
907
908 __proto.getContainerElement = function () {
909 return this.containerElement;
910 };
911 /**
912 * Return items.
913 * @ko 아이템들을 반환한다.
914 */
915
916
917 __proto.getItems = function () {
918 return this.items;
919 };
920 /**
921 * Returns the children of the container element.
922 * @ko 컨테이너 엘리먼트의 children을 반환한다.
923 */
924
925
926 __proto.getChildren = function () {
927 return [].slice.call(this.containerElement.children);
928 };
929 /**
930 * Set items.
931 * @ko 아이템들을 설정한다.
932 * @param items - The items to set. <ko>설정할 아이템들</ko>
933 */
934
935
936 __proto.setItems = function (items) {
937 this.items = items;
938 return this;
939 };
940 /**
941 * Gets the container's inline size. ("width" if horizontal is false, otherwise "height")
942 * @ko container의 inline 사이즈를 가져온다. (horizontal이 false면 "width", 아니면 "height")
943 */
944
945
946 __proto.getContainerInlineSize = function () {
947 return this.containerManager.getInlineSize();
948 };
949 /**
950 * Returns the outlines of the start and end of the Grid.
951 * @ko Grid의 처음과 끝의 outline을 반환한다.
952 */
953
954
955 __proto.getOutlines = function () {
956 return this.outlines;
957 };
958 /**
959 * Set outlines.
960 * @ko 아웃라인을 설정한다.
961 * @param outlines - The outlines to set. <ko>설정할 아웃라인.</ko>
962 */
963
964
965 __proto.setOutlines = function (outlines) {
966 this.outlines = outlines;
967 return this;
968 };
969 /**
970 * When elements change, it synchronizes and renders items.
971 * @ko elements가 바뀐 경우 동기화를 하고 렌더링을 한다.
972 * @param - Options for rendering. <ko>렌더링을 하기 위한 옵션.</ko>
973 */
974
975
976 __proto.syncElements = function (options) {
977 if (options === void 0) {
978 options = {};
979 }
980
981 var items = this.items;
982 var horizontal = this.options.horizontal;
983 var elements = this.getChildren();
984
985 var _a = childrenDiffer.diff(this.items.map(function (item) {
986 return item.element;
987 }), elements),
988 added = _a.added,
989 maintained = _a.maintained,
990 changed = _a.changed,
991 removed = _a.removed;
992
993 var nextItems = [];
994 maintained.forEach(function (_a) {
995 var beforeIndex = _a[0],
996 afterIndex = _a[1];
997 nextItems[afterIndex] = items[beforeIndex];
998 });
999 added.forEach(function (index) {
1000 nextItems[index] = new GridItem(horizontal, {
1001 element: elements[index]
1002 });
1003 });
1004 this.setItems(nextItems);
1005
1006 if (added.length || removed.length || changed.length) {
1007 this.renderItems(options);
1008 }
1009
1010 return this;
1011 };
1012 /**
1013 * Update the size of the items and render them.
1014 * @ko 아이템들의 사이즈를 업데이트하고 렌더링을 한다.
1015 * @param - Items to be updated. <ko>업데이트할 아이템들.</ko>
1016 * @param - Options for rendering. <ko>렌더링을 하기 위한 옵션.</ko>
1017 */
1018
1019
1020 __proto.updateItems = function (items, options) {
1021 if (items === void 0) {
1022 items = this.items;
1023 }
1024
1025 if (options === void 0) {
1026 options = {};
1027 }
1028
1029 items.forEach(function (item) {
1030 item.updateState = UPDATE_STATE.NEED_UPDATE;
1031 });
1032 this.checkReady(options);
1033 return this;
1034 };
1035 /**
1036 * Rearrange items to fit the grid and render them. When rearrange is complete, the `renderComplete` event is fired.
1037 * @ko grid에 맞게 아이템을 재배치하고 렌더링을 한다. 배치가 완료되면 `renderComplete` 이벤트가 발생한다.
1038 * @param - Options for rendering. <ko>렌더링을 하기 위한 옵션.</ko>
1039 * @example
1040 * ```js
1041 * import { MasonryGrid } from "@egjs/grid";
1042 * const grid = new MasonryGrid();
1043 *
1044 * grid.on("renderComplete", e => {
1045 * console.log(e);
1046 * });
1047 * grid.renderItems();
1048 * ```
1049 */
1050
1051
1052 __proto.renderItems = function (options) {
1053 if (options === void 0) {
1054 options = {};
1055 }
1056
1057 this._clearRenderTimer();
1058
1059 if (!this.getItems().length && this.getChildren().length) {
1060 this.syncElements(options);
1061 } else if (options.useResize) {
1062 // Resize container and Update all items
1063 this._resizeContainer();
1064
1065 this.updateItems(this.items, options);
1066 } else {
1067 // Update only items that need to be updated.
1068 this.checkReady(options);
1069 }
1070
1071 return this;
1072 };
1073 /**
1074 * Returns current status such as item's position, size. The returned status can be restored with the setStatus() method.
1075 * @ko 아이템의 위치, 사이즈 등 현재 상태를 반환한다. 반환한 상태는 setStatus() 메서드로 복원할 수 있다.
1076 * @param - Whether to minimize the status of the item. (default: false) <ko>item의 status를 최소화할지 여부. (default: false)</ko>
1077 */
1078
1079
1080 __proto.getStatus = function (minimize) {
1081 return {
1082 outlines: this.outlines,
1083 items: this.items.map(function (item) {
1084 return minimize ? item.getMinimizedStatus() : item.getStatus();
1085 }),
1086 containerManager: this.containerManager.getStatus(),
1087 itemRenderer: this.itemRenderer.getStatus()
1088 };
1089 };
1090 /**
1091 * Set status of the Grid module with the status returned through a call to the getStatus() method.
1092 * @ko getStatus() 메서드에 대한 호출을 통해 반환된 상태로 Grid 모듈의 상태를 설정한다.
1093 */
1094
1095
1096 __proto.setStatus = function (status) {
1097 var _this = this;
1098
1099 var horizontal = this.options.horizontal;
1100 var containerManager = this.containerManager;
1101 var prevInlineSize = containerManager.getInlineSize();
1102 var children = this.getChildren();
1103 this.itemRenderer.setStatus(status.itemRenderer);
1104 containerManager.setStatus(status.containerManager);
1105 this.outlines = status.outlines;
1106 this.items = status.items.map(function (item, i) {
1107 return new GridItem(horizontal, __assign(__assign({}, item), {
1108 element: children[i]
1109 }));
1110 });
1111 this.itemRenderer.renderItems(this.items);
1112
1113 if (prevInlineSize !== containerManager.getInlineSize()) {
1114 this.renderItems({
1115 useResize: true
1116 });
1117 } else {
1118 window.setTimeout(function () {
1119 _this._renderComplete({
1120 direction: _this.defaultDirection,
1121 mounted: _this.items,
1122 updated: [],
1123 isResize: false
1124 });
1125 });
1126 }
1127
1128 return this;
1129 };
1130 /**
1131 * Releases the instnace and events and returns the CSS of the container and elements.
1132 * @ko 인스턴스와 이벤트를 해제하고 컨테이너와 엘리먼트들의 CSS를 되돌린다.
1133 * @param Options for destroy. <ko>destory()를 위한 옵션</ko>
1134 */
1135
1136
1137 __proto.destroy = function (options) {
1138 var _a;
1139
1140 if (options === void 0) {
1141 options = {};
1142 }
1143
1144 var _b = options.preserveUI,
1145 preserveUI = _b === void 0 ? this.options.preserveUIOnDestroy : _b;
1146 this.containerManager.destroy({
1147 preserveUI: preserveUI
1148 });
1149
1150 if (!preserveUI) {
1151 this.items.forEach(function (_a) {
1152 var element = _a.element,
1153 orgCSSText = _a.orgCSSText;
1154
1155 if (element) {
1156 element.style.cssText = orgCSSText;
1157 }
1158 });
1159 }
1160
1161 (_a = this._im) === null || _a === void 0 ? void 0 : _a.destroy();
1162 };
1163
1164 __proto.checkReady = function (options) {
1165 var _this = this;
1166
1167 var _a;
1168
1169 if (options === void 0) {
1170 options = {};
1171 } // Grid: renderItems => checkReady => readyItems => applyGrid
1172
1173
1174 var items = this.items;
1175 var updated = items.filter(function (item) {
1176 var _a;
1177
1178 return ((_a = item.element) === null || _a === void 0 ? void 0 : _a.parentNode) && item.updateState !== UPDATE_STATE.UPDATED;
1179 });
1180 var mounted = updated.filter(function (item) {
1181 return item.mountState !== MOUNT_STATE.MOUNTED;
1182 });
1183 var moreUpdated = [];
1184 mounted.filter(function (item) {
1185 if (item.hasTransition) {
1186 return true;
1187 } else {
1188 var element = item.element;
1189 var transitionDuration = parseFloat(getComputedStyle(element).transitionDuration);
1190
1191 if (transitionDuration > 0) {
1192 item.hasTransition = true;
1193 item.transitionDuration = element.style.transitionDuration;
1194 return true;
1195 }
1196 }
1197
1198 return false;
1199 }).forEach(function (item) {
1200 item.element.style.transitionDuration = "0s";
1201 });
1202 (_a = this._im) === null || _a === void 0 ? void 0 : _a.destroy();
1203 this._im = new ImReady({
1204 prefix: this.options.attributePrefix
1205 }).on("preReadyElement", function (e) {
1206 updated[e.index].updateState = UPDATE_STATE.WAIT_LOADING;
1207 }).on("preReady", function () {
1208 _this.itemRenderer.updateItems(updated);
1209
1210 _this.readyItems(mounted, updated, options);
1211 }).on("readyElement", function (e) {
1212 var item = updated[e.index];
1213 item.updateState = UPDATE_STATE.NEED_UPDATE; // after preReady
1214
1215 if (e.isPreReadyOver) {
1216 item.element.style.cssText = item.orgCSSText;
1217
1218 _this.itemRenderer.updateItems([item]);
1219
1220 _this.readyItems([], [item], options);
1221 }
1222 }).on("error", function (e) {
1223 var item = items[e.index];
1224 /**
1225 * This event is fired when an error occurs in the content.
1226 * @ko 콘텐츠 로드에 에러가 날 때 발생하는 이벤트.
1227 * @event Grid#contentError
1228 * @param {Grid.OnContentError} e - The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
1229 * @example
1230 * ```js
1231 * grid.on("contentError", e => {
1232 * e.update();
1233 * });
1234 * ```
1235 */
1236
1237 _this.trigger("contentError", {
1238 element: e.element,
1239 target: e.target,
1240 item: item,
1241 update: function () {
1242 moreUpdated.push(item);
1243 }
1244 });
1245 }).on("ready", function () {
1246 if (moreUpdated.length) {
1247 _this.updateItems(moreUpdated);
1248 }
1249 }).check(updated.map(function (item) {
1250 return item.element;
1251 }));
1252 };
1253
1254 __proto.scheduleRender = function () {
1255 var _this = this;
1256
1257 this._clearRenderTimer();
1258
1259 this._renderTimer = window.setTimeout(function () {
1260 _this.renderItems();
1261 });
1262 };
1263
1264 __proto.fitOutlines = function (useFit) {
1265 if (useFit === void 0) {
1266 useFit = this.useFit;
1267 }
1268
1269 var outlines = this.outlines;
1270 var startOutline = outlines.start;
1271 var endOutline = outlines.end;
1272 var outlineOffset = startOutline.length ? Math.min.apply(Math, startOutline) : 0; // If the outline is less than 0, a fit occurs forcibly.
1273
1274 if (!useFit && outlineOffset > 0) {
1275 return;
1276 }
1277
1278 outlines.start = startOutline.map(function (point) {
1279 return point - outlineOffset;
1280 });
1281 outlines.end = endOutline.map(function (point) {
1282 return point - outlineOffset;
1283 });
1284 this.items.forEach(function (item) {
1285 var contentPos = item.cssContentPos;
1286
1287 if (!isNumber(contentPos)) {
1288 return;
1289 }
1290
1291 item.cssContentPos = contentPos - outlineOffset;
1292 });
1293 };
1294
1295 __proto.readyItems = function (mounted, updated, options) {
1296 var prevOutlines = this.outlines;
1297 var direction = options.direction || this.options.defaultDirection;
1298 var prevOutline = options.outline || prevOutlines[direction === "end" ? "start" : "end"];
1299 var items = this.items;
1300 var nextOutlines = {
1301 start: __spreadArrays(prevOutline),
1302 end: __spreadArrays(prevOutline)
1303 };
1304 updated.forEach(function (item) {
1305 item.isUpdate = true;
1306 });
1307
1308 if (items.length) {
1309 nextOutlines = this.applyGrid(this.items, direction, prevOutline);
1310 }
1311
1312 updated.forEach(function (item) {
1313 item.isUpdate = false;
1314 });
1315 this.setOutlines(nextOutlines);
1316 this.fitOutlines();
1317 this.itemRenderer.renderItems(this.items);
1318
1319 this._refreshContainerContentSize();
1320
1321 var transitionMounted = mounted.filter(function (item) {
1322 return item.hasTransition;
1323 });
1324
1325 if (transitionMounted.length) {
1326 this.containerManager.resize();
1327 transitionMounted.forEach(function (item) {
1328 var element = item.element;
1329 element.style.transitionDuration = item.transitionDuration;
1330 });
1331 }
1332
1333 this._renderComplete({
1334 direction: direction,
1335 mounted: mounted,
1336 updated: updated,
1337 isResize: !!options.useResize
1338 });
1339 };
1340
1341 __proto._renderComplete = function (e) {
1342 /**
1343 * This event is fired when the Grid has completed rendering.
1344 * @ko Grid가 렌더링이 완료됐을 때 발생하는 이벤트이다.
1345 * @event Grid#renderComplete
1346 * @param {Grid.OnRenderComplete} e - The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
1347 * @example
1348 * ```js
1349 * grid.on("renderComplete", e => {
1350 * console.log(e.mounted, e.updated, e.useResize);
1351 * });
1352 * ```
1353 */
1354 this.trigger("renderComplete", e);
1355 };
1356
1357 __proto._clearRenderTimer = function () {
1358 clearTimeout(this._renderTimer);
1359 this._renderTimer = 0;
1360 };
1361
1362 __proto._refreshContainerContentSize = function () {
1363 var _a = this.outlines,
1364 startOutline = _a.start,
1365 endOutline = _a.end;
1366 var gap = this.options.gap;
1367 var endPoint = endOutline.length ? Math.max.apply(Math, endOutline) : 0;
1368 var startPoint = startOutline.length ? Math.max.apply(Math, startOutline) : 0;
1369 var contentSize = Math.max(startPoint, endPoint - gap);
1370 this.containerManager.setContentSize(contentSize);
1371 };
1372
1373 __proto._resizeContainer = function () {
1374 this.containerManager.resize();
1375 this.itemRenderer.setContainerRect(this.containerManager.getRect());
1376 };
1377
1378 __proto._init = function () {
1379 this._resizeContainer();
1380 };
1381
1382 var Grid_1;
1383 Grid.defaultOptions = DEFAULT_GRID_OPTIONS;
1384 Grid.propertyTypes = GRID_PROPERTY_TYPES;
1385 Grid = Grid_1 = __decorate([GetterSetter], Grid);
1386 return Grid;
1387}(Component);
1388/**
1389 * Gap used to create space around items.
1390 * @ko 아이템들 사이의 공간.
1391 * @name Grid#gap
1392 * @type {$ts:Grid.GridOptions["gap"]}
1393 * @example
1394 * ```js
1395 * import { MasonryGrid } from "@egjs/grid";
1396 *
1397 * const grid = new MasonryGrid(container, {
1398 * gap: 0,
1399 * });
1400 *
1401 * grid.gap = 5;
1402 * ```
1403 */
1404
1405/**
1406 * The default direction value when direction is not set in the render option.
1407 * @ko render옵션에서 direction을 미설정시의 기본 방향값.
1408 * @name Grid#defaultDirection
1409 * @type {$ts:Grid.GridOptions["defaultDirection"]}
1410 * @example
1411 * ```js
1412 * import { MasonryGrid } from "@egjs/grid";
1413 *
1414 * const grid = new MasonryGrid(container, {
1415 * defaultDirection: "end",
1416 * });
1417 *
1418 * grid.defaultDirection = "start";
1419 * ```
1420 */
1421
1422/**
1423 * Whether to move the outline to 0 when the top is empty when rendering. However, if it overflows above the top, the outline is forced to 0. (default: true)
1424 * @ko 렌더링시 상단이 비어있을 때 아웃라인을 0으로 이동시킬지 여부. 하지만 상단보다 넘치는 경우 아웃라인을 0으로 강제 이동한다. (default: true)
1425 * @name Grid#useFit
1426 * @type {$ts:Grid.GridOptions["useFit"]}
1427 * @example
1428 * ```js
1429 * import { MasonryGrid } from "@egjs/grid";
1430 *
1431 * const grid = new MasonryGrid(container, {
1432 * useFit: true,
1433 * });
1434 *
1435 * grid.useFit = false;
1436 * ```
1437 */
1438
1439/**
1440 * Whether to preserve the UI of the existing container or item when destroying.
1441 * @ko destroy 시 기존 컨테이너, 아이템의 UI를 보존할지 여부.
1442 * @name Grid#preserveUIOnDestroy
1443 * @type {$ts:Grid.GridOptions["preserveUIOnDestroy"]}
1444 * @example
1445 * ```js
1446 * import { MasonryGrid } from "@egjs/grid";
1447 *
1448 * const grid = new MasonryGrid(container, {
1449 * preserveUIOnDestroy: false,
1450 * });
1451 *
1452 * grid.preserveUIOnDestroy = true;
1453 * ```
1454 */
1455
1456function getColumnPoint(outline, columnIndex, columnCount, pointCaculationName) {
1457 return Math[pointCaculationName].apply(Math, outline.slice(columnIndex, columnIndex + columnCount));
1458}
1459
1460function getColumnIndex(outline, columnCount, nearestCalculationName) {
1461 var length = outline.length - columnCount + 1;
1462 var pointCaculationName = nearestCalculationName === "max" ? "min" : "max";
1463 var indexCaculationName = nearestCalculationName === "max" ? "lastIndexOf" : "indexOf";
1464 var points = range(length).map(function (index) {
1465 return getColumnPoint(outline, index, columnCount, pointCaculationName);
1466 });
1467 return points[indexCaculationName](Math[nearestCalculationName].apply(Math, points));
1468}
1469/**
1470 * MasonryGrid is a grid that stacks items with the same width as a stack of bricks. Adjust the width of all images to the same size, find the lowest height column, and insert a new item.
1471 *
1472 * @ko MasonryGrid는 벽돌을 쌓아 올린 모양처럼 동일한 너비를 가진 아이템를 쌓는 레이아웃이다. 모든 이미지의 너비를 동일한 크기로 조정하고, 가장 높이가 낮은 열을 찾아 새로운 이미지를 삽입한다. 따라서 배치된 아이템 사이에 빈 공간이 생기지는 않지만 배치된 레이아웃의 아래쪽은 울퉁불퉁해진다.
1473 * @memberof Grid
1474 * @param {HTMLElement | string} container - A base element for a module <ko>모듈을 적용할 기준 엘리먼트</ko>
1475 * @param {Grid.MasonryGrid.MasonryGridOptions} options - The option object of the MasonryGrid module <ko>MasonryGrid 모듈의 옵션 객체</ko>
1476 */
1477
1478
1479var MasonryGrid =
1480/*#__PURE__*/
1481function (_super) {
1482 __extends(MasonryGrid, _super);
1483
1484 function MasonryGrid() {
1485 var _this = _super !== null && _super.apply(this, arguments) || this;
1486
1487 _this._columnSize = 0;
1488 _this._column = 1;
1489 return _this;
1490 }
1491
1492 var __proto = MasonryGrid.prototype;
1493
1494 __proto.applyGrid = function (items, direction, outline) {
1495 this._calculateColumnSize(items);
1496
1497 this._calculateColumn(items);
1498
1499 var column = this._column;
1500 var columnSize = this._columnSize;
1501 var _a = this.options,
1502 gap = _a.gap,
1503 align = _a.align,
1504 columnSizeRatio = _a.columnSizeRatio,
1505 columnSizeOption = _a.columnSize;
1506 var outlineLength = outline.length;
1507 var itemsLength = items.length;
1508
1509 var alignPoses = this._getAlignPoses();
1510
1511 var isEndDirection = direction === "end";
1512 var nearestCalculationName = isEndDirection ? "min" : "max";
1513 var pointCalculationName = isEndDirection ? "max" : "min";
1514 var startOutline = [0];
1515
1516 if (outlineLength === column) {
1517 startOutline = outline.slice();
1518 } else {
1519 var point_1 = outlineLength ? Math[pointCalculationName].apply(Math, outline) : 0;
1520 startOutline = range(column).map(function () {
1521 return point_1;
1522 });
1523 }
1524
1525 var endOutline = startOutline.slice();
1526 var columnDist = column > 1 ? alignPoses[1] - alignPoses[0] : 0;
1527 var isStretch = align === "stretch";
1528
1529 var _loop_1 = function (i) {
1530 var item = items[isEndDirection ? i : itemsLength - 1 - i];
1531 var columnAttribute = parseInt(item.attributes.column || "1", 10);
1532 var maxColumnAttribute = parseInt(item.attributes.maxColumn || "1", 10);
1533 var inlineSize = item.inlineSize;
1534 var contentSize = item.contentSize;
1535 var columnCount = Math.min(column, columnAttribute || Math.max(1, Math.ceil((inlineSize + gap) / columnDist)));
1536 var maxColumnCount = Math.min(column, Math.max(columnCount, maxColumnAttribute));
1537 var columnIndex = getColumnIndex(endOutline, columnCount, nearestCalculationName);
1538 var contentPos = getColumnPoint(endOutline, columnIndex, columnCount, pointCalculationName);
1539
1540 while (columnCount < maxColumnCount) {
1541 var nextEndColumnIndex = columnIndex + columnCount;
1542 var nextColumnIndex = columnIndex - 1;
1543
1544 if (isEndDirection && (nextEndColumnIndex >= column || endOutline[nextEndColumnIndex] > contentPos)) {
1545 break;
1546 }
1547
1548 if (!isEndDirection && (nextColumnIndex < 0 || endOutline[nextColumnIndex]) < contentPos) {
1549 break;
1550 }
1551
1552 if (!isEndDirection) {
1553 --columnIndex;
1554 }
1555
1556 ++columnCount;
1557 }
1558
1559 columnIndex = Math.max(0, columnIndex);
1560 columnCount = Math.min(column - columnIndex, columnCount);
1561
1562 if (columnAttribute > 0 && (columnCount > 1 || isStretch || columnSizeOption)) {
1563 inlineSize = (columnCount - 1) * columnDist + columnSize;
1564 item.cssInlineSize = inlineSize;
1565 }
1566
1567 if (columnSizeRatio > 0) {
1568 contentSize = inlineSize / columnSizeRatio;
1569 item.cssContentSize = contentSize;
1570 }
1571
1572 var inlinePos = alignPoses[columnIndex];
1573 contentPos = isEndDirection ? contentPos : contentPos - gap - contentSize;
1574 item.cssInlinePos = inlinePos;
1575 item.cssContentPos = contentPos;
1576 var nextOutlinePoint = isEndDirection ? contentPos + contentSize + gap : contentPos;
1577 range(columnCount).forEach(function (indexOffset) {
1578 endOutline[columnIndex + indexOffset] = nextOutlinePoint;
1579 });
1580 };
1581
1582 for (var i = 0; i < itemsLength; ++i) {
1583 _loop_1(i);
1584 } // if end items, startOutline is low, endOutline is high
1585 // if start items, startOutline is high, endOutline is low
1586
1587
1588 return {
1589 start: isEndDirection ? startOutline : endOutline,
1590 end: isEndDirection ? endOutline : startOutline
1591 };
1592 };
1593
1594 __proto._calculateColumnSize = function (items) {
1595 var _a = this.options,
1596 columnSizeOption = _a.columnSize,
1597 gap = _a.gap,
1598 align = _a.align;
1599
1600 if (align === "stretch") {
1601 var column = this.column;
1602
1603 if (columnSizeOption) {
1604 column = Math.max(1, Math.floor((this.getContainerInlineSize() + gap) / (columnSizeOption + gap)));
1605 }
1606
1607 this._columnSize = (this.getContainerInlineSize() + gap) / (column || 1) - gap;
1608 } else if (columnSizeOption) {
1609 this._columnSize = columnSizeOption;
1610 } else if (items.length) {
1611 var checkedItem = items[0];
1612
1613 for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
1614 var item = items_1[_i];
1615 var attributes = item.attributes;
1616
1617 if (item.updateState !== UPDATE_STATE.UPDATED || !item.inlineSize || attributes.column || attributes.maxColumnCount) {
1618 continue;
1619 }
1620
1621 checkedItem = item;
1622 break;
1623 }
1624
1625 var inlineSize = checkedItem.inlineSize || 0;
1626 this._columnSize = inlineSize;
1627 return inlineSize;
1628 }
1629
1630 this._columnSize = this._columnSize || 0;
1631 return this._columnSize;
1632 };
1633
1634 __proto._calculateColumn = function (items) {
1635 var _a = this.options,
1636 gap = _a.gap,
1637 columnOption = _a.column;
1638 var columnSize = this._columnSize;
1639 var column = 1;
1640
1641 if (columnOption) {
1642 column = columnOption;
1643 } else if (!columnSize) {
1644 column = 1;
1645 } else {
1646 column = Math.min(items.length, Math.max(1, Math.floor((this.getContainerInlineSize() + gap) / (columnSize + gap))));
1647 }
1648
1649 this._column = column;
1650 return column;
1651 };
1652
1653 __proto._getAlignPoses = function () {
1654 var columnSize = this._columnSize;
1655 var column = this._column;
1656 var _a = this.options,
1657 align = _a.align,
1658 gap = _a.gap;
1659 var containerSize = this.getContainerInlineSize();
1660 var indexes = range(column);
1661 var offset = 0;
1662 var dist = 0;
1663
1664 if (align === "justify" || align === "stretch") {
1665 var countDist = column - 1;
1666 dist = countDist ? Math.max((containerSize - columnSize) / countDist, columnSize + gap) : 0;
1667 offset = Math.min(0, containerSize / 2 - (countDist * dist + columnSize) / 2);
1668 } else {
1669 dist = columnSize + gap;
1670 var totalColumnSize = (column - 1) * dist + columnSize;
1671
1672 if (align === "center") {
1673 offset = (containerSize - totalColumnSize) / 2;
1674 } else if (align === "end") {
1675 offset = containerSize - totalColumnSize;
1676 }
1677 }
1678
1679 return indexes.map(function (i) {
1680 return offset + i * dist;
1681 });
1682 };
1683
1684 MasonryGrid.propertyTypes = __assign(__assign({}, Grid.propertyTypes), {
1685 column: PROPERTY_TYPE.RENDER_PROPERTY,
1686 columnSize: PROPERTY_TYPE.RENDER_PROPERTY,
1687 columnSizeRatio: PROPERTY_TYPE.RENDER_PROPERTY,
1688 align: PROPERTY_TYPE.RENDER_PROPERTY
1689 });
1690 MasonryGrid.defaultOptions = __assign(__assign({}, Grid.defaultOptions), {
1691 align: "justify",
1692 column: 0,
1693 columnSize: 0,
1694 columnSizeRatio: 0
1695 });
1696 MasonryGrid = __decorate([GetterSetter], MasonryGrid);
1697 return MasonryGrid;
1698}(Grid);
1699/**
1700 * Align of the position of the items. If you want to use `stretch`, be sure to set `column` or `columnSize` option. ("start", "center", "end", "justify", "stretch") (default: "justify")
1701 * @ko 아이템들의 위치의 정렬. `stretch`를 사용하고 싶다면 `column` 또는 `columnSize` 옵션을 설정해라. ("start", "center", "end", "justify", "stretch") (default: "justify")
1702 * @name Grid.MasonryGrid#align
1703 * @type {$ts:Grid.MasonryGrid.MasonryGridOptions["align"]}
1704 * @example
1705 * ```js
1706 * import { MasonryGrid } from "@egjs/grid";
1707 *
1708 * const grid = new MasonryGrid(container, {
1709 * align: "start",
1710 * });
1711 *
1712 * grid.align = "justify";
1713 * ```
1714 */
1715
1716/**
1717 * The number of columns. If the number of columns is 0, it is automatically calculated according to the size of the container.
1718 * @ko 열의 개수. 열의 개수가 0이라면, 컨테이너의 사이즈에 의해 계산이 된다. (default: 0)
1719 * @name Grid.MasonryGrid#column
1720 * @type {$ts:Grid.MasonryGrid.MasonryGridOptions["column"]}
1721 * @example
1722 * ```js
1723 * import { MasonryGrid } from "@egjs/grid";
1724 *
1725 * const grid = new MasonryGrid(container, {
1726 * column: 0,
1727 * });
1728 *
1729 * grid.column = 4;
1730 * ```
1731 */
1732
1733/**
1734 * The size of the columns. If it is 0, it is calculated as the size of the first item in items. (default: 0)
1735 * @ko 열의 사이즈. 만약 열의 사이즈가 0이면, 아이템들의 첫번째 아이템의 사이즈로 계산이 된다. (default: 0)
1736 * @name Grid.MasonryGrid#columnSize
1737 * @type {$ts:Grid.MasonryGrid.MasonryGridOptions["columnSize"]}
1738 * @example
1739 * ```js
1740 * import { MasonryGrid } from "@egjs/grid";
1741 *
1742 * const grid = new MasonryGrid(container, {
1743 * columnSize: 0,
1744 * });
1745 *
1746 * grid.columnSize = 200;
1747 * ```
1748 */
1749
1750/**
1751 * The size ratio(inlineSize / contentSize) of the columns. 0 is not set. (default: 0)
1752 * @ko 열의 사이즈 비율(inlineSize / contentSize). 0은 미설정이다.
1753 * @name Grid.MasonryGrid#columnSizeRatio
1754 * @type {$ts:Grid.MasonryGrid.MasonryGridOptions["columnSizeRatio"]}
1755 * @example
1756 * ```js
1757 * import { MasonryGrid } from "@egjs/grid";
1758 *
1759 * const grid = new MasonryGrid(container, {
1760 * columnSizeRatio: 0,
1761 * });
1762 *
1763 * grid.columnSizeRatio = 0.5;
1764 * ```
1765 */
1766
1767/* eslint-disable */
1768
1769/******************************************************************************
1770 * Created 2008-08-19.
1771 *
1772 * Dijkstra path-finding functions. Adapted from the Dijkstar Python project.
1773 *
1774 * Copyright (C) 2008
1775 * Wyatt Baldwin <self@wyattbaldwin.com>
1776 * All rights reserved
1777 *
1778 * Licensed under the MIT license.
1779 *
1780 * http://www.opensource.org/licenses/mit-license.php
1781 *
1782 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1783 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1784 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1785 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1786 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1787 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1788 * THE SOFTWARE.
1789 *****************************************************************************/
1790function single_source_shortest_paths(graph, s, d) {
1791 // Predecessor map for each node that has been encountered.
1792 // node ID => predecessor node ID
1793 var predecessors = {}; // Costs of shortest paths from s to all nodes encountered.
1794 // node ID => cost
1795
1796 var costs = {};
1797 costs[s] = 0; // Costs of shortest paths from s to all nodes encountered; differs from
1798 // `costs` in that it provides easy access to the node that currently has
1799 // the known shortest path from s.
1800 // XXX: Do we actually need both `costs` and `open`?
1801
1802 var open = new BinaryHeap(function (x) {
1803 return x.cost;
1804 });
1805 open.push({
1806 value: s,
1807 cost: 0
1808 });
1809 var closest;
1810 var u;
1811 var cost_of_s_to_u;
1812 var adjacent_nodes;
1813 var cost_of_e;
1814 var cost_of_s_to_u_plus_cost_of_e;
1815 var cost_of_s_to_v;
1816 var first_visit;
1817
1818 while (open.size()) {
1819 // In the nodes remaining in graph that have a known cost from s,
1820 // find the node, u, that currently has the shortest path from s.
1821 closest = open.pop();
1822 u = closest.value;
1823 cost_of_s_to_u = closest.cost; // Get nodes adjacent to u...
1824
1825 adjacent_nodes = graph(u) || {}; // ...and explore the edges that connect u to those nodes, updating
1826 // the cost of the shortest paths to any or all of those nodes as
1827 // necessary. v is the node across the current edge from u.
1828
1829 for (var v in adjacent_nodes) {
1830 // Get the cost of the edge running from u to v.
1831 cost_of_e = adjacent_nodes[v]; // Cost of s to u plus the cost of u to v across e--this is *a*
1832 // cost from s to v that may or may not be less than the current
1833 // known cost to v.
1834
1835 cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e; // If we haven't visited v yet OR if the current known cost from s to
1836 // v is greater than the new cost we just found (cost of s to u plus
1837 // cost of u to v across e), update v's cost in the cost list and
1838 // update v's predecessor in the predecessor list (it's now u).
1839
1840 cost_of_s_to_v = costs[v];
1841 first_visit = typeof costs[v] === "undefined";
1842
1843 if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
1844 costs[v] = cost_of_s_to_u_plus_cost_of_e;
1845 open.push({
1846 value: v,
1847 cost: cost_of_s_to_u_plus_cost_of_e
1848 });
1849 predecessors[v] = u;
1850 }
1851 }
1852 }
1853
1854 if (typeof costs[d] === "undefined") {
1855 var msg = ["Could not find a path from ", s, " to ", d, "."].join("");
1856 throw new Error(msg);
1857 }
1858
1859 return predecessors;
1860}
1861
1862function extract_shortest_path_from_predecessor_list(predecessors, d) {
1863 var nodes = [];
1864 var u = d;
1865
1866 while (u) {
1867 nodes.push(u);
1868 u = predecessors[u];
1869 }
1870
1871 nodes.reverse();
1872 return nodes;
1873}
1874
1875function find_path(graph, s, d) {
1876 var predecessors = single_source_shortest_paths(graph, s, d);
1877 return extract_shortest_path_from_predecessor_list(predecessors, d);
1878}
1879
1880var BinaryHeap =
1881/*#__PURE__*/
1882function () {
1883 function BinaryHeap(scoreFunction) {
1884 this.content = [];
1885 this.scoreFunction = scoreFunction;
1886 }
1887
1888 var __proto = BinaryHeap.prototype;
1889
1890 __proto.push = function (element) {
1891 // Add the new element to the end of the array.
1892 this.content.push(element); // Allow it to bubble up.
1893
1894 this.bubbleUp(this.content.length - 1);
1895 };
1896
1897 __proto.pop = function () {
1898 // Store the first element so we can return it later.
1899 var result = this.content[0]; // Get the element at the end of the array.
1900
1901 var end = this.content.pop(); // If there are any elements left, put the end element at the
1902 // start, and let it sink down.
1903
1904 if (this.content.length > 0) {
1905 this.content[0] = end;
1906 this.sinkDown(0);
1907 }
1908
1909 return result;
1910 };
1911
1912 __proto.size = function () {
1913 return this.content.length;
1914 };
1915
1916 __proto.bubbleUp = function (_n) {
1917 var n = _n; // Fetch the element that has to be moved.
1918
1919 var element = this.content[n]; // When at 0, an element can not go up any further.
1920
1921 while (n > 0) {
1922 // Compute the parent element's index, and fetch it.
1923 var parentN = Math.floor((n + 1) / 2) - 1;
1924 var parent = this.content[parentN]; // Swap the elements if the parent is greater.
1925
1926 if (this.scoreFunction(element) < this.scoreFunction(parent)) {
1927 this.content[parentN] = element;
1928 this.content[n] = parent; // Update 'n' to continue at the new position.
1929
1930 n = parentN;
1931 } else {
1932 // Found a parent that is less, no need to move it further.
1933 break;
1934 }
1935 }
1936 };
1937
1938 __proto.sinkDown = function (n) {
1939 // Look up the target element and its score.
1940 var length = this.content.length;
1941 var element = this.content[n];
1942 var elemScore = this.scoreFunction(element);
1943 var child1Score;
1944
1945 while (true) {
1946 // Compute the indices of the child elements.
1947 var child2N = (n + 1) * 2;
1948 var child1N = child2N - 1; // This is used to store the new position of the element,
1949 // if any.
1950
1951 var swap = null; // If the first child exists (is inside the array)...
1952
1953 if (child1N < length) {
1954 // Look it up and compute its score.
1955 var child1 = this.content[child1N];
1956 child1Score = this.scoreFunction(child1); // If the score is less than our element's, we need to swap.
1957
1958 if (child1Score < elemScore) {
1959 swap = child1N;
1960 }
1961 } // Do the same checks for the other child.
1962
1963
1964 if (child2N < length) {
1965 var child2 = this.content[child2N];
1966 var child2Score = this.scoreFunction(child2);
1967
1968 if (child2Score < (swap == null ? elemScore : child1Score)) {
1969 swap = child2N;
1970 }
1971 } // If the element needs to be moved, swap it, and continue.
1972
1973
1974 if (swap !== null) {
1975 this.content[n] = this.content[swap];
1976 this.content[swap] = element;
1977 n = swap;
1978 } else {
1979 // Otherwise, we are done.
1980 break;
1981 }
1982 }
1983 };
1984
1985 return BinaryHeap;
1986}();
1987
1988function splitItems(items, path) {
1989 var length = path.length;
1990 var groups = [];
1991
1992 for (var i = 0; i < length - 1; ++i) {
1993 var path1 = parseInt(path[i], 10);
1994 var path2 = parseInt(path[i + 1], 10);
1995 groups.push(items.slice(path1, path2));
1996 }
1997
1998 return groups;
1999}
2000
2001function getExpectedColumnSize(item, rowSize) {
2002 var inlineSize = item.orgInlineSize;
2003 var contentSize = item.orgContentSize;
2004
2005 if (!inlineSize || !contentSize) {
2006 return 0;
2007 }
2008
2009 var inlineOffset = parseFloat(item.gridData.inlineOffset) || 0;
2010 var contentOffset = parseFloat(item.gridData.contentOffset) || 0;
2011 return (inlineSize - inlineOffset) / (contentSize - contentOffset) * (rowSize - contentOffset) + inlineOffset;
2012}
2013/**
2014 * 'justified' is a printing term with the meaning that 'it fits in one row wide'. JustifiedGrid is a grid that the item is filled up on the basis of a line given a size.
2015 * If 'data-grid-inline-offset' or 'data-grid-content-offset' are set for item element, the ratio is maintained except for the offset value.
2016 * If 'data-grid-maintained-target' is set for an element whose ratio is to be maintained, the item is rendered while maintaining the ratio of the element.
2017 * @ko 'justified'는 '1행의 너비에 맞게 꼭 들어찬'이라는 의미를 가진 인쇄 용어다. JustifiedGrid는 용어의 의미대로 너비가 주어진 사이즈를 기준으로 아이템가 가득 차도록 배치하는 Grid다.
2018 * 아이템 엘리먼트에 'data-grid-inline-offset' 또는 'data-grid-content-offset'를 설정하면 offset 값을 제외하고 비율을 유지한다.
2019 * 비율을 유지하고 싶은 엘리먼트에 'data-grid-maintained-target'을 설정한다면 해당 엘리먼트의 비율을 유지하면서 아이템이 렌더링이 된다.
2020 * @memberof Grid
2021 * @param {HTMLElement | string} container - A base element for a module <ko>모듈을 적용할 기준 엘리먼트</ko>
2022 * @param {Grid.JustifiedGrid.JustifiedGridOptions} options - The option object of the JustifiedGrid module <ko>JustifiedGrid 모듈의 옵션 객체</ko>
2023 */
2024
2025
2026var JustifiedGrid =
2027/*#__PURE__*/
2028function (_super) {
2029 __extends(JustifiedGrid, _super);
2030
2031 function JustifiedGrid() {
2032 return _super !== null && _super.apply(this, arguments) || this;
2033 }
2034
2035 var __proto = JustifiedGrid.prototype;
2036
2037 __proto.applyGrid = function (items, direction, outline) {
2038 var _a = this.options,
2039 attributePrefix = _a.attributePrefix,
2040 horizontal = _a.horizontal;
2041 items.forEach(function (item) {
2042 if (!item.isUpdate) {
2043 return;
2044 }
2045
2046 var element = item.element;
2047 var attributes = item.attributes;
2048 var gridData = item.gridData;
2049 var inlineOffset = parseFloat(attributes.inlineOffset) || gridData.inlineOffset || 0;
2050 var contentOffset = parseFloat(attributes.contentOffset) || gridData.contentOffset | 0;
2051
2052 if (element && !("inlineOffset" in attributes) && !("contentOffset" in attributes) && item.mountState === MOUNT_STATE.MOUNTED) {
2053 var maintainedTarget = element.querySelector("[" + attributePrefix + "maintained-target]");
2054
2055 if (maintainedTarget) {
2056 var widthOffset = element.offsetWidth - element.clientWidth + element.scrollWidth - maintainedTarget.clientWidth;
2057 var heightOffset = element.offsetHeight - element.clientHeight + element.scrollHeight - maintainedTarget.clientHeight;
2058
2059 if (horizontal) {
2060 inlineOffset = heightOffset;
2061 contentOffset = widthOffset;
2062 } else {
2063 inlineOffset = widthOffset;
2064 contentOffset = heightOffset;
2065 }
2066 }
2067 }
2068
2069 gridData.inlineOffset = inlineOffset;
2070 gridData.contentOffset = contentOffset;
2071 });
2072 var rowRange = this.options.rowRange;
2073 var path = [];
2074
2075 if (items.length) {
2076 path = rowRange ? this._getRowPath(items) : this._getPath(items);
2077 }
2078
2079 return this._setStyle(items, path, outline, direction === "end");
2080 };
2081
2082 __proto._getRowPath = function (items) {
2083 var _a;
2084
2085 var columnRange = this._getColumnRange();
2086
2087 var rowRange = this._getRowRange();
2088
2089 var pathLink = this._getRowLink(items, {
2090 path: [0],
2091 cost: 0,
2092 length: 0,
2093 currentNode: 0
2094 }, columnRange, rowRange);
2095
2096 return (_a = pathLink === null || pathLink === void 0 ? void 0 : pathLink.path.map(function (node) {
2097 return "" + node;
2098 })) !== null && _a !== void 0 ? _a : [];
2099 };
2100
2101 __proto._getRowLink = function (items, currentLink, columnRange, rowRange) {
2102 var minColumn = columnRange[0];
2103 var minRow = rowRange[0],
2104 maxRow = rowRange[1];
2105 var lastNode = items.length;
2106 var path = currentLink.path,
2107 pathLength = currentLink.length,
2108 cost = currentLink.cost,
2109 currentNode = currentLink.currentNode; // not reached lastNode but path is exceed or the number of remaining nodes is less than minColumn.
2110
2111 if (currentNode < lastNode && (maxRow <= pathLength || currentNode + minColumn > lastNode)) {
2112 var rangeCost = getRangeCost(lastNode - currentNode, columnRange);
2113 var lastCost = rangeCost * Math.abs(this._getCost(items, currentNode, lastNode));
2114 return __assign(__assign({}, currentLink), {
2115 length: pathLength + 1,
2116 path: __spreadArrays(path, [lastNode]),
2117 currentNode: lastNode,
2118 cost: cost + lastCost,
2119 isOver: true
2120 });
2121 } else if (currentNode >= lastNode) {
2122 return __assign(__assign({}, currentLink), {
2123 currentNode: lastNode,
2124 isOver: minRow > pathLength || maxRow < pathLength
2125 });
2126 } else {
2127 return this._searchRowLink(items, currentLink, lastNode, columnRange, rowRange);
2128 }
2129 };
2130
2131 __proto._searchRowLink = function (items, currentLink, lastNode, columnRange, rowRange) {
2132 var minColumn = columnRange[0],
2133 maxColumn = columnRange[1];
2134 var currentNode = currentLink.currentNode,
2135 path = currentLink.path,
2136 pathLength = currentLink.length,
2137 cost = currentLink.cost;
2138 var length = Math.min(lastNode, currentNode + maxColumn);
2139 var links = [];
2140
2141 for (var nextNode = currentNode + minColumn; nextNode <= length; ++nextNode) {
2142 if (nextNode === currentNode) {
2143 continue;
2144 }
2145
2146 var nextCost = Math.abs(this._getCost(items, currentNode, nextNode));
2147
2148 var nextLink = this._getRowLink(items, {
2149 path: __spreadArrays(path, [nextNode]),
2150 length: pathLength + 1,
2151 cost: cost + nextCost,
2152 currentNode: nextNode
2153 }, columnRange, rowRange);
2154
2155 if (nextLink) {
2156 links.push(nextLink);
2157 }
2158 }
2159
2160 links.sort(function (a, b) {
2161 var aIsOver = a.isOver;
2162 var bIsOver = b.isOver;
2163
2164 if (aIsOver !== bIsOver) {
2165 // If it is over, the cost is high.
2166 return aIsOver ? 1 : -1;
2167 }
2168
2169 var aRangeCost = getRangeCost(a.length, rowRange);
2170 var bRangeCost = getRangeCost(b.length, rowRange);
2171 return aRangeCost - bRangeCost || a.cost - b.cost;
2172 }); // It returns the lowest cost link.
2173
2174 return links[0];
2175 };
2176
2177 __proto._getExpectedRowSize = function (items) {
2178 var gap = this.options.gap;
2179 var containerInlineSize = this.getContainerInlineSize() - gap * (items.length - 1);
2180 var ratioSum = 0;
2181 var inlineSum = 0;
2182 items.forEach(function (item) {
2183 var inlineSize = item.orgInlineSize;
2184 var contentSize = item.orgContentSize;
2185
2186 if (!inlineSize || !contentSize) {
2187 return;
2188 } // sum((expect - offset) * ratio) = container inline size
2189
2190
2191 var inlineOffset = parseFloat(item.gridData.inlineOffset) || 0;
2192 var contentOffset = parseFloat(item.gridData.contentOffset) || 0;
2193 var maintainedRatio = (inlineSize - inlineOffset) / (contentSize - contentOffset);
2194 ratioSum += maintainedRatio;
2195 inlineSum += contentOffset * maintainedRatio;
2196 containerInlineSize -= inlineOffset;
2197 });
2198 return ratioSum ? (containerInlineSize + inlineSum) / ratioSum : 0;
2199 };
2200
2201 __proto._getExpectedInlineSize = function (items, rowSize) {
2202 var gap = this.options.gap;
2203 var size = items.reduce(function (sum, item) {
2204 return sum + getExpectedColumnSize(item, rowSize);
2205 }, 0);
2206 return size ? size + gap * (items.length - 1) : 0;
2207 };
2208
2209 __proto._getCost = function (items, i, j) {
2210 var lineItems = items.slice(i, j);
2211
2212 var rowSize = this._getExpectedRowSize(lineItems);
2213
2214 var _a = this._getSizeRange(),
2215 minSize = _a[0],
2216 maxSize = _a[1];
2217
2218 if (this.isCroppedSize) {
2219 if (minSize <= rowSize && rowSize <= maxSize) {
2220 return 0;
2221 }
2222
2223 var expectedInlineSize = this._getExpectedInlineSize(lineItems, rowSize < minSize ? minSize : maxSize);
2224
2225 return Math.pow(expectedInlineSize - this.getContainerInlineSize(), 2);
2226 }
2227
2228 if (isFinite(maxSize)) {
2229 // if this size is not in range, the cost increases sharply.
2230 if (rowSize < minSize) {
2231 return Math.pow(rowSize - minSize, 2) + Math.pow(maxSize, 2);
2232 } else if (rowSize > maxSize) {
2233 return Math.pow(rowSize - maxSize, 2) + Math.pow(maxSize, 2);
2234 }
2235 } else if (rowSize < minSize) {
2236 return Math.max(Math.pow(minSize, 2), Math.pow(rowSize, 2)) + Math.pow(maxSize, 2);
2237 } // if this size in range, the cost is row
2238
2239
2240 return rowSize - minSize;
2241 };
2242
2243 __proto._getPath = function (items) {
2244 var _this = this;
2245
2246 var lastNode = items.length;
2247 var columnRangeOption = this.options.columnRange;
2248
2249 var _a = isObject(columnRangeOption) ? columnRangeOption : [columnRangeOption, columnRangeOption],
2250 minColumn = _a[0],
2251 maxColumn = _a[1];
2252
2253 var graph = function (nodeKey) {
2254 var results = {};
2255 var currentNode = parseInt(nodeKey, 10);
2256
2257 for (var nextNode = Math.min(currentNode + minColumn, lastNode); nextNode <= lastNode; ++nextNode) {
2258 if (nextNode - currentNode > maxColumn) {
2259 break;
2260 }
2261
2262 var cost = _this._getCost(items, currentNode, nextNode);
2263
2264 if (cost < 0 && nextNode === lastNode) {
2265 cost = 0;
2266 }
2267
2268 results["" + nextNode] = Math.pow(cost, 2);
2269 }
2270
2271 return results;
2272 }; // shortest path for items' total height.
2273
2274
2275 return find_path(graph, "0", "" + lastNode);
2276 };
2277
2278 __proto._setStyle = function (items, path, outline, isEndDirection) {
2279 var _this = this;
2280
2281 if (outline === void 0) {
2282 outline = [];
2283 }
2284
2285 var _a = this.options,
2286 gap = _a.gap,
2287 isCroppedSize = _a.isCroppedSize,
2288 displayedRow = _a.displayedRow;
2289
2290 var sizeRange = this._getSizeRange();
2291
2292 var startPoint = outline[0] || 0;
2293 var containerInlineSize = this.getContainerInlineSize();
2294 var groups = splitItems(items, path);
2295 var contentPos = startPoint;
2296 var displayedSize = 0;
2297 groups.forEach(function (groupItems, rowIndex) {
2298 var length = groupItems.length;
2299
2300 var rowSize = _this._getExpectedRowSize(groupItems);
2301
2302 if (isCroppedSize) {
2303 rowSize = Math.max(sizeRange[0], Math.min(rowSize, sizeRange[1]));
2304 }
2305
2306 var expectedInlineSize = _this._getExpectedInlineSize(groupItems, rowSize);
2307
2308 var allGap = gap * (length - 1);
2309 var scale = (containerInlineSize - allGap) / (expectedInlineSize - allGap);
2310 groupItems.forEach(function (item, i) {
2311 var columnSize = getExpectedColumnSize(item, rowSize);
2312 var prevItem = groupItems[i - 1];
2313 var inlinePos = prevItem ? prevItem.cssInlinePos + prevItem.cssInlineSize + gap : 0;
2314
2315 if (isCroppedSize) {
2316 columnSize *= scale;
2317 }
2318
2319 item.setCSSGridRect({
2320 inlinePos: inlinePos,
2321 contentPos: contentPos,
2322 inlineSize: columnSize,
2323 contentSize: rowSize
2324 });
2325 });
2326 contentPos += gap + rowSize;
2327
2328 if (displayedRow < 0 || rowIndex < displayedRow) {
2329 displayedSize = contentPos;
2330 }
2331 });
2332
2333 if (isEndDirection) {
2334 // previous group's end outline is current group's start outline
2335 return {
2336 start: [startPoint],
2337 end: [displayedSize]
2338 };
2339 } // always start is lower than end.
2340 // contentPos is endPoinnt
2341
2342
2343 var height = contentPos - startPoint;
2344 items.forEach(function (item) {
2345 item.cssContentPos -= height;
2346 });
2347 return {
2348 start: [startPoint - height],
2349 end: [startPoint]
2350 };
2351 };
2352
2353 __proto._getRowRange = function () {
2354 var rowRange = this.rowRange;
2355 return isObject(rowRange) ? rowRange : [rowRange, rowRange];
2356 };
2357
2358 __proto._getColumnRange = function () {
2359 var columnRange = this.columnRange;
2360 return isObject(columnRange) ? columnRange : [columnRange, columnRange];
2361 };
2362
2363 __proto._getSizeRange = function () {
2364 var sizeRange = this.sizeRange;
2365 return isObject(sizeRange) ? sizeRange : [sizeRange, sizeRange];
2366 };
2367
2368 JustifiedGrid.propertyTypes = __assign(__assign({}, Grid.propertyTypes), {
2369 columnRange: PROPERTY_TYPE.RENDER_PROPERTY,
2370 rowRange: PROPERTY_TYPE.RENDER_PROPERTY,
2371 sizeRange: PROPERTY_TYPE.RENDER_PROPERTY,
2372 isCroppedSize: PROPERTY_TYPE.RENDER_PROPERTY,
2373 displayedRow: PROPERTY_TYPE.RENDER_PROPERTY
2374 });
2375 JustifiedGrid.defaultOptions = __assign(__assign({}, Grid.defaultOptions), {
2376 columnRange: [1, 8],
2377 rowRange: 0,
2378 sizeRange: [0, Infinity],
2379 displayedRow: -1,
2380 isCroppedSize: false
2381 });
2382 JustifiedGrid = __decorate([GetterSetter], JustifiedGrid);
2383 return JustifiedGrid;
2384}(Grid);
2385/**
2386 * The minimum and maximum number of items per line. (default: [1, 8])
2387 * @ko 한 줄에 들어가는 아이템의 최소, 최대 개수. (default: [1, 8])
2388 * @name Grid.JustifiedGrid#columnRange
2389 * @type {$ts:Grid.JustifiedGrid.JustifiedGridOptions["columnRange"]}
2390 * @example
2391 * ```js
2392 * import { JustifiedGrid } from "@egjs/grid";
2393 *
2394 * const grid = new JustifiedGrid(container, {
2395 * columnRange: [1, 8],
2396 * });
2397 *
2398 * grid.columnRange = [3, 6];
2399 * ```
2400 */
2401
2402/**
2403 * The minimum and maximum number of rows in a group, 0 is not set. (default: 0)
2404 * @ko 한 그룹에 들어가는 행의 최소, 최대 개수, 0은 미설정이다. (default: 0)
2405 * @name Grid.JustifiedGrid#rowRange
2406 * @type {$ts:Grid.JustifiedGrid.JustifiedGridOptions["rowRange"]}
2407 * @example
2408 * ```js
2409 * import { JustifiedGrid } from "@egjs/grid";
2410 *
2411 * const grid = new JustifiedGrid(container, {
2412 * rowRange: 0,
2413 * });
2414 *
2415 * grid.rowRange = [3, 4];
2416 * ```
2417 */
2418
2419/**
2420 * The minimum and maximum size by which the item is adjusted. If it is not calculated, it may deviate from the minimum and maximum sizes. (default: [0, Infinity])
2421 * @ko 아이템이 조정되는 최소, 최대 사이즈. 계산이 되지 않는 경우 최소, 최대 사이즈를 벗어날 수 있다. (default: [0, Infinity])
2422 * @name Grid.JustifiedGrid#sizeRange
2423 * @type {$ts:Grid.JustifiedGrid.JustifiedGridOptions["sizeRange"]}
2424 * @example
2425 * ```js
2426 * import { JustifiedGrid } from "@egjs/grid";
2427 *
2428 * const grid = new JustifiedGrid(container, {
2429 * sizeRange: [0, Infinity],
2430 * });
2431 *
2432 * grid.sizeRange = [200, 800];
2433 * ```
2434 */
2435
2436/**
2437 * Maximum number of rows to be counted for container size. You can hide it on the screen by setting overflow: hidden. -1 is not set. (default: -1)
2438 * @ko - 컨테이너 크기에 계산될 최대 row 개수. overflow: hidden을 설정하면 화면에 가릴 수 있다. -1은 미설정이다. (default: -1)
2439 * @name Grid.JustifiedGrid#displayedRow
2440 * @type {$ts:Grid.JustifiedGrid.JustifiedGridOptions["displayedRow"]}
2441 * @example
2442 * ```js
2443 * import { JustifiedGrid } from "@egjs/grid";
2444 *
2445 * const grid = new JustifiedGrid(container, {
2446 * displayedRow: -1,
2447 * });
2448 *
2449 * grid.displayedRow = 3;
2450 * ```
2451 */
2452
2453/**
2454 * Whether to crop when the row size is out of sizeRange. If set to true, this ratio can be broken. (default: false)
2455 * @ko - row 사이즈가 sizeRange에 벗어나면 크롭할지 여부. true로 설정하면 비율이 깨질 수 있다. (default: false)
2456 * @name Grid.JustifiedGrid#isCroppedSize
2457 * @type {$ts:Grid.JustifiedGrid.JustifiedGridOptions["isCroppedSize"]}
2458 * @example
2459 * ```js
2460 * import { JustifiedGrid } from "@egjs/grid";
2461 *
2462 * const grid = new JustifiedGrid(container, {
2463 * sizeRange: [200, 250],
2464 * isCroppedSize: false,
2465 * });
2466 *
2467 * grid.isCroppedSize = true;
2468 * ```
2469 */
2470
2471function getMaxPoint(outline) {
2472 var maxPoint = -Infinity;
2473 outline.forEach(function (point) {
2474 if (isFinite(point)) {
2475 maxPoint = Math.max(maxPoint, point);
2476 }
2477 });
2478 return isFinite(maxPoint) ? maxPoint : 0;
2479}
2480
2481function getMinPoint(outline) {
2482 var minPoint = Infinity;
2483 outline.forEach(function (point) {
2484 if (isFinite(point)) {
2485 minPoint = Math.min(minPoint, point);
2486 }
2487 });
2488 return isFinite(minPoint) ? minPoint : 0;
2489}
2490
2491function getOutlinePoint(startOutline, frameOutline, useFrameFill) {
2492 return getMaxPoint(startOutline) + getOutlineDist(startOutline, frameOutline, useFrameFill);
2493}
2494
2495function getOutlineDist(startOutline, endOutline, useFrameFill) {
2496 var length = startOutline.length;
2497
2498 if (!length) {
2499 return 0;
2500 }
2501
2502 var minEndPoint = getMinPoint(endOutline);
2503 var maxStartPoint = getMaxPoint(startOutline);
2504 var frameDist = 0;
2505
2506 if (!useFrameFill) {
2507 return 0;
2508 }
2509
2510 for (var outlineIndex = 0; outlineIndex < length; ++outlineIndex) {
2511 var startPoint = startOutline[outlineIndex];
2512 var endPoint = endOutline[outlineIndex];
2513
2514 if (!isFinite(startPoint) || !isFinite(endPoint)) {
2515 continue;
2516 }
2517
2518 var startPos = startPoint - maxStartPoint;
2519 var endPos = endPoint - minEndPoint; // Fill empty block.
2520
2521 frameDist = outlineIndex ? Math.max(frameDist, frameDist + startPos - endPos) : startPos - endPos;
2522 }
2523
2524 return frameDist;
2525}
2526
2527function fillOutlines(startOutline, endOutline, rect) {
2528 var inlinePos = rect.inlinePos,
2529 inlineSize = rect.inlineSize,
2530 contentPos = rect.contentPos,
2531 contentSize = rect.contentSize;
2532
2533 for (var outlineIndex = inlinePos; outlineIndex < inlinePos + inlineSize; ++outlineIndex) {
2534 startOutline[outlineIndex] = Math.min(startOutline[outlineIndex], contentPos);
2535 endOutline[outlineIndex] = Math.max(endOutline[outlineIndex], contentPos + contentSize);
2536 }
2537}
2538/**
2539 * 'Frame' is a printing term with the meaning that 'it fits in one row wide'. FrameGrid is a grid that the item is filled up on the basis of a line given a size.
2540 * @ko 'Frame'는 '1행의 너비에 맞게 꼭 들어찬'이라는 의미를 가진 인쇄 용어다. FrameGrid는 용어의 의미대로 너비가 주어진 사이즈를 기준으로 아이템이 가득 차도록 배치하는 Grid다.
2541 * @memberof Grid
2542 * @param {HTMLElement | string} container - A base element for a module <ko>모듈을 적용할 기준 엘리먼트</ko>
2543 * @param {Grid.FrameGrid.FrameGridOptions} options - The option object of the FrameGrid module <ko>FrameGrid 모듈의 옵션 객체</ko>
2544 */
2545
2546
2547var FrameGrid =
2548/*#__PURE__*/
2549function (_super) {
2550 __extends(FrameGrid, _super);
2551
2552 function FrameGrid() {
2553 return _super !== null && _super.apply(this, arguments) || this;
2554 }
2555
2556 var __proto = FrameGrid.prototype;
2557
2558 __proto.applyGrid = function (items, direction, outline) {
2559 var frame = this._getFrame();
2560
2561 var frameInlineSize = frame.inlineSize,
2562 frameContentSize = frame.contentSize,
2563 frameRects = frame.rects;
2564 var _a = this.options,
2565 gap = _a.gap,
2566 useFrameFill = _a.useFrameFill;
2567
2568 var _b = this.getRectSize(frameInlineSize),
2569 rectInlineSize = _b.inlineSize,
2570 rectContentSize = _b.contentSize;
2571
2572 var itemsLength = items.length;
2573
2574 if (!itemsLength || !frameInlineSize || !frameContentSize) {
2575 return {
2576 start: outline,
2577 end: outline
2578 };
2579 }
2580
2581 var rectsLength = frameRects.length;
2582 var startOutline = range(frameInlineSize).map(function () {
2583 return Infinity;
2584 });
2585 var endOutline = range(frameInlineSize).map(function () {
2586 return -Infinity;
2587 });
2588 var frameOutline = frame.outline.map(function (point) {
2589 return point * (rectContentSize + gap);
2590 });
2591
2592 for (var startIndex = 0; startIndex < itemsLength; startIndex += rectsLength) {
2593 // Compare group's startOutline and startOutline of rect
2594 var startPoint = getOutlinePoint(endOutline, frameOutline, useFrameFill);
2595
2596 for (var rectIndex = 0; rectIndex < rectsLength && startIndex + rectIndex < itemsLength; ++rectIndex) {
2597 var item = items[startIndex + rectIndex];
2598 var _c = frameRects[rectIndex],
2599 frameRectContentPos = _c.contentPos,
2600 frameRectInlinePos = _c.inlinePos,
2601 frameRectContentSize = _c.contentSize,
2602 frameRectInlineSize = _c.inlineSize;
2603 var contentPos = startPoint + frameRectContentPos * (rectContentSize + gap);
2604 var inlinePos = frameRectInlinePos * (rectInlineSize + gap);
2605 var contentSize = frameRectContentSize * (rectContentSize + gap) - gap;
2606 var inlineSize = frameRectInlineSize * (rectInlineSize + gap) - gap;
2607 fillOutlines(startOutline, endOutline, {
2608 inlinePos: frameRectInlinePos,
2609 inlineSize: frameRectInlineSize,
2610 contentPos: contentPos,
2611 contentSize: contentSize + gap
2612 });
2613 item.setCSSGridRect({
2614 inlinePos: inlinePos,
2615 contentPos: contentPos,
2616 inlineSize: inlineSize,
2617 contentSize: contentSize
2618 });
2619 }
2620 }
2621
2622 var isDirectionEnd = direction === "end";
2623 var gridOutline = outline.length ? outline : [0];
2624
2625 if (gridOutline.length !== frameInlineSize) {
2626 var point_1 = isDirectionEnd ? Math.max.apply(Math, gridOutline) : Math.min.apply(Math, gridOutline);
2627 gridOutline = range(frameInlineSize).map(function () {
2628 return point_1;
2629 });
2630 }
2631
2632 startOutline = startOutline.map(function (point) {
2633 return isFinite(point) ? point : 0;
2634 });
2635 endOutline = endOutline.map(function (point) {
2636 return isFinite(point) ? point : 0;
2637 });
2638 var outlineDist = isDirectionEnd ? getOutlinePoint(gridOutline, startOutline, useFrameFill) : getOutlinePoint(endOutline, gridOutline, useFrameFill);
2639 items.forEach(function (item) {
2640 item.cssContentPos += outlineDist;
2641 });
2642 return {
2643 start: startOutline.map(function (point) {
2644 return point + outlineDist;
2645 }),
2646 end: endOutline.map(function (point) {
2647 return point + outlineDist;
2648 })
2649 };
2650 };
2651
2652 __proto.getRectSize = function (frameInlineSize) {
2653 var _a = this.options,
2654 gap = _a.gap,
2655 rectSizeOption = _a.rectSize;
2656
2657 if (typeof rectSizeOption === "object") {
2658 return rectSizeOption;
2659 }
2660
2661 var rectSizeValue = rectSizeOption ? rectSizeOption : (this.getContainerInlineSize() + gap) / frameInlineSize - gap;
2662 return {
2663 inlineSize: rectSizeValue,
2664 contentSize: rectSizeValue
2665 };
2666 };
2667
2668 __proto._getFrame = function () {
2669 var frame = this.options.frame;
2670 var frameContentSize = frame.length;
2671 var frameInlineSize = frameContentSize ? frame[0].length : 0;
2672 var rects = [];
2673 var passMap = {};
2674 var startOutline = range(frameInlineSize).map(function () {
2675 return Infinity;
2676 });
2677 var endOutline = range(frameInlineSize).map(function () {
2678 return -Infinity;
2679 });
2680
2681 for (var y1 = 0; y1 < frameContentSize; ++y1) {
2682 for (var x1 = 0; x1 < frameInlineSize; ++x1) {
2683 var type = frame[y1][x1];
2684
2685 if (!type) {
2686 continue;
2687 }
2688
2689 if (passMap[y1 + "," + x1]) {
2690 continue;
2691 }
2692
2693 var rect = this._findRect(passMap, type, y1, x1, frameInlineSize, frameContentSize);
2694
2695 fillOutlines(startOutline, endOutline, rect);
2696 rects.push(rect);
2697 }
2698 }
2699
2700 rects.sort(function (a, b) {
2701 return a.type < b.type ? -1 : 1;
2702 });
2703 return {
2704 rects: rects,
2705 inlineSize: frameInlineSize,
2706 contentSize: frameContentSize,
2707 outline: startOutline
2708 };
2709 };
2710
2711 __proto._findRect = function (passMap, type, y1, x1, frameInlineSize, frameContentSize) {
2712 var frame = this.options.frame;
2713 var contentSize = 1;
2714 var inlineSize = 1; // find rect
2715
2716 for (var x2 = x1; x2 < frameInlineSize; ++x2) {
2717 if (frame[y1][x2] === type) {
2718 inlineSize = x2 - x1 + 1;
2719 continue;
2720 }
2721
2722 break;
2723 }
2724
2725 for (var y2 = y1; y2 < frameContentSize; ++y2) {
2726 if (frame[y2][x1] === type) {
2727 contentSize = y2 - y1 + 1;
2728 continue;
2729 }
2730
2731 break;
2732 } // pass rect
2733
2734
2735 for (var y = y1; y < y1 + contentSize; ++y) {
2736 for (var x = x1; x < x1 + inlineSize; ++x) {
2737 passMap[y + "," + x] = true;
2738 }
2739 }
2740
2741 var rect = {
2742 type: type,
2743 inlinePos: x1,
2744 contentPos: y1,
2745 inlineSize: inlineSize,
2746 contentSize: contentSize
2747 };
2748 return rect;
2749 };
2750
2751 FrameGrid.propertyTypes = __assign(__assign({}, Grid.propertyTypes), {
2752 frame: PROPERTY_TYPE.RENDER_PROPERTY,
2753 useFrameFill: PROPERTY_TYPE.RENDER_PROPERTY,
2754 rectSize: PROPERTY_TYPE.RENDER_PROPERTY
2755 });
2756 FrameGrid.defaultOptions = __assign(__assign({}, Grid.defaultOptions), {
2757 frame: [],
2758 rectSize: 0,
2759 useFrameFill: true
2760 });
2761 FrameGrid = __decorate([GetterSetter], FrameGrid);
2762 return FrameGrid;
2763}(Grid);
2764/**
2765 * The shape of the grid. You can set the shape and order of items with a 2d array ([contentPos][inlinePos]). You can place items as many times as you fill the array with numbers, and zeros and spaces are empty spaces. The order of the items is arranged in ascending order of the numeric values that fill the array. (default: [])
2766 * @ko Grid의 모양. 2d 배열([contentPos][inlinePos])로 아이템의 모양과 순서를 설정할 수 있다. 숫자로 배열을 채운만큼 아이템을 배치할 수 있으며 0과 공백은 빈 공간이다. 아이템들의 순서는 배열을 채운 숫자값의 오름차순대로 배치가 된다. (default: [])
2767 * @name Grid.FrameGrid#frame
2768 * @type {$ts:Grid.FrameGrid.FrameGridOptions["frame"]}
2769 * @example
2770 * ```js
2771 * import { FrameGrid } from "@egjs/grid";
2772 *
2773 * // Item 1 : 2 x 2
2774 * // Item 2 : 1 x 1
2775 * // Item 3 : 1 x 2
2776 * // Item 4 : 1 x 1
2777 * // Item 5 : 2 x 1
2778 * const grid = new FrameGrid(container, {
2779 * frame: [
2780 * [1, 1, 0, 0, 2, 3],
2781 * [1, 1, 0, 4, 5, 5],
2782 * ],
2783 * });
2784 *
2785 * // Item 1 : 2 x 2
2786 * // Item 2 : 2 x 2
2787 * grid.frame = [
2788 * [1, 1, 0, 0, 2, 2],
2789 * [1, 1, 0, 0, 2, 2],
2790 * ];
2791 * ```
2792 */
2793
2794/**
2795 * Make sure that the frame can be attached after the previous frame. (default: true)
2796 * @ko 다음 프레임이 전 프레임에 이어 붙일 수 있는지 있는지 확인한다. (default: true)
2797 * @name Grid.FrameGrid#useFrameFill
2798 * @type {$ts:Grid.FrameGrid.FrameGridOptions["useFrameFill"]}
2799 * @example
2800 * ```js
2801 * import { FrameGrid } from "@egjs/grid";
2802 *
2803 * const grid = new FrameGrid(container, {
2804 * useFrameFill: true,
2805 * });
2806 *
2807 * grid.useFrameFill = false;
2808 * ```
2809 */
2810
2811/**
2812 * 1x1 rect size. If it is 0, it is determined by the number of columns in the frame. (default: 0)
2813 * @ko 1x1 직사각형 크기. 0이면 frame의 column의 개수에 의해 결정된다. (default: 0)
2814 * @name Grid.FrameGrid#rectSize
2815 * @type {$ts:Grid.FrameGrid.FrameGridOptions["rectSize"]}
2816 * @example
2817 * ```js
2818 * import { FrameGrid } from "@egjs/grid";
2819 *
2820 * const grid = new FrameGrid(container, {
2821 * rectSize: 0,
2822 * });
2823 *
2824 * grid.rectSize = { inlineSize: 100, contentSize: 150 };
2825 * ```
2826 */
2827
2828var BoxModel =
2829/*#__PURE__*/
2830function () {
2831 function BoxModel(status) {
2832 var boxStatus = __assign({
2833 orgInlineSize: 0,
2834 orgContentSize: 0,
2835 inlineSize: 0,
2836 contentSize: 0,
2837 inlinePos: 0,
2838 contentPos: 0,
2839 items: []
2840 }, status);
2841
2842 for (var name in boxStatus) {
2843 this[name] = boxStatus[name];
2844 }
2845 }
2846
2847 var __proto = BoxModel.prototype;
2848
2849 __proto.scaleTo = function (inlineSize, contentSize) {
2850 var scaleX = this.inlineSize ? inlineSize / this.inlineSize : 0;
2851 var scaleY = this.contentSize ? contentSize / this.contentSize : 0;
2852 this.items.forEach(function (item) {
2853 if (scaleX !== 0) {
2854 item.inlinePos *= scaleX;
2855 item.inlineSize *= scaleX;
2856 }
2857
2858 if (scaleY !== 0) {
2859 item.contentPos *= scaleY;
2860 item.contentSize *= scaleY;
2861 }
2862 });
2863 this.inlineSize = inlineSize;
2864 this.contentSize = contentSize;
2865 };
2866
2867 __proto.push = function (item) {
2868 this.items.push(item);
2869 };
2870
2871 __proto.getOrgSizeWeight = function () {
2872 return this.orgInlineSize * this.orgContentSize;
2873 };
2874
2875 __proto.getSize = function () {
2876 return this.inlineSize * this.contentSize;
2877 };
2878
2879 __proto.getOrgRatio = function () {
2880 return this.orgContentSize === 0 ? 0 : this.orgInlineSize / this.orgContentSize;
2881 };
2882
2883 __proto.getRatio = function () {
2884 return this.contentSize === 0 ? 0 : this.inlineSize / this.contentSize;
2885 };
2886
2887 return BoxModel;
2888}();
2889
2890function getCost(originLength, length) {
2891 var cost = originLength / length;
2892
2893 if (cost < 1) {
2894 cost = 1 / cost;
2895 }
2896
2897 return cost - 1;
2898}
2899
2900function fitArea(item, bestFitArea, itemFitSize, containerFitSize, isContentDirection) {
2901 item.contentSize = itemFitSize.contentSize;
2902 item.inlineSize = itemFitSize.inlineSize;
2903 bestFitArea.contentSize = containerFitSize.contentSize;
2904 bestFitArea.inlineSize = containerFitSize.inlineSize;
2905
2906 if (isContentDirection) {
2907 item.contentPos = bestFitArea.contentPos + bestFitArea.contentSize;
2908 item.inlinePos = bestFitArea.inlinePos;
2909 } else {
2910 item.inlinePos = bestFitArea.inlinePos + bestFitArea.inlineSize;
2911 item.contentPos = bestFitArea.contentPos;
2912 }
2913}
2914/**
2915 * The PackingGrid is a grid that shows the important items bigger without sacrificing the weight of the items.
2916 * Rows and columns are separated so that items are dynamically placed within the horizontal and vertical space rather than arranged in an orderly fashion.
2917 * If `sizeWeight` is higher than `ratioWeight`, the size of items is preserved as much as possible.
2918 * Conversely, if `ratioWeight` is higher than `sizeWeight`, the ratio of items is preserved as much as possible.
2919 * @ko PackingGrid는 아이템의 본래 크기에 따른 비중을 해치지 않으면서 중요한 카드는 더 크게 보여 주는 레이아웃이다.
2920 * 행과 열이 구분돼 아이템을 정돈되게 배치하는 대신 가로세로 일정 공간 내에서 동적으로 아이템을 배치한다.
2921 * `sizeWeight`가 `ratioWeight`보다 높으면 아이템들의 size가 최대한 보존이 된다.
2922 * 반대로 `ratioWeight`가 `sizeWeight`보다 높으면 아이템들의 비율이 최대한 보존이 된다.
2923 * @memberof Grid
2924 * @param {HTMLElement | string} container - A base element for a module <ko>모듈을 적용할 기준 엘리먼트</ko>
2925 * @param {Grid.PackingGrid.PackingGridOptions} options - The option object of the PackingGrid module <ko>PackingGrid 모듈의 옵션 객체</ko>
2926 */
2927
2928
2929var PackingGrid =
2930/*#__PURE__*/
2931function (_super) {
2932 __extends(PackingGrid, _super);
2933
2934 function PackingGrid() {
2935 return _super !== null && _super.apply(this, arguments) || this;
2936 }
2937
2938 var __proto = PackingGrid.prototype;
2939
2940 __proto.applyGrid = function (items, direction, outline) {
2941 var _this = this;
2942
2943 var _a = this.options,
2944 aspectRatio = _a.aspectRatio,
2945 gap = _a.gap;
2946 var containerInlineSize = this.getContainerInlineSize();
2947 var containerContentSize = containerInlineSize / aspectRatio;
2948 var prevOutline = outline.length ? outline : [0];
2949 var startPoint = direction === "end" ? Math.max.apply(Math, prevOutline) : Math.min.apply(Math, prevOutline) - containerContentSize - gap;
2950 var endPoint = startPoint + containerContentSize + gap;
2951 var container = new BoxModel({});
2952 items.forEach(function (item) {
2953 var model = new BoxModel({
2954 inlineSize: item.orgInlineSize,
2955 contentSize: item.orgContentSize,
2956 orgInlineSize: item.orgInlineSize,
2957 orgContentSize: item.orgContentSize
2958 });
2959
2960 _this._findBestFitArea(container, model);
2961
2962 container.push(model);
2963 container.scaleTo(containerInlineSize + gap, containerContentSize + gap);
2964 });
2965 items.forEach(function (item, i) {
2966 var boxItem = container.items[i];
2967 var inlineSize = boxItem.inlineSize - gap;
2968 var contentSize = boxItem.contentSize - gap;
2969 var contentPos = startPoint + boxItem.contentPos;
2970 var inlinePos = boxItem.inlinePos;
2971 item.setCSSGridRect({
2972 inlinePos: inlinePos,
2973 contentPos: contentPos,
2974 inlineSize: inlineSize,
2975 contentSize: contentSize
2976 });
2977 });
2978 return {
2979 start: [startPoint],
2980 end: [endPoint]
2981 };
2982 };
2983
2984 __proto._findBestFitArea = function (container, item) {
2985 if (container.getRatio() === 0) {
2986 // 아이템 최초 삽입시 전체영역 지정
2987 container.orgInlineSize = item.inlineSize;
2988 container.orgContentSize = item.contentSize;
2989 container.inlineSize = item.inlineSize;
2990 container.contentSize = item.contentSize;
2991 return;
2992 }
2993
2994 var bestFitArea;
2995 var minCost = Infinity;
2996 var isContentDirection = false;
2997 var itemFitSize = {
2998 inlineSize: 0,
2999 contentSize: 0
3000 };
3001 var containerFitSize = {
3002 inlineSize: 0,
3003 contentSize: 0
3004 };
3005
3006 var sizeWeight = this._getWeight("size");
3007
3008 var ratioWeight = this._getWeight("ratio");
3009
3010 container.items.forEach(function (child) {
3011 var containerSizeCost = getCost(child.getOrgSizeWeight(), child.getSize()) * sizeWeight;
3012 var containerRatioCost = getCost(child.getOrgRatio(), child.getRatio()) * ratioWeight;
3013 var inlineSize = child.inlineSize;
3014 var contentSize = child.contentSize;
3015
3016 for (var i = 0; i < 2; ++i) {
3017 var itemInlineSize = void 0;
3018 var itemContentSize = void 0;
3019 var containerInlineSize = void 0;
3020 var containerContentSize = void 0;
3021
3022 if (i === 0) {
3023 // add item to content pos (top, bottom)
3024 itemInlineSize = inlineSize;
3025 itemContentSize = contentSize * (item.contentSize / (child.orgContentSize + item.contentSize));
3026 containerInlineSize = inlineSize;
3027 containerContentSize = contentSize - itemContentSize;
3028 } else {
3029 // add item to inline pos (left, right)
3030 itemContentSize = contentSize;
3031 itemInlineSize = inlineSize * (item.inlineSize / (child.orgInlineSize + item.inlineSize));
3032 containerContentSize = contentSize;
3033 containerInlineSize = inlineSize - itemInlineSize;
3034 }
3035
3036 var itemSize = itemInlineSize * itemContentSize;
3037 var itemRatio = itemInlineSize / itemContentSize;
3038 var containerSize = containerInlineSize * containerContentSize;
3039 var containerRatio = containerContentSize / containerContentSize;
3040 var cost = getCost(item.getSize(), itemSize) * sizeWeight;
3041 cost += getCost(item.getRatio(), itemRatio) * ratioWeight;
3042 cost += getCost(child.getOrgSizeWeight(), containerSize) * sizeWeight - containerSizeCost;
3043 cost += getCost(child.getOrgRatio(), containerRatio) * ratioWeight - containerRatioCost;
3044
3045 if (cost === Math.min(cost, minCost)) {
3046 minCost = cost;
3047 bestFitArea = child;
3048 isContentDirection = i === 0;
3049 itemFitSize.inlineSize = itemInlineSize;
3050 itemFitSize.contentSize = itemContentSize;
3051 containerFitSize.inlineSize = containerInlineSize;
3052 containerFitSize.contentSize = containerContentSize;
3053 }
3054 }
3055 });
3056 fitArea(item, bestFitArea, itemFitSize, containerFitSize, isContentDirection);
3057 };
3058
3059 __proto._getWeight = function (type) {
3060 var options = this.options;
3061 var weightPriority = options.weightPriority;
3062
3063 if (weightPriority === type) {
3064 return 100;
3065 } else if (weightPriority === "custom") {
3066 return options[type + "Weight"];
3067 }
3068
3069 return 1;
3070 };
3071
3072 PackingGrid.propertyTypes = __assign(__assign({}, Grid.propertyTypes), {
3073 aspectRatio: PROPERTY_TYPE.RENDER_PROPERTY,
3074 sizeWeight: PROPERTY_TYPE.RENDER_PROPERTY,
3075 ratioWeight: PROPERTY_TYPE.RENDER_PROPERTY,
3076 weightPriority: PROPERTY_TYPE.RENDER_PROPERTY
3077 });
3078 PackingGrid.defaultOptions = __assign(__assign({}, Grid.defaultOptions), {
3079 aspectRatio: 1,
3080 sizeWeight: 1,
3081 ratioWeight: 1,
3082 weightPriority: "custom"
3083 });
3084 PackingGrid = __decorate([GetterSetter], PackingGrid);
3085 return PackingGrid;
3086}(Grid);
3087/**
3088 * The aspect ratio (inlineSize / contentSize) of the container with items. (default: 1)
3089 * @ko 아이템들을 가진 컨테이너의 종횡비(inlineSize / contentSize). (default: 1)
3090 * @name Grid.PackingGrid#aspectRatio
3091 * @type {$ts:Grid.PackingGrid.PackingGridOptions["aspectRatio"]}
3092 * @example
3093 * ```js
3094 * import { PackingGrid } from "@egjs/grid";
3095 *
3096 * const grid = new PackingGrid(container, {
3097 * aspectRatio: 1,
3098 * });
3099 *
3100 * grid.aspectRatio = 1.5;
3101 * ```
3102 */
3103
3104/**
3105 * The priority that determines the weight of the item. (default: "custom"), "size" = (sizeWieght: 2, ratioWeight: 1), "ratio" = (sizeWeight: 1, ratioWeight; 2), "custom" = (set sizeWeight, ratioWeight)
3106 * item's weight = item's ratio(inlineSize / contentSize) change * `ratioWeight` + size(inlineSize * contentSize) change * `sizeWeight`.
3107 * @ko 아이템의 가중치를 결정하는 우선수치. (default: "custom"), "size" = (sizeWieght: 2, ratioWeight: 1), "ratio" = (sizeWeight: 1, ratioWeight; 2), "custom" = (set sizeWeight, ratioWeight). 아이템의 가중치 = ratio(inlineSize / contentSize)의 변화량 * `ratioWeight` + size(inlineSize * contentSize)의 변화량 * `sizeWeight`.
3108 * @name Grid.PackingGrid#weightPriority
3109 * @type {$ts:Grid.PackingGrid.PackingGridOptions["weightPriority"]}
3110 * @example
3111 * ```js
3112 * import { PackingGrid } from "@egjs/grid";
3113 *
3114 * const grid = new PackingGrid(container, {
3115 * weightPriority: "custom",
3116 * sizeWeight: 1,
3117 * ratioWeight: 1,
3118 * });
3119 *
3120 * grid.weightPriority = "size";
3121 * // or
3122 * grid.weightPriority = "ratio";
3123 * ```
3124 */
3125
3126/**
3127 * The size weight when placing items. (default: 1)
3128 * @ko 아이템들을 배치하는데 사이즈 가중치. (default: 1)
3129 * @name Grid.PackingGrid#sizeWeight
3130 * @type {$ts:Grid.PackingGrid.PackingGridOptions["sizeWeight"]}
3131 * @example
3132 * ```js
3133 * import { PackingGrid } from "@egjs/grid";
3134 *
3135 * const grid = new PackingGrid(container, {
3136 * sizeWeight: 1,
3137 * });
3138 *
3139 * grid.sizeWeight = 10;
3140 * ```
3141 */
3142
3143/**
3144 * The weight to keep ratio when placing items. (default: 1)
3145 * @ko 아이템들을 배치하는데 비율을 유지하는 가중치. (default: 1)
3146 * @name Grid.PackingGrid#ratioWeight
3147 * @type {$ts:Grid.PackingGrid.PackingGridOptions["ratioWeight"]}
3148 * @example
3149 * ```js
3150 * import { PackingGrid } from "@egjs/grid";
3151 *
3152 * const grid = new PackingGrid(container, {
3153 * ratioWeight: 1,
3154 * });
3155 *
3156 * grid.ratioWeight = 10;
3157 * ```
3158 */
3159
3160/**
3161 * egjs-grid
3162 * Copyright (c) 2021-present NAVER Corp.
3163 * MIT license
3164 */
3165
3166var modules = {
3167 __proto__: null,
3168 'default': Grid,
3169 GetterSetter: GetterSetter,
3170 withGridMethods: withGridMethods,
3171 withMethods: withMethods,
3172 MasonryGrid: MasonryGrid,
3173 JustifiedGrid: JustifiedGrid,
3174 FrameGrid: FrameGrid,
3175 PackingGrid: PackingGrid,
3176 ItemRenderer: ItemRenderer,
3177 GridItem: GridItem,
3178 ContainerManager: ContainerManager,
3179 DEFAULT_GRID_OPTIONS: DEFAULT_GRID_OPTIONS,
3180 get PROPERTY_TYPE () { return PROPERTY_TYPE; },
3181 get MOUNT_STATE () { return MOUNT_STATE; },
3182 get UPDATE_STATE () { return UPDATE_STATE; },
3183 GRID_PROPERTY_TYPES: GRID_PROPERTY_TYPES,
3184 GRID_METHODS: GRID_METHODS,
3185 GRID_EVENTS: GRID_EVENTS,
3186 RECT_NAMES: RECT_NAMES
3187};
3188
3189/**
3190 * egjs-grid
3191 * Copyright (c) 2021-present NAVER Corp.
3192 * MIT license
3193 */
3194
3195for (var name in modules) {
3196 Grid[name] = modules[name];
3197}
3198
3199module.exports = Grid;
3200//# sourceMappingURL=grid.cjs.js.map