From a44af13f3a531c3bfe1578499190d1e49f9339bf Mon Sep 17 00:00:00 2001 From: Haider Alshamma Date: Fri, 6 Sep 2024 17:04:45 -0400 Subject: [PATCH 1/5] fix: remove defaultProps and PropTypes --- src/BrandedNavBar/isValidMenuItem.ts | 21 +-- src/Branding/BrandingText.tsx | 36 ++--- src/Branding/LettermarkLogo.tsx | 39 ++--- src/Branding/WordmarkLogo.tsx | 62 ++++---- src/Breadcrumbs/Breadcrumbs.tsx | 8 +- src/ButtonGroup/ButtonGroup.tsx | 10 +- src/Card/Card.tsx | 30 ++-- src/Checkbox/Checkbox.tsx | 21 +-- src/Checkbox/CheckboxGroup.tsx | 66 ++++---- src/DatePicker/DatePickerHeader.tsx | 18 +-- src/DropdownMenu/DropdownButton.tsx | 8 +- src/DropdownMenu/DropdownItem.tsx | 16 +- src/DropdownMenu/DropdownLink.tsx | 27 ++-- src/FieldLabel/FieldLabel.tsx | 51 ++++--- src/FieldLabel/Label.tsx | 7 +- src/Form/FormSection.tsx | 20 ++- src/Icon/Icon.tsx | 53 +++---- src/Input/Suffix.tsx | 15 +- src/Link/Link.tsx | 8 +- src/List/List.tsx | 29 ++-- src/List/ListItem.tsx | 17 +-- src/LoadingAnimation/LoadingAnimation.tsx | 13 +- src/Modal/Modal.tsx | 31 +--- src/NavBar/DesktopMenu.tsx | 5 - src/NavBar/MenuTrigger.tsx | 60 +++----- src/Overlay/Overlay.tsx | 29 ++-- src/Pagination/NextButton.tsx | 13 -- src/Pagination/Pagination.tsx | 29 +--- src/Pagination/PreviousButton.tsx | 15 +- src/Popper/Popper.tsx | 44 +++--- src/Radio/Radio.tsx | 18 +-- src/Radio/RadioGroup.tsx | 75 ++++----- src/RangeContainer/RangeContainer.tsx | 20 +-- src/Select/Select.tsx | 55 ++----- src/StatusIndicator/StatusIndicator.tsx | 44 +++--- src/Table/BaseTable.tsx | 49 +----- src/Table/SortingColumnHeader.tsx | 35 +++-- src/Table/StatefulTable.tsx | 35 ++++- src/Table/Table.tsx | 1 + src/Table/TableBody.tsx | 17 --- src/Table/TableCell.tsx | 18 +-- src/Table/TableFoot.tsx | 22 +-- src/Table/addExpandableControl.tsx | 25 ++- src/Table/addSelectableControl.tsx | 11 -- src/Tabs/Tab.tsx | 6 +- src/Tabs/TabScrollIndicator.tsx | 40 ++--- src/Tabs/TabScrollIndicators.js | 178 ---------------------- src/Tabs/TabScrollIndicators.tsx | 2 + src/Textarea/Textarea.tsx | 19 +-- src/TimePicker/TimePicker.tsx | 1 + src/TimeRange/TimeRange.tsx | 27 +--- src/Toast/Toast.tsx | 15 +- src/ToastContainer/ToastContainer.tsx | 23 +-- src/Toggle/Toggle.tsx | 43 +----- src/Toggle/ToggleButton.tsx | 46 +++--- src/Tooltip/Tooltip.tsx | 25 +-- src/TruncatedText/MaybeTooltip.tsx | 13 +- src/TruncatedText/TruncatedText.tsx | 56 +++---- src/TruncatedText/TruncatedTextProps.ts | 3 +- src/Type/Text.tsx | 8 +- src/Validation/InlineValidation.tsx | 17 +-- src/locales.const.ts | 2 +- src/utils/DetectOutsideClick.js | 16 +- src/utils/PreventBodyElementScrolling.js | 14 +- src/utils/localized-date-fns.js | 5 - src/utils/localized-date-fns.ts | 6 + 66 files changed, 594 insertions(+), 1197 deletions(-) delete mode 100644 src/Tabs/TabScrollIndicators.js delete mode 100644 src/utils/localized-date-fns.js create mode 100644 src/utils/localized-date-fns.ts diff --git a/src/BrandedNavBar/isValidMenuItem.ts b/src/BrandedNavBar/isValidMenuItem.ts index 466596d72..1e040727f 100644 --- a/src/BrandedNavBar/isValidMenuItem.ts +++ b/src/BrandedNavBar/isValidMenuItem.ts @@ -1,6 +1,4 @@ -import PropTypes from "prop-types"; - -const isValidMenuItem = function validArrayItem(arr, idx, componentName, location, propFullName) { +export default function isValidMenuItem(arr, idx, componentName, location, propFullName) { const obj = arr[idx]; if (typeof obj !== "object") { @@ -9,19 +7,6 @@ const isValidMenuItem = function validArrayItem(arr, idx, componentName, locatio ); } - PropTypes.checkPropTypes( - { - name: PropTypes.node.isRequired, - ariaLabel: PropTypes.string, - href: PropTypes.string, - items: PropTypes.arrayOf(isValidMenuItem), - render: PropTypes.func, - }, - obj, - propFullName, - componentName - ); - let numberOfDefiningKeys = 0; const definingKeys = ["href", "items", "render"]; const keys = Object.keys(obj); @@ -38,6 +23,4 @@ const isValidMenuItem = function validArrayItem(arr, idx, componentName, locatio } return null; -}; - -export default isValidMenuItem; +} diff --git a/src/Branding/BrandingText.tsx b/src/Branding/BrandingText.tsx index 49706c5a1..cb4a0fdcb 100644 --- a/src/Branding/BrandingText.tsx +++ b/src/Branding/BrandingText.tsx @@ -13,25 +13,21 @@ const logoColors = { const getLogoColor = (logoColor) => logoColors[logoColor] || logoColors.blue; -const BrandingText: React.FC> = styled.span( - ({ logoColor, size }: BrandingTextProps): any => ({ +const BrandingText = styled.span(({ logoColor = "blue", size }) => ({ + color: getLogoColor(logoColor), + textDecoration: "none", + fontWeight: theme.fontWeights.medium, + letterSpacing: "0.0333em", + textTransform: "uppercase", + fontSize: size === "small" ? "10px" : "11px", + lineHeight: "12px", + whiteSpace: "nowrap", + active: { color: getLogoColor(logoColor), - textDecoration: "none", - fontWeight: theme.fontWeights.medium, - letterSpacing: "0.0333em", - textTransform: "uppercase", - fontSize: size === "small" ? "10px" : "11px", - lineHeight: "12px", - whiteSpace: "nowrap", - active: { - color: getLogoColor(logoColor), - }, - visited: { - color: getLogoColor(logoColor), - }, - }) -); -BrandingText.defaultProps = { - logoColor: "blue", -}; + }, + visited: { + color: getLogoColor(logoColor), + }, +})); + export default BrandingText; diff --git a/src/Branding/LettermarkLogo.tsx b/src/Branding/LettermarkLogo.tsx index 4bee112df..46f2671a1 100644 --- a/src/Branding/LettermarkLogo.tsx +++ b/src/Branding/LettermarkLogo.tsx @@ -1,4 +1,5 @@ import React from "react"; + const sizes = { small: { height: "24px", @@ -13,26 +14,26 @@ const sizes = { width: "56px", }, }; -const getSize = (size) => sizes[size] || sizes.medium; + +const getSize = (size: string) => sizes[size] || sizes.medium; + type LettermarkLogoProps = { letterFill?: string; size?: string; }; -const LettermarkLogo: React.FC> = ({ size, letterFill, ...props }) => ( - - - -); -LettermarkLogo.defaultProps = { - letterFill: undefined, - size: undefined, -}; -export default LettermarkLogo; + +export default function LettermarkLogo({ size, letterFill, ...props }: LettermarkLogoProps) { + return ( + + + + ); +} diff --git a/src/Branding/WordmarkLogo.tsx b/src/Branding/WordmarkLogo.tsx index 90c35305e..041192b3c 100644 --- a/src/Branding/WordmarkLogo.tsx +++ b/src/Branding/WordmarkLogo.tsx @@ -1,4 +1,5 @@ import React from "react"; + const sizes = { small: { height: "24px", @@ -13,41 +14,36 @@ const sizes = { width: "200px", }, }; -const getSize = (size) => sizes[size] || sizes.medium; + +const getSize = (size: string) => sizes[size] || sizes.medium; + type WordmarkLogoProps = { logoFill?: string; letterFill?: string; size?: string; + children?: React.ReactNode; }; -const WordmarkLogo: React.FC> = ({ - size, - logoFill, - letterFill, - ...props -}) => ( - - - - - - - - - - - -); -WordmarkLogo.defaultProps = { - logoFill: undefined, - letterFill: undefined, - size: undefined, -}; -export default WordmarkLogo; + +export default function WordmarkLogo({ size, logoFill, letterFill, ...props }: WordmarkLogoProps) { + return ( + + + + + + + + + + + + ); +} diff --git a/src/Breadcrumbs/Breadcrumbs.tsx b/src/Breadcrumbs/Breadcrumbs.tsx index 39d8e3803..d0bb4cb3e 100644 --- a/src/Breadcrumbs/Breadcrumbs.tsx +++ b/src/Breadcrumbs/Breadcrumbs.tsx @@ -19,7 +19,7 @@ const insertSeparators = (items: JSX.Element[]) => { type BreadcrumbsProps = Omit & { size?: ComponentSize }; -const Breadcrumbs = ({ size, children, ...props }: BreadcrumbsProps) => { +const Breadcrumbs = ({ size, as = "nav", children, ...props }: BreadcrumbsProps) => { const componentSize = useComponentSize(size); const allItems = React.Children.map(children, (child, index) => { @@ -33,14 +33,10 @@ const Breadcrumbs = ({ size, children, ...props }: BreadcrumbsProps) => { }).filter(Boolean); return ( - + {insertSeparators(allItems)} ); }; -Breadcrumbs.defaultProps = { - as: "nav", -}; - export default Breadcrumbs; diff --git a/src/ButtonGroup/ButtonGroup.tsx b/src/ButtonGroup/ButtonGroup.tsx index 82ca5607d..8de079731 100644 --- a/src/ButtonGroup/ButtonGroup.tsx +++ b/src/ButtonGroup/ButtonGroup.tsx @@ -3,6 +3,7 @@ import { Flex } from "../Flex"; import { FlexProps } from "../Flex/Flex"; type ButtonGroupProps = FlexProps & { + children?: React.ReactNode; alignment?: "left" | "spaced" | "right"; className?: string; }; @@ -12,6 +13,7 @@ const alignments = { spaced: "space-between", right: "flex-end", }; + const buttonSpacings = (theme) => ({ left: { "button:not(:last-child)": { @@ -29,10 +31,11 @@ const buttonSpacings = (theme) => ({ }, }, }); + const getAlignment = (alignment) => alignments[alignment] || alignments.left; const getButtonSpacing = (alignment, theme) => buttonSpacings(theme)[alignment] || buttonSpacings(theme).left; -const ButtonGroup: React.FC> = styled(Flex)(({ alignment, theme }: any) => ({ +const ButtonGroup = styled(Flex)(({ alignment = "left", theme }) => ({ flexWrap: "wrap", marginBottom: `-${theme.space.x1}`, justifyContent: getAlignment(alignment), @@ -41,8 +44,5 @@ const ButtonGroup: React.FC> = styled( }, ...getButtonSpacing(alignment, theme), })); -ButtonGroup.defaultProps = { - alignment: "left", - className: undefined, -}; + export default ButtonGroup; diff --git a/src/Card/Card.tsx b/src/Card/Card.tsx index 3634121b8..17d7015b0 100644 --- a/src/Card/Card.tsx +++ b/src/Card/Card.tsx @@ -1,16 +1,20 @@ -import styled from "styled-components"; +import React from "react"; import { Box } from "../Box"; import { BoxProps } from "../Box/Box"; -const Card: React.FC> = styled(Box)({}); - -Card.defaultProps = { - children: [], - borderRadius: "medium", - boxShadow: "small", - bg: "whiteGrey", - py: "x2", - px: "x2", - position: "relative", -}; -export default Card; +export default function Card({ + children = [], + borderRadius = "medium", + boxShadow = "small", + bg = "whiteGrey", + py = "x2", + px = "x2", + position = "relative", + ...props +}: BoxProps) { + return ( + + {children} + + ); +} diff --git a/src/Checkbox/Checkbox.tsx b/src/Checkbox/Checkbox.tsx index 1cf2f0cb1..b92761c28 100644 --- a/src/Checkbox/Checkbox.tsx +++ b/src/Checkbox/Checkbox.tsx @@ -14,6 +14,7 @@ type NativeInputProps = Omit, "size">; type CheckboxProps = NativeInputProps & SpaceProps & { + children?: React.ReactNode; htmlSize?: number; size?: ComponentSize; labelText?: string; @@ -24,7 +25,7 @@ type CheckboxProps = NativeInputProps & theme?: DefaultNDSThemeType; }; -const checkboxStyle = (theme) => ({ +const checkboxStyle = (theme: DefaultNDSThemeType) => ({ checked: { disabled: { borderColor: theme.colors.lightGrey, @@ -55,7 +56,7 @@ const checkboxStyle = (theme) => ({ }, }); -const getCheckboxStyle = (props, checked) => { +const getCheckboxStyle = (props: CheckboxProps, checked: "checked" | "unchecked") => { const checkboxStyleMap = checkboxStyle(props.theme); if (props.disabled) { return checkboxStyleMap[checked].disabled; @@ -127,7 +128,9 @@ const CheckboxInput = styled.input((props) => ({ }, })); -const Checkbox: React.FC> = forwardRef((props, ref) => { +type Ref = HTMLInputElement; + +const Checkbox = forwardRef((props, ref) => { const { size, className, labelText, disabled, checked, required, error, indeterminate } = props; const componentSize = useComponentSize(size); @@ -163,16 +166,4 @@ const Checkbox: React.FC> = forwardRef((p ); }); -Checkbox.defaultProps = { - labelText: undefined, - checked: undefined, - defaultChecked: undefined, - disabled: false, - error: false, - id: undefined, - className: undefined, - required: false, - indeterminate: undefined, -}; - export default Checkbox; diff --git a/src/Checkbox/CheckboxGroup.tsx b/src/Checkbox/CheckboxGroup.tsx index 442b01d59..b3f617476 100644 --- a/src/Checkbox/CheckboxGroup.tsx +++ b/src/Checkbox/CheckboxGroup.tsx @@ -6,6 +6,7 @@ import { Fieldset } from "../Form"; import Checkbox from "./Checkbox"; interface CheckboxGroupProps { + children?: React.ReactNode; errorMessage?: string; errorList?: string[]; labelText: string; @@ -21,6 +22,30 @@ interface CheckboxGroupProps { disabled?: boolean; } +export default function CheckboxGroup({ + className, + id, + errorMessage, + errorList, + labelText, + helpText, + requirementText, + ...props +}: CheckboxGroupProps) { + const otherProps = { ...props, errorMessage, errorList }; + return ( +
+ + {labelText} + {requirementText && {requirementText}} + + {helpText && {helpText}} + {getCheckboxButtons(otherProps)} + +
+ ); +} + const getCheckboxButtons = (props) => { const checkboxButtons = React.Children.map(props.children, (checkbox) => { const { value, disabled, required, onChange, ...checkboxProps } = checkbox.props; @@ -41,7 +66,7 @@ const getCheckboxButtons = (props) => { return checkboxButtons; }; -const LabelText = styled.span(({ theme }) => ({ +const LabelText = styled.span(({ theme }) => ({ fontSize: theme.fontSizes.small, fontWeight: theme.fontWeights.bold, lineHeight: theme.lineHeights.smallTextBase, @@ -50,42 +75,3 @@ const LabelText = styled.span(({ theme }) => ({ const Legend = styled.legend(({ theme }) => ({ marginBottom: theme.space.x1, })); - -const CheckboxGroup: React.FC> = ({ - className, - id, - errorMessage, - errorList, - labelText, - helpText, - requirementText, - ...props -}) => { - const otherProps = { ...props, errorMessage, errorList }; - return ( -
- - {labelText} - {requirementText && {requirementText}} - - {helpText && {helpText}} - {getCheckboxButtons(otherProps)} - -
- ); -}; - -CheckboxGroup.defaultProps = { - errorMessage: undefined, - errorList: undefined, - defaultValue: undefined, - checkedValue: undefined, - onChange: undefined, - className: undefined, - id: undefined, - helpText: undefined, - requirementText: undefined, - disabled: false, -}; - -export default CheckboxGroup; diff --git a/src/DatePicker/DatePickerHeader.tsx b/src/DatePicker/DatePickerHeader.tsx index d0844bf85..8d58145bd 100644 --- a/src/DatePicker/DatePickerHeader.tsx +++ b/src/DatePicker/DatePickerHeader.tsx @@ -4,23 +4,23 @@ import { Text } from "../Type"; import { ControlIcon } from "../Button"; import { localizedFormat } from "../utils/localized-date-fns"; -type DatePickerHeaderProps = { - date: any; - decreaseMonth: (...args: any[]) => any; - increaseMonth: (...args: any[]) => any; +type Props = { + date: number; + decreaseMonth: React.MouseEventHandler; + increaseMonth: React.MouseEventHandler; prevMonthButtonDisabled: boolean; nextMonthButtonDisabled: boolean; locale?: string; }; -const DatePickerHeader: React.FC> = ({ +export default function DatePickerHeader({ date, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled, locale, -}) => { +}: Props) { return ( > /> ); -}; -DatePickerHeader.defaultProps = { - locale: undefined, -}; -export default DatePickerHeader; +} diff --git a/src/DropdownMenu/DropdownButton.tsx b/src/DropdownMenu/DropdownButton.tsx index 5039c5327..5c4e717f5 100644 --- a/src/DropdownMenu/DropdownButton.tsx +++ b/src/DropdownMenu/DropdownButton.tsx @@ -15,7 +15,7 @@ type DropdownButtonProps = React.ComponentPropsWithRef<"button"> & }; const DropdownButton = styled.button( - ({ disabled, theme, hoverColor, bgHoverColor }) => ({ + ({ disabled = false, hoverColor = "darkBlue", bgHoverColor = "lightBlue", theme }) => ({ color: theme.colors.darkGrey, fontWeight: theme.fontWeights.medium, display: "block", @@ -66,10 +66,4 @@ const DropdownButton = styled.button( addStyledProps ); -DropdownButton.defaultProps = { - disabled: false, - hoverColor: "darkBlue", - bgHoverColor: "lightBlue", -}; - export default DropdownButton; diff --git a/src/DropdownMenu/DropdownItem.tsx b/src/DropdownMenu/DropdownItem.tsx index 02974c5cd..eeb3271ae 100644 --- a/src/DropdownMenu/DropdownItem.tsx +++ b/src/DropdownMenu/DropdownItem.tsx @@ -1,15 +1,13 @@ -import styled, { CSSObject } from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; +import styled from "styled-components"; -type DropdownItemProps = { - theme?: DefaultNDSThemeType; +type Props = { color?: string; hoverColor?: string; bgHoverColor?: string; }; -const DropdownItem: React.FC> = styled.div( - ({ theme, color, hoverColor, bgHoverColor }: DropdownItemProps): CSSObject => ({ +const DropdownItem = styled.div( + ({ theme, color = "darkGrey", hoverColor = "darkBlue", bgHoverColor = "lightBlue" }) => ({ "*": { color: theme.colors[color], fontWeight: theme.fontWeights.medium, @@ -40,9 +38,5 @@ const DropdownItem: React.FC> = style }, }) ); -DropdownItem.defaultProps = { - color: "darkGrey", - hoverColor: "darkBlue", - bgHoverColor: "lightBlue", -}; + export default DropdownItem; diff --git a/src/DropdownMenu/DropdownLink.tsx b/src/DropdownMenu/DropdownLink.tsx index 311ba8faa..f2671c3ea 100644 --- a/src/DropdownMenu/DropdownLink.tsx +++ b/src/DropdownMenu/DropdownLink.tsx @@ -2,24 +2,21 @@ import React from "react"; import styled from "styled-components"; import { variant } from "styled-system"; import { addStyledProps, StyledProps } from "../StyledProps"; -import { DefaultNDSThemeType } from "../theme.type"; import { ComponentSize } from "../NDSProvider/ComponentSizeContext"; -type DropdownLinkProps = React.ComponentPropsWithRef<"a"> & - StyledProps & { - disabled?: boolean; - size?: ComponentSize; - color?: string; - theme?: DefaultNDSThemeType; - hoverColor?: string; - bgHoverColor?: string; - }; +interface Props extends React.ComponentPropsWithRef<"a">, StyledProps { + disabled?: boolean; + size?: ComponentSize; + color?: string; + hoverColor?: string; + bgHoverColor?: string; +} -const DropdownLink = styled.a.withConfig({ +const DropdownLink = styled.a.withConfig({ shouldForwardProp: (prop, defaultValidatorFn) => !["hoverColor", "bgHoverColor"].includes(prop) && defaultValidatorFn(prop), })( - ({ theme, color, bgHoverColor, hoverColor }) => ({ + ({ theme, color = "darkGrey", hoverColor = "darkBlue", bgHoverColor = "lightBlue" }) => ({ color: theme.colors[color], fontWeight: theme.fontWeights.medium, display: "flex", @@ -74,10 +71,4 @@ const DropdownLink = styled.a.withConfig({ addStyledProps ); -DropdownLink.defaultProps = { - disabled: false, - color: "darkGrey", - hoverColor: "darkBlue", - bgHoverColor: "lightBlue", -}; export default DropdownLink; diff --git a/src/FieldLabel/FieldLabel.tsx b/src/FieldLabel/FieldLabel.tsx index 87c2ac05d..3fa51964e 100644 --- a/src/FieldLabel/FieldLabel.tsx +++ b/src/FieldLabel/FieldLabel.tsx @@ -5,29 +5,34 @@ import HelpText from "./HelpText"; import Label from "./Label"; import LabelText from "./LabelText"; import RequirementText from "./RequirementText"; -import { FieldLabelProps, FieldLabelDefaultProps } from "./FieldLabel.type"; +import { FieldLabelProps } from "./FieldLabel.type"; import FramedIcon from "./FramedIcon"; -const FieldLabel = ({ labelText, requirementText, helpText, hint, children, ...props }: FieldLabelProps) => ( - + ); +} diff --git a/src/FieldLabel/Label.tsx b/src/FieldLabel/Label.tsx index f6faf93ba..3ffa7553a 100644 --- a/src/FieldLabel/Label.tsx +++ b/src/FieldLabel/Label.tsx @@ -6,7 +6,8 @@ import type { ComponentPropsWithRef } from "react"; export interface LabelProps extends SpaceProps, DisplayProps, Omit, "color"> {} const Label = styled.label( - () => ({ + ({ color = "black" }) => ({ + color: color, display: "inline-block", }), display, @@ -14,8 +15,4 @@ const Label = styled.label( color ); -Label.defaultProps = { - color: "black", -}; - export default Label; diff --git a/src/Form/FormSection.tsx b/src/Form/FormSection.tsx index 6069c896d..ed6d506f0 100644 --- a/src/Form/FormSection.tsx +++ b/src/Form/FormSection.tsx @@ -4,20 +4,21 @@ import { Heading3 } from "../Type"; import Field from "./Field"; import Fieldset from "./Fieldset"; -type BaseFormSectionProps = React.ComponentPropsWithRef<"fieldset"> & { +interface BaseFormSectionProps extends React.ComponentPropsWithRef<"fieldset"> { title?: string; -}; +} -const FormSectionTitle = styled(Heading3).attrs({ - as: "legend", -})({}); - -const BaseFormSection: React.FC> = ({ title, children, ...props }) => ( +const BaseFormSection = ({ title, children, ...props }: BaseFormSectionProps) => (
{title != null && {title}} {children}
); + +const FormSectionTitle = styled(Heading3).attrs({ + as: "legend", +})({}); + const FormSection = styled(BaseFormSection)(({ title, theme }) => ({ width: "100%", padding: 0, @@ -34,8 +35,5 @@ const FormSection = styled(BaseFormSection)(({ title, theme }) => ({ }, }, })); -BaseFormSection.defaultProps = { - children: [], - title: undefined, -}; + export default FormSection; diff --git a/src/Icon/Icon.tsx b/src/Icon/Icon.tsx index 4d8ac6899..99a6f213e 100644 --- a/src/Icon/Icon.tsx +++ b/src/Icon/Icon.tsx @@ -2,8 +2,6 @@ import React from "react"; import styled, { CSSObject, useTheme } from "styled-components"; import { space, SpaceProps } from "styled-system"; import icons from "@nulogy/icons"; - -import theme from "../theme"; import LoadingIcon from "./LoadingIcon"; interface IconProps extends SpaceProps { @@ -27,8 +25,20 @@ const getPathElements = (icon: any) => ( /* eslint-enable react/no-array-index-key */ const Svg = React.forwardRef( - ({ icon, size, focusable, className, color: fillColor, title, ...props }: IconProps, ref) => { - const { space } = useTheme(); + ( + { + color: fillColor = "currentColor", + className = undefined, + title = undefined, + size = "24px", + focusable = false, + icon, + ...props + }: IconProps, + ref + ) => { + const theme = useTheme(); + if (icon === "loading") { return ( ( ( } ); -Svg.displayName = "Svg"; - -Svg.defaultProps = { - color: "currentColor", - className: undefined, - title: undefined, - size: "24px", - focusable: false, -}; - const Icon = styled(Svg)( space, - ({ size }: IconProps): CSSObject => ({ + ({ color = "currentColor", size = "24px" }): CSSObject => ({ minWidth: size, + color: color, }) ); -Icon.defaultProps = { - color: "currentColor", - title: undefined, - size: "24px", -}; - const iconSizeRatio = 1.25; const CenteredIcon = styled(Svg)({ @@ -96,10 +91,12 @@ const IconContainer = styled.span(space, { width: `${iconSizeRatio}em`, }); -export const InlineIcon = (props: IconProps) => ( - - - -); +export function InlineIcon(props: IconProps) { + return ( + + + + ); +} export default Icon; diff --git a/src/Input/Suffix.tsx b/src/Input/Suffix.tsx index 681968fec..fb490eaa1 100644 --- a/src/Input/Suffix.tsx +++ b/src/Input/Suffix.tsx @@ -3,20 +3,15 @@ import { Box } from "../Box"; import { Text } from "../Type"; import { TextProps } from "../Type/Text"; -type SuffixProps = TextProps & { +interface SuffixProps extends TextProps { suffix?: string; suffixWidth?: string; -}; +} -const Suffix = ({ suffix, suffixWidth, ...props }: SuffixProps) => - suffix ? ( +export default function Suffix({ suffix, suffixWidth, ...props }: SuffixProps) { + return suffix ? ( {suffix} ) : null; -Suffix.defaultProps = { - suffix: null, - children: null, - suffixWidth: null, -}; -export default Suffix; +} diff --git a/src/Link/Link.tsx b/src/Link/Link.tsx index 717c3211f..b32ac798f 100644 --- a/src/Link/Link.tsx +++ b/src/Link/Link.tsx @@ -60,14 +60,10 @@ const StyledLink = styled.a( addStyledProps ); -const Link = React.forwardRef(({ size, ...props }, ref) => { +const Link = React.forwardRef(({ size, underline = true, ...props }, ref) => { const componentSize = useComponentSize(size); - return ; + return ; }); -Link.defaultProps = { - underline: true, -}; - export default Link; diff --git a/src/List/List.tsx b/src/List/List.tsx index 1d807d6e3..e0858608a 100644 --- a/src/List/List.tsx +++ b/src/List/List.tsx @@ -1,19 +1,18 @@ import styled from "styled-components"; -import { DefaultNDSThemeType } from "../theme.type"; import { addStyledProps, StyledProps } from "../StyledProps"; import ListItem from "./ListItem"; -type ListProps = React.ComponentPropsWithRef<"ul"> & - StyledProps & { - theme?: DefaultNDSThemeType; - className?: string; - compact?: boolean; - leftAlign?: boolean; - listStyle?: string; - }; -const List: React.FC> = styled.ul( - ({ compact, theme, leftAlign, listStyle }: ListProps) => ({ +interface Props extends React.ComponentPropsWithRef<"ul">, StyledProps { + className?: string; + compact?: boolean; + leftAlign?: boolean; + listStyle?: string; +} + +const List = styled.ul( + ({ compact = false, leftAlign = false, color = "currentColor", theme, listStyle }) => ({ margin: 0, + color: color, paddingLeft: leftAlign ? "18px" : undefined, listStyle, [`${ListItem}`]: { @@ -22,11 +21,5 @@ const List: React.FC> = styled.ul( }), addStyledProps ); -List.defaultProps = { - className: undefined, - compact: false, - leftAlign: false, - listStyle: undefined, - color: "currentColor", -}; + export default List; diff --git a/src/List/ListItem.tsx b/src/List/ListItem.tsx index 75deb4c3d..a45b1bacd 100644 --- a/src/List/ListItem.tsx +++ b/src/List/ListItem.tsx @@ -1,19 +1,12 @@ import styled from "styled-components"; import { space, color, typography, SpaceProps, ColorProps, TypographyProps } from "styled-system"; -type ListItemProps = React.ComponentPropsWithRef<"li"> & - SpaceProps & - ColorProps & - TypographyProps & { - className?: string; - }; -const ListItem: React.FC> = styled.li(space, color, typography, { + +type Props = React.ComponentPropsWithRef<"li"> & SpaceProps & ColorProps & TypographyProps; + +const ListItem = styled.li(space, color, typography, { "&:last-child": { marginBottom: 0, }, }); -ListItem.defaultProps = { - className: undefined, - color: "currentColor", - mb: "x1", -}; + export default ListItem; diff --git a/src/LoadingAnimation/LoadingAnimation.tsx b/src/LoadingAnimation/LoadingAnimation.tsx index 75a00d6e0..766d5595a 100644 --- a/src/LoadingAnimation/LoadingAnimation.tsx +++ b/src/LoadingAnimation/LoadingAnimation.tsx @@ -1,10 +1,11 @@ import React from "react"; import { useTheme } from "styled-components"; -type LoadingAnimationProps = React.ComponentPropsWithRef<"svg"> & { +interface Props extends React.ComponentPropsWithRef<"svg"> { inactive?: boolean; -}; -const LoadingAnimation: React.FC> = ({ inactive }) => { +} + +export default function LoadingAnimation({ inactive = false }: Props) { const { colors } = useTheme(); const color1 = inactive ? colors.grey : colors.blue; @@ -113,8 +114,4 @@ const LoadingAnimation: React.FC> ); -}; -LoadingAnimation.defaultProps = { - inactive: false, -}; -export default LoadingAnimation; +} diff --git a/src/Modal/Modal.tsx b/src/Modal/Modal.tsx index 776aae83f..50013fe15 100644 --- a/src/Modal/Modal.tsx +++ b/src/Modal/Modal.tsx @@ -85,22 +85,22 @@ type ModalProps = { const Modal: React.FC> & { setAppElement: (element: string | HTMLElement) => void; } = ({ - isOpen, + isOpen = true, + shouldFocusAfterRender = true, + shouldReturnFocusAfterClose = true, + maxWidth = "624px", + ariaHideApp = true, children, title, onRequestClose, onAfterOpen, - shouldFocusAfterRender, - shouldReturnFocusAfterClose, ariaLabel, ariaDescribedBy, portalClassName, overlayClassName, className, id, - maxWidth, appElement, - ariaHideApp, footerContent, closeAriaLabel, parentSelector, @@ -153,27 +153,6 @@ const Modal: React.FC> & { ); }; -Modal.defaultProps = { - isOpen: true, - title: undefined, - ariaLabel: undefined, - onRequestClose: undefined, - closeAriaLabel: undefined, - onAfterOpen: undefined, - shouldFocusAfterRender: true, - shouldReturnFocusAfterClose: true, - ariaDescribedBy: undefined, - maxWidth: "624px", - portalClassName: undefined, - overlayClassName: undefined, - className: undefined, - id: undefined, - appElement: undefined, - ariaHideApp: true, - footerContent: undefined, - parentSelector: undefined, -}; - Modal.setAppElement = ReactModal.setAppElement; export default Modal; diff --git a/src/NavBar/DesktopMenu.tsx b/src/NavBar/DesktopMenu.tsx index 4fbd6216c..14514126b 100644 --- a/src/NavBar/DesktopMenu.tsx +++ b/src/NavBar/DesktopMenu.tsx @@ -131,11 +131,6 @@ BaseDesktopMenu.propTypes = { themeColorObject: PropTypes.shape({}), }; -BaseDesktopMenu.defaultProps = { - menuData: null, - themeColorObject: null, -}; - const DesktopMenu = styled(BaseDesktopMenu)({ "> div": { ":not(:last-of-type)": { diff --git a/src/NavBar/MenuTrigger.tsx b/src/NavBar/MenuTrigger.tsx index 004555415..cccdabbfc 100644 --- a/src/NavBar/MenuTrigger.tsx +++ b/src/NavBar/MenuTrigger.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import styled from "styled-components"; +import React, { ReactNode } from "react"; +import styled, { useTheme } from "styled-components"; import PropTypes from "prop-types"; import { themeGet } from "@styled-system/theme-get"; import theme from "../theme"; @@ -9,7 +9,7 @@ import SubMenuTrigger from "./SubMenuTrigger"; import renderSubMenuItems from "./renderSubMenuItems"; export type MenuTriggerProps = { - name?: string; + name?: ReactNode; "aria-label"?: string; color?: string; hoverColor?: string; @@ -20,11 +20,11 @@ export type MenuTriggerProps = { const StyledButton = styled.button<{ hoverColor: string; hoverBackground: string; -}>(({ color, hoverColor, hoverBackground }) => ({ +}>(({ color = "white", hoverColor = "lightBlue", hoverBackground = "black", ...props }) => ({ display: "flex", alignItems: "center", position: "relative", - color: themeGet(`colors.${color}`, color)(color), + color: themeGet(`colors.${color}`, color)(props), border: "none", backgroundColor: "transparent", textDecoration: "none", @@ -35,8 +35,8 @@ const StyledButton = styled.button<{ borderRadius: theme.radii.medium, "&:hover, &:focus": { outline: "none", - color: themeGet(`colors.${hoverColor}`, hoverColor)(hoverColor), - backgroundColor: themeGet(`colors.${hoverBackground}`, hoverBackground)(hoverBackground), + color: themeGet(`colors.${hoverColor}`, hoverColor)(props), + backgroundColor: themeGet(`colors.${hoverBackground}`, hoverBackground)(props), cursor: "pointer", }, "&:focus": { @@ -53,11 +53,7 @@ StyledButton.propTypes = { hoverBackground: PropTypes.string, }; -StyledButton.defaultProps = { - color: theme.colors.white, - hoverColor: theme.colors.lightBlue, - hoverBackground: theme.colors.black, -}; +StyledButton.defaultProps = {}; const MenuTriggerButton = React.forwardRef( ({ name, color, hoverColor, hoverBackground, ...props }, ref) => ( @@ -81,14 +77,21 @@ MenuTriggerButton.propTypes = { hoverBackground: PropTypes.string, }; -MenuTriggerButton.defaultProps = { - color: theme.colors.white, - hoverColor: theme.colors.lightBlue, - hoverBackground: theme.colors.black, -}; +function MenuTrigger({ + menuData, + name, + color, + hoverColor, + hoverBackground, + "aria-label": ariaLabel, + ...otherProps +}: MenuTriggerProps) { + const theme = useTheme(); + + color = color || theme.colors.white; + hoverColor = hoverColor || theme.colors.lightBlue; + hoverBackground = hoverBackground || theme.colors.black; -const MenuTrigger = (props) => { - const { menuData, name, color, hoverColor, hoverBackground, "aria-label": ariaLabel, ...otherProps } = props; let dropdownMinWidth = "auto"; const setDropdownMinWidth = (popperData) => { // Popper.js throws an error if popperData is not returned from this fn @@ -142,23 +145,6 @@ const MenuTrigger = (props) => { )} ); -}; - -MenuTrigger.propTypes = { - name: PropTypes.node.isRequired, - "aria-label": PropTypes.string, - menuData: PropTypes.arrayOf(PropTypes.shape({})), - color: PropTypes.string, - hoverColor: PropTypes.string, - hoverBackground: PropTypes.string, -}; - -MenuTrigger.defaultProps = { - menuData: null, - "aria-label": undefined, - color: theme.colors.white, - hoverColor: theme.colors.lightBlue, - hoverBackground: theme.colors.black, -}; +} export default MenuTrigger; diff --git a/src/Overlay/Overlay.tsx b/src/Overlay/Overlay.tsx index cf70c12eb..980a50b12 100644 --- a/src/Overlay/Overlay.tsx +++ b/src/Overlay/Overlay.tsx @@ -2,28 +2,21 @@ import styled from "styled-components"; import { transparentize } from "polished"; import { Flex } from "../Flex"; import { FlexProps } from "../Flex/Flex"; -import { DefaultNDSThemeType } from "../theme.type"; -import CSSObject from "styled-components"; -type OverlayProps = FlexProps & { +interface Props extends FlexProps { dark?: boolean; - theme?: DefaultNDSThemeType; -}; +} -const Overlay: React.FC> = styled(Flex)( - ({ dark, theme }: OverlayProps) => ({ - top: 0, - left: 0, - right: 0, - bottom: 0, - zIndex: theme.zIndices.overlay, - backgroundColor: dark ? transparentize(0.5, theme.colors.blackBlue) : transparentize(0.05, theme.colors.white), - }) -); -Overlay.defaultProps = { +const Overlay = styled(Flex)(({ dark = false, theme }) => ({ position: "fixed", justifyContent: "center", alignItems: "center", - dark: false, -}; + top: 0, + left: 0, + right: 0, + bottom: 0, + zIndex: theme.zIndices.overlay, + backgroundColor: dark ? transparentize(0.5, theme.colors.blackBlue) : transparentize(0.05, theme.colors.white), +})); + export default Overlay; diff --git a/src/Pagination/NextButton.tsx b/src/Pagination/NextButton.tsx index 242780fb6..e8e90b918 100644 --- a/src/Pagination/NextButton.tsx +++ b/src/Pagination/NextButton.tsx @@ -1,5 +1,4 @@ import React, { ReactNode } from "react"; -import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { Icon } from "../Icon"; import PaginationButton from "./PaginationButton"; @@ -20,16 +19,4 @@ const NextButton = ({ disabled, onClick, label, ariaLabel }: NextButtonProps) => ); }; -NextButton.propTypes = { - disabled: PropTypes.bool, - onClick: PropTypes.func, - label: PropTypes.node, - ariaLabel: PropTypes.string, -}; - -NextButton.defaultProps = { - disabled: false, - onClick: null, -}; - export default NextButton; diff --git a/src/Pagination/Pagination.tsx b/src/Pagination/Pagination.tsx index aa84d3f35..73784a94c 100644 --- a/src/Pagination/Pagination.tsx +++ b/src/Pagination/Pagination.tsx @@ -1,5 +1,4 @@ import React, { ReactNode, RefObject } from "react"; -import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { flushSync } from "react-dom"; import { Flex } from "../Flex"; @@ -41,11 +40,11 @@ interface PaginationProps extends FlexProps { } function Pagination({ - currentPage, - totalPages, onNext, onPrevious, onSelectPage, + currentPage, + totalPages, nextAriaLabel, nextLabel, previousAriaLabel, @@ -127,28 +126,4 @@ function Pagination({ ); } -Pagination.propTypes = { - currentPage: PropTypes.number.isRequired, - totalPages: PropTypes.number.isRequired, - onNext: PropTypes.func, - onPrevious: PropTypes.func, - onSelectPage: PropTypes.func, - nextLabel: PropTypes.node, - nextAriaLabel: PropTypes.string, - previousLabel: PropTypes.node, - previousAriaLabel: PropTypes.string, - "aria-label": PropTypes.string, -}; - -Pagination.defaultProps = { - onNext: null, - onPrevious: null, - onSelectPage: null, - nextLabel: undefined, - nextAriaLabel: undefined, - previousLabel: undefined, - previousAriaLabel: undefined, - "aria-label": undefined, -}; - export default Pagination; diff --git a/src/Pagination/PreviousButton.tsx b/src/Pagination/PreviousButton.tsx index b95bd2599..d3c3ff693 100644 --- a/src/Pagination/PreviousButton.tsx +++ b/src/Pagination/PreviousButton.tsx @@ -1,5 +1,4 @@ import React, { ReactNode } from "react"; -import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { Icon } from "../Icon"; import PaginationButton from "./PaginationButton"; @@ -11,7 +10,7 @@ type PreviousButtonProps = { ariaLabel: string; }; -const PreviousButton = ({ disabled, onClick, label, ariaLabel }: PreviousButtonProps) => { +const PreviousButton = ({ disabled = false, onClick = null, label, ariaLabel }: PreviousButtonProps) => { const { t } = useTranslation(); return ( @@ -20,16 +19,4 @@ const PreviousButton = ({ disabled, onClick, label, ariaLabel }: PreviousButtonP ); }; -PreviousButton.propTypes = { - disabled: PropTypes.bool, - onClick: PropTypes.func, - label: PropTypes.node, - ariaLabel: PropTypes.string, -}; - -PreviousButton.defaultProps = { - disabled: false, - onClick: null, -}; - export default PreviousButton; diff --git a/src/Popper/Popper.tsx b/src/Popper/Popper.tsx index 2c2c33e7b..8399c8d7d 100644 --- a/src/Popper/Popper.tsx +++ b/src/Popper/Popper.tsx @@ -1,17 +1,20 @@ // @ts-nocheck -import React, { useState, useEffect, useRef } from "react"; +import React, { useState, useEffect, useRef, LegacyRef } from "react"; import { Manager, Reference, Popper as ReactPopperPopUp } from "react-popper"; import { useTranslation } from "react-i18next"; import { PopperArrow } from "../utils"; + const makeArray = (children) => { if (!Array.isArray(children)) { return [children]; } return children; }; -const wrapInFunction = (x) => (typeof x === "function" ? x : () => x); + +const wrapInFunction = (x: unknown) => (typeof x === "function" ? x : () => x); + type PopperProps = { - ref: any; + children?: React.ReactNode; popperPlacement?: string; defaultOpen?: boolean; showDelay?: string | number; @@ -27,24 +30,25 @@ type PopperProps = { openAriaLabel?: string; closeAriaLabel?: string; }; -const Popper: React.FC> = React.forwardRef( + +const Popper = React.forwardRef( ( { - popperPlacement, - defaultOpen, id, - showDelay, - hideDelay, trigger, children, - openOnClick, - openOnHover, - modifiers, backgroundColor, borderColor, - showArrow, openAriaLabel, closeAriaLabel, + modifiers, + showDelay = "100", + hideDelay = "350", + defaultOpen = false, + popperPlacement = "bottom", + openOnClick = false, + openOnHover = true, + showArrow = true, }, popperRef ) => { @@ -209,19 +213,5 @@ const Popper: React.FC> = React.forwardRef( ); } ); -Popper.defaultProps = { - showDelay: "100", - hideDelay: "350", - defaultOpen: false, - popperPlacement: "bottom", - id: null, - openOnClick: false, - openOnHover: true, - modifiers: null, - backgroundColor: undefined, - borderColor: undefined, - showArrow: true, - openAriaLabel: undefined, - closeAriaLabel: undefined, -}; + export default Popper; diff --git a/src/Radio/Radio.tsx b/src/Radio/Radio.tsx index db27f325d..6dcf7f4c8 100644 --- a/src/Radio/Radio.tsx +++ b/src/Radio/Radio.tsx @@ -9,7 +9,7 @@ import { DefaultNDSThemeType } from "../theme.type"; import { getSubset, omitSubset } from "../utils/subset"; import { ComponentSize, useComponentSize } from "../NDSProvider/ComponentSizeContext"; -const radioStyle = (theme) => ({ +const radioStyle = (theme: DefaultNDSThemeType) => ({ checked: { disabled: { borderColor: theme.colors.lightGrey, @@ -113,8 +113,10 @@ type RadioProps = NativeInputProps & error?: boolean; }; -const Radio: React.FC> = forwardRef( - ({ className, labelText, disabled, checked, required, error, size, ...props }, ref) => { +type Ref = HTMLInputElement; + +const Radio = forwardRef( + ({ disabled = false, error = false, required = false, className, labelText, checked, size, ...props }, ref) => { const componentSize = useComponentSize(size); const spaceProps = getSubset(props, propTypes.space); const restProps = omitSubset(props, propTypes.space); @@ -144,14 +146,4 @@ const Radio: React.FC> = forwardRef( } ); -Radio.defaultProps = { - checked: undefined, - defaultChecked: undefined, - disabled: false, - error: false, - id: undefined, - className: undefined, - required: false, -}; - export default Radio; diff --git a/src/Radio/RadioGroup.tsx b/src/Radio/RadioGroup.tsx index f972d9054..7d77f92a5 100644 --- a/src/Radio/RadioGroup.tsx +++ b/src/Radio/RadioGroup.tsx @@ -1,38 +1,11 @@ import React, { useContext } from "react"; import { CSSObject, ThemeContext } from "styled-components"; - import { HelpText, RequirementText } from "../FieldLabel"; import { InlineValidation } from "../Validation"; import { Fieldset } from "../Form"; import { DefaultNDSThemeType } from "../theme.type"; import Radio from "./Radio"; -const labelTextStyles = (theme: DefaultNDSThemeType): CSSObject => ({ - fontSize: theme.fontSizes.small, - fontWeight: Number(theme.fontWeights.bold), - lineHeight: theme.lineHeights.smallTextBase, -}); - -const getRadioButtons = (props: any) => { - const radioButtons = React.Children.map(props.children, (radio) => { - const { value, disabled, required, onChange, ...radioProps } = radio.props; - return ( - - ); - }); - return radioButtons; -}; - interface RadioGroupProps { className?: string; id?: string; @@ -45,9 +18,13 @@ interface RadioGroupProps { children?: any; name?: string; disabled?: boolean; + defaultValue?: string; + checkedValue?: string; + default?: boolean; + onChange?: (e: React.ChangeEvent) => void; } -const RadioGroup = ({ +export default function RadioGroup({ className, id, errorMessage, @@ -56,7 +33,7 @@ const RadioGroup = ({ helpText, requirementText, ...props -}: RadioGroupProps) => { +}: RadioGroupProps) { const otherProps = { ...props, errorMessage, errorList }; const themeContext = useContext(ThemeContext); @@ -71,19 +48,31 @@ const RadioGroup = ({ ); -}; +} -RadioGroup.defaultProps = { - errorMessage: null, - errorList: null, - defaultValue: undefined, - checkedValue: undefined, - onChange: undefined, - className: undefined, - id: undefined, - helpText: null, - requirementText: null, - default: false, -}; +const labelTextStyles = (theme: DefaultNDSThemeType): CSSObject => ({ + fontSize: theme.fontSizes.small, + fontWeight: Number(theme.fontWeights.bold), + lineHeight: theme.lineHeights.smallTextBase, +}); -export default RadioGroup; +const getRadioButtons = (props: any) => { + const radioButtons = React.Children.map(props.children, (radio) => { + const { value, disabled, required, onChange, ...radioProps } = radio.props; + return ( + + ); + }); + + return radioButtons; +}; diff --git a/src/RangeContainer/RangeContainer.tsx b/src/RangeContainer/RangeContainer.tsx index 344bbcbdc..828db4418 100644 --- a/src/RangeContainer/RangeContainer.tsx +++ b/src/RangeContainer/RangeContainer.tsx @@ -14,16 +14,20 @@ type RangeContainerProps = { endComponent?: React.ReactNode; size?: ComponentSize; errorMessages?: (string | undefined)[]; + children?: React.ReactNode; }; -const RangeContainer: React.FC> = ({ - labelProps, +const RangeContainer = ({ startComponent, endComponent, errorMessages = [], + labelProps = { + ...FieldLabelDefaultProps, + labelText: "Range", + }, size, ...props -}) => { +}: RangeContainerProps) => { const spaceProps = getSubset(props, propTypes.space); const restProps = omitSubset(props, propTypes.space); @@ -45,14 +49,4 @@ const RangeContainer: React.FC> = ( ); }; -RangeContainer.defaultProps = { - labelProps: { - ...FieldLabelDefaultProps, - labelText: "Range", - }, - startComponent: null, - endComponent: null, - errorMessages: [], -}; - export default RangeContainer; diff --git a/src/Select/Select.tsx b/src/Select/Select.tsx index db67d1297..2b120975b 100644 --- a/src/Select/Select.tsx +++ b/src/Select/Select.tsx @@ -65,47 +65,12 @@ export type NDSSelectProps & CustomProps; -export const SelectDefaultProps = { - autocomplete: true, - disabled: undefined, - defaultValue: undefined, - error: undefined, - errorMessage: undefined, - errorList: undefined, - labelText: undefined, - helpText: undefined, - noOptionsMessage: undefined, - requirementText: undefined, - id: undefined, - initialIsOpen: undefined, - maxHeight: "248px", - menuPosition: "absolute" as MenuPosition, - menuPlacement: "bottom" as MenuPlacement, - multiselect: false, - name: undefined, - onBlur: undefined, - onChange: undefined, - placeholder: undefined, - required: false, - value: undefined, - className: undefined, - classNamePrefix: "ndsSelect", // a prefix is required in react-select top put classes on all buttons to apply style overrides - menuIsOpen: undefined, - onMenuOpen: undefined, - onMenuClose: undefined, - onInputChange: undefined, - components: undefined, - closeMenuOnSelect: true, -}; - const ReactSelect = React.forwardRef( >( { size, - autocomplete, options, labelText, - required, requirementText, helpText, disabled, @@ -114,8 +79,6 @@ const ReactSelect = React.forwardRef( error = !!(errorMessage || errorList), id, initialIsOpen, - maxHeight, - multiselect, onChange, placeholder, value, @@ -123,6 +86,14 @@ const ReactSelect = React.forwardRef( components, "aria-label": ariaLabel, windowThreshold = 300, + autocomplete = true, + maxHeight = "248px", + required = false, + menuPosition = "absolute" as MenuPosition, + menuPlacement = "bottom" as MenuPlacement, + multiselect, + classNamePrefix = "ndsSelect", + closeMenuOnSelect = true, ...props }: NDSSelectProps, ref @@ -190,6 +161,10 @@ const ReactSelect = React.forwardRef( }} aria-label={ariaLabel} options={options} + menuPosition={menuPosition} + menuPlacement={menuPlacement} + classNamePrefix={classNamePrefix} + closeMenuOnSelect={closeMenuOnSelect} {...props} /> @@ -243,10 +218,4 @@ function extractValue(options: NDSOptionType[] | NDSOptionType, isMulti: boolean } } -ReactSelect.defaultProps = { - ...SelectDefaultProps, - windowThreshold: 300, - filterOption: undefined, -}; - export default ReactSelect; diff --git a/src/StatusIndicator/StatusIndicator.tsx b/src/StatusIndicator/StatusIndicator.tsx index 541dfb7ff..adadcc709 100644 --- a/src/StatusIndicator/StatusIndicator.tsx +++ b/src/StatusIndicator/StatusIndicator.tsx @@ -57,28 +57,26 @@ interface Props extends SpaceProps, TypographyProps, FlexboxProps { type?: StatusIndicatorType; } -const StatusIndicator = styled.span(space, typography, flexbox, ({ theme, type }) => ({ - display: "inline-block", - fontWeight: theme.fontWeights.bold, - textTransform: "uppercase", - letterSpacing: ".05em", - borderRadius: theme.space.x1, - ...statusIndicatorStyles(theme)[type], -})); - -StatusIndicator.defaultProps = { - type: StatusIndicatorValues.neutral, - mt: "0", - mr: "0", - mb: "0", - ml: "0", - pt: "0", - pr: "x1", - pb: "0", - pl: "x1", - fontSize: "smaller", - lineHeight: "smallerText", - alignSelf: "center", -}; +const StatusIndicator = styled.span( + ({ theme, type = StatusIndicatorValues.neutral }) => ({ + margin: theme.space.none, + paddingTop: theme.space.none, + paddingRight: theme.space.x1, + paddingBottom: theme.space.none, + paddingLeft: theme.space.x1, + fontSize: theme.fontSizes.smaller, + lineHeight: theme.lineHeights.smallerText, + alignSelf: "center", + display: "inline-block", + fontWeight: theme.fontWeights.bold, + textTransform: "uppercase", + letterSpacing: ".05em", + borderRadius: theme.space.x1, + ...statusIndicatorStyles(theme)[type], + }), + space, + typography, + flexbox +); export default StatusIndicator; diff --git a/src/Table/BaseTable.tsx b/src/Table/BaseTable.tsx index e1cf47638..077dd0876 100644 --- a/src/Table/BaseTable.tsx +++ b/src/Table/BaseTable.tsx @@ -1,12 +1,10 @@ import React from "react"; import styled from "styled-components"; -import PropTypes from "prop-types"; import { space } from "styled-system"; -import propTypes from "@styled-system/prop-types"; import TableHead from "./TableHead"; import TableBody from "./TableBody"; import TableFoot from "./TableFoot"; -import { rowsPropType, RowType, Columns } from "./Table.types"; +import { RowType, Columns } from "./Table.types"; export type BaseTableProps = { columns: Columns; @@ -34,19 +32,19 @@ const StyledTable = styled.table(space, { }); function BaseTable({ - columns, - rows, noRowsContent = "No records have been created for this table.", keyField = "id", - id, - loading, + loading = false, footerRows = [], rowHovers = true, - compact, - className, - stickyHeader, + compact = false, + stickyHeader = false, onRowMouseEnter = () => {}, onRowMouseLeave = () => {}, + columns, + rows, + id, + className, ...props }: BaseTableProps) { return ( @@ -70,35 +68,4 @@ function BaseTable({ ); } -BaseTable.propTypes = { - ...propTypes.space, - columns: PropTypes.any, - rows: PropTypes.any, - noRowsContent: PropTypes.string, - keyField: PropTypes.string, - id: PropTypes.string, - loading: PropTypes.bool, - footerRows: rowsPropType, - rowHovers: PropTypes.bool, - compact: PropTypes.bool, - className: PropTypes.string, - stickyHeader: PropTypes.bool, - onRowMouseEnter: PropTypes.func, - onRowMouseLeave: PropTypes.func, -}; - -BaseTable.defaultProps = { - noRowsContent: "No records have been created for this table.", - keyField: "id", - id: undefined, - loading: false, - footerRows: [], - rowHovers: true, - compact: false, - className: undefined, - stickyHeader: false, - onRowMouseEnter: () => {}, - onRowMouseLeave: () => {}, -}; - export default BaseTable; diff --git a/src/Table/SortingColumnHeader.tsx b/src/Table/SortingColumnHeader.tsx index bfc22f98b..3f0327a56 100644 --- a/src/Table/SortingColumnHeader.tsx +++ b/src/Table/SortingColumnHeader.tsx @@ -1,13 +1,27 @@ import React from "react"; -import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { Text } from "../Type"; import { Flex } from "../Flex"; import { ControlIcon } from "../Button"; -const SortingColumnHeader = ({ onChange, label, ascending, active, ariaLabel }) => { +interface SortingColumnHeaderProps { + onChange?: React.MouseEventHandler; + ariaLabel?: string; + label?: string; + ascending?: boolean; + active?: boolean; +} + +function SortingColumnHeader({ + onChange, + label, + ariaLabel, + ascending = false, + active = false, +}: SortingColumnHeaderProps) { const { t } = useTranslation(); const defaultAriaLabel = ascending ? t("sort descending") : t("sort ascending"); + return ( {label} @@ -20,21 +34,6 @@ const SortingColumnHeader = ({ onChange, label, ascending, active, ariaLabel }) /> ); -}; - -SortingColumnHeader.propTypes = { - onChange: PropTypes.func.isRequired, - ariaLabel: PropTypes.string, - label: PropTypes.string, - ascending: PropTypes.bool, - active: PropTypes.bool, -}; - -SortingColumnHeader.defaultProps = { - ariaLabel: null, - label: null, - ascending: false, - active: false, -}; +} export default SortingColumnHeader; diff --git a/src/Table/StatefulTable.tsx b/src/Table/StatefulTable.tsx index 97bdb2e67..82d534deb 100644 --- a/src/Table/StatefulTable.tsx +++ b/src/Table/StatefulTable.tsx @@ -1,9 +1,12 @@ import React, { Component } from "react"; +import propTypes from "@styled-system/prop-types"; +import PropTypes from "prop-types"; import { Pagination } from "../Pagination"; import { getSubset } from "../utils/subset"; import BaseTable, { BaseTableProps } from "./BaseTable"; import { addExpandableControl } from "./addExpandableControl"; import { addSelectableControl } from "./addSelectableControl"; +import { rowsPropType } from "./Table.types"; export type StatefulTableProps = BaseTableProps & { selectedRows?: string[]; @@ -36,9 +39,20 @@ type StatefulTableState = { currentPage: number; paginatedRows: any; }; + class StatefulTable extends Component, StatefulTableState> { static defaultProps = { - ...BaseTable.defaultProps, + noRowsContent: "No records have been created for this table.", + keyField: "id", + id: undefined, + loading: false, + footerRows: [], + rowHovers: true, + compact: false, + className: undefined, + stickyHeader: false, + onRowMouseEnter: () => {}, + onRowMouseLeave: () => {}, hasSelectableRows: false, selectedRows: [], isHeaderSelected: false, @@ -224,7 +238,7 @@ class StatefulTable extends Component @@ -247,4 +261,21 @@ class StatefulTable extends Component({ ); } + Table.SortingHeader = SortingColumnHeader; export default Table; diff --git a/src/Table/TableBody.tsx b/src/Table/TableBody.tsx index 1e92e2bb1..d6582a929 100644 --- a/src/Table/TableBody.tsx +++ b/src/Table/TableBody.tsx @@ -97,18 +97,6 @@ const TableBodyRow = ({ ); }; -TableBodyRow.propTypes = { - row: rowPropType.isRequired, - columns: columnsPropType.isRequired, - rowHovers: PropTypes.bool.isRequired, - compact: PropTypes.bool.isRequired, - rowClassName: PropTypes.string, -}; - -TableBodyRow.defaultProps = { - rowClassName: undefined, -}; - const TableMessageContainer = ({ colSpan, children }) => ( @@ -117,11 +105,6 @@ const TableMessageContainer = ({ colSpan, children }) => ( ); -TableMessageContainer.propTypes = { - colSpan: PropTypes.number.isRequired, - children: PropTypes.node.isRequired, -}; - const LoadingContent = ({ colSpan }) => Loading...; LoadingContent.propTypes = { diff --git a/src/Table/TableCell.tsx b/src/Table/TableCell.tsx index 17b57651f..d51bf69ad 100644 --- a/src/Table/TableCell.tsx +++ b/src/Table/TableCell.tsx @@ -1,9 +1,9 @@ -import React from "react"; +import React, { CSSProperties } from "react"; import styled, { CSSObject } from "styled-components"; import { DefaultNDSThemeType } from "../theme.type"; type StyledTableCellProps = { - align?: any; + align?: CSSProperties["textAlign"]; compact?: boolean; theme?: DefaultNDSThemeType; }; @@ -21,14 +21,16 @@ const StyledTableCell: React.FC> = }; } ); + type TableCellProps = { column?: any; row?: any; colSpan?: number; - cellData?: object | React.ReactNode | boolean; + cellData?: Record | React.ReactNode | boolean; compact?: boolean; }; -const TableCell: React.FC> = ({ row, column, colSpan, cellData, compact }) => { + +const TableCell = ({ column = {}, row = {}, cellData = "", colSpan = undefined, compact = false }: TableCellProps) => { const cellRenderer = row.cellRenderer || column.cellRenderer; const { cellFormatter } = column; const isCustomCell = Boolean(cellRenderer); @@ -42,11 +44,5 @@ const TableCell: React.FC> = ({ row, col ); }; -TableCell.defaultProps = { - column: {}, - row: {}, - cellData: "", - colSpan: undefined, - compact: false, -}; + export default TableCell; diff --git a/src/Table/TableFoot.tsx b/src/Table/TableFoot.tsx index 88d6d47c9..0e9dcff48 100644 --- a/src/Table/TableFoot.tsx +++ b/src/Table/TableFoot.tsx @@ -3,7 +3,7 @@ import PropTypes from "prop-types"; import styled from "styled-components"; import TableCell from "./TableCell"; import StyledTh from "./StyledTh"; -import { columnsPropType, rowsPropType, rowPropType, RowType, Columns } from "./Table.types"; +import { columnsPropType, rowPropType, RowType, Columns } from "./Table.types"; const StyledFooterRow = styled.tr(({ theme }) => ({ "&:first-of-type": { @@ -58,9 +58,9 @@ TableFooterRow.propTypes = { function TableFoot({ columns, rows, - keyField, - loading, - compact, + keyField = "id", + loading = false, + compact = false, }: { columns: Columns; rows: RowType[]; @@ -71,18 +71,4 @@ function TableFoot({ return {renderRows(rows, columns, keyField, loading, compact)}; } -TableFoot.propTypes = { - columns: columnsPropType.isRequired, - rows: rowsPropType.isRequired, - keyField: PropTypes.string, - loading: PropTypes.bool, - compact: PropTypes.bool, -}; - -TableFoot.defaultProps = { - keyField: "id", - loading: false, - compact: false, -}; - export default TableFoot; diff --git a/src/Table/addExpandableControl.tsx b/src/Table/addExpandableControl.tsx index e8b4b318e..5531a3568 100644 --- a/src/Table/addExpandableControl.tsx +++ b/src/Table/addExpandableControl.tsx @@ -1,13 +1,20 @@ import React from "react"; -import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { ControlIcon } from "../Button"; -import { rowPropType } from "./Table.types"; import { SELECTABLE_COLUMN_DATA_KEY } from "./addSelectableControl"; const EXPANDABLE_COLUMN_DATA_KEY = "expanded"; -const ExpandCell = ({ row, onRowExpansionChange }) => { +type Row = Record>; + +interface ExpandCellProps { + row: Row; + onRowExpansionChange: (row: Row) => void; + collapseAriaLabel?: string; + expandAriaLabel?: string; +} + +const ExpandCell = ({ row, onRowExpansionChange }: ExpandCellProps) => { const expandRowHandler = () => onRowExpansionChange(row); const { t } = useTranslation(); const collapseLabel = row.collapseAriaLabel || t("collapse row"); @@ -25,18 +32,6 @@ const ExpandCell = ({ row, onRowExpansionChange }) => { ); }; -ExpandCell.propTypes = { - row: rowPropType.isRequired, - onRowExpansionChange: PropTypes.func, - collapseAriaLabel: PropTypes.string, - expandAriaLabel: PropTypes.string, -}; - -ExpandCell.defaultProps = { - onRowExpansionChange: null, - collapseAriaLabel: undefined, - expandAriaLabel: undefined, -}; const expandCellRenderer = (onRowExpansionChange) => (props) => ; const addExpandableColumn = ({ columns, onRowExpansionChange }) => { diff --git a/src/Table/addSelectableControl.tsx b/src/Table/addSelectableControl.tsx index 66a3cdc15..81d304ac1 100644 --- a/src/Table/addSelectableControl.tsx +++ b/src/Table/addSelectableControl.tsx @@ -1,8 +1,6 @@ import React from "react"; -import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { Checkbox } from "../Checkbox"; -import { rowPropType } from "./Table.types"; export const SELECTABLE_COLUMN_DATA_KEY = "selected"; @@ -24,15 +22,6 @@ const SelectCell = ({ row, onSelectRow }) => { return ; }; -SelectCell.propTypes = { - row: rowPropType.isRequired, - onSelectRow: PropTypes.func, -}; - -SelectCell.defaultProps = { - onSelectRow: null, -}; - const selectCellRenderer = (onSelectRow) => (props) => ; export const addSelectableControl = ({ diff --git a/src/Tabs/Tab.tsx b/src/Tabs/Tab.tsx index 3a765f6cc..9a1abdf2d 100644 --- a/src/Tabs/Tab.tsx +++ b/src/Tabs/Tab.tsx @@ -101,12 +101,10 @@ type TabProps = TabButtonProps & { label?: React.ReactNode; }; -const Tab: React.FC> = React.forwardRef(({ label, ...props }, ref) => ( +const Tab = React.forwardRef(({ label, ...props }, ref) => ( {label} )); -Tab.defaultProps = { - label: null, -}; + export default Tab; diff --git a/src/Tabs/TabScrollIndicator.tsx b/src/Tabs/TabScrollIndicator.tsx index c35ac5888..30f24b1c4 100644 --- a/src/Tabs/TabScrollIndicator.tsx +++ b/src/Tabs/TabScrollIndicator.tsx @@ -1,9 +1,11 @@ -// @ts-nocheck import styled from "styled-components"; import React from "react"; import { useTranslation } from "react-i18next"; import { Icon } from "../Icon"; -const TabScrollIndicatorButton = styled.button(({ side, width, theme }) => ({ + +type Side = "left" | "right"; + +const TabScrollIndicatorButton = styled.button<{ side: Side; width: string | number }>(({ side, width, theme }) => ({ position: "absolute", color: theme.colors.black, top: 0, @@ -37,34 +39,38 @@ const TabScrollIndicatorButton = styled.button(({ side, width, theme }) => ({ opacity: ".5", }, })); -function preventFocusMovement(e) { - e.preventDefault(); -} + type TabScrollIndicatorProps = { - onClick?: (...args: any[]) => any; - side?: "left" | "right"; + onClick?: React.MouseEventHandler; + side?: Side; width?: string | number; ariaLabelLeft?: string; ariaLabelRight?: string; }; + const TabScrollIndicator: React.FC> = ({ - onClick, - side, + side = "left", + width = 40, ariaLabelLeft, ariaLabelRight, + onClick, ...props }) => { const { t } = useTranslation(); - const handleClick = () => { - onClick(side); - }; + const rightArrowLabel = ariaLabelRight || t("next"); const leftArrowLabel = ariaLabelLeft || t("previous"); + + function preventFocusMovement(event: React.MouseEvent) { + event.preventDefault(); + } + return ( ); }; -TabScrollIndicator.defaultProps = { - onClick: () => {}, - side: "left", - width: 40, - ariaLabelLeft: undefined, - ariaLabelRight: undefined, -}; + export default TabScrollIndicator; diff --git a/src/Tabs/TabScrollIndicators.js b/src/Tabs/TabScrollIndicators.js deleted file mode 100644 index 52c372c6f..000000000 --- a/src/Tabs/TabScrollIndicators.js +++ /dev/null @@ -1,178 +0,0 @@ -// @ts-nocheck -import styled from "styled-components"; -import PropTypes from "prop-types"; -import React from "react"; -import smoothscroll from "smoothscroll-polyfill"; -import TabScrollIndicator from "./TabScrollIndicator"; - -const TabScrollIndicatorContainer = styled.div(({ width, theme }) => ({ - position: "absolute", - width, - height: theme.space.x5, -})); - -class TabScrollIndicators extends React.Component { - constructor(props) { - super(props); - - this.state = { - contentHiddenLeft: this.contentHiddenLeft(), - contentHiddenRight: this.contentHiddenRight(), - }; - - this.handleIndicatorClick = this.handleIndicatorClick.bind(this); - this.getScrollLeftValueByTabIndex = this.getScrollLeftValueByTabIndex.bind(this); - this.contentHiddenLeft = this.contentHiddenLeft.bind(this); - this.contentHiddenRight = this.contentHiddenRight.bind(this); - this.handleScroll = this.handleScroll.bind(this); - this.handleResize = this.handleResize.bind(this); - } - - componentDidMount() { - this.conditionallyUpdateState(); - smoothscroll.polyfill(); - } - - getScrollLeftValueByTabIndex(index) { - const { tabRefs } = this.props; - let scrollLeftSum = 0; - for (let i = 0; i < index; i += 1) { - scrollLeftSum += tabRefs[i].offsetWidth; - } - return scrollLeftSum; - } - - contentHiddenRight() { - const { tabContainerRef } = this.props; - if (!tabContainerRef.current) { - return false; - } - return ( - tabContainerRef.current.scrollLeft + tabContainerRef.current.offsetWidth < tabContainerRef.current.scrollWidth - ); - } - - contentHiddenLeft() { - const { tabContainerRef } = this.props; - if (!tabContainerRef.current) { - return false; - } - return ( - tabContainerRef.current.scrollLeft !== 0 && - tabContainerRef.current.offsetWidth < tabContainerRef.current.scrollWidth - ); - } - - findLastVisibleTab() { - const { tabContainerRef, tabRefs, indicatorWidth } = this.props; - const rightMarker = tabContainerRef.current.scrollLeft + tabContainerRef.current.offsetWidth - indicatorWidth; - let scrollLeftSum = 0; - - for (let i = 0; i < tabRefs.length; i += 1) { - scrollLeftSum += tabRefs[i].offsetWidth; - if (rightMarker <= scrollLeftSum) { - return i; - } - } - return null; - } - - findFirstVisibleTab() { - const { tabContainerRef, tabRefs, indicatorWidth } = this.props; - const leftMarker = tabContainerRef.current.scrollLeft + indicatorWidth; - let scrollLeftSum = 0; - - for (let i = 0; i < tabRefs.length; i += 1) { - scrollLeftSum += tabRefs[i].offsetWidth; - if (leftMarker <= scrollLeftSum) { - return i; - } - } - return null; - } - - handleScroll() { - this.conditionallyUpdateState(); - } - - handleResize() { - this.setState({ - contentHiddenLeft: this.contentHiddenLeft(), - contentHiddenRight: this.contentHiddenRight(), - }); - } - - conditionallyUpdateState() { - const { contentHiddenLeft, contentHiddenRight } = this.state; - const currentContentHiddenLeft = this.contentHiddenLeft(); - const currentContentHiddenRight = this.contentHiddenRight(); - - if (currentContentHiddenLeft !== contentHiddenLeft) { - this.setState({ contentHiddenLeft: currentContentHiddenLeft }); - } - - if (currentContentHiddenRight !== contentHiddenRight) { - this.setState({ contentHiddenRight: currentContentHiddenRight }); - } - } - - handleIndicatorClick(side) { - const { tabRefs, tabContainerRef, indicatorWidth } = this.props; - - if (side === "right") { - const lastVisibleTab = this.findLastVisibleTab(); - const scrollLeft = this.getScrollLeftValueByTabIndex(lastVisibleTab) - indicatorWidth; - this.applyScrollLeft(scrollLeft); - } else { - const firstVisibleTab = this.findFirstVisibleTab(); - const scrollLeft = - this.getScrollLeftValueByTabIndex(firstVisibleTab) + - indicatorWidth + - tabRefs[firstVisibleTab].offsetWidth - - tabContainerRef.current.offsetWidth; - this.applyScrollLeft(scrollLeft); - } - } - - applyScrollLeft(scrollLeft) { - const { tabContainerRef } = this.props; - tabContainerRef.current.scroll({ left: scrollLeft, behavior: "smooth" }); - } - - render() { - const { tabContainerRef, indicatorWidth, children } = this.props; - const { contentHiddenLeft, contentHiddenRight } = this.state; - - return ( - <> - - {contentHiddenLeft && ( - - )} - {contentHiddenRight && ( - - )} - - {children({ - handleScroll: this.handleScroll, - handleResize: this.handleResize, - })} - - ); - } -} - -TabScrollIndicators.propTypes = { - children: PropTypes.func.isRequired, - tabRefs: PropTypes.arrayOf(PropTypes.shape({ offsetWidth: PropTypes.number })), - tabContainerRef: PropTypes.shape({ current: PropTypes.object }), - indicatorWidth: PropTypes.number, -}; - -TabScrollIndicators.defaultProps = { - tabRefs: undefined, - tabContainerRef: undefined, - indicatorWidth: 40, -}; - -export default TabScrollIndicators; diff --git a/src/Tabs/TabScrollIndicators.tsx b/src/Tabs/TabScrollIndicators.tsx index 20f630636..3101577e9 100644 --- a/src/Tabs/TabScrollIndicators.tsx +++ b/src/Tabs/TabScrollIndicators.tsx @@ -151,9 +151,11 @@ class TabScrollIndicators extends React.Component( ( { + disabled = false, + required = false, + rows = 3, errorMessage, errorList, error = !!(errorMessage || errorList), - required, labelText, requirementText, helpText, id, className, - rows, isResizeable = true, size, ...props @@ -61,6 +62,7 @@ const Textarea = forwardRef( rows={rows} isResizeable={isResizeable} size={componentSize} + disabled={disabled} {...restProps} /> @@ -70,17 +72,4 @@ const Textarea = forwardRef( } ); -Textarea.defaultProps = { - className: undefined, - id: undefined, - disabled: false, - errorMessage: undefined, - errorList: undefined, - required: false, - labelText: undefined, - helpText: undefined, - requirementText: undefined, - rows: 3, -}; - export default Textarea; diff --git a/src/TimePicker/TimePicker.tsx b/src/TimePicker/TimePicker.tsx index 31e45112b..783e25206 100644 --- a/src/TimePicker/TimePicker.tsx +++ b/src/TimePicker/TimePicker.tsx @@ -149,6 +149,7 @@ const TimePicker: React.FC> = forwardRe error, disabled, size, + ...props }, inputRef diff --git a/src/TimeRange/TimeRange.tsx b/src/TimeRange/TimeRange.tsx index 1af53e6cb..b04788a7c 100644 --- a/src/TimeRange/TimeRange.tsx +++ b/src/TimeRange/TimeRange.tsx @@ -40,8 +40,6 @@ const TimeRange = forwardRef( errorMessage, defaultStartTime, defaultEndTime, - disableRangeValidation, - labelProps, minTime, maxTime, interval, @@ -50,6 +48,11 @@ const TimeRange = forwardRef( endTimeProps, startTimeProps, size, + disableRangeValidation = false, + labelProps = { + ...FieldLabelDefaultProps, + labelText: DEFAULT_LABEL, + }, ...props }: TimeRangeProps, ref @@ -176,24 +179,4 @@ const TimeRange = forwardRef( } ); -TimeRange.defaultProps = { - timeFormat: undefined, - onRangeChange: null, - onStartTimeChange: null, - onEndTimeChange: null, - errorMessage: null, - defaultStartTime: null, - defaultEndTime: null, - disableRangeValidation: false, - labelProps: { - ...FieldLabelDefaultProps, - labelText: DEFAULT_LABEL, - }, - minTime: null, - maxTime: null, - interval: undefined, - startAriaLabel: undefined, - endAriaLabel: undefined, -}; - export default TimeRange; diff --git a/src/Toast/Toast.tsx b/src/Toast/Toast.tsx index 15b2211b6..02fdec9c2 100644 --- a/src/Toast/Toast.tsx +++ b/src/Toast/Toast.tsx @@ -33,12 +33,12 @@ export const toastAnimationConfig = { }; export const Toast = ({ - triggered, + triggered = false, + isCloseable = false, + showDuration = TOAST_SHOW_DURATION, onHide, onShow, - isCloseable, children, - showDuration, onHidden, zIndex, ...props @@ -139,13 +139,4 @@ export const Toast = ({ ); }; -Toast.defaultProps = { - triggered: false, - isCloseable: false, - showDuration: TOAST_SHOW_DURATION, - onShow: () => {}, - onHide: () => {}, - onHidden: () => {}, -}; - export default Toast; diff --git a/src/ToastContainer/ToastContainer.tsx b/src/ToastContainer/ToastContainer.tsx index 6633f683c..03db1cc8f 100644 --- a/src/ToastContainer/ToastContainer.tsx +++ b/src/ToastContainer/ToastContainer.tsx @@ -1,8 +1,8 @@ import React, { useEffect } from "react"; import { toast as _toast, Toaster, ToasterProps, useToasterStore } from "react-hot-toast"; import { useTheme } from "styled-components"; -import { TOAST_SHOW_DURATION } from "../Toast/Toast"; import numberFromDimension from "../utils/numberFromDimension"; +import { TOAST_SHOW_DURATION } from "../Toast/Toast"; import { ToastOptions } from "./ToastFunction"; type ToastContainerProps = { @@ -11,7 +11,15 @@ type ToastContainerProps = { toastOptions?: ToastOptions; } & Omit; -const ToastContainer = ({ gap, maxVisibleToasts, toastOptions, ...props }: ToastContainerProps) => { +const ToastContainer = ({ + gap, + position = "bottom-center", + reverseOrder = false, + containerClassName = "nds-toast-container", + toastOptions = { duration: TOAST_SHOW_DURATION }, + maxVisibleToasts = 8, + ...props +}: ToastContainerProps) => { const theme = useTheme(); const { toasts } = useToasterStore(); @@ -28,17 +36,12 @@ const ToastContainer = ({ gap, maxVisibleToasts, toastOptions, ...props }: Toast toastOptions={{ custom: { ...toastOptions }, }} + position={position} + reverseOrder={reverseOrder} + containerClassName={containerClassName} {...props} /> ); }; -ToastContainer.defaultProps = { - position: "bottom-center", - reverseOrder: false, - containerClassName: "nds-toast-container", - toastOptions: { duration: TOAST_SHOW_DURATION }, - maxVisibleToasts: 8, -}; - export default ToastContainer; diff --git a/src/Toggle/Toggle.tsx b/src/Toggle/Toggle.tsx index 5bb969d7c..b9c80184c 100644 --- a/src/Toggle/Toggle.tsx +++ b/src/Toggle/Toggle.tsx @@ -1,5 +1,4 @@ import React, { useState, useContext } from "react"; -import PropTypes from "prop-types"; import { ThemeContext } from "styled-components"; import { SpaceProps } from "styled-system"; import propTypes from "@styled-system/prop-types"; @@ -23,15 +22,10 @@ type MaybeToggleTitleProps = React.ComponentPropsWithRef<"div"> & { labelText?: string; requirementText?: string; helpText?: string; - children?: any; + children?: React.ReactNode; }; -const MaybeToggleTitle: React.FC> = ({ - labelText, - requirementText, - helpText, - children, - ...props -}) => { + +function MaybeToggleTitle({ labelText, requirementText, helpText, children, ...props }: MaybeToggleTitleProps) { const themeContext = useContext(ThemeContext); return labelText ? (
@@ -45,7 +39,7 @@ const MaybeToggleTitle: React.FC> ) : ( <>{children} ); -}; +} type BaseToggleProps = SpaceProps & { onChange?: (...args: any[]) => any; @@ -57,7 +51,7 @@ type BaseToggleProps = SpaceProps & { id?: string; className?: string; required?: boolean; - helpText?: any; + helpText?: string; labelText?: string; requirementText?: string; error?: boolean; @@ -93,6 +87,7 @@ const BaseToggle = ({ const componentSize = useComponentSize(size); const spaceProps = getSubset(props, propTypes.space); const restProps = omitSubset(props, propTypes.space); + return ( {}, - toggled: undefined, - disabled: false, - onText: undefined, - offText: undefined, - id: undefined, - className: undefined, - required: false, - helpText: undefined, - labelText: undefined, - requirementText: undefined, - error: false, - onClick: () => {}, -}; - type StatefulToggleProps = BaseToggleProps & { defaultToggled?: boolean; onClick?: boolean; @@ -159,16 +138,6 @@ const StatefulToggle = ({ defaultToggled, onClick, disabled, ...props }: Statefu return ; }; -StatefulToggle.propTypes = { - defaultToggled: PropTypes.bool, - onClick: PropTypes.func, -}; - -StatefulToggle.defaultProps = { - defaultToggled: undefined, - onClick: () => {}, -}; - type ToggleProps = StatefulToggleProps; const Toggle = ({ toggled, ...props }: ToggleProps) => diff --git a/src/Toggle/ToggleButton.tsx b/src/Toggle/ToggleButton.tsx index febf07ad8..eda84af01 100644 --- a/src/Toggle/ToggleButton.tsx +++ b/src/Toggle/ToggleButton.tsx @@ -8,9 +8,10 @@ import { default as theme } from "../theme"; import { AnimatedBox } from "../Box"; type SwitchProps = { + children?: React.ReactNode; disabled?: boolean; toggled?: boolean; - onClick?: (event: React.MouseEvent) => void; + onClick?: (event: React.MouseEvent) => void; }; type SliderProps = { @@ -48,23 +49,25 @@ const animationConfig: AnimationConfig = { scale: 1.08, }; -const Switch: React.FC> = ({ children, disabled, toggled, onClick }) => ( - - {children} - -); +function Switch({ children, disabled, toggled, onClick }: SwitchProps) { + return ( + + {children} + + ); +} const Slider: React.FC> = ({ disabled, children }) => ( > = React.forwardRef((props, ref) => { +const ToggleButton = React.forwardRef, ToggleButtonProps>((props, ref) => { const { disabled, defaultToggled, toggled } = props; const inputRef = useRef(null); @@ -137,9 +140,4 @@ const ToggleButton: React.FC> = React ); }); -ToggleButton.defaultProps = { - defaultToggled: undefined, - disabled: false, -}; - export default ToggleButton; diff --git a/src/Tooltip/Tooltip.tsx b/src/Tooltip/Tooltip.tsx index c90fd3736..c5062e3ed 100644 --- a/src/Tooltip/Tooltip.tsx +++ b/src/Tooltip/Tooltip.tsx @@ -26,8 +26,20 @@ export type TooltipProps = { children?: React.ReactNode; }; -const Tooltip: React.FC> = React.forwardRef( - ({ className, tooltip, maxWidth, children, placement, showDelay, hideDelay, defaultOpen }, ref) => ( +const Tooltip = React.forwardRef( + ( + { + showDelay = "100", + hideDelay = "350", + defaultOpen = false, + placement = "bottom", + maxWidth = "24em", + className, + tooltip, + children, + }, + ref + ) => ( > = React.forwardRe ) ); -Tooltip.defaultProps = { - showDelay: "100", - hideDelay: "350", - defaultOpen: false, - className: undefined, - placement: "bottom", - maxWidth: "24em", -}; - export default Tooltip; diff --git a/src/TruncatedText/MaybeTooltip.tsx b/src/TruncatedText/MaybeTooltip.tsx index 2b01d7127..dd72e2cd2 100644 --- a/src/TruncatedText/MaybeTooltip.tsx +++ b/src/TruncatedText/MaybeTooltip.tsx @@ -1,5 +1,4 @@ import React from "react"; -import PropTypes from "prop-types"; import { Tooltip } from "../Tooltip"; import { TooltipProps } from "../Tooltip/Tooltip"; @@ -7,18 +6,8 @@ type MaybeTooltipProps = TooltipProps & { showTooltip?: boolean; }; -const MaybeTooltip = ({ children, showTooltip, ...props }: MaybeTooltipProps) => { +const MaybeTooltip = ({ children = "", showTooltip = true, ...props }: MaybeTooltipProps) => { return showTooltip ? {children} : <>{children}; }; -MaybeTooltip.propTypes = { - children: PropTypes.node, - showTooltip: PropTypes.bool, -}; - -MaybeTooltip.defaultProps = { - children: "", - showTooltip: true, -}; - export default MaybeTooltip; diff --git a/src/TruncatedText/TruncatedText.tsx b/src/TruncatedText/TruncatedText.tsx index d82dd26c9..8174bc403 100644 --- a/src/TruncatedText/TruncatedText.tsx +++ b/src/TruncatedText/TruncatedText.tsx @@ -1,37 +1,41 @@ import React from "react"; -import PropTypes from "prop-types"; import { Text } from "../Type"; import { TruncatedTextProps } from "./TruncatedTextProps"; import TruncatedTextFillWidth from "./TruncatedTextFillWidth"; import TruncatedTextMaxCharacters from "./TruncatedTextMaxCharacters"; -const TruncatedText = ({ fullWidth, children, ...props }: TruncatedTextProps) => +const TruncatedText = ({ + indicator = "...", + element = , + maxCharacters = 20, + fullWidth = false, + showTooltip = true, + "data-testid": dataTestId = "truncated-text", + children, + ...props +}: TruncatedTextProps) => fullWidth ? ( - {children} + + {children} + ) : ( - {children} + + {children} + ); -TruncatedText.propTypes = { - children: PropTypes.node, - indicator: PropTypes.string, - element: PropTypes.node, - maxCharacters: PropTypes.number, - showTooltip: PropTypes.bool, - fullWidth: PropTypes.bool, - "data-testid": PropTypes.string, - tooltipProps: PropTypes.shape({}), -}; - -TruncatedText.defaultProps = { - children: undefined, - indicator: "...", - element: , - maxCharacters: 20, - fullWidth: false, - showTooltip: true, - "data-testid": "truncated-text", - tooltipProps: undefined, -}; - export default TruncatedText; diff --git a/src/TruncatedText/TruncatedTextProps.ts b/src/TruncatedText/TruncatedTextProps.ts index ea02843d4..72074eb5d 100644 --- a/src/TruncatedText/TruncatedTextProps.ts +++ b/src/TruncatedText/TruncatedTextProps.ts @@ -1,10 +1,11 @@ +import { ReactElement } from "react"; import { TooltipProps } from "../Tooltip/Tooltip"; import { TextProps } from "../Type"; export interface TruncatedTextProps extends TextProps { children?: string; indicator?: string; - element?: any; + element?: ReactElement; maxCharacters?: number; showTooltip?: boolean; fullWidth?: boolean; diff --git a/src/Type/Text.tsx b/src/Type/Text.tsx index d47c83383..ba129cab7 100644 --- a/src/Type/Text.tsx +++ b/src/Type/Text.tsx @@ -1,4 +1,4 @@ -import styled, { CSSObject } from "styled-components"; +import styled from "styled-components"; import type { DefaultNDSThemeType } from "../theme.type"; import { addStyledProps, StyledProps } from "../StyledProps"; @@ -22,7 +22,7 @@ export type TextProps = React.HTMLAttributes & { } & StyledProps & { theme?: DefaultNDSThemeType }; const Text = styled.p( - ({ disabled, textTransform, inline, theme }): CSSObject => ({ + ({ disabled = false, textTransform, inline = false, theme }) => ({ textTransform, color: "currentColor", marginTop: 0, @@ -35,8 +35,4 @@ const Text = styled.p( addStyledProps ); -Text.defaultProps = { - inline: false, - disabled: false, -}; export default Text; diff --git a/src/Validation/InlineValidation.tsx b/src/Validation/InlineValidation.tsx index c6ae74252..4656dcfff 100644 --- a/src/Validation/InlineValidation.tsx +++ b/src/Validation/InlineValidation.tsx @@ -1,10 +1,10 @@ import React from "react"; import styled from "styled-components"; +import { SpaceProps } from "styled-system"; import { Text } from "../Type"; import { Icon } from "../Icon"; import { Flex } from "../Flex"; import mapErrorsToList from "./mapErrorsToList"; -import { SpaceProps } from "styled-system"; const Wrapper = styled.div(({ theme }) => ({ [`${Text}`]: { @@ -22,14 +22,14 @@ type InlineValidationProps = SpaceProps & { children?: React.ReactNode; }; -const InlineValidation: React.FC> = ({ +export default function InlineValidation({ className, errorMessage, errorList, children, ...boxProps -}) => - errorMessage || errorList ? ( +}: InlineValidationProps) { + return errorMessage || errorList ? ( @@ -39,11 +39,4 @@ const InlineValidation: React.FC> ) : null; - -InlineValidation.defaultProps = { - className: undefined, - errorMessage: undefined, - errorList: undefined, - children: undefined, -}; -export default InlineValidation; +} diff --git a/src/locales.const.ts b/src/locales.const.ts index 5871a4f1a..0aa7da795 100644 --- a/src/locales.const.ts +++ b/src/locales.const.ts @@ -11,7 +11,7 @@ export const NDS_TO_DATE_FN_LOCALES_MAP = { pt_BR: ptBR, ro_RO: ro, zh_CN: zhCN, -}; +} as const; export const ALL_NDS_LOCALES = [ { diff --git a/src/utils/DetectOutsideClick.js b/src/utils/DetectOutsideClick.js index 45f8b5c3a..126466ba4 100644 --- a/src/utils/DetectOutsideClick.js +++ b/src/utils/DetectOutsideClick.js @@ -1,7 +1,6 @@ import React from "react"; -import PropTypes from "prop-types"; -class DetectOutsideClick extends React.Component { +export default class DetectOutsideClick extends React.Component { constructor(props) { super(props); @@ -44,16 +43,3 @@ class DetectOutsideClick extends React.Component { return <>{children}; } } - -DetectOutsideClick.propTypes = { - onClick: PropTypes.func.isRequired, - clickRef: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.arrayOf(PropTypes.shape({}))]), - children: PropTypes.node, -}; - -DetectOutsideClick.defaultProps = { - clickRef: null, - children: undefined, -}; - -export default DetectOutsideClick; diff --git a/src/utils/PreventBodyElementScrolling.js b/src/utils/PreventBodyElementScrolling.js index 25becd0d4..cc340566f 100644 --- a/src/utils/PreventBodyElementScrolling.js +++ b/src/utils/PreventBodyElementScrolling.js @@ -1,8 +1,7 @@ import React from "react"; -import PropTypes from "prop-types"; import { disableBodyScroll, clearAllBodyScrollLocks } from "body-scroll-lock"; -class PreventBodyElementScrolling extends React.Component { +export default class PreventBodyElementScrolling extends React.Component { componentDidMount() { const { scrollableRef } = this.props; const refs = Array.isArray(scrollableRef) ? scrollableRef : [scrollableRef]; @@ -22,14 +21,3 @@ class PreventBodyElementScrolling extends React.Component { return <>{children}; } } - -PreventBodyElementScrolling.propTypes = { - children: PropTypes.node, - scrollableRef: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.arrayOf(PropTypes.shape({}))]), -}; - -PreventBodyElementScrolling.defaultProps = { - children: null, - scrollableRef: null, -}; -export default PreventBodyElementScrolling; diff --git a/src/utils/localized-date-fns.js b/src/utils/localized-date-fns.js deleted file mode 100644 index d90f4ee0a..000000000 --- a/src/utils/localized-date-fns.js +++ /dev/null @@ -1,5 +0,0 @@ -import { format } from "date-fns"; -import { NDS_TO_DATE_FN_LOCALES_MAP } from "../locales.const"; - -export const localizedFormat = (date, stringFormat, ndsLocale) => - format(date, stringFormat, { locale: NDS_TO_DATE_FN_LOCALES_MAP[ndsLocale] }); diff --git a/src/utils/localized-date-fns.ts b/src/utils/localized-date-fns.ts new file mode 100644 index 000000000..abf799712 --- /dev/null +++ b/src/utils/localized-date-fns.ts @@ -0,0 +1,6 @@ +import { format } from "date-fns"; +import { NDS_TO_DATE_FN_LOCALES_MAP } from "../locales.const"; + +export function localizedFormat(date: number, dateFormat: string, ndsLocale: string): string { + return format(date, dateFormat, { locale: NDS_TO_DATE_FN_LOCALES_MAP[ndsLocale] }); +} From 4b71cef7a6d88227034a98f534fb427224d27ec6 Mon Sep 17 00:00:00 2001 From: Haider Alshamma Date: Fri, 6 Sep 2024 16:40:32 -0400 Subject: [PATCH 2/5] fix: improve types --- src/BrandedNavBar/MobileMenu.tsx | 5 ++--- src/BrandedNavBar/NavBarDropdownMenu.tsx | 2 -- src/Button/ControlIcon.tsx | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/BrandedNavBar/MobileMenu.tsx b/src/BrandedNavBar/MobileMenu.tsx index 3003d3990..41b1b9a23 100644 --- a/src/BrandedNavBar/MobileMenu.tsx +++ b/src/BrandedNavBar/MobileMenu.tsx @@ -8,7 +8,6 @@ import { BrandingText } from "../Branding"; import { DropdownLink, DropdownText } from "../DropdownMenu"; import { Icon } from "../Icon"; import { Link } from "../Link"; -import { LinkProps } from "../Link/Link"; import { addStyledProps } from "../StyledProps"; import NulogyLogo from "./NulogyLogo"; import { TriggerFunctionProps } from "./TriggerFunctionProps"; @@ -163,7 +162,7 @@ const getSubMenuHeading = (layer, name) => type ThemeColorObject = { textColor?: string; background?: string; - logoColor?: string; + logoColor?: "white" | "blue"; }; type MenuItem = { @@ -237,7 +236,7 @@ const BaseMobileMenu: React.FC> = ( }) => ( ); -BaseMobileMenu.propTypes = { - menuData: PropTypes.shape({ - primaryMenu: PropTypes.arrayOf(PropTypes.shape({})), - secondaryMenu: PropTypes.arrayOf(PropTypes.shape({})), - }), - subtext: PropTypes.string, - includeSubtext: PropTypes.bool, - closeMenu: PropTypes.func, - themeColorObject: PropTypes.shape(ThemeColorObjectPropTypes), -}; - BaseMobileMenu.defaultProps = { menuData: null, subtext: null, diff --git a/src/NavBar/NavBar.tsx b/src/NavBar/NavBar.tsx index c982f9495..6120dc660 100644 --- a/src/NavBar/NavBar.tsx +++ b/src/NavBar/NavBar.tsx @@ -1,5 +1,4 @@ import React from "react"; -import PropTypes from "prop-types"; import styled from "styled-components"; import { themeGet } from "@styled-system/theme-get"; import ReactResizeDetector from "react-resize-detector"; @@ -120,22 +119,6 @@ const MediumNavBar: React.FC> = ({ ); }; -export const MenuDataPropTypes = { - primaryMenu: PropTypes.arrayOf(isValidMenuItem), - secondaryMenu: PropTypes.arrayOf(isValidMenuItem), - search: PropTypes.shape({ - onSubmit: PropTypes.func, - }), -}; - -MediumNavBar.propTypes = { - subtext: PropTypes.string, - brandingLinkHref: PropTypes.string, - menuData: PropTypes.shape(MenuDataPropTypes), - brandingLinkTo: PropTypes.string, - themeColor: PropTypes.oneOf(["blue", "white"]), -}; - MediumNavBar.defaultProps = { subtext: null, brandingLinkHref: "/", @@ -192,10 +175,6 @@ export const MenuIcon = ({ isOpen }) => { return ; }; -MenuIcon.propTypes = { - isOpen: PropTypes.bool, -}; - MenuIcon.defaultProps = { isOpen: false, }; @@ -219,13 +198,6 @@ const NavBar = (props) => ( ); -NavBar.propTypes = { - menuData: PropTypes.shape(MenuDataPropTypes), - className: PropTypes.string, - breakpointUpper: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - themeColor: PropTypes.oneOf(["blue", "white"]), -}; - NavBar.defaultProps = { menuData: null, className: undefined, diff --git a/src/NavBar/NavBarDropdownMenu.tsx b/src/NavBar/NavBarDropdownMenu.tsx index 60f215d93..9b21c031c 100644 --- a/src/NavBar/NavBarDropdownMenu.tsx +++ b/src/NavBar/NavBarDropdownMenu.tsx @@ -1,6 +1,5 @@ // @ts-nocheck import React from "react"; -import PropTypes from "prop-types"; import { Manager, Reference, Popper } from "react-popper"; import { DetectOutsideClick, withMenuState, PopperArrow } from "../utils"; import DropdownMenuContainer from "../DropdownMenu/DropdownMenuContainer"; @@ -129,22 +128,6 @@ class StatelessNavBarDropdownMenu extends React.Component { } /* eslint-enable react/destructuring-assignment */ -StatelessNavBarDropdownMenu.propTypes = { - children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired, - trigger: PropTypes.oneOfType([PropTypes.node, PropTypes.func]).isRequired, - menuState: PropTypes.shape({ - isOpen: PropTypes.bool, - openMenu: PropTypes.func, - closeMenu: PropTypes.func, - toggleMenu: PropTypes.func, - }).isRequired, - showArrow: PropTypes.bool, - placement: PropTypes.oneOf(["bottom-start", "right-start"]), - modifiers: PropTypes.shape({}), - triggerTogglesMenuState: PropTypes.bool, - dropdownMenuContainerEventHandlers: PropTypes.func, -}; - StatelessNavBarDropdownMenu.defaultProps = { showArrow: true, placement: "bottom-start", @@ -155,11 +138,6 @@ StatelessNavBarDropdownMenu.defaultProps = { const NavBarDropdownMenu = withMenuState(StatelessNavBarDropdownMenu); -NavBarDropdownMenu.propTypes = { - showDelay: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - hideDelay: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), -}; - NavBarDropdownMenu.defaultProps = { showDelay: "0", hideDelay: "100", diff --git a/src/NavBar/SmallNavBar.tsx b/src/NavBar/SmallNavBar.tsx index 0c082fc9d..429fa3245 100644 --- a/src/NavBar/SmallNavBar.tsx +++ b/src/NavBar/SmallNavBar.tsx @@ -1,6 +1,5 @@ // @ts-nocheck import React from "react"; -import PropTypes from "prop-types"; import { Branding } from "../Branding"; import { Flex } from "../Flex"; import theme from "../theme"; @@ -10,7 +9,6 @@ import MobileMenu from "./MobileMenu"; import { BrandingLink, getThemeColor, - MenuDataPropTypes, MenuIcon, MobileMenuTrigger, NavBarBackground, @@ -95,21 +93,6 @@ class SmallNavBarNoState extends React.Component { } } -SmallNavBarNoState.propTypes = { - menuState: PropTypes.shape({ - isOpen: PropTypes.bool, - toggleMenu: PropTypes.func, - closeMenu: PropTypes.func, - }).isRequired, - menuData: PropTypes.shape(MenuDataPropTypes), - subtext: PropTypes.string, - brandingLinkHref: PropTypes.string, - brandingLinkTo: PropTypes.string, - breakpointLower: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - width: PropTypes.number, - themeColor: PropTypes.oneOf(["blue", "white"]), -}; - SmallNavBarNoState.defaultProps = { menuData: null, subtext: null, diff --git a/src/NavBar/SubMenuTrigger.tsx b/src/NavBar/SubMenuTrigger.tsx index e4a332cb2..608511d47 100644 --- a/src/NavBar/SubMenuTrigger.tsx +++ b/src/NavBar/SubMenuTrigger.tsx @@ -1,6 +1,5 @@ import React from "react"; import styled from "styled-components"; -import PropTypes from "prop-types"; import theme from "../theme"; import { Icon } from "../Icon"; import NavBarDropdownMenu from "./NavBarDropdownMenu"; @@ -50,11 +49,6 @@ const SubMenuTriggerButton = React.forwardRef(({ )); -SubMenuTriggerButton.propTypes = { - name: PropTypes.string.isRequired, - isOpen: PropTypes.bool, -}; - SubMenuTriggerButton.defaultProps = { isOpen: false, }; @@ -83,12 +77,6 @@ const SubMenuTrigger = (props) => { ); }; -SubMenuTrigger.propTypes = { - name: PropTypes.string.isRequired, - menuData: PropTypes.arrayOf(PropTypes.shape({})), - onItemClick: PropTypes.func, -}; - SubMenuTrigger.defaultProps = { menuData: null, onItemClick: null, diff --git a/src/NavBar/isValidMenuItem.tsx b/src/NavBar/isValidMenuItem.tsx index 466596d72..e058cb3d7 100644 --- a/src/NavBar/isValidMenuItem.tsx +++ b/src/NavBar/isValidMenuItem.tsx @@ -1,5 +1,3 @@ -import PropTypes from "prop-types"; - const isValidMenuItem = function validArrayItem(arr, idx, componentName, location, propFullName) { const obj = arr[idx]; @@ -9,19 +7,6 @@ const isValidMenuItem = function validArrayItem(arr, idx, componentName, locatio ); } - PropTypes.checkPropTypes( - { - name: PropTypes.node.isRequired, - ariaLabel: PropTypes.string, - href: PropTypes.string, - items: PropTypes.arrayOf(isValidMenuItem), - render: PropTypes.func, - }, - obj, - propFullName, - componentName - ); - let numberOfDefiningKeys = 0; const definingKeys = ["href", "items", "render"]; const keys = Object.keys(obj); diff --git a/src/NavBarSearch/NavBarSearch.js b/src/NavBarSearch/NavBarSearch.js index 9e180c99a..6833d1688 100644 --- a/src/NavBarSearch/NavBarSearch.js +++ b/src/NavBarSearch/NavBarSearch.js @@ -1,6 +1,5 @@ import React from "react"; import styled from "styled-components"; -import PropTypes from "prop-types"; import { darken, transparentize } from "polished"; import { useTranslation } from "react-i18next"; import { Flex } from "../Flex"; @@ -73,11 +72,6 @@ const NavBarSearch = styled(BaseNavBarSearch)({ }, }); -BaseNavBarSearch.propTypes = { - name: PropTypes.string, - onSubmit: PropTypes.func, -}; - BaseNavBarSearch.defaultProps = { name: "global-search", onSubmit: () => {}, diff --git a/src/Switcher/Switch.tsx b/src/Switcher/Switch.tsx index 46dc37352..6a8197b19 100644 --- a/src/Switcher/Switch.tsx +++ b/src/Switcher/Switch.tsx @@ -1,6 +1,5 @@ import React from "react"; import styled from "styled-components"; -import PropTypes from "prop-types"; import { variant } from "styled-system"; import numberFromDimension from "../utils/numberFromDimension"; import { ComponentSize } from "../NDSProvider/ComponentSizeContext"; @@ -62,10 +61,4 @@ const SwitchButton = styled.button( }) ); -Switch.propTypes = { - children: PropTypes.node, - selected: PropTypes.bool, - value: PropTypes.string, -}; - export default Switch; diff --git a/src/Switcher/Switcher.tsx b/src/Switcher/Switcher.tsx index 66302c2a3..0c8a9a4ea 100644 --- a/src/Switcher/Switcher.tsx +++ b/src/Switcher/Switcher.tsx @@ -1,5 +1,4 @@ import React, { ReactElement } from "react"; -import PropTypes from "prop-types"; import { Box } from "../Box"; import FocusManager from "../utils/ts/FocusManager"; import type { ComponentSize } from "../NDSProvider/ComponentSizeContext"; @@ -63,10 +62,4 @@ const Switcher: React.FC> = ({ size, sele ); }; -Switcher.propTypes = { - children: PropTypes.arrayOf(PropTypes.element), - selected: PropTypes.string, - onChange: PropTypes.func, -}; - export default Switcher; diff --git a/src/Table/StatefulTable.tsx b/src/Table/StatefulTable.tsx index 82d534deb..efcc9a373 100644 --- a/src/Table/StatefulTable.tsx +++ b/src/Table/StatefulTable.tsx @@ -1,12 +1,27 @@ import React, { Component } from "react"; import propTypes from "@styled-system/prop-types"; -import PropTypes from "prop-types"; import { Pagination } from "../Pagination"; -import { getSubset } from "../utils/subset"; +import { pick } from "../utils/subset"; import BaseTable, { BaseTableProps } from "./BaseTable"; import { addExpandableControl } from "./addExpandableControl"; import { addSelectableControl } from "./addSelectableControl"; -import { rowsPropType } from "./Table.types"; + +const propNames = [ + ...Object.keys(propTypes.space), + "columns", + "rows", + "noRowsContent", + "keyField", + "id", + "loading", + "footerRows", + "rowHovers", + "compact", + "className", + "stickyHeader", + "onRowMouseEnter", + "onRowMouseLeave", +]; export type StatefulTableProps = BaseTableProps & { selectedRows?: string[]; @@ -238,7 +253,7 @@ class StatefulTable extends Component @@ -261,21 +276,4 @@ class StatefulTable extends Component = { } & ({ key: Key; dataKey?: never | undefined } | { dataKey: Key; key?: never | undefined }); export type Columns = ColumnType[]; - -export const columnPropType = PropTypes.shape({ - align: PropTypes.oneOf(["right", "left", "center"]), - label: PropTypes.string, - dataKey: PropTypes.oneOf([PropTypes.string, PropTypes.number]), - key: PropTypes.oneOf([PropTypes.string, PropTypes.number]), - cellFormatter: PropTypes.func, - cellRenderer: PropTypes.func, - headerRenderer: PropTypes.func, - width: PropTypes.string, -}); - -export const rowPropType = PropTypes.objectOf( - PropTypes.oneOfType([ - PropTypes.number, - PropTypes.string, - PropTypes.bool, - PropTypes.func, - PropTypes.node, - PropTypes.shape({}), - ]) -); - -export const columnsPropType = PropTypes.arrayOf(columnPropType); - -export const rowsPropType = PropTypes.arrayOf(rowPropType); diff --git a/src/Table/TableBody.tsx b/src/Table/TableBody.tsx index d6582a929..36beeabd8 100644 --- a/src/Table/TableBody.tsx +++ b/src/Table/TableBody.tsx @@ -1,9 +1,7 @@ import React from "react"; -import PropTypes from "prop-types"; import styled from "styled-components"; import { Box } from "../Box"; import { DefaultNDSThemeType } from "../theme.type"; -import { columnsPropType, rowPropType } from "./Table.types"; import TableCell from "./TableCell"; const StyledMessageContainer = styled(Box)(({ theme }) => ({ @@ -107,10 +105,6 @@ const TableMessageContainer = ({ colSpan, children }) => ( const LoadingContent = ({ colSpan }) => Loading...; -LoadingContent.propTypes = { - colSpan: PropTypes.number.isRequired, -}; - type TableBodyProps = { rows: any[]; columns: any[]; diff --git a/src/Table/TableFoot.tsx b/src/Table/TableFoot.tsx index 0e9dcff48..b94aee96e 100644 --- a/src/Table/TableFoot.tsx +++ b/src/Table/TableFoot.tsx @@ -1,9 +1,8 @@ import React from "react"; -import PropTypes from "prop-types"; import styled from "styled-components"; import TableCell from "./TableCell"; import StyledTh from "./StyledTh"; -import { columnsPropType, rowPropType, RowType, Columns } from "./Table.types"; +import { RowType, Columns } from "./Table.types"; const StyledFooterRow = styled.tr(({ theme }) => ({ "&:first-of-type": { @@ -48,13 +47,6 @@ const TableFooterRow = ({ row, columns, loading, compact }) => { ); }; -TableFooterRow.propTypes = { - row: rowPropType.isRequired, - columns: columnsPropType.isRequired, - loading: PropTypes.bool.isRequired, - compact: PropTypes.bool.isRequired, -}; - function TableFoot({ columns, rows, diff --git a/src/utils/PopperArrow.tsx b/src/utils/PopperArrow.tsx index 70dabe8da..b05ca578a 100644 --- a/src/utils/PopperArrow.tsx +++ b/src/utils/PopperArrow.tsx @@ -1,5 +1,4 @@ import styled from "styled-components"; -import PropTypes from "prop-types"; import { PopperArrowProps as ReactPopperArrowProps } from "react-popper"; import theme from "../theme"; diff --git a/src/utils/ScrollIndicators.js b/src/utils/ScrollIndicators.js index c446502f0..c0b7dfc7a 100644 --- a/src/utils/ScrollIndicators.js +++ b/src/utils/ScrollIndicators.js @@ -1,5 +1,4 @@ import React from "react"; -import PropTypes from "prop-types"; import { Icon } from "../Icon"; import theme from "../theme"; @@ -90,8 +89,4 @@ class ScrollIndicators extends React.Component { } /* eslint-enable react/destructuring-assignment */ -ScrollIndicators.propTypes = { - children: PropTypes.element.isRequired, -}; - export default ScrollIndicators; diff --git a/src/utils/subset.js b/src/utils/subset.js index 73f04489b..ac6c61899 100644 --- a/src/utils/subset.js +++ b/src/utils/subset.js @@ -12,7 +12,7 @@ export const omitSubset = (o, propObj) => { }, {}); }; -const pick = (o, ...fields) => { +export const pick = (o, ...fields) => { const objectProps = Object.keys(o); return fields.reduce((a, x) => { if (objectProps.includes(x)) a[x] = o[x]; diff --git a/src/utils/withWindowDimensions.js b/src/utils/withWindowDimensions.js index d3ec59142..409bd465b 100644 --- a/src/utils/withWindowDimensions.js +++ b/src/utils/withWindowDimensions.js @@ -1,5 +1,4 @@ import React from "react"; -import PropTypes from "prop-types"; class WindowDimensions extends React.Component { constructor(props) { @@ -32,15 +31,10 @@ class WindowDimensions extends React.Component { } } -WindowDimensions.propTypes = { - children: PropTypes.func.isRequired, -}; - -const withWindowDimensions = (Component) => (props) => - ( - - {(windowDimensions) => } - - ); +const withWindowDimensions = (Component) => (props) => ( + + {(windowDimensions) => } + +); export default withWindowDimensions; diff --git a/yarn.lock b/yarn.lock index 13e15d284..7a6e677e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16432,7 +16432,7 @@ promzard@^0.3.0: dependencies: read "1" -prop-types@15.7.2, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== From 86c6f5e53aacc3e37b68b7ef8344ea6545f23cb5 Mon Sep 17 00:00:00 2001 From: Haider Alshamma Date: Tue, 10 Sep 2024 14:08:30 -0400 Subject: [PATCH 5/5] fix: code review fixes --- src/DropdownMenu/DropdownMenu.tsx | 7 ++----- src/List/ListItem.tsx | 18 +++++++++++++----- src/Popper/Popper.tsx | 2 +- src/Tooltip/Tooltip.tsx | 4 ++-- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/DropdownMenu/DropdownMenu.tsx b/src/DropdownMenu/DropdownMenu.tsx index 3d173a55f..b56d37807 100644 --- a/src/DropdownMenu/DropdownMenu.tsx +++ b/src/DropdownMenu/DropdownMenu.tsx @@ -1,6 +1,5 @@ import React, { useMemo } from "react"; import propTypes from "@styled-system/prop-types"; -import { Reference } from "react-popper"; import { IconicButton } from "../Button"; import { ComponentSize, useComponentSize } from "../NDSProvider/ComponentSizeContext"; import { Popper } from "../Popper"; @@ -9,6 +8,7 @@ import { StyledProps } from "../StyledProps"; import DropdownMenuContainer from "./DropdownMenuContainer"; type DropdownMenuProps = { + children?: React.ReactNode; className?: string; size?: ComponentSize; id?: string; @@ -47,10 +47,7 @@ const transformPropsToModifiers = ({ boundariesElement }) => ({ boundariesElement, }); -const DropdownMenu: React.FC> = React.forwardRef< - Reference, - DropdownMenuProps ->( +const DropdownMenu = React.forwardRef, DropdownMenuProps>( ( { trigger = () => , diff --git a/src/List/ListItem.tsx b/src/List/ListItem.tsx index a45b1bacd..27b024552 100644 --- a/src/List/ListItem.tsx +++ b/src/List/ListItem.tsx @@ -1,12 +1,20 @@ +import React from "react"; import styled from "styled-components"; import { space, color, typography, SpaceProps, ColorProps, TypographyProps } from "styled-system"; type Props = React.ComponentPropsWithRef<"li"> & SpaceProps & ColorProps & TypographyProps; -const ListItem = styled.li(space, color, typography, { - "&:last-child": { - marginBottom: 0, - }, -}); +const ListItem = styled.li( + ({ theme }) => ({ + color: "currentcolor", + marginBottom: theme.space.x1, + "&:last-child": { + marginBottom: 0, + }, + }), + space, + color, + typography +); export default ListItem; diff --git a/src/Popper/Popper.tsx b/src/Popper/Popper.tsx index 8399c8d7d..d131c81dc 100644 --- a/src/Popper/Popper.tsx +++ b/src/Popper/Popper.tsx @@ -31,7 +31,7 @@ type PopperProps = { closeAriaLabel?: string; }; -const Popper = React.forwardRef( +const Popper = React.forwardRef, PopperProps>( ( { id, diff --git a/src/Tooltip/Tooltip.tsx b/src/Tooltip/Tooltip.tsx index c5062e3ed..1cc206789 100644 --- a/src/Tooltip/Tooltip.tsx +++ b/src/Tooltip/Tooltip.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { LegacyRef } from "react"; import { Popper } from "../Popper"; import { generateId } from "../utils"; import TooltipContainer from "./TooltipContainer"; @@ -26,7 +26,7 @@ export type TooltipProps = { children?: React.ReactNode; }; -const Tooltip = React.forwardRef( +const Tooltip = React.forwardRef, TooltipProps>( ( { showDelay = "100",