@wordpress/block-editor 15.6.5 → 15.6.7
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/build/components/block-variation-transforms/index.js +32 -5
- package/build/components/block-variation-transforms/index.js.map +2 -2
- package/build/components/border-radius-control/single-input-control.js +1 -0
- package/build/components/border-radius-control/single-input-control.js.map +2 -2
- package/build/components/global-styles/typography-panel.js +3 -2
- package/build/components/global-styles/typography-panel.js.map +2 -2
- package/build/hooks/block-bindings.js +11 -7
- package/build/hooks/block-bindings.js.map +2 -2
- package/build/hooks/fit-text.js +3 -71
- package/build/hooks/fit-text.js.map +3 -3
- package/build/hooks/font-size.js +5 -2
- package/build/hooks/font-size.js.map +2 -2
- package/build/hooks/typography.js +3 -7
- package/build/hooks/typography.js.map +2 -2
- package/build/store/selectors.js +9 -3
- package/build/store/selectors.js.map +2 -2
- package/build/utils/fit-text-utils.js +10 -2
- package/build/utils/fit-text-utils.js.map +2 -2
- package/build-module/components/block-variation-transforms/index.js +32 -5
- package/build-module/components/block-variation-transforms/index.js.map +2 -2
- package/build-module/components/border-radius-control/single-input-control.js +1 -0
- package/build-module/components/border-radius-control/single-input-control.js.map +2 -2
- package/build-module/components/global-styles/typography-panel.js +3 -2
- package/build-module/components/global-styles/typography-panel.js.map +2 -2
- package/build-module/hooks/block-bindings.js +11 -7
- package/build-module/hooks/block-bindings.js.map +2 -2
- package/build-module/hooks/fit-text.js +2 -62
- package/build-module/hooks/fit-text.js.map +2 -2
- package/build-module/hooks/font-size.js +5 -2
- package/build-module/hooks/font-size.js.map +2 -2
- package/build-module/hooks/typography.js +3 -7
- package/build-module/hooks/typography.js.map +2 -2
- package/build-module/store/selectors.js +9 -3
- package/build-module/store/selectors.js.map +2 -2
- package/build-module/utils/fit-text-utils.js +10 -2
- package/build-module/utils/fit-text-utils.js.map +2 -2
- package/package.json +8 -8
- package/src/components/block-variation-transforms/index.js +96 -35
- package/src/components/border-radius-control/single-input-control.js +1 -0
- package/src/components/global-styles/typography-panel.js +2 -1
- package/src/hooks/block-bindings.js +11 -7
- package/src/hooks/fit-text.js +2 -78
- package/src/hooks/font-size.js +7 -2
- package/src/hooks/typography.js +2 -10
- package/src/store/selectors.js +17 -3
- package/src/utils/fit-text-utils.js +20 -2
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
function findOptimalFontSize(textElement, applyFontSize) {
|
|
2
2
|
const alreadyHasScrollableHeight = textElement.scrollHeight > textElement.clientHeight;
|
|
3
3
|
let minSize = 5;
|
|
4
|
-
let maxSize =
|
|
4
|
+
let maxSize = 2400;
|
|
5
5
|
let bestSize = minSize;
|
|
6
|
+
const computedStyle = window.getComputedStyle(textElement);
|
|
7
|
+
const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;
|
|
8
|
+
const paddingRight = parseFloat(computedStyle.paddingRight) || 0;
|
|
9
|
+
const range = document.createRange();
|
|
10
|
+
range.selectNodeContents(textElement);
|
|
6
11
|
while (minSize <= maxSize) {
|
|
7
12
|
const midSize = Math.floor((minSize + maxSize) / 2);
|
|
8
13
|
applyFontSize(midSize);
|
|
9
|
-
const
|
|
14
|
+
const rect = range.getBoundingClientRect();
|
|
15
|
+
const textWidth = rect.width;
|
|
16
|
+
const fitsWidth = textElement.scrollWidth <= textElement.clientWidth && textWidth <= textElement.clientWidth - paddingLeft - paddingRight;
|
|
10
17
|
const fitsHeight = alreadyHasScrollableHeight || textElement.scrollHeight <= textElement.clientHeight;
|
|
11
18
|
if (fitsWidth && fitsHeight) {
|
|
12
19
|
bestSize = midSize;
|
|
@@ -15,6 +22,7 @@ function findOptimalFontSize(textElement, applyFontSize) {
|
|
|
15
22
|
maxSize = midSize - 1;
|
|
16
23
|
}
|
|
17
24
|
}
|
|
25
|
+
range.detach();
|
|
18
26
|
return bestSize;
|
|
19
27
|
}
|
|
20
28
|
function optimizeFitText(textElement, applyFontSize) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/fit-text-utils.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * Shared utility functions for fit text functionality.\n * Uses callback-based approach for maximum code reuse between editor and frontend.\n */\n\n/**\n * Find optimal font size using simple binary search between 5-600px.\n *\n * @param {HTMLElement} textElement The text element\n * @param {Function} applyFontSize Function that receives font size in pixels\n * @return {number} Optimal font size\n */\nfunction findOptimalFontSize( textElement, applyFontSize ) {\n\tconst alreadyHasScrollableHeight =\n\t\ttextElement.scrollHeight > textElement.clientHeight;\n\tlet minSize = 5;\n\tlet maxSize =
|
|
5
|
-
"mappings": "AAYA,SAAS,oBAAqB,aAAa,eAAgB;AAC1D,QAAM,6BACL,YAAY,eAAe,YAAY;AACxC,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,WAAW;AAEf,SAAQ,WAAW,SAAU;AAC5B,UAAM,UAAU,KAAK,OAAS,UAAU,WAAY,CAAE;AACtD,kBAAe,OAAQ;
|
|
4
|
+
"sourcesContent": ["/**\n * Shared utility functions for fit text functionality.\n * Uses callback-based approach for maximum code reuse between editor and frontend.\n */\n\n/**\n * Find optimal font size using simple binary search between 5-600px.\n *\n * @param {HTMLElement} textElement The text element\n * @param {Function} applyFontSize Function that receives font size in pixels\n * @return {number} Optimal font size\n */\nfunction findOptimalFontSize( textElement, applyFontSize ) {\n\tconst alreadyHasScrollableHeight =\n\t\ttextElement.scrollHeight > textElement.clientHeight;\n\tlet minSize = 5;\n\tlet maxSize = 2400;\n\tlet bestSize = minSize;\n\n\tconst computedStyle = window.getComputedStyle( textElement );\n\tconst paddingLeft = parseFloat( computedStyle.paddingLeft ) || 0;\n\tconst paddingRight = parseFloat( computedStyle.paddingRight ) || 0;\n\tconst range = document.createRange();\n\trange.selectNodeContents( textElement );\n\n\twhile ( minSize <= maxSize ) {\n\t\tconst midSize = Math.floor( ( minSize + maxSize ) / 2 );\n\t\tapplyFontSize( midSize );\n\n\t\t// When there is padding if the text overflows to the\n\t\t// padding area, it should be considered overflowing.\n\t\t// Use Range API to measure actual text content dimensions.\n\t\tconst rect = range.getBoundingClientRect();\n\t\tconst textWidth = rect.width;\n\n\t\t// Check if text fits within the element's width and is not\n\t\t// overflowing into the padding area.\n\t\tconst fitsWidth =\n\t\t\ttextElement.scrollWidth <= textElement.clientWidth &&\n\t\t\ttextWidth <= textElement.clientWidth - paddingLeft - paddingRight;\n\t\t// Check if text fits within the element's height.\n\t\tconst fitsHeight =\n\t\t\talreadyHasScrollableHeight ||\n\t\t\ttextElement.scrollHeight <= textElement.clientHeight;\n\n\t\tif ( fitsWidth && fitsHeight ) {\n\t\t\tbestSize = midSize;\n\t\t\tminSize = midSize + 1;\n\t\t} else {\n\t\t\tmaxSize = midSize - 1;\n\t\t}\n\t}\n\trange.detach();\n\n\treturn bestSize;\n}\n\n/**\n * Complete fit text optimization for a single text element.\n * Handles the full flow using callbacks for font size application.\n *\n * @param {HTMLElement} textElement The text element (paragraph, heading, etc.)\n * @param {Function} applyFontSize Function that receives font size in pixels (0 to clear, >0 to apply)\n */\nexport function optimizeFitText( textElement, applyFontSize ) {\n\tif ( ! textElement ) {\n\t\treturn;\n\t}\n\n\tapplyFontSize( 0 );\n\n\tconst optimalSize = findOptimalFontSize( textElement, applyFontSize );\n\n\tapplyFontSize( optimalSize );\n\treturn optimalSize;\n}\n"],
|
|
5
|
+
"mappings": "AAYA,SAAS,oBAAqB,aAAa,eAAgB;AAC1D,QAAM,6BACL,YAAY,eAAe,YAAY;AACxC,MAAI,UAAU;AACd,MAAI,UAAU;AACd,MAAI,WAAW;AAEf,QAAM,gBAAgB,OAAO,iBAAkB,WAAY;AAC3D,QAAM,cAAc,WAAY,cAAc,WAAY,KAAK;AAC/D,QAAM,eAAe,WAAY,cAAc,YAAa,KAAK;AACjE,QAAM,QAAQ,SAAS,YAAY;AACnC,QAAM,mBAAoB,WAAY;AAEtC,SAAQ,WAAW,SAAU;AAC5B,UAAM,UAAU,KAAK,OAAS,UAAU,WAAY,CAAE;AACtD,kBAAe,OAAQ;AAKvB,UAAM,OAAO,MAAM,sBAAsB;AACzC,UAAM,YAAY,KAAK;AAIvB,UAAM,YACL,YAAY,eAAe,YAAY,eACvC,aAAa,YAAY,cAAc,cAAc;AAEtD,UAAM,aACL,8BACA,YAAY,gBAAgB,YAAY;AAEzC,QAAK,aAAa,YAAa;AAC9B,iBAAW;AACX,gBAAU,UAAU;AAAA,IACrB,OAAO;AACN,gBAAU,UAAU;AAAA,IACrB;AAAA,EACD;AACA,QAAM,OAAO;AAEb,SAAO;AACR;AASO,SAAS,gBAAiB,aAAa,eAAgB;AAC7D,MAAK,CAAE,aAAc;AACpB;AAAA,EACD;AAEA,gBAAe,CAAE;AAEjB,QAAM,cAAc,oBAAqB,aAAa,aAAc;AAEpE,gBAAe,WAAY;AAC3B,SAAO;AACR;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/block-editor",
|
|
3
|
-
"version": "15.6.
|
|
3
|
+
"version": "15.6.7",
|
|
4
4
|
"description": "Generic block editor.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
"@wordpress/base-styles": "^6.9.1",
|
|
62
62
|
"@wordpress/blob": "^4.33.1",
|
|
63
63
|
"@wordpress/block-serialization-default-parser": "^5.33.1",
|
|
64
|
-
"@wordpress/blocks": "^15.6.
|
|
65
|
-
"@wordpress/commands": "^1.33.
|
|
66
|
-
"@wordpress/components": "^30.6.
|
|
64
|
+
"@wordpress/blocks": "^15.6.2",
|
|
65
|
+
"@wordpress/commands": "^1.33.4",
|
|
66
|
+
"@wordpress/components": "^30.6.4",
|
|
67
67
|
"@wordpress/compose": "^7.33.1",
|
|
68
68
|
"@wordpress/data": "^10.33.1",
|
|
69
69
|
"@wordpress/date": "^5.33.1",
|
|
@@ -80,13 +80,13 @@
|
|
|
80
80
|
"@wordpress/keyboard-shortcuts": "^5.33.1",
|
|
81
81
|
"@wordpress/keycodes": "^4.33.1",
|
|
82
82
|
"@wordpress/notices": "^5.33.1",
|
|
83
|
-
"@wordpress/preferences": "^4.33.
|
|
83
|
+
"@wordpress/preferences": "^4.33.4",
|
|
84
84
|
"@wordpress/priority-queue": "^3.33.1",
|
|
85
85
|
"@wordpress/private-apis": "^1.33.1",
|
|
86
|
-
"@wordpress/rich-text": "^7.33.
|
|
86
|
+
"@wordpress/rich-text": "^7.33.2",
|
|
87
87
|
"@wordpress/style-engine": "^2.33.1",
|
|
88
88
|
"@wordpress/token-list": "^3.33.1",
|
|
89
|
-
"@wordpress/upload-media": "^0.18.
|
|
89
|
+
"@wordpress/upload-media": "^0.18.4",
|
|
90
90
|
"@wordpress/url": "^4.33.1",
|
|
91
91
|
"@wordpress/warning": "^3.33.1",
|
|
92
92
|
"@wordpress/wordcount": "^4.33.1",
|
|
@@ -112,5 +112,5 @@
|
|
|
112
112
|
"publishConfig": {
|
|
113
113
|
"access": "public"
|
|
114
114
|
},
|
|
115
|
-
"gitHead": "
|
|
115
|
+
"gitHead": "1c473d047a0b8f529f07cc1e23324a6be723bbc9"
|
|
116
116
|
}
|
|
@@ -139,41 +139,102 @@ function VariationsToggleGroupControl( {
|
|
|
139
139
|
|
|
140
140
|
function __experimentalBlockVariationTransforms( { blockClientId } ) {
|
|
141
141
|
const { updateBlockAttributes } = useDispatch( blockEditorStore );
|
|
142
|
-
const {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
142
|
+
const {
|
|
143
|
+
activeBlockVariation,
|
|
144
|
+
unfilteredVariations,
|
|
145
|
+
blockName,
|
|
146
|
+
isContentOnly,
|
|
147
|
+
isSection,
|
|
148
|
+
} = useSelect(
|
|
149
|
+
( select ) => {
|
|
150
|
+
const { getActiveBlockVariation, getBlockVariations } =
|
|
151
|
+
select( blocksStore );
|
|
152
|
+
|
|
153
|
+
const {
|
|
154
|
+
getBlockName,
|
|
155
|
+
getBlockAttributes,
|
|
156
|
+
getBlockEditingMode,
|
|
157
|
+
isSectionBlock,
|
|
158
|
+
} = unlock( select( blockEditorStore ) );
|
|
159
|
+
|
|
160
|
+
const name = blockClientId && getBlockName( blockClientId );
|
|
161
|
+
|
|
162
|
+
const { hasContentRoleAttribute } = unlock( select( blocksStore ) );
|
|
163
|
+
const isContentBlock = hasContentRoleAttribute( name );
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
activeBlockVariation: getActiveBlockVariation(
|
|
167
|
+
name,
|
|
168
|
+
getBlockAttributes( blockClientId ),
|
|
169
|
+
'transform'
|
|
170
|
+
),
|
|
171
|
+
unfilteredVariations:
|
|
172
|
+
name && getBlockVariations( name, 'transform' ),
|
|
173
|
+
blockName: name,
|
|
174
|
+
isContentOnly:
|
|
175
|
+
getBlockEditingMode( blockClientId ) === 'contentOnly' &&
|
|
176
|
+
! isContentBlock,
|
|
177
|
+
isSection: isSectionBlock( blockClientId ),
|
|
178
|
+
};
|
|
179
|
+
},
|
|
180
|
+
[ blockClientId ]
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
/*
|
|
184
|
+
* Hack for WordPress 6.9
|
|
185
|
+
*
|
|
186
|
+
* The Stretchy blocks shipped in 6.9 were ultimately
|
|
187
|
+
* implemented as block variations of the base types Paragraph
|
|
188
|
+
* and Heading. See #73056 for discussion and trade-offs.
|
|
189
|
+
*
|
|
190
|
+
* The main drawback of this choice is that the Variations API
|
|
191
|
+
* doesn't offer enough control over how prominent and how tied
|
|
192
|
+
* to the base type a variation should be.
|
|
193
|
+
*
|
|
194
|
+
* In order to ship these new "blocks" with an acceptable UX,
|
|
195
|
+
* we need two hacks until the Variations API is improved:
|
|
196
|
+
*
|
|
197
|
+
* - Don't show the variations switcher in the block inspector
|
|
198
|
+
* for Paragraph, Heading, Stretchy Paragraph and Stretchy
|
|
199
|
+
* Heading (implemented below). Transformations are still
|
|
200
|
+
* available in the block switcher.
|
|
201
|
+
*
|
|
202
|
+
* - Move the stretchy variations to the end of the core blocks
|
|
203
|
+
* list in the block inserter (implemented in
|
|
204
|
+
* getInserterItems in #73056).
|
|
205
|
+
*/
|
|
206
|
+
const variations = useMemo( () => {
|
|
207
|
+
if ( blockName === 'core/paragraph' ) {
|
|
208
|
+
// Always hide options when active variation is stretchy, but
|
|
209
|
+
// ensure that there are no third-party variations before doing the
|
|
210
|
+
// same elsewhere.
|
|
211
|
+
if (
|
|
212
|
+
activeBlockVariation?.name === 'stretchy-paragraph' ||
|
|
213
|
+
unfilteredVariations.every( ( v ) =>
|
|
214
|
+
[ 'paragraph', 'stretchy-paragraph' ].includes( v.name )
|
|
215
|
+
)
|
|
216
|
+
) {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
// If there are other variations, only hide the stretchy one.
|
|
220
|
+
return unfilteredVariations.filter(
|
|
221
|
+
( v ) => v.name !== 'stretchy-paragraph'
|
|
222
|
+
);
|
|
223
|
+
} else if ( blockName === 'core/heading' ) {
|
|
224
|
+
if (
|
|
225
|
+
activeBlockVariation?.name === 'stretchy-heading' ||
|
|
226
|
+
unfilteredVariations.every( ( v ) =>
|
|
227
|
+
[ 'heading', 'stretchy-heading' ].includes( v.name )
|
|
228
|
+
)
|
|
229
|
+
) {
|
|
230
|
+
return [];
|
|
231
|
+
}
|
|
232
|
+
return unfilteredVariations.filter(
|
|
233
|
+
( v ) => v.name !== 'stretchy-heading'
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
return unfilteredVariations;
|
|
237
|
+
}, [ activeBlockVariation?.name, blockName, unfilteredVariations ] );
|
|
177
238
|
|
|
178
239
|
const selectedValue = activeBlockVariation?.name;
|
|
179
240
|
|
|
@@ -74,6 +74,7 @@ export default function SingleInputControl( {
|
|
|
74
74
|
const onChangeUnit = ( next ) => {
|
|
75
75
|
const newUnits = { ...selectedUnits };
|
|
76
76
|
if ( corner === 'all' ) {
|
|
77
|
+
newUnits.flat = next;
|
|
77
78
|
newUnits.topLeft = next;
|
|
78
79
|
newUnits.topRight = next;
|
|
79
80
|
newUnits.bottomLeft = next;
|
|
@@ -178,6 +178,7 @@ export default function TypographyPanel( {
|
|
|
178
178
|
settings,
|
|
179
179
|
panelId,
|
|
180
180
|
defaultControls = DEFAULT_CONTROLS,
|
|
181
|
+
fitText = false,
|
|
181
182
|
} ) {
|
|
182
183
|
const decodeValue = ( rawValue ) =>
|
|
183
184
|
getValueFromVariable( { settings }, '', rawValue );
|
|
@@ -447,7 +448,7 @@ export default function TypographyPanel( {
|
|
|
447
448
|
/>
|
|
448
449
|
</ToolsPanelItem>
|
|
449
450
|
) }
|
|
450
|
-
{ hasFontSizeEnabled && (
|
|
451
|
+
{ hasFontSizeEnabled && ! fitText && (
|
|
451
452
|
<ToolsPanelItem
|
|
452
453
|
label={ __( 'Size' ) }
|
|
453
454
|
hasValue={ hasFontSize }
|
|
@@ -110,13 +110,17 @@ function BlockBindingsPanelMenuContent( { attribute, binding, sources } ) {
|
|
|
110
110
|
key: item.key,
|
|
111
111
|
},
|
|
112
112
|
};
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
let values = {};
|
|
114
|
+
try {
|
|
115
|
+
values = source.getValues( {
|
|
116
|
+
select,
|
|
117
|
+
context: blockContext,
|
|
118
|
+
bindings: {
|
|
119
|
+
[ attribute ]: itemBindings,
|
|
120
|
+
},
|
|
121
|
+
} );
|
|
122
|
+
} catch ( e ) {}
|
|
123
|
+
|
|
120
124
|
return (
|
|
121
125
|
<Menu.CheckboxItem
|
|
122
126
|
key={
|
package/src/hooks/fit-text.js
CHANGED
|
@@ -5,11 +5,6 @@ import { addFilter } from '@wordpress/hooks';
|
|
|
5
5
|
import { hasBlockSupport } from '@wordpress/blocks';
|
|
6
6
|
import { useEffect, useCallback } from '@wordpress/element';
|
|
7
7
|
import { useSelect } from '@wordpress/data';
|
|
8
|
-
import { __ } from '@wordpress/i18n';
|
|
9
|
-
import {
|
|
10
|
-
ToggleControl,
|
|
11
|
-
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
12
|
-
} from '@wordpress/components';
|
|
13
8
|
|
|
14
9
|
const EMPTY_OBJECT = {};
|
|
15
10
|
|
|
@@ -19,7 +14,6 @@ const EMPTY_OBJECT = {};
|
|
|
19
14
|
import { optimizeFitText } from '../utils/fit-text-utils';
|
|
20
15
|
import { store as blockEditorStore } from '../store';
|
|
21
16
|
import { useBlockElement } from '../components/block-list/use-block-props/use-block-refs';
|
|
22
|
-
import InspectorControls from '../components/inspector-controls';
|
|
23
17
|
|
|
24
18
|
export const FIT_TEXT_SUPPORT_KEY = 'typography.fitText';
|
|
25
19
|
|
|
@@ -207,76 +201,6 @@ function useFitText( { fitText, name, clientId } ) {
|
|
|
207
201
|
] );
|
|
208
202
|
}
|
|
209
203
|
|
|
210
|
-
/**
|
|
211
|
-
* Fit text control component for the typography panel.
|
|
212
|
-
*
|
|
213
|
-
* @param {Object} props Component props.
|
|
214
|
-
* @param {string} props.clientId Block client ID.
|
|
215
|
-
* @param {Function} props.setAttributes Function to set block attributes.
|
|
216
|
-
* @param {string} props.name Block name.
|
|
217
|
-
* @param {boolean} props.fitText Whether fit text is enabled.
|
|
218
|
-
* @param {string} props.fontSize Font size slug.
|
|
219
|
-
* @param {Object} props.style Block style object.
|
|
220
|
-
*/
|
|
221
|
-
export function FitTextControl( {
|
|
222
|
-
clientId,
|
|
223
|
-
fitText = false,
|
|
224
|
-
setAttributes,
|
|
225
|
-
name,
|
|
226
|
-
fontSize,
|
|
227
|
-
style,
|
|
228
|
-
} ) {
|
|
229
|
-
if ( ! hasBlockSupport( name, FIT_TEXT_SUPPORT_KEY ) ) {
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
|
-
return (
|
|
233
|
-
<InspectorControls group="typography">
|
|
234
|
-
<ToolsPanelItem
|
|
235
|
-
hasValue={ () => fitText }
|
|
236
|
-
label={ __( 'Fit text' ) }
|
|
237
|
-
onDeselect={ () => setAttributes( { fitText: undefined } ) }
|
|
238
|
-
resetAllFilter={ () => ( { fitText: undefined } ) }
|
|
239
|
-
panelId={ clientId }
|
|
240
|
-
>
|
|
241
|
-
<ToggleControl
|
|
242
|
-
__nextHasNoMarginBottom
|
|
243
|
-
label={ __( 'Fit text' ) }
|
|
244
|
-
checked={ fitText }
|
|
245
|
-
onChange={ () => {
|
|
246
|
-
const newFitText = ! fitText || undefined;
|
|
247
|
-
const updates = { fitText: newFitText };
|
|
248
|
-
|
|
249
|
-
// When enabling fit text, clear font size if it has a value
|
|
250
|
-
if ( newFitText ) {
|
|
251
|
-
if ( fontSize ) {
|
|
252
|
-
updates.fontSize = undefined;
|
|
253
|
-
}
|
|
254
|
-
if ( style?.typography?.fontSize ) {
|
|
255
|
-
updates.style = {
|
|
256
|
-
...style,
|
|
257
|
-
typography: {
|
|
258
|
-
...style?.typography,
|
|
259
|
-
fontSize: undefined,
|
|
260
|
-
},
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
setAttributes( updates );
|
|
266
|
-
} }
|
|
267
|
-
help={
|
|
268
|
-
fitText
|
|
269
|
-
? __( 'Text will resize to fit its container.' )
|
|
270
|
-
: __(
|
|
271
|
-
'The text will resize to fit its container, resetting other font size settings.'
|
|
272
|
-
)
|
|
273
|
-
}
|
|
274
|
-
/>
|
|
275
|
-
</ToolsPanelItem>
|
|
276
|
-
</InspectorControls>
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
204
|
/**
|
|
281
205
|
* Override props applied to the block element on save.
|
|
282
206
|
*
|
|
@@ -338,7 +262,7 @@ const hasFitTextSupport = ( blockNameOrType ) => {
|
|
|
338
262
|
export default {
|
|
339
263
|
useBlockProps,
|
|
340
264
|
addSaveProps,
|
|
341
|
-
attributeKeys: [ 'fitText'
|
|
265
|
+
attributeKeys: [ 'fitText' ],
|
|
342
266
|
hasSupport: hasFitTextSupport,
|
|
343
|
-
edit:
|
|
267
|
+
edit: () => null,
|
|
344
268
|
};
|
package/src/hooks/font-size.js
CHANGED
|
@@ -92,11 +92,16 @@ function addSaveProps( props, blockNameOrType, attributes ) {
|
|
|
92
92
|
*/
|
|
93
93
|
export function FontSizeEdit( props ) {
|
|
94
94
|
const {
|
|
95
|
-
attributes: { fontSize, style },
|
|
95
|
+
attributes: { fontSize, style, fitText },
|
|
96
96
|
setAttributes,
|
|
97
97
|
} = props;
|
|
98
|
+
|
|
98
99
|
const [ fontSizes ] = useSettings( 'typography.fontSizes' );
|
|
99
100
|
|
|
101
|
+
// Hide font size UI when fitText is enabled
|
|
102
|
+
if ( fitText ) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
100
105
|
const onChange = ( value, selectedItem ) => {
|
|
101
106
|
// Use the selectedItem's slug if available, otherwise fall back to finding by value
|
|
102
107
|
const fontSizeSlug =
|
|
@@ -211,7 +216,7 @@ function useBlockProps( { name, fontSize, style } ) {
|
|
|
211
216
|
export default {
|
|
212
217
|
useBlockProps,
|
|
213
218
|
addSaveProps,
|
|
214
|
-
attributeKeys: [ 'fontSize', 'style' ],
|
|
219
|
+
attributeKeys: [ 'fontSize', 'style', 'fitText' ],
|
|
215
220
|
hasSupport( name ) {
|
|
216
221
|
return hasBlockSupport( name, FONT_SIZE_SUPPORT_KEY );
|
|
217
222
|
},
|
package/src/hooks/typography.js
CHANGED
|
@@ -130,16 +130,7 @@ export function TypographyPanel( { clientId, name, setAttributes, settings } ) {
|
|
|
130
130
|
);
|
|
131
131
|
|
|
132
132
|
const onChange = ( newStyle ) => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// If setting a font size and fitText is currently enabled, disable it
|
|
136
|
-
const hasFontSize =
|
|
137
|
-
newAttributes.fontSize || newAttributes.style?.typography?.fontSize;
|
|
138
|
-
if ( hasFontSize && fitText ) {
|
|
139
|
-
newAttributes.fitText = undefined;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
setAttributes( newAttributes );
|
|
133
|
+
setAttributes( styleToAttributes( newStyle ) );
|
|
143
134
|
};
|
|
144
135
|
|
|
145
136
|
if ( ! isEnabled ) {
|
|
@@ -159,6 +150,7 @@ export function TypographyPanel( { clientId, name, setAttributes, settings } ) {
|
|
|
159
150
|
value={ value }
|
|
160
151
|
onChange={ onChange }
|
|
161
152
|
defaultControls={ defaultControls }
|
|
153
|
+
fitText={ fitText }
|
|
162
154
|
/>
|
|
163
155
|
);
|
|
164
156
|
}
|
package/src/store/selectors.js
CHANGED
|
@@ -2263,6 +2263,8 @@ export const getInserterItems = createRegistrySelector( ( select ) =>
|
|
|
2263
2263
|
} ) );
|
|
2264
2264
|
}
|
|
2265
2265
|
|
|
2266
|
+
// Hardcode: Collect stretch variations separately to add at the end
|
|
2267
|
+
const stretchVariations = [];
|
|
2266
2268
|
const items = blockTypeInserterItems.reduce(
|
|
2267
2269
|
( accumulator, item ) => {
|
|
2268
2270
|
const { variations = [] } = item;
|
|
@@ -2275,14 +2277,26 @@ export const getInserterItems = createRegistrySelector( ( select ) =>
|
|
|
2275
2277
|
state,
|
|
2276
2278
|
item
|
|
2277
2279
|
);
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2280
|
+
variations
|
|
2281
|
+
.map( variationMapper )
|
|
2282
|
+
.forEach( ( variation ) => {
|
|
2283
|
+
if (
|
|
2284
|
+
variation.id ===
|
|
2285
|
+
'core/paragraph/stretchy-paragraph' ||
|
|
2286
|
+
variation.id ===
|
|
2287
|
+
'core/heading/stretchy-heading'
|
|
2288
|
+
) {
|
|
2289
|
+
stretchVariations.push( variation );
|
|
2290
|
+
} else {
|
|
2291
|
+
accumulator.push( variation );
|
|
2292
|
+
}
|
|
2293
|
+
} );
|
|
2281
2294
|
}
|
|
2282
2295
|
return accumulator;
|
|
2283
2296
|
},
|
|
2284
2297
|
[]
|
|
2285
2298
|
);
|
|
2299
|
+
items.push( ...stretchVariations );
|
|
2286
2300
|
|
|
2287
2301
|
// Ensure core blocks are prioritized in the returned results,
|
|
2288
2302
|
// because third party blocks can be registered earlier than
|
|
@@ -14,14 +14,31 @@ function findOptimalFontSize( textElement, applyFontSize ) {
|
|
|
14
14
|
const alreadyHasScrollableHeight =
|
|
15
15
|
textElement.scrollHeight > textElement.clientHeight;
|
|
16
16
|
let minSize = 5;
|
|
17
|
-
let maxSize =
|
|
17
|
+
let maxSize = 2400;
|
|
18
18
|
let bestSize = minSize;
|
|
19
19
|
|
|
20
|
+
const computedStyle = window.getComputedStyle( textElement );
|
|
21
|
+
const paddingLeft = parseFloat( computedStyle.paddingLeft ) || 0;
|
|
22
|
+
const paddingRight = parseFloat( computedStyle.paddingRight ) || 0;
|
|
23
|
+
const range = document.createRange();
|
|
24
|
+
range.selectNodeContents( textElement );
|
|
25
|
+
|
|
20
26
|
while ( minSize <= maxSize ) {
|
|
21
27
|
const midSize = Math.floor( ( minSize + maxSize ) / 2 );
|
|
22
28
|
applyFontSize( midSize );
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
// When there is padding if the text overflows to the
|
|
31
|
+
// padding area, it should be considered overflowing.
|
|
32
|
+
// Use Range API to measure actual text content dimensions.
|
|
33
|
+
const rect = range.getBoundingClientRect();
|
|
34
|
+
const textWidth = rect.width;
|
|
35
|
+
|
|
36
|
+
// Check if text fits within the element's width and is not
|
|
37
|
+
// overflowing into the padding area.
|
|
38
|
+
const fitsWidth =
|
|
39
|
+
textElement.scrollWidth <= textElement.clientWidth &&
|
|
40
|
+
textWidth <= textElement.clientWidth - paddingLeft - paddingRight;
|
|
41
|
+
// Check if text fits within the element's height.
|
|
25
42
|
const fitsHeight =
|
|
26
43
|
alreadyHasScrollableHeight ||
|
|
27
44
|
textElement.scrollHeight <= textElement.clientHeight;
|
|
@@ -33,6 +50,7 @@ function findOptimalFontSize( textElement, applyFontSize ) {
|
|
|
33
50
|
maxSize = midSize - 1;
|
|
34
51
|
}
|
|
35
52
|
}
|
|
53
|
+
range.detach();
|
|
36
54
|
|
|
37
55
|
return bestSize;
|
|
38
56
|
}
|