From 96951a85bcdb5c37290915dc040be79d38e443ec Mon Sep 17 00:00:00 2001 From: Charley Campbell <115992455+charleycampbell@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:22:03 +0100 Subject: [PATCH] Revert "Revert "Ticker Update"" --- dotcom-rendering/package.json | 2 +- .../designableBanner/DesignableBanner.tsx | 15 +- .../components/DesignableBannerTicker.tsx | 198 ----------------- .../banners/designableBanner/settings.ts | 10 +- .../stories/DesignableBanner.stories.tsx | 16 +- .../marketing/banners/utils/storybook.ts | 6 +- .../epics/ContributionsEpic.stories.tsx | 40 +++- .../marketing/epics/ContributionsEpic.tsx | 20 +- .../epics/ContributionsEpicTicker.tsx | 201 ------------------ .../components/marketing/hooks/useTicker.ts | 29 --- dotcom-rendering/src/lib/useIsInView.ts | 11 + pnpm-lock.yaml | 8 +- 12 files changed, 89 insertions(+), 467 deletions(-) delete mode 100644 dotcom-rendering/src/components/marketing/epics/ContributionsEpicTicker.tsx delete mode 100644 dotcom-rendering/src/components/marketing/hooks/useTicker.ts diff --git a/dotcom-rendering/package.json b/dotcom-rendering/package.json index 5a4f34b3854..66b07752f7d 100644 --- a/dotcom-rendering/package.json +++ b/dotcom-rendering/package.json @@ -51,7 +51,7 @@ "@guardian/ophan-tracker-js": "2.2.5", "@guardian/shimport": "1.0.2", "@guardian/source": "8.0.0", - "@guardian/source-development-kitchen": "8.0.0", + "@guardian/source-development-kitchen": "9.0.0", "@guardian/support-dotcom-components": "2.9.1", "@guardian/tsconfig": "0.2.0", "@playwright/test": "1.45.3", diff --git a/dotcom-rendering/src/components/marketing/banners/designableBanner/DesignableBanner.tsx b/dotcom-rendering/src/components/marketing/banners/designableBanner/DesignableBanner.tsx index 95592cc063e..b39400d8e8e 100644 --- a/dotcom-rendering/src/components/marketing/banners/designableBanner/DesignableBanner.tsx +++ b/dotcom-rendering/src/components/marketing/banners/designableBanner/DesignableBanner.tsx @@ -16,6 +16,7 @@ import { until, } from '@guardian/source/foundations'; import { Button, SvgGuardianLogo } from '@guardian/source/react-components'; +import { Ticker } from '@guardian/source-development-kitchen/react-components'; import { hexColourToString, SecondaryCtaType, @@ -47,7 +48,6 @@ import { DesignableBannerCloseButton } from './components/DesignableBannerCloseB import { DesignableBannerCtas } from './components/DesignableBannerCtas'; import { DesignableBannerHeader } from './components/DesignableBannerHeader'; import { DesignableBannerReminder } from './components/DesignableBannerReminder'; -import { DesignableBannerTicker } from './components/DesignableBannerTicker'; import { DesignableBannerVisual } from './components/DesignableBannerVisual'; import type { BannerTemplateSettings, CtaSettings } from './settings'; import { buttonStyles } from './styles/buttonStyles'; @@ -265,12 +265,13 @@ const DesignableBanner: ReactComponent = ({ imageSettings, bannerId: 'designable-banner', tickerStylingSettings: { - textColour: hexColourToString(ticker.text), filledProgressColour: hexColourToString(ticker.filledProgress), progressBarBackgroundColour: hexColourToString( ticker.progressBarBackground, ), - goalMarkerColour: hexColourToString(ticker.goalMarker), + headlineColour: hexColourToString(ticker.headlineColour), + totalColour: hexColourToString(ticker.totalColour), + goalColour: hexColourToString(ticker.goalColour), }, }; @@ -342,9 +343,11 @@ const DesignableBanner: ReactComponent = ({ {tickerSettings?.tickerData && templateSettings.tickerStylingSettings && ( - diff --git a/dotcom-rendering/src/components/marketing/banners/designableBanner/components/DesignableBannerTicker.tsx b/dotcom-rendering/src/components/marketing/banners/designableBanner/components/DesignableBannerTicker.tsx index 0bab9248ff7..e69de29bb2d 100644 --- a/dotcom-rendering/src/components/marketing/banners/designableBanner/components/DesignableBannerTicker.tsx +++ b/dotcom-rendering/src/components/marketing/banners/designableBanner/components/DesignableBannerTicker.tsx @@ -1,198 +0,0 @@ -/** - * @file - * This file was migrated from: - * https://github.com/guardian/support-dotcom-components/blob/0a2439b701586a7a2cc60dce10b4d96cf7a828db/packages/modules/src/modules/banners/designableBanner/components/DesignableBannerTicker.tsx - */ -import type { SerializedStyles } from '@emotion/react'; -import { css } from '@emotion/react'; -import { from, space, textSansBold15 } from '@guardian/source/foundations'; -import { TickerCountType } from '@guardian/support-dotcom-components'; -import type { TickerSettings } from '@guardian/support-dotcom-components/dist/shared/src/types'; -import { useEffect, useState } from 'react'; -import { useIsInView } from '../../../../../lib/useIsInView'; -import { useTicker } from '../../../hooks/useTicker'; -import type { ReactComponent } from '../../../lib/ReactComponent'; -import type { TickerStylingSettings } from '../settings'; -import { templateSpacing } from '../styles/templateStyles'; - -const progressBarHeight = 12; -const tickerFillOffset = 15; -const overFilledTickerOffset = 10; - -const styles = { - containerStyles: css` - position: relative; - ${templateSpacing.bannerTicker} - `, - tickerLabelsContainer: css` - display: flex; - justify-content: space-between; - align-items: end; - margin-bottom: ${space[1]}px; - `, - countLabelStyles: (colour: string) => css` - ${textSansBold15}; - font-size: 13px; - color: ${colour}; - line-height: 1.3; - - ${from.desktop} { - font-size: 17px; - } - `, - progressBarContainerStyles: css` - position: relative; - `, - progressBarStyles: (backgroundColour: string) => css` - position: relative; - overflow: hidden; - width: 100%; - height: ${progressBarHeight}px; - background: ${backgroundColour}; - `, - progressBarTransform: ( - end: number, - runningTotal: number, - total: number, - ): string => { - const haveStartedAnimating = runningTotal > 0; - - if (!haveStartedAnimating) { - return 'translateX(-100%)'; - } - - const percentage = (total / end) * 100 - 100; - - return `translate3d(${percentage >= 0 ? 0 : percentage}%, 0, 0)`; - }, - filledProgressStyles: ( - end: number, - runningTotal: number, - total: number, - colour: string, - isGoalReached: boolean, - ): SerializedStyles => css` - height: ${progressBarHeight}px; - width: calc( - 100% - ${isGoalReached ? overFilledTickerOffset : tickerFillOffset}% - ); - transform: ${styles.progressBarTransform(end, runningTotal, total)}; - transition: transform 3s cubic-bezier(0.25, 0.55, 0.2, 0.85); - background-color: ${colour}; - `, - soFarContainerStyles: css` - padding-right: ${space[5]}px; - `, - goalContainerStyles: css` - text-align: end; - margin-right: ${tickerFillOffset}%; - transform: translateX(50%); - `, - goalMarkerStyles: (colour: string): SerializedStyles => css` - border-right: 2px solid ${colour}; - height: calc(100% + 6px); - position: absolute; - top: -3px; - right: ${tickerFillOffset}%; - `, -}; - -type DesignableBannerTickerProps = { - tickerSettings: TickerSettings; - stylingSettings: TickerStylingSettings; -}; - -const DesignableBannerTicker: ReactComponent = ({ - tickerSettings, - stylingSettings, -}: DesignableBannerTickerProps) => { - const [readyToAnimate, setReadyToAnimate] = useState(false); - - const [hasBeenSeen, setNode] = useIsInView({ - debounce: true, - threshold: 0, - }); - - useEffect(() => { - if (hasBeenSeen) { - setTimeout(() => setReadyToAnimate(true), 500); - } - }, [hasBeenSeen]); - - const total = tickerSettings.tickerData?.total ?? 1; - const goal = tickerSettings.tickerData?.goal ?? 1; - const isGoalReached = total >= goal; - const runningTotal = useTicker(total, readyToAnimate); - - const currencySymbol = - tickerSettings.countType === TickerCountType.money - ? tickerSettings.currencySymbol - : ''; - - return ( -
-
-
-
- {!isGoalReached && currencySymbol} - {isGoalReached - ? tickerSettings.copy.goalReachedPrimary - : runningTotal.toLocaleString()}{' '} - - {isGoalReached - ? tickerSettings.copy.goalReachedSecondary - : tickerSettings.copy.countLabel} - -
-
- -
-
- {currencySymbol} - {isGoalReached - ? runningTotal.toLocaleString() - : goal.toLocaleString()}{' '} - - {isGoalReached - ? tickerSettings.copy.countLabel - : 'goal'} - -
-
-
- -
-
-
-
-
-
-
- ); -}; - -export { DesignableBannerTicker }; diff --git a/dotcom-rendering/src/components/marketing/banners/designableBanner/settings.ts b/dotcom-rendering/src/components/marketing/banners/designableBanner/settings.ts index f1b87a42634..851809c0a26 100644 --- a/dotcom-rendering/src/components/marketing/banners/designableBanner/settings.ts +++ b/dotcom-rendering/src/components/marketing/banners/designableBanner/settings.ts @@ -3,6 +3,7 @@ * This file was migrated from: * https://github.com/guardian/support-dotcom-components/blob/0a2439b701586a7a2cc60dce10b4d96cf7a828db/packages/modules/src/modules/banners/designableBanner/settings.ts */ +import type { TickerSettings } from '@guardian/source-development-kitchen/react-components'; import type { Image } from '@guardian/support-dotcom-components/dist/shared/src/types'; import type { ReactNode } from 'react'; import type { BannerId } from '../common/types'; @@ -32,13 +33,6 @@ export interface HighlightedTextSettings { highlightColour?: string; } -export interface TickerStylingSettings { - textColour: string; - filledProgressColour: string; - progressBarBackgroundColour: string; - goalMarkerColour: string; -} - export interface HeaderSettings { textColour?: string; headerImage?: Image; @@ -56,6 +50,6 @@ export interface BannerTemplateSettings { alternativeVisual?: ReactNode; choiceCardSettings?: ChoiceCardSettings; bannerId?: BannerId; - tickerStylingSettings?: TickerStylingSettings; + tickerStylingSettings?: TickerSettings['tickerStylingSettings']; headerSettings?: HeaderSettings; } diff --git a/dotcom-rendering/src/components/marketing/banners/designableBanner/stories/DesignableBanner.stories.tsx b/dotcom-rendering/src/components/marketing/banners/designableBanner/stories/DesignableBanner.stories.tsx index 80a64ee0e53..e21efc79487 100644 --- a/dotcom-rendering/src/components/marketing/banners/designableBanner/stories/DesignableBanner.stories.tsx +++ b/dotcom-rendering/src/components/marketing/banners/designableBanner/stories/DesignableBanner.stories.tsx @@ -11,8 +11,8 @@ import { import type { BannerDesignImage, SelectedAmountsVariant, + TickerSettings, } from '@guardian/support-dotcom-components/dist/shared/src/types'; -import type { TickerSettings } from '@guardian/support-dotcom-components/dist/shared/src/types'; import type { Meta, StoryObj } from '@storybook/react'; import lzstring from 'lz-string'; import { DesignableBannerUnvalidated as DesignableBanner } from '../../../banners/designableBanner/DesignableBanner'; @@ -55,19 +55,19 @@ export const Default: Story = { }; const tickerSettings: TickerSettings = { + endType: TickerEndType.unlimited, countType: TickerCountType.money, - endType: TickerEndType.hardstop, - currencySymbol: '', + currencySymbol: '£', copy: { - countLabel: 'contributions in May', - goalReachedPrimary: "We've met our goal - thank you!", + countLabel: 'Help us reach our end-of-year goal', + goalReachedPrimary: '', goalReachedSecondary: '', }, tickerData: { - total: 4_000, - goal: 50_000, + total: 500000, + goal: 1000000, }, - name: 'AU', + name: 'US', }; const regularChoiceCardAmounts: SelectedAmountsVariant = { diff --git a/dotcom-rendering/src/components/marketing/banners/utils/storybook.ts b/dotcom-rendering/src/components/marketing/banners/utils/storybook.ts index dcc704f916a..a933aaeb697 100644 --- a/dotcom-rendering/src/components/marketing/banners/utils/storybook.ts +++ b/dotcom-rendering/src/components/marketing/banners/utils/storybook.ts @@ -137,9 +137,9 @@ export const design: ConfigurableDesign = { filledProgress: stringToHexColour('052962'), progressBarBackground: stringToHexColour('cccccc'), goalMarker: stringToHexColour('000000'), - goalColour: stringToHexColour('000000'), - headlineColour: stringToHexColour('000000'), - totalColour: stringToHexColour('000000'), + headlineColour: stringToHexColour('052962'), + totalColour: stringToHexColour('052962'), + goalColour: stringToHexColour('052962'), }, }, }; diff --git a/dotcom-rendering/src/components/marketing/epics/ContributionsEpic.stories.tsx b/dotcom-rendering/src/components/marketing/epics/ContributionsEpic.stories.tsx index b96e2540e2a..058fe3d66bc 100644 --- a/dotcom-rendering/src/components/marketing/epics/ContributionsEpic.stories.tsx +++ b/dotcom-rendering/src/components/marketing/epics/ContributionsEpic.stories.tsx @@ -198,14 +198,41 @@ export const WithTicker: Story = { variant: { ...props.variant, tickerSettings: { + endType: TickerEndType.unlimited, countType: TickerCountType.money, + currencySymbol: '£', + copy: { + countLabel: 'Help us reach our end-of-year goal', + goalReachedPrimary: '', + goalReachedSecondary: '', + }, + tickerData: { + total: 10000, + goal: 100000, + }, + name: 'US', + }, + }, + }, +}; + +export const WithTickerAndWithAboveTopReaderArticleCount: Story = { + name: 'ContributionsEpic with ticker and top reader article count', + args: { + ...meta.args, + variant: { + ...props.variant, + separateArticleCount: { + type: 'above', + }, + tickerSettings: { endType: TickerEndType.unlimited, + countType: TickerCountType.money, currencySymbol: '£', copy: { - countLabel: 'contributed', - goalReachedPrimary: "We've met our goal - thank you", - goalReachedSecondary: - 'Contributions are still being accepted', + countLabel: 'Help us reach our end-of-year goal', + goalReachedPrimary: '', + goalReachedSecondary: '', }, tickerData: { total: 10000, @@ -214,6 +241,11 @@ export const WithTicker: Story = { name: 'US', }, }, + articleCounts: { + for52Weeks: 99, + forTargetedWeeks: 99, + }, + hasConsentForArticleCount: true, }, }; diff --git a/dotcom-rendering/src/components/marketing/epics/ContributionsEpic.tsx b/dotcom-rendering/src/components/marketing/epics/ContributionsEpic.tsx index 69550f96879..7b9d25a3085 100644 --- a/dotcom-rendering/src/components/marketing/epics/ContributionsEpic.tsx +++ b/dotcom-rendering/src/components/marketing/epics/ContributionsEpic.tsx @@ -12,6 +12,8 @@ import { palette, space, } from '@guardian/source/foundations'; +import { Ticker } from '@guardian/source-development-kitchen/react-components'; +import type { TickerSettings } from '@guardian/source-development-kitchen/react-components'; import { containsNonArticleCountPlaceholder, epicPropsSchema, @@ -39,7 +41,6 @@ import { BylineWithHeadshot } from './BylineWithHeadshot'; import { ContributionsEpicArticleCountAboveWithOptOut } from './ContributionsEpicArticleCountAboveWithOptOut'; import { ContributionsEpicNewsletterSignup } from './ContributionsEpicNewsletterSignup'; import { ContributionsEpicSignInCta } from './ContributionsEpicSignInCta'; -import { ContributionsEpicTicker } from './ContributionsEpicTicker'; import { ContributionsEpicCtasContainer } from './ctas/ContributionsEpicCtasContainer'; // CSS Styling @@ -109,6 +110,14 @@ const imageStyles = css` object-fit: cover; `; +const defaultTickerStylingSettings: TickerSettings['tickerStylingSettings'] = { + filledProgressColour: '#5056F5', + progressBarBackgroundColour: 'rgba(80, 86, 245, 0.35)', + headlineColour: '#000000', + totalColour: '#5056F5', + goalColour: '#000000', +}; + const articleCountAboveContainerStyles = css` margin-bottom: ${space[4]}px; `; @@ -393,10 +402,11 @@ const ContributionsEpic: ReactComponent = ({ )} {tickerSettings?.tickerData && ( - )} diff --git a/dotcom-rendering/src/components/marketing/epics/ContributionsEpicTicker.tsx b/dotcom-rendering/src/components/marketing/epics/ContributionsEpicTicker.tsx deleted file mode 100644 index a6f55ca6a06..00000000000 --- a/dotcom-rendering/src/components/marketing/epics/ContributionsEpicTicker.tsx +++ /dev/null @@ -1,201 +0,0 @@ -/** - * @file - * This file was migrated from: - * https://github.com/guardian/support-dotcom-components/blob/a482b35a25ca59f66501c4de02de817046206298/packages/modules/src/modules/epics/ContributionsEpicTicker.tsx - */ -import type { SerializedStyles } from '@emotion/react'; -import { css } from '@emotion/react'; -import { - palette, - textSans17, - textSansBold17, -} from '@guardian/source/foundations'; -import type { TickerSettings } from '@guardian/support-dotcom-components/dist/shared/src/types'; -import { useEffect, useState } from 'react'; -import { useIsInView } from '../../../lib/useIsInView'; -import { useTicker } from '../hooks/useTicker'; -import type { ReactComponent } from '../lib/ReactComponent'; - -// This ticker component provides an animated progress bar and counter for the -// epic. It mirrors the behaviour of the "unlimited" ticker type from frontend. -// The "hardstop" type is not supported. The differences between the two relate -// to behaviour once the goal has been reached. - -const rootStyles = css` - position: relative; - height: 65px; - margin-bottom: 15px; - line-height: 18px; -`; - -const totalCountStyles = css` - ${textSansBold17} -`; - -const soFarCountStyles = css` - ${textSansBold17} -`; - -const countLabelStyles = css` - ${textSans17} -`; - -const progressBarHeight = 10; - -const progressBarContainerStyles = css` - width: 100%; - height: ${progressBarHeight}px; - /* stylelint-disable-next-line color-no-hex */ - background-color: #dda7a1; - position: absolute; - bottom: 0; - margin-top: 40px; -`; - -const progressBarStyles = css` - overflow: hidden; - width: 100%; - height: ${progressBarHeight}px; - position: absolute; -`; - -const soFarContainerStyles = css` - position: absolute; - left: 0; - bottom: ${progressBarHeight + 5}px; -`; - -const progressBarTransform = ( - end: number, - runningTotal: number, - total: number, -): string => { - const haveStartedAnimating = runningTotal > 0; - - if (!haveStartedAnimating) { - return 'translateX(-100%)'; - } - - const percentage = (total / end) * 100 - 100; - - return `translate3d(${percentage >= 0 ? 0 : percentage}%, 0, 0)`; -}; - -const filledProgressStyles = ( - end: number, - runningTotal: number, - total: number, -): SerializedStyles => css` - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - transform: ${progressBarTransform(end, runningTotal, total)}; - transition: transform 3s cubic-bezier(0.25, 0.55, 0.2, 0.85); - background-color: ${palette.news[400]}; -`; - -const goalContainerStyles: SerializedStyles = css` - position: absolute; - right: 0; - bottom: ${progressBarHeight + 5}px; - text-align: right; -`; - -const goalMarkerStyles = (transform: string): SerializedStyles => css` - border-right: 2px solid ${palette.neutral[7]}; - content: ' '; - display: block; - height: 12px; - margin-top: -2px; - transform: ${transform}; -`; - -type MarkerProps = { - goal: number; - end: number; -}; - -const Marker: ReactComponent = ({ goal, end }: MarkerProps) => { - if (end > goal) { - const markerTranslate = (goal / end) * 100 - 100; - const markerTransform = `translate3d(${markerTranslate}%, 0, 0)`; - - return
; - } else { - return <>; - } -}; - -export type Props = { - settings: TickerSettings; - total: number; - goal: number; -}; - -export const ContributionsEpicTicker: ReactComponent = ({ - settings, - total, - goal, -}: Props) => { - const [readyToAnimate, setReadyToAnimate] = useState(false); - const [hasBeenSeen, setNode] = useIsInView({ - debounce: true, - rootMargin: '-18px', - threshold: 0, - }); - - useEffect(() => { - if (hasBeenSeen) { - setTimeout(() => setReadyToAnimate(true), 500); - } - }, [hasBeenSeen]); - - const runningTotal = useTicker(total, readyToAnimate); - - const goalReached = total >= goal; - const currencySymbol = settings.currencySymbol; - - // If we've exceeded the goal then extend the bar 15% beyond the total - const end = total > goal ? total + total * 0.15 : goal; - - return ( -
-
-
-
- {goalReached - ? settings.copy.goalReachedPrimary - : `${currencySymbol}${runningTotal.toLocaleString()}`} -
-
- {goalReached - ? settings.copy.goalReachedSecondary - : settings.copy.countLabel} -
-
- -
-
- {goalReached - ? `${currencySymbol}${total.toLocaleString()}` - : `${currencySymbol}${goal.toLocaleString()}`} -
-
- {goalReached ? settings.copy.countLabel : 'our goal'} -
-
-
- -
-
-
-
- -
-
- ); -}; diff --git a/dotcom-rendering/src/components/marketing/hooks/useTicker.ts b/dotcom-rendering/src/components/marketing/hooks/useTicker.ts deleted file mode 100644 index 0cf68eaff3c..00000000000 --- a/dotcom-rendering/src/components/marketing/hooks/useTicker.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file - * This file was migrated from: - * https://github.com/guardian/support-dotcom-components/blob/a482b35a25ca59f66501c4de02de817046206298/packages/modules/src/hooks/useTicker.ts - */ -import { useEffect, useState } from 'react'; - -export const useTicker = (total: number, readyToAnimate: boolean): number => { - const [runningTotal, setRunningTotal] = useState(0); - - useEffect(() => { - if (readyToAnimate && runningTotal < total) { - window.requestAnimationFrame(() => { - setRunningTotal((prevRunningTotal) => { - const newRunningTotal = - prevRunningTotal + Math.floor(total / 100); - - if (newRunningTotal > total) { - return total; - } - - return newRunningTotal; - }); - }); - } - }, [readyToAnimate, runningTotal, total]); - - return runningTotal; -}; diff --git a/dotcom-rendering/src/lib/useIsInView.ts b/dotcom-rendering/src/lib/useIsInView.ts index e122cf583ef..128347a390c 100644 --- a/dotcom-rendering/src/lib/useIsInView.ts +++ b/dotcom-rendering/src/lib/useIsInView.ts @@ -1,6 +1,17 @@ import libDebounce from 'lodash.debounce'; import { useCallback, useEffect, useRef, useState } from 'react'; +/** + * This file was copied into the source development kitchen from the following repository: + * https://github.com/guardian/csnx/blob/main/libs/%40guardian/source-development-kitchen/src/react-components/ticker/useIsInView.ts + * + * Note: This version of the file uses `lodash.debounce`, whereas the original version does not. + * As a result, we now have two versions of the `useIsInView` hook—one with `lodash.debounce` and one without. + * + * A discussion is needed to determine the best approach for consolidating these two versions into a single file. + * Consider whether the use of `lodash.debounce` is necessary, and if so, integrate it into the consolidated version. + */ + type Options = { /** * Defaults to `undefined` (falsy), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce1a891649f..3bacce86d5c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -371,8 +371,8 @@ importers: specifier: 8.0.0 version: 8.0.0(@emotion/react@11.11.3)(@types/react@18.3.1)(react@18.3.1)(tslib@2.6.2)(typescript@5.5.3) '@guardian/source-development-kitchen': - specifier: 8.0.0 - version: 8.0.0(@emotion/react@11.11.3)(@guardian/libs@18.0.0)(@guardian/source@8.0.0)(@types/react@18.3.1)(react@18.3.1)(tslib@2.6.2)(typescript@5.5.3) + specifier: 9.0.0 + version: 9.0.0(@emotion/react@11.11.3)(@guardian/libs@18.0.0)(@guardian/source@8.0.0)(@types/react@18.3.1)(react@18.3.1)(tslib@2.6.2)(typescript@5.5.3) '@guardian/support-dotcom-components': specifier: 2.9.1 version: 2.9.1(@guardian/libs@18.0.0)(zod@3.22.4) @@ -4603,8 +4603,8 @@ packages: typescript: 5.5.3 dev: false - /@guardian/source-development-kitchen@8.0.0(@emotion/react@11.11.3)(@guardian/libs@18.0.0)(@guardian/source@8.0.0)(@types/react@18.3.1)(react@18.3.1)(tslib@2.6.2)(typescript@5.5.3): - resolution: {integrity: sha512-97Qcm9laquXen7GMOkQ2syvKlvY6VaAN3zalXnxEDHZiSgUhthWrVFJp2G5CsqP9c5lpl4RkUcF2PkYek8J2Jw==} + /@guardian/source-development-kitchen@9.0.0(@emotion/react@11.11.3)(@guardian/libs@18.0.0)(@guardian/source@8.0.0)(@types/react@18.3.1)(react@18.3.1)(tslib@2.6.2)(typescript@5.5.3): + resolution: {integrity: sha512-7384llH2Q8eyWBd48ITY6TTis5YhhaOeEW6y7ziPNwlRmI1wP99hlxidXv9FxReiPcdTkQ2U+c0l5k2qdiRg1g==} peerDependencies: '@emotion/react': ^11.11.3 '@guardian/libs': ^18.0.0