@windstream/react-shared-components 0.1.79 → 0.1.81

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.
@@ -13,13 +13,15 @@ import { useCarouselSwipe } from "@shared/hooks/use-carousel-swipe";
13
13
  import { CheckPlansProps } from "@shared/types/micro-components";
14
14
  import { cx } from "@shared/utils";
15
15
 
16
- export function ProductCardCarousel({
16
+ function ProductCardPanel({
17
17
  fields,
18
18
  renderCheckPlans,
19
+ isVisible = true,
19
20
  }: {
20
21
  fields: CarouselWithProductCards;
21
22
  onModalButtonClick?: (id?: string) => void;
22
23
  renderCheckPlans?: (overrides?: CheckPlansProps) => React.ReactNode;
24
+ isVisible?: boolean;
23
25
  }) {
24
26
  const itemsExpanded = fields?.items?.items?.[0]?.benefitsExpanded || false;
25
27
  const [desktopExpanded, setDesktopExpanded] = useState(itemsExpanded);
@@ -29,6 +31,7 @@ export function ProductCardCarousel({
29
31
  const [currentIndex, setCurrentIndex] = useState(0);
30
32
  const items = fields?.items?.items || [];
31
33
  const isCarousel = items.length > 2;
34
+ const showArrows = fields?.showArrows !== false && isCarousel;
32
35
  const cardsRef = useRef<(HTMLDivElement | null)[]>([]);
33
36
 
34
37
  const prevSlide = useCallback(() => {
@@ -43,7 +46,7 @@ export function ProductCardCarousel({
43
46
 
44
47
  // Equalize card heights
45
48
  useEffect(() => {
46
- if (!isCarousel) return;
49
+ if (!isCarousel || !isVisible) return;
47
50
 
48
51
  const equalizeHeights = () => {
49
52
  const cards = cardsRef.current.filter(Boolean) as HTMLDivElement[];
@@ -70,7 +73,7 @@ export function ProductCardCarousel({
70
73
  const timeoutId = setTimeout(equalizeHeights, 100);
71
74
 
72
75
  return () => clearTimeout(timeoutId);
73
- }, [isCarousel, desktopExpanded, items.length]);
76
+ }, [isCarousel, isVisible, desktopExpanded, items.length]);
74
77
 
75
78
  if (!items.length && !fields?.title) {
76
79
  return null;
@@ -177,23 +180,25 @@ export function ProductCardCarousel({
177
180
  {/* Desktop View: Horizontal Carousel */}
178
181
  <div className="relative hidden w-full md:block">
179
182
  {/* Navigation Arrows */}
180
- <div className="pointer-events-none absolute -left-16 -right-16 top-[50%] z-30 flex -translate-y-1/2 justify-between px-4 md:px-10">
181
- <Button
182
- onClick={prevSlide}
183
- className="pointer-events-auto flex h-12 w-12 items-center justify-center rounded-full border border-gray-100 bg-white p-2 text-text shadow-cardDrop transition-all hover:bg-gray-50"
184
- aria-label="Previous"
185
- >
186
- <MaterialIcon name="arrow_back" size={24} />
187
- </Button>
188
-
189
- <Button
190
- onClick={nextSlide}
191
- className="pointer-events-auto flex h-12 w-12 items-center justify-center rounded-full border border-gray-100 bg-white p-2 text-text shadow-cardDrop transition-all hover:bg-gray-50"
192
- aria-label="Next"
193
- >
194
- <MaterialIcon name="arrow_forward" size={24} />
195
- </Button>
196
- </div>
183
+ {showArrows && (
184
+ <div className="pointer-events-none absolute -left-16 -right-16 top-[50%] z-30 flex -translate-y-1/2 justify-between px-4 md:px-10">
185
+ <Button
186
+ onClick={prevSlide}
187
+ className="pointer-events-auto flex h-12 w-12 items-center justify-center rounded-full border border-gray-100 bg-white p-2 text-text shadow-cardDrop transition-all hover:bg-gray-50"
188
+ aria-label="Previous"
189
+ >
190
+ <MaterialIcon name="arrow_back" size={24} />
191
+ </Button>
192
+
193
+ <Button
194
+ onClick={nextSlide}
195
+ className="pointer-events-auto flex h-12 w-12 items-center justify-center rounded-full border border-gray-100 bg-white p-2 text-text shadow-cardDrop transition-all hover:bg-gray-50"
196
+ aria-label="Next"
197
+ >
198
+ <MaterialIcon name="arrow_forward" size={24} />
199
+ </Button>
200
+ </div>
201
+ )}
197
202
 
198
203
  {/* Carousel Window */}
199
204
  <div className="mx-auto max-w-[1280px] overflow-hidden">
@@ -211,6 +216,55 @@ export function ProductCardCarousel({
211
216
  );
212
217
  }
213
218
 
219
+ export function ProductCardCarousel({
220
+ fields,
221
+ renderCheckPlans,
222
+ activeTab,
223
+ tabs,
224
+ }: {
225
+ fields: CarouselWithProductCards;
226
+ onModalButtonClick?: (id?: string) => void;
227
+ renderCheckPlans?: (overrides?: CheckPlansProps) => React.ReactNode;
228
+ activeTab?: string;
229
+ tabs?: string[];
230
+ }) {
231
+ const allItems = fields?.items?.items || [];
232
+
233
+ if (tabs && tabs.length > 1 && activeTab) {
234
+ return (
235
+ <>
236
+ {tabs.map(tab => {
237
+ const tabItems = allItems.filter(item => {
238
+ const category = item.productCategory || tabs[0];
239
+ return category === tab;
240
+ });
241
+ const tabFields = {
242
+ ...fields,
243
+ items: { ...fields.items, items: tabItems },
244
+ };
245
+ return (
246
+ <div
247
+ key={tab}
248
+ style={{ display: tab === activeTab ? "block" : "none" }}
249
+ aria-hidden={tab !== activeTab}
250
+ >
251
+ <ProductCardPanel
252
+ fields={tabFields as CarouselWithProductCards}
253
+ renderCheckPlans={renderCheckPlans}
254
+ isVisible={tab === activeTab}
255
+ />
256
+ </div>
257
+ );
258
+ })}
259
+ </>
260
+ );
261
+ }
262
+
263
+ return (
264
+ <ProductCardPanel fields={fields} renderCheckPlans={renderCheckPlans} />
265
+ );
266
+ }
267
+
214
268
  /**
215
269
  * Individual slide component for the testimonial carousel
216
270
  * Memoized to prevent unnecessary re-renders of inactive slides
@@ -58,6 +58,8 @@ export const Carousel: React.FC<CarouselProps> = ({
58
58
  onModalButtonClick={onModalButtonClick}
59
59
  renderCheckPlans={renderCheckPlans}
60
60
  fields={fields as CarouselWithProductCards}
61
+ activeTab={activeTab}
62
+ tabs={tabs}
61
63
  />
62
64
  )}
63
65
  </div>
@@ -64,6 +64,7 @@ export interface ProductCardFields {
64
64
  benefitsTitle?: string;
65
65
  benefitsExpanded?: boolean;
66
66
  innerBadge?: string;
67
+ productCategory?: string;
67
68
  // GraphQL patterns for nested references
68
69
  benefits?: {
69
70
  items: Array<any>;