@depict-ai/ui 2.1.22 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  var $5vyXB$depictaiutilishared = require("@depict-ai/utilishared/latest");
2
2
  var $5vyXB$solidjsweb = require("solid-js/web");
3
3
  var $5vyXB$solidjs = require("solid-js");
4
+ var $5vyXB$depictaiutilisharedlatest = require("@depict-ai/utilishared/latest");
4
5
  var $5vyXB$solidjsstore = require("solid-js/store");
5
6
  require("../../multi_import_deduplicator.cjs").register_es_version("ui", "latest");
6
7
  function $parcel$export(e, n, v, s) {
@@ -11,6 +12,10 @@ function $parcel$export(e, n, v, s) {
11
12
  configurable: true
12
13
  });
13
14
  }
15
+ $parcel$export(module.exports, "Tab", () => $8c38828ae2321937$export$3e41faf802a29e71);
16
+ $parcel$export(module.exports, "Tabs", () => $8c38828ae2321937$export$b2539bed5023c21c);
17
+ $parcel$export(module.exports, "ShopTheLookButton", () => $a5f3eaa1a24bbc1e$export$d4973c31938cbfd1);
18
+ $parcel$export(module.exports, "history_dot_state_to_state", () => $6e22b5314fb52f4c$export$e183a13865960371);
14
19
  $parcel$export(module.exports, "strip_encoded_filter_and_sort", () => $1ab22f2cd39b3061$export$916e6850778505f6);
15
20
  $parcel$export(module.exports, "encode_filters", () => $1ab22f2cd39b3061$export$58aa3f171519b6d7);
16
21
  $parcel$export(module.exports, "decode_filters", () => $1ab22f2cd39b3061$export$f934fa24c3a86811);
@@ -37,12 +42,12 @@ $parcel$export(module.exports, "SolidLayout", () => $f48d0fbb00835aaa$export$d21
37
42
  $parcel$export(module.exports, "general_modal_abstraction", () => $9abb0a35d4b60ed3$export$79b1565500412d9b);
38
43
  $parcel$export(module.exports, "CrossIcon", () => $c77c68e559a1506c$export$3b621d86b1566b2);
39
44
  $parcel$export(module.exports, "GenericSliderArrowButton", () => $0f313083912e447a$export$8be2714ec7f169ee);
40
- $parcel$export(module.exports, "fetchDepictRecommendations", () => $bc91d938b8c601b4$export$58e808b1db15d3bc);
45
+ $parcel$export(module.exports, "fetchDepictRecommendations", () => $bd429c994399dd82$export$58e808b1db15d3bc);
41
46
  $parcel$export(module.exports, "QuickLinks", () => $48567ac5b39bac56$export$de035477d6fef996);
42
47
  $parcel$export(module.exports, "BreadCrumbs", () => $48567ac5b39bac56$export$5b7c3ce0ebe51f86);
43
48
  $parcel$export(module.exports, "CategoryTitle", () => $0b23bfd073d9a4e8$export$b91cec6bdc6b32a1);
44
49
  $parcel$export(module.exports, "embedded_num_products", () => $85b747260aa175c9$export$824dde41348efed1);
45
- $parcel$export(module.exports, "get_categories", () => $63b10c9f461e0ef6$export$643598a327b5833e);
50
+ $parcel$export(module.exports, "get_listings", () => $6382a1b83da39674$export$c1a6b039e689a58e);
46
51
  $parcel$export(module.exports, "DepictCategory", () => $48567ac5b39bac56$export$f34314aa9505732e);
47
52
  $parcel$export(module.exports, "CategoryPage", () => $48567ac5b39bac56$export$e2bf8ce7779e827e);
48
53
  $parcel$export(module.exports, "DepictSearch", () => $2c61e4cd8229c49a$export$ac6237957a15b3f0);
@@ -72,449 +77,1010 @@ $parcel$export(module.exports, "defaultColsAtSize", () => $a3280f0aad997933$expo
72
77
  $parcel$export(module.exports, "defaultCategoryTitlePlugin", () => $a3280f0aad997933$export$7bf543b9d9be2c22);
73
78
  $parcel$export(module.exports, "version", () => $b757f75811f3261f$export$83d89fbfd8236492);
74
79
  /*! Depict.ai search and product listing SDK */
75
- const $b757f75811f3261f$export$83d89fbfd8236492 = "2.1.22";
76
- const $1ab22f2cd39b3061$var$fallback_operator = "in";
77
- const $1ab22f2cd39b3061$var$fallback_token = "";
78
- const $1ab22f2cd39b3061$var$legacy_filter_prefix = "filter_";
79
- const $1ab22f2cd39b3061$var$operator_map = {
80
- "eq": "≡",
81
- "neq": "≠",
82
- "in": "∈",
83
- "nin": "∉",
84
- "leq": "≤",
85
- "geq": "≥",
86
- "inrange": "\uD83D\uDD22"
87
- };
88
- const $1ab22f2cd39b3061$var$ascending_token = "\uD83D\uDCC8";
89
- const $1ab22f2cd39b3061$var$descending_token = "\uD83D\uDCC9";
90
- const $1ab22f2cd39b3061$var$range_delimiter = "-";
91
- const $1ab22f2cd39b3061$var$string_item_delimiter = "‚"; // This is not a comma but a comma-like character that browsers will render in the URL bar.
92
- const $1ab22f2cd39b3061$var$array_item_delimiter = "‣"; // FIXME: decide on a character. Could theoretically be a double string delimiter.
93
- const $1ab22f2cd39b3061$var$empty_item_replacement = "0️⃣";
94
- const $1ab22f2cd39b3061$var$op_to_token = op => {
95
- if (op === $1ab22f2cd39b3061$var$fallback_operator) return $1ab22f2cd39b3061$var$fallback_token;
96
- return $1ab22f2cd39b3061$var$operator_map[op];
97
- };
98
- /**
99
- * Checks if a given array of filter data can be neatly serialized into an URL query parameter, or if it should fall back to JSON+base64.
100
- * The requirements are either an array of strings, containing no reserved characters, or an array of arrays of strings, containing no reserved characters.
101
- * No deep or mixed nesting levels are supported.
102
- */
103
- function $1ab22f2cd39b3061$var$array_is_serializable(array, is_root = true) {
104
- if (array.every(item => Array.isArray(item))) {
105
- if (!is_root)
106
- // Deeply nested arrays are not supported, but also don't exist as filters (yet)
107
- return false;
108
- return array.every(item => $1ab22f2cd39b3061$var$array_is_serializable(item, false));
109
- }
110
- if (array.some(item => typeof item !== "string"))
111
- // Numbers are not supported, since 1 and "1" would encode to the same thing
112
- return false;
113
- // Encoding reserved characters is not supported
114
- return !array.some(item => item.includes($1ab22f2cd39b3061$var$array_item_delimiter) || item.includes($1ab22f2cd39b3061$var$string_item_delimiter) || item === $1ab22f2cd39b3061$var$empty_item_replacement);
115
- }
116
- /**
117
- * Human readable string[] or string[][] serialization for URLs.
118
- * @param array
119
- * @returns
120
- */
121
- function $1ab22f2cd39b3061$var$encode_array(array) {
122
- const is_nested = array.every(item => Array.isArray(item));
123
- if (is_nested) return array.map($1ab22f2cd39b3061$var$encode_array).join($1ab22f2cd39b3061$var$array_item_delimiter) + $1ab22f2cd39b3061$var$array_item_delimiter; // Nested arrays require a suffix to close nesting levels
124
- return array.map(item => item === "" ? $1ab22f2cd39b3061$var$empty_item_replacement : item).join($1ab22f2cd39b3061$var$string_item_delimiter);
80
+ const $b757f75811f3261f$export$83d89fbfd8236492 = "3.0.0";
81
+ const $0f313083912e447a$var$_tmpl$ = ["<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"></path></svg>'];
82
+ function $0f313083912e447a$export$8be2714ec7f169ee(props = {}) {
83
+ return $5vyXB$solidjsweb.ssr($0f313083912e447a$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.ssrAttribute("width", $5vyXB$solidjsweb.escape(props.width_, true) ?? 14, false) + $5vyXB$solidjsweb.ssrAttribute("height", $5vyXB$solidjsweb.escape(props.height_, true) ?? 26, false));
125
84
  }
126
- function $1ab22f2cd39b3061$var$decode_array(encoded_array) {
127
- const is_nested = encoded_array.includes($1ab22f2cd39b3061$var$array_item_delimiter);
128
- if (is_nested) return encoded_array.split($1ab22f2cd39b3061$var$array_item_delimiter).filter(s => s !== "") // Remove empty segments, caused by trailing delimiter
129
- .map($1ab22f2cd39b3061$var$decode_array);
130
- return encoded_array.split($1ab22f2cd39b3061$var$string_item_delimiter).filter(s => s !== "") // Remove empty segments, caused by trailing delimiter in the single item special case
131
- .map(item => item === $1ab22f2cd39b3061$var$empty_item_replacement ? "" : item);
85
+ const $a0e53f99354809d9$var$_tmpl$ = ["<div", ">", "</div>"];
86
+ function $a0e53f99354809d9$export$6649caad96ef8870({
87
+ children: children,
88
+ slider_ref_: slider_ref_,
89
+ faded_opacity_ = 0.7,
90
+ mutation_plugins_ = [],
91
+ disable_fading_: disable_fading_,
92
+ arrow_width_: arrow_width_,
93
+ arrow_height_: arrow_height_
94
+ }) {
95
+ const slider = new (0, $5vyXB$depictaiutilishared.Amazing_Slider)({
96
+ button_contents: {
97
+ left: [$5vyXB$solidjsweb.ssr($a0e53f99354809d9$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $0f313083912e447a$export$8be2714ec7f169ee), {
98
+ height_: arrow_height_,
99
+ width_: arrow_width_
100
+ })))],
101
+ right: [$5vyXB$solidjsweb.ssr($a0e53f99354809d9$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $0f313083912e447a$export$8be2714ec7f169ee), {
102
+ height_: arrow_height_,
103
+ width_: arrow_width_
104
+ })))]
105
+ },
106
+ constructor_plugins: [$5vyXB$depictaiutilishared.slider_snap_css().constructor_plugin],
107
+ mutation_plugins: [...(disable_fading_ ? [] : [$5vyXB$depictaiutilishared.slider_fading_factory({
108
+ threshold_: 0.96,
109
+ faded_opacity_: faded_opacity_
110
+ }).mutation_plugin_]), ...mutation_plugins_]
111
+ });
112
+ $5vyXB$solidjsweb.insert(slider.insert_here, children);
113
+ $5vyXB$solidjs.onCleanup(() => slider.observer.disconnect());
114
+ slider_ref_?.(slider);
115
+ return slider.container;
132
116
  }
133
- function $1ab22f2cd39b3061$var$encode_filter_data(op, data) {
134
- if (data === "true")
135
- // boolean encoding
136
- return "1";
137
- if (data === "false")
138
- // boolean encoding
139
- return "0";
140
- const data_is_array = Array.isArray(data);
141
- if (op === "inrange" && data_is_array && data.every(item => typeof item === "number"))
142
- // numeric range filter encoding
143
- return data.join($1ab22f2cd39b3061$var$range_delimiter);
144
- if (data_is_array && $1ab22f2cd39b3061$var$array_is_serializable(data)) {
145
- const encoded_data = $1ab22f2cd39b3061$var$encode_array(data);
146
- if (!encoded_data.includes($1ab22f2cd39b3061$var$array_item_delimiter) && !encoded_data.includes($1ab22f2cd39b3061$var$string_item_delimiter))
147
- // A string[] with only one item will encode without delimiters, which is indistinguishable from a plain string during decoding
148
- // In that case we add a delimiter suffix at the end
149
- return encoded_data + $1ab22f2cd39b3061$var$string_item_delimiter;
150
- return encoded_data;
151
- }
152
- // Fallback encoding
153
- return $5vyXB$depictaiutilishared.base64_encode_unicode(JSON.stringify(data));
117
+ const $8c38828ae2321937$var$_tmpl$ = ["<section", ' aria-live="polite" role="region" class="tabs-body">', "</section>"],
118
+ $8c38828ae2321937$var$_tmpl$2 = ["<nav", ' role="tablist" class="tabs-bar">', "</nav>"],
119
+ $8c38828ae2321937$var$_tmpl$3 = ["<article", ' role="tabpanel" class="', '" style="', '">', "</article>"];
120
+ const $8c38828ae2321937$var$TabsContext = /*@__PURE__*/$5vyXB$solidjs.createContext();
121
+ const $8c38828ae2321937$var$useTabs = () => $5vyXB$solidjs.useContext($8c38828ae2321937$var$TabsContext);
122
+ function $8c38828ae2321937$export$b2539bed5023c21c(props) {
123
+ return $5vyXB$solidjsweb.createComponent($8c38828ae2321937$var$TabsContext.Provider, {
124
+ value: new (0, $5vyXB$depictaiutilisharedlatest.ListenableSet)(),
125
+ get children() {
126
+ return $5vyXB$solidjsweb.createComponent($8c38828ae2321937$var$ActualTabs, $5vyXB$solidjsweb.mergeProps(props, {
127
+ get children() {
128
+ return props.children;
129
+ }
130
+ }));
131
+ }
132
+ });
154
133
  }
155
- function $1ab22f2cd39b3061$var$decode_filter_data(op, encoded_data) {
156
- if (encoded_data === "1") return "true";
157
- if (encoded_data === "0") return "false";
158
- if (op === "inrange" && encoded_data.includes($1ab22f2cd39b3061$var$range_delimiter)) return encoded_data.split($1ab22f2cd39b3061$var$range_delimiter).map(x => parseFloat(x));
159
- if (encoded_data.includes($1ab22f2cd39b3061$var$string_item_delimiter) || encoded_data.includes($1ab22f2cd39b3061$var$array_item_delimiter)) return $1ab22f2cd39b3061$var$decode_array(encoded_data);
160
- try {
161
- return JSON.parse($5vyXB$depictaiutilishared.base64_decode_unicode(encoded_data));
162
- } catch (e) {
163
- $5vyXB$depictaiutilishared.dlog("Failed to fallback parse filter data", op, encoded_data, e);
134
+ function $8c38828ae2321937$var$ActualTabs(props) {
135
+ const [tabsReactive, setTabsReactive] = $5vyXB$solidjs.createSignal([]); // Can't have a store since reconciling with a store would call the children getters, and we could get x-tle rendered components
136
+ const [currentlySelected, setCurrentlySelected] = $5vyXB$solidjs.createSignal();
137
+ const [tabsVisitedOnce, setTabsVisitedOnce] = $5vyXB$solidjs.createSignal(new Set(), {
138
+ equals: false
139
+ });
140
+ const isSelected = $5vyXB$solidjs.createSelector(currentlySelected);
141
+ const owner = $5vyXB$solidjs.getOwner();
142
+ const updateTabsSignal = $5vyXB$depictaiutilisharedlatest.catchify(() => $5vyXB$solidjs.runWithOwner(owner, () => setTabsReactive([...ourTabsSet])));
143
+ const ourTabsSet = $8c38828ae2321937$var$useTabs();
144
+ const location = $5vyXB$depictaiutilisharedlatest.use_href_accessor();
145
+ const linkWithChangedHash = hash => {
146
+ const u_o = new URL(location());
147
+ u_o.hash = hash;
148
+ return u_o.href;
149
+ };
150
+ const headerItems = $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Index), {
151
+ get each() {
152
+ return tabsReactive();
153
+ },
154
+ children: item => {
155
+ const weSelected = $5vyXB$solidjs.createMemo(() => isSelected(item().id));
156
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjsweb.Dynamic), $5vyXB$solidjsweb.mergeProps({
157
+ get component() {
158
+ return props.AnchorComponent;
159
+ },
160
+ get ["aria-controls"]() {
161
+ return item().id;
162
+ },
163
+ role: "tab",
164
+ get classList() {
165
+ return {
166
+ selected: weSelected()
167
+ };
168
+ }
169
+ }, () => weSelected() ? {} : {
170
+ href: linkWithChangedHash(item().id)
171
+ }, {
172
+ get children() {
173
+ return item().label;
174
+ }
175
+ }));
176
+ }
177
+ });
178
+ // Enable nice pattern of doing <Tabs><Tab>Content</Tab><Tab>More content</Tab></Tabs>
179
+ $5vyXB$solidjs.children(() => props.children); // "Render" children (.children is a getter), this means that we now can connect the children with the parent
180
+ for (const event of ["add", "delete"]) {
181
+ ourTabsSet.addEventListener(event, updateTabsSignal);
182
+ $5vyXB$solidjs.onCleanup(() => ourTabsSet.removeEventListener(event, updateTabsSignal));
164
183
  }
165
- return null;
166
- }
167
- function $1ab22f2cd39b3061$export$58aa3f171519b6d7(filters, search_params, filter_query_param_prefix) {
168
- for (const filter of filters) {
184
+ updateTabsSignal();
185
+ $5vyXB$solidjs.createEffect(() => {
169
186
  const {
170
- field: field,
171
- op: op,
172
- data: data
173
- } = filter;
174
- const encoded_data = $1ab22f2cd39b3061$var$encode_filter_data(op, data);
175
- search_params.set(filter_query_param_prefix + field + $1ab22f2cd39b3061$var$op_to_token(op), encoded_data);
176
- }
177
- }
178
- function $1ab22f2cd39b3061$export$f934fa24c3a86811(search_params, filter_query_param_prefix) {
179
- const found_filters = [];
180
- for (const key of search_params.keys()) {
181
- // Allow for backwards compatibility with the old filter query param prefix
182
- let chosen_prefix = filter_query_param_prefix;
183
- if (!key.startsWith(chosen_prefix)) {
184
- chosen_prefix = $1ab22f2cd39b3061$var$legacy_filter_prefix;
185
- if (!key.startsWith(chosen_prefix)) continue;
187
+ hash: hash
188
+ } = new URL(location());
189
+ const id = hash.slice(1);
190
+ if (tabsReactive().some(item => item.id === id)) {
191
+ setCurrentlySelected(id);
192
+ return;
186
193
  }
187
- const encoded_data = search_params.get(key);
188
- if (!encoded_data) continue;
189
- const [op, token] = Object.entries($1ab22f2cd39b3061$var$operator_map).find(([, token]) => key.endsWith(token)) || [$1ab22f2cd39b3061$var$fallback_operator, $1ab22f2cd39b3061$var$fallback_token];
190
- const data = $1ab22f2cd39b3061$var$decode_filter_data(op, encoded_data);
191
- if (!data) continue;
192
- const field = key.slice(chosen_prefix.length, token ? -token.length : undefined);
193
- found_filters.push({
194
- field: field,
195
- op: op,
196
- data: data
197
- });
198
- }
199
- return found_filters;
200
- }
201
- function $1ab22f2cd39b3061$export$62acb285a7579555(sorting, search_params, sorting_query_param) {
202
- if (!sorting) return;
203
- const {
204
- field: field,
205
- order: order
206
- } = sorting;
207
- const ascending = order === "asc";
208
- search_params.set(sorting_query_param, field + (ascending ? $1ab22f2cd39b3061$var$ascending_token : $1ab22f2cd39b3061$var$descending_token));
209
- }
210
- function $1ab22f2cd39b3061$export$766e9676e74997d3(search_params, sorting_query_param_) {
211
- const encoded_sorting = search_params.get(sorting_query_param_);
212
- if (!encoded_sorting) return;
213
- if (encoded_sorting.endsWith($1ab22f2cd39b3061$var$ascending_token)) return {
214
- field: encoded_sorting.slice(0, -$1ab22f2cd39b3061$var$ascending_token.length),
215
- order: "asc"
216
- };
217
- if (encoded_sorting.endsWith($1ab22f2cd39b3061$var$descending_token)) return {
218
- field: encoded_sorting.slice(0, -$1ab22f2cd39b3061$var$descending_token.length),
219
- order: "desc"
220
- };
221
- $5vyXB$depictaiutilishared.dlog("Invalid sorting query param value", encoded_sorting);
222
- return;
223
- }
224
- function $1ab22f2cd39b3061$export$916e6850778505f6(search_params, filter_query_param_prefix, sorting_query_param) {
225
- // We'll be modifying the URLSearchParams object, so we need to make a copy of the keys first
226
- const keys = [...search_params.keys()];
227
- for (const key of keys) if (key.startsWith(filter_query_param_prefix) || key === sorting_query_param || key.startsWith($1ab22f2cd39b3061$var$legacy_filter_prefix)) search_params.delete(key);
228
- }
229
- const $1ab22f2cd39b3061$export$cf5feb2102aec7f2 = "went_sideways_clear_filters";
230
- function $1ab22f2cd39b3061$export$43cd1e747fecd42e({
231
- to_url_: to_url_,
232
- set_clearing_flag_: set_clearing_flag_,
233
- from_search_params_ = new URLSearchParams(location.search),
234
- sorting_query_param_: sorting_query_param_,
235
- filter_query_param_prefix_: filter_query_param_prefix_
236
- }) {
237
- if (!to_url_) return to_url_;
238
- const was_url_object = to_url_ instanceof URL;
239
- const url_object = was_url_object ? to_url_ : new URL(to_url_, location.origin);
240
- const {
241
- searchParams: searchParams
242
- } = url_object;
243
- if (set_clearing_flag_) searchParams.set($1ab22f2cd39b3061$export$cf5feb2102aec7f2, "true");
244
- if (from_search_params_.has(sorting_query_param_)) searchParams.set(sorting_query_param_, from_search_params_.get(sorting_query_param_));
245
- for (const key of from_search_params_.keys()) if (key.startsWith(filter_query_param_prefix_)) searchParams.set(key, from_search_params_.get(key));
246
- if (was_url_object) return url_object;
247
- return url_object.href;
248
- }
249
- const $84798aaa863a4909$var$ListingContext = /*@__PURE__*/$5vyXB$solidjs.createContext();
250
- function $84798aaa863a4909$export$e68cff63f76bd15b(props) {
251
- const our_object = {};
252
- return $5vyXB$solidjsweb.createComponent($84798aaa863a4909$var$ListingContext.Provider, {
253
- value: our_object,
254
- get children() {
255
- return props.children;
194
+ if (!currentlySelected() || !tabsReactive().some(item => item.id === currentlySelected())) {
195
+ // Select first one by default if possible
196
+ const firstTab = tabsReactive()[0]?.id;
197
+ if (!firstTab) return;
198
+ setCurrentlySelected(firstTab);
256
199
  }
257
200
  });
201
+ return [(props.wrapTabBar || (v => v))($5vyXB$solidjsweb.ssr($8c38828ae2321937$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), props.slidable ? $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $a0e53f99354809d9$export$6649caad96ef8870), {
202
+ children: headerItems
203
+ })) : $5vyXB$solidjsweb.escape(headerItems))), $5vyXB$solidjsweb.ssr($8c38828ae2321937$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Index), {
204
+ get each() {
205
+ return tabsReactive();
206
+ },
207
+ children: item => {
208
+ const weSelected = $5vyXB$solidjs.createMemo(() => isSelected(item().id));
209
+ $5vyXB$solidjs.createEffect(() => {
210
+ if (weSelected()) {
211
+ setTabsVisitedOnce(prev => {
212
+ prev.add(item().id);
213
+ return prev;
214
+ });
215
+ $5vyXB$solidjs.untrack(() => item().onSelected?.());
216
+ }
217
+ });
218
+ $5vyXB$solidjs.onCleanup(() => setTabsVisitedOnce(prev => (prev.delete(item().id), prev)));
219
+ return $5vyXB$solidjsweb.ssr($8c38828ae2321937$var$_tmpl$3, $5vyXB$solidjsweb.ssrHydrationKey() + $5vyXB$solidjsweb.ssrAttribute("id", $5vyXB$solidjsweb.escape(item().id, true), false), weSelected() ? "selected" : "", "display:" + (weSelected() ? "" : "none"), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
220
+ get when() {
221
+ return tabsVisitedOnce().has(item().id);
222
+ },
223
+ get children() {
224
+ return item().children;
225
+ }
226
+ })));
227
+ }
228
+ })))];
258
229
  }
259
- function $84798aaa863a4909$export$8d0c4fdbb05a2f2e() {
260
- return $5vyXB$solidjs.useContext($84798aaa863a4909$var$ListingContext);
261
- }
262
- const $93304d59a9747aa6$var$_tmpl$ = ["<div", ' style="', '"', "></div>"];
263
- function $93304d59a9747aa6$export$94026ee33dbabc26(props) {
264
- return $5vyXB$solidjsweb.ssr($93304d59a9747aa6$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.ssrStyle(`position:relative;width:100%;padding-bottom:${1 / props.aspectRatio * 100}%`), $5vyXB$solidjsweb.ssrAttribute("class", $5vyXB$solidjsweb.escape(props.class, true), false));
230
+ function $8c38828ae2321937$export$3e41faf802a29e71(props) {
231
+ const currentTabs = $8c38828ae2321937$var$useTabs();
232
+ if (!currentTabs) throw new Error("Tab must be a child of Tabs");
233
+ const id = $5vyXB$solidjs.createUniqueId();
234
+ const ourSet = currentTabs;
235
+ const extendedProps = $5vyXB$solidjs.mergeProps({
236
+ id: id
237
+ }, props);
238
+ ourSet.add(extendedProps);
239
+ $5vyXB$solidjs.onCleanup(() => ourSet.delete(extendedProps));
240
+ return undefined;
265
241
  }
266
- function $19950faaac026e09$export$e6fffe67d4cdd848(whatToWatch) {
267
- const [size, setSize] = $5vyXB$solidjs.createSignal(0);
268
- const resizeObserver = new ResizeObserver($5vyXB$depictaiutilishared.catchify(records => {
269
- for (let j = 0; j < records.length; j++) {
270
- const {
271
- width: width
272
- } = records[j].contentRect;
273
- if (!width) continue;
274
- // add extra 5% just in case. + safari is (in some cases) acting a bit questionable and needs a third extra to fill the set width
275
- const new_size = width * 1.05 * ((0, $5vyXB$depictaiutilishared.is_safari) ? 4 / 3 : 1);
276
- setSize(Math.round(new_size));
277
- }
278
- }));
279
- // 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.
280
- // It doesn't seem to work even when waiting for it to be in the DOM, also wait an animation frame
281
- const disconnect = (0, $5vyXB$depictaiutilishared.observer).onexists(whatToWatch, ({
282
- element: element
283
- }) => requestAnimationFrame($5vyXB$depictaiutilishared.catchify(() => resizeObserver.observe(element))));
284
- $5vyXB$solidjs.onCleanup(() => {
285
- resizeObserver.disconnect();
286
- disconnect();
242
+ async function $9abb0a35d4b60ed3$export$79b1565500412d9b(search_modal, modal_fn_opts, parent) {
243
+ const body = parent || (await (0, $5vyXB$depictaiutilishared.observer).wait_for_element("body"));
244
+ let dispose_and_remove;
245
+ const open_modal_ = $5vyXB$depictaiutilishared.catchify(async (extra_options_for_modal = {}, on_dispose) => {
246
+ // Below await is very intentional,
247
+ // The reason is that effects don't run in <Suspense> boundaries before they've resolved and this carries even through roots created, but if a modal is opened from a suspense boundary we still want the effects in it to run
248
+ // This is because the suspense is for the content in the page and not the modal (the modal goes above it)
249
+ // By having an await here, solid loses all its knowledge of the suspense boundary
250
+ // (there is also some bug where effects don't run when created inside a suspense boundary that is resolved)
251
+ if (await dispose_and_remove)
252
+ // modal is already open
253
+ return;
254
+ const modal_els = $5vyXB$solidjs.createRoot(dispose => {
255
+ let closing_animation;
256
+ let animation_started;
257
+ dispose_and_remove = () => {
258
+ const actually_close = () => {
259
+ dispose();
260
+ on_dispose?.();
261
+ modal_els.forEach(el => el.remove());
262
+ };
263
+ if (animation_started && +new Date() - animation_started > 1000)
264
+ // Animation broke, close it this time
265
+ actually_close();else if (!animation_started && closing_animation) {
266
+ animation_started = +new Date();
267
+ $5vyXB$depictaiutilishared.catchify(closing_animation)()?.then($5vyXB$depictaiutilishared.catchify(actually_close));
268
+ } else actually_close();
269
+ };
270
+ return search_modal({
271
+ ...modal_fn_opts,
272
+ ...extra_options_for_modal,
273
+ close_modal_: close_modal_,
274
+ open_modal_: open_modal_,
275
+ register_closing_animation_: animation => closing_animation = animation
276
+ });
277
+ });
278
+ body.append(...modal_els);
287
279
  });
288
- return size;
280
+ const close_modal_ = $5vyXB$depictaiutilishared.catchify(() => {
281
+ if (dispose_and_remove) {
282
+ // modal is open
283
+ const dispose_fn = dispose_and_remove;
284
+ // set dispose function to undefined in case that it triggers this dispose function itself. Not doing it leads to a bug like https://github.com/solidjs/solid/discussions/1194
285
+ dispose_and_remove = undefined;
286
+ dispose_fn();
287
+ }
288
+ });
289
+ return {
290
+ open_modal_: open_modal_,
291
+ close_modal_: close_modal_
292
+ };
289
293
  }
290
- const $19950faaac026e09$var$onIdleFunctionsSymbol = /*@__PURE__*/Symbol("onIdleFunctions");
291
- function $19950faaac026e09$export$6e5611bc7e57e477(props) {
292
- // Enable reactive props
293
- const otherOptions = $5vyXB$solidjs.createMemo(() => {
294
- const cloned_props = {
295
- ...props
296
- };
297
- delete cloned_props.resolutions;
298
- // @ts-ignore
299
- delete cloned_props.size;
300
- // @ts-ignore
301
- delete cloned_props.src;
302
- return cloned_props;
294
+ function $6e22b5314fb52f4c$export$e183a13865960371(params_to_default_value, router_) {
295
+ const signals = {};
296
+ const entries = Object.entries(params_to_default_value);
297
+ const event_handler = $5vyXB$depictaiutilishared.catchify((what_happened, args) => {
298
+ // Intentionally always update our signals to the history state to allow external control of SDK state for doing things like https://linear.app/depictai/issue/X-1432/is-this-possible-with-the-depict-sdk
299
+ if (what_happened !== "popstate") return;
300
+ // Had to undo the comment above,but leaving the history. Doing this because discovering why it doesn't work is a deja-vu and I don't want to have to discover it again.
301
+ // If we want others to interface with our state, it's better to expose it from DepictCategory/DepictSearch
302
+ // The reason for that is because writes to the state trigger writes to the state (something about local filter state, see the comment where `last_remote_state !== available_filters_()` happens in create_modified_filters.tsx)
303
+ // And can infinite loop, like in https://app.jiminny.com/playback/569c8f65-edea-4735-bd9e-4eb5a0b14cad
304
+ // It's the classical equilibrium problem when syncing state both down and up, and it's much easier to avoid than solve
305
+ $6e22b5314fb52f4c$var$history_state_change(signals, entries, args.state);
303
306
  });
304
- const src_options = $5vyXB$solidjs.createMemo(() => {
305
- const src = new URL(props.src, location.origin);
306
- const fallback_src = $19950faaac026e09$var$generateImageUrl(src, 400);
307
- const srcset = $19950faaac026e09$var$make_srcset(src, props.resolutions || [64, 128, 256, 300, 400, 512, 768, 1024, 1280, 1536, 2048, 4096]);
308
- return {
309
- src: fallback_src,
310
- srcset: srcset
311
- };
307
+ // createRenderEffect because we need the instant execution so the signals always contain values, even before solid's render phase
308
+ $5vyXB$solidjs.createRenderEffect(() => {
309
+ let signal_changed = false;
310
+ let {
311
+ state: state
312
+ } = globalThis?.history || {
313
+ state: {}
314
+ }; // cloning isn't necessary because we're calling replaceState on it anyway
315
+ if (state === null || typeof state != "object") state = {};
316
+ for (const [param, default_value] of entries) {
317
+ const [read_signal] = signals[param] ||= $5vyXB$solidjs.createSignal(state[param] ?? default_value);
318
+ const new_value = read_signal();
319
+ if (new_value !== state[param]) {
320
+ signal_changed = true;
321
+ state[param] = new_value;
322
+ }
323
+ }
324
+ if (signal_changed) router_.navigate_.replace_state_(state);
312
325
  });
313
- // Work around https://github.com/solidjs/solid/issues/1828
314
- const img = new Image(); // Need to use new Image or browser might not start loading image before it's in the DOM
315
- const [hasSetSize, setHasSetSize] = $5vyXB$solidjs.createSignal(false);
316
- const [hasDecoded, setHasDecoded] = $5vyXB$solidjs.createSignal(false);
317
- const sizePX = $5vyXB$solidjs.createMemo(() => `${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
318
- const listingContext = $84798aaa863a4909$export$8d0c4fdbb05a2f2e();
319
- // 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
320
- // Happened on singular, they have some weird observer (+we also have one but ours is at least 3x more efficient)
321
- const executeWhenIdleBatched = fn => {
322
- if (typeof requestIdleCallback !== "function") return setTimeout(fn); // Old browsers don't get optimisation
323
- const existingStack = listingContext?.[$19950faaac026e09$var$onIdleFunctionsSymbol];
324
- if (existingStack) return existingStack.add(fn);
325
- const newStack = new Set([fn]);
326
- if (listingContext) listingContext[$19950faaac026e09$var$onIdleFunctionsSymbol] = newStack;
327
- const processStackWhenIdle = () => requestIdleCallback(deadline => {
328
- const start = performance.now();
329
- const thirdDeadlineTime = deadline.timeRemaining() / 3; // observers coming after this take up 2-3x the time so don't use all of it
330
- for (const fn of newStack) {
331
- newStack.delete(fn);
332
- fn();
333
- const timeTaken = performance.now() - start;
334
- if ((!deadline.timeRemaining() || timeTaken > thirdDeadlineTime) && newStack.size) {
335
- // There's still work to be done but no time, so schedule another idle callback
336
- processStackWhenIdle();
337
- return;
326
+ // history_dot_state_to_state needs to update after its signals after url_state does BUT in the same task (might even have to be in the same tick in the microtask queue). If we'd use window.addEventListener("popstate") it would be guaranteed to be too late since each event listener has its own task
327
+ (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(event_handler);
328
+ $5vyXB$solidjs.onCleanup($5vyXB$depictaiutilishared.catchify(() => (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(event_handler)));
329
+ $5vyXB$solidjs.createEffect($5vyXB$depictaiutilishared.catchify(() => $5vyXB$solidjs.untrack($5vyXB$depictaiutilishared.catchify(() => $6e22b5314fb52f4c$var$history_state_change(signals, entries, history.state))))); // we need this to run after reading the initial state from history.state to write the defaults to history.state
330
+ return signals;
331
+ }
332
+ function $6e22b5314fb52f4c$var$history_state_change(signals, entries, state) {
333
+ $5vyXB$solidjs.batch(() => {
334
+ for (const [param, default_value] of entries) {
335
+ const [, write_signal] = signals[param];
336
+ const new_value = state?.[param];
337
+ write_signal(new_value ?? default_value);
338
+ }
339
+ });
340
+ }
341
+ const $d84fe647b84b5dc5$export$3064e1e8c6513da3 = new Set();
342
+ let $d84fe647b84b5dc5$var$has_ran = false;
343
+ function $d84fe647b84b5dc5$export$5162a71f252e6122() {
344
+ if ($d84fe647b84b5dc5$var$has_ran || typeof history !== "object") return;
345
+ $d84fe647b84b5dc5$var$has_ran = true;
346
+ for (const function_name of ["replaceState", "pushState"]) {
347
+ if (Object.getOwnPropertyNames(history).includes(function_name)) $d84fe647b84b5dc5$var$proxy_push_state(function_name, history);
348
+ $d84fe647b84b5dc5$var$proxy_push_state(function_name, History.prototype);
349
+ }
350
+ }
351
+ function $d84fe647b84b5dc5$var$proxy_push_state(function_name, thing) {
352
+ thing[function_name] = new Proxy(thing[function_name], {
353
+ apply(target, this_arg, arg_list) {
354
+ try {
355
+ const old_state = history.state;
356
+ if (typeof old_state == "object" && old_state !== null) {
357
+ // This effectively disallows the user from passing in a string, number, null or undefined
358
+ const intended_new_value_as_obj = typeof arg_list[0] === "object" ? arg_list[0] ?? {} : {};
359
+ const cloned_object = {
360
+ ...intended_new_value_as_obj
361
+ };
362
+ for (const key in old_state) {
363
+ if (!$d84fe647b84b5dc5$var$starts_with_any_prefix(key)) continue;
364
+ if (!(key in cloned_object)) cloned_object[key] = old_state[key];
365
+ }
366
+ arg_list[0] = cloned_object;
338
367
  }
368
+ } catch (e) {
369
+ $5vyXB$depictaiutilishared.report([e, "Failed to preserve items in history.state"], "error");
339
370
  }
340
- // Stack is empty
341
- if (listingContext) delete listingContext[$19950faaac026e09$var$onIdleFunctionsSymbol];
342
- }, {
343
- timeout: 15000
344
- } // 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
345
- );
346
-
347
- processStackWhenIdle();
348
- };
349
- let sizeSetFastPath = false;
350
- let hasDecodedFastPath = false;
351
- let timeoutSet = false;
352
- let gotCleanedUp = false;
353
- $5vyXB$solidjs.onCleanup(() => gotCleanedUp = true);
354
- $5vyXB$solidjsweb.spread(img, $5vyXB$solidjs.mergeProps(otherOptions), false, true);
355
- $5vyXB$solidjs.createEffect(() => {
356
- if (!props.size()) return; // wait until we have a size
357
- if (timeoutSet) return;
358
- const handler = $5vyXB$depictaiutilishared.catchify(() => {
359
- if (gotCleanedUp) return;
360
- img.sizes = sizePX(); // use latest available value of props.size
361
- if (!sizeSetFastPath) {
362
- setHasSetSize(true);
363
- sizeSetFastPath = true;
364
- }
365
- timeoutSet = false;
366
- });
367
- // Throttle the updating of sizes to avoid unnecessary image re-fetches during resize
368
- // And also because we first set src after sizes has been set, wait with loading and decoding images until browser is idle
369
- // This greatly improves performance when loading (more) products
370
- // See https://depictaiworkspace.slack.com/archives/C05NJ0K3WRL/p1698220617663139
371
- executeWhenIdleBatched(handler);
372
- timeoutSet = true;
371
+ return Reflect.apply(target, this_arg, arg_list);
372
+ }
373
373
  });
374
- $5vyXB$solidjs.createEffect(() => {
375
- if (!props.size() || !hasSetSize()) return; // If size isn't known or set, don't assign src yet since it would cause the most low res image to load
376
- Object.assign(img, src_options());
377
- // Add to DOM once decoded to not require/block any paints before image has completed loading and avoid showing broken image symbol
378
- // We can do this because there has to be a container around us giving us a size
379
- // No need to listen if we're already in the DOM
380
- if (hasDecodedFastPath) return;
381
- if (props.loading === "lazy") {
382
- // For lazy loading there's no decoding to wait for as it only occurs when the image is visible
383
- // Make sure src is set before we put the image into the DOM though so no broken image symbol is shown
384
- setHasDecoded(true);
385
- hasDecodedFastPath = true;
386
- return;
374
+ }
375
+ function $d84fe647b84b5dc5$var$starts_with_any_prefix(key) {
376
+ for (const prefix of $d84fe647b84b5dc5$export$3064e1e8c6513da3) {
377
+ if (key.startsWith(prefix)) return true;
378
+ }
379
+ }
380
+ class $e96dd13889871fc0$export$7e1297a3a19f10d8 {
381
+ /**
382
+ * Function that will be called when we want to navigate, or a string saying it's not an SPA. You can change this OTG
383
+ */ /**
384
+ * We store listing_id in history.state and do operate on this both here and in js-ui, this is the key to be used which js-ui provides
385
+ */
386
+ #throwing_on_navigation(...args) {
387
+ const {
388
+ on_navigation_: on_navigation_
389
+ } = this;
390
+ if (typeof on_navigation_ !== "function") throw new Error("on_navigation_ is not a function");
391
+ // make sure that we don't accidentally catchify if the SDK consumer has fucked up
392
+ try {
393
+ return on_navigation_(...args);
394
+ } catch (e) {
395
+ queueMicrotask(() => {
396
+ throw e;
397
+ });
398
+ }
399
+ }
400
+ /**
401
+ * Checks if this tab shouldn't navigate because user wants to open in new tab
402
+ */
403
+ #dont_attempt_navigation(ev) {
404
+ return ev?.button || ev?.metaKey || ev?.ctrlKey;
405
+ }
406
+ /**
407
+ * Vue has async router that needs to be awaited (it navigates after a microtask)
408
+ * This standardises waiting for all kinds of routers
409
+ */
410
+ #get_navigation_happened_promise(is_replace) {
411
+ return new Promise(resolve => {
412
+ const handler = what_happened => {
413
+ if (what_happened === (is_replace ? "replaceState" : "pushState")) {
414
+ resolve();
415
+ (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(handler);
416
+ }
417
+ };
418
+ (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(handler);
419
+ });
420
+ }
421
+ navigate_ = {
422
+ /**
423
+ * Call this if you *just* want to replace the state object in history.state
424
+ */
425
+ replace_state_: new_state => {
426
+ // This doesn't break any router, so we just do this directly for now, since many don't expose an interface for changing the state
427
+ globalThis?.history?.replaceState(new_state, "");
428
+ },
429
+ /**
430
+ * Call this to change the URL
431
+ * @param new_url_ new URL to go to
432
+ * @param event_ event if you have this in a click handler, will not do anything on cmd/ctrl or non-left click then
433
+ * @param force_spa_navigation_ if you want to force SPA navigation even if on_navigation_ is set to "hard_navigation". You should only set this to true for inter-SDK-page navigations
434
+ * @param is_replace_ if you want to replace the current URL in history instead of pushing a new one
435
+ * @param listing_id_ If you are navigating to a category and know the listing_id of, please provide it. This is for making a better devEx in js-ui
436
+ */
437
+ go_to_: $5vyXB$depictaiutilishared.catchify(async ({
438
+ new_url_: raw_new_url,
439
+ event_: event_,
440
+ force_spa_navigation_: force_spa_navigation_,
441
+ is_replace_: is_replace_,
442
+ listing_id_: listing_id_,
443
+ scroll = true
444
+ }) => {
445
+ const new_url_ = raw_new_url instanceof URL ? raw_new_url : new URL(raw_new_url, location.origin);
446
+ const wants_hard_navigation = this.on_navigation_ === "hard_navigation";
447
+ if (this.#dont_attempt_navigation(event_)) return;
448
+ const different_origin = new_url_.origin !== location.origin;
449
+ if (wants_hard_navigation && (!force_spa_navigation_ || different_origin)) {
450
+ if (force_spa_navigation_ && different_origin)
451
+ // If we call history.pushState on a different origin, it will throw an error, so fallback to hard navigations
452
+ $5vyXB$depictaiutilishared.dwarn("Can't single page navigate to", new_url_.href, "due to different origin, this MIGHT mean you should fix the URLs");
453
+ if (!event_)
454
+ // If we haven't gotten an event, nothing will happen by not calling prevent default, so we need to change the URL
455
+ location.assign(new_url_);
456
+ return;
457
+ }
458
+ event_?.preventDefault();
459
+ const promise = this.#get_navigation_happened_promise(true);
460
+ if (force_spa_navigation_ && wants_hard_navigation) {
461
+ // Don't allow hard navigation if we're forcing SPA navigation, which we do for things where PageReplacer can be used for performance
462
+ const new_state = history.state;
463
+ if (listing_id_) {
464
+ // In JS-UI we need to know the listing_id of the current category, therefore push it into state
465
+ if (!this.listing_id_state_key) $5vyXB$depictaiutilishared.report(new Error("listing_id_state_key is not set"), "error");
466
+ new_state[this.listing_id_state_key] = listing_id_;
467
+ }
468
+ history[is_replace_ ? "replaceState" : "pushState"](new_state, "", new_url_);
469
+ } else this.#throwing_on_navigation.call(this, {
470
+ is_replace: is_replace_,
471
+ new_url: new_url_ instanceof URL ? new_url_ : new URL(new_url_, location.origin),
472
+ scroll: scroll
473
+ });
474
+ await promise;
475
+ })
476
+ };
477
+ constructor(on_navigation, listing_id_state_key) {
478
+ this.listing_id_state_key = listing_id_state_key;
479
+ this.on_navigation_ = on_navigation;
480
+ }
481
+ }
482
+ function $ca1176b694a6ee2e$export$fe334901e8bebd57() {
483
+ const cleanup_fns = [];
484
+ const cleanup = () => cleanup_fns.forEach(f => f());
485
+ // use an animation to automatically retain the `overflow` values and all other styling
486
+ for (const element of [document.documentElement, document.body]) {
487
+ try {
488
+ const animation = element.animate({
489
+ overflow: "hidden",
490
+ offset: 0
491
+ }, 1);
492
+ animation.pause();
493
+ const fn = $5vyXB$depictaiutilishared.catchify(animation.play.bind(animation));
494
+ cleanup_fns.push(fn);
495
+ $5vyXB$solidjs.onCleanup(fn);
496
+ } catch (e) {
497
+ $5vyXB$depictaiutilishared.dlog("Probably partial keyframe error", e);
498
+ }
499
+ if (getComputedStyle(element).overflow !== "hidden") {
500
+ // safari gets special hacky treatment
501
+ const style = element.style;
502
+ const original_value = style.overflow;
503
+ style.overflow = "hidden";
504
+ const fn = $5vyXB$depictaiutilishared.catchify(() => style.overflow = original_value);
505
+ cleanup_fns.push(fn);
506
+ $5vyXB$solidjs.onCleanup(fn);
507
+ }
508
+ }
509
+ return cleanup;
510
+ } // the way that houdini does that (FYI) it fixes the page jumps
511
+ // const from_top = scrollY;
512
+ // document.body.style.position = "fixed";
513
+ // document.body.style.left = 0;
514
+ // document.body.style.right = 0;
515
+ // document.body.style.top = `-${from_top}px`;
516
+ // document.body.style.overflowY = "scroll";
517
+
518
+ // Errors caused by SDK consuming code interfacing with the SDK, not the SDK itself or other Depict packages
519
+ class $7dd1edb2ee2b43ad$export$e1d52e4f0c7557a1 extends Error {}
520
+ class $7dd1edb2ee2b43ad$export$aa14a9f43128f61f extends $7dd1edb2ee2b43ad$export$e1d52e4f0c7557a1 {
521
+ constructor(templateError) {
522
+ super("Uncaught error in product card template", {
523
+ cause: templateError
524
+ });
525
+ }
526
+ }
527
+ const $edafe91daf3091d7$var$_tmpl$ = ["<div", ' class="', '"><!--$-->', "<!--/--><!--$-->", "<!--/--></div>"];
528
+ function $edafe91daf3091d7$export$b69d0d92862de18b(props) {
529
+ return $5vyXB$solidjs.ErrorBoundary({
530
+ fallback(err, retry) {
531
+ const {
532
+ message_: message_,
533
+ severity_: severity_
534
+ } = props;
535
+ let message = message_;
536
+ if (err instanceof (0, $7dd1edb2ee2b43ad$export$aa14a9f43128f61f)) {
537
+ console.error(err.cause);
538
+ message = `${message}: ${err.message}`;
539
+ } else $5vyXB$depictaiutilishared.report([err, message_], severity_);
540
+ return $5vyXB$solidjsweb.ssr($edafe91daf3091d7$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.ssrClassList(Object.fromEntries(props.class_list_?.map(c => [c, true]) || [])), $5vyXB$solidjsweb.escape(message), $5vyXB$solidjsweb.escape(props.on_error_?.(retry)));
541
+ },
542
+ get children() {
543
+ return props.children;
544
+ }
545
+ });
546
+ }
547
+ const $c77c68e559a1506c$var$_tmpl$ = '<path d="M11.669 10.531l9.156-9.156a.78.78 0 0 0 .237-.569c0-.221-.079-.412-.237-.569A.8.8 0 0 0 20.24 0a.77.77 0 0 0-.569.237l-9.14 9.14-9.14-9.14A.79.79 0 0 0 .807 0a.77.77 0 0 0-.569.237A.78.78 0 0 0 0 .807a.77.77 0 0 0 .237.569l9.156 9.156-9.156 9.14c-.159.157-.237.349-.237.569s.079.412.237.569c.085.085.174.148.268.19a1.095 1.095 0 0 0 .316.048.894.894 0 0 0 .285-.048.84.84 0 0 0 .285-.19l9.139-9.14 9.14 9.14a.894.894 0 0 0 .268.19 1.049 1.049 0 0 0 .301.048.941.941 0 0 0 .301-.048.84.84 0 0 0 .285-.19.78.78 0 0 0 .237-.569c0-.221-.079-.412-.237-.569z"></path>';
548
+ function $c77c68e559a1506c$export$3b621d86b1566b2(props = {}) {
549
+ return $5vyXB$solidjsweb.ssrElement("svg", $5vyXB$solidjsweb.mergeProps({
550
+ xmlns: "http://www.w3.org/2000/svg",
551
+ width: "21.064",
552
+ height: "21.064",
553
+ viewBox: "0 0 21.064 21.064"
554
+ }, props), () => $5vyXB$solidjsweb.ssr($c77c68e559a1506c$var$_tmpl$), true);
555
+ }
556
+ const $9fe9883b1d8ecccc$var$_tmpl$ = ["<span", ' class="', '" style="', '"></span>'];
557
+ function $9fe9883b1d8ecccc$export$acb3eaade4b23afd(props) {
558
+ return $5vyXB$solidjsweb.ssr($9fe9883b1d8ecccc$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), `depict-placeholder${$5vyXB$solidjsweb.escape(props.class, true) || ""}`, $5vyXB$solidjsweb.ssrStyle(props.style));
559
+ }
560
+ function $3bc4a89b971a3af5$export$3f37af283f8fb843(props) {
561
+ const style = $5vyXB$solidjs.createMemo(() => {
562
+ const {
563
+ style: style,
564
+ height: height,
565
+ width: width,
566
+ aspectRatio: aspectRatio
567
+ } = props;
568
+ const is_image = aspectRatio != undefined;
569
+ const size_data = is_image ? {
570
+ width: "100%",
571
+ "padding-bottom": 1 / aspectRatio * 100 + "%"
572
+ } : {
573
+ width: width,
574
+ height: height
575
+ };
576
+ return {
577
+ display: "block",
578
+ ...(style || {}),
579
+ ...size_data
580
+ };
581
+ });
582
+ return $5vyXB$solidjsweb.createComponent((0, $9fe9883b1d8ecccc$export$acb3eaade4b23afd), {
583
+ get style() {
584
+ return style();
585
+ },
586
+ get ["class"]() {
587
+ return props.class;
588
+ }
589
+ });
590
+ }
591
+ const $bbe694fe824b9c78$var$_tmpl$ = ["<div", ' class="image-container">', "</div>"];
592
+ function $bbe694fe824b9c78$export$41e1a079d40a0d58(props) {
593
+ const [display] = $5vyXB$solidjs.createResource(() => ({
594
+ merchant: props.merchant_,
595
+ market: props.market_,
596
+ locale: props.locale_,
597
+ product_ids: [props.productId_]
598
+ }), async request => {
599
+ const response = await fetch($5vyXB$depictaiutilishared.add_version_query_params(`${(0, $5vyXB$depictaiutilishared.base_url)}/v3/get-displays`), {
600
+ method: "POST",
601
+ body: JSON.stringify(request)
602
+ });
603
+ const decoded = await response.json();
604
+ return decoded.displays[0];
605
+ });
606
+ const placeholder = $5vyXB$solidjsweb.createComponent((0, $3bc4a89b971a3af5$export$3f37af283f8fb843), {
607
+ get aspectRatio() {
608
+ return props.imageAspectRatio_;
609
+ }
610
+ });
611
+ return $5vyXB$solidjsweb.ssr($bbe694fe824b9c78$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Suspense), {
612
+ fallback: placeholder,
613
+ get children() {
614
+ return (() => {
615
+ const imageUrl = $5vyXB$solidjs.createMemo(() => {
616
+ const d = display();
617
+ const variant = d?.variant_displays[d?.variant_index];
618
+ return variant?.image_urls?.[0] || variant?.display_image_url;
619
+ });
620
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
621
+ get when() {
622
+ return imageUrl();
623
+ },
624
+ fallback: "Cannot load image",
625
+ get children() {
626
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$depictaiutilishared.ContainedImage), {
627
+ loading: "lazy",
628
+ srcset_opts: {
629
+ set_dataset: false
630
+ },
631
+ get src() {
632
+ return imageUrl();
633
+ },
634
+ get aspect_ratio() {
635
+ return props.imageAspectRatio_;
636
+ },
637
+ rendering_options: {},
638
+ alt: "Product image showing the current product with other outfits highlighted on the model"
639
+ });
640
+ }
641
+ });
642
+ })();
643
+ }
644
+ })));
645
+ }
646
+ function $061ff5b4c3d36171$export$89c6019e4baa40b1(props) {
647
+ const style = $5vyXB$solidjs.createMemo(() => {
648
+ const {
649
+ style: style,
650
+ height: height,
651
+ width: width
652
+ } = props;
653
+ return {
654
+ ...(style || {}),
655
+ height: height ?? "1em",
656
+ ...(width && {
657
+ width: width
658
+ })
659
+ };
660
+ });
661
+ return $5vyXB$solidjsweb.createComponent((0, $9fe9883b1d8ecccc$export$acb3eaade4b23afd), {
662
+ get style() {
663
+ return style();
664
+ },
665
+ get ["class"]() {
666
+ return props.class;
667
+ }
668
+ });
669
+ }
670
+ const $6b502b1b2155a0bc$export$5c28802497c8a83c = /*@__PURE__*/Symbol("category_title_type");
671
+ const $0b23bfd073d9a4e8$var$_tmpl$ = ["<div", ' class="category-title"><h1 class="title">', '</h1><span class="explanation"> \u2014 <!--$-->', "<!--/--></span></div>"];
672
+ const $0b23bfd073d9a4e8$export$b91cec6bdc6b32a1 = /*@__PURE__*/(() => {
673
+ const actual_function = ({
674
+ category_title_: category_title_,
675
+ product_count_: product_count_
676
+ }) => {
677
+ return $5vyXB$solidjsweb.ssr($0b23bfd073d9a4e8$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(category_title_()) || $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $061ff5b4c3d36171$export$89c6019e4baa40b1), {
678
+ height: "1em",
679
+ width: "10ch"
680
+ })), $5vyXB$solidjsweb.escape(product_count_));
681
+ };
682
+ // This is wrong but parcel can't build correctly, it says unexpected undefined
683
+ actual_function[(0, $6b502b1b2155a0bc$export$5c28802497c8a83c)] = "simple";
684
+ return actual_function;
685
+ })();
686
+ const $a3280f0aad997933$export$c3834fa86c616831 = [[4], [3, 1024], [2, 901]];
687
+ const $a3280f0aad997933$export$864d304a0bc46829 = "2%";
688
+ const $a3280f0aad997933$export$7bf543b9d9be2c22 = (0, $0b23bfd073d9a4e8$export$b91cec6bdc6b32a1);
689
+ function $fc23d7668ae0011d$export$a2cc176055f8f08() {
690
+ const text = "Please try setting `columnsAtSize`/`gridSpacing` on the `SearchPage`/`CategoryPage` components to change the grid 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.";
691
+ return (0, $5vyXB$solidjsweb.isServer) ? {
692
+ t: `<!-- ${text} -->`
693
+ } : document.createComment(text);
694
+ }
695
+ function $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(elements) {
696
+ // FYI this probably doesn't work on hugely deep nestings or large amount of elements
697
+ return $5vyXB$solidjs.createMemo(() => $5f7d55c710fd1bc2$var$unwrapping_helper(elements));
698
+ }
699
+ function $5f7d55c710fd1bc2$var$unwrapping_helper(elements) {
700
+ const result = [];
701
+ if (Array.isArray(elements)) for (let i = 0; i < elements.length; i++) {
702
+ const element = elements[i];
703
+ result.push(...$5f7d55c710fd1bc2$var$unwrapping_helper(element));
704
+ } else if (typeof elements == "function") result.push(...$5f7d55c710fd1bc2$var$unwrapping_helper(elements()));else if (elements != undefined && typeof elements != "boolean") result.push(elements);
705
+ return result;
706
+ }
707
+ let $0caf87eaa19079da$var$cached_placeholder_element;
708
+ let $0caf87eaa19079da$var$rendering_cached_placeholder_element;
709
+ function $0caf87eaa19079da$export$f33414a4df0afd3f({
710
+ product_card_template_: product_card_template_,
711
+ num_placeholders_: num_placeholders_,
712
+ content_blocks_: content_blocks_
713
+ }) {
714
+ const [num_to_actually_show, set_num_to_actually_show] = $5vyXB$solidjs.createSignal($5vyXB$solidjs.untrack(num_placeholders_));
715
+ if (0, $5vyXB$solidjsweb.isServer)
716
+ // want to render simple placeholders on server, effects don't run there
717
+ // FIXME when adding proper SSR: also SSR content blocks
718
+ return $5vyXB$solidjs.createMemo(() => Array.from({
719
+ length: num_placeholders_()
720
+ }).map(() => {
721
+ const template_result = product_card_template_(null, undefined);
722
+ // @ts-ignore
723
+ if (typeof template_result?.then !== "function") return template_result;
724
+ }));
725
+ $5vyXB$solidjs.createRenderEffect(() => {
726
+ const existing_num = num_to_actually_show();
727
+ const to_add = num_placeholders_() - existing_num;
728
+ if (to_add <= 0) return;
729
+ // 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.
730
+ // 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.
731
+ // 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.
732
+ // 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
733
+ // Functionality should be the same
734
+ set_num_to_actually_show(existing_num + to_add);
735
+ });
736
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Index), {
737
+ get each() {
738
+ return Array.from({
739
+ length: num_to_actually_show()
740
+ });
741
+ },
742
+ children: (_item, index) => {
743
+ const possible_content_block = $5vyXB$solidjs.createMemo(() => content_blocks_?.()?.()?.[index]);
744
+ // Show content block before product card, so it's *at* that index
745
+ return [possible_content_block, $0caf87eaa19079da$var$Placeholder({
746
+ product_card_template_: product_card_template_
747
+ })]; // https://github.com/solidjs/solid/releases/tag/v1.7.0
748
+ }
749
+ });
750
+ }
751
+ /**
752
+ * Get one placeholder element. It will be cloned for each placeholder for ultimate performance even when solid-js isn't rendering the placeholders.
753
+ */
754
+ function $0caf87eaa19079da$var$Placeholder({
755
+ product_card_template_: product_card_template_
756
+ }) {
757
+ const get_cloned_placeholders = (element_to_clone = $0caf87eaa19079da$var$cached_placeholder_element) => Array.isArray(element_to_clone) ? element_to_clone.map(el => el instanceof Node ? el.cloneNode(true) : el) : element_to_clone;
758
+ if ($0caf87eaa19079da$var$cached_placeholder_element) return get_cloned_placeholders();
759
+ let dispose_original_copy;
760
+ const get_unwrapped_element = $5vyXB$solidjs.createRoot(dispose => {
761
+ dispose_original_copy = dispose;
762
+ // if product_card_template_ is async and rejects the resource will take care of throwing upwards here in the solid-js error handling system
763
+ const [resource] = $5vyXB$solidjs.createResource(() => {
764
+ if ($0caf87eaa19079da$var$rendering_cached_placeholder_element) return $0caf87eaa19079da$var$rendering_cached_placeholder_element;
765
+ const return_value = product_card_template_(null, undefined);
766
+ if (typeof return_value === "object" && typeof return_value?.then === "function")
767
+ // Is Promise or promise-like object
768
+ $0caf87eaa19079da$var$rendering_cached_placeholder_element = return_value;
769
+ return return_value;
770
+ });
771
+ return $5vyXB$solidjs.createMemo(() => {
772
+ if (resource.loading) return () => [];
773
+ return $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(resource);
774
+ });
775
+ });
776
+ $5vyXB$solidjs.onCleanup(() => {
777
+ if ($0caf87eaa19079da$var$rendering_cached_placeholder_element) {
778
+ // 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
779
+ const unset_current_rendering = () => {
780
+ dispose_original_copy();
781
+ $0caf87eaa19079da$var$rendering_cached_placeholder_element = undefined;
782
+ };
783
+ $0caf87eaa19079da$var$rendering_cached_placeholder_element?.then(unset_current_rendering, unset_current_rendering);
784
+ } else
785
+ // Otherwise, just make sure we've disposed our root
786
+ dispose_original_copy();
787
+ });
788
+ return $5vyXB$solidjs.createMemo(() => {
789
+ const unwrapped_array = get_unwrapped_element()();
790
+ if (!unwrapped_array?.length || !unwrapped_array.every(item => item))
791
+ // Haven't finished rendering yet in case of "async" rendering, so don't freeze the elements yet
792
+ return;
793
+ // placeholders have finished rendering, freeze the elements
794
+ // 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
795
+ $0caf87eaa19079da$var$cached_placeholder_element ||= 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
796
+ $0caf87eaa19079da$var$rendering_cached_placeholder_element = undefined;
797
+ dispose_original_copy(); // So that this memo will never re-run and the placeholder rendering function can clean up
798
+ 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
799
+ });
800
+ }
801
+
802
+ /**
803
+ * Gets product_id (the thing we key the rendering on) from a display
804
+ */
805
+ function $a5871dacf261adf8$export$548d053aba053d79(display) {
806
+ if ("variant_index" in display) {
807
+ const actual_display = display.variant_displays[display.variant_index];
808
+ return actual_display.product_id;
809
+ }
810
+ return display.product_id;
811
+ }
812
+ let $a73063cc642f3e5f$var$printedCloneError = false;
813
+ function $a73063cc642f3e5f$export$7f8bd308237ab5a5(get_displays_) {
814
+ const displays_by_key_ = $5vyXB$solidjs.createMemo(() => {
815
+ const displays = get_displays_();
816
+ // We key by product_id because that's what can be used to uniquely identify products
817
+ // This way <For> can optimize the rendering
818
+ const map = new Map();
819
+ for (let i = 0; i < displays.length; i++) {
820
+ const display = displays[i];
821
+ const product_id = $a5871dacf261adf8$export$548d053aba053d79(display);
822
+ map.set(product_id, display);
823
+ }
824
+ return map;
825
+ });
826
+ return displays_by_key_;
827
+ }
828
+ const $a73063cc642f3e5f$var$result_ids = ["search_result_id", "product_listing_result_id", "recommendation_id"];
829
+ function $a73063cc642f3e5f$export$43f0fb951fcb0c54({
830
+ displays_by_key_: displays_by_key_,
831
+ product_card_template_: product_card_template_,
832
+ do_per_elements_: do_per_elements_,
833
+ content_blocks_: content_blocks_
834
+ }) {
835
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.For), {
836
+ get each() {
837
+ return [...displays_by_key_().keys()];
838
+ },
839
+ children: (product_id, index) => {
840
+ const owner = $5vyXB$solidjs.getOwner();
841
+ const possible_content_block = $5vyXB$solidjs.createMemo(() => content_blocks_?.()?.()?.[index()]);
842
+ const display_accessor = $5vyXB$solidjs.createMemo(prev => {
843
+ const new_display = displays_by_key_().get(product_id);
844
+ if (prev && $a73063cc642f3e5f$var$deep_equal(prev, new_display))
845
+ // 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.
846
+ // This doesn't work if people mutate the displays from within the template but we hope they don't
847
+ // (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)
848
+ return prev;
849
+ return new_display;
850
+ });
851
+ const [product_card_resource] = $5vyXB$solidjs.createResource(display_accessor,
852
+ // re-render when the reference to the display object changes
853
+ display => {
854
+ // It's easy for merchants to accidentally mutate the display or some sub-object thereof
855
+ // We had a case on singular where they popped an image url and due to use caching after some time there was no image
856
+ // Attempt cloning the displays if possible (99.9% of the cases probably) and if not, just use the original display
857
+ try {
858
+ display = structuredClone(display);
859
+ } catch (e) {
860
+ if (!$a73063cc642f3e5f$var$printedCloneError) {
861
+ $a73063cc642f3e5f$var$printedCloneError = true;
862
+ $5vyXB$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);
863
+ }
864
+ }
865
+ return product_card_template_(display, {
866
+ set_on_index_change: fn => $5vyXB$solidjs.runWithOwner(owner, () => $5vyXB$solidjs.createEffect(() => fn(index())))
867
+ });
868
+ });
869
+ const node_accessor = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(product_card_resource);
870
+ $5vyXB$solidjs.createEffect(() => {
871
+ const product_card_nodes = node_accessor();
872
+ const display = display_accessor();
873
+ const elements = [];
874
+ for (let i = 0; i < product_card_nodes.length; i++) {
875
+ const element = product_card_nodes[i];
876
+ if (!(element instanceof Element)) continue;
877
+ elements.push(element);
878
+ // Add tracking ids
879
+ if (!(element instanceof HTMLElement)) continue; // Apparently only HTMLElements have dataset
880
+ for (let i = 0; i < $a73063cc642f3e5f$var$result_ids.length; i++) {
881
+ const id = $a73063cc642f3e5f$var$result_ids[i];
882
+ const value = display[id];
883
+ if (value) Object.assign(element.dataset, $5vyXB$depictaiutilishared.camelCasifyObject({
884
+ [id]: value
885
+ }));
886
+ }
887
+ }
888
+ do_per_elements_?.(elements, index);
889
+ });
890
+ return [
891
+ // Show content block before product card, so it's *at* that index
892
+ possible_content_block, product_card_resource]; // https://github.com/solidjs/solid/releases/tag/v1.7.0
387
893
  }
388
- img.decode().catch(e => $5vyXB$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"
389
- .then(async () => {
390
- // Also wait with inserting image (i.e. paint) until browser is idle
391
- await new Promise(r => executeWhenIdleBatched(r));
392
- if (gotCleanedUp) return;
393
- setHasDecoded(true);
394
- hasDecodedFastPath = true;
395
- });
396
- });
397
- return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
398
- get when() {
399
- return hasDecoded();
400
- },
401
- children: img
402
894
  });
403
895
  }
404
- function $19950faaac026e09$var$make_srcset(url, resolutions) {
405
- return resolutions.map(width => `${$19950faaac026e09$var$generateImageUrl(url, width)} ${width}w`).join(", ");
406
- }
407
- function $19950faaac026e09$var$generateImageUrl(url, width) {
408
- // This function is quite slow, we maybe could do string concat with encodeURIComponent instead if shopify handles double width params well?
409
- url.searchParams.set("width", width);
410
- return url.href;
896
+ // source: https://medium.com/@pancemarko/deep-equality-in-javascript-determining-if-two-objects-are-equal-bf98cf47e934
897
+ function $a73063cc642f3e5f$var$deep_equal(obj1, obj2) {
898
+ if (obj1 === obj2) return true;
899
+ if (Array.isArray(obj1) && Array.isArray(obj2)) {
900
+ if (obj1.length !== obj2.length) return false;
901
+ return obj1.every((elem, index) => {
902
+ return $a73063cc642f3e5f$var$deep_equal(elem, obj2[index]);
903
+ });
904
+ }
905
+ if (typeof obj1 === "object" && typeof obj2 === "object" && obj1 !== null && obj2 !== null) {
906
+ if (Array.isArray(obj1) || Array.isArray(obj2)) return false;
907
+ const keys1 = Object.keys(obj1);
908
+ const keys2 = Object.keys(obj2);
909
+ if (keys1.length !== keys2.length || !keys1.every(key => keys2.includes(key))) return false;
910
+ for (const key in obj1) {
911
+ if ($a73063cc642f3e5f$var$result_ids.includes(key)) continue; // ignore keys changing with every request
912
+ const isEqual = $a73063cc642f3e5f$var$deep_equal(obj1[key], obj2[key]);
913
+ if (!isEqual) return false;
914
+ }
915
+ return true;
916
+ }
917
+ return false;
411
918
  }
412
- const $a33065cfed827fc0$var$backupSizeSignal = /*@__PURE__*/$5vyXB$solidjs.createSignal();
413
- const $a33065cfed827fc0$export$d7b7ab832c20e2f4 = /*@__PURE__*/Symbol("ShopifyContainedImage");
414
- function $a33065cfed827fc0$export$e4b984597b71e989(props) {
415
- const context = $84798aaa863a4909$export$8d0c4fdbb05a2f2e();
416
- if (context && !context[$a33065cfed827fc0$export$d7b7ab832c20e2f4])
417
- // create a signal that's the same for all items in this listing
418
- context[$a33065cfed827fc0$export$d7b7ab832c20e2f4] = $5vyXB$solidjs.createSignal();
419
- const [currentImageSize, setCurrentImageSize] = context?.[$a33065cfed827fc0$export$d7b7ab832c20e2f4] || $a33065cfed827fc0$var$backupSizeSignal; // use global fallback signal (might lead to blurry images) if no context is available
420
- const container = $5vyXB$solidjsweb.createComponent((0, $93304d59a9747aa6$export$94026ee33dbabc26), {
421
- get aspectRatio() {
422
- return props.aspectRatio;
919
+ const $f48d0fbb00835aaa$var$_tmpl$ = ["<div", ' class="', '">', "</div>"],
920
+ $f48d0fbb00835aaa$var$_tmpl$2 = ["<style", ' type="text/css">', "</style>"];
921
+ function $f48d0fbb00835aaa$export$d21e32dfedac04be(props) {
922
+ const container_class = "x" + $5vyXB$solidjs.createUniqueId();
923
+ const container_element_ = $5vyXB$solidjsweb.ssrElement("div", $5vyXB$solidjsweb.mergeProps(() => props.element_attributes, {
924
+ classList: {
925
+ [container_class]: true
926
+ }
927
+ }), () => $5vyXB$solidjsweb.escape(props.children), true); // Don't want this in the error boundary below, it should only be for the actual layouting
928
+ return $5vyXB$solidjsweb.createComponent((0, $edafe91daf3091d7$export$b69d0d92862de18b), {
929
+ get message_() {
930
+ return "Failed calculating " + props.layout + " layout";
423
931
  },
424
- get ["class"]() {
425
- return props.class;
932
+ severity_: "error",
933
+ get children() {
934
+ return $f48d0fbb00835aaa$export$445d8d3f5f706a40(props, container_element_, false, container_class);
426
935
  }
427
936
  });
428
- const owner = $5vyXB$solidjs.getOwner();
429
- let createdSizeAccessor = false;
430
- let wasCleanedUp = false;
431
- $5vyXB$solidjs.createEffect(() => {
432
- if (currentImageSize() || wasCleanedUp) return; // We get into the effect when onCleanup is called if we don't have wasCleanedUp
433
- // ensure we always have a size accessor
434
- // 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
435
- createdSizeAccessor = true;
436
- setCurrentImageSize(() => $5vyXB$solidjs.runWithOwner(owner, () => $19950faaac026e09$export$e6fffe67d4cdd848(container)));
937
+ }
938
+ function $f48d0fbb00835aaa$export$445d8d3f5f706a40(props, container_element, insert_after_container = false, container_class) {
939
+ if (!container_class) {
940
+ // only try to add if it wasn't provided, so that we have a code path without classList when doing SSR
941
+ container_class = $5vyXB$depictaiutilishared.make_random_classname();
942
+ container_element.classList.add(container_class);
943
+ }
944
+ // Copy of Layout from utilishared but using solid-js signals instead of async iterable IPNS
945
+ const show_all_rows = $5vyXB$solidjs.createMemo(() => props.rows === "all");
946
+ const rows_or_empty_object = $5vyXB$solidjs.createMemo(() => show_all_rows() ? {} : props.rows);
947
+ const view_more_button_elements = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52($5vyXB$solidjs.createMemo(() => rows_or_empty_object().button));
948
+ const view_less_button_elements = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52($5vyXB$solidjs.createMemo(() => rows_or_empty_object().view_less_button));
949
+ const have_a_view_more_button = $5vyXB$solidjs.createMemo(() => {
950
+ const button = view_more_button_elements();
951
+ return !(!button || Array.isArray(button) && !button.length);
437
952
  });
438
- $5vyXB$solidjs.onCleanup(() => {
439
- wasCleanedUp = true; // important to set this before the function call below and always, so the dead effects don't create dead size accessors
440
- if (!createdSizeAccessor) return;
441
- $5vyXB$depictaiutilishared.queueMacroTask(() => setCurrentImageSize(undefined)); // 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
953
+ const have_a_view_less_button = $5vyXB$solidjs.createMemo(() => {
954
+ const button = view_less_button_elements();
955
+ return !(!button || Array.isArray(button) && !button.length);
442
956
  });
443
-
444
- $5vyXB$solidjsweb.insert(container, $5vyXB$solidjsweb.createComponent((0, $19950faaac026e09$export$6e5611bc7e57e477), {
445
- style: "width: 100%; height: 100%; object-fit: contain; position: absolute; inset: 0;",
446
- get size() {
447
- return $5vyXB$solidjs.createMemo(() => currentImageSize()?.() || 0);
448
- },
449
- get src() {
450
- return props.src;
957
+ const [get_styling, set_styling] = $5vyXB$solidjs.createSignal();
958
+ const selector_beginning = `.depict .${container_class}>`; // class so ppl can have id if needed
959
+ const [get_children_count, set_children_count] = $5vyXB$solidjs.createSignal(0);
960
+ const update_children_count = () => (0, $5vyXB$solidjsweb.isServer) ? 20 : set_children_count(container_element.children.length);
961
+ const col_styling = $5vyXB$solidjs.createMemo(() => $5vyXB$depictaiutilishared.n_col_styling_with_dist(selector_beginning, props.grid_spacing, props.cols_at_size, props.layout, props.override_vertical_spacing));
962
+ const default_currently_visible_signal = $5vyXB$solidjs.createSignal($5vyXB$solidjs.untrack(() => rows_or_empty_object().start_rows ?? 1)); // 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
963
+ const rows_visible_signal = $5vyXB$solidjs.createMemo(() => rows_or_empty_object().currently_visible || default_currently_visible_signal);
964
+ const get_rows_visible = $5vyXB$solidjs.createMemo(() => rows_visible_signal()[0]());
965
+ const set_rows_visible = $5vyXB$solidjs.createMemo(() => rows_visible_signal()[1]);
966
+ const view_more_button_class = "m" + $5vyXB$solidjs.createUniqueId();
967
+ const view_less_button_class = "l" + $5vyXB$solidjs.createUniqueId(); // https://github.com/solidjs/solid-docs/issues/263#issuecomment-1622388079
968
+ const view_more_button_container = $5vyXB$solidjs.createMemo(() => have_a_view_more_button() && $5vyXB$solidjsweb.ssr($f48d0fbb00835aaa$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), `load-more-container ${$5vyXB$solidjsweb.escape(view_more_button_class, true)}`, $5vyXB$solidjsweb.escape(rows_or_empty_object().button)));
969
+ // 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
970
+ const view_less_button_container = $5vyXB$solidjs.createMemo(() => have_a_view_less_button() && $5vyXB$solidjsweb.ssr($f48d0fbb00835aaa$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), `load-less-container ${$5vyXB$solidjsweb.escape(view_less_button_class, true)}`, $5vyXB$solidjsweb.escape(rows_or_empty_object().view_less_button)));
971
+ const [force_style_update, set_force_style_update] = $5vyXB$solidjs.createSignal("");
972
+ $5vyXB$solidjs.createComputed(() => {
973
+ // Make sure we don't have more rows visible than max_rows (this could happen by max_rows being decreased)
974
+ const rows_visible = get_rows_visible();
975
+ const max_rows = rows_or_empty_object().max_rows;
976
+ if (!isNaN(max_rows) && max_rows >= 0 && rows_visible > max_rows) set_rows_visible()(max_rows);
977
+ });
978
+ $5vyXB$solidjs.createEffect(() => set_force_style_update(" ")); // force style update after hydration due to https://discord.com/channels/722131463138705510/722167424186843267/1151544212517552168
979
+ $5vyXB$solidjs.createRenderEffect(() => {
980
+ // Be careful to only read show_all_rows in here (ofc doesn't apply to nested effects)
981
+ if (show_all_rows()) {
982
+ // no view more functionality requested
983
+ set_styling(() => col_styling);
984
+ return;
451
985
  }
452
- }));
453
- return container;
454
- }
455
- const $0f313083912e447a$var$_tmpl$ = ["<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"></path></svg>'];
456
- function $0f313083912e447a$export$8be2714ec7f169ee(props = {}) {
457
- return $5vyXB$solidjsweb.ssr($0f313083912e447a$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.ssrAttribute("width", $5vyXB$solidjsweb.escape(props.width_, true) ?? 14, false) + $5vyXB$solidjsweb.ssrAttribute("height", $5vyXB$solidjsweb.escape(props.height_, true) ?? 26, false));
458
- }
459
- const $a0e53f99354809d9$var$_tmpl$ = ["<div", ">", "</div>"];
460
- function $a0e53f99354809d9$export$6649caad96ef8870({
461
- children: children,
462
- slider_ref_: slider_ref_,
463
- faded_opacity_ = 0.7,
464
- mutation_plugins_ = [],
465
- disable_fading_: disable_fading_,
466
- arrow_width_: arrow_width_,
467
- arrow_height_: arrow_height_
468
- }) {
469
- const slider = new (0, $5vyXB$depictaiutilishared.Amazing_Slider)({
470
- button_contents: {
471
- left: [$5vyXB$solidjsweb.ssr($a0e53f99354809d9$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $0f313083912e447a$export$8be2714ec7f169ee), {
472
- height_: arrow_height_,
473
- width_: arrow_width_
474
- })))],
475
- right: [$5vyXB$solidjsweb.ssr($a0e53f99354809d9$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $0f313083912e447a$export$8be2714ec7f169ee), {
476
- height_: arrow_height_,
477
- width_: arrow_width_
478
- })))]
479
- },
480
- constructor_plugins: [$5vyXB$depictaiutilishared.slider_snap_css().constructor_plugin],
481
- mutation_plugins: [...(disable_fading_ ? [] : [$5vyXB$depictaiutilishared.slider_fading_factory({
482
- threshold_: 0.96,
483
- faded_opacity_: faded_opacity_
484
- }).mutation_plugin_]), ...mutation_plugins_]
986
+ update_children_count();
987
+ if (!(0, $5vyXB$solidjsweb.isServer)) {
988
+ const mutation_observer = new MutationObserver($5vyXB$depictaiutilishared.catchify(update_children_count));
989
+ mutation_observer.observe(container_element, {
990
+ childList: true
991
+ });
992
+ $5vyXB$solidjs.onCleanup(() => mutation_observer.disconnect());
993
+ }
994
+ set_styling(
995
+ // this is needed because solid will think that the memo-accessor is a setter function otherwise
996
+ () => $5vyXB$solidjs.createMemo(() => {
997
+ const {
998
+ rows_per_click: rows_per_click,
999
+ max_rows = -1,
1000
+ start_rows: start_rows
1001
+ } = rows_or_empty_object();
1002
+ const rows_visible = get_rows_visible();
1003
+ const children_count = get_children_count();
1004
+ return force_style_update() + col_styling() + props.cols_at_size.map(options => {
1005
+ const [recs_per_row, min, max] = options;
1006
+ let should_hide_view_more_button;
1007
+ let visible_recs;
1008
+ if (props.disable_partial_rows) {
1009
+ visible_recs = $5vyXB$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible, children_count, options);
1010
+ const visible_recs_next_show_more = $5vyXB$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible + (rows_per_click || 0),
1011
+ // Should this really be zero when we default rows_per_click to 1?
1012
+ children_count, options);
1013
+ should_hide_view_more_button = visible_recs === visible_recs_next_show_more;
1014
+ } else {
1015
+ visible_recs = $5vyXB$depictaiutilishared.layout_get_total_rec_amount_for_row(rows_visible, options);
1016
+ should_hide_view_more_button = visible_recs >= children_count;
1017
+ }
1018
+ const should_hide_button_final = should_hide_view_more_button || max_rows !== -1 && rows_visible >= max_rows;
1019
+ // 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
1020
+ 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;
1021
+ return `${$5vyXB$depictaiutilishared.layout_media_query_header(min, max)}{${selector_beginning}:nth-child(n+${visible_recs + 1}){display:none}${props.layout == "slider" ? `${selector_beginning}:nth-child(n+${visible_recs}){margin-right:0}` : ""}${should_hide_button_final ? `.depict .${view_more_button_class}{display:none!important}` : ``}${should_hide_view_less_button ? `.depict .${view_less_button_class}{display:none!important}` : ``}}`;
1022
+ }).join("");
1023
+ }));
485
1024
  });
486
- $5vyXB$solidjsweb.insert(slider.insert_here, children);
487
- $5vyXB$solidjs.onCleanup(() => slider.observer.disconnect());
488
- slider_ref_?.(slider);
489
- return slider.container;
1025
+ const style_element = $5vyXB$solidjsweb.ssr($f48d0fbb00835aaa$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), get_styling); // need to create this after set_styling has been called or else there will be no styling in the SSR'd output
1026
+ if (insert_after_container) container_element.after(style_element);
1027
+ return [container_element, view_more_button_container(), view_less_button_container(), style_element];
490
1028
  }
491
-
492
- /** @jsxImportSource solid-js */
493
-
494
- function $f13855d1b951b24a$export$ebdc3711f7e02ccd(what_to_watch) {
495
- const [width, setWidth] = $5vyXB$solidjs.createSignal();
496
- const resizeObserver = new ResizeObserver($5vyXB$depictaiutilishared.catchify(records => {
497
- for (let j = 0; j < records.length; j++) {
498
- const width = records[j].borderBoxSize?.[0]?.inlineSize ?? what_to_watch.getBoundingClientRect().width;
499
- setWidth(width);
1029
+ const $b8e79813f4f7ebe4$var$_tmpl$ = ["<h2", ' class="recs-title">', "</h2>"],
1030
+ $b8e79813f4f7ebe4$var$_tmpl$2 = ["<div", ' class="recommendation-grid"><!--$-->', "<!--/--><!--$-->", "<!--/--></div>"];
1031
+ function $b8e79813f4f7ebe4$export$7da560f849543dff({
1032
+ recommendations_resource_: recommendations_resource_,
1033
+ product_card_template_: product_card_template_,
1034
+ layout_options_: layout_options_,
1035
+ rows_object_: rows_object_,
1036
+ title_: title_
1037
+ }) {
1038
+ const is_showing_something = $5vyXB$solidjs.createMemo(() => recommendations_resource_.loading || recommendations_resource_()?.length);
1039
+ const title = $5vyXB$solidjs.createMemo(() => title_?.()); // In case getter/accessor creates elements, don't create them twice
1040
+ const num_placeholders_ = () => 20;
1041
+ const elements = [$5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1042
+ get when() {
1043
+ return title();
1044
+ },
1045
+ get children() {
1046
+ return $5vyXB$solidjsweb.ssr($b8e79813f4f7ebe4$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(title()));
500
1047
  }
501
- }));
502
- // 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.
503
- // It doesn't seem to work even when waiting for it to be in the DOM, also wait an animation frame
504
- const disconnect = (0, $5vyXB$depictaiutilishared.observer).onexists(what_to_watch, ({
505
- element: element
506
- }) => requestAnimationFrame($5vyXB$depictaiutilishared.catchify(() => {
507
- const current_size = what_to_watch.getBoundingClientRect().width;
508
- if (current_size)
509
- // If element has size, set signal to that. ResizeObserver only triggers when the content is visible in some cases, but it might already have a size. This reduces size filter expanding animation jank in chrome.
510
- setWidth(current_size);
511
- resizeObserver.observe(element);
512
- })));
513
- $5vyXB$solidjs.onCleanup(() => {
514
- resizeObserver.disconnect();
515
- disconnect();
1048
+ }), $5vyXB$solidjsweb.ssr($b8e79813f4f7ebe4$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($fc23d7668ae0011d$export$a2cc176055f8f08()), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $f48d0fbb00835aaa$export$d21e32dfedac04be), $5vyXB$solidjsweb.mergeProps({
1049
+ get rows() {
1050
+ return rows_object_();
1051
+ },
1052
+ layout: "grid",
1053
+ element_attributes: {
1054
+ class: "cards"
1055
+ }
1056
+ }, layout_options_, {
1057
+ get children() {
1058
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Suspense), {
1059
+ get fallback() {
1060
+ return $0caf87eaa19079da$export$f33414a4df0afd3f({
1061
+ num_placeholders_: num_placeholders_,
1062
+ product_card_template_: product_card_template_
1063
+ });
1064
+ },
1065
+ get children() {
1066
+ return (() => {
1067
+ // IIFE to make sure we access both the recommendations_resource and the resources containing the product card rendering results themselves within the Suspense boundary
1068
+ const displays_by_key_ = $a73063cc642f3e5f$export$7f8bd308237ab5a5($5vyXB$solidjs.createMemo(() => recommendations_resource_() || []));
1069
+ return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
1070
+ displays_by_key_: displays_by_key_,
1071
+ product_card_template_: product_card_template_
1072
+ });
1073
+ })();
1074
+ }
1075
+ });
1076
+ }
1077
+ }))))];
1078
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1079
+ get when() {
1080
+ return is_showing_something();
1081
+ },
1082
+ children: elements
516
1083
  });
517
- return width;
518
1084
  }
519
1085
  const $4e04be41243c3d80$var$transform_elements = sorted_cols_at_size => {
520
1086
  const cols_at_size = [];
@@ -551,546 +1117,777 @@ const $4e04be41243c3d80$export$6daf8749b65a1b77 = cols_at_size => {
551
1117
  });
552
1118
  return $4e04be41243c3d80$var$transform_elements(sorted_cols_at_size);
553
1119
  };
554
- function $fc23d7668ae0011d$export$a2cc176055f8f08() {
555
- const text = "Please try setting `columnsAtSize`/`gridSpacing` on the `SearchPage`/`CategoryPage` components to change the grid 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.";
556
- return (0, $5vyXB$solidjsweb.isServer) ? {
557
- t: `<!-- ${text} -->`
558
- } : document.createComment(text);
1120
+ function $95837413165cc2df$export$23fca46f3143581f(component, error_message) {
1121
+ const component_in_error_boundary = do_with_elements => {
1122
+ const error_boundary_wrapped = $edafe91daf3091d7$export$b69d0d92862de18b({
1123
+ severity_: "error",
1124
+ message_: error_message,
1125
+ get children() {
1126
+ const elements = component();
1127
+ do_with_elements?.(elements);
1128
+ return elements;
1129
+ }
1130
+ });
1131
+ // This might return an accessor, in that case we need to "unwrap" it since our SDK consumers expect HTML elements or arrays thereof
1132
+ if (typeof error_boundary_wrapped === "function")
1133
+ // @ts-ignore
1134
+ return error_boundary_wrapped();
1135
+ // On the server it returns a string, so we just return that
1136
+ return error_boundary_wrapped;
1137
+ };
1138
+ const owner = $5vyXB$solidjs.getOwner();
1139
+ if (owner == null) return $5vyXB$solidjs.createRoot(dispose => {
1140
+ // 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
1141
+ return component_in_error_boundary(elements => {
1142
+ const have_multiple = Array.isArray(elements);
1143
+ if (have_multiple ? !elements?.length : !elements) return;
1144
+ (0, $5vyXB$depictaiutilishared.observer).onremoved(have_multiple ? elements[0] : elements, ({
1145
+ element: element
1146
+ }) => {
1147
+ if (document.documentElement.contains(element)) return; // If element has instantly been re-inserted, don't dispose
1148
+ // See https://depictaiworkspace.slack.com/archives/C050GHEPBTR/p1695809102791259?thread_ts=1695106805.459729&cid=C050GHEPBTR
1149
+ dispose();
1150
+ });
1151
+ });
1152
+ });else
1153
+ // we're already in a root so cleanups are handled
1154
+ return component_in_error_boundary();
559
1155
  }
560
- function $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(elements) {
561
- // FYI this probably doesn't work on hugely deep nestings or large amount of elements
562
- return $5vyXB$solidjs.createMemo(() => $5f7d55c710fd1bc2$var$unwrapping_helper(elements));
1156
+ const $84798aaa863a4909$var$ListingContext = /*@__PURE__*/$5vyXB$solidjs.createContext();
1157
+ function $84798aaa863a4909$export$e68cff63f76bd15b(props) {
1158
+ const our_object = {};
1159
+ return $5vyXB$solidjsweb.createComponent($84798aaa863a4909$var$ListingContext.Provider, {
1160
+ value: our_object,
1161
+ get children() {
1162
+ return props.children;
1163
+ }
1164
+ });
563
1165
  }
564
- function $5f7d55c710fd1bc2$var$unwrapping_helper(elements) {
565
- const result = [];
566
- if (Array.isArray(elements)) for (let i = 0; i < elements.length; i++) {
567
- const element = elements[i];
568
- result.push(...$5f7d55c710fd1bc2$var$unwrapping_helper(element));
569
- } else if (typeof elements == "function") result.push(...$5f7d55c710fd1bc2$var$unwrapping_helper(elements()));else if (elements != undefined && typeof elements != "boolean") result.push(elements);
570
- return result;
1166
+ function $84798aaa863a4909$export$8d0c4fdbb05a2f2e() {
1167
+ return $5vyXB$solidjs.useContext($84798aaa863a4909$var$ListingContext);
571
1168
  }
572
- let $0caf87eaa19079da$var$cached_placeholder_element;
573
- let $0caf87eaa19079da$var$rendering_cached_placeholder_element;
574
- function $0caf87eaa19079da$export$f33414a4df0afd3f({
575
- product_card_template_: product_card_template_,
576
- num_placeholders_: num_placeholders_,
577
- content_blocks_: content_blocks_
578
- }) {
579
- const [num_to_actually_show, set_num_to_actually_show] = $5vyXB$solidjs.createSignal($5vyXB$solidjs.untrack(num_placeholders_));
580
- if (0, $5vyXB$solidjsweb.isServer)
581
- // want to render simple placeholders on server, effects don't run there
582
- // FIXME when adding proper SSR: also SSR content blocks
583
- return $5vyXB$solidjs.createMemo(() => Array.from({
584
- length: num_placeholders_()
585
- }).map(() => {
586
- const template_result = product_card_template_(null, undefined);
587
- // @ts-ignore
588
- if (typeof template_result?.then !== "function") return template_result;
589
- }));
590
- $5vyXB$solidjs.createRenderEffect(() => {
591
- const existing_num = num_to_actually_show();
592
- const to_add = num_placeholders_() - existing_num;
593
- if (to_add <= 0) return;
594
- // 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.
595
- // 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.
596
- // 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.
597
- // 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
598
- // Functionality should be the same
599
- set_num_to_actually_show(existing_num + to_add);
600
- });
601
- return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Index), {
602
- get each() {
603
- return Array.from({
604
- length: num_to_actually_show()
605
- });
1169
+ const $1f8dbf7e28b3eff2$var$_tmpl$ = ["<button", ' class="show-more major" type="button">', "</button>"],
1170
+ $1f8dbf7e28b3eff2$var$_tmpl$2 = ["<div", ' class="depict plp recommendations">', "</div>"];
1171
+ function $1f8dbf7e28b3eff2$export$9756467d34d91cdb(props) {
1172
+ return $95837413165cc2df$export$23fca46f3143581f(() => {
1173
+ const rows_object_ = $5vyXB$solidjs.createMemo(() => {
1174
+ const {
1175
+ view_more_button: view_more_button,
1176
+ max_rows: max_rows
1177
+ } = props;
1178
+ if (!view_more_button) {
1179
+ if (max_rows) return {
1180
+ max_rows: max_rows
1181
+ };
1182
+ return "all";
1183
+ }
1184
+ return {
1185
+ max_rows: max_rows,
1186
+ start_rows: view_more_button.start_rows,
1187
+ rows_per_click: view_more_button.rows_per_click ?? 2,
1188
+ button: $5vyXB$solidjsweb.ssr($1f8dbf7e28b3eff2$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(view_more_button.text))
1189
+ };
1190
+ });
1191
+ const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
1192
+ const {
1193
+ grid_spacing: grid_spacing
1194
+ } = props; // can be reactive
1195
+ return typeof grid_spacing === "string" ? {
1196
+ grid_spacing: grid_spacing
1197
+ } : {
1198
+ override_vertical_spacing: grid_spacing.vertical,
1199
+ grid_spacing: grid_spacing.horizontal
1200
+ };
1201
+ });
1202
+ const [recommendations_resource_] = $5vyXB$solidjs.createResource(() => props.recommendations, recs => recs);
1203
+ return $5vyXB$solidjsweb.ssr($1f8dbf7e28b3eff2$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $84798aaa863a4909$export$e68cff63f76bd15b), {
1204
+ get children() {
1205
+ return $b8e79813f4f7ebe4$export$7da560f849543dff({
1206
+ rows_object_: rows_object_,
1207
+ product_card_template_: (...args) => props.product_card_template(...args),
1208
+ recommendations_resource_: recommendations_resource_,
1209
+ title_: () => props.title,
1210
+ layout_options_: $5vyXB$solidjs.createMemo(() => ({
1211
+ cols_at_size: $4e04be41243c3d80$export$6daf8749b65a1b77(props.cols_at_size),
1212
+ ...grid_spacing_override()
1213
+ }))
1214
+ });
1215
+ }
1216
+ })));
1217
+ }, "RecommendationGrid failed");
1218
+ }
1219
+ function $f55548318724b05c$export$6b35356958ae5587(props) {
1220
+ const gridSpacing = (0, $a3280f0aad997933$export$864d304a0bc46829);
1221
+ const columnsAtSize = [[3], [2, 901]];
1222
+ const href = $5vyXB$depictaiutilishared.use_href_accessor();
1223
+ const hrefWithoutHash = $5vyXB$solidjs.createMemo(() => {
1224
+ // Don't let the hash count for knowing when the user navigated away as we change the hash when different tabs are selected
1225
+ const url = new URL(href());
1226
+ url.hash = "";
1227
+ return "" + url;
1228
+ });
1229
+ const makeJSXElementCloseModalWhenClicked = returnValue => {
1230
+ const resolved = $5vyXB$solidjs.children(() => returnValue);
1231
+ $5vyXB$solidjs.createEffect(() => {
1232
+ // If someone clicks on a product card in the shop the look modal, close the modal the next time the href changes
1233
+ for (const item of resolved.toArray()) {
1234
+ if (!(item instanceof Element)) return;
1235
+ item.addEventListener("click", $5vyXB$depictaiutilishared.catchify(() =>
1236
+ // run with modal owner so we don't do stuff after the modal closes
1237
+ // can't have the owner of the product card as that gets disposed if the productId changes which might be too early (before location.href has changed)
1238
+ $5vyXB$solidjs.runWithOwner(props.modalOwner_, () => $5vyXB$solidjs.createEffect($5vyXB$solidjs.on(hrefWithoutHash, props.actually_close_modal_, {
1239
+ defer: true
1240
+ })))), {
1241
+ capture: true
1242
+ });
1243
+ }
1244
+ });
1245
+ return resolved;
1246
+ };
1247
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1248
+ get when() {
1249
+ return !props.products_to_shop_.error;
606
1250
  },
607
- children: (_item, index) => {
608
- const possible_content_block = $5vyXB$solidjs.createMemo(() => content_blocks_?.()?.()?.[index]);
609
- // Show content block before product card, so it's *at* that index
610
- return [possible_content_block, $0caf87eaa19079da$var$Placeholder({
611
- product_card_template_: product_card_template_
612
- })]; // https://github.com/solidjs/solid/releases/tag/v1.7.0
1251
+ fallback: "Failed fetching shop by look recommendations",
1252
+ get children() {
1253
+ return $5vyXB$solidjsweb.createComponent((0, $8c38828ae2321937$export$b2539bed5023c21c), {
1254
+ AnchorComponent: anchorProps => $5vyXB$solidjsweb.ssrElement("a", anchorProps, () => $5vyXB$solidjsweb.escape(anchorProps.children), true),
1255
+ get children() {
1256
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Suspense), {
1257
+ get fallback() {
1258
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Index), {
1259
+ get each() {
1260
+ return Array.from({
1261
+ length: 2
1262
+ });
1263
+ },
1264
+ children: () => $5vyXB$solidjsweb.createComponent((0, $8c38828ae2321937$export$3e41faf802a29e71), {
1265
+ get label() {
1266
+ return $5vyXB$solidjsweb.createComponent((0, $061ff5b4c3d36171$export$89c6019e4baa40b1), {
1267
+ height: "1em",
1268
+ width: "10ch"
1269
+ });
1270
+ },
1271
+ get children() {
1272
+ return $5vyXB$solidjsweb.createComponent((0, $1f8dbf7e28b3eff2$export$9756467d34d91cdb), {
1273
+ grid_spacing: gridSpacing,
1274
+ cols_at_size: columnsAtSize,
1275
+ recommendations: new Promise(r => $5vyXB$solidjs.onCleanup(() => r([]))),
1276
+ get product_card_template() {
1277
+ return props.productCardTemplate_;
1278
+ },
1279
+ max_rows: 2
1280
+ });
1281
+ }
1282
+ })
1283
+ });
1284
+ },
1285
+ get children() {
1286
+ return (() => {
1287
+ const groups = $5vyXB$solidjs.createMemo(() => Object.keys(props.products_to_shop_()?.shop_the_look || {}));
1288
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.For), {
1289
+ get each() {
1290
+ return groups();
1291
+ },
1292
+ children: group => $5vyXB$solidjsweb.createComponent((0, $8c38828ae2321937$export$3e41faf802a29e71), {
1293
+ label: group,
1294
+ get id() {
1295
+ return "shop-the-look-" + group.replaceAll(" ", "-").toLowerCase();
1296
+ },
1297
+ get children() {
1298
+ return $5vyXB$solidjsweb.createComponent((0, $1f8dbf7e28b3eff2$export$9756467d34d91cdb), {
1299
+ grid_spacing: gridSpacing,
1300
+ cols_at_size: columnsAtSize,
1301
+ get recommendations() {
1302
+ return Promise.resolve(props.products_to_shop_().shop_the_look[group]);
1303
+ },
1304
+ product_card_template: (...args) => {
1305
+ const returnValue = props.productCardTemplate_(...args);
1306
+ // Product card template can return promise, handle that
1307
+ if (typeof returnValue === "object" && returnValue && "then" in returnValue) {
1308
+ const owner = $5vyXB$solidjs.getOwner();
1309
+ return returnValue.then(returnValue => $5vyXB$solidjs.runWithOwner(owner, () => makeJSXElementCloseModalWhenClicked(returnValue)));
1310
+ }
1311
+ return makeJSXElementCloseModalWhenClicked(returnValue);
1312
+ }
1313
+ });
1314
+ }
1315
+ })
1316
+ });
1317
+ })();
1318
+ }
1319
+ });
1320
+ }
1321
+ });
1322
+ }
1323
+ });
1324
+ }
1325
+ const $b0ceb08960135d83$var$_tmpl$ = ["<div", ' class="top-bar"><button class="close">', "</button></div>"],
1326
+ $b0ceb08960135d83$var$_tmpl$2 = ["<div", ' class="below-top-bar"><h2>Outfit recommendations</h2><div class="image-and-suggestions"><!--$-->', '<!--/--><div class="tabs">', "</div></div></div>"],
1327
+ $b0ceb08960135d83$var$_tmpl$3 = ["<div", ' id="depict-shop-the-look-modal" class="depict shop-the-look"><div class="shop-the-look-backdrop"></div><div class="modal-contents">', "</div></div>"];
1328
+ function $b0ceb08960135d83$export$a3cbef418994a664(props) {
1329
+ const pseudo_router_ = new (0, $e96dd13889871fc0$export$7e1297a3a19f10d8)(props.onNavigation);
1330
+ const closing_animations = [];
1331
+ const owner = $5vyXB$solidjs.getOwner();
1332
+ const isBig = () => matchMedia("(min-height: 740px) and (min-width: 740px)").matches;
1333
+ props.register_closing_animation_(() => Promise.all(closing_animations.map(animation => animation().finished)));
1334
+ $ca1176b694a6ee2e$export$fe334901e8bebd57();
1335
+ return [$5vyXB$solidjsweb.ssr($b0ceb08960135d83$var$_tmpl$3, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $edafe91daf3091d7$export$b69d0d92862de18b), {
1336
+ message_: "ShopTheLookModal failed",
1337
+ severity_: "error",
1338
+ get children() {
1339
+ return [$5vyXB$solidjsweb.ssr($b0ceb08960135d83$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $c77c68e559a1506c$export$3b621d86b1566b2), {
1340
+ width: 16,
1341
+ height: 16
1342
+ }))), $5vyXB$solidjsweb.ssr($b0ceb08960135d83$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $bbe694fe824b9c78$export$41e1a079d40a0d58), {
1343
+ get locale_() {
1344
+ return props.locale;
1345
+ },
1346
+ get market_() {
1347
+ return props.market;
1348
+ },
1349
+ get merchant_() {
1350
+ return props.merchant;
1351
+ },
1352
+ get imageAspectRatio_() {
1353
+ return props.imageAspectRatio;
1354
+ },
1355
+ get productId_() {
1356
+ return props.productId;
1357
+ }
1358
+ })), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $f55548318724b05c$export$6b35356958ae5587), {
1359
+ modalOwner_: owner,
1360
+ pseudo_router_: pseudo_router_,
1361
+ get productCardTemplate_() {
1362
+ return props.productCardTemplate;
1363
+ },
1364
+ get products_to_shop_() {
1365
+ return props.products_to_shop_;
1366
+ },
1367
+ get actually_close_modal_() {
1368
+ return props.actually_close_modal_;
1369
+ }
1370
+ })))];
1371
+ }
1372
+ })))];
1373
+ }
1374
+ const $a5f3eaa1a24bbc1e$var$_tmpl$ = ["<div", ">Failed fetching shop the look recommendations</div>"];
1375
+ const $a5f3eaa1a24bbc1e$var$CANT_FETCH = "Failed fetching shop the look recommendations";
1376
+ let $a5f3eaa1a24bbc1e$var$setModalShouldBeOpen;
1377
+ let $a5f3eaa1a24bbc1e$var$modalProps;
1378
+ function $a5f3eaa1a24bbc1e$export$d4973c31938cbfd1(props) {
1379
+ return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.ErrorBoundary), {
1380
+ fallback: () => $5vyXB$solidjsweb.ssr($a5f3eaa1a24bbc1e$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey()),
1381
+ get children() {
1382
+ return $5vyXB$solidjsweb.createComponent($a5f3eaa1a24bbc1e$var$ActualShopTheLookButton, props);
1383
+ }
1384
+ });
1385
+ }
1386
+ function $a5f3eaa1a24bbc1e$var$ActualShopTheLookButton(props) {
1387
+ const [products_to_shop_] = $5vyXB$solidjs.createResource(() => ({
1388
+ merchant: props.merchant,
1389
+ market: props.market,
1390
+ locale: props.locale,
1391
+ product_ids: [props.productId],
1392
+ type: "shop_the_look",
1393
+ session_id: $5vyXB$depictaiutilishared.get_session_id()
1394
+ }), async request => {
1395
+ const response = await fetch($5vyXB$depictaiutilishared.add_version_query_params(`${(0, $5vyXB$depictaiutilishared.base_url)}/v3/shop-the-look`), {
1396
+ method: "POST",
1397
+ body: JSON.stringify(request)
1398
+ });
1399
+ if (!response.ok) {
1400
+ $5vyXB$depictaiutilishared.dwarn(response);
1401
+ throw new Error($a5f3eaa1a24bbc1e$var$CANT_FETCH);
613
1402
  }
1403
+ const decoded = await response.json();
1404
+ return decoded;
614
1405
  });
1406
+ const [localProps, partForModal] = $5vyXB$solidjs.splitProps(props, ["buttonAttributes"]);
1407
+ const {
1408
+ openModal: openModal,
1409
+ closeModal: closeModal
1410
+ } = $a5f3eaa1a24bbc1e$var$useShopTheLookModal();
1411
+ const hasAnythingToShow = $5vyXB$solidjs.createMemo(() => Object.entries(products_to_shop_()?.shop_the_look || {}).length);
1412
+ const displayStyleValue = $5vyXB$solidjs.createMemo(() => hasAnythingToShow() ? "" : "none");
1413
+ const button = $5vyXB$solidjsweb.ssrElement("button", localProps.buttonAttributes, () => $5vyXB$solidjsweb.escape(localProps?.buttonAttributes?.children) || "Shop the look", true);
1414
+ $5vyXB$solidjs.createEffect(() => button.style.display = displayStyleValue()); // Set our attributes like this, so we allow total control over the button from the outside via buttonAttributes
1415
+ $5vyXB$solidjs.createEffect(() => !hasAnythingToShow() && closeModal()); // close modal if we ever get into the state of having it open and not having anything to show
1416
+ $a5f3eaa1a24bbc1e$var$modalProps = $5vyXB$solidjs.mergeProps(partForModal, {
1417
+ products_to_shop_: products_to_shop_
1418
+ });
1419
+ button.addEventListener("click", openModal);
1420
+ return button;
615
1421
  }
616
1422
  /**
617
- * Get one placeholder element. It will be cloned for each placeholder for ultimate performance even when solid-js isn't rendering the placeholders.
1423
+ * This does not need to be run in a root at all, it will create a root every time the modal is opened and then tear it down when the modal is closed again
618
1424
  */
619
- function $0caf87eaa19079da$var$Placeholder({
620
- product_card_template_: product_card_template_
621
- }) {
622
- const get_cloned_placeholders = (element_to_clone = $0caf87eaa19079da$var$cached_placeholder_element) => Array.isArray(element_to_clone) ? element_to_clone.map(el => el instanceof Node ? el.cloneNode(true) : el) : element_to_clone;
623
- if ($0caf87eaa19079da$var$cached_placeholder_element) return get_cloned_placeholders();
624
- let dispose_original_copy;
625
- const get_unwrapped_element = $5vyXB$solidjs.createRoot(dispose => {
626
- dispose_original_copy = dispose;
627
- // if product_card_template_ is async and rejects the resource will take care of throwing upwards here in the solid-js error handling system
628
- const [resource] = $5vyXB$solidjs.createResource(() => {
629
- if ($0caf87eaa19079da$var$rendering_cached_placeholder_element) return $0caf87eaa19079da$var$rendering_cached_placeholder_element;
630
- const return_value = product_card_template_(null, undefined);
631
- if (typeof return_value === "object" && typeof return_value?.then === "function")
632
- // Is Promise or promise-like object
633
- $0caf87eaa19079da$var$rendering_cached_placeholder_element = return_value;
634
- return return_value;
635
- });
636
- return $5vyXB$solidjs.createMemo(() => {
637
- if (resource.loading) return () => [];
638
- return $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(resource);
639
- });
640
- });
641
- $5vyXB$solidjs.onCleanup(() => {
642
- if ($0caf87eaa19079da$var$rendering_cached_placeholder_element) {
643
- // 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
644
- const unset_current_rendering = () => {
645
- dispose_original_copy();
646
- $0caf87eaa19079da$var$rendering_cached_placeholder_element = undefined;
647
- };
648
- $0caf87eaa19079da$var$rendering_cached_placeholder_element?.then(unset_current_rendering, unset_current_rendering);
649
- } else
650
- // Otherwise, just make sure we've disposed our root
651
- dispose_original_copy();
652
- });
653
- return $5vyXB$solidjs.createMemo(() => {
654
- const unwrapped_array = get_unwrapped_element()();
655
- if (!unwrapped_array?.length || !unwrapped_array.every(item => item))
656
- // Haven't finished rendering yet in case of "async" rendering, so don't freeze the elements yet
657
- return;
658
- // placeholders have finished rendering, freeze the elements
659
- // 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
660
- $0caf87eaa19079da$var$cached_placeholder_element ||= 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
661
- $0caf87eaa19079da$var$rendering_cached_placeholder_element = undefined;
662
- dispose_original_copy(); // So that this memo will never re-run and the placeholder rendering function can clean up
663
- 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
1425
+ function $a5f3eaa1a24bbc1e$var$useShopTheLookModal() {
1426
+ if ($a5f3eaa1a24bbc1e$var$setModalShouldBeOpen) return $a5f3eaa1a24bbc1e$var$setModalShouldBeOpen;
1427
+ return $a5f3eaa1a24bbc1e$var$setModalShouldBeOpen = $5vyXB$solidjs.createRoot(() => $a5f3eaa1a24bbc1e$var$actualSetupModal());
1428
+ }
1429
+ function $a5f3eaa1a24bbc1e$var$actualSetupModal() {
1430
+ // Save modal state in history so modal is still open after people go back
1431
+ const history_key = "depict_shop_the_look_open";
1432
+ const {
1433
+ [history_key]: [history_value, set_history_value]
1434
+ } = $6e22b5314fb52f4c$export$e183a13865960371({
1435
+ [history_key]: false
1436
+ }, {
1437
+ navigate_: {
1438
+ replace_state_: new_state => globalThis?.history?.replaceState(new_state, "")
1439
+ }
664
1440
  });
1441
+ (0, $d84fe647b84b5dc5$export$3064e1e8c6513da3).add(history_key);
1442
+ const actually_close_modal_ = () => set_history_value(false);
1443
+ const owner = $5vyXB$solidjs.getOwner();
1444
+ $5vyXB$depictaiutilishared.catchify(async () => {
1445
+ const {
1446
+ open_modal_: open_modal_,
1447
+ close_modal_: close_modal_
1448
+ } = await $9abb0a35d4b60ed3$export$79b1565500412d9b((0, $b0ceb08960135d83$export$a3cbef418994a664), {
1449
+ actually_close_modal_: actually_close_modal_
1450
+ });
1451
+ $5vyXB$solidjs.runWithOwner(owner, () => $5vyXB$solidjs.createEffect(() => {
1452
+ if (history_value()) open_modal_($a5f3eaa1a24bbc1e$var$modalProps);else close_modal_();
1453
+ }));
1454
+ })();
1455
+ return {
1456
+ openModal: () => set_history_value(true),
1457
+ closeModal: actually_close_modal_
1458
+ };
665
1459
  }
666
-
1460
+ const $1ab22f2cd39b3061$var$fallback_operator = "in";
1461
+ const $1ab22f2cd39b3061$var$fallback_token = "";
1462
+ const $1ab22f2cd39b3061$var$legacy_filter_prefix = "filter_";
1463
+ const $1ab22f2cd39b3061$var$operator_map = {
1464
+ "eq": "\u2261",
1465
+ "neq": "\u2260",
1466
+ "in": "\u2208",
1467
+ "nin": "\u2209",
1468
+ "leq": "\u2264",
1469
+ "geq": "\u2265",
1470
+ "inrange": "\uD83D\uDD22"
1471
+ };
1472
+ const $1ab22f2cd39b3061$var$ascending_token = "\uD83D\uDCC8";
1473
+ const $1ab22f2cd39b3061$var$descending_token = "\uD83D\uDCC9";
1474
+ const $1ab22f2cd39b3061$var$range_delimiter = "-";
1475
+ const $1ab22f2cd39b3061$var$string_item_delimiter = "\u201A"; // This is not a comma but a comma-like character that browsers will render in the URL bar.
1476
+ const $1ab22f2cd39b3061$var$array_item_delimiter = "\u2023"; // FIXME: decide on a character. Could theoretically be a double string delimiter.
1477
+ const $1ab22f2cd39b3061$var$empty_item_replacement = "0\uFE0F\u20E3";
1478
+ const $1ab22f2cd39b3061$var$op_to_token = op => {
1479
+ if (op === $1ab22f2cd39b3061$var$fallback_operator) return $1ab22f2cd39b3061$var$fallback_token;
1480
+ return $1ab22f2cd39b3061$var$operator_map[op];
1481
+ };
667
1482
  /**
668
- * Gets product_id (the thing we key the rendering on) from a display
1483
+ * Checks if a given array of filter data can be neatly serialized into an URL query parameter, or if it should fall back to JSON+base64.
1484
+ * The requirements are either an array of strings, containing no reserved characters, or an array of arrays of strings, containing no reserved characters.
1485
+ * No deep or mixed nesting levels are supported.
669
1486
  */
670
- function $a5871dacf261adf8$export$548d053aba053d79(display) {
671
- if ("variant_index" in display) {
672
- const actual_display = display.variant_displays[display.variant_index];
673
- return actual_display.product_id;
1487
+ function $1ab22f2cd39b3061$var$array_is_serializable(array, is_root = true) {
1488
+ if (array.every(item => Array.isArray(item))) {
1489
+ if (!is_root)
1490
+ // Deeply nested arrays are not supported, but also don't exist as filters (yet)
1491
+ return false;
1492
+ return array.every(item => $1ab22f2cd39b3061$var$array_is_serializable(item, false));
674
1493
  }
675
- return display.product_id;
1494
+ if (array.some(item => typeof item !== "string"))
1495
+ // Numbers are not supported, since 1 and "1" would encode to the same thing
1496
+ return false;
1497
+ // Encoding reserved characters is not supported
1498
+ return !array.some(item => item.includes($1ab22f2cd39b3061$var$array_item_delimiter) || item.includes($1ab22f2cd39b3061$var$string_item_delimiter) || item === $1ab22f2cd39b3061$var$empty_item_replacement);
676
1499
  }
677
- let $a73063cc642f3e5f$var$printedCloneError = false;
678
- function $a73063cc642f3e5f$export$7f8bd308237ab5a5(get_displays_) {
679
- const displays_by_key_ = $5vyXB$solidjs.createMemo(() => {
680
- const displays = get_displays_();
681
- // We key by product_id because that's what can be used to uniquely identify products
682
- // This way <For> can optimize the rendering
683
- const map = new Map();
684
- for (let i = 0; i < displays.length; i++) {
685
- const display = displays[i];
686
- const product_id = $a5871dacf261adf8$export$548d053aba053d79(display);
687
- map.set(product_id, display);
688
- }
689
- return map;
690
- });
691
- return displays_by_key_;
1500
+ /**
1501
+ * Human readable string[] or string[][] serialization for URLs.
1502
+ * @param array
1503
+ * @returns
1504
+ */
1505
+ function $1ab22f2cd39b3061$var$encode_array(array) {
1506
+ const is_nested = array.every(item => Array.isArray(item));
1507
+ if (is_nested) return array.map($1ab22f2cd39b3061$var$encode_array).join($1ab22f2cd39b3061$var$array_item_delimiter) + $1ab22f2cd39b3061$var$array_item_delimiter; // Nested arrays require a suffix to close nesting levels
1508
+ return array.map(item => item === "" ? $1ab22f2cd39b3061$var$empty_item_replacement : item).join($1ab22f2cd39b3061$var$string_item_delimiter);
692
1509
  }
693
- const $a73063cc642f3e5f$var$result_ids = ["search_result_id", "product_listing_result_id", "recommendation_id"];
694
- function $a73063cc642f3e5f$export$43f0fb951fcb0c54({
695
- displays_by_key_: displays_by_key_,
696
- merchant_: merchant_,
697
- market_: market_,
698
- product_card_template_: product_card_template_,
699
- do_per_elements_: do_per_elements_,
700
- content_blocks_: content_blocks_
701
- }) {
702
- return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.For), {
703
- get each() {
704
- return [...displays_by_key_().keys()];
705
- },
706
- children: (product_id, index) => {
707
- const owner = $5vyXB$solidjs.getOwner();
708
- const possible_content_block = $5vyXB$solidjs.createMemo(() => content_blocks_?.()?.()?.[index()]);
709
- const display_accessor = $5vyXB$solidjs.createMemo(prev => {
710
- const new_display = displays_by_key_().get(product_id);
711
- if (prev && $a73063cc642f3e5f$var$deep_equal(prev, new_display))
712
- // 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.
713
- // This doesn't work if people mutate the displays from within the template but we hope they don't
714
- // (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)
715
- return prev;
716
- return new_display;
717
- });
718
- const [product_card_resource] = $5vyXB$solidjs.createResource(() => [merchant_(), market_(), display_accessor()],
719
- // re-render when the reference to the display object changes or the merchant or market changes
720
- // (We don't want to re-render if nothing has changed)
721
- ([merchant, market, display]) => {
722
- // It's easy for merchants to accidentally mutate the display or some sub-object thereof
723
- // We had a case on singular where they popped an image url and due to use caching after some time there was no image
724
- // Attempt cloning the displays if possible (99.9% of the cases probably) and if not, just use the original display
725
- try {
726
- display = structuredClone(display);
727
- } catch (e) {
728
- if (!$a73063cc642f3e5f$var$printedCloneError) {
729
- $a73063cc642f3e5f$var$printedCloneError = true;
730
- $5vyXB$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);
731
- }
732
- }
733
- return product_card_template_(display, {
734
- set_on_index_change: fn => $5vyXB$solidjs.runWithOwner(owner, () => $5vyXB$solidjs.createEffect(() => fn(index()))),
735
- merchant: merchant,
736
- market: market // recommendation_grid can provide a sneaky undefined here just FYI
737
- });
738
- });
739
-
740
- const node_accessor = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(product_card_resource);
741
- $5vyXB$solidjs.createEffect(() => {
742
- const product_card_nodes = node_accessor();
743
- const display = display_accessor();
744
- const elements = [];
745
- for (let i = 0; i < product_card_nodes.length; i++) {
746
- const element = product_card_nodes[i];
747
- if (!(element instanceof Element)) continue;
748
- elements.push(element);
749
- // Add tracking ids
750
- if (!(element instanceof HTMLElement)) continue; // Apparently only HTMLElements have dataset
751
- for (let i = 0; i < $a73063cc642f3e5f$var$result_ids.length; i++) {
752
- const id = $a73063cc642f3e5f$var$result_ids[i];
753
- const value = display[id];
754
- if (value) Object.assign(element.dataset, $5vyXB$depictaiutilishared.camelCasifyObject({
755
- [id]: value
756
- }));
757
- }
758
- }
759
- do_per_elements_?.(elements, index);
760
- });
761
- return [
762
- // Show content block before product card, so it's *at* that index
763
- possible_content_block, product_card_resource]; // https://github.com/solidjs/solid/releases/tag/v1.7.0
764
- }
765
- });
1510
+ function $1ab22f2cd39b3061$var$decode_array(encoded_array) {
1511
+ const is_nested = encoded_array.includes($1ab22f2cd39b3061$var$array_item_delimiter);
1512
+ if (is_nested) return encoded_array.split($1ab22f2cd39b3061$var$array_item_delimiter).filter(s => s !== "") // Remove empty segments, caused by trailing delimiter
1513
+ .map($1ab22f2cd39b3061$var$decode_array);
1514
+ return encoded_array.split($1ab22f2cd39b3061$var$string_item_delimiter).filter(s => s !== "") // Remove empty segments, caused by trailing delimiter in the single item special case
1515
+ .map(item => item === $1ab22f2cd39b3061$var$empty_item_replacement ? "" : item);
766
1516
  }
767
- // source: https://medium.com/@pancemarko/deep-equality-in-javascript-determining-if-two-objects-are-equal-bf98cf47e934
768
- function $a73063cc642f3e5f$var$deep_equal(obj1, obj2) {
769
- if (obj1 === obj2) return true;
770
- if (Array.isArray(obj1) && Array.isArray(obj2)) {
771
- if (obj1.length !== obj2.length) return false;
772
- return obj1.every((elem, index) => {
773
- return $a73063cc642f3e5f$var$deep_equal(elem, obj2[index]);
774
- });
1517
+ function $1ab22f2cd39b3061$var$encode_filter_data(op, data) {
1518
+ if (data === "true")
1519
+ // boolean encoding
1520
+ return "1";
1521
+ if (data === "false")
1522
+ // boolean encoding
1523
+ return "0";
1524
+ const data_is_array = Array.isArray(data);
1525
+ if (op === "inrange" && data_is_array && data.every(item => typeof item === "number"))
1526
+ // numeric range filter encoding
1527
+ return data.join($1ab22f2cd39b3061$var$range_delimiter);
1528
+ if (data_is_array && $1ab22f2cd39b3061$var$array_is_serializable(data)) {
1529
+ const encoded_data = $1ab22f2cd39b3061$var$encode_array(data);
1530
+ if (!encoded_data.includes($1ab22f2cd39b3061$var$array_item_delimiter) && !encoded_data.includes($1ab22f2cd39b3061$var$string_item_delimiter))
1531
+ // A string[] with only one item will encode without delimiters, which is indistinguishable from a plain string during decoding
1532
+ // In that case we add a delimiter suffix at the end
1533
+ return encoded_data + $1ab22f2cd39b3061$var$string_item_delimiter;
1534
+ return encoded_data;
775
1535
  }
776
- if (typeof obj1 === "object" && typeof obj2 === "object" && obj1 !== null && obj2 !== null) {
777
- if (Array.isArray(obj1) || Array.isArray(obj2)) return false;
778
- const keys1 = Object.keys(obj1);
779
- const keys2 = Object.keys(obj2);
780
- if (keys1.length !== keys2.length || !keys1.every(key => keys2.includes(key))) return false;
781
- for (const key in obj1) {
782
- if ($a73063cc642f3e5f$var$result_ids.includes(key)) continue; // ignore keys changing with every request
783
- const isEqual = $a73063cc642f3e5f$var$deep_equal(obj1[key], obj2[key]);
784
- if (!isEqual) return false;
785
- }
786
- return true;
1536
+ // Fallback encoding
1537
+ return $5vyXB$depictaiutilishared.base64_encode_unicode(JSON.stringify(data));
1538
+ }
1539
+ function $1ab22f2cd39b3061$var$decode_filter_data(op, encoded_data) {
1540
+ if (encoded_data === "1") return "true";
1541
+ if (encoded_data === "0") return "false";
1542
+ if (op === "inrange" && encoded_data.includes($1ab22f2cd39b3061$var$range_delimiter)) return encoded_data.split($1ab22f2cd39b3061$var$range_delimiter).map(x => parseFloat(x));
1543
+ if (encoded_data.includes($1ab22f2cd39b3061$var$string_item_delimiter) || encoded_data.includes($1ab22f2cd39b3061$var$array_item_delimiter)) return $1ab22f2cd39b3061$var$decode_array(encoded_data);
1544
+ try {
1545
+ return JSON.parse($5vyXB$depictaiutilishared.base64_decode_unicode(encoded_data));
1546
+ } catch (e) {
1547
+ $5vyXB$depictaiutilishared.dlog("Failed to fallback parse filter data", op, encoded_data, e);
787
1548
  }
788
- return false;
1549
+ return null;
789
1550
  }
790
-
791
- // Errors caused by SDK consuming code interfacing with the SDK, not the SDK itself or other Depict packages
792
- class $7dd1edb2ee2b43ad$export$e1d52e4f0c7557a1 extends Error {}
793
- class $7dd1edb2ee2b43ad$export$aa14a9f43128f61f extends $7dd1edb2ee2b43ad$export$e1d52e4f0c7557a1 {
794
- constructor(templateError) {
795
- super("Uncaught error in product card template", {
796
- cause: templateError
797
- });
1551
+ function $1ab22f2cd39b3061$export$58aa3f171519b6d7(filters, search_params, filter_query_param_prefix) {
1552
+ for (const filter of filters) {
1553
+ const {
1554
+ field: field,
1555
+ op: op,
1556
+ data: data
1557
+ } = filter;
1558
+ const encoded_data = $1ab22f2cd39b3061$var$encode_filter_data(op, data);
1559
+ search_params.set(filter_query_param_prefix + field + $1ab22f2cd39b3061$var$op_to_token(op), encoded_data);
798
1560
  }
799
1561
  }
800
- const $edafe91daf3091d7$var$_tmpl$ = ["<div", ' class="', '"><!--$-->', "<!--/--><!--$-->", "<!--/--></div>"];
801
- function $edafe91daf3091d7$export$b69d0d92862de18b(props) {
802
- return $5vyXB$solidjs.ErrorBoundary({
803
- fallback(err, retry) {
804
- const {
805
- message_: message_,
806
- severity_: severity_
807
- } = props;
808
- let message = message_;
809
- if (err instanceof (0, $7dd1edb2ee2b43ad$export$aa14a9f43128f61f)) {
810
- console.error(err.cause);
811
- message = `${message}: ${err.message}`;
812
- } else $5vyXB$depictaiutilishared.report([err, message_], severity_);
813
- return $5vyXB$solidjsweb.ssr($edafe91daf3091d7$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.ssrClassList(Object.fromEntries(props.class_list_?.map(c => [c, true]) || [])), $5vyXB$solidjsweb.escape(message), $5vyXB$solidjsweb.escape(props.on_error_?.(retry)));
814
- },
815
- get children() {
816
- return props.children;
1562
+ function $1ab22f2cd39b3061$export$f934fa24c3a86811(search_params, filter_query_param_prefix) {
1563
+ const found_filters = [];
1564
+ for (const key of search_params.keys()) {
1565
+ // Allow for backwards compatibility with the old filter query param prefix
1566
+ let chosen_prefix = filter_query_param_prefix;
1567
+ if (!key.startsWith(chosen_prefix)) {
1568
+ chosen_prefix = $1ab22f2cd39b3061$var$legacy_filter_prefix;
1569
+ if (!key.startsWith(chosen_prefix)) continue;
817
1570
  }
818
- });
1571
+ const encoded_data = search_params.get(key);
1572
+ if (!encoded_data) continue;
1573
+ const [op, token] = Object.entries($1ab22f2cd39b3061$var$operator_map).find(([, token]) => key.endsWith(token)) || [$1ab22f2cd39b3061$var$fallback_operator, $1ab22f2cd39b3061$var$fallback_token];
1574
+ const data = $1ab22f2cd39b3061$var$decode_filter_data(op, encoded_data);
1575
+ if (!data) continue;
1576
+ const field = key.slice(chosen_prefix.length, token ? -token.length : undefined);
1577
+ found_filters.push({
1578
+ field: field,
1579
+ op: op,
1580
+ data: data
1581
+ });
1582
+ }
1583
+ return found_filters;
819
1584
  }
820
- const $f48d0fbb00835aaa$var$_tmpl$ = ["<div", ' class="', '">', "</div>"],
821
- $f48d0fbb00835aaa$var$_tmpl$2 = ["<style", ' type="text/css">', "</style>"];
822
- function $f48d0fbb00835aaa$export$d21e32dfedac04be(props) {
823
- const container_class = "x" + $5vyXB$solidjs.createUniqueId();
824
- const container_element_ = $5vyXB$solidjsweb.ssrElement("div", $5vyXB$solidjsweb.mergeProps(() => props.element_attributes, {
825
- classList: {
826
- [container_class]: true
827
- }
828
- }), () => $5vyXB$solidjsweb.escape(props.children), true); // Don't want this in the error boundary below, it should only be for the actual layouting
829
- return $5vyXB$solidjsweb.createComponent((0, $edafe91daf3091d7$export$b69d0d92862de18b), {
830
- get message_() {
831
- return "Failed calculating " + props.layout + " layout";
832
- },
833
- severity_: "error",
834
- get children() {
835
- return $f48d0fbb00835aaa$export$445d8d3f5f706a40(props, container_element_, false, container_class);
1585
+ function $1ab22f2cd39b3061$export$62acb285a7579555(sorting, search_params, sorting_query_param) {
1586
+ if (!sorting) return;
1587
+ const {
1588
+ field: field,
1589
+ order: order
1590
+ } = sorting;
1591
+ const ascending = order === "asc";
1592
+ search_params.set(sorting_query_param, field + (ascending ? $1ab22f2cd39b3061$var$ascending_token : $1ab22f2cd39b3061$var$descending_token));
1593
+ }
1594
+ function $1ab22f2cd39b3061$export$766e9676e74997d3(search_params, sorting_query_param_) {
1595
+ const encoded_sorting = search_params.get(sorting_query_param_);
1596
+ if (!encoded_sorting) return;
1597
+ if (encoded_sorting.endsWith($1ab22f2cd39b3061$var$ascending_token)) return {
1598
+ field: encoded_sorting.slice(0, -$1ab22f2cd39b3061$var$ascending_token.length),
1599
+ order: "asc"
1600
+ };
1601
+ if (encoded_sorting.endsWith($1ab22f2cd39b3061$var$descending_token)) return {
1602
+ field: encoded_sorting.slice(0, -$1ab22f2cd39b3061$var$descending_token.length),
1603
+ order: "desc"
1604
+ };
1605
+ $5vyXB$depictaiutilishared.dlog("Invalid sorting query param value", encoded_sorting);
1606
+ return;
1607
+ }
1608
+ function $1ab22f2cd39b3061$export$916e6850778505f6(search_params, filter_query_param_prefix, sorting_query_param) {
1609
+ // We'll be modifying the URLSearchParams object, so we need to make a copy of the keys first
1610
+ const keys = [...search_params.keys()];
1611
+ for (const key of keys) if (key.startsWith(filter_query_param_prefix) || key === sorting_query_param || key.startsWith($1ab22f2cd39b3061$var$legacy_filter_prefix)) search_params.delete(key);
1612
+ }
1613
+ const $1ab22f2cd39b3061$export$cf5feb2102aec7f2 = "went_sideways_clear_filters";
1614
+ function $1ab22f2cd39b3061$export$43cd1e747fecd42e({
1615
+ to_url_: to_url_,
1616
+ set_clearing_flag_: set_clearing_flag_,
1617
+ from_search_params_ = new URLSearchParams(location.search),
1618
+ sorting_query_param_: sorting_query_param_,
1619
+ filter_query_param_prefix_: filter_query_param_prefix_
1620
+ }) {
1621
+ if (!to_url_) return to_url_;
1622
+ const was_url_object = to_url_ instanceof URL;
1623
+ const url_object = was_url_object ? to_url_ : new URL(to_url_, location.origin);
1624
+ const {
1625
+ searchParams: searchParams
1626
+ } = url_object;
1627
+ if (set_clearing_flag_) searchParams.set($1ab22f2cd39b3061$export$cf5feb2102aec7f2, "true");
1628
+ if (from_search_params_.has(sorting_query_param_)) searchParams.set(sorting_query_param_, from_search_params_.get(sorting_query_param_));
1629
+ for (const key of from_search_params_.keys()) if (key.startsWith(filter_query_param_prefix_)) searchParams.set(key, from_search_params_.get(key));
1630
+ if (was_url_object) return url_object;
1631
+ return url_object.href;
1632
+ }
1633
+ const $93304d59a9747aa6$var$_tmpl$ = ["<div", ' style="', '"', "></div>"];
1634
+ function $93304d59a9747aa6$export$94026ee33dbabc26(props) {
1635
+ return $5vyXB$solidjsweb.ssr($93304d59a9747aa6$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.ssrStyle(`position:relative;width:100%;padding-bottom:${1 / props.aspectRatio * 100}%`), $5vyXB$solidjsweb.ssrAttribute("class", $5vyXB$solidjsweb.escape(props.class, true), false));
1636
+ }
1637
+ function $19950faaac026e09$export$e6fffe67d4cdd848(whatToWatch) {
1638
+ const [size, setSize] = $5vyXB$solidjs.createSignal(0);
1639
+ const resizeObserver = new ResizeObserver($5vyXB$depictaiutilishared.catchify(records => {
1640
+ for (let j = 0; j < records.length; j++) {
1641
+ const {
1642
+ width: width
1643
+ } = records[j].contentRect;
1644
+ if (!width) continue;
1645
+ // add extra 5% just in case. + safari is (in some cases) acting a bit questionable and needs a third extra to fill the set width
1646
+ const new_size = width * 1.05 * ((0, $5vyXB$depictaiutilishared.is_safari) ? 4 / 3 : 1);
1647
+ setSize(Math.round(new_size));
836
1648
  }
1649
+ }));
1650
+ // 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.
1651
+ // It doesn't seem to work even when waiting for it to be in the DOM, also wait an animation frame
1652
+ const disconnect = (0, $5vyXB$depictaiutilishared.observer).onexists(whatToWatch, ({
1653
+ element: element
1654
+ }) => requestAnimationFrame($5vyXB$depictaiutilishared.catchify(() => resizeObserver.observe(element))));
1655
+ $5vyXB$solidjs.onCleanup(() => {
1656
+ resizeObserver.disconnect();
1657
+ disconnect();
837
1658
  });
1659
+ return size;
838
1660
  }
839
- function $f48d0fbb00835aaa$export$445d8d3f5f706a40(props, container_element, insert_after_container = false, container_class) {
840
- if (!container_class) {
841
- // only try to add if it wasn't provided, so that we have a code path without classList when doing SSR
842
- container_class = $5vyXB$depictaiutilishared.make_random_classname();
843
- container_element.classList.add(container_class);
844
- }
845
- // Copy of Layout from utilishared but using solid-js signals instead of async iterable IPNS
846
- const show_all_rows = $5vyXB$solidjs.createMemo(() => props.rows === "all");
847
- const rows_or_empty_object = $5vyXB$solidjs.createMemo(() => show_all_rows() ? {} : props.rows);
848
- const view_more_button_elements = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52($5vyXB$solidjs.createMemo(() => rows_or_empty_object().button));
849
- const view_less_button_elements = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52($5vyXB$solidjs.createMemo(() => rows_or_empty_object().view_less_button));
850
- const have_a_view_more_button = $5vyXB$solidjs.createMemo(() => {
851
- const button = view_more_button_elements();
852
- return !(!button || Array.isArray(button) && !button.length);
1661
+ const $19950faaac026e09$var$onIdleFunctionsSymbol = /*@__PURE__*/Symbol("onIdleFunctions");
1662
+ function $19950faaac026e09$export$6e5611bc7e57e477(props) {
1663
+ // Enable reactive props
1664
+ const otherOptions = $5vyXB$solidjs.createMemo(() => {
1665
+ const cloned_props = {
1666
+ ...props
1667
+ };
1668
+ delete cloned_props.resolutions;
1669
+ // @ts-ignore
1670
+ delete cloned_props.size;
1671
+ // @ts-ignore
1672
+ delete cloned_props.src;
1673
+ return cloned_props;
853
1674
  });
854
- const have_a_view_less_button = $5vyXB$solidjs.createMemo(() => {
855
- const button = view_less_button_elements();
856
- return !(!button || Array.isArray(button) && !button.length);
1675
+ const src_options = $5vyXB$solidjs.createMemo(() => {
1676
+ const src = new URL(props.src, location.origin);
1677
+ const fallback_src = $19950faaac026e09$var$generateImageUrl(src, 400);
1678
+ const srcset = $19950faaac026e09$var$make_srcset(src, props.resolutions || [64, 128, 256, 300, 400, 512, 768, 1024, 1280, 1536, 2048, 4096]);
1679
+ return {
1680
+ src: fallback_src,
1681
+ srcset: srcset
1682
+ };
857
1683
  });
858
- const [get_styling, set_styling] = $5vyXB$solidjs.createSignal();
859
- const selector_beginning = `.depict .${container_class}>`; // class so ppl can have id if needed
860
- const [get_children_count, set_children_count] = $5vyXB$solidjs.createSignal(0);
861
- const update_children_count = () => (0, $5vyXB$solidjsweb.isServer) ? 20 : set_children_count(container_element.children.length);
862
- const col_styling = $5vyXB$solidjs.createMemo(() => $5vyXB$depictaiutilishared.n_col_styling_with_dist(selector_beginning, props.grid_spacing, props.cols_at_size, props.layout, props.override_vertical_spacing));
863
- const default_currently_visible_signal = $5vyXB$solidjs.createSignal($5vyXB$solidjs.untrack(() => rows_or_empty_object().start_rows ?? 1)); // 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
864
- const rows_visible_signal = $5vyXB$solidjs.createMemo(() => rows_or_empty_object().currently_visible || default_currently_visible_signal);
865
- const get_rows_visible = $5vyXB$solidjs.createMemo(() => rows_visible_signal()[0]());
866
- const set_rows_visible = $5vyXB$solidjs.createMemo(() => rows_visible_signal()[1]);
867
- const view_more_button_class = "m" + $5vyXB$solidjs.createUniqueId();
868
- const view_less_button_class = "l" + $5vyXB$solidjs.createUniqueId(); // https://github.com/solidjs/solid-docs/issues/263#issuecomment-1622388079
869
- const view_more_button_container = $5vyXB$solidjs.createMemo(() => have_a_view_more_button() && $5vyXB$solidjsweb.ssr($f48d0fbb00835aaa$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), `load-more-container ${$5vyXB$solidjsweb.escape(view_more_button_class, true)}`, $5vyXB$solidjsweb.escape(rows_or_empty_object().button)));
870
- // 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
871
- const view_less_button_container = $5vyXB$solidjs.createMemo(() => have_a_view_less_button() && $5vyXB$solidjsweb.ssr($f48d0fbb00835aaa$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), `load-less-container ${$5vyXB$solidjsweb.escape(view_less_button_class, true)}`, $5vyXB$solidjsweb.escape(rows_or_empty_object().view_less_button)));
872
- const [force_style_update, set_force_style_update] = $5vyXB$solidjs.createSignal("");
873
- $5vyXB$solidjs.createComputed(() => {
874
- // Make sure we don't have more rows visible than max_rows (this could happen by max_rows being decreased)
875
- const rows_visible = get_rows_visible();
876
- const max_rows = rows_or_empty_object().max_rows;
877
- if (!isNaN(max_rows) && max_rows >= 0 && rows_visible > max_rows) set_rows_visible()(max_rows);
1684
+ // Work around https://github.com/solidjs/solid/issues/1828
1685
+ const img = new Image(); // Need to use new Image or browser might not start loading image before it's in the DOM
1686
+ const [hasSetSize, setHasSetSize] = $5vyXB$solidjs.createSignal(false);
1687
+ const [hasDecoded, setHasDecoded] = $5vyXB$solidjs.createSignal(false);
1688
+ const sizePX = $5vyXB$solidjs.createMemo(() => `${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
1689
+ const listingContext = $84798aaa863a4909$export$8d0c4fdbb05a2f2e();
1690
+ // 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
1691
+ // Happened on singular, they have some weird observer (+we also have one but ours is at least 3x more efficient)
1692
+ const executeWhenIdleBatched = fn => {
1693
+ if (typeof requestIdleCallback !== "function") return setTimeout(fn); // Old browsers don't get optimisation
1694
+ const existingStack = listingContext?.[$19950faaac026e09$var$onIdleFunctionsSymbol];
1695
+ if (existingStack) return existingStack.add(fn);
1696
+ const newStack = new Set([fn]);
1697
+ if (listingContext) listingContext[$19950faaac026e09$var$onIdleFunctionsSymbol] = newStack;
1698
+ const processStackWhenIdle = () => requestIdleCallback(deadline => {
1699
+ const start = performance.now();
1700
+ const thirdDeadlineTime = deadline.timeRemaining() / 3; // observers coming after this take up 2-3x the time so don't use all of it
1701
+ for (const fn of newStack) {
1702
+ newStack.delete(fn);
1703
+ fn();
1704
+ const timeTaken = performance.now() - start;
1705
+ if ((!deadline.timeRemaining() || timeTaken > thirdDeadlineTime) && newStack.size) {
1706
+ // There's still work to be done but no time, so schedule another idle callback
1707
+ processStackWhenIdle();
1708
+ return;
1709
+ }
1710
+ }
1711
+ // Stack is empty
1712
+ if (listingContext) delete listingContext[$19950faaac026e09$var$onIdleFunctionsSymbol];
1713
+ }, {
1714
+ timeout: 15000
1715
+ } // 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
1716
+ );
1717
+
1718
+ processStackWhenIdle();
1719
+ };
1720
+ let sizeSetFastPath = false;
1721
+ let hasDecodedFastPath = false;
1722
+ let timeoutSet = false;
1723
+ let gotCleanedUp = false;
1724
+ $5vyXB$solidjs.onCleanup(() => gotCleanedUp = true);
1725
+ $5vyXB$solidjsweb.spread(img, $5vyXB$solidjs.mergeProps(otherOptions), false, true);
1726
+ $5vyXB$solidjs.createEffect(() => {
1727
+ if (!props.size()) return; // wait until we have a size
1728
+ if (timeoutSet) return;
1729
+ const handler = $5vyXB$depictaiutilishared.catchify(() => {
1730
+ if (gotCleanedUp) return;
1731
+ img.sizes = sizePX(); // use latest available value of props.size
1732
+ if (!sizeSetFastPath) {
1733
+ setHasSetSize(true);
1734
+ sizeSetFastPath = true;
1735
+ }
1736
+ timeoutSet = false;
1737
+ });
1738
+ // Throttle the updating of sizes to avoid unnecessary image re-fetches during resize
1739
+ // And also because we first set src after sizes has been set, wait with loading and decoding images until browser is idle
1740
+ // This greatly improves performance when loading (more) products
1741
+ // See https://depictaiworkspace.slack.com/archives/C05NJ0K3WRL/p1698220617663139
1742
+ executeWhenIdleBatched(handler);
1743
+ timeoutSet = true;
878
1744
  });
879
- $5vyXB$solidjs.createEffect(() => set_force_style_update(" ")); // force style update after hydration due to https://discord.com/channels/722131463138705510/722167424186843267/1151544212517552168
880
- $5vyXB$solidjs.createRenderEffect(() => {
881
- // Be careful to only read show_all_rows in here (ofc doesn't apply to nested effects)
882
- if (show_all_rows()) {
883
- // no view more functionality requested
884
- set_styling(() => col_styling);
1745
+ $5vyXB$solidjs.createEffect(() => {
1746
+ if (!props.size() || !hasSetSize()) return; // If size isn't known or set, don't assign src yet since it would cause the most low res image to load
1747
+ Object.assign(img, src_options());
1748
+ // Add to DOM once decoded to not require/block any paints before image has completed loading and avoid showing broken image symbol
1749
+ // We can do this because there has to be a container around us giving us a size
1750
+ // No need to listen if we're already in the DOM
1751
+ if (hasDecodedFastPath) return;
1752
+ if (props.loading === "lazy") {
1753
+ // For lazy loading there's no decoding to wait for as it only occurs when the image is visible
1754
+ // Make sure src is set before we put the image into the DOM though so no broken image symbol is shown
1755
+ setHasDecoded(true);
1756
+ hasDecodedFastPath = true;
885
1757
  return;
886
1758
  }
887
- update_children_count();
888
- if (!(0, $5vyXB$solidjsweb.isServer)) {
889
- const mutation_observer = new MutationObserver($5vyXB$depictaiutilishared.catchify(update_children_count));
890
- mutation_observer.observe(container_element, {
891
- childList: true
892
- });
893
- $5vyXB$solidjs.onCleanup(() => mutation_observer.disconnect());
894
- }
895
- set_styling(
896
- // this is needed because solid will think that the memo-accessor is a setter function otherwise
897
- () => $5vyXB$solidjs.createMemo(() => {
898
- const {
899
- rows_per_click: rows_per_click,
900
- max_rows = -1,
901
- start_rows: start_rows
902
- } = rows_or_empty_object();
903
- const rows_visible = get_rows_visible();
904
- const children_count = get_children_count();
905
- return force_style_update() + col_styling() + props.cols_at_size.map(options => {
906
- const [recs_per_row, min, max] = options;
907
- let should_hide_view_more_button;
908
- let visible_recs;
909
- if (props.disable_partial_rows) {
910
- visible_recs = $5vyXB$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible, children_count, options);
911
- const visible_recs_next_show_more = $5vyXB$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible + (rows_per_click || 0),
912
- // Should this really be zero when we default rows_per_click to 1?
913
- children_count, options);
914
- should_hide_view_more_button = visible_recs === visible_recs_next_show_more;
915
- } else {
916
- visible_recs = $5vyXB$depictaiutilishared.layout_get_total_rec_amount_for_row(rows_visible, options);
917
- should_hide_view_more_button = visible_recs >= children_count;
918
- }
919
- const should_hide_button_final = should_hide_view_more_button || max_rows !== -1 && rows_visible >= max_rows;
920
- // 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
921
- 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;
922
- return `${$5vyXB$depictaiutilishared.layout_media_query_header(min, max)}{${selector_beginning}:nth-child(n+${visible_recs + 1}){display:none}${props.layout == "slider" ? `${selector_beginning}:nth-child(n+${visible_recs}){margin-right:0}` : ""}${should_hide_button_final ? `.depict .${view_more_button_class}{display:none!important}` : ``}${should_hide_view_less_button ? `.depict .${view_less_button_class}{display:none!important}` : ``}}`;
923
- }).join("");
924
- }));
1759
+ img.decode().catch(e => $5vyXB$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"
1760
+ .then(async () => {
1761
+ // Also wait with inserting image (i.e. paint) until browser is idle
1762
+ await new Promise(r => executeWhenIdleBatched(r));
1763
+ if (gotCleanedUp) return;
1764
+ setHasDecoded(true);
1765
+ hasDecodedFastPath = true;
1766
+ });
925
1767
  });
926
- const style_element = $5vyXB$solidjsweb.ssr($f48d0fbb00835aaa$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), get_styling); // need to create this after set_styling has been called or else there will be no styling in the SSR'd output
927
- if (insert_after_container) container_element.after(style_element);
928
- return [container_element, view_more_button_container(), view_less_button_container(), style_element];
929
- }
930
- const $363ce4d1d71041aa$var$_tmpl$ = ["<h2", ' class="recs-title">', "</h2>"];
931
- function $363ce4d1d71041aa$export$d41d19e89346fa2({
932
- recommendations_resource_: recommendations_resource_,
933
- product_card_template_: product_card_template_,
934
- layout_options_: layout_options_,
935
- merchant_: merchant_,
936
- market_: market_,
937
- title_: title_
938
- }) {
939
- const is_showing_something = $5vyXB$solidjs.createMemo(() => recommendations_resource_.loading || recommendations_resource_()?.length);
940
- const title = $5vyXB$solidjs.createMemo(() => title_?.()); // In case getter/accessor creates elements, don't create them twice
941
- const num_placeholders_ = () => 20;
942
- const slider = [$5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
943
- get when() {
944
- return title();
945
- },
946
- get children() {
947
- return $5vyXB$solidjsweb.ssr($363ce4d1d71041aa$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(title()));
948
- }
949
- }), $5vyXB$solidjsweb.createComponent((0, $a0e53f99354809d9$export$6649caad96ef8870), {
950
- arrow_height_: 25,
951
- arrow_width_: 12.5,
952
- disable_fading_: true,
953
- slider_ref_: slider => {
954
- const {
955
- insert_here: insert_here
956
- } = slider;
957
- const Layout = props => $f48d0fbb00835aaa$export$445d8d3f5f706a40(props, insert_here, true);
958
- // Do like this, so we don't have to call mergeProps ourselves
959
- $5vyXB$solidjsweb.createComponent(Layout, $5vyXB$solidjsweb.mergeProps({
960
- rows: "all",
961
- layout: "slider"
962
- }, layout_options_));
963
- $5vyXB$depictaiutilishared.slider_fractional_factory(0, 0.75).constructor_plugin.call(slider, {}); // enable fractional scrolling
964
- insert_here.before($fc23d7668ae0011d$export$a2cc176055f8f08());
965
- },
966
- get children() {
967
- return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Suspense), {
968
- get fallback() {
969
- return $0caf87eaa19079da$export$f33414a4df0afd3f({
970
- num_placeholders_: num_placeholders_,
971
- product_card_template_: product_card_template_
972
- });
973
- },
974
- get children() {
975
- return (() => {
976
- // IIFE to make sure we access both the recommendations_resource and the resources containing the product card rendering results themselves within the Suspense boundary
977
- const displays_by_key_ = $a73063cc642f3e5f$export$7f8bd308237ab5a5($5vyXB$solidjs.createMemo(() => recommendations_resource_() || []));
978
- return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
979
- displays_by_key_: displays_by_key_,
980
- merchant_: merchant_,
981
- market_: market_,
982
- product_card_template_: product_card_template_
983
- });
984
- })();
985
- }
986
- });
987
- }
988
- })];
989
1768
  return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
990
1769
  get when() {
991
- return is_showing_something();
1770
+ return hasDecoded();
992
1771
  },
993
- children: slider
1772
+ children: img
994
1773
  });
995
1774
  }
996
- function $95837413165cc2df$export$23fca46f3143581f(component, error_message) {
997
- const component_in_error_boundary = do_with_elements => {
998
- const error_boundary_wrapped = $edafe91daf3091d7$export$b69d0d92862de18b({
999
- severity_: "error",
1000
- message_: error_message,
1001
- get children() {
1002
- const elements = component();
1003
- do_with_elements?.(elements);
1004
- return elements;
1005
- }
1006
- });
1007
- // This might return an accessor, in that case we need to "unwrap" it since our SDK consumers expect HTML elements or arrays thereof
1008
- if (typeof error_boundary_wrapped === "function")
1009
- // @ts-ignore
1010
- return error_boundary_wrapped();
1011
- // On the server it returns a string, so we just return that
1012
- return error_boundary_wrapped;
1013
- };
1775
+ function $19950faaac026e09$var$make_srcset(url, resolutions) {
1776
+ return resolutions.map(width => `${$19950faaac026e09$var$generateImageUrl(url, width)} ${width}w`).join(", ");
1777
+ }
1778
+ function $19950faaac026e09$var$generateImageUrl(url, width) {
1779
+ // This function is quite slow, we maybe could do string concat with encodeURIComponent instead if shopify handles double width params well?
1780
+ url.searchParams.set("width", width);
1781
+ return url.href;
1782
+ }
1783
+ const $a33065cfed827fc0$var$backupSizeSignal = /*@__PURE__*/$5vyXB$solidjs.createSignal();
1784
+ const $a33065cfed827fc0$export$d7b7ab832c20e2f4 = /*@__PURE__*/Symbol("ShopifyContainedImage");
1785
+ function $a33065cfed827fc0$export$e4b984597b71e989(props) {
1786
+ const context = $84798aaa863a4909$export$8d0c4fdbb05a2f2e();
1787
+ if (context && !context[$a33065cfed827fc0$export$d7b7ab832c20e2f4])
1788
+ // create a signal that's the same for all items in this listing
1789
+ context[$a33065cfed827fc0$export$d7b7ab832c20e2f4] = $5vyXB$solidjs.createSignal();
1790
+ const [currentImageSize, setCurrentImageSize] = context?.[$a33065cfed827fc0$export$d7b7ab832c20e2f4] || $a33065cfed827fc0$var$backupSizeSignal; // use global fallback signal (might lead to blurry images) if no context is available
1791
+ const container = $5vyXB$solidjsweb.createComponent((0, $93304d59a9747aa6$export$94026ee33dbabc26), {
1792
+ get aspectRatio() {
1793
+ return props.aspectRatio;
1794
+ },
1795
+ get ["class"]() {
1796
+ return props.class;
1797
+ }
1798
+ });
1014
1799
  const owner = $5vyXB$solidjs.getOwner();
1015
- if (owner == null) return $5vyXB$solidjs.createRoot(dispose => {
1016
- // 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
1017
- return component_in_error_boundary(elements => {
1018
- const have_multiple = Array.isArray(elements);
1019
- if (have_multiple ? !elements?.length : !elements) return;
1020
- (0, $5vyXB$depictaiutilishared.observer).onremoved(have_multiple ? elements[0] : elements, ({
1021
- element: element
1022
- }) => {
1023
- if (document.documentElement.contains(element)) return; // If element has instantly been re-inserted, don't dispose
1024
- // See https://depictaiworkspace.slack.com/archives/C050GHEPBTR/p1695809102791259?thread_ts=1695106805.459729&cid=C050GHEPBTR
1025
- dispose();
1026
- });
1027
- });
1028
- });else
1029
- // we're already in a root so cleanups are handled
1030
- return component_in_error_boundary();
1800
+ let createdSizeAccessor = false;
1801
+ let wasCleanedUp = false;
1802
+ $5vyXB$solidjs.createEffect(() => {
1803
+ if (currentImageSize() || wasCleanedUp) return; // We get into the effect when onCleanup is called if we don't have wasCleanedUp
1804
+ // ensure we always have a size accessor
1805
+ // 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
1806
+ createdSizeAccessor = true;
1807
+ setCurrentImageSize(() => $5vyXB$solidjs.runWithOwner(owner, () => $19950faaac026e09$export$e6fffe67d4cdd848(container)));
1808
+ });
1809
+ $5vyXB$solidjs.onCleanup(() => {
1810
+ wasCleanedUp = true; // important to set this before the function call below and always, so the dead effects don't create dead size accessors
1811
+ if (!createdSizeAccessor) return;
1812
+ $5vyXB$depictaiutilishared.queueMacroTask(() => setCurrentImageSize(undefined)); // 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
1813
+ });
1814
+
1815
+ $5vyXB$solidjsweb.insert(container, $5vyXB$solidjsweb.createComponent((0, $19950faaac026e09$export$6e5611bc7e57e477), {
1816
+ style: "width: 100%; height: 100%; object-fit: contain; position: absolute; inset: 0;",
1817
+ get size() {
1818
+ return $5vyXB$solidjs.createMemo(() => currentImageSize()?.() || 0);
1819
+ },
1820
+ get src() {
1821
+ return props.src;
1822
+ },
1823
+ get alt() {
1824
+ return props.alt;
1825
+ }
1826
+ }));
1827
+ return container;
1031
1828
  }
1032
- const $72f96c4782db0b1b$var$_tmpl$ = ["<div", ' class="depict recommendations">', "</div>"];
1033
- function $72f96c4782db0b1b$export$9574e176201e5e8d(props) {
1034
- return $95837413165cc2df$export$23fca46f3143581f(() => {
1035
- const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
1036
- const {
1037
- grid_spacing: grid_spacing
1038
- } = props; // can be reactive
1039
- return typeof grid_spacing === "string" ? {
1040
- grid_spacing: grid_spacing
1041
- } : {
1042
- override_vertical_spacing: grid_spacing.vertical,
1043
- grid_spacing: grid_spacing.horizontal
1044
- };
1045
- });
1046
- const [recommendations_resource_] = $5vyXB$solidjs.createResource(() => props.recommendations, recs => recs);
1047
- return $5vyXB$solidjsweb.ssr($72f96c4782db0b1b$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $84798aaa863a4909$export$e68cff63f76bd15b), {
1048
- get children() {
1049
- return $363ce4d1d71041aa$export$d41d19e89346fa2({
1050
- product_card_template_: (...args) => props.product_card_template(...args),
1051
- recommendations_resource_: recommendations_resource_,
1052
- market_: () => props.market,
1053
- merchant_: () => props.merchant,
1054
- title_: () => props.title,
1055
- layout_options_: $5vyXB$solidjs.createMemo(() => ({
1056
- cols_at_size: $4e04be41243c3d80$export$6daf8749b65a1b77(props.cols_at_size),
1057
- ...grid_spacing_override()
1058
- }))
1059
- });
1060
- }
1061
- })));
1062
- }, "RecommendationSlider failed");
1829
+
1830
+ /** @jsxImportSource solid-js */
1831
+
1832
+ function $f13855d1b951b24a$export$ebdc3711f7e02ccd(what_to_watch) {
1833
+ const [width, setWidth] = $5vyXB$solidjs.createSignal();
1834
+ const resizeObserver = new ResizeObserver($5vyXB$depictaiutilishared.catchify(records => {
1835
+ for (let j = 0; j < records.length; j++) {
1836
+ const width = records[j].borderBoxSize?.[0]?.inlineSize ?? what_to_watch.getBoundingClientRect().width;
1837
+ setWidth(width);
1838
+ }
1839
+ }));
1840
+ // 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.
1841
+ // It doesn't seem to work even when waiting for it to be in the DOM, also wait an animation frame
1842
+ const disconnect = (0, $5vyXB$depictaiutilishared.observer).onexists(what_to_watch, ({
1843
+ element: element
1844
+ }) => requestAnimationFrame($5vyXB$depictaiutilishared.catchify(() => {
1845
+ const current_size = what_to_watch.getBoundingClientRect().width;
1846
+ if (current_size)
1847
+ // If element has size, set signal to that. ResizeObserver only triggers when the content is visible in some cases, but it might already have a size. This reduces size filter expanding animation jank in chrome.
1848
+ setWidth(current_size);
1849
+ resizeObserver.observe(element);
1850
+ })));
1851
+ $5vyXB$solidjs.onCleanup(() => {
1852
+ resizeObserver.disconnect();
1853
+ disconnect();
1854
+ });
1855
+ return width;
1063
1856
  }
1064
- const $b8e79813f4f7ebe4$var$_tmpl$ = ["<h2", ' class="recs-title">', "</h2>"],
1065
- $b8e79813f4f7ebe4$var$_tmpl$2 = ["<div", ' class="recommendation-grid"><!--$-->', "<!--/--><!--$-->", "<!--/--></div>"];
1066
- function $b8e79813f4f7ebe4$export$7da560f849543dff({
1857
+ const $363ce4d1d71041aa$var$_tmpl$ = ["<h2", ' class="recs-title">', "</h2>"];
1858
+ function $363ce4d1d71041aa$export$d41d19e89346fa2({
1067
1859
  recommendations_resource_: recommendations_resource_,
1068
1860
  product_card_template_: product_card_template_,
1069
1861
  layout_options_: layout_options_,
1070
- merchant_: merchant_,
1071
- market_: market_,
1072
- rows_object_: rows_object_,
1073
1862
  title_: title_
1074
1863
  }) {
1075
1864
  const is_showing_something = $5vyXB$solidjs.createMemo(() => recommendations_resource_.loading || recommendations_resource_()?.length);
1076
1865
  const title = $5vyXB$solidjs.createMemo(() => title_?.()); // In case getter/accessor creates elements, don't create them twice
1077
1866
  const num_placeholders_ = () => 20;
1078
- const elements = [$5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1867
+ const slider = [$5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1079
1868
  get when() {
1080
1869
  return title();
1081
1870
  },
1082
1871
  get children() {
1083
- return $5vyXB$solidjsweb.ssr($b8e79813f4f7ebe4$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(title()));
1872
+ return $5vyXB$solidjsweb.ssr($363ce4d1d71041aa$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(title()));
1084
1873
  }
1085
- }), $5vyXB$solidjsweb.ssr($b8e79813f4f7ebe4$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($fc23d7668ae0011d$export$a2cc176055f8f08()), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $f48d0fbb00835aaa$export$d21e32dfedac04be), $5vyXB$solidjsweb.mergeProps({
1086
- get rows() {
1087
- return rows_object_();
1874
+ }), $5vyXB$solidjsweb.createComponent((0, $a0e53f99354809d9$export$6649caad96ef8870), {
1875
+ arrow_height_: 25,
1876
+ arrow_width_: 12.5,
1877
+ disable_fading_: true,
1878
+ slider_ref_: slider => {
1879
+ const {
1880
+ insert_here: insert_here
1881
+ } = slider;
1882
+ const Layout = props => $f48d0fbb00835aaa$export$445d8d3f5f706a40(props, insert_here, true);
1883
+ // Do like this, so we don't have to call mergeProps ourselves
1884
+ $5vyXB$solidjsweb.createComponent(Layout, $5vyXB$solidjsweb.mergeProps({
1885
+ rows: "all",
1886
+ layout: "slider"
1887
+ }, layout_options_));
1888
+ $5vyXB$depictaiutilishared.slider_fractional_factory(0, 0.75).constructor_plugin.call(slider, {}); // enable fractional scrolling
1889
+ insert_here.before($fc23d7668ae0011d$export$a2cc176055f8f08());
1088
1890
  },
1089
- layout: "grid",
1090
- element_attributes: {
1091
- class: "cards"
1092
- }
1093
- }, layout_options_, {
1094
1891
  get children() {
1095
1892
  return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Suspense), {
1096
1893
  get fallback() {
@@ -1105,44 +1902,23 @@ function $b8e79813f4f7ebe4$export$7da560f849543dff({
1105
1902
  const displays_by_key_ = $a73063cc642f3e5f$export$7f8bd308237ab5a5($5vyXB$solidjs.createMemo(() => recommendations_resource_() || []));
1106
1903
  return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
1107
1904
  displays_by_key_: displays_by_key_,
1108
- merchant_: merchant_,
1109
- market_: market_,
1110
1905
  product_card_template_: product_card_template_
1111
1906
  });
1112
1907
  })();
1113
1908
  }
1114
1909
  });
1115
1910
  }
1116
- }))))];
1911
+ })];
1117
1912
  return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1118
1913
  get when() {
1119
1914
  return is_showing_something();
1120
1915
  },
1121
- children: elements
1916
+ children: slider
1122
1917
  });
1123
1918
  }
1124
- const $1f8dbf7e28b3eff2$var$_tmpl$ = ["<button", ' class="show-more major" type="button">', "</button>"],
1125
- $1f8dbf7e28b3eff2$var$_tmpl$2 = ["<div", ' class="depict plp recommendations">', "</div>"];
1126
- function $1f8dbf7e28b3eff2$export$9756467d34d91cdb(props) {
1919
+ const $72f96c4782db0b1b$var$_tmpl$ = ["<div", ' class="depict recommendations">', "</div>"];
1920
+ function $72f96c4782db0b1b$export$9574e176201e5e8d(props) {
1127
1921
  return $95837413165cc2df$export$23fca46f3143581f(() => {
1128
- const rows_object_ = $5vyXB$solidjs.createMemo(() => {
1129
- const {
1130
- view_more_button: view_more_button,
1131
- max_rows: max_rows
1132
- } = props;
1133
- if (!view_more_button) {
1134
- if (max_rows) return {
1135
- max_rows: max_rows
1136
- };
1137
- return "all";
1138
- }
1139
- return {
1140
- max_rows: max_rows,
1141
- start_rows: view_more_button.start_rows,
1142
- rows_per_click: view_more_button.rows_per_click ?? 2,
1143
- button: $5vyXB$solidjsweb.ssr($1f8dbf7e28b3eff2$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(view_more_button.text))
1144
- };
1145
- });
1146
1922
  const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
1147
1923
  const {
1148
1924
  grid_spacing: grid_spacing
@@ -1155,14 +1931,11 @@ function $1f8dbf7e28b3eff2$export$9756467d34d91cdb(props) {
1155
1931
  };
1156
1932
  });
1157
1933
  const [recommendations_resource_] = $5vyXB$solidjs.createResource(() => props.recommendations, recs => recs);
1158
- return $5vyXB$solidjsweb.ssr($1f8dbf7e28b3eff2$var$_tmpl$2, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $84798aaa863a4909$export$e68cff63f76bd15b), {
1934
+ return $5vyXB$solidjsweb.ssr($72f96c4782db0b1b$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $84798aaa863a4909$export$e68cff63f76bd15b), {
1159
1935
  get children() {
1160
- return $b8e79813f4f7ebe4$export$7da560f849543dff({
1161
- rows_object_: rows_object_,
1936
+ return $363ce4d1d71041aa$export$d41d19e89346fa2({
1162
1937
  product_card_template_: (...args) => props.product_card_template(...args),
1163
1938
  recommendations_resource_: recommendations_resource_,
1164
- market_: () => props.market,
1165
- merchant_: () => props.merchant,
1166
1939
  title_: () => props.title,
1167
1940
  layout_options_: $5vyXB$solidjs.createMemo(() => ({
1168
1941
  cols_at_size: $4e04be41243c3d80$export$6daf8749b65a1b77(props.cols_at_size),
@@ -1171,7 +1944,7 @@ function $1f8dbf7e28b3eff2$export$9756467d34d91cdb(props) {
1171
1944
  });
1172
1945
  }
1173
1946
  })));
1174
- }, "RecommendationGrid failed");
1947
+ }, "RecommendationSlider failed");
1175
1948
  }
1176
1949
  function $4b455f60dadde8b8$export$5bad61ecde080b1f(...params) {
1177
1950
  const {
@@ -1291,15 +2064,6 @@ function $d659702496cb72ea$export$a71e92cfbb498adc(props) {
1291
2064
  return $5vyXB$depictaiutilishared.standard_price_format(props.price_, price_formatting.places_after_comma_, price_formatting.decimal_places_delimiter_, price_formatting.thousands_delimiter_);
1292
2065
  });
1293
2066
  }
1294
- const $c77c68e559a1506c$var$_tmpl$ = '<path d="M11.669 10.531l9.156-9.156a.78.78 0 0 0 .237-.569c0-.221-.079-.412-.237-.569A.8.8 0 0 0 20.24 0a.77.77 0 0 0-.569.237l-9.14 9.14-9.14-9.14A.79.79 0 0 0 .807 0a.77.77 0 0 0-.569.237A.78.78 0 0 0 0 .807a.77.77 0 0 0 .237.569l9.156 9.156-9.156 9.14c-.159.157-.237.349-.237.569s.079.412.237.569c.085.085.174.148.268.19a1.095 1.095 0 0 0 .316.048.894.894 0 0 0 .285-.048.84.84 0 0 0 .285-.19l9.139-9.14 9.14 9.14a.894.894 0 0 0 .268.19 1.049 1.049 0 0 0 .301.048.941.941 0 0 0 .301-.048.84.84 0 0 0 .285-.19.78.78 0 0 0 .237-.569c0-.221-.079-.412-.237-.569z"></path>';
1295
- function $c77c68e559a1506c$export$3b621d86b1566b2(props = {}) {
1296
- return $5vyXB$solidjsweb.ssrElement("svg", $5vyXB$solidjsweb.mergeProps({
1297
- xmlns: "http://www.w3.org/2000/svg",
1298
- width: "21.064",
1299
- height: "21.047",
1300
- viewBox: "0 0 21.064 21.064"
1301
- }, props), () => $5vyXB$solidjsweb.ssr($c77c68e559a1506c$var$_tmpl$), true);
1302
- }
1303
2067
 
1304
2068
  /**
1305
2069
  * Lower cases a string if possible. Mostly used to make the filter url values case-insensitive.
@@ -1310,7 +2074,7 @@ function $daa394359b026187$export$325f75597868c4f0(stuff) {
1310
2074
  }
1311
2075
  const $235a2771a44e28e9$var$_tmpl$ = ["<button", ' class="clear-all-filters minor">', "</button>"],
1312
2076
  $235a2771a44e28e9$var$_tmpl$2 = ["<div", ' class="inner"><span class="title"><!--$-->', "<!--/-->: </span><!--$-->", "<!--/--></div>"],
1313
- $235a2771a44e28e9$var$_tmpl$3 = ["<button", ' class="clear-filter major"><!--$-->', "<!--/--><span><!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--> – <!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></span></button>"],
2077
+ $235a2771a44e28e9$var$_tmpl$3 = ["<button", ' class="clear-filter major"><!--$-->', "<!--/--><span><!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--> \u2013 <!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></span></button>"],
1314
2078
  $235a2771a44e28e9$var$_tmpl$4 = ["<button", ' class="clear-filter major"><!--$-->', "<!--/--><span>", "</span></button>"];
1315
2079
  function $235a2771a44e28e9$export$fecbb157621501bd({
1316
2080
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
@@ -2079,7 +2843,7 @@ function $5ea5a82e398f6f44$var$cut_text(segmented_text) {
2079
2843
  // identical split point, or split end before split start, can't do anything
2080
2844
  split_start_segment == split_end_segment && split_start_character >= split_end_character || split_start_segment > split_end_segment) return;
2081
2845
  const dots_segment = {
2082
- text_: " … ",
2846
+ text_: " \u2026 ",
2083
2847
  highlighted_: false
2084
2848
  };
2085
2849
  const split_and_dotted_values = segmented_text.flatMap((segment, i) => {
@@ -2171,7 +2935,7 @@ function $5ea5a82e398f6f44$var$cut_start(cut_left_of_index, segmented_text) {
2171
2935
  if (character === "," || is_space)
2172
2936
  // if we cut at a comma or psace, we add a … at the beginning
2173
2937
  segmented_text.unshift({
2174
- text_: "… ",
2938
+ text_: "\u2026 ",
2175
2939
  highlighted_: false
2176
2940
  });
2177
2941
  break outmost_loop;
@@ -3062,7 +3826,7 @@ function $b064919833b3e80b$export$53c59af873b303c9({
3062
3826
  get price_formatting_() {
3063
3827
  return price_formatting_();
3064
3828
  }
3065
- }), price_formatting_().post_, " – ", price_formatting_().pre_, $5vyXB$solidjsweb.createComponent((0, $d659702496cb72ea$export$a71e92cfbb498adc), {
3829
+ }), price_formatting_().post_, " \u2013 ", price_formatting_().pre_, $5vyXB$solidjsweb.createComponent((0, $d659702496cb72ea$export$a71e92cfbb498adc), {
3066
3830
  get price_() {
3067
3831
  return selected_filter.data[1];
3068
3832
  },
@@ -3144,34 +3908,6 @@ function $8c939a05b87fbbbc$export$ab34afce88557c0e(props) {
3144
3908
  }));
3145
3909
  return is_open;
3146
3910
  }
3147
- const $9fe9883b1d8ecccc$var$_tmpl$ = ["<span", ' class="', '" style="', '"></span>'];
3148
- function $9fe9883b1d8ecccc$export$acb3eaade4b23afd(props) {
3149
- return $5vyXB$solidjsweb.ssr($9fe9883b1d8ecccc$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), `depict-placeholder${$5vyXB$solidjsweb.escape(props.class, true) || ""}`, $5vyXB$solidjsweb.ssrStyle(props.style));
3150
- }
3151
- function $061ff5b4c3d36171$export$89c6019e4baa40b1(props) {
3152
- const style = $5vyXB$solidjs.createMemo(() => {
3153
- const {
3154
- style: style,
3155
- height: height,
3156
- width: width
3157
- } = props;
3158
- return {
3159
- ...(style || {}),
3160
- height: height ?? "1em",
3161
- ...(width && {
3162
- width: width
3163
- })
3164
- };
3165
- });
3166
- return $5vyXB$solidjsweb.createComponent((0, $9fe9883b1d8ecccc$export$acb3eaade4b23afd), {
3167
- get style() {
3168
- return style();
3169
- },
3170
- get ["class"]() {
3171
- return props.class;
3172
- }
3173
- });
3174
- }
3175
3911
  const $87d7574e1d89d69b$var$_tmpl$ = '<path d="M19.811 20.174l-6.234-6.809a7.96 7.96 0 0 0 .923-1.179c.274-.424.502-.865.687-1.323a8.04 8.04 0 0 0 .42-1.436 7.88 7.88 0 0 0 .144-1.507c0-.526-.051-1.042-.154-1.548-.096-.506-.243-.995-.441-1.466s-.441-.919-.728-1.343a8.28 8.28 0 0 0-.984-1.21 7.86 7.86 0 0 0-1.2-.984A7.56 7.56 0 0 0 10.89.651C10.418.453 9.929.302 9.423.2S8.401.046 7.875.046 6.833.097 6.327.2 5.332.453 4.86.651a7.56 7.56 0 0 0-1.354.718c-.431.287-.831.615-1.2.984a8.28 8.28 0 0 0-.984 1.21 7.73 7.73 0 0 0-.728 1.343c-.198.472-.349.96-.451 1.466A8.31 8.31 0 0 0 0 7.921a8.31 8.31 0 0 0 .144 1.548c.103.506.253.995.451 1.466a8.08 8.08 0 0 0 .728 1.354 7.86 7.86 0 0 0 .984 1.2 7.54 7.54 0 0 0 1.2.995c.431.287.882.53 1.354.728.472.191.96.338 1.466.441a8.31 8.31 0 0 0 1.548.144c.451 0 .896-.038 1.333-.113a7.83 7.83 0 0 0 1.282-.328 7.55 7.55 0 0 0 1.2-.533 8.08 8.08 0 0 0 1.107-.749l6.245 6.809a.45.45 0 0 0 .174.123.55.55 0 0 0 .205.041.61.61 0 0 0 .195-.031c.061-.021.116-.055.164-.102.109-.096.164-.219.164-.369.007-.144-.038-.267-.133-.369zM1.046 7.921c0-.937.178-1.818.533-2.646.362-.834.851-1.559 1.466-2.174.622-.615 1.347-1.101 2.174-1.456.827-.362 1.712-.543 2.656-.543s1.829.181 2.656.543c.827.355 1.548.841 2.164 1.456.622.615 1.111 1.34 1.466 2.174a6.52 6.52 0 0 1 .543 2.646c0 .943-.181 1.829-.543 2.656a6.89 6.89 0 0 1-1.466 2.174c-.615.615-1.336 1.104-2.164 1.466-.827.356-1.712.533-2.656.533s-1.829-.178-2.656-.533c-.827-.362-1.552-.851-2.174-1.466-.615-.622-1.104-1.347-1.466-2.174-.355-.827-.533-1.712-.533-2.656z"></path>';
3176
3912
  function $87d7574e1d89d69b$export$82eafebb825fc23f(props = {}) {
3177
3913
  return $5vyXB$solidjsweb.ssrElement("svg", $5vyXB$solidjsweb.mergeProps({
@@ -3630,151 +4366,34 @@ function $70482f04605572e2$var$modify_only_local_filter(local_filter_object, sel
3630
4366
  }
3631
4367
  }
3632
4368
  }
3633
- return modified_filter_object;
3634
- }
3635
- async function $9abb0a35d4b60ed3$export$79b1565500412d9b(search_modal, modal_fn_opts, parent) {
3636
- const body = parent || (await (0, $5vyXB$depictaiutilishared.observer).wait_for_element("body"));
3637
- let dispose_and_remove;
3638
- const open_modal_ = (extra_options_for_modal = {}, on_dispose) => {
3639
- if (dispose_and_remove)
3640
- // modal is already open
3641
- return;
3642
- const modal_els = $5vyXB$solidjs.createRoot(dispose => {
3643
- let closing_animation;
3644
- let animation_started;
3645
- dispose_and_remove = () => {
3646
- const actually_close = () => {
3647
- dispose();
3648
- on_dispose?.();
3649
- modal_els.forEach(el => el.remove());
3650
- };
3651
- if (animation_started && +new Date() - animation_started > 1000)
3652
- // Animation broke, close it this time
3653
- actually_close();else if (!animation_started && closing_animation) {
3654
- animation_started = +new Date();
3655
- $5vyXB$depictaiutilishared.catchify(closing_animation)()?.then($5vyXB$depictaiutilishared.catchify(actually_close));
3656
- } else actually_close();
3657
- };
3658
- return search_modal({
3659
- ...modal_fn_opts,
3660
- ...extra_options_for_modal,
3661
- close_modal_: close_modal_,
3662
- open_modal_: open_modal_,
3663
- register_closing_animation_: animation => closing_animation = animation
3664
- });
3665
- });
3666
- body.append(...modal_els);
3667
- };
3668
- const close_modal_ = () => {
3669
- if (dispose_and_remove) {
3670
- // modal is open
3671
- const dispose_fn = dispose_and_remove;
3672
- // set dispose function to undefined in case that it triggers this dispose function itself. Not doing it leads to a bug like https://github.com/solidjs/solid/discussions/1194
3673
- dispose_and_remove = undefined;
3674
- dispose_fn();
3675
- }
3676
- };
3677
- return {
3678
- open_modal_: open_modal_,
3679
- close_modal_: close_modal_
3680
- };
3681
- }
3682
- async function $bc91d938b8c601b4$export$58e808b1db15d3bc({
3683
- merchant: merchant,
3684
- market: market,
3685
- headers: headers,
3686
- ...fetch_recs_options
3687
- }) {
3688
- return await $5vyXB$depictaiutilishared.fetch_recs({
3689
- tenant: merchant,
3690
- market: market
3691
- }, $5vyXB$depictaiutilishared.snakeCasifyObject(fetch_recs_options), headers);
3692
- }
3693
- function $6e22b5314fb52f4c$export$e183a13865960371(params_to_default_value, router_) {
3694
- const signals = {};
3695
- const entries = Object.entries(params_to_default_value);
3696
- const event_handler = $5vyXB$depictaiutilishared.catchify((what_happened, args) => {
3697
- // Intentionally always update our signals to the history state to allow external control of SDK state for doing things like https://linear.app/depictai/issue/X-1432/is-this-possible-with-the-depict-sdk
3698
- if (what_happened !== "popstate") return;
3699
- // Had to undo the comment above,but leaving the history. Doing this because discovering why it doesn't work is a deja-vu and I don't want to have to discover it again.
3700
- // If we want others to interface with our state, it's better to expose it from DepictCategory/DepictSearch
3701
- // The reason for that is because writes to the state trigger writes to the state (something about local filter state, see the comment where `last_remote_state !== available_filters_()` happens in create_modified_filters.tsx)
3702
- // And can infinite loop, like in https://app.jiminny.com/playback/569c8f65-edea-4735-bd9e-4eb5a0b14cad
3703
- // It's the classical equilibrium problem when syncing state both down and up, and it's much easier to avoid than solve
3704
- $6e22b5314fb52f4c$var$history_state_change(signals, entries, args.state);
3705
- });
3706
- // createRenderEffect because we need the instant execution so the signals always contain values, even before solid's render phase
3707
- $5vyXB$solidjs.createRenderEffect(() => {
3708
- let signal_changed = false;
3709
- let {
3710
- state: state
3711
- } = globalThis?.history || {
3712
- state: {}
3713
- }; // cloning isn't necessary because we're calling replaceState on it anyway
3714
- if (state === null || typeof state != "object") state = {};
3715
- for (const [param, default_value] of entries) {
3716
- const [read_signal] = signals[param] ||= $5vyXB$solidjs.createSignal(state[param] ?? default_value);
3717
- const new_value = read_signal();
3718
- if (new_value !== state[param]) {
3719
- signal_changed = true;
3720
- state[param] = new_value;
3721
- }
3722
- }
3723
- if (signal_changed) router_.navigate_.replace_state_(state);
3724
- });
3725
- // history_dot_state_to_state needs to update after its signals after url_state does BUT in the same task (might even have to be in the same tick in the microtask queue). If we'd use window.addEventListener("popstate") it would be guaranteed to be too late since each event listener has its own task
3726
- (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(event_handler);
3727
- $5vyXB$solidjs.onCleanup($5vyXB$depictaiutilishared.catchify(() => (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(event_handler)));
3728
- $5vyXB$solidjs.createEffect($5vyXB$depictaiutilishared.catchify(() => $5vyXB$solidjs.untrack($5vyXB$depictaiutilishared.catchify(() => $6e22b5314fb52f4c$var$history_state_change(signals, entries, history.state))))); // we need this to run after reading the initial state from history.state to write the defaults to history.state
3729
- return signals;
3730
- }
3731
- function $6e22b5314fb52f4c$var$history_state_change(signals, entries, state) {
3732
- $5vyXB$solidjs.batch(() => {
3733
- for (const [param, default_value] of entries) {
3734
- const [, write_signal] = signals[param];
3735
- const new_value = state?.[param];
3736
- write_signal(new_value ?? default_value);
3737
- }
3738
- });
3739
- }
3740
- const $d84fe647b84b5dc5$export$3064e1e8c6513da3 = new Set();
3741
- let $d84fe647b84b5dc5$var$has_ran = false;
3742
- function $d84fe647b84b5dc5$export$5162a71f252e6122() {
3743
- if ($d84fe647b84b5dc5$var$has_ran || typeof history !== "object") return;
3744
- $d84fe647b84b5dc5$var$has_ran = true;
3745
- for (const function_name of ["replaceState", "pushState"]) {
3746
- if (Object.getOwnPropertyNames(history).includes(function_name)) $d84fe647b84b5dc5$var$proxy_push_state(function_name, history);
3747
- $d84fe647b84b5dc5$var$proxy_push_state(function_name, History.prototype);
3748
- }
3749
- }
3750
- function $d84fe647b84b5dc5$var$proxy_push_state(function_name, thing) {
3751
- thing[function_name] = new Proxy(thing[function_name], {
3752
- apply(target, this_arg, arg_list) {
3753
- try {
3754
- const old_state = history.state;
3755
- if (typeof old_state == "object" && old_state !== null) {
3756
- // This effectively disallows the user from passing in a string, number, null or undefined
3757
- const intended_new_value_as_obj = typeof arg_list[0] === "object" ? arg_list[0] ?? {} : {};
3758
- const cloned_object = {
3759
- ...intended_new_value_as_obj
3760
- };
3761
- for (const key in old_state) {
3762
- if (!$d84fe647b84b5dc5$var$starts_with_any_prefix(key)) continue;
3763
- if (!(key in cloned_object)) cloned_object[key] = old_state[key];
3764
- }
3765
- arg_list[0] = cloned_object;
3766
- }
3767
- } catch (e) {
3768
- $5vyXB$depictaiutilishared.report([e, "Failed to preserve items in history.state"], "error");
3769
- }
3770
- return Reflect.apply(target, this_arg, arg_list);
3771
- }
3772
- });
3773
- }
3774
- function $d84fe647b84b5dc5$var$starts_with_any_prefix(key) {
3775
- for (const prefix of $d84fe647b84b5dc5$export$3064e1e8c6513da3) {
3776
- if (key.startsWith(prefix)) return true;
3777
- }
4369
+ return modified_filter_object;
4370
+ }
4371
+ async function $bd429c994399dd82$export$58e808b1db15d3bc(options) {
4372
+ const headers = options.headers;
4373
+ const product_id = options.productId || options.product_id; // Second fallback here is just because there was very little missing to make this work with snake_case input and in case someone puts in snake case'd stuff already (preview browser did) we can easily not break it
4374
+ const cleaned_up_options = $5vyXB$depictaiutilishared.snakeCasifyObject(options);
4375
+ delete cleaned_up_options.headers;
4376
+ delete cleaned_up_options.product_id;
4377
+ cleaned_up_options.session_id ||= $5vyXB$depictaiutilishared.get_session_id();
4378
+ if (product_id && !cleaned_up_options.product_ids) cleaned_up_options.product_ids = [product_id];
4379
+ const options_to_send = cleaned_up_options;
4380
+ const url = $5vyXB$depictaiutilishared.add_version_query_params(`${(0, $5vyXB$depictaiutilishared.base_url)}/v3/recommend/products`);
4381
+ return await $5vyXB$depictaiutilishared.fetch_retry(url, {
4382
+ body: JSON.stringify(options_to_send),
4383
+ ...(headers ? {
4384
+ headers: headers
4385
+ } : {}),
4386
+ method: "POST"
4387
+ }).catch(e => $5vyXB$depictaiutilishared.dlog("fetch_retry threw", e)).then(async maybe_response => {
4388
+ if (!maybe_response) return [];
4389
+ let decoded;
4390
+ try {
4391
+ decoded = await maybe_response.json();
4392
+ } catch (e) {
4393
+ $5vyXB$depictaiutilishared.dlog("Failed to decode JSON", e);
4394
+ }
4395
+ return decoded?.displays || [];
4396
+ });
3778
4397
  }
3779
4398
  function $26a56f6b44703084$export$9862539c89138352({
3780
4399
  get_default_values_: get_default_values_,
@@ -3831,8 +4450,8 @@ function $67dc366d96177e70$export$967e966fca9515e(api_response) {
3831
4450
  }
3832
4451
  return api_response;
3833
4452
  }
3834
- const $e1d6c0f3d89d531c$var$v2_base_url = (0, $5vyXB$depictaiutilishared.base_url) + "/v2/";
3835
- const $e1d6c0f3d89d531c$var$search_base_url = $e1d6c0f3d89d531c$var$v2_base_url + "search/";
4453
+ const $e1d6c0f3d89d531c$var$v3_base_url = (0, $5vyXB$depictaiutilishared.base_url) + "/v3/";
4454
+ const $e1d6c0f3d89d531c$var$search_base_url = $e1d6c0f3d89d531c$var$v3_base_url + "search/";
3836
4455
  class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3837
4456
  #supports_finalization_registry = typeof FinalizationRegistry === "function";
3838
4457
  #cache_objs = {};
@@ -3851,18 +4470,14 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3851
4470
  const request = {
3852
4471
  ...input_req
3853
4472
  };
3854
- request.dsid ??= $5vyXB$depictaiutilishared.get_depict_id();
3855
- // Todo: remove the default user and session IDs once we've confirmed backend can handle it and do whatever fallback is necessary.
3856
- request.user_id ??= this.#get_user_id?.() || $5vyXB$depictaiutilishared.get_user_id();
3857
4473
  request.session_id ??= this.#get_session_id?.() || $5vyXB$depictaiutilishared.get_session_id();
3858
4474
  return request;
3859
4475
  };
3860
4476
  #get_metadata;
3861
- #get_user_id;
3862
4477
  #get_session_id;
3863
4478
  #guard_url_creator_length(expected, received) {
3864
4479
  if (expected.length !== received.length) {
3865
- const e = new Error("Page URL creator returned wrong number of page URLs, got " + received.length + ", expected " + expected.length);
4480
+ const e = new Error("displayTransformer returned wrong number of page URLs, got " + received.length + ", expected " + expected.length);
3866
4481
  queueMicrotask(() => {
3867
4482
  throw e;
3868
4483
  });
@@ -3899,8 +4514,9 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3899
4514
  const category_transformer = display_transformers?.categories;
3900
4515
  const content_result_transformer = display_transformers?.contentResults;
3901
4516
  const displays = input_data.displays;
4517
+ const owner = $5vyXB$solidjs.getOwner();
3902
4518
  const {
3903
- breadcrumb: breadcrumb,
4519
+ breadcrumbs: breadcrumbs,
3904
4520
  quick_links: quick_links,
3905
4521
  content_search_links: content_search_links
3906
4522
  } = input_data;
@@ -3929,7 +4545,7 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3929
4545
  displays[i] = new_display_or_page_url;
3930
4546
  }
3931
4547
  }
3932
- if (page_url_creator || category_transformer) for (const category_display_array of [breadcrumb, quick_links]) {
4548
+ if (page_url_creator || category_transformer) for (const category_display_array of [breadcrumbs, quick_links]) {
3933
4549
  if (!category_display_array) continue;
3934
4550
  const page_urls = await (page_url_creator || category_transformer)({
3935
4551
  merchant: merchant,
@@ -3945,24 +4561,32 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3945
4561
  Object.defineProperties(category_display_array[i], Object.getOwnPropertyDescriptors(page_urls[i]));
3946
4562
  }
3947
4563
  if (content_search_links?.length && content_result_transformer) {
3948
- const result = await content_result_transformer({
4564
+ const result = await $5vyXB$solidjs.runWithOwner(owner, () => content_result_transformer({
3949
4565
  merchant: merchant,
3950
4566
  market: market,
3951
4567
  data: [...content_search_links]
3952
- });
4568
+ }));
3953
4569
  this.#guard_url_creator_length(content_search_links, result);
3954
4570
  input_data.content_search_links = result;
3955
4571
  }
3956
4572
  return input_data;
3957
4573
  }
3958
- async #cached_post_request(endpoint, input_req, fallback_response) {
3959
- const cache_obj = this.#get_cache_obj_for_endpoint(endpoint);
3960
- const with_ids = this.#add_ids_to_request(input_req);
4574
+ async #cached_request({
4575
+ endpoint_: endpoint_,
4576
+ input_req_: input_req_,
4577
+ fallback_response_: fallback_response_,
4578
+ method_ = "POST",
4579
+ delete_key_before_sending_: delete_key_before_sending_ // only supported for GET requests
4580
+ }) {
4581
+ const cache_obj = this.#get_cache_obj_for_endpoint(endpoint_);
4582
+ const with_ids = this.#add_ids_to_request(input_req_);
4583
+ const owner = $5vyXB$solidjs.getOwner();
3961
4584
  const metaData = await this.#get_metadata?.();
3962
4585
  const request = metaData ? Object.assign(with_ids, {
3963
4586
  metadata: metaData
3964
4587
  }) : with_ids;
3965
- const body = JSON.stringify($5vyXB$depictaiutilishared.sort_obj(request));
4588
+ const sorted_request = $5vyXB$depictaiutilishared.sort_obj(request);
4589
+ const body = JSON.stringify(sorted_request);
3966
4590
  const response_from_cache = cache_obj.cache_[body]?.deref?.();
3967
4591
  if (response_from_cache) return response_from_cache;
3968
4592
  const in_progress_request = cache_obj.in_progress_[body];
@@ -3970,18 +4594,23 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3970
4594
  let resolve_in_progress;
3971
4595
  cache_obj.in_progress_[body] = new Promise(r => resolve_in_progress = r);
3972
4596
  try {
3973
- const api_response = await $5vyXB$depictaiutilishared.fetch_retry($5vyXB$depictaiutilishared.add_version_query_params(endpoint), {
3974
- method: "POST",
3975
- body: body
4597
+ const is_post = method_ === "POST";
4598
+ if (!is_post && delete_key_before_sending_) delete sorted_request[delete_key_before_sending_];
4599
+ const url_to_request = is_post ? endpoint_ : $5vyXB$depictaiutilishared.make_url_with_query_params(endpoint_, sorted_request);
4600
+ const api_response = await $5vyXB$depictaiutilishared.fetch_retry($5vyXB$depictaiutilishared.add_version_query_params(url_to_request), {
4601
+ method: method_,
4602
+ ...(is_post ? {
4603
+ body: body
4604
+ } : {})
3976
4605
  });
3977
4606
  return_successfully: {
3978
4607
  if (!api_response || api_response.status !== 200) break return_successfully;
3979
4608
  let result;
3980
4609
  try {
3981
4610
  const unmodified_result = await api_response.json();
3982
- result = await this.#run_display_transformers_for_rest(input_req.tenant, input_req.market, unmodified_result);
4611
+ result = await $5vyXB$solidjs.runWithOwner(owner, () => this.#run_display_transformers_for_rest(input_req_.merchant, input_req_.market, unmodified_result));
3983
4612
  } catch (e) {
3984
- $5vyXB$depictaiutilishared.dwarn("URL creator or json decoding failed", e);
4613
+ $5vyXB$depictaiutilishared.dwarn("displayTransformer or json decoding failed", e);
3985
4614
  break return_successfully;
3986
4615
  }
3987
4616
  // Here result actually becomes O
@@ -3999,7 +4628,7 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3999
4628
  return result;
4000
4629
  }
4001
4630
  // If we get here, the request failed
4002
- const retval = fallback_response(input_req);
4631
+ const retval = fallback_response_(input_req_);
4003
4632
  resolve_in_progress(retval);
4004
4633
  return retval;
4005
4634
  } finally {
@@ -4009,19 +4638,18 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
4009
4638
  constructor(options) {
4010
4639
  const {
4011
4640
  get_metadata: get_metadata,
4012
- get_user_id: get_user_id,
4013
4641
  get_session_id: get_session_id,
4014
4642
  page_url_creator: page_url_creator,
4015
4643
  display_transformers: display_transformers
4016
4644
  } = options ?? {};
4017
4645
  this.#get_metadata = get_metadata;
4018
- this.#get_user_id = get_user_id;
4019
4646
  this.#get_session_id = get_session_id;
4020
4647
  this.page_url_creator = page_url_creator;
4021
4648
  this.display_transformers = display_transformers;
4022
4649
  }
4023
4650
  async suggest(input_req) {
4024
4651
  const with_ids = this.#add_ids_to_request(input_req);
4652
+ const owner = $5vyXB$solidjs.getOwner();
4025
4653
  const metaData = await this.#get_metadata?.();
4026
4654
  const request = metaData ? Object.assign(with_ids, {
4027
4655
  metadata: JSON.stringify(metaData)
@@ -4033,9 +4661,9 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
4033
4661
  const decoded_json = await results.json();
4034
4662
  if (!Array.isArray(decoded_json?.suggestions)) break attempt_to_return_api_response;
4035
4663
  try {
4036
- return await this.#run_url_creator_for_suggest(input_req.tenant, input_req.market, decoded_json);
4664
+ return await $5vyXB$solidjs.runWithOwner(owner, () => this.#run_url_creator_for_suggest(input_req.merchant, input_req.market, decoded_json));
4037
4665
  } catch (e) {
4038
- $5vyXB$depictaiutilishared.dwarn("URL creator failed", e);
4666
+ $5vyXB$depictaiutilishared.dwarn("displayTransformer failed", e);
4039
4667
  }
4040
4668
  }
4041
4669
  return {
@@ -4045,31 +4673,67 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
4045
4673
  };
4046
4674
  }
4047
4675
  async query(input_req) {
4048
- return await this.#cached_post_request($e1d6c0f3d89d531c$var$search_base_url + "results", input_req, () => ({
4049
- "n_hits": 0,
4050
- "displays": [],
4051
- "sorts": [],
4052
- "filters": [],
4053
- "search_request_id": "error",
4054
- failed: true
4055
- }));
4676
+ return await this.#cached_request({
4677
+ endpoint_: $e1d6c0f3d89d531c$var$search_base_url + "results",
4678
+ input_req_: input_req,
4679
+ fallback_response_: () => ({
4680
+ "n_hits": 0,
4681
+ "displays": [],
4682
+ "sorts": [],
4683
+ "filters": [],
4684
+ "search_request_id": "error",
4685
+ failed: true
4686
+ })
4687
+ });
4056
4688
  }
4057
- async list(input_req) {
4058
- return await this.#cached_post_request($e1d6c0f3d89d531c$var$v2_base_url + "product-listing", input_req, () => ({
4059
- "n_hits": 0,
4060
- "displays": [],
4061
- "sorts": [],
4062
- "filters": [],
4063
- "breadcrumb": [],
4064
- "quick_links": [],
4065
- "product_listing_request_id": "error",
4066
- failed: true
4067
- }));
4689
+ async get_listing(input_req) {
4690
+ return await this.#cached_request({
4691
+ endpoint_: $e1d6c0f3d89d531c$var$v3_base_url + "listings/" + encodeURIComponent(input_req.listing_id),
4692
+ input_req_: input_req,
4693
+ fallback_response_: () => ({
4694
+ listing_id: "",
4695
+ listing_type: "category",
4696
+ "title": "",
4697
+ "description": "string",
4698
+ "replace_meta_tags": true,
4699
+ "slug": "",
4700
+ "updated_at": new Date().toISOString(),
4701
+ "breadcrumbs": [],
4702
+ "quick_links": [],
4703
+ failed: true
4704
+ }),
4705
+ method_: "GET",
4706
+ delete_key_before_sending_: "listing_id" // this goes into the path, but we still need to have it in the request object until the last second as we want to include it as a key when caching requests
4707
+ });
4708
+ }
4709
+
4710
+ async get_listing_products(input_req) {
4711
+ const listing_id = input_req.listing_id; // listing_id goes into the path
4712
+ const cloned_request = {
4713
+ ...input_req
4714
+ };
4715
+ delete cloned_request["listing_id"];
4716
+ return await this.#cached_request({
4717
+ endpoint_: $e1d6c0f3d89d531c$var$v3_base_url + "listings/" + encodeURIComponent(listing_id) + "/products",
4718
+ input_req_: input_req,
4719
+ fallback_response_: () => ({
4720
+ "n_hits": 0,
4721
+ "displays": [],
4722
+ "sorts": [],
4723
+ "filters": [],
4724
+ "product_listing_request_id": "error",
4725
+ failed: true
4726
+ })
4727
+ });
4068
4728
  }
4069
4729
  async get_recommended(input_req) {
4070
- return await this.#cached_post_request($e1d6c0f3d89d531c$var$search_base_url + "related", input_req, () => ({
4071
- displays: []
4072
- }));
4730
+ return await this.#cached_request({
4731
+ endpoint_: $e1d6c0f3d89d531c$var$search_base_url + "related",
4732
+ input_req_: input_req,
4733
+ fallback_response_: () => ({
4734
+ displays: []
4735
+ })
4736
+ });
4073
4737
  }
4074
4738
  }
4075
4739
  function $b54e6192d0caa293$export$d9f36cf74e24d595(media_query) {
@@ -4168,7 +4832,7 @@ function $76b6ac05693f5c71$export$205efb947c7ffd78(handler, passive = true) {
4168
4832
  $5vyXB$solidjs.onCleanup(() => removeEventListener(event, catchified_handler));
4169
4833
  }
4170
4834
  }
4171
- const $401aee5f33dca9e2$var$_tmpl$ = ["<div", ' class="scroll-status" style="display:none"><span class="text"><b>', "</b> – <b>", "</b> <!--$-->", "<!--/--> <b>", "</b></span></div>"];
4835
+ const $401aee5f33dca9e2$var$_tmpl$ = ["<div", ' class="scroll-status" style="display:none"><span class="text"><b>', "</b> \u2013 <b>", "</b> <!--$-->", "<!--/--> <b>", "</b></span></div>"];
4172
4836
  function $401aee5f33dca9e2$export$83fd5de5504a7a67({
4173
4837
  formatted_number_of_results_: formatted_number_of_results_,
4174
4838
  first_result_in_viewport_: [get_first_result_in_viewport],
@@ -4352,7 +5016,7 @@ function $3f08fe2992a2a8ca$export$5e4aed86c12acdd9({
4352
5016
  // After first load, always just load 20 since people might just be browsing the top ones still
4353
5017
  min_products_to_fetch_ : now - last_loaded < 10000 ? min_products_to_fetch_ * 5 : min_products_to_fetch_;
4354
5018
  // dlog("loading ", number_of_results_to_load, "products, because it was", now - last_loaded, "ms since last load");
4355
- const api_response = await depict_api_["query_id" in base_part ? "list" : "query"]({
5019
+ const api_response = await depict_api_["listing_id" in base_part ? "get_listing_products" : "query"]({
4356
5020
  cursor: get_last_cursor(),
4357
5021
  limit: number_of_results_to_load,
4358
5022
  ...base_part
@@ -4415,8 +5079,6 @@ function $ac167f6af6a48fc3$export$a1fd619a4743ca08({
4415
5079
  product_card_template_: product_card_template_,
4416
5080
  first_result_in_viewport_: [, set_first_result_in_viewport],
4417
5081
  last_result_in_viewport_: [get_last_result_in_viewport_, set_last_result_in_viewport],
4418
- merchant_: merchant_,
4419
- market_: market_,
4420
5082
  all_products_loaded_: all_products_loaded_,
4421
5083
  min_products_to_fetch_: min_products_to_fetch_,
4422
5084
  query_base_: query_base_,
@@ -4468,8 +5130,6 @@ function $ac167f6af6a48fc3$export$a1fd619a4743ca08({
4468
5130
  });
4469
5131
  return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
4470
5132
  displays_by_key_: displays_by_key_,
4471
- merchant_: merchant_,
4472
- market_: market_,
4473
5133
  product_card_template_: product_card_template_,
4474
5134
  content_blocks_: content_blocks_,
4475
5135
  do_per_elements_: (elements, index_accessor) =>
@@ -4614,37 +5274,6 @@ function $055384b985678603$export$a79e666719b3647c(cols_at_size_) {
4614
5274
  });
4615
5275
  return n_cols_currently_showing;
4616
5276
  }
4617
- function $3bc4a89b971a3af5$export$3f37af283f8fb843(props) {
4618
- const style = $5vyXB$solidjs.createMemo(() => {
4619
- const {
4620
- style: style,
4621
- height: height,
4622
- width: width,
4623
- aspectRatio: aspectRatio
4624
- } = props;
4625
- const is_image = aspectRatio != undefined;
4626
- const size_data = is_image ? {
4627
- width: "100%",
4628
- "padding-bottom": 1 / aspectRatio * 100 + "%"
4629
- } : {
4630
- width: width,
4631
- height: height
4632
- };
4633
- return {
4634
- display: "block",
4635
- ...(style || {}),
4636
- ...size_data
4637
- };
4638
- });
4639
- return $5vyXB$solidjsweb.createComponent((0, $9fe9883b1d8ecccc$export$acb3eaade4b23afd), {
4640
- get style() {
4641
- return style();
4642
- },
4643
- get ["class"]() {
4644
- return props.class;
4645
- }
4646
- });
4647
- }
4648
5277
  const $d92f338ba8f9da9b$var$_tmpl$ = ["<div", ' class="content-block-wrapper" style="', '">', "</div>"];
4649
5278
  function $d92f338ba8f9da9b$export$791ef57e62e21c3f({
4650
5279
  content_blocks_: incoming_content_blocks,
@@ -4838,8 +5467,6 @@ function $fe76fb463cc60b89$export$3925f87b1545cfc6({
4838
5467
  }) {
4839
5468
  // The plp_results_ resource will be delayed because we're using createBatchedMemo to not make triplicate API requests, but we need to show the placeholders before already to match Chrome and Firefox's "content has to be there, ready for scroll restoration, before all popstate tasks have been completed"-requirement
4840
5469
  const is_loading_ = $5vyXB$solidjs.createMemo(() => plp_results_.loading || query_base_.loading);
4841
- const merchant_ = $5vyXB$solidjs.createMemo(() => query_base_().tenant);
4842
- const market_ = $5vyXB$solidjs.createMemo(() => query_base_().market);
4843
5470
  const has_no_results_or_failed = $5vyXB$solidjs.createMemo(() => {
4844
5471
  const displays = plp_results_()?.displays;
4845
5472
  return !is_loading_() && (!Array.isArray(displays) || !displays.length);
@@ -4947,8 +5574,6 @@ function $fe76fb463cc60b89$export$3925f87b1545cfc6({
4947
5574
  plp_results_: plp_results_,
4948
5575
  last_result_in_viewport_: last_result_in_viewport_,
4949
5576
  first_result_in_viewport_: first_result_in_viewport_,
4950
- market_: market_,
4951
- merchant_: merchant_,
4952
5577
  all_products_loaded_: all_products_loaded_,
4953
5578
  min_products_to_fetch_: min_products_to_fetch_,
4954
5579
  query_base_: query_base_,
@@ -5076,42 +5701,6 @@ function $be89be42ce9ea60f$export$1f1775a58da589b5({
5076
5701
  }
5077
5702
  });
5078
5703
  }
5079
- function $ca1176b694a6ee2e$export$fe334901e8bebd57() {
5080
- const cleanup_fns = [];
5081
- const cleanup = () => cleanup_fns.forEach(f => f());
5082
- // use an animation to automatically retain the `overflow` values and all other styling
5083
- for (const element of [document.documentElement, document.body]) {
5084
- try {
5085
- const animation = element.animate({
5086
- overflow: "hidden",
5087
- offset: 0
5088
- }, 1);
5089
- animation.pause();
5090
- const fn = $5vyXB$depictaiutilishared.catchify(animation.play.bind(animation));
5091
- cleanup_fns.push(fn);
5092
- $5vyXB$solidjs.onCleanup(fn);
5093
- } catch (e) {
5094
- $5vyXB$depictaiutilishared.dlog("Probably partial keyframe error", e);
5095
- }
5096
- if (getComputedStyle(element).overflow !== "hidden") {
5097
- // safari gets special hacky treatment
5098
- const style = element.style;
5099
- const original_value = style.overflow;
5100
- style.overflow = "hidden";
5101
- const fn = $5vyXB$depictaiutilishared.catchify(() => style.overflow = original_value);
5102
- cleanup_fns.push(fn);
5103
- $5vyXB$solidjs.onCleanup(fn);
5104
- }
5105
- }
5106
- return cleanup;
5107
- } // the way that houdini does that (FYI) it fixes the page jumps
5108
- // const from_top = scrollY;
5109
- // document.body.style.position = "fixed";
5110
- // document.body.style.left = 0;
5111
- // document.body.style.right = 0;
5112
- // document.body.style.top = `-${from_top}px`;
5113
- // document.body.style.overflowY = "scroll";
5114
-
5115
5704
  const $f958b5ac0e4a78da$var$_tmpl$ = '<path d="M6.199 10.254a.35.35 0 0 0-.496 0L3.5 12.453V.348a.35.35 0 0 0-.7 0v12.105L.598 10.254c-.137-.137-.359-.137-.492 0a.35.35 0 0 0 0 .492l2.797 2.801a.35.35 0 0 0 .496 0L6.2 10.746c.137-.137.137-.355 0-.492zM9.449 3.5H8.051a.35.35 0 0 1-.352-.352V1.75c0-.191.156-.352.352-.352h1.398c.195 0 .352.16.352.352v1.398a.35.35 0 0 1-.352.352zm-1.051-.699h.703v-.699h-.703zm0 0"></path>',
5116
5705
  $f958b5ac0e4a78da$var$_tmpl$2 = '<path d="M10.852 6.301H8.051a.35.35 0 0 1-.352-.352V4.551a.35.35 0 0 1 .352-.352h2.801a.35.35 0 0 1 .348.352v1.398a.35.35 0 0 1-.348.352zm-2.453-.699H10.5v-.703H8.398zm3.851 3.5H8.051c-.195 0-.352-.16-.352-.352V7.352A.35.35 0 0 1 8.051 7h4.199c.191 0 .352.156.352.352V8.75c0 .191-.16.352-.352.352zm-3.852-.703h3.5V7.7h-3.5zm5.25 3.499H8.051a.35.35 0 0 1-.352-.348v-1.402a.35.35 0 0 1 .352-.348h5.598a.35.35 0 0 1 .352.348v1.402a.35.35 0 0 1-.352.348zm-5.25-.699H13.3V10.5H8.398zm0 0"></path>';
5117
5706
  function $f958b5ac0e4a78da$export$da32f7add8a22e86(props = {}) {
@@ -5671,7 +6260,6 @@ function $e53b2e7e632ac4cb$export$5646050d516e06bc({
5671
6260
  }) {
5672
6261
  const placeholder_crumb_data = [,,,];
5673
6262
  const crumb_data = $5vyXB$solidjs.createMemo(() => get_api_crumb_data() || placeholder_crumb_data);
5674
- const href_accessor = $5vyXB$depictaiutilishared.use_href_accessor();
5675
6263
  return $5vyXB$solidjsweb.createComponent((0, $edafe91daf3091d7$export$b69d0d92862de18b), {
5676
6264
  severity_: "error",
5677
6265
  message_: "BreadCrumbs failed",
@@ -5681,10 +6269,8 @@ function $e53b2e7e632ac4cb$export$5646050d516e06bc({
5681
6269
  return crumb_data();
5682
6270
  },
5683
6271
  children: (display_accessor, index) => {
5684
- const is_last = $5vyXB$solidjs.createMemo(() => index === crumb_data()?.length - 1);
5685
- const url = $5vyXB$solidjs.createMemo(() => is_last() ? href_accessor() : display_accessor()?.page_url);
5686
6272
  const href = $5vyXB$solidjs.createMemo(() => $1ab22f2cd39b3061$export$43cd1e747fecd42e({
5687
- to_url_: url(),
6273
+ to_url_: display_accessor()?.page_url,
5688
6274
  filter_query_param_prefix_: filter_query_param_prefix_,
5689
6275
  sorting_query_param_: sorting_query_param_
5690
6276
  }));
@@ -5720,42 +6306,42 @@ const $8cceb1d3a967f369$var$_tmpl$ = ["<nav", ' class="quicklinks"', ">", "</nav
5720
6306
  function $8cceb1d3a967f369$export$466cdc317043f6cb({
5721
6307
  quicklinks_data_: quicklinks_data_,
5722
6308
  router_: router_,
5723
- current_query_id_: current_query_id_,
6309
+ current_listing_id_: current_listing_id_,
5724
6310
  breadcrumb_data_: breadcrumb_data_,
5725
6311
  i18n_: i18n_,
5726
6312
  sorting_query_param_: sorting_query_param_,
5727
6313
  filter_query_param_prefix_: filter_query_param_prefix_
5728
6314
  }) {
5729
- let scrolling_logic_ran_for_query_id = false;
6315
+ let scrolling_logic_ran_for_listing_id = false;
5730
6316
  let last_scroll_position;
5731
6317
  let scroll_to_element_on_dom_insertion;
5732
6318
  let last_was_placeholder = false;
5733
6319
  let sliding_element;
5734
6320
  $5vyXB$solidjs.createComputed(() => {
5735
- current_query_id_();
5736
- scrolling_logic_ran_for_query_id = false;
6321
+ current_listing_id_();
6322
+ scrolling_logic_ran_for_listing_id = false;
5737
6323
  });
5738
6324
  const place_holdey_quicklinks_data = $5vyXB$solidjs.createMemo(() => quicklinks_data_() || [,,,]);
5739
- const selected_index = $5vyXB$solidjs.createMemo(() => quicklinks_data_()?.findIndex(item => item.query_id === current_query_id_())); // this will be -1 when viewing child categories
5740
- const scrollpos_per_queryid = {};
6325
+ const selected_index = $5vyXB$solidjs.createMemo(() => quicklinks_data_()?.findIndex(item => item.listing_id === current_listing_id_())); // this will be -1 when viewing child categories
6326
+ const scrollpos_per_listing_id = {};
5741
6327
  const mutation_plugins = [function () {
5742
- if (!scrolling_logic_ran_for_query_id) return;
6328
+ if (!scrolling_logic_ran_for_listing_id) return;
5743
6329
  const {
5744
6330
  scrollLeft: scrollLeft
5745
6331
  } = this.insert_here;
5746
6332
  if (scrollLeft > 0) {
5747
6333
  last_scroll_position = scrollLeft;
5748
- const current_id = $5vyXB$solidjs.untrack(current_query_id_);
6334
+ const current_id = $5vyXB$solidjs.untrack(current_listing_id_);
5749
6335
  // make sure to not save position where selected item isn't in viewport
5750
6336
  const current_selected_index = $5vyXB$solidjs.untrack(selected_index);
5751
6337
  const intersecting_thing = this.intersecting_items_object[current_selected_index];
5752
- if (intersecting_thing?.intersectionRatio >= 0.95 || current_selected_index == undefined || current_selected_index < 0) scrollpos_per_queryid[current_id] = scrollLeft;else if (current_id in scrollpos_per_queryid)
6338
+ if (intersecting_thing?.intersectionRatio >= 0.95 || current_selected_index == undefined || current_selected_index < 0) scrollpos_per_listing_id[current_id] = scrollLeft;else if (current_id in scrollpos_per_listing_id)
5753
6339
  // if about to go out of view, stop saving it so that the "always show new things in view" thing can get to work
5754
- delete scrollpos_per_queryid[current_id];
6340
+ delete scrollpos_per_listing_id[current_id];
5755
6341
  }
5756
6342
  }];
5757
6343
  $5vyXB$solidjs.createComputed(() => {
5758
- if (place_holdey_quicklinks_data()?.[0]?.query_id) {
6344
+ if (place_holdey_quicklinks_data()?.[0]?.listing_id) {
5759
6345
  if (last_was_placeholder) queueMicrotask($5vyXB$depictaiutilishared.catchify(() => {
5760
6346
  sliding_element?.scrollTo({
5761
6347
  left: 0
@@ -5807,13 +6393,13 @@ function $8cceb1d3a967f369$export$466cdc317043f6cb({
5807
6393
  equals: false
5808
6394
  }), new_data => {
5809
6395
  const quicklinks_data = quicklinks_data_(); // this signal should have updated by now since this is a createEffect
5810
- const current_id = current_query_id_();
6396
+ const current_id = current_listing_id_();
5811
6397
  if (!new_data || !quicklinks_data || !current_id) return;
5812
6398
  const owner = $5vyXB$solidjs.getOwner();
5813
6399
  queueMicrotask(() => {
5814
6400
  // has to be in microtask so that elements have rendered and are scroll-to-able
5815
- scrolling_logic_ran_for_query_id = true;
5816
- const saved_scroll_position = scrollpos_per_queryid[current_id];
6401
+ scrolling_logic_ran_for_listing_id = true;
6402
+ const saved_scroll_position = scrollpos_per_listing_id[current_id];
5817
6403
  if (saved_scroll_position) {
5818
6404
  insert_here.scrollTo({
5819
6405
  left: saved_scroll_position
@@ -5855,10 +6441,10 @@ function $8cceb1d3a967f369$export$466cdc317043f6cb({
5855
6441
  // Problem: When you don't open a link in a new tab, we don't display the filter cleared toast
5856
6442
  // Solution: instead of not adding the state to the url, add a flag to the link if it's a sibling and then display the toast on load if the flag is set
5857
6443
  const is_sibling = $5vyXB$solidjs.createMemo(() => {
5858
- const current_id = current_query_id_();
6444
+ const current_id = current_listing_id_();
5859
6445
  return quicklinks_data_()?.some(({
5860
- query_id: query_id
5861
- }) => query_id === current_id);
6446
+ listing_id: listing_id
6447
+ }) => listing_id === current_id);
5862
6448
  });
5863
6449
  const href = $5vyXB$solidjs.createMemo(() =>
5864
6450
  // We don't want these links to delete the sort and filter state by default, only if `clear_filters_when_going_sideways` explicitly clears them
@@ -5947,10 +6533,12 @@ async function $276380e4607fb9fb$export$cc42dd29bf655ab6({
5947
6533
  const total_products_to_fetch = to_fetch_according_to_state < min_products_to_fetch_ ? min_products_to_fetch_ : to_fetch_according_to_state + 20; // if we fetch according to state, fetch some more in case that the screen size increased, there's some in-accuracy or for the user to scroll. Sometimes the load more post processor will trigger to fetch more after this, but I think that's ok.
5948
6534
  if (total_products_to_fetch <= $276380e4607fb9fb$var$api_max_products_per_request) return await make_request_(total_products_to_fetch);
5949
6535
  const displays = [];
6536
+ const owner = $5vyXB$solidjs.getOwner();
5950
6537
  let last_response;
5951
6538
  let next_cursor;
5952
6539
  for (let fetch_this_time = $276380e4607fb9fb$var$api_max_products_per_request; displays.length < total_products_to_fetch;) {
5953
- last_response = await make_request_(fetch_this_time, next_cursor);
6540
+ // Carry over the request when making the owner so that display transformers can use onCleanup
6541
+ last_response = await $5vyXB$solidjs.runWithOwner(owner, () => make_request_(fetch_this_time, next_cursor));
5954
6542
  const new_displays = last_response.displays;
5955
6543
  displays.push(...new_displays);
5956
6544
  next_cursor = last_response.cursor;
@@ -6064,7 +6652,7 @@ function $47e2cc552c02110c$export$8895d39404bd2bb1(props) {
6064
6652
  }
6065
6653
  function $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6066
6654
  crumb_data_: crumb_data_,
6067
- query_id_: query_id_,
6655
+ listing_id_: listing_id_,
6068
6656
  i18n_: i18n_,
6069
6657
  selected_filters_: selected_filters_,
6070
6658
  local_filter_cache_: local_filter_cache_,
@@ -6083,15 +6671,15 @@ function $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6083
6671
  });
6084
6672
  // Code below is for when we're already open and the user navigates to a new category
6085
6673
  let previous_crumb_data = $5vyXB$solidjs.untrack(crumb_data_);
6086
- let query_id_when_we_got_previous_data = $5vyXB$solidjs.untrack(query_id_);
6674
+ let listing_id_when_we_got_previous_data = $5vyXB$solidjs.untrack(listing_id_);
6087
6675
  let allow_filter_clearing = true; // set to false when going backwards/forwards
6088
6676
  // temporarily disable filter clearing when going backwards/forwards
6089
6677
  const handler = () => allow_filter_clearing = false;
6090
6678
  window.addEventListener("popstate", handler); // popstate only gets called when using back/forwards button of browser or the history navigate to achieve the same, but not on pushState or replaceState
6091
6679
  $5vyXB$solidjs.onCleanup(() => window.removeEventListener("popstate", handler));
6092
6680
  $5vyXB$solidjs.createEffect($5vyXB$solidjs.on(crumb_data_, $5vyXB$depictaiutilishared.catchify(new_crumb_data => {
6093
- const query_id_of_new_data = query_id_();
6094
- if (allow_filter_clearing && previous_crumb_data && new_crumb_data && query_id_of_new_data !== query_id_when_we_got_previous_data) {
6681
+ const listing_id_of_new_data = listing_id_();
6682
+ if (allow_filter_clearing && previous_crumb_data && new_crumb_data && listing_id_of_new_data !== listing_id_when_we_got_previous_data) {
6095
6683
  const previous_length = previous_crumb_data.length;
6096
6684
  const new_length = new_crumb_data.length;
6097
6685
  const went_upwards = new_length < previous_length;
@@ -6099,8 +6687,8 @@ function $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6099
6687
  const shorter_array = went_upwards ? new_crumb_data : previous_crumb_data;
6100
6688
  const longer_array = went_upwards ? previous_crumb_data : new_crumb_data;
6101
6689
  if (!((went_upwards || went_downwards) && shorter_array.every(({
6102
- query_id: query_id
6103
- }, index) => longer_array[index].query_id === query_id))) {
6690
+ listing_id: listing_id
6691
+ }, index) => longer_array[index].listing_id === listing_id))) {
6104
6692
  // We went sideways, not up or down. Clear filters.
6105
6693
  $47e2cc552c02110c$export$8895d39404bd2bb1({
6106
6694
  user_triggered_: false,
@@ -6114,7 +6702,7 @@ function $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6114
6702
  sideways_filter_clearing_flag_[1](false);
6115
6703
  }
6116
6704
  }
6117
- query_id_when_we_got_previous_data = query_id_of_new_data;
6705
+ listing_id_when_we_got_previous_data = listing_id_of_new_data;
6118
6706
  previous_crumb_data = new_crumb_data;
6119
6707
  if (!allow_filter_clearing) allow_filter_clearing = true;
6120
6708
  })));
@@ -6146,7 +6734,6 @@ function $ef972f5c10b1c5b4$var$clear_if_opened_new_tab_with_sideways_url_params_
6146
6734
  });
6147
6735
  tracking_function_for_plp_results(plp_results_);
6148
6736
  }
6149
- const $6b502b1b2155a0bc$export$5c28802497c8a83c = /*@__PURE__*/Symbol("category_title_type");
6150
6737
  function $6a8e766e914723d8$export$d31a1a1a83ad9413(plp_results_, [get_selected_filters, set_selected_filters]) {
6151
6738
  $5vyXB$solidjs.createComputed(() => {
6152
6739
  const available_filters = plp_results_()?.filters;
@@ -6178,8 +6765,7 @@ const $840d88a04b2d22a7$var$_tmpl$ = ["<div", ' class="product-count"><!--$-->',
6178
6765
  $840d88a04b2d22a7$var$_tmpl$4 = ["<div", ' class="depict plp category"><div class="listing-page"><!--$-->', "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></div><!--$-->", "<!--/--><!--$-->", "<!--/--></div>"];
6179
6766
  function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6180
6767
  depict_api_: depict_api_,
6181
- query_id_: query_id_,
6182
- listing_type_: listing_type_,
6768
+ listing_id_: listing_id_,
6183
6769
  meta_title_suffix_: meta_title_suffix_,
6184
6770
  current_sorting_: current_sorting_,
6185
6771
  min_products_to_fetch_: min_products_to_fetch_,
@@ -6192,7 +6778,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6192
6778
  get_breadcrumb_accessor_: get_breadcrumb_accessor_,
6193
6779
  expanded_hierarchical_filters_: expanded_hierarchical_filters_,
6194
6780
  local_filter_cache_: local_filter_cache_,
6195
- tenant_: tenant_,
6781
+ merchant_: merchant_,
6196
6782
  market_: market_,
6197
6783
  router_: router_,
6198
6784
  show_quicklinks_: show_quicklinks_,
@@ -6215,22 +6801,25 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6215
6801
  show_n_results_: incoming_i18n.show_n_products_,
6216
6802
  no_results_text_: incoming_i18n.no_products_text_
6217
6803
  };
6804
+ const {
6805
+ backend_locale_: backend_locale_
6806
+ } = i18n_;
6218
6807
  const [get_sorting] = current_sorting_;
6219
6808
  const number_of_rendered_selected_filters_items_ = $5vyXB$solidjs.createSignal(0);
6220
6809
  const first_result_in_viewport_ = $5vyXB$solidjs.createSignal();
6221
6810
  const last_result_in_viewport_ = $5vyXB$solidjs.createSignal();
6222
6811
  const [can_write_scroll_restoration_, set_can_write_scroll_restoration] = $5vyXB$solidjs.createSignal(false);
6223
- const query_base_ = $8cd545330f2674dc$export$210f130a61ac1e8d(() => {
6812
+ const products_query_base_ = $8cd545330f2674dc$export$210f130a61ac1e8d(() => {
6224
6813
  const sort_obj = get_sorting() && {
6225
6814
  ...get_sorting()
6226
6815
  };
6227
6816
  delete sort_obj?.meta;
6228
6817
  const f = selected_filters_[0]();
6229
6818
  return {
6230
- tenant: tenant_(),
6819
+ merchant: merchant_(),
6231
6820
  market: market_(),
6232
- query_id: query_id_(),
6233
- type: listing_type_(),
6821
+ locale: backend_locale_(),
6822
+ listing_id: listing_id_(),
6234
6823
  ...(f.length ? {
6235
6824
  filters: f
6236
6825
  } : {}),
@@ -6239,13 +6828,14 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6239
6828
  } : {})
6240
6829
  };
6241
6830
  });
6242
- const [plp_results_] = $5vyXB$solidjs.createResource(query_base_,
6831
+ // Make "Get products in listing" request to get products in listing
6832
+ const [plp_products_] = $5vyXB$solidjs.createResource(products_query_base_,
6243
6833
  // only first page of results, unless the history state says we should load more (can't do that in load more thing, I tested, they need to be added at once for the browser to not give up scroll restoration)
6244
6834
  $5vyXB$depictaiutilishared.catchify(base_query => $276380e4607fb9fb$export$cc42dd29bf655ab6({
6245
- id_: $5vyXB$solidjs.untrack(query_id_),
6835
+ id_: $5vyXB$solidjs.untrack(listing_id_),
6246
6836
  scroll_restoration_data_: scroll_restoration_data_,
6247
6837
  min_products_to_fetch_: min_products_to_fetch_,
6248
- make_request_: (limit, cursor) => depict_api_.list({
6838
+ make_request_: (limit, cursor) => depict_api_.get_listing_products({
6249
6839
  ...base_query,
6250
6840
  limit: limit,
6251
6841
  ...(cursor ? {
@@ -6253,24 +6843,33 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6253
6843
  } : {})
6254
6844
  })
6255
6845
  })));
6256
- const available_sortings_ = $5vyXB$solidjs.createMemo(() => plp_results_()?.sorts?.map(sort => ({
6846
+ const meta_query_base = $8cd545330f2674dc$export$210f130a61ac1e8d(() => ({
6847
+ merchant: merchant_(),
6848
+ market: market_(),
6849
+ locale: backend_locale_(),
6850
+ listing_id: listing_id_()
6851
+ }));
6852
+ // Make "Get Listing" request to get quicklinks, breadcrumbs, title, etc
6853
+ const [plp_meta] = $5vyXB$solidjs.createResource(meta_query_base, $5vyXB$depictaiutilishared.catchify(query => depict_api_.get_listing(query)));
6854
+ const available_sortings_ = $5vyXB$solidjs.createMemo(() => plp_products_()?.sorts?.map(sort => ({
6257
6855
  ...sort,
6258
6856
  order: sort.order ?? "desc"
6259
6857
  })));
6260
- const available_filters_ = $5vyXB$solidjs.createMemo(() => plp_results_()?.filters);
6261
- const crumb_data_ = $5vyXB$solidjs.createMemo(() => plp_results_()?.breadcrumb);
6262
- const quicklinks_data_ = $5vyXB$solidjs.createMemo(() => plp_results_()?.quick_links);
6858
+ const available_filters_ = $5vyXB$solidjs.createMemo(() => plp_products_()?.filters);
6859
+ const title = $5vyXB$solidjs.createMemo(() => plp_meta()?.title);
6860
+ const crumb_data_ = $840d88a04b2d22a7$var$add_us_to_crumbs(plp_meta, title);
6861
+ const quicklinks_data_ = $5vyXB$solidjs.createMemo(() => plp_meta()?.quick_links);
6263
6862
  const meta_tag_data_ = $5vyXB$solidjs.createMemo(() => {
6264
- if (plp_results_()?.metadata?.replace_meta_tags) return {
6265
- title: plp_results_()?.metadata?.title + (meta_title_suffix_() || ""),
6266
- description: plp_results_()?.metadata?.description
6863
+ if (plp_meta()?.replace_meta_tags) return {
6864
+ title: plp_meta()?.title + (meta_title_suffix_() || ""),
6865
+ description: plp_meta()?.description
6267
6866
  };
6268
6867
  });
6269
6868
  $5vyXB$depictaiutilishared.edit_current_page_meta_tags(meta_tag_data_);
6270
6869
  const [sort_or_filter_open_, set_sort_or_filter_open_] = $5vyXB$solidjs.createSignal(false);
6271
6870
  const [desktop_filter_elements_, set_desktop_filter_elements] = $5vyXB$solidjs.createSignal();
6272
6871
  const formatted_number_of_results_ = $0f400c3f7248d5f1$export$92f2da32c6e7e7ee({
6273
- number_: $5vyXB$solidjs.createMemo(() => plp_results_()?.n_hits),
6872
+ number_: $5vyXB$solidjs.createMemo(() => plp_products_()?.n_hits),
6274
6873
  i18n_: i18n_
6275
6874
  });
6276
6875
  const [sort_and_filter_element_, set_sort_and_filter_element_] = $5vyXB$solidjs.createSignal();
@@ -6282,7 +6881,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6282
6881
  const extra_sort_and_filter_args_ = {};
6283
6882
  const make_product_count_ = () => $5vyXB$solidjsweb.ssr($840d88a04b2d22a7$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
6284
6883
  get when() {
6285
- return plp_results_.loading;
6884
+ return plp_products_.loading;
6286
6885
  },
6287
6886
  fallback: formatted_number_of_results_,
6288
6887
  get children() {
@@ -6293,7 +6892,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6293
6892
  }
6294
6893
  })), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
6295
6894
  get when() {
6296
- return plp_results_()?.n_hits === 1;
6895
+ return plp_products_()?.n_hits === 1;
6297
6896
  },
6298
6897
  get fallback() {
6299
6898
  return i18n_.products_();
@@ -6302,11 +6901,10 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6302
6901
  return i18n_.product_();
6303
6902
  }
6304
6903
  })));
6305
- $6a8e766e914723d8$export$d31a1a1a83ad9413(plp_results_, selected_filters_);
6904
+ $6a8e766e914723d8$export$d31a1a1a83ad9413(plp_products_, selected_filters_);
6306
6905
  // aiming to have as little unneeded functionality in the bundle as possible, therefore we have two kinds of components that can "plug in" here depending on if there should be a title in the category page along with the count in a row above the buttons on mobile or if it should merge between the buttons when possible
6307
6906
  if (category_title_type === "simple") {
6308
6907
  const CategoryTitleComponent = category_title_;
6309
- const title = $5vyXB$solidjs.createMemo(() => crumb_data_()?.at(-1)?.title ?? plp_results_()?.metadata?.title);
6310
6908
  results_for = $5vyXB$solidjsweb.createComponent(CategoryTitleComponent, {
6311
6909
  category_title_: title,
6312
6910
  get product_count_() {
@@ -6352,12 +6950,12 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6352
6950
  $5vyXB$depictaiutilishared.catchify((0, $276380e4607fb9fb$export$6e49da55e449af7c))({
6353
6951
  scroll_restoration_data_: scroll_restoration_data_,
6354
6952
  last_result_in_viewport_: last_result_in_viewport_,
6355
- id_: query_id_,
6953
+ id_: listing_id_,
6356
6954
  can_write_scroll_restoration_: can_write_scroll_restoration_
6357
6955
  });
6358
6956
  on_filters_constructed_?.();
6359
6957
  $5vyXB$solidjs.createComputed(() => {
6360
- if (plp_results_.loading) set_can_write_scroll_restoration(false);else if (plp_results_()) set_can_write_scroll_restoration(true);
6958
+ if (plp_products_.loading) set_can_write_scroll_restoration(false);else if (plp_products_()) set_can_write_scroll_restoration(true);
6361
6959
  });
6362
6960
  $5vyXB$solidjs.createRenderEffect($5vyXB$depictaiutilishared.catchify(async () => {
6363
6961
  const slim = is_slim_();
@@ -6372,13 +6970,13 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6372
6970
  available_filters_: available_filters_
6373
6971
  });
6374
6972
  $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6375
- query_id_: query_id_,
6973
+ listing_id_: listing_id_,
6376
6974
  crumb_data_: crumb_data_,
6377
6975
  i18n_: i18n_,
6378
6976
  selected_filters_: selected_filters_,
6379
6977
  local_filter_cache_: local_filter_cache_,
6380
6978
  expanded_hierarchical_filters_: expanded_hierarchical_filters_,
6381
- plp_results_: plp_results_,
6979
+ plp_results_: plp_products_,
6382
6980
  sideways_filter_clearing_flag_: sideways_filter_clearing_flag_
6383
6981
  });
6384
6982
  get_breadcrumb_accessor_?.(crumb_data_);
@@ -6403,7 +7001,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6403
7001
  get children() {
6404
7002
  return $5vyXB$solidjsweb.createComponent((0, $8cceb1d3a967f369$export$466cdc317043f6cb), {
6405
7003
  quicklinks_data_: quicklinks_data_,
6406
- current_query_id_: query_id_,
7004
+ current_listing_id_: listing_id_,
6407
7005
  router_: router_,
6408
7006
  breadcrumb_data_: crumb_data_,
6409
7007
  i18n_: i18n_,
@@ -6442,8 +7040,8 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6442
7040
  min_products_to_fetch_:
6443
7041
  // if you want to get if all products have been loaded you can add an optional signal here, see SearchPage
6444
7042
  min_products_to_fetch_,
6445
- query_base_: query_base_,
6446
- plp_results_: plp_results_,
7043
+ query_base_: products_query_base_,
7044
+ plp_results_: plp_products_,
6447
7045
  depict_api_: depict_api_,
6448
7046
  first_result_in_viewport_: first_result_in_viewport_,
6449
7047
  last_result_in_viewport_: last_result_in_viewport_,
@@ -6453,7 +7051,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6453
7051
  sort_or_filter_open_: sort_or_filter_open_,
6454
7052
  desktop_filter_elements_: desktop_filter_elements_,
6455
7053
  content_blocks_by_row_: content_blocks_by_row_,
6456
- id_currently_querying_for_: query_id_,
7054
+ id_currently_querying_for_: listing_id_,
6457
7055
  no_results_options_: {
6458
7056
  selected_filters_: selected_filters_,
6459
7057
  expanded_hierarchical_filters_: expanded_hierarchical_filters_,
@@ -6473,7 +7071,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6473
7071
  last_result_in_viewport_: last_result_in_viewport_,
6474
7072
  formatted_number_of_results_: formatted_number_of_results_,
6475
7073
  i18n_: i18n_,
6476
- number_of_results_: $5vyXB$solidjs.createMemo(() => plp_results_()?.n_hits)
7074
+ number_of_results_: $5vyXB$solidjs.createMemo(() => plp_products_()?.n_hits)
6477
7075
  });
6478
7076
  }
6479
7077
  })), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $edafe91daf3091d7$export$b69d0d92862de18b), {
@@ -6490,16 +7088,40 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6490
7088
  }
6491
7089
  })))];
6492
7090
  }
7091
+ /**
7092
+ * Adds the current page as last breadcrumb to the breadcrumb trail
7093
+ */
7094
+ function $840d88a04b2d22a7$var$add_us_to_crumbs(plp_meta, title) {
7095
+ const href_accessor = $5vyXB$depictaiutilishared.use_href_accessor();
7096
+ return $5vyXB$solidjs.createMemo(() => {
7097
+ const api_value = plp_meta()?.breadcrumbs;
7098
+ if (!api_value) return api_value;
7099
+ return [...api_value, {
7100
+ get listing_id() {
7101
+ return plp_meta().listing_id;
7102
+ },
7103
+ get title() {
7104
+ return title();
7105
+ },
7106
+ get page_url() {
7107
+ return href_accessor();
7108
+ },
7109
+ get slug() {
7110
+ return plp_meta().slug;
7111
+ }
7112
+ }];
7113
+ });
7114
+ }
6493
7115
  function $c79fd10a3ab7d6e0$export$477caf01aecaeb2a(options) {
6494
7116
  const router_ = options.router_;
6495
7117
  const search_query_url_param_name_ = "search_query_url_param_name_" in options ? options.search_query_url_param_name_ : undefined;
6496
7118
  const search_query_ = search_query_url_param_name_ ? $5vyXB$solidjs.createSignal("") : undefined;
6497
- const override_query_id_query_param_names_ = "override_query_id_query_param_names_" in options ? options.override_query_id_query_param_names_ : undefined;
6498
- const override_query_id_ = override_query_id_query_param_names_ ? $5vyXB$solidjs.createSignal(null) : undefined;
7119
+ const override_listing_id_query_param_names_ = "override_listing_id_query_param_names_" in options ? options.override_listing_id_query_param_names_ : undefined;
7120
+ const override_listing_id_ = override_listing_id_query_param_names_ ? $5vyXB$solidjs.createSignal(null) : undefined;
6499
7121
  const get_search_query_ = search_query_?.[0];
6500
7122
  const set_search_query = search_query_?.[1];
6501
- const get_override_query_id_ = override_query_id_?.[0];
6502
- const set_override_query_id = override_query_id_?.[1];
7123
+ const get_override_listing_id_ = override_listing_id_?.[0];
7124
+ const set_override_listing_id = override_listing_id_?.[1];
6503
7125
  const current_sorting_ = $5vyXB$solidjs.createSignal();
6504
7126
  const selected_filters_ = $5vyXB$solidjs.createSignal([]);
6505
7127
  const sideways_filter_clearing_flag_ = $5vyXB$solidjs.createSignal(false);
@@ -6544,10 +7166,10 @@ function $c79fd10a3ab7d6e0$export$477caf01aecaeb2a(options) {
6544
7166
  const found_query = searchParams.get(search_query_url_param_name_);
6545
7167
  set_search_query(found_query || "");
6546
7168
  }
6547
- if (override_query_id_query_param_names_) {
6548
- const found_override_query_id = override_query_id_query_param_names_.map(n => searchParams.get(n)).find(n => n);
6549
- set_override_query_id(found_override_query_id || null);
6550
- if (found_override_query_id) $5vyXB$depictaiutilishared.dlog("Found override query id:", found_override_query_id); // This stuff might get confusing so better log it
7169
+ if (override_listing_id_query_param_names_) {
7170
+ const found_override_listing_id = override_listing_id_query_param_names_.map(n => searchParams.get(n)).find(n => n);
7171
+ set_override_listing_id(found_override_listing_id || null);
7172
+ if (found_override_listing_id) $5vyXB$depictaiutilishared.dlog("Found override query id:", found_override_listing_id); // This stuff might get confusing so better log it
6551
7173
  }
6552
7174
 
6553
7175
  if (searchParams.get((0, $1ab22f2cd39b3061$export$cf5feb2102aec7f2)) === "true") set_has_sideways_filter_clearing_flag(true);
@@ -6574,8 +7196,8 @@ function $c79fd10a3ab7d6e0$export$477caf01aecaeb2a(options) {
6574
7196
  } : {
6575
7197
  sideways_filter_clearing_flag_: sideways_filter_clearing_flag_
6576
7198
  }),
6577
- ...(typeof override_query_id_query_param_names_ === "object" ? {
6578
- override_query_id_accessor_: get_override_query_id_
7199
+ ...(typeof override_listing_id_query_param_names_ === "object" ? {
7200
+ override_listing_id_accessor_: get_override_listing_id_
6579
7201
  } : {})
6580
7202
  };
6581
7203
  }
@@ -6620,108 +7242,6 @@ function $c79fd10a3ab7d6e0$var$start_href_writer({
6620
7242
  function $c79fd10a3ab7d6e0$var$delete_sideways_param_flag(searchParams) {
6621
7243
  if (searchParams.get((0, $1ab22f2cd39b3061$export$cf5feb2102aec7f2)) === "true") searchParams.delete((0, $1ab22f2cd39b3061$export$cf5feb2102aec7f2));
6622
7244
  }
6623
- class $e96dd13889871fc0$export$7e1297a3a19f10d8 {
6624
- /**
6625
- * Function that will be called when we want to navigate, or a string saying it's not an SPA. You can change this OTG
6626
- */ /**
6627
- * We store query_id in history.state and do operate on this both here and in js-ui, this is the key to be used which js-ui provides
6628
- */
6629
- #throwing_on_navigation(...args) {
6630
- const {
6631
- on_navigation_: on_navigation_
6632
- } = this;
6633
- if (typeof on_navigation_ !== "function") throw new Error("on_navigation_ is not a function");
6634
- // make sure that we don't accidentally catchify if the SDK consumer has fucked up
6635
- try {
6636
- return on_navigation_(...args);
6637
- } catch (e) {
6638
- queueMicrotask(() => {
6639
- throw e;
6640
- });
6641
- }
6642
- }
6643
- /**
6644
- * Checks if this tab shouldn't navigate because user wants to open in new tab
6645
- */
6646
- #dont_attempt_navigation(ev) {
6647
- return ev?.button || ev?.metaKey || ev?.ctrlKey;
6648
- }
6649
- /**
6650
- * Vue has async router that needs to be awaited (it navigates after a microtask)
6651
- * This standardises waiting for all kinds of routers
6652
- */
6653
- #get_navigation_happened_promise(is_replace) {
6654
- return new Promise(resolve => {
6655
- const handler = what_happened => {
6656
- if (what_happened === (is_replace ? "replaceState" : "pushState")) {
6657
- resolve();
6658
- (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(handler);
6659
- }
6660
- };
6661
- (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(handler);
6662
- });
6663
- }
6664
- navigate_ = {
6665
- /**
6666
- * Call this if you *just* want to replace the state object in history.state
6667
- */
6668
- replace_state_: new_state => {
6669
- // This doesn't break any router, so we just do this directly for now, since many don't expose an interface for changing the state
6670
- globalThis?.history?.replaceState(new_state, "");
6671
- },
6672
- /**
6673
- * Call this to change the URL
6674
- * @param new_url_ new URL to go to
6675
- * @param event_ event if you have this in a click handler, will not do anything on cmd/ctrl or non-left click then
6676
- * @param force_spa_navigation_ if you want to force SPA navigation even if on_navigation_ is set to "hard_navigation". You should only set this to true for inter-SDK-page navigations
6677
- * @param is_replace_ if you want to replace the current URL in history instead of pushing a new one
6678
- * @param category_query_id_ If you are navigating to a category and know the query_id of, please provide it. This is for making a better devEx in js-ui
6679
- */
6680
- go_to_: $5vyXB$depictaiutilishared.catchify(async ({
6681
- new_url_: raw_new_url,
6682
- event_: event_,
6683
- force_spa_navigation_: force_spa_navigation_,
6684
- is_replace_: is_replace_,
6685
- category_query_id_: category_query_id_,
6686
- scroll = true
6687
- }) => {
6688
- const new_url_ = raw_new_url instanceof URL ? raw_new_url : new URL(raw_new_url, location.origin);
6689
- const wants_hard_navigation = this.on_navigation_ === "hard_navigation";
6690
- if (this.#dont_attempt_navigation(event_)) return;
6691
- const different_origin = new_url_.origin !== location.origin;
6692
- if (wants_hard_navigation && (!force_spa_navigation_ || different_origin)) {
6693
- if (force_spa_navigation_ && different_origin)
6694
- // If we call history.pushState on a different origin, it will throw an error, so fallback to hard navigations
6695
- $5vyXB$depictaiutilishared.dwarn("Can't single page navigate to", new_url_.href, "due to different origin, this MIGHT mean you should fix the URLs");
6696
- if (!event_)
6697
- // If we haven't gotten an event, nothing will happen by not calling prevent default, so we need to change the URL
6698
- location.assign(new_url_);
6699
- return;
6700
- }
6701
- event_?.preventDefault();
6702
- const promise = this.#get_navigation_happened_promise(true);
6703
- if (force_spa_navigation_ && wants_hard_navigation) {
6704
- // Don't allow hard navigation if we're forcing SPA navigation, which we do for things where PageReplacer can be used for performance
6705
- const new_state = history.state;
6706
- if (category_query_id_) {
6707
- // In JS-UI we need to know the query_id of the current category, therefore push it into state
6708
- if (!this.query_id_state_key) $5vyXB$depictaiutilishared.report(new Error("query_id_state_key is not set"), "error");
6709
- new_state[this.query_id_state_key] = category_query_id_;
6710
- }
6711
- history[is_replace_ ? "replaceState" : "pushState"](new_state, "", new_url_);
6712
- } else this.#throwing_on_navigation.call(this, {
6713
- is_replace: is_replace_,
6714
- new_url: new_url_ instanceof URL ? new_url_ : new URL(new_url_, location.origin),
6715
- scroll: scroll
6716
- });
6717
- await promise;
6718
- })
6719
- };
6720
- constructor(on_navigation, query_id_state_key) {
6721
- this.query_id_state_key = query_id_state_key;
6722
- this.on_navigation_ = on_navigation;
6723
- }
6724
- }
6725
7245
 
6726
7246
  /**
6727
7247
  * Wraps a function in a try/catch block and throws the error globally. If undefined is provided as fn, a no-op is returned.
@@ -6752,26 +7272,25 @@ const $48567ac5b39bac56$var$InExternalAreaDiv = ({
6752
7272
  }) => $5vyXB$solidjsweb.ssr($48567ac5b39bac56$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey() + $5vyXB$solidjsweb.ssrAttribute("id", $5vyXB$solidjsweb.escape((0, $0b6e2070a98de347$export$44dad306455dddf).PLP_CATEGORY, true), false), $5vyXB$solidjsweb.escape(children));
6753
7273
  class $48567ac5b39bac56$export$f34314aa9505732e {
6754
7274
  #router;
6755
- #locale_signal = $5vyXB$solidjs.createSignal();
7275
+ #localization_signal = $5vyXB$solidjs.createSignal();
6756
7276
  #merchant_signal = $5vyXB$solidjs.createSignal();
6757
7277
  #market_signal = $5vyXB$solidjs.createSignal();
6758
- #query_id_signal = $5vyXB$solidjs.createSignal("");
7278
+ #listing_id_signal = $5vyXB$solidjs.createSignal("");
6759
7279
  #meta_title_suffix_ = $5vyXB$solidjs.createSignal();
6760
- #disable_override_query_id = $5vyXB$solidjs.createSignal();
6761
- #listing_type_signal = $5vyXB$solidjs.createSignal();
7280
+ #disable_override_listing_id = $5vyXB$solidjs.createSignal();
6762
7281
  static #keys_constructed_with = /*@__PURE__*/new Set();
6763
7282
  get localization() {
6764
7283
  // allow reactive access
6765
- return this.#locale_signal[0]();
7284
+ return this.#localization_signal[0]();
6766
7285
  }
6767
7286
  set localization(locale_obj) {
6768
- this.#locale_signal[1](locale_obj);
7287
+ this.#localization_signal[1](locale_obj);
6769
7288
  }
6770
- get category_id() {
6771
- return this.#query_id_signal[0]();
7289
+ get listing_id() {
7290
+ return this.#listing_id_signal[0]();
6772
7291
  }
6773
- set category_id(id) {
6774
- this.#query_id_signal[1](id);
7292
+ set listing_id(id) {
7293
+ this.#listing_id_signal[1](id);
6775
7294
  }
6776
7295
  get merchant() {
6777
7296
  return this.#merchant_signal[0]();
@@ -6785,23 +7304,17 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6785
7304
  set market(market) {
6786
7305
  this.#market_signal[1](market);
6787
7306
  }
6788
- get listing_type() {
6789
- return this.#listing_type_signal[0]();
6790
- }
6791
- set listing_type(listing_type) {
6792
- this.#listing_type_signal[1](listing_type);
6793
- }
6794
7307
  get meta_title_suffix() {
6795
7308
  return this.#meta_title_suffix_[0]();
6796
7309
  }
6797
7310
  set meta_title_suffix(new_suffix) {
6798
7311
  this.#meta_title_suffix_[1](new_suffix);
6799
7312
  }
6800
- get disable_override_query_id() {
6801
- return this.#disable_override_query_id[0]();
7313
+ get disable_override_listing_id() {
7314
+ return this.#disable_override_listing_id[0]();
6802
7315
  }
6803
- set disable_override_query_id(new_value) {
6804
- this.#disable_override_query_id[1](new_value);
7316
+ set disable_override_listing_id(new_value) {
7317
+ this.#disable_override_listing_id[1](new_value);
6805
7318
  }
6806
7319
  get on_navigation() {
6807
7320
  // The only non-reactive public property on the class (I don't see it making sense to have it reactive)
@@ -6816,7 +7329,7 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6816
7329
  page_url_creator: page_url_creator,
6817
7330
  display_transformers: display_transformers,
6818
7331
  unique_instance_key_for_state = "",
6819
- query_id_state_key: query_id_state_key,
7332
+ listing_id_state_key: listing_id_state_key,
6820
7333
  ...props_on_class
6821
7334
  }) {
6822
7335
  const owner = $5vyXB$solidjs.getOwner() || $5vyXB$solidjs.createRoot(() => $5vyXB$solidjs.getOwner()); // we might have an owner, if so, pass it on. Otherwise, create one so solid doesn't print warnings to the console
@@ -6826,21 +7339,21 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6826
7339
  throw new Error("You can only have one instance of DepictCategory with the same uniqueInstanceKeyForState");
6827
7340
  Object.assign(this, props_on_class); // set initial signal values
6828
7341
  $d84fe647b84b5dc5$export$5162a71f252e6122();
6829
- this.#router = new (0, $e96dd13889871fc0$export$7e1297a3a19f10d8)("hard_navigation", query_id_state_key);
7342
+ this.#router = new (0, $e96dd13889871fc0$export$7e1297a3a19f10d8)("hard_navigation", listing_id_state_key);
6830
7343
  if (on_navigation) this.#router.on_navigation_ = on_navigation;
6831
- const override_query_id_query_param_names_ = ["query_id_" + unique_instance_key_for_state, "query_id"]; // If you're wondering why this is an array https://gitlab.com/depict-ai/depict.ai/-/merge_requests/7958#note_1511700842
7344
+ const override_listing_id_query_param_names_ = ["listing_id_" + unique_instance_key_for_state, "listing_id"]; // If you're wondering why this is an array https://gitlab.com/depict-ai/depict.ai/-/merge_requests/7958#note_1511700842
6832
7345
  const sorting_query_param_ = "sorting" + unique_instance_key_for_state;
6833
7346
  const filter_query_param_prefix_ = "f" + unique_instance_key_for_state + "_";
6834
7347
  const {
6835
7348
  selected_filters_: selected_filters_,
6836
7349
  current_sorting_: current_sorting_,
6837
7350
  sideways_filter_clearing_flag_: sideways_filter_clearing_flag_,
6838
- override_query_id_accessor_: override_query_id_accessor_
7351
+ override_listing_id_accessor_: override_listing_id_accessor_
6839
7352
  } = $c79fd10a3ab7d6e0$export$477caf01aecaeb2a({
6840
7353
  router_: this.#router,
6841
7354
  sorting_query_param_: sorting_query_param_,
6842
7355
  filter_query_param_prefix_: filter_query_param_prefix_,
6843
- override_query_id_query_param_names_: override_query_id_query_param_names_
7356
+ override_listing_id_query_param_names_: override_listing_id_query_param_names_
6844
7357
  });
6845
7358
  const [reset_history_state_, state_] = $26a56f6b44703084$export$9862539c89138352({
6846
7359
  get_default_values_: () => ({
@@ -6855,7 +7368,7 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6855
7368
  router_: this.#router,
6856
7369
  prefix_: "category" + unique_instance_key_for_state + "_"
6857
7370
  });
6858
- const i18n_ = $0785f4c9947d9b5f$export$f091cbac892643a4(this.#locale_signal[0]);
7371
+ const i18n_ = $0785f4c9947d9b5f$export$f091cbac892643a4(this.#localization_signal[0]);
6859
7372
  $48567ac5b39bac56$var$privately_shared_properties.set(this, {
6860
7373
  state_: state_,
6861
7374
  breadcrumb_signal_: $5vyXB$solidjs.createSignal(),
@@ -6870,7 +7383,7 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6870
7383
  router_: this.#router,
6871
7384
  selected_filters_: selected_filters_,
6872
7385
  current_sorting_: current_sorting_,
6873
- override_query_id_accessor_: override_query_id_accessor_,
7386
+ override_listing_id_accessor_: override_listing_id_accessor_,
6874
7387
  sideways_filter_clearing_flag_: sideways_filter_clearing_flag_,
6875
7388
  sorting_query_param_: sorting_query_param_,
6876
7389
  filter_query_param_prefix_: filter_query_param_prefix_
@@ -6890,11 +7403,11 @@ function $48567ac5b39bac56$export$e2bf8ce7779e827e(props) {
6890
7403
  return $95837413165cc2df$export$23fca46f3143581f(() => {
6891
7404
  $5vyXB$solidjs.createEffect(prev => {
6892
7405
  // this is here (and not on DepictCategory) so that people also know when PageReplacer removes the page, it's intended to help people replace their own content when a depict page is navigated, see https://depictaiworkspace.slack.com/archives/C04M8MGCF3K/p1691670636155369
6893
- const id = depict_category.category_id; // <- this is a reactive getter
6894
- $deaaf04362a1bc71$export$f50b88e2a00918b5(props.on_query_id_change)(id, prev);
7406
+ const id = depict_category.listing_id; // <- this is a reactive getter
7407
+ $deaaf04362a1bc71$export$f50b88e2a00918b5(props.on_listing_id_change)(id, prev);
6895
7408
  return id;
6896
7409
  });
6897
- $5vyXB$solidjs.onCleanup(() => $deaaf04362a1bc71$export$f50b88e2a00918b5(props.on_query_id_change)());
7410
+ $5vyXB$solidjs.onCleanup(() => $deaaf04362a1bc71$export$f50b88e2a00918b5(props.on_listing_id_change)());
6898
7411
  const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
6899
7412
  const {
6900
7413
  grid_spacing: grid_spacing
@@ -6917,7 +7430,7 @@ function $48567ac5b39bac56$export$e2bf8ce7779e827e(props) {
6917
7430
  },
6918
7431
  current_sorting_: current_sorting_,
6919
7432
  selected_filters_: selected_filters_,
6920
- override_query_id_accessor_: override_query_id_accessor_,
7433
+ override_listing_id_accessor_: override_listing_id_accessor_,
6921
7434
  reset_history_state_: reset_history_state_,
6922
7435
  depict_api_: depict_api_,
6923
7436
  i18n_: i18n_,
@@ -6930,14 +7443,13 @@ function $48567ac5b39bac56$export$e2bf8ce7779e827e(props) {
6930
7443
  } = shared_properties;
6931
7444
  $5vyXB$solidjs.onCleanup(reset_history_state_);
6932
7445
  return $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6933
- tenant_: () => depict_category.merchant,
7446
+ merchant_: () => depict_category.merchant,
6934
7447
  market_: () => depict_category.market,
6935
7448
  depict_api_: depict_api_,
6936
7449
  min_products_to_fetch_: $48567ac5b39bac56$var$min_products_to_fetch_,
6937
7450
  local_filter_cache_: local_filter_cache_,
6938
- query_id_: $5vyXB$solidjs.createMemo(() => !depict_category.disable_override_query_id && override_query_id_accessor_() || depict_category.category_id),
7451
+ listing_id_: $5vyXB$solidjs.createMemo(() => !depict_category.disable_override_listing_id && override_listing_id_accessor_() || depict_category.listing_id),
6939
7452
  meta_title_suffix_: () => depict_category.meta_title_suffix,
6940
- listing_type_: () => depict_category.listing_type,
6941
7453
  i18n_: i18n_,
6942
7454
  show_quicklinks_: $5vyXB$solidjs.createMemo(() => props.show_quicklinks ?? true),
6943
7455
  category_title_: category_title,
@@ -7003,7 +7515,7 @@ function $48567ac5b39bac56$export$de035477d6fef996({
7003
7515
  i18n_: i18n_,
7004
7516
  quicklinks_data_: quicklinks_data_,
7005
7517
  router_: router_,
7006
- current_query_id_: () => depict_category.category_id,
7518
+ current_listing_id_: () => depict_category.listing_id,
7007
7519
  breadcrumb_data_: breadcrumb_data_,
7008
7520
  sorting_query_param_: sorting_query_param_,
7009
7521
  filter_query_param_prefix_: filter_query_param_prefix_
@@ -7016,21 +7528,6 @@ function $48567ac5b39bac56$var$get_shared_properties(depict_category) {
7016
7528
  if (!shared_properties) throw new Error("Can't connect to provided DepictCategory instance");
7017
7529
  return shared_properties;
7018
7530
  }
7019
- const $0b23bfd073d9a4e8$var$_tmpl$ = ["<div", ' class="category-title"><h1 class="title">', '</h1><span class="explanation"> — <!--$-->', "<!--/--></span></div>"];
7020
- const $0b23bfd073d9a4e8$export$b91cec6bdc6b32a1 = /*@__PURE__*/(() => {
7021
- const actual_function = ({
7022
- category_title_: category_title_,
7023
- product_count_: product_count_
7024
- }) => {
7025
- return $5vyXB$solidjsweb.ssr($0b23bfd073d9a4e8$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(category_title_()) || $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $061ff5b4c3d36171$export$89c6019e4baa40b1), {
7026
- height: "1em",
7027
- width: "10ch"
7028
- })), $5vyXB$solidjsweb.escape(product_count_));
7029
- };
7030
- // This is wrong but parcel can't build correctly, it says unexpected undefined
7031
- actual_function[(0, $6b502b1b2155a0bc$export$5c28802497c8a83c)] = "simple";
7032
- return actual_function;
7033
- })();
7034
7531
  const $85b747260aa175c9$var$_tmpl$ = ["<div", ' class="sort-and-filter-buttons fake" aria-hidden="true" style="position:absolute;z-index:-1;pointer-events:none;opacity:0"><div class="outer"><div class="inner"><!--$-->', "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></div></div></div>"];
7035
7532
  const $85b747260aa175c9$export$824dde41348efed1 = /*@__PURE__*/(() => {
7036
7533
  const actual_function = ({
@@ -7115,11 +7612,11 @@ const $85b747260aa175c9$export$824dde41348efed1 = /*@__PURE__*/(() => {
7115
7612
  actual_function[(0, $6b502b1b2155a0bc$export$5c28802497c8a83c)] = "interactive";
7116
7613
  return actual_function;
7117
7614
  })();
7118
- const $63b10c9f461e0ef6$var$TEN_MINUTES = 600000;
7119
- const $63b10c9f461e0ef6$var$TWENTY_FOUR_HOURS = 86400000;
7120
- async function $63b10c9f461e0ef6$export$643598a327b5833e(tenant, market, type) {
7615
+ const $6382a1b83da39674$var$TEN_MINUTES = 600000;
7616
+ const $6382a1b83da39674$var$TWENTY_FOUR_HOURS = 86400000;
7617
+ async function $6382a1b83da39674$export$c1a6b039e689a58e(merchant, market, locale) {
7121
7618
  let localstorage_value;
7122
- const localstorage_key = `depict_${tenant}_${type ?? "categories"}_` + market;
7619
+ const localstorage_key = `depict_listings_${JSON.stringify([merchant, market, locale])}}`;
7123
7620
  try {
7124
7621
  const in_ls = localStorage[localstorage_key];
7125
7622
  if (in_ls) localstorage_value = JSON.parse(in_ls);
@@ -7131,20 +7628,20 @@ async function $63b10c9f461e0ef6$export$643598a327b5833e(tenant, market, type) {
7131
7628
  const stored_queries = localstorage_value?.queries;
7132
7629
  if (Array.isArray(stored_queries) && typeof updated === "number") {
7133
7630
  const age = now - updated;
7134
- if (stored_queries.length && age < $63b10c9f461e0ef6$var$TEN_MINUTES)
7631
+ if (stored_queries.length && age < $6382a1b83da39674$var$TEN_MINUTES)
7135
7632
  // if younger than 10 minutes and probably valid data, just return stored value
7136
- return stored_queries;else if (age < $63b10c9f461e0ef6$var$TWENTY_FOUR_HOURS) {
7633
+ return stored_queries;else if (age < $6382a1b83da39674$var$TWENTY_FOUR_HOURS) {
7137
7634
  // if younger than a day, return stored value but still trigger re-fetch, so we have fresh data next page load (stale data this one but never a delay)
7138
- $63b10c9f461e0ef6$var$fetch_and_store_categories(tenant, market, localstorage_key, type).catch(e => $5vyXB$depictaiutilishared.report([e, "couldn't fetch categories"], "warning"));
7635
+ $6382a1b83da39674$var$fetch_and_store_categories(merchant, market, locale, localstorage_key).catch(e => $5vyXB$depictaiutilishared.report([e, "couldn't fetch categories"], "warning"));
7139
7636
  return stored_queries;
7140
7637
  }
7141
7638
  // else: we are older and just fetch, store and return new queries
7142
7639
  }
7143
7640
 
7144
- return await $63b10c9f461e0ef6$var$fetch_and_store_categories(tenant, market, localstorage_key, type);
7641
+ return await $6382a1b83da39674$var$fetch_and_store_categories(merchant, market, locale, localstorage_key);
7145
7642
  }
7146
- async function $63b10c9f461e0ef6$var$fetch_and_store_categories(tenant, market, localstorage_key, type) {
7147
- const new_categories = await $63b10c9f461e0ef6$var$download_categories(tenant, market, type);
7643
+ async function $6382a1b83da39674$var$fetch_and_store_categories(merchant, market, locale, localstorage_key) {
7644
+ const new_categories = await $6382a1b83da39674$var$download_categories(merchant, market, locale);
7148
7645
  try {
7149
7646
  localStorage[localstorage_key] = JSON.stringify({
7150
7647
  updated: +new Date(),
@@ -7156,24 +7653,22 @@ async function $63b10c9f461e0ef6$var$fetch_and_store_categories(tenant, market,
7156
7653
 
7157
7654
  return new_categories;
7158
7655
  }
7159
- async function $63b10c9f461e0ef6$var$download_categories(tenant, market, type) {
7160
- const fetched = await $5vyXB$depictaiutilishared.fetch_retry((0, $5vyXB$depictaiutilishared.base_url) + "/v2/product-listing/queries", {
7161
- method: "POST",
7162
- body: JSON.stringify({
7163
- tenant: tenant,
7164
- market: market,
7165
- ...(type ? {
7166
- type: type
7167
- } : {})
7168
- })
7169
- });
7656
+ async function $6382a1b83da39674$var$download_categories(merchant, market, locale) {
7657
+ const url = new URL((0, $5vyXB$depictaiutilishared.base_url) + "/v3/listings");
7658
+ const request = {
7659
+ merchant: merchant,
7660
+ market: market,
7661
+ locale: locale
7662
+ };
7663
+ url.search = "" + new URLSearchParams(request);
7664
+ const fetched = await $5vyXB$depictaiutilishared.fetch_retry(url.href);
7170
7665
  if (!fetched) return [];
7171
7666
  try {
7172
7667
  if (fetched.status !== 200) {
7173
7668
  $5vyXB$depictaiutilishared.dlog("failed to fetch queries, server responded with", fetched.status, fetched, await fetched.text());
7174
7669
  return [];
7175
7670
  }
7176
- return (await fetched.json())?.query_ids;
7671
+ return await fetched.json();
7177
7672
  } catch (e) {
7178
7673
  $5vyXB$depictaiutilishared.dlog("failed to decode queries json", fetched, e);
7179
7674
  return [];
@@ -7284,8 +7779,6 @@ function $fb29c6201c369e39$export$7de92c4c2205ebf3({
7284
7779
  }));
7285
7780
  return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
7286
7781
  displays_by_key_: displays_by_key_,
7287
- merchant_: $5vyXB$solidjs.createMemo(() => search_query_base_().tenant),
7288
- market_: $5vyXB$solidjs.createMemo(() => search_query_base_().market),
7289
7782
  product_card_template_: product_card_template_
7290
7783
  });
7291
7784
  })();
@@ -7530,7 +8023,7 @@ const $6ae556e536054e87$var$_tmpl$ = ["<div", ' class="instant-results">', "</di
7530
8023
  function $6ae556e536054e87$export$62f101a8aa597bf8({
7531
8024
  depict_api_: depict_api_,
7532
8025
  search_field_value_: [get_search_field_value],
7533
- tenant_: tenant_,
8026
+ merchant_: merchant_,
7534
8027
  market_: market_,
7535
8028
  render_instant_card_: render_instant_card_,
7536
8029
  render_instant_card_placeholder_: render_instant_card_placeholder_,
@@ -7554,8 +8047,10 @@ function $6ae556e536054e87$export$62f101a8aa597bf8({
7554
8047
  timeout = setTimeout($5vyXB$depictaiutilishared.catchify(() => write_current_instant_query(value)), 250);
7555
8048
  });
7556
8049
  const [search_results] = $5vyXB$solidjs.createResource($5vyXB$solidjs.createMemo(() => ({
7557
- tenant: tenant_(),
8050
+ // <-- key order important, see comment below
8051
+ merchant: merchant_(),
7558
8052
  market: market_(),
8053
+ locale: i18n_.backend_locale_(),
7559
8054
  query: read_current_instant_query()
7560
8055
  })), $5vyXB$depictaiutilishared.catchify(variable_data => {
7561
8056
  return depict_api_.query({
@@ -7601,12 +8096,12 @@ function $6ae556e536054e87$export$62f101a8aa597bf8({
7601
8096
  const card = render_instant_card_ ? $5vyXB$solidjs.createMemo(() => render_instant_card_(d(), {
7602
8097
  index: i,
7603
8098
  i18n: $639c124c22b6cbaa$export$27b710c08412a7ad(i18n_),
7604
- merchant: tenant_(),
8099
+ merchant: merchant_(),
7605
8100
  market: market_()
7606
8101
  })) : $6ae613870d3380fc$export$b05c0ae390cf3e06(d, {
7607
8102
  index: i,
7608
8103
  i18n: i18n_,
7609
- merchant: tenant_(),
8104
+ merchant: merchant_(),
7610
8105
  market: market_()
7611
8106
  }, router_);
7612
8107
  return card;
@@ -8059,7 +8554,7 @@ function $3ec9e21d6b6debdd$export$2f2b9559550c7bbc({
8059
8554
  previous_searches_: [unfiltered_previous_searches, set_unfiltered_previous_searches_],
8060
8555
  previous_searches_text_: previous_searches_text_,
8061
8556
  depict_api_: depict_api_,
8062
- tenant_: tenant_,
8557
+ merchant_: merchant_,
8063
8558
  market_: market_,
8064
8559
  input_field_: input_field_,
8065
8560
  url_transformer_: url_transformer_,
@@ -8132,9 +8627,10 @@ function $3ec9e21d6b6debdd$export$2f2b9559550c7bbc({
8132
8627
  set_show_stale_content_results(true);else {
8133
8628
  set_searching_for_value(field_value);
8134
8629
  deparallelized_fn({
8135
- query: field_value,
8136
- tenant: tenant_(),
8137
- market: market_()
8630
+ merchant: merchant_(),
8631
+ market: market_(),
8632
+ locale: i18n_.backend_locale_(),
8633
+ query: field_value
8138
8634
  });
8139
8635
  set_show_stale_content_results(false);
8140
8636
  }
@@ -8266,7 +8762,7 @@ function $f40a47a30a358305$export$1c593cbd6f1e10bc({
8266
8762
  close_modal_: close_modal_,
8267
8763
  style_props_ = $5vyXB$solidjs.createSignal({}),
8268
8764
  depict_api_: depict_api_,
8269
- tenant_: tenant_,
8765
+ merchant_: merchant_,
8270
8766
  market_: market_,
8271
8767
  submit_query_: props_submit_query,
8272
8768
  instant_results_options_: instant_results_options_,
@@ -8366,7 +8862,7 @@ function $f40a47a30a358305$export$1c593cbd6f1e10bc({
8366
8862
  previous_searches_: previous_searches_,
8367
8863
  search_query_url_param_name_: search_query_url_param_name_,
8368
8864
  market_: market_,
8369
- tenant_: tenant_,
8865
+ merchant_: merchant_,
8370
8866
  selected_index_: selected_index,
8371
8867
  currently_showing_suggestions_: currently_showing_suggestions_,
8372
8868
  depict_api_: depict_api_,
@@ -8388,7 +8884,7 @@ function $f40a47a30a358305$export$1c593cbd6f1e10bc({
8388
8884
  return $6ae556e536054e87$export$62f101a8aa597bf8({
8389
8885
  search_field_value_: search_field_value_,
8390
8886
  depict_api_: depict_api_,
8391
- tenant_: tenant_,
8887
+ merchant_: merchant_,
8392
8888
  i18n_: i18n_,
8393
8889
  market_: market_,
8394
8890
  set_total_num_results_accessor_: set_total_num_results_accessor_,
@@ -8777,6 +9273,9 @@ function $f1d7cb69f839a526$export$a54ec244c8863715({
8777
9273
  const first_result_in_viewport_ = $5vyXB$solidjs.createSignal();
8778
9274
  const last_result_in_viewport_ = $5vyXB$solidjs.createSignal();
8779
9275
  const [can_write_scroll_restoration_, set_can_write_scroll_restoration] = $5vyXB$solidjs.createSignal(false);
9276
+ const {
9277
+ backend_locale_: backend_locale_
9278
+ } = i18n_;
8780
9279
  const search_query_base_ = $8cd545330f2674dc$export$210f130a61ac1e8d(() => {
8781
9280
  const sort_obj = get_sorting() && {
8782
9281
  ...get_sorting()
@@ -8784,8 +9283,9 @@ function $f1d7cb69f839a526$export$a54ec244c8863715({
8784
9283
  delete sort_obj?.meta;
8785
9284
  const f = selected_filters_[0]();
8786
9285
  return {
8787
- tenant: tenant_(),
9286
+ merchant: tenant_(),
8788
9287
  market: market_(),
9288
+ locale: backend_locale_(),
8789
9289
  query: get_search_query_(),
8790
9290
  ...(f.length ? {
8791
9291
  filters: f
@@ -8811,11 +9311,12 @@ function $f1d7cb69f839a526$export$a54ec244c8863715({
8811
9311
  })
8812
9312
  });
8813
9313
  }));
8814
- const [suggestions] = $5vyXB$solidjs.createResource($5vyXB$solidjs.createMemo(() => ({
9314
+ const [suggestions] = $5vyXB$solidjs.createResource(() => ({
8815
9315
  query: get_search_query_(),
8816
- tenant: tenant_(),
8817
- market: market_()
8818
- })), opts => depict_api_.suggest(opts));
9316
+ merchant: tenant_(),
9317
+ market: market_(),
9318
+ locale: backend_locale_()
9319
+ }), opts => depict_api_.suggest(opts));
8819
9320
  const available_sortings_ = $5vyXB$solidjs.createMemo(() => search_results_()?.sorts?.map(sort => ({
8820
9321
  ...sort,
8821
9322
  order: sort.order ?? "desc"
@@ -9259,7 +9760,7 @@ class $2c61e4cd8229c49a$export$ac6237957a15b3f0 {
9259
9760
  search_query_url_param_name_: search_query_url_param_name_,
9260
9761
  previous_searches_: previous_searches,
9261
9762
  depict_api_: depict_api_,
9262
- tenant_: this.#merchant_signal[0],
9763
+ merchant_: this.#merchant_signal[0],
9263
9764
  clear_filters_: clear_filters_on_next_submit_,
9264
9765
  market_: this.#market_signal[0],
9265
9766
  submit_query_: configured_submit_query_,
@@ -9373,11 +9874,12 @@ class $2c61e4cd8229c49a$export$ac6237957a15b3f0 {
9373
9874
  depict_api_: depict_api_
9374
9875
  } = $2c61e4cd8229c49a$var$privately_shared_properties.get(this);
9375
9876
  const result = await depict_api_.query({
9376
- tenant: this.merchant,
9877
+ merchant: this.merchant,
9377
9878
  market: this.market,
9378
9879
  query: query,
9379
9880
  filters: filters,
9380
- limit: maxResults
9881
+ limit: maxResults,
9882
+ locale: this.localization.backend_locale_
9381
9883
  });
9382
9884
  if (result.failed) throw new Error("Failed to fetch search results");
9383
9885
  return result.displays;
@@ -9813,7 +10315,4 @@ function $0a6acf31d1eae57c$var$clean_url(url) {
9813
10315
  url_object.hash = "";
9814
10316
  return url_object.href;
9815
10317
  }
9816
- const $a3280f0aad997933$export$c3834fa86c616831 = [[4], [3, 1024], [2, 901]];
9817
- const $a3280f0aad997933$export$864d304a0bc46829 = "2%";
9818
- const $a3280f0aad997933$export$7bf543b9d9be2c22 = (0, $0b23bfd073d9a4e8$export$b91cec6bdc6b32a1);
9819
10318
  $5vyXB$depictaiutilishared.add_to_version_info("ui", (0, $b757f75811f3261f$export$83d89fbfd8236492));