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