@opensite/ui 3.6.5 → 3.6.6

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 video = require('@page-speed/video');
8
8
  var icon = require('@page-speed/icon');
9
9
  var jsxRuntime = require('react/jsx-runtime');
10
10
  var pressable = require('@page-speed/pressable');
11
+ var img = require('@page-speed/img');
11
12
 
12
13
  function _interopNamespace(e) {
13
14
  if (e && e.__esModule) return e;
@@ -46,6 +47,47 @@ var DynamicIcon = React__namespace.memo(function DynamicIcon2({
46
47
  return /* @__PURE__ */ jsxRuntime.jsx(icon.Icon, { ...props, name, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
47
48
  });
48
49
  DynamicIcon.displayName = "DynamicIcon";
50
+ var SIZE_CLASSES = {
51
+ sm: "max-h-6 sm:max-h-7",
52
+ md: "max-h-8 sm:max-h-9 lg:max-h-10",
53
+ lg: "max-h-10 sm:max-h-12 lg:max-h-14",
54
+ xl: "max-h-12 sm:max-h-14 lg:max-h-16"
55
+ };
56
+ var BrandLogo = ({
57
+ logo,
58
+ logoSlot,
59
+ logoClassName,
60
+ size = "md",
61
+ optixFlowConfig
62
+ }) => {
63
+ if (logoSlot) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: logoSlot });
64
+ if (!logo || !logo.src) return null;
65
+ const imgElement = /* @__PURE__ */ jsxRuntime.jsx(
66
+ img.Img,
67
+ {
68
+ src: logo.src,
69
+ className: cn(
70
+ "w-auto object-contain",
71
+ SIZE_CLASSES[size],
72
+ logo.className
73
+ ),
74
+ alt: logo.alt || "Logo",
75
+ optixFlowConfig,
76
+ loading: "eager"
77
+ }
78
+ );
79
+ if (logo.url) {
80
+ return /* @__PURE__ */ jsxRuntime.jsx(
81
+ pressable.Pressable,
82
+ {
83
+ href: logo.url,
84
+ className: cn("flex items-center", logoClassName),
85
+ children: imgElement
86
+ }
87
+ );
88
+ }
89
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center", logoClassName), children: imgElement });
90
+ };
49
91
  var maxWidthStyles = {
50
92
  sm: "max-w-screen-sm",
51
93
  md: "max-w-screen-md",
@@ -502,6 +544,9 @@ function ActionComponent({ action }) {
502
544
  }
503
545
  function HeroVideoOverlayStars({
504
546
  sectionId = "hero-video-overlay-stars",
547
+ logo,
548
+ logoSlot,
549
+ logoClassName,
505
550
  heading,
506
551
  actions,
507
552
  actionsSlot,
@@ -565,6 +610,7 @@ function HeroVideoOverlayStars({
565
610
  containerClassName,
566
611
  children: [
567
612
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 flex size-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "m-auto flex max-w-100 flex-col items-center gap-9 sm:max-w-125 md:max-w-200 text-center", children: [
613
+ (logo || logoSlot) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-2 flex justify-center", logoClassName), children: /* @__PURE__ */ jsxRuntime.jsx(BrandLogo, { logo, logoSlot, size: "lg" }) }),
568
614
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex w-full flex-col gap-8", contentClassName), children: [
569
615
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
570
616
  "h1",
@@ -1,7 +1,10 @@
1
1
  import * as React from 'react';
2
2
  import { S as SectionBackground, s as SectionSpacing, t as PatternName } from './community-initiatives-Cgd-IXlI.cjs';
3
+ import { L as LogoConfig } from './types-mWZcgKth.cjs';
3
4
  import { A as ActionConfig, M as MediaItem } from './blocks-DyouPohq.cjs';
4
5
  import 'react/jsx-runtime';
6
+ import './dynamic-icon.cjs';
7
+ import '@page-speed/icon';
5
8
  import 'class-variance-authority';
6
9
  import '@page-speed/pressable';
7
10
  import '@opensite/hooks/usePlatformFromUrl';
@@ -20,6 +23,19 @@ interface TrustConfig {
20
23
  message?: string;
21
24
  }
22
25
  interface HeroVideoOverlayStarsProps {
26
+ /**
27
+ * Brand logo configuration — renders centered above the heading.
28
+ * LOGO MEDIA ONLY. Do not use photos, hero images, or video assets.
29
+ */
30
+ logo?: LogoConfig;
31
+ /**
32
+ * Custom slot for logo (overrides logo prop)
33
+ */
34
+ logoSlot?: React.ReactNode;
35
+ /**
36
+ * Additional CSS classes for the logo container
37
+ */
38
+ logoClassName?: string;
23
39
  /**
24
40
  * Main heading text
25
41
  */
@@ -103,6 +119,6 @@ interface HeroVideoOverlayStarsProps {
103
119
  * HeroVideoOverlayStars - A full-screen hero with video background, gradient text heading,
104
120
  * prominent CTA button, and star rating trust indicator. Ideal for product launches.
105
121
  */
106
- declare function HeroVideoOverlayStars({ sectionId, heading, actions, actionsSlot, actionsClassName, description, descriptionClassName, trust, trustSlot, background, spacing, pattern, patternOpacity, containerClassName, contentClassName, className, headingClassName, backgroundVideo, videoSrc, videoSlot, }: HeroVideoOverlayStarsProps): React.JSX.Element;
122
+ declare function HeroVideoOverlayStars({ sectionId, logo, logoSlot, logoClassName, heading, actions, actionsSlot, actionsClassName, description, descriptionClassName, trust, trustSlot, background, spacing, pattern, patternOpacity, containerClassName, contentClassName, className, headingClassName, backgroundVideo, videoSrc, videoSlot, }: HeroVideoOverlayStarsProps): React.JSX.Element;
107
123
 
108
124
  export { HeroVideoOverlayStars, type HeroVideoOverlayStarsProps };
@@ -1,7 +1,10 @@
1
1
  import * as React from 'react';
2
2
  import { S as SectionBackground, s as SectionSpacing, t as PatternName } from './community-initiatives-Dud0DKXB.js';
3
+ import { L as LogoConfig } from './types-hJ2R0GoH.js';
3
4
  import { A as ActionConfig, M as MediaItem } from './blocks-DyouPohq.js';
4
5
  import 'react/jsx-runtime';
6
+ import './dynamic-icon.js';
7
+ import '@page-speed/icon';
5
8
  import 'class-variance-authority';
6
9
  import '@page-speed/pressable';
7
10
  import '@opensite/hooks/usePlatformFromUrl';
@@ -20,6 +23,19 @@ interface TrustConfig {
20
23
  message?: string;
21
24
  }
22
25
  interface HeroVideoOverlayStarsProps {
26
+ /**
27
+ * Brand logo configuration — renders centered above the heading.
28
+ * LOGO MEDIA ONLY. Do not use photos, hero images, or video assets.
29
+ */
30
+ logo?: LogoConfig;
31
+ /**
32
+ * Custom slot for logo (overrides logo prop)
33
+ */
34
+ logoSlot?: React.ReactNode;
35
+ /**
36
+ * Additional CSS classes for the logo container
37
+ */
38
+ logoClassName?: string;
23
39
  /**
24
40
  * Main heading text
25
41
  */
@@ -103,6 +119,6 @@ interface HeroVideoOverlayStarsProps {
103
119
  * HeroVideoOverlayStars - A full-screen hero with video background, gradient text heading,
104
120
  * prominent CTA button, and star rating trust indicator. Ideal for product launches.
105
121
  */
106
- declare function HeroVideoOverlayStars({ sectionId, heading, actions, actionsSlot, actionsClassName, description, descriptionClassName, trust, trustSlot, background, spacing, pattern, patternOpacity, containerClassName, contentClassName, className, headingClassName, backgroundVideo, videoSrc, videoSlot, }: HeroVideoOverlayStarsProps): React.JSX.Element;
122
+ declare function HeroVideoOverlayStars({ sectionId, logo, logoSlot, logoClassName, heading, actions, actionsSlot, actionsClassName, description, descriptionClassName, trust, trustSlot, background, spacing, pattern, patternOpacity, containerClassName, contentClassName, className, headingClassName, backgroundVideo, videoSrc, videoSlot, }: HeroVideoOverlayStarsProps): React.JSX.Element;
107
123
 
108
124
  export { HeroVideoOverlayStars, type HeroVideoOverlayStarsProps };
@@ -7,6 +7,7 @@ import { Video } from '@page-speed/video';
7
7
  import { Icon } from '@page-speed/icon';
8
8
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
9
9
  import { Pressable, buttonVariants } from '@page-speed/pressable';
10
+ import { Img } from '@page-speed/img';
10
11
 
11
12
  // components/blocks/hero/hero-video-overlay-stars.tsx
12
13
  function cn(...inputs) {
@@ -25,6 +26,47 @@ var DynamicIcon = React.memo(function DynamicIcon2({
25
26
  return /* @__PURE__ */ jsx(Icon, { ...props, name, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
26
27
  });
27
28
  DynamicIcon.displayName = "DynamicIcon";
29
+ var SIZE_CLASSES = {
30
+ sm: "max-h-6 sm:max-h-7",
31
+ md: "max-h-8 sm:max-h-9 lg:max-h-10",
32
+ lg: "max-h-10 sm:max-h-12 lg:max-h-14",
33
+ xl: "max-h-12 sm:max-h-14 lg:max-h-16"
34
+ };
35
+ var BrandLogo = ({
36
+ logo,
37
+ logoSlot,
38
+ logoClassName,
39
+ size = "md",
40
+ optixFlowConfig
41
+ }) => {
42
+ if (logoSlot) return /* @__PURE__ */ jsx(Fragment, { children: logoSlot });
43
+ if (!logo || !logo.src) return null;
44
+ const imgElement = /* @__PURE__ */ jsx(
45
+ Img,
46
+ {
47
+ src: logo.src,
48
+ className: cn(
49
+ "w-auto object-contain",
50
+ SIZE_CLASSES[size],
51
+ logo.className
52
+ ),
53
+ alt: logo.alt || "Logo",
54
+ optixFlowConfig,
55
+ loading: "eager"
56
+ }
57
+ );
58
+ if (logo.url) {
59
+ return /* @__PURE__ */ jsx(
60
+ Pressable,
61
+ {
62
+ href: logo.url,
63
+ className: cn("flex items-center", logoClassName),
64
+ children: imgElement
65
+ }
66
+ );
67
+ }
68
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center", logoClassName), children: imgElement });
69
+ };
28
70
  var maxWidthStyles = {
29
71
  sm: "max-w-screen-sm",
30
72
  md: "max-w-screen-md",
@@ -481,6 +523,9 @@ function ActionComponent({ action }) {
481
523
  }
482
524
  function HeroVideoOverlayStars({
483
525
  sectionId = "hero-video-overlay-stars",
526
+ logo,
527
+ logoSlot,
528
+ logoClassName,
484
529
  heading,
485
530
  actions,
486
531
  actionsSlot,
@@ -544,6 +589,7 @@ function HeroVideoOverlayStars({
544
589
  containerClassName,
545
590
  children: [
546
591
  /* @__PURE__ */ jsx("div", { className: "relative z-10 flex size-full", children: /* @__PURE__ */ jsxs("div", { className: "m-auto flex max-w-100 flex-col items-center gap-9 sm:max-w-125 md:max-w-200 text-center", children: [
592
+ (logo || logoSlot) && /* @__PURE__ */ jsx("div", { className: cn("mb-2 flex justify-center", logoClassName), children: /* @__PURE__ */ jsx(BrandLogo, { logo, logoSlot, size: "lg" }) }),
547
593
  /* @__PURE__ */ jsxs("div", { className: cn("flex w-full flex-col gap-8", contentClassName), children: [
548
594
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
549
595
  "h1",
package/dist/registry.cjs CHANGED
@@ -53027,8 +53027,52 @@ function HeroGridPatternEfficiency({
53027
53027
  }
53028
53028
  );
53029
53029
  }
53030
+ var SIZE_CLASSES = {
53031
+ sm: "max-h-6 sm:max-h-7",
53032
+ md: "max-h-8 sm:max-h-9 lg:max-h-10",
53033
+ lg: "max-h-10 sm:max-h-12 lg:max-h-14",
53034
+ xl: "max-h-12 sm:max-h-14 lg:max-h-16"
53035
+ };
53036
+ var BrandLogo = ({
53037
+ logo,
53038
+ logoSlot: logoSlot2,
53039
+ logoClassName,
53040
+ size = "md",
53041
+ optixFlowConfig
53042
+ }) => {
53043
+ if (logoSlot2) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: logoSlot2 });
53044
+ if (!logo || !logo.src) return null;
53045
+ const imgElement = /* @__PURE__ */ jsxRuntime.jsx(
53046
+ img$1.Img,
53047
+ {
53048
+ src: logo.src,
53049
+ className: cn(
53050
+ "w-auto object-contain",
53051
+ SIZE_CLASSES[size],
53052
+ logo.className
53053
+ ),
53054
+ alt: logo.alt || "Logo",
53055
+ optixFlowConfig,
53056
+ loading: "eager"
53057
+ }
53058
+ );
53059
+ if (logo.url) {
53060
+ return /* @__PURE__ */ jsxRuntime.jsx(
53061
+ pressable.Pressable,
53062
+ {
53063
+ href: logo.url,
53064
+ className: cn("flex items-center", logoClassName),
53065
+ children: imgElement
53066
+ }
53067
+ );
53068
+ }
53069
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center", logoClassName), children: imgElement });
53070
+ };
53030
53071
  function HeroDashedBorderFeatures({
53031
53072
  sectionId = "hero-dashed-border-features",
53073
+ logo,
53074
+ logoSlot: logoSlot2,
53075
+ logoClassName,
53032
53076
  badgeText,
53033
53077
  announcementText,
53034
53078
  announcementHref,
@@ -53040,7 +53084,7 @@ function HeroDashedBorderFeatures({
53040
53084
  features,
53041
53085
  featuresSlot,
53042
53086
  background,
53043
- spacing = "xl",
53087
+ spacing = "hero",
53044
53088
  pattern,
53045
53089
  patternOpacity,
53046
53090
  className,
@@ -53113,14 +53157,18 @@ function HeroDashedBorderFeatures({
53113
53157
  pressable.Pressable,
53114
53158
  {
53115
53159
  className: cn(
53116
- "flex items-center gap-6 border-t border-dashed p-4 font-medium md:justify-center lg:p-10 lg:text-lg",
53160
+ "flex items-center gap-6 border-t border-dashed p-4 md:justify-center lg:p-10 ",
53161
+ feature.href ? "cursor-pointer bg-transparent transition-colors duration-300 hover:bg-card hover:text-card-foreground" : "",
53117
53162
  index === 1 && "md:border-x",
53118
53163
  index === 2 ? "border-b" : "md:border-b"
53119
53164
  ),
53120
53165
  href: feature.href,
53121
53166
  children: [
53122
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-md text-sm lg:size-12 lg:text-base bg-card text-card-foreground", children: feature.icon ? feature.icon : feature.iconName ? /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: feature.iconName || "lucide/check", size: 20 }) : null }),
53123
- feature.title
53167
+ feature.icon || feature.iconName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-md text-sm lg:size-12 lg:text-base bg-card text-card-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: feature.icon || feature.iconName, size: 20 }) }) : null,
53168
+ feature.title || feature.description ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-left flex flex-col gap-1", children: [
53169
+ feature.title ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-base md:text-lg line-clamp-2", children: feature.title }) : null,
53170
+ feature.description ? typeof feature.description === "string" && feature.description?.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm md:text-base opacity-70 text-balance line-clamp-1", children: feature.description }) : feature.description : null
53171
+ ] }) : null
53124
53172
  ]
53125
53173
  },
53126
53174
  index
@@ -53137,6 +53185,7 @@ function HeroDashedBorderFeatures({
53137
53185
  className: cn("relative flex items-center justify-center", className),
53138
53186
  containerClassName,
53139
53187
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
53188
+ (logo || logoSlot2) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-6", logoClassName), children: /* @__PURE__ */ jsxRuntime.jsx(BrandLogo, { logo, logoSlot: logoSlot2, size: "lg" }) }),
53140
53189
  /* @__PURE__ */ jsxRuntime.jsx(
53141
53190
  "div",
53142
53191
  {
@@ -53150,12 +53199,12 @@ function HeroDashedBorderFeatures({
53150
53199
  "h1",
53151
53200
  {
53152
53201
  className: cn(
53153
- "my-4 mb-6 text-center text-3xl font-semibold lg:text-8xl",
53202
+ "my-4 mb-6 text-center text-3xl font-semibold lg:text-8xl leading-tight",
53154
53203
  headingClassName
53155
53204
  ),
53156
53205
  children: heading
53157
53206
  }
53158
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
53207
+ ) : heading),
53159
53208
  description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
53160
53209
  "p",
53161
53210
  {
@@ -53165,7 +53214,7 @@ function HeroDashedBorderFeatures({
53165
53214
  ),
53166
53215
  children: description
53167
53216
  }
53168
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description })),
53217
+ ) : description),
53169
53218
  renderActions
53170
53219
  ] })
53171
53220
  }
@@ -53231,13 +53280,17 @@ function HeroDesignCarouselPortfolio({
53231
53280
  const renderLogo = React30.useMemo(() => {
53232
53281
  if (logoSlot2) return logoSlot2;
53233
53282
  if (!logo) return null;
53234
- const logoSrc = typeof logo.src === "string" ? logo.src : logo.src.light;
53283
+ const logoConfig = {
53284
+ src: typeof logo.src === "string" ? logo.src : logo.src.light,
53285
+ alt: logo.alt,
53286
+ className: logo.className,
53287
+ url: logo.href
53288
+ };
53235
53289
  return /* @__PURE__ */ jsxRuntime.jsx(
53236
- img$1.Img,
53290
+ BrandLogo,
53237
53291
  {
53238
- src: logoSrc,
53239
- className: cn("object-contain w-auto h-12 lg:h-16", logo.className),
53240
- alt: logo.alt,
53292
+ logo: logoConfig,
53293
+ size: "xl",
53241
53294
  optixFlowConfig
53242
53295
  }
53243
53296
  );
@@ -55881,6 +55934,9 @@ function HeroDesignShowcaseLogos({
55881
55934
  }
55882
55935
  function HeroVideoOverlayStars({
55883
55936
  sectionId = "hero-video-overlay-stars",
55937
+ logo,
55938
+ logoSlot: logoSlot2,
55939
+ logoClassName,
55884
55940
  heading,
55885
55941
  actions,
55886
55942
  actionsSlot,
@@ -55944,6 +56000,7 @@ function HeroVideoOverlayStars({
55944
56000
  containerClassName,
55945
56001
  children: [
55946
56002
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-10 flex size-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "m-auto flex max-w-100 flex-col items-center gap-9 sm:max-w-125 md:max-w-200 text-center", children: [
56003
+ (logo || logoSlot2) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mb-2 flex justify-center", logoClassName), children: /* @__PURE__ */ jsxRuntime.jsx(BrandLogo, { logo, logoSlot: logoSlot2, size: "lg" }) }),
55947
56004
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex w-full flex-col gap-8", contentClassName), children: [
55948
56005
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
55949
56006
  "h1",
@@ -117189,13 +117246,16 @@ var HERO_BLOCK_CONTRACTS = {
117189
117246
  "hero-dashed-border-features": {
117190
117247
  exampleUsage: `
117191
117248
  <HeroDashedBorderFeatures
117249
+ logo={{ src: "https://cdn.ing/assets/i/r/287634/e4cmvu8nbwoqy2qer90t4gpap0ed/logo-light.png", alt: "Brand Logo" }}
117192
117250
  heading="Features that make a difference"
117193
117251
  description="Discover the powerful capabilities that set us apart."
117194
117252
  badgeText="New Features"
117253
+ announcementText="Latest innovations"
117254
+ announcementHref="#"
117195
117255
  features={[
117196
- { icon: null, title: "Lightning Fast", description: "Optimized for speed", href: "#" },
117197
- { icon: null, title: "Secure by Default", description: "Enterprise-grade security", href: "#" },
117198
- { icon: null, title: "AI-Powered", description: "Smart automation", href: "#" },
117256
+ { iconName: "lucide/zap", title: "Lightning Fast", description: "Optimized for speed", href: "#" },
117257
+ { iconName: "lucide/shield", title: "Secure by Default", description: "Enterprise-grade security", href: "#" },
117258
+ { iconName: "lucide/sparkles", title: "AI-Powered", description: "Smart automation", href: "#" },
117199
117259
  ]}
117200
117260
  actions={[
117201
117261
  { label: "Explore Features", href: "#", variant: "default" },
@@ -117203,25 +117263,32 @@ var HERO_BLOCK_CONTRACTS = {
117203
117263
  ]}
117204
117264
  />
117205
117265
  `.trim(),
117206
- importantUsageNotes: "Supply exactly 3 'features' objects. Do not exceed 50 characters for 'heading'. Do not exceed 130 characters for 'description'. If you supply multiple 'actions', use 'default' for the first and 'outline' for the second. This is a text/icon hero \u2014 no images required.",
117266
+ importantUsageNotes: "The optional 'logo' prop accepts a LogoConfig object and renders via the BrandLogo component \u2014 it must be a brand logo image, NEVER a photo or hero image. Supply exactly 3 'features' objects. Do not exceed 50 characters for 'heading'. Do not exceed 130 characters for 'description'. If you supply multiple 'actions', use 'default' for the first and 'outline' for the second.",
117207
117267
  usageRequirements: {
117208
117268
  requiredProps: ["heading", "features"],
117209
117269
  propConstraints: {
117210
117270
  heading: { required: true, maxLength: 50 },
117211
117271
  description: { maxLength: 130 },
117212
117272
  features: { required: true, count: 3, minItems: 2, maxItems: 4 },
117213
- actions: { maxItems: 2, pinnedValues: { "0.variant": "default", "1.variant": "outline" } }
117273
+ actions: { maxItems: 2, pinnedValues: { "0.variant": "default", "1.variant": "outline" } },
117274
+ "logo.src": { note: "LOGO MEDIA ONLY. Must be a brand logo image (SVG, PNG, WebP). Never use a photo, hero image, or video asset." }
117214
117275
  },
117215
- mediaSlots: {}
117276
+ mediaSlots: {
117277
+ "logo.src": logoSlot("logo.src", "Brand logo rendered via BrandLogo component above the dashed border content.", false)
117278
+ },
117279
+ notes: ["The logo prop is optional. When provided, the BrandLogo component renders it above the announcement badge with responsive sizing."]
117216
117280
  },
117217
117281
  exampleProps: {
117282
+ logo: { src: "https://cdn.ing/assets/i/r/287634/e4cmvu8nbwoqy2qer90t4gpap0ed/logo-light.png", alt: "Brand Logo" },
117218
117283
  heading: "Features that make a difference",
117219
117284
  description: "Discover the powerful capabilities that set us apart.",
117220
117285
  badgeText: "New Features",
117286
+ announcementText: "Latest innovations",
117287
+ announcementHref: "#",
117221
117288
  features: [
117222
- { title: "Lightning Fast", description: "Optimized for speed", href: "#" },
117223
- { title: "Secure by Default", description: "Enterprise-grade security", href: "#" },
117224
- { title: "AI-Powered", description: "Smart automation", href: "#" }
117289
+ { iconName: "lucide/zap", title: "Lightning Fast", description: "Optimized for speed", href: "#" },
117290
+ { iconName: "lucide/shield", title: "Secure by Default", description: "Enterprise-grade security", href: "#" },
117291
+ { iconName: "lucide/sparkles", title: "AI-Powered", description: "Smart automation", href: "#" }
117225
117292
  ],
117226
117293
  actions: [
117227
117294
  { label: "Explore Features", href: "#", variant: "default" },
@@ -117235,12 +117302,13 @@ var HERO_BLOCK_CONTRACTS = {
117235
117302
  "hero-design-carousel-portfolio": {
117236
117303
  exampleUsage: `
117237
117304
  <HeroDesignCarouselPortfolio
117305
+ logo={{ src: "https://cdn.ing/assets/i/r/287634/e4cmvu8nbwoqy2qer90t4gpap0ed/logo-light.png", alt: "Brand Logo" }}
117238
117306
  heading="Design portfolio that speaks volumes"
117239
117307
  description="Showcase your best work with beautiful, interactive carousels."
117240
117308
  features={[
117241
- { title: "Strategic Focus", description: "Aligning work with your goals." },
117242
- { title: "Rapid Execution", description: "Agile methodology for fast delivery." },
117243
- { title: "Human-Centered", description: "Design for people first." },
117309
+ { iconName: "lucide/target", title: "Strategic Focus", description: "Aligning work with your goals." },
117310
+ { iconName: "lucide/zap", title: "Rapid Execution", description: "Agile methodology for fast delivery." },
117311
+ { iconName: "lucide/heart", title: "Human-Centered", description: "Design for people first." },
117244
117312
  ]}
117245
117313
  carouselImages={[
117246
117314
  { src: "${HERO_EXAMPLE_IMAGE_URL}", alt: "Design 1" },
@@ -117254,7 +117322,7 @@ var HERO_BLOCK_CONTRACTS = {
117254
117322
  ]}
117255
117323
  />
117256
117324
  `.trim(),
117257
- importantUsageNotes: `Supply exactly 4 carousel images. Supply exactly 3 'features' objects. Do not exceed 50 characters for 'heading'. Do not exceed 130 characters for 'description'. If you supply multiple 'actions', use 'default' for the first and 'outline' for the second. ${HERO_MEDIA_NOTE}`,
117325
+ importantUsageNotes: `The 'logo' prop renders via BrandLogo and must be a brand logo image (SVG, PNG, WebP) \u2014 NEVER a photo or hero image. The AI Agent must use a real brand logo asset here, not an image placeholder. Supply exactly 4 carousel images for the portfolio. Supply exactly 3 'features'. ${HERO_MEDIA_NOTE}`,
117258
117326
  usageRequirements: {
117259
117327
  requiredProps: ["heading", "carouselImages", "features"],
117260
117328
  propConstraints: {
@@ -117262,21 +117330,23 @@ var HERO_BLOCK_CONTRACTS = {
117262
117330
  description: { maxLength: 130 },
117263
117331
  carouselImages: { required: true, count: 4, minItems: 3, maxItems: 5 },
117264
117332
  features: { required: true, count: 3, minItems: 3, maxItems: 3 },
117265
- actions: { maxItems: 2, pinnedValues: { "0.variant": "default", "1.variant": "outline" } }
117333
+ actions: { maxItems: 2, pinnedValues: { "0.variant": "default", "1.variant": "outline" } },
117334
+ "logo.src": { note: "LOGO MEDIA ONLY. Must be a brand logo image. Never use a photo, hero image, or video asset." }
117266
117335
  },
117267
117336
  mediaSlots: {
117268
117337
  "carouselImages[]": imageSlot("carouselImages[]", "Portfolio showcase images for the carousel.", ["feature", "hero"], "medium", true),
117269
- "logo.src": logoSlot("logo.src", "Optional brand or client logo.")
117338
+ "logo.src": logoSlot("logo.src", "Brand logo rendered via BrandLogo component above the features and heading.", false)
117270
117339
  },
117271
117340
  requiresSiteCapabilities: heroCapabilities("media_library")
117272
117341
  },
117273
117342
  exampleProps: {
117343
+ logo: { src: "https://cdn.ing/assets/i/r/287634/e4cmvu8nbwoqy2qer90t4gpap0ed/logo-light.png", alt: "Brand Logo" },
117274
117344
  heading: "Design portfolio that speaks volumes",
117275
117345
  description: "Showcase your best work with beautiful, interactive carousels.",
117276
117346
  features: [
117277
- { title: "Strategic Focus", description: "Aligning work with your goals." },
117278
- { title: "Rapid Execution", description: "Agile methodology for fast delivery." },
117279
- { title: "Human-Centered", description: "Design for people first." }
117347
+ { iconName: "lucide/target", title: "Strategic Focus", description: "Aligning work with your goals." },
117348
+ { iconName: "lucide/zap", title: "Rapid Execution", description: "Agile methodology for fast delivery." },
117349
+ { iconName: "lucide/heart", title: "Human-Centered", description: "Design for people first." }
117280
117350
  ],
117281
117351
  carouselImages: Array(4).fill({ src: HERO_EXAMPLE_IMAGE_URL, alt: "Design" }),
117282
117352
  actions: [
@@ -118063,6 +118133,7 @@ var HERO_BLOCK_CONTRACTS = {
118063
118133
  "hero-video-overlay-stars": {
118064
118134
  exampleUsage: `
118065
118135
  <HeroVideoOverlayStars
118136
+ logo={{ src: "https://cdn.ing/assets/i/r/287634/e4cmvu8nbwoqy2qer90t4gpap0ed/logo-light.png", alt: "Brand Logo" }}
118066
118137
  heading="Trusted by thousands"
118067
118138
  description="Our solution is designed to streamline your business operations."
118068
118139
  actions={[{ label: "Try It Free", href: "#" }]}
@@ -118075,21 +118146,24 @@ var HERO_BLOCK_CONTRACTS = {
118075
118146
  trust={{ starCount: 5, message: "Trusted by 2,500+ customers" }}
118076
118147
  />
118077
118148
  `.trim(),
118078
- importantUsageNotes: `Only use when you have a real video asset. The 'backgroundVideo.video' prop requires masterPlaylistUrl and fallbackSrc. Only supply real 'trust.message' \u2014 do not fabricate review counts. Do not exceed 40 characters for 'heading'. ${HERO_MEDIA_NOTE}`,
118149
+ importantUsageNotes: `The optional 'logo' prop renders via BrandLogo centered above the heading \u2014 it must be a brand logo image, NEVER a photo. Only use when you have a real video asset. The 'backgroundVideo.video' prop requires masterPlaylistUrl and fallbackSrc. Only supply real 'trust.message' \u2014 do not fabricate review counts. ${HERO_MEDIA_NOTE}`,
118079
118150
  usageRequirements: {
118080
118151
  requiredProps: ["heading", "backgroundVideo"],
118081
118152
  propConstraints: {
118082
118153
  heading: { required: true, maxLength: 40 },
118083
118154
  description: { maxLength: 130 },
118084
118155
  backgroundVideo: { required: true, note: "Must contain a valid video with masterPlaylistUrl and fallbackSrc." },
118085
- "trust.message": { note: "Must be real trust/review data. Do not fabricate." }
118156
+ "trust.message": { note: "Must be real trust/review data. Do not fabricate." },
118157
+ "logo.src": { note: "LOGO MEDIA ONLY. Must be a brand logo image. Never use a photo, hero image, or video asset." }
118086
118158
  },
118087
118159
  mediaSlots: {
118088
- "backgroundVideo.video": videoMediaSlot("backgroundVideo.video")
118160
+ "backgroundVideo.video": videoMediaSlot("backgroundVideo.video"),
118161
+ "logo.src": logoSlot("logo.src", "Brand logo rendered via BrandLogo centered above the heading on the video overlay.", false)
118089
118162
  },
118090
118163
  requiresSiteCapabilities: heroCapabilities("media_library", "reviews_or_testimonials")
118091
118164
  },
118092
118165
  exampleProps: {
118166
+ logo: { src: "https://cdn.ing/assets/i/r/287634/e4cmvu8nbwoqy2qer90t4gpap0ed/logo-light.png", alt: "Brand Logo" },
118093
118167
  heading: "Trusted by thousands",
118094
118168
  description: "Our solution is designed to streamline your business operations.",
118095
118169
  backgroundVideo: { video: EXAMPLE_VIDEO_1 },