@automattic/jetpack-components 1.6.1 → 1.8.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 +21 -0
- package/build/components/admin-page/index.js +6 -12
- package/build/components/admin-page/style.module.scss +0 -1
- package/build/components/admin-page/types.d.ts +0 -12
- package/build/components/jetpack-footer/index.d.ts +8 -0
- package/build/components/jetpack-footer/index.js +26 -59
- package/build/components/jetpack-footer/style.scss +20 -90
- package/build/components/jetpack-footer/types.d.ts +3 -32
- package/build/components/navigator-modal/header.d.ts +9 -1
- package/build/components/navigator-modal/header.js +8 -3
- package/build/components/navigator-modal/screen.d.ts +3 -12
- package/build/components/navigator-modal/screen.js +2 -2
- package/components/admin-page/index.tsx +4 -27
- package/components/admin-page/style.module.scss +0 -1
- package/components/admin-page/types.ts +0 -15
- package/components/jetpack-footer/README.md +23 -10
- package/components/jetpack-footer/index.tsx +78 -117
- package/components/jetpack-footer/style.scss +20 -90
- package/components/jetpack-footer/types.ts +3 -39
- package/components/navigator-modal/header.tsx +23 -3
- package/components/navigator-modal/screen.tsx +45 -47
- package/package.json +13 -11
- package/tools/copy-scss-to-build.mjs +1 -5
- package/build/tools/get-site-admin-url/index.d.ts +0 -8
- package/build/tools/get-site-admin-url/index.js +0 -17
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
### This is a list detailing changes for the Jetpack RNA Components package releases.
|
|
4
4
|
|
|
5
|
+
## [1.8.0] - 2026-04-06
|
|
6
|
+
### Added
|
|
7
|
+
- Add onGoBack and onClose callback props to NavigatorModal Screen and Header components. [#47896]
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- JetpackFooter: Update footer design with Products and Help navigation links, removing About, Privacy, and Terms links and related props. [#47840]
|
|
11
|
+
- Remove padding from admin page header subtitle for consistent spacing. [#47418]
|
|
12
|
+
- Update network admin settings visually. [#47912]
|
|
13
|
+
- Update package dependencies. [#47870]
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- JetpackFooter: Pin base font-size to design token to prevent page context from leaking into footer layout. [#47921]
|
|
17
|
+
|
|
18
|
+
## [1.7.0] - 2026-03-30
|
|
19
|
+
### Changed
|
|
20
|
+
- Remove double heading wrapper from AdminPage title, fixing header title sizing across all Jetpack admin pages. [#47696]
|
|
21
|
+
- Update legacy Node calls. [#47770]
|
|
22
|
+
- Update package dependencies. [#47799]
|
|
23
|
+
|
|
5
24
|
## [1.6.1] - 2026-03-23
|
|
6
25
|
### Changed
|
|
7
26
|
- Update package dependencies. [#47684] [#47719]
|
|
@@ -1709,6 +1728,8 @@
|
|
|
1709
1728
|
### Changed
|
|
1710
1729
|
- Update node version requirement to 14.16.1
|
|
1711
1730
|
|
|
1731
|
+
[1.8.0]: https://github.com/Automattic/jetpack-components/compare/1.7.0...1.8.0
|
|
1732
|
+
[1.7.0]: https://github.com/Automattic/jetpack-components/compare/1.6.1...1.7.0
|
|
1712
1733
|
[1.6.1]: https://github.com/Automattic/jetpack-components/compare/1.6.0...1.6.1
|
|
1713
1734
|
[1.6.0]: https://github.com/Automattic/jetpack-components/compare/1.5.0...1.6.0
|
|
1714
1735
|
[1.5.0]: https://github.com/Automattic/jetpack-components/compare/1.4.16...1.5.0
|
|
@@ -2,8 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import restApi from '@automattic/jetpack-api';
|
|
3
3
|
import { Page } from '@wordpress/admin-ui';
|
|
4
4
|
import '@wordpress/admin-ui/build-style/style.css';
|
|
5
|
-
import {
|
|
6
|
-
__experimentalHStack as HStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
|
|
5
|
+
import { __experimentalHStack as HStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
|
|
7
6
|
} from '@wordpress/components';
|
|
8
7
|
import { __, sprintf } from '@wordpress/i18n';
|
|
9
8
|
import clsx from 'clsx';
|
|
@@ -21,7 +20,7 @@ import styles from './style.module.scss';
|
|
|
21
20
|
* @param {AdminPageProps} props - Component properties.
|
|
22
21
|
* @return {ReactNode} AdminPage component.
|
|
23
22
|
*/
|
|
24
|
-
const AdminPage = ({ children, className,
|
|
23
|
+
const AdminPage = ({ children, className, showHeader = true, showFooter = true, showBackground = true, sandboxedDomain = '', apiRoot = '', apiNonce = '', optionalMenuItems, header, title, subTitle, logo, actions, breadcrumbs, tabs, showBottomBorder = true, }) => {
|
|
25
24
|
useEffect(() => {
|
|
26
25
|
restApi.setApiRoot(apiRoot);
|
|
27
26
|
restApi.setApiNonce(apiNonce);
|
|
@@ -44,21 +43,16 @@ const AdminPage = ({ children, className, moduleName = 'Jetpack' /** "Jetpack" i
|
|
|
44
43
|
}
|
|
45
44
|
}, []);
|
|
46
45
|
// Compose the title with logo for the admin-ui Page header.
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
// needed until https://github.com/WordPress/gutenberg/pull/75899 fixes
|
|
50
|
-
// non-string title rendering in admin-ui. Once that lands, remove the Heading
|
|
51
|
-
// here and pass the plain HStack with a string child.
|
|
52
|
-
const composedTitle = title ? (_jsxs(HStack, { spacing: 2, justify: "left", children: [logo || _jsx(JetpackLogo, { showText: false, height: 20 }), _jsx(Heading, { as: "h2", level: 3, weight: 500, truncate: true, children: title })
|
|
46
|
+
// Page's Header wraps this in an <h2> tag, so we just pass the content directly.
|
|
47
|
+
const composedTitle = title ? (_jsxs(HStack, { spacing: 2, justify: "left", children: [logo || _jsx(JetpackLogo, { showText: false, height: 20 }), _jsx("span", { children: title })
|
|
53
48
|
] })) : undefined;
|
|
54
|
-
const footer = showFooter && (_jsx(Container, { className: styles['admin-page-footer'], horizontalSpacing: 5, children: _jsx(Col, { children: _jsx(JetpackFooter, { moduleName: moduleName, moduleNameHref: moduleNameHref, menu: optionalMenuItems, useInternalLinks: useInternalLinks }) }) }));
|
|
55
49
|
// When title or breadcrumbs are provided, use admin-ui Page for the full page layout.
|
|
56
50
|
if (showHeader && (composedTitle || breadcrumbs)) {
|
|
57
|
-
return (_jsx("div", { className: rootClassName, children: _jsxs(Page, { ariaLabel: title, breadcrumbs: breadcrumbs, title: composedTitle, subTitle: subTitle, actions: actions, showSidebarToggle: false, children: [tabs, _jsx(Container, { fluid: true, horizontalSpacing: 0, children: _jsx(Col, { children: children }) }),
|
|
51
|
+
return (_jsx("div", { className: rootClassName, children: _jsxs(Page, { ariaLabel: title, breadcrumbs: breadcrumbs, title: composedTitle, subTitle: subTitle, actions: actions, showSidebarToggle: false, children: [tabs, _jsx(Container, { fluid: true, horizontalSpacing: 0, children: _jsx(Col, { children: children }) }), showFooter && _jsx(JetpackFooter, { menu: optionalMenuItems })] }) }));
|
|
58
52
|
}
|
|
59
53
|
// Legacy path: no title provided, render the classic header.
|
|
60
54
|
return (_jsxs("div", { className: rootClassName, children: [showHeader && (_jsx(Container, { horizontalSpacing: 5, children: _jsxs(Col, { className: clsx(styles['admin-page-header'], 'jp-admin-page-header'), children: [header ? header : _jsx(JetpackLogo, {}), sandboxedDomain && (_jsx("code", { className: styles['sandbox-domain-badge'], onClick: testConnection, onKeyDown: testConnection,
|
|
61
55
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role
|
|
62
|
-
role: "button", tabIndex: 0, title: `Sandboxing via ${sandboxedDomain}. Click to test connection.`, children: "API Sandboxed" }))] }) })), _jsx(Container, { fluid: true, horizontalSpacing: 0, children: _jsx(Col, { children: children }) }),
|
|
56
|
+
role: "button", tabIndex: 0, title: `Sandboxing via ${sandboxedDomain}. Click to test connection.`, children: "API Sandboxed" }))] }) })), _jsx(Container, { fluid: true, horizontalSpacing: 0, children: _jsx(Col, { children: children }) }), showFooter && _jsx(JetpackFooter, { menu: optionalMenuItems })] }));
|
|
63
57
|
};
|
|
64
58
|
export default AdminPage;
|
|
@@ -5,10 +5,6 @@ export type AdminPageProps = {
|
|
|
5
5
|
* The page content
|
|
6
6
|
*/
|
|
7
7
|
children: ReactNode;
|
|
8
|
-
/**
|
|
9
|
-
* Name of the module, e.g. 'Jetpack Search' that will be displayed in the footer.
|
|
10
|
-
*/
|
|
11
|
-
moduleName?: string;
|
|
12
8
|
/**
|
|
13
9
|
* Whether or not to display the Header
|
|
14
10
|
*/
|
|
@@ -47,14 +43,6 @@ export type AdminPageProps = {
|
|
|
47
43
|
* Whether or not to display the Footer
|
|
48
44
|
*/
|
|
49
45
|
showFooter?: boolean;
|
|
50
|
-
/**
|
|
51
|
-
* Whether or not to link to Jetpack plugin admin pages.
|
|
52
|
-
*/
|
|
53
|
-
useInternalLinks?: boolean;
|
|
54
|
-
/**
|
|
55
|
-
* Link that the Footer Module name will link to (optional).
|
|
56
|
-
*/
|
|
57
|
-
moduleNameHref?: string;
|
|
58
46
|
/**
|
|
59
47
|
* Whether or not to display the Background Color
|
|
60
48
|
*/
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import './style.scss';
|
|
2
2
|
import type { JetpackFooterProps } from './types.ts';
|
|
3
3
|
import type { FC } from 'react';
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
JetpackNetworkAdminData?: {
|
|
7
|
+
sitesUrl: string;
|
|
8
|
+
settingsUrl: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
}
|
|
4
12
|
/**
|
|
5
13
|
* JetpackFooter component displays a tiny Jetpack logo with the product name on the left and the Automattic Airline "by line" on the right.
|
|
6
14
|
*
|
|
@@ -1,76 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { isWpcomPlatformSite, getAdminUrl } from '@automattic/jetpack-script-data';
|
|
3
|
+
import { __ } from '@wordpress/i18n';
|
|
4
|
+
import { Stack, Text, Link } from '@wordpress/ui';
|
|
4
5
|
import clsx from 'clsx';
|
|
5
6
|
import { getRedirectUrl } from '../../index.js';
|
|
6
|
-
import getSiteAdminUrl from '../../tools/get-site-admin-url/index.js';
|
|
7
7
|
import AutomatticBylineLogo from '../automattic-byline-logo/index.js';
|
|
8
8
|
import './style.scss';
|
|
9
9
|
import JetpackLogo from '../jetpack-logo/index.js';
|
|
10
|
-
import useBreakpointMatch from '../layout/use-breakpoint-match/index.js';
|
|
11
|
-
const JetpackIcon = () => (_jsx(JetpackLogo, { logoColor: "#000", showText: false, height: 16, "aria-hidden": "true" }));
|
|
12
|
-
const ExternalIcon = () => (_jsxs(_Fragment, { children: [
|
|
13
|
-
_jsx(Icon, { icon: external, size: 16 }), _jsx("span", { className: "jp-dashboard-footer__accessible-external-link", children:
|
|
14
|
-
/* translators: accessibility text */
|
|
15
|
-
__('(opens in a new tab)', 'jetpack-components') })
|
|
16
|
-
] }));
|
|
17
10
|
/**
|
|
18
11
|
* JetpackFooter component displays a tiny Jetpack logo with the product name on the left and the Automattic Airline "by line" on the right.
|
|
19
12
|
*
|
|
20
13
|
* @param {JetpackFooterProps} props - Component properties.
|
|
21
14
|
* @return {ReactNode} JetpackFooter component.
|
|
22
15
|
*/
|
|
23
|
-
const JetpackFooter = ({
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
label: _x('Privacy', 'Shorthand for Privacy Policy.', 'jetpack-components'),
|
|
40
|
-
title: __("Automattic's Privacy Policy", 'jetpack-components'),
|
|
41
|
-
href: useInternalLinks
|
|
42
|
-
? new URL('admin.php?page=jetpack#/privacy', siteAdminUrl).href
|
|
43
|
-
: getRedirectUrl('a8c-privacy'),
|
|
44
|
-
target: useInternalLinks ? '_self' : '_blank',
|
|
45
|
-
onClick: onPrivacyClick,
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
label: _x('Terms', 'Shorthand for Terms of Service.', 'jetpack-components'),
|
|
49
|
-
title: __('WordPress.com Terms of Service', 'jetpack-components'),
|
|
50
|
-
href: getRedirectUrl('wpcom-tos'),
|
|
51
|
-
target: '_blank',
|
|
52
|
-
onClick: onTermsClick,
|
|
53
|
-
},
|
|
54
|
-
];
|
|
16
|
+
const JetpackFooter = ({ className, menu, ...otherProps }) => {
|
|
17
|
+
let items = [];
|
|
18
|
+
if (!isWpcomPlatformSite() && !window?.JetpackNetworkAdminData) {
|
|
19
|
+
items = [
|
|
20
|
+
{
|
|
21
|
+
label: __('Products', 'jetpack-components'),
|
|
22
|
+
href: getAdminUrl('admin.php?page=my-jetpack#/products'),
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: __('Help', 'jetpack-components'),
|
|
26
|
+
href: getAdminUrl('admin.php?page=my-jetpack#/help'),
|
|
27
|
+
},
|
|
28
|
+
...items,
|
|
29
|
+
];
|
|
30
|
+
}
|
|
55
31
|
if (menu) {
|
|
56
32
|
items = [...items, ...menu];
|
|
57
33
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'is-md': isMd,
|
|
63
|
-
'is-lg': isLg,
|
|
64
|
-
}, className), "aria-label": __('Jetpack', 'jetpack-components'), role: "contentinfo", ...otherProps, children: _jsxs("ul", { children: [
|
|
65
|
-
_jsx("li", { className: "jp-dashboard-footer__jp-item", children: moduleNameHref ? (_jsx("a", { href: moduleNameHref, children: jetpackItemContent })) : (jetpackItemContent) }), items.map(item => {
|
|
34
|
+
return (_jsxs(Stack, { render: _jsx("footer", {}), className: clsx('jetpack-footer', className), "aria-label": __('Jetpack', 'jetpack-components'), role: "contentinfo", direction: "row", justify: "flex-start", align: "center", wrap: "wrap", gap: "xl", ...otherProps, children: [
|
|
35
|
+
_jsxs(Stack, { className: "jetpack-footer__logo", direction: "row", gap: "sm", align: "center", children: [
|
|
36
|
+
_jsx(JetpackLogo, { showText: false, height: 16, "aria-hidden": "true" }), _jsx(Text, { variant: "body-md", children: "Jetpack" })
|
|
37
|
+
] }), _jsx(Stack, { render: _jsx("ul", {}), direction: "row", gap: "lg", wrap: "wrap", children: items.map(item => {
|
|
66
38
|
const isButton = item.role === 'button';
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}), role: item.role, rel: isExternalLink ? 'noopener noreferrer' : undefined, tabIndex: isButton ? 0 : undefined, children: [item.label, isExternalLink && _jsx(ExternalIcon, {})] }) }, item.label));
|
|
71
|
-
}), _jsx("li", { className: "jp-dashboard-footer__a8c-item", children: _jsx("a", { href: useInternalLinks
|
|
72
|
-
? new URL('admin.php?page=jetpack_about', siteAdminUrl).href
|
|
73
|
-
: getRedirectUrl('a8c-about'), "aria-label": __('An Automattic Airline', 'jetpack-components'), children: _jsx(AutomatticBylineLogo, { "aria-hidden": "true" }) }) })
|
|
74
|
-
] }) }));
|
|
39
|
+
return (_jsx("li", { children: _jsx(Text, { variant: "body-sm", className: "jetpack-footer__menu-item", render: isButton ? (_jsx(Link, { render: _jsx(Text, { variant: "body-md", render: _jsx("span", {}) }), tone: "neutral", variant: "default", role: item.role, tabIndex: 0, onClick: item.onClick || undefined, onKeyDown: item.onKeyDown || undefined })) : (_jsx(Link, { render: _jsx(Text, { variant: "body-md", render: _jsx("a", {}) }), tone: "neutral", variant: "default", href: item.href || '', title: item.title || '', role: item.role, onClick: item.onClick || undefined, onKeyDown: item.onKeyDown || undefined })), children: item.label }) }, item.label));
|
|
40
|
+
}) }), _jsx("a", { className: "jetpack-footer__a8c", href: getRedirectUrl('a8c-about'), rel: "noopener noreferrer", target: "_blank", children: _jsx(AutomatticBylineLogo, { height: 8 }) })
|
|
41
|
+
] }));
|
|
75
42
|
};
|
|
76
43
|
export default JetpackFooter;
|
|
@@ -1,119 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
@use "sass:meta";
|
|
2
|
+
@include meta.load-css("pkg:@wordpress/theme/design-tokens.css");
|
|
3
|
+
|
|
4
|
+
.jetpack-footer {
|
|
5
|
+
border-top: var(--wpds-border-width-xs, 1px) solid var(--wpds-color-stroke-surface-neutral-weak, #e0e0e0);
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
font-size: var(--wpds-font-size-md, 13px);
|
|
8
|
+
padding: var(--wpds-dimension-padding-xl) var(--wpds-dimension-padding-2xl);
|
|
7
9
|
width: 100%;
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
font-size: var(--font-body-extra-small);
|
|
12
|
-
line-height: 1.333;
|
|
13
|
-
|
|
14
|
-
a {
|
|
15
|
-
text-decoration: none;
|
|
11
|
+
.jetpack-footer__menu-item {
|
|
16
12
|
|
|
17
13
|
&:any-link,
|
|
18
14
|
&[role="button"] {
|
|
19
|
-
color:
|
|
15
|
+
color: var(--wpds-color-fg-interactive-neutral-weak);
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
text-decoration: none;
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
&:hover {
|
|
23
21
|
text-decoration: underline;
|
|
24
|
-
text-decoration-thickness: 1.5px;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
&:focus {
|
|
28
|
-
box-shadow: none;
|
|
29
|
-
outline-width: 0;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
&:focus-visible {
|
|
33
|
-
border-radius: 2px;
|
|
34
|
-
box-shadow: none;
|
|
35
|
-
outline: 1.5px solid currentColor;
|
|
36
|
-
outline-offset: 3px;
|
|
37
22
|
}
|
|
38
23
|
}
|
|
39
24
|
|
|
40
|
-
&.is-sm {
|
|
41
|
-
|
|
42
|
-
> ul {
|
|
43
|
-
flex-direction: column;
|
|
44
|
-
align-items: flex-start;
|
|
45
|
-
gap: 0.125rem;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
&.is-md {
|
|
50
|
-
flex-direction: column;
|
|
51
|
-
align-items: flex-start;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
25
|
> ul {
|
|
55
|
-
|
|
56
|
-
flex-wrap: wrap;
|
|
57
|
-
align-items: center;
|
|
58
|
-
gap: 1rem;
|
|
59
|
-
|
|
60
|
-
width: 100%;
|
|
26
|
+
list-style: none;
|
|
61
27
|
margin: 0;
|
|
62
28
|
padding: 0;
|
|
63
29
|
|
|
64
|
-
list-style: none;
|
|
65
|
-
|
|
66
30
|
> li {
|
|
67
|
-
margin
|
|
68
|
-
|
|
69
|
-
> a {
|
|
70
|
-
display: flex;
|
|
71
|
-
align-items: center;
|
|
72
|
-
gap: 0.25rem;
|
|
73
|
-
|
|
74
|
-
min-height: 44px; // Minimum target area size
|
|
75
|
-
}
|
|
31
|
+
margin: 0;
|
|
76
32
|
}
|
|
77
33
|
}
|
|
78
34
|
}
|
|
79
35
|
|
|
80
|
-
.
|
|
81
|
-
|
|
82
|
-
clip-path: inset(50%);
|
|
83
|
-
height: 1px;
|
|
84
|
-
margin: -1px;
|
|
85
|
-
overflow: hidden;
|
|
86
|
-
padding: 0;
|
|
87
|
-
position: absolute;
|
|
88
|
-
width: 1px;
|
|
89
|
-
overflow-wrap: normal;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.jp-dashboard-footer__jp-item {
|
|
93
|
-
padding-inline-end: 1rem;
|
|
94
|
-
|
|
95
|
-
font-weight: 600;
|
|
96
|
-
|
|
97
|
-
.jp-dashboard-footer.is-sm & {
|
|
98
|
-
padding-bottom: 1rem;
|
|
99
|
-
}
|
|
36
|
+
.jetpack-footer__logo {
|
|
37
|
+
flex-shrink: 0;
|
|
100
38
|
}
|
|
101
39
|
|
|
102
|
-
.
|
|
40
|
+
a.jetpack-footer__a8c {
|
|
103
41
|
|
|
104
|
-
|
|
42
|
+
@media (min-width: 480px) {
|
|
105
43
|
margin-inline-start: auto;
|
|
106
44
|
}
|
|
107
45
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.jp-dashboard-footer__jp-item,
|
|
114
|
-
.jp-dashboard-footer__a8c-item {
|
|
115
|
-
|
|
116
|
-
> a {
|
|
117
|
-
text-decoration: none; // Logos typically have no hover effect
|
|
46
|
+
svg {
|
|
47
|
+
fill: var(--wpds-color-fg-interactive-neutral-weak);
|
|
118
48
|
}
|
|
119
49
|
}
|
|
@@ -1,47 +1,18 @@
|
|
|
1
1
|
export type JetpackFooterMenuItem = {
|
|
2
|
-
href
|
|
2
|
+
href?: string;
|
|
3
3
|
label: string;
|
|
4
4
|
onClick?: () => void;
|
|
5
5
|
onKeyDown?: () => void;
|
|
6
|
-
target?: string;
|
|
7
6
|
title?: string;
|
|
8
7
|
role?: string;
|
|
9
8
|
};
|
|
10
9
|
export type JetpackFooterProps = {
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
13
|
-
*/
|
|
14
|
-
moduleName?: string;
|
|
15
|
-
/**
|
|
16
|
-
* additional className of the wrapper, `jp-dashboard-footer` always included.
|
|
11
|
+
* Additional className of the wrapper, `jetpack-footer` always included.
|
|
17
12
|
*/
|
|
18
13
|
className?: string;
|
|
19
14
|
/**
|
|
20
|
-
*
|
|
21
|
-
*/
|
|
22
|
-
moduleNameHref?: string;
|
|
23
|
-
/**
|
|
24
|
-
* Navigation menu to display in the footer.
|
|
15
|
+
* Additional links to display in the footer.
|
|
25
16
|
*/
|
|
26
17
|
menu?: JetpackFooterMenuItem[];
|
|
27
|
-
/**
|
|
28
|
-
* Whether to enable Jetpack admin links.
|
|
29
|
-
*/
|
|
30
|
-
useInternalLinks?: boolean;
|
|
31
|
-
/**
|
|
32
|
-
* URL of the site WP Admin.
|
|
33
|
-
*/
|
|
34
|
-
siteAdminUrl?: string;
|
|
35
|
-
/**
|
|
36
|
-
* Function called when the About link is clicked.
|
|
37
|
-
*/
|
|
38
|
-
onAboutClick?: () => void;
|
|
39
|
-
/**
|
|
40
|
-
* Function called when the Privacy link is clicked.
|
|
41
|
-
*/
|
|
42
|
-
onPrivacyClick?: () => void;
|
|
43
|
-
/**
|
|
44
|
-
* Function called when the Terms link is clicked.
|
|
45
|
-
*/
|
|
46
|
-
onTermsClick?: () => void;
|
|
47
18
|
};
|
|
@@ -11,6 +11,14 @@ export type HeaderProps = {
|
|
|
11
11
|
* Optional icon to display in the header.
|
|
12
12
|
*/
|
|
13
13
|
icon?: React.ReactNode;
|
|
14
|
+
/**
|
|
15
|
+
* Optional callback to run before navigating back.
|
|
16
|
+
*/
|
|
17
|
+
onGoBack?: VoidFunction;
|
|
18
|
+
/**
|
|
19
|
+
* Optional callback to run before closing the modal.
|
|
20
|
+
*/
|
|
21
|
+
onClose?: VoidFunction;
|
|
14
22
|
};
|
|
15
23
|
/**
|
|
16
24
|
* Renders a header for the NavigatorModal.
|
|
@@ -18,4 +26,4 @@ export type HeaderProps = {
|
|
|
18
26
|
*
|
|
19
27
|
* @return component
|
|
20
28
|
*/
|
|
21
|
-
export declare function Header({ icon, title, isScreenLocked }: HeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export declare function Header({ icon, title, isScreenLocked, onGoBack: onGoBackProp, onClose: onCloseProp }: HeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -10,13 +10,18 @@ import { NavigatorModalContext } from './context.js';
|
|
|
10
10
|
*
|
|
11
11
|
* @return component
|
|
12
12
|
*/
|
|
13
|
-
export function Header({ icon, title, isScreenLocked }) {
|
|
13
|
+
export function Header({ icon, title, isScreenLocked, onGoBack: onGoBackProp, onClose: onCloseProp, }) {
|
|
14
14
|
const context = useContext(NavigatorModalContext);
|
|
15
15
|
const navigator = useNavigator();
|
|
16
16
|
const onGoBack = useCallback(() => {
|
|
17
|
+
onGoBackProp?.();
|
|
17
18
|
navigator.goBack();
|
|
18
|
-
}, [navigator]);
|
|
19
|
+
}, [navigator, onGoBackProp]);
|
|
20
|
+
const onCloseModal = useCallback(() => {
|
|
21
|
+
onCloseProp?.();
|
|
22
|
+
context.onClose?.();
|
|
23
|
+
}, [onCloseProp, context]);
|
|
19
24
|
return (_jsxs("div", { className: "jp-navigator-modal__header", children: [
|
|
20
25
|
_jsxs("div", { className: "jp-navigator-modal__title-wrap", children: [!isScreenLocked ? (_jsx(Button, { label: __('Go back', 'jetpack-components'), icon: isRTL() ? chevronRight : chevronLeft, onClick: onGoBack, variant: "tertiary", size: "compact" })) : null, icon, _jsx("h1", { children: title })
|
|
21
|
-
] }), context.isDismissible ? (_jsx(Button, { size: "compact", onClick:
|
|
26
|
+
] }), context.isDismissible ? (_jsx(Button, { size: "compact", onClick: onCloseModal, icon: close, label: __('Close', 'jetpack-components'), variant: "tertiary" })) : null] }));
|
|
22
27
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { Navigator } from '@wordpress/components';
|
|
2
2
|
import { FooterProps } from './footer.tsx';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* The title of the screen.
|
|
6
|
-
*/
|
|
7
|
-
title?: string;
|
|
3
|
+
import { HeaderProps } from './header.tsx';
|
|
4
|
+
export type ScreenProps = Omit<React.ComponentProps<typeof Navigator.Screen>, 'content' | 'children'> & Omit<HeaderProps, 'icon'> & {
|
|
8
5
|
/**
|
|
9
6
|
* Optional icon to display in the header.
|
|
10
7
|
*/
|
|
@@ -17,12 +14,6 @@ export type ScreenProps = Omit<React.ComponentProps<typeof Navigator.Screen>, 'c
|
|
|
17
14
|
* The sidebar content
|
|
18
15
|
*/
|
|
19
16
|
sidebar?: React.ReactNode;
|
|
20
|
-
/**
|
|
21
|
-
* Whether the screen is locked or has a parent screen.
|
|
22
|
-
*
|
|
23
|
-
* When it's locked, it means there will be no navigation back to a previous screen.
|
|
24
|
-
*/
|
|
25
|
-
isScreenLocked?: boolean;
|
|
26
17
|
/**
|
|
27
18
|
* The footer content
|
|
28
19
|
*/
|
|
@@ -51,4 +42,4 @@ export type ScreenProps = Omit<React.ComponentProps<typeof Navigator.Screen>, 'c
|
|
|
51
42
|
*
|
|
52
43
|
* @return The rendered screen.
|
|
53
44
|
*/
|
|
54
|
-
export declare function Screen({ path, className, title, sidebar, headerIcon, isScreenLocked, footerContent, footerActions, children, content, ...props }: ScreenProps): import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
export declare function Screen({ path, className, title, sidebar, headerIcon, isScreenLocked, onGoBack, onClose, footerContent, footerActions, children, content, ...props }: ScreenProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -10,9 +10,9 @@ import { Header } from './header.js';
|
|
|
10
10
|
*
|
|
11
11
|
* @return The rendered screen.
|
|
12
12
|
*/
|
|
13
|
-
export function Screen({ path, className, title, sidebar, headerIcon, isScreenLocked, footerContent, footerActions, children, content, ...props }) {
|
|
13
|
+
export function Screen({ path, className, title, sidebar, headerIcon, isScreenLocked, onGoBack, onClose, footerContent, footerActions, children, content, ...props }) {
|
|
14
14
|
const hasFooter = Boolean(footerContent || (footerActions && footerActions.length));
|
|
15
15
|
return (_jsx(Navigator.Screen, { path: path, className: clsx('jp-navigator-modal__screen', className), ...props, children: _jsxs(Flex, { direction: "column", gap: 0, children: [
|
|
16
|
-
_jsx(Header, { title: title, isScreenLocked: isScreenLocked, icon: headerIcon }), _jsxs(Flex, { gap: 0, align: "start", className: "jp-navigator-modal__body", children: [sidebar ? _jsx("div", { className: "jp-navigator-modal__sidebar", children: sidebar }) : null, _jsx("div", { className: "jp-navigator-modal__content", children: content ?? children })
|
|
16
|
+
_jsx(Header, { title: title, isScreenLocked: isScreenLocked, icon: headerIcon, onGoBack: onGoBack, onClose: onClose }), _jsxs(Flex, { gap: 0, align: "start", className: "jp-navigator-modal__body", children: [sidebar ? _jsx("div", { className: "jp-navigator-modal__sidebar", children: sidebar }) : null, _jsx("div", { className: "jp-navigator-modal__content", children: content ?? children })
|
|
17
17
|
] }), hasFooter ? (_jsx(Footer, { actions: footerActions, isScreenLocked: isScreenLocked, children: footerContent })) : null] }) }));
|
|
18
18
|
}
|
|
@@ -2,7 +2,6 @@ import restApi from '@automattic/jetpack-api';
|
|
|
2
2
|
import { Page } from '@wordpress/admin-ui';
|
|
3
3
|
import '@wordpress/admin-ui/build-style/style.css';
|
|
4
4
|
import {
|
|
5
|
-
__experimentalHeading as Heading, // eslint-disable-line @wordpress/no-unsafe-wp-apis
|
|
6
5
|
__experimentalHStack as HStack, // eslint-disable-line @wordpress/no-unsafe-wp-apis
|
|
7
6
|
} from '@wordpress/components';
|
|
8
7
|
import { __, sprintf } from '@wordpress/i18n';
|
|
@@ -27,11 +26,8 @@ import type { FC, ReactNode } from 'react';
|
|
|
27
26
|
const AdminPage: FC< AdminPageProps > = ( {
|
|
28
27
|
children,
|
|
29
28
|
className,
|
|
30
|
-
moduleName = 'Jetpack' /** "Jetpack" is a product name, do not translate. */,
|
|
31
|
-
moduleNameHref,
|
|
32
29
|
showHeader = true,
|
|
33
30
|
showFooter = true,
|
|
34
|
-
useInternalLinks = false,
|
|
35
31
|
showBackground = true,
|
|
36
32
|
sandboxedDomain = '',
|
|
37
33
|
apiRoot = '',
|
|
@@ -75,33 +71,14 @@ const AdminPage: FC< AdminPageProps > = ( {
|
|
|
75
71
|
}, [] );
|
|
76
72
|
|
|
77
73
|
// Compose the title with logo for the admin-ui Page header.
|
|
78
|
-
//
|
|
79
|
-
// also wraps title in a Heading. This is a known issue — the inner Heading is
|
|
80
|
-
// needed until https://github.com/WordPress/gutenberg/pull/75899 fixes
|
|
81
|
-
// non-string title rendering in admin-ui. Once that lands, remove the Heading
|
|
82
|
-
// here and pass the plain HStack with a string child.
|
|
74
|
+
// Page's Header wraps this in an <h2> tag, so we just pass the content directly.
|
|
83
75
|
const composedTitle = title ? (
|
|
84
76
|
<HStack spacing={ 2 } justify="left">
|
|
85
77
|
{ logo || <JetpackLogo showText={ false } height={ 20 } /> }
|
|
86
|
-
<
|
|
87
|
-
{ title }
|
|
88
|
-
</Heading>
|
|
78
|
+
<span>{ title }</span>
|
|
89
79
|
</HStack>
|
|
90
80
|
) : undefined;
|
|
91
81
|
|
|
92
|
-
const footer = showFooter && (
|
|
93
|
-
<Container className={ styles[ 'admin-page-footer' ] } horizontalSpacing={ 5 }>
|
|
94
|
-
<Col>
|
|
95
|
-
<JetpackFooter
|
|
96
|
-
moduleName={ moduleName }
|
|
97
|
-
moduleNameHref={ moduleNameHref }
|
|
98
|
-
menu={ optionalMenuItems }
|
|
99
|
-
useInternalLinks={ useInternalLinks }
|
|
100
|
-
/>
|
|
101
|
-
</Col>
|
|
102
|
-
</Container>
|
|
103
|
-
);
|
|
104
|
-
|
|
105
82
|
// When title or breadcrumbs are provided, use admin-ui Page for the full page layout.
|
|
106
83
|
if ( showHeader && ( composedTitle || breadcrumbs ) ) {
|
|
107
84
|
return (
|
|
@@ -118,7 +95,7 @@ const AdminPage: FC< AdminPageProps > = ( {
|
|
|
118
95
|
<Container fluid horizontalSpacing={ 0 }>
|
|
119
96
|
<Col>{ children }</Col>
|
|
120
97
|
</Container>
|
|
121
|
-
{
|
|
98
|
+
{ showFooter && <JetpackFooter menu={ optionalMenuItems } /> }
|
|
122
99
|
</Page>
|
|
123
100
|
</div>
|
|
124
101
|
);
|
|
@@ -150,7 +127,7 @@ const AdminPage: FC< AdminPageProps > = ( {
|
|
|
150
127
|
<Container fluid horizontalSpacing={ 0 }>
|
|
151
128
|
<Col>{ children }</Col>
|
|
152
129
|
</Container>
|
|
153
|
-
{
|
|
130
|
+
{ showFooter && <JetpackFooter menu={ optionalMenuItems } /> }
|
|
154
131
|
</div>
|
|
155
132
|
);
|
|
156
133
|
};
|
|
@@ -7,11 +7,6 @@ export type AdminPageProps = {
|
|
|
7
7
|
*/
|
|
8
8
|
children: ReactNode;
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* Name of the module, e.g. 'Jetpack Search' that will be displayed in the footer.
|
|
12
|
-
*/
|
|
13
|
-
moduleName?: string;
|
|
14
|
-
|
|
15
10
|
/**
|
|
16
11
|
* Whether or not to display the Header
|
|
17
12
|
*/
|
|
@@ -59,16 +54,6 @@ export type AdminPageProps = {
|
|
|
59
54
|
*/
|
|
60
55
|
showFooter?: boolean;
|
|
61
56
|
|
|
62
|
-
/**
|
|
63
|
-
* Whether or not to link to Jetpack plugin admin pages.
|
|
64
|
-
*/
|
|
65
|
-
useInternalLinks?: boolean;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Link that the Footer Module name will link to (optional).
|
|
69
|
-
*/
|
|
70
|
-
moduleNameHref?: string;
|
|
71
|
-
|
|
72
57
|
/**
|
|
73
58
|
* Whether or not to display the Background Color
|
|
74
59
|
*/
|