@khanacademy/wonder-blocks-icon-button 10.1.0 → 10.2.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @khanacademy/wonder-blocks-icon-button@10.1.0 build:css /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-icon-button
2
+ > @khanacademy/wonder-blocks-icon-button@10.2.0 build:css /home/runner/work/wonder-blocks/wonder-blocks/packages/wonder-blocks-icon-button
3
3
  > pnpm exec wonder-blocks-tokens .
4
4
 
5
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,40 @@
1
1
  # @khanacademy/wonder-blocks-icon-button
2
2
 
3
+ ## 10.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b1ee2b4: Adds `chonky` category and `ActivityIconButton` component.
8
+ - 63ad56e: Adds `label` prop to `ActivityIconButton`. Modifies the types to expect one of `aria-label` or `label`.
9
+
10
+ ### Patch Changes
11
+
12
+ - fa3e433: Fixes how the onPress handler is called when released. Updated unit tests and docs for IconButton
13
+ - Updated dependencies [b1ee2b4]
14
+ - Updated dependencies [7abcccf]
15
+ - Updated dependencies [9bacc1a]
16
+ - Updated dependencies [9bacc1a]
17
+ - Updated dependencies [7abcccf]
18
+ - Updated dependencies [1c3c335]
19
+ - Updated dependencies [689f5d3]
20
+ - Updated dependencies [7d2a646]
21
+ - @khanacademy/wonder-blocks-tokens@10.4.0
22
+ - @khanacademy/wonder-blocks-clickable@7.1.5
23
+ - @khanacademy/wonder-blocks-styles@0.2.12
24
+ - @khanacademy/wonder-blocks-typography@4.1.0
25
+
26
+ ## 10.1.1
27
+
28
+ ### Patch Changes
29
+
30
+ - Updated dependencies [dd76e7c]
31
+ - @khanacademy/wonder-blocks-tokens@10.3.0
32
+ - @khanacademy/wonder-blocks-clickable@7.1.4
33
+ - @khanacademy/wonder-blocks-core@12.3.0
34
+ - @khanacademy/wonder-blocks-icon@5.1.4
35
+ - @khanacademy/wonder-blocks-styles@0.2.11
36
+ - @khanacademy/wonder-blocks-theming@3.4.0
37
+
3
38
  ## 10.1.0
4
39
 
5
40
  ### Minor Changes
@@ -0,0 +1,50 @@
1
+ import * as React from "react";
2
+ import { Link } from "react-router-dom-v5-compat";
3
+ import type { ActivityIconButtonActionType, IconButtonProps } from "../util/icon-button.types";
4
+ type AriaLabelOnly = {
5
+ /**
6
+ * The alternative text for the icon button. Use `aria-label` for when
7
+ * there's no visible label for the button, such as when the button only
8
+ * contains an icon.
9
+ */
10
+ "aria-label": string;
11
+ label?: never;
12
+ };
13
+ type LabelOnly = {
14
+ "aria-label"?: never;
15
+ /**
16
+ * A label for the button that describes its action.
17
+ *
18
+ * NOTE: If `label` is set, then `aria-label` will be ignored.
19
+ */
20
+ label: string;
21
+ };
22
+ type Props = Omit<IconButtonProps, "actionType" | "size"> & (AriaLabelOnly | LabelOnly) & {
23
+ /**
24
+ * The action type of the button. This determines the visual style of the
25
+ * button.
26
+ *
27
+ * - `progressive` is used for actions that move the user forward in a flow.
28
+ * - `neutral` is used for buttons that indicate a neutral action.
29
+ */
30
+ actionType?: ActivityIconButtonActionType;
31
+ };
32
+ /**
33
+ * `ActivityIconButton` is an icon button that is used for actions in the
34
+ * context of learner activities. It uses a "chonky" design, which is a more
35
+ * playful and engaging design that is suitable for learner activities
36
+ *
37
+ * ```tsx
38
+ * import magnifyingGlassIcon from
39
+ * "@phosphor-icons/core/regular/magnifying-glass.svg";
40
+ * import {ActivityIconButton} from "@khanacademy/wonder-blocks-icon-button";
41
+ *
42
+ * <ActivityIconButton
43
+ * icon={magnifyingGlassIcon}
44
+ * aria-label="An Icon"
45
+ * onClick={(e) => console.log("Hello, world!")}
46
+ * />
47
+ * ```
48
+ */
49
+ export declare const ActivityIconButton: React.ForwardRefExoticComponent<Props & React.RefAttributes<typeof Link | HTMLButtonElement | HTMLAnchorElement>>;
50
+ export {};
@@ -1,6 +1,5 @@
1
1
  import * as React from "react";
2
- import { Link } from "react-router-dom-v5-compat";
3
- import type { IconButtonProps } from "../util/icon-button.types";
2
+ import type { IconButtonProps, IconButtonRef } from "../util/icon-button.types";
4
3
  type Props = Omit<IconButtonProps, "icon"> & {
5
4
  /**
6
5
  * The button content.
@@ -29,5 +28,5 @@ type Props = Omit<IconButtonProps, "icon"> & {
29
28
  */
30
29
  onPress?: (isPressing: boolean) => unknown;
31
30
  };
32
- export declare const IconButtonUnstyled: React.ForwardRefExoticComponent<Props & React.RefAttributes<typeof Link | HTMLButtonElement | HTMLAnchorElement>>;
31
+ export declare const IconButtonUnstyled: React.ForwardRefExoticComponent<Props & React.RefAttributes<IconButtonRef>>;
33
32
  export {};
@@ -1,6 +1,5 @@
1
1
  import * as React from "react";
2
- import { Link } from "react-router-dom-v5-compat";
3
- import type { IconButtonProps } from "../util/icon-button.types";
2
+ import type { IconButtonProps, IconButtonRef } from "../util/icon-button.types";
4
3
  /**
5
4
  * An `IconButton` is a button whose contents are an SVG image.
6
5
  *
@@ -40,4 +39,4 @@ import type { IconButtonProps } from "../util/icon-button.types";
40
39
  * />
41
40
  * ```
42
41
  */
43
- export declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<typeof Link | HTMLButtonElement | HTMLAnchorElement>>;
42
+ export declare const IconButton: React.ForwardRefExoticComponent<IconButtonProps & React.RefAttributes<IconButtonRef>>;
package/dist/es/index.js CHANGED
@@ -1,19 +1,22 @@
1
- import { jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
3
  import { StyleSheet } from 'aphrodite';
4
4
  import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
5
5
  import { focusStyles } from '@khanacademy/wonder-blocks-styles';
6
6
  import { border, sizing, mapValuesToCssVars, semanticColor } from '@khanacademy/wonder-blocks-tokens';
7
7
  import { Link, useInRouterContext } from 'react-router-dom-v5-compat';
8
- import { addStyle, keys } from '@khanacademy/wonder-blocks-core';
8
+ import { addStyle, keys, View } from '@khanacademy/wonder-blocks-core';
9
9
  import { isClientSideUrl } from '@khanacademy/wonder-blocks-clickable';
10
+ import { BodyText } from '@khanacademy/wonder-blocks-typography';
10
11
 
11
12
  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}}}};
12
13
 
13
14
  var iconButtonTheme = mapValuesToCssVars(themeDefault,"--wb-c-icon-button-");
14
15
 
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"}});
16
+ 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$2.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$2=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"}});
16
17
 
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]};
18
+ const theme$1=iconButtonTheme.iconButton;function IconChooser({icon,size}){const iconStyle={width:theme$1.icon.sizing[size],height:theme$1.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$1(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$1={};const _generateStyles$1=(actionType="progressive",disabled,kind,size)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}`;if(styles$1[buttonType]){return styles$1[buttonType]}const borderWidthKind=theme$1.root.border.width[kind];const outlineOffsetKind=theme$1.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$1.root.border.radius.press,color:themeVariant.press.foreground,transition:"border-radius 0.1s ease-in-out"};const newStyles={default:{height:theme$1.root.sizing[size],width:theme$1.root.sizing[size],borderRadius:theme$1.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$1.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$1.root.border.radius.default},":active":{...disabledStatesStyles,outline:"none",borderRadius:theme$1.root.border.radius.default},":focus-visible":disabledStatesStyles},pressed:pressStyles};styles$1[buttonType]=StyleSheet.create(newStyles);return styles$1[buttonType]};
18
19
 
19
- export { IconButton as default };
20
+ const ActivityIconButton=React.forwardRef(function ActivityIconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",style,type="button","aria-label":ariaLabel,label,...restProps}=props;const[pressed,setPressed]=React.useState(false);const buttonStyles=_generateStyles(actionType,!!disabled,kind);const styles=[buttonStyles.button,disabled&&buttonStyles.disabled,!disabled&&pressed&&buttonStyles.pressed,style];const chonkyStyles=[buttonStyles.chonky,disabled&&buttonStyles.chonkyDisabled,!disabled&&pressed&&buttonStyles.chonkyPressed];const handlePress=React.useCallback(isPressing=>{setPressed(isPressing);},[]);const hasVisibleLabel=label!==undefined&&label!=="";return jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,...!hasVisibleLabel?{"aria-label":ariaLabel}:{},children:jsxs(Fragment,{children:[jsx(View,{style:chonkyStyles,className:"chonky",children:jsx(PhosphorIcon,{size:"medium",color:"currentColor",icon:icon})}),hasVisibleLabel&&jsx(BodyText,{tag:"span",size:"medium",weight:"semi",style:buttonStyles.label,children:label})]})})});const theme={root:{border:{width:{primary:{rest:border.width.thin,hover:border.width.thin,press:border.width.thin},secondary:{rest:border.width.thin,hover:border.width.thin,press:border.width.thin},tertiary:{rest:border.width.thin,hover:border.width.thin,press:border.width.thin}},radius:border.radius.radius_120},layout:{padding:{block:sizing.size_140,inline:sizing.size_200}},shadow:{y:{rest:"6px",hover:"8px",press:sizing.size_0}}},label:{color:{progressive:semanticColor.core.foreground.instructive.default,neutral:semanticColor.core.foreground.neutral.default,disabled:semanticColor.core.foreground.disabled.default},layout:{width:sizing.size_640}}};const styles={};const _generateStyles=(actionType="progressive",disabled,kind)=>{const buttonType=`${actionType}-d_${disabled}-${kind}`;if(styles[buttonType]){return styles[buttonType]}const borderWidthKind=theme.root.border.width[kind];const themeVariant=semanticColor.chonky[actionType];const disabledState=semanticColor.chonky.disabled;const disabledStatesStyles={outline:"none",transform:"none"};const chonkyDisabled={background:disabledState.background[kind],borderWidth:borderWidthKind.rest,borderColor:disabledState.border[kind],color:disabledState.foreground[kind],boxShadow:`0 ${theme.root.shadow.y.rest} 0 0 ${disabledState.shadow[kind]}`,transform:"none"};const chonkyPressed={background:themeVariant.background[kind].press,border:`${borderWidthKind.press} solid ${themeVariant.border[kind].press}`,boxShadow:`0 ${theme.root.shadow.y.press} 0 0 ${themeVariant.shadow[kind].press}`,color:themeVariant.foreground[kind].press,transform:`translateY(${theme.root.shadow.y.rest})`};const newStyles={button:{borderRadius:theme.root.border.radius,color:theme.label.color[actionType],flexDirection:"column",gap:sizing.size_020,maxWidth:theme.label.layout.width,alignSelf:"flex-start",justifySelf:"center",[":is(:hover) .chonky"]:{background:themeVariant.background[kind].hover,border:`${borderWidthKind.hover} solid ${themeVariant.border[kind].hover}`,boxShadow:`0 ${theme.root.shadow.y.hover} 0 0 ${themeVariant.shadow[kind].hover}`,color:themeVariant.foreground[kind].hover,transform:`translateY(calc((${theme.root.shadow.y.hover} - ${theme.root.shadow.y.rest}) * -1))`},[":is(:active) .chonky"]:chonkyPressed,...focusStyles.focus},disabled:{cursor:"not-allowed",color:theme.label.color.disabled,...disabledStatesStyles,":hover":disabledStatesStyles,":active":disabledStatesStyles,":focus-visible":{transform:"none"},[":is(:hover) .chonky"]:disabledStatesStyles,[":is(:hover) .chonky"]:chonkyDisabled,[":is(:active) .chonky"]:chonkyDisabled},pressed:{[".chonky"]:chonkyPressed},chonky:{borderRadius:theme.root.border.radius,marginBlockEnd:theme.root.shadow.y.rest,paddingBlock:theme.root.layout.padding.block,paddingInline:theme.root.layout.padding.inline,background:themeVariant.background[kind].rest,border:`${borderWidthKind.rest} solid ${themeVariant.border[kind].rest}`,color:themeVariant.foreground[kind].rest,boxShadow:`0 ${theme.root.shadow.y.rest} 0 0 ${themeVariant.shadow[kind].rest}`,transition:"all 0.12s ease-out",["@media not (hover: hover)"]:{transition:"none"}},chonkyPressed,chonkyDisabled,label:{margin:0,textAlign:"center",display:"-webkit-box",WebkitBoxOrient:"vertical",WebkitLineClamp:"2",overflow:"hidden",wordBreak:"break-word"}};styles[buttonType]=StyleSheet.create(newStyles);return styles[buttonType]};
21
+
22
+ export { ActivityIconButton, IconButton as default };
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { IconButton as default } from "./components/icon-button";
2
+ export { ActivityIconButton } from "./components/activity-icon-button";
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
3
5
  var jsxRuntime = require('react/jsx-runtime');
4
6
  var React = require('react');
5
7
  var aphrodite = require('aphrodite');
@@ -9,6 +11,7 @@ var wonderBlocksTokens = require('@khanacademy/wonder-blocks-tokens');
9
11
  var reactRouterDomV5Compat = require('react-router-dom-v5-compat');
10
12
  var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
11
13
  var wonderBlocksClickable = require('@khanacademy/wonder-blocks-clickable');
14
+ var wonderBlocksTypography = require('@khanacademy/wonder-blocks-typography');
12
15
 
13
16
  function _interopNamespace(e) {
14
17
  if (e && e.__esModule) return e;
@@ -34,8 +37,11 @@ var themeDefault = {iconButton:{root:{border:{offset:{primary:wonderBlocksTokens
34
37
 
35
38
  var iconButtonTheme = wonderBlocksTokens.mapValuesToCssVars(themeDefault,"--wb-c-icon-button-");
36
39
 
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"}});
40
+ 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$2.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$2=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
+
42
+ const theme$1=iconButtonTheme.iconButton;function IconChooser({icon,size}){const iconStyle={width:theme$1.icon.sizing[size],height:theme$1.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$1(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$1={};const _generateStyles$1=(actionType="progressive",disabled,kind,size)=>{const buttonType=`${actionType}-d_${disabled}-${kind}-${size}`;if(styles$1[buttonType]){return styles$1[buttonType]}const borderWidthKind=theme$1.root.border.width[kind];const outlineOffsetKind=theme$1.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$1.root.border.radius.press,color:themeVariant.press.foreground,transition:"border-radius 0.1s ease-in-out"};const newStyles={default:{height:theme$1.root.sizing[size],width:theme$1.root.sizing[size],borderRadius:theme$1.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$1.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$1.root.border.radius.default},":active":{...disabledStatesStyles,outline:"none",borderRadius:theme$1.root.border.radius.default},":focus-visible":disabledStatesStyles},pressed:pressStyles};styles$1[buttonType]=aphrodite.StyleSheet.create(newStyles);return styles$1[buttonType]};
38
43
 
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]};
44
+ const ActivityIconButton=React__namespace.forwardRef(function ActivityIconButton(props,ref){const{actionType="progressive",disabled=false,icon,kind="primary",style,type="button","aria-label":ariaLabel,label,...restProps}=props;const[pressed,setPressed]=React__namespace.useState(false);const buttonStyles=_generateStyles(actionType,!!disabled,kind);const styles=[buttonStyles.button,disabled&&buttonStyles.disabled,!disabled&&pressed&&buttonStyles.pressed,style];const chonkyStyles=[buttonStyles.chonky,disabled&&buttonStyles.chonkyDisabled,!disabled&&pressed&&buttonStyles.chonkyPressed];const handlePress=React__namespace.useCallback(isPressing=>{setPressed(isPressing);},[]);const hasVisibleLabel=label!==undefined&&label!=="";return jsxRuntime.jsx(IconButtonUnstyled,{...restProps,disabled:disabled,onPress:handlePress,ref:ref,style:styles,type:type,...!hasVisibleLabel?{"aria-label":ariaLabel}:{},children:jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(wonderBlocksCore.View,{style:chonkyStyles,className:"chonky",children:jsxRuntime.jsx(wonderBlocksIcon.PhosphorIcon,{size:"medium",color:"currentColor",icon:icon})}),hasVisibleLabel&&jsxRuntime.jsx(wonderBlocksTypography.BodyText,{tag:"span",size:"medium",weight:"semi",style:buttonStyles.label,children:label})]})})});const theme={root:{border:{width:{primary:{rest:wonderBlocksTokens.border.width.thin,hover:wonderBlocksTokens.border.width.thin,press:wonderBlocksTokens.border.width.thin},secondary:{rest:wonderBlocksTokens.border.width.thin,hover:wonderBlocksTokens.border.width.thin,press:wonderBlocksTokens.border.width.thin},tertiary:{rest:wonderBlocksTokens.border.width.thin,hover:wonderBlocksTokens.border.width.thin,press:wonderBlocksTokens.border.width.thin}},radius:wonderBlocksTokens.border.radius.radius_120},layout:{padding:{block:wonderBlocksTokens.sizing.size_140,inline:wonderBlocksTokens.sizing.size_200}},shadow:{y:{rest:"6px",hover:"8px",press:wonderBlocksTokens.sizing.size_0}}},label:{color:{progressive:wonderBlocksTokens.semanticColor.core.foreground.instructive.default,neutral:wonderBlocksTokens.semanticColor.core.foreground.neutral.default,disabled:wonderBlocksTokens.semanticColor.core.foreground.disabled.default},layout:{width:wonderBlocksTokens.sizing.size_640}}};const styles={};const _generateStyles=(actionType="progressive",disabled,kind)=>{const buttonType=`${actionType}-d_${disabled}-${kind}`;if(styles[buttonType]){return styles[buttonType]}const borderWidthKind=theme.root.border.width[kind];const themeVariant=wonderBlocksTokens.semanticColor.chonky[actionType];const disabledState=wonderBlocksTokens.semanticColor.chonky.disabled;const disabledStatesStyles={outline:"none",transform:"none"};const chonkyDisabled={background:disabledState.background[kind],borderWidth:borderWidthKind.rest,borderColor:disabledState.border[kind],color:disabledState.foreground[kind],boxShadow:`0 ${theme.root.shadow.y.rest} 0 0 ${disabledState.shadow[kind]}`,transform:"none"};const chonkyPressed={background:themeVariant.background[kind].press,border:`${borderWidthKind.press} solid ${themeVariant.border[kind].press}`,boxShadow:`0 ${theme.root.shadow.y.press} 0 0 ${themeVariant.shadow[kind].press}`,color:themeVariant.foreground[kind].press,transform:`translateY(${theme.root.shadow.y.rest})`};const newStyles={button:{borderRadius:theme.root.border.radius,color:theme.label.color[actionType],flexDirection:"column",gap:wonderBlocksTokens.sizing.size_020,maxWidth:theme.label.layout.width,alignSelf:"flex-start",justifySelf:"center",[":is(:hover) .chonky"]:{background:themeVariant.background[kind].hover,border:`${borderWidthKind.hover} solid ${themeVariant.border[kind].hover}`,boxShadow:`0 ${theme.root.shadow.y.hover} 0 0 ${themeVariant.shadow[kind].hover}`,color:themeVariant.foreground[kind].hover,transform:`translateY(calc((${theme.root.shadow.y.hover} - ${theme.root.shadow.y.rest}) * -1))`},[":is(:active) .chonky"]:chonkyPressed,...wonderBlocksStyles.focusStyles.focus},disabled:{cursor:"not-allowed",color:theme.label.color.disabled,...disabledStatesStyles,":hover":disabledStatesStyles,":active":disabledStatesStyles,":focus-visible":{transform:"none"},[":is(:hover) .chonky"]:disabledStatesStyles,[":is(:hover) .chonky"]:chonkyDisabled,[":is(:active) .chonky"]:chonkyDisabled},pressed:{[".chonky"]:chonkyPressed},chonky:{borderRadius:theme.root.border.radius,marginBlockEnd:theme.root.shadow.y.rest,paddingBlock:theme.root.layout.padding.block,paddingInline:theme.root.layout.padding.inline,background:themeVariant.background[kind].rest,border:`${borderWidthKind.rest} solid ${themeVariant.border[kind].rest}`,color:themeVariant.foreground[kind].rest,boxShadow:`0 ${theme.root.shadow.y.rest} 0 0 ${themeVariant.shadow[kind].rest}`,transition:"all 0.12s ease-out",["@media not (hover: hover)"]:{transition:"none"}},chonkyPressed,chonkyDisabled,label:{margin:0,textAlign:"center",display:"-webkit-box",WebkitBoxOrient:"vertical",WebkitLineClamp:"2",overflow:"hidden",wordBreak:"break-word"}};styles[buttonType]=aphrodite.StyleSheet.create(newStyles);return styles[buttonType]};
40
45
 
41
- module.exports = IconButton;
46
+ exports.ActivityIconButton = ActivityIconButton;
47
+ exports["default"] = IconButton;
@@ -1,9 +1,11 @@
1
1
  import * as React from "react";
2
2
  import { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
3
3
  import { PhosphorIconAsset } from "@khanacademy/wonder-blocks-icon";
4
+ import { Link } from "react-router-dom-v5-compat";
4
5
  export type IconButtonKind = "primary" | "secondary" | "tertiary";
5
6
  export type IconButtonSize = "xsmall" | "small" | "medium" | "large";
6
7
  export type IconButtonActionType = "progressive" | "destructive" | "neutral";
8
+ export type ActivityIconButtonActionType = "progressive" | "neutral";
7
9
  export type IconButtonProps = Partial<Omit<AriaProps, "aria-disabled">> & {
8
10
  /**
9
11
  * A unique identifier for the IconButton.
@@ -114,3 +116,4 @@ export type IconButtonProps = Partial<Omit<AriaProps, "aria-disabled">> & {
114
116
  */
115
117
  onMouseDown?: (e: React.MouseEvent) => void;
116
118
  };
119
+ export type IconButtonRef = typeof Link | HTMLButtonElement | HTMLAnchorElement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-icon-button",
3
- "version": "10.1.0",
3
+ "version": "10.2.0",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -20,12 +20,13 @@
20
20
  "author": "",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "@khanacademy/wonder-blocks-clickable": "7.1.3",
23
+ "@khanacademy/wonder-blocks-clickable": "7.1.5",
24
24
  "@khanacademy/wonder-blocks-core": "12.3.0",
25
25
  "@khanacademy/wonder-blocks-icon": "5.1.4",
26
- "@khanacademy/wonder-blocks-styles": "0.2.10",
26
+ "@khanacademy/wonder-blocks-styles": "0.2.12",
27
27
  "@khanacademy/wonder-blocks-theming": "3.4.0",
28
- "@khanacademy/wonder-blocks-tokens": "10.2.1"
28
+ "@khanacademy/wonder-blocks-tokens": "10.4.0",
29
+ "@khanacademy/wonder-blocks-typography": "4.1.0"
29
30
  },
30
31
  "peerDependencies": {
31
32
  "aphrodite": "^1.2.5",
@@ -35,7 +36,7 @@
35
36
  "react-router-dom-v5-compat": "^6.30.0"
36
37
  },
37
38
  "devDependencies": {
38
- "@khanacademy/wb-dev-build-settings": "3.1.0"
39
+ "@khanacademy/wb-dev-build-settings": "3.2.0"
39
40
  },
40
41
  "scripts": {
41
42
  "build:css": "pnpm exec wonder-blocks-tokens .",