@envive-ai/react-toolkit 0.1.10 → 0.1.12

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 (162) hide show
  1. package/dist/Accordion/index.cjs +3 -82
  2. package/dist/Accordion/index.d.cts +2 -2
  3. package/dist/Accordion/index.d.ts +2 -2
  4. package/dist/Accordion/index.js +2 -75
  5. package/dist/Accordion-Cp3Hx2zm.js +77 -0
  6. package/dist/Accordion-DBZpiQe7.cjs +88 -0
  7. package/dist/AppliedFiltersScrollbar/index.d.cts +2 -2
  8. package/dist/AppliedFiltersScrollbar/index.d.ts +2 -2
  9. package/dist/ButtonBase/index.cjs +2 -2
  10. package/dist/ButtonBase/index.d.cts +2 -2
  11. package/dist/ButtonBase/index.d.ts +2 -2
  12. package/dist/ButtonBase/index.js +2 -2
  13. package/dist/DynamicFiltersScrollbar/index.d.cts +2 -2
  14. package/dist/DynamicFiltersScrollbar/index.d.ts +2 -2
  15. package/dist/FilterScrollbar/index.cjs +1 -1
  16. package/dist/FilterScrollbar/index.d.cts +3 -3
  17. package/dist/FilterScrollbar/index.d.ts +3 -3
  18. package/dist/FilterScrollbar/index.js +1 -1
  19. package/dist/Headline/index.cjs +1 -1
  20. package/dist/Headline/index.d.cts +2 -2
  21. package/dist/Headline/index.d.ts +2 -2
  22. package/dist/Headline/index.js +1 -1
  23. package/dist/ImageWithFallback/index.d.cts +2 -2
  24. package/dist/ImageWithFallback/index.d.ts +2 -2
  25. package/dist/ModalSheet/index.cjs +3 -0
  26. package/dist/ModalSheet/index.d.cts +38 -0
  27. package/dist/ModalSheet/index.d.ts +38 -0
  28. package/dist/ModalSheet/index.js +3 -0
  29. package/dist/ModalSheet-01pxpy_K.js +326 -0
  30. package/dist/ModalSheet-Csz8HIxs.cjs +337 -0
  31. package/dist/ProductCard/index.cjs +3 -3
  32. package/dist/ProductCard/index.d.cts +1 -1
  33. package/dist/ProductCard/index.d.ts +1 -1
  34. package/dist/ProductCard/index.js +3 -3
  35. package/dist/{ProductCard-Dkkhl9pk.js → ProductCard-C3MjnfZJ.js} +3 -3
  36. package/dist/{ProductCard-CymUvJnC.cjs → ProductCard-FDyIMnZs.cjs} +5 -5
  37. package/dist/ProductGrid/index.cjs +4 -4
  38. package/dist/ProductGrid/index.d.cts +3 -3
  39. package/dist/ProductGrid/index.d.ts +3 -3
  40. package/dist/ProductGrid/index.js +4 -4
  41. package/dist/{ProductGrid-B3Ypqh7j.js → ProductGrid-C9OKsyB2.js} +1 -1
  42. package/dist/{ProductGrid-ZNRujkuN.cjs → ProductGrid-TlntVJ6h.cjs} +1 -1
  43. package/dist/RadioButton/index.cjs +6 -0
  44. package/dist/RadioButton/index.d.cts +30 -0
  45. package/dist/RadioButton/index.d.ts +30 -0
  46. package/dist/RadioButton/index.js +6 -0
  47. package/dist/RadioButton-Bf68dZl7.js +68 -0
  48. package/dist/RadioButton-DZ6QXkrN.cjs +77 -0
  49. package/dist/RadioButtonGroup/index.cjs +8 -0
  50. package/dist/RadioButtonGroup/index.d.cts +36 -0
  51. package/dist/RadioButtonGroup/index.d.ts +36 -0
  52. package/dist/RadioButtonGroup/index.js +7 -0
  53. package/dist/RadioButtonGroup-8k7hkJYB.js +37 -0
  54. package/dist/RadioButtonGroup-Dc_n5amh.cjs +51 -0
  55. package/dist/SearchAutocomplete/index.cjs +1 -1
  56. package/dist/SearchAutocomplete/index.js +1 -1
  57. package/dist/SearchFilter/index.cjs +9 -2
  58. package/dist/SearchFilter/index.d.cts +15 -9
  59. package/dist/SearchFilter/index.d.ts +15 -9
  60. package/dist/SearchFilter/index.js +9 -2
  61. package/dist/SearchFilter-CTVBi5s3.cjs +279 -0
  62. package/dist/SearchFilter-DvqBIXa1.js +258 -0
  63. package/dist/SearchInput/index.cjs +3 -3
  64. package/dist/SearchInput/index.d.cts +1 -1
  65. package/dist/SearchInput/index.d.ts +2 -2
  66. package/dist/SearchInput/index.js +3 -3
  67. package/dist/{SearchInput-BT1rrc4F.js → SearchInput-CVaCPWCE.js} +2 -2
  68. package/dist/{SearchInput-CdR_nsR3.cjs → SearchInput-vJMWoLzS.cjs} +2 -2
  69. package/dist/SearchInputForm/index.cjs +4 -4
  70. package/dist/SearchInputForm/index.d.cts +1 -1
  71. package/dist/SearchInputForm/index.d.ts +1 -1
  72. package/dist/SearchInputForm/index.js +4 -4
  73. package/dist/SearchResultsContent/index.cjs +14 -14
  74. package/dist/SearchResultsContent/index.d.cts +5 -5
  75. package/dist/SearchResultsContent/index.d.ts +5 -5
  76. package/dist/SearchResultsContent/index.js +10 -10
  77. package/dist/SearchResultsFilterSidebar/index.cjs +15 -8
  78. package/dist/SearchResultsFilterSidebar/index.d.cts +1 -1
  79. package/dist/SearchResultsFilterSidebar/index.d.ts +1 -1
  80. package/dist/SearchResultsFilterSidebar/index.js +13 -6
  81. package/dist/SearchResultsStates/index.cjs +9 -9
  82. package/dist/SearchResultsStates/index.d.cts +6 -6
  83. package/dist/SearchResultsStates/index.d.ts +6 -6
  84. package/dist/SearchResultsStates/index.js +9 -9
  85. package/dist/{SearchResultsStates-ESlrrf20.cjs → SearchResultsStates-CH4agenX.cjs} +5 -5
  86. package/dist/{SearchResultsStates-BxJphoL-.js → SearchResultsStates-iKz64Pd4.js} +5 -5
  87. package/dist/SparkleAnimation/index.cjs +1 -1
  88. package/dist/SparkleAnimation/index.d.cts +2 -2
  89. package/dist/SparkleAnimation/index.d.ts +2 -2
  90. package/dist/SparkleAnimation/index.js +1 -1
  91. package/dist/Spinner/index.cjs +1 -1
  92. package/dist/Spinner/index.d.cts +2 -2
  93. package/dist/Spinner/index.d.ts +2 -2
  94. package/dist/Spinner/index.js +1 -1
  95. package/dist/SuggestionButton/index.cjs +1 -1
  96. package/dist/SuggestionButton/index.d.cts +2 -2
  97. package/dist/SuggestionButton/index.d.ts +2 -2
  98. package/dist/SuggestionButton/index.js +1 -1
  99. package/dist/Text/index.d.cts +2 -2
  100. package/dist/Text/index.d.ts +3 -3
  101. package/dist/TextInput/index.cjs +1 -1
  102. package/dist/TextInput/index.d.ts +1 -1
  103. package/dist/TextInput/index.js +1 -1
  104. package/dist/ToggleButton/index.cjs +6 -0
  105. package/dist/ToggleButton/index.d.cts +30 -0
  106. package/dist/ToggleButton/index.d.ts +30 -0
  107. package/dist/ToggleButton/index.js +6 -0
  108. package/dist/ToggleButton-CK_vkMvt.cjs +68 -0
  109. package/dist/ToggleButton-GIVd2-Z4.js +60 -0
  110. package/dist/{index-DV2K-9lE.d.cts → index-B8l3muO3.d.ts} +5 -5
  111. package/dist/{index-agU5rfIs.d.ts → index-BMt66uqr.d.cts} +5 -5
  112. package/dist/{index-b4yAASuy.d.cts → index-CFH3KUVw.d.cts} +4 -4
  113. package/dist/{index-uU3sIiRx.d.ts → index-H_9LhS_1.d.cts} +2 -2
  114. package/dist/{index-DggZTKvc.d.ts → index-Vck3pox6.d.ts} +4 -4
  115. package/dist/{index-Bpjv4lP2.d.cts → index-h-QwQNnu.d.ts} +2 -2
  116. package/dist/{searchFilterSidebarVariants-BnIcOVWR.js → searchFilterSidebarVariants-CI782ylo.js} +1 -1
  117. package/dist/{searchFilterSidebarVariants-DVZ7wRlb.cjs → searchFilterSidebarVariants-DFfOTqjc.cjs} +1 -1
  118. package/package.json +20 -3
  119. package/src/components/AnimatedChevron/AnimatedChevron.tsx +37 -0
  120. package/src/components/ModalSheet/ModalSheet.tsx +42 -0
  121. package/src/components/ModalSheet/common/closeIcon.tsx +40 -0
  122. package/src/components/ModalSheet/desktop/desktopHeader.tsx +24 -0
  123. package/src/components/ModalSheet/desktop/index.tsx +119 -0
  124. package/src/components/ModalSheet/index.ts +1 -0
  125. package/src/components/ModalSheet/mobile/index.tsx +118 -0
  126. package/src/components/ModalSheet/mobile/mobileHeader.tsx +42 -0
  127. package/src/components/ModalSheet/types.ts +33 -0
  128. package/src/components/ProductCard/ProductCard.tsx +1 -1
  129. package/src/components/RadioButton/RadioButton.tsx +88 -0
  130. package/src/components/RadioButton/index.ts +1 -0
  131. package/src/components/RadioButtonGroup/RadioButtonGroup.tsx +72 -0
  132. package/src/components/RadioButtonGroup/index.ts +1 -0
  133. package/src/components/SearchFilter/SearchFilter.tsx +161 -64
  134. package/src/components/SearchFilter/SearchFilterFooter.tsx +55 -0
  135. package/src/components/SearchFilter/types.ts +2 -1
  136. package/src/components/SearchFilter/useHasFilterStateChanged.tsx +40 -0
  137. package/src/components/SearchFilter/utils.ts +15 -0
  138. package/src/components/SearchResultsContent/SearchResultsContent.tsx +1 -1
  139. package/src/components/SearchResultsFilterSidebar/SearchResultsFilter.tsx +2 -2
  140. package/src/components/ToggleButton/ToggleButton.tsx +98 -0
  141. package/src/components/ToggleButton/index.ts +1 -0
  142. package/dist/SearchFilter-CLYCSNAa.cjs +0 -137
  143. package/dist/SearchFilter-qQPpx-34.js +0 -117
  144. /package/dist/{ButtonBase-C_uKnl48.js → ButtonBase-0NN6wmX-.js} +0 -0
  145. /package/dist/{ButtonBase-DGbSm0SJ.js → ButtonBase-BAf-nlCm.js} +0 -0
  146. /package/dist/{ButtonBase-DbWQ25n-.cjs → ButtonBase-BIXx56hq.cjs} +0 -0
  147. /package/dist/{ButtonBase-DGpQBeLR.cjs → ButtonBase-Do88ndKa.cjs} +0 -0
  148. /package/dist/{DynamicFiltersScrollbar-Dev5vGsW.js → DynamicFiltersScrollbar-C4kdNSJ9.js} +0 -0
  149. /package/dist/{DynamicFiltersScrollbar-ChvmEiPB.cjs → DynamicFiltersScrollbar-CVw1PINp.cjs} +0 -0
  150. /package/dist/{Headline-DTaT30_m.js → Headline-DNEWF8ly.js} +0 -0
  151. /package/dist/{Headline-DSmu5Mg8.cjs → Headline-DTT4RSv2.cjs} +0 -0
  152. /package/dist/{SearchAutocomplete-C4RY0IoT.js → SearchAutocomplete-BlpII8Xs.js} +0 -0
  153. /package/dist/{SearchAutocomplete-hQDnKtwQ.cjs → SearchAutocomplete-DIEhLT4C.cjs} +0 -0
  154. /package/dist/{SparkleAnimation-fQHP7b-R.js → SparkleAnimation-BLfNojLv.js} +0 -0
  155. /package/dist/{SparkleAnimation-BY5iw7s0.cjs → SparkleAnimation-qi5WCJ9B.cjs} +0 -0
  156. /package/dist/{Spinner-BqTt55uu.js → Spinner-CjGLIRgs.js} +0 -0
  157. /package/dist/{Spinner-DjK8ts9E.cjs → Spinner-DFor2Szi.cjs} +0 -0
  158. /package/dist/{TextInput-BJrdkZsM.cjs → TextInput-B3dTeD3q.cjs} +0 -0
  159. /package/dist/{TextInput-DIjjsSMg.js → TextInput-DoM41M53.js} +0 -0
  160. /package/dist/{colorsConfig-CJTKbJsm.cjs → colorsConfig-D-MZuBvt.cjs} +0 -0
  161. /package/dist/{colorsConfig-CYZ8f_gj.js → colorsConfig-DEfiLHH0.js} +0 -0
  162. /package/dist/{textVariantClasses-ypYGLq0h.d.ts → textVariantClasses-kyZtL8F5.d.ts} +0 -0
@@ -0,0 +1,119 @@
1
+ import { useEffect, useState } from 'react';
2
+ import classNames from 'classnames';
3
+ import { motion } from 'framer-motion';
4
+
5
+ import { ModalSheetProps } from '../types';
6
+ import { ModalSheetDesktopHeader } from './desktopHeader';
7
+
8
+ export const ModalSheetDesktop = ({
9
+ children,
10
+ isOpen,
11
+ closeModal,
12
+ desktopWidth = 512,
13
+ animationDuration,
14
+ headerProps,
15
+ footerProps,
16
+ showOverlay = false,
17
+ }: ModalSheetProps) => {
18
+ const [isHidden, setIsHidden] = useState(isOpen ? 'block' : 'none');
19
+ const [right, setRight] = useState(isOpen ? 0 : 0 - desktopWidth);
20
+ const [overlayOpacity, setOverlayOpacity] = useState(0);
21
+
22
+ useEffect(() => {
23
+ setIsHidden(isOpen ? 'block' : 'none');
24
+ setRight(isOpen ? 0 : 0 - desktopWidth);
25
+ setOverlayOpacity(isOpen ? 1 : 0);
26
+ }, [desktopWidth, isOpen]);
27
+
28
+ const overlayClassNames = classNames({
29
+ 'spiffy-modal-sheet-overlay': true,
30
+ 'spiffy-tw-fixed': true,
31
+ 'spiffy-tw-inset-0': true,
32
+ 'spiffy-tw-top-[0]': true,
33
+ 'spiffy-tw-bottom-[0]': true,
34
+ 'spiffy-tw-left-[0]': true,
35
+ 'spiffy-tw-right-[0]': true,
36
+ 'spiffy-tw-z-[2147483647]': true,
37
+ 'spiffy-tw-bg-black/30': showOverlay,
38
+ });
39
+
40
+ const modalClassNames = classNames({
41
+ 'spiffy-modal-sheet': true,
42
+ 'spiffy-modal-sheet-open': isOpen,
43
+ 'spiffy-tw-max-h-full': true,
44
+ 'spiffy-tw-h-screen': true,
45
+ 'spiffy-tw-w-[512px]': true,
46
+ 'spiffy-tw-shadow-lg': true,
47
+ 'spiffy-tw-top-[0]': true,
48
+ 'spiffy-tw-bottom-[0]': true,
49
+ 'spiffy-tw-fixed': true,
50
+ 'spiffy-tw-bg-white': true,
51
+ 'spiffy-tw-border-box': true,
52
+ });
53
+
54
+ const contentClassNames = classNames({
55
+ 'spiffy-modal-sheet-content': true,
56
+ 'spiffy-tw-overflow-y-auto': true,
57
+ 'spiffy-tw-overflow-x-hidden': true,
58
+ 'spiffy-tw-flex': true,
59
+ 'spiffy-tw-flex-col': true,
60
+ 'spiffy-tw-h-full': true,
61
+ 'spiffy-tw-w-full': true,
62
+ });
63
+
64
+ const headerClassNames = classNames({
65
+ 'spiffy-tw-sticky': true,
66
+ 'spiffy-tw-top-0': true,
67
+ 'spiffy-tw-flex': true,
68
+ 'spiffy-tw-flex-col': true,
69
+ });
70
+
71
+ const { footerContent, footerClassName } = footerProps || {};
72
+
73
+ const footerClassNames = classNames(
74
+ {
75
+ 'spiffy-tw-sticky': true,
76
+ 'spiffy-tw-bottom-0': true,
77
+ 'spiffy-modal-sheet-footer': true,
78
+ 'spiffy-tw-flex': true,
79
+ 'spiffy-tw-flex-col': true,
80
+ },
81
+ footerClassName,
82
+ );
83
+
84
+ return (
85
+ <div>
86
+ <motion.div
87
+ className={overlayClassNames}
88
+ initial={{ opacity: 0, display: 'none' }}
89
+ animate={{ opacity: overlayOpacity, display: isHidden }}
90
+ onClick={closeModal}
91
+ >
92
+ <motion.div
93
+ role="dialog"
94
+ className={modalClassNames}
95
+ initial={{ right, display: isHidden }}
96
+ animate={{ right, display: isHidden }}
97
+ exit={{ right, display: isHidden }}
98
+ transition={{ duration: animationDuration, ease: 'easeIn' }}
99
+ style={{ width: desktopWidth }}
100
+ onClick={(e) => e.stopPropagation()}
101
+ >
102
+ <div className={contentClassNames}>
103
+ <div className={headerClassNames}>
104
+ <ModalSheetDesktopHeader
105
+ headerContent={headerProps.headerContent}
106
+ headerVariant={headerProps?.headerVariant}
107
+ chevronColor="#000"
108
+ />
109
+ </div>
110
+ {children}
111
+ {/* this div will grow to fill the remaining space */}
112
+ <div className="spiffy-tw-flex-grow" />
113
+ {footerContent && <div className={footerClassNames}>{footerContent}</div>}
114
+ </div>
115
+ </motion.div>
116
+ </motion.div>
117
+ </div>
118
+ );
119
+ };
@@ -0,0 +1 @@
1
+ export * from './ModalSheet';
@@ -0,0 +1,118 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import classNames from 'classnames';
4
+ import { motion } from 'framer-motion';
5
+
6
+ import { ModalSheetProps } from '../types';
7
+ import { ModalSheetMobileHeader } from './mobileHeader';
8
+
9
+ export const ModalSheetMobile = ({
10
+ children,
11
+ isOpen,
12
+ closeModal,
13
+ mobileFullHeight = 180,
14
+ animationDuration,
15
+ headerProps,
16
+ footerProps,
17
+ }: ModalSheetProps) => {
18
+ const [isHidden, setIsHidden] = useState(isOpen ? 'block' : 'none');
19
+ const [bottom, setBottom] = useState(isOpen ? 0 : 0 - mobileFullHeight);
20
+ const [overlayOpacity, setOverlayOpacity] = useState(isOpen ? 1 : 0);
21
+
22
+ useEffect(() => {
23
+ setIsHidden(isOpen ? 'block' : 'none');
24
+ setBottom(isOpen ? 0 : 0 - mobileFullHeight);
25
+ setOverlayOpacity(isOpen ? 1 : 0);
26
+ }, [mobileFullHeight, isOpen]);
27
+
28
+ // TODO: Support partial view
29
+
30
+ const overlayClassNames = classNames({
31
+ 'spiffy-modal-sheet-overlay': true,
32
+ 'spiffy-tw-fixed': true,
33
+ 'spiffy-tw-inset-0': true,
34
+ 'spiffy-tw-top-[0]': true,
35
+ 'spiffy-tw-bottom-[0]': true,
36
+ 'spiffy-tw-left-[0]': true,
37
+ 'spiffy-tw-right-[0]': true,
38
+ 'spiffy-tw-bg-black/30': true,
39
+ 'spiffy-tw-z-[100]': true,
40
+ });
41
+
42
+ const modalClassNames = classNames({
43
+ 'spiffy-modal-sheet': true,
44
+ 'spiffy-modal-sheet-open': isOpen,
45
+ 'spiffy-tw-w-full': true,
46
+ 'spiffy-tw-overflow-y-auto': true,
47
+ 'spiffy-tw-shadow-lg': true,
48
+ 'spiffy-tw-fixed': true,
49
+ 'spiffy-tw-bg-white': true,
50
+ 'spiffy-tw-border-box': true,
51
+ 'spiffy-tw-rounded-t-[16px]': true,
52
+ 'spiffy-tw-h-[89%]': true,
53
+ 'spiffy-tw-max-h-[89%]': true,
54
+ });
55
+
56
+ const contentClassNames = classNames({
57
+ 'spiffy-modal-sheet-content': true,
58
+ 'spiffy-tw-flex': true,
59
+ 'spiffy-tw-flex-col': true,
60
+ 'spiffy-tw-w-full': true,
61
+ 'spiffy-tw-h-full': true,
62
+ });
63
+
64
+ const headerClassNames = classNames({
65
+ 'spiffy-tw-sticky': true,
66
+ 'spiffy-tw-top-[0px]': true,
67
+ 'spiffy-tw-flex': true,
68
+ 'spiffy-tw-flex-col': true,
69
+ });
70
+ const { footerContent, footerClassName } = footerProps || {};
71
+
72
+ const footerClassNames = classNames(
73
+ {
74
+ 'spiffy-tw-sticky': true,
75
+ 'spiffy-tw-bottom-[0px]': true,
76
+ 'spiffy-modal-sheet-footer': true,
77
+ 'spiffy-tw-flex': true,
78
+ 'spiffy-tw-flex-col': true,
79
+ },
80
+ footerClassName,
81
+ );
82
+
83
+ return (
84
+ <div>
85
+ <motion.div
86
+ className={overlayClassNames}
87
+ animate={{ opacity: overlayOpacity, display: isHidden }}
88
+ onClick={closeModal}
89
+ >
90
+ <motion.div
91
+ role="dialog"
92
+ className={modalClassNames}
93
+ initial={{ bottom, display: isHidden }}
94
+ animate={{ bottom, display: isHidden }}
95
+ exit={{ bottom, display: isHidden }}
96
+ transition={{ duration: animationDuration, ease: 'easeIn' }}
97
+ onClick={(e) => e.stopPropagation()}
98
+ >
99
+ <div className={contentClassNames}>
100
+ <div className={headerClassNames}>
101
+ <ModalSheetMobileHeader
102
+ headerContent={headerProps.headerContent}
103
+ headerVariant={headerProps?.headerVariant}
104
+ handleHeaderClick={closeModal}
105
+ chevronColor="#000"
106
+ />
107
+ </div>
108
+ {children}
109
+ {/* this div will grow to fill the remaining space */}
110
+ <div className="spiffy-tw-flex-grow" />
111
+
112
+ {footerContent && <div className={footerClassNames}>{footerContent}</div>}
113
+ </div>
114
+ </motion.div>
115
+ </motion.div>
116
+ </div>
117
+ );
118
+ };
@@ -0,0 +1,42 @@
1
+ import classNames from 'classnames';
2
+ import { motion, useMotionValue } from 'framer-motion';
3
+ import { ModalSheetHeaderProps } from '../types';
4
+ import { AnimatedChevron } from 'src/components/AnimatedChevron/AnimatedChevron';
5
+
6
+ const modalSheetVariants = {
7
+ primary: {
8
+ 'spiffy-tw-bg-[--spiffy-colors-background-primary]': true,
9
+ 'spiffy-tw-text-[--spiffy-colors-text-light]': true,
10
+ },
11
+ };
12
+
13
+ export const ModalSheetMobileHeader = ({
14
+ headerVariant = 'primary',
15
+ headerContent,
16
+ handleHeaderClick,
17
+ chevronColor,
18
+ }: ModalSheetHeaderProps) => {
19
+ const animationKey = useMotionValue(-1);
20
+ const headerClassName = classNames({
21
+ 'spiffy-modal-sheet-header': true,
22
+ 'spiffy-tw-flex': true,
23
+ 'spiffy-tw-items-center': true,
24
+ 'spiffy-tw-justify-between': true,
25
+ 'spiffy-tw-w-full': true,
26
+ 'spiffy-tw-flex-col': true,
27
+ 'spiffy-tw-pt-[16px]': true,
28
+ 'spiffy-tw-shadow-[0px_-8px_16px_0px_#0000001A]': true,
29
+ ...modalSheetVariants[headerVariant],
30
+ });
31
+
32
+ return (
33
+ <motion.div
34
+ className={headerClassName}
35
+ onTouchStart={handleHeaderClick}
36
+ onMouseDown={handleHeaderClick}
37
+ >
38
+ <AnimatedChevron animationKey={animationKey} chevronColor={chevronColor} />
39
+ {headerContent}
40
+ </motion.div>
41
+ );
42
+ };
@@ -0,0 +1,33 @@
1
+ export type ModalSheetProps = {
2
+ children: React.ReactNode;
3
+ isOpen: boolean;
4
+ closeModal: () => void;
5
+ desktopWidth?: number;
6
+ mobileFullHeight?: number;
7
+ animationDuration?: number;
8
+ headerProps: ModalSheetHeaderProps;
9
+ footerProps?: ModalSheetFooterProps;
10
+ showOverlay?: boolean;
11
+ };
12
+
13
+ export type ModalSheetHeaderProps = {
14
+ headerVariant?: ModalSheetHeaderVariant;
15
+ headerContent: React.ReactNode;
16
+ handleHeaderClick?: () => void;
17
+ chevronColor: string;
18
+ };
19
+
20
+ export type ModalSheetFooterProps = {
21
+ footerContent: React.ReactNode;
22
+ footerClassName?: string;
23
+ };
24
+
25
+ export type ModalSheetHeaderVariant = 'primary';
26
+
27
+ export type CloseIconVariant = 'light' | 'tertiary' | 'dark';
28
+ export type ModalSheetCloseIconProps = {
29
+ closeIconVariant: CloseIconVariant;
30
+ closeIcon?: React.ReactNode;
31
+ closeModal?: () => void;
32
+ iconSize?: string;
33
+ };
@@ -18,8 +18,8 @@ import {
18
18
  } from './types';
19
19
  import { Text } from 'src/components/Text/Text';
20
20
  import { formatPrice } from 'src/util/formatPrice';
21
- import { useImageResolver } from '@envive-ai/react-hooks/hooks';
22
21
  import { TestProps } from '@envive-ai/react-hooks/types';
22
+ import { useImageResolver } from '@envive-ai/react-hooks/hooks/ImageResolver';
23
23
 
24
24
  const formatReviews = (stars: number) =>
25
25
  String(
@@ -0,0 +1,88 @@
1
+ import classNames from 'classnames';
2
+ import { Text } from 'src/components/Text';
3
+ import { useState } from 'react';
4
+ import { TestProps } from '@envive-ai/react-hooks/types';
5
+
6
+ interface RadioButtonProps extends TestProps {
7
+ isDisabled?: boolean;
8
+ label: string;
9
+ name: string;
10
+ value: string;
11
+ textButtonGap?: 'small' | 'medium' | 'large';
12
+ fillColor?: string;
13
+ hoverColor?: string;
14
+ uncheckedBorderColor?: string;
15
+ checked?: boolean;
16
+ onChange: (value: string) => void;
17
+ }
18
+
19
+ export const RadioButton = ({
20
+ isDisabled = false,
21
+ label,
22
+ name,
23
+ value,
24
+ textButtonGap = 'medium',
25
+ fillColor,
26
+ hoverColor,
27
+ uncheckedBorderColor,
28
+ checked = false,
29
+ onChange,
30
+ }: RadioButtonProps) => {
31
+ const [isHovered, setIsHovered] = useState(false);
32
+
33
+ const containerClassName = classNames({
34
+ 'spiffy-tw-flex': true,
35
+ 'spiffy-tw-items-center': true,
36
+ 'spiffy-tw-group': true,
37
+ 'spiffy-tw-gap-1': textButtonGap === 'small',
38
+ 'spiffy-tw-gap-2': textButtonGap === 'medium',
39
+ 'spiffy-tw-gap-4': textButtonGap === 'large',
40
+ 'spiffy-tw-cursor-pointer': !isDisabled,
41
+ 'spiffy-tw-opacity-40': isDisabled,
42
+ });
43
+
44
+ const getFillColor = () => {
45
+ if (isHovered && hoverColor) return hoverColor;
46
+ if (checked) return fillColor;
47
+ return uncheckedBorderColor;
48
+ };
49
+
50
+ const handleChange = () => {
51
+ if (!isDisabled) {
52
+ onChange(value);
53
+ }
54
+ };
55
+
56
+ return (
57
+ <label
58
+ className={containerClassName}
59
+ onMouseEnter={() => !isDisabled && setIsHovered(true)}
60
+ onMouseLeave={() => setIsHovered(false)}
61
+ >
62
+ <div className="spiffy-tw-relative">
63
+ <input
64
+ type="radio"
65
+ name={name}
66
+ value={value}
67
+ checked={checked}
68
+ disabled={isDisabled}
69
+ onChange={handleChange}
70
+ className="spiffy-tw-sr-only"
71
+ />
72
+ <svg
73
+ xmlns="http://www.w3.org/2000/svg"
74
+ width="24"
75
+ height="24"
76
+ viewBox="0 0 24 24"
77
+ fill="none"
78
+ >
79
+ {/* Outer circle (border). Gray when unchecked */}
80
+ <circle cx="12" cy="12" r="11.5" fill="white" stroke={getFillColor()} />
81
+ {/* Inner filled circle (when checked) */}
82
+ {checked && <circle cx="12" cy="12" r="9" fill={getFillColor()} />}
83
+ </svg>
84
+ </div>
85
+ <Text variant="body3">{label}</Text>
86
+ </label>
87
+ );
88
+ };
@@ -0,0 +1 @@
1
+ export * from './RadioButton';
@@ -0,0 +1,72 @@
1
+ import { TestProps } from '@envive-ai/react-hooks/types';
2
+ import classNames from 'classnames';
3
+ import { RadioButton } from '../RadioButton';
4
+
5
+ export const SPIFFY_RADIO_BUTTON_GROUP_CLASS = 'spiffy-radio-button-group-class';
6
+
7
+ interface RadioButtonOption {
8
+ label: string;
9
+ value: string;
10
+ disabled?: boolean;
11
+ }
12
+
13
+ interface RadioButtonGroupProps extends TestProps {
14
+ name: string;
15
+ options: RadioButtonOption[];
16
+ fillColor?: string;
17
+ hoverColor?: string;
18
+ value?: string;
19
+ isDisabled?: boolean;
20
+ gap?: 'small' | 'medium' | 'large'; // Gap between each radio button
21
+ textButtonGap?: 'small' | 'medium' | 'large'; // Gap between radio button and text
22
+ onChange: (value: string) => void;
23
+ uncheckedBorderColor?: string;
24
+ }
25
+
26
+ export const RadioButtonGroup = ({
27
+ name,
28
+ options,
29
+ fillColor,
30
+ hoverColor,
31
+ uncheckedBorderColor,
32
+ value,
33
+ isDisabled = false,
34
+ gap = 'medium',
35
+ textButtonGap = 'medium',
36
+ onChange,
37
+ }: RadioButtonGroupProps) => {
38
+ const groupClassName = classNames({
39
+ [SPIFFY_RADIO_BUTTON_GROUP_CLASS]: true,
40
+ 'spiffy-tw-flex': true,
41
+ 'spiffy-tw-flex-col': true,
42
+ 'spiffy-tw-gap-1': gap === 'small',
43
+ 'spiffy-tw-gap-2': gap === 'medium',
44
+ 'spiffy-tw-gap-4': gap === 'large',
45
+ });
46
+
47
+ const handleChange = (selectedValue: string) => {
48
+ if (!isDisabled) {
49
+ onChange(selectedValue);
50
+ }
51
+ };
52
+
53
+ return (
54
+ <div className={groupClassName}>
55
+ {options.map((option) => (
56
+ <RadioButton
57
+ key={option.value}
58
+ name={name}
59
+ value={option.value}
60
+ fillColor={fillColor}
61
+ hoverColor={hoverColor}
62
+ uncheckedBorderColor={uncheckedBorderColor}
63
+ label={option.label}
64
+ checked={value === option.value}
65
+ isDisabled={isDisabled || option.disabled}
66
+ onChange={handleChange}
67
+ textButtonGap={textButtonGap}
68
+ />
69
+ ))}
70
+ </div>
71
+ );
72
+ };
@@ -0,0 +1 @@
1
+ export * from './RadioButtonGroup';