| 1 |
import { Button, ColorPalette, Popover } from '@wordpress/components'; |
| 2 |
import { useDispatch, useSelect } from '@wordpress/data'; |
| 3 |
import { useRef, useState } from '@wordpress/element'; |
| 4 |
import { __ } from '@wordpress/i18n'; |
| 5 |
import { |
| 6 |
applyColorFormat, |
| 7 |
captureDomRichTextSelection, |
| 8 |
} from '../../lib/rich-text-color'; |
| 9 |
|
| 10 |
export function ColorButton({ kind, label, iconClassName }) { |
| 11 |
const [open, setOpen] = useState(false); |
| 12 |
const wrapRef = useRef(null); |
| 13 |
const frozenSel = useRef(null); |
| 14 |
|
| 15 |
const sel = useSelect((select) => { |
| 16 |
const editor = select('core/block-editor'); |
| 17 |
const start = editor.getSelectionStart(); |
| 18 |
const end = editor.getSelectionEnd(); |
| 19 |
if (!start || !start.clientId) return null; |
| 20 |
const block = editor.getBlock(start.clientId); |
| 21 |
if (!block) return null; |
| 22 |
const settings = editor.getSettings() || {}; |
| 23 |
return { start, end, block, palette: settings.colors || [] }; |
| 24 |
}, []); |
| 25 |
|
| 26 |
// React-context registry dispatch; the outer wp.data.dispatch can't see this block. |
| 27 |
const dispatch = useDispatch('core/block-editor'); |
| 28 |
|
| 29 |
return ( |
| 30 |
<div className="relative inline-flex items-center" ref={wrapRef}> |
| 31 |
<Button |
| 32 |
className="extendify-quick-edit-color-button" |
| 33 |
label={label} |
| 34 |
aria-expanded={open} |
| 35 |
onMouseDown={(ev) => { |
| 36 |
// Capture selection before focus moves to the popover and discards it. |
| 37 |
ev.preventDefault(); |
| 38 |
frozenSel.current = { |
| 39 |
sel, |
| 40 |
dom: captureDomRichTextSelection(), |
| 41 |
}; |
| 42 |
}} |
| 43 |
onClick={() => setOpen((v) => !v)} |
| 44 |
icon={ |
| 45 |
<span |
| 46 |
className={`relative inline-flex h-[20px] w-[20px] items-center justify-center text-[15px] font-semibold leading-none text-gray-900 font-qe ${iconClassName}`} |
| 47 |
aria-hidden="true" |
| 48 |
/> |
| 49 |
} |
| 50 |
/> |
| 51 |
{open ? ( |
| 52 |
<Popover |
| 53 |
placement="bottom-start" |
| 54 |
onClose={() => setOpen(false)} |
| 55 |
focusOnMount="firstElement" |
| 56 |
className="extendify-quick-edit extendify-quick-edit-color-popover" |
| 57 |
anchor={wrapRef.current} |
| 58 |
> |
| 59 |
<div className="extendify-quick-edit-color-popover-inner"> |
| 60 |
<ColorPalette |
| 61 |
colors={sel?.palette || []} |
| 62 |
onChange={(c) => { |
| 63 |
applyColorFormat(frozenSel.current, kind, c, dispatch); |
| 64 |
setOpen(false); |
| 65 |
}} |
| 66 |
clearable |
| 67 |
disableCustomColors={false} |
| 68 |
enableAlpha={false} |
| 69 |
/> |
| 70 |
<Button |
| 71 |
variant="tertiary" |
| 72 |
className="extendify-quick-edit-color-clear" |
| 73 |
onClick={() => { |
| 74 |
applyColorFormat(frozenSel.current, kind, null, dispatch); |
| 75 |
setOpen(false); |
| 76 |
}} |
| 77 |
> |
| 78 |
{kind === 'text' |
| 79 |
? __('Clear text color', 'extendify-local') |
| 80 |
: __('Clear highlight', 'extendify-local')} |
| 81 |
</Button> |
| 82 |
</div> |
| 83 |
</Popover> |
| 84 |
) : null} |
| 85 |
</div> |
| 86 |
); |
| 87 |
} |
| 88 |
|