@opensite/ui 3.0.7 → 3.0.8

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.
@@ -8,6 +8,7 @@ var pressable = require('@page-speed/pressable');
8
8
  var AvatarPrimitive = require('@radix-ui/react-avatar');
9
9
  var jsxRuntime = require('react/jsx-runtime');
10
10
  var img = require('@page-speed/img');
11
+ var AspectRatioPrimitive = require('@radix-ui/react-aspect-ratio');
11
12
 
12
13
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
14
 
@@ -31,6 +32,7 @@ function _interopNamespace(e) {
31
32
 
32
33
  var React__default = /*#__PURE__*/_interopDefault(React);
33
34
  var AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespace(AvatarPrimitive);
35
+ var AspectRatioPrimitive__namespace = /*#__PURE__*/_interopNamespace(AspectRatioPrimitive);
34
36
 
35
37
  // components/blocks/hero/hero-premium-split-avatars.tsx
36
38
  function cn(...inputs) {
@@ -457,6 +459,174 @@ var Section = React__default.default.forwardRef(
457
459
  }
458
460
  );
459
461
  Section.displayName = "Section";
462
+ function AspectRatio({
463
+ ...props
464
+ }) {
465
+ return /* @__PURE__ */ jsxRuntime.jsx(AspectRatioPrimitive__namespace.Root, { "data-slot": "aspect-ratio", ...props });
466
+ }
467
+ var DEFAULT_DEVICE_ASPECT_RATIOS = {
468
+ desktop: "square",
469
+ mobile: "square"
470
+ };
471
+ var DEFAULT_MEDIA_CLASS_NAME = "size-full object-cover";
472
+ var DEFAULT_FRAME_CLASS_NAME = "overflow-hidden";
473
+ var DEFAULT_BREAKPOINT = "lg";
474
+ var BREAKPOINT_VISIBILITY_CLASSES = {
475
+ sm: {
476
+ desktop: "hidden sm:block",
477
+ mobile: "sm:hidden"
478
+ },
479
+ md: {
480
+ desktop: "hidden md:block",
481
+ mobile: "md:hidden"
482
+ },
483
+ lg: {
484
+ desktop: "hidden lg:block",
485
+ mobile: "lg:hidden"
486
+ },
487
+ xl: {
488
+ desktop: "hidden xl:block",
489
+ mobile: "xl:hidden"
490
+ },
491
+ "2xl": {
492
+ desktop: "hidden 2xl:block",
493
+ mobile: "2xl:hidden"
494
+ }
495
+ };
496
+ var MEDIA_ASPECT_RATIOS = {
497
+ square: 1,
498
+ horizontal: 16 / 9,
499
+ vertical: 355 / 520
500
+ };
501
+ function resolveAspectRatio(ratio, fallback) {
502
+ const resolvedRatio = ratio ?? fallback;
503
+ if (typeof resolvedRatio === "number" && Number.isFinite(resolvedRatio) && resolvedRatio > 0) {
504
+ return resolvedRatio;
505
+ }
506
+ return MEDIA_ASPECT_RATIOS[resolvedRatio];
507
+ }
508
+ function hasRenderableMedia(mediaItem) {
509
+ return Boolean(mediaItem?.image?.src || mediaItem?.video?.src);
510
+ }
511
+ function renderMediaElement({
512
+ mediaItem,
513
+ optixFlowConfig,
514
+ mediaClassName,
515
+ imageClassName,
516
+ videoClassName
517
+ }) {
518
+ if (!hasRenderableMedia(mediaItem)) {
519
+ return null;
520
+ }
521
+ if (mediaItem.video?.src) {
522
+ const { className: inlineVideoClassName, poster, ...videoProps } = mediaItem.video;
523
+ const posterFallback = poster ?? (typeof mediaItem.image?.src === "string" ? mediaItem.image.src : void 0);
524
+ return /* @__PURE__ */ jsxRuntime.jsx(
525
+ "video",
526
+ {
527
+ ...videoProps,
528
+ poster: posterFallback,
529
+ className: cn(
530
+ DEFAULT_MEDIA_CLASS_NAME,
531
+ mediaClassName,
532
+ videoClassName,
533
+ inlineVideoClassName
534
+ )
535
+ }
536
+ );
537
+ }
538
+ if (mediaItem.image?.src) {
539
+ const { className: inlineImageClassName, alt, src, ...imageProps } = mediaItem.image;
540
+ return /* @__PURE__ */ jsxRuntime.jsx(
541
+ img.Img,
542
+ {
543
+ ...imageProps,
544
+ src,
545
+ alt: alt ?? "",
546
+ className: cn(
547
+ DEFAULT_MEDIA_CLASS_NAME,
548
+ mediaClassName,
549
+ imageClassName,
550
+ inlineImageClassName
551
+ ),
552
+ optixFlowConfig
553
+ }
554
+ );
555
+ }
556
+ return null;
557
+ }
558
+ function MediaAspectRatio({
559
+ containerClassName,
560
+ mobileClassName,
561
+ desktopClassName,
562
+ frameClassName,
563
+ mobileFrameClassName,
564
+ desktopFrameClassName,
565
+ mediaClassName,
566
+ imageClassName,
567
+ videoClassName,
568
+ mediaItem,
569
+ optixFlowConfig,
570
+ deviceAspectRatios = DEFAULT_DEVICE_ASPECT_RATIOS,
571
+ breakpoint = DEFAULT_BREAKPOINT
572
+ }) {
573
+ if (!hasRenderableMedia(mediaItem)) {
574
+ return null;
575
+ }
576
+ const ratios = {
577
+ desktop: resolveAspectRatio(
578
+ deviceAspectRatios.desktop,
579
+ DEFAULT_DEVICE_ASPECT_RATIOS.desktop
580
+ ),
581
+ mobile: resolveAspectRatio(
582
+ deviceAspectRatios.mobile,
583
+ DEFAULT_DEVICE_ASPECT_RATIOS.mobile
584
+ )
585
+ };
586
+ const sharedFrameClassName = cn(
587
+ DEFAULT_FRAME_CLASS_NAME,
588
+ frameClassName,
589
+ mediaItem.containerClassName
590
+ );
591
+ const visibilityClasses = BREAKPOINT_VISIBILITY_CLASSES[breakpoint];
592
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClassName, "data-slot": "media-aspect-ratio", children: [
593
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative", visibilityClasses.mobile, mobileClassName), children: /* @__PURE__ */ jsxRuntime.jsx(
594
+ AspectRatio,
595
+ {
596
+ ratio: ratios.mobile,
597
+ className: cn(sharedFrameClassName, mobileFrameClassName),
598
+ children: renderMediaElement({
599
+ mediaItem,
600
+ optixFlowConfig,
601
+ mediaClassName,
602
+ imageClassName,
603
+ videoClassName
604
+ })
605
+ }
606
+ ) }),
607
+ /* @__PURE__ */ jsxRuntime.jsx(
608
+ "div",
609
+ {
610
+ className: cn(visibilityClasses.desktop, desktopClassName),
611
+ style: { aspectRatio: String(ratios.desktop) },
612
+ children: /* @__PURE__ */ jsxRuntime.jsx(
613
+ "div",
614
+ {
615
+ className: cn("size-full", sharedFrameClassName, desktopFrameClassName),
616
+ "data-slot": "media-aspect-ratio-frame",
617
+ children: renderMediaElement({
618
+ mediaItem,
619
+ optixFlowConfig,
620
+ mediaClassName,
621
+ imageClassName,
622
+ videoClassName
623
+ })
624
+ }
625
+ )
626
+ }
627
+ )
628
+ ] });
629
+ }
460
630
  function HeroPremiumSplitAvatars({
461
631
  sectionId = "hero-premium-split-avatars",
462
632
  brandName,
@@ -472,7 +642,7 @@ function HeroPremiumSplitAvatars({
472
642
  image,
473
643
  imageSlot,
474
644
  className,
475
- spacing = "pt-28 pb-8 md:pt-32 md:pb-32",
645
+ spacing = "hero",
476
646
  containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
477
647
  background,
478
648
  pattern,
@@ -481,8 +651,15 @@ function HeroPremiumSplitAvatars({
481
651
  headingClassName,
482
652
  descriptionClassName,
483
653
  imageClassName,
484
- optixFlowConfig
654
+ optixFlowConfig,
655
+ mediaAspectRatios = { desktop: "vertical", mobile: "vertical" },
656
+ directionConfig = { desktop: "mediaRight", mobile: "mediaBottom" }
485
657
  }) {
658
+ const responsiveClassName = React.useMemo(() => {
659
+ const desktopOrder = directionConfig.desktop === "mediaRight" ? "md:flex-row" : "md:flex-row-reverse";
660
+ const mobileOrder = directionConfig.mobile === "mediaTop" ? "flex-col-reverse" : "flex-col";
661
+ return `${mobileOrder} ${desktopOrder}`;
662
+ }, [directionConfig.desktop, directionConfig.mobile]);
486
663
  const renderBrand = React.useMemo(() => {
487
664
  if (brandSlot) return brandSlot;
488
665
  return /* @__PURE__ */ jsxRuntime.jsxs("h1", { className: "text-4xl ", children: [
@@ -530,19 +707,31 @@ function HeroPremiumSplitAvatars({
530
707
  if (imageSlot) return imageSlot;
531
708
  if (!image) return null;
532
709
  return /* @__PURE__ */ jsxRuntime.jsx(
533
- img.Img,
710
+ MediaAspectRatio,
534
711
  {
535
- src: image.src,
536
- alt: image.alt,
537
- className: cn(
538
- "h-full w-full md:w-1/2 object-cover block rounded-xl shadow-xl",
539
- imageClassName,
540
- image.className
541
- ),
542
- optixFlowConfig
712
+ breakpoint: "md",
713
+ containerClassName: "relative flex w-full justify-center md:w-1/2",
714
+ mobileClassName: "w-full",
715
+ desktopClassName: "w-full max-h-[70dvh]",
716
+ frameClassName: "rounded-xl shadow-xl",
717
+ imageClassName: cn("block", imageClassName),
718
+ mediaItem: {
719
+ image: {
720
+ ...image,
721
+ loading: "eager"
722
+ }
723
+ },
724
+ optixFlowConfig,
725
+ deviceAspectRatios: mediaAspectRatios
543
726
  }
544
727
  );
545
- }, [imageSlot, image, imageClassName, optixFlowConfig]);
728
+ }, [
729
+ imageSlot,
730
+ image,
731
+ imageClassName,
732
+ optixFlowConfig,
733
+ mediaAspectRatios
734
+ ]);
546
735
  return /* @__PURE__ */ jsxRuntime.jsx(
547
736
  Section,
548
737
  {
@@ -553,27 +742,36 @@ function HeroPremiumSplitAvatars({
553
742
  patternOpacity,
554
743
  className: cn("relative flex items-center justify-center", className),
555
744
  containerClassName,
556
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex w-full flex-col md:flex-row gap-8 md:gap-20", children: [
557
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full items-center justify-center lg:w-1/2", children: /* @__PURE__ */ jsxRuntime.jsxs(
558
- "div",
559
- {
560
- className: cn(
561
- "my-10 flex w-full flex-col gap-6 md:gap-24",
562
- contentClassName
563
- ),
564
- children: [
565
- renderBrand,
566
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 md:gap-8", children: [
567
- heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: cn("text-4xl lg:text-6xl", headingClassName), children: heading }) : /* @__PURE__ */ jsxRuntime.jsx("h2", { className: cn("text-4xl lg:text-6xl", headingClassName), children: heading })),
568
- description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-2.5 lg:text-xl", descriptionClassName), children: description }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description })),
569
- renderAction
570
- ] }),
571
- renderAvatars
572
- ]
573
- }
574
- ) }),
575
- renderImage
576
- ] })
745
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
746
+ "div",
747
+ {
748
+ className: cn(
749
+ "relative flex w-full gap-8 md:gap-20",
750
+ responsiveClassName
751
+ ),
752
+ children: [
753
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full items-center justify-center lg:w-1/2", children: /* @__PURE__ */ jsxRuntime.jsxs(
754
+ "div",
755
+ {
756
+ className: cn(
757
+ "my-10 flex w-full flex-col gap-6 md:gap-24",
758
+ contentClassName
759
+ ),
760
+ children: [
761
+ renderBrand,
762
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 md:gap-8", children: [
763
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: cn("text-4xl lg:text-6xl", headingClassName), children: heading }) : /* @__PURE__ */ jsxRuntime.jsx("h2", { className: cn("text-4xl lg:text-6xl", headingClassName), children: heading })),
764
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-2.5 lg:text-xl", descriptionClassName), children: description }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description })),
765
+ renderAction
766
+ ] }),
767
+ renderAvatars
768
+ ]
769
+ }
770
+ ) }),
771
+ renderImage
772
+ ]
773
+ }
774
+ )
577
775
  }
578
776
  );
579
777
  }
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { S as SectionBackground, s as SectionSpacing, t as PatternName } from './community-initiatives-D8cbIf_y.cjs';
3
- import { A as ActionConfig, I as ImageItem, O as OptixFlowConfig } from './blocks-DL92rOxr.cjs';
3
+ import { ResponsiveMediaAspectRatioProps } from './media-aspect-ratio.cjs';
4
+ import { A as ActionConfig, I as ImageItem, O as OptixFlowConfig, h as DirectionConfig } from './blocks-DL92rOxr.cjs';
4
5
  import 'react/jsx-runtime';
5
6
  import 'class-variance-authority';
6
7
  import '@page-speed/pressable';
@@ -64,7 +65,8 @@ interface HeroPremiumSplitAvatarsProps {
64
65
  /**
65
66
  * Custom slot for image (overrides image prop)
66
67
  */
67
- imageSlot?: React.ReactNode; /**
68
+ imageSlot?: React.ReactNode;
69
+ /**
68
70
  * Background style for the section
69
71
  */
70
72
  background?: SectionBackground;
@@ -110,7 +112,17 @@ interface HeroPremiumSplitAvatarsProps {
110
112
  optixFlowConfig?: OptixFlowConfig;
111
113
  /** Optional Section ID */
112
114
  sectionId?: string;
115
+ /**
116
+ * Media aspect ratios for desktop and mobile breakpoints
117
+ * @default { desktop: "vertical", mobile: "vertical" }
118
+ */
119
+ mediaAspectRatios?: ResponsiveMediaAspectRatioProps;
120
+ /**
121
+ * Direction configuration for desktop and mobile layouts
122
+ * @default { desktop: 'mediaRight', mobile: 'mediaBottom' }
123
+ */
124
+ directionConfig?: DirectionConfig;
113
125
  }
114
- declare function HeroPremiumSplitAvatars({ sectionId, brandName, brandSuffix, brandSlot, heading, description, action, actionSlot, avatars, avatarsSlot, socialProofText, image, imageSlot, className, spacing, containerClassName, background, pattern, patternOpacity, contentClassName, headingClassName, descriptionClassName, imageClassName, optixFlowConfig, }: HeroPremiumSplitAvatarsProps): React.JSX.Element;
126
+ declare function HeroPremiumSplitAvatars({ sectionId, brandName, brandSuffix, brandSlot, heading, description, action, actionSlot, avatars, avatarsSlot, socialProofText, image, imageSlot, className, spacing, containerClassName, background, pattern, patternOpacity, contentClassName, headingClassName, descriptionClassName, imageClassName, optixFlowConfig, mediaAspectRatios, directionConfig, }: HeroPremiumSplitAvatarsProps): React.JSX.Element;
115
127
 
116
128
  export { HeroPremiumSplitAvatars, type HeroPremiumSplitAvatarsProps };
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { S as SectionBackground, s as SectionSpacing, t as PatternName } from './community-initiatives-qC2HCInM.js';
3
- import { A as ActionConfig, I as ImageItem, O as OptixFlowConfig } from './blocks-DL92rOxr.js';
3
+ import { ResponsiveMediaAspectRatioProps } from './media-aspect-ratio.js';
4
+ import { A as ActionConfig, I as ImageItem, O as OptixFlowConfig, h as DirectionConfig } from './blocks-DL92rOxr.js';
4
5
  import 'react/jsx-runtime';
5
6
  import 'class-variance-authority';
6
7
  import '@page-speed/pressable';
@@ -64,7 +65,8 @@ interface HeroPremiumSplitAvatarsProps {
64
65
  /**
65
66
  * Custom slot for image (overrides image prop)
66
67
  */
67
- imageSlot?: React.ReactNode; /**
68
+ imageSlot?: React.ReactNode;
69
+ /**
68
70
  * Background style for the section
69
71
  */
70
72
  background?: SectionBackground;
@@ -110,7 +112,17 @@ interface HeroPremiumSplitAvatarsProps {
110
112
  optixFlowConfig?: OptixFlowConfig;
111
113
  /** Optional Section ID */
112
114
  sectionId?: string;
115
+ /**
116
+ * Media aspect ratios for desktop and mobile breakpoints
117
+ * @default { desktop: "vertical", mobile: "vertical" }
118
+ */
119
+ mediaAspectRatios?: ResponsiveMediaAspectRatioProps;
120
+ /**
121
+ * Direction configuration for desktop and mobile layouts
122
+ * @default { desktop: 'mediaRight', mobile: 'mediaBottom' }
123
+ */
124
+ directionConfig?: DirectionConfig;
113
125
  }
114
- declare function HeroPremiumSplitAvatars({ sectionId, brandName, brandSuffix, brandSlot, heading, description, action, actionSlot, avatars, avatarsSlot, socialProofText, image, imageSlot, className, spacing, containerClassName, background, pattern, patternOpacity, contentClassName, headingClassName, descriptionClassName, imageClassName, optixFlowConfig, }: HeroPremiumSplitAvatarsProps): React.JSX.Element;
126
+ declare function HeroPremiumSplitAvatars({ sectionId, brandName, brandSuffix, brandSlot, heading, description, action, actionSlot, avatars, avatarsSlot, socialProofText, image, imageSlot, className, spacing, containerClassName, background, pattern, patternOpacity, contentClassName, headingClassName, descriptionClassName, imageClassName, optixFlowConfig, mediaAspectRatios, directionConfig, }: HeroPremiumSplitAvatarsProps): React.JSX.Element;
115
127
 
116
128
  export { HeroPremiumSplitAvatars, type HeroPremiumSplitAvatarsProps };