@searchcraft/react-sdk 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -231,8 +231,40 @@ export interface MostRecentToggleFilterItem extends FilterItem {
231
231
  };
232
232
  }
233
233
  export type TemplateHtml = (strings: TemplateStringsArray, ...values: (string | number | undefined)[]) => string;
234
- export type SearchResultTemplate<T> = (data: T, index: number, utils: {
234
+ /**
235
+ * Options for the `safeUrl` template helper.
236
+ */
237
+ export type SafeUrlOptions = {
238
+ /**
239
+ * More URL schemes to allow, such as an app's own scheme (`['myapp']`). A link with such a
240
+ * scheme must be written in the template's own markup. If its markup is placed as a value in
241
+ * the text of another `html` call, DOMPurify removes the URL.
242
+ */
243
+ schemes?: string[];
244
+ };
245
+ /**
246
+ * Returns `url` unchanged when it is safe to place in an `href` or `src` attribute, and `#` when
247
+ * it is not. Relative URLs, `http:`, `https:`, `mailto:`, `tel:`, `sms:` and `data:image/` URLs
248
+ * are safe, along with any scheme passed in `options.schemes`.
249
+ */
250
+ export type SafeUrl = (url: unknown, options?: SafeUrlOptions) => string;
251
+ /**
252
+ * The helpers passed to every template.
253
+ */
254
+ export type TemplateUtils = {
255
+ /**
256
+ * Builds the template's markup. Values in text are sanitized, and values in attributes are
257
+ * escaped so they stay inside their attribute. Values in event handler attributes such as
258
+ * `onclick`, or in `style`, are not made safe, so never place result values there.
259
+ */
235
260
  html: TemplateHtml;
261
+ /**
262
+ * Checks a URL before it is placed in an `href` or `src`. Returns `#` for unsafe URLs,
263
+ * such as `javascript:` URLs.
264
+ */
265
+ safeUrl: SafeUrl;
266
+ };
267
+ export type SearchResultTemplate<T> = (data: T, index: number, utils: TemplateUtils & {
236
268
  source_index?: string;
237
269
  }) => string;
238
270
  export type SearchResultTemplateData = any;
@@ -243,23 +275,18 @@ export type ResultsInfoTemplate = (data: {
243
275
  ];
244
276
  count: number;
245
277
  responseTime: string;
246
- }, utils: {
247
- html: TemplateHtml;
248
- }) => string;
278
+ }, utils: TemplateUtils) => string;
249
279
  export type CustomAdTemplate = (data: {
250
280
  adContainerId: string;
251
281
  searchTerm: string;
252
- }, utils: {
253
- html: TemplateHtml;
254
- }) => string;
282
+ }, utils: TemplateUtils) => string;
255
283
  export type PopoverButtonTemplate = (data: {
256
284
  isPopoverVisible: boolean;
257
- }, utils: {
258
- html: TemplateHtml;
259
- }) => string;
260
- export type ADMAdTemplate = (data: ADMAd, utils: {
261
- html: TemplateHtml;
262
- }) => string;
285
+ }, utils: TemplateUtils) => string;
286
+ export type PopoverNoResultsTemplate = (data: {
287
+ searchTerm: string;
288
+ }, utils: TemplateUtils) => string;
289
+ export type ADMAdTemplate = (data: ADMAd, utils: TemplateUtils) => string;
263
290
  export interface CustomAdConfig {
264
291
  /**
265
292
  * The amount of debounce delay to add before calling the ad_container_rendered event
@@ -1124,6 +1151,11 @@ export namespace Components {
1124
1151
  * ```
1125
1152
  */
1126
1153
  interface SearchcraftPopoverButton {
1154
+ /**
1155
+ * The placeholder text shown in the `skeuomorphic` button, and the accessible label of the `magnifying-glass` button. Set it to the same value as the `placeholderValue` of `searchcraft-popover-form` so the button matches the form it opens. When it is blank, the `magnifying-glass` button is labeled "Search".
1156
+ * @default 'Search'
1157
+ */
1158
+ "placeholderValue"?: string;
1127
1159
  /**
1128
1160
  * The id of the Searchcraft instance that this component should use.
1129
1161
  */
@@ -1175,6 +1207,14 @@ export namespace Components {
1175
1207
  * // index.js
1176
1208
  * const popoverForm = document.querySelector('searchcraft-popover-form');
1177
1209
  * popoverForm.popoverResultMappings = {};
1210
+ * // Or render each result with a template instead of `popoverResultMappings`.
1211
+ * popoverForm.template = (item, index, { html, safeUrl }) => html`
1212
+ * <a href="${safeUrl(item.url)}">${item.title}</a>
1213
+ * `;
1214
+ * // Change the message shown when a search returns no results.
1215
+ * popoverForm.noResultsTemplate = ({ searchTerm }, { html }) => html`
1216
+ * <p>Nothing matched "${searchTerm}".</p>
1217
+ * `;
1178
1218
  * ```
1179
1219
  * @react-example ```jsx
1180
1220
  * <SearchcraftPopoverForm type="inline" popoverResultMappings={[]} />
@@ -1194,6 +1234,10 @@ export namespace Components {
1194
1234
  * @default 'meta'
1195
1235
  */
1196
1236
  "hotkeyModifier"?: "ctrl" | "meta" | "alt" | "option";
1237
+ /**
1238
+ * A callback function responsible for rendering the message shown when a search returns no results. When it is not provided, the popover shows `No results found for "<search term>".` The returned markup is sanitized with DOMPurify, which removes scripts, event handler attributes such as `onclick`, and links with schemes it does not allow, such as an app's own scheme.
1239
+ */
1240
+ "noResultsTemplate"?: PopoverNoResultsTemplate;
1197
1241
  /**
1198
1242
  * The placeholder's render behavior. 'hide-on-focus' - Hide the placeholder text immediately when the input form gains focus. 'hide-on-text-entered' - Only hide the placeholder when the input form has text entered into it.
1199
1243
  */
@@ -1221,6 +1265,10 @@ export namespace Components {
1221
1265
  * @default false
1222
1266
  */
1223
1267
  "showSummaryBox"?: boolean;
1268
+ /**
1269
+ * A callback function responsible for rendering a result. When provided, it is used instead of `popoverResultMappings`. Pass URLs from the result through the `safeUrl` helper before placing them in an `href` or `src`. Never place result values in event handler attributes such as `onclick`, or in `style`.
1270
+ */
1271
+ "template"?: SearchResultTemplate<SearchResultTemplateData>;
1224
1272
  /**
1225
1273
  * The type of popover form to render. - `inline` - Renders inline with the rest of the content on the page. The search results pop over the page content. - `fullscreen` - Renders in fullscreen view. Used together with the `searchcraft-popover-button` component. - `modal` - Renders in a modal view. Used together with the `searchcraft-popover-button` component.
1226
1274
  * @default 'inline'
@@ -1244,12 +1292,21 @@ export namespace Components {
1244
1292
  * @default 0
1245
1293
  */
1246
1294
  "documentPosition": number;
1295
+ /**
1296
+ * The index of the result in the list view. Passed to the `template` callback.
1297
+ * @default 0
1298
+ */
1299
+ "index": number;
1247
1300
  "item": SearchClientResponseItem | undefined;
1248
1301
  "popoverResultMappings": PopoverResultMappings | undefined;
1249
1302
  /**
1250
1303
  * The id of the Searchcraft instance that this component should use.
1251
1304
  */
1252
1305
  "searchcraftId"?: string;
1306
+ /**
1307
+ * A callback function responsible for rendering the result. When provided, it is used instead of `popoverResultMappings`, which are still used if the template throws.
1308
+ */
1309
+ "template"?: SearchResultTemplate<SearchResultTemplateData>;
1253
1310
  }
1254
1311
  /**
1255
1312
  * This web component is designed to display a list of results within a popover interface.
@@ -1274,6 +1331,10 @@ export namespace Components {
1274
1331
  * The id of the Searchcraft instance that this component should use.
1275
1332
  */
1276
1333
  "searchcraftId"?: string;
1334
+ /**
1335
+ * A callback function responsible for rendering a result. Passed to `searchcraft-popover-list-item`.
1336
+ */
1337
+ "template"?: SearchResultTemplate<SearchResultTemplateData>;
1277
1338
  }
1278
1339
  /**
1279
1340
  * This web component is designed to display the number of results returned from a search query.
@@ -1379,10 +1440,7 @@ export namespace Components {
1379
1440
  * ```
1380
1441
  * @js-example ```html
1381
1442
  * <!-- index.html -->
1382
- * <searchcraft-search-results
1383
- * ad-interval="4"
1384
- * place-ad-at-start="true"
1385
- * />
1443
+ * <searchcraft-search-results></searchcraft-search-results>
1386
1444
  * ```
1387
1445
  * ```js
1388
1446
  * // index.js
@@ -1393,8 +1451,6 @@ export namespace Components {
1393
1451
  * ```
1394
1452
  * @react-example ```jsx
1395
1453
  * <SearchcraftSearchResults
1396
- * adInterval={4}
1397
- * placeAdAtState={true}
1398
1454
  * template={(item, index, { html }) => html`
1399
1455
  * <h2>${item.title}</h2>
1400
1456
  * `}
@@ -1402,8 +1458,6 @@ export namespace Components {
1402
1458
  * ```
1403
1459
  * @vue-example ```jsx
1404
1460
  * <SearchcraftSearchResults
1405
- * adInterval={4}
1406
- * placeAdAtState={true}
1407
1461
  * :template={(item, index, { html }) => html`
1408
1462
  * <h2>${item.title}</h2>
1409
1463
  * `}
@@ -1420,7 +1474,7 @@ export namespace Components {
1420
1474
  */
1421
1475
  "searchcraftId"?: string;
1422
1476
  /**
1423
- * A callback function responsible for rendering a result. Passed to `searchcraft-search-result`.
1477
+ * A callback function responsible for rendering a result. Passed to `searchcraft-search-result`. Pass URLs from the result through the `safeUrl` helper before placing them in an `href` or `src`. Never place result values in event handler attributes such as `onclick`, or in `style`.
1424
1478
  */
1425
1479
  "template"?: SearchResultTemplate<SearchResultTemplateData>;
1426
1480
  }
@@ -1898,6 +1952,14 @@ declare global {
1898
1952
  * // index.js
1899
1953
  * const popoverForm = document.querySelector('searchcraft-popover-form');
1900
1954
  * popoverForm.popoverResultMappings = {};
1955
+ * // Or render each result with a template instead of `popoverResultMappings`.
1956
+ * popoverForm.template = (item, index, { html, safeUrl }) => html`
1957
+ * <a href="${safeUrl(item.url)}">${item.title}</a>
1958
+ * `;
1959
+ * // Change the message shown when a search returns no results.
1960
+ * popoverForm.noResultsTemplate = ({ searchTerm }, { html }) => html`
1961
+ * <p>Nothing matched "${searchTerm}".</p>
1962
+ * `;
1901
1963
  * ```
1902
1964
  * @react-example ```jsx
1903
1965
  * <SearchcraftPopoverForm type="inline" popoverResultMappings={[]} />
@@ -2020,10 +2082,7 @@ declare global {
2020
2082
  * ```
2021
2083
  * @js-example ```html
2022
2084
  * <!-- index.html -->
2023
- * <searchcraft-search-results
2024
- * ad-interval="4"
2025
- * place-ad-at-start="true"
2026
- * />
2085
+ * <searchcraft-search-results></searchcraft-search-results>
2027
2086
  * ```
2028
2087
  * ```js
2029
2088
  * // index.js
@@ -2034,8 +2093,6 @@ declare global {
2034
2093
  * ```
2035
2094
  * @react-example ```jsx
2036
2095
  * <SearchcraftSearchResults
2037
- * adInterval={4}
2038
- * placeAdAtState={true}
2039
2096
  * template={(item, index, { html }) => html`
2040
2097
  * <h2>${item.title}</h2>
2041
2098
  * `}
@@ -2043,8 +2100,6 @@ declare global {
2043
2100
  * ```
2044
2101
  * @vue-example ```jsx
2045
2102
  * <SearchcraftSearchResults
2046
- * adInterval={4}
2047
- * placeAdAtState={true}
2048
2103
  * :template={(item, index, { html }) => html`
2049
2104
  * <h2>${item.title}</h2>
2050
2105
  * `}
@@ -2583,6 +2638,11 @@ declare namespace LocalJSX {
2583
2638
  * ```
2584
2639
  */
2585
2640
  interface SearchcraftPopoverButton {
2641
+ /**
2642
+ * The placeholder text shown in the `skeuomorphic` button, and the accessible label of the `magnifying-glass` button. Set it to the same value as the `placeholderValue` of `searchcraft-popover-form` so the button matches the form it opens. When it is blank, the `magnifying-glass` button is labeled "Search".
2643
+ * @default 'Search'
2644
+ */
2645
+ "placeholderValue"?: string;
2586
2646
  /**
2587
2647
  * The id of the Searchcraft instance that this component should use.
2588
2648
  */
@@ -2634,6 +2694,14 @@ declare namespace LocalJSX {
2634
2694
  * // index.js
2635
2695
  * const popoverForm = document.querySelector('searchcraft-popover-form');
2636
2696
  * popoverForm.popoverResultMappings = {};
2697
+ * // Or render each result with a template instead of `popoverResultMappings`.
2698
+ * popoverForm.template = (item, index, { html, safeUrl }) => html`
2699
+ * <a href="${safeUrl(item.url)}">${item.title}</a>
2700
+ * `;
2701
+ * // Change the message shown when a search returns no results.
2702
+ * popoverForm.noResultsTemplate = ({ searchTerm }, { html }) => html`
2703
+ * <p>Nothing matched "${searchTerm}".</p>
2704
+ * `;
2637
2705
  * ```
2638
2706
  * @react-example ```jsx
2639
2707
  * <SearchcraftPopoverForm type="inline" popoverResultMappings={[]} />
@@ -2653,6 +2721,10 @@ declare namespace LocalJSX {
2653
2721
  * @default 'meta'
2654
2722
  */
2655
2723
  "hotkeyModifier"?: "ctrl" | "meta" | "alt" | "option";
2724
+ /**
2725
+ * A callback function responsible for rendering the message shown when a search returns no results. When it is not provided, the popover shows `No results found for "<search term>".` The returned markup is sanitized with DOMPurify, which removes scripts, event handler attributes such as `onclick`, and links with schemes it does not allow, such as an app's own scheme.
2726
+ */
2727
+ "noResultsTemplate"?: PopoverNoResultsTemplate;
2656
2728
  /**
2657
2729
  * The placeholder's render behavior. 'hide-on-focus' - Hide the placeholder text immediately when the input form gains focus. 'hide-on-text-entered' - Only hide the placeholder when the input form has text entered into it.
2658
2730
  */
@@ -2680,6 +2752,10 @@ declare namespace LocalJSX {
2680
2752
  * @default false
2681
2753
  */
2682
2754
  "showSummaryBox"?: boolean;
2755
+ /**
2756
+ * A callback function responsible for rendering a result. When provided, it is used instead of `popoverResultMappings`. Pass URLs from the result through the `safeUrl` helper before placing them in an `href` or `src`. Never place result values in event handler attributes such as `onclick`, or in `style`.
2757
+ */
2758
+ "template"?: SearchResultTemplate<SearchResultTemplateData>;
2683
2759
  /**
2684
2760
  * The type of popover form to render. - `inline` - Renders inline with the rest of the content on the page. The search results pop over the page content. - `fullscreen` - Renders in fullscreen view. Used together with the `searchcraft-popover-button` component. - `modal` - Renders in a modal view. Used together with the `searchcraft-popover-button` component.
2685
2761
  * @default 'inline'
@@ -2703,12 +2779,21 @@ declare namespace LocalJSX {
2703
2779
  * @default 0
2704
2780
  */
2705
2781
  "documentPosition"?: number;
2782
+ /**
2783
+ * The index of the result in the list view. Passed to the `template` callback.
2784
+ * @default 0
2785
+ */
2786
+ "index"?: number;
2706
2787
  "item"?: SearchClientResponseItem | undefined;
2707
2788
  "popoverResultMappings"?: PopoverResultMappings | undefined;
2708
2789
  /**
2709
2790
  * The id of the Searchcraft instance that this component should use.
2710
2791
  */
2711
2792
  "searchcraftId"?: string;
2793
+ /**
2794
+ * A callback function responsible for rendering the result. When provided, it is used instead of `popoverResultMappings`, which are still used if the template throws.
2795
+ */
2796
+ "template"?: SearchResultTemplate<SearchResultTemplateData>;
2712
2797
  }
2713
2798
  /**
2714
2799
  * This web component is designed to display a list of results within a popover interface.
@@ -2733,6 +2818,10 @@ declare namespace LocalJSX {
2733
2818
  * The id of the Searchcraft instance that this component should use.
2734
2819
  */
2735
2820
  "searchcraftId"?: string;
2821
+ /**
2822
+ * A callback function responsible for rendering a result. Passed to `searchcraft-popover-list-item`.
2823
+ */
2824
+ "template"?: SearchResultTemplate<SearchResultTemplateData>;
2736
2825
  }
2737
2826
  /**
2738
2827
  * This web component is designed to display the number of results returned from a search query.
@@ -2838,10 +2927,7 @@ declare namespace LocalJSX {
2838
2927
  * ```
2839
2928
  * @js-example ```html
2840
2929
  * <!-- index.html -->
2841
- * <searchcraft-search-results
2842
- * ad-interval="4"
2843
- * place-ad-at-start="true"
2844
- * />
2930
+ * <searchcraft-search-results></searchcraft-search-results>
2845
2931
  * ```
2846
2932
  * ```js
2847
2933
  * // index.js
@@ -2852,8 +2938,6 @@ declare namespace LocalJSX {
2852
2938
  * ```
2853
2939
  * @react-example ```jsx
2854
2940
  * <SearchcraftSearchResults
2855
- * adInterval={4}
2856
- * placeAdAtState={true}
2857
2941
  * template={(item, index, { html }) => html`
2858
2942
  * <h2>${item.title}</h2>
2859
2943
  * `}
@@ -2861,8 +2945,6 @@ declare namespace LocalJSX {
2861
2945
  * ```
2862
2946
  * @vue-example ```jsx
2863
2947
  * <SearchcraftSearchResults
2864
- * adInterval={4}
2865
- * placeAdAtState={true}
2866
2948
  * :template={(item, index, { html }) => html`
2867
2949
  * <h2>${item.title}</h2>
2868
2950
  * `}
@@ -2879,7 +2961,7 @@ declare namespace LocalJSX {
2879
2961
  */
2880
2962
  "searchcraftId"?: string;
2881
2963
  /**
2882
- * A callback function responsible for rendering a result. Passed to `searchcraft-search-result`.
2964
+ * A callback function responsible for rendering a result. Passed to `searchcraft-search-result`. Pass URLs from the result through the `safeUrl` helper before placing them in an `href` or `src`. Never place result values in event handler attributes such as `onclick`, or in `style`.
2883
2965
  */
2884
2966
  "template"?: SearchResultTemplate<SearchResultTemplateData>;
2885
2967
  }
@@ -3281,6 +3363,14 @@ declare module "@stencil/core" {
3281
3363
  * // index.js
3282
3364
  * const popoverForm = document.querySelector('searchcraft-popover-form');
3283
3365
  * popoverForm.popoverResultMappings = {};
3366
+ * // Or render each result with a template instead of `popoverResultMappings`.
3367
+ * popoverForm.template = (item, index, { html, safeUrl }) => html`
3368
+ * <a href="${safeUrl(item.url)}">${item.title}</a>
3369
+ * `;
3370
+ * // Change the message shown when a search returns no results.
3371
+ * popoverForm.noResultsTemplate = ({ searchTerm }, { html }) => html`
3372
+ * <p>Nothing matched "${searchTerm}".</p>
3373
+ * `;
3284
3374
  * ```
3285
3375
  * @react-example ```jsx
3286
3376
  * <SearchcraftPopoverForm type="inline" popoverResultMappings={[]} />
@@ -3373,10 +3463,7 @@ declare module "@stencil/core" {
3373
3463
  * ```
3374
3464
  * @js-example ```html
3375
3465
  * <!-- index.html -->
3376
- * <searchcraft-search-results
3377
- * ad-interval="4"
3378
- * place-ad-at-start="true"
3379
- * />
3466
+ * <searchcraft-search-results></searchcraft-search-results>
3380
3467
  * ```
3381
3468
  * ```js
3382
3469
  * // index.js
@@ -3387,8 +3474,6 @@ declare module "@stencil/core" {
3387
3474
  * ```
3388
3475
  * @react-example ```jsx
3389
3476
  * <SearchcraftSearchResults
3390
- * adInterval={4}
3391
- * placeAdAtState={true}
3392
3477
  * template={(item, index, { html }) => html`
3393
3478
  * <h2>${item.title}</h2>
3394
3479
  * `}
@@ -3396,8 +3481,6 @@ declare module "@stencil/core" {
3396
3481
  * ```
3397
3482
  * @vue-example ```jsx
3398
3483
  * <SearchcraftSearchResults
3399
- * adInterval={4}
3400
- * placeAdAtState={true}
3401
3484
  * :template={(item, index, { html }) => html`
3402
3485
  * <h2>${item.title}</h2>
3403
3486
  * `}