import * as React from 'react' import {__, _x} from '@wordpress/i18n' import { hasBlockSupport, // @ts-expect-error } from '@wordpress/blocks' import { useMemo, } from '@wordpress/element' import { addFilter, } from '@wordpress/hooks' import { BlockControls, // @ts-expect-error } from '@wordpress/block-editor' import { ToolbarGroup, } from '@wordpress/components' import { ButtonGroup, } from '@ska/components' import { URLPicker, } from '../components' import { dynamicLinks, } from '../data' import { usePluginOptions, } from '../plugins/options' import { kebabCase, } from '@ska/utils' import type { tBlockEditProps, tBlockNameOrType, tBlockSaveProps, tBlockType, } from '@ska/shared' export interface DynamicLinkOption { label: string value: string } export interface LinkValue { href?: string opensInNewTab?: boolean id?: number kind?: string type?: string } export interface LinkAttributes { skaBlocksLink?: LinkValue } export const LINK_SUPPORT_KEY = 'skaBlocksLink' export const LINK_SUPPORT_DEFAULT_ENABLED = false export const hasLinkSupport = (block: tBlockNameOrType) => hasBlockSupport(block, LINK_SUPPORT_KEY, LINK_SUPPORT_DEFAULT_ENABLED) const withCustomAttributes = (settings: tBlockType) => { if(!hasLinkSupport(settings)) { return settings } if(!settings.attributes.skaBlocksLink) { Object.assign(settings.attributes, { skaBlocksLink: { type: 'object', }, }) } return settings } export const useUserDynamicLinks = () => { const { userDynamicLinks = {}, } = usePluginOptions() return useMemo(() => { return Object.keys(userDynamicLinks).map(key => { return { label: key, value: `#ska-link--${kebabCase(key)}`, tooltip: userDynamicLinks[key], } }) }, [userDynamicLinks]) } const DEFAULT_ADDITIONAL_DYNAMIC_LINKS = [] as DynamicLinkOption[] export const useDynamicLinks = (additionalDynamicLinks = DEFAULT_ADDITIONAL_DYNAMIC_LINKS) => { const userDynamicLinks = useUserDynamicLinks() return useMemo(() => [ ...dynamicLinks, ...additionalDynamicLinks, ...userDynamicLinks, ], [additionalDynamicLinks, userDynamicLinks]) } export const LinkControls: React.FC & {additionalDynamicLinks?: DynamicLinkOption[]}> = (props) => { const { attributes, setAttributes, additionalDynamicLinks = [], } = props const { skaBlocksLink = {}, } = attributes const { href = '', opensInNewTab = false, } = skaBlocksLink const dynamicLinks = useDynamicLinks(additionalDynamicLinks) return <> { setAttributes({skaBlocksLink: {...skaBlocksLink, href: nextValue, id, kind, type}}) }} opensInNewTab={opensInNewTab} onToggleOpensInNewTab={() => setAttributes({skaBlocksLink: {...skaBlocksLink, opensInNewTab: !opensInNewTab}})} renderControlBottom={dynamicLinks.length > 0 ? ( { setAttributes({ skaBlocksLink: { ...skaBlocksLink, href: nextValue, opensInNewTab, id: undefined, kind: undefined, type: undefined, }, }) }} /> ) : null} /> } export interface LinkProps { href?: string 'data-ska-href'?: string target?: string rel?: string } const getLink = (attributes: LinkAttributes, save = false): LinkProps => { const { skaBlocksLink = {}, } = attributes const { href = '', opensInNewTab = false, } = skaBlocksLink return { ...(href && { [save ? 'href' : 'data-ska-href']: href, ...(opensInNewTab && { target: '_blank', rel: 'noopener noreferrer', }), }), } } export const useLink = (props: tBlockEditProps): Omit => { return getLink(props.attributes, false) } useLink.save = (props: tBlockSaveProps): Omit => { return getLink(props.attributes, true) } export const useLinkWrapper = (Element: string, props: tBlockEditProps): [string, Omit] => { const linkProps = getLink(props.attributes, false) const As = Object.keys(linkProps).length > 0 ? 'a' : Element return [As, linkProps] } useLinkWrapper.save = (Element: string, props: tBlockSaveProps): [string, Omit] => { const linkProps = getLink(props.attributes, true) const As = Object.keys(linkProps).length > 0 ? 'a' : Element return [As, linkProps] } export default () => { addFilter('blocks.registerBlockType', 'ska-blocks/with-link-attributes', withCustomAttributes) }