newspack-components 4.8.0 → 4.9.0-alpha.1
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 +10 -0
- package/DEVELOPMENT.md +18 -17
- package/dist/cjs/action-card/index.js +85 -18
- package/dist/cjs/action-card/index.test.js +192 -5
- package/dist/cjs/action-card/style.scss +3 -9
- package/dist/cjs/card-feature/index.js +28 -3
- package/dist/cjs/card-feature/index.test.js +100 -45
- package/dist/cjs/card-feature/style.scss +1 -5
- package/dist/cjs/debug-badge/index.js +44 -0
- package/dist/cjs/debug-badge/index.test.js +50 -0
- package/dist/cjs/debug-badge/style.scss +26 -0
- package/dist/cjs/empty-state/index.test.js +37 -24
- package/dist/cjs/empty-state/root.js +2 -1
- package/dist/cjs/footer/index.js +52 -16
- package/dist/cjs/footer/index.test.js +208 -0
- package/dist/cjs/footer/style.scss +17 -1
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/integration-icon/index.js +4 -4
- package/dist/cjs/integration-icon/style.scss +18 -2
- package/dist/cjs/integration-icons/active-campaign.js +4 -7
- package/dist/cjs/integration-icons/beehiiv.js +19 -0
- package/dist/cjs/integration-icons/gravity-forms.js +19 -0
- package/dist/cjs/integration-icons/index.js +26 -6
- package/dist/cjs/integration-icons/salesforce.js +5 -3
- package/dist/cjs/notice/index.js +1 -4
- package/dist/cjs/notice/style.scss +0 -19
- package/dist/cjs/plugin-toggle/index.js +1 -1
- package/dist/cjs/with-wizard-screen/index.js +1 -3
- package/dist/cjs/with-wizard-screen/index.test.js +0 -3
- package/dist/cjs/wizard/breadcrumbs-select.js +17 -4
- package/dist/cjs/wizard/breadcrumbs-select.test.js +17 -0
- package/dist/cjs/wizard/index.js +50 -13
- package/dist/cjs/wizard/index.test.js +304 -5
- package/dist/cjs/wizard/store/index.js +2 -0
- package/dist/esm/action-card/index.js +86 -21
- package/dist/esm/action-card/index.test.js +192 -1
- package/dist/esm/action-card/style.scss +3 -9
- package/dist/esm/card-feature/index.js +29 -4
- package/dist/esm/card-feature/index.test.js +100 -45
- package/dist/esm/card-feature/style.scss +1 -5
- package/dist/esm/debug-badge/index.js +39 -0
- package/dist/esm/debug-badge/index.test.js +46 -0
- package/dist/esm/debug-badge/style.scss +26 -0
- package/dist/esm/empty-state/index.test.js +37 -24
- package/dist/esm/empty-state/root.js +2 -1
- package/dist/esm/footer/index.js +52 -17
- package/dist/esm/footer/index.test.js +210 -0
- package/dist/esm/footer/style.scss +17 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/integration-icon/index.js +5 -5
- package/dist/esm/integration-icon/style.scss +18 -2
- package/dist/esm/integration-icons/active-campaign.js +5 -8
- package/dist/esm/integration-icons/beehiiv.js +13 -0
- package/dist/esm/integration-icons/gravity-forms.js +13 -0
- package/dist/esm/integration-icons/index.js +15 -4
- package/dist/esm/integration-icons/salesforce.js +5 -3
- package/dist/esm/notice/index.js +2 -5
- package/dist/esm/notice/style.scss +0 -19
- package/dist/esm/plugin-toggle/index.js +1 -1
- package/dist/esm/with-wizard-screen/index.js +2 -4
- package/dist/esm/with-wizard-screen/index.test.js +0 -3
- package/dist/esm/wizard/breadcrumbs-select.js +16 -3
- package/dist/esm/wizard/breadcrumbs-select.test.js +18 -1
- package/dist/esm/wizard/index.js +53 -16
- package/dist/esm/wizard/index.test.js +304 -5
- package/dist/esm/wizard/store/index.js +2 -0
- package/package.json +1 -1
- package/src/action-card/action-card.d.ts +3 -2
- package/src/action-card/index.js +81 -8
- package/src/action-card/index.test.js +159 -0
- package/src/action-card/style.scss +3 -9
- package/src/card-feature/README.md +10 -11
- package/src/card-feature/index.test.js +45 -15
- package/src/card-feature/index.tsx +43 -24
- package/src/card-feature/style.scss +1 -5
- package/src/debug-badge/index.js +36 -0
- package/src/debug-badge/index.test.js +39 -0
- package/src/debug-badge/style.scss +26 -0
- package/src/empty-state/README.md +11 -10
- package/src/empty-state/index.test.js +10 -0
- package/src/empty-state/root.tsx +2 -1
- package/src/empty-state/types.ts +1 -1
- package/src/footer/index.js +47 -2
- package/src/footer/index.test.js +114 -0
- package/src/footer/style.scss +17 -1
- package/src/index.js +1 -0
- package/src/integration-icon/index.tsx +5 -5
- package/src/integration-icon/style.scss +18 -2
- package/src/integration-icons/active-campaign.js +1 -5
- package/src/integration-icons/beehiiv.js +10 -0
- package/src/integration-icons/gravity-forms.js +10 -0
- package/src/integration-icons/index.js +14 -3
- package/src/integration-icons/salesforce.js +3 -3
- package/src/notice/index.js +2 -17
- package/src/notice/style.scss +0 -19
- package/src/plugin-toggle/index.js +1 -1
- package/src/with-wizard-screen/index.js +2 -2
- package/src/with-wizard-screen/index.test.js +0 -2
- package/src/wizard/breadcrumbs-select.js +12 -4
- package/src/wizard/breadcrumbs-select.test.js +15 -1
- package/src/wizard/index.js +45 -14
- package/src/wizard/index.test.js +169 -3
- package/src/wizard/store/index.js +2 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { render, screen } from '@testing-library/react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import DebugBadge from '.';
|
|
10
|
+
|
|
11
|
+
describe( 'DebugBadge', () => {
|
|
12
|
+
afterEach( () => {
|
|
13
|
+
delete window.newspack_aux_data;
|
|
14
|
+
} );
|
|
15
|
+
|
|
16
|
+
it( 'renders the badge and its glyph in debug mode', () => {
|
|
17
|
+
window.newspack_aux_data = { is_debug_mode: true };
|
|
18
|
+
const { container } = render( <DebugBadge /> );
|
|
19
|
+
expect( container.querySelector( '.newspack-debug-badge' ) ).toBeInTheDocument();
|
|
20
|
+
expect( container.querySelector( '.newspack-debug-badge > svg' ) ).toBeInTheDocument();
|
|
21
|
+
} );
|
|
22
|
+
|
|
23
|
+
it( 'names itself for assistive tech', () => {
|
|
24
|
+
window.newspack_aux_data = { is_debug_mode: true };
|
|
25
|
+
render( <DebugBadge /> );
|
|
26
|
+
expect( screen.getByRole( 'img', { name: 'Debug mode' } ) ).toBeInTheDocument();
|
|
27
|
+
} );
|
|
28
|
+
|
|
29
|
+
it( 'renders nothing outside debug mode', () => {
|
|
30
|
+
window.newspack_aux_data = { is_debug_mode: false };
|
|
31
|
+
const { container } = render( <DebugBadge /> );
|
|
32
|
+
expect( container ).toBeEmptyDOMElement();
|
|
33
|
+
} );
|
|
34
|
+
|
|
35
|
+
it( 'renders nothing when the global is absent', () => {
|
|
36
|
+
const { container } = render( <DebugBadge /> );
|
|
37
|
+
expect( container ).toBeEmptyDOMElement();
|
|
38
|
+
} );
|
|
39
|
+
} );
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Badge
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
@use "~@wordpress/base-styles/colors" as wp-colors;
|
|
6
|
+
@use "~@wordpress/base-styles/variables" as wp-vars;
|
|
7
|
+
@use "../../../colors/colors.module" as np-colors;
|
|
8
|
+
|
|
9
|
+
.newspack-debug-badge {
|
|
10
|
+
background: np-colors.$primary-600;
|
|
11
|
+
border-radius: wp-vars.$radius-round;
|
|
12
|
+
bottom: 0;
|
|
13
|
+
box-shadow: var(--wpds-elevation-sm, #{wp-vars.$elevation-small});
|
|
14
|
+
display: grid;
|
|
15
|
+
height: wp-vars.$button-size;
|
|
16
|
+
margin: 0 wp-vars.$grid-unit-30 wp-vars.$grid-unit-30;
|
|
17
|
+
place-items: center;
|
|
18
|
+
pointer-events: none;
|
|
19
|
+
position: fixed;
|
|
20
|
+
width: wp-vars.$button-size;
|
|
21
|
+
z-index: 9997;
|
|
22
|
+
|
|
23
|
+
> svg {
|
|
24
|
+
fill: wp-colors.$white;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -68,15 +68,16 @@ import { EmptyState } from 'newspack-components';
|
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
Every slot except `Root` is optional, and anything else you pass to `Root`
|
|
71
|
-
becomes a sibling of the header at the same
|
|
72
|
-
|
|
73
|
-
`EmptyState.Actions`. Pass elements:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
becomes a sibling of the header at the same gap the stack uses: 8 units at the
|
|
72
|
+
default size, 6 at `small`. A screen that offers choices rather than one action
|
|
73
|
+
can drop a stack of cards in instead of `EmptyState.Actions`. Pass elements:
|
|
74
|
+
`Root`'s stack keeps a lone string but drops one sitting beside an element, so
|
|
75
|
+
wrap loose text in a `<p>`. The `Grid` margin reset reaches direct children
|
|
76
|
+
only, so a `<p>` inside a slot keeps the browser's default block margin and you
|
|
77
|
+
zero it where you use it. The component resets margins on the two elements it
|
|
78
|
+
renders itself and stops there: a blanket reset on slot content would silently
|
|
79
|
+
flatten a consumer's own stack of cards or prose, and the gaps this component
|
|
80
|
+
owns all come from its stacks anyway.
|
|
80
81
|
|
|
81
82
|
## Consumers own their wrappers
|
|
82
83
|
|
|
@@ -120,7 +121,7 @@ With a children slot there is no pair to check. A button that navigates takes
|
|
|
120
121
|
|------|------|---------|-------------|
|
|
121
122
|
| `children` | `React.ReactNode` | — | The slots, plus any custom body. |
|
|
122
123
|
| `className` | `string` | — | Merged onto the grid. |
|
|
123
|
-
| `size` | `'default'` \| `'small'` | `'default'` |
|
|
124
|
+
| `size` | `'default'` \| `'small'` | `'default'` | Sets the stack gap, and is read by `EmptyState.Header`. `small` suits an empty state standing in for a panel inside a card. |
|
|
124
125
|
|
|
125
126
|
The grid always carries `newspack-empty-state`, and `className` lands there
|
|
126
127
|
rather than on a wrapper, because consumers key off both. Inside it, the stack
|
|
@@ -45,6 +45,16 @@ describe( 'EmptyState.Root', () => {
|
|
|
45
45
|
expect( stack ).toHaveStyle( { gap: 'var(--wpds-dimension-gap-2xl, 32px)' } );
|
|
46
46
|
} );
|
|
47
47
|
|
|
48
|
+
it( 'tightens the stack gap when small', () => {
|
|
49
|
+
const { container } = render(
|
|
50
|
+
<EmptyState.Root size="small">
|
|
51
|
+
<p>body</p>
|
|
52
|
+
</EmptyState.Root>
|
|
53
|
+
);
|
|
54
|
+
const stack = container.querySelector( '.newspack-empty-state' ).firstElementChild;
|
|
55
|
+
expect( stack ).toHaveStyle( { gap: 'var(--wpds-dimension-gap-xl, 24px)' } );
|
|
56
|
+
} );
|
|
57
|
+
|
|
48
58
|
// Consumers key `:has()` selectors off this class, so losing it changes their
|
|
49
59
|
// layout without failing anything.
|
|
50
60
|
it( 'merges className onto the grid', () => {
|
package/src/empty-state/root.tsx
CHANGED
|
@@ -24,11 +24,12 @@ const gridColumn = { 'data-start': '2', 'data-end': '4' };
|
|
|
24
24
|
|
|
25
25
|
const Root = ( { size = 'default', className, children }: EmptyStateRootProps ) => {
|
|
26
26
|
const context = useMemo( () => ( { size } ), [ size ] );
|
|
27
|
+
const isSmall = size === 'small';
|
|
27
28
|
|
|
28
29
|
return (
|
|
29
30
|
<EmptyStateContext.Provider value={ context }>
|
|
30
31
|
<Grid className={ classnames( 'newspack-empty-state', className ) } columns={ 4 } noMargin>
|
|
31
|
-
<Stack className="newspack-empty-state__stack" direction="column" gap=
|
|
32
|
+
<Stack className="newspack-empty-state__stack" direction="column" gap={ isSmall ? 'xl' : '2xl' } { ...gridColumn }>
|
|
32
33
|
{ children }
|
|
33
34
|
</Stack>
|
|
34
35
|
</Grid>
|
package/src/empty-state/types.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type EmptyStateSize = 'default' | 'small';
|
|
|
5
5
|
export type EmptyStateActionsOrientation = 'row' | 'column';
|
|
6
6
|
|
|
7
7
|
export type EmptyStateRootProps = {
|
|
8
|
-
/**
|
|
8
|
+
/** Sets the stack gap here, and is read by `EmptyState.Header` through context. */
|
|
9
9
|
size?: EmptyStateSize;
|
|
10
10
|
/** Merged onto the grid, which is the element consumers' `:has()` selectors look for. */
|
|
11
11
|
className?: string;
|
package/src/footer/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { ExternalLink } from '@wordpress/components';
|
|
|
11
11
|
/**
|
|
12
12
|
* Internal dependencies.
|
|
13
13
|
*/
|
|
14
|
+
import useConfirmDialog from '../hooks/use-confirm-dialog';
|
|
14
15
|
import './style.scss';
|
|
15
16
|
|
|
16
17
|
const Footer = ( { simple = undefined } ) => {
|
|
@@ -24,6 +25,23 @@ const Footer = ( { simple = undefined } ) => {
|
|
|
24
25
|
support_email: supportEmail,
|
|
25
26
|
} = window.newspack_urls || {};
|
|
26
27
|
|
|
28
|
+
const resetDialog = useConfirmDialog( {
|
|
29
|
+
title: __( 'Reset Newspack?', 'newspack-plugin' ),
|
|
30
|
+
message: __(
|
|
31
|
+
'This deletes the Newspack settings on this site and returns you to the setup wizard. Your posts, pages and users are not affected. This cannot be undone.',
|
|
32
|
+
'newspack-plugin'
|
|
33
|
+
),
|
|
34
|
+
confirmButtonText: __( 'Reset Newspack', 'newspack-plugin' ),
|
|
35
|
+
isDestructive: true,
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
const starterContentDialog = useConfirmDialog( {
|
|
39
|
+
title: __( 'Remove Starter Content?', 'newspack-plugin' ),
|
|
40
|
+
message: __( 'This deletes the posts, pages and categories created as starter content. This cannot be undone.', 'newspack-plugin' ),
|
|
41
|
+
confirmButtonText: __( 'Remove Starter Content', 'newspack-plugin' ),
|
|
42
|
+
isDestructive: true,
|
|
43
|
+
} );
|
|
44
|
+
|
|
27
45
|
const footerElements = [
|
|
28
46
|
{
|
|
29
47
|
label: pluginVersion.label,
|
|
@@ -57,12 +75,14 @@ const Footer = ( { simple = undefined } ) => {
|
|
|
57
75
|
footerElements.push( {
|
|
58
76
|
label: __( 'Reset Newspack', 'newspack-plugin' ),
|
|
59
77
|
url: resetUrl,
|
|
78
|
+
confirm: resetDialog.requestConfirm,
|
|
60
79
|
} );
|
|
61
80
|
}
|
|
62
81
|
if ( removeStarterContent ) {
|
|
63
82
|
footerElements.push( {
|
|
64
83
|
label: __( 'Remove Starter Content', 'newspack-plugin' ),
|
|
65
84
|
url: removeStarterContent,
|
|
85
|
+
confirm: starterContentDialog.requestConfirm,
|
|
66
86
|
} );
|
|
67
87
|
}
|
|
68
88
|
if ( supportEmail ) {
|
|
@@ -71,15 +91,40 @@ const Footer = ( { simple = undefined } ) => {
|
|
|
71
91
|
url: `mailto:${ supportEmail }`,
|
|
72
92
|
} );
|
|
73
93
|
}
|
|
94
|
+
const renderItem = ( { url, label, external, confirm } ) => {
|
|
95
|
+
if ( external ) {
|
|
96
|
+
return <ExternalLink href={ url }>{ label }</ExternalLink>;
|
|
97
|
+
}
|
|
98
|
+
if ( ! confirm ) {
|
|
99
|
+
return <a href={ url }>{ label }</a>;
|
|
100
|
+
}
|
|
101
|
+
// onClick only sees primary clicks, so an href here would let a middle-click
|
|
102
|
+
// or "Open link in new tab" reach the URL unguarded.
|
|
103
|
+
return (
|
|
104
|
+
<button
|
|
105
|
+
type="button"
|
|
106
|
+
onClick={ () =>
|
|
107
|
+
confirm( () => {
|
|
108
|
+
window.location.href = url;
|
|
109
|
+
} )
|
|
110
|
+
}
|
|
111
|
+
>
|
|
112
|
+
{ label }
|
|
113
|
+
</button>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
|
|
74
117
|
return (
|
|
75
118
|
<div className="newspack-footer">
|
|
76
119
|
{ ! simple && (
|
|
77
120
|
<ul>
|
|
78
|
-
{ footerElements.map( (
|
|
79
|
-
<li key={ index }>{
|
|
121
|
+
{ footerElements.map( ( element, index ) => (
|
|
122
|
+
<li key={ index }>{ renderItem( element ) }</li>
|
|
80
123
|
) ) }
|
|
81
124
|
</ul>
|
|
82
125
|
) }
|
|
126
|
+
{ resetDialog.confirmDialog }
|
|
127
|
+
{ starterContentDialog.confirmDialog }
|
|
83
128
|
</div>
|
|
84
129
|
);
|
|
85
130
|
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies.
|
|
3
|
+
*/
|
|
4
|
+
import { fireEvent, render, screen, within } from '@testing-library/react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies.
|
|
8
|
+
*/
|
|
9
|
+
import Footer from './';
|
|
10
|
+
|
|
11
|
+
// Footer renders outside the wizard's HashRouter, so there is no MemoryRouter
|
|
12
|
+
// wrapper here on purpose.
|
|
13
|
+
describe( 'Footer', () => {
|
|
14
|
+
const RESET_URL = 'https://example.test/wp-admin/admin.php?page=newspack-dashboard&newspack_reset=reset';
|
|
15
|
+
const STARTER_CONTENT_URL = 'https://example.test/wp-admin/admin.php?page=newspack-dashboard&newspack_reset=starter-content';
|
|
16
|
+
let assigned;
|
|
17
|
+
let originalLocation;
|
|
18
|
+
let originalUrls;
|
|
19
|
+
|
|
20
|
+
const confirmIn = async name => within( await screen.findByRole( 'dialog' ) ).getByRole( 'button', { name } );
|
|
21
|
+
|
|
22
|
+
beforeEach( () => {
|
|
23
|
+
assigned = [];
|
|
24
|
+
originalLocation = window.location;
|
|
25
|
+
originalUrls = window.newspack_urls;
|
|
26
|
+
delete window.location;
|
|
27
|
+
window.location = {
|
|
28
|
+
get href() {
|
|
29
|
+
return 'https://example.test/wp-admin/admin.php?page=newspack-dashboard';
|
|
30
|
+
},
|
|
31
|
+
set href( value ) {
|
|
32
|
+
assigned.push( value );
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
window.newspack_urls = {
|
|
36
|
+
support: 'https://help.newspack.com/',
|
|
37
|
+
reset_url: RESET_URL,
|
|
38
|
+
remove_starter_content: STARTER_CONTENT_URL,
|
|
39
|
+
plugin_version: { label: 'Newspack 1.0.0' },
|
|
40
|
+
};
|
|
41
|
+
} );
|
|
42
|
+
|
|
43
|
+
afterEach( () => {
|
|
44
|
+
delete window.location;
|
|
45
|
+
window.location = originalLocation;
|
|
46
|
+
if ( undefined === originalUrls ) {
|
|
47
|
+
delete window.newspack_urls;
|
|
48
|
+
} else {
|
|
49
|
+
window.newspack_urls = originalUrls;
|
|
50
|
+
}
|
|
51
|
+
} );
|
|
52
|
+
|
|
53
|
+
it( 'offers no link for a browser gesture to follow', () => {
|
|
54
|
+
render( <Footer /> );
|
|
55
|
+
expect( screen.getByRole( 'button', { name: 'Reset Newspack' } ) ).not.toHaveAttribute( 'href' );
|
|
56
|
+
expect( screen.getByRole( 'button', { name: 'Remove Starter Content' } ) ).not.toHaveAttribute( 'href' );
|
|
57
|
+
} );
|
|
58
|
+
|
|
59
|
+
it( 'does not reset on the first click', () => {
|
|
60
|
+
render( <Footer /> );
|
|
61
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Reset Newspack' } ) );
|
|
62
|
+
expect( assigned ).toEqual( [] );
|
|
63
|
+
} );
|
|
64
|
+
|
|
65
|
+
it( 'asks before resetting', async () => {
|
|
66
|
+
render( <Footer /> );
|
|
67
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Reset Newspack' } ) );
|
|
68
|
+
expect( await screen.findByText( /deletes the Newspack settings/ ) ).toBeInTheDocument();
|
|
69
|
+
} );
|
|
70
|
+
|
|
71
|
+
it( 'leaves the site alone when the reset is cancelled', async () => {
|
|
72
|
+
render( <Footer /> );
|
|
73
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Reset Newspack' } ) );
|
|
74
|
+
// The modal's close icon also carries aria-label="Cancel"; this is the text button.
|
|
75
|
+
const cancel = ( await screen.findAllByRole( 'button', { name: 'Cancel' } ) ).find( button => 'Cancel' === button.textContent );
|
|
76
|
+
fireEvent.click( cancel );
|
|
77
|
+
expect( assigned ).toEqual( [] );
|
|
78
|
+
} );
|
|
79
|
+
|
|
80
|
+
it( 'resets once confirmed', async () => {
|
|
81
|
+
render( <Footer /> );
|
|
82
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Reset Newspack' } ) );
|
|
83
|
+
fireEvent.click( await confirmIn( 'Reset Newspack' ) );
|
|
84
|
+
expect( assigned ).toEqual( [ RESET_URL ] );
|
|
85
|
+
} );
|
|
86
|
+
|
|
87
|
+
it( 'does not remove the starter content on the first click', () => {
|
|
88
|
+
render( <Footer /> );
|
|
89
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Remove Starter Content' } ) );
|
|
90
|
+
expect( assigned ).toEqual( [] );
|
|
91
|
+
} );
|
|
92
|
+
|
|
93
|
+
it( 'asks before removing the starter content', async () => {
|
|
94
|
+
render( <Footer /> );
|
|
95
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Remove Starter Content' } ) );
|
|
96
|
+
expect( await screen.findByText( /created as starter content/ ) ).toBeInTheDocument();
|
|
97
|
+
} );
|
|
98
|
+
|
|
99
|
+
it( 'removes the starter content once confirmed', async () => {
|
|
100
|
+
render( <Footer /> );
|
|
101
|
+
fireEvent.click( screen.getByRole( 'button', { name: 'Remove Starter Content' } ) );
|
|
102
|
+
fireEvent.click( await confirmIn( 'Remove Starter Content' ) );
|
|
103
|
+
expect( assigned ).toEqual( [ STARTER_CONTENT_URL ] );
|
|
104
|
+
} );
|
|
105
|
+
|
|
106
|
+
it( 'does not guard the non-destructive links', () => {
|
|
107
|
+
window.newspack_urls.setup_wizard = 'https://example.test/wp-admin/admin.php?page=newspack-setup-wizard';
|
|
108
|
+
render( <Footer /> );
|
|
109
|
+
const link = screen.getByRole( 'link', { name: 'Setup Wizard' } );
|
|
110
|
+
expect( link ).toHaveAttribute( 'href', window.newspack_urls.setup_wizard );
|
|
111
|
+
fireEvent.click( link );
|
|
112
|
+
expect( screen.queryByRole( 'dialog' ) ).not.toBeInTheDocument();
|
|
113
|
+
} );
|
|
114
|
+
} );
|
package/src/footer/style.scss
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Footer
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
@use "../mixins" as mixins;
|
|
5
6
|
@use "~@wordpress/base-styles/colors" as wp-colors;
|
|
6
7
|
|
|
7
8
|
.newspack-footer {
|
|
@@ -31,7 +32,8 @@
|
|
|
31
32
|
li {
|
|
32
33
|
margin: 8px;
|
|
33
34
|
|
|
34
|
-
a
|
|
35
|
+
a,
|
|
36
|
+
button {
|
|
35
37
|
align-items: flex-end;
|
|
36
38
|
color: inherit;
|
|
37
39
|
display: flex;
|
|
@@ -42,5 +44,19 @@
|
|
|
42
44
|
color: wp-colors.$gray-900;
|
|
43
45
|
}
|
|
44
46
|
}
|
|
47
|
+
|
|
48
|
+
button {
|
|
49
|
+
appearance: none;
|
|
50
|
+
background: none;
|
|
51
|
+
border: 0;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
font: inherit;
|
|
54
|
+
padding: 0;
|
|
55
|
+
text-decoration: underline;
|
|
56
|
+
|
|
57
|
+
&:focus-visible {
|
|
58
|
+
@include mixins.wpds-focus-ring;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
45
61
|
}
|
|
46
62
|
}
|
package/src/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export { default as ColorPicker } from './color-picker';
|
|
|
17
17
|
export { default as ConfirmDialog } from './confirm-dialog';
|
|
18
18
|
export { default as CustomSelectControl } from './custom-select-control';
|
|
19
19
|
export { default as DataViews } from './dataviews';
|
|
20
|
+
export { default as DebugBadge } from './debug-badge';
|
|
20
21
|
export { default as Divider } from './divider';
|
|
21
22
|
export { default as Drawer } from './drawer';
|
|
22
23
|
export { default as EmptyState } from './empty-state';
|
|
@@ -6,17 +6,17 @@ import classnames from 'classnames';
|
|
|
6
6
|
/**
|
|
7
7
|
* Internal dependencies
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { providerIcons } from '../integration-icons';
|
|
10
10
|
import './style.scss';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* The single source for how
|
|
14
|
-
* background. A new provider needs an icon file,
|
|
13
|
+
* The single source for how a provider is shown: brand mark plus badge
|
|
14
|
+
* background. A new provider needs an icon file, a `providerIcons` entry,
|
|
15
15
|
* and a background rule in this component's stylesheet.
|
|
16
16
|
*/
|
|
17
17
|
const IntegrationIcon = ( { provider, className }: { provider: string; className?: string } ) => {
|
|
18
|
-
const icons: Record< string, React.ReactNode > =
|
|
19
|
-
const node = Object.prototype.hasOwnProperty.call(
|
|
18
|
+
const icons: Record< string, React.ReactNode > = providerIcons;
|
|
19
|
+
const node = Object.prototype.hasOwnProperty.call( providerIcons, provider ) ? icons[ provider ] : null;
|
|
20
20
|
if ( ! node ) {
|
|
21
21
|
return null;
|
|
22
22
|
}
|
|
@@ -21,14 +21,26 @@
|
|
|
21
21
|
background: #004cff;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
&--
|
|
25
|
-
background: #
|
|
24
|
+
&--beehiiv {
|
|
25
|
+
background: #060419;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
&--constant-contact {
|
|
29
29
|
background: wp-colors.$gray-100;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
&--fundraiseup {
|
|
33
|
+
background: #2bb77b;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&--gravity-forms {
|
|
37
|
+
background: #ff4f00;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&--mailchimp {
|
|
41
|
+
background: #ffe01b;
|
|
42
|
+
}
|
|
43
|
+
|
|
32
44
|
&--manual {
|
|
33
45
|
background: wp-colors.$gray-800;
|
|
34
46
|
color: wp-colors.$white;
|
|
@@ -39,4 +51,8 @@
|
|
|
39
51
|
fill: currentcolor;
|
|
40
52
|
}
|
|
41
53
|
}
|
|
54
|
+
|
|
55
|
+
&--salesforce {
|
|
56
|
+
background: #0d9dda;
|
|
57
|
+
}
|
|
42
58
|
}
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
const activeCampaign = (
|
|
2
2
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
3
3
|
<path
|
|
4
|
-
d="
|
|
5
|
-
fill="white"
|
|
6
|
-
/>
|
|
7
|
-
<path
|
|
8
|
-
d="M6.56445 8.77441C6.56445 8.35519 7.04853 8.12873 7.37109 8.35449L12.6611 11.9355L11.9512 12.4189C11.4996 12.7091 10.9193 12.7092 10.4678 12.4189L9.30664 11.6777L6.56445 9.83887V8.77441Z"
|
|
4
|
+
d="M17.28 10.4037C17.8244 10.7666 18.115 11.3468 18.115 11.9637C18.115 12.5805 17.788 13.1609 17.28 13.5238L5.88501 21V19.4399C5.88501 18.9681 6.10324 18.4965 6.5387 18.2062L15.9375 11.9637L6.5387 5.68506C6.13946 5.43097 5.88501 4.95947 5.88501 4.45129V3L17.28 10.4037ZM5.88501 8.37122C5.88501 7.89959 6.4296 7.64482 6.79248 7.8988L12.7438 11.9275L11.9451 12.4713C11.4371 12.7977 10.7842 12.7978 10.2762 12.4713L8.96997 11.6375L5.88501 9.56873V8.37122Z"
|
|
9
5
|
fill="white"
|
|
10
6
|
/>
|
|
11
7
|
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const beehiiv = (
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
3
|
+
<path
|
|
4
|
+
d="M18.6602 11.4894H5.35668C5.19293 11.4883 5.03627 11.4225 4.92088 11.3063C4.80549 11.1901 4.74073 11.033 4.74073 10.8692V9.92487C4.7398 9.67122 4.78886 9.41988 4.88509 9.1852C4.98132 8.95052 5.12284 8.73709 5.30157 8.55712C5.4803 8.37714 5.69274 8.23414 5.92675 8.13629C6.16076 8.03843 6.41176 7.98764 6.6654 7.9868H17.3353C17.5889 7.98754 17.8398 8.03822 18.0738 8.13595C18.3078 8.23368 18.5203 8.37654 18.6991 8.55637C18.8779 8.7362 19.0195 8.94949 19.1158 9.18406C19.2122 9.41862 19.2614 9.66987 19.2607 9.92346V10.8685C19.2638 10.9491 19.2506 11.0296 19.2218 11.1049C19.193 11.1803 19.1492 11.249 19.0931 11.307C19.0369 11.365 18.9697 11.411 18.8953 11.4422C18.8209 11.4734 18.7409 11.4899 18.6602 11.4894ZM15.8574 6.96492H8.15947C7.99191 6.96343 7.8317 6.89593 7.71361 6.77704C7.59552 6.65816 7.52908 6.4975 7.52872 6.32994C7.52872 4.74919 8.80643 3.46302 10.3773 3.46302H13.641C15.2119 3.46302 16.4896 4.74919 16.4896 6.32994C16.4907 6.41334 16.4752 6.49613 16.4439 6.57345C16.4126 6.65077 16.3662 6.72106 16.3074 6.7802C16.2486 6.83934 16.1785 6.88615 16.1014 6.91787C16.0243 6.94959 15.9416 6.96558 15.8582 6.96492H15.8574ZM19.2755 12.5113H4.74073C3.7858 12.5113 3 13.3013 3 14.2619C3 15.2225 3.7858 16.0132 4.74073 16.0132H9.89879C10.0834 15.0216 10.9453 14.2619 11.9919 14.2619C12.4923 14.2631 12.9767 14.4386 13.3618 14.7582C13.7468 15.0778 14.0085 15.5216 14.1019 16.0132H19.2607C20.2149 16.0132 21 15.2225 21 14.2619C21 13.3013 20.2304 12.5113 19.2755 12.5113ZM18.6454 17.0358H14.1336V20.537H17.5214C18.4756 20.537 19.2607 19.7477 19.2607 18.7864V17.6708C19.2636 17.5882 19.2499 17.506 19.2202 17.4289C19.1906 17.3518 19.1457 17.2816 19.0883 17.2223C19.0308 17.163 18.962 17.1159 18.8859 17.0838C18.8098 17.0518 18.728 17.0354 18.6454 17.0358ZM5.35668 17.0358C5.189 17.0371 5.02861 17.1045 4.91037 17.2234C4.79213 17.3423 4.72559 17.5031 4.72523 17.6708V18.7864C4.72523 19.747 5.51102 20.537 6.46596 20.537H9.85298V17.0358H5.35668Z"
|
|
5
|
+
fill="white"
|
|
6
|
+
/>
|
|
7
|
+
</svg>
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
export default beehiiv;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const gravityForms = (
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
3
|
+
<path
|
|
4
|
+
d="M8.74072 8.98989H24V4.73383H8.77618C6.75022 4.67092 4.79489 5.46964 3.41 6.92583C0.0886559 10.4377 0 19.2696 0 19.2696H23.8818V11.2749H19.5912V15.0019H4.58018C4.67474 13.6123 5.31889 11.1296 6.53633 9.84462C7.10785 9.25496 7.91399 8.9424 8.74072 8.98989Z"
|
|
5
|
+
fill="white"
|
|
6
|
+
/>
|
|
7
|
+
</svg>
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
export default gravityForms;
|
|
@@ -7,23 +7,34 @@ import { atSymbol } from '@wordpress/icons';
|
|
|
7
7
|
* Internal dependencies
|
|
8
8
|
*/
|
|
9
9
|
import activeCampaign from './active-campaign';
|
|
10
|
+
import beehiiv from './beehiiv';
|
|
10
11
|
import constantContact from './constant-contact';
|
|
12
|
+
import fundraiseUp from './fundraise-up';
|
|
13
|
+
import gravityForms from './gravity-forms';
|
|
11
14
|
import mailchimp from './mailchimp';
|
|
15
|
+
import salesforce from './salesforce';
|
|
12
16
|
|
|
13
17
|
export { default as activeCampaign } from './active-campaign';
|
|
18
|
+
export { default as beehiiv } from './beehiiv';
|
|
14
19
|
export { default as constantContact } from './constant-contact';
|
|
15
20
|
export { default as fundraiseUp } from './fundraise-up';
|
|
21
|
+
export { default as gravityForms } from './gravity-forms';
|
|
16
22
|
export { default as mailchimp } from './mailchimp';
|
|
17
23
|
export { default as salesforce } from './salesforce';
|
|
18
24
|
export { default as wisepops } from './wisepops';
|
|
19
25
|
|
|
20
|
-
//
|
|
21
|
-
// (`Newspack_Newsletters::service_provider()`)
|
|
22
|
-
|
|
26
|
+
// Brand marks keyed by the ESP slug the backend reports
|
|
27
|
+
// (`Newspack_Newsletters::service_provider()`), by integration ID, or by the
|
|
28
|
+
// brand slug an integration maps to. Rendered via IntegrationIcon.
|
|
29
|
+
export const providerIcons = {
|
|
23
30
|
active_campaign: activeCampaign,
|
|
24
31
|
mailchimp,
|
|
25
32
|
constant_contact: constantContact,
|
|
26
33
|
manual: atSymbol,
|
|
34
|
+
salesforce,
|
|
35
|
+
beehiiv,
|
|
36
|
+
fundraiseup: fundraiseUp,
|
|
37
|
+
gravity_forms: gravityForms,
|
|
27
38
|
};
|
|
28
39
|
|
|
29
40
|
export const espProviderOrder = [ 'active_campaign', 'mailchimp', 'constant_contact', 'manual' ];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const salesforce = (
|
|
2
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
3
3
|
<path
|
|
4
|
-
d="
|
|
5
|
-
fill="
|
|
4
|
+
d="M10.0838 5.745C10.8213 4.9775 11.8463 4.5 12.9813 4.5C14.4913 4.5 15.8063 5.3425 16.5088 6.59C17.1188 6.3175 17.7938 6.165 18.5013 6.165C21.2238 6.165 23.4288 8.39 23.4288 11.1375C23.4288 13.885 21.2213 16.11 18.5013 16.11C18.1688 16.11 17.8438 16.0775 17.5313 16.0125C16.9138 17.1125 15.7363 17.8575 14.3863 17.8575C13.8213 17.8575 13.2863 17.7275 12.8113 17.495C12.1863 18.9675 10.7263 20 9.02876 20C7.33126 20 5.75126 18.88 5.17126 17.31C4.91876 17.3625 4.65626 17.3925 4.38626 17.3925C2.27876 17.3925 0.571259 15.6675 0.571259 13.5375C0.571259 12.11 1.33876 10.865 2.47876 10.1975C2.24376 9.6575 2.11376 9.06 2.11376 8.435C2.11376 5.985 4.10126 4 6.55376 4C7.99376 4 9.27376 4.685 10.0838 5.745Z"
|
|
5
|
+
fill="white"
|
|
6
6
|
/>
|
|
7
7
|
</svg>
|
|
8
8
|
);
|
package/src/notice/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* WordPress dependencies.
|
|
7
7
|
*/
|
|
8
8
|
import { Component, RawHTML } from '@wordpress/element';
|
|
9
|
-
import { Icon,
|
|
9
|
+
import { Icon, check, help, info } from '@wordpress/icons';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Internal dependencies.
|
|
@@ -23,23 +23,10 @@ class Notice extends Component {
|
|
|
23
23
|
* Render
|
|
24
24
|
*/
|
|
25
25
|
render() {
|
|
26
|
-
const {
|
|
27
|
-
className,
|
|
28
|
-
debugMode,
|
|
29
|
-
isError,
|
|
30
|
-
isHandoff,
|
|
31
|
-
isHelp,
|
|
32
|
-
isSuccess,
|
|
33
|
-
isWarning,
|
|
34
|
-
noticeText,
|
|
35
|
-
rawHTML,
|
|
36
|
-
style = {},
|
|
37
|
-
children = null,
|
|
38
|
-
} = this.props;
|
|
26
|
+
const { className, isError, isHandoff, isHelp, isSuccess, isWarning, noticeText, rawHTML, style = {}, children = null } = this.props;
|
|
39
27
|
const classes = classnames(
|
|
40
28
|
'newspack-notice',
|
|
41
29
|
className,
|
|
42
|
-
debugMode && 'newspack-notice__is-debug',
|
|
43
30
|
isError && 'newspack-notice__is-error',
|
|
44
31
|
isHandoff && 'newspack-notice__is-handoff',
|
|
45
32
|
isHelp && 'newspack-notice__is-help',
|
|
@@ -51,8 +38,6 @@ class Notice extends Component {
|
|
|
51
38
|
noticeIcon = help;
|
|
52
39
|
} else if ( isSuccess ) {
|
|
53
40
|
noticeIcon = check;
|
|
54
|
-
} else if ( debugMode ) {
|
|
55
|
-
noticeIcon = bug;
|
|
56
41
|
} else {
|
|
57
42
|
noticeIcon = info;
|
|
58
43
|
}
|
package/src/notice/style.scss
CHANGED
|
@@ -22,25 +22,6 @@
|
|
|
22
22
|
margin-right: 4px;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
&__is-debug {
|
|
26
|
-
background: np-colors.$primary-600;
|
|
27
|
-
border-radius: 50%;
|
|
28
|
-
bottom: 16px;
|
|
29
|
-
box-shadow: 0 0 8px 4px rgba(black, 0.08);
|
|
30
|
-
color: white;
|
|
31
|
-
font-weight: bold;
|
|
32
|
-
margin: 0 16px;
|
|
33
|
-
padding: 6px;
|
|
34
|
-
position: fixed;
|
|
35
|
-
text-transform: uppercase;
|
|
36
|
-
z-index: 9997;
|
|
37
|
-
|
|
38
|
-
> svg {
|
|
39
|
-
fill: white;
|
|
40
|
-
margin: 0;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
25
|
&__is-error {
|
|
45
26
|
background: color.adjust(wp-colors.$alert-red, $lightness: 35%);
|
|
46
27
|
|
|
@@ -99,7 +99,7 @@ class PluginToggle extends Component {
|
|
|
99
99
|
toggleChecked={ this.isPluginInstalledAndActive( plugin ) }
|
|
100
100
|
toggleOnChange={ value => this.managePlugin( slug, value ) }
|
|
101
101
|
notification={ error }
|
|
102
|
-
notificationHTML
|
|
102
|
+
notificationHTML
|
|
103
103
|
notificationLevel="error"
|
|
104
104
|
/>
|
|
105
105
|
);
|
|
@@ -6,7 +6,7 @@ import { cloneElement } from '@wordpress/element';
|
|
|
6
6
|
/**
|
|
7
7
|
* Internal dependencies
|
|
8
8
|
*/
|
|
9
|
-
import { Button,
|
|
9
|
+
import { Button, DebugBadge, Handoff, HandoffMessage, TabbedNavigation, Page } from '../';
|
|
10
10
|
import { activeBreadcrumbs } from '../wizard/breadcrumbs-select';
|
|
11
11
|
import { buttonProps } from '../button-props';
|
|
12
12
|
import Router from '../proxied-imports/router';
|
|
@@ -112,7 +112,7 @@ export default function withWizardScreen( WrappedComponent, { hidePrimaryButton,
|
|
|
112
112
|
}
|
|
113
113
|
return (
|
|
114
114
|
<>
|
|
115
|
-
|
|
115
|
+
<DebugBadge />
|
|
116
116
|
{ hideHeader ? (
|
|
117
117
|
// Without the Page shell the tabs still own the content: it
|
|
118
118
|
// renders inside the active tab's panel.
|