@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.
- package/README.md +1 -1
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.js +136 -17
- package/dist/components/index.js.map +1 -1
- package/dist/components/{p-b7e99386.js → p-870f81fd.js} +38 -6
- package/dist/components/p-870f81fd.js.map +1 -0
- package/dist/components/{p-0c495408.js → p-e8d97093.js} +110 -37
- package/dist/components/p-e8d97093.js.map +1 -0
- package/dist/components/searchcraft-facet-list.js +1 -1
- package/dist/components/searchcraft-filter-panel.js +3 -3
- package/dist/components/searchcraft-filter-panel.js.map +1 -1
- package/dist/components/searchcraft-input-form.js +1 -1
- package/dist/components/searchcraft-pagination.js +8 -2
- package/dist/components/searchcraft-pagination.js.map +1 -1
- package/dist/components/searchcraft-popover-form.js +1 -1
- package/dist/components/searchcraft-results-info.js +9 -1
- package/dist/components/searchcraft-results-info.js.map +1 -1
- package/dist/components/searchcraft-search-results-per-page.js +8 -2
- package/dist/components/searchcraft-search-results-per-page.js.map +1 -1
- package/dist/hydrate/index.js +229 -105
- package/dist/hydrate/index.mjs +229 -105
- package/dist/types/classes/SearchcraftCore.d.ts +1 -1
- package/dist/types/components/searchcraft-facet-list/searchcraft-facet-list.d.ts +5 -1
- package/dist/types/components/searchcraft-filter-panel/searchcraft-filter-panel.d.ts +1 -1
- package/dist/types/components/searchcraft-input-form/searchcraft-input-form.d.ts +5 -0
- package/dist/types/components/searchcraft-pagination/searchcraft-pagination.d.ts +1 -0
- package/dist/types/components/searchcraft-results-info/searchcraft-results-info.d.ts +1 -0
- package/dist/types/components/searchcraft-search-results-per-page/searchcraft-search-results-per-page.d.ts +1 -0
- package/dist/types/components.d.ts +16 -0
- package/dist/types/store/SearchcraftStore.types.d.ts +6 -1
- package/dist/types/types/sdk-types/searchcraft-filter-panel.types.d.ts +1 -0
- package/dist/types/utils/facets.d.ts +5 -1
- package/package.json +4 -3
- package/dist/components/p-0c495408.js.map +0 -1
- package/dist/components/p-b7e99386.js.map +0 -1
package/dist/hydrate/index.js
CHANGED
|
@@ -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 (
|
|
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
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
if (this.
|
|
4454
|
-
|
|
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
|
-
|
|
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 (
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
JSON.
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
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: '
|
|
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
|
-
|
|
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: '
|
|
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: '
|
|
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
|
-
//
|
|
5124
|
-
|
|
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
|
|
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
|
-
//
|
|
6627
|
-
|
|
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]
|