@wordpress/edit-site 5.28.2 → 5.28.4

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.
Files changed (162) hide show
  1. package/build/components/add-new-pattern/index.js +18 -8
  2. package/build/components/add-new-pattern/index.js.map +1 -1
  3. package/build/components/editor/index.js +1 -1
  4. package/build/components/editor/index.js.map +1 -1
  5. package/build/components/global-styles/block-preview-panel.js +2 -2
  6. package/build/components/global-styles/block-preview-panel.js.map +1 -1
  7. package/build/components/global-styles/font-library-modal/collection-font-variant.js +2 -2
  8. package/build/components/global-styles/font-library-modal/collection-font-variant.js.map +1 -1
  9. package/build/components/global-styles/font-library-modal/font-card.js +10 -15
  10. package/build/components/global-styles/font-library-modal/font-card.js.map +1 -1
  11. package/build/components/global-styles/font-library-modal/font-collection.js +167 -37
  12. package/build/components/global-styles/font-library-modal/font-collection.js.map +1 -1
  13. package/build/components/global-styles/font-library-modal/font-demo.js +29 -8
  14. package/build/components/global-styles/font-library-modal/font-demo.js.map +1 -1
  15. package/build/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js +1 -1
  16. package/build/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js.map +1 -1
  17. package/build/components/global-styles/font-library-modal/installed-fonts.js +149 -83
  18. package/build/components/global-styles/font-library-modal/installed-fonts.js.map +1 -1
  19. package/build/components/global-styles/font-library-modal/library-font-variant.js +2 -2
  20. package/build/components/global-styles/font-library-modal/library-font-variant.js.map +1 -1
  21. package/build/components/global-styles/font-library-modal/upload-fonts.js +6 -4
  22. package/build/components/global-styles/font-library-modal/upload-fonts.js.map +1 -1
  23. package/build/components/global-styles/screen-revisions/index.js +2 -2
  24. package/build/components/global-styles/screen-revisions/index.js.map +1 -1
  25. package/build/components/global-styles/ui.js +27 -2
  26. package/build/components/global-styles/ui.js.map +1 -1
  27. package/build/components/header-edit-mode/index.js +1 -1
  28. package/build/components/header-edit-mode/index.js.map +1 -1
  29. package/build/components/layout/index.js +8 -3
  30. package/build/components/layout/index.js.map +1 -1
  31. package/build/components/layout/router.js +26 -5
  32. package/build/components/layout/router.js.map +1 -1
  33. package/build/components/page-patterns/index.js +14 -14
  34. package/build/components/page-patterns/index.js.map +1 -1
  35. package/build/components/page-patterns/use-patterns.js +10 -5
  36. package/build/components/page-patterns/use-patterns.js.map +1 -1
  37. package/build/components/page-templates-template-parts/index.js +1 -0
  38. package/build/components/page-templates-template-parts/index.js.map +1 -1
  39. package/build/components/sidebar/index.js +6 -3
  40. package/build/components/sidebar/index.js.map +1 -1
  41. package/build/components/sidebar-dataviews/default-views.js +2 -0
  42. package/build/components/sidebar-dataviews/default-views.js.map +1 -1
  43. package/build/components/sidebar-navigation-screen-pages/index.js +3 -1
  44. package/build/components/sidebar-navigation-screen-pages/index.js.map +1 -1
  45. package/build/components/sidebar-navigation-screen-templates-browse/content.js +2 -2
  46. package/build/components/sidebar-navigation-screen-templates-browse/content.js.map +1 -1
  47. package/build/components/sidebar-navigation-screen-templates-browse/index.js +7 -5
  48. package/build/components/sidebar-navigation-screen-templates-browse/index.js.map +1 -1
  49. package/build/components/style-book/index.js +2 -0
  50. package/build/components/style-book/index.js.map +1 -1
  51. package/build/store/private-actions.js +3 -1
  52. package/build/store/private-actions.js.map +1 -1
  53. package/build-module/components/add-new-pattern/index.js +18 -8
  54. package/build-module/components/add-new-pattern/index.js.map +1 -1
  55. package/build-module/components/editor/index.js +1 -1
  56. package/build-module/components/editor/index.js.map +1 -1
  57. package/build-module/components/global-styles/block-preview-panel.js +2 -2
  58. package/build-module/components/global-styles/block-preview-panel.js.map +1 -1
  59. package/build-module/components/global-styles/font-library-modal/collection-font-variant.js +4 -4
  60. package/build-module/components/global-styles/font-library-modal/collection-font-variant.js.map +1 -1
  61. package/build-module/components/global-styles/font-library-modal/font-card.js +11 -16
  62. package/build-module/components/global-styles/font-library-modal/font-card.js.map +1 -1
  63. package/build-module/components/global-styles/font-library-modal/font-collection.js +172 -42
  64. package/build-module/components/global-styles/font-library-modal/font-collection.js.map +1 -1
  65. package/build-module/components/global-styles/font-library-modal/font-demo.js +30 -9
  66. package/build-module/components/global-styles/font-library-modal/font-demo.js.map +1 -1
  67. package/build-module/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js +1 -1
  68. package/build-module/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js.map +1 -1
  69. package/build-module/components/global-styles/font-library-modal/installed-fonts.js +149 -83
  70. package/build-module/components/global-styles/font-library-modal/installed-fonts.js.map +1 -1
  71. package/build-module/components/global-styles/font-library-modal/library-font-variant.js +4 -4
  72. package/build-module/components/global-styles/font-library-modal/library-font-variant.js.map +1 -1
  73. package/build-module/components/global-styles/font-library-modal/upload-fonts.js +7 -5
  74. package/build-module/components/global-styles/font-library-modal/upload-fonts.js.map +1 -1
  75. package/build-module/components/global-styles/screen-revisions/index.js +2 -2
  76. package/build-module/components/global-styles/screen-revisions/index.js.map +1 -1
  77. package/build-module/components/global-styles/ui.js +27 -2
  78. package/build-module/components/global-styles/ui.js.map +1 -1
  79. package/build-module/components/header-edit-mode/index.js +1 -1
  80. package/build-module/components/header-edit-mode/index.js.map +1 -1
  81. package/build-module/components/layout/index.js +8 -3
  82. package/build-module/components/layout/index.js.map +1 -1
  83. package/build-module/components/layout/router.js +26 -5
  84. package/build-module/components/layout/router.js.map +1 -1
  85. package/build-module/components/page-patterns/index.js +14 -14
  86. package/build-module/components/page-patterns/index.js.map +1 -1
  87. package/build-module/components/page-patterns/use-patterns.js +10 -5
  88. package/build-module/components/page-patterns/use-patterns.js.map +1 -1
  89. package/build-module/components/page-templates-template-parts/index.js +1 -0
  90. package/build-module/components/page-templates-template-parts/index.js.map +1 -1
  91. package/build-module/components/sidebar/index.js +6 -3
  92. package/build-module/components/sidebar/index.js.map +1 -1
  93. package/build-module/components/sidebar-dataviews/default-views.js +3 -1
  94. package/build-module/components/sidebar-dataviews/default-views.js.map +1 -1
  95. package/build-module/components/sidebar-navigation-screen-pages/index.js +3 -1
  96. package/build-module/components/sidebar-navigation-screen-pages/index.js.map +1 -1
  97. package/build-module/components/sidebar-navigation-screen-templates-browse/content.js +2 -2
  98. package/build-module/components/sidebar-navigation-screen-templates-browse/content.js.map +1 -1
  99. package/build-module/components/sidebar-navigation-screen-templates-browse/index.js +7 -5
  100. package/build-module/components/sidebar-navigation-screen-templates-browse/index.js.map +1 -1
  101. package/build-module/components/style-book/index.js +2 -0
  102. package/build-module/components/style-book/index.js.map +1 -1
  103. package/build-module/store/private-actions.js +3 -1
  104. package/build-module/store/private-actions.js.map +1 -1
  105. package/build-style/style-rtl.css +52 -25
  106. package/build-style/style.css +52 -25
  107. package/package.json +18 -18
  108. package/src/components/add-new-pattern/index.js +27 -11
  109. package/src/components/editor/index.js +1 -0
  110. package/src/components/global-styles/block-preview-panel.js +2 -2
  111. package/src/components/global-styles/font-library-modal/collection-font-variant.js +4 -4
  112. package/src/components/global-styles/font-library-modal/font-card.js +11 -26
  113. package/src/components/global-styles/font-library-modal/font-collection.js +328 -129
  114. package/src/components/global-styles/font-library-modal/font-demo.js +38 -4
  115. package/src/components/global-styles/font-library-modal/google-fonts-confirm-dialog.js +1 -1
  116. package/src/components/global-styles/font-library-modal/installed-fonts.js +246 -132
  117. package/src/components/global-styles/font-library-modal/library-font-variant.js +4 -4
  118. package/src/components/global-styles/font-library-modal/style.scss +17 -13
  119. package/src/components/global-styles/font-library-modal/upload-fonts.js +13 -5
  120. package/src/components/global-styles/screen-revisions/index.js +5 -2
  121. package/src/components/global-styles/ui.js +26 -2
  122. package/src/components/header-edit-mode/index.js +3 -1
  123. package/src/components/layout/index.js +47 -30
  124. package/src/components/layout/router.js +31 -2
  125. package/src/components/layout/style.scss +7 -0
  126. package/src/components/page-patterns/index.js +20 -20
  127. package/src/components/page-patterns/style.scss +10 -0
  128. package/src/components/page-patterns/use-patterns.js +13 -5
  129. package/src/components/page-templates-template-parts/index.js +1 -0
  130. package/src/components/page-templates-template-parts/style.scss +6 -0
  131. package/src/components/sidebar/index.js +9 -4
  132. package/src/components/sidebar-dataviews/default-views.js +3 -1
  133. package/src/components/sidebar-navigation-screen-pages/index.js +10 -6
  134. package/src/components/sidebar-navigation-screen-templates-browse/content.js +2 -2
  135. package/src/components/sidebar-navigation-screen-templates-browse/index.js +5 -3
  136. package/src/components/style-book/index.js +5 -1
  137. package/src/store/private-actions.js +4 -0
  138. package/build/components/global-styles/font-library-modal/collection-font-details.js +0 -50
  139. package/build/components/global-styles/font-library-modal/collection-font-details.js.map +0 -1
  140. package/build/components/global-styles/font-library-modal/confirm-delete-dialog.js +0 -30
  141. package/build/components/global-styles/font-library-modal/confirm-delete-dialog.js.map +0 -1
  142. package/build/components/global-styles/font-library-modal/fonts-grid.js +0 -57
  143. package/build/components/global-styles/font-library-modal/fonts-grid.js.map +0 -1
  144. package/build/components/global-styles/font-library-modal/library-font-card.js +0 -39
  145. package/build/components/global-styles/font-library-modal/library-font-card.js.map +0 -1
  146. package/build/components/global-styles/font-library-modal/tab-panel-layout.js +0 -67
  147. package/build/components/global-styles/font-library-modal/tab-panel-layout.js.map +0 -1
  148. package/build-module/components/global-styles/font-library-modal/collection-font-details.js +0 -42
  149. package/build-module/components/global-styles/font-library-modal/collection-font-details.js.map +0 -1
  150. package/build-module/components/global-styles/font-library-modal/confirm-delete-dialog.js +0 -23
  151. package/build-module/components/global-styles/font-library-modal/confirm-delete-dialog.js.map +0 -1
  152. package/build-module/components/global-styles/font-library-modal/fonts-grid.js +0 -50
  153. package/build-module/components/global-styles/font-library-modal/fonts-grid.js.map +0 -1
  154. package/build-module/components/global-styles/font-library-modal/library-font-card.js +0 -31
  155. package/build-module/components/global-styles/font-library-modal/library-font-card.js.map +0 -1
  156. package/build-module/components/global-styles/font-library-modal/tab-panel-layout.js +0 -60
  157. package/build-module/components/global-styles/font-library-modal/tab-panel-layout.js.map +0 -1
  158. package/src/components/global-styles/font-library-modal/collection-font-details.js +0 -56
  159. package/src/components/global-styles/font-library-modal/confirm-delete-dialog.js +0 -33
  160. package/src/components/global-styles/font-library-modal/fonts-grid.js +0 -59
  161. package/src/components/global-styles/font-library-modal/library-font-card.js +0 -34
  162. package/src/components/global-styles/font-library-modal/tab-panel-layout.js +0 -85
@@ -1,59 +1,87 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useContext, useEffect, useState, useMemo } from '@wordpress/element';
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,
16
+ __experimentalVStack as VStack,
17
+ __experimentalNavigatorProvider as NavigatorProvider,
18
+ __experimentalNavigatorScreen as NavigatorScreen,
19
+ __experimentalNavigatorToParentButton as NavigatorToParentButton,
20
+ __experimentalHeading as Heading,
21
+ Notice,
9
22
  SelectControl,
10
23
  Spinner,
11
24
  Icon,
12
25
  FlexItem,
13
26
  Flex,
14
27
  Button,
28
+ DropdownMenu,
15
29
  } from '@wordpress/components';
16
30
  import { debounce } from '@wordpress/compose';
17
- import { __, _x } from '@wordpress/i18n';
18
- import { search, closeSmall } from '@wordpress/icons';
31
+ import { sprintf, __, _x } from '@wordpress/i18n';
32
+ import {
33
+ search,
34
+ closeSmall,
35
+ moreVertical,
36
+ chevronLeft,
37
+ } from '@wordpress/icons';
19
38
 
20
39
  /**
21
40
  * Internal dependencies
22
41
  */
23
- import TabPanelLayout from './tab-panel-layout';
24
42
  import { FontLibraryContext } from './context';
25
- import FontsGrid from './fonts-grid';
26
43
  import FontCard from './font-card';
27
44
  import filterFonts from './utils/filter-fonts';
28
- import CollectionFontDetails from './collection-font-details';
29
45
  import { toggleFont } from './utils/toggleFont';
30
- import { getFontsOutline } from './utils/fonts-outline';
46
+ import {
47
+ getFontsOutline,
48
+ isFontFontFaceInOutline,
49
+ } from './utils/fonts-outline';
31
50
  import GoogleFontsConfirmDialog from './google-fonts-confirm-dialog';
32
51
  import { downloadFontFaceAssets } from './utils';
52
+ import { sortFontFaces } from './utils/sort-font-faces';
53
+ import CollectionFontVariant from './collection-font-variant';
33
54
 
34
55
  const DEFAULT_CATEGORY = {
35
56
  slug: 'all',
36
57
  name: _x( 'All', 'font categories' ),
37
58
  };
59
+
60
+ const LOCAL_STORAGE_ITEM = 'wp-font-library-google-fonts-permission';
61
+ const MIN_WINDOW_HEIGHT = 500;
62
+
38
63
  function FontCollection( { slug } ) {
39
64
  const requiresPermission = slug === 'google-fonts';
40
65
 
41
66
  const getGoogleFontsPermissionFromStorage = () => {
42
- return (
43
- window.localStorage.getItem(
44
- 'wp-font-library-google-fonts-permission'
45
- ) === 'true'
46
- );
67
+ return window.localStorage.getItem( LOCAL_STORAGE_ITEM ) === 'true';
47
68
  };
48
69
 
49
70
  const [ selectedFont, setSelectedFont ] = useState( null );
50
71
  const [ fontsToInstall, setFontsToInstall ] = useState( [] );
72
+ const [ page, setPage ] = useState( 1 );
51
73
  const [ filters, setFilters ] = useState( {} );
52
74
  const [ renderConfirmDialog, setRenderConfirmDialog ] = useState(
53
75
  requiresPermission && ! getGoogleFontsPermissionFromStorage()
54
76
  );
55
- const { collections, getFontCollection, installFont, notice, setNotice } =
56
- useContext( FontLibraryContext );
77
+ const {
78
+ collections,
79
+ getFontCollection,
80
+ installFont,
81
+ isInstalling,
82
+ notice,
83
+ setNotice,
84
+ } = useContext( FontLibraryContext );
57
85
  const selectedCollection = collections.find(
58
86
  ( collection ) => collection.slug === slug
59
87
  );
@@ -69,6 +97,11 @@ function FontCollection( { slug } ) {
69
97
  return () => window.removeEventListener( 'storage', handleStorage );
70
98
  }, [ slug, requiresPermission ] );
71
99
 
100
+ const revokeAccess = () => {
101
+ window.localStorage.setItem( LOCAL_STORAGE_ITEM, 'false' );
102
+ window.dispatchEvent( new Event( 'storage' ) );
103
+ };
104
+
72
105
  useEffect( () => {
73
106
  const fetchFontCollection = async () => {
74
107
  try {
@@ -109,26 +142,35 @@ function FontCollection( { slug } ) {
109
142
  [ collectionFonts, filters ]
110
143
  );
111
144
 
145
+ // NOTE: The height of the font library modal unavailable to use for rendering font family items is roughly 417px
146
+ // The height of each font family item is 61px.
147
+ const windowHeight = Math.max( window.innerHeight, MIN_WINDOW_HEIGHT );
148
+ const pageSize = Math.floor( ( windowHeight - 417 ) / 61 );
149
+ const totalPages = Math.ceil( fonts.length / pageSize );
150
+ const itemsStart = ( page - 1 ) * pageSize;
151
+ const itemsLimit = page * pageSize;
152
+ const items = fonts.slice( itemsStart, itemsLimit );
153
+
112
154
  const handleCategoryFilter = ( category ) => {
113
155
  setFilters( { ...filters, category } );
156
+ setPage( 1 );
114
157
  };
115
158
 
116
159
  const handleUpdateSearchInput = ( value ) => {
117
160
  setFilters( { ...filters, search: value } );
161
+ setPage( 1 );
118
162
  };
119
163
 
120
164
  const debouncedUpdateSearchInput = debounce( handleUpdateSearchInput, 300 );
121
165
 
122
166
  const resetFilters = () => {
123
167
  setFilters( {} );
168
+ setPage( 1 );
124
169
  };
125
170
 
126
171
  const resetSearch = () => {
127
172
  setFilters( { ...filters, search: '' } );
128
- };
129
-
130
- const handleUnselectFont = () => {
131
- setSelectedFont( null );
173
+ setPage( 1 );
132
174
  };
133
175
 
134
176
  const handleToggleVariant = ( font, face ) => {
@@ -186,126 +228,283 @@ function FontCollection( { slug } ) {
186
228
  resetFontsToInstall();
187
229
  };
188
230
 
189
- return (
190
- <TabPanelLayout
191
- title={
192
- ! selectedFont ? selectedCollection.name : selectedFont.name
193
- }
194
- description={
195
- ! selectedFont
196
- ? selectedCollection.description
197
- : __( 'Select font variants to install.' )
198
- }
199
- notice={ notice }
200
- handleBack={ !! selectedFont && handleUnselectFont }
201
- footer={
202
- <Footer
203
- handleInstall={ handleInstall }
204
- isDisabled={ fontsToInstall.length === 0 }
205
- />
206
- }
207
- >
208
- { renderConfirmDialog && (
209
- <>
210
- <Spacer margin={ 8 } />
211
- <GoogleFontsConfirmDialog />
212
- </>
213
- ) }
231
+ const getSortedFontFaces = ( fontFamily ) => {
232
+ if ( ! fontFamily ) {
233
+ return [];
234
+ }
235
+ if ( ! fontFamily.fontFace || ! fontFamily.fontFace.length ) {
236
+ return [
237
+ {
238
+ fontFamily: fontFamily.fontFamily,
239
+ fontStyle: 'normal',
240
+ fontWeight: '400',
241
+ },
242
+ ];
243
+ }
244
+ return sortFontFaces( fontFamily.fontFace );
245
+ };
214
246
 
215
- { ! renderConfirmDialog && ! selectedFont && (
216
- <Flex>
217
- <FlexItem>
218
- <InputControl
219
- value={ filters.search }
220
- placeholder={ __( 'Font name…' ) }
221
- label={ __( 'Search' ) }
222
- onChange={ debouncedUpdateSearchInput }
223
- prefix={ <Icon icon={ search } /> }
224
- suffix={
225
- filters?.search ? (
226
- <Icon
227
- icon={ closeSmall }
228
- onClick={ resetSearch }
229
- />
230
- ) : null
231
- }
232
- />
233
- </FlexItem>
234
- <FlexItem>
235
- <SelectControl
236
- label={ __( 'Category' ) }
237
- value={ filters.category }
238
- onChange={ handleCategoryFilter }
239
- >
240
- { categories &&
241
- categories.map( ( category ) => (
242
- <option
243
- value={ category.slug }
244
- key={ category.slug }
245
- >
246
- { category.name }
247
- </option>
248
- ) ) }
249
- </SelectControl>
250
- </FlexItem>
251
- </Flex>
252
- ) }
247
+ if ( renderConfirmDialog ) {
248
+ return <GoogleFontsConfirmDialog />;
249
+ }
250
+
251
+ const ActionsComponent = () => {
252
+ if ( slug !== 'google-fonts' || renderConfirmDialog || selectedFont ) {
253
+ return null;
254
+ }
255
+ return (
256
+ <DropdownMenu
257
+ icon={ moreVertical }
258
+ label={ __( 'Actions' ) }
259
+ popoverProps={ {
260
+ position: 'bottom left',
261
+ } }
262
+ controls={ [
263
+ {
264
+ title: __( 'Revoke access to Google Fonts' ),
265
+ onClick: revokeAccess,
266
+ },
267
+ ] }
268
+ />
269
+ );
270
+ };
253
271
 
254
- <Spacer margin={ 4 } />
255
- { ! renderConfirmDialog &&
256
- ! selectedCollection?.font_families &&
257
- ! notice && <Spinner /> }
258
-
259
- { ! renderConfirmDialog &&
260
- !! selectedCollection?.font_families?.length &&
261
- ! fonts.length && (
262
- <Text>
263
- { __(
264
- 'No fonts found. Try with a different search term'
272
+ return (
273
+ <div className="font-library-modal__tabpanel-layout">
274
+ <NavigatorProvider
275
+ initialPath="/"
276
+ className="font-library-modal__tabpanel-layout"
277
+ >
278
+ <NavigatorScreen path="/">
279
+ <HStack justify="space-between">
280
+ <Heading level={ 2 } size={ 13 }>
281
+ { selectedCollection.name }
282
+ </Heading>
283
+ <ActionsComponent />
284
+ </HStack>
285
+ <Text>{ selectedCollection.description }</Text>
286
+ <Spacer margin={ 4 } />
287
+ <Flex>
288
+ <FlexItem>
289
+ <InputControl
290
+ value={ filters.search }
291
+ placeholder={ __( 'Font name…' ) }
292
+ label={ __( 'Search' ) }
293
+ onChange={ debouncedUpdateSearchInput }
294
+ prefix={ <Icon icon={ search } /> }
295
+ suffix={
296
+ filters?.search ? (
297
+ <Icon
298
+ icon={ closeSmall }
299
+ onClick={ resetSearch }
300
+ />
301
+ ) : null
302
+ }
303
+ />
304
+ </FlexItem>
305
+ <FlexItem>
306
+ <SelectControl
307
+ label={ __( 'Category' ) }
308
+ value={ filters.category }
309
+ onChange={ handleCategoryFilter }
310
+ >
311
+ { categories &&
312
+ categories.map( ( category ) => (
313
+ <option
314
+ value={ category.slug }
315
+ key={ category.slug }
316
+ >
317
+ { category.name }
318
+ </option>
319
+ ) ) }
320
+ </SelectControl>
321
+ </FlexItem>
322
+ </Flex>
323
+
324
+ <Spacer margin={ 4 } />
325
+
326
+ { ! selectedCollection?.font_families && ! notice && (
327
+ <Spinner />
328
+ ) }
329
+
330
+ { !! selectedCollection?.font_families?.length &&
331
+ ! fonts.length && (
332
+ <Text>
333
+ { __(
334
+ 'No fonts found. Try with a different search term'
335
+ ) }
336
+ </Text>
265
337
  ) }
266
- </Text>
267
- ) }
268
-
269
- { ! renderConfirmDialog && selectedFont && (
270
- <CollectionFontDetails
271
- font={ selectedFont }
272
- handleToggleVariant={ handleToggleVariant }
273
- fontToInstallOutline={ fontToInstallOutline }
274
- />
275
- ) }
276
338
 
277
- { ! renderConfirmDialog && ! selectedFont && (
278
- <FontsGrid>
279
- { fonts.map( ( font ) => (
280
- <FontCard
281
- key={ font.font_family_settings.slug }
282
- font={ font.font_family_settings }
339
+ <div className="font-library-modal__fonts-grid__main">
340
+ { items.map( ( font ) => (
341
+ <FontCard
342
+ key={ font.font_family_settings.slug }
343
+ font={ font.font_family_settings }
344
+ navigatorPath={ '/fontFamily' }
345
+ onClick={ () => {
346
+ setSelectedFont(
347
+ font.font_family_settings
348
+ );
349
+ } }
350
+ />
351
+ ) ) }
352
+ </div>
353
+ </NavigatorScreen>
354
+
355
+ <NavigatorScreen path="/fontFamily">
356
+ <Flex justify="flex-start">
357
+ <NavigatorToParentButton
358
+ icon={ chevronLeft }
359
+ isSmall
283
360
  onClick={ () => {
284
- setSelectedFont( font.font_family_settings );
361
+ setSelectedFont( null );
285
362
  } }
363
+ aria-label={ __( 'Navigate to the previous view' ) }
286
364
  />
287
- ) ) }
288
- </FontsGrid>
365
+ <Heading
366
+ level={ 2 }
367
+ size={ 13 }
368
+ className="edit-site-global-styles-header"
369
+ >
370
+ { selectedFont?.name }
371
+ </Heading>
372
+ </Flex>
373
+ { notice && (
374
+ <>
375
+ <Spacer margin={ 1 } />
376
+ <Notice
377
+ status={ notice.type }
378
+ onRemove={ () => setNotice( null ) }
379
+ >
380
+ { notice.message }
381
+ </Notice>
382
+ <Spacer margin={ 1 } />
383
+ </>
384
+ ) }
385
+ <Spacer margin={ 4 } />
386
+ <Text> { __( 'Select font variants to install.' ) } </Text>
387
+ <Spacer margin={ 4 } />
388
+ <VStack spacing={ 0 }>
389
+ <Spacer margin={ 8 } />
390
+ { getSortedFontFaces( selectedFont ).map(
391
+ ( face, i ) => (
392
+ <CollectionFontVariant
393
+ font={ selectedFont }
394
+ face={ face }
395
+ key={ `face${ i }` }
396
+ handleToggleVariant={ handleToggleVariant }
397
+ selected={ isFontFontFaceInOutline(
398
+ selectedFont.slug,
399
+ selectedFont.fontFace ? face : null, // If the font has no fontFace, we want to check if the font is in the outline
400
+ fontToInstallOutline
401
+ ) }
402
+ />
403
+ )
404
+ ) }
405
+ </VStack>
406
+ <Spacer margin={ 16 } />
407
+ </NavigatorScreen>
408
+ </NavigatorProvider>
409
+
410
+ { selectedFont && (
411
+ <Flex
412
+ justify="flex-end"
413
+ className="font-library-modal__tabpanel-layout__footer"
414
+ >
415
+ <Button
416
+ variant="primary"
417
+ onClick={ handleInstall }
418
+ isBusy={ isInstalling }
419
+ disabled={ fontsToInstall.length === 0 || isInstalling }
420
+ __experimentalIsFocusable
421
+ >
422
+ { __( 'Install' ) }
423
+ </Button>
424
+ </Flex>
289
425
  ) }
290
- </TabPanelLayout>
291
- );
292
- }
293
-
294
- function Footer( { handleInstall, isDisabled } ) {
295
- const { isInstalling } = useContext( FontLibraryContext );
296
426
 
297
- return (
298
- <Flex justify="flex-end">
299
- <Button
300
- variant="primary"
301
- onClick={ handleInstall }
302
- isBusy={ isInstalling }
303
- disabled={ isDisabled || isInstalling }
304
- __experimentalIsFocusable
305
- >
306
- { __( 'Install' ) }
307
- </Button>
308
- </Flex>
427
+ { ! selectedFont && (
428
+ <Flex
429
+ justify="center"
430
+ className="font-library-modal__tabpanel-layout__footer"
431
+ >
432
+ <Button
433
+ label={ __( 'First page' ) }
434
+ size="compact"
435
+ onClick={ () => setPage( 1 ) }
436
+ disabled={ page === 1 }
437
+ __experimentalIsFocusable
438
+ >
439
+ <span>«</span>
440
+ </Button>
441
+ <Button
442
+ label={ __( 'Previous page' ) }
443
+ size="compact"
444
+ onClick={ () => setPage( page - 1 ) }
445
+ disabled={ page === 1 }
446
+ __experimentalIsFocusable
447
+ >
448
+ <span>‹</span>
449
+ </Button>
450
+ <HStack
451
+ justify="flex-start"
452
+ expanded={ false }
453
+ spacing={ 2 }
454
+ >
455
+ { createInterpolateElement(
456
+ sprintf(
457
+ // translators: %s: Total number of pages.
458
+ _x(
459
+ 'Page <CurrenPageControl /> of %s',
460
+ 'paging'
461
+ ),
462
+ totalPages
463
+ ),
464
+ {
465
+ CurrenPageControl: (
466
+ <SelectControl
467
+ aria-label={ __( 'Current page' ) }
468
+ value={ page }
469
+ options={ [
470
+ ...Array( totalPages ),
471
+ ].map( ( e, i ) => {
472
+ return {
473
+ label: i + 1,
474
+ value: i + 1,
475
+ };
476
+ } ) }
477
+ onChange={ ( newPage ) =>
478
+ setPage( parseInt( newPage ) )
479
+ }
480
+ size={ 'compact' }
481
+ __nextHasNoMarginBottom
482
+ />
483
+ ),
484
+ }
485
+ ) }
486
+ </HStack>
487
+ <Button
488
+ label={ __( 'Next page' ) }
489
+ size="compact"
490
+ onClick={ () => setPage( page + 1 ) }
491
+ disabled={ page === totalPages }
492
+ __experimentalIsFocusable
493
+ >
494
+ <span>›</span>
495
+ </Button>
496
+ <Button
497
+ label={ __( 'Last page' ) }
498
+ size="compact"
499
+ onClick={ () => setPage( totalPages ) }
500
+ disabled={ page === totalPages }
501
+ __experimentalIsFocusable
502
+ >
503
+ <span>»</span>
504
+ </Button>
505
+ </Flex>
506
+ ) }
507
+ </div>
309
508
  );
310
509
  }
311
510
 
@@ -8,7 +8,10 @@ import { useContext, useEffect, useState, useRef } from '@wordpress/element';
8
8
  * Internal dependencies
9
9
  */
10
10
  import { FontLibraryContext } from './context';
11
- import { getFacePreviewStyle } from './utils/preview-styles';
11
+ import {
12
+ getFacePreviewStyle,
13
+ getFamilyPreviewStyle,
14
+ } from './utils/preview-styles';
12
15
 
13
16
  function getPreviewUrl( fontFace ) {
14
17
  if ( fontFace.preview ) {
@@ -19,8 +22,39 @@ function getPreviewUrl( fontFace ) {
19
22
  }
20
23
  }
21
24
 
22
- function FontFaceDemo( { customPreviewUrl, fontFace, text, style = {} } ) {
25
+ function getDisplayFontFace( font ) {
26
+ // if this IS a font face return it
27
+ if ( font.fontStyle || font.fontWeight ) {
28
+ return font;
29
+ }
30
+ // if this is a font family with a collection of font faces
31
+ // return the first one that is normal and 400 OR just the first one
32
+ if ( font.fontFace && font.fontFace.length ) {
33
+ return (
34
+ font.fontFace.find(
35
+ ( face ) =>
36
+ face.fontStyle === 'normal' && face.fontWeight === '400'
37
+ ) || font.fontFace[ 0 ]
38
+ );
39
+ }
40
+ // This must be a font family with no font faces
41
+ // return a fake font face
42
+ return {
43
+ fontStyle: 'normal',
44
+ fontWeight: '400',
45
+ fontFamily: font.fontFamily,
46
+ fake: true,
47
+ };
48
+ }
49
+
50
+ function FontDemo( { font, text } ) {
23
51
  const ref = useRef( null );
52
+
53
+ const fontFace = getDisplayFontFace( font );
54
+ const style = getFamilyPreviewStyle( font );
55
+ text = text || font.name;
56
+ const customPreviewUrl = font.preview;
57
+
24
58
  const [ isIntersecting, setIsIntersecting ] = useState( false );
25
59
  const [ isAssetLoaded, setIsAssetLoaded ] = useState( false );
26
60
  const { loadFontFaceAsset } = useContext( FontLibraryContext );
@@ -34,8 +68,8 @@ function FontFaceDemo( { customPreviewUrl, fontFace, text, style = {} } ) {
34
68
  fontSize: '18px',
35
69
  lineHeight: 1,
36
70
  opacity: isAssetLoaded ? '1' : '0',
37
- ...faceStyles,
38
71
  ...style,
72
+ ...faceStyles,
39
73
  };
40
74
 
41
75
  useEffect( () => {
@@ -79,4 +113,4 @@ function FontFaceDemo( { customPreviewUrl, fontFace, text, style = {} } ) {
79
113
  );
80
114
  }
81
115
 
82
- export default FontFaceDemo;
116
+ export default FontDemo;
@@ -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
  { __(