@searchstax-inc/searchstudio-ux-react 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -325,33 +325,469 @@ example of pagination widget initialization with minimum options
325
325
 
326
326
  example of pagination widget initialization with various options
327
327
  ```
328
+ function paginationTemplate(
329
+ paginationData: IPaginationData | null,
330
+ nextPage: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void,
331
+ previousPage: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void
332
+ ) {
333
+ return (
334
+ <>
335
+ {paginationData && paginationData?.totalResults !== 0 && (
336
+ <div className="searchstax-pagination-container">
337
+ <div className="searchstax-pagination-content">
338
+ <a
339
+ className="searchstax-pagination-previous"
340
+ style={paginationData?.isFirstPage ? { pointerEvents: "none" } : {}}
341
+ onClick={(e) => {
342
+ previousPage(e);
343
+ }}
344
+ id="searchstax-pagination-previous"
345
+ >
346
+ {" "}
347
+ &lt; Previous{" "}
348
+ </a>
349
+ <div className="searchstax-pagination-details">
350
+ {" "}
351
+ {paginationData?.startResultIndex} - {paginationData?.endResultIndex} of {paginationData?.totalResults}
352
+ </div>
353
+ <a
354
+ className="searchstax-pagination-next"
355
+ style={paginationData?.isLastPage ? { pointerEvents: "none" } : {}}
356
+ onClick={(e) => {
357
+ nextPage(e);
358
+ }}
359
+ id="searchstax-pagination-next"
360
+ >
361
+ Next &gt;
362
+ </a>
363
+ </div>
364
+ </div>
365
+ )}
366
+ </>
367
+ );
368
+ }
328
369
 
370
+ <SearchstaxPaginationWidget paginationTemplate={paginationTemplate}></SearchstaxPaginationWidget>
329
371
  ```
330
372
 
331
373
  ### Facets Widget ###
332
374
 
333
375
  example of facets widget initialization with minimum options
334
376
  ```
335
-
377
+ <SearchstaxFacetsWidget
378
+ facetingType="and"
379
+ itemsPerPageDesktop={2}
380
+ itemsPerPageMobile={3}
381
+ specificFacets={undefined}
382
+ ></SearchstaxFacetsWidget>
336
383
  ```
337
384
 
338
385
 
339
386
  example of facets widget initialization with template overrides
340
387
  ```
388
+ function facetsTemplateDesktop(
389
+ facetsTemplateDataDesktop: IFacetsTemplateData | null,
390
+ facetContainers: {
391
+ [key: string]: React.LegacyRef<HTMLDivElement> | undefined;
392
+ },
393
+ isNotDeactivated: (name: string) => boolean,
394
+ toggleFacetGroup: (name: string) => void,
395
+ selectFacet: (
396
+ index: string,
397
+ event: React.MouseEvent<HTMLDivElement, MouseEvent>,
398
+ data: IFacetValueData,
399
+ isInput: boolean
400
+ ) => void,
401
+ isChecked: (facetValue: IFacetValueData) => boolean | undefined,
402
+ showMoreLessDesktop: (
403
+ e: React.MouseEvent<HTMLDivElement, MouseEvent>,
404
+ data: IFacetData
405
+ ) => void
406
+ ) {
407
+ return (
408
+ <div className="searchstax-facets-container-desktop">
409
+ {facetsTemplateDataDesktop?.facets.map((facet) => {
410
+ return (
411
+ <div
412
+ className={`searchstax-facet-container ${
413
+ isNotDeactivated(facet.name) ? "active" : ""
414
+ }`}
415
+ key={facet.name + "desktop"}
416
+ >
417
+ <div>
418
+ <div
419
+ className="searchstax-facet-title-container"
420
+ onClick={() => {
421
+ toggleFacetGroup(facet.name);
422
+ }}
423
+ >
424
+ <div className="searchstax-facet-title"> {facet.label} kjhjk</div>
425
+ <div className="searchstax-facet-title-arrow active"></div>
426
+ </div>
427
+ <div className="searchstax-facet-values-container">
428
+ {facet.values.map(
429
+ //@ts-ignore
430
+ (facetValue: IFacetValueData, key) => {
431
+ facetContainers[key + facet.name] = createRef();
432
+ return (
433
+ <div
434
+ key={facetValue.value + facetValue.parentName}
435
+ className={`searchstax-facet-value-container ${
436
+ facetValue.disabled
437
+ ? "searchstax-facet-value-disabled"
438
+ : ""
439
+ }`}
440
+ ref={facetContainers[key + facet.name]}
441
+ >
442
+ <div className="searchstax-facet-input">
443
+ <input
444
+ type="checkbox"
445
+ className="searchstax-facet-input-checkbox"
446
+ checked={isChecked(facetValue)}
447
+ readOnly={true}
448
+ disabled={facetValue.disabled}
449
+ onClick={(e) => {
450
+ selectFacet(
451
+ key + facet.name,
452
+ e,
453
+ facetValue,
454
+ true
455
+ );
456
+ }}
457
+ />
458
+ </div>
459
+ <div
460
+ className="searchstax-facet-value-label"
461
+ onClick={(e) => {
462
+ selectFacet(
463
+ key + facet.name,
464
+ e,
465
+ facetValue,
466
+ false
467
+ );
468
+ }}
469
+ >
470
+ {facetValue.value}
471
+ </div>
472
+ <div
473
+ className="searchstax-facet-value-count"
474
+ onClick={(e) => {
475
+ selectFacet(
476
+ key + facet.name,
477
+ e,
478
+ facetValue,
479
+ false
480
+ );
481
+ }}
482
+ >
483
+ ({facetValue.count})
484
+ </div>
485
+ </div>
486
+ );
487
+ }
488
+ )}
489
+
490
+ {facet.hasMoreFacets && (
491
+ <div className="searchstax-facet-show-more-container">
492
+ <div
493
+ className="searchstax-facet-show-more-container"
494
+ onClick={(e) => {
495
+ showMoreLessDesktop(e, facet);
496
+ }}
497
+ >
498
+ {facet.showingAllFacets && (
499
+ <div className="searchstax-facet-show-less-button searchstax-facet-show-button">
500
+ less
501
+ </div>
502
+ )}
503
+ {!facet.showingAllFacets && (
504
+ <div className="searchstax-facet-show-more-button searchstax-facet-show-button">
505
+ more
506
+ </div>
507
+ )}
508
+ </div>
509
+ </div>
510
+ )}
511
+ </div>
512
+ </div>
513
+ </div>
514
+ );
515
+ })}
516
+ </div>
517
+ );
518
+ }
341
519
 
520
+ function facetsTemplateMobile(
521
+ facetsTemplateDataMobile: IFacetsTemplateData | null,
522
+ selectedFacetsCheckboxes: IFacetValue[],
523
+ facetContainers: {
524
+ [key: string]: React.LegacyRef<HTMLDivElement> | undefined;
525
+ },
526
+ isNotDeactivated: (name: string) => boolean,
527
+ toggleFacetGroup: (name: string) => void,
528
+ selectFacet: (
529
+ index: string,
530
+ event: React.MouseEvent<HTMLDivElement, MouseEvent>,
531
+ data: IFacetValueData,
532
+ isInput: boolean
533
+ ) => void,
534
+ isChecked: (facetValue: IFacetValueData) => boolean | undefined,
535
+ unselectFacet: (facet: IFacetValue) => void,
536
+ showMoreLessMobile: (
537
+ e: React.MouseEvent<HTMLDivElement, MouseEvent>,
538
+ data: IFacetData
539
+ ) => void,
540
+ openOverlay: () => void,
541
+ closeOverlay: () => void,
542
+ unselectAll: () => void
543
+ ) {
544
+ return facetsTemplateDataMobile ? (
545
+ <div className="searchstax-facets-container-mobile">
546
+ <div className="searchstax-facets-pills-container">
547
+ <div
548
+ className="searchstax-facets-pill searchstax-facets-pill-filter-by"
549
+ onClick={() => {
550
+ openOverlay();
551
+ }}
552
+ >
553
+ <div className="searchstax-facets-pill-label">Filter By</div>
554
+ </div>
555
+ <div className="searchstax-facets-pills-selected">
556
+ {selectedFacetsCheckboxes.map((facet) => {
557
+ return (
558
+ <div
559
+ className="searchstax-facets-pill searchstax-facets-pill-facets"
560
+ key={facet.value}
561
+ onClick={() => {
562
+ unselectFacet(facet);
563
+ }}
564
+ >
565
+ <div className="searchstax-facets-pill-label">
566
+ {facet.value} ({facet.count})
567
+ </div>
568
+ <div className="searchstax-facets-pill-icon-close"></div>
569
+ </div>
570
+ );
571
+ })}
572
+ {selectedFacetsCheckboxes.length !== 0 && (
573
+ <div
574
+ className="searchstax-facets-pill searchstax-clear-filters searchstax-facets-pill-clear-all"
575
+ onClick={() => {
576
+ unselectAll();
577
+ }}
578
+ >
579
+ <div className="searchstax-facets-pill-label">
580
+ Clear Filters
581
+ </div>
582
+ </div>
583
+ )}
584
+ </div>
585
+ <div
586
+ className={`searchstax-facets-mobile-overlay ${
587
+ //@ts-ignore
588
+ facetsTemplateDataMobile.overlayOpened ? "searchstax-show" : ""
589
+ }`}
590
+ >
591
+ <div className="searchstax-facets-mobile-overlay-header">
592
+ <div className="searchstax-facets-mobile-overlay-header-title">
593
+ Filter By
594
+ </div>
595
+ <div
596
+ className="searchstax-search-close"
597
+ onClick={() => {
598
+ closeOverlay();
599
+ }}
600
+ ></div>
601
+ </div>
602
+ <div className="searchstax-facets-container-mobile">
603
+ {facetsTemplateDataMobile?.facets.map((facet) => {
604
+ return (
605
+ <div
606
+ key={facet.name + "mobile"}
607
+ className={`searchstax-facet-container ${
608
+ isNotDeactivated(facet.name) ? `active` : ``
609
+ }`}
610
+ >
611
+ <div>
612
+ <div
613
+ className="searchstax-facet-title-container"
614
+ onClick={() => {
615
+ toggleFacetGroup(facet.name);
616
+ }}
617
+ >
618
+ <div className="searchstax-facet-title">
619
+ {" "}
620
+ {facet.label}{" "}
621
+ </div>
622
+ <div className="searchstax-facet-title-arrow active"></div>
623
+ </div>
624
+ <div className="searchstax-facet-values-container">
625
+ {facet.values.map(
626
+ //@ts-ignore
627
+ (facetValue: IFacetValueData, key) => {
628
+ facetContainers[key + facet.name] = createRef();
629
+
630
+ return (
631
+ <div
632
+ key={facetValue.value + facetValue.parentName}
633
+ className={`searchstax-facet-value-container ${
634
+ facetValue.disabled
635
+ ? `searchstax-facet-value-disabled`
636
+ : ``
637
+ }`}
638
+ ref={facetContainers[key + facet.name]}
639
+ >
640
+ <div className="searchstax-facet-input">
641
+ <input
642
+ type="checkbox"
643
+ className="searchstax-facet-input-checkbox"
644
+ checked={isChecked(facetValue)}
645
+ readOnly={true}
646
+ disabled={facetValue.disabled}
647
+ onClick={(e) => {
648
+ selectFacet(
649
+ key + facet.name,
650
+ e,
651
+ facetValue,
652
+ true
653
+ );
654
+ }}
655
+ />
656
+ </div>
657
+ <div
658
+ className="searchstax-facet-value-label"
659
+ onClick={(e) => {
660
+ selectFacet(
661
+ key + facet.name,
662
+ e,
663
+ facetValue,
664
+ false
665
+ );
666
+ }}
667
+ >
668
+ {facetValue.value}
669
+ </div>
670
+ <div
671
+ className="searchstax-facet-value-count"
672
+ onClick={(e) => {
673
+ selectFacet(
674
+ key + facet.name,
675
+ e,
676
+ facetValue,
677
+ false
678
+ );
679
+ }}
680
+ >
681
+ ({facetValue.count})
682
+ </div>
683
+ </div>
684
+ );
685
+ }
686
+ )}
687
+
688
+ <div
689
+ className="searchstax-facet-show-more-container"
690
+ v-if="facet.hasMoreFacets"
691
+ >
692
+ <div
693
+ className="searchstax-facet-show-more-container"
694
+ onClick={(e) => {
695
+ showMoreLessMobile(e, facet);
696
+ }}
697
+ >
698
+ {facet.showingAllFacets && (
699
+ <div className="searchstax-facet-show-less-button searchstax-facet-show-button">
700
+ less
701
+ </div>
702
+ )}
703
+ {!facet.showingAllFacets && (
704
+ <div className="searchstax-facet-show-more-button searchstax-facet-show-button">
705
+ more
706
+ </div>
707
+ )}
708
+ </div>
709
+ </div>
710
+ </div>
711
+ </div>
712
+ </div>
713
+ );
714
+ })}
715
+ </div>
716
+ <button
717
+ className="searchstax-facets-mobile-overlay-done"
718
+ onClick={() => {
719
+ closeOverlay();
720
+ }}
721
+ >
722
+ Done
723
+ </button>
724
+ </div>
725
+ </div>
726
+ </div>
727
+ ) : (<></>);
728
+ }
729
+ <SearchstaxFacetsWidget
730
+ facetingType="and"
731
+ itemsPerPageDesktop={2}
732
+ itemsPerPageMobile={3}
733
+ specificFacets={undefined}
734
+ facetsTemplateDesktop={facetsTemplateDesktop}
735
+ facetsTemplateMobile={facetsTemplateMobile}
736
+ ></SearchstaxFacetsWidget>
342
737
  ```
343
738
 
344
739
  ### SearchFeedback Widget ###
345
740
 
346
741
  example of search feedback widget initialization with minimum options
347
742
  ```
348
-
743
+ <SearchstaxOverviewWidget></SearchstaxOverviewWidget>
349
744
  ```
350
745
 
351
746
 
352
747
  example of search feedback widget initialization with template overrides
353
748
  ```
354
-
749
+ function searchOverviewTemplate(
750
+ searchFeedbackData: null | ISearchstaxSearchFeedbackData,
751
+ onOriginalQueryClick: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void
752
+ ) {
753
+ return (
754
+ <>
755
+ {searchFeedbackData && searchFeedbackData?.searchExecuted && searchFeedbackData?.totalResults && (
756
+ <>
757
+ Showing{" "}
758
+ <b>
759
+ {searchFeedbackData.startResultIndex} - {searchFeedbackData.endResultIndex}
760
+ </b>{" "}
761
+ of
762
+ <b> {searchFeedbackData.totalResults}</b> results
763
+ {searchFeedbackData.searchTerm && (
764
+ <span>
765
+ &nbsp;for "<b>{searchFeedbackData.searchTerm}</b>"{" "}
766
+ </span>
767
+ )}
768
+ <div className="searchstax-feedback-container-suggested">
769
+ {searchFeedbackData.autoCorrectedQuery && (
770
+ <div>
771
+ {" "}
772
+ Search instead for{" "}
773
+ <a
774
+ href="#"
775
+ onClick={(e) => {
776
+ onOriginalQueryClick(e);
777
+ }}
778
+ className="searchstax-feedback-original-query"
779
+ >
780
+ {searchFeedbackData.originalQuery}
781
+ </a>
782
+ </div>
783
+ )}
784
+ </div>
785
+ </>
786
+ )}
787
+ </>
788
+ );
789
+ }
790
+ <SearchstaxOverviewWidget searchOverviewTemplate={searchOverviewTemplate}></SearchstaxOverviewWidget>
355
791
  ```
356
792
 
357
793
  ## RelatedSearches widget
@@ -387,13 +823,42 @@ example of search feedback widget initialization with template overrides
387
823
 
388
824
  example of sorting widget initialization with minimum options
389
825
  ```
390
-
826
+ <SearchstaxSortingWidget></SearchstaxSortingWidget>
391
827
  ```
392
828
 
393
829
 
394
830
  example of sorting widget initialization with template override
395
831
  ```
396
-
832
+ function searchSortingTemplate(
833
+ sortingData: null | ISearchstaxSearchSortingData,
834
+ orderChange: (value: string) => void,
835
+ selectedSorting: string
836
+ ) {
837
+ return (
838
+ <>
839
+ {sortingData && sortingData?.searchExecuted && sortingData?.hasResultsOrExternalPromotions && (
840
+ <div className="searchstax-sorting-container">
841
+ <label className="searchstax-sorting-label" htmlFor="sort-by">
842
+ Sort By
843
+ </label>
844
+ <select
845
+ id="searchstax-search-order-select"
846
+ className="searchstax-search-order-select"
847
+ value={selectedSorting}
848
+ onChange={(e) => {
849
+ orderChange(e.target.value);
850
+ }}
851
+ >
852
+ <option value=""> Relevance </option>
853
+ <option value="date desc"> Newest Content </option>
854
+ <option value="date asc"> Oldest Content </option>
855
+ </select>
856
+ </div>
857
+ )}
858
+ </>
859
+ );
860
+ }
861
+ <SearchstaxSortingWidget searchSortingTemplate={searchSortingTemplate}></SearchstaxSortingWidget>
397
862
  ```
398
863
 
399
864
 
@@ -0,0 +1,14 @@
1
+ import type { IFacetsTemplateData, IFacetValue, IFacetData, IFacetValueData } from "@searchstax-inc/searchstudio-ux-js";
2
+ declare function SearchstaxFacetsWidget(props: {
3
+ facetingType: "and" | "or" | "showUnavailable" | "tabs";
4
+ itemsPerPageDesktop: number;
5
+ itemsPerPageMobile: number;
6
+ specificFacets: string[] | undefined;
7
+ facetsTemplateDesktop?: (facetsTemplateDataDesktop: IFacetsTemplateData | null, facetContainers: {
8
+ [key: string]: React.LegacyRef<HTMLDivElement> | undefined;
9
+ }, isNotDeactivated: (name: string) => boolean, toggleFacetGroup: (name: string) => void, selectFacet: (index: string, event: React.MouseEvent<HTMLDivElement, MouseEvent>, data: IFacetValueData, isInput: boolean) => void, isChecked: (facetValue: IFacetValueData) => boolean | undefined, showMoreLessDesktop: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, data: IFacetData) => void) => React.ReactElement;
10
+ facetsTemplateMobile?: (facetsTemplateDataMobile: IFacetsTemplateData | null, selectedFacetsCheckboxes: IFacetValue[], facetContainers: {
11
+ [key: string]: React.LegacyRef<HTMLDivElement> | undefined;
12
+ }, isNotDeactivated: (name: string) => boolean, toggleFacetGroup: (name: string) => void, selectFacet: (index: string, event: React.MouseEvent<HTMLDivElement, MouseEvent>, data: IFacetValueData, isInput: boolean) => void, isChecked: (facetValue: IFacetValueData) => boolean | undefined, unselectFacet: (facet: IFacetValue) => void, showMoreLessMobile: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, data: IFacetData) => void, openOverlay: () => void, closeOverlay: () => void, unselectAll: () => void) => React.ReactElement;
13
+ }): import("react/jsx-runtime").JSX.Element;
14
+ export default SearchstaxFacetsWidget;
@@ -0,0 +1,5 @@
1
+ import type { ISearchstaxSearchFeedbackData } from "@searchstax-inc/searchstudio-ux-js";
2
+ declare function SearchstaxOverviewWidget(props: {
3
+ searchOverviewTemplate?: (searchFeedbackData: null | ISearchstaxSearchFeedbackData, onOriginalQueryClick: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void) => React.ReactElement;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ export default SearchstaxOverviewWidget;
@@ -0,0 +1,5 @@
1
+ import type { IPaginationData } from "@searchstax-inc/searchstudio-ux-js";
2
+ declare function SearchstaxPaginationWidget(props: {
3
+ paginationTemplate?: (paginationData: IPaginationData | null, nextPage: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void, previousPage: (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => void) => React.ReactElement;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ export default SearchstaxPaginationWidget;
@@ -0,0 +1,5 @@
1
+ import type { ISearchstaxSearchSortingData } from "@searchstax-inc/searchstudio-ux-js";
2
+ declare function SearchstaxSortingWidget(props: {
3
+ searchSortingTemplate?: (sortingData: null | ISearchstaxSearchSortingData, orderChange: (value: string) => void, selectedSorting: string) => React.ReactElement;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ export default SearchstaxSortingWidget;
@@ -1 +1,8 @@
1
- export * from '../main'
1
+ import SearchstaxInputWidget from "./components/SearchstaxInputWidget";
2
+ import SearchstaxWrapper from "./components/SearchstaxWrapper";
3
+ import SearchstaxResultWidget from "./components/SearchstaxResultWidget";
4
+ import SearchstaxPaginationWidget from "./components/SearchstaxPaginationWidget";
5
+ import SearchstaxSortingWidget from "./components/SearchstaxSortingWidget";
6
+ import SearchstaxOverviewWidget from "./components/SearchstaxOverviewWidget";
7
+ import SearchstaxFacetsWidget from "./components/SearchstaxFacetsWidget";
8
+ export { SearchstaxWrapper, SearchstaxResultWidget, SearchstaxInputWidget, SearchstaxPaginationWidget, SearchstaxSortingWidget, SearchstaxOverviewWidget, SearchstaxFacetsWidget, };