@@ -10,7 +10,9 @@ import {
1010 ExperienceComponentNode ,
1111 DisplaySettingsType ,
1212 ExperienceCompositionNode ,
13+ InferredContentReference ,
1314} from '../infer.js' ;
15+ import { Renditions } from '../model/assets.js' ;
1416import { isComponentNode } from '../util/baseTypeUtil.js' ;
1517import { parseDisplaySettings } from '../model/displayTemplates.js' ;
1618import { getDisplayTemplateTag } from '../model/displayTemplateRegistry.js' ;
@@ -308,6 +310,15 @@ export function OptimizelyGridSection({
308310
309311/** Get context-aware functions for preview */
310312export function getPreviewUtils ( opti : OptimizelyComponentProps [ 'opti' ] ) {
313+ /** Helper function to append preview token to URL */
314+ const appendPreviewToken = ( url : string ) : string => {
315+ if ( opti . __context ?. preview_token ) {
316+ const separator = url . includes ( '?' ) ? '&' : '?' ;
317+ return `${ url } ${ separator } preview_token=${ opti . __context . preview_token } ` ;
318+ }
319+ return url ;
320+ } ;
321+
311322 return {
312323 /** Get the HTML data attributes required for a property */
313324 pa ( property ?: string | { key : string } ) {
@@ -328,13 +339,81 @@ export function getPreviewUtils(opti: OptimizelyComponentProps['opti']) {
328339 }
329340 } ,
330341
331- /** Appends the preview token to the provided image URL */
332- src ( url : string ) {
333- if ( opti . __context ?. preview_token ) {
334- const separator = url . includes ( '?' ) ? '&' : '?' ;
335- return `${ url } ${ separator } preview_token=${ opti . __context . preview_token } ` ;
342+ /** Appends the preview token to the provided image URL or ContentReference */
343+ src (
344+ input : string | InferredContentReference | null | undefined ,
345+ options ?: { renditionName ?: string }
346+ ) : string {
347+ if ( ! input ) return '' ;
348+
349+ let url : string ;
350+ if ( typeof input === 'string' ) {
351+ url = input ;
352+ } else {
353+ // If renditionName is specified, find the matching rendition
354+ if (
355+ options ?. renditionName &&
356+ input . item &&
357+ 'Renditions' in input . item
358+ ) {
359+ const rendition = input . item . Renditions ?. find (
360+ ( r ) => r . Name === options . renditionName
361+ ) ;
362+ if ( rendition ?. Url ) {
363+ url = rendition . Url ;
364+ } else {
365+ // Fallback to default URL if rendition not found
366+ url = input . item ?. Url ?? input . url ?. default ?? '' ;
367+ }
368+ } else {
369+ // Prefer item.Url if available (DAM asset), otherwise use url.default
370+ url = input . item ?. Url ?? input . url ?. default ?? '' ;
371+ }
372+ }
373+
374+ return appendPreviewToken ( url ) ;
375+ } ,
376+
377+ /** Generates srcset from ContentReference renditions */
378+ srcset ( input : InferredContentReference | null | undefined ) : string {
379+ if ( ! input ?. item || ! ( 'Renditions' in input . item ) ) return '' ;
380+
381+ const renditions = input . item . Renditions ;
382+ if ( ! renditions || renditions . length === 0 ) return '' ;
383+
384+ // Track seen widths to avoid duplicate width descriptors
385+ const seenWidths = new Set < number > ( ) ;
386+
387+ const srcsetEntries = renditions
388+ . filter ( ( r ) => {
389+ if ( ! r . Url || ! r . Width ) return false ;
390+ // Skip if we've already seen this width
391+ if ( seenWidths . has ( r . Width ) ) return false ;
392+ seenWidths . add ( r . Width ) ;
393+ return true ;
394+ } )
395+ . map ( ( r ) => {
396+ const url = appendPreviewToken ( r . Url ! ) ;
397+ return `${ url } ${ r . Width } w` ;
398+ } ) ;
399+
400+ return srcsetEntries . join ( ', ' ) ;
401+ } ,
402+
403+ /** Gets the alt text from a ContentReference or returns the string as-is */
404+ alt ( input : string | InferredContentReference | null | undefined ) : string {
405+ if ( ! input ) return '' ;
406+
407+ if ( typeof input === 'string' ) {
408+ return input ;
409+ }
410+
411+ // Check if item has AltText property (PublicImageAsset or PublicVideoAsset)
412+ if ( input . item && 'AltText' in input . item ) {
413+ return input . item . AltText ?? '' ;
336414 }
337- return url ;
415+
416+ return '' ;
338417 } ,
339418 } ;
340419}
0 commit comments