@wordpress/edit-site 5.28.1 → 5.28.3
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/add-new-pattern/index.js +18 -8
- package/build/components/add-new-pattern/index.js.map +1 -1
- package/build/components/editor/index.js +1 -1
- package/build/components/editor/index.js.map +1 -1
- package/build/components/global-styles/block-preview-panel.js +2 -2
- package/build/components/global-styles/block-preview-panel.js.map +1 -1
- package/build/components/global-styles/font-library-modal/collection-font-details.js +1 -1
- package/build/components/global-styles/font-library-modal/collection-font-details.js.map +1 -1
- package/build/components/global-styles/font-library-modal/context.js +1 -1
- package/build/components/global-styles/font-library-modal/context.js.map +1 -1
- package/build/components/global-styles/font-library-modal/font-collection.js +84 -7
- package/build/components/global-styles/font-library-modal/font-collection.js.map +1 -1
- package/build/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js +1 -1
- package/build/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js.map +1 -1
- package/build/components/global-styles/font-library-modal/installed-fonts.js +10 -7
- package/build/components/global-styles/font-library-modal/installed-fonts.js.map +1 -1
- package/build/components/global-styles/font-library-modal/utils/index.js +1 -1
- package/build/components/global-styles/font-library-modal/utils/index.js.map +1 -1
- package/build/components/global-styles/font-library-modal/utils/make-families-from-faces.js +14 -1
- package/build/components/global-styles/font-library-modal/utils/make-families-from-faces.js.map +1 -1
- package/build/components/global-styles/font-library-modal/utils/preview-styles.js +64 -8
- package/build/components/global-styles/font-library-modal/utils/preview-styles.js.map +1 -1
- package/build/components/global-styles/screen-revisions/revisions-buttons.js +6 -4
- package/build/components/global-styles/screen-revisions/revisions-buttons.js.map +1 -1
- package/build/components/layout/index.js +8 -3
- package/build/components/layout/index.js.map +1 -1
- package/build/components/layout/router.js +26 -5
- package/build/components/layout/router.js.map +1 -1
- package/build/components/media/index.js +3 -3
- package/build/components/media/index.js.map +1 -1
- package/build/components/page-patterns/use-patterns.js +10 -5
- package/build/components/page-patterns/use-patterns.js.map +1 -1
- package/build/components/page-templates-template-parts/index.js +1 -0
- package/build/components/page-templates-template-parts/index.js.map +1 -1
- package/build/components/sidebar/index.js +10 -3
- package/build/components/sidebar/index.js.map +1 -1
- package/build/components/sidebar-dataviews/default-views.js +1 -1
- package/build/components/sidebar-dataviews/default-views.js.map +1 -1
- package/build/components/sidebar-navigation-screen-pages/index.js +3 -1
- package/build/components/sidebar-navigation-screen-pages/index.js.map +1 -1
- package/build/hooks/commands/use-edit-mode-commands.js +8 -8
- package/build/hooks/commands/use-edit-mode-commands.js.map +1 -1
- package/build/store/private-actions.js +3 -1
- package/build/store/private-actions.js.map +1 -1
- package/build-module/components/add-new-pattern/index.js +18 -8
- package/build-module/components/add-new-pattern/index.js.map +1 -1
- package/build-module/components/editor/index.js +1 -1
- package/build-module/components/editor/index.js.map +1 -1
- package/build-module/components/global-styles/block-preview-panel.js +2 -2
- package/build-module/components/global-styles/block-preview-panel.js.map +1 -1
- package/build-module/components/global-styles/font-library-modal/collection-font-details.js +1 -1
- package/build-module/components/global-styles/font-library-modal/collection-font-details.js.map +1 -1
- package/build-module/components/global-styles/font-library-modal/context.js +1 -1
- package/build-module/components/global-styles/font-library-modal/context.js.map +1 -1
- package/build-module/components/global-styles/font-library-modal/font-collection.js +87 -10
- package/build-module/components/global-styles/font-library-modal/font-collection.js.map +1 -1
- package/build-module/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js +1 -1
- package/build-module/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js.map +1 -1
- package/build-module/components/global-styles/font-library-modal/installed-fonts.js +11 -8
- package/build-module/components/global-styles/font-library-modal/installed-fonts.js.map +1 -1
- package/build-module/components/global-styles/font-library-modal/utils/index.js +2 -2
- package/build-module/components/global-styles/font-library-modal/utils/index.js.map +1 -1
- package/build-module/components/global-styles/font-library-modal/utils/make-families-from-faces.js +13 -1
- package/build-module/components/global-styles/font-library-modal/utils/make-families-from-faces.js.map +1 -1
- package/build-module/components/global-styles/font-library-modal/utils/preview-styles.js +63 -8
- package/build-module/components/global-styles/font-library-modal/utils/preview-styles.js.map +1 -1
- package/build-module/components/global-styles/screen-revisions/revisions-buttons.js +6 -4
- package/build-module/components/global-styles/screen-revisions/revisions-buttons.js.map +1 -1
- package/build-module/components/layout/index.js +8 -3
- package/build-module/components/layout/index.js.map +1 -1
- package/build-module/components/layout/router.js +26 -5
- package/build-module/components/layout/router.js.map +1 -1
- package/build-module/components/media/index.js +3 -3
- package/build-module/components/media/index.js.map +1 -1
- package/build-module/components/page-patterns/use-patterns.js +10 -5
- package/build-module/components/page-patterns/use-patterns.js.map +1 -1
- package/build-module/components/page-templates-template-parts/index.js +1 -0
- package/build-module/components/page-templates-template-parts/index.js.map +1 -1
- package/build-module/components/sidebar/index.js +10 -3
- package/build-module/components/sidebar/index.js.map +1 -1
- package/build-module/components/sidebar-dataviews/default-views.js +2 -2
- package/build-module/components/sidebar-dataviews/default-views.js.map +1 -1
- package/build-module/components/sidebar-navigation-screen-pages/index.js +3 -1
- package/build-module/components/sidebar-navigation-screen-pages/index.js.map +1 -1
- package/build-module/hooks/commands/use-edit-mode-commands.js +8 -8
- package/build-module/hooks/commands/use-edit-mode-commands.js.map +1 -1
- package/build-module/store/private-actions.js +3 -1
- package/build-module/store/private-actions.js.map +1 -1
- package/build-style/style-rtl.css +33 -11
- package/build-style/style.css +33 -11
- package/package.json +42 -42
- package/src/components/add-new-pattern/index.js +27 -11
- package/src/components/editor/index.js +1 -0
- package/src/components/global-styles/block-preview-panel.js +2 -2
- package/src/components/global-styles/font-library-modal/collection-font-details.js +1 -1
- package/src/components/global-styles/font-library-modal/context.js +1 -1
- package/src/components/global-styles/font-library-modal/font-collection.js +118 -13
- package/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js +1 -1
- package/src/components/global-styles/font-library-modal/installed-fonts.js +25 -23
- package/src/components/global-styles/font-library-modal/style.scss +2 -5
- package/src/components/global-styles/font-library-modal/utils/index.js +2 -2
- package/src/components/global-styles/font-library-modal/utils/make-families-from-faces.js +13 -1
- package/src/components/global-styles/font-library-modal/utils/preview-styles.js +72 -15
- package/src/components/global-styles/font-library-modal/utils/test/preview-styles.spec.js +60 -5
- package/src/components/global-styles/screen-revisions/revisions-buttons.js +7 -5
- package/src/components/global-styles/screen-revisions/style.scss +11 -6
- package/src/components/layout/index.js +47 -30
- package/src/components/layout/router.js +31 -2
- package/src/components/layout/style.scss +7 -0
- package/src/components/media/index.js +7 -9
- package/src/components/page-patterns/style.scss +10 -0
- package/src/components/page-patterns/use-patterns.js +13 -5
- package/src/components/page-templates-template-parts/index.js +1 -0
- package/src/components/page-templates-template-parts/style.scss +6 -0
- package/src/components/sidebar/index.js +14 -5
- package/src/components/sidebar-dataviews/default-views.js +2 -2
- package/src/components/sidebar-edit-mode/page-panels/style.scss +0 -1
- package/src/components/sidebar-navigation-screen-pages/index.js +10 -6
- package/src/hooks/commands/use-edit-mode-commands.js +14 -14
- package/src/store/private-actions.js +4 -0
- package/build/components/global-styles/font-library-modal/fonts-grid.js +0 -57
- package/build/components/global-styles/font-library-modal/fonts-grid.js.map +0 -1
- package/build/components/sidebar-navigation-screen-pages-dataviews/index.js +0 -92
- package/build/components/sidebar-navigation-screen-pages-dataviews/index.js.map +0 -1
- package/build-module/components/global-styles/font-library-modal/fonts-grid.js +0 -50
- package/build-module/components/global-styles/font-library-modal/fonts-grid.js.map +0 -1
- package/build-module/components/sidebar-navigation-screen-pages-dataviews/index.js +0 -84
- package/build-module/components/sidebar-navigation-screen-pages-dataviews/index.js.map +0 -1
- package/src/components/global-styles/font-library-modal/fonts-grid.js +0 -59
- package/src/components/sidebar-navigation-screen-pages-dataviews/index.js +0 -103
|
@@ -25,10 +25,11 @@ import {
|
|
|
25
25
|
PATTERN_DEFAULT_CATEGORY,
|
|
26
26
|
TEMPLATE_PART_POST_TYPE,
|
|
27
27
|
} from '../../utils/constants';
|
|
28
|
-
import usePatternCategories from '../sidebar-navigation-screen-patterns/use-pattern-categories';
|
|
29
28
|
|
|
30
29
|
const { useHistory, useLocation } = unlock( routerPrivateApis );
|
|
31
|
-
const { CreatePatternModal } = unlock(
|
|
30
|
+
const { CreatePatternModal, useAddPatternCategory } = unlock(
|
|
31
|
+
editPatternsPrivateApis
|
|
32
|
+
);
|
|
32
33
|
|
|
33
34
|
export default function AddNewPattern() {
|
|
34
35
|
const history = useHistory();
|
|
@@ -43,7 +44,6 @@ export default function AddNewPattern() {
|
|
|
43
44
|
const { createSuccessNotice, createErrorNotice } =
|
|
44
45
|
useDispatch( noticesStore );
|
|
45
46
|
const patternUploadInputRef = useRef();
|
|
46
|
-
const { patternCategories } = usePatternCategories();
|
|
47
47
|
|
|
48
48
|
function handleCreatePattern( { pattern, categoryId } ) {
|
|
49
49
|
setShowPatternModal( false );
|
|
@@ -97,6 +97,7 @@ export default function AddNewPattern() {
|
|
|
97
97
|
title: __( 'Import pattern from JSON' ),
|
|
98
98
|
} );
|
|
99
99
|
|
|
100
|
+
const { categoryMap, findOrCreateTerm } = useAddPatternCategory();
|
|
100
101
|
return (
|
|
101
102
|
<>
|
|
102
103
|
<DropdownMenu
|
|
@@ -132,12 +133,23 @@ export default function AddNewPattern() {
|
|
|
132
133
|
const file = event.target.files?.[ 0 ];
|
|
133
134
|
if ( ! file ) return;
|
|
134
135
|
try {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
let currentCategoryId;
|
|
137
|
+
// When we're not handling template parts, we should
|
|
138
|
+
// add or create the proper pattern category.
|
|
139
|
+
if ( params.categoryType !== TEMPLATE_PART_POST_TYPE ) {
|
|
140
|
+
const currentCategory = categoryMap
|
|
141
|
+
.values()
|
|
142
|
+
.find(
|
|
143
|
+
( term ) => term.name === params.categoryId
|
|
144
|
+
);
|
|
145
|
+
if ( !! currentCategory ) {
|
|
146
|
+
currentCategoryId =
|
|
147
|
+
currentCategory.id ||
|
|
148
|
+
( await findOrCreateTerm(
|
|
149
|
+
currentCategory.label
|
|
150
|
+
) );
|
|
151
|
+
}
|
|
152
|
+
}
|
|
141
153
|
const pattern = await createPatternFromFile(
|
|
142
154
|
file,
|
|
143
155
|
currentCategoryId
|
|
@@ -146,8 +158,12 @@ export default function AddNewPattern() {
|
|
|
146
158
|
);
|
|
147
159
|
|
|
148
160
|
// Navigate to the All patterns category for the newly created pattern
|
|
149
|
-
// if we're not on that page already
|
|
150
|
-
|
|
161
|
+
// if we're not on that page already and if we're not in the `my-patterns`
|
|
162
|
+
// category.
|
|
163
|
+
if (
|
|
164
|
+
! currentCategoryId &&
|
|
165
|
+
params.categoryId !== 'my-patterns'
|
|
166
|
+
) {
|
|
151
167
|
history.push( {
|
|
152
168
|
path: `/patterns`,
|
|
153
169
|
categoryType: PATTERN_TYPES.theme,
|
|
@@ -28,7 +28,7 @@ const BlockPreviewPanel = ( { name, variation = '' } ) => {
|
|
|
28
28
|
}, [ name, blockExample, variation ] );
|
|
29
29
|
|
|
30
30
|
const viewportWidth = blockExample?.viewportWidth ?? null;
|
|
31
|
-
const previewHeight =
|
|
31
|
+
const previewHeight = 150;
|
|
32
32
|
|
|
33
33
|
if ( ! blockExample ) {
|
|
34
34
|
return null;
|
|
@@ -48,7 +48,7 @@ const BlockPreviewPanel = ( { name, variation = '' } ) => {
|
|
|
48
48
|
{
|
|
49
49
|
css: `
|
|
50
50
|
body{
|
|
51
|
-
min-height:${ previewHeight };
|
|
51
|
+
min-height:${ previewHeight }px;
|
|
52
52
|
display:flex;align-items:center;justify-content:center;
|
|
53
53
|
}
|
|
54
54
|
`,
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
useContext,
|
|
6
|
+
useEffect,
|
|
7
|
+
useState,
|
|
8
|
+
useMemo,
|
|
9
|
+
createInterpolateElement,
|
|
10
|
+
} from '@wordpress/element';
|
|
5
11
|
import {
|
|
6
12
|
__experimentalSpacer as Spacer,
|
|
7
13
|
__experimentalInputControl as InputControl,
|
|
8
14
|
__experimentalText as Text,
|
|
15
|
+
__experimentalHStack as HStack,
|
|
9
16
|
SelectControl,
|
|
10
17
|
Spinner,
|
|
11
18
|
Icon,
|
|
@@ -14,7 +21,7 @@ import {
|
|
|
14
21
|
Button,
|
|
15
22
|
} from '@wordpress/components';
|
|
16
23
|
import { debounce } from '@wordpress/compose';
|
|
17
|
-
import { __, _x } from '@wordpress/i18n';
|
|
24
|
+
import { sprintf, __, _x } from '@wordpress/i18n';
|
|
18
25
|
import { search, closeSmall } from '@wordpress/icons';
|
|
19
26
|
|
|
20
27
|
/**
|
|
@@ -22,7 +29,6 @@ import { search, closeSmall } from '@wordpress/icons';
|
|
|
22
29
|
*/
|
|
23
30
|
import TabPanelLayout from './tab-panel-layout';
|
|
24
31
|
import { FontLibraryContext } from './context';
|
|
25
|
-
import FontsGrid from './fonts-grid';
|
|
26
32
|
import FontCard from './font-card';
|
|
27
33
|
import filterFonts from './utils/filter-fonts';
|
|
28
34
|
import CollectionFontDetails from './collection-font-details';
|
|
@@ -48,6 +54,7 @@ function FontCollection( { slug } ) {
|
|
|
48
54
|
|
|
49
55
|
const [ selectedFont, setSelectedFont ] = useState( null );
|
|
50
56
|
const [ fontsToInstall, setFontsToInstall ] = useState( [] );
|
|
57
|
+
const [ page, setPage ] = useState( 1 );
|
|
51
58
|
const [ filters, setFilters ] = useState( {} );
|
|
52
59
|
const [ renderConfirmDialog, setRenderConfirmDialog ] = useState(
|
|
53
60
|
requiresPermission && ! getGoogleFontsPermissionFromStorage()
|
|
@@ -109,22 +116,34 @@ function FontCollection( { slug } ) {
|
|
|
109
116
|
[ collectionFonts, filters ]
|
|
110
117
|
);
|
|
111
118
|
|
|
119
|
+
// NOTE: The height of the font library modal unavailable to use for rendering font family items is roughly 417px
|
|
120
|
+
// The height of each font family item is 61px.
|
|
121
|
+
const pageSize = Math.floor( ( window.innerHeight - 417 ) / 61 );
|
|
122
|
+
const totalPages = Math.ceil( fonts.length / pageSize );
|
|
123
|
+
const itemsStart = ( page - 1 ) * pageSize;
|
|
124
|
+
const itemsLimit = page * pageSize;
|
|
125
|
+
const items = fonts.slice( itemsStart, itemsLimit );
|
|
126
|
+
|
|
112
127
|
const handleCategoryFilter = ( category ) => {
|
|
113
128
|
setFilters( { ...filters, category } );
|
|
129
|
+
setPage( 1 );
|
|
114
130
|
};
|
|
115
131
|
|
|
116
132
|
const handleUpdateSearchInput = ( value ) => {
|
|
117
133
|
setFilters( { ...filters, search: value } );
|
|
134
|
+
setPage( 1 );
|
|
118
135
|
};
|
|
119
136
|
|
|
120
137
|
const debouncedUpdateSearchInput = debounce( handleUpdateSearchInput, 300 );
|
|
121
138
|
|
|
122
139
|
const resetFilters = () => {
|
|
123
140
|
setFilters( {} );
|
|
141
|
+
setPage( 1 );
|
|
124
142
|
};
|
|
125
143
|
|
|
126
144
|
const resetSearch = () => {
|
|
127
145
|
setFilters( { ...filters, search: '' } );
|
|
146
|
+
setPage( 1 );
|
|
128
147
|
};
|
|
129
148
|
|
|
130
149
|
const handleUnselectFont = () => {
|
|
@@ -186,6 +205,24 @@ function FontCollection( { slug } ) {
|
|
|
186
205
|
resetFontsToInstall();
|
|
187
206
|
};
|
|
188
207
|
|
|
208
|
+
let footerComponent = null;
|
|
209
|
+
if ( selectedFont ) {
|
|
210
|
+
footerComponent = (
|
|
211
|
+
<InstallFooter
|
|
212
|
+
handleInstall={ handleInstall }
|
|
213
|
+
isDisabled={ fontsToInstall.length === 0 }
|
|
214
|
+
/>
|
|
215
|
+
);
|
|
216
|
+
} else if ( ! renderConfirmDialog && totalPages > 1 ) {
|
|
217
|
+
footerComponent = (
|
|
218
|
+
<PaginationFooter
|
|
219
|
+
page={ page }
|
|
220
|
+
totalPages={ totalPages }
|
|
221
|
+
setPage={ setPage }
|
|
222
|
+
/>
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
189
226
|
return (
|
|
190
227
|
<TabPanelLayout
|
|
191
228
|
title={
|
|
@@ -198,12 +235,7 @@ function FontCollection( { slug } ) {
|
|
|
198
235
|
}
|
|
199
236
|
notice={ notice }
|
|
200
237
|
handleBack={ !! selectedFont && handleUnselectFont }
|
|
201
|
-
footer={
|
|
202
|
-
<Footer
|
|
203
|
-
handleInstall={ handleInstall }
|
|
204
|
-
isDisabled={ fontsToInstall.length === 0 }
|
|
205
|
-
/>
|
|
206
|
-
}
|
|
238
|
+
footer={ footerComponent }
|
|
207
239
|
>
|
|
208
240
|
{ renderConfirmDialog && (
|
|
209
241
|
<>
|
|
@@ -275,8 +307,8 @@ function FontCollection( { slug } ) {
|
|
|
275
307
|
) }
|
|
276
308
|
|
|
277
309
|
{ ! renderConfirmDialog && ! selectedFont && (
|
|
278
|
-
<
|
|
279
|
-
{
|
|
310
|
+
<div className="font-library-modal__fonts-grid__main">
|
|
311
|
+
{ items.map( ( font ) => (
|
|
280
312
|
<FontCard
|
|
281
313
|
key={ font.font_family_settings.slug }
|
|
282
314
|
font={ font.font_family_settings }
|
|
@@ -285,13 +317,86 @@ function FontCollection( { slug } ) {
|
|
|
285
317
|
} }
|
|
286
318
|
/>
|
|
287
319
|
) ) }
|
|
288
|
-
</
|
|
320
|
+
</div>
|
|
289
321
|
) }
|
|
290
322
|
</TabPanelLayout>
|
|
291
323
|
);
|
|
292
324
|
}
|
|
293
325
|
|
|
294
|
-
function
|
|
326
|
+
function PaginationFooter( { page, totalPages, setPage } ) {
|
|
327
|
+
return (
|
|
328
|
+
<Flex justify="center">
|
|
329
|
+
<Button
|
|
330
|
+
label={ __( 'First page' ) }
|
|
331
|
+
size="compact"
|
|
332
|
+
onClick={ () => setPage( 1 ) }
|
|
333
|
+
disabled={ page === 1 }
|
|
334
|
+
__experimentalIsFocusable
|
|
335
|
+
>
|
|
336
|
+
<span>«</span>
|
|
337
|
+
</Button>
|
|
338
|
+
<Button
|
|
339
|
+
label={ __( 'Previous page' ) }
|
|
340
|
+
size="compact"
|
|
341
|
+
onClick={ () => setPage( page - 1 ) }
|
|
342
|
+
disabled={ page === 1 }
|
|
343
|
+
__experimentalIsFocusable
|
|
344
|
+
>
|
|
345
|
+
<span>‹</span>
|
|
346
|
+
</Button>
|
|
347
|
+
<HStack justify="flex-start" expanded={ false } spacing={ 2 }>
|
|
348
|
+
{ createInterpolateElement(
|
|
349
|
+
sprintf(
|
|
350
|
+
// translators: %s: Total number of pages.
|
|
351
|
+
_x( 'Page <CurrenPageControl /> of %s', 'paging' ),
|
|
352
|
+
totalPages
|
|
353
|
+
),
|
|
354
|
+
{
|
|
355
|
+
CurrenPageControl: (
|
|
356
|
+
<SelectControl
|
|
357
|
+
aria-label={ __( 'Current page' ) }
|
|
358
|
+
value={ page }
|
|
359
|
+
options={ [ ...Array( totalPages ) ].map(
|
|
360
|
+
( e, i ) => {
|
|
361
|
+
return {
|
|
362
|
+
label: i + 1,
|
|
363
|
+
value: i + 1,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
) }
|
|
367
|
+
onChange={ ( newPage ) =>
|
|
368
|
+
setPage( parseInt( newPage ) )
|
|
369
|
+
}
|
|
370
|
+
size={ 'compact' }
|
|
371
|
+
__nextHasNoMarginBottom
|
|
372
|
+
/>
|
|
373
|
+
),
|
|
374
|
+
}
|
|
375
|
+
) }
|
|
376
|
+
</HStack>
|
|
377
|
+
<Button
|
|
378
|
+
label={ __( 'Next page' ) }
|
|
379
|
+
size="compact"
|
|
380
|
+
onClick={ () => setPage( page + 1 ) }
|
|
381
|
+
disabled={ page === totalPages }
|
|
382
|
+
__experimentalIsFocusable
|
|
383
|
+
>
|
|
384
|
+
<span>›</span>
|
|
385
|
+
</Button>
|
|
386
|
+
<Button
|
|
387
|
+
label={ __( 'Last page' ) }
|
|
388
|
+
size="compact"
|
|
389
|
+
onClick={ () => setPage( totalPages ) }
|
|
390
|
+
disabled={ page === totalPages }
|
|
391
|
+
__experimentalIsFocusable
|
|
392
|
+
>
|
|
393
|
+
<span>»</span>
|
|
394
|
+
</Button>
|
|
395
|
+
</Flex>
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
function InstallFooter( { handleInstall, isDisabled } ) {
|
|
295
400
|
const { isInstalling } = useContext( FontLibraryContext );
|
|
296
401
|
|
|
297
402
|
return (
|
|
@@ -24,7 +24,7 @@ function GoogleFontsConfirmDialog() {
|
|
|
24
24
|
<div className="font-library__google-fonts-confirm">
|
|
25
25
|
<Card>
|
|
26
26
|
<CardBody>
|
|
27
|
-
<Text as="h3">Connect to Google Fonts</Text>
|
|
27
|
+
<Text as="h3">{ __( 'Connect to Google Fonts' ) }</Text>
|
|
28
28
|
<Spacer margin={ 6 } />
|
|
29
29
|
<Text as="p">
|
|
30
30
|
{ __(
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
privateApis as componentsPrivateApis,
|
|
8
8
|
__experimentalHStack as HStack,
|
|
9
9
|
__experimentalSpacer as Spacer,
|
|
10
|
+
__experimentalText as Text,
|
|
10
11
|
Button,
|
|
11
12
|
Spinner,
|
|
12
13
|
FlexItem,
|
|
@@ -17,7 +18,6 @@ import {
|
|
|
17
18
|
*/
|
|
18
19
|
import TabPanelLayout from './tab-panel-layout';
|
|
19
20
|
import { FontLibraryContext } from './context';
|
|
20
|
-
import FontsGrid from './fonts-grid';
|
|
21
21
|
import LibraryFontDetails from './library-font-details';
|
|
22
22
|
import LibraryFontCard from './library-font-card';
|
|
23
23
|
import ConfirmDeleteDialog from './confirm-delete-dialog';
|
|
@@ -123,36 +123,38 @@ function InstalledFonts() {
|
|
|
123
123
|
) }
|
|
124
124
|
{ baseCustomFonts.length > 0 && (
|
|
125
125
|
<>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
) ) }
|
|
136
|
-
</FontsGrid>
|
|
126
|
+
{ baseCustomFonts.map( ( font ) => (
|
|
127
|
+
<LibraryFontCard
|
|
128
|
+
font={ font }
|
|
129
|
+
key={ font.slug }
|
|
130
|
+
onClick={ () => {
|
|
131
|
+
handleSelectFont( font );
|
|
132
|
+
} }
|
|
133
|
+
/>
|
|
134
|
+
) ) }
|
|
137
135
|
<Spacer margin={ 8 } />
|
|
138
136
|
</>
|
|
139
137
|
) }
|
|
140
138
|
|
|
141
139
|
{ baseThemeFonts.length > 0 && (
|
|
142
140
|
<>
|
|
143
|
-
<
|
|
144
|
-
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
141
|
+
<Text className="font-library-modal__subtitle">
|
|
142
|
+
{ __( 'Theme Fonts' ) }
|
|
143
|
+
</Text>
|
|
144
|
+
|
|
145
|
+
<Spacer margin={ 2 } />
|
|
146
|
+
{ baseThemeFonts.map( ( font ) => (
|
|
147
|
+
<LibraryFontCard
|
|
148
|
+
font={ font }
|
|
149
|
+
key={ font.slug }
|
|
150
|
+
onClick={ () => {
|
|
151
|
+
handleSelectFont( font );
|
|
152
|
+
} }
|
|
153
|
+
/>
|
|
154
|
+
) ) }
|
|
154
155
|
</>
|
|
155
156
|
) }
|
|
157
|
+
<Spacer margin={ 16 } />
|
|
156
158
|
</>
|
|
157
159
|
) }
|
|
158
160
|
|
|
@@ -36,11 +36,8 @@
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
.font-library-
|
|
40
|
-
|
|
41
|
-
display: flex;
|
|
42
|
-
flex-direction: column;
|
|
43
|
-
}
|
|
39
|
+
.font-library-modal__tabpanel-layout .components-base-control__field {
|
|
40
|
+
margin-bottom: 0;
|
|
44
41
|
}
|
|
45
42
|
|
|
46
43
|
.font-library-modal__font-card {
|
|
@@ -9,7 +9,7 @@ import { privateApis as componentsPrivateApis } from '@wordpress/components';
|
|
|
9
9
|
import { FONT_WEIGHTS, FONT_STYLES } from './constants';
|
|
10
10
|
import { unlock } from '../../../../lock-unlock';
|
|
11
11
|
import { fetchInstallFontFace } from '../resolvers';
|
|
12
|
-
import {
|
|
12
|
+
import { formatFontFaceName } from './preview-styles';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Browser dependencies
|
|
@@ -99,7 +99,7 @@ export async function loadFontFaceInBrowser( fontFace, source, addTo = 'all' ) {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
const newFont = new window.FontFace(
|
|
102
|
-
|
|
102
|
+
formatFontFaceName( fontFace.fontFamily ),
|
|
103
103
|
dataSource,
|
|
104
104
|
{
|
|
105
105
|
style: fontFace.fontStyle,
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { privateApis as componentsPrivateApis } from '@wordpress/components';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { unlock } from '../../../../lock-unlock';
|
|
10
|
+
|
|
11
|
+
const { kebabCase } = unlock( componentsPrivateApis );
|
|
12
|
+
|
|
1
13
|
export default function makeFamiliesFromFaces( fontFaces ) {
|
|
2
14
|
const fontFamiliesObject = fontFaces.reduce( ( acc, item ) => {
|
|
3
15
|
if ( ! acc[ item.fontFamily ] ) {
|
|
4
16
|
acc[ item.fontFamily ] = {
|
|
5
17
|
name: item.fontFamily,
|
|
6
18
|
fontFamily: item.fontFamily,
|
|
7
|
-
slug: item.fontFamily.
|
|
19
|
+
slug: kebabCase( item.fontFamily.toLowerCase() ),
|
|
8
20
|
fontFace: [],
|
|
9
21
|
};
|
|
10
22
|
}
|
|
@@ -30,22 +30,79 @@ function extractFontWeights( fontFaces ) {
|
|
|
30
30
|
return result;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/*
|
|
34
|
+
* Format the font family to use in the CSS font-family property of a CSS rule.
|
|
35
|
+
*
|
|
36
|
+
* The input can be a string with the font family name or a string with multiple font family names separated by commas.
|
|
37
|
+
* It follows the recommendations from the CSS Fonts Module Level 4.
|
|
38
|
+
* https://www.w3.org/TR/css-fonts-4/#font-family-prop
|
|
39
|
+
*
|
|
40
|
+
* @param {string} input - The font family.
|
|
41
|
+
* @return {string} The formatted font family.
|
|
42
|
+
*
|
|
43
|
+
* Example:
|
|
44
|
+
* formatFontFamily( "Open Sans, Font+Name, sans-serif" ) => '"Open Sans", "Font+Name", sans-serif'
|
|
45
|
+
* formatFontFamily( "'Open Sans', generic(kai), sans-serif" ) => '"Open Sans", sans-serif'
|
|
46
|
+
* formatFontFamily( "DotGothic16, Slabo 27px, serif" ) => '"DotGothic16","Slabo 27px",serif'
|
|
47
|
+
* formatFontFamily( "Mine's, Moe's Typography" ) => `"mine's","Moe's Typography"`
|
|
48
|
+
*/
|
|
33
49
|
export function formatFontFamily( input ) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
// Matches strings that are not exclusively alphabetic characters or hyphens, and do not exactly follow the pattern generic(alphabetic characters or hyphens).
|
|
51
|
+
const regex = /^(?!generic\([ a-zA-Z\-]+\)$)(?!^[a-zA-Z\-]+$).+/;
|
|
52
|
+
const output = input.trim();
|
|
53
|
+
|
|
54
|
+
const formatItem = ( item ) => {
|
|
55
|
+
item = item.trim();
|
|
56
|
+
if ( item.match( regex ) ) {
|
|
57
|
+
// removes leading and trailing quotes.
|
|
58
|
+
item = item.replace( /^["']|["']$/g, '' );
|
|
59
|
+
return `"${ item }"`;
|
|
60
|
+
}
|
|
61
|
+
return item;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if ( output.includes( ',' ) ) {
|
|
65
|
+
return output
|
|
66
|
+
.split( ',' )
|
|
67
|
+
.map( formatItem )
|
|
68
|
+
.filter( ( item ) => item !== '' )
|
|
69
|
+
.join( ', ' );
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return formatItem( output );
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/*
|
|
76
|
+
* Format the font face name to use in the font-family property of a font face.
|
|
77
|
+
*
|
|
78
|
+
* The input can be a string with the font face name or a string with multiple font face names separated by commas.
|
|
79
|
+
* It removes the leading and trailing quotes from the font face name.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} input - The font face name.
|
|
82
|
+
* @return {string} The formatted font face name.
|
|
83
|
+
*
|
|
84
|
+
* Example:
|
|
85
|
+
* formatFontFaceName("Open Sans") => "Open Sans"
|
|
86
|
+
* formatFontFaceName("'Open Sans', sans-serif") => "Open Sans"
|
|
87
|
+
* formatFontFaceName(", 'Open Sans', 'Helvetica Neue', sans-serif") => "Open Sans"
|
|
88
|
+
*/
|
|
89
|
+
export function formatFontFaceName( input ) {
|
|
90
|
+
let output = input.trim();
|
|
91
|
+
if ( output.includes( ',' ) ) {
|
|
92
|
+
output = output
|
|
93
|
+
.split( ',' )
|
|
94
|
+
// finds the first item that is not an empty string.
|
|
95
|
+
.find( ( item ) => item.trim() !== '' )
|
|
96
|
+
.trim();
|
|
97
|
+
}
|
|
98
|
+
// removes leading and trailing quotes.
|
|
99
|
+
output = output.replace( /^["']|["']$/g, '' );
|
|
100
|
+
|
|
101
|
+
// Firefox needs the font name to be wrapped in double quotes meanwhile other browsers don't.
|
|
102
|
+
if ( window.navigator.userAgent.toLowerCase().includes( 'firefox' ) ) {
|
|
103
|
+
output = `"${ output }"`;
|
|
104
|
+
}
|
|
105
|
+
return output;
|
|
49
106
|
}
|
|
50
107
|
|
|
51
108
|
export function getFamilyPreviewStyle( family ) {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
getFamilyPreviewStyle,
|
|
6
|
+
formatFontFamily,
|
|
7
|
+
formatFontFaceName,
|
|
8
|
+
} from '../preview-styles';
|
|
5
9
|
|
|
6
10
|
describe( 'getFamilyPreviewStyle', () => {
|
|
7
11
|
it( 'should return default fontStyle and fontWeight if fontFace is not provided', () => {
|
|
@@ -139,7 +143,7 @@ describe( 'formatFontFamily', () => {
|
|
|
139
143
|
"Seravek, 'Gill Sans Nova', Ubuntu, Calibri, 'DejaVu Sans', source-sans-pro, sans-serif"
|
|
140
144
|
)
|
|
141
145
|
).toBe(
|
|
142
|
-
|
|
146
|
+
'Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans", source-sans-pro, sans-serif'
|
|
143
147
|
);
|
|
144
148
|
} );
|
|
145
149
|
|
|
@@ -153,9 +157,60 @@ describe( 'formatFontFamily', () => {
|
|
|
153
157
|
);
|
|
154
158
|
} );
|
|
155
159
|
|
|
156
|
-
it( 'should wrap
|
|
157
|
-
expect(
|
|
158
|
-
|
|
160
|
+
it( 'should wrap names with special characters in quotes', () => {
|
|
161
|
+
expect(
|
|
162
|
+
formatFontFamily(
|
|
163
|
+
'Font+Name, Font*Name, _Font_Name_, generic(kai), sans-serif'
|
|
164
|
+
)
|
|
165
|
+
).toBe(
|
|
166
|
+
'"Font+Name", "Font*Name", "_Font_Name_", generic(kai), sans-serif'
|
|
167
|
+
);
|
|
168
|
+
} );
|
|
169
|
+
|
|
170
|
+
it( 'should fix empty wrong formatted font family', () => {
|
|
171
|
+
expect( formatFontFamily( ', Abril Fatface,Times,serif' ) ).toBe(
|
|
172
|
+
'"Abril Fatface", Times, serif'
|
|
173
|
+
);
|
|
174
|
+
} );
|
|
175
|
+
|
|
176
|
+
it( 'should not add quotes to generic names', () => {
|
|
177
|
+
expect(
|
|
178
|
+
formatFontFamily(
|
|
179
|
+
'Paren(thesis)Font, generic(kai), generic(fasongsong), generic( abc ), Helvetica Neue'
|
|
180
|
+
)
|
|
181
|
+
).toBe(
|
|
182
|
+
'"Paren(thesis)Font", generic(kai), generic(fasongsong), generic( abc ), "Helvetica Neue"'
|
|
159
183
|
);
|
|
160
184
|
} );
|
|
161
185
|
} );
|
|
186
|
+
|
|
187
|
+
describe( 'formatFontFaceName', () => {
|
|
188
|
+
it( 'should remove leading and trailing quotes', () => {
|
|
189
|
+
expect( formatFontFaceName( '"Open Sans"' ) ).toBe( 'Open Sans' );
|
|
190
|
+
} );
|
|
191
|
+
|
|
192
|
+
it( 'should remove leading and trailing quotes from multiple font face names', () => {
|
|
193
|
+
expect(
|
|
194
|
+
formatFontFaceName( "'Open Sans', 'Helvetica Neue', sans-serif" )
|
|
195
|
+
).toBe( 'Open Sans' );
|
|
196
|
+
} );
|
|
197
|
+
|
|
198
|
+
it( 'should remove leading and trailing quotes even from names with spaces and special characters', () => {
|
|
199
|
+
expect( formatFontFaceName( "'Font+Name 24', sans-serif" ) ).toBe(
|
|
200
|
+
'Font+Name 24'
|
|
201
|
+
);
|
|
202
|
+
} );
|
|
203
|
+
|
|
204
|
+
it( 'should ouput the font face name with quotes on Firefox', () => {
|
|
205
|
+
const mockUserAgent =
|
|
206
|
+
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0';
|
|
207
|
+
|
|
208
|
+
// Mock the userAgent for this test
|
|
209
|
+
Object.defineProperty( window.navigator, 'userAgent', {
|
|
210
|
+
value: mockUserAgent,
|
|
211
|
+
configurable: true,
|
|
212
|
+
} );
|
|
213
|
+
|
|
214
|
+
expect( formatFontFaceName( 'Open Sans' ) ).toBe( '"Open Sans"' );
|
|
215
|
+
} );
|
|
216
|
+
} );
|