Skip to content

Commit

Permalink
fix(number-field): show decimal on iPad minimized keyboard (#4784)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Rúben Carvalho <rubcar@sapo.pt>
  • Loading branch information
mizgaionutalexandru and rubencarvalho authored Oct 10, 2024
1 parent fc9a448 commit deb7a1c
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 28 deletions.
50 changes: 22 additions & 28 deletions packages/number-field/src/NumberField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/

import { NumberFormatter, NumberParser } from '@internationalized/number';
import {
CSSResultArray,
html,
Expand All @@ -21,24 +22,24 @@ import {
property,
query,
} from '@spectrum-web-components/base/src/decorators.js';
import { streamingListener } from '@spectrum-web-components/base/src/streaming-listener.js';
import {
LanguageResolutionController,
languageResolverUpdatedSymbol,
} from '@spectrum-web-components/reactive-controllers/src/LanguageResolution.js';
import { streamingListener } from '@spectrum-web-components/base/src/streaming-listener.js';
import { NumberFormatter, NumberParser } from '@internationalized/number';

import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron50.js';
import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron75.js';
import chevronStyles from '@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js';
import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';
import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron200.js';
import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron50.js';
import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron75.js';
import '@spectrum-web-components/infield-button/sp-infield-button.js';
import {
isAndroid,
isIOS,
isIPhone,
} from '@spectrum-web-components/shared/src/platform.js';
import { TextfieldBase } from '@spectrum-web-components/textfield';
import chevronStyles from '@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js';
import styles from './number-field.css.js';

export const FRAMES_PER_CHANGE = 5;
Expand Down Expand Up @@ -241,7 +242,7 @@ export class NumberField extends TextfieldBase {
const uniqueSeparators = new Set(separators);

if (
isIPhone() &&
isIOS() &&
this.inputElement.inputMode === 'decimal' &&
normalizedValue !== this.valueBeforeFocus
) {
Expand Down Expand Up @@ -802,30 +803,23 @@ export class NumberField extends TextfieldBase {
}

if (changes.has('min') || changes.has('formatOptions')) {
let inputMode = 'numeric';
const hasNegative = typeof this.min !== 'undefined' && this.min < 0;
const hasOnlyPositives =
typeof this.min !== 'undefined' && this.min >= 0;

const { maximumFractionDigits } =
this.numberFormatter.resolvedOptions();
const hasDecimals = maximumFractionDigits > 0;
/* c8 ignore next 18 */
if (isIPhone()) {
// iPhone doesn't have a minus sign in either numeric or decimal.
// Note this is only for iPhone, not iPad, which always has both
// minus and decimal in numeric.
if (hasNegative) {
inputMode = 'text';
} else if (hasDecimals) {
inputMode = 'decimal';
}
} else if (isAndroid()) {
// Android numeric has both a decimal point and minus key.
// decimal does not have a minus key.
if (hasNegative) {
inputMode = 'numeric';
} else if (hasDecimals) {
inputMode = 'decimal';
}
}
const hasDecimals =
maximumFractionDigits && maximumFractionDigits > 0;

let inputMode = 'numeric';
/* c8 ignore next 5 */
// iPhone doesn't have a minus sign in either numeric or decimal.
if (isIPhone() && !hasOnlyPositives) inputMode = 'text';
else if (isIOS() && hasDecimals) inputMode = 'decimal';
// Android numeric has both a decimal point and minus key. Decimal does not have a minus key.
else if (isAndroid() && hasDecimals && hasOnlyPositives)
inputMode = 'decimal';

this.inputElement.inputMode = inputMode;
}
if (
Expand Down
35 changes: 35 additions & 0 deletions packages/number-field/test/number-field.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,28 @@ describe('NumberField', () => {
expect(changeSpy.callCount).to.equal(1);
expect(lastChangeValue, 'last change value').to.equal(10);
});
xit('manages `inputMode` in iPad', async () => {
// setUserAgent is not currently supported by Playwright
await setUserAgent(
'Mozilla/5.0 (iPad; CPU OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile15E148 Safari/604.1'
);
el.min = 0;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('numeric');
el.min = -10;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('numeric');
el.min = undefined;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('numeric');
el.formatOptions = {
minimumFractionDigits: 1,
maximumFractionDigits: 2,
};
el.min = 0;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('decimal');
});
xit('manages `inputMode` in iPhone', async () => {
// setUserAgent is not currently supported by Playwright
await setUserAgent(
Expand All @@ -1239,6 +1261,9 @@ describe('NumberField', () => {
el.min = -10;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('text');
el.min = undefined;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('text');
el.formatOptions = {
minimumFractionDigits: 1,
maximumFractionDigits: 2,
Expand All @@ -1258,13 +1283,23 @@ describe('NumberField', () => {
el.min = -10;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('numeric');
el.min = undefined;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('numeric');
el.formatOptions = {
minimumFractionDigits: 1,
maximumFractionDigits: 2,
};
el.min = 0;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('decimal');
el.formatOptions = {
minimumFractionDigits: 1,
maximumFractionDigits: 2,
};
el.min = -10;
await elementUpdated(el);
expect(el.focusElement.inputMode).to.equal('numeric');
});
it('constrains `value`', async () => {
el.value = 0;
Expand Down

0 comments on commit deb7a1c

Please sign in to comment.