Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: WordPress/gutenberg
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d2bef1d514cc8d0d532e811db5d575eb1ec1b303
Choose a base ref
...
head repository: WordPress/gutenberg
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f06dcd92b067ddb0954d27e382a3625f4744f25c
Choose a head ref
  • 2 commits
  • 12 files changed
  • 2 contributors

Commits on Nov 8, 2020

  1. Format library: introduce useAnchorRef (#26782)

    * Format library: introduce useAnchorRef
    
    * Add doc
    
    * Reorg
    
    * Explicitly pass down props
    
    * Fix ref type
    ellatrix authored Nov 8, 2020
    Copy the full SHA
    707540c View commit details

Commits on Nov 9, 2020

  1. [Android] Image block - upload multiple (#24346)

    * Set appends as siblings flag for image block uploads
    
    * Update changelog
    mkevins authored Nov 9, 2020
    Copy the full SHA
    f06dcd9 View commit details
55 changes: 26 additions & 29 deletions packages/format-library/src/image/index.js
Original file line number Diff line number Diff line change
@@ -3,8 +3,8 @@
*/
import { Path, SVG, TextControl, Popover, Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useMemo, useState } from '@wordpress/element';
import { insertObject } from '@wordpress/rich-text';
import { useState } from '@wordpress/element';
import { insertObject, useAnchorRef } from '@wordpress/rich-text';
import {
MediaUpload,
RichTextToolbarButton,
@@ -18,6 +18,22 @@ const ALLOWED_MEDIA_TYPES = [ 'image' ];
const name = 'core/image';
const title = __( 'Inline image' );

export const image = {
name,
title,
keywords: [ __( 'photo' ), __( 'media' ) ],
object: true,
tagName: 'img',
className: null,
attributes: {
className: 'class',
style: 'style',
url: 'src',
alt: 'alt',
},
edit: Edit,
};

function stopKeyPropagation( event ) {
event.stopPropagation();
}
@@ -33,18 +49,14 @@ function onKeyDown( event ) {
}
}

function InlineUI( {
value,
onChange,
isObjectActive,
activeObjectAttributes,
} ) {
function InlineUI( { value, onChange, activeObjectAttributes, contentRef } ) {
const { style } = activeObjectAttributes;
const [ width, setWidth ] = useState( style.replace( /\D/g, '' ) );
const anchorRef = useMemo( () => {
const selection = window.getSelection();
return selection.rangeCount ? selection.getRangeAt( 0 ) : null;
}, [ isObjectActive ] );
const anchorRef = useAnchorRef( {
ref: contentRef,
value,
settings: image,
} );

return (
<Popover
@@ -104,6 +116,7 @@ function Edit( {
onFocus,
isObjectActive,
activeObjectAttributes,
contentRef,
} ) {
const [ isModalOpen, setIsModalOpen ] = useState( false );

@@ -159,26 +172,10 @@ function Edit( {
<InlineUI
value={ value }
onChange={ onChange }
isObjectActive={ isObjectActive }
activeObjectAttributes={ activeObjectAttributes }
contentRef={ contentRef }
/>
) }
</MediaUploadCheck>
);
}

export const image = {
name,
title,
keywords: [ __( 'photo' ), __( 'media' ) ],
object: true,
tagName: 'img',
className: null,
attributes: {
className: 'class',
style: 'style',
url: 'src',
alt: 'alt',
},
edit: Edit,
};
10 changes: 9 additions & 1 deletion packages/format-library/src/link/index.js
Original file line number Diff line number Diff line change
@@ -27,7 +27,14 @@ import InlineLinkUI from './inline';
const name = 'core/link';
const title = __( 'Link' );

function Edit( { isActive, activeAttributes, value, onChange, onFocus } ) {
function Edit( {
isActive,
activeAttributes,
value,
onChange,
onFocus,
contentRef,
} ) {
const [ addingLink, setAddingLink ] = useState( false );

function addLink() {
@@ -100,6 +107,7 @@ function Edit( { isActive, activeAttributes, value, onChange, onFocus } ) {
activeAttributes={ activeAttributes }
value={ value }
onChange={ onChange }
contentRef={ contentRef }
/>
) }
</>
37 changes: 11 additions & 26 deletions packages/format-library/src/link/inline.js
Original file line number Diff line number Diff line change
@@ -10,13 +10,20 @@ import { useMemo, useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { withSpokenMessages, Popover } from '@wordpress/components';
import { prependHTTP } from '@wordpress/url';
import { create, insert, isCollapsed, applyFormat } from '@wordpress/rich-text';
import {
create,
insert,
isCollapsed,
applyFormat,
useAnchorRef,
} from '@wordpress/rich-text';
import { __experimentalLinkControl as LinkControl } from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import { createLinkFormat, isValidHref } from './utils';
import { link as settings } from './index';

function InlineLinkUI( {
isActive,
@@ -26,6 +33,7 @@ function InlineLinkUI( {
onChange,
speak,
stopAddingLink,
contentRef,
} ) {
/**
* A unique key is generated when switching between editing and not editing
@@ -53,31 +61,6 @@ function InlineLinkUI( {
*/
const [ nextLinkValue, setNextLinkValue ] = useState();

const anchorRef = useMemo( () => {
const selection = window.getSelection();

if ( ! selection.rangeCount ) {
return;
}

const range = selection.getRangeAt( 0 );

if ( addingLink && ! isActive ) {
return range;
}

let element = range.startContainer;

// If the caret is right before the element, select the next element.
element = element.nextElementSibling || element;

while ( element.nodeType !== element.ELEMENT_NODE ) {
element = element.parentNode;
}

return element.closest( 'a' );
}, [ addingLink, value.start, value.end ] );

const linkValue = {
url: activeAttributes.url,
type: activeAttributes.type,
@@ -161,6 +144,8 @@ function InlineLinkUI( {
}
}

const anchorRef = useAnchorRef( { ref: contentRef, value, settings } );

return (
<Popover
key={ mountingKey }
10 changes: 8 additions & 2 deletions packages/format-library/src/text-color/index.js
Original file line number Diff line number Diff line change
@@ -25,7 +25,13 @@ const title = __( 'Text Color' );

const EMPTY_ARRAY = [];

function TextColorEdit( { value, onChange, isActive, activeAttributes } ) {
function TextColorEdit( {
value,
onChange,
isActive,
activeAttributes,
contentRef,
} ) {
const allowCustomControl = useEditorFeature( 'color.custom' );
const colors = useEditorFeature( 'color.palette' ) || EMPTY_ARRAY;
const [ isAddingColor, setIsAddingColor ] = useState( false );
@@ -78,11 +84,11 @@ function TextColorEdit( { value, onChange, isActive, activeAttributes } ) {
{ isAddingColor && (
<InlineColorUI
name={ name }
addingColor={ isAddingColor }
onClose={ disableIsAddingColor }
activeAttributes={ activeAttributes }
value={ value }
onChange={ onChange }
contentRef={ contentRef }
/>
) }
</>
54 changes: 11 additions & 43 deletions packages/format-library/src/text-color/inline.js
Original file line number Diff line number Diff line change
@@ -8,11 +8,11 @@ import { get } from 'lodash';
*/
import { useCallback, useMemo } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { getRectangleFromRange } from '@wordpress/dom';
import {
applyFormat,
removeFormat,
getActiveFormat,
useAnchorRef,
} from '@wordpress/rich-text';
import {
ColorPalette,
@@ -22,6 +22,11 @@ import {
getColorObjectByAttributeValues,
} from '@wordpress/block-editor';

/**
* Internal dependencies
*/
import { textColor as settings } from './index';

export function getActiveColor( formatName, formatValue, colors ) {
const activeColorFormat = getActiveFormat( formatValue, formatName );
if ( ! activeColorFormat ) {
@@ -41,44 +46,6 @@ export function getActiveColor( formatName, formatValue, colors ) {
}
}

const ColorPopoverAtLink = ( { addingColor, ...props } ) => {
// There is no way to open a text formatter popover when another one is mounted.
// The first popover will always be dismounted when a click outside happens, so we can store the
// anchor Rect during the lifetime of the component.
const anchorRect = useMemo( () => {
const selection = window.getSelection();
const range =
selection.rangeCount > 0 ? selection.getRangeAt( 0 ) : null;
if ( ! range ) {
return;
}

if ( addingColor ) {
return getRectangleFromRange( range );
}

let element = range.startContainer;

// If the caret is right before the element, select the next element.
element = element.nextElementSibling || element;

while ( element.nodeType !== element.ELEMENT_NODE ) {
element = element.parentNode;
}

const closest = element.closest( 'span' );
if ( closest ) {
return closest.getBoundingClientRect();
}
}, [] );

if ( ! anchorRect ) {
return null;
}

return <URLPopover anchorRect={ anchorRect } { ...props } />;
};

const ColorPicker = ( { name, value, onChange } ) => {
const colors = useSelect( ( select ) => {
const { getSettings } = select( 'core/block-editor' );
@@ -123,16 +90,17 @@ export default function InlineColorUI( {
value,
onChange,
onClose,
addingColor,
contentRef,
} ) {
const anchorRef = useAnchorRef( { ref: contentRef, value, settings } );
return (
<ColorPopoverAtLink
<URLPopover
value={ value }
addingColor={ addingColor }
onClose={ onClose }
className="components-inline-color-popover"
anchorRef={ anchorRef }
>
<ColorPicker name={ name } value={ value } onChange={ onChange } />
</ColorPopoverAtLink>
</URLPopover>
);
}
Original file line number Diff line number Diff line change
@@ -234,10 +234,11 @@ public void requestMediaPickFromMediaLibrary(MediaSelectedCallback mediaSelected
@Override
public void requestMediaPickFromDeviceLibrary(MediaSelectedCallback mediaSelectedCallback, Boolean allowMultipleSelection, MediaType mediaType) {
mMediaPickedByUserOnBlock = true;
mAppendsMultipleSelectedToSiblingBlocks = false;
// image blocks do not respect the multiple selection flag, so we set the append as siblings flag instead
mAppendsMultipleSelectedToSiblingBlocks = mediaType == MediaType.IMAGE && !allowMultipleSelection;
mMediaSelectedCallback = mediaSelectedCallback;
if (mediaType == MediaType.IMAGE) {
mOnMediaLibraryButtonListener.onUploadPhotoButtonClicked(allowMultipleSelection);
mOnMediaLibraryButtonListener.onUploadPhotoButtonClicked(true);
} else if (mediaType == MediaType.VIDEO) {
mOnMediaLibraryButtonListener.onUploadVideoButtonClicked(allowMultipleSelection);
} else if (mediaType == MediaType.MEDIA) {
4 changes: 4 additions & 0 deletions packages/react-native-editor/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -12,6 +12,10 @@ For each user feature we should also add a importance categorization label to i
## Unreleased
* [***] Faster editor start and overall operation on Android [#26732]

* [*] [Android] Enable multiple upload support for Image block

## 1.40.0

## 1.39.1

* [*] Heading block - Disable full-width/wide alignment [#26308]
18 changes: 18 additions & 0 deletions packages/rich-text/README.md
Original file line number Diff line number Diff line change
@@ -343,6 +343,24 @@ _Returns_

- `(RichTextFormatType|undefined)`: The previous format value, if it has been successfully unregistered; otherwise `undefined`.

<a name="useAnchorRef" href="#useAnchorRef">#</a> **useAnchorRef**

This hook, to be used in a format type's Edit component, returns the active
element that is formatted, or the selection range if no format is active.
The returned value is meant to be used for positioning UI, e.g. by passing it
to the `Popover` component.

_Parameters_

- _$1_ `Object`: Named parameters.
- _$1.ref_ `RefObject<HTMLElement>`: React ref of the element containing the editable content.
- _$1.value_ `RichTextValue`: Value to check for selection.
- _$1.settings_ `RichTextFormatType`: The format type's settings.

_Returns_

- `(Element|Range)`: The active element or selection range.


<!-- END TOKEN(Autogenerated API docs) -->

6 changes: 5 additions & 1 deletion packages/rich-text/src/component/format-edit.js
Original file line number Diff line number Diff line change
@@ -30,8 +30,11 @@ export default function FormatEdit( {
value,
allowedFormats,
withoutInteractiveFormatting,
forwardedRef,
} ) {
return formatTypes.map( ( { name, edit: Edit, tagName } ) => {
return formatTypes.map( ( settings ) => {
const { name, edit: Edit, tagName } = settings;

if ( ! Edit ) {
return null;
}
@@ -67,6 +70,7 @@ export default function FormatEdit( {
value={ value }
onChange={ onChange }
onFocus={ onFocus }
contentRef={ forwardedRef }
/>
);
} );
1 change: 1 addition & 0 deletions packages/rich-text/src/component/index.js
Original file line number Diff line number Diff line change
@@ -1138,6 +1138,7 @@ function RichText(
onChange={ handleChange }
onFocus={ focus }
formatTypes={ formatTypes }
forwardedRef={ ref }
/>
) }
{ children &&
Loading