@behold/widget 0.5.55 → 0.5.57

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,110 @@
1
+ import { B as BaseElement, t as throttle, c as createElement, a as setClasses } from './index-R4lEDZFo.js';
2
+
3
+ var logo = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<svg version=\"1.1\" id=\"Layer_1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\t viewBox=\"0 0 91.5 29.5\" enable-background=\"new 0 0 91.5 29.5\" xml:space=\"preserve\">\n<g>\n\t<path fill=\"#3BA566\" d=\"M12,11.7c0.8,0,1.8,0.1,2.8,0.3c1.3,0.3,2.4,1.3,2.6,2.6c0.2,1,0.3,1.9,0.3,2.8s-0.1,1.9-0.3,2.9\n\t\tc-0.3,1.3-1.3,2.3-2.6,2.6c-1,0.2-2,0.4-2.8,0.4c-0.9,0-1.9-0.1-3-0.4s-2-1.2-2.3-2.3s-0.4-2.1-0.4-3c0-0.8,0.1-1.8,0.3-2.8\n\t\tc0.3-1.3,1.3-2.4,2.6-2.6C10.2,11.9,11.2,11.7,12,11.7 M12,5.5c-1.4,0-2.8,0.2-4,0.5c-3.8,0.7-6.7,3.6-7.5,7.4\n\t\tC0.2,14.7,0,16.1,0,17.5c0,1.6,0.2,3.1,0.6,4.5c0.8,3.4,3.5,6.1,6.9,7c1.4,0.3,2.9,0.5,4.5,0.5c1.5,0,2.9-0.2,4.2-0.5\n\t\tc3.7-0.8,6.5-3.7,7.3-7.4c0.3-1.3,0.5-2.7,0.5-4.2c0-1.4-0.2-2.8-0.4-4c-0.8-3.8-3.7-6.6-7.5-7.4C14.8,5.7,13.4,5.5,12,5.5L12,5.5z\n\t\t\"/>\n</g>\n<g id=\"type\">\n\t<path fill=\"#FFFFFF\" d=\"M42.2,20.8c0,2.6-1.9,4.3-5.1,4.3h-5.2c0.5-1.4,0.6-2.5,0.6-3.9v-7.7c0-1.4-0.1-2.5-0.6-3.9H37\n\t\tc2.4,0,4.7,1,4.7,3.6c0,2.1-1.4,3.4-3.1,3.9C40.5,17.5,42.2,18.5,42.2,20.8z M35.2,10.4c0,1.1-0.1,2-0.1,3v3.4h1.4\n\t\tc1.7,0,2.5-1.2,2.5-3.1c0-2.2-1-3.4-3.2-3.4C35.6,10.4,35.4,10.4,35.2,10.4z M39.5,21.3c0-2.4-1.4-3.6-3.3-3.6\n\t\tc-0.2,0-0.6,0-1.1,0.1v3.5c0,0.9,0,2,0.1,2.9c0.5,0.1,0.9,0.1,1.4,0.1C38.6,24.3,39.5,23.2,39.5,21.3z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M52.7,19.1h-6.5c0.2,2.5,1.2,4.1,3.8,4.1c1.1,0,1.8-0.3,2.6-0.9c-0.2,1.6-1.5,3.1-3.9,3.1c-3,0-5-2.4-5-6.2\n\t\tc0-3.4,1.6-6.4,5-6.4c2.9,0,4,2.1,4,4.5C52.7,17.3,52.7,19.1,52.7,19.1z M50.2,17.3c0-2.5-0.7-3.6-1.8-3.6c-1.3,0-2.1,1.5-2.1,4.3\n\t\tv0.3h3C50,18.4,50.2,18.3,50.2,17.3z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M64,25.2h-2.8c-0.2-1.1-0.3-2.4-0.3-3.8v-4.6c0-1.4-0.5-2.1-1.5-2.1c-0.6,0-1.3,0.2-2.1,1.2v5.6\n\t\tc0,1.3,0.1,2.3,0.6,3.6h-3.6c0.5-1.3,0.6-2.3,0.6-3.6v-8.2c0-1.5,0-2.9-0.6-4c1.1-0.3,2-0.7,3-1.2v7c0.9-1.6,2.2-2.2,3.4-2.2\n\t\tc1.6,0,2.6,1,2.6,3.4v5C63.4,22.7,63.5,23.8,64,25.2z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M65.4,19.2c0-3.8,2-6.3,5-6.3c2.9,0,4.8,2.7,4.8,6.3c0,3.8-2,6.3-5,6.3C67.3,25.4,65.4,22.8,65.4,19.2z\n\t\t M72.4,19.9c0-3.1-0.7-6.1-2.4-6.1c-1.3,0-1.9,1.7-1.9,4.6c0,3.2,0.7,6.1,2.4,6.1C71.8,24.5,72.4,23,72.4,19.9z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M77.3,21.5v-8.2c0-1.5,0-2.9-0.6-4c1.1-0.3,2-0.7,3-1.2v13.4c0,1.3,0.1,2.3,0.6,3.6h-3.6\n\t\tC77.2,23.8,77.3,22.8,77.3,21.5z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M89,25.2c-0.2-0.3-0.4-0.8-0.4-1.4c-0.7,1.1-1.6,1.5-2.8,1.5c-2.2,0-4-1.9-4-5.6c0-4.4,2.4-6.8,5-6.8\n\t\tc0.7,0,1.2,0.1,1.7,0.4l0,0c0-1.4,0-2.9-0.6-3.9c1.1-0.3,2-0.7,3-1.2v13.3c0,1.3,0.1,2.2,0.6,3.6H89V25.2z M88.5,23.1v-6.6\n\t\tc0-2-0.8-2.6-1.7-2.6c-1.4,0-2.3,1.5-2.3,4.8c0,3.4,1.1,4.9,2.8,4.9C87.8,23.5,88.2,23.4,88.5,23.1z\"/>\n</g>\n<g>\n\t<path fill=\"#FFFFFF\" d=\"M32.3,4.7V0.1h2.2c1,0,1.6,0.7,1.6,1.5c0,0.8-0.6,1.5-1.6,1.5h-1.2v1.7H32.3z M34.3,0.9h-1.1v1.3h1.1\n\t\tC34.7,2.2,35,2,35,1.6C35,1.2,34.7,0.9,34.3,0.9z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M39.5,0C41,0,42,1,42,2.4c0,1.4-1,2.4-2.4,2.4c-1.4,0-2.4-1-2.4-2.4C37.1,1,38.1,0,39.5,0z M39.5,0.9\n\t\tc-0.9,0-1.4,0.7-1.4,1.5c0,0.9,0.6,1.5,1.4,1.5S41,3.3,41,2.4C41,1.5,40.4,0.9,39.5,0.9z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M46.8,4.7L46,1.5l-0.8,3.2h-1.1l-1.3-4.7h1.1l0.8,3.4l0.9-3.4h0.8l0.9,3.4l0.8-3.4h1.1l-1.3,4.7H46.8z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M50.4,4.7V0.1h3.3v0.9h-2.3v1h2.3v0.9h-2.3v1.1h2.3v0.9H50.4z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M57.8,4.7l-0.9-1.7h-0.7v1.7h-1V0.1h2.2c1,0,1.6,0.6,1.6,1.5c0,0.8-0.5,1.3-1,1.4l1.1,1.8H57.8z M57.2,0.9\n\t\th-1v1.3h1c0.4,0,0.7-0.3,0.7-0.6C57.9,1.2,57.6,0.9,57.2,0.9z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M60.4,4.7V0.1h3.3v0.9h-2.3v1h2.3v0.9h-2.3v1.1h2.3v0.9H60.4z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M65.1,4.7V0.1H67c1.5,0,2.5,0.9,2.5,2.3c0,1.4-1,2.3-2.5,2.3H65.1z M66.1,3.9H67c0.9,0,1.5-0.7,1.5-1.5\n\t\tC68.4,1.6,67.9,1,67,1h-0.8V3.9z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M73.3,4.7V0.1h2.5c0.9,0,1.3,0.6,1.3,1.2c0,0.6-0.4,1-0.8,1.1c0.5,0.1,0.9,0.6,0.9,1.1\n\t\tc0,0.7-0.5,1.3-1.4,1.3H73.3z M74.3,2h1.2c0.3,0,0.5-0.2,0.5-0.5c0-0.3-0.2-0.5-0.5-0.5h-1.2V2z M74.3,3.9h1.3\n\t\tc0.4,0,0.6-0.2,0.6-0.6c0-0.3-0.2-0.5-0.6-0.5h-1.3V3.9z\"/>\n\t<path fill=\"#FFFFFF\" d=\"M79.8,4.7V2.8L78,0.1h1.1L80.3,2l1.1-1.9h1.1l-1.8,2.8v1.9H79.8z\"/>\n</g>\n</svg>";
4
+
5
+ var upgradeIcon = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 17.54 17.54\"><path d=\"M8.77,17.54c-2.35,0-4.7-.81-6.33-2.44C-.81,11.84-.81,5.69,2.44,2.44,5.69-.81,11.84-.81,15.1,2.44c3.26,3.25,3.25,9.4,0,12.66-1.63,1.63-3.98,2.44-6.33,2.44ZM8.77,1.51c-1.97,0-3.94,.67-5.27,1.99C.84,6.16,.84,11.38,3.5,14.04c2.66,2.66,7.88,2.66,10.54,0,2.66-2.66,2.66-7.88,0-10.54-1.33-1.33-3.3-1.99-5.27-1.99Z\"/><path d=\"M8.76,13.02c-.41,0-.75-.34-.75-.75V5.26c0-.41,.34-.75,.75-.75s.75,.34,.75,.75v7.01c0,.41-.34,.75-.75,.75Z\"/><path d=\"M6.36,8.42c-.19,0-.38-.07-.53-.22-.29-.29-.29-.77,0-1.06l2.41-2.41c.29-.29,.77-.29,1.06,0s.29,.77,0,1.06l-2.41,2.41c-.15,.15-.34,.22-.53,.22Z\"/><path d=\"M11.17,8.42c-.19,0-.38-.07-.53-.22l-2.41-2.41c-.29-.29-.29-.77,0-1.06s.77-.29,1.06,0l2.41,2.41c.29,.29,.29,.77,0,1.06-.15,.15-.34,.22-.53,.22Z\"/></svg>";
6
+
7
+ var errorIcon = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" x=\"0px\" y=\"0px\"\n\t viewBox=\"0 0 20.5 20.5\" enable-background=\"new 0 0 20.5 20.5\" xml:space=\"preserve\">\n<g>\n\t<path fill=\"#010101\" d=\"M10.2,20.5c-1.2,0-2.4-0.2-3.8-0.5c-2.9-0.7-5.3-3.1-6-6.1C0.2,12.7,0,11.4,0,10.3C0,9.2,0.1,8,0.4,6.8\n\t\tC1.1,3.6,3.7,1,6.9,0.4c2.4-0.5,4.4-0.5,6.8,0c3.3,0.7,5.8,3.2,6.5,6.5c0.2,1.1,0.4,2.3,0.4,3.3c0,1.1-0.1,2.3-0.4,3.5l0,0\n\t\tc-0.7,3.2-3.2,5.7-6.4,6.4C12.5,20.4,11.3,20.5,10.2,20.5z M10.2,1.5c-0.9,0-2,0.1-3,0.3C4.5,2.4,2.5,4.5,1.9,7.1\n\t\tc-0.2,1.1-0.4,2.2-0.4,3.1c0,1,0.1,2.2,0.4,3.4c0.6,2.4,2.5,4.4,4.9,5c2.3,0.6,4.2,0.6,6.6,0.1c2.6-0.6,4.7-2.7,5.2-5.3\n\t\tc0.2-1.1,0.3-2.1,0.3-3.2c0-1-0.1-2-0.3-3c-0.5-2.7-2.6-4.7-5.3-5.3C12.2,1.6,11.2,1.5,10.2,1.5z\"/>\n</g>\n<g>\n\t<g>\n\t\t<path fill=\"#010101\" d=\"M10.2,13.5c0.6,0,1,0.5,1,1.1c0,0.6-0.5,1.1-1,1.1s-1-0.5-1-1.1C9.2,14,9.7,13.5,10.2,13.5z M9.6,12.3\n\t\t\tL9.3,4.7h1.9l-0.3,7.5H9.6z\"/>\n\t</g>\n</g>\n</svg>";
8
+
9
+ var css_248z = ":host{align-items:center;background:#f1f1f1 url(https://behold.pictures/widget:error-background.webp) 0 no-repeat;background-size:auto 100%;border:none;border-radius:20px;box-shadow:none;box-sizing:border-box;color:#000;display:flex;height:200px;justify-content:space-between;margin:0;max-width:750px;min-width:50px;outline:none;overflow:hidden;width:100%}:host *{box-sizing:border-box}:host(.large){height:180px}:host(.medium),:host(.small){background:#f1f1f1 url(https://behold.pictures/widget:error-background-small.webp) top no-repeat;background-size:auto 186px;flex-direction:column;height:auto}.logo{align-items:center;background:linear-gradient(90deg,rgba(0,0,0,.75) 10%,rgba(0,0,0,.5) 75%,transparent);display:flex;flex-grow:0;flex-shrink:0;height:100%;justify-content:center;padding:0 10px 5px 0;width:220px}.logo svg{height:40px;width:auto}:host(.large) .logo{width:180px}:host(.large) .logo svg{height:35px}:host(.medium) .logo,:host(.small) .logo{background:linear-gradient(180deg,rgba(0,0,0,.75) 10%,rgba(0,0,0,.5) 40%,transparent);height:150px;width:100%}.message{align-items:center;display:flex;flex-direction:column;flex-grow:1;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica,Arial,sans-serif;font-size:16px;gap:15px;justify-content:center;line-height:1.5;padding:20px 60px 20px 80px;text-align:center}.message a{color:#000;display:inline-block;text-decoration:underline}:host(.large) .message{font-size:15px;gap:10px;padding:20px 30px 20px 70px}:host(.medium) .message{font-size:16px;gap:15px;padding:40px 30px}:host(.small) .message{font-size:15px;gap:15px;padding:30px 20px}.message__title{align-items:center;display:flex;font-size:20px;font-weight:500;justify-content:center}.message__title svg{height:25px;margin-right:15px;width:25px}:host(.large) .message__title{font-size:18px}:host(.large) .message__title svg{height:20px;margin-right:10px;width:20px}:host(.medium) .message__title,:host(.small) .message__title{flex-direction:column;font-size:17px}:host(.medium) .message__title svg,:host(.small) .message__title svg{margin-bottom:7px;margin-right:0}";
10
+ var styles = css_248z;
11
+
12
+ /*
13
+ * ErrorMessage
14
+ */
15
+ class ErrorMessage extends BaseElement {
16
+ label = 'ErrorMessage';
17
+ // Internal
18
+ shadow;
19
+ logoEl;
20
+ styleEl;
21
+ errorTitleEl;
22
+ errorMessageEl;
23
+ errorMessageTextEl;
24
+ // Provided
25
+ errorMessage;
26
+ constructor() {
27
+ super();
28
+ this.shadow = this.attachShadow({ mode: 'open' });
29
+ // Define which props will trigger _handlePropChange
30
+ this.onPropChange(this._handlePropChange, ['errorMessage']);
31
+ this.onConnect(() => {
32
+ this.onResize(this, this, throttle(this._handleResize, 50, this));
33
+ });
34
+ this.onConnect(() => {
35
+ this.render();
36
+ });
37
+ }
38
+ /*
39
+ * Handle prop change
40
+ */
41
+ _handlePropChange({ changedProp }) {
42
+ this.render();
43
+ }
44
+ /**
45
+ * Render
46
+ */
47
+ render() {
48
+ if (!this.errorMessage)
49
+ return;
50
+ let titleIcon = errorIcon;
51
+ let errorTitle = 'Error';
52
+ if (this.errorMessage.includes('Upgrade')) {
53
+ titleIcon = upgradeIcon;
54
+ errorTitle = 'Upgrade Required';
55
+ }
56
+ this.logoEl = createElement({
57
+ type: 'a',
58
+ classes: 'logo',
59
+ contents: logo,
60
+ attributes: {
61
+ href: 'https://behold.so',
62
+ target: '_blank',
63
+ 'aria-label': 'behold',
64
+ },
65
+ });
66
+ this.errorTitleEl = createElement({
67
+ classes: 'message__title',
68
+ contents: [titleIcon, errorTitle],
69
+ });
70
+ this.errorMessageTextEl = createElement({ classes: 'message__inner' });
71
+ this.errorMessageTextEl.innerHTML = this.errorMessage?.replace('Upgrade your plan', '<a href="https://app.behold.so/account" target="blank">Upgrade your plan</a>');
72
+ this.errorMessageEl = createElement({
73
+ classes: 'message',
74
+ contents: [this.errorTitleEl, this.errorMessageTextEl],
75
+ });
76
+ this.styleEl = createElement({ type: 'style', contents: styles.toString() });
77
+ this.shadow.beholdReplaceChildren(this.logoEl, this.errorMessageEl, this.styleEl);
78
+ }
79
+ /*
80
+ * Handle Resize
81
+ */
82
+ _handleResize(entry) {
83
+ const width = entry?.borderBoxSize?.[0]?.inlineSize || entry?.contentRect?.width || 0;
84
+ let size = 'xlarge';
85
+ if (width < 600)
86
+ size = 'large';
87
+ if (width < 500)
88
+ size = 'medium';
89
+ if (width < 250)
90
+ size = 'small';
91
+ const widths = ['small', 'medium', 'large', 'xlarge'];
92
+ widths.forEach((sizeString) => {
93
+ const sizeClass = `${sizeString}`;
94
+ setClasses(this, {
95
+ [sizeClass]: sizeString === size,
96
+ });
97
+ });
98
+ }
99
+ /*
100
+ * Register
101
+ */
102
+ static register(name = 'behold-error-message') {
103
+ if (!customElements.get(name)) {
104
+ customElements.define(name, ErrorMessage);
105
+ }
106
+ return name;
107
+ }
108
+ }
109
+
110
+ export { ErrorMessage as default };
@@ -0,0 +1,354 @@
1
+ import { c as createElement, a as setClasses, s as setCssVars, f as forceLayout, t as throttle } from './index-R4lEDZFo.js';
2
+ import { B as BaseWidget, I as ImagePost, V as VideoPost, A as AlbumPost, b as baseGridStyles, g as getMedianHSL } from './base-GZO73SkY.js';
3
+
4
+ var css_248z = ".posts{display:block;min-height:100%;width:100%}.height-ref{position:relative}.post{-webkit-font-smoothing:inherit;-moz-osx-font-smoothing:inherit;border:none;color:inherit;display:block;font:inherit;height:100px;left:0;line-height:normal;overflow:hidden;position:absolute;top:0;transform-origin:top left;transition:background .3s ease;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100px}.post--placeholder{background-color:#dedede;position:absolute}";
5
+ var styles = css_248z;
6
+
7
+ /*
8
+ * GalleryWall
9
+ */
10
+ class GalleryWall extends BaseWidget {
11
+ label = 'GalleryWall';
12
+ // Provided
13
+ widgetSettings;
14
+ feedMetadata;
15
+ posts;
16
+ previewLoadingColors = null;
17
+ // Internal
18
+ containerEl;
19
+ heightRefEl;
20
+ postEls;
21
+ popoverGalleryEl;
22
+ appliedBreakpoint;
23
+ medianPaletteHSL;
24
+ constructor() {
25
+ super();
26
+ // Define which props will trigger _handlePropChange
27
+ this.onPropChange(this._handlePropChange, ['widgetSettings', 'feedMetadata', 'posts', 'previewLoadingColors'], ['widgetSettings', 'feedMetadata', 'posts'], this.setup);
28
+ // Register child components
29
+ ImagePost.register();
30
+ VideoPost.register();
31
+ AlbumPost.register();
32
+ // Bind event handlers
33
+ this._handlePostClick = this._handlePostClick.bind(this);
34
+ // Listen to focus
35
+ this.addEventListener('post-focus-next', this._handleFocusNextPost);
36
+ this.addEventListener('post-focus-previous', this._handleFocusPreviousPost);
37
+ // Connect
38
+ this.onConnect(() => {
39
+ this.style.opacity = '0';
40
+ this.heightRefEl = createElement({
41
+ classes: 'height-ref',
42
+ });
43
+ this.containerEl = createElement({
44
+ type: 'figure',
45
+ classes: 'posts',
46
+ contents: [this.heightRefEl],
47
+ });
48
+ this.renderWidget(this.containerEl, [baseGridStyles, styles]);
49
+ // A11y stuff
50
+ this.setAttribute('tabindex', '0');
51
+ this.setAttribute('aria-label', 'Gallery of Instagram posts. Shift + arrow keys to navigate');
52
+ // listen to resize
53
+ this.onResize(this, this.containerEl, this._handleResize);
54
+ });
55
+ }
56
+ /*
57
+ * Run initial setup that requires data to be fully loaded
58
+ */
59
+ setup() {
60
+ // Calculate medianPaletteHSL
61
+ if (this.widgetSettings.loadingColor !== 'transparent') {
62
+ const palettes = this.posts
63
+ .filter((post) => post.colorPalette)
64
+ .map((post) => post.colorPalette);
65
+ this.medianPaletteHSL = getMedianHSL(palettes, this.widgetSettings.loadingColor);
66
+ }
67
+ // Find initial breakpoint
68
+ const matchingBreakpoint = this.getMatchingBreakpoint(this.offsetWidth, this.widgetSettings.breakpoints);
69
+ // Render posts with current breakpoint styles
70
+ this.renderBreakpoint(matchingBreakpoint);
71
+ this.style.opacity = '';
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
+ // Handle changes
82
+ switch (changedProp) {
83
+ case 'posts':
84
+ this._handlePostsChange();
85
+ break;
86
+ case 'widgetSettings':
87
+ this._handleSettingsChange(oldValue, newValue);
88
+ break;
89
+ case 'feedMetadata':
90
+ this._handleMetadataChange();
91
+ break;
92
+ case 'previewLoadingColors':
93
+ this.postEls.forEach((postEl) => {
94
+ postEl.previewLoadingColors = this.previewLoadingColors;
95
+ });
96
+ setClasses(this, {
97
+ 'is-previewing-loading-colors': !!this.previewLoadingColors,
98
+ });
99
+ break;
100
+ }
101
+ }
102
+ /*
103
+ * Handle posts change
104
+ */
105
+ _handlePostsChange() {
106
+ this.postEls = [];
107
+ this.renderBreakpoint(this.appliedBreakpoint, true);
108
+ if (this.popoverGalleryEl) {
109
+ this.popoverGalleryEl.posts = this.posts;
110
+ }
111
+ }
112
+ /*
113
+ * Handle settings change
114
+ */
115
+ _handleSettingsChange(oldValue, newValue) {
116
+ if (oldValue?.onPostClick !== 'openPopupGallery' &&
117
+ newValue?.onPostClick === 'openPopupGallery') {
118
+ this.enablePopoverGallery();
119
+ }
120
+ this.renderBreakpoint(this.getMatchingBreakpoint(this.offsetWidth, this.widgetSettings.breakpoints));
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
+ const { default: PopoverGallery } = await import('./PopoverGallery-pssVDO_O.js');
149
+ PopoverGallery.register();
150
+ this.popoverGalleryEl = document.createElement('behold-popover-gallery');
151
+ Object.assign(this.popoverGalleryEl, {
152
+ widgetSettings: this.widgetSettings,
153
+ feedMetadata: this.feedMetadata,
154
+ posts: this.posts,
155
+ closeFocusEl: this,
156
+ onSlideChange: (slideIndex) => {
157
+ this.popoverGalleryEl.closeFocusEl = this.postEls[slideIndex];
158
+ },
159
+ });
160
+ }
161
+ /*
162
+ * Handle resize
163
+ */
164
+ _handleResize(entry) {
165
+ const widgetWidth = entry.contentBoxSize?.[0]?.inlineSize;
166
+ const breakpoints = this.widgetSettings.breakpoints;
167
+ const matchingBreakpoint = this.getMatchingBreakpoint(widgetWidth, breakpoints);
168
+ this.renderBreakpoint(matchingBreakpoint);
169
+ }
170
+ /**
171
+ * Handle prev post focus
172
+ */
173
+ _handleFocusPreviousPost() {
174
+ if (!this.postEls.length)
175
+ return;
176
+ let currentFocusIndex = [...this.heightRefEl.children].indexOf(this.shadow.activeElement?.parentElement);
177
+ if (currentFocusIndex > 0) {
178
+ currentFocusIndex = currentFocusIndex - 1;
179
+ }
180
+ else {
181
+ currentFocusIndex = this.postEls.length - 1;
182
+ }
183
+ this.postEls[currentFocusIndex].focus();
184
+ }
185
+ /**
186
+ * Handle next post focus
187
+ */
188
+ _handleFocusNextPost() {
189
+ if (!this.postEls.length)
190
+ return;
191
+ let currentFocusIndex = [...this.heightRefEl.children].indexOf(this.shadow.activeElement?.parentElement);
192
+ if (currentFocusIndex > -1 && currentFocusIndex < this.postEls.length - 1) {
193
+ currentFocusIndex = currentFocusIndex + 1;
194
+ }
195
+ else {
196
+ currentFocusIndex = 0;
197
+ }
198
+ this.postEls[currentFocusIndex].focus();
199
+ }
200
+ /**
201
+ * Handle post click
202
+ */
203
+ _handlePostClick(post) {
204
+ this.popoverGalleryEl.open(this.postEls.indexOf(post), post);
205
+ }
206
+ /*
207
+ * Update postEls
208
+ */
209
+ renderPosts(breakpoint) {
210
+ this.postEls = this.createPostEls(breakpoint);
211
+ this.raf(() => {
212
+ this.heightRefEl.beholdReplaceChildren(...this.postEls);
213
+ }, 'renderPosts');
214
+ }
215
+ /*
216
+ * Get breakpoint that matches a width
217
+ */
218
+ getMatchingBreakpoint(width, breakpoints) {
219
+ return Object.entries(breakpoints)
220
+ .map(([key, value]) => ({ width: key, ...value }))
221
+ .filter((bp) => bp.width !== 'default')
222
+ .sort((a, b) => b.width.localeCompare(a.width))
223
+ .reduce((acc, curr) => {
224
+ return width <= parseInt(curr.width) ? curr : acc;
225
+ },
226
+ // numPosts doesn't exist on default breakpoint for some reason
227
+ // @todo fix that
228
+ {
229
+ ...breakpoints.default,
230
+ numPosts: breakpoints.default.galleryWallLayout.length,
231
+ });
232
+ }
233
+ /*
234
+ * Render posts with breakpoint
235
+ */
236
+ renderBreakpoint(breakpoint, forceRender = false) {
237
+ this.cancelRaf('setContainerHeight');
238
+ if (!this.postEls)
239
+ forceRender = true;
240
+ const applied = this.appliedBreakpoint;
241
+ this.appliedBreakpoint = breakpoint;
242
+ const { gap, borderRadius, numPosts, galleryWallLayout, galleryWallNamedLayout, } = breakpoint;
243
+ // First apply container styles to prevent FOUC
244
+ switch (this.widgetSettings.alignment) {
245
+ case 'left':
246
+ this.style.justifyContent = 'flex-start';
247
+ break;
248
+ case 'right':
249
+ this.style.justifyContent = 'flex-end';
250
+ break;
251
+ default:
252
+ this.style.justifyContent = 'center';
253
+ break;
254
+ }
255
+ if (this.widgetSettings.maxWidth &&
256
+ this.widgetSettings.constrainWidth &&
257
+ this.containerEl.style.maxWidth !== `${this.widgetSettings.maxWidth}px`) {
258
+ this.containerEl.style.maxWidth = `${this.widgetSettings.maxWidth}px`;
259
+ }
260
+ if (!this.widgetSettings.constrainWidth) {
261
+ this.containerEl.style.maxWidth = '';
262
+ }
263
+ this.containerEl.setAttribute('data-hover-effect', this.widgetSettings.hoverEffect);
264
+ setCssVars(this.containerEl, { '--post-border-radius': `${borderRadius}%` });
265
+ // Then render posts into updated container
266
+ if (applied?.numPosts !== numPosts ||
267
+ applied?.galleryWallNamedLayout !== galleryWallNamedLayout.toString() ||
268
+ forceRender) {
269
+ this.renderPosts(breakpoint);
270
+ }
271
+ const containerWidth = this.containerEl.offsetWidth;
272
+ const gapX = (gap.x / 1000) * containerWidth;
273
+ const gapY = (gap.y / 1000) * containerWidth;
274
+ this.postEls.forEach((el, i) => {
275
+ const [x, y, w, h] = galleryWallLayout?.[i]
276
+ ? galleryWallLayout[i].split(',').map((item) => parseInt(item))
277
+ : [0, 0, 10, 10];
278
+ const xTranslate = x * (containerWidth / 100) + gapX / 2;
279
+ const yTranslate = y * (containerWidth / 100);
280
+ el.style.transform = `translate(${xTranslate}px, ${yTranslate}px`;
281
+ el.style.width = `${w * (containerWidth / 100) - gapX}px`;
282
+ el.style.height = `${h * (containerWidth / 100) - gapY}px`;
283
+ });
284
+ forceLayout();
285
+ this.raf(() => {
286
+ this.setContainerHeight();
287
+ }, 'setContainerHeight');
288
+ }
289
+ /*
290
+ * Create post Els based on a breakpoint
291
+ */
292
+ createPostEls(breakpoint) {
293
+ const { gap, postAspectRatio } = breakpoint;
294
+ const numPosts = breakpoint?.numPosts || this.posts?.length || 200;
295
+ const filteredPostsArray = this.posts.filter((p, i) => {
296
+ return i < numPosts;
297
+ });
298
+ const postEls = filteredPostsArray.map((post, i) => {
299
+ let postType = 'behold-image-post';
300
+ if (post.mediaType === 'VIDEO') {
301
+ postType = 'behold-video-post';
302
+ }
303
+ if (post.mediaType === 'CAROUSEL_ALBUM') {
304
+ postType = 'behold-album-post';
305
+ }
306
+ const postEl = createElement({
307
+ type: postType,
308
+ props: {
309
+ post,
310
+ widgetSettings: this.widgetSettings,
311
+ feedMetadata: this.feedMetadata,
312
+ medianPaletteHSL: this.medianPaletteHSL,
313
+ onClick: this._handlePostClick,
314
+ hasRowGap: `${gap.y}` !== '0',
315
+ index: i,
316
+ aspectRatio: postAspectRatio || [1, 1],
317
+ totalPosts: filteredPostsArray?.length ||
318
+ breakpoint?.numPosts ||
319
+ this.posts?.length ||
320
+ 0,
321
+ },
322
+ });
323
+ return postEl;
324
+ });
325
+ if (postEls.length < breakpoint.galleryWallLayout.length) {
326
+ breakpoint.galleryWallLayout
327
+ .filter((item, i) => i >= postEls.length)
328
+ .forEach((item) => {
329
+ const placeholderEl = createElement({
330
+ classes: 'post post--placeholder',
331
+ });
332
+ postEls.push(placeholderEl);
333
+ });
334
+ }
335
+ return postEls;
336
+ }
337
+ /*
338
+ * Set container height
339
+ */
340
+ setContainerHeight = throttle(() => {
341
+ this.style.height = `${this.heightRefEl.scrollHeight}px`;
342
+ }, 10, this);
343
+ /*
344
+ * Register
345
+ */
346
+ static register(name = 'behold-gallery-wall') {
347
+ if (!customElements.get(name)) {
348
+ customElements.define(name, GalleryWall);
349
+ }
350
+ return name;
351
+ }
352
+ }
353
+
354
+ export { GalleryWall as default };