@depict-ai/ui 1.3.7 → 1.4.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.
- package/README.md +2 -1
- package/dist/client/main.cjs +3497 -3484
- package/dist/client/module.js +3496 -3488
- package/dist/index.d.ts +208 -144
- package/dist/server/main.cjs +2953 -2940
- package/dist/server/module.js +2952 -2944
- package/locales/index.d.ts +1 -0
- package/locales/index.js +13 -0
- package/locales/require.cjs +13 -0
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,219 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { JSX, Signal, Accessor, Setter } from "solid-js";
|
|
2
|
+
import { Elem, Display, ColsAtSize, ModernDisplay, Node_Array } from "@depict-ai/utilishared";
|
|
3
|
+
import { SearchFilter, SearchRequest } from "@depict-ai/types/api/SearchRequest";
|
|
4
|
+
import { SearchFilter as _SearchFilter1, SearchResponse } from "@depict-ai/types/api/SearchResponse";
|
|
3
5
|
import { BaseCategoryDisplay, ProductListingResponse } from "@depict-ai/types/api/ProductListingResponse";
|
|
4
6
|
import { CategorySuggestion, SearchSuggestionsResponse } from "@depict-ai/types/api/SearchSuggestionsResponse";
|
|
5
|
-
import { SearchResponse } from "@depict-ai/types/api/SearchResponse";
|
|
6
|
-
import { SearchRequest, SearchFilter } from "@depict-ai/types/api/SearchRequest";
|
|
7
7
|
import { BaseSearchRequest } from "@depict-ai/types/api/BaseSearchRequest";
|
|
8
8
|
import { SearchSuggestionsRequest } from "@depict-ai/types/api/SearchSuggestionsRequest";
|
|
9
9
|
import { ProductListingRequest } from "@depict-ai/types/api/ProductListingRequest";
|
|
10
|
-
export const version = "1.
|
|
10
|
+
export const version = "1.4.1";
|
|
11
|
+
export function ExpandingDetails(props: {
|
|
12
|
+
details_: HTMLDetailsElement;
|
|
13
|
+
summary_: HTMLElement;
|
|
14
|
+
children: JSX.Element | (() => JSX.Element);
|
|
15
|
+
is_open_: Signal<boolean>;
|
|
16
|
+
duration_?: number;
|
|
17
|
+
delay_?: number;
|
|
18
|
+
dont_animate_if_instant_open_?: boolean;
|
|
19
|
+
}): HTMLDetailsElement;
|
|
20
|
+
export function accessor_of_object_to_object_with_accessor_values<O extends Record<string | symbol, any>>(obj: Accessor<O>): { [K in keyof O]: Accessor<O[K]>; };
|
|
21
|
+
/**
|
|
22
|
+
* Like standard_price_format except that the price and the formatting are reactive accessors
|
|
23
|
+
*/
|
|
24
|
+
export function SolidFormatPrice(props: {
|
|
25
|
+
price_: number;
|
|
26
|
+
price_formatting_: {
|
|
27
|
+
pre_: string;
|
|
28
|
+
post_: string;
|
|
29
|
+
decimal_places_delimiter_: string;
|
|
30
|
+
thousands_delimiter_: string;
|
|
31
|
+
places_after_comma_: number | "auto";
|
|
32
|
+
};
|
|
33
|
+
}): JSX.Element;
|
|
34
|
+
/**
|
|
35
|
+
* PLP internationalisation shared between search and category listing
|
|
36
|
+
*/
|
|
37
|
+
type plp_shared_i18n = {
|
|
38
|
+
scroll_to_top_: string;
|
|
39
|
+
back_: string;
|
|
40
|
+
open_sorting_: string;
|
|
41
|
+
close_sorting_: string;
|
|
42
|
+
open_filters_: string;
|
|
43
|
+
close_filters_: string;
|
|
44
|
+
close_: string;
|
|
45
|
+
ok_: string;
|
|
46
|
+
filters_cleared_: string;
|
|
47
|
+
we_cleared_your_filters_: string;
|
|
48
|
+
restore_: string;
|
|
49
|
+
sorting_text_: string;
|
|
50
|
+
filter_text_: string;
|
|
51
|
+
selected_filters_title_: string;
|
|
52
|
+
filters_: string;
|
|
53
|
+
view_less_: string;
|
|
54
|
+
view_more_: string;
|
|
55
|
+
clear_all_from_filter_crumbs_: string;
|
|
56
|
+
clear_individual_filter_: string;
|
|
57
|
+
of_: string;
|
|
58
|
+
clear_all_filters_from_big_button_: string;
|
|
59
|
+
try_without_filters_: string;
|
|
60
|
+
range_filter_low_point_aria_label_: string;
|
|
61
|
+
range_filter_high_point_aria_label_: string;
|
|
62
|
+
morphing_sign_expanded_aria_label_: string;
|
|
63
|
+
morphing_sign_collapsed_aria_label_: string;
|
|
64
|
+
price_formatting_: {
|
|
65
|
+
pre_: string;
|
|
66
|
+
post_: string;
|
|
67
|
+
decimal_places_delimiter_: string;
|
|
68
|
+
thousands_delimiter_: string;
|
|
69
|
+
places_after_comma_: number | "auto";
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Search internationalisation
|
|
74
|
+
*/
|
|
75
|
+
interface search_i18n extends plp_shared_i18n {
|
|
76
|
+
placeholder_text_: string;
|
|
77
|
+
show_n_results_: (number_of_results: HTMLElement) => Elem[];
|
|
78
|
+
no_results_text_: string;
|
|
79
|
+
search_recs_title_: string;
|
|
80
|
+
clear_filters_query_sorting_after_submit_: string;
|
|
81
|
+
modal_view_all_results_: (number_of_results: HTMLElement) => Elem[];
|
|
82
|
+
modal_discover_more_: string;
|
|
83
|
+
get_showing_results_for_: (query: HTMLElement, number_of_results: HTMLElement) => Elem[];
|
|
84
|
+
previous_searches_text_: string;
|
|
85
|
+
category_: string;
|
|
86
|
+
brand_: string;
|
|
87
|
+
suggestions_: string;
|
|
88
|
+
search_submit_button_aria_label_: string;
|
|
89
|
+
search_field_field_aria_label_: string;
|
|
90
|
+
previous_searches_delete_entry_from_history_: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Category internationalisation
|
|
94
|
+
*/
|
|
95
|
+
interface category_i18n extends plp_shared_i18n {
|
|
96
|
+
show_n_products_: (number_of_results: HTMLElement) => Elem[];
|
|
97
|
+
no_products_text_: string;
|
|
98
|
+
product_: string;
|
|
99
|
+
products_: string;
|
|
100
|
+
breadcrumbs_aria_label_: string;
|
|
101
|
+
quicklinks_aria_label_: string;
|
|
102
|
+
breadcrumbs_separator_: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* For anything that is not exposed and only used internally we can use solid signals to get more performant rendering.
|
|
106
|
+
* For anything that can be used outside of solid, like Product Cards and InstantCards these types should not be used.
|
|
107
|
+
*
|
|
108
|
+
* Any solid_ type below should not be exposed outside of this library, as the accessors can be confusing and unnecessary.
|
|
109
|
+
*/
|
|
110
|
+
/** For internal components using i18n that gets wrapped in solid's Accessors */
|
|
111
|
+
type solid_plp_shared_i18n = {
|
|
112
|
+
[K in keyof plp_shared_i18n]: Accessor<plp_shared_i18n[K]>;
|
|
113
|
+
};
|
|
114
|
+
/** @jsxImportSource solid-js */
|
|
115
|
+
export function GenericSliderArrowButton(props?: {
|
|
116
|
+
width_?: number;
|
|
117
|
+
height_?: number;
|
|
118
|
+
}): SVGElement;
|
|
119
|
+
export function show_toast({ children, on_close_, close_after_, ...more_attributes }: {
|
|
120
|
+
children?: JSX.Element;
|
|
121
|
+
close_after_: number;
|
|
122
|
+
on_close_?: VoidFunction;
|
|
123
|
+
} & JSX.HTMLAttributes<HTMLDivElement>): {
|
|
124
|
+
close_toast_: VoidFunction;
|
|
125
|
+
};
|
|
126
|
+
export type SDKGridSpacing = string | {
|
|
127
|
+
horizontal: string;
|
|
128
|
+
vertical: string;
|
|
129
|
+
};
|
|
130
|
+
export type WithRequired<T, K extends keyof T> = T & {
|
|
131
|
+
[P in K]-?: T[P];
|
|
132
|
+
};
|
|
133
|
+
type FilterWithData = WithRequired<SearchFilter, "data">;
|
|
134
|
+
export interface SDKRenderingInfo {
|
|
135
|
+
set_on_index_change: (fn: (index: number) => void) => void;
|
|
136
|
+
merchant: string;
|
|
137
|
+
market: string;
|
|
138
|
+
}
|
|
139
|
+
export type ProductCardTemplate<T extends Display> = (display: T | null, info?: SDKRenderingInfo) => JSX.Element | Promise<JSX.Element>;
|
|
140
|
+
/**
|
|
141
|
+
* Will be sent to backend to indicate whether the query_id_ is for a collection or category.
|
|
142
|
+
* Backend defaults to category if not specified.
|
|
143
|
+
*/
|
|
144
|
+
export type ListingType = "collection" | "category";
|
|
145
|
+
export function CrossIcon(props?: JSX.SvgSVGAttributes<SVGSVGElement>): SVGElement;
|
|
146
|
+
export function SelectedFilters({ number_of_rendered_selected_filters_items_, i18n_, selected_filters_, local_filter_cache_: [read_local_filter_cache], get_search_filters_open_, get_search_sorting_open_, local_filter_cache_, expanded_hierarchical_filters_, }: {
|
|
147
|
+
get_search_filters_open_: Accessor<boolean>;
|
|
148
|
+
get_search_sorting_open_: Accessor<boolean>;
|
|
149
|
+
expanded_hierarchical_filters_: Signal<{
|
|
150
|
+
value_: string[];
|
|
151
|
+
expanded_: boolean;
|
|
152
|
+
}[]>;
|
|
153
|
+
number_of_rendered_selected_filters_items_: Signal<number>;
|
|
154
|
+
i18n_: solid_plp_shared_i18n;
|
|
155
|
+
selected_filters_: Signal<FilterWithData[]>;
|
|
156
|
+
local_filter_cache_: Signal<SearchFilter[]>;
|
|
157
|
+
}): HTMLDivElement;
|
|
158
|
+
/**
|
|
159
|
+
* Use `javascript_media_query` but return a reactive accessor instead of taking a callback function
|
|
160
|
+
*/
|
|
161
|
+
export function media_query_to_accessor(media_query: string): import("solid-js").Accessor<boolean>;
|
|
11
162
|
declare class SDKError extends Error {
|
|
12
163
|
}
|
|
13
164
|
export class ProductCardError extends SDKError {
|
|
14
165
|
constructor(templateError: Error);
|
|
15
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Base placeholder component used by ImagePlaceholder and TextPlaceholder
|
|
169
|
+
*/
|
|
170
|
+
export function BasePlaceholder(props: {
|
|
171
|
+
style: JSX.CSSProperties;
|
|
172
|
+
class?: string;
|
|
173
|
+
}): JSX.Element;
|
|
174
|
+
/**
|
|
175
|
+
* A Placeholder to use instead of some text, while it's loading. This is the inline version, meant to be embedded into sentences (or exist instead of them), etc.
|
|
176
|
+
* If you want a block version, use `ImagePlaceholder` with `width`and `height` set instead.
|
|
177
|
+
* @property height height of the placeholder. Set to `1em` by default.
|
|
178
|
+
* @property width width of the placeholder. For specific number of characters use `ch`, ex: `width="7ch"`
|
|
179
|
+
* @property class extra classes to add to the placeholder
|
|
180
|
+
* @property style extra styles to add to the placeholder
|
|
181
|
+
*/
|
|
182
|
+
export function TextPlaceholder(props: {
|
|
183
|
+
style?: JSX.CSSProperties;
|
|
184
|
+
height: string;
|
|
185
|
+
width: string;
|
|
186
|
+
class?: string;
|
|
187
|
+
}): JSX.Element;
|
|
188
|
+
interface FilterBodyProps {
|
|
189
|
+
available_filters_: Accessor<_SearchFilter1[] | undefined>;
|
|
190
|
+
expanded_filters_: Signal<{
|
|
191
|
+
section_: string;
|
|
192
|
+
expanded_: boolean;
|
|
193
|
+
}[]>;
|
|
194
|
+
selected_filters_: Signal<{
|
|
195
|
+
field: string;
|
|
196
|
+
op: _SearchFilter1["op"];
|
|
197
|
+
data: any;
|
|
198
|
+
}[]>;
|
|
199
|
+
local_filter_cache_: Signal<_SearchFilter1[]>;
|
|
200
|
+
i18n_: solid_plp_shared_i18n;
|
|
201
|
+
expanded_hierarchical_filters_: Signal<{
|
|
202
|
+
value_: string[];
|
|
203
|
+
expanded_: boolean;
|
|
204
|
+
}[]>;
|
|
205
|
+
are_in_modal_?: boolean;
|
|
206
|
+
}
|
|
207
|
+
export function FilterBody(props: FilterBodyProps): JSX.Element;
|
|
208
|
+
export function create_modified_filters({ available_filters_, local_filter_cache_: [read_local_cache, write_local_cache], selected_filters_: [read_selected_filters], }: {
|
|
209
|
+
available_filters_: Accessor<_SearchFilter1[] | undefined>;
|
|
210
|
+
selected_filters_: Signal<{
|
|
211
|
+
field: string;
|
|
212
|
+
op: _SearchFilter1["op"];
|
|
213
|
+
data: any;
|
|
214
|
+
}[]>;
|
|
215
|
+
local_filter_cache_: Signal<_SearchFilter1[]>;
|
|
216
|
+
}): void;
|
|
16
217
|
export type SolidLayoutOptions = {
|
|
17
218
|
cols_at_size: ColsAtSize;
|
|
18
219
|
grid_spacing: string;
|
|
@@ -95,12 +296,6 @@ export function general_modal_abstraction<StaticOptions extends {
|
|
|
95
296
|
open_modal_: (extra_options_for_modal?: ExtraOptionsProvidedOnOpen, on_dispose?: VoidFunction) => void;
|
|
96
297
|
close_modal_: () => void;
|
|
97
298
|
}>;
|
|
98
|
-
export function CrossIcon(props?: JSX.SvgSVGAttributes<SVGSVGElement>): SVGElement;
|
|
99
|
-
/** @jsxImportSource solid-js */
|
|
100
|
-
export function GenericSliderArrowButton(props?: {
|
|
101
|
-
width_?: number;
|
|
102
|
-
height_?: number;
|
|
103
|
-
}): SVGElement;
|
|
104
299
|
export type OnNavigation = ((options: {
|
|
105
300
|
is_replace: boolean;
|
|
106
301
|
new_url: URL;
|
|
@@ -168,88 +363,6 @@ type RecsAPIWrapperOptions = {
|
|
|
168
363
|
* @return This function is guaranteed to return an array of Displays. If anything fails, you will get an empty array.
|
|
169
364
|
*/
|
|
170
365
|
export function fetchDepictRecommendations<T extends Display = Display>({ merchant, market, headers, ...fetch_recs_options }: RecsAPIWrapperOptions): Promise<T[]>;
|
|
171
|
-
/**
|
|
172
|
-
* Like standard_price_format except that the price and the formatting are reactive accessors
|
|
173
|
-
*/
|
|
174
|
-
export function SolidFormatPrice(props: {
|
|
175
|
-
price_: number;
|
|
176
|
-
price_formatting_: {
|
|
177
|
-
pre_: string;
|
|
178
|
-
post_: string;
|
|
179
|
-
decimal_places_delimiter_: string;
|
|
180
|
-
thousands_delimiter_: string;
|
|
181
|
-
places_after_comma_: number | "auto";
|
|
182
|
-
};
|
|
183
|
-
}): JSX.Element;
|
|
184
|
-
/**
|
|
185
|
-
* PLP internationalisation shared between search and category listing
|
|
186
|
-
*/
|
|
187
|
-
type plp_shared_i18n = {
|
|
188
|
-
scroll_to_top_: string;
|
|
189
|
-
back_: string;
|
|
190
|
-
open_sorting_: string;
|
|
191
|
-
close_sorting_: string;
|
|
192
|
-
open_filters_: string;
|
|
193
|
-
close_filters_: string;
|
|
194
|
-
close_: string;
|
|
195
|
-
ok_: string;
|
|
196
|
-
filters_cleared_: string;
|
|
197
|
-
we_cleared_your_filters_: string;
|
|
198
|
-
restore_: string;
|
|
199
|
-
sorting_text_: string;
|
|
200
|
-
filter_text_: string;
|
|
201
|
-
selected_filters_title_: string;
|
|
202
|
-
filters_: string;
|
|
203
|
-
view_less_: string;
|
|
204
|
-
view_more_: string;
|
|
205
|
-
clear_all_from_filter_crumbs_: string;
|
|
206
|
-
clear_individual_filter_: string;
|
|
207
|
-
of_: string;
|
|
208
|
-
clear_all_filters_from_big_button_: string;
|
|
209
|
-
try_without_filters_: string;
|
|
210
|
-
range_filter_low_point_aria_label_: string;
|
|
211
|
-
range_filter_high_point_aria_label_: string;
|
|
212
|
-
morphing_sign_expanded_aria_label_: string;
|
|
213
|
-
morphing_sign_collapsed_aria_label_: string;
|
|
214
|
-
price_formatting_: {
|
|
215
|
-
pre_: string;
|
|
216
|
-
post_: string;
|
|
217
|
-
decimal_places_delimiter_: string;
|
|
218
|
-
thousands_delimiter_: string;
|
|
219
|
-
places_after_comma_: number | "auto";
|
|
220
|
-
};
|
|
221
|
-
};
|
|
222
|
-
/**
|
|
223
|
-
* Search internationalisation
|
|
224
|
-
*/
|
|
225
|
-
interface search_i18n extends plp_shared_i18n {
|
|
226
|
-
placeholder_text_: string;
|
|
227
|
-
show_n_results_: (number_of_results: HTMLElement) => Elem[];
|
|
228
|
-
no_results_text_: string;
|
|
229
|
-
search_recs_title_: string;
|
|
230
|
-
clear_filters_query_sorting_after_submit_: string;
|
|
231
|
-
modal_view_all_results_: (number_of_results: HTMLElement) => Elem[];
|
|
232
|
-
modal_discover_more_: string;
|
|
233
|
-
get_showing_results_for_: (query: HTMLElement, number_of_results: HTMLElement) => Elem[];
|
|
234
|
-
previous_searches_text_: string;
|
|
235
|
-
category_: string;
|
|
236
|
-
suggestions_: string;
|
|
237
|
-
search_submit_button_aria_label_: string;
|
|
238
|
-
search_field_field_aria_label_: string;
|
|
239
|
-
previous_searches_delete_entry_from_history_: string;
|
|
240
|
-
}
|
|
241
|
-
/**
|
|
242
|
-
* Category internationalisation
|
|
243
|
-
*/
|
|
244
|
-
interface category_i18n extends plp_shared_i18n {
|
|
245
|
-
show_n_products_: (number_of_results: HTMLElement) => Elem[];
|
|
246
|
-
no_products_text_: string;
|
|
247
|
-
product_: string;
|
|
248
|
-
products_: string;
|
|
249
|
-
breadcrumbs_aria_label_: string;
|
|
250
|
-
quicklinks_aria_label_: string;
|
|
251
|
-
breadcrumbs_separator_: string;
|
|
252
|
-
}
|
|
253
366
|
export type InstantCard<T extends Display> = (display: T, context: {
|
|
254
367
|
index: number;
|
|
255
368
|
i18n: search_i18n;
|
|
@@ -309,56 +422,6 @@ export class DepictAPI<InputDisplay extends Display, OutputDisplay extends Moder
|
|
|
309
422
|
failed?: true | undefined;
|
|
310
423
|
}>;
|
|
311
424
|
}
|
|
312
|
-
/**
|
|
313
|
-
* Use `javascript_media_query` but return a reactive accessor instead of taking a callback function
|
|
314
|
-
*/
|
|
315
|
-
export function media_query_to_accessor(media_query: string): import("solid-js").Accessor<boolean>;
|
|
316
|
-
export type SDKGridSpacing = string | {
|
|
317
|
-
horizontal: string;
|
|
318
|
-
vertical: string;
|
|
319
|
-
};
|
|
320
|
-
export type WithRequired<T, K extends keyof T> = T & {
|
|
321
|
-
[P in K]-?: T[P];
|
|
322
|
-
};
|
|
323
|
-
export interface SDKRenderingInfo {
|
|
324
|
-
set_on_index_change: (fn: (index: number) => void) => void;
|
|
325
|
-
merchant: string;
|
|
326
|
-
market: string;
|
|
327
|
-
}
|
|
328
|
-
export type ProductCardTemplate<T extends Display> = (display: T | null, info?: SDKRenderingInfo) => JSX.Element | Promise<JSX.Element>;
|
|
329
|
-
/**
|
|
330
|
-
* Will be sent to backend to indicate whether the query_id_ is for a collection or category.
|
|
331
|
-
* Backend defaults to category if not specified.
|
|
332
|
-
*/
|
|
333
|
-
export type ListingType = "collection" | "category";
|
|
334
|
-
export function show_toast({ children, on_close_, close_after_, ...more_attributes }: {
|
|
335
|
-
children?: JSX.Element;
|
|
336
|
-
close_after_: number;
|
|
337
|
-
on_close_?: VoidFunction;
|
|
338
|
-
} & JSX.HTMLAttributes<HTMLDivElement>): {
|
|
339
|
-
close_toast_: VoidFunction;
|
|
340
|
-
};
|
|
341
|
-
/**
|
|
342
|
-
* Base placeholder component used by ImagePlaceholder and TextPlaceholder
|
|
343
|
-
*/
|
|
344
|
-
export function BasePlaceholder(props: {
|
|
345
|
-
style: JSX.CSSProperties;
|
|
346
|
-
class?: string;
|
|
347
|
-
}): JSX.Element;
|
|
348
|
-
/**
|
|
349
|
-
* A Placeholder to use instead of some text, while it's loading. This is the inline version, meant to be embedded into sentences (or exist instead of them), etc.
|
|
350
|
-
* If you want a block version, use `ImagePlaceholder` with `width`and `height` set instead.
|
|
351
|
-
* @property height height of the placeholder. Set to `1em` by default.
|
|
352
|
-
* @property width width of the placeholder. For specific number of characters use `ch`, ex: `width="7ch"`
|
|
353
|
-
* @property class extra classes to add to the placeholder
|
|
354
|
-
* @property style extra styles to add to the placeholder
|
|
355
|
-
*/
|
|
356
|
-
export function TextPlaceholder(props: {
|
|
357
|
-
style?: JSX.CSSProperties;
|
|
358
|
-
height: string;
|
|
359
|
-
width: string;
|
|
360
|
-
class?: string;
|
|
361
|
-
}): JSX.Element;
|
|
362
425
|
/**
|
|
363
426
|
* Disables scrolling until the solidjs reactive scoped is disposed (onCleanup)
|
|
364
427
|
* @returns A cleanup function to manually re-enable scrolling.
|
|
@@ -600,8 +663,9 @@ export type BaseProviderConfig<InputDisplay extends Display, PossibleTransformed
|
|
|
600
663
|
metaData?: Record<string, string>;
|
|
601
664
|
/**
|
|
602
665
|
* You can't have more than one instance of the same provider on the same page, unless you specify a unique instance key for each one.
|
|
666
|
+
* This is because there's state in the URL and history.state and the state of the different instances would collide.
|
|
667
|
+
* By setting this property, you can specify a unique key for each instance, so that the state of each instance is kept separate.
|
|
603
668
|
* We recommend to just use an incrementing number for this, e.g. "1", "2", "3", ...
|
|
604
|
-
* TODO: more explanation
|
|
605
669
|
*/
|
|
606
670
|
uniqueInstanceKeyForState?: string;
|
|
607
671
|
} & (InputDisplay extends ModernDisplay ? "page_url" extends keyof InputDisplay["variant_displays"][number] ? {
|