Skip to content

Commit

Permalink
fix(ts): adds types to next/ListBoxTrigger next/ListBoxSelection tsx (c…
Browse files Browse the repository at this point in the history
…arbon-design-system#17325)

* fix(17292): rename .js to .tsx

* fix(17292): convert ListBoxTigger and Selection to TS
  • Loading branch information
2nikhiltom committed Sep 7, 2024
1 parent 2558b38 commit 71c9596
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 93 deletions.
1 change: 0 additions & 1 deletion packages/react/src/components/ComboBox/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,6 @@ const ComboBox = forwardRef(
)}
<ListBoxTrigger
{...buttonProps}
// @ts-expect-error
isOpen={isOpen}
translateWithId={translateWithId}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2016, 2023
* Copyright IBM Corp. 2016, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
Expand All @@ -20,14 +20,66 @@ import { usePrefix } from '../../../internal/usePrefix';
export const translationIds = {
'clear.all': 'clear.all',
'clear.selection': 'clear.selection',
};
} as const;

export type TranslationKey = keyof typeof translationIds;

const defaultTranslations = {
[translationIds['clear.all']]: 'Clear all selected items',
[translationIds['clear.selection']]: 'Clear selected item',
const defaultTranslations: Record<TranslationKey, string> = {
'clear.all': 'Clear all selected items',
'clear.selection': 'Clear selected item',
};

const defaultTranslateWithId = (id) => defaultTranslations[id];
function defaultTranslateWithId(id: TranslationKey): string {
return defaultTranslations[id];
}
export interface ListBoxSelectionProps {
/**
* Specify a function to be invoked when a user interacts with the clear
* selection element.
*/
clearSelection: (
event:
| React.MouseEvent<HTMLButtonElement>
| React.KeyboardEvent<HTMLButtonElement>
) => void;
/**
* Specify an optional `selectionCount` value that will be used to determine
* whether the selection should display a badge or a single clear icon.
*/
selectionCount?: number;
/**
* i18n hook used to provide the appropriate description for the given menu
* icon. This function takes in an id defined in `translationIds` and should
* return a string message for that given message id.
*/
translateWithId?: (id: TranslationKey) => string;
/**
* Specify whether or not the clear selection element should be disabled
*/
disabled?: boolean;
/**
* Specify an optional `onClearSelection` handler that is called when the underlying
* element is cleared
*/
onClearSelection?: (event: React.MouseEvent<HTMLButtonElement>) => void;
/**
* Specify an optional `onClick` handler that is called when the underlying
* clear selection element is clicked
*/
onClick?: React.MouseEventHandler<HTMLButtonElement>;

/**
* Specify an optional `onKeyDown` handler that is called when the underlying
* clear selection element fires a keydown event
*/
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;

/**
* Specify an optional `onMouseUp` handler that is called when the underlying
* clear selection element fires a mouseup event
*/
onMouseUp?: React.MouseEventHandler<HTMLButtonElement>;
}

function ListBoxSelection({
clearSelection,
Expand All @@ -36,7 +88,7 @@ function ListBoxSelection({
disabled,
onClearSelection,
...rest
}) {
}: ListBoxSelectionProps) {
const prefix = usePrefix();
const className = cx(`${prefix}--list-box__selection`, {
[`${prefix}--tag--filter`]: selectionCount,
Expand All @@ -52,7 +104,7 @@ function ListBoxSelection({
}
);

function onClick(event) {
function onClick(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
event.stopPropagation();
if (disabled) {
return;
Expand All @@ -66,7 +118,9 @@ function ListBoxSelection({
if (selectionCount) {
return (
<div className={tagClasses}>
<span className={`${prefix}--tag__label`} title={selectionCount}>
<span
className={`${prefix}--tag__label`}
title={selectionCount?.toString()}>
{selectionCount}
</span>
<button
Expand Down Expand Up @@ -122,6 +176,12 @@ ListBoxSelection.propTypes = {
*/
onClick: PropTypes.func,

/**
* Specify an optional `onClick` handler that is called when the underlying
* clear selection element is clicked
*/
onMouseUp: PropTypes.func,

/**
* Specify an optional `onKeyDown` handler that is called when the underlying
* clear selection element fires a keydown event
Expand Down
70 changes: 0 additions & 70 deletions packages/react/src/components/ListBox/next/ListBoxTrigger.js

This file was deleted.

90 changes: 90 additions & 0 deletions packages/react/src/components/ListBox/next/ListBoxTrigger.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Copyright IBM Corp. 2016, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import cx from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
import { ChevronDown } from '@carbon/icons-react';
import { usePrefix } from '../../../internal/usePrefix';

export const translationIds = {
'close.menu': 'close.menu',
'open.menu': 'open.menu',
} as const;

export type TranslationKey = keyof typeof translationIds;

const defaultTranslations: Record<TranslationKey, string> = {
[translationIds['close.menu']]: 'Close',
[translationIds['open.menu']]: 'Open',
};

const defaultTranslateWithId = (id: TranslationKey): string =>
defaultTranslations[id];

export interface ListBoxTriggerProps
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
/**
* Specify whether the menu is currently open, which will influence the
* direction of the menu icon
*/
isOpen: boolean;
/**
* i18n hook used to provide the appropriate description for the given menu
* icon. This function takes in an id defined in `translationIds` and should
* return a string message for that given message id.
*/
translateWithId?: (id: TranslationKey) => string;
}

/**
* `ListBoxTrigger` is used to orient the icon up or down depending on the
* state of the menu for a given `ListBox`
*/

const ListBoxTrigger = React.forwardRef<HTMLButtonElement, ListBoxTriggerProps>(
function ListBoxTrigger(
{ isOpen, translateWithId: t = defaultTranslateWithId, ...rest },
ref
) {
const prefix = usePrefix();
const className = cx({
[`${prefix}--list-box__menu-icon`]: true,
[`${prefix}--list-box__menu-icon--open`]: isOpen,
});
const description = isOpen ? t('close.menu') : t('open.menu');
return (
<button
{...rest}
aria-label={description}
title={description}
className={className}
type="button"
tabIndex={-1}
ref={ref}>
<ChevronDown />
</button>
);
}
);

ListBoxTrigger.propTypes = {
/**
* Specify whether the menu is currently open, which will influence the
* direction of the menu icon
*/
isOpen: PropTypes.bool.isRequired,

/**
* i18n hook used to provide the appropriate description for the given menu
* icon. This function takes in an id defined in `translationIds` and should
* return a string message for that given message id.
*/
translateWithId: PropTypes.func,
};

export default ListBoxTrigger;
9 changes: 0 additions & 9 deletions packages/react/src/components/ListBox/next/index.js

This file was deleted.

15 changes: 15 additions & 0 deletions packages/react/src/components/ListBox/next/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright IBM Corp. 2016, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

export {
default as ListBoxSelection,
type ListBoxSelectionProps,
} from './ListBoxSelection';
export {
default as ListBoxTrigger,
type ListBoxTriggerProps,
} from './ListBoxTrigger';
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import React, {
ForwardedRef,
type FocusEvent,
type KeyboardEvent,
type MouseEvent,
ReactElement,
useLayoutEffect,
useMemo,
Expand Down Expand Up @@ -650,7 +651,9 @@ const FilterableMultiSelect = React.forwardRef(function FilterableMultiSelect<
}
});

function clearInputValue(event?: KeyboardEvent | undefined) {
function clearInputValue(
event?: KeyboardEvent<Element> | MouseEvent<HTMLButtonElement>
) {
const value = textInput.current?.value;
if (value?.length === 1 || (event && match(event, keys.Escape))) {
setInputValue('');
Expand Down Expand Up @@ -832,7 +835,6 @@ const FilterableMultiSelect = React.forwardRef(function FilterableMultiSelect<
className={`${prefix}--list-box__field`}
ref={autoAlign ? refs.setReference : null}>
{controlledSelectedItems.length > 0 && (
// @ts-expect-error: It is expecting a non-required prop called: "onClearSelection"
<ListBoxSelection
clearSelection={() => {
clearSelection();
Expand All @@ -859,7 +861,6 @@ const FilterableMultiSelect = React.forwardRef(function FilterableMultiSelect<
/>
)}
{inputValue && (
// @ts-expect-error: It is expecting two non-required prop called: "onClearSelection" & "selectionCount"
<ListBoxSelection
clearSelection={clearInputValue}
disabled={disabled}
Expand All @@ -876,7 +877,6 @@ const FilterableMultiSelect = React.forwardRef(function FilterableMultiSelect<
)}
<ListBoxTrigger
{...buttonProps}
// @ts-expect-error
isOpen={isOpen}
translateWithId={translateWithId}
/>
Expand Down

0 comments on commit 71c9596

Please sign in to comment.