etudes 0.56.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/MasonryGrid.d.ts +21 -101
- package/lib/MasonryGrid.js +186 -261
- package/lib/MasonryGrid.js.map +1 -1
- package/package.json +4 -4
package/lib/MasonryGrid.d.ts
CHANGED
|
@@ -1,104 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { CSSProperties, PureComponent, ReactNode } from 'react';
|
|
1
|
+
import { HTMLAttributes, PropsWithChildren } from 'react';
|
|
3
2
|
import { Orientation } from './types';
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
sections: number;
|
|
13
|
-
verticalSpacing: number;
|
|
14
|
-
height?: string;
|
|
15
|
-
width?: string;
|
|
16
|
-
}
|
|
3
|
+
export declare type Props = HTMLAttributes<HTMLDivElement> & PropsWithChildren<{
|
|
4
|
+
areSectionsAligned?: boolean;
|
|
5
|
+
horizontalSpacing?: number;
|
|
6
|
+
isReversed?: boolean;
|
|
7
|
+
orientation?: Orientation;
|
|
8
|
+
sections?: number;
|
|
9
|
+
verticalSpacing?: number;
|
|
10
|
+
}>;
|
|
17
11
|
/**
|
|
18
|
-
* This is a React component that
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* parallel to the orientation of the grid. This means that in a vertically
|
|
30
|
-
* oriented grid, *number of secitons* refers to the *number of rows*, whereas
|
|
31
|
-
* in a horizontally oriented grid, *number of sections* refers to the *number
|
|
32
|
-
* of columns*.
|
|
12
|
+
* This is a React component that arranges all of its immediate children in a masonry grid. Refrain
|
|
13
|
+
* from assigning CSS styles to it via `className` or `style` property, though they are still
|
|
14
|
+
* handled if absolutely necessary. Customize the grid via its supported properties. The grid can be
|
|
15
|
+
* in either vertical or horizontal orientation. The length of every child element *parallel to the
|
|
16
|
+
* direction of the orientation* is automatically set according to the number of sections specified
|
|
17
|
+
* for the grid. This means that in an horizontally oriented grid, the *width* of each child element
|
|
18
|
+
* is automatically set, whereas in a vertically oriented grid the *height* of each child element is
|
|
19
|
+
* automatically set. Additionally, the *number of sections* corresponds to the maximum the number
|
|
20
|
+
* of child elements present in the direction that is parallel to the orientation of the grid.
|
|
21
|
+
* Hence, in a vertically oriented grid, *number of secitons* refers to the *number of rows*,
|
|
22
|
+
* whereas in a horizontally oriented grid, *number of sections* refers to the *number of columns*.
|
|
33
23
|
*/
|
|
34
|
-
|
|
35
|
-
static defaultProps: Props;
|
|
36
|
-
static BASE_MODIFIER_CLASS_PREFIX: string;
|
|
37
|
-
private nodeRefs;
|
|
38
|
-
private minWidth;
|
|
39
|
-
private maxWidth;
|
|
40
|
-
private minHeight;
|
|
41
|
-
private maxHeight;
|
|
42
|
-
private updateDelegate?;
|
|
43
|
-
get width(): number;
|
|
44
|
-
get height(): number;
|
|
45
|
-
componentDidMount(): void;
|
|
46
|
-
componentDidUpdate(prevProps: Props): void;
|
|
47
|
-
componentWillUnmount(): void;
|
|
48
|
-
render(): JSX.Element;
|
|
49
|
-
update(info: DirtyInfo): void;
|
|
50
|
-
/**
|
|
51
|
-
* Repositions all the child elements of the grid.
|
|
52
|
-
*/
|
|
53
|
-
private repositionChildren;
|
|
54
|
-
/**
|
|
55
|
-
* Computes the index and current length of the next available section for a
|
|
56
|
-
* specific base value, based on a provided array of existing section lengths.
|
|
57
|
-
*
|
|
58
|
-
* @param currentSectionLengths - An array of the current section lengths.
|
|
59
|
-
* @param base - The base value of the item to be inserted into the grid, and
|
|
60
|
-
* to be used to evaluate the next available section.
|
|
61
|
-
*
|
|
62
|
-
* @returns An array consiting of the computed section index and its to-be
|
|
63
|
-
* length if a new item were to be placed in it.
|
|
64
|
-
*/
|
|
65
|
-
private computeNextAvailableSectionAndLengthByBase;
|
|
66
|
-
/**
|
|
67
|
-
* A helper function that computes the max section length of an array of
|
|
68
|
-
* section lengths. Only the first n = `base` sections are inspected.
|
|
69
|
-
*
|
|
70
|
-
* @param currentSectionLengths - An array of section lengths.
|
|
71
|
-
* @param base - The number representing the first n sections to inspect.
|
|
72
|
-
* Any non-numerical values will be ignored and return value
|
|
73
|
-
* will be based on all sections. A `base` value will be clamped
|
|
74
|
-
* between 1 and the maximum length of the array of section
|
|
75
|
-
* lengths.
|
|
76
|
-
*
|
|
77
|
-
* @returns The max section length.
|
|
78
|
-
*/
|
|
79
|
-
private computeMaxLength;
|
|
80
|
-
/**
|
|
81
|
-
* Computes the base value of an element from its classes.
|
|
82
|
-
*
|
|
83
|
-
* @param element - The HTML element.
|
|
84
|
-
*
|
|
85
|
-
* @returns The computed base value that is clamped between 1 and max number
|
|
86
|
-
* of sections.
|
|
87
|
-
*/
|
|
88
|
-
private computeBaseFromElement;
|
|
89
|
-
/**
|
|
90
|
-
* Reinitializes the update delegate. If there are images within the body
|
|
91
|
-
* of the masonry grid, the initialization will be deferred until all images
|
|
92
|
-
* are loaded.
|
|
93
|
-
*/
|
|
94
|
-
private reconfigureUpdateDelegate;
|
|
95
|
-
/**
|
|
96
|
-
* Scans an HTML string and returns all the image sources.
|
|
97
|
-
*
|
|
98
|
-
* @param htmlString The HTML string.
|
|
99
|
-
*
|
|
100
|
-
* @returns The image sources.
|
|
101
|
-
*/
|
|
102
|
-
private getAllImageSources;
|
|
103
|
-
}
|
|
104
|
-
export default MasonryGrid;
|
|
24
|
+
export default function MasonryGrid({ areSectionsAligned, children, horizontalSpacing, isReversed, orientation, sections, style, verticalSpacing, ...props }: Props): JSX.Element;
|
package/lib/MasonryGrid.js
CHANGED
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
2
|
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
|
|
18
3
|
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
|
|
19
4
|
return cooked;
|
|
@@ -52,6 +37,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
52
37
|
__setModuleDefault(result, mod);
|
|
53
38
|
return result;
|
|
54
39
|
};
|
|
40
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
41
|
+
var t = {};
|
|
42
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
43
|
+
t[p] = s[p];
|
|
44
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
45
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
46
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
47
|
+
t[p[i]] = s[p[i]];
|
|
48
|
+
}
|
|
49
|
+
return t;
|
|
50
|
+
};
|
|
55
51
|
var __read = (this && this.__read) || function (o, n) {
|
|
56
52
|
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
57
53
|
if (!m) return o;
|
|
@@ -81,128 +77,177 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
81
77
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
82
78
|
};
|
|
83
79
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
84
|
-
var dirty_dom_1 = require("dirty-dom");
|
|
85
80
|
var react_1 = __importStar(require("react"));
|
|
86
81
|
var spase_1 = require("spase");
|
|
87
82
|
var styled_components_1 = __importDefault(require("styled-components"));
|
|
83
|
+
var useResizeEffect_1 = __importDefault(require("./hooks/useResizeEffect"));
|
|
88
84
|
var debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:masonry-grid') : function () { };
|
|
85
|
+
var BASE_MODIFIER_CLASS_PREFIX = 'base-';
|
|
89
86
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* child element is automatically set. Additionally, the *number of sections*
|
|
100
|
-
* means maximum the number of child elements present in the direction that is
|
|
101
|
-
* parallel to the orientation of the grid. This means that in a vertically
|
|
102
|
-
* oriented grid, *number of secitons* refers to the *number of rows*, whereas
|
|
103
|
-
* in a horizontally oriented grid, *number of sections* refers to the *number
|
|
104
|
-
* of columns*.
|
|
87
|
+
* Computes the index and current length of the next available section for a specific base value,
|
|
88
|
+
* based on a provided array of existing section lengths.
|
|
89
|
+
*
|
|
90
|
+
* @param currentSectionLengths - An array of the current section lengths.
|
|
91
|
+
* @param base - The base value of the item to be inserted into the grid, and to be used to evaluate
|
|
92
|
+
* the next available section.
|
|
93
|
+
*
|
|
94
|
+
* @returns An array consiting of the computed section index and its to-be length if a new item were
|
|
95
|
+
* to be placed in it.
|
|
105
96
|
*/
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return _this;
|
|
119
|
-
}
|
|
120
|
-
Object.defineProperty(MasonryGrid.prototype, "width", {
|
|
121
|
-
get: function () {
|
|
122
|
-
var _a, _b;
|
|
123
|
-
return (_b = (_a = spase_1.Rect.from(this.nodeRefs.root.current)) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : 0;
|
|
124
|
-
},
|
|
125
|
-
enumerable: false,
|
|
126
|
-
configurable: true
|
|
127
|
-
});
|
|
128
|
-
Object.defineProperty(MasonryGrid.prototype, "height", {
|
|
129
|
-
get: function () {
|
|
130
|
-
var _a, _b;
|
|
131
|
-
return (_b = (_a = spase_1.Rect.from(this.nodeRefs.root.current)) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : 0;
|
|
132
|
-
},
|
|
133
|
-
enumerable: false,
|
|
134
|
-
configurable: true
|
|
135
|
-
});
|
|
136
|
-
MasonryGrid.prototype.componentDidMount = function () {
|
|
137
|
-
this.reconfigureUpdateDelegate();
|
|
138
|
-
};
|
|
139
|
-
MasonryGrid.prototype.componentDidUpdate = function (prevProps) {
|
|
140
|
-
this.reconfigureUpdateDelegate();
|
|
141
|
-
};
|
|
142
|
-
MasonryGrid.prototype.componentWillUnmount = function () {
|
|
143
|
-
var _a;
|
|
144
|
-
(_a = this.updateDelegate) === null || _a === void 0 ? void 0 : _a.deinit();
|
|
145
|
-
};
|
|
146
|
-
MasonryGrid.prototype.render = function () {
|
|
147
|
-
var _a, _b;
|
|
148
|
-
return (react_1.default.createElement(StyledRoot, { ref: this.nodeRefs.root, className: this.props.className, orientation: this.props.orientation, style: __assign(__assign({}, this.props.style), { height: (_a = this.props.height) !== null && _a !== void 0 ? _a : ((this.props.orientation === 'vertical' && !isNaN(this.minHeight)) ? "".concat(this.minHeight, "px") : ''), width: (_b = this.props.width) !== null && _b !== void 0 ? _b : ((this.props.orientation === 'horizontal' && !isNaN(this.minWidth)) ? "".concat(this.minWidth, "px") : ''), flex: '0 0 auto', padding: '0' }) }, this.props.children));
|
|
149
|
-
};
|
|
150
|
-
MasonryGrid.prototype.update = function (info) {
|
|
151
|
-
var _a = info, _b = dirty_dom_1.DirtyType.SIZE, dirtySize = _a[_b];
|
|
152
|
-
if (dirtySize) {
|
|
153
|
-
if ((this.minWidth !== this.width) || (this.minHeight !== this.height) || (dirtySize.maxSize.width !== this.maxWidth) || dirtySize.maxSize.height !== this.maxHeight) {
|
|
154
|
-
this.repositionChildren();
|
|
155
|
-
this.maxWidth = dirtySize.maxSize.width;
|
|
156
|
-
this.maxHeight = dirtySize.maxSize.height;
|
|
97
|
+
function computeNextAvailableSectionAndLengthByBase(currentSectionLengths, base) {
|
|
98
|
+
var numSections = currentSectionLengths.length;
|
|
99
|
+
var sectionIdx = NaN;
|
|
100
|
+
var minLength = Infinity;
|
|
101
|
+
for (var i = 0; i < numSections; i++) {
|
|
102
|
+
var length_1 = currentSectionLengths[i];
|
|
103
|
+
var isShorter = length_1 < minLength;
|
|
104
|
+
var isEligibleSection = (i + base) <= numSections;
|
|
105
|
+
var hasRoomInSubsequentSections = true;
|
|
106
|
+
for (var j = 1; j < base; j++) {
|
|
107
|
+
if (currentSectionLengths[i + j] > length_1) {
|
|
108
|
+
hasRoomInSubsequentSections = false;
|
|
157
109
|
}
|
|
158
110
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
111
|
+
if (isShorter && isEligibleSection && hasRoomInSubsequentSections) {
|
|
112
|
+
sectionIdx = i;
|
|
113
|
+
minLength = length_1;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (isNaN(sectionIdx)) {
|
|
117
|
+
return [0, computeMaxLength(currentSectionLengths, base)];
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
return [sectionIdx, minLength];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* A helper function that computes the max section length of an array of section lengths. Only the
|
|
125
|
+
* first n = `base` sections are inspected.
|
|
126
|
+
*
|
|
127
|
+
* @param currentSectionLengths - An array of section lengths.
|
|
128
|
+
* @param base - The number representing the first n sections to inspect. Any non-numerical values
|
|
129
|
+
* will be ignored and return value will be based on all sections. A `base` value will
|
|
130
|
+
* be clamped between 1 and the maximum length of the array of section lengths.
|
|
131
|
+
*
|
|
132
|
+
* @returns The max section length.
|
|
133
|
+
*/
|
|
134
|
+
function computeMaxLength(currentSectionLengths, base) {
|
|
135
|
+
var arr = currentSectionLengths;
|
|
136
|
+
if (base !== undefined && base !== null && !isNaN(base)) {
|
|
137
|
+
arr = arr.slice(0, Math.max(1, Math.min(base, currentSectionLengths.length)));
|
|
138
|
+
}
|
|
139
|
+
return arr.reduce(function (out, curr, i) { return (curr > out) ? curr : out; }, 0);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Computes the base value of an element from its classes.
|
|
143
|
+
*
|
|
144
|
+
* @param element - The HTML element.
|
|
145
|
+
* @param numSections - Total number of sections.
|
|
146
|
+
*
|
|
147
|
+
* @returns The computed base value that is clamped between 1 and max number of sections.
|
|
148
|
+
*/
|
|
149
|
+
function computeBaseFromElement(element, numSections) {
|
|
150
|
+
var classList = element.classList;
|
|
151
|
+
for (var i = 0; i < classList.length; i++) {
|
|
152
|
+
var c = classList[i];
|
|
153
|
+
if (c.startsWith(BASE_MODIFIER_CLASS_PREFIX)) {
|
|
154
|
+
var base = parseFloat(c.replace(BASE_MODIFIER_CLASS_PREFIX, ''));
|
|
155
|
+
if (!isNaN(base))
|
|
156
|
+
return Math.min(Math.max(base, 1), numSections);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return 1;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Scans an HTML string and returns all the image sources.
|
|
163
|
+
*
|
|
164
|
+
* @param htmlString The HTML string.
|
|
165
|
+
*
|
|
166
|
+
* @returns The image sources.
|
|
167
|
+
*/
|
|
168
|
+
function getAllImageSources(htmlString) {
|
|
169
|
+
var _a, _b;
|
|
170
|
+
if (!htmlString)
|
|
171
|
+
return [];
|
|
172
|
+
var regexImg = /<img.*?src=("|')(.*?)("|')/g;
|
|
173
|
+
var regexSrc = /<img.*?src=("|')(.*?)("|')/;
|
|
174
|
+
var imageTags = (_a = htmlString.match(regexImg)) !== null && _a !== void 0 ? _a : [];
|
|
175
|
+
var out = [];
|
|
176
|
+
for (var i = 0; i < imageTags.length; i++) {
|
|
177
|
+
var tag = imageTags[i];
|
|
178
|
+
var src = (_b = tag.match(regexSrc)) === null || _b === void 0 ? void 0 : _b[2];
|
|
179
|
+
if (!src)
|
|
180
|
+
continue;
|
|
181
|
+
out.push(src);
|
|
182
|
+
}
|
|
183
|
+
return out;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* This is a React component that arranges all of its immediate children in a masonry grid. Refrain
|
|
187
|
+
* from assigning CSS styles to it via `className` or `style` property, though they are still
|
|
188
|
+
* handled if absolutely necessary. Customize the grid via its supported properties. The grid can be
|
|
189
|
+
* in either vertical or horizontal orientation. The length of every child element *parallel to the
|
|
190
|
+
* direction of the orientation* is automatically set according to the number of sections specified
|
|
191
|
+
* for the grid. This means that in an horizontally oriented grid, the *width* of each child element
|
|
192
|
+
* is automatically set, whereas in a vertically oriented grid the *height* of each child element is
|
|
193
|
+
* automatically set. Additionally, the *number of sections* corresponds to the maximum the number
|
|
194
|
+
* of child elements present in the direction that is parallel to the orientation of the grid.
|
|
195
|
+
* Hence, in a vertically oriented grid, *number of secitons* refers to the *number of rows*,
|
|
196
|
+
* whereas in a horizontally oriented grid, *number of sections* refers to the *number of columns*.
|
|
197
|
+
*/
|
|
198
|
+
function MasonryGrid(_a) {
|
|
199
|
+
var _b = _a.areSectionsAligned, areSectionsAligned = _b === void 0 ? false : _b, children = _a.children, _c = _a.horizontalSpacing, horizontalSpacing = _c === void 0 ? 0 : _c, _d = _a.isReversed, isReversed = _d === void 0 ? false : _d, _e = _a.orientation, orientation = _e === void 0 ? 'vertical' : _e, _f = _a.sections, sections = _f === void 0 ? 3 : _f, _g = _a.style, style = _g === void 0 ? {} : _g, _h = _a.verticalSpacing, verticalSpacing = _h === void 0 ? 0 : _h, props = __rest(_a, ["areSectionsAligned", "children", "horizontalSpacing", "isReversed", "orientation", "sections", "style", "verticalSpacing"]);
|
|
200
|
+
var rootRef = (0, react_1.useRef)(null);
|
|
201
|
+
var _j = __read((0, react_1.useState)(NaN), 2), minWidth = _j[0], setMinWidth = _j[1];
|
|
202
|
+
var _k = __read((0, react_1.useState)(NaN), 2), minHeight = _k[0], setMinHeight = _k[1];
|
|
203
|
+
var _l = __read((0, react_1.useState)(NaN), 2), maxWidth = _l[0], setMaxWidth = _l[1];
|
|
204
|
+
var _m = __read((0, react_1.useState)(NaN), 2), maxHeight = _m[0], setMaxHeight = _m[1];
|
|
205
|
+
var getCurrentWidth = function () { var _a, _b; return (_b = (_a = spase_1.Rect.from(rootRef.current)) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : 0; };
|
|
206
|
+
var getCurrentHeight = function () { var _a, _b; return (_b = (_a = spase_1.Rect.from(rootRef.current)) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : 0; };
|
|
207
|
+
var repositionChildren = function () {
|
|
164
208
|
var _a, _b, _c, _d;
|
|
165
|
-
var rootNode =
|
|
209
|
+
var rootNode = rootRef.current;
|
|
166
210
|
if (!rootNode)
|
|
167
211
|
return;
|
|
168
212
|
debug('Repositioning children... OK');
|
|
169
213
|
var children = rootNode.children;
|
|
170
|
-
var numSections =
|
|
214
|
+
var numSections = sections;
|
|
171
215
|
if (numSections <= 0)
|
|
172
216
|
throw new Error('You must specifiy a minimum of 1 section(s) (a.k.a. row(s) for horizontal orientation, column(s) for vertical orientation) for a MasonryGrid instance');
|
|
173
|
-
if (
|
|
217
|
+
if (orientation === 'vertical') {
|
|
174
218
|
var sectionHeights = __spreadArray([], __read(new Array(numSections)), false).map(function () { return 0; });
|
|
175
219
|
for (var i = 0; i < children.length; i++) {
|
|
176
220
|
var child = children[i];
|
|
177
221
|
if (!(child instanceof HTMLElement))
|
|
178
222
|
continue;
|
|
179
|
-
var base =
|
|
180
|
-
var _e = __read(
|
|
223
|
+
var base = computeBaseFromElement(child, sections);
|
|
224
|
+
var _e = __read(computeNextAvailableSectionAndLengthByBase(sectionHeights, base), 2), colIdx = _e[0], y = _e[1];
|
|
181
225
|
child.style.position = 'absolute';
|
|
182
|
-
child.style.width = "calc(".concat(100 / numSections * base, "% - ").concat((
|
|
226
|
+
child.style.width = "calc(".concat(100 / numSections * base, "% - ").concat((horizontalSpacing * (numSections - 1) / numSections) * base, "px + ").concat(horizontalSpacing * (base - 1), "px)");
|
|
183
227
|
child.style.height = '';
|
|
184
|
-
child.style.left = "calc(".concat(100 / numSections * colIdx, "% - ").concat((
|
|
185
|
-
child.style.top = "".concat(y + (y === 0 ? 0 :
|
|
228
|
+
child.style.left = "calc(".concat(100 / numSections * colIdx, "% - ").concat((horizontalSpacing * (numSections - 1) / numSections) * colIdx, "px + ").concat(horizontalSpacing * colIdx, "px)");
|
|
229
|
+
child.style.top = "".concat(y + (y === 0 ? 0 : verticalSpacing), "px");
|
|
186
230
|
for (var j = 0; j < base; j++) {
|
|
187
|
-
sectionHeights[colIdx + j] = y + (y === 0 ? 0 :
|
|
231
|
+
sectionHeights[colIdx + j] = y + (y === 0 ? 0 : verticalSpacing) + ((_b = (_a = spase_1.Rect.from(child)) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : 0);
|
|
188
232
|
}
|
|
189
|
-
if (
|
|
190
|
-
var m =
|
|
233
|
+
if (areSectionsAligned && ((colIdx + base) === numSections)) {
|
|
234
|
+
var m = computeMaxLength(sectionHeights);
|
|
191
235
|
for (var j = 0; j < numSections; j++) {
|
|
192
236
|
sectionHeights[j] = m;
|
|
193
237
|
}
|
|
194
238
|
}
|
|
195
239
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
240
|
+
var currWidth = getCurrentWidth();
|
|
241
|
+
setMinWidth(currWidth);
|
|
242
|
+
setMinHeight(computeMaxLength(sectionHeights, numSections));
|
|
243
|
+
rootNode.style.height = "".concat(minHeight, "px");
|
|
244
|
+
if (isReversed) {
|
|
200
245
|
for (var i = 0; i < children.length; i++) {
|
|
201
246
|
var child = children[i];
|
|
202
247
|
if (!(child instanceof HTMLElement))
|
|
203
248
|
continue;
|
|
204
249
|
var x = parseFloat(child.style.left);
|
|
205
|
-
child.style.left = "".concat(
|
|
250
|
+
child.style.left = "".concat(currWidth - x - parseFloat(child.style.width), "px");
|
|
206
251
|
}
|
|
207
252
|
}
|
|
208
253
|
}
|
|
@@ -212,185 +257,65 @@ var MasonryGrid = /** @class */ (function (_super) {
|
|
|
212
257
|
var child = children[i];
|
|
213
258
|
if (!(child instanceof HTMLElement))
|
|
214
259
|
continue;
|
|
215
|
-
var base =
|
|
216
|
-
var _f = __read(
|
|
260
|
+
var base = computeBaseFromElement(child, sections);
|
|
261
|
+
var _f = __read(computeNextAvailableSectionAndLengthByBase(sectionWidths, base), 2), rowIdx = _f[0], x = _f[1];
|
|
217
262
|
child.style.position = 'absolute';
|
|
218
263
|
child.style.width = '';
|
|
219
|
-
child.style.height = "calc(".concat(100 / numSections * base, "% - ").concat((
|
|
220
|
-
child.style.top = "calc(".concat(100 / numSections * rowIdx, "% - ").concat((
|
|
221
|
-
child.style.left = "".concat(x + (x === 0 ? 0 :
|
|
264
|
+
child.style.height = "calc(".concat(100 / numSections * base, "% - ").concat((verticalSpacing * (numSections - 1) / numSections) * base, "px + ").concat(verticalSpacing * (base - 1), "px)");
|
|
265
|
+
child.style.top = "calc(".concat(100 / numSections * rowIdx, "% - ").concat((verticalSpacing * (numSections - 1) / numSections) * rowIdx, "px + ").concat(verticalSpacing * rowIdx, "px)");
|
|
266
|
+
child.style.left = "".concat(x + (x === 0 ? 0 : horizontalSpacing), "px");
|
|
222
267
|
for (var j = 0; j < base; j++) {
|
|
223
|
-
sectionWidths[rowIdx + j] = x + (x === 0 ? 0 :
|
|
268
|
+
sectionWidths[rowIdx + j] = x + (x === 0 ? 0 : horizontalSpacing) + ((_d = (_c = spase_1.Rect.from(child)) === null || _c === void 0 ? void 0 : _c.width) !== null && _d !== void 0 ? _d : 0);
|
|
224
269
|
}
|
|
225
|
-
if (
|
|
226
|
-
var m =
|
|
270
|
+
if (areSectionsAligned && ((rowIdx + base) === numSections)) {
|
|
271
|
+
var m = computeMaxLength(sectionWidths);
|
|
227
272
|
for (var j = 0; j < numSections; j++) {
|
|
228
273
|
sectionWidths[j] = m;
|
|
229
274
|
}
|
|
230
275
|
}
|
|
231
276
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
277
|
+
var currHeight = getCurrentHeight();
|
|
278
|
+
setMinHeight(currHeight);
|
|
279
|
+
setMinWidth(computeMaxLength(sectionWidths, numSections));
|
|
280
|
+
if (!isNaN(minWidth))
|
|
281
|
+
rootNode.style.width = "".concat(minWidth, "px");
|
|
282
|
+
if (isReversed) {
|
|
237
283
|
for (var i = 0; i < children.length; i++) {
|
|
238
284
|
var child = children[i];
|
|
239
285
|
if (!(child instanceof HTMLElement))
|
|
240
286
|
continue;
|
|
241
287
|
var y = parseFloat(child.style.top);
|
|
242
|
-
child.style.top = "".concat(
|
|
288
|
+
child.style.top = "".concat(currHeight - y - parseFloat(child.style.height), "px");
|
|
243
289
|
}
|
|
244
290
|
}
|
|
245
291
|
}
|
|
246
292
|
};
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
* @returns An array consiting of the computed section index and its to-be
|
|
256
|
-
* length if a new item were to be placed in it.
|
|
257
|
-
*/
|
|
258
|
-
MasonryGrid.prototype.computeNextAvailableSectionAndLengthByBase = function (currentSectionLengths, base) {
|
|
259
|
-
if (currentSectionLengths.length !== this.props.sections)
|
|
260
|
-
throw new Error('Unmatched number of provided section lengths');
|
|
261
|
-
var numSections = currentSectionLengths.length;
|
|
262
|
-
var sectionIdx = NaN;
|
|
263
|
-
var minLength = Infinity;
|
|
264
|
-
for (var i = 0; i < numSections; i++) {
|
|
265
|
-
var length_1 = currentSectionLengths[i];
|
|
266
|
-
var isShorter = length_1 < minLength;
|
|
267
|
-
var isEligibleSection = (i + base) <= numSections;
|
|
268
|
-
var hasRoomInSubsequentSections = true;
|
|
269
|
-
for (var j = 1; j < base; j++) {
|
|
270
|
-
if (currentSectionLengths[i + j] > length_1) {
|
|
271
|
-
hasRoomInSubsequentSections = false;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (isShorter && isEligibleSection && hasRoomInSubsequentSections) {
|
|
275
|
-
sectionIdx = i;
|
|
276
|
-
minLength = length_1;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
if (isNaN(sectionIdx)) {
|
|
280
|
-
return [0, this.computeMaxLength(currentSectionLengths, base)];
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
return [sectionIdx, minLength];
|
|
284
|
-
}
|
|
285
|
-
};
|
|
286
|
-
/**
|
|
287
|
-
* A helper function that computes the max section length of an array of
|
|
288
|
-
* section lengths. Only the first n = `base` sections are inspected.
|
|
289
|
-
*
|
|
290
|
-
* @param currentSectionLengths - An array of section lengths.
|
|
291
|
-
* @param base - The number representing the first n sections to inspect.
|
|
292
|
-
* Any non-numerical values will be ignored and return value
|
|
293
|
-
* will be based on all sections. A `base` value will be clamped
|
|
294
|
-
* between 1 and the maximum length of the array of section
|
|
295
|
-
* lengths.
|
|
296
|
-
*
|
|
297
|
-
* @returns The max section length.
|
|
298
|
-
*/
|
|
299
|
-
MasonryGrid.prototype.computeMaxLength = function (currentSectionLengths, base) {
|
|
300
|
-
var arr = currentSectionLengths;
|
|
301
|
-
if (base !== undefined && base !== null && !isNaN(base)) {
|
|
302
|
-
arr = arr.slice(0, Math.max(1, Math.min(base, currentSectionLengths.length)));
|
|
303
|
-
}
|
|
304
|
-
return arr.reduce(function (out, curr, i) { return (curr > out) ? curr : out; }, 0);
|
|
305
|
-
};
|
|
306
|
-
/**
|
|
307
|
-
* Computes the base value of an element from its classes.
|
|
308
|
-
*
|
|
309
|
-
* @param element - The HTML element.
|
|
310
|
-
*
|
|
311
|
-
* @returns The computed base value that is clamped between 1 and max number
|
|
312
|
-
* of sections.
|
|
313
|
-
*/
|
|
314
|
-
MasonryGrid.prototype.computeBaseFromElement = function (element) {
|
|
315
|
-
var classList = element.classList;
|
|
316
|
-
for (var i = 0; i < classList.length; i++) {
|
|
317
|
-
var c = classList[i];
|
|
318
|
-
if (c.startsWith(MasonryGrid.BASE_MODIFIER_CLASS_PREFIX)) {
|
|
319
|
-
var base = parseFloat(c.replace(MasonryGrid.BASE_MODIFIER_CLASS_PREFIX, ''));
|
|
320
|
-
if (!isNaN(base))
|
|
321
|
-
return Math.min(Math.max(base, 1), this.props.sections);
|
|
293
|
+
(0, useResizeEffect_1.default)(rootRef, {
|
|
294
|
+
onResize: function (maxSize) {
|
|
295
|
+
var currWidth = getCurrentWidth();
|
|
296
|
+
var currHeight = getCurrentHeight();
|
|
297
|
+
if ((minWidth !== currWidth) || (minHeight !== currHeight) || (maxSize.width !== maxWidth) || maxSize.height !== maxHeight) {
|
|
298
|
+
repositionChildren();
|
|
299
|
+
setMaxWidth(maxSize.width);
|
|
300
|
+
setMaxHeight(maxSize.height);
|
|
322
301
|
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Reinitializes the update delegate. If there are images within the body
|
|
328
|
-
* of the masonry grid, the initialization will be deferred until all images
|
|
329
|
-
* are loaded.
|
|
330
|
-
*/
|
|
331
|
-
MasonryGrid.prototype.reconfigureUpdateDelegate = function () {
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
(0, react_1.useEffect)(function () {
|
|
332
305
|
var _a;
|
|
333
|
-
var
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
var numImages_1 = imageSources.length;
|
|
343
|
-
for (var i = 0; i < numImages_1; i++) {
|
|
344
|
-
var src = imageSources[i];
|
|
345
|
-
var image = new Image();
|
|
346
|
-
image.src = src;
|
|
347
|
-
image.onload = function () {
|
|
348
|
-
var _a;
|
|
349
|
-
if (++loaded_1 === numImages_1)
|
|
350
|
-
(_a = _this.updateDelegate) === null || _a === void 0 ? void 0 : _a.init();
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
else {
|
|
355
|
-
(_d = this.updateDelegate) === null || _d === void 0 ? void 0 : _d.init();
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
/**
|
|
359
|
-
* Scans an HTML string and returns all the image sources.
|
|
360
|
-
*
|
|
361
|
-
* @param htmlString The HTML string.
|
|
362
|
-
*
|
|
363
|
-
* @returns The image sources.
|
|
364
|
-
*/
|
|
365
|
-
MasonryGrid.prototype.getAllImageSources = function (htmlString) {
|
|
366
|
-
var _a, _b;
|
|
367
|
-
if (!htmlString)
|
|
368
|
-
return [];
|
|
369
|
-
var regexImg = /<img.*?src=("|')(.*?)("|')/g;
|
|
370
|
-
var regexSrc = /<img.*?src=("|')(.*?)("|')/;
|
|
371
|
-
var imageTags = (_a = htmlString.match(regexImg)) !== null && _a !== void 0 ? _a : [];
|
|
372
|
-
var out = [];
|
|
373
|
-
for (var i = 0; i < imageTags.length; i++) {
|
|
374
|
-
var tag = imageTags[i];
|
|
375
|
-
var src = (_b = tag.match(regexSrc)) === null || _b === void 0 ? void 0 : _b[2];
|
|
376
|
-
if (!src)
|
|
377
|
-
continue;
|
|
378
|
-
out.push(src);
|
|
306
|
+
var imageSources = getAllImageSources((_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.innerHTML);
|
|
307
|
+
if (imageSources.length === 0)
|
|
308
|
+
return;
|
|
309
|
+
var numImages = imageSources.length;
|
|
310
|
+
for (var i = 0; i < numImages; i++) {
|
|
311
|
+
var src = imageSources[i];
|
|
312
|
+
var image = new Image();
|
|
313
|
+
image.src = src;
|
|
314
|
+
image.onload = function () { return repositionChildren(); };
|
|
379
315
|
}
|
|
380
|
-
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
areSectionsAligned: false,
|
|
384
|
-
horizontalSpacing: 0,
|
|
385
|
-
isReversed: false,
|
|
386
|
-
orientation: 'vertical',
|
|
387
|
-
sections: 3,
|
|
388
|
-
style: {},
|
|
389
|
-
verticalSpacing: 0,
|
|
390
|
-
};
|
|
391
|
-
MasonryGrid.BASE_MODIFIER_CLASS_PREFIX = 'base-';
|
|
392
|
-
return MasonryGrid;
|
|
393
|
-
}(react_1.PureComponent));
|
|
316
|
+
}, []);
|
|
317
|
+
return (react_1.default.createElement(StyledRoot, __assign({}, props, { ref: rootRef, orientation: orientation, style: __assign(__assign({}, style), { flex: '0 0 auto', minHeight: ((orientation === 'vertical' && !isNaN(minHeight)) ? "".concat(minHeight, "px") : ''), minWidth: ((orientation === 'horizontal' && !isNaN(minWidth)) ? "".concat(minWidth, "px") : ''), padding: '0' }) }), children));
|
|
318
|
+
}
|
|
394
319
|
exports.default = MasonryGrid;
|
|
395
320
|
var StyledRoot = styled_components_1.default.div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n box-sizing: border-box;\n display: block;\n height: ", ";\n position: relative;\n width: ", ";\n"], ["\n box-sizing: border-box;\n display: block;\n height: ", ";\n position: relative;\n width: ", ";\n"])), function (props) { return props.orientation === 'vertical' ? 'auto' : '100%'; }, function (props) { return props.orientation === 'horizontal' ? 'auto' : '100%'; });
|
|
396
321
|
var templateObject_1;
|
package/lib/MasonryGrid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MasonryGrid.js","sourceRoot":"/","sources":["MasonryGrid.tsx"],"names":[],"mappings":"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","sourcesContent":["import { DirtyInfo, DirtyType, EventType, UpdateDelegate } from 'dirty-dom'\nimport React, { createRef, CSSProperties, PureComponent, ReactNode } from 'react'\nimport { Rect } from 'spase'\nimport styled from 'styled-components'\nimport { Orientation } from './types'\n\nconst debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:masonry-grid') : () => {}\n\nexport interface Props {\n className?: string\n style: CSSProperties\n children?: ReactNode | ReactNode[]\n areSectionsAligned: boolean\n isReversed: boolean\n horizontalSpacing: number\n orientation: Orientation\n sections: number\n verticalSpacing: number\n height?: string\n width?: string\n}\n\n/**\n * This is a React component that aligns all of its immediate children in a\n * masonry grid. Refrain from assigning CSS styles to it via `className` or\n * `style` property, although they are handled if absolutely necessary.\n * Customize the grid via its supported properties. The grid can be in either\n * vertical or horizontal orientation. The length of every child element\n * *parallel to the direction of the orientation* is automatically set according\n * to the number of sections specified for the grid. This means that in an\n * horizontally oriented grid, the *width* of each child element is\n * automatically set, whereas in a vertically oriented grid the *height* of each\n * child element is automatically set. Additionally, the *number of sections*\n * means maximum the number of child elements present in the direction that is\n * parallel to the orientation of the grid. This means that in a vertically\n * oriented grid, *number of secitons* refers to the *number of rows*, whereas\n * in a horizontally oriented grid, *number of sections* refers to the *number\n * of columns*.\n */\nclass MasonryGrid extends PureComponent<Props> {\n static defaultProps: Props = {\n areSectionsAligned: false,\n horizontalSpacing: 0,\n isReversed: false,\n orientation: 'vertical',\n sections: 3,\n style: {},\n verticalSpacing: 0,\n }\n\n static BASE_MODIFIER_CLASS_PREFIX = 'base-'\n\n private nodeRefs = {\n root: createRef<HTMLDivElement>(),\n }\n\n private minWidth = NaN\n private maxWidth = NaN\n private minHeight = NaN\n private maxHeight = NaN\n\n private updateDelegate?: UpdateDelegate = undefined\n\n get width(): number {\n return Rect.from(this.nodeRefs.root.current)?.width ?? 0\n }\n\n get height(): number {\n return Rect.from(this.nodeRefs.root.current)?.height ?? 0\n }\n\n componentDidMount() {\n this.reconfigureUpdateDelegate()\n }\n\n componentDidUpdate(prevProps: Props) {\n this.reconfigureUpdateDelegate()\n }\n\n componentWillUnmount() {\n this.updateDelegate?.deinit()\n }\n\n render() {\n return (\n <StyledRoot\n ref={this.nodeRefs.root}\n className={this.props.className}\n orientation={this.props.orientation}\n style={{\n ...this.props.style,\n height: this.props.height ?? ((this.props.orientation === 'vertical' && !isNaN(this.minHeight)) ? `${this.minHeight}px` : ''),\n width: this.props.width ?? ((this.props.orientation === 'horizontal' && !isNaN(this.minWidth)) ? `${this.minWidth}px` : ''),\n flex: '0 0 auto',\n padding: '0',\n }}\n >\n {this.props.children}\n </StyledRoot>\n )\n }\n\n update(info: DirtyInfo) {\n const { [DirtyType.SIZE]: dirtySize } = info\n\n if (dirtySize) {\n if ((this.minWidth !== this.width) || (this.minHeight !== this.height) || (dirtySize.maxSize.width !== this.maxWidth) || dirtySize.maxSize.height !== this.maxHeight) {\n this.repositionChildren()\n this.maxWidth = dirtySize.maxSize.width\n this.maxHeight = dirtySize.maxSize.height\n }\n }\n }\n\n /**\n * Repositions all the child elements of the grid.\n */\n private repositionChildren() {\n const rootNode = this.nodeRefs.root.current\n\n if (!rootNode) return\n\n debug('Repositioning children... OK')\n\n const children = rootNode.children\n const numSections = this.props.sections\n\n if (numSections <= 0) throw new Error('You must specifiy a minimum of 1 section(s) (a.k.a. row(s) for horizontal orientation, column(s) for vertical orientation) for a MasonryGrid instance')\n\n if (this.props.orientation === 'vertical') {\n const sectionHeights: number[] = [...new Array(numSections)].map(() => 0)\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n\n if (!(child instanceof HTMLElement)) continue\n\n const base = this.computeBaseFromElement(child)\n const [colIdx, y] = this.computeNextAvailableSectionAndLengthByBase(sectionHeights, base)\n\n child.style.position = 'absolute'\n child.style.width = `calc(${100 / numSections * base}% - ${(this.props.horizontalSpacing * (numSections - 1) / numSections) * base}px + ${this.props.horizontalSpacing * (base - 1)}px)`\n child.style.height = ''\n child.style.left = `calc(${100 / numSections * colIdx}% - ${(this.props.horizontalSpacing * (numSections - 1) / numSections) * colIdx}px + ${this.props.horizontalSpacing * colIdx}px)`\n child.style.top = `${y + (y === 0 ? 0 : this.props.verticalSpacing)}px`\n\n for (let j = 0; j < base; j++) {\n sectionHeights[colIdx + j] = y + (y === 0 ? 0 : this.props.verticalSpacing) + (Rect.from(child)?.height ?? 0)\n }\n\n if (this.props.areSectionsAligned && ((colIdx + base) === numSections)) {\n const m = this.computeMaxLength(sectionHeights)\n\n for (let j = 0; j < numSections; j++) {\n sectionHeights[j] = m\n }\n }\n }\n\n this.minWidth = this.width\n this.minHeight = this.computeMaxLength(sectionHeights, numSections)\n rootNode.style.height = `${this.minHeight}px`\n\n if (this.props.isReversed) {\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n\n if (!(child instanceof HTMLElement)) continue\n\n const x = parseFloat(child.style.left)\n\n child.style.left = `${this.width - x - parseFloat(child.style.width)}px`\n }\n }\n }\n else {\n const sectionWidths: number[] = [...new Array(numSections)].map(() => 0)\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n\n if (!(child instanceof HTMLElement)) continue\n\n const base = this.computeBaseFromElement(child)\n const [rowIdx, x] = this.computeNextAvailableSectionAndLengthByBase(sectionWidths, base)\n\n child.style.position = 'absolute'\n child.style.width = ''\n child.style.height = `calc(${100 / numSections * base}% - ${(this.props.verticalSpacing * (numSections - 1) / numSections) * base}px + ${this.props.verticalSpacing * (base - 1)}px)`\n child.style.top = `calc(${100 / numSections * rowIdx}% - ${(this.props.verticalSpacing * (numSections - 1) / numSections) * rowIdx}px + ${this.props.verticalSpacing * rowIdx}px)`\n child.style.left = `${x + (x === 0 ? 0 : this.props.horizontalSpacing)}px`\n\n for (let j = 0; j < base; j++) {\n sectionWidths[rowIdx + j] = x + (x === 0 ? 0 : this.props.horizontalSpacing) + (Rect.from(child)?.width ?? 0)\n }\n\n if (this.props.areSectionsAligned && ((rowIdx + base) === numSections)) {\n const m = this.computeMaxLength(sectionWidths)\n\n for (let j = 0; j < numSections; j++) {\n sectionWidths[j] = m\n }\n }\n }\n\n this.minHeight = this.height\n this.minWidth = this.computeMaxLength(sectionWidths, numSections)\n if (!isNaN(this.minWidth)) rootNode.style.width = `${this.minWidth}px`\n\n if (this.props.isReversed) {\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n\n if (!(child instanceof HTMLElement)) continue\n\n const y = parseFloat(child.style.top)\n\n child.style.top = `${this.height - y - parseFloat(child.style.height)}px`\n }\n }\n }\n }\n\n /**\n * Computes the index and current length of the next available section for a\n * specific base value, based on a provided array of existing section lengths.\n *\n * @param currentSectionLengths - An array of the current section lengths.\n * @param base - The base value of the item to be inserted into the grid, and\n * to be used to evaluate the next available section.\n *\n * @returns An array consiting of the computed section index and its to-be\n * length if a new item were to be placed in it.\n */\n private computeNextAvailableSectionAndLengthByBase(currentSectionLengths: number[], base: number): [number, number] {\n if (currentSectionLengths.length !== this.props.sections) throw new Error('Unmatched number of provided section lengths')\n\n const numSections = currentSectionLengths.length\n\n let sectionIdx = NaN\n let minLength = Infinity\n\n for (let i = 0; i < numSections; i++) {\n const length = currentSectionLengths[i]\n const isShorter = length < minLength\n const isEligibleSection = (i + base) <= numSections\n let hasRoomInSubsequentSections = true\n\n for (let j = 1; j < base; j++) {\n if (currentSectionLengths[i + j] > length) {\n hasRoomInSubsequentSections = false\n }\n }\n\n if (isShorter && isEligibleSection && hasRoomInSubsequentSections) {\n sectionIdx = i\n minLength = length\n }\n }\n\n if (isNaN(sectionIdx)) {\n return [0, this.computeMaxLength(currentSectionLengths, base)]\n }\n else {\n return [sectionIdx, minLength]\n }\n }\n\n /**\n * A helper function that computes the max section length of an array of\n * section lengths. Only the first n = `base` sections are inspected.\n *\n * @param currentSectionLengths - An array of section lengths.\n * @param base - The number representing the first n sections to inspect.\n * Any non-numerical values will be ignored and return value\n * will be based on all sections. A `base` value will be clamped\n * between 1 and the maximum length of the array of section\n * lengths.\n *\n * @returns The max section length.\n */\n private computeMaxLength(currentSectionLengths: number[], base?: number): number {\n let arr = currentSectionLengths\n\n if (base !== undefined && base !== null && !isNaN(base)) {\n arr = arr.slice(0, Math.max(1, Math.min(base, currentSectionLengths.length)))\n }\n\n return arr.reduce((out, curr, i) => (curr > out) ? curr : out, 0)\n }\n\n /**\n * Computes the base value of an element from its classes.\n *\n * @param element - The HTML element.\n *\n * @returns The computed base value that is clamped between 1 and max number\n * of sections.\n */\n private computeBaseFromElement(element: HTMLElement): number {\n const classList = element.classList\n\n for (let i = 0; i < classList.length; i++) {\n const c = classList[i]\n\n if (c.startsWith(MasonryGrid.BASE_MODIFIER_CLASS_PREFIX)) {\n const base = parseFloat(c.replace(MasonryGrid.BASE_MODIFIER_CLASS_PREFIX, ''))\n if (!isNaN(base)) return Math.min(Math.max(base, 1), this.props.sections)\n }\n }\n\n return 1\n }\n\n /**\n * Reinitializes the update delegate. If there are images within the body\n * of the masonry grid, the initialization will be deferred until all images\n * are loaded.\n */\n private reconfigureUpdateDelegate() {\n this.updateDelegate?.deinit()\n\n this.updateDelegate = new UpdateDelegate(info => this.update(info), {\n [EventType.RESIZE]: true,\n })\n\n const imageSources = this.getAllImageSources(this.nodeRefs.root.current?.innerHTML)\n\n if (imageSources.length > 0) {\n let loaded = 0\n const numImages = imageSources.length\n\n for (let i = 0; i < numImages; i++) {\n const src = imageSources[i]\n const image = new Image()\n image.src = src\n image.onload = () => {\n if (++loaded === numImages) this.updateDelegate?.init()\n }\n }\n }\n else {\n this.updateDelegate?.init()\n }\n }\n\n /**\n * Scans an HTML string and returns all the image sources.\n *\n * @param htmlString The HTML string.\n *\n * @returns The image sources.\n */\n private getAllImageSources(htmlString?: string): string[] {\n if (!htmlString) return []\n\n const regexImg = /<img.*?src=(\"|')(.*?)(\"|')/g\n const regexSrc = /<img.*?src=(\"|')(.*?)(\"|')/\n const imageTags = htmlString.match(regexImg) ?? []\n\n const out: string[] = []\n\n for (let i = 0; i < imageTags.length; i++) {\n const tag = imageTags[i]\n const src = tag.match(regexSrc)?.[2]\n\n if (!src) continue\n\n out.push(src)\n }\n\n return out\n }\n}\n\nexport default MasonryGrid\n\nconst StyledRoot = styled.div<{\n orientation: Props['orientation']\n}>`\n box-sizing: border-box;\n display: block;\n height: ${props => props.orientation === 'vertical' ? 'auto' : '100%'};\n position: relative;\n width: ${props => props.orientation === 'horizontal' ? 'auto' : '100%'};\n`\n"]}
|
|
1
|
+
{"version":3,"file":"MasonryGrid.js","sourceRoot":"/","sources":["MasonryGrid.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { HTMLAttributes, PropsWithChildren, useEffect, useRef, useState } from 'react'\nimport { Rect } from 'spase'\nimport styled from 'styled-components'\nimport useResizeEffect from './hooks/useResizeEffect'\nimport { Orientation } from './types'\n\nconst debug = process.env.NODE_ENV === 'development' ? require('debug')('etudes:masonry-grid') : () => {}\n\nexport type Props = HTMLAttributes<HTMLDivElement> & PropsWithChildren<{\n areSectionsAligned?: boolean\n horizontalSpacing?: number\n isReversed?: boolean\n orientation?: Orientation\n sections?: number\n verticalSpacing?: number\n}>\n\nconst BASE_MODIFIER_CLASS_PREFIX = 'base-'\n\n/**\n * Computes the index and current length of the next available section for a specific base value,\n * based on a provided array of existing section lengths.\n *\n * @param currentSectionLengths - An array of the current section lengths.\n * @param base - The base value of the item to be inserted into the grid, and to be used to evaluate\n * the next available section.\n *\n * @returns An array consiting of the computed section index and its to-be length if a new item were\n * to be placed in it.\n */\nfunction computeNextAvailableSectionAndLengthByBase(currentSectionLengths: number[], base: number): [number, number] {\n const numSections = currentSectionLengths.length\n\n let sectionIdx = NaN\n let minLength = Infinity\n\n for (let i = 0; i < numSections; i++) {\n const length = currentSectionLengths[i]\n const isShorter = length < minLength\n const isEligibleSection = (i + base) <= numSections\n let hasRoomInSubsequentSections = true\n\n for (let j = 1; j < base; j++) {\n if (currentSectionLengths[i + j] > length) {\n hasRoomInSubsequentSections = false\n }\n }\n\n if (isShorter && isEligibleSection && hasRoomInSubsequentSections) {\n sectionIdx = i\n minLength = length\n }\n }\n\n if (isNaN(sectionIdx)) {\n return [0, computeMaxLength(currentSectionLengths, base)]\n }\n else {\n return [sectionIdx, minLength]\n }\n}\n\n/**\n * A helper function that computes the max section length of an array of section lengths. Only the\n * first n = `base` sections are inspected.\n *\n * @param currentSectionLengths - An array of section lengths.\n * @param base - The number representing the first n sections to inspect. Any non-numerical values\n * will be ignored and return value will be based on all sections. A `base` value will\n * be clamped between 1 and the maximum length of the array of section lengths.\n *\n * @returns The max section length.\n */\nfunction computeMaxLength(currentSectionLengths: number[], base?: number): number {\n let arr = currentSectionLengths\n\n if (base !== undefined && base !== null && !isNaN(base)) {\n arr = arr.slice(0, Math.max(1, Math.min(base, currentSectionLengths.length)))\n }\n\n return arr.reduce((out, curr, i) => (curr > out) ? curr : out, 0)\n}\n\n/**\n * Computes the base value of an element from its classes.\n *\n * @param element - The HTML element.\n * @param numSections - Total number of sections.\n *\n * @returns The computed base value that is clamped between 1 and max number of sections.\n */\nfunction computeBaseFromElement(element: HTMLElement, numSections: number): number {\n const classList = element.classList\n\n for (let i = 0; i < classList.length; i++) {\n const c = classList[i]\n\n if (c.startsWith(BASE_MODIFIER_CLASS_PREFIX)) {\n const base = parseFloat(c.replace(BASE_MODIFIER_CLASS_PREFIX, ''))\n if (!isNaN(base)) return Math.min(Math.max(base, 1), numSections)\n }\n }\n\n return 1\n}\n\n/**\n * Scans an HTML string and returns all the image sources.\n *\n * @param htmlString The HTML string.\n *\n * @returns The image sources.\n */\nfunction getAllImageSources(htmlString?: string): string[] {\n if (!htmlString) return []\n\n const regexImg = /<img.*?src=(\"|')(.*?)(\"|')/g\n const regexSrc = /<img.*?src=(\"|')(.*?)(\"|')/\n const imageTags = htmlString.match(regexImg) ?? []\n\n const out: string[] = []\n\n for (let i = 0; i < imageTags.length; i++) {\n const tag = imageTags[i]\n const src = tag.match(regexSrc)?.[2]\n\n if (!src) continue\n\n out.push(src)\n }\n\n return out\n}\n\n/**\n * This is a React component that arranges all of its immediate children in a masonry grid. Refrain\n * from assigning CSS styles to it via `className` or `style` property, though they are still\n * handled if absolutely necessary. Customize the grid via its supported properties. The grid can be\n * in either vertical or horizontal orientation. The length of every child element *parallel to the\n * direction of the orientation* is automatically set according to the number of sections specified\n * for the grid. This means that in an horizontally oriented grid, the *width* of each child element\n * is automatically set, whereas in a vertically oriented grid the *height* of each child element is\n * automatically set. Additionally, the *number of sections* corresponds to the maximum the number\n * of child elements present in the direction that is parallel to the orientation of the grid.\n * Hence, in a vertically oriented grid, *number of secitons* refers to the *number of rows*,\n * whereas in a horizontally oriented grid, *number of sections* refers to the *number of columns*.\n */\nexport default function MasonryGrid({\n areSectionsAligned = false,\n children,\n horizontalSpacing= 0,\n isReversed = false,\n orientation = 'vertical',\n sections = 3,\n style = {},\n verticalSpacing = 0,\n ...props\n}: Props) {\n const rootRef = useRef<HTMLDivElement>(null)\n\n const [minWidth, setMinWidth] = useState(NaN)\n const [minHeight, setMinHeight] = useState(NaN)\n const [maxWidth, setMaxWidth] = useState(NaN)\n const [maxHeight, setMaxHeight] = useState(NaN)\n\n const getCurrentWidth = () => Rect.from(rootRef.current)?.width ?? 0\n\n const getCurrentHeight = () => Rect.from(rootRef.current)?.height ?? 0\n\n const repositionChildren = () => {\n const rootNode = rootRef.current\n\n if (!rootNode) return\n\n debug('Repositioning children... OK')\n\n const children = rootNode.children\n const numSections = sections\n\n if (numSections <= 0) throw new Error('You must specifiy a minimum of 1 section(s) (a.k.a. row(s) for horizontal orientation, column(s) for vertical orientation) for a MasonryGrid instance')\n\n if (orientation === 'vertical') {\n const sectionHeights: number[] = [...new Array(numSections)].map(() => 0)\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n\n if (!(child instanceof HTMLElement)) continue\n\n const base = computeBaseFromElement(child, sections)\n const [colIdx, y] = computeNextAvailableSectionAndLengthByBase(sectionHeights, base)\n\n child.style.position = 'absolute'\n child.style.width = `calc(${100 / numSections * base}% - ${(horizontalSpacing * (numSections - 1) / numSections) * base}px + ${horizontalSpacing * (base - 1)}px)`\n child.style.height = ''\n child.style.left = `calc(${100 / numSections * colIdx}% - ${(horizontalSpacing * (numSections - 1) / numSections) * colIdx}px + ${horizontalSpacing * colIdx}px)`\n child.style.top = `${y + (y === 0 ? 0 : verticalSpacing)}px`\n\n for (let j = 0; j < base; j++) {\n sectionHeights[colIdx + j] = y + (y === 0 ? 0 : verticalSpacing) + (Rect.from(child)?.height ?? 0)\n }\n\n if (areSectionsAligned && ((colIdx + base) === numSections)) {\n const m = computeMaxLength(sectionHeights)\n\n for (let j = 0; j < numSections; j++) {\n sectionHeights[j] = m\n }\n }\n }\n\n const currWidth = getCurrentWidth()\n\n setMinWidth(currWidth)\n setMinHeight(computeMaxLength(sectionHeights, numSections))\n rootNode.style.height = `${minHeight}px`\n\n if (isReversed) {\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n\n if (!(child instanceof HTMLElement)) continue\n\n const x = parseFloat(child.style.left)\n\n child.style.left = `${currWidth - x - parseFloat(child.style.width)}px`\n }\n }\n }\n else {\n const sectionWidths: number[] = [...new Array(numSections)].map(() => 0)\n\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n\n if (!(child instanceof HTMLElement)) continue\n\n const base = computeBaseFromElement(child, sections)\n const [rowIdx, x] = computeNextAvailableSectionAndLengthByBase(sectionWidths, base)\n\n child.style.position = 'absolute'\n child.style.width = ''\n child.style.height = `calc(${100 / numSections * base}% - ${(verticalSpacing * (numSections - 1) / numSections) * base}px + ${verticalSpacing * (base - 1)}px)`\n child.style.top = `calc(${100 / numSections * rowIdx}% - ${(verticalSpacing * (numSections - 1) / numSections) * rowIdx}px + ${verticalSpacing * rowIdx}px)`\n child.style.left = `${x + (x === 0 ? 0 : horizontalSpacing)}px`\n\n for (let j = 0; j < base; j++) {\n sectionWidths[rowIdx + j] = x + (x === 0 ? 0 : horizontalSpacing) + (Rect.from(child)?.width ?? 0)\n }\n\n if (areSectionsAligned && ((rowIdx + base) === numSections)) {\n const m = computeMaxLength(sectionWidths)\n\n for (let j = 0; j < numSections; j++) {\n sectionWidths[j] = m\n }\n }\n }\n\n const currHeight = getCurrentHeight()\n setMinHeight(currHeight)\n setMinWidth(computeMaxLength(sectionWidths, numSections))\n\n if (!isNaN(minWidth)) rootNode.style.width = `${minWidth}px`\n\n if (isReversed) {\n for (let i = 0; i < children.length; i++) {\n const child = children[i]\n\n if (!(child instanceof HTMLElement)) continue\n\n const y = parseFloat(child.style.top)\n\n child.style.top = `${currHeight - y - parseFloat(child.style.height)}px`\n }\n }\n }\n }\n\n useResizeEffect(rootRef, {\n onResize: maxSize => {\n const currWidth = getCurrentWidth()\n const currHeight = getCurrentHeight()\n\n if ((minWidth !== currWidth) || (minHeight !== currHeight) || (maxSize.width !== maxWidth) || maxSize.height !== maxHeight) {\n repositionChildren()\n setMaxWidth(maxSize.width)\n setMaxHeight(maxSize.height)\n }\n },\n })\n\n useEffect(() => {\n const imageSources = getAllImageSources(rootRef.current?.innerHTML)\n\n if (imageSources.length === 0) return\n\n const numImages = imageSources.length\n\n for (let i = 0; i < numImages; i++) {\n const src = imageSources[i]\n const image = new Image()\n image.src = src\n image.onload = () => repositionChildren()\n }\n }, [])\n\n return (\n <StyledRoot\n {...props}\n ref={rootRef}\n orientation={orientation}\n style={{\n ...style,\n flex: '0 0 auto',\n minHeight: ((orientation === 'vertical' && !isNaN(minHeight)) ? `${minHeight}px` : ''),\n minWidth: ((orientation === 'horizontal' && !isNaN(minWidth)) ? `${minWidth}px` : ''),\n padding: '0',\n }}\n >\n {children}\n </StyledRoot>\n )\n}\n\nconst StyledRoot = styled.div<{\n orientation: Props['orientation']\n}>`\n box-sizing: border-box;\n display: block;\n height: ${props => props.orientation === 'vertical' ? 'auto' : '100%'};\n position: relative;\n width: ${props => props.orientation === 'horizontal' ? 'auto' : '100%'};\n`\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "etudes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.57.0",
|
|
4
4
|
"description": "A study of styled React components",
|
|
5
5
|
"main": "lib",
|
|
6
6
|
"scripts": {
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"@types/styled-components": "^5.1.24",
|
|
47
47
|
"@types/webpack": "^5.28.0",
|
|
48
48
|
"@types/webpack-env": "^1.16.3",
|
|
49
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
50
|
-
"@typescript-eslint/parser": "^5.
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
|
50
|
+
"@typescript-eslint/parser": "^5.14.0",
|
|
51
51
|
"babel-loader": "^8.2.3",
|
|
52
52
|
"babel-plugin-styled-components": "^2.0.6",
|
|
53
53
|
"concurrently": "^7.0.0",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"rimraf": "^3.0.2",
|
|
67
67
|
"styled-components": "^5.3.3",
|
|
68
68
|
"ts-loader": "^9.2.7",
|
|
69
|
-
"ts-node": "^10.
|
|
69
|
+
"ts-node": "^10.7.0",
|
|
70
70
|
"typescript": "^4.6.2",
|
|
71
71
|
"url-loader": "^4.1.1",
|
|
72
72
|
"wait-on": "^6.0.1",
|