@automattic/jetpack-components 0.39.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/.gitattributes +8 -0
- package/CHANGELOG.md +747 -0
- package/LICENSE.txt +357 -0
- package/README.md +11 -0
- package/SECURITY.md +38 -0
- package/components/action-button/index.jsx +70 -0
- package/components/action-button/stories/index.stories.jsx +38 -0
- package/components/action-button/style.module.scss +11 -0
- package/components/action-button/test/component.jsx +16 -0
- package/components/action-popover/index.tsx +105 -0
- package/components/action-popover/stories/index.stories.jsx +115 -0
- package/components/action-popover/stories/styles.module.scss +7 -0
- package/components/action-popover/styles.module.scss +49 -0
- package/components/action-popover/types.ts +20 -0
- package/components/admin-page/index.tsx +58 -0
- package/components/admin-page/stories/index.stories.tsx +35 -0
- package/components/admin-page/stories/style.module.scss +13 -0
- package/components/admin-page/style.module.scss +11 -0
- package/components/admin-page/types.ts +41 -0
- package/components/admin-section/basic/index.tsx +15 -0
- package/components/admin-section/basic/style.module.scss +3 -0
- package/components/admin-section/hero/index.tsx +15 -0
- package/components/admin-section/hero/style.module.scss +3 -0
- package/components/admin-section/stories/index.stories.tsx +60 -0
- package/components/admin-section/types.ts +6 -0
- package/components/alert/index.tsx +61 -0
- package/components/alert/stories/index.stories.jsx +24 -0
- package/components/alert/style.module.scss +43 -0
- package/components/automattic-byline-logo/README.md +16 -0
- package/components/automattic-byline-logo/index.tsx +38 -0
- package/components/automattic-byline-logo/stories/index.stories.tsx +20 -0
- package/components/automattic-byline-logo/test/component.tsx +28 -0
- package/components/automattic-byline-logo/types.ts +18 -0
- package/components/boost-score-bar/index.tsx +103 -0
- package/components/boost-score-bar/stories/index.stories.tsx +39 -0
- package/components/boost-score-bar/style.scss +184 -0
- package/components/boost-score-bar/test/component.tsx +102 -0
- package/components/boost-score-bar/types.ts +9 -0
- package/components/button/index.tsx +84 -0
- package/components/button/stories/index.mdx +90 -0
- package/components/button/stories/index.stories.tsx +400 -0
- package/components/button/stories/style.module.scss +20 -0
- package/components/button/style.module.scss +212 -0
- package/components/button/types.ts +21 -0
- package/components/contextual-upgrade-trigger/README.md +81 -0
- package/components/contextual-upgrade-trigger/index.tsx +44 -0
- package/components/contextual-upgrade-trigger/stories/index.stories.tsx +25 -0
- package/components/contextual-upgrade-trigger/style.module.scss +75 -0
- package/components/contextual-upgrade-trigger/types.ts +9 -0
- package/components/decorative-card/index.tsx +44 -0
- package/components/decorative-card/stories/index.stories.tsx +18 -0
- package/components/decorative-card/style.scss +116 -0
- package/components/decorative-card/types.ts +16 -0
- package/components/dialog/index.tsx +69 -0
- package/components/dialog/stories/boost.png +0 -0
- package/components/dialog/stories/declaration.d.ts +1 -0
- package/components/dialog/stories/index.stories.tsx +118 -0
- package/components/dialog/stories/js-components.components.dialog.mdx +62 -0
- package/components/dialog/stories/js-components.components.dialog.stories.js +37 -0
- package/components/dialog/stories/style.module.scss +21 -0
- package/components/dialog/style.module.scss +30 -0
- package/components/donut-meter/index.tsx +147 -0
- package/components/donut-meter/stories/index.stories.tsx +51 -0
- package/components/donut-meter/style.scss +11 -0
- package/components/donut-meter/test/component.tsx +24 -0
- package/components/gridicon/index.tsx +298 -0
- package/components/gridicon/stories/index.stories.tsx +18 -0
- package/components/gridicon/style.scss +16 -0
- package/components/gridicon/types.ts +48 -0
- package/components/icon-tooltip/index.tsx +96 -0
- package/components/icon-tooltip/stories/index.stories.tsx +108 -0
- package/components/icon-tooltip/stories/style.scss +36 -0
- package/components/icon-tooltip/style.scss +121 -0
- package/components/icon-tooltip/test/component.tsx +15 -0
- package/components/icon-tooltip/types.ts +76 -0
- package/components/icons/README.md +98 -0
- package/components/icons/index.tsx +369 -0
- package/components/icons/stories/index.stories.tsx +65 -0
- package/components/icons/stories/style.module.scss +33 -0
- package/components/icons/style.module.scss +40 -0
- package/components/icons/types.ts +38 -0
- package/components/indeterminate-progress-bar/index.tsx +28 -0
- package/components/indeterminate-progress-bar/stories/index.stories.tsx +14 -0
- package/components/indeterminate-progress-bar/style.module.scss +34 -0
- package/components/indeterminate-progress-bar/types.ts +6 -0
- package/components/jetpack-footer/README.md +21 -0
- package/components/jetpack-footer/index.tsx +94 -0
- package/components/jetpack-footer/stories/index.stories.tsx +40 -0
- package/components/jetpack-footer/style.scss +116 -0
- package/components/jetpack-footer/test/component.tsx +45 -0
- package/components/jetpack-footer/types.ts +36 -0
- package/components/jetpack-logo/README.md +20 -0
- package/components/jetpack-logo/index.tsx +46 -0
- package/components/jetpack-logo/stories/index.stories.tsx +20 -0
- package/components/jetpack-logo/test/component.tsx +16 -0
- package/components/jetpack-logo/types.ts +7 -0
- package/components/jetpack-search-logo/README.md +20 -0
- package/components/jetpack-search-logo/index.tsx +93 -0
- package/components/jetpack-search-logo/stories/index.stories.tsx +21 -0
- package/components/jetpack-search-logo/test/component.tsx +16 -0
- package/components/jetpack-search-logo/types.ts +7 -0
- package/components/jetpack-vaultpress-backup-logo/README.md +19 -0
- package/components/jetpack-vaultpress-backup-logo/index.tsx +113 -0
- package/components/jetpack-vaultpress-backup-logo/stories/index.stories.tsx +20 -0
- package/components/jetpack-vaultpress-backup-logo/test/component.tsx +18 -0
- package/components/jetpack-vaultpress-backup-logo/types.ts +6 -0
- package/components/jetpack-videopress-logo/README.md +19 -0
- package/components/jetpack-videopress-logo/index.tsx +93 -0
- package/components/jetpack-videopress-logo/stories/index.stories.tsx +20 -0
- package/components/jetpack-videopress-logo/test/component.tsx +16 -0
- package/components/jetpack-videopress-logo/types.tsx +6 -0
- package/components/layout/README.md +9 -0
- package/components/layout/breakpoints.module.scss +20 -0
- package/components/layout/col/README.md +81 -0
- package/components/layout/col/index.tsx +49 -0
- package/components/layout/col/style.module.scss +28 -0
- package/components/layout/container/README.md +77 -0
- package/components/layout/container/index.tsx +42 -0
- package/components/layout/container/style.module.scss +35 -0
- package/components/layout/stories/index.stories.tsx +145 -0
- package/components/layout/stories/styles.module.scss +22 -0
- package/components/layout/types.ts +55 -0
- package/components/layout/use-breakpoint-match/README.md +43 -0
- package/components/layout/use-breakpoint-match/declaration.d.ts +9 -0
- package/components/layout/use-breakpoint-match/index.ts +79 -0
- package/components/loading-placeholder/README.md +22 -0
- package/components/loading-placeholder/index.tsx +23 -0
- package/components/loading-placeholder/stories/index.stories.tsx +78 -0
- package/components/loading-placeholder/style.module.scss +18 -0
- package/components/notice/index.tsx +98 -0
- package/components/notice/stories/index.stories.jsx +90 -0
- package/components/notice/style.module.scss +107 -0
- package/components/number-format/README.md +25 -0
- package/components/number-format/index.ts +16 -0
- package/components/pricing-card/index.tsx +127 -0
- package/components/pricing-card/stories/index.stories.tsx +55 -0
- package/components/pricing-card/style.scss +112 -0
- package/components/pricing-card/test/component.tsx +89 -0
- package/components/pricing-card/types.ts +52 -0
- package/components/pricing-slider/index.tsx +53 -0
- package/components/pricing-slider/stories/index.stories.tsx +44 -0
- package/components/pricing-slider/style.scss +55 -0
- package/components/pricing-slider/test/component.tsx +14 -0
- package/components/pricing-slider/types.ts +58 -0
- package/components/pricing-table/index.tsx +200 -0
- package/components/pricing-table/stories/index.stories.tsx +74 -0
- package/components/pricing-table/styles.module.scss +160 -0
- package/components/pricing-table/test/component.tsx +41 -0
- package/components/pricing-table/types.ts +84 -0
- package/components/product-offer/icons-card.tsx +47 -0
- package/components/product-offer/index.tsx +115 -0
- package/components/product-offer/product-offer-header.tsx +23 -0
- package/components/product-offer/stories/index.stories.tsx +104 -0
- package/components/product-offer/style.module.scss +93 -0
- package/components/product-offer/types.ts +125 -0
- package/components/product-price/index.tsx +90 -0
- package/components/product-price/price.tsx +35 -0
- package/components/product-price/stories/index.stories.tsx +33 -0
- package/components/product-price/style.module.scss +69 -0
- package/components/product-price/test/component.tsx +26 -0
- package/components/product-price/types.ts +73 -0
- package/components/qr-code/Readme.md +5 -0
- package/components/qr-code/index.tsx +78 -0
- package/components/qr-code/stories/index.stories.tsx +32 -0
- package/components/record-meter-bar/index.tsx +135 -0
- package/components/record-meter-bar/stories/index.stories.tsx +39 -0
- package/components/record-meter-bar/style.scss +38 -0
- package/components/record-meter-bar/test/component.tsx +52 -0
- package/components/spinner/README.md +28 -0
- package/components/spinner/index.jsx +45 -0
- package/components/spinner/stories/index.stories.jsx +20 -0
- package/components/spinner/style.scss +31 -0
- package/components/spinner/test/component.jsx +17 -0
- package/components/split-button/index.tsx +39 -0
- package/components/split-button/stories/index.stories.tsx +35 -0
- package/components/split-button/style.module.scss +21 -0
- package/components/split-button/types.ts +14 -0
- package/components/stat-card/index.tsx +49 -0
- package/components/stat-card/stories/index.mdx +35 -0
- package/components/stat-card/stories/index.stories.tsx +41 -0
- package/components/stat-card/style.module.scss +49 -0
- package/components/stat-card/test/component.tsx +24 -0
- package/components/stat-card/types.ts +28 -0
- package/components/status/README.md +42 -0
- package/components/status/index.tsx +40 -0
- package/components/status/stories/index.stories.tsx +44 -0
- package/components/status/style.module.scss +72 -0
- package/components/terms-of-service/index.tsx +63 -0
- package/components/terms-of-service/styles.scss +10 -0
- package/components/terms-of-service/test/index.test.jsx +52 -0
- package/components/terms-of-service/types.ts +30 -0
- package/components/testimonials/index.tsx +58 -0
- package/components/testimonials/style.scss +127 -0
- package/components/testimonials/test/component.tsx +103 -0
- package/components/testimonials/testimonial.tsx +47 -0
- package/components/testimonials/types.ts +17 -0
- package/components/text/constants.ts +30 -0
- package/components/text/index.tsx +91 -0
- package/components/text/stories/headings.index.stories.tsx +80 -0
- package/components/text/stories/index.mdx +195 -0
- package/components/text/stories/index.stories.tsx +69 -0
- package/components/text/stories/style.module.scss +64 -0
- package/components/text/stories/title.index.stories.tsx +34 -0
- package/components/text/style.module.scss +125 -0
- package/components/text/types.ts +53 -0
- package/components/theme-provider/Readme.md +49 -0
- package/components/theme-provider/globals.module.scss +6 -0
- package/components/theme-provider/index.tsx +151 -0
- package/components/theme-provider/stories/index.stories.tsx +164 -0
- package/components/theme-provider/stories/style.module.scss +79 -0
- package/components/theme-provider/types.ts +25 -0
- package/components/toggle-control/README.md +5 -0
- package/components/toggle-control/index.tsx +67 -0
- package/components/toggle-control/stories/index.stories.tsx +83 -0
- package/components/toggle-control/styles.module.scss +41 -0
- package/components/zendesk-chat/README.md +26 -0
- package/components/zendesk-chat/constants.ts +2 -0
- package/components/zendesk-chat/index.tsx +22 -0
- package/components/zendesk-chat/stories/index.stories.tsx +15 -0
- package/components/zendesk-chat/test/component.tsx +16 -0
- package/components/zendesk-chat/types.ts +3 -0
- package/index.ts +69 -0
- package/lib/locale/index.ts +48 -0
- package/lib/locale/test/index.ts +21 -0
- package/package.json +80 -0
- package/tools/get-product-checkout-url/Readme.md +32 -0
- package/tools/get-product-checkout-url/index.ts +31 -0
- package/tools/jp-redirect/README.md +61 -0
- package/tools/jp-redirect/index.ts +62 -0
- package/tools/jp-redirect/test/index.tsx +89 -0
- package/tools/jp-redirect/types.ts +49 -0
- package/tools/pricing-utils/README.md +16 -0
- package/tools/pricing-utils/index.ts +11 -0
- package/tools/pricing-utils/test/index.ts +39 -0
- package/tools/pricing-utils/types.ts +12 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* eslint-disable react/react-in-jsx-scope */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import Spinner from '../index.jsx';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'JS Packages/Components/Spinner',
|
|
7
|
+
component: Spinner,
|
|
8
|
+
argTypes: {
|
|
9
|
+
color: { control: 'color' },
|
|
10
|
+
},
|
|
11
|
+
parameters: {
|
|
12
|
+
backgrounds: {
|
|
13
|
+
default: 'dark',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const Template = args => <Spinner { ...args } />;
|
|
19
|
+
|
|
20
|
+
export const _default = Template.bind( {} );
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
@keyframes rotate-spinner {
|
|
2
|
+
100% {
|
|
3
|
+
transform: rotate( 360deg );
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.jp-components-spinner {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.jp-components-spinner__outer, .jp-components-spinner__inner {
|
|
13
|
+
margin: auto;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
border: 0.1em solid transparent;
|
|
16
|
+
border-radius: 50%;
|
|
17
|
+
animation: 3s linear infinite;
|
|
18
|
+
animation-name: rotate-spinner;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.jp-components-spinner__outer {
|
|
22
|
+
border-top-color: white;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.jp-components-spinner__inner {
|
|
26
|
+
width: 100%;
|
|
27
|
+
height: 100%;
|
|
28
|
+
border-top-color: white;
|
|
29
|
+
border-right-color: white;
|
|
30
|
+
opacity: 0.4;
|
|
31
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import Spinner from '../index';
|
|
3
|
+
|
|
4
|
+
describe( 'Spinner', () => {
|
|
5
|
+
const testProps = {
|
|
6
|
+
className: 'sample-classname',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
describe( 'Render the Spinner component', () => {
|
|
10
|
+
const { container } = render( <Spinner { ...testProps } /> );
|
|
11
|
+
|
|
12
|
+
it( 'validate the class name', () => {
|
|
13
|
+
// eslint-disable-next-line testing-library/no-node-access
|
|
14
|
+
expect( container.firstChild ).toHaveClass( 'sample-classname' );
|
|
15
|
+
} );
|
|
16
|
+
} );
|
|
17
|
+
} );
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ButtonGroup, Button, DropdownMenu } from '@wordpress/components';
|
|
2
|
+
import styles from './style.module.scss';
|
|
3
|
+
import { SplitButtonProps } from './types';
|
|
4
|
+
import type React from 'react';
|
|
5
|
+
|
|
6
|
+
const DownIcon = () => (
|
|
7
|
+
<svg width="15" height="9" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="10 9 4 7">
|
|
8
|
+
<path
|
|
9
|
+
fillRule="evenodd"
|
|
10
|
+
clipRule="evenodd"
|
|
11
|
+
d="m18.004 10.555-6.005 5.459-6.004-5.459 1.009-1.11 4.995 4.542 4.996-4.542 1.009 1.11Z"
|
|
12
|
+
/>
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const SplitButton: React.FC< SplitButtonProps > = ( {
|
|
17
|
+
variant,
|
|
18
|
+
controls,
|
|
19
|
+
popoverProps,
|
|
20
|
+
toggleProps,
|
|
21
|
+
label,
|
|
22
|
+
...buttonProps
|
|
23
|
+
} ) => {
|
|
24
|
+
return (
|
|
25
|
+
<ButtonGroup className={ styles[ 'split-button' ] }>
|
|
26
|
+
<Button variant={ variant } { ...buttonProps } className={ styles.button } />
|
|
27
|
+
<DropdownMenu
|
|
28
|
+
toggleProps={ { variant, className: styles.button, ...toggleProps } }
|
|
29
|
+
popoverProps={ { noArrow: false, ...popoverProps } }
|
|
30
|
+
icon={ <DownIcon /> }
|
|
31
|
+
disableOpenOnArrowDown={ true }
|
|
32
|
+
controls={ controls }
|
|
33
|
+
label={ label }
|
|
34
|
+
/>
|
|
35
|
+
</ButtonGroup>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default SplitButton;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import SplitButton from '../index';
|
|
2
|
+
import type { ComponentStory, ComponentMeta } from '@storybook/react';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'JS Packages/Components/Split Button',
|
|
6
|
+
component: SplitButton,
|
|
7
|
+
argTypes: {
|
|
8
|
+
variant: { type: 'select', options: [ undefined, 'secondary', 'primary', 'tertiary', 'link' ] },
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
controls: [
|
|
12
|
+
{
|
|
13
|
+
title: 'Add to cart',
|
|
14
|
+
icon: null,
|
|
15
|
+
onClick: () => null,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
title: 'Add to wishlist',
|
|
19
|
+
icon: null,
|
|
20
|
+
onClick: () => null,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
parameters: {
|
|
25
|
+
backgrounds: {
|
|
26
|
+
default: 'dark',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
} as ComponentMeta< typeof SplitButton >;
|
|
30
|
+
|
|
31
|
+
const Template: ComponentStory< typeof SplitButton > = args => (
|
|
32
|
+
<SplitButton { ...args }>Buy now!</SplitButton>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
export const _default = Template.bind( {} );
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.split-button {
|
|
2
|
+
--actions-size: 28px;
|
|
3
|
+
display: flex;
|
|
4
|
+
height: var(--actions-size);
|
|
5
|
+
border-radius: var(--jp-border-radius);
|
|
6
|
+
|
|
7
|
+
& > .button:first-child {
|
|
8
|
+
border-radius: var(--jp-border-radius) 0 0 var(--jp-border-radius);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
& > :global(.components-dropdown) > .button {
|
|
12
|
+
border-radius: 0 var(--jp-border-radius) var(--jp-border-radius) 0;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.button {
|
|
17
|
+
font-size: var(--font-body-extra-small);
|
|
18
|
+
border-radius: var(--jp-border-radius);
|
|
19
|
+
height: var(--actions-size);
|
|
20
|
+
line-height: var(--actions-size);
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import type { Button, DropdownMenu } from '@wordpress/components';
|
|
5
|
+
|
|
6
|
+
type AllowedDropdownMenuProps = Pick<
|
|
7
|
+
React.ComponentProps< typeof DropdownMenu >,
|
|
8
|
+
'controls' | 'popoverProps' | 'toggleProps' | 'label'
|
|
9
|
+
>;
|
|
10
|
+
|
|
11
|
+
export type SplitButtonProps = Omit< React.ComponentProps< typeof Button >, 'controls' > &
|
|
12
|
+
AllowedDropdownMenuProps &
|
|
13
|
+
// make `controls` prop required
|
|
14
|
+
Required< Pick< AllowedDropdownMenuProps, 'controls' > >;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { Tooltip } from '@wordpress/components';
|
|
5
|
+
import classnames from 'classnames';
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import numberFormat from '../number-format';
|
|
10
|
+
import Text from '../text';
|
|
11
|
+
import styles from './style.module.scss';
|
|
12
|
+
import { StatCardProps } from './types';
|
|
13
|
+
import type React from 'react';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* StatCard component
|
|
17
|
+
*
|
|
18
|
+
* @param {StatCardProps} props - Component props.
|
|
19
|
+
* @returns {React.ReactNode} - StatCard react component.
|
|
20
|
+
*/
|
|
21
|
+
const StatCard = ( { className, icon, label, value, variant = 'square' }: StatCardProps ) => {
|
|
22
|
+
const formattedValue = numberFormat( value );
|
|
23
|
+
const compactValue = numberFormat( value, {
|
|
24
|
+
notation: 'compact',
|
|
25
|
+
compactDisplay: 'short',
|
|
26
|
+
} );
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className={ classnames( className, styles.wrapper, styles[ variant ] ) }>
|
|
30
|
+
<div className={ classnames( styles.icon ) }>{ icon }</div>
|
|
31
|
+
<div className={ classnames( styles.info ) }>
|
|
32
|
+
<Text className={ styles.label }>{ label }</Text>
|
|
33
|
+
{ variant === 'square' ? (
|
|
34
|
+
<Tooltip text={ formattedValue } position="top center">
|
|
35
|
+
<Text variant="headline-small" className={ classnames( styles.value ) }>
|
|
36
|
+
{ compactValue }
|
|
37
|
+
</Text>
|
|
38
|
+
</Tooltip>
|
|
39
|
+
) : (
|
|
40
|
+
<Text variant="title-medium-semi-bold" className={ classnames( styles.value ) }>
|
|
41
|
+
{ formattedValue }
|
|
42
|
+
</Text>
|
|
43
|
+
) }
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default StatCard;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Meta, Story, Canvas } from '@storybook/addon-docs';
|
|
2
|
+
import StatCard from '../index';
|
|
3
|
+
import * as StatCardStories from './index.stories';
|
|
4
|
+
|
|
5
|
+
<Meta of={StatCardStories} />
|
|
6
|
+
|
|
7
|
+
# StatCard
|
|
8
|
+
|
|
9
|
+
Component that shows a stat value.
|
|
10
|
+
|
|
11
|
+
## API
|
|
12
|
+
|
|
13
|
+
### icon
|
|
14
|
+
|
|
15
|
+
- type: `JSX.Element`
|
|
16
|
+
|
|
17
|
+
### label
|
|
18
|
+
|
|
19
|
+
- type: `string`
|
|
20
|
+
|
|
21
|
+
### value
|
|
22
|
+
|
|
23
|
+
- type: `number`
|
|
24
|
+
|
|
25
|
+
### variant
|
|
26
|
+
|
|
27
|
+
- type: `string`
|
|
28
|
+
- default: `"square"`
|
|
29
|
+
|
|
30
|
+
It accepts 2 values: `square` and `horizontal`.
|
|
31
|
+
|
|
32
|
+
<Canvas withSource="open">
|
|
33
|
+
<Story id="js-packages-components-stat-card--default" />
|
|
34
|
+
<Story id="js-packages-components-stat-card--horizontal" />
|
|
35
|
+
</Canvas>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Icon, postList } from '@wordpress/icons';
|
|
2
|
+
import StatCard from '..';
|
|
3
|
+
import type { ComponentStory, ComponentMeta } from '@storybook/react';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'JS Packages/Components/Stat Card',
|
|
7
|
+
component: StatCard,
|
|
8
|
+
argTypes: {
|
|
9
|
+
variant: {
|
|
10
|
+
control: { type: 'radio' },
|
|
11
|
+
options: [ 'square', 'horizontal' ],
|
|
12
|
+
},
|
|
13
|
+
label: {
|
|
14
|
+
control: { type: 'text' },
|
|
15
|
+
},
|
|
16
|
+
value: {
|
|
17
|
+
control: { type: 'number' },
|
|
18
|
+
},
|
|
19
|
+
icon: {
|
|
20
|
+
table: {
|
|
21
|
+
disable: true,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
} as ComponentMeta< typeof StatCard >;
|
|
26
|
+
|
|
27
|
+
const defaultArgs = {
|
|
28
|
+
icon: <Icon icon={ postList } color="green" />,
|
|
29
|
+
label: 'Posted this month',
|
|
30
|
+
value: 1806,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const Template: ComponentStory< typeof StatCard > = args => {
|
|
34
|
+
return <StatCard { ...args } />;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const _default = Template.bind( {} );
|
|
38
|
+
_default.args = defaultArgs;
|
|
39
|
+
|
|
40
|
+
export const Horizontal = Template.bind( {} );
|
|
41
|
+
Horizontal.args = { ...defaultArgs, variant: 'horizontal' };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
.wrapper {
|
|
2
|
+
background-color: var( --jp-white );
|
|
3
|
+
box-shadow: 0px 4px 40px rgba(0, 0, 0, 0.08);
|
|
4
|
+
border-radius: calc( var( --jp-border-radius ) * 2 ); // 8px;
|
|
5
|
+
display: flex;
|
|
6
|
+
|
|
7
|
+
&.horizontal {
|
|
8
|
+
align-items: center;
|
|
9
|
+
padding: calc( var( --spacing-base ) * 2 ); // 16px;
|
|
10
|
+
width: 358px;
|
|
11
|
+
|
|
12
|
+
.info {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
width: 100%;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.label {
|
|
20
|
+
margin: 0 calc( var( --spacing-base ) * 2 ); // 16px;
|
|
21
|
+
flex-grow: 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
&.square {
|
|
26
|
+
--square-stat-vertical-spacing: calc( var( --spacing-base ) * 2 ); // 16px;
|
|
27
|
+
--square-stat-horizontal-spacing: calc( var( --spacing-base ) * 3 ); // 24px;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
justify-content: space-between;
|
|
30
|
+
height: 168px;
|
|
31
|
+
width: 168px;
|
|
32
|
+
padding: var( --square-stat-vertical-spacing ) var( --square-stat-horizontal-spacing );
|
|
33
|
+
|
|
34
|
+
.label {
|
|
35
|
+
margin-bottom: calc( var( --spacing-base ) / 2 ); // 4px;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.value {
|
|
40
|
+
overflow: hidden;
|
|
41
|
+
text-overflow: ellipsis;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.icon {
|
|
45
|
+
display: flex;
|
|
46
|
+
color: var( --jp-green-40 );
|
|
47
|
+
fill: var( --jp-green-40 );
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import StatCard from '../index';
|
|
3
|
+
|
|
4
|
+
describe( 'StatCard', () => {
|
|
5
|
+
const testProps = {
|
|
6
|
+
icon: <div></div>,
|
|
7
|
+
label: 'Label',
|
|
8
|
+
value: 1806,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
describe( 'when using the square variant', () => {
|
|
12
|
+
it( 'renders the compact value', () => {
|
|
13
|
+
render( <StatCard { ...testProps } variant="square" /> );
|
|
14
|
+
expect( screen.getByText( '1.8K' ) ).toBeInTheDocument();
|
|
15
|
+
} );
|
|
16
|
+
} );
|
|
17
|
+
|
|
18
|
+
describe( 'when using the horizontal variant', () => {
|
|
19
|
+
it( 'renders the full value', () => {
|
|
20
|
+
render( <StatCard { ...testProps } variant="horizontal" /> );
|
|
21
|
+
expect( screen.getByText( '1,806' ) ).toBeInTheDocument();
|
|
22
|
+
} );
|
|
23
|
+
} );
|
|
24
|
+
} );
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type StatCardProps = {
|
|
2
|
+
/**
|
|
3
|
+
* Custom className to be inserted.
|
|
4
|
+
*/
|
|
5
|
+
className?: string;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The stat card icon.
|
|
9
|
+
*/
|
|
10
|
+
icon: JSX.Element;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The stat label.
|
|
14
|
+
*/
|
|
15
|
+
label: string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The stat value.
|
|
19
|
+
*/
|
|
20
|
+
value: number;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The component variant.
|
|
24
|
+
*
|
|
25
|
+
* @default 'square'
|
|
26
|
+
*/
|
|
27
|
+
variant?: 'square' | 'horizontal';
|
|
28
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
= Status
|
|
2
|
+
|
|
3
|
+
A simple component to display a status indicator.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```jsx
|
|
8
|
+
import { Status } from '@automattic/jetpack-components';
|
|
9
|
+
|
|
10
|
+
function MyComponent() {
|
|
11
|
+
return (
|
|
12
|
+
<>
|
|
13
|
+
{ /* Default status is "inactive". */}
|
|
14
|
+
<Status />
|
|
15
|
+
|
|
16
|
+
{ /* You can also pass a status prop to display a different status. */}
|
|
17
|
+
<Status status="active" />
|
|
18
|
+
|
|
19
|
+
{ /* You can also pass a label prop to display a label beside the status indicator. */}
|
|
20
|
+
<Status status="error" label="Connection Error" />
|
|
21
|
+
</>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Props
|
|
27
|
+
|
|
28
|
+
### status
|
|
29
|
+
|
|
30
|
+
Optional. The status to display. It can be one of the following:
|
|
31
|
+
|
|
32
|
+
- `active`
|
|
33
|
+
- `inactive`
|
|
34
|
+
- `error`
|
|
35
|
+
|
|
36
|
+
Defaults to `inactive`.
|
|
37
|
+
|
|
38
|
+
### label
|
|
39
|
+
|
|
40
|
+
Optional. The label to display beside the status indicator.
|
|
41
|
+
|
|
42
|
+
If none is provided, the name of the status will be used by default (i.e. "Active"). Pass an empty string to hide the label.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { __ } from '@wordpress/i18n';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import Text from '../text';
|
|
4
|
+
import styles from './style.module.scss';
|
|
5
|
+
|
|
6
|
+
interface StatusProps {
|
|
7
|
+
status?: 'active' | 'error' | 'inactive' | 'action' | 'initializing';
|
|
8
|
+
label?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Status = ( { className, label, status = 'inactive' }: StatusProps ): JSX.Element => {
|
|
13
|
+
const defaultLabels: Record< string, string > = {
|
|
14
|
+
active: __( 'Active', 'jetpack' ),
|
|
15
|
+
error: __( 'Error', 'jetpack' ),
|
|
16
|
+
action: __( 'Action needed', 'jetpack' ),
|
|
17
|
+
inactive: __( 'Inactive', 'jetpack' ),
|
|
18
|
+
initializing: __( 'Setting up', 'jetpack' ),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Text
|
|
23
|
+
variant="body-extra-small"
|
|
24
|
+
className={ classNames(
|
|
25
|
+
styles.status,
|
|
26
|
+
{
|
|
27
|
+
[ styles[ `is-${ status }` ] ]: status,
|
|
28
|
+
},
|
|
29
|
+
className
|
|
30
|
+
) }
|
|
31
|
+
>
|
|
32
|
+
<span className={ styles.status__indicator } />
|
|
33
|
+
<span className={ styles.status__label }>
|
|
34
|
+
{ label || label === '' ? label : defaultLabels[ status ] }
|
|
35
|
+
</span>
|
|
36
|
+
</Text>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default Status;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Status from '..';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'JS Packages/Components/Status',
|
|
5
|
+
component: Status,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'centered',
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
12
|
+
export const Active = args => {
|
|
13
|
+
return <Status status="active" />;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
17
|
+
export const Error = args => {
|
|
18
|
+
return <Status status="error" />;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
22
|
+
export const ActionNeeded = args => {
|
|
23
|
+
return <Status status="action" />;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
27
|
+
export const Initializing = args => {
|
|
28
|
+
return <Status status="initializing" />;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
32
|
+
export const Inactive = args => {
|
|
33
|
+
return <Status status="inactive" />;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
37
|
+
export const CustomLabel = args => {
|
|
38
|
+
return <Status label="Code is poetry" />;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
42
|
+
export const NoLabel = args => {
|
|
43
|
+
return <Status status="active" label="" />;
|
|
44
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
.status {
|
|
2
|
+
--spacing-base: 8px;
|
|
3
|
+
--wp-admin-border-width-focus: 1.5px;
|
|
4
|
+
|
|
5
|
+
align-items: center;
|
|
6
|
+
display: flex;
|
|
7
|
+
white-space: nowrap;
|
|
8
|
+
|
|
9
|
+
&__indicator {
|
|
10
|
+
background-color: var( --jp-gray-50 );
|
|
11
|
+
border-radius: 50%;
|
|
12
|
+
flex-shrink: 0;
|
|
13
|
+
height: 0.666em;
|
|
14
|
+
width: 0.666em;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&__label {
|
|
18
|
+
font-weight: 600;
|
|
19
|
+
line-height: 1.666;
|
|
20
|
+
margin-left: calc( var( --spacing-base ) / 2 ); // 4px
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&.is-active {
|
|
24
|
+
span, a {
|
|
25
|
+
color: var(--jp-green-50);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.status__indicator {
|
|
29
|
+
background-color: var( --jp-green-50 );
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&.is-inactive {
|
|
34
|
+
span, a {
|
|
35
|
+
color: var(--jp-gray-50);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.status__indicator {
|
|
39
|
+
background-color: var( --jp-gray-50 );
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&.is-error {
|
|
44
|
+
span, a {
|
|
45
|
+
color: var(--jp-red-50);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.status__indicator {
|
|
49
|
+
background-color: var( --jp-red-50 );
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
&.is-action {
|
|
54
|
+
span, a {
|
|
55
|
+
color: var(--jp-yellow-30);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.status__indicator {
|
|
59
|
+
background-color: var( --jp-yellow-30 );
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&.is-initializing {
|
|
64
|
+
span, a {
|
|
65
|
+
color: var(--jp-blue-40);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.status__indicator {
|
|
69
|
+
background-color: var( --jp-blue-40 );
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createInterpolateElement } from '@wordpress/element';
|
|
2
|
+
import { __, sprintf } from '@wordpress/i18n';
|
|
3
|
+
import classNames from 'classnames';
|
|
4
|
+
import { getRedirectUrl } from '../../../components';
|
|
5
|
+
import Text from '../text';
|
|
6
|
+
import type { TermsOfServiceProps } from './types';
|
|
7
|
+
import './styles.scss';
|
|
8
|
+
|
|
9
|
+
const TermsOfService: React.FC< TermsOfServiceProps > = ( {
|
|
10
|
+
className,
|
|
11
|
+
multipleButtons,
|
|
12
|
+
agreeButtonLabel,
|
|
13
|
+
} ) => (
|
|
14
|
+
<Text className={ classNames( className, 'terms-of-service' ) }>
|
|
15
|
+
{ multipleButtons ? (
|
|
16
|
+
<MultipleButtonsText />
|
|
17
|
+
) : (
|
|
18
|
+
<SingleButtonText agreeButtonLabel={ agreeButtonLabel } />
|
|
19
|
+
) }
|
|
20
|
+
</Text>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const MultipleButtonsText = () =>
|
|
24
|
+
createInterpolateElement(
|
|
25
|
+
__(
|
|
26
|
+
'By clicking the buttons above, you agree to our <tosLink>Terms of Service</tosLink> and to <shareDetailsLink>share details</shareDetailsLink> with WordPress.com.',
|
|
27
|
+
'jetpack'
|
|
28
|
+
),
|
|
29
|
+
{
|
|
30
|
+
tosLink: <Link slug="wpcom-tos" />,
|
|
31
|
+
shareDetailsLink: <Link slug="jetpack-support-what-data-does-jetpack-sync" />,
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const SingleButtonText = ( { agreeButtonLabel } ) =>
|
|
36
|
+
createInterpolateElement(
|
|
37
|
+
sprintf(
|
|
38
|
+
/* translators: %s is a button label */
|
|
39
|
+
__(
|
|
40
|
+
'By clicking the <strong>%s</strong> button, you agree to our <tosLink>Terms of Service</tosLink> and to <shareDetailsLink>share details</shareDetailsLink> with WordPress.com.',
|
|
41
|
+
'jetpack'
|
|
42
|
+
),
|
|
43
|
+
agreeButtonLabel
|
|
44
|
+
),
|
|
45
|
+
{
|
|
46
|
+
strong: <strong />,
|
|
47
|
+
tosLink: <Link slug="wpcom-tos" />,
|
|
48
|
+
shareDetailsLink: <Link slug="jetpack-support-what-data-does-jetpack-sync" />,
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const Link: React.FC< { slug: string; children?: React.ReactNode } > = ( { slug, children } ) => (
|
|
53
|
+
<a
|
|
54
|
+
className="terms-of-service__link"
|
|
55
|
+
href={ getRedirectUrl( slug ) }
|
|
56
|
+
rel="noopener noreferrer"
|
|
57
|
+
target="_blank"
|
|
58
|
+
>
|
|
59
|
+
{ children }
|
|
60
|
+
</a>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
export default TermsOfService;
|