From dd74cf7066b905de1bc41905147b66cc568c3bb7 Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Fri, 17 May 2024 14:05:46 +0300 Subject: [PATCH 1/6] [sitecore-jss-react] [sitecore-jss-nextjs] Reconciled withSitecoreContext and Placeholder types --- CHANGELOG.md | 3 +-- docs/upgrades/unreleased.md | 3 +-- .../src/components/Placeholder.tsx | 9 ++++++++- packages/sitecore-jss-nextjs/src/index.ts | 2 +- .../src/components/PlaceholderCommon.tsx | 3 +-- .../src/components/SitecoreContext.test.tsx | 4 ++-- .../src/enhancers/withSitecoreContext.tsx | 18 +++++++++++------- packages/sitecore-jss-react/src/index.ts | 3 ++- packages/sitecore-jss/src/utils/index.ts | 2 +- packages/sitecore-jss/src/utils/utils.ts | 7 +++++++ 10 files changed, 35 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38d9aab5bd..ea1c907191 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,8 +24,7 @@ Our versioning strategy is as follows: * Editing Integration Support: ([#1776](https://github.com/Sitecore/jss/pull/1776))([#1792](https://github.com/Sitecore/jss/pull/1792)) ([#1773](https://github.com/Sitecore/jss/pull/1773)) * `[sitecore-jss-react]` Introduces `PlaceholderMetadata` component which supports the hydration of chromes on Pages by rendering the components and placeholders with required metadata. * `[sitecore-jss]` Chromes are hydrated based on the basis of new `editMode` property derived from LayoutData, which is defined as an enum consisting of `metadata` and `chromes`. - * `[sitecore-jss-react]` _sitecoreContext_ property within the `WithSitecoreContextProps` interface has been made optional. If you use _withSitecoreContext_ HOC please add safegaurds for scenarios where `sitecoreContext` could be undefined. - * `WithSitecoreContextHocProps` is now deprecated and removed. Please use your own component prop types. + * `ComponentConsumerProps` is removed. You might need to reuse _WithSitecoreContextProps_ type. * `[sitecore-jss-react]` `[sitecore-jss-nextjs]` Introduce FieldMetadata component and functionality to render it when metadata field property is provided in the field's layout data. In such case the field component is wrapped with metadata markup to enable chromes hydration when editing in pages. Ability to render metadata has been added to the field rendering components for react and nextjs. ## 22.0.0 diff --git a/docs/upgrades/unreleased.md b/docs/upgrades/unreleased.md index 98bc99b5fe..f1d5edf5a6 100644 --- a/docs/upgrades/unreleased.md +++ b/docs/upgrades/unreleased.md @@ -3,8 +3,7 @@ # react * With the simplification of Editing Support work we have added the following breaking changes to the `sitecore-jss-react` package. Please make the necessary updates. - - `sitecoreContext` property within the `WithSitecoreContextProps` interface has been made optional. Please add safegaurds for scenarios where `sitecoreContext` could be undefined. - - `WithSitecoreContextHocProps` is now deprecated and removed. We suggest that you define and use your own component prop types. + - `ComponentConsumerProps` is removed. You might need to reuse _WithSitecoreContextProps_ type. ### headless-ssr-experience-edge * Replace `scripts/generate-config.js` if you have not modified it. Otherwise: diff --git a/packages/sitecore-jss-nextjs/src/components/Placeholder.tsx b/packages/sitecore-jss-nextjs/src/components/Placeholder.tsx index 42713cb1d1..1ba2b7ab20 100644 --- a/packages/sitecore-jss-nextjs/src/components/Placeholder.tsx +++ b/packages/sitecore-jss-nextjs/src/components/Placeholder.tsx @@ -2,10 +2,17 @@ import React, { useContext } from 'react'; import { Placeholder as ReactPlaceholder, PlaceholderComponentProps, + WithSitecoreContextProps, + EnhancedOmit, } from '@sitecore-jss/sitecore-jss-react'; import { ComponentPropsReactContext } from './ComponentPropsContext'; -export const Placeholder = (props: PlaceholderComponentProps) => { +/** + * React Placeholder component wrapped by withSitecoreContext, so these properties shouldn't be passed to the Next.js Placeholder. + */ +type PlaceholderProps = EnhancedOmit; + +export const Placeholder = (props: PlaceholderProps) => { const componentPropsContext = useContext(ComponentPropsReactContext); return ( diff --git a/packages/sitecore-jss-nextjs/src/index.ts b/packages/sitecore-jss-nextjs/src/index.ts index 8fea6e3cf7..874148de1c 100644 --- a/packages/sitecore-jss-nextjs/src/index.ts +++ b/packages/sitecore-jss-nextjs/src/index.ts @@ -165,8 +165,8 @@ export { withPlaceholder, withDatasourceCheck, ImageSizeParameters, - ComponentConsumerProps, WithSitecoreContextOptions, WithSitecoreContextProps, + WithSitecoreContextHocProps, withFieldMetadata, } from '@sitecore-jss/sitecore-jss-react'; diff --git a/packages/sitecore-jss-react/src/components/PlaceholderCommon.tsx b/packages/sitecore-jss-react/src/components/PlaceholderCommon.tsx index 9c634b3d8f..99039f6b9e 100644 --- a/packages/sitecore-jss-react/src/components/PlaceholderCommon.tsx +++ b/packages/sitecore-jss-react/src/components/PlaceholderCommon.tsx @@ -81,8 +81,7 @@ export interface PlaceholderProps { /** * Context data from the Sitecore Layout Service */ - sitecoreContext?: SitecoreContextValue; - + sitecoreContext: SitecoreContextValue; /** * The message that gets displayed while component is loading */ diff --git a/packages/sitecore-jss-react/src/components/SitecoreContext.test.tsx b/packages/sitecore-jss-react/src/components/SitecoreContext.test.tsx index 955dfb8697..a0de96fc01 100644 --- a/packages/sitecore-jss-react/src/components/SitecoreContext.test.tsx +++ b/packages/sitecore-jss-react/src/components/SitecoreContext.test.tsx @@ -4,10 +4,10 @@ import { shallow } from 'enzyme'; import { SitecoreContext } from './SitecoreContext'; import { ComponentFactory } from './sharedTypes'; -import { withSitecoreContext, ComponentConsumerProps } from '../enhancers/withSitecoreContext'; +import { WithSitecoreContextProps, withSitecoreContext } from '../enhancers/withSitecoreContext'; import { LayoutServiceData } from '../index'; -interface NestedComponentProps extends ComponentConsumerProps { +interface NestedComponentProps extends WithSitecoreContextProps { anotherProperty?: string; } const NestedComponent: FC = (props: NestedComponentProps) => ( diff --git a/packages/sitecore-jss-react/src/enhancers/withSitecoreContext.tsx b/packages/sitecore-jss-react/src/enhancers/withSitecoreContext.tsx index 72e79cebca..46f455a159 100644 --- a/packages/sitecore-jss-react/src/enhancers/withSitecoreContext.tsx +++ b/packages/sitecore-jss-react/src/enhancers/withSitecoreContext.tsx @@ -1,27 +1,31 @@ -import React, { ReactNode } from 'react'; +import React from 'react'; +import { EnhancedOmit } from '@sitecore-jss/sitecore-jss/utils'; import { SitecoreContextReactContext, SitecoreContextValue } from '../components/SitecoreContext'; export interface WithSitecoreContextOptions { updatable?: boolean; } +// The props that HOC will inject export interface WithSitecoreContextProps { - sitecoreContext?: SitecoreContextValue; + sitecoreContext: SitecoreContextValue; updateSitecoreContext?: ((value: SitecoreContextValue) => void) | false; } -export interface ComponentConsumerProps extends WithSitecoreContextProps { - children?: ReactNode; -} +// The props that HOC will receive. +export type WithSitecoreContextHocProps = EnhancedOmit< + ComponentProps, + keyof WithSitecoreContextProps +>; /** * @param {WithSitecoreContextOptions} [options] */ export function withSitecoreContext(options?: WithSitecoreContextOptions) { - return function withSitecoreContextHoc( + return function withSitecoreContextHoc( Component: React.ComponentType ) { - return function WithSitecoreContext(props: ComponentProps) { + return function WithSitecoreContext(props: WithSitecoreContextHocProps) { return ( {(context) => ( diff --git a/packages/sitecore-jss-react/src/index.ts b/packages/sitecore-jss-react/src/index.ts index bfdc6464e2..60556cd528 100644 --- a/packages/sitecore-jss-react/src/index.ts +++ b/packages/sitecore-jss-react/src/index.ts @@ -8,6 +8,7 @@ export { FieldEditButton, WebEditButton, EditButtonTypes, + EnhancedOmit, } from '@sitecore-jss/sitecore-jss/utils'; export { getContentStylesheetLink, @@ -92,9 +93,9 @@ export { export { withSitecoreContext, useSitecoreContext, - ComponentConsumerProps, WithSitecoreContextOptions, WithSitecoreContextProps, + WithSitecoreContextHocProps, } from './enhancers/withSitecoreContext'; export { withEditorChromes } from './enhancers/withEditorChromes'; export { withPlaceholder } from './enhancers/withPlaceholder'; diff --git a/packages/sitecore-jss/src/utils/index.ts b/packages/sitecore-jss/src/utils/index.ts index cde295e130..60b7b7fae7 100644 --- a/packages/sitecore-jss/src/utils/index.ts +++ b/packages/sitecore-jss/src/utils/index.ts @@ -1,5 +1,5 @@ export { default as isServer } from './is-server'; -export { resolveUrl, isAbsoluteUrl, isTimeoutError } from './utils'; +export { resolveUrl, isAbsoluteUrl, isTimeoutError, EnhancedOmit } from './utils'; export { tryParseEnvValue } from './env'; export { ExperienceEditor, diff --git a/packages/sitecore-jss/src/utils/utils.ts b/packages/sitecore-jss/src/utils/utils.ts index 137a0718de..c2bfe4c229 100644 --- a/packages/sitecore-jss/src/utils/utils.ts +++ b/packages/sitecore-jss/src/utils/utils.ts @@ -3,6 +3,13 @@ import { ParsedUrlQueryInput } from 'querystring'; import { AxiosError } from 'axios'; import { ResponseError } from '../data-fetcher'; +/** + * Omit properties from T that are in K. This is a simplified version of TypeScript's built-in `Omit` utility type. + * Since default `Omit` doesn't support indexing types, we had to introduce this custom implementation. + */ +// eslint-disable-next-line prettier/prettier +export type EnhancedOmit = { [P in keyof T as Exclude]: T[P] }; + /** * note: encodeURIComponent is available via browser (window) or natively in node.js * if you use another js engine for server-side rendering you may not have native encodeURIComponent From 76e5cfd1b389cd9fa1a17f23e65c1c428e678d5d Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Fri, 17 May 2024 14:21:50 +0300 Subject: [PATCH 2/6] Reuse default _editable_ value in withFieldMetadata component --- .../src/enhancers/withFieldMetadata.tsx | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx b/packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx index 5702c3d9d2..246345e0a6 100644 --- a/packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx +++ b/packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx @@ -19,28 +19,28 @@ export function withFieldMetadata< >(FieldComponent: ComponentType, isForwardRef = false) { if (isForwardRef) { // eslint-disable-next-line react/display-name - return forwardRef( - ({ ...props }: FieldComponentProps, ref: React.ForwardedRef) => { - const metadata = props.field?.metadata; + return forwardRef((props: FieldComponentProps, ref: React.ForwardedRef) => { + const { editable = true } = props; + const metadata = props.field?.metadata; - if (!metadata || !props.editable) { - return ; - } - - return ( - - - - ); + if (!metadata || !editable) { + return ; } - ); + + return ( + + + + ); + }); } // eslint-disable-next-line react/display-name return ({ ...props }: FieldComponentProps) => { + const { editable = true } = props; const metadata = props.field?.metadata; - if (!metadata || !props.editable) { + if (!metadata || !editable) { return ; } From 28446bd73b44d369b1304494b729a68bc99a9462 Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Fri, 17 May 2024 14:23:04 +0300 Subject: [PATCH 3/6] Updated CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea1c907191..2deb26347c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ Our versioning strategy is as follows: ### 🛠 Breaking Change -* Editing Integration Support: ([#1776](https://github.com/Sitecore/jss/pull/1776))([#1792](https://github.com/Sitecore/jss/pull/1792)) ([#1773](https://github.com/Sitecore/jss/pull/1773)) +* Editing Integration Support: ([#1776](https://github.com/Sitecore/jss/pull/1776))([#1792](https://github.com/Sitecore/jss/pull/1792)) ([#1773](https://github.com/Sitecore/jss/pull/1773))([#1797](https://github.com/Sitecore/jss/pull/1797)) * `[sitecore-jss-react]` Introduces `PlaceholderMetadata` component which supports the hydration of chromes on Pages by rendering the components and placeholders with required metadata. * `[sitecore-jss]` Chromes are hydrated based on the basis of new `editMode` property derived from LayoutData, which is defined as an enum consisting of `metadata` and `chromes`. * `ComponentConsumerProps` is removed. You might need to reuse _WithSitecoreContextProps_ type. From ac621f6eadacb409b6cb937cc50f0c1ef844976a Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Fri, 17 May 2024 14:35:34 +0300 Subject: [PATCH 4/6] Updated props param --- packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx b/packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx index 246345e0a6..b403cd021f 100644 --- a/packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx +++ b/packages/sitecore-jss-react/src/enhancers/withFieldMetadata.tsx @@ -36,7 +36,7 @@ export function withFieldMetadata< } // eslint-disable-next-line react/display-name - return ({ ...props }: FieldComponentProps) => { + return (props: FieldComponentProps) => { const { editable = true } = props; const metadata = props.field?.metadata; From 6d8b5cc70073962e1ee17649866e3e153f435958 Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Mon, 20 May 2024 09:32:37 +0300 Subject: [PATCH 5/6] Remove extra type --- packages/sitecore-jss-react/src/components/Placeholder.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/sitecore-jss-react/src/components/Placeholder.tsx b/packages/sitecore-jss-react/src/components/Placeholder.tsx index 9b4effa26d..7fbad2ee9a 100644 --- a/packages/sitecore-jss-react/src/components/Placeholder.tsx +++ b/packages/sitecore-jss-react/src/components/Placeholder.tsx @@ -123,6 +123,4 @@ class PlaceholderComponent extends PlaceholderCommon const PlaceholderWithComponentFactory = withComponentFactory(PlaceholderComponent); -export const Placeholder = withSitecoreContext()( - PlaceholderWithComponentFactory -); +export const Placeholder = withSitecoreContext()(PlaceholderWithComponentFactory); From 99abaeaa0ef61948d4ec09d54cc5aad8a412f10c Mon Sep 17 00:00:00 2001 From: illiakovalenko Date: Mon, 20 May 2024 09:35:02 +0300 Subject: [PATCH 6/6] Remove generic in Styleguide-Layout-Tabs --- .../src/components/styleguide/Styleguide-Layout-Tabs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Layout-Tabs.tsx b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Layout-Tabs.tsx index 01f84b72c3..47a7b96e83 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Layout-Tabs.tsx +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-Layout-Tabs.tsx @@ -104,7 +104,7 @@ const tabsComponentWithPlaceholderInjected = withPlaceholder({ // We need to know if experience editor is active, to disable the dynamic tab behavior for editing. // Using the same technique as injecting the placeholder, we wrap the component again to inject the // `sitecoreContext` prop. -const tabsWithPlaceholderAndSitecoreContext = withSitecoreContext()( +const tabsWithPlaceholderAndSitecoreContext = withSitecoreContext()( tabsComponentWithPlaceholderInjected );