@sproutsocial/racine 11.7.0 → 11.9.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/__flow__/Checkbox/index.stories.js +73 -56
  3. package/__flow__/EnumIconNames.js +1 -1
  4. package/__flow__/Icon/index.stories.js +41 -36
  5. package/__flow__/IconViewBoxes.js +1 -1
  6. package/__flow__/Input/index.js +47 -23
  7. package/__flow__/Input/index.stories.js +59 -33
  8. package/__flow__/Input/index.test.js +20 -0
  9. package/__flow__/Input/styles.js +2 -2
  10. package/__flow__/Loader/index.stories.js +18 -14
  11. package/__flow__/Numeral/index.stories.js +109 -50
  12. package/__flow__/Radio/index.stories.js +41 -26
  13. package/__flow__/Switch/index.stories.js +26 -18
  14. package/__flow__/themes/extendedThemes/sproutTheme/dark/theme.js +9 -0
  15. package/__flow__/themes/extendedThemes/sproutTheme/light/theme.js +9 -0
  16. package/__flow__/types/theme.flow.js +2 -0
  17. package/commonjs/IconViewBoxes.js +2 -0
  18. package/commonjs/Input/index.js +42 -22
  19. package/commonjs/Input/styles.js +2 -2
  20. package/commonjs/include-icons.js +1 -1
  21. package/commonjs/themes/extendedThemes/sproutTheme/dark/theme.js +11 -2
  22. package/commonjs/themes/extendedThemes/sproutTheme/light/theme.js +11 -2
  23. package/dist/iconList.js +1 -1
  24. package/dist/icons.svg +1 -1
  25. package/dist/themes/extendedThemes/sproutTheme/dark/theme.scss +14 -0
  26. package/dist/themes/extendedThemes/sproutTheme/light/theme.scss +14 -0
  27. package/icons/help-alt.svg +3 -0
  28. package/icons/plug.svg +3 -0
  29. package/includeIcons.js +1 -1
  30. package/lib/IconViewBoxes.js +2 -0
  31. package/lib/Input/index.js +42 -22
  32. package/lib/Input/styles.js +2 -2
  33. package/lib/include-icons.js +1 -1
  34. package/lib/themes/extendedThemes/sproutTheme/dark/theme.js +9 -1
  35. package/lib/themes/extendedThemes/sproutTheme/light/theme.js +9 -1
  36. package/lib/types/theme.flow.js +1 -1
  37. package/package.json +1 -1
@@ -141,60 +141,86 @@ leftAndRightIcons.story = {
141
141
  name: "Left and right icons",
142
142
  };
143
143
 
144
- export const searchInput = () => (
145
- <Input
146
- type="search"
147
- placeholder={text("placeholder", "Please enter a value...")}
148
- value={text("value", "val")}
149
- onClear={() => window.alert("Cleared!")}
150
- clearButtonLabel={text("clearButtonLabel", "Clear search")}
151
- ariaLabel={text("ariaLabel", "Descriptive label goes here")}
152
- />
153
- );
144
+ export const SearchInput = () => {
145
+ const [value, setValue] = React.useState("");
146
+ return (
147
+ <Input
148
+ type="search"
149
+ placeholder={text("placeholder", "Please enter a value...")}
150
+ value={value}
151
+ onChange={(e, value) => setValue(value)}
152
+ clearButtonLabel={text("clearButtonLabel", "Clear search")}
153
+ ariaLabel={text("ariaLabel", "Descriptive label goes here")}
154
+ />
155
+ );
156
+ };
154
157
 
155
- searchInput.story = {
158
+ SearchInput.story = {
156
159
  name: "Search Input",
157
160
  };
158
161
 
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
- );
162
+ export const SmallSearchInput = () => {
163
+ const [value, setValue] = React.useState("");
170
164
 
171
- smallSearchInput.story = {
165
+ return (
166
+ <Input
167
+ type="search"
168
+ size="small"
169
+ placeholder={text("placeholder", "Please enter a value...")}
170
+ value={value}
171
+ onChange={(e, value) => setValue(value)}
172
+ clearButtonLabel={text("clearButtonLabel", "Clear search")}
173
+ ariaLabel={text("ariaLabel", "Descriptive label goes here")}
174
+ />
175
+ );
176
+ };
177
+
178
+ SmallSearchInput.story = {
172
179
  name: "Small Search Input",
173
180
  };
174
181
 
175
- export const largeSearchInput = () => (
182
+ export const LargeSearchInput = () => {
183
+ const [value, setValue] = React.useState("");
184
+
185
+ return (
186
+ <Input
187
+ type="search"
188
+ size="large"
189
+ placeholder={text("placeholder", "Please enter a value...")}
190
+ value={value}
191
+ onChange={(e, value) => setValue(value)}
192
+ clearButtonLabel={text("clearButtonLabel", "Clear search")}
193
+ ariaLabel={text("ariaLabel", "Descriptive label goes here")}
194
+ />
195
+ );
196
+ };
197
+
198
+ LargeSearchInput.story = {
199
+ name: "Large Search Input",
200
+ };
201
+
202
+ export const uncontrolledSearchInput = () => (
176
203
  <Input
177
204
  type="search"
178
- size="large"
179
205
  placeholder={text("placeholder", "Please enter a value...")}
180
- value={text("value", "val")}
181
- onClear={() => window.alert("Cleared!")}
182
206
  clearButtonLabel={text("clearButtonLabel", "Clear search")}
183
207
  ariaLabel={text("ariaLabel", "Descriptive label goes here")}
184
208
  />
185
209
  );
186
210
 
187
- largeSearchInput.story = {
188
- name: "Large Search Input",
211
+ uncontrolledSearchInput.story = {
212
+ name: "Uncontrolled Search Input",
189
213
  };
190
214
 
191
- export const nonSearchClearButtonInput = () => {
215
+ export const NonSearchClearButtonInput = () => {
216
+ const [value, setValue] = React.useState("");
217
+
192
218
  return (
193
219
  <Input
194
220
  type="text"
195
221
  placeholder={text("placeholder", "Please enter a value...")}
196
- value={text("value", "val")}
197
- onClear={() => window.alert("Cleared!")}
222
+ value={value}
223
+ onChange={(e, value) => setValue(value)}
198
224
  ariaLabel={text("ariaLabel", "Descriptive label goes here")}
199
225
  clearButtonLabel={text("clearButtonLabel", "Clear text")}
200
226
  elemAfter={<Input.ClearButton />}
@@ -202,7 +228,7 @@ export const nonSearchClearButtonInput = () => {
202
228
  );
203
229
  };
204
230
 
205
- nonSearchClearButtonInput.story = {
231
+ NonSearchClearButtonInput.story = {
206
232
  name: "Manual Input.ClearButton usage",
207
233
  };
208
234
 
@@ -85,6 +85,26 @@ describe("Input", () => {
85
85
  expect(getByRole("button")).toBeTruthy();
86
86
  });
87
87
 
88
+ it("should render a clear button for an uncontrolled search Input only when it has text", () => {
89
+ const { getByRole, queryByRole } = render(
90
+ <Input
91
+ id="name"
92
+ name="name"
93
+ type="search"
94
+ clearButtonLabel="Clear search"
95
+ />
96
+ );
97
+ expect(queryByRole("button")).toBeFalsy();
98
+ const input = getByRole("searchbox");
99
+ userEvent.tab();
100
+ expect(input).toHaveFocus();
101
+ userEvent.keyboard("some text");
102
+ expect(getByRole("button")).toBeTruthy();
103
+ userEvent.tab();
104
+ userEvent.keyboard("{enter}");
105
+ expect(queryByRole("button")).toBeFalsy();
106
+ });
107
+
88
108
  it("should not render a clear button for search Inputs if there is no text", () => {
89
109
  const { queryByRole } = render(
90
110
  <Input
@@ -134,13 +134,13 @@ export const Accessory: StyledComponent<any, TypeTheme, *> = styled.div`
134
134
  ${(props) =>
135
135
  props.before &&
136
136
  css`
137
- left: ${props.theme.space[350]};
137
+ left: ${props.theme.space[300]};
138
138
  `};
139
139
 
140
140
  ${(props) =>
141
141
  props.after &&
142
142
  css`
143
- right: ${props.isClearButton ? 0 : props.theme.space[350]};
143
+ right: ${props.isClearButton ? 0 : props.theme.space[300]};
144
144
  `};
145
145
  `;
146
146
 
@@ -1,34 +1,38 @@
1
1
  import React from "react";
2
- import { boolean, text } from "@storybook/addon-knobs";
3
-
4
2
  import Loader from "./";
5
3
 
6
4
  export default {
7
5
  title: "Loader",
6
+ component: Loader,
8
7
  };
9
8
 
10
- export const defaultStory = () => (
11
- <Loader text={text("text", "Content loading")} />
12
- );
9
+ export const defaultStory = (args) => <Loader {...args} />;
10
+
11
+ defaultStory.args = {
12
+ text: "Content loading",
13
+ };
13
14
 
14
15
  defaultStory.story = {
15
16
  name: "Default",
16
17
  };
17
18
 
18
- export const small = () => (
19
- <Loader text={text("text", "Content loading")} size={text("size", "small")} />
20
- );
19
+ export const small = (args) => <Loader {...args} />;
20
+
21
+ small.args = {
22
+ text: "Content loading",
23
+ size: "small",
24
+ };
21
25
 
22
26
  small.story = {
23
27
  name: "Small",
24
28
  };
25
29
 
26
- export const noDelay = () => (
27
- <Loader
28
- text={text("text", "Content loading")}
29
- delay={boolean("delay", false)}
30
- />
31
- );
30
+ export const noDelay = (args) => <Loader {...args} />;
31
+
32
+ noDelay.args = {
33
+ text: "Content loading",
34
+ delay: false,
35
+ };
32
36
 
33
37
  noDelay.story = {
34
38
  name: "No delay",
@@ -1,9 +1,22 @@
1
1
  import React from "react";
2
- import { number, select } from "@storybook/addon-knobs";
3
2
  import Numeral from "./index";
4
3
 
5
- const localeOptions = {
6
- "": null,
4
+ const localeOptions = [
5
+ "United States (en-US)",
6
+ "English (en)",
7
+ "Arabic (ar-EG)",
8
+ "Brazil (pt-BR)",
9
+ "India (en-IN)",
10
+ "French (fr-FR)",
11
+ "Spain (es-ES)",
12
+ "Mexico (es-MX)",
13
+ "Germany (de-DE)",
14
+ "German (de)",
15
+ "Japan (ja-JP)",
16
+ "Japanese (ja)",
17
+ ];
18
+
19
+ const localeMapping = {
7
20
  "United States (en-US)": "en-US",
8
21
  "English (en)": "en",
9
22
  "Arabic (ar-EG)": "ar-EG",
@@ -18,8 +31,15 @@ const localeOptions = {
18
31
  "Japanese (ja)": "ja",
19
32
  };
20
33
 
21
- const currencyOptions = {
22
- "": null,
34
+ const currencyOptions = [
35
+ "Egyptian £",
36
+ "European €",
37
+ "Indian ₹",
38
+ "Japanese ¥",
39
+ "USA $",
40
+ ];
41
+
42
+ const currencyMapping = {
23
43
  "Egyptian £": "EGP",
24
44
  "European €": "EUR",
25
45
  "Indian ₹": "INR",
@@ -27,15 +47,24 @@ const currencyOptions = {
27
47
  "USA $": "USD",
28
48
  };
29
49
 
30
- const formatOptions = {
31
- "": null,
50
+ const formatOptions = ["decimal", "currency", "percent"];
51
+
52
+ const formatMapping = {
32
53
  decimal: "decimal",
33
54
  currency: "currency",
34
55
  percent: "percent",
35
56
  };
36
57
 
37
- const abbreviateOptions = {
38
- "": null,
58
+ const abbreviateOptions = [
59
+ "true",
60
+ "false",
61
+ " 500",
62
+ "1_000",
63
+ "10_000",
64
+ "100_000",
65
+ ];
66
+
67
+ const abbreviateMapping = {
39
68
  true: true,
40
69
  false: false,
41
70
  " 500": 500,
@@ -44,79 +73,109 @@ const abbreviateOptions = {
44
73
  "100_000": 100000,
45
74
  };
46
75
 
47
- const precisionOptions = {
48
- "": null,
49
- " 0": 0,
50
- " 1": 1,
51
- " 2": 2,
52
- " 3": 3,
53
- " 6": 6,
76
+ const precisionOptions = ["0", "1", "2", "3", "6", "none"];
77
+
78
+ const precisionMapping = {
79
+ "0": 0,
80
+ "1": 1,
81
+ "2": 2,
82
+ "3": 3,
83
+ "6": 6,
54
84
  none: "none",
55
85
  };
56
86
 
57
87
  export default {
58
88
  title: "Numeral",
89
+ component: Numeral,
90
+ argTypes: {
91
+ locale: {
92
+ control: "select",
93
+ options: localeOptions,
94
+ mapping: localeMapping,
95
+ },
96
+ format: {
97
+ control: "select",
98
+ options: formatOptions,
99
+ mapping: formatMapping,
100
+ },
101
+ currency: {
102
+ control: "select",
103
+ options: currencyOptions,
104
+ mapping: currencyMapping,
105
+ },
106
+ abbreviate: {
107
+ control: "select",
108
+ options: abbreviateOptions,
109
+ mapping: abbreviateMapping,
110
+ },
111
+ precision: {
112
+ control: "select",
113
+ options: precisionOptions,
114
+ mapping: precisionMapping,
115
+ },
116
+ },
117
+ args: {
118
+ color: "text.headline",
119
+ number: 12.89,
120
+ },
59
121
  };
60
122
 
61
- // We wrap the knobs select function to properly create undefined values
62
- const _select = (...args) => {
63
- const answer = select(...args);
64
-
65
- return answer === null ? undefined : answer;
66
- };
67
-
68
- export const defaultStory = () => (
69
- <Numeral
70
- number={number("Number", 12.89)}
71
- locale={_select("Locale", localeOptions)}
72
- format={_select("Format", formatOptions)}
73
- currency={_select("Currency", currencyOptions)}
74
- abbreviate={_select("Abbreviate", abbreviateOptions)}
75
- precision={_select("Precision", precisionOptions)}
76
- color="text.headline"
77
- />
78
- );
123
+ export const defaultStory = (args) => <Numeral {...args} />;
79
124
 
80
125
  defaultStory.story = {
81
126
  name: "Default",
82
127
  };
83
128
 
84
- export const total = () => (
85
- <Numeral
86
- number={100}
87
- fontWeight="semibold"
88
- fontSize={500}
89
- color="text.headline"
90
- />
91
- );
129
+ export const total = (args) => <Numeral {...args} />;
130
+
131
+ total.args = {
132
+ number: 100,
133
+ fontWeight: "semibold",
134
+ fontSize: 500,
135
+ };
92
136
 
93
137
  total.story = {
94
138
  name: "Total",
95
139
  };
96
140
 
97
- export const trend = () => <Numeral number={100} color="teal.500" />;
141
+ export const trend = (args) => <Numeral {...args} />;
142
+
143
+ trend.args = {
144
+ number: 100,
145
+ color: "teal.500",
146
+ };
98
147
 
99
148
  trend.story = {
100
149
  name: "Trend",
101
150
  };
102
151
 
103
- export const noPrecision = () => (
104
- <Numeral number={123.45678} precision="none" color="text.headline" />
105
- );
152
+ export const noPrecision = (args) => <Numeral {...args} />;
153
+
154
+ noPrecision.args = {
155
+ number: 123.45678,
156
+ precision: "none",
157
+ };
106
158
 
107
159
  noPrecision.story = {
108
160
  name: "No Precision",
109
161
  };
110
162
 
111
- export const currencyPrecision = () => (
112
- <Numeral number={123.4} format="currency" color="text.headline" />
113
- );
163
+ export const currencyPrecision = (args) => <Numeral {...args} />;
164
+
165
+ currencyPrecision.args = {
166
+ number: 123.4,
167
+ format: "currency",
168
+ };
114
169
 
115
170
  currencyPrecision.story = {
116
171
  name: "Currency precision",
117
172
  };
118
173
 
119
- export const invalid = () => <Numeral number={null} />;
174
+ export const invalid = (args) => <Numeral {...args} />;
175
+
176
+ invalid.args = {
177
+ number: null,
178
+ };
120
179
 
121
180
  invalid.story = {
122
181
  name: "Invalid",
@@ -1,58 +1,73 @@
1
1
  import React from "react";
2
- import { boolean } from "@storybook/addon-knobs";
3
-
4
2
  import Radio from "./";
5
3
 
6
4
  export default {
7
5
  title: "Radio",
6
+ component: Radio,
7
+ };
8
+
9
+ export const Unchecked = (args) => <Radio {...args} />;
10
+
11
+ Unchecked.args = {
12
+ checked: false,
8
13
  };
9
14
 
10
- export const Unchecked = () => <Radio checked={boolean("checked", false)} />;
15
+ export const Checked = (args) => <Radio {...args} />;
11
16
 
12
- export const Checked = () => <Radio checked={boolean("checked", true)} />;
17
+ Checked.args = {
18
+ checked: true,
19
+ };
20
+
21
+ export const DisabledUnchecked = (args) => <Radio {...args} />;
13
22
 
14
- export const DisabledUnchecked = () => (
15
- <Radio disabled={boolean("disabled", true)} />
16
- );
23
+ DisabledUnchecked.args = {
24
+ disabled: true,
25
+ };
17
26
 
18
27
  DisabledUnchecked.story = {
19
28
  name: "Disabled/Unchecked",
20
29
  };
21
30
 
22
- export const DisabledChecked = () => (
23
- <Radio
24
- checked={boolean("checked", true)}
25
- disabled={boolean("disabled", true)}
26
- />
27
- );
31
+ export const DisabledChecked = (args) => <Radio {...args} />;
32
+
33
+ DisabledChecked.args = {
34
+ checked: true,
35
+ disabled: true,
36
+ };
28
37
 
29
38
  DisabledChecked.story = {
30
39
  name: "Disabled/Checked",
31
40
  };
32
41
 
33
- export const LabelledChecked = () => (
34
- <Radio checked={boolean("checked", true)} label="Toggle Me" />
35
- );
42
+ export const LabelledChecked = (args) => <Radio {...args} />;
43
+
44
+ LabelledChecked.args = {
45
+ checked: true,
46
+ label: "Toggle Me",
47
+ };
36
48
 
37
49
  LabelledChecked.story = {
38
50
  name: "Labelled/Checked",
39
51
  };
40
52
 
41
- export const LabelledUnchecked = () => (
42
- <Radio checked={boolean("checked", false)} label="Toggle Me" />
43
- );
53
+ export const LabelledUnchecked = (args) => <Radio {...args} />;
54
+
55
+ LabelledUnchecked.args = {
56
+ checked: false,
57
+ label: "Toggle Me",
58
+ };
44
59
 
45
60
  LabelledUnchecked.story = {
46
61
  name: "Labelled/Unchecked",
47
62
  };
48
63
 
49
- export const LabelledDisabled = () => (
50
- <Radio
51
- checked={boolean("checked", true)}
52
- disabled={boolean("disabled", true)}
53
- label="Toggle Me"
54
- />
55
- );
64
+ export const LabelledDisabled = (args) => <Radio {...args} />;
65
+
66
+ LabelledDisabled.args = {
67
+ checked: false,
68
+ disabled: true,
69
+ label: "Toggle Me",
70
+ };
56
71
 
57
72
  LabelledDisabled.story = {
58
73
  name: "Labelled/Disabled",
@@ -1,33 +1,41 @@
1
1
  import React from "react";
2
- import { boolean } from "@storybook/addon-knobs";
3
-
4
2
  import Switch from "./";
5
3
 
6
4
  export default {
7
5
  title: "Switch",
6
+ component: Switch,
8
7
  };
9
8
 
10
- export const Off = () => <Switch checked={boolean("checked", false)} />;
11
- export const On = () => <Switch checked={boolean("checked", true)} />;
9
+ export const On = (args) => <Switch {...args} />;
12
10
 
13
- export const DisabledOff = () => (
14
- <Switch
15
- checked={boolean("checked", false)}
16
- disabled={boolean("disabled", true)}
17
- />
18
- );
11
+ On.args = {
12
+ checked: true,
13
+ };
19
14
 
20
- DisabledOff.story = {
21
- name: "Disabled/Off",
15
+ export const Off = (args) => <Switch {...args} />;
16
+
17
+ Off.args = {
18
+ checked: false,
22
19
  };
23
20
 
24
- export const DisabledOn = () => (
25
- <Switch
26
- checked={boolean("checked", true)}
27
- disabled={boolean("disabled", true)}
28
- />
29
- );
21
+ export const DisabledOn = (args) => <Switch {...args} />;
22
+
23
+ DisabledOn.args = {
24
+ checked: true,
25
+ disabled: true,
26
+ };
30
27
 
31
28
  DisabledOn.story = {
32
29
  name: "Disabled/On",
33
30
  };
31
+
32
+ export const DisabledOff = (args) => <Switch {...args} />;
33
+
34
+ DisabledOff.args = {
35
+ checked: false,
36
+ disabled: true,
37
+ };
38
+
39
+ DisabledOff.story = {
40
+ name: "Disabled/Off",
41
+ };
@@ -42,12 +42,21 @@ export const datePicker = {
42
42
  },
43
43
  };
44
44
 
45
+ export const analytics = {
46
+ trend: {
47
+ positive: baseDarkTheme.colors.teal[500],
48
+ neutral: baseDarkTheme.colors.neutral[100],
49
+ negative: baseDarkTheme.colors.neutral[100],
50
+ },
51
+ };
52
+
45
53
  const darkTheme: TypeSproutTheme = {
46
54
  ...baseDarkTheme,
47
55
  colors: {
48
56
  ...baseDarkTheme.colors,
49
57
  navigation,
50
58
  datePicker,
59
+ analytics,
51
60
  },
52
61
  };
53
62
 
@@ -42,12 +42,21 @@ export const datePicker = {
42
42
  },
43
43
  };
44
44
 
45
+ export const analytics = {
46
+ trend: {
47
+ positive: baseLightTheme.colors.teal[800],
48
+ neutral: baseLightTheme.colors.neutral[800],
49
+ negative: baseLightTheme.colors.neutral[800],
50
+ },
51
+ };
52
+
45
53
  const lightTheme: TypeSproutTheme = {
46
54
  ...baseLightTheme,
47
55
  colors: {
48
56
  ...baseLightTheme.colors,
49
57
  navigation,
50
58
  datePicker,
59
+ analytics,
51
60
  },
52
61
  };
53
62
 
@@ -16,6 +16,7 @@ import type { TypeFontFamilyString } from "../themes/light/theme";
16
16
  import {
17
17
  datePicker,
18
18
  navigation,
19
+ analytics,
19
20
  } from "../themes/extendedThemes/sproutTheme/light/theme";
20
21
 
21
22
  export type TypeThemeUtils = {| interact: (color: string) => string |};
@@ -57,5 +58,6 @@ export type TypeSproutTheme = {
57
58
  ...$Exact<TypeColor>,
58
59
  navigation: typeof navigation,
59
60
  datePicker: typeof datePicker,
61
+ analytics: typeof analytics,
60
62
  |},
61
63
  };
@@ -173,6 +173,7 @@ module.exports = {
173
173
  "heart-outline": "0 0 16 16",
174
174
  "heart": "0 0 16 16",
175
175
  "heartbeat": "0 0 18 16",
176
+ "help-alt": "0 0 12 16",
176
177
  "help": "0 0 16 16",
177
178
  "hiking": "0 0 16 16",
178
179
  "history": "0 0 16 16",
@@ -255,6 +256,7 @@ module.exports = {
255
256
  "pinterest": "0 0 16 16",
256
257
  "play-circle": "0 0 16 16",
257
258
  "play": "0 0 14 16",
259
+ "plug": "0 0 12 16",
258
260
  "plus": "0 0 16 18",
259
261
  "positive-sentiment": "0 0 16 16",
260
262
  "power-up-outline": "0 0 12 16",