@khanacademy/wonder-blocks-icon-button 9.0.7 → 10.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.
@@ -0,0 +1,5 @@
1
+
2
+ > @khanacademy/wonder-blocks-icon-button@10.1.0 build:css /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-icon-button
3
+ > pnpm exec wonder-blocks-tokens .
4
+
5
+ CSS variables generated successfully in: /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-icon-button/dist/css
package/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @khanacademy/wonder-blocks-icon-button
2
2
 
3
+ ## 10.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1338494: Adds the `thunderblocks` theme to the IconButton component.
8
+
9
+ ### Patch Changes
10
+
11
+ - 2779e43: Refactor `IconButton` internally to create an `IconButtonUnstyled` component that can be reused for more button components. Fixed visual styles with keyboard navigation."
12
+ - Updated dependencies [1338494]
13
+ - @khanacademy/wonder-blocks-tokens@10.2.1
14
+ - @khanacademy/wonder-blocks-clickable@7.1.3
15
+ - @khanacademy/wonder-blocks-styles@0.2.10
16
+
17
+ ## 10.0.0
18
+
19
+ ### Major Changes
20
+
21
+ - 668093b: Theming: Switch from React Context to using CSS variables for theming. Modifies build and dev scripts to include generating CSS as part of the dev/build processes.
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies [c7d95bf]
26
+ - Updated dependencies [668093b]
27
+ - @khanacademy/wonder-blocks-theming@3.4.0
28
+ - @khanacademy/wonder-blocks-tokens@10.2.0
29
+ - @khanacademy/wonder-blocks-clickable@7.1.2
30
+ - @khanacademy/wonder-blocks-core@12.3.0
31
+ - @khanacademy/wonder-blocks-icon@5.1.4
32
+ - @khanacademy/wonder-blocks-styles@0.2.9
33
+
3
34
  ## 9.0.7
4
35
 
5
36
  ### Patch Changes
@@ -1,7 +1,11 @@
1
1
  import * as React from "react";
2
2
  import { Link } from "react-router-dom-v5-compat";
3
- import type { SharedProps } from "./icon-button";
4
- type Props = SharedProps & {
3
+ import type { IconButtonProps } from "../util/icon-button.types";
4
+ type Props = Omit<IconButtonProps, "icon"> & {
5
+ /**
6
+ * The button content.
7
+ */
8
+ children: React.ReactNode;
5
9
  /**
6
10
  * URL to navigate to.
7
11
  *
@@ -19,6 +23,11 @@ type Props = SharedProps & {
19
23
  * actions when the user presses the spacebar or enter key.
20
24
  */
21
25
  onKeyUp?: (e: React.KeyboardEvent) => unknown;
26
+ /**
27
+ * When the button is in a pressing state. This is useful for keyboard
28
+ * interactions, so we can provide visual feedback to the user.
29
+ */
30
+ onPress?: (isPressing: boolean) => unknown;
22
31
  };
23
- declare const IconButtonCore: React.ForwardRefExoticComponent<Props & React.RefAttributes<typeof Link | HTMLButtonElement | HTMLAnchorElement>>;
24
- export default IconButtonCore;
32
+ export declare const IconButtonUnstyled: React.ForwardRefExoticComponent<Props & React.RefAttributes<typeof Link | HTMLButtonElement | HTMLAnchorElement>>;
33
+ export {};
@@ -1,119 +1,6 @@
1
1
  import * as React from "react";
2
- import type { PhosphorIconAsset } from "@khanacademy/wonder-blocks-icon";
3
- import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
4
2
  import { Link } from "react-router-dom-v5-compat";
5
- export type IconButtonSize = "xsmall" | "small" | "medium" | "large";
6
- export type IconButtonActionType = "progressive" | "destructive" | "neutral";
7
- export type SharedProps = Partial<Omit<AriaProps, "aria-disabled">> & {
8
- /**
9
- * A unique identifier for the IconButton.
10
- */
11
- id?: string;
12
- /**
13
- * A Phosphor icon asset (imported as a static SVG file).
14
- */
15
- icon: PhosphorIconAsset;
16
- /**
17
- * The action type/category of the icon button.
18
- *
19
- * - `progressive` is used for actions that move the user forward in a flow.
20
- * - `destructive` is used for actions that have a negative impact on the
21
- * user.
22
- * - `neutral` is used for actions that are neither positive nor negative.
23
- *
24
- * Defaults to `progressive`.
25
- */
26
- actionType?: IconButtonActionType;
27
- /**
28
- * The kind of the icon button, either primary, secondary, or tertiary.
29
- *
30
- * In default state:
31
- * - Primary icon buttons are color: props.color
32
- * - Secondary buttons are offBlack
33
- * - Tertiary buttons are offBlack64
34
- *
35
- * In the hover/focus/press states, all variants have a border.
36
- */
37
- kind?: "primary" | "secondary" | "tertiary";
38
- /**
39
- * Whether the icon button is disabled.
40
- */
41
- disabled?: boolean;
42
- /**
43
- * Test ID used for e2e testing.
44
- */
45
- testId?: string;
46
- /**
47
- * Used for icon buttons within <form>s.
48
- */
49
- type?: "submit";
50
- /**
51
- * Size of the icon button.
52
- * One of `xsmall` (16 icon, 20 target), `small` (24, 32), `medium` (24, 40),
53
- * or `large` (24, 48).
54
- * Defaults to `medium`.
55
- */
56
- size?: IconButtonSize;
57
- /**
58
- * Optional custom styles.
59
- */
60
- style?: StyleType;
61
- /**
62
- * Adds CSS classes to the IconButton.
63
- */
64
- className?: string;
65
- /**
66
- * URL to navigate to.
67
- *
68
- * Note: Either href or onClick must be defined
69
- */
70
- href?: string;
71
- /**
72
- * A target destination window for a link to open in.
73
- */
74
- target?: "_blank";
75
- /**
76
- * Specifies the type of relationship between the current document and the
77
- * linked document. Should only be used when `href` is specified. This
78
- * defaults to "noopener noreferrer" when `target="_blank"`, but can be
79
- * overridden by setting this prop to something else.
80
- */
81
- rel?: string;
82
- /**
83
- * Set the tabindex attribute on the rendered element.
84
- */
85
- tabIndex?: number;
86
- /**
87
- * Whether to avoid using client-side navigation.
88
- *
89
- * If the URL passed to href is local to the client-side, e.g.
90
- * /math/algebra/eval-exprs, then it tries to use react-router-dom's Link
91
- * component which handles the client-side navigation. You can set
92
- * `skipClientNav` to true avoid using client-side nav entirely.
93
- *
94
- * NOTE: All URLs containing a protocol are considered external, e.g.
95
- * https://khanacademy.org/math/algebra/eval-exprs will trigger a full
96
- * page reload.
97
- */
98
- skipClientNav?: boolean;
99
- /**
100
- * Function to call when button is clicked.
101
- *
102
- * This callback should be used for things like marking BigBingo
103
- * conversions. It should NOT be used to redirect to a different URL or to
104
- * prevent navigation via e.preventDefault(). The event passed to this
105
- * handler will have its preventDefault() and stopPropagation() methods
106
- * stubbed out.
107
- *
108
- * Note: onClick is optional if href is present, but must be defined if
109
- * href is not
110
- */
111
- onClick?: (e: React.SyntheticEvent) => unknown;
112
- /**
113
- * Function to call when the mouse down event is triggered.
114
- */
115
- onMouseDown?: (e: React.MouseEvent) => void;
116
- };
3
+ import type { IconButtonProps } from "../util/icon-button.types";
117
4
  /**
118
5
  * An `IconButton` is a button whose contents are an SVG image.
119
6
  *
@@ -153,4 +40,4 @@ export type SharedProps = Partial<Omit<AriaProps, "aria-disabled">> & {
153
40
  * />
154
41
  * ```
155
42
  */
156
- export declare const IconButton: React.ForwardRefExoticComponent<SharedProps & React.RefAttributes<typeof Link | HTMLButtonElement | HTMLAnchorElement>>;
43
+ export declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<typeof Link | HTMLButtonElement | HTMLAnchorElement>>;
@@ -0,0 +1,47 @@
1
+ :root {--wb-c-icon-button-iconButton-root-border-offset-primary: var(--wb-border-width-medium);
2
+ --wb-c-icon-button-iconButton-root-border-offset-secondary: calc(-1 * var(--wb-border-width-medium));
3
+ --wb-c-icon-button-iconButton-root-border-offset-tertiary: calc(-1 * var(--wb-border-width-medium));
4
+ --wb-c-icon-button-iconButton-root-border-width-primary-default: var(--wb-border-width-none);
5
+ --wb-c-icon-button-iconButton-root-border-width-primary-hover: var(--wb-border-width-medium);
6
+ --wb-c-icon-button-iconButton-root-border-width-primary-press: var(--wb-border-width-medium);
7
+ --wb-c-icon-button-iconButton-root-border-width-secondary-default: var(--wb-border-width-thin);
8
+ --wb-c-icon-button-iconButton-root-border-width-secondary-hover: var(--wb-border-width-medium);
9
+ --wb-c-icon-button-iconButton-root-border-width-secondary-press: var(--wb-border-width-medium);
10
+ --wb-c-icon-button-iconButton-root-border-width-tertiary-default: var(--wb-border-width-none);
11
+ --wb-c-icon-button-iconButton-root-border-width-tertiary-hover: var(--wb-border-width-medium);
12
+ --wb-c-icon-button-iconButton-root-border-width-tertiary-press: var(--wb-border-width-medium);
13
+ --wb-c-icon-button-iconButton-root-border-radius-default: var(--wb-border-radius-radius_040);
14
+ --wb-c-icon-button-iconButton-root-border-radius-hover: var(--wb-border-radius-radius_040);
15
+ --wb-c-icon-button-iconButton-root-border-radius-press: var(--wb-border-radius-radius_040);
16
+ --wb-c-icon-button-iconButton-root-sizing-xsmall: var(--wb-sizing-size_240);
17
+ --wb-c-icon-button-iconButton-root-sizing-small: var(--wb-sizing-size_320);
18
+ --wb-c-icon-button-iconButton-root-sizing-medium: var(--wb-sizing-size_400);
19
+ --wb-c-icon-button-iconButton-root-sizing-large: var(--wb-sizing-size_480);
20
+ --wb-c-icon-button-iconButton-icon-sizing-xsmall: var(--wb-sizing-size_160);
21
+ --wb-c-icon-button-iconButton-icon-sizing-small: var(--wb-sizing-size_240);
22
+ --wb-c-icon-button-iconButton-icon-sizing-medium: var(--wb-sizing-size_240);
23
+ --wb-c-icon-button-iconButton-icon-sizing-large: var(--wb-sizing-size_240);}
24
+
25
+ [data-wb-theme='thunderblocks'] {--wb-c-icon-button-iconButton-root-border-offset-primary: var(--wb-border-width-medium);
26
+ --wb-c-icon-button-iconButton-root-border-offset-secondary: calc(-1 * var(--wb-border-width-medium));
27
+ --wb-c-icon-button-iconButton-root-border-offset-tertiary: calc(-1 * var(--wb-border-width-medium));
28
+ --wb-c-icon-button-iconButton-root-border-width-primary-default: var(--wb-border-width-none);
29
+ --wb-c-icon-button-iconButton-root-border-width-primary-hover: var(--wb-border-width-none);
30
+ --wb-c-icon-button-iconButton-root-border-width-primary-press: var(--wb-border-width-none);
31
+ --wb-c-icon-button-iconButton-root-border-width-secondary-default: var(--wb-border-width-thin);
32
+ --wb-c-icon-button-iconButton-root-border-width-secondary-hover: var(--wb-border-width-medium);
33
+ --wb-c-icon-button-iconButton-root-border-width-secondary-press: var(--wb-border-width-medium);
34
+ --wb-c-icon-button-iconButton-root-border-width-tertiary-default: var(--wb-border-width-none);
35
+ --wb-c-icon-button-iconButton-root-border-width-tertiary-hover: var(--wb-border-width-medium);
36
+ --wb-c-icon-button-iconButton-root-border-width-tertiary-press: var(--wb-border-width-medium);
37
+ --wb-c-icon-button-iconButton-root-border-radius-default: var(--wb-border-radius-radius_080);
38
+ --wb-c-icon-button-iconButton-root-border-radius-hover: var(--wb-border-radius-radius_080);
39
+ --wb-c-icon-button-iconButton-root-border-radius-press: var(--wb-border-radius-radius_120);
40
+ --wb-c-icon-button-iconButton-root-sizing-xsmall: var(--wb-sizing-size_240);
41
+ --wb-c-icon-button-iconButton-root-sizing-small: var(--wb-sizing-size_260);
42
+ --wb-c-icon-button-iconButton-root-sizing-medium: var(--wb-sizing-size_400);
43
+ --wb-c-icon-button-iconButton-root-sizing-large: var(--wb-sizing-size_440);
44
+ --wb-c-icon-button-iconButton-icon-sizing-xsmall: var(--wb-sizing-size_120);
45
+ --wb-c-icon-button-iconButton-icon-sizing-small: var(--wb-sizing-size_120);
46
+ --wb-c-icon-button-iconButton-icon-sizing-medium: var(--wb-sizing-size_180);
47
+ --wb-c-icon-button-iconButton-icon-sizing-large: var(--wb-sizing-size_200);}
package/dist/es/index.js CHANGED
@@ -1,22 +1,19 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
- import { addStyle, keys } from '@khanacademy/wonder-blocks-core';
4
3
  import { StyleSheet } from 'aphrodite';
5
- import { Link, useInRouterContext } from 'react-router-dom-v5-compat';
6
- import { isClientSideUrl } from '@khanacademy/wonder-blocks-clickable';
7
4
  import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
8
- import { createThemeContext, ThemeSwitcherContext, useScopedTheme } from '@khanacademy/wonder-blocks-theming';
9
5
  import { focusStyles } from '@khanacademy/wonder-blocks-styles';
10
- import { semanticColor, border } from '@khanacademy/wonder-blocks-tokens';
11
-
12
- const iconSizeForButtonSize=size=>{switch(size){case"xsmall":return "small";case"small":return "medium";case"medium":return "medium";case"large":return "medium"}};const targetPixelsForSize=size=>({xsmall:24,small:32,medium:40,large:48})[size];
6
+ import { border, sizing, mapValuesToCssVars, semanticColor } from '@khanacademy/wonder-blocks-tokens';
7
+ import { Link, useInRouterContext } from 'react-router-dom-v5-compat';
8
+ import { addStyle, keys } from '@khanacademy/wonder-blocks-core';
9
+ import { isClientSideUrl } from '@khanacademy/wonder-blocks-clickable';
13
10
 
14
- const theme={color:semanticColor.action,border:{offset:{primary:border.width.medium,secondary:`-${border.width.medium}`,tertiary:-border.width.medium},width:{primary:{default:border.width.none,hover:border.width.medium,press:border.width.medium},secondary:{default:border.width.thin,hover:border.width.medium,press:border.width.medium},tertiary:{default:border.width.none,hover:border.width.medium,press:border.width.medium}},radius:{default:border.radius.radius_040}}};
11
+ var themeDefault = {iconButton:{root:{border:{offset:{primary:border.width.medium,secondary:`calc(-1 * ${border.width.medium})`,tertiary:`calc(-1 * ${border.width.medium})`},width:{primary:{default:border.width.none,hover:border.width.medium,press:border.width.medium},secondary:{default:border.width.thin,hover:border.width.medium,press:border.width.medium},tertiary:{default:border.width.none,hover:border.width.medium,press:border.width.medium}},radius:{default:border.radius.radius_040,hover:border.radius.radius_040,press:border.radius.radius_040}},sizing:{xsmall:sizing.size_240,small:sizing.size_320,medium:sizing.size_400,large:sizing.size_480}},icon:{sizing:{xsmall:sizing.size_160,small:sizing.size_240,medium:sizing.size_240,large:sizing.size_240}}}};
15
12
 
16
- const themes={default:theme};const IconButtonThemeContext=createThemeContext(theme);function ThemedIconButton(props){const currentTheme=React.useContext(ThemeSwitcherContext);const theme$1=themes[currentTheme]??theme;return jsx(IconButtonThemeContext.Provider,{value:theme$1,children:props.children})}
13
+ var iconButtonTheme = mapValuesToCssVars(themeDefault,"--wb-c-icon-button-");
17
14
 
18
- function IconChooser({icon,size}){const iconSize=iconSizeForButtonSize(size);switch(iconSize){case"small":return jsx(PhosphorIcon,{size:"small",color:"currentColor",icon:icon});case"medium":default:return jsx(PhosphorIcon,{size:"medium",color:"currentColor",icon:icon})}}const StyledA=addStyle("a");const StyledButton=addStyle("button");const StyledLink=addStyle(Link);const IconButtonCore=React.forwardRef(function IconButtonCore(props,ref){const{actionType,disabled,href,icon,kind="primary",size="medium",skipClientNav,style,testId,type="button",...restProps}=props;const{theme,themeName}=useScopedTheme(IconButtonThemeContext);const inRouterContext=useInRouterContext();const buttonStyles=_generateStyles(actionType,!!disabled,kind,size,theme,themeName);const defaultStyle=[sharedStyles.shared,buttonStyles.default,disabled&&buttonStyles.disabled];const child=jsx(IconChooser,{size:size,icon:icon});const commonProps={"data-testid":testId,style:[defaultStyle,style],...restProps};if(href&&!disabled){return inRouterContext&&!skipClientNav&&isClientSideUrl(href)?jsx(StyledLink,{...commonProps,to:href,ref:ref,children:child}):jsx(StyledA,{...commonProps,href:href,ref:ref,children:child})}else {return jsx(StyledButton,{type:type,...commonProps,onClick:disabled?undefined:restProps.onClick,"aria-disabled":disabled,ref:ref,children:child})}});const sharedStyles=StyleSheet.create({shared:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",boxSizing:"border-box",padding:0,cursor:"pointer",border:"none",outline:"none",textDecoration:"none",background:"none",margin:0,touchAction:"manipulation"}});const styles={};const _generateStyles=(actionType="progressive",disabled,kind,size,theme,themeName)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}-${themeName}`;if(styles[buttonType]){return styles[buttonType]}const pixelsForSize=targetPixelsForSize(size);const borderWidthKind=theme.border.width[kind];const outlineOffsetKind=theme.border.offset[kind];const themeVariant=theme.color[kind][actionType];const disabledState=theme.color[kind].disabled;const disabledStatesStyles={borderColor:disabledState.border,borderWidth:borderWidthKind.default,background:disabledState.background,color:disabledState.foreground};const newStyles={default:{height:pixelsForSize,width:pixelsForSize,borderRadius:theme.border.radius.default,borderStyle:"solid",borderWidth:borderWidthKind.default,borderColor:themeVariant.default.border,background:themeVariant.default.background,color:themeVariant.default.foreground,":hover":{background:themeVariant.hover.background,color:themeVariant.hover.foreground,outline:kind==="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined},["@media not (hover: hover)"]:{":hover":{backgroundColor:"transparent"}},":active":{outline:kind==="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:undefined,background:themeVariant.press.background,color:themeVariant.press.foreground},...focusStyles.focus},disabled:{cursor:"not-allowed",...disabledStatesStyles,":hover":{...disabledStatesStyles,outline:"none"},":active":{...disabledStatesStyles,outline:"none"},":focus-visible":disabledStatesStyles}};styles[buttonType]=StyleSheet.create(newStyles);return styles[buttonType]};
15
+ const StyledA=addStyle("a");const StyledButton=addStyle("button");const StyledLink=addStyle(Link);const IconButtonUnstyled=React.forwardRef(function IconButtonUnstyled(props,ref){const{children,disabled,href,onPress,skipClientNav,style,testId,type="button",...restProps}=props;const inRouterContext=useInRouterContext();const handleKeyDown=React.useCallback(e=>{const key=e.key;if(!href&&(key===keys.enter||key===keys.space)){e.preventDefault();onPress?.(true);}},[href,onPress]);const handleKeyUp=React.useCallback(e=>{const key=e.key;if(!href&&(key===keys.enter||key===keys.space)){if(restProps.onClick){restProps.onClick(e);onPress?.(false);}}},[href,onPress,restProps]);const commonProps={"data-testid":testId,style:[styles$1.shared,style],onKeyDown:handleKeyDown,onKeyUp:handleKeyUp,...restProps};if(href&&!disabled){return inRouterContext&&!skipClientNav&&isClientSideUrl(href)?jsx(StyledLink,{...commonProps,to:href,ref:ref,children:children}):jsx(StyledA,{...commonProps,href:href,ref:ref,children:children})}else {return jsx(StyledButton,{type:type,...commonProps,onClick:disabled?undefined:restProps.onClick,"aria-disabled":disabled,ref:ref,children:children})}});const styles$1=StyleSheet.create({shared:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",boxSizing:"border-box",padding:0,cursor:"pointer",border:"none",outline:"none",textDecoration:"none",background:"none",margin:0,touchAction:"manipulation"}});
19
16
 
20
- const IconButton=React.forwardRef(function IconButton(props,ref){const{actionType="progressive",disabled=false,href,kind="primary",size="medium",skipClientNav,tabIndex,target,type,...sharedProps}=props;function handleKeyDown(e){const key=e.key;if(!href&&(key===keys.enter||key===keys.space)){e.preventDefault();}}function handleKeyUp(e){const key=e.key;if(!href&&(key===keys.enter||key===keys.space)){if(sharedProps.onClick){sharedProps.onClick(e);}}}return jsx(ThemedIconButton,{children:jsx(IconButtonCore,{...sharedProps,actionType:actionType,disabled:disabled,href:href,kind:kind,ref:ref,skipClientNav:skipClientNav,size:size,target:target,tabIndex:tabIndex,onKeyDown:handleKeyDown,onKeyUp:handleKeyUp,type:type})})});
17
+ const theme=iconButtonTheme.iconButton;function IconChooser({icon,size}){const iconStyle={width:theme.icon.sizing[size],height:theme.icon.sizing[size]};switch(size){case"small":return jsx(PhosphorIcon,{size:"small",color:"currentColor",icon:icon,style:iconStyle});case"medium":default:return jsx(PhosphorIcon,{size:"medium",color:"currentColor",icon:icon,style:iconStyle})}}const IconButton=React.forwardRef(function IconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",size="medium",style,type="button",...restProps}=props;const[pressed,setPressed]=React.useState(false);const buttonStyles=_generateStyles(actionType,!!disabled,kind,size);const styles=[buttonStyles.default,disabled&&buttonStyles.disabled,pressed&&buttonStyles.pressed,style];const handlePress=React.useCallback(isPressing=>{setPressed(isPressing);},[]);return jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,children:jsx(IconChooser,{size:size,icon:icon})})});const styles={};const _generateStyles=(actionType="progressive",disabled,kind,size)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}`;if(styles[buttonType]){return styles[buttonType]}const borderWidthKind=theme.root.border.width[kind];const outlineOffsetKind=theme.root.border.offset[kind];const themeVariant=semanticColor.action[kind][actionType];const disabledState=semanticColor.action[kind].disabled;const disabledStatesStyles={borderColor:disabledState.border,borderWidth:borderWidthKind.default,background:disabledState.background,color:disabledState.foreground};const pressStyles={outline:kind==="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",background:themeVariant.press.background,borderRadius:theme.root.border.radius.press,color:themeVariant.press.foreground,transition:"border-radius 0.1s ease-in-out"};const newStyles={default:{height:theme.root.sizing[size],width:theme.root.sizing[size],borderRadius:theme.root.border.radius.default,borderStyle:"solid",borderWidth:borderWidthKind.default,borderColor:themeVariant.default.border,background:themeVariant.default.background,color:themeVariant.default.foreground,":hover":{background:themeVariant.hover.background,borderRadius:theme.root.border.radius.hover,color:themeVariant.hover.foreground,outline:kind==="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined},["@media not (hover: hover)"]:{":hover":{backgroundColor:"transparent"}},":active":pressStyles,...focusStyles.focus},disabled:{cursor:"not-allowed",...disabledStatesStyles,":hover":{...disabledStatesStyles,outline:"none",borderRadius:theme.root.border.radius.default},":active":{...disabledStatesStyles,outline:"none",borderRadius:theme.root.border.radius.default},":focus-visible":disabledStatesStyles},pressed:pressStyles};styles[buttonType]=StyleSheet.create(newStyles);return styles[buttonType]};
21
18
 
22
19
  export { IconButton as default };
package/dist/index.js CHANGED
@@ -2,14 +2,13 @@
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
- var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
6
5
  var aphrodite = require('aphrodite');
7
- var reactRouterDomV5Compat = require('react-router-dom-v5-compat');
8
- var wonderBlocksClickable = require('@khanacademy/wonder-blocks-clickable');
9
6
  var wonderBlocksIcon = require('@khanacademy/wonder-blocks-icon');
10
- var wonderBlocksTheming = require('@khanacademy/wonder-blocks-theming');
11
7
  var wonderBlocksStyles = require('@khanacademy/wonder-blocks-styles');
12
8
  var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
9
+ var reactRouterDomV5Compat = require('react-router-dom-v5-compat');
10
+ var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
11
+ var wonderBlocksClickable = require('@khanacademy/wonder-blocks-clickable');
13
12
 
14
13
  function _interopNamespace(e) {
15
14
  if (e && e.__esModule) return e;
@@ -31,14 +30,12 @@ function _interopNamespace(e) {
31
30
 
32
31
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
33
32
 
34
- const iconSizeForButtonSize=size=>{switch(size){case"xsmall":return "small";case"small":return "medium";case"medium":return "medium";case"large":return "medium"}};const targetPixelsForSize=size=>({xsmall:24,small:32,medium:40,large:48})[size];
35
-
36
- const theme={color:wonderBlocksTokens.semanticColor.action,border:{offset:{primary:wonderBlocksTokens.border.width.medium,secondary:`-${wonderBlocksTokens.border.width.medium}`,tertiary:-wonderBlocksTokens.border.width.medium},width:{primary:{default:wonderBlocksTokens.border.width.none,hover:wonderBlocksTokens.border.width.medium,press:wonderBlocksTokens.border.width.medium},secondary:{default:wonderBlocksTokens.border.width.thin,hover:wonderBlocksTokens.border.width.medium,press:wonderBlocksTokens.border.width.medium},tertiary:{default:wonderBlocksTokens.border.width.none,hover:wonderBlocksTokens.border.width.medium,press:wonderBlocksTokens.border.width.medium}},radius:{default:wonderBlocksTokens.border.radius.radius_040}}};
33
+ var themeDefault = {iconButton:{root:{border:{offset:{primary:wonderBlocksTokens.border.width.medium,secondary:`calc(-1 * ${wonderBlocksTokens.border.width.medium})`,tertiary:`calc(-1 * ${wonderBlocksTokens.border.width.medium})`},width:{primary:{default:wonderBlocksTokens.border.width.none,hover:wonderBlocksTokens.border.width.medium,press:wonderBlocksTokens.border.width.medium},secondary:{default:wonderBlocksTokens.border.width.thin,hover:wonderBlocksTokens.border.width.medium,press:wonderBlocksTokens.border.width.medium},tertiary:{default:wonderBlocksTokens.border.width.none,hover:wonderBlocksTokens.border.width.medium,press:wonderBlocksTokens.border.width.medium}},radius:{default:wonderBlocksTokens.border.radius.radius_040,hover:wonderBlocksTokens.border.radius.radius_040,press:wonderBlocksTokens.border.radius.radius_040}},sizing:{xsmall:wonderBlocksTokens.sizing.size_240,small:wonderBlocksTokens.sizing.size_320,medium:wonderBlocksTokens.sizing.size_400,large:wonderBlocksTokens.sizing.size_480}},icon:{sizing:{xsmall:wonderBlocksTokens.sizing.size_160,small:wonderBlocksTokens.sizing.size_240,medium:wonderBlocksTokens.sizing.size_240,large:wonderBlocksTokens.sizing.size_240}}}};
37
34
 
38
- const themes={default:theme};const IconButtonThemeContext=wonderBlocksTheming.createThemeContext(theme);function ThemedIconButton(props){const currentTheme=React__namespace.useContext(wonderBlocksTheming.ThemeSwitcherContext);const theme$1=themes[currentTheme]??theme;return jsxRuntime.jsx(IconButtonThemeContext.Provider,{value:theme$1,children:props.children})}
35
+ var iconButtonTheme = wonderBlocksTokens.mapValuesToCssVars(themeDefault,"--wb-c-icon-button-");
39
36
 
40
- function IconChooser({icon,size}){const iconSize=iconSizeForButtonSize(size);switch(iconSize){case"small":return jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{size:"small",color:"currentColor",icon:icon});case"medium":default:return jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{size:"medium",color:"currentColor",icon:icon})}}const StyledA=wonderBlocksCore.addStyle("a");const StyledButton=wonderBlocksCore.addStyle("button");const StyledLink=wonderBlocksCore.addStyle(reactRouterDomV5Compat.Link);const IconButtonCore=React__namespace.forwardRef(function IconButtonCore(props,ref){const{actionType,disabled,href,icon,kind="primary",size="medium",skipClientNav,style,testId,type="button",...restProps}=props;const{theme,themeName}=wonderBlocksTheming.useScopedTheme(IconButtonThemeContext);const inRouterContext=reactRouterDomV5Compat.useInRouterContext();const buttonStyles=_generateStyles(actionType,!!disabled,kind,size,theme,themeName);const defaultStyle=[sharedStyles.shared,buttonStyles.default,disabled&&buttonStyles.disabled];const child=jsxRuntime.jsx(IconChooser,{size:size,icon:icon});const commonProps={"data-testid":testId,style:[defaultStyle,style],...restProps};if(href&&!disabled){return inRouterContext&&!skipClientNav&&wonderBlocksClickable.isClientSideUrl(href)?jsxRuntime.jsx(StyledLink,{...commonProps,to:href,ref:ref,children:child}):jsxRuntime.jsx(StyledA,{...commonProps,href:href,ref:ref,children:child})}else {return jsxRuntime.jsx(StyledButton,{type:type,...commonProps,onClick:disabled?undefined:restProps.onClick,"aria-disabled":disabled,ref:ref,children:child})}});const sharedStyles=aphrodite.StyleSheet.create({shared:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",boxSizing:"border-box",padding:0,cursor:"pointer",border:"none",outline:"none",textDecoration:"none",background:"none",margin:0,touchAction:"manipulation"}});const styles={};const _generateStyles=(actionType="progressive",disabled,kind,size,theme,themeName)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}-${themeName}`;if(styles[buttonType]){return styles[buttonType]}const pixelsForSize=targetPixelsForSize(size);const borderWidthKind=theme.border.width[kind];const outlineOffsetKind=theme.border.offset[kind];const themeVariant=theme.color[kind][actionType];const disabledState=theme.color[kind].disabled;const disabledStatesStyles={borderColor:disabledState.border,borderWidth:borderWidthKind.default,background:disabledState.background,color:disabledState.foreground};const newStyles={default:{height:pixelsForSize,width:pixelsForSize,borderRadius:theme.border.radius.default,borderStyle:"solid",borderWidth:borderWidthKind.default,borderColor:themeVariant.default.border,background:themeVariant.default.background,color:themeVariant.default.foreground,":hover":{background:themeVariant.hover.background,color:themeVariant.hover.foreground,outline:kind==="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined},["@media not (hover: hover)"]:{":hover":{backgroundColor:"transparent"}},":active":{outline:kind==="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:undefined,background:themeVariant.press.background,color:themeVariant.press.foreground},...wonderBlocksStyles.focusStyles.focus},disabled:{cursor:"not-allowed",...disabledStatesStyles,":hover":{...disabledStatesStyles,outline:"none"},":active":{...disabledStatesStyles,outline:"none"},":focus-visible":disabledStatesStyles}};styles[buttonType]=aphrodite.StyleSheet.create(newStyles);return styles[buttonType]};
37
+ const StyledA=wonderBlocksCore.addStyle("a");const StyledButton=wonderBlocksCore.addStyle("button");const StyledLink=wonderBlocksCore.addStyle(reactRouterDomV5Compat.Link);const IconButtonUnstyled=React__namespace.forwardRef(function IconButtonUnstyled(props,ref){const{children,disabled,href,onPress,skipClientNav,style,testId,type="button",...restProps}=props;const inRouterContext=reactRouterDomV5Compat.useInRouterContext();const handleKeyDown=React__namespace.useCallback(e=>{const key=e.key;if(!href&&(key===wonderBlocksCore.keys.enter||key===wonderBlocksCore.keys.space)){e.preventDefault();onPress?.(true);}},[href,onPress]);const handleKeyUp=React__namespace.useCallback(e=>{const key=e.key;if(!href&&(key===wonderBlocksCore.keys.enter||key===wonderBlocksCore.keys.space)){if(restProps.onClick){restProps.onClick(e);onPress?.(false);}}},[href,onPress,restProps]);const commonProps={"data-testid":testId,style:[styles$1.shared,style],onKeyDown:handleKeyDown,onKeyUp:handleKeyUp,...restProps};if(href&&!disabled){return inRouterContext&&!skipClientNav&&wonderBlocksClickable.isClientSideUrl(href)?jsxRuntime.jsx(StyledLink,{...commonProps,to:href,ref:ref,children:children}):jsxRuntime.jsx(StyledA,{...commonProps,href:href,ref:ref,children:children})}else {return jsxRuntime.jsx(StyledButton,{type:type,...commonProps,onClick:disabled?undefined:restProps.onClick,"aria-disabled":disabled,ref:ref,children:children})}});const styles$1=aphrodite.StyleSheet.create({shared:{position:"relative",display:"inline-flex",alignItems:"center",justifyContent:"center",boxSizing:"border-box",padding:0,cursor:"pointer",border:"none",outline:"none",textDecoration:"none",background:"none",margin:0,touchAction:"manipulation"}});
41
38
 
42
- const IconButton=React__namespace.forwardRef(function IconButton(props,ref){const{actionType="progressive",disabled=false,href,kind="primary",size="medium",skipClientNav,tabIndex,target,type,...sharedProps}=props;function handleKeyDown(e){const key=e.key;if(!href&&(key===wonderBlocksCore.keys.enter||key===wonderBlocksCore.keys.space)){e.preventDefault();}}function handleKeyUp(e){const key=e.key;if(!href&&(key===wonderBlocksCore.keys.enter||key===wonderBlocksCore.keys.space)){if(sharedProps.onClick){sharedProps.onClick(e);}}}return jsxRuntime.jsx(ThemedIconButton,{children:jsxRuntime.jsx(IconButtonCore,{...sharedProps,actionType:actionType,disabled:disabled,href:href,kind:kind,ref:ref,skipClientNav:skipClientNav,size:size,target:target,tabIndex:tabIndex,onKeyDown:handleKeyDown,onKeyUp:handleKeyUp,type:type})})});
39
+ const theme=iconButtonTheme.iconButton;function IconChooser({icon,size}){const iconStyle={width:theme.icon.sizing[size],height:theme.icon.sizing[size]};switch(size){case"small":return jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{size:"small",color:"currentColor",icon:icon,style:iconStyle});case"medium":default:return jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{size:"medium",color:"currentColor",icon:icon,style:iconStyle})}}const IconButton=React__namespace.forwardRef(function IconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",size="medium",style,type="button",...restProps}=props;const[pressed,setPressed]=React__namespace.useState(false);const buttonStyles=_generateStyles(actionType,!!disabled,kind,size);const styles=[buttonStyles.default,disabled&&buttonStyles.disabled,pressed&&buttonStyles.pressed,style];const handlePress=React__namespace.useCallback(isPressing=>{setPressed(isPressing);},[]);return jsxRuntime.jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,children:jsxRuntime.jsx(IconChooser,{size:size,icon:icon})})});const styles={};const _generateStyles=(actionType="progressive",disabled,kind,size)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}`;if(styles[buttonType]){return styles[buttonType]}const borderWidthKind=theme.root.border.width[kind];const outlineOffsetKind=theme.root.border.offset[kind];const themeVariant=wonderBlocksTokens.semanticColor.action[kind][actionType];const disabledState=wonderBlocksTokens.semanticColor.action[kind].disabled;const disabledStatesStyles={borderColor:disabledState.border,borderWidth:borderWidthKind.default,background:disabledState.background,color:disabledState.foreground};const pressStyles={outline:kind==="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.press} solid ${themeVariant.press.border}`:"none",background:themeVariant.press.background,borderRadius:theme.root.border.radius.press,color:themeVariant.press.foreground,transition:"border-radius 0.1s ease-in-out"};const newStyles={default:{height:theme.root.sizing[size],width:theme.root.sizing[size],borderRadius:theme.root.border.radius.default,borderStyle:"solid",borderWidth:borderWidthKind.default,borderColor:themeVariant.default.border,background:themeVariant.default.background,color:themeVariant.default.foreground,":hover":{background:themeVariant.hover.background,borderRadius:theme.root.border.radius.hover,color:themeVariant.hover.foreground,outline:kind==="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined,outlineOffset:kind==="primary"?outlineOffsetKind:undefined,border:kind!=="primary"?`${borderWidthKind.hover} solid ${themeVariant.hover.border}`:undefined},["@media not (hover: hover)"]:{":hover":{backgroundColor:"transparent"}},":active":pressStyles,...wonderBlocksStyles.focusStyles.focus},disabled:{cursor:"not-allowed",...disabledStatesStyles,":hover":{...disabledStatesStyles,outline:"none",borderRadius:theme.root.border.radius.default},":active":{...disabledStatesStyles,outline:"none",borderRadius:theme.root.border.radius.default},":focus-visible":disabledStatesStyles},pressed:pressStyles};styles[buttonType]=aphrodite.StyleSheet.create(newStyles);return styles[buttonType]};
43
40
 
44
41
  module.exports = IconButton;
@@ -0,0 +1,50 @@
1
+ declare const _default: {
2
+ iconButton: {
3
+ root: {
4
+ border: {
5
+ offset: {
6
+ primary: string;
7
+ secondary: string;
8
+ tertiary: string;
9
+ };
10
+ width: {
11
+ primary: {
12
+ default: string;
13
+ hover: string;
14
+ press: string;
15
+ };
16
+ secondary: {
17
+ default: string;
18
+ hover: string;
19
+ press: string;
20
+ };
21
+ tertiary: {
22
+ default: string;
23
+ hover: string;
24
+ press: string;
25
+ };
26
+ };
27
+ radius: {
28
+ default: string;
29
+ hover: string;
30
+ press: string;
31
+ };
32
+ };
33
+ sizing: {
34
+ xsmall: string;
35
+ small: string;
36
+ medium: string;
37
+ large: string;
38
+ };
39
+ };
40
+ icon: {
41
+ sizing: {
42
+ xsmall: string;
43
+ small: string;
44
+ medium: string;
45
+ large: string;
46
+ };
47
+ };
48
+ };
49
+ };
50
+ export default _default;
@@ -0,0 +1,50 @@
1
+ declare const _default: {
2
+ iconButton: {
3
+ root: {
4
+ border: {
5
+ offset: {
6
+ primary: string;
7
+ secondary: string;
8
+ tertiary: string;
9
+ };
10
+ width: {
11
+ primary: {
12
+ default: string;
13
+ hover: string;
14
+ press: string;
15
+ };
16
+ secondary: {
17
+ default: string;
18
+ hover: string;
19
+ press: string;
20
+ };
21
+ tertiary: {
22
+ default: string;
23
+ hover: string;
24
+ press: string;
25
+ };
26
+ };
27
+ radius: {
28
+ default: string;
29
+ hover: string;
30
+ press: string;
31
+ };
32
+ };
33
+ sizing: {
34
+ xsmall: string;
35
+ small: string;
36
+ medium: string;
37
+ large: string;
38
+ };
39
+ };
40
+ icon: {
41
+ sizing: {
42
+ xsmall: string;
43
+ small: string;
44
+ medium: string;
45
+ large: string;
46
+ };
47
+ };
48
+ };
49
+ };
50
+ export default _default;
@@ -0,0 +1,50 @@
1
+ declare const _default: {
2
+ iconButton: {
3
+ root: {
4
+ border: {
5
+ offset: {
6
+ primary: string;
7
+ secondary: string;
8
+ tertiary: string;
9
+ };
10
+ width: {
11
+ primary: {
12
+ default: string;
13
+ hover: string;
14
+ press: string;
15
+ };
16
+ secondary: {
17
+ default: string;
18
+ hover: string;
19
+ press: string;
20
+ };
21
+ tertiary: {
22
+ default: string;
23
+ hover: string;
24
+ press: string;
25
+ };
26
+ };
27
+ radius: {
28
+ default: string;
29
+ hover: string;
30
+ press: string;
31
+ };
32
+ };
33
+ sizing: {
34
+ xsmall: string;
35
+ small: string;
36
+ medium: string;
37
+ large: string;
38
+ };
39
+ };
40
+ icon: {
41
+ sizing: {
42
+ xsmall: string;
43
+ small: string;
44
+ medium: string;
45
+ large: string;
46
+ };
47
+ };
48
+ };
49
+ };
50
+ export default _default;
@@ -0,0 +1,116 @@
1
+ import * as React from "react";
2
+ import { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
3
+ import { PhosphorIconAsset } from "@khanacademy/wonder-blocks-icon";
4
+ export type IconButtonKind = "primary" | "secondary" | "tertiary";
5
+ export type IconButtonSize = "xsmall" | "small" | "medium" | "large";
6
+ export type IconButtonActionType = "progressive" | "destructive" | "neutral";
7
+ export type IconButtonProps = Partial<Omit<AriaProps, "aria-disabled">> & {
8
+ /**
9
+ * A unique identifier for the IconButton.
10
+ */
11
+ id?: string;
12
+ /**
13
+ * A Phosphor icon asset (imported as a static SVG file).
14
+ */
15
+ icon: PhosphorIconAsset;
16
+ /**
17
+ * The action type/category of the icon button.
18
+ *
19
+ * - `progressive` is used for actions that move the user forward in a flow.
20
+ * - `destructive` is used for actions that have a negative impact on the
21
+ * user.
22
+ * - `neutral` is used for actions that are neither positive nor negative.
23
+ *
24
+ * Defaults to `progressive`.
25
+ */
26
+ actionType?: IconButtonActionType;
27
+ /**
28
+ * The kind of the icon button, either primary, secondary, or tertiary.
29
+ *
30
+ * In default state:
31
+ * - Primary icon buttons are color: props.color
32
+ * - Secondary buttons are offBlack
33
+ * - Tertiary buttons are offBlack64
34
+ *
35
+ * In the hover/focus/press states, all variants have a border.
36
+ */
37
+ kind?: IconButtonKind;
38
+ /**
39
+ * Whether the icon button is disabled.
40
+ */
41
+ disabled?: boolean;
42
+ /**
43
+ * Test ID used for e2e testing.
44
+ */
45
+ testId?: string;
46
+ /**
47
+ * Used for icon buttons within <form>s.
48
+ */
49
+ type?: "submit" | "button";
50
+ /**
51
+ * Size of the icon button.
52
+ * One of `xsmall` (16 icon, 20 target), `small` (24, 32), `medium` (24, 40),
53
+ * or `large` (24, 48).
54
+ * Defaults to `medium`.
55
+ */
56
+ size?: IconButtonSize;
57
+ /**
58
+ * Optional custom styles.
59
+ */
60
+ style?: StyleType;
61
+ /**
62
+ * Adds CSS classes to the IconButton.
63
+ */
64
+ className?: string;
65
+ /**
66
+ * URL to navigate to.
67
+ *
68
+ * Note: Either href or onClick must be defined
69
+ */
70
+ href?: string;
71
+ /**
72
+ * A target destination window for a link to open in.
73
+ */
74
+ target?: "_blank";
75
+ /**
76
+ * Specifies the type of relationship between the current document and the
77
+ * linked document. Should only be used when `href` is specified. This
78
+ * defaults to "noopener noreferrer" when `target="_blank"`, but can be
79
+ * overridden by setting this prop to something else.
80
+ */
81
+ rel?: string;
82
+ /**
83
+ * Set the tabindex attribute on the rendered element.
84
+ */
85
+ tabIndex?: number;
86
+ /**
87
+ * Whether to avoid using client-side navigation.
88
+ *
89
+ * If the URL passed to href is local to the client-side, e.g.
90
+ * /math/algebra/eval-exprs, then it tries to use react-router-dom's Link
91
+ * component which handles the client-side navigation. You can set
92
+ * `skipClientNav` to true avoid using client-side nav entirely.
93
+ *
94
+ * NOTE: All URLs containing a protocol are considered external, e.g.
95
+ * https://khanacademy.org/math/algebra/eval-exprs will trigger a full
96
+ * page reload.
97
+ */
98
+ skipClientNav?: boolean;
99
+ /**
100
+ * Function to call when button is clicked.
101
+ *
102
+ * This callback should be used for things like marking BigBingo
103
+ * conversions. It should NOT be used to redirect to a different URL or to
104
+ * prevent navigation via e.preventDefault(). The event passed to this
105
+ * handler will have its preventDefault() and stopPropagation() methods
106
+ * stubbed out.
107
+ *
108
+ * Note: onClick is optional if href is present, but must be defined if
109
+ * href is not
110
+ */
111
+ onClick?: (e: React.SyntheticEvent) => unknown;
112
+ /**
113
+ * Function to call when the mouse down event is triggered.
114
+ */
115
+ onMouseDown?: (e: React.MouseEvent) => void;
116
+ };
package/package.json CHANGED
@@ -1,23 +1,31 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-icon-button",
3
- "version": "9.0.7",
3
+ "version": "10.1.0",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "description": "",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/es/index.js",
12
+ "require": "./dist/index.js",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./styles.css": "./dist/css/vars.css"
16
+ },
9
17
  "main": "dist/index.js",
10
18
  "module": "dist/es/index.js",
11
19
  "types": "dist/index.d.ts",
12
20
  "author": "",
13
21
  "license": "MIT",
14
22
  "dependencies": {
15
- "@khanacademy/wonder-blocks-clickable": "7.1.1",
23
+ "@khanacademy/wonder-blocks-clickable": "7.1.3",
16
24
  "@khanacademy/wonder-blocks-core": "12.3.0",
17
25
  "@khanacademy/wonder-blocks-icon": "5.1.4",
18
- "@khanacademy/wonder-blocks-styles": "0.2.8",
19
- "@khanacademy/wonder-blocks-theming": "3.3.0",
20
- "@khanacademy/wonder-blocks-tokens": "10.1.0"
26
+ "@khanacademy/wonder-blocks-styles": "0.2.10",
27
+ "@khanacademy/wonder-blocks-theming": "3.4.0",
28
+ "@khanacademy/wonder-blocks-tokens": "10.2.1"
21
29
  },
22
30
  "peerDependencies": {
23
31
  "aphrodite": "^1.2.5",
@@ -27,9 +35,10 @@
27
35
  "react-router-dom-v5-compat": "^6.30.0"
28
36
  },
29
37
  "devDependencies": {
30
- "@khanacademy/wb-dev-build-settings": "3.0.0"
38
+ "@khanacademy/wb-dev-build-settings": "3.1.0"
31
39
  },
32
40
  "scripts": {
41
+ "build:css": "pnpm exec wonder-blocks-tokens .",
33
42
  "test": "echo \"Error: no test specified\" && exit 1"
34
43
  }
35
44
  }
@@ -1,206 +0,0 @@
1
- declare const theme: {
2
- color: {
3
- primary: {
4
- progressive: {
5
- default: {
6
- border: string;
7
- background: string;
8
- foreground: string;
9
- };
10
- hover: {
11
- border: string;
12
- background: string;
13
- foreground: string;
14
- };
15
- press: {
16
- border: string;
17
- background: string;
18
- foreground: string;
19
- };
20
- };
21
- destructive: {
22
- default: {
23
- border: string;
24
- background: string;
25
- foreground: string;
26
- };
27
- hover: {
28
- border: string;
29
- background: string;
30
- foreground: string;
31
- };
32
- press: {
33
- border: string;
34
- background: string;
35
- foreground: string;
36
- };
37
- };
38
- neutral: {
39
- default: {
40
- border: string;
41
- background: string;
42
- foreground: string;
43
- };
44
- hover: {
45
- border: string;
46
- background: string;
47
- foreground: string;
48
- };
49
- press: {
50
- border: string;
51
- background: string;
52
- foreground: string;
53
- };
54
- };
55
- disabled: {
56
- border: string;
57
- background: string;
58
- foreground: string;
59
- };
60
- };
61
- secondary: {
62
- progressive: {
63
- default: {
64
- border: string;
65
- background: string;
66
- foreground: string;
67
- };
68
- hover: {
69
- border: string;
70
- background: string;
71
- foreground: string;
72
- };
73
- press: {
74
- border: string;
75
- background: string;
76
- foreground: string;
77
- };
78
- };
79
- destructive: {
80
- default: {
81
- border: string;
82
- background: string;
83
- foreground: string;
84
- };
85
- hover: {
86
- border: string;
87
- background: string;
88
- foreground: string;
89
- };
90
- press: {
91
- border: string;
92
- background: string;
93
- foreground: string;
94
- };
95
- };
96
- neutral: {
97
- default: {
98
- border: string;
99
- background: string;
100
- foreground: string;
101
- };
102
- hover: {
103
- border: string;
104
- background: string;
105
- foreground: string;
106
- };
107
- press: {
108
- border: string;
109
- background: string;
110
- foreground: string;
111
- };
112
- };
113
- disabled: {
114
- border: string;
115
- background: string;
116
- foreground: string;
117
- };
118
- };
119
- tertiary: {
120
- progressive: {
121
- default: {
122
- border: string;
123
- background: string;
124
- foreground: string;
125
- };
126
- hover: {
127
- border: string;
128
- background: string;
129
- foreground: string;
130
- };
131
- press: {
132
- border: string;
133
- background: string;
134
- foreground: string;
135
- };
136
- };
137
- destructive: {
138
- default: {
139
- border: string;
140
- background: string;
141
- foreground: string;
142
- };
143
- hover: {
144
- border: string;
145
- background: string;
146
- foreground: string;
147
- };
148
- press: {
149
- border: string;
150
- background: string;
151
- foreground: string;
152
- };
153
- };
154
- neutral: {
155
- default: {
156
- border: string;
157
- background: string;
158
- foreground: string;
159
- };
160
- hover: {
161
- border: string;
162
- background: string;
163
- foreground: string;
164
- };
165
- press: {
166
- border: string;
167
- background: string;
168
- foreground: string;
169
- };
170
- };
171
- disabled: {
172
- border: string;
173
- background: string;
174
- foreground: string;
175
- };
176
- };
177
- };
178
- border: {
179
- offset: {
180
- primary: string;
181
- secondary: string;
182
- tertiary: number;
183
- };
184
- width: {
185
- primary: {
186
- default: string;
187
- hover: string;
188
- press: string;
189
- };
190
- secondary: {
191
- default: string;
192
- hover: string;
193
- press: string;
194
- };
195
- tertiary: {
196
- default: string;
197
- hover: string;
198
- press: string;
199
- };
200
- };
201
- radius: {
202
- default: string;
203
- };
204
- };
205
- };
206
- export default theme;
@@ -1,221 +0,0 @@
1
- import * as React from "react";
2
- import defaultTheme from "./default";
3
- type Props = {
4
- children: React.ReactNode;
5
- };
6
- export type IconButtonThemeContract = typeof defaultTheme;
7
- /**
8
- * The context that provides the theme to the IconButton component.
9
- * This is generally consumed via the `useScopedTheme` hook.
10
- */
11
- export declare const IconButtonThemeContext: React.Context<{
12
- color: {
13
- primary: {
14
- progressive: {
15
- default: {
16
- border: string;
17
- background: string;
18
- foreground: string;
19
- };
20
- hover: {
21
- border: string;
22
- background: string;
23
- foreground: string;
24
- };
25
- press: {
26
- border: string;
27
- background: string;
28
- foreground: string;
29
- };
30
- };
31
- destructive: {
32
- default: {
33
- border: string;
34
- background: string;
35
- foreground: string;
36
- };
37
- hover: {
38
- border: string;
39
- background: string;
40
- foreground: string;
41
- };
42
- press: {
43
- border: string;
44
- background: string;
45
- foreground: string;
46
- };
47
- };
48
- neutral: {
49
- default: {
50
- border: string;
51
- background: string;
52
- foreground: string;
53
- };
54
- hover: {
55
- border: string;
56
- background: string;
57
- foreground: string;
58
- };
59
- press: {
60
- border: string;
61
- background: string;
62
- foreground: string;
63
- };
64
- };
65
- disabled: {
66
- border: string;
67
- background: string;
68
- foreground: string;
69
- };
70
- };
71
- secondary: {
72
- progressive: {
73
- default: {
74
- border: string;
75
- background: string;
76
- foreground: string;
77
- };
78
- hover: {
79
- border: string;
80
- background: string;
81
- foreground: string;
82
- };
83
- press: {
84
- border: string;
85
- background: string;
86
- foreground: string;
87
- };
88
- };
89
- destructive: {
90
- default: {
91
- border: string;
92
- background: string;
93
- foreground: string;
94
- };
95
- hover: {
96
- border: string;
97
- background: string;
98
- foreground: string;
99
- };
100
- press: {
101
- border: string;
102
- background: string;
103
- foreground: string;
104
- };
105
- };
106
- neutral: {
107
- default: {
108
- border: string;
109
- background: string;
110
- foreground: string;
111
- };
112
- hover: {
113
- border: string;
114
- background: string;
115
- foreground: string;
116
- };
117
- press: {
118
- border: string;
119
- background: string;
120
- foreground: string;
121
- };
122
- };
123
- disabled: {
124
- border: string;
125
- background: string;
126
- foreground: string;
127
- };
128
- };
129
- tertiary: {
130
- progressive: {
131
- default: {
132
- border: string;
133
- background: string;
134
- foreground: string;
135
- };
136
- hover: {
137
- border: string;
138
- background: string;
139
- foreground: string;
140
- };
141
- press: {
142
- border: string;
143
- background: string;
144
- foreground: string;
145
- };
146
- };
147
- destructive: {
148
- default: {
149
- border: string;
150
- background: string;
151
- foreground: string;
152
- };
153
- hover: {
154
- border: string;
155
- background: string;
156
- foreground: string;
157
- };
158
- press: {
159
- border: string;
160
- background: string;
161
- foreground: string;
162
- };
163
- };
164
- neutral: {
165
- default: {
166
- border: string;
167
- background: string;
168
- foreground: string;
169
- };
170
- hover: {
171
- border: string;
172
- background: string;
173
- foreground: string;
174
- };
175
- press: {
176
- border: string;
177
- background: string;
178
- foreground: string;
179
- };
180
- };
181
- disabled: {
182
- border: string;
183
- background: string;
184
- foreground: string;
185
- };
186
- };
187
- };
188
- border: {
189
- offset: {
190
- primary: string;
191
- secondary: string;
192
- tertiary: number;
193
- };
194
- width: {
195
- primary: {
196
- default: string;
197
- hover: string;
198
- press: string;
199
- };
200
- secondary: {
201
- default: string;
202
- hover: string;
203
- press: string;
204
- };
205
- tertiary: {
206
- default: string;
207
- hover: string;
208
- press: string;
209
- };
210
- };
211
- radius: {
212
- default: string;
213
- };
214
- };
215
- }>;
216
- /**
217
- * ThemedIconButton is a component that provides a theme to the <IconButton/>
218
- * component.
219
- */
220
- export default function ThemedIconButton(props: Props): React.JSX.Element;
221
- export {};
@@ -1,10 +0,0 @@
1
- import { IconSize } from "@khanacademy/wonder-blocks-icon";
2
- import { IconButtonSize } from "../components/icon-button";
3
- /**
4
- * A function that returns the icon size for a given icon button size.
5
- */
6
- export declare const iconSizeForButtonSize: (size: IconButtonSize) => IconSize;
7
- /**
8
- * A function that returns the size of the touch target in pixels for a given icon button size.
9
- */
10
- export declare const targetPixelsForSize: (size: IconButtonSize) => number;