From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../components/AccessibilityTreeFilter.js | 171 +++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 devtools/client/accessibility/components/AccessibilityTreeFilter.js (limited to 'devtools/client/accessibility/components/AccessibilityTreeFilter.js') diff --git a/devtools/client/accessibility/components/AccessibilityTreeFilter.js b/devtools/client/accessibility/components/AccessibilityTreeFilter.js new file mode 100644 index 0000000000..90eabd350a --- /dev/null +++ b/devtools/client/accessibility/components/AccessibilityTreeFilter.js @@ -0,0 +1,171 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +/* global gTelemetry */ + +// React +const { + createFactory, + Component, +} = require("resource://devtools/client/shared/vendor/react.js"); +const { + div, + hr, + span, +} = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); +const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js"); +const { + L10N, +} = require("resource://devtools/client/accessibility/utils/l10n.js"); + +loader.lazyGetter(this, "MenuButton", function () { + return createFactory( + require("resource://devtools/client/shared/components/menu/MenuButton.js") + ); +}); +loader.lazyGetter(this, "MenuItem", function () { + return createFactory( + require("resource://devtools/client/shared/components/menu/MenuItem.js") + ); +}); +loader.lazyGetter(this, "MenuList", function () { + return createFactory( + require("resource://devtools/client/shared/components/menu/MenuList.js") + ); +}); + +const actions = require("resource://devtools/client/accessibility/actions/audit.js"); + +const { + connect, +} = require("resource://devtools/client/shared/vendor/react-redux.js"); +const { + FILTERS, +} = require("resource://devtools/client/accessibility/constants.js"); + +const TELEMETRY_AUDIT_ACTIVATED = "devtools.accessibility.audit_activated"; +const FILTER_LABELS = { + [FILTERS.NONE]: "accessibility.filter.none", + [FILTERS.ALL]: "accessibility.filter.all2", + [FILTERS.CONTRAST]: "accessibility.filter.contrast", + [FILTERS.KEYBOARD]: "accessibility.filter.keyboard", + [FILTERS.TEXT_LABEL]: "accessibility.filter.textLabel", +}; + +class AccessibilityTreeFilter extends Component { + static get propTypes() { + return { + auditing: PropTypes.array.isRequired, + filters: PropTypes.object.isRequired, + dispatch: PropTypes.func.isRequired, + describedby: PropTypes.string, + toolboxDoc: PropTypes.object.isRequired, + audit: PropTypes.func.isRequired, + }; + } + + async toggleFilter(filterKey) { + const { audit: auditFunc, dispatch, filters } = this.props; + + if (filterKey !== FILTERS.NONE && !filters[filterKey]) { + if (gTelemetry) { + gTelemetry.keyedScalarAdd(TELEMETRY_AUDIT_ACTIVATED, filterKey, 1); + } + + dispatch(actions.auditing(filterKey)); + await dispatch(actions.audit(auditFunc, filterKey)); + } + + // We wait to dispatch filter toggle until the tree is ready to be filtered + // right after the audit. This is to make sure that we render an empty tree + // (filtered) while the audit is running. + dispatch(actions.filterToggle(filterKey)); + } + + onClick(filterKey) { + this.toggleFilter(filterKey); + } + + render() { + const { auditing, filters, describedby, toolboxDoc } = this.props; + const toolbarLabelID = "accessibility-tree-filters-label"; + const filterNoneChecked = !Object.values(filters).includes(true); + const items = [ + MenuItem({ + key: FILTERS.NONE, + checked: filterNoneChecked, + className: `filter ${FILTERS.NONE}`, + label: L10N.getStr(FILTER_LABELS[FILTERS.NONE]), + onClick: this.onClick.bind(this, FILTERS.NONE), + disabled: !!auditing.length, + }), + hr({ key: "hr-1" }), + ]; + + const { [FILTERS.ALL]: filterAllChecked, ...filtersWithoutAll } = filters; + items.push( + MenuItem({ + key: FILTERS.ALL, + checked: filterAllChecked, + className: `filter ${FILTERS.ALL}`, + label: L10N.getStr(FILTER_LABELS[FILTERS.ALL]), + onClick: this.onClick.bind(this, FILTERS.ALL), + disabled: !!auditing.length, + }), + hr({ key: "hr-2" }), + Object.entries(filtersWithoutAll).map(([filterKey, active]) => + MenuItem({ + key: filterKey, + checked: active, + className: `filter ${filterKey}`, + label: L10N.getStr(FILTER_LABELS[filterKey]), + onClick: this.onClick.bind(this, filterKey), + disabled: !!auditing.length, + }) + ) + ); + + let label; + if (filterNoneChecked) { + label = L10N.getStr(FILTER_LABELS[FILTERS.NONE]); + } else if (filterAllChecked) { + label = L10N.getStr(FILTER_LABELS[FILTERS.ALL]); + } else { + label = Object.keys(filtersWithoutAll) + .filter(filterKey => filtersWithoutAll[filterKey]) + .map(filterKey => L10N.getStr(FILTER_LABELS[filterKey])) + .join(", "); + } + + return div( + { + role: "group", + className: "accessibility-tree-filters", + "aria-labelledby": toolbarLabelID, + "aria-describedby": describedby, + }, + span( + { id: toolbarLabelID, role: "presentation" }, + L10N.getStr("accessibility.tree.filters") + ), + MenuButton( + { + menuId: "accessibility-tree-filters-menu", + toolboxDoc, + className: `devtools-button badge toolbar-menu-button filters`, + label, + }, + MenuList({}, items) + ) + ); + } +} + +const mapStateToProps = ({ audit: { filters, auditing } }) => { + return { filters, auditing }; +}; + +// Exports from this module +module.exports = connect(mapStateToProps)(AccessibilityTreeFilter); -- cgit v1.2.3