@searchcraft/javascript-sdk 0.12.0 → 0.12.2

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 (35) hide show
  1. package/README.md +1 -1
  2. package/dist/components/index.d.ts +22 -0
  3. package/dist/components/index.js +136 -17
  4. package/dist/components/index.js.map +1 -1
  5. package/dist/components/{p-b7e99386.js → p-870f81fd.js} +38 -6
  6. package/dist/components/p-870f81fd.js.map +1 -0
  7. package/dist/components/{p-0c495408.js → p-e8d97093.js} +110 -37
  8. package/dist/components/p-e8d97093.js.map +1 -0
  9. package/dist/components/searchcraft-facet-list.js +1 -1
  10. package/dist/components/searchcraft-filter-panel.js +3 -3
  11. package/dist/components/searchcraft-filter-panel.js.map +1 -1
  12. package/dist/components/searchcraft-input-form.js +1 -1
  13. package/dist/components/searchcraft-pagination.js +8 -2
  14. package/dist/components/searchcraft-pagination.js.map +1 -1
  15. package/dist/components/searchcraft-popover-form.js +1 -1
  16. package/dist/components/searchcraft-results-info.js +9 -1
  17. package/dist/components/searchcraft-results-info.js.map +1 -1
  18. package/dist/components/searchcraft-search-results-per-page.js +8 -2
  19. package/dist/components/searchcraft-search-results-per-page.js.map +1 -1
  20. package/dist/hydrate/index.js +229 -105
  21. package/dist/hydrate/index.mjs +229 -105
  22. package/dist/types/classes/SearchcraftCore.d.ts +1 -1
  23. package/dist/types/components/searchcraft-facet-list/searchcraft-facet-list.d.ts +5 -1
  24. package/dist/types/components/searchcraft-filter-panel/searchcraft-filter-panel.d.ts +1 -1
  25. package/dist/types/components/searchcraft-input-form/searchcraft-input-form.d.ts +5 -0
  26. package/dist/types/components/searchcraft-pagination/searchcraft-pagination.d.ts +1 -0
  27. package/dist/types/components/searchcraft-results-info/searchcraft-results-info.d.ts +1 -0
  28. package/dist/types/components/searchcraft-search-results-per-page/searchcraft-search-results-per-page.d.ts +1 -0
  29. package/dist/types/components.d.ts +16 -0
  30. package/dist/types/store/SearchcraftStore.types.d.ts +6 -1
  31. package/dist/types/types/sdk-types/searchcraft-filter-panel.types.d.ts +1 -0
  32. package/dist/types/utils/facets.d.ts +5 -1
  33. package/package.json +4 -3
  34. package/dist/components/p-0c495408.js.map +0 -1
  35. package/dist/components/p-b7e99386.js.map +0 -1
@@ -2555,6 +2555,65 @@ class SearchcraftErrorMessage {
2555
2555
  }; }
2556
2556
  }
2557
2557
 
2558
+ /**
2559
+ * This is the default instance id for searchcraft core instances.
2560
+ * When no id is specified in a component's props, use this one.
2561
+ */
2562
+ const DEFAULT_CORE_INSTANCE_ID = 'searchcraft';
2563
+ /**
2564
+ * CoreInstanceRegistry
2565
+ *
2566
+ * This class is responsible for managing all of the instances of SearchcraftCore on a page.
2567
+ * It provides a means for consuming components to use the instance of SearchcraftCore that
2568
+ * they need to use when that instance of core gets added to the Registry.
2569
+ */
2570
+ class CoreInstanceRegistry {
2571
+ coreInstances = {};
2572
+ subscriptions = {};
2573
+ /**
2574
+ * Adds a SearchcraftCore instance to the Registry.
2575
+ *
2576
+ * When the instance is added, iterates through the onAvailable callbacks
2577
+ * that have been subscribed via useCoreInstance.
2578
+ *
2579
+ * @param coreInstance The SearchcraftCore instance to add to the registry
2580
+ * @param searchcraftId The unique identifier for this SearchcraftCore instance.
2581
+ */
2582
+ addCoreInstance(coreInstance, searchcraftId) {
2583
+ const id = searchcraftId || DEFAULT_CORE_INSTANCE_ID;
2584
+ this.coreInstances[id] = coreInstance;
2585
+ for (const callback of this.subscriptions[id] || []) {
2586
+ callback(coreInstance);
2587
+ }
2588
+ }
2589
+ /**
2590
+ * Use the specified instance of SearchcraftCore. When the instance becomes available,
2591
+ * the onAvailable callback will be called.
2592
+ *
2593
+ * @param searchcraftId The SearchcraftCore instance to use.
2594
+ * @param onAvailable The callback that gets called when the core instance becomes available.
2595
+ */
2596
+ useCoreInstance(searchcraftId, onAvailable) {
2597
+ const id = searchcraftId || DEFAULT_CORE_INSTANCE_ID;
2598
+ // If the core instance already is available, call the onAvailable callback immediately.
2599
+ if (this.coreInstances[id]) {
2600
+ onAvailable(this.coreInstances[id]);
2601
+ return () => { };
2602
+ }
2603
+ // Add the callback to the collection of callbacks for this searchcraft instance.
2604
+ if (!this.subscriptions[id]) {
2605
+ this.subscriptions[id] = [];
2606
+ }
2607
+ this.subscriptions[id].push(onAvailable);
2608
+ return () => {
2609
+ if (this.subscriptions[id]) {
2610
+ this.subscriptions[id] = this.subscriptions[id].filter((cb) => cb !== onAvailable);
2611
+ }
2612
+ };
2613
+ }
2614
+ }
2615
+ const registry = new CoreInstanceRegistry();
2616
+
2558
2617
  /**
2559
2618
  * Helper function for getting a Node (FacetWithChildrenObject)
2560
2619
  * at a given path. Traverses the node tree to get the node.
@@ -2629,8 +2688,12 @@ const mergeFacetTrees = (currentTree, incomingTree) => {
2629
2688
  * It uses the `path` of each Facet to build the tree.
2630
2689
  *
2631
2690
  * @param facetWithChildArray
2691
+ * @param exclude - Optional array of facet values or paths to exclude from the tree.
2692
+ * - Values starting with "/" are treated as full paths and exclude the path and all children
2693
+ * (e.g., "/news" excludes "/news", "/news/local", "/news/national", etc.)
2694
+ * - Values without "/" are treated as segment names (e.g., "local" excludes all paths containing "local")
2632
2695
  */
2633
- const facetWithChildrenArrayToCompleteFacetTree = (rootArray) => {
2696
+ const facetWithChildrenArrayToCompleteFacetTree = (rootArray, exclude) => {
2634
2697
  // 1) Start with an empty tree at root "/"
2635
2698
  const tree = {
2636
2699
  path: '/',
@@ -2653,6 +2716,29 @@ const facetWithChildrenArrayToCompleteFacetTree = (rootArray) => {
2653
2716
  // 3) Insert each flat node into our tree, creating missing ancestors
2654
2717
  for (const { path, count } of allFacets) {
2655
2718
  const segments = path.split('/').filter(Boolean); // "/sports/outdoors" -> ["sports","outdoors"]
2719
+ // Skip this facet if it matches any excluded value
2720
+ if (exclude && exclude.length > 0) {
2721
+ let shouldExclude = false;
2722
+ for (const excludeValue of exclude) {
2723
+ if (excludeValue.startsWith('/')) {
2724
+ // Full path exclusion: prefix match (excludes the path and all children)
2725
+ if (path === excludeValue || path.startsWith(`${excludeValue}/`)) {
2726
+ shouldExclude = true;
2727
+ break;
2728
+ }
2729
+ }
2730
+ else {
2731
+ // Segment exclusion: check if any segment matches
2732
+ if (segments.includes(excludeValue)) {
2733
+ shouldExclude = true;
2734
+ break;
2735
+ }
2736
+ }
2737
+ }
2738
+ if (shouldExclude) {
2739
+ continue;
2740
+ }
2741
+ }
2656
2742
  let cursor = tree; // start at the root
2657
2743
  for (const segment of segments) {
2658
2744
  // Build the full path of this level
@@ -4215,65 +4301,6 @@ const html = (strings, ...values) => {
4215
4301
  return result || '';
4216
4302
  };
4217
4303
 
4218
- /**
4219
- * This is the default instance id for searchcraft core instances.
4220
- * When no id is specified in a component's props, use this one.
4221
- */
4222
- const DEFAULT_CORE_INSTANCE_ID = 'searchcraft';
4223
- /**
4224
- * CoreInstanceRegistry
4225
- *
4226
- * This class is responsible for managing all of the instances of SearchcraftCore on a page.
4227
- * It provides a means for consuming components to use the instance of SearchcraftCore that
4228
- * they need to use when that instance of core gets added to the Registry.
4229
- */
4230
- class CoreInstanceRegistry {
4231
- coreInstances = {};
4232
- subscriptions = {};
4233
- /**
4234
- * Adds a SearchcraftCore instance to the Registry.
4235
- *
4236
- * When the instance is added, iterates through the onAvailable callbacks
4237
- * that have been subscribed via useCoreInstance.
4238
- *
4239
- * @param coreInstance The SearchcraftCore instance to add to the registry
4240
- * @param searchcraftId The unique identifier for this SearchcraftCore instance.
4241
- */
4242
- addCoreInstance(coreInstance, searchcraftId) {
4243
- const id = searchcraftId || DEFAULT_CORE_INSTANCE_ID;
4244
- this.coreInstances[id] = coreInstance;
4245
- for (const callback of this.subscriptions[id] || []) {
4246
- callback(coreInstance);
4247
- }
4248
- }
4249
- /**
4250
- * Use the specified instance of SearchcraftCore. When the instance becomes available,
4251
- * the onAvailable callback will be called.
4252
- *
4253
- * @param searchcraftId The SearchcraftCore instance to use.
4254
- * @param onAvailable The callback that gets called when the core instance becomes available.
4255
- */
4256
- useCoreInstance(searchcraftId, onAvailable) {
4257
- const id = searchcraftId || DEFAULT_CORE_INSTANCE_ID;
4258
- // If the core instance already is available, call the onAvailable callback immediately.
4259
- if (this.coreInstances[id]) {
4260
- onAvailable(this.coreInstances[id]);
4261
- return () => { };
4262
- }
4263
- // Add the callback to the collection of callbacks for this searchcraft instance.
4264
- if (!this.subscriptions[id]) {
4265
- this.subscriptions[id] = [];
4266
- }
4267
- this.subscriptions[id].push(onAvailable);
4268
- return () => {
4269
- if (this.subscriptions[id]) {
4270
- this.subscriptions[id] = this.subscriptions[id].filter((cb) => cb !== onAvailable);
4271
- }
4272
- };
4273
- }
4274
- }
4275
- const registry = new CoreInstanceRegistry();
4276
-
4277
4304
  /**
4278
4305
  * 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.
4279
4306
  * It is consumed within the `searchcraft-filter-panel`.
@@ -4308,6 +4335,10 @@ class SearchcraftFacetList {
4308
4335
  * The name of the field where facets are applied.
4309
4336
  */
4310
4337
  fieldName = '';
4338
+ /**
4339
+ * Array of facet values to exclude from rendering.
4340
+ */
4341
+ exclude;
4311
4342
  /**
4312
4343
  * Emitted when the facets are updated.
4313
4344
  */
@@ -4362,7 +4393,7 @@ class SearchcraftFacetList {
4362
4393
  path: '/',
4363
4394
  count: 0,
4364
4395
  children: incomingFacetsWithChildrenArray || [],
4365
- });
4396
+ }, this.exclude);
4366
4397
  // Determine what action to take to accumulate items into the `facetTreeCollectedFromSearchResponse`.
4367
4398
  // This facet tree gets accumulated in different ways depending on what action type occured.
4368
4399
  switch (actionType) {
@@ -4386,7 +4417,7 @@ class SearchcraftFacetList {
4386
4417
  path: '/',
4387
4418
  count: 0,
4388
4419
  children: supplementalFacetsWithChildrenArray || [],
4389
- });
4420
+ }, this.exclude);
4390
4421
  this.facetTreeCollectedFromSearchResponse = mergeFacetTrees(supplementalFacetTree, incomingFacetTree);
4391
4422
  }
4392
4423
  else {
@@ -4428,7 +4459,7 @@ class SearchcraftFacetList {
4428
4459
  }
4429
4460
  }
4430
4461
  this.facetTreeFromFacetPathsNotInSearchResponse =
4431
- facetWithChildrenArrayToCompleteFacetTree(collectedFacetArray);
4462
+ facetWithChildrenArrayToCompleteFacetTree(collectedFacetArray, this.exclude);
4432
4463
  // Merges facetTreeCollectedFromSearchResponse with selectedFacetPathsNotInCurrentFacetTree.
4433
4464
  // This results in a single, final facet tree that gets rendered in as Checkboxes
4434
4465
  this.renderedFacetTree = deepMergeWithSpread(this.facetTreeFromFacetPathsNotInSearchResponse, this.facetTreeCollectedFromSearchResponse);
@@ -4436,45 +4467,86 @@ class SearchcraftFacetList {
4436
4467
  handleStateUpdate(_state) {
4437
4468
  const state = { ..._state };
4438
4469
  // Determine what action to take based on the current State
4439
- if (state.searchTerm.trim() === '') {
4470
+ // Check if this is an initialQuery case (string requestProperties with empty searchTerm)
4471
+ const isInitialQuery = typeof state.searchClientRequestProperties === 'string' &&
4472
+ state.searchTerm.trim() === '';
4473
+ if (state.searchTerm.trim() === '' && !isInitialQuery) {
4440
4474
  this.handleIncomingSearchResponse(state, 'SEARCH_TERM_EMPTY');
4441
4475
  this.lastSearchTerm = '';
4442
4476
  }
4443
4477
  else if (this.lastTimeTaken !== state.searchResponseTimeTaken &&
4444
- state.searchClientRequestProperties &&
4445
- typeof state.searchClientRequestProperties === 'object') {
4446
- const requestProperties = state.searchClientRequestProperties;
4447
- let actionType = 'UNKNOWN';
4448
- if (this.lastSearchTerm !== requestProperties.searchTerm) {
4449
- if (this.areAnyFacetPathsSelected) {
4450
- actionType = 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE';
4478
+ state.searchClientRequestProperties) {
4479
+ // Handle both object and string requestProperties (string is used for initialQuery)
4480
+ if (typeof state.searchClientRequestProperties === 'object') {
4481
+ const requestProperties = state.searchClientRequestProperties;
4482
+ let actionType = 'UNKNOWN';
4483
+ if (this.lastSearchTerm !== requestProperties.searchTerm) {
4484
+ if (this.areAnyFacetPathsSelected) {
4485
+ actionType = 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE';
4486
+ }
4487
+ else {
4488
+ actionType = 'NEW_SEARCH_TERM';
4489
+ }
4451
4490
  }
4452
- else {
4453
- actionType = 'NEW_SEARCH_TERM';
4491
+ else if (this.lastRangeValues !==
4492
+ JSON.stringify(requestProperties.rangeValueForIndexFields)) {
4493
+ actionType = 'RANGE_VALUE_UPDATE';
4454
4494
  }
4495
+ else if (this.lastFacetValues !==
4496
+ JSON.stringify(requestProperties.facetPathsForIndexFields)) {
4497
+ actionType = 'FACET_UPDATE';
4498
+ }
4499
+ else if (this.lastSortType !== requestProperties.order_by) {
4500
+ actionType = 'SORT_ORDER_UPDATE';
4501
+ }
4502
+ else if (this.lastSearchMode !== requestProperties.mode) {
4503
+ actionType = 'EXACT_MATCH_UPDATE';
4504
+ }
4505
+ this.lastRangeValues = JSON.stringify(requestProperties.rangeValueForIndexFields);
4506
+ this.lastFacetValues = JSON.stringify(requestProperties.facetPathsForIndexFields);
4507
+ this.lastSortType = requestProperties.order_by;
4508
+ this.lastSearchMode = requestProperties.mode;
4509
+ this.lastSearchTerm = requestProperties.searchTerm;
4510
+ this.lastTimeTaken = state.searchResponseTimeTaken;
4511
+ // Handle the incoming response, using the action we have determined.
4512
+ this.handleIncomingSearchResponse(state, actionType);
4455
4513
  }
4456
- else if (this.lastRangeValues !==
4457
- JSON.stringify(requestProperties.rangeValueForIndexFields)) {
4458
- actionType = 'RANGE_VALUE_UPDATE';
4459
- }
4460
- else if (this.lastFacetValues !==
4461
- JSON.stringify(requestProperties.facetPathsForIndexFields)) {
4462
- actionType = 'FACET_UPDATE';
4463
- }
4464
- else if (this.lastSortType !== requestProperties.order_by) {
4465
- actionType = 'SORT_ORDER_UPDATE';
4466
- }
4467
- else if (this.lastSearchMode !== requestProperties.mode) {
4468
- actionType = 'EXACT_MATCH_UPDATE';
4514
+ else if (typeof state.searchClientRequestProperties === 'string') {
4515
+ // Handle initialQuery case where requestProperties is a string
4516
+ // For initialQuery, searchTerm will be empty but we still want to show facets
4517
+ let actionType = 'NEW_SEARCH_TERM';
4518
+ // Parse the request to get facet and range filters from the query array
4519
+ const requestObj = JSON.parse(state.searchClientRequestProperties);
4520
+ const queryArray = Array.isArray(requestObj.query)
4521
+ ? requestObj.query
4522
+ : [requestObj.query];
4523
+ // Extract filter queries (those with occur: 'must')
4524
+ const filterQueries = queryArray.filter((q) => q.occur === 'must');
4525
+ const currentFilters = JSON.stringify(filterQueries);
4526
+ // Determine the action type based on what changed
4527
+ if (this.lastFacetValues !== undefined && this.lastFacetValues !== currentFilters) {
4528
+ // Filters have changed (not initial load)
4529
+ actionType = 'FACET_UPDATE';
4530
+ }
4531
+ else if (state.searchTerm.trim() === '' && this.lastSearchTerm === '') {
4532
+ // Initial load or no changes with empty search term
4533
+ actionType = 'NEW_SEARCH_TERM';
4534
+ }
4535
+ else if (this.lastSearchTerm !== state.searchTerm) {
4536
+ // User has typed a new search term after initialQuery
4537
+ if (this.areAnyFacetPathsSelected) {
4538
+ actionType = 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE';
4539
+ }
4540
+ else {
4541
+ actionType = 'NEW_SEARCH_TERM';
4542
+ }
4543
+ }
4544
+ this.lastFacetValues = currentFilters;
4545
+ this.lastSearchTerm = state.searchTerm;
4546
+ this.lastTimeTaken = state.searchResponseTimeTaken;
4547
+ // Handle the incoming response, using the action we have determined.
4548
+ this.handleIncomingSearchResponse(state, actionType);
4469
4549
  }
4470
- this.lastRangeValues = JSON.stringify(requestProperties.rangeValueForIndexFields);
4471
- this.lastFacetValues = JSON.stringify(requestProperties.facetPathsForIndexFields);
4472
- this.lastSortType = requestProperties.order_by;
4473
- this.lastSearchMode = requestProperties.mode;
4474
- this.lastSearchTerm = requestProperties.searchTerm;
4475
- this.lastTimeTaken = state.searchResponseTimeTaken;
4476
- // Handle the incoming response, using the action we have determined.
4477
- this.handleIncomingSearchResponse(state, actionType);
4478
4550
  }
4479
4551
  }
4480
4552
  onCoreAvailable(core) {
@@ -4569,6 +4641,7 @@ class SearchcraftFacetList {
4569
4641
  "$members$": {
4570
4642
  "searchcraftId": [1, "searchcraft-id"],
4571
4643
  "fieldName": [1, "field-name"],
4644
+ "exclude": [16],
4572
4645
  "selectedPaths": [32],
4573
4646
  "facetTreeCollectedFromSearchResponse": [32],
4574
4647
  "renderedFacetTree": [32]
@@ -4714,7 +4787,7 @@ class SearchcraftFilterPanel {
4714
4787
  * Iterate through `items` and render them based on `type`
4715
4788
  */
4716
4789
  render() {
4717
- return (hAsync("div", { key: 'b18a05516bea8d145d1ca015835d63fafbfc8bd8', class: 'searchcraft-filter-panel' }, this.items.map((filterItem) => {
4790
+ return (hAsync("div", { key: 'ee8974e38b296a1ba27111bc2a4244d8915f5839', class: 'searchcraft-filter-panel' }, this.items.map((filterItem) => {
4718
4791
  switch (filterItem.type) {
4719
4792
  case 'dateRange': {
4720
4793
  const item = filterItem;
@@ -4734,7 +4807,7 @@ class SearchcraftFilterPanel {
4734
4807
  case 'facets': {
4735
4808
  const item = filterItem;
4736
4809
  // return "filters-list"
4737
- return (hAsync("div", { class: 'searchcraft-filter-panel-section' }, hAsync("p", { class: 'searchcraft-filter-panel-label' }, filterItem.label), hAsync("searchcraft-facet-list", { fieldName: item.fieldName, onFacetSelectionUpdated: (event) => {
4810
+ return (hAsync("div", { class: 'searchcraft-filter-panel-section' }, hAsync("p", { class: 'searchcraft-filter-panel-label' }, filterItem.label), hAsync("searchcraft-facet-list", { fieldName: item.fieldName, exclude: item.options.exclude, onFacetSelectionUpdated: (event) => {
4738
4811
  this.handleFacetSelectionUpdated(item.fieldName, event.detail.paths);
4739
4812
  } })));
4740
4813
  }
@@ -4833,6 +4906,10 @@ class SearchcraftInputForm {
4833
4906
  * 'hide-on-text-entered' - Only hide the placeholder when the input form has text entered into it.
4834
4907
  */
4835
4908
  placeholderBehavior;
4909
+ /**
4910
+ * The value to display in the input field.
4911
+ */
4912
+ value;
4836
4913
  /**
4837
4914
  * When the input becomes focused.
4838
4915
  */
@@ -4853,18 +4930,41 @@ class SearchcraftInputForm {
4853
4930
  cleanupCore;
4854
4931
  init() {
4855
4932
  if (this.core) {
4933
+ // Initialize inputValue from prop if provided
4934
+ if (this.value !== undefined && this.value.trim().length > 0) {
4935
+ this.inputValue = this.value;
4936
+ this.core.store.getState().setSearchTerm(this.value);
4937
+ // Trigger search if autoSearch is enabled
4938
+ if (this.autoSearch) {
4939
+ this.core.store.getState().search();
4940
+ }
4941
+ }
4856
4942
  this.inputInit?.emit();
4857
4943
  }
4858
4944
  }
4859
4945
  onCoreChange() {
4860
4946
  this.init();
4861
4947
  }
4948
+ onValueChange(newValue) {
4949
+ if (newValue !== undefined && newValue !== this.inputValue) {
4950
+ this.inputValue = newValue;
4951
+ this.core?.store.getState().setSearchTerm(newValue);
4952
+ // Trigger search if autoSearch is enabled and value is not empty
4953
+ if (this.autoSearch && newValue.trim().length > 0) {
4954
+ this.core?.store.getState().search();
4955
+ }
4956
+ }
4957
+ }
4862
4958
  onCoreAvailable(core) {
4863
4959
  this.core = core;
4864
4960
  this.init();
4865
4961
  this.unsubscribe = core.store.subscribe((state) => {
4866
4962
  this.searchTerm = state.searchTerm;
4867
- this.inputValue = state.searchTerm;
4963
+ // Only update inputValue from store if value prop is not set
4964
+ // OR if the store was cleared (empty string)
4965
+ if (this.value === undefined || state.searchTerm === '') {
4966
+ this.inputValue = state.searchTerm;
4967
+ }
4868
4968
  });
4869
4969
  }
4870
4970
  connectedCallback() {
@@ -4893,6 +4993,8 @@ class SearchcraftInputForm {
4893
4993
  }
4894
4994
  };
4895
4995
  handleClearInput = () => {
4996
+ // Clear the input value even if controlled by prop
4997
+ this.inputValue = '';
4896
4998
  this.core?.store.getState().resetSearchValues();
4897
4999
  this.error = false;
4898
5000
  };
@@ -4911,14 +5013,15 @@ class SearchcraftInputForm {
4911
5013
  const inputGridStyles = {
4912
5014
  gap: shouldHaveVerticalGap ? '4px 8px' : '0px 8px',
4913
5015
  };
4914
- return (hAsync("form", { key: 'c1eea324038f640a9075d5714378d5c4b97168e0', class: 'searchcraft-input-form', onSubmit: this.handleFormSubmit }, hAsync("div", { key: 'f157c00510e5c3e75dd703996be24de5e97bbcd9', class: inputGridClassNames, style: inputGridStyles }, hAsync("div", { key: 'c97f3e5ef9ed6aee103dedc76b3ee1620b69ebba', class: 'searchcraft-input-form-button' }, hAsync("searchcraft-button", { key: '4bb5dfea8b9f8f2f0a7e5fc5c1b199ef9d209278', onButtonClick: this.handleFormSubmit, label: this.buttonLabel })), this.inputLabel && (hAsync("div", { key: 'aa8beca21ce414d645687ee73b7ca29c740438a2', class: 'searchcraft-input-form-label' }, hAsync("searchcraft-input-label", { key: '8c15364abcf2e43354b445be6c7ceb9387ea4a67', label: this.inputLabel }))), this.error && (hAsync("div", { key: '5987b6da22a25da50613ceb277bfe44b31ba8f37', class: 'searchcraft-input-form-error-message' }, hAsync("searchcraft-error-message", { key: 'f2a230f0cf3cf0bbaddbb37ef2f38afdf73b28f6' }, "Something went wrong."))), hAsync("div", { key: 'a0862217135ac6f9a96d9e64e6fca5f772eb8f51', class: 'searchcraft-input-form-input-wrapper' }, hAsync("input", { key: '7071be386f0c73a0230e0815640b134ee5139262', autoComplete: 'off', class: classNames('searchcraft-input-form-input', {
5016
+ return (hAsync("form", { key: 'd214ace44e9209154d215e803de088aefa58a285', class: 'searchcraft-input-form', onSubmit: this.handleFormSubmit }, hAsync("div", { key: '5699f5dca28caf5e9584401f1883d2e08d26e3ec', class: inputGridClassNames, style: inputGridStyles }, hAsync("div", { key: 'ef792a946414a680e9c99c145246d00b9b8f2ffb', class: 'searchcraft-input-form-button' }, hAsync("searchcraft-button", { key: 'ba5a8cb98889bb486781af4915a21c94a0b1498a', onButtonClick: this.handleFormSubmit, label: this.buttonLabel })), this.inputLabel && (hAsync("div", { key: 'a9e770ef967f7ab1c6ddf8f87f23cea509894536', class: 'searchcraft-input-form-label' }, hAsync("searchcraft-input-label", { key: '93b29e630e71a3c7724921aa9586aab76e592f4f', label: this.inputLabel }))), this.error && (hAsync("div", { key: '641ef4f468d527c24a1635d49dcbbba03030686f', class: 'searchcraft-input-form-error-message' }, hAsync("searchcraft-error-message", { key: '2d839d17b702fe1b41d7e49aacfc52fb53315766' }, "Something went wrong."))), hAsync("div", { key: 'af0c73478de21447c992bd0037ba007d54f53a86', class: 'searchcraft-input-form-input-wrapper' }, hAsync("input", { key: '3de1be1aa71c143b58cd6080d422410bd400e4e5', autoComplete: 'off', class: classNames('searchcraft-input-form-input', {
4915
5017
  'searchcraft-placeholder-hide-on-focus': this.placeholderBehavior === 'hide-on-focus',
4916
5018
  }), onFocus: () => this.inputFocus?.emit(), onBlur: () => this.inputBlur?.emit(), onInput: (event) => {
4917
5019
  this.handleInput(event);
4918
- }, placeholder: this.placeholderValue, type: 'text', value: this.inputValue }), hAsync("div", { key: '178a7a21a84f012662312dc2b9145fff0aec6a44', class: 'searchcraft-input-form-input-icon' }, hAsync("svg", { key: '7fb86586c155f7075fb65280482eb2ab5ff8a9db', class: 'searchcraft-input-form-input-search-icon', viewBox: '0 0 20 20', fill: 'none', xmlns: 'http://www.w3.org/2000/svg', "aria-labelledby": 'searchcraft-title' }, hAsync("title", { key: '0a48667010f2c998917271f941877c5ec826329f' }, "Search icon"), hAsync("path", { key: '94c54dfa1406bdc6c2f87f3b31e1b01862b58e08', 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', stroke: 'currentColor', "stroke-width": '1.5', "stroke-linecap": 'round', "stroke-linejoin": 'round' }))), isShowingClearButton && (hAsync("button", { key: '931fc5e8842de1e8f3bab3fa163261c54c24148c', type: 'button', class: 'searchcraft-input-form-clear-button', onClick: this.handleClearInput }, hAsync("svg", { key: '0676b050222eb9a7bf2f7c7c112ae40c0644ecf7', class: 'searchcraft-input-form-clear-icon', viewBox: '0 0 22 22', fill: 'none', xmlns: 'http://www.w3.org/2000/svg', "aria-labelledby": 'icon-title' }, hAsync("title", { key: '002b23596bc977b5a942776e4f7b513db4584361' }, "Clear icon"), hAsync("path", { key: '05346b8f1ede39b9e1924760f400df10d8b0aa49', 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', stroke: 'currentColor', "stroke-width": '1.5', "stroke-linecap": 'round', "stroke-linejoin": 'round' }))))))));
5020
+ }, placeholder: this.placeholderValue, type: 'text', value: this.inputValue }), hAsync("div", { key: 'fe9043c046e3b1b91129299f0860919ba8a8416b', class: 'searchcraft-input-form-input-icon' }, hAsync("svg", { key: '31ae1553cd214d5e2f97c9e3699862dff51a0916', class: 'searchcraft-input-form-input-search-icon', viewBox: '0 0 20 20', fill: 'none', xmlns: 'http://www.w3.org/2000/svg', "aria-labelledby": 'searchcraft-title' }, hAsync("title", { key: '9db677da65283ff15b0d4e79b5d9daf89637b33f' }, "Search icon"), hAsync("path", { key: '2a002eae6ed3725a432e7c3e4649c0bd2ffff7a0', 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', stroke: 'currentColor', "stroke-width": '1.5', "stroke-linecap": 'round', "stroke-linejoin": 'round' }))), isShowingClearButton && (hAsync("button", { key: 'b7e92b22c3234eb31d85b0aa98d7c682b2fc0021', type: 'button', class: 'searchcraft-input-form-clear-button', onClick: this.handleClearInput }, hAsync("svg", { key: 'bfbeb742f197da0cac6dd5df2627db9df5349207', class: 'searchcraft-input-form-clear-icon', viewBox: '0 0 22 22', fill: 'none', xmlns: 'http://www.w3.org/2000/svg', "aria-labelledby": 'icon-title' }, hAsync("title", { key: 'c62b9d237b3762609fed72e0520322fb5eabe979' }, "Clear icon"), hAsync("path", { key: '198a13760ce8b076ef8e791dec933b210ff3017a', 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', stroke: 'currentColor', "stroke-width": '1.5', "stroke-linecap": 'round', "stroke-linejoin": 'round' }))))))));
4919
5021
  }
4920
5022
  static get watchers() { return {
4921
- "core": ["onCoreChange"]
5023
+ "core": ["onCoreChange"],
5024
+ "value": ["onValueChange"]
4922
5025
  }; }
4923
5026
  static get cmpMeta() { return {
4924
5027
  "$flags$": 0,
@@ -4931,6 +5034,7 @@ class SearchcraftInputForm {
4931
5034
  "inputLabel": [1, "input-label"],
4932
5035
  "placeholderValue": [1, "placeholder-value"],
4933
5036
  "placeholderBehavior": [1, "placeholder-behavior"],
5037
+ "value": [1],
4934
5038
  "inputValue": [32],
4935
5039
  "searchTerm": [32],
4936
5040
  "error": [32]
@@ -5042,6 +5146,7 @@ class SearchcraftPagination {
5042
5146
  searchResultsPerPage;
5043
5147
  searchResultsPage;
5044
5148
  searchResultsCount;
5149
+ searchClientRequestProperties;
5045
5150
  // local vars
5046
5151
  searchResultsPagesCount = 1;
5047
5152
  searchResultsRangeMin = 1;
@@ -5057,6 +5162,7 @@ class SearchcraftPagination {
5057
5162
  this.searchResultsPerPage = state.searchResultsPerPage;
5058
5163
  this.searchResultsPage = state.searchResultsPage;
5059
5164
  this.searchResultsCount = state.searchResultsCount;
5165
+ this.searchClientRequestProperties = state.searchClientRequestProperties;
5060
5166
  // local vars
5061
5167
  this.searchResultsPagesCount = Math.ceil(this.searchResultsCount / this.searchResultsPerPage);
5062
5168
  this.searchResultsRangeMin =
@@ -5116,8 +5222,11 @@ class SearchcraftPagination {
5116
5222
  return (hAsync("li", null, hAsync("span", { class: 'searchcraft-pagination-item searchcraft-pagination-item-active' }, this.searchResultsPage)));
5117
5223
  }
5118
5224
  render() {
5119
- // early return if there isn't a searchTerm or there is 1 or fewer pages of results
5120
- if (!this.searchTerm || this.searchResultsPagesCount <= 1) {
5225
+ // Check if this is an initialQuery case (string requestProperties with empty searchTerm)
5226
+ const isInitialQuery = typeof this.searchClientRequestProperties === 'string' &&
5227
+ this.searchTerm.trim() === '';
5228
+ // early return if there isn't a searchTerm (unless it's initialQuery) or there is 1 or fewer pages of results
5229
+ if ((!this.searchTerm && !isInitialQuery) || this.searchResultsPagesCount <= 1) {
5121
5230
  return;
5122
5231
  }
5123
5232
  return (hAsync("div", { class: 'searchcraft-pagination' }, hAsync("div", { class: 'searchcraft-pagination-control' }, hAsync("searchcraft-button", { disabled: this.searchResultsPage === 1, hierarchy: 'tertiary', onButtonClick: () => this.handleGoToPage(Math.max(1, this.searchResultsPage - 1)), label: 'Previous', iconPosition: 'left', icon: hAsync("svg", { class: 'searchcraft-button-icon', width: '20', height: '20', viewBox: '0 0 20 20', fill: 'none', xmlns: 'http://www.w3.org/2000/svg' }, hAsync("title", null, "Previous page icon"), hAsync("path", { d: 'M12.5 15L7.5 10L12.5 5', stroke: 'currentColor', "stroke-width": '1.5', "stroke-linecap": 'round', "stroke-linejoin": 'round' })), iconOnly: true })), hAsync("ul", { class: 'searchcraft-pagination-list' }, this.renderOddPaginationItem(1), this.renderEvenPaginationItem(2), this.renderMiddlePaginationItem(), this.renderEvenPaginationItem(this.searchResultsPagesCount > 4
@@ -5135,6 +5244,7 @@ class SearchcraftPagination {
5135
5244
  "searchResultsPerPage": [32],
5136
5245
  "searchResultsPage": [32],
5137
5246
  "searchResultsCount": [32],
5247
+ "searchClientRequestProperties": [32],
5138
5248
  "searchResultsPagesCount": [32],
5139
5249
  "searchResultsRangeMin": [32],
5140
5250
  "searchResultsRangeMax": [32],
@@ -6158,6 +6268,7 @@ class SearchcraftResultsInfo {
6158
6268
  searchResultsPage;
6159
6269
  searchResultsPerPage;
6160
6270
  searchResultsCount;
6271
+ searchClientRequestProperties;
6161
6272
  // local vars
6162
6273
  count = 0;
6163
6274
  range = [0, 0];
@@ -6171,6 +6282,7 @@ class SearchcraftResultsInfo {
6171
6282
  this.searchResultsPage = state.searchResultsPage;
6172
6283
  this.searchResultsPerPage = state.searchResultsPerPage;
6173
6284
  this.searchResultsCount = state.searchResultsCount;
6285
+ this.searchClientRequestProperties = state.searchClientRequestProperties;
6174
6286
  // local vars
6175
6287
  this.count = this.searchResultsCount;
6176
6288
  this.range[0] =
@@ -6193,7 +6305,12 @@ class SearchcraftResultsInfo {
6193
6305
  this.cleanupCore?.();
6194
6306
  }
6195
6307
  render() {
6196
- if (!this.searchTerm || this.searchResultsCount === 0) {
6308
+ // Check if this is an initialQuery case (string requestProperties with empty searchTerm)
6309
+ const isInitialQuery = typeof this.searchClientRequestProperties === 'string' &&
6310
+ this.searchTerm.trim() === '';
6311
+ // Only hide if there's no search term AND no initialQuery AND no results
6312
+ if ((!this.searchTerm && !isInitialQuery) ||
6313
+ this.searchResultsCount === 0) {
6197
6314
  return null;
6198
6315
  }
6199
6316
  return (hAsync("p", { class: 'searchcraft-results-info' }, typeof this.template !== 'undefined'
@@ -6214,6 +6331,7 @@ class SearchcraftResultsInfo {
6214
6331
  "searchResultsPage": [32],
6215
6332
  "searchResultsPerPage": [32],
6216
6333
  "searchResultsCount": [32],
6334
+ "searchClientRequestProperties": [32],
6217
6335
  "count": [32],
6218
6336
  "range": [32],
6219
6337
  "responseTime": [32]
@@ -6588,6 +6706,7 @@ class SearchcraftSearchResultsPerPage {
6588
6706
  searchResultsPerPage;
6589
6707
  searchResultsCount;
6590
6708
  searchResultsPagesCount;
6709
+ searchClientRequestProperties;
6591
6710
  // local vars
6592
6711
  initialSearchResultsPerPage;
6593
6712
  // store functions
@@ -6602,6 +6721,7 @@ class SearchcraftSearchResultsPerPage {
6602
6721
  this.searchResultsPerPage = state.searchResultsPerPage;
6603
6722
  this.searchResultsPage = state.searchResultsPage;
6604
6723
  this.searchResultsCount = state.searchResultsCount;
6724
+ this.searchClientRequestProperties = state.searchClientRequestProperties;
6605
6725
  // local vars
6606
6726
  this.searchResultsPagesCount = Math.ceil(this.searchResultsCount / this.searchResultsPerPage);
6607
6727
  // store functions
@@ -6619,8 +6739,11 @@ class SearchcraftSearchResultsPerPage {
6619
6739
  this.cleanupCore?.();
6620
6740
  }
6621
6741
  render() {
6622
- // early return if there isn't a searchTerm or there is 1 or fewer pages of results
6623
- if (!this.searchTerm || this.searchResultsPagesCount <= 1) {
6742
+ // Check if this is an initialQuery case (string requestProperties with empty searchTerm)
6743
+ const isInitialQuery = typeof this.searchClientRequestProperties === 'string' &&
6744
+ this.searchTerm.trim() === '';
6745
+ // early return if there isn't a searchTerm (unless it's initialQuery) or there is 1 or fewer pages of results
6746
+ if ((!this.searchTerm && !isInitialQuery) || this.searchResultsPagesCount <= 1) {
6624
6747
  return;
6625
6748
  }
6626
6749
  return (hAsync("div", { class: 'searchcraft-search-results-per-page' }, hAsync("div", { class: 'searchcraft-search-results-per-page-select' }, hAsync("label", { class: 'searchcraft-search-results-per-page-select-label', htmlFor: 'searchcraft-search-results-per-page-select-input' }, "Results Per Page"), hAsync("div", { class: 'searchcraft-search-results-per-page-select-input' }, hAsync("searchcraft-select", { inputId: 'searchcraft-search-results-per-page-select-input', name: 'results-per-page', options: [...Array(5)].map((_, index) => {
@@ -6646,6 +6769,7 @@ class SearchcraftSearchResultsPerPage {
6646
6769
  "searchResultsPerPage": [32],
6647
6770
  "searchResultsCount": [32],
6648
6771
  "searchResultsPagesCount": [32],
6772
+ "searchClientRequestProperties": [32],
6649
6773
  "initialSearchResultsPerPage": [32],
6650
6774
  "setSearchResultsPerPage": [32],
6651
6775
  "setSearchResultsPage": [32]
@@ -1,5 +1,5 @@
1
1
  import { type AdClient, MeasureClient, SearchClient } from "../clients/index";
2
- import type { AdClientResponseItem, SearchcraftConfig, SearchcraftSDKInfo, SubscriptionEventName, SubscriptionEventCallback, SubscriptionEventMap, UnsubscribeFunction, SearchClientRequestProperties } from "../types/index";
2
+ import type { AdClientResponseItem, SearchClientRequestProperties, SearchcraftConfig, SearchcraftSDKInfo, SubscriptionEventCallback, SubscriptionEventMap, SubscriptionEventName, UnsubscribeFunction } from "../types/index";
3
3
  import { type SearchcraftStore } from "../store/index";
4
4
  /**
5
5
  * Javascript Class providing the functionality to interact with the Searchcraft BE
@@ -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.
@@ -33,6 +33,10 @@ export declare class SearchcraftFacetList {
33
33
  * The name of the field where facets are applied.
34
34
  */
35
35
  fieldName: string;
36
+ /**
37
+ * Array of facet values to exclude from rendering.
38
+ */
39
+ exclude?: string[];
36
40
  /**
37
41
  * Emitted when the facets are updated.
38
42
  */
@@ -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;
@@ -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;