Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ts): adds types to next/ListBoxTrigger next/ListBoxSelection tsx #17325

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading