Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ export default [
'@eslint-react/prop-types': 'off',
'@eslint-react/require-default-props': 'off',
'@eslint-react/react-in-jsx-scope': 'off',
// `use()` is intended for conditional context access; for unconditional
// reads `useContext()` remains the simpler, preferred approach here.
'@eslint-react/no-use-context': 'off',
// Extra
'@eslint-react/jsx-no-useless-fragment': 'warn',
'@eslint-react/no-array-index-key': 'error',
Expand Down
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@city-of-helsinki/react-helsinki-headless-cms",
"engines": {
"node": ">=22.11.0"
"node": "^24"
},
"packageManager": "pnpm@11.1.2",
"version": "3.0.3",
Expand Down Expand Up @@ -53,9 +53,9 @@
"homepage": "https://github.com/City-of-Helsinki/react-helsinki-headless-cms#readme",
"peerDependencies": {
"@apollo/client": "^3.14.0",
"hds-react": ">=4.8.1",
"react": "^18",
"react-dom": "^18"
"hds-react": "^6.0.2",
"react": "^19",
"react-dom": "^19"
},
"peerDependenciesMeta": {
"@apollo/client": {
Expand Down Expand Up @@ -96,8 +96,8 @@
"@testing-library/user-event": "^14.6.1",
"@types/lodash-es": "^4.17.12",
"@types/node": "^24.12.4",
"@types/react": "^18.3.27",
"@types/react-dom": "18.3.7",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.1",
"@vitest/coverage-v8": "^4.1.4",
"babel-loader": "^9.2.1",
Expand All @@ -115,8 +115,8 @@
"git-rev-sync": "^3.0.2",
"globals": "^17.4.0",
"graphql": "^16.12.0",
"hds-core": "^4.8.1",
"hds-react": "4.8.1",
"hds-core": "^6.0.2",
"hds-react": "6.0.2",
Comment thread
Riippi marked this conversation as resolved.
"husky": "^9.1.7",
"jsdom": "^29.0.2",
"lint-staged": "^16.2.7",
Expand All @@ -125,9 +125,9 @@
"postcss": "^8.5.6",
"postcss-scss": "^4.0.9",
"prettier": "3.7.4",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-helmet-async": "^2.0.5",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-helmet-async": "^3.0.0",
"rollup": "^4.59.0",
"rollup-plugin-copy": "^3.5.0",
"rollup-plugin-delete": "^3.0.2",
Expand All @@ -151,7 +151,7 @@
"classnames": "^2.5.1",
"date-fns": "^4.1.0",
"doctoc": "^2.3.0",
"hds-design-tokens": "^4.8.1",
"hds-design-tokens": "^6.0.2",
"html-entities": "^2.6.0",
"html-react-parser": "^5.2.5",
"isomorphic-dompurify": "^2.36.0",
Expand Down
549 changes: 226 additions & 323 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/apollo/pageContent/PageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type PageProps = Omit<PageContentPropsWithoutData, 'page'> & {
/**
* Page content if data not found or missing from cms.
*/
notFoundPageContent?: JSX.Element;
notFoundPageContent?: React.JSX.Element;
// All other props
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[x: string]: any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export type PageProps = Omit<PageContentPropsWithoutData, 'page'> & {
/**
* Page content if data not found or missing from cms.
*/
notFoundPageContent?: JSX.Element;
notFoundPageContent?: React.JSX.Element;
// All other props
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[x: string]: any;
Expand Down
4 changes: 2 additions & 2 deletions src/common/components/container/Container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ type ContainerProps = {
/**
* Additional children to render inside the container.
*/
children: JSX.Element | string;
children: React.JSX.Element | string;
/**
* Optional wrapper element for the container.
*/
wrapper?: JSX.Element;
wrapper?: React.JSX.Element;
};

export default function Container({ wrapper, children }: ContainerProps) {
Expand Down
4 changes: 2 additions & 2 deletions src/common/components/list/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import classNames from 'classnames';

import styles from './list.module.scss';

function getKey(...elements: JSX.Element[]): string {
function getKey(...elements: React.JSX.Element[]): string {
return elements.reduce((acc, element) => `${acc}${element.key}`, '');
}

type ListProps = {
/**
* List item elements.
*/
items?: (JSX.Element | JSX.Element[] | null | false)[];
items?: (React.JSX.Element | React.JSX.Element[] | null | false)[];
/**
* List item variant options.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export interface SearchPageContentProps {
/**
* Custom content react components to be dispayed on the page.
*/
customContent?: string | JSX.Element;
customContent?: string | React.JSX.Element;
/**
* Archive collection items..
*/
Expand Down
6 changes: 3 additions & 3 deletions src/core/carousel/components/CarouselSliderPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ export function CarouselSliderPage({
const styleWidth = `${100 / itemsPerSlide}%`;
return (
<li
ref={(node) =>
node && node.toggleAttribute('inert', itemSetIndex !== currentSlide)
}
ref={(node) => {
node?.toggleAttribute('inert', itemSetIndex !== currentSlide);
}}
aria-hidden={itemSetIndex !== currentSlide}
className={classNames(
styles.slide,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('CarouselSlideButton', () => {
providerProps: Partial<CarouselContextType>,
) =>
render(
<CarouselContext.Provider
<CarouselContext
value={{
...initialCarouselContextStateValues,
// Dummy functions for context fields that require them
Expand All @@ -50,7 +50,7 @@ describe('CarouselSlideButton', () => {
}}
>
{ui}
</CarouselContext.Provider>,
</CarouselContext>,
);

beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const renderWithContext = (
providerProps: Partial<CarouselContextType>,
) =>
render(
<CarouselContext.Provider
<CarouselContext
value={{
...initialCarouselContextStateValues,
// Dummy functions for context fields that require them
Expand All @@ -37,7 +37,7 @@ const renderWithContext = (
}}
>
{ui}
</CarouselContext.Provider>,
</CarouselContext>,
);

describe('CarouselSlider', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const renderWithContext = (
providerProps: Partial<CarouselContextType>,
) =>
render(
<CarouselContext.Provider
<CarouselContext
value={{
...initialCarouselContextStateValues,
// Dummy functions for context fields that require them
Expand All @@ -36,7 +36,7 @@ const renderWithContext = (
}}
>
{ui}
</CarouselContext.Provider>,
</CarouselContext>,
);

describe('CarouselSlideDots', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const renderWithContext = (
providerProps: Partial<CarouselContextType>,
) =>
render(
<CarouselContext.Provider
<CarouselContext
value={{
...initialCarouselContextStateValues,
// Dummy functions for context fields that require them
Expand All @@ -29,7 +29,7 @@ const renderWithContext = (
}}
>
{ui}
</CarouselContext.Provider>,
</CarouselContext>,
);

describe('CarouselSliderPage', () => {
Expand Down
6 changes: 1 addition & 5 deletions src/core/carousel/context/CarouselContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,5 @@ export function CarouselContextProvider({
}),
[numberOfItems, carouselContext, backwardCompatibleProps],
);
return (
<CarouselContext.Provider value={value}>
{children}
</CarouselContext.Provider>
);
return <CarouselContext value={value}>{children}</CarouselContext>;
}
2 changes: 1 addition & 1 deletion src/core/collection/Collection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export function Collection({
const {
copy: { loadMoreButtonLabelText, showAllText },
} = useConfig();
const componentForType: Record<CollectionProps['type'], JSX.Element> = {
const componentForType: Record<CollectionProps['type'], React.JSX.Element> = {
carousel: (
<CollectionCarousel
cards={cards}
Expand Down
4 changes: 1 addition & 3 deletions src/core/configProvider/ConfigProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,5 @@ export function ConfigProvider({
[userConfig],
);

return (
<ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>
);
return <ConfigContext value={config}>{children}</ConfigContext>;
}
12 changes: 8 additions & 4 deletions src/core/configProvider/configContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,16 @@ export type Config = {
* React component replacements for defined html elements.
*/
components: {
A: (props: React.AnchorHTMLAttributes<HTMLAnchorElement>) => JSX.Element;
Img: (props: React.ImgHTMLAttributes<HTMLImageElement>) => JSX.Element;
A: (
props: React.AnchorHTMLAttributes<HTMLAnchorElement>,
) => React.JSX.Element;
Img: (
props: React.ImgHTMLAttributes<HTMLImageElement>,
) => React.JSX.Element;
Link?: (
props: React.AnchorHTMLAttributes<HTMLAnchorElement>,
) => JSX.Element;
Head?: (props: { children: React.ReactNode }) => JSX.Element;
) => React.JSX.Element;
Head?: (props: { children: React.ReactNode }) => React.JSX.Element;
EventCardContent?: React.FC<Record<string, unknown>>;
VenueCardContent?: React.FC<Record<string, unknown>>;
ArticleCardContent?: React.FC<Record<string, unknown>>;
Expand Down
2 changes: 1 addition & 1 deletion src/core/hero/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export type HeroComponentProps = {
/**
* Hero container wrapper component.
*/
container?: JSX.Element;
container?: React.JSX.Element;
} & HeroProps;

export default function Hero({
Expand Down
6 changes: 1 addition & 5 deletions src/core/imageGallery/ImageGalleryProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,5 @@ export function ImageGalleryProvider({ children }: ImageGalleryProviderProps) {
[imageIndex, isLightboxVisible, selectedImageIndex, toggleLightbox],
);

return (
<ImageGalleryContext.Provider value={config}>
{children}
</ImageGalleryContext.Provider>
);
return <ImageGalleryContext value={config}>{children}</ImageGalleryContext>;
}
4 changes: 2 additions & 2 deletions src/core/imageGallery/Lightbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface ActionsProps {
export function Lightbox({
images,
lightboxUid,
}: LightboxProps): JSX.Element | null {
}: LightboxProps): React.JSX.Element | null {
const lightboxRef = useRef<HTMLDivElement | null>(null);
const barrierRef = useRef<HTMLHeadingElement | null>(null);

Expand Down Expand Up @@ -97,7 +97,7 @@ export function Lightbox({
const imagePhotogrpher = images[imageIndex].photographer;
const imageUrl = images[imageIndex].url;

const renderLightboxComponent = (): JSX.Element => (
const renderLightboxComponent = (): React.JSX.Element => (
<div
id={lightboxUid}
role="dialog"
Expand Down
47 changes: 24 additions & 23 deletions src/core/link/LinkBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import styles from './LinkBase.module.scss';
// issue is created to hds: https://github.com/City-of-Helsinki/helsinki-design-system/issues/808

export type LinkProps = Omit<
React.ComponentPropsWithoutRef<'a'>,
React.ComponentPropsWithRef<'a'>,
'target' | 'href' | 'onPointerEnterCapture' | 'onPointerLeaveCapture'
> & {
Comment thread
Riippi marked this conversation as resolved.
/**
Expand Down Expand Up @@ -118,26 +118,24 @@ export const getTextFromReactChildren = (children: ReactNode): string => {
) as string;
};

function LinkBase(
{
children,
className,
disableVisitedStyles = true,
external = false,
showExternalIcon = true,
href,
iconLeft,
iconRight,
openInNewTab = false,
openInExternalDomainAriaLabel,
openInNewTabAriaLabel,
style = {},
size = 'M',
inlineIcons = false,
...rest
}: LinkProps,
ref: React.Ref<HTMLAnchorElement>,
) {
function LinkBase({
children,
className,
disableVisitedStyles = true,
external = false,
showExternalIcon = true,
href,
iconLeft,
iconRight,
openInNewTab = false,
openInExternalDomainAriaLabel,
openInNewTabAriaLabel,
style = {},
size = 'M',
inlineIcons = false,
ref,
...rest
}: LinkProps) {
Comment thread
Riippi marked this conversation as resolved.
const composeAriaLabel = () => {
let childrenText = getTextFromReactChildren(children);
const newTabText = openInNewTab
Expand Down Expand Up @@ -237,7 +235,10 @@ function LinkBase(
>
{!inlineIcons && leftIcon}
<span
className={classNames(styles.content, iconLeft && styles.withLeftIcon)}
className={classNames(
styles.content,
!!iconLeft && styles.withLeftIcon,
)}
>
{inlineIcons && leftIcon}
{children}
Expand All @@ -250,4 +251,4 @@ function LinkBase(
);
}

export default React.forwardRef<HTMLAnchorElement, LinkProps>(LinkBase);
export default LinkBase;
Comment thread
Riippi marked this conversation as resolved.
2 changes: 1 addition & 1 deletion src/core/pageContent/PageContentLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { HeroProps } from './types';
export type PageContentLayoutProps = {
id: string;
breadcrumbs?: React.ReactNode;
heroContainer?: JSX.Element;
heroContainer?: React.JSX.Element;
content: React.ReactNode;
shareLinks?: React.ReactNode;
collections?: React.ReactNode;
Expand Down
Loading
Loading