@openedx/paragon 22.5.1 → 22.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/Button/index.d.ts +35 -0
  2. package/dist/Button/index.js +38 -15
  3. package/dist/Button/index.js.map +1 -1
  4. package/dist/Chip/ChipIcon.d.ts +2 -2
  5. package/dist/Chip/ChipIcon.js.map +1 -1
  6. package/dist/Chip/index.d.ts +2 -2
  7. package/dist/Chip/index.js +2 -2
  8. package/dist/Chip/index.js.map +1 -1
  9. package/dist/Hyperlink/index.d.ts +1 -1
  10. package/dist/Icon/index.d.ts +4 -2
  11. package/dist/Icon/index.js +1 -1
  12. package/dist/Icon/index.js.map +1 -1
  13. package/dist/Modal/ModalPopup.js +7 -1
  14. package/dist/Modal/ModalPopup.js.map +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.js +3 -3
  17. package/dist/utils/types/bootstrap.d.ts +39 -0
  18. package/dist/utils/types/bootstrap.js +2 -0
  19. package/dist/utils/types/bootstrap.js.map +1 -0
  20. package/package.json +3 -3
  21. package/src/Button/{Button.test.jsx → Button.test.tsx} +14 -2
  22. package/src/Button/__snapshots__/{Button.test.jsx.snap → Button.test.tsx.snap} +19 -2
  23. package/src/Button/{index.jsx → index.tsx} +59 -16
  24. package/src/Chip/ChipIcon.tsx +1 -1
  25. package/src/Chip/index.tsx +5 -5
  26. package/src/Icon/index.d.ts +4 -2
  27. package/src/Icon/index.jsx +1 -1
  28. package/src/Modal/ModalPopup.jsx +9 -1
  29. package/src/Modal/tests/ModalPopupNoMock.test.jsx +29 -0
  30. package/src/index.d.ts +1 -1
  31. package/src/index.js +3 -3
  32. package/src/utils/types/bootstrap.test.tsx +86 -0
  33. package/src/utils/types/bootstrap.ts +43 -0
  34. /package/src/Button/{ButtonGroup.test.jsx → ButtonGroup.test.tsx} +0 -0
  35. /package/src/Button/{ButtonToolbar.test.jsx → ButtonToolbar.test.tsx} +0 -0
  36. /package/src/Button/__snapshots__/{ButtonGroup.test.jsx.snap → ButtonGroup.test.tsx.snap} +0 -0
  37. /package/src/Button/__snapshots__/{ButtonToolbar.test.jsx.snap → ButtonToolbar.test.tsx.snap} +0 -0
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { type ButtonProps as BaseButtonProps } from 'react-bootstrap/Button';
3
+ import { type ButtonGroupProps as BaseButtonGroupProps } from 'react-bootstrap/ButtonGroup';
4
+ import { type ButtonToolbarProps } from 'react-bootstrap/ButtonToolbar';
5
+ import type { ComponentWithAsProp } from '../utils/types/bootstrap';
6
+ interface ButtonProps extends Omit<BaseButtonProps, 'size'> {
7
+ /**
8
+ * An icon component to render. Example:
9
+ * ```
10
+ * import { Close } from '@openedx/paragon/icons';
11
+ * <Button iconBefore={Close}>Close</Button>
12
+ * ```
13
+ */
14
+ iconBefore?: React.ComponentType;
15
+ /**
16
+ * An icon component to render. Example:
17
+ * ```
18
+ * import { Close } from '@openedx/paragon/icons';
19
+ * <Button iconAfter={Close}>Close</Button>
20
+ * ```
21
+ */
22
+ iconAfter?: React.ComponentType;
23
+ size?: 'sm' | 'md' | 'lg' | 'inline';
24
+ }
25
+ type ButtonType = ComponentWithAsProp<'button', ButtonProps> & {
26
+ Deprecated?: any;
27
+ };
28
+ declare const Button: ButtonType;
29
+ interface ButtonGroupProps extends Omit<BaseButtonGroupProps, 'size'> {
30
+ size?: 'sm' | 'md' | 'lg' | 'inline';
31
+ }
32
+ declare const ButtonGroup: ComponentWithAsProp<'div', ButtonGroupProps>;
33
+ declare const ButtonToolbar: ComponentWithAsProp<'div', ButtonToolbarProps>;
34
+ export default Button;
35
+ export { ButtonGroup, ButtonToolbar };
@@ -1,5 +1,6 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
- var _excluded = ["children", "iconAfter", "iconBefore"];
2
+ var _excluded = ["children", "iconAfter", "iconBefore", "size"],
3
+ _excluded2 = ["size"];
3
4
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
5
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
6
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -14,27 +15,31 @@ import classNames from 'classnames';
14
15
  import BaseButton from 'react-bootstrap/Button';
15
16
  import BaseButtonGroup from 'react-bootstrap/ButtonGroup';
16
17
  import BaseButtonToolbar from 'react-bootstrap/ButtonToolbar';
18
+ // @ts-ignore - we're not going to bother adding types for the deprecated button
17
19
  import ButtonDeprecated from './deprecated';
18
20
  import Icon from '../Icon';
19
21
  var Button = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
20
22
  var children = _ref.children,
21
23
  iconAfter = _ref.iconAfter,
22
24
  iconBefore = _ref.iconBefore,
25
+ size = _ref.size,
23
26
  props = _objectWithoutProperties(_ref, _excluded);
24
- return /*#__PURE__*/React.createElement(BaseButton, _extends({}, props, {
27
+ return /*#__PURE__*/React.createElement(BaseButton, _extends({
28
+ size: size // Bootstrap's <Button> types do not allow 'md' or 'inline', but we do.
29
+ }, props, {
25
30
  className: classNames(props.className),
26
31
  ref: ref
27
32
  }), iconBefore && /*#__PURE__*/React.createElement(Icon, {
28
33
  className: "btn-icon-before",
29
- size: props.size,
34
+ size: size,
30
35
  src: iconBefore
31
36
  }), children, iconAfter && /*#__PURE__*/React.createElement(Icon, {
32
37
  className: "btn-icon-after",
33
- size: props.size,
38
+ size: size,
34
39
  src: iconAfter
35
40
  }));
36
41
  });
37
- Button.propTypes = _objectSpread(_objectSpread({}, Button.propTypes), {}, {
42
+ Button.propTypes = {
38
43
  /** Specifies class name to apply to the button */
39
44
  className: PropTypes.string,
40
45
  /** Disables the Button, preventing mouse events, even if the underlying component is an `<a>` element */
@@ -60,11 +65,14 @@ Button.propTypes = _objectSpread(_objectSpread({}, Button.propTypes), {}, {
60
65
  variant: PropTypes.string,
61
66
  /** An icon component to render.
62
67
  * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` */
63
- iconBefore: PropTypes.oneOfType([PropTypes.elementType, PropTypes.node]),
68
+ iconBefore: PropTypes.elementType,
64
69
  /** An icon component to render.
65
70
  * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` */
66
- iconAfter: PropTypes.oneOfType([PropTypes.elementType, PropTypes.node])
67
- });
71
+ iconAfter: PropTypes.elementType
72
+ // The 'as' type casting above is required for TypeScript checking, because the 'PropTypes.elementType' type normally
73
+ // allows strings as a value (for use cases like 'div') but we don't support that for <Icon />/iconBefore/iconAfter.
74
+ // The React TypeScript type definitions are more specific (React.ComponentType vs React.ElementType).
75
+ };
68
76
  Button.defaultProps = _objectSpread(_objectSpread({}, Button.defaultProps), {}, {
69
77
  children: undefined,
70
78
  className: undefined,
@@ -73,19 +81,29 @@ Button.defaultProps = _objectSpread(_objectSpread({}, Button.defaultProps), {},
73
81
  disabled: false
74
82
  });
75
83
  Button.Deprecated = ButtonDeprecated;
76
- function ButtonGroup(props) {
77
- return /*#__PURE__*/React.createElement(BaseButtonGroup, props);
78
- }
79
- function ButtonToolbar(props) {
80
- return /*#__PURE__*/React.createElement(BaseButtonToolbar, props);
81
- }
84
+
85
+ // We could just re-export 'ButtonGroup' and 'ButtonToolbar', but we currently
86
+ // override them to add propTypes validation at runtime, since most Paragon
87
+ // consumers aren't using TypeScript yet. We also force ButtonGroup's 'size'
88
+ // prop to accept our custom values of 'md' and 'inline' which are used in
89
+ // Paragon but not used in the base Bootstrap classes.
90
+
91
+ var ButtonGroup = /*#__PURE__*/React.forwardRef(function (_ref2, ref) {
92
+ var size = _ref2.size,
93
+ props = _objectWithoutProperties(_ref2, _excluded2);
94
+ return /*#__PURE__*/React.createElement(BaseButtonGroup, _extends({
95
+ size: size
96
+ }, props, {
97
+ ref: ref
98
+ }));
99
+ });
82
100
  ButtonGroup.propTypes = {
83
101
  /** Specifies element type for this component. */
84
102
  as: PropTypes.elementType,
85
103
  /** An ARIA role describing the button group. */
86
104
  role: PropTypes.string,
87
105
  /** Specifies the size for all Buttons in the group. */
88
- size: PropTypes.oneOf(['sm', 'md', 'lg']),
106
+ size: PropTypes.oneOf(['sm', 'md', 'lg', 'inline']),
89
107
  /** Display as a button toggle group. */
90
108
  toggle: PropTypes.bool,
91
109
  /** Specifies if the set of Buttons should appear vertically stacked. */
@@ -101,6 +119,11 @@ ButtonGroup.defaultProps = {
101
119
  bsPrefix: 'btn-group',
102
120
  size: 'md'
103
121
  };
122
+ var ButtonToolbar = /*#__PURE__*/React.forwardRef(function (props, ref) {
123
+ return /*#__PURE__*/React.createElement(BaseButtonToolbar, _extends({}, props, {
124
+ ref: ref
125
+ }));
126
+ });
104
127
  ButtonToolbar.propTypes = {
105
128
  /** An ARIA role describing the button group. */
106
129
  role: PropTypes.string,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["React","PropTypes","classNames","BaseButton","BaseButtonGroup","BaseButtonToolbar","ButtonDeprecated","Icon","Button","forwardRef","_ref","ref","children","iconAfter","iconBefore","props","_objectWithoutProperties","_excluded","createElement","_extends","className","size","src","propTypes","_objectSpread","string","disabled","bool","node","isRequired","onClick","func","onKeyDown","type","variant","oneOfType","elementType","defaultProps","undefined","Deprecated","ButtonGroup","ButtonToolbar","as","role","oneOf","toggle","vertical","bsPrefix"],"sources":["../../src/Button/index.jsx"],"sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\nimport BaseButton from 'react-bootstrap/Button';\nimport BaseButtonGroup from 'react-bootstrap/ButtonGroup';\nimport BaseButtonToolbar from 'react-bootstrap/ButtonToolbar';\nimport ButtonDeprecated from './deprecated';\n\nimport Icon from '../Icon';\n\nconst Button = React.forwardRef(({\n children,\n iconAfter,\n iconBefore,\n ...props\n}, ref) => (\n <BaseButton\n {...props}\n className={classNames(props.className)}\n ref={ref}\n >\n {iconBefore && <Icon className=\"btn-icon-before\" size={props.size} src={iconBefore} />}\n {children}\n {iconAfter && <Icon className=\"btn-icon-after\" size={props.size} src={iconAfter} />}\n </BaseButton>\n));\n\nButton.propTypes = {\n ...Button.propTypes,\n /** Specifies class name to apply to the button */\n className: PropTypes.string,\n /** Disables the Button, preventing mouse events, even if the underlying component is an `<a>` element */\n disabled: PropTypes.bool,\n /** Specifies the text that is displayed within the button. */\n children: PropTypes.node.isRequired,\n /** A function that would specify what the button should do when the `onClick` event is triggered.\n * For example, the button could launch a `Modal`. The default is an empty function. */\n onClick: PropTypes.func,\n /** A function that would specify what the button should do when the `onKeyDown` event is triggered.\n * For example, this could handle using the `Escape` key to trigger the button's action.\n * The default is an empty function. */\n onKeyDown: PropTypes.func,\n /** Used to set the `type` attribute on the `button` tag. The default type is `button`. */\n type: PropTypes.string,\n /** Specifies variant to use.\n * Can be on of the base variants: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `dark`,\n * `light`, `link`\n *\n * as well as one of the customized variants (= base variant prefixed with `inverse-`, `outline-`\n * or `inverse-outline-`)\n * */\n variant: PropTypes.string,\n /** An icon component to render.\n * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` */\n iconBefore: PropTypes.oneOfType([PropTypes.elementType, PropTypes.node]),\n /** An icon component to render.\n * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` */\n iconAfter: PropTypes.oneOfType([PropTypes.elementType, PropTypes.node]),\n};\n\nButton.defaultProps = {\n ...Button.defaultProps,\n children: undefined,\n className: undefined,\n iconBefore: undefined,\n iconAfter: undefined,\n disabled: false,\n};\n\nButton.Deprecated = ButtonDeprecated;\n\nfunction ButtonGroup(props) {\n return <BaseButtonGroup {...props} />;\n}\nfunction ButtonToolbar(props) {\n return <BaseButtonToolbar {...props} />;\n}\n\nButtonGroup.propTypes = {\n /** Specifies element type for this component. */\n as: PropTypes.elementType,\n /** An ARIA role describing the button group. */\n role: PropTypes.string,\n /** Specifies the size for all Buttons in the group. */\n size: PropTypes.oneOf(['sm', 'md', 'lg']),\n /** Display as a button toggle group. */\n toggle: PropTypes.bool,\n /** Specifies if the set of Buttons should appear vertically stacked. */\n vertical: PropTypes.bool,\n /** Overrides underlying component base CSS class name */\n bsPrefix: PropTypes.string,\n};\n\nButtonGroup.defaultProps = {\n as: 'div',\n role: 'group',\n toggle: false,\n vertical: false,\n bsPrefix: 'btn-group',\n size: 'md',\n};\n\nButtonToolbar.propTypes = {\n /** An ARIA role describing the button group. */\n role: PropTypes.string,\n /** Overrides underlying component base CSS class name */\n bsPrefix: PropTypes.string,\n};\n\nButtonToolbar.defaultProps = {\n role: 'toolbar',\n bsPrefix: 'btn-toolbar',\n};\n\nexport default Button;\nexport { ButtonGroup, ButtonToolbar };\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["React","PropTypes","classNames","BaseButton","BaseButtonGroup","BaseButtonToolbar","ButtonDeprecated","Icon","Button","forwardRef","_ref","ref","children","iconAfter","iconBefore","size","props","_objectWithoutProperties","_excluded","createElement","_extends","className","src","propTypes","string","disabled","bool","node","isRequired","onClick","func","onKeyDown","type","variant","elementType","defaultProps","_objectSpread","undefined","Deprecated","ButtonGroup","_ref2","_excluded2","as","role","oneOf","toggle","vertical","bsPrefix","ButtonToolbar"],"sources":["../../src/Button/index.tsx"],"sourcesContent":["import React from 'react';\nimport PropTypes, { type Requireable } from 'prop-types';\nimport classNames from 'classnames';\nimport BaseButton, { type ButtonProps as BaseButtonProps } from 'react-bootstrap/Button';\nimport BaseButtonGroup, { type ButtonGroupProps as BaseButtonGroupProps } from 'react-bootstrap/ButtonGroup';\nimport BaseButtonToolbar, { type ButtonToolbarProps } from 'react-bootstrap/ButtonToolbar';\nimport type { ComponentWithAsProp } from '../utils/types/bootstrap';\n// @ts-ignore - we're not going to bother adding types for the deprecated button\nimport ButtonDeprecated from './deprecated';\n\nimport Icon from '../Icon';\n\ninterface ButtonProps extends Omit<BaseButtonProps, 'size'> {\n /**\n * An icon component to render. Example:\n * ```\n * import { Close } from '@openedx/paragon/icons';\n * <Button iconBefore={Close}>Close</Button>\n * ```\n */\n iconBefore?: React.ComponentType;\n /**\n * An icon component to render. Example:\n * ```\n * import { Close } from '@openedx/paragon/icons';\n * <Button iconAfter={Close}>Close</Button>\n * ```\n */\n iconAfter?: React.ComponentType;\n size?: 'sm' | 'md' | 'lg' | 'inline';\n}\n\ntype ButtonType = ComponentWithAsProp<'button', ButtonProps> & { Deprecated?: any };\n\nconst Button: ButtonType = React.forwardRef<HTMLButtonElement, ButtonProps>(({\n children,\n iconAfter,\n iconBefore,\n size,\n ...props\n}, ref) => (\n <BaseButton\n size={size as 'sm' | 'lg' | undefined} // Bootstrap's <Button> types do not allow 'md' or 'inline', but we do.\n {...props}\n className={classNames(props.className)}\n ref={ref}\n >\n {iconBefore && <Icon className=\"btn-icon-before\" size={size} src={iconBefore} />}\n {children}\n {iconAfter && <Icon className=\"btn-icon-after\" size={size} src={iconAfter} />}\n </BaseButton>\n));\n\nButton.propTypes = {\n /** Specifies class name to apply to the button */\n className: PropTypes.string,\n /** Disables the Button, preventing mouse events, even if the underlying component is an `<a>` element */\n disabled: PropTypes.bool,\n /** Specifies the text that is displayed within the button. */\n children: PropTypes.node.isRequired,\n /** A function that would specify what the button should do when the `onClick` event is triggered.\n * For example, the button could launch a `Modal`. The default is an empty function. */\n onClick: PropTypes.func,\n /** A function that would specify what the button should do when the `onKeyDown` event is triggered.\n * For example, this could handle using the `Escape` key to trigger the button's action.\n * The default is an empty function. */\n onKeyDown: PropTypes.func,\n /** Used to set the `type` attribute on the `button` tag. The default type is `button`. */\n type: PropTypes.string,\n /** Specifies variant to use.\n * Can be on of the base variants: `primary`, `secondary`, `success`, `danger`, `warning`, `info`, `dark`,\n * `light`, `link`\n *\n * as well as one of the customized variants (= base variant prefixed with `inverse-`, `outline-`\n * or `inverse-outline-`)\n * */\n variant: PropTypes.string,\n /** An icon component to render.\n * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` */\n iconBefore: PropTypes.elementType as Requireable<React.ComponentType>,\n /** An icon component to render.\n * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` */\n iconAfter: PropTypes.elementType as Requireable<React.ComponentType>,\n // The 'as' type casting above is required for TypeScript checking, because the 'PropTypes.elementType' type normally\n // allows strings as a value (for use cases like 'div') but we don't support that for <Icon />/iconBefore/iconAfter.\n // The React TypeScript type definitions are more specific (React.ComponentType vs React.ElementType).\n};\n\nButton.defaultProps = {\n ...Button.defaultProps,\n children: undefined,\n className: undefined,\n iconBefore: undefined,\n iconAfter: undefined,\n disabled: false,\n};\n\nButton.Deprecated = ButtonDeprecated;\n\n// We could just re-export 'ButtonGroup' and 'ButtonToolbar', but we currently\n// override them to add propTypes validation at runtime, since most Paragon\n// consumers aren't using TypeScript yet. We also force ButtonGroup's 'size'\n// prop to accept our custom values of 'md' and 'inline' which are used in\n// Paragon but not used in the base Bootstrap classes.\n\ninterface ButtonGroupProps extends Omit<BaseButtonGroupProps, 'size'> {\n size?: 'sm' | 'md' | 'lg' | 'inline';\n}\n\nconst ButtonGroup: ComponentWithAsProp<'div', ButtonGroupProps> = (\n React.forwardRef<HTMLButtonElement, ButtonGroupProps>(({ size, ...props }, ref) => (\n <BaseButtonGroup size={size as 'sm' | 'lg'} {...props} ref={ref} />\n ))\n);\n\nButtonGroup.propTypes = {\n /** Specifies element type for this component. */\n as: PropTypes.elementType,\n /** An ARIA role describing the button group. */\n role: PropTypes.string,\n /** Specifies the size for all Buttons in the group. */\n size: PropTypes.oneOf(['sm', 'md', 'lg', 'inline']),\n /** Display as a button toggle group. */\n toggle: PropTypes.bool,\n /** Specifies if the set of Buttons should appear vertically stacked. */\n vertical: PropTypes.bool,\n /** Overrides underlying component base CSS class name */\n bsPrefix: PropTypes.string,\n};\n\nButtonGroup.defaultProps = {\n as: 'div',\n role: 'group',\n toggle: false,\n vertical: false,\n bsPrefix: 'btn-group',\n size: 'md',\n};\n\nconst ButtonToolbar: ComponentWithAsProp<'div', ButtonToolbarProps> = (\n React.forwardRef<HTMLButtonElement, ButtonToolbarProps>((props, ref) => (\n <BaseButtonToolbar {...props} ref={ref} />\n ))\n);\n\nButtonToolbar.propTypes = {\n /** An ARIA role describing the button group. */\n role: PropTypes.string,\n /** Overrides underlying component base CSS class name */\n bsPrefix: PropTypes.string,\n};\n\nButtonToolbar.defaultProps = {\n role: 'toolbar',\n bsPrefix: 'btn-toolbar',\n};\n\nexport default Button;\nexport { ButtonGroup, ButtonToolbar };\n"],"mappings":"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","ignoreList":[]}
@@ -2,13 +2,13 @@ import React, { KeyboardEventHandler, MouseEventHandler } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  export interface ChipIconProps {
4
4
  className: string;
5
- src: React.ReactElement | Function;
5
+ src: React.ComponentType;
6
6
  onClick?: KeyboardEventHandler & MouseEventHandler;
7
7
  alt?: string;
8
8
  variant: string;
9
9
  disabled?: boolean;
10
10
  }
11
- declare function ChipIcon({ className, src, onClick, alt, variant, disabled, }: ChipIconProps): JSX.Element;
11
+ declare function ChipIcon({ className, src, onClick, alt, variant, disabled, }: ChipIconProps): React.JSX.Element;
12
12
  declare namespace ChipIcon {
13
13
  var propTypes: {
14
14
  className: PropTypes.Validator<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"ChipIcon.js","names":["React","PropTypes","Icon","IconButton","STYLE_VARIANTS","ChipIcon","_ref","className","src","onClick","alt","variant","disabled","createElement","iconAs","invertColors","DARK","tabIndex","size","propTypes","string","isRequired","oneOfType","element","func","bool","defaultProps","undefined","LIGHT"],"sources":["../../src/Chip/ChipIcon.tsx"],"sourcesContent":["import React, { KeyboardEventHandler, MouseEventHandler } from 'react';\nimport PropTypes from 'prop-types';\nimport Icon from '../Icon';\n// @ts-ignore\nimport IconButton from '../IconButton';\n// @ts-ignore\nimport { STYLE_VARIANTS } from './constants';\n\nexport interface ChipIconProps {\n className: string,\n src: React.ReactElement | Function,\n onClick?: KeyboardEventHandler & MouseEventHandler,\n alt?: string,\n variant: string,\n disabled?: boolean,\n}\n\nfunction ChipIcon({\n className, src, onClick, alt, variant, disabled,\n}: ChipIconProps) {\n if (onClick) {\n return (\n <IconButton\n className={className}\n src={src}\n onClick={onClick}\n iconAs={Icon}\n alt={alt}\n invertColors={variant === STYLE_VARIANTS.DARK}\n tabIndex={disabled ? -1 : 0}\n />\n );\n }\n\n return <Icon src={src} className={className} size=\"sm\" />;\n}\n\nChipIcon.propTypes = {\n className: PropTypes.string.isRequired,\n src: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,\n onClick: PropTypes.func,\n alt: PropTypes.string,\n variant: PropTypes.string,\n disabled: PropTypes.bool,\n};\n\nChipIcon.defaultProps = {\n onClick: undefined,\n alt: undefined,\n variant: STYLE_VARIANTS.LIGHT,\n disabled: false,\n};\n\nexport default ChipIcon;\n"],"mappings":"AAAA,OAAOA,KAAK,MAAmD,OAAO;AACtE,OAAOC,SAAS,MAAM,YAAY;AAClC,OAAOC,IAAI,MAAM,SAAS;AAC1B;AACA,OAAOC,UAAU,MAAM,eAAe;AACtC;AACA,SAASC,cAAc,QAAQ,aAAa;AAW5C,SAASC,QAAQA,CAAAC,IAAA,EAEC;EAAA,IADhBC,SAAS,GAAAD,IAAA,CAATC,SAAS;IAAEC,GAAG,GAAAF,IAAA,CAAHE,GAAG;IAAEC,OAAO,GAAAH,IAAA,CAAPG,OAAO;IAAEC,GAAG,GAAAJ,IAAA,CAAHI,GAAG;IAAEC,OAAO,GAAAL,IAAA,CAAPK,OAAO;IAAEC,QAAQ,GAAAN,IAAA,CAARM,QAAQ;EAE/C,IAAIH,OAAO,EAAE;IACX,oBACET,KAAA,CAAAa,aAAA,CAACV,UAAU;MACTI,SAAS,EAAEA,SAAU;MACrBC,GAAG,EAAEA,GAAI;MACTC,OAAO,EAAEA,OAAQ;MACjBK,MAAM,EAAEZ,IAAK;MACbQ,GAAG,EAAEA,GAAI;MACTK,YAAY,EAAEJ,OAAO,KAAKP,cAAc,CAACY,IAAK;MAC9CC,QAAQ,EAAEL,QAAQ,GAAG,CAAC,CAAC,GAAG;IAAE,CAC7B,CAAC;EAEN;EAEA,oBAAOZ,KAAA,CAAAa,aAAA,CAACX,IAAI;IAACM,GAAG,EAAEA,GAAI;IAACD,SAAS,EAAEA,SAAU;IAACW,IAAI,EAAC;EAAI,CAAE,CAAC;AAC3D;AAEAb,QAAQ,CAACc,SAAS,GAAG;EACnBZ,SAAS,EAAEN,SAAS,CAACmB,MAAM,CAACC,UAAU;EACtCb,GAAG,EAAEP,SAAS,CAACqB,SAAS,CAAC,CAACrB,SAAS,CAACsB,OAAO,EAAEtB,SAAS,CAACuB,IAAI,CAAC,CAAC,CAACH,UAAU;EACxEZ,OAAO,EAAER,SAAS,CAACuB,IAAI;EACvBd,GAAG,EAAET,SAAS,CAACmB,MAAM;EACrBT,OAAO,EAAEV,SAAS,CAACmB,MAAM;EACzBR,QAAQ,EAAEX,SAAS,CAACwB;AACtB,CAAC;AAEDpB,QAAQ,CAACqB,YAAY,GAAG;EACtBjB,OAAO,EAAEkB,SAAS;EAClBjB,GAAG,EAAEiB,SAAS;EACdhB,OAAO,EAAEP,cAAc,CAACwB,KAAK;EAC7BhB,QAAQ,EAAE;AACZ,CAAC;AAED,eAAeP,QAAQ","ignoreList":[]}
1
+ {"version":3,"file":"ChipIcon.js","names":["React","PropTypes","Icon","IconButton","STYLE_VARIANTS","ChipIcon","_ref","className","src","onClick","alt","variant","disabled","createElement","iconAs","invertColors","DARK","tabIndex","size","propTypes","string","isRequired","oneOfType","element","func","bool","defaultProps","undefined","LIGHT"],"sources":["../../src/Chip/ChipIcon.tsx"],"sourcesContent":["import React, { KeyboardEventHandler, MouseEventHandler } from 'react';\nimport PropTypes from 'prop-types';\nimport Icon from '../Icon';\n// @ts-ignore\nimport IconButton from '../IconButton';\n// @ts-ignore\nimport { STYLE_VARIANTS } from './constants';\n\nexport interface ChipIconProps {\n className: string,\n src: React.ComponentType,\n onClick?: KeyboardEventHandler & MouseEventHandler,\n alt?: string,\n variant: string,\n disabled?: boolean,\n}\n\nfunction ChipIcon({\n className, src, onClick, alt, variant, disabled,\n}: ChipIconProps) {\n if (onClick) {\n return (\n <IconButton\n className={className}\n src={src}\n onClick={onClick}\n iconAs={Icon}\n alt={alt}\n invertColors={variant === STYLE_VARIANTS.DARK}\n tabIndex={disabled ? -1 : 0}\n />\n );\n }\n\n return <Icon src={src} className={className} size=\"sm\" />;\n}\n\nChipIcon.propTypes = {\n className: PropTypes.string.isRequired,\n src: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired,\n onClick: PropTypes.func,\n alt: PropTypes.string,\n variant: PropTypes.string,\n disabled: PropTypes.bool,\n};\n\nChipIcon.defaultProps = {\n onClick: undefined,\n alt: undefined,\n variant: STYLE_VARIANTS.LIGHT,\n disabled: false,\n};\n\nexport default ChipIcon;\n"],"mappings":"AAAA,OAAOA,KAAK,MAAmD,OAAO;AACtE,OAAOC,SAAS,MAAM,YAAY;AAClC,OAAOC,IAAI,MAAM,SAAS;AAC1B;AACA,OAAOC,UAAU,MAAM,eAAe;AACtC;AACA,SAASC,cAAc,QAAQ,aAAa;AAW5C,SAASC,QAAQA,CAAAC,IAAA,EAEC;EAAA,IADhBC,SAAS,GAAAD,IAAA,CAATC,SAAS;IAAEC,GAAG,GAAAF,IAAA,CAAHE,GAAG;IAAEC,OAAO,GAAAH,IAAA,CAAPG,OAAO;IAAEC,GAAG,GAAAJ,IAAA,CAAHI,GAAG;IAAEC,OAAO,GAAAL,IAAA,CAAPK,OAAO;IAAEC,QAAQ,GAAAN,IAAA,CAARM,QAAQ;EAE/C,IAAIH,OAAO,EAAE;IACX,oBACET,KAAA,CAAAa,aAAA,CAACV,UAAU;MACTI,SAAS,EAAEA,SAAU;MACrBC,GAAG,EAAEA,GAAI;MACTC,OAAO,EAAEA,OAAQ;MACjBK,MAAM,EAAEZ,IAAK;MACbQ,GAAG,EAAEA,GAAI;MACTK,YAAY,EAAEJ,OAAO,KAAKP,cAAc,CAACY,IAAK;MAC9CC,QAAQ,EAAEL,QAAQ,GAAG,CAAC,CAAC,GAAG;IAAE,CAC7B,CAAC;EAEN;EAEA,oBAAOZ,KAAA,CAAAa,aAAA,CAACX,IAAI;IAACM,GAAG,EAAEA,GAAI;IAACD,SAAS,EAAEA,SAAU;IAACW,IAAI,EAAC;EAAI,CAAE,CAAC;AAC3D;AAEAb,QAAQ,CAACc,SAAS,GAAG;EACnBZ,SAAS,EAAEN,SAAS,CAACmB,MAAM,CAACC,UAAU;EACtCb,GAAG,EAAEP,SAAS,CAACqB,SAAS,CAAC,CAACrB,SAAS,CAACsB,OAAO,EAAEtB,SAAS,CAACuB,IAAI,CAAC,CAAC,CAACH,UAAU;EACxEZ,OAAO,EAAER,SAAS,CAACuB,IAAI;EACvBd,GAAG,EAAET,SAAS,CAACmB,MAAM;EACrBT,OAAO,EAAEV,SAAS,CAACmB,MAAM;EACzBR,QAAQ,EAAEX,SAAS,CAACwB;AACtB,CAAC;AAEDpB,QAAQ,CAACqB,YAAY,GAAG;EACtBjB,OAAO,EAAEkB,SAAS;EAClBjB,GAAG,EAAEiB,SAAS;EACdhB,OAAO,EAAEP,cAAc,CAACwB,KAAK;EAC7BhB,QAAQ,EAAE;AACZ,CAAC;AAED,eAAeP,QAAQ","ignoreList":[]}
@@ -5,9 +5,9 @@ export interface IChip {
5
5
  onClick?: KeyboardEventHandler & MouseEventHandler;
6
6
  className?: string;
7
7
  variant?: string;
8
- iconBefore?: React.ReactElement | Function;
8
+ iconBefore?: React.ComponentType;
9
9
  iconBeforeAlt?: string;
10
- iconAfter?: React.ReactElement | Function;
10
+ iconAfter?: React.ComponentType;
11
11
  iconAfterAlt?: string;
12
12
  onIconBeforeClick?: KeyboardEventHandler & MouseEventHandler;
13
13
  onIconAfterClick?: KeyboardEventHandler & MouseEventHandler;
@@ -79,7 +79,7 @@ Chip.propTypes = {
79
79
  *
80
80
  * `import { Check } from '@openedx/paragon/icons';`
81
81
  */
82
- iconBefore: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
82
+ iconBefore: PropTypes.elementType,
83
83
  /** Specifies icon alt text. */
84
84
  iconBeforeAlt: requiredWhen(PropTypes.string, ['iconBefore', 'onIconBeforeClick']),
85
85
  /** A click handler for the `Chip` icon before. */
@@ -90,7 +90,7 @@ Chip.propTypes = {
90
90
  *
91
91
  * `import { Check } from '@openedx/paragon/icons';`
92
92
  */
93
- iconAfter: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
93
+ iconAfter: PropTypes.elementType,
94
94
  /** Specifies icon alt text. */
95
95
  iconAfterAlt: requiredWhen(PropTypes.string, ['iconAfter', 'onIconAfterClick']),
96
96
  /** A click handler for the `Chip` icon after. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["React","PropTypes","classNames","requiredWhen","STYLE_VARIANTS","ChipIcon","CHIP_PGN_CLASS","Chip","forwardRef","_ref","ref","children","className","variant","iconBefore","iconBeforeAlt","iconAfter","iconAfterAlt","onIconBeforeClick","onIconAfterClick","disabled","isSelected","onClick","props","_objectWithoutProperties","_excluded","hasInteractiveIcons","isChipInteractive","interactionProps","onKeyPress","tabIndex","role","createElement","_extends","concat","selected","interactive","src","alt","propTypes","node","isRequired","string","oneOf","bool","func","oneOfType","element","defaultProps","undefined","LIGHT"],"sources":["../../src/Chip/index.tsx"],"sourcesContent":["import React, { ForwardedRef, KeyboardEventHandler, MouseEventHandler } from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n// @ts-ignore\nimport { requiredWhen } from '../utils/propTypes';\n// @ts-ignore\nimport { STYLE_VARIANTS } from './constants';\n// @ts-ignore\nimport ChipIcon from './ChipIcon';\n\nexport const CHIP_PGN_CLASS = 'pgn__chip';\n\nexport interface IChip {\n children: React.ReactNode,\n onClick?: KeyboardEventHandler & MouseEventHandler,\n className?: string,\n variant?: string,\n iconBefore?: React.ReactElement | Function,\n iconBeforeAlt?: string,\n iconAfter?: React.ReactElement | Function,\n iconAfterAlt?: string,\n onIconBeforeClick?: KeyboardEventHandler & MouseEventHandler,\n onIconAfterClick?: KeyboardEventHandler & MouseEventHandler,\n disabled?: boolean,\n isSelected?: boolean,\n}\n\nconst Chip = React.forwardRef(({\n children,\n className,\n variant,\n iconBefore,\n iconBeforeAlt,\n iconAfter,\n iconAfterAlt,\n onIconBeforeClick,\n onIconAfterClick,\n disabled,\n isSelected,\n onClick,\n ...props\n}: IChip, ref: ForwardedRef<HTMLDivElement>) => {\n const hasInteractiveIcons = !!(onIconBeforeClick || onIconAfterClick);\n const isChipInteractive = !hasInteractiveIcons && !!onClick;\n\n const interactionProps = isChipInteractive ? {\n onClick,\n onKeyPress: onClick,\n tabIndex: 0,\n role: 'button',\n } : {};\n\n return (\n <div\n className={classNames(\n CHIP_PGN_CLASS,\n `pgn__chip-${variant}`,\n className,\n { disabled, selected: isSelected, interactive: isChipInteractive },\n )}\n ref={ref}\n {...interactionProps}\n {...props}\n >\n {iconBefore && (\n <ChipIcon\n className={`${CHIP_PGN_CLASS}__icon-before`}\n src={iconBefore}\n onClick={onIconBeforeClick}\n alt={iconBeforeAlt}\n variant={variant}\n disabled={disabled}\n />\n )}\n <div\n className={classNames(`${CHIP_PGN_CLASS}__label`, {\n 'p-before': iconBefore,\n 'p-after': iconAfter,\n })}\n >\n {children}\n </div>\n {iconAfter && (\n <ChipIcon\n className={`${CHIP_PGN_CLASS}__icon-after`}\n src={iconAfter}\n onClick={onIconAfterClick}\n alt={iconAfterAlt}\n variant={variant}\n disabled={disabled}\n />\n )}\n </div>\n );\n});\n\nChip.propTypes = {\n /** Specifies the content of the `Chip`. */\n children: PropTypes.node.isRequired,\n /** Specifies an additional `className` to add to the base element. */\n className: PropTypes.string,\n /** The `Chip` style variant to use. */\n variant: PropTypes.oneOf(['light', 'dark']),\n /** Disables the `Chip`. */\n disabled: PropTypes.bool,\n /** Click handler for the whole Chip, has effect only when Chip does not have any interactive icons. */\n onClick: PropTypes.func,\n /**\n * An icon component to render before the content.\n * Example import of a Paragon icon component:\n *\n * `import { Check } from '@openedx/paragon/icons';`\n */\n iconBefore: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),\n /** Specifies icon alt text. */\n iconBeforeAlt: requiredWhen(PropTypes.string, ['iconBefore', 'onIconBeforeClick']),\n /** A click handler for the `Chip` icon before. */\n onIconBeforeClick: PropTypes.func,\n /**\n * An icon component to render before after the content.\n * Example import of a Paragon icon component:\n *\n * `import { Check } from '@openedx/paragon/icons';`\n */\n iconAfter: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),\n /** Specifies icon alt text. */\n iconAfterAlt: requiredWhen(PropTypes.string, ['iconAfter', 'onIconAfterClick']),\n /** A click handler for the `Chip` icon after. */\n onIconAfterClick: PropTypes.func,\n /** Indicates if `Chip` has been selected. */\n isSelected: PropTypes.bool,\n};\n\nChip.defaultProps = {\n className: undefined,\n variant: STYLE_VARIANTS.LIGHT,\n disabled: false,\n onClick: undefined,\n iconBefore: undefined,\n iconAfter: undefined,\n onIconBeforeClick: undefined,\n onIconAfterClick: undefined,\n isSelected: false,\n iconAfterAlt: undefined,\n iconBeforeAlt: undefined,\n};\n\nexport default Chip;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["React","PropTypes","classNames","requiredWhen","STYLE_VARIANTS","ChipIcon","CHIP_PGN_CLASS","Chip","forwardRef","_ref","ref","children","className","variant","iconBefore","iconBeforeAlt","iconAfter","iconAfterAlt","onIconBeforeClick","onIconAfterClick","disabled","isSelected","onClick","props","_objectWithoutProperties","_excluded","hasInteractiveIcons","isChipInteractive","interactionProps","onKeyPress","tabIndex","role","createElement","_extends","concat","selected","interactive","src","alt","propTypes","node","isRequired","string","oneOf","bool","func","elementType","defaultProps","undefined","LIGHT"],"sources":["../../src/Chip/index.tsx"],"sourcesContent":["import React, { ForwardedRef, KeyboardEventHandler, MouseEventHandler } from 'react';\nimport PropTypes, { type Requireable } from 'prop-types';\nimport classNames from 'classnames';\n// @ts-ignore\nimport { requiredWhen } from '../utils/propTypes';\n// @ts-ignore\nimport { STYLE_VARIANTS } from './constants';\n// @ts-ignore\nimport ChipIcon from './ChipIcon';\n\nexport const CHIP_PGN_CLASS = 'pgn__chip';\n\nexport interface IChip {\n children: React.ReactNode,\n onClick?: KeyboardEventHandler & MouseEventHandler,\n className?: string,\n variant?: string,\n iconBefore?: React.ComponentType,\n iconBeforeAlt?: string,\n iconAfter?: React.ComponentType,\n iconAfterAlt?: string,\n onIconBeforeClick?: KeyboardEventHandler & MouseEventHandler,\n onIconAfterClick?: KeyboardEventHandler & MouseEventHandler,\n disabled?: boolean,\n isSelected?: boolean,\n}\n\nconst Chip = React.forwardRef(({\n children,\n className,\n variant,\n iconBefore,\n iconBeforeAlt,\n iconAfter,\n iconAfterAlt,\n onIconBeforeClick,\n onIconAfterClick,\n disabled,\n isSelected,\n onClick,\n ...props\n}: IChip, ref: ForwardedRef<HTMLDivElement>) => {\n const hasInteractiveIcons = !!(onIconBeforeClick || onIconAfterClick);\n const isChipInteractive = !hasInteractiveIcons && !!onClick;\n\n const interactionProps = isChipInteractive ? {\n onClick,\n onKeyPress: onClick,\n tabIndex: 0,\n role: 'button',\n } : {};\n\n return (\n <div\n className={classNames(\n CHIP_PGN_CLASS,\n `pgn__chip-${variant}`,\n className,\n { disabled, selected: isSelected, interactive: isChipInteractive },\n )}\n ref={ref}\n {...interactionProps}\n {...props}\n >\n {iconBefore && (\n <ChipIcon\n className={`${CHIP_PGN_CLASS}__icon-before`}\n src={iconBefore}\n onClick={onIconBeforeClick}\n alt={iconBeforeAlt}\n variant={variant}\n disabled={disabled}\n />\n )}\n <div\n className={classNames(`${CHIP_PGN_CLASS}__label`, {\n 'p-before': iconBefore,\n 'p-after': iconAfter,\n })}\n >\n {children}\n </div>\n {iconAfter && (\n <ChipIcon\n className={`${CHIP_PGN_CLASS}__icon-after`}\n src={iconAfter}\n onClick={onIconAfterClick}\n alt={iconAfterAlt}\n variant={variant}\n disabled={disabled}\n />\n )}\n </div>\n );\n});\n\nChip.propTypes = {\n /** Specifies the content of the `Chip`. */\n children: PropTypes.node.isRequired,\n /** Specifies an additional `className` to add to the base element. */\n className: PropTypes.string,\n /** The `Chip` style variant to use. */\n variant: PropTypes.oneOf(['light', 'dark']),\n /** Disables the `Chip`. */\n disabled: PropTypes.bool,\n /** Click handler for the whole Chip, has effect only when Chip does not have any interactive icons. */\n onClick: PropTypes.func,\n /**\n * An icon component to render before the content.\n * Example import of a Paragon icon component:\n *\n * `import { Check } from '@openedx/paragon/icons';`\n */\n iconBefore: PropTypes.elementType as Requireable<React.ComponentType>,\n /** Specifies icon alt text. */\n iconBeforeAlt: requiredWhen(PropTypes.string, ['iconBefore', 'onIconBeforeClick']),\n /** A click handler for the `Chip` icon before. */\n onIconBeforeClick: PropTypes.func,\n /**\n * An icon component to render before after the content.\n * Example import of a Paragon icon component:\n *\n * `import { Check } from '@openedx/paragon/icons';`\n */\n iconAfter: PropTypes.elementType as Requireable<React.ComponentType>,\n /** Specifies icon alt text. */\n iconAfterAlt: requiredWhen(PropTypes.string, ['iconAfter', 'onIconAfterClick']),\n /** A click handler for the `Chip` icon after. */\n onIconAfterClick: PropTypes.func,\n /** Indicates if `Chip` has been selected. */\n isSelected: PropTypes.bool,\n};\n\nChip.defaultProps = {\n className: undefined,\n variant: STYLE_VARIANTS.LIGHT,\n disabled: false,\n onClick: undefined,\n iconBefore: undefined,\n iconAfter: undefined,\n onIconBeforeClick: undefined,\n onIconAfterClick: undefined,\n isSelected: false,\n iconAfterAlt: undefined,\n iconBeforeAlt: undefined,\n};\n\nexport default Chip;\n"],"mappings":"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","ignoreList":[]}
@@ -20,5 +20,5 @@ interface Props extends Omit<React.ComponentPropsWithRef<'a'>, 'href' | 'target'
20
20
  showLaunchIcon?: boolean;
21
21
  target?: '_blank' | '_self';
22
22
  }
23
- declare const Hyperlink: React.ForwardRefExoticComponent<Pick<Props, "variant" | "className" | "children" | "key" | "slot" | "style" | "title" | "onClick" | "tabIndex" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "spellCheck" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "download" | "hrefLang" | "media" | "ping" | "rel" | "target" | "type" | "referrerPolicy" | "destination" | "externalLinkAlternativeText" | "externalLinkTitle" | "isInline" | "showLaunchIcon"> & React.RefAttributes<HTMLAnchorElement>>;
23
+ declare const Hyperlink: React.ForwardRefExoticComponent<Omit<Props, "ref"> & React.RefAttributes<HTMLAnchorElement>>;
24
24
  export default Hyperlink;
@@ -1,13 +1,15 @@
1
1
  import React from 'react';
2
2
 
3
3
  export interface IconProps extends React.ComponentPropsWithoutRef<'span'> {
4
- src?: React.ReactElement | Function;
4
+ // Note: React.ComponentType is what we want here. React.ElementType would allow some element type strings like "div",
5
+ // but we only want to allow components like 'Add' (a specific icon component function/class)
6
+ src?: React.ComponentType;
5
7
  svgAttrs?: {
6
8
  'aria-label'?: string;
7
9
  'aria-labelledby'?: string;
8
10
  };
9
11
  id?: string | null;
10
- size?: 'xs' | 'sm' | 'md' | 'lg';
12
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'inline';
11
13
  className?: string | string[];
12
14
  hidden?: boolean;
13
15
  screenReaderText?: React.ReactNode;
@@ -61,7 +61,7 @@ Icon.propTypes = {
61
61
  * An icon component to render.
62
62
  * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';`
63
63
  */
64
- src: PropTypes.oneOfType([PropTypes.element, PropTypes.elementType]),
64
+ src: PropTypes.elementType,
65
65
  /** HTML element attributes to pass through to the underlying svg element */
66
66
  svgAttrs: PropTypes.shape({
67
67
  'aria-label': PropTypes.string,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["React","PropTypes","classNames","newId","withDeprecatedProps","DeprTypes","Icon","_ref","Component","src","id","className","hidden","screenReaderText","svgAttrs","size","attrs","_objectWithoutProperties","_excluded","hasAriaLabel","mergedSvgProps","_objectSpread","undefined","createElement","_extends","_defineProperty","concat","role","focusable","Fragment","propTypes","oneOfType","element","elementType","shape","string","oneOf","bool","defaultProps","deprType","FORMAT","expect","value","transform","Array","isArray","join","message"],"sources":["../../src/Icon/index.jsx"],"sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\nimport newId from '../utils/newId';\nimport withDeprecatedProps, { DeprTypes } from '../withDeprecatedProps';\n\n/**\n * An svg with an \"img\" role must satisfy the following a11y requirements\n * - It needs a text alternative in the form of aria-label, aria-labelledby, or screen-reader only text.\n * - If no label is desired, aria-label will be set to an empty string and aria-hidden to \"true\".\n * - focusable is set to false on the svg in all cases as a workaround for an ie11 bug\n */\n\nfunction Icon({\n src: Component,\n id,\n className,\n hidden,\n screenReaderText,\n svgAttrs,\n size,\n ...attrs\n}) {\n if (Component) {\n // If no aria label is specified, hide this icon from screenreaders\n const hasAriaLabel = svgAttrs['aria-label'] || svgAttrs['aria-labelledby'];\n\n const mergedSvgProps = { ...svgAttrs };\n\n if (!hasAriaLabel) {\n mergedSvgProps['aria-label'] = undefined;\n mergedSvgProps['aria-hidden'] = true;\n }\n\n return (\n <span\n className={classNames('pgn__icon', { [`pgn__icon__${size}`]: !!size }, className)}\n id={id}\n {...attrs}\n >\n <Component\n role=\"img\"\n focusable={false}\n {...mergedSvgProps}\n />\n {screenReaderText && (\n <span className=\"sr-only\">\n {screenReaderText}\n </span>\n )}\n </span>\n );\n }\n\n return (\n <>\n <span\n id={id || newId('Icon')}\n className={className}\n aria-hidden={hidden}\n />\n {screenReaderText && (\n <span className=\"sr-only\">\n {screenReaderText}\n </span>\n )}\n </>\n );\n}\n\nIcon.propTypes = {\n /**\n * An icon component to render.\n * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';`\n */\n src: PropTypes.oneOfType([PropTypes.element, PropTypes.elementType]),\n /** HTML element attributes to pass through to the underlying svg element */\n svgAttrs: PropTypes.shape({\n 'aria-label': PropTypes.string,\n 'aria-labelledby': PropTypes.string,\n }),\n /**\n * the `id` property of the Icon element, by default this value is generated\n * with the `newId` function with the `prefix` of `Icon`.\n */\n id: PropTypes.string,\n /** The size of the icon. */\n size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg']),\n /** A class name that will define what the Icon looks like. */\n className: PropTypes.string,\n /**\n * a boolean that determines the value of `aria-hidden` attribute on the Icon span,\n * this value is `true` by default.\n */\n hidden: PropTypes.bool,\n /**\n * a string or an element that will be used on a secondary span leveraging the `sr-only` style\n * for screenreader only text, this value is `undefined` by default. This value is recommended for use unless\n * the Icon is being used in a way that is purely decorative or provides no additional context for screen\n * reader users. This field should be thought of the same way an `alt` attribute would be used for `image` tags.\n */\n screenReaderText: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),\n};\n\nIcon.defaultProps = {\n src: null,\n svgAttrs: {},\n id: undefined,\n hidden: true,\n screenReaderText: undefined,\n size: undefined,\n className: undefined,\n};\n\nexport default withDeprecatedProps(Icon, 'Icon', {\n className: {\n deprType: DeprTypes.FORMAT,\n expect: value => typeof value === 'string',\n transform: value => (Array.isArray(value) ? value.join(' ') : value),\n message: 'It should be a string.',\n },\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["React","PropTypes","classNames","newId","withDeprecatedProps","DeprTypes","Icon","_ref","Component","src","id","className","hidden","screenReaderText","svgAttrs","size","attrs","_objectWithoutProperties","_excluded","hasAriaLabel","mergedSvgProps","_objectSpread","undefined","createElement","_extends","_defineProperty","concat","role","focusable","Fragment","propTypes","elementType","shape","string","oneOf","bool","oneOfType","element","defaultProps","deprType","FORMAT","expect","value","transform","Array","isArray","join","message"],"sources":["../../src/Icon/index.jsx"],"sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport classNames from 'classnames';\n\nimport newId from '../utils/newId';\nimport withDeprecatedProps, { DeprTypes } from '../withDeprecatedProps';\n\n/**\n * An svg with an \"img\" role must satisfy the following a11y requirements\n * - It needs a text alternative in the form of aria-label, aria-labelledby, or screen-reader only text.\n * - If no label is desired, aria-label will be set to an empty string and aria-hidden to \"true\".\n * - focusable is set to false on the svg in all cases as a workaround for an ie11 bug\n */\n\nfunction Icon({\n src: Component,\n id,\n className,\n hidden,\n screenReaderText,\n svgAttrs,\n size,\n ...attrs\n}) {\n if (Component) {\n // If no aria label is specified, hide this icon from screenreaders\n const hasAriaLabel = svgAttrs['aria-label'] || svgAttrs['aria-labelledby'];\n\n const mergedSvgProps = { ...svgAttrs };\n\n if (!hasAriaLabel) {\n mergedSvgProps['aria-label'] = undefined;\n mergedSvgProps['aria-hidden'] = true;\n }\n\n return (\n <span\n className={classNames('pgn__icon', { [`pgn__icon__${size}`]: !!size }, className)}\n id={id}\n {...attrs}\n >\n <Component\n role=\"img\"\n focusable={false}\n {...mergedSvgProps}\n />\n {screenReaderText && (\n <span className=\"sr-only\">\n {screenReaderText}\n </span>\n )}\n </span>\n );\n }\n\n return (\n <>\n <span\n id={id || newId('Icon')}\n className={className}\n aria-hidden={hidden}\n />\n {screenReaderText && (\n <span className=\"sr-only\">\n {screenReaderText}\n </span>\n )}\n </>\n );\n}\n\nIcon.propTypes = {\n /**\n * An icon component to render.\n * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';`\n */\n src: PropTypes.elementType,\n /** HTML element attributes to pass through to the underlying svg element */\n svgAttrs: PropTypes.shape({\n 'aria-label': PropTypes.string,\n 'aria-labelledby': PropTypes.string,\n }),\n /**\n * the `id` property of the Icon element, by default this value is generated\n * with the `newId` function with the `prefix` of `Icon`.\n */\n id: PropTypes.string,\n /** The size of the icon. */\n size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg']),\n /** A class name that will define what the Icon looks like. */\n className: PropTypes.string,\n /**\n * a boolean that determines the value of `aria-hidden` attribute on the Icon span,\n * this value is `true` by default.\n */\n hidden: PropTypes.bool,\n /**\n * a string or an element that will be used on a secondary span leveraging the `sr-only` style\n * for screenreader only text, this value is `undefined` by default. This value is recommended for use unless\n * the Icon is being used in a way that is purely decorative or provides no additional context for screen\n * reader users. This field should be thought of the same way an `alt` attribute would be used for `image` tags.\n */\n screenReaderText: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),\n};\n\nIcon.defaultProps = {\n src: null,\n svgAttrs: {},\n id: undefined,\n hidden: true,\n screenReaderText: undefined,\n size: undefined,\n className: undefined,\n};\n\nexport default withDeprecatedProps(Icon, 'Icon', {\n className: {\n deprType: DeprTypes.FORMAT,\n expect: value => typeof value === 'string',\n transform: value => (Array.isArray(value) ? value.join(' ') : value),\n message: 'It should be a string.',\n },\n});\n"],"mappings":"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","ignoreList":[]}
@@ -37,6 +37,12 @@ function ModalPopup(_ref) {
37
37
  }
38
38
  }
39
39
  }];
40
+ var handleOnClickOutside = function handleOnClickOutside(e) {
41
+ if (e.type === 'touchstart') {
42
+ return;
43
+ }
44
+ onClose();
45
+ };
40
46
  return /*#__PURE__*/React.createElement(ModalContextProvider, {
41
47
  onClose: onClose,
42
48
  isOpen: isOpen,
@@ -49,7 +55,7 @@ function ModalPopup(_ref) {
49
55
  scrollLock: false,
50
56
  enabled: isOpen,
51
57
  onEscapeKey: onClose,
52
- onClickOutside: onClose
58
+ onClickOutside: handleOnClickOutside
53
59
  }, isOpen && /*#__PURE__*/React.createElement("div", {
54
60
  className: "pgn__modal-popup__tooltip"
55
61
  }, children, hasArrow && /*#__PURE__*/React.createElement("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"ModalPopup.js","names":["React","PropTypes","FocusOn","Portal","PopperElement","ModalContextProvider","PLACEMENT_OFFSETS","right","left","ModalPopup","_ref","children","onClose","isOpen","positionRef","isBlocking","withPortal","placement","hasArrow","popperProps","_objectWithoutProperties","_excluded","RootComponent","Fragment","placementOffsetValue","popperParams","name","options","scroll","offset","createElement","_extends","modifiers","target","scrollLock","enabled","onEscapeKey","onClickOutside","className","id","concat","propTypes","node","isRequired","func","bool","oneOfType","shape","current","defaultProps"],"sources":["../../src/Modal/ModalPopup.jsx"],"sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { FocusOn } from 'react-focus-on';\nimport Portal from './Portal';\nimport PopperElement from './PopperElement';\nimport { ModalContextProvider } from './ModalContext';\n\nconst PLACEMENT_OFFSETS = { right: [-2, 10], left: [-2, 10] };\n\nfunction ModalPopup({\n children,\n onClose,\n isOpen,\n positionRef,\n isBlocking,\n withPortal,\n placement,\n hasArrow,\n ...popperProps\n}) {\n const RootComponent = withPortal ? Portal : React.Fragment;\n const placementOffsetValue = PLACEMENT_OFFSETS[placement] || [0, 10];\n\n const popperParams = [\n {\n name: 'eventListeners',\n options: { scroll: false },\n },\n {\n name: 'offset',\n options: {\n offset: () => placementOffsetValue,\n },\n },\n ];\n\n return (\n <ModalContextProvider onClose={onClose} isOpen={isOpen} isBlocking={isBlocking}>\n <RootComponent>\n <PopperElement\n modifiers={hasArrow ? popperParams : null}\n target={positionRef}\n placement={placement}\n {...popperProps}\n >\n <FocusOn\n scrollLock={false}\n enabled={isOpen}\n onEscapeKey={onClose}\n onClickOutside={onClose}\n >\n {isOpen && (\n <div className=\"pgn__modal-popup__tooltip\">\n {children}\n {hasArrow && (\n <div\n id=\"arrow\"\n data-testid=\"modal-popup-arrow\"\n className={`pgn__modal-popup__arrow pgn__modal-popup__arrow-${placement}`}\n data-popper-arrow=\"\"\n />\n )}\n </div>\n )}\n </FocusOn>\n </PopperElement>\n </RootComponent>\n </ModalContextProvider>\n );\n}\n\nModalPopup.propTypes = {\n /** Specifies the contents of the modal */\n children: PropTypes.node.isRequired,\n /** A callback function for when the modal is dismissed */\n onClose: PropTypes.func.isRequired,\n /** Is the modal dialog open or closed */\n isOpen: PropTypes.bool.isRequired,\n /** Prevent clicking on the backdrop or pressing Esc to close the modal */\n isBlocking: PropTypes.bool,\n /** Insert modal into a different location in the DOM */\n withPortal: PropTypes.bool,\n // This type: https://stackoverflow.com/questions/48007326/what-is-the-correct-proptype-for-a-ref-in-react\n /** Specifies an element near which the modal should be displayed */\n positionRef: PropTypes.oneOfType([\n PropTypes.func,\n PropTypes.shape({ current: PropTypes.shape({}) }),\n ]),\n /** Specifies position according to the element that the ``positionRef`` prop points to */\n placement: PopperElement.propTypes.placement,\n /** Caret to the modal popup pointing to the target */\n hasArrow: PropTypes.bool,\n};\n\nModalPopup.defaultProps = {\n isBlocking: false,\n withPortal: false,\n placement: 'bottom-start',\n positionRef: null,\n hasArrow: false,\n};\n\nexport default ModalPopup;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"ModalPopup.js","names":["React","PropTypes","FocusOn","Portal","PopperElement","ModalContextProvider","PLACEMENT_OFFSETS","right","left","ModalPopup","_ref","children","onClose","isOpen","positionRef","isBlocking","withPortal","placement","hasArrow","popperProps","_objectWithoutProperties","_excluded","RootComponent","Fragment","placementOffsetValue","popperParams","name","options","scroll","offset","handleOnClickOutside","e","type","createElement","_extends","modifiers","target","scrollLock","enabled","onEscapeKey","onClickOutside","className","id","concat","propTypes","node","isRequired","func","bool","oneOfType","shape","current","defaultProps"],"sources":["../../src/Modal/ModalPopup.jsx"],"sourcesContent":["import React from 'react';\nimport PropTypes from 'prop-types';\nimport { FocusOn } from 'react-focus-on';\nimport Portal from './Portal';\nimport PopperElement from './PopperElement';\nimport { ModalContextProvider } from './ModalContext';\n\nconst PLACEMENT_OFFSETS = { right: [-2, 10], left: [-2, 10] };\n\nfunction ModalPopup({\n children,\n onClose,\n isOpen,\n positionRef,\n isBlocking,\n withPortal,\n placement,\n hasArrow,\n ...popperProps\n}) {\n const RootComponent = withPortal ? Portal : React.Fragment;\n const placementOffsetValue = PLACEMENT_OFFSETS[placement] || [0, 10];\n\n const popperParams = [\n {\n name: 'eventListeners',\n options: { scroll: false },\n },\n {\n name: 'offset',\n options: {\n offset: () => placementOffsetValue,\n },\n },\n ];\n\n const handleOnClickOutside = (e) => {\n if (e.type === 'touchstart') {\n return;\n }\n\n onClose();\n };\n\n return (\n <ModalContextProvider onClose={onClose} isOpen={isOpen} isBlocking={isBlocking}>\n <RootComponent>\n <PopperElement\n modifiers={hasArrow ? popperParams : null}\n target={positionRef}\n placement={placement}\n {...popperProps}\n >\n <FocusOn\n scrollLock={false}\n enabled={isOpen}\n onEscapeKey={onClose}\n onClickOutside={handleOnClickOutside}\n >\n {isOpen && (\n <div className=\"pgn__modal-popup__tooltip\">\n {children}\n {hasArrow && (\n <div\n id=\"arrow\"\n data-testid=\"modal-popup-arrow\"\n className={`pgn__modal-popup__arrow pgn__modal-popup__arrow-${placement}`}\n data-popper-arrow=\"\"\n />\n )}\n </div>\n )}\n </FocusOn>\n </PopperElement>\n </RootComponent>\n </ModalContextProvider>\n );\n}\n\nModalPopup.propTypes = {\n /** Specifies the contents of the modal */\n children: PropTypes.node.isRequired,\n /** A callback function for when the modal is dismissed */\n onClose: PropTypes.func.isRequired,\n /** Is the modal dialog open or closed */\n isOpen: PropTypes.bool.isRequired,\n /** Prevent clicking on the backdrop or pressing Esc to close the modal */\n isBlocking: PropTypes.bool,\n /** Insert modal into a different location in the DOM */\n withPortal: PropTypes.bool,\n // This type: https://stackoverflow.com/questions/48007326/what-is-the-correct-proptype-for-a-ref-in-react\n /** Specifies an element near which the modal should be displayed */\n positionRef: PropTypes.oneOfType([\n PropTypes.func,\n PropTypes.shape({ current: PropTypes.shape({}) }),\n ]),\n /** Specifies position according to the element that the ``positionRef`` prop points to */\n placement: PopperElement.propTypes.placement,\n /** Caret to the modal popup pointing to the target */\n hasArrow: PropTypes.bool,\n};\n\nModalPopup.defaultProps = {\n isBlocking: false,\n withPortal: false,\n placement: 'bottom-start',\n positionRef: null,\n hasArrow: false,\n};\n\nexport default ModalPopup;\n"],"mappings":"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","ignoreList":[]}
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  // Things that have types
6
6
  // // // // // // // // // // // // // // // // // // // // // // // // // // //
7
7
  export { default as Bubble } from './Bubble';
8
+ export { default as Button, ButtonGroup, ButtonToolbar } from './Button';
8
9
  export { default as Chip, CHIP_PGN_CLASS } from './Chip';
9
10
  export { default as ChipCarousel } from './ChipCarousel';
10
11
  export { default as Hyperlink, HYPER_LINK_EXTERNAL_LINK_ALT_TEXT, HYPER_LINK_EXTERNAL_LINK_TITLE } from './Hyperlink';
@@ -21,7 +22,6 @@ export const Avatar: any; // from './Avatar';
21
22
  export const AvatarButton: any; // from './AvatarButton';
22
23
  export const Badge: any; // from './Badge';
23
24
  export const Breadcrumb: any; // from './Breadcrumb';
24
- export const Button: any, ButtonGroup: any, ButtonToolbar: any; // from './Button';
25
25
  export const
26
26
  Card: any,
27
27
  CardColumns: any,
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
- // To keep this file in sync with the .d.ts file, it's in the same order
2
- // and each line number is the same
1
+ // Keep this file in sync with the .d.ts file (manually). It's in the same order
2
+ // and each line number is the same, to make it easier.
3
3
 
4
4
  // // // // // // // // // // // // // // // // // // // // // // // // // // //
5
5
  // Things that have types
6
6
  // // // // // // // // // // // // // // // // // // // // // // // // // // //
7
7
  export { default as Bubble } from './Bubble';
8
+ export { default as Button, ButtonGroup, ButtonToolbar } from './Button';
8
9
  export { default as Chip, CHIP_PGN_CLASS } from './Chip';
9
10
  export { default as ChipCarousel } from './ChipCarousel';
10
11
  export { default as Hyperlink, HYPER_LINK_EXTERNAL_LINK_ALT_TEXT, HYPER_LINK_EXTERNAL_LINK_TITLE } from './Hyperlink';
@@ -21,7 +22,6 @@ export { default as Avatar } from './Avatar';
21
22
  export { default as AvatarButton } from './AvatarButton';
22
23
  export { default as Badge } from './Badge';
23
24
  export { default as Breadcrumb } from './Breadcrumb';
24
- export { default as Button, ButtonGroup, ButtonToolbar } from './Button';
25
25
  export {
26
26
  default as Card,
27
27
  CardColumns,
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Types related to bootstrap components
3
+ */
4
+ import React from 'react';
5
+ import type { BsPrefixProps, BsPrefixRefForwardingComponent } from 'react-bootstrap/esm/helpers';
6
+ /**
7
+ * Type helper for defining props of a component that wraps a bootstrap
8
+ * component. This type defines three props:
9
+ * 1. `className`: this component accepts additional CSS classes.
10
+ * 2. `bsPrefix`: locally change the class name prefix used for this component.
11
+ * 3. `as`: optionally specify which HTML element or Component is used, e.g. `"div"`
12
+ *
13
+ * This type assumes no `children` are allowed, but you can extend it to allow children.
14
+ */
15
+ export type BsPropsWithAs<As extends React.ElementType = React.ElementType> = BsPrefixProps<As>;
16
+ /**
17
+ * This is a helper that can be used to define the type of a Paragon component
18
+ * that accepts an `as` prop.
19
+ *
20
+ * It:
21
+ * - assumes you are using `forwardRef`, and sets the type of the `ref` prop
22
+ * to match the type of the component passed in the `as` prop.
23
+ * - assumes you are passing all unused props to the component, so adds any
24
+ * props from the `as` component type to the props you specify as `Props`.
25
+ *
26
+ * Example;
27
+ * ```
28
+ * interface MyProps extends BsPropsWithAs {
29
+ * customProp?: string;
30
+ * }
31
+ * export const MyComponent: ComponentWithAsProp<'div', MyProps> = (
32
+ * React.forwardRef<HTMLDivElement, MyProps>(
33
+ * ({ as: Inner = 'div', ...props }, ref) => <Inner {...props} ref={ref} />,
34
+ * )
35
+ * );
36
+ * ```
37
+ * Note that you need to define the default (e.g. `'div'`) in three different places.
38
+ */
39
+ export type ComponentWithAsProp<DefaultElementType extends React.ElementType, Props> = BsPrefixRefForwardingComponent<DefaultElementType, Props>;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","names":[],"sources":["../../../src/utils/types/bootstrap.ts"],"sourcesContent":["/**\n * Types related to bootstrap components\n */\nimport React from 'react';\n\nimport type { BsPrefixProps, BsPrefixRefForwardingComponent } from 'react-bootstrap/esm/helpers';\n\n/**\n * Type helper for defining props of a component that wraps a bootstrap\n * component. This type defines three props:\n * 1. `className`: this component accepts additional CSS classes.\n * 2. `bsPrefix`: locally change the class name prefix used for this component.\n * 3. `as`: optionally specify which HTML element or Component is used, e.g. `\"div\"`\n *\n * This type assumes no `children` are allowed, but you can extend it to allow children.\n */\nexport type BsPropsWithAs<As extends React.ElementType = React.ElementType> = BsPrefixProps<As>;\n\n/**\n * This is a helper that can be used to define the type of a Paragon component\n * that accepts an `as` prop.\n *\n * It:\n * - assumes you are using `forwardRef`, and sets the type of the `ref` prop\n * to match the type of the component passed in the `as` prop.\n * - assumes you are passing all unused props to the component, so adds any\n * props from the `as` component type to the props you specify as `Props`.\n *\n * Example;\n * ```\n * interface MyProps extends BsPropsWithAs {\n * customProp?: string;\n * }\n * export const MyComponent: ComponentWithAsProp<'div', MyProps> = (\n * React.forwardRef<HTMLDivElement, MyProps>(\n * ({ as: Inner = 'div', ...props }, ref) => <Inner {...props} ref={ref} />,\n * )\n * );\n * ```\n * Note that you need to define the default (e.g. `'div'`) in three different places.\n */\nexport type ComponentWithAsProp<DefaultElementType extends React.ElementType, Props>\n = BsPrefixRefForwardingComponent<DefaultElementType, Props>;\n"],"mappings":"","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openedx/paragon",
3
- "version": "22.5.1",
3
+ "version": "22.6.1",
4
4
  "description": "Accessible, responsive UI component library based on Bootstrap.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -106,8 +106,8 @@
106
106
  "@testing-library/react-hooks": "^8.0.1",
107
107
  "@testing-library/user-event": "^13.5.0",
108
108
  "@types/jest": "^29.5.10",
109
- "@types/react": "17.0.0",
110
- "@types/react-dom": "17.0.11",
109
+ "@types/react": "^17.0.80",
110
+ "@types/react-dom": "^17.0.11",
111
111
  "@types/react-responsive": "^8.0.8",
112
112
  "@types/react-table": "^7.7.19",
113
113
  "@types/react-test-renderer": "^18.0.0",
@@ -30,7 +30,7 @@ describe('<Button />', () => {
30
30
 
31
31
  it('renders with props iconAfter and size', () => {
32
32
  const tree = renderer.create((
33
- <Button iconAfter={Close} size="md">Button</Button>
33
+ <Button iconAfter={Close} size="sm">Button</Button>
34
34
  )).toJSON();
35
35
  expect(tree).toMatchSnapshot();
36
36
  });
@@ -94,9 +94,21 @@ describe('<Button />', () => {
94
94
  });
95
95
 
96
96
  test('test button as hyperlink', () => {
97
- render(<Button as={Hyperlink} destination="https://www.poop.com/💩">Button</Button>);
97
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
98
+ const ref = (_current: HTMLAnchorElement) => {}; // Check typing of a ref - should not show type errors.
99
+ render(<Button as={Hyperlink} ref={ref} destination="https://www.poop.com/💩">Button</Button>);
98
100
  expect(screen.getByRole('link').getAttribute('href')).toEqual('https://www.poop.com/💩');
99
101
  });
100
102
  });
103
+
104
+ test('with size="inline"', () => {
105
+ const tree = renderer.create((
106
+ <p>
107
+ <span className="mr-1">2 items selected.</span>
108
+ <Button variant="link" size="inline">Clear</Button>
109
+ </p>
110
+ )).toJSON();
111
+ expect(tree).toMatchSnapshot();
112
+ });
101
113
  });
102
114
  });
@@ -55,13 +55,13 @@ exports[`<Button /> correct rendering renders with props iconAfter 1`] = `
55
55
 
56
56
  exports[`<Button /> correct rendering renders with props iconAfter and size 1`] = `
57
57
  <button
58
- className="btn btn-primary btn-md"
58
+ className="btn btn-primary btn-sm"
59
59
  disabled={false}
60
60
  type="button"
61
61
  >
62
62
  Button
63
63
  <span
64
- className="pgn__icon pgn__icon__md btn-icon-after"
64
+ className="pgn__icon pgn__icon__sm btn-icon-after"
65
65
  >
66
66
  <svg
67
67
  aria-hidden={true}
@@ -197,3 +197,20 @@ exports[`<Button /> correct rendering renders without props 1`] = `
197
197
  Button
198
198
  </button>
199
199
  `;
200
+
201
+ exports[`<Button /> correct rendering with size="inline" 1`] = `
202
+ <p>
203
+ <span
204
+ className="mr-1"
205
+ >
206
+ 2 items selected.
207
+ </span>
208
+ <button
209
+ className="btn btn-link btn-inline"
210
+ disabled={false}
211
+ type="button"
212
+ >
213
+ Clear
214
+ </button>
215
+ </p>
216
+ `;
@@ -1,32 +1,57 @@
1
1
  import React from 'react';
2
- import PropTypes from 'prop-types';
2
+ import PropTypes, { type Requireable } from 'prop-types';
3
3
  import classNames from 'classnames';
4
- import BaseButton from 'react-bootstrap/Button';
5
- import BaseButtonGroup from 'react-bootstrap/ButtonGroup';
6
- import BaseButtonToolbar from 'react-bootstrap/ButtonToolbar';
4
+ import BaseButton, { type ButtonProps as BaseButtonProps } from 'react-bootstrap/Button';
5
+ import BaseButtonGroup, { type ButtonGroupProps as BaseButtonGroupProps } from 'react-bootstrap/ButtonGroup';
6
+ import BaseButtonToolbar, { type ButtonToolbarProps } from 'react-bootstrap/ButtonToolbar';
7
+ import type { ComponentWithAsProp } from '../utils/types/bootstrap';
8
+ // @ts-ignore - we're not going to bother adding types for the deprecated button
7
9
  import ButtonDeprecated from './deprecated';
8
10
 
9
11
  import Icon from '../Icon';
10
12
 
11
- const Button = React.forwardRef(({
13
+ interface ButtonProps extends Omit<BaseButtonProps, 'size'> {
14
+ /**
15
+ * An icon component to render. Example:
16
+ * ```
17
+ * import { Close } from '@openedx/paragon/icons';
18
+ * <Button iconBefore={Close}>Close</Button>
19
+ * ```
20
+ */
21
+ iconBefore?: React.ComponentType;
22
+ /**
23
+ * An icon component to render. Example:
24
+ * ```
25
+ * import { Close } from '@openedx/paragon/icons';
26
+ * <Button iconAfter={Close}>Close</Button>
27
+ * ```
28
+ */
29
+ iconAfter?: React.ComponentType;
30
+ size?: 'sm' | 'md' | 'lg' | 'inline';
31
+ }
32
+
33
+ type ButtonType = ComponentWithAsProp<'button', ButtonProps> & { Deprecated?: any };
34
+
35
+ const Button: ButtonType = React.forwardRef<HTMLButtonElement, ButtonProps>(({
12
36
  children,
13
37
  iconAfter,
14
38
  iconBefore,
39
+ size,
15
40
  ...props
16
41
  }, ref) => (
17
42
  <BaseButton
43
+ size={size as 'sm' | 'lg' | undefined} // Bootstrap's <Button> types do not allow 'md' or 'inline', but we do.
18
44
  {...props}
19
45
  className={classNames(props.className)}
20
46
  ref={ref}
21
47
  >
22
- {iconBefore && <Icon className="btn-icon-before" size={props.size} src={iconBefore} />}
48
+ {iconBefore && <Icon className="btn-icon-before" size={size} src={iconBefore} />}
23
49
  {children}
24
- {iconAfter && <Icon className="btn-icon-after" size={props.size} src={iconAfter} />}
50
+ {iconAfter && <Icon className="btn-icon-after" size={size} src={iconAfter} />}
25
51
  </BaseButton>
26
52
  ));
27
53
 
28
54
  Button.propTypes = {
29
- ...Button.propTypes,
30
55
  /** Specifies class name to apply to the button */
31
56
  className: PropTypes.string,
32
57
  /** Disables the Button, preventing mouse events, even if the underlying component is an `<a>` element */
@@ -52,10 +77,13 @@ Button.propTypes = {
52
77
  variant: PropTypes.string,
53
78
  /** An icon component to render.
54
79
  * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` */
55
- iconBefore: PropTypes.oneOfType([PropTypes.elementType, PropTypes.node]),
80
+ iconBefore: PropTypes.elementType as Requireable<React.ComponentType>,
56
81
  /** An icon component to render.
57
82
  * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` */
58
- iconAfter: PropTypes.oneOfType([PropTypes.elementType, PropTypes.node]),
83
+ iconAfter: PropTypes.elementType as Requireable<React.ComponentType>,
84
+ // The 'as' type casting above is required for TypeScript checking, because the 'PropTypes.elementType' type normally
85
+ // allows strings as a value (for use cases like 'div') but we don't support that for <Icon />/iconBefore/iconAfter.
86
+ // The React TypeScript type definitions are more specific (React.ComponentType vs React.ElementType).
59
87
  };
60
88
 
61
89
  Button.defaultProps = {
@@ -69,20 +97,29 @@ Button.defaultProps = {
69
97
 
70
98
  Button.Deprecated = ButtonDeprecated;
71
99
 
72
- function ButtonGroup(props) {
73
- return <BaseButtonGroup {...props} />;
74
- }
75
- function ButtonToolbar(props) {
76
- return <BaseButtonToolbar {...props} />;
100
+ // We could just re-export 'ButtonGroup' and 'ButtonToolbar', but we currently
101
+ // override them to add propTypes validation at runtime, since most Paragon
102
+ // consumers aren't using TypeScript yet. We also force ButtonGroup's 'size'
103
+ // prop to accept our custom values of 'md' and 'inline' which are used in
104
+ // Paragon but not used in the base Bootstrap classes.
105
+
106
+ interface ButtonGroupProps extends Omit<BaseButtonGroupProps, 'size'> {
107
+ size?: 'sm' | 'md' | 'lg' | 'inline';
77
108
  }
78
109
 
110
+ const ButtonGroup: ComponentWithAsProp<'div', ButtonGroupProps> = (
111
+ React.forwardRef<HTMLButtonElement, ButtonGroupProps>(({ size, ...props }, ref) => (
112
+ <BaseButtonGroup size={size as 'sm' | 'lg'} {...props} ref={ref} />
113
+ ))
114
+ );
115
+
79
116
  ButtonGroup.propTypes = {
80
117
  /** Specifies element type for this component. */
81
118
  as: PropTypes.elementType,
82
119
  /** An ARIA role describing the button group. */
83
120
  role: PropTypes.string,
84
121
  /** Specifies the size for all Buttons in the group. */
85
- size: PropTypes.oneOf(['sm', 'md', 'lg']),
122
+ size: PropTypes.oneOf(['sm', 'md', 'lg', 'inline']),
86
123
  /** Display as a button toggle group. */
87
124
  toggle: PropTypes.bool,
88
125
  /** Specifies if the set of Buttons should appear vertically stacked. */
@@ -100,6 +137,12 @@ ButtonGroup.defaultProps = {
100
137
  size: 'md',
101
138
  };
102
139
 
140
+ const ButtonToolbar: ComponentWithAsProp<'div', ButtonToolbarProps> = (
141
+ React.forwardRef<HTMLButtonElement, ButtonToolbarProps>((props, ref) => (
142
+ <BaseButtonToolbar {...props} ref={ref} />
143
+ ))
144
+ );
145
+
103
146
  ButtonToolbar.propTypes = {
104
147
  /** An ARIA role describing the button group. */
105
148
  role: PropTypes.string,
@@ -8,7 +8,7 @@ import { STYLE_VARIANTS } from './constants';
8
8
 
9
9
  export interface ChipIconProps {
10
10
  className: string,
11
- src: React.ReactElement | Function,
11
+ src: React.ComponentType,
12
12
  onClick?: KeyboardEventHandler & MouseEventHandler,
13
13
  alt?: string,
14
14
  variant: string,
@@ -1,5 +1,5 @@
1
1
  import React, { ForwardedRef, KeyboardEventHandler, MouseEventHandler } from 'react';
2
- import PropTypes from 'prop-types';
2
+ import PropTypes, { type Requireable } from 'prop-types';
3
3
  import classNames from 'classnames';
4
4
  // @ts-ignore
5
5
  import { requiredWhen } from '../utils/propTypes';
@@ -15,9 +15,9 @@ export interface IChip {
15
15
  onClick?: KeyboardEventHandler & MouseEventHandler,
16
16
  className?: string,
17
17
  variant?: string,
18
- iconBefore?: React.ReactElement | Function,
18
+ iconBefore?: React.ComponentType,
19
19
  iconBeforeAlt?: string,
20
- iconAfter?: React.ReactElement | Function,
20
+ iconAfter?: React.ComponentType,
21
21
  iconAfterAlt?: string,
22
22
  onIconBeforeClick?: KeyboardEventHandler & MouseEventHandler,
23
23
  onIconAfterClick?: KeyboardEventHandler & MouseEventHandler,
@@ -111,7 +111,7 @@ Chip.propTypes = {
111
111
  *
112
112
  * `import { Check } from '@openedx/paragon/icons';`
113
113
  */
114
- iconBefore: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
114
+ iconBefore: PropTypes.elementType as Requireable<React.ComponentType>,
115
115
  /** Specifies icon alt text. */
116
116
  iconBeforeAlt: requiredWhen(PropTypes.string, ['iconBefore', 'onIconBeforeClick']),
117
117
  /** A click handler for the `Chip` icon before. */
@@ -122,7 +122,7 @@ Chip.propTypes = {
122
122
  *
123
123
  * `import { Check } from '@openedx/paragon/icons';`
124
124
  */
125
- iconAfter: PropTypes.oneOfType([PropTypes.element, PropTypes.func]),
125
+ iconAfter: PropTypes.elementType as Requireable<React.ComponentType>,
126
126
  /** Specifies icon alt text. */
127
127
  iconAfterAlt: requiredWhen(PropTypes.string, ['iconAfter', 'onIconAfterClick']),
128
128
  /** A click handler for the `Chip` icon after. */
@@ -1,13 +1,15 @@
1
1
  import React from 'react';
2
2
 
3
3
  export interface IconProps extends React.ComponentPropsWithoutRef<'span'> {
4
- src?: React.ReactElement | Function;
4
+ // Note: React.ComponentType is what we want here. React.ElementType would allow some element type strings like "div",
5
+ // but we only want to allow components like 'Add' (a specific icon component function/class)
6
+ src?: React.ComponentType;
5
7
  svgAttrs?: {
6
8
  'aria-label'?: string;
7
9
  'aria-labelledby'?: string;
8
10
  };
9
11
  id?: string | null;
10
- size?: 'xs' | 'sm' | 'md' | 'lg';
12
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'inline';
11
13
  className?: string | string[];
12
14
  hidden?: boolean;
13
15
  screenReaderText?: React.ReactNode;
@@ -74,7 +74,7 @@ Icon.propTypes = {
74
74
  * An icon component to render.
75
75
  * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';`
76
76
  */
77
- src: PropTypes.oneOfType([PropTypes.element, PropTypes.elementType]),
77
+ src: PropTypes.elementType,
78
78
  /** HTML element attributes to pass through to the underlying svg element */
79
79
  svgAttrs: PropTypes.shape({
80
80
  'aria-label': PropTypes.string,
@@ -34,6 +34,14 @@ function ModalPopup({
34
34
  },
35
35
  ];
36
36
 
37
+ const handleOnClickOutside = (e) => {
38
+ if (e.type === 'touchstart') {
39
+ return;
40
+ }
41
+
42
+ onClose();
43
+ };
44
+
37
45
  return (
38
46
  <ModalContextProvider onClose={onClose} isOpen={isOpen} isBlocking={isBlocking}>
39
47
  <RootComponent>
@@ -47,7 +55,7 @@ function ModalPopup({
47
55
  scrollLock={false}
48
56
  enabled={isOpen}
49
57
  onEscapeKey={onClose}
50
- onClickOutside={onClose}
58
+ onClickOutside={handleOnClickOutside}
51
59
  >
52
60
  {isOpen && (
53
61
  <div className="pgn__modal-popup__tooltip">
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { fireEvent, render } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import ModalPopup from '../ModalPopup';
5
+
6
+ describe('<ModalPopup />', () => {
7
+ const mockPositionRef = React.createRef();
8
+
9
+ describe('when isOpen', () => {
10
+ const isOpen = true;
11
+ const closeFn = jest.fn();
12
+
13
+ it('calls close on click events but not touchstart events', async () => {
14
+ render(
15
+ <ModalPopup
16
+ positionRef={mockPositionRef}
17
+ isOpen={isOpen}
18
+ onClose={closeFn}
19
+ >
20
+ <div>Modal Contents</div>
21
+ </ModalPopup>,
22
+ );
23
+ await fireEvent.touchStart(document.body);
24
+ expect(closeFn).not.toHaveBeenCalled();
25
+ await userEvent.click(document.body);
26
+ expect(closeFn).toHaveBeenCalled();
27
+ });
28
+ });
29
+ });
package/src/index.d.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  // Things that have types
6
6
  // // // // // // // // // // // // // // // // // // // // // // // // // // //
7
7
  export { default as Bubble } from './Bubble';
8
+ export { default as Button, ButtonGroup, ButtonToolbar } from './Button';
8
9
  export { default as Chip, CHIP_PGN_CLASS } from './Chip';
9
10
  export { default as ChipCarousel } from './ChipCarousel';
10
11
  export { default as Hyperlink, HYPER_LINK_EXTERNAL_LINK_ALT_TEXT, HYPER_LINK_EXTERNAL_LINK_TITLE } from './Hyperlink';
@@ -21,7 +22,6 @@ export const Avatar: any; // from './Avatar';
21
22
  export const AvatarButton: any; // from './AvatarButton';
22
23
  export const Badge: any; // from './Badge';
23
24
  export const Breadcrumb: any; // from './Breadcrumb';
24
- export const Button: any, ButtonGroup: any, ButtonToolbar: any; // from './Button';
25
25
  export const
26
26
  Card: any,
27
27
  CardColumns: any,
package/src/index.js CHANGED
@@ -1,10 +1,11 @@
1
- // To keep this file in sync with the .d.ts file, it's in the same order
2
- // and each line number is the same
1
+ // Keep this file in sync with the .d.ts file (manually). It's in the same order
2
+ // and each line number is the same, to make it easier.
3
3
 
4
4
  // // // // // // // // // // // // // // // // // // // // // // // // // // //
5
5
  // Things that have types
6
6
  // // // // // // // // // // // // // // // // // // // // // // // // // // //
7
7
  export { default as Bubble } from './Bubble';
8
+ export { default as Button, ButtonGroup, ButtonToolbar } from './Button';
8
9
  export { default as Chip, CHIP_PGN_CLASS } from './Chip';
9
10
  export { default as ChipCarousel } from './ChipCarousel';
10
11
  export { default as Hyperlink, HYPER_LINK_EXTERNAL_LINK_ALT_TEXT, HYPER_LINK_EXTERNAL_LINK_TITLE } from './Hyperlink';
@@ -21,7 +22,6 @@ export { default as Avatar } from './Avatar';
21
22
  export { default as AvatarButton } from './AvatarButton';
22
23
  export { default as Badge } from './Badge';
23
24
  export { default as Breadcrumb } from './Breadcrumb';
24
- export { default as Button, ButtonGroup, ButtonToolbar } from './Button';
25
25
  export {
26
26
  default as Card,
27
27
  CardColumns,
@@ -0,0 +1,86 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import React from 'react';
3
+ import type { BsPropsWithAs, ComponentWithAsProp } from './bootstrap';
4
+
5
+ // Note: these are type-only tests. They don't actually do much at runtime; the important checks are at transpile time.
6
+
7
+ describe('BsPropsWithAs', () => {
8
+ interface Props<As extends React.ElementType = 'table'> extends BsPropsWithAs<As> {
9
+ otherProp?: number;
10
+ }
11
+
12
+ it('defines optional bsPrefix, className, and as but no other props', () => {
13
+ const checkProps = <As extends React.ElementType = 'table'>(_props: Props<As>) => {};
14
+ // These are all valid props per the prop definition:
15
+ checkProps({ });
16
+ checkProps({ bsPrefix: 'bs' });
17
+ checkProps({ className: 'foo bar' });
18
+ checkProps({ as: 'tr' });
19
+ checkProps({ className: 'foo bar', as: 'button', otherProp: 15 });
20
+ // But these are all invalid:
21
+ // @ts-expect-error
22
+ checkProps({ newProp: 10 });
23
+ // @ts-expect-error
24
+ checkProps({ onClick: () => {} });
25
+ // @ts-expect-error
26
+ checkProps({ id: 'id' });
27
+ // @ts-expect-error
28
+ checkProps({ children: <tr /> });
29
+ });
30
+ });
31
+
32
+ describe('ComponentWithAsProp', () => {
33
+ interface MyProps extends BsPropsWithAs {
34
+ customProp?: string;
35
+ }
36
+ const MyComponent: ComponentWithAsProp<'div', MyProps> = (
37
+ React.forwardRef<HTMLDivElement, MyProps>(
38
+ ({ as: Inner = 'div', ...props }, ref) => <Inner {...props} ref={ref} />,
39
+ )
40
+ );
41
+
42
+ // eslint-disable-next-line react/function-component-definition
43
+ const CustomComponent: React.FC<{ requiredProp: string }> = () => <span />;
44
+
45
+ it('is defined to wrap a <div> by default, and accepts related props', () => {
46
+ // This is valid - by default it is a DIV so accepts props and ref related to DIV:
47
+ const divClick: React.MouseEventHandler<HTMLDivElement> = () => {};
48
+ const divRef: React.RefObject<HTMLDivElement> = { current: null };
49
+ const valid = <MyComponent ref={divRef} onClick={divClick} customProp="foo" />;
50
+ });
51
+
52
+ it('is defined to wrap a <div> by default, and rejects unrelated props', () => {
53
+ const btnRef: React.RefObject<HTMLButtonElement> = { current: null };
54
+ // @ts-expect-error because the ref is to a <button> ref, but this is wrapping a <div>
55
+ const invalidRef = <MyComponent ref={btnRef} customProp="foo" />;
56
+
57
+ const btnClick: React.MouseEventHandler<HTMLButtonElement> = () => {};
58
+ // @ts-expect-error because the handler is for a <button> event, but this is wrapping a <div>
59
+ const invalidClick = <MyComponent onClick={btnClick} />;
60
+ });
61
+
62
+ it('can be changed to wrap a <canvas>, and accepts related props', () => {
63
+ const canvasClick: React.MouseEventHandler<HTMLCanvasElement> = () => {};
64
+ const canvasRef: React.RefObject<HTMLCanvasElement> = { current: null };
65
+ const valid = <MyComponent as="canvas" ref={canvasRef} onClick={canvasClick} customProp="foo" />;
66
+ });
67
+
68
+ it('can be changed to wrap a <canvas>, and rejects unrelated props', () => {
69
+ const btnRef: React.RefObject<HTMLButtonElement> = { current: null };
70
+ // @ts-expect-error because the ref is to a <button> ref, but this is wrapping an <canvas>
71
+ const invalidRef = <MyComponent as="canvas" ref={btnRef} customProp="foo" />;
72
+
73
+ const btnClick: React.MouseEventHandler<HTMLButtonElement> = () => {};
74
+ // @ts-expect-error because the handler is for a <button> event, but this is wrapping an <canvas>
75
+ const invalidClick = <MyComponent as="canvas" onClick={btnClick} />;
76
+ });
77
+
78
+ it('can be changed to wrap a custom component, and accepts related props', () => {
79
+ const valid = <MyComponent as={CustomComponent} requiredProp="hello" />;
80
+ });
81
+
82
+ it('can be changed to wrap a custom component, and rejects unrelated props', () => {
83
+ // @ts-expect-error The onClick prop has not been declared for our custom component.
84
+ const valid = <MyComponent as={CustomComponent} requiredProp="hello" onClick={() => {}} />;
85
+ });
86
+ });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Types related to bootstrap components
3
+ */
4
+ import React from 'react';
5
+
6
+ import type { BsPrefixProps, BsPrefixRefForwardingComponent } from 'react-bootstrap/esm/helpers';
7
+
8
+ /**
9
+ * Type helper for defining props of a component that wraps a bootstrap
10
+ * component. This type defines three props:
11
+ * 1. `className`: this component accepts additional CSS classes.
12
+ * 2. `bsPrefix`: locally change the class name prefix used for this component.
13
+ * 3. `as`: optionally specify which HTML element or Component is used, e.g. `"div"`
14
+ *
15
+ * This type assumes no `children` are allowed, but you can extend it to allow children.
16
+ */
17
+ export type BsPropsWithAs<As extends React.ElementType = React.ElementType> = BsPrefixProps<As>;
18
+
19
+ /**
20
+ * This is a helper that can be used to define the type of a Paragon component
21
+ * that accepts an `as` prop.
22
+ *
23
+ * It:
24
+ * - assumes you are using `forwardRef`, and sets the type of the `ref` prop
25
+ * to match the type of the component passed in the `as` prop.
26
+ * - assumes you are passing all unused props to the component, so adds any
27
+ * props from the `as` component type to the props you specify as `Props`.
28
+ *
29
+ * Example;
30
+ * ```
31
+ * interface MyProps extends BsPropsWithAs {
32
+ * customProp?: string;
33
+ * }
34
+ * export const MyComponent: ComponentWithAsProp<'div', MyProps> = (
35
+ * React.forwardRef<HTMLDivElement, MyProps>(
36
+ * ({ as: Inner = 'div', ...props }, ref) => <Inner {...props} ref={ref} />,
37
+ * )
38
+ * );
39
+ * ```
40
+ * Note that you need to define the default (e.g. `'div'`) in three different places.
41
+ */
42
+ export type ComponentWithAsProp<DefaultElementType extends React.ElementType, Props>
43
+ = BsPrefixRefForwardingComponent<DefaultElementType, Props>;