Skip to content

Commit

Permalink
Add TypeScript types to ContentSwitcher, Switch (#13993)
Browse files Browse the repository at this point in the history
* refactor: add types for ContentSwitcher, Layout and Switch components

* docs: update contributors list

* refactor: density and size props typing
  • Loading branch information
anton-tsymuk-viacomcbs authored Jun 16, 2023
1 parent 7efc2f3 commit ab30e22
Show file tree
Hide file tree
Showing 6 changed files with 401 additions and 170 deletions.
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,15 @@
"contributions": [
"code"
]
},
{
"login": "anton-tsymuk-viacomcbs",
"name": "Anton Tsymuk",
"avatar_url": "https://avatars.githubusercontent.com/u/112623876?v=4",
"profile": "https://github.com/anton-tsymuk-viacomcbs",
"contributions": [
"code"
]
}
],
"commitConvention": "none"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ check out our [Contributing Guide](/.github/CONTRIBUTING.md) and our
<tr>
<td align="center"><a href="http://www.steveblackonline.com/"><img src="https://avatars.githubusercontent.com/u/7853451?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Steven Black</b></sub></a><br /><a href="https://github.com/carbon-design-system/carbon/commits?author=sjbeatle" title="Code">💻</a> <a href="#a11y-sjbeatle" title="Accessibility">️️️️♿️</a></td>
<td align="center"><a href="https://github.com/mrkjdy"><img src="https://avatars.githubusercontent.com/u/32761859?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mark Judy</b></sub></a><br /><a href="https://github.com/carbon-design-system/carbon/commits?author=mrkjdy" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/anton-tsymuk-viacomcbs"><img src="https://avatars.githubusercontent.com/u/112623876?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anton Tsymuk</b></sub></a><br /><a href="https://github.com/carbon-design-system/carbon/commits?author=anton-tsymuk-viacomcbs" title="Code">💻</a></td>
</tr>
</table>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,81 @@
*/

import PropTypes from 'prop-types';
import React from 'react';
import React, { HTMLAttributes, ReactElement } from 'react';
import classNames from 'classnames';
import deprecate from '../../prop-types/deprecate';
import { LayoutConstraint } from '../Layout';
import { composeEventHandlers } from '../../tools/events';
import { getNextIndex, matches, keys } from '../../internal/keyboard';
import { PrefixContext } from '../../internal/usePrefix';

export default class ContentSwitcher extends React.Component {
interface SwitchEventHandlersParams {
index?: number;
name?: string | number;
text?: string;
key?: string | number;
}

export interface ContentSwitcherProps
extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
/**
* Pass in Switch components to be rendered in the ContentSwitcher
*/
children?: ReactElement[];

/**
* Specify an optional className to be added to the container node
*/
className?: string;

/**
* `true` to use the light version.
*
* @deprecated The `light` prop for `ContentSwitcher` has
* been deprecated in favor of the new `Layer` component. It will be removed in the next major release.
*/
light?: boolean;

/**
* Specify an `onChange` handler that is called whenever the ContentSwitcher
* changes which item is selected
*/
onChange: (params: SwitchEventHandlersParams) => void;

/**
* Specify a selected index for the initially selected content
*/
selectedIndex: number;

/**
* Choose whether or not to automatically change selection on focus
*/
selectionMode: 'automatic' | 'manual';

/**
* Specify the size of the Content Switcher. Currently supports either `sm`, 'md' (default) or 'lg` as an option.
*/
size: 'sm' | 'md' | 'lg';
}

interface ContentSwitcherState {
selectedIndex?: number;
}

export default class ContentSwitcher extends React.Component<
ContentSwitcherProps,
ContentSwitcherState
> {
/**
* The DOM references of child `<Switch>`.
* @type {Array<Element>}
* @private
*/
_switchRefs = [];
_switchRefs: HTMLButtonElement[] = [];

state = {};
state = {
selectedIndex: undefined,
};

static propTypes = {
/**
Expand Down Expand Up @@ -97,18 +155,26 @@ export default class ContentSwitcher extends React.Component {
const { key } = data;

if (matches(data, [keys.ArrowRight, keys.ArrowLeft])) {
const nextIndex = getNextIndex(key, index, this.props.children.length);
const nextIndex = getNextIndex(
key,
index,
this.props.children?.length as number
);
const children = React.Children.toArray(this.props.children);
if (selectionMode === 'manual') {
const switchRef = this._switchRefs[nextIndex];
const switchRef = this._switchRefs[nextIndex as number];
switchRef && switchRef.focus();
} else {
this.setState(
{
selectedIndex: nextIndex,
},
() => {
const child = children[this.state.selectedIndex];
if (typeof this.state.selectedIndex !== 'number') {
return;
}

const child = children[this.state.selectedIndex] as ReactElement;
const switchRef = this._switchRefs[this.state.selectedIndex];
switchRef && switchRef.focus();
this.props.onChange({
Expand All @@ -135,15 +201,20 @@ export default class ContentSwitcher extends React.Component {
children,
className,
light,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
selectedIndex, // eslint-disable-line no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
selectionMode, // eslint-disable-line no-unused-vars
size,
...other
} = this.props;

const isIconOnly = React.Children.map(children, (child) => {
return child.type.displayName === 'IconSwitch';
}).every((val) => val === true);
const isIconOnly = React.Children?.map(children, (child) => {
return (
(child as { type: { displayName: string } }).type.displayName ===
'IconSwitch'
);
})?.every((val) => val === true);

const classes = classNames(`${prefix}--content-switcher`, className, {
[`${prefix}--content-switcher--light`]: light,
Expand All @@ -157,20 +228,22 @@ export default class ContentSwitcher extends React.Component {
size={{ default: 'md', min: 'sm', max: 'lg' }}
{...other}
className={classes}
role="tablist">
{React.Children.map(children, (child, index) =>
React.cloneElement(child, {
index,
onClick: composeEventHandlers([
this.handleChildChange,
child.props.onClick,
]),
onKeyDown: this.handleChildChange,
selected: index === this.state.selectedIndex,
ref: this.handleItemRef(index),
size,
})
)}
role="tablist"
onChange={undefined}>
{children &&
React.Children.map(children, (child: ReactElement, index) =>
React.cloneElement(child, {
index,
onClick: composeEventHandlers([
this.handleChildChange,
child.props.onClick,
]),
onKeyDown: this.handleChildChange,
selected: index === this.state.selectedIndex,
ref: this.handleItemRef(index),
size,
})
)}
</LayoutConstraint>
);
}
Expand Down
138 changes: 0 additions & 138 deletions packages/react/src/components/Layout/index.js

This file was deleted.

Loading

0 comments on commit ab30e22

Please sign in to comment.