Merge remote-tracking branch 'origin/experimental' into dbkr/sas
This commit is contained in:
commit
6a90625d36
172 changed files with 1885 additions and 661 deletions
|
@ -28,41 +28,56 @@ import { KeyCode } from '../../../Keyboard';
|
|||
* @returns {Object} rendered react
|
||||
*/
|
||||
export default function AccessibleButton(props) {
|
||||
const {element, onClick, children, ...restProps} = props;
|
||||
restProps.onClick = onClick;
|
||||
// We need to consume enter onKeyDown and space onKeyUp
|
||||
// otherwise we are risking also activating other keyboard focusable elements
|
||||
// that might receive focus as a result of the AccessibleButtonClick action
|
||||
// It's because we are using html buttons at a few places e.g. inside dialogs
|
||||
// And divs which we report as role button to assistive technologies.
|
||||
// Browsers handle space and enter keypresses differently and we are only adjusting to the
|
||||
// inconsistencies here
|
||||
restProps.onKeyDown = function(e) {
|
||||
if (e.keyCode === KeyCode.ENTER) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return onClick(e);
|
||||
}
|
||||
if (e.keyCode === KeyCode.SPACE) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
restProps.onKeyUp = function(e) {
|
||||
if (e.keyCode === KeyCode.SPACE) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return onClick(e);
|
||||
}
|
||||
if (e.keyCode === KeyCode.ENTER) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
const {element, onClick, children, kind, disabled, ...restProps} = props;
|
||||
|
||||
if (!disabled) {
|
||||
restProps.onClick = onClick;
|
||||
// We need to consume enter onKeyDown and space onKeyUp
|
||||
// otherwise we are risking also activating other keyboard focusable elements
|
||||
// that might receive focus as a result of the AccessibleButtonClick action
|
||||
// It's because we are using html buttons at a few places e.g. inside dialogs
|
||||
// And divs which we report as role button to assistive technologies.
|
||||
// Browsers handle space and enter keypresses differently and we are only adjusting to the
|
||||
// inconsistencies here
|
||||
restProps.onKeyDown = function(e) {
|
||||
if (e.keyCode === KeyCode.ENTER) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return onClick(e);
|
||||
}
|
||||
if (e.keyCode === KeyCode.SPACE) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
restProps.onKeyUp = function(e) {
|
||||
if (e.keyCode === KeyCode.SPACE) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return onClick(e);
|
||||
}
|
||||
if (e.keyCode === KeyCode.ENTER) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
restProps.tabIndex = restProps.tabIndex || "0";
|
||||
restProps.role = "button";
|
||||
restProps.className = (restProps.className ? restProps.className + " " : "") +
|
||||
"mx_AccessibleButton";
|
||||
|
||||
if (kind) {
|
||||
// We apply a hasKind class to maintain backwards compatibility with
|
||||
// buttons which might not know about kind and break
|
||||
restProps.className += " mx_AccessibleButton_hasKind mx_AccessibleButton_kind_" + kind;
|
||||
}
|
||||
|
||||
if (disabled) {
|
||||
restProps.className += " mx_AccessibleButton_disabled";
|
||||
}
|
||||
|
||||
return React.createElement(element, restProps, children);
|
||||
}
|
||||
|
||||
|
@ -76,6 +91,12 @@ AccessibleButton.propTypes = {
|
|||
children: PropTypes.node,
|
||||
element: PropTypes.string,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
|
||||
// The kind of button, similar to how Bootstrap works.
|
||||
// See available classes for AccessibleButton for options.
|
||||
kind: PropTypes.string,
|
||||
|
||||
disabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
AccessibleButton.defaultProps = {
|
||||
|
|
|
@ -150,7 +150,7 @@ export default React.createClass({
|
|||
showAddress={this.props.showAddress}
|
||||
justified={true}
|
||||
networkName="vector"
|
||||
networkUrl="img/search-icon-vector.svg"
|
||||
networkUrl={require("../../../../res/img/search-icon-vector.svg")}
|
||||
/>
|
||||
</div>,
|
||||
);
|
||||
|
|
|
@ -54,7 +54,7 @@ export default React.createClass({
|
|||
address.avatarMxc, 25, 25, 'crop',
|
||||
));
|
||||
} else if (address.addressType === 'email') {
|
||||
imgUrls.push('img/icon-email-user.svg');
|
||||
imgUrls.push(require("../../../../res/img/icon-email-user.svg"));
|
||||
}
|
||||
|
||||
// Removing networks for now as they're not really supported
|
||||
|
@ -141,7 +141,7 @@ export default React.createClass({
|
|||
if (this.props.canDismiss) {
|
||||
dismiss = (
|
||||
<div className="mx_AddressTile_dismiss" onClick={this.props.onDismissed} >
|
||||
<TintableSvg src="img/icon-address-delete.svg" width="9" height="9" />
|
||||
<TintableSvg src={require("../../../../res/img/icon-address-delete.svg")} width="9" height="9" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ export default class AppPermission extends React.Component {
|
|||
return (
|
||||
<div className='mx_AppPermissionWarning'>
|
||||
<div className='mx_AppPermissionWarningImage'>
|
||||
<img src='img/warning.svg' alt={_t('Warning!')} />
|
||||
<img src={require("../../../../res/img/warning.svg")} alt={_t('Warning!')} />
|
||||
</div>
|
||||
<div className='mx_AppPermissionWarningText'>
|
||||
<span className='mx_AppPermissionWarningTextLabel'>{ _t('Do you want to load widget from URL:') }</span> <span className='mx_AppPermissionWarningTextURL'>{ this.state.curlBase }</span>
|
||||
|
|
|
@ -582,19 +582,21 @@ export default class AppTile extends React.Component {
|
|||
// editing is done in scalar
|
||||
const showEditButton = Boolean(this._scalarClient && this._canUserModify());
|
||||
const deleteWidgetLabel = this._deleteWidgetLabel();
|
||||
let deleteIcon = 'img/cancel_green.svg';
|
||||
let deleteIcon = require("../../../../res/img/cancel_green.svg");
|
||||
let deleteClasses = 'mx_AppTileMenuBarWidget';
|
||||
if (this._canUserModify()) {
|
||||
deleteIcon = 'img/icon-delete-pink.svg';
|
||||
deleteIcon = require("../../../../res/img/icon-delete-pink.svg");
|
||||
deleteClasses += ' mx_AppTileMenuBarWidgetDelete';
|
||||
}
|
||||
|
||||
// Picture snapshot - only show button when apps are maximised.
|
||||
const showPictureSnapshotButton = this._hasCapability('m.capability.screenshot') && this.props.show;
|
||||
const showPictureSnapshotIcon = 'img/camera_green.svg';
|
||||
const popoutWidgetIcon = 'img/button-new-window.svg';
|
||||
const reloadWidgetIcon = 'img/button-refresh.svg';
|
||||
const windowStateIcon = (this.props.show ? 'img/minimize.svg' : 'img/maximize.svg');
|
||||
const showPictureSnapshotIcon = require("../../../../res/img/camera_green.svg");
|
||||
const popoutWidgetIcon = require("../../../../res/img/button-new-window.svg");
|
||||
const reloadWidgetIcon = require("../../../../res/img/button-refresh.svg");
|
||||
const minimizeIcon = require("../../../../res/img/minimize.svg");
|
||||
const maximizeIcon = require("../../../../res/img/maximize.svg");
|
||||
const windowStateIcon = (this.props.show ? minimizeIcon : maximizeIcon);
|
||||
|
||||
let appTileClass;
|
||||
if (this.props.miniMode) {
|
||||
|
@ -653,7 +655,7 @@ export default class AppTile extends React.Component {
|
|||
|
||||
{ /* Edit widget */ }
|
||||
{ showEditButton && <TintableSvgButton
|
||||
src="img/edit_green.svg"
|
||||
src={require("../../../../res/img/edit_green.svg")}
|
||||
className={"mx_AppTileMenuBarWidget " +
|
||||
(this.props.showDelete ? "mx_AppTileMenuBarWidgetPadding" : "")}
|
||||
title={_t('Edit')}
|
||||
|
|
|
@ -5,7 +5,7 @@ const AppWarning = (props) => {
|
|||
return (
|
||||
<div className='mx_AppPermissionWarning'>
|
||||
<div className='mx_AppPermissionWarningImage'>
|
||||
<img src='img/warning.svg' alt='' />
|
||||
<img src={require("../../../../res/img/warning.svg")} alt='' />
|
||||
</div>
|
||||
<div className='mx_AppPermissionWarningText'>
|
||||
<span className='mx_AppPermissionWarningTextLabel'>{ props.errorMsg }</span>
|
||||
|
|
|
@ -25,7 +25,7 @@ const CreateRoomButton = function(props) {
|
|||
<ActionButton action="view_create_room"
|
||||
mouseOverAction={props.callout ? "callout_create_room" : null}
|
||||
label={_t("Create new room")}
|
||||
iconPath="img/icons-create-room.svg"
|
||||
iconPath={require("../../../../res/img/icons-create-room.svg")}
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
/>
|
||||
|
|
|
@ -62,13 +62,13 @@ const EditableItem = React.createClass({
|
|||
{ this.props.onAdd ?
|
||||
<div className="mx_EditableItem_addButton">
|
||||
<img className="mx_filterFlipColor"
|
||||
src="img/plus.svg" width="14" height="14"
|
||||
src={require("../../../../res/img/plus.svg")} width="14" height="14"
|
||||
alt={_t("Add")} onClick={this.onAdd} />
|
||||
</div>
|
||||
:
|
||||
<div className="mx_EditableItem_removeButton">
|
||||
<img className="mx_filterFlipColor"
|
||||
src="img/cancel-small.svg" width="14" height="14"
|
||||
src={require("../../../../res/img/cancel-small.svg")} width="14" height="14"
|
||||
alt={_t("Delete")} onClick={this.onRemove} />
|
||||
</div>
|
||||
}
|
||||
|
|
54
src/components/views/elements/Field.js
Normal file
54
src/components/views/elements/Field.js
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Copyright 2019 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default class Field extends React.PureComponent {
|
||||
static propTypes = {
|
||||
// The field's ID, which binds the input and label together.
|
||||
id: PropTypes.string.isRequired,
|
||||
// The field's <input> type. Defaults to "text".
|
||||
type: PropTypes.string,
|
||||
// The field's label string.
|
||||
label: PropTypes.string,
|
||||
// The field's placeholder string.
|
||||
placeholder: PropTypes.string,
|
||||
// The type of field to create. Defaults to "input". Should be "input" or "select".
|
||||
// To define options for a select, use <Field><option ... /></Field>
|
||||
element: PropTypes.string,
|
||||
// All other props pass through to the <input>.
|
||||
}
|
||||
|
||||
render() {
|
||||
const extraProps = Object.assign({}, this.props);
|
||||
|
||||
// Remove explicit properties that shouldn't be copied
|
||||
delete extraProps.element;
|
||||
delete extraProps.children;
|
||||
|
||||
// Set some defaults for the element
|
||||
extraProps.type = extraProps.type || "text";
|
||||
|
||||
const element = this.props.element || "input";
|
||||
const fieldInput = React.createElement(element, extraProps, this.props.children);
|
||||
|
||||
return <div className="mx_Field">
|
||||
{fieldInput}
|
||||
<label htmlFor={this.props.id}>{this.props.label}</label>
|
||||
</div>;
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ const HomeButton = function(props) {
|
|||
return (
|
||||
<ActionButton action="view_home_page"
|
||||
label={_t("Home")}
|
||||
iconPath="img/icons-home.svg"
|
||||
iconPath={require("../../../../res/img/icons-home.svg")}
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
/>
|
||||
|
|
|
@ -176,7 +176,7 @@ module.exports = React.createClass({
|
|||
<img src={this.props.src} style={style} />
|
||||
<div className="mx_ImageView_labelWrapper">
|
||||
<div className="mx_ImageView_label">
|
||||
<AccessibleButton className="mx_ImageView_cancel" onClick={ this.props.onFinished }><img src="img/cancel-white.svg" width="18" height="18" alt={ _t('Close') } /></AccessibleButton>
|
||||
<AccessibleButton className="mx_ImageView_cancel" onClick={ this.props.onFinished }><img src={require("../../../../res/img/cancel-white.svg")} width="18" height="18" alt={ _t('Close') } /></AccessibleButton>
|
||||
<div className="mx_ImageView_shim">
|
||||
</div>
|
||||
<div className="mx_ImageView_name">
|
||||
|
|
|
@ -26,7 +26,7 @@ module.exports = React.createClass({
|
|||
|
||||
return (
|
||||
<div className="mx_InlineSpinner">
|
||||
<img src="img/spinner.gif" width={w} height={h} className={imgClass} />
|
||||
<img src={require("../../../../res/img/spinner.gif")} width={w} height={h} className={imgClass} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -80,7 +80,11 @@ export default class ManageIntegsButton extends React.Component {
|
|||
});
|
||||
|
||||
if (this.state.scalarError && !this.scalarClient.hasCredentials()) {
|
||||
integrationsWarningTriangle = <img src="img/warning.svg" title={_t('Integrations Error')} width="17" />;
|
||||
integrationsWarningTriangle = <img
|
||||
src={require("../../../../res/img/warning.svg")}
|
||||
title={_t('Integrations Error')}
|
||||
width="17"
|
||||
/>;
|
||||
// Popup shown when hovering over integrationsButton_error (via CSS)
|
||||
integrationsErrorPopup = (
|
||||
<span className="mx_RoomSettings_integrationsButton_errorPopup">
|
||||
|
@ -91,7 +95,7 @@ export default class ManageIntegsButton extends React.Component {
|
|||
|
||||
integrationsButton = (
|
||||
<AccessibleButton className={integrationsButtonClasses} onClick={this.onManageIntegrations} title={_t('Manage Integrations')}>
|
||||
<TintableSvg src="img/feather-icons/grid.svg" width="20" height="20" />
|
||||
<TintableSvg src={require("../../../../res/img/feather-icons/grid.svg")} width="20" height="20" />
|
||||
{ integrationsWarningTriangle }
|
||||
{ integrationsErrorPopup }
|
||||
</AccessibleButton>
|
||||
|
|
|
@ -27,7 +27,7 @@ module.exports = React.createClass({
|
|||
return (
|
||||
<div className="mx_Spinner">
|
||||
<div className="mx_Spinner_Msg">{ msg }</div>
|
||||
<img src="img/spinner.gif" width={w} height={h} className={imgClass} />
|
||||
<img src={require("../../../../res/img/spinner.gif")} width={w} height={h} className={imgClass} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -25,7 +25,7 @@ const RoomDirectoryButton = function(props) {
|
|||
<ActionButton action="view_room_directory"
|
||||
mouseOverAction={props.callout ? "callout_room_directory" : null}
|
||||
label={_t("Room directory")}
|
||||
iconPath="img/icons-directory.svg"
|
||||
iconPath={require("../../../../res/img/icons-directory.svg")}
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
/>
|
||||
|
|
|
@ -24,7 +24,7 @@ const SettingsButton = function(props) {
|
|||
return (
|
||||
<ActionButton action="view_user_settings"
|
||||
label={_t("Settings")}
|
||||
iconPath="img/icons-settings.svg"
|
||||
iconPath={require("../../../../res/img/icons-settings.svg")}
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
/>
|
||||
|
|
|
@ -27,7 +27,7 @@ module.exports = React.createClass({
|
|||
const imgClass = this.props.imgClassName || "";
|
||||
return (
|
||||
<div className="mx_Spinner">
|
||||
<img src="img/spinner.gif" width={w} height={h} className={imgClass} />
|
||||
<img src={require("../../../../res/img/spinner.gif")} width={w} height={h} className={imgClass} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -25,7 +25,7 @@ const StartChatButton = function(props) {
|
|||
<ActionButton action="view_create_chat"
|
||||
mouseOverAction={props.callout ? "callout_start_chat" : null}
|
||||
label={_t("Start chat")}
|
||||
iconPath="img/icons-people.svg"
|
||||
iconPath={require("../../../../res/img/icons-people.svg")}
|
||||
size={props.size}
|
||||
tooltip={props.tooltip}
|
||||
/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue