Merge pull request #6336 from matrix-org/t3chguy/fix/pins
This commit is contained in:
commit
ac0162c218
2 changed files with 97 additions and 85 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||||
Copyright 2015, 2016, 2018, 2019, 2021 The Matrix.org Foundation C.I.C.
|
Copyright 2015 - 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -16,12 +16,11 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import { EventStatus, MatrixEvent } from 'matrix-js-sdk/src/models/event';
|
||||||
import { EventStatus } from 'matrix-js-sdk/src/models/event';
|
import { EventType, RelationType } from "matrix-js-sdk/src/@types/event";
|
||||||
|
|
||||||
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
import dis from '../../../dispatcher/dispatcher';
|
import dis from '../../../dispatcher/dispatcher';
|
||||||
import * as sdk from '../../../index';
|
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import Modal from '../../../Modal';
|
import Modal from '../../../Modal';
|
||||||
import Resend from '../../../Resend';
|
import Resend from '../../../Resend';
|
||||||
|
@ -29,53 +28,65 @@ import SettingsStore from '../../../settings/SettingsStore';
|
||||||
import { isUrlPermitted } from '../../../HtmlUtils';
|
import { isUrlPermitted } from '../../../HtmlUtils';
|
||||||
import { isContentActionable } from '../../../utils/EventUtils';
|
import { isContentActionable } from '../../../utils/EventUtils';
|
||||||
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from './IconizedContextMenu';
|
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from './IconizedContextMenu';
|
||||||
import { EventType } from "matrix-js-sdk/src/@types/event";
|
|
||||||
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
import { ReadPinsEventId } from "../right_panel/PinnedMessagesCard";
|
import { ReadPinsEventId } from "../right_panel/PinnedMessagesCard";
|
||||||
import ForwardDialog from "../dialogs/ForwardDialog";
|
import ForwardDialog from "../dialogs/ForwardDialog";
|
||||||
import { Action } from "../../../dispatcher/actions";
|
import { Action } from "../../../dispatcher/actions";
|
||||||
|
import ReportEventDialog from '../dialogs/ReportEventDialog';
|
||||||
|
import ViewSource from '../../structures/ViewSource';
|
||||||
|
import ConfirmRedactDialog from '../dialogs/ConfirmRedactDialog';
|
||||||
|
import ErrorDialog from '../dialogs/ErrorDialog';
|
||||||
|
import ShareDialog from '../dialogs/ShareDialog';
|
||||||
|
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||||
|
|
||||||
export function canCancel(eventStatus) {
|
export function canCancel(eventStatus: EventStatus): boolean {
|
||||||
return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT;
|
return eventStatus === EventStatus.QUEUED || eventStatus === EventStatus.NOT_SENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IEventTileOps {
|
||||||
|
isWidgetHidden(): boolean;
|
||||||
|
unhideWidget(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
/* the MatrixEvent associated with the context menu */
|
||||||
|
mxEvent: MatrixEvent;
|
||||||
|
/* an optional EventTileOps implementation that can be used to unhide preview widgets */
|
||||||
|
eventTileOps?: IEventTileOps;
|
||||||
|
permalinkCreator?: RoomPermalinkCreator;
|
||||||
|
/* an optional function to be called when the user clicks collapse thread, if not provided hide button */
|
||||||
|
collapseReplyThread?(): void;
|
||||||
|
/* callback called when the menu is dismissed */
|
||||||
|
onFinished(): void;
|
||||||
|
/* if the menu is inside a dialog, we sometimes need to close that dialog after click (forwarding) */
|
||||||
|
onCloseDialog?(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
canRedact: boolean;
|
||||||
|
canPin: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.context_menus.MessageContextMenu")
|
@replaceableComponent("views.context_menus.MessageContextMenu")
|
||||||
export default class MessageContextMenu extends React.Component {
|
export default class MessageContextMenu extends React.Component<IProps, IState> {
|
||||||
static propTypes = {
|
|
||||||
/* the MatrixEvent associated with the context menu */
|
|
||||||
mxEvent: PropTypes.object.isRequired,
|
|
||||||
|
|
||||||
/* an optional EventTileOps implementation that can be used to unhide preview widgets */
|
|
||||||
eventTileOps: PropTypes.object,
|
|
||||||
|
|
||||||
/* an optional function to be called when the user clicks collapse thread, if not provided hide button */
|
|
||||||
collapseReplyThread: PropTypes.func,
|
|
||||||
|
|
||||||
/* callback called when the menu is dismissed */
|
|
||||||
onFinished: PropTypes.func,
|
|
||||||
|
|
||||||
/* if the menu is inside a dialog, we sometimes need to close that dialog after click (forwarding) */
|
|
||||||
onCloseDialog: PropTypes.func,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
canRedact: false,
|
canRedact: false,
|
||||||
canPin: false,
|
canPin: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
MatrixClientPeg.get().on('RoomMember.powerLevel', this._checkPermissions);
|
MatrixClientPeg.get().on('RoomMember.powerLevel', this.checkPermissions);
|
||||||
this._checkPermissions();
|
this.checkPermissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
if (cli) {
|
if (cli) {
|
||||||
cli.removeListener('RoomMember.powerLevel', this._checkPermissions);
|
cli.removeListener('RoomMember.powerLevel', this.checkPermissions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_checkPermissions = () => {
|
private checkPermissions = (): void => {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||||
|
|
||||||
|
@ -93,7 +104,7 @@ export default class MessageContextMenu extends React.Component {
|
||||||
this.setState({ canRedact, canPin });
|
this.setState({ canRedact, canPin });
|
||||||
};
|
};
|
||||||
|
|
||||||
_isPinned() {
|
private isPinned(): boolean {
|
||||||
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
||||||
const pinnedEvent = room.currentState.getStateEvents(EventType.RoomPinnedEvents, '');
|
const pinnedEvent = room.currentState.getStateEvents(EventType.RoomPinnedEvents, '');
|
||||||
if (!pinnedEvent) return false;
|
if (!pinnedEvent) return false;
|
||||||
|
@ -101,38 +112,35 @@ export default class MessageContextMenu extends React.Component {
|
||||||
return content.pinned && Array.isArray(content.pinned) && content.pinned.includes(this.props.mxEvent.getId());
|
return content.pinned && Array.isArray(content.pinned) && content.pinned.includes(this.props.mxEvent.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
onResendReactionsClick = () => {
|
private onResendReactionsClick = (): void => {
|
||||||
for (const reaction of this._getUnsentReactions()) {
|
for (const reaction of this.getUnsentReactions()) {
|
||||||
Resend.resend(reaction);
|
Resend.resend(reaction);
|
||||||
}
|
}
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
onReportEventClick = () => {
|
private onReportEventClick = (): void => {
|
||||||
const ReportEventDialog = sdk.getComponent("dialogs.ReportEventDialog");
|
|
||||||
Modal.createTrackedDialog('Report Event', '', ReportEventDialog, {
|
Modal.createTrackedDialog('Report Event', '', ReportEventDialog, {
|
||||||
mxEvent: this.props.mxEvent,
|
mxEvent: this.props.mxEvent,
|
||||||
}, 'mx_Dialog_reportEvent');
|
}, 'mx_Dialog_reportEvent');
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
onViewSourceClick = () => {
|
private onViewSourceClick = (): void => {
|
||||||
const ViewSource = sdk.getComponent('structures.ViewSource');
|
|
||||||
Modal.createTrackedDialog('View Event Source', '', ViewSource, {
|
Modal.createTrackedDialog('View Event Source', '', ViewSource, {
|
||||||
mxEvent: this.props.mxEvent,
|
mxEvent: this.props.mxEvent,
|
||||||
}, 'mx_Dialog_viewsource');
|
}, 'mx_Dialog_viewsource');
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
onRedactClick = () => {
|
private onRedactClick = (): void => {
|
||||||
const ConfirmRedactDialog = sdk.getComponent("dialogs.ConfirmRedactDialog");
|
|
||||||
Modal.createTrackedDialog('Confirm Redact Dialog', '', ConfirmRedactDialog, {
|
Modal.createTrackedDialog('Confirm Redact Dialog', '', ConfirmRedactDialog, {
|
||||||
onFinished: async (proceed, reason) => {
|
onFinished: async (proceed: boolean, reason?: string) => {
|
||||||
if (!proceed) return;
|
if (!proceed) return;
|
||||||
|
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
try {
|
try {
|
||||||
if (this.props.onCloseDialog) this.props.onCloseDialog();
|
this.props.onCloseDialog?.();
|
||||||
await cli.redactEvent(
|
await cli.redactEvent(
|
||||||
this.props.mxEvent.getRoomId(),
|
this.props.mxEvent.getRoomId(),
|
||||||
this.props.mxEvent.getId(),
|
this.props.mxEvent.getId(),
|
||||||
|
@ -145,7 +153,6 @@ export default class MessageContextMenu extends React.Component {
|
||||||
// (e.g. no errcode or statusCode) as in that case the redactions end up in the
|
// (e.g. no errcode or statusCode) as in that case the redactions end up in the
|
||||||
// detached queue and we show the room status bar to allow retry
|
// detached queue and we show the room status bar to allow retry
|
||||||
if (typeof code !== "undefined") {
|
if (typeof code !== "undefined") {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
|
||||||
// display error message stating you couldn't delete this.
|
// display error message stating you couldn't delete this.
|
||||||
Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, {
|
Modal.createTrackedDialog('You cannot delete this message', '', ErrorDialog, {
|
||||||
title: _t('Error'),
|
title: _t('Error'),
|
||||||
|
@ -158,7 +165,7 @@ export default class MessageContextMenu extends React.Component {
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
onForwardClick = () => {
|
private onForwardClick = (): void => {
|
||||||
Modal.createTrackedDialog('Forward Message', '', ForwardDialog, {
|
Modal.createTrackedDialog('Forward Message', '', ForwardDialog, {
|
||||||
matrixClient: MatrixClientPeg.get(),
|
matrixClient: MatrixClientPeg.get(),
|
||||||
event: this.props.mxEvent,
|
event: this.props.mxEvent,
|
||||||
|
@ -167,12 +174,12 @@ export default class MessageContextMenu extends React.Component {
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
onPinClick = () => {
|
private onPinClick = (): void => {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||||
const eventId = this.props.mxEvent.getId();
|
const eventId = this.props.mxEvent.getId();
|
||||||
|
|
||||||
const pinnedIds = room?.currentState?.getStateEvents(EventType.RoomPinnedEvents, "")?.pinned || [];
|
const pinnedIds = room?.currentState?.getStateEvents(EventType.RoomPinnedEvents, "")?.getContent().pinned || [];
|
||||||
if (pinnedIds.includes(eventId)) {
|
if (pinnedIds.includes(eventId)) {
|
||||||
pinnedIds.splice(pinnedIds.indexOf(eventId), 1);
|
pinnedIds.splice(pinnedIds.indexOf(eventId), 1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -188,18 +195,16 @@ export default class MessageContextMenu extends React.Component {
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
closeMenu = () => {
|
private closeMenu = (): void => {
|
||||||
if (this.props.onFinished) this.props.onFinished();
|
this.props.onFinished();
|
||||||
};
|
};
|
||||||
|
|
||||||
onUnhidePreviewClick = () => {
|
private onUnhidePreviewClick = (): void => {
|
||||||
if (this.props.eventTileOps) {
|
this.props.eventTileOps?.unhideWidget();
|
||||||
this.props.eventTileOps.unhideWidget();
|
|
||||||
}
|
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
onQuoteClick = () => {
|
private onQuoteClick = (): void => {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: Action.ComposerInsert,
|
action: Action.ComposerInsert,
|
||||||
event: this.props.mxEvent,
|
event: this.props.mxEvent,
|
||||||
|
@ -207,9 +212,8 @@ export default class MessageContextMenu extends React.Component {
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
onPermalinkClick = (e) => {
|
private onPermalinkClick = (e: React.MouseEvent): void => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const ShareDialog = sdk.getComponent("dialogs.ShareDialog");
|
|
||||||
Modal.createTrackedDialog('share room message dialog', '', ShareDialog, {
|
Modal.createTrackedDialog('share room message dialog', '', ShareDialog, {
|
||||||
target: this.props.mxEvent,
|
target: this.props.mxEvent,
|
||||||
permalinkCreator: this.props.permalinkCreator,
|
permalinkCreator: this.props.permalinkCreator,
|
||||||
|
@ -217,30 +221,27 @@ export default class MessageContextMenu extends React.Component {
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
onCollapseReplyThreadClick = () => {
|
private onCollapseReplyThreadClick = (): void => {
|
||||||
this.props.collapseReplyThread();
|
this.props.collapseReplyThread();
|
||||||
this.closeMenu();
|
this.closeMenu();
|
||||||
};
|
};
|
||||||
|
|
||||||
_getReactions(filter) {
|
private getReactions(filter: (e: MatrixEvent) => boolean): MatrixEvent[] {
|
||||||
const cli = MatrixClientPeg.get();
|
const cli = MatrixClientPeg.get();
|
||||||
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
const room = cli.getRoom(this.props.mxEvent.getRoomId());
|
||||||
const eventId = this.props.mxEvent.getId();
|
const eventId = this.props.mxEvent.getId();
|
||||||
return room.getPendingEvents().filter(e => {
|
return room.getPendingEvents().filter(e => {
|
||||||
const relation = e.getRelation();
|
const relation = e.getRelation();
|
||||||
return relation &&
|
return relation?.rel_type === RelationType.Annotation && relation.event_id === eventId && filter(e);
|
||||||
relation.rel_type === "m.annotation" &&
|
|
||||||
relation.event_id === eventId &&
|
|
||||||
filter(e);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_getPendingReactions() {
|
private getPendingReactions(): MatrixEvent[] {
|
||||||
return this._getReactions(e => canCancel(e.status));
|
return this.getReactions(e => canCancel(e.status));
|
||||||
}
|
}
|
||||||
|
|
||||||
_getUnsentReactions() {
|
private getUnsentReactions(): MatrixEvent[] {
|
||||||
return this._getReactions(e => e.status === EventStatus.NOT_SENT);
|
return this.getReactions(e => e.status === EventStatus.NOT_SENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -248,16 +249,17 @@ export default class MessageContextMenu extends React.Component {
|
||||||
const me = cli.getUserId();
|
const me = cli.getUserId();
|
||||||
const mxEvent = this.props.mxEvent;
|
const mxEvent = this.props.mxEvent;
|
||||||
const eventStatus = mxEvent.status;
|
const eventStatus = mxEvent.status;
|
||||||
const unsentReactionsCount = this._getUnsentReactions().length;
|
const unsentReactionsCount = this.getUnsentReactions().length;
|
||||||
let resendReactionsButton;
|
|
||||||
let redactButton;
|
let resendReactionsButton: JSX.Element;
|
||||||
let forwardButton;
|
let redactButton: JSX.Element;
|
||||||
let pinButton;
|
let forwardButton: JSX.Element;
|
||||||
let unhidePreviewButton;
|
let pinButton: JSX.Element;
|
||||||
let externalURLButton;
|
let unhidePreviewButton: JSX.Element;
|
||||||
let quoteButton;
|
let externalURLButton: JSX.Element;
|
||||||
let collapseReplyThread;
|
let quoteButton: JSX.Element;
|
||||||
let redactItemList;
|
let collapseReplyThread: JSX.Element;
|
||||||
|
let redactItemList: JSX.Element;
|
||||||
|
|
||||||
// status is SENT before remote-echo, null after
|
// status is SENT before remote-echo, null after
|
||||||
const isSent = !eventStatus || eventStatus === EventStatus.SENT;
|
const isSent = !eventStatus || eventStatus === EventStatus.SENT;
|
||||||
|
@ -296,7 +298,7 @@ export default class MessageContextMenu extends React.Component {
|
||||||
pinButton = (
|
pinButton = (
|
||||||
<IconizedContextMenuOption
|
<IconizedContextMenuOption
|
||||||
iconClassName="mx_MessageContextMenu_iconPin"
|
iconClassName="mx_MessageContextMenu_iconPin"
|
||||||
label={ this._isPinned() ? _t('Unpin') : _t('Pin') }
|
label={ this.isPinned() ? _t('Unpin') : _t('Pin') }
|
||||||
onClick={this.onPinClick}
|
onClick={this.onPinClick}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -333,9 +335,14 @@ export default class MessageContextMenu extends React.Component {
|
||||||
onClick={this.onPermalinkClick}
|
onClick={this.onPermalinkClick}
|
||||||
label= {_t('Share')}
|
label= {_t('Share')}
|
||||||
element="a"
|
element="a"
|
||||||
href={permalink}
|
{
|
||||||
target="_blank"
|
// XXX: Typescript signature for AccessibleButton doesn't work properly for non-inputs like `a`
|
||||||
rel="noreferrer noopener"
|
...{
|
||||||
|
href: permalink,
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer noopener",
|
||||||
|
}
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -350,8 +357,8 @@ export default class MessageContextMenu extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bridges can provide a 'external_url' to link back to the source.
|
// Bridges can provide a 'external_url' to link back to the source.
|
||||||
if (typeof (mxEvent.event.content.external_url) === "string" &&
|
if (typeof (mxEvent.getContent().external_url) === "string" &&
|
||||||
isUrlPermitted(mxEvent.event.content.external_url)
|
isUrlPermitted(mxEvent.getContent().external_url)
|
||||||
) {
|
) {
|
||||||
externalURLButton = (
|
externalURLButton = (
|
||||||
<IconizedContextMenuOption
|
<IconizedContextMenuOption
|
||||||
|
@ -359,9 +366,14 @@ export default class MessageContextMenu extends React.Component {
|
||||||
onClick={this.closeMenu}
|
onClick={this.closeMenu}
|
||||||
label={ _t('Source URL') }
|
label={ _t('Source URL') }
|
||||||
element="a"
|
element="a"
|
||||||
target="_blank"
|
{
|
||||||
rel="noreferrer noopener"
|
// XXX: Typescript signature for AccessibleButton doesn't work properly for non-inputs like `a`
|
||||||
href={mxEvent.event.content.external_url}
|
...{
|
||||||
|
target: "_blank",
|
||||||
|
rel: "noreferrer noopener",
|
||||||
|
href: mxEvent.getContent().external_url,
|
||||||
|
}
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -376,7 +388,7 @@ export default class MessageContextMenu extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let reportEventButton;
|
let reportEventButton: JSX.Element;
|
||||||
if (mxEvent.getSender() !== me) {
|
if (mxEvent.getSender() !== me) {
|
||||||
reportEventButton = (
|
reportEventButton = (
|
||||||
<IconizedContextMenuOption
|
<IconizedContextMenuOption
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, { ReactHTML } from 'react';
|
||||||
|
|
||||||
import { Key } from '../../../Keyboard';
|
import { Key } from '../../../Keyboard';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
@ -29,7 +29,7 @@ export type ButtonEvent = React.MouseEvent<Element> | React.KeyboardEvent<Elemen
|
||||||
*/
|
*/
|
||||||
interface IProps extends React.InputHTMLAttributes<Element> {
|
interface IProps extends React.InputHTMLAttributes<Element> {
|
||||||
inputRef?: React.Ref<Element>;
|
inputRef?: React.Ref<Element>;
|
||||||
element?: string;
|
element?: keyof ReactHTML;
|
||||||
// The kind of button, similar to how Bootstrap works.
|
// The kind of button, similar to how Bootstrap works.
|
||||||
// See available classes for AccessibleButton for options.
|
// See available classes for AccessibleButton for options.
|
||||||
kind?: string;
|
kind?: string;
|
||||||
|
@ -122,7 +122,7 @@ export default function AccessibleButton({
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessibleButton.defaultProps = {
|
AccessibleButton.defaultProps = {
|
||||||
element: 'div',
|
element: 'div' as keyof ReactHTML,
|
||||||
role: 'button',
|
role: 'button',
|
||||||
tabIndex: 0,
|
tabIndex: 0,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue