@depict-ai/ui 4.7.32 → 4.7.34

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/ES10/index.cjs CHANGED
@@ -18,6 +18,9 @@ function $parcel$export(e, n, v, s) {
18
18
  function $parcel$interopDefault(a) {
19
19
  return a && a.__esModule ? a.default : a;
20
20
  }
21
+ $parcel$export(module.exports, "ModernResponsiveImage", () => $f3db423dc84bc35d$export$140423fa4bfb6d63);
22
+ $parcel$export(module.exports, "setExtraDisplayTransformers", () => $cc9aacef898ccc9a$export$f98b8d5ea7207a1);
23
+ $parcel$export(module.exports, "getExtraDisplayTransformers", () => $cc9aacef898ccc9a$export$b2d94be4f02525b2);
21
24
  $parcel$export(module.exports, "remap_blocks_to_index", () => $f8f375d6245ffff2$export$92aa5d691d588f3f);
22
25
  $parcel$export(module.exports, "useMobileHover", () => $0deb6ff75e3d67c6$export$d4d96868197be50e);
23
26
  $parcel$export(module.exports, "useVisibilityState", () => $e7a7d2fe8a8217d8$export$54299a3c81f5425);
@@ -58,7 +61,6 @@ $parcel$export(module.exports, "make_accurate_width_accessor", () => $c387d7f1d9
58
61
  $parcel$export(module.exports, "RecommendationSlider", () => $2badc30d7c6610e1$export$9574e176201e5e8d);
59
62
  $parcel$export(module.exports, "RecommendationGrid", () => $41227f10ad680afd$export$9756467d34d91cdb);
60
63
  $parcel$export(module.exports, "ShopifyResponsiveImg", () => $858fdcf73148519f$export$6e5611bc7e57e477);
61
- $parcel$export(module.exports, "makeSizeAccessor", () => $858fdcf73148519f$export$e6fffe67d4cdd848);
62
64
  $parcel$export(module.exports, "ImageContainer", () => $ce467edb5343cfcd$export$94026ee33dbabc26);
63
65
  $parcel$export(module.exports, "SentryErrorBoundary", () => $1b3cf201cdd38687$export$b69d0d92862de18b);
64
66
  $parcel$export(module.exports, "ExtraSentryContextProvider", () => $1b3cf201cdd38687$export$240ecf5363d76c0f);
@@ -110,203 +112,32 @@ $parcel$export(module.exports, "SearchField", () => $98aef9965764903d$export$316
110
112
  $parcel$export(module.exports, "BreadCrumbs", () => $335c02c1241a9ca8$export$5b7c3ce0ebe51f86);
111
113
  $parcel$export(module.exports, "QuickLinks", () => $335c02c1241a9ca8$export$de035477d6fef996);
112
114
  $parcel$export(module.exports, "CategoryPage", () => $c10e33c4681f8c9b$export$e2bf8ce7779e827e);
115
+ $parcel$export(module.exports, "makeSizeAccessors", () => $054b1113e4897051$export$54c6d6ff54e72743);
113
116
  /*! Depict.ai search and product listing SDK */
114
- const $aa1938dec50d6c12$export$83d89fbfd8236492 = "4.7.32";
115
- function $3e17e871e9d0911d$export$d9f36cf74e24d595(media_query) {
116
- const signal = $52FdA$solidjs.createSignal(false);
117
- $52FdA$solidjs.onCleanup($52FdA$depictaiutilishared.javascript_media_query(media_query, _ref => {
118
- let {
119
- matches: matches
120
- } = _ref;
121
- return signal[1](matches);
122
- }).remove);
123
- return signal[0];
124
- }
125
- function $478e5a09664da64c$export$a79e666719b3647c(cols_at_size_) {
126
- const size_active = $52FdA$solidjs.createMemo(() => cols_at_size_().map(_ref => {
127
- let [n_cols, min_width, max_width] = _ref;
128
- const media_query = $52FdA$depictaiutilishared.layout_media_query_header(min_width, max_width).replaceAll("@media", "");
129
- const matches = $3e17e871e9d0911d$export$d9f36cf74e24d595(media_query);
130
- return [matches, n_cols];
131
- }));
132
- const n_cols_currently_showing = $52FdA$solidjs.createMemo(() => {
133
- try {
134
- const [, n_cols_currently_showing] = size_active().find(_ref2 => {
135
- let [media_query] = _ref2;
136
- return media_query();
137
- });
138
- return n_cols_currently_showing;
139
- } catch (e) {
140
- $52FdA$depictaiutilishared.dwarn("No active size found in columnsAtSize - can't render content blocks or looks");
141
- return null;
142
- }
143
- });
144
- return n_cols_currently_showing;
145
- }
146
-
147
- // Errors caused by SDK consuming code interfacing with the SDK, not the SDK itself or other Depict packages
148
- class $95e4006e1dcb5b72$export$e1d52e4f0c7557a1 extends Error {}
149
- class $95e4006e1dcb5b72$export$aa14a9f43128f61f extends $95e4006e1dcb5b72$export$e1d52e4f0c7557a1 {
150
- constructor(templateError) {
151
- super("Uncaught error in product card template", {
152
- cause: templateError
153
- });
154
- }
155
- }
156
- var $1b3cf201cdd38687$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div><!$><!/><!$><!/>`);
157
- const $1b3cf201cdd38687$var$ExtraInfoContext = /*@__PURE__*/$52FdA$solidjs.createContext();
158
- function $1b3cf201cdd38687$export$240ecf5363d76c0f(props) {
159
- return $52FdA$solidjsweb.createComponent($1b3cf201cdd38687$var$ExtraInfoContext.Provider, {
160
- get value() {
161
- return props.getContext_;
162
- },
163
- get children() {
164
- return props.children;
165
- }
166
- });
167
- }
168
- function $1b3cf201cdd38687$export$b69d0d92862de18b(props) {
169
- const getContextFunction = $52FdA$solidjs.useContext($1b3cf201cdd38687$var$ExtraInfoContext);
170
- return $52FdA$solidjs.ErrorBoundary({
171
- fallback(err, retry) {
172
- const {
173
- message_: message_,
174
- severity_: severity_
175
- } = props;
176
- let message = message_;
177
- if (err instanceof (0, $95e4006e1dcb5b72$export$aa14a9f43128f61f)) {
178
- console.error(err.cause);
179
- message = "".concat(message, ": ").concat(err.message);
180
- } else $52FdA$depictaiutilishared.report([err, message_], severity_, getContextFunction === null || getContextFunction === void 0 ? void 0 : getContextFunction());
181
- return (() => {
182
- var _el$ = $52FdA$solidjsweb.getNextElement($1b3cf201cdd38687$var$_tmpl$),
183
- _el$2 = _el$.firstChild,
184
- [_el$3, _co$] = $52FdA$solidjsweb.getNextMarker(_el$2.nextSibling),
185
- _el$4 = _el$3.nextSibling,
186
- [_el$5, _co$2] = $52FdA$solidjsweb.getNextMarker(_el$4.nextSibling);
187
- $52FdA$solidjsweb.insert(_el$, message, _el$3, _co$);
188
- $52FdA$solidjsweb.insert(_el$, () => {
189
- var _props$on_error_;
190
- return (_props$on_error_ = props.on_error_) === null || _props$on_error_ === void 0 ? void 0 : _props$on_error_.call(props, retry);
191
- }, _el$5, _co$2);
192
- $52FdA$solidjsweb.effect(_$p => {
193
- var _props$class_list_;
194
- return $52FdA$solidjsweb.classList(_el$, Object.fromEntries(((_props$class_list_ = props.class_list_) === null || _props$class_list_ === void 0 ? void 0 : _props$class_list_.map(c => [c, true])) || []), _$p);
195
- });
196
- return _el$;
197
- })();
198
- },
117
+ const $aa1938dec50d6c12$export$83d89fbfd8236492 = "4.7.34";
118
+ const $d067f3a30f047b41$var$ListingContext = /*@__PURE__*/$52FdA$solidjs.createContext();
119
+ function $d067f3a30f047b41$export$e68cff63f76bd15b(props) {
120
+ const our_object = {};
121
+ return $52FdA$solidjsweb.createComponent($d067f3a30f047b41$var$ListingContext.Provider, {
122
+ value: our_object,
199
123
  get children() {
200
124
  return props.children;
201
125
  }
202
126
  });
203
127
  }
204
- var $830518481649feb1$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div>`),
205
- $830518481649feb1$var$_tmpl$2 = /*#__PURE__*/$52FdA$solidjsweb.template(`<style type=text/css>`);
206
- const $830518481649feb1$export$c500183c31c2b22e = "--spans-columns";
207
- function $830518481649feb1$export$ab6b147eec64fea5(props) {
208
- const container_class = "x" + $52FdA$solidjs.createUniqueId();
209
- const container_element_ = (() => {
210
- var _el$ = $52FdA$solidjsweb.getNextElement($830518481649feb1$var$_tmpl$);
211
- $52FdA$solidjsweb.spread(_el$, $52FdA$solidjsweb.mergeProps(() => props.element_attributes, {
212
- "classList": {
213
- [container_class]: true
214
- }
215
- }), false, true);
216
- $52FdA$solidjsweb.insert(_el$, () => props.children);
217
- $52FdA$solidjsweb.runHydrationEvents();
218
- return _el$;
219
- })(); // Don't want this in the error boundary below, it should only be for the actual layouting
220
- return $52FdA$solidjsweb.createComponent((0, $1b3cf201cdd38687$export$b69d0d92862de18b), {
221
- message_: "Failed calculating css grid layout",
222
- severity_: "error",
223
- get children() {
224
- return $830518481649feb1$export$e2f22da34aaf310a(props, container_element_, false, container_class);
225
- }
226
- });
227
- }
228
- function $830518481649feb1$export$e2f22da34aaf310a(props, container_element) {
229
- let insert_after_container = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
230
- let container_class = arguments.length > 3 ? arguments[3] : undefined;
231
- if (!container_class) {
232
- // only try to add if it wasn't provided, so that we have a code path without classList when doing SSR
233
- container_class = $52FdA$depictaiutilishared.make_random_classname();
234
- container_element.classList.add(container_class);
235
- }
236
- const container_selector = ".depict .".concat(container_class); // class so ppl can have id if needed
237
- const col_styling = $52FdA$solidjs.createMemo(() => $830518481649feb1$var$generate_media_queried_declarations({
238
- container_selector_: container_selector,
239
- default_grid_spacing_text: props.grid_spacing,
240
- cols_at_size_: props.cols_at_size,
241
- override_vertical_spacing_: props.override_vertical_spacing,
242
- top_row_shortened_by_: props.top_row_shortened_by_()
243
- }));
244
- const base_styling = $52FdA$solidjs.createMemo(() => {
245
- return "".concat(container_selector, "{display:grid;}");
246
- });
247
- const get_styling = $52FdA$solidjs.createMemo(() => base_styling() + col_styling());
248
- const style_element = (() => {
249
- var _el$2 = $52FdA$solidjsweb.getNextElement($830518481649feb1$var$_tmpl$2);
250
- $52FdA$solidjsweb.insert(_el$2, get_styling);
251
- return _el$2;
252
- })(); // need to create this after set_styling has been called or else there will be no styling in the SSR'd output
253
- if (insert_after_container) container_element.after(style_element);
254
- return [container_element, style_element];
255
- }
256
- function $830518481649feb1$var$generate_media_queried_declarations(_ref) {
257
- let {
258
- container_selector_: container_selector_,
259
- default_grid_spacing_text: default_grid_spacing_text,
260
- cols_at_size_: cols_at_size_,
261
- override_vertical_spacing_: override_vertical_spacing_,
262
- top_row_shortened_by_: top_row_shortened_by_
263
- } = _ref;
264
- return cols_at_size_.map(options => {
265
- const [n_cols, min, max, grid_spacing_for_size] = options;
266
- const main_spacing_to_use = grid_spacing_for_size || default_grid_spacing_text;
267
- // See comment in else block below
268
- const can_use_gap = override_vertical_spacing_ ? $830518481649feb1$var$can_use_gap_for_unit(override_vertical_spacing_) : $830518481649feb1$var$can_use_gap_for_unit(main_spacing_to_use);
269
- let spacing_styling;
270
- let additional_styling = ""; // outside the media query
271
- if (can_use_gap) spacing_styling = "gap:".concat(main_spacing_to_use, ";").concat(override_vertical_spacing_ ? "row-gap:".concat(override_vertical_spacing_, ";") : "");else {
272
- // When using percent units, which our default styling does (because convenient) and our interface relies on (hard to specify different gaps for different screen sizes)
273
- // row gaps in grids are relative to the whole height of the grid, maybe see also https://stackoverflow.com/a/53563865. The issue with that is that as we load more products, the gap grows. Also, it breaks existing integrations.
274
- // Logical thought: use margins for the vertical spacing. But margins in grids are apparently relative to the size of the individual items in grids.
275
- // Given that, and that content blocks can be of different width, we have to do some complicated calculations to convert the provided gap, which is in gap of the total container width, to a margin of the individual items.
276
- const vertical_spacing_to_use = override_vertical_spacing_ !== null && override_vertical_spacing_ !== void 0 ? override_vertical_spacing_ : main_spacing_to_use;
277
- const width_multiplier = "var(".concat($830518481649feb1$export$c500183c31c2b22e, ", 1)"); // How many cards wide the current item is (needed because content blocks)
278
- const one_item_width_exclusing_gaps = "calc(calc(100 / ".concat(n_cols, ") - calc(calc(").concat(n_cols * 2 - 2, " * calc(").concat($830518481649feb1$var$strip_percent_unit(vertical_spacing_to_use), " / 2)) / ").concat(n_cols, "))"); // Width of one item in percent of the whole
279
- // Equation from layout.tsx, also used in CheckboxGrid. Needs half spacing for some reason
280
- const this_item_width_meat = "calc(".concat(one_item_width_exclusing_gaps, " * ").concat(width_multiplier, ")"); // Width of just the card
281
- const this_item_width_gaps = "calc(calc(".concat(width_multiplier, " - 1) * ").concat($830518481649feb1$var$strip_percent_unit(vertical_spacing_to_use), ")"); // Width of the gaps
282
- const this_item_width = "calc(".concat(this_item_width_meat, " + ").concat(this_item_width_gaps, ")"); // Width of this item including gaps
283
- // this_item_width needs to be unitless, and since plain css can't do calc(40% / 5%) which would become unitless we need to strip all units in the calculations before
284
- const convert_top_spacing_to_item_width_percentage = spacing => "calc(calc(100 / ".concat(this_item_width, ") * ").concat(spacing, ")"); // Now finally we can convert the desired spacing to a percentage of this individual item's width (including gaps that would be there but aren't because content blocks span them)
285
- spacing_styling = "column-gap:".concat(main_spacing_to_use, ";"); // Still use gaps in the horizontal direction because that works flawlessly
286
- // Re-use old layout code to get the correct :nth-child declarations for the top margins
287
- additional_styling = $52FdA$depictaiutilishared.n_col_styling_with_dist(container_selector_ + ">", convert_top_spacing_to_item_width_percentage(default_grid_spacing_text), [[n_cols, min, max, grid_spacing_for_size ? convert_top_spacing_to_item_width_percentage(grid_spacing_for_size) : null]], "grid", override_vertical_spacing_ ? convert_top_spacing_to_item_width_percentage(override_vertical_spacing_) : override_vertical_spacing_, top_row_shortened_by_);
288
- }
289
- const media_query_body = "".concat(container_selector_, "{").concat(spacing_styling, "grid-template-columns:repeat(").concat(n_cols, ",minmax(0,1fr));}");
290
- return "".concat($52FdA$depictaiutilishared.layout_media_query_header(min, max), "{").concat(media_query_body, "}").concat(additional_styling);
291
- }).join("");
292
- }
293
- function $830518481649feb1$var$can_use_gap_for_unit(spacing) {
294
- const trimmed_spacing = spacing.trim();
295
- return !trimmed_spacing.includes("%");
296
- }
297
- function $830518481649feb1$var$strip_percent_unit(css_value) {
298
- return css_value.replaceAll("%", "");
128
+ function $d067f3a30f047b41$export$8d0c4fdbb05a2f2e() {
129
+ return $52FdA$solidjs.useContext($d067f3a30f047b41$var$ListingContext);
299
130
  }
300
- var $e3d733f899558f40$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<span>`);
301
- function $e3d733f899558f40$export$acb3eaade4b23afd(props) {
302
- // Work around https://github.com/solidjs/solid/issues/1980
131
+ var $ce467edb5343cfcd$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div>`);
132
+ function $ce467edb5343cfcd$export$94026ee33dbabc26(props) {
303
133
  return (() => {
304
- var _el$ = $52FdA$solidjsweb.getNextElement($e3d733f899558f40$var$_tmpl$);
134
+ var _el$ = $52FdA$solidjsweb.getNextElement($ce467edb5343cfcd$var$_tmpl$);
135
+ $52FdA$solidjsweb.insert(_el$, () => props.children);
305
136
  $52FdA$solidjsweb.effect(_p$ => {
306
- var _v$ = "".concat(props.class || "", " depict-placeholder"),
307
- _v$2 = props.style;
308
- _v$ !== _p$.e && $52FdA$solidjsweb.className(_el$, _p$.e = _v$);
309
- _p$.t = $52FdA$solidjsweb.style(_el$, _v$2, _p$.t);
137
+ var _v$ = "padding-bottom:calc(calc(1 / ".concat(props.aspectRatio, ") * 100%)"),
138
+ _v$2 = "s-image-container" + (props.class ? " " + props.class : "");
139
+ _p$.e = $52FdA$solidjsweb.style(_el$, _v$, _p$.e);
140
+ _v$2 !== _p$.t && $52FdA$solidjsweb.className(_el$, _p$.t = _v$2);
310
141
  return _p$;
311
142
  }, {
312
143
  e: undefined,
@@ -315,309 +146,241 @@ function $e3d733f899558f40$export$acb3eaade4b23afd(props) {
315
146
  return _el$;
316
147
  })();
317
148
  }
318
- function $b8a8d61b3ec5f5ac$export$3f37af283f8fb843(props) {
319
- const style = $52FdA$solidjs.createMemo(() => {
320
- const {
321
- style: style,
322
- height: height,
323
- width: width,
324
- aspectRatio: aspectRatio
325
- } = props;
326
- const is_image = aspectRatio != undefined;
327
- const size_data = is_image ? {
328
- width: "100%",
329
- "padding-bottom": "calc(calc(1 / ".concat(aspectRatio, ") * 100%)")
330
- } : {
331
- width: width,
332
- height: height
333
- };
334
- return {
335
- display: "block",
336
- ...(style || {}),
337
- ...size_data
338
- };
339
- });
340
- return $52FdA$solidjsweb.createComponent((0, $e3d733f899558f40$export$acb3eaade4b23afd), {
341
- get style() {
342
- return style();
149
+ const $b54645378dfc7280$var$ProductCardIndexContext = /*@__PURE__*/$52FdA$solidjs.createContext();
150
+ function $b54645378dfc7280$export$11354f017ddc9790(props) {
151
+ return $52FdA$solidjsweb.createComponent($b54645378dfc7280$var$ProductCardIndexContext.Provider, {
152
+ get value() {
153
+ return props.index_;
343
154
  },
344
- get ["class"]() {
345
- return props.class;
155
+ get children() {
156
+ return props.children;
346
157
  }
347
158
  });
348
159
  }
349
- var $f8f375d6245ffff2$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div class=content-block-wrapper>`);
350
- function $f8f375d6245ffff2$export$791ef57e62e21c3f(_ref) {
160
+ function $b54645378dfc7280$export$e3faf4d95300054f() {
161
+ return $52FdA$solidjs.useContext($b54645378dfc7280$var$ProductCardIndexContext);
162
+ }
163
+ let $e4e98e5080f4386e$var$browserIsBugged = false;
164
+ function $e4e98e5080f4386e$export$2972b890694ced75(callback, _ref) {
351
165
  let {
352
- content_blocks_: incoming_content_blocks,
353
- cols_at_size_: cols_at_size_,
354
- set_top_row_shortened_by_: set_top_row_shortened_by_
166
+ timeout: timeout
355
167
  } = _ref;
356
- // these are by row
357
- const [content_blocks, set_content_blocks] = $52FdA$solidjsstore.createStore([]);
358
- const n_cols_currently_showing_ = $478e5a09664da64c$export$a79e666719b3647c(cols_at_size_);
359
- $52FdA$solidjs.createEffect(() => {
360
- const incoming_value = incoming_content_blocks();
361
- if (!incoming_value) {
362
- set_content_blocks([]);
363
- return;
364
- }
365
- set_content_blocks($52FdA$solidjsstore.reconcile(incoming_value, {
366
- key: "content"
367
- })); // key: Make moving blocks faster, see https://github.com/solidjs/solid/issues/1925#issuecomment-1769671596
368
- });
369
-
370
- const get_wrapped_blocks_ = $f8f375d6245ffff2$var$wrap_blocks_in_div(content_blocks, n_cols_currently_showing_);
371
- $52FdA$solidjs.createComputed(() => {
372
- // Update our styling if a content block forces some items that should be in the top row into a lower one, so we can generate margin-top declarations for them
373
- const top_row_block = get_wrapped_blocks_()[0];
374
- const blocks_in_top_row_taken = top_row_block === null || top_row_block === void 0 ? void 0 : top_row_block.span_columns;
375
- if (blocks_in_top_row_taken == undefined) {
376
- // Fall back to zero if no content block in top row, since then no blocks in top row are taken
377
- set_top_row_shortened_by_(0);
378
- return;
379
- }
380
- set_top_row_shortened_by_(blocks_in_top_row_taken - 1); // minus one because the content block wrapper also is an element
168
+ if ($e4e98e5080f4386e$var$browserIsBugged) timeout /= 4;
169
+ const cancel = () => {
170
+ cancelIdleCallback(idleHandle);
171
+ clearTimeout(racingTimeout);
172
+ };
173
+ const idleHandle = requestIdleCallback(deadline => {
174
+ cancel();
175
+ return callback(deadline);
176
+ }, {
177
+ timeout: timeout
381
178
  });
382
-
383
- return $52FdA$solidjs.createMemo(() => $f8f375d6245ffff2$export$92aa5d691d588f3f({
384
- wrapped_blocks_: get_wrapped_blocks_(),
385
- n_cols_currently_showing_: n_cols_currently_showing_()
386
- }).content_blocks_by_index_);
179
+ const racingTimeout = setTimeout(() => {
180
+ $52FdA$depictaiutilishared.dwarn("Browser did not respect requestIdleCallback timeout");
181
+ $e4e98e5080f4386e$var$browserIsBugged = true;
182
+ cancel();
183
+ callback({
184
+ didTimeout: false,
185
+ timeRemaining() {
186
+ return 500;
187
+ }
188
+ });
189
+ }, timeout + 1000);
190
+ return cancel;
387
191
  }
388
- function $f8f375d6245ffff2$export$92aa5d691d588f3f(_ref2) {
389
- let {
390
- wrapped_blocks_: wrapped_blocks_,
391
- n_cols_currently_showing_: n_cols_currently_showing_
392
- } = _ref2;
393
- // This computation should be quite cheap since it just moves around things into an array
394
- const content_blocks_by_index_ = [];
395
- const constructed_block_arrays = new WeakSet();
396
- // Need to keep track of products displaced by blocks above when mapping rows to indexes in the actual grid
397
- const displaced_products_ = []; // undefined = is product, true = is content block if number instead of tuple number indicates content blocks in that row. Index in first array is row, index in second array is column
398
- if (!n_cols_currently_showing_)
399
- // Nope out of here if we don't know how many columns are showing
192
+ const $858fdcf73148519f$var$onIdleFunctionsSymbol = /*@__PURE__*/Symbol("onIdleFunctions");
193
+ const $858fdcf73148519f$export$f8945274f08a3105 = /*@__PURE__*/Symbol("listingContextAspectRatios");
194
+ const $858fdcf73148519f$export$6066eb417ed2e9f7 = /*@__PURE__*/Symbol("listingContextAspectRatios");
195
+ function $858fdcf73148519f$export$6e5611bc7e57e477(props) {
196
+ const img = new Image(); // Need to use new Image or browser might not start loading image before it's in the DOM
197
+ const [ourRatioKeyed, setOurRatioKeyed] = $52FdA$solidjs.createSignal();
198
+ const sizeToUse = $52FdA$solidjs.createMemo(() => {
199
+ var _props$sizeHeight;
200
+ // props.size could be a getter that expects a cleanup so get it in this memo instead of where we set img.sizes (also we need to multiply, and it's good with some diffing here so people calling the comp don't have to)
201
+ const incomingSize = props.size();
202
+ const ratio = ourRatioKeyed();
203
+ const containerHeight = (_props$sizeHeight = props.sizeHeight) === null || _props$sizeHeight === void 0 ? void 0 : _props$sizeHeight.call(props);
204
+ if (!incomingSize || !ratio || !containerHeight || getComputedStyle(img).objectFit !== "cover") return incomingSize;
205
+ const maybeCorrectedSize = ratio * containerHeight;
206
+ return Math.round(Math.max(incomingSize, maybeCorrectedSize));
207
+ });
208
+ const src_options = $52FdA$solidjs.createMemo(() => {
209
+ const {
210
+ src: src,
211
+ customUrls: customUrls
212
+ } = props;
213
+ const fallback_src = (customUrls || $858fdcf73148519f$export$1d6267828870adda)(src, 400);
214
+ const srcset = $858fdcf73148519f$var$make_srcset(props.src, props.resolutions || [64, 128, 256, 300, 400, 512, 640, 768, 1024, 1280, 1536, 2048, 2560, 3072, 3584, 4096], customUrls);
215
+ // The order here *might* matter - I've seen mobile safari always start with loading the 400px version when it was reversed
400
216
  return {
401
- content_blocks_by_index_: content_blocks_by_index_
217
+ srcset: srcset,
218
+ src: fallback_src
402
219
  };
403
- for (let i = 0; i < wrapped_blocks_.length; i++) {
404
- // i = row to show at
405
- const block = wrapped_blocks_[i];
406
- if (!block) continue; // Array can have holes/not defined places
407
- const index_of_first_item_in_row = i * n_cols_currently_showing_;
408
- const index_of_last_item_in_row = index_of_first_item_in_row + n_cols_currently_showing_;
220
+ });
221
+ // Work around https://github.com/solidjs/solid/issues/1828
222
+ const [, otherAttributes] = $52FdA$solidjs.splitProps(props, ["resolutions", "size", "src", "srcSet", "loading", "keyRatioUpdating", "sizeHeight", "customUrls" // Can't have properties ending on underscore because the property name mangling will get confused by this <-
223
+ ]);
224
+
225
+ const [hasSetSize, setHasSetSize] = $52FdA$solidjs.createSignal(false);
226
+ const [hasDecoded, setHasDecoded] = $52FdA$solidjs.createSignal(false);
227
+ const productCardIndexAccessor = $b54645378dfc7280$export$e3faf4d95300054f();
228
+ const listingContext = $d067f3a30f047b41$export$8d0c4fdbb05a2f2e();
229
+ const isPrioritisedImage = $52FdA$solidjs.createMemo(() => (productCardIndexAccessor === null || productCardIndexAccessor === void 0 ? void 0 : productCardIndexAccessor()) < 8);
230
+ const shouldActuallyEnableLazyLoading = $52FdA$solidjs.createMemo(() => {
409
231
  const {
410
- span_rows: span_rows,
411
- position: position,
412
- span_columns: span_columns
413
- } = block; // span columns is already capped in the block wrapping step (wrap_blocks_in_div)
414
- let target_index;
415
- if (position === "left") target_index = index_of_first_item_in_row;else if (position === "right") target_index = index_of_last_item_in_row - span_columns;else if (position === "center") target_index = index_of_first_item_in_row + Math.floor((n_cols_currently_showing_ - span_columns) / 2);else throw new Error("Invalid position for content block - must be left, right or center: " + JSON.stringify(position));
416
- // Calculate displacement of us by content blocks above us
417
- let displacement_by_added_blocks = 0;
418
- for (let j = 0; j < i; j++) {
419
- const row = displaced_products_[j];
420
- if (row === undefined) continue; // there were no blocks in this row
421
- let displaced_items_in_row;
422
- if (typeof row === "number") displaced_items_in_row = row;else {
423
- displaced_items_in_row = row.filter(item => item).length;
424
- displaced_products_[j] = displaced_items_in_row;
425
- }
426
- displacement_by_added_blocks += displaced_items_in_row;
427
- }
428
- const index_of_us_in_row = target_index - index_of_first_item_in_row;
429
- for (let j = 0; j < index_of_us_in_row; j++) {
430
- var _displaced_products_$;
431
- if ((_displaced_products_$ = displaced_products_[i]) !== null && _displaced_products_$ !== void 0 && _displaced_products_$[j])
432
- // Add blocks in our *current* row to the displacement, but only the ones to our left
433
- displacement_by_added_blocks++;
232
+ loading: loading
233
+ } = props;
234
+ if (loading === "force-lazy") return true;
235
+ return loading === "lazy" && !isPrioritisedImage();
236
+ });
237
+ const modifiedOtherAttributes = $52FdA$solidjs.mergeProps(otherAttributes, {
238
+ get loading() {
239
+ return shouldActuallyEnableLazyLoading() ? "lazy" : undefined;
434
240
  }
435
- // Add block to output array at the correct index
436
- const final_target_index = target_index - displacement_by_added_blocks;
437
- const existing_block = content_blocks_by_index_[final_target_index];
438
- const block_content = block.content;
439
- // If two blocks want to exist at the same location (can happen, for example if one block wants to be at the end of a row and the other one at the start of the next row) add an array with both
440
- if (existing_block) {
441
- if (constructed_block_arrays.has(existing_block))
442
- // Only push to arrays we have created to not create funky bugs when there's an array in JSX.Element
443
- existing_block.push(block_content);else {
444
- const array = [existing_block, block_content];
445
- constructed_block_arrays.add(array);
446
- content_blocks_by_index_[final_target_index] = array;
241
+ });
242
+ // Batch idle callbacks so that MutationObserver can batch the resulting mutations better, so we don't lose tons of CPU time to MutationObservers doing lots of things for each image
243
+ // Happened on singular, they have some weird observer (+we also have one but ours is at least 3x more efficient)
244
+ const executeWhenIdleBatched = (fn, isSizesUpdate) => {
245
+ if (typeof requestIdleCallback !== "function") return setTimeout(fn); // Old browsers don't get optimisation
246
+ if ((!isSizesUpdate || !sizeSetFastPath) && $52FdA$solidjs.untrack(isPrioritisedImage)) return fn(); // If we're one of the first 8 images, execute the callbacks immediately (improves lighthouse metrics)
247
+ // unless we're just a `sizes` update after the initial sizes setting (this optimisation makes the looks animation a lot smoother on low-cpu devices)
248
+ const existingStack = listingContext === null || listingContext === void 0 ? void 0 : listingContext[$858fdcf73148519f$var$onIdleFunctionsSymbol];
249
+ if (existingStack) return existingStack.add(fn);
250
+ const newStack = new Set([fn]);
251
+ if (listingContext) listingContext[$858fdcf73148519f$var$onIdleFunctionsSymbol] = newStack;
252
+ const processStackWhenIdle = () => $e4e98e5080f4386e$export$2972b890694ced75($52FdA$depictaiutilishared.catchify(deadline => {
253
+ const start = performance.now();
254
+ const thirdDeadlineTime = deadline.timeRemaining() / 3; // observers coming after this take up 2-3x the time so don't use all of it
255
+ for (const fn of newStack) {
256
+ newStack.delete(fn);
257
+ fn();
258
+ const timeTaken = performance.now() - start;
259
+ if ((!deadline.timeRemaining() || timeTaken > thirdDeadlineTime) && newStack.size) {
260
+ // There's still work to be done but no time, so schedule another idle callback
261
+ processStackWhenIdle();
262
+ return;
263
+ }
447
264
  }
448
- } else content_blocks_by_index_[final_target_index] = block_content;
449
- // Update displacement
450
- for (let j = 0; j < span_rows; j++) {
451
- var _ref3;
452
- const row = displaced_products_[_ref3 = i + j] || (displaced_products_[_ref3] = []);
453
- for (let k = index_of_us_in_row; k < index_of_us_in_row + span_columns; k++) row[k] = true;
454
- }
455
- }
456
- return {
457
- content_blocks_by_index_: content_blocks_by_index_,
458
- displaced_products_: displaced_products_
265
+ // Stack is empty
266
+ if (listingContext) delete listingContext[$858fdcf73148519f$var$onIdleFunctionsSymbol];
267
+ }), {
268
+ timeout: 15000
269
+ } // long timeout, better to not have images than to freeze the browser. But also we don't want to confuse user why no iamges are loading
270
+ );
271
+
272
+ processStackWhenIdle();
459
273
  };
460
- }
461
- /**
462
- * Takes a store that contains an array from where index is number of row and value is the result of executing the content block rendering function.
463
- * Then renders the content and wraps it into a div with the correct styling.
464
- * Also caps span_columns to max available columns
465
- */
466
- function $f8f375d6245ffff2$var$wrap_blocks_in_div(rendered_content_blocks, max_span_columns) {
467
- const get_wrapped_blocks = $52FdA$solidjs.mapArray(() => rendered_content_blocks, block => {
468
- if (!block) return;
469
- const final_span_columns = $52FdA$solidjs.createMemo(() => {
470
- var _max_span_columns;
471
- return Math.min(block.span_columns, (_max_span_columns = max_span_columns()) !== null && _max_span_columns !== void 0 ? _max_span_columns : Infinity);
472
- });
473
- // If the item spans an entire row, limit the height to 1 row since there's no concept of "rows" if there are no products beside the block
474
- const final_span_rows = $52FdA$solidjs.createMemo(() => final_span_columns() === max_span_columns() ? 1 : block.span_rows);
475
- const [rendering_delayed, set_rendering_delayed_] = $52FdA$solidjs.createSignal(true);
476
- const content = $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
477
- get when() {
478
- return !rendering_delayed();
479
- },
480
- get children() {
481
- var _el$ = $52FdA$solidjsweb.getNextElement($f8f375d6245ffff2$var$_tmpl$);
482
- $52FdA$solidjsweb.insert(_el$, $52FdA$solidjsweb.createComponent($f8f375d6245ffff2$var$RenderContent, {
483
- get content() {
484
- return block.content;
485
- }
486
- }));
487
- $52FdA$solidjsweb.effect(_p$ => {
488
- var _v$ = !!(final_span_columns() === max_span_columns()),
489
- _v$2 = {
490
- [(0, $830518481649feb1$export$c500183c31c2b22e)]: final_span_columns()
491
- },
492
- _v$3 = "span ".concat(final_span_columns()),
493
- _v$4 = "span ".concat(final_span_rows());
494
- _v$ !== _p$.e && _el$.classList.toggle("spans-whole-row", _p$.e = _v$);
495
- _p$.t = $52FdA$solidjsweb.style(_el$, _v$2, _p$.t);
496
- _v$3 !== _p$.a && ((_p$.a = _v$3) != null ? _el$.style.setProperty("grid-column", _v$3) : _el$.style.removeProperty("grid-column"));
497
- _v$4 !== _p$.o && ((_p$.o = _v$4) != null ? _el$.style.setProperty("grid-row", _v$4) : _el$.style.removeProperty("grid-row"));
498
- return _p$;
499
- }, {
500
- e: undefined,
501
- t: undefined,
502
- a: undefined,
503
- o: undefined
504
- });
505
- return _el$;
506
- }
507
- });
508
- return $52FdA$solidjs.mergeProps(block, {
509
- // Create content divs for the blocks with as much fine-grained diffing as possible?
510
- content: () => {
511
- // Sneaky on-demand rendering, so we don't render more blocks than we can show: we have the rendered value here and don't return a function that renders because if our block would be moved around we'd be guaranteed to re-render
512
- // However, no need to count products to know if we should render: the <For> loops in Placeholders and render_displays will only call this function if there's actually a product here that wants to display this block
513
- set_rendering_delayed_(false);
514
- return content;
515
- },
516
- get span_columns() {
517
- // Cap max width of block to the number of columns available, for everyone downstream
518
- return final_span_columns();
519
- },
520
- get span_rows() {
521
- return final_span_rows();
522
- }
274
+ let sizeSetFastPath = false;
275
+ let hasDecodedFastPath = false;
276
+ let timeoutSet = false;
277
+ let gotCleanedUp = false;
278
+ let srcJustChanged = true;
279
+ img.classList.add("s-responsive-image");
280
+ if (listingContext) {
281
+ let prevValue;
282
+ const aspectRatios = listingContext[$858fdcf73148519f$export$f8945274f08a3105] || (listingContext[$858fdcf73148519f$export$f8945274f08a3105] = new Set());
283
+ const [, setMostPrevalentAspectRatio] = listingContext[$858fdcf73148519f$export$6066eb417ed2e9f7] || (listingContext[$858fdcf73148519f$export$6066eb417ed2e9f7] = $52FdA$solidjs.createSignal());
284
+ img.addEventListener("load", $52FdA$depictaiutilishared.catchify(() => {
285
+ const aspectRatio_ = img.naturalWidth / img.naturalHeight;
286
+ if (srcJustChanged)
287
+ // Always key object-fit-cover compensation to avoid loading-different-images-infinite-loop
288
+ setOurRatioKeyed(aspectRatio_);else if (props.keyRatioUpdating) return;
289
+ srcJustChanged = false;
290
+ // Save our aspect ratio whenever it changes, so that we can base the containers on the most dominant aspect ratio, used in SearchModalV2 and LookItem
291
+ if (prevValue) aspectRatios.delete(prevValue);
292
+ const newValue = !isNaN(aspectRatio_) ? {
293
+ aspectRatio_: aspectRatio_
294
+ } : undefined;
295
+ if (newValue) aspectRatios.add(newValue);
296
+ prevValue = newValue;
297
+ // Do all calculations resulting of an update directly, for performance
298
+ const asArray = [...aspectRatios].map(_ref => {
299
+ let {
300
+ aspectRatio_: aspectRatio_
301
+ } = _ref;
302
+ return aspectRatio_;
303
+ });
304
+ const mostPrevalentAspectRatio = $52FdA$depictaiutilishared.findMostFrequentItem(asArray);
305
+ setMostPrevalentAspectRatio(mostPrevalentAspectRatio);
306
+ }));
307
+ $52FdA$solidjs.onCleanup(() => prevValue && aspectRatios.delete(prevValue));
308
+ }
309
+ $52FdA$solidjs.onCleanup(() => gotCleanedUp = true);
310
+ $52FdA$solidjsweb.spread(img, $52FdA$solidjs.mergeProps(modifiedOtherAttributes), false, true);
311
+ $52FdA$solidjs.createRenderEffect(() => {
312
+ props.src;
313
+ srcJustChanged = true;
314
+ });
315
+ $52FdA$solidjs.createEffect(() => {
316
+ if (!sizeToUse()) return; // wait until we have a size, run every time the size changes
317
+ if (timeoutSet) return;
318
+ const handler = $52FdA$depictaiutilishared.catchify(() => {
319
+ if (gotCleanedUp) return;
320
+ img.sizes = "".concat(sizeToUse(), "px"); // use latest available value of size in case it has changed
321
+ if (!sizeSetFastPath) {
322
+ setHasSetSize(true);
323
+ sizeSetFastPath = true;
324
+ }
325
+ timeoutSet = false;
523
326
  });
327
+ // Throttle the updating of sizes to avoid unnecessary image re-fetches during resize
328
+ // And also because we first set src after sizes has been set, wait with loading and decoding images until browser is idle
329
+ // This greatly improves performance when loading (more) products
330
+ // See https://depictaiworkspace.slack.com/archives/C05NJ0K3WRL/p1698220617663139
331
+ timeoutSet = true; // Important to set timeoutSet before the call to executeWhenIdleBatched since if this is an important image executeWhenIdleBatched will execute fn immediately
332
+ executeWhenIdleBatched(handler, true);
524
333
  });
525
- return get_wrapped_blocks;
526
- }
527
- /**
528
- * Basically adds support for async content block functions and shows a rudimentary placeholder if rendering is delayed. Required due to react having a rendering delay.
529
- */
530
- function $f8f375d6245ffff2$var$RenderContent(props) {
531
- const [resource] = $52FdA$solidjs.createResource(() => props.content,
532
- // Could be reactive
533
- fn => fn());
334
+ const dontLoadImageYet = $52FdA$solidjs.createMemo(() => !sizeToUse() || !hasSetSize()); // Moving this condition into a memo saves us from re-setting src and srcset (expensive) if just props.size changes
534
335
  $52FdA$solidjs.createEffect(() => {
535
- if (resource.error) console.error("Error in content block rendering", resource.error);
336
+ if (dontLoadImageYet()) return; // If size isn't known or set, don't assign src yet since it would cause the most low res image to load
337
+ Object.assign(img, src_options());
338
+ // Add to DOM once decoded to not require/block any paints before image has completed loading and avoid showing broken image symbol
339
+ // We can do this because there has to be a container around us giving us a size
340
+ // No need to listen if we're already in the DOM
341
+ if (hasDecodedFastPath) return;
342
+ if (shouldActuallyEnableLazyLoading()) {
343
+ // For lazy loading there's no decoding to wait for as it only occurs when the image is visible
344
+ // Make sure src is set before we put the image into the DOM though so no broken image symbol is shown
345
+ setHasDecoded(true);
346
+ hasDecodedFastPath = true;
347
+ return;
348
+ }
349
+ img.decode().catch(e => $52FdA$depictaiutilishared.dwarn("Failed to decode image", e, img)) // Display the image also if loading failed so webdev can debug and doesn't get "no image"
350
+ .then(async () => {
351
+ // Also wait with inserting image (i.e. paint) until browser is idle
352
+ await new Promise(r => executeWhenIdleBatched(r, false));
353
+ if (gotCleanedUp) return;
354
+ setHasDecoded(true);
355
+ hasDecodedFastPath = true;
356
+ });
536
357
  });
537
- // The suspense is for when there's an async content block (which we have to support due to react having a rendering delay) so that we can show some height while it's loading (should kinda never be visible)
538
- return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Suspense), {
539
- get fallback() {
540
- return $52FdA$solidjsweb.createComponent((0, $b8a8d61b3ec5f5ac$export$3f37af283f8fb843), {
541
- width: "100%",
542
- height: "max(100%, 400px)"
543
- });
358
+ return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
359
+ get when() {
360
+ return hasDecoded();
544
361
  },
545
- children: resource
546
- });
547
- }
548
- let $0deb6ff75e3d67c6$var$elementsHoveredSignal;
549
- let $0deb6ff75e3d67c6$var$consumersSignal;
550
- function $0deb6ff75e3d67c6$export$d4d96868197be50e() {
551
- if (!$0deb6ff75e3d67c6$var$elementsHoveredSignal || !$0deb6ff75e3d67c6$var$consumersSignal) $52FdA$solidjs.createRoot(dispose => {
552
- $0deb6ff75e3d67c6$var$elementsHoveredSignal = $52FdA$solidjs.createSignal(new Set());
553
- $0deb6ff75e3d67c6$var$consumersSignal = $52FdA$solidjs.createSignal(0);
554
- const [consumers] = $0deb6ff75e3d67c6$var$consumersSignal;
555
- // No matter how often useMobileHover is called, only add one listener and get hovered elements once per touchmove event, for efficiency
556
- $0deb6ff75e3d67c6$var$doHeavyCalculations();
557
- $52FdA$solidjs.createEffect(() => {
558
- // No-one needs information anymore, stop listening
559
- const users = consumers();
560
- if (users < 1) {
561
- $52FdA$depictaiutilisharedlatest.dlog("Stopping to listen for mobile hover");
562
- dispose();
563
- $0deb6ff75e3d67c6$var$elementsHoveredSignal = undefined;
564
- $0deb6ff75e3d67c6$var$consumersSignal = undefined;
565
- }
566
- });
362
+ children: img
567
363
  });
568
- const [elementsHovered] = $0deb6ff75e3d67c6$var$elementsHoveredSignal;
569
- const [, setConsumers] = $0deb6ff75e3d67c6$var$consumersSignal;
570
- setConsumers(prev => prev + 1);
571
- $52FdA$solidjs.onCleanup(() => setConsumers(prev => prev - 1));
572
- return elementsHovered;
573
364
  }
574
- function $0deb6ff75e3d67c6$var$doHeavyCalculations() {
575
- $52FdA$depictaiutilisharedlatest.dlog("Starting to listen for mobile hover");
576
- const [, setElementsHovered] = $0deb6ff75e3d67c6$var$elementsHoveredSignal;
577
- const elementAtTouch = new Map();
578
- const updateSet = () => setElementsHovered(new Set([...elementAtTouch.values()].filter(v => v)));
579
- const setPositionHandler = $52FdA$depictaiutilisharedlatest.catchify(evt => {
580
- for (const touch of evt.changedTouches) elementAtTouch.set(touch.identifier, document.elementFromPoint(touch.clientX, touch.clientY));
581
- updateSet();
582
- });
583
- const deleteTouchHandler = $52FdA$depictaiutilisharedlatest.catchify(evt => {
584
- for (const touch of evt.changedTouches) elementAtTouch.delete(touch.identifier);
585
- updateSet();
586
- });
587
- addEventListener("touchstart", setPositionHandler, {
588
- passive: true
589
- });
590
- addEventListener("touchend", deleteTouchHandler, {
591
- passive: true
592
- });
593
- addEventListener("touchcancel", deleteTouchHandler, {
594
- passive: true
595
- });
596
- $52FdA$solidjs.onCleanup(() => {
597
- removeEventListener("touchstart", setPositionHandler);
598
- removeEventListener("touchend", deleteTouchHandler);
599
- removeEventListener("touchcancel", deleteTouchHandler);
600
- });
365
+ function $858fdcf73148519f$var$make_srcset(url, resolutions, customGenerateImageUrl_) {
366
+ return resolutions.map(width => "".concat((customGenerateImageUrl_ || $858fdcf73148519f$export$1d6267828870adda)(url, width), " ").concat(width, "w")).join(", ");
601
367
  }
602
- function $e7a7d2fe8a8217d8$export$54299a3c81f5425() {
603
- const d = document;
604
- const [isVisible, setIsVisible] = $52FdA$solidjs.createSignal(d.visibilityState !== "hidden");
605
- const handleVisibilityChange = () => setIsVisible(d.visibilityState !== "hidden");
606
- d.addEventListener("visibilitychange", handleVisibilityChange);
607
- $52FdA$solidjs.onCleanup(() => d.removeEventListener("visibilitychange", handleVisibilityChange));
608
- return isVisible;
368
+ function $858fdcf73148519f$export$1d6267828870adda(url, width) {
369
+ // Even just creating one `URL` object per image src and then setting the search parameter is quite slow (0.25ms to set the width param)
370
+ // We're making the assumptions that the url has already at least one query parameter and that the image resizing service will choose the last one out of a duplicate width parameter (shopify's does)
371
+ // That way we can just to string concatenation which is insanely fast
372
+ return url + "&width=" + encodeURIComponent(width);
609
373
  }
610
- var $9d19451330d04c3c$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 14 26"><path d="M2 24.656c-.078 0-.156-.016-.234-.047s-.133-.066-.187-.129c-.117-.117-.176-.258-.176-.422s.059-.305.176-.422l10.371-10.371L1.578 2.883c-.117-.117-.176-.258-.176-.422s.059-.305.176-.422.258-.176.422-.176.305.059.422.176l10.805 10.793a.59.59 0 0 1 .176.434c0 .172-.059.305-.176.422L2.422 24.48a.42.42 0 0 1-.199.129.54.54 0 0 1-.223.047zm0 0"fill=#0f0f0f>`);
611
- function $9d19451330d04c3c$export$8be2714ec7f169ee() {
612
- let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
374
+ var $e3d733f899558f40$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<span>`);
375
+ function $e3d733f899558f40$export$acb3eaade4b23afd(props) {
376
+ // Work around https://github.com/solidjs/solid/issues/1980
613
377
  return (() => {
614
- var _el$ = $52FdA$solidjsweb.getNextElement($9d19451330d04c3c$var$_tmpl$);
378
+ var _el$ = $52FdA$solidjsweb.getNextElement($e3d733f899558f40$var$_tmpl$);
615
379
  $52FdA$solidjsweb.effect(_p$ => {
616
- var _props$width_, _props$height_;
617
- var _v$ = (_props$width_ = props.width_) !== null && _props$width_ !== void 0 ? _props$width_ : 14,
618
- _v$2 = (_props$height_ = props.height_) !== null && _props$height_ !== void 0 ? _props$height_ : 26;
619
- _v$ !== _p$.e && $52FdA$solidjsweb.setAttribute(_el$, "width", _p$.e = _v$);
620
- _v$2 !== _p$.t && $52FdA$solidjsweb.setAttribute(_el$, "height", _p$.t = _v$2);
380
+ var _v$ = "".concat(props.class || "", " depict-placeholder"),
381
+ _v$2 = props.style;
382
+ _v$ !== _p$.e && $52FdA$solidjsweb.className(_el$, _p$.e = _v$);
383
+ _p$.t = $52FdA$solidjsweb.style(_el$, _v$2, _p$.t);
621
384
  return _p$;
622
385
  }, {
623
386
  e: undefined,
@@ -626,1246 +389,1514 @@ function $9d19451330d04c3c$export$8be2714ec7f169ee() {
626
389
  return _el$;
627
390
  })();
628
391
  }
629
- var $ad8ec7729fffeb9c$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div>`),
630
- $ad8ec7729fffeb9c$var$_tmpl$2 = /*#__PURE__*/$52FdA$solidjsweb.template(`<div class="depict-slider depict"><button aria-label="Scroll left"class="left d-navbutton"type=button></button><button aria-label="Scroll right"class="right d-navbutton"type=button></button><div class=sliding>`);
631
- const $ad8ec7729fffeb9c$var$SlidableContext = /*@__PURE__*/$52FdA$solidjs.createContext();
632
- function $ad8ec7729fffeb9c$export$6649caad96ef8870(props) {
633
- const {
634
- slider_ref_: slider_ref_,
635
- faded_opacity_ = 0.7,
636
- mutation_plugins_ = [],
637
- disable_fading_: disable_fading_,
638
- snapAlign_: snapAlign_,
639
- fadingThreshold_ = 0.96
640
- } = props;
641
- const [hasHydrated, setHasHydrated] = $52FdA$solidjs.createSignal(false);
642
- $52FdA$solidjs.createEffect(() => setHasHydrated(true));
643
- const MakeButton = () => (() => {
644
- var _el$ = $52FdA$solidjsweb.getNextElement($ad8ec7729fffeb9c$var$_tmpl$);
645
- $52FdA$solidjsweb.insert(_el$, $52FdA$solidjsweb.createComponent((0, $9d19451330d04c3c$export$8be2714ec7f169ee), {
646
- get height_() {
647
- return props.arrow_height_;
648
- },
649
- get width_() {
650
- return props.arrow_width_;
651
- }
652
- }));
653
- return _el$;
654
- })();
655
- // To support SSR it would be very hard to make Amazing_Slider compatible with solid's SSR because it would have to be rewritten in a more JSX way
656
- // However, all it would do on the server (when used by SlidableItems) is creating the following 5 div elements
657
- // Therefore, we just bail on the server (and first render on the client which is the hydration) and return a static version of the slider
658
- // Once we have hydrated, we construct and insert the actual slider
659
- return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
660
- get when() {
661
- return hasHydrated() && !(0, $52FdA$solidjsweb.isServer);
392
+ function $b8a8d61b3ec5f5ac$export$3f37af283f8fb843(props) {
393
+ const style = $52FdA$solidjs.createMemo(() => {
394
+ const {
395
+ style: style,
396
+ height: height,
397
+ width: width,
398
+ aspectRatio: aspectRatio
399
+ } = props;
400
+ const is_image = aspectRatio != undefined;
401
+ const size_data = is_image ? {
402
+ width: "100%",
403
+ "padding-bottom": "calc(calc(1 / ".concat(aspectRatio, ") * 100%)")
404
+ } : {
405
+ width: width,
406
+ height: height
407
+ };
408
+ return {
409
+ display: "block",
410
+ ...(style || {}),
411
+ ...size_data
412
+ };
413
+ });
414
+ return $52FdA$solidjsweb.createComponent((0, $e3d733f899558f40$export$acb3eaade4b23afd), {
415
+ get style() {
416
+ return style();
662
417
  },
663
- get fallback() {
664
- return (() => {
665
- var _el$2 = $52FdA$solidjsweb.getNextElement($ad8ec7729fffeb9c$var$_tmpl$2),
666
- _el$3 = _el$2.firstChild,
667
- _el$4 = _el$3.nextSibling,
668
- _el$5 = _el$4.nextSibling;
669
- $52FdA$solidjsweb.insert(_el$3, $52FdA$solidjsweb.createComponent(MakeButton, {}));
670
- $52FdA$solidjsweb.insert(_el$4, $52FdA$solidjsweb.createComponent(MakeButton, {}));
671
- $52FdA$solidjsweb.insert(_el$5, () => props.children);
672
- return _el$2;
673
- })();
418
+ get ["class"]() {
419
+ return props.class;
420
+ }
421
+ });
422
+ }
423
+ function $a7f7d416e6f61504$export$89c6019e4baa40b1(props) {
424
+ const style = $52FdA$solidjs.createMemo(() => {
425
+ const {
426
+ style: style,
427
+ height: height,
428
+ width: width
429
+ } = props;
430
+ return {
431
+ ...(style || {}),
432
+ height: height !== null && height !== void 0 ? height : "1em",
433
+ ...(width && {
434
+ width: width
435
+ })
436
+ };
437
+ });
438
+ return $52FdA$solidjsweb.createComponent((0, $e3d733f899558f40$export$acb3eaade4b23afd), {
439
+ get style() {
440
+ return style();
674
441
  },
675
- get children() {
676
- return (() => {
677
- const [intersectionEntries_, setIntersectionEntries] = $52FdA$solidjs.createSignal([]);
678
- const fading_plugin = disable_fading_ ? undefined : $52FdA$depictaiutilishared.slider_fading_factory({
679
- threshold_: fadingThreshold_,
680
- faded_opacity_: faded_opacity_
681
- });
682
- const slider = new (0, $52FdA$depictaiutilishared.Amazing_Slider)({
683
- button_contents: {
684
- left: [MakeButton()],
685
- right: [MakeButton()]
686
- },
687
- constructor_plugins: [$52FdA$depictaiutilishared.slider_snap_css(0, {
688
- align: snapAlign_
689
- }).constructor_plugin, ...(fading_plugin ? [fading_plugin.constructor_plugin] : [])],
690
- mutation_plugins: [...(fading_plugin ? [fading_plugin.mutation_plugin_] : []), ...mutation_plugins_, entries => setIntersectionEntries(entries)]
691
- });
692
- $52FdA$solidjsweb.insert(slider.insert_here, () => $52FdA$solidjsweb.createComponent($ad8ec7729fffeb9c$var$SlidableContext.Provider, {
693
- value: {
694
- slider_: slider,
695
- intersectionEntries_: intersectionEntries_
696
- },
697
- get children() {
698
- return props.children;
699
- }
700
- }));
701
- $52FdA$solidjs.onCleanup(() => slider.observer.disconnect());
702
- slider_ref_ === null || slider_ref_ === void 0 || slider_ref_(slider);
703
- return slider.container;
704
- })();
442
+ get ["class"]() {
443
+ return props.class;
705
444
  }
706
445
  });
707
446
  }
708
- function $ad8ec7729fffeb9c$export$eaa625fb39439e37() {
709
- return $52FdA$solidjs.useContext($ad8ec7729fffeb9c$var$SlidableContext);
447
+ var $c0cf6af094336798$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div class=instant-card><div class=img-part></div><div class=right-part><div class=title-brand-tagline><span class=title></span></div><div class=price-container>`);
448
+ const $c0cf6af094336798$export$8a2234b5b1a5ebd4 = "--image-aspect-ratio";
449
+ function $c0cf6af094336798$export$ee1733d9a8495996() {
450
+ return (() => {
451
+ var _el$ = $52FdA$solidjsweb.getNextElement($c0cf6af094336798$var$_tmpl$),
452
+ _el$2 = _el$.firstChild,
453
+ _el$3 = _el$2.nextSibling,
454
+ _el$4 = _el$3.firstChild,
455
+ _el$5 = _el$4.firstChild,
456
+ _el$6 = _el$4.nextSibling;
457
+ $52FdA$solidjsweb.insert(_el$2, $52FdA$solidjsweb.createComponent((0, $b8a8d61b3ec5f5ac$export$3f37af283f8fb843), {
458
+ aspectRatio: "var(".concat($c0cf6af094336798$export$8a2234b5b1a5ebd4, ", 1)")
459
+ }));
460
+ $52FdA$solidjsweb.insert(_el$5, $52FdA$solidjsweb.createComponent((0, $a7f7d416e6f61504$export$89c6019e4baa40b1), {
461
+ width: "20ch",
462
+ height: "1em"
463
+ }));
464
+ $52FdA$solidjsweb.insert(_el$6, $52FdA$solidjsweb.createComponent((0, $a7f7d416e6f61504$export$89c6019e4baa40b1), {
465
+ width: "5ch",
466
+ height: "1em",
467
+ "class": "price"
468
+ }));
469
+ return _el$;
470
+ })();
471
+ }
472
+ function $054b1113e4897051$export$54c6d6ff54e72743(whatToWatch) {
473
+ const [width, setWidth] = $52FdA$solidjs.createSignal(0);
474
+ const [height, setHeight] = $52FdA$solidjs.createSignal(0);
475
+ const resizeObserver = new ResizeObserver($52FdA$depictaiutilishared.catchify(records => $52FdA$solidjs.batch(() => {
476
+ for (let j = 0; j < records.length; j++) {
477
+ const {
478
+ width: width,
479
+ height: height
480
+ } = records[j].contentRect;
481
+ // Padding hack makes that we can't use contentRect to get the height since that's apparently without padding
482
+ const definitiveHeight = height || whatToWatch.getBoundingClientRect().height;
483
+ if (definitiveHeight) setHeight(Math.ceil(definitiveHeight));
484
+ if (width) setWidth(Math.ceil(width));
485
+ }
486
+ })));
487
+ // If we start observing elements before they're in the DOM Chrome (Version 117.0.5938.92 (Official Build) (arm64)) sometimes gives us a resize event with a width of 0 and then doesn't dispatch one with the actual width once it's in the DOM. So we wait until the element is in the DOM before we start observing it.
488
+ // It doesn't seem to work even when waiting for it to be in the DOM, also wait an animation frame
489
+ const disconnect = (0, $52FdA$depictaiutilishared.observer).onexists(whatToWatch, _ref => {
490
+ let {
491
+ element: element
492
+ } = _ref;
493
+ return requestAnimationFrame($52FdA$depictaiutilishared.catchify(() => resizeObserver.observe(element)));
494
+ });
495
+ $52FdA$solidjs.onCleanup(() => {
496
+ resizeObserver.disconnect();
497
+ disconnect();
498
+ });
499
+ return [width, height];
710
500
  }
501
+ const $28535bb7671c63d1$var$backupSizeSignal = /*@__PURE__*/$52FdA$solidjs.createSignal();
502
+ const $28535bb7671c63d1$export$d7b7ab832c20e2f4 = /*@__PURE__*/Symbol("ShopifyContainedImage");
503
+ function $28535bb7671c63d1$export$e4b984597b71e989(props) {
504
+ const context = $d067f3a30f047b41$export$8d0c4fdbb05a2f2e();
505
+ if (context && !context[$28535bb7671c63d1$export$d7b7ab832c20e2f4])
506
+ // create a signal that's the same for all items in this listing
507
+ context[$28535bb7671c63d1$export$d7b7ab832c20e2f4] = $52FdA$solidjs.createSignal();
508
+ const [currentImageSize, setCurrentImageSize] = (context === null || context === void 0 ? void 0 : context[$28535bb7671c63d1$export$d7b7ab832c20e2f4]) || $28535bb7671c63d1$var$backupSizeSignal; // use global fallback signal (might lead to blurry images) if no context is available
509
+ const [mostPrevalentAspectRatio] = context ? context[(0, $858fdcf73148519f$export$6066eb417ed2e9f7)] || (context[(0, $858fdcf73148519f$export$6066eb417ed2e9f7)] = $52FdA$solidjs.createSignal()) : [];
510
+ const container = $ce467edb5343cfcd$export$94026ee33dbabc26({
511
+ // Write getters manually instead of using JSX, so we can do more complex logic in the aspectRatio getter without increasing bundle size
512
+ get class() {
513
+ return props.class;
514
+ },
515
+ get aspectRatio() {
516
+ if (props.autoAdjustAspectRatio) {
517
+ const targetRatio = mostPrevalentAspectRatio === null || mostPrevalentAspectRatio === void 0 ? void 0 : mostPrevalentAspectRatio();
518
+ if (targetRatio != undefined) return "var(".concat((0, $c0cf6af094336798$export$8a2234b5b1a5ebd4), ", ").concat(targetRatio, ")");
519
+ }
520
+ return props.aspectRatio;
521
+ }
522
+ });
523
+ const owner = $52FdA$solidjs.getOwner();
524
+ let createdSizeAccessor = false;
525
+ let wasCleanedUp = false;
526
+ $52FdA$solidjs.createEffect(() => {
527
+ if (currentImageSize() || wasCleanedUp) return; // We get into the effect when onCleanup is called if we don't have wasCleanedUp
528
+ // ensure we always have a size accessor
529
+ // what this whole thing does is set the sizes attribute to the actual size of one of the existing image containers, therefore the value doesn't have to manually be specified
530
+ createdSizeAccessor = true;
531
+ setCurrentImageSize(() => $52FdA$solidjs.runWithOwner(owner, () => $054b1113e4897051$export$54c6d6ff54e72743(container)));
532
+ });
533
+ $52FdA$solidjs.onCleanup(() => {
534
+ wasCleanedUp = true; // important to set this before the function call below and always, so the dead effects don't create dead size accessors
535
+ if (!createdSizeAccessor) return;
536
+ $52FdA$depictaiutilishared.queueMacroTask(() => setCurrentImageSize()); // unset the size accessor next event loop iteration, so that all onCleanup's have time to run, since the effects run more aggressively and can create a size accessor with a cleaned up owner otherwise
537
+ });
711
538
 
712
- /**
713
- * Gets product_id (the thing we key the rendering on) from a display
714
- */
715
- function $b85edfec41cd3989$export$548d053aba053d79(display) {
716
- if ("variant_index" in display) {
717
- const actual_display = display.variant_displays[display.variant_index];
718
- return actual_display.product_id;
719
- }
720
- if ("listing_id" in display) return display.listing_id;
721
- return display.product_id;
539
+ $52FdA$solidjsweb.insert(container, $52FdA$solidjsweb.createComponent((0, $858fdcf73148519f$export$6e5611bc7e57e477), $52FdA$solidjsweb.mergeProps({
540
+ size: () => {
541
+ var _currentImageSize, _currentImageSize$;
542
+ return ((_currentImageSize = currentImageSize()) === null || _currentImageSize === void 0 ? void 0 : (_currentImageSize$ = _currentImageSize[0]) === null || _currentImageSize$ === void 0 ? void 0 : _currentImageSize$.call(_currentImageSize)) || 0;
543
+ },
544
+ sizeHeight: () => {
545
+ var _currentImageSize2, _currentImageSize2$;
546
+ return ((_currentImageSize2 = currentImageSize()) === null || _currentImageSize2 === void 0 ? void 0 : (_currentImageSize2$ = _currentImageSize2[1]) === null || _currentImageSize2$ === void 0 ? void 0 : _currentImageSize2$.call(_currentImageSize2)) || 0;
547
+ },
548
+ get src() {
549
+ return props.src;
550
+ }
551
+ }, () => props.imgProps, {
552
+ get style() {
553
+ var _props$imgProps;
554
+ return (_props$imgProps = props.imgProps) === null || _props$imgProps === void 0 ? void 0 : _props$imgProps.style;
555
+ }
556
+ })));
557
+ return container;
722
558
  }
723
- function $e82d0d417fa613e8$export$2f0cbfbb4354bb52(elements) {
724
- // FYI this probably doesn't work on hugely deep nestings or large amount of elements
725
- return $52FdA$solidjs.createMemo(() => $e82d0d417fa613e8$var$unwrapping_helper(elements));
559
+ const $f3db423dc84bc35d$var$customUrls = (url, width) => {
560
+ var _url$startsWith;
561
+ if (url !== null && url !== void 0 && (_url$startsWith = url.startsWith) !== null && _url$startsWith !== void 0 && _url$startsWith.call(url, "https://cdn.shopify.com"))
562
+ // The shopify image resizing CDN blocks Cloudflare's image resizer. It's possible that we can't detect shopify image URLs sometimes because they go to the merchant's domain,
563
+ // but it seems like the URLs returned by the Depict API always goes to the cdn.shopify.com version of an image, so this simple workaround works.
564
+ return $858fdcf73148519f$export$1d6267828870adda(url, width);
565
+ // Use cloudflare image resizer instead of img.depict.ai because it's a lot faster (and also auto-chooses other formats if webp is not supported)
566
+ return "https://app.depict.ai/cdn-cgi/image/width=".concat(width, ",format=auto/").concat(url);
567
+ };
568
+ function $f3db423dc84bc35d$export$9d4a4b669b1929ab(props) {
569
+ return $52FdA$solidjsweb.createComponent((0, $28535bb7671c63d1$export$e4b984597b71e989), $52FdA$solidjsweb.mergeProps(props, {
570
+ get imgProps() {
571
+ return {
572
+ ...props.imgProps,
573
+ customUrls: $f3db423dc84bc35d$var$customUrls
574
+ };
575
+ }
576
+ }));
726
577
  }
727
- function $e82d0d417fa613e8$var$unwrapping_helper(elements) {
728
- const result = [];
729
- if (Array.isArray(elements)) for (let i = 0; i < elements.length; i++) {
730
- const element = elements[i];
731
- result.push(...$e82d0d417fa613e8$var$unwrapping_helper(element));
732
- } else if (typeof elements == "function") result.push(...$e82d0d417fa613e8$var$unwrapping_helper(elements()));else if (elements != undefined && typeof elements != "boolean") result.push(elements);
733
- return result;
578
+ function $f3db423dc84bc35d$export$140423fa4bfb6d63(props) {
579
+ return $52FdA$solidjsweb.createComponent((0, $858fdcf73148519f$export$6e5611bc7e57e477), $52FdA$solidjsweb.mergeProps(props, {
580
+ customUrls: $f3db423dc84bc35d$var$customUrls
581
+ }));
734
582
  }
735
- const $b54645378dfc7280$var$ProductCardIndexContext = /*@__PURE__*/$52FdA$solidjs.createContext();
736
- function $b54645378dfc7280$export$11354f017ddc9790(props) {
737
- return $52FdA$solidjsweb.createComponent($b54645378dfc7280$var$ProductCardIndexContext.Provider, {
583
+
584
+ // Value first so shopify merchants can set (extra) display transformers in the shopify app
585
+ // Calling these functions normally doesn't do anything, but our shopify app respects them
586
+ // Them being here is value first too because this can be easily imported in the product card editor
587
+ let $cc9aacef898ccc9a$var$extraDisplayTransformers;
588
+ const $cc9aacef898ccc9a$export$b2d94be4f02525b2 = () => $cc9aacef898ccc9a$var$extraDisplayTransformers;
589
+ const $cc9aacef898ccc9a$export$f98b8d5ea7207a1 = displayTransformers => $cc9aacef898ccc9a$var$extraDisplayTransformers = displayTransformers;
590
+ function $3e17e871e9d0911d$export$d9f36cf74e24d595(media_query) {
591
+ const signal = $52FdA$solidjs.createSignal(false);
592
+ $52FdA$solidjs.onCleanup($52FdA$depictaiutilishared.javascript_media_query(media_query, _ref => {
593
+ let {
594
+ matches: matches
595
+ } = _ref;
596
+ return signal[1](matches);
597
+ }).remove);
598
+ return signal[0];
599
+ }
600
+ function $478e5a09664da64c$export$a79e666719b3647c(cols_at_size_) {
601
+ const size_active = $52FdA$solidjs.createMemo(() => cols_at_size_().map(_ref => {
602
+ let [n_cols, min_width, max_width] = _ref;
603
+ const media_query = $52FdA$depictaiutilishared.layout_media_query_header(min_width, max_width).replaceAll("@media", "");
604
+ const matches = $3e17e871e9d0911d$export$d9f36cf74e24d595(media_query);
605
+ return [matches, n_cols];
606
+ }));
607
+ const n_cols_currently_showing = $52FdA$solidjs.createMemo(() => {
608
+ try {
609
+ const [, n_cols_currently_showing] = size_active().find(_ref2 => {
610
+ let [media_query] = _ref2;
611
+ return media_query();
612
+ });
613
+ return n_cols_currently_showing;
614
+ } catch (e) {
615
+ $52FdA$depictaiutilishared.dwarn("No active size found in columnsAtSize - can't render content blocks or looks");
616
+ return null;
617
+ }
618
+ });
619
+ return n_cols_currently_showing;
620
+ }
621
+
622
+ // Errors caused by SDK consuming code interfacing with the SDK, not the SDK itself or other Depict packages
623
+ class $95e4006e1dcb5b72$export$e1d52e4f0c7557a1 extends Error {}
624
+ class $95e4006e1dcb5b72$export$aa14a9f43128f61f extends $95e4006e1dcb5b72$export$e1d52e4f0c7557a1 {
625
+ constructor(templateError) {
626
+ super("Uncaught error in product card template", {
627
+ cause: templateError
628
+ });
629
+ }
630
+ }
631
+ var $1b3cf201cdd38687$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div><!$><!/><!$><!/>`);
632
+ const $1b3cf201cdd38687$var$ExtraInfoContext = /*@__PURE__*/$52FdA$solidjs.createContext();
633
+ function $1b3cf201cdd38687$export$240ecf5363d76c0f(props) {
634
+ return $52FdA$solidjsweb.createComponent($1b3cf201cdd38687$var$ExtraInfoContext.Provider, {
738
635
  get value() {
739
- return props.index_;
636
+ return props.getContext_;
740
637
  },
741
638
  get children() {
742
639
  return props.children;
743
640
  }
744
641
  });
745
642
  }
746
- function $b54645378dfc7280$export$e3faf4d95300054f() {
747
- return $52FdA$solidjs.useContext($b54645378dfc7280$var$ProductCardIndexContext);
643
+ function $1b3cf201cdd38687$export$b69d0d92862de18b(props) {
644
+ const getContextFunction = $52FdA$solidjs.useContext($1b3cf201cdd38687$var$ExtraInfoContext);
645
+ return $52FdA$solidjs.ErrorBoundary({
646
+ fallback(err, retry) {
647
+ const {
648
+ message_: message_,
649
+ severity_: severity_
650
+ } = props;
651
+ let message = message_;
652
+ if (err instanceof (0, $95e4006e1dcb5b72$export$aa14a9f43128f61f)) {
653
+ console.error(err.cause);
654
+ message = "".concat(message, ": ").concat(err.message);
655
+ } else $52FdA$depictaiutilishared.report([err, message_], severity_, getContextFunction === null || getContextFunction === void 0 ? void 0 : getContextFunction());
656
+ return (() => {
657
+ var _el$ = $52FdA$solidjsweb.getNextElement($1b3cf201cdd38687$var$_tmpl$),
658
+ _el$2 = _el$.firstChild,
659
+ [_el$3, _co$] = $52FdA$solidjsweb.getNextMarker(_el$2.nextSibling),
660
+ _el$4 = _el$3.nextSibling,
661
+ [_el$5, _co$2] = $52FdA$solidjsweb.getNextMarker(_el$4.nextSibling);
662
+ $52FdA$solidjsweb.insert(_el$, message, _el$3, _co$);
663
+ $52FdA$solidjsweb.insert(_el$, () => {
664
+ var _props$on_error_;
665
+ return (_props$on_error_ = props.on_error_) === null || _props$on_error_ === void 0 ? void 0 : _props$on_error_.call(props, retry);
666
+ }, _el$5, _co$2);
667
+ $52FdA$solidjsweb.effect(_$p => {
668
+ var _props$class_list_;
669
+ return $52FdA$solidjsweb.classList(_el$, Object.fromEntries(((_props$class_list_ = props.class_list_) === null || _props$class_list_ === void 0 ? void 0 : _props$class_list_.map(c => [c, true])) || []), _$p);
670
+ });
671
+ return _el$;
672
+ })();
673
+ },
674
+ get children() {
675
+ return props.children;
676
+ }
677
+ });
748
678
  }
749
-
750
- /**
751
- * This is a function that will safely clone an object that may contain promises.
752
- * It will use structuredClone to clone the object and then re-apply (copy) any promises that were in the original object to the cloned object.
753
- * @param obj Anything to clone
754
- */
755
- function $400d96565bbbfe07$export$83bb9af5671e1dbe(obj) {
756
- if (obj instanceof Promise) return obj;
757
- // Extract all promises, keep a map of them, and then re-apply them to both the original object and the target object after cloning
758
- const seen = new Set();
759
- const keyStack = [[]];
760
- const valueStack = [obj];
761
- const promiseLocationStack = [];
762
- while (valueStack.length) {
763
- const value = valueStack.pop();
764
- const keyPath = keyStack.pop();
765
- // Promises can only be in objects and we don't need to check for objects we've already seen (like in circular references)
766
- if (typeof value !== "object" || value === null || seen.has(value)) continue;
767
- seen.add(value);
768
- if (Array.isArray(value)) {
769
- for (let i = 0; i < value.length; i++) {
770
- const ourValue = value[i];
771
- const valuesKeyPath = [...keyPath, i];
772
- if (ourValue instanceof Promise) {
773
- promiseLocationStack.push([valuesKeyPath, ourValue]);
774
- delete value[i]; // This will leave a hole in the array, but it's fine since we'll put it back soon
775
- // This way both the indexes will be correct when putting the value back and our for loop doesn't get messed up
776
- } else {
777
- keyStack.push(valuesKeyPath);
778
- valueStack.push(ourValue);
779
- }
780
- }
781
- continue;
782
- }
783
- for (const innerKey in value) {
784
- const ourValue = value[innerKey];
785
- const valuesKeyPath = [...keyPath, innerKey];
786
- if (ourValue instanceof Promise) {
787
- promiseLocationStack.push([valuesKeyPath, ourValue]);
788
- delete value[innerKey];
789
- } else {
790
- keyStack.push(valuesKeyPath);
791
- valueStack.push(ourValue);
679
+ var $830518481649feb1$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div>`),
680
+ $830518481649feb1$var$_tmpl$2 = /*#__PURE__*/$52FdA$solidjsweb.template(`<style type=text/css>`);
681
+ const $830518481649feb1$export$c500183c31c2b22e = "--spans-columns";
682
+ function $830518481649feb1$export$ab6b147eec64fea5(props) {
683
+ const container_class = "x" + $52FdA$solidjs.createUniqueId();
684
+ const container_element_ = (() => {
685
+ var _el$ = $52FdA$solidjsweb.getNextElement($830518481649feb1$var$_tmpl$);
686
+ $52FdA$solidjsweb.spread(_el$, $52FdA$solidjsweb.mergeProps(() => props.element_attributes, {
687
+ "classList": {
688
+ [container_class]: true
792
689
  }
690
+ }), false, true);
691
+ $52FdA$solidjsweb.insert(_el$, () => props.children);
692
+ $52FdA$solidjsweb.runHydrationEvents();
693
+ return _el$;
694
+ })(); // Don't want this in the error boundary below, it should only be for the actual layouting
695
+ return $52FdA$solidjsweb.createComponent((0, $1b3cf201cdd38687$export$b69d0d92862de18b), {
696
+ message_: "Failed calculating css grid layout",
697
+ severity_: "error",
698
+ get children() {
699
+ return $830518481649feb1$export$e2f22da34aaf310a(props, container_element_, false, container_class);
793
700
  }
701
+ });
702
+ }
703
+ function $830518481649feb1$export$e2f22da34aaf310a(props, container_element) {
704
+ let insert_after_container = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
705
+ let container_class = arguments.length > 3 ? arguments[3] : undefined;
706
+ if (!container_class) {
707
+ // only try to add if it wasn't provided, so that we have a code path without classList when doing SSR
708
+ container_class = $52FdA$depictaiutilishared.make_random_classname();
709
+ container_element.classList.add(container_class);
794
710
  }
795
- let structuredClonedObject;
796
- let error;
797
- try {
798
- structuredClonedObject = structuredClone(obj);
799
- } catch (e) {
800
- // We still need to put back the promises in the original object, even if we threw an error
801
- error = e;
802
- }
803
- // Put back the promises in both the original object and the cloned object
804
- while (promiseLocationStack.length) {
805
- const [keyPath, promise] = promiseLocationStack.pop();
806
- let targetInClone = structuredClonedObject;
807
- let targetInOriginal = obj;
808
- for (let i = 0; i < keyPath.length - 1; i++) {
809
- if (!error) targetInClone = targetInClone[keyPath[i]];
810
- targetInOriginal = targetInOriginal[keyPath[i]];
811
- }
812
- if (!error) targetInClone[keyPath[keyPath.length - 1]] = promise;
813
- targetInOriginal[keyPath[keyPath.length - 1]] = promise;
814
- }
815
- if (error) throw error;
816
- return structuredClonedObject;
711
+ const container_selector = ".depict .".concat(container_class); // class so ppl can have id if needed
712
+ const col_styling = $52FdA$solidjs.createMemo(() => $830518481649feb1$var$generate_media_queried_declarations({
713
+ container_selector_: container_selector,
714
+ default_grid_spacing_text: props.grid_spacing,
715
+ cols_at_size_: props.cols_at_size,
716
+ override_vertical_spacing_: props.override_vertical_spacing,
717
+ top_row_shortened_by_: props.top_row_shortened_by_()
718
+ }));
719
+ const base_styling = $52FdA$solidjs.createMemo(() => {
720
+ return "".concat(container_selector, "{display:grid;}");
721
+ });
722
+ const get_styling = $52FdA$solidjs.createMemo(() => base_styling() + col_styling());
723
+ const style_element = (() => {
724
+ var _el$2 = $52FdA$solidjsweb.getNextElement($830518481649feb1$var$_tmpl$2);
725
+ $52FdA$solidjsweb.insert(_el$2, get_styling);
726
+ return _el$2;
727
+ })(); // need to create this after set_styling has been called or else there will be no styling in the SSR'd output
728
+ if (insert_after_container) container_element.after(style_element);
729
+ return [container_element, style_element];
817
730
  }
818
- let $76012c4468a53d1f$var$printedCloneError = false;
819
- function $76012c4468a53d1f$export$7f8bd308237ab5a5(get_displays_) {
820
- const displays_by_key_ = $52FdA$solidjs.createMemo(() => {
821
- const displays = get_displays_();
822
- // We key by product_id because that's what can be used to uniquely identify products
823
- // This way <For> can optimize the rendering
824
- const map = new Map();
825
- for (let i = 0; i < displays.length; i++) {
826
- const display = displays[i];
827
- const product_id = $b85edfec41cd3989$export$548d053aba053d79(display);
828
- map.set(product_id, display);
731
+ function $830518481649feb1$var$generate_media_queried_declarations(_ref) {
732
+ let {
733
+ container_selector_: container_selector_,
734
+ default_grid_spacing_text: default_grid_spacing_text,
735
+ cols_at_size_: cols_at_size_,
736
+ override_vertical_spacing_: override_vertical_spacing_,
737
+ top_row_shortened_by_: top_row_shortened_by_
738
+ } = _ref;
739
+ return cols_at_size_.map(options => {
740
+ const [n_cols, min, max, grid_spacing_for_size] = options;
741
+ const main_spacing_to_use = grid_spacing_for_size || default_grid_spacing_text;
742
+ // See comment in else block below
743
+ const can_use_gap = override_vertical_spacing_ ? $830518481649feb1$var$can_use_gap_for_unit(override_vertical_spacing_) : $830518481649feb1$var$can_use_gap_for_unit(main_spacing_to_use);
744
+ let spacing_styling;
745
+ let additional_styling = ""; // outside the media query
746
+ if (can_use_gap) spacing_styling = "gap:".concat(main_spacing_to_use, ";").concat(override_vertical_spacing_ ? "row-gap:".concat(override_vertical_spacing_, ";") : "");else {
747
+ // When using percent units, which our default styling does (because convenient) and our interface relies on (hard to specify different gaps for different screen sizes)
748
+ // row gaps in grids are relative to the whole height of the grid, maybe see also https://stackoverflow.com/a/53563865. The issue with that is that as we load more products, the gap grows. Also, it breaks existing integrations.
749
+ // Logical thought: use margins for the vertical spacing. But margins in grids are apparently relative to the size of the individual items in grids.
750
+ // Given that, and that content blocks can be of different width, we have to do some complicated calculations to convert the provided gap, which is in gap of the total container width, to a margin of the individual items.
751
+ const vertical_spacing_to_use = override_vertical_spacing_ !== null && override_vertical_spacing_ !== void 0 ? override_vertical_spacing_ : main_spacing_to_use;
752
+ const width_multiplier = "var(".concat($830518481649feb1$export$c500183c31c2b22e, ", 1)"); // How many cards wide the current item is (needed because content blocks)
753
+ const one_item_width_exclusing_gaps = "calc(calc(100 / ".concat(n_cols, ") - calc(calc(").concat(n_cols * 2 - 2, " * calc(").concat($830518481649feb1$var$strip_percent_unit(vertical_spacing_to_use), " / 2)) / ").concat(n_cols, "))"); // Width of one item in percent of the whole
754
+ // Equation from layout.tsx, also used in CheckboxGrid. Needs half spacing for some reason
755
+ const this_item_width_meat = "calc(".concat(one_item_width_exclusing_gaps, " * ").concat(width_multiplier, ")"); // Width of just the card
756
+ const this_item_width_gaps = "calc(calc(".concat(width_multiplier, " - 1) * ").concat($830518481649feb1$var$strip_percent_unit(vertical_spacing_to_use), ")"); // Width of the gaps
757
+ const this_item_width = "calc(".concat(this_item_width_meat, " + ").concat(this_item_width_gaps, ")"); // Width of this item including gaps
758
+ // this_item_width needs to be unitless, and since plain css can't do calc(40% / 5%) which would become unitless we need to strip all units in the calculations before
759
+ const convert_top_spacing_to_item_width_percentage = spacing => "calc(calc(100 / ".concat(this_item_width, ") * ").concat(spacing, ")"); // Now finally we can convert the desired spacing to a percentage of this individual item's width (including gaps that would be there but aren't because content blocks span them)
760
+ spacing_styling = "column-gap:".concat(main_spacing_to_use, ";"); // Still use gaps in the horizontal direction because that works flawlessly
761
+ // Re-use old layout code to get the correct :nth-child declarations for the top margins
762
+ additional_styling = $52FdA$depictaiutilishared.n_col_styling_with_dist(container_selector_ + ">", convert_top_spacing_to_item_width_percentage(default_grid_spacing_text), [[n_cols, min, max, grid_spacing_for_size ? convert_top_spacing_to_item_width_percentage(grid_spacing_for_size) : null]], "grid", override_vertical_spacing_ ? convert_top_spacing_to_item_width_percentage(override_vertical_spacing_) : override_vertical_spacing_, top_row_shortened_by_);
829
763
  }
830
- return map;
831
- });
832
- return displays_by_key_;
764
+ const media_query_body = "".concat(container_selector_, "{").concat(spacing_styling, "grid-template-columns:repeat(").concat(n_cols, ",minmax(0,1fr));}");
765
+ return "".concat($52FdA$depictaiutilishared.layout_media_query_header(min, max), "{").concat(media_query_body, "}").concat(additional_styling);
766
+ }).join("");
833
767
  }
834
- const $76012c4468a53d1f$var$result_ids = ["search_result_id", "product_listing_result_id", "recommendation_id"];
835
- function $76012c4468a53d1f$export$43f0fb951fcb0c54(_ref) {
768
+ function $830518481649feb1$var$can_use_gap_for_unit(spacing) {
769
+ const trimmed_spacing = spacing.trim();
770
+ return !trimmed_spacing.includes("%");
771
+ }
772
+ function $830518481649feb1$var$strip_percent_unit(css_value) {
773
+ return css_value.replaceAll("%", "");
774
+ }
775
+ var $f8f375d6245ffff2$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div class=content-block-wrapper>`);
776
+ function $f8f375d6245ffff2$export$791ef57e62e21c3f(_ref) {
836
777
  let {
837
- displays_by_key_: displays_by_key_,
838
- product_card_template_: product_card_template_,
839
- do_per_elements_: do_per_elements_,
840
- content_blocks_: content_blocks_
778
+ content_blocks_: incoming_content_blocks,
779
+ cols_at_size_: cols_at_size_,
780
+ set_top_row_shortened_by_: set_top_row_shortened_by_
841
781
  } = _ref;
842
- return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.For), {
843
- get each() {
844
- return [...displays_by_key_().keys()];
845
- },
846
- children: (product_id, index) => {
847
- const owner = $52FdA$solidjs.getOwner();
848
- const possible_content_block = $52FdA$solidjs.createMemo(() => {
849
- var _content_blocks_, _content_blocks_2;
850
- return content_blocks_ === null || content_blocks_ === void 0 ? void 0 : (_content_blocks_ = content_blocks_()) === null || _content_blocks_ === void 0 ? void 0 : (_content_blocks_2 = _content_blocks_()) === null || _content_blocks_2 === void 0 ? void 0 : _content_blocks_2[index()];
851
- });
852
- const display_accessor = $52FdA$solidjs.createMemo(prev => {
853
- const new_display = displays_by_key_().get(product_id);
854
- if (prev && $76012c4468a53d1f$var$deep_equal(prev, new_display))
855
- // If displays are identical, they haven't changed due to merchant/market changing OR we made a new query and the displays are the same. Return the old display (same object reference) to avoid re-rendering.
856
- // This doesn't work if people mutate the displays from within the template but we hope they don't
857
- // (We can't know if the display changing is due to merchant/market changing or a new query otherwise and don't want to run into https://gitlab.com/depict-ai/depict.ai/-/merge_requests/6890/diffs)
858
- return prev;
859
- return new_display;
860
- });
861
- const [product_card_resource] = $52FdA$solidjs.createResource(display_accessor,
862
- // re-render when the reference to the display object changes
863
- display => {
864
- // It's easy for merchants to accidentally mutate the display or some sub-object thereof
865
- // We had a case on singular where they popped an image url and due to use caching after some time there was no image
866
- // Attempt cloning the displays if possible (99.9% of the cases probably) and if not, just use the original display
867
- try {
868
- // Use promiseSafeStructuredClone so that:
869
- // 1. When fetching for example prices from an API, one can start that API request
870
- // 2. Add the promise to the display
871
- // 3. Already render the product card with placeholders for prices while the price loads
872
- // 4. When the price loads, re-render the display with the new price
873
- display = $400d96565bbbfe07$export$83bb9af5671e1dbe(display);
874
- } catch (e) {
875
- if (!$76012c4468a53d1f$var$printedCloneError) {
876
- $76012c4468a53d1f$var$printedCloneError = true;
877
- $52FdA$depictaiutilishared.dlog("Can't clone display", display, " (uncloneable objects in it), make sure you don't mutate it in the template since we cache.", e);
878
- }
879
- }
880
- let renderingResult;
881
- // Wrap the product card in a ProductCardIndexProvider so that the index is available to the product card
882
- // This is wo we can do intelligent image loading in ShopifyContainedImage without shopify devs having to pass in the index
883
- // We don't care about the return value of ProductCardIndexProvider because our rendering result might be a promise which solid doesn't support until it has gone through createResource
884
- $b54645378dfc7280$export$11354f017ddc9790({
885
- index_: index,
886
- get children() {
887
- // This is the key - the functions called inside of the children getter of the provider are the one that have the context defined in their solid-internal Owner
888
- renderingResult = product_card_template_(display, {
889
- set_on_index_change: fn => $52FdA$solidjs.runWithOwner(owner, () => $52FdA$solidjs.createEffect(() => fn(index())))
890
- });
891
- return undefined; // just to satisfy the typing
892
- }
893
- });
894
- // renderingResult is guaranteed to be defined here (if rendering returned something) because the children getter of ProductCardIndexProvider is called synchronously (createRenderEffect is used solid-internally)
895
- return renderingResult;
896
- });
897
- const node_accessor = $e82d0d417fa613e8$export$2f0cbfbb4354bb52(product_card_resource);
898
- $52FdA$solidjs.createEffect(() => {
899
- const product_card_nodes = node_accessor();
900
- const display = display_accessor();
901
- const elements = [];
902
- for (let i = 0; i < product_card_nodes.length; i++) {
903
- const element = product_card_nodes[i];
904
- if (!(element instanceof Element)) continue;
905
- elements.push(element);
906
- // Add tracking ids
907
- if (!(element instanceof HTMLElement)) continue; // Apparently only HTMLElements have dataset
908
- for (let i = 0; i < $76012c4468a53d1f$var$result_ids.length; i++) {
909
- const id = $76012c4468a53d1f$var$result_ids[i];
910
- const value = display[id];
911
- if (value) Object.assign(element.dataset, $52FdA$depictaiutilishared.camelCasifyObject({
912
- [id]: value
913
- }));
914
- }
915
- }
916
- do_per_elements_ === null || do_per_elements_ === void 0 || do_per_elements_(elements, index);
917
- });
918
- return [
919
- // Show content block before product card, so it's *at* that index
920
- possible_content_block, node_accessor // Don't return product_card_resource as calling it could be creating the nodes which would mean we'd be double-creating the nodes,
921
- ]; // Regarding the as unknown shenanigans: https://github.com/solidjs/solid/releases/tag/v1.7.0
782
+ // these are by row
783
+ const [content_blocks, set_content_blocks] = $52FdA$solidjsstore.createStore([]);
784
+ const n_cols_currently_showing_ = $478e5a09664da64c$export$a79e666719b3647c(cols_at_size_);
785
+ $52FdA$solidjs.createEffect(() => {
786
+ const incoming_value = incoming_content_blocks();
787
+ if (!incoming_value) {
788
+ set_content_blocks([]);
789
+ return;
922
790
  }
791
+ set_content_blocks($52FdA$solidjsstore.reconcile(incoming_value, {
792
+ key: "content"
793
+ })); // key: Make moving blocks faster, see https://github.com/solidjs/solid/issues/1925#issuecomment-1769671596
923
794
  });
924
- }
925
- // source: https://medium.com/@pancemarko/deep-equality-in-javascript-determining-if-two-objects-are-equal-bf98cf47e934
926
- // deeply diffs two objects
927
- // Modified by chatGPT to not be recursive, since stiga was getting a stack overflow just due to the size of their data
928
- // Modified futher to bias towards saying objects are equal non-primitive objects differ
929
- function $76012c4468a53d1f$var$deep_equal(obj1, obj2) {
930
- const stack = [[obj1, obj2]];
931
- while (stack.length) {
932
- const [currentObj1, currentObj2] = stack.pop();
933
- if (currentObj1 === currentObj2) continue;
934
- if (Array.isArray(currentObj1) && Array.isArray(currentObj2)) {
935
- if (currentObj1.length !== currentObj2.length) return false;
936
- for (let i = 0; i < currentObj1.length; i++) stack.push([currentObj1[i], currentObj2[i]]);
937
- } else if (typeof currentObj1 === "object" && typeof currentObj2 === "object" && currentObj1 !== null && currentObj2 !== null) {
938
- if (Array.isArray(currentObj1) || Array.isArray(currentObj2)) return false;
939
- const keys1 = Object.keys(currentObj1);
940
- const keys2 = Object.keys(currentObj2);
941
- if (keys1.length !== keys2.length || !keys1.every(key => keys2.includes(key))) return false;
942
- for (let key in currentObj1) {
943
- if ($76012c4468a53d1f$var$result_ids.includes(key)) continue; // ignore comparing values for keys we know are changing with every request
944
- stack.push([currentObj1[key], currentObj2[key]]);
795
+
796
+ const get_wrapped_blocks_ = $f8f375d6245ffff2$var$wrap_blocks_in_div(content_blocks, n_cols_currently_showing_);
797
+ $52FdA$solidjs.createComputed(() => {
798
+ // Update our styling if a content block forces some items that should be in the top row into a lower one, so we can generate margin-top declarations for them
799
+ const top_row_block = get_wrapped_blocks_()[0];
800
+ const blocks_in_top_row_taken = top_row_block === null || top_row_block === void 0 ? void 0 : top_row_block.span_columns;
801
+ if (blocks_in_top_row_taken == undefined) {
802
+ // Fall back to zero if no content block in top row, since then no blocks in top row are taken
803
+ set_top_row_shortened_by_(0);
804
+ return;
805
+ }
806
+ set_top_row_shortened_by_(blocks_in_top_row_taken - 1); // minus one because the content block wrapper also is an element
807
+ });
808
+
809
+ return $52FdA$solidjs.createMemo(() => $f8f375d6245ffff2$export$92aa5d691d588f3f({
810
+ wrapped_blocks_: get_wrapped_blocks_(),
811
+ n_cols_currently_showing_: n_cols_currently_showing_()
812
+ }).content_blocks_by_index_);
813
+ }
814
+ function $f8f375d6245ffff2$export$92aa5d691d588f3f(_ref2) {
815
+ let {
816
+ wrapped_blocks_: wrapped_blocks_,
817
+ n_cols_currently_showing_: n_cols_currently_showing_
818
+ } = _ref2;
819
+ // This computation should be quite cheap since it just moves around things into an array
820
+ const content_blocks_by_index_ = [];
821
+ const constructed_block_arrays = new WeakSet();
822
+ // Need to keep track of products displaced by blocks above when mapping rows to indexes in the actual grid
823
+ const displaced_products_ = []; // undefined = is product, true = is content block if number instead of tuple number indicates content blocks in that row. Index in first array is row, index in second array is column
824
+ if (!n_cols_currently_showing_)
825
+ // Nope out of here if we don't know how many columns are showing
826
+ return {
827
+ content_blocks_by_index_: content_blocks_by_index_
828
+ };
829
+ for (let i = 0; i < wrapped_blocks_.length; i++) {
830
+ // i = row to show at
831
+ const block = wrapped_blocks_[i];
832
+ if (!block) continue; // Array can have holes/not defined places
833
+ const index_of_first_item_in_row = i * n_cols_currently_showing_;
834
+ const index_of_last_item_in_row = index_of_first_item_in_row + n_cols_currently_showing_;
835
+ const {
836
+ span_rows: span_rows,
837
+ position: position,
838
+ span_columns: span_columns
839
+ } = block; // span columns is already capped in the block wrapping step (wrap_blocks_in_div)
840
+ let target_index;
841
+ if (position === "left") target_index = index_of_first_item_in_row;else if (position === "right") target_index = index_of_last_item_in_row - span_columns;else if (position === "center") target_index = index_of_first_item_in_row + Math.floor((n_cols_currently_showing_ - span_columns) / 2);else throw new Error("Invalid position for content block - must be left, right or center: " + JSON.stringify(position));
842
+ // Calculate displacement of us by content blocks above us
843
+ let displacement_by_added_blocks = 0;
844
+ for (let j = 0; j < i; j++) {
845
+ const row = displaced_products_[j];
846
+ if (row === undefined) continue; // there were no blocks in this row
847
+ let displaced_items_in_row;
848
+ if (typeof row === "number") displaced_items_in_row = row;else {
849
+ displaced_items_in_row = row.filter(item => item).length;
850
+ displaced_products_[j] = displaced_items_in_row;
945
851
  }
946
- } else if (typeof currentObj1 !== "function" && typeof currentObj2 !== "function")
947
- // Claim that all functions are equal, since the only way a function ends up here is because someone added it in the displayTransformer and that shouldn't force us to re-render, right?
948
- return false;
852
+ displacement_by_added_blocks += displaced_items_in_row;
853
+ }
854
+ const index_of_us_in_row = target_index - index_of_first_item_in_row;
855
+ for (let j = 0; j < index_of_us_in_row; j++) {
856
+ var _displaced_products_$;
857
+ if ((_displaced_products_$ = displaced_products_[i]) !== null && _displaced_products_$ !== void 0 && _displaced_products_$[j])
858
+ // Add blocks in our *current* row to the displacement, but only the ones to our left
859
+ displacement_by_added_blocks++;
860
+ }
861
+ // Add block to output array at the correct index
862
+ const final_target_index = target_index - displacement_by_added_blocks;
863
+ const existing_block = content_blocks_by_index_[final_target_index];
864
+ const block_content = block.content;
865
+ // If two blocks want to exist at the same location (can happen, for example if one block wants to be at the end of a row and the other one at the start of the next row) add an array with both
866
+ if (existing_block) {
867
+ if (constructed_block_arrays.has(existing_block))
868
+ // Only push to arrays we have created to not create funky bugs when there's an array in JSX.Element
869
+ existing_block.push(block_content);else {
870
+ const array = [existing_block, block_content];
871
+ constructed_block_arrays.add(array);
872
+ content_blocks_by_index_[final_target_index] = array;
873
+ }
874
+ } else content_blocks_by_index_[final_target_index] = block_content;
875
+ // Update displacement
876
+ for (let j = 0; j < span_rows; j++) {
877
+ var _ref3;
878
+ const row = displaced_products_[_ref3 = i + j] || (displaced_products_[_ref3] = []);
879
+ for (let k = index_of_us_in_row; k < index_of_us_in_row + span_columns; k++) row[k] = true;
880
+ }
949
881
  }
950
- return true;
882
+ return {
883
+ content_blocks_by_index_: content_blocks_by_index_,
884
+ displaced_products_: displaced_products_
885
+ };
951
886
  }
952
- const $a52942afacbced93$export$f223d69ed12f5fb7 = /*@__PURE__*/$52FdA$solidjs.createContext();
953
- function $a52942afacbced93$export$4a14175d33d81a96(_ref) {
954
- let {
955
- displays_by_key_: displays_by_key_,
956
- product_card_template_: product_card_template_,
957
- content_blocks_: content_blocks_,
958
- alwaysObserveCards_: alwaysObserveCards_
959
- } = _ref;
960
- const targetToIndexMap_ = new Map();
961
- const indexToTargetMap_ = new Map();
962
- const [listenersForIntersecting, setListenersForIntersecting] = $52FdA$solidjs.createSignal(0);
963
- const [currentlyIntersecting, setCurrentlyIntersecting] = $52FdA$solidjs.createSignal(new Set(), {
964
- equals: false
887
+ /**
888
+ * Takes a store that contains an array from where index is number of row and value is the result of executing the content block rendering function.
889
+ * Then renders the content and wraps it into a div with the correct styling.
890
+ * Also caps span_columns to max available columns
891
+ */
892
+ function $f8f375d6245ffff2$var$wrap_blocks_in_div(rendered_content_blocks, max_span_columns) {
893
+ const get_wrapped_blocks = $52FdA$solidjs.mapArray(() => rendered_content_blocks, block => {
894
+ if (!block) return;
895
+ const final_span_columns = $52FdA$solidjs.createMemo(() => {
896
+ var _max_span_columns;
897
+ return Math.min(block.span_columns, (_max_span_columns = max_span_columns()) !== null && _max_span_columns !== void 0 ? _max_span_columns : Infinity);
898
+ });
899
+ // If the item spans an entire row, limit the height to 1 row since there's no concept of "rows" if there are no products beside the block
900
+ const final_span_rows = $52FdA$solidjs.createMemo(() => final_span_columns() === max_span_columns() ? 1 : block.span_rows);
901
+ const [rendering_delayed, set_rendering_delayed_] = $52FdA$solidjs.createSignal(true);
902
+ const content = $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
903
+ get when() {
904
+ return !rendering_delayed();
905
+ },
906
+ get children() {
907
+ var _el$ = $52FdA$solidjsweb.getNextElement($f8f375d6245ffff2$var$_tmpl$);
908
+ $52FdA$solidjsweb.insert(_el$, $52FdA$solidjsweb.createComponent($f8f375d6245ffff2$var$RenderContent, {
909
+ get content() {
910
+ return block.content;
911
+ }
912
+ }));
913
+ $52FdA$solidjsweb.effect(_p$ => {
914
+ var _v$ = !!(final_span_columns() === max_span_columns()),
915
+ _v$2 = {
916
+ [(0, $830518481649feb1$export$c500183c31c2b22e)]: final_span_columns()
917
+ },
918
+ _v$3 = "span ".concat(final_span_columns()),
919
+ _v$4 = "span ".concat(final_span_rows());
920
+ _v$ !== _p$.e && _el$.classList.toggle("spans-whole-row", _p$.e = _v$);
921
+ _p$.t = $52FdA$solidjsweb.style(_el$, _v$2, _p$.t);
922
+ _v$3 !== _p$.a && ((_p$.a = _v$3) != null ? _el$.style.setProperty("grid-column", _v$3) : _el$.style.removeProperty("grid-column"));
923
+ _v$4 !== _p$.o && ((_p$.o = _v$4) != null ? _el$.style.setProperty("grid-row", _v$4) : _el$.style.removeProperty("grid-row"));
924
+ return _p$;
925
+ }, {
926
+ e: undefined,
927
+ t: undefined,
928
+ a: undefined,
929
+ o: undefined
930
+ });
931
+ return _el$;
932
+ }
933
+ });
934
+ return $52FdA$solidjs.mergeProps(block, {
935
+ // Create content divs for the blocks with as much fine-grained diffing as possible?
936
+ content: () => {
937
+ // Sneaky on-demand rendering, so we don't render more blocks than we can show: we have the rendered value here and don't return a function that renders because if our block would be moved around we'd be guaranteed to re-render
938
+ // However, no need to count products to know if we should render: the <For> loops in Placeholders and render_displays will only call this function if there's actually a product here that wants to display this block
939
+ set_rendering_delayed_(false);
940
+ return content;
941
+ },
942
+ get span_columns() {
943
+ // Cap max width of block to the number of columns available, for everyone downstream
944
+ return final_span_columns();
945
+ },
946
+ get span_rows() {
947
+ return final_span_rows();
948
+ }
949
+ });
965
950
  });
966
- if (0, $52FdA$solidjsweb.isServer) return {
967
- renderedDisplays_: $76012c4468a53d1f$export$43f0fb951fcb0c54({
968
- displays_by_key_: displays_by_key_,
969
- product_card_template_: product_card_template_,
970
- content_blocks_: content_blocks_
971
- }),
972
- indexToTargetMap_: indexToTargetMap_,
973
- currentlyIntersecting: currentlyIntersecting
974
- };
975
- // The following sets up an intersection observer to determine which results are in the viewport, used for the ScrollStatus indicator, knowing when to load more and any other consumer of the useProductCardIsVisible hook.
976
- const shouldObserve = $52FdA$solidjs.createMemo(() => alwaysObserveCards_ || listenersForIntersecting() > 0);
977
- const intersection_observer = new IntersectionObserver($52FdA$depictaiutilishared.catchify(records => {
978
- const intersectingValue = currentlyIntersecting();
979
- for (let i = 0; i < records.length; i++) {
980
- const record = records[i];
981
- const {
982
- target: target,
983
- intersectionRatio: intersectionRatio
984
- } = record;
985
- const index_of_target = targetToIndexMap_.get(target);
986
- if (index_of_target == undefined) return; // It seems like it can happen that we get IntersectionObserverEntries after the onCleanup function for a recommendation card has run, in Firefox. Probably a bug in Firefox? If I understood the bug correctly, this is a workaround.
987
- const is_in_set = intersectingValue.has(index_of_target);
988
- if (intersectionRatio > 0) {
989
- if (!is_in_set) intersectingValue.add(index_of_target);
990
- } else if (is_in_set) intersectingValue.delete(index_of_target);
991
- }
992
- setCurrentlyIntersecting(intersectingValue);
993
- }, "renderDisplays IO failed"));
994
- const renderedDisplays_ = $52FdA$solidjsweb.createComponent($a52942afacbced93$export$f223d69ed12f5fb7.Provider, {
995
- value: {
996
- currentlyIntersecting_: currentlyIntersecting,
997
- setIsListening_: setListenersForIntersecting
951
+ return get_wrapped_blocks;
952
+ }
953
+ /**
954
+ * Basically adds support for async content block functions and shows a rudimentary placeholder if rendering is delayed. Required due to react having a rendering delay.
955
+ */
956
+ function $f8f375d6245ffff2$var$RenderContent(props) {
957
+ const [resource] = $52FdA$solidjs.createResource(() => props.content,
958
+ // Could be reactive
959
+ fn => fn());
960
+ $52FdA$solidjs.createEffect(() => {
961
+ if (resource.error) console.error("Error in content block rendering", resource.error);
962
+ });
963
+ // The suspense is for when there's an async content block (which we have to support due to react having a rendering delay) so that we can show some height while it's loading (should kinda never be visible)
964
+ return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Suspense), {
965
+ get fallback() {
966
+ return $52FdA$solidjsweb.createComponent((0, $b8a8d61b3ec5f5ac$export$3f37af283f8fb843), {
967
+ width: "100%",
968
+ height: "max(100%, 400px)"
969
+ });
970
+ },
971
+ children: resource
972
+ });
973
+ }
974
+ let $0deb6ff75e3d67c6$var$elementsHoveredSignal;
975
+ let $0deb6ff75e3d67c6$var$consumersSignal;
976
+ function $0deb6ff75e3d67c6$export$d4d96868197be50e() {
977
+ if (!$0deb6ff75e3d67c6$var$elementsHoveredSignal || !$0deb6ff75e3d67c6$var$consumersSignal) $52FdA$solidjs.createRoot(dispose => {
978
+ $0deb6ff75e3d67c6$var$elementsHoveredSignal = $52FdA$solidjs.createSignal(new Set());
979
+ $0deb6ff75e3d67c6$var$consumersSignal = $52FdA$solidjs.createSignal(0);
980
+ const [consumers] = $0deb6ff75e3d67c6$var$consumersSignal;
981
+ // No matter how often useMobileHover is called, only add one listener and get hovered elements once per touchmove event, for efficiency
982
+ $0deb6ff75e3d67c6$var$doHeavyCalculations();
983
+ $52FdA$solidjs.createEffect(() => {
984
+ // No-one needs information anymore, stop listening
985
+ const users = consumers();
986
+ if (users < 1) {
987
+ $52FdA$depictaiutilisharedlatest.dlog("Stopping to listen for mobile hover");
988
+ dispose();
989
+ $0deb6ff75e3d67c6$var$elementsHoveredSignal = undefined;
990
+ $0deb6ff75e3d67c6$var$consumersSignal = undefined;
991
+ }
992
+ });
993
+ });
994
+ const [elementsHovered] = $0deb6ff75e3d67c6$var$elementsHoveredSignal;
995
+ const [, setConsumers] = $0deb6ff75e3d67c6$var$consumersSignal;
996
+ setConsumers(prev => prev + 1);
997
+ $52FdA$solidjs.onCleanup(() => setConsumers(prev => prev - 1));
998
+ return elementsHovered;
999
+ }
1000
+ function $0deb6ff75e3d67c6$var$doHeavyCalculations() {
1001
+ $52FdA$depictaiutilisharedlatest.dlog("Starting to listen for mobile hover");
1002
+ const [, setElementsHovered] = $0deb6ff75e3d67c6$var$elementsHoveredSignal;
1003
+ const elementAtTouch = new Map();
1004
+ const updateSet = () => setElementsHovered(new Set([...elementAtTouch.values()].filter(v => v)));
1005
+ const setPositionHandler = $52FdA$depictaiutilisharedlatest.catchify(evt => {
1006
+ for (const touch of evt.changedTouches) elementAtTouch.set(touch.identifier, document.elementFromPoint(touch.clientX, touch.clientY));
1007
+ updateSet();
1008
+ });
1009
+ const deleteTouchHandler = $52FdA$depictaiutilisharedlatest.catchify(evt => {
1010
+ for (const touch of evt.changedTouches) elementAtTouch.delete(touch.identifier);
1011
+ updateSet();
1012
+ });
1013
+ addEventListener("touchstart", setPositionHandler, {
1014
+ passive: true
1015
+ });
1016
+ addEventListener("touchend", deleteTouchHandler, {
1017
+ passive: true
1018
+ });
1019
+ addEventListener("touchcancel", deleteTouchHandler, {
1020
+ passive: true
1021
+ });
1022
+ $52FdA$solidjs.onCleanup(() => {
1023
+ removeEventListener("touchstart", setPositionHandler);
1024
+ removeEventListener("touchend", deleteTouchHandler);
1025
+ removeEventListener("touchcancel", deleteTouchHandler);
1026
+ });
1027
+ }
1028
+ function $e7a7d2fe8a8217d8$export$54299a3c81f5425() {
1029
+ const d = document;
1030
+ const [isVisible, setIsVisible] = $52FdA$solidjs.createSignal(d.visibilityState !== "hidden");
1031
+ const handleVisibilityChange = () => setIsVisible(d.visibilityState !== "hidden");
1032
+ d.addEventListener("visibilitychange", handleVisibilityChange);
1033
+ $52FdA$solidjs.onCleanup(() => d.removeEventListener("visibilitychange", handleVisibilityChange));
1034
+ return isVisible;
1035
+ }
1036
+ var $9d19451330d04c3c$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<svg xmlns=http://www.w3.org/2000/svg viewBox="0 0 14 26"><path d="M2 24.656c-.078 0-.156-.016-.234-.047s-.133-.066-.187-.129c-.117-.117-.176-.258-.176-.422s.059-.305.176-.422l10.371-10.371L1.578 2.883c-.117-.117-.176-.258-.176-.422s.059-.305.176-.422.258-.176.422-.176.305.059.422.176l10.805 10.793a.59.59 0 0 1 .176.434c0 .172-.059.305-.176.422L2.422 24.48a.42.42 0 0 1-.199.129.54.54 0 0 1-.223.047zm0 0"fill=#0f0f0f>`);
1037
+ function $9d19451330d04c3c$export$8be2714ec7f169ee() {
1038
+ let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1039
+ return (() => {
1040
+ var _el$ = $52FdA$solidjsweb.getNextElement($9d19451330d04c3c$var$_tmpl$);
1041
+ $52FdA$solidjsweb.effect(_p$ => {
1042
+ var _props$width_, _props$height_;
1043
+ var _v$ = (_props$width_ = props.width_) !== null && _props$width_ !== void 0 ? _props$width_ : 14,
1044
+ _v$2 = (_props$height_ = props.height_) !== null && _props$height_ !== void 0 ? _props$height_ : 26;
1045
+ _v$ !== _p$.e && $52FdA$solidjsweb.setAttribute(_el$, "width", _p$.e = _v$);
1046
+ _v$2 !== _p$.t && $52FdA$solidjsweb.setAttribute(_el$, "height", _p$.t = _v$2);
1047
+ return _p$;
1048
+ }, {
1049
+ e: undefined,
1050
+ t: undefined
1051
+ });
1052
+ return _el$;
1053
+ })();
1054
+ }
1055
+ var $ad8ec7729fffeb9c$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div>`),
1056
+ $ad8ec7729fffeb9c$var$_tmpl$2 = /*#__PURE__*/$52FdA$solidjsweb.template(`<div class="depict-slider depict"><button aria-label="Scroll left"class="left d-navbutton"type=button></button><button aria-label="Scroll right"class="right d-navbutton"type=button></button><div class=sliding>`);
1057
+ const $ad8ec7729fffeb9c$var$SlidableContext = /*@__PURE__*/$52FdA$solidjs.createContext();
1058
+ function $ad8ec7729fffeb9c$export$6649caad96ef8870(props) {
1059
+ const {
1060
+ slider_ref_: slider_ref_,
1061
+ faded_opacity_ = 0.7,
1062
+ mutation_plugins_ = [],
1063
+ disable_fading_: disable_fading_,
1064
+ snapAlign_: snapAlign_,
1065
+ fadingThreshold_ = 0.96
1066
+ } = props;
1067
+ const [hasHydrated, setHasHydrated] = $52FdA$solidjs.createSignal(false);
1068
+ $52FdA$solidjs.createEffect(() => setHasHydrated(true));
1069
+ const MakeButton = () => (() => {
1070
+ var _el$ = $52FdA$solidjsweb.getNextElement($ad8ec7729fffeb9c$var$_tmpl$);
1071
+ $52FdA$solidjsweb.insert(_el$, $52FdA$solidjsweb.createComponent((0, $9d19451330d04c3c$export$8be2714ec7f169ee), {
1072
+ get height_() {
1073
+ return props.arrow_height_;
1074
+ },
1075
+ get width_() {
1076
+ return props.arrow_width_;
1077
+ }
1078
+ }));
1079
+ return _el$;
1080
+ })();
1081
+ // To support SSR it would be very hard to make Amazing_Slider compatible with solid's SSR because it would have to be rewritten in a more JSX way
1082
+ // However, all it would do on the server (when used by SlidableItems) is creating the following 5 div elements
1083
+ // Therefore, we just bail on the server (and first render on the client which is the hydration) and return a static version of the slider
1084
+ // Once we have hydrated, we construct and insert the actual slider
1085
+ return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
1086
+ get when() {
1087
+ return hasHydrated() && !(0, $52FdA$solidjsweb.isServer);
1088
+ },
1089
+ get fallback() {
1090
+ return (() => {
1091
+ var _el$2 = $52FdA$solidjsweb.getNextElement($ad8ec7729fffeb9c$var$_tmpl$2),
1092
+ _el$3 = _el$2.firstChild,
1093
+ _el$4 = _el$3.nextSibling,
1094
+ _el$5 = _el$4.nextSibling;
1095
+ $52FdA$solidjsweb.insert(_el$3, $52FdA$solidjsweb.createComponent(MakeButton, {}));
1096
+ $52FdA$solidjsweb.insert(_el$4, $52FdA$solidjsweb.createComponent(MakeButton, {}));
1097
+ $52FdA$solidjsweb.insert(_el$5, () => props.children);
1098
+ return _el$2;
1099
+ })();
998
1100
  },
999
1101
  get children() {
1000
- return $76012c4468a53d1f$export$43f0fb951fcb0c54({
1001
- displays_by_key_: displays_by_key_,
1002
- product_card_template_: product_card_template_,
1003
- content_blocks_: content_blocks_,
1004
- do_per_elements_: (elements, index_accessor) =>
1005
- // Adds/removes elements from the "results in viewport" intersection observer above
1006
- $52FdA$solidjs.createEffect(() => {
1007
- if (!shouldObserve()) return;
1008
- const display_index = index_accessor();
1009
- // Nested createEffect because we only want to re-run this when the index changes (or we should/shouldn't observe)
1010
- // We need to save in a map which index the elements of this template are so that we can know that in the IntersectionObserver callback
1011
- for (let i = 0; i < elements.length; i++) {
1012
- const element = elements[i];
1013
- targetToIndexMap_.set(element, display_index);
1014
- intersection_observer.observe(element);
1015
- $52FdA$solidjs.onCleanup(() => {
1016
- intersection_observer.unobserve(element);
1017
- targetToIndexMap_.delete(element);
1018
- const intersecting = $52FdA$solidjs.untrack(currentlyIntersecting);
1019
- const wasDeleted = intersecting.delete(display_index);
1020
- if (wasDeleted) setCurrentlyIntersecting(intersecting);
1021
- });
1102
+ return (() => {
1103
+ const [intersectionEntries_, setIntersectionEntries] = $52FdA$solidjs.createSignal([]);
1104
+ const fading_plugin = disable_fading_ ? undefined : $52FdA$depictaiutilishared.slider_fading_factory({
1105
+ threshold_: fadingThreshold_,
1106
+ faded_opacity_: faded_opacity_
1107
+ });
1108
+ const slider = new (0, $52FdA$depictaiutilishared.Amazing_Slider)({
1109
+ button_contents: {
1110
+ left: [MakeButton()],
1111
+ right: [MakeButton()]
1112
+ },
1113
+ constructor_plugins: [$52FdA$depictaiutilishared.slider_snap_css(0, {
1114
+ align: snapAlign_
1115
+ }).constructor_plugin, ...(fading_plugin ? [fading_plugin.constructor_plugin] : [])],
1116
+ mutation_plugins: [...(fading_plugin ? [fading_plugin.mutation_plugin_] : []), ...mutation_plugins_, entries => setIntersectionEntries(entries)]
1117
+ });
1118
+ $52FdA$solidjsweb.insert(slider.insert_here, () => $52FdA$solidjsweb.createComponent($ad8ec7729fffeb9c$var$SlidableContext.Provider, {
1119
+ value: {
1120
+ slider_: slider,
1121
+ intersectionEntries_: intersectionEntries_
1122
+ },
1123
+ get children() {
1124
+ return props.children;
1022
1125
  }
1023
- indexToTargetMap_.set(display_index, elements);
1024
- $52FdA$solidjs.onCleanup(() => indexToTargetMap_.delete(display_index));
1025
- })
1026
- });
1126
+ }));
1127
+ $52FdA$solidjs.onCleanup(() => slider.observer.disconnect());
1128
+ slider_ref_ === null || slider_ref_ === void 0 || slider_ref_(slider);
1129
+ return slider.container;
1130
+ })();
1027
1131
  }
1028
1132
  });
1029
- return {
1030
- renderedDisplays_: renderedDisplays_,
1031
- indexToTargetMap_: indexToTargetMap_,
1032
- currentlyIntersecting: currentlyIntersecting
1033
- };
1034
1133
  }
1035
- function $a52942afacbced93$export$80bb7300ce6a8be3() {
1036
- const {
1037
- setIsListening_: setIsListening_,
1038
- currentlyIntersecting_: currentlyIntersecting_
1039
- } = $52FdA$solidjs.useContext($a52942afacbced93$export$f223d69ed12f5fb7) || {};
1040
- const getOurIndex = $b54645378dfc7280$export$e3faf4d95300054f();
1041
- const isVisible = $52FdA$solidjs.createMemo(() => currentlyIntersecting_ === null || currentlyIntersecting_ === void 0 ? void 0 : currentlyIntersecting_().has(getOurIndex === null || getOurIndex === void 0 ? void 0 : getOurIndex()));
1042
- setIsListening_ === null || setIsListening_ === void 0 || setIsListening_(prev => prev + 1);
1043
- $52FdA$solidjs.onCleanup(() => setIsListening_ === null || setIsListening_ === void 0 ? void 0 : setIsListening_(prev => prev + 1));
1044
- return isVisible;
1134
+ function $ad8ec7729fffeb9c$export$eaa625fb39439e37() {
1135
+ return $52FdA$solidjs.useContext($ad8ec7729fffeb9c$var$SlidableContext);
1045
1136
  }
1046
- function $d6d51b09cb2116a6$export$5bad61ecde080b1f() {
1047
- const {
1048
- collapse: collapse,
1049
- expand: expand,
1050
- ExpandingContainer: ExpandingContainer
1051
- } = $52FdA$depictaiutilishared.useExpandingContainer(...arguments);
1052
- return {
1053
- collapse: collapse,
1054
- expand: expand,
1055
- ExpandingContainer: _ref => {
1056
- let {
1057
- children: children
1058
- } = _ref;
1059
- // get reactive signals/solid's jsx elements into `ExpandingContainer`
1060
- const fake_div = document.createElement("div");
1061
- const outer_expanding = $52FdA$solidjsweb.createComponent(ExpandingContainer, {
1062
- children: [fake_div]
1063
- });
1064
- const parent = fake_div.parentElement;
1065
- fake_div.remove();
1066
- $52FdA$solidjsweb.insert(parent, children);
1067
- return outer_expanding;
1068
- }
1069
- };
1137
+
1138
+ /**
1139
+ * Gets product_id (the thing we key the rendering on) from a display
1140
+ */
1141
+ function $b85edfec41cd3989$export$548d053aba053d79(display) {
1142
+ if ("variant_index" in display) {
1143
+ const actual_display = display.variant_displays[display.variant_index];
1144
+ return actual_display.product_id;
1145
+ }
1146
+ if ("listing_id" in display) return display.listing_id;
1147
+ return display.product_id;
1070
1148
  }
1071
- const $5401a6698b0c0658$var$transform_elements = sorted_cols_at_size => {
1072
- const cols_at_size = [];
1073
- for (let i = 0; i < sorted_cols_at_size.length; i++) {
1074
- var _sorted_cols_at_size;
1075
- const [nb_cols, width] = sorted_cols_at_size[i];
1076
- const next_width = (_sorted_cols_at_size = sorted_cols_at_size[i + 1]) === null || _sorted_cols_at_size === void 0 ? void 0 : _sorted_cols_at_size[1];
1077
- const max_width = i === 0 ? "" : "".concat(width, "px");
1078
- const min_width = next_width !== undefined ? "".concat(next_width + 1, "px") : "";
1079
- const col_at_size = [nb_cols, min_width, max_width];
1080
- cols_at_size.push(col_at_size);
1149
+ function $e82d0d417fa613e8$export$2f0cbfbb4354bb52(elements) {
1150
+ // FYI this probably doesn't work on hugely deep nestings or large amount of elements
1151
+ return $52FdA$solidjs.createMemo(() => $e82d0d417fa613e8$var$unwrapping_helper(elements));
1152
+ }
1153
+ function $e82d0d417fa613e8$var$unwrapping_helper(elements) {
1154
+ const result = [];
1155
+ if (Array.isArray(elements)) for (let i = 0; i < elements.length; i++) {
1156
+ const element = elements[i];
1157
+ result.push(...$e82d0d417fa613e8$var$unwrapping_helper(element));
1158
+ } else if (typeof elements == "function") result.push(...$e82d0d417fa613e8$var$unwrapping_helper(elements()));else if (elements != undefined && typeof elements != "boolean") result.push(elements);
1159
+ return result;
1160
+ }
1161
+
1162
+ /**
1163
+ * This is a function that will safely clone an object that may contain promises.
1164
+ * It will use structuredClone to clone the object and then re-apply (copy) any promises that were in the original object to the cloned object.
1165
+ * @param obj Anything to clone
1166
+ */
1167
+ function $400d96565bbbfe07$export$83bb9af5671e1dbe(obj) {
1168
+ if (obj instanceof Promise) return obj;
1169
+ // Extract all promises, keep a map of them, and then re-apply them to both the original object and the target object after cloning
1170
+ const seen = new Set();
1171
+ const keyStack = [[]];
1172
+ const valueStack = [obj];
1173
+ const promiseLocationStack = [];
1174
+ while (valueStack.length) {
1175
+ const value = valueStack.pop();
1176
+ const keyPath = keyStack.pop();
1177
+ // Promises can only be in objects and we don't need to check for objects we've already seen (like in circular references)
1178
+ if (typeof value !== "object" || value === null || seen.has(value)) continue;
1179
+ seen.add(value);
1180
+ if (Array.isArray(value)) {
1181
+ for (let i = 0; i < value.length; i++) {
1182
+ const ourValue = value[i];
1183
+ const valuesKeyPath = [...keyPath, i];
1184
+ if (ourValue instanceof Promise) {
1185
+ promiseLocationStack.push([valuesKeyPath, ourValue]);
1186
+ delete value[i]; // This will leave a hole in the array, but it's fine since we'll put it back soon
1187
+ // This way both the indexes will be correct when putting the value back and our for loop doesn't get messed up
1188
+ } else {
1189
+ keyStack.push(valuesKeyPath);
1190
+ valueStack.push(ourValue);
1191
+ }
1192
+ }
1193
+ continue;
1194
+ }
1195
+ for (const innerKey in value) {
1196
+ const ourValue = value[innerKey];
1197
+ const valuesKeyPath = [...keyPath, innerKey];
1198
+ if (ourValue instanceof Promise) {
1199
+ promiseLocationStack.push([valuesKeyPath, ourValue]);
1200
+ delete value[innerKey];
1201
+ } else {
1202
+ keyStack.push(valuesKeyPath);
1203
+ valueStack.push(ourValue);
1204
+ }
1205
+ }
1081
1206
  }
1082
- return cols_at_size;
1083
- };
1084
- const $5401a6698b0c0658$export$6daf8749b65a1b77 = cols_at_size => {
1085
- var _cols_at_size$every;
1086
- // Check that every element is an array
1087
- const are_arrays = cols_at_size === null || cols_at_size === void 0 ? void 0 : (_cols_at_size$every = cols_at_size.every) === null || _cols_at_size$every === void 0 ? void 0 : _cols_at_size$every.call(cols_at_size, element => Array.isArray(element));
1088
- if (!are_arrays) throw new Error("Every element in cols_at_size must be an array");
1089
- // Check width duplicates
1090
- const widths = cols_at_size.map(_ref => {
1091
- let [_, width] = _ref;
1092
- return width;
1093
- });
1094
- const widths_set = new Set(widths);
1095
- if (widths_set.size < widths.length) throw new Error("There are duplicate widths in cols_at_size");
1096
- if (cols_at_size.length === 1) {
1097
- const [nb_cols, width] = cols_at_size[0];
1098
- const max_width = width !== undefined ? "".concat(width, "px") : "";
1099
- return [[nb_cols, "", max_width]];
1207
+ let structuredClonedObject;
1208
+ let error;
1209
+ try {
1210
+ structuredClonedObject = structuredClone(obj);
1211
+ } catch (e) {
1212
+ // We still need to put back the promises in the original object, even if we threw an error
1213
+ error = e;
1100
1214
  }
1101
- // Sort widths in ascending order
1102
- const sorted_cols_at_size = [...cols_at_size].sort((a, b) => {
1103
- const [_b, width_A] = a;
1104
- const [_a, width_b] = b;
1105
- if (width_A === undefined) return -1;
1106
- if (width_b === undefined) return 1;
1107
- return width_b - width_A;
1215
+ // Put back the promises in both the original object and the cloned object
1216
+ while (promiseLocationStack.length) {
1217
+ const [keyPath, promise] = promiseLocationStack.pop();
1218
+ let targetInClone = structuredClonedObject;
1219
+ let targetInOriginal = obj;
1220
+ for (let i = 0; i < keyPath.length - 1; i++) {
1221
+ if (!error) targetInClone = targetInClone[keyPath[i]];
1222
+ targetInOriginal = targetInOriginal[keyPath[i]];
1223
+ }
1224
+ if (!error) targetInClone[keyPath[keyPath.length - 1]] = promise;
1225
+ targetInOriginal[keyPath[keyPath.length - 1]] = promise;
1226
+ }
1227
+ if (error) throw error;
1228
+ return structuredClonedObject;
1229
+ }
1230
+ let $76012c4468a53d1f$var$printedCloneError = false;
1231
+ function $76012c4468a53d1f$export$7f8bd308237ab5a5(get_displays_) {
1232
+ const displays_by_key_ = $52FdA$solidjs.createMemo(() => {
1233
+ const displays = get_displays_();
1234
+ // We key by product_id because that's what can be used to uniquely identify products
1235
+ // This way <For> can optimize the rendering
1236
+ const map = new Map();
1237
+ for (let i = 0; i < displays.length; i++) {
1238
+ const display = displays[i];
1239
+ const product_id = $b85edfec41cd3989$export$548d053aba053d79(display);
1240
+ map.set(product_id, display);
1241
+ }
1242
+ return map;
1108
1243
  });
1109
- return $5401a6698b0c0658$var$transform_elements(sorted_cols_at_size);
1110
- };
1111
- function $8edd3cf30d1fd8b4$export$a2cc176055f8f08() {
1112
- let what = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "grid";
1113
- const text = "Please try setting `columnsAtSize`/`gridSpacing` on the `SearchPage`/`CategoryPage` components to change the " + what + " before setting it with CSS. If you do with CSS, set `columnsAtSize` to an empty array to ensure no declarations created by the SDK leak through.";
1114
- return (0, $52FdA$solidjsweb.isServer) ? {
1115
- t: "<!-- ".concat(text, " -->")
1116
- } : document.createComment(text);
1244
+ return displays_by_key_;
1117
1245
  }
1118
- const $e3915574cfd3466c$var$defaultCacheKey = /*@__PURE__*/Symbol();
1119
- const $e3915574cfd3466c$var$cachedPlaceholderElements = {};
1120
- const $e3915574cfd3466c$var$renderingCachedPlaceholderElement = {};
1121
- function $e3915574cfd3466c$export$f33414a4df0afd3f(_ref) {
1246
+ const $76012c4468a53d1f$var$result_ids = ["search_result_id", "product_listing_result_id", "recommendation_id"];
1247
+ function $76012c4468a53d1f$export$43f0fb951fcb0c54(_ref) {
1122
1248
  let {
1249
+ displays_by_key_: displays_by_key_,
1123
1250
  product_card_template_: product_card_template_,
1124
- num_placeholders_: num_placeholders_,
1125
- content_blocks_: content_blocks_,
1126
- placeholderCacheKey_: placeholderCacheKey_
1251
+ do_per_elements_: do_per_elements_,
1252
+ content_blocks_: content_blocks_
1127
1253
  } = _ref;
1128
- const [num_to_actually_show, set_num_to_actually_show] = $52FdA$solidjs.createSignal($52FdA$solidjs.untrack(num_placeholders_));
1129
- if (0, $52FdA$solidjsweb.isServer)
1130
- // want to render simple placeholders on server, effects don't run there
1131
- // FIXME when adding proper SSR: also SSR content blocks
1132
- return $52FdA$solidjs.createMemo(() => Array.from({
1133
- length: num_placeholders_()
1134
- }).map(() => {
1135
- const template_result = product_card_template_(null, undefined);
1136
- // @ts-ignore
1137
- if (typeof (template_result === null || template_result === void 0 ? void 0 : template_result.then) !== "function") return template_result;
1138
- }));
1139
- $52FdA$solidjs.createRenderEffect(() => {
1140
- const existing_num = num_to_actually_show();
1141
- const to_add = num_placeholders_() - existing_num;
1142
- if (to_add <= 0) return;
1143
- // Below comment is from when we used recommendation renderer and manual DOM manipulation for this, but I'm still scared to remove placeholders and mess up scroll restoration, so I'm keeping the way it worked. Otherwise, <Index> could be used which would be far more elegant.
1144
- // We don't need to remove placeholders, only need to add. The reason for that is that chrome restores the scroll position once all tasks queued as reaction of the "popstate" events have been completed in the task queue. That means that we need to get the placeholders in fast, or we might lose scroll position if the previous site was shorter.
1145
- // The query id and the amount might update in separate tasks because one comes from href_change_ipns and the other one from another "popstate" listener. Therefore, we need to be able to dynamically add more placeholders. I'm not entirely sure about this anymore though, since we have the scroll position on a per-id basis it might work anyway but THIS WORKS, and I've been working on this bug for 3 hours so let's just keep it this way.
1146
- // Above comments were from when we added elements in this createRenderEffect. Now I changed it to just increment the number and render them from an <Index> instead, so I can add content blocks better
1147
- // Functionality should be the same
1148
- set_num_to_actually_show(existing_num + to_add);
1149
- });
1150
- return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Index), {
1254
+ return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.For), {
1151
1255
  get each() {
1152
- return Array.from({
1153
- length: num_to_actually_show()
1154
- });
1256
+ return [...displays_by_key_().keys()];
1155
1257
  },
1156
- children: (_item, index) => {
1258
+ children: (product_id, index) => {
1259
+ const owner = $52FdA$solidjs.getOwner();
1157
1260
  const possible_content_block = $52FdA$solidjs.createMemo(() => {
1158
1261
  var _content_blocks_, _content_blocks_2;
1159
- return content_blocks_ === null || content_blocks_ === void 0 ? void 0 : (_content_blocks_ = content_blocks_()) === null || _content_blocks_ === void 0 ? void 0 : (_content_blocks_2 = _content_blocks_()) === null || _content_blocks_2 === void 0 ? void 0 : _content_blocks_2[index];
1262
+ return content_blocks_ === null || content_blocks_ === void 0 ? void 0 : (_content_blocks_ = content_blocks_()) === null || _content_blocks_ === void 0 ? void 0 : (_content_blocks_2 = _content_blocks_()) === null || _content_blocks_2 === void 0 ? void 0 : _content_blocks_2[index()];
1160
1263
  });
1161
- // Show content block before product card, so it's *at* that index
1162
- return [possible_content_block, $e3915574cfd3466c$var$Placeholder({
1163
- product_card_template_: product_card_template_,
1164
- placeholderCacheKey_: placeholderCacheKey_
1165
- })]; // https://github.com/solidjs/solid/releases/tag/v1.7.0
1166
- }
1167
- });
1168
- }
1169
- /**
1170
- * Get one placeholder element. It will be cloned for each placeholder for ultimate performance even when solid-js isn't rendering the placeholders.
1171
- */
1172
- function $e3915574cfd3466c$var$Placeholder(_ref2) {
1173
- let {
1174
- product_card_template_: product_card_template_,
1175
- placeholderCacheKey_ = $e3915574cfd3466c$var$defaultCacheKey
1176
- } = _ref2;
1177
- const get_cloned_placeholders = function () {
1178
- let element_to_clone = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : $e3915574cfd3466c$var$cachedPlaceholderElements[placeholderCacheKey_];
1179
- return Array.isArray(element_to_clone) ? element_to_clone.map(el => el instanceof Node ? el.cloneNode(true) : el) : element_to_clone;
1180
- };
1181
- if ($e3915574cfd3466c$var$cachedPlaceholderElements[placeholderCacheKey_]) return get_cloned_placeholders();
1182
- let dispose_original_copy;
1183
- const get_unwrapped_element = $52FdA$solidjs.createRoot(dispose => {
1184
- dispose_original_copy = dispose;
1185
- // if product_card_template_ is async and rejects the resource will take care of throwing upwards here in the solid-js error handling system
1186
- const [resource] = $52FdA$solidjs.createResource(() => {
1187
- const rendering_cached_placeholder_element = $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_];
1188
- if (rendering_cached_placeholder_element) return rendering_cached_placeholder_element;
1189
- const return_value = product_card_template_(null, undefined);
1190
- if (typeof return_value === "object" && typeof (return_value === null || return_value === void 0 ? void 0 : return_value.then) === "function")
1191
- // Is Promise or promise-like object
1192
- $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_] = return_value;
1193
- return return_value;
1194
- });
1195
- return $52FdA$solidjs.createMemo(() => {
1196
- if (resource.loading) return () => [];
1197
- return $e82d0d417fa613e8$export$2f0cbfbb4354bb52(resource);
1198
- });
1199
- });
1200
- $52FdA$solidjs.onCleanup(() => {
1201
- const rendering = $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_];
1202
- if (rendering) {
1203
- // If we're still rendering in our separate root, let the rendering finish or other <Placeholder> components waiting for it might get an incomplete result
1204
- const unset_current_rendering = () => {
1205
- dispose_original_copy();
1206
- $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_] = undefined;
1207
- };
1208
- rendering === null || rendering === void 0 || rendering.then(unset_current_rendering, unset_current_rendering);
1209
- } else
1210
- // Otherwise, just make sure we've disposed our root
1211
- dispose_original_copy();
1212
- });
1213
- return $52FdA$solidjs.createMemo(() => {
1214
- const unwrapped_array = get_unwrapped_element()();
1215
- if (!(unwrapped_array !== null && unwrapped_array !== void 0 && unwrapped_array.length) || !unwrapped_array.every(item => item))
1216
- // Haven't finished rendering yet in case of "async" rendering, so don't freeze the elements yet
1217
- return;
1218
- // placeholders have finished rendering, freeze the elements
1219
- // here we might receive the result of a promise that has already been received, tore down and put into cached_placeholder_element, so don't overwrite that more valid result if it's already set
1220
- $e3915574cfd3466c$var$cachedPlaceholderElements[placeholderCacheKey_] || ($e3915574cfd3466c$var$cachedPlaceholderElements[placeholderCacheKey_] = get_cloned_placeholders(unwrapped_array)); // Clone initial return value so that who gave us the elements can't mutate them, which has caused issues before with react
1221
- $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_] = undefined;
1222
- dispose_original_copy(); // So that this memo will never re-run and the placeholder rendering function can clean up
1223
- return get_cloned_placeholders(); // clone, just in case. If we wouldn't, someone could modify the copy in the DOM, and it would affect the cached version
1224
- });
1225
- }
1226
-
1227
- var $6c2c739b113a8ddf$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div>`),
1228
- $6c2c739b113a8ddf$var$_tmpl$2 = /*#__PURE__*/$52FdA$solidjsweb.template(`<style type=text/css>`);
1229
- function $6c2c739b113a8ddf$export$d21e32dfedac04be(props) {
1230
- const container_class = "x" + $52FdA$solidjs.createUniqueId();
1231
- const container_element_ = (() => {
1232
- var _el$ = $52FdA$solidjsweb.getNextElement($6c2c739b113a8ddf$var$_tmpl$);
1233
- $52FdA$solidjsweb.spread(_el$, $52FdA$solidjsweb.mergeProps(() => props.element_attributes, {
1234
- "classList": {
1235
- [container_class]: true
1236
- }
1237
- }), false, true);
1238
- $52FdA$solidjsweb.insert(_el$, () => props.children);
1239
- $52FdA$solidjsweb.runHydrationEvents();
1240
- return _el$;
1241
- })(); // Don't want this in the error boundary below, it should only be for the actual layouting
1242
- return $52FdA$solidjsweb.createComponent((0, $1b3cf201cdd38687$export$b69d0d92862de18b), {
1243
- get message_() {
1244
- return "Failed calculating " + props.layout + " layout";
1245
- },
1246
- severity_: "error",
1247
- get children() {
1248
- return $6c2c739b113a8ddf$export$445d8d3f5f706a40(props, container_element_, false, container_class);
1249
- }
1250
- });
1251
- }
1252
- function $6c2c739b113a8ddf$export$445d8d3f5f706a40(props, container_element) {
1253
- let insert_after_container = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1254
- let container_class = arguments.length > 3 ? arguments[3] : undefined;
1255
- if (!container_class) {
1256
- // only try to add if it wasn't provided, so that we have a code path without classList when doing SSR
1257
- container_class = $52FdA$depictaiutilishared.make_random_classname();
1258
- container_element.classList.add(container_class);
1259
- }
1260
- // Copy of Layout from utilishared but using solid-js signals instead of async iterable IPNS
1261
- const show_all_rows = $52FdA$solidjs.createMemo(() => props.rows === "all");
1262
- const rows_or_empty_object = $52FdA$solidjs.createMemo(() => show_all_rows() ? {} : props.rows);
1263
- const view_more_button_elements = $e82d0d417fa613e8$export$2f0cbfbb4354bb52($52FdA$solidjs.createMemo(() => rows_or_empty_object().button));
1264
- const view_less_button_elements = $e82d0d417fa613e8$export$2f0cbfbb4354bb52($52FdA$solidjs.createMemo(() => rows_or_empty_object().view_less_button));
1265
- const have_a_view_more_button = $52FdA$solidjs.createMemo(() => {
1266
- const button = view_more_button_elements();
1267
- return !(!button || Array.isArray(button) && !button.length);
1268
- });
1269
- const have_a_view_less_button = $52FdA$solidjs.createMemo(() => {
1270
- const button = view_less_button_elements();
1271
- return !(!button || Array.isArray(button) && !button.length);
1272
- });
1273
- const [get_styling, set_styling] = $52FdA$solidjs.createSignal();
1274
- const selector_beginning = ".depict .".concat(container_class, ">"); // class so ppl can have id if needed
1275
- const [get_children_count, set_children_count] = $52FdA$solidjs.createSignal(0);
1276
- const update_children_count = () => (0, $52FdA$solidjsweb.isServer) ? 20 : set_children_count(container_element.children.length);
1277
- const col_styling = $52FdA$solidjs.createMemo(() => $52FdA$depictaiutilishared.n_col_styling_with_dist(selector_beginning, props.grid_spacing, props.cols_at_size, props.layout, props.override_vertical_spacing));
1278
- const default_currently_visible_signal = $52FdA$solidjs.createSignal($52FdA$solidjs.untrack(() => {
1279
- var _rows_or_empty_object;
1280
- return (_rows_or_empty_object = rows_or_empty_object().start_rows) !== null && _rows_or_empty_object !== void 0 ? _rows_or_empty_object : 1;
1281
- })); // Keep this signal here, so it doesn't change when rows_or_empty_object and I think it's to be expected that the "internal default signal" stays the same
1282
- const rows_visible_signal = $52FdA$solidjs.createMemo(() => rows_or_empty_object().currently_visible || default_currently_visible_signal);
1283
- const get_rows_visible = $52FdA$solidjs.createMemo(() => rows_visible_signal()[0]());
1284
- const set_rows_visible = $52FdA$solidjs.createMemo(() => rows_visible_signal()[1]);
1285
- const view_more_button_class = "m" + $52FdA$solidjs.createUniqueId();
1286
- const view_less_button_class = "l" + $52FdA$solidjs.createUniqueId(); // https://github.com/solidjs/solid-docs/issues/263#issuecomment-1622388079
1287
- const view_more_button_container = $52FdA$solidjs.createMemo(() => have_a_view_more_button() && (() => {
1288
- var _el$2 = $52FdA$solidjsweb.getNextElement($6c2c739b113a8ddf$var$_tmpl$);
1289
- $52FdA$solidjsweb.addEventListener(_el$2, "click", $52FdA$depictaiutilishared.catchify(() => set_rows_visible()(prev => {
1290
- var _rows_or_empty_object2;
1291
- return prev + ((_rows_or_empty_object2 = rows_or_empty_object().rows_per_click) !== null && _rows_or_empty_object2 !== void 0 ? _rows_or_empty_object2 : 1);
1292
- })), true);
1293
- $52FdA$solidjsweb.className(_el$2, "load-more-container ".concat(view_more_button_class));
1294
- $52FdA$solidjsweb.insert(_el$2, () => rows_or_empty_object().button);
1295
- $52FdA$solidjsweb.runHydrationEvents();
1296
- return _el$2;
1297
- })());
1298
- // We need to have duplicate buttons because which ones is shown depends on the number of rows visible and therefore on the viewport size and therefore on the css media queries
1299
- const view_less_button_container = $52FdA$solidjs.createMemo(() => have_a_view_less_button() && (() => {
1300
- var _el$3 = $52FdA$solidjsweb.getNextElement($6c2c739b113a8ddf$var$_tmpl$);
1301
- $52FdA$solidjsweb.addEventListener(_el$3, "click", $52FdA$depictaiutilishared.catchify(() => set_rows_visible()(() => {
1302
- var _rows_or_empty_object3;
1303
- return (_rows_or_empty_object3 = rows_or_empty_object().start_rows) !== null && _rows_or_empty_object3 !== void 0 ? _rows_or_empty_object3 : 1;
1304
- })), true);
1305
- $52FdA$solidjsweb.className(_el$3, "load-less-container ".concat(view_less_button_class));
1306
- $52FdA$solidjsweb.insert(_el$3, () => rows_or_empty_object().view_less_button);
1307
- $52FdA$solidjsweb.runHydrationEvents();
1308
- return _el$3;
1309
- })());
1310
- const [force_style_update, set_force_style_update] = $52FdA$solidjs.createSignal("");
1311
- $52FdA$solidjs.createComputed(() => {
1312
- // Make sure we don't have more rows visible than max_rows (this could happen by max_rows being decreased)
1313
- const rows_visible = get_rows_visible();
1314
- const max_rows = rows_or_empty_object().max_rows;
1315
- if (!isNaN(max_rows) && max_rows >= 0 && rows_visible > max_rows) set_rows_visible()(max_rows);
1316
- });
1317
- $52FdA$solidjs.createEffect(() => set_force_style_update(" ")); // force style update after hydration due to https://discord.com/channels/722131463138705510/722167424186843267/1151544212517552168
1318
- $52FdA$solidjs.createRenderEffect(() => {
1319
- // Be careful to only read show_all_rows in here (ofc doesn't apply to nested effects)
1320
- if (show_all_rows()) {
1321
- // no view more functionality requested
1322
- set_styling(() => col_styling);
1323
- return;
1324
- }
1325
- update_children_count();
1326
- if (!(0, $52FdA$solidjsweb.isServer)) {
1327
- const mutation_observer = new MutationObserver($52FdA$depictaiutilishared.catchify(update_children_count));
1328
- mutation_observer.observe(container_element, {
1329
- childList: true
1264
+ const display_accessor = $52FdA$solidjs.createMemo(prev => {
1265
+ const new_display = displays_by_key_().get(product_id);
1266
+ if (prev && $76012c4468a53d1f$var$deep_equal(prev, new_display))
1267
+ // If displays are identical, they haven't changed due to merchant/market changing OR we made a new query and the displays are the same. Return the old display (same object reference) to avoid re-rendering.
1268
+ // This doesn't work if people mutate the displays from within the template but we hope they don't
1269
+ // (We can't know if the display changing is due to merchant/market changing or a new query otherwise and don't want to run into https://gitlab.com/depict-ai/depict.ai/-/merge_requests/6890/diffs)
1270
+ return prev;
1271
+ return new_display;
1272
+ });
1273
+ const [product_card_resource] = $52FdA$solidjs.createResource(display_accessor,
1274
+ // re-render when the reference to the display object changes
1275
+ display => {
1276
+ // It's easy for merchants to accidentally mutate the display or some sub-object thereof
1277
+ // We had a case on singular where they popped an image url and due to use caching after some time there was no image
1278
+ // Attempt cloning the displays if possible (99.9% of the cases probably) and if not, just use the original display
1279
+ try {
1280
+ // Use promiseSafeStructuredClone so that:
1281
+ // 1. When fetching for example prices from an API, one can start that API request
1282
+ // 2. Add the promise to the display
1283
+ // 3. Already render the product card with placeholders for prices while the price loads
1284
+ // 4. When the price loads, re-render the display with the new price
1285
+ display = $400d96565bbbfe07$export$83bb9af5671e1dbe(display);
1286
+ } catch (e) {
1287
+ if (!$76012c4468a53d1f$var$printedCloneError) {
1288
+ $76012c4468a53d1f$var$printedCloneError = true;
1289
+ $52FdA$depictaiutilishared.dlog("Can't clone display", display, " (uncloneable objects in it), make sure you don't mutate it in the template since we cache.", e);
1290
+ }
1291
+ }
1292
+ let renderingResult;
1293
+ // Wrap the product card in a ProductCardIndexProvider so that the index is available to the product card
1294
+ // This is wo we can do intelligent image loading in ShopifyContainedImage without shopify devs having to pass in the index
1295
+ // We don't care about the return value of ProductCardIndexProvider because our rendering result might be a promise which solid doesn't support until it has gone through createResource
1296
+ $b54645378dfc7280$export$11354f017ddc9790({
1297
+ index_: index,
1298
+ get children() {
1299
+ // This is the key - the functions called inside of the children getter of the provider are the one that have the context defined in their solid-internal Owner
1300
+ renderingResult = product_card_template_(display, {
1301
+ set_on_index_change: fn => $52FdA$solidjs.runWithOwner(owner, () => $52FdA$solidjs.createEffect(() => fn(index())))
1302
+ });
1303
+ return undefined; // just to satisfy the typing
1304
+ }
1305
+ });
1306
+ // renderingResult is guaranteed to be defined here (if rendering returned something) because the children getter of ProductCardIndexProvider is called synchronously (createRenderEffect is used solid-internally)
1307
+ return renderingResult;
1330
1308
  });
1331
- $52FdA$solidjs.onCleanup(() => mutation_observer.disconnect());
1332
- }
1333
- set_styling(
1334
- // this is needed because solid will think that the memo-accessor is a setter function otherwise
1335
- () => $52FdA$solidjs.createMemo(() => {
1336
- const {
1337
- rows_per_click: rows_per_click,
1338
- max_rows = -1,
1339
- start_rows: start_rows
1340
- } = rows_or_empty_object();
1341
- const rows_visible = get_rows_visible();
1342
- const children_count = get_children_count();
1343
- return force_style_update() + col_styling() + props.cols_at_size.map(options => {
1344
- const [recs_per_row, min, max] = options;
1345
- let should_hide_view_more_button;
1346
- let visible_recs;
1347
- if (props.disable_partial_rows) {
1348
- visible_recs = $52FdA$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible, children_count, options);
1349
- const visible_recs_next_show_more = $52FdA$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible + (rows_per_click || 0),
1350
- // Should this really be zero when we default rows_per_click to 1?
1351
- children_count, options);
1352
- should_hide_view_more_button = visible_recs === visible_recs_next_show_more;
1353
- } else {
1354
- visible_recs = $52FdA$depictaiutilishared.layout_get_total_rec_amount_for_row(rows_visible, options);
1355
- should_hide_view_more_button = visible_recs >= children_count;
1309
+ const node_accessor = $e82d0d417fa613e8$export$2f0cbfbb4354bb52(product_card_resource);
1310
+ $52FdA$solidjs.createEffect(() => {
1311
+ const product_card_nodes = node_accessor();
1312
+ const display = display_accessor();
1313
+ const elements = [];
1314
+ for (let i = 0; i < product_card_nodes.length; i++) {
1315
+ const element = product_card_nodes[i];
1316
+ if (!(element instanceof Element)) continue;
1317
+ elements.push(element);
1318
+ // Add tracking ids
1319
+ if (!(element instanceof HTMLElement)) continue; // Apparently only HTMLElements have dataset
1320
+ for (let i = 0; i < $76012c4468a53d1f$var$result_ids.length; i++) {
1321
+ const id = $76012c4468a53d1f$var$result_ids[i];
1322
+ const value = display[id];
1323
+ if (value) Object.assign(element.dataset, $52FdA$depictaiutilishared.camelCasifyObject({
1324
+ [id]: value
1325
+ }));
1326
+ }
1356
1327
  }
1357
- const should_hide_button_final = should_hide_view_more_button || max_rows !== -1 && rows_visible >= max_rows;
1358
- // I don't really understand the logic for when the view more button gets hidden so IDK if below is correct, but it works how it should for now
1359
- const should_hide_view_less_button = !should_hide_view_more_button || start_rows == undefined || rows_visible <= start_rows || children_count <= recs_per_row * start_rows;
1360
- return "".concat($52FdA$depictaiutilishared.layout_media_query_header(min, max), "{").concat(selector_beginning, ":nth-child(n+").concat(visible_recs + 1, "){display:none}").concat(props.layout == "slider" ? "".concat(selector_beginning, ":nth-child(n+").concat(visible_recs, "){margin-right:0}") : "").concat(should_hide_button_final ? ".depict .".concat(view_more_button_class, "{display:none!important}") : "").concat(should_hide_view_less_button ? ".depict .".concat(view_less_button_class, "{display:none!important}") : "", "}");
1361
- }).join("");
1362
- }));
1328
+ do_per_elements_ === null || do_per_elements_ === void 0 || do_per_elements_(elements, index);
1329
+ });
1330
+ return [
1331
+ // Show content block before product card, so it's *at* that index
1332
+ possible_content_block, node_accessor // Don't return product_card_resource as calling it could be creating the nodes which would mean we'd be double-creating the nodes,
1333
+ ]; // Regarding the as unknown shenanigans: https://github.com/solidjs/solid/releases/tag/v1.7.0
1334
+ }
1363
1335
  });
1364
- const style_element = (() => {
1365
- var _el$4 = $52FdA$solidjsweb.getNextElement($6c2c739b113a8ddf$var$_tmpl$2);
1366
- $52FdA$solidjsweb.insert(_el$4, get_styling);
1367
- return _el$4;
1368
- })(); // need to create this after set_styling has been called or else there will be no styling in the SSR'd output
1369
- if (insert_after_container) container_element.after(style_element);
1370
- return [container_element, $52FdA$solidjsweb.memo(view_more_button_container), $52FdA$solidjsweb.memo(view_less_button_container), style_element];
1371
1336
  }
1372
- $52FdA$solidjsweb.delegateEvents(["click"]);
1373
- var $236a257ee52e5414$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<h2 class=recs-title>`);
1374
- function $236a257ee52e5414$export$d41d19e89346fa2(_ref) {
1337
+ // source: https://medium.com/@pancemarko/deep-equality-in-javascript-determining-if-two-objects-are-equal-bf98cf47e934
1338
+ // deeply diffs two objects
1339
+ // Modified by chatGPT to not be recursive, since stiga was getting a stack overflow just due to the size of their data
1340
+ // Modified futher to bias towards saying objects are equal non-primitive objects differ
1341
+ function $76012c4468a53d1f$var$deep_equal(obj1, obj2) {
1342
+ const stack = [[obj1, obj2]];
1343
+ while (stack.length) {
1344
+ const [currentObj1, currentObj2] = stack.pop();
1345
+ if (currentObj1 === currentObj2) continue;
1346
+ if (Array.isArray(currentObj1) && Array.isArray(currentObj2)) {
1347
+ if (currentObj1.length !== currentObj2.length) return false;
1348
+ for (let i = 0; i < currentObj1.length; i++) stack.push([currentObj1[i], currentObj2[i]]);
1349
+ } else if (typeof currentObj1 === "object" && typeof currentObj2 === "object" && currentObj1 !== null && currentObj2 !== null) {
1350
+ if (Array.isArray(currentObj1) || Array.isArray(currentObj2)) return false;
1351
+ const keys1 = Object.keys(currentObj1);
1352
+ const keys2 = Object.keys(currentObj2);
1353
+ if (keys1.length !== keys2.length || !keys1.every(key => keys2.includes(key))) return false;
1354
+ for (let key in currentObj1) {
1355
+ if ($76012c4468a53d1f$var$result_ids.includes(key)) continue; // ignore comparing values for keys we know are changing with every request
1356
+ stack.push([currentObj1[key], currentObj2[key]]);
1357
+ }
1358
+ } else if (typeof currentObj1 !== "function" && typeof currentObj2 !== "function")
1359
+ // Claim that all functions are equal, since the only way a function ends up here is because someone added it in the displayTransformer and that shouldn't force us to re-render, right?
1360
+ return false;
1361
+ }
1362
+ return true;
1363
+ }
1364
+ const $a52942afacbced93$export$f223d69ed12f5fb7 = /*@__PURE__*/$52FdA$solidjs.createContext();
1365
+ function $a52942afacbced93$export$4a14175d33d81a96(_ref) {
1375
1366
  let {
1376
- recommendations_resource_: recommendations_resource_,
1367
+ displays_by_key_: displays_by_key_,
1377
1368
  product_card_template_: product_card_template_,
1378
- layout_options_: layout_options_,
1379
- title_: title_,
1380
- NoResultsFallback_: NoResultsFallback_,
1381
- placeholderCacheKey_: placeholderCacheKey_
1369
+ content_blocks_: content_blocks_,
1370
+ alwaysObserveCards_: alwaysObserveCards_
1382
1371
  } = _ref;
1383
- const is_showing_something = $52FdA$solidjs.createMemo(() => {
1384
- var _recommendations_reso;
1385
- return recommendations_resource_.loading || ((_recommendations_reso = recommendations_resource_()) === null || _recommendations_reso === void 0 ? void 0 : _recommendations_reso.length);
1372
+ const targetToIndexMap_ = new Map();
1373
+ const indexToTargetMap_ = new Map();
1374
+ const [listenersForIntersecting, setListenersForIntersecting] = $52FdA$solidjs.createSignal(0);
1375
+ const [currentlyIntersecting, setCurrentlyIntersecting] = $52FdA$solidjs.createSignal(new Set(), {
1376
+ equals: false
1386
1377
  });
1387
- const title = $52FdA$solidjs.createMemo(() => title_ === null || title_ === void 0 ? void 0 : title_()); // In case getter/accessor creates elements, don't create them twice
1388
- const num_placeholders_ = () => 20;
1389
- const slider = [$52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
1390
- get when() {
1391
- return title();
1392
- },
1393
- get children() {
1394
- var _el$ = $52FdA$solidjsweb.getNextElement($236a257ee52e5414$var$_tmpl$);
1395
- $52FdA$solidjsweb.insert(_el$, title);
1396
- return _el$;
1397
- }
1398
- }), $52FdA$solidjsweb.createComponent((0, $ad8ec7729fffeb9c$export$6649caad96ef8870), {
1399
- arrow_height_: 25,
1400
- arrow_width_: 12.5,
1401
- disable_fading_: true,
1402
- slider_ref_: slider => {
1378
+ if (0, $52FdA$solidjsweb.isServer) return {
1379
+ renderedDisplays_: $76012c4468a53d1f$export$43f0fb951fcb0c54({
1380
+ displays_by_key_: displays_by_key_,
1381
+ product_card_template_: product_card_template_,
1382
+ content_blocks_: content_blocks_
1383
+ }),
1384
+ indexToTargetMap_: indexToTargetMap_,
1385
+ currentlyIntersecting: currentlyIntersecting
1386
+ };
1387
+ // The following sets up an intersection observer to determine which results are in the viewport, used for the ScrollStatus indicator, knowing when to load more and any other consumer of the useProductCardIsVisible hook.
1388
+ const shouldObserve = $52FdA$solidjs.createMemo(() => alwaysObserveCards_ || listenersForIntersecting() > 0);
1389
+ const intersection_observer = new IntersectionObserver($52FdA$depictaiutilishared.catchify(records => {
1390
+ const intersectingValue = currentlyIntersecting();
1391
+ for (let i = 0; i < records.length; i++) {
1392
+ const record = records[i];
1403
1393
  const {
1404
- insert_here: insert_here,
1405
- container: container
1406
- } = slider;
1407
- const Layout = props => $6c2c739b113a8ddf$export$445d8d3f5f706a40(props, insert_here, true);
1408
- // Do like this, so we don't have to call mergeProps ourselves
1409
- $52FdA$solidjsweb.createComponent(Layout, $52FdA$solidjsweb.mergeProps({
1410
- rows: "all",
1411
- layout: "slider"
1412
- }, layout_options_));
1413
- $52FdA$depictaiutilishared.slider_fractional_factory(0, 0.75).constructor_plugin.call(slider, {}); // enable fractional scrolling
1414
- insert_here.before($8edd3cf30d1fd8b4$export$a2cc176055f8f08());
1415
- container.classList.add("products");
1394
+ target: target,
1395
+ intersectionRatio: intersectionRatio
1396
+ } = record;
1397
+ const index_of_target = targetToIndexMap_.get(target);
1398
+ if (index_of_target == undefined) return; // It seems like it can happen that we get IntersectionObserverEntries after the onCleanup function for a recommendation card has run, in Firefox. Probably a bug in Firefox? If I understood the bug correctly, this is a workaround.
1399
+ const is_in_set = intersectingValue.has(index_of_target);
1400
+ if (intersectionRatio > 0) {
1401
+ if (!is_in_set) intersectingValue.add(index_of_target);
1402
+ } else if (is_in_set) intersectingValue.delete(index_of_target);
1403
+ }
1404
+ setCurrentlyIntersecting(intersectingValue);
1405
+ }, "renderDisplays IO failed"));
1406
+ const renderedDisplays_ = $52FdA$solidjsweb.createComponent($a52942afacbced93$export$f223d69ed12f5fb7.Provider, {
1407
+ value: {
1408
+ currentlyIntersecting_: currentlyIntersecting,
1409
+ setIsListening_: setListenersForIntersecting
1416
1410
  },
1417
1411
  get children() {
1418
- return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Suspense), {
1419
- get fallback() {
1420
- return $e3915574cfd3466c$export$f33414a4df0afd3f({
1421
- num_placeholders_: num_placeholders_,
1422
- product_card_template_: product_card_template_,
1423
- placeholderCacheKey_: placeholderCacheKey_
1424
- });
1425
- },
1426
- get children() {
1427
- return (() => {
1428
- // IIFE to make sure we access both the recommendations_resource and the resources containing the product card rendering results themselves within the Suspense boundary
1429
- const displays_by_key_ = $76012c4468a53d1f$export$7f8bd308237ab5a5($52FdA$solidjs.createMemo(() => recommendations_resource_() || []));
1430
- const {
1431
- renderedDisplays_: renderedDisplays_
1432
- } = $a52942afacbced93$export$4a14175d33d81a96({
1433
- displays_by_key_: displays_by_key_,
1434
- product_card_template_: product_card_template_
1412
+ return $76012c4468a53d1f$export$43f0fb951fcb0c54({
1413
+ displays_by_key_: displays_by_key_,
1414
+ product_card_template_: product_card_template_,
1415
+ content_blocks_: content_blocks_,
1416
+ do_per_elements_: (elements, index_accessor) =>
1417
+ // Adds/removes elements from the "results in viewport" intersection observer above
1418
+ $52FdA$solidjs.createEffect(() => {
1419
+ if (!shouldObserve()) return;
1420
+ const display_index = index_accessor();
1421
+ // Nested createEffect because we only want to re-run this when the index changes (or we should/shouldn't observe)
1422
+ // We need to save in a map which index the elements of this template are so that we can know that in the IntersectionObserver callback
1423
+ for (let i = 0; i < elements.length; i++) {
1424
+ const element = elements[i];
1425
+ targetToIndexMap_.set(element, display_index);
1426
+ intersection_observer.observe(element);
1427
+ $52FdA$solidjs.onCleanup(() => {
1428
+ intersection_observer.unobserve(element);
1429
+ targetToIndexMap_.delete(element);
1430
+ const intersecting = $52FdA$solidjs.untrack(currentlyIntersecting);
1431
+ const wasDeleted = intersecting.delete(display_index);
1432
+ if (wasDeleted) setCurrentlyIntersecting(intersecting);
1435
1433
  });
1436
- return renderedDisplays_;
1437
- })();
1438
- }
1434
+ }
1435
+ indexToTargetMap_.set(display_index, elements);
1436
+ $52FdA$solidjs.onCleanup(() => indexToTargetMap_.delete(display_index));
1437
+ })
1438
+ });
1439
+ }
1440
+ });
1441
+ return {
1442
+ renderedDisplays_: renderedDisplays_,
1443
+ indexToTargetMap_: indexToTargetMap_,
1444
+ currentlyIntersecting: currentlyIntersecting
1445
+ };
1446
+ }
1447
+ function $a52942afacbced93$export$80bb7300ce6a8be3() {
1448
+ const {
1449
+ setIsListening_: setIsListening_,
1450
+ currentlyIntersecting_: currentlyIntersecting_
1451
+ } = $52FdA$solidjs.useContext($a52942afacbced93$export$f223d69ed12f5fb7) || {};
1452
+ const getOurIndex = $b54645378dfc7280$export$e3faf4d95300054f();
1453
+ const isVisible = $52FdA$solidjs.createMemo(() => currentlyIntersecting_ === null || currentlyIntersecting_ === void 0 ? void 0 : currentlyIntersecting_().has(getOurIndex === null || getOurIndex === void 0 ? void 0 : getOurIndex()));
1454
+ setIsListening_ === null || setIsListening_ === void 0 || setIsListening_(prev => prev + 1);
1455
+ $52FdA$solidjs.onCleanup(() => setIsListening_ === null || setIsListening_ === void 0 ? void 0 : setIsListening_(prev => prev + 1));
1456
+ return isVisible;
1457
+ }
1458
+ function $d6d51b09cb2116a6$export$5bad61ecde080b1f() {
1459
+ const {
1460
+ collapse: collapse,
1461
+ expand: expand,
1462
+ ExpandingContainer: ExpandingContainer
1463
+ } = $52FdA$depictaiutilishared.useExpandingContainer(...arguments);
1464
+ return {
1465
+ collapse: collapse,
1466
+ expand: expand,
1467
+ ExpandingContainer: _ref => {
1468
+ let {
1469
+ children: children
1470
+ } = _ref;
1471
+ // get reactive signals/solid's jsx elements into `ExpandingContainer`
1472
+ const fake_div = document.createElement("div");
1473
+ const outer_expanding = $52FdA$solidjsweb.createComponent(ExpandingContainer, {
1474
+ children: [fake_div]
1439
1475
  });
1476
+ const parent = fake_div.parentElement;
1477
+ fake_div.remove();
1478
+ $52FdA$solidjsweb.insert(parent, children);
1479
+ return outer_expanding;
1440
1480
  }
1441
- })];
1442
- return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
1443
- get when() {
1444
- return is_showing_something();
1445
- },
1446
- get fallback() {
1447
- return NoResultsFallback_ === null || NoResultsFallback_ === void 0 ? void 0 : NoResultsFallback_();
1448
- },
1449
- children: slider
1450
- });
1451
- }
1452
- function $d05611ff6b8c8357$export$23fca46f3143581f(component, error_message) {
1453
- const component_in_error_boundary = do_with_elements => {
1454
- const error_boundary_wrapped = $1b3cf201cdd38687$export$b69d0d92862de18b({
1455
- severity_: "error",
1456
- message_: error_message,
1457
- get children() {
1458
- const elements = component();
1459
- do_with_elements === null || do_with_elements === void 0 || do_with_elements(elements);
1460
- return elements;
1461
- }
1462
- });
1463
- // This might return an accessor, in that case we need to "unwrap" it since our SDK consumers expect HTML elements or arrays thereof
1464
- if (typeof error_boundary_wrapped === "function")
1465
- // @ts-ignore
1466
- return error_boundary_wrapped();
1467
- // On the server it returns a string, so we just return that
1468
- return error_boundary_wrapped;
1469
1481
  };
1470
- const owner = $52FdA$solidjs.getOwner();
1471
- if (owner == null) return $52FdA$solidjs.createRoot(dispose => {
1472
- // if we're not already run in a root, create a root and automatically dispose it when the first returned element is removed from the DOM
1473
- return component_in_error_boundary(elements => {
1474
- const have_multiple = Array.isArray(elements);
1475
- if (have_multiple ? !(elements !== null && elements !== void 0 && elements.length) : !elements) return;
1476
- (0, $52FdA$depictaiutilishared.observer).onremoved(have_multiple ? elements[0] : elements, _ref => {
1477
- let {
1478
- element: element
1479
- } = _ref;
1480
- if (document.documentElement.contains(element)) return; // If element has instantly been re-inserted, don't dispose
1481
- // See https://depictaiworkspace.slack.com/archives/C050GHEPBTR/p1695809102791259?thread_ts=1695106805.459729&cid=C050GHEPBTR
1482
- dispose();
1483
- });
1484
- });
1485
- });else
1486
- // we're already in a root so cleanups are handled
1487
- return component_in_error_boundary();
1488
1482
  }
1489
- const $d067f3a30f047b41$var$ListingContext = /*@__PURE__*/$52FdA$solidjs.createContext();
1490
- function $d067f3a30f047b41$export$e68cff63f76bd15b(props) {
1491
- const our_object = {};
1492
- return $52FdA$solidjsweb.createComponent($d067f3a30f047b41$var$ListingContext.Provider, {
1493
- value: our_object,
1494
- get children() {
1495
- return props.children;
1496
- }
1483
+ const $5401a6698b0c0658$var$transform_elements = sorted_cols_at_size => {
1484
+ const cols_at_size = [];
1485
+ for (let i = 0; i < sorted_cols_at_size.length; i++) {
1486
+ var _sorted_cols_at_size;
1487
+ const [nb_cols, width] = sorted_cols_at_size[i];
1488
+ const next_width = (_sorted_cols_at_size = sorted_cols_at_size[i + 1]) === null || _sorted_cols_at_size === void 0 ? void 0 : _sorted_cols_at_size[1];
1489
+ const max_width = i === 0 ? "" : "".concat(width, "px");
1490
+ const min_width = next_width !== undefined ? "".concat(next_width + 1, "px") : "";
1491
+ const col_at_size = [nb_cols, min_width, max_width];
1492
+ cols_at_size.push(col_at_size);
1493
+ }
1494
+ return cols_at_size;
1495
+ };
1496
+ const $5401a6698b0c0658$export$6daf8749b65a1b77 = cols_at_size => {
1497
+ var _cols_at_size$every;
1498
+ // Check that every element is an array
1499
+ const are_arrays = cols_at_size === null || cols_at_size === void 0 ? void 0 : (_cols_at_size$every = cols_at_size.every) === null || _cols_at_size$every === void 0 ? void 0 : _cols_at_size$every.call(cols_at_size, element => Array.isArray(element));
1500
+ if (!are_arrays) throw new Error("Every element in cols_at_size must be an array");
1501
+ // Check width duplicates
1502
+ const widths = cols_at_size.map(_ref => {
1503
+ let [_, width] = _ref;
1504
+ return width;
1497
1505
  });
1506
+ const widths_set = new Set(widths);
1507
+ if (widths_set.size < widths.length) throw new Error("There are duplicate widths in cols_at_size");
1508
+ if (cols_at_size.length === 1) {
1509
+ const [nb_cols, width] = cols_at_size[0];
1510
+ const max_width = width !== undefined ? "".concat(width, "px") : "";
1511
+ return [[nb_cols, "", max_width]];
1512
+ }
1513
+ // Sort widths in ascending order
1514
+ const sorted_cols_at_size = [...cols_at_size].sort((a, b) => {
1515
+ const [_b, width_A] = a;
1516
+ const [_a, width_b] = b;
1517
+ if (width_A === undefined) return -1;
1518
+ if (width_b === undefined) return 1;
1519
+ return width_b - width_A;
1520
+ });
1521
+ return $5401a6698b0c0658$var$transform_elements(sorted_cols_at_size);
1522
+ };
1523
+ function $8edd3cf30d1fd8b4$export$a2cc176055f8f08() {
1524
+ let what = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "grid";
1525
+ const text = "Please try setting `columnsAtSize`/`gridSpacing` on the `SearchPage`/`CategoryPage` components to change the " + what + " before setting it with CSS. If you do with CSS, set `columnsAtSize` to an empty array to ensure no declarations created by the SDK leak through.";
1526
+ return (0, $52FdA$solidjsweb.isServer) ? {
1527
+ t: "<!-- ".concat(text, " -->")
1528
+ } : document.createComment(text);
1498
1529
  }
1499
- function $d067f3a30f047b41$export$8d0c4fdbb05a2f2e() {
1500
- return $52FdA$solidjs.useContext($d067f3a30f047b41$var$ListingContext);
1501
- }
1502
- function $a7f7d416e6f61504$export$89c6019e4baa40b1(props) {
1503
- const style = $52FdA$solidjs.createMemo(() => {
1504
- const {
1505
- style: style,
1506
- height: height,
1507
- width: width
1508
- } = props;
1509
- return {
1510
- ...(style || {}),
1511
- height: height !== null && height !== void 0 ? height : "1em",
1512
- ...(width && {
1513
- width: width
1514
- })
1515
- };
1530
+ const $e3915574cfd3466c$var$defaultCacheKey = /*@__PURE__*/Symbol();
1531
+ const $e3915574cfd3466c$var$cachedPlaceholderElements = {};
1532
+ const $e3915574cfd3466c$var$renderingCachedPlaceholderElement = {};
1533
+ function $e3915574cfd3466c$export$f33414a4df0afd3f(_ref) {
1534
+ let {
1535
+ product_card_template_: product_card_template_,
1536
+ num_placeholders_: num_placeholders_,
1537
+ content_blocks_: content_blocks_,
1538
+ placeholderCacheKey_: placeholderCacheKey_
1539
+ } = _ref;
1540
+ const [num_to_actually_show, set_num_to_actually_show] = $52FdA$solidjs.createSignal($52FdA$solidjs.untrack(num_placeholders_));
1541
+ if (0, $52FdA$solidjsweb.isServer)
1542
+ // want to render simple placeholders on server, effects don't run there
1543
+ // FIXME when adding proper SSR: also SSR content blocks
1544
+ return $52FdA$solidjs.createMemo(() => Array.from({
1545
+ length: num_placeholders_()
1546
+ }).map(() => {
1547
+ const template_result = product_card_template_(null, undefined);
1548
+ // @ts-ignore
1549
+ if (typeof (template_result === null || template_result === void 0 ? void 0 : template_result.then) !== "function") return template_result;
1550
+ }));
1551
+ $52FdA$solidjs.createRenderEffect(() => {
1552
+ const existing_num = num_to_actually_show();
1553
+ const to_add = num_placeholders_() - existing_num;
1554
+ if (to_add <= 0) return;
1555
+ // Below comment is from when we used recommendation renderer and manual DOM manipulation for this, but I'm still scared to remove placeholders and mess up scroll restoration, so I'm keeping the way it worked. Otherwise, <Index> could be used which would be far more elegant.
1556
+ // We don't need to remove placeholders, only need to add. The reason for that is that chrome restores the scroll position once all tasks queued as reaction of the "popstate" events have been completed in the task queue. That means that we need to get the placeholders in fast, or we might lose scroll position if the previous site was shorter.
1557
+ // The query id and the amount might update in separate tasks because one comes from href_change_ipns and the other one from another "popstate" listener. Therefore, we need to be able to dynamically add more placeholders. I'm not entirely sure about this anymore though, since we have the scroll position on a per-id basis it might work anyway but THIS WORKS, and I've been working on this bug for 3 hours so let's just keep it this way.
1558
+ // Above comments were from when we added elements in this createRenderEffect. Now I changed it to just increment the number and render them from an <Index> instead, so I can add content blocks better
1559
+ // Functionality should be the same
1560
+ set_num_to_actually_show(existing_num + to_add);
1516
1561
  });
1517
- return $52FdA$solidjsweb.createComponent((0, $e3d733f899558f40$export$acb3eaade4b23afd), {
1518
- get style() {
1519
- return style();
1562
+ return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Index), {
1563
+ get each() {
1564
+ return Array.from({
1565
+ length: num_to_actually_show()
1566
+ });
1520
1567
  },
1521
- get ["class"]() {
1522
- return props.class;
1568
+ children: (_item, index) => {
1569
+ const possible_content_block = $52FdA$solidjs.createMemo(() => {
1570
+ var _content_blocks_, _content_blocks_2;
1571
+ return content_blocks_ === null || content_blocks_ === void 0 ? void 0 : (_content_blocks_ = content_blocks_()) === null || _content_blocks_ === void 0 ? void 0 : (_content_blocks_2 = _content_blocks_()) === null || _content_blocks_2 === void 0 ? void 0 : _content_blocks_2[index];
1572
+ });
1573
+ // Show content block before product card, so it's *at* that index
1574
+ return [possible_content_block, $e3915574cfd3466c$var$Placeholder({
1575
+ product_card_template_: product_card_template_,
1576
+ placeholderCacheKey_: placeholderCacheKey_
1577
+ })]; // https://github.com/solidjs/solid/releases/tag/v1.7.0
1523
1578
  }
1524
1579
  });
1525
1580
  }
1526
- var $c0cf6af094336798$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div class=instant-card><div class=img-part></div><div class=right-part><div class=title-brand-tagline><span class=title></span></div><div class=price-container>`);
1527
- const $c0cf6af094336798$export$8a2234b5b1a5ebd4 = "--image-aspect-ratio";
1528
- function $c0cf6af094336798$export$ee1733d9a8495996() {
1529
- return (() => {
1530
- var _el$ = $52FdA$solidjsweb.getNextElement($c0cf6af094336798$var$_tmpl$),
1531
- _el$2 = _el$.firstChild,
1532
- _el$3 = _el$2.nextSibling,
1533
- _el$4 = _el$3.firstChild,
1534
- _el$5 = _el$4.firstChild,
1535
- _el$6 = _el$4.nextSibling;
1536
- $52FdA$solidjsweb.insert(_el$2, $52FdA$solidjsweb.createComponent((0, $b8a8d61b3ec5f5ac$export$3f37af283f8fb843), {
1537
- aspectRatio: "var(".concat($c0cf6af094336798$export$8a2234b5b1a5ebd4, ", 1)")
1538
- }));
1539
- $52FdA$solidjsweb.insert(_el$5, $52FdA$solidjsweb.createComponent((0, $a7f7d416e6f61504$export$89c6019e4baa40b1), {
1540
- width: "20ch",
1541
- height: "1em"
1542
- }));
1543
- $52FdA$solidjsweb.insert(_el$6, $52FdA$solidjsweb.createComponent((0, $a7f7d416e6f61504$export$89c6019e4baa40b1), {
1544
- width: "5ch",
1545
- height: "1em",
1546
- "class": "price"
1547
- }));
1548
- return _el$;
1549
- })();
1550
- }
1551
- var $ce467edb5343cfcd$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div>`);
1552
- function $ce467edb5343cfcd$export$94026ee33dbabc26(props) {
1553
- return (() => {
1554
- var _el$ = $52FdA$solidjsweb.getNextElement($ce467edb5343cfcd$var$_tmpl$);
1555
- $52FdA$solidjsweb.insert(_el$, () => props.children);
1556
- $52FdA$solidjsweb.effect(_p$ => {
1557
- var _v$ = "padding-bottom:calc(calc(1 / ".concat(props.aspectRatio, ") * 100%)"),
1558
- _v$2 = "s-image-container" + (props.class ? " " + props.class : "");
1559
- _p$.e = $52FdA$solidjsweb.style(_el$, _v$, _p$.e);
1560
- _v$2 !== _p$.t && $52FdA$solidjsweb.className(_el$, _p$.t = _v$2);
1561
- return _p$;
1562
- }, {
1563
- e: undefined,
1564
- t: undefined
1565
- });
1566
- return _el$;
1567
- })();
1568
- }
1569
- let $e4e98e5080f4386e$var$browserIsBugged = false;
1570
- function $e4e98e5080f4386e$export$2972b890694ced75(callback, _ref) {
1581
+ /**
1582
+ * Get one placeholder element. It will be cloned for each placeholder for ultimate performance even when solid-js isn't rendering the placeholders.
1583
+ */
1584
+ function $e3915574cfd3466c$var$Placeholder(_ref2) {
1571
1585
  let {
1572
- timeout: timeout
1573
- } = _ref;
1574
- if ($e4e98e5080f4386e$var$browserIsBugged) timeout /= 4;
1575
- const cancel = () => {
1576
- cancelIdleCallback(idleHandle);
1577
- clearTimeout(racingTimeout);
1586
+ product_card_template_: product_card_template_,
1587
+ placeholderCacheKey_ = $e3915574cfd3466c$var$defaultCacheKey
1588
+ } = _ref2;
1589
+ const get_cloned_placeholders = function () {
1590
+ let element_to_clone = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : $e3915574cfd3466c$var$cachedPlaceholderElements[placeholderCacheKey_];
1591
+ return Array.isArray(element_to_clone) ? element_to_clone.map(el => el instanceof Node ? el.cloneNode(true) : el) : element_to_clone;
1578
1592
  };
1579
- const idleHandle = requestIdleCallback(deadline => {
1580
- cancel();
1581
- return callback(deadline);
1582
- }, {
1583
- timeout: timeout
1584
- });
1585
- const racingTimeout = setTimeout(() => {
1586
- $52FdA$depictaiutilishared.dwarn("Browser did not respect requestIdleCallback timeout");
1587
- $e4e98e5080f4386e$var$browserIsBugged = true;
1588
- cancel();
1589
- callback({
1590
- didTimeout: false,
1591
- timeRemaining() {
1592
- return 500;
1593
- }
1593
+ if ($e3915574cfd3466c$var$cachedPlaceholderElements[placeholderCacheKey_]) return get_cloned_placeholders();
1594
+ let dispose_original_copy;
1595
+ const get_unwrapped_element = $52FdA$solidjs.createRoot(dispose => {
1596
+ dispose_original_copy = dispose;
1597
+ // if product_card_template_ is async and rejects the resource will take care of throwing upwards here in the solid-js error handling system
1598
+ const [resource] = $52FdA$solidjs.createResource(() => {
1599
+ const rendering_cached_placeholder_element = $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_];
1600
+ if (rendering_cached_placeholder_element) return rendering_cached_placeholder_element;
1601
+ const return_value = product_card_template_(null, undefined);
1602
+ if (typeof return_value === "object" && typeof (return_value === null || return_value === void 0 ? void 0 : return_value.then) === "function")
1603
+ // Is Promise or promise-like object
1604
+ $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_] = return_value;
1605
+ return return_value;
1606
+ });
1607
+ return $52FdA$solidjs.createMemo(() => {
1608
+ if (resource.loading) return () => [];
1609
+ return $e82d0d417fa613e8$export$2f0cbfbb4354bb52(resource);
1594
1610
  });
1595
- }, timeout + 1000);
1596
- return cancel;
1597
- }
1598
- function $858fdcf73148519f$export$e6fffe67d4cdd848(whatToWatch) {
1599
- const [size, setSize] = $52FdA$solidjs.createSignal(0);
1600
- const resizeObserver = new ResizeObserver($52FdA$depictaiutilishared.catchify(records => {
1601
- for (let j = 0; j < records.length; j++) {
1602
- const {
1603
- width: width
1604
- } = records[j].contentRect;
1605
- if (!width) continue;
1606
- setSize(Math.ceil(width));
1607
- }
1608
- }));
1609
- // If we start observing elements before they're in the DOM Chrome (Version 117.0.5938.92 (Official Build) (arm64)) sometimes gives us a resize event with a width of 0 and then doesn't dispatch one with the actual width once it's in the DOM. So we wait until the element is in the DOM before we start observing it.
1610
- // It doesn't seem to work even when waiting for it to be in the DOM, also wait an animation frame
1611
- const disconnect = (0, $52FdA$depictaiutilishared.observer).onexists(whatToWatch, _ref => {
1612
- let {
1613
- element: element
1614
- } = _ref;
1615
- return requestAnimationFrame($52FdA$depictaiutilishared.catchify(() => resizeObserver.observe(element)));
1616
1611
  });
1617
1612
  $52FdA$solidjs.onCleanup(() => {
1618
- resizeObserver.disconnect();
1619
- disconnect();
1613
+ const rendering = $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_];
1614
+ if (rendering) {
1615
+ // If we're still rendering in our separate root, let the rendering finish or other <Placeholder> components waiting for it might get an incomplete result
1616
+ const unset_current_rendering = () => {
1617
+ dispose_original_copy();
1618
+ $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_] = undefined;
1619
+ };
1620
+ rendering === null || rendering === void 0 || rendering.then(unset_current_rendering, unset_current_rendering);
1621
+ } else
1622
+ // Otherwise, just make sure we've disposed our root
1623
+ dispose_original_copy();
1620
1624
  });
1621
- return size;
1622
- }
1623
- const $858fdcf73148519f$var$onIdleFunctionsSymbol = /*@__PURE__*/Symbol("onIdleFunctions");
1624
- const $858fdcf73148519f$export$f8945274f08a3105 = /*@__PURE__*/Symbol("listingContextAspectRatios");
1625
- const $858fdcf73148519f$export$6066eb417ed2e9f7 = /*@__PURE__*/Symbol("listingContextAspectRatios");
1626
- function $858fdcf73148519f$export$6e5611bc7e57e477(props) {
1627
- const src_options = $52FdA$solidjs.createMemo(() => {
1628
- const {
1629
- src: src,
1630
- customUrls: customUrls
1631
- } = props;
1632
- const fallback_src = (customUrls || $858fdcf73148519f$export$1d6267828870adda)(src, 400);
1633
- const srcset = $858fdcf73148519f$var$make_srcset(props.src, props.resolutions || [64, 128, 256, 300, 400, 512, 640, 768, 1024, 1280, 1536, 2048, 2560, 3072, 3584, 4096], customUrls);
1634
- // The order here *might* matter - I've seen mobile safari always start with loading the 400px version when it was reversed
1635
- return {
1636
- srcset: srcset,
1637
- src: fallback_src
1638
- };
1625
+ return $52FdA$solidjs.createMemo(() => {
1626
+ const unwrapped_array = get_unwrapped_element()();
1627
+ if (!(unwrapped_array !== null && unwrapped_array !== void 0 && unwrapped_array.length) || !unwrapped_array.every(item => item))
1628
+ // Haven't finished rendering yet in case of "async" rendering, so don't freeze the elements yet
1629
+ return;
1630
+ // placeholders have finished rendering, freeze the elements
1631
+ // here we might receive the result of a promise that has already been received, tore down and put into cached_placeholder_element, so don't overwrite that more valid result if it's already set
1632
+ $e3915574cfd3466c$var$cachedPlaceholderElements[placeholderCacheKey_] || ($e3915574cfd3466c$var$cachedPlaceholderElements[placeholderCacheKey_] = get_cloned_placeholders(unwrapped_array)); // Clone initial return value so that who gave us the elements can't mutate them, which has caused issues before with react
1633
+ $e3915574cfd3466c$var$renderingCachedPlaceholderElement[placeholderCacheKey_] = undefined;
1634
+ dispose_original_copy(); // So that this memo will never re-run and the placeholder rendering function can clean up
1635
+ return get_cloned_placeholders(); // clone, just in case. If we wouldn't, someone could modify the copy in the DOM, and it would affect the cached version
1639
1636
  });
1640
- // Work around https://github.com/solidjs/solid/issues/1828
1641
- const img = new Image(); // Need to use new Image or browser might not start loading image before it's in the DOM
1642
- const [, otherAttributes] = $52FdA$solidjs.splitProps(props, ["resolutions", "size", "src", "srcSet", "loading", "keyRatioUpdating", "customUrls" // Can't have properties ending on underscore because the property name mangling will get confused by this <-
1643
- ]);
1637
+ }
1644
1638
 
1645
- const [hasSetSize, setHasSetSize] = $52FdA$solidjs.createSignal(false);
1646
- const [hasDecoded, setHasDecoded] = $52FdA$solidjs.createSignal(false);
1647
- const productCardIndexAccessor = $b54645378dfc7280$export$e3faf4d95300054f();
1648
- const sizePX = $52FdA$solidjs.createMemo(() => "".concat(props.size(), "px")); // props.size could be a getter that expects a cleanup so get it in this memo instead of where we set img.sizes
1649
- const listingContext = $d067f3a30f047b41$export$8d0c4fdbb05a2f2e();
1650
- const isPrioritisedImage = $52FdA$solidjs.createMemo(() => (productCardIndexAccessor === null || productCardIndexAccessor === void 0 ? void 0 : productCardIndexAccessor()) < 8);
1651
- const shouldActuallyEnableLazyLoading = $52FdA$solidjs.createMemo(() => {
1652
- const {
1653
- loading: loading
1654
- } = props;
1655
- if (loading === "force-lazy") return true;
1656
- return loading === "lazy" && !isPrioritisedImage();
1657
- });
1658
- const modifiedOtherAttributes = $52FdA$solidjs.mergeProps(otherAttributes, {
1659
- get loading() {
1660
- return shouldActuallyEnableLazyLoading() ? "lazy" : undefined;
1639
+ var $6c2c739b113a8ddf$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<div>`),
1640
+ $6c2c739b113a8ddf$var$_tmpl$2 = /*#__PURE__*/$52FdA$solidjsweb.template(`<style type=text/css>`);
1641
+ function $6c2c739b113a8ddf$export$d21e32dfedac04be(props) {
1642
+ const container_class = "x" + $52FdA$solidjs.createUniqueId();
1643
+ const container_element_ = (() => {
1644
+ var _el$ = $52FdA$solidjsweb.getNextElement($6c2c739b113a8ddf$var$_tmpl$);
1645
+ $52FdA$solidjsweb.spread(_el$, $52FdA$solidjsweb.mergeProps(() => props.element_attributes, {
1646
+ "classList": {
1647
+ [container_class]: true
1648
+ }
1649
+ }), false, true);
1650
+ $52FdA$solidjsweb.insert(_el$, () => props.children);
1651
+ $52FdA$solidjsweb.runHydrationEvents();
1652
+ return _el$;
1653
+ })(); // Don't want this in the error boundary below, it should only be for the actual layouting
1654
+ return $52FdA$solidjsweb.createComponent((0, $1b3cf201cdd38687$export$b69d0d92862de18b), {
1655
+ get message_() {
1656
+ return "Failed calculating " + props.layout + " layout";
1657
+ },
1658
+ severity_: "error",
1659
+ get children() {
1660
+ return $6c2c739b113a8ddf$export$445d8d3f5f706a40(props, container_element_, false, container_class);
1661
1661
  }
1662
1662
  });
1663
- // Batch idle callbacks so that MutationObserver can batch the resulting mutations better, so we don't lose tons of CPU time to MutationObservers doing lots of things for each image
1664
- // Happened on singular, they have some weird observer (+we also have one but ours is at least 3x more efficient)
1665
- const executeWhenIdleBatched = (fn, isSizesUpdate) => {
1666
- if (typeof requestIdleCallback !== "function") return setTimeout(fn); // Old browsers don't get optimisation
1667
- if ((!isSizesUpdate || !sizeSetFastPath) && $52FdA$solidjs.untrack(isPrioritisedImage)) return fn(); // If we're one of the first 8 images, execute the callbacks immediately (improves lighthouse metrics)
1668
- // unless we're just a `sizes` update after the initial sizes setting (this optimisation makes the looks animation a lot smoother on low-cpu devices)
1669
- const existingStack = listingContext === null || listingContext === void 0 ? void 0 : listingContext[$858fdcf73148519f$var$onIdleFunctionsSymbol];
1670
- if (existingStack) return existingStack.add(fn);
1671
- const newStack = new Set([fn]);
1672
- if (listingContext) listingContext[$858fdcf73148519f$var$onIdleFunctionsSymbol] = newStack;
1673
- const processStackWhenIdle = () => $e4e98e5080f4386e$export$2972b890694ced75($52FdA$depictaiutilishared.catchify(deadline => {
1674
- const start = performance.now();
1675
- const thirdDeadlineTime = deadline.timeRemaining() / 3; // observers coming after this take up 2-3x the time so don't use all of it
1676
- for (const fn of newStack) {
1677
- newStack.delete(fn);
1678
- fn();
1679
- const timeTaken = performance.now() - start;
1680
- if ((!deadline.timeRemaining() || timeTaken > thirdDeadlineTime) && newStack.size) {
1681
- // There's still work to be done but no time, so schedule another idle callback
1682
- processStackWhenIdle();
1683
- return;
1684
- }
1685
- }
1686
- // Stack is empty
1687
- if (listingContext) delete listingContext[$858fdcf73148519f$var$onIdleFunctionsSymbol];
1688
- }), {
1689
- timeout: 15000
1690
- } // long timeout, better to not have images than to freeze the browser. But also we don't want to confuse user why no iamges are loading
1691
- );
1692
-
1693
- processStackWhenIdle();
1694
- };
1695
- let sizeSetFastPath = false;
1696
- let hasDecodedFastPath = false;
1697
- let timeoutSet = false;
1698
- let gotCleanedUp = false;
1699
- let srcJustChanged = true;
1700
- img.classList.add("s-responsive-image");
1701
- if (listingContext) {
1702
- let prevValue;
1703
- const aspectRatios = listingContext[$858fdcf73148519f$export$f8945274f08a3105] || (listingContext[$858fdcf73148519f$export$f8945274f08a3105] = new Set());
1704
- const [, setMostPrevalentAspectRatio] = listingContext[$858fdcf73148519f$export$6066eb417ed2e9f7] || (listingContext[$858fdcf73148519f$export$6066eb417ed2e9f7] = $52FdA$solidjs.createSignal());
1705
- img.addEventListener("load", $52FdA$depictaiutilishared.catchify(() => {
1706
- if (props.keyRatioUpdating) {
1707
- if (!srcJustChanged) return;
1708
- srcJustChanged = false;
1709
- }
1710
- // Save our aspect ratio whenever it changes, so that we can base the containers on the most dominant aspect ratio, used in SearchModalV2 and LookItem
1711
- const aspectRatio_ = img.naturalWidth / img.naturalHeight;
1712
- if (prevValue) aspectRatios.delete(prevValue);
1713
- const newValue = !isNaN(aspectRatio_) ? {
1714
- aspectRatio_: aspectRatio_
1715
- } : undefined;
1716
- if (newValue) aspectRatios.add(newValue);
1717
- prevValue = newValue;
1718
- // Do all calculations resulting of an update directly, for performance
1719
- const asArray = [...aspectRatios].map(_ref2 => {
1720
- let {
1721
- aspectRatio_: aspectRatio_
1722
- } = _ref2;
1723
- return aspectRatio_;
1724
- });
1725
- const mostPrevalentAspectRatio = $52FdA$depictaiutilishared.findMostFrequentItem(asArray);
1726
- setMostPrevalentAspectRatio(mostPrevalentAspectRatio);
1727
- }));
1728
- $52FdA$solidjs.onCleanup(() => prevValue && aspectRatios.delete(prevValue));
1663
+ }
1664
+ function $6c2c739b113a8ddf$export$445d8d3f5f706a40(props, container_element) {
1665
+ let insert_after_container = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1666
+ let container_class = arguments.length > 3 ? arguments[3] : undefined;
1667
+ if (!container_class) {
1668
+ // only try to add if it wasn't provided, so that we have a code path without classList when doing SSR
1669
+ container_class = $52FdA$depictaiutilishared.make_random_classname();
1670
+ container_element.classList.add(container_class);
1729
1671
  }
1730
- $52FdA$solidjs.onCleanup(() => gotCleanedUp = true);
1731
- $52FdA$solidjsweb.spread(img, $52FdA$solidjs.mergeProps(modifiedOtherAttributes), false, true);
1732
- $52FdA$solidjs.createRenderEffect(() => {
1733
- props.src;
1734
- srcJustChanged = true;
1672
+ // Copy of Layout from utilishared but using solid-js signals instead of async iterable IPNS
1673
+ const show_all_rows = $52FdA$solidjs.createMemo(() => props.rows === "all");
1674
+ const rows_or_empty_object = $52FdA$solidjs.createMemo(() => show_all_rows() ? {} : props.rows);
1675
+ const view_more_button_elements = $e82d0d417fa613e8$export$2f0cbfbb4354bb52($52FdA$solidjs.createMemo(() => rows_or_empty_object().button));
1676
+ const view_less_button_elements = $e82d0d417fa613e8$export$2f0cbfbb4354bb52($52FdA$solidjs.createMemo(() => rows_or_empty_object().view_less_button));
1677
+ const have_a_view_more_button = $52FdA$solidjs.createMemo(() => {
1678
+ const button = view_more_button_elements();
1679
+ return !(!button || Array.isArray(button) && !button.length);
1735
1680
  });
1736
- $52FdA$solidjs.createEffect(() => {
1737
- if (!props.size()) return; // wait until we have a size, run every time the size changes
1738
- if (timeoutSet) return;
1739
- const handler = $52FdA$depictaiutilishared.catchify(() => {
1740
- if (gotCleanedUp) return;
1741
- img.sizes = sizePX(); // use latest available value of props.size
1742
- if (!sizeSetFastPath) {
1743
- setHasSetSize(true);
1744
- sizeSetFastPath = true;
1745
- }
1746
- timeoutSet = false;
1747
- });
1748
- // Throttle the updating of sizes to avoid unnecessary image re-fetches during resize
1749
- // And also because we first set src after sizes has been set, wait with loading and decoding images until browser is idle
1750
- // This greatly improves performance when loading (more) products
1751
- // See https://depictaiworkspace.slack.com/archives/C05NJ0K3WRL/p1698220617663139
1752
- timeoutSet = true; // Important to set timeoutSet before the call to executeWhenIdleBatched since if this is an important image executeWhenIdleBatched will execute fn immediately
1753
- executeWhenIdleBatched(handler, true);
1681
+ const have_a_view_less_button = $52FdA$solidjs.createMemo(() => {
1682
+ const button = view_less_button_elements();
1683
+ return !(!button || Array.isArray(button) && !button.length);
1684
+ });
1685
+ const [get_styling, set_styling] = $52FdA$solidjs.createSignal();
1686
+ const selector_beginning = ".depict .".concat(container_class, ">"); // class so ppl can have id if needed
1687
+ const [get_children_count, set_children_count] = $52FdA$solidjs.createSignal(0);
1688
+ const update_children_count = () => (0, $52FdA$solidjsweb.isServer) ? 20 : set_children_count(container_element.children.length);
1689
+ const col_styling = $52FdA$solidjs.createMemo(() => $52FdA$depictaiutilishared.n_col_styling_with_dist(selector_beginning, props.grid_spacing, props.cols_at_size, props.layout, props.override_vertical_spacing));
1690
+ const default_currently_visible_signal = $52FdA$solidjs.createSignal($52FdA$solidjs.untrack(() => {
1691
+ var _rows_or_empty_object;
1692
+ return (_rows_or_empty_object = rows_or_empty_object().start_rows) !== null && _rows_or_empty_object !== void 0 ? _rows_or_empty_object : 1;
1693
+ })); // Keep this signal here, so it doesn't change when rows_or_empty_object and I think it's to be expected that the "internal default signal" stays the same
1694
+ const rows_visible_signal = $52FdA$solidjs.createMemo(() => rows_or_empty_object().currently_visible || default_currently_visible_signal);
1695
+ const get_rows_visible = $52FdA$solidjs.createMemo(() => rows_visible_signal()[0]());
1696
+ const set_rows_visible = $52FdA$solidjs.createMemo(() => rows_visible_signal()[1]);
1697
+ const view_more_button_class = "m" + $52FdA$solidjs.createUniqueId();
1698
+ const view_less_button_class = "l" + $52FdA$solidjs.createUniqueId(); // https://github.com/solidjs/solid-docs/issues/263#issuecomment-1622388079
1699
+ const view_more_button_container = $52FdA$solidjs.createMemo(() => have_a_view_more_button() && (() => {
1700
+ var _el$2 = $52FdA$solidjsweb.getNextElement($6c2c739b113a8ddf$var$_tmpl$);
1701
+ $52FdA$solidjsweb.addEventListener(_el$2, "click", $52FdA$depictaiutilishared.catchify(() => set_rows_visible()(prev => {
1702
+ var _rows_or_empty_object2;
1703
+ return prev + ((_rows_or_empty_object2 = rows_or_empty_object().rows_per_click) !== null && _rows_or_empty_object2 !== void 0 ? _rows_or_empty_object2 : 1);
1704
+ })), true);
1705
+ $52FdA$solidjsweb.className(_el$2, "load-more-container ".concat(view_more_button_class));
1706
+ $52FdA$solidjsweb.insert(_el$2, () => rows_or_empty_object().button);
1707
+ $52FdA$solidjsweb.runHydrationEvents();
1708
+ return _el$2;
1709
+ })());
1710
+ // We need to have duplicate buttons because which ones is shown depends on the number of rows visible and therefore on the viewport size and therefore on the css media queries
1711
+ const view_less_button_container = $52FdA$solidjs.createMemo(() => have_a_view_less_button() && (() => {
1712
+ var _el$3 = $52FdA$solidjsweb.getNextElement($6c2c739b113a8ddf$var$_tmpl$);
1713
+ $52FdA$solidjsweb.addEventListener(_el$3, "click", $52FdA$depictaiutilishared.catchify(() => set_rows_visible()(() => {
1714
+ var _rows_or_empty_object3;
1715
+ return (_rows_or_empty_object3 = rows_or_empty_object().start_rows) !== null && _rows_or_empty_object3 !== void 0 ? _rows_or_empty_object3 : 1;
1716
+ })), true);
1717
+ $52FdA$solidjsweb.className(_el$3, "load-less-container ".concat(view_less_button_class));
1718
+ $52FdA$solidjsweb.insert(_el$3, () => rows_or_empty_object().view_less_button);
1719
+ $52FdA$solidjsweb.runHydrationEvents();
1720
+ return _el$3;
1721
+ })());
1722
+ const [force_style_update, set_force_style_update] = $52FdA$solidjs.createSignal("");
1723
+ $52FdA$solidjs.createComputed(() => {
1724
+ // Make sure we don't have more rows visible than max_rows (this could happen by max_rows being decreased)
1725
+ const rows_visible = get_rows_visible();
1726
+ const max_rows = rows_or_empty_object().max_rows;
1727
+ if (!isNaN(max_rows) && max_rows >= 0 && rows_visible > max_rows) set_rows_visible()(max_rows);
1754
1728
  });
1755
- const dontLoadImageYet = $52FdA$solidjs.createMemo(() => !props.size() || !hasSetSize()); // Moving this condition into a memo saves us from re-setting src and srcset (expensive) if just props.size changes
1756
- $52FdA$solidjs.createEffect(() => {
1757
- if (dontLoadImageYet()) return; // If size isn't known or set, don't assign src yet since it would cause the most low res image to load
1758
- Object.assign(img, src_options());
1759
- // Add to DOM once decoded to not require/block any paints before image has completed loading and avoid showing broken image symbol
1760
- // We can do this because there has to be a container around us giving us a size
1761
- // No need to listen if we're already in the DOM
1762
- if (hasDecodedFastPath) return;
1763
- if (shouldActuallyEnableLazyLoading()) {
1764
- // For lazy loading there's no decoding to wait for as it only occurs when the image is visible
1765
- // Make sure src is set before we put the image into the DOM though so no broken image symbol is shown
1766
- setHasDecoded(true);
1767
- hasDecodedFastPath = true;
1729
+ $52FdA$solidjs.createEffect(() => set_force_style_update(" ")); // force style update after hydration due to https://discord.com/channels/722131463138705510/722167424186843267/1151544212517552168
1730
+ $52FdA$solidjs.createRenderEffect(() => {
1731
+ // Be careful to only read show_all_rows in here (ofc doesn't apply to nested effects)
1732
+ if (show_all_rows()) {
1733
+ // no view more functionality requested
1734
+ set_styling(() => col_styling);
1768
1735
  return;
1769
1736
  }
1770
- img.decode().catch(e => $52FdA$depictaiutilishared.dwarn("Failed to decode image", e, img)) // Display the image also if loading failed so webdev can debug and doesn't get "no image"
1771
- .then(async () => {
1772
- // Also wait with inserting image (i.e. paint) until browser is idle
1773
- await new Promise(r => executeWhenIdleBatched(r, false));
1774
- if (gotCleanedUp) return;
1775
- setHasDecoded(true);
1776
- hasDecodedFastPath = true;
1777
- });
1737
+ update_children_count();
1738
+ if (!(0, $52FdA$solidjsweb.isServer)) {
1739
+ const mutation_observer = new MutationObserver($52FdA$depictaiutilishared.catchify(update_children_count));
1740
+ mutation_observer.observe(container_element, {
1741
+ childList: true
1742
+ });
1743
+ $52FdA$solidjs.onCleanup(() => mutation_observer.disconnect());
1744
+ }
1745
+ set_styling(
1746
+ // this is needed because solid will think that the memo-accessor is a setter function otherwise
1747
+ () => $52FdA$solidjs.createMemo(() => {
1748
+ const {
1749
+ rows_per_click: rows_per_click,
1750
+ max_rows = -1,
1751
+ start_rows: start_rows
1752
+ } = rows_or_empty_object();
1753
+ const rows_visible = get_rows_visible();
1754
+ const children_count = get_children_count();
1755
+ return force_style_update() + col_styling() + props.cols_at_size.map(options => {
1756
+ const [recs_per_row, min, max] = options;
1757
+ let should_hide_view_more_button;
1758
+ let visible_recs;
1759
+ if (props.disable_partial_rows) {
1760
+ visible_recs = $52FdA$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible, children_count, options);
1761
+ const visible_recs_next_show_more = $52FdA$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible + (rows_per_click || 0),
1762
+ // Should this really be zero when we default rows_per_click to 1?
1763
+ children_count, options);
1764
+ should_hide_view_more_button = visible_recs === visible_recs_next_show_more;
1765
+ } else {
1766
+ visible_recs = $52FdA$depictaiutilishared.layout_get_total_rec_amount_for_row(rows_visible, options);
1767
+ should_hide_view_more_button = visible_recs >= children_count;
1768
+ }
1769
+ const should_hide_button_final = should_hide_view_more_button || max_rows !== -1 && rows_visible >= max_rows;
1770
+ // I don't really understand the logic for when the view more button gets hidden so IDK if below is correct, but it works how it should for now
1771
+ const should_hide_view_less_button = !should_hide_view_more_button || start_rows == undefined || rows_visible <= start_rows || children_count <= recs_per_row * start_rows;
1772
+ return "".concat($52FdA$depictaiutilishared.layout_media_query_header(min, max), "{").concat(selector_beginning, ":nth-child(n+").concat(visible_recs + 1, "){display:none}").concat(props.layout == "slider" ? "".concat(selector_beginning, ":nth-child(n+").concat(visible_recs, "){margin-right:0}") : "").concat(should_hide_button_final ? ".depict .".concat(view_more_button_class, "{display:none!important}") : "").concat(should_hide_view_less_button ? ".depict .".concat(view_less_button_class, "{display:none!important}") : "", "}");
1773
+ }).join("");
1774
+ }));
1775
+ });
1776
+ const style_element = (() => {
1777
+ var _el$4 = $52FdA$solidjsweb.getNextElement($6c2c739b113a8ddf$var$_tmpl$2);
1778
+ $52FdA$solidjsweb.insert(_el$4, get_styling);
1779
+ return _el$4;
1780
+ })(); // need to create this after set_styling has been called or else there will be no styling in the SSR'd output
1781
+ if (insert_after_container) container_element.after(style_element);
1782
+ return [container_element, $52FdA$solidjsweb.memo(view_more_button_container), $52FdA$solidjsweb.memo(view_less_button_container), style_element];
1783
+ }
1784
+ $52FdA$solidjsweb.delegateEvents(["click"]);
1785
+ var $236a257ee52e5414$var$_tmpl$ = /*#__PURE__*/$52FdA$solidjsweb.template(`<h2 class=recs-title>`);
1786
+ function $236a257ee52e5414$export$d41d19e89346fa2(_ref) {
1787
+ let {
1788
+ recommendations_resource_: recommendations_resource_,
1789
+ product_card_template_: product_card_template_,
1790
+ layout_options_: layout_options_,
1791
+ title_: title_,
1792
+ NoResultsFallback_: NoResultsFallback_,
1793
+ placeholderCacheKey_: placeholderCacheKey_
1794
+ } = _ref;
1795
+ const is_showing_something = $52FdA$solidjs.createMemo(() => {
1796
+ var _recommendations_reso;
1797
+ return recommendations_resource_.loading || ((_recommendations_reso = recommendations_resource_()) === null || _recommendations_reso === void 0 ? void 0 : _recommendations_reso.length);
1778
1798
  });
1799
+ const title = $52FdA$solidjs.createMemo(() => title_ === null || title_ === void 0 ? void 0 : title_()); // In case getter/accessor creates elements, don't create them twice
1800
+ const num_placeholders_ = () => 20;
1801
+ const slider = [$52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
1802
+ get when() {
1803
+ return title();
1804
+ },
1805
+ get children() {
1806
+ var _el$ = $52FdA$solidjsweb.getNextElement($236a257ee52e5414$var$_tmpl$);
1807
+ $52FdA$solidjsweb.insert(_el$, title);
1808
+ return _el$;
1809
+ }
1810
+ }), $52FdA$solidjsweb.createComponent((0, $ad8ec7729fffeb9c$export$6649caad96ef8870), {
1811
+ arrow_height_: 25,
1812
+ arrow_width_: 12.5,
1813
+ disable_fading_: true,
1814
+ slider_ref_: slider => {
1815
+ const {
1816
+ insert_here: insert_here,
1817
+ container: container
1818
+ } = slider;
1819
+ const Layout = props => $6c2c739b113a8ddf$export$445d8d3f5f706a40(props, insert_here, true);
1820
+ // Do like this, so we don't have to call mergeProps ourselves
1821
+ $52FdA$solidjsweb.createComponent(Layout, $52FdA$solidjsweb.mergeProps({
1822
+ rows: "all",
1823
+ layout: "slider"
1824
+ }, layout_options_));
1825
+ $52FdA$depictaiutilishared.slider_fractional_factory(0, 0.75).constructor_plugin.call(slider, {}); // enable fractional scrolling
1826
+ insert_here.before($8edd3cf30d1fd8b4$export$a2cc176055f8f08());
1827
+ container.classList.add("products");
1828
+ },
1829
+ get children() {
1830
+ return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Suspense), {
1831
+ get fallback() {
1832
+ return $e3915574cfd3466c$export$f33414a4df0afd3f({
1833
+ num_placeholders_: num_placeholders_,
1834
+ product_card_template_: product_card_template_,
1835
+ placeholderCacheKey_: placeholderCacheKey_
1836
+ });
1837
+ },
1838
+ get children() {
1839
+ return (() => {
1840
+ // IIFE to make sure we access both the recommendations_resource and the resources containing the product card rendering results themselves within the Suspense boundary
1841
+ const displays_by_key_ = $76012c4468a53d1f$export$7f8bd308237ab5a5($52FdA$solidjs.createMemo(() => recommendations_resource_() || []));
1842
+ const {
1843
+ renderedDisplays_: renderedDisplays_
1844
+ } = $a52942afacbced93$export$4a14175d33d81a96({
1845
+ displays_by_key_: displays_by_key_,
1846
+ product_card_template_: product_card_template_
1847
+ });
1848
+ return renderedDisplays_;
1849
+ })();
1850
+ }
1851
+ });
1852
+ }
1853
+ })];
1779
1854
  return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjs.Show), {
1780
1855
  get when() {
1781
- return hasDecoded();
1856
+ return is_showing_something();
1782
1857
  },
1783
- children: img
1858
+ get fallback() {
1859
+ return NoResultsFallback_ === null || NoResultsFallback_ === void 0 ? void 0 : NoResultsFallback_();
1860
+ },
1861
+ children: slider
1784
1862
  });
1785
1863
  }
1786
- function $858fdcf73148519f$var$make_srcset(url, resolutions, customGenerateImageUrl_) {
1787
- return resolutions.map(width => "".concat((customGenerateImageUrl_ || $858fdcf73148519f$export$1d6267828870adda)(url, width), " ").concat(width, "w")).join(", ");
1788
- }
1789
- function $858fdcf73148519f$export$1d6267828870adda(url, width) {
1790
- // Even just creating one `URL` object per image src and then setting the search parameter is quite slow (0.25ms to set the width param)
1791
- // We're making the assumptions that the url has already at least one query parameter and that the image resizing service will choose the last one out of a duplicate width parameter (shopify's does)
1792
- // That way we can just to string concatenation which is insanely fast
1793
- return url + "&width=" + encodeURIComponent(width);
1794
- }
1795
- const $28535bb7671c63d1$var$backupSizeSignal = /*@__PURE__*/$52FdA$solidjs.createSignal();
1796
- const $28535bb7671c63d1$export$d7b7ab832c20e2f4 = /*@__PURE__*/Symbol("ShopifyContainedImage");
1797
- function $28535bb7671c63d1$export$e4b984597b71e989(props) {
1798
- const context = $d067f3a30f047b41$export$8d0c4fdbb05a2f2e();
1799
- if (context && !context[$28535bb7671c63d1$export$d7b7ab832c20e2f4])
1800
- // create a signal that's the same for all items in this listing
1801
- context[$28535bb7671c63d1$export$d7b7ab832c20e2f4] = $52FdA$solidjs.createSignal();
1802
- const [currentImageSize, setCurrentImageSize] = (context === null || context === void 0 ? void 0 : context[$28535bb7671c63d1$export$d7b7ab832c20e2f4]) || $28535bb7671c63d1$var$backupSizeSignal; // use global fallback signal (might lead to blurry images) if no context is available
1803
- const [mostPrevalentAspectRatio] = context ? context[(0, $858fdcf73148519f$export$6066eb417ed2e9f7)] || (context[(0, $858fdcf73148519f$export$6066eb417ed2e9f7)] = $52FdA$solidjs.createSignal()) : [];
1804
- const container = $ce467edb5343cfcd$export$94026ee33dbabc26({
1805
- // Write getters manually instead of using JSX, so we can do more complex logic in the aspectRatio getter without increasing bundle size
1806
- get class() {
1807
- return props.class;
1808
- },
1809
- get aspectRatio() {
1810
- if (props.autoAdjustAspectRatio) {
1811
- const targetRatio = mostPrevalentAspectRatio === null || mostPrevalentAspectRatio === void 0 ? void 0 : mostPrevalentAspectRatio();
1812
- if (targetRatio != undefined) return "var(".concat((0, $c0cf6af094336798$export$8a2234b5b1a5ebd4), ", ").concat(targetRatio, ")");
1864
+ function $d05611ff6b8c8357$export$23fca46f3143581f(component, error_message) {
1865
+ const component_in_error_boundary = do_with_elements => {
1866
+ const error_boundary_wrapped = $1b3cf201cdd38687$export$b69d0d92862de18b({
1867
+ severity_: "error",
1868
+ message_: error_message,
1869
+ get children() {
1870
+ const elements = component();
1871
+ do_with_elements === null || do_with_elements === void 0 || do_with_elements(elements);
1872
+ return elements;
1813
1873
  }
1814
- return props.aspectRatio;
1815
- }
1816
- });
1874
+ });
1875
+ // This might return an accessor, in that case we need to "unwrap" it since our SDK consumers expect HTML elements or arrays thereof
1876
+ if (typeof error_boundary_wrapped === "function")
1877
+ // @ts-ignore
1878
+ return error_boundary_wrapped();
1879
+ // On the server it returns a string, so we just return that
1880
+ return error_boundary_wrapped;
1881
+ };
1817
1882
  const owner = $52FdA$solidjs.getOwner();
1818
- let createdSizeAccessor = false;
1819
- let wasCleanedUp = false;
1820
- $52FdA$solidjs.createEffect(() => {
1821
- if (currentImageSize() || wasCleanedUp) return; // We get into the effect when onCleanup is called if we don't have wasCleanedUp
1822
- // ensure we always have a size accessor
1823
- // what this whole thing does is set the sizes attribute to the actual size of one of the existing image containers, therefore the value doesn't have to manually be specified
1824
- createdSizeAccessor = true;
1825
- setCurrentImageSize(() => $52FdA$solidjs.runWithOwner(owner, () => $858fdcf73148519f$export$e6fffe67d4cdd848(container)));
1826
- });
1827
- $52FdA$solidjs.onCleanup(() => {
1828
- wasCleanedUp = true; // important to set this before the function call below and always, so the dead effects don't create dead size accessors
1829
- if (!createdSizeAccessor) return;
1830
- $52FdA$depictaiutilishared.queueMacroTask(() => setCurrentImageSize()); // unset the size accessor next event loop iteration, so that all onCleanup's have time to run, since the effects run more aggressively and can create a size accessor with a cleaned up owner otherwise
1831
- });
1832
-
1833
- $52FdA$solidjsweb.insert(container, $52FdA$solidjsweb.createComponent((0, $858fdcf73148519f$export$6e5611bc7e57e477), $52FdA$solidjsweb.mergeProps({
1834
- get size() {
1835
- return $52FdA$solidjs.createMemo(() => {
1836
- var _currentImageSize;
1837
- return ((_currentImageSize = currentImageSize()) === null || _currentImageSize === void 0 ? void 0 : _currentImageSize()) || 0;
1883
+ if (owner == null) return $52FdA$solidjs.createRoot(dispose => {
1884
+ // if we're not already run in a root, create a root and automatically dispose it when the first returned element is removed from the DOM
1885
+ return component_in_error_boundary(elements => {
1886
+ const have_multiple = Array.isArray(elements);
1887
+ if (have_multiple ? !(elements !== null && elements !== void 0 && elements.length) : !elements) return;
1888
+ (0, $52FdA$depictaiutilishared.observer).onremoved(have_multiple ? elements[0] : elements, _ref => {
1889
+ let {
1890
+ element: element
1891
+ } = _ref;
1892
+ if (document.documentElement.contains(element)) return; // If element has instantly been re-inserted, don't dispose
1893
+ // See https://depictaiworkspace.slack.com/archives/C050GHEPBTR/p1695809102791259?thread_ts=1695106805.459729&cid=C050GHEPBTR
1894
+ dispose();
1838
1895
  });
1839
- },
1840
- get src() {
1841
- return props.src;
1842
- }
1843
- }, () => props.imgProps, {
1844
- get style() {
1845
- var _props$imgProps;
1846
- return (_props$imgProps = props.imgProps) === null || _props$imgProps === void 0 ? void 0 : _props$imgProps.style;
1847
- }
1848
- })));
1849
- return container;
1850
- }
1851
- function $f3db423dc84bc35d$export$9d4a4b669b1929ab(props) {
1852
- return $52FdA$solidjsweb.createComponent((0, $28535bb7671c63d1$export$e4b984597b71e989), $52FdA$solidjsweb.mergeProps(props, {
1853
- get imgProps() {
1854
- return {
1855
- ...props.imgProps,
1856
- customUrls: (url, width // Apparently don't have to encode url for CF's service
1857
- ) => {
1858
- var _url$startsWith;
1859
- if (url !== null && url !== void 0 && (_url$startsWith = url.startsWith) !== null && _url$startsWith !== void 0 && _url$startsWith.call(url, "https://cdn.shopify.com"))
1860
- // The shopify image resizing CDN blocks Cloudflare's image resizer. It's possible that we can't detect shopify image URLs sometimes because they go to the merchant's domain,
1861
- // but it seems like the URLs returned by the Depict API always goes to the cdn.shopify.com version of an image, so this simple workaround works.
1862
- return $858fdcf73148519f$export$1d6267828870adda(url, width);
1863
- // Use cloudflare image resizer instead of img.depict.ai because it's a lot faster (and also auto-chooses other formats if webp is not supported)
1864
- return "https://app.depict.ai/cdn-cgi/image/width=".concat(width, ",format=auto/").concat(url);
1865
- }
1866
- };
1867
- }
1868
- }));
1896
+ });
1897
+ });else
1898
+ // we're already in a root so cleanups are handled
1899
+ return component_in_error_boundary();
1869
1900
  }
1870
1901
  function $f38f2e64ebe2da86$export$a71e92cfbb498adc(props) {
1871
1902
  return $52FdA$solidjs.createMemo(() => {
@@ -15946,7 +15977,7 @@ function $c19709057a32b2e7$export$780a853d15174484(_ref) {
15946
15977
  return $52FdA$solidjsweb.createComponent((0, $52FdA$solidjsweb.Dynamic), $52FdA$solidjsweb.mergeProps({
15947
15978
  component: link ? "a" : "div",
15948
15979
  "class": "d-standard-content-wrapper",
15949
- ref: el => setWrapperSize(() => $858fdcf73148519f$export$e6fffe67d4cdd848(el)),
15980
+ ref: el => setWrapperSize(() => $054b1113e4897051$export$54c6d6ff54e72743(el)),
15950
15981
  get onClick() {
15951
15982
  return $52FdA$depictaiutilisharedlatest.catchify(ev => link && router_.navigate_.go_to_({
15952
15983
  new_url_: link,
@@ -15958,12 +15989,14 @@ function $c19709057a32b2e7$export$780a853d15174484(_ref) {
15958
15989
  href: link
15959
15990
  }, {
15960
15991
  get children() {
15961
- return $52FdA$solidjsweb.createComponent((0, $858fdcf73148519f$export$6e5611bc7e57e477), {
15962
- get size() {
15963
- return $52FdA$solidjs.createMemo(() => {
15964
- var _wrapperSize;
15965
- return ((_wrapperSize = wrapperSize()) === null || _wrapperSize === void 0 ? void 0 : _wrapperSize()) || 0;
15966
- });
15992
+ return $52FdA$solidjsweb.createComponent((0, $f3db423dc84bc35d$export$140423fa4bfb6d63), {
15993
+ size: () => {
15994
+ var _wrapperSize, _wrapperSize$;
15995
+ return ((_wrapperSize = wrapperSize()) === null || _wrapperSize === void 0 ? void 0 : (_wrapperSize$ = _wrapperSize[0]) === null || _wrapperSize$ === void 0 ? void 0 : _wrapperSize$.call(_wrapperSize)) || 0;
15996
+ },
15997
+ sizeHeight: () => {
15998
+ var _wrapperSize2, _wrapperSize2$;
15999
+ return ((_wrapperSize2 = wrapperSize()) === null || _wrapperSize2 === void 0 ? void 0 : (_wrapperSize2$ = _wrapperSize2[1]) === null || _wrapperSize2$ === void 0 ? void 0 : _wrapperSize2$.call(_wrapperSize2)) || 0;
15967
16000
  },
15968
16001
  src: mediaUrl,
15969
16002
  "class": "d-standard-content"