diff --git a/apps/cms/config/sync/entity_usage.settings.yml b/apps/cms/config/sync/entity_usage.settings.yml
index 575153e65..8f69040e1 100644
--- a/apps/cms/config/sync/entity_usage.settings.yml
+++ b/apps/cms/config/sync/entity_usage.settings.yml
@@ -5,8 +5,8 @@ local_task_enabled_entity_types:
- node
track_enabled_source_entity_types:
- node
- - content_moderation_state
- block_content
+ - content_moderation_state
- menu_link_content
- media
- redirect
@@ -14,8 +14,8 @@ track_enabled_source_entity_types:
- path_alias
track_enabled_target_entity_types:
- node
- - content_moderation_state
- block_content
+ - content_moderation_state
- menu_link_content
- media
- redirect
@@ -32,6 +32,8 @@ track_enabled_plugins:
- html_link
- ckeditor_image
- block_field
+ - gutenberg_linked_content
+ - gutenberg_referenced_content
- gutenberg_media_embed
track_enabled_base_fields: false
site_domains: { }
diff --git a/apps/cms/config/sync/linkit.linkit_profile.gutenberg.yml b/apps/cms/config/sync/linkit.linkit_profile.gutenberg.yml
index 844075fdc..4eded13a4 100644
--- a/apps/cms/config/sync/linkit.linkit_profile.gutenberg.yml
+++ b/apps/cms/config/sync/linkit.linkit_profile.gutenberg.yml
@@ -28,6 +28,6 @@ matchers:
bundles:
document: document
group_by_bundle: 0
- substitution_type: null
+ substitution_type: canonical
limit: '100'
weight: -9
diff --git a/apps/preview/.lagoon.env b/apps/preview/.lagoon.env
index 752e3109d..e10314091 100644
--- a/apps/preview/.lagoon.env
+++ b/apps/preview/.lagoon.env
@@ -1 +1,2 @@
+PROJECT_NAME="example"
DRUPAL_URL="https://nginx.${LAGOON_ENVIRONMENT}.${LAGOON_PROJECT}.ch4.amazee.io"
diff --git a/packages/drupal/custom/custom.module b/packages/drupal/custom/custom.module
index 030c5f087..07ac7bc44 100644
--- a/packages/drupal/custom/custom.module
+++ b/packages/drupal/custom/custom.module
@@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\RenderContext;
+use Drupal\Core\StreamWrapper\LocalStream;
+use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Drupal\Core\Utility\Error as ErrorUtil;
use Drupal\file\Entity\File;
use Drupal\media\Entity\Media;
@@ -90,6 +92,75 @@ function custom_silverback_gutenberg_link_processor_outbound_url_alter(
}
}
+/**
+ * Implements hook_silverback_gutenberg_link_processor_inbound_link_alter().
+ * @param \DOMElement $link
+ * @param \Drupal\silverback_gutenberg\LinkProcessor $linkProcessor
+ *
+ * @return void
+ * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
+ * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
+ */
+function custom_silverback_gutenberg_link_processor_inbound_link_alter(
+ \DOMElement $link,
+ LinkProcessor $linkProcessor
+) {
+ // For inbound links (when data gets saved), if the link points to a public
+ // file, then we want to replace the href value with "media/uuid/edit" and
+ // also make sure the data-id and data-entity-type attributes have the proper
+ // values (the uuid and the 'media' value). This is a special case for media,
+ // because the url of the media item is replaced by
+ // custom_silverback_gutenberg_link_processor_outbound_url_alter() with the
+ // file path, so now on inbound we need to basically do the opposite. This is
+ // needed so that the entity usage integration works properly (where the
+ // data-id and data-entity-type attributes are checked).
+ $href = $link->getAttribute('href');
+ /* @var \Drupal\Core\StreamWrapper\StreamWrapperManager $wrapperManager */
+ $wrapperManager = \Drupal::service('stream_wrapper_manager');
+ /* @var \Drupal\Core\StreamWrapper\StreamWrapperInterface[] $visibleWrappers */
+ $visibleWrappers = $wrapperManager->getWrappers(StreamWrapperInterface::VISIBLE);
+ foreach ($visibleWrappers as $scheme => $wrapperInfo) {
+ $wrapper = $wrapperManager->getViaScheme($scheme);
+ // We are only handle local streams for now.
+ if (!$wrapper instanceof LocalStream) {
+ continue;
+ }
+ if (!str_starts_with($href, '/' . $wrapper->getDirectoryPath() . '/')) {
+ continue;
+ }
+ // When searching for a file inside the database, the wrapper uri is used
+ // instead of the directory path. That is why we need the wrapper in the
+ // first place.
+ $fileuri = str_replace('/' . $wrapper->getDirectoryPath() . '/', $wrapper->getUri(), urldecode($href));
+ $files = \Drupal::entityTypeManager()
+ ->getStorage('file')
+ ->loadByProperties(['uri' => $fileuri]);
+ // No files found, just continue to the next wrapper.
+ if (empty($files)) {
+ continue;
+ }
+ $file = array_shift($files);
+ $usageList = \Drupal::service('file.usage')->listUsage($file);
+ // If the media file usage list is empty, then this is probably some kind of
+ // orphan file, or tracked by some other entity type.
+ if (empty($usageList['file']['media'])) {
+ continue;
+ }
+ $mids = array_keys($usageList['file']['media']);
+ $mid = reset($mids);
+ $media = Media::load($mid);
+ if (empty($media)) {
+ continue;
+ }
+ // If we got here, we found a matching media item, so we can populate the
+ // link metadata with its values and just break out of the wrappers loop.
+ $link->setAttribute('href', '/media/' . $media->uuid() . '/edit');
+ $link->setAttribute('data-id', $media->uuid());
+ $link->setAttribute('data-entity-type', 'media');
+ break;
+ }
+}
+
/**
* Implements hook_form_alter().
*
diff --git a/packages/drupal/gutenberg_blocks/src/blocks/info-grid-item.tsx b/packages/drupal/gutenberg_blocks/src/blocks/info-grid-item.tsx
index 5027a7214..bef7ba263 100644
--- a/packages/drupal/gutenberg_blocks/src/blocks/info-grid-item.tsx
+++ b/packages/drupal/gutenberg_blocks/src/blocks/info-grid-item.tsx
@@ -52,8 +52,9 @@ registerBlockType('custom/info-grid-item', {
)}
>
diff --git a/packages/drupal/test_content/content/node/25086be7-ca5f-4ff8-9695-b9c71a676d4e.yml b/packages/drupal/test_content/content/node/25086be7-ca5f-4ff8-9695-b9c71a676d4e.yml
index 5561d002f..0cceba025 100644
--- a/packages/drupal/test_content/content/node/25086be7-ca5f-4ff8-9695-b9c71a676d4e.yml
+++ b/packages/drupal/test_content/content/node/25086be7-ca5f-4ff8-9695-b9c71a676d4e.yml
@@ -4,6 +4,8 @@ _meta:
uuid: 25086be7-ca5f-4ff8-9695-b9c71a676d4e
bundle: page
default_langcode: en
+ depends:
+ b998ae5e-8b56-40ca-8f80-fd4404e7e716: media
default:
revision_uid:
-
@@ -47,7 +49,7 @@ default:
-
link to file
+ link to file
diff --git a/packages/drupal/test_content/content/node/3164a225-df20-4794-8cfc-b7cd81cfde58.yml b/packages/drupal/test_content/content/node/3164a225-df20-4794-8cfc-b7cd81cfde58.yml
new file mode 100644
index 000000000..160220cf3
--- /dev/null
+++ b/packages/drupal/test_content/content/node/3164a225-df20-4794-8cfc-b7cd81cfde58.yml
@@ -0,0 +1,142 @@
+_meta:
+ version: '1.0'
+ entity_type: node
+ uuid: 3164a225-df20-4794-8cfc-b7cd81cfde58
+ bundle: page
+ default_langcode: en
+ depends:
+ 3a0fe860-a6d6-428a-9474-365bd57509aa: media
+default:
+ revision_uid:
+ -
+ target_id: 1
+ status:
+ -
+ value: true
+ uid:
+ -
+ target_id: 1
+ title:
+ -
+ value: 'Info grid'
+ created:
+ -
+ value: 1716194667
+ promote:
+ -
+ value: false
+ sticky:
+ -
+ value: false
+ moderation_state:
+ -
+ value: published
+ path:
+ -
+ alias: /info-grid
+ langcode: en
+ pathauto: 0
+ content_translation_source:
+ -
+ value: und
+ content_translation_outdated:
+ -
+ value: false
+ body:
+ -
+ value: |-
+
+
+
+
+
+
+ I am a heading
+
+
+
+ I am the body
+
+
+
+
+
+
+
+ I am second heading
+
+
+
+ I am the second body
+
+
+
+
+
+
+
+ I am the third heading
+
+
+
+ I am the third body
+
+
+
+
+
+
+
+
+
+ Just one info grid
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ format: gutenberg
+ summary: ''
diff --git a/packages/drupal/test_content/content/node/a397ca48-8fad-411e-8901-0eba2feb989c.yml b/packages/drupal/test_content/content/node/a397ca48-8fad-411e-8901-0eba2feb989c.yml
index 23feb209b..f52ee74d0 100644
--- a/packages/drupal/test_content/content/node/a397ca48-8fad-411e-8901-0eba2feb989c.yml
+++ b/packages/drupal/test_content/content/node/a397ca48-8fad-411e-8901-0eba2feb989c.yml
@@ -7,47 +7,35 @@ _meta:
depends:
3a0fe860-a6d6-428a-9474-365bd57509aa: media
478c4289-961d-4ce8-85d6-578ae05f3019: media
- 72187a1f-3e48-4b45-a9b7-189c6fd7ee26: media
5dfc1856-e9e4-4f02-9cd6-9d888870ce1a: media
+ 72187a1f-3e48-4b45-a9b7-189c6fd7ee26: media
default:
revision_uid:
- -
- target_id: 1
+ - target_id: 1
status:
- -
- value: true
+ - value: true
uid:
- -
- target_id: 1
+ - target_id: 1
title:
- -
- value: 'Blocks: complete'
+ - value: 'Blocks: complete'
created:
- -
- value: 1686759493
+ - value: 1686759493
promote:
- -
- value: false
+ - value: false
sticky:
- -
- value: false
+ - value: false
moderation_state:
- -
- value: published
+ - value: published
path:
- -
- alias: /blocks-complete
+ - alias: /blocks-complete
langcode: en
pathauto: 0
content_translation_source:
- -
- value: und
+ - value: und
content_translation_outdated:
- -
- value: false
+ - value: false
body:
- -
- value: |-
+ - value: |-
@@ -107,7 +95,7 @@ default:
-
+
@@ -137,46 +125,82 @@ default:
+
+
+
+
+ Email us:
+
+
+
+ Email us for general queries, including marketing and partnership opportunities.
+
+
+
+ hello@company.com
+
+
+
+
+
+
+
+ Call us:
+
+
+
+ Call us to speak to a member of our team. We are always happy to help.
+
+
+
+ +1 (646) 786-5060
+
+
+
+
+
+
+
+ Support
+
+
+
+ Check out helpful resources, FAQs and developer tools.
+
+
+
+
+
+
format: gutenberg
summary: ''
translations:
de:
status:
- -
- value: true
+ - value: true
uid:
- -
- target_id: 1
+ - target_id: 1
title:
- -
- value: 'Blocks: complete DE'
+ - value: 'Blocks: complete DE'
created:
- -
- value: 1687338353
+ - value: 1687338353
promote:
- -
- value: false
+ - value: false
sticky:
- -
- value: false
+ - value: false
moderation_state:
- -
- value: published
+ - value: published
path:
- -
- alias: /blocks-complete
+ - alias: /blocks-complete
langcode: de
pathauto: 0
content_translation_source:
- -
- value: en
+ - value: en
content_translation_outdated:
- -
- value: false
+ - value: false
body:
- -
- value: |-
+ - value: |-
diff --git a/packages/schema/src/schema.graphql b/packages/schema/src/schema.graphql
index 92128a15b..1b71ce821 100644
--- a/packages/schema/src/schema.graphql
+++ b/packages/schema/src/schema.graphql
@@ -277,6 +277,18 @@ enum CTAIconPosition {
BEFORE
}
+type BlockImageWithText @type(id: "custom/image-with-text") {
+ image: MediaImage @resolveEditorBlockMedia
+ textContent: BlockMarkup @resolveEditorBlockChildren @seek(pos: 0)
+}
+
+type BlockQuote @type(id: "custom/quote") {
+ quote: Markup @resolveEditorBlockAttribute(key: "quote")
+ author: String @resolveEditorBlockAttribute(key: "author")
+ role: String @resolveEditorBlockAttribute(key: "role")
+ image: MediaImage @resolveEditorBlockMedia
+}
+
type BlockImageWithText @type(id: "custom/image-with-text") {
image: MediaImage @resolveEditorBlockMedia
imagePosition: ImagePosition!
@@ -301,6 +313,7 @@ enum InfoGridIcon @default @value(string: "EMAIL") {
PHONE
LIFE_RING
}
+
type BlockInfoGrid @type(id: "custom/info-grid") {
gridItems: [BlockInfoGridItem]! @resolveEditorBlockChildren
}
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 967e148ea..99ff25abb 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -40,11 +40,10 @@
"dependencies": {
"@amazeelabs/silverback-iframe": "^1.3.0",
"@custom/schema": "workspace:*",
- "@headlessui/react": "^1.7.17",
+ "@headlessui/react": "^2.0.3",
"@heroicons/react": "^2.1.1",
"@hookform/resolvers": "^3.3.3",
"clsx": "^2.1.0",
- "flowbite-react": "^0.9.0",
"framer-motion": "^10.17.4",
"hast-util-is-element": "^2.1.3",
"hast-util-select": "^5.0.5",
diff --git a/packages/ui/src/components/Client/DesktopMenu.tsx b/packages/ui/src/components/Client/DesktopMenu.tsx
index dc6442c48..756031972 100644
--- a/packages/ui/src/components/Client/DesktopMenu.tsx
+++ b/packages/ui/src/components/Client/DesktopMenu.tsx
@@ -1,5 +1,14 @@
'use client';
-import { Disclosure, Popover, Transition } from '@headlessui/react';
+import {
+ Disclosure,
+ DisclosureButton,
+ DisclosurePanel,
+ Popover,
+ PopoverButton,
+ PopoverGroup,
+ PopoverPanel,
+ Transition,
+} from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/20/solid';
import clsx from 'clsx';
import React, { PropsWithChildren } from 'react';
@@ -8,9 +17,9 @@ import { avoidFocusOnClick } from '../../utils/avoidFocusOnClick';
export function DesktopMenu({ children }: PropsWithChildren<{}>) {
return (
-
+
{children}
-
+
);
}
@@ -21,8 +30,8 @@ export function DesktopMenuDropDown({
return (
{({ open }) => (
-
-
+
-
+
-
+
{children}
-
+
-
+ >
)}
);
@@ -68,7 +74,7 @@ export function DesktopMenuDropdownDisclosure({
{({ open }) => (
-
-
- {children}
+
+ {children}
)}
diff --git a/packages/ui/src/components/Client/MobileMenu.tsx b/packages/ui/src/components/Client/MobileMenu.tsx
index 9652da9de..022402639 100644
--- a/packages/ui/src/components/Client/MobileMenu.tsx
+++ b/packages/ui/src/components/Client/MobileMenu.tsx
@@ -1,5 +1,11 @@
'use client';
-import { Dialog, Disclosure } from '@headlessui/react';
+import {
+ Dialog,
+ DialogPanel,
+ Disclosure,
+ DisclosureButton,
+ DisclosurePanel,
+} from '@headlessui/react';
import { ChevronDownIcon } from '@heroicons/react/20/solid';
import clsx from 'clsx';
import React, { createContext, PropsWithChildren } from 'react';
@@ -11,7 +17,7 @@ const MobileMenuContext = createContext({
setIsOpen: (isOpen: boolean) => {},
});
-export function MobileMenuProvider({ children }: PropsWithChildren) {
+export function MobileMenuProvider({ children }: PropsWithChildren<{}>) {
const [isOpen, setIsOpen] = React.useState(false);
return (
@@ -42,14 +48,15 @@ export function MobileMenuButton(
);
}
+
export function MobileMenu({ children }: PropsWithChildren<{}>) {
const { isOpen, setIsOpen } = React.useContext(MobileMenuContext);
return (
-
+
{children}
-
+
);
}
@@ -62,13 +69,13 @@ export function MobileMenuLink({
title: string;
}) {
return (
-
{title}
-
+
);
}
@@ -86,15 +93,13 @@ export function MobileMenuDropdown({
open && nestLevel === 2 && 'bg-gray-100 rounded mx-8',
)}
>
-
-
- {children}
+
+ {children}
)}
diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx
index 60cde5299..994fad5dd 100644
--- a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx
+++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx
@@ -1,11 +1,18 @@
+'use client';
import { BlockAccordionFragment, Html } from '@custom/schema';
+import {
+ Disclosure,
+ DisclosureButton,
+ DisclosurePanel,
+} from '@headlessui/react';
import {
ArrowRightCircleIcon,
CheckCircleIcon,
+ ChevronDownIcon,
+ ChevronUpIcon,
QuestionMarkCircleIcon,
} from '@heroicons/react/20/solid';
import clsx from 'clsx';
-import { Accordion, CustomFlowbiteTheme, Flowbite } from 'flowbite-react';
import type { Element } from 'hast';
import { selectAll } from 'hast-util-select';
import React, { PropsWithChildren } from 'react';
@@ -17,53 +24,39 @@ const unorderedItems: Plugin<[], Element> = () => (tree) => {
});
};
-const accordionTheme: CustomFlowbiteTheme['accordion'] = {
- root: {
- base: 'mt-10 divide-y divide-gray-200 border-gray-200',
- flush: {
- off: 'last:border-0',
- on: 'last:border-0',
- },
- },
- content: {
- base: 'pb-5 pt-5 text-base font-normal text-gray-500',
- },
- title: {
- base: 'flex w-full items-center justify-between p-4 pl-1 text-left font-medium text-lg text-gray-500',
- flush: {
- off: 'hover:bg-gray-100',
- on: 'bg-transparent',
- },
- heading: '',
- open: {
- off: '',
- on: 'text-gray-900',
- },
- },
-};
-
-// Applying the custom theme to the Accordion component
-// doesn't work out, wrapping it in a Flowbite component.
-const theme: CustomFlowbiteTheme = {
- accordion: accordionTheme,
-};
-
export function BlockAccordion(props: BlockAccordionFragment) {
return (
-
+
-
-
- {props.items.map((item, index) => (
-
-
+ {props.items.map((item, index) => (
+
+ {({ open }) => (
+ <>
+
{item.icon && }{' '}
{item.title}
-
-
+
+ {open ? (
+
+ ) : (
+
+ )}
+
+
+
{item.textContent?.markup && (
)}
-
-
- ))}
-
-
+
+ >
+ )}
+
+ ))}
diff --git a/packages/ui/src/components/Organisms/PageContent/BlockImageTeasers.stories.tsx b/packages/ui/src/components/Organisms/PageContent/BlockImageTeasers.stories.tsx
new file mode 100644
index 000000000..6b90bf401
--- /dev/null
+++ b/packages/ui/src/components/Organisms/PageContent/BlockImageTeasers.stories.tsx
@@ -0,0 +1,36 @@
+import { Url } from '@custom/schema';
+import Landscape from '@stories/landscape.jpg?as=metadata';
+import Portrait from '@stories/portrait.jpg?as=metadata';
+import { Meta, StoryObj } from '@storybook/react';
+
+import { image } from '../../../helpers/image';
+import { BlockImageTeasers } from './BlockImageTeasers';
+
+export default {
+ component: BlockImageTeasers,
+} satisfies Meta;
+
+export const Default = {
+ args: {
+ teasers: [
+ {
+ title: 'Title',
+ ctaText: 'Call to action',
+ ctaUrl: '/test' as Url,
+ image: {
+ source: image(Landscape),
+ alt: 'Alt text',
+ },
+ },
+ {
+ title: 'Title',
+ ctaText: 'Call to action',
+ ctaUrl: '/test' as Url,
+ image: {
+ source: image(Portrait),
+ alt: 'Alt text',
+ },
+ },
+ ],
+ },
+} satisfies StoryObj;
diff --git a/packages/ui/src/components/Organisms/PageContent/BlockImageTeasers.tsx b/packages/ui/src/components/Organisms/PageContent/BlockImageTeasers.tsx
new file mode 100644
index 000000000..0b3472b57
--- /dev/null
+++ b/packages/ui/src/components/Organisms/PageContent/BlockImageTeasers.tsx
@@ -0,0 +1,55 @@
+import { BlockImageTeasersFragment, Image, Link } from '@custom/schema';
+import React from 'react';
+
+import { isTruthy } from '../../../utils/isTruthy';
+
+export function BlockImageTeasers(props: BlockImageTeasersFragment) {
+ return (
+ // eslint-disable-next-line tailwindcss/no-custom-classname
+
+
+
+ {props.teasers.filter(isTruthy).map((teaser, index) => (
+
+ ))}
+
+
+
+ );
+}
+
+// This component uses the following Flowbite component:
+// https://flowbite.com/blocks/marketing/hero/#background-image-cards
+export function BlockImageTeaser(
+ props: BlockImageTeasersFragment['teasers'][0],
+) {
+ return (
+
+ {props.image ? (
+
+ ) : null}
+
+
+ {props.title ? (
+
+ {props.title}
+
+ ) : null}
+
+ {props.ctaUrl && props.ctaText ? (
+
+ {props.ctaText}
+
+ ) : null}
+
+
+ );
+}
diff --git a/packages/ui/src/components/Organisms/PageDisplay.tsx b/packages/ui/src/components/Organisms/PageDisplay.tsx
index e1e5c326e..203452462 100644
--- a/packages/ui/src/components/Organisms/PageDisplay.tsx
+++ b/packages/ui/src/components/Organisms/PageDisplay.tsx
@@ -9,6 +9,7 @@ import { BlockAccordion } from './PageContent/BlockAccordion';
import { BlockCta } from './PageContent/BlockCta';
import { BlockForm } from './PageContent/BlockForm';
import { BlockHorizontalSeparator } from './PageContent/BlockHorizontalSeparator';
+import { BlockImageTeasers } from './PageContent/BlockImageTeasers';
import { BlockImageWithText } from './PageContent/BlockImageWithText';
import { BlockInfoGrid } from './PageContent/BlockInfoGrid';
import { BlockMarkup } from './PageContent/BlockMarkup';
@@ -31,20 +32,17 @@ export function PageDisplay(page: PageFragment) {
case 'BlockForm':
return ;
case 'BlockImageTeasers':
- return (
- // TODO: Implement BlockImageTeasers
-
- BlockImageTeasers goes here
-
- );
+ return ;
+ case 'BlockCta':
+ return ;
+ case 'BlockImageWithText':
+ return ;
+ case 'BlockQuote':
+ return ;
+ case 'BlockHorizontalSeparator':
+ return ;
+ case 'BlockAccordion':
+ return ;
case 'BlockCta':
return ;
case 'BlockImageWithText':
diff --git a/packages/ui/src/components/Organisms/PageHero.tsx b/packages/ui/src/components/Organisms/PageHero.tsx
index 9004af958..237765e00 100644
--- a/packages/ui/src/components/Organisms/PageHero.tsx
+++ b/packages/ui/src/components/Organisms/PageHero.tsx
@@ -17,7 +17,7 @@ export function PageHero(props: NonNullable) {
function DefaultHero(props: NonNullable) {
return (
<>
-
+
{props.image ? (
['content'],
},
},
diff --git a/packages/ui/src/tailwind.css b/packages/ui/src/tailwind.css
index f977bbc41..18682f9a6 100644
--- a/packages/ui/src/tailwind.css
+++ b/packages/ui/src/tailwind.css
@@ -35,3 +35,11 @@
)::after {
content: '' !important;
}
+
+/*
+ Selects the .block-background-image-cards only when it is the direct
+ sibling of .default-hero section.
+ */
+.default-hero + .block-background-image-cards {
+ @apply mt-2 px-0;
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 642d8ebde..e274343f9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -521,8 +521,8 @@ importers:
specifier: workspace:*
version: link:../schema
'@headlessui/react':
- specifier: ^1.7.17
- version: 1.7.17(react-dom@18.2.0)(react@18.2.0)
+ specifier: ^2.0.3
+ version: 2.0.3(react-dom@18.2.0)(react@18.2.0)
'@heroicons/react':
specifier: ^2.1.1
version: 2.1.1(react@18.2.0)
@@ -532,9 +532,6 @@ importers:
clsx:
specifier: ^2.1.0
version: 2.1.0
- flowbite-react:
- specifier: ^0.9.0
- version: 0.9.0(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.4.0)
framer-motion:
specifier: ^10.17.4
version: 10.17.4(react-dom@18.2.0)(react@18.2.0)
@@ -4178,8 +4175,8 @@ packages:
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
- /@floating-ui/react@0.26.10(react-dom@18.2.0)(react@18.2.0):
- resolution: {integrity: sha512-sh6f9gVvWQdEzLObrWbJ97c0clJObiALsFe0LiR/kb3tDRKwEhObASEH2QyfdoO/ZBPzwxa9j+nYFo+sqgbioA==}
+ /@floating-ui/react@0.26.15(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-WKmfLkxTwCm09Dxq4LpjL3EPbZVSp5wvnap1jmculsfnzg2Ag/pCkP+OPyjE5dFMXqX97hsLIqJehboZ5XAHXw==}
peerDependencies:
react: '>=16.8.0'
react-dom: '>=16.8.0'
@@ -5193,14 +5190,17 @@ packages:
'@hapi/hoek': 11.0.4
dev: false
- /@headlessui/react@1.7.17(react-dom@18.2.0)(react@18.2.0):
- resolution: {integrity: sha512-4am+tzvkqDSSgiwrsEpGWqgGo9dz8qU5M3znCkC4PgkpY4HcCZzEDEvozltGGGHIKl9jbXbZPSH5TWn4sWJdow==}
+ /@headlessui/react@2.0.3(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-Xd1h0YZgfhxZ7W1w4TvK0/TZ1c4qaX4liYVUkAXqW1HCLcXSqnMeYAUGJS/BBroBAUL9HErjyFcRpCWRQZ/0lA==}
engines: {node: '>=10'}
peerDependencies:
- react: ^16 || ^17 || ^18
- react-dom: ^16 || ^17 || ^18
+ react: ^18
+ react-dom: ^18
dependencies:
- client-only: 0.0.1
+ '@floating-ui/react': 0.26.15(react-dom@18.2.0)(react@18.2.0)
+ '@react-aria/focus': 3.17.0(react@18.2.0)
+ '@react-aria/interactions': 3.21.2(react@18.2.0)
+ '@tanstack/react-virtual': 3.5.0(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
@@ -7285,10 +7285,6 @@ packages:
resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
dev: true
- /@popperjs/core@2.11.8:
- resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
- dev: false
-
/@radix-ui/number@1.0.1:
resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==}
dependencies:
@@ -7849,6 +7845,54 @@ packages:
'@babel/runtime': 7.24.4
dev: true
+ /@react-aria/focus@3.17.0(react@18.2.0):
+ resolution: {integrity: sha512-aRzBw1WTUkcIV3xFrqPA6aB8ZVt3XyGpTaSHAypU0Pgoy2wRq9YeJYpbunsKj9CJmskuffvTqXwAjTcaQish1Q==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
+ dependencies:
+ '@react-aria/interactions': 3.21.2(react@18.2.0)
+ '@react-aria/utils': 3.24.0(react@18.2.0)
+ '@react-types/shared': 3.23.0(react@18.2.0)
+ '@swc/helpers': 0.5.11
+ clsx: 2.1.0
+ react: 18.2.0
+ dev: false
+
+ /@react-aria/interactions@3.21.2(react@18.2.0):
+ resolution: {integrity: sha512-Ju706DtoEmI/2vsfu9DCEIjDqsRBVLm/wmt2fr0xKbBca7PtmK8daajxFWz+eTq+EJakvYfLr7gWgLau9HyWXg==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
+ dependencies:
+ '@react-aria/ssr': 3.9.3(react@18.2.0)
+ '@react-aria/utils': 3.24.0(react@18.2.0)
+ '@react-types/shared': 3.23.0(react@18.2.0)
+ '@swc/helpers': 0.5.11
+ react: 18.2.0
+ dev: false
+
+ /@react-aria/ssr@3.9.3(react@18.2.0):
+ resolution: {integrity: sha512-5bUZ93dmvHFcmfUcEN7qzYe8yQQ8JY+nHN6m9/iSDCQ/QmCiE0kWXYwhurjw5ch6I8WokQzx66xKIMHBAa4NNA==}
+ engines: {node: '>= 12'}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
+ dependencies:
+ '@swc/helpers': 0.5.11
+ react: 18.2.0
+ dev: false
+
+ /@react-aria/utils@3.24.0(react@18.2.0):
+ resolution: {integrity: sha512-JAxkPhK5fCvFVNY2YG3TW3m1nTzwRcbz7iyTSkUzLFat4N4LZ7Kzh7NMHsgeE/oMOxd8zLY+XsUxMu/E/2GujA==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
+ dependencies:
+ '@react-aria/ssr': 3.9.3(react@18.2.0)
+ '@react-stately/utils': 3.10.0(react@18.2.0)
+ '@react-types/shared': 3.23.0(react@18.2.0)
+ '@swc/helpers': 0.5.11
+ clsx: 2.1.0
+ react: 18.2.0
+ dev: false
+
/@react-dnd/asap@4.0.1:
resolution: {integrity: sha512-kLy0PJDDwvwwTXxqTFNAAllPHD73AycE9ypWeln/IguoGBEbvFcPDbCV03G52bEcC5E+YgupBE0VzHGdC8SIXg==}
dev: false
@@ -7861,6 +7905,23 @@ packages:
resolution: {integrity: sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==}
dev: false
+ /@react-stately/utils@3.10.0(react@18.2.0):
+ resolution: {integrity: sha512-nji2i9fTYg65ZWx/3r11zR1F2tGya+mBubRCbMTwHyRnsSLFZaeq/W6lmrOyIy1uMJKBNKLJpqfmpT4x7rw6pg==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
+ dependencies:
+ '@swc/helpers': 0.5.11
+ react: 18.2.0
+ dev: false
+
+ /@react-types/shared@3.23.0(react@18.2.0):
+ resolution: {integrity: sha512-GQm/iPiii3ikcaMNR4WdVkJ4w0mKtV3mLqeSfSqzdqbPr6vONkqXbh3RhPlPmAJs1b4QHnexd/wZQP3U9DHOwQ==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
/@reduxjs/toolkit@1.9.7(react-redux@7.2.9)(react@18.2.0):
resolution: {integrity: sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==}
peerDependencies:
@@ -9309,6 +9370,12 @@ packages:
legacy-swc-helpers: /@swc/helpers@0.4.14
tslib: 2.6.2
+ /@swc/helpers@0.5.11:
+ resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==}
+ dependencies:
+ tslib: 2.6.2
+ dev: false
+
/@swc/jest@0.2.36(@swc/core@1.4.13):
resolution: {integrity: sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw==}
engines: {npm: '>= 7.0.0'}
@@ -9388,6 +9455,21 @@ packages:
resolution: {integrity: sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==}
dev: true
+ /@tanstack/react-virtual@3.5.0(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-rtvo7KwuIvqK9zb0VZ5IL7fiJAEnG+0EiFZz8FUOs+2mhGqdGmjKIaT1XU7Zq0eFqL0jonLlhbayJI/J2SA/Bw==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ '@tanstack/virtual-core': 3.5.0
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
+ /@tanstack/virtual-core@3.5.0:
+ resolution: {integrity: sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==}
+ dev: false
+
/@testing-library/dom@9.3.4:
resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==}
engines: {node: '>=14'}
@@ -10390,7 +10472,6 @@ packages:
typescript: 5.4.4
transitivePeerDependencies:
- supports-color
- dev: false
/@typescript-eslint/parser@6.17.0(eslint@7.0.0)(typescript@5.3.3):
resolution: {integrity: sha512-C4bBaX2orvhK+LlwrY8oWGmSl4WolCfYm513gEccdWZj0CwGadbIADb0FtVEcI+WzUyjyoBj2JRP8g25E6IB8A==}
@@ -10704,7 +10785,6 @@ packages:
typescript: 5.4.4
transitivePeerDependencies:
- supports-color
- dev: false
/@typescript-eslint/typescript-estree@6.17.0(typescript@5.3.3):
resolution: {integrity: sha512-gVQe+SLdNPfjlJn5VNGhlOhrXz4cajwFd5kAgWtZ9dCZf4XJf8xmgCTLIqec7aha3JwgLI2CK6GY1043FRxZwg==}
@@ -11035,7 +11115,7 @@ packages:
vite: ^4 || ^5
dependencies:
'@swc/core': 1.4.13
- vite: 5.0.10(@types/node@20.11.17)
+ vite: 5.0.10(@types/node@18.0.0)
transitivePeerDependencies:
- '@swc/helpers'
dev: true
@@ -13812,10 +13892,6 @@ packages:
static-extend: 0.1.2
dev: false
- /classnames@2.5.1:
- resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==}
- dev: false
-
/clean-deep@3.4.0:
resolution: {integrity: sha512-Lo78NV5ItJL/jl+B5w0BycAisaieJGXK1qYi/9m4SjR8zbqmrUtO7Yhro40wEShGmmxs/aJLI/A+jNhdkXK8mw==}
engines: {node: '>=4'}
@@ -15005,11 +15081,6 @@ packages:
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
dev: true
- /debounce@2.0.0:
- resolution: {integrity: sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==}
- engines: {node: '>=18'}
- dev: false
-
/debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
@@ -17125,7 +17196,7 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
- '@typescript-eslint/parser': 5.62.0(eslint@7.32.0)(typescript@4.9.5)
+ '@typescript-eslint/parser': 5.62.0(eslint@7.32.0)(typescript@5.4.4)
debug: 3.2.7
eslint: 7.32.0
eslint-import-resolver-node: 0.3.9
@@ -17232,7 +17303,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
- '@typescript-eslint/parser': 5.62.0(eslint@7.32.0)(typescript@4.9.5)
+ '@typescript-eslint/parser': 5.62.0(eslint@7.32.0)(typescript@5.4.4)
array-includes: 3.1.8
array.prototype.findlastindex: 1.2.5
array.prototype.flat: 1.3.2
@@ -18607,32 +18678,6 @@ packages:
engines: {node: '>=0.4.0'}
dev: true
- /flowbite-react@0.9.0(react-dom@18.2.0)(react@18.2.0)(tailwindcss@3.4.0):
- resolution: {integrity: sha512-wRGzTPHaEuRSXiAFhdTuksezABE/AjI/iyOOBGZpsFAz/sq7zuorAqjRud9FWgy3TlFPtldl7kL93wNY2nOnKQ==}
- peerDependencies:
- react: '>=18'
- react-dom: '>=18'
- tailwindcss: ^3
- dependencies:
- '@floating-ui/core': 1.6.0
- '@floating-ui/react': 0.26.10(react-dom@18.2.0)(react@18.2.0)
- classnames: 2.5.1
- debounce: 2.0.0
- flowbite: 2.3.0
- react: 18.2.0
- react-dom: 18.2.0(react@18.2.0)
- react-icons: 5.0.1(react@18.2.0)
- tailwind-merge: 2.2.2
- tailwindcss: 3.4.0
- dev: false
-
- /flowbite@2.3.0:
- resolution: {integrity: sha512-pm3JRo8OIJHGfFYWgaGpPv8E+UdWy0Z3gEAGufw+G/1dusaU/P1zoBLiQpf2/+bYAi+GBQtPVG86KYlV0W+AFQ==}
- dependencies:
- '@popperjs/core': 2.11.8
- mini-svg-data-uri: 1.4.4
- dev: false
-
/flush-write-stream@2.0.0:
resolution: {integrity: sha512-uXClqPxT4xW0lcdSBheb2ObVU+kuqUk3Jk64EwieirEXZx9XUrVwp/JuBfKAWaM4T5Td/VL7QLDWPXp/MvGm/g==}
dependencies:
@@ -24763,6 +24808,7 @@ packages:
/mini-svg-data-uri@1.4.4:
resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
hasBin: true
+ dev: true
/minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -26757,6 +26803,7 @@ packages:
postcss-value-parser: 4.2.0
read-cache: 1.0.0
resolve: 1.22.8
+ dev: true
/postcss-import@15.1.0(postcss@8.4.38):
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
@@ -26791,6 +26838,7 @@ packages:
dependencies:
camelcase-css: 2.0.1
postcss: 8.4.32
+ dev: true
/postcss-js@4.0.1(postcss@8.4.38):
resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==}
@@ -26817,7 +26865,8 @@ packages:
dependencies:
lilconfig: 3.1.1
postcss: 8.4.32
- yaml: 2.3.4
+ yaml: 2.4.1
+ dev: true
/postcss-load-config@4.0.2(postcss@8.4.38):
resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==}
@@ -27040,6 +27089,7 @@ packages:
dependencies:
postcss: 8.4.32
postcss-selector-parser: 6.0.16
+ dev: true
/postcss-nested@6.0.1(postcss@8.4.38):
resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==}
@@ -27381,6 +27431,7 @@ packages:
nanoid: 3.3.7
picocolors: 1.0.0
source-map-js: 1.2.0
+ dev: true
/postcss@8.4.38:
resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
@@ -28196,14 +28247,6 @@ packages:
source-map: 0.7.4
dev: false
- /react-icons@5.0.1(react@18.2.0):
- resolution: {integrity: sha512-WqLZJ4bLzlhmsvme6iFdgO8gfZP17rfjYEJ2m9RsZjZ+cc4k1hTzknEz63YS1MeT50kVzoa1Nz36f4BEx+Wigw==}
- peerDependencies:
- react: '*'
- dependencies:
- react: 18.2.0
- dev: false
-
/react-immutable-proptypes@2.2.0(immutable@3.8.2):
resolution: {integrity: sha512-Vf4gBsePlwdGvSZoLSBfd4HAP93HDauMY4fDjXhreg/vg6F3Fj/MXDNyTbltPC/xZKmZc+cjLu3598DdYK6sgQ==}
peerDependencies:
@@ -31001,12 +31044,6 @@ packages:
- supports-color
dev: false
- /tailwind-merge@2.2.2:
- resolution: {integrity: sha512-tWANXsnmJzgw6mQ07nE3aCDkCK4QdT3ThPMCzawoYA2Pws7vSTCvz3Vrjg61jVUGfFZPJzxEP+NimbcW+EdaDw==}
- dependencies:
- '@babel/runtime': 7.24.4
- dev: false
-
/tailwindcss@3.4.0:
resolution: {integrity: sha512-VigzymniH77knD1dryXbyxR+ePHihHociZbXnLZHUyzf2MMs2ZVqlUrZ3FvpXP8pno9JzmILt1sZPD19M3IxtA==}
engines: {node: '>=14.0.0'}
@@ -31036,6 +31073,7 @@ packages:
sucrase: 3.35.0
transitivePeerDependencies:
- ts-node
+ dev: true
/tailwindcss@3.4.3:
resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==}
@@ -31727,7 +31765,6 @@ packages:
dependencies:
tslib: 1.14.1
typescript: 5.4.4
- dev: false
/tsx@4.7.1:
resolution: {integrity: sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==}
@@ -33945,6 +33982,7 @@ packages:
/yaml@2.3.4:
resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==}
engines: {node: '>= 14'}
+ dev: false
/yaml@2.4.1:
resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==}
diff --git a/tests/e2e/specs/drupal/entity-usage.spec.ts b/tests/e2e/specs/drupal/entity-usage.spec.ts
new file mode 100644
index 000000000..118ac4421
--- /dev/null
+++ b/tests/e2e/specs/drupal/entity-usage.spec.ts
@@ -0,0 +1,16 @@
+import { expect, test } from '@playwright/test';
+
+import { cmsUrl } from '../../helpers/url';
+
+test.describe('entity-usage', () => {
+ test.use({ storageState: '.auth/admin.json' });
+
+ test('media usage works with inline doc links', async ({ page }) => {
+ await page.goto(cmsUrl('/admin/content/media'));
+ page.locator('div.view-content').getByText('Example DOCX document').click();
+ page.locator('a.tabs__link').getByText('Usage').click();
+ await expect(
+ page.locator('table').getByText('Page with links'),
+ ).toBeVisible();
+ });
+});
diff --git a/tests/schema/specs/blocks.spec.ts b/tests/schema/specs/blocks.spec.ts
index 48868307e..eacbc6586 100644
--- a/tests/schema/specs/blocks.spec.ts
+++ b/tests/schema/specs/blocks.spec.ts
@@ -55,6 +55,23 @@ test('Blocks', async () => {
icon
iconPosition
}
+ ... on BlockImageWithText {
+ image {
+ __typename
+ }
+ textContent {
+ __typename
+ markup
+ }
+ }
+ ... on BlockQuote {
+ quote
+ author
+ role
+ image {
+ __typename
+ }
+ }
... on BlockImageWithText {
image {
__typename
@@ -89,21 +106,6 @@ test('Blocks', async () => {
}
}
}
- ... on BlockInfoGrid {
- gridItems {
- icon
- textContent {
- markup
- }
- cta {
- url
- icon
- iconPosition
- text
- openInNewTab
- }
- }
- }
}
}
{
@@ -370,3 +372,174 @@ test('Blocks', async () => {
);
expect(germanForm.url).toBe('http://127.0.0.1:8000/de/form/contact');
});
+
+test('Block - info grid', async () => {
+ const result = await fetch(gql`
+ {
+ _loadDrupalPage(id: "3164a225-df20-4794-8cfc-b7cd81cfde58") {
+ content {
+ __typename
+ ... on BlockInfoGrid {
+ gridItems {
+ icon
+ textContent {
+ markup
+ }
+ cta {
+ url
+ icon
+ iconPosition
+ text
+ openInNewTab
+ }
+ }
+ }
+ }
+ }
+ }
+ `);
+ expect(result).toMatchInlineSnapshot(`
+ {
+ "data": {
+ "_loadDrupalPage": {
+ "content": [
+ {
+ "__typename": "BlockInfoGrid",
+ "gridItems": [
+ {
+ "cta": {
+ "icon": null,
+ "iconPosition": null,
+ "openInNewTab": null,
+ "text": "Link text",
+ "url": null,
+ },
+ "icon": "EMAIL",
+ "textContent": {
+ "markup": "
+ I am a heading
+
+ I am the body
+ ",
+ },
+ },
+ {
+ "cta": {
+ "icon": null,
+ "iconPosition": null,
+ "openInNewTab": null,
+ "text": "Second link text",
+ "url": null,
+ },
+ "icon": "PHONE",
+ "textContent": {
+ "markup": "
+ I am second heading
+
+ I am the second body
+ ",
+ },
+ },
+ {
+ "cta": {
+ "icon": null,
+ "iconPosition": null,
+ "openInNewTab": null,
+ "text": "third link text",
+ "url": null,
+ },
+ "icon": "LIFE-RING",
+ "textContent": {
+ "markup": "
+ I am the third heading
+
+ I am the third body
+ ",
+ },
+ },
+ ],
+ },
+ {
+ "__typename": "BlockInfoGrid",
+ "gridItems": [
+ {
+ "cta": {
+ "icon": null,
+ "iconPosition": null,
+ "openInNewTab": null,
+ "text": null,
+ "url": null,
+ },
+ "icon": "",
+ "textContent": {
+ "markup": "
+ Just one info grid
+
+
+ ",
+ },
+ },
+ ],
+ },
+ {
+ "__typename": "BlockInfoGrid",
+ "gridItems": [
+ {
+ "cta": {
+ "icon": null,
+ "iconPosition": null,
+ "openInNewTab": null,
+ "text": null,
+ "url": null,
+ },
+ "icon": "",
+ "textContent": {
+ "markup": "
+
+
+
+ ",
+ },
+ },
+ {
+ "cta": {
+ "icon": null,
+ "iconPosition": null,
+ "openInNewTab": null,
+ "text": null,
+ "url": null,
+ },
+ "icon": "",
+ "textContent": {
+ "markup": "
+
+
+
+ ",
+ },
+ },
+ {
+ "cta": {
+ "icon": null,
+ "iconPosition": null,
+ "openInNewTab": null,
+ "text": null,
+ "url": null,
+ },
+ "icon": "",
+ "textContent": {
+ "markup": "
+
+
+
+ ",
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ }
+ `);
+});
diff --git a/tests/schema/specs/links.spec.ts b/tests/schema/specs/links.spec.ts
index f1196bc00..2262cb2b1 100644
--- a/tests/schema/specs/links.spec.ts
+++ b/tests/schema/specs/links.spec.ts
@@ -29,7 +29,7 @@ test('Links', async () => {
{
"__typename": "BlockMarkup",
"markup": "
- link to file
+ link to file
link to page
",