inline.js
112 lines
| 1 | /** |
| 2 | * WordPress dependencies |
| 3 | */ |
| 4 | import { |
| 5 | removeFormat, |
| 6 | getActiveFormat, |
| 7 | useAnchor, |
| 8 | useAnchorRef, |
| 9 | } from '@wordpress/rich-text'; |
| 10 | import { ColorPalette, useCachedTruthy } from '@wordpress/block-editor'; |
| 11 | import { Popover } from '@wordpress/components'; |
| 12 | |
| 13 | /** |
| 14 | * Internal dependencies |
| 15 | */ |
| 16 | import { highlighColor as settings, highlighterOnApply } from './common'; |
| 17 | |
| 18 | export function getGradientDirectionByWritingMode(contentRef) { |
| 19 | if (!contentRef?.current) { |
| 20 | return ''; |
| 21 | } |
| 22 | let el = contentRef.current; |
| 23 | while (el) { |
| 24 | const writingMode = window.getComputedStyle(el).writingMode; |
| 25 | if (writingMode && writingMode.startsWith('vertical')) { |
| 26 | if (writingMode === 'vertical-rl') { |
| 27 | return 'to left'; |
| 28 | } |
| 29 | if (writingMode === 'vertical-lr') { |
| 30 | return 'to right'; |
| 31 | } |
| 32 | return 'to left'; // デフォルトで縦書きは左 |
| 33 | } |
| 34 | el = el.parentElement; |
| 35 | } |
| 36 | return ''; // 横書き |
| 37 | } |
| 38 | |
| 39 | export function getActiveColors(value, name) { |
| 40 | const activeColorFormat = getActiveFormat(value, name); |
| 41 | |
| 42 | if (!activeColorFormat) { |
| 43 | return undefined; |
| 44 | } |
| 45 | |
| 46 | return activeColorFormat.attributes.data; |
| 47 | } |
| 48 | |
| 49 | function ColorPicker({ name, value, onChange, setIsAddingColor, contentRef }) { |
| 50 | const onColorChange = (color) => { |
| 51 | if (color) { |
| 52 | // select color on palette |
| 53 | const direction = getGradientDirectionByWritingMode(contentRef); |
| 54 | highlighterOnApply({ |
| 55 | color, |
| 56 | value, |
| 57 | onChange, |
| 58 | direction, |
| 59 | }); |
| 60 | } else { |
| 61 | // clear palette |
| 62 | onChange(removeFormat(value, name)); |
| 63 | setIsAddingColor(false); |
| 64 | } |
| 65 | }; |
| 66 | |
| 67 | const activeColor = getActiveColors(value, name); |
| 68 | |
| 69 | return <ColorPalette value={activeColor} onChange={onColorChange} />; |
| 70 | } |
| 71 | |
| 72 | export default function InlineColorUI({ |
| 73 | name, |
| 74 | value, |
| 75 | onChange, |
| 76 | onClose, |
| 77 | contentRef, |
| 78 | setIsAddingColor, |
| 79 | }) { |
| 80 | /* |
| 81 | As you change the text color by typing a HEX value into a field, |
| 82 | the return value of document.getSelection jumps to the field you're editing, |
| 83 | not the highlighted text. Given that useAnchor uses document.getSelection, |
| 84 | it will return null, since it can't find the <mark> element within the HEX input. |
| 85 | This caches the last truthy value of the selection anchor reference. |
| 86 | */ |
| 87 | |
| 88 | // NOTE: useAnchorRefが非推奨になったのでフォールバック WP6.0以下をサポートしなくなったら削除すること #1456 |
| 89 | const existsUseAnchor = typeof useAnchor === 'function'; |
| 90 | const _useAnchor = existsUseAnchor ? useAnchor : useAnchorRef; |
| 91 | const useAnchorObj = existsUseAnchor |
| 92 | ? { editableContentElement: contentRef.current, value, settings } |
| 93 | : { ref: contentRef, value }; |
| 94 | const popoverAnchor = useCachedTruthy(_useAnchor(useAnchorObj)); |
| 95 | |
| 96 | return ( |
| 97 | <Popover |
| 98 | onClose={onClose} |
| 99 | className="vk-blocks-format-popover components-inline-color-popover" |
| 100 | anchor={popoverAnchor} |
| 101 | > |
| 102 | <ColorPicker |
| 103 | name={name} |
| 104 | value={value} |
| 105 | onChange={onChange} |
| 106 | setIsAddingColor={setIsAddingColor} |
| 107 | contentRef={contentRef} |
| 108 | /> |
| 109 | </Popover> |
| 110 | ); |
| 111 | } |
| 112 |