@behold/widget 0.5.63 → 0.5.65
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/ElasticCarousel-6SPFdi5u.js +1032 -0
- package/dist/ErrorMessage-WxAD9Li7.js +110 -0
- package/dist/GalleryWall-Cn7UUK_i.js +355 -0
- package/dist/Grid--7TepH_z.js +339 -0
- package/dist/PopoverGallery-oswhxqGK.js +1905 -0
- package/dist/base-D7ZLOWQ5.js +1242 -0
- package/dist/caret-right-S2XSTDFy.js +5 -0
- package/dist/demo/favicon.svg +11 -0
- package/dist/demo/index.html +205 -0
- package/dist/elements/BaseElement.d.ts +1 -1
- package/dist/elements/BaseElement.d.ts.map +1 -1
- package/dist/elements/BasePost.d.ts +1 -1
- package/dist/index-zGq7k0wG.js +938 -0
- package/dist/index.js +1 -1
- package/dist/lib/createElement.d.ts.map +1 -1
- package/dist/lib/gyre.d.ts +2 -2
- package/dist/lib/gyre.d.ts.map +1 -1
- package/dist/replaceChildren-WvILsw1L.js +32 -0
- package/dist/resizeObserver-OlrW1x9X.js +454 -0
- package/dist/widgets/GalleryWall.d.ts.map +1 -1
- package/dist/widgets/Grid.d.ts.map +1 -1
- package/package.json +2 -4
- package/dist/ElasticCarousel-TgYctl0q.js +0 -1
- package/dist/ErrorMessage-JdTd1HQ0.js +0 -1
- package/dist/GalleryWall-YhaOqfTo.js +0 -1
- package/dist/Grid-D1wqy3hY.js +0 -1
- package/dist/PopoverGallery-frjpY9Sq.js +0 -1
- package/dist/base-dR64s75u.js +0 -1
- package/dist/caret-right-xsqAZl9R.js +0 -1
- package/dist/index-P5DzRXeC.js +0 -1
- package/dist/replaceChildren-4H1qCpyP.js +0 -1
- package/dist/resizeObserver--rsjm-GV.js +0 -1
@@ -0,0 +1,339 @@
|
|
1
|
+
import { c as createElement, a as setClasses, f as forceLayout, s as setCssVars } from './index-zGq7k0wG.js';
|
2
|
+
import { B as BaseWidget, I as ImagePost, V as VideoPost, A as AlbumPost, b as baseGridStyles, g as getMedianHSL } from './base-D7ZLOWQ5.js';
|
3
|
+
|
4
|
+
var css_248z = ".post--placeholder{background-color:#dedede;height:0;padding-bottom:calc(100%/var(--post-aspect-ratio))}";
|
5
|
+
var styles = css_248z;
|
6
|
+
|
7
|
+
/*
|
8
|
+
* Grid
|
9
|
+
*/
|
10
|
+
class Grid extends BaseWidget {
|
11
|
+
label = 'Grid';
|
12
|
+
// Provided
|
13
|
+
widgetSettings;
|
14
|
+
feedMetadata;
|
15
|
+
posts;
|
16
|
+
previewLoadingColors = null;
|
17
|
+
// Internal
|
18
|
+
containerEl;
|
19
|
+
postEls;
|
20
|
+
popoverGalleryEl;
|
21
|
+
appliedBreakpoint;
|
22
|
+
medianPaletteHSL;
|
23
|
+
constructor() {
|
24
|
+
super();
|
25
|
+
// Define which props will trigger _handlePropChange
|
26
|
+
this.onPropChange(this._handlePropChange, ['widgetSettings', 'feedMetadata', 'posts', 'previewLoadingColors'], ['widgetSettings', 'feedMetadata', 'posts'], this.setup);
|
27
|
+
// Register child components
|
28
|
+
ImagePost.register();
|
29
|
+
VideoPost.register();
|
30
|
+
AlbumPost.register();
|
31
|
+
// Bind event handlers
|
32
|
+
this._handlePostClick = this._handlePostClick.bind(this);
|
33
|
+
// Listen to focus
|
34
|
+
this.addEventListener('post-focus-next', this._handleFocusNextPost);
|
35
|
+
this.addEventListener('post-focus-previous', this._handleFocusPreviousPost);
|
36
|
+
// Connect
|
37
|
+
this.onConnect(() => {
|
38
|
+
this.containerEl = createElement({
|
39
|
+
type: 'figure',
|
40
|
+
classes: 'posts',
|
41
|
+
});
|
42
|
+
this.renderWidget(this.containerEl, [baseGridStyles, styles]);
|
43
|
+
// A11y stuff
|
44
|
+
this.setAttribute('tabindex', '0');
|
45
|
+
this.setAttribute('aria-label', 'Gallery of Instagram posts. Shift + arrow keys to navigate');
|
46
|
+
// listen to resize
|
47
|
+
this.onResize(this, this, this._handleResize);
|
48
|
+
});
|
49
|
+
}
|
50
|
+
/*
|
51
|
+
* Run initial setup that requires data to be fully loaded
|
52
|
+
*/
|
53
|
+
setup() {
|
54
|
+
// Calculate medianPaletteHSL
|
55
|
+
if (this.widgetSettings.loadingColor !== 'transparent') {
|
56
|
+
const palettes = this.posts
|
57
|
+
.filter((post) => post.colorPalette)
|
58
|
+
.map((post) => post.colorPalette);
|
59
|
+
this.medianPaletteHSL = getMedianHSL(palettes, this.widgetSettings.loadingColor);
|
60
|
+
}
|
61
|
+
// Find initial breakpoint
|
62
|
+
const matchingBreakpoint = this.getMatchingBreakpoint(this.offsetWidth, this.widgetSettings.breakpoints);
|
63
|
+
// Render posts with current breakpoint styles
|
64
|
+
this.renderBreakpoint(matchingBreakpoint);
|
65
|
+
// Pass settings and metadata to posts
|
66
|
+
if (this.postEls) {
|
67
|
+
this.postEls.forEach((postEl) => {
|
68
|
+
postEl.widgetSettings = this.widgetSettings;
|
69
|
+
postEl.feedMetadata = this.feedMetadata;
|
70
|
+
});
|
71
|
+
}
|
72
|
+
// Enable popoverGallery if necessary
|
73
|
+
if (this.widgetSettings.onPostClick === 'openPopupGallery') {
|
74
|
+
this.enablePopoverGallery();
|
75
|
+
}
|
76
|
+
}
|
77
|
+
/*
|
78
|
+
* Handle prop change
|
79
|
+
*/
|
80
|
+
_handlePropChange({ changedProp, oldValue, newValue }) {
|
81
|
+
switch (changedProp) {
|
82
|
+
case 'posts':
|
83
|
+
this._handlePostsChange({ oldValue, newValue });
|
84
|
+
break;
|
85
|
+
case 'widgetSettings':
|
86
|
+
this._handleSettingsChange(oldValue, newValue);
|
87
|
+
break;
|
88
|
+
case 'feedMetadata':
|
89
|
+
this._handleMetadataChange();
|
90
|
+
break;
|
91
|
+
case 'previewLoadingColors':
|
92
|
+
this.postEls.forEach((postEl) => {
|
93
|
+
postEl.previewLoadingColors = this.previewLoadingColors;
|
94
|
+
});
|
95
|
+
setClasses(this, {
|
96
|
+
'is-previewing-loading-colors': !!this.previewLoadingColors,
|
97
|
+
});
|
98
|
+
break;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
/*
|
102
|
+
* Handle posts change
|
103
|
+
*/
|
104
|
+
_handlePostsChange({ oldValue, newValue }) {
|
105
|
+
this.postEls = [];
|
106
|
+
this.renderBreakpoint(this.getMatchingBreakpoint(this.offsetWidth, this.widgetSettings.breakpoints), true);
|
107
|
+
if (this.popoverGalleryEl) {
|
108
|
+
this.popoverGalleryEl.posts = this.posts;
|
109
|
+
}
|
110
|
+
}
|
111
|
+
/*
|
112
|
+
* Handle settings change
|
113
|
+
*/
|
114
|
+
_handleSettingsChange(oldValue, newValue) {
|
115
|
+
if (oldValue?.onPostClick !== 'openPopupGallery' &&
|
116
|
+
newValue?.onPostClick === 'openPopupGallery') {
|
117
|
+
this.enablePopoverGallery();
|
118
|
+
}
|
119
|
+
const matchingBreakpoint = this.getMatchingBreakpoint(this.offsetWidth, this.widgetSettings.breakpoints);
|
120
|
+
this.renderBreakpoint(matchingBreakpoint);
|
121
|
+
this.postEls.forEach((postEl) => {
|
122
|
+
postEl.widgetSettings = this.widgetSettings;
|
123
|
+
});
|
124
|
+
if (this.popoverGalleryEl) {
|
125
|
+
this.popoverGalleryEl.widgetSettings = this.widgetSettings;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
/*
|
129
|
+
* Handle settings change
|
130
|
+
*/
|
131
|
+
_handleMetadataChange() {
|
132
|
+
let description = `from @${this.feedMetadata.username}`;
|
133
|
+
if (this.feedMetadata.hashtags?.length) {
|
134
|
+
description = `from hashtag${this.feedMetadata.hashtags.length > 1 ? 's' : ''} ${this.feedMetadata.hashtags.join(', ')}`;
|
135
|
+
}
|
136
|
+
this.setAttribute('aria-label', `Gallery of Instagram posts ${description}. Shift + arrow keys to navigate`);
|
137
|
+
this.postEls.forEach((postEl) => {
|
138
|
+
postEl.feedMetadata = this.feedMetadata;
|
139
|
+
});
|
140
|
+
if (this.popoverGalleryEl) {
|
141
|
+
this.popoverGalleryEl.feedMetadata = this.feedMetadata;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
/**
|
145
|
+
* Enable popup carousel
|
146
|
+
*/
|
147
|
+
async enablePopoverGallery() {
|
148
|
+
if (this.popoverGalleryEl)
|
149
|
+
return;
|
150
|
+
const { default: PopoverGallery } = await import('./PopoverGallery-oswhxqGK.js');
|
151
|
+
PopoverGallery.register();
|
152
|
+
this.popoverGalleryEl = document.createElement('behold-popover-gallery');
|
153
|
+
Object.assign(this.popoverGalleryEl, {
|
154
|
+
widgetSettings: this.widgetSettings,
|
155
|
+
feedMetadata: this.feedMetadata,
|
156
|
+
posts: this.posts,
|
157
|
+
closeFocusEl: this,
|
158
|
+
onSlideChange: (slideIndex) => {
|
159
|
+
this.popoverGalleryEl.closeFocusEl = this.postEls[slideIndex];
|
160
|
+
},
|
161
|
+
});
|
162
|
+
}
|
163
|
+
/*
|
164
|
+
* Handle resize
|
165
|
+
*/
|
166
|
+
_handleResize(entry) {
|
167
|
+
const widgetWidth = entry.contentBoxSize?.[0]?.inlineSize;
|
168
|
+
const breakpoints = this.widgetSettings.breakpoints;
|
169
|
+
const matchingBreakpoint = this.getMatchingBreakpoint(widgetWidth, breakpoints);
|
170
|
+
this.renderBreakpoint(matchingBreakpoint);
|
171
|
+
}
|
172
|
+
/**
|
173
|
+
* Handle prev post focus
|
174
|
+
*/
|
175
|
+
_handleFocusPreviousPost() {
|
176
|
+
if (!this.postEls.length)
|
177
|
+
return;
|
178
|
+
let currentFocusIndex = [...this.containerEl.children].indexOf(this.shadow.activeElement?.parentElement);
|
179
|
+
if (currentFocusIndex > 0) {
|
180
|
+
currentFocusIndex = currentFocusIndex - 1;
|
181
|
+
}
|
182
|
+
else {
|
183
|
+
currentFocusIndex = this.postEls.length - 1;
|
184
|
+
}
|
185
|
+
this.postEls[currentFocusIndex].focus();
|
186
|
+
}
|
187
|
+
/**
|
188
|
+
* Handle next post focus
|
189
|
+
*/
|
190
|
+
_handleFocusNextPost() {
|
191
|
+
if (!this.postEls.length)
|
192
|
+
return;
|
193
|
+
let currentFocusIndex = [...this.containerEl.children].indexOf(this.shadow.activeElement?.parentElement);
|
194
|
+
if (currentFocusIndex > -1 && currentFocusIndex < this.postEls.length - 1) {
|
195
|
+
currentFocusIndex = currentFocusIndex + 1;
|
196
|
+
}
|
197
|
+
else {
|
198
|
+
currentFocusIndex = 0;
|
199
|
+
}
|
200
|
+
this.postEls[currentFocusIndex].focus();
|
201
|
+
}
|
202
|
+
/**
|
203
|
+
* Handle post click
|
204
|
+
*/
|
205
|
+
_handlePostClick(post) {
|
206
|
+
this.popoverGalleryEl.open(this.postEls.indexOf(post), post);
|
207
|
+
}
|
208
|
+
/*
|
209
|
+
* Update postEls
|
210
|
+
*/
|
211
|
+
renderPosts(breakpoint) {
|
212
|
+
this.postEls = this.createPostEls(breakpoint);
|
213
|
+
this.raf(() => {
|
214
|
+
this.containerEl.beholdReplaceChildren(...this.postEls);
|
215
|
+
}, 'renderPosts');
|
216
|
+
}
|
217
|
+
/*
|
218
|
+
* Get breakpoint that matches a width
|
219
|
+
*/
|
220
|
+
getMatchingBreakpoint(width, breakpoints) {
|
221
|
+
const matchingBreakpoint = Object.entries(breakpoints)
|
222
|
+
.map(([key, value]) => ({ width: key, ...value }))
|
223
|
+
.filter((bp) => bp.width !== 'default')
|
224
|
+
.sort((a, b) => parseInt(b.width) - parseInt(a.width))
|
225
|
+
.reduce((acc, curr) => {
|
226
|
+
return width <= parseInt(curr.width) ? curr : acc;
|
227
|
+
},
|
228
|
+
// numPosts doesn't exist on default breakpoint for some reason
|
229
|
+
// @todo fix that
|
230
|
+
{ numPosts: this.posts.length, ...breakpoints.default });
|
231
|
+
return { numPosts: this.posts.length, ...breakpoints.default, ...matchingBreakpoint };
|
232
|
+
}
|
233
|
+
/*
|
234
|
+
* Render posts with breakpoint
|
235
|
+
*/
|
236
|
+
renderBreakpoint(breakpoint, forceRender = false) {
|
237
|
+
if (!this.posts || !this.containerEl)
|
238
|
+
return;
|
239
|
+
if (!this.postEls?.length)
|
240
|
+
forceRender = true;
|
241
|
+
const applied = this.appliedBreakpoint;
|
242
|
+
const { numColumns, gap, borderRadius, numPosts, postAspectRatio } = breakpoint;
|
243
|
+
// If we're reducing the # of posts, first remove them all to prevent fouc
|
244
|
+
if (applied?.numPosts > numPosts) {
|
245
|
+
this.containerEl.beholdReplaceChildren();
|
246
|
+
forceLayout();
|
247
|
+
}
|
248
|
+
// First apply container styles to prevent FOUC
|
249
|
+
switch (this.widgetSettings.alignment) {
|
250
|
+
case 'left':
|
251
|
+
this.style.justifyContent = 'flex-start';
|
252
|
+
break;
|
253
|
+
case 'right':
|
254
|
+
this.style.justifyContent = 'flex-end';
|
255
|
+
break;
|
256
|
+
default:
|
257
|
+
this.style.justifyContent = 'center';
|
258
|
+
break;
|
259
|
+
}
|
260
|
+
if (this.widgetSettings.maxWidth &&
|
261
|
+
this.widgetSettings.constrainWidth &&
|
262
|
+
this.containerEl.style.maxWidth !== `${this.widgetSettings.maxWidth}px`) {
|
263
|
+
this.containerEl.style.maxWidth = `${this.widgetSettings.maxWidth}px`;
|
264
|
+
}
|
265
|
+
if (!this.widgetSettings.constrainWidth) {
|
266
|
+
this.containerEl.style.maxWidth = '';
|
267
|
+
}
|
268
|
+
this.containerEl.style.gridTemplateColumns = `repeat(${numColumns}, 1fr)`;
|
269
|
+
this.containerEl.style.gap = `${gap.y}px ${gap.x}px`;
|
270
|
+
this.containerEl.setAttribute('data-hover-effect', this.widgetSettings.hoverEffect);
|
271
|
+
let aspectRatio = (postAspectRatio || [1, 1]).reduce((w, h) => w / h);
|
272
|
+
setCssVars(this.containerEl, {
|
273
|
+
'--post-border-radius': `${borderRadius}%`,
|
274
|
+
'--post-aspect-ratio': `${aspectRatio}`,
|
275
|
+
});
|
276
|
+
// Then render posts into updated container
|
277
|
+
if (applied?.numPosts !== numPosts || forceRender) {
|
278
|
+
this.renderPosts(breakpoint);
|
279
|
+
}
|
280
|
+
this.postEls.forEach((el, i) => {
|
281
|
+
el.hasRowGap = `${breakpoint.gap.y}` !== '0';
|
282
|
+
});
|
283
|
+
this.appliedBreakpoint = breakpoint;
|
284
|
+
}
|
285
|
+
/*
|
286
|
+
* Create post Els based on a breakpoint
|
287
|
+
*/
|
288
|
+
createPostEls(breakpoint) {
|
289
|
+
const { numPosts, numColumns, gap, postAspectRatio } = breakpoint;
|
290
|
+
const filteredArray = this.posts.filter((p, i) => {
|
291
|
+
const numPosts = breakpoint?.numPosts || this.posts?.length || 200;
|
292
|
+
return i < numPosts;
|
293
|
+
});
|
294
|
+
const postEls = filteredArray.map((post, i) => {
|
295
|
+
const numRows = Math.ceil((numPosts || this.posts.length) / numColumns);
|
296
|
+
let postType = 'behold-image-post';
|
297
|
+
if (post.mediaType === 'VIDEO') {
|
298
|
+
postType = 'behold-video-post';
|
299
|
+
}
|
300
|
+
if (post.mediaType === 'CAROUSEL_ALBUM') {
|
301
|
+
postType = 'behold-album-post';
|
302
|
+
}
|
303
|
+
const postEl = createElement({
|
304
|
+
type: postType,
|
305
|
+
props: {
|
306
|
+
post,
|
307
|
+
widgetSettings: this.widgetSettings,
|
308
|
+
feedMetadata: this.feedMetadata,
|
309
|
+
medianPaletteHSL: this.medianPaletteHSL,
|
310
|
+
onClick: this._handlePostClick,
|
311
|
+
hasRowGap: `${gap.y}` !== '0',
|
312
|
+
isLastRow: Math.ceil((i + 1) / numColumns) === numRows,
|
313
|
+
index: i,
|
314
|
+
aspectRatio: postAspectRatio || [1, 1],
|
315
|
+
totalPosts: filteredArray?.length || numPosts || this.posts?.length || 0,
|
316
|
+
},
|
317
|
+
});
|
318
|
+
return postEl;
|
319
|
+
});
|
320
|
+
while (postEls.length < breakpoint.numPosts) {
|
321
|
+
const placeholderEl = createElement({
|
322
|
+
classes: 'post post--placeholder',
|
323
|
+
});
|
324
|
+
postEls.push(placeholderEl);
|
325
|
+
}
|
326
|
+
return postEls;
|
327
|
+
}
|
328
|
+
/*
|
329
|
+
* Register
|
330
|
+
*/
|
331
|
+
static register(name = 'behold-grid') {
|
332
|
+
if (!customElements.get(name)) {
|
333
|
+
customElements.define(name, Grid);
|
334
|
+
}
|
335
|
+
return name;
|
336
|
+
}
|
337
|
+
}
|
338
|
+
|
339
|
+
export { Grid as default };
|