1- /**
2- * Copyright 2026 Salesforce, Inc.
3- *
4- * Licensed under the Apache License, Version 2.0 (the "License");
5- * you may not use this file except in compliance with the License.
6- * You may obtain a copy of the License at
7- *
8- * http://www.apache.org/licenses/LICENSE-2.0
9- *
10- * Unless required by applicable law or agreed to in writing, software
11- * distributed under the License is distributed on an "AS IS" BASIS,
12- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13- * See the License for the specific language governing permissions and
14- * limitations under the License.
1+ /*
2+ * Copyright (c) 2026, Salesforce, Inc.
3+ * All rights reserved.
4+ * SPDX-License-Identifier: BSD-3-Clause
5+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
156 */
167import React , { type ReactElement , type ReactNode , Suspense } from 'react'
17- import { Component } from '../Component' ;
18- import { RegionWrapper } from './region-wrapper' ;
19- import type { ShopperExperience } from '@salesforce/storefront-next-runtime/scapi' ;
8+ import { Component } from '../Component'
9+ import { RegionWrapper } from './region-wrapper'
10+ import type { ShopperExperience } from '@salesforce/storefront-next-runtime/scapi'
2011import {
2112 PageDesignerPageMetadataProvider ,
22- useRegionContext ,
23- } from '@salesforce/storefront-next-runtime/design/react/core' ;
13+ useRegionContext
14+ } from '@salesforce/storefront-next-runtime/design/react/core'
2415import type {
2516 ComponentDecoratorProps ,
26- RegionDesignMetadata ,
27- } from '@salesforce/storefront-next-runtime/design/react' ;
17+ RegionDesignMetadata
18+ } from '@salesforce/storefront-next-runtime/design/react'
2819
29- export type { RegionDesignMetadata } ;
20+ export type { RegionDesignMetadata }
3021
3122export interface PageDesignMetadata {
32- id : string ;
33- name : string ;
34- description ?: string ;
35- archType ?: 'controller' | 'headless' ;
36- route ?: string ;
37- supportedAspectTypes ?: string [ ] ;
38- regionDefinitions ?: RegionDesignMetadata [ ] ;
23+ id : string
24+ name : string
25+ description ?: string
26+ archType ?: 'controller' | 'headless'
27+ route ?: string
28+ supportedAspectTypes ?: string [ ]
29+ regionDefinitions ?: RegionDesignMetadata [ ]
3930 attributeDefinitionGroups ?: {
40- id : string ;
41- name ?: string ;
42- description ?: string ;
43- attributeDefinitions ?: Record < string , unknown > [ ] ;
44- } [ ] ;
31+ id : string
32+ name ?: string
33+ description ?: string
34+ attributeDefinitions ?: Record < string , unknown > [ ]
35+ } [ ]
4536}
4637
4738export type PageDecoratorProps < TProps > = React . PropsWithChildren <
4839 {
49- designMetadata ?: PageDesignMetadata ;
40+ designMetadata ?: PageDesignMetadata
5041 } & TProps
51- > ;
42+ >
5243
5344// Extended Page type with design metadata
5445type PageWithDesignMetadata = PageDecoratorProps < ShopperExperience . schemas [ 'Page' ] > & {
55- componentData ?: Record < string , Promise < unknown > > ;
56- } ;
46+ componentData ?: Record < string , Promise < unknown > >
47+ }
5748
5849// Props when rendering a page-level region
5950interface PageRegionProps extends React . HTMLAttributes < HTMLDivElement > {
60- page : PageWithDesignMetadata ;
61- component ?: never ;
62- regionId : string ;
63- fallbackElement ?: ReactNode ;
64- errorElement ?: ReactNode ;
51+ page : PageWithDesignMetadata
52+ component ?: never
53+ regionId : string
54+ fallbackElement ?: ReactNode
55+ errorElement ?: ReactNode
6556}
6657
67- export type ComponentType = ComponentDecoratorProps < ShopperExperience . schemas [ 'Component' ] > ;
58+ export type ComponentType = ComponentDecoratorProps < ShopperExperience . schemas [ 'Component' ] >
6859
6960// Props when rendering a component-level region (nested)
7061interface ComponentRegionProps extends React . HTMLAttributes < HTMLDivElement > {
71- page ?: never ;
72- component : ComponentType ;
73- regionId : string ;
74- fallbackElement ?: ReactNode ;
75- errorElement ?: ReactNode ;
62+ page ?: never
63+ component : ComponentType
64+ regionId : string
65+ fallbackElement ?: ReactNode
66+ errorElement ?: ReactNode
7667}
7768
7869// Discriminated union
79- export type RegionProps = PageRegionProps | ComponentRegionProps ;
70+ export type RegionProps = PageRegionProps | ComponentRegionProps
8071
8172// Helper: Extract design metadata from region definition
8273function getDesignMetadata ( regionId : string , metadata ?: RegionDesignMetadata ) {
8374 return {
8475 id : regionId ,
8576 componentTypeExclusions : metadata ?. componentTypeExclusions ?? [ ] ,
86- componentTypeInclusions : metadata ?. componentTypeInclusions ?? [ ] ,
87- } ;
77+ componentTypeInclusions : metadata ?. componentTypeInclusions ?? [ ]
78+ }
8879}
8980
9081// Helper: Render region wrapper with components
@@ -100,12 +91,20 @@ function renderRegionContent(
10091 region = { region }
10192 className = { className }
10293 designMetadata = { getDesignMetadata ( regionId , metadata ) }
103- { ...rest } >
94+ { ...rest }
95+ >
10496 { region . components ?. map (
105- ( comp ) => comp . id && < Component key = { comp . id } component = { comp as ComponentType } regionId = { region . id } />
97+ ( comp ) =>
98+ comp . id && (
99+ < Component
100+ key = { comp . id }
101+ component = { comp as ComponentType }
102+ regionId = { region . id }
103+ />
104+ )
106105 ) }
107106 </ RegionWrapper >
108- ) ;
107+ )
109108}
110109
111110/**
@@ -142,39 +141,41 @@ function renderRegionContent(
142141 * regions that can contain multiple components managed through the Page Designer interface.
143142 */
144143export function Region ( props : RegionProps ) : ReactElement | null {
145- const { regionId, className = '' , errorElement, fallbackElement = < div /> , ...rest } = props ;
146- const regionContext = useRegionContext ( ) ;
144+ const { regionId, className = '' , errorElement, fallbackElement = < div /> , ...rest } = props
145+ const regionContext = useRegionContext ( )
147146
148147 // COMPONENT MODE: Rendering a component-level region (nested)
149148 if ( props . component !== undefined ) {
150- const region = props . component . regions ?. find ( ( r ) => r . id === regionId ) ;
149+ const region = props . component . regions ?. find ( ( r ) => r . id === regionId )
151150 if ( ! region ) {
152- return errorElement ? < > { errorElement } </ > : null ;
151+ return errorElement ? < > { errorElement } </ > : null
153152 }
154153
155- const metadata = props . component . designMetadata ?. regionDefinitions ?. find ( ( r ) => r . id === regionId ) ;
156- return renderRegionContent ( region , regionId , metadata , className , rest ) ;
154+ const metadata = props . component . designMetadata ?. regionDefinitions ?. find (
155+ ( r ) => r . id === regionId
156+ )
157+ return renderRegionContent ( region , regionId , metadata , className , rest )
157158 }
158159
159160 // PAGE MODE: Rendering a page-level region
160- const page = props . page ;
161- const region = page ?. regions ?. find ( ( r ) => r . id === regionId ) ;
161+ const page = props . page
162+ const region = page ?. regions ?. find ( ( r ) => r . id === regionId )
162163 if ( ! region ) {
163- return errorElement ? < > { errorElement } </ > : null ;
164+ return errorElement ? < > { errorElement } </ > : null
164165 }
165166
166- const metadata = page . designMetadata ?. regionDefinitions ?. find ( ( r ) => r . id === regionId ) ;
167- const { componentData : pageComponentData , ...pageData } = page ;
167+ const metadata = page . designMetadata ?. regionDefinitions ?. find ( ( r ) => r . id === regionId )
168+ const { componentData : pageComponentData , ...pageData } = page
168169
169170 return (
170171 < Suspense fallback = { fallbackElement } >
171172 { ! regionContext && < PageDesignerPageMetadataProvider page = { pageData } /> }
172173 { renderRegionContent ( region , regionId , metadata , className , rest ) }
173174 </ Suspense >
174- ) ;
175+ )
175176}
176177
177178export default Region
178179// Re-export RegionWrapper for direct usage if needed
179- export { RegionWrapper } from './region-wrapper' ;
180- export type { RegionRendererProps } from './region-wrapper' ;
180+ export { RegionWrapper } from './region-wrapper'
181+ export type { RegionRendererProps } from './region-wrapper'
0 commit comments