import * as React from 'react'
import {__, _x, sprintf} from '@wordpress/i18n'
import cx from 'classnames'

import {
	RangeControl,
	ToggleControl,
	FocalPointPicker,
	MenuItem,
} from '@wordpress/components'

import {
	hasBlockSupport,
	// @ts-expect-error
} from '@wordpress/blocks'

import {
	addFilter,
} from '@wordpress/hooks'

import {
	useSelect,
} from '@wordpress/data'

import {
	store as coreDataStore,
	type Attachment,
} from '@wordpress/core-data'

import {
	BlockControls,
	InspectorControls,
	MediaReplaceFlow,
	// @ts-expect-error
} from '@wordpress/block-editor'

import {
	createHigherOrderComponent,
} from '@wordpress/compose'

import {
	siteLogo as siteLogoIcon,
	trash as trashIcon,
} from '@wordpress/icons'

import {
	ButtonGroup,
	WithTooltip,
} from '@ska/components'

import {
	SkaPanelBody,
} from '@ska/plugin'

import {
	ImageSizeControl,
	PlaceholderImageControl,
} from '../components'

import {
	useSkaBlocksDispatch,
} from '../tailwind/reducer'

import {
	homeUrl,
	placeholderImageUrl,
} from '../data'

import {
	selectImageUrl,
	type tImage,
	type tBlockEditProps,
	type tBlockNameOrType,
	type tBlockSaveProps,
	type tBlockType,
	type tBlockEditInnerBlocksProps,
	type tBlockSaveInnerBlocksProps,
	type tVideo,
	type tBlockAttributes,
	getPlaceholderSvg,
} from '@ska/shared'

export interface BackgroundValue {
	mode?: 'image' | 'video' | 'background' | 'placeholder'
	id?: number
	src?: string
	posterId?: number
	posterSrc?: string
	loading?: 'lazy' | 'eager' | 'lcp' | 'preload'
	/** Add `srcset` to image when possible. */
	srcset?: boolean
	/** Add low res placeholder background to the image. */
	placeholder?: boolean
	/** Whether to preload low res placeholder in head. */
	preloadPlaceholder?: boolean
	/** Whether to preload poster image in head. */
	preloadPoster?: boolean
	size?: 'cover' | 'contain' | 'fill' | 'scale-down'
	repeat?: string
	opacity?: number
	focalPoint?: {x: number, y: number}
	placeholderIndex?: number
	/** Whether to autoplay in editor. */
	play?: boolean
}

export interface BackgroundAttributes {
	skaBlocksBackground?: BackgroundValue
}

export const BACKGROUND_SUPPORT_KEY = 'skaBlocksBackground'
export const BACKGROUND_SUPPORT_DEFAULT_ENABLED = false
export const hasBackgroundSupport = (block: tBlockNameOrType) => hasBlockSupport(block, BACKGROUND_SUPPORT_KEY, BACKGROUND_SUPPORT_DEFAULT_ENABLED)

const PLACEHOLDER_SVG = getPlaceholderSvg()
const PLACEHOLDER_SRC = `data:image/svg+xml;base64,${btoa(PLACEHOLDER_SVG.trim())}`
const PLACEHOLDER_SRC_PLACEHOLDER = '%SKA_PLACEHOLDER_IMAGE%'

const BACKGROUND_PREFIX = '🌄 '

const getBlockLabelRenderer = (defaultLabel: string, __experimentalLabel?: tBlockType['__experimentalLabel']) => {

	const getLabel: tBlockType['__experimentalLabel'] = (attributes, arg) => {

		const {context} = arg
		const label = __experimentalLabel ? (__experimentalLabel(attributes, arg) || defaultLabel) : defaultLabel

		if(context !== 'list-view' || typeof label !== 'string') {
			return label
		}

		const {
			skaBlocksBackground = {},
		} = attributes

		const {
			src,
		} = skaBlocksBackground

		return `${src ? BACKGROUND_PREFIX : ''}${label}`
	}

	return getLabel
}

const withBackgroundSupport = (settings: tBlockType) => {

	const hasSupport = hasBackgroundSupport(settings)

	if(!hasSupport) {

		switch(settings.name) {

			/**
			 * Support adding a background to embed - it's only used by `ska-theme` as a placeholder when using `Video` preset.
			 */
			case 'core/embed':
				if(settings.supports) {
					Object.assign(settings.supports, {[BACKGROUND_SUPPORT_KEY]: true})
				} else {
					settings.supports = {[BACKGROUND_SUPPORT_KEY]: true}
				}
			break

			default:
				return settings
		}
	}

	if(!settings.attributes.skaBlocksBackground) {
		Object.assign(settings.attributes, {
			skaBlocksBackground: {
				type: 'object',
			},
		})
	}

	if(hasSupport) {
		settings.__experimentalLabel = getBlockLabelRenderer(settings.title, settings.__experimentalLabel)
	}

	return settings
}

const MODES = [
	{
		label: _x('Image', 'Background mode', 'ska-blocks'),
		value: 'image',
	},
	{
		label: _x('Video', 'Background mode', 'ska-blocks'),
		value: 'video',
	},
	{
		label: _x('Background', 'Background mode', 'ska-blocks'),
		value: 'background',
	},
	{
		label: _x('Placeholder', 'Background mode', 'ska-blocks'),
		value: 'placeholder',
	},
]

const LOADING = [
	{
		label: _x('Lazy', 'Image loading attribute', 'ska-blocks'),
		tooltip: _x(`Lazyload the image.`, 'Image loading description', 'ska-blocks'),
		value: 'lazy',
	},
	{
		label: _x('Eager', 'Image loading attribute', 'ska-blocks'),
		tooltip: _x(`Don't lazyload the image.`, 'Image loading description', 'ska-blocks'),
		value: 'eager',
	},
	{
		label: _x('LCP', 'Image loading attribute', 'ska-blocks'),
		tooltip: _x(`Enable high fetchpriority and synchronous decoding.`, 'Image loading description', 'ska-blocks'),
		value: 'lcp',
	},
	{
		label: _x('Preload', 'Image loading attribute', 'ska-blocks'),
		tooltip: _x(`Preload the image in document head.`, 'Image loading description', 'ska-blocks'),
		value: 'preload',
	},
]

const BACKGROUND_SIZE = [
	{
		label: __('Cover', 'ska-blocks'),
		value: 'cover',
	},
	{
		label: __('Contain', 'ska-blocks'),
		value: 'contain',
	},
	{
		label: __('Fill', 'ska-blocks'),
		value: 'fill',
	},
	{
		label: __('Scale down', 'ska-blocks'),
		value: 'scale-down',
	},
]
const VALID_BACKGROUND_SIZES = ['cover', 'contain']

const BACKGROUND_REPEAT = [
	{
		label: __('No repeat', 'ska-blocks'),
		value: 'no-repeat',
	},
	{
		label: __('Repeat', 'ska-blocks'),
		value: 'repeat',
	},
	{
		label: __('Repeat X', 'ska-blocks'),
		value: 'repeat-x',
	},
	{
		label: __('Repeat Y', 'ska-blocks'),
		value: 'repeat-y',
	},
	{
		label: __('Space', 'ska-blocks'),
		value: 'space',
	},
	{
		label: __('Round', 'ska-blocks'),
		value: 'round',
	},
]

const DEFAULT_FOCAL_POINT = {x: 0.5, y: 0.5}
const mediaPosition = ({x, y} = DEFAULT_FOCAL_POINT) => {
	return `${Math.round(x * 100)}% ${Math.round(y * 100)}%`
}

const VIDEO_EXTENSIONS = ['.mp4', '.mkv', '.webm', '.mov', '.avi', '.wmv', '.flv', '.mpeg', '.mpg']
const isVideoUrl = (url: string) => {
	const cleanUrl = url.trim().split(/[#?]/)[0].toLowerCase()
	return VIDEO_EXTENSIONS.some(ext => cleanUrl.endsWith(ext))
}

const BackgroundInspectorControls: React.FC<tBlockEditProps<BackgroundAttributes>> = (props) => {

	const {
		name,
		attributes,
		setAttributes,
	} = props

	const {
		skaBlocksBackground = {},
	} = attributes

	const {
		mode = 'image',
		id,
		src,
		posterId,
		posterSrc,
		loading = 'lazy',
		srcset = true,
		placeholder = false,
		preloadPlaceholder = true,
		preloadPoster = false,
		size = BACKGROUND_SIZE[0].value,
		repeat = BACKGROUND_REPEAT[0].value,
		opacity = 1,
		focalPoint = DEFAULT_FOCAL_POINT,
		placeholderIndex = 0,
		play = true,
	} = skaBlocksBackground

	const isPlaceholder = src === PLACEHOLDER_SRC_PLACEHOLDER && ['image', 'background'].includes(mode)
	const isEmbed = name === 'core/embed'
	const hasVideoPreset = attributes?.skaBlocks?.p?.find(({id}: any) => id === 'ska-theme--video')

	const dispatch = useSkaBlocksDispatch(attributes, setAttributes)

	const attachment = useSelect(select => select(coreDataStore).getEntityRecord<Attachment>('postType', 'attachment', id), [id])

	const setAttribute = (key: keyof BackgroundValue, value: BackgroundValue[typeof key]) => {
		setAttributes({
			skaBlocksBackground: {
				...skaBlocksBackground,
				[key]: value,
			},
		})
	}

	const onSelectMedia = (media: tImage | tVideo) => {
		dispatch.setAttributes({
			skaBlocksBackground: {
				...skaBlocksBackground,
				id: media.id,
				src: media.type === 'image' && attachment?.media_type === 'image'
					? selectImageUrl(media, src, attachment)
					: media.url,
				mode: ['image', 'video'].includes(media.type) ? media.type : (
					media?.mime_type && media.mime_type.startsWith('video') ? 'video' : 'image'
				),
			},
		})
	}

	const onSelectMediaURL = (url: string) => {
		dispatch.setAttributes({
			skaBlocksBackground: {
				...skaBlocksBackground,
				id: undefined,
				src: url,
				mode: isVideoUrl(url) ? 'video' : 'image',
			},
		})
	}

	const onClear = () => {
		dispatch.setAttributes({
			skaBlocksBackground: {
				...skaBlocksBackground,
				id: undefined,
				src: undefined,
			},
		})
	}

	const onSelectPoster = (media: tImage) => {
		dispatch.setAttributes({
			skaBlocksBackground: {
				...skaBlocksBackground,
				posterId: media.id,
				posterSrc: media.url,
			},
		})
	}

	const onSelectPosterURL = (url: string) => {
		dispatch.setAttributes({
			skaBlocksBackground: {
				...skaBlocksBackground,
				posterId: undefined,
				posterSrc: url,
			},
		})
	}

	const onClearPoster = () => {
		dispatch.setAttributes({
			skaBlocksBackground: {
				...skaBlocksBackground,
				posterId: undefined,
				posterSrc: undefined,
			},
		})
	}

	const setMode = (nextMode?: string) => {
		if(nextMode) {
			dispatch.setAttributes({
				skaBlocksBackground: {
					...skaBlocksBackground,
					mode: nextMode as BackgroundValue['mode'],
					...(src && {
						/** Reset media when switching from or to video as they use different media type. */
						...((mode === 'video' || nextMode === 'video') && {
							src: undefined,
							id: undefined,
						}),
					}),
					...(nextMode === 'placeholder' && {
						id: undefined,
						src: PLACEHOLDER_SRC,
						placeholderIndex: undefined,
					}),
				},
			})
		}
	}

	if(isEmbed && !hasVideoPreset) {
		return null
	}

	return <>
		<BlockControls group='other'>
			<MediaReplaceFlow
				name={src
					? (isEmbed
						? `${BACKGROUND_PREFIX}${__('Edit poster', 'ska-blocks')}`
						: `${BACKGROUND_PREFIX}${__('Edit background', 'ska-blocks')}`
					)
					: (isEmbed
						? `${__('Add poster', 'ska-blocks')} 🚩`
						: __('Add background', 'ska-blocks')
					)
				}
				mediaId={id}
				mediaURL={src}
				allowedTypes={isEmbed ? ['image'] : ['image', 'video']}
				accept={isEmbed ? 'image/*' : 'image/*,video/*'}
				onSelect={onSelectMedia}
				onSelectURL={onSelectMediaURL}
				children={({onClose}: any) => <>
					{!src && !isEmbed && (
						<MenuItem
							icon={siteLogoIcon}
							children={__('Placeholder', 'ska-blocks')}
							onClick={() => {
								dispatch.setAttributes({
									skaBlocksBackground: {
										...skaBlocksBackground,
										mode: 'placeholder',
										src: PLACEHOLDER_SRC,
										...(placeholderIndex > 0 && {
											mode: 'image',
											src: PLACEHOLDER_SRC_PLACEHOLDER,
										}),
									},
								})
								onClose()
							}}
						/>
					)}
					{src && (
						<MenuItem
							icon={trashIcon}
							children={isEmbed ? __('Remove poster', 'ska-blocks') : __('Remove background', 'ska-blocks')}
							onClick={() => {
								onClear()
								onClose()
							}}
						/>
					)}
				</>}
			/>
			{mode === 'video' && <>
				<MediaReplaceFlow
					name={posterSrc ? __('Edit poster', 'ska-blocks') : `${__('Add poster', 'ska-blocks')} 🚩`}
					mediaId={posterId}
					mediaURL={posterSrc}
					allowedTypes={['image']}
					accept={'image/*'}
					onSelect={onSelectPoster}
					onSelectURL={onSelectPosterURL}
					children={({onClose}: any) => <>
						{posterSrc && (
							<MenuItem
								icon={trashIcon}
								children={__('Remove poster', 'ska-blocks')}
								onClick={() => {
									onClearPoster()
									onClose()
								}}
							/>
						)}
					</>}
				/>
			</>}
		</BlockControls>
		<InspectorControls>
			{src && (
				<SkaPanelBody
					id={BACKGROUND_SUPPORT_KEY}
					title={isEmbed ? __('Poster', 'ska-blocks') : __('Background', 'ska-blocks')}
					skaIcon
				>
					{!isEmbed && <>
						<ButtonGroup.Radio
							label={__('Mode', 'ska-blocks')}
							pills
							options={MODES}
							value={mode}
							onChange={setMode}
						/>
					</>}
					{src && <>
						{!isEmbed && <>
							{(mode === 'placeholder' || isPlaceholder) && <>
								<PlaceholderImageControl
									value={placeholderIndex}
									onChange={nextIndex => {
										setAttributes({
											skaBlocksBackground: {
												...skaBlocksBackground,
												placeholderIndex: nextIndex,
												...(mode === 'placeholder' && nextIndex > 0 && {
													mode: 'image',
												}),
												...(nextIndex < 1 && mode !== 'placeholder' && {
													mode: 'placeholder',
												}),
												...(nextIndex > 0 ? {
													src: PLACEHOLDER_SRC_PLACEHOLDER,
												} : {
													src: PLACEHOLDER_SRC,
												}),
											},
										})
									}}
								/>
							</>}
							{mode === 'image' && <>
								<ButtonGroup.Radio
									fluid
									label={_x('Loading', 'Title for image "loading" attribute', 'ska-blocks')}
									options={LOADING}
									value={loading}
									onChange={value => value && setAttribute('loading', value)}
									useDefaultButtons
								/>
								{!!id && <>
									<WithTooltip tooltip={__('Add "srcset" and "sizes" attributes to background image when possible.', 'ska-blocks')}>
										<ToggleControl
											label={__('Responsive', 'ska-blocks')}
											checked={srcset}
											onChange={() => setAttribute('srcset', !srcset)}
											__nextHasNoMarginBottom
										/>
									</WithTooltip>
									<WithTooltip tooltip={__('Add a low quality version of the image as a placeholder background.', 'ska-blocks')}>
										<ToggleControl
											label={__('Low-res placeholder', 'ska-blocks')}
											checked={placeholder}
											onChange={() => setAttribute('placeholder', !placeholder)}
											__nextHasNoMarginBottom
										/>
									</WithTooltip>
									{placeholder && <>
										<WithTooltip tooltip={__('Pre-load low-res placeholder image in document head.', 'ska-blocks')}>
											<ToggleControl
												label={__('Preload placeholder', 'ska-blocks')}
												checked={preloadPlaceholder}
												onChange={() => setAttribute('preloadPlaceholder', !preloadPlaceholder)}
												__nextHasNoMarginBottom
											/>
										</WithTooltip>
									</>}
								</>}
							</>}
							<RangeControl
								label={__('Opacity', 'ska-blocks')}
								value={Math.round(opacity * 100)}
								onChange={value => {
									if(Number.isNaN(value)) {
										return
									}
									setAttribute('opacity', Number(value) / 100)
								}}
								min={1}
								max={100}
								__nextHasNoMarginBottom
								__next40pxDefaultSize
							/>
							<ButtonGroup.Radio
								isSmall
								pills
								fluid
								label={__('Size', 'ska-blocks')}
								options={mode === 'background' ? BACKGROUND_SIZE.filter(({value}) => VALID_BACKGROUND_SIZES.includes(value)) : BACKGROUND_SIZE}
								value={size}
								onChange={value => value && setAttribute('size', value)}
							/>
							{mode === 'background' && (
								<ButtonGroup.Radio
									isSmall
									pills
									label={__('Repeat', 'ska-blocks')}
									options={BACKGROUND_REPEAT}
									value={repeat}
									onChange={value => value && setAttribute('repeat', value)}
								/>
							)}
							<FocalPointPicker
								label={__('Focal point', 'ska-blocks')}
								url={getSrc(skaBlocksBackground)}
								value={focalPoint}
								onChange={nextFocalPoint => setAttribute('focalPoint', nextFocalPoint)}
								__nextHasNoMarginBottom
							/>
						</>}
						{(mode === 'image' || mode === 'background') && id && <>
							<ImageSizeControl
								id={id}
								src={src}
								onChange={({src}) => setAttribute('src', src)}
							/>
						</>}
						{mode === 'video' && <>
							<ToggleControl
								label={__('Play in editor', 'ska-blocks')}
								help={__('Uncheck to disable autoplaying the video in the block editor.', 'ska-blocks')}
								checked={play}
								onChange={() => setAttribute('play', !play)}
								__nextHasNoMarginBottom
							/>
							{posterSrc && <>
								{posterId && <>
									<ImageSizeControl
										label={__('Poster source image', 'ska-blocks')}
										id={posterId}
										src={posterSrc}
										onChange={({src}) => setAttribute('posterSrc', src)}
									/>
								</>}
								<ToggleControl
									label={__('Preload poster image', 'ska-blocks')}
									help={__('Start fetching the poster image as early as possible with high priority.', 'ska-blocks')}
									checked={preloadPoster}
									onChange={() => setAttribute('preloadPoster', !preloadPoster)}
									__nextHasNoMarginBottom
								/>
							</>}
						</>}
					</>}
				</SkaPanelBody>
			)}
		</InspectorControls>
	</>
}

const withBackgroundControls = createHigherOrderComponent(
	(BlockEdit: any) => (props: tBlockEditProps) => {
		if(hasBackgroundSupport(props.name)) {
			return <>
				<BackgroundInspectorControls {...props as any as tBlockEditProps<BackgroundAttributes>} />
				<BlockEdit {...props} />
			</>
		}
		return <BlockEdit {...props} />
	},
	'withSkaBlocksBackground'
)

const getSrc = (skaBlocksBackground: BackgroundValue): string => {

	if(!skaBlocksBackground) {
		return ''
	}

	const {
		src,
	} = skaBlocksBackground

	if(!src) {
		return ''
	}

	if(src === PLACEHOLDER_SRC_PLACEHOLDER) {

		const {
			mode = 'image',
		} = skaBlocksBackground

		if(!placeholderImageUrl || !['image', 'background'].includes(mode)) {
			return ''
		}

		const {
			placeholderIndex = 1,
		} = skaBlocksBackground

		// @ts-expect-error
		const placeholderSrc = sprintf(placeholderImageUrl, placeholderIndex)

		if(placeholderSrc.indexOf(homeUrl) === 0) {
			return placeholderSrc.replace(homeUrl, '/')
		}

		return placeholderSrc
	}

	return src
}

export const getBackgroundTailwindClassNames = (skaBlocksBackground: BackgroundValue = {}): string => {

	const src = getSrc(skaBlocksBackground)
	if(!src) {
		return ''
	}

	return 'has-ska-bg'
}

const withBackgroundTailwindClassNames = (classNames: string = '', attributes: tBlockAttributes = {}) => {

	if(getSrc(attributes?.skaBlocksBackground)) {

		const tailwindClassNames = getBackgroundTailwindClassNames(attributes.skaBlocksBackground)
		if(classNames.indexOf(tailwindClassNames) === -1) {
			return cx(tailwindClassNames, classNames)
		}
	}

	return classNames
}

const getBackgroundElement = (skaBlocksBackground: BackgroundValue, save = false): React.ReactNode => {

	const {
		mode = 'image',
		id,
		posterSrc,
		loading = 'lazy',
		size = BACKGROUND_SIZE[0].value,
		repeat = BACKGROUND_REPEAT[0].value,
		opacity = 1,
		focalPoint = DEFAULT_FOCAL_POINT,
		play = true,
	} = skaBlocksBackground

	const src = getSrc(skaBlocksBackground)
	if(!src) {
		return null
	}

	const className = cx('ska-bg', [
		...(id ? [`ska-bg-${id}`] : []),
	])

	if(mode === 'video') {
		return (
			<video
				key={save ? undefined : `video-${id}-${play ? 'playing' : 'paused'}`}
				className={className}
				src={src}
				{...(posterSrc && {
					poster: posterSrc,
				})}
				muted
				loop
				playsInline
				autoPlay={save ? true : play}
				disablePictureInPicture
				disableRemotePlayback
				controls={false}
				style={{
					// @ts-expect-error
					objectFit: size,
					objectPosition: mediaPosition(focalPoint),
					...(opacity < 1 && {opacity}),
				}}
				aria-hidden={true}
			/>
		)
	}

	if(mode === 'image' || mode === 'placeholder') {
		return (
			<img
				className={className}
				src={src}
				decoding={loading === 'preload' ? 'sync' : 'async'}
				{...(loading === 'lazy' && {
					loading: 'lazy',
				})}
				style={{
					// @ts-expect-error
					objectFit: size,
					objectPosition: mediaPosition(focalPoint),
					...(opacity < 1 && {opacity}),
				}}
				aria-hidden={true}
			/>
		)
	}

	return (
		<div
			className={className}
			style={{
				backgroundImage: `url(${src})`,
				...(VALID_BACKGROUND_SIZES.includes(size) && {
					backgroundSize: size,
				}),
				backgroundRepeat: repeat,
				...(opacity < 1 && {opacity}),
				backgroundPosition: mediaPosition(focalPoint),
			}}
		/>
	)
}

export const useBackground = (props: tBlockEditProps<BackgroundAttributes>, innerBlocksProps: tBlockEditInnerBlocksProps): tBlockEditInnerBlocksProps => {

	const {
		attributes = {},
	} = props

	const {
		skaBlocksBackground = {},
	} = attributes

	const src = getSrc(skaBlocksBackground)
	if(!src) {
		return innerBlocksProps
	}

	return {
		...innerBlocksProps,
		className: withBackgroundTailwindClassNames(innerBlocksProps.className, attributes),
		children: <>
			{getBackgroundElement(skaBlocksBackground)}
			{innerBlocksProps.children}
		</>,
	}
}

useBackground.save = (props: tBlockSaveProps<BackgroundAttributes>, innerBlocksProps: tBlockSaveInnerBlocksProps): tBlockSaveInnerBlocksProps => {

	const {
		attributes = {},
	} = props

	const {
		skaBlocksBackground = {},
	} = attributes

	const src = getSrc(skaBlocksBackground)
	if(!src) {
		return innerBlocksProps
	}

	return {
		...innerBlocksProps,
		className: withBackgroundTailwindClassNames(innerBlocksProps.className, attributes),
		children: <>
			{getBackgroundElement(skaBlocksBackground, true)}
			{innerBlocksProps.children}
		</>,
	}
}

const withBackgroundPlugin = (plugins: Record<string, string>) => {

	if(!(BACKGROUND_SUPPORT_KEY in plugins)) {

		plugins[BACKGROUND_SUPPORT_KEY] = `
			@utility has-ska-bg {

				:where(&) {
					position: relative;
				}

				& .ska-bg {
					position: absolute;
					inset: 0;
					width: 100%;
					height: 100%;
					border-radius: inherit;
					user-select: none;
					pointer-events: none;
				}

				:where(& .ska-bg ~ *) {
					position: relative;
				}
			}
		`
	}

	return plugins
}

export const registerTailwindPlugins = () => {
	addFilter('ska.blocks.tailwind.staticPlugins', 'ska-blocks/with-background-plugin', withBackgroundPlugin)
}

export default () => {
	addFilter('blocks.registerBlockType', 'ska-blocks/with-background-support', withBackgroundSupport)
	addFilter('editor.BlockEdit', 'ska-blocks/with-background-controls', withBackgroundControls, 450)
	addFilter('ska.blocks.tailwindClassNames', 'ska-blocks/with-background-tailwind-classnames', withBackgroundTailwindClassNames)
}
