@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.
@@ -6,6 +6,7 @@ import { Pressable } from '@page-speed/pressable';
6
6
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
8
  import { Img } from '@page-speed/img';
9
+ import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio';
9
10
 
10
11
  // components/blocks/hero/hero-premium-split-avatars.tsx
11
12
  function cn(...inputs) {
@@ -432,6 +433,174 @@ var Section = React.forwardRef(
432
433
  }
433
434
  );
434
435
  Section.displayName = "Section";
436
+ function AspectRatio({
437
+ ...props
438
+ }) {
439
+ return /* @__PURE__ */ jsx(AspectRatioPrimitive.Root, { "data-slot": "aspect-ratio", ...props });
440
+ }
441
+ var DEFAULT_DEVICE_ASPECT_RATIOS = {
442
+ desktop: "square",
443
+ mobile: "square"
444
+ };
445
+ var DEFAULT_MEDIA_CLASS_NAME = "size-full object-cover";
446
+ var DEFAULT_FRAME_CLASS_NAME = "overflow-hidden";
447
+ var DEFAULT_BREAKPOINT = "lg";
448
+ var BREAKPOINT_VISIBILITY_CLASSES = {
449
+ sm: {
450
+ desktop: "hidden sm:block",
451
+ mobile: "sm:hidden"
452
+ },
453
+ md: {
454
+ desktop: "hidden md:block",
455
+ mobile: "md:hidden"
456
+ },
457
+ lg: {
458
+ desktop: "hidden lg:block",
459
+ mobile: "lg:hidden"
460
+ },
461
+ xl: {
462
+ desktop: "hidden xl:block",
463
+ mobile: "xl:hidden"
464
+ },
465
+ "2xl": {
466
+ desktop: "hidden 2xl:block",
467
+ mobile: "2xl:hidden"
468
+ }
469
+ };
470
+ var MEDIA_ASPECT_RATIOS = {
471
+ square: 1,
472
+ horizontal: 16 / 9,
473
+ vertical: 355 / 520
474
+ };
475
+ function resolveAspectRatio(ratio, fallback) {
476
+ const resolvedRatio = ratio ?? fallback;
477
+ if (typeof resolvedRatio === "number" && Number.isFinite(resolvedRatio) && resolvedRatio > 0) {
478
+ return resolvedRatio;
479
+ }
480
+ return MEDIA_ASPECT_RATIOS[resolvedRatio];
481
+ }
482
+ function hasRenderableMedia(mediaItem) {
483
+ return Boolean(mediaItem?.image?.src || mediaItem?.video?.src);
484
+ }
485
+ function renderMediaElement({
486
+ mediaItem,
487
+ optixFlowConfig,
488
+ mediaClassName,
489
+ imageClassName,
490
+ videoClassName
491
+ }) {
492
+ if (!hasRenderableMedia(mediaItem)) {
493
+ return null;
494
+ }
495
+ if (mediaItem.video?.src) {
496
+ const { className: inlineVideoClassName, poster, ...videoProps } = mediaItem.video;
497
+ const posterFallback = poster ?? (typeof mediaItem.image?.src === "string" ? mediaItem.image.src : void 0);
498
+ return /* @__PURE__ */ jsx(
499
+ "video",
500
+ {
501
+ ...videoProps,
502
+ poster: posterFallback,
503
+ className: cn(
504
+ DEFAULT_MEDIA_CLASS_NAME,
505
+ mediaClassName,
506
+ videoClassName,
507
+ inlineVideoClassName
508
+ )
509
+ }
510
+ );
511
+ }
512
+ if (mediaItem.image?.src) {
513
+ const { className: inlineImageClassName, alt, src, ...imageProps } = mediaItem.image;
514
+ return /* @__PURE__ */ jsx(
515
+ Img,
516
+ {
517
+ ...imageProps,
518
+ src,
519
+ alt: alt ?? "",
520
+ className: cn(
521
+ DEFAULT_MEDIA_CLASS_NAME,
522
+ mediaClassName,
523
+ imageClassName,
524
+ inlineImageClassName
525
+ ),
526
+ optixFlowConfig
527
+ }
528
+ );
529
+ }
530
+ return null;
531
+ }
532
+ function MediaAspectRatio({
533
+ containerClassName,
534
+ mobileClassName,
535
+ desktopClassName,
536
+ frameClassName,
537
+ mobileFrameClassName,
538
+ desktopFrameClassName,
539
+ mediaClassName,
540
+ imageClassName,
541
+ videoClassName,
542
+ mediaItem,
543
+ optixFlowConfig,
544
+ deviceAspectRatios = DEFAULT_DEVICE_ASPECT_RATIOS,
545
+ breakpoint = DEFAULT_BREAKPOINT
546
+ }) {
547
+ if (!hasRenderableMedia(mediaItem)) {
548
+ return null;
549
+ }
550
+ const ratios = {
551
+ desktop: resolveAspectRatio(
552
+ deviceAspectRatios.desktop,
553
+ DEFAULT_DEVICE_ASPECT_RATIOS.desktop
554
+ ),
555
+ mobile: resolveAspectRatio(
556
+ deviceAspectRatios.mobile,
557
+ DEFAULT_DEVICE_ASPECT_RATIOS.mobile
558
+ )
559
+ };
560
+ const sharedFrameClassName = cn(
561
+ DEFAULT_FRAME_CLASS_NAME,
562
+ frameClassName,
563
+ mediaItem.containerClassName
564
+ );
565
+ const visibilityClasses = BREAKPOINT_VISIBILITY_CLASSES[breakpoint];
566
+ return /* @__PURE__ */ jsxs("div", { className: containerClassName, "data-slot": "media-aspect-ratio", children: [
567
+ /* @__PURE__ */ jsx("div", { className: cn("relative", visibilityClasses.mobile, mobileClassName), children: /* @__PURE__ */ jsx(
568
+ AspectRatio,
569
+ {
570
+ ratio: ratios.mobile,
571
+ className: cn(sharedFrameClassName, mobileFrameClassName),
572
+ children: renderMediaElement({
573
+ mediaItem,
574
+ optixFlowConfig,
575
+ mediaClassName,
576
+ imageClassName,
577
+ videoClassName
578
+ })
579
+ }
580
+ ) }),
581
+ /* @__PURE__ */ jsx(
582
+ "div",
583
+ {
584
+ className: cn(visibilityClasses.desktop, desktopClassName),
585
+ style: { aspectRatio: String(ratios.desktop) },
586
+ children: /* @__PURE__ */ jsx(
587
+ "div",
588
+ {
589
+ className: cn("size-full", sharedFrameClassName, desktopFrameClassName),
590
+ "data-slot": "media-aspect-ratio-frame",
591
+ children: renderMediaElement({
592
+ mediaItem,
593
+ optixFlowConfig,
594
+ mediaClassName,
595
+ imageClassName,
596
+ videoClassName
597
+ })
598
+ }
599
+ )
600
+ }
601
+ )
602
+ ] });
603
+ }
435
604
  function HeroPremiumSplitAvatars({
436
605
  sectionId = "hero-premium-split-avatars",
437
606
  brandName,
@@ -447,7 +616,7 @@ function HeroPremiumSplitAvatars({
447
616
  image,
448
617
  imageSlot,
449
618
  className,
450
- spacing = "pt-28 pb-8 md:pt-32 md:pb-32",
619
+ spacing = "hero",
451
620
  containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
452
621
  background,
453
622
  pattern,
@@ -456,8 +625,15 @@ function HeroPremiumSplitAvatars({
456
625
  headingClassName,
457
626
  descriptionClassName,
458
627
  imageClassName,
459
- optixFlowConfig
628
+ optixFlowConfig,
629
+ mediaAspectRatios = { desktop: "vertical", mobile: "vertical" },
630
+ directionConfig = { desktop: "mediaRight", mobile: "mediaBottom" }
460
631
  }) {
632
+ const responsiveClassName = useMemo(() => {
633
+ const desktopOrder = directionConfig.desktop === "mediaRight" ? "md:flex-row" : "md:flex-row-reverse";
634
+ const mobileOrder = directionConfig.mobile === "mediaTop" ? "flex-col-reverse" : "flex-col";
635
+ return `${mobileOrder} ${desktopOrder}`;
636
+ }, [directionConfig.desktop, directionConfig.mobile]);
461
637
  const renderBrand = useMemo(() => {
462
638
  if (brandSlot) return brandSlot;
463
639
  return /* @__PURE__ */ jsxs("h1", { className: "text-4xl ", children: [
@@ -505,19 +681,31 @@ function HeroPremiumSplitAvatars({
505
681
  if (imageSlot) return imageSlot;
506
682
  if (!image) return null;
507
683
  return /* @__PURE__ */ jsx(
508
- Img,
684
+ MediaAspectRatio,
509
685
  {
510
- src: image.src,
511
- alt: image.alt,
512
- className: cn(
513
- "h-full w-full md:w-1/2 object-cover block rounded-xl shadow-xl",
514
- imageClassName,
515
- image.className
516
- ),
517
- optixFlowConfig
686
+ breakpoint: "md",
687
+ containerClassName: "relative flex w-full justify-center md:w-1/2",
688
+ mobileClassName: "w-full",
689
+ desktopClassName: "w-full max-h-[70dvh]",
690
+ frameClassName: "rounded-xl shadow-xl",
691
+ imageClassName: cn("block", imageClassName),
692
+ mediaItem: {
693
+ image: {
694
+ ...image,
695
+ loading: "eager"
696
+ }
697
+ },
698
+ optixFlowConfig,
699
+ deviceAspectRatios: mediaAspectRatios
518
700
  }
519
701
  );
520
- }, [imageSlot, image, imageClassName, optixFlowConfig]);
702
+ }, [
703
+ imageSlot,
704
+ image,
705
+ imageClassName,
706
+ optixFlowConfig,
707
+ mediaAspectRatios
708
+ ]);
521
709
  return /* @__PURE__ */ jsx(
522
710
  Section,
523
711
  {
@@ -528,27 +716,36 @@ function HeroPremiumSplitAvatars({
528
716
  patternOpacity,
529
717
  className: cn("relative flex items-center justify-center", className),
530
718
  containerClassName,
531
- children: /* @__PURE__ */ jsxs("div", { className: "relative flex w-full flex-col md:flex-row gap-8 md:gap-20", children: [
532
- /* @__PURE__ */ jsx("div", { className: "flex w-full items-center justify-center lg:w-1/2", children: /* @__PURE__ */ jsxs(
533
- "div",
534
- {
535
- className: cn(
536
- "my-10 flex w-full flex-col gap-6 md:gap-24",
537
- contentClassName
538
- ),
539
- children: [
540
- renderBrand,
541
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 md:gap-8", children: [
542
- heading && (typeof heading === "string" ? /* @__PURE__ */ jsx("h2", { className: cn("text-4xl lg:text-6xl", headingClassName), children: heading }) : /* @__PURE__ */ jsx("h2", { className: cn("text-4xl lg:text-6xl", headingClassName), children: heading })),
543
- description && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: cn("mt-2.5 lg:text-xl", descriptionClassName), children: description }) : /* @__PURE__ */ jsx("div", { className: descriptionClassName, children: description })),
544
- renderAction
545
- ] }),
546
- renderAvatars
547
- ]
548
- }
549
- ) }),
550
- renderImage
551
- ] })
719
+ children: /* @__PURE__ */ jsxs(
720
+ "div",
721
+ {
722
+ className: cn(
723
+ "relative flex w-full gap-8 md:gap-20",
724
+ responsiveClassName
725
+ ),
726
+ children: [
727
+ /* @__PURE__ */ jsx("div", { className: "flex w-full items-center justify-center lg:w-1/2", children: /* @__PURE__ */ jsxs(
728
+ "div",
729
+ {
730
+ className: cn(
731
+ "my-10 flex w-full flex-col gap-6 md:gap-24",
732
+ contentClassName
733
+ ),
734
+ children: [
735
+ renderBrand,
736
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 md:gap-8", children: [
737
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsx("h2", { className: cn("text-4xl lg:text-6xl", headingClassName), children: heading }) : /* @__PURE__ */ jsx("h2", { className: cn("text-4xl lg:text-6xl", headingClassName), children: heading })),
738
+ description && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: cn("mt-2.5 lg:text-xl", descriptionClassName), children: description }) : /* @__PURE__ */ jsx("div", { className: descriptionClassName, children: description })),
739
+ renderAction
740
+ ] }),
741
+ renderAvatars
742
+ ]
743
+ }
744
+ ) }),
745
+ renderImage
746
+ ]
747
+ }
748
+ )
552
749
  }
553
750
  );
554
751
  }
package/dist/index.cjs CHANGED
@@ -9,6 +9,7 @@ var framerMotion = require('framer-motion');
9
9
  var useOnClickOutside = require('@opensite/hooks/useOnClickOutside');
10
10
  var react = require('motion/react');
11
11
  var img = require('@page-speed/img');
12
+ var AspectRatioPrimitive = require('@radix-ui/react-aspect-ratio');
12
13
  var reactSlot = require('@radix-ui/react-slot');
13
14
  var pressable = require('@page-speed/pressable');
14
15
  var classVarianceAuthority = require('class-variance-authority');
@@ -38,6 +39,7 @@ function _interopNamespace(e) {
38
39
  }
39
40
 
40
41
  var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
42
+ var AspectRatioPrimitive__namespace = /*#__PURE__*/_interopNamespace(AspectRatioPrimitive);
41
43
  var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
42
44
  var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
43
45
 
@@ -978,6 +980,174 @@ var ImageSlider = ({
978
980
  }
979
981
  );
980
982
  };
983
+ function AspectRatio({
984
+ ...props
985
+ }) {
986
+ return /* @__PURE__ */ jsxRuntime.jsx(AspectRatioPrimitive__namespace.Root, { "data-slot": "aspect-ratio", ...props });
987
+ }
988
+ var DEFAULT_DEVICE_ASPECT_RATIOS = {
989
+ desktop: "square",
990
+ mobile: "square"
991
+ };
992
+ var DEFAULT_MEDIA_CLASS_NAME = "size-full object-cover";
993
+ var DEFAULT_FRAME_CLASS_NAME = "overflow-hidden";
994
+ var DEFAULT_BREAKPOINT = "lg";
995
+ var BREAKPOINT_VISIBILITY_CLASSES = {
996
+ sm: {
997
+ desktop: "hidden sm:block",
998
+ mobile: "sm:hidden"
999
+ },
1000
+ md: {
1001
+ desktop: "hidden md:block",
1002
+ mobile: "md:hidden"
1003
+ },
1004
+ lg: {
1005
+ desktop: "hidden lg:block",
1006
+ mobile: "lg:hidden"
1007
+ },
1008
+ xl: {
1009
+ desktop: "hidden xl:block",
1010
+ mobile: "xl:hidden"
1011
+ },
1012
+ "2xl": {
1013
+ desktop: "hidden 2xl:block",
1014
+ mobile: "2xl:hidden"
1015
+ }
1016
+ };
1017
+ var MEDIA_ASPECT_RATIOS = {
1018
+ square: 1,
1019
+ horizontal: 16 / 9,
1020
+ vertical: 355 / 520
1021
+ };
1022
+ function resolveAspectRatio(ratio, fallback) {
1023
+ const resolvedRatio = ratio ?? fallback;
1024
+ if (typeof resolvedRatio === "number" && Number.isFinite(resolvedRatio) && resolvedRatio > 0) {
1025
+ return resolvedRatio;
1026
+ }
1027
+ return MEDIA_ASPECT_RATIOS[resolvedRatio];
1028
+ }
1029
+ function hasRenderableMedia(mediaItem) {
1030
+ return Boolean(mediaItem?.image?.src || mediaItem?.video?.src);
1031
+ }
1032
+ function renderMediaElement({
1033
+ mediaItem,
1034
+ optixFlowConfig,
1035
+ mediaClassName,
1036
+ imageClassName,
1037
+ videoClassName
1038
+ }) {
1039
+ if (!hasRenderableMedia(mediaItem)) {
1040
+ return null;
1041
+ }
1042
+ if (mediaItem.video?.src) {
1043
+ const { className: inlineVideoClassName, poster, ...videoProps } = mediaItem.video;
1044
+ const posterFallback = poster ?? (typeof mediaItem.image?.src === "string" ? mediaItem.image.src : void 0);
1045
+ return /* @__PURE__ */ jsxRuntime.jsx(
1046
+ "video",
1047
+ {
1048
+ ...videoProps,
1049
+ poster: posterFallback,
1050
+ className: cn(
1051
+ DEFAULT_MEDIA_CLASS_NAME,
1052
+ mediaClassName,
1053
+ videoClassName,
1054
+ inlineVideoClassName
1055
+ )
1056
+ }
1057
+ );
1058
+ }
1059
+ if (mediaItem.image?.src) {
1060
+ const { className: inlineImageClassName, alt, src, ...imageProps } = mediaItem.image;
1061
+ return /* @__PURE__ */ jsxRuntime.jsx(
1062
+ img.Img,
1063
+ {
1064
+ ...imageProps,
1065
+ src,
1066
+ alt: alt ?? "",
1067
+ className: cn(
1068
+ DEFAULT_MEDIA_CLASS_NAME,
1069
+ mediaClassName,
1070
+ imageClassName,
1071
+ inlineImageClassName
1072
+ ),
1073
+ optixFlowConfig
1074
+ }
1075
+ );
1076
+ }
1077
+ return null;
1078
+ }
1079
+ function MediaAspectRatio({
1080
+ containerClassName,
1081
+ mobileClassName,
1082
+ desktopClassName,
1083
+ frameClassName,
1084
+ mobileFrameClassName,
1085
+ desktopFrameClassName,
1086
+ mediaClassName,
1087
+ imageClassName,
1088
+ videoClassName,
1089
+ mediaItem,
1090
+ optixFlowConfig,
1091
+ deviceAspectRatios = DEFAULT_DEVICE_ASPECT_RATIOS,
1092
+ breakpoint = DEFAULT_BREAKPOINT
1093
+ }) {
1094
+ if (!hasRenderableMedia(mediaItem)) {
1095
+ return null;
1096
+ }
1097
+ const ratios = {
1098
+ desktop: resolveAspectRatio(
1099
+ deviceAspectRatios.desktop,
1100
+ DEFAULT_DEVICE_ASPECT_RATIOS.desktop
1101
+ ),
1102
+ mobile: resolveAspectRatio(
1103
+ deviceAspectRatios.mobile,
1104
+ DEFAULT_DEVICE_ASPECT_RATIOS.mobile
1105
+ )
1106
+ };
1107
+ const sharedFrameClassName = cn(
1108
+ DEFAULT_FRAME_CLASS_NAME,
1109
+ frameClassName,
1110
+ mediaItem.containerClassName
1111
+ );
1112
+ const visibilityClasses = BREAKPOINT_VISIBILITY_CLASSES[breakpoint];
1113
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClassName, "data-slot": "media-aspect-ratio", children: [
1114
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative", visibilityClasses.mobile, mobileClassName), children: /* @__PURE__ */ jsxRuntime.jsx(
1115
+ AspectRatio,
1116
+ {
1117
+ ratio: ratios.mobile,
1118
+ className: cn(sharedFrameClassName, mobileFrameClassName),
1119
+ children: renderMediaElement({
1120
+ mediaItem,
1121
+ optixFlowConfig,
1122
+ mediaClassName,
1123
+ imageClassName,
1124
+ videoClassName
1125
+ })
1126
+ }
1127
+ ) }),
1128
+ /* @__PURE__ */ jsxRuntime.jsx(
1129
+ "div",
1130
+ {
1131
+ className: cn(visibilityClasses.desktop, desktopClassName),
1132
+ style: { aspectRatio: String(ratios.desktop) },
1133
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1134
+ "div",
1135
+ {
1136
+ className: cn("size-full", sharedFrameClassName, desktopFrameClassName),
1137
+ "data-slot": "media-aspect-ratio-frame",
1138
+ children: renderMediaElement({
1139
+ mediaItem,
1140
+ optixFlowConfig,
1141
+ mediaClassName,
1142
+ imageClassName,
1143
+ videoClassName
1144
+ })
1145
+ }
1146
+ )
1147
+ }
1148
+ )
1149
+ ] });
1150
+ }
981
1151
  function Button({
982
1152
  className,
983
1153
  variant = "default",
@@ -6756,6 +6926,7 @@ exports.FooterSimpleCentered = FooterSimpleCentered;
6756
6926
  exports.FooterSocialApps = FooterSocialApps;
6757
6927
  exports.FooterSocialNewsletter = FooterSocialNewsletter;
6758
6928
  exports.ImageSlider = ImageSlider;
6929
+ exports.MediaAspectRatio = MediaAspectRatio;
6759
6930
  exports.MediaHoverCtas = MediaHoverCtas;
6760
6931
  exports.PageHeroBanner = PageHeroBanner;
6761
6932
  exports.PaymentPlatformIcon = PaymentPlatformIcon;
package/dist/index.d.cts CHANGED
@@ -3,6 +3,7 @@ export { Section } from './section.cjs';
3
3
  export { AnimatedDialog } from './animated-dialog.cjs';
4
4
  export { PageHeroBanner } from './page-hero-banner.cjs';
5
5
  export { ImageSlider } from './image-slider.cjs';
6
+ export { MediaAspectRatio, MediaAspectRatioBreakpoint, MediaAspectRatioProps, MediaAspectRatioVariant, ResponsiveMediaAspectRatioProps } from './media-aspect-ratio.cjs';
6
7
  export { Button } from './button.cjs';
7
8
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './card.cjs';
8
9
  export { Badge } from './badge.cjs';
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export { Section } from './section.js';
3
3
  export { AnimatedDialog } from './animated-dialog.js';
4
4
  export { PageHeroBanner } from './page-hero-banner.js';
5
5
  export { ImageSlider } from './image-slider.js';
6
+ export { MediaAspectRatio, MediaAspectRatioBreakpoint, MediaAspectRatioProps, MediaAspectRatioVariant, ResponsiveMediaAspectRatioProps } from './media-aspect-ratio.js';
6
7
  export { Button } from './button.js';
7
8
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './card.js';
8
9
  export { Badge } from './badge.js';