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

chore: Types for FileUploader, FileUploaderButton, FileUploaderDropContainer, FileUploaderItem, FileUploaderSkeleton, Filename, Upload and ButtonSkeleton #13992

Merged
12 changes: 11 additions & 1 deletion packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3422,7 +3422,17 @@ Map {
"type": "oneOf",
},
"tabIndex": Object {
"type": "string",
"args": Array [
Array [
Object {
"type": "number",
},
Object {
"type": "string",
},
],
],
"type": "oneOfType",
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,37 @@ import React from 'react';
import cx from 'classnames';
import { usePrefix } from '../../internal/usePrefix';

export interface ButtonSkeletonProps extends React.HTMLAttributes<HTMLElement> {
/**
* Specify an optional className to add.
*/
className?: string;

/**
* Optionally specify an href for your Button to become an `<a>` element
*/
href?: string;

/**
* Specify the size of the button, from a list of available sizes.
* For `default` buttons, this prop can remain unspecified or use `default`.
* In the next major release of Carbon, `default`, `field`, and `small` will be removed
*/
size?: 'sm' | 'md' | 'field' | 'lg' | 'xl' | '2xl';
imp-dance marked this conversation as resolved.
Show resolved Hide resolved

/**
* Specify whether the Button should be a small variant
*/
small?: boolean;
}

const ButtonSkeleton = ({
className,
small = false,
href,
size = 'lg',
...rest
}) => {
}: ButtonSkeletonProps) => {
const prefix = usePrefix();

const buttonClasses = cx(className, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ import cx from 'classnames';
import SkeletonText from '../SkeletonText';
import ButtonSkeleton from '../Button/Button.Skeleton';
import { usePrefix } from '../../internal/usePrefix';
import { ReactAttr } from '../../types/common';

export interface FileUploaderSkeletonProps extends ReactAttr<HTMLDivElement> {
/**
* Specify an optional className to add.
*/
className?: string;
}

function FileUploaderSkeleton({ className, ...rest }) {
const prefix = usePrefix();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,102 @@ import FileUploaderButton from './FileUploaderButton';
import { ButtonKinds } from '../../prop-types/types';
import { keys, matches } from '../../internal/keyboard';
import { PrefixContext } from '../../internal/usePrefix';
import { ReactAttr } from '../../types/common';

export default class FileUploader extends React.Component {
export interface FileUploaderProps extends ReactAttr<HTMLSpanElement> {
/**
* Specify the types of files that this input should be able to receive
*/
accept?: string[];

/**
* Specify the type of the `<FileUploaderButton>`
*/
buttonKind?:
| 'primary'
| 'secondary'
| 'danger'
| 'ghost'
| 'danger--primary'
| 'danger--ghost'
| 'danger--tertiary'
| 'tertiary';

/**
* Provide the label text to be read by screen readers when interacting with
* the `<FileUploaderButton>`
*/
buttonLabel?: string;

/**
* Provide a custom className to be applied to the container node
*/
className?: string;

/**
* Specify whether file input is disabled
*/
disabled?: boolean;

/**
* Specify the status of the File Upload
*/
filenameStatus: 'edit' | 'complete' | 'uploading';

/**
* Provide a description for the complete/close icon that can be read by screen readers
*/
iconDescription: string;

/**
* Specify the description text of this `<FileUploader>`
*/
labelDescription?: string;

/**
* Specify the title text of this `<FileUploader>`
*/
labelTitle?: string;

/**
* Specify if the component should accept multiple files to upload
*/
multiple?: boolean;

/**
* Provide a name for the underlying `<input>` node
*/
name?: string;

/**
* Provide an optional `onChange` hook that is called each time the input is
* changed
*/
onChange?: (event: any) => void;

/**
* Provide an optional `onClick` hook that is called each time the
* FileUploader is clicked
*/
onClick?: (event: any) => void;

/**
* Provide an optional `onDelete` hook that is called when an uploaded item
* is removed
*/
onDelete?: (event: any) => void;

/**
* Specify the size of the FileUploaderButton, from a list of available
* sizes.
*/
size?: 'sm' | 'small' | 'md' | 'field' | 'lg';
}

export default class FileUploader extends React.Component<
FileUploaderProps,
{ filenames: string[] }
> {
static propTypes = {
/**
* Specify the types of files that this input should be able to receive
Expand Down Expand Up @@ -111,12 +205,12 @@ export default class FileUploader extends React.Component {
};

state = {
filenames: [],
filenames: [] as string[],
};

nodes = [];
nodes: HTMLElement[] = [];

uploaderButton = React.createRef();
uploaderButton = React.createRef<HTMLLabelElement>();

static getDerivedStateFromProps({ filenameStatus }, state) {
const { prevFilenameStatus } = state;
Expand All @@ -133,7 +227,7 @@ export default class FileUploader extends React.Component {
const filenames = Array.prototype.map.call(
evt.target.files,
(file) => file.name
);
) as string[];
this.setState({
filenames: this.props.multiple
? this.state.filenames.concat(filenames)
Expand All @@ -153,9 +247,9 @@ export default class FileUploader extends React.Component {
this.setState({ filenames: filteredArray });
if (this.props.onDelete) {
this.props.onDelete(evt);
this.uploaderButton.current.focus();
this.uploaderButton.current?.focus?.();
}
this.props.onClick(evt);
this.props.onClick?.(evt);
}
};

Expand All @@ -178,15 +272,15 @@ export default class FileUploader extends React.Component {
accept,
name,
size = 'md',
onDelete, // eslint-disable-line no-unused-vars
onDelete, // eslint-disable-line
...other
} = this.props;

const prefix = this.context;

const classes = classNames({
[`${prefix}--form-item`]: true,
[className]: className,
[className as string]: className,
});

const getHelperLabelClasses = (baseClass) =>
Expand Down Expand Up @@ -228,7 +322,7 @@ export default class FileUploader extends React.Component {
<span
key={index}
className={selectedFileClasses}
ref={(node) => (this.nodes[index] = node)} // eslint-disable-line
ref={(node) => (this.nodes[index] = node as HTMLSpanElement)} // eslint-disable-line
{...other}>
<p className={`${prefix}--file-filename`} id={name}>
{name}
Expand All @@ -239,7 +333,12 @@ export default class FileUploader extends React.Component {
iconDescription={iconDescription}
status={filenameStatus}
onKeyDown={(evt) => {
if (matches(evt, [keys.Enter, keys.Space])) {
if (
matches(evt as unknown as Event, [
keys.Enter,
keys.Space,
])
) {
this.handleClick(evt, { index, filenameStatus });
}
}}
Expand Down
Loading