@wordpress/block-editor 10.1.0 → 10.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/build/components/block-controls/slot.js +2 -2
- package/build/components/block-controls/slot.js.map +1 -1
- package/build/components/block-draggable/index.js +1 -1
- package/build/components/block-draggable/index.js.map +1 -1
- package/build/components/block-inspector/index.js +4 -5
- package/build/components/block-inspector/index.js.map +1 -1
- package/build/components/block-list/use-in-between-inserter.js +4 -4
- package/build/components/block-list/use-in-between-inserter.js.map +1 -1
- package/build/components/block-parent-selector/index.js +2 -2
- package/build/components/block-parent-selector/index.js.map +1 -1
- package/build/components/block-popover/inbetween.js +3 -1
- package/build/components/block-popover/inbetween.js.map +1 -1
- package/build/components/block-popover/index.js +20 -17
- package/build/components/block-popover/index.js.map +1 -1
- package/build/components/block-settings-menu/block-settings-dropdown.js +5 -5
- package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
- package/build/components/block-tools/index.js +1 -1
- package/build/components/block-tools/index.js.map +1 -1
- package/build/components/block-tools/use-block-toolbar-popover-props.js +6 -3
- package/build/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
- package/build/components/image-editor/use-transform-image.js +2 -2
- package/build/components/image-editor/use-transform-image.js.map +1 -1
- package/build/components/index.js +9 -0
- package/build/components/index.js.map +1 -1
- package/build/components/inserter/block-types-tab.js +1 -1
- package/build/components/inserter/block-types-tab.js.map +1 -1
- package/build/components/inserter/search-items.js +2 -17
- package/build/components/inserter/search-items.js.map +1 -1
- package/build/components/inspector-controls/slot.js +2 -1
- package/build/components/inspector-controls/slot.js.map +1 -1
- package/build/components/rich-text/index.js +17 -0
- package/build/components/rich-text/index.js.map +1 -1
- package/build/components/spacing-sizes-control/index.js +10 -2
- package/build/components/spacing-sizes-control/index.js.map +1 -1
- package/build/components/spacing-sizes-control/spacing-input-control.js +5 -4
- package/build/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
- package/build/components/url-popover/image-url-input-ui.js +1 -1
- package/build/components/url-popover/image-url-input-ui.js.map +1 -1
- package/build/components/use-block-drop-zone/index.js +19 -1
- package/build/components/use-block-drop-zone/index.js.map +1 -1
- package/build/components/use-on-block-drop/index.js +62 -20
- package/build/components/use-on-block-drop/index.js.map +1 -1
- package/build/components/writing-flow/use-arrow-nav.js +14 -7
- package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
- package/build/hooks/index.js +13 -1
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/layout.js +76 -23
- package/build/hooks/layout.js.map +1 -1
- package/build/index.js +14 -0
- package/build/index.js.map +1 -1
- package/build/store/reducer.js +5 -3
- package/build/store/reducer.js.map +1 -1
- package/build/store/selectors.js +1 -1
- package/build/store/selectors.js.map +1 -1
- package/build-module/components/block-controls/slot.js +3 -3
- package/build-module/components/block-controls/slot.js.map +1 -1
- package/build-module/components/block-draggable/index.js +1 -1
- package/build-module/components/block-draggable/index.js.map +1 -1
- package/build-module/components/block-inspector/index.js +5 -6
- package/build-module/components/block-inspector/index.js.map +1 -1
- package/build-module/components/block-list/use-in-between-inserter.js +4 -4
- package/build-module/components/block-list/use-in-between-inserter.js.map +1 -1
- package/build-module/components/block-parent-selector/index.js +2 -2
- package/build-module/components/block-parent-selector/index.js.map +1 -1
- package/build-module/components/block-popover/inbetween.js +3 -1
- package/build-module/components/block-popover/inbetween.js.map +1 -1
- package/build-module/components/block-popover/index.js +20 -17
- package/build-module/components/block-popover/index.js.map +1 -1
- package/build-module/components/block-settings-menu/block-settings-dropdown.js +7 -7
- package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
- package/build-module/components/block-tools/index.js +1 -1
- package/build-module/components/block-tools/index.js.map +1 -1
- package/build-module/components/block-tools/use-block-toolbar-popover-props.js +6 -3
- package/build-module/components/block-tools/use-block-toolbar-popover-props.js.map +1 -1
- package/build-module/components/image-editor/use-transform-image.js +2 -2
- package/build-module/components/image-editor/use-transform-image.js.map +1 -1
- package/build-module/components/index.js +1 -0
- package/build-module/components/index.js.map +1 -1
- package/build-module/components/inserter/block-types-tab.js +3 -3
- package/build-module/components/inserter/block-types-tab.js.map +1 -1
- package/build-module/components/inserter/search-items.js +3 -17
- package/build-module/components/inserter/search-items.js.map +1 -1
- package/build-module/components/inspector-controls/slot.js +3 -2
- package/build-module/components/inspector-controls/slot.js.map +1 -1
- package/build-module/components/rich-text/index.js +17 -0
- package/build-module/components/rich-text/index.js.map +1 -1
- package/build-module/components/spacing-sizes-control/index.js +10 -3
- package/build-module/components/spacing-sizes-control/index.js.map +1 -1
- package/build-module/components/spacing-sizes-control/spacing-input-control.js +6 -5
- package/build-module/components/spacing-sizes-control/spacing-input-control.js.map +1 -1
- package/build-module/components/url-popover/image-url-input-ui.js +1 -1
- package/build-module/components/url-popover/image-url-input-ui.js.map +1 -1
- package/build-module/components/use-block-drop-zone/index.js +19 -1
- package/build-module/components/use-block-drop-zone/index.js.map +1 -1
- package/build-module/components/use-on-block-drop/index.js +62 -21
- package/build-module/components/use-on-block-drop/index.js.map +1 -1
- package/build-module/components/writing-flow/use-arrow-nav.js +14 -7
- package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
- package/build-module/hooks/index.js +1 -0
- package/build-module/hooks/index.js.map +1 -1
- package/build-module/hooks/layout.js +73 -23
- package/build-module/hooks/layout.js.map +1 -1
- package/build-module/index.js +1 -1
- package/build-module/index.js.map +1 -1
- package/build-module/store/reducer.js +5 -4
- package/build-module/store/reducer.js.map +1 -1
- package/build-module/store/selectors.js +1 -1
- package/build-module/store/selectors.js.map +1 -1
- package/build-style/style-rtl.css +48 -23
- package/build-style/style.css +48 -23
- package/package.json +29 -30
- package/src/components/block-controls/slot.js +3 -3
- package/src/components/block-draggable/index.js +1 -1
- package/src/components/block-draggable/test/index.native.js +0 -9
- package/src/components/block-inspector/index.js +6 -10
- package/src/components/block-list/use-in-between-inserter.js +5 -5
- package/src/components/block-parent-selector/index.js +2 -2
- package/src/components/block-popover/inbetween.js +1 -1
- package/src/components/block-popover/index.js +37 -22
- package/src/components/block-preview/style.scss +13 -0
- package/src/components/block-settings-menu/block-settings-dropdown.js +7 -7
- package/src/components/block-switcher/test/__snapshots__/index.js.snap +104 -33
- package/src/components/block-switcher/test/index.js +121 -61
- package/src/components/block-tools/index.js +1 -1
- package/src/components/block-tools/use-block-toolbar-popover-props.js +6 -0
- package/src/components/button-block-appender/style.scss +3 -1
- package/src/components/image-editor/use-transform-image.js +2 -2
- package/src/components/index.js +1 -0
- package/src/components/inserter/block-types-tab.js +3 -3
- package/src/components/inserter/search-items.js +3 -15
- package/src/components/inserter/test/search-items.js +4 -0
- package/src/components/inspector-controls/slot.js +6 -2
- package/src/components/responsive-block-control/test/index.js +73 -118
- package/src/components/rich-text/index.js +22 -0
- package/src/components/spacing-sizes-control/index.js +15 -3
- package/src/components/spacing-sizes-control/spacing-input-control.js +8 -7
- package/src/components/spacing-sizes-control/style.scss +28 -24
- package/src/components/url-popover/image-url-input-ui.js +1 -1
- package/src/components/use-block-drop-zone/index.js +26 -1
- package/src/components/use-on-block-drop/index.js +110 -35
- package/src/components/use-on-block-drop/test/index.js +33 -43
- package/src/components/writing-flow/use-arrow-nav.js +12 -8
- package/src/hooks/index.js +1 -0
- package/src/hooks/layout.js +64 -21
- package/src/index.js +2 -0
- package/src/store/reducer.js +4 -4
- package/src/store/selectors.js +1 -0
|
@@ -54,6 +54,16 @@ export function getNearestBlockIndex(elements, position, orientation) {
|
|
|
54
54
|
});
|
|
55
55
|
return candidateIndex;
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Determine if the element is an empty paragraph block.
|
|
59
|
+
*
|
|
60
|
+
* @param {?HTMLElement} element The element being tested.
|
|
61
|
+
* @return {boolean} True or False.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
function isEmptyParagraph(element) {
|
|
65
|
+
return !!element && element.dataset.type === 'core/paragraph' && element.dataset.empty === 'true';
|
|
66
|
+
}
|
|
57
67
|
/**
|
|
58
68
|
* @typedef {Object} WPBlockDropZoneConfig
|
|
59
69
|
* @property {string} rootClientId The root client id for the block list.
|
|
@@ -65,6 +75,7 @@ export function getNearestBlockIndex(elements, position, orientation) {
|
|
|
65
75
|
* @param {WPBlockDropZoneConfig} dropZoneConfig configuration data for the drop zone.
|
|
66
76
|
*/
|
|
67
77
|
|
|
78
|
+
|
|
68
79
|
export default function useBlockDropZone() {
|
|
69
80
|
let {
|
|
70
81
|
// An undefined value represents a top-level block. Default to an empty
|
|
@@ -102,7 +113,14 @@ export default function useBlockDropZone() {
|
|
|
102
113
|
}, (_getBlockListSettings = getBlockListSettings(targetRootClientId)) === null || _getBlockListSettings === void 0 ? void 0 : _getBlockListSettings.orientation);
|
|
103
114
|
setTargetBlockIndex(targetIndex === undefined ? 0 : targetIndex);
|
|
104
115
|
|
|
105
|
-
if (targetIndex !==
|
|
116
|
+
if (targetIndex !== undefined) {
|
|
117
|
+
const nextBlock = blockElements[targetIndex];
|
|
118
|
+
const previousBlock = blockElements[targetIndex - 1]; // Don't show the insertion point when it's near an empty paragraph block.
|
|
119
|
+
|
|
120
|
+
if (isEmptyParagraph(nextBlock) || isEmptyParagraph(previousBlock)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
106
124
|
showInsertionPoint(targetRootClientId, targetIndex);
|
|
107
125
|
}
|
|
108
126
|
}, []), 200);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/block-editor/src/components/use-block-drop-zone/index.js"],"names":["useDispatch","useSelect","useCallback","useState","useThrottle","__experimentalUseDropZone","useDropZone","isRTL","useOnBlockDrop","getDistanceToNearestEdge","store","blockEditorStore","getNearestBlockIndex","elements","position","orientation","allowedEdges","isRightToLeft","candidateIndex","candidateDistance","forEach","element","index","rect","getBoundingClientRect","distance","edge","undefined","isTrailingEdge","offset","useBlockDropZone","rootClientId","targetRootClientId","targetBlockIndex","setTargetBlockIndex","isDisabled","select","getTemplateLock","__unstableIsWithinBlockOverlay","__unstableHasActiveBlockOverlayActive","templateLock","some","lock","getBlockListSettings","showInsertionPoint","hideInsertionPoint","onBlockDrop","throttled","event","currentTarget","blockElements","Array","from","children","filter","classList","contains","targetIndex","x","clientX","y","clientY","onDrop","onDragOver","onDragLeave","cancel","onDragEnd"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { useCallback, useState } from '@wordpress/element';\nimport {\n\tuseThrottle,\n\t__experimentalUseDropZone as useDropZone,\n} from '@wordpress/compose';\nimport { isRTL } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport useOnBlockDrop from '../use-on-block-drop';\nimport { getDistanceToNearestEdge } from '../../utils/math';\nimport { store as blockEditorStore } from '../../store';\n\n/** @typedef {import('../../utils/math').WPPoint} WPPoint */\n\n/**\n * The orientation of a block list.\n *\n * @typedef {'horizontal'|'vertical'|undefined} WPBlockListOrientation\n */\n\n/**\n * Given a list of block DOM elements finds the index that a block should be dropped\n * at.\n *\n * @param {Element[]} elements Array of DOM elements that represent each block in a block list.\n * @param {WPPoint} position The position of the item being dragged.\n * @param {WPBlockListOrientation} orientation The orientation of a block list.\n *\n * @return {number|undefined} The block index that's closest to the drag position.\n */\nexport function getNearestBlockIndex( elements, position, orientation ) {\n\tconst allowedEdges =\n\t\torientation === 'horizontal'\n\t\t\t? [ 'left', 'right' ]\n\t\t\t: [ 'top', 'bottom' ];\n\n\tconst isRightToLeft = isRTL();\n\n\tlet candidateIndex;\n\tlet candidateDistance;\n\n\telements.forEach( ( element, index ) => {\n\t\tconst rect = element.getBoundingClientRect();\n\t\tconst [ distance, edge ] = getDistanceToNearestEdge(\n\t\t\tposition,\n\t\t\trect,\n\t\t\tallowedEdges\n\t\t);\n\n\t\tif ( candidateDistance === undefined || distance < candidateDistance ) {\n\t\t\t// If the user is dropping to the trailing edge of the block\n\t\t\t// add 1 to the index to represent dragging after.\n\t\t\t// Take RTL languages into account where the left edge is\n\t\t\t// the trailing edge.\n\t\t\tconst isTrailingEdge =\n\t\t\t\tedge === 'bottom' ||\n\t\t\t\t( ! isRightToLeft && edge === 'right' ) ||\n\t\t\t\t( isRightToLeft && edge === 'left' );\n\t\t\tconst offset = isTrailingEdge ? 1 : 0;\n\n\t\t\t// Update the currently known best candidate.\n\t\t\tcandidateDistance = distance;\n\t\t\tcandidateIndex = index + offset;\n\t\t}\n\t} );\n\n\treturn candidateIndex;\n}\n\n/**\n * @typedef {Object} WPBlockDropZoneConfig\n * @property {string} rootClientId The root client id for the block list.\n */\n\n/**\n * A React hook that can be used to make a block list handle drag and drop.\n *\n * @param {WPBlockDropZoneConfig} dropZoneConfig configuration data for the drop zone.\n */\nexport default function useBlockDropZone( {\n\t// An undefined value represents a top-level block. Default to an empty\n\t// string for this so that `targetRootClientId` can be easily compared to\n\t// values returned by the `getRootBlockClientId` selector, which also uses\n\t// an empty string to represent top-level blocks.\n\trootClientId: targetRootClientId = '',\n} = {} ) {\n\tconst [ targetBlockIndex, setTargetBlockIndex ] = useState( null );\n\n\tconst isDisabled = useSelect(\n\t\t( select ) => {\n\t\t\tconst {\n\t\t\t\tgetTemplateLock,\n\t\t\t\t__unstableIsWithinBlockOverlay,\n\t\t\t\t__unstableHasActiveBlockOverlayActive,\n\t\t\t} = select( blockEditorStore );\n\t\t\tconst templateLock = getTemplateLock( targetRootClientId );\n\t\t\treturn (\n\t\t\t\t[ 'all', 'contentOnly' ].some(\n\t\t\t\t\t( lock ) => lock === templateLock\n\t\t\t\t) ||\n\t\t\t\t__unstableHasActiveBlockOverlayActive( targetRootClientId ) ||\n\t\t\t\t__unstableIsWithinBlockOverlay( targetRootClientId )\n\t\t\t);\n\t\t},\n\t\t[ targetRootClientId ]\n\t);\n\n\tconst { getBlockListSettings } = useSelect( blockEditorStore );\n\tconst { showInsertionPoint, hideInsertionPoint } =\n\t\tuseDispatch( blockEditorStore );\n\n\tconst onBlockDrop = useOnBlockDrop( targetRootClientId, targetBlockIndex );\n\tconst throttled = useThrottle(\n\t\tuseCallback( ( event, currentTarget ) => {\n\t\t\tconst blockElements = Array.from( currentTarget.children ).filter(\n\t\t\t\t// Ensure the element is a block. It should have the `wp-block` class.\n\t\t\t\t( element ) => element.classList.contains( 'wp-block' )\n\t\t\t);\n\t\t\tconst targetIndex = getNearestBlockIndex(\n\t\t\t\tblockElements,\n\t\t\t\t{ x: event.clientX, y: event.clientY },\n\t\t\t\tgetBlockListSettings( targetRootClientId )?.orientation\n\t\t\t);\n\n\t\t\tsetTargetBlockIndex( targetIndex === undefined ? 0 : targetIndex );\n\n\t\t\tif ( targetIndex !== null ) {\n\t\t\t\tshowInsertionPoint( targetRootClientId, targetIndex );\n\t\t\t}\n\t\t}, [] ),\n\t\t200\n\t);\n\n\treturn useDropZone( {\n\t\tisDisabled,\n\t\tonDrop: onBlockDrop,\n\t\tonDragOver( event ) {\n\t\t\t// `currentTarget` is only available while the event is being\n\t\t\t// handled, so get it now and pass it to the thottled function.\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget\n\t\t\tthrottled( event, event.currentTarget );\n\t\t},\n\t\tonDragLeave() {\n\t\t\tthrottled.cancel();\n\t\t\thideInsertionPoint();\n\t\t\tsetTargetBlockIndex( null );\n\t\t},\n\t\tonDragEnd() {\n\t\t\tthrottled.cancel();\n\t\t\thideInsertionPoint();\n\t\t\tsetTargetBlockIndex( null );\n\t\t},\n\t} );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["@wordpress/block-editor/src/components/use-block-drop-zone/index.js"],"names":["useDispatch","useSelect","useCallback","useState","useThrottle","__experimentalUseDropZone","useDropZone","isRTL","useOnBlockDrop","getDistanceToNearestEdge","store","blockEditorStore","getNearestBlockIndex","elements","position","orientation","allowedEdges","isRightToLeft","candidateIndex","candidateDistance","forEach","element","index","rect","getBoundingClientRect","distance","edge","undefined","isTrailingEdge","offset","isEmptyParagraph","dataset","type","empty","useBlockDropZone","rootClientId","targetRootClientId","targetBlockIndex","setTargetBlockIndex","isDisabled","select","getTemplateLock","__unstableIsWithinBlockOverlay","__unstableHasActiveBlockOverlayActive","templateLock","some","lock","getBlockListSettings","showInsertionPoint","hideInsertionPoint","onBlockDrop","throttled","event","currentTarget","blockElements","Array","from","children","filter","classList","contains","targetIndex","x","clientX","y","clientY","nextBlock","previousBlock","onDrop","onDragOver","onDragLeave","cancel","onDragEnd"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { useCallback, useState } from '@wordpress/element';\nimport {\n\tuseThrottle,\n\t__experimentalUseDropZone as useDropZone,\n} from '@wordpress/compose';\nimport { isRTL } from '@wordpress/i18n';\n\n/**\n * Internal dependencies\n */\nimport useOnBlockDrop from '../use-on-block-drop';\nimport { getDistanceToNearestEdge } from '../../utils/math';\nimport { store as blockEditorStore } from '../../store';\n\n/** @typedef {import('../../utils/math').WPPoint} WPPoint */\n\n/**\n * The orientation of a block list.\n *\n * @typedef {'horizontal'|'vertical'|undefined} WPBlockListOrientation\n */\n\n/**\n * Given a list of block DOM elements finds the index that a block should be dropped\n * at.\n *\n * @param {Element[]} elements Array of DOM elements that represent each block in a block list.\n * @param {WPPoint} position The position of the item being dragged.\n * @param {WPBlockListOrientation} orientation The orientation of a block list.\n *\n * @return {number|undefined} The block index that's closest to the drag position.\n */\nexport function getNearestBlockIndex( elements, position, orientation ) {\n\tconst allowedEdges =\n\t\torientation === 'horizontal'\n\t\t\t? [ 'left', 'right' ]\n\t\t\t: [ 'top', 'bottom' ];\n\n\tconst isRightToLeft = isRTL();\n\n\tlet candidateIndex;\n\tlet candidateDistance;\n\n\telements.forEach( ( element, index ) => {\n\t\tconst rect = element.getBoundingClientRect();\n\t\tconst [ distance, edge ] = getDistanceToNearestEdge(\n\t\t\tposition,\n\t\t\trect,\n\t\t\tallowedEdges\n\t\t);\n\n\t\tif ( candidateDistance === undefined || distance < candidateDistance ) {\n\t\t\t// If the user is dropping to the trailing edge of the block\n\t\t\t// add 1 to the index to represent dragging after.\n\t\t\t// Take RTL languages into account where the left edge is\n\t\t\t// the trailing edge.\n\t\t\tconst isTrailingEdge =\n\t\t\t\tedge === 'bottom' ||\n\t\t\t\t( ! isRightToLeft && edge === 'right' ) ||\n\t\t\t\t( isRightToLeft && edge === 'left' );\n\t\t\tconst offset = isTrailingEdge ? 1 : 0;\n\n\t\t\t// Update the currently known best candidate.\n\t\t\tcandidateDistance = distance;\n\t\t\tcandidateIndex = index + offset;\n\t\t}\n\t} );\n\n\treturn candidateIndex;\n}\n\n/**\n * Determine if the element is an empty paragraph block.\n *\n * @param {?HTMLElement} element The element being tested.\n * @return {boolean} True or False.\n */\nfunction isEmptyParagraph( element ) {\n\treturn (\n\t\t!! element &&\n\t\telement.dataset.type === 'core/paragraph' &&\n\t\telement.dataset.empty === 'true'\n\t);\n}\n\n/**\n * @typedef {Object} WPBlockDropZoneConfig\n * @property {string} rootClientId The root client id for the block list.\n */\n\n/**\n * A React hook that can be used to make a block list handle drag and drop.\n *\n * @param {WPBlockDropZoneConfig} dropZoneConfig configuration data for the drop zone.\n */\nexport default function useBlockDropZone( {\n\t// An undefined value represents a top-level block. Default to an empty\n\t// string for this so that `targetRootClientId` can be easily compared to\n\t// values returned by the `getRootBlockClientId` selector, which also uses\n\t// an empty string to represent top-level blocks.\n\trootClientId: targetRootClientId = '',\n} = {} ) {\n\tconst [ targetBlockIndex, setTargetBlockIndex ] = useState( null );\n\n\tconst isDisabled = useSelect(\n\t\t( select ) => {\n\t\t\tconst {\n\t\t\t\tgetTemplateLock,\n\t\t\t\t__unstableIsWithinBlockOverlay,\n\t\t\t\t__unstableHasActiveBlockOverlayActive,\n\t\t\t} = select( blockEditorStore );\n\t\t\tconst templateLock = getTemplateLock( targetRootClientId );\n\t\t\treturn (\n\t\t\t\t[ 'all', 'contentOnly' ].some(\n\t\t\t\t\t( lock ) => lock === templateLock\n\t\t\t\t) ||\n\t\t\t\t__unstableHasActiveBlockOverlayActive( targetRootClientId ) ||\n\t\t\t\t__unstableIsWithinBlockOverlay( targetRootClientId )\n\t\t\t);\n\t\t},\n\t\t[ targetRootClientId ]\n\t);\n\n\tconst { getBlockListSettings } = useSelect( blockEditorStore );\n\tconst { showInsertionPoint, hideInsertionPoint } =\n\t\tuseDispatch( blockEditorStore );\n\n\tconst onBlockDrop = useOnBlockDrop( targetRootClientId, targetBlockIndex );\n\tconst throttled = useThrottle(\n\t\tuseCallback( ( event, currentTarget ) => {\n\t\t\tconst blockElements = Array.from( currentTarget.children ).filter(\n\t\t\t\t// Ensure the element is a block. It should have the `wp-block` class.\n\t\t\t\t( element ) => element.classList.contains( 'wp-block' )\n\t\t\t);\n\t\t\tconst targetIndex = getNearestBlockIndex(\n\t\t\t\tblockElements,\n\t\t\t\t{ x: event.clientX, y: event.clientY },\n\t\t\t\tgetBlockListSettings( targetRootClientId )?.orientation\n\t\t\t);\n\n\t\t\tsetTargetBlockIndex( targetIndex === undefined ? 0 : targetIndex );\n\n\t\t\tif ( targetIndex !== undefined ) {\n\t\t\t\tconst nextBlock = blockElements[ targetIndex ];\n\t\t\t\tconst previousBlock = blockElements[ targetIndex - 1 ];\n\n\t\t\t\t// Don't show the insertion point when it's near an empty paragraph block.\n\t\t\t\tif (\n\t\t\t\t\tisEmptyParagraph( nextBlock ) ||\n\t\t\t\t\tisEmptyParagraph( previousBlock )\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tshowInsertionPoint( targetRootClientId, targetIndex );\n\t\t\t}\n\t\t}, [] ),\n\t\t200\n\t);\n\n\treturn useDropZone( {\n\t\tisDisabled,\n\t\tonDrop: onBlockDrop,\n\t\tonDragOver( event ) {\n\t\t\t// `currentTarget` is only available while the event is being\n\t\t\t// handled, so get it now and pass it to the thottled function.\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget\n\t\t\tthrottled( event, event.currentTarget );\n\t\t},\n\t\tonDragLeave() {\n\t\t\tthrottled.cancel();\n\t\t\thideInsertionPoint();\n\t\t\tsetTargetBlockIndex( null );\n\t\t},\n\t\tonDragEnd() {\n\t\t\tthrottled.cancel();\n\t\t\thideInsertionPoint();\n\t\t\tsetTargetBlockIndex( null );\n\t\t},\n\t} );\n}\n"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
+
import { useCallback } from '@wordpress/element';
|
|
4
5
|
import { cloneBlock, findTransform, getBlockTransforms, pasteHandler } from '@wordpress/blocks';
|
|
5
|
-
import { useDispatch, useSelect } from '@wordpress/data';
|
|
6
|
+
import { useDispatch, useSelect, useRegistry } from '@wordpress/data';
|
|
6
7
|
import { getFilesFromDataTransfer } from '@wordpress/dom';
|
|
7
8
|
/**
|
|
8
9
|
* Internal dependencies
|
|
@@ -47,13 +48,13 @@ export function parseDropEvent(event) {
|
|
|
47
48
|
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
|
|
48
49
|
* @param {Function} getBlockIndex A function that gets the index of a block.
|
|
49
50
|
* @param {Function} getClientIdsOfDescendants A function that gets the client ids of descendant blocks.
|
|
50
|
-
* @param {Function}
|
|
51
|
-
* @param {Function}
|
|
51
|
+
* @param {Function} moveBlocks A function that moves blocks.
|
|
52
|
+
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
|
|
52
53
|
* @param {Function} clearSelectedBlock A function that clears block selection.
|
|
53
54
|
* @return {Function} The event handler for a block drop event.
|
|
54
55
|
*/
|
|
55
56
|
|
|
56
|
-
export function onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex, getClientIdsOfDescendants,
|
|
57
|
+
export function onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex, getClientIdsOfDescendants, moveBlocks, insertOrReplaceBlocks, clearSelectedBlock) {
|
|
57
58
|
return event => {
|
|
58
59
|
const {
|
|
59
60
|
srcRootClientId: sourceRootClientId,
|
|
@@ -65,7 +66,7 @@ export function onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex,
|
|
|
65
66
|
if (dropType === 'inserter') {
|
|
66
67
|
clearSelectedBlock();
|
|
67
68
|
const blocksToInsert = blocks.map(block => cloneBlock(block));
|
|
68
|
-
|
|
69
|
+
insertOrReplaceBlocks(blocksToInsert, true, null);
|
|
69
70
|
} // If the user is moving a block.
|
|
70
71
|
|
|
71
72
|
|
|
@@ -89,7 +90,7 @@ export function onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex,
|
|
|
89
90
|
// were removed from the block list above the insertion point.
|
|
90
91
|
|
|
91
92
|
const insertIndex = isAtSameLevel && sourceBlockIndex < targetBlockIndex ? targetBlockIndex - draggedBlockCount : targetBlockIndex;
|
|
92
|
-
|
|
93
|
+
moveBlocks(sourceClientIds, sourceRootClientId, insertIndex);
|
|
93
94
|
}
|
|
94
95
|
};
|
|
95
96
|
}
|
|
@@ -101,12 +102,12 @@ export function onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex,
|
|
|
101
102
|
* @param {boolean} hasUploadPermissions Whether the user has upload permissions.
|
|
102
103
|
* @param {Function} updateBlockAttributes A function that updates a block's attributes.
|
|
103
104
|
* @param {Function} canInsertBlockType A function that returns checks whether a block type can be inserted.
|
|
104
|
-
* @param {Function}
|
|
105
|
+
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
|
|
105
106
|
*
|
|
106
107
|
* @return {Function} The event handler for a block-related file drop event.
|
|
107
108
|
*/
|
|
108
109
|
|
|
109
|
-
export function onFilesDrop(targetRootClientId, targetBlockIndex, hasUploadPermissions, updateBlockAttributes, canInsertBlockType,
|
|
110
|
+
export function onFilesDrop(targetRootClientId, targetBlockIndex, hasUploadPermissions, updateBlockAttributes, canInsertBlockType, insertOrReplaceBlocks) {
|
|
110
111
|
return files => {
|
|
111
112
|
if (!hasUploadPermissions) {
|
|
112
113
|
return;
|
|
@@ -116,21 +117,21 @@ export function onFilesDrop(targetRootClientId, targetBlockIndex, hasUploadPermi
|
|
|
116
117
|
|
|
117
118
|
if (transformation) {
|
|
118
119
|
const blocks = transformation.transform(files, updateBlockAttributes);
|
|
119
|
-
|
|
120
|
+
insertOrReplaceBlocks(blocks);
|
|
120
121
|
}
|
|
121
122
|
};
|
|
122
123
|
}
|
|
123
124
|
/**
|
|
124
125
|
* A function that returns an event handler function for block-related HTML drop events.
|
|
125
126
|
*
|
|
126
|
-
* @param {string} targetRootClientId
|
|
127
|
-
* @param {number} targetBlockIndex
|
|
128
|
-
* @param {Function}
|
|
127
|
+
* @param {string} targetRootClientId The root client id where the block(s) will be inserted.
|
|
128
|
+
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
|
|
129
|
+
* @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.
|
|
129
130
|
*
|
|
130
131
|
* @return {Function} The event handler for a block-related HTML drop event.
|
|
131
132
|
*/
|
|
132
133
|
|
|
133
|
-
export function onHTMLDrop(targetRootClientId, targetBlockIndex,
|
|
134
|
+
export function onHTMLDrop(targetRootClientId, targetBlockIndex, insertOrReplaceBlocks) {
|
|
134
135
|
return HTML => {
|
|
135
136
|
const blocks = pasteHandler({
|
|
136
137
|
HTML,
|
|
@@ -138,38 +139,78 @@ export function onHTMLDrop(targetRootClientId, targetBlockIndex, insertBlocks) {
|
|
|
138
139
|
});
|
|
139
140
|
|
|
140
141
|
if (blocks.length) {
|
|
141
|
-
|
|
142
|
+
insertOrReplaceBlocks(blocks);
|
|
142
143
|
}
|
|
143
144
|
};
|
|
144
145
|
}
|
|
145
146
|
/**
|
|
146
147
|
* A React hook for handling block drop events.
|
|
147
148
|
*
|
|
148
|
-
* @
|
|
149
|
-
*
|
|
149
|
+
* @typedef {'insert'|'replace'} DropAction The type of action to perform on drop.
|
|
150
|
+
*
|
|
151
|
+
* @param {string} targetRootClientId The root client id where the block(s) will be inserted.
|
|
152
|
+
* @param {number} targetBlockIndex The index where the block(s) will be inserted.
|
|
153
|
+
* @param {Object} options The optional options.
|
|
154
|
+
* @param {DropAction} options.action The type of action to perform on drop. Could be `insert` or `replace` for now.
|
|
150
155
|
*
|
|
151
156
|
* @return {Object} An object that contains the event handlers `onDrop`, `onFilesDrop` and `onHTMLDrop`.
|
|
152
157
|
*/
|
|
153
158
|
|
|
154
159
|
export default function useOnBlockDrop(targetRootClientId, targetBlockIndex) {
|
|
160
|
+
let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
161
|
+
const {
|
|
162
|
+
action = 'insert'
|
|
163
|
+
} = options;
|
|
155
164
|
const hasUploadPermissions = useSelect(select => select(blockEditorStore).getSettings().mediaUpload, []);
|
|
156
165
|
const {
|
|
157
166
|
canInsertBlockType,
|
|
158
167
|
getBlockIndex,
|
|
159
|
-
getClientIdsOfDescendants
|
|
168
|
+
getClientIdsOfDescendants,
|
|
169
|
+
getBlockOrder,
|
|
170
|
+
getBlocksByClientId
|
|
160
171
|
} = useSelect(blockEditorStore);
|
|
161
172
|
const {
|
|
162
173
|
insertBlocks,
|
|
163
174
|
moveBlocksToPosition,
|
|
164
175
|
updateBlockAttributes,
|
|
165
|
-
clearSelectedBlock
|
|
176
|
+
clearSelectedBlock,
|
|
177
|
+
replaceBlocks,
|
|
178
|
+
removeBlocks
|
|
166
179
|
} = useDispatch(blockEditorStore);
|
|
180
|
+
const registry = useRegistry();
|
|
181
|
+
const insertOrReplaceBlocks = useCallback(function (blocks) {
|
|
182
|
+
let updateSelection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
183
|
+
let initialPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
184
|
+
|
|
185
|
+
if (action === 'replace') {
|
|
186
|
+
const clientIds = getBlockOrder(targetRootClientId);
|
|
187
|
+
const clientId = clientIds[targetBlockIndex];
|
|
188
|
+
replaceBlocks(clientId, blocks, undefined, initialPosition);
|
|
189
|
+
} else {
|
|
190
|
+
insertBlocks(blocks, targetBlockIndex, targetRootClientId, updateSelection, initialPosition);
|
|
191
|
+
}
|
|
192
|
+
}, [action, getBlockOrder, insertBlocks, replaceBlocks, targetBlockIndex, targetRootClientId]);
|
|
193
|
+
const moveBlocks = useCallback((sourceClientIds, sourceRootClientId, insertIndex) => {
|
|
194
|
+
if (action === 'replace') {
|
|
195
|
+
const sourceBlocks = getBlocksByClientId(sourceClientIds);
|
|
196
|
+
const targetBlockClientIds = getBlockOrder(targetRootClientId);
|
|
197
|
+
const targetBlockClientId = targetBlockClientIds[targetBlockIndex];
|
|
198
|
+
registry.batch(() => {
|
|
199
|
+
// Remove the source blocks.
|
|
200
|
+
removeBlocks(sourceClientIds, false); // Replace the target block with the source blocks.
|
|
201
|
+
|
|
202
|
+
replaceBlocks(targetBlockClientId, sourceBlocks, undefined, 0);
|
|
203
|
+
});
|
|
204
|
+
} else {
|
|
205
|
+
moveBlocksToPosition(sourceClientIds, sourceRootClientId, targetRootClientId, insertIndex);
|
|
206
|
+
}
|
|
207
|
+
}, [action, getBlockOrder, getBlocksByClientId, insertBlocks, moveBlocksToPosition, removeBlocks, targetBlockIndex, targetRootClientId]);
|
|
167
208
|
|
|
168
|
-
const _onDrop = onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex, getClientIdsOfDescendants,
|
|
209
|
+
const _onDrop = onBlockDrop(targetRootClientId, targetBlockIndex, getBlockIndex, getClientIdsOfDescendants, moveBlocks, insertOrReplaceBlocks, clearSelectedBlock);
|
|
169
210
|
|
|
170
|
-
const _onFilesDrop = onFilesDrop(targetRootClientId, targetBlockIndex, hasUploadPermissions, updateBlockAttributes, canInsertBlockType,
|
|
211
|
+
const _onFilesDrop = onFilesDrop(targetRootClientId, targetBlockIndex, hasUploadPermissions, updateBlockAttributes, canInsertBlockType, insertOrReplaceBlocks);
|
|
171
212
|
|
|
172
|
-
const _onHTMLDrop = onHTMLDrop(targetRootClientId, targetBlockIndex,
|
|
213
|
+
const _onHTMLDrop = onHTMLDrop(targetRootClientId, targetBlockIndex, insertOrReplaceBlocks);
|
|
173
214
|
|
|
174
215
|
return event => {
|
|
175
216
|
const files = getFilesFromDataTransfer(event.dataTransfer);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/block-editor/src/components/use-on-block-drop/index.js"],"names":["cloneBlock","findTransform","getBlockTransforms","pasteHandler","useDispatch","useSelect","getFilesFromDataTransfer","store","blockEditorStore","parseDropEvent","event","result","srcRootClientId","srcClientIds","srcIndex","type","blocks","dataTransfer","Object","assign","JSON","parse","getData","err","onBlockDrop","targetRootClientId","targetBlockIndex","getBlockIndex","getClientIdsOfDescendants","moveBlocksToPosition","insertBlocks","clearSelectedBlock","sourceRootClientId","sourceClientIds","dropType","blocksToInsert","map","block","sourceBlockIndex","includes","some","id","isAtSameLevel","draggedBlockCount","length","insertIndex","onFilesDrop","hasUploadPermissions","updateBlockAttributes","canInsertBlockType","files","transformation","transform","blockName","isMatch","onHTMLDrop","HTML","mode","useOnBlockDrop","select","getSettings","mediaUpload","_onDrop","_onFilesDrop","_onHTMLDrop","html"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport {\n\tcloneBlock,\n\tfindTransform,\n\tgetBlockTransforms,\n\tpasteHandler,\n} from '@wordpress/blocks';\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { getFilesFromDataTransfer } from '@wordpress/dom';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../../store';\n\n/** @typedef {import('@wordpress/element').WPSyntheticEvent} WPSyntheticEvent */\n\n/**\n * Retrieve the data for a block drop event.\n *\n * @param {WPSyntheticEvent} event The drop event.\n *\n * @return {Object} An object with block drag and drop data.\n */\nexport function parseDropEvent( event ) {\n\tlet result = {\n\t\tsrcRootClientId: null,\n\t\tsrcClientIds: null,\n\t\tsrcIndex: null,\n\t\ttype: null,\n\t\tblocks: null,\n\t};\n\n\tif ( ! event.dataTransfer ) {\n\t\treturn result;\n\t}\n\n\ttry {\n\t\tresult = Object.assign(\n\t\t\tresult,\n\t\t\tJSON.parse( event.dataTransfer.getData( 'wp-blocks' ) )\n\t\t);\n\t} catch ( err ) {\n\t\treturn result;\n\t}\n\n\treturn result;\n}\n\n/**\n * A function that returns an event handler function for block drop events.\n *\n * @param {string} targetRootClientId The root client id where the block(s) will be inserted.\n * @param {number} targetBlockIndex The index where the block(s) will be inserted.\n * @param {Function} getBlockIndex A function that gets the index of a block.\n * @param {Function} getClientIdsOfDescendants A function that gets the client ids of descendant blocks.\n * @param {Function} moveBlocksToPosition A function that moves blocks.\n * @param {Function} insertBlocks A function that inserts blocks.\n * @param {Function} clearSelectedBlock A function that clears block selection.\n * @return {Function} The event handler for a block drop event.\n */\nexport function onBlockDrop(\n\ttargetRootClientId,\n\ttargetBlockIndex,\n\tgetBlockIndex,\n\tgetClientIdsOfDescendants,\n\tmoveBlocksToPosition,\n\tinsertBlocks,\n\tclearSelectedBlock\n) {\n\treturn ( event ) => {\n\t\tconst {\n\t\t\tsrcRootClientId: sourceRootClientId,\n\t\t\tsrcClientIds: sourceClientIds,\n\t\t\ttype: dropType,\n\t\t\tblocks,\n\t\t} = parseDropEvent( event );\n\n\t\t// If the user is inserting a block.\n\t\tif ( dropType === 'inserter' ) {\n\t\t\tclearSelectedBlock();\n\t\t\tconst blocksToInsert = blocks.map( ( block ) =>\n\t\t\t\tcloneBlock( block )\n\t\t\t);\n\t\t\tinsertBlocks(\n\t\t\t\tblocksToInsert,\n\t\t\t\ttargetBlockIndex,\n\t\t\t\ttargetRootClientId,\n\t\t\t\ttrue,\n\t\t\t\tnull\n\t\t\t);\n\t\t}\n\n\t\t// If the user is moving a block.\n\t\tif ( dropType === 'block' ) {\n\t\t\tconst sourceBlockIndex = getBlockIndex( sourceClientIds[ 0 ] );\n\n\t\t\t// If the user is dropping to the same position, return early.\n\t\t\tif (\n\t\t\t\tsourceRootClientId === targetRootClientId &&\n\t\t\t\tsourceBlockIndex === targetBlockIndex\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If the user is attempting to drop a block within its own\n\t\t\t// nested blocks, return early as this would create infinite\n\t\t\t// recursion.\n\t\t\tif (\n\t\t\t\tsourceClientIds.includes( targetRootClientId ) ||\n\t\t\t\tgetClientIdsOfDescendants( sourceClientIds ).some(\n\t\t\t\t\t( id ) => id === targetRootClientId\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst isAtSameLevel = sourceRootClientId === targetRootClientId;\n\t\t\tconst draggedBlockCount = sourceClientIds.length;\n\n\t\t\t// If the block is kept at the same level and moved downwards,\n\t\t\t// subtract to take into account that the blocks being dragged\n\t\t\t// were removed from the block list above the insertion point.\n\t\t\tconst insertIndex =\n\t\t\t\tisAtSameLevel && sourceBlockIndex < targetBlockIndex\n\t\t\t\t\t? targetBlockIndex - draggedBlockCount\n\t\t\t\t\t: targetBlockIndex;\n\n\t\t\tmoveBlocksToPosition(\n\t\t\t\tsourceClientIds,\n\t\t\t\tsourceRootClientId,\n\t\t\t\ttargetRootClientId,\n\t\t\t\tinsertIndex\n\t\t\t);\n\t\t}\n\t};\n}\n\n/**\n * A function that returns an event handler function for block-related file drop events.\n *\n * @param {string} targetRootClientId The root client id where the block(s) will be inserted.\n * @param {number} targetBlockIndex The index where the block(s) will be inserted.\n * @param {boolean} hasUploadPermissions Whether the user has upload permissions.\n * @param {Function} updateBlockAttributes A function that updates a block's attributes.\n * @param {Function} canInsertBlockType A function that returns checks whether a block type can be inserted.\n * @param {Function} insertBlocks A function that inserts blocks.\n *\n * @return {Function} The event handler for a block-related file drop event.\n */\nexport function onFilesDrop(\n\ttargetRootClientId,\n\ttargetBlockIndex,\n\thasUploadPermissions,\n\tupdateBlockAttributes,\n\tcanInsertBlockType,\n\tinsertBlocks\n) {\n\treturn ( files ) => {\n\t\tif ( ! hasUploadPermissions ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst transformation = findTransform(\n\t\t\tgetBlockTransforms( 'from' ),\n\t\t\t( transform ) =>\n\t\t\t\ttransform.type === 'files' &&\n\t\t\t\tcanInsertBlockType( transform.blockName, targetRootClientId ) &&\n\t\t\t\ttransform.isMatch( files )\n\t\t);\n\n\t\tif ( transformation ) {\n\t\t\tconst blocks = transformation.transform(\n\t\t\t\tfiles,\n\t\t\t\tupdateBlockAttributes\n\t\t\t);\n\t\t\tinsertBlocks( blocks, targetBlockIndex, targetRootClientId );\n\t\t}\n\t};\n}\n\n/**\n * A function that returns an event handler function for block-related HTML drop events.\n *\n * @param {string} targetRootClientId The root client id where the block(s) will be inserted.\n * @param {number} targetBlockIndex The index where the block(s) will be inserted.\n * @param {Function} insertBlocks A function that inserts blocks.\n *\n * @return {Function} The event handler for a block-related HTML drop event.\n */\nexport function onHTMLDrop(\n\ttargetRootClientId,\n\ttargetBlockIndex,\n\tinsertBlocks\n) {\n\treturn ( HTML ) => {\n\t\tconst blocks = pasteHandler( { HTML, mode: 'BLOCKS' } );\n\n\t\tif ( blocks.length ) {\n\t\t\tinsertBlocks( blocks, targetBlockIndex, targetRootClientId );\n\t\t}\n\t};\n}\n\n/**\n * A React hook for handling block drop events.\n *\n * @param {string} targetRootClientId The root client id where the block(s) will be inserted.\n * @param {number} targetBlockIndex The index where the block(s) will be inserted.\n *\n * @return {Object} An object that contains the event handlers `onDrop`, `onFilesDrop` and `onHTMLDrop`.\n */\nexport default function useOnBlockDrop( targetRootClientId, targetBlockIndex ) {\n\tconst hasUploadPermissions = useSelect(\n\t\t( select ) => select( blockEditorStore ).getSettings().mediaUpload,\n\t\t[]\n\t);\n\tconst { canInsertBlockType, getBlockIndex, getClientIdsOfDescendants } =\n\t\tuseSelect( blockEditorStore );\n\tconst {\n\t\tinsertBlocks,\n\t\tmoveBlocksToPosition,\n\t\tupdateBlockAttributes,\n\t\tclearSelectedBlock,\n\t} = useDispatch( blockEditorStore );\n\n\tconst _onDrop = onBlockDrop(\n\t\ttargetRootClientId,\n\t\ttargetBlockIndex,\n\t\tgetBlockIndex,\n\t\tgetClientIdsOfDescendants,\n\t\tmoveBlocksToPosition,\n\t\tinsertBlocks,\n\t\tclearSelectedBlock\n\t);\n\tconst _onFilesDrop = onFilesDrop(\n\t\ttargetRootClientId,\n\t\ttargetBlockIndex,\n\t\thasUploadPermissions,\n\t\tupdateBlockAttributes,\n\t\tcanInsertBlockType,\n\t\tinsertBlocks\n\t);\n\tconst _onHTMLDrop = onHTMLDrop(\n\t\ttargetRootClientId,\n\t\ttargetBlockIndex,\n\t\tinsertBlocks\n\t);\n\n\treturn ( event ) => {\n\t\tconst files = getFilesFromDataTransfer( event.dataTransfer );\n\t\tconst html = event.dataTransfer.getData( 'text/html' );\n\n\t\t/**\n\t\t * From Windows Chrome 96, the `event.dataTransfer` returns both file object and HTML.\n\t\t * The order of the checks is important to recognise the HTML drop.\n\t\t */\n\t\tif ( html ) {\n\t\t\t_onHTMLDrop( html );\n\t\t} else if ( files.length ) {\n\t\t\t_onFilesDrop( files );\n\t\t} else {\n\t\t\t_onDrop( event );\n\t\t}\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["@wordpress/block-editor/src/components/use-on-block-drop/index.js"],"names":["useCallback","cloneBlock","findTransform","getBlockTransforms","pasteHandler","useDispatch","useSelect","useRegistry","getFilesFromDataTransfer","store","blockEditorStore","parseDropEvent","event","result","srcRootClientId","srcClientIds","srcIndex","type","blocks","dataTransfer","Object","assign","JSON","parse","getData","err","onBlockDrop","targetRootClientId","targetBlockIndex","getBlockIndex","getClientIdsOfDescendants","moveBlocks","insertOrReplaceBlocks","clearSelectedBlock","sourceRootClientId","sourceClientIds","dropType","blocksToInsert","map","block","sourceBlockIndex","includes","some","id","isAtSameLevel","draggedBlockCount","length","insertIndex","onFilesDrop","hasUploadPermissions","updateBlockAttributes","canInsertBlockType","files","transformation","transform","blockName","isMatch","onHTMLDrop","HTML","mode","useOnBlockDrop","options","action","select","getSettings","mediaUpload","getBlockOrder","getBlocksByClientId","insertBlocks","moveBlocksToPosition","replaceBlocks","removeBlocks","registry","updateSelection","initialPosition","clientIds","clientId","undefined","sourceBlocks","targetBlockClientIds","targetBlockClientId","batch","_onDrop","_onFilesDrop","_onHTMLDrop","html"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useCallback } from '@wordpress/element';\nimport {\n\tcloneBlock,\n\tfindTransform,\n\tgetBlockTransforms,\n\tpasteHandler,\n} from '@wordpress/blocks';\nimport { useDispatch, useSelect, useRegistry } from '@wordpress/data';\nimport { getFilesFromDataTransfer } from '@wordpress/dom';\n\n/**\n * Internal dependencies\n */\nimport { store as blockEditorStore } from '../../store';\n\n/** @typedef {import('@wordpress/element').WPSyntheticEvent} WPSyntheticEvent */\n\n/**\n * Retrieve the data for a block drop event.\n *\n * @param {WPSyntheticEvent} event The drop event.\n *\n * @return {Object} An object with block drag and drop data.\n */\nexport function parseDropEvent( event ) {\n\tlet result = {\n\t\tsrcRootClientId: null,\n\t\tsrcClientIds: null,\n\t\tsrcIndex: null,\n\t\ttype: null,\n\t\tblocks: null,\n\t};\n\n\tif ( ! event.dataTransfer ) {\n\t\treturn result;\n\t}\n\n\ttry {\n\t\tresult = Object.assign(\n\t\t\tresult,\n\t\t\tJSON.parse( event.dataTransfer.getData( 'wp-blocks' ) )\n\t\t);\n\t} catch ( err ) {\n\t\treturn result;\n\t}\n\n\treturn result;\n}\n\n/**\n * A function that returns an event handler function for block drop events.\n *\n * @param {string} targetRootClientId The root client id where the block(s) will be inserted.\n * @param {number} targetBlockIndex The index where the block(s) will be inserted.\n * @param {Function} getBlockIndex A function that gets the index of a block.\n * @param {Function} getClientIdsOfDescendants A function that gets the client ids of descendant blocks.\n * @param {Function} moveBlocks A function that moves blocks.\n * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.\n * @param {Function} clearSelectedBlock A function that clears block selection.\n * @return {Function} The event handler for a block drop event.\n */\nexport function onBlockDrop(\n\ttargetRootClientId,\n\ttargetBlockIndex,\n\tgetBlockIndex,\n\tgetClientIdsOfDescendants,\n\tmoveBlocks,\n\tinsertOrReplaceBlocks,\n\tclearSelectedBlock\n) {\n\treturn ( event ) => {\n\t\tconst {\n\t\t\tsrcRootClientId: sourceRootClientId,\n\t\t\tsrcClientIds: sourceClientIds,\n\t\t\ttype: dropType,\n\t\t\tblocks,\n\t\t} = parseDropEvent( event );\n\n\t\t// If the user is inserting a block.\n\t\tif ( dropType === 'inserter' ) {\n\t\t\tclearSelectedBlock();\n\t\t\tconst blocksToInsert = blocks.map( ( block ) =>\n\t\t\t\tcloneBlock( block )\n\t\t\t);\n\t\t\tinsertOrReplaceBlocks( blocksToInsert, true, null );\n\t\t}\n\n\t\t// If the user is moving a block.\n\t\tif ( dropType === 'block' ) {\n\t\t\tconst sourceBlockIndex = getBlockIndex( sourceClientIds[ 0 ] );\n\n\t\t\t// If the user is dropping to the same position, return early.\n\t\t\tif (\n\t\t\t\tsourceRootClientId === targetRootClientId &&\n\t\t\t\tsourceBlockIndex === targetBlockIndex\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If the user is attempting to drop a block within its own\n\t\t\t// nested blocks, return early as this would create infinite\n\t\t\t// recursion.\n\t\t\tif (\n\t\t\t\tsourceClientIds.includes( targetRootClientId ) ||\n\t\t\t\tgetClientIdsOfDescendants( sourceClientIds ).some(\n\t\t\t\t\t( id ) => id === targetRootClientId\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst isAtSameLevel = sourceRootClientId === targetRootClientId;\n\t\t\tconst draggedBlockCount = sourceClientIds.length;\n\n\t\t\t// If the block is kept at the same level and moved downwards,\n\t\t\t// subtract to take into account that the blocks being dragged\n\t\t\t// were removed from the block list above the insertion point.\n\t\t\tconst insertIndex =\n\t\t\t\tisAtSameLevel && sourceBlockIndex < targetBlockIndex\n\t\t\t\t\t? targetBlockIndex - draggedBlockCount\n\t\t\t\t\t: targetBlockIndex;\n\n\t\t\tmoveBlocks( sourceClientIds, sourceRootClientId, insertIndex );\n\t\t}\n\t};\n}\n\n/**\n * A function that returns an event handler function for block-related file drop events.\n *\n * @param {string} targetRootClientId The root client id where the block(s) will be inserted.\n * @param {number} targetBlockIndex The index where the block(s) will be inserted.\n * @param {boolean} hasUploadPermissions Whether the user has upload permissions.\n * @param {Function} updateBlockAttributes A function that updates a block's attributes.\n * @param {Function} canInsertBlockType A function that returns checks whether a block type can be inserted.\n * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.\n *\n * @return {Function} The event handler for a block-related file drop event.\n */\nexport function onFilesDrop(\n\ttargetRootClientId,\n\ttargetBlockIndex,\n\thasUploadPermissions,\n\tupdateBlockAttributes,\n\tcanInsertBlockType,\n\tinsertOrReplaceBlocks\n) {\n\treturn ( files ) => {\n\t\tif ( ! hasUploadPermissions ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst transformation = findTransform(\n\t\t\tgetBlockTransforms( 'from' ),\n\t\t\t( transform ) =>\n\t\t\t\ttransform.type === 'files' &&\n\t\t\t\tcanInsertBlockType( transform.blockName, targetRootClientId ) &&\n\t\t\t\ttransform.isMatch( files )\n\t\t);\n\n\t\tif ( transformation ) {\n\t\t\tconst blocks = transformation.transform(\n\t\t\t\tfiles,\n\t\t\t\tupdateBlockAttributes\n\t\t\t);\n\t\t\tinsertOrReplaceBlocks( blocks );\n\t\t}\n\t};\n}\n\n/**\n * A function that returns an event handler function for block-related HTML drop events.\n *\n * @param {string} targetRootClientId The root client id where the block(s) will be inserted.\n * @param {number} targetBlockIndex The index where the block(s) will be inserted.\n * @param {Function} insertOrReplaceBlocks A function that inserts or replaces blocks.\n *\n * @return {Function} The event handler for a block-related HTML drop event.\n */\nexport function onHTMLDrop(\n\ttargetRootClientId,\n\ttargetBlockIndex,\n\tinsertOrReplaceBlocks\n) {\n\treturn ( HTML ) => {\n\t\tconst blocks = pasteHandler( { HTML, mode: 'BLOCKS' } );\n\n\t\tif ( blocks.length ) {\n\t\t\tinsertOrReplaceBlocks( blocks );\n\t\t}\n\t};\n}\n\n/**\n * A React hook for handling block drop events.\n *\n * @typedef {'insert'|'replace'} DropAction The type of action to perform on drop.\n *\n * @param {string} targetRootClientId The root client id where the block(s) will be inserted.\n * @param {number} targetBlockIndex The index where the block(s) will be inserted.\n * @param {Object} options The optional options.\n * @param {DropAction} options.action The type of action to perform on drop. Could be `insert` or `replace` for now.\n *\n * @return {Object} An object that contains the event handlers `onDrop`, `onFilesDrop` and `onHTMLDrop`.\n */\nexport default function useOnBlockDrop(\n\ttargetRootClientId,\n\ttargetBlockIndex,\n\toptions = {}\n) {\n\tconst { action = 'insert' } = options;\n\tconst hasUploadPermissions = useSelect(\n\t\t( select ) => select( blockEditorStore ).getSettings().mediaUpload,\n\t\t[]\n\t);\n\tconst {\n\t\tcanInsertBlockType,\n\t\tgetBlockIndex,\n\t\tgetClientIdsOfDescendants,\n\t\tgetBlockOrder,\n\t\tgetBlocksByClientId,\n\t} = useSelect( blockEditorStore );\n\tconst {\n\t\tinsertBlocks,\n\t\tmoveBlocksToPosition,\n\t\tupdateBlockAttributes,\n\t\tclearSelectedBlock,\n\t\treplaceBlocks,\n\t\tremoveBlocks,\n\t} = useDispatch( blockEditorStore );\n\tconst registry = useRegistry();\n\n\tconst insertOrReplaceBlocks = useCallback(\n\t\t( blocks, updateSelection = true, initialPosition = 0 ) => {\n\t\t\tif ( action === 'replace' ) {\n\t\t\t\tconst clientIds = getBlockOrder( targetRootClientId );\n\t\t\t\tconst clientId = clientIds[ targetBlockIndex ];\n\n\t\t\t\treplaceBlocks( clientId, blocks, undefined, initialPosition );\n\t\t\t} else {\n\t\t\t\tinsertBlocks(\n\t\t\t\t\tblocks,\n\t\t\t\t\ttargetBlockIndex,\n\t\t\t\t\ttargetRootClientId,\n\t\t\t\t\tupdateSelection,\n\t\t\t\t\tinitialPosition\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\taction,\n\t\t\tgetBlockOrder,\n\t\t\tinsertBlocks,\n\t\t\treplaceBlocks,\n\t\t\ttargetBlockIndex,\n\t\t\ttargetRootClientId,\n\t\t]\n\t);\n\n\tconst moveBlocks = useCallback(\n\t\t( sourceClientIds, sourceRootClientId, insertIndex ) => {\n\t\t\tif ( action === 'replace' ) {\n\t\t\t\tconst sourceBlocks = getBlocksByClientId( sourceClientIds );\n\t\t\t\tconst targetBlockClientIds =\n\t\t\t\t\tgetBlockOrder( targetRootClientId );\n\t\t\t\tconst targetBlockClientId =\n\t\t\t\t\ttargetBlockClientIds[ targetBlockIndex ];\n\n\t\t\t\tregistry.batch( () => {\n\t\t\t\t\t// Remove the source blocks.\n\t\t\t\t\tremoveBlocks( sourceClientIds, false );\n\t\t\t\t\t// Replace the target block with the source blocks.\n\t\t\t\t\treplaceBlocks(\n\t\t\t\t\t\ttargetBlockClientId,\n\t\t\t\t\t\tsourceBlocks,\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t\t0\n\t\t\t\t\t);\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tmoveBlocksToPosition(\n\t\t\t\t\tsourceClientIds,\n\t\t\t\t\tsourceRootClientId,\n\t\t\t\t\ttargetRootClientId,\n\t\t\t\t\tinsertIndex\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t\t[\n\t\t\taction,\n\t\t\tgetBlockOrder,\n\t\t\tgetBlocksByClientId,\n\t\t\tinsertBlocks,\n\t\t\tmoveBlocksToPosition,\n\t\t\tremoveBlocks,\n\t\t\ttargetBlockIndex,\n\t\t\ttargetRootClientId,\n\t\t]\n\t);\n\n\tconst _onDrop = onBlockDrop(\n\t\ttargetRootClientId,\n\t\ttargetBlockIndex,\n\t\tgetBlockIndex,\n\t\tgetClientIdsOfDescendants,\n\t\tmoveBlocks,\n\t\tinsertOrReplaceBlocks,\n\t\tclearSelectedBlock\n\t);\n\tconst _onFilesDrop = onFilesDrop(\n\t\ttargetRootClientId,\n\t\ttargetBlockIndex,\n\t\thasUploadPermissions,\n\t\tupdateBlockAttributes,\n\t\tcanInsertBlockType,\n\t\tinsertOrReplaceBlocks\n\t);\n\tconst _onHTMLDrop = onHTMLDrop(\n\t\ttargetRootClientId,\n\t\ttargetBlockIndex,\n\t\tinsertOrReplaceBlocks\n\t);\n\n\treturn ( event ) => {\n\t\tconst files = getFilesFromDataTransfer( event.dataTransfer );\n\t\tconst html = event.dataTransfer.getData( 'text/html' );\n\n\t\t/**\n\t\t * From Windows Chrome 96, the `event.dataTransfer` returns both file object and HTML.\n\t\t * The order of the checks is important to recognise the HTML drop.\n\t\t */\n\t\tif ( html ) {\n\t\t\t_onHTMLDrop( html );\n\t\t} else if ( files.length ) {\n\t\t\t_onFilesDrop( files );\n\t\t} else {\n\t\t\t_onDrop( event );\n\t\t}\n\t};\n}\n"]}
|
|
@@ -134,7 +134,11 @@ export default function useArrowNav() {
|
|
|
134
134
|
function onKeyDown(event) {
|
|
135
135
|
const {
|
|
136
136
|
keyCode,
|
|
137
|
-
target
|
|
137
|
+
target,
|
|
138
|
+
shiftKey,
|
|
139
|
+
ctrlKey,
|
|
140
|
+
altKey,
|
|
141
|
+
metaKey
|
|
138
142
|
} = event;
|
|
139
143
|
const isUp = keyCode === UP;
|
|
140
144
|
const isDown = keyCode === DOWN;
|
|
@@ -144,8 +148,7 @@ export default function useArrowNav() {
|
|
|
144
148
|
const isHorizontal = isLeft || isRight;
|
|
145
149
|
const isVertical = isUp || isDown;
|
|
146
150
|
const isNav = isHorizontal || isVertical;
|
|
147
|
-
const
|
|
148
|
-
const hasModifier = isShift || event.ctrlKey || event.altKey || event.metaKey;
|
|
151
|
+
const hasModifier = shiftKey || ctrlKey || altKey || metaKey;
|
|
149
152
|
const isNavEdge = isVertical ? isVerticalEdge : isHorizontalEdge;
|
|
150
153
|
const {
|
|
151
154
|
ownerDocument
|
|
@@ -170,7 +173,7 @@ export default function useArrowNav() {
|
|
|
170
173
|
return;
|
|
171
174
|
}
|
|
172
175
|
|
|
173
|
-
if (
|
|
176
|
+
if (shiftKey) {
|
|
174
177
|
return;
|
|
175
178
|
}
|
|
176
179
|
|
|
@@ -221,17 +224,21 @@ export default function useArrowNav() {
|
|
|
221
224
|
keepCaretInsideBlock
|
|
222
225
|
} = getSettings();
|
|
223
226
|
|
|
224
|
-
if (
|
|
227
|
+
if (shiftKey) {
|
|
225
228
|
if (isClosestTabbableABlock(target, isReverse) && isNavEdge(target, isReverse)) {
|
|
226
229
|
node.contentEditable = true; // Firefox doesn't automatically move focus.
|
|
227
230
|
|
|
228
231
|
node.focus();
|
|
229
232
|
}
|
|
230
|
-
} else if (isVertical && isVerticalEdge(target, isReverse) &&
|
|
233
|
+
} else if (isVertical && isVerticalEdge(target, isReverse) && ( // When Alt is pressed, only intercept if the caret is also at
|
|
234
|
+
// the horizontal edge.
|
|
235
|
+
altKey ? isHorizontalEdge(target, isReverseDir) : true) && !keepCaretInsideBlock) {
|
|
231
236
|
const closestTabbable = getClosestTabbable(target, isReverse, node, true);
|
|
232
237
|
|
|
233
238
|
if (closestTabbable) {
|
|
234
|
-
placeCaretAtVerticalEdge(closestTabbable,
|
|
239
|
+
placeCaretAtVerticalEdge(closestTabbable, // When Alt is pressed, place the caret at the furthest
|
|
240
|
+
// horizontal edge and the furthest vertical edge.
|
|
241
|
+
altKey ? !isReverse : isReverse, altKey ? undefined : verticalRect);
|
|
235
242
|
event.preventDefault();
|
|
236
243
|
}
|
|
237
244
|
} else if (isHorizontal && defaultView.getSelection().isCollapsed && isHorizontalEdge(target, isReverseDir) && !keepCaretInsideBlock) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/block-editor/src/components/writing-flow/use-arrow-nav.js"],"names":["computeCaretRect","focus","isHorizontalEdge","isVerticalEdge","placeCaretAtHorizontalEdge","placeCaretAtVerticalEdge","isRTL","UP","DOWN","LEFT","RIGHT","useDispatch","useSelect","useRefEffect","getBlockClientId","isInSameBlock","store","blockEditorStore","isNavigationCandidate","element","keyCode","hasModifier","isVertical","tagName","simpleInputTypes","includes","getAttribute","getClosestTabbable","target","isReverse","containerElement","onlyVertical","focusableNodes","focusable","find","reverse","slice","indexOf","targetRect","getBoundingClientRect","isTabCandidate","node","children","length","firstElementChild","tabbable","isTabbableIndex","isContentEditable","contentEditable","nodeRect","left","right","useArrowNav","getMultiSelectedBlocksStartClientId","getMultiSelectedBlocksEndClientId","getSettings","hasMultiSelection","__unstableIsFullySelected","selectBlock","verticalRect","onMouseDown","isClosestTabbableABlock","closestTabbable","onKeyDown","event","isUp","isDown","isLeft","isRight","isHorizontal","isNav","isShift","shiftKey","ctrlKey","altKey","metaKey","isNavEdge","ownerDocument","defaultView","defaultPrevented","preventDefault","isReverseDir","keepCaretInsideBlock","getSelection","isCollapsed","addEventListener","removeEventListener"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport {\n\tcomputeCaretRect,\n\tfocus,\n\tisHorizontalEdge,\n\tisVerticalEdge,\n\tplaceCaretAtHorizontalEdge,\n\tplaceCaretAtVerticalEdge,\n\tisRTL,\n} from '@wordpress/dom';\nimport { UP, DOWN, LEFT, RIGHT } from '@wordpress/keycodes';\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { useRefEffect } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport { getBlockClientId, isInSameBlock } from '../../utils/dom';\nimport { store as blockEditorStore } from '../../store';\n\n/**\n * Returns true if the element should consider edge navigation upon a keyboard\n * event of the given directional key code, or false otherwise.\n *\n * @param {Element} element HTML element to test.\n * @param {number} keyCode KeyboardEvent keyCode to test.\n * @param {boolean} hasModifier Whether a modifier is pressed.\n *\n * @return {boolean} Whether element should consider edge navigation.\n */\nexport function isNavigationCandidate( element, keyCode, hasModifier ) {\n\tconst isVertical = keyCode === UP || keyCode === DOWN;\n\n\t// Currently, all elements support unmodified vertical navigation.\n\tif ( isVertical && ! hasModifier ) {\n\t\treturn true;\n\t}\n\n\tconst { tagName } = element;\n\n\t// Native inputs should not navigate horizontally, unless they are simple types that don't need left/right arrow keys.\n\tif ( tagName === 'INPUT' ) {\n\t\tconst simpleInputTypes = [\n\t\t\t'button',\n\t\t\t'checkbox',\n\t\t\t'color',\n\t\t\t'file',\n\t\t\t'image',\n\t\t\t'radio',\n\t\t\t'reset',\n\t\t\t'submit',\n\t\t];\n\t\treturn simpleInputTypes.includes( element.getAttribute( 'type' ) );\n\t}\n\n\t// Native textareas should not navigate horizontally.\n\treturn tagName !== 'TEXTAREA';\n}\n\n/**\n * Returns the optimal tab target from the given focused element in the desired\n * direction. A preference is made toward text fields, falling back to the block\n * focus stop if no other candidates exist for the block.\n *\n * @param {Element} target Currently focused text field.\n * @param {boolean} isReverse True if considering as the first field.\n * @param {Element} containerElement Element containing all blocks.\n * @param {boolean} onlyVertical Whether to only consider tabbable elements\n * that are visually above or under the\n * target.\n *\n * @return {?Element} Optimal tab target, if one exists.\n */\nexport function getClosestTabbable(\n\ttarget,\n\tisReverse,\n\tcontainerElement,\n\tonlyVertical\n) {\n\t// Since the current focus target is not guaranteed to be a text field, find\n\t// all focusables. Tabbability is considered later.\n\tlet focusableNodes = focus.focusable.find( containerElement );\n\n\tif ( isReverse ) {\n\t\tfocusableNodes.reverse();\n\t}\n\n\t// Consider as candidates those focusables after the current target. It's\n\t// assumed this can only be reached if the target is focusable (on its\n\t// keydown event), so no need to verify it exists in the set.\n\tfocusableNodes = focusableNodes.slice(\n\t\tfocusableNodes.indexOf( target ) + 1\n\t);\n\n\tlet targetRect;\n\n\tif ( onlyVertical ) {\n\t\ttargetRect = target.getBoundingClientRect();\n\t}\n\n\tfunction isTabCandidate( node ) {\n\t\t// Skip if there's only one child that is content editable (and thus a\n\t\t// better candidate).\n\t\tif (\n\t\t\tnode.children.length === 1 &&\n\t\t\tisInSameBlock( node, node.firstElementChild ) &&\n\t\t\tnode.firstElementChild.getAttribute( 'contenteditable' ) === 'true'\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Not a candidate if the node is not tabbable.\n\t\tif ( ! focus.tabbable.isTabbableIndex( node ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Skip focusable elements such as links within content editable nodes.\n\t\tif ( node.isContentEditable && node.contentEditable !== 'true' ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( onlyVertical ) {\n\t\t\tconst nodeRect = node.getBoundingClientRect();\n\n\t\t\tif (\n\t\t\t\tnodeRect.left >= targetRect.right ||\n\t\t\t\tnodeRect.right <= targetRect.left\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\treturn focusableNodes.find( isTabCandidate );\n}\n\nexport default function useArrowNav() {\n\tconst {\n\t\tgetMultiSelectedBlocksStartClientId,\n\t\tgetMultiSelectedBlocksEndClientId,\n\t\tgetSettings,\n\t\thasMultiSelection,\n\t\t__unstableIsFullySelected,\n\t} = useSelect( blockEditorStore );\n\tconst { selectBlock } = useDispatch( blockEditorStore );\n\treturn useRefEffect( ( node ) => {\n\t\t// Here a DOMRect is stored while moving the caret vertically so\n\t\t// vertical position of the start position can be restored. This is to\n\t\t// recreate browser behaviour across blocks.\n\t\tlet verticalRect;\n\n\t\tfunction onMouseDown() {\n\t\t\tverticalRect = null;\n\t\t}\n\n\t\tfunction isClosestTabbableABlock( target, isReverse ) {\n\t\t\tconst closestTabbable = getClosestTabbable(\n\t\t\t\ttarget,\n\t\t\t\tisReverse,\n\t\t\t\tnode\n\t\t\t);\n\t\t\treturn closestTabbable && getBlockClientId( closestTabbable );\n\t\t}\n\n\t\tfunction onKeyDown( event ) {\n\t\t\tconst { keyCode, target } = event;\n\t\t\tconst isUp = keyCode === UP;\n\t\t\tconst isDown = keyCode === DOWN;\n\t\t\tconst isLeft = keyCode === LEFT;\n\t\t\tconst isRight = keyCode === RIGHT;\n\t\t\tconst isReverse = isUp || isLeft;\n\t\t\tconst isHorizontal = isLeft || isRight;\n\t\t\tconst isVertical = isUp || isDown;\n\t\t\tconst isNav = isHorizontal || isVertical;\n\t\t\tconst isShift = event.shiftKey;\n\t\t\tconst hasModifier =\n\t\t\t\tisShift || event.ctrlKey || event.altKey || event.metaKey;\n\t\t\tconst isNavEdge = isVertical ? isVerticalEdge : isHorizontalEdge;\n\t\t\tconst { ownerDocument } = node;\n\t\t\tconst { defaultView } = ownerDocument;\n\n\t\t\t// If there is a multi-selection, the arrow keys should collapse the\n\t\t\t// selection to the start or end of the selection.\n\t\t\tif ( hasMultiSelection() ) {\n\t\t\t\t// Only handle if we have a full selection (not a native partial\n\t\t\t\t// selection).\n\t\t\t\tif ( ! __unstableIsFullySelected() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( event.defaultPrevented ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( ! isNav ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( isShift ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tif ( isReverse ) {\n\t\t\t\t\tselectBlock( getMultiSelectedBlocksStartClientId() );\n\t\t\t\t} else {\n\t\t\t\t\tselectBlock( getMultiSelectedBlocksEndClientId(), -1 );\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// When presing any key other than up or down, the initial vertical\n\t\t\t// position must ALWAYS be reset. The vertical position is saved so\n\t\t\t// it can be restored as well as possible on sebsequent vertical\n\t\t\t// arrow key presses. It may not always be possible to restore the\n\t\t\t// exact same position (such as at an empty line), so it wouldn't be\n\t\t\t// good to compute the position right before any vertical arrow key\n\t\t\t// press.\n\t\t\tif ( ! isVertical ) {\n\t\t\t\tverticalRect = null;\n\t\t\t} else if ( ! verticalRect ) {\n\t\t\t\tverticalRect = computeCaretRect( defaultView );\n\t\t\t}\n\n\t\t\t// Abort if navigation has already been handled (e.g. RichText\n\t\t\t// inline boundaries).\n\t\t\tif ( event.defaultPrevented ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( ! isNav ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Abort if our current target is not a candidate for navigation\n\t\t\t// (e.g. preserve native input behaviors).\n\t\t\tif ( ! isNavigationCandidate( target, keyCode, hasModifier ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// In the case of RTL scripts, right means previous and left means\n\t\t\t// next, which is the exact reverse of LTR.\n\t\t\tconst isReverseDir = isRTL( target ) ? ! isReverse : isReverse;\n\t\t\tconst { keepCaretInsideBlock } = getSettings();\n\n\t\t\tif ( isShift ) {\n\t\t\t\tif (\n\t\t\t\t\tisClosestTabbableABlock( target, isReverse ) &&\n\t\t\t\t\tisNavEdge( target, isReverse )\n\t\t\t\t) {\n\t\t\t\t\tnode.contentEditable = true;\n\t\t\t\t\t// Firefox doesn't automatically move focus.\n\t\t\t\t\tnode.focus();\n\t\t\t\t}\n\t\t\t} else if (\n\t\t\t\tisVertical &&\n\t\t\t\tisVerticalEdge( target, isReverse ) &&\n\t\t\t\t! keepCaretInsideBlock\n\t\t\t) {\n\t\t\t\tconst closestTabbable = getClosestTabbable(\n\t\t\t\t\ttarget,\n\t\t\t\t\tisReverse,\n\t\t\t\t\tnode,\n\t\t\t\t\ttrue\n\t\t\t\t);\n\n\t\t\t\tif ( closestTabbable ) {\n\t\t\t\t\tplaceCaretAtVerticalEdge(\n\t\t\t\t\t\tclosestTabbable,\n\t\t\t\t\t\tisReverse,\n\t\t\t\t\t\tverticalRect\n\t\t\t\t\t);\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t} else if (\n\t\t\t\tisHorizontal &&\n\t\t\t\tdefaultView.getSelection().isCollapsed &&\n\t\t\t\tisHorizontalEdge( target, isReverseDir ) &&\n\t\t\t\t! keepCaretInsideBlock\n\t\t\t) {\n\t\t\t\tconst closestTabbable = getClosestTabbable(\n\t\t\t\t\ttarget,\n\t\t\t\t\tisReverseDir,\n\t\t\t\t\tnode\n\t\t\t\t);\n\t\t\t\tplaceCaretAtHorizontalEdge( closestTabbable, isReverse );\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\n\t\tnode.addEventListener( 'mousedown', onMouseDown );\n\t\tnode.addEventListener( 'keydown', onKeyDown );\n\t\treturn () => {\n\t\t\tnode.removeEventListener( 'mousedown', onMouseDown );\n\t\t\tnode.removeEventListener( 'keydown', onKeyDown );\n\t\t};\n\t}, [] );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["@wordpress/block-editor/src/components/writing-flow/use-arrow-nav.js"],"names":["computeCaretRect","focus","isHorizontalEdge","isVerticalEdge","placeCaretAtHorizontalEdge","placeCaretAtVerticalEdge","isRTL","UP","DOWN","LEFT","RIGHT","useDispatch","useSelect","useRefEffect","getBlockClientId","isInSameBlock","store","blockEditorStore","isNavigationCandidate","element","keyCode","hasModifier","isVertical","tagName","simpleInputTypes","includes","getAttribute","getClosestTabbable","target","isReverse","containerElement","onlyVertical","focusableNodes","focusable","find","reverse","slice","indexOf","targetRect","getBoundingClientRect","isTabCandidate","node","children","length","firstElementChild","tabbable","isTabbableIndex","isContentEditable","contentEditable","nodeRect","left","right","useArrowNav","getMultiSelectedBlocksStartClientId","getMultiSelectedBlocksEndClientId","getSettings","hasMultiSelection","__unstableIsFullySelected","selectBlock","verticalRect","onMouseDown","isClosestTabbableABlock","closestTabbable","onKeyDown","event","shiftKey","ctrlKey","altKey","metaKey","isUp","isDown","isLeft","isRight","isHorizontal","isNav","isNavEdge","ownerDocument","defaultView","defaultPrevented","preventDefault","isReverseDir","keepCaretInsideBlock","undefined","getSelection","isCollapsed","addEventListener","removeEventListener"],"mappings":"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","sourcesContent":["/**\n * WordPress dependencies\n */\nimport {\n\tcomputeCaretRect,\n\tfocus,\n\tisHorizontalEdge,\n\tisVerticalEdge,\n\tplaceCaretAtHorizontalEdge,\n\tplaceCaretAtVerticalEdge,\n\tisRTL,\n} from '@wordpress/dom';\nimport { UP, DOWN, LEFT, RIGHT } from '@wordpress/keycodes';\nimport { useDispatch, useSelect } from '@wordpress/data';\nimport { useRefEffect } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport { getBlockClientId, isInSameBlock } from '../../utils/dom';\nimport { store as blockEditorStore } from '../../store';\n\n/**\n * Returns true if the element should consider edge navigation upon a keyboard\n * event of the given directional key code, or false otherwise.\n *\n * @param {Element} element HTML element to test.\n * @param {number} keyCode KeyboardEvent keyCode to test.\n * @param {boolean} hasModifier Whether a modifier is pressed.\n *\n * @return {boolean} Whether element should consider edge navigation.\n */\nexport function isNavigationCandidate( element, keyCode, hasModifier ) {\n\tconst isVertical = keyCode === UP || keyCode === DOWN;\n\n\t// Currently, all elements support unmodified vertical navigation.\n\tif ( isVertical && ! hasModifier ) {\n\t\treturn true;\n\t}\n\n\tconst { tagName } = element;\n\n\t// Native inputs should not navigate horizontally, unless they are simple types that don't need left/right arrow keys.\n\tif ( tagName === 'INPUT' ) {\n\t\tconst simpleInputTypes = [\n\t\t\t'button',\n\t\t\t'checkbox',\n\t\t\t'color',\n\t\t\t'file',\n\t\t\t'image',\n\t\t\t'radio',\n\t\t\t'reset',\n\t\t\t'submit',\n\t\t];\n\t\treturn simpleInputTypes.includes( element.getAttribute( 'type' ) );\n\t}\n\n\t// Native textareas should not navigate horizontally.\n\treturn tagName !== 'TEXTAREA';\n}\n\n/**\n * Returns the optimal tab target from the given focused element in the desired\n * direction. A preference is made toward text fields, falling back to the block\n * focus stop if no other candidates exist for the block.\n *\n * @param {Element} target Currently focused text field.\n * @param {boolean} isReverse True if considering as the first field.\n * @param {Element} containerElement Element containing all blocks.\n * @param {boolean} onlyVertical Whether to only consider tabbable elements\n * that are visually above or under the\n * target.\n *\n * @return {?Element} Optimal tab target, if one exists.\n */\nexport function getClosestTabbable(\n\ttarget,\n\tisReverse,\n\tcontainerElement,\n\tonlyVertical\n) {\n\t// Since the current focus target is not guaranteed to be a text field, find\n\t// all focusables. Tabbability is considered later.\n\tlet focusableNodes = focus.focusable.find( containerElement );\n\n\tif ( isReverse ) {\n\t\tfocusableNodes.reverse();\n\t}\n\n\t// Consider as candidates those focusables after the current target. It's\n\t// assumed this can only be reached if the target is focusable (on its\n\t// keydown event), so no need to verify it exists in the set.\n\tfocusableNodes = focusableNodes.slice(\n\t\tfocusableNodes.indexOf( target ) + 1\n\t);\n\n\tlet targetRect;\n\n\tif ( onlyVertical ) {\n\t\ttargetRect = target.getBoundingClientRect();\n\t}\n\n\tfunction isTabCandidate( node ) {\n\t\t// Skip if there's only one child that is content editable (and thus a\n\t\t// better candidate).\n\t\tif (\n\t\t\tnode.children.length === 1 &&\n\t\t\tisInSameBlock( node, node.firstElementChild ) &&\n\t\t\tnode.firstElementChild.getAttribute( 'contenteditable' ) === 'true'\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Not a candidate if the node is not tabbable.\n\t\tif ( ! focus.tabbable.isTabbableIndex( node ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Skip focusable elements such as links within content editable nodes.\n\t\tif ( node.isContentEditable && node.contentEditable !== 'true' ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( onlyVertical ) {\n\t\t\tconst nodeRect = node.getBoundingClientRect();\n\n\t\t\tif (\n\t\t\t\tnodeRect.left >= targetRect.right ||\n\t\t\t\tnodeRect.right <= targetRect.left\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\treturn focusableNodes.find( isTabCandidate );\n}\n\nexport default function useArrowNav() {\n\tconst {\n\t\tgetMultiSelectedBlocksStartClientId,\n\t\tgetMultiSelectedBlocksEndClientId,\n\t\tgetSettings,\n\t\thasMultiSelection,\n\t\t__unstableIsFullySelected,\n\t} = useSelect( blockEditorStore );\n\tconst { selectBlock } = useDispatch( blockEditorStore );\n\treturn useRefEffect( ( node ) => {\n\t\t// Here a DOMRect is stored while moving the caret vertically so\n\t\t// vertical position of the start position can be restored. This is to\n\t\t// recreate browser behaviour across blocks.\n\t\tlet verticalRect;\n\n\t\tfunction onMouseDown() {\n\t\t\tverticalRect = null;\n\t\t}\n\n\t\tfunction isClosestTabbableABlock( target, isReverse ) {\n\t\t\tconst closestTabbable = getClosestTabbable(\n\t\t\t\ttarget,\n\t\t\t\tisReverse,\n\t\t\t\tnode\n\t\t\t);\n\t\t\treturn closestTabbable && getBlockClientId( closestTabbable );\n\t\t}\n\n\t\tfunction onKeyDown( event ) {\n\t\t\tconst { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } =\n\t\t\t\tevent;\n\t\t\tconst isUp = keyCode === UP;\n\t\t\tconst isDown = keyCode === DOWN;\n\t\t\tconst isLeft = keyCode === LEFT;\n\t\t\tconst isRight = keyCode === RIGHT;\n\t\t\tconst isReverse = isUp || isLeft;\n\t\t\tconst isHorizontal = isLeft || isRight;\n\t\t\tconst isVertical = isUp || isDown;\n\t\t\tconst isNav = isHorizontal || isVertical;\n\t\t\tconst hasModifier = shiftKey || ctrlKey || altKey || metaKey;\n\t\t\tconst isNavEdge = isVertical ? isVerticalEdge : isHorizontalEdge;\n\t\t\tconst { ownerDocument } = node;\n\t\t\tconst { defaultView } = ownerDocument;\n\n\t\t\t// If there is a multi-selection, the arrow keys should collapse the\n\t\t\t// selection to the start or end of the selection.\n\t\t\tif ( hasMultiSelection() ) {\n\t\t\t\t// Only handle if we have a full selection (not a native partial\n\t\t\t\t// selection).\n\t\t\t\tif ( ! __unstableIsFullySelected() ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( event.defaultPrevented ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( ! isNav ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( shiftKey ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\tif ( isReverse ) {\n\t\t\t\t\tselectBlock( getMultiSelectedBlocksStartClientId() );\n\t\t\t\t} else {\n\t\t\t\t\tselectBlock( getMultiSelectedBlocksEndClientId(), -1 );\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// When presing any key other than up or down, the initial vertical\n\t\t\t// position must ALWAYS be reset. The vertical position is saved so\n\t\t\t// it can be restored as well as possible on sebsequent vertical\n\t\t\t// arrow key presses. It may not always be possible to restore the\n\t\t\t// exact same position (such as at an empty line), so it wouldn't be\n\t\t\t// good to compute the position right before any vertical arrow key\n\t\t\t// press.\n\t\t\tif ( ! isVertical ) {\n\t\t\t\tverticalRect = null;\n\t\t\t} else if ( ! verticalRect ) {\n\t\t\t\tverticalRect = computeCaretRect( defaultView );\n\t\t\t}\n\n\t\t\t// Abort if navigation has already been handled (e.g. RichText\n\t\t\t// inline boundaries).\n\t\t\tif ( event.defaultPrevented ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( ! isNav ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Abort if our current target is not a candidate for navigation\n\t\t\t// (e.g. preserve native input behaviors).\n\t\t\tif ( ! isNavigationCandidate( target, keyCode, hasModifier ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// In the case of RTL scripts, right means previous and left means\n\t\t\t// next, which is the exact reverse of LTR.\n\t\t\tconst isReverseDir = isRTL( target ) ? ! isReverse : isReverse;\n\t\t\tconst { keepCaretInsideBlock } = getSettings();\n\n\t\t\tif ( shiftKey ) {\n\t\t\t\tif (\n\t\t\t\t\tisClosestTabbableABlock( target, isReverse ) &&\n\t\t\t\t\tisNavEdge( target, isReverse )\n\t\t\t\t) {\n\t\t\t\t\tnode.contentEditable = true;\n\t\t\t\t\t// Firefox doesn't automatically move focus.\n\t\t\t\t\tnode.focus();\n\t\t\t\t}\n\t\t\t} else if (\n\t\t\t\tisVertical &&\n\t\t\t\tisVerticalEdge( target, isReverse ) &&\n\t\t\t\t// When Alt is pressed, only intercept if the caret is also at\n\t\t\t\t// the horizontal edge.\n\t\t\t\t( altKey ? isHorizontalEdge( target, isReverseDir ) : true ) &&\n\t\t\t\t! keepCaretInsideBlock\n\t\t\t) {\n\t\t\t\tconst closestTabbable = getClosestTabbable(\n\t\t\t\t\ttarget,\n\t\t\t\t\tisReverse,\n\t\t\t\t\tnode,\n\t\t\t\t\ttrue\n\t\t\t\t);\n\n\t\t\t\tif ( closestTabbable ) {\n\t\t\t\t\tplaceCaretAtVerticalEdge(\n\t\t\t\t\t\tclosestTabbable,\n\t\t\t\t\t\t// When Alt is pressed, place the caret at the furthest\n\t\t\t\t\t\t// horizontal edge and the furthest vertical edge.\n\t\t\t\t\t\taltKey ? ! isReverse : isReverse,\n\t\t\t\t\t\taltKey ? undefined : verticalRect\n\t\t\t\t\t);\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t} else if (\n\t\t\t\tisHorizontal &&\n\t\t\t\tdefaultView.getSelection().isCollapsed &&\n\t\t\t\tisHorizontalEdge( target, isReverseDir ) &&\n\t\t\t\t! keepCaretInsideBlock\n\t\t\t) {\n\t\t\t\tconst closestTabbable = getClosestTabbable(\n\t\t\t\t\ttarget,\n\t\t\t\t\tisReverseDir,\n\t\t\t\t\tnode\n\t\t\t\t);\n\t\t\t\tplaceCaretAtHorizontalEdge( closestTabbable, isReverse );\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\n\t\tnode.addEventListener( 'mousedown', onMouseDown );\n\t\tnode.addEventListener( 'keydown', onKeyDown );\n\t\treturn () => {\n\t\t\tnode.removeEventListener( 'mousedown', onMouseDown );\n\t\t\tnode.removeEventListener( 'keydown', onKeyDown );\n\t\t};\n\t}, [] );\n}\n"]}
|
|
@@ -19,6 +19,7 @@ import './content-lock-ui';
|
|
|
19
19
|
import './metadata';
|
|
20
20
|
import './metadata-name';
|
|
21
21
|
export { useCustomSides } from './dimensions';
|
|
22
|
+
export { useLayoutClasses, useLayoutStyles } from './layout';
|
|
22
23
|
export { getBorderClassesAndStyles, useBorderProps } from './use-border-props';
|
|
23
24
|
export { getColorClassesAndStyles, useColorProps } from './use-color-props';
|
|
24
25
|
export { getSpacingClassesAndStyles } from './use-spacing-props';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/block-editor/src/hooks/index.js"],"names":["useCustomSides","getBorderClassesAndStyles","useBorderProps","getColorClassesAndStyles","useColorProps","getSpacingClassesAndStyles","getTypographyClassesAndStyles","getGapCSSValue","useCachedTruthy"],"mappings":"AAAA;AACA;AACA;AACA,OAAO,UAAP;AACA,OAAO,SAAP;AACA,OAAO,QAAP;AACA,OAAO,UAAP;AACA,OAAO,cAAP;AACA,OAAO,qBAAP;AACA,OAAO,wBAAP;AACA,OAAO,SAAP;AACA,OAAO,YAAP;AACA,OAAO,SAAP;AACA,OAAO,WAAP;AACA,OAAO,aAAP;AACA,OAAO,UAAP;AACA,OAAO,UAAP;AACA,OAAO,mBAAP;AACA,OAAO,YAAP;AACA,OAAO,iBAAP;AAEA,SAASA,cAAT,QAA+B,cAA/B;AACA,SAASC,yBAAT,EAAoCC,cAApC,QAA0D,oBAA1D;AACA,SAASC,wBAAT,EAAmCC,aAAnC,QAAwD,mBAAxD;AACA,SAASC,0BAAT,QAA2C,qBAA3C;AACA,SAASC,6BAAT,QAA8C,wBAA9C;AACA,SAASC,cAAT,QAA+B,OAA/B;AACA,SAASC,eAAT,QAAgC,qBAAhC","sourcesContent":["/**\n * Internal dependencies\n */\nimport './compat';\nimport './align';\nimport './lock';\nimport './anchor';\nimport './aria-label';\nimport './custom-class-name';\nimport './generated-class-name';\nimport './style';\nimport './settings';\nimport './color';\nimport './duotone';\nimport './font-size';\nimport './border';\nimport './layout';\nimport './content-lock-ui';\nimport './metadata';\nimport './metadata-name';\n\nexport { useCustomSides } from './dimensions';\nexport { getBorderClassesAndStyles, useBorderProps } from './use-border-props';\nexport { getColorClassesAndStyles, useColorProps } from './use-color-props';\nexport { getSpacingClassesAndStyles } from './use-spacing-props';\nexport { getTypographyClassesAndStyles } from './use-typography-props';\nexport { getGapCSSValue } from './gap';\nexport { useCachedTruthy } from './use-cached-truthy';\n"]}
|
|
1
|
+
{"version":3,"sources":["@wordpress/block-editor/src/hooks/index.js"],"names":["useCustomSides","useLayoutClasses","useLayoutStyles","getBorderClassesAndStyles","useBorderProps","getColorClassesAndStyles","useColorProps","getSpacingClassesAndStyles","getTypographyClassesAndStyles","getGapCSSValue","useCachedTruthy"],"mappings":"AAAA;AACA;AACA;AACA,OAAO,UAAP;AACA,OAAO,SAAP;AACA,OAAO,QAAP;AACA,OAAO,UAAP;AACA,OAAO,cAAP;AACA,OAAO,qBAAP;AACA,OAAO,wBAAP;AACA,OAAO,SAAP;AACA,OAAO,YAAP;AACA,OAAO,SAAP;AACA,OAAO,WAAP;AACA,OAAO,aAAP;AACA,OAAO,UAAP;AACA,OAAO,UAAP;AACA,OAAO,mBAAP;AACA,OAAO,YAAP;AACA,OAAO,iBAAP;AAEA,SAASA,cAAT,QAA+B,cAA/B;AACA,SAASC,gBAAT,EAA2BC,eAA3B,QAAkD,UAAlD;AACA,SAASC,yBAAT,EAAoCC,cAApC,QAA0D,oBAA1D;AACA,SAASC,wBAAT,EAAmCC,aAAnC,QAAwD,mBAAxD;AACA,SAASC,0BAAT,QAA2C,qBAA3C;AACA,SAASC,6BAAT,QAA8C,wBAA9C;AACA,SAASC,cAAT,QAA+B,OAA/B;AACA,SAASC,eAAT,QAAgC,qBAAhC","sourcesContent":["/**\n * Internal dependencies\n */\nimport './compat';\nimport './align';\nimport './lock';\nimport './anchor';\nimport './aria-label';\nimport './custom-class-name';\nimport './generated-class-name';\nimport './style';\nimport './settings';\nimport './color';\nimport './duotone';\nimport './font-size';\nimport './border';\nimport './layout';\nimport './content-lock-ui';\nimport './metadata';\nimport './metadata-name';\n\nexport { useCustomSides } from './dimensions';\nexport { useLayoutClasses, useLayoutStyles } from './layout';\nexport { getBorderClassesAndStyles, useBorderProps } from './use-border-props';\nexport { getColorClassesAndStyles, useColorProps } from './use-color-props';\nexport { getSpacingClassesAndStyles } from './use-spacing-props';\nexport { getTypographyClassesAndStyles } from './use-typography-props';\nexport { getGapCSSValue } from './gap';\nexport { useCachedTruthy } from './use-cached-truthy';\n"]}
|