@depict-ai/ui 2.1.23 → 3.0.1

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,452 +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.23";
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.1";
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;
451
- },
452
- get alt() {
453
- return props.alt;
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;
454
985
  }
455
- }));
456
- return container;
457
- }
458
- 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>'];
459
- function $0f313083912e447a$export$8be2714ec7f169ee(props = {}) {
460
- 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));
461
- }
462
- const $a0e53f99354809d9$var$_tmpl$ = ["<div", ">", "</div>"];
463
- function $a0e53f99354809d9$export$6649caad96ef8870({
464
- children: children,
465
- slider_ref_: slider_ref_,
466
- faded_opacity_ = 0.7,
467
- mutation_plugins_ = [],
468
- disable_fading_: disable_fading_,
469
- arrow_width_: arrow_width_,
470
- arrow_height_: arrow_height_
471
- }) {
472
- const slider = new (0, $5vyXB$depictaiutilishared.Amazing_Slider)({
473
- button_contents: {
474
- left: [$5vyXB$solidjsweb.ssr($a0e53f99354809d9$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $0f313083912e447a$export$8be2714ec7f169ee), {
475
- height_: arrow_height_,
476
- width_: arrow_width_
477
- })))],
478
- right: [$5vyXB$solidjsweb.ssr($a0e53f99354809d9$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $0f313083912e447a$export$8be2714ec7f169ee), {
479
- height_: arrow_height_,
480
- width_: arrow_width_
481
- })))]
482
- },
483
- constructor_plugins: [$5vyXB$depictaiutilishared.slider_snap_css().constructor_plugin],
484
- mutation_plugins: [...(disable_fading_ ? [] : [$5vyXB$depictaiutilishared.slider_fading_factory({
485
- threshold_: 0.96,
486
- faded_opacity_: faded_opacity_
487
- }).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
+ }));
488
1024
  });
489
- $5vyXB$solidjsweb.insert(slider.insert_here, children);
490
- $5vyXB$solidjs.onCleanup(() => slider.observer.disconnect());
491
- slider_ref_?.(slider);
492
- 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];
493
1028
  }
494
-
495
- /** @jsxImportSource solid-js */
496
-
497
- function $f13855d1b951b24a$export$ebdc3711f7e02ccd(what_to_watch) {
498
- const [width, setWidth] = $5vyXB$solidjs.createSignal();
499
- const resizeObserver = new ResizeObserver($5vyXB$depictaiutilishared.catchify(records => {
500
- for (let j = 0; j < records.length; j++) {
501
- const width = records[j].borderBoxSize?.[0]?.inlineSize ?? what_to_watch.getBoundingClientRect().width;
502
- 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()));
503
1047
  }
504
- }));
505
- // 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.
506
- // It doesn't seem to work even when waiting for it to be in the DOM, also wait an animation frame
507
- const disconnect = (0, $5vyXB$depictaiutilishared.observer).onexists(what_to_watch, ({
508
- element: element
509
- }) => requestAnimationFrame($5vyXB$depictaiutilishared.catchify(() => {
510
- const current_size = what_to_watch.getBoundingClientRect().width;
511
- if (current_size)
512
- // 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.
513
- setWidth(current_size);
514
- resizeObserver.observe(element);
515
- })));
516
- $5vyXB$solidjs.onCleanup(() => {
517
- resizeObserver.disconnect();
518
- 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
519
1083
  });
520
- return width;
521
1084
  }
522
1085
  const $4e04be41243c3d80$var$transform_elements = sorted_cols_at_size => {
523
1086
  const cols_at_size = [];
@@ -554,546 +1117,777 @@ const $4e04be41243c3d80$export$6daf8749b65a1b77 = cols_at_size => {
554
1117
  });
555
1118
  return $4e04be41243c3d80$var$transform_elements(sorted_cols_at_size);
556
1119
  };
557
- function $fc23d7668ae0011d$export$a2cc176055f8f08() {
558
- 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.";
559
- return (0, $5vyXB$solidjsweb.isServer) ? {
560
- t: `<!-- ${text} -->`
561
- } : 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();
562
1155
  }
563
- function $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(elements) {
564
- // FYI this probably doesn't work on hugely deep nestings or large amount of elements
565
- 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
+ });
566
1165
  }
567
- function $5f7d55c710fd1bc2$var$unwrapping_helper(elements) {
568
- const result = [];
569
- if (Array.isArray(elements)) for (let i = 0; i < elements.length; i++) {
570
- const element = elements[i];
571
- result.push(...$5f7d55c710fd1bc2$var$unwrapping_helper(element));
572
- } else if (typeof elements == "function") result.push(...$5f7d55c710fd1bc2$var$unwrapping_helper(elements()));else if (elements != undefined && typeof elements != "boolean") result.push(elements);
573
- return result;
1166
+ function $84798aaa863a4909$export$8d0c4fdbb05a2f2e() {
1167
+ return $5vyXB$solidjs.useContext($84798aaa863a4909$var$ListingContext);
574
1168
  }
575
- let $0caf87eaa19079da$var$cached_placeholder_element;
576
- let $0caf87eaa19079da$var$rendering_cached_placeholder_element;
577
- function $0caf87eaa19079da$export$f33414a4df0afd3f({
578
- product_card_template_: product_card_template_,
579
- num_placeholders_: num_placeholders_,
580
- content_blocks_: content_blocks_
581
- }) {
582
- const [num_to_actually_show, set_num_to_actually_show] = $5vyXB$solidjs.createSignal($5vyXB$solidjs.untrack(num_placeholders_));
583
- if (0, $5vyXB$solidjsweb.isServer)
584
- // want to render simple placeholders on server, effects don't run there
585
- // FIXME when adding proper SSR: also SSR content blocks
586
- return $5vyXB$solidjs.createMemo(() => Array.from({
587
- length: num_placeholders_()
588
- }).map(() => {
589
- const template_result = product_card_template_(null, undefined);
590
- // @ts-ignore
591
- if (typeof template_result?.then !== "function") return template_result;
592
- }));
593
- $5vyXB$solidjs.createRenderEffect(() => {
594
- const existing_num = num_to_actually_show();
595
- const to_add = num_placeholders_() - existing_num;
596
- if (to_add <= 0) return;
597
- // 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.
598
- // 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.
599
- // 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.
600
- // 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
601
- // Functionality should be the same
602
- set_num_to_actually_show(existing_num + to_add);
603
- });
604
- return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Index), {
605
- get each() {
606
- return Array.from({
607
- length: num_to_actually_show()
608
- });
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;
609
1250
  },
610
- children: (_item, index) => {
611
- const possible_content_block = $5vyXB$solidjs.createMemo(() => content_blocks_?.()?.()?.[index]);
612
- // Show content block before product card, so it's *at* that index
613
- return [possible_content_block, $0caf87eaa19079da$var$Placeholder({
614
- product_card_template_: product_card_template_
615
- })]; // 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);
616
1402
  }
1403
+ const decoded = await response.json();
1404
+ return decoded;
617
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;
618
1421
  }
619
1422
  /**
620
- * 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
621
1424
  */
622
- function $0caf87eaa19079da$var$Placeholder({
623
- product_card_template_: product_card_template_
624
- }) {
625
- 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;
626
- if ($0caf87eaa19079da$var$cached_placeholder_element) return get_cloned_placeholders();
627
- let dispose_original_copy;
628
- const get_unwrapped_element = $5vyXB$solidjs.createRoot(dispose => {
629
- dispose_original_copy = dispose;
630
- // if product_card_template_ is async and rejects the resource will take care of throwing upwards here in the solid-js error handling system
631
- const [resource] = $5vyXB$solidjs.createResource(() => {
632
- if ($0caf87eaa19079da$var$rendering_cached_placeholder_element) return $0caf87eaa19079da$var$rendering_cached_placeholder_element;
633
- const return_value = product_card_template_(null, undefined);
634
- if (typeof return_value === "object" && typeof return_value?.then === "function")
635
- // Is Promise or promise-like object
636
- $0caf87eaa19079da$var$rendering_cached_placeholder_element = return_value;
637
- return return_value;
638
- });
639
- return $5vyXB$solidjs.createMemo(() => {
640
- if (resource.loading) return () => [];
641
- return $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(resource);
642
- });
643
- });
644
- $5vyXB$solidjs.onCleanup(() => {
645
- if ($0caf87eaa19079da$var$rendering_cached_placeholder_element) {
646
- // 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
647
- const unset_current_rendering = () => {
648
- dispose_original_copy();
649
- $0caf87eaa19079da$var$rendering_cached_placeholder_element = undefined;
650
- };
651
- $0caf87eaa19079da$var$rendering_cached_placeholder_element?.then(unset_current_rendering, unset_current_rendering);
652
- } else
653
- // Otherwise, just make sure we've disposed our root
654
- dispose_original_copy();
655
- });
656
- return $5vyXB$solidjs.createMemo(() => {
657
- const unwrapped_array = get_unwrapped_element()();
658
- if (!unwrapped_array?.length || !unwrapped_array.every(item => item))
659
- // Haven't finished rendering yet in case of "async" rendering, so don't freeze the elements yet
660
- return;
661
- // placeholders have finished rendering, freeze the elements
662
- // 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
663
- $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
664
- $0caf87eaa19079da$var$rendering_cached_placeholder_element = undefined;
665
- dispose_original_copy(); // So that this memo will never re-run and the placeholder rendering function can clean up
666
- 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
+ }
667
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
+ };
668
1459
  }
669
-
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
+ };
670
1482
  /**
671
- * 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.
672
1486
  */
673
- function $a5871dacf261adf8$export$548d053aba053d79(display) {
674
- if ("variant_index" in display) {
675
- const actual_display = display.variant_displays[display.variant_index];
676
- 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));
677
1493
  }
678
- 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);
679
1499
  }
680
- let $a73063cc642f3e5f$var$printedCloneError = false;
681
- function $a73063cc642f3e5f$export$7f8bd308237ab5a5(get_displays_) {
682
- const displays_by_key_ = $5vyXB$solidjs.createMemo(() => {
683
- const displays = get_displays_();
684
- // We key by product_id because that's what can be used to uniquely identify products
685
- // This way <For> can optimize the rendering
686
- const map = new Map();
687
- for (let i = 0; i < displays.length; i++) {
688
- const display = displays[i];
689
- const product_id = $a5871dacf261adf8$export$548d053aba053d79(display);
690
- map.set(product_id, display);
691
- }
692
- return map;
693
- });
694
- 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);
695
1509
  }
696
- const $a73063cc642f3e5f$var$result_ids = ["search_result_id", "product_listing_result_id", "recommendation_id"];
697
- function $a73063cc642f3e5f$export$43f0fb951fcb0c54({
698
- displays_by_key_: displays_by_key_,
699
- merchant_: merchant_,
700
- market_: market_,
701
- product_card_template_: product_card_template_,
702
- do_per_elements_: do_per_elements_,
703
- content_blocks_: content_blocks_
704
- }) {
705
- return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.For), {
706
- get each() {
707
- return [...displays_by_key_().keys()];
708
- },
709
- children: (product_id, index) => {
710
- const owner = $5vyXB$solidjs.getOwner();
711
- const possible_content_block = $5vyXB$solidjs.createMemo(() => content_blocks_?.()?.()?.[index()]);
712
- const display_accessor = $5vyXB$solidjs.createMemo(prev => {
713
- const new_display = displays_by_key_().get(product_id);
714
- if (prev && $a73063cc642f3e5f$var$deep_equal(prev, new_display))
715
- // 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.
716
- // This doesn't work if people mutate the displays from within the template but we hope they don't
717
- // (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)
718
- return prev;
719
- return new_display;
720
- });
721
- const [product_card_resource] = $5vyXB$solidjs.createResource(() => [merchant_(), market_(), display_accessor()],
722
- // re-render when the reference to the display object changes or the merchant or market changes
723
- // (We don't want to re-render if nothing has changed)
724
- ([merchant, market, display]) => {
725
- // It's easy for merchants to accidentally mutate the display or some sub-object thereof
726
- // We had a case on singular where they popped an image url and due to use caching after some time there was no image
727
- // Attempt cloning the displays if possible (99.9% of the cases probably) and if not, just use the original display
728
- try {
729
- display = structuredClone(display);
730
- } catch (e) {
731
- if (!$a73063cc642f3e5f$var$printedCloneError) {
732
- $a73063cc642f3e5f$var$printedCloneError = true;
733
- $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);
734
- }
735
- }
736
- return product_card_template_(display, {
737
- set_on_index_change: fn => $5vyXB$solidjs.runWithOwner(owner, () => $5vyXB$solidjs.createEffect(() => fn(index()))),
738
- merchant: merchant,
739
- market: market // recommendation_grid can provide a sneaky undefined here just FYI
740
- });
741
- });
742
-
743
- const node_accessor = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52(product_card_resource);
744
- $5vyXB$solidjs.createEffect(() => {
745
- const product_card_nodes = node_accessor();
746
- const display = display_accessor();
747
- const elements = [];
748
- for (let i = 0; i < product_card_nodes.length; i++) {
749
- const element = product_card_nodes[i];
750
- if (!(element instanceof Element)) continue;
751
- elements.push(element);
752
- // Add tracking ids
753
- if (!(element instanceof HTMLElement)) continue; // Apparently only HTMLElements have dataset
754
- for (let i = 0; i < $a73063cc642f3e5f$var$result_ids.length; i++) {
755
- const id = $a73063cc642f3e5f$var$result_ids[i];
756
- const value = display[id];
757
- if (value) Object.assign(element.dataset, $5vyXB$depictaiutilishared.camelCasifyObject({
758
- [id]: value
759
- }));
760
- }
761
- }
762
- do_per_elements_?.(elements, index);
763
- });
764
- return [
765
- // Show content block before product card, so it's *at* that index
766
- possible_content_block, product_card_resource]; // https://github.com/solidjs/solid/releases/tag/v1.7.0
767
- }
768
- });
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);
769
1516
  }
770
- // source: https://medium.com/@pancemarko/deep-equality-in-javascript-determining-if-two-objects-are-equal-bf98cf47e934
771
- function $a73063cc642f3e5f$var$deep_equal(obj1, obj2) {
772
- if (obj1 === obj2) return true;
773
- if (Array.isArray(obj1) && Array.isArray(obj2)) {
774
- if (obj1.length !== obj2.length) return false;
775
- return obj1.every((elem, index) => {
776
- return $a73063cc642f3e5f$var$deep_equal(elem, obj2[index]);
777
- });
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;
778
1535
  }
779
- if (typeof obj1 === "object" && typeof obj2 === "object" && obj1 !== null && obj2 !== null) {
780
- if (Array.isArray(obj1) || Array.isArray(obj2)) return false;
781
- const keys1 = Object.keys(obj1);
782
- const keys2 = Object.keys(obj2);
783
- if (keys1.length !== keys2.length || !keys1.every(key => keys2.includes(key))) return false;
784
- for (const key in obj1) {
785
- if ($a73063cc642f3e5f$var$result_ids.includes(key)) continue; // ignore keys changing with every request
786
- const isEqual = $a73063cc642f3e5f$var$deep_equal(obj1[key], obj2[key]);
787
- if (!isEqual) return false;
788
- }
789
- 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);
790
1548
  }
791
- return false;
1549
+ return null;
792
1550
  }
793
-
794
- // Errors caused by SDK consuming code interfacing with the SDK, not the SDK itself or other Depict packages
795
- class $7dd1edb2ee2b43ad$export$e1d52e4f0c7557a1 extends Error {}
796
- class $7dd1edb2ee2b43ad$export$aa14a9f43128f61f extends $7dd1edb2ee2b43ad$export$e1d52e4f0c7557a1 {
797
- constructor(templateError) {
798
- super("Uncaught error in product card template", {
799
- cause: templateError
800
- });
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);
801
1560
  }
802
1561
  }
803
- const $edafe91daf3091d7$var$_tmpl$ = ["<div", ' class="', '"><!--$-->', "<!--/--><!--$-->", "<!--/--></div>"];
804
- function $edafe91daf3091d7$export$b69d0d92862de18b(props) {
805
- return $5vyXB$solidjs.ErrorBoundary({
806
- fallback(err, retry) {
807
- const {
808
- message_: message_,
809
- severity_: severity_
810
- } = props;
811
- let message = message_;
812
- if (err instanceof (0, $7dd1edb2ee2b43ad$export$aa14a9f43128f61f)) {
813
- console.error(err.cause);
814
- message = `${message}: ${err.message}`;
815
- } else $5vyXB$depictaiutilishared.report([err, message_], severity_);
816
- 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)));
817
- },
818
- get children() {
819
- 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;
820
1570
  }
821
- });
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;
822
1584
  }
823
- const $f48d0fbb00835aaa$var$_tmpl$ = ["<div", ' class="', '">', "</div>"],
824
- $f48d0fbb00835aaa$var$_tmpl$2 = ["<style", ' type="text/css">', "</style>"];
825
- function $f48d0fbb00835aaa$export$d21e32dfedac04be(props) {
826
- const container_class = "x" + $5vyXB$solidjs.createUniqueId();
827
- const container_element_ = $5vyXB$solidjsweb.ssrElement("div", $5vyXB$solidjsweb.mergeProps(() => props.element_attributes, {
828
- classList: {
829
- [container_class]: true
830
- }
831
- }), () => $5vyXB$solidjsweb.escape(props.children), true); // Don't want this in the error boundary below, it should only be for the actual layouting
832
- return $5vyXB$solidjsweb.createComponent((0, $edafe91daf3091d7$export$b69d0d92862de18b), {
833
- get message_() {
834
- return "Failed calculating " + props.layout + " layout";
835
- },
836
- severity_: "error",
837
- get children() {
838
- 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));
839
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();
840
1658
  });
1659
+ return size;
841
1660
  }
842
- function $f48d0fbb00835aaa$export$445d8d3f5f706a40(props, container_element, insert_after_container = false, container_class) {
843
- if (!container_class) {
844
- // only try to add if it wasn't provided, so that we have a code path without classList when doing SSR
845
- container_class = $5vyXB$depictaiutilishared.make_random_classname();
846
- container_element.classList.add(container_class);
847
- }
848
- // Copy of Layout from utilishared but using solid-js signals instead of async iterable IPNS
849
- const show_all_rows = $5vyXB$solidjs.createMemo(() => props.rows === "all");
850
- const rows_or_empty_object = $5vyXB$solidjs.createMemo(() => show_all_rows() ? {} : props.rows);
851
- const view_more_button_elements = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52($5vyXB$solidjs.createMemo(() => rows_or_empty_object().button));
852
- const view_less_button_elements = $5f7d55c710fd1bc2$export$2f0cbfbb4354bb52($5vyXB$solidjs.createMemo(() => rows_or_empty_object().view_less_button));
853
- const have_a_view_more_button = $5vyXB$solidjs.createMemo(() => {
854
- const button = view_more_button_elements();
855
- 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;
856
1674
  });
857
- const have_a_view_less_button = $5vyXB$solidjs.createMemo(() => {
858
- const button = view_less_button_elements();
859
- 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
+ };
860
1683
  });
861
- const [get_styling, set_styling] = $5vyXB$solidjs.createSignal();
862
- const selector_beginning = `.depict .${container_class}>`; // class so ppl can have id if needed
863
- const [get_children_count, set_children_count] = $5vyXB$solidjs.createSignal(0);
864
- const update_children_count = () => (0, $5vyXB$solidjsweb.isServer) ? 20 : set_children_count(container_element.children.length);
865
- 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));
866
- 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
867
- const rows_visible_signal = $5vyXB$solidjs.createMemo(() => rows_or_empty_object().currently_visible || default_currently_visible_signal);
868
- const get_rows_visible = $5vyXB$solidjs.createMemo(() => rows_visible_signal()[0]());
869
- const set_rows_visible = $5vyXB$solidjs.createMemo(() => rows_visible_signal()[1]);
870
- const view_more_button_class = "m" + $5vyXB$solidjs.createUniqueId();
871
- const view_less_button_class = "l" + $5vyXB$solidjs.createUniqueId(); // https://github.com/solidjs/solid-docs/issues/263#issuecomment-1622388079
872
- 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)));
873
- // 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
874
- 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)));
875
- const [force_style_update, set_force_style_update] = $5vyXB$solidjs.createSignal("");
876
- $5vyXB$solidjs.createComputed(() => {
877
- // Make sure we don't have more rows visible than max_rows (this could happen by max_rows being decreased)
878
- const rows_visible = get_rows_visible();
879
- const max_rows = rows_or_empty_object().max_rows;
880
- 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;
881
1744
  });
882
- $5vyXB$solidjs.createEffect(() => set_force_style_update(" ")); // force style update after hydration due to https://discord.com/channels/722131463138705510/722167424186843267/1151544212517552168
883
- $5vyXB$solidjs.createRenderEffect(() => {
884
- // Be careful to only read show_all_rows in here (ofc doesn't apply to nested effects)
885
- if (show_all_rows()) {
886
- // no view more functionality requested
887
- 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;
888
1757
  return;
889
1758
  }
890
- update_children_count();
891
- if (!(0, $5vyXB$solidjsweb.isServer)) {
892
- const mutation_observer = new MutationObserver($5vyXB$depictaiutilishared.catchify(update_children_count));
893
- mutation_observer.observe(container_element, {
894
- childList: true
895
- });
896
- $5vyXB$solidjs.onCleanup(() => mutation_observer.disconnect());
897
- }
898
- set_styling(
899
- // this is needed because solid will think that the memo-accessor is a setter function otherwise
900
- () => $5vyXB$solidjs.createMemo(() => {
901
- const {
902
- rows_per_click: rows_per_click,
903
- max_rows = -1,
904
- start_rows: start_rows
905
- } = rows_or_empty_object();
906
- const rows_visible = get_rows_visible();
907
- const children_count = get_children_count();
908
- return force_style_update() + col_styling() + props.cols_at_size.map(options => {
909
- const [recs_per_row, min, max] = options;
910
- let should_hide_view_more_button;
911
- let visible_recs;
912
- if (props.disable_partial_rows) {
913
- visible_recs = $5vyXB$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible, children_count, options);
914
- const visible_recs_next_show_more = $5vyXB$depictaiutilishared.layout_get_visible_recs_without_partial_rows(rows_visible + (rows_per_click || 0),
915
- // Should this really be zero when we default rows_per_click to 1?
916
- children_count, options);
917
- should_hide_view_more_button = visible_recs === visible_recs_next_show_more;
918
- } else {
919
- visible_recs = $5vyXB$depictaiutilishared.layout_get_total_rec_amount_for_row(rows_visible, options);
920
- should_hide_view_more_button = visible_recs >= children_count;
921
- }
922
- const should_hide_button_final = should_hide_view_more_button || max_rows !== -1 && rows_visible >= max_rows;
923
- // 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
924
- 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;
925
- 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}` : ``}}`;
926
- }).join("");
927
- }));
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
+ });
928
1767
  });
929
- 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
930
- if (insert_after_container) container_element.after(style_element);
931
- return [container_element, view_more_button_container(), view_less_button_container(), style_element];
932
- }
933
- const $363ce4d1d71041aa$var$_tmpl$ = ["<h2", ' class="recs-title">', "</h2>"];
934
- function $363ce4d1d71041aa$export$d41d19e89346fa2({
935
- recommendations_resource_: recommendations_resource_,
936
- product_card_template_: product_card_template_,
937
- layout_options_: layout_options_,
938
- merchant_: merchant_,
939
- market_: market_,
940
- title_: title_
941
- }) {
942
- const is_showing_something = $5vyXB$solidjs.createMemo(() => recommendations_resource_.loading || recommendations_resource_()?.length);
943
- const title = $5vyXB$solidjs.createMemo(() => title_?.()); // In case getter/accessor creates elements, don't create them twice
944
- const num_placeholders_ = () => 20;
945
- const slider = [$5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
946
- get when() {
947
- return title();
948
- },
949
- get children() {
950
- return $5vyXB$solidjsweb.ssr($363ce4d1d71041aa$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(title()));
951
- }
952
- }), $5vyXB$solidjsweb.createComponent((0, $a0e53f99354809d9$export$6649caad96ef8870), {
953
- arrow_height_: 25,
954
- arrow_width_: 12.5,
955
- disable_fading_: true,
956
- slider_ref_: slider => {
957
- const {
958
- insert_here: insert_here
959
- } = slider;
960
- const Layout = props => $f48d0fbb00835aaa$export$445d8d3f5f706a40(props, insert_here, true);
961
- // Do like this, so we don't have to call mergeProps ourselves
962
- $5vyXB$solidjsweb.createComponent(Layout, $5vyXB$solidjsweb.mergeProps({
963
- rows: "all",
964
- layout: "slider"
965
- }, layout_options_));
966
- $5vyXB$depictaiutilishared.slider_fractional_factory(0, 0.75).constructor_plugin.call(slider, {}); // enable fractional scrolling
967
- insert_here.before($fc23d7668ae0011d$export$a2cc176055f8f08());
968
- },
969
- get children() {
970
- return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Suspense), {
971
- get fallback() {
972
- return $0caf87eaa19079da$export$f33414a4df0afd3f({
973
- num_placeholders_: num_placeholders_,
974
- product_card_template_: product_card_template_
975
- });
976
- },
977
- get children() {
978
- return (() => {
979
- // IIFE to make sure we access both the recommendations_resource and the resources containing the product card rendering results themselves within the Suspense boundary
980
- const displays_by_key_ = $a73063cc642f3e5f$export$7f8bd308237ab5a5($5vyXB$solidjs.createMemo(() => recommendations_resource_() || []));
981
- return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
982
- displays_by_key_: displays_by_key_,
983
- merchant_: merchant_,
984
- market_: market_,
985
- product_card_template_: product_card_template_
986
- });
987
- })();
988
- }
989
- });
990
- }
991
- })];
992
1768
  return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
993
1769
  get when() {
994
- return is_showing_something();
1770
+ return hasDecoded();
995
1771
  },
996
- children: slider
1772
+ children: img
997
1773
  });
998
1774
  }
999
- function $95837413165cc2df$export$23fca46f3143581f(component, error_message) {
1000
- const component_in_error_boundary = do_with_elements => {
1001
- const error_boundary_wrapped = $edafe91daf3091d7$export$b69d0d92862de18b({
1002
- severity_: "error",
1003
- message_: error_message,
1004
- get children() {
1005
- const elements = component();
1006
- do_with_elements?.(elements);
1007
- return elements;
1008
- }
1009
- });
1010
- // This might return an accessor, in that case we need to "unwrap" it since our SDK consumers expect HTML elements or arrays thereof
1011
- if (typeof error_boundary_wrapped === "function")
1012
- // @ts-ignore
1013
- return error_boundary_wrapped();
1014
- // On the server it returns a string, so we just return that
1015
- return error_boundary_wrapped;
1016
- };
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
+ });
1017
1799
  const owner = $5vyXB$solidjs.getOwner();
1018
- if (owner == null) return $5vyXB$solidjs.createRoot(dispose => {
1019
- // 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
1020
- return component_in_error_boundary(elements => {
1021
- const have_multiple = Array.isArray(elements);
1022
- if (have_multiple ? !elements?.length : !elements) return;
1023
- (0, $5vyXB$depictaiutilishared.observer).onremoved(have_multiple ? elements[0] : elements, ({
1024
- element: element
1025
- }) => {
1026
- if (document.documentElement.contains(element)) return; // If element has instantly been re-inserted, don't dispose
1027
- // See https://depictaiworkspace.slack.com/archives/C050GHEPBTR/p1695809102791259?thread_ts=1695106805.459729&cid=C050GHEPBTR
1028
- dispose();
1029
- });
1030
- });
1031
- });else
1032
- // we're already in a root so cleanups are handled
1033
- 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;
1034
1828
  }
1035
- const $72f96c4782db0b1b$var$_tmpl$ = ["<div", ' class="depict recommendations">', "</div>"];
1036
- function $72f96c4782db0b1b$export$9574e176201e5e8d(props) {
1037
- return $95837413165cc2df$export$23fca46f3143581f(() => {
1038
- const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
1039
- const {
1040
- grid_spacing: grid_spacing
1041
- } = props; // can be reactive
1042
- return typeof grid_spacing === "string" ? {
1043
- grid_spacing: grid_spacing
1044
- } : {
1045
- override_vertical_spacing: grid_spacing.vertical,
1046
- grid_spacing: grid_spacing.horizontal
1047
- };
1048
- });
1049
- const [recommendations_resource_] = $5vyXB$solidjs.createResource(() => props.recommendations, recs => recs);
1050
- return $5vyXB$solidjsweb.ssr($72f96c4782db0b1b$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $84798aaa863a4909$export$e68cff63f76bd15b), {
1051
- get children() {
1052
- return $363ce4d1d71041aa$export$d41d19e89346fa2({
1053
- product_card_template_: (...args) => props.product_card_template(...args),
1054
- recommendations_resource_: recommendations_resource_,
1055
- market_: () => props.market,
1056
- merchant_: () => props.merchant,
1057
- title_: () => props.title,
1058
- layout_options_: $5vyXB$solidjs.createMemo(() => ({
1059
- cols_at_size: $4e04be41243c3d80$export$6daf8749b65a1b77(props.cols_at_size),
1060
- ...grid_spacing_override()
1061
- }))
1062
- });
1063
- }
1064
- })));
1065
- }, "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;
1066
1856
  }
1067
- const $b8e79813f4f7ebe4$var$_tmpl$ = ["<h2", ' class="recs-title">', "</h2>"],
1068
- $b8e79813f4f7ebe4$var$_tmpl$2 = ["<div", ' class="recommendation-grid"><!--$-->', "<!--/--><!--$-->", "<!--/--></div>"];
1069
- function $b8e79813f4f7ebe4$export$7da560f849543dff({
1857
+ const $363ce4d1d71041aa$var$_tmpl$ = ["<h2", ' class="recs-title">', "</h2>"];
1858
+ function $363ce4d1d71041aa$export$d41d19e89346fa2({
1070
1859
  recommendations_resource_: recommendations_resource_,
1071
1860
  product_card_template_: product_card_template_,
1072
1861
  layout_options_: layout_options_,
1073
- merchant_: merchant_,
1074
- market_: market_,
1075
- rows_object_: rows_object_,
1076
1862
  title_: title_
1077
1863
  }) {
1078
1864
  const is_showing_something = $5vyXB$solidjs.createMemo(() => recommendations_resource_.loading || recommendations_resource_()?.length);
1079
1865
  const title = $5vyXB$solidjs.createMemo(() => title_?.()); // In case getter/accessor creates elements, don't create them twice
1080
1866
  const num_placeholders_ = () => 20;
1081
- const elements = [$5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1867
+ const slider = [$5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1082
1868
  get when() {
1083
1869
  return title();
1084
1870
  },
1085
1871
  get children() {
1086
- 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()));
1087
1873
  }
1088
- }), $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({
1089
- get rows() {
1090
- 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());
1091
1890
  },
1092
- layout: "grid",
1093
- element_attributes: {
1094
- class: "cards"
1095
- }
1096
- }, layout_options_, {
1097
1891
  get children() {
1098
1892
  return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Suspense), {
1099
1893
  get fallback() {
@@ -1108,44 +1902,23 @@ function $b8e79813f4f7ebe4$export$7da560f849543dff({
1108
1902
  const displays_by_key_ = $a73063cc642f3e5f$export$7f8bd308237ab5a5($5vyXB$solidjs.createMemo(() => recommendations_resource_() || []));
1109
1903
  return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
1110
1904
  displays_by_key_: displays_by_key_,
1111
- merchant_: merchant_,
1112
- market_: market_,
1113
1905
  product_card_template_: product_card_template_
1114
1906
  });
1115
1907
  })();
1116
1908
  }
1117
1909
  });
1118
1910
  }
1119
- }))))];
1911
+ })];
1120
1912
  return $5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
1121
1913
  get when() {
1122
1914
  return is_showing_something();
1123
1915
  },
1124
- children: elements
1916
+ children: slider
1125
1917
  });
1126
1918
  }
1127
- const $1f8dbf7e28b3eff2$var$_tmpl$ = ["<button", ' class="show-more major" type="button">', "</button>"],
1128
- $1f8dbf7e28b3eff2$var$_tmpl$2 = ["<div", ' class="depict plp recommendations">', "</div>"];
1129
- function $1f8dbf7e28b3eff2$export$9756467d34d91cdb(props) {
1919
+ const $72f96c4782db0b1b$var$_tmpl$ = ["<div", ' class="depict recommendations">', "</div>"];
1920
+ function $72f96c4782db0b1b$export$9574e176201e5e8d(props) {
1130
1921
  return $95837413165cc2df$export$23fca46f3143581f(() => {
1131
- const rows_object_ = $5vyXB$solidjs.createMemo(() => {
1132
- const {
1133
- view_more_button: view_more_button,
1134
- max_rows: max_rows
1135
- } = props;
1136
- if (!view_more_button) {
1137
- if (max_rows) return {
1138
- max_rows: max_rows
1139
- };
1140
- return "all";
1141
- }
1142
- return {
1143
- max_rows: max_rows,
1144
- start_rows: view_more_button.start_rows,
1145
- rows_per_click: view_more_button.rows_per_click ?? 2,
1146
- button: $5vyXB$solidjsweb.ssr($1f8dbf7e28b3eff2$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape(view_more_button.text))
1147
- };
1148
- });
1149
1922
  const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
1150
1923
  const {
1151
1924
  grid_spacing: grid_spacing
@@ -1158,14 +1931,11 @@ function $1f8dbf7e28b3eff2$export$9756467d34d91cdb(props) {
1158
1931
  };
1159
1932
  });
1160
1933
  const [recommendations_resource_] = $5vyXB$solidjs.createResource(() => props.recommendations, recs => recs);
1161
- 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), {
1162
1935
  get children() {
1163
- return $b8e79813f4f7ebe4$export$7da560f849543dff({
1164
- rows_object_: rows_object_,
1936
+ return $363ce4d1d71041aa$export$d41d19e89346fa2({
1165
1937
  product_card_template_: (...args) => props.product_card_template(...args),
1166
1938
  recommendations_resource_: recommendations_resource_,
1167
- market_: () => props.market,
1168
- merchant_: () => props.merchant,
1169
1939
  title_: () => props.title,
1170
1940
  layout_options_: $5vyXB$solidjs.createMemo(() => ({
1171
1941
  cols_at_size: $4e04be41243c3d80$export$6daf8749b65a1b77(props.cols_at_size),
@@ -1174,7 +1944,7 @@ function $1f8dbf7e28b3eff2$export$9756467d34d91cdb(props) {
1174
1944
  });
1175
1945
  }
1176
1946
  })));
1177
- }, "RecommendationGrid failed");
1947
+ }, "RecommendationSlider failed");
1178
1948
  }
1179
1949
  function $4b455f60dadde8b8$export$5bad61ecde080b1f(...params) {
1180
1950
  const {
@@ -1294,15 +2064,6 @@ function $d659702496cb72ea$export$a71e92cfbb498adc(props) {
1294
2064
  return $5vyXB$depictaiutilishared.standard_price_format(props.price_, price_formatting.places_after_comma_, price_formatting.decimal_places_delimiter_, price_formatting.thousands_delimiter_);
1295
2065
  });
1296
2066
  }
1297
- 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>';
1298
- function $c77c68e559a1506c$export$3b621d86b1566b2(props = {}) {
1299
- return $5vyXB$solidjsweb.ssrElement("svg", $5vyXB$solidjsweb.mergeProps({
1300
- xmlns: "http://www.w3.org/2000/svg",
1301
- width: "21.064",
1302
- height: "21.047",
1303
- viewBox: "0 0 21.064 21.064"
1304
- }, props), () => $5vyXB$solidjsweb.ssr($c77c68e559a1506c$var$_tmpl$), true);
1305
- }
1306
2067
 
1307
2068
  /**
1308
2069
  * Lower cases a string if possible. Mostly used to make the filter url values case-insensitive.
@@ -1313,7 +2074,7 @@ function $daa394359b026187$export$325f75597868c4f0(stuff) {
1313
2074
  }
1314
2075
  const $235a2771a44e28e9$var$_tmpl$ = ["<button", ' class="clear-all-filters minor">', "</button>"],
1315
2076
  $235a2771a44e28e9$var$_tmpl$2 = ["<div", ' class="inner"><span class="title"><!--$-->', "<!--/-->: </span><!--$-->", "<!--/--></div>"],
1316
- $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>"],
1317
2078
  $235a2771a44e28e9$var$_tmpl$4 = ["<button", ' class="clear-filter major"><!--$-->', "<!--/--><span>", "</span></button>"];
1318
2079
  function $235a2771a44e28e9$export$fecbb157621501bd({
1319
2080
  number_of_rendered_selected_filters_items_: number_of_rendered_selected_filters_items_,
@@ -2082,7 +2843,7 @@ function $5ea5a82e398f6f44$var$cut_text(segmented_text) {
2082
2843
  // identical split point, or split end before split start, can't do anything
2083
2844
  split_start_segment == split_end_segment && split_start_character >= split_end_character || split_start_segment > split_end_segment) return;
2084
2845
  const dots_segment = {
2085
- text_: " … ",
2846
+ text_: " \u2026 ",
2086
2847
  highlighted_: false
2087
2848
  };
2088
2849
  const split_and_dotted_values = segmented_text.flatMap((segment, i) => {
@@ -2174,7 +2935,7 @@ function $5ea5a82e398f6f44$var$cut_start(cut_left_of_index, segmented_text) {
2174
2935
  if (character === "," || is_space)
2175
2936
  // if we cut at a comma or psace, we add a … at the beginning
2176
2937
  segmented_text.unshift({
2177
- text_: "… ",
2938
+ text_: "\u2026 ",
2178
2939
  highlighted_: false
2179
2940
  });
2180
2941
  break outmost_loop;
@@ -3065,7 +3826,7 @@ function $b064919833b3e80b$export$53c59af873b303c9({
3065
3826
  get price_formatting_() {
3066
3827
  return price_formatting_();
3067
3828
  }
3068
- }), 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), {
3069
3830
  get price_() {
3070
3831
  return selected_filter.data[1];
3071
3832
  },
@@ -3147,34 +3908,6 @@ function $8c939a05b87fbbbc$export$ab34afce88557c0e(props) {
3147
3908
  }));
3148
3909
  return is_open;
3149
3910
  }
3150
- const $9fe9883b1d8ecccc$var$_tmpl$ = ["<span", ' class="', '" style="', '"></span>'];
3151
- function $9fe9883b1d8ecccc$export$acb3eaade4b23afd(props) {
3152
- return $5vyXB$solidjsweb.ssr($9fe9883b1d8ecccc$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), `depict-placeholder${$5vyXB$solidjsweb.escape(props.class, true) || ""}`, $5vyXB$solidjsweb.ssrStyle(props.style));
3153
- }
3154
- function $061ff5b4c3d36171$export$89c6019e4baa40b1(props) {
3155
- const style = $5vyXB$solidjs.createMemo(() => {
3156
- const {
3157
- style: style,
3158
- height: height,
3159
- width: width
3160
- } = props;
3161
- return {
3162
- ...(style || {}),
3163
- height: height ?? "1em",
3164
- ...(width && {
3165
- width: width
3166
- })
3167
- };
3168
- });
3169
- return $5vyXB$solidjsweb.createComponent((0, $9fe9883b1d8ecccc$export$acb3eaade4b23afd), {
3170
- get style() {
3171
- return style();
3172
- },
3173
- get ["class"]() {
3174
- return props.class;
3175
- }
3176
- });
3177
- }
3178
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>';
3179
3912
  function $87d7574e1d89d69b$export$82eafebb825fc23f(props = {}) {
3180
3913
  return $5vyXB$solidjsweb.ssrElement("svg", $5vyXB$solidjsweb.mergeProps({
@@ -3633,152 +4366,35 @@ function $70482f04605572e2$var$modify_only_local_filter(local_filter_object, sel
3633
4366
  }
3634
4367
  }
3635
4368
  }
3636
- return modified_filter_object;
3637
- }
3638
- async function $9abb0a35d4b60ed3$export$79b1565500412d9b(search_modal, modal_fn_opts, parent) {
3639
- const body = parent || (await (0, $5vyXB$depictaiutilishared.observer).wait_for_element("body"));
3640
- let dispose_and_remove;
3641
- const open_modal_ = (extra_options_for_modal = {}, on_dispose) => {
3642
- if (dispose_and_remove)
3643
- // modal is already open
3644
- return;
3645
- const modal_els = $5vyXB$solidjs.createRoot(dispose => {
3646
- let closing_animation;
3647
- let animation_started;
3648
- dispose_and_remove = () => {
3649
- const actually_close = () => {
3650
- dispose();
3651
- on_dispose?.();
3652
- modal_els.forEach(el => el.remove());
3653
- };
3654
- if (animation_started && +new Date() - animation_started > 1000)
3655
- // Animation broke, close it this time
3656
- actually_close();else if (!animation_started && closing_animation) {
3657
- animation_started = +new Date();
3658
- $5vyXB$depictaiutilishared.catchify(closing_animation)()?.then($5vyXB$depictaiutilishared.catchify(actually_close));
3659
- } else actually_close();
3660
- };
3661
- return search_modal({
3662
- ...modal_fn_opts,
3663
- ...extra_options_for_modal,
3664
- close_modal_: close_modal_,
3665
- open_modal_: open_modal_,
3666
- register_closing_animation_: animation => closing_animation = animation
3667
- });
3668
- });
3669
- body.append(...modal_els);
3670
- };
3671
- const close_modal_ = () => {
3672
- if (dispose_and_remove) {
3673
- // modal is open
3674
- const dispose_fn = dispose_and_remove;
3675
- // 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
3676
- dispose_and_remove = undefined;
3677
- dispose_fn();
3678
- }
3679
- };
3680
- return {
3681
- open_modal_: open_modal_,
3682
- close_modal_: close_modal_
3683
- };
3684
- }
3685
- async function $bc91d938b8c601b4$export$58e808b1db15d3bc({
3686
- merchant: merchant,
3687
- market: market,
3688
- headers: headers,
3689
- ...fetch_recs_options
3690
- }) {
3691
- return await $5vyXB$depictaiutilishared.fetch_recs({
3692
- tenant: merchant,
3693
- market: market
3694
- }, $5vyXB$depictaiutilishared.snakeCasifyObject(fetch_recs_options), headers);
3695
- }
3696
- function $6e22b5314fb52f4c$export$e183a13865960371(params_to_default_value, router_) {
3697
- const signals = {};
3698
- const entries = Object.entries(params_to_default_value);
3699
- const event_handler = $5vyXB$depictaiutilishared.catchify((what_happened, args) => {
3700
- // 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
3701
- if (what_happened !== "popstate") return;
3702
- // 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.
3703
- // If we want others to interface with our state, it's better to expose it from DepictCategory/DepictSearch
3704
- // 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)
3705
- // And can infinite loop, like in https://app.jiminny.com/playback/569c8f65-edea-4735-bd9e-4eb5a0b14cad
3706
- // It's the classical equilibrium problem when syncing state both down and up, and it's much easier to avoid than solve
3707
- $6e22b5314fb52f4c$var$history_state_change(signals, entries, args.state);
3708
- });
3709
- // createRenderEffect because we need the instant execution so the signals always contain values, even before solid's render phase
3710
- $5vyXB$solidjs.createRenderEffect(() => {
3711
- let signal_changed = false;
3712
- let {
3713
- state: state
3714
- } = globalThis?.history || {
3715
- state: {}
3716
- }; // cloning isn't necessary because we're calling replaceState on it anyway
3717
- if (state === null || typeof state != "object") state = {};
3718
- for (const [param, default_value] of entries) {
3719
- const [read_signal] = signals[param] ||= $5vyXB$solidjs.createSignal(state[param] ?? default_value);
3720
- const new_value = read_signal();
3721
- if (new_value !== state[param]) {
3722
- signal_changed = true;
3723
- state[param] = new_value;
3724
- }
3725
- }
3726
- if (signal_changed) router_.navigate_.replace_state_(state);
3727
- });
3728
- // 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
3729
- (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(event_handler);
3730
- $5vyXB$solidjs.onCleanup($5vyXB$depictaiutilishared.catchify(() => (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(event_handler)));
3731
- $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
3732
- return signals;
3733
- }
3734
- function $6e22b5314fb52f4c$var$history_state_change(signals, entries, state) {
3735
- $5vyXB$solidjs.batch(() => {
3736
- for (const [param, default_value] of entries) {
3737
- const [, write_signal] = signals[param];
3738
- const new_value = state?.[param];
3739
- write_signal(new_value ?? default_value);
3740
- }
3741
- });
3742
- }
3743
- const $d84fe647b84b5dc5$export$3064e1e8c6513da3 = new Set();
3744
- let $d84fe647b84b5dc5$var$has_ran = false;
3745
- function $d84fe647b84b5dc5$export$5162a71f252e6122() {
3746
- if ($d84fe647b84b5dc5$var$has_ran || typeof history !== "object") return;
3747
- $d84fe647b84b5dc5$var$has_ran = true;
3748
- for (const function_name of ["replaceState", "pushState"]) {
3749
- if (Object.getOwnPropertyNames(history).includes(function_name)) $d84fe647b84b5dc5$var$proxy_push_state(function_name, history);
3750
- $d84fe647b84b5dc5$var$proxy_push_state(function_name, History.prototype);
3751
- }
3752
- }
3753
- function $d84fe647b84b5dc5$var$proxy_push_state(function_name, thing) {
3754
- thing[function_name] = new Proxy(thing[function_name], {
3755
- apply(target, this_arg, arg_list) {
3756
- try {
3757
- const old_state = history.state;
3758
- if (typeof old_state == "object" && old_state !== null) {
3759
- // This effectively disallows the user from passing in a string, number, null or undefined
3760
- const intended_new_value_as_obj = typeof arg_list[0] === "object" ? arg_list[0] ?? {} : {};
3761
- const cloned_object = {
3762
- ...intended_new_value_as_obj
3763
- };
3764
- for (const key in old_state) {
3765
- if (!$d84fe647b84b5dc5$var$starts_with_any_prefix(key)) continue;
3766
- if (!(key in cloned_object)) cloned_object[key] = old_state[key];
3767
- }
3768
- arg_list[0] = cloned_object;
3769
- }
3770
- } catch (e) {
3771
- $5vyXB$depictaiutilishared.report([e, "Failed to preserve items in history.state"], "error");
3772
- }
3773
- return Reflect.apply(target, this_arg, arg_list);
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);
3774
4394
  }
4395
+ return decoded?.displays || [];
3775
4396
  });
3776
4397
  }
3777
- function $d84fe647b84b5dc5$var$starts_with_any_prefix(key) {
3778
- for (const prefix of $d84fe647b84b5dc5$export$3064e1e8c6513da3) {
3779
- if (key.startsWith(prefix)) return true;
3780
- }
3781
- }
3782
4398
  function $26a56f6b44703084$export$9862539c89138352({
3783
4399
  get_default_values_: get_default_values_,
3784
4400
  router_: router_,
@@ -3834,8 +4450,8 @@ function $67dc366d96177e70$export$967e966fca9515e(api_response) {
3834
4450
  }
3835
4451
  return api_response;
3836
4452
  }
3837
- const $e1d6c0f3d89d531c$var$v2_base_url = (0, $5vyXB$depictaiutilishared.base_url) + "/v2/";
3838
- 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/";
3839
4455
  class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3840
4456
  #supports_finalization_registry = typeof FinalizationRegistry === "function";
3841
4457
  #cache_objs = {};
@@ -3854,18 +4470,14 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3854
4470
  const request = {
3855
4471
  ...input_req
3856
4472
  };
3857
- request.dsid ??= $5vyXB$depictaiutilishared.get_depict_id();
3858
- // Todo: remove the default user and session IDs once we've confirmed backend can handle it and do whatever fallback is necessary.
3859
- request.user_id ??= this.#get_user_id?.() || $5vyXB$depictaiutilishared.get_user_id();
3860
4473
  request.session_id ??= this.#get_session_id?.() || $5vyXB$depictaiutilishared.get_session_id();
3861
4474
  return request;
3862
4475
  };
3863
4476
  #get_metadata;
3864
- #get_user_id;
3865
4477
  #get_session_id;
3866
4478
  #guard_url_creator_length(expected, received) {
3867
4479
  if (expected.length !== received.length) {
3868
- 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);
3869
4481
  queueMicrotask(() => {
3870
4482
  throw e;
3871
4483
  });
@@ -3902,8 +4514,9 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3902
4514
  const category_transformer = display_transformers?.categories;
3903
4515
  const content_result_transformer = display_transformers?.contentResults;
3904
4516
  const displays = input_data.displays;
4517
+ const owner = $5vyXB$solidjs.getOwner();
3905
4518
  const {
3906
- breadcrumb: breadcrumb,
4519
+ breadcrumbs: breadcrumbs,
3907
4520
  quick_links: quick_links,
3908
4521
  content_search_links: content_search_links
3909
4522
  } = input_data;
@@ -3932,40 +4545,48 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3932
4545
  displays[i] = new_display_or_page_url;
3933
4546
  }
3934
4547
  }
3935
- 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]) {
3936
4549
  if (!category_display_array) continue;
3937
- const page_urls = await (page_url_creator || category_transformer)({
4550
+ const page_urls = await $5vyXB$solidjs.runWithOwner(owner, () => (page_url_creator || category_transformer)({
3938
4551
  merchant: merchant,
3939
4552
  market: market,
3940
4553
  data: [...category_display_array],
3941
4554
  ...(page_url_creator ? {
3942
4555
  type: "categories"
3943
4556
  } : {})
3944
- });
4557
+ }));
3945
4558
  this.#guard_url_creator_length(category_display_array, page_urls);
3946
4559
  for (let i = 0; i < category_display_array.length; i++)
3947
4560
  // Copy over getters so we sneakily can make this reactive
3948
4561
  Object.defineProperties(category_display_array[i], Object.getOwnPropertyDescriptors(page_urls[i]));
3949
4562
  }
3950
4563
  if (content_search_links?.length && content_result_transformer) {
3951
- const result = await content_result_transformer({
4564
+ const result = await $5vyXB$solidjs.runWithOwner(owner, () => content_result_transformer({
3952
4565
  merchant: merchant,
3953
4566
  market: market,
3954
4567
  data: [...content_search_links]
3955
- });
4568
+ }));
3956
4569
  this.#guard_url_creator_length(content_search_links, result);
3957
4570
  input_data.content_search_links = result;
3958
4571
  }
3959
4572
  return input_data;
3960
4573
  }
3961
- async #cached_post_request(endpoint, input_req, fallback_response) {
3962
- const cache_obj = this.#get_cache_obj_for_endpoint(endpoint);
3963
- 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();
3964
4584
  const metaData = await this.#get_metadata?.();
3965
4585
  const request = metaData ? Object.assign(with_ids, {
3966
4586
  metadata: metaData
3967
4587
  }) : with_ids;
3968
- 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);
3969
4590
  const response_from_cache = cache_obj.cache_[body]?.deref?.();
3970
4591
  if (response_from_cache) return response_from_cache;
3971
4592
  const in_progress_request = cache_obj.in_progress_[body];
@@ -3973,18 +4594,23 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
3973
4594
  let resolve_in_progress;
3974
4595
  cache_obj.in_progress_[body] = new Promise(r => resolve_in_progress = r);
3975
4596
  try {
3976
- const api_response = await $5vyXB$depictaiutilishared.fetch_retry($5vyXB$depictaiutilishared.add_version_query_params(endpoint), {
3977
- method: "POST",
3978
- 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
+ } : {})
3979
4605
  });
3980
4606
  return_successfully: {
3981
4607
  if (!api_response || api_response.status !== 200) break return_successfully;
3982
4608
  let result;
3983
4609
  try {
3984
4610
  const unmodified_result = await api_response.json();
3985
- 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));
3986
4612
  } catch (e) {
3987
- $5vyXB$depictaiutilishared.dwarn("URL creator or json decoding failed", e);
4613
+ $5vyXB$depictaiutilishared.dwarn("displayTransformer or json decoding failed", e);
3988
4614
  break return_successfully;
3989
4615
  }
3990
4616
  // Here result actually becomes O
@@ -4002,7 +4628,7 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
4002
4628
  return result;
4003
4629
  }
4004
4630
  // If we get here, the request failed
4005
- const retval = fallback_response(input_req);
4631
+ const retval = fallback_response_(input_req_);
4006
4632
  resolve_in_progress(retval);
4007
4633
  return retval;
4008
4634
  } finally {
@@ -4012,19 +4638,18 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
4012
4638
  constructor(options) {
4013
4639
  const {
4014
4640
  get_metadata: get_metadata,
4015
- get_user_id: get_user_id,
4016
4641
  get_session_id: get_session_id,
4017
4642
  page_url_creator: page_url_creator,
4018
4643
  display_transformers: display_transformers
4019
4644
  } = options ?? {};
4020
4645
  this.#get_metadata = get_metadata;
4021
- this.#get_user_id = get_user_id;
4022
4646
  this.#get_session_id = get_session_id;
4023
4647
  this.page_url_creator = page_url_creator;
4024
4648
  this.display_transformers = display_transformers;
4025
4649
  }
4026
4650
  async suggest(input_req) {
4027
4651
  const with_ids = this.#add_ids_to_request(input_req);
4652
+ const owner = $5vyXB$solidjs.getOwner();
4028
4653
  const metaData = await this.#get_metadata?.();
4029
4654
  const request = metaData ? Object.assign(with_ids, {
4030
4655
  metadata: JSON.stringify(metaData)
@@ -4036,9 +4661,9 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
4036
4661
  const decoded_json = await results.json();
4037
4662
  if (!Array.isArray(decoded_json?.suggestions)) break attempt_to_return_api_response;
4038
4663
  try {
4039
- 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));
4040
4665
  } catch (e) {
4041
- $5vyXB$depictaiutilishared.dwarn("URL creator failed", e);
4666
+ $5vyXB$depictaiutilishared.dwarn("displayTransformer failed", e);
4042
4667
  }
4043
4668
  }
4044
4669
  return {
@@ -4048,31 +4673,67 @@ class $e1d6c0f3d89d531c$export$e015ed2f2950f2e3 {
4048
4673
  };
4049
4674
  }
4050
4675
  async query(input_req) {
4051
- return await this.#cached_post_request($e1d6c0f3d89d531c$var$search_base_url + "results", input_req, () => ({
4052
- "n_hits": 0,
4053
- "displays": [],
4054
- "sorts": [],
4055
- "filters": [],
4056
- "search_request_id": "error",
4057
- failed: true
4058
- }));
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
+ });
4059
4688
  }
4060
- async list(input_req) {
4061
- return await this.#cached_post_request($e1d6c0f3d89d531c$var$v2_base_url + "product-listing", input_req, () => ({
4062
- "n_hits": 0,
4063
- "displays": [],
4064
- "sorts": [],
4065
- "filters": [],
4066
- "breadcrumb": [],
4067
- "quick_links": [],
4068
- "product_listing_request_id": "error",
4069
- failed: true
4070
- }));
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
+ });
4071
4728
  }
4072
4729
  async get_recommended(input_req) {
4073
- return await this.#cached_post_request($e1d6c0f3d89d531c$var$search_base_url + "related", input_req, () => ({
4074
- displays: []
4075
- }));
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
+ });
4076
4737
  }
4077
4738
  }
4078
4739
  function $b54e6192d0caa293$export$d9f36cf74e24d595(media_query) {
@@ -4171,7 +4832,7 @@ function $76b6ac05693f5c71$export$205efb947c7ffd78(handler, passive = true) {
4171
4832
  $5vyXB$solidjs.onCleanup(() => removeEventListener(event, catchified_handler));
4172
4833
  }
4173
4834
  }
4174
- 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>"];
4175
4836
  function $401aee5f33dca9e2$export$83fd5de5504a7a67({
4176
4837
  formatted_number_of_results_: formatted_number_of_results_,
4177
4838
  first_result_in_viewport_: [get_first_result_in_viewport],
@@ -4355,7 +5016,7 @@ function $3f08fe2992a2a8ca$export$5e4aed86c12acdd9({
4355
5016
  // After first load, always just load 20 since people might just be browsing the top ones still
4356
5017
  min_products_to_fetch_ : now - last_loaded < 10000 ? min_products_to_fetch_ * 5 : min_products_to_fetch_;
4357
5018
  // dlog("loading ", number_of_results_to_load, "products, because it was", now - last_loaded, "ms since last load");
4358
- 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"]({
4359
5020
  cursor: get_last_cursor(),
4360
5021
  limit: number_of_results_to_load,
4361
5022
  ...base_part
@@ -4418,8 +5079,6 @@ function $ac167f6af6a48fc3$export$a1fd619a4743ca08({
4418
5079
  product_card_template_: product_card_template_,
4419
5080
  first_result_in_viewport_: [, set_first_result_in_viewport],
4420
5081
  last_result_in_viewport_: [get_last_result_in_viewport_, set_last_result_in_viewport],
4421
- merchant_: merchant_,
4422
- market_: market_,
4423
5082
  all_products_loaded_: all_products_loaded_,
4424
5083
  min_products_to_fetch_: min_products_to_fetch_,
4425
5084
  query_base_: query_base_,
@@ -4471,8 +5130,6 @@ function $ac167f6af6a48fc3$export$a1fd619a4743ca08({
4471
5130
  });
4472
5131
  return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
4473
5132
  displays_by_key_: displays_by_key_,
4474
- merchant_: merchant_,
4475
- market_: market_,
4476
5133
  product_card_template_: product_card_template_,
4477
5134
  content_blocks_: content_blocks_,
4478
5135
  do_per_elements_: (elements, index_accessor) =>
@@ -4617,37 +5274,6 @@ function $055384b985678603$export$a79e666719b3647c(cols_at_size_) {
4617
5274
  });
4618
5275
  return n_cols_currently_showing;
4619
5276
  }
4620
- function $3bc4a89b971a3af5$export$3f37af283f8fb843(props) {
4621
- const style = $5vyXB$solidjs.createMemo(() => {
4622
- const {
4623
- style: style,
4624
- height: height,
4625
- width: width,
4626
- aspectRatio: aspectRatio
4627
- } = props;
4628
- const is_image = aspectRatio != undefined;
4629
- const size_data = is_image ? {
4630
- width: "100%",
4631
- "padding-bottom": 1 / aspectRatio * 100 + "%"
4632
- } : {
4633
- width: width,
4634
- height: height
4635
- };
4636
- return {
4637
- display: "block",
4638
- ...(style || {}),
4639
- ...size_data
4640
- };
4641
- });
4642
- return $5vyXB$solidjsweb.createComponent((0, $9fe9883b1d8ecccc$export$acb3eaade4b23afd), {
4643
- get style() {
4644
- return style();
4645
- },
4646
- get ["class"]() {
4647
- return props.class;
4648
- }
4649
- });
4650
- }
4651
5277
  const $d92f338ba8f9da9b$var$_tmpl$ = ["<div", ' class="content-block-wrapper" style="', '">', "</div>"];
4652
5278
  function $d92f338ba8f9da9b$export$791ef57e62e21c3f({
4653
5279
  content_blocks_: incoming_content_blocks,
@@ -4841,8 +5467,6 @@ function $fe76fb463cc60b89$export$3925f87b1545cfc6({
4841
5467
  }) {
4842
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
4843
5469
  const is_loading_ = $5vyXB$solidjs.createMemo(() => plp_results_.loading || query_base_.loading);
4844
- const merchant_ = $5vyXB$solidjs.createMemo(() => query_base_().tenant);
4845
- const market_ = $5vyXB$solidjs.createMemo(() => query_base_().market);
4846
5470
  const has_no_results_or_failed = $5vyXB$solidjs.createMemo(() => {
4847
5471
  const displays = plp_results_()?.displays;
4848
5472
  return !is_loading_() && (!Array.isArray(displays) || !displays.length);
@@ -4950,8 +5574,6 @@ function $fe76fb463cc60b89$export$3925f87b1545cfc6({
4950
5574
  plp_results_: plp_results_,
4951
5575
  last_result_in_viewport_: last_result_in_viewport_,
4952
5576
  first_result_in_viewport_: first_result_in_viewport_,
4953
- market_: market_,
4954
- merchant_: merchant_,
4955
5577
  all_products_loaded_: all_products_loaded_,
4956
5578
  min_products_to_fetch_: min_products_to_fetch_,
4957
5579
  query_base_: query_base_,
@@ -5079,42 +5701,6 @@ function $be89be42ce9ea60f$export$1f1775a58da589b5({
5079
5701
  }
5080
5702
  });
5081
5703
  }
5082
- function $ca1176b694a6ee2e$export$fe334901e8bebd57() {
5083
- const cleanup_fns = [];
5084
- const cleanup = () => cleanup_fns.forEach(f => f());
5085
- // use an animation to automatically retain the `overflow` values and all other styling
5086
- for (const element of [document.documentElement, document.body]) {
5087
- try {
5088
- const animation = element.animate({
5089
- overflow: "hidden",
5090
- offset: 0
5091
- }, 1);
5092
- animation.pause();
5093
- const fn = $5vyXB$depictaiutilishared.catchify(animation.play.bind(animation));
5094
- cleanup_fns.push(fn);
5095
- $5vyXB$solidjs.onCleanup(fn);
5096
- } catch (e) {
5097
- $5vyXB$depictaiutilishared.dlog("Probably partial keyframe error", e);
5098
- }
5099
- if (getComputedStyle(element).overflow !== "hidden") {
5100
- // safari gets special hacky treatment
5101
- const style = element.style;
5102
- const original_value = style.overflow;
5103
- style.overflow = "hidden";
5104
- const fn = $5vyXB$depictaiutilishared.catchify(() => style.overflow = original_value);
5105
- cleanup_fns.push(fn);
5106
- $5vyXB$solidjs.onCleanup(fn);
5107
- }
5108
- }
5109
- return cleanup;
5110
- } // the way that houdini does that (FYI) it fixes the page jumps
5111
- // const from_top = scrollY;
5112
- // document.body.style.position = "fixed";
5113
- // document.body.style.left = 0;
5114
- // document.body.style.right = 0;
5115
- // document.body.style.top = `-${from_top}px`;
5116
- // document.body.style.overflowY = "scroll";
5117
-
5118
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>',
5119
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>';
5120
5706
  function $f958b5ac0e4a78da$export$da32f7add8a22e86(props = {}) {
@@ -5674,7 +6260,6 @@ function $e53b2e7e632ac4cb$export$5646050d516e06bc({
5674
6260
  }) {
5675
6261
  const placeholder_crumb_data = [,,,];
5676
6262
  const crumb_data = $5vyXB$solidjs.createMemo(() => get_api_crumb_data() || placeholder_crumb_data);
5677
- const href_accessor = $5vyXB$depictaiutilishared.use_href_accessor();
5678
6263
  return $5vyXB$solidjsweb.createComponent((0, $edafe91daf3091d7$export$b69d0d92862de18b), {
5679
6264
  severity_: "error",
5680
6265
  message_: "BreadCrumbs failed",
@@ -5684,11 +6269,11 @@ function $e53b2e7e632ac4cb$export$5646050d516e06bc({
5684
6269
  return crumb_data();
5685
6270
  },
5686
6271
  children: (display_accessor, index) => {
5687
- const is_last = $5vyXB$solidjs.createMemo(() => index === crumb_data()?.length - 1);
5688
- const url = $5vyXB$solidjs.createMemo(() => is_last() ? href_accessor() : display_accessor()?.page_url);
5689
6272
  const href = $5vyXB$solidjs.createMemo(() => $1ab22f2cd39b3061$export$43cd1e747fecd42e({
5690
- to_url_: url(),
5691
- filter_query_param_prefix_: filter_query_param_prefix_,
6273
+ to_url_: display_accessor()?.page_url,
6274
+ filter_query_param_prefix_:
6275
+ // page_url here can be a getter if that was added in the display transformers as a way of making this reactive
6276
+ filter_query_param_prefix_,
5692
6277
  sorting_query_param_: sorting_query_param_
5693
6278
  }));
5694
6279
  return [$5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
@@ -5723,42 +6308,42 @@ const $8cceb1d3a967f369$var$_tmpl$ = ["<nav", ' class="quicklinks"', ">", "</nav
5723
6308
  function $8cceb1d3a967f369$export$466cdc317043f6cb({
5724
6309
  quicklinks_data_: quicklinks_data_,
5725
6310
  router_: router_,
5726
- current_query_id_: current_query_id_,
6311
+ current_listing_id_: current_listing_id_,
5727
6312
  breadcrumb_data_: breadcrumb_data_,
5728
6313
  i18n_: i18n_,
5729
6314
  sorting_query_param_: sorting_query_param_,
5730
6315
  filter_query_param_prefix_: filter_query_param_prefix_
5731
6316
  }) {
5732
- let scrolling_logic_ran_for_query_id = false;
6317
+ let scrolling_logic_ran_for_listing_id = false;
5733
6318
  let last_scroll_position;
5734
6319
  let scroll_to_element_on_dom_insertion;
5735
6320
  let last_was_placeholder = false;
5736
6321
  let sliding_element;
5737
6322
  $5vyXB$solidjs.createComputed(() => {
5738
- current_query_id_();
5739
- scrolling_logic_ran_for_query_id = false;
6323
+ current_listing_id_();
6324
+ scrolling_logic_ran_for_listing_id = false;
5740
6325
  });
5741
6326
  const place_holdey_quicklinks_data = $5vyXB$solidjs.createMemo(() => quicklinks_data_() || [,,,]);
5742
- const selected_index = $5vyXB$solidjs.createMemo(() => quicklinks_data_()?.findIndex(item => item.query_id === current_query_id_())); // this will be -1 when viewing child categories
5743
- const scrollpos_per_queryid = {};
6327
+ const selected_index = $5vyXB$solidjs.createMemo(() => quicklinks_data_()?.findIndex(item => item.listing_id === current_listing_id_())); // this will be -1 when viewing child categories
6328
+ const scrollpos_per_listing_id = {};
5744
6329
  const mutation_plugins = [function () {
5745
- if (!scrolling_logic_ran_for_query_id) return;
6330
+ if (!scrolling_logic_ran_for_listing_id) return;
5746
6331
  const {
5747
6332
  scrollLeft: scrollLeft
5748
6333
  } = this.insert_here;
5749
6334
  if (scrollLeft > 0) {
5750
6335
  last_scroll_position = scrollLeft;
5751
- const current_id = $5vyXB$solidjs.untrack(current_query_id_);
6336
+ const current_id = $5vyXB$solidjs.untrack(current_listing_id_);
5752
6337
  // make sure to not save position where selected item isn't in viewport
5753
6338
  const current_selected_index = $5vyXB$solidjs.untrack(selected_index);
5754
6339
  const intersecting_thing = this.intersecting_items_object[current_selected_index];
5755
- 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)
6340
+ 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)
5756
6341
  // if about to go out of view, stop saving it so that the "always show new things in view" thing can get to work
5757
- delete scrollpos_per_queryid[current_id];
6342
+ delete scrollpos_per_listing_id[current_id];
5758
6343
  }
5759
6344
  }];
5760
6345
  $5vyXB$solidjs.createComputed(() => {
5761
- if (place_holdey_quicklinks_data()?.[0]?.query_id) {
6346
+ if (place_holdey_quicklinks_data()?.[0]?.listing_id) {
5762
6347
  if (last_was_placeholder) queueMicrotask($5vyXB$depictaiutilishared.catchify(() => {
5763
6348
  sliding_element?.scrollTo({
5764
6349
  left: 0
@@ -5810,13 +6395,13 @@ function $8cceb1d3a967f369$export$466cdc317043f6cb({
5810
6395
  equals: false
5811
6396
  }), new_data => {
5812
6397
  const quicklinks_data = quicklinks_data_(); // this signal should have updated by now since this is a createEffect
5813
- const current_id = current_query_id_();
6398
+ const current_id = current_listing_id_();
5814
6399
  if (!new_data || !quicklinks_data || !current_id) return;
5815
6400
  const owner = $5vyXB$solidjs.getOwner();
5816
6401
  queueMicrotask(() => {
5817
6402
  // has to be in microtask so that elements have rendered and are scroll-to-able
5818
- scrolling_logic_ran_for_query_id = true;
5819
- const saved_scroll_position = scrollpos_per_queryid[current_id];
6403
+ scrolling_logic_ran_for_listing_id = true;
6404
+ const saved_scroll_position = scrollpos_per_listing_id[current_id];
5820
6405
  if (saved_scroll_position) {
5821
6406
  insert_here.scrollTo({
5822
6407
  left: saved_scroll_position
@@ -5858,10 +6443,10 @@ function $8cceb1d3a967f369$export$466cdc317043f6cb({
5858
6443
  // Problem: When you don't open a link in a new tab, we don't display the filter cleared toast
5859
6444
  // 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
5860
6445
  const is_sibling = $5vyXB$solidjs.createMemo(() => {
5861
- const current_id = current_query_id_();
6446
+ const current_id = current_listing_id_();
5862
6447
  return quicklinks_data_()?.some(({
5863
- query_id: query_id
5864
- }) => query_id === current_id);
6448
+ listing_id: listing_id
6449
+ }) => listing_id === current_id);
5865
6450
  });
5866
6451
  const href = $5vyXB$solidjs.createMemo(() =>
5867
6452
  // 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
@@ -5950,10 +6535,12 @@ async function $276380e4607fb9fb$export$cc42dd29bf655ab6({
5950
6535
  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.
5951
6536
  if (total_products_to_fetch <= $276380e4607fb9fb$var$api_max_products_per_request) return await make_request_(total_products_to_fetch);
5952
6537
  const displays = [];
6538
+ const owner = $5vyXB$solidjs.getOwner();
5953
6539
  let last_response;
5954
6540
  let next_cursor;
5955
6541
  for (let fetch_this_time = $276380e4607fb9fb$var$api_max_products_per_request; displays.length < total_products_to_fetch;) {
5956
- last_response = await make_request_(fetch_this_time, next_cursor);
6542
+ // Carry over the request when making the owner so that display transformers can use onCleanup
6543
+ last_response = await $5vyXB$solidjs.runWithOwner(owner, () => make_request_(fetch_this_time, next_cursor));
5957
6544
  const new_displays = last_response.displays;
5958
6545
  displays.push(...new_displays);
5959
6546
  next_cursor = last_response.cursor;
@@ -6067,7 +6654,7 @@ function $47e2cc552c02110c$export$8895d39404bd2bb1(props) {
6067
6654
  }
6068
6655
  function $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6069
6656
  crumb_data_: crumb_data_,
6070
- query_id_: query_id_,
6657
+ listing_id_: listing_id_,
6071
6658
  i18n_: i18n_,
6072
6659
  selected_filters_: selected_filters_,
6073
6660
  local_filter_cache_: local_filter_cache_,
@@ -6086,15 +6673,15 @@ function $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6086
6673
  });
6087
6674
  // Code below is for when we're already open and the user navigates to a new category
6088
6675
  let previous_crumb_data = $5vyXB$solidjs.untrack(crumb_data_);
6089
- let query_id_when_we_got_previous_data = $5vyXB$solidjs.untrack(query_id_);
6676
+ let listing_id_when_we_got_previous_data = $5vyXB$solidjs.untrack(listing_id_);
6090
6677
  let allow_filter_clearing = true; // set to false when going backwards/forwards
6091
6678
  // temporarily disable filter clearing when going backwards/forwards
6092
6679
  const handler = () => allow_filter_clearing = false;
6093
6680
  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
6094
6681
  $5vyXB$solidjs.onCleanup(() => window.removeEventListener("popstate", handler));
6095
6682
  $5vyXB$solidjs.createEffect($5vyXB$solidjs.on(crumb_data_, $5vyXB$depictaiutilishared.catchify(new_crumb_data => {
6096
- const query_id_of_new_data = query_id_();
6097
- if (allow_filter_clearing && previous_crumb_data && new_crumb_data && query_id_of_new_data !== query_id_when_we_got_previous_data) {
6683
+ const listing_id_of_new_data = listing_id_();
6684
+ if (allow_filter_clearing && previous_crumb_data && new_crumb_data && listing_id_of_new_data !== listing_id_when_we_got_previous_data) {
6098
6685
  const previous_length = previous_crumb_data.length;
6099
6686
  const new_length = new_crumb_data.length;
6100
6687
  const went_upwards = new_length < previous_length;
@@ -6102,8 +6689,8 @@ function $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6102
6689
  const shorter_array = went_upwards ? new_crumb_data : previous_crumb_data;
6103
6690
  const longer_array = went_upwards ? previous_crumb_data : new_crumb_data;
6104
6691
  if (!((went_upwards || went_downwards) && shorter_array.every(({
6105
- query_id: query_id
6106
- }, index) => longer_array[index].query_id === query_id))) {
6692
+ listing_id: listing_id
6693
+ }, index) => longer_array[index].listing_id === listing_id))) {
6107
6694
  // We went sideways, not up or down. Clear filters.
6108
6695
  $47e2cc552c02110c$export$8895d39404bd2bb1({
6109
6696
  user_triggered_: false,
@@ -6117,7 +6704,7 @@ function $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6117
6704
  sideways_filter_clearing_flag_[1](false);
6118
6705
  }
6119
6706
  }
6120
- query_id_when_we_got_previous_data = query_id_of_new_data;
6707
+ listing_id_when_we_got_previous_data = listing_id_of_new_data;
6121
6708
  previous_crumb_data = new_crumb_data;
6122
6709
  if (!allow_filter_clearing) allow_filter_clearing = true;
6123
6710
  })));
@@ -6149,7 +6736,6 @@ function $ef972f5c10b1c5b4$var$clear_if_opened_new_tab_with_sideways_url_params_
6149
6736
  });
6150
6737
  tracking_function_for_plp_results(plp_results_);
6151
6738
  }
6152
- const $6b502b1b2155a0bc$export$5c28802497c8a83c = /*@__PURE__*/Symbol("category_title_type");
6153
6739
  function $6a8e766e914723d8$export$d31a1a1a83ad9413(plp_results_, [get_selected_filters, set_selected_filters]) {
6154
6740
  $5vyXB$solidjs.createComputed(() => {
6155
6741
  const available_filters = plp_results_()?.filters;
@@ -6181,8 +6767,7 @@ const $840d88a04b2d22a7$var$_tmpl$ = ["<div", ' class="product-count"><!--$-->',
6181
6767
  $840d88a04b2d22a7$var$_tmpl$4 = ["<div", ' class="depict plp category"><div class="listing-page"><!--$-->', "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--><!--$-->", "<!--/--></div><!--$-->", "<!--/--><!--$-->", "<!--/--></div>"];
6182
6768
  function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6183
6769
  depict_api_: depict_api_,
6184
- query_id_: query_id_,
6185
- listing_type_: listing_type_,
6770
+ listing_id_: listing_id_,
6186
6771
  meta_title_suffix_: meta_title_suffix_,
6187
6772
  current_sorting_: current_sorting_,
6188
6773
  min_products_to_fetch_: min_products_to_fetch_,
@@ -6195,7 +6780,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6195
6780
  get_breadcrumb_accessor_: get_breadcrumb_accessor_,
6196
6781
  expanded_hierarchical_filters_: expanded_hierarchical_filters_,
6197
6782
  local_filter_cache_: local_filter_cache_,
6198
- tenant_: tenant_,
6783
+ merchant_: merchant_,
6199
6784
  market_: market_,
6200
6785
  router_: router_,
6201
6786
  show_quicklinks_: show_quicklinks_,
@@ -6218,22 +6803,25 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6218
6803
  show_n_results_: incoming_i18n.show_n_products_,
6219
6804
  no_results_text_: incoming_i18n.no_products_text_
6220
6805
  };
6806
+ const {
6807
+ backend_locale_: backend_locale_
6808
+ } = i18n_;
6221
6809
  const [get_sorting] = current_sorting_;
6222
6810
  const number_of_rendered_selected_filters_items_ = $5vyXB$solidjs.createSignal(0);
6223
6811
  const first_result_in_viewport_ = $5vyXB$solidjs.createSignal();
6224
6812
  const last_result_in_viewport_ = $5vyXB$solidjs.createSignal();
6225
6813
  const [can_write_scroll_restoration_, set_can_write_scroll_restoration] = $5vyXB$solidjs.createSignal(false);
6226
- const query_base_ = $8cd545330f2674dc$export$210f130a61ac1e8d(() => {
6814
+ const products_query_base_ = $8cd545330f2674dc$export$210f130a61ac1e8d(() => {
6227
6815
  const sort_obj = get_sorting() && {
6228
6816
  ...get_sorting()
6229
6817
  };
6230
6818
  delete sort_obj?.meta;
6231
6819
  const f = selected_filters_[0]();
6232
6820
  return {
6233
- tenant: tenant_(),
6821
+ merchant: merchant_(),
6234
6822
  market: market_(),
6235
- query_id: query_id_(),
6236
- type: listing_type_(),
6823
+ locale: backend_locale_(),
6824
+ listing_id: listing_id_(),
6237
6825
  ...(f.length ? {
6238
6826
  filters: f
6239
6827
  } : {}),
@@ -6242,13 +6830,14 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6242
6830
  } : {})
6243
6831
  };
6244
6832
  });
6245
- const [plp_results_] = $5vyXB$solidjs.createResource(query_base_,
6833
+ // Make "Get products in listing" request to get products in listing
6834
+ const [plp_products_] = $5vyXB$solidjs.createResource(products_query_base_,
6246
6835
  // 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)
6247
6836
  $5vyXB$depictaiutilishared.catchify(base_query => $276380e4607fb9fb$export$cc42dd29bf655ab6({
6248
- id_: $5vyXB$solidjs.untrack(query_id_),
6837
+ id_: $5vyXB$solidjs.untrack(listing_id_),
6249
6838
  scroll_restoration_data_: scroll_restoration_data_,
6250
6839
  min_products_to_fetch_: min_products_to_fetch_,
6251
- make_request_: (limit, cursor) => depict_api_.list({
6840
+ make_request_: (limit, cursor) => depict_api_.get_listing_products({
6252
6841
  ...base_query,
6253
6842
  limit: limit,
6254
6843
  ...(cursor ? {
@@ -6256,24 +6845,33 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6256
6845
  } : {})
6257
6846
  })
6258
6847
  })));
6259
- const available_sortings_ = $5vyXB$solidjs.createMemo(() => plp_results_()?.sorts?.map(sort => ({
6848
+ const meta_query_base = $8cd545330f2674dc$export$210f130a61ac1e8d(() => ({
6849
+ merchant: merchant_(),
6850
+ market: market_(),
6851
+ locale: backend_locale_(),
6852
+ listing_id: listing_id_()
6853
+ }));
6854
+ // Make "Get Listing" request to get quicklinks, breadcrumbs, title, etc
6855
+ const [plp_meta] = $5vyXB$solidjs.createResource(meta_query_base, $5vyXB$depictaiutilishared.catchify(query => depict_api_.get_listing(query)));
6856
+ const available_sortings_ = $5vyXB$solidjs.createMemo(() => plp_products_()?.sorts?.map(sort => ({
6260
6857
  ...sort,
6261
6858
  order: sort.order ?? "desc"
6262
6859
  })));
6263
- const available_filters_ = $5vyXB$solidjs.createMemo(() => plp_results_()?.filters);
6264
- const crumb_data_ = $5vyXB$solidjs.createMemo(() => plp_results_()?.breadcrumb);
6265
- const quicklinks_data_ = $5vyXB$solidjs.createMemo(() => plp_results_()?.quick_links);
6860
+ const available_filters_ = $5vyXB$solidjs.createMemo(() => plp_products_()?.filters);
6861
+ const title = $5vyXB$solidjs.createMemo(() => plp_meta()?.title);
6862
+ const crumb_data_ = $840d88a04b2d22a7$var$add_us_to_crumbs(plp_meta, title);
6863
+ const quicklinks_data_ = $5vyXB$solidjs.createMemo(() => plp_meta()?.quick_links);
6266
6864
  const meta_tag_data_ = $5vyXB$solidjs.createMemo(() => {
6267
- if (plp_results_()?.metadata?.replace_meta_tags) return {
6268
- title: plp_results_()?.metadata?.title + (meta_title_suffix_() || ""),
6269
- description: plp_results_()?.metadata?.description
6865
+ if (plp_meta()?.replace_meta_tags) return {
6866
+ title: plp_meta()?.title + (meta_title_suffix_() || ""),
6867
+ description: plp_meta()?.description
6270
6868
  };
6271
6869
  });
6272
6870
  $5vyXB$depictaiutilishared.edit_current_page_meta_tags(meta_tag_data_);
6273
6871
  const [sort_or_filter_open_, set_sort_or_filter_open_] = $5vyXB$solidjs.createSignal(false);
6274
6872
  const [desktop_filter_elements_, set_desktop_filter_elements] = $5vyXB$solidjs.createSignal();
6275
6873
  const formatted_number_of_results_ = $0f400c3f7248d5f1$export$92f2da32c6e7e7ee({
6276
- number_: $5vyXB$solidjs.createMemo(() => plp_results_()?.n_hits),
6874
+ number_: $5vyXB$solidjs.createMemo(() => plp_products_()?.n_hits),
6277
6875
  i18n_: i18n_
6278
6876
  });
6279
6877
  const [sort_and_filter_element_, set_sort_and_filter_element_] = $5vyXB$solidjs.createSignal();
@@ -6285,7 +6883,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6285
6883
  const extra_sort_and_filter_args_ = {};
6286
6884
  const make_product_count_ = () => $5vyXB$solidjsweb.ssr($840d88a04b2d22a7$var$_tmpl$, $5vyXB$solidjsweb.ssrHydrationKey(), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
6287
6885
  get when() {
6288
- return plp_results_.loading;
6886
+ return plp_products_.loading;
6289
6887
  },
6290
6888
  fallback: formatted_number_of_results_,
6291
6889
  get children() {
@@ -6296,7 +6894,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6296
6894
  }
6297
6895
  })), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $5vyXB$solidjs.Show), {
6298
6896
  get when() {
6299
- return plp_results_()?.n_hits === 1;
6897
+ return plp_products_()?.n_hits === 1;
6300
6898
  },
6301
6899
  get fallback() {
6302
6900
  return i18n_.products_();
@@ -6305,11 +6903,10 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6305
6903
  return i18n_.product_();
6306
6904
  }
6307
6905
  })));
6308
- $6a8e766e914723d8$export$d31a1a1a83ad9413(plp_results_, selected_filters_);
6906
+ $6a8e766e914723d8$export$d31a1a1a83ad9413(plp_products_, selected_filters_);
6309
6907
  // 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
6310
6908
  if (category_title_type === "simple") {
6311
6909
  const CategoryTitleComponent = category_title_;
6312
- const title = $5vyXB$solidjs.createMemo(() => crumb_data_()?.at(-1)?.title ?? plp_results_()?.metadata?.title);
6313
6910
  results_for = $5vyXB$solidjsweb.createComponent(CategoryTitleComponent, {
6314
6911
  category_title_: title,
6315
6912
  get product_count_() {
@@ -6355,12 +6952,12 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6355
6952
  $5vyXB$depictaiutilishared.catchify((0, $276380e4607fb9fb$export$6e49da55e449af7c))({
6356
6953
  scroll_restoration_data_: scroll_restoration_data_,
6357
6954
  last_result_in_viewport_: last_result_in_viewport_,
6358
- id_: query_id_,
6955
+ id_: listing_id_,
6359
6956
  can_write_scroll_restoration_: can_write_scroll_restoration_
6360
6957
  });
6361
6958
  on_filters_constructed_?.();
6362
6959
  $5vyXB$solidjs.createComputed(() => {
6363
- if (plp_results_.loading) set_can_write_scroll_restoration(false);else if (plp_results_()) set_can_write_scroll_restoration(true);
6960
+ if (plp_products_.loading) set_can_write_scroll_restoration(false);else if (plp_products_()) set_can_write_scroll_restoration(true);
6364
6961
  });
6365
6962
  $5vyXB$solidjs.createRenderEffect($5vyXB$depictaiutilishared.catchify(async () => {
6366
6963
  const slim = is_slim_();
@@ -6375,13 +6972,13 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6375
6972
  available_filters_: available_filters_
6376
6973
  });
6377
6974
  $ef972f5c10b1c5b4$export$3945d6db2dfd3d12({
6378
- query_id_: query_id_,
6975
+ listing_id_: listing_id_,
6379
6976
  crumb_data_: crumb_data_,
6380
6977
  i18n_: i18n_,
6381
6978
  selected_filters_: selected_filters_,
6382
6979
  local_filter_cache_: local_filter_cache_,
6383
6980
  expanded_hierarchical_filters_: expanded_hierarchical_filters_,
6384
- plp_results_: plp_results_,
6981
+ plp_results_: plp_products_,
6385
6982
  sideways_filter_clearing_flag_: sideways_filter_clearing_flag_
6386
6983
  });
6387
6984
  get_breadcrumb_accessor_?.(crumb_data_);
@@ -6406,7 +7003,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6406
7003
  get children() {
6407
7004
  return $5vyXB$solidjsweb.createComponent((0, $8cceb1d3a967f369$export$466cdc317043f6cb), {
6408
7005
  quicklinks_data_: quicklinks_data_,
6409
- current_query_id_: query_id_,
7006
+ current_listing_id_: listing_id_,
6410
7007
  router_: router_,
6411
7008
  breadcrumb_data_: crumb_data_,
6412
7009
  i18n_: i18n_,
@@ -6445,8 +7042,8 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6445
7042
  min_products_to_fetch_:
6446
7043
  // if you want to get if all products have been loaded you can add an optional signal here, see SearchPage
6447
7044
  min_products_to_fetch_,
6448
- query_base_: query_base_,
6449
- plp_results_: plp_results_,
7045
+ query_base_: products_query_base_,
7046
+ plp_results_: plp_products_,
6450
7047
  depict_api_: depict_api_,
6451
7048
  first_result_in_viewport_: first_result_in_viewport_,
6452
7049
  last_result_in_viewport_: last_result_in_viewport_,
@@ -6456,7 +7053,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6456
7053
  sort_or_filter_open_: sort_or_filter_open_,
6457
7054
  desktop_filter_elements_: desktop_filter_elements_,
6458
7055
  content_blocks_by_row_: content_blocks_by_row_,
6459
- id_currently_querying_for_: query_id_,
7056
+ id_currently_querying_for_: listing_id_,
6460
7057
  no_results_options_: {
6461
7058
  selected_filters_: selected_filters_,
6462
7059
  expanded_hierarchical_filters_: expanded_hierarchical_filters_,
@@ -6476,7 +7073,7 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6476
7073
  last_result_in_viewport_: last_result_in_viewport_,
6477
7074
  formatted_number_of_results_: formatted_number_of_results_,
6478
7075
  i18n_: i18n_,
6479
- number_of_results_: $5vyXB$solidjs.createMemo(() => plp_results_()?.n_hits)
7076
+ number_of_results_: $5vyXB$solidjs.createMemo(() => plp_products_()?.n_hits)
6480
7077
  });
6481
7078
  }
6482
7079
  })), $5vyXB$solidjsweb.escape($5vyXB$solidjsweb.createComponent((0, $edafe91daf3091d7$export$b69d0d92862de18b), {
@@ -6493,16 +7090,40 @@ function $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6493
7090
  }
6494
7091
  })))];
6495
7092
  }
7093
+ /**
7094
+ * Adds the current page as last breadcrumb to the breadcrumb trail
7095
+ */
7096
+ function $840d88a04b2d22a7$var$add_us_to_crumbs(plp_meta, title) {
7097
+ const href_accessor = $5vyXB$depictaiutilishared.use_href_accessor();
7098
+ return $5vyXB$solidjs.createMemo(() => {
7099
+ const api_value = plp_meta()?.breadcrumbs;
7100
+ if (!api_value) return api_value;
7101
+ return [...api_value, {
7102
+ get listing_id() {
7103
+ return plp_meta().listing_id;
7104
+ },
7105
+ get title() {
7106
+ return title();
7107
+ },
7108
+ get page_url() {
7109
+ return href_accessor();
7110
+ },
7111
+ get slug() {
7112
+ return plp_meta().slug;
7113
+ }
7114
+ }];
7115
+ });
7116
+ }
6496
7117
  function $c79fd10a3ab7d6e0$export$477caf01aecaeb2a(options) {
6497
7118
  const router_ = options.router_;
6498
7119
  const search_query_url_param_name_ = "search_query_url_param_name_" in options ? options.search_query_url_param_name_ : undefined;
6499
7120
  const search_query_ = search_query_url_param_name_ ? $5vyXB$solidjs.createSignal("") : undefined;
6500
- const override_query_id_query_param_names_ = "override_query_id_query_param_names_" in options ? options.override_query_id_query_param_names_ : undefined;
6501
- const override_query_id_ = override_query_id_query_param_names_ ? $5vyXB$solidjs.createSignal(null) : undefined;
7121
+ const override_listing_id_query_param_names_ = "override_listing_id_query_param_names_" in options ? options.override_listing_id_query_param_names_ : undefined;
7122
+ const override_listing_id_ = override_listing_id_query_param_names_ ? $5vyXB$solidjs.createSignal(null) : undefined;
6502
7123
  const get_search_query_ = search_query_?.[0];
6503
7124
  const set_search_query = search_query_?.[1];
6504
- const get_override_query_id_ = override_query_id_?.[0];
6505
- const set_override_query_id = override_query_id_?.[1];
7125
+ const get_override_listing_id_ = override_listing_id_?.[0];
7126
+ const set_override_listing_id = override_listing_id_?.[1];
6506
7127
  const current_sorting_ = $5vyXB$solidjs.createSignal();
6507
7128
  const selected_filters_ = $5vyXB$solidjs.createSignal([]);
6508
7129
  const sideways_filter_clearing_flag_ = $5vyXB$solidjs.createSignal(false);
@@ -6547,10 +7168,10 @@ function $c79fd10a3ab7d6e0$export$477caf01aecaeb2a(options) {
6547
7168
  const found_query = searchParams.get(search_query_url_param_name_);
6548
7169
  set_search_query(found_query || "");
6549
7170
  }
6550
- if (override_query_id_query_param_names_) {
6551
- const found_override_query_id = override_query_id_query_param_names_.map(n => searchParams.get(n)).find(n => n);
6552
- set_override_query_id(found_override_query_id || null);
6553
- 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
7171
+ if (override_listing_id_query_param_names_) {
7172
+ const found_override_listing_id = override_listing_id_query_param_names_.map(n => searchParams.get(n)).find(n => n);
7173
+ set_override_listing_id(found_override_listing_id || null);
7174
+ 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
6554
7175
  }
6555
7176
 
6556
7177
  if (searchParams.get((0, $1ab22f2cd39b3061$export$cf5feb2102aec7f2)) === "true") set_has_sideways_filter_clearing_flag(true);
@@ -6577,8 +7198,8 @@ function $c79fd10a3ab7d6e0$export$477caf01aecaeb2a(options) {
6577
7198
  } : {
6578
7199
  sideways_filter_clearing_flag_: sideways_filter_clearing_flag_
6579
7200
  }),
6580
- ...(typeof override_query_id_query_param_names_ === "object" ? {
6581
- override_query_id_accessor_: get_override_query_id_
7201
+ ...(typeof override_listing_id_query_param_names_ === "object" ? {
7202
+ override_listing_id_accessor_: get_override_listing_id_
6582
7203
  } : {})
6583
7204
  };
6584
7205
  }
@@ -6623,108 +7244,6 @@ function $c79fd10a3ab7d6e0$var$start_href_writer({
6623
7244
  function $c79fd10a3ab7d6e0$var$delete_sideways_param_flag(searchParams) {
6624
7245
  if (searchParams.get((0, $1ab22f2cd39b3061$export$cf5feb2102aec7f2)) === "true") searchParams.delete((0, $1ab22f2cd39b3061$export$cf5feb2102aec7f2));
6625
7246
  }
6626
- class $e96dd13889871fc0$export$7e1297a3a19f10d8 {
6627
- /**
6628
- * Function that will be called when we want to navigate, or a string saying it's not an SPA. You can change this OTG
6629
- */ /**
6630
- * 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
6631
- */
6632
- #throwing_on_navigation(...args) {
6633
- const {
6634
- on_navigation_: on_navigation_
6635
- } = this;
6636
- if (typeof on_navigation_ !== "function") throw new Error("on_navigation_ is not a function");
6637
- // make sure that we don't accidentally catchify if the SDK consumer has fucked up
6638
- try {
6639
- return on_navigation_(...args);
6640
- } catch (e) {
6641
- queueMicrotask(() => {
6642
- throw e;
6643
- });
6644
- }
6645
- }
6646
- /**
6647
- * Checks if this tab shouldn't navigate because user wants to open in new tab
6648
- */
6649
- #dont_attempt_navigation(ev) {
6650
- return ev?.button || ev?.metaKey || ev?.ctrlKey;
6651
- }
6652
- /**
6653
- * Vue has async router that needs to be awaited (it navigates after a microtask)
6654
- * This standardises waiting for all kinds of routers
6655
- */
6656
- #get_navigation_happened_promise(is_replace) {
6657
- return new Promise(resolve => {
6658
- const handler = what_happened => {
6659
- if (what_happened === (is_replace ? "replaceState" : "pushState")) {
6660
- resolve();
6661
- (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).delete(handler);
6662
- }
6663
- };
6664
- (0, $5vyXB$depictaiutilishared.instant_exec_on_suspect_history_change).add(handler);
6665
- });
6666
- }
6667
- navigate_ = {
6668
- /**
6669
- * Call this if you *just* want to replace the state object in history.state
6670
- */
6671
- replace_state_: new_state => {
6672
- // 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
6673
- globalThis?.history?.replaceState(new_state, "");
6674
- },
6675
- /**
6676
- * Call this to change the URL
6677
- * @param new_url_ new URL to go to
6678
- * @param event_ event if you have this in a click handler, will not do anything on cmd/ctrl or non-left click then
6679
- * @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
6680
- * @param is_replace_ if you want to replace the current URL in history instead of pushing a new one
6681
- * @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
6682
- */
6683
- go_to_: $5vyXB$depictaiutilishared.catchify(async ({
6684
- new_url_: raw_new_url,
6685
- event_: event_,
6686
- force_spa_navigation_: force_spa_navigation_,
6687
- is_replace_: is_replace_,
6688
- category_query_id_: category_query_id_,
6689
- scroll = true
6690
- }) => {
6691
- const new_url_ = raw_new_url instanceof URL ? raw_new_url : new URL(raw_new_url, location.origin);
6692
- const wants_hard_navigation = this.on_navigation_ === "hard_navigation";
6693
- if (this.#dont_attempt_navigation(event_)) return;
6694
- const different_origin = new_url_.origin !== location.origin;
6695
- if (wants_hard_navigation && (!force_spa_navigation_ || different_origin)) {
6696
- if (force_spa_navigation_ && different_origin)
6697
- // If we call history.pushState on a different origin, it will throw an error, so fallback to hard navigations
6698
- $5vyXB$depictaiutilishared.dwarn("Can't single page navigate to", new_url_.href, "due to different origin, this MIGHT mean you should fix the URLs");
6699
- if (!event_)
6700
- // If we haven't gotten an event, nothing will happen by not calling prevent default, so we need to change the URL
6701
- location.assign(new_url_);
6702
- return;
6703
- }
6704
- event_?.preventDefault();
6705
- const promise = this.#get_navigation_happened_promise(true);
6706
- if (force_spa_navigation_ && wants_hard_navigation) {
6707
- // Don't allow hard navigation if we're forcing SPA navigation, which we do for things where PageReplacer can be used for performance
6708
- const new_state = history.state;
6709
- if (category_query_id_) {
6710
- // In JS-UI we need to know the query_id of the current category, therefore push it into state
6711
- if (!this.query_id_state_key) $5vyXB$depictaiutilishared.report(new Error("query_id_state_key is not set"), "error");
6712
- new_state[this.query_id_state_key] = category_query_id_;
6713
- }
6714
- history[is_replace_ ? "replaceState" : "pushState"](new_state, "", new_url_);
6715
- } else this.#throwing_on_navigation.call(this, {
6716
- is_replace: is_replace_,
6717
- new_url: new_url_ instanceof URL ? new_url_ : new URL(new_url_, location.origin),
6718
- scroll: scroll
6719
- });
6720
- await promise;
6721
- })
6722
- };
6723
- constructor(on_navigation, query_id_state_key) {
6724
- this.query_id_state_key = query_id_state_key;
6725
- this.on_navigation_ = on_navigation;
6726
- }
6727
- }
6728
7247
 
6729
7248
  /**
6730
7249
  * Wraps a function in a try/catch block and throws the error globally. If undefined is provided as fn, a no-op is returned.
@@ -6755,26 +7274,25 @@ const $48567ac5b39bac56$var$InExternalAreaDiv = ({
6755
7274
  }) => $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));
6756
7275
  class $48567ac5b39bac56$export$f34314aa9505732e {
6757
7276
  #router;
6758
- #locale_signal = $5vyXB$solidjs.createSignal();
7277
+ #localization_signal = $5vyXB$solidjs.createSignal();
6759
7278
  #merchant_signal = $5vyXB$solidjs.createSignal();
6760
7279
  #market_signal = $5vyXB$solidjs.createSignal();
6761
- #query_id_signal = $5vyXB$solidjs.createSignal("");
7280
+ #listing_id_signal = $5vyXB$solidjs.createSignal("");
6762
7281
  #meta_title_suffix_ = $5vyXB$solidjs.createSignal();
6763
- #disable_override_query_id = $5vyXB$solidjs.createSignal();
6764
- #listing_type_signal = $5vyXB$solidjs.createSignal();
7282
+ #disable_override_listing_id = $5vyXB$solidjs.createSignal();
6765
7283
  static #keys_constructed_with = /*@__PURE__*/new Set();
6766
7284
  get localization() {
6767
7285
  // allow reactive access
6768
- return this.#locale_signal[0]();
7286
+ return this.#localization_signal[0]();
6769
7287
  }
6770
7288
  set localization(locale_obj) {
6771
- this.#locale_signal[1](locale_obj);
7289
+ this.#localization_signal[1](locale_obj);
6772
7290
  }
6773
- get category_id() {
6774
- return this.#query_id_signal[0]();
7291
+ get listing_id() {
7292
+ return this.#listing_id_signal[0]();
6775
7293
  }
6776
- set category_id(id) {
6777
- this.#query_id_signal[1](id);
7294
+ set listing_id(id) {
7295
+ this.#listing_id_signal[1](id);
6778
7296
  }
6779
7297
  get merchant() {
6780
7298
  return this.#merchant_signal[0]();
@@ -6788,23 +7306,17 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6788
7306
  set market(market) {
6789
7307
  this.#market_signal[1](market);
6790
7308
  }
6791
- get listing_type() {
6792
- return this.#listing_type_signal[0]();
6793
- }
6794
- set listing_type(listing_type) {
6795
- this.#listing_type_signal[1](listing_type);
6796
- }
6797
7309
  get meta_title_suffix() {
6798
7310
  return this.#meta_title_suffix_[0]();
6799
7311
  }
6800
7312
  set meta_title_suffix(new_suffix) {
6801
7313
  this.#meta_title_suffix_[1](new_suffix);
6802
7314
  }
6803
- get disable_override_query_id() {
6804
- return this.#disable_override_query_id[0]();
7315
+ get disable_override_listing_id() {
7316
+ return this.#disable_override_listing_id[0]();
6805
7317
  }
6806
- set disable_override_query_id(new_value) {
6807
- this.#disable_override_query_id[1](new_value);
7318
+ set disable_override_listing_id(new_value) {
7319
+ this.#disable_override_listing_id[1](new_value);
6808
7320
  }
6809
7321
  get on_navigation() {
6810
7322
  // The only non-reactive public property on the class (I don't see it making sense to have it reactive)
@@ -6819,7 +7331,7 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6819
7331
  page_url_creator: page_url_creator,
6820
7332
  display_transformers: display_transformers,
6821
7333
  unique_instance_key_for_state = "",
6822
- query_id_state_key: query_id_state_key,
7334
+ listing_id_state_key: listing_id_state_key,
6823
7335
  ...props_on_class
6824
7336
  }) {
6825
7337
  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
@@ -6829,21 +7341,21 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6829
7341
  throw new Error("You can only have one instance of DepictCategory with the same uniqueInstanceKeyForState");
6830
7342
  Object.assign(this, props_on_class); // set initial signal values
6831
7343
  $d84fe647b84b5dc5$export$5162a71f252e6122();
6832
- this.#router = new (0, $e96dd13889871fc0$export$7e1297a3a19f10d8)("hard_navigation", query_id_state_key);
7344
+ this.#router = new (0, $e96dd13889871fc0$export$7e1297a3a19f10d8)("hard_navigation", listing_id_state_key);
6833
7345
  if (on_navigation) this.#router.on_navigation_ = on_navigation;
6834
- 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
7346
+ 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
6835
7347
  const sorting_query_param_ = "sorting" + unique_instance_key_for_state;
6836
7348
  const filter_query_param_prefix_ = "f" + unique_instance_key_for_state + "_";
6837
7349
  const {
6838
7350
  selected_filters_: selected_filters_,
6839
7351
  current_sorting_: current_sorting_,
6840
7352
  sideways_filter_clearing_flag_: sideways_filter_clearing_flag_,
6841
- override_query_id_accessor_: override_query_id_accessor_
7353
+ override_listing_id_accessor_: override_listing_id_accessor_
6842
7354
  } = $c79fd10a3ab7d6e0$export$477caf01aecaeb2a({
6843
7355
  router_: this.#router,
6844
7356
  sorting_query_param_: sorting_query_param_,
6845
7357
  filter_query_param_prefix_: filter_query_param_prefix_,
6846
- override_query_id_query_param_names_: override_query_id_query_param_names_
7358
+ override_listing_id_query_param_names_: override_listing_id_query_param_names_
6847
7359
  });
6848
7360
  const [reset_history_state_, state_] = $26a56f6b44703084$export$9862539c89138352({
6849
7361
  get_default_values_: () => ({
@@ -6858,7 +7370,7 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6858
7370
  router_: this.#router,
6859
7371
  prefix_: "category" + unique_instance_key_for_state + "_"
6860
7372
  });
6861
- const i18n_ = $0785f4c9947d9b5f$export$f091cbac892643a4(this.#locale_signal[0]);
7373
+ const i18n_ = $0785f4c9947d9b5f$export$f091cbac892643a4(this.#localization_signal[0]);
6862
7374
  $48567ac5b39bac56$var$privately_shared_properties.set(this, {
6863
7375
  state_: state_,
6864
7376
  breadcrumb_signal_: $5vyXB$solidjs.createSignal(),
@@ -6873,7 +7385,7 @@ class $48567ac5b39bac56$export$f34314aa9505732e {
6873
7385
  router_: this.#router,
6874
7386
  selected_filters_: selected_filters_,
6875
7387
  current_sorting_: current_sorting_,
6876
- override_query_id_accessor_: override_query_id_accessor_,
7388
+ override_listing_id_accessor_: override_listing_id_accessor_,
6877
7389
  sideways_filter_clearing_flag_: sideways_filter_clearing_flag_,
6878
7390
  sorting_query_param_: sorting_query_param_,
6879
7391
  filter_query_param_prefix_: filter_query_param_prefix_
@@ -6893,11 +7405,11 @@ function $48567ac5b39bac56$export$e2bf8ce7779e827e(props) {
6893
7405
  return $95837413165cc2df$export$23fca46f3143581f(() => {
6894
7406
  $5vyXB$solidjs.createEffect(prev => {
6895
7407
  // 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
6896
- const id = depict_category.category_id; // <- this is a reactive getter
6897
- $deaaf04362a1bc71$export$f50b88e2a00918b5(props.on_query_id_change)(id, prev);
7408
+ const id = depict_category.listing_id; // <- this is a reactive getter
7409
+ $deaaf04362a1bc71$export$f50b88e2a00918b5(props.on_listing_id_change)(id, prev);
6898
7410
  return id;
6899
7411
  });
6900
- $5vyXB$solidjs.onCleanup(() => $deaaf04362a1bc71$export$f50b88e2a00918b5(props.on_query_id_change)());
7412
+ $5vyXB$solidjs.onCleanup(() => $deaaf04362a1bc71$export$f50b88e2a00918b5(props.on_listing_id_change)());
6901
7413
  const grid_spacing_override = $5vyXB$solidjs.createMemo(() => {
6902
7414
  const {
6903
7415
  grid_spacing: grid_spacing
@@ -6920,7 +7432,7 @@ function $48567ac5b39bac56$export$e2bf8ce7779e827e(props) {
6920
7432
  },
6921
7433
  current_sorting_: current_sorting_,
6922
7434
  selected_filters_: selected_filters_,
6923
- override_query_id_accessor_: override_query_id_accessor_,
7435
+ override_listing_id_accessor_: override_listing_id_accessor_,
6924
7436
  reset_history_state_: reset_history_state_,
6925
7437
  depict_api_: depict_api_,
6926
7438
  i18n_: i18n_,
@@ -6933,14 +7445,13 @@ function $48567ac5b39bac56$export$e2bf8ce7779e827e(props) {
6933
7445
  } = shared_properties;
6934
7446
  $5vyXB$solidjs.onCleanup(reset_history_state_);
6935
7447
  return $840d88a04b2d22a7$export$f7d2f673fc2f091d({
6936
- tenant_: () => depict_category.merchant,
7448
+ merchant_: () => depict_category.merchant,
6937
7449
  market_: () => depict_category.market,
6938
7450
  depict_api_: depict_api_,
6939
7451
  min_products_to_fetch_: $48567ac5b39bac56$var$min_products_to_fetch_,
6940
7452
  local_filter_cache_: local_filter_cache_,
6941
- query_id_: $5vyXB$solidjs.createMemo(() => !depict_category.disable_override_query_id && override_query_id_accessor_() || depict_category.category_id),
7453
+ listing_id_: $5vyXB$solidjs.createMemo(() => !depict_category.disable_override_listing_id && override_listing_id_accessor_() || depict_category.listing_id),
6942
7454
  meta_title_suffix_: () => depict_category.meta_title_suffix,
6943
- listing_type_: () => depict_category.listing_type,
6944
7455
  i18n_: i18n_,
6945
7456
  show_quicklinks_: $5vyXB$solidjs.createMemo(() => props.show_quicklinks ?? true),
6946
7457
  category_title_: category_title,
@@ -7006,7 +7517,7 @@ function $48567ac5b39bac56$export$de035477d6fef996({
7006
7517
  i18n_: i18n_,
7007
7518
  quicklinks_data_: quicklinks_data_,
7008
7519
  router_: router_,
7009
- current_query_id_: () => depict_category.category_id,
7520
+ current_listing_id_: () => depict_category.listing_id,
7010
7521
  breadcrumb_data_: breadcrumb_data_,
7011
7522
  sorting_query_param_: sorting_query_param_,
7012
7523
  filter_query_param_prefix_: filter_query_param_prefix_
@@ -7019,21 +7530,6 @@ function $48567ac5b39bac56$var$get_shared_properties(depict_category) {
7019
7530
  if (!shared_properties) throw new Error("Can't connect to provided DepictCategory instance");
7020
7531
  return shared_properties;
7021
7532
  }
7022
- const $0b23bfd073d9a4e8$var$_tmpl$ = ["<div", ' class="category-title"><h1 class="title">', '</h1><span class="explanation"> — <!--$-->', "<!--/--></span></div>"];
7023
- const $0b23bfd073d9a4e8$export$b91cec6bdc6b32a1 = /*@__PURE__*/(() => {
7024
- const actual_function = ({
7025
- category_title_: category_title_,
7026
- product_count_: product_count_
7027
- }) => {
7028
- 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), {
7029
- height: "1em",
7030
- width: "10ch"
7031
- })), $5vyXB$solidjsweb.escape(product_count_));
7032
- };
7033
- // This is wrong but parcel can't build correctly, it says unexpected undefined
7034
- actual_function[(0, $6b502b1b2155a0bc$export$5c28802497c8a83c)] = "simple";
7035
- return actual_function;
7036
- })();
7037
7533
  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>"];
7038
7534
  const $85b747260aa175c9$export$824dde41348efed1 = /*@__PURE__*/(() => {
7039
7535
  const actual_function = ({
@@ -7118,11 +7614,11 @@ const $85b747260aa175c9$export$824dde41348efed1 = /*@__PURE__*/(() => {
7118
7614
  actual_function[(0, $6b502b1b2155a0bc$export$5c28802497c8a83c)] = "interactive";
7119
7615
  return actual_function;
7120
7616
  })();
7121
- const $63b10c9f461e0ef6$var$TEN_MINUTES = 600000;
7122
- const $63b10c9f461e0ef6$var$TWENTY_FOUR_HOURS = 86400000;
7123
- async function $63b10c9f461e0ef6$export$643598a327b5833e(tenant, market, type) {
7617
+ const $6382a1b83da39674$var$TEN_MINUTES = 600000;
7618
+ const $6382a1b83da39674$var$TWENTY_FOUR_HOURS = 86400000;
7619
+ async function $6382a1b83da39674$export$c1a6b039e689a58e(merchant, market, locale) {
7124
7620
  let localstorage_value;
7125
- const localstorage_key = `depict_${tenant}_${type ?? "categories"}_` + market;
7621
+ const localstorage_key = `depict_listings_${JSON.stringify([merchant, market, locale])}}`;
7126
7622
  try {
7127
7623
  const in_ls = localStorage[localstorage_key];
7128
7624
  if (in_ls) localstorage_value = JSON.parse(in_ls);
@@ -7134,20 +7630,20 @@ async function $63b10c9f461e0ef6$export$643598a327b5833e(tenant, market, type) {
7134
7630
  const stored_queries = localstorage_value?.queries;
7135
7631
  if (Array.isArray(stored_queries) && typeof updated === "number") {
7136
7632
  const age = now - updated;
7137
- if (stored_queries.length && age < $63b10c9f461e0ef6$var$TEN_MINUTES)
7633
+ if (stored_queries.length && age < $6382a1b83da39674$var$TEN_MINUTES)
7138
7634
  // if younger than 10 minutes and probably valid data, just return stored value
7139
- return stored_queries;else if (age < $63b10c9f461e0ef6$var$TWENTY_FOUR_HOURS) {
7635
+ return stored_queries;else if (age < $6382a1b83da39674$var$TWENTY_FOUR_HOURS) {
7140
7636
  // 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)
7141
- $63b10c9f461e0ef6$var$fetch_and_store_categories(tenant, market, localstorage_key, type).catch(e => $5vyXB$depictaiutilishared.report([e, "couldn't fetch categories"], "warning"));
7637
+ $6382a1b83da39674$var$fetch_and_store_categories(merchant, market, locale, localstorage_key).catch(e => $5vyXB$depictaiutilishared.report([e, "couldn't fetch categories"], "warning"));
7142
7638
  return stored_queries;
7143
7639
  }
7144
7640
  // else: we are older and just fetch, store and return new queries
7145
7641
  }
7146
7642
 
7147
- return await $63b10c9f461e0ef6$var$fetch_and_store_categories(tenant, market, localstorage_key, type);
7643
+ return await $6382a1b83da39674$var$fetch_and_store_categories(merchant, market, locale, localstorage_key);
7148
7644
  }
7149
- async function $63b10c9f461e0ef6$var$fetch_and_store_categories(tenant, market, localstorage_key, type) {
7150
- const new_categories = await $63b10c9f461e0ef6$var$download_categories(tenant, market, type);
7645
+ async function $6382a1b83da39674$var$fetch_and_store_categories(merchant, market, locale, localstorage_key) {
7646
+ const new_categories = await $6382a1b83da39674$var$download_categories(merchant, market, locale);
7151
7647
  try {
7152
7648
  localStorage[localstorage_key] = JSON.stringify({
7153
7649
  updated: +new Date(),
@@ -7159,24 +7655,22 @@ async function $63b10c9f461e0ef6$var$fetch_and_store_categories(tenant, market,
7159
7655
 
7160
7656
  return new_categories;
7161
7657
  }
7162
- async function $63b10c9f461e0ef6$var$download_categories(tenant, market, type) {
7163
- const fetched = await $5vyXB$depictaiutilishared.fetch_retry((0, $5vyXB$depictaiutilishared.base_url) + "/v2/product-listing/queries", {
7164
- method: "POST",
7165
- body: JSON.stringify({
7166
- tenant: tenant,
7167
- market: market,
7168
- ...(type ? {
7169
- type: type
7170
- } : {})
7171
- })
7172
- });
7658
+ async function $6382a1b83da39674$var$download_categories(merchant, market, locale) {
7659
+ const url = new URL((0, $5vyXB$depictaiutilishared.base_url) + "/v3/listings");
7660
+ const request = {
7661
+ merchant: merchant,
7662
+ market: market,
7663
+ locale: locale
7664
+ };
7665
+ url.search = "" + new URLSearchParams(request);
7666
+ const fetched = await $5vyXB$depictaiutilishared.fetch_retry(url.href);
7173
7667
  if (!fetched) return [];
7174
7668
  try {
7175
7669
  if (fetched.status !== 200) {
7176
7670
  $5vyXB$depictaiutilishared.dlog("failed to fetch queries, server responded with", fetched.status, fetched, await fetched.text());
7177
7671
  return [];
7178
7672
  }
7179
- return (await fetched.json())?.query_ids;
7673
+ return await fetched.json();
7180
7674
  } catch (e) {
7181
7675
  $5vyXB$depictaiutilishared.dlog("failed to decode queries json", fetched, e);
7182
7676
  return [];
@@ -7287,8 +7781,6 @@ function $fb29c6201c369e39$export$7de92c4c2205ebf3({
7287
7781
  }));
7288
7782
  return $a73063cc642f3e5f$export$43f0fb951fcb0c54({
7289
7783
  displays_by_key_: displays_by_key_,
7290
- merchant_: $5vyXB$solidjs.createMemo(() => search_query_base_().tenant),
7291
- market_: $5vyXB$solidjs.createMemo(() => search_query_base_().market),
7292
7784
  product_card_template_: product_card_template_
7293
7785
  });
7294
7786
  })();
@@ -7533,7 +8025,7 @@ const $6ae556e536054e87$var$_tmpl$ = ["<div", ' class="instant-results">', "</di
7533
8025
  function $6ae556e536054e87$export$62f101a8aa597bf8({
7534
8026
  depict_api_: depict_api_,
7535
8027
  search_field_value_: [get_search_field_value],
7536
- tenant_: tenant_,
8028
+ merchant_: merchant_,
7537
8029
  market_: market_,
7538
8030
  render_instant_card_: render_instant_card_,
7539
8031
  render_instant_card_placeholder_: render_instant_card_placeholder_,
@@ -7557,8 +8049,10 @@ function $6ae556e536054e87$export$62f101a8aa597bf8({
7557
8049
  timeout = setTimeout($5vyXB$depictaiutilishared.catchify(() => write_current_instant_query(value)), 250);
7558
8050
  });
7559
8051
  const [search_results] = $5vyXB$solidjs.createResource($5vyXB$solidjs.createMemo(() => ({
7560
- tenant: tenant_(),
8052
+ // <-- key order important, see comment below
8053
+ merchant: merchant_(),
7561
8054
  market: market_(),
8055
+ locale: i18n_.backend_locale_(),
7562
8056
  query: read_current_instant_query()
7563
8057
  })), $5vyXB$depictaiutilishared.catchify(variable_data => {
7564
8058
  return depict_api_.query({
@@ -7604,12 +8098,12 @@ function $6ae556e536054e87$export$62f101a8aa597bf8({
7604
8098
  const card = render_instant_card_ ? $5vyXB$solidjs.createMemo(() => render_instant_card_(d(), {
7605
8099
  index: i,
7606
8100
  i18n: $639c124c22b6cbaa$export$27b710c08412a7ad(i18n_),
7607
- merchant: tenant_(),
8101
+ merchant: merchant_(),
7608
8102
  market: market_()
7609
8103
  })) : $6ae613870d3380fc$export$b05c0ae390cf3e06(d, {
7610
8104
  index: i,
7611
8105
  i18n: i18n_,
7612
- merchant: tenant_(),
8106
+ merchant: merchant_(),
7613
8107
  market: market_()
7614
8108
  }, router_);
7615
8109
  return card;
@@ -8062,7 +8556,7 @@ function $3ec9e21d6b6debdd$export$2f2b9559550c7bbc({
8062
8556
  previous_searches_: [unfiltered_previous_searches, set_unfiltered_previous_searches_],
8063
8557
  previous_searches_text_: previous_searches_text_,
8064
8558
  depict_api_: depict_api_,
8065
- tenant_: tenant_,
8559
+ merchant_: merchant_,
8066
8560
  market_: market_,
8067
8561
  input_field_: input_field_,
8068
8562
  url_transformer_: url_transformer_,
@@ -8135,9 +8629,10 @@ function $3ec9e21d6b6debdd$export$2f2b9559550c7bbc({
8135
8629
  set_show_stale_content_results(true);else {
8136
8630
  set_searching_for_value(field_value);
8137
8631
  deparallelized_fn({
8138
- query: field_value,
8139
- tenant: tenant_(),
8140
- market: market_()
8632
+ merchant: merchant_(),
8633
+ market: market_(),
8634
+ locale: i18n_.backend_locale_(),
8635
+ query: field_value
8141
8636
  });
8142
8637
  set_show_stale_content_results(false);
8143
8638
  }
@@ -8269,7 +8764,7 @@ function $f40a47a30a358305$export$1c593cbd6f1e10bc({
8269
8764
  close_modal_: close_modal_,
8270
8765
  style_props_ = $5vyXB$solidjs.createSignal({}),
8271
8766
  depict_api_: depict_api_,
8272
- tenant_: tenant_,
8767
+ merchant_: merchant_,
8273
8768
  market_: market_,
8274
8769
  submit_query_: props_submit_query,
8275
8770
  instant_results_options_: instant_results_options_,
@@ -8369,7 +8864,7 @@ function $f40a47a30a358305$export$1c593cbd6f1e10bc({
8369
8864
  previous_searches_: previous_searches_,
8370
8865
  search_query_url_param_name_: search_query_url_param_name_,
8371
8866
  market_: market_,
8372
- tenant_: tenant_,
8867
+ merchant_: merchant_,
8373
8868
  selected_index_: selected_index,
8374
8869
  currently_showing_suggestions_: currently_showing_suggestions_,
8375
8870
  depict_api_: depict_api_,
@@ -8391,7 +8886,7 @@ function $f40a47a30a358305$export$1c593cbd6f1e10bc({
8391
8886
  return $6ae556e536054e87$export$62f101a8aa597bf8({
8392
8887
  search_field_value_: search_field_value_,
8393
8888
  depict_api_: depict_api_,
8394
- tenant_: tenant_,
8889
+ merchant_: merchant_,
8395
8890
  i18n_: i18n_,
8396
8891
  market_: market_,
8397
8892
  set_total_num_results_accessor_: set_total_num_results_accessor_,
@@ -8780,6 +9275,9 @@ function $f1d7cb69f839a526$export$a54ec244c8863715({
8780
9275
  const first_result_in_viewport_ = $5vyXB$solidjs.createSignal();
8781
9276
  const last_result_in_viewport_ = $5vyXB$solidjs.createSignal();
8782
9277
  const [can_write_scroll_restoration_, set_can_write_scroll_restoration] = $5vyXB$solidjs.createSignal(false);
9278
+ const {
9279
+ backend_locale_: backend_locale_
9280
+ } = i18n_;
8783
9281
  const search_query_base_ = $8cd545330f2674dc$export$210f130a61ac1e8d(() => {
8784
9282
  const sort_obj = get_sorting() && {
8785
9283
  ...get_sorting()
@@ -8787,8 +9285,9 @@ function $f1d7cb69f839a526$export$a54ec244c8863715({
8787
9285
  delete sort_obj?.meta;
8788
9286
  const f = selected_filters_[0]();
8789
9287
  return {
8790
- tenant: tenant_(),
9288
+ merchant: tenant_(),
8791
9289
  market: market_(),
9290
+ locale: backend_locale_(),
8792
9291
  query: get_search_query_(),
8793
9292
  ...(f.length ? {
8794
9293
  filters: f
@@ -8814,11 +9313,12 @@ function $f1d7cb69f839a526$export$a54ec244c8863715({
8814
9313
  })
8815
9314
  });
8816
9315
  }));
8817
- const [suggestions] = $5vyXB$solidjs.createResource($5vyXB$solidjs.createMemo(() => ({
9316
+ const [suggestions] = $5vyXB$solidjs.createResource(() => ({
8818
9317
  query: get_search_query_(),
8819
- tenant: tenant_(),
8820
- market: market_()
8821
- })), opts => depict_api_.suggest(opts));
9318
+ merchant: tenant_(),
9319
+ market: market_(),
9320
+ locale: backend_locale_()
9321
+ }), opts => depict_api_.suggest(opts));
8822
9322
  const available_sortings_ = $5vyXB$solidjs.createMemo(() => search_results_()?.sorts?.map(sort => ({
8823
9323
  ...sort,
8824
9324
  order: sort.order ?? "desc"
@@ -9262,7 +9762,7 @@ class $2c61e4cd8229c49a$export$ac6237957a15b3f0 {
9262
9762
  search_query_url_param_name_: search_query_url_param_name_,
9263
9763
  previous_searches_: previous_searches,
9264
9764
  depict_api_: depict_api_,
9265
- tenant_: this.#merchant_signal[0],
9765
+ merchant_: this.#merchant_signal[0],
9266
9766
  clear_filters_: clear_filters_on_next_submit_,
9267
9767
  market_: this.#market_signal[0],
9268
9768
  submit_query_: configured_submit_query_,
@@ -9376,11 +9876,12 @@ class $2c61e4cd8229c49a$export$ac6237957a15b3f0 {
9376
9876
  depict_api_: depict_api_
9377
9877
  } = $2c61e4cd8229c49a$var$privately_shared_properties.get(this);
9378
9878
  const result = await depict_api_.query({
9379
- tenant: this.merchant,
9879
+ merchant: this.merchant,
9380
9880
  market: this.market,
9381
9881
  query: query,
9382
9882
  filters: filters,
9383
- limit: maxResults
9883
+ limit: maxResults,
9884
+ locale: this.localization.backend_locale_
9384
9885
  });
9385
9886
  if (result.failed) throw new Error("Failed to fetch search results");
9386
9887
  return result.displays;
@@ -9816,7 +10317,4 @@ function $0a6acf31d1eae57c$var$clean_url(url) {
9816
10317
  url_object.hash = "";
9817
10318
  return url_object.href;
9818
10319
  }
9819
- const $a3280f0aad997933$export$c3834fa86c616831 = [[4], [3, 1024], [2, 901]];
9820
- const $a3280f0aad997933$export$864d304a0bc46829 = "2%";
9821
- const $a3280f0aad997933$export$7bf543b9d9be2c22 = (0, $0b23bfd073d9a4e8$export$b91cec6bdc6b32a1);
9822
10320
  $5vyXB$depictaiutilishared.add_to_version_info("ui", (0, $b757f75811f3261f$export$83d89fbfd8236492));