@wix/headless-stores 0.0.58 → 0.0.60
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/cjs/dist/react/Category.d.ts +5 -4
- package/cjs/dist/react/Product.d.ts +13 -12
- package/cjs/dist/react/ProductList.d.ts +3 -4
- package/cjs/dist/react/ProductList.js +2 -2
- package/cjs/dist/react/core/ProductList.d.ts +0 -3
- package/cjs/dist/react/core/ProductList.js +1 -3
- package/cjs/dist/services/index.d.ts +1 -2
- package/cjs/dist/services/index.js +1 -2
- package/cjs/dist/services/products-list-search-service.d.ts +1 -128
- package/cjs/dist/services/products-list-search-service.js +1 -507
- package/cjs/dist/services/products-list-service.d.ts +65 -1
- package/cjs/dist/services/products-list-service.js +413 -1
- package/dist/react/Category.d.ts +5 -4
- package/dist/react/Product.d.ts +13 -12
- package/dist/react/ProductList.d.ts +3 -4
- package/dist/react/ProductList.js +2 -2
- package/dist/react/core/ProductList.d.ts +0 -3
- package/dist/react/core/ProductList.js +1 -3
- package/dist/services/index.d.ts +1 -2
- package/dist/services/index.js +1 -2
- package/dist/services/products-list-search-service.d.ts +0 -128
- package/dist/services/products-list-search-service.js +1 -507
- package/dist/services/products-list-service.d.ts +65 -1
- package/dist/services/products-list-service.js +413 -1
- package/package.json +3 -2
|
@@ -2,8 +2,14 @@ import { defineService, implementService } from '@wix/services-definitions';
|
|
|
2
2
|
import { SignalsServiceDefinition, } from '@wix/services-definitions/core-services/signals';
|
|
3
3
|
import { customizationsV3, productsV3, readOnlyVariantsV3 } from '@wix/stores';
|
|
4
4
|
import { loadCategoriesListServiceConfig } from './categories-list-service.js';
|
|
5
|
-
import { InventoryStatusType, parseUrlToSearchOptions, } from './products-list-search-service.js';
|
|
6
5
|
export const DEFAULT_QUERY_LIMIT = 100;
|
|
6
|
+
import { SortType } from './../enums/sort-enums.js';
|
|
7
|
+
export { SortType } from './../enums/sort-enums.js';
|
|
8
|
+
/**
|
|
9
|
+
* Enumeration of inventory status types available for filtering.
|
|
10
|
+
* Re-exports the Wix inventory availability status enum values.
|
|
11
|
+
*/
|
|
12
|
+
export const InventoryStatusType = productsV3.InventoryAvailabilityStatus;
|
|
7
13
|
/**
|
|
8
14
|
* Loads products list service configuration from the Wix Stores API for SSR initialization.
|
|
9
15
|
* This function is designed to be used during Server-Side Rendering (SSR) to preload
|
|
@@ -471,3 +477,409 @@ function getAvailableProductOptions(aggregationData = [], customizations = []) {
|
|
|
471
477
|
.filter((option) => option.choices.length > 0);
|
|
472
478
|
return options;
|
|
473
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* Parse URL and build complete search options with all filters, sort, and pagination.
|
|
482
|
+
* This function extracts search parameters, filters, sorting, and pagination from a URL
|
|
483
|
+
* and converts them into the format expected by the Wix Stores API.
|
|
484
|
+
*
|
|
485
|
+
* @param {string} url - The URL to parse search parameters from
|
|
486
|
+
* @param {Category[]} categoriesList - List of available categories for category slug resolution
|
|
487
|
+
* @param {productsV3.V3ProductSearch} [defaultSearchOptions] - Default search options to merge with parsed URL parameters
|
|
488
|
+
* @returns {Promise<{searchOptions: productsV3.V3ProductSearch, initialSearchState: InitialSearchState}>}
|
|
489
|
+
* Object containing both API-ready search options and UI-ready initial state
|
|
490
|
+
*
|
|
491
|
+
* @example
|
|
492
|
+
* ```tsx
|
|
493
|
+
* // Parse URL with filters, sort, and pagination
|
|
494
|
+
* const categories = await loadCategoriesListServiceConfig();
|
|
495
|
+
* const { searchOptions, initialSearchState } = await parseUrlToSearchOptions(
|
|
496
|
+
* 'https://example.com/products?sort=price:desc&Color=red,blue&minPrice=50',
|
|
497
|
+
* categories.categories
|
|
498
|
+
* );
|
|
499
|
+
*
|
|
500
|
+
* // Use searchOptions for API calls
|
|
501
|
+
* const products = await productsV3.searchProducts(searchOptions);
|
|
502
|
+
*
|
|
503
|
+
* // Use initialSearchState for UI initialization
|
|
504
|
+
* const filterState = initialSearchState.productOptions; // { colorId: ['red-id', 'blue-id'] }
|
|
505
|
+
* ```
|
|
506
|
+
*/
|
|
507
|
+
export async function parseUrlToSearchOptions(url, categoriesList, customizations, defaultSearchOptions) {
|
|
508
|
+
const urlObj = new URL(url);
|
|
509
|
+
const searchParams = urlObj.searchParams;
|
|
510
|
+
// Build search options
|
|
511
|
+
const searchOptions = {
|
|
512
|
+
cursorPaging: {
|
|
513
|
+
limit: DEFAULT_QUERY_LIMIT,
|
|
514
|
+
},
|
|
515
|
+
...defaultSearchOptions,
|
|
516
|
+
};
|
|
517
|
+
// Initialize search state for service
|
|
518
|
+
const initialSearchState = {};
|
|
519
|
+
// Extract category slug from URL path
|
|
520
|
+
// The category slug is always the last segment of the path
|
|
521
|
+
const pathSegments = urlObj.pathname.split('/').filter(Boolean);
|
|
522
|
+
let category = undefined;
|
|
523
|
+
if (pathSegments.length > 0) {
|
|
524
|
+
const lastSegment = pathSegments[pathSegments.length - 1];
|
|
525
|
+
// Check if the last segment matches any category in the categories list
|
|
526
|
+
category = categoriesList.find((cat) => cat.slug === lastSegment);
|
|
527
|
+
if (category) {
|
|
528
|
+
initialSearchState.category = category;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
// Handle text search (q parameter)
|
|
532
|
+
const query = searchParams.get('q');
|
|
533
|
+
if (query) {
|
|
534
|
+
searchOptions.search = {
|
|
535
|
+
expression: query,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
// Handle sorting
|
|
539
|
+
const sort = searchParams.get('sort');
|
|
540
|
+
if (sort) {
|
|
541
|
+
const sortType = convertUrlSortToSortType(sort);
|
|
542
|
+
if (sortType) {
|
|
543
|
+
initialSearchState.sort = sortType;
|
|
544
|
+
// Apply sort to search options
|
|
545
|
+
switch (sortType) {
|
|
546
|
+
case SortType.NAME_ASC:
|
|
547
|
+
searchOptions.sort = [
|
|
548
|
+
{ fieldName: 'name', order: productsV3.SortDirection.ASC },
|
|
549
|
+
];
|
|
550
|
+
break;
|
|
551
|
+
case SortType.NAME_DESC:
|
|
552
|
+
searchOptions.sort = [
|
|
553
|
+
{ fieldName: 'name', order: productsV3.SortDirection.DESC },
|
|
554
|
+
];
|
|
555
|
+
break;
|
|
556
|
+
case SortType.PRICE_ASC:
|
|
557
|
+
searchOptions.sort = [
|
|
558
|
+
{
|
|
559
|
+
fieldName: 'actualPriceRange.minValue.amount',
|
|
560
|
+
order: productsV3.SortDirection.ASC,
|
|
561
|
+
},
|
|
562
|
+
];
|
|
563
|
+
break;
|
|
564
|
+
case SortType.PRICE_DESC:
|
|
565
|
+
searchOptions.sort = [
|
|
566
|
+
{
|
|
567
|
+
fieldName: 'actualPriceRange.minValue.amount',
|
|
568
|
+
order: productsV3.SortDirection.DESC,
|
|
569
|
+
},
|
|
570
|
+
];
|
|
571
|
+
break;
|
|
572
|
+
case SortType.RECOMMENDED:
|
|
573
|
+
searchOptions.sort = [
|
|
574
|
+
{
|
|
575
|
+
fieldName: 'name',
|
|
576
|
+
order: productsV3.SortDirection.DESC,
|
|
577
|
+
},
|
|
578
|
+
];
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
// Handle pagination
|
|
584
|
+
const limit = searchParams.get('limit');
|
|
585
|
+
const cursor = searchParams.get('cursor');
|
|
586
|
+
if (limit || cursor) {
|
|
587
|
+
searchOptions.cursorPaging = {};
|
|
588
|
+
if (limit) {
|
|
589
|
+
const limitNum = parseInt(limit, 10);
|
|
590
|
+
if (!isNaN(limitNum) && limitNum > 0) {
|
|
591
|
+
searchOptions.cursorPaging.limit = limitNum;
|
|
592
|
+
initialSearchState.limit = limitNum;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
if (cursor) {
|
|
596
|
+
searchOptions.cursorPaging.cursor = cursor;
|
|
597
|
+
initialSearchState.cursor = cursor;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
// Handle filtering for search options
|
|
601
|
+
const filter = {};
|
|
602
|
+
const visible = searchParams.get('visible');
|
|
603
|
+
if (visible !== null) {
|
|
604
|
+
filter['visible'] = visible === 'true';
|
|
605
|
+
initialSearchState.visible = visible === 'true';
|
|
606
|
+
}
|
|
607
|
+
const productType = searchParams.get('productType');
|
|
608
|
+
if (productType) {
|
|
609
|
+
filter['productType'] = productType;
|
|
610
|
+
initialSearchState.productType = productType;
|
|
611
|
+
}
|
|
612
|
+
// Add category filter if found
|
|
613
|
+
if (category) {
|
|
614
|
+
filter['allCategoriesInfo.categories'] = {
|
|
615
|
+
$matchItems: [{ _id: { $in: [category._id] } }],
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
// Price range filtering
|
|
619
|
+
const minPrice = searchParams.get('minPrice');
|
|
620
|
+
const maxPrice = searchParams.get('maxPrice');
|
|
621
|
+
if (minPrice || maxPrice) {
|
|
622
|
+
initialSearchState.priceRange = {};
|
|
623
|
+
if (minPrice) {
|
|
624
|
+
const minPriceNum = parseFloat(minPrice);
|
|
625
|
+
if (!isNaN(minPriceNum)) {
|
|
626
|
+
filter['actualPriceRange.minValue.amount'] = { $gte: minPriceNum };
|
|
627
|
+
initialSearchState.priceRange.min = minPriceNum;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
if (maxPrice) {
|
|
631
|
+
const maxPriceNum = parseFloat(maxPrice);
|
|
632
|
+
if (!isNaN(maxPriceNum)) {
|
|
633
|
+
filter['actualPriceRange.maxValue.amount'] = { $lte: maxPriceNum };
|
|
634
|
+
initialSearchState.priceRange.max = maxPriceNum;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
const inventoryStatus = searchParams.get('inventoryStatus');
|
|
639
|
+
if (inventoryStatus) {
|
|
640
|
+
filter['inventory.availabilityStatus'] = {
|
|
641
|
+
$in: inventoryStatus.split(','),
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
// Parse product options from URL parameters
|
|
645
|
+
const reservedParams = [
|
|
646
|
+
'minPrice',
|
|
647
|
+
'maxPrice',
|
|
648
|
+
'inventory_status',
|
|
649
|
+
'inventoryStatus',
|
|
650
|
+
'visible',
|
|
651
|
+
'productType',
|
|
652
|
+
'q',
|
|
653
|
+
'limit',
|
|
654
|
+
'cursor',
|
|
655
|
+
'sort',
|
|
656
|
+
];
|
|
657
|
+
const productOptionsById = {};
|
|
658
|
+
for (const [optionName, optionValues] of searchParams.entries()) {
|
|
659
|
+
if (reservedParams.includes(optionName))
|
|
660
|
+
continue;
|
|
661
|
+
// Find the option by name in customizations
|
|
662
|
+
const option = customizations.find((c) => c.name === optionName &&
|
|
663
|
+
c.customizationType ===
|
|
664
|
+
customizationsV3.CustomizationType.PRODUCT_OPTION);
|
|
665
|
+
if (option && option._id) {
|
|
666
|
+
const choiceValues = optionValues.split(',').filter(Boolean);
|
|
667
|
+
const choiceIds = [];
|
|
668
|
+
// Convert choice names to IDs
|
|
669
|
+
for (const choiceName of choiceValues) {
|
|
670
|
+
const choice = option.choicesSettings?.choices?.find((c) => c.name === choiceName);
|
|
671
|
+
if (choice && choice._id) {
|
|
672
|
+
choiceIds.push(choice._id);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
if (choiceIds.length > 0) {
|
|
676
|
+
productOptionsById[option._id] = choiceIds;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
if (Object.keys(productOptionsById).length > 0) {
|
|
681
|
+
initialSearchState.productOptions = productOptionsById;
|
|
682
|
+
// Add product option filter to search options
|
|
683
|
+
filter[`options.choicesSettings.choices.choiceId`] = {
|
|
684
|
+
$hasSome: Object.values(productOptionsById).flat(),
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
// Add filter to search options if any filters were set
|
|
688
|
+
if (Object.keys(filter).length > 0) {
|
|
689
|
+
searchOptions.filter = filter;
|
|
690
|
+
}
|
|
691
|
+
// Add aggregations for getting filter options
|
|
692
|
+
searchOptions.aggregations = [
|
|
693
|
+
{
|
|
694
|
+
name: 'minPrice',
|
|
695
|
+
fieldPath: 'actualPriceRange.minValue.amount',
|
|
696
|
+
type: 'SCALAR',
|
|
697
|
+
scalar: { type: 'MIN' },
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
name: 'maxPrice',
|
|
701
|
+
fieldPath: 'actualPriceRange.maxValue.amount',
|
|
702
|
+
type: 'SCALAR',
|
|
703
|
+
scalar: { type: 'MAX' },
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
name: 'optionNames',
|
|
707
|
+
fieldPath: 'options.name',
|
|
708
|
+
type: productsV3.SortType.VALUE,
|
|
709
|
+
value: {
|
|
710
|
+
limit: 20,
|
|
711
|
+
sortType: productsV3.SortType.VALUE,
|
|
712
|
+
sortDirection: productsV3.SortDirection.ASC,
|
|
713
|
+
},
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
name: 'choiceNames',
|
|
717
|
+
fieldPath: 'options.choicesSettings.choices.name',
|
|
718
|
+
type: productsV3.SortType.VALUE,
|
|
719
|
+
value: {
|
|
720
|
+
limit: 50,
|
|
721
|
+
sortType: productsV3.SortType.VALUE,
|
|
722
|
+
sortDirection: productsV3.SortDirection.ASC,
|
|
723
|
+
},
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
name: 'inventoryStatus',
|
|
727
|
+
fieldPath: 'inventory.availabilityStatus',
|
|
728
|
+
type: productsV3.SortType.VALUE,
|
|
729
|
+
value: {
|
|
730
|
+
limit: 10,
|
|
731
|
+
sortType: productsV3.SortType.VALUE,
|
|
732
|
+
sortDirection: productsV3.SortDirection.ASC,
|
|
733
|
+
},
|
|
734
|
+
},
|
|
735
|
+
];
|
|
736
|
+
return { searchOptions, initialSearchState };
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Convert SortType enum to URL format
|
|
740
|
+
*/
|
|
741
|
+
function convertSortTypeToUrl(sortType) {
|
|
742
|
+
switch (sortType) {
|
|
743
|
+
case SortType.NAME_ASC:
|
|
744
|
+
return 'name';
|
|
745
|
+
case SortType.NAME_DESC:
|
|
746
|
+
return 'name:desc';
|
|
747
|
+
case SortType.PRICE_ASC:
|
|
748
|
+
return 'price';
|
|
749
|
+
case SortType.PRICE_DESC:
|
|
750
|
+
return 'price:desc';
|
|
751
|
+
case SortType.NEWEST:
|
|
752
|
+
return 'newest';
|
|
753
|
+
case SortType.RECOMMENDED:
|
|
754
|
+
return 'recommended';
|
|
755
|
+
default:
|
|
756
|
+
return 'name';
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Convert URL sort format to SortType enum
|
|
761
|
+
*/
|
|
762
|
+
export function convertUrlSortToSortType(urlSort) {
|
|
763
|
+
const sortParts = urlSort.split(':');
|
|
764
|
+
const field = sortParts[0]?.toLowerCase();
|
|
765
|
+
const order = sortParts[1]?.toLowerCase() === 'desc' ? 'desc' : 'asc';
|
|
766
|
+
switch (field) {
|
|
767
|
+
case 'name':
|
|
768
|
+
return order === 'desc' ? SortType.NAME_DESC : SortType.NAME_ASC;
|
|
769
|
+
case 'price':
|
|
770
|
+
return order === 'desc' ? SortType.PRICE_DESC : SortType.PRICE_ASC;
|
|
771
|
+
case 'newest':
|
|
772
|
+
case 'created':
|
|
773
|
+
return SortType.NEWEST;
|
|
774
|
+
case 'recommended':
|
|
775
|
+
return SortType.RECOMMENDED;
|
|
776
|
+
default:
|
|
777
|
+
return null;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Update URL with current search state (sort, filters, pagination)
|
|
782
|
+
*/
|
|
783
|
+
//@ts-expect-error
|
|
784
|
+
function updateUrlWithSearchState(searchState) {
|
|
785
|
+
if (typeof window === 'undefined')
|
|
786
|
+
return;
|
|
787
|
+
const { sort, filters, customizations, catalogBounds, categorySlug } = searchState;
|
|
788
|
+
// Convert filter IDs back to human-readable names for URL
|
|
789
|
+
const humanReadableOptions = {};
|
|
790
|
+
for (const [optionId, choiceIds] of Object.entries(filters?.productOptions ?? {})) {
|
|
791
|
+
const option = customizations.find((c) => c._id === optionId);
|
|
792
|
+
if (option && option.name) {
|
|
793
|
+
const choiceNames = [];
|
|
794
|
+
for (const choiceId of choiceIds) {
|
|
795
|
+
const choice = option.choicesSettings?.choices?.find((c) => c._id === choiceId);
|
|
796
|
+
if (choice && choice.name) {
|
|
797
|
+
choiceNames.push(choice.name);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
if (choiceNames.length > 0) {
|
|
801
|
+
humanReadableOptions[option.name] = choiceNames;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
// Start with current URL parameters to preserve non-search parameters
|
|
806
|
+
const params = new URLSearchParams(window.location.search);
|
|
807
|
+
// Define search-related parameters that we manage
|
|
808
|
+
const searchParams = [
|
|
809
|
+
'sort',
|
|
810
|
+
'limit',
|
|
811
|
+
'cursor',
|
|
812
|
+
'minPrice',
|
|
813
|
+
'maxPrice',
|
|
814
|
+
'inventoryStatus',
|
|
815
|
+
'visible',
|
|
816
|
+
'productType',
|
|
817
|
+
// Product option names will be dynamically added below
|
|
818
|
+
// Note: category is NOT included here as it's handled in the URL path
|
|
819
|
+
];
|
|
820
|
+
// Remove existing search parameters first
|
|
821
|
+
searchParams.forEach((param) => params.delete(param));
|
|
822
|
+
// Remove existing product option parameters (they have dynamic names)
|
|
823
|
+
for (const customization of customizations) {
|
|
824
|
+
if (customization.customizationType ===
|
|
825
|
+
customizationsV3.CustomizationType.PRODUCT_OPTION &&
|
|
826
|
+
customization.name) {
|
|
827
|
+
params.delete(customization.name);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
// Add sort parameter (only if not default)
|
|
831
|
+
const urlSort = convertSortTypeToUrl(sort);
|
|
832
|
+
if (sort !== SortType.NAME_ASC) {
|
|
833
|
+
params.set('sort', urlSort);
|
|
834
|
+
}
|
|
835
|
+
// Add price range parameters only if they differ from catalog bounds
|
|
836
|
+
if (filters.priceRange?.min &&
|
|
837
|
+
filters.priceRange.min > catalogBounds.minPrice) {
|
|
838
|
+
params.set('minPrice', filters.priceRange.min.toString());
|
|
839
|
+
}
|
|
840
|
+
if (filters.priceRange?.max &&
|
|
841
|
+
filters.priceRange.max < catalogBounds.maxPrice) {
|
|
842
|
+
params.set('maxPrice', filters.priceRange.max.toString());
|
|
843
|
+
}
|
|
844
|
+
// Add inventory status parameters
|
|
845
|
+
if (filters.inventoryStatuses && filters.inventoryStatuses.length > 0) {
|
|
846
|
+
params.set('inventoryStatus', filters.inventoryStatuses.join(','));
|
|
847
|
+
}
|
|
848
|
+
// Add visibility filter (only if explicitly false, since true is default)
|
|
849
|
+
if (filters.visible === false) {
|
|
850
|
+
params.set('visible', 'false');
|
|
851
|
+
}
|
|
852
|
+
// Add product type filter
|
|
853
|
+
if (filters.productType) {
|
|
854
|
+
params.set('productType', filters.productType);
|
|
855
|
+
}
|
|
856
|
+
// Add product options as individual parameters (Color=Red,Blue&Size=Large)
|
|
857
|
+
for (const [optionName, values] of Object.entries(humanReadableOptions)) {
|
|
858
|
+
if (values.length > 0) {
|
|
859
|
+
params.set(optionName, values.join(','));
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
// Handle URL path construction with category
|
|
863
|
+
let baseUrl = window.location.pathname;
|
|
864
|
+
// If categorySlug is provided, replace the last path segment (which represents the category)
|
|
865
|
+
if (categorySlug) {
|
|
866
|
+
const pathSegments = baseUrl.split('/').filter(Boolean);
|
|
867
|
+
if (pathSegments.length > 0) {
|
|
868
|
+
// Replace the last segment with the new category slug
|
|
869
|
+
pathSegments[pathSegments.length - 1] = categorySlug;
|
|
870
|
+
baseUrl = '/' + pathSegments.join('/');
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
// If no segments, just use the category slug
|
|
874
|
+
baseUrl = `/${categorySlug}`;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
// Build the new URL
|
|
878
|
+
const newUrl = params.toString()
|
|
879
|
+
? `${baseUrl}?${params.toString()}`
|
|
880
|
+
: baseUrl;
|
|
881
|
+
// Only update if URL actually changed
|
|
882
|
+
if (newUrl !== window.location.pathname + window.location.search) {
|
|
883
|
+
window.history.pushState(null, '', newUrl);
|
|
884
|
+
}
|
|
885
|
+
}
|
package/dist/react/Category.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type Category } from '../services/category-service.js';
|
|
3
3
|
import { type CategoryServiceConfig } from '../services/category-service.js';
|
|
4
|
+
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
4
5
|
/**
|
|
5
6
|
* Props for Category.Root component
|
|
6
7
|
*/
|
|
@@ -21,7 +22,7 @@ export interface CategoryTriggerProps {
|
|
|
21
22
|
/** Whether to render as a child component */
|
|
22
23
|
asChild?: boolean;
|
|
23
24
|
/** Custom render function when using asChild */
|
|
24
|
-
children?:
|
|
25
|
+
children?: AsChildChildren<{
|
|
25
26
|
category: Category;
|
|
26
27
|
isSelected: boolean;
|
|
27
28
|
onSelect: () => void;
|
|
@@ -39,7 +40,7 @@ export interface CategoryLabelProps {
|
|
|
39
40
|
/** Whether to render as a child component */
|
|
40
41
|
asChild?: boolean;
|
|
41
42
|
/** Custom render function when using asChild */
|
|
42
|
-
children?:
|
|
43
|
+
children?: AsChildChildren<{
|
|
43
44
|
name: string;
|
|
44
45
|
category: Category;
|
|
45
46
|
}>;
|
|
@@ -53,7 +54,7 @@ export interface CategoryIDProps {
|
|
|
53
54
|
/** Whether to render as a child component */
|
|
54
55
|
asChild?: boolean;
|
|
55
56
|
/** Custom render function when using asChild */
|
|
56
|
-
children?:
|
|
57
|
+
children?: AsChildChildren<{
|
|
57
58
|
id: string;
|
|
58
59
|
category: Category;
|
|
59
60
|
}>;
|
|
@@ -67,7 +68,7 @@ export interface CategoryRawProps {
|
|
|
67
68
|
/** Whether to render as a child component */
|
|
68
69
|
asChild?: boolean;
|
|
69
70
|
/** Custom render function when using asChild */
|
|
70
|
-
children?:
|
|
71
|
+
children?: AsChildChildren<{
|
|
71
72
|
category: Category;
|
|
72
73
|
isSelected: boolean;
|
|
73
74
|
}>;
|
package/dist/react/Product.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { V3Product } from '@wix/auto_sdk_stores_products-v-3';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
3
4
|
import { AsContent } from './types.js';
|
|
4
5
|
/**
|
|
5
6
|
* Context for sharing variant options state between components
|
|
@@ -59,9 +60,9 @@ export interface NameProps {
|
|
|
59
60
|
/** Whether to render as a child component */
|
|
60
61
|
asChild?: boolean;
|
|
61
62
|
/** Custom render function when using asChild */
|
|
62
|
-
children?:
|
|
63
|
+
children?: AsChildChildren<{
|
|
63
64
|
name: string;
|
|
64
|
-
}
|
|
65
|
+
}>;
|
|
65
66
|
/** CSS classes to apply to the default element */
|
|
66
67
|
className?: string;
|
|
67
68
|
}
|
|
@@ -97,9 +98,9 @@ export interface DescriptionProps {
|
|
|
97
98
|
/** Whether to render as a child component */
|
|
98
99
|
asChild?: boolean;
|
|
99
100
|
/** Custom render function when using asChild */
|
|
100
|
-
children?:
|
|
101
|
+
children?: AsChildChildren<{
|
|
101
102
|
description: string;
|
|
102
|
-
}
|
|
103
|
+
}>;
|
|
103
104
|
/** CSS classes to apply to the default element */
|
|
104
105
|
className?: string;
|
|
105
106
|
/** Format of the description content */
|
|
@@ -136,10 +137,10 @@ export interface PriceProps {
|
|
|
136
137
|
/** Whether to render as a child component */
|
|
137
138
|
asChild?: boolean;
|
|
138
139
|
/** Custom render function when using asChild */
|
|
139
|
-
children?:
|
|
140
|
+
children?: AsChildChildren<{
|
|
140
141
|
price: string;
|
|
141
142
|
formattedPrice: string;
|
|
142
|
-
}
|
|
143
|
+
}>;
|
|
143
144
|
/** CSS classes to apply to the default element */
|
|
144
145
|
className?: string;
|
|
145
146
|
}
|
|
@@ -175,10 +176,10 @@ export interface CompareAtPriceProps {
|
|
|
175
176
|
/** Whether to render as a child component */
|
|
176
177
|
asChild?: boolean;
|
|
177
178
|
/** Custom render function when using asChild */
|
|
178
|
-
children?:
|
|
179
|
+
children?: AsChildChildren<{
|
|
179
180
|
price: string;
|
|
180
181
|
formattedPrice: string;
|
|
181
|
-
}
|
|
182
|
+
}>;
|
|
182
183
|
/** CSS classes to apply to the default element */
|
|
183
184
|
className?: string;
|
|
184
185
|
}
|
|
@@ -219,9 +220,9 @@ export interface SlugProps {
|
|
|
219
220
|
/** Whether to render as a child component */
|
|
220
221
|
asChild?: boolean;
|
|
221
222
|
/** Custom render function when using asChild */
|
|
222
|
-
children?:
|
|
223
|
+
children?: AsChildChildren<{
|
|
223
224
|
slug: string;
|
|
224
|
-
}
|
|
225
|
+
}>;
|
|
225
226
|
/** CSS classes to apply to the default element */
|
|
226
227
|
className?: string;
|
|
227
228
|
}
|
|
@@ -255,9 +256,9 @@ export interface RawProps {
|
|
|
255
256
|
/** Whether to render as a child component */
|
|
256
257
|
asChild?: boolean;
|
|
257
258
|
/** Custom render function when using asChild */
|
|
258
|
-
children?:
|
|
259
|
+
children?: AsChildChildren<{
|
|
259
260
|
product: V3Product;
|
|
260
|
-
}
|
|
261
|
+
}>;
|
|
261
262
|
/** CSS classes to apply to the default element */
|
|
262
263
|
className?: string;
|
|
263
264
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { V3Product } from '@wix/auto_sdk_stores_products-v-3';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import type { ProductsListSearchServiceConfig } from '../services/products-list-search-service.js';
|
|
4
3
|
import type { ProductsListServiceConfig } from '../services/products-list-service.js';
|
|
4
|
+
import { AsChildChildren } from '@wix/headless-utils/react';
|
|
5
5
|
/**
|
|
6
6
|
* Props for the ProductList root component following the documented API
|
|
7
7
|
*/
|
|
@@ -9,7 +9,6 @@ export interface ProductListRootProps {
|
|
|
9
9
|
children: React.ReactNode;
|
|
10
10
|
products?: V3Product[];
|
|
11
11
|
productsListConfig?: ProductsListServiceConfig;
|
|
12
|
-
productsListSearchConfig?: ProductsListSearchServiceConfig;
|
|
13
12
|
className?: string;
|
|
14
13
|
}
|
|
15
14
|
/**
|
|
@@ -142,9 +141,9 @@ export interface TotalsDisplayedProps {
|
|
|
142
141
|
/** Whether to render as a child component */
|
|
143
142
|
asChild?: boolean;
|
|
144
143
|
/** Custom render function when using asChild */
|
|
145
|
-
children?:
|
|
144
|
+
children?: AsChildChildren<{
|
|
146
145
|
displayedProducts: number;
|
|
147
|
-
}
|
|
146
|
+
}>;
|
|
148
147
|
/** CSS classes to apply to the default element */
|
|
149
148
|
className?: string;
|
|
150
149
|
}
|
|
@@ -38,7 +38,7 @@ var TestIds;
|
|
|
38
38
|
* ```
|
|
39
39
|
*/
|
|
40
40
|
export const Root = React.forwardRef((props, ref) => {
|
|
41
|
-
const { children, products, productsListConfig,
|
|
41
|
+
const { children, products, productsListConfig, className } = props;
|
|
42
42
|
const serviceConfig = productsListConfig || {
|
|
43
43
|
products: products || [],
|
|
44
44
|
searchOptions: {
|
|
@@ -50,7 +50,7 @@ export const Root = React.forwardRef((props, ref) => {
|
|
|
50
50
|
aggregations: {}, // Empty aggregation data
|
|
51
51
|
customizations: [],
|
|
52
52
|
};
|
|
53
|
-
return (_jsx(CoreProductList.Root, { productsListConfig: serviceConfig,
|
|
53
|
+
return (_jsx(CoreProductList.Root, { productsListConfig: serviceConfig, children: _jsx(RootContent, { children: children, className: className, ref: ref }) }));
|
|
54
54
|
});
|
|
55
55
|
/**
|
|
56
56
|
* Internal component to handle the Root content with service access
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { type ProductsListServiceConfig } from '../../services/products-list-service.js';
|
|
2
2
|
import { productsV3 } from '@wix/stores';
|
|
3
|
-
import { ProductsListSearchServiceConfig } from '../../services/products-list-search-service.js';
|
|
4
3
|
import { CategoriesListServiceConfig } from '../../services/categories-list-service.js';
|
|
5
4
|
/**
|
|
6
5
|
* Props for Root headless component
|
|
@@ -10,8 +9,6 @@ export interface RootProps {
|
|
|
10
9
|
children: React.ReactNode;
|
|
11
10
|
/** Configuration for the ProductList service */
|
|
12
11
|
productsListConfig: ProductsListServiceConfig;
|
|
13
|
-
/** Configuration for the ProductListSearch service */
|
|
14
|
-
productsListSearchConfig?: ProductsListSearchServiceConfig;
|
|
15
12
|
/** Configuration for the CategoriesList service */
|
|
16
13
|
categoriesListConfig?: CategoriesListServiceConfig;
|
|
17
14
|
}
|
|
@@ -3,7 +3,6 @@ import { useService, WixServices } from '@wix/services-manager-react';
|
|
|
3
3
|
import { createServicesMap } from '@wix/services-manager';
|
|
4
4
|
import { ProductListService, ProductsListServiceDefinition, } from '../../services/products-list-service.js';
|
|
5
5
|
import { ProductService, ProductServiceDefinition, } from '../../services/product-service.js';
|
|
6
|
-
import { ProductsListSearchService, ProductsListSearchServiceDefinition, } from '../../services/products-list-search-service.js';
|
|
7
6
|
import { CategoriesListService, CategoriesListServiceDefinition, } from '../../services/categories-list-service.js';
|
|
8
7
|
/**
|
|
9
8
|
* Root component that provides both ProductList and ProductListSearch service contexts to its children.
|
|
@@ -66,8 +65,7 @@ import { CategoriesListService, CategoriesListServiceDefinition, } from '../../s
|
|
|
66
65
|
export function Root(props) {
|
|
67
66
|
return (_jsx(WixServices, { servicesMap: createServicesMap()
|
|
68
67
|
.addService(CategoriesListServiceDefinition, CategoriesListService, props.categoriesListConfig)
|
|
69
|
-
.addService(ProductsListServiceDefinition, ProductListService, props.productsListConfig)
|
|
70
|
-
.addService(ProductsListSearchServiceDefinition, ProductsListSearchService, props.productsListSearchConfig), children: props.children }));
|
|
68
|
+
.addService(ProductsListServiceDefinition, ProductListService, props.productsListConfig), children: props.children }));
|
|
71
69
|
}
|
|
72
70
|
/**
|
|
73
71
|
* Component that renders content when the products list is empty.
|
package/dist/services/index.d.ts
CHANGED
|
@@ -3,5 +3,4 @@ export { CategoriesListService, CategoriesListServiceDefinition, loadCategoriesL
|
|
|
3
3
|
export { ProductModifiersService, ProductModifiersServiceDefinition, } from './product-modifiers-service.js';
|
|
4
4
|
export { ProductService, ProductServiceDefinition, loadProductServiceConfig, } from './product-service.js';
|
|
5
5
|
export { SelectedVariantService, SelectedVariantServiceDefinition, } from './selected-variant-service.js';
|
|
6
|
-
export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, ProductsListServiceConfig, ProductOption, ProductChoice, } from './products-list-service.js';
|
|
7
|
-
export { InventoryStatusType, SortType, ProductsListSearchService, ProductsListSearchServiceDefinition, ProductsListSearchServiceConfig, loadProductsListSearchServiceConfig, parseUrlToSearchOptions, convertUrlSortToSortType, } from './products-list-search-service.js';
|
|
6
|
+
export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, ProductsListServiceConfig, ProductOption, ProductChoice, InventoryStatusType, SortType, InitialSearchState, parseUrlToSearchOptions, convertUrlSortToSortType, } from './products-list-service.js';
|
package/dist/services/index.js
CHANGED
|
@@ -3,5 +3,4 @@ export { CategoriesListService, CategoriesListServiceDefinition, loadCategoriesL
|
|
|
3
3
|
export { ProductModifiersService, ProductModifiersServiceDefinition, } from './product-modifiers-service.js';
|
|
4
4
|
export { ProductService, ProductServiceDefinition, loadProductServiceConfig, } from './product-service.js';
|
|
5
5
|
export { SelectedVariantService, SelectedVariantServiceDefinition, } from './selected-variant-service.js';
|
|
6
|
-
export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, } from './products-list-service.js';
|
|
7
|
-
export { InventoryStatusType, SortType, ProductsListSearchService, ProductsListSearchServiceDefinition, loadProductsListSearchServiceConfig, parseUrlToSearchOptions, convertUrlSortToSortType, } from './products-list-search-service.js';
|
|
6
|
+
export { ProductListService, ProductsListServiceDefinition, loadProductsListServiceConfig, InventoryStatusType, SortType, parseUrlToSearchOptions, convertUrlSortToSortType, } from './products-list-service.js';
|