/** * External dependencies */ import clsx from 'clsx'; /** * WordPress dependencies */ import { useBlockProps } from '@wordpress/block-editor'; import type { BlockSaveProps } from '@wordpress/blocks'; /** * Internal dependencies */ import type { BlockAttributes } from './types'; import { getStyleObject } from './utils'; type V1Attributes = { heightLg: number; heightMd: number; heightSm: number; isNegativeLg: boolean; isNegativeMd: boolean; isNegativeSm: boolean; }; // Stop depending on the default values from the settings page in the save // function. This version is the same as v2 except that omitted heights are parsed // as `100px`, as in the block.json of that time. It recovers content that was // valid at that time, such as a height saved as an empty string. const v3 = { attributes: { heightLg: { type: 'string', default: '100px', }, heightMd: { type: 'string', default: '100px', }, heightSm: { type: 'string', default: '100px', }, isNegativeLg: { type: 'boolean', default: false, }, isNegativeMd: { type: 'boolean', default: false, }, isNegativeSm: { type: 'boolean', default: false, }, }, migrate( attributes: BlockAttributes ): BlockAttributes { const { heightLg, heightMd, heightSm } = attributes; const { defaultValue } = fsbConf; return { ...attributes, heightLg: heightLg || defaultValue.lg + defaultValue.lg_unit, heightMd: heightMd || defaultValue.md + defaultValue.md_unit, heightSm: heightSm || defaultValue.sm + defaultValue.sm_unit, }; }, save( { attributes, className }: BlockSaveProps< BlockAttributes > ) { const { heightLg, heightMd, heightSm, isNegativeLg, isNegativeMd, isNegativeSm } = attributes; const { defaultValue } = fsbConf; const styleLg = getStyleObject( heightLg, isNegativeLg, defaultValue.lg, defaultValue.lg_unit ); const styleMd = getStyleObject( heightMd, isNegativeMd, defaultValue.md, defaultValue.md_unit ); const styleSm = getStyleObject( heightSm, isNegativeSm, defaultValue.sm, defaultValue.sm_unit ); const blockProps = useBlockProps.save( { 'aria-hidden': true, className: clsx( 'fsb-flexible-spacer', className ), } ); return (
); }, }; // When a height was cleared, it was empty and therefore not saved, while the save // function output it with the default value from the settings page // (`fsbConf.defaultValue`). On reload the height was parsed as `100px`, so the // block became invalid when that default value was not 100px. This version parses // omitted heights as empty to match such content, and writes the default value // back to them so that the block keeps the height it was shown with. const v2 = { attributes: { heightLg: { type: 'string', }, heightMd: { type: 'string', }, heightSm: { type: 'string', }, isNegativeLg: { type: 'boolean', default: false, }, isNegativeMd: { type: 'boolean', default: false, }, isNegativeSm: { type: 'boolean', default: false, }, }, migrate( attributes: BlockAttributes ): BlockAttributes { const { heightLg, heightMd, heightSm } = attributes; const { defaultValue } = fsbConf; return { ...attributes, heightLg: heightLg || defaultValue.lg + defaultValue.lg_unit, heightMd: heightMd || defaultValue.md + defaultValue.md_unit, heightSm: heightSm || defaultValue.sm + defaultValue.sm_unit, }; }, save( { attributes, className }: BlockSaveProps< BlockAttributes > ) { const { heightLg, heightMd, heightSm, isNegativeLg, isNegativeMd, isNegativeSm } = attributes; const { defaultValue } = fsbConf; const styleLg = getStyleObject( heightLg, isNegativeLg, defaultValue.lg, defaultValue.lg_unit ); const styleMd = getStyleObject( heightMd, isNegativeMd, defaultValue.md, defaultValue.md_unit ); const styleSm = getStyleObject( heightSm, isNegativeSm, defaultValue.sm, defaultValue.sm_unit ); const blockProps = useBlockProps.save( { 'aria-hidden': true, className: clsx( 'fsb-flexible-spacer', className ), } ); return (
); }, }; // Add unit support const v1 = { attributes: { heightLg: { type: 'number', default: 100, }, heightMd: { type: 'number', default: 100, }, heightSm: { type: 'number', default: 100, }, isNegativeLg: { type: 'boolean', default: false, }, isNegativeMd: { type: 'boolean', default: false, }, isNegativeSm: { type: 'boolean', default: false, }, }, migrate( attributes: V1Attributes ): BlockAttributes { const { heightLg, heightMd, heightSm } = attributes; return { ...attributes, heightLg: heightLg !== undefined ? `${ heightLg }px` : undefined, heightMd: heightMd !== undefined ? `${ heightMd }px` : undefined, heightSm: heightSm !== undefined ? `${ heightSm }px` : undefined, }; }, save( { attributes, className }: BlockSaveProps< V1Attributes > ) { const { heightLg, heightMd, heightSm, isNegativeLg, isNegativeMd, isNegativeSm } = attributes; const styleLg = isNegativeLg ? { marginBottom: -heightLg } : { height: heightLg }; const styleMd = isNegativeMd ? { marginBottom: -heightMd } : { height: heightMd }; const styleSm = isNegativeSm ? { marginBottom: -heightSm } : { height: heightSm }; const blockProps = useBlockProps.save( { 'aria-hidden': true, className: clsx( 'fsb-flexible-spacer', className ), } ); return (
); }, }; export default [ v3, v2, v1 ];