refactor(picker): rename internal picker components to ion-picker and ion-picker-column (#28589)
@@ -34,7 +34,7 @@
|
||||
* widest item in the column. Setting a minimum
|
||||
* width avoids this layout shifting.
|
||||
*/
|
||||
ion-picker-column-internal {
|
||||
ion-picker-column {
|
||||
min-width: 26px;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { caretDownSharp, caretUpSharp, chevronBack, chevronDown, chevronForward
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import type { Color, Mode, StyleEventDetail } from '../../interface';
|
||||
import type { PickerColumnItem } from '../picker-column-internal/picker-column-internal-interfaces';
|
||||
import type { PickerColumnItem } from '../picker-column/picker-column-interfaces';
|
||||
|
||||
import type {
|
||||
DatetimePresentation,
|
||||
@@ -1527,7 +1527,7 @@ export class Datetime implements ComponentInterface {
|
||||
forcePresentation === 'time-date'
|
||||
? [this.renderTimePickerColumns(forcePresentation), this.renderDatePickerColumns(forcePresentation)]
|
||||
: [this.renderDatePickerColumns(forcePresentation), this.renderTimePickerColumns(forcePresentation)];
|
||||
return <ion-picker-internal>{renderArray}</ion-picker-internal>;
|
||||
return <ion-picker>{renderArray}</ion-picker>;
|
||||
}
|
||||
|
||||
private renderDatePickerColumns(forcePresentation: string) {
|
||||
@@ -1613,7 +1613,7 @@ export class Datetime implements ComponentInterface {
|
||||
: `${defaultParts.year}-${defaultParts.month}-${defaultParts.day}`;
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
<ion-picker-column
|
||||
class="date-column"
|
||||
color={this.color}
|
||||
disabled={disabled}
|
||||
@@ -1647,7 +1647,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
></ion-picker-column>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1733,7 +1733,7 @@ export class Datetime implements ComponentInterface {
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
<ion-picker-column
|
||||
class="day-column"
|
||||
color={this.color}
|
||||
disabled={disabled}
|
||||
@@ -1764,7 +1764,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
></ion-picker-column>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1778,7 +1778,7 @@ export class Datetime implements ComponentInterface {
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
<ion-picker-column
|
||||
class="month-column"
|
||||
color={this.color}
|
||||
disabled={disabled}
|
||||
@@ -1809,7 +1809,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
></ion-picker-column>
|
||||
);
|
||||
}
|
||||
private renderYearPickerColumn(years: PickerColumnItem[]) {
|
||||
@@ -1822,7 +1822,7 @@ export class Datetime implements ComponentInterface {
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
<ion-picker-column
|
||||
class="year-column"
|
||||
color={this.color}
|
||||
disabled={disabled}
|
||||
@@ -1853,7 +1853,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
></ion-picker-column>
|
||||
);
|
||||
}
|
||||
private renderTimePickerColumns(forcePresentation: string) {
|
||||
@@ -1897,7 +1897,7 @@ export class Datetime implements ComponentInterface {
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
<ion-picker-column
|
||||
color={this.color}
|
||||
disabled={disabled}
|
||||
value={activePart.hour}
|
||||
@@ -1916,7 +1916,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
></ion-picker-column>
|
||||
);
|
||||
}
|
||||
private renderMinutePickerColumn(minutesData: PickerColumnItem[]) {
|
||||
@@ -1926,7 +1926,7 @@ export class Datetime implements ComponentInterface {
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
<ion-picker-column
|
||||
color={this.color}
|
||||
disabled={disabled}
|
||||
value={activePart.minute}
|
||||
@@ -1945,7 +1945,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
></ion-picker-column>
|
||||
);
|
||||
}
|
||||
private renderDayPeriodPickerColumn(dayPeriodData: PickerColumnItem[]) {
|
||||
@@ -1958,7 +1958,7 @@ export class Datetime implements ComponentInterface {
|
||||
const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
<ion-picker-column
|
||||
style={isDayPeriodRTL ? { order: '-1' } : {}}
|
||||
color={this.color}
|
||||
disabled={disabled}
|
||||
@@ -1981,7 +1981,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
></ion-picker-column-internal>
|
||||
></ion-picker-column>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2345,7 +2345,7 @@ export class Datetime implements ComponentInterface {
|
||||
* This will correctly scroll the element position to the correct time value,
|
||||
* before the popover is fully presented.
|
||||
*/
|
||||
const cols = (ev.target! as HTMLElement).querySelectorAll('ion-picker-column-internal');
|
||||
const cols = (ev.target! as HTMLElement).querySelectorAll('ion-picker-column');
|
||||
// TODO (FW-615): Potentially remove this when intersection observers are fixed in picker column
|
||||
cols.forEach((col) => col.scrollActiveItemIntoView());
|
||||
}}
|
||||
|
||||
@@ -52,28 +52,28 @@
|
||||
}
|
||||
|
||||
/*
|
||||
The second selectors that target ion-picker(-column)-internal
|
||||
The second selectors that target ion-picker(-column)
|
||||
directly are for styling the time picker. This is currently
|
||||
undocumented usage.
|
||||
*/
|
||||
|
||||
.custom-grid-wheel,
|
||||
ion-picker-internal {
|
||||
ion-picker {
|
||||
--wheel-highlight-background: rgb(218, 216, 255);
|
||||
--wheel-fade-background-rgb: 245, 235, 247;
|
||||
}
|
||||
|
||||
ion-picker-internal {
|
||||
ion-picker {
|
||||
background-color: rgb(245, 235, 247);
|
||||
}
|
||||
|
||||
.custom-grid-wheel::part(wheel-item),
|
||||
ion-picker-column-internal::part(wheel-item) {
|
||||
ion-picker-column::part(wheel-item) {
|
||||
color: rgb(255, 134, 154);
|
||||
}
|
||||
|
||||
.custom-grid-wheel::part(wheel-item active),
|
||||
ion-picker-column-internal::part(wheel-item active) {
|
||||
ion-picker-column::part(wheel-item active) {
|
||||
color: rgb(128, 30, 171);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import { h } from '@stencil/core';
|
||||
import { newSpecPage } from '@stencil/core/testing';
|
||||
|
||||
import { Datetime } from '../../../datetime/datetime';
|
||||
import { PickerColumnInternal } from '../../../picker-column-internal/picker-column-internal';
|
||||
import { PickerInternal } from '../../../picker-internal/picker-internal';
|
||||
import { PickerColumn } from '../../../picker-column/picker-column';
|
||||
import { Picker } from '../../../picker/picker';
|
||||
|
||||
describe('ion-datetime disabled', () => {
|
||||
beforeEach(() => {
|
||||
@@ -19,7 +19,7 @@ describe('ion-datetime disabled', () => {
|
||||
|
||||
it('picker should be disabled in prefer wheel mode', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Datetime, PickerColumnInternal, PickerInternal],
|
||||
components: [Datetime, PickerColumn, Picker],
|
||||
template: () => (
|
||||
<ion-datetime id="inline-datetime-wheel" disabled prefer-wheel value="2022-04-21T00:00:00"></ion-datetime>
|
||||
),
|
||||
@@ -28,7 +28,7 @@ describe('ion-datetime disabled', () => {
|
||||
await page.waitForChanges();
|
||||
|
||||
const datetime = page.body.querySelector('ion-datetime')!;
|
||||
const columns = datetime.shadowRoot!.querySelectorAll('ion-picker-column-internal');
|
||||
const columns = datetime.shadowRoot!.querySelectorAll('ion-picker-column');
|
||||
|
||||
await expect(columns.length).toEqual(4);
|
||||
|
||||
|
||||
@@ -109,12 +109,8 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
await page.click('.time-body');
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const hours = page.locator(
|
||||
'ion-popover ion-picker-column-internal:nth-child(1) .picker-item:not(.picker-item-empty)'
|
||||
);
|
||||
const minutes = page.locator(
|
||||
'ion-popover ion-picker-column-internal:nth-child(2) .picker-item:not(.picker-item-empty)'
|
||||
);
|
||||
const hours = page.locator('ion-popover ion-picker-column:nth-child(1) .picker-item:not(.picker-item-empty)');
|
||||
const minutes = page.locator('ion-popover ion-picker-column:nth-child(2) .picker-item:not(.picker-item-empty)');
|
||||
|
||||
expect(await hours.count()).toBe(12);
|
||||
expect(await minutes.count()).toBe(60);
|
||||
@@ -219,7 +215,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
);
|
||||
|
||||
const hourPickerItems = page.locator(
|
||||
'ion-datetime ion-picker-column-internal:first-of-type .picker-item:not(.picker-item-empty)'
|
||||
'ion-datetime ion-picker-column:first-of-type .picker-item:not(.picker-item-empty)'
|
||||
);
|
||||
await expect(hourPickerItems).toHaveText(['8', '9', '10', '11']);
|
||||
});
|
||||
@@ -243,7 +239,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
);
|
||||
|
||||
const hourPickerItems = page.locator(
|
||||
'ion-datetime ion-picker-column-internal:first-of-type .picker-item:not(.picker-item-empty)'
|
||||
'ion-datetime ion-picker-column:first-of-type .picker-item:not(.picker-item-empty)'
|
||||
);
|
||||
await expect(hourPickerItems).toHaveText(['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']);
|
||||
});
|
||||
@@ -360,9 +356,7 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const hours = page.locator(
|
||||
'ion-popover ion-picker-column-internal:nth-child(1) .picker-item:not(.picker-item-empty)'
|
||||
);
|
||||
const hours = page.locator('ion-popover ion-picker-column:nth-child(1) .picker-item:not(.picker-item-empty)');
|
||||
|
||||
await expect(await hours.count()).toBe(4);
|
||||
});
|
||||
|
||||
@@ -308,7 +308,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const columns = page.locator('ion-picker-column-internal');
|
||||
const columns = page.locator('ion-picker-column');
|
||||
|
||||
await expect(columns.nth(0)).toHaveClass(/month-column/);
|
||||
await expect(columns.nth(1)).toHaveClass(/day-column/);
|
||||
@@ -329,7 +329,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const columns = page.locator('ion-picker-column-internal');
|
||||
const columns = page.locator('ion-picker-column');
|
||||
|
||||
await expect(columns.nth(0)).toHaveClass(/day-column/);
|
||||
await expect(columns.nth(1)).toHaveClass(/month-column/);
|
||||
|
||||
@@ -227,7 +227,7 @@ class TimePickerFixture {
|
||||
}
|
||||
|
||||
async expectTime(hour: number, minute: number, ampm: string) {
|
||||
const pickerColumns = this.timePicker.locator('ion-picker-column-internal');
|
||||
const pickerColumns = this.timePicker.locator('ion-picker-column');
|
||||
|
||||
await expect(pickerColumns.nth(0)).toHaveJSProperty('value', hour);
|
||||
await expect(pickerColumns.nth(1)).toHaveJSProperty('value', minute);
|
||||
|
||||
@@ -51,7 +51,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const items = page.locator('ion-picker-column-internal:first-of-type .picker-item:not(.picker-item-empty)');
|
||||
const items = page.locator('ion-picker-column:first-of-type .picker-item:not(.picker-item-empty)');
|
||||
await expect(items).toHaveText(['1', '2', '3']);
|
||||
});
|
||||
test('should render correct minutes', async ({ page }) => {
|
||||
@@ -62,7 +62,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const items = page.locator('ion-picker-column-internal:nth-of-type(2) .picker-item:not(.picker-item-empty)');
|
||||
const items = page.locator('ion-picker-column:nth-of-type(2) .picker-item:not(.picker-item-empty)');
|
||||
await expect(items).toHaveText(['01', '02', '03']);
|
||||
});
|
||||
test('should adjust default parts for allowed hour and minute values', async ({ page }) => {
|
||||
@@ -93,13 +93,11 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const minuteItems = page.locator(
|
||||
'ion-picker-column-internal:nth-of-type(2) .picker-item:not(.picker-item-empty)'
|
||||
);
|
||||
const minuteItems = page.locator('ion-picker-column:nth-of-type(2) .picker-item:not(.picker-item-empty)');
|
||||
await expect(minuteItems).toHaveText(['00', '15', '30', '45']);
|
||||
await expect(minuteItems.nth(1)).toHaveClass(/picker-item-active/);
|
||||
|
||||
const hourItems = page.locator('ion-picker-column-internal:nth-of-type(1) .picker-item:not(.picker-item-empty)');
|
||||
const hourItems = page.locator('ion-picker-column:nth-of-type(1) .picker-item:not(.picker-item-empty)');
|
||||
await expect(hourItems).toHaveText(['2']);
|
||||
await expect(hourItems.nth(0)).toHaveClass(/picker-item-active/);
|
||||
|
||||
@@ -107,7 +105,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
* Since the allowed hour is 2AM, the time period
|
||||
* should switch from PM to AM.
|
||||
*/
|
||||
const ampmItems = page.locator('ion-picker-column-internal:nth-of-type(3) .picker-item:not(.picker-item-empty)');
|
||||
const ampmItems = page.locator('ion-picker-column:nth-of-type(3) .picker-item:not(.picker-item-empty)');
|
||||
await expect(ampmItems).toHaveText(['AM', 'PM']);
|
||||
await expect(ampmItems.nth(0)).toHaveClass(/picker-item-active/);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Mode } from '../../../interface';
|
||||
import type { PickerColumnItem } from '../../picker-column-internal/picker-column-internal-interfaces';
|
||||
import type { PickerColumnItem } from '../../picker-column/picker-column-interfaces';
|
||||
import type { DatetimeParts, DatetimeHourCycle } from '../datetime-interface';
|
||||
|
||||
import { isAfter, isBefore, isSameDay } from './comparison';
|
||||
@@ -380,7 +380,7 @@ export const getMonthColumnData = (
|
||||
* @param minParts The minimum bound on the date that can be returned
|
||||
* @param maxParts The maximum bound on the date that can be returned
|
||||
* @param dayValues The allowed date values
|
||||
* @returns Date data to be used in ion-picker-column-internal
|
||||
* @returns Date data to be used in ion-picker-column
|
||||
*/
|
||||
export const getDayColumnData = (
|
||||
locale: string,
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
@import "./picker-column-internal.scss";
|
||||
1
core/src/components/picker-column/picker-column.ios.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import "./picker-column.scss";
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "./picker-column-internal.scss";
|
||||
@import "./picker-column.scss";
|
||||
@import "../../themes/ionic.globals.md";
|
||||
|
||||
:host .picker-item-active {
|
||||
@@ -1,6 +1,6 @@
|
||||
@import "../../themes/ionic.globals";
|
||||
|
||||
// Picker Internal
|
||||
// Picker Column
|
||||
// --------------------------------------------------
|
||||
|
||||
:host {
|
||||
@@ -7,33 +7,32 @@ import { createColorClasses } from '@utils/theme';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import type { Color } from '../../interface';
|
||||
import type { PickerInternalCustomEvent } from '../picker-internal/picker-internal-interfaces';
|
||||
import type { PickerCustomEvent } from '../picker/picker-interfaces';
|
||||
|
||||
import type { PickerColumnItem } from './picker-column-internal-interfaces';
|
||||
import type { PickerColumnItem } from './picker-column-interfaces';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
* @internal
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-picker-column-internal',
|
||||
tag: 'ion-picker-column',
|
||||
styleUrls: {
|
||||
ios: 'picker-column-internal.ios.scss',
|
||||
md: 'picker-column-internal.md.scss',
|
||||
ios: 'picker-column.ios.scss',
|
||||
md: 'picker-column.md.scss',
|
||||
},
|
||||
shadow: true,
|
||||
})
|
||||
export class PickerColumnInternal implements ComponentInterface {
|
||||
export class PickerColumn implements ComponentInterface {
|
||||
private destroyScrollListener?: () => void;
|
||||
private isScrolling = false;
|
||||
private scrollEndCallback?: () => void;
|
||||
private isColumnVisible = false;
|
||||
private parentEl?: HTMLIonPickerInternalElement | null;
|
||||
private parentEl?: HTMLIonPickerElement | null;
|
||||
private canExitInputMode = true;
|
||||
|
||||
@State() isActive = false;
|
||||
|
||||
@Element() el!: HTMLIonPickerColumnInternalElement;
|
||||
@Element() el!: HTMLIonPickerColumnElement;
|
||||
|
||||
/**
|
||||
* If `true`, the user cannot interact with the picker.
|
||||
@@ -123,7 +122,7 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
};
|
||||
new IntersectionObserver(visibleCallback, { threshold: 0.001 }).observe(this.el);
|
||||
|
||||
const parentEl = (this.parentEl = this.el.closest('ion-picker-internal') as HTMLIonPickerInternalElement | null);
|
||||
const parentEl = (this.parentEl = this.el.closest('ion-picker') as HTMLIonPickerElement | null);
|
||||
if (parentEl !== null) {
|
||||
// TODO(FW-2832): type
|
||||
parentEl.addEventListener('ionInputModeChange', (ev: any) => this.inputModeChange(ev));
|
||||
@@ -215,7 +214,7 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
* needs to check if it is the one being made available
|
||||
* for text entry.
|
||||
*/
|
||||
private inputModeChange = (ev: PickerInternalCustomEvent) => {
|
||||
private inputModeChange = (ev: PickerCustomEvent) => {
|
||||
if (!this.numericInput) {
|
||||
return;
|
||||
}
|
||||
@@ -428,7 +427,7 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
* exportparts is needed so ion-datetime can expose the parts
|
||||
* from two layers of shadow nesting. If this causes problems,
|
||||
* the attribute can be moved to datetime.tsx and set on every
|
||||
* instance of ion-picker-column-internal there instead.
|
||||
* instance of ion-picker-column there instead.
|
||||
*/
|
||||
|
||||
return (
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Picker Column Internal - Basic</title>
|
||||
<title>Picker Column - Basic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
@@ -39,16 +39,16 @@
|
||||
<ion-app>
|
||||
<ion-header translucent="true">
|
||||
<ion-toolbar>
|
||||
<ion-title>Picker Column Internal - Basic</ion-title>
|
||||
<ion-title>Picker Column - Basic</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Default</h2>
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal id="default"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column id="default"></ion-picker-column>
|
||||
</ion-picker>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -5,33 +5,33 @@ import { configs, test } from '@utils/test/playwright';
|
||||
* This behavior does not vary across modes/directions.
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('picker-column-internal'), () => {
|
||||
test.describe(title('picker-column'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/src/components/picker-column-internal/test/basic', config);
|
||||
await page.goto('/src/components/picker-column/test/basic', config);
|
||||
});
|
||||
|
||||
test('should render a picker item for each item', async ({ page }) => {
|
||||
const columns = page.locator('ion-picker-column-internal .picker-item:not(.picker-item-empty)');
|
||||
const columns = page.locator('ion-picker-column .picker-item:not(.picker-item-empty)');
|
||||
await expect(columns).toHaveCount(24);
|
||||
});
|
||||
|
||||
test('should render 6 empty picker items', async ({ page }) => {
|
||||
const columns = page.locator('ion-picker-column-internal .picker-item-empty');
|
||||
const columns = page.locator('ion-picker-column .picker-item-empty');
|
||||
await expect(columns).toHaveCount(6);
|
||||
});
|
||||
|
||||
test('should not have an active item when value is not set', async ({ page }) => {
|
||||
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
|
||||
const activeColumn = page.locator('ion-picker-column .picker-item-active');
|
||||
await expect(activeColumn).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('should have an active item when value is set', async ({ page }) => {
|
||||
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
|
||||
await page.locator('#default').evaluate((el: HTMLIonPickerColumnElement) => {
|
||||
el.value = '12';
|
||||
});
|
||||
await page.waitForChanges();
|
||||
|
||||
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
|
||||
const activeColumn = page.locator('ion-picker-column .picker-item-active');
|
||||
|
||||
expect(activeColumn).not.toBeNull();
|
||||
});
|
||||
@@ -40,12 +40,12 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
test.skip('scrolling should change the active item', async ({ page, skip }) => {
|
||||
skip.browser('firefox', 'https://bugzilla.mozilla.org/show_bug.cgi?id=1766890');
|
||||
|
||||
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
|
||||
await page.locator('#default').evaluate((el: HTMLIonPickerColumnElement) => {
|
||||
el.scrollTop = 801;
|
||||
});
|
||||
await page.waitForChanges();
|
||||
|
||||
const activeColumn = page.locator('ion-picker-column-internal .picker-item-active');
|
||||
const activeColumn = page.locator('ion-picker-column .picker-item-active');
|
||||
|
||||
expect(await activeColumn?.innerText()).toEqual('23');
|
||||
});
|
||||
@@ -55,7 +55,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
|
||||
const ionChangeSpy = await page.spyOnEvent('ionChange');
|
||||
|
||||
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
|
||||
await page.locator('#default').evaluate((el: HTMLIonPickerColumnElement) => {
|
||||
el.value = '12';
|
||||
});
|
||||
|
||||
@@ -68,7 +68,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
|
||||
const ionChangeSpy = await page.spyOnEvent('ionChange');
|
||||
|
||||
await page.locator('#default').evaluate((el: HTMLIonPickerColumnInternalElement) => {
|
||||
await page.locator('#default').evaluate((el: HTMLIonPickerColumnElement) => {
|
||||
el.scrollTo(0, el.scrollHeight);
|
||||
});
|
||||
await page.waitForChanges();
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Picker Column Internal - Basic</title>
|
||||
<title>Picker Column - Basic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
@@ -39,22 +39,22 @@
|
||||
<ion-app>
|
||||
<ion-header translucent="true">
|
||||
<ion-toolbar>
|
||||
<ion-title>Picker Column Internal - Disabled</ion-title>
|
||||
<ion-title>Picker Column - Disabled</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Even items disabled</h2>
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal id="half-disabled"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column id="half-disabled"></ion-picker-column>
|
||||
</ion-picker>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>Column disabled</h2>
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal id="column-disabled" value="11" disabled></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column id="column-disabled" value="11" disabled></ion-picker-column>
|
||||
</ion-picker>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -5,16 +5,16 @@ import { configs, test } from '@utils/test/playwright';
|
||||
* This behavior does not vary across directions.
|
||||
*/
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('picker-column-internal: disabled rendering'), () => {
|
||||
test.describe(title('picker-column: disabled rendering'), () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal value="b"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column value="b"></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: 'A', value: 'a', disabled: true },
|
||||
{ text: 'B', value: 'b' },
|
||||
@@ -25,8 +25,8 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
config
|
||||
);
|
||||
|
||||
const picker = page.locator('ion-picker-internal');
|
||||
await expect(picker).toHaveScreenshot(screenshot(`picker-internal-disabled`));
|
||||
const picker = page.locator('ion-picker');
|
||||
await expect(picker).toHaveScreenshot(screenshot(`picker-disabled`));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -35,16 +35,16 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
* This behavior does not vary across modes/directions.
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('picker-column-internal: disabled items'), () => {
|
||||
test.describe(title('picker-column: disabled items'), () => {
|
||||
test('all picker items should be enabled by default', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: 'A', value: 'a' },
|
||||
{ text: 'B', value: 'b' },
|
||||
@@ -55,19 +55,19 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const pickerItems = page.locator('ion-picker-column-internal .picker-item:not(.picker-item-empty, [disabled])');
|
||||
const pickerItems = page.locator('ion-picker-column .picker-item:not(.picker-item-empty, [disabled])');
|
||||
|
||||
expect(await pickerItems.count()).toBe(3);
|
||||
});
|
||||
test('disabled picker item should not be interactive', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: 'A', value: 'a' },
|
||||
{ text: 'B', value: 'b', disabled: true },
|
||||
@@ -78,18 +78,18 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const disabledItem = page.locator('ion-picker-column-internal .picker-item[disabled]');
|
||||
const disabledItem = page.locator('ion-picker-column .picker-item[disabled]');
|
||||
await expect(disabledItem).not.toBeEnabled();
|
||||
});
|
||||
test('disabled picker item should not be considered active', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal value="b"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column value="b"></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: 'A', value: 'a' },
|
||||
{ text: 'B', value: 'b', disabled: true },
|
||||
@@ -100,18 +100,18 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
|
||||
const disabledItem = page.locator('ion-picker-column .picker-item[data-value="b"]');
|
||||
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
|
||||
});
|
||||
test('setting the value to a disabled item should not cause that item to be active', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: 'A', value: 'a' },
|
||||
{ text: 'B', value: 'b', disabled: true },
|
||||
@@ -122,24 +122,24 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const pickerColumn = page.locator('ion-picker-column-internal');
|
||||
await pickerColumn.evaluate((el: HTMLIonPickerColumnInternalElement) => (el.value = 'b'));
|
||||
const pickerColumn = page.locator('ion-picker-column');
|
||||
await pickerColumn.evaluate((el: HTMLIonPickerColumnElement) => (el.value = 'b'));
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
|
||||
const disabledItem = page.locator('ion-picker-column .picker-item[data-value="b"]');
|
||||
await expect(disabledItem).toBeDisabled();
|
||||
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
|
||||
});
|
||||
test('defaulting the value to a disabled item should not cause that item to be active', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: 'A', value: 'a' },
|
||||
{ text: 'B', value: 'b', disabled: true },
|
||||
@@ -151,7 +151,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const disabledItem = page.locator('ion-picker-column-internal .picker-item[data-value="b"]');
|
||||
const disabledItem = page.locator('ion-picker-column .picker-item[data-value="b"]');
|
||||
await expect(disabledItem).toBeDisabled();
|
||||
await expect(disabledItem).not.toHaveClass(/picker-item-active/);
|
||||
});
|
||||
@@ -162,16 +162,16 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
* This behavior does not vary across directions.
|
||||
*/
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('picker-column-internal: disabled column rendering'), () => {
|
||||
test.describe(title('picker-column: disabled column rendering'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/src/components/picker-column-internal/test/disabled', config);
|
||||
await page.goto('/src/components/picker-column/test/disabled', config);
|
||||
});
|
||||
|
||||
test('disabled column should not have visual regressions', async ({ page }) => {
|
||||
const disabledColumn = page.locator('#column-disabled');
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(disabledColumn).toHaveScreenshot(screenshot('picker-internal-disabled-column'));
|
||||
await expect(disabledColumn).toHaveScreenshot(screenshot('picker-disabled-column'));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -180,9 +180,9 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
* This behavior does not vary across modes/directions.
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('picker-column-internal: disabled column'), () => {
|
||||
test.describe(title('picker-column: disabled column'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/src/components/picker-column-internal/test/disabled', config);
|
||||
await page.goto('/src/components/picker-column/test/disabled', config);
|
||||
});
|
||||
|
||||
test('item in disabled column should not be interactive', async ({ page }) => {
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -1,9 +0,0 @@
|
||||
export interface PickerInternalChangeEventDetail {
|
||||
useInputMode: boolean;
|
||||
inputModeColumn?: HTMLIonPickerColumnInternalElement;
|
||||
}
|
||||
|
||||
export interface PickerInternalCustomEvent extends CustomEvent {
|
||||
target: HTMLIonPickerInternalElement;
|
||||
detail: PickerInternalChangeEventDetail;
|
||||
}
|
||||
9
core/src/components/picker/picker-interfaces.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export interface PickerChangeEventDetail {
|
||||
useInputMode: boolean;
|
||||
inputModeColumn?: HTMLIonPickerColumnElement;
|
||||
}
|
||||
|
||||
export interface PickerCustomEvent extends CustomEvent {
|
||||
target: HTMLIonPickerElement;
|
||||
detail: PickerChangeEventDetail;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
@import "./picker-internal.scss";
|
||||
@import "./picker-internal.vars.scss";
|
||||
@import "./picker.scss";
|
||||
@import "./picker.vars.scss";
|
||||
@import "../../themes/ionic.globals.ios";
|
||||
|
||||
:host .picker-before {
|
||||
@@ -1,5 +1,5 @@
|
||||
@import "./picker-internal.scss";
|
||||
@import "./picker-internal.vars.scss";
|
||||
@import "./picker.scss";
|
||||
@import "./picker.vars.scss";
|
||||
@import "../../themes/ionic.globals.md";
|
||||
|
||||
:host .picker-before {
|
||||
@@ -1,6 +1,6 @@
|
||||
@import "../../themes/ionic.globals";
|
||||
|
||||
// Picker Internal
|
||||
// Picker
|
||||
// --------------------------------------------------
|
||||
|
||||
:host {
|
||||
@@ -81,14 +81,14 @@
|
||||
@include visually-hidden();
|
||||
}
|
||||
|
||||
:host ::slotted(ion-picker-column-internal:first-of-type) {
|
||||
:host ::slotted(ion-picker-column:first-of-type) {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
:host ::slotted(ion-picker-column-internal:last-of-type) {
|
||||
:host ::slotted(ion-picker-column:last-of-type) {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
:host ::slotted(ion-picker-column-internal:only-child) {
|
||||
:host ::slotted(ion-picker-column:only-child) {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -2,32 +2,31 @@ import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||
import { Component, Element, Event, Listen, Method, Host, h } from '@stencil/core';
|
||||
import { getElementRoot } from '@utils/helpers';
|
||||
|
||||
import type { PickerInternalChangeEventDetail } from './picker-internal-interfaces';
|
||||
import type { PickerChangeEventDetail } from './picker-interfaces';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
* @internal
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-picker-internal',
|
||||
tag: 'ion-picker',
|
||||
styleUrls: {
|
||||
ios: 'picker-internal.ios.scss',
|
||||
md: 'picker-internal.md.scss',
|
||||
ios: 'picker.ios.scss',
|
||||
md: 'picker.md.scss',
|
||||
},
|
||||
shadow: true,
|
||||
})
|
||||
export class PickerInternal implements ComponentInterface {
|
||||
export class Picker implements ComponentInterface {
|
||||
private inputEl?: HTMLInputElement;
|
||||
private useInputMode = false;
|
||||
private inputModeColumn?: HTMLIonPickerColumnInternalElement;
|
||||
private inputModeColumn?: HTMLIonPickerColumnElement;
|
||||
private highlightEl?: HTMLElement;
|
||||
private actionOnClick?: () => void;
|
||||
private destroyKeypressListener?: () => void;
|
||||
private singleColumnSearchTimeout?: ReturnType<typeof setTimeout>;
|
||||
|
||||
@Element() el!: HTMLIonPickerInternalElement;
|
||||
@Element() el!: HTMLIonPickerElement;
|
||||
|
||||
@Event() ionInputModeChange!: EventEmitter<PickerInternalChangeEventDetail>;
|
||||
@Event() ionInputModeChange!: EventEmitter<PickerChangeEventDetail>;
|
||||
|
||||
/**
|
||||
* When the picker is interacted with
|
||||
@@ -78,7 +77,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
// TODO(FW-2832): type
|
||||
const { relatedTarget } = ev;
|
||||
|
||||
if (!relatedTarget || (relatedTarget.tagName !== 'ION-PICKER-COLUMN-INTERNAL' && relatedTarget !== this.inputEl)) {
|
||||
if (!relatedTarget || (relatedTarget.tagName !== 'ION-PICKER-COLUMN' && relatedTarget !== this.inputEl)) {
|
||||
this.exitInputMode();
|
||||
}
|
||||
};
|
||||
@@ -98,7 +97,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
* make sure that this function only ever runs when
|
||||
* focusing a picker column.
|
||||
*/
|
||||
if (target.tagName !== 'ION-PICKER-COLUMN-INTERNAL') {
|
||||
if (target.tagName !== 'ION-PICKER-COLUMN') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -116,7 +115,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
* we should enter/exit input mode automatically.
|
||||
*/
|
||||
if (!this.actionOnClick) {
|
||||
const columnEl = target as HTMLIonPickerColumnInternalElement;
|
||||
const columnEl = target as HTMLIonPickerColumnElement;
|
||||
const allowInput = columnEl.numericInput;
|
||||
if (allowInput) {
|
||||
this.enterInputMode(columnEl, false);
|
||||
@@ -167,7 +166,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
* since we just tapped the highlight and
|
||||
* not a column.
|
||||
*/
|
||||
if ((ev.target as HTMLElement).tagName === 'ION-PICKER-COLUMN-INTERNAL') {
|
||||
if ((ev.target as HTMLElement).tagName === 'ION-PICKER-COLUMN') {
|
||||
/**
|
||||
* If user taps 2 different columns
|
||||
* then we should just switch to input mode
|
||||
@@ -180,7 +179,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
};
|
||||
} else {
|
||||
this.actionOnClick = () => {
|
||||
this.enterInputMode(ev.target as HTMLIonPickerColumnInternalElement);
|
||||
this.enterInputMode(ev.target as HTMLIonPickerColumnElement);
|
||||
};
|
||||
}
|
||||
} else {
|
||||
@@ -198,8 +197,8 @@ export class PickerInternal implements ComponentInterface {
|
||||
* If there is only 1 numeric input column
|
||||
* then we should skip multi column input.
|
||||
*/
|
||||
const columns = el.querySelectorAll('ion-picker-column-internal.picker-column-numeric-input');
|
||||
const columnEl = columns.length === 1 ? (ev.target as HTMLIonPickerColumnInternalElement) : undefined;
|
||||
const columns = el.querySelectorAll('ion-picker-column.picker-column-numeric-input');
|
||||
const columnEl = columns.length === 1 ? (ev.target as HTMLIonPickerColumnElement) : undefined;
|
||||
this.actionOnClick = () => {
|
||||
this.enterInputMode(columnEl);
|
||||
};
|
||||
@@ -226,7 +225,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
* users from having any visual indication of which
|
||||
* column is focused.
|
||||
*/
|
||||
private enterInputMode = (columnEl?: HTMLIonPickerColumnInternalElement, focusInput = true) => {
|
||||
private enterInputMode = (columnEl?: HTMLIonPickerColumnElement, focusInput = true) => {
|
||||
const { inputEl, el } = this;
|
||||
if (!inputEl) {
|
||||
return;
|
||||
@@ -236,7 +235,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
* Only active input mode if there is at
|
||||
* least one column that accepts numeric input.
|
||||
*/
|
||||
const hasInputColumn = el.querySelector('ion-picker-column-internal.picker-column-numeric-input');
|
||||
const hasInputColumn = el.querySelector('ion-picker-column.picker-column-numeric-input');
|
||||
if (!hasInputColumn) {
|
||||
return;
|
||||
}
|
||||
@@ -397,7 +396,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
* or trailing zeros when looking at the item text.
|
||||
*/
|
||||
private searchColumn = (
|
||||
colEl: HTMLIonPickerColumnInternalElement,
|
||||
colEl: HTMLIonPickerColumnElement,
|
||||
value: string,
|
||||
zeroBehavior: 'start' | 'end' = 'start'
|
||||
) => {
|
||||
@@ -415,9 +414,7 @@ export class PickerInternal implements ComponentInterface {
|
||||
return;
|
||||
}
|
||||
|
||||
const numericPickers = Array.from(el.querySelectorAll('ion-picker-column-internal')).filter(
|
||||
(col) => col.numericInput
|
||||
);
|
||||
const numericPickers = Array.from(el.querySelectorAll('ion-picker-column')).filter((col) => col.numericInput);
|
||||
|
||||
const firstColumn = numericPickers[0];
|
||||
const lastColumn = numericPickers[1];
|
||||
@@ -15,13 +15,13 @@
|
||||
<ion-content>
|
||||
<h1>Picker - a11y</h1>
|
||||
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal color="tertiary" value="3"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column color="tertiary" value="3"></ion-picker-column>
|
||||
</ion-picker>
|
||||
</ion-content>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: 'First', value: '1' },
|
||||
{ text: 'Second', value: '2' },
|
||||
@@ -3,9 +3,9 @@ import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
configs().forEach(({ title, config }) => {
|
||||
test.describe(title('picker-internal: a11y'), () => {
|
||||
test.describe(title('picker: a11y'), () => {
|
||||
test('should not have accessibility violations', async ({ page }) => {
|
||||
await page.goto(`/src/components/picker-internal/test/a11y`, config);
|
||||
await page.goto(`/src/components/picker/test/a11y`, config);
|
||||
|
||||
const results = await new AxeBuilder({ page }).analyze();
|
||||
|
||||
@@ -53,33 +53,33 @@
|
||||
<div class="grid">
|
||||
<div class="grid-item">
|
||||
<h2>Inline</h2>
|
||||
<ion-picker-internal id="inline">
|
||||
<ion-picker-column-internal id="first"></ion-picker-column-internal>
|
||||
<ion-picker-column-internal id="second"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker id="inline">
|
||||
<ion-picker-column id="first"></ion-picker-column>
|
||||
<ion-picker-column id="second"></ion-picker-column>
|
||||
</ion-picker>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>One Numeric Input</h2>
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal numeric-input="true" id="numeric-first"></ion-picker-column-internal>
|
||||
<ion-picker-column-internal id="numeric-second"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column numeric-input="true" id="numeric-first"></ion-picker-column>
|
||||
<ion-picker-column id="numeric-second"></ion-picker-column>
|
||||
</ion-picker>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>Two Numeric Input</h2>
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal numeric-input="true" id="dual-numeric-first"></ion-picker-column-internal>
|
||||
<ion-picker-column-internal numeric-input="true" id="dual-numeric-second"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column numeric-input="true" id="dual-numeric-first"></ion-picker-column>
|
||||
<ion-picker-column numeric-input="true" id="dual-numeric-second"></ion-picker-column>
|
||||
</ion-picker>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
<h2>Popover</h2>
|
||||
<ion-button id="popover">Open Picker</ion-button>
|
||||
<ion-popover trigger="popover">
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal id="popover-first"></ion-picker-column-internal>
|
||||
<ion-picker-column-internal id="popover-second"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column id="popover-first"></ion-picker-column>
|
||||
<ion-picker-column id="popover-second"></ion-picker-column>
|
||||
</ion-picker>
|
||||
</ion-popover>
|
||||
</div>
|
||||
<div class="grid-item">
|
||||
@@ -94,10 +94,10 @@
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content force-overscroll="false">
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal id="modal-first"></ion-picker-column-internal>
|
||||
<ion-picker-column-internal id="modal-second"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column id="modal-first"></ion-picker-column>
|
||||
<ion-picker-column id="modal-second"></ion-picker-column>
|
||||
</ion-picker>
|
||||
</ion-content>
|
||||
</ion-modal>
|
||||
</div>
|
||||
@@ -106,7 +106,7 @@
|
||||
</ion-app>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal#numeric-first');
|
||||
const column = document.querySelector('ion-picker-column#numeric-first');
|
||||
column.addEventListener('ionChange', (ev) => {
|
||||
console.log('Column change', ev.detail);
|
||||
});
|
||||
@@ -5,9 +5,9 @@ import { configs, test } from '@utils/test/playwright';
|
||||
* This behavior does not vary across directions.
|
||||
*/
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('picker-internal: rendering'), () => {
|
||||
test.describe(title('picker: rendering'), () => {
|
||||
test('inline pickers should not have visual regression', async ({ page }) => {
|
||||
await page.goto(`/src/components/picker-internal/test/basic`, config);
|
||||
await page.goto(`/src/components/picker/test/basic`, config);
|
||||
|
||||
const fullStack = page.locator('#inline button[data-value="full-stack"]');
|
||||
const onion = page.locator('#inline button[data-value="onion"]');
|
||||
@@ -17,26 +17,26 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(page.locator('#inline')).toHaveScreenshot(screenshot(`picker-internal-inline-diff`));
|
||||
await expect(page.locator('#inline')).toHaveScreenshot(screenshot(`picker-inline-diff`));
|
||||
});
|
||||
});
|
||||
|
||||
test.describe(title('picker-internal: overlay rendering'), () => {
|
||||
test.describe(title('picker: overlay rendering'), () => {
|
||||
test('popover: should not have visual regression', async ({ page }) => {
|
||||
await page.goto(`/src/components/picker-internal/test/basic`, config);
|
||||
await page.goto(`/src/components/picker/test/basic`, config);
|
||||
|
||||
const button = page.locator('#popover');
|
||||
const didPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
const pickerInternal = page.locator('ion-popover ion-picker-internal');
|
||||
const picker = page.locator('ion-popover ion-picker');
|
||||
|
||||
await button.click();
|
||||
await didPresent.next();
|
||||
|
||||
await expect(pickerInternal).toBeVisible();
|
||||
await expect(picker).toBeVisible();
|
||||
|
||||
const popoverContent = page.locator('ion-popover .ion-delegate-host');
|
||||
|
||||
await expect(popoverContent).toHaveScreenshot(screenshot(`picker-internal-popover-diff`), {
|
||||
await expect(popoverContent).toHaveScreenshot(screenshot(`picker-popover-diff`), {
|
||||
/**
|
||||
* Animations must be enabled to capture the screenshot.
|
||||
* By default, animations are disabled with toHaveScreenshot,
|
||||
@@ -49,20 +49,20 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
});
|
||||
|
||||
test('modal: should not have visual regression', async ({ page }) => {
|
||||
await page.goto('/src/components/picker-internal/test/basic', config);
|
||||
await page.goto('/src/components/picker/test/basic', config);
|
||||
|
||||
const button = page.locator('#modal');
|
||||
const didPresent = await page.spyOnEvent('ionModalDidPresent');
|
||||
const pickerInternal = page.locator('ion-modal ion-picker-internal');
|
||||
const picker = page.locator('ion-modal ion-picker');
|
||||
|
||||
await button.click();
|
||||
await didPresent.next();
|
||||
|
||||
await expect(pickerInternal).toBeVisible();
|
||||
await expect(picker).toBeVisible();
|
||||
|
||||
const modalContent = page.locator('ion-modal .ion-delegate-host');
|
||||
|
||||
await expect(modalContent).toHaveScreenshot(screenshot(`picker-internal-modal-diff`), {
|
||||
await expect(modalContent).toHaveScreenshot(screenshot(`picker-modal-diff`), {
|
||||
/**
|
||||
* Animations must be enabled to capture the screenshot.
|
||||
* By default, animations are disabled with toHaveScreenshot,
|
||||
@@ -80,17 +80,17 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
* This behavior does not vary across modes/directions.
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('picker-internal: focus'), () => {
|
||||
test.describe(title('picker: focus'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal value="full-stack" id="first"></ion-picker-column-internal>
|
||||
<ion-picker-column-internal value="onion" id="second"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column value="full-stack" id="first"></ion-picker-column>
|
||||
<ion-picker-column value="onion" id="second"></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const columns = document.querySelectorAll('ion-picker-column-internal');
|
||||
const columns = document.querySelectorAll('ion-picker-column');
|
||||
columns[0].items = [
|
||||
{ text: 'Minified', value: 'minified' },
|
||||
{ text: 'Responsive', value: 'responsive' },
|
||||
@@ -113,8 +113,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
});
|
||||
|
||||
test('tabbing should correctly move focus between columns', async ({ page }) => {
|
||||
const firstColumn = page.locator('ion-picker-column-internal#first');
|
||||
const secondColumn = page.locator('ion-picker-column-internal#second');
|
||||
const firstColumn = page.locator('ion-picker-column#first');
|
||||
const secondColumn = page.locator('ion-picker-column#second');
|
||||
|
||||
// Focus first column
|
||||
await page.keyboard.press('Tab');
|
||||
@@ -128,8 +128,8 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
});
|
||||
|
||||
test('tabbing should correctly move focus back', async ({ page }) => {
|
||||
const firstColumn = page.locator('ion-picker-column-internal#first');
|
||||
const secondColumn = page.locator('ion-picker-column-internal#second');
|
||||
const firstColumn = page.locator('ion-picker-column#first');
|
||||
const secondColumn = page.locator('ion-picker-column#second');
|
||||
|
||||
await secondColumn.focus();
|
||||
await expect(secondColumn).toBeFocused();
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@@ -6,16 +6,16 @@ import type { E2ELocator } from '@utils/test/playwright/page/utils/locator';
|
||||
* This behavior does not vary across modes/directions.
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('picker-internal: keyboard entry'), () => {
|
||||
test.describe(title('picker: keyboard entry'), () => {
|
||||
test('should scroll to and update the value prop for a single column', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: '01', value: 1 },
|
||||
{ text: '02', value: 2 },
|
||||
@@ -30,7 +30,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const column = page.locator('ion-picker-column-internal');
|
||||
const column = page.locator('ion-picker-column');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
await column.focus();
|
||||
|
||||
@@ -43,13 +43,13 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
test('should scroll to and update the value prop for multiple columns', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal id="first"></ion-picker-column-internal>
|
||||
<ion-picker-column-internal id="second"></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column id="first"></ion-picker-column>
|
||||
<ion-picker-column id="second"></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const firstColumn = document.querySelector('ion-picker-column-internal#first');
|
||||
const firstColumn = document.querySelector('ion-picker-column#first');
|
||||
firstColumn.items = [
|
||||
{ text: '01', value: 1 },
|
||||
{ text: '02', value: 2 },
|
||||
@@ -60,7 +60,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
firstColumn.value = 5;
|
||||
firstColumn.numericInput = true;
|
||||
|
||||
const secondColumn = document.querySelector('ion-picker-column-internal#second');
|
||||
const secondColumn = document.querySelector('ion-picker-column#second');
|
||||
secondColumn.items = [
|
||||
{ text: '20', value: 20 },
|
||||
{ text: '21', value: 21 },
|
||||
@@ -75,9 +75,9 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const firstColumn = page.locator('ion-picker-column-internal#first');
|
||||
const secondColumn = page.locator('ion-picker-column-internal#second');
|
||||
const highlight = page.locator('ion-picker-internal .picker-highlight');
|
||||
const firstColumn = page.locator('ion-picker-column#first');
|
||||
const secondColumn = page.locator('ion-picker-column#second');
|
||||
const highlight = page.locator('ion-picker .picker-highlight');
|
||||
const firstIonChange = await (firstColumn as E2ELocator).spyOnEvent('ionChange');
|
||||
const secondIonChange = await (secondColumn as E2ELocator).spyOnEvent('ionChange');
|
||||
|
||||
@@ -103,12 +103,12 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
test('should select 00', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-picker-internal>
|
||||
<ion-picker-column-internal></ion-picker-column-internal>
|
||||
</ion-picker-internal>
|
||||
<ion-picker>
|
||||
<ion-picker-column></ion-picker-column>
|
||||
</ion-picker>
|
||||
|
||||
<script>
|
||||
const column = document.querySelector('ion-picker-column-internal');
|
||||
const column = document.querySelector('ion-picker-column');
|
||||
column.items = [
|
||||
{ text: '00', value: 12 },
|
||||
{ text: '01', value: 1 },
|
||||
@@ -124,7 +124,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
config
|
||||
);
|
||||
|
||||
const column = page.locator('ion-picker-column-internal');
|
||||
const column = page.locator('ion-picker-column');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
await column.focus();
|
||||
|
||||