@searchcraft/javascript-sdk 0.11.1 → 0.12.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.
Files changed (45) hide show
  1. package/README.md +11 -2
  2. package/dist/components/index.d.ts +44 -2
  3. package/dist/components/index.js +162 -95
  4. package/dist/components/index.js.map +1 -1
  5. package/dist/components/{p-3e41546c.js → p-02ad136b.js} +3 -3
  6. package/dist/components/{p-3e41546c.js.map → p-02ad136b.js.map} +1 -1
  7. package/dist/components/{p-b7e99386.js → p-870f81fd.js} +38 -6
  8. package/dist/components/p-870f81fd.js.map +1 -0
  9. package/dist/components/{p-0c495408.js → p-c8566920.js} +74 -33
  10. package/dist/components/p-c8566920.js.map +1 -0
  11. package/dist/components/searchcraft-facet-list.js +1 -1
  12. package/dist/components/searchcraft-filter-panel.js +3 -3
  13. package/dist/components/searchcraft-filter-panel.js.map +1 -1
  14. package/dist/components/searchcraft-input-form.js +1 -1
  15. package/dist/components/searchcraft-pagination.js +8 -2
  16. package/dist/components/searchcraft-pagination.js.map +1 -1
  17. package/dist/components/searchcraft-popover-form.js +22 -4
  18. package/dist/components/searchcraft-popover-form.js.map +1 -1
  19. package/dist/components/searchcraft-results-info.js +9 -1
  20. package/dist/components/searchcraft-results-info.js.map +1 -1
  21. package/dist/components/searchcraft-search-results-per-page.js +8 -2
  22. package/dist/components/searchcraft-search-results-per-page.js.map +1 -1
  23. package/dist/components/searchcraft-summary-box.js +42 -10
  24. package/dist/components/searchcraft-summary-box.js.map +1 -1
  25. package/dist/components/searchcraft-theme.js +1 -1
  26. package/dist/components/searchcraft-toggle-button.js +1 -1
  27. package/dist/hydrate/index.js +258 -116
  28. package/dist/hydrate/index.mjs +258 -116
  29. package/dist/types/classes/SearchcraftCore.d.ts +1 -1
  30. package/dist/types/clients/SearchClient.d.ts +1 -0
  31. package/dist/types/components/searchcraft-facet-list/searchcraft-facet-list.d.ts +1 -1
  32. package/dist/types/components/searchcraft-filter-panel/searchcraft-filter-panel.d.ts +1 -1
  33. package/dist/types/components/searchcraft-input-form/searchcraft-input-form.d.ts +5 -0
  34. package/dist/types/components/searchcraft-pagination/searchcraft-pagination.d.ts +1 -0
  35. package/dist/types/components/searchcraft-popover-form/searchcraft-popover-form.d.ts +10 -0
  36. package/dist/types/components/searchcraft-results-info/searchcraft-results-info.d.ts +1 -0
  37. package/dist/types/components/searchcraft-search-results-per-page/searchcraft-search-results-per-page.d.ts +1 -0
  38. package/dist/types/components/searchcraft-summary-box/searchcraft-summary-box.d.ts +17 -0
  39. package/dist/types/components.d.ts +24 -0
  40. package/dist/types/store/SearchcraftStore.types.d.ts +10 -2
  41. package/dist/types/types/core-types/Measure.types.d.ts +1 -0
  42. package/dist/types/types/core-types/SearchcraftConfig.types.d.ts +9 -1
  43. package/package.json +5 -4
  44. package/dist/components/p-0c495408.js.map +0 -1
  45. package/dist/components/p-b7e99386.js.map +0 -1
@@ -10,6 +10,7 @@ export declare class SearchClient {
10
10
  constructor(parent: SearchcraftCore, config: SearchcraftConfig, userId: string);
11
11
  /**
12
12
  * Getter for the base url used by the /search endpoint.
13
+ * Supports both index and federation search endpoints.
13
14
  */
14
15
  private get baseSearchUrl();
15
16
  /**
@@ -1,7 +1,7 @@
1
1
  import { type EventEmitter } from '../../stencil-public-runtime';
2
2
  import type { FacetWithChildrenObject } from "../../types/index";
3
- import type { SearchcraftState } from "../../store/index";
4
3
  import type { SearchcraftCore } from "../../classes/index";
4
+ import type { SearchcraftState } from "../../store/index";
5
5
  type HandlerActionType = 'SEARCH_TERM_EMPTY' | 'NEW_SEARCH_TERM' | 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE' | 'RANGE_VALUE_UPDATE' | 'EXACT_MATCH_UPDATE' | 'SORT_ORDER_UPDATE' | 'FACET_UPDATE' | 'UNKNOWN';
6
6
  /**
7
7
  * This web component is designed to display facets in a search interface, allowing users to refine their search results by applying filters based on various attributes.
@@ -1,5 +1,5 @@
1
1
  import type { SearchcraftCore } from "../../classes/index";
2
- import type { FilterItem, DateRangeFilterItem } from "../../types/index";
2
+ import type { DateRangeFilterItem, FilterItem } from "../../types/index";
3
3
  /**
4
4
  * This web component represents a series of filters that allows users to refine and control their search queries by applying various filter criteria.
5
5
  *
@@ -60,6 +60,10 @@ export declare class SearchcraftInputForm {
60
60
  * 'hide-on-text-entered' - Only hide the placeholder when the input form has text entered into it.
61
61
  */
62
62
  placeholderBehavior?: 'hide-on-focus' | 'hide-on-text-entered';
63
+ /**
64
+ * The value to display in the input field.
65
+ */
66
+ value?: string;
63
67
  /**
64
68
  * When the input becomes focused.
65
69
  */
@@ -80,6 +84,7 @@ export declare class SearchcraftInputForm {
80
84
  private cleanupCore?;
81
85
  init(): void;
82
86
  onCoreChange(): void;
87
+ onValueChange(newValue: string | undefined): void;
83
88
  onCoreAvailable(core: SearchcraftCore): void;
84
89
  connectedCallback(): void;
85
90
  disconnectedCallback(): void;
@@ -36,6 +36,7 @@ export declare class SearchcraftPagination {
36
36
  searchResultsPerPage: any;
37
37
  searchResultsPage: any;
38
38
  searchResultsCount: any;
39
+ searchClientRequestProperties: any;
39
40
  searchResultsPagesCount: number;
40
41
  searchResultsRangeMin: number;
41
42
  searchResultsRangeMax: number;
@@ -61,6 +61,16 @@ export declare class SearchcraftPopoverForm {
61
61
  * The id of the Searchcraft instance that this component should use.
62
62
  */
63
63
  searchcraftId?: string;
64
+ /**
65
+ * The input element's placeholder value.
66
+ */
67
+ placeholderValue?: string;
68
+ /**
69
+ * The placeholder's render behavior.
70
+ * 'hide-on-focus' - Hide the placeholder text immediately when the input form gains focus.
71
+ * 'hide-on-text-entered' - Only hide the placeholder when the input form has text entered into it.
72
+ */
73
+ placeholderBehavior?: 'hide-on-focus' | 'hide-on-text-entered';
64
74
  isPopoverVisibleInState: boolean;
65
75
  searchClientResponseItems: SearchClientResponseItem[];
66
76
  adClientResponseItems: AdClientResponseItem[];
@@ -59,6 +59,7 @@ export declare class SearchcraftResultsInfo {
59
59
  searchResultsPage: any;
60
60
  searchResultsPerPage: any;
61
61
  searchResultsCount: any;
62
+ searchClientRequestProperties: any;
62
63
  count: number;
63
64
  range: number[];
64
65
  responseTime: string;
@@ -43,6 +43,7 @@ export declare class SearchcraftSearchResultsPerPage {
43
43
  searchResultsPerPage: any;
44
44
  searchResultsCount: any;
45
45
  searchResultsPagesCount: any;
46
+ searchClientRequestProperties: any;
46
47
  initialSearchResultsPerPage: any;
47
48
  setSearchResultsPerPage: (perPage: number) => void;
48
49
  setSearchResultsPage: (page: number) => void;
@@ -38,12 +38,29 @@ export declare class SearchcraftSummaryBox {
38
38
  searchcraftId?: string;
39
39
  summary: string;
40
40
  isLoading: boolean;
41
+ isSummaryNotEnabled: boolean;
41
42
  hostElement?: HTMLElement;
42
43
  private unsubscribe?;
43
44
  private cleanupCore?;
44
45
  onCoreAvailable(core: SearchcraftCore): void;
45
46
  connectedCallback(): void;
46
47
  disconnectedCallback(): void;
48
+ /**
49
+ * Handles state changes from the store and updates component state.
50
+ */
51
+ private handleStateChange;
52
+ /**
53
+ * Sanitizes and converts markdown to HTML.
54
+ */
55
+ private sanitizeMarkdown;
56
+ /**
57
+ * Updates the content element directly without triggering a re-render.
58
+ */
59
+ private updateContentElement;
60
+ /**
61
+ * Renders the appropriate content based on current state.
62
+ */
63
+ private renderContent;
47
64
  render(): any;
48
65
  }
49
66
  //# sourceMappingURL=searchcraft-summary-box.d.ts.map
@@ -178,6 +178,10 @@ export namespace Components {
178
178
  * The id of the Searchcraft instance that this component should use.
179
179
  */
180
180
  "searchcraftId"?: string;
181
+ /**
182
+ * The value to display in the input field.
183
+ */
184
+ "value"?: string;
181
185
  }
182
186
  /**
183
187
  * This web component serves as the input label for the searchcraft-input-form component.
@@ -318,6 +322,14 @@ export namespace Components {
318
322
  * The hotkey modifier that activates the popover. Used together with the `hotkey` prop.
319
323
  */
320
324
  "hotkeyModifier"?: 'ctrl' | 'meta' | 'alt' | 'option';
325
+ /**
326
+ * 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.
327
+ */
328
+ "placeholderBehavior"?: 'hide-on-focus' | 'hide-on-text-entered';
329
+ /**
330
+ * The input element's placeholder value.
331
+ */
332
+ "placeholderValue"?: string;
321
333
  /**
322
334
  * Formats the content rendered for each result.
323
335
  */
@@ -1429,6 +1441,10 @@ declare namespace LocalJSX {
1429
1441
  * The id of the Searchcraft instance that this component should use.
1430
1442
  */
1431
1443
  "searchcraftId"?: string;
1444
+ /**
1445
+ * The value to display in the input field.
1446
+ */
1447
+ "value"?: string;
1432
1448
  }
1433
1449
  /**
1434
1450
  * This web component serves as the input label for the searchcraft-input-form component.
@@ -1569,6 +1585,14 @@ declare namespace LocalJSX {
1569
1585
  * The hotkey modifier that activates the popover. Used together with the `hotkey` prop.
1570
1586
  */
1571
1587
  "hotkeyModifier"?: 'ctrl' | 'meta' | 'alt' | 'option';
1588
+ /**
1589
+ * 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.
1590
+ */
1591
+ "placeholderBehavior"?: 'hide-on-focus' | 'hide-on-text-entered';
1592
+ /**
1593
+ * The input element's placeholder value.
1594
+ */
1595
+ "placeholderValue"?: string;
1572
1596
  /**
1573
1597
  * Formats the content rendered for each result.
1574
1598
  */
@@ -1,5 +1,5 @@
1
+ import type { AdClientResponseItem, FacetPathsForIndexField, FacetPrime, RangeValueForIndexField, SearchClientRequest, SearchClientRequestProperties, SearchClientResponseItem } from "../types/index";
1
2
  import type { StoreApi } from 'zustand';
2
- import type { FacetPathsForIndexField, FacetPrime, RangeValueForIndexField, SearchClientResponseItem, AdClientResponseItem, SearchClientRequestProperties, SearchClientRequest } from "../types/index";
3
3
  import type { SearchcraftCore } from "../classes/index";
4
4
  import type { SummaryClient } from "../clients/SummaryClient";
5
5
  /**
@@ -11,7 +11,9 @@ export interface SearchcraftStateFunctions {
11
11
  removeFacetPathsForIndexField: (fieldName: string) => void;
12
12
  removeRangeValueForIndexField: (fieldName: string) => void;
13
13
  resetSearchValues: () => void;
14
- search: () => Promise<void>;
14
+ search: (options?: {
15
+ skipSummary?: boolean;
16
+ }) => Promise<void>;
15
17
  setPopoverVisibility: (isVisible: boolean) => void;
16
18
  setSearchResultsCount: (count: number) => void;
17
19
  setSearchResultsPage: (page: number) => void;
@@ -42,6 +44,11 @@ export interface SearchcraftStateValues {
42
44
  searchClientRequestProperties: SearchClientRequestProperties | string | undefined | null;
43
45
  searchClientResponseItems: SearchClientResponseItem[];
44
46
  cachedSearchClientResponseItems: SearchClientResponseItem[];
47
+ cachedSearchResponseFacetPrime: FacetPrime | undefined | null;
48
+ cachedSupplementalFacetPrime: FacetPrime | undefined | null;
49
+ cachedSearchResponseTimeTaken: number | undefined;
50
+ cachedSearchResultsCount: number | undefined;
51
+ cachedSearchClientRequestProperties: SearchClientRequestProperties | string | undefined | null;
45
52
  searchResponseTimeTaken: number | undefined;
46
53
  searchResponseFacetPrime: FacetPrime | undefined | null;
47
54
  supplementalFacetPrime: FacetPrime | undefined | null;
@@ -55,6 +62,7 @@ export interface SearchcraftStateValues {
55
62
  hasSummaryBox: boolean;
56
63
  isSummaryLoading: boolean;
57
64
  summaryClient?: SummaryClient;
65
+ isSummaryNotEnabled: boolean;
58
66
  }
59
67
  export interface SearchcraftState extends SearchcraftStateFunctions, SearchcraftStateValues {
60
68
  }
@@ -24,6 +24,7 @@ export interface MeasureRequestProperties {
24
24
  searchcraft_organization_id?: string;
25
25
  searchcraft_application_id?: string;
26
26
  searchcraft_index_names: string[];
27
+ searchcraft_federation_name?: string;
27
28
  search_term?: string;
28
29
  number_of_documents?: number;
29
30
  external_document_id?: string;
@@ -13,8 +13,16 @@ export interface SearchcraftConfig {
13
13
  endpointURL: string;
14
14
  /**
15
15
  * Name of the Searchcraft search index to search for results within. If you are using Searchcraft Cloud, this value can be found within the Vektron dashboard in the Code Snippets section when configuring a search index.
16
+ *
17
+ * Note: Either `indexName` or `federationName` must be provided, but not both.
18
+ */
19
+ indexName?: string;
20
+ /**
21
+ * Name of the Searchcraft federation to search across multiple indices. Federation search allows you to search across all indices defined in a federation with a single query.
22
+ *
23
+ * Note: Either `indexName` or `federationName` must be provided, but not both.
16
24
  */
17
- indexName: string;
25
+ federationName?: string;
18
26
  /**
19
27
  * The initial search query to call when Searchcraft is first initialized in your front-end application. This parameter can be used when you want to populate a page with an initial set of search results based on a query.
20
28
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@searchcraft/javascript-sdk",
3
3
  "private": false,
4
- "version": "0.11.1",
4
+ "version": "0.12.1",
5
5
  "description": "Searchcraft Javascript SDK",
6
6
  "author": "Searchcraft Inc.",
7
7
  "license": "Apache-2.0",
@@ -25,8 +25,9 @@
25
25
  },
26
26
  "repository": {
27
27
  "type": "git",
28
- "url": "https://bitbucket.org/madebychalk/searchcraft-javascript-sdks/"
28
+ "url": "https://github.com/searchcraft-inc/searchcraft-javascript-sdks"
29
29
  },
30
+ "homepage": "https://github.com/searchcraft-inc/searchcraft-javascript-sdks#readme",
30
31
  "files": [
31
32
  "dist/"
32
33
  ],
@@ -46,7 +47,7 @@
46
47
  },
47
48
  "devDependencies": {
48
49
  "@stencil/core": "^4.7.0",
49
- "@stencil/react-output-target": "^0.8.2",
50
+ "@stencil/react-output-target": "^1.2.0",
50
51
  "@stencil/sass": "^3.0.12",
51
52
  "@stencil/vue-output-target": "^0.9.2",
52
53
  "@thumbmarkjs/thumbmarkjs": "^0.16.1",
@@ -54,5 +55,5 @@
54
55
  "nanoid": "^5.0.9",
55
56
  "zustand": "^5.0.1"
56
57
  },
57
- "gitHead": "a76993be3f9de0f8dd0a1d8326a43435e794ec7d"
58
+ "gitHead": "585c42c689029256b94d34ae6f0a900240c3dfbe"
58
59
  }
@@ -1 +0,0 @@
1
- {"file":"p-0c495408.js","mappings":"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","names":[],"sources":["src/utils/facets.ts","src/components/searchcraft-facet-list/searchcraft-facet-list.tsx"],"sourcesContent":["import type {\n Facet,\n FacetTree,\n FacetWithChildrenArray,\n FacetWithChildrenObject,\n} from '@types';\n\n/**\n * Helper function for getting a Node (FacetWithChildrenObject)\n * at a given path. Traverses the node tree to get the node.\n */\nexport const getFacetTreeNodeAtPath = (\n tree: FacetTree,\n nodePaths: string[],\n): FacetWithChildrenObject | undefined => {\n let cursor: FacetWithChildrenObject | undefined = tree;\n for (const nodePath of nodePaths) {\n cursor = cursor?.children[nodePath];\n }\n\n return cursor;\n};\n\n/**\n * Helper function to perform a deep merge.\n * Used for merging two branches of a facet tree together.\n */\nexport const deepMergeWithSpread = (obj1, obj2) => {\n const result = { ...obj1 };\n\n for (const key in obj2) {\n // biome-ignore lint/suspicious/noPrototypeBuiltins: <explanation>\n if (obj2.hasOwnProperty(key)) {\n if (obj2[key] instanceof Object && obj1[key] instanceof Object) {\n result[key] = deepMergeWithSpread(obj1[key], obj2[key]);\n } else {\n result[key] = obj2[key];\n }\n }\n }\n\n return result;\n};\n\n/**\n * Given an array of facet paths, removes parent facet paths so that only the\n * Leaf facets are sent with the search request.\n */\nexport function removeSubstringMatches(arr: string[]): string[] {\n return arr.filter(\n (entry, index, array) =>\n !array.some(\n (otherEntry, otherIndex) =>\n otherIndex !== index && otherEntry.includes(entry),\n ),\n );\n}\n\n/**\n * Merges a current facet tree with an incoming facet tree.\n *\n * At each branch, the incoming facet tree's facets override current facet tree\n *\n * @param currentTree\n * @param incomingTree\n */\nexport const mergeFacetTrees = (\n currentTree: FacetTree,\n incomingTree: FacetTree,\n): FacetTree => {\n const mergedTree: FacetTree = structuredClone(currentTree);\n\n const merge = (\n currentBranch: FacetWithChildrenObject,\n nodePath: string[],\n ): FacetWithChildrenObject => {\n const mergedBranch = structuredClone(currentBranch);\n const incomingBranch = getFacetTreeNodeAtPath(incomingTree, nodePath);\n\n if (!incomingBranch) {\n return mergedBranch;\n }\n\n for (const nodeName of Object.keys(currentBranch.children)) {\n if (incomingBranch.children[nodeName]) {\n mergedBranch.children[nodeName] = {\n ...deepMergeWithSpread(\n currentBranch.children[nodeName],\n incomingBranch.children[nodeName],\n ),\n count: mergedBranch.children[nodeName]?.count || 0,\n };\n } else if (mergedBranch.children[nodeName]) {\n mergedBranch.children[nodeName] = merge(\n mergedBranch.children[nodeName],\n [...nodePath, nodeName],\n );\n }\n }\n\n return mergedBranch;\n };\n\n return merge(mergedTree, []);\n};\n\n/**\n * A function that converts a FacetWithChidrenArray to a complete FacetTree object.\n *\n * It uses the `path` of each Facet to build the tree.\n *\n * @param facetWithChildArray\n */\nexport const facetWithChildrenArrayToCompleteFacetTree = (\n rootArray: FacetWithChildrenArray,\n): FacetTree => {\n // 1) Start with an empty tree at root \"/\"\n const tree: FacetTree = {\n path: '/',\n count: 0,\n children: {},\n };\n\n // 2) Recursively collect all nodes except the implicit \"/\" itself\n const allFacets: Facet[] = [];\n const collect = (node: FacetWithChildrenArray) => {\n if (node.path !== '/') {\n allFacets.push({ path: node.path, count: node.count });\n }\n if (node.children) {\n for (const child of node.children) {\n collect(child);\n }\n }\n };\n collect(rootArray);\n\n // 3) Insert each flat node into our tree, creating missing ancestors\n for (const { path, count } of allFacets) {\n const segments = path.split('/').filter(Boolean); // \"/sports/outdoors\" -> [\"sports\",\"outdoors\"]\n let cursor: FacetWithChildrenObject = tree; // start at the root\n for (const segment of segments) {\n // Build the full path of this level\n const prefixPath =\n cursor.path === '/' ? `/${segment}` : `${cursor.path}/${segment}`;\n\n // If this segment doesn't exist yet, create it\n if (!cursor.children[segment]) {\n cursor.children[segment] = {\n path: prefixPath,\n count: count,\n children: {},\n };\n }\n\n // Descend to the next level deeper\n cursor = cursor.children[segment];\n }\n\n // 4) Now `cursor` is the node matching `path` assign its real count\n cursor.count = count;\n }\n\n return tree;\n};\n","import {\n Component,\n h,\n State,\n Prop,\n Event,\n type EventEmitter,\n} from '@stencil/core';\n\nimport type {\n FacetRoot,\n FacetWithChildrenArray,\n FacetWithChildrenObject,\n} from '@types';\n\nimport type { SearchcraftState } from '@store';\nimport {\n deepMergeWithSpread,\n facetWithChildrenArrayToCompleteFacetTree,\n getFacetTreeNodeAtPath,\n mergeFacetTrees,\n removeSubstringMatches,\n} from '@utils';\nimport type { SearchcraftCore } from '@classes';\nimport { registry } from '@classes/CoreInstanceRegistry';\n\ntype HandlerActionType =\n | 'SEARCH_TERM_EMPTY'\n | 'NEW_SEARCH_TERM'\n | 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE'\n | 'RANGE_VALUE_UPDATE'\n | 'EXACT_MATCH_UPDATE'\n | 'SORT_ORDER_UPDATE'\n | 'FACET_UPDATE'\n | 'UNKNOWN';\n\n/**\n * This web component is designed to display facets in a search interface, allowing users to refine their search results by applying filters based on various attributes.\n * It is consumed within the `searchcraft-filter-panel`.\n *\n * @js-example\n * ```html\n * <!-- index.html -->\n * <searchcraft-facet-list field-name=\"title\" />\n * ```\n *\n * ```js\n * // index.js\n * const facetList = document.querySelector('searchcraft-facet-list');\n *\n * facetList.addEventListener('facetSelectionUpdated', () => {\n * console.log('Facet selection updated');\n * });\n * ```\n *\n * @internal\n */\n@Component({\n tag: 'searchcraft-facet-list',\n shadow: false,\n})\nexport class SearchcraftFacetList {\n /**\n * The id of the Searchcraft instance that this component should use.\n */\n @Prop() searchcraftId?: string;\n /**\n * The name of the field where facets are applied.\n */\n @Prop() fieldName = '';\n\n /**\n * Emitted when the facets are updated.\n */\n @Event() facetSelectionUpdated?: EventEmitter<{ paths: string[] }>;\n\n /**\n * The currently selected facet paths.\n */\n @State() selectedPaths: Record<string, boolean> = {};\n\n /**\n * A Tree representing all of the facets collected from search responses.\n */\n @State() facetTreeCollectedFromSearchResponse: FacetWithChildrenObject = {\n path: '/',\n count: 0,\n children: {},\n };\n\n /**\n * A Tree representing the facet paths that are selected, but were not included\n * in any search response.\n */\n facetTreeFromFacetPathsNotInSearchResponse: FacetWithChildrenObject = {\n path: '/',\n count: 0,\n children: {},\n };\n\n /**\n * The facet tree that ultimately gets rendered.\n * This is a mergin of the facetTreeCollectedFromSearchResponse and the facetTreeFromFacetPathsNotInSearchResponse tree\n */\n @State() renderedFacetTree: FacetWithChildrenObject = {\n path: '/',\n count: 0,\n children: {},\n };\n\n // Internal vars used to track when to perform various facet actions.\n private lastTimeTaken?: number;\n private lastSearchTerm?: string;\n private lastSearchMode?: string;\n private lastSortType?: string | null;\n private lastRangeValues?: string;\n private lastFacetValues?: string;\n\n private unsubscribe?: () => void;\n private cleanupCore?: () => void;\n\n get areAnyFacetPathsSelected(): boolean {\n return Object.keys(this.selectedPaths).some(\n (key) => this.selectedPaths[key],\n );\n }\n\n handleIncomingSearchResponse(\n state: SearchcraftState,\n actionType: HandlerActionType,\n ) {\n // Look at the incoming facet root from the search response, and convert it to a FacetTree\n const incomingFacetRoot: FacetRoot | undefined =\n state.searchResponseFacetPrime?.find(\n (facet) => this.fieldName === Object.keys(facet)[0],\n );\n const incomingFacetsWithChildrenArray = incomingFacetRoot?.[this.fieldName];\n const incomingFacetTree = facetWithChildrenArrayToCompleteFacetTree({\n path: '/',\n count: 0,\n children: incomingFacetsWithChildrenArray || [],\n });\n\n // Determine what action to take to accumulate items into the `facetTreeCollectedFromSearchResponse`.\n // This facet tree gets accumulated in different ways depending on what action type occured.\n switch (actionType) {\n case 'SEARCH_TERM_EMPTY':\n this.facetTreeCollectedFromSearchResponse = {\n path: '/',\n count: 0,\n children: {},\n };\n break;\n case 'NEW_SEARCH_TERM':\n this.facetTreeCollectedFromSearchResponse = incomingFacetTree;\n break;\n case 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE':\n case 'EXACT_MATCH_UPDATE':\n case 'RANGE_VALUE_UPDATE': {\n if (state.supplementalFacetPrime) {\n const supplementalFacetRoot: FacetRoot | undefined =\n state.supplementalFacetPrime?.find(\n (facet) => this.fieldName === Object.keys(facet)[0],\n );\n const supplementalFacetsWithChildrenArray =\n supplementalFacetRoot?.[this.fieldName];\n const supplementalFacetTree =\n facetWithChildrenArrayToCompleteFacetTree({\n path: '/',\n count: 0,\n children: supplementalFacetsWithChildrenArray || [],\n });\n\n this.facetTreeCollectedFromSearchResponse = mergeFacetTrees(\n supplementalFacetTree,\n incomingFacetTree,\n );\n } else {\n this.facetTreeCollectedFromSearchResponse = incomingFacetTree;\n }\n break;\n }\n case 'FACET_UPDATE':\n case 'SORT_ORDER_UPDATE':\n this.facetTreeCollectedFromSearchResponse = mergeFacetTrees(\n this.facetTreeCollectedFromSearchResponse,\n incomingFacetTree,\n );\n break;\n default:\n return;\n }\n\n // Determine if there are any selected facet paths not in the current tree.\n // If there are, we add them to \"facetTreeFromFacetPathsNotInSearchResponse\"\n this.facetTreeFromFacetPathsNotInSearchResponse = {\n path: '/',\n count: 0,\n children: {},\n };\n const collectedFacetArray: FacetWithChildrenArray = {\n path: '/',\n count: 0,\n children: [],\n };\n for (const pathName of Object.keys(this.selectedPaths).filter(\n (path) => this.selectedPaths[path],\n )) {\n const nodePaths = pathName.startsWith('/')\n ? pathName.substring(1).split('/')\n : pathName.split('/');\n\n const wasFoundInFacetTree = !!getFacetTreeNodeAtPath(\n this.facetTreeCollectedFromSearchResponse,\n nodePaths,\n );\n\n const pathKeyName = nodePaths.at(-1);\n if (!wasFoundInFacetTree && pathKeyName) {\n collectedFacetArray.children?.push({\n children: [],\n count: 0,\n path: pathName,\n });\n }\n }\n this.facetTreeFromFacetPathsNotInSearchResponse =\n facetWithChildrenArrayToCompleteFacetTree(collectedFacetArray);\n\n // Merges facetTreeCollectedFromSearchResponse with selectedFacetPathsNotInCurrentFacetTree.\n // This results in a single, final facet tree that gets rendered in as Checkboxes\n this.renderedFacetTree = deepMergeWithSpread(\n this.facetTreeFromFacetPathsNotInSearchResponse,\n this.facetTreeCollectedFromSearchResponse,\n );\n }\n\n handleStateUpdate(_state: SearchcraftState) {\n const state = { ..._state };\n // Determine what action to take based on the current State\n if (state.searchTerm.trim() === '') {\n this.handleIncomingSearchResponse(state, 'SEARCH_TERM_EMPTY');\n this.lastSearchTerm = '';\n } else if (\n this.lastTimeTaken !== state.searchResponseTimeTaken &&\n state.searchClientRequestProperties &&\n typeof state.searchClientRequestProperties === 'object'\n ) {\n const requestProperties = state.searchClientRequestProperties;\n let actionType: HandlerActionType = 'UNKNOWN';\n\n if (this.lastSearchTerm !== requestProperties.searchTerm) {\n if (this.areAnyFacetPathsSelected) {\n actionType = 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE';\n } else {\n actionType = 'NEW_SEARCH_TERM';\n }\n } else if (\n this.lastRangeValues !==\n JSON.stringify(requestProperties.rangeValueForIndexFields)\n ) {\n actionType = 'RANGE_VALUE_UPDATE';\n } else if (\n this.lastFacetValues !==\n JSON.stringify(requestProperties.facetPathsForIndexFields)\n ) {\n actionType = 'FACET_UPDATE';\n } else if (this.lastSortType !== requestProperties.order_by) {\n actionType = 'SORT_ORDER_UPDATE';\n } else if (this.lastSearchMode !== requestProperties.mode) {\n actionType = 'EXACT_MATCH_UPDATE';\n }\n\n this.lastRangeValues = JSON.stringify(\n requestProperties.rangeValueForIndexFields,\n );\n this.lastFacetValues = JSON.stringify(\n requestProperties.facetPathsForIndexFields,\n );\n this.lastSortType = requestProperties.order_by;\n this.lastSearchMode = requestProperties.mode;\n this.lastSearchTerm = requestProperties.searchTerm;\n this.lastTimeTaken = state.searchResponseTimeTaken;\n // Handle the incoming response, using the action we have determined.\n this.handleIncomingSearchResponse(state, actionType);\n }\n }\n\n onCoreAvailable(core: SearchcraftCore) {\n this.handleStateUpdate(core.store.getState());\n\n this.unsubscribe = core.store.subscribe((state) => {\n this.handleStateUpdate(state);\n });\n }\n\n connectedCallback() {\n this.cleanupCore = registry.useCoreInstance(\n this.searchcraftId,\n this.onCoreAvailable.bind(this),\n );\n }\n\n disconnectedCallback() {\n this.unsubscribe?.();\n this.cleanupCore?.();\n }\n\n handleCheckboxChange(path: string) {\n const isCheckboxChecked = !this.selectedPaths[path];\n\n if (isCheckboxChecked) {\n /**\n * Checkbox Checked: Add to the selectedPaths record\n * Uses spread operator here so UI updates.\n */\n this.selectedPaths = {\n ...this.selectedPaths,\n [path]: true,\n };\n } else {\n /**\n * Checkbox Uncheck: Remove any paths and sub-paths\n */\n const updatedPaths = Object.keys(this.selectedPaths).filter(\n (testPath) => !testPath.includes(path),\n );\n\n this.selectedPaths = updatedPaths.reduce(\n (acc, str) => {\n acc[str] = true;\n return acc;\n },\n {} as Record<string, boolean>,\n );\n }\n\n /**\n * Emit the paths array, with parent paths removed.\n */\n const paths = Object.keys(this.selectedPaths).filter(\n (path) => this.selectedPaths[path],\n );\n const pathsWithParentPathsRemoved = removeSubstringMatches(paths);\n\n this.facetSelectionUpdated?.emit({ paths: pathsWithParentPathsRemoved });\n }\n\n formatFacetName = (name: string): string => {\n const label = name.replace(/^\\//, '');\n return `${label.replace(/-/g, ' ').replace(/\\b\\w/g, (char) => char.toUpperCase())}`;\n };\n\n renderFacet(keyName: string, facet: FacetWithChildrenObject) {\n let isChildSelected = false;\n for (const path of Object.keys(this.selectedPaths)) {\n if (\n this.selectedPaths[path] &&\n path.startsWith(facet.path) &&\n path.length > facet.path.length\n ) {\n isChildSelected = true;\n }\n }\n\n const isSelected = Object.keys(this.selectedPaths).includes(facet.path);\n\n const shouldRenderChildren =\n (Object.keys(facet.children).length > 0 &&\n (isSelected || isChildSelected)) ||\n keyName === '@@root';\n\n return (\n <div class='searchcraft-facet-list-item'>\n {keyName !== '@@root' && (\n <label class='searchcraft-facet-list-checkbox-label'>\n <div class='searchcraft-facet-list-checkbox-input-wrapper'>\n <input\n class='searchcraft-facet-list-checkbox-input'\n checked={this.selectedPaths[facet.path]}\n onChange={(_event: Event) => {\n this.handleCheckboxChange(facet.path);\n }}\n type='checkbox'\n />\n {isChildSelected ? (\n <div class='searchcraft-facet-list-checkbox-input-dash-icon'>\n <svg viewBox='0 0 14 3' fill='none'>\n <title>Checkbox dash</title>\n <line\n x1='1.5'\n y1='1.5'\n x2='12.5'\n y2='1.5'\n stroke='white'\n stroke-width='3'\n stroke-linecap='round'\n />\n </svg>\n </div>\n ) : (\n <div class='searchcraft-facet-list-checkbox-input-check-icon'>\n <svg width='16' height='16' viewBox='0 0 16 16' fill='none'>\n <title>Checkbox check</title>\n <path\n d='M13.9999 2L5.74988 10L1.99988 6.36364'\n stroke='white'\n stroke-width='3'\n stroke-linecap='round'\n stroke-linejoin='round'\n />\n </svg>\n </div>\n )}\n </div>\n <span>\n {this.formatFacetName(keyName)} ({facet.count})\n </span>\n </label>\n )}\n {shouldRenderChildren && (\n <div\n class='searchcraft-facet-list'\n style={{\n paddingLeft: keyName !== '@@root' ? '24px' : '0px',\n paddingTop: keyName !== '@@root' ? '6px' : '0px',\n }}\n >\n {Object.keys(facet.children).map((key) => {\n if (facet.children[key]) {\n return this.renderFacet(key, facet.children[key]);\n }\n })}\n </div>\n )}\n </div>\n );\n }\n\n render() {\n if (!this.fieldName) {\n return;\n }\n\n if (\n Object.keys(this.facetTreeCollectedFromSearchResponse.children).length ===\n 0 &&\n (this.lastSearchTerm || '').trim().length === 0\n ) {\n return;\n }\n\n if (\n Object.keys(this.facetTreeCollectedFromSearchResponse.children).length ===\n 0 &&\n (this.lastSearchTerm || '').trim().length > 0\n ) {\n return (\n <p class='searchcraft-facet-list-message'>\n No facets are available for this search query.\n </p>\n );\n }\n\n return (\n <div class='searchcraft-facet-list'>\n {this.renderFacet('@@root', this.renderedFacetTree)}\n </div>\n );\n }\n}\n"],"version":3}
@@ -1 +0,0 @@
1
- {"file":"p-b7e99386.js","mappings":"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","names":[],"sources":["src/components/searchcraft-input-form/searchcraft-input-form.tsx"],"sourcesContent":["import {\n Component,\n h,\n Prop,\n State,\n Event,\n type EventEmitter,\n Watch,\n} from '@stencil/core';\nimport classNames from 'classnames';\n\nimport type { SearchcraftCore } from '@classes';\nimport type { SearchcraftState } from '@store';\nimport { registry } from '@classes/CoreInstanceRegistry';\n\n/**\n * This web component provides a user-friendly interface for querying an indexed dataset, enabling users to easily search large collections of data.\n * It abstracts the complexities of index-based searching, making it accessible to users of all technical levels.\n *\n * @react-import\n * ```jsx\n * import { SearchcraftInputForm } from \"@searchcraft/react-sdk\";\n * ```\n *\n * @vue-import\n * ```jsx\n * import { SearchcraftInputForm } from \"@searchcraft/vue-sdk\";\n * ```\n *\n * @js-example\n * ```html\n * <searchcraft-input-form auto-search />\n * ```\n *\n * @react-example\n * ```jsx\n * <SearchcraftInputForm autoSearch />\n * ```\n *\n * @vue-example\n * ```jsx\n * <SearchcraftInputForm autoSearch />\n * ```\n */\n@Component({\n tag: 'searchcraft-input-form',\n shadow: false,\n})\nexport class SearchcraftInputForm {\n /**\n * The id of the Searchcraft instance that this component should use.\n */\n @Prop() searchcraftId?: string;\n /**\n * Whether or not to automatically submit the search term when the input changes.\n */\n @Prop() autoSearch?: boolean = true;\n /**\n * Where to place the search button.\n */\n @Prop() buttonPlacement?: 'left' | 'right' | 'none' = 'none';\n /**\n * The label for the submit button.\n */\n @Prop() buttonLabel?: string;\n /**\n * The label rendered above the input.\n */\n @Prop() inputLabel?: string;\n /**\n * The input element's placeholder value.\n */\n @Prop() placeholderValue?: string = 'Enter Search';\n /**\n * The placeholder's render behavior.\n * 'hide-on-focus' - Hide the placeholder text immediately when the input form gains focus.\n * 'hide-on-text-entered' - Only hide the placeholder when the input form has text entered into it.\n */\n @Prop() placeholderBehavior?: 'hide-on-focus' | 'hide-on-text-entered';\n /**\n * When the input becomes focused.\n */\n @Event() inputFocus?: EventEmitter<void>;\n /**\n * When the input becomes unfocused.\n */\n @Event() inputBlur?: EventEmitter<void>;\n /**\n * Event emitted when input initializes.\n */\n @Event() inputInit?: EventEmitter<void>;\n\n @State() inputValue = '';\n @State() searchTerm = '';\n @State() error = false;\n\n private core?: SearchcraftCore;\n private unsubscribe?: () => void;\n private cleanupCore?: () => void;\n\n init() {\n if (this.core) {\n this.inputInit?.emit();\n }\n }\n\n @Watch('core')\n onCoreChange() {\n this.init();\n }\n\n onCoreAvailable(core: SearchcraftCore) {\n this.core = core;\n this.init();\n this.unsubscribe = core.store.subscribe((state: SearchcraftState) => {\n this.searchTerm = state.searchTerm;\n this.inputValue = state.searchTerm;\n });\n }\n\n connectedCallback() {\n this.cleanupCore = registry.useCoreInstance(\n this.searchcraftId,\n this.onCoreAvailable.bind(this),\n );\n }\n\n disconnectedCallback() {\n this.unsubscribe?.();\n this.cleanupCore?.();\n }\n\n handleInput = (event: Event) => {\n const input = event.target as HTMLInputElement;\n this.inputValue = input.value;\n this.core?.store.getState().setSearchTerm(input.value);\n\n if (!this.autoSearch) {\n return;\n }\n\n this.performSearch();\n };\n\n private performSearch = async () => {\n this.error = false;\n\n try {\n await this.core?.store.getState().search();\n } catch (error) {\n this.error = true;\n }\n };\n\n handleClearInput = () => {\n this.core?.store.getState().resetSearchValues();\n this.error = false;\n };\n\n handleFormSubmit = async (event: Event) => {\n event.preventDefault();\n await this.performSearch();\n };\n\n render() {\n const isShowingClearButton = this.inputValue.length > 0;\n const inputGridClassNames = classNames('searchcraft-input-form-grid', {\n 'searchcraft-input-form-grid-button-left':\n this.buttonPlacement === 'left',\n 'searchcraft-input-form-grid-button-right':\n this.buttonPlacement === 'right',\n 'searchcraft-input-form-grid-button-none':\n this.buttonPlacement === 'none',\n });\n const shouldHaveVerticalGap = this.inputLabel || this.error;\n const inputGridStyles = {\n gap: shouldHaveVerticalGap ? '4px 8px' : '0px 8px',\n };\n return (\n <form class='searchcraft-input-form' onSubmit={this.handleFormSubmit}>\n <div class={inputGridClassNames} style={inputGridStyles}>\n <div class='searchcraft-input-form-button'>\n <searchcraft-button\n onButtonClick={this.handleFormSubmit}\n label={this.buttonLabel}\n />\n </div>\n {this.inputLabel && (\n <div class='searchcraft-input-form-label'>\n <searchcraft-input-label label={this.inputLabel} />\n </div>\n )}\n {this.error && (\n <div class='searchcraft-input-form-error-message'>\n <searchcraft-error-message>\n Something went wrong.\n </searchcraft-error-message>\n </div>\n )}\n <div class='searchcraft-input-form-input-wrapper'>\n <input\n autoComplete='off'\n class={classNames('searchcraft-input-form-input', {\n 'searchcraft-placeholder-hide-on-focus':\n this.placeholderBehavior === 'hide-on-focus',\n })}\n onFocus={() => this.inputFocus?.emit()}\n onBlur={() => this.inputBlur?.emit()}\n onInput={(event) => {\n this.handleInput(event);\n }}\n placeholder={this.placeholderValue}\n type='text'\n value={this.inputValue}\n />\n <div class='searchcraft-input-form-input-icon'>\n <svg\n class='searchcraft-input-form-input-search-icon'\n viewBox='0 0 20 20'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n aria-labelledby='searchcraft-title'\n >\n <title>Search icon</title>\n <path\n d='M17.5 17.5L13.875 13.875M15.8333 9.16667C15.8333 12.8486 12.8486 15.8333 9.16667 15.8333C5.48477 15.8333 2.5 12.8486 2.5 9.16667C2.5 5.48477 5.48477 2.5 9.16667 2.5C12.8486 2.5 15.8333 5.48477 15.8333 9.16667Z'\n stroke='currentColor'\n stroke-width='1.5'\n stroke-linecap='round'\n stroke-linejoin='round'\n />\n </svg>\n </div>\n {isShowingClearButton && (\n <button\n type='button'\n class='searchcraft-input-form-clear-button'\n onClick={this.handleClearInput}\n >\n <svg\n class='searchcraft-input-form-clear-icon'\n viewBox='0 0 22 22'\n fill='none'\n xmlns='http://www.w3.org/2000/svg'\n aria-labelledby='icon-title'\n >\n <title>Clear icon</title>\n <path\n d='M14 8L8 14M8 8L14 14M21 11C21 16.5228 16.5228 21 11 21C5.47715 21 1 16.5228 1 11C1 5.47715 5.47715 1 11 1C16.5228 1 21 5.47715 21 11Z'\n stroke='currentColor'\n stroke-width='1.5'\n stroke-linecap='round'\n stroke-linejoin='round'\n />\n </svg>\n </button>\n )}\n </div>\n </div>\n </form>\n );\n }\n}\n"],"version":3}