@sproutsocial/racine 11.3.0-beta.0 → 11.3.0-beta.3
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 +30 -0
- package/__flow__/Badge/constants.js +48 -0
- package/__flow__/Badge/index.js +60 -33
- package/__flow__/Badge/index.stories.js +35 -42
- package/__flow__/Badge/index.test.js +34 -32
- package/__flow__/Badge/styles.js +22 -42
- package/__flow__/Input/index.js +43 -26
- package/__flow__/Input/index.stories.js +33 -1
- package/__flow__/Input/index.test.js +41 -38
- package/__flow__/Link/index.js +2 -1
- package/__flow__/themes/extendedThemes/README.md +6 -0
- package/commonjs/Badge/constants.js +43 -0
- package/commonjs/Badge/index.js +41 -39
- package/commonjs/Badge/styles.js +15 -31
- package/commonjs/Input/index.js +50 -19
- package/lib/Badge/constants.js +38 -0
- package/lib/Badge/index.js +38 -39
- package/lib/Badge/styles.js +12 -27
- package/lib/Input/index.js +50 -19
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 11.2.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 206bd32: copy updates to the TypeProps comments that power Seeds prop tables
|
|
8
|
+
|
|
9
|
+
## 11.2.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 514d738: Patch badge component flow issue
|
|
14
|
+
|
|
15
|
+
## 11.2.2
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 9cc377e: Created extended theme directory
|
|
20
|
+
|
|
21
|
+
## 11.2.1
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 6968733: adds deprecation messaging to typeProps to be displayed on seeds page
|
|
26
|
+
|
|
27
|
+
## 11.2.0
|
|
28
|
+
|
|
29
|
+
### Minor Changes
|
|
30
|
+
|
|
31
|
+
- a71a431: backwards compatible style and api changes to the badge component
|
|
32
|
+
|
|
3
33
|
## 11.1.2
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//@flow
|
|
2
|
+
|
|
3
|
+
const defaultPurple = {
|
|
4
|
+
color: "colors.text.body",
|
|
5
|
+
background: "colors.container.background.decorative.purple",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const suggestion = {
|
|
9
|
+
color: "colors.text.body",
|
|
10
|
+
background: "colors.container.background.decorative.blue",
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const passive = {
|
|
14
|
+
color: "colors.text.body",
|
|
15
|
+
background: "colors.container.background.decorative.neutral",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const primary = {
|
|
19
|
+
color: "colors.text.body",
|
|
20
|
+
background: "colors.container.background.decorative.blue",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const secondary = {
|
|
24
|
+
color: "colors.text.body",
|
|
25
|
+
background: "colors.container.background.decorative.yellow",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const common = {
|
|
29
|
+
color: "colors.text.inverse",
|
|
30
|
+
background: "colors.aqua.600",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const approval = {
|
|
34
|
+
color: "colors.text.body",
|
|
35
|
+
background: "colors.container.background.decorative.orange",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
//Deprecated former "types"
|
|
39
|
+
|
|
40
|
+
export const legacyBadgeColors = {
|
|
41
|
+
primary,
|
|
42
|
+
secondary,
|
|
43
|
+
passive,
|
|
44
|
+
common,
|
|
45
|
+
approval,
|
|
46
|
+
default: defaultPurple,
|
|
47
|
+
suggestion,
|
|
48
|
+
};
|
package/__flow__/Badge/index.js
CHANGED
|
@@ -1,43 +1,70 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import Icon from "../Icon";
|
|
3
4
|
import Container from "./styles";
|
|
5
|
+
import Box from "../Box";
|
|
4
6
|
|
|
5
7
|
type TypeProps = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
| "
|
|
13
|
-
| "
|
|
14
|
-
| "
|
|
15
|
-
|
|
8
|
+
children?: React.Node,
|
|
9
|
+
/** DEPRECATED: Use children instead of text */
|
|
10
|
+
text?: React.Node,
|
|
11
|
+
/** Size default is deprecated in favor of small and large */
|
|
12
|
+
size?: "small" | "large" | "default",
|
|
13
|
+
badgeColor?:
|
|
14
|
+
| "green"
|
|
15
|
+
| "blue"
|
|
16
|
+
| "purple"
|
|
17
|
+
| "yellow"
|
|
18
|
+
| "orange"
|
|
19
|
+
| "red"
|
|
20
|
+
| "neutral",
|
|
21
|
+
iconName?: string,
|
|
22
|
+
/** DEPRECATED: Possibly only used for testing. Refrain from using at all if possible. (optional) */
|
|
16
23
|
tip?: React.Node,
|
|
24
|
+
/** DEPRECATED: The legacy method of choosing a theme. Use badgeColor instead. (optional) */
|
|
25
|
+
type?: string,
|
|
17
26
|
};
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
data-tip={tip}
|
|
33
|
-
data-qa-badge={text || ""}
|
|
34
|
-
data-qa-badge-type={type}
|
|
35
|
-
data-qa-badge-tip={tip || ""}
|
|
36
|
-
// $FlowIssue - upgrade v0.112.0
|
|
37
|
-
{...rest}
|
|
38
|
-
>
|
|
39
|
-
{text}
|
|
40
|
-
</Container>
|
|
28
|
+
const Badge = ({
|
|
29
|
+
children,
|
|
30
|
+
text,
|
|
31
|
+
iconName,
|
|
32
|
+
type,
|
|
33
|
+
tip,
|
|
34
|
+
size = "small",
|
|
35
|
+
badgeColor = "blue",
|
|
36
|
+
...rest
|
|
37
|
+
}: TypeProps) => {
|
|
38
|
+
if (children && text) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
"can't use both `children` and `text` props. Text is deprecated, consider using children."
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Container
|
|
46
|
+
{...rest}
|
|
47
|
+
// size previously included default, which currently maps to small. Once consumers have updated this can be simplified.
|
|
48
|
+
size={size === "default" ? "large" : size}
|
|
49
|
+
badgeColor={badgeColor}
|
|
50
|
+
data-tip={tip}
|
|
51
|
+
data-qa-badge={text || ""}
|
|
52
|
+
data-qa-badge-type={type}
|
|
53
|
+
data-qa-badge-tip={tip || ""}
|
|
54
|
+
type={type && type}
|
|
55
|
+
>
|
|
56
|
+
<Box display="flex" alignItems="center" JustifyContent="center">
|
|
57
|
+
{iconName ? (
|
|
58
|
+
<Icon
|
|
59
|
+
mr={200}
|
|
60
|
+
name={iconName}
|
|
61
|
+
size={size === "small" ? "mini" : "default"}
|
|
62
|
+
/>
|
|
63
|
+
) : null}
|
|
64
|
+
{children || text}
|
|
65
|
+
</Box>
|
|
66
|
+
</Container>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default Badge;
|
|
@@ -1,53 +1,46 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { text } from "@storybook/addon-knobs";
|
|
3
2
|
import Badge from "./index";
|
|
3
|
+
import Box from "../Box";
|
|
4
|
+
import Numeral from "../Numeral";
|
|
5
|
+
import Text from "../Text";
|
|
6
|
+
import Stack from "../Stack";
|
|
4
7
|
|
|
5
8
|
export default {
|
|
6
9
|
title: "Badge",
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
export const permutations = () => (
|
|
10
|
-
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
size=
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
/>
|
|
42
|
-
|
|
43
|
-
<Badge text={text("text", "Test")} type="default" />
|
|
44
|
-
<Badge text={text("text", "Test")} />
|
|
45
|
-
<Badge text={text("text", "Test")} type="secondary" />
|
|
46
|
-
<Badge text={text("text", "Test")} type="passive" />
|
|
47
|
-
<Badge text={text("text", "Test")} type="common" />
|
|
48
|
-
<Badge text={text("text", "Test")} type="approval" />
|
|
49
|
-
<Badge text={text("text", "Test")} type="suggestion" />
|
|
50
|
-
</>
|
|
13
|
+
<Stack space={450}>
|
|
14
|
+
<Box display="flex" alignItems="center">
|
|
15
|
+
<Badge badgeColor="green">Badge</Badge>
|
|
16
|
+
<Badge>Badge</Badge>
|
|
17
|
+
<Badge badgeColor="purple">Badge</Badge>
|
|
18
|
+
<Badge badgeColor="yellow">Badge</Badge>
|
|
19
|
+
<Badge badgeColor="orange">Badge</Badge>
|
|
20
|
+
<Badge badgeColor="red">Badge</Badge>
|
|
21
|
+
<Badge badgeColor="neutral" iconName="atom">
|
|
22
|
+
Badge
|
|
23
|
+
</Badge>
|
|
24
|
+
<Badge
|
|
25
|
+
size="small"
|
|
26
|
+
type="default"
|
|
27
|
+
bg="chartreuse"
|
|
28
|
+
color="crimson"
|
|
29
|
+
p={500}
|
|
30
|
+
>
|
|
31
|
+
Radical overrides!
|
|
32
|
+
</Badge>
|
|
33
|
+
</Box>
|
|
34
|
+
<Box display="flex" alignItems="center">
|
|
35
|
+
<Badge size="large" type="secondary" iconName="sparkles">
|
|
36
|
+
Supports legacy types
|
|
37
|
+
</Badge>
|
|
38
|
+
<Badge size="large">
|
|
39
|
+
<Numeral fontWeight="bold" number={1569241} />
|
|
40
|
+
<Text ml={200}>and children!</Text>
|
|
41
|
+
</Badge>
|
|
42
|
+
</Box>
|
|
43
|
+
</Stack>
|
|
51
44
|
);
|
|
52
45
|
|
|
53
46
|
permutations.story = {
|
|
@@ -3,48 +3,50 @@ import Badge from "./";
|
|
|
3
3
|
import { render } from "../utils/react-testing-library";
|
|
4
4
|
import "jest-styled-components";
|
|
5
5
|
|
|
6
|
-
describe("
|
|
7
|
-
it("should render with default props", () => {
|
|
8
|
-
const { getByText
|
|
6
|
+
describe("Badge...", () => {
|
|
7
|
+
it("...should render with default props", () => {
|
|
8
|
+
const { getByText } = render(<Badge>Test</Badge>);
|
|
9
9
|
expect(getByText("Test")).toBeTruthy();
|
|
10
|
-
expect(
|
|
10
|
+
expect(getByText("Test").closest("span")).toHaveStyleRule(
|
|
11
|
+
"padding",
|
|
12
|
+
"0px 4px"
|
|
13
|
+
);
|
|
14
|
+
expect(getByText("Test").closest("span")).toHaveStyleRule(
|
|
15
|
+
"background",
|
|
16
|
+
"#dcf2ff"
|
|
17
|
+
);
|
|
11
18
|
});
|
|
12
19
|
|
|
13
|
-
it("should render with correct size styling", () => {
|
|
14
|
-
const { getByText } = render(<Badge
|
|
15
|
-
expect(getByText("Test")).toHaveStyleRule("padding", "
|
|
20
|
+
it("...should render with correct size styling", () => {
|
|
21
|
+
const { getByText } = render(<Badge size="large">Test</Badge>);
|
|
22
|
+
expect(getByText("Test").closest("span")).toHaveStyleRule("padding", "8px");
|
|
16
23
|
});
|
|
17
24
|
|
|
18
|
-
it("should render with
|
|
19
|
-
const { getByText
|
|
20
|
-
<Badge text="Test" type="secondary" />
|
|
21
|
-
);
|
|
25
|
+
it("...should render with legacy type", () => {
|
|
26
|
+
const { getByText } = render(<Badge type="secondary">Test</Badge>);
|
|
22
27
|
expect(getByText("Test")).toBeTruthy();
|
|
23
|
-
expect(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
expect(getByText("Test").closest("span")).toHaveStyleRule(
|
|
29
|
+
"color",
|
|
30
|
+
"#364141"
|
|
31
|
+
);
|
|
32
|
+
expect(getByText("Test").closest("span")).toHaveStyleRule(
|
|
33
|
+
"background",
|
|
34
|
+
"#fdefcd"
|
|
29
35
|
);
|
|
30
|
-
expect(getByText("Test")).toBeTruthy();
|
|
31
|
-
expect(getByDataQaLabel({ "badge-type": "passive" })).toBeTruthy();
|
|
32
36
|
});
|
|
33
37
|
|
|
34
|
-
it("should render with
|
|
35
|
-
const { getByText
|
|
36
|
-
<Badge text="Test" type="common" />
|
|
37
|
-
);
|
|
38
|
+
it("...should render with a badge color", () => {
|
|
39
|
+
const { getByText } = render(<Badge badgeColor="purple">Test</Badge>);
|
|
38
40
|
expect(getByText("Test")).toBeTruthy();
|
|
39
|
-
expect(
|
|
41
|
+
expect(getByText("Test").closest("span")).toHaveStyleRule(
|
|
42
|
+
"background",
|
|
43
|
+
"#eaeaf9"
|
|
44
|
+
);
|
|
40
45
|
});
|
|
41
46
|
|
|
42
|
-
it("should render with
|
|
43
|
-
const {
|
|
44
|
-
|
|
45
|
-
);
|
|
46
|
-
expect(getByText("Test")).toBeTruthy();
|
|
47
|
-
expect(getByDataQaLabel({ "badge-type": "approval" })).toBeTruthy();
|
|
47
|
+
it("...should render with an icon", () => {
|
|
48
|
+
const { container } = render(<Badge iconName="sparkles">Test</Badge>);
|
|
49
|
+
expect(container.querySelector("svg")).toBeTruthy();
|
|
48
50
|
});
|
|
49
51
|
it("should render with suggestion type", () => {
|
|
50
52
|
const { getByText, getByDataQaLabel } = render(
|
|
@@ -54,9 +56,9 @@ describe("Racine Badge", () => {
|
|
|
54
56
|
expect(getByDataQaLabel({ "badge-type": "suggestion" })).toBeTruthy();
|
|
55
57
|
});
|
|
56
58
|
|
|
57
|
-
it("should render with tooltip class", () => {
|
|
59
|
+
it("...should render with tooltip class", () => {
|
|
58
60
|
const { getByText, getByDataQaLabel } = render(
|
|
59
|
-
<Badge
|
|
61
|
+
<Badge tip="test tip">Test</Badge>
|
|
60
62
|
);
|
|
61
63
|
expect(getByText("Test")).toBeTruthy();
|
|
62
64
|
expect(getByDataQaLabel({ "badge-tip": "test tip" })).toBeTruthy();
|
package/__flow__/Badge/styles.js
CHANGED
|
@@ -1,51 +1,31 @@
|
|
|
1
1
|
//@flow
|
|
2
|
-
import styled, {
|
|
2
|
+
import styled, { type StyledComponent } from "styled-components";
|
|
3
3
|
import { COMMON } from "../utils/system-props";
|
|
4
|
-
import { themeGet } from "@styled-system/theme-get";
|
|
5
|
-
|
|
6
4
|
import type { TypeTheme } from "../types/theme.flow";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
primary: "colors.neutral.0",
|
|
10
|
-
secondary: "colors.neutral.800",
|
|
11
|
-
passive: "colors.neutral.800",
|
|
12
|
-
common: "colors.neutral.0",
|
|
13
|
-
approval: "colors.neutral.800",
|
|
14
|
-
default: "colors.neutral.0",
|
|
15
|
-
suggestion: "colors.neutral.900",
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const backgroundColors = {
|
|
19
|
-
primary: "colors.blue.700",
|
|
20
|
-
secondary: "colors.yellow.500",
|
|
21
|
-
passive: "colors.neutral.200",
|
|
22
|
-
common: "colors.aqua.600",
|
|
23
|
-
approval: "colors.orange.300",
|
|
24
|
-
default: "colors.purple.700",
|
|
25
|
-
suggestion: "colors.blue.300",
|
|
26
|
-
};
|
|
5
|
+
import { themeGet } from "@styled-system/theme-get";
|
|
6
|
+
import { legacyBadgeColors } from "./constants";
|
|
27
7
|
|
|
28
8
|
// eslint-disable-next-line prettier/prettier
|
|
29
|
-
const Container: StyledComponent<{type:
|
|
9
|
+
const Container: StyledComponent<{type: ?string, badgeColor: string, size: string, ...}, TypeTheme, *> = styled.span`
|
|
10
|
+
font-family: ${(p) => p.theme.fontFamily};
|
|
11
|
+
${(p) =>
|
|
12
|
+
p.size === "small" ? p.theme.typography[100] : p.theme.typography[200]};
|
|
13
|
+
border-radius: 9999px;
|
|
14
|
+
line-height: 16px;
|
|
30
15
|
display: inline-block;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
?
|
|
38
|
-
:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
${
|
|
44
|
-
color: ${themeGet(colors[props.type])(props)};
|
|
45
|
-
background: ${themeGet(backgroundColors[props.type])(props)};
|
|
46
|
-
`}
|
|
47
|
-
|
|
48
|
-
${COMMON}
|
|
16
|
+
color: ${(p) =>
|
|
17
|
+
p.type
|
|
18
|
+
? themeGet(legacyBadgeColors[p.type].color)
|
|
19
|
+
: p.theme.colors.text.body};
|
|
20
|
+
background: ${(p) =>
|
|
21
|
+
p.type
|
|
22
|
+
? themeGet(legacyBadgeColors[p.type].background)
|
|
23
|
+
: p.theme.colors.container.background.decorative[p.badgeColor]};
|
|
24
|
+
padding: ${(p) =>
|
|
25
|
+
p.size === "small"
|
|
26
|
+
? `${p.theme.space[0]} ${p.theme.space[200]}`
|
|
27
|
+
: `${p.theme.space[300]}`};
|
|
28
|
+
${COMMON};
|
|
49
29
|
`;
|
|
50
30
|
|
|
51
31
|
export default Container;
|
package/__flow__/Input/index.js
CHANGED
|
@@ -45,13 +45,8 @@ type TypeProps = {
|
|
|
45
45
|
/** Used to get a reference to the underlying element */
|
|
46
46
|
innerRef?: React.Ref<"input">,
|
|
47
47
|
onBlur?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
|
|
48
|
-
onChange?: (
|
|
49
|
-
|
|
50
|
-
| SyntheticInputEvent<HTMLInputElement>
|
|
51
|
-
| SyntheticEvent<HTMLButtonElement>,
|
|
52
|
-
value: string
|
|
53
|
-
) => void,
|
|
54
|
-
/** Called on Input.ClearButton trigger */
|
|
48
|
+
onChange?: (e: SyntheticInputEvent<HTMLInputElement>, value: string) => void,
|
|
49
|
+
/** Called on Input.ClearButton trigger. */
|
|
55
50
|
onClear?: (e: SyntheticEvent<HTMLButtonElement>) => void,
|
|
56
51
|
onFocus?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
|
|
57
52
|
onKeyDown?: (
|
|
@@ -77,21 +72,48 @@ type TypeProps = {
|
|
|
77
72
|
type TypeInputContext = $Shape<{
|
|
78
73
|
handleClear: (e: SyntheticEvent<HTMLButtonElement>) => void,
|
|
79
74
|
clearButtonLabel: string,
|
|
75
|
+
hasValue: boolean,
|
|
80
76
|
}>;
|
|
81
77
|
|
|
82
78
|
const InputContext = React.createContext<TypeInputContext>({});
|
|
83
79
|
|
|
84
80
|
const ClearButton = () => {
|
|
85
|
-
const { handleClear, clearButtonLabel } =
|
|
81
|
+
const { handleClear, clearButtonLabel, hasValue, size } =
|
|
82
|
+
React.useContext(InputContext);
|
|
83
|
+
|
|
84
|
+
// Hide the button when there is no text to clear.
|
|
85
|
+
if (!hasValue) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Cut down the padding for size small Inputs so that the focus ring won't go outside the bounds of the Input.
|
|
90
|
+
// This adjustment is handled automatically for default and large Inputs via Button's size. There is no "small" Button.
|
|
91
|
+
const py = size === "small" ? 100 : undefined;
|
|
92
|
+
const px = size === "small" ? 200 : undefined;
|
|
93
|
+
const buttonSize = size === "small" ? "default" : size;
|
|
94
|
+
|
|
95
|
+
// Warn if clearButtonLabel is not included, so that the unlocalized fallback will not be mistaken for a proper label.
|
|
96
|
+
if (!clearButtonLabel) {
|
|
97
|
+
console.warn(
|
|
98
|
+
"Warning: clearButtonLabel prop is required when using Input.ClearButton. Please pass a localized label to Input."
|
|
99
|
+
);
|
|
100
|
+
}
|
|
86
101
|
return (
|
|
87
|
-
<Button onClick={handleClear}>
|
|
88
|
-
{/*Unlocalized fallback should not be used. Always include a localized
|
|
89
|
-
clearButtonLabel when using <Input.ClearButton/> or <Input type="search"/>.*/}
|
|
102
|
+
<Button onClick={handleClear} size={buttonSize} py={py} px={px}>
|
|
90
103
|
<Icon name="circlex" title={clearButtonLabel || "Clear"} />
|
|
91
104
|
</Button>
|
|
92
105
|
);
|
|
93
106
|
};
|
|
94
107
|
|
|
108
|
+
// Used for positioning elementAfter. This logic will detect if the element is a ClearButton,
|
|
109
|
+
// regardless of whether it was manually passed as elemAfter or automatically added to a search Input.
|
|
110
|
+
const isClearButton = (elem: any) => {
|
|
111
|
+
if (elem?.type) {
|
|
112
|
+
return elem.type.displayName === "Input.ClearButton";
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
};
|
|
116
|
+
|
|
95
117
|
class Input extends React.Component<TypeProps> {
|
|
96
118
|
static defaultProps = {
|
|
97
119
|
autoFocus: false,
|
|
@@ -107,11 +129,8 @@ class Input extends React.Component<TypeProps> {
|
|
|
107
129
|
this.props.onBlur?.(e);
|
|
108
130
|
|
|
109
131
|
handleClear = (e: SyntheticEvent<HTMLButtonElement>) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
} else if (this.props.onChange) {
|
|
113
|
-
this.props.onChange(e, "");
|
|
114
|
-
}
|
|
132
|
+
this.props.onClear?.(e);
|
|
133
|
+
this.props.innerRef?.current?.focus();
|
|
115
134
|
};
|
|
116
135
|
|
|
117
136
|
handleChange = (e: SyntheticInputEvent<HTMLInputElement>) =>
|
|
@@ -160,6 +179,7 @@ class Input extends React.Component<TypeProps> {
|
|
|
160
179
|
inputProps = {},
|
|
161
180
|
qa = {},
|
|
162
181
|
appearance,
|
|
182
|
+
size,
|
|
163
183
|
...rest
|
|
164
184
|
} = this.props;
|
|
165
185
|
|
|
@@ -172,12 +192,13 @@ class Input extends React.Component<TypeProps> {
|
|
|
172
192
|
// Add default elemBefore and elemAfter elements if type is search.
|
|
173
193
|
const elementBefore =
|
|
174
194
|
type === "search" && !elemBefore ? (
|
|
175
|
-
<Icon name="search" ariaHidden />
|
|
195
|
+
<Icon name="search" ariaHidden color="icon.base" />
|
|
176
196
|
) : (
|
|
177
197
|
elemBefore
|
|
178
198
|
);
|
|
199
|
+
// Do not add a ClearButton if no onClear callback is provided or if an elemAfter prop was passed.
|
|
179
200
|
const elementAfter =
|
|
180
|
-
type === "search" && !elemAfter ? <ClearButton /> : elemAfter;
|
|
201
|
+
type === "search" && onClear && !elemAfter ? <ClearButton /> : elemAfter;
|
|
181
202
|
|
|
182
203
|
return (
|
|
183
204
|
<Container
|
|
@@ -187,13 +208,16 @@ class Input extends React.Component<TypeProps> {
|
|
|
187
208
|
invalid={!!isInvalid}
|
|
188
209
|
warning={hasWarning}
|
|
189
210
|
appearance={appearance}
|
|
211
|
+
size={size}
|
|
190
212
|
// $FlowIssue - upgrade v0.112.0
|
|
191
213
|
{...rest}
|
|
192
214
|
>
|
|
193
215
|
<InputContext.Provider
|
|
194
216
|
value={{
|
|
195
217
|
handleClear: this.handleClear,
|
|
218
|
+
hasValue: !!value,
|
|
196
219
|
clearButtonLabel,
|
|
220
|
+
size,
|
|
197
221
|
}}
|
|
198
222
|
>
|
|
199
223
|
{elementBefore && <Accessory before>{elementBefore}</Accessory>}
|
|
@@ -228,14 +252,7 @@ class Input extends React.Component<TypeProps> {
|
|
|
228
252
|
/>
|
|
229
253
|
|
|
230
254
|
{elementAfter && (
|
|
231
|
-
<Accessory
|
|
232
|
-
after
|
|
233
|
-
// Used for positioning. This logic will detect if the element is a ClearButton,
|
|
234
|
-
// regardless of whether it was manually passed as elemAfter or automatically added to a search Input.
|
|
235
|
-
isClearButton={
|
|
236
|
-
elementAfter?.type?.prototype === Input.ClearButton.prototype
|
|
237
|
-
}
|
|
238
|
-
>
|
|
255
|
+
<Accessory after isClearButton={isClearButton(elementAfter)}>
|
|
239
256
|
{elementAfter}
|
|
240
257
|
</Accessory>
|
|
241
258
|
)}
|
|
@@ -156,6 +156,38 @@ searchInput.story = {
|
|
|
156
156
|
name: "Search Input",
|
|
157
157
|
};
|
|
158
158
|
|
|
159
|
+
export const smallSearchInput = () => (
|
|
160
|
+
<Input
|
|
161
|
+
type="search"
|
|
162
|
+
size="small"
|
|
163
|
+
placeholder={text("placeholder", "Please enter a value...")}
|
|
164
|
+
value={text("value", "val")}
|
|
165
|
+
onClear={() => window.alert("Cleared!")}
|
|
166
|
+
clearButtonLabel={text("clearButtonLabel", "Clear search")}
|
|
167
|
+
ariaLabel={text("ariaLabel", "Descriptive label goes here")}
|
|
168
|
+
/>
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
smallSearchInput.story = {
|
|
172
|
+
name: "Small Search Input",
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export const largeSearchInput = () => (
|
|
176
|
+
<Input
|
|
177
|
+
type="search"
|
|
178
|
+
size="large"
|
|
179
|
+
placeholder={text("placeholder", "Please enter a value...")}
|
|
180
|
+
value={text("value", "val")}
|
|
181
|
+
onClear={() => window.alert("Cleared!")}
|
|
182
|
+
clearButtonLabel={text("clearButtonLabel", "Clear search")}
|
|
183
|
+
ariaLabel={text("ariaLabel", "Descriptive label goes here")}
|
|
184
|
+
/>
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
largeSearchInput.story = {
|
|
188
|
+
name: "Large Search Input",
|
|
189
|
+
};
|
|
190
|
+
|
|
159
191
|
export const nonSearchClearButtonInput = () => {
|
|
160
192
|
return (
|
|
161
193
|
<Input
|
|
@@ -171,7 +203,7 @@ export const nonSearchClearButtonInput = () => {
|
|
|
171
203
|
};
|
|
172
204
|
|
|
173
205
|
nonSearchClearButtonInput.story = {
|
|
174
|
-
name: "Input.ClearButton usage",
|
|
206
|
+
name: "Manual Input.ClearButton usage",
|
|
175
207
|
};
|
|
176
208
|
|
|
177
209
|
export const autofocus = () => (
|