@automattic/jetpack-components 3.2.0 → 4.0.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 +26 -0
- package/build/components/admin-page/style.module.scss +2 -2
- package/build/components/copy-to-clipboard/index.js +1 -1
- package/build/components/decorative-card/style.scss +4 -1
- package/build/components/diff-viewer/index.d.ts +2 -1
- package/build/components/global-notices/global-notices.d.ts +4 -0
- package/build/components/global-notices/global-notices.js +4 -0
- package/build/components/global-notices/use-global-notices.d.ts +3 -0
- package/build/components/global-notices/use-global-notices.js +3 -0
- package/build/components/gravatar/index.d.ts +1 -0
- package/build/components/icon-tooltip/index.js +37 -15
- package/build/components/icon-tooltip/style.scss +0 -8
- package/build/components/icon-tooltip/types.d.ts +4 -0
- package/build/components/jetpack-footer/style.scss +2 -5
- package/build/components/jitm-slot/index.d.ts +15 -0
- package/build/components/jitm-slot/index.js +52 -0
- package/build/components/jitm-slot/style.scss +16 -0
- package/build/components/jitm-slot/types.d.ts +10 -0
- package/build/components/text/style.module.scss +4 -4
- package/build/components/text/types.d.ts +4 -4
- package/build/components/theme-provider/index.js +1 -1
- package/build/index.d.ts +1 -2
- package/build/index.js +1 -2
- package/components/admin-page/style.module.scss +2 -2
- package/components/copy-to-clipboard/index.tsx +2 -2
- package/components/decorative-card/style.scss +4 -1
- package/components/diff-viewer/index.tsx +1 -0
- package/components/global-notices/README.md +25 -0
- package/components/global-notices/global-notices.tsx +4 -0
- package/components/global-notices/use-global-notices.ts +3 -0
- package/components/gravatar/index.tsx +1 -0
- package/components/icon-tooltip/index.tsx +49 -18
- package/components/icon-tooltip/style.scss +0 -8
- package/components/icon-tooltip/types.ts +5 -0
- package/components/jetpack-footer/style.scss +2 -5
- package/components/jitm-slot/index.tsx +67 -0
- package/components/jitm-slot/style.scss +16 -0
- package/components/jitm-slot/types.ts +10 -0
- package/components/text/style.module.scss +4 -4
- package/components/text/types.ts +4 -4
- package/components/theme-provider/index.tsx +1 -1
- package/index.ts +1 -2
- package/package.json +12 -7
- package/build/components/notice/index.d.ts +0 -29
- package/build/components/notice/index.js +0 -35
- package/build/components/notice/style.module.scss +0 -120
- package/build/components/zendesk-chat/constants.d.ts +0 -1
- package/build/components/zendesk-chat/constants.js +0 -2
- package/build/components/zendesk-chat/index.d.ts +0 -3
- package/build/components/zendesk-chat/index.js +0 -27
- package/build/components/zendesk-chat/types.d.ts +0 -11
- package/components/notice/index.tsx +0 -93
- package/components/notice/style.module.scss +0 -120
- package/components/zendesk-chat/README.md +0 -25
- package/components/zendesk-chat/constants.ts +0 -2
- package/components/zendesk-chat/index.tsx +0 -34
- package/components/zendesk-chat/types.ts +0 -14
- /package/build/components/{zendesk-chat → jitm-slot}/types.js +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { speak } from '@wordpress/a11y';
|
|
1
2
|
import { Popover } from '@wordpress/components';
|
|
2
3
|
import { focus } from '@wordpress/dom';
|
|
3
4
|
import { Icon, info } from '@wordpress/icons';
|
|
@@ -43,6 +44,7 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
43
44
|
placement = 'bottom-end',
|
|
44
45
|
animate = true,
|
|
45
46
|
iconCode = info,
|
|
47
|
+
label,
|
|
46
48
|
iconSize = 18,
|
|
47
49
|
offset = 10,
|
|
48
50
|
title,
|
|
@@ -62,7 +64,7 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
62
64
|
const [ hoverTimeout, setHoverTimeout ] = useState( null );
|
|
63
65
|
const wrapperRef = useRef< HTMLDivElement >( null );
|
|
64
66
|
const popoverRef = useRef< HTMLDivElement >( null );
|
|
65
|
-
const triggerRef = useRef<
|
|
67
|
+
const triggerRef = useRef< HTMLElement >( null );
|
|
66
68
|
const hasTextTrigger = trigger !== undefined;
|
|
67
69
|
// Where focus should land after Tab leaves the tooltip. The effect below applies it, rather
|
|
68
70
|
// than the handler, because Popover puts focus back on the trigger as it unmounts.
|
|
@@ -80,14 +82,17 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
80
82
|
[ isVisible, setIsVisible, onTriggerClick ]
|
|
81
83
|
);
|
|
82
84
|
|
|
83
|
-
// Focus can stay on
|
|
85
|
+
// Focus can stay on the trigger while its tooltip is open, so it handles the dialog keys too.
|
|
84
86
|
const handleTriggerKeyDown = useCallback(
|
|
85
|
-
( event: KeyboardEvent<
|
|
87
|
+
( event: KeyboardEvent< HTMLElement > ) => {
|
|
88
|
+
// A held key repeats activation, so only its first press toggles.
|
|
89
|
+
if ( event.repeat && ( event.key === 'Enter' || event.key === ' ' ) ) {
|
|
90
|
+
event.preventDefault();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
86
93
|
// A link only activates on Enter; a button also activates on Space.
|
|
87
|
-
if ( event.key === ' ' ) {
|
|
88
|
-
|
|
89
|
-
toggleTooltip( event );
|
|
90
|
-
}
|
|
94
|
+
if ( hasTextTrigger && event.key === ' ' ) {
|
|
95
|
+
toggleTooltip( event );
|
|
91
96
|
return;
|
|
92
97
|
}
|
|
93
98
|
if ( ! isVisible ) {
|
|
@@ -107,7 +112,7 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
107
112
|
}
|
|
108
113
|
}
|
|
109
114
|
},
|
|
110
|
-
[ isVisible, hideTooltip, toggleTooltip ]
|
|
115
|
+
[ hasTextTrigger, isVisible, hideTooltip, toggleTooltip ]
|
|
111
116
|
);
|
|
112
117
|
|
|
113
118
|
const isAnchorWrapper = popoverAnchorStyle === 'wrapper';
|
|
@@ -151,10 +156,6 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
151
156
|
[ hideTooltip ]
|
|
152
157
|
);
|
|
153
158
|
|
|
154
|
-
const focusOnOpen =
|
|
155
|
-
isForcedToShow || ( hasTextTrigger && ! openedByHover.current )
|
|
156
|
-
? 'firstElement'
|
|
157
|
-
: ! openedByHover.current;
|
|
158
159
|
const args = {
|
|
159
160
|
// To be compatible with deprecating prop `position`.
|
|
160
161
|
position: placementsToPositions( placement ),
|
|
@@ -164,9 +165,9 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
164
165
|
resize: false,
|
|
165
166
|
flip: false,
|
|
166
167
|
offset, // The distance (in px) between the anchor and the popover.
|
|
167
|
-
//
|
|
168
|
-
//
|
|
169
|
-
focusOnMount:
|
|
168
|
+
// Focus stays on the trigger, which handles the dialog keys; a caller-controlled popover
|
|
169
|
+
// has no trigger, so it focuses its first button instead.
|
|
170
|
+
focusOnMount: isForcedToShow ? 'firstElement' : false,
|
|
170
171
|
// Tab moves through the popover in document order rather than cycling inside it, and
|
|
171
172
|
// handlePopoverKeyDown decides where it lands on the way out.
|
|
172
173
|
constrainTabbing: false,
|
|
@@ -174,7 +175,7 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
174
175
|
ref: popoverRef,
|
|
175
176
|
onClose: () => {
|
|
176
177
|
const popover = popoverRef.current;
|
|
177
|
-
if (
|
|
178
|
+
if ( popover?.contains( popover.ownerDocument.activeElement ) ) {
|
|
178
179
|
focusAfterClose.current = triggerRef.current;
|
|
179
180
|
}
|
|
180
181
|
hideTooltip();
|
|
@@ -215,6 +216,21 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
215
216
|
return () => doc?.removeEventListener( 'pointerdown', handlePointerDown );
|
|
216
217
|
}, [ isVisible, isForcedToShow, closeOnClickOutside, hideTooltip ] );
|
|
217
218
|
|
|
219
|
+
// Hover leaves focus elsewhere, so Escape is watched directly to keep the content dismissible.
|
|
220
|
+
useEffect( () => {
|
|
221
|
+
if ( ! isVisible || ! openedByHover.current ) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const doc = wrapperRef.current?.ownerDocument;
|
|
225
|
+
const handleKeyDown = ( event: globalThis.KeyboardEvent ) => {
|
|
226
|
+
if ( event.key === 'Escape' ) {
|
|
227
|
+
hideTooltip();
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
doc?.addEventListener( 'keydown', handleKeyDown );
|
|
231
|
+
return () => doc?.removeEventListener( 'keydown', handleKeyDown );
|
|
232
|
+
}, [ isVisible, hideTooltip ] );
|
|
233
|
+
|
|
218
234
|
useEffect( () => {
|
|
219
235
|
if ( isForcedToShow || isVisible ) {
|
|
220
236
|
return;
|
|
@@ -224,6 +240,14 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
224
240
|
destination?.focus();
|
|
225
241
|
}, [ isForcedToShow, isVisible ] );
|
|
226
242
|
|
|
243
|
+
// Focus stays on the trigger, so a screen reader hears the popover through an announcement.
|
|
244
|
+
useEffect( () => {
|
|
245
|
+
const popover = popoverRef.current;
|
|
246
|
+
if ( isVisible && ! openedByHover.current && popover ) {
|
|
247
|
+
speak( popover.innerText ?? popover.textContent, 'polite' );
|
|
248
|
+
}
|
|
249
|
+
}, [ isVisible ] );
|
|
250
|
+
|
|
227
251
|
const handleMouseEnter = useCallback( () => {
|
|
228
252
|
if ( hoverShow ) {
|
|
229
253
|
if ( hoverTimeout ) {
|
|
@@ -270,7 +294,7 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
270
294
|
<>
|
|
271
295
|
{ /* A link, not a button, so it keeps the host page's link styling. */ }
|
|
272
296
|
<a
|
|
273
|
-
ref={ triggerRef }
|
|
297
|
+
ref={ triggerRef as React.RefObject< HTMLAnchorElement > }
|
|
274
298
|
href="#"
|
|
275
299
|
role="button"
|
|
276
300
|
className="icon-tooltip-trigger"
|
|
@@ -286,7 +310,14 @@ const IconTooltip: FC< IconTooltipProps > = ( {
|
|
|
286
310
|
</>
|
|
287
311
|
) }
|
|
288
312
|
{ ! hasTextTrigger && ! isAnchorWrapper && (
|
|
289
|
-
<Button
|
|
313
|
+
<Button
|
|
314
|
+
ref={ triggerRef }
|
|
315
|
+
variant="link"
|
|
316
|
+
aria-label={ label }
|
|
317
|
+
aria-expanded={ isVisible }
|
|
318
|
+
onClick={ toggleTooltip }
|
|
319
|
+
onKeyDown={ handleTriggerKeyDown }
|
|
320
|
+
>
|
|
290
321
|
<Icon className={ iconClassName } icon={ iconCode } size={ iconSize } />
|
|
291
322
|
</Button>
|
|
292
323
|
) }
|
|
@@ -107,14 +107,6 @@ $arrow-color: var(--jp-gray);
|
|
|
107
107
|
.icon-tooltip-container {
|
|
108
108
|
// Recover events
|
|
109
109
|
pointer-events: all;
|
|
110
|
-
// Takes focus on open, but its box is wider than the visible content,
|
|
111
|
-
// so the ring goes on the content instead.
|
|
112
|
-
outline: none;
|
|
113
|
-
|
|
114
|
-
&:focus-visible .components-popover__content {
|
|
115
|
-
outline: var(--wp-admin-border-width-focus, 2px) solid var(--wp-admin-theme-color, #3858e9);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
110
|
// __content styles here covers both the inline and portal modes
|
|
119
111
|
.components-popover__content {
|
|
120
112
|
padding: 24px;
|
|
@@ -41,6 +41,11 @@ export type IconTooltipProps = {
|
|
|
41
41
|
*/
|
|
42
42
|
iconCode?: ComponentProps< typeof Icon >[ 'icon' ];
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The accessible name of the icon button. Ignored when `trigger` is set, since its text names it.
|
|
46
|
+
*/
|
|
47
|
+
label?: string;
|
|
48
|
+
|
|
44
49
|
/**
|
|
45
50
|
* The title of Popover.
|
|
46
51
|
*/
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
@use "sass:meta";
|
|
2
|
-
@include meta.load-css("pkg:@wordpress/theme/design-tokens.css");
|
|
3
|
-
|
|
4
1
|
.jetpack-footer {
|
|
5
|
-
border-top: var(--wpds-border-width-xs
|
|
2
|
+
border-top: var(--wpds-border-width-xs) solid var(--wpds-color-stroke-surface-neutral-weak);
|
|
6
3
|
box-sizing: border-box;
|
|
7
|
-
font-size: var(--wpds-typography-font-size-md
|
|
4
|
+
font-size: var(--wpds-typography-font-size-md);
|
|
8
5
|
padding: var(--wpds-dimension-padding-xl) var(--wpds-dimension-padding-2xl);
|
|
9
6
|
width: 100%;
|
|
10
7
|
display: flex;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import { useLayoutEffect, useRef } from 'react';
|
|
3
|
+
import './style.scss';
|
|
4
|
+
import type { JitmSlotProps } from './types.ts';
|
|
5
|
+
import type { JSX, FC } from 'react';
|
|
6
|
+
|
|
7
|
+
const NOTICES_ID = 'jp-admin-notices';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Returns the page's one `#jp-admin-notices`, creating it on first use.
|
|
11
|
+
*
|
|
12
|
+
* Found through the DOM, not a module variable: each wp-build route bundles its own copy
|
|
13
|
+
* of this module.
|
|
14
|
+
*
|
|
15
|
+
* @return {HTMLElement} The element.
|
|
16
|
+
*/
|
|
17
|
+
const getNotices = (): HTMLElement => {
|
|
18
|
+
let element = document.getElementById( NOTICES_ID );
|
|
19
|
+
if ( ! element ) {
|
|
20
|
+
element = document.createElement( 'div' );
|
|
21
|
+
element.id = NOTICES_ID;
|
|
22
|
+
}
|
|
23
|
+
return element;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Hosts the element the JITM script re-parents its card into.
|
|
28
|
+
*
|
|
29
|
+
* The JITM script places its card once per page load, so the element outlives any
|
|
30
|
+
* one slot: an unmounted slot parks it, hidden, and the next slot takes it back.
|
|
31
|
+
* `className` is for width and alignment; `style.scss` owns spacing.
|
|
32
|
+
*
|
|
33
|
+
* @param {JitmSlotProps} props - Component props.
|
|
34
|
+
* @return {JSX.Element} The slot.
|
|
35
|
+
*/
|
|
36
|
+
const JitmSlot: FC< JitmSlotProps > = ( { className, inset } ) => {
|
|
37
|
+
const ref = useRef< HTMLDivElement >( null );
|
|
38
|
+
|
|
39
|
+
useLayoutEffect( () => {
|
|
40
|
+
const host = ref.current;
|
|
41
|
+
if ( ! host ) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const element = getNotices();
|
|
46
|
+
element.hidden = false;
|
|
47
|
+
host.appendChild( element );
|
|
48
|
+
|
|
49
|
+
return () => {
|
|
50
|
+
// A slot that mounted before this one unmounted may already hold it.
|
|
51
|
+
if ( element.parentNode === host ) {
|
|
52
|
+
element.hidden = true;
|
|
53
|
+
document.body.appendChild( element );
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}, [] );
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div
|
|
60
|
+
ref={ ref }
|
|
61
|
+
className={ clsx( 'jp-jitm-slot', { 'jp-jitm-slot--inset': inset }, className ) }
|
|
62
|
+
data-testid="jp-jitm-slot"
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default JitmSlot;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// The slot is always rendered and usually empty, so it takes no space
|
|
2
|
+
// of its own; spacing sits on the card so a dismissed one leaves no gap.
|
|
3
|
+
.jp-jitm-slot {
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
|
|
7
|
+
// `jitm-card` comes from packages/jitm/src/js/jetpack-jitm.js.
|
|
8
|
+
.jitm-card {
|
|
9
|
+
margin: var(--wpds-dimension-gap-xl) 0;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Same specificity as the rule above, so it has to come after it.
|
|
14
|
+
.jp-jitm-slot--inset .jitm-card {
|
|
15
|
+
margin-inline: var(--wpds-dimension-padding-2xl);
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type JitmSlotProps = {
|
|
2
|
+
/**
|
|
3
|
+
* Layout the dashboard owns: width, column span, centering. Not spacing.
|
|
4
|
+
*/
|
|
5
|
+
className?: string;
|
|
6
|
+
/**
|
|
7
|
+
* The slot sits outside the page's padded container, so the card takes the page gutter.
|
|
8
|
+
*/
|
|
9
|
+
inset?: boolean;
|
|
10
|
+
};
|
|
@@ -89,9 +89,9 @@ $props: (
|
|
|
89
89
|
|
|
90
90
|
$sides: (
|
|
91
91
|
"top": "t",
|
|
92
|
-
"
|
|
92
|
+
"inline-end": "r",
|
|
93
93
|
"bottom": "b",
|
|
94
|
-
"
|
|
94
|
+
"inline-start": "l",
|
|
95
95
|
);
|
|
96
96
|
|
|
97
97
|
@each $prop, $p in $props {
|
|
@@ -106,8 +106,8 @@ $sides: (
|
|
|
106
106
|
|
|
107
107
|
/* mx, px */
|
|
108
108
|
.#{$p}x-#{$size} {
|
|
109
|
-
#{$prop}-
|
|
110
|
-
#{$prop}-
|
|
109
|
+
#{$prop}-inline-start: calc(var(--spacing-base) * #{$size});
|
|
110
|
+
#{$prop}-inline-end: calc(var(--spacing-base) * #{$size});
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
.#{$p}y-#{$size} {
|
package/components/text/types.ts
CHANGED
|
@@ -9,11 +9,11 @@ export type TextProps = {
|
|
|
9
9
|
m?: SpacingValue;
|
|
10
10
|
/** margin-top */
|
|
11
11
|
mt?: SpacingValue;
|
|
12
|
-
/** margin-right */
|
|
12
|
+
/** margin-inline-end (right in LTR) */
|
|
13
13
|
mr?: SpacingValue;
|
|
14
14
|
/** margin-bottom */
|
|
15
15
|
mb?: SpacingValue;
|
|
16
|
-
/** margin-left */
|
|
16
|
+
/** margin-inline-start (left in LTR) */
|
|
17
17
|
ml?: SpacingValue;
|
|
18
18
|
/** margin left and right */
|
|
19
19
|
mx?: SpacingValue;
|
|
@@ -23,11 +23,11 @@ export type TextProps = {
|
|
|
23
23
|
p?: SpacingValue;
|
|
24
24
|
/** padding-top */
|
|
25
25
|
pt?: SpacingValue;
|
|
26
|
-
/** padding-right */
|
|
26
|
+
/** padding-inline-end (right in LTR) */
|
|
27
27
|
pr?: SpacingValue;
|
|
28
28
|
/** padding-bottom */
|
|
29
29
|
pb?: SpacingValue;
|
|
30
|
-
/** padding-left */
|
|
30
|
+
/** padding-inline-start (left in LTR) */
|
|
31
31
|
pl?: SpacingValue;
|
|
32
32
|
/** padding left and right */
|
|
33
33
|
px?: SpacingValue;
|
|
@@ -121,7 +121,7 @@ const ThemeProvider: FC< ThemeProviderProps > = ( {
|
|
|
121
121
|
id,
|
|
122
122
|
withGlobalStyles = true,
|
|
123
123
|
} ) => {
|
|
124
|
-
const themeWrapperRef = useRef< HTMLDivElement >();
|
|
124
|
+
const themeWrapperRef = useRef< HTMLDivElement >( undefined );
|
|
125
125
|
|
|
126
126
|
// Check whether the theme provider instance is already registered.
|
|
127
127
|
const isAlreadyProvided = globalThemeInstances?.[ id ]?.provided;
|
package/index.ts
CHANGED
|
@@ -35,6 +35,7 @@ export { default as Col } from './components/layout/col/index.tsx';
|
|
|
35
35
|
export { default as Testimonials } from './components/testimonials/index.tsx';
|
|
36
36
|
export { default as Container } from './components/layout/container/index.tsx';
|
|
37
37
|
export { default as CopyToClipboard } from './components/copy-to-clipboard/index.tsx';
|
|
38
|
+
export { default as JitmSlot } from './components/jitm-slot/index.tsx';
|
|
38
39
|
export * from './components/icons/index.tsx';
|
|
39
40
|
export { default as ThemeProvider } from './components/theme-provider/index.tsx';
|
|
40
41
|
export { default as Text, H2, H3, Title } from './components/text/index.tsx';
|
|
@@ -56,11 +57,9 @@ export { default as ProductPrice } from './components/product-price/index.tsx';
|
|
|
56
57
|
export { default as DotPager } from './components/dot-pager/index.tsx';
|
|
57
58
|
export { default as DonutMeter } from './components/donut-meter/index.tsx';
|
|
58
59
|
export { default as RecordMeterBar } from './components/record-meter-bar/index.tsx';
|
|
59
|
-
export { default as Notice } from './components/notice/index.tsx';
|
|
60
60
|
export { default as Popover } from './components/popover/index.tsx';
|
|
61
61
|
export { default as IndeterminateProgressBar } from './components/indeterminate-progress-bar/index.tsx';
|
|
62
62
|
export { default as ActionPopover } from './components/action-popover/index.tsx';
|
|
63
|
-
export { default as ZendeskChat } from './components/zendesk-chat/index.tsx';
|
|
64
63
|
export { default as ProgressBar } from './components/progress-bar/index.tsx';
|
|
65
64
|
export { default as UpsellBanner } from './components/upsell-banner/index.tsx';
|
|
66
65
|
export { getUserLocale, cleanLocale } from './lib/locale/index.ts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/jetpack-components",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Jetpack Components Package",
|
|
5
5
|
"homepage": "https://github.com/Automattic/jetpack/tree/HEAD/projects/js-packages/components/#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -46,6 +46,10 @@
|
|
|
46
46
|
"types": "./build/components/jetpack-logo/index.d.ts",
|
|
47
47
|
"default": "./build/components/jetpack-logo/index.js"
|
|
48
48
|
},
|
|
49
|
+
"./jitm-slot": {
|
|
50
|
+
"types": "./build/components/jitm-slot/index.d.ts",
|
|
51
|
+
"default": "./build/components/jitm-slot/index.js"
|
|
52
|
+
},
|
|
49
53
|
"./pricing-table": {
|
|
50
54
|
"types": "./build/components/pricing-table/index.d.ts",
|
|
51
55
|
"default": "./build/components/pricing-table/index.js"
|
|
@@ -72,12 +76,13 @@
|
|
|
72
76
|
"extends @wordpress/browserslist-config"
|
|
73
77
|
],
|
|
74
78
|
"dependencies": {
|
|
75
|
-
"@automattic/jetpack-api": "^2.
|
|
76
|
-
"@automattic/jetpack-boost-score-api": "^1.
|
|
79
|
+
"@automattic/jetpack-api": "^2.1.0",
|
|
80
|
+
"@automattic/jetpack-boost-score-api": "^1.2.0",
|
|
77
81
|
"@automattic/jetpack-script-data": "^0.6.8",
|
|
78
|
-
"@automattic/number-formatters": "^1.2.
|
|
82
|
+
"@automattic/number-formatters": "^1.2.10",
|
|
79
83
|
"@babel/runtime": "^7",
|
|
80
84
|
"@gravatar-com/hovercards": "0.16.0",
|
|
85
|
+
"@wordpress/a11y": "4.55.0",
|
|
81
86
|
"@wordpress/admin-ui": "2.10.0",
|
|
82
87
|
"@wordpress/browserslist-config": "6.55.0",
|
|
83
88
|
"@wordpress/components": "40.1.0",
|
|
@@ -95,12 +100,12 @@
|
|
|
95
100
|
"js-sha256": "0.11.1",
|
|
96
101
|
"prop-types": "^15.7.2",
|
|
97
102
|
"qrcode.react": "4.2.0",
|
|
98
|
-
"social-logos": "^3.
|
|
103
|
+
"social-logos": "^3.4.0",
|
|
99
104
|
"uplot": "1.6.31",
|
|
100
105
|
"uplot-react": "1.1.4"
|
|
101
106
|
},
|
|
102
107
|
"devDependencies": {
|
|
103
|
-
"@automattic/jetpack-base-styles": "^1.2.
|
|
108
|
+
"@automattic/jetpack-base-styles": "^1.2.16",
|
|
104
109
|
"@babel/core": "7.29.7",
|
|
105
110
|
"@jest/globals": "30.5.1",
|
|
106
111
|
"@storybook/addon-docs": "10.4.6",
|
|
@@ -119,7 +124,7 @@
|
|
|
119
124
|
"storybook": "10.4.6",
|
|
120
125
|
"ts-dedent": "2.2.0",
|
|
121
126
|
"typescript": "6.0.3",
|
|
122
|
-
"webpack": "5.
|
|
127
|
+
"webpack": "5.111.1",
|
|
123
128
|
"webpack-cli": "7.2.1"
|
|
124
129
|
},
|
|
125
130
|
"peerDependencies": {
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { FC, ReactNode } from 'react';
|
|
2
|
-
type NoticeProps = {
|
|
3
|
-
/** The severity of the alert. */
|
|
4
|
-
level?: 'error' | 'warning' | 'info' | 'success';
|
|
5
|
-
/** The title of the notice */
|
|
6
|
-
title?: string;
|
|
7
|
-
/** A list of action elements to show across the bottom */
|
|
8
|
-
actions?: ReactNode[];
|
|
9
|
-
/** Hide close button */
|
|
10
|
-
hideCloseButton?: boolean;
|
|
11
|
-
/** Method to call when the close button is clicked */
|
|
12
|
-
onClose?: () => void;
|
|
13
|
-
/** Children to be rendered inside the alert. */
|
|
14
|
-
children: ReactNode;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Notice component
|
|
18
|
-
*
|
|
19
|
-
* @param {object} props - The component properties.
|
|
20
|
-
* @param {string} props.level - The notice level: error, warning, info, success.
|
|
21
|
-
* @param {boolean} props.hideCloseButton - Whether to hide the close button.
|
|
22
|
-
* @param {Function} props.onClose - The function to call when the close button is clicked.
|
|
23
|
-
* @param {string} props.title - The title of the notice.
|
|
24
|
-
* @param {ReactNode[]} props.actions - Actions to show across the bottom of the bar.
|
|
25
|
-
* @param {Component} props.children - The notice content.
|
|
26
|
-
* @return {ReactElement} The `Notice` component.
|
|
27
|
-
*/
|
|
28
|
-
declare const Notice: FC<NoticeProps>;
|
|
29
|
-
export default Notice;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Icon, cautionFilled as warning, info, check, close } from '@wordpress/icons';
|
|
3
|
-
import clsx from 'clsx';
|
|
4
|
-
import styles from './style.module.scss';
|
|
5
|
-
const getIconByLevel = (level) => {
|
|
6
|
-
switch (level) {
|
|
7
|
-
case 'error':
|
|
8
|
-
return warning;
|
|
9
|
-
case 'warning':
|
|
10
|
-
return warning;
|
|
11
|
-
case 'info':
|
|
12
|
-
return info;
|
|
13
|
-
case 'success':
|
|
14
|
-
return check;
|
|
15
|
-
default:
|
|
16
|
-
return warning;
|
|
17
|
-
}
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Notice component
|
|
21
|
-
*
|
|
22
|
-
* @param {object} props - The component properties.
|
|
23
|
-
* @param {string} props.level - The notice level: error, warning, info, success.
|
|
24
|
-
* @param {boolean} props.hideCloseButton - Whether to hide the close button.
|
|
25
|
-
* @param {Function} props.onClose - The function to call when the close button is clicked.
|
|
26
|
-
* @param {string} props.title - The title of the notice.
|
|
27
|
-
* @param {ReactNode[]} props.actions - Actions to show across the bottom of the bar.
|
|
28
|
-
* @param {Component} props.children - The notice content.
|
|
29
|
-
* @return {ReactElement} The `Notice` component.
|
|
30
|
-
*/
|
|
31
|
-
const Notice = ({ level = 'info', title, children, actions, hideCloseButton = false, onClose, }) => {
|
|
32
|
-
const classes = clsx(styles.container, styles[`is-${level}`]);
|
|
33
|
-
return (_jsxs("div", { className: classes, children: [_jsx("div", { className: styles['icon-wrapper'], children: _jsx(Icon, { icon: getIconByLevel(level), className: styles.icon }) }), _jsxs("div", { className: styles['main-content'], children: [title && _jsx("div", { className: styles.title, children: title }), children, actions && actions.length > 0 && (_jsx("div", { className: styles['action-bar'], children: actions.map((action, index) => (_jsx("div", { className: styles.action, children: action }, index))) }))] }), !hideCloseButton && (_jsx("button", { "aria-label": "close", className: styles['close-button'], onClick: onClose, children: _jsx(Icon, { icon: close }) }))] }));
|
|
34
|
-
};
|
|
35
|
-
export default Notice;
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
.container {
|
|
2
|
-
display: flex;
|
|
3
|
-
align-items: flex-start;
|
|
4
|
-
|
|
5
|
-
font-size: var(--font-body);
|
|
6
|
-
|
|
7
|
-
border: 1px solid var(--jp-black);
|
|
8
|
-
border-radius: 4px;
|
|
9
|
-
border-color: var(--jp-gray-5);
|
|
10
|
-
border-left-width: 6px;
|
|
11
|
-
|
|
12
|
-
padding: 24px 31px 27px 18px;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.icon-wrapper {
|
|
16
|
-
margin-right: 20px;
|
|
17
|
-
width: calc(var(--spacing-base) * 3);
|
|
18
|
-
height: calc(var(--spacing-base) * 3);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
.close-button {
|
|
22
|
-
padding: 0;
|
|
23
|
-
background-color: transparent;
|
|
24
|
-
border: none;
|
|
25
|
-
cursor: pointer;
|
|
26
|
-
outline: none;
|
|
27
|
-
|
|
28
|
-
svg {
|
|
29
|
-
display: block;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Mobile layout differences.
|
|
34
|
-
@media screen and ( max-width: 600px ) {
|
|
35
|
-
|
|
36
|
-
.container {
|
|
37
|
-
position: relative;
|
|
38
|
-
padding-top: 68px;
|
|
39
|
-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.03), 0 1px 2px rgba(0, 0, 0, 0.06);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.icon-wrapper {
|
|
43
|
-
position: absolute;
|
|
44
|
-
top: 24px;
|
|
45
|
-
left: 24px;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.close-button {
|
|
49
|
-
position: absolute;
|
|
50
|
-
top: 24px;
|
|
51
|
-
right: 24px;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.main-content {
|
|
56
|
-
flex-grow: 1;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.title {
|
|
60
|
-
font-weight: 600;
|
|
61
|
-
margin-bottom: 8px;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.action-bar {
|
|
65
|
-
display: flex;
|
|
66
|
-
align-items: center;
|
|
67
|
-
margin-top: 20px;
|
|
68
|
-
row-gap: 20px;
|
|
69
|
-
flex-wrap: wrap;
|
|
70
|
-
|
|
71
|
-
@media screen and ( max-width: 600px ) {
|
|
72
|
-
justify-content: center;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
a {
|
|
76
|
-
|
|
77
|
-
&,
|
|
78
|
-
&:hover,
|
|
79
|
-
&:active,
|
|
80
|
-
&:focus {
|
|
81
|
-
color: var(--jp-black);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
> * {
|
|
86
|
-
margin-right: 24px;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.is-error {
|
|
91
|
-
border-left-color: var(--jp-red);
|
|
92
|
-
|
|
93
|
-
.icon {
|
|
94
|
-
color: var(--jp-red);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.is-warning {
|
|
99
|
-
border-left-color: var(--jp-yellow-20);
|
|
100
|
-
|
|
101
|
-
.icon {
|
|
102
|
-
color: var(--jp-yellow-20);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.is-info {
|
|
107
|
-
border-left-color: var(--black);
|
|
108
|
-
|
|
109
|
-
.icon {
|
|
110
|
-
color: var(--black);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.is-success {
|
|
115
|
-
border-left-color: var(--jp-green);
|
|
116
|
-
|
|
117
|
-
.icon {
|
|
118
|
-
color: var(--jp-green);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const chatKey = "d729d42c-b547-4750-a6f6-8b30534a5f12";
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useCallback } from 'react';
|
|
3
|
-
import { chatKey } from './constants.js';
|
|
4
|
-
export const ZendeskChat = ({ jwt_token }) => {
|
|
5
|
-
const authenticateUser = useCallback(() => {
|
|
6
|
-
if (typeof window !== 'undefined' && typeof window.zE === 'function') {
|
|
7
|
-
window.zE('messenger', 'loginUser', function (callback) {
|
|
8
|
-
callback(jwt_token);
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
}, [jwt_token]);
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
const script = document.createElement('script');
|
|
14
|
-
const container = document.getElementById('zendesk-chat-container');
|
|
15
|
-
script.src = 'https://static.zdassets.com/ekr/snippet.js?key=' + encodeURIComponent(chatKey);
|
|
16
|
-
script.type = 'text/javascript';
|
|
17
|
-
script.id = 'ze-snippet';
|
|
18
|
-
script.onload = () => {
|
|
19
|
-
authenticateUser();
|
|
20
|
-
};
|
|
21
|
-
if (container) {
|
|
22
|
-
container.appendChild(script);
|
|
23
|
-
}
|
|
24
|
-
}, [authenticateUser]);
|
|
25
|
-
return _jsx("div", { "data-testid": "zendesk-chat-container", id: "zendesk-chat-container" });
|
|
26
|
-
};
|
|
27
|
-
export default ZendeskChat;
|