@khanacademy/wonder-blocks-icon-button 5.0.0 → 5.1.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/index.js CHANGED
@@ -1,15 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  var React = require('react');
4
- var reactRouter = require('react-router');
5
- var wonderBlocksClickable = require('@khanacademy/wonder-blocks-clickable');
6
4
  var aphrodite = require('aphrodite');
7
5
  var reactRouterDom = require('react-router-dom');
8
- var Color = require('@khanacademy/wonder-blocks-color');
6
+ var reactRouter = require('react-router');
9
7
  var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
8
+ var wonderBlocksClickable = require('@khanacademy/wonder-blocks-clickable');
10
9
  var wonderBlocksIcon = require('@khanacademy/wonder-blocks-icon');
11
-
12
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
+ var wonderBlocksTheming = require('@khanacademy/wonder-blocks-theming');
13
11
 
14
12
  function _interopNamespace(e) {
15
13
  if (e && e.__esModule) return e;
@@ -30,11 +28,6 @@ function _interopNamespace(e) {
30
28
  }
31
29
 
32
30
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
33
- var Color__default = /*#__PURE__*/_interopDefaultLegacy(Color);
34
-
35
- function _objectDestructuringEmpty(obj) {
36
- if (obj == null) throw new TypeError("Cannot destructure " + obj);
37
- }
38
31
 
39
32
  function _extends() {
40
33
  _extends = Object.assign ? Object.assign.bind() : function (target) {
@@ -80,7 +73,155 @@ const targetPixelsForSize = size => ({
80
73
  medium: 40
81
74
  })[size];
82
75
 
83
- const _excluded$1 = ["color", "disabled", "focused", "hovered", "href", "icon", "kind", "light", "pressed", "size", "skipClientNav", "style", "testId", "waiting"];
76
+ const theme$1 = {
77
+ color: {
78
+ bg: {
79
+ hovered: "transparent",
80
+ active: "transparent",
81
+ disabled: "transparent",
82
+ filled: {
83
+ action: {
84
+ hovered: "transparent",
85
+ active: "transparent"
86
+ },
87
+ critical: {
88
+ hovered: "transparent",
89
+ active: "transparent"
90
+ }
91
+ }
92
+ },
93
+ stroke: {
94
+ disabled: {
95
+ default: wonderBlocksTheming.tokens.color.offBlack32,
96
+ inverse: wonderBlocksTheming.tokens.color.white50
97
+ },
98
+ inverse: wonderBlocksTheming.tokens.color.white,
99
+ action: {
100
+ default: wonderBlocksTheming.tokens.color.blue,
101
+ active: wonderBlocksTheming.tokens.color.activeBlue,
102
+ inverse: wonderBlocksTheming.tokens.color.fadedBlue
103
+ },
104
+ critical: {
105
+ default: wonderBlocksTheming.tokens.color.red,
106
+ active: wonderBlocksTheming.tokens.color.activeRed,
107
+ inverse: wonderBlocksTheming.tokens.color.fadedRed
108
+ },
109
+ primary: {
110
+ action: {
111
+ hovered: wonderBlocksTheming.tokens.color.blue,
112
+ active: wonderBlocksTheming.tokens.color.activeBlue
113
+ },
114
+ critical: {
115
+ hovered: wonderBlocksTheming.tokens.color.red,
116
+ active: wonderBlocksTheming.tokens.color.activeRed
117
+ },
118
+ inverse: {
119
+ default: wonderBlocksTheming.tokens.color.white,
120
+ hovered: wonderBlocksTheming.tokens.color.white
121
+ }
122
+ },
123
+ secondary: {
124
+ default: wonderBlocksTheming.tokens.color.offBlack
125
+ },
126
+ tertiary: {
127
+ default: wonderBlocksTheming.tokens.color.offBlack64
128
+ },
129
+ filled: {
130
+ action: {
131
+ hovered: wonderBlocksTheming.tokens.color.blue,
132
+ active: wonderBlocksTheming.tokens.color.activeBlue
133
+ },
134
+ critical: {
135
+ hovered: wonderBlocksTheming.tokens.color.red,
136
+ active: wonderBlocksTheming.tokens.color.activeRed
137
+ }
138
+ }
139
+ }
140
+ },
141
+ border: {
142
+ width: {
143
+ default: wonderBlocksTheming.tokens.border.width.thin,
144
+ active: wonderBlocksTheming.tokens.border.width.none,
145
+ hovered: wonderBlocksTheming.tokens.border.width.thin,
146
+ hoveredInverse: wonderBlocksTheming.tokens.border.width.thin
147
+ },
148
+ radius: {
149
+ default: wonderBlocksTheming.tokens.border.radius.medium_4
150
+ }
151
+ }
152
+ };
153
+
154
+ const theme = wonderBlocksTheming.mergeTheme(theme$1, {
155
+ color: {
156
+ bg: {
157
+ hovered: wonderBlocksTheming.tokens.color.white,
158
+ active: wonderBlocksTheming.tokens.color.white64,
159
+ filled: {
160
+ action: {
161
+ hovered: wonderBlocksTheming.tokens.color.blue,
162
+ active: wonderBlocksTheming.tokens.color.activeBlue
163
+ },
164
+ critical: {
165
+ hovered: wonderBlocksTheming.tokens.color.red,
166
+ active: wonderBlocksTheming.tokens.color.activeRed
167
+ }
168
+ }
169
+ },
170
+ stroke: {
171
+ action: {
172
+ inverse: wonderBlocksTheming.tokens.color.eggplant
173
+ },
174
+ critical: {
175
+ inverse: wonderBlocksTheming.tokens.color.eggplant
176
+ },
177
+ primary: {
178
+ action: {
179
+ hovered: wonderBlocksTheming.tokens.color.eggplant,
180
+ active: wonderBlocksTheming.tokens.color.eggplant
181
+ },
182
+ critical: {
183
+ hovered: wonderBlocksTheming.tokens.color.eggplant,
184
+ active: wonderBlocksTheming.tokens.color.eggplant
185
+ },
186
+ inverse: {
187
+ hovered: wonderBlocksTheming.tokens.color.eggplant
188
+ }
189
+ },
190
+ filled: {
191
+ action: {
192
+ hovered: wonderBlocksTheming.tokens.color.white,
193
+ active: wonderBlocksTheming.tokens.color.white
194
+ },
195
+ critical: {
196
+ hovered: wonderBlocksTheming.tokens.color.white,
197
+ active: wonderBlocksTheming.tokens.color.white
198
+ }
199
+ }
200
+ }
201
+ },
202
+ border: {
203
+ width: {
204
+ hovered: wonderBlocksTheming.tokens.border.width.none,
205
+ hoveredInverse: wonderBlocksTheming.tokens.border.width.none
206
+ }
207
+ }
208
+ });
209
+
210
+ const themes = {
211
+ default: theme$1,
212
+ khanmigo: theme
213
+ };
214
+ const IconButtonThemeContext = wonderBlocksTheming.createThemeContext(theme$1);
215
+ function ThemedIconButton(props) {
216
+ var _themes$currentTheme;
217
+ const currentTheme = React__namespace.useContext(wonderBlocksTheming.ThemeSwitcherContext);
218
+ const theme = (_themes$currentTheme = themes[currentTheme]) != null ? _themes$currentTheme : theme$1;
219
+ return React__namespace.createElement(IconButtonThemeContext.Provider, {
220
+ value: theme
221
+ }, props.children);
222
+ }
223
+
224
+ const _excluded$1 = ["color", "disabled", "href", "icon", "kind", "light", "size", "skipClientNav", "style", "testId"];
84
225
  function IconChooser({
85
226
  icon,
86
227
  size
@@ -109,23 +250,23 @@ const IconButtonCore = React__namespace.forwardRef(function IconButtonCore(props
109
250
  const {
110
251
  color,
111
252
  disabled,
112
- focused,
113
- hovered,
114
253
  href,
115
254
  icon,
116
255
  kind = "primary",
117
256
  light = false,
118
- pressed,
119
257
  size = "medium",
120
258
  skipClientNav,
121
259
  style,
122
260
  testId
123
261
  } = props,
124
262
  restProps = _objectWithoutPropertiesLoose(props, _excluded$1);
263
+ const {
264
+ theme,
265
+ themeName
266
+ } = wonderBlocksTheming.useScopedTheme(IconButtonThemeContext);
125
267
  const renderInner = router => {
126
- const buttonColor = color === "destructive" ? Color.SemanticColor.controlDestructive : Color.SemanticColor.controlDefault;
127
- const buttonStyles = _generateStyles(buttonColor, kind, light, size);
128
- const defaultStyle = [sharedStyles.shared, buttonStyles.default, disabled && buttonStyles.disabled, !disabled && (pressed ? buttonStyles.active : (hovered || focused) && buttonStyles.focus)];
268
+ const buttonStyles = _generateStyles(color, kind, light, size, theme, themeName);
269
+ const defaultStyle = [sharedStyles.shared, buttonStyles.default, disabled && buttonStyles.disabled];
129
270
  const child = React__namespace.createElement(IconChooser, {
130
271
  size: size,
131
272
  icon: icon
@@ -146,7 +287,8 @@ const IconButtonCore = React__namespace.forwardRef(function IconButtonCore(props
146
287
  return React__namespace.createElement(StyledButton, _extends({
147
288
  type: "button"
148
289
  }, commonProps, {
149
- disabled: disabled,
290
+ onClick: disabled ? undefined : restProps.onClick,
291
+ "aria-disabled": disabled,
150
292
  ref: ref
151
293
  }), child);
152
294
  }
@@ -167,70 +309,141 @@ const sharedStyles = aphrodite.StyleSheet.create({
167
309
  textDecoration: "none",
168
310
  background: "none",
169
311
  margin: -8,
170
- touchAction: "manipulation",
171
- ":focus": {
172
- WebkitTapHighlightColor: "rgba(0,0,0,0)"
173
- }
312
+ touchAction: "manipulation"
174
313
  }
175
314
  });
176
315
  const styles = {};
177
- const _generateStyles = (color, kind, light, size) => {
178
- const buttonType = `${color}-${kind}-${light}-${size}`;
316
+ function getStylesByKind(kind, theme, color, light, buttonColor) {
317
+ switch (kind) {
318
+ case "primary":
319
+ const primaryHoveredColor = buttonColor === "destructive" ? theme.color.stroke.primary.critical.hovered : theme.color.stroke.primary.action.hovered;
320
+ return {
321
+ ":hover": {
322
+ backgroundColor: theme.color.bg.hovered,
323
+ color: light ? theme.color.stroke.primary.inverse.hovered : primaryHoveredColor,
324
+ outlineColor: light ? theme.color.stroke.inverse : color,
325
+ outlineOffset: 1,
326
+ outlineStyle: "solid",
327
+ outlineWidth: light ? theme.border.width.hoveredInverse : theme.border.width.hovered
328
+ },
329
+ ":active": {
330
+ backgroundColor: theme.color.bg.active
331
+ }
332
+ };
333
+ case "secondary":
334
+ case "tertiary":
335
+ return {
336
+ ":hover": {
337
+ backgroundColor: buttonColor === "destructive" ? theme.color.bg.filled.critical.hovered : theme.color.bg.filled.action.hovered,
338
+ color: buttonColor === "destructive" ? theme.color.stroke.filled.critical.hovered : theme.color.stroke.filled.action.hovered,
339
+ outlineWidth: theme.border.width.active
340
+ },
341
+ ":active": {
342
+ backgroundColor: buttonColor === "destructive" ? theme.color.bg.filled.critical.active : theme.color.bg.filled.action.active,
343
+ color: buttonColor === "destructive" ? theme.color.stroke.filled.critical.active : theme.color.stroke.filled.action.active,
344
+ outlineWidth: theme.border.width.active
345
+ }
346
+ };
347
+ default:
348
+ return {
349
+ ":focus-visible": {},
350
+ ":hover": {},
351
+ ":active": {}
352
+ };
353
+ }
354
+ }
355
+ const _generateStyles = (buttonColor = "default", kind, light, size, theme, themeName) => {
356
+ const color = buttonColor === "destructive" ? theme.color.stroke.critical.default : theme.color.stroke.action.default;
357
+ const buttonType = `${color}-${kind}-${light}-${size}-${themeName}`;
179
358
  if (styles[buttonType]) {
180
359
  return styles[buttonType];
181
360
  }
182
361
  if (light && kind !== "primary") {
183
362
  throw new Error("Light is only supported for primary IconButtons");
184
363
  }
185
- const {
186
- white,
187
- offBlack32,
188
- offBlack64,
189
- offBlack
190
- } = Color__default["default"];
191
364
  const defaultColor = (() => {
192
365
  switch (kind) {
193
366
  case "primary":
194
- return light ? white : color;
367
+ return light ? theme.color.stroke.primary.inverse.default : color;
195
368
  case "secondary":
196
- return offBlack;
369
+ return theme.color.stroke.secondary.default;
197
370
  case "tertiary":
198
- return offBlack64;
371
+ return theme.color.stroke.tertiary.default;
199
372
  default:
200
373
  throw new Error("IconButton kind not recognized");
201
374
  }
202
375
  })();
203
376
  const pixelsForSize = targetPixelsForSize(size);
377
+ const kindOverrides = getStylesByKind(kind, theme, color, light, buttonColor);
378
+ const activeInverseColor = buttonColor === "destructive" ? theme.color.stroke.critical.inverse : theme.color.stroke.action.inverse;
379
+ const activeColor = buttonColor === "destructive" ? theme.color.stroke.critical.active : theme.color.stroke.action.active;
380
+ const defaultStrokeColor = light ? theme.color.stroke.inverse : color;
381
+ const disabledStrokeColor = light ? theme.color.stroke.disabled.inverse : theme.color.stroke.disabled.default;
382
+ const disabledStatesStyles = {
383
+ backgroundColor: theme.color.bg.disabled,
384
+ color: disabledStrokeColor,
385
+ outlineColor: disabledStrokeColor
386
+ };
204
387
  const newStyles = {
205
388
  default: {
206
389
  height: pixelsForSize,
207
390
  width: pixelsForSize,
208
- color: defaultColor
209
- },
210
- focus: {
211
- color: light ? white : color,
212
- borderWidth: 2,
213
- borderColor: light ? white : color,
214
- borderStyle: "solid",
215
- borderRadius: 4
216
- },
217
- active: {
218
- color: light ? Color.mix(Color.fade(color, 0.32), white) : Color.mix(offBlack32, color),
219
- borderWidth: 2,
220
- borderColor: light ? Color.mix(Color.fade(color, 0.32), white) : Color.mix(offBlack32, color),
221
- borderStyle: "solid",
222
- borderRadius: 4
391
+ color: defaultColor,
392
+ borderRadius: theme.border.radius.default,
393
+ ":hover": _extends({
394
+ boxShadow: "none",
395
+ color: defaultStrokeColor,
396
+ borderRadius: theme.border.radius.default,
397
+ outlineWidth: theme.border.width.default
398
+ }, kindOverrides[":hover"]),
399
+ ":focus": {
400
+ boxShadow: `0 0 0 ${theme.border.width.default}px ${defaultStrokeColor}`,
401
+ borderRadius: theme.border.radius.default
402
+ },
403
+ ":focus:not(:focus-visible)": {
404
+ boxShadow: "none"
405
+ },
406
+ ":focus-visible": _extends({
407
+ boxShadow: "none",
408
+ outlineWidth: theme.border.width.default,
409
+ outlineColor: defaultStrokeColor,
410
+ outlineOffset: 1,
411
+ outlineStyle: "solid",
412
+ borderRadius: theme.border.radius.default
413
+ }, kindOverrides[":focus-visible"]),
414
+ ":active": _extends({
415
+ color: light ? activeInverseColor : activeColor,
416
+ outlineWidth: theme.border.width.default,
417
+ outlineColor: light ? activeInverseColor : activeColor,
418
+ outlineOffset: 1,
419
+ outlineStyle: "solid",
420
+ borderRadius: theme.border.radius.default
421
+ }, kindOverrides[":active"])
223
422
  },
224
423
  disabled: {
225
- color: light ? Color.mix(Color.fade(white, 0.32), color) : offBlack32,
226
- cursor: "default"
424
+ color: disabledStrokeColor,
425
+ cursor: "not-allowed",
426
+ ":hover": _extends({}, disabledStatesStyles, {
427
+ outline: "none"
428
+ }),
429
+ ":active": _extends({}, disabledStatesStyles, {
430
+ outline: "none"
431
+ }),
432
+ ":focus": {
433
+ boxShadow: `0 0 0 ${theme.border.width.default}px ${disabledStrokeColor}`,
434
+ borderRadius: theme.border.radius.default
435
+ },
436
+ ":focus:not(:focus-visible)": {
437
+ boxShadow: "none"
438
+ },
439
+ ":focus-visible": disabledStatesStyles
227
440
  }
228
441
  };
229
442
  styles[buttonType] = aphrodite.StyleSheet.create(newStyles);
230
443
  return styles[buttonType];
231
444
  };
232
445
 
233
- const _excluded = ["color", "disabled", "href", "kind", "light", "onClick", "size", "skipClientNav", "tabIndex", "target"];
446
+ const _excluded = ["color", "disabled", "href", "kind", "light", "size", "skipClientNav", "tabIndex", "target"];
234
447
  const IconButton = React__namespace.forwardRef(function IconButton(props, ref) {
235
448
  const {
236
449
  color = "default",
@@ -238,38 +451,24 @@ const IconButton = React__namespace.forwardRef(function IconButton(props, ref) {
238
451
  href,
239
452
  kind = "primary",
240
453
  light = false,
241
- onClick,
242
454
  size = "medium",
243
455
  skipClientNav,
244
456
  tabIndex,
245
457
  target
246
458
  } = props,
247
459
  sharedProps = _objectWithoutPropertiesLoose(props, _excluded);
248
- const renderClickableBehavior = router => {
249
- const ClickableBehavior = wonderBlocksClickable.getClickableBehavior(href, skipClientNav, router);
250
- return React__namespace.createElement(ClickableBehavior, {
251
- disabled: disabled,
252
- href: href,
253
- onClick: onClick,
254
- role: "button",
255
- target: target
256
- }, (state, _ref) => {
257
- let childrenProps = _extends({}, (_objectDestructuringEmpty(_ref), _ref));
258
- return React__namespace.createElement(IconButtonCore, _extends({}, sharedProps, state, childrenProps, {
259
- color: color,
260
- disabled: disabled,
261
- href: href,
262
- kind: kind,
263
- light: light,
264
- ref: ref,
265
- skipClientNav: skipClientNav,
266
- size: size,
267
- target: target,
268
- tabIndex: tabIndex
269
- }));
270
- });
271
- };
272
- return React__namespace.createElement(reactRouter.__RouterContext.Consumer, null, router => renderClickableBehavior(router));
460
+ return React__namespace.createElement(ThemedIconButton, null, React__namespace.createElement(IconButtonCore, _extends({}, sharedProps, {
461
+ color: color,
462
+ disabled: disabled,
463
+ href: href,
464
+ kind: kind,
465
+ light: light,
466
+ ref: ref,
467
+ skipClientNav: skipClientNav,
468
+ size: size,
469
+ target: target,
470
+ tabIndex: tabIndex
471
+ })));
273
472
  });
274
473
 
275
474
  module.exports = IconButton;
@@ -0,0 +1,93 @@
1
+ declare const theme: {
2
+ color: {
3
+ bg: {
4
+ /**
5
+ * Default
6
+ */
7
+ hovered: string;
8
+ active: string;
9
+ disabled: string;
10
+ /**
11
+ * Kind
12
+ */
13
+ filled: {
14
+ action: {
15
+ hovered: string;
16
+ active: string;
17
+ };
18
+ critical: {
19
+ hovered: string;
20
+ active: string;
21
+ };
22
+ };
23
+ };
24
+ stroke: {
25
+ /**
26
+ * Default
27
+ */
28
+ disabled: {
29
+ default: string;
30
+ inverse: string;
31
+ };
32
+ inverse: string;
33
+ /**
34
+ * Color
35
+ */
36
+ action: {
37
+ default: string;
38
+ active: string;
39
+ inverse: string;
40
+ };
41
+ critical: {
42
+ default: string;
43
+ active: string;
44
+ inverse: string;
45
+ };
46
+ /**
47
+ * Kind
48
+ */
49
+ primary: {
50
+ action: {
51
+ hovered: string;
52
+ active: string;
53
+ };
54
+ critical: {
55
+ hovered: string;
56
+ active: string;
57
+ };
58
+ inverse: {
59
+ default: string;
60
+ hovered: string;
61
+ };
62
+ };
63
+ secondary: {
64
+ default: string;
65
+ };
66
+ tertiary: {
67
+ default: string;
68
+ };
69
+ filled: {
70
+ action: {
71
+ hovered: string;
72
+ active: string;
73
+ };
74
+ critical: {
75
+ hovered: string;
76
+ active: string;
77
+ };
78
+ };
79
+ };
80
+ };
81
+ border: {
82
+ width: {
83
+ default: number;
84
+ active: number;
85
+ hovered: number;
86
+ hoveredInverse: number;
87
+ };
88
+ radius: {
89
+ default: number;
90
+ };
91
+ };
92
+ };
93
+ export default theme;
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The overrides for the Khanmigo theme.
3
+ */
4
+ declare const theme: {
5
+ color: {
6
+ bg: {
7
+ hovered: string;
8
+ active: string;
9
+ disabled: string;
10
+ filled: {
11
+ action: {
12
+ hovered: string;
13
+ active: string;
14
+ };
15
+ critical: {
16
+ hovered: string;
17
+ active: string;
18
+ };
19
+ };
20
+ };
21
+ stroke: {
22
+ disabled: {
23
+ default: string;
24
+ inverse: string;
25
+ };
26
+ inverse: string;
27
+ action: {
28
+ default: string;
29
+ active: string;
30
+ inverse: string;
31
+ };
32
+ critical: {
33
+ default: string;
34
+ active: string;
35
+ inverse: string;
36
+ };
37
+ primary: {
38
+ action: {
39
+ hovered: string;
40
+ active: string;
41
+ };
42
+ critical: {
43
+ hovered: string;
44
+ active: string;
45
+ };
46
+ inverse: {
47
+ default: string;
48
+ hovered: string;
49
+ };
50
+ };
51
+ secondary: {
52
+ default: string;
53
+ };
54
+ tertiary: {
55
+ default: string;
56
+ };
57
+ filled: {
58
+ action: {
59
+ hovered: string;
60
+ active: string;
61
+ };
62
+ critical: {
63
+ hovered: string;
64
+ active: string;
65
+ };
66
+ };
67
+ };
68
+ };
69
+ border: {
70
+ width: {
71
+ default: number;
72
+ active: number;
73
+ hovered: number;
74
+ hoveredInverse: number;
75
+ };
76
+ radius: {
77
+ default: number;
78
+ };
79
+ };
80
+ };
81
+ export default theme;