diff --git a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php new file mode 100644 index 000000000..4ab6b31ab --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionItemTextValidator.php @@ -0,0 +1,51 @@ + [ + 'field_label' => $this->t('Title'), + 'rules' => ['required'], + ], + ]; + } + + /** + * {@inheritDoc} + */ + public function validateContent($block = []): array { + $expectedChildren = [ + 'validationType' => GutenbergCardinalityValidatorInterface::CARDINALITY_ANY, + 'min' => 1, + 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED, + ]; + return $this->validateCardinality($block, $expectedChildren); + } + +} diff --git a/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php new file mode 100644 index 000000000..d0bae38b0 --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/Plugin/Validation/GutenbergValidator/AccordionValidator.php @@ -0,0 +1,42 @@ + 'custom/accordion-item-text', + 'blockLabel' => $this->t('Accordion'), + 'min' => 1, + 'max' => GutenbergCardinalityValidatorInterface::CARDINALITY_UNLIMITED, + ], + ]; + return $this->validateCardinality($block, $expectedChildren); + } + +} diff --git a/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx b/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx new file mode 100644 index 000000000..dd50cd99e --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/accordion-item-text.tsx @@ -0,0 +1,85 @@ +import React, { Fragment } from 'react'; +import { + InnerBlocks, + InspectorControls, + RichText, +} from 'wordpress__block-editor'; +import { registerBlockType } from 'wordpress__blocks'; +import { PanelBody, SelectControl } from 'wordpress__components'; +import { compose, withState } from 'wordpress__compose'; + +// @ts-ignore +const { t: __ } = Drupal; +// @ts-ignore +registerBlockType('custom/accordion-item-text', { + title: 'Accordion Item Text', + icon: 'text', + category: 'layout', + parent: ['custom/accordion'], + attributes: { + title: { + type: 'string', + }, + icon: { + type: 'string', + }, + }, + // @ts-ignore + edit: compose(withState())((props) => { + const { attributes, setAttributes } = props; + const icons = [ + { label: __('- Select an optional icon -'), value: '' }, + { label: __('Checkmark'), value: 'checkmark' }, + { label: __('Questionmark'), value: 'questionmark' }, + { label: __('Arrow'), value: 'arrow' }, + ]; + setAttributes({ + icon: attributes.icon === undefined ? '' : attributes.icon, + }); + + return ( + + + + { + setAttributes({ + icon: newValue, + }); + }} + /> + + +
+
{__('Accordion Item Text')}
+
+ { + setAttributes({ title: newValue }); + }} + /> + +
+
+
+ ); + }), + + save: () => { + return ; + }, +}); diff --git a/packages/drupal/gutenberg_blocks/src/blocks/accordion.tsx b/packages/drupal/gutenberg_blocks/src/blocks/accordion.tsx new file mode 100644 index 000000000..924746dd8 --- /dev/null +++ b/packages/drupal/gutenberg_blocks/src/blocks/accordion.tsx @@ -0,0 +1,25 @@ +import { InnerBlocks } from 'wordpress__block-editor'; +import { registerBlockType } from 'wordpress__blocks'; + +// @ts-ignore +const { t: __ } = Drupal; + +registerBlockType('custom/accordion', { + title: __('Accordion'), + icon: 'menu', + category: 'layout', + attributes: {}, + edit: () => { + return ( +
+
{__('Accordion')}
+ +
+ ); + }, + save: () => , +}); diff --git a/packages/drupal/gutenberg_blocks/src/index.ts b/packages/drupal/gutenberg_blocks/src/index.ts index 2c86b28df..e2c0159f7 100644 --- a/packages/drupal/gutenberg_blocks/src/index.ts +++ b/packages/drupal/gutenberg_blocks/src/index.ts @@ -10,3 +10,5 @@ import './filters/list'; import './blocks/cta'; import './blocks/quote'; import './blocks/horizontal-separator'; +import './blocks/accordion'; +import './blocks/accordion-item-text'; 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 78300131d..5d892f82f 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 @@ -107,9 +107,23 @@ default: + + -

+

Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.

+ + + + + + + + + +

Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.

+ + format: gutenberg summary: '' diff --git a/packages/schema/src/fragments/Page.gql b/packages/schema/src/fragments/Page.gql index 3ecddb3c9..59285ccc4 100644 --- a/packages/schema/src/fragments/Page.gql +++ b/packages/schema/src/fragments/Page.gql @@ -36,6 +36,7 @@ fragment Page on Page { ...BlockImageWithText ...BlockQuote ...BlockHorizontalSeparator + ...BlockAccordion } metaTags { tag diff --git a/packages/schema/src/fragments/PageContent/BlockAccordion.gql b/packages/schema/src/fragments/PageContent/BlockAccordion.gql new file mode 100644 index 000000000..0f77b257d --- /dev/null +++ b/packages/schema/src/fragments/PageContent/BlockAccordion.gql @@ -0,0 +1,13 @@ +fragment BlockAccordion on BlockAccordion { + items { + ...BlockAccordionItemText + } +} + +fragment BlockAccordionItemText on BlockAccordionItemText { + title + icon + textContent { + markup + } +} diff --git a/packages/schema/src/schema.graphql b/packages/schema/src/schema.graphql index c5da9ee7d..3d8a4bda4 100644 --- a/packages/schema/src/schema.graphql +++ b/packages/schema/src/schema.graphql @@ -207,6 +207,7 @@ union PageContent @resolveEditorBlockType = | BlockImageWithText | BlockQuote | BlockHorizontalSeparator + | BlockAccordion type BlockForm @type(id: "custom/form") { url: Url @resolveEditorBlockAttribute(key: "formId") @webformIdToUrl(id: "$") @@ -246,6 +247,16 @@ type BlockImageTeaser @default @value { ctaUrl: Url @resolveEditorBlockAttribute(key: "ctaUrl") } +type BlockAccordion @type(id: "custom/accordion") { + items: [BlockAccordionItemText!]! @resolveEditorBlockChildren +} + +type BlockAccordionItemText @default @value { + title: String! @resolveEditorBlockAttribute(key: "title") + icon: String! @resolveEditorBlockAttribute(key: "icon") + textContent: BlockMarkup @resolveEditorBlockChildren @seek(pos: 0) +} + type BlockCta @type(id: "custom/cta") { url: Url @resolveEditorBlockAttribute(key: "url") text: String @resolveEditorBlockAttribute(key: "text") diff --git a/packages/ui/package.json b/packages/ui/package.json index f3320b5ce..967e148ea 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -44,6 +44,7 @@ "@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/Organisms/PageContent/BlockAccordion.stories.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx new file mode 100644 index 000000000..6f7be4e00 --- /dev/null +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.stories.tsx @@ -0,0 +1,56 @@ +import { Markup } from '@custom/schema'; +import { Meta, StoryObj } from '@storybook/react'; + +import { BlockAccordion } from './BlockAccordion'; + +export default { + component: BlockAccordion, +} satisfies Meta; + +export const AccordionItemText = { + args: { + items: [ + { + title: 'Cheese Fondue', + icon: '', + textContent: { + markup: ` +

The earliest known recipe for the modern form of cheese fondue comes from a 1699 book published in Zürich, under the name "Käss mit Wein zu kochen" 'to cook cheese with wine'. It calls for grated or cut-up cheese to be melted with wine, and for bread to be dipped in it.

+
    +
  • Fribourgeoise
  • +
  • Moitié-Moitié
  • +
+ ` as Markup, + }, + }, + { + title: 'Rösti', + icon: 'questionmark', + textContent: { + markup: ` +

Rösti is a kind of fried potato cake served as a main course or side dish.

+

As a main dish, rösti is usually accompanied with cheese, onions and cold meat or eggs. This dish, originally from Zürich, was first simply made by frying grated raw potatoes in a pan. It has then spread towards Bern where it is made with boiled potatoes instead. This is where it took the name Rösti. There are many variants in Switzerland and outside the borders. This culinary specialty gives its name to the röstigraben, which designates the cultural differences between the German- and French-speaking parts of the country.

+ ` as Markup, + }, + }, + { + title: 'Älplermagronen', + icon: 'checkmark', + textContent: { + markup: ` +

Älplermagronen are now regarded as a traditional dish of the Swiss Alps and a classic of Swiss comfort foods. According to a popular theory, pasta became widespread in northern Switzerland in the late 19th century, when the Gotthard Tunnel was built, partly by Italian workers who brought dry pasta with them.

+ ` as Markup, + }, + }, + { + title: 'Meringue with double cream', + icon: 'arrow', + textContent: { + markup: ` +

The Oxford English Dictionary states that the French word is of unknown origin. The name meringue for this confection first appeared in print in François Massialot's cookbook of 1692.

+ ` as Markup, + }, + }, + ], + }, +} satisfies StoryObj; diff --git a/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx new file mode 100644 index 000000000..5f4e19453 --- /dev/null +++ b/packages/ui/src/components/Organisms/PageContent/BlockAccordion.tsx @@ -0,0 +1,121 @@ +import { BlockAccordionFragment, Html } from '@custom/schema'; +import { + ArrowRightCircleIcon, + CheckCircleIcon, + 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'; +import { Plugin } from 'unified'; + +const unorderedItems: Plugin<[], Element> = () => (tree) => { + selectAll('ul > li', tree).forEach((node) => { + node.properties!.unordered = true; + }); +}; + +const accordionTheme: CustomFlowbiteTheme['accordion'] = { + root: { + base: 'mt-10 divide-y divide-gray-200 border-gray-200 dark:divide-gray-700 dark:border-gray-700', + flush: { + off: 'border-b last:border-0', + on: 'border-b last:border-0', + }, + }, + content: { + base: 'pb-5 pt-5 text-base font-light text-gray-500 dark:bg-gray-900 dark:text-gray-100', + }, + title: { + arrow: { + base: 'h-0 w-0', + }, + base: 'flex w-full items-center justify-between p-4 pl-1 text-left font-normal text-lg text-gray-500 dark:text-gray-400', + flush: { + off: 'hover:bg-gray-100 dark:hover:bg-gray-800 dark:focus:ring-gray-800', + on: 'bg-transparent dark:bg-transparent', + }, + heading: '', + open: { + off: '', + on: 'text-gray-900 dark:text-gray-100', + }, + }, +}; + +// 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) => ( + + + + {item.icon && } {item.title} + + + +
+ {item.textContent?.markup && ( + ) => { + return ( +
  • + {children} +
  • + ); + }, + }} + markup={item.textContent.markup} + /> + )} +
    +
    +
    + ))} +
    +
    + ); +} + +function AccordionIcon({ icon }: { icon: string }) { + switch (icon) { + case 'questionmark': + return ( + + ); + case 'checkmark': + return ( + + ); + case 'arrow': + return ( + + ); + default: + return null; + } +} diff --git a/packages/ui/src/components/Organisms/PageDisplay.tsx b/packages/ui/src/components/Organisms/PageDisplay.tsx index f5b15c390..05a5eaf7b 100644 --- a/packages/ui/src/components/Organisms/PageDisplay.tsx +++ b/packages/ui/src/components/Organisms/PageDisplay.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { isTruthy } from '../../utils/isTruthy'; import { UnreachableCaseError } from '../../utils/unreachable-case-error'; import { PageTransition } from '../Molecules/PageTransition'; +import { BlockAccordion } from './PageContent/BlockAccordion'; import { BlockCta } from './PageContent/BlockCta'; import { BlockForm } from './PageContent/BlockForm'; import { BlockHorizontalSeparator } from './PageContent/BlockHorizontalSeparator'; @@ -63,6 +64,8 @@ export function PageDisplay(page: PageFragment) { return
    ; case 'BlockHorizontalSeparator': return ; + case 'BlockAccordion': + return ; default: throw new UnreachableCaseError(block); } diff --git a/packages/ui/src/components/Routes/Page.stories.tsx b/packages/ui/src/components/Routes/Page.stories.tsx index f3d048c25..9821e0180 100644 --- a/packages/ui/src/components/Routes/Page.stories.tsx +++ b/packages/ui/src/components/Routes/Page.stories.tsx @@ -10,6 +10,7 @@ import { Meta, StoryObj } from '@storybook/react'; import React from 'react'; import { image } from '../../helpers/image'; +import { AccordionItemText } from '../Organisms/PageContent/BlockAccordion.stories'; import { Mixed, Paragraph } from '../Organisms/PageContent/BlockMarkup.stories'; import { WithCaption } from '../Organisms/PageContent/BlockMedia.stories'; import { Default as FrameStory } from './Frame.stories'; @@ -59,6 +60,10 @@ export const Default = { __typename: 'BlockMarkup', ...Paragraph.args, }, + { + __typename: 'BlockAccordion', + ...AccordionItemText.args, + }, ] as Exclude['content'], }, }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2a3e8c4b..48a576944 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: devDependencies: '@commitlint/cli': specifier: ^18.4.3 - version: 18.4.3(@types/node@18.19.31)(typescript@5.3.3) + version: 18.4.3(@types/node@20.11.17)(typescript@5.3.3) '@commitlint/config-conventional': specifier: ^18.4.3 version: 18.4.3 @@ -64,7 +64,7 @@ importers: version: 5.3.3 vitest: specifier: ^1.1.1 - version: 1.1.1(@types/node@18.19.31) + version: 1.1.1(@types/node@20.11.17) apps/cms: dependencies: @@ -532,6 +532,9 @@ 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) @@ -601,7 +604,7 @@ importers: version: 8.0.0-alpha.14(jest@29.7.0)(vitest@1.1.1) '@storybook/test-runner': specifier: ^0.16.0 - version: 0.16.0(@types/node@18.19.31) + version: 0.16.0(@types/node@20.11.17) '@swc/cli': specifier: ^0.1.63 version: 0.1.63(@swc/core@1.3.102) @@ -694,7 +697,7 @@ importers: version: 5.3.3 vite: specifier: ^5.0.10 - version: 5.0.10(@types/node@18.19.31) + version: 5.0.10(@types/node@20.11.17) vite-imagetools: specifier: ^6.2.9 version: 6.2.9 @@ -703,7 +706,7 @@ importers: version: 1.0.3 vitest: specifier: ^1.1.1 - version: 1.1.1(@types/node@18.19.31)(happy-dom@12.10.3) + version: 1.1.1(@types/node@20.11.17)(happy-dom@12.10.3) tests/e2e: devDependencies: @@ -2687,14 +2690,14 @@ packages: resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} - /@commitlint/cli@18.4.3(@types/node@18.19.31)(typescript@5.3.3): + /@commitlint/cli@18.4.3(@types/node@20.11.17)(typescript@5.3.3): resolution: {integrity: sha512-zop98yfB3A6NveYAZ3P1Mb6bIXuCeWgnUfVNkH4yhIMQpQfzFwseadazOuSn0OOfTt0lWuFauehpm9GcqM5lww==} engines: {node: '>=v18'} hasBin: true dependencies: '@commitlint/format': 18.6.1 '@commitlint/lint': 18.6.1 - '@commitlint/load': 18.6.1(@types/node@18.19.31)(typescript@5.3.3) + '@commitlint/load': 18.6.1(@types/node@20.11.17)(typescript@5.3.3) '@commitlint/read': 18.6.1 '@commitlint/types': 18.6.1 execa: 5.1.1 @@ -2765,7 +2768,7 @@ packages: '@commitlint/types': 18.6.1 dev: true - /@commitlint/load@18.6.1(@types/node@18.19.31)(typescript@5.3.3): + /@commitlint/load@18.6.1(@types/node@20.11.17)(typescript@5.3.3): resolution: {integrity: sha512-p26x8734tSXUHoAw0ERIiHyW4RaI4Bj99D8YgUlVV9SedLf8hlWAfyIFhHRIhfPngLlCe0QYOdRKYFt8gy56TA==} engines: {node: '>=v18'} dependencies: @@ -2775,7 +2778,7 @@ packages: '@commitlint/types': 18.6.1 chalk: 4.1.2 cosmiconfig: 8.3.6(typescript@5.3.3) - cosmiconfig-typescript-loader: 5.0.0(@types/node@18.19.31)(cosmiconfig@8.3.6)(typescript@5.3.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.11.17)(cosmiconfig@8.3.6)(typescript@5.3.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -4158,14 +4161,12 @@ packages: resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} dependencies: '@floating-ui/utils': 0.2.1 - dev: true /@floating-ui/dom@1.6.3: resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} dependencies: '@floating-ui/core': 1.6.0 '@floating-ui/utils': 0.2.1 - dev: true /@floating-ui/react-dom@2.0.8(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==} @@ -4176,11 +4177,22 @@ packages: '@floating-ui/dom': 1.6.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - dev: true + + /@floating-ui/react@0.26.10(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-sh6f9gVvWQdEzLObrWbJ97c0clJObiALsFe0LiR/kb3tDRKwEhObASEH2QyfdoO/ZBPzwxa9j+nYFo+sqgbioA==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) + '@floating-ui/utils': 0.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tabbable: 6.2.0 + dev: false /@floating-ui/utils@0.2.1: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} - dev: true /@formatjs/cli@6.2.4: resolution: {integrity: sha512-g1o9O143F5TGB55skib3fKbyjifPa9YoDcX9L07hVJocRKngCcu4JhKViyUSN55KGcN2ttfBomM+wihN6wtBSQ==} @@ -5683,7 +5695,7 @@ packages: magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.3.3) typescript: 5.3.3 - vite: 5.0.10(@types/node@18.19.31) + vite: 5.0.10(@types/node@20.11.17) dev: true /@jridgewell/gen-mapping@0.3.5: @@ -7273,6 +7285,10 @@ 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: @@ -8352,7 +8368,7 @@ packages: magic-string: 0.30.9 rollup: 3.29.4 typescript: 5.3.3 - vite: 5.0.10(@types/node@18.19.31) + vite: 5.0.10(@types/node@20.11.17) transitivePeerDependencies: - encoding - supports-color @@ -8861,7 +8877,7 @@ packages: react: 18.2.0 react-docgen: 7.0.3 react-dom: 18.2.0(react@18.2.0) - vite: 5.0.10(@types/node@18.19.31) + vite: 5.0.10(@types/node@20.11.17) transitivePeerDependencies: - '@preact/preset-vite' - encoding @@ -8935,7 +8951,7 @@ packages: - supports-color dev: true - /@storybook/test-runner@0.16.0(@types/node@18.19.31): + /@storybook/test-runner@0.16.0(@types/node@20.11.17): resolution: {integrity: sha512-LDmNbKFoEDW/VS9o6KR8e1r5MnbCc5ZojUfi5yqLdq80gFD7BvilgKgV0lUh/xWHryzoy+Ids5LYgrPJZmU2dQ==} engines: {node: ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true @@ -8955,7 +8971,7 @@ packages: commander: 9.5.0 expect-playwright: 0.8.0 glob: 10.3.12 - jest: 29.7.0(@types/node@18.19.31) + jest: 29.7.0(@types/node@20.11.17) jest-circus: 29.7.0 jest-environment-node: 29.7.0 jest-junit: 16.0.0 @@ -9413,10 +9429,10 @@ packages: chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.6.3 - jest: 29.7.0(@types/node@18.19.31) + jest: 29.7.0(@types/node@20.11.17) lodash: 4.17.21 redent: 3.0.0 - vitest: 1.1.1(@types/node@18.19.31)(happy-dom@12.10.3) + vitest: 1.1.1(@types/node@20.11.17)(happy-dom@12.10.3) dev: true /@testing-library/react@14.1.2(react-dom@18.2.0)(react@18.2.0): @@ -11017,7 +11033,7 @@ packages: vite: ^4 || ^5 dependencies: '@swc/core': 1.4.13 - vite: 5.0.10(@types/node@18.0.0) + vite: 5.0.10(@types/node@20.11.17) transitivePeerDependencies: - '@swc/helpers' dev: true @@ -11044,7 +11060,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.4) magic-string: 0.27.0 react-refresh: 0.14.0 - vite: 5.0.10(@types/node@18.19.31) + vite: 5.0.10(@types/node@20.11.17) transitivePeerDependencies: - supports-color dev: true @@ -13793,6 +13809,10 @@ 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'} @@ -14425,7 +14445,7 @@ packages: object-assign: 4.1.1 vary: 1.1.2 - /cosmiconfig-typescript-loader@5.0.0(@types/node@18.19.31)(cosmiconfig@8.3.6)(typescript@5.3.3): + /cosmiconfig-typescript-loader@5.0.0(@types/node@20.11.17)(cosmiconfig@8.3.6)(typescript@5.3.3): resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} engines: {node: '>=v16'} peerDependencies: @@ -14433,7 +14453,7 @@ packages: cosmiconfig: '>=8.2' typescript: '>=4' dependencies: - '@types/node': 18.19.31 + '@types/node': 20.11.17 cosmiconfig: 8.3.6(typescript@5.3.3) jiti: 1.21.0 typescript: 5.3.3 @@ -14559,7 +14579,7 @@ packages: dependencies: '@babel/runtime': 7.24.4 - /create-jest@29.7.0(@types/node@18.19.31): + /create-jest@29.7.0(@types/node@20.11.17): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -14568,7 +14588,7 @@ packages: chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.19.31) + jest-config: 29.7.0(@types/node@20.11.17) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -14981,6 +15001,11 @@ 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: @@ -18614,6 +18639,32 @@ 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: @@ -22517,7 +22568,7 @@ packages: - supports-color dev: true - /jest-cli@29.7.0(@types/node@18.19.31): + /jest-cli@29.7.0(@types/node@20.11.17): resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -22531,10 +22582,10 @@ packages: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.19.31) + create-jest: 29.7.0(@types/node@20.11.17) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@18.19.31) + jest-config: 29.7.0(@types/node@20.11.17) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -22585,6 +22636,46 @@ packages: - supports-color dev: true + /jest-config@29.7.0(@types/node@20.11.17): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.24.4 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.17 + babel-jest: 29.7.0(@babel/core@7.24.4) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true + /jest-diff@29.7.0: resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -22723,7 +22814,7 @@ packages: jest-runner: ^29.3.1 dependencies: expect-playwright: 0.8.0 - jest: 29.7.0(@types/node@18.19.31) + jest: 29.7.0(@types/node@20.11.17) jest-circus: 29.7.0 jest-environment-node: 29.7.0 jest-process-manager: 0.4.0 @@ -22934,7 +23025,7 @@ packages: dependencies: ansi-escapes: 6.2.1 chalk: 5.3.0 - jest: 29.7.0(@types/node@18.19.31) + jest: 29.7.0(@types/node@20.11.17) jest-regex-util: 29.6.3 jest-watcher: 29.7.0 slash: 5.1.0 @@ -22982,7 +23073,7 @@ packages: supports-color: 8.1.1 dev: true - /jest@29.7.0(@types/node@18.19.31): + /jest@29.7.0(@types/node@20.11.17): resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true @@ -22995,7 +23086,7 @@ packages: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@18.19.31) + jest-cli: 29.7.0(@types/node@20.11.17) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -24704,7 +24795,6 @@ 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==} @@ -25940,6 +26030,7 @@ packages: /p-limit@4.0.0: resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + requiresBuild: true dependencies: yocto-queue: 1.0.0 @@ -26697,7 +26788,6 @@ 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==} @@ -26732,7 +26822,6 @@ 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==} @@ -26760,7 +26849,6 @@ packages: lilconfig: 3.1.1 postcss: 8.4.32 yaml: 2.3.4 - dev: true /postcss-load-config@4.0.2(postcss@8.4.38): resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} @@ -26983,7 +27071,6 @@ 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==} @@ -27325,7 +27412,6 @@ 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==} @@ -28149,6 +28235,14 @@ 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: @@ -30908,6 +31002,10 @@ packages: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} engines: {node: '>=18'} + /tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: false + /table@5.4.6: resolution: {integrity: sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==} engines: {node: '>=6.0.0'} @@ -30941,6 +31039,12 @@ 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'} @@ -30970,7 +31074,6 @@ packages: sucrase: 3.35.0 transitivePeerDependencies: - ts-node - dev: true /tailwindcss@3.4.3: resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} @@ -32677,6 +32780,27 @@ packages: - terser dev: true + /vite-node@1.1.1(@types/node@20.11.17): + resolution: {integrity: sha512-2bGE5w4jvym5v8llF6Gu1oBrmImoNSs4WmRVcavnG2me6+8UQntTqLiAMFyiAobp+ZXhj5ZFhI7SmLiFr/jrow==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.0 + vite: 5.2.8(@types/node@20.11.17) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vite-plugin-istanbul@3.0.4: resolution: {integrity: sha512-DJy3cq6yOFbsM3gLQf/3zeuaJNJsfBv5dLFdZdv8sUV30xLtZI+66QeYfHUyP/5vBUYyLA+xNUCSG5uHY6w+5g==} dependencies: @@ -32728,7 +32852,7 @@ packages: fsevents: 2.3.3 dev: true - /vite@5.0.10(@types/node@18.19.31): + /vite@5.0.10(@types/node@20.11.17): resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -32756,7 +32880,7 @@ packages: terser: optional: true dependencies: - '@types/node': 18.19.31 + '@types/node': 20.11.17 esbuild: 0.19.12 postcss: 8.4.32 rollup: 4.14.1 @@ -33063,7 +33187,7 @@ packages: - terser dev: true - /vitest@1.1.1(@types/node@18.19.31): + /vitest@1.1.1(@types/node@18.19.31)(happy-dom@12.10.3): resolution: {integrity: sha512-Ry2qs4UOu/KjpXVfOCfQkTnwSXYGrqTbBZxw6reIYEFjSy1QUARRg5pxiI5BEXy+kBVntxUYNMlq4Co+2vD3fQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -33099,6 +33223,7 @@ packages: chai: 4.4.1 debug: 4.3.4 execa: 8.0.1 + happy-dom: 12.10.3 local-pkg: 0.5.0 magic-string: 0.30.9 pathe: 1.1.2 @@ -33120,7 +33245,7 @@ packages: - terser dev: true - /vitest@1.1.1(@types/node@18.19.31)(happy-dom@12.10.3): + /vitest@1.1.1(@types/node@20.11.17): resolution: {integrity: sha512-Ry2qs4UOu/KjpXVfOCfQkTnwSXYGrqTbBZxw6reIYEFjSy1QUARRg5pxiI5BEXy+kBVntxUYNMlq4Co+2vD3fQ==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -33145,7 +33270,64 @@ packages: jsdom: optional: true dependencies: - '@types/node': 18.19.31 + '@types/node': 20.11.17 + '@vitest/expect': 1.1.1 + '@vitest/runner': 1.1.1 + '@vitest/snapshot': 1.1.1 + '@vitest/spy': 1.1.1 + '@vitest/utils': 1.1.1 + acorn-walk: 8.3.2 + cac: 6.7.14 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.9 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 1.3.0 + tinybench: 2.6.0 + tinypool: 0.8.3 + vite: 5.2.8(@types/node@20.11.17) + vite-node: 1.1.1(@types/node@20.11.17) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vitest@1.1.1(@types/node@20.11.17)(happy-dom@12.10.3): + resolution: {integrity: sha512-Ry2qs4UOu/KjpXVfOCfQkTnwSXYGrqTbBZxw6reIYEFjSy1QUARRg5pxiI5BEXy+kBVntxUYNMlq4Co+2vD3fQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': ^1.0.0 + '@vitest/ui': ^1.0.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 20.11.17 '@vitest/expect': 1.1.1 '@vitest/runner': 1.1.1 '@vitest/snapshot': 1.1.1 @@ -33165,8 +33347,8 @@ packages: strip-literal: 1.3.0 tinybench: 2.6.0 tinypool: 0.8.3 - vite: 5.2.8(@types/node@18.19.31) - vite-node: 1.1.1(@types/node@18.19.31) + vite: 5.2.8(@types/node@20.11.17) + vite-node: 1.1.1(@types/node@20.11.17) why-is-node-running: 2.2.2 transitivePeerDependencies: - less diff --git a/tests/schema/specs/blocks.spec.ts b/tests/schema/specs/blocks.spec.ts index bb6de6994..673181811 100644 --- a/tests/schema/specs/blocks.spec.ts +++ b/tests/schema/specs/blocks.spec.ts @@ -93,6 +93,19 @@ test('Blocks', async () => { ... on BlockHorizontalSeparator { __typename } + ... on BlockAccordion { + items { + __typename + ... on BlockAccordionItemText { + __typename + title + icon + textContent { + markup + } + } + } + } } } { @@ -241,10 +254,31 @@ test('Blocks', async () => { "role": "Project manager", }, { - "__typename": "BlockMarkup", - "markup": " -

    + "__typename": "BlockAccordion", + "items": [ + { + "__typename": "BlockAccordionItemText", + "icon": "", + "textContent": { + "markup": " +

    Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.

    + ", + }, + "title": "With a single paragraph and no icon", + }, + { + "__typename": "BlockAccordionItemText", + "icon": "arrow", + "textContent": { + "markup": " +
    • Moitié-moitié
    • Fribourgeoise
    + +

    Incididunt laborum velit non proident nostrud velit. Minim excepteur ut aliqua nisi. Culpa laboris consectetur proident. Tempor esse ullamco et dolor proident id officia laborum voluptate nostrud elit dolore qui amet. Ex Lorem irure eu anim ipsum officia.

    ", + }, + "title": "With a list and a paragraph and arrow icon", + }, + ], }, ], "hero": {