@codecademy/gamut 67.4.2-alpha.b3304f.0 → 67.4.2-alpha.b7c260.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/dist/Tip/InfoTip/InfoTipButton.js +5 -2
- package/dist/Tip/InfoTip/index.d.ts +8 -0
- package/dist/Tip/InfoTip/index.js +37 -65
- package/dist/Tip/__tests__/helpers.d.ts +3 -21
- package/dist/Tip/__tests__/mocks.d.ts +3 -1
- package/dist/Tip/shared/FloatingTip.js +3 -3
- package/dist/Tip/shared/InlineTip.js +4 -1
- package/dist/Tip/shared/types.d.ts +1 -1
- package/package.json +2 -2
- package/dist/Tip/InfoTip/elements.d.ts +0 -12
- package/dist/Tip/InfoTip/elements.js +0 -9
- package/dist/utils/react.d.ts +0 -18
- package/dist/utils/react.js +0 -36
|
@@ -8,14 +8,17 @@ export const InfoTipButton = /*#__PURE__*/forwardRef(({
|
|
|
8
8
|
active,
|
|
9
9
|
children,
|
|
10
10
|
emphasis,
|
|
11
|
+
'aria-label': ariaLabel,
|
|
12
|
+
'aria-labelledby': ariaLabelledby,
|
|
11
13
|
...props
|
|
12
14
|
}, ref) => {
|
|
13
15
|
const Icon = emphasis === 'high' ? MiniInfoCircleIcon : MiniInfoOutlineIcon;
|
|
14
16
|
return /*#__PURE__*/_jsxs(InfoTipButtonBase, {
|
|
17
|
+
...props,
|
|
15
18
|
active: active,
|
|
16
19
|
"aria-expanded": active,
|
|
17
|
-
"aria-label":
|
|
18
|
-
|
|
20
|
+
"aria-label": ariaLabel,
|
|
21
|
+
"aria-labelledby": ariaLabelledby,
|
|
19
22
|
ref: ref,
|
|
20
23
|
children: [Icon && /*#__PURE__*/_jsx(Icon, {
|
|
21
24
|
"aria-hidden": true,
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
import { TipBaseAlignment, TipBaseProps } from '../shared/types';
|
|
3
3
|
export type InfoTipProps = TipBaseProps & {
|
|
4
4
|
alignment?: TipBaseAlignment;
|
|
5
|
+
/**
|
|
6
|
+
* Accessible label for the InfoTip button. Its recommended to provide either `ariaLabel` or `ariaLabelledby`.
|
|
7
|
+
*/
|
|
8
|
+
ariaLabel?: string;
|
|
9
|
+
/**
|
|
10
|
+
* ID of an element that labels the InfoTip button. Its recommended to provide either `ariaLabel` or `ariaLabelledby`.
|
|
11
|
+
*/
|
|
12
|
+
ariaLabelledby?: string;
|
|
5
13
|
emphasis?: 'low' | 'high';
|
|
6
14
|
/**
|
|
7
15
|
* Called when the info tip is clicked - the onClick function is called after the DOM updates and the tip is mounted.
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { getFocusableElements as getFocusableElementsUtil } from '../../utils/focus';
|
|
3
|
-
import { extractTextContent } from '../../utils/react';
|
|
4
3
|
import { FloatingTip } from '../shared/FloatingTip';
|
|
5
4
|
import { InlineTip } from '../shared/InlineTip';
|
|
6
5
|
import { tipDefaultProps } from '../shared/types';
|
|
7
|
-
import { ScreenreaderNavigableText } from './elements';
|
|
8
6
|
import { InfoTipButton } from './InfoTipButton';
|
|
9
|
-
import { jsx as _jsx
|
|
10
|
-
const ARIA_HIDDEN_DELAY_MS = 1000;
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
8
|
const MODAL_SELECTOR = 'dialog[open],[role="dialog"],[role="alertdialog"]';
|
|
12
9
|
export const InfoTip = ({
|
|
13
10
|
alignment = 'top-right',
|
|
11
|
+
ariaLabel,
|
|
12
|
+
ariaLabelledby,
|
|
14
13
|
emphasis = 'low',
|
|
15
14
|
info,
|
|
16
15
|
onClick,
|
|
@@ -19,25 +18,14 @@ export const InfoTip = ({
|
|
|
19
18
|
}) => {
|
|
20
19
|
const isFloating = placement === 'floating';
|
|
21
20
|
const [isTipHidden, setHideTip] = useState(true);
|
|
22
|
-
const [isAriaHidden, setIsAriaHidden] = useState(false);
|
|
23
|
-
const [shouldAnnounce, setShouldAnnounce] = useState(false);
|
|
24
21
|
const [loaded, setLoaded] = useState(false);
|
|
25
22
|
const wrapperRef = useRef(null);
|
|
26
23
|
const buttonRef = useRef(null);
|
|
27
24
|
const popoverContentNodeRef = useRef(null);
|
|
28
25
|
const isInitialMount = useRef(true);
|
|
29
|
-
const ariaHiddenTimeoutRef = useRef(null);
|
|
30
|
-
const announceTimeoutRef = useRef(null);
|
|
31
26
|
const getFocusableElements = useCallback(() => {
|
|
32
27
|
return getFocusableElementsUtil(popoverContentNodeRef.current);
|
|
33
28
|
}, []);
|
|
34
|
-
const clearAndSetTimeout = useCallback((timeoutRef, callback, delay) => {
|
|
35
|
-
clearTimeout(timeoutRef.current ?? undefined);
|
|
36
|
-
timeoutRef.current = setTimeout(() => {
|
|
37
|
-
callback();
|
|
38
|
-
timeoutRef.current = null;
|
|
39
|
-
}, delay);
|
|
40
|
-
}, []);
|
|
41
29
|
const popoverContentRef = useCallback(node => {
|
|
42
30
|
popoverContentNodeRef.current = node;
|
|
43
31
|
if (node && !isTipHidden && isFloating) {
|
|
@@ -48,24 +36,10 @@ export const InfoTip = ({
|
|
|
48
36
|
}, [onClick, isTipHidden, isFloating]);
|
|
49
37
|
useEffect(() => {
|
|
50
38
|
setLoaded(true);
|
|
51
|
-
const ariaHiddenTimeout = ariaHiddenTimeoutRef.current;
|
|
52
|
-
const announceTimeout = announceTimeoutRef.current;
|
|
53
|
-
return () => {
|
|
54
|
-
clearTimeout(ariaHiddenTimeout ?? undefined);
|
|
55
|
-
clearTimeout(announceTimeout ?? undefined);
|
|
56
|
-
};
|
|
57
39
|
}, []);
|
|
58
40
|
const setTipIsHidden = useCallback(nextTipState => {
|
|
59
41
|
setHideTip(nextTipState);
|
|
60
|
-
|
|
61
|
-
clearAndSetTimeout(ariaHiddenTimeoutRef, () => setIsAriaHidden(true), ARIA_HIDDEN_DELAY_MS);
|
|
62
|
-
} else if (nextTipState) {
|
|
63
|
-
if (isAriaHidden) setIsAriaHidden(false);
|
|
64
|
-
setShouldAnnounce(false);
|
|
65
|
-
clearTimeout(ariaHiddenTimeoutRef.current ?? undefined);
|
|
66
|
-
ariaHiddenTimeoutRef.current = null;
|
|
67
|
-
}
|
|
68
|
-
}, [isAriaHidden, isFloating, clearAndSetTimeout]);
|
|
42
|
+
}, []);
|
|
69
43
|
const handleOutsideClick = useCallback(e => {
|
|
70
44
|
const wrapper = wrapperRef.current;
|
|
71
45
|
const isOutside = wrapper && (!(e.target instanceof HTMLElement) || !wrapper.contains(e.target));
|
|
@@ -76,10 +50,7 @@ export const InfoTip = ({
|
|
|
76
50
|
const clickHandler = useCallback(() => {
|
|
77
51
|
const currentTipState = !isTipHidden;
|
|
78
52
|
setTipIsHidden(currentTipState);
|
|
79
|
-
|
|
80
|
-
clearAndSetTimeout(announceTimeoutRef, () => setShouldAnnounce(true), 0);
|
|
81
|
-
}
|
|
82
|
-
}, [isTipHidden, setTipIsHidden, clearAndSetTimeout]);
|
|
53
|
+
}, [isTipHidden, setTipIsHidden]);
|
|
83
54
|
useLayoutEffect(() => {
|
|
84
55
|
if (isInitialMount.current) {
|
|
85
56
|
isInitialMount.current = false;
|
|
@@ -117,7 +88,18 @@ export const InfoTip = ({
|
|
|
117
88
|
const handleTabKeyInPopover = event => {
|
|
118
89
|
if (event.key !== 'Tab' || event.shiftKey) return;
|
|
119
90
|
const focusableElements = getFocusableElements();
|
|
120
|
-
|
|
91
|
+
const {
|
|
92
|
+
activeElement
|
|
93
|
+
} = document;
|
|
94
|
+
|
|
95
|
+
// If no focusable elements and popover itself has focus, wrap to button
|
|
96
|
+
if (focusableElements.length === 0) {
|
|
97
|
+
if (activeElement === popoverContentNodeRef.current) {
|
|
98
|
+
event.preventDefault();
|
|
99
|
+
buttonRef.current?.focus();
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
121
103
|
const lastElement = focusableElements[focusableElements.length - 1];
|
|
122
104
|
|
|
123
105
|
// Only wrap forward: if on last element, wrap to button
|
|
@@ -137,46 +119,36 @@ export const InfoTip = ({
|
|
|
137
119
|
document.removeEventListener('keydown', handleGlobalEscapeKey, true);
|
|
138
120
|
};
|
|
139
121
|
}
|
|
140
|
-
return () => document.removeEventListener('keydown', handleGlobalEscapeKey
|
|
141
|
-
}, [isTipHidden, isFloating,
|
|
122
|
+
return () => document.removeEventListener('keydown', handleGlobalEscapeKey);
|
|
123
|
+
}, [isTipHidden, isFloating, getFocusableElements, setTipIsHidden]);
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (isTipHidden) return;
|
|
126
|
+
const timeoutId = setTimeout(() => {
|
|
127
|
+
popoverContentNodeRef.current?.focus();
|
|
128
|
+
}, 0);
|
|
129
|
+
return () => clearTimeout(timeoutId);
|
|
130
|
+
}, [isTipHidden]);
|
|
142
131
|
const Tip = loaded && isFloating ? FloatingTip : InlineTip;
|
|
143
132
|
const tipProps = useMemo(() => ({
|
|
144
133
|
alignment,
|
|
145
134
|
info,
|
|
146
135
|
isTipHidden,
|
|
136
|
+
contentRef: popoverContentRef,
|
|
147
137
|
wrapperRef,
|
|
148
|
-
...(isFloating && {
|
|
149
|
-
popoverContentRef
|
|
150
|
-
}),
|
|
151
138
|
...rest
|
|
152
|
-
}), [alignment, info, isTipHidden,
|
|
153
|
-
const extractedTextContent = useMemo(() => extractTextContent(info), [info]);
|
|
154
|
-
const screenreaderInfo = shouldAnnounce && !isTipHidden ? extractedTextContent : '\xa0';
|
|
155
|
-
const screenreaderText = useMemo(() => /*#__PURE__*/_jsx(ScreenreaderNavigableText, {
|
|
156
|
-
"aria-hidden": isAriaHidden,
|
|
157
|
-
"aria-live": "assertive",
|
|
158
|
-
screenreader: true,
|
|
159
|
-
children: screenreaderInfo
|
|
160
|
-
}), [isAriaHidden, screenreaderInfo]);
|
|
161
|
-
const button = useMemo(() => /*#__PURE__*/_jsx(InfoTipButton, {
|
|
162
|
-
active: !isTipHidden,
|
|
163
|
-
"aria-expanded": !isTipHidden,
|
|
164
|
-
emphasis: emphasis,
|
|
165
|
-
ref: buttonRef,
|
|
166
|
-
onClick: clickHandler
|
|
167
|
-
}), [isTipHidden, emphasis, clickHandler]);
|
|
168
|
-
|
|
169
|
-
/*
|
|
170
|
-
* For floating placement, screenreader text comes before button to maintain
|
|
171
|
-
* correct DOM order despite Portal rendering. See GMT-64 for planned fix.
|
|
172
|
-
*/
|
|
139
|
+
}), [alignment, info, isTipHidden, popoverContentRef, wrapperRef, rest]);
|
|
173
140
|
return /*#__PURE__*/_jsx(Tip, {
|
|
174
141
|
...tipProps,
|
|
175
142
|
type: "info",
|
|
176
|
-
children:
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
143
|
+
children: /*#__PURE__*/_jsx(InfoTipButton, {
|
|
144
|
+
active: !isTipHidden,
|
|
145
|
+
"aria-expanded": !isTipHidden,
|
|
146
|
+
"aria-label": ariaLabel,
|
|
147
|
+
"aria-labelledby": ariaLabelledby,
|
|
148
|
+
"aria-roledescription": "More information button",
|
|
149
|
+
emphasis: emphasis,
|
|
150
|
+
ref: buttonRef,
|
|
151
|
+
onClick: clickHandler
|
|
180
152
|
})
|
|
181
153
|
});
|
|
182
154
|
};
|
|
@@ -48,13 +48,10 @@ export declare const pressKey: (key: string) => Promise<void>;
|
|
|
48
48
|
export declare const waitForLinkToHaveFocus: ({ view, linkText, }: ViewParam & LinkTextParam) => Promise<HTMLElement>;
|
|
49
49
|
export declare const openTipAndWaitForLink: ({ view, linkText, }: ViewParam & LinkTextParam) => Promise<HTMLElement>;
|
|
50
50
|
export declare const openTipTabToLinkAndWaitForFocus: (view: InfoTipView, linkText: string) => Promise<HTMLElement>;
|
|
51
|
-
export declare const
|
|
52
|
-
export declare const testEscapeKeyReturnsFocus: ({ view, info, placement, }: ViewParam & InfoParam & PlacementParam) => Promise<void>;
|
|
53
|
-
export declare const testFocusWrap: ({ view, containerRef, direction, }: ViewParam & {
|
|
54
|
-
containerRef: RefObject<HTMLDivElement>;
|
|
51
|
+
export declare const testFocusWrap: ({ view, direction, }: ViewParam & {
|
|
55
52
|
direction: 'forward' | 'backward';
|
|
56
53
|
}) => Promise<void>;
|
|
57
|
-
export declare const
|
|
54
|
+
export declare const testTabFromPopoverWithNoInteractiveElements: (view: InfoTipView) => Promise<void>;
|
|
58
55
|
export declare const testTabbingBetweenLinks: ({ view, firstLinkText, secondLinkText, placement, }: ViewParam & {
|
|
59
56
|
firstLinkText: string;
|
|
60
57
|
secondLinkText: string;
|
|
@@ -86,18 +83,6 @@ type ViewWithQueries = {
|
|
|
86
83
|
getAllByText: (text: string) => HTMLElement[];
|
|
87
84
|
getAllByLabelText: (text: string) => HTMLElement[];
|
|
88
85
|
};
|
|
89
|
-
export declare const getVisibleTip: ({ text, placement, }: {
|
|
90
|
-
text: string;
|
|
91
|
-
placement?: "inline" | "floating" | undefined;
|
|
92
|
-
}) => HTMLElement | undefined;
|
|
93
|
-
export declare const expectTipToBeVisible: ({ text, placement, }: {
|
|
94
|
-
text: string;
|
|
95
|
-
placement?: "inline" | "floating" | undefined;
|
|
96
|
-
}) => void;
|
|
97
|
-
export declare const expectTipToBeClosed: ({ text, placement, }: {
|
|
98
|
-
text: string;
|
|
99
|
-
placement?: "inline" | "floating" | undefined;
|
|
100
|
-
}) => void;
|
|
101
86
|
export declare const openInfoTipsWithKeyboard: ({ view, count, }: {
|
|
102
87
|
view: ViewWithQueries;
|
|
103
88
|
count: number;
|
|
@@ -106,8 +91,5 @@ export declare const expectTipsVisible: (tips: {
|
|
|
106
91
|
text: string;
|
|
107
92
|
placement?: 'inline' | 'floating';
|
|
108
93
|
}[]) => void;
|
|
109
|
-
export declare const expectTipsClosed: (
|
|
110
|
-
text: string;
|
|
111
|
-
placement?: 'inline' | 'floating';
|
|
112
|
-
}[]) => void;
|
|
94
|
+
export declare const expectTipsClosed: () => void;
|
|
113
95
|
export {};
|
|
@@ -5,6 +5,8 @@ import { ToolTipProps } from '../ToolTip';
|
|
|
5
5
|
export declare const ToolTipMock: React.FC<ToolTipProps & ComponentProps<typeof FillButton>>;
|
|
6
6
|
export declare const InfoTipInsideModalMock: React.FC<Pick<InfoTipProps, 'info' | 'placement'>>;
|
|
7
7
|
export declare const MultipleInfoTipsMock: React.FC<{
|
|
8
|
-
tips:
|
|
8
|
+
tips: (Pick<InfoTipProps, 'info' | 'placement'> & {
|
|
9
|
+
id: string;
|
|
10
|
+
})[];
|
|
9
11
|
includeOutsideElement?: boolean;
|
|
10
12
|
}>;
|
|
@@ -18,7 +18,7 @@ export const FloatingTip = ({
|
|
|
18
18
|
loading,
|
|
19
19
|
narrow,
|
|
20
20
|
overline,
|
|
21
|
-
|
|
21
|
+
contentRef,
|
|
22
22
|
truncateLines,
|
|
23
23
|
type,
|
|
24
24
|
username,
|
|
@@ -123,7 +123,7 @@ export const FloatingTip = ({
|
|
|
123
123
|
width: inheritDims ? 'inherit' : undefined,
|
|
124
124
|
onBlur: toolOnlyEventFunc,
|
|
125
125
|
onFocus: toolOnlyEventFunc,
|
|
126
|
-
onKeyDown: escapeKeyPressHandler
|
|
126
|
+
onKeyDown: escapeKeyPressHandler,
|
|
127
127
|
onMouseDown: e => e.preventDefault(),
|
|
128
128
|
onMouseEnter: toolOnlyEventFunc,
|
|
129
129
|
children: children
|
|
@@ -134,7 +134,7 @@ export const FloatingTip = ({
|
|
|
134
134
|
horizontalOffset: offset,
|
|
135
135
|
isOpen: isPopoverOpen,
|
|
136
136
|
outline: true,
|
|
137
|
-
popoverContainerRef:
|
|
137
|
+
popoverContainerRef: contentRef,
|
|
138
138
|
skipFocusTrap: true,
|
|
139
139
|
targetRef: ref,
|
|
140
140
|
variant: "secondary",
|
|
@@ -17,6 +17,7 @@ export const InlineTip = ({
|
|
|
17
17
|
loading,
|
|
18
18
|
narrow,
|
|
19
19
|
overline,
|
|
20
|
+
contentRef,
|
|
20
21
|
truncateLines,
|
|
21
22
|
type,
|
|
22
23
|
username,
|
|
@@ -42,7 +43,7 @@ export const InlineTip = ({
|
|
|
42
43
|
height: inheritDims ? 'inherit' : undefined,
|
|
43
44
|
ref: wrapperRef,
|
|
44
45
|
width: inheritDims ? 'inherit' : undefined,
|
|
45
|
-
onKeyDown: escapeKeyPressHandler
|
|
46
|
+
onKeyDown: escapeKeyPressHandler,
|
|
46
47
|
children: children
|
|
47
48
|
});
|
|
48
49
|
const tipBody = /*#__PURE__*/_jsx(InlineTipBodyWrapper, {
|
|
@@ -55,7 +56,9 @@ export const InlineTip = ({
|
|
|
55
56
|
color: "currentColor",
|
|
56
57
|
horizNarrow: narrow && isHorizontalCenter,
|
|
57
58
|
id: id,
|
|
59
|
+
ref: contentRef,
|
|
58
60
|
role: type === 'tool' ? 'tooltip' : undefined,
|
|
61
|
+
tabIndex: type === 'info' ? -1 : undefined,
|
|
59
62
|
width: narrow && !isHorizontalCenter ? narrowWidth : 'max-content',
|
|
60
63
|
zIndex: "auto",
|
|
61
64
|
children: type === 'preview' ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
@@ -46,7 +46,7 @@ export type TipPlacementComponentProps = Omit<TipNewBaseProps, 'placement' | 'em
|
|
|
46
46
|
escapeKeyPressHandler?: (event: React.KeyboardEvent<HTMLDivElement>) => void;
|
|
47
47
|
id?: string;
|
|
48
48
|
isTipHidden?: boolean;
|
|
49
|
-
|
|
49
|
+
contentRef?: React.RefObject<HTMLDivElement> | ((node: HTMLDivElement | null) => void);
|
|
50
50
|
type: 'info' | 'tool' | 'preview';
|
|
51
51
|
wrapperRef?: React.RefObject<HTMLDivElement>;
|
|
52
52
|
zIndex?: number;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codecademy/gamut",
|
|
3
3
|
"description": "Styleguide & Component library for Codecademy",
|
|
4
|
-
"version": "67.4.2-alpha.
|
|
4
|
+
"version": "67.4.2-alpha.b7c260.0",
|
|
5
5
|
"author": "Codecademy Engineering <dev@codecademy.com>",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@codecademy/gamut-icons": "9.52.1",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"dist/**/[A-Z]**/[A-Z]*.js",
|
|
57
57
|
"dist/**/[A-Z]**/index.js"
|
|
58
58
|
],
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "6432656246ee13d3f609f32fda6f67d9ae69aaef"
|
|
60
60
|
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
export declare const ScreenreaderNavigableText: import("@emotion/styled").StyledComponent<(((Omit<{
|
|
3
|
-
theme?: import("@emotion/react").Theme | undefined;
|
|
4
|
-
as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
|
|
5
|
-
} & import("../..").TextTruncateProps & Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "slot" | "style" | "title" | "dir" | "children" | "className" | "aria-hidden" | "onAnimationStart" | "onDragStart" | "onDragEnd" | "onDrag" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoFocus" | "contentEditable" | "contextMenu" | "draggable" | "hidden" | "id" | "lang" | "nonce" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDragCapture" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | keyof import("react").ClassAttributes<HTMLSpanElement>>, "ref"> | Omit<{
|
|
6
|
-
theme?: import("@emotion/react").Theme | undefined;
|
|
7
|
-
as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
|
|
8
|
-
} & import("../..").TextNoTruncateProps & Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "slot" | "style" | "title" | "dir" | "children" | "className" | "aria-hidden" | "onAnimationStart" | "onDragStart" | "onDragEnd" | "onDrag" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoFocus" | "contentEditable" | "contextMenu" | "draggable" | "hidden" | "id" | "lang" | "nonce" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDragCapture" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | keyof import("react").ClassAttributes<HTMLSpanElement>>, "ref">) & import("react").RefAttributes<HTMLSpanElement>) & {
|
|
9
|
-
theme?: import("@emotion/react").Theme | undefined;
|
|
10
|
-
}) & {
|
|
11
|
-
theme?: import("@emotion/react").Theme | undefined;
|
|
12
|
-
}, {}, {}>;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import _styled from "@emotion/styled/base";
|
|
2
|
-
import { css } from '@codecademy/gamut-styles';
|
|
3
|
-
import { Text } from '../../Typography';
|
|
4
|
-
export const ScreenreaderNavigableText = /*#__PURE__*/_styled(Text, {
|
|
5
|
-
target: "e1rvjfdo0",
|
|
6
|
-
label: "ScreenreaderNavigableText"
|
|
7
|
-
})(css({
|
|
8
|
-
position: 'absolute'
|
|
9
|
-
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9UaXAvSW5mb1RpcC9lbGVtZW50cy50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBS3lDIiwiZmlsZSI6Ii4uLy4uLy4uL3NyYy9UaXAvSW5mb1RpcC9lbGVtZW50cy50c3giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjc3MgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnO1xuXG5pbXBvcnQgeyBUZXh0IH0gZnJvbSAnLi4vLi4vVHlwb2dyYXBoeSc7XG5cbmV4cG9ydCBjb25zdCBTY3JlZW5yZWFkZXJOYXZpZ2FibGVUZXh0ID0gc3R5bGVkKFRleHQpKFxuICBjc3MoeyBwb3NpdGlvbjogJ2Fic29sdXRlJyB9KVxuKTtcbiJdfQ== */");
|
package/dist/utils/react.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Recursively extracts plain text content from React children.
|
|
3
|
-
*
|
|
4
|
-
* Useful for converting JSX to plain text for accessibility purposes
|
|
5
|
-
* like screenreader announcements or aria-labels.
|
|
6
|
-
*
|
|
7
|
-
* @param children - React children to extract text from
|
|
8
|
-
* @returns Plain text string with all text content joined by spaces
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```tsx
|
|
12
|
-
* const text = extractTextContent(
|
|
13
|
-
* <div>Hello <strong>world</strong>!</div>
|
|
14
|
-
* );
|
|
15
|
-
* // Returns: "Hello world !"
|
|
16
|
-
* ```
|
|
17
|
-
*/
|
|
18
|
-
export declare const extractTextContent: (children: React.ReactNode) => string;
|
package/dist/utils/react.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { Children, isValidElement } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Recursively extracts plain text content from React children.
|
|
5
|
-
*
|
|
6
|
-
* Useful for converting JSX to plain text for accessibility purposes
|
|
7
|
-
* like screenreader announcements or aria-labels.
|
|
8
|
-
*
|
|
9
|
-
* @param children - React children to extract text from
|
|
10
|
-
* @returns Plain text string with all text content joined by spaces
|
|
11
|
-
*
|
|
12
|
-
* @example
|
|
13
|
-
* ```tsx
|
|
14
|
-
* const text = extractTextContent(
|
|
15
|
-
* <div>Hello <strong>world</strong>!</div>
|
|
16
|
-
* );
|
|
17
|
-
* // Returns: "Hello world !"
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
export const extractTextContent = children => {
|
|
21
|
-
if (typeof children === 'string' || typeof children === 'number') {
|
|
22
|
-
return String(children);
|
|
23
|
-
}
|
|
24
|
-
return Children.toArray(children).map(child => {
|
|
25
|
-
if (typeof child === 'string' || typeof child === 'number') {
|
|
26
|
-
return String(child);
|
|
27
|
-
}
|
|
28
|
-
if (typeof child === 'boolean' || child == null) {
|
|
29
|
-
return '';
|
|
30
|
-
}
|
|
31
|
-
if (/*#__PURE__*/isValidElement(child)) {
|
|
32
|
-
return extractTextContent(child.props.children);
|
|
33
|
-
}
|
|
34
|
-
return '';
|
|
35
|
-
}).filter(Boolean).join(' ');
|
|
36
|
-
};
|