From 369b483356fc23333c615c642017c3b9ee38fe07 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford <7019101+cwillisf@users.noreply.github.com> Date: Tue, 23 May 2023 16:56:56 -0700 Subject: [PATCH] fix: balance wrapped text where appropriate in connection flow --- package-lock.json | 11 +++ package.json | 1 + .../connection-modal/auto-scanning-step.jsx | 3 +- .../connection-modal/scanning-step.jsx | 3 +- .../update-peripheral-step.jsx | 12 ++- src/containers/balanced-formatted-message.jsx | 20 ++++ src/containers/balanced-text.jsx | 97 +++++++++++++++++++ 7 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 src/containers/balanced-formatted-message.jsx create mode 100644 src/containers/balanced-text.jsx diff --git a/package-lock.json b/package-lock.json index 6db2da361..40c22c102 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@microbit/microbit-universal-hex": "0.2.2", "arraybuffer-loader": "^1.0.6", "autoprefixer": "^9.0.1", + "balance-text": "3.3.1", "base64-loader": "1.0.0", "bowser": "1.9.4", "cat-blocks": "npm:scratch-blocks@0.1.0-prerelease.20220318143026", @@ -9069,6 +9070,11 @@ "babylon": "bin/babylon.js" } }, + "node_modules/balance-text": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/balance-text/-/balance-text-3.3.1.tgz", + "integrity": "sha512-tpnHvo1w0rJ5rbu+jZKf7NLKKg6XZ6eAwREP/9jEDJ+ZTBi6jQFqn/UGARL3/oqD8SgQbyTwBXBjhKDdTgoPRw==" + }, "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -38227,6 +38233,11 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, + "balance-text": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/balance-text/-/balance-text-3.3.1.tgz", + "integrity": "sha512-tpnHvo1w0rJ5rbu+jZKf7NLKKg6XZ6eAwREP/9jEDJ+ZTBi6jQFqn/UGARL3/oqD8SgQbyTwBXBjhKDdTgoPRw==" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", diff --git a/package.json b/package.json index 38b55c990..6cf0b12f4 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@microbit/microbit-universal-hex": "0.2.2", "arraybuffer-loader": "^1.0.6", "autoprefixer": "^9.0.1", + "balance-text": "3.3.1", "base64-loader": "1.0.0", "bowser": "1.9.4", "cat-blocks": "npm:scratch-blocks@0.1.0-prerelease.20220318143026", diff --git a/src/components/connection-modal/auto-scanning-step.jsx b/src/components/connection-modal/auto-scanning-step.jsx index ed024706a..c74f95925 100644 --- a/src/components/connection-modal/auto-scanning-step.jsx +++ b/src/components/connection-modal/auto-scanning-step.jsx @@ -4,6 +4,7 @@ import React from 'react'; import keyMirror from 'keymirror'; import classNames from 'classnames'; +import BalancedFormattedMessage from '../../containers/balanced-formatted-message.jsx'; import Box from '../box/box.jsx'; import Dots from './dots.jsx'; @@ -93,7 +94,7 @@ const AutoScanningStep = props => { {showUpdate && ( - { // Show this message if we're done scanning AND we can update // Note that it's possible the list includes devices but does not include the desired device, // so don't limit this message to the (props.peripheralList.length === 0) case - ); } else if (this.state.err.message === 'No valid interfaces found.') { // this is a special case where the micro:bit's communication firmware is too old to support WebUSB - resultsContent = ( {!showResults && - { + const {className, resize, style, ...otherProps} = props; + const balancedTextProps = {className, resize, style}; + return ( + {(...children) => {children}} + ); +}; + +BalancedFormattedMessage.propTypes = { + ...FormattedMessage.propTypes, + resize: PropTypes.bool +}; + +export default BalancedFormattedMessage; diff --git a/src/containers/balanced-text.jsx b/src/containers/balanced-text.jsx new file mode 100644 index 000000000..9a359ce86 --- /dev/null +++ b/src/containers/balanced-text.jsx @@ -0,0 +1,97 @@ +/* + * Attempts to balance the length of each line of wrapped text. + * If the text does not wrap, this component will have no effect. + * See https://developer.chrome.com/blog/css-text-wrap-balance/ + * Patterned after `react-balance-text` with adjustments to support our method of styling. + * We may want to replace this with react-wrap-balancer once we use React >= 16.8 + */ + +import React from 'react'; +import PropTypes from 'prop-types'; + +import balanceText from 'balance-text'; +import bindAll from 'lodash.bindall'; + +class BalancedText extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'balanceText', + 'handleResize' + ]); + this.state = { + forceHide: true + }; + } + + componentDidMount () { + self.addEventListener('resize', this.handleResize); + this.stopHiding(); + } + + componentDidUpdate () { + this.balanceText(); + } + + componentWillUnmount () { + self.removeEventListener('resize', this.handleResize); + } + + handleResize () { + if (this.props.resize) { + this.balanceText(); + } + } + + balanceText () { + const {container} = this; + if (container) { + balanceText(container, {}); + } + } + + stopHiding () { + this.setState({forceHide: false}); + setTimeout(() => this.balanceText(), 0); + } + + render () { + let { + children, + resize, // eslint-disable-line no-unused-vars + style, + ...otherProps + } = this.props; + + if (this.state.forceHide) { + style = Object.assign({}, style, {visibility: 'hidden'}); + } + + return ( +
+ { + this.container = container; + }} + > + {children} + +
+ ); + } +} + +BalancedText.propTypes = { + children: PropTypes.node, + resize: PropTypes.bool, + style: PropTypes.object // eslint-disable-line react/forbid-prop-types +}; + +BalancedText.defaultProps = { + resize: true +}; + +export default BalancedText;