diff --git a/package-lock.json b/package-lock.json index bb45b294d..243e3e53c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,7 +68,7 @@ "stylelint-config-standard-scss": "3.0.0", "ts-jest": "27.1.3", "ts-node": "10.7.0", - "typescript": "4.5.5" + "typescript": "5.9.3" } }, "node_modules/@ardatan/relay-compiler": { @@ -2366,6 +2366,20 @@ "node": ">=v12" } }, + "node_modules/@commitlint/load/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/@commitlint/message": { "version": "16.2.1", "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-16.2.1.tgz", @@ -19946,9 +19960,9 @@ } }, "node_modules/typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -19956,7 +19970,7 @@ "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/ua-parser-js": { diff --git a/package.json b/package.json index f34868348..b481fedeb 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,6 @@ "stylelint-config-standard-scss": "3.0.0", "ts-jest": "27.1.3", "ts-node": "10.7.0", - "typescript": "4.5.5" + "typescript": "5.9.3" } } diff --git a/ui/biome.json b/ui/biome.json index 9a653819b..ac4c6c234 100644 --- a/ui/biome.json +++ b/ui/biome.json @@ -7,7 +7,11 @@ }, "files": { "ignoreUnknown": false, - "includes": ["src/**", "scripts/**", "!src/react-admin/modules/shared/helpers/map-deep/map-deep.mocks.ts"] + "includes": [ + "src/**", + "scripts/**", + "!src/react-admin/modules/shared/helpers/map-deep/map-deep.mocks.ts" + ] }, "formatter": { "enabled": true, diff --git a/ui/package-lock.json b/ui/package-lock.json index 96494d7ef..15bd61064 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -9,7 +9,8 @@ "version": "6.0.7", "dependencies": { "jsdom": "27.4.0", - "memoizee": "0.4.17" + "memoizee": "0.4.17", + "swiper": "14.0.5" }, "devDependencies": { "@babel/core": "7.29.7", @@ -16125,6 +16126,25 @@ "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, + "node_modules/swiper": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-14.0.5.tgz", + "integrity": "sha512-SMSKS0sj+lPIFzngfIKb5cyBtzmAuJw7rXgXdyYiDReb+pSpJXuNljHYgT4DXa5Stnl2Ew2/Lam5ipv4PIqZ7A==", + "funding": [ + { + "type": "custom", + "url": "https://sponsors.nolimits4web.com" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nolimits4web" + } + ], + "license": "MIT", + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/ui/package.json b/ui/package.json index 8952e3459..b087d36e1 100644 --- a/ui/package.json +++ b/ui/package.json @@ -45,13 +45,15 @@ "serve": "vite preview", "copy-to-client-hetarchief": "rimraf ../../hetarchief-client/node_modules/@meemoo/admin-core-ui/dist ../../hetarchief-client/node_modules/.cache ../../hetarchief-client/.swc ../../hetarchief-client/.next && rimraf ../../hetarchief-client/.next && cp -r dist package.json ../../hetarchief-client/node_modules/@meemoo/admin-core-ui", "copy-to-client-avo": "rimraf ../../avo2-client/node_modules/@meemoo/admin-core-ui/dist ../../avo2-client/node_modules/.cache ../../avo2-client/node_modules/.vite && cp -r dist package.json ../../avo2-client/node_modules/@meemoo/admin-core-ui", - "copy": "vite build && npm run copy-to-client-avo && npm run copy-to-client-hetarchief", - "copy:avo": "vite build && npm run copy-to-client-avo", - "copy:hetarchief": "vite build && npm run copy-to-client-hetarchief", + "copy": "npm run build && npm run copy-to-client-avo && npm run copy-to-client-hetarchief", + "copy:avo": "npm run build && npm run copy-to-client-avo", + "copy:hetarchief": "npm run build && npm run copy-to-client-hetarchief", "lint": "npm run lint:ts && npm run lint:scss", "lint:ts": "biome lint --write .", "lint:scss": "stylelint --fix src/**/*.{css,scss}", "format": "biome format --write src", + "biome": "biome ci", + "biome:fix": "biome check --write", "test": "vitest", "type-check": "tsc --noEmit", "build:analyze": "npx vite-bundle-visualizer", @@ -186,7 +188,8 @@ }, "dependencies": { "jsdom": "27.4.0", - "memoizee": "0.4.17" + "memoizee": "0.4.17", + "swiper": "14.0.5" }, "allowScripts": { "@parcel/watcher@2.5.6": true, diff --git a/ui/scripts/execute-database-query.ts b/ui/scripts/execute-database-query.ts index d46f078ce..154c3d308 100644 --- a/ui/scripts/execute-database-query.ts +++ b/ui/scripts/execute-database-query.ts @@ -1,41 +1,41 @@ -import fetch, { Headers } from "node-fetch"; +import fetch, { Headers } from 'node-fetch'; export async function executeDatabaseQuery( - app: "AVO" | "HET_ARCHIEF", + app: 'AVO' | 'HET_ARCHIEF', query: string, // biome-ignore lint/suspicious/noExplicitAny: todo variables: any = {}, - env: "LOCAL" | "QAS" = "LOCAL", + env: 'LOCAL' | 'QAS' = 'LOCAL' // biome-ignore lint/suspicious/noExplicitAny: todo ): Promise { if ( - env === "LOCAL" && + env === 'LOCAL' && (!process.env.GRAPHQL_URL_AVO || !process.env.GRAPHQL_SECRET_AVO || !process.env.GRAPHQL_URL_HETARCHIEF || !process.env.GRAPHQL_SECRET_HETARCHIEF) ) { throw new Error( - "Missing environment variables. One or more of these are missing: GRAPHQL_URL_AVO, GRAPHQL_SECRET_AVO, GRAPHQL_URL_HETARCHIEF, GRAPHQL_SECRET_HETARCHIEF", + 'Missing environment variables. One or more of these are missing: GRAPHQL_URL_AVO, GRAPHQL_SECRET_AVO, GRAPHQL_URL_HETARCHIEF, GRAPHQL_SECRET_HETARCHIEF' ); } if ( - env === "QAS" && + env === 'QAS' && (!process.env.GRAPHQL_URL_AVO_QAS || !process.env.GRAPHQL_SECRET_AVO_QAS || !process.env.GRAPHQL_URL_HETARCHIEF_QAS || !process.env.GRAPHQL_SECRET_HETARCHIEF_QAS) ) { throw new Error( - "Missing environment variables. One or more of these are missing: GRAPHQL_URL_AVO_QAS, GRAPHQL_SECRET_AVO_QAS, GRAPHQL_URL_HETARCHIEF_QAS, GRAPHQL_SECRET_HETARCHIEF_QAS", + 'Missing environment variables. One or more of these are missing: GRAPHQL_URL_AVO_QAS, GRAPHQL_SECRET_AVO_QAS, GRAPHQL_URL_HETARCHIEF_QAS, GRAPHQL_SECRET_HETARCHIEF_QAS' ); } - let graphQlUrl = ""; - let graphQlPassword = ""; - if (env === "QAS") { - if (env === "QAS") { + let graphQlUrl = ''; + let graphQlPassword = ''; + if (env === 'QAS') { + if (env === 'QAS') { // We need the QAS database environment variables to fetch the latest translations and QAS is the "master" of all translations - if (app === "AVO") { + if (app === 'AVO') { graphQlUrl = process.env.GRAPHQL_URL_AVO_QAS as string; graphQlPassword = process.env.GRAPHQL_SECRET_AVO_QAS as string; } else { @@ -44,7 +44,7 @@ export async function executeDatabaseQuery( } } } else { - if (app === "AVO") { + if (app === 'AVO') { graphQlUrl = process.env.GRAPHQL_URL_AVO as string; graphQlPassword = process.env.GRAPHQL_SECRET_AVO as string; } else { @@ -53,8 +53,8 @@ export async function executeDatabaseQuery( } } const requestHeaders = new Headers(); - requestHeaders.append("Content-Type", "application/json"); - requestHeaders.append("x-hasura-admin-secret", graphQlPassword); + requestHeaders.append('Content-Type', 'application/json'); + requestHeaders.append('x-hasura-admin-secret', graphQlPassword); const raw = JSON.stringify({ query, @@ -62,7 +62,7 @@ export async function executeDatabaseQuery( }); const requestOptions = { - method: "POST", + method: 'POST', headers: requestHeaders, body: raw, }; diff --git a/ui/scripts/extract-and-replace-translations.ts b/ui/scripts/extract-and-replace-translations.ts index b78bac426..b8b160b93 100644 --- a/ui/scripts/extract-and-replace-translations.ts +++ b/ui/scripts/extract-and-replace-translations.ts @@ -140,7 +140,7 @@ function reconstructVariablesInFallback(fallback: string, variables: string[]): } function getFallbackTranslation(key: string, variables: string[] = []): string { - const fallback = `${upperFirst(lowerCase(key.split(TRANSLATION_SEPARATOR).pop()))}`; + const fallback = `${upperFirst(lowerCase(key.split(TRANSLATION_SEPARATOR).pop() as string))}`; if (variables.length === 0) return fallback; return reconstructVariablesInFallback(fallback, variables); } @@ -777,10 +777,7 @@ async function extractTranslations() { console.info(`Writing SQL file: ${sqlFilePath}`); const uniqueTranslations = [ ...new Map( - allTranslations.map((t) => [ - `${t.component}|${t.location}|${t.key}|${t.language}`, - t, - ]) + allTranslations.map((t) => [`${t.component}|${t.location}|${t.key}|${t.language}`, t]) ).values(), ]; let sql: string = uniqueTranslations diff --git a/ui/scripts/tsconfig.json b/ui/scripts/tsconfig.json index 3938d0ca7..331e6bb70 100644 --- a/ui/scripts/tsconfig.json +++ b/ui/scripts/tsconfig.json @@ -1,12 +1,12 @@ { - "extends": "../tsconfig.json", - "compilerOptions": { - "module": "ES2022", + "extends": "../tsconfig.json", + "compilerOptions": { + "module": "ES2022", "resolveJsonModule": true, "esModuleInterop": true, "allowImportingTsExtensions": true - }, - "files": [ + }, + "files": [ "backup-translations.ts", "execute-database-query.ts", "extract-and-replace-translations.ts" diff --git a/ui/src/client.ts b/ui/src/client.ts index a477cad4f..1588c6387 100644 --- a/ui/src/client.ts +++ b/ui/src/client.ts @@ -19,6 +19,7 @@ export { BlockIntro } from '~content-blocks/BlockIntro'; export { BlockKlaar } from '~content-blocks/BlockKlaar'; export { BlockMaintainersGrid } from '~content-blocks/BlockMaintainersGrid'; export { BlockOverviewNewspaperTitles } from '~content-blocks/BlockOverviewNewspaperTitles'; +export { BlockOverviewWithCarousel } from '~content-blocks/BlockOverviewWithCarousel'; export { BlockPageOverviewWrapper } from '~content-blocks/BlockPageOverview/BlockPageOverview.wrapper'; export { BlockQuote } from '~content-blocks/BlockQuote'; export { BlockRichText } from '~content-blocks/BlockRichText'; diff --git a/ui/src/react-admin/core/config/config.types.ts b/ui/src/react-admin/core/config/config.types.ts index 20c531d34..0b00f6779 100644 --- a/ui/src/react-admin/core/config/config.types.ts +++ b/ui/src/react-admin/core/config/config.types.ts @@ -47,9 +47,11 @@ export interface LinkInfo { className?: string; to?: string; onClick?: (evt: MouseEvent) => void; + onKeyUp?: (evt: KeyboardEvent) => void; title?: string; children: ReactNode; target?: LinkTarget; + tabIndex?: number; } export type NavigateFunction = (to: string, options?: { replace?: boolean }) => Promise; @@ -169,6 +171,7 @@ export interface IconConfig { angleRight: IconComponentProps; anglesLeft: IconComponentProps; anglesRight: IconComponentProps; + arrowLeft: IconComponentProps; arrowRight: IconComponentProps; delete: IconComponentProps; extraOptions: IconComponentProps; diff --git a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.const.tsx b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.const.tsx index e398109ee..2b41e4d26 100644 --- a/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.const.tsx +++ b/ui/src/react-admin/modules/content-page/components/ContentBlockRenderer/ContentBlockRenderer.const.tsx @@ -22,6 +22,7 @@ import { BlockIntro } from '~content-blocks/BlockIntro'; import { BlockKlaar } from '~content-blocks/BlockKlaar'; import { BlockMaintainersGrid } from '~content-blocks/BlockMaintainersGrid'; import { BlockOverviewNewspaperTitles } from '~content-blocks/BlockOverviewNewspaperTitles'; +import { BlockOverviewWithCarousel } from '~content-blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.tsx'; import { BlockPageOverviewWrapper } from '~content-blocks/BlockPageOverview'; import { BlockQuote } from '~content-blocks/BlockQuote'; import { BlockRichTextWrapper } from '~content-blocks/BlockRichText'; @@ -85,6 +86,7 @@ export function GET_BLOCK_COMPONENT( ), [ContentBlockType.Breadcrumbs]: BlockBreadcrumbs, [ContentBlockType.HetArchiefImageTextBackground]: BlockHetArchiefImageTextBackground, + [ContentBlockType.OverviewWithCarousel]: BlockOverviewWithCarousel, // Avo specific blocks [ContentBlockType.MediaGrid]: loadComponentFromConfig(ContentBlockType.MediaGrid), diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoHero/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoHero/index.ts index 012a145a2..752730222 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoHero/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoHero/index.ts @@ -1,2 +1,2 @@ -export * from './BlockAvoHero.editorconfig'; export * from './BlockAvoHero'; +export * from './BlockAvoHero.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoImageTextBackground/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoImageTextBackground/index.ts index 50c09cf8c..0e9104edb 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoImageTextBackground/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockAvoImageTextBackground/index.ts @@ -1,2 +1,2 @@ -export * from './BlockAvoImageTextBackground.editorconfig'; export * from './BlockAvoImageTextBackground'; +export * from './BlockAvoImageTextBackground.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockBreadcrumbs/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockBreadcrumbs/index.ts index 786ca78d2..619d28634 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockBreadcrumbs/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockBreadcrumbs/index.ts @@ -1,2 +1,2 @@ -export { CONTENT_BREADCRUMBS_CONFIG } from './BlockBreadcrumbs.editorconfig'; export { BlockBreadcrumbs } from './BlockBreadcrumbs'; +export { CONTENT_BREADCRUMBS_CONFIG } from './BlockBreadcrumbs.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockButtons/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockButtons/index.ts index 724cc922e..73d5a2a64 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockButtons/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockButtons/index.ts @@ -1,3 +1,3 @@ -export * from './BlockButtons.editorconfig'; export * from './BlockButtons'; +export * from './BlockButtons.editorconfig'; export * from './BlockButtons.wrapper'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockCTAs/BlockCTAs.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockCTAs/BlockCTAs.editorconfig.ts index eb2a006b0..09e0fafa4 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockCTAs/BlockCTAs.editorconfig.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockCTAs/BlockCTAs.editorconfig.ts @@ -1,19 +1,19 @@ import type { CTAProps } from '@viaa/avo2-components'; +import { AdminConfigManager } from '~core/config/config.class'; import { GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF, GET_BACKGROUND_COLOR_OPTIONS_AVO, } from '~modules/content-page/const/get-color-options'; import { GET_HEADING_TYPE_OPTIONS } from '~modules/content-page/const/get-heading-type-options'; -import { isAvo } from '~shared/helpers/is-avo'; import { GET_ADMIN_ICON_OPTIONS } from '~shared/consts/icons.consts'; +import { isAvo } from '~shared/helpers/is-avo'; import { tText } from '~shared/helpers/translation-functions'; import type { ContentBlockConfig, DefaultContentBlockState, } from '../../../types/content-block.types'; import { ContentBlockEditor, ContentBlockType } from '../../../types/content-block.types'; - import { BACKGROUND_COLOR_FIELD, BLOCK_FIELD_DEFAULTS, @@ -22,8 +22,6 @@ import { TEXT_FIELD, } from '../defaults'; -import { AdminConfigManager } from '~core/config/config.class'; - const EMPTY_CTA: Partial = { headingType: 'h2', heading: '', diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockCTAs/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockCTAs/index.ts index a14bcf2e1..6761475bd 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockCTAs/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockCTAs/index.ts @@ -1,3 +1,3 @@ -export * from './BlockCTAs.editorconfig'; export * from './BlockCTAs'; +export * from './BlockCTAs.editorconfig'; export * from './BlockCTAs.wrapper'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockCardsWithoutDescription/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockCardsWithoutDescription/index.ts index b3eda6c02..bebf81e94 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockCardsWithoutDescription/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockCardsWithoutDescription/index.ts @@ -1,2 +1,2 @@ -export * from './BlockCardsWithoutDescription.editorconfig'; export * from './BlockCardsWithoutDescription'; +export * from './BlockCardsWithoutDescription.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockContentPageMeta/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockContentPageMeta/index.ts index 2dde8dd85..0404b1419 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockContentPageMeta/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockContentPageMeta/index.ts @@ -1,2 +1,2 @@ -export * from './BlockContentPageMeta.editorconfig'; export * from './BlockContentPageMeta'; +export * from './BlockContentPageMeta.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockEventbrite/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockEventbrite/index.ts index a458e096b..b35094db5 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockEventbrite/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockEventbrite/index.ts @@ -1,2 +1,2 @@ -export * from './BlockEventbrite.editorconfig'; export * from './BlockEventbrite'; +export * from './BlockEventbrite.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHeading/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHeading/index.ts index 1d4020072..857764753 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHeading/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHeading/index.ts @@ -1,2 +1,2 @@ -export * from './BlockHeading.editorconfig'; export * from './BlockHeading'; +export * from './BlockHeading.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefHeaderSearch/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefHeaderSearch/index.ts index 65324db34..9f219627b 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefHeaderSearch/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefHeaderSearch/index.ts @@ -1,2 +1,2 @@ -export * from './BlockHetArchiefHeaderSearch.editorconfig'; export * from './BlockHetArchiefHeaderSearch'; +export * from './BlockHetArchiefHeaderSearch.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefImageTextBackground/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefImageTextBackground/index.ts index 7d4a1c88b..6d695986a 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefImageTextBackground/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockHetArchiefImageTextBackground/index.ts @@ -1,2 +1,2 @@ -export * from './BlockHetArchiefImageTextBackground.editorconfig'; export * from './BlockHetArchiefImageTextBackground'; +export * from './BlockHetArchiefImageTextBackground.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockIFrame/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockIFrame/index.ts index cefd3eae3..85206a5e0 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockIFrame/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockIFrame/index.ts @@ -1,2 +1,2 @@ -export * from './BlockIFrame.editorconfig'; export * from './BlockIFrame'; +export * from './BlockIFrame.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockImage/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockImage/index.ts index d49f6e7bf..285b6cb80 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockImage/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockImage/index.ts @@ -1,2 +1,2 @@ -export * from './BlockImage.editorconfig'; export * from './BlockImage'; +export * from './BlockImage.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockImageGrid/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockImageGrid/index.ts index b7b1f1886..46f540c83 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockImageGrid/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockImageGrid/index.ts @@ -1,5 +1,5 @@ -export * from './BlockImageGrid.editorconfig'; export * from './BlockImageGrid'; +export * from './BlockImageGrid.editorconfig'; export * from './BlockImageGrid.types'; export * from './BlockImageGrid.wrapper'; export * from './BlockLogoGrid.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockImageTitleTextButton/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockImageTitleTextButton/index.ts index 60927e057..e0d655e06 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockImageTitleTextButton/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockImageTitleTextButton/index.ts @@ -1,3 +1,3 @@ -export * from './BlockImageTitleTextButton.editorconfig'; export * from './BlockImageTitleTextButton'; +export * from './BlockImageTitleTextButton.editorconfig'; export * from './BlockImageTitleTextButton.wrapper'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockIntro/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockIntro/index.ts index 9c13a246a..7aca8143a 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockIntro/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockIntro/index.ts @@ -1,2 +1,2 @@ -export * from './BlockIntro.editorconfig'; export * from './BlockIntro'; +export * from './BlockIntro.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockKlaar/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockKlaar/index.ts index 53401ca19..b99377348 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockKlaar/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockKlaar/index.ts @@ -1,2 +1,2 @@ -export * from './BlockKlaar.editorconfig'; export * from './BlockKlaar'; +export * from './BlockKlaar.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockMaintainersGrid/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockMaintainersGrid/index.ts index 59d0568ec..b9ed1038c 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockMaintainersGrid/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockMaintainersGrid/index.ts @@ -1,2 +1,2 @@ -export * from './BlockMaintainersGrid.editorconfig'; export * from './BlockMaintainersGrid'; +export * from './BlockMaintainersGrid.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.editorconfig.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.editorconfig.ts new file mode 100644 index 000000000..b2b67b856 --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.editorconfig.ts @@ -0,0 +1,168 @@ +import { AvoCoreContentPickerType } from '@viaa/avo2-types'; +import { + BACKGROUND_COLOR_FIELD, + BLOCK_FIELD_DEFAULTS, + BLOCK_STATE_DEFAULTS, + FOREGROUND_COLOR_FIELD, + TEXT_FIELD, +} from '~content-blocks/defaults'; +import { + GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF, + GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF, +} from '~modules/content-page/const/get-color-options.ts'; +import { GET_FULL_HEADING_TYPE_OPTIONS } from '~modules/content-page/const/get-heading-type-options'; +import { + Color, + type ContentBlockConfig, + ContentBlockEditor, + ContentBlockType, + type DefaultContentBlockState, +} from '~modules/content-page/types/content-block.types'; +import type { FileUploadProps } from '~shared/components/FileUpload/FileUpload.tsx'; +import { PHOTO_TYPES } from '~shared/helpers/files.ts'; +import { tText } from '~shared/helpers/translation-functions'; +import { validateRequiredValue } from '~shared/helpers/validation.ts'; +import { HET_ARCHIEF } from '~shared/types'; + +const INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_ELEMENT_STATE = () => ({ + mediaItem: { + label: '', + type: AvoCoreContentPickerType.CONTENT_PAGE, + value: '', + }, + image: '', + title: '', + backgroundColor: Color.White, + itemDisplay: '', +}); + +export const INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_COMPONENTS_STATE = () => ({ + title: '', + titleType: '', + buttonLabel: '', + buttonAltTitle: '', + elements: [INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_ELEMENT_STATE()], +}); + +export const INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_BLOCK_STATE = (): DefaultContentBlockState => ({ + ...BLOCK_STATE_DEFAULTS(), +}); + +export const CONTENT_OVERVIEW_WITH_CAROUSEL_CONFIG = (position = 0): ContentBlockConfig => ({ + position, + name: tText('Overzicht met carrousel'), + type: ContentBlockType.OverviewWithCarousel, + components: { + state: INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_COMPONENTS_STATE(), + fields: { + title: TEXT_FIELD( + { + label: tText('title', undefined, [HET_ARCHIEF]), + }, + tText('titel is verplicht') + ), + titleType: { + label: tText('titletype', undefined, [HET_ARCHIEF]), + editorType: ContentBlockEditor.Select, + editorProps: { + options: GET_FULL_HEADING_TYPE_OPTIONS(), + }, + validator: (value: string) => validateRequiredValue(value, 'titletype is verplicht'), + }, + buttonLabel: TEXT_FIELD({ + label: tText('button label', undefined, [HET_ARCHIEF]), + }), + buttonAltTitle: TEXT_FIELD({ + label: tText('button alt title', undefined, [HET_ARCHIEF]), + }), + buttonAction: { + label: tText('button action', undefined, [HET_ARCHIEF]), + editorType: ContentBlockEditor.ContentPicker, + editorProps: { + allowedTypes: [ + AvoCoreContentPickerType.CONTENT_PAGE, + AvoCoreContentPickerType.INTERNAL_LINK, + AvoCoreContentPickerType.EXTERNAL_LINK, + ], + }, + }, + elements: { + label: tText('Content item', undefined, [HET_ARCHIEF]), + fields: { + mediaItem: { + label: tText('Item', undefined, [HET_ARCHIEF]), + editorType: ContentBlockEditor.ContentPicker, + editorProps: { + allowedTypes: [ + AvoCoreContentPickerType.EXTERNAL_LINK, + AvoCoreContentPickerType.CONTENT_PAGE, + AvoCoreContentPickerType.IE_OBJECT, + ], + }, + }, + image: { + label: tText('Item image'), + editorType: ContentBlockEditor.FileUpload, + validator: (value: string) => validateRequiredValue(value, 'Afbeelding is verplicht'), + editorProps: { + assetType: 'CONTENT_BLOCK_IMAGE', + allowMulti: false, + allowedTypes: PHOTO_TYPES, + } as FileUploadProps, + }, + imageAlt: TEXT_FIELD({ + label: tText('alt tekst voor de afbeelding'), + validator: undefined, + }), + title: TEXT_FIELD( + { + label: tText('Item title', undefined, [HET_ARCHIEF]), + }, + tText('titel is verplicht') + ), + backgroundColor: BACKGROUND_COLOR_FIELD( + tText('achtergrondkleur van het item'), + GET_BACKGROUND_COLOR_OPTIONS_ARCHIEF()[1] + ), + textColor: FOREGROUND_COLOR_FIELD( + tText('tekst kleur'), + GET_FOREGROUND_COLOR_OPTIONS_ARCHIEF()[3] + ), + itemDisplay: { + label: tText('Weergave'), + editorType: ContentBlockEditor.Select, + editorProps: { + options: [ + { + label: tText('Portret'), + value: '9:16', + }, + { + label: tText('Afgerond portret'), + value: '9:16round', + }, + { + label: tText('Landscape'), + value: '16:9', + }, + ], + }, + validator: (value: string) => validateRequiredValue(value, 'Weergave is verplicht'), + }, + }, + type: 'fieldGroup', + repeat: { + defaultState: INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_ELEMENT_STATE(), + addButtonLabel: tText('voeg object toe', undefined, [HET_ARCHIEF]), + deleteButtonLabel: tText('verwijder object', undefined, [HET_ARCHIEF]), + }, + }, + }, + }, + block: { + state: INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_BLOCK_STATE(), + fields: { + ...BLOCK_FIELD_DEFAULTS(), + }, + }, +}); diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.scss b/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.scss new file mode 100644 index 000000000..51b212359 --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.scss @@ -0,0 +1,199 @@ +@use "sass:math"; +@use "../../../../shared/styles/settings/variables" as variables; +@use "../../../../shared/styles/settings/colors" as colors; + +.c-block-overview-with-carousel { + .c-block-overview-with-carousel__header { + width: 100%; + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + gap: 1.6rem; + margin-bottom: 2.2rem; + justify-content: space-between; + + @media (max-width: variables.$g-bp2) { + margin-bottom: 2.4rem; + gap: 1.2rem; + } + + &-title { + color: colors.$color-gray-1000; + font-family: "SofiaPro"; + font-size: 2.4rem; + font-style: normal; + font-weight: 800; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: fit-content; + } + + &-actions { + display: flex; + align-items: center; + gap: 1.6rem; + min-width: 0; + + .c-button { + margin: 0 !important; + } + + // Only the buttonLabel button (a direct child) may shrink/truncate, + // the prev/next nav group keeps its natural size. + > a { + min-width: 0; + flex-shrink: 1; + + > .c-button { + min-width: 0; + width: 100%; + + .c-button__content { + min-width: 0; + width: 100%; + } + + .c-button__label { + font-weight: 700; // since sm buttons loose this + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + } + } + + &-nav { + display: flex; + align-items: center; + gap: .8rem; + margin-left: auto; + flex-shrink: 0; + } + + @media (max-width: variables.$g-bp2) { + flex-direction: column; + align-items: stretch; + + &-title { + margin-right: 0; + } + + &-actions { + width: 100%; + } + } + } + + &__wrapper { + overflow: visible !important; + } + + &__slide { + display: flex !important; + flex-direction: column; + height: 36.8rem !important; + + a { + text-decoration: none; + + &:focus-visible { + outline: 2px solid colors.$color-ocean-green; + } + } + + &:hover { + .c-block-overview-with-carousel__slide-image > img { + transform: scale(1.1); + } + } + + &-image { + flex: auto; + width: 100%; + } + + &__portrait { + width: 28rem !important; + + .c-block-overview-with-carousel__slide-image { + min-height: 28rem; + } + + .c-block-overview-with-carousel__slide-description { + flex: unset; + } + } + + &__round { + width: 28rem !important; + border-radius: 140px 140px 0 0; + + .c-block-overview-with-carousel__slide-image { + height: 28rem; + clip-path: circle(); + flex: initial; + } + } + + &__landscape { + aspect-ratio: 16/9; + max-width: 64rem; + + .c-block-overview-with-carousel__slide-description { + display: inline-flex; + max-width: 87.5%; + align-items: flex-start; + position: absolute; + } + + .c-block-overview-with-carousel__slide-text { + font-size: 3.2rem; + font-style: normal; + font-weight: 800; + line-height: 4.0rem; + } + } + + &-image { + width: 100%; + height: 100%; + overflow: hidden; + + > img { + object-fit: cover; + object-position: center; + width: 100%; + height: 100%; + transition: transform 0.5s ease-out; + } + } + + &-description { + flex: 1 1 auto; + min-height: 0; + display: flex; + align-items: end; + padding: 1.6rem 2.4rem; + } + + &-text { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + line-clamp: 2; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + + color: colors.$color-gray-1000; + font-family: "SofiaPro"; + font-size: 1.8rem; + font-style: normal; + font-weight: 800; + line-height: 2.8rem; + } + } +} diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.tsx b/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.tsx new file mode 100644 index 000000000..c68be4525 --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.tsx @@ -0,0 +1,179 @@ +import { type ButtonAction, Image } from '@viaa/avo2-components'; +import React, { type FunctionComponent, type ReactElement, useEffect, useState } from 'react'; +import type { Color, HeadingTypeOption } from '~modules/content-page/types/content-block.types'; +import type { DefaultComponentProps } from '~modules/shared/types/components'; +import './BlockOverviewWithCarousel.scss'; +import { Button } from '@meemoo/react-components'; +import type SwiperController from 'swiper'; +import { Controller } from 'swiper/modules'; +import { Swiper, SwiperSlide } from 'swiper/react'; +import { Icon } from '~shared/components/Icon'; +import { tText } from '~shared/helpers/translation-functions.ts'; +import 'swiper/css'; +import clsx from 'clsx'; +import { BlockHeading } from '~content-blocks/BlockHeading'; +import { generateSmartLink } from '~shared/components/SmartLink/SmartLink.tsx'; + +export interface BlockOverviewWithCarouselProps extends DefaultComponentProps { + backgroundColor: string; + title: string; + titleType: HeadingTypeOption; + buttonLabel: string; + buttonAltTitle?: string; + buttonAction?: ButtonAction; + elements: { + mediaItem: ButtonAction; + image: string; + imageAlt: string; + title: string; + textColor: Color; + backgroundColor: Color; + itemDisplay: string; + }[]; +} + +export const BlockOverviewWithCarousel: FunctionComponent = ({ + backgroundColor, + title, + titleType, + buttonLabel, + buttonAltTitle, + buttonAction, + elements, +}): ReactElement => { + const [controlledSwiper, setControlledSwiper] = useState(null); + const [showPrevSlideButton, setShowPrevSlideButton] = useState(false); + const [showNextSlideButton, setShowNextSlideButton] = useState(false); + + const updateSlideButtons = () => { + setShowPrevSlideButton(controlledSwiper ? !controlledSwiper.isBeginning : false); + setShowNextSlideButton(controlledSwiper ? !controlledSwiper.isEnd : false); + }; + + // biome-ignore lint/correctness/useExhaustiveDependencies: Only used to init the buttons + useEffect(() => { + if (controlledSwiper) { + updateSlideButtons(); + } + }, [controlledSwiper]); + + const renderSlideContent = ( + image: string, + imageAlt: string, + title: string, + backgroundColor: Color + ) => { + return ( + <> + {imageAlt +
+ {title} +
+ + ); + }; + + return ( +
+
+ + {title} + + +
+ {buttonAction && + generateSmartLink( + buttonAction, +
+
+
+ updateSlideButtons()} + watchSlidesProgress={true} + > + {elements.map( + ({ title, image, imageAlt, itemDisplay, textColor, backgroundColor, mediaItem }) => { + const componentClassName = clsx( + 'c-block-overview-with-carousel__slide', + itemDisplay === '9:16' && `c-block-overview-with-carousel__slide__portrait`, + itemDisplay === '9:16round' && `c-block-overview-with-carousel__slide__round`, + itemDisplay === '16:9' && `c-block-overview-with-carousel__slide__landscape` + ); + return ( + + {({ isVisible }) => { + return generateSmartLink( + mediaItem, + renderSlideContent(image, imageAlt, title, backgroundColor), + title, + componentClassName, + isVisible ? undefined : -1 + ); + }} + + ); + } + )} + + + ); +}; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/index.ts new file mode 100644 index 000000000..233fececc --- /dev/null +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockOverviewWithCarousel/index.ts @@ -0,0 +1,2 @@ +export { BlockOverviewWithCarousel } from './BlockOverviewWithCarousel'; +export { CONTENT_OVERVIEW_WITH_CAROUSEL_CONFIG } from './BlockOverviewWithCarousel.editorconfig.ts'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockPageOverview/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockPageOverview/index.ts index 9c7ef96c1..195386c48 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockPageOverview/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockPageOverview/index.ts @@ -1,4 +1,4 @@ -export * from './BlockPageOverview.editorconfig'; export * from './BlockPageOverview'; +export * from './BlockPageOverview.editorconfig'; export * from './BlockPageOverview.types'; export * from './BlockPageOverview.wrapper'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/index.ts index ded29cb9e..a03d999c1 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockQuote/index.ts @@ -1,2 +1,2 @@ -export * from './BlockQuote.editorconfig'; export * from './BlockQuote'; +export * from './BlockQuote.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockRichText/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockRichText/index.ts index fc5e79c31..67c34eba3 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockRichText/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockRichText/index.ts @@ -1,4 +1,4 @@ -export * from './BlockRichText.editorconfig'; export * from './BlockRichText'; +export * from './BlockRichText.editorconfig'; export * from './BlockRichText.wrapper'; export * from './BlockRichTextTwoColumns.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockScrollDownNudge/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockScrollDownNudge/index.ts index 9cc475ec4..6cc67072a 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockScrollDownNudge/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockScrollDownNudge/index.ts @@ -1,5 +1,5 @@ +export { BlockScrollDownNudge } from './BlockScrollDownNudge'; export { CONTENT_SCROLL_DOWN_NUDGE_CONFIG, INITIAL_SCROLL_DOWN_NUDGE_BLOCK_STATE, } from './BlockScrollDownNudge.editorconfig'; -export { BlockScrollDownNudge } from './BlockScrollDownNudge'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockSpotlight/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockSpotlight/index.ts index 3c6031403..45a2f33ae 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockSpotlight/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockSpotlight/index.ts @@ -1,4 +1,4 @@ export * from './BlockProjectSpotlight.editorconfig'; export * from './BlockProjectSpotlight.wrapper'; -export * from './BlockSpotlight.editorconfig'; export * from './BlockSpotlight'; +export * from './BlockSpotlight.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockTagsWithLink/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockTagsWithLink/index.ts index 5de079935..d524ca7bf 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockTagsWithLink/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockTagsWithLink/index.ts @@ -1,2 +1,2 @@ -export * from './BlockTagsWithLink.editorconfig'; export * from './BlockTagsWithLink'; +export * from './BlockTagsWithLink.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockThreeClickableTiles/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockThreeClickableTiles/index.ts index 9ee42e530..59264fb77 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockThreeClickableTiles/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockThreeClickableTiles/index.ts @@ -1,2 +1,2 @@ -export * from './BlockThreeClickableTiles.editorconfig'; export * from './BlockThreeClickableTiles'; +export * from './BlockThreeClickableTiles.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockUitgeklaard/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockUitgeklaard/index.ts index 98d34fb16..ec0312a87 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockUitgeklaard/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockUitgeklaard/index.ts @@ -1,2 +1,2 @@ -export * from './BlockUitgeklaard.editorconfig'; export * from './BlockUitgeklaard'; +export * from './BlockUitgeklaard.editorconfig'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockVideo/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockVideo/index.ts index 2b74a5778..b1109c5ef 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockVideo/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockVideo/index.ts @@ -1,3 +1,3 @@ -export * from './BlockVideo.editorconfig'; export * from './BlockVideo'; +export * from './BlockVideo.editorconfig'; export * from './BlockVideo.wrapper'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/BlockVideoTitleTextButton/index.ts b/ui/src/react-admin/modules/content-page/components/blocks/BlockVideoTitleTextButton/index.ts index 95e2c58e1..241f61ccb 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/BlockVideoTitleTextButton/index.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/BlockVideoTitleTextButton/index.ts @@ -1,3 +1,3 @@ -export * from './BlockVideoTitleTextButton.editorconfig'; export * from './BlockVideoTitleTextButton'; +export * from './BlockVideoTitleTextButton.editorconfig'; export * from './BlockVideoTitleTextButton.wrapper'; diff --git a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts index 9561d7e27..c09bb709b 100644 --- a/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts +++ b/ui/src/react-admin/modules/content-page/components/blocks/defaults.ts @@ -14,6 +14,7 @@ import type { UserGroupSelectProps } from '~shared/components/UserGroupSelect/Us import { RICH_TEXT_EDITOR_OPTIONS_FULL_WITHOUT_ALIGN } from '~shared/consts/rich-text-editor.consts'; import { isAvo } from '~shared/helpers/is-avo'; import { tText } from '~shared/helpers/translation-functions'; +import { validateRequiredValue } from '~shared/helpers/validation.ts'; import { SpecialUserGroups } from '~shared/types/authentication.types'; import type { ContentBlockField, @@ -149,18 +150,7 @@ export const TEXT_FIELD = ( ): ContentBlockField => ({ label: tText('admin/content-block/helpers/generators/defaults___tekst'), editorType: ContentBlockEditor.TextInput, // Default text input type. also supported: textarea and rich text editor - validator: (value: string) => { - const errorArray: string[] = []; - - if (!value && emptyFieldValidatorMessage) { - errorArray.push( - emptyFieldValidatorMessage || - tText('admin/content-block/helpers/generators/defaults___tekst-is-verplicht') - ); - } - - return errorArray; - }, + validator: (value: string) => validateRequiredValue(value, emptyFieldValidatorMessage), editorProps: { controls: [...RICH_TEXT_EDITOR_OPTIONS_FULL_WITHOUT_ALIGN, 'media'], fileType: 'CONTENT_BLOCK_IMAGE', @@ -176,15 +166,7 @@ export const FILE_FIELD = ( ): ContentBlockField => ({ label: tText('admin/content-block/helpers/generators/defaults___bestand'), editorType: ContentBlockEditor.FileUpload, - validator: (value: string) => { - const errorArray: string[] = []; - - if (!value) { - errorArray.push(emptyFieldValidatorMessage); - } - - return errorArray; - }, + validator: (value: string) => validateRequiredValue(value, emptyFieldValidatorMessage), editorProps: { assetType: 'CONTENT_BLOCK_IMAGE' } as FileUploadProps, ...propOverride, }); @@ -197,15 +179,7 @@ export const ITEM_PICKER_FIELD = ( ): ContentBlockField => ({ label: tText('admin/content-block/helpers/generators/media-player___video-of-audio-item'), editorType: ContentBlockEditor.ContentPicker, - validator: (value: string) => { - const errorArray: string[] = []; - - if (!value) { - errorArray.push(emptyFieldValidatorMessage); - } - - return errorArray; - }, + validator: (value: string) => validateRequiredValue(value, emptyFieldValidatorMessage), editorProps: { allowedTypes: ['ITEM'], hideTargetSwitch: true, diff --git a/ui/src/react-admin/modules/content-page/components/fields/PaddingSelectTopBottom/PaddingSelectTopBottom.tsx b/ui/src/react-admin/modules/content-page/components/fields/PaddingSelectTopBottom/PaddingSelectTopBottom.tsx index aadf8e0fe..1fa87cd1d 100644 --- a/ui/src/react-admin/modules/content-page/components/fields/PaddingSelectTopBottom/PaddingSelectTopBottom.tsx +++ b/ui/src/react-admin/modules/content-page/components/fields/PaddingSelectTopBottom/PaddingSelectTopBottom.tsx @@ -2,10 +2,8 @@ import type { SelectOption, SpacerOption } from '@viaa/avo2-components'; import { Form, FormGroup, Select } from '@viaa/avo2-components'; import type { FunctionComponent } from 'react'; import React from 'react'; - -import type { PaddingFieldState } from '../../../types/content-block.types'; - import { tHtml } from '~shared/helpers/translation-functions'; +import type { PaddingFieldState } from '../../../types/content-block.types'; import './PaddingSelectTopBottom.scss'; diff --git a/ui/src/react-admin/modules/content-page/const/content-block-config-map.ts b/ui/src/react-admin/modules/content-page/const/content-block-config-map.ts index d81d8bd91..470d2a55d 100644 --- a/ui/src/react-admin/modules/content-page/const/content-block-config-map.ts +++ b/ui/src/react-admin/modules/content-page/const/content-block-config-map.ts @@ -1,4 +1,4 @@ -import { ANCHOR_LINKS_BLOCK_CONFIG } from '~content-blocks/anchor-links'; +import { ANCHOR_LINKS_BLOCK_CONFIG } from '~content-blocks/anchor-links.ts'; import { AVO_HERO_BLOCK_CONFIG } from '~content-blocks/BlockAvoHero'; import { AVO_IMAGE_TEXT_BACKGROUND_BLOCK_CONFIG } from '~content-blocks/BlockAvoImageTextBackground'; import { CONTENT_BREADCRUMBS_CONFIG } from '~content-blocks/BlockBreadcrumbs'; @@ -24,6 +24,7 @@ import { KLAAR_BLOCK_CONFIG } from '~content-blocks/BlockKlaar'; import { MAINTAINERS_GRID_BLOCK_CONFIG } from '~content-blocks/BlockMaintainersGrid'; import { MEDIA_GRID_BLOCK_CONFIG } from '~content-blocks/BlockMediaGrid'; import { OVERVIEW_NEWSPAPER_TITLES_BLOCK_CONFIG } from '~content-blocks/BlockOverviewNewspaperTitles'; +import { CONTENT_OVERVIEW_WITH_CAROUSEL_CONFIG } from '~content-blocks/BlockOverviewWithCarousel'; import { QUOTE_BLOCK_CONFIG } from '~content-blocks/BlockQuote'; import { RICH_TEXT_BLOCK_CONFIG, @@ -85,4 +86,5 @@ export const CONTENT_BLOCK_CONFIG_MAP: Record< [ContentBlockType.ContentEncloseGrid]: CONTENT_ENCLOSE_BLOCK_CONFIG, [ContentBlockType.Breadcrumbs]: CONTENT_BREADCRUMBS_CONFIG, [ContentBlockType.ScrollDownNudge]: CONTENT_SCROLL_DOWN_NUDGE_CONFIG, + [ContentBlockType.OverviewWithCarousel]: CONTENT_OVERVIEW_WITH_CAROUSEL_CONFIG, }; diff --git a/ui/src/react-admin/modules/content-page/const/content-block-initial-state-map.ts b/ui/src/react-admin/modules/content-page/const/content-block-initial-state-map.ts index e58d1ad57..a864713a5 100644 --- a/ui/src/react-admin/modules/content-page/const/content-block-initial-state-map.ts +++ b/ui/src/react-admin/modules/content-page/const/content-block-initial-state-map.ts @@ -24,6 +24,7 @@ import { INITIAL_KLAAR_COMPONENTS_STATE } from '~content-blocks/BlockKlaar'; import { INITIAL_MAINTAINERS_GRID_BLOCK_STATE } from '~content-blocks/BlockMaintainersGrid'; import { INITIAL_MEDIA_GRID_COMPONENTS_STATE } from '~content-blocks/BlockMediaGrid'; import { INITIAL_OVERVIEW_NEWSPAPER_TITLES_BLOCK_STATE } from '~content-blocks/BlockOverviewNewspaperTitles'; +import { INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_BLOCK_STATE } from '~content-blocks/BlockOverviewWithCarousel/BlockOverviewWithCarousel.editorconfig.ts'; import { INITIAL_PAGE_OVERVIEW_COMPONENTS_STATE } from '~content-blocks/BlockPageOverview'; import { INITIAL_QUOTE_COMPONENTS_STATE } from '~content-blocks/BlockQuote'; import { @@ -88,4 +89,5 @@ export const CONTENT_BLOCK_INITIAL_STATE_MAP: { [ContentBlockType.ContentEncloseGrid]: INITIAL_CONTENT_ENCLOSE_BLOCK_STATE, [ContentBlockType.Breadcrumbs]: INITIAL_BREADCRUMBS_BLOCK_STATE, [ContentBlockType.ScrollDownNudge]: INITIAL_SCROLL_DOWN_NUDGE_BLOCK_STATE, + [ContentBlockType.OverviewWithCarousel]: INITIAL_CONTENT_OVERVIEW_WITH_CAROUSEL_BLOCK_STATE, }; diff --git a/ui/src/react-admin/modules/content-page/const/get-content-block-type-options.ts b/ui/src/react-admin/modules/content-page/const/get-content-block-type-options.ts index f1b5331eb..94bcf7c77 100644 --- a/ui/src/react-admin/modules/content-page/const/get-content-block-type-options.ts +++ b/ui/src/react-admin/modules/content-page/const/get-content-block-type-options.ts @@ -176,6 +176,14 @@ export const GET_CONTENT_BLOCK_TYPE_OPTIONS: () => SelectOption[] = () = label: tText('modules/content-page/const/get-content-block-type-options___scroll-down-nudge'), value: ContentBlockType.ScrollDownNudge, }, + { + label: tText( + 'modules/content-page/const/get-content-block-type-options___overzicht-met-carousel', + {}, + [HET_ARCHIEF] + ), + value: ContentBlockType.OverviewWithCarousel, + }, ]; // Only show the content blocks that the client enabled through the config object diff --git a/ui/src/react-admin/modules/content-page/types/content-block.types.ts b/ui/src/react-admin/modules/content-page/types/content-block.types.ts index c6e6dd3f7..534dfefaf 100644 --- a/ui/src/react-admin/modules/content-page/types/content-block.types.ts +++ b/ui/src/react-admin/modules/content-page/types/content-block.types.ts @@ -174,6 +174,7 @@ export enum ContentBlockType { Breadcrumbs = 'BREADCRUMBS', AvoImageTextBackground = 'AVO_IMAGE_TEXT_BACKGROUND', // Avo ScrollDownNudge = 'SCROLL_DOWN_NUDGE', + OverviewWithCarousel = 'OVERVIEW_WITH_CAROUSEL', } export enum ContentBlockEditor { diff --git a/ui/src/react-admin/modules/maintenance-alerts/views/MaintenanceAlertsEditForm.tsx b/ui/src/react-admin/modules/maintenance-alerts/views/MaintenanceAlertsEditForm.tsx index 3c1de5490..e086022f9 100644 --- a/ui/src/react-admin/modules/maintenance-alerts/views/MaintenanceAlertsEditForm.tsx +++ b/ui/src/react-admin/modules/maintenance-alerts/views/MaintenanceAlertsEditForm.tsx @@ -13,6 +13,7 @@ import type { FunctionComponent } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react'; import DatePicker from 'react-datepicker'; import { ValidationError } from 'yup'; +import { AdminConfigManager } from '~core/config'; import { ToastType } from '~core/config/config.types'; import { getDatePickerDefaultProps } from '~modules/content-page/components/DatePicker/DatePicker.consts'; import { MaintenanceAlertsService } from '~modules/maintenance-alerts/maintenance-alerts.service'; @@ -41,7 +42,6 @@ import { GET_ALERTS_ICON_OPTIONS, RICH_TEXT_EDITOR_OPTIONS, } from '../maintenance-alerts.const'; -import { AdminConfigManager } from '~core/config'; const MaintenanceAlertsEditForm: FunctionComponent = ({ maintenanceAlert, diff --git a/ui/src/react-admin/modules/shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal.tsx b/ui/src/react-admin/modules/shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal.tsx index b690502d2..6552da7db 100644 --- a/ui/src/react-admin/modules/shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal.tsx +++ b/ui/src/react-admin/modules/shared/components/AddOrRemoveLinkedElementsModal/AddOrRemoveLinkedElementsModal.tsx @@ -1,6 +1,3 @@ -import type { FunctionComponent } from 'react'; -import React, { useState } from 'react'; - import type { TagInfo } from '@viaa/avo2-components'; import { Button, @@ -16,6 +13,8 @@ import { ToolbarItem, ToolbarRight, } from '@viaa/avo2-components'; +import type { FunctionComponent } from 'react'; +import React, { useState } from 'react'; import { tText } from '~shared/helpers/translation-functions'; export type AddOrRemove = 'add' | 'remove'; diff --git a/ui/src/react-admin/modules/shared/components/MoreOptionsDropdown/MoreOptionsDropdown.tsx b/ui/src/react-admin/modules/shared/components/MoreOptionsDropdown/MoreOptionsDropdown.tsx index 254955322..2883855b5 100644 --- a/ui/src/react-admin/modules/shared/components/MoreOptionsDropdown/MoreOptionsDropdown.tsx +++ b/ui/src/react-admin/modules/shared/components/MoreOptionsDropdown/MoreOptionsDropdown.tsx @@ -1,8 +1,3 @@ -import type { FunctionComponent } from 'react'; -import React from 'react'; - -import { tText } from '~shared/helpers/translation-functions'; - import type { IconName, MenuItemInfo } from '@viaa/avo2-components'; import { Button, @@ -11,6 +6,9 @@ import { DropdownContent, MenuContent, } from '@viaa/avo2-components'; +import type { FunctionComponent } from 'react'; +import React from 'react'; +import { tText } from '~shared/helpers/translation-functions'; export interface MoreOptionsDropdownProps { isOpen: boolean; diff --git a/ui/src/react-admin/modules/shared/components/MultiUserSelectDropdown/MultiUserSelectDropdown.tsx b/ui/src/react-admin/modules/shared/components/MultiUserSelectDropdown/MultiUserSelectDropdown.tsx index 39a58b8e4..9c9127389 100644 --- a/ui/src/react-admin/modules/shared/components/MultiUserSelectDropdown/MultiUserSelectDropdown.tsx +++ b/ui/src/react-admin/modules/shared/components/MultiUserSelectDropdown/MultiUserSelectDropdown.tsx @@ -18,9 +18,9 @@ import React, { useEffect, useState } from 'react'; import { ToastType } from '~core/config/config.types'; import { showToast } from '~shared/helpers/show-toast'; import { tText } from '~shared/helpers/translation-functions'; -import { useGetNamesByProfileIds } from './hooks/useGetNamesByProfileIds'; import type { PickerItem } from '../../types/content-picker'; import { ContentPicker } from '../ContentPicker/ContentPicker'; +import { useGetNamesByProfileIds } from './hooks/useGetNamesByProfileIds'; import './MultiUserSelectDropdown.scss'; import { AvoCoreContentPickerType } from '@viaa/avo2-types'; diff --git a/ui/src/react-admin/modules/shared/components/SmartLink/SmartLink.tsx b/ui/src/react-admin/modules/shared/components/SmartLink/SmartLink.tsx index d4da62d9f..813c7dc83 100644 --- a/ui/src/react-admin/modules/shared/components/SmartLink/SmartLink.tsx +++ b/ui/src/react-admin/modules/shared/components/SmartLink/SmartLink.tsx @@ -1,16 +1,17 @@ +import { keysSpacebar, onKey } from '@meemoo/react-components'; import type { ButtonAction } from '@viaa/avo2-components'; import type { AvoCoreContentPickerType } from '@viaa/avo2-types'; import clsx from 'clsx'; import { map } from 'es-toolkit/compat'; import { stringify } from 'query-string'; -import { +import React, { type FunctionComponent, + type KeyboardEvent, type ReactElement, type ReactNode, useEffect, useState, } from 'react'; -import React from 'react'; import { AdminConfigManager } from '~core/config'; import { getAdminCoreApiUrl } from '~shared/helpers/get-proxy-url-from-admin-core-config'; import { isServerSideRendering } from '~shared/helpers/routing/is-server-side-rendering'; @@ -27,6 +28,7 @@ export interface SmartLinkProps { ariaLabel?: string; className?: string; children: ReactNode; + tabIndex?: number; } export const SmartLink: FunctionComponent = ({ @@ -36,6 +38,7 @@ export const SmartLink: FunctionComponent = ({ children, className, ariaLabel, + tabIndex, }) => { const location = useLocation(); @@ -67,6 +70,11 @@ export const SmartLink: FunctionComponent = ({ fullUrl = fullUrl.replace(clientUrlWithoutProtocol, ''); } + const onKeyUpHandler = (evt: KeyboardEvent) => + onKey(evt, keysSpacebar, () => { + (evt.target as HTMLElement).click(); + }); + switch (target) { case LinkTarget.Self: // Open inside same tab @@ -80,6 +88,8 @@ export const SmartLink: FunctionComponent = ({ aria-label={ariaLabel} className={clsx(className, { 'a-link__no-styles': removeStyles })} onClick={() => AdminConfigManager.getConfig().handlers.onExternalLink(fullUrl)} + onKeyUp={onKeyUpHandler} + tabIndex={tabIndex} > {children} @@ -102,6 +112,8 @@ export const SmartLink: FunctionComponent = ({ scrollTo({ top: 0 }); } }} + onKeyUp={(evt) => onKeyUpHandler(evt as unknown as KeyboardEvent)} + tabIndex={tabIndex} > {children} @@ -118,6 +130,8 @@ export const SmartLink: FunctionComponent = ({ title={title} className={clsx(className, { 'a-link__no-styles': removeStyles })} onClick={() => AdminConfigManager.getConfig().handlers.onExternalLink(fullUrl)} + onKeyUp={onKeyUpHandler} + tabIndex={tabIndex} > {children} @@ -132,6 +146,8 @@ export const SmartLink: FunctionComponent = ({ title={title} className={clsx(className, { 'a-link__no-styles': removeStyles })} onClick={() => AdminConfigManager.getConfig().handlers.onExternalLink(fullUrl)} + onKeyUp={onKeyUpHandler} + tabIndex={tabIndex} > {children} @@ -250,7 +266,8 @@ export const generateSmartLink = ( action: ButtonAction | null | undefined, children: ReactNode, title?: string, - className?: string + className?: string, + tabIndex?: number // biome-ignore lint/suspicious/noExplicitAny: todo ): ReactElement | null => { return ( @@ -259,6 +276,7 @@ export const generateSmartLink = ( title={title} className={className} key={`smart-link-${action?.value}-${title}-${className}`} + tabIndex={tabIndex} > {children} diff --git a/ui/src/react-admin/modules/shared/helpers/sanitize/index.ts b/ui/src/react-admin/modules/shared/helpers/sanitize/index.ts index 949f97b0a..e4b4d514e 100644 --- a/ui/src/react-admin/modules/shared/helpers/sanitize/index.ts +++ b/ui/src/react-admin/modules/shared/helpers/sanitize/index.ts @@ -1,14 +1,14 @@ -import type { DOMPurifyI } from 'dompurify'; +import type { DOMPurify } from 'dompurify'; import { isServerSideRendering } from '~shared/helpers/routing/is-server-side-rendering'; import type { SanitizePreset } from './presets'; import sanitizePresets from './presets'; // biome-ignore lint/suspicious/noExplicitAny: This is a generic function that can be used for multiple types -function normalizeModule(requiredModule: any): DOMPurifyI { +function normalizeModule(requiredModule: any): DOMPurify { return requiredModule?.default || requiredModule; } -let domPurify: DOMPurifyI | undefined; +let domPurify: DOMPurify | undefined; let _domPurifyInitPromise: Promise | undefined; /** @@ -23,7 +23,7 @@ function initDOMPurify(): void { sanitize: (source: string, _preset: SanitizePreset): string => { return source; }, - } as unknown as DOMPurifyI; + } as unknown as DOMPurify; } else { // Start loading DOMPurify asynchronously _domPurifyInitPromise = import('dompurify').then((module) => { diff --git a/ui/src/react-admin/modules/shared/helpers/validation.ts b/ui/src/react-admin/modules/shared/helpers/validation.ts index 0f7cacb44..4deff10d8 100644 --- a/ui/src/react-admin/modules/shared/helpers/validation.ts +++ b/ui/src/react-admin/modules/shared/helpers/validation.ts @@ -64,3 +64,13 @@ export function validateFlowplayerVideoUrl(url: string | null | undefined) { } return []; } + +export function validateRequiredValue(value: string, emptyFieldValidatorMessage?: string) { + const errorArray: string[] = []; + + if (!value && emptyFieldValidatorMessage) { + errorArray.push(emptyFieldValidatorMessage); + } + + return errorArray; +} diff --git a/ui/src/react-admin/modules/translations/views/TranslationsOverview.tsx b/ui/src/react-admin/modules/translations/views/TranslationsOverview.tsx index 0d17d5fca..4e3277eaa 100644 --- a/ui/src/react-admin/modules/translations/views/TranslationsOverview.tsx +++ b/ui/src/react-admin/modules/translations/views/TranslationsOverview.tsx @@ -41,8 +41,8 @@ import { useGetAllLanguages } from '../hooks/use-get-all-languages'; import { TranslationsService } from '../translations.service'; import './TranslationsOverview.scss'; import { AvoSearchOrderDirection } from '@viaa/avo2-types'; -import { isHetArchief } from '~shared/helpers/is-hetarchief.ts'; import { AdminConfigManager } from '~core/config'; +import { isHetArchief } from '~shared/helpers/is-hetarchief.ts'; type OrderProp = `value_${Locale}` | 'id'; diff --git a/ui/src/routes.ts b/ui/src/routes.ts index 00146a26f..9af6cfbd2 100644 --- a/ui/src/routes.ts +++ b/ui/src/routes.ts @@ -1,5 +1,5 @@ import { asyncNoop } from 'es-toolkit'; -import { type MiddlewareFunction, redirect, type RouteObject } from 'react-router'; +import { type MiddlewareFunction, type RouteObject, redirect } from 'react-router'; import { Loading } from '~shared/components/Loading/Loading'; import { ROUTE_PARTS } from '~shared/consts'; import App from './App'; diff --git a/ui/src/shared/helpers/admin-core-config.tsx b/ui/src/shared/helpers/admin-core-config.tsx index a7086aace..c9e68078d 100644 --- a/ui/src/shared/helpers/admin-core-config.tsx +++ b/ui/src/shared/helpers/admin-core-config.tsx @@ -96,6 +96,7 @@ export function getAdminCoreConfigForLocalTestApp(navigateFunc: NavigateFunction // ContentBlockType.OverviewNewspaperTitles, // ContentBlockType.ContentEncloseGrid, // ContentBlockType.Breadcrumbs, + ContentBlockType.OverviewWithCarousel, ], defaultPageWidth: ContentPageWidth.LARGE, onSaveContentPage: async (contentPageInfo: ContentPageInfo) => { @@ -140,6 +141,7 @@ export function getAdminCoreConfigForLocalTestApp(navigateFunc: NavigateFunction sortTable: { name: 'sort-table' }, arrowDown: { name: 'arrow-down' }, arrowRight: { name: 'arrow-right' }, + arrowLeft: { name: 'arrow-left' }, chevronLeft: { name: 'chevron-left' }, check: { name: 'check' }, calendar: { name: 'calendar' }, diff --git a/ui/src/shared/types/index.ts b/ui/src/shared/types/index.ts index fb7643751..59a8fabb4 100644 --- a/ui/src/shared/types/index.ts +++ b/ui/src/shared/types/index.ts @@ -1,6 +1,5 @@ -import type { ReactElement, ReactNode } from 'react'; - import type { IconName } from '@viaa/avo2-components'; +import type { ReactElement, ReactNode } from 'react'; export type NavigationItemInfo = { label: string | ReactNode;