@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
@@ -2559,6 +2559,65 @@ class SearchcraftErrorMessage {
2559
2559
  }; }
2560
2560
  }
2561
2561
 
2562
+ /**
2563
+ * This is the default instance id for searchcraft core instances.
2564
+ * When no id is specified in a component's props, use this one.
2565
+ */
2566
+ const DEFAULT_CORE_INSTANCE_ID = 'searchcraft';
2567
+ /**
2568
+ * CoreInstanceRegistry
2569
+ *
2570
+ * This class is responsible for managing all of the instances of SearchcraftCore on a page.
2571
+ * It provides a means for consuming components to use the instance of SearchcraftCore that
2572
+ * they need to use when that instance of core gets added to the Registry.
2573
+ */
2574
+ class CoreInstanceRegistry {
2575
+ coreInstances = {};
2576
+ subscriptions = {};
2577
+ /**
2578
+ * Adds a SearchcraftCore instance to the Registry.
2579
+ *
2580
+ * When the instance is added, iterates through the onAvailable callbacks
2581
+ * that have been subscribed via useCoreInstance.
2582
+ *
2583
+ * @param coreInstance The SearchcraftCore instance to add to the registry
2584
+ * @param searchcraftId The unique identifier for this SearchcraftCore instance.
2585
+ */
2586
+ addCoreInstance(coreInstance, searchcraftId) {
2587
+ const id = searchcraftId || DEFAULT_CORE_INSTANCE_ID;
2588
+ this.coreInstances[id] = coreInstance;
2589
+ for (const callback of this.subscriptions[id] || []) {
2590
+ callback(coreInstance);
2591
+ }
2592
+ }
2593
+ /**
2594
+ * Use the specified instance of SearchcraftCore. When the instance becomes available,
2595
+ * the onAvailable callback will be called.
2596
+ *
2597
+ * @param searchcraftId The SearchcraftCore instance to use.
2598
+ * @param onAvailable The callback that gets called when the core instance becomes available.
2599
+ */
2600
+ useCoreInstance(searchcraftId, onAvailable) {
2601
+ const id = searchcraftId || DEFAULT_CORE_INSTANCE_ID;
2602
+ // If the core instance already is available, call the onAvailable callback immediately.
2603
+ if (this.coreInstances[id]) {
2604
+ onAvailable(this.coreInstances[id]);
2605
+ return () => { };
2606
+ }
2607
+ // Add the callback to the collection of callbacks for this searchcraft instance.
2608
+ if (!this.subscriptions[id]) {
2609
+ this.subscriptions[id] = [];
2610
+ }
2611
+ this.subscriptions[id].push(onAvailable);
2612
+ return () => {
2613
+ if (this.subscriptions[id]) {
2614
+ this.subscriptions[id] = this.subscriptions[id].filter((cb) => cb !== onAvailable);
2615
+ }
2616
+ };
2617
+ }
2618
+ }
2619
+ const registry = new CoreInstanceRegistry();
2620
+
2562
2621
  /**
2563
2622
  * Helper function for getting a Node (FacetWithChildrenObject)
2564
2623
  * at a given path. Traverses the node tree to get the node.
@@ -2633,8 +2692,12 @@ const mergeFacetTrees = (currentTree, incomingTree) => {
2633
2692
  * It uses the `path` of each Facet to build the tree.
2634
2693
  *
2635
2694
  * @param facetWithChildArray
2695
+ * @param exclude - Optional array of facet values or paths to exclude from the tree.
2696
+ * - Values starting with "/" are treated as full paths and exclude the path and all children
2697
+ * (e.g., "/news" excludes "/news", "/news/local", "/news/national", etc.)
2698
+ * - Values without "/" are treated as segment names (e.g., "local" excludes all paths containing "local")
2636
2699
  */
2637
- const facetWithChildrenArrayToCompleteFacetTree = (rootArray) => {
2700
+ const facetWithChildrenArrayToCompleteFacetTree = (rootArray, exclude) => {
2638
2701
  // 1) Start with an empty tree at root "/"
2639
2702
  const tree = {
2640
2703
  path: '/',
@@ -2657,6 +2720,29 @@ const facetWithChildrenArrayToCompleteFacetTree = (rootArray) => {
2657
2720
  // 3) Insert each flat node into our tree, creating missing ancestors
2658
2721
  for (const { path, count } of allFacets) {
2659
2722
  const segments = path.split('/').filter(Boolean); // "/sports/outdoors" -> ["sports","outdoors"]
2723
+ // Skip this facet if it matches any excluded value
2724
+ if (exclude && exclude.length > 0) {
2725
+ let shouldExclude = false;
2726
+ for (const excludeValue of exclude) {
2727
+ if (excludeValue.startsWith('/')) {
2728
+ // Full path exclusion: prefix match (excludes the path and all children)
2729
+ if (path === excludeValue || path.startsWith(`${excludeValue}/`)) {
2730
+ shouldExclude = true;
2731
+ break;
2732
+ }
2733
+ }
2734
+ else {
2735
+ // Segment exclusion: check if any segment matches
2736
+ if (segments.includes(excludeValue)) {
2737
+ shouldExclude = true;
2738
+ break;
2739
+ }
2740
+ }
2741
+ }
2742
+ if (shouldExclude) {
2743
+ continue;
2744
+ }
2745
+ }
2660
2746
  let cursor = tree; // start at the root
2661
2747
  for (const segment of segments) {
2662
2748
  // Build the full path of this level
@@ -4219,65 +4305,6 @@ const html = (strings, ...values) => {
4219
4305
  return result || '';
4220
4306
  };
4221
4307
 
4222
- /**
4223
- * This is the default instance id for searchcraft core instances.
4224
- * When no id is specified in a component's props, use this one.
4225
- */
4226
- const DEFAULT_CORE_INSTANCE_ID = 'searchcraft';
4227
- /**
4228
- * CoreInstanceRegistry
4229
- *
4230
- * This class is responsible for managing all of the instances of SearchcraftCore on a page.
4231
- * It provides a means for consuming components to use the instance of SearchcraftCore that
4232
- * they need to use when that instance of core gets added to the Registry.
4233
- */
4234
- class CoreInstanceRegistry {
4235
- coreInstances = {};
4236
- subscriptions = {};
4237
- /**
4238
- * Adds a SearchcraftCore instance to the Registry.
4239
- *
4240
- * When the instance is added, iterates through the onAvailable callbacks
4241
- * that have been subscribed via useCoreInstance.
4242
- *
4243
- * @param coreInstance The SearchcraftCore instance to add to the registry
4244
- * @param searchcraftId The unique identifier for this SearchcraftCore instance.
4245
- */
4246
- addCoreInstance(coreInstance, searchcraftId) {
4247
- const id = searchcraftId || DEFAULT_CORE_INSTANCE_ID;
4248
- this.coreInstances[id] = coreInstance;
4249
- for (const callback of this.subscriptions[id] || []) {
4250
- callback(coreInstance);
4251
- }
4252
- }
4253
- /**
4254
- * Use the specified instance of SearchcraftCore. When the instance becomes available,
4255
- * the onAvailable callback will be called.
4256
- *
4257
- * @param searchcraftId The SearchcraftCore instance to use.
4258
- * @param onAvailable The callback that gets called when the core instance becomes available.
4259
- */
4260
- useCoreInstance(searchcraftId, onAvailable) {
4261
- const id = searchcraftId || DEFAULT_CORE_INSTANCE_ID;
4262
- // If the core instance already is available, call the onAvailable callback immediately.
4263
- if (this.coreInstances[id]) {
4264
- onAvailable(this.coreInstances[id]);
4265
- return () => { };
4266
- }
4267
- // Add the callback to the collection of callbacks for this searchcraft instance.
4268
- if (!this.subscriptions[id]) {
4269
- this.subscriptions[id] = [];
4270
- }
4271
- this.subscriptions[id].push(onAvailable);
4272
- return () => {
4273
- if (this.subscriptions[id]) {
4274
- this.subscriptions[id] = this.subscriptions[id].filter((cb) => cb !== onAvailable);
4275
- }
4276
- };
4277
- }
4278
- }
4279
- const registry = new CoreInstanceRegistry();
4280
-
4281
4308
  /**
4282
4309
  * 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.
4283
4310
  * It is consumed within the `searchcraft-filter-panel`.
@@ -4312,6 +4339,10 @@ class SearchcraftFacetList {
4312
4339
  * The name of the field where facets are applied.
4313
4340
  */
4314
4341
  fieldName = '';
4342
+ /**
4343
+ * Array of facet values to exclude from rendering.
4344
+ */
4345
+ exclude;
4315
4346
  /**
4316
4347
  * Emitted when the facets are updated.
4317
4348
  */
@@ -4366,7 +4397,7 @@ class SearchcraftFacetList {
4366
4397
  path: '/',
4367
4398
  count: 0,
4368
4399
  children: incomingFacetsWithChildrenArray || [],
4369
- });
4400
+ }, this.exclude);
4370
4401
  // Determine what action to take to accumulate items into the `facetTreeCollectedFromSearchResponse`.
4371
4402
  // This facet tree gets accumulated in different ways depending on what action type occured.
4372
4403
  switch (actionType) {
@@ -4390,7 +4421,7 @@ class SearchcraftFacetList {
4390
4421
  path: '/',
4391
4422
  count: 0,
4392
4423
  children: supplementalFacetsWithChildrenArray || [],
4393
- });
4424
+ }, this.exclude);
4394
4425
  this.facetTreeCollectedFromSearchResponse = mergeFacetTrees(supplementalFacetTree, incomingFacetTree);
4395
4426
  }
4396
4427
  else {
@@ -4432,7 +4463,7 @@ class SearchcraftFacetList {
4432
4463
  }
4433
4464
  }
4434
4465
  this.facetTreeFromFacetPathsNotInSearchResponse =
4435
- facetWithChildrenArrayToCompleteFacetTree(collectedFacetArray);
4466
+ facetWithChildrenArrayToCompleteFacetTree(collectedFacetArray, this.exclude);
4436
4467
  // Merges facetTreeCollectedFromSearchResponse with selectedFacetPathsNotInCurrentFacetTree.
4437
4468
  // This results in a single, final facet tree that gets rendered in as Checkboxes
4438
4469
  this.renderedFacetTree = deepMergeWithSpread(this.facetTreeFromFacetPathsNotInSearchResponse, this.facetTreeCollectedFromSearchResponse);
@@ -4440,45 +4471,86 @@ class SearchcraftFacetList {
4440
4471
  handleStateUpdate(_state) {
4441
4472
  const state = { ..._state };
4442
4473
  // Determine what action to take based on the current State
4443
- if (state.searchTerm.trim() === '') {
4474
+ // Check if this is an initialQuery case (string requestProperties with empty searchTerm)
4475
+ const isInitialQuery = typeof state.searchClientRequestProperties === 'string' &&
4476
+ state.searchTerm.trim() === '';
4477
+ if (state.searchTerm.trim() === '' && !isInitialQuery) {
4444
4478
  this.handleIncomingSearchResponse(state, 'SEARCH_TERM_EMPTY');
4445
4479
  this.lastSearchTerm = '';
4446
4480
  }
4447
4481
  else if (this.lastTimeTaken !== state.searchResponseTimeTaken &&
4448
- state.searchClientRequestProperties &&
4449
- typeof state.searchClientRequestProperties === 'object') {
4450
- const requestProperties = state.searchClientRequestProperties;
4451
- let actionType = 'UNKNOWN';
4452
- if (this.lastSearchTerm !== requestProperties.searchTerm) {
4453
- if (this.areAnyFacetPathsSelected) {
4454
- actionType = 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE';
4482
+ state.searchClientRequestProperties) {
4483
+ // Handle both object and string requestProperties (string is used for initialQuery)
4484
+ if (typeof state.searchClientRequestProperties === 'object') {
4485
+ const requestProperties = state.searchClientRequestProperties;
4486
+ let actionType = 'UNKNOWN';
4487
+ if (this.lastSearchTerm !== requestProperties.searchTerm) {
4488
+ if (this.areAnyFacetPathsSelected) {
4489
+ actionType = 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE';
4490
+ }
4491
+ else {
4492
+ actionType = 'NEW_SEARCH_TERM';
4493
+ }
4455
4494
  }
4456
- else {
4457
- actionType = 'NEW_SEARCH_TERM';
4495
+ else if (this.lastRangeValues !==
4496
+ JSON.stringify(requestProperties.rangeValueForIndexFields)) {
4497
+ actionType = 'RANGE_VALUE_UPDATE';
4458
4498
  }
4499
+ else if (this.lastFacetValues !==
4500
+ JSON.stringify(requestProperties.facetPathsForIndexFields)) {
4501
+ actionType = 'FACET_UPDATE';
4502
+ }
4503
+ else if (this.lastSortType !== requestProperties.order_by) {
4504
+ actionType = 'SORT_ORDER_UPDATE';
4505
+ }
4506
+ else if (this.lastSearchMode !== requestProperties.mode) {
4507
+ actionType = 'EXACT_MATCH_UPDATE';
4508
+ }
4509
+ this.lastRangeValues = JSON.stringify(requestProperties.rangeValueForIndexFields);
4510
+ this.lastFacetValues = JSON.stringify(requestProperties.facetPathsForIndexFields);
4511
+ this.lastSortType = requestProperties.order_by;
4512
+ this.lastSearchMode = requestProperties.mode;
4513
+ this.lastSearchTerm = requestProperties.searchTerm;
4514
+ this.lastTimeTaken = state.searchResponseTimeTaken;
4515
+ // Handle the incoming response, using the action we have determined.
4516
+ this.handleIncomingSearchResponse(state, actionType);
4459
4517
  }
4460
- else if (this.lastRangeValues !==
4461
- JSON.stringify(requestProperties.rangeValueForIndexFields)) {
4462
- actionType = 'RANGE_VALUE_UPDATE';
4463
- }
4464
- else if (this.lastFacetValues !==
4465
- JSON.stringify(requestProperties.facetPathsForIndexFields)) {
4466
- actionType = 'FACET_UPDATE';
4467
- }
4468
- else if (this.lastSortType !== requestProperties.order_by) {
4469
- actionType = 'SORT_ORDER_UPDATE';
4470
- }
4471
- else if (this.lastSearchMode !== requestProperties.mode) {
4472
- actionType = 'EXACT_MATCH_UPDATE';
4518
+ else if (typeof state.searchClientRequestProperties === 'string') {
4519
+ // Handle initialQuery case where requestProperties is a string
4520
+ // For initialQuery, searchTerm will be empty but we still want to show facets
4521
+ let actionType = 'NEW_SEARCH_TERM';
4522
+ // Parse the request to get facet and range filters from the query array
4523
+ const requestObj = JSON.parse(state.searchClientRequestProperties);
4524
+ const queryArray = Array.isArray(requestObj.query)
4525
+ ? requestObj.query
4526
+ : [requestObj.query];
4527
+ // Extract filter queries (those with occur: 'must')
4528
+ const filterQueries = queryArray.filter((q) => q.occur === 'must');
4529
+ const currentFilters = JSON.stringify(filterQueries);
4530
+ // Determine the action type based on what changed
4531
+ if (this.lastFacetValues !== undefined && this.lastFacetValues !== currentFilters) {
4532
+ // Filters have changed (not initial load)
4533
+ actionType = 'FACET_UPDATE';
4534
+ }
4535
+ else if (state.searchTerm.trim() === '' && this.lastSearchTerm === '') {
4536
+ // Initial load or no changes with empty search term
4537
+ actionType = 'NEW_SEARCH_TERM';
4538
+ }
4539
+ else if (this.lastSearchTerm !== state.searchTerm) {
4540
+ // User has typed a new search term after initialQuery
4541
+ if (this.areAnyFacetPathsSelected) {
4542
+ actionType = 'NEW_SEARCH_TERM_WHILE_FACETS_ACTIVE';
4543
+ }
4544
+ else {
4545
+ actionType = 'NEW_SEARCH_TERM';
4546
+ }
4547
+ }
4548
+ this.lastFacetValues = currentFilters;
4549
+ this.lastSearchTerm = state.searchTerm;
4550
+ this.lastTimeTaken = state.searchResponseTimeTaken;
4551
+ // Handle the incoming response, using the action we have determined.
4552
+ this.handleIncomingSearchResponse(state, actionType);
4473
4553
  }
4474
- this.lastRangeValues = JSON.stringify(requestProperties.rangeValueForIndexFields);
4475
- this.lastFacetValues = JSON.stringify(requestProperties.facetPathsForIndexFields);
4476
- this.lastSortType = requestProperties.order_by;
4477
- this.lastSearchMode = requestProperties.mode;
4478
- this.lastSearchTerm = requestProperties.searchTerm;
4479
- this.lastTimeTaken = state.searchResponseTimeTaken;
4480
- // Handle the incoming response, using the action we have determined.
4481
- this.handleIncomingSearchResponse(state, actionType);
4482
4554
  }
4483
4555
  }
4484
4556
  onCoreAvailable(core) {
@@ -4573,6 +4645,7 @@ class SearchcraftFacetList {
4573
4645
  "$members$": {
4574
4646
  "searchcraftId": [1, "searchcraft-id"],
4575
4647
  "fieldName": [1, "field-name"],
4648
+ "exclude": [16],
4576
4649
  "selectedPaths": [32],
4577
4650
  "facetTreeCollectedFromSearchResponse": [32],
4578
4651
  "renderedFacetTree": [32]
@@ -4718,7 +4791,7 @@ class SearchcraftFilterPanel {
4718
4791
  * Iterate through `items` and render them based on `type`
4719
4792
  */
4720
4793
  render() {
4721
- return (hAsync("div", { key: 'b18a05516bea8d145d1ca015835d63fafbfc8bd8', class: 'searchcraft-filter-panel' }, this.items.map((filterItem) => {
4794
+ return (hAsync("div", { key: 'ee8974e38b296a1ba27111bc2a4244d8915f5839', class: 'searchcraft-filter-panel' }, this.items.map((filterItem) => {
4722
4795
  switch (filterItem.type) {
4723
4796
  case 'dateRange': {
4724
4797
  const item = filterItem;
@@ -4738,7 +4811,7 @@ class SearchcraftFilterPanel {
4738
4811
  case 'facets': {
4739
4812
  const item = filterItem;
4740
4813
  // return "filters-list"
4741
- 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) => {
4814
+ 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) => {
4742
4815
  this.handleFacetSelectionUpdated(item.fieldName, event.detail.paths);
4743
4816
  } })));
4744
4817
  }
@@ -4837,6 +4910,10 @@ class SearchcraftInputForm {
4837
4910
  * 'hide-on-text-entered' - Only hide the placeholder when the input form has text entered into it.
4838
4911
  */
4839
4912
  placeholderBehavior;
4913
+ /**
4914
+ * The value to display in the input field.
4915
+ */
4916
+ value;
4840
4917
  /**
4841
4918
  * When the input becomes focused.
4842
4919
  */
@@ -4857,18 +4934,41 @@ class SearchcraftInputForm {
4857
4934
  cleanupCore;
4858
4935
  init() {
4859
4936
  if (this.core) {
4937
+ // Initialize inputValue from prop if provided
4938
+ if (this.value !== undefined && this.value.trim().length > 0) {
4939
+ this.inputValue = this.value;
4940
+ this.core.store.getState().setSearchTerm(this.value);
4941
+ // Trigger search if autoSearch is enabled
4942
+ if (this.autoSearch) {
4943
+ this.core.store.getState().search();
4944
+ }
4945
+ }
4860
4946
  this.inputInit?.emit();
4861
4947
  }
4862
4948
  }
4863
4949
  onCoreChange() {
4864
4950
  this.init();
4865
4951
  }
4952
+ onValueChange(newValue) {
4953
+ if (newValue !== undefined && newValue !== this.inputValue) {
4954
+ this.inputValue = newValue;
4955
+ this.core?.store.getState().setSearchTerm(newValue);
4956
+ // Trigger search if autoSearch is enabled and value is not empty
4957
+ if (this.autoSearch && newValue.trim().length > 0) {
4958
+ this.core?.store.getState().search();
4959
+ }
4960
+ }
4961
+ }
4866
4962
  onCoreAvailable(core) {
4867
4963
  this.core = core;
4868
4964
  this.init();
4869
4965
  this.unsubscribe = core.store.subscribe((state) => {
4870
4966
  this.searchTerm = state.searchTerm;
4871
- this.inputValue = state.searchTerm;
4967
+ // Only update inputValue from store if value prop is not set
4968
+ // OR if the store was cleared (empty string)
4969
+ if (this.value === undefined || state.searchTerm === '') {
4970
+ this.inputValue = state.searchTerm;
4971
+ }
4872
4972
  });
4873
4973
  }
4874
4974
  connectedCallback() {
@@ -4897,6 +4997,8 @@ class SearchcraftInputForm {
4897
4997
  }
4898
4998
  };
4899
4999
  handleClearInput = () => {
5000
+ // Clear the input value even if controlled by prop
5001
+ this.inputValue = '';
4900
5002
  this.core?.store.getState().resetSearchValues();
4901
5003
  this.error = false;
4902
5004
  };
@@ -4915,14 +5017,15 @@ class SearchcraftInputForm {
4915
5017
  const inputGridStyles = {
4916
5018
  gap: shouldHaveVerticalGap ? '4px 8px' : '0px 8px',
4917
5019
  };
4918
- 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', {
5020
+ 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', {
4919
5021
  'searchcraft-placeholder-hide-on-focus': this.placeholderBehavior === 'hide-on-focus',
4920
5022
  }), onFocus: () => this.inputFocus?.emit(), onBlur: () => this.inputBlur?.emit(), onInput: (event) => {
4921
5023
  this.handleInput(event);
4922
- }, 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' }))))))));
5024
+ }, 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' }))))))));
4923
5025
  }
4924
5026
  static get watchers() { return {
4925
- "core": ["onCoreChange"]
5027
+ "core": ["onCoreChange"],
5028
+ "value": ["onValueChange"]
4926
5029
  }; }
4927
5030
  static get cmpMeta() { return {
4928
5031
  "$flags$": 0,
@@ -4935,6 +5038,7 @@ class SearchcraftInputForm {
4935
5038
  "inputLabel": [1, "input-label"],
4936
5039
  "placeholderValue": [1, "placeholder-value"],
4937
5040
  "placeholderBehavior": [1, "placeholder-behavior"],
5041
+ "value": [1],
4938
5042
  "inputValue": [32],
4939
5043
  "searchTerm": [32],
4940
5044
  "error": [32]
@@ -5046,6 +5150,7 @@ class SearchcraftPagination {
5046
5150
  searchResultsPerPage;
5047
5151
  searchResultsPage;
5048
5152
  searchResultsCount;
5153
+ searchClientRequestProperties;
5049
5154
  // local vars
5050
5155
  searchResultsPagesCount = 1;
5051
5156
  searchResultsRangeMin = 1;
@@ -5061,6 +5166,7 @@ class SearchcraftPagination {
5061
5166
  this.searchResultsPerPage = state.searchResultsPerPage;
5062
5167
  this.searchResultsPage = state.searchResultsPage;
5063
5168
  this.searchResultsCount = state.searchResultsCount;
5169
+ this.searchClientRequestProperties = state.searchClientRequestProperties;
5064
5170
  // local vars
5065
5171
  this.searchResultsPagesCount = Math.ceil(this.searchResultsCount / this.searchResultsPerPage);
5066
5172
  this.searchResultsRangeMin =
@@ -5120,8 +5226,11 @@ class SearchcraftPagination {
5120
5226
  return (hAsync("li", null, hAsync("span", { class: 'searchcraft-pagination-item searchcraft-pagination-item-active' }, this.searchResultsPage)));
5121
5227
  }
5122
5228
  render() {
5123
- // early return if there isn't a searchTerm or there is 1 or fewer pages of results
5124
- if (!this.searchTerm || this.searchResultsPagesCount <= 1) {
5229
+ // Check if this is an initialQuery case (string requestProperties with empty searchTerm)
5230
+ const isInitialQuery = typeof this.searchClientRequestProperties === 'string' &&
5231
+ this.searchTerm.trim() === '';
5232
+ // early return if there isn't a searchTerm (unless it's initialQuery) or there is 1 or fewer pages of results
5233
+ if ((!this.searchTerm && !isInitialQuery) || this.searchResultsPagesCount <= 1) {
5125
5234
  return;
5126
5235
  }
5127
5236
  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
@@ -5139,6 +5248,7 @@ class SearchcraftPagination {
5139
5248
  "searchResultsPerPage": [32],
5140
5249
  "searchResultsPage": [32],
5141
5250
  "searchResultsCount": [32],
5251
+ "searchClientRequestProperties": [32],
5142
5252
  "searchResultsPagesCount": [32],
5143
5253
  "searchResultsRangeMin": [32],
5144
5254
  "searchResultsRangeMax": [32],
@@ -6162,6 +6272,7 @@ class SearchcraftResultsInfo {
6162
6272
  searchResultsPage;
6163
6273
  searchResultsPerPage;
6164
6274
  searchResultsCount;
6275
+ searchClientRequestProperties;
6165
6276
  // local vars
6166
6277
  count = 0;
6167
6278
  range = [0, 0];
@@ -6175,6 +6286,7 @@ class SearchcraftResultsInfo {
6175
6286
  this.searchResultsPage = state.searchResultsPage;
6176
6287
  this.searchResultsPerPage = state.searchResultsPerPage;
6177
6288
  this.searchResultsCount = state.searchResultsCount;
6289
+ this.searchClientRequestProperties = state.searchClientRequestProperties;
6178
6290
  // local vars
6179
6291
  this.count = this.searchResultsCount;
6180
6292
  this.range[0] =
@@ -6197,7 +6309,12 @@ class SearchcraftResultsInfo {
6197
6309
  this.cleanupCore?.();
6198
6310
  }
6199
6311
  render() {
6200
- if (!this.searchTerm || this.searchResultsCount === 0) {
6312
+ // Check if this is an initialQuery case (string requestProperties with empty searchTerm)
6313
+ const isInitialQuery = typeof this.searchClientRequestProperties === 'string' &&
6314
+ this.searchTerm.trim() === '';
6315
+ // Only hide if there's no search term AND no initialQuery AND no results
6316
+ if ((!this.searchTerm && !isInitialQuery) ||
6317
+ this.searchResultsCount === 0) {
6201
6318
  return null;
6202
6319
  }
6203
6320
  return (hAsync("p", { class: 'searchcraft-results-info' }, typeof this.template !== 'undefined'
@@ -6218,6 +6335,7 @@ class SearchcraftResultsInfo {
6218
6335
  "searchResultsPage": [32],
6219
6336
  "searchResultsPerPage": [32],
6220
6337
  "searchResultsCount": [32],
6338
+ "searchClientRequestProperties": [32],
6221
6339
  "count": [32],
6222
6340
  "range": [32],
6223
6341
  "responseTime": [32]
@@ -6592,6 +6710,7 @@ class SearchcraftSearchResultsPerPage {
6592
6710
  searchResultsPerPage;
6593
6711
  searchResultsCount;
6594
6712
  searchResultsPagesCount;
6713
+ searchClientRequestProperties;
6595
6714
  // local vars
6596
6715
  initialSearchResultsPerPage;
6597
6716
  // store functions
@@ -6606,6 +6725,7 @@ class SearchcraftSearchResultsPerPage {
6606
6725
  this.searchResultsPerPage = state.searchResultsPerPage;
6607
6726
  this.searchResultsPage = state.searchResultsPage;
6608
6727
  this.searchResultsCount = state.searchResultsCount;
6728
+ this.searchClientRequestProperties = state.searchClientRequestProperties;
6609
6729
  // local vars
6610
6730
  this.searchResultsPagesCount = Math.ceil(this.searchResultsCount / this.searchResultsPerPage);
6611
6731
  // store functions
@@ -6623,8 +6743,11 @@ class SearchcraftSearchResultsPerPage {
6623
6743
  this.cleanupCore?.();
6624
6744
  }
6625
6745
  render() {
6626
- // early return if there isn't a searchTerm or there is 1 or fewer pages of results
6627
- if (!this.searchTerm || this.searchResultsPagesCount <= 1) {
6746
+ // Check if this is an initialQuery case (string requestProperties with empty searchTerm)
6747
+ const isInitialQuery = typeof this.searchClientRequestProperties === 'string' &&
6748
+ this.searchTerm.trim() === '';
6749
+ // early return if there isn't a searchTerm (unless it's initialQuery) or there is 1 or fewer pages of results
6750
+ if ((!this.searchTerm && !isInitialQuery) || this.searchResultsPagesCount <= 1) {
6628
6751
  return;
6629
6752
  }
6630
6753
  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) => {
@@ -6650,6 +6773,7 @@ class SearchcraftSearchResultsPerPage {
6650
6773
  "searchResultsPerPage": [32],
6651
6774
  "searchResultsCount": [32],
6652
6775
  "searchResultsPagesCount": [32],
6776
+ "searchClientRequestProperties": [32],
6653
6777
  "initialSearchResultsPerPage": [32],
6654
6778
  "setSearchResultsPerPage": [32],
6655
6779
  "setSearchResultsPage": [32]