import { FC, useEffect, useId, useState } from 'react'; import JSXStyle from 'styled-jsx/style'; import { RectangleItem as TRectangleItem, getLayoutStyles, FillLayer } from '@cntrl-site/sdk'; import { CntrlColor } from '@cntrl-site/color'; import { ItemProps } from '../Item'; import { LinkWrapper } from '../LinkWrapper'; import { useRectangleItem } from './useRectangleItem'; import { useItemAngle } from '../useItemAngle'; import { useCntrlContext } from '../../../provider/useCntrlContext'; import { useRegisterResize } from '../../../common/useRegisterResize'; import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams'; import { getFill } from '../../../utils/getFill'; import { areFillsVisible } from '../../../utils/areFillsVisible/areFillsVisible'; import { useItemGeometry } from '../../../ItemGeometry/useItemGeometry'; export const RectangleItem: FC> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => { const reactId = useId(); const id = `${reactId}-rect-${item.id}`; const { layouts } = useCntrlContext(); const { fill: itemFill, radius: itemRadius, strokeWidth: itemStrokeWidth, strokeFill: itemStrokeFill, blur: itemBlur, backdropBlur: itemBackdropBlur } = useRectangleItem(item, sectionId); const itemAngle = useItemAngle(item, sectionId); const stateParams = interactionCtrl?.getState(['angle', 'blur', 'backdropBlur']); const stateFillParams = interactionCtrl?.getState(['fill', 'strokeWidth', 'radius', 'strokeFill']); const stateFillLayers = stateFillParams?.styles?.fill; const fillTransition = stateFillParams?.transition ?? 'none'; const styles = stateParams?.styles ?? {}; const layoutValues: Record[] = [item.area, item.layoutParams]; const [ref, setRef] = useState(null); useRegisterResize(ref, onResize); useItemGeometry(item.id, ref); const backdropBlur = getStyleFromItemStateAndParams(styles?.backdropBlur, itemBackdropBlur); const radius = getStyleFromItemStateAndParams(stateFillParams?.styles?.radius, itemRadius); const strokeWidth = getStyleFromItemStateAndParams(stateFillParams?.styles?.strokeWidth, itemStrokeWidth); const strokeFill = getStyleFromItemStateAndParams(stateFillParams?.styles?.strokeFill?.[0], itemStrokeFill?.[0]) ?? itemStrokeFill?.[0]; const angle = getStyleFromItemStateAndParams(styles?.angle, itemAngle); const blur = getStyleFromItemStateAndParams(styles?.blur, itemBlur); const backdropFilterValue = backdropBlur ? `blur(${backdropBlur * 100}vw)` : undefined; const isInteractive = areFillsVisible(stateFillLayers ?? itemFill ?? []) || (strokeWidth !== 0 && strokeFill && strokeFill.value && CntrlColor.parse(strokeFill.value).getAlpha() !== 0); useEffect(() => { onVisibilityChange?.(isInteractive); }, [isInteractive, onVisibilityChange]); const stroke = strokeFill ? getFill(strokeFill) ?? 'transparent' : 'transparent'; return ( <>
{itemFill && itemFill.map((fill, index) => { const stateFillLayer = stateFillLayers?.find((layer: FillLayer) => layer.id === fill.id); const value = stateFillLayer ? (getStyleFromItemStateAndParams(stateFillLayer, fill) ?? fill) : fill; const background = value ? getFill(value) ?? 'transparent' : 'transparent'; return ( ); })}
{` .rectangle-${item.id} { position: absolute; width: 100%; height: 100%; box-sizing: border-box; }, .image-fill-${item.id} { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transform-origin: center center; z-index: 1; background-position: center; }, ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams]) => { return (` .rectangle-${item.id} { border-radius: ${layoutParams.radius * 100}vw; transform: rotate(${area.angle}deg); filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'}; ${layoutParams.blur !== 0 ? 'will-change: transform;' : ''}; backdrop-filter: ${layoutParams.backdropBlur !== 0 ? `blur(${layoutParams.backdropBlur * 100}vw)` : 'unset'}; -webkit-backdrop-filter: ${layoutParams.backdropBlur !== 0 ? `blur(${layoutParams.backdropBlur * 100}vw)` : 'unset'}; } `); })} `}
); }; function Fill({ fill, itemId, background, fillTransition, radius, strokeWidth, isHighest, borderColor }: { fill: FillLayer; itemId: string; background: string; fillTransition: string; radius: number; strokeWidth: number; isHighest: boolean; borderColor: string; }) { const isRotatedImage = fill.type === 'image' && fill.rotation && fill.rotation !== 0; return (
); };