| 1 |
import { __ } from "@wordpress/i18n"; |
| 2 |
import { |
| 3 |
__experimentalColorGradientControl as ColorGradientControl, |
| 4 |
__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients, |
| 5 |
} from "@wordpress/block-editor"; |
| 6 |
import { |
| 7 |
Button, |
| 8 |
ColorIndicator, |
| 9 |
Dropdown, |
| 10 |
FlexItem, |
| 11 |
__experimentalHStack as HStack, |
| 12 |
__experimentalDropdownContentWrapper as DropdownContentWrapper, |
| 13 |
} from "@wordpress/components"; |
| 14 |
import { reset as resetIcon } from "@wordpress/icons"; |
| 15 |
import { useRef } from "react"; |
| 16 |
import classNames from "classnames"; |
| 17 |
|
| 18 |
import "./color-dropdown-style.scss"; |
| 19 |
|
| 20 |
interface ColorDropdownProps { |
| 21 |
label: string; |
| 22 |
colorValue: string | undefined | null; |
| 23 |
gradientValue?: string | null; |
| 24 |
onColorChange: (newValue: string | undefined) => void; |
| 25 |
onGradientChange?: (newValue: string | undefined) => void; |
| 26 |
onDeselect?: () => void; |
| 27 |
allowGradient?: boolean; |
| 28 |
enableAlpha?: boolean; |
| 29 |
} |
| 30 |
|
| 31 |
const LabeledColorIndicator = ({ |
| 32 |
colorValue, |
| 33 |
label, |
| 34 |
}: { |
| 35 |
colorValue: string | undefined | null; |
| 36 |
label: string; |
| 37 |
}) => ( |
| 38 |
<HStack justify="flex-start"> |
| 39 |
<ColorIndicator |
| 40 |
className="block-editor-panel-color-gradient-settings__color-indicator" |
| 41 |
colorValue={colorValue || ""} |
| 42 |
/> |
| 43 |
<FlexItem |
| 44 |
className="block-editor-panel-color-gradient-settings__color-name" |
| 45 |
title={label} |
| 46 |
> |
| 47 |
{label} |
| 48 |
</FlexItem> |
| 49 |
</HStack> |
| 50 |
); |
| 51 |
|
| 52 |
function ColorDropdown({ |
| 53 |
label, |
| 54 |
colorValue, |
| 55 |
gradientValue, |
| 56 |
onColorChange, |
| 57 |
onGradientChange, |
| 58 |
onDeselect, |
| 59 |
allowGradient = false, |
| 60 |
enableAlpha = true, |
| 61 |
}: ColorDropdownProps) { |
| 62 |
const colorGradientSettings = useMultipleOriginColorsAndGradients(); |
| 63 |
const colorButtonRef = useRef<HTMLButtonElement>(null); |
| 64 |
|
| 65 |
const lastColor = useRef(colorValue); |
| 66 |
const lastGradient = useRef(gradientValue); |
| 67 |
|
| 68 |
const value = colorValue ?? gradientValue; |
| 69 |
const clearable = !!value; |
| 70 |
|
| 71 |
const clearValue = () => { |
| 72 |
if (colorValue) { |
| 73 |
onColorChange(undefined); |
| 74 |
} else if (gradientValue && onGradientChange) { |
| 75 |
onGradientChange(undefined); |
| 76 |
} |
| 77 |
onDeselect?.(); |
| 78 |
}; |
| 79 |
|
| 80 |
const handleColorChange = (newColor: string | undefined) => { |
| 81 |
if (lastColor.current !== newColor) { |
| 82 |
lastColor.current = newColor; |
| 83 |
onColorChange(newColor); |
| 84 |
} |
| 85 |
}; |
| 86 |
|
| 87 |
const handleGradientChange = (newGradient: string | undefined) => { |
| 88 |
if (onGradientChange && lastGradient.current !== newGradient) { |
| 89 |
lastGradient.current = newGradient; |
| 90 |
onGradientChange(newGradient); |
| 91 |
} |
| 92 |
}; |
| 93 |
|
| 94 |
return ( |
| 95 |
<HStack className="tableberg-color-dropdown"> |
| 96 |
<Dropdown |
| 97 |
popoverProps={{ |
| 98 |
placement: "left-start", |
| 99 |
offset: 36, |
| 100 |
shift: true, |
| 101 |
}} |
| 102 |
className="block-editor-tools-panel-color-gradient-settings__dropdown" |
| 103 |
renderToggle={({ onToggle, isOpen }) => ( |
| 104 |
<Button |
| 105 |
__next40pxDefaultSize |
| 106 |
onClick={onToggle} |
| 107 |
className={classNames( |
| 108 |
"block-editor-panel-color-gradient-settings__dropdown", |
| 109 |
{ "is-open": isOpen } |
| 110 |
)} |
| 111 |
aria-expanded={isOpen} |
| 112 |
ref={colorButtonRef} |
| 113 |
> |
| 114 |
<LabeledColorIndicator |
| 115 |
colorValue={value} |
| 116 |
label={label} |
| 117 |
/> |
| 118 |
</Button> |
| 119 |
)} |
| 120 |
renderContent={() => ( |
| 121 |
<DropdownContentWrapper paddingSize="none"> |
| 122 |
<div className="block-editor-panel-color-gradient-settings__dropdown-content"> |
| 123 |
<ColorGradientControl |
| 124 |
{...colorGradientSettings} |
| 125 |
enableAlpha={enableAlpha} |
| 126 |
label={label} |
| 127 |
colorValue={colorValue} |
| 128 |
onColorChange={handleColorChange} |
| 129 |
gradientValue={ |
| 130 |
allowGradient ? gradientValue : undefined |
| 131 |
} |
| 132 |
onGradientChange={ |
| 133 |
allowGradient |
| 134 |
? handleGradientChange |
| 135 |
: undefined |
| 136 |
} |
| 137 |
showTitle={false} |
| 138 |
clearable={false} |
| 139 |
__experimentalIsRenderedInSidebar |
| 140 |
/> |
| 141 |
</div> |
| 142 |
</DropdownContentWrapper> |
| 143 |
)} |
| 144 |
/> |
| 145 |
{clearable && ( |
| 146 |
<Button |
| 147 |
__next40pxDefaultSize |
| 148 |
label={__("Reset", "tableberg")} |
| 149 |
className="block-editor-panel-color-gradient-settings__reset" |
| 150 |
size="small" |
| 151 |
icon={resetIcon} |
| 152 |
onClick={() => { |
| 153 |
clearValue(); |
| 154 |
colorButtonRef.current?.focus(); |
| 155 |
}} |
| 156 |
/> |
| 157 |
)} |
| 158 |
</HStack> |
| 159 |
); |
| 160 |
} |
| 161 |
|
| 162 |
export default ColorDropdown; |
| 163 |
|